aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2018-07-28 11:06:01 +0000
committerDimitry Andric <dim@FreeBSD.org>2018-07-28 11:06:01 +0000
commit486754660bb926339aefcf012a3f848592babb8b (patch)
treeecdbc446c9876f4f120f701c243373cd3cb43db3
parent55e6d896ad333f07bb3b1ba487df214fc268a4ab (diff)
downloadsrc-vendor/clang/clang-trunk-r338150.tar.gz
src-vendor/clang/clang-trunk-r338150.zip
Vendor import of clang trunk r338150:vendor/clang/clang-trunk-r338150
-rw-r--r--.clang-tidy7
-rw-r--r--CMakeLists.txt36
-rw-r--r--LICENSE.TXT2
-rw-r--r--bindings/python/clang/cindex.py26
-rw-r--r--bindings/python/tests/cindex/test_cdb.py2
-rw-r--r--bindings/python/tests/cindex/test_cursor.py16
-rw-r--r--bindings/python/tests/cindex/test_translation_unit.py49
-rw-r--r--cmake/caches/Apple-stage2.cmake4
-rw-r--r--cmake/caches/BaremetalARM.cmake2
-rw-r--r--cmake/caches/DistributionExample-stage2.cmake2
-rw-r--r--cmake/caches/Fuchsia-stage2.cmake128
-rw-r--r--cmake/caches/Fuchsia.cmake31
-rw-r--r--docs/AddressSanitizer.rst15
-rw-r--r--docs/AutomaticReferenceCounting.rst76
-rw-r--r--docs/Block-ABI-Apple.rst8
-rw-r--r--docs/ClangCommandLineReference.rst212
-rw-r--r--docs/ClangFormatStyleOptions.rst261
-rw-r--r--docs/CommandGuide/clang.rst121
-rw-r--r--docs/CommandGuide/diagtool.rst52
-rw-r--r--docs/CommandGuide/index.rst1
-rw-r--r--docs/ControlFlowIntegrity.rst50
-rw-r--r--docs/DiagnosticsReference.rst6
-rw-r--r--docs/HardwareAssistedAddressSanitizerDesign.rst65
-rw-r--r--docs/HowToSetupToolingForLLVM.rst3
-rw-r--r--docs/InternalsManual.rst63
-rw-r--r--docs/LTOVisibility.rst6
-rw-r--r--docs/LanguageExtensions.rst89
-rw-r--r--docs/LibASTMatchersReference.html821
-rw-r--r--docs/LibASTMatchersTutorial.rst2
-rw-r--r--docs/LibFormat.rst4
-rw-r--r--docs/LibTooling.rst2
-rw-r--r--docs/MemorySanitizer.rst6
-rw-r--r--docs/Modules.rst15
-rw-r--r--docs/OpenMPSupport.rst131
-rw-r--r--docs/ReleaseNotes.rst292
-rw-r--r--docs/SafeStack.rst18
-rw-r--r--docs/SanitizerStats.rst2
-rw-r--r--docs/ShadowCallStack.rst193
-rw-r--r--docs/ThinLTO.rst2
-rw-r--r--docs/ThreadSanitizer.rst7
-rw-r--r--docs/Toolchain.rst2
-rw-r--r--docs/UndefinedBehaviorSanitizer.rst17
-rw-r--r--docs/UsersManual.rst199
-rw-r--r--docs/analyzer/DesignDiscussions/InitializerLists.rst2
-rw-r--r--docs/conf.py4
-rw-r--r--docs/doxygen.cfg.in6
-rw-r--r--docs/index.rst2
-rw-r--r--docs/tools/dump_ast_matchers.py29
-rw-r--r--docs/tools/dump_format_style.py4
-rw-r--r--examples/PrintFunctionNames/CMakeLists.txt2
-rw-r--r--examples/analyzer-plugin/MainCallChecker.cpp4
-rw-r--r--examples/clang-interpreter/CMakeLists.txt67
-rw-r--r--examples/clang-interpreter/README.txt7
-rw-r--r--examples/clang-interpreter/Test.cxx34
-rw-r--r--examples/clang-interpreter/main.cpp129
-rw-r--r--include/clang-c/BuildSystem.h30
-rw-r--r--include/clang-c/CXCompilationDatabase.h38
-rw-r--r--include/clang-c/CXErrorCode.h12
-rw-r--r--include/clang-c/CXString.h8
-rw-r--r--include/clang-c/Documentation.h62
-rw-r--r--include/clang-c/Index.h1658
-rw-r--r--include/clang/ARCMigrate/ARCMT.h10
-rw-r--r--include/clang/ARCMigrate/ARCMTActions.h2
-rw-r--r--include/clang/AST/APValue.h80
-rw-r--r--include/clang/AST/ASTConsumer.h22
-rw-r--r--include/clang/AST/ASTContext.h623
-rw-r--r--include/clang/AST/ASTDiagnostic.h2
-rw-r--r--include/clang/AST/ASTFwd.h2
-rw-r--r--include/clang/AST/ASTImporter.h165
-rw-r--r--include/clang/AST/ASTLambda.h2
-rw-r--r--include/clang/AST/ASTMutationListener.h44
-rw-r--r--include/clang/AST/ASTStructuralEquivalence.h34
-rw-r--r--include/clang/AST/ASTTypeTraits.h70
-rw-r--r--include/clang/AST/ASTUnresolvedSet.h4
-rw-r--r--include/clang/AST/Attr.h163
-rw-r--r--include/clang/AST/Availability.h4
-rw-r--r--include/clang/AST/BuiltinTypes.def77
-rw-r--r--include/clang/AST/CXXInheritance.h89
-rw-r--r--include/clang/AST/CanonicalType.h68
-rw-r--r--include/clang/AST/Comment.h2
-rw-r--r--include/clang/AST/CommentBriefParser.h2
-rw-r--r--include/clang/AST/CommentCommandTraits.h22
-rw-r--r--include/clang/AST/CommentLexer.h27
-rw-r--r--include/clang/AST/CommentSema.h4
-rw-r--r--include/clang/AST/ComparisonCategories.h243
-rw-r--r--include/clang/AST/DataCollection.h4
-rw-r--r--include/clang/AST/Decl.h964
-rw-r--r--include/clang/AST/DeclBase.h241
-rw-r--r--include/clang/AST/DeclCXX.h876
-rw-r--r--include/clang/AST/DeclContextInternals.h10
-rw-r--r--include/clang/AST/DeclFriend.h8
-rw-r--r--include/clang/AST/DeclLookups.h23
-rw-r--r--include/clang/AST/DeclObjC.h166
-rw-r--r--include/clang/AST/DeclOpenMP.h33
-rw-r--r--include/clang/AST/DeclTemplate.h537
-rw-r--r--include/clang/AST/DeclVisitor.h6
-rw-r--r--include/clang/AST/DeclarationName.h8
-rw-r--r--include/clang/AST/EvaluatedExprVisitor.h4
-rw-r--r--include/clang/AST/Expr.h526
-rw-r--r--include/clang/AST/ExprCXX.h651
-rw-r--r--include/clang/AST/ExprObjC.h136
-rw-r--r--include/clang/AST/ExprOpenMP.h18
-rw-r--r--include/clang/AST/ExternalASTMerger.h2
-rw-r--r--include/clang/AST/ExternalASTSource.h89
-rw-r--r--include/clang/AST/LambdaCapture.h32
-rw-r--r--include/clang/AST/LocInfoType.h2
-rw-r--r--include/clang/AST/Mangle.h8
-rw-r--r--include/clang/AST/MangleNumberingContext.h10
-rw-r--r--include/clang/AST/NSAPI.h66
-rw-r--r--include/clang/AST/NestedNameSpecifier.h142
-rw-r--r--include/clang/AST/NonTrivialTypeVisitor.h113
-rw-r--r--include/clang/AST/ODRHash.h15
-rw-r--r--include/clang/AST/OpenMPClause.h987
-rw-r--r--include/clang/AST/OperationKinds.def36
-rw-r--r--include/clang/AST/OperationKinds.h8
-rw-r--r--include/clang/AST/ParentMap.h2
-rw-r--r--include/clang/AST/PrettyDeclStackTrace.h (renamed from include/clang/Sema/PrettyDeclStackTrace.h)12
-rw-r--r--include/clang/AST/PrettyPrinter.h2
-rw-r--r--include/clang/AST/QualTypeNames.h5
-rw-r--r--include/clang/AST/RawCommentList.h54
-rw-r--r--include/clang/AST/RecordLayout.h2
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h65
-rw-r--r--include/clang/AST/Redeclarable.h102
-rw-r--r--include/clang/AST/SelectorLocationsKind.h16
-rw-r--r--include/clang/AST/Stmt.h198
-rw-r--r--include/clang/AST/StmtCXX.h43
-rw-r--r--include/clang/AST/StmtObjC.h32
-rw-r--r--include/clang/AST/StmtOpenMP.h580
-rw-r--r--include/clang/AST/StmtVisitor.h2
-rw-r--r--include/clang/AST/TemplateBase.h108
-rw-r--r--include/clang/AST/TemplateName.h102
-rw-r--r--include/clang/AST/Type.h639
-rw-r--r--include/clang/AST/TypeLoc.h113
-rw-r--r--include/clang/AST/TypeNodes.def1
-rw-r--r--include/clang/AST/TypeOrdering.h6
-rw-r--r--include/clang/AST/TypeVisitor.h6
-rw-r--r--include/clang/AST/UnresolvedSet.h4
-rw-r--r--include/clang/AST/VTTBuilder.h36
-rw-r--r--include/clang/AST/VTableBuilder.h102
-rw-r--r--include/clang/ASTMatchers/ASTMatchFinder.h48
-rw-r--r--include/clang/ASTMatchers/ASTMatchers.h1138
-rw-r--r--include/clang/ASTMatchers/ASTMatchersInternal.h256
-rw-r--r--include/clang/ASTMatchers/ASTMatchersMacros.h27
-rw-r--r--include/clang/ASTMatchers/Dynamic/Diagnostics.h34
-rw-r--r--include/clang/ASTMatchers/Dynamic/Parser.h22
-rw-r--r--include/clang/ASTMatchers/Dynamic/Registry.h18
-rw-r--r--include/clang/ASTMatchers/Dynamic/VariantValue.h72
-rw-r--r--include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h12
-rw-r--r--include/clang/Analysis/Analyses/Consumed.h109
-rw-r--r--include/clang/Analysis/Analyses/Dominators.h91
-rw-r--r--include/clang/Analysis/Analyses/FormatString.h39
-rw-r--r--include/clang/Analysis/Analyses/LiveVariables.h9
-rw-r--r--include/clang/Analysis/Analyses/PostOrderCFGView.h54
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafety.h63
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafetyCommon.h185
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafetyLogical.h4
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafetyTIL.h543
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafetyTraverse.h173
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafetyUtil.h107
-rw-r--r--include/clang/Analysis/Analyses/UninitializedValues.h26
-rw-r--r--include/clang/Analysis/AnalysisDeclContext.h104
-rw-r--r--include/clang/Analysis/CFG.h187
-rw-r--r--include/clang/Analysis/CallGraph.h20
-rw-r--r--include/clang/Analysis/CloneDetection.h6
-rw-r--r--include/clang/Analysis/CodeInjector.h4
-rw-r--r--include/clang/Analysis/ConstructionContext.h474
-rw-r--r--include/clang/Analysis/ProgramPoint.h89
-rw-r--r--include/clang/Basic/ABI.h40
-rw-r--r--include/clang/Basic/AddressSpaces.h18
-rw-r--r--include/clang/Basic/AlignedAllocation.h12
-rw-r--r--include/clang/Basic/AllDiagnostics.h2
-rw-r--r--include/clang/Basic/Attr.td416
-rw-r--r--include/clang/Basic/AttrDocs.td307
-rw-r--r--include/clang/Basic/AttrKinds.h4
-rw-r--r--include/clang/Basic/AttrSubjectMatchRules.h2
-rw-r--r--include/clang/Basic/Attributes.h2
-rw-r--r--include/clang/Basic/BitmaskEnum.h25
-rw-r--r--include/clang/Basic/Builtins.def73
-rw-r--r--include/clang/Basic/Builtins.h75
-rw-r--r--include/clang/Basic/BuiltinsAArch64.def35
-rw-r--r--include/clang/Basic/BuiltinsAMDGPU.def21
-rw-r--r--include/clang/Basic/BuiltinsHexagon.def45
-rw-r--r--include/clang/Basic/BuiltinsNEON.def1
-rw-r--r--include/clang/Basic/BuiltinsNVPTX.def318
-rw-r--r--include/clang/Basic/BuiltinsPPC.def9
-rw-r--r--include/clang/Basic/BuiltinsWebAssembly.def15
-rw-r--r--include/clang/Basic/BuiltinsX86.def3474
-rw-r--r--include/clang/Basic/BuiltinsX86_64.def104
-rw-r--r--include/clang/Basic/CMakeLists.txt4
-rw-r--r--include/clang/Basic/CapturedStmt.h3
-rw-r--r--include/clang/Basic/CharInfo.h13
-rw-r--r--include/clang/Basic/CommentOptions.h24
-rw-r--r--include/clang/Basic/Cuda.h21
-rw-r--r--include/clang/Basic/DebugInfoOptions.h2
-rw-r--r--include/clang/Basic/Diagnostic.h500
-rw-r--r--include/clang/Basic/Diagnostic.td9
-rw-r--r--include/clang/Basic/DiagnosticASTKinds.td2
-rw-r--r--include/clang/Basic/DiagnosticCommonKinds.td16
-rw-r--r--include/clang/Basic/DiagnosticDriverKinds.td63
-rw-r--r--include/clang/Basic/DiagnosticError.h2
-rw-r--r--include/clang/Basic/DiagnosticFrontendKinds.td7
-rw-r--r--include/clang/Basic/DiagnosticGroups.td63
-rw-r--r--include/clang/Basic/DiagnosticIDs.h62
-rw-r--r--include/clang/Basic/DiagnosticLexKinds.td26
-rw-r--r--include/clang/Basic/DiagnosticOptions.h25
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td43
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td876
-rw-r--r--include/clang/Basic/DiagnosticSerializationKinds.td83
-rw-r--r--include/clang/Basic/ExceptionSpecificationType.h17
-rw-r--r--include/clang/Basic/ExpressionTraits.h2
-rw-r--r--include/clang/Basic/Features.def238
-rw-r--r--include/clang/Basic/FileManager.h62
-rw-r--r--include/clang/Basic/FileSystemOptions.h6
-rw-r--r--include/clang/Basic/FileSystemStatCache.h69
-rw-r--r--include/clang/Basic/IdentifierTable.h136
-rw-r--r--include/clang/Basic/LLVM.h14
-rw-r--r--include/clang/Basic/Lambda.h6
-rw-r--r--include/clang/Basic/LangOptions.def35
-rw-r--r--include/clang/Basic/LangOptions.h139
-rw-r--r--include/clang/Basic/Linkage.h35
-rw-r--r--include/clang/Basic/MacroBuilder.h2
-rw-r--r--include/clang/Basic/Module.h238
-rw-r--r--include/clang/Basic/ObjCRuntime.h66
-rw-r--r--include/clang/Basic/OpenCLExtensions.def3
-rw-r--r--include/clang/Basic/OpenCLOptions.h6
-rw-r--r--include/clang/Basic/OpenMPKinds.def2
-rw-r--r--include/clang/Basic/OpenMPKinds.h46
-rw-r--r--include/clang/Basic/OperatorKinds.h6
-rw-r--r--include/clang/Basic/OperatorPrecedence.h4
-rw-r--r--include/clang/Basic/PartialDiagnostic.h96
-rw-r--r--include/clang/Basic/PlistSupport.h19
-rw-r--r--include/clang/Basic/PrettyStackTrace.h2
-rw-r--r--include/clang/Basic/Sanitizers.def12
-rw-r--r--include/clang/Basic/Sanitizers.h28
-rw-r--r--include/clang/Basic/SourceLocation.h127
-rw-r--r--include/clang/Basic/SourceManager.h454
-rw-r--r--include/clang/Basic/SourceManagerInternals.h22
-rw-r--r--include/clang/Basic/Specifiers.h55
-rw-r--r--include/clang/Basic/Stack.h27
-rw-r--r--include/clang/Basic/StmtNodes.td1
-rw-r--r--include/clang/Basic/SyncScope.h20
-rw-r--r--include/clang/Basic/TargetBuiltins.h30
-rw-r--r--include/clang/Basic/TargetCXXABI.h27
-rw-r--r--include/clang/Basic/TargetInfo.h412
-rw-r--r--include/clang/Basic/TargetOptions.h15
-rw-r--r--include/clang/Basic/TemplateKinds.h4
-rw-r--r--include/clang/Basic/TokenKinds.def62
-rw-r--r--include/clang/Basic/TokenKinds.h24
-rw-r--r--include/clang/Basic/TypeTraits.h11
-rw-r--r--include/clang/Basic/Version.h18
-rw-r--r--include/clang/Basic/VersionTuple.h168
-rw-r--r--include/clang/Basic/VirtualFileSystem.h125
-rw-r--r--include/clang/Basic/Visibility.h6
-rw-r--r--include/clang/Basic/X86Target.def147
-rw-r--r--include/clang/Basic/XRayInstr.h70
-rw-r--r--include/clang/Basic/XRayLists.h3
-rw-r--r--include/clang/Basic/arm_fp16.td131
-rw-r--r--include/clang/Basic/arm_neon.td524
-rw-r--r--include/clang/Basic/arm_neon_incl.td316
-rw-r--r--include/clang/CodeGen/BackendUtil.h2
-rw-r--r--include/clang/CodeGen/CGFunctionInfo.h73
-rw-r--r--include/clang/CodeGen/ConstantInitBuilder.h4
-rw-r--r--include/clang/CodeGen/SwiftCallingConv.h22
-rw-r--r--include/clang/Config/config.h.cmake13
-rw-r--r--include/clang/CrossTU/CrossTranslationUnit.h14
-rw-r--r--include/clang/Driver/Action.h113
-rw-r--r--include/clang/Driver/CC1Options.td31
-rw-r--r--include/clang/Driver/CLCompatOptions.td17
-rw-r--r--include/clang/Driver/Compilation.h61
-rw-r--r--include/clang/Driver/Distro.h3
-rw-r--r--include/clang/Driver/Driver.h93
-rw-r--r--include/clang/Driver/Job.h35
-rw-r--r--include/clang/Driver/Multilib.h54
-rw-r--r--include/clang/Driver/Options.td488
-rw-r--r--include/clang/Driver/SanitizerArgs.h2
-rw-r--r--include/clang/Driver/Tool.h8
-rw-r--r--include/clang/Driver/ToolChain.h136
-rw-r--r--include/clang/Driver/Types.def3
-rw-r--r--include/clang/Driver/Types.h3
-rw-r--r--include/clang/Driver/XRayArgs.h10
-rw-r--r--include/clang/Edit/Commit.h36
-rw-r--r--include/clang/Edit/EditedSource.h36
-rw-r--r--include/clang/Edit/EditsReceiver.h19
-rw-r--r--include/clang/Edit/FileOffset.h23
-rw-r--r--include/clang/Format/Format.h709
-rw-r--r--include/clang/Frontend/ASTConsumers.h7
-rw-r--r--include/clang/Frontend/ASTUnit.h286
-rw-r--r--include/clang/Frontend/ChainedDiagnosticConsumer.h2
-rw-r--r--include/clang/Frontend/CodeGenOptions.def54
-rw-r--r--include/clang/Frontend/CodeGenOptions.h34
-rw-r--r--include/clang/Frontend/CommandLineSourceLoc.h4
-rw-r--r--include/clang/Frontend/CompilerInstance.h53
-rw-r--r--include/clang/Frontend/CompilerInvocation.h78
-rw-r--r--include/clang/Frontend/DependencyOutputOptions.h25
-rw-r--r--include/clang/Frontend/DiagnosticRenderer.h32
-rw-r--r--include/clang/Frontend/FrontendAction.h48
-rw-r--r--include/clang/Frontend/FrontendActions.h32
-rw-r--r--include/clang/Frontend/FrontendOptions.h357
-rw-r--r--include/clang/Frontend/FrontendPluginRegistry.h12
-rw-r--r--include/clang/Frontend/LangStandards.def7
-rw-r--r--include/clang/Frontend/LayoutOverrideSource.h20
-rw-r--r--include/clang/Frontend/MultiplexConsumer.h23
-rw-r--r--include/clang/Frontend/PrecompiledPreamble.h27
-rw-r--r--include/clang/Frontend/SerializedDiagnosticPrinter.h6
-rw-r--r--include/clang/Frontend/SerializedDiagnosticReader.h83
-rw-r--r--include/clang/Frontend/SerializedDiagnostics.h8
-rw-r--r--include/clang/Frontend/TextDiagnostic.h6
-rw-r--r--include/clang/Frontend/TextDiagnosticBuffer.h32
-rw-r--r--include/clang/Frontend/TextDiagnosticPrinter.h2
-rw-r--r--include/clang/Frontend/Utils.h73
-rw-r--r--include/clang/Frontend/VerifyDiagnosticConsumer.h62
-rw-r--r--include/clang/FrontendTool/Utils.h9
-rw-r--r--include/clang/Index/IndexDataConsumer.h13
-rw-r--r--include/clang/Index/IndexSymbol.h48
-rw-r--r--include/clang/Index/IndexingAction.h25
-rw-r--r--include/clang/Index/USRGeneration.h18
-rw-r--r--include/clang/Lex/CodeCompletionHandler.h14
-rw-r--r--include/clang/Lex/DirectoryLookup.h12
-rw-r--r--include/clang/Lex/ExternalPreprocessorSource.h10
-rw-r--r--include/clang/Lex/HeaderSearch.h191
-rw-r--r--include/clang/Lex/HeaderSearchOptions.h28
-rw-r--r--include/clang/Lex/Lexer.h52
-rw-r--r--include/clang/Lex/LiteralSupport.h21
-rw-r--r--include/clang/Lex/MacroInfo.h118
-rw-r--r--include/clang/Lex/ModuleLoader.h20
-rw-r--r--include/clang/Lex/ModuleMap.h208
-rw-r--r--include/clang/Lex/MultipleIncludeOpt.h16
-rw-r--r--include/clang/Lex/PPCallbacks.h104
-rw-r--r--include/clang/Lex/PPConditionalDirectiveRecord.h10
-rw-r--r--include/clang/Lex/Pragma.h8
-rw-r--r--include/clang/Lex/PreprocessingRecord.h170
-rw-r--r--include/clang/Lex/Preprocessor.h392
-rw-r--r--include/clang/Lex/PreprocessorLexer.h30
-rw-r--r--include/clang/Lex/PreprocessorOptions.h52
-rw-r--r--include/clang/Lex/Token.h46
-rw-r--r--include/clang/Lex/TokenLexer.h14
-rw-r--r--include/clang/Lex/VariadicMacroSupport.h6
-rw-r--r--include/clang/Parse/ParseAST.h4
-rw-r--r--include/clang/Parse/Parser.h580
-rw-r--r--include/clang/Parse/RAIIObjectsForParser.h17
-rw-r--r--include/clang/Rewrite/Core/DeltaTree.h13
-rw-r--r--include/clang/Rewrite/Core/HTMLRewrite.h3
-rw-r--r--include/clang/Rewrite/Core/RewriteBuffer.h19
-rw-r--r--include/clang/Rewrite/Core/RewriteRope.h55
-rw-r--r--include/clang/Rewrite/Core/Rewriter.h56
-rw-r--r--include/clang/Rewrite/Core/TokenRewriter.h28
-rw-r--r--include/clang/Rewrite/Frontend/FixItRewriter.h69
-rw-r--r--include/clang/Rewrite/Frontend/FrontendActions.h2
-rw-r--r--include/clang/Sema/AnalysisBasedWarnings.h18
-rw-r--r--include/clang/Sema/CodeCompleteConsumer.h768
-rw-r--r--include/clang/Sema/CodeCompleteOptions.h11
-rw-r--r--include/clang/Sema/DeclSpec.h771
-rw-r--r--include/clang/Sema/DelayedDiagnostic.h87
-rw-r--r--include/clang/Sema/ExternalSemaSource.h38
-rw-r--r--include/clang/Sema/IdentifierResolver.h61
-rw-r--r--include/clang/Sema/Initialization.h767
-rw-r--r--include/clang/Sema/Lookup.h212
-rw-r--r--include/clang/Sema/LoopHint.h4
-rw-r--r--include/clang/Sema/MultiplexExternalSemaSource.h86
-rw-r--r--include/clang/Sema/ObjCMethodList.h6
-rw-r--r--include/clang/Sema/Overload.h298
-rw-r--r--include/clang/Sema/Ownership.h101
-rw-r--r--include/clang/Sema/ParsedAttr.h (renamed from include/clang/Sema/AttributeList.h)733
-rw-r--r--include/clang/Sema/ParsedTemplate.h53
-rw-r--r--include/clang/Sema/Scope.h100
-rw-r--r--include/clang/Sema/ScopeInfo.h521
-rw-r--r--include/clang/Sema/Sema.h1884
-rw-r--r--include/clang/Sema/SemaConsumer.h6
-rw-r--r--include/clang/Sema/SemaFixItUtils.h2
-rw-r--r--include/clang/Sema/SemaInternal.h55
-rw-r--r--include/clang/Sema/SemaLambda.h10
-rw-r--r--include/clang/Sema/Template.h197
-rw-r--r--include/clang/Sema/TemplateDeduction.h148
-rw-r--r--include/clang/Sema/TemplateInstCallback.h83
-rw-r--r--include/clang/Sema/TypoCorrection.h137
-rw-r--r--include/clang/Sema/Weak.h2
-rw-r--r--include/clang/Serialization/ASTBitCodes.h1104
-rw-r--r--include/clang/Serialization/ASTDeserializationListener.h18
-rw-r--r--include/clang/Serialization/ASTReader.h791
-rw-r--r--include/clang/Serialization/ASTWriter.h267
-rw-r--r--include/clang/Serialization/ContinuousRangeMap.h7
-rw-r--r--include/clang/Serialization/GlobalModuleIndex.h60
-rw-r--r--include/clang/Serialization/Module.h231
-rw-r--r--include/clang/Serialization/ModuleManager.h92
-rw-r--r--include/clang/StaticAnalyzer/Checkers/CMakeLists.txt1
-rw-r--r--include/clang/StaticAnalyzer/Checkers/Checkers.td50
-rw-r--r--include/clang/StaticAnalyzer/Core/AnalyzerOptions.h236
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h246
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h181
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugType.h40
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h296
-rw-r--r--include/clang/StaticAnalyzer/Core/Checker.h24
-rw-r--r--include/clang/StaticAnalyzer/Core/CheckerManager.h294
-rw-r--r--include/clang/StaticAnalyzer/Core/CheckerRegistry.h22
-rw-r--r--include/clang/StaticAnalyzer/Core/IssueHash.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h2
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h6
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h30
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h79
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h2
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h296
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h42
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h21
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h41
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h174
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h8
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h28
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h39
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h125
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h264
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h29
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h2
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h274
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h185
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h142
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h (renamed from lib/StaticAnalyzer/Core/RangedConstraintManager.h)114
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h77
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SMTContext.h31
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h62
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h996
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h91
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h64
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h232
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h5
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/Store.h73
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h25
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h10
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h39
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h140
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h31
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h11
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h18
-rw-r--r--include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h15
-rw-r--r--include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h10
-rw-r--r--include/clang/StaticAnalyzer/Frontend/FrontendActions.h2
-rw-r--r--include/clang/StaticAnalyzer/Frontend/ModelConsumer.h4
-rw-r--r--include/clang/Tooling/AllTUsExecution.h76
-rw-r--r--include/clang/Tooling/ArgumentsAdjusters.h27
-rw-r--r--include/clang/Tooling/CommonOptionsParser.h10
-rw-r--r--include/clang/Tooling/CompilationDatabase.h67
-rw-r--r--include/clang/Tooling/CompilationDatabasePluginRegistry.h14
-rw-r--r--include/clang/Tooling/Core/Diagnostic.h22
-rw-r--r--include/clang/Tooling/Core/Replacement.h88
-rw-r--r--include/clang/Tooling/DiagnosticsYaml.h6
-rw-r--r--include/clang/Tooling/Execution.h44
-rw-r--r--include/clang/Tooling/FileMatchTrie.h31
-rw-r--r--include/clang/Tooling/FixIt.h14
-rw-r--r--include/clang/Tooling/Inclusions/HeaderIncludes.h137
-rw-r--r--include/clang/Tooling/Inclusions/IncludeStyle.h139
-rw-r--r--include/clang/Tooling/JSONCompilationDatabase.h37
-rw-r--r--include/clang/Tooling/Refactoring.h12
-rw-r--r--include/clang/Tooling/Refactoring/AtomicChange.h34
-rw-r--r--include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h2
-rw-r--r--include/clang/Tooling/Refactoring/RefactoringActionRule.h2
-rw-r--r--include/clang/Tooling/Refactoring/RefactoringResultConsumer.h4
-rw-r--r--include/clang/Tooling/Refactoring/Rename/RenamingAction.h4
-rw-r--r--include/clang/Tooling/Refactoring/Rename/SymbolName.h2
-rw-r--r--include/clang/Tooling/Refactoring/Rename/USRFinder.h2
-rw-r--r--include/clang/Tooling/Refactoring/Rename/USRFindingAction.h2
-rw-r--r--include/clang/Tooling/Refactoring/Rename/USRLocFinder.h2
-rw-r--r--include/clang/Tooling/RefactoringCallbacks.h12
-rw-r--r--include/clang/Tooling/ReplacementsYaml.h8
-rw-r--r--include/clang/Tooling/StandaloneExecution.h11
-rw-r--r--include/clang/Tooling/ToolExecutorPluginRegistry.h8
-rw-r--r--include/clang/Tooling/Tooling.h163
-rw-r--r--include/clang/module.modulemap6
-rw-r--r--lib/ARCMigrate/ARCMT.cpp2
-rw-r--r--lib/ARCMigrate/ObjCMT.cpp6
-rw-r--r--lib/ARCMigrate/PlistReporter.cpp3
-rw-r--r--lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp2
-rw-r--r--lib/ARCMigrate/TransGCAttrs.cpp7
-rw-r--r--lib/ARCMigrate/TransProperties.cpp2
-rw-r--r--lib/ARCMigrate/TransRetainReleaseDealloc.cpp4
-rw-r--r--lib/ARCMigrate/TransUnbridgedCasts.cpp5
-rw-r--r--lib/ARCMigrate/TransformActions.cpp24
-rw-r--r--lib/ARCMigrate/Transforms.cpp4
-rw-r--r--lib/ARCMigrate/Transforms.h12
-rw-r--r--lib/AST/APValue.cpp79
-rw-r--r--lib/AST/ASTContext.cpp1307
-rw-r--r--lib/AST/ASTDiagnostic.cpp2
-rw-r--r--lib/AST/ASTDumper.cpp60
-rw-r--r--lib/AST/ASTImporter.cpp2911
-rw-r--r--lib/AST/ASTStructuralEquivalence.cpp535
-rw-r--r--lib/AST/CMakeLists.txt1
-rw-r--r--lib/AST/CXXInheritance.cpp33
-rw-r--r--lib/AST/CommentBriefParser.cpp4
-rw-r--r--lib/AST/CommentLexer.cpp246
-rw-r--r--lib/AST/CommentSema.cpp2
-rw-r--r--lib/AST/ComparisonCategories.cpp211
-rw-r--r--lib/AST/Decl.cpp143
-rw-r--r--lib/AST/DeclBase.cpp278
-rw-r--r--lib/AST/DeclCXX.cpp452
-rw-r--r--lib/AST/DeclFriend.cpp6
-rw-r--r--lib/AST/DeclObjC.cpp142
-rw-r--r--lib/AST/DeclOpenMP.cpp9
-rw-r--r--lib/AST/DeclPrinter.cpp51
-rw-r--r--lib/AST/DeclTemplate.cpp56
-rw-r--r--lib/AST/Expr.cpp130
-rw-r--r--lib/AST/ExprCXX.cpp76
-rw-r--r--lib/AST/ExprClassification.cpp26
-rw-r--r--lib/AST/ExprConstant.cpp1486
-rw-r--r--lib/AST/ExternalASTMerger.cpp45
-rw-r--r--lib/AST/ItaniumCXXABI.cpp63
-rw-r--r--lib/AST/ItaniumMangle.cpp125
-rw-r--r--lib/AST/MicrosoftCXXABI.cpp4
-rw-r--r--lib/AST/MicrosoftMangle.cpp329
-rw-r--r--lib/AST/NSAPI.cpp31
-rw-r--r--lib/AST/NestedNameSpecifier.cpp22
-rw-r--r--lib/AST/ODRHash.cpp212
-rw-r--r--lib/AST/OpenMPClause.cpp4
-rw-r--r--lib/AST/ParentMap.cpp3
-rw-r--r--lib/AST/QualTypeNames.cpp20
-rw-r--r--lib/AST/RawCommentList.cpp110
-rw-r--r--lib/AST/RecordLayoutBuilder.cpp155
-rw-r--r--lib/AST/Stmt.cpp78
-rw-r--r--lib/AST/StmtCXX.cpp10
-rw-r--r--lib/AST/StmtPrinter.cpp253
-rw-r--r--lib/AST/StmtProfile.cpp64
-rw-r--r--lib/AST/TemplateBase.cpp4
-rw-r--r--lib/AST/TemplateName.cpp5
-rw-r--r--lib/AST/Type.cpp702
-rw-r--r--lib/AST/TypeLoc.cpp38
-rw-r--r--lib/AST/TypePrinter.cpp254
-rw-r--r--lib/AST/VTableBuilder.cpp62
-rw-r--r--lib/ASTMatchers/ASTMatchFinder.cpp37
-rw-r--r--lib/ASTMatchers/ASTMatchersInternal.cpp40
-rw-r--r--lib/ASTMatchers/Dynamic/Marshallers.h50
-rw-r--r--lib/ASTMatchers/Dynamic/Parser.cpp30
-rw-r--r--lib/ASTMatchers/Dynamic/Registry.cpp16
-rw-r--r--lib/ASTMatchers/Dynamic/VariantValue.cpp2
-rw-r--r--lib/Analysis/AnalysisDeclContext.cpp165
-rw-r--r--lib/Analysis/BodyFarm.cpp68
-rw-r--r--lib/Analysis/CFG.cpp644
-rw-r--r--lib/Analysis/CFGReachabilityAnalysis.cpp11
-rw-r--r--lib/Analysis/CMakeLists.txt1
-rw-r--r--lib/Analysis/CloneDetection.cpp6
-rw-r--r--lib/Analysis/ConstructionContext.cpp184
-rw-r--r--lib/Analysis/Consumed.cpp171
-rw-r--r--lib/Analysis/Dominators.cpp4
-rw-r--r--lib/Analysis/LiveVariables.cpp87
-rw-r--r--lib/Analysis/PostOrderCFGView.cpp7
-rw-r--r--lib/Analysis/PrintfFormatString.cpp114
-rw-r--r--lib/Analysis/ReachableCode.cpp25
-rw-r--r--lib/Analysis/ThreadSafety.cpp547
-rw-r--r--lib/Analysis/ThreadSafetyCommon.cpp107
-rw-r--r--lib/Analysis/ThreadSafetyTIL.cpp38
-rw-r--r--lib/Analysis/UninitializedValues.cpp172
-rw-r--r--lib/Basic/Builtins.cpp23
-rw-r--r--lib/Basic/CMakeLists.txt3
-rw-r--r--lib/Basic/Cuda.cpp103
-rw-r--r--lib/Basic/Diagnostic.cpp171
-rw-r--r--lib/Basic/DiagnosticIDs.cpp6
-rw-r--r--lib/Basic/DiagnosticOptions.cpp5
-rw-r--r--lib/Basic/FileManager.cpp28
-rw-r--r--lib/Basic/FileSystemStatCache.cpp7
-rw-r--r--lib/Basic/IdentifierTable.cpp58
-rw-r--r--lib/Basic/LangOptions.cpp12
-rw-r--r--lib/Basic/Module.cpp19
-rw-r--r--lib/Basic/ObjCRuntime.cpp7
-rw-r--r--lib/Basic/OpenMPKinds.cpp14
-rw-r--r--lib/Basic/OperatorPrecedence.cpp2
-rw-r--r--lib/Basic/Sanitizers.cpp5
-rw-r--r--lib/Basic/SourceLocation.cpp30
-rw-r--r--lib/Basic/SourceManager.cpp113
-rw-r--r--lib/Basic/TargetInfo.cpp105
-rw-r--r--lib/Basic/Targets.cpp22
-rw-r--r--lib/Basic/Targets.h2
-rw-r--r--lib/Basic/Targets/AArch64.cpp64
-rw-r--r--lib/Basic/Targets/AArch64.h9
-rw-r--r--lib/Basic/Targets/AMDGPU.cpp309
-rw-r--r--lib/Basic/Targets/AMDGPU.h234
-rw-r--r--lib/Basic/Targets/ARM.cpp34
-rw-r--r--lib/Basic/Targets/ARM.h8
-rw-r--r--lib/Basic/Targets/AVR.cpp48
-rw-r--r--lib/Basic/Targets/AVR.h3
-rw-r--r--lib/Basic/Targets/BPF.cpp12
-rw-r--r--lib/Basic/Targets/BPF.h19
-rw-r--r--lib/Basic/Targets/Hexagon.cpp35
-rw-r--r--lib/Basic/Targets/Hexagon.h2
-rw-r--r--lib/Basic/Targets/Lanai.cpp4
-rw-r--r--lib/Basic/Targets/Lanai.h2
-rw-r--r--lib/Basic/Targets/Mips.cpp43
-rw-r--r--lib/Basic/Targets/Mips.h16
-rw-r--r--lib/Basic/Targets/NVPTX.cpp37
-rw-r--r--lib/Basic/Targets/NVPTX.h10
-rw-r--r--lib/Basic/Targets/Nios2.h4
-rw-r--r--lib/Basic/Targets/OSTargets.h46
-rw-r--r--lib/Basic/Targets/PPC.cpp185
-rw-r--r--lib/Basic/Targets/PPC.h135
-rw-r--r--lib/Basic/Targets/RISCV.cpp104
-rw-r--r--lib/Basic/Targets/RISCV.h114
-rw-r--r--lib/Basic/Targets/SPIR.h5
-rw-r--r--lib/Basic/Targets/Sparc.cpp140
-rw-r--r--lib/Basic/Targets/Sparc.h49
-rw-r--r--lib/Basic/Targets/SystemZ.cpp56
-rw-r--r--lib/Basic/Targets/SystemZ.h6
-rw-r--r--lib/Basic/Targets/WebAssembly.cpp32
-rw-r--r--lib/Basic/Targets/WebAssembly.h18
-rw-r--r--lib/Basic/Targets/X86.cpp231
-rw-r--r--lib/Basic/Targets/X86.h64
-rw-r--r--lib/Basic/VersionTuple.cpp100
-rw-r--r--lib/Basic/VirtualFileSystem.cpp363
-rw-r--r--lib/Basic/XRayInstr.cpp30
-rw-r--r--lib/Basic/XRayLists.cpp24
-rw-r--r--lib/CodeGen/ABIInfo.h15
-rw-r--r--lib/CodeGen/BackendUtil.cpp282
-rw-r--r--lib/CodeGen/CGAtomic.cpp67
-rw-r--r--lib/CodeGen/CGBlocks.cpp493
-rw-r--r--lib/CodeGen/CGBlocks.h9
-rw-r--r--lib/CodeGen/CGBuilder.h37
-rw-r--r--lib/CodeGen/CGBuiltin.cpp3055
-rw-r--r--lib/CodeGen/CGCUDANV.cpp394
-rw-r--r--lib/CodeGen/CGCXX.cpp29
-rw-r--r--lib/CodeGen/CGCXXABI.cpp14
-rw-r--r--lib/CodeGen/CGCXXABI.h29
-rw-r--r--lib/CodeGen/CGCall.cpp510
-rw-r--r--lib/CodeGen/CGCall.h114
-rw-r--r--lib/CodeGen/CGClass.cpp111
-rw-r--r--lib/CodeGen/CGCleanup.cpp48
-rw-r--r--lib/CodeGen/CGCleanup.h9
-rw-r--r--lib/CodeGen/CGCoroutine.cpp73
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp508
-rw-r--r--lib/CodeGen/CGDebugInfo.h69
-rw-r--r--lib/CodeGen/CGDecl.cpp568
-rw-r--r--lib/CodeGen/CGDeclCXX.cpp25
-rw-r--r--lib/CodeGen/CGException.cpp299
-rw-r--r--lib/CodeGen/CGExpr.cpp201
-rw-r--r--lib/CodeGen/CGExprAgg.cpp454
-rw-r--r--lib/CodeGen/CGExprCXX.cpp80
-rw-r--r--lib/CodeGen/CGExprComplex.cpp13
-rw-r--r--lib/CodeGen/CGExprConstant.cpp174
-rw-r--r--lib/CodeGen/CGExprScalar.cpp108
-rw-r--r--lib/CodeGen/CGGPUBuiltin.cpp13
-rw-r--r--lib/CodeGen/CGLoopInfo.h70
-rw-r--r--lib/CodeGen/CGNonTrivialStruct.cpp885
-rw-r--r--lib/CodeGen/CGObjC.cpp68
-rw-r--r--lib/CodeGen/CGObjCGNU.cpp1808
-rw-r--r--lib/CodeGen/CGObjCMac.cpp47
-rw-r--r--lib/CodeGen/CGOpenCLRuntime.cpp81
-rw-r--r--lib/CodeGen/CGOpenCLRuntime.h33
-rw-r--r--lib/CodeGen/CGOpenMPRuntime.cpp4158
-rw-r--r--lib/CodeGen/CGOpenMPRuntime.h998
-rw-r--r--lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp2300
-rw-r--r--lib/CodeGen/CGOpenMPRuntimeNVPTX.h165
-rw-r--r--lib/CodeGen/CGRecordLayout.h18
-rw-r--r--lib/CodeGen/CGRecordLayoutBuilder.cpp83
-rw-r--r--lib/CodeGen/CGStmt.cpp51
-rw-r--r--lib/CodeGen/CGStmtOpenMP.cpp1676
-rw-r--r--lib/CodeGen/CGVTT.cpp2
-rw-r--r--lib/CodeGen/CGVTables.cpp283
-rw-r--r--lib/CodeGen/CGVTables.h10
-rw-r--r--lib/CodeGen/CGValue.h44
-rw-r--r--lib/CodeGen/CMakeLists.txt7
-rw-r--r--lib/CodeGen/CodeGenAction.cpp54
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp255
-rw-r--r--lib/CodeGen/CodeGenFunction.h928
-rw-r--r--lib/CodeGen/CodeGenModule.cpp1020
-rw-r--r--lib/CodeGen/CodeGenModule.h155
-rw-r--r--lib/CodeGen/CodeGenPGO.cpp8
-rw-r--r--lib/CodeGen/CodeGenTBAA.cpp31
-rw-r--r--lib/CodeGen/CodeGenTBAA.h9
-rw-r--r--lib/CodeGen/CodeGenTypeCache.h2
-rw-r--r--lib/CodeGen/CodeGenTypes.cpp27
-rw-r--r--lib/CodeGen/CodeGenTypes.h9
-rw-r--r--lib/CodeGen/ConstantEmitter.h2
-rw-r--r--lib/CodeGen/CoverageMappingGen.cpp153
-rw-r--r--lib/CodeGen/CoverageMappingGen.h16
-rw-r--r--lib/CodeGen/ItaniumCXXABI.cpp423
-rw-r--r--lib/CodeGen/MacroPPCallbacks.cpp3
-rw-r--r--lib/CodeGen/MacroPPCallbacks.h3
-rw-r--r--lib/CodeGen/MicrosoftCXXABI.cpp264
-rw-r--r--lib/CodeGen/ObjectFilePCHContainerOperations.cpp12
-rw-r--r--lib/CodeGen/SanitizerMetadata.cpp9
-rw-r--r--lib/CodeGen/SwiftCallingConv.cpp44
-rw-r--r--lib/CodeGen/TargetInfo.cpp615
-rw-r--r--lib/CodeGen/TargetInfo.h12
-rw-r--r--lib/CodeGen/VarBypassDetector.cpp2
-rw-r--r--lib/Driver/Action.cpp47
-rw-r--r--lib/Driver/CMakeLists.txt2
-rw-r--r--lib/Driver/Compilation.cpp66
-rw-r--r--lib/Driver/Distro.cpp3
-rw-r--r--lib/Driver/Driver.cpp992
-rw-r--r--lib/Driver/Job.cpp59
-rw-r--r--lib/Driver/Multilib.cpp31
-rw-r--r--lib/Driver/SanitizerArgs.cpp192
-rw-r--r--lib/Driver/ToolChain.cpp124
-rw-r--r--lib/Driver/ToolChains/AMDGPU.cpp1
-rw-r--r--lib/Driver/ToolChains/Ananas.cpp38
-rw-r--r--lib/Driver/ToolChains/Arch/AArch64.cpp6
-rw-r--r--lib/Driver/ToolChains/Arch/ARM.cpp24
-rw-r--r--lib/Driver/ToolChains/Arch/Mips.cpp78
-rw-r--r--lib/Driver/ToolChains/Arch/Mips.h3
-rw-r--r--lib/Driver/ToolChains/Arch/PPC.cpp10
-rw-r--r--lib/Driver/ToolChains/Arch/PPC.h7
-rw-r--r--lib/Driver/ToolChains/Arch/RISCV.cpp378
-rw-r--r--lib/Driver/ToolChains/Arch/RISCV.h32
-rw-r--r--lib/Driver/ToolChains/Arch/Sparc.cpp23
-rw-r--r--lib/Driver/ToolChains/Arch/X86.cpp43
-rw-r--r--lib/Driver/ToolChains/BareMetal.cpp33
-rw-r--r--lib/Driver/ToolChains/BareMetal.h1
-rw-r--r--lib/Driver/ToolChains/Clang.cpp555
-rw-r--r--lib/Driver/ToolChains/Clang.h6
-rw-r--r--lib/Driver/ToolChains/CloudABI.cpp13
-rw-r--r--lib/Driver/ToolChains/CloudABI.h4
-rw-r--r--lib/Driver/ToolChains/CommonArgs.cpp344
-rw-r--r--lib/Driver/ToolChains/CommonArgs.h24
-rw-r--r--lib/Driver/ToolChains/Contiki.h4
-rw-r--r--lib/Driver/ToolChains/CrossWindows.cpp3
-rw-r--r--lib/Driver/ToolChains/Cuda.cpp228
-rw-r--r--lib/Driver/ToolChains/Cuda.h28
-rw-r--r--lib/Driver/ToolChains/Darwin.cpp197
-rw-r--r--lib/Driver/ToolChains/Darwin.h15
-rw-r--r--lib/Driver/ToolChains/FreeBSD.cpp69
-rw-r--r--lib/Driver/ToolChains/Fuchsia.cpp50
-rw-r--r--lib/Driver/ToolChains/Fuchsia.h5
-rw-r--r--lib/Driver/ToolChains/Gnu.cpp655
-rw-r--r--lib/Driver/ToolChains/Gnu.h55
-rw-r--r--lib/Driver/ToolChains/HIP.cpp350
-rw-r--r--lib/Driver/ToolChains/HIP.h123
-rw-r--r--lib/Driver/ToolChains/Haiku.cpp6
-rw-r--r--lib/Driver/ToolChains/Haiku.h4
-rw-r--r--lib/Driver/ToolChains/Hexagon.cpp59
-rw-r--r--lib/Driver/ToolChains/Hexagon.h1
-rw-r--r--lib/Driver/ToolChains/Lanai.h4
-rw-r--r--lib/Driver/ToolChains/Linux.cpp120
-rw-r--r--lib/Driver/ToolChains/Linux.h4
-rw-r--r--lib/Driver/ToolChains/MSVC.cpp37
-rw-r--r--lib/Driver/ToolChains/MSVC.h4
-rw-r--r--lib/Driver/ToolChains/MinGW.cpp88
-rw-r--r--lib/Driver/ToolChains/MinGW.h1
-rw-r--r--lib/Driver/ToolChains/MipsLinux.cpp9
-rw-r--r--lib/Driver/ToolChains/MipsLinux.h4
-rw-r--r--lib/Driver/ToolChains/Myriad.cpp7
-rw-r--r--lib/Driver/ToolChains/Myriad.h4
-rw-r--r--lib/Driver/ToolChains/NaCl.cpp20
-rw-r--r--lib/Driver/ToolChains/NaCl.h4
-rw-r--r--lib/Driver/ToolChains/NetBSD.cpp62
-rw-r--r--lib/Driver/ToolChains/NetBSD.h4
-rw-r--r--lib/Driver/ToolChains/OpenBSD.cpp49
-rw-r--r--lib/Driver/ToolChains/OpenBSD.h4
-rw-r--r--lib/Driver/ToolChains/PS4CPU.cpp11
-rw-r--r--lib/Driver/ToolChains/PS4CPU.h6
-rw-r--r--lib/Driver/ToolChains/Solaris.cpp173
-rw-r--r--lib/Driver/ToolChains/Solaris.h11
-rw-r--r--lib/Driver/ToolChains/WebAssembly.cpp22
-rw-r--r--lib/Driver/ToolChains/WebAssembly.h2
-rw-r--r--lib/Driver/Types.cpp19
-rw-r--r--lib/Driver/XRayArgs.cpp99
-rw-r--r--lib/Edit/Commit.cpp25
-rw-r--r--lib/Edit/EditedSource.cpp27
-rw-r--r--lib/Edit/RewriteObjCFoundationAPI.cpp8
-rw-r--r--lib/Format/AffectedRangeManager.cpp22
-rw-r--r--lib/Format/AffectedRangeManager.h11
-rw-r--r--lib/Format/BreakableToken.cpp76
-rw-r--r--lib/Format/BreakableToken.h56
-rw-r--r--lib/Format/CMakeLists.txt1
-rw-r--r--lib/Format/ContinuationIndenter.cpp458
-rw-r--r--lib/Format/ContinuationIndenter.h158
-rw-r--r--lib/Format/Encoding.h14
-rw-r--r--lib/Format/Format.cpp745
-rw-r--r--lib/Format/FormatInternal.h4
-rw-r--r--lib/Format/FormatToken.cpp3
-rw-r--r--lib/Format/FormatToken.h175
-rw-r--r--lib/Format/FormatTokenLexer.cpp10
-rw-r--r--lib/Format/FormatTokenLexer.h2
-rw-r--r--lib/Format/NamespaceEndCommentsFixer.cpp29
-rw-r--r--lib/Format/NamespaceEndCommentsFixer.h12
-rw-r--r--lib/Format/SortJavaScriptImports.cpp20
-rw-r--r--lib/Format/SortJavaScriptImports.h2
-rw-r--r--lib/Format/TokenAnalyzer.cpp57
-rw-r--r--lib/Format/TokenAnalyzer.h51
-rw-r--r--lib/Format/TokenAnnotator.cpp617
-rw-r--r--lib/Format/TokenAnnotator.h12
-rw-r--r--lib/Format/UnwrappedLineFormatter.cpp119
-rw-r--r--lib/Format/UnwrappedLineFormatter.h13
-rw-r--r--lib/Format/UnwrappedLineParser.cpp302
-rw-r--r--lib/Format/UnwrappedLineParser.h44
-rw-r--r--lib/Format/UsingDeclarationsSorter.cpp7
-rw-r--r--lib/Format/UsingDeclarationsSorter.h2
-rw-r--r--lib/Format/WhitespaceManager.cpp4
-rw-r--r--lib/Format/WhitespaceManager.h36
-rw-r--r--lib/Frontend/ASTConsumers.cpp19
-rw-r--r--lib/Frontend/ASTMerge.cpp2
-rw-r--r--lib/Frontend/ASTUnit.cpp524
-rw-r--r--lib/Frontend/CMakeLists.txt1
-rw-r--r--lib/Frontend/CacheTokens.cpp32
-rw-r--r--lib/Frontend/CodeGenOptions.cpp2
-rw-r--r--lib/Frontend/CompilerInstance.cpp181
-rw-r--r--lib/Frontend/CompilerInvocation.cpp576
-rw-r--r--lib/Frontend/DependencyFile.cpp45
-rw-r--r--lib/Frontend/DependencyGraph.cpp23
-rw-r--r--lib/Frontend/DiagnosticRenderer.cpp168
-rw-r--r--lib/Frontend/FrontendAction.cpp41
-rw-r--r--lib/Frontend/FrontendActions.cpp254
-rw-r--r--lib/Frontend/FrontendOptions.cpp3
-rw-r--r--lib/Frontend/FrontendTiming.cpp20
-rw-r--r--lib/Frontend/HeaderIncludeGen.cpp16
-rw-r--r--lib/Frontend/InitHeaderSearch.cpp94
-rw-r--r--lib/Frontend/InitPreprocessor.cpp235
-rw-r--r--lib/Frontend/LayoutOverrideSource.cpp2
-rw-r--r--lib/Frontend/ModuleDependencyCollector.cpp6
-rw-r--r--lib/Frontend/MultiplexConsumer.cpp24
-rw-r--r--lib/Frontend/PCHContainerOperations.cpp2
-rw-r--r--lib/Frontend/PrecompiledPreamble.cpp60
-rw-r--r--lib/Frontend/PrintPreprocessedOutput.cpp25
-rw-r--r--lib/Frontend/Rewrite/FixItRewriter.cpp31
-rw-r--r--lib/Frontend/Rewrite/HTMLPrint.cpp7
-rw-r--r--lib/Frontend/Rewrite/InclusionRewriter.cpp38
-rw-r--r--lib/Frontend/Rewrite/RewriteModernObjC.cpp31
-rw-r--r--lib/Frontend/Rewrite/RewriteObjC.cpp30
-rw-r--r--lib/Frontend/SerializedDiagnosticPrinter.cpp76
-rw-r--r--lib/Frontend/SerializedDiagnosticReader.cpp31
-rw-r--r--lib/Frontend/TextDiagnostic.cpp70
-rw-r--r--lib/Frontend/TextDiagnosticBuffer.cpp21
-rw-r--r--lib/Frontend/TextDiagnosticPrinter.cpp2
-rw-r--r--lib/Frontend/VerifyDiagnosticConsumer.cpp133
-rw-r--r--lib/FrontendTool/ExecuteCompilerInvocation.cpp11
-rw-r--r--lib/Headers/CMakeLists.txt26
-rw-r--r--lib/Headers/__clang_cuda_builtin_vars.h2
-rw-r--r--lib/Headers/__clang_cuda_device_functions.h1768
-rw-r--r--lib/Headers/__clang_cuda_intrinsics.h3
-rw-r--r--lib/Headers/__clang_cuda_libdevice_declares.h466
-rw-r--r--lib/Headers/__clang_cuda_runtime_wrapper.h95
-rw-r--r--lib/Headers/__wmmintrin_aes.h25
-rw-r--r--lib/Headers/__wmmintrin_pclmul.h19
-rw-r--r--lib/Headers/ammintrin.h14
-rw-r--r--lib/Headers/avx2intrin.h658
-rw-r--r--lib/Headers/avx512bitalgintrin.h6
-rw-r--r--lib/Headers/avx512bwintrin.h866
-rw-r--r--lib/Headers/avx512cdintrin.h34
-rw-r--r--lib/Headers/avx512dqintrin.h660
-rw-r--r--lib/Headers/avx512erintrin.h128
-rw-r--r--lib/Headers/avx512fintrin.h6513
-rw-r--r--lib/Headers/avx512ifmaintrin.h48
-rw-r--r--lib/Headers/avx512ifmavlintrin.h116
-rw-r--r--lib/Headers/avx512pfintrin.h70
-rw-r--r--lib/Headers/avx512vbmi2intrin.h130
-rw-r--r--lib/Headers/avx512vbmiintrin.h66
-rw-r--r--lib/Headers/avx512vbmivlintrin.h183
-rw-r--r--lib/Headers/avx512vlbitalgintrin.h72
-rw-r--r--lib/Headers/avx512vlbwintrin.h977
-rw-r--r--lib/Headers/avx512vlcdintrin.h138
-rw-r--r--lib/Headers/avx512vldqintrin.h579
-rw-r--r--lib/Headers/avx512vlintrin.h5697
-rw-r--r--lib/Headers/avx512vlvbmi2intrin.h475
-rw-r--r--lib/Headers/avx512vlvnniintrin.h253
-rw-r--r--lib/Headers/avx512vnniintrin.h99
-rw-r--r--lib/Headers/avx512vpopcntdqintrin.h6
-rw-r--r--lib/Headers/avx512vpopcntdqvlintrin.h40
-rw-r--r--lib/Headers/avxintrin.h1181
-rw-r--r--lib/Headers/bmiintrin.h38
-rw-r--r--lib/Headers/cetintrin.h22
-rw-r--r--lib/Headers/cldemoteintrin.h42
-rw-r--r--lib/Headers/clflushoptintrin.h2
-rw-r--r--lib/Headers/clwbintrin.h2
-rw-r--r--lib/Headers/clzerointrin.h10
-rw-r--r--lib/Headers/cpuid.h14
-rw-r--r--lib/Headers/cuda_wrappers/algorithm64
-rw-r--r--lib/Headers/emmintrin.h869
-rw-r--r--lib/Headers/f16cintrin.h82
-rw-r--r--lib/Headers/fma4intrin.h70
-rw-r--r--lib/Headers/fmaintrin.h72
-rw-r--r--lib/Headers/fxsrintrin.h16
-rw-r--r--lib/Headers/gfniintrin.h112
-rw-r--r--lib/Headers/htmxlintrin.h2
-rw-r--r--lib/Headers/ia32intrin.h5
-rw-r--r--lib/Headers/immintrin.h197
-rw-r--r--lib/Headers/intrin.h158
-rw-r--r--lib/Headers/invpcidintrin.h37
-rw-r--r--lib/Headers/lwpintrin.h14
-rw-r--r--lib/Headers/lzcntintrin.h14
-rw-r--r--lib/Headers/mm3dnow.h6
-rw-r--r--lib/Headers/mmintrin.h160
-rw-r--r--lib/Headers/module.modulemap20
-rw-r--r--lib/Headers/movdirintrin.h63
-rw-r--r--lib/Headers/mwaitxintrin.h6
-rw-r--r--lib/Headers/nmmintrin.h6
-rw-r--r--lib/Headers/opencl-c.h6
-rw-r--r--lib/Headers/pconfigintrin.h50
-rw-r--r--lib/Headers/pkuintrin.h4
-rw-r--r--lib/Headers/pmmintrin.h32
-rw-r--r--lib/Headers/popcntintrin.h14
-rw-r--r--lib/Headers/prfchwintrin.h6
-rw-r--r--lib/Headers/ptwriteintrin.h51
-rw-r--r--lib/Headers/rdseedintrin.h2
-rw-r--r--lib/Headers/sgxintrin.h70
-rw-r--r--lib/Headers/shaintrin.h6
-rw-r--r--lib/Headers/smmintrin.h345
-rw-r--r--lib/Headers/stdint.h4
-rw-r--r--lib/Headers/tmmintrin.h124
-rw-r--r--lib/Headers/vaesintrin.h4
-rw-r--r--lib/Headers/vpclmulqdqintrin.h10
-rw-r--r--lib/Headers/waitpkgintrin.h56
-rw-r--r--lib/Headers/wbnoinvdintrin.h38
-rw-r--r--lib/Headers/wmmintrin.h6
-rw-r--r--lib/Headers/x86intrin.h25
-rw-r--r--lib/Headers/xmmintrin.h462
-rw-r--r--lib/Headers/xopintrin.h74
-rw-r--r--lib/Headers/xsavecintrin.h2
-rw-r--r--lib/Headers/xsaveintrin.h10
-rw-r--r--lib/Headers/xsaveoptintrin.h6
-rw-r--r--lib/Headers/xsavesintrin.h2
-rw-r--r--lib/Headers/xtestintrin.h2
-rw-r--r--lib/Index/CMakeLists.txt1
-rw-r--r--lib/Index/IndexDecl.cpp11
-rw-r--r--lib/Index/IndexSymbol.cpp12
-rw-r--r--lib/Index/IndexTypeSourceInfo.cpp2
-rw-r--r--lib/Index/IndexingAction.cpp159
-rw-r--r--lib/Index/IndexingContext.cpp57
-rw-r--r--lib/Index/IndexingContext.h15
-rw-r--r--lib/Index/SimpleFormatContext.h4
-rw-r--r--lib/Index/USRGeneration.cpp30
-rw-r--r--lib/Lex/HeaderSearch.cpp140
-rw-r--r--lib/Lex/Lexer.cpp103
-rw-r--r--lib/Lex/LiteralSupport.cpp197
-rw-r--r--lib/Lex/MacroArgs.cpp5
-rw-r--r--lib/Lex/MacroInfo.cpp2
-rw-r--r--lib/Lex/ModuleMap.cpp310
-rw-r--r--lib/Lex/PPCaching.cpp4
-rw-r--r--lib/Lex/PPDirectives.cpp124
-rw-r--r--lib/Lex/PPExpressions.cpp2
-rw-r--r--lib/Lex/PPLexerChange.cpp32
-rw-r--r--lib/Lex/PPMacroExpansion.cpp238
-rw-r--r--lib/Lex/PTHLexer.cpp10
-rw-r--r--lib/Lex/Pragma.cpp83
-rw-r--r--lib/Lex/PreprocessingRecord.cpp34
-rw-r--r--lib/Lex/Preprocessor.cpp117
-rw-r--r--lib/Lex/PreprocessorLexer.cpp2
-rw-r--r--lib/Lex/ScratchBuffer.cpp8
-rw-r--r--lib/Lex/TokenLexer.cpp14
-rw-r--r--lib/Parse/ParseAST.cpp18
-rw-r--r--lib/Parse/ParseCXXInlineMethods.cpp24
-rw-r--r--lib/Parse/ParseDecl.cpp738
-rw-r--r--lib/Parse/ParseDeclCXX.cpp283
-rw-r--r--lib/Parse/ParseExpr.cpp208
-rw-r--r--lib/Parse/ParseExprCXX.cpp348
-rw-r--r--lib/Parse/ParseObjc.cpp197
-rw-r--r--lib/Parse/ParseOpenMP.cpp319
-rw-r--r--lib/Parse/ParsePragma.cpp208
-rw-r--r--lib/Parse/ParseStmt.cpp74
-rw-r--r--lib/Parse/ParseStmtAsm.cpp2
-rw-r--r--lib/Parse/ParseTemplate.cpp383
-rw-r--r--lib/Parse/ParseTentative.cpp63
-rw-r--r--lib/Parse/Parser.cpp81
-rw-r--r--lib/Rewrite/DeltaTree.cpp48
-rw-r--r--lib/Rewrite/HTMLRewrite.cpp224
-rw-r--r--lib/Rewrite/RewriteRope.cpp77
-rw-r--r--lib/Rewrite/Rewriter.cpp42
-rw-r--r--lib/Rewrite/TokenRewriter.cpp15
-rw-r--r--lib/Sema/AnalysisBasedWarnings.cpp270
-rw-r--r--lib/Sema/CMakeLists.txt2
-rw-r--r--lib/Sema/CodeCompleteConsumer.cpp162
-rw-r--r--lib/Sema/CoroutineStmtBuilder.h10
-rw-r--r--lib/Sema/DeclSpec.cpp70
-rw-r--r--lib/Sema/DelayedDiagnostic.cpp21
-rw-r--r--lib/Sema/IdentifierResolver.cpp39
-rw-r--r--lib/Sema/JumpDiagnostics.cpp12
-rw-r--r--lib/Sema/MultiplexExternalSemaSource.cpp18
-rw-r--r--lib/Sema/ParsedAttr.cpp (renamed from lib/Sema/AttributeList.cpp)162
-rw-r--r--lib/Sema/Scope.cpp99
-rw-r--r--lib/Sema/ScopeInfo.cpp1
-rw-r--r--lib/Sema/Sema.cpp232
-rw-r--r--lib/Sema/SemaAccess.cpp29
-rw-r--r--lib/Sema/SemaAttr.cpp17
-rw-r--r--lib/Sema/SemaCUDA.cpp88
-rw-r--r--lib/Sema/SemaCXXScopeSpec.cpp21
-rw-r--r--lib/Sema/SemaCast.cpp457
-rw-r--r--lib/Sema/SemaChecking.cpp2529
-rw-r--r--lib/Sema/SemaCodeComplete.cpp2365
-rw-r--r--lib/Sema/SemaCoroutine.cpp326
-rw-r--r--lib/Sema/SemaDecl.cpp1443
-rw-r--r--lib/Sema/SemaDeclAttr.cpp4288
-rw-r--r--lib/Sema/SemaDeclCXX.cpp1150
-rw-r--r--lib/Sema/SemaDeclObjC.cpp211
-rw-r--r--lib/Sema/SemaExceptionSpec.cpp421
-rw-r--r--lib/Sema/SemaExpr.cpp1159
-rw-r--r--lib/Sema/SemaExprCXX.cpp588
-rw-r--r--lib/Sema/SemaExprMember.cpp152
-rw-r--r--lib/Sema/SemaExprObjC.cpp76
-rw-r--r--lib/Sema/SemaInit.cpp1076
-rw-r--r--lib/Sema/SemaLambda.cpp162
-rw-r--r--lib/Sema/SemaLookup.cpp240
-rw-r--r--lib/Sema/SemaObjCProperty.cpp24
-rw-r--r--lib/Sema/SemaOpenMP.cpp3152
-rw-r--r--lib/Sema/SemaOverload.cpp724
-rw-r--r--lib/Sema/SemaPseudoObject.cpp95
-rw-r--r--lib/Sema/SemaStmt.cpp579
-rw-r--r--lib/Sema/SemaStmtAsm.cpp4
-rw-r--r--lib/Sema/SemaStmtAttr.cpp27
-rw-r--r--lib/Sema/SemaTemplate.cpp772
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp909
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp329
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp201
-rw-r--r--lib/Sema/SemaTemplateVariadic.cpp119
-rw-r--r--lib/Sema/SemaType.cpp1488
-rw-r--r--lib/Sema/TreeTransform.h703
-rw-r--r--lib/Sema/TypeLocBuilder.h6
-rw-r--r--lib/Serialization/ASTCommon.cpp97
-rw-r--r--lib/Serialization/ASTCommon.h8
-rw-r--r--lib/Serialization/ASTReader.cpp992
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp660
-rw-r--r--lib/Serialization/ASTReaderInternals.h16
-rw-r--r--lib/Serialization/ASTReaderStmt.cpp180
-rw-r--r--lib/Serialization/ASTWriter.cpp348
-rw-r--r--lib/Serialization/ASTWriterDecl.cpp49
-rw-r--r--lib/Serialization/ASTWriterStmt.cpp16
-rw-r--r--lib/Serialization/GlobalModuleIndex.cpp76
-rw-r--r--lib/Serialization/Module.cpp9
-rw-r--r--lib/Serialization/MultiOnDiskHashTable.h22
-rw-r--r--lib/StaticAnalyzer/Checkers/AllocationDiagnostics.h2
-rw-r--r--lib/StaticAnalyzer/Checkers/AllocationState.h34
-rw-r--r--lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp62
-rw-r--r--lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp25
-rw-r--r--lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp14
-rw-r--r--lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp10
-rw-r--r--lib/StaticAnalyzer/Checkers/CMakeLists.txt7
-rw-r--r--lib/StaticAnalyzer/Checkers/CStringChecker.cpp470
-rw-r--r--lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp79
-rw-r--r--lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp8
-rw-r--r--lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp152
-rw-r--r--lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp61
-rw-r--r--lib/StaticAnalyzer/Checkers/ChrootChecker.cpp4
-rw-r--r--lib/StaticAnalyzer/Checkers/DeleteWithNonVirtualDtorChecker.cpp6
-rw-r--r--lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp18
-rw-r--r--lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp3
-rw-r--r--lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp8
-rw-r--r--lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp4
-rw-r--r--lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp3
-rw-r--r--lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp229
-rw-r--r--lib/StaticAnalyzer/Checkers/GTestChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp60
-rw-r--r--lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp4
-rw-r--r--lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp252
-rw-r--r--lib/StaticAnalyzer/Checkers/IteratorChecker.cpp512
-rw-r--r--lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp12
-rw-r--r--lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp10
-rw-r--r--lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.h2
-rw-r--r--lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp10
-rw-r--r--lib/StaticAnalyzer/Checkers/MallocChecker.cpp328
-rw-r--r--lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp9
-rw-r--r--lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp88
-rw-r--r--lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp3
-rw-r--r--lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp140
-rw-r--r--lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp4
-rw-r--r--lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp44
-rw-r--r--lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp6
-rw-r--r--lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp209
-rw-r--r--lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp8
-rw-r--r--lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp16
-rw-r--r--lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp4
-rw-r--r--lib/StaticAnalyzer/Checkers/PaddingChecker.cpp6
-rw-r--r--lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp22
-rw-r--r--lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp6
-rw-r--r--lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp23
-rw-r--r--lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp77
-rw-r--r--lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp217
-rw-r--r--lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp13
-rw-r--r--lib/StaticAnalyzer/Checkers/StreamChecker.cpp36
-rw-r--r--lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp10
-rw-r--r--lib/StaticAnalyzer/Checkers/TraversalChecker.cpp5
-rw-r--r--lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp90
-rw-r--r--lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp4
-rw-r--r--lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp33
-rw-r--r--lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp34
-rw-r--r--lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp688
-rw-r--r--lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp9
-rw-r--r--lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp3
-rw-r--r--lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp21
-rw-r--r--lib/StaticAnalyzer/Checkers/ValistChecker.cpp28
-rw-r--r--lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp13
-rw-r--r--lib/StaticAnalyzer/Core/AnalysisManager.cpp3
-rw-r--r--lib/StaticAnalyzer/Core/AnalyzerOptions.cpp113
-rw-r--r--lib/StaticAnalyzer/Core/BasicValueFactory.cpp62
-rw-r--r--lib/StaticAnalyzer/Core/BugReporter.cpp2538
-rw-r--r--lib/StaticAnalyzer/Core/BugReporterVisitors.cpp1245
-rw-r--r--lib/StaticAnalyzer/Core/CMakeLists.txt5
-rw-r--r--lib/StaticAnalyzer/Core/CallEvent.cpp240
-rw-r--r--lib/StaticAnalyzer/Core/CheckerContext.cpp3
-rw-r--r--lib/StaticAnalyzer/Core/CheckerHelpers.cpp29
-rw-r--r--lib/StaticAnalyzer/Core/CheckerManager.cpp310
-rw-r--r--lib/StaticAnalyzer/Core/CheckerRegistry.cpp72
-rw-r--r--lib/StaticAnalyzer/Core/ConstraintManager.cpp11
-rw-r--r--lib/StaticAnalyzer/Core/CoreEngine.cpp257
-rw-r--r--lib/StaticAnalyzer/Core/DynamicTypeMap.cpp38
-rw-r--r--lib/StaticAnalyzer/Core/Environment.cpp95
-rw-r--r--lib/StaticAnalyzer/Core/ExplodedGraph.cpp47
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngine.cpp1088
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineC.cpp49
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineCXX.cpp530
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp224
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineObjC.cpp94
-rw-r--r--lib/StaticAnalyzer/Core/FunctionSummary.cpp13
-rw-r--r--lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp266
-rw-r--r--lib/StaticAnalyzer/Core/LoopUnrolling.cpp20
-rw-r--r--lib/StaticAnalyzer/Core/LoopWidening.cpp33
-rw-r--r--lib/StaticAnalyzer/Core/MemRegion.cpp303
-rw-r--r--lib/StaticAnalyzer/Core/PathDiagnostic.cpp409
-rw-r--r--lib/StaticAnalyzer/Core/PlistDiagnostics.cpp142
-rw-r--r--lib/StaticAnalyzer/Core/ProgramState.cpp65
-rw-r--r--lib/StaticAnalyzer/Core/RangeConstraintManager.cpp455
-rw-r--r--lib/StaticAnalyzer/Core/RangedConstraintManager.cpp25
-rw-r--r--lib/StaticAnalyzer/Core/RegionStore.cpp140
-rw-r--r--lib/StaticAnalyzer/Core/SMTConstraintManager.cpp181
-rw-r--r--lib/StaticAnalyzer/Core/SValBuilder.cpp85
-rw-r--r--lib/StaticAnalyzer/Core/SVals.cpp65
-rw-r--r--lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp260
-rw-r--r--lib/StaticAnalyzer/Core/Store.cpp96
-rw-r--r--lib/StaticAnalyzer/Core/SymbolManager.cpp46
-rw-r--r--lib/StaticAnalyzer/Core/WorkList.cpp254
-rw-r--r--lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp2053
-rw-r--r--lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp174
-rw-r--r--lib/StaticAnalyzer/Frontend/CMakeLists.txt3
-rw-r--r--lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp13
-rw-r--r--lib/StaticAnalyzer/Frontend/ModelConsumer.cpp2
-rw-r--r--lib/StaticAnalyzer/Frontend/ModelInjector.cpp6
-rw-r--r--lib/StaticAnalyzer/Frontend/ModelInjector.h4
-rw-r--r--lib/Tooling/ASTDiff/ASTDiff.cpp4
-rw-r--r--lib/Tooling/AllTUsExecution.cpp161
-rw-r--r--lib/Tooling/ArgumentsAdjusters.cpp7
-rw-r--r--lib/Tooling/CMakeLists.txt3
-rw-r--r--lib/Tooling/CompilationDatabase.cpp57
-rw-r--r--lib/Tooling/Core/CMakeLists.txt2
-rw-r--r--lib/Tooling/Core/Replacement.cpp69
-rw-r--r--lib/Tooling/Execution.cpp9
-rw-r--r--lib/Tooling/FileMatchTrie.cpp45
-rw-r--r--lib/Tooling/Inclusions/CMakeLists.txt12
-rw-r--r--lib/Tooling/Inclusions/HeaderIncludes.cpp330
-rw-r--r--lib/Tooling/Inclusions/IncludeStyle.cpp31
-rw-r--r--lib/Tooling/InterpolatingCompilationDatabase.cpp458
-rw-r--r--lib/Tooling/JSONCompilationDatabase.cpp88
-rw-r--r--lib/Tooling/Refactoring/AtomicChange.cpp6
-rw-r--r--lib/Tooling/Refactoring/Extract/Extract.cpp2
-rw-r--r--lib/Tooling/Refactoring/Rename/RenamingAction.cpp2
-rw-r--r--lib/Tooling/Refactoring/Rename/USRFinder.cpp4
-rw-r--r--lib/Tooling/Refactoring/Rename/USRFindingAction.cpp4
-rw-r--r--lib/Tooling/Refactoring/Rename/USRLocFinder.cpp8
-rw-r--r--lib/Tooling/StandaloneExecution.cpp8
-rw-r--r--lib/Tooling/Tooling.cpp196
-rw-r--r--runtime/CMakeLists.txt6
-rw-r--r--test/ARCMT/checking.m2
-rw-r--r--test/ARCMT/releases-driver.m2
-rw-r--r--test/ARCMT/releases-driver.m.result2
-rw-r--r--test/ARCMT/with-arc-mode-modify.m2
-rw-r--r--test/ARCMT/with-arc-mode-modify.m.result2
-rw-r--r--test/ASTMerge/class-template/Inputs/class-template1.cpp5
-rw-r--r--test/ASTMerge/class-template/Inputs/class-template2.cpp4
-rw-r--r--test/ASTMerge/class-template/test.cpp36
-rw-r--r--test/ASTMerge/class/Inputs/class1.cpp28
-rw-r--r--test/ASTMerge/class/Inputs/class2.cpp26
-rw-r--r--test/ASTMerge/class/test.cpp10
-rw-r--r--test/ASTMerge/exprs-cpp/Inputs/exprs3.cpp17
-rw-r--r--test/ASTMerge/exprs-cpp/test.cpp3
-rw-r--r--test/ASTMerge/function-cpp/Inputs/function-1.cpp8
-rw-r--r--test/ASTMerge/function-cpp/test.cpp10
-rw-r--r--test/ASTMerge/injected-class-name-decl/Inputs/inject1.cpp2
-rw-r--r--test/ASTMerge/injected-class-name-decl/Inputs/inject2.cpp2
-rw-r--r--test/ASTMerge/injected-class-name-decl/test.cpp3
-rw-r--r--test/ASTMerge/interface/Inputs/interface1.m4
-rw-r--r--test/ASTMerge/namespace/test.cpp2
-rw-r--r--test/ASTMerge/std-initializer-list/Inputs/il.cpp9
-rw-r--r--test/ASTMerge/std-initializer-list/test.cpp3
-rw-r--r--test/ASTMerge/struct/Inputs/struct1.c62
-rw-r--r--test/ASTMerge/struct/Inputs/struct2.c62
-rw-r--r--test/ASTMerge/struct/test.c10
-rw-r--r--test/ASTMerge/var-cpp/Inputs/var1.cpp17
-rw-r--r--test/ASTMerge/var-cpp/test.cpp9
-rw-r--r--test/Analysis/Checkers/RunLoopAutoreleaseLeakChecker.m104
-rw-r--r--test/Analysis/Inputs/ctu-chain.cpp20
-rw-r--r--test/Analysis/Inputs/ctu-other.cpp77
-rw-r--r--test/Analysis/Inputs/externalFnMap.txt15
-rw-r--r--test/Analysis/Inputs/system-header-simulator-cxx.h35
-rw-r--r--test/Analysis/Inputs/system-header-simulator-for-cxx-uninitialized-object.h18
-rw-r--r--test/Analysis/Inputs/system-header-simulator-for-nullability-cxx.h9
-rw-r--r--test/Analysis/Inputs/system-header-simulator-for-nullability.h11
-rw-r--r--test/Analysis/Inputs/system-header-simulator-for-objc-dealloc.h4
-rw-r--r--test/Analysis/Inputs/system-header-simulator.h5
-rw-r--r--test/Analysis/MismatchedDeallocator-checker-test.mm1
-rw-r--r--test/Analysis/MismatchedDeallocator-path-notes.cpp70
-rw-r--r--test/Analysis/MisusedMovedObject.cpp11
-rw-r--r--test/Analysis/NewDelete-atomics.cpp78
-rw-r--r--test/Analysis/NewDelete-checker-test.cpp20
-rw-r--r--test/Analysis/NewDelete-custom.cpp25
-rw-r--r--test/Analysis/NewDelete-intersections.mm2
-rw-r--r--test/Analysis/NewDelete-path-notes.cpp129
-rw-r--r--test/Analysis/NewDeleteLeaks-PR19102.cpp1
-rw-r--r--test/Analysis/PR24184.cpp1
-rw-r--r--test/Analysis/PR37855.c24
-rw-r--r--test/Analysis/PR38208.c43
-rw-r--r--test/Analysis/_Bool-increment-decrement.c140
-rw-r--r--test/Analysis/analyzeOneFunction.m2
-rw-r--r--test/Analysis/analyzer-config.c12
-rw-r--r--test/Analysis/analyzer-config.cpp18
-rw-r--r--test/Analysis/analyzer-stats.c18
-rw-r--r--test/Analysis/auto-obj-dtors-cfg-output.cpp467
-rw-r--r--test/Analysis/autoreleasewritechecker_test.m281
-rw-r--r--test/Analysis/bitwise-ops.c11
-rw-r--r--test/Analysis/blocks.mm18
-rw-r--r--test/Analysis/bool-increment.cpp84
-rw-r--r--test/Analysis/bsd-string.c45
-rw-r--r--test/Analysis/bstring.c9
-rw-r--r--test/Analysis/bstring.cpp124
-rw-r--r--test/Analysis/builtin-functions.cpp17
-rw-r--r--test/Analysis/call_once.cpp63
-rw-r--r--test/Analysis/casts.c26
-rw-r--r--test/Analysis/casts.cpp20
-rw-r--r--test/Analysis/cfg-rich-constructors.cpp906
-rw-r--r--test/Analysis/cfg.cpp36
-rw-r--r--test/Analysis/conditional-path-notes.c326
-rw-r--r--test/Analysis/const-method-call.cpp24
-rw-r--r--test/Analysis/constant-folding.c4
-rw-r--r--test/Analysis/constraint_manager_negate_difference.c98
-rw-r--r--test/Analysis/copypaste/macro-complexity.cpp4
-rw-r--r--test/Analysis/copypaste/plist-diagnostics.cpp33
-rw-r--r--test/Analysis/crash-trace.c4
-rw-r--r--test/Analysis/cstring-plist.c22
-rw-r--r--test/Analysis/cstring-syntax.c20
-rw-r--r--test/Analysis/ctor.mm148
-rw-r--r--test/Analysis/ctu-hdr.h3
-rw-r--r--test/Analysis/ctu-main.cpp68
-rw-r--r--test/Analysis/cxx-for-range.cpp2
-rw-r--r--test/Analysis/cxx-uninitialized-object-inheritance.cpp775
-rw-r--r--test/Analysis/cxx-uninitialized-object-notes-as-warnings.cpp15
-rw-r--r--test/Analysis/cxx-uninitialized-object-ptr-ref.cpp695
-rw-r--r--test/Analysis/cxx-uninitialized-object.cpp1103
-rw-r--r--test/Analysis/cxx17-mandatory-elision.cpp304
-rw-r--r--test/Analysis/cxxnewexpr-callback-inline.cpp32
-rw-r--r--test/Analysis/cxxnewexpr-callback-noinline.cpp29
-rw-r--r--test/Analysis/dead-stores.c2
-rw-r--r--test/Analysis/diagnostics/deref-track-symbolic-region.c2
-rw-r--r--test/Analysis/diagnostics/explicit-suppression.cpp2
-rw-r--r--test/Analysis/diagnostics/implicit-cxx-std-suppression.cpp2
-rw-r--r--test/Analysis/diagnostics/macro-null-return-suppression.cpp68
-rw-r--r--test/Analysis/diagnostics/no-store-func-path-notes.c226
-rw-r--r--test/Analysis/diagnostics/no-store-func-path-notes.cpp177
-rw-r--r--test/Analysis/diagnostics/no-store-func-path-notes.m77
-rw-r--r--test/Analysis/diagnostics/plist-multi-file.c205
-rw-r--r--test/Analysis/diagnostics/plist-multi-file.h3
-rw-r--r--test/Analysis/diagnostics/report-issues-within-main-file.cpp210
-rw-r--r--test/Analysis/diagnostics/undef-value-caller.c36
-rw-r--r--test/Analysis/diagnostics/undef-value-param.c174
-rw-r--r--test/Analysis/diagnostics/undef-value-param.m120
-rw-r--r--test/Analysis/dtor-cxx11.cpp2
-rw-r--r--test/Analysis/dtor.cpp2
-rw-r--r--test/Analysis/dynamic_type_check.m2
-rw-r--r--test/Analysis/edges-new.mm2
-rw-r--r--test/Analysis/explain-svals.cpp4
-rw-r--r--test/Analysis/exploration_order/noexprcrash.c17
-rw-r--r--test/Analysis/exploration_order/prefer_unexplored.cpp43
-rw-r--r--test/Analysis/expr-inspection.c6
-rw-r--r--test/Analysis/gcdantipatternchecker_test.m345
-rw-r--r--test/Analysis/globals.cpp111
-rw-r--r--test/Analysis/gtest.cpp7
-rw-r--r--test/Analysis/hangs.c30
-rw-r--r--test/Analysis/html_diagnostics/relevant_lines/goto.c13
-rw-r--r--test/Analysis/html_diagnostics/relevant_lines/header.h12
-rw-r--r--test/Analysis/html_diagnostics/relevant_lines/macros_same_file.c15
-rw-r--r--test/Analysis/html_diagnostics/relevant_lines/multifile.c14
-rw-r--r--test/Analysis/html_diagnostics/relevant_lines/multiline_func_def.c16
-rw-r--r--test/Analysis/html_diagnostics/relevant_lines/notexecutedlines.c12
-rw-r--r--test/Analysis/html_diagnostics/relevant_lines/objcmethods.m19
-rw-r--r--test/Analysis/html_diagnostics/relevant_lines/simple_conditional.c13
-rw-r--r--test/Analysis/html_diagnostics/relevant_lines/switch.c20
-rw-r--r--test/Analysis/html_diagnostics/relevant_lines/switch_default.c20
-rw-r--r--test/Analysis/html_diagnostics/relevant_lines/unused_header.c19
-rw-r--r--test/Analysis/implicit-ctor-undef-value.cpp75
-rw-r--r--test/Analysis/index-type.c23
-rw-r--r--test/Analysis/initialization.c28
-rw-r--r--test/Analysis/initialization.cpp20
-rw-r--r--test/Analysis/initializer.cpp25
-rw-r--r--test/Analysis/initializers-cfg-output.cpp30
-rw-r--r--test/Analysis/inline-plist.c206
-rw-r--r--test/Analysis/inline-unique-reports.c36
-rw-r--r--test/Analysis/inline.cpp13
-rw-r--r--test/Analysis/inlining/containers.cpp2
-rw-r--r--test/Analysis/inlining/eager-reclamation-path-notes.c142
-rw-r--r--test/Analysis/inlining/eager-reclamation-path-notes.cpp2
-rw-r--r--test/Analysis/inlining/false-positive-suppression.c14
-rw-r--r--test/Analysis/inlining/inline-defensive-checks.c3
-rw-r--r--test/Analysis/inlining/inline-defensive-checks.cpp17
-rw-r--r--test/Analysis/inlining/path-notes.c546
-rw-r--r--test/Analysis/inlining/path-notes.cpp694
-rw-r--r--test/Analysis/inlining/path-notes.m295
-rw-r--r--test/Analysis/inlining/temp-dtors-path-notes.cpp59
-rw-r--r--test/Analysis/inner-pointer.cpp291
-rw-r--r--test/Analysis/iterator-range.cpp107
-rw-r--r--test/Analysis/lambda-notes.cpp2
-rw-r--r--test/Analysis/lambdas.cpp17
-rw-r--r--test/Analysis/lifetime-cfg-output.cpp2
-rw-r--r--test/Analysis/lifetime-extension.cpp298
-rw-r--r--test/Analysis/live-bindings-test.cpp124
-rw-r--r--test/Analysis/localization.m18
-rw-r--r--test/Analysis/loop-unrolling.cpp144
-rw-r--r--test/Analysis/loop-widening-preserve-reference-type.cpp14
-rw-r--r--test/Analysis/loop-widening.c14
-rw-r--r--test/Analysis/malloc-custom.c2
-rw-r--r--test/Analysis/malloc-fnptr-plist.c11
-rw-r--r--test/Analysis/malloc-plist.c1188
-rw-r--r--test/Analysis/malloc.c31
-rw-r--r--test/Analysis/malloc.cpp2
-rw-r--r--test/Analysis/malloc.mm10
-rw-r--r--test/Analysis/method-call-path-notes.cpp2
-rw-r--r--test/Analysis/misc-ps-region-store.m2
-rw-r--r--test/Analysis/missing-bind-temporary.cpp130
-rw-r--r--test/Analysis/mmap-writeexec.c44
-rw-r--r--test/Analysis/new-ctor-conservative.cpp46
-rw-r--r--test/Analysis/new-ctor-inlined.cpp55
-rw-r--r--test/Analysis/new-ctor-malloc.cpp21
-rw-r--r--test/Analysis/new-ctor-null-throw.cpp26
-rw-r--r--test/Analysis/new-ctor-null.cpp36
-rw-r--r--test/Analysis/new-ctor-recursive.cpp118
-rw-r--r--test/Analysis/new-ctor-symbolic.cpp33
-rw-r--r--test/Analysis/new-dynamic-types.cpp28
-rw-r--r--test/Analysis/new.cpp28
-rw-r--r--test/Analysis/nonnullparamchecker-crash.cpp11
-rw-r--r--test/Analysis/novoidtypecrash.c8
-rw-r--r--test/Analysis/null-deref-path-notes.c45
-rw-r--r--test/Analysis/null-deref-path-notes.m2
-rw-r--r--test/Analysis/null-deref-ps-region.c2
-rw-r--r--test/Analysis/nullability-notes.m2
-rw-r--r--test/Analysis/nullability.mm2
-rw-r--r--test/Analysis/number-object-conversion.mm13
-rw-r--r--test/Analysis/objc-arc.m2
-rw-r--r--test/Analysis/objc-for.m8
-rw-r--r--test/Analysis/objc-properties.m2
-rw-r--r--test/Analysis/objc-radar17039661.m246
-rw-r--r--test/Analysis/objc/direct-ivar-assignment-in-annotated-functions.m2
-rw-r--r--test/Analysis/offsetofexpr-callback.c13
-rw-r--r--test/Analysis/plist-diagnostics-template-function.cpp41
-rw-r--r--test/Analysis/plist-diagnostics-template-record.cpp42
-rw-r--r--test/Analysis/plist-macros.cpp220
-rw-r--r--test/Analysis/plist-output-alternate.m252
-rw-r--r--test/Analysis/plist-output.m862
-rw-r--r--test/Analysis/plist-stats-output.c14
-rw-r--r--test/Analysis/pr22954.c5
-rw-r--r--test/Analysis/pr37802.cpp107
-rw-r--r--test/Analysis/ptr-arith.c29
-rw-r--r--test/Analysis/region-store.cpp2
-rw-r--r--test/Analysis/region_store_overflow.c16
-rw-r--r--test/Analysis/retain-release-path-notes-gc.m192
-rw-r--r--test/Analysis/retain-release-path-notes.m1104
-rw-r--r--test/Analysis/retain-release-safe.c21
-rw-r--r--test/Analysis/retaincountchecker-compoundregion.m25
-rw-r--r--test/Analysis/return-stmt-merge.cpp37
-rw-r--r--test/Analysis/scopes-cfg-output.cpp1171
-rw-r--r--test/Analysis/security-syntax-checks.m31
-rw-r--r--test/Analysis/stack-addr-ps.c2
-rw-r--r--test/Analysis/stack-addr-ps.cpp4
-rw-r--r--test/Analysis/stackaddrleak.c2
-rw-r--r--test/Analysis/std-c-library-functions.c3
-rw-r--r--test/Analysis/string.c325
-rw-r--r--test/Analysis/structured_bindings.cc10
-rw-r--r--test/Analysis/sval-dump-int128.c7
-rw-r--r--test/Analysis/svalbuilder-rearrange-comparisons.c936
-rw-r--r--test/Analysis/symbol-reaper.c56
-rw-r--r--test/Analysis/taint-diagnostic-visitor.c25
-rw-r--r--test/Analysis/taint-generic.c6
-rw-r--r--test/Analysis/temp-obj-dtors-cfg-output.cpp656
-rw-r--r--test/Analysis/temp-obj-dtors-option.cpp22
-rw-r--r--test/Analysis/temporaries-callback-order.cpp7
-rw-r--r--test/Analysis/temporaries.cpp423
-rw-r--r--test/Analysis/this-pointer.cpp88
-rw-r--r--test/Analysis/trustnonnullchecker_test.m69
-rw-r--r--test/Analysis/trustnonnullchecker_test.mm9
-rw-r--r--test/Analysis/undef-call.c14
-rw-r--r--test/Analysis/unified-sources/UnifiedSource-1.cpp5
-rw-r--r--test/Analysis/unified-sources/container.h10
-rw-r--r--test/Analysis/unified-sources/source1.cpp15
-rw-r--r--test/Analysis/unified-sources/source2.cpp25
-rw-r--r--test/Analysis/uninit-const.cpp1
-rw-r--r--test/Analysis/unions.cpp20
-rw-r--r--test/Analysis/unix-fns.c206
-rw-r--r--test/Analysis/unreachable-code-path.c1
-rw-r--r--test/Analysis/virtualcall.cpp3
-rw-r--r--test/Analysis/yaccignore.c13
-rw-r--r--test/Analysis/z3-crosscheck.c43
-rw-r--r--test/Analysis/z3/apsint.c16
-rw-r--r--test/Analysis/z3/enabled.c3
-rw-r--r--test/CMakeLists.txt6
-rw-r--r--test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp15
-rw-r--r--test/CXX/class/class.bit/p2.cpp2
-rw-r--r--test/CXX/class/class.mem/p13.cpp47
-rw-r--r--test/CXX/class/class.mem/p14.cpp5
-rw-r--r--test/CXX/class/class.union/p1.cpp16
-rw-r--r--test/CXX/conv/conv.prom/p5.cpp19
-rw-r--r--test/CXX/dcl.dcl/dcl.attr/dcl.align/p1.cpp6
-rw-r--r--test/CXX/dcl.dcl/dcl.attr/dcl.attr.unused/p2.cpp2
-rw-r--r--test/CXX/dcl.dcl/dcl.link/p7.cpp8
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp2
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp5
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p4-cxx0x.cpp7
-rw-r--r--test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1.cpp5
-rw-r--r--test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp31
-rw-r--r--test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp9
-rw-r--r--test/CXX/dcl.decl/dcl.meaning/p1-0x.cpp21
-rw-r--r--test/CXX/drs/dr0xx.cpp9
-rw-r--r--test/CXX/drs/dr10xx.cpp5
-rw-r--r--test/CXX/drs/dr12xx.cpp15
-rw-r--r--test/CXX/drs/dr14xx.cpp2
-rw-r--r--test/CXX/drs/dr15xx.cpp31
-rw-r--r--test/CXX/drs/dr16xx.cpp148
-rw-r--r--test/CXX/drs/dr18xx.cpp48
-rw-r--r--test/CXX/drs/dr1xx.cpp44
-rw-r--r--test/CXX/drs/dr21xx.cpp16
-rw-r--r--test/CXX/drs/dr22xx.cpp17
-rw-r--r--test/CXX/drs/dr3xx.cpp102
-rw-r--r--test/CXX/drs/dr4xx.cpp25
-rw-r--r--test/CXX/drs/dr5xx.cpp2
-rw-r--r--test/CXX/drs/dr6xx.cpp680
-rw-r--r--test/CXX/drs/dr7xx.cpp76
-rw-r--r--test/CXX/except/except.spec/p3.cpp10
-rw-r--r--test/CXX/expr/expr.post/expr.reinterpret.cast/p2.cpp26
-rw-r--r--test/CXX/expr/expr.prim/expr.prim.lambda/p2-template-parameter.cpp7
-rw-r--r--test/CXX/expr/expr.prim/expr.prim.lambda/p3.cpp12
-rw-r--r--test/CXX/modules-ts/basic/basic.def.odr/p4/module.cpp16
-rw-r--r--test/CXX/modules-ts/basic/basic.def.odr/p4/module.cppm42
-rw-r--r--test/CXX/modules-ts/basic/basic.def.odr/p4/user.cpp8
-rw-r--r--test/CXX/over/over.built/p15.cpp44
-rw-r--r--test/CXX/over/over.match/over.match.funcs/p4-0x.cpp38
-rw-r--r--test/CXX/special/class.copy/p11.0x.copy.cpp12
-rw-r--r--test/CXX/special/class.copy/p11.0x.move.cpp2
-rw-r--r--test/CXX/special/class.ctor/p5-0x.cpp6
-rw-r--r--test/CXX/special/class.inhctor/p1.cpp4
-rw-r--r--test/CXX/special/class.init/class.inhctor.init/p1.cpp2
-rw-r--r--test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp2
-rw-r--r--test/CXX/stmt.stmt/stmt.select/p3.cpp60
-rw-r--r--test/CXX/temp/temp.decls/temp.friend/p1.cpp28
-rw-r--r--test/CXX/temp/temp.deduct.guide/p1.cpp2
-rw-r--r--test/CXX/temp/temp.deduct.guide/p3.cpp4
-rw-r--r--test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp85
-rw-r--r--test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p1.cpp10
-rw-r--r--test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p5-0x.cpp18
-rw-r--r--test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp38
-rw-r--r--test/CXX/temp/temp.param/p2.cpp28
-rw-r--r--test/CXX/temp/temp.param/p5.cpp12
-rw-r--r--test/CXX/temp/temp.res/p3.cpp2
-rw-r--r--test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp8
-rw-r--r--test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp31
-rw-r--r--test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp48
-rw-r--r--test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp8
-rw-r--r--test/CodeCompletion/Inputs/comments.h4
-rw-r--r--test/CodeCompletion/comments.cpp13
-rw-r--r--test/CodeCompletion/crash-skipped-bodies-template-inst.cpp27
-rw-r--r--test/CodeCompletion/ctor-initializer.cpp4
-rw-r--r--test/CodeCompletion/enable-if-attr-crash.cpp8
-rw-r--r--test/CodeCompletion/end-of-file.cpp7
-rw-r--r--test/CodeCompletion/end-of-ident-macro.cpp16
-rw-r--r--test/CodeCompletion/end-of-ident.cpp20
-rw-r--r--test/CodeCompletion/incomplete-ret-type.cpp13
-rw-r--r--test/CodeCompletion/inside-macros.cpp13
-rw-r--r--test/CodeCompletion/macros.c8
-rw-r--r--test/CodeCompletion/member-access.cpp70
-rw-r--r--test/CodeCompletion/namespace.cpp4
-rw-r--r--test/CodeCompletion/operator.cpp4
-rw-r--r--test/CodeCompletion/skip-auto-funcs.cpp61
-rw-r--r--test/CodeCompletion/tag.c4
-rw-r--r--test/CodeCompletion/tag.cpp4
-rw-r--r--test/CodeCompletion/using-namespace.cpp4
-rw-r--r--test/CodeCompletion/using.cpp4
-rw-r--r--test/CodeGen/2004-03-07-ExternalConstant.c2
-rw-r--r--test/CodeGen/2007-06-18-SextAttrAggregate.c2
-rw-r--r--test/CodeGen/2007-11-07-CopyAggregateAlign.c2
-rw-r--r--test/CodeGen/2007-11-07-ZeroAggregateAlign.c2
-rw-r--r--test/CodeGen/2008-07-21-mixed-var-fn-decl.c4
-rw-r--r--test/CodeGen/64bit-swiftcall.c33
-rw-r--r--test/CodeGen/Atomics.c7
-rw-r--r--test/CodeGen/Inputs/debug-info-embed-source.c1
-rw-r--r--test/CodeGen/Inputs/thinlto-distributed-backend-skip.bcbin0 -> 124 bytes
-rw-r--r--test/CodeGen/aarch64-inline-asm.c26
-rw-r--r--test/CodeGen/aarch64-neon-2velem.c23
-rw-r--r--test/CodeGen/aarch64-neon-dot-product.c117
-rw-r--r--test/CodeGen/aarch64-neon-intrinsics.c3708
-rw-r--r--test/CodeGen/aarch64-neon-ldst-one.c1714
-rw-r--r--test/CodeGen/aarch64-neon-misc.c112
-rw-r--r--test/CodeGen/aarch64-neon-perm.c324
-rw-r--r--test/CodeGen/aarch64-poly64.c24
-rw-r--r--test/CodeGen/aarch64-v8.2a-fp16-intrinsics.c659
-rw-r--r--test/CodeGen/aarch64-v8.2a-neon-intrinsics.c63
-rw-r--r--test/CodeGen/aarch64-varargs-ms.c2
-rw-r--r--test/CodeGen/address-safety-attr-flavors.cpp75
-rw-r--r--test/CodeGen/address-safety-attr-kasan-hwasan.cpp53
-rw-r--r--test/CodeGen/address-safety-attr-kasan.cpp38
-rw-r--r--test/CodeGen/address-sanitizer-and-array-cookie.cpp9
-rw-r--r--test/CodeGen/address-space.c17
-rw-r--r--test/CodeGen/addrsig.c20
-rw-r--r--test/CodeGen/adx-builtins.c2
-rw-r--r--test/CodeGen/aggregate-assign-call.c93
-rw-r--r--test/CodeGen/alias.c6
-rw-r--r--test/CodeGen/arm-aapcs-vfp.c4
-rw-r--r--test/CodeGen/arm-arguments.c4
-rw-r--r--test/CodeGen/arm-build-attributes.c4
-rw-r--r--test/CodeGen/arm-fp16-arguments.c24
-rw-r--r--test/CodeGen/arm-long-calls.c4
-rw-r--r--test/CodeGen/arm-neon-directed-rounding.c115
-rw-r--r--test/CodeGen/arm-neon-dot-product.c76
-rw-r--r--test/CodeGen/arm-neon-fma.c24
-rw-r--r--test/CodeGen/arm-neon-vld.c2498
-rw-r--r--test/CodeGen/arm-neon-vst.c2312
-rw-r--r--test/CodeGen/arm-no-movt.c4
-rw-r--r--test/CodeGen/arm-swiftcall.c10
-rw-r--r--test/CodeGen/arm-target-features.c74
-rw-r--r--test/CodeGen/arm-thumb-mode-target-feature.c8
-rw-r--r--test/CodeGen/arm-v8.2a-neon-intrinsics.c989
-rw-r--r--test/CodeGen/arm64-be-bitfield.c2
-rw-r--r--test/CodeGen/arm64-microsoft-arguments.cpp25
-rw-r--r--test/CodeGen/arm64-microsoft-intrinsics.c35
-rw-r--r--test/CodeGen/arm64-vrnd.c29
-rw-r--r--test/CodeGen/arm64_vdup.c2
-rw-r--r--test/CodeGen/arm_neon_intrinsics.c1299
-rw-r--r--test/CodeGen/array-init.c15
-rw-r--r--test/CodeGen/artificial.c10
-rw-r--r--test/CodeGen/asm-parser-info.S12
-rw-r--r--test/CodeGen/atomic-arm64.c2
-rw-r--r--test/CodeGen/atomic-ops.c16
-rw-r--r--test/CodeGen/atomics-sema-alignment.c27
-rw-r--r--test/CodeGen/attr-cpuspecific.c101
-rw-r--r--test/CodeGen/attr-target-mv-func-ptrs.c32
-rw-r--r--test/CodeGen/attr-target-mv-va-args.c26
-rw-r--r--test/CodeGen/attr-target-mv.c91
-rw-r--r--test/CodeGen/attr-target-x86.c16
-rw-r--r--test/CodeGen/attr-x86-interrupt.c8
-rw-r--r--test/CodeGen/attributes.c14
-rw-r--r--test/CodeGen/avx-builtins.c938
-rw-r--r--test/CodeGen/avx-cmp-builtins.c24
-rw-r--r--test/CodeGen/avx-shuffle-builtins.c16
-rw-r--r--test/CodeGen/avx2-builtins.c52
-rw-r--r--test/CodeGen/avx512-reduceIntrin.c618
-rw-r--r--test/CodeGen/avx512-reduceMinMaxIntrin.c4902
-rw-r--r--test/CodeGen/avx512bw-builtins.c136
-rw-r--r--test/CodeGen/avx512dq-builtins.c80
-rw-r--r--test/CodeGen/avx512f-builtins.c3024
-rw-r--r--test/CodeGen/avx512ifma-builtins.c16
-rw-r--r--test/CodeGen/avx512ifmavl-builtins.c32
-rw-r--r--test/CodeGen/avx512vbmi-builtins.c19
-rw-r--r--test/CodeGen/avx512vbmi2-builtins.c60
-rw-r--r--test/CodeGen/avx512vbmivl-builtin.c38
-rw-r--r--test/CodeGen/avx512vl-builtins.c2703
-rw-r--r--test/CodeGen/avx512vlbitalg-builtins.c60
-rw-r--r--test/CodeGen/avx512vlbw-builtins.c221
-rw-r--r--test/CodeGen/avx512vldq-builtins.c93
-rw-r--r--test/CodeGen/avx512vlvbmi2-builtins.c420
-rw-r--r--test/CodeGen/avx512vlvnni-builtins.c136
-rw-r--r--test/CodeGen/avx512vnni-builtins.c32
-rw-r--r--test/CodeGen/backend-unsupported-error.ll8
-rw-r--r--test/CodeGen/bitscan-builtins.c2
-rw-r--r--test/CodeGen/bittest-intrin.c135
-rw-r--r--test/CodeGen/block-byref-aggr.c6
-rw-r--r--test/CodeGen/blocks-windows.c4
-rw-r--r--test/CodeGen/bmi-builtins.c2
-rw-r--r--test/CodeGen/bmi2-builtins.c2
-rw-r--r--test/CodeGen/builtin-abs.c29
-rw-r--r--test/CodeGen/builtin-clflushopt.c2
-rw-r--r--test/CodeGen/builtin-clwb.c2
-rw-r--r--test/CodeGen/builtin-memfns.c10
-rw-r--r--test/CodeGen/builtin-movdir.c36
-rw-r--r--test/CodeGen/builtin-wbinvd.c10
-rw-r--r--test/CodeGen/builtin-wbnoinvd.c9
-rw-r--r--test/CodeGen/builtins-arm.c60
-rw-r--r--test/CodeGen/builtins-hexagon-circ.c156
-rw-r--r--test/CodeGen/builtins-hexagon.c1616
-rw-r--r--test/CodeGen/builtins-hvx128.c802
-rw-r--r--test/CodeGen/builtins-hvx64.c802
-rw-r--r--test/CodeGen/builtins-mips-args.c28
-rw-r--r--test/CodeGen/builtins-ms.c4
-rw-r--r--test/CodeGen/builtins-nvptx-ptx50.cu2
-rw-r--r--test/CodeGen/builtins-nvptx-sm_70.cu489
-rw-r--r--test/CodeGen/builtins-nvptx.c139
-rw-r--r--test/CodeGen/builtins-overflow.c26
-rw-r--r--test/CodeGen/builtins-ppc-p9-f128.c50
-rw-r--r--test/CodeGen/builtins-ppc-p9vector.c2
-rw-r--r--test/CodeGen/builtins-ppc-vsx.c22
-rw-r--r--test/CodeGen/builtins-systemz-vector-error.c140
-rw-r--r--test/CodeGen/builtins-systemz-vector2-error.c32
-rw-r--r--test/CodeGen/builtins-systemz-zvector-error.c4
-rw-r--r--test/CodeGen/builtins-systemz-zvector2-error.c4
-rw-r--r--test/CodeGen/builtins-wasm.c32
-rw-r--r--test/CodeGen/builtins-x86.c10
-rw-r--r--test/CodeGen/builtins.c22
-rw-r--r--test/CodeGen/c-strings.c12
-rw-r--r--test/CodeGen/c11atomics-ios.c46
-rw-r--r--test/CodeGen/c11atomics.c46
-rw-r--r--test/CodeGen/cetintrin.c33
-rw-r--r--test/CodeGen/cfi-check-fail2.c6
-rw-r--r--test/CodeGen/cfi-icall-cross-dso.c14
-rw-r--r--test/CodeGen/cfi-icall.c6
-rw-r--r--test/CodeGen/cfstring-windows.c4
-rw-r--r--test/CodeGen/clang-sections-attribute.c76
-rw-r--r--test/CodeGen/cldemote.c10
-rw-r--r--test/CodeGen/code-coverage.c33
-rw-r--r--test/CodeGen/compound-literal.c4
-rw-r--r--test/CodeGen/constructor-attribute.c56
-rw-r--r--test/CodeGen/debug-info-block-out-return.c2
-rw-r--r--test/CodeGen/debug-info-cc.c120
-rw-r--r--test/CodeGen/debug-info-codeview-unnamed.c30
-rw-r--r--test/CodeGen/debug-info-embed-source.c5
-rw-r--r--test/CodeGen/debug-info-enum.cpp100
-rw-r--r--test/CodeGen/debug-info-file-checksum.c1
-rw-r--r--test/CodeGen/debug-info-inline-for.c13
-rw-r--r--test/CodeGen/debug-info-vla.c8
-rw-r--r--test/CodeGen/decl.c8
-rw-r--r--test/CodeGen/default-address-space.c19
-rw-r--r--test/CodeGen/delete-null-pointer-checks.c20
-rw-r--r--test/CodeGen/dllexport.c48
-rw-r--r--test/CodeGen/dllimport.c26
-rw-r--r--test/CodeGen/dso-local-executable.c112
-rw-r--r--test/CodeGen/dump-struct-builtin.c555
-rw-r--r--test/CodeGen/elf-linker-options.c7
-rw-r--r--test/CodeGen/emit-summary-index.c17
-rw-r--r--test/CodeGen/exceptions-seh-finally.c94
-rw-r--r--test/CodeGen/exceptions-seh-leave.c48
-rw-r--r--test/CodeGen/exceptions-seh.c44
-rw-r--r--test/CodeGen/ext-vector.c4
-rw-r--r--test/CodeGen/f16c-builtins.c2
-rw-r--r--test/CodeGen/fentry.c11
-rw-r--r--test/CodeGen/fixup-depth-overflow.c2
-rw-r--r--test/CodeGen/flip-dllimport.c7
-rw-r--r--test/CodeGen/fma-builtins.c116
-rw-r--r--test/CodeGen/fma4-builtins.c116
-rw-r--r--test/CodeGen/fsgsbase-builtins.c2
-rw-r--r--test/CodeGen/function-alignment.c16
-rw-r--r--test/CodeGen/function-attributes.c4
-rw-r--r--test/CodeGen/function-min-vector-width.c7
-rw-r--r--test/CodeGen/gfni-builtins.c12
-rw-r--r--test/CodeGen/hexagon-brev-ld-ptr-incdec.c52
-rw-r--r--test/CodeGen/hexagon-brev-store-elm.c46
-rw-r--r--test/CodeGen/hexagon-check-builtins.c30
-rw-r--r--test/CodeGen/init.c156
-rw-r--r--test/CodeGen/inline.c12
-rw-r--r--test/CodeGen/invpcid.c12
-rw-r--r--test/CodeGen/kr-func-promote.c8
-rw-r--r--test/CodeGen/le32-vaarg.c2
-rw-r--r--test/CodeGen/libcalls-fno-builtin.c133
-rw-r--r--test/CodeGen/lto-newpm-pipeline.c1
-rw-r--r--test/CodeGen/lzcnt-builtins.c2
-rw-r--r--test/CodeGen/mangle-ms-string-literals.c10
-rw-r--r--test/CodeGen/mangle-ms.c8
-rw-r--r--test/CodeGen/mangle-windows-rtd.c6
-rw-r--r--test/CodeGen/mangle-windows.c64
-rw-r--r--test/CodeGen/math-builtins.c54
-rw-r--r--test/CodeGen/may-alias.c69
-rw-r--r--test/CodeGen/mbackchain-2.c2
-rw-r--r--test/CodeGen/mbackchain-3.c2
-rw-r--r--test/CodeGen/mcount.c22
-rw-r--r--test/CodeGen/microsoft-call-conv-x64.c4
-rw-r--r--test/CodeGen/mingw-long-double.c36
-rw-r--r--test/CodeGen/mips-vector-return.c6
-rw-r--r--test/CodeGen/mms-bitfields.c43
-rw-r--r--test/CodeGen/mmx-builtins.c2
-rw-r--r--test/CodeGen/ms-align-tentative.c12
-rw-r--r--test/CodeGen/ms-annotation.c2
-rw-r--r--test/CodeGen/ms-barriers-intrinsics.c8
-rw-r--r--test/CodeGen/ms-declspecs.c14
-rw-r--r--test/CodeGen/ms-declspecs.cpp10
-rw-r--r--test/CodeGen/ms-inline-asm-align.c2
-rw-r--r--test/CodeGen/ms-inline-asm-avx512.c2
-rw-r--r--test/CodeGen/ms-inline-asm.c7
-rw-r--r--test/CodeGen/ms-intrinsics-other.c11
-rw-r--r--test/CodeGen/ms-intrinsics-rotations.c132
-rw-r--r--test/CodeGen/ms-intrinsics.c155
-rw-r--r--test/CodeGen/ms-setjmp.c18
-rw-r--r--test/CodeGen/ms-volatile-aarch64.c13
-rw-r--r--test/CodeGen/ms-x86-intrinsics.c28
-rw-r--r--test/CodeGen/ms_abi.c25
-rw-r--r--test/CodeGen/ms_abi_aarch64.c10
-rw-r--r--test/CodeGen/ms_struct-long-double.c17
-rw-r--r--test/CodeGen/ms_this.cpp6
-rw-r--r--test/CodeGen/no-bitfield-type-align.c44
-rw-r--r--test/CodeGen/no-common.c12
-rw-r--r--test/CodeGen/no-ident-version.c23
-rw-r--r--test/CodeGen/no-junk-ftrunc.c18
-rw-r--r--test/CodeGen/no-opt-volatile-memcpy.c10
-rw-r--r--test/CodeGen/no-prototype.c20
-rw-r--r--test/CodeGen/nonnull.c30
-rw-r--r--test/CodeGen/noplt.c3
-rw-r--r--test/CodeGen/opt-record-MIR.c5
-rw-r--r--test/CodeGen/overloadable.c6
-rw-r--r--test/CodeGen/packed-nest-unpacked.c10
-rw-r--r--test/CodeGen/packed-structure.c6
-rw-r--r--test/CodeGen/partial-reinitialization2.c16
-rw-r--r--test/CodeGen/pch-dllexport.cpp84
-rw-r--r--test/CodeGen/personality.c43
-rw-r--r--test/CodeGen/pgo-sample-thinlto-summary.c12
-rw-r--r--test/CodeGen/popcnt-builtins.c2
-rw-r--r--test/CodeGen/ppc-varargs-struct.c2
-rw-r--r--test/CodeGen/ppc64-align-struct.c42
-rw-r--r--test/CodeGen/ppc64-soft-float.c10
-rw-r--r--test/CodeGen/ppc64le-aggregates.c2
-rw-r--r--test/CodeGen/ppc64le-f128Aggregates.c124
-rw-r--r--test/CodeGen/pr19841.cpp2
-rw-r--r--test/CodeGen/pr3518.c2
-rw-r--r--test/CodeGen/pr4349.c8
-rw-r--r--test/CodeGen/pragma-comment.c7
-rw-r--r--test/CodeGen/pragma-do-while.cpp36
-rw-r--r--test/CodeGen/preserve-call-conv.c5
-rw-r--r--test/CodeGen/ptwrite.c22
-rw-r--r--test/CodeGen/rdpid-builtins.c10
-rw-r--r--test/CodeGen/rdrand-builtins.c2
-rw-r--r--test/CodeGen/regcall.c60
-rw-r--r--test/CodeGen/riscv32-abi.c430
-rw-r--r--test/CodeGen/riscv64-abi.c422
-rw-r--r--test/CodeGen/shadowcallstack-attr.c16
-rw-r--r--test/CodeGen/sparc-vaarg.c2
-rw-r--r--test/CodeGen/sparcv8-inline-asm.c33
-rw-r--r--test/CodeGen/sparcv9-inline-asm.c32
-rw-r--r--test/CodeGen/spir-half-type.cpp146
-rw-r--r--test/CodeGen/split-debug-filename.c7
-rw-r--r--test/CodeGen/split-stacks.c10
-rw-r--r--test/CodeGen/sse-builtins.c35
-rw-r--r--test/CodeGen/sse2-builtins.c50
-rw-r--r--test/CodeGen/sse3-builtins.c2
-rw-r--r--test/CodeGen/sse41-builtins.c28
-rw-r--r--test/CodeGen/sse42-builtins.c2
-rw-r--r--test/CodeGen/ssse3-builtins.c2
-rw-r--r--test/CodeGen/stack-arg-probe.c8
-rw-r--r--test/CodeGen/stack-protector.c20
-rw-r--r--test/CodeGen/stack-size-section.c9
-rw-r--r--test/CodeGen/string-literal-short-wstring.c4
-rw-r--r--test/CodeGen/target-data.c8
-rw-r--r--test/CodeGen/target-features-error-2.c38
-rw-r--r--test/CodeGen/target-features-error.c3
-rw-r--r--test/CodeGen/tbaa-base.cpp58
-rw-r--r--test/CodeGen/tbaa-cast.cpp13
-rw-r--r--test/CodeGen/tbaa-class.cpp67
-rw-r--r--test/CodeGen/tbaa-for-vptr.cpp16
-rw-r--r--test/CodeGen/tbaa-ms-abi.cpp15
-rw-r--r--test/CodeGen/tbaa-reference.cpp20
-rw-r--r--test/CodeGen/tbaa-struct.cpp138
-rw-r--r--test/CodeGen/tentative-decls.c14
-rw-r--r--test/CodeGen/thinlto-backend-option.ll6
-rw-r--r--test/CodeGen/thinlto-diagnostic-handler-remarks-with-hotness.ll49
-rw-r--r--test/CodeGen/thinlto-distributed-backend-skip.ll21
-rw-r--r--test/CodeGen/thinlto-distributed-cfi-devirt.ll109
-rw-r--r--test/CodeGen/thinlto-distributed-cfi.ll74
-rw-r--r--test/CodeGen/thinlto-distributed.ll21
-rw-r--r--test/CodeGen/thinlto-split-dwarf.c21
-rw-r--r--test/CodeGen/thinlto_backend.ll21
-rw-r--r--test/CodeGen/transparent-union-redecl.c44
-rw-r--r--test/CodeGen/vaes-builtins.c4
-rw-r--r--test/CodeGen/variadic-null-win64.c2
-rw-r--r--test/CodeGen/vector-scalar.c42
-rw-r--r--test/CodeGen/vector.c6
-rw-r--r--test/CodeGen/vectorcall.c80
-rw-r--r--test/CodeGen/vla.c6
-rw-r--r--test/CodeGen/vld_dup.c50
-rw-r--r--test/CodeGen/volatile-1.c6
-rw-r--r--test/CodeGen/volatile.c4
-rw-r--r--test/CodeGen/vpclmulqdq-builtins.c4
-rw-r--r--test/CodeGen/waitpkg.c25
-rw-r--r--test/CodeGen/wasm-arguments.c4
-rw-r--r--test/CodeGen/wasm-varargs.c10
-rw-r--r--test/CodeGen/wchar-const.c2
-rw-r--r--test/CodeGen/windows-itanium.c4
-rw-r--r--test/CodeGen/windows-on-arm-dllimport-dllexport.c4
-rw-r--r--test/CodeGen/windows-struct-abi.c12
-rw-r--r--test/CodeGen/windows-swiftcall.c62
-rw-r--r--test/CodeGen/wmemcmp.c37
-rw-r--r--test/CodeGen/x86-atomic-long_double.c56
-rw-r--r--test/CodeGen/x86-builtins-vector-width.c32
-rw-r--r--test/CodeGen/x86-cf-protection.c8
-rw-r--r--test/CodeGen/x86-nontemporal.c2
-rw-r--r--test/CodeGen/x86_32-arguments-realign.c2
-rw-r--r--test/CodeGen/x86_32-arguments-win32.c18
-rw-r--r--test/CodeGen/x86_32-fpcc-struct-return.c8
-rw-r--r--test/CodeGen/x86_64-arguments-win32.c16
-rw-r--r--test/CodeGen/x86_64-arguments.c2
-rw-r--r--test/CodeGen/x86_64-floatvectors.c131
-rw-r--r--test/CodeGen/xcore-abi.c4
-rw-r--r--test/CodeGen/xray-always-emit-typedevent.cpp10
-rw-r--r--test/CodeGen/xray-always-instrument.cpp10
-rw-r--r--test/CodeGen/xray-attr-list.cpp19
-rw-r--r--test/CodeGen/xray-imbue-arg1.cpp9
-rw-r--r--test/CodeGen/xray-instrumentation-bundles.cpp50
-rw-r--r--test/CodeGen/xray-never-instrument.cpp24
-rw-r--r--test/CodeGen/xray-typedevent.cpp34
-rw-r--r--test/CodeGenCUDA/Inputs/cuda.h5
-rw-r--r--test/CodeGenCUDA/address-spaces.cu19
-rw-r--r--test/CodeGenCUDA/alias.cu3
-rw-r--r--test/CodeGenCUDA/amdgpu-kernel-attrs.cu37
-rw-r--r--test/CodeGenCUDA/convergent.cu4
-rw-r--r--test/CodeGenCUDA/device-stub.cu177
-rw-r--r--test/CodeGenCUDA/device-var-init.cu110
-rw-r--r--test/CodeGenCUDA/device-vtable.cu11
-rw-r--r--test/CodeGenCUDA/filter-decl.cu8
-rw-r--r--test/CodeGenCUDA/flush-denormals.cu15
-rw-r--r--test/CodeGenCUDA/kernel-amdgcn.cu41
-rw-r--r--test/CodeGenCUDA/kernel-args.cu39
-rw-r--r--test/CodeGenCUDA/kernel-call.cu13
-rw-r--r--test/CodeGenCUDA/library-builtin.cu22
-rw-r--r--test/CodeGenCUDA/link-device-bitcode.cu2
-rw-r--r--test/CodeGenCUDA/propagate-metadata.cu2
-rw-r--r--test/CodeGenCXX/Inputs/override-bit-field-layout.layout16
-rw-r--r--test/CodeGenCXX/Inputs/std-compare.h437
-rw-r--r--test/CodeGenCXX/PR19955.cpp24
-rw-r--r--test/CodeGenCXX/PR26569.cpp14
-rw-r--r--test/CodeGenCXX/PR28220.cpp2
-rw-r--r--test/CodeGenCXX/PR37481.cpp17
-rw-r--r--test/CodeGenCXX/abstract-class-ctors-dtors.cpp2
-rw-r--r--test/CodeGenCXX/address-space-cast.cpp15
-rw-r--r--test/CodeGenCXX/address-space-ref.cpp6
-rw-r--r--test/CodeGenCXX/alignment.cpp48
-rw-r--r--test/CodeGenCXX/alloc-size.cpp34
-rw-r--r--test/CodeGenCXX/amdgcn-func-arg.cpp94
-rw-r--r--test/CodeGenCXX/amdgcn-string-literal.cpp28
-rw-r--r--test/CodeGenCXX/amdgcn_declspec_get.cpp27
-rw-r--r--test/CodeGenCXX/apple-kext-guard-variable.cpp2
-rw-r--r--test/CodeGenCXX/arm-swiftcall.cpp10
-rw-r--r--test/CodeGenCXX/array-default-argument.cpp2
-rw-r--r--test/CodeGenCXX/assign-construct-memcpy.cpp30
-rw-r--r--test/CodeGenCXX/atomic-dllexport.cpp4
-rw-r--r--test/CodeGenCXX/atomic-inline.cpp61
-rw-r--r--test/CodeGenCXX/attr-target-mv-diff-ns.cpp54
-rw-r--r--test/CodeGenCXX/attr-target-mv-func-ptrs.cpp45
-rw-r--r--test/CodeGenCXX/attr-target-mv-member-funcs.cpp137
-rw-r--r--test/CodeGenCXX/attr-target-mv-modules.cpp29
-rw-r--r--test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp39
-rw-r--r--test/CodeGenCXX/attr-target-mv-overloads.cpp50
-rw-r--r--test/CodeGenCXX/attr-x86-interrupt.cpp12
-rw-r--r--test/CodeGenCXX/block-capture.cpp13
-rw-r--r--test/CodeGenCXX/block-inalloca.cpp11
-rw-r--r--test/CodeGenCXX/builtin-operator-new-delete.cpp71
-rw-r--r--test/CodeGenCXX/builtins.cpp16
-rw-r--r--test/CodeGenCXX/captured-statements.cpp2
-rw-r--r--test/CodeGenCXX/catch-undef-behavior.cpp6
-rw-r--r--test/CodeGenCXX/cfi-cross-dso.cpp2
-rw-r--r--test/CodeGenCXX/cfi-icall.cpp2
-rw-r--r--test/CodeGenCXX/cfi-mfcall-incomplete.cpp12
-rw-r--r--test/CodeGenCXX/cfi-mfcall.cpp30
-rw-r--r--test/CodeGenCXX/cfi-ms-vbase-derived-cast.cpp2
-rw-r--r--test/CodeGenCXX/cfi-ms-vbase-nvcall.cpp2
-rw-r--r--test/CodeGenCXX/cfi-vcall-check-after-args.cpp12
-rw-r--r--test/CodeGenCXX/char8_t.cpp9
-rw-r--r--test/CodeGenCXX/code-seg.cpp139
-rw-r--r--test/CodeGenCXX/code-seg1.cpp87
-rw-r--r--test/CodeGenCXX/code-seg2.cpp111
-rw-r--r--test/CodeGenCXX/code-seg3.cpp65
-rw-r--r--test/CodeGenCXX/conditional-temporaries.cpp2
-rw-r--r--test/CodeGenCXX/const-base-cast.cpp2
-rw-r--r--test/CodeGenCXX/const-global-linkage.cpp4
-rw-r--r--test/CodeGenCXX/const-init-cxx11.cpp2
-rw-r--r--test/CodeGenCXX/constructor-alias.cpp2
-rw-r--r--test/CodeGenCXX/constructor-destructor-return-this.cpp12
-rw-r--r--test/CodeGenCXX/constructor-direct-call.cpp4
-rw-r--r--test/CodeGenCXX/constructors.cpp15
-rw-r--r--test/CodeGenCXX/copy-constructor-elim.cpp2
-rw-r--r--test/CodeGenCXX/copy-constructor-synthesis-2.cpp6
-rw-r--r--test/CodeGenCXX/copy-constructor-synthesis.cpp4
-rw-r--r--test/CodeGenCXX/ctor-dtor-alias.cpp55
-rw-r--r--test/CodeGenCXX/cxx0x-delegating-ctors.cpp2
-rw-r--r--test/CodeGenCXX/cxx0x-initializer-array.cpp2
-rw-r--r--test/CodeGenCXX/cxx0x-initializer-references.cpp2
-rw-r--r--test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp90
-rw-r--r--test/CodeGenCXX/cxx11-initializer-aggregate.cpp68
-rw-r--r--test/CodeGenCXX/cxx11-initializer-array-new.cpp2
-rw-r--r--test/CodeGenCXX/cxx11-thread-local.cpp12
-rw-r--r--test/CodeGenCXX/cxx1z-aligned-allocation.cpp14
-rw-r--r--test/CodeGenCXX/cxx1z-eval-order.cpp6
-rw-r--r--test/CodeGenCXX/cxx1z-initializer-aggregate.cpp18
-rw-r--r--test/CodeGenCXX/cxx1z-inline-variables.cpp34
-rw-r--r--test/CodeGenCXX/cxx1z-lambda-star-this.cpp6
-rw-r--r--test/CodeGenCXX/cxx2a-compare.cpp188
-rw-r--r--test/CodeGenCXX/cxx2a-destroying-delete.cpp24
-rw-r--r--test/CodeGenCXX/debug-info-access.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-class-nolimit.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-codeview-unnamed.cpp108
-rw-r--r--test/CodeGenCXX/debug-info-codeview-var-templates.cpp35
-rw-r--r--test/CodeGenCXX/debug-info-composite-cc.cpp50
-rw-r--r--test/CodeGenCXX/debug-info-enum-class.cpp6
-rw-r--r--test/CodeGenCXX/debug-info-enum.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-line-if.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-ms-dtor-thunks.cpp12
-rw-r--r--test/CodeGenCXX/debug-info-ms-vbase.cpp8
-rw-r--r--test/CodeGenCXX/debug-info-range-for-var-names.cpp35
-rw-r--r--test/CodeGenCXX/debug-info-scope.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-static-member.cpp6
-rw-r--r--test/CodeGenCXX/debug-info-template.cpp6
-rw-r--r--test/CodeGenCXX/debug-info-thunk-msabi.cpp4
-rw-r--r--test/CodeGenCXX/debug-info-thunk.cpp302
-rw-r--r--test/CodeGenCXX/debug-info-vla.cpp6
-rw-r--r--test/CodeGenCXX/debug-info-windows-dtor.cpp4
-rw-r--r--test/CodeGenCXX/delayed-template-parsing.cpp4
-rw-r--r--test/CodeGenCXX/derived-cast.cpp27
-rw-r--r--test/CodeGenCXX/destructors.cpp12
-rw-r--r--test/CodeGenCXX/devirtualize-ms-dtor.cpp16
-rw-r--r--test/CodeGenCXX/discard-name-values.cpp33
-rw-r--r--test/CodeGenCXX/dllexport-alias.cpp4
-rw-r--r--test/CodeGenCXX/dllexport-ctor-closure.cpp30
-rw-r--r--test/CodeGenCXX/dllexport-dtor-thunks.cpp4
-rw-r--r--test/CodeGenCXX/dllexport-members.cpp660
-rw-r--r--test/CodeGenCXX/dllexport-ms-friend.cpp2
-rw-r--r--test/CodeGenCXX/dllexport-pr26549.cpp2
-rw-r--r--test/CodeGenCXX/dllexport-vtable-thunks.cpp4
-rw-r--r--test/CodeGenCXX/dllexport.cpp572
-rw-r--r--test/CodeGenCXX/dllimport-dtor-thunks.cpp20
-rw-r--r--test/CodeGenCXX/dllimport-members.cpp684
-rw-r--r--test/CodeGenCXX/dllimport-memptr-global.cpp24
-rw-r--r--test/CodeGenCXX/dllimport-missing-key.cpp20
-rw-r--r--test/CodeGenCXX/dllimport-rtti.cpp22
-rw-r--r--test/CodeGenCXX/dllimport-template-sdm.cpp53
-rw-r--r--test/CodeGenCXX/dllimport.cpp424
-rw-r--r--test/CodeGenCXX/dso-local-executable.cpp62
-rw-r--r--test/CodeGenCXX/duplicate-mangled-name.cpp10
-rw-r--r--test/CodeGenCXX/eh.cpp8
-rw-r--r--test/CodeGenCXX/exceptions-cxx-ehsc.cpp8
-rw-r--r--test/CodeGenCXX/exceptions-cxx-new.cpp26
-rw-r--r--test/CodeGenCXX/exceptions-seh-filter-captures.cpp22
-rw-r--r--test/CodeGenCXX/exceptions-seh.cpp42
-rw-r--r--test/CodeGenCXX/explicit-instantiation.cpp4
-rw-r--r--test/CodeGenCXX/extern-c.cpp16
-rw-r--r--test/CodeGenCXX/finegrain-bitfield-type.cpp22
-rw-r--r--test/CodeGenCXX/float128-declarations.cpp4
-rw-r--r--test/CodeGenCXX/float16-declarations.cpp26
-rw-r--r--test/CodeGenCXX/funcsig.cpp14
-rw-r--r--test/CodeGenCXX/global-llvm-constant.cpp4
-rw-r--r--test/CodeGenCXX/hidden-dllimport.cpp10
-rw-r--r--test/CodeGenCXX/homogeneous-aggregates.cpp8
-rw-r--r--test/CodeGenCXX/inheriting-constructor.cpp176
-rw-r--r--test/CodeGenCXX/initializer-list-ctor-order.cpp4
-rw-r--r--test/CodeGenCXX/inline-dllexport-member.cpp4
-rw-r--r--test/CodeGenCXX/inline-functions.cpp36
-rw-r--r--test/CodeGenCXX/inline-hint.cpp6
-rw-r--r--test/CodeGenCXX/internal-linkage.cpp2
-rw-r--r--test/CodeGenCXX/invariant.group-for-vptrs.cpp2
-rw-r--r--test/CodeGenCXX/lambda-expressions-inside-auto-functions.cpp9
-rw-r--r--test/CodeGenCXX/lambda-to-function-pointer-conversion.cpp18
-rw-r--r--test/CodeGenCXX/linetable-eh.cpp2
-rw-r--r--test/CodeGenCXX/mangle-abi-tag.cpp4
-rw-r--r--test/CodeGenCXX/mangle-mingw.cpp19
-rw-r--r--test/CodeGenCXX/mangle-ms-abi-examples.cpp8
-rw-r--r--test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp252
-rw-r--r--test/CodeGenCXX/mangle-ms-back-references-pr13207.cpp66
-rw-r--r--test/CodeGenCXX/mangle-ms-back-references.cpp34
-rw-r--r--test/CodeGenCXX/mangle-ms-cxx11.cpp176
-rw-r--r--test/CodeGenCXX/mangle-ms-cxx14.cpp34
-rw-r--r--test/CodeGenCXX/mangle-ms-md5.cpp6
-rw-r--r--test/CodeGenCXX/mangle-ms-return-qualifiers.cpp118
-rw-r--r--test/CodeGenCXX/mangle-ms-string-literals.cpp746
-rw-r--r--test/CodeGenCXX/mangle-ms-template-callback.cpp36
-rw-r--r--test/CodeGenCXX/mangle-ms-templates-memptrs-2.cpp18
-rw-r--r--test/CodeGenCXX/mangle-ms-templates-memptrs.cpp60
-rw-r--r--test/CodeGenCXX/mangle-ms-templates.cpp156
-rw-r--r--test/CodeGenCXX/mangle-ms-vector-types.cpp81
-rw-r--r--test/CodeGenCXX/mangle-ms.cpp236
-rw-r--r--test/CodeGenCXX/mangle-windows.cpp28
-rw-r--r--test/CodeGenCXX/member-function-pointer-calls.cpp4
-rw-r--r--test/CodeGenCXX/microsoft-abi-arg-order.cpp44
-rw-r--r--test/CodeGenCXX/microsoft-abi-array-cookies.cpp18
-rw-r--r--test/CodeGenCXX/microsoft-abi-byval-sret.cpp16
-rw-r--r--test/CodeGenCXX/microsoft-abi-byval-thunks.cpp24
-rw-r--r--test/CodeGenCXX/microsoft-abi-byval-vararg.cpp16
-rw-r--r--test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp16
-rw-r--r--test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp4
-rw-r--r--test/CodeGenCXX/microsoft-abi-default-cc.cpp14
-rw-r--r--test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp36
-rw-r--r--test/CodeGenCXX/microsoft-abi-eh-catch.cpp26
-rw-r--r--test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp154
-rw-r--r--test/CodeGenCXX/microsoft-abi-eh-inlineasm.cpp18
-rw-r--r--test/CodeGenCXX/microsoft-abi-eh-terminate.cpp6
-rw-r--r--test/CodeGenCXX/microsoft-abi-emit-dependent.cpp11
-rw-r--r--test/CodeGenCXX/microsoft-abi-extern-template.cpp14
-rwxr-xr-xtest/CodeGenCXX/microsoft-abi-member-pointers.cpp282
-rw-r--r--test/CodeGenCXX/microsoft-abi-methods.cpp32
-rw-r--r--test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp55
-rw-r--r--test/CodeGenCXX/microsoft-abi-rtti.cpp476
-rw-r--r--test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp227
-rw-r--r--test/CodeGenCXX/microsoft-abi-static-initializers.cpp98
-rw-r--r--test/CodeGenCXX/microsoft-abi-structors-alias.cpp8
-rw-r--r--test/CodeGenCXX/microsoft-abi-structors-delayed-template.cpp2
-rw-r--r--test/CodeGenCXX/microsoft-abi-structors.cpp134
-rw-r--r--test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp56
-rw-r--r--test/CodeGenCXX/microsoft-abi-throw.cpp60
-rw-r--r--test/CodeGenCXX/microsoft-abi-thunks.cpp76
-rw-r--r--test/CodeGenCXX/microsoft-abi-try-throw.cpp12
-rw-r--r--test/CodeGenCXX/microsoft-abi-typeid.cpp26
-rw-r--r--test/CodeGenCXX/microsoft-abi-vbtables.cpp376
-rw-r--r--test/CodeGenCXX/microsoft-abi-vftables.cpp34
-rw-r--r--test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp15
-rw-r--r--test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp143
-rw-r--r--test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp48
-rw-r--r--test/CodeGenCXX/microsoft-abi-vmemptr-conflicts.cpp32
-rw-r--r--test/CodeGenCXX/microsoft-abi-vmemptr-fastcall.cpp2
-rw-r--r--test/CodeGenCXX/microsoft-abi-vmemptr-vbase.cpp2
-rw-r--r--test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-no-thunks.cpp22
-rw-r--r--test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-pure-virtual.cpp4
-rw-r--r--test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-return-adjustment.cpp2
-rw-r--r--test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp28
-rw-r--r--test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp60
-rw-r--r--test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp18
-rw-r--r--test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp70
-rw-r--r--test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp112
-rw-r--r--test/CodeGenCXX/microsoft-compatibility.cpp8
-rw-r--r--test/CodeGenCXX/microsoft-inaccessible-base.cpp4
-rw-r--r--test/CodeGenCXX/microsoft-interface.cpp14
-rw-r--r--test/CodeGenCXX/microsoft-new.cpp8
-rw-r--r--test/CodeGenCXX/microsoft-no-rtti-data.cpp6
-rw-r--r--test/CodeGenCXX/microsoft-templ-uuidof.cpp12
-rw-r--r--test/CodeGenCXX/microsoft-uuidof.cpp20
-rw-r--r--test/CodeGenCXX/mingw-new-abi.cpp4
-rw-r--r--test/CodeGenCXX/mingw-w64-seh-exceptions.cpp4
-rw-r--r--test/CodeGenCXX/ms-eh-personality.cpp20
-rw-r--r--test/CodeGenCXX/ms-inline-asm-return.cpp16
-rw-r--r--test/CodeGenCXX/ms-integer-static-data-members-exported.cpp4
-rw-r--r--test/CodeGenCXX/ms-integer-static-data-members.cpp14
-rw-r--r--test/CodeGenCXX/ms-novtable.cpp10
-rw-r--r--test/CodeGenCXX/ms-property.cpp48
-rw-r--r--test/CodeGenCXX/ms-thread_local.cpp10
-rw-r--r--test/CodeGenCXX/ms-thunks-unprototyped-return.cpp15
-rw-r--r--test/CodeGenCXX/ms-thunks-unprototyped.cpp73
-rw-r--r--test/CodeGenCXX/ms_wide_predefined_expr.cpp2
-rw-r--r--test/CodeGenCXX/msabi-blocks.cpp56
-rw-r--r--test/CodeGenCXX/msabi-swiftcall-cc.cpp67
-rw-r--r--test/CodeGenCXX/naked.cpp2
-rw-r--r--test/CodeGenCXX/new-array-init.cpp10
-rw-r--r--test/CodeGenCXX/no-opt-volatile-memcpy.cpp12
-rw-r--r--test/CodeGenCXX/optnone-pragma-optimize-off.cpp16
-rw-r--r--test/CodeGenCXX/override-bit-field-layout.cpp20
-rw-r--r--test/CodeGenCXX/personality.cpp42
-rw-r--r--test/CodeGenCXX/pod-member-memcpys.cpp68
-rw-r--r--test/CodeGenCXX/pr20719.cpp4
-rw-r--r--test/CodeGenCXX/pr20897.cpp8
-rw-r--r--test/CodeGenCXX/pr27030.cpp2
-rw-r--r--test/CodeGenCXX/pr28360.cpp6
-rw-r--r--test/CodeGenCXX/pr30731.cpp2
-rw-r--r--test/CodeGenCXX/pr33080.cpp18
-rw-r--r--test/CodeGenCXX/pragma-init_seg.cpp32
-rw-r--r--test/CodeGenCXX/pragma-weak.cpp2
-rw-r--r--test/CodeGenCXX/reference-init.cpp10
-rw-r--r--test/CodeGenCXX/regcall.cpp52
-rw-r--r--test/CodeGenCXX/rtti-fundamental.cpp71
-rw-r--r--test/CodeGenCXX/rtti-hidden.cpp10
-rw-r--r--test/CodeGenCXX/rtti-mingw64.cpp4
-rw-r--r--test/CodeGenCXX/runtime-dllstorage.cpp85
-rw-r--r--test/CodeGenCXX/sanitize-no-dtor-callback.cpp6
-rw-r--r--test/CodeGenCXX/sections.cpp44
-rw-r--r--test/CodeGenCXX/specialized-static-data-mem-init.cpp4
-rw-r--r--test/CodeGenCXX/split-stacks.cpp12
-rw-r--r--test/CodeGenCXX/stack-reuse-exceptions.cpp189
-rw-r--r--test/CodeGenCXX/stack-reuse-miscompile.cpp36
-rw-r--r--test/CodeGenCXX/strict-vtable-pointers.cpp353
-rw-r--r--test/CodeGenCXX/tail-padding.cpp34
-rw-r--r--test/CodeGenCXX/temporaries.cpp123
-rw-r--r--test/CodeGenCXX/trap-fnattr.cpp12
-rw-r--r--test/CodeGenCXX/trivial_abi.cpp239
-rw-r--r--test/CodeGenCXX/type-metadata-memfun.cpp31
-rw-r--r--test/CodeGenCXX/type-metadata.cpp71
-rw-r--r--test/CodeGenCXX/ubsan-ctor-srcloc.cpp26
-rw-r--r--test/CodeGenCXX/ubsan-devirtualized-calls.cpp10
-rw-r--r--test/CodeGenCXX/ubsan-function-noexcept.cpp15
-rw-r--r--test/CodeGenCXX/ubsan-vtable-checks.cpp10
-rw-r--r--test/CodeGenCXX/unaligned-member-qualifier.cpp8
-rw-r--r--test/CodeGenCXX/uncopyable-args.cpp46
-rw-r--r--test/CodeGenCXX/value-init.cpp24
-rw-r--r--test/CodeGenCXX/vararg-non-pod-ms-compat.cpp6
-rw-r--r--test/CodeGenCXX/varargs.cpp2
-rw-r--r--test/CodeGenCXX/virt-template-vtable.cpp8
-rw-r--r--test/CodeGenCXX/virtual-base-cast.cpp8
-rw-r--r--test/CodeGenCXX/virtual-base-ctor.cpp2
-rw-r--r--test/CodeGenCXX/virtual-bases.cpp36
-rw-r--r--test/CodeGenCXX/virtual-destructor-calls.cpp6
-rw-r--r--test/CodeGenCXX/virtual-function-attrs.cpp6
-rw-r--r--test/CodeGenCXX/virtual-function-calls.cpp2
-rw-r--r--test/CodeGenCXX/visibility-pr36810.cpp23
-rw-r--r--test/CodeGenCXX/vla-consruct.cpp4
-rw-r--r--test/CodeGenCXX/vla.cpp32
-rw-r--r--test/CodeGenCXX/volatile-1.cpp4
-rw-r--r--test/CodeGenCXX/vtable-assume-load.cpp4
-rw-r--r--test/CodeGenCXX/vtable-available-externally.cpp154
-rw-r--r--test/CodeGenCXX/vtable-key-function-ios.cpp56
-rw-r--r--test/CodeGenCXX/vtable-key-function-win-comdat.cpp6
-rw-r--r--test/CodeGenCXX/wasm-eh.cpp384
-rw-r--r--test/CodeGenCXX/weak-extern-typeinfo.cpp28
-rw-r--r--test/CodeGenCXX/windows-implicit-dllexport-template-specialization.cpp4
-rw-r--r--test/CodeGenCXX/windows-itanium-exceptions.cpp2
-rw-r--r--test/CodeGenCXX/windows-itanium-type-info.cpp18
-rw-r--r--test/CodeGenCoroutines/coro-alloc.cpp61
-rw-r--r--test/CodeGenCoroutines/coro-await-resume-eh.cpp108
-rw-r--r--test/CodeGenCoroutines/coro-builtins.c3
-rw-r--r--test/CodeGenCoroutines/coro-eh-cleanup.cpp8
-rw-r--r--test/CodeGenCoroutines/coro-gro-nrvo.cpp87
-rw-r--r--test/CodeGenCoroutines/coro-params.cpp58
-rw-r--r--test/CodeGenCoroutines/coro-promise-dtor.cpp8
-rw-r--r--test/CodeGenCoroutines/coro-unhandled-exception.cpp14
-rw-r--r--test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp4
-rw-r--r--test/CodeGenObjC/Inputs/strong_in_union.h10
-rw-r--r--test/CodeGenObjC/arc-foreach.m2
-rw-r--r--test/CodeGenObjC/arc.m69
-rw-r--r--test/CodeGenObjC/availability-dso-local.m6
-rw-r--r--test/CodeGenObjC/blocks.m5
-rw-r--r--test/CodeGenObjC/builtin-memfns.m2
-rw-r--r--test/CodeGenObjC/constant-strings.m15
-rw-r--r--test/CodeGenObjC/debug-info-category.m52
-rw-r--r--test/CodeGenObjC/disable-tail-call-escaping-block.m54
-rw-r--r--test/CodeGenObjC/dllstorage.m38
-rw-r--r--test/CodeGenObjC/forward-declare-protocol-gnu.m11
-rw-r--r--test/CodeGenObjC/forward-protocol-metadata-symbols.m15
-rw-r--r--test/CodeGenObjC/gnu-empty-protocol-v3.m26
-rw-r--r--test/CodeGenObjC/gnu-init.m69
-rw-r--r--test/CodeGenObjC/gnustep2-category.m26
-rw-r--r--test/CodeGenObjC/gnustep2-class.m55
-rw-r--r--test/CodeGenObjC/gnustep2-ivar-offset.m28
-rw-r--r--test/CodeGenObjC/gnustep2-proto.m39
-rw-r--r--test/CodeGenObjC/ivar-type-encoding.m8
-rw-r--r--test/CodeGenObjC/messages-2.m4
-rw-r--r--test/CodeGenObjC/noescape.m47
-rw-r--r--test/CodeGenObjC/nontrivial-c-struct-exception.m62
-rw-r--r--test/CodeGenObjC/nontrivial-c-struct-func-name-collision.m14
-rw-r--r--test/CodeGenObjC/objc-container-subscripting-1.m8
-rw-r--r--test/CodeGenObjC/objc-non-trivial-struct-nrvo.m134
-rw-r--r--test/CodeGenObjC/objc-runtime-name.m24
-rw-r--r--test/CodeGenObjC/personality.m76
-rw-r--r--test/CodeGenObjC/runtime-abi-match.m2
-rw-r--r--test/CodeGenObjC/stret-1.m2
-rw-r--r--test/CodeGenObjC/strong-in-c-struct.m563
-rw-r--r--test/CodeGenObjC/ubsan-nullability.m37
-rw-r--r--test/CodeGenObjC/weak-in-c-struct.m193
-rw-r--r--test/CodeGenObjCXX/arc-blocks.mm135
-rw-r--r--test/CodeGenObjCXX/arc-cxx11-init-list.mm2
-rw-r--r--test/CodeGenObjCXX/arc-exceptions.mm2
-rw-r--r--test/CodeGenObjCXX/arc-forwarded-lambda-call.mm20
-rw-r--r--test/CodeGenObjCXX/arc-marker-funclet.mm17
-rw-r--r--test/CodeGenObjCXX/arc-special-member-functions.mm71
-rw-r--r--test/CodeGenObjCXX/debug-info-line.mm2
-rw-r--r--test/CodeGenObjCXX/instantiate-return.mm22
-rw-r--r--test/CodeGenObjCXX/lambda-expressions.mm28
-rw-r--r--test/CodeGenObjCXX/literals.mm14
-rw-r--r--test/CodeGenObjCXX/microsoft-abi-arc-param-order.mm6
-rw-r--r--test/CodeGenObjCXX/msabi-objc-extensions.mm66
-rw-r--r--test/CodeGenObjCXX/msabi-objc-types.mm146
-rw-r--r--test/CodeGenObjCXX/msabi-stret.mm18
-rw-r--r--test/CodeGenObjCXX/objc-struct-cxx-abi.mm180
-rw-r--r--test/CodeGenObjCXX/personality.mm105
-rw-r--r--test/CodeGenObjCXX/property-dot-copy-elision.mm41
-rw-r--r--test/CodeGenObjCXX/property-objects.mm8
-rw-r--r--test/CodeGenOpenCL/addr-space-struct-arg.cl103
-rw-r--r--test/CodeGenOpenCL/address-space-constant-initializers.cl21
-rw-r--r--test/CodeGenOpenCL/address-spaces.cl46
-rw-r--r--test/CodeGenOpenCL/amdgcn-automatic-variable.cl2
-rw-r--r--test/CodeGenOpenCL/amdgpu-abi-struct-coerce.cl42
-rw-r--r--test/CodeGenOpenCL/amdgpu-alignment.cl170
-rw-r--r--test/CodeGenOpenCL/amdgpu-attrs.cl61
-rw-r--r--test/CodeGenOpenCL/amdgpu-debug-info-variable-expression.cl26
-rw-r--r--test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl29
-rw-r--r--test/CodeGenOpenCL/amdgpu-env-amdgcn.cl5
-rw-r--r--test/CodeGenOpenCL/amdgpu-env-amdgiz.cl9
-rw-r--r--test/CodeGenOpenCL/amdgpu-features.cl12
-rw-r--r--test/CodeGenOpenCL/amdgpu-nullptr.cl166
-rw-r--r--test/CodeGenOpenCL/blocks.cl66
-rw-r--r--test/CodeGenOpenCL/builtins-amdgcn-dl-insts-err.cl25
-rw-r--r--test/CodeGenOpenCL/builtins-amdgcn-dl-insts.cl36
-rw-r--r--test/CodeGenOpenCL/builtins-amdgcn-vi.cl17
-rw-r--r--test/CodeGenOpenCL/builtins-amdgcn.cl12
-rw-r--r--test/CodeGenOpenCL/byval.cl8
-rw-r--r--test/CodeGenOpenCL/cast_image.cl2
-rw-r--r--test/CodeGenOpenCL/cl-uniform-wg-size.cl16
-rw-r--r--test/CodeGenOpenCL/cl20-device-side-enqueue.cl119
-rw-r--r--test/CodeGenOpenCL/convergent.cl5
-rw-r--r--test/CodeGenOpenCL/denorms-are-zero.cl32
-rw-r--r--test/CodeGenOpenCL/half.cl1
-rw-r--r--test/CodeGenOpenCL/inline-asm-amdgcn.cl8
-rw-r--r--test/CodeGenOpenCL/kernel-attributes.cl6
-rw-r--r--test/CodeGenOpenCL/kernel-metadata.cl2
-rw-r--r--test/CodeGenOpenCL/lifetime.cl4
-rw-r--r--test/CodeGenOpenCL/opencl_types.cl41
-rw-r--r--test/CodeGenOpenCL/partial_initializer.cl14
-rw-r--r--test/CodeGenOpenCL/pipe_builtin.cl66
-rw-r--r--test/CodeGenOpenCL/pipe_types.cl19
-rw-r--r--test/CodeGenOpenCL/private-array-initialization.cl30
-rw-r--r--test/CodeGenOpenCL/shifts.cl15
-rw-r--r--test/CodeGenOpenCL/size_t.cl51
-rw-r--r--test/CodeGenOpenCL/str_literals.cl16
-rw-r--r--test/CodeGenOpenCL/vla.cl13
-rw-r--r--test/Coverage/ast-printing.m6
-rw-r--r--test/Coverage/html-multifile-diagnostics.c2
-rw-r--r--test/CoverageMapping/break.c11
-rw-r--r--test/CoverageMapping/classtemplate.cpp41
-rw-r--r--test/CoverageMapping/deferred-region.cpp24
-rw-r--r--test/CoverageMapping/label.cpp17
-rw-r--r--test/CoverageMapping/moremacros.c2
-rw-r--r--test/CoverageMapping/openmp.c12
-rw-r--r--test/CoverageMapping/trycatch.cpp2
-rwxr-xr-x[-rw-r--r--]test/Driver/Inputs/CUDA-nolibdevice/usr/local/cuda/bin/ptxas (renamed from test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/crtbegin_dynamic.o)0
-rwxr-xr-x[-rw-r--r--]test/Driver/Inputs/CUDA-symlinks/opt/cuda/bin/ptxas (renamed from test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/crtbegin_so.o)0
-rw-r--r--test/Driver/Inputs/CUDA-symlinks/opt/cuda/include/.keep (renamed from test/Driver/Inputs/mingw_ubuntu_tree/usr/include/c++/4.8/86_64-w64-mingw32/.keep)0
-rw-r--r--test/Driver/Inputs/CUDA-symlinks/opt/cuda/lib/.keep (renamed from test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/crtbegin_static.o)0
-rw-r--r--test/Driver/Inputs/CUDA-symlinks/opt/cuda/nvvm/libdevice/libdevice.compute_30.10.bc (renamed from test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/crtend_android.o)0
-rw-r--r--test/Driver/Inputs/CUDA-symlinks/opt/cuda/nvvm/libdevice/libdevice.compute_35.10.bc (renamed from test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/crtend_so.o)0
l---------test/Driver/Inputs/CUDA-symlinks/usr/bin/ptxas1
-rwxr-xr-x[-rw-r--r--]test/Driver/Inputs/CUDA/usr/local/cuda/bin/ptxas (renamed from test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr2/crtbegin_dynamic.o)0
-rw-r--r--test/Driver/Inputs/ami_linux_tree/lib/.keep (renamed from test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr2/crtbegin_so.o)0
-rw-r--r--test/Driver/Inputs/ami_linux_tree/usr/lib/gcc/x86_64-amazon-linux/7/crtbegin.o (renamed from test/Driver/Inputs/sparc-sun-solaris2.11/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/crtbegin.o)0
-rw-r--r--test/Driver/Inputs/ami_linux_tree/usr/lib/gcc/x86_64-amazon-linux/7/crtbeginT.o (renamed from test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr2/crtbegin_static.o)0
-rw-r--r--test/Driver/Inputs/ami_linux_tree/usr/lib/gcc/x86_64-amazon-linux/7/crtend.o (renamed from test/Driver/Inputs/sparc-sun-solaris2.11/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/crtend.o)0
-rw-r--r--test/Driver/Inputs/ami_linux_tree/usr/lib64/crt1.o (renamed from test/Driver/Inputs/sparc-sun-solaris2.11/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/crt1.o)0
-rw-r--r--test/Driver/Inputs/ami_linux_tree/usr/lib64/crti.o (renamed from test/Driver/Inputs/sparc-sun-solaris2.11/usr/lib/crti.o)0
-rw-r--r--test/Driver/Inputs/ami_linux_tree/usr/lib64/crtn.o (renamed from test/Driver/Inputs/sparc-sun-solaris2.11/usr/lib/crtn.o)0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/include/c++/4.9/x86_64-linux-android/.keep (renamed from test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr2/crtend_android.o)0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/x86_64-linux-android/4.9/crtbegin.o (renamed from test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr2/crtend_so.o)0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/x86_64-linux-android/4.9/crtend.o (renamed from test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr6/crtbegin_dynamic.o)0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/x86_64-linux-android/4.9/include/.keep (renamed from test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr6/crtbegin_so.o)0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/include/aarch64-linux-android/.keep (renamed from test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr6/crtbegin_static.o)0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/include/arm-linux-androideabi/.keep (renamed from test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr6/crtend_android.o)0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/include/i686-linux-android/.keep (renamed from test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr6/crtend_so.o)0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/include/x86_64-linux-android/.keep (renamed from test/Driver/Inputs/resource_dir/asan_blacklist.txt)0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/21/crtbegin_dynamic.o (renamed from test/Driver/Inputs/resource_dir/hwasan_blacklist.txt)0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/21/crtbegin_so.o (renamed from test/Driver/Inputs/resource_dir/ubsan_blacklist.txt)0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/21/crtbegin_static.o (renamed from test/Driver/Inputs/resource_dir/vtables_blacklist.txt)0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/21/crtend_android.o (renamed from test/Driver/Inputs/sparc-sun-solaris2.11/usr/lib/ld.so.1)0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/21/crtend_so.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/21/libc.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/21/libdl.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/21/libm.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/21/libstdc++.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/libc.a0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/libdl.a0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/libm.a0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/libstdc++.a0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/crtbegin_dynamic.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/crtbegin_so.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/crtbegin_static.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/crtend_android.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/crtend_so.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/libc.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/libdl.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/libm.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/libstdc++.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/crtbegin_dynamic.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/crtbegin_so.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/crtbegin_static.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/crtend_android.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/crtend_so.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/libc.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/libdl.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/libm.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/libstdc++.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/libc.a0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/libdl.a0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/libm.a0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/libstdc++.a0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/crtbegin_dynamic.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/crtbegin_so.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/crtbegin_static.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/crtend_android.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/crtend_so.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/libc.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/libdl.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/libm.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/libstdc++.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/crtbegin_dynamic.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/crtbegin_so.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/crtbegin_static.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/crtend_android.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/crtend_so.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/libc.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/libdl.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/libm.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/libstdc++.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/libc.a0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/libdl.a0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/libm.a0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/libstdc++.a0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/crtbegin_dynamic.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/crtbegin_so.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/crtbegin_static.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/crtend_android.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/crtend_so.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/libc.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/libdl.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/libm.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/libstdc++.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/crtbegin_dynamic.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/crtbegin_so.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/crtbegin_static.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/crtend_android.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/crtend_so.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/libc.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/libdl.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/libm.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/libstdc++.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/crtbegin_dynamic.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/crtbegin_so.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/crtbegin_static.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/crtend_android.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/crtend_so.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/libc.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/libdl.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/libm.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/libstdc++.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/crtbegin_dynamic.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/crtbegin_so.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/crtbegin_static.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/crtend_android.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/crtend_so.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/libc.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/libdl.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/libm.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/libstdc++.so0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/libc.a0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/libdl.a0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/libm.a0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/libstdc++.a0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/x86_64-linux-android/bin/ld0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/x86_64-linux-android/bin/ld.bfd0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/x86_64-linux-android/bin/ld.gold0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/x86_64-linux-android/lib/.keep0
-rw-r--r--test/Driver/Inputs/config-1.cfg6
-rw-r--r--test/Driver/Inputs/config-2.cfg2
-rw-r--r--test/Driver/Inputs/config-2a.cfg2
-rw-r--r--test/Driver/Inputs/config-3.cfg1
-rw-r--r--test/Driver/Inputs/config-4.cfg3
-rw-r--r--test/Driver/Inputs/config-5.cfg2
-rw-r--r--test/Driver/Inputs/config-6.cfg1
-rw-r--r--test/Driver/Inputs/config/config-4.cfg1
-rw-r--r--test/Driver/Inputs/config/i386-qqq.cfg1
-rw-r--r--test/Driver/Inputs/config/i386-qqq3.cfg1
-rw-r--r--test/Driver/Inputs/config/x86_64-qqq.cfg1
-rw-r--r--test/Driver/Inputs/config/x86_64-qqq2.cfg1
-rw-r--r--test/Driver/Inputs/config/x86_64.cfg1
-rw-r--r--test/Driver/Inputs/config2/config-4.cfg1
-rw-r--r--test/Driver/Inputs/config2/i386.cfg1
-rw-r--r--test/Driver/Inputs/empty.cfg0
-rwxr-xr-xtest/Driver/Inputs/fuse_ld_windows/ld.foo.exe0
-rw-r--r--test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/etc/env.d/gcc/config-x86_64-pc-linux-gnu1
-rw-r--r--test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/etc/env.d/gcc/x86_64-pc-linux-gnu-4.9.310
-rw-r--r--test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/etc/gentoo-release1
-rw-r--r--test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/include/.keep0
-rw-r--r--test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x/32/crtbegin.o0
-rw-r--r--test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x/crtbegin.o0
-rw-r--r--test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x/include/g++-v4.9.3/.keep0
-rw-r--r--test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x/x32/crtbegin.o0
-rw-r--r--test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/lib/gcc/x86_64-pc-linux-gnu/5.4.0/32/crtbegin.o0
-rw-r--r--test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/lib/gcc/x86_64-pc-linux-gnu/5.4.0/crtbegin.o0
-rw-r--r--test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/lib/gcc/x86_64-pc-linux-gnu/5.4.0/include/g++-v5.4.0/.keep0
-rw-r--r--test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/lib/gcc/x86_64-pc-linux-gnu/5.4.0/x32/crtbegin.o0
-rw-r--r--test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/x86_64-pc-linux-gnu/lib/.keep0
-rw-r--r--test/Driver/Inputs/hip_dev_lib/irif.amdgcn.bc0
-rw-r--r--test/Driver/Inputs/hip_dev_lib/ockl.amdgcn.bc0
-rw-r--r--test/Driver/Inputs/hip_dev_lib/oclc_correctly_rounded_sqrt_on.amdgcn.bc0
-rw-r--r--test/Driver/Inputs/hip_dev_lib/oclc_daz_opt_off.amdgcn.bc0
-rw-r--r--test/Driver/Inputs/hip_dev_lib/oclc_daz_opt_on.amdgcn.bc0
-rw-r--r--test/Driver/Inputs/hip_dev_lib/oclc_finite_only_off.amdgcn.bc0
-rw-r--r--test/Driver/Inputs/hip_dev_lib/oclc_isa_version_803.amdgcn.bc0
-rw-r--r--test/Driver/Inputs/hip_dev_lib/oclc_isa_version_900.amdgcn.bc0
-rw-r--r--test/Driver/Inputs/hip_dev_lib/oclc_unsafe_math_off.amdgcn.bc0
-rw-r--r--test/Driver/Inputs/hip_dev_lib/ocml.amdgcn.bc0
-rw-r--r--test/Driver/Inputs/hip_dev_lib/opencl.amdgcn.bc0
-rw-r--r--test/Driver/Inputs/hip_multiple_inputs/a.cu0
-rw-r--r--test/Driver/Inputs/hip_multiple_inputs/b.hip0
-rw-r--r--test/Driver/Inputs/hip_multiple_inputs/lib1/lib1.bc0
-rw-r--r--test/Driver/Inputs/hip_multiple_inputs/lib2/lib2.bc0
-rw-r--r--test/Driver/Inputs/libomptarget/libomptarget-nvptx-sm_20.bc0
-rw-r--r--test/Driver/Inputs/mingw_ubuntu_posix_tree/usr/lib/gcc/x86_64-w64-mingw32/5.3-posix/include-fixed/.keep0
-rw-r--r--test/Driver/Inputs/mingw_ubuntu_posix_tree/usr/lib/gcc/x86_64-w64-mingw32/5.3-posix/include/c++/backward/.keep0
-rw-r--r--test/Driver/Inputs/mingw_ubuntu_posix_tree/usr/lib/gcc/x86_64-w64-mingw32/5.3-posix/include/c++/x86_64-w64-mingw32/.keep0
-rw-r--r--test/Driver/Inputs/mingw_ubuntu_posix_tree/usr/x86_64-w64-mingw32/include/.keep0
-rw-r--r--test/Driver/Inputs/mingw_ubuntu_tree/usr/include/c++/4.8/x86_64-w64-mingw32/.keep0
-rw-r--r--test/Driver/Inputs/multilib_riscv_linux_sdk/bin/.keep0
-rw-r--r--test/Driver/Inputs/multilib_riscv_linux_sdk/include/.keep0
-rw-r--r--test/Driver/Inputs/multilib_riscv_linux_sdk/lib/gcc/riscv64-unknown-linux-gnu/7.2.0/crtbegin.o0
-rw-r--r--test/Driver/Inputs/multilib_riscv_linux_sdk/lib/gcc/riscv64-unknown-linux-gnu/7.2.0/lib32/ilp32/crtbegin.o0
-rw-r--r--test/Driver/Inputs/multilib_riscv_linux_sdk/lib/gcc/riscv64-unknown-linux-gnu/7.2.0/lib32/ilp32d/crtbegin.o0
-rw-r--r--test/Driver/Inputs/multilib_riscv_linux_sdk/lib/gcc/riscv64-unknown-linux-gnu/7.2.0/lib64/lp64/crtbegin.o0
-rw-r--r--test/Driver/Inputs/multilib_riscv_linux_sdk/lib/gcc/riscv64-unknown-linux-gnu/7.2.0/lib64/lp64d/crtbegin.o0
-rwxr-xr-xtest/Driver/Inputs/multilib_riscv_linux_sdk/riscv64-unknown-linux-gnu/bin/ld1
-rw-r--r--test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/lib/.keep0
-rw-r--r--test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/lib32/ilp32/.keep0
-rw-r--r--test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/lib32/ilp32d/.keep0
-rw-r--r--test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/lib64/lp64/.keep0
-rw-r--r--test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/lib64/lp64d/.keep0
-rw-r--r--test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/usr/lib32/ilp32/.keep0
-rw-r--r--test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/usr/lib32/ilp32d/.keep0
-rw-r--r--test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/usr/lib64/lp64/.keep0
-rw-r--r--test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/usr/lib64/lp64d/.keep0
-rw-r--r--test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_ios_dynamic.dylib0
-rw-r--r--test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_iossim_dynamic.dylib0
-rw-r--r--test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_osx_dynamic.dylib0
-rw-r--r--test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_tvos_dynamic.dylib0
-rw-r--r--test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_tvossim_dynamic.dylib0
-rw-r--r--test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_watchos_dynamic.dylib0
-rw-r--r--test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_watchossim_dynamic.dylib0
-rw-r--r--test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.fuzzer_osx.a0
-rw-r--r--test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.lsan_ios_dynamic.dylib0
-rw-r--r--test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.lsan_iossim_dynamic.dylib0
-rw-r--r--test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.lsan_osx_dynamic.dylib0
-rw-r--r--test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.lsan_tvossim_dynamic.dylib0
-rw-r--r--test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.tsan_iossim_dynamic.dylib0
-rw-r--r--test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.tsan_osx_dynamic.dylib0
-rw-r--r--test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.tsan_tvossim_dynamic.dylib0
-rw-r--r--test/Driver/Inputs/resource_dir/lib/linux/libclang_rt.hwasan-x86_64.a.syms0
-rw-r--r--test/Driver/Inputs/resource_dir/share/asan_blacklist.txt0
-rw-r--r--test/Driver/Inputs/resource_dir/share/hwasan_blacklist.txt0
-rw-r--r--test/Driver/Inputs/resource_dir/share/ubsan_blacklist.txt0
-rw-r--r--test/Driver/Inputs/resource_dir/share/vtables_blacklist.txt0
-rw-r--r--test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/.keep0
-rw-r--r--test/Driver/Inputs/resource_dir_with_per_target_subdir/i386-linux-gnu/lib/.keep0
-rw-r--r--test/Driver/Inputs/resource_dir_with_per_target_subdir/include/c++/v1/.keep0
-rw-r--r--test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/.keep0
-rw-r--r--test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-linux-gnu/lib/.keep0
-rw-r--r--test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/include/c++/4.8.2/sparc-sun-solaris2.11/bits/gthr.h0
-rw-r--r--test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/include/c++/4.8.2/typeinfo0
-rw-r--r--test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/crt1.o0
-rw-r--r--test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/crtbegin.o0
-rw-r--r--test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/crtend.o0
-rw-r--r--test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/sparcv9/crt1.o0
-rw-r--r--test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/sparcv9/crtbegin.o0
-rw-r--r--test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/sparcv9/crtend.o0
-rw-r--r--test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/lib/libatomic.a0
-rw-r--r--test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/lib/sparcv9/libatomic.a0
-rw-r--r--test/Driver/Inputs/solaris_sparc_tree/usr/lib/crti.o0
-rw-r--r--test/Driver/Inputs/solaris_sparc_tree/usr/lib/crtn.o0
-rw-r--r--test/Driver/Inputs/solaris_sparc_tree/usr/lib/ld.so.10
-rw-r--r--test/Driver/Inputs/solaris_sparc_tree/usr/lib/sparcv9/crti.o0
-rw-r--r--test/Driver/Inputs/solaris_sparc_tree/usr/lib/sparcv9/crtn.o0
-rw-r--r--test/Driver/Inputs/solaris_sparc_tree/usr/lib/sparcv9/ld.so.10
-rw-r--r--test/Driver/Inputs/solaris_x86_tree/usr/gcc/4.9/include/c++/4.9.4/i386-pc-solaris2.11/bits/gthr.h0
-rw-r--r--test/Driver/Inputs/solaris_x86_tree/usr/gcc/4.9/include/c++/4.9.4/typeinfo0
-rw-r--r--test/Driver/Inputs/solaris_x86_tree/usr/gcc/4.9/lib/amd64/libatomic.a0
-rw-r--r--test/Driver/Inputs/solaris_x86_tree/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4/amd64/crtbegin.o0
-rw-r--r--test/Driver/Inputs/solaris_x86_tree/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4/amd64/crtend.o0
-rw-r--r--test/Driver/Inputs/solaris_x86_tree/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4/crtbegin.o0
-rw-r--r--test/Driver/Inputs/solaris_x86_tree/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4/crtend.o0
-rw-r--r--test/Driver/Inputs/solaris_x86_tree/usr/gcc/4.9/lib/libatomic.a0
-rw-r--r--test/Driver/Inputs/solaris_x86_tree/usr/lib/amd64/crt1.o0
-rw-r--r--test/Driver/Inputs/solaris_x86_tree/usr/lib/amd64/crti.o0
-rw-r--r--test/Driver/Inputs/solaris_x86_tree/usr/lib/amd64/crtn.o0
-rw-r--r--test/Driver/Inputs/solaris_x86_tree/usr/lib/amd64/ld.so.10
-rw-r--r--test/Driver/Inputs/solaris_x86_tree/usr/lib/crt1.o0
-rw-r--r--test/Driver/Inputs/solaris_x86_tree/usr/lib/crti.o0
-rw-r--r--test/Driver/Inputs/solaris_x86_tree/usr/lib/crtn.o0
-rw-r--r--test/Driver/Inputs/solaris_x86_tree/usr/lib/ld.so.10
-rw-r--r--test/Driver/XRay/lit.local.cfg7
-rw-r--r--test/Driver/XRay/xray-instrument-os.c2
-rw-r--r--test/Driver/XRay/xray-mode-flags.cpp35
-rw-r--r--test/Driver/XRay/xray-nolinkdeps.cpp8
-rw-r--r--test/Driver/aarch64-cpus.c30
-rw-r--r--test/Driver/aarch64-fix-cortex-a53-835769.c6
-rw-r--r--test/Driver/aarch64-fixed-x20.c4
-rw-r--r--test/Driver/aarch64-outliner.c8
-rw-r--r--test/Driver/addrsig.c8
-rw-r--r--test/Driver/amdgcn-toolchain-pic.cl7
-rw-r--r--test/Driver/amdgpu-features.c2
-rw-r--r--test/Driver/amdgpu-macros.cl277
-rw-r--r--test/Driver/amdgpu-mcpu.cl223
-rw-r--r--test/Driver/ananas.c8
-rw-r--r--test/Driver/android-ndk-standalone.cpp186
-rw-r--r--test/Driver/android-pie.c17
-rw-r--r--test/Driver/apple-kext-mkernel.c4
-rw-r--r--test/Driver/arch-specific-libdir-rpath.c33
-rw-r--r--test/Driver/arclite-link.c6
-rw-r--r--test/Driver/arm-cortex-cpus.c42
-rw-r--r--test/Driver/arm-dotprod.c21
-rw-r--r--test/Driver/arm-execute-only.c4
-rw-r--r--test/Driver/arm-mfpu.c168
-rw-r--r--test/Driver/arm-restrict-it.c4
-rw-r--r--test/Driver/asan.c7
-rw-r--r--test/Driver/autocomplete.c57
-rw-r--r--test/Driver/cl-include.c13
-rw-r--r--test/Driver/cl-options.c30
-rw-r--r--test/Driver/cl-pch-search.cpp4
-rw-r--r--test/Driver/cl-pch-showincludes.cpp10
-rw-r--r--test/Driver/cl-pch.cpp101
-rw-r--r--test/Driver/cl-x86-flags.c148
-rw-r--r--test/Driver/clang-g-opts.c4
-rw-r--r--test/Driver/clang-translation.cppm2
-rw-r--r--test/Driver/clang_f_opts.c40
-rw-r--r--test/Driver/codeview-column-info.c15
-rw-r--r--test/Driver/complete-member-pointers.cpp7
-rw-r--r--test/Driver/config-file-errs.c54
-rw-r--r--test/Driver/config-file.c73
-rw-r--r--test/Driver/config-file2.c51
-rw-r--r--test/Driver/config-file3.c106
-rw-r--r--test/Driver/config-file4.c2
-rw-r--r--test/Driver/constructors.c8
-rw-r--r--test/Driver/crash-diagnostics-dir.c6
-rw-r--r--test/Driver/crash-report-header.h5
-rw-r--r--test/Driver/crash-report-modules.m31
-rw-r--r--test/Driver/crash-report-spaces.c5
-rw-r--r--test/Driver/crash-report.c7
-rw-r--r--test/Driver/cuda-arch-translation.cu39
-rw-r--r--test/Driver/cuda-bad-arch.cu8
-rw-r--r--test/Driver/cuda-detect-path.cu83
-rw-r--r--test/Driver/cuda-detect.cu25
-rw-r--r--test/Driver/cuda-dwarf-2.cu47
-rw-r--r--test/Driver/cuda-external-tools.cu133
-rw-r--r--test/Driver/cuda-no-pgo-or-coverage.cu34
-rw-r--r--test/Driver/cuda-not-found.cu4
-rw-r--r--test/Driver/cuda-options.cu82
-rw-r--r--test/Driver/cuda-phases.cu348
-rw-r--r--test/Driver/cuda-version-check.cu22
-rw-r--r--test/Driver/cxa-atexit.cpp17
-rw-r--r--test/Driver/darwin-asan-nofortify.c2
-rw-r--r--test/Driver/darwin-infer-simulator-sdkroot.c77
-rw-r--r--test/Driver/darwin-ld.c14
-rw-r--r--test/Driver/darwin-sanitizer-ld.c19
-rw-r--r--test/Driver/darwin-version.c29
-rw-r--r--test/Driver/debug-options.c29
-rw-r--r--test/Driver/debug-prefix-map.S6
-rw-r--r--test/Driver/emulated-tls.cpp47
-rw-r--r--test/Driver/fast-math.c24
-rw-r--r--test/Driver/fno-escaping-block-tail-calls.c9
-rw-r--r--test/Driver/fno-rtti-data.cpp2
-rw-r--r--test/Driver/frame-pointer-elim.c9
-rw-r--r--test/Driver/frame-pointer.c24
-rw-r--r--test/Driver/freebsd-mips-as.c24
-rw-r--r--test/Driver/freebsd.c48
-rw-r--r--test/Driver/fsanitize-blacklist.c23
-rw-r--r--test/Driver/fsanitize-coverage.c1
-rw-r--r--test/Driver/fsanitize-object-size.c5
-rw-r--r--test/Driver/fsanitize.c139
-rw-r--r--test/Driver/fuchsia.c84
-rw-r--r--test/Driver/fuchsia.cpp10
-rw-r--r--test/Driver/function-alignment.c17
-rw-r--r--test/Driver/fuse-ld-windows.c25
-rw-r--r--test/Driver/fuzzer.c10
-rw-r--r--test/Driver/gcc_forward.c6
-rw-r--r--test/Driver/global-isel.c24
-rw-r--r--test/Driver/hexagon-hvx.c33
-rw-r--r--test/Driver/hexagon-memops.c10
-rw-r--r--test/Driver/hexagon-nvj.c10
-rw-r--r--test/Driver/hexagon-nvs.c10
-rw-r--r--test/Driver/hexagon-packets.c10
-rw-r--r--test/Driver/hexagon-toolchain-elf.c16
-rw-r--r--test/Driver/hexagon-vectorize.c9
-rw-r--r--test/Driver/hip-binding.hip15
-rw-r--r--test/Driver/hip-device-libs.hip28
-rw-r--r--test/Driver/hip-inputs.hip23
-rw-r--r--test/Driver/hip-toolchain.hip84
-rw-r--r--test/Driver/lanai-unknown-unknown.cpp14
-rw-r--r--test/Driver/le32-unknown-nacl.cpp20
-rw-r--r--test/Driver/le64-unknown-unknown.cpp20
-rw-r--r--test/Driver/linux-header-search.cpp58
-rw-r--r--test/Driver/linux-ld.c36
-rw-r--r--test/Driver/linux-per-target-runtime-dir.c21
-rw-r--r--test/Driver/lit.local.cfg2
-rw-r--r--test/Driver/lto-dwo.c6
-rw-r--r--test/Driver/lto.cu80
-rw-r--r--test/Driver/masm.c2
-rw-r--r--test/Driver/mglobal-merge.c8
-rw-r--r--test/Driver/mingw-libgcc.c13
-rw-r--r--test/Driver/mingw-msvcrt.c9
-rw-r--r--test/Driver/mingw-sysroot.cpp42
-rw-r--r--test/Driver/mingw-windowsapp.c6
-rw-r--r--test/Driver/mingw.cpp11
-rw-r--r--test/Driver/mips-abicalls-error.c2
-rw-r--r--test/Driver/mips-abicalls-warning.c25
-rw-r--r--test/Driver/mips-as.c16
-rw-r--r--test/Driver/mips-features.c48
-rw-r--r--test/Driver/mips-indirect-branch.c23
-rw-r--r--test/Driver/modules.m6
-rw-r--r--test/Driver/myriad-toolchain.c2
-rw-r--r--test/Driver/netbsd.c13
-rw-r--r--test/Driver/no-canonical-prefixes.c5
-rw-r--r--test/Driver/openbsd.c10
-rw-r--r--test/Driver/opencl.cl4
-rw-r--r--test/Driver/openmp-offload-gpu.c71
-rw-r--r--test/Driver/pic.c4
-rw-r--r--test/Driver/ppc-f128-support-check.c20
-rw-r--r--test/Driver/ppc-features.cpp4
-rw-r--r--test/Driver/print-empty-prog-name.c5
-rw-r--r--test/Driver/rewrite-legacy-objc.m6
-rw-r--r--test/Driver/rewrite-objc.m2
-rw-r--r--test/Driver/riscv-abi.c47
-rw-r--r--test/Driver/riscv-arch.c317
-rw-r--r--test/Driver/riscv-features.c13
-rw-r--r--test/Driver/riscv-gnutools.c19
-rw-r--r--test/Driver/riscv32-toolchain.c122
-rw-r--r--test/Driver/riscv64-toolchain.c91
-rw-r--r--test/Driver/rtti-options.cpp21
-rw-r--r--test/Driver/sanitizer-ld.c250
-rw-r--r--test/Driver/save-stats.c8
-rw-r--r--test/Driver/solaris-header-search.cpp50
-rw-r--r--test/Driver/solaris-ld.c125
-rw-r--r--test/Driver/sparc-as.c69
-rw-r--r--test/Driver/split-debug.c3
-rw-r--r--test/Driver/split-debug.s3
-rw-r--r--test/Driver/stack-arg-probe.c7
-rw-r--r--test/Driver/stack-size-section.c9
-rw-r--r--test/Driver/target-triple-deployment.c2
-rw-r--r--test/Driver/thinlto.cu54
-rw-r--r--test/Driver/thinlto_backend.c9
-rw-r--r--test/Driver/types.c18
-rw-r--r--test/Driver/unknown-arg.c25
-rw-r--r--test/Driver/unknown-std.cl1
-rw-r--r--test/Driver/unsupported-option.c7
-rw-r--r--test/Driver/wasm-toolchain.c21
-rw-r--r--test/Driver/wasm-toolchain.cpp23
-rw-r--r--test/Driver/windows-cross.c10
-rw-r--r--test/Driver/windows-exceptions.cpp9
-rw-r--r--test/Driver/woa-restrict-it.c2
-rw-r--r--test/Driver/x86-march.c22
-rw-r--r--test/Driver/x86-target-features.c54
-rw-r--r--test/FixIt/fixit-format-ios-nopedantic.m21
-rw-r--r--test/FixIt/fixit-format-ios.m2
-rw-r--r--test/FixIt/fixit-typedef-instead-of-typename-typo.cpp16
-rw-r--r--test/FixIt/fixit-unused-lambda-capture.cpp94
-rw-r--r--test/Format/dump-config-cxx.h3
-rw-r--r--test/Format/dump-config-objc.h5
-rw-r--r--test/Format/lit.local.cfg4
-rw-r--r--test/Frontend/Inputs/NextIncludes/rewrite-includes9.h1
-rw-r--r--test/Frontend/Inputs/SystemHeaderPrefix/with-header-guard.h3
-rw-r--r--test/Frontend/Inputs/resource_dir_with_cfi_blacklist/share/cfi_blacklist.txt0
-rw-r--r--test/Frontend/Inputs/rewrite-includes9.h3
-rw-r--r--test/Frontend/ast-codegen.c4
-rw-r--r--test/Frontend/backend-option.c4
-rw-r--r--test/Frontend/compiler-options-dump.cpp25
-rw-r--r--test/Frontend/dependency-gen-extradeps-phony.c10
-rw-r--r--test/Frontend/dependency-gen-symlink.c24
-rw-r--r--test/Frontend/dependency-gen.c2
-rw-r--r--test/Frontend/fixed_point.c399
-rw-r--r--test/Frontend/fixed_point_bit_widths.c196
-rw-r--r--test/Frontend/fixed_point_declarations.c113
-rw-r--r--test/Frontend/fixed_point_errors.c234
-rw-r--r--test/Frontend/fixed_point_errors.cpp14
-rw-r--r--test/Frontend/fixed_point_not_enabled.c21
-rw-r--r--test/Frontend/fixed_point_same_fbits.c28
-rw-r--r--test/Frontend/ftime-report-template-decl.cpp159
-rw-r--r--test/Frontend/gnu-mcount.c2
-rw-r--r--test/Frontend/nostdlib-for-asmpp.s5
-rw-r--r--test/Frontend/opencl.cl37
-rw-r--r--test/Frontend/print-header-includes.c24
-rw-r--r--test/Frontend/region-pragmas.c5
-rw-r--r--test/Frontend/rewrite-includes-messages.c2
-rw-r--r--test/Frontend/rewrite-includes.c34
-rw-r--r--test/Frontend/stdlang.c1
-rw-r--r--test/Frontend/unknown-arg.c9
-rw-r--r--test/Frontend/warning-stdlibcxx-darwin.cpp5
-rw-r--r--test/Frontend/windows-exceptions.cpp27
-rw-r--r--test/Frontend/x86-target-cpu.c3
-rw-r--r--test/Headers/ms-intrin.cpp2
-rw-r--r--test/Headers/ms-null-ms-header-vs-stddef.cpp2
-rw-r--r--test/Headers/pconfigintin.c12
-rw-r--r--test/Headers/sgxintrin.c27
-rw-r--r--test/Headers/x86-intrinsics-headers-clean.cpp14
-rw-r--r--test/Headers/x86intrin-2.c4
-rw-r--r--test/Import/attr/Inputs/S.cpp13
-rw-r--r--test/Import/attr/test.cpp26
-rw-r--r--test/Import/inherited-ctor-init-expr/Inputs/A.cpp11
-rw-r--r--test/Import/inherited-ctor-init-expr/test.cpp6
-rw-r--r--test/Import/template-specialization/Inputs/T.cpp4
-rw-r--r--test/Import/template-specialization/test.cpp5
-rw-r--r--test/Index/Core/index-macros.c12
-rw-r--r--test/Index/Core/index-pch.cpp17
-rw-r--r--test/Index/Inputs/crash-preamble-classes.h9
-rw-r--r--test/Index/Inputs/reparse-issue.h3
-rw-r--r--test/Index/Inputs/reparse-issue.h-04
-rw-r--r--test/Index/Inputs/reparse-issue.h-15
-rw-r--r--test/Index/USR/linkage.cpp7
-rw-r--r--test/Index/annotate-tokens-unexposed.cpp20
-rw-r--r--test/Index/annotate-tokens.cpp12
-rw-r--r--test/Index/comment-objc-parameterized-classes.m2
-rw-r--r--test/Index/complete-access-checks.cpp27
-rw-r--r--test/Index/complete-and-plugins.c6
-rw-r--r--test/Index/complete-arrow-dot.cpp54
-rw-r--r--test/Index/complete-call.cpp50
-rw-r--r--test/Index/complete-exprs.c6
-rw-r--r--test/Index/complete-exprs.cpp4
-rw-r--r--test/Index/complete-pch-skip.cpp30
-rw-r--r--test/Index/complete-preprocessor.m4
-rw-r--r--test/Index/crash-preamble-classes.cpp8
-rw-r--r--test/Index/create-libclang-completion-reproducer.c14
-rw-r--r--test/Index/create-libclang-parsing-reproducer.c21
-rw-r--r--test/Index/get-cursor.cpp10
-rw-r--r--test/Index/headerfile-comment-to-html.m6
-rw-r--r--test/Index/index-refs.cpp16
-rw-r--r--test/Index/index-subscripting-literals.m2
-rw-r--r--test/Index/index-template-specialization.cpp19
-rw-r--r--test/Index/missing_vfs.c6
-rw-r--r--test/Index/opencl-types.cl30
-rw-r--r--test/Index/overriding-ftemplate-comments.cpp4
-rw-r--r--test/Index/paren-type.c16
-rw-r--r--test/Index/pipe-size.cl12
-rw-r--r--test/Index/print-display-names.cpp23
-rw-r--r--test/Index/print-type-size.cpp4
-rw-r--r--test/Index/print-type.c4
-rw-r--r--test/Index/reparsed-live-issue.cpp4
-rw-r--r--test/Layout/itanium-pack-and-align.cpp26
-rw-r--r--test/Layout/ms-x86-pack-and-align.cpp24
-rw-r--r--test/Layout/v6-empty.cpp20
-rw-r--r--test/Layout/watchos-standard-layout.cpp47
-rw-r--r--test/Lexer/char8_t.cpp17
-rw-r--r--test/Lexer/cxx-features.cpp40
-rw-r--r--test/Lexer/cxx1y_digit_separators.cpp2
-rw-r--r--test/Lexer/digraph.c23
-rw-r--r--test/Lexer/has_feature_address_sanitizer.cpp1
-rw-r--r--test/Lexer/has_feature_objc_arc.m8
-rw-r--r--test/Lexer/null-character-in-literal.cbin0 -> 917 bytes
-rw-r--r--test/Misc/ast-dump-attr.cpp4
-rw-r--r--test/Misc/ast-dump-attr.m57
-rw-r--r--test/Misc/ast-dump-decl.cpp4
-rw-r--r--test/Misc/ast-dump-stmt.c38
-rw-r--r--test/Misc/ast-print-bool.c44
-rw-r--r--test/Misc/ast-print-enum-decl.c105
-rw-r--r--test/Misc/ast-print-objectivec.m12
-rw-r--r--test/Misc/ast-print-pragmas-xfail.cpp2
-rw-r--r--test/Misc/ast-print-pragmas.cpp4
-rw-r--r--test/Misc/ast-print-record-decl.c291
-rw-r--r--test/Misc/attr-print-emit.cpp69
-rw-r--r--test/Misc/backend-stack-frame-diagnostics.cpp4
-rw-r--r--test/Misc/cc1as-split-dwarf.s26
-rw-r--r--test/Misc/dev-fd-fs.c1
-rw-r--r--test/Misc/diag-format.c2
-rw-r--r--test/Misc/diag-greatergreater.cpp43
-rw-r--r--test/Misc/diag-macro-backtrace2.c2
-rw-r--r--test/Misc/diag-template-diffing.cpp6
-rw-r--r--test/Misc/pragma-attribute-supported-attributes-list.test8
-rw-r--r--test/Misc/serialized-diags-bcanalyzer.c3
-rw-r--r--test/Misc/target-invalid-cpu-note.c162
-rw-r--r--test/Misc/thinlto.c4
-rw-r--r--test/Misc/warning-flags.c5
-rw-r--r--test/Modules/ExtDebugInfo.cpp2
-rw-r--r--test/Modules/Inputs/DebugCXX.h3
-rw-r--r--test/Modules/Inputs/DependsOnModule.framework/module.map18
-rw-r--r--test/Modules/Inputs/at-import-in-framework-header/A.framework/Headers/A.h2
-rw-r--r--test/Modules/Inputs/at-import-in-framework-header/A.framework/Modules/module.modulemap4
-rw-r--r--test/Modules/Inputs/at-import-in-framework-header/module.modulemap2
-rw-r--r--test/Modules/Inputs/autoload-subdirectory/a.h9
-rw-r--r--test/Modules/Inputs/autoload-subdirectory/b.h1
-rw-r--r--test/Modules/Inputs/autoload-subdirectory/c.h7
-rw-r--r--test/Modules/Inputs/autoload-subdirectory/include/module.modulemap3
-rw-r--r--test/Modules/Inputs/autoload-subdirectory/module.modulemap3
-rw-r--r--test/Modules/Inputs/bad-private-include/Bad.framework/Headers/Bad.h1
-rw-r--r--test/Modules/Inputs/bad-private-include/Bad.framework/Modules/module.modulemap5
-rw-r--r--test/Modules/Inputs/bad-private-include/Bad.framework/Modules/module.private.modulemap5
-rw-r--r--test/Modules/Inputs/bad-private-include/Bad.framework/PrivateHeaders/BadPrivate.h1
-rw-r--r--test/Modules/Inputs/bad-private-include/Bad.framework/PrivateHeaders/Shared.h3
-rw-r--r--test/Modules/Inputs/class-extension/a-private.h5
-rw-r--r--test/Modules/Inputs/class-extension/a-proto.h7
-rw-r--r--test/Modules/Inputs/class-extension/a.h5
-rw-r--r--test/Modules/Inputs/class-extension/module.modulemap11
-rw-r--r--test/Modules/Inputs/declare-use/h.h2
-rw-r--r--test/Modules/Inputs/diag_flags.h3
-rw-r--r--test/Modules/Inputs/double-quotes/A.framework/Headers/A.h6
-rw-r--r--test/Modules/Inputs/double-quotes/A.framework/Headers/A0.h1
-rw-r--r--test/Modules/Inputs/double-quotes/A.framework/Modules/module.modulemap5
-rw-r--r--test/Modules/Inputs/double-quotes/B.h1
-rw-r--r--test/Modules/Inputs/double-quotes/X.framework/Headers/X.h1
-rw-r--r--test/Modules/Inputs/double-quotes/X.framework/Modules/module.modulemap4
-rw-r--r--test/Modules/Inputs/double-quotes/a.hmap.json6
-rw-r--r--test/Modules/Inputs/double-quotes/flat-header-path/Z.h1
-rw-r--r--test/Modules/Inputs/double-quotes/flat-header-path/Z.modulemap4
-rw-r--r--test/Modules/Inputs/double-quotes/x.hmap.json7
-rw-r--r--test/Modules/Inputs/double-quotes/z.yaml28
-rw-r--r--test/Modules/Inputs/exportas-link/OtherKit.framework/Headers/OtherKit.h7
-rw-r--r--test/Modules/Inputs/exportas-link/OtherKit.framework/Modules/module.modulemap5
-rw-r--r--test/Modules/Inputs/exportas-link/SomeKit.framework/Headers/SKWidget.h2
-rw-r--r--test/Modules/Inputs/exportas-link/SomeKit.framework/Headers/SomeKit.h6
-rw-r--r--test/Modules/Inputs/exportas-link/SomeKit.framework/Modules/module.modulemap6
-rw-r--r--test/Modules/Inputs/exportas-link/SomeKit.framework/SomeKit.tbd1
-rw-r--r--test/Modules/Inputs/exportas-link/SomeKitCore.framework/Headers/SKWidget.h4
-rw-r--r--test/Modules/Inputs/exportas-link/SomeKitCore.framework/Headers/SomeKitCore.h6
-rw-r--r--test/Modules/Inputs/exportas-link/SomeKitCore.framework/Modules/module.modulemap7
-rw-r--r--test/Modules/Inputs/exportas-link/SomeKitCore.framework/SomeKitCore.tbd1
-rw-r--r--test/Modules/Inputs/framework-public-includes-private/A.framework/Headers/A.h4
-rw-r--r--test/Modules/Inputs/framework-public-includes-private/A.framework/Modules/module.modulemap4
-rw-r--r--test/Modules/Inputs/framework-public-includes-private/A.framework/Modules/module.private.modulemap4
-rw-r--r--test/Modules/Inputs/framework-public-includes-private/A.framework/PrivateHeaders/APriv.h1
-rw-r--r--test/Modules/Inputs/framework-public-includes-private/A.framework/PrivateHeaders/APriv2.h1
-rw-r--r--test/Modules/Inputs/framework-public-includes-private/a.hmap.json8
-rw-r--r--test/Modules/Inputs/framework-public-includes-private/flat-header-path/Z.h2
-rw-r--r--test/Modules/Inputs/framework-public-includes-private/flat-header-path/Z.modulemap4
-rw-r--r--test/Modules/Inputs/framework-public-includes-private/flat-header-path/Z.private.modulemap4
-rw-r--r--test/Modules/Inputs/framework-public-includes-private/flat-header-path/ZPriv.h1
-rw-r--r--test/Modules/Inputs/framework-public-includes-private/z.hmap.json7
-rw-r--r--test/Modules/Inputs/framework-public-includes-private/z.yaml45
-rw-r--r--test/Modules/Inputs/implicit-private-canonical/A.framework/Modules/module.modulemap3
-rw-r--r--test/Modules/Inputs/implicit-private-with-submodule/A.framework/Modules/module.modulemap6
-rw-r--r--test/Modules/Inputs/implicit-private-with-submodule/A.framework/Modules/module.private.modulemap6
-rw-r--r--test/Modules/Inputs/incomplete-framework-module/Foo.framework/Headers/Foo.h1
-rw-r--r--test/Modules/Inputs/incomplete-framework-module/Foo.framework/Headers/FooB.h1
-rw-r--r--test/Modules/Inputs/incomplete-framework-module/Foo.framework/Modules/module.modulemap4
-rw-r--r--test/Modules/Inputs/module.map15
-rw-r--r--test/Modules/Inputs/non-ambiguous-enum/A.framework/Headers/a.h1
-rw-r--r--test/Modules/Inputs/non-ambiguous-enum/A.framework/Headers/a0.h1
-rw-r--r--test/Modules/Inputs/non-ambiguous-enum/A.framework/Modules/module.modulemap5
-rw-r--r--test/Modules/Inputs/non-ambiguous-enum/B.framework/Headers/b.h6
-rw-r--r--test/Modules/Inputs/odr_hash-Friend/Bad.h17
-rw-r--r--test/Modules/Inputs/odr_hash-Friend/Box.h14
-rw-r--r--test/Modules/Inputs/odr_hash-Friend/Good.h17
-rw-r--r--test/Modules/Inputs/odr_hash-Friend/M1.h6
-rw-r--r--test/Modules/Inputs/odr_hash-Friend/M2.h5
-rw-r--r--test/Modules/Inputs/odr_hash-Friend/M3.h7
-rw-r--r--test/Modules/Inputs/odr_hash-Friend/module.modulemap23
-rw-r--r--test/Modules/Inputs/odr_hash-Unresolved/Module2/include.h3
-rw-r--r--test/Modules/Inputs/odr_hash-Unresolved/Module2/not-include.h5
-rw-r--r--test/Modules/Inputs/odr_hash-Unresolved/Sub1/X.h3
-rw-r--r--test/Modules/Inputs/odr_hash-Unresolved/Sub1/Y.h4
-rw-r--r--test/Modules/Inputs/odr_hash-Unresolved/Sub1/Z.h4
-rw-r--r--test/Modules/Inputs/odr_hash-Unresolved/Sub2/A.h3
-rw-r--r--test/Modules/Inputs/odr_hash-Unresolved/Sub2/B.h3
-rw-r--r--test/Modules/Inputs/odr_hash-Unresolved/class.h11
-rw-r--r--test/Modules/Inputs/odr_hash-Unresolved/function.h6
-rw-r--r--test/Modules/Inputs/odr_hash-Unresolved/module.modulemap21
-rw-r--r--test/Modules/Inputs/odr_hash-elaborated-types/first.h6
-rw-r--r--test/Modules/Inputs/odr_hash-elaborated-types/module.modulemap5
-rw-r--r--test/Modules/Inputs/odr_hash-elaborated-types/second.h6
-rw-r--r--test/Modules/Inputs/odr_hash-elaborated-types/textual_stat.h11
-rw-r--r--test/Modules/Inputs/odr_hash-elaborated-types/textual_time.h6
-rw-r--r--test/Modules/Inputs/protocol-redefinition/Base.framework/Headers/Base.h3
-rw-r--r--test/Modules/Inputs/protocol-redefinition/Base.framework/Modules/module.modulemap4
-rw-r--r--test/Modules/Inputs/protocol-redefinition/Kit.framework/Headers/Kit.h6
-rw-r--r--test/Modules/Inputs/protocol-redefinition/Kit.framework/Modules/module.modulemap4
-rw-r--r--test/Modules/Inputs/self-referencing-lambda/a.h4
-rw-r--r--test/Modules/Inputs/self-referencing-lambda/module.modulemap4
-rw-r--r--test/Modules/Inputs/shadow/A1/A.h1
-rw-r--r--test/Modules/Inputs/shadow/A1/module.modulemap5
-rw-r--r--test/Modules/Inputs/shadow/A2/A.h1
-rw-r--r--test/Modules/Inputs/shadow/A2/module.modulemap5
-rw-r--r--test/Modules/Inputs/shadowed-submodule/A1/Foo.h1
-rw-r--r--test/Modules/Inputs/shadowed-submodule/A1/module.modulemap14
-rw-r--r--test/Modules/Inputs/shadowed-submodule/A1/sys/A.h1
-rw-r--r--test/Modules/Inputs/shadowed-submodule/A1/sys/A2.h1
-rw-r--r--test/Modules/Inputs/shadowed-submodule/A2/Foo.h1
-rw-r--r--test/Modules/Inputs/shadowed-submodule/A2/module.modulemap14
-rw-r--r--test/Modules/Inputs/shadowed-submodule/A2/sys/A.h1
-rw-r--r--test/Modules/Inputs/shadowed-submodule/A2/sys/A2.h1
-rw-r--r--test/Modules/Inputs/shadowed-submodule/Foo/module.modulemap3
-rw-r--r--test/Modules/Inputs/submodule-in-private-mmap/A.framework/Headers/A.h1
-rw-r--r--test/Modules/Inputs/submodule-in-private-mmap/A.framework/Headers/SomeSub.h0
-rw-r--r--test/Modules/Inputs/submodule-in-private-mmap/A.framework/Modules/module.modulemap3
-rw-r--r--test/Modules/Inputs/submodule-in-private-mmap/A.framework/Modules/module.private.modulemap7
-rw-r--r--test/Modules/Inputs/submodule-in-private-mmap/A.framework/PrivateHeaders/APrivate.h0
-rw-r--r--test/Modules/Inputs/template-nontrivial0.h13
-rw-r--r--test/Modules/Inputs/template-nontrivial1.h6
-rw-r--r--test/Modules/ModuleDebugInfo.cpp19
-rw-r--r--test/Modules/at-import-in-framework-header.m17
-rw-r--r--test/Modules/autoload-subdirectory.cpp10
-rw-r--r--test/Modules/bad-private-include.m6
-rw-r--r--test/Modules/check-for-sanitizer-feature.cpp2
-rw-r--r--test/Modules/class-extension-protocol.m9
-rw-r--r--test/Modules/codegen.test1
-rw-r--r--test/Modules/crash-vfs-headermaps.m10
-rw-r--r--test/Modules/crash-vfs-path-emptydir-entries.m2
-rw-r--r--test/Modules/crash-vfs-path-symlink-component.m2
-rw-r--r--test/Modules/crash-vfs-path-symlink-topheader.m2
-rw-r--r--test/Modules/crash-vfs-umbrella-frameworks.m2
-rw-r--r--test/Modules/cxx-dtor.cpp1
-rw-r--r--test/Modules/cxx-irgen.cpp8
-rw-r--r--test/Modules/cxx17-exception-spec.cpp34
-rw-r--r--test/Modules/diag-flags.cpp34
-rw-r--r--test/Modules/double-quotes.m39
-rw-r--r--test/Modules/framework-public-includes-private.m37
-rw-r--r--test/Modules/friend-definition-2.cpp35
-rw-r--r--test/Modules/friend-definition.cpp39
-rw-r--r--test/Modules/implicit-private-with-submodule.m11
-rw-r--r--test/Modules/incomplete-framework-module.m11
-rw-r--r--test/Modules/local-visibility.cpp15
-rw-r--r--test/Modules/merge-deduced-return.cpp33
-rw-r--r--test/Modules/merge-lambdas.cpp48
-rw-r--r--test/Modules/merge-static-locals.cpp27
-rw-r--r--test/Modules/merge-target-features.cpp11
-rw-r--r--test/Modules/modify-module.m6
-rw-r--r--test/Modules/module-imported-by-pch-with-modulemap.m16
-rw-r--r--test/Modules/module-name-private.m12
-rw-r--r--test/Modules/module_file_info.m10
-rw-r--r--test/Modules/new-delete.cpp23
-rw-r--r--test/Modules/non-ambiguous-enum.m10
-rw-r--r--test/Modules/odr_hash-Friend.cpp90
-rw-r--r--test/Modules/odr_hash-Unresolved.cpp14
-rw-r--r--test/Modules/odr_hash-blocks.cpp119
-rw-r--r--test/Modules/odr_hash-elaborated-types.cpp12
-rw-r--r--test/Modules/odr_hash.cpp1119
-rw-r--r--test/Modules/pr27401.cpp1
-rw-r--r--test/Modules/protocol-redefinition.m6
-rw-r--r--test/Modules/requires.m17
-rw-r--r--test/Modules/self-referencing-lambda.cpp5
-rw-r--r--test/Modules/shadow.m21
-rw-r--r--test/Modules/shadowed-submodule.m5
-rw-r--r--test/Modules/submodule-in-private-mmap.m7
-rw-r--r--test/Modules/target-features.m40
-rw-r--r--test/Modules/templates.mm14
-rw-r--r--test/Modules/use-exportas-for-link.m44
-rw-r--r--test/Modules/using-decl-friend-2.cpp39
-rw-r--r--test/Modules/using-decl-friend.cpp37
-rw-r--r--test/OpenMP/atomic_ast_print.cpp6
-rw-r--r--test/OpenMP/atomic_capture_codegen.cpp5
-rw-r--r--test/OpenMP/atomic_codegen.cpp6
-rw-r--r--test/OpenMP/atomic_messages.c2
-rw-r--r--test/OpenMP/atomic_messages.cpp2
-rw-r--r--test/OpenMP/atomic_read_codegen.c5
-rw-r--r--test/OpenMP/atomic_update_codegen.cpp5
-rw-r--r--test/OpenMP/atomic_write_codegen.c9
-rw-r--r--test/OpenMP/barrier_ast_print.cpp6
-rw-r--r--test/OpenMP/barrier_codegen.cpp5
-rw-r--r--test/OpenMP/barrier_messages.cpp2
-rw-r--r--test/OpenMP/cancel_ast_print.cpp6
-rw-r--r--test/OpenMP/cancel_codegen.cpp35
-rw-r--r--test/OpenMP/cancel_codegen_cleanup.cpp3
-rw-r--r--test/OpenMP/cancel_if_messages.cpp2
-rw-r--r--test/OpenMP/cancel_messages.cpp2
-rw-r--r--test/OpenMP/cancellation_point_ast_print.cpp6
-rw-r--r--test/OpenMP/cancellation_point_codegen.cpp39
-rw-r--r--test/OpenMP/cancellation_point_messages.cpp2
-rw-r--r--test/OpenMP/capturing_in_templates.cpp3
-rw-r--r--test/OpenMP/constexpr_codegen.cpp29
-rw-r--r--test/OpenMP/critical_ast_print.cpp8
-rw-r--r--test/OpenMP/critical_codegen.cpp6
-rw-r--r--test/OpenMP/critical_messages.cpp2
-rw-r--r--test/OpenMP/debug-info-openmp-array.cpp3
-rw-r--r--test/OpenMP/declare_reduction_ast_print.c6
-rw-r--r--test/OpenMP/declare_reduction_ast_print.cpp6
-rw-r--r--test/OpenMP/declare_reduction_codegen.c5
-rw-r--r--test/OpenMP/declare_reduction_codegen.cpp13
-rw-r--r--test/OpenMP/declare_reduction_messages.c2
-rw-r--r--test/OpenMP/declare_reduction_messages.cpp4
-rw-r--r--test/OpenMP/declare_simd_ast_print.c12
-rw-r--r--test/OpenMP/declare_simd_ast_print.cpp8
-rw-r--r--test/OpenMP/declare_simd_codegen.cpp9
-rw-r--r--test/OpenMP/declare_simd_messages.cpp2
-rw-r--r--test/OpenMP/declare_target_ast_print.cpp44
-rw-r--r--test/OpenMP/declare_target_codegen.cpp94
-rw-r--r--test/OpenMP/declare_target_codegen_globalization.cpp43
-rw-r--r--test/OpenMP/declare_target_link_codegen.cpp69
-rw-r--r--test/OpenMP/declare_target_messages.cpp39
-rw-r--r--test/OpenMP/distribute_ast_print.cpp6
-rw-r--r--test/OpenMP/distribute_codegen.cpp36
-rw-r--r--test/OpenMP/distribute_collapse_messages.cpp4
-rw-r--r--test/OpenMP/distribute_dist_schedule_ast_print.cpp6
-rw-r--r--test/OpenMP/distribute_dist_schedule_messages.cpp2
-rw-r--r--test/OpenMP/distribute_firstprivate_codegen.cpp28
-rw-r--r--test/OpenMP/distribute_firstprivate_messages.cpp2
-rw-r--r--test/OpenMP/distribute_lastprivate_codegen.cpp32
-rw-r--r--test/OpenMP/distribute_parallel_for_ast_print.cpp6
-rw-r--r--test/OpenMP/distribute_parallel_for_codegen.cpp16
-rw-r--r--test/OpenMP/distribute_parallel_for_collapse_messages.cpp4
-rw-r--r--test/OpenMP/distribute_parallel_for_copyin_messages.cpp2
-rw-r--r--test/OpenMP/distribute_parallel_for_default_messages.cpp2
-rw-r--r--test/OpenMP/distribute_parallel_for_dist_schedule_messages.cpp2
-rw-r--r--test/OpenMP/distribute_parallel_for_firstprivate_codegen.cpp31
-rw-r--r--test/OpenMP/distribute_parallel_for_firstprivate_messages.cpp2
-rw-r--r--test/OpenMP/distribute_parallel_for_if_codegen.cpp5
-rw-r--r--test/OpenMP/distribute_parallel_for_if_messages.cpp2
-rw-r--r--test/OpenMP/distribute_parallel_for_lastprivate_codegen.cpp44
-rw-r--r--test/OpenMP/distribute_parallel_for_lastprivate_messages.cpp2
-rw-r--r--test/OpenMP/distribute_parallel_for_messages.cpp2
-rw-r--r--test/OpenMP/distribute_parallel_for_num_threads_codegen.cpp5
-rw-r--r--test/OpenMP/distribute_parallel_for_num_threads_messages.cpp2
-rw-r--r--test/OpenMP/distribute_parallel_for_private_codegen.cpp16
-rw-r--r--test/OpenMP/distribute_parallel_for_private_messages.cpp2
-rw-r--r--test/OpenMP/distribute_parallel_for_proc_bind_codegen.cpp11
-rw-r--r--test/OpenMP/distribute_parallel_for_proc_bind_messages.cpp2
-rw-r--r--test/OpenMP/distribute_parallel_for_reduction_codegen.cpp84
-rw-r--r--test/OpenMP/distribute_parallel_for_reduction_messages.cpp4
-rw-r--r--test/OpenMP/distribute_parallel_for_schedule_messages.cpp2
-rw-r--r--test/OpenMP/distribute_parallel_for_shared_messages.cpp2
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_aligned_messages.cpp2
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_ast_print.cpp6
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_codegen.cpp16
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_collapse_messages.cpp4
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_copyin_messages.cpp2
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_default_messages.cpp2
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_dist_schedule_messages.cpp2
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_firstprivate_codegen.cpp31
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_firstprivate_messages.cpp2
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_if_codegen.cpp5
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_if_messages.cpp2
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_lastprivate_codegen.cpp44
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_lastprivate_messages.cpp2
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_linear_messages.cpp2
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_loop_messages.cpp2
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_misc_messages.c2
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_num_threads_codegen.cpp5
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_num_threads_messages.cpp2
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_private_codegen.cpp16
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_private_messages.cpp2
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_proc_bind_codegen.cpp11
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_proc_bind_messages.cpp2
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_reduction_messages.cpp4
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_safelen_messages.cpp4
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_schedule_messages.cpp2
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_shared_messages.cpp2
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_simdlen_messages.cpp3
-rw-r--r--test/OpenMP/distribute_private_codegen.cpp16
-rw-r--r--test/OpenMP/distribute_private_messages.cpp2
-rw-r--r--test/OpenMP/distribute_simd_aligned_messages.cpp2
-rw-r--r--test/OpenMP/distribute_simd_ast_print.cpp6
-rw-r--r--test/OpenMP/distribute_simd_codegen.cpp36
-rw-r--r--test/OpenMP/distribute_simd_collapse_messages.cpp4
-rw-r--r--test/OpenMP/distribute_simd_dist_schedule_messages.cpp2
-rw-r--r--test/OpenMP/distribute_simd_firstprivate_codegen.cpp28
-rw-r--r--test/OpenMP/distribute_simd_firstprivate_messages.cpp2
-rw-r--r--test/OpenMP/distribute_simd_lastprivate_codegen.cpp32
-rw-r--r--test/OpenMP/distribute_simd_lastprivate_messages.cpp2
-rw-r--r--test/OpenMP/distribute_simd_linear_messages.cpp2
-rw-r--r--test/OpenMP/distribute_simd_loop_messages.cpp6
-rw-r--r--test/OpenMP/distribute_simd_misc_messages.c2
-rw-r--r--test/OpenMP/distribute_simd_private_codegen.cpp16
-rw-r--r--test/OpenMP/distribute_simd_private_messages.cpp2
-rw-r--r--test/OpenMP/distribute_simd_reduction_codegen.cpp13
-rw-r--r--test/OpenMP/distribute_simd_reduction_messages.cpp4
-rw-r--r--test/OpenMP/distribute_simd_safelen_messages.cpp4
-rw-r--r--test/OpenMP/distribute_simd_simdlen_messages.cpp4
-rw-r--r--test/OpenMP/driver.c17
-rw-r--r--test/OpenMP/dump.cpp44
-rw-r--r--test/OpenMP/flush_ast_print.cpp6
-rw-r--r--test/OpenMP/flush_codegen.cpp7
-rw-r--r--test/OpenMP/flush_messages.cpp2
-rw-r--r--test/OpenMP/for_ast_print.cpp6
-rw-r--r--test/OpenMP/for_codegen.cpp31
-rw-r--r--test/OpenMP/for_collapse_messages.cpp4
-rw-r--r--test/OpenMP/for_firstprivate_codegen.cpp11
-rw-r--r--test/OpenMP/for_firstprivate_messages.cpp1
-rw-r--r--test/OpenMP/for_lastprivate_codegen.cpp11
-rw-r--r--test/OpenMP/for_lastprivate_messages.cpp2
-rw-r--r--test/OpenMP/for_linear_codegen.cpp7
-rw-r--r--test/OpenMP/for_linear_messages.cpp2
-rw-r--r--test/OpenMP/for_loop_messages.cpp2
-rw-r--r--test/OpenMP/for_misc_messages.c16
-rw-r--r--test/OpenMP/for_ordered_clause.cpp5
-rw-r--r--test/OpenMP/for_private_codegen.cpp11
-rw-r--r--test/OpenMP/for_private_messages.cpp2
-rw-r--r--test/OpenMP/for_reduction_codegen.cpp51
-rw-r--r--test/OpenMP/for_reduction_codegen_UDR.cpp9
-rw-r--r--test/OpenMP/for_reduction_messages.cpp4
-rw-r--r--test/OpenMP/for_schedule_messages.cpp2
-rw-r--r--test/OpenMP/for_simd_aligned_messages.cpp2
-rw-r--r--test/OpenMP/for_simd_ast_print.cpp6
-rw-r--r--test/OpenMP/for_simd_codegen.cpp69
-rw-r--r--test/OpenMP/for_simd_collapse_messages.cpp4
-rw-r--r--test/OpenMP/for_simd_firstprivate_messages.cpp2
-rw-r--r--test/OpenMP/for_simd_lastprivate_messages.cpp2
-rw-r--r--test/OpenMP/for_simd_linear_messages.cpp2
-rw-r--r--test/OpenMP/for_simd_loop_messages.cpp2
-rw-r--r--test/OpenMP/for_simd_misc_messages.c2
-rw-r--r--test/OpenMP/for_simd_private_messages.cpp2
-rw-r--r--test/OpenMP/for_simd_reduction_messages.cpp4
-rw-r--r--test/OpenMP/for_simd_safelen_messages.cpp4
-rw-r--r--test/OpenMP/for_simd_schedule_messages.cpp2
-rw-r--r--test/OpenMP/for_simd_simdlen_messages.cpp4
-rw-r--r--test/OpenMP/function-attr.cpp3
-rw-r--r--test/OpenMP/is_initial_device.c5
-rw-r--r--test/OpenMP/linking.c20
-rw-r--r--test/OpenMP/loops_explicit_clauses_codegen.cpp5
-rw-r--r--test/OpenMP/master_ast_print.cpp6
-rw-r--r--test/OpenMP/master_codegen.cpp6
-rw-r--r--test/OpenMP/master_messages.cpp2
-rw-r--r--test/OpenMP/nesting_of_regions.cpp3
-rw-r--r--test/OpenMP/no_option.c3
-rw-r--r--test/OpenMP/no_option_no_warn.c3
-rw-r--r--test/OpenMP/nvptx_data_sharing.cpp95
-rw-r--r--test/OpenMP/nvptx_declare_target_var_ctor_dtor_codegen.cpp111
-rw-r--r--test/OpenMP/nvptx_distribute_parallel_generic_mode_codegen.cpp51
-rw-r--r--test/OpenMP/nvptx_parallel_codegen.cpp507
-rw-r--r--test/OpenMP/nvptx_target_codegen.cpp119
-rw-r--r--test/OpenMP/nvptx_target_cuda_mode_messages.cpp108
-rw-r--r--test/OpenMP/nvptx_target_exceptions_messages.cpp71
-rw-r--r--test/OpenMP/nvptx_target_firstprivate_codegen.cpp18
-rw-r--r--test/OpenMP/nvptx_target_parallel_codegen.cpp17
-rw-r--r--test/OpenMP/nvptx_target_parallel_num_threads_codegen.cpp52
-rw-r--r--test/OpenMP/nvptx_target_parallel_proc_bind_codegen.cpp19
-rw-r--r--test/OpenMP/nvptx_target_parallel_reduction_codegen.cpp67
-rw-r--r--test/OpenMP/nvptx_target_printf_codegen.c10
-rw-r--r--test/OpenMP/nvptx_target_simd_codegen.cpp87
-rw-r--r--test/OpenMP/nvptx_target_teams_codegen.cpp62
-rw-r--r--test/OpenMP/nvptx_target_teams_distribute_parallel_for_codegen.cpp136
-rw-r--r--test/OpenMP/nvptx_target_teams_distribute_parallel_for_generic_mode_codegen.cpp66
-rw-r--r--test/OpenMP/nvptx_target_teams_distribute_parallel_for_simd_codegen.cpp127
-rw-r--r--test/OpenMP/nvptx_target_teams_distribute_simd_codegen.cpp95
-rw-r--r--test/OpenMP/nvptx_teams_codegen.cpp36
-rw-r--r--test/OpenMP/nvptx_teams_reduction_codegen.cpp177
-rw-r--r--test/OpenMP/openmp_check.cpp11
-rw-r--r--test/OpenMP/openmp_common.c3
-rw-r--r--test/OpenMP/openmp_offload_codegen.cpp12
-rw-r--r--test/OpenMP/openmp_seh.c3
-rw-r--r--test/OpenMP/openmp_win_codegen.cpp35
-rw-r--r--test/OpenMP/option_warn.c3
-rw-r--r--test/OpenMP/ordered_ast_print.cpp6
-rw-r--r--test/OpenMP/ordered_codegen.cpp5
-rw-r--r--test/OpenMP/ordered_doacross_codegen.c61
-rw-r--r--test/OpenMP/ordered_doacross_codegen.cpp9
-rw-r--r--test/OpenMP/ordered_messages.cpp6
-rw-r--r--test/OpenMP/parallel_ast_print.cpp6
-rw-r--r--test/OpenMP/parallel_codegen.cpp45
-rw-r--r--test/OpenMP/parallel_copyin_codegen.cpp48
-rw-r--r--test/OpenMP/parallel_copyin_messages.cpp2
-rw-r--r--test/OpenMP/parallel_default_messages.cpp2
-rw-r--r--test/OpenMP/parallel_firstprivate_codegen.cpp25
-rw-r--r--test/OpenMP/parallel_firstprivate_messages.cpp2
-rw-r--r--test/OpenMP/parallel_for_ast_print.cpp6
-rw-r--r--test/OpenMP/parallel_for_codegen.cpp13
-rw-r--r--test/OpenMP/parallel_for_collapse_messages.cpp4
-rw-r--r--test/OpenMP/parallel_for_copyin_messages.cpp2
-rw-r--r--test/OpenMP/parallel_for_default_messages.cpp2
-rw-r--r--test/OpenMP/parallel_for_firstprivate_messages.cpp2
-rw-r--r--test/OpenMP/parallel_for_if_messages.cpp2
-rw-r--r--test/OpenMP/parallel_for_lastprivate_messages.cpp2
-rw-r--r--test/OpenMP/parallel_for_linear_codegen.cpp7
-rw-r--r--test/OpenMP/parallel_for_linear_messages.cpp2
-rw-r--r--test/OpenMP/parallel_for_loop_messages.cpp2
-rw-r--r--test/OpenMP/parallel_for_messages.cpp2
-rw-r--r--test/OpenMP/parallel_for_misc_messages.c2
-rw-r--r--test/OpenMP/parallel_for_num_threads_messages.cpp2
-rw-r--r--test/OpenMP/parallel_for_ordered_messages.cpp4
-rw-r--r--test/OpenMP/parallel_for_private_messages.cpp2
-rw-r--r--test/OpenMP/parallel_for_proc_bind_messages.cpp2
-rw-r--r--test/OpenMP/parallel_for_reduction_messages.cpp4
-rw-r--r--test/OpenMP/parallel_for_schedule_messages.cpp2
-rw-r--r--test/OpenMP/parallel_for_simd_aligned_messages.cpp2
-rw-r--r--test/OpenMP/parallel_for_simd_ast_print.cpp6
-rw-r--r--test/OpenMP/parallel_for_simd_codegen.cpp67
-rw-r--r--test/OpenMP/parallel_for_simd_collapse_messages.cpp4
-rw-r--r--test/OpenMP/parallel_for_simd_copyin_messages.cpp2
-rw-r--r--test/OpenMP/parallel_for_simd_default_messages.cpp2
-rw-r--r--test/OpenMP/parallel_for_simd_firstprivate_messages.cpp2
-rw-r--r--test/OpenMP/parallel_for_simd_if_messages.cpp2
-rw-r--r--test/OpenMP/parallel_for_simd_lastprivate_messages.cpp2
-rw-r--r--test/OpenMP/parallel_for_simd_linear_messages.cpp2
-rw-r--r--test/OpenMP/parallel_for_simd_loop_messages.cpp2
-rw-r--r--test/OpenMP/parallel_for_simd_messages.cpp2
-rw-r--r--test/OpenMP/parallel_for_simd_misc_messages.c2
-rw-r--r--test/OpenMP/parallel_for_simd_num_threads_messages.cpp2
-rw-r--r--test/OpenMP/parallel_for_simd_private_messages.cpp2
-rw-r--r--test/OpenMP/parallel_for_simd_proc_bind_messages.cpp2
-rw-r--r--test/OpenMP/parallel_for_simd_reduction_messages.cpp4
-rw-r--r--test/OpenMP/parallel_for_simd_safelen_messages.cpp4
-rw-r--r--test/OpenMP/parallel_for_simd_schedule_messages.cpp2
-rw-r--r--test/OpenMP/parallel_for_simd_simdlen_messages.cpp4
-rw-r--r--test/OpenMP/parallel_if_codegen.cpp25
-rw-r--r--test/OpenMP/parallel_if_messages.cpp2
-rw-r--r--test/OpenMP/parallel_messages.cpp4
-rw-r--r--test/OpenMP/parallel_num_threads_codegen.cpp5
-rw-r--r--test/OpenMP/parallel_num_threads_messages.cpp2
-rw-r--r--test/OpenMP/parallel_private_codegen.cpp11
-rw-r--r--test/OpenMP/parallel_private_messages.cpp2
-rw-r--r--test/OpenMP/parallel_proc_bind_codegen.cpp11
-rw-r--r--test/OpenMP/parallel_proc_bind_messages.cpp2
-rw-r--r--test/OpenMP/parallel_reduction_codegen.cpp31
-rw-r--r--test/OpenMP/parallel_reduction_messages.c11
-rw-r--r--test/OpenMP/parallel_reduction_messages.cpp4
-rw-r--r--test/OpenMP/parallel_sections_ast_print.cpp6
-rw-r--r--test/OpenMP/parallel_sections_codegen.cpp5
-rw-r--r--test/OpenMP/parallel_sections_copyin_messages.cpp2
-rw-r--r--test/OpenMP/parallel_sections_default_messages.cpp2
-rw-r--r--test/OpenMP/parallel_sections_firstprivate_messages.cpp2
-rw-r--r--test/OpenMP/parallel_sections_if_messages.cpp2
-rw-r--r--test/OpenMP/parallel_sections_lastprivate_messages.cpp2
-rw-r--r--test/OpenMP/parallel_sections_messages.cpp2
-rw-r--r--test/OpenMP/parallel_sections_misc_messages.c2
-rw-r--r--test/OpenMP/parallel_sections_num_threads_messages.cpp2
-rw-r--r--test/OpenMP/parallel_sections_private_messages.cpp2
-rw-r--r--test/OpenMP/parallel_sections_proc_bind_messages.cpp2
-rw-r--r--test/OpenMP/parallel_sections_reduction_messages.cpp4
-rw-r--r--test/OpenMP/parallel_sections_shared_messages.cpp2
-rw-r--r--test/OpenMP/parallel_shared_messages.cpp2
-rw-r--r--test/OpenMP/predefined_macro.c3
-rw-r--r--test/OpenMP/report_default_DSA.cpp2
-rw-r--r--test/OpenMP/schedule_codegen.cpp3
-rw-r--r--test/OpenMP/sections_ast_print.cpp8
-rw-r--r--test/OpenMP/sections_codegen.cpp5
-rw-r--r--test/OpenMP/sections_firstprivate_codegen.cpp11
-rw-r--r--test/OpenMP/sections_firstprivate_messages.cpp2
-rw-r--r--test/OpenMP/sections_lastprivate_codegen.cpp9
-rw-r--r--test/OpenMP/sections_lastprivate_messages.cpp2
-rw-r--r--test/OpenMP/sections_misc_messages.c2
-rw-r--r--test/OpenMP/sections_private_codegen.cpp11
-rw-r--r--test/OpenMP/sections_private_messages.cpp2
-rw-r--r--test/OpenMP/sections_reduction_codegen.cpp27
-rw-r--r--test/OpenMP/sections_reduction_messages.cpp4
-rw-r--r--test/OpenMP/simd_aligned_messages.cpp2
-rw-r--r--test/OpenMP/simd_ast_print.cpp8
-rw-r--r--test/OpenMP/simd_codegen.cpp47
-rw-r--r--test/OpenMP/simd_collapse_messages.cpp4
-rw-r--r--test/OpenMP/simd_lastprivate_messages.cpp2
-rw-r--r--test/OpenMP/simd_linear_messages.cpp2
-rw-r--r--test/OpenMP/simd_loop_messages.cpp6
-rw-r--r--test/OpenMP/simd_metadata.c9
-rw-r--r--test/OpenMP/simd_misc_messages.c2
-rw-r--r--test/OpenMP/simd_private_messages.cpp2
-rw-r--r--test/OpenMP/simd_reduction_messages.cpp4
-rw-r--r--test/OpenMP/simd_safelen_messages.cpp4
-rw-r--r--test/OpenMP/simd_simdlen_messages.cpp4
-rw-r--r--test/OpenMP/single_ast_print.cpp6
-rw-r--r--test/OpenMP/single_codegen.cpp11
-rw-r--r--test/OpenMP/single_copyprivate_messages.cpp2
-rw-r--r--test/OpenMP/single_firstprivate_codegen.cpp11
-rw-r--r--test/OpenMP/single_firstprivate_messages.cpp2
-rw-r--r--test/OpenMP/single_misc_messages.c2
-rw-r--r--test/OpenMP/single_private_codegen.cpp11
-rw-r--r--test/OpenMP/single_private_messages.cpp2
-rw-r--r--test/OpenMP/target_ast_print.cpp6
-rw-r--r--test/OpenMP/target_codegen.cpp184
-rw-r--r--test/OpenMP/target_codegen_global_capture.cpp18
-rw-r--r--test/OpenMP/target_codegen_registration.cpp199
-rw-r--r--test/OpenMP/target_codegen_registration_naming.cpp18
-rw-r--r--test/OpenMP/target_data_ast_print.cpp6
-rw-r--r--test/OpenMP/target_data_codegen.cpp50
-rw-r--r--test/OpenMP/target_data_device_messages.cpp2
-rw-r--r--test/OpenMP/target_data_if_messages.cpp2
-rw-r--r--test/OpenMP/target_data_messages.c2
-rw-r--r--test/OpenMP/target_data_use_device_ptr_ast_print.cpp5
-rw-r--r--test/OpenMP/target_data_use_device_ptr_codegen.cpp72
-rw-r--r--test/OpenMP/target_data_use_device_ptr_messages.cpp2
-rw-r--r--test/OpenMP/target_defaultmap_messages.cpp2
-rw-r--r--test/OpenMP/target_depend_codegen.cpp261
-rw-r--r--test/OpenMP/target_depend_messages.cpp2
-rw-r--r--test/OpenMP/target_device_messages.cpp2
-rw-r--r--test/OpenMP/target_enter_data_ast_print.cpp6
-rw-r--r--test/OpenMP/target_enter_data_codegen.cpp56
-rw-r--r--test/OpenMP/target_enter_data_depend_codegen.cpp93
-rw-r--r--test/OpenMP/target_enter_data_depend_messages.cpp2
-rw-r--r--test/OpenMP/target_enter_data_device_messages.cpp2
-rw-r--r--test/OpenMP/target_enter_data_if_messages.cpp2
-rw-r--r--test/OpenMP/target_enter_data_map_messages.c3
-rw-r--r--test/OpenMP/target_enter_data_nowait_messages.cpp2
-rw-r--r--test/OpenMP/target_exit_data_ast_print.cpp6
-rw-r--r--test/OpenMP/target_exit_data_codegen.cpp38
-rw-r--r--test/OpenMP/target_exit_data_depend_codegen.cpp93
-rw-r--r--test/OpenMP/target_exit_data_depend_messages.cpp2
-rw-r--r--test/OpenMP/target_exit_data_device_messages.cpp2
-rw-r--r--test/OpenMP/target_exit_data_if_messages.cpp2
-rw-r--r--test/OpenMP/target_exit_data_map_messages.c3
-rw-r--r--test/OpenMP/target_exit_data_nowait_messages.cpp2
-rw-r--r--test/OpenMP/target_firstprivate_codegen.cpp114
-rw-r--r--test/OpenMP/target_firstprivate_messages.cpp4
-rw-r--r--test/OpenMP/target_if_messages.cpp2
-rw-r--r--test/OpenMP/target_is_device_ptr_ast_print.cpp6
-rw-r--r--test/OpenMP/target_is_device_ptr_codegen.cpp81
-rw-r--r--test/OpenMP/target_is_device_ptr_messages.cpp2
-rw-r--r--test/OpenMP/target_map_codegen.cpp1366
-rw-r--r--test/OpenMP/target_map_messages.cpp29
-rw-r--r--test/OpenMP/target_messages.cpp23
-rw-r--r--test/OpenMP/target_nowait_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_ast_print.cpp6
-rw-r--r--test/OpenMP/target_parallel_codegen.cpp169
-rw-r--r--test/OpenMP/target_parallel_codegen_registration.cpp199
-rw-r--r--test/OpenMP/target_parallel_codegen_registration_naming.cpp18
-rw-r--r--test/OpenMP/target_parallel_debug_codegen.cpp31
-rw-r--r--test/OpenMP/target_parallel_default_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_defaultmap_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_depend_codegen.cpp261
-rw-r--r--test/OpenMP/target_parallel_depend_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_device_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_firstprivate_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_ast_print.cpp12
-rw-r--r--test/OpenMP/target_parallel_for_codegen.cpp173
-rw-r--r--test/OpenMP/target_parallel_for_codegen_registration.cpp199
-rw-r--r--test/OpenMP/target_parallel_for_codegen_registration_naming.cpp18
-rw-r--r--test/OpenMP/target_parallel_for_collapse_messages.cpp4
-rw-r--r--test/OpenMP/target_parallel_for_debug_codegen.cpp22
-rw-r--r--test/OpenMP/target_parallel_for_default_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_defaultmap_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_depend_codegen.cpp261
-rw-r--r--test/OpenMP/target_parallel_for_depend_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_device_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_firstprivate_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_if_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_is_device_ptr_ast_print.cpp6
-rw-r--r--test/OpenMP/target_parallel_for_is_device_ptr_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_lastprivate_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_linear_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_loop_messages.cpp4
-rw-r--r--test/OpenMP/target_parallel_for_map_messages.cpp4
-rw-r--r--test/OpenMP/target_parallel_for_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_misc_messages.c2
-rw-r--r--test/OpenMP/target_parallel_for_nowait_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_num_threads_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_ordered_messages.cpp4
-rw-r--r--test/OpenMP/target_parallel_for_private_messages.cpp4
-rw-r--r--test/OpenMP/target_parallel_for_proc_bind_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_reduction_messages.cpp4
-rw-r--r--test/OpenMP/target_parallel_for_schedule_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_simd_aligned_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_simd_ast_print.cpp12
-rw-r--r--test/OpenMP/target_parallel_for_simd_codegen.cpp169
-rw-r--r--test/OpenMP/target_parallel_for_simd_codegen_registration.cpp199
-rw-r--r--test/OpenMP/target_parallel_for_simd_codegen_registration_naming.cpp18
-rw-r--r--test/OpenMP/target_parallel_for_simd_collapse_messages.cpp4
-rw-r--r--test/OpenMP/target_parallel_for_simd_default_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_simd_defaultmap_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_simd_depend_codegen.cpp261
-rw-r--r--test/OpenMP/target_parallel_for_simd_depend_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_simd_device_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_simd_firstprivate_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_simd_if_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_simd_is_device_ptr_ast_print.cpp6
-rw-r--r--test/OpenMP/target_parallel_for_simd_is_device_ptr_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_simd_lastprivate_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_simd_linear_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_simd_loop_messages.cpp4
-rw-r--r--test/OpenMP/target_parallel_for_simd_map_messages.cpp4
-rw-r--r--test/OpenMP/target_parallel_for_simd_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_simd_misc_messages.c2
-rw-r--r--test/OpenMP/target_parallel_for_simd_nowait_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_simd_num_threads_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_simd_ordered_messages.cpp4
-rw-r--r--test/OpenMP/target_parallel_for_simd_private_messages.cpp4
-rw-r--r--test/OpenMP/target_parallel_for_simd_proc_bind_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_simd_reduction_messages.cpp4
-rw-r--r--test/OpenMP/target_parallel_for_simd_safelen_messages.cpp4
-rw-r--r--test/OpenMP/target_parallel_for_simd_schedule_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_simd_simdlen_messages.cpp4
-rw-r--r--test/OpenMP/target_parallel_if_codegen.cpp62
-rw-r--r--test/OpenMP/target_parallel_if_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_is_device_ptr_ast_print.cpp6
-rw-r--r--test/OpenMP/target_parallel_is_device_ptr_messages.cpp4
-rw-r--r--test/OpenMP/target_parallel_map_messages.cpp4
-rw-r--r--test/OpenMP/target_parallel_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_nowait_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_num_threads_codegen.cpp76
-rw-r--r--test/OpenMP/target_parallel_num_threads_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_private_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_proc_bind_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_reduction_messages.cpp4
-rw-r--r--test/OpenMP/target_parallel_shared_messages.cpp2
-rw-r--r--test/OpenMP/target_private_codegen.cpp34
-rw-r--r--test/OpenMP/target_private_messages.cpp4
-rw-r--r--test/OpenMP/target_reduction_codegen.cpp22
-rw-r--r--test/OpenMP/target_reduction_messages.cpp4
-rw-r--r--test/OpenMP/target_simd_aligned_messages.cpp2
-rw-r--r--test/OpenMP/target_simd_ast_print.cpp12
-rw-r--r--test/OpenMP/target_simd_codegen.cpp149
-rw-r--r--test/OpenMP/target_simd_codegen_registration.cpp199
-rw-r--r--test/OpenMP/target_simd_codegen_registration_naming.cpp18
-rw-r--r--test/OpenMP/target_simd_collapse_messages.cpp3
-rw-r--r--test/OpenMP/target_simd_defaultmap_messages.cpp2
-rw-r--r--test/OpenMP/target_simd_depend_codegen.cpp261
-rw-r--r--test/OpenMP/target_simd_depend_messages.cpp2
-rw-r--r--test/OpenMP/target_simd_device_messages.cpp2
-rw-r--r--test/OpenMP/target_simd_firstprivate_messages.cpp2
-rw-r--r--test/OpenMP/target_simd_if_messages.cpp2
-rw-r--r--test/OpenMP/target_simd_is_device_ptr_messages.cpp2
-rw-r--r--test/OpenMP/target_simd_lastprivate_messages.cpp2
-rw-r--r--test/OpenMP/target_simd_linear_messages.cpp2
-rw-r--r--test/OpenMP/target_simd_loop_messages.cpp4
-rw-r--r--test/OpenMP/target_simd_map_messages.cpp4
-rw-r--r--test/OpenMP/target_simd_messages.cpp2
-rw-r--r--test/OpenMP/target_simd_misc_messages.c2
-rw-r--r--test/OpenMP/target_simd_nowait_messages.cpp2
-rw-r--r--test/OpenMP/target_simd_private_messages.cpp4
-rw-r--r--test/OpenMP/target_simd_reduction_messages.cpp4
-rw-r--r--test/OpenMP/target_simd_safelen_messages.cpp4
-rw-r--r--test/OpenMP/target_simd_simdlen_messages.cpp4
-rw-r--r--test/OpenMP/target_teams_ast_print.cpp6
-rw-r--r--test/OpenMP/target_teams_codegen.cpp174
-rw-r--r--test/OpenMP/target_teams_codegen_registration.cpp199
-rw-r--r--test/OpenMP/target_teams_codegen_registration_naming.cpp18
-rw-r--r--test/OpenMP/target_teams_default_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_defaultmap_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_depend_codegen.cpp261
-rw-r--r--test/OpenMP/target_teams_depend_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_device_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_ast_print.cpp12
-rw-r--r--test/OpenMP/target_teams_distribute_codegen.cpp253
-rw-r--r--test/OpenMP/target_teams_distribute_codegen_registration.cpp199
-rw-r--r--test/OpenMP/target_teams_distribute_codegen_registration_naming.cpp18
-rw-r--r--test/OpenMP/target_teams_distribute_collapse_codegen.cpp16
-rw-r--r--test/OpenMP/target_teams_distribute_collapse_messages.cpp4
-rw-r--r--test/OpenMP/target_teams_distribute_default_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_defaultmap_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_depend_codegen.cpp261
-rw-r--r--test/OpenMP/target_teams_distribute_depend_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_device_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_dist_schedule_codegen.cpp16
-rw-r--r--test/OpenMP/target_teams_distribute_dist_schedule_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_firstprivate_codegen.cpp60
-rw-r--r--test/OpenMP/target_teams_distribute_firstprivate_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_if_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_lastprivate_codegen.cpp32
-rw-r--r--test/OpenMP/target_teams_distribute_lastprivate_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_loop_messages.cpp4
-rw-r--r--test/OpenMP/target_teams_distribute_map_messages.cpp4
-rw-r--r--test/OpenMP/target_teams_distribute_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_misc_messages.c2
-rw-r--r--test/OpenMP/target_teams_distribute_nowait_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_num_teams_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_ast_print.cpp12
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_codegen.cpp118
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_collapse_codegen.cpp157
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_collapse_messages.cpp4
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_default_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_defaultmap_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_depend_codegen.cpp261
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_depend_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_device_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_dist_schedule_codegen.cpp270
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_dist_schedule_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_firstprivate_codegen.cpp523
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_firstprivate_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_if_codegen.cpp181
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_if_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_is_device_ptr_ast_print.cpp6
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_is_device_ptr_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_lastprivate_codegen.cpp454
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_lastprivate_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_loop_messages.cpp4
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_map_messages.cpp4
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_misc_messages.c2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_nowait_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_num_teams_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_num_threads_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_private_codegen.cpp369
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_private_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_proc_bind_codegen.cpp93
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_proc_bind_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_reduction_codegen.cpp353
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_reduction_messages.cpp4
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_schedule_codegen.cpp400
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_schedule_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_shared_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_aligned_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_ast_print.cpp12
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_codegen.cpp131
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_codegen_registration.cpp472
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_codegen_registration_naming.cpp86
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_collapse_codegen.cpp157
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_collapse_messages.cpp4
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_default_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_defaultmap_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_depend_codegen.cpp261
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_depend_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_device_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_dist_schedule_codegen.cpp270
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_dist_schedule_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_firstprivate_codegen.cpp523
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_firstprivate_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_if_codegen.cpp181
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_if_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_is_device_ptr_ast_print.cpp6
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_is_device_ptr_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_codegen.cpp456
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_linear_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_loop_messages.cpp4
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_map_messages.cpp4
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_misc_messages.c2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_nowait_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_num_teams_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_num_threads_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_private_codegen.cpp369
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_private_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_proc_bind_codegen.cpp93
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_proc_bind_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_reduction_codegen.cpp353
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_reduction_messages.cpp4
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_safelen_messages.cpp4
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_schedule_codegen.cpp400
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_schedule_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_shared_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_simdlen_messages.cpp4
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_thread_limit_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_thread_limit_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_private_codegen.cpp25
-rw-r--r--test/OpenMP/target_teams_distribute_private_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_reduction_codegen.cpp13
-rw-r--r--test/OpenMP/target_teams_distribute_reduction_messages.cpp4
-rw-r--r--test/OpenMP/target_teams_distribute_shared_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_simd_aligned_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_simd_ast_print.cpp12
-rw-r--r--test/OpenMP/target_teams_distribute_simd_codegen.cpp174
-rw-r--r--test/OpenMP/target_teams_distribute_simd_codegen_registration.cpp199
-rw-r--r--test/OpenMP/target_teams_distribute_simd_codegen_registration_naming.cpp18
-rw-r--r--test/OpenMP/target_teams_distribute_simd_collapse_codegen.cpp16
-rw-r--r--test/OpenMP/target_teams_distribute_simd_collapse_messages.cpp4
-rw-r--r--test/OpenMP/target_teams_distribute_simd_defaultmap_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_simd_depend_codegen.cpp261
-rw-r--r--test/OpenMP/target_teams_distribute_simd_depend_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_simd_device_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_simd_dist_schedule_codegen.cpp16
-rw-r--r--test/OpenMP/target_teams_distribute_simd_dist_schedule_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_simd_firstprivate_codegen.cpp60
-rw-r--r--test/OpenMP/target_teams_distribute_simd_firstprivate_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_simd_if_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_simd_is_device_ptr_ast_print.cpp6
-rw-r--r--test/OpenMP/target_teams_distribute_simd_is_device_ptr_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_simd_lastprivate_codegen.cpp32
-rw-r--r--test/OpenMP/target_teams_distribute_simd_lastprivate_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_simd_linear_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_simd_loop_messages.cpp4
-rw-r--r--test/OpenMP/target_teams_distribute_simd_map_messages.cpp4
-rw-r--r--test/OpenMP/target_teams_distribute_simd_messages.cpp4
-rw-r--r--test/OpenMP/target_teams_distribute_simd_misc_messages.c2
-rw-r--r--test/OpenMP/target_teams_distribute_simd_nowait_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_simd_num_teams_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_simd_private_codegen.cpp25
-rw-r--r--test/OpenMP/target_teams_distribute_simd_private_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_simd_reduction_codegen.cpp13
-rw-r--r--test/OpenMP/target_teams_distribute_simd_reduction_messages.cpp4
-rw-r--r--test/OpenMP/target_teams_distribute_simd_safelen_messages.cpp4
-rw-r--r--test/OpenMP/target_teams_distribute_simd_shared_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_simd_simdlen_messages.cpp4
-rw-r--r--test/OpenMP/target_teams_distribute_simd_thread_limit_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_firstprivate_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_if_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_is_device_ptr_ast_print.cpp6
-rw-r--r--test/OpenMP/target_teams_is_device_ptr_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_map_messages.cpp18
-rw-r--r--test/OpenMP/target_teams_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_nowait_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_num_teams_codegen.cpp76
-rw-r--r--test/OpenMP/target_teams_num_teams_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_private_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_reduction_messages.cpp4
-rw-r--r--test/OpenMP/target_teams_shared_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_thread_limit_codegen.cpp76
-rw-r--r--test/OpenMP/target_teams_thread_limit_messages.cpp2
-rw-r--r--test/OpenMP/target_update_ast_print.cpp6
-rw-r--r--test/OpenMP/target_update_codegen.cpp55
-rw-r--r--test/OpenMP/target_update_depend_codegen.cpp93
-rw-r--r--test/OpenMP/target_update_depend_messages.cpp2
-rw-r--r--test/OpenMP/target_update_device_messages.cpp2
-rw-r--r--test/OpenMP/target_update_from_messages.cpp4
-rw-r--r--test/OpenMP/target_update_if_messages.cpp2
-rw-r--r--test/OpenMP/target_update_messages.cpp2
-rw-r--r--test/OpenMP/target_update_nowait_messages.cpp2
-rw-r--r--test/OpenMP/target_update_to_messages.cpp4
-rw-r--r--test/OpenMP/target_vla_messages.cpp9
-rw-r--r--test/OpenMP/task_ast_print.cpp6
-rw-r--r--test/OpenMP/task_codegen.c5
-rw-r--r--test/OpenMP/task_codegen.cpp9
-rw-r--r--test/OpenMP/task_default_messages.cpp2
-rw-r--r--test/OpenMP/task_depend_messages.cpp2
-rw-r--r--test/OpenMP/task_final_messages.cpp2
-rw-r--r--test/OpenMP/task_firstprivate_codegen.cpp12
-rw-r--r--test/OpenMP/task_firstprivate_messages.cpp2
-rw-r--r--test/OpenMP/task_if_codegen.cpp5
-rw-r--r--test/OpenMP/task_if_messages.cpp2
-rw-r--r--test/OpenMP/task_in_reduction_codegen.cpp21
-rw-r--r--test/OpenMP/task_in_reduction_message.cpp5
-rw-r--r--test/OpenMP/task_messages.cpp2
-rw-r--r--test/OpenMP/task_priority_messages.cpp2
-rw-r--r--test/OpenMP/task_private_codegen.cpp8
-rw-r--r--test/OpenMP/task_private_messages.cpp2
-rw-r--r--test/OpenMP/task_shared_messages.cpp2
-rw-r--r--test/OpenMP/taskgroup_ast_print.cpp6
-rw-r--r--test/OpenMP/taskgroup_codegen.cpp6
-rw-r--r--test/OpenMP/taskgroup_messages.cpp2
-rw-r--r--test/OpenMP/taskgroup_task_reduction_codegen.cpp93
-rw-r--r--test/OpenMP/taskgroup_task_reduction_messages.cpp4
-rw-r--r--test/OpenMP/taskloop_ast_print.cpp6
-rw-r--r--test/OpenMP/taskloop_codegen.cpp37
-rw-r--r--test/OpenMP/taskloop_collapse_messages.cpp4
-rw-r--r--test/OpenMP/taskloop_final_messages.cpp2
-rw-r--r--test/OpenMP/taskloop_firstprivate_codegen.cpp12
-rw-r--r--test/OpenMP/taskloop_firstprivate_messages.cpp2
-rw-r--r--test/OpenMP/taskloop_grainsize_messages.cpp2
-rw-r--r--test/OpenMP/taskloop_in_reduction_codegen.cpp19
-rw-r--r--test/OpenMP/taskloop_in_reduction_messages.cpp4
-rw-r--r--test/OpenMP/taskloop_lastprivate_codegen.cpp24
-rw-r--r--test/OpenMP/taskloop_lastprivate_messages.cpp2
-rw-r--r--test/OpenMP/taskloop_loop_messages.cpp6
-rw-r--r--test/OpenMP/taskloop_misc_messages.c2
-rw-r--r--test/OpenMP/taskloop_num_tasks_messages.cpp2
-rw-r--r--test/OpenMP/taskloop_priority_messages.cpp2
-rw-r--r--test/OpenMP/taskloop_private_codegen.cpp8
-rw-r--r--test/OpenMP/taskloop_private_messages.cpp2
-rw-r--r--test/OpenMP/taskloop_reduction_codegen.cpp79
-rw-r--r--test/OpenMP/taskloop_reduction_messages.cpp4
-rw-r--r--test/OpenMP/taskloop_simd_aligned_messages.cpp2
-rw-r--r--test/OpenMP/taskloop_simd_ast_print.cpp6
-rw-r--r--test/OpenMP/taskloop_simd_codegen.cpp33
-rw-r--r--test/OpenMP/taskloop_simd_collapse_messages.cpp4
-rw-r--r--test/OpenMP/taskloop_simd_final_messages.cpp2
-rw-r--r--test/OpenMP/taskloop_simd_firstprivate_codegen.cpp12
-rw-r--r--test/OpenMP/taskloop_simd_firstprivate_messages.cpp2
-rw-r--r--test/OpenMP/taskloop_simd_grainsize_messages.cpp2
-rw-r--r--test/OpenMP/taskloop_simd_in_reduction_codegen.cpp19
-rw-r--r--test/OpenMP/taskloop_simd_in_reduction_messages.cpp4
-rw-r--r--test/OpenMP/taskloop_simd_lastprivate_codegen.cpp24
-rw-r--r--test/OpenMP/taskloop_simd_lastprivate_messages.cpp2
-rw-r--r--test/OpenMP/taskloop_simd_linear_messages.cpp2
-rw-r--r--test/OpenMP/taskloop_simd_loop_messages.cpp2
-rw-r--r--test/OpenMP/taskloop_simd_misc_messages.c2
-rw-r--r--test/OpenMP/taskloop_simd_num_tasks_messages.cpp2
-rw-r--r--test/OpenMP/taskloop_simd_priority_messages.cpp2
-rw-r--r--test/OpenMP/taskloop_simd_private_codegen.cpp8
-rw-r--r--test/OpenMP/taskloop_simd_private_messages.cpp2
-rw-r--r--test/OpenMP/taskloop_simd_reduction_codegen.cpp62
-rw-r--r--test/OpenMP/taskloop_simd_reduction_messages.cpp4
-rw-r--r--test/OpenMP/taskloop_simd_safelen_messages.cpp4
-rw-r--r--test/OpenMP/taskloop_simd_simdlen_messages.cpp4
-rw-r--r--test/OpenMP/taskwait_ast_print.cpp6
-rw-r--r--test/OpenMP/taskwait_codegen.cpp5
-rw-r--r--test/OpenMP/taskwait_messages.cpp2
-rw-r--r--test/OpenMP/taskyield_ast_print.cpp6
-rw-r--r--test/OpenMP/taskyield_codegen.cpp5
-rw-r--r--test/OpenMP/taskyield_messages.cpp2
-rw-r--r--test/OpenMP/teams_ast_print.cpp6
-rw-r--r--test/OpenMP/teams_codegen.cpp78
-rw-r--r--test/OpenMP/teams_default_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_ast_print.cpp6
-rw-r--r--test/OpenMP/teams_distribute_codegen.cpp32
-rw-r--r--test/OpenMP/teams_distribute_collapse_codegen.cpp16
-rw-r--r--test/OpenMP/teams_distribute_collapse_messages.cpp4
-rw-r--r--test/OpenMP/teams_distribute_default_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_dist_schedule_codegen.cpp16
-rw-r--r--test/OpenMP/teams_distribute_dist_schedule_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_firstprivate_codegen.cpp53
-rw-r--r--test/OpenMP/teams_distribute_firstprivate_messages.cpp4
-rw-r--r--test/OpenMP/teams_distribute_lastprivate_codegen.cpp56
-rw-r--r--test/OpenMP/teams_distribute_lastprivate_messages.cpp4
-rw-r--r--test/OpenMP/teams_distribute_loop_messages.cpp4
-rw-r--r--test/OpenMP/teams_distribute_num_teams_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_ast_print.cpp6
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_codegen.cpp32
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_collapse_codegen.cpp16
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_collapse_messages.cpp4
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_copyin_codegen.cpp13
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_copyin_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_default_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_dist_schedule_codegen.cpp16
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_dist_schedule_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_firstprivate_codegen.cpp77
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_firstprivate_messages.cpp4
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_if_codegen.cpp5
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_if_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_lastprivate_codegen.cpp70
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_lastprivate_messages.cpp4
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_loop_messages.cpp4
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_num_teams_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_num_threads_codegen.cpp5
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_private_codegen.cpp25
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_private_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_proc_bind_codegen.cpp11
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_proc_bind_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_reduction_codegen.cpp13
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_reduction_messages.cpp10
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_schedule_codegen.cpp16
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_schedule_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_shared_messages.cpp4
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_aligned_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_ast_print.cpp6
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp34
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_collapse_codegen.cpp16
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_collapse_messages.cpp4
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_default_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_codegen.cpp16
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_firstprivate_codegen.cpp77
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_firstprivate_messages.cpp4
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_if_codegen.cpp5
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_if_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_codegen.cpp70
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_messages.cpp4
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_linear_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_loop_messages.cpp4
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_num_teams_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_num_threads_codegen.cpp5
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_num_threads_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_private_codegen.cpp25
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_private_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_proc_bind_codegen.cpp11
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_proc_bind_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_reduction_codegen.cpp13
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_reduction_messages.cpp10
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_safelen_messages.cpp4
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_schedule_codegen.cpp16
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_shared_messages.cpp4
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_simdlen_messages.cpp4
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_thread_limit_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_thread_limit_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_private_codegen.cpp25
-rw-r--r--test/OpenMP/teams_distribute_private_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_reduction_codegen.cpp13
-rw-r--r--test/OpenMP/teams_distribute_reduction_messages.cpp10
-rw-r--r--test/OpenMP/teams_distribute_shared_messages.cpp4
-rw-r--r--test/OpenMP/teams_distribute_simd_aligned_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_simd_ast_print.cpp6
-rw-r--r--test/OpenMP/teams_distribute_simd_codegen.cpp32
-rw-r--r--test/OpenMP/teams_distribute_simd_collapse_codegen.cpp16
-rw-r--r--test/OpenMP/teams_distribute_simd_collapse_messages.cpp4
-rw-r--r--test/OpenMP/teams_distribute_simd_default_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_simd_dist_schedule_codegen.cpp16
-rw-r--r--test/OpenMP/teams_distribute_simd_dist_schedule_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_simd_firstprivate_codegen.cpp53
-rw-r--r--test/OpenMP/teams_distribute_simd_firstprivate_messages.cpp4
-rw-r--r--test/OpenMP/teams_distribute_simd_lastprivate_codegen.cpp56
-rw-r--r--test/OpenMP/teams_distribute_simd_lastprivate_messages.cpp4
-rw-r--r--test/OpenMP/teams_distribute_simd_linear_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_simd_loop_messages.cpp4
-rw-r--r--test/OpenMP/teams_distribute_simd_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_simd_num_teams_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_simd_private_codegen.cpp25
-rw-r--r--test/OpenMP/teams_distribute_simd_private_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_simd_reduction_codegen.cpp13
-rw-r--r--test/OpenMP/teams_distribute_simd_reduction_messages.cpp10
-rw-r--r--test/OpenMP/teams_distribute_simd_safelen_messages.cpp4
-rw-r--r--test/OpenMP/teams_distribute_simd_shared_messages.cpp4
-rw-r--r--test/OpenMP/teams_distribute_simd_simdlen_messages.cpp4
-rw-r--r--test/OpenMP/teams_distribute_simd_thread_limit_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_thread_limit_messages.cpp2
-rw-r--r--test/OpenMP/teams_firstprivate_codegen.cpp68
-rw-r--r--test/OpenMP/teams_firstprivate_messages.cpp4
-rw-r--r--test/OpenMP/teams_messages.cpp2
-rw-r--r--test/OpenMP/teams_num_teams_messages.cpp2
-rw-r--r--test/OpenMP/teams_private_codegen.cpp16
-rw-r--r--test/OpenMP/teams_private_messages.cpp2
-rw-r--r--test/OpenMP/teams_reduction_messages.cpp10
-rw-r--r--test/OpenMP/teams_shared_messages.cpp4
-rw-r--r--test/OpenMP/teams_thread_limit_messages.cpp2
-rw-r--r--test/OpenMP/threadprivate_ast_print.cpp9
-rw-r--r--test/OpenMP/threadprivate_codegen.cpp51
-rw-r--r--test/OpenMP/threadprivate_messages.cpp3
-rw-r--r--test/OpenMP/varargs.cpp3
-rw-r--r--test/OpenMP/vla_crash.c3
-rw-r--r--test/PCH/Inputs/pch-through-use0.cpp2
-rw-r--r--test/PCH/Inputs/pch-through-use1.cpp5
-rw-r--r--test/PCH/Inputs/pch-through-use2.cpp3
-rw-r--r--test/PCH/Inputs/pch-through-use3a.cpp2
-rw-r--r--test/PCH/Inputs/pch-through-use3b.cpp3
-rw-r--r--test/PCH/Inputs/pch-through1.h2
-rw-r--r--test/PCH/Inputs/pch-through2.h2
-rw-r--r--test/PCH/Inputs/pch-through3.h2
-rw-r--r--test/PCH/Inputs/pch-through4.h2
-rw-r--r--test/PCH/Inputs/std-compare.h437
-rw-r--r--test/PCH/chain-openmp-threadprivate.cpp6
-rw-r--r--test/PCH/cxx-required-decls.cpp2
-rw-r--r--test/PCH/cxx2a-compare.cpp28
-rw-r--r--test/PCH/cxx_exprs.cpp34
-rw-r--r--test/PCH/dllexport-default-arg-closure.cpp4
-rw-r--r--test/PCH/include-stream-type.cpp10
-rw-r--r--test/PCH/late-parsed-instantiations.cpp31
-rw-r--r--test/PCH/modified-header-crash.c2
-rw-r--r--test/PCH/objc_stmts.m10
-rw-r--r--test/PCH/pch-through1.cpp34
-rw-r--r--test/PCH/pch-through2.cpp28
-rw-r--r--test/PCH/pch-through3a.cpp10
-rw-r--r--test/PCH/pch-through3b.cpp14
-rw-r--r--test/PCH/pragma-loop.cpp9
-rw-r--r--test/PCH/pragma-weak.c2
-rw-r--r--test/PCH/uses-seh.cpp4
-rw-r--r--test/PCH/verify_pch.m2
-rw-r--r--test/Parser/MicrosoftExtensions.cpp7
-rw-r--r--test/Parser/brackets.c4
-rw-r--r--test/Parser/brackets.cpp4
-rw-r--r--test/Parser/cxx-ambig-decl-expr.cpp4
-rw-r--r--test/Parser/cxx-decl.cpp10
-rw-r--r--test/Parser/cxx-extra-semi.cpp3
-rw-r--r--test/Parser/cxx0x-decl.cpp11
-rw-r--r--test/Parser/cxx11-brace-initializers.cpp4
-rw-r--r--test/Parser/cxx1z-class-template-argument-deduction.cpp43
-rw-r--r--test/Parser/decomposed-condition.cpp34
-rw-r--r--test/Parser/gcc-for-loop-init-compatibility.c15
-rw-r--r--test/Parser/objc-attr.m28
-rw-r--r--test/Parser/objc-try-catch-1.m4
-rw-r--r--test/Parser/opencl-cl20.cl12
-rw-r--r--test/Parser/opencl-cxx-keywords.cl50
-rw-r--r--test/Parser/opencl-cxx-virtual.cl45
-rw-r--r--test/Parser/opencl-storage-class.cl8
-rw-r--r--test/Parser/pointer_promotion.c2
-rw-r--r--test/Parser/skip-function-bodies.h3
-rw-r--r--test/Parser/skip-function-bodies.mm13
-rw-r--r--test/Parser/switch-recovery.cpp8
-rw-r--r--test/Preprocessor/Inputs/cycle/a.h8
-rw-r--r--test/Preprocessor/Inputs/cycle/b.h1
-rw-r--r--test/Preprocessor/Inputs/cycle/c.h1
-rw-r--r--test/Preprocessor/Inputs/headermap-rel/foo.hmapbin804 -> 0 bytes
-rw-r--r--test/Preprocessor/Inputs/headermap-rel/foo.hmap.json6
-rw-r--r--test/Preprocessor/Inputs/headermap-rel2/project-headers.hmapbin108 -> 0 bytes
-rw-r--r--test/Preprocessor/Inputs/headermap-rel2/project-headers.hmap.json6
-rw-r--r--test/Preprocessor/Inputs/nonportable-hmaps/foo.hmapbin102 -> 0 bytes
-rw-r--r--test/Preprocessor/Inputs/nonportable-hmaps/foo.hmap.json6
-rw-r--r--test/Preprocessor/aarch64-target-features.c17
-rw-r--r--test/Preprocessor/arm-target-features.c346
-rw-r--r--test/Preprocessor/cuda-types.cu20
-rw-r--r--test/Preprocessor/has_include.c12
-rw-r--r--test/Preprocessor/headermap-rel.c8
-rw-r--r--test/Preprocessor/headermap-rel2.c9
-rw-r--r--test/Preprocessor/include-cycle.c5
-rw-r--r--test/Preprocessor/init.c503
-rw-r--r--test/Preprocessor/macro-multiline.c2
-rw-r--r--test/Preprocessor/macro_paste_commaext.c4
-rw-r--r--test/Preprocessor/nonportable-include-with-hmap.c4
-rw-r--r--test/Preprocessor/pragma-comment-linux.c5
-rw-r--r--test/Preprocessor/pragma_microsoft.c12
-rw-r--r--test/Preprocessor/pragma_unknown.c20
-rw-r--r--test/Preprocessor/predefined-arch-macros.c509
-rw-r--r--test/Preprocessor/predefined-macros.c124
-rw-r--r--test/Preprocessor/predefined-win-macros.c110
-rw-r--r--test/Preprocessor/riscv-target-features.c49
-rw-r--r--test/Preprocessor/stdint.c40
-rw-r--r--test/Preprocessor/x86_target_features.c7
-rw-r--r--test/Profile/c-captured.c4
-rw-r--r--test/Profile/c-general.c8
-rw-r--r--test/Profile/cxx-lambda.cpp8
-rw-r--r--test/Rewriter/rewrite-modern-try-finally.m4
-rw-r--r--test/Sema/Inputs/pragma-align-no-header-change-warning.h5
-rw-r--r--test/Sema/_Float128.c22
-rw-r--r--test/Sema/aarch64-neon-fp16-ranges.c64
-rw-r--r--test/Sema/aarch64-neon-ranges.c150
-rw-r--r--test/Sema/address_spaces.c1
-rw-r--r--test/Sema/alloc-size.c12
-rw-r--r--test/Sema/annotate.c6
-rw-r--r--test/Sema/arm-asm.c7
-rw-r--r--test/Sema/arm-neon-types.c2
-rw-r--r--test/Sema/arm-no-fp16.c76
-rw-r--r--test/Sema/arm64-inline-asm.c6
-rw-r--r--test/Sema/artificial.c4
-rw-r--r--test/Sema/assign.c8
-rw-r--r--test/Sema/ast-print.c44
-rw-r--r--test/Sema/atomic-ops.c164
-rw-r--r--test/Sema/attr-availability-square-brackets.c25
-rw-r--r--test/Sema/attr-availability-tvos.c2
-rw-r--r--test/Sema/attr-availability-watchos.c2
-rw-r--r--test/Sema/attr-cpuspecific.c96
-rw-r--r--test/Sema/attr-cx2.c26
-rw-r--r--test/Sema/attr-external-source-symbol.c14
-rw-r--r--test/Sema/attr-format_arg.c17
-rw-r--r--test/Sema/attr-ifunc.c2
-rw-r--r--test/Sema/attr-min-vector-width.c16
-rw-r--r--test/Sema/attr-nocf_check.c23
-rw-r--r--test/Sema/attr-nocf_check.cpp23
-rw-r--r--test/Sema/attr-objc-bridge-related.m7
-rw-r--r--test/Sema/attr-ownership.c2
-rw-r--r--test/Sema/attr-ownership.cpp7
-rw-r--r--test/Sema/attr-print.c3
-rw-r--r--test/Sema/attr-target-ast.c5
-rw-r--r--test/Sema/attr-target-mv-bad-target.c10
-rw-r--r--test/Sema/attr-target-mv.c103
-rw-r--r--test/Sema/attr-target-unsupported.c12
-rw-r--r--test/Sema/attr-target.c25
-rw-r--r--test/Sema/attr-type-safety.c45
-rw-r--r--test/Sema/attr-used.c4
-rw-r--r--test/Sema/attr-weak.c3
-rw-r--r--test/Sema/availability-guard-format.mm15
-rw-r--r--test/Sema/bitfield.c4
-rw-r--r--test/Sema/bittest-intrinsics.c84
-rw-r--r--test/Sema/builtin-classify-type.c19
-rw-r--r--test/Sema/builtin-dump-struct.c42
-rw-r--r--test/Sema/builtin-object-size.c6
-rw-r--r--test/Sema/builtin-prefetch.c6
-rw-r--r--test/Sema/builtin-redecl.cpp18
-rw-r--r--test/Sema/builtins-arm.c39
-rw-r--r--test/Sema/builtins-arm64.c14
-rw-r--r--test/Sema/builtins-hexagon-v55.c17
-rw-r--r--test/Sema/builtins-hexagon-v60.c16
-rw-r--r--test/Sema/builtins-hexagon-v62.c15
-rw-r--r--test/Sema/builtins-hexagon-v65.c15
-rw-r--r--test/Sema/builtins-hvx-none.c26
-rw-r--r--test/Sema/builtins-hvx-v60.c25
-rw-r--r--test/Sema/builtins-hvx-v62.c24
-rw-r--r--test/Sema/builtins-hvx-v65.c23
-rw-r--r--test/Sema/builtins-ppc.c34
-rw-r--r--test/Sema/builtins-x86.c119
-rw-r--r--test/Sema/builtins-x86.cpp24
-rw-r--r--test/Sema/builtins.c28
-rw-r--r--test/Sema/compare.c15
-rw-r--r--test/Sema/complex-int.c4
-rw-r--r--test/Sema/constant-builtins-2.c25
-rw-r--r--test/Sema/conversion.c19
-rw-r--r--test/Sema/cxx-as-c.c9
-rw-r--r--test/Sema/darwin-tls.c6
-rw-r--r--test/Sema/diagnose_if.c10
-rw-r--r--test/Sema/error-type-safety.cpp39
-rw-r--r--test/Sema/ext_vector_comparisons.c12
-rw-r--r--test/Sema/float128-ld-incompatibility.cpp5
-rw-r--r--test/Sema/inline-asm-validate-amdgpu.cl5
-rw-r--r--test/Sema/integer-overflow.c15
-rw-r--r--test/Sema/internal_linkage.c8
-rw-r--r--test/Sema/mms-bitfields.c15
-rw-r--r--test/Sema/ms_wide_predefined_expr.cpp2
-rw-r--r--test/Sema/multistep-explicit-cast.c70
-rw-r--r--test/Sema/no_stack_protector.c5
-rw-r--r--test/Sema/nocf_check_attr_not_allowed.c5
-rw-r--r--test/Sema/nonnull.c4
-rw-r--r--test/Sema/pr30372.c2
-rw-r--r--test/Sema/pragma-align-no-header-change-warning.c5
-rw-r--r--test/Sema/preserve-call-conv.c1
-rw-r--r--test/Sema/redefine_extname.c1
-rw-r--r--test/Sema/return.c12
-rw-r--r--test/Sema/riscv-interrupt-attr.c62
-rw-r--r--test/Sema/riscv-interrupt-attr.cpp16
-rw-r--r--test/Sema/self-comparison.c7
-rw-r--r--test/Sema/sign-compare-enum.c79
-rw-r--r--test/Sema/switch.c2
-rw-r--r--test/Sema/tautological-constant-compare.c44
-rw-r--r--test/Sema/tautological-constant-enum-compare.c4
-rw-r--r--test/Sema/tautological-unsigned-enum-zero-compare.c3
-rw-r--r--test/Sema/tautological-unsigned-enum-zero-compare.cpp3
-rw-r--r--test/Sema/tautological-unsigned-zero-compare.c43
-rw-r--r--test/Sema/tls.c4
-rw-r--r--test/Sema/transparent-union.c29
-rw-r--r--test/Sema/transpose-memset.c61
-rw-r--r--test/Sema/typedef-retain.c4
-rw-r--r--test/Sema/typo-correction.c13
-rw-r--r--test/Sema/uninit-variables.c2
-rw-r--r--test/Sema/varargs.c9
-rw-r--r--test/Sema/vector-gcc-compat.c2
-rw-r--r--test/Sema/vector-gcc-compat.cpp2
-rw-r--r--test/Sema/vla.c21
-rw-r--r--test/Sema/warn-cast-qual.c10
-rw-r--r--test/Sema/warn-documentation.m4
-rw-r--r--test/Sema/warn-duplicate-enum.c20
-rw-r--r--test/Sema/warn-strict-prototypes.c6
-rw-r--r--test/Sema/warn-string-conversion.c2
-rw-r--r--test/Sema/warn-type-safety.c8
-rw-r--r--test/Sema/warn-unreachable.c4
-rw-r--r--test/Sema/x86-builtin-palignr.c4
-rw-r--r--test/SemaCUDA/amdgpu-attrs.cu62
-rw-r--r--test/SemaCUDA/call-device-fn-from-host.cu7
-rw-r--r--test/SemaCUDA/device-var-init.cu17
-rw-r--r--test/SemaCUDA/extern-shared.cu24
-rw-r--r--test/SemaCUDA/function-overload.cu4
-rw-r--r--test/SemaCUDA/function-template-overload.cu2
-rw-r--r--test/SemaCUDA/kernel-call.cu4
-rw-r--r--test/SemaCXX/Inputs/std-compare.h437
-rw-r--r--test/SemaCXX/MicrosoftCompatibility.cpp9
-rw-r--r--test/SemaCXX/MicrosoftExtensions.cpp1
-rw-r--r--test/SemaCXX/PR22637.cpp40
-rw-r--r--test/SemaCXX/PR35832.cpp21
-rw-r--r--test/SemaCXX/PR38235.cpp20
-rw-r--r--test/SemaCXX/access.cpp47
-rw-r--r--test/SemaCXX/address-of-temporary.cpp19
-rw-r--r--test/SemaCXX/address-space-references.cpp8
-rw-r--r--test/SemaCXX/aggregate-initialization.cpp6
-rw-r--r--test/SemaCXX/anonymous-struct.cpp2
-rw-r--r--test/SemaCXX/anonymous-union-export.cpp6
-rw-r--r--test/SemaCXX/anonymous-union.cpp4
-rw-r--r--test/SemaCXX/array-bounds.cpp15
-rw-r--r--test/SemaCXX/ast-print-crash.cpp12
-rw-r--r--test/SemaCXX/ast-print.cpp7
-rw-r--r--test/SemaCXX/attr-cpuspecific.cpp111
-rw-r--r--test/SemaCXX/attr-noreturn.cpp10
-rw-r--r--test/SemaCXX/attr-print.cpp9
-rw-r--r--test/SemaCXX/attr-section.cpp44
-rw-r--r--test/SemaCXX/attr-target-mv.cpp185
-rw-r--r--test/SemaCXX/base-class-ambiguity-check.cpp9
-rw-r--r--test/SemaCXX/builtin-classify-type.cpp25
-rw-r--r--test/SemaCXX/builtin-operator-new-delete.cpp157
-rw-r--r--test/SemaCXX/builtins-overflow.cpp93
-rw-r--r--test/SemaCXX/char8_t.cpp44
-rw-r--r--test/SemaCXX/class-layout.cpp34
-rw-r--r--test/SemaCXX/code-seg.cpp105
-rw-r--r--test/SemaCXX/code-seg1.cpp97
-rw-r--r--test/SemaCXX/compare-cxx2a.cpp327
-rw-r--r--test/SemaCXX/compare.cpp2
-rw-r--r--test/SemaCXX/complete-member-pointers.cpp15
-rw-r--r--test/SemaCXX/conditional-expr.cpp20
-rw-r--r--test/SemaCXX/const-cast.cpp10
-rw-r--r--test/SemaCXX/constant-conversion.cpp24
-rw-r--r--test/SemaCXX/constant-expression-cxx11.cpp24
-rw-r--r--test/SemaCXX/constant-expression-cxx1y.cpp83
-rw-r--r--test/SemaCXX/constant-expression-cxx1z.cpp13
-rw-r--r--test/SemaCXX/constant-expression-cxx2a.cpp197
-rw-r--r--test/SemaCXX/constexpr-default-arg.cpp38
-rw-r--r--test/SemaCXX/constexpr-string.cpp15
-rw-r--r--test/SemaCXX/conversion-function.cpp10
-rw-r--r--test/SemaCXX/copy-initialization.cpp2
-rw-r--r--test/SemaCXX/coroutine-source-location-crash.cpp33
-rw-r--r--test/SemaCXX/coroutine-traits-undefined-template.cpp19
-rw-r--r--test/SemaCXX/coroutines.cpp217
-rw-r--r--test/SemaCXX/cxx-deprecated.cpp3
-rw-r--r--test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp9
-rw-r--r--test/SemaCXX/cxx0x-nontrivial-union.cpp2
-rw-r--r--test/SemaCXX/cxx11-gnu-attrs.cpp5
-rw-r--r--test/SemaCXX/cxx1y-contextual-conversion-tweaks.cpp10
-rw-r--r--test/SemaCXX/cxx1y-generic-lambdas.cpp18
-rw-r--r--test/SemaCXX/cxx1y-variable-templates_in_class.cpp31
-rw-r--r--test/SemaCXX/cxx1y-variable-templates_top_level.cpp11
-rw-r--r--test/SemaCXX/cxx1z-class-template-argument-deduction.cpp64
-rw-r--r--test/SemaCXX/cxx1z-constexpr-lambdas.cpp35
-rw-r--r--test/SemaCXX/cxx1z-decomposition.cpp5
-rw-r--r--test/SemaCXX/cxx1z-noexcept-function-type.cpp2
-rw-r--r--test/SemaCXX/cxx2a-lambda-equals-this.cpp12
-rw-r--r--test/SemaCXX/cxx2a-pointer-to-const-ref-member.cpp7
-rw-r--r--test/SemaCXX/cxx2a-user-defined-literals.cpp27
-rw-r--r--test/SemaCXX/cxx98-compat.cpp12
-rw-r--r--test/SemaCXX/dllimport-constexpr.cpp62
-rw-r--r--test/SemaCXX/dllimport-memptr.cpp1
-rw-r--r--test/SemaCXX/err_typecheck_assign_const.cpp20
-rw-r--r--test/SemaCXX/err_typecheck_assign_const_filecheck.cpp2
-rw-r--r--test/SemaCXX/eval-crashes.cpp6
-rw-r--r--test/SemaCXX/extern-c.cpp17
-rw-r--r--test/SemaCXX/extra-semi.cpp29
-rw-r--r--test/SemaCXX/for-range-examples.cpp8
-rw-r--r--test/SemaCXX/friend2.cpp28
-rw-r--r--test/SemaCXX/i-c-e-cxx.cpp6
-rw-r--r--test/SemaCXX/init-expr-crash.cpp8
-rw-r--r--test/SemaCXX/injected-class-name-crash.cpp11
-rw-r--r--test/SemaCXX/instantiate-blocks.cpp9
-rw-r--r--test/SemaCXX/integer-overflow.cpp15
-rw-r--r--test/SemaCXX/invalid-template-specifier.cpp2
-rw-r--r--test/SemaCXX/lambda-expressions.cpp40
-rw-r--r--test/SemaCXX/large-array-init.cpp10
-rw-r--r--test/SemaCXX/member-init.cpp5
-rw-r--r--test/SemaCXX/ms-initlist-narrowing.cpp17
-rw-r--r--test/SemaCXX/ms-interface.cpp6
-rw-r--r--test/SemaCXX/ms-uuid.cpp15
-rw-r--r--test/SemaCXX/multistep-explicit-cast.cpp155
-rw-r--r--test/SemaCXX/neon-vector-types.cpp2
-rw-r--r--test/SemaCXX/no-rtti.cpp4
-rw-r--r--test/SemaCXX/overload-call.cpp54
-rw-r--r--test/SemaCXX/overload-member-call.cpp3
-rw-r--r--test/SemaCXX/overloaded-builtin-operators-cxx17.cpp10
-rw-r--r--test/SemaCXX/overloaded-builtin-operators.cpp18
-rw-r--r--test/SemaCXX/overloaded-name.cpp8
-rw-r--r--test/SemaCXX/pr36536.cpp44
-rw-r--r--test/SemaCXX/pragma-optimize.cpp6
-rw-r--r--test/SemaCXX/references.cpp47
-rw-r--r--test/SemaCXX/return-stack-addr-2.cpp2
-rw-r--r--test/SemaCXX/return-stack-addr.cpp9
-rw-r--r--test/SemaCXX/rval-references.cpp5
-rw-r--r--test/SemaCXX/scope-check.cpp3
-rw-r--r--test/SemaCXX/self-comparison.cpp21
-rw-r--r--test/SemaCXX/sourceranges.cpp89
-rw-r--r--test/SemaCXX/std-compare-cxx2a.cpp65
-rw-r--r--test/SemaCXX/type-attrs.cpp5
-rw-r--r--test/SemaCXX/type-traits.cpp100
-rw-r--r--test/SemaCXX/typeid-ref.cpp4
-rw-r--r--test/SemaCXX/typo-correction-cxx17.cpp7
-rw-r--r--test/SemaCXX/typo-correction.cpp4
-rw-r--r--test/SemaCXX/uninitialized.cpp12
-rw-r--r--test/SemaCXX/vector.cpp45
-rw-r--r--test/SemaCXX/warn-dangling-field.cpp11
-rw-r--r--test/SemaCXX/warn-dangling-local.cpp20
-rw-r--r--test/SemaCXX/warn-float-conversion.cpp43
-rw-r--r--test/SemaCXX/warn-infinite-recursion.cpp16
-rw-r--r--test/SemaCXX/warn-literal-conversion.cpp11
-rw-r--r--test/SemaCXX/warn-missing-variable-declarations.cpp23
-rw-r--r--test/SemaCXX/warn-return-std-move.cpp334
-rw-r--r--test/SemaCXX/warn-self-assign-builtin.cpp67
-rw-r--r--test/SemaCXX/warn-self-assign-field-builtin.cpp117
-rw-r--r--test/SemaCXX/warn-self-assign-field-overloaded.cpp162
-rw-r--r--test/SemaCXX/warn-self-assign-overloaded-disable.cpp18
-rw-r--r--test/SemaCXX/warn-self-assign-overloaded.cpp115
-rw-r--r--test/SemaCXX/warn-self-assign.cpp50
-rw-r--r--test/SemaCXX/warn-thread-safety-analysis.cpp203
-rw-r--r--test/SemaCXX/warn-throw-out-noexcept-func.cpp143
-rw-r--r--test/SemaCXX/warn-unreachable.cpp2
-rw-r--r--test/SemaObjC/Inputs/module.map3
-rw-r--r--test/SemaObjC/arc-decls.m28
-rw-r--r--test/SemaObjC/arc-peformselector.m2
-rw-r--r--test/SemaObjC/arc-property-decl-attrs.m35
-rw-r--r--test/SemaObjC/arc-repeated-weak.mm3
-rw-r--r--test/SemaObjC/arc-system-header.m6
-rw-r--r--test/SemaObjC/arc.m20
-rw-r--r--test/SemaObjC/attr-availability-1.m4
-rw-r--r--test/SemaObjC/attr-deprecated-replacement-fixit.m177
-rw-r--r--test/SemaObjC/avoid-unavailable-implementation-warning-in-app-extension.m24
-rw-r--r--test/SemaObjC/block-compare.mm51
-rw-r--r--test/SemaObjC/catch-invalid.m9
-rw-r--r--test/SemaObjC/class-unavail-warning.m4
-rw-r--r--test/SemaObjC/compare-qualified-class.m2
-rw-r--r--test/SemaObjC/comptypes-legal.m2
-rw-r--r--test/SemaObjC/finally-msvc.m14
-rw-r--r--test/SemaObjC/foreachtemplatized.mm15
-rw-r--r--test/SemaObjC/format-size-spec-nsinteger.m52
-rw-r--r--test/SemaObjC/incomplete-implementation.m7
-rw-r--r--test/SemaObjC/integer-overflow.m18
-rw-r--r--test/SemaObjC/ns-consumed-error-not-warning.m13
-rw-r--r--test/SemaObjC/nullability.m11
-rw-r--r--test/SemaObjC/property-10.m2
-rw-r--r--test/SemaObjC/property-deprecated-warning.m11
-rw-r--r--test/SemaObjC/property-ivar-mismatch.m2
-rw-r--r--test/SemaObjC/property.m2
-rw-r--r--test/SemaObjC/protocol-expr-neg-1.m6
-rw-r--r--test/SemaObjC/scope-check.m2
-rw-r--r--test/SemaObjC/strong-in-c-struct.m56
-rw-r--r--test/SemaObjC/undef-class-property-error.m9
-rw-r--r--test/SemaObjC/unguarded-availability-category-protocol-use.m18
-rw-r--r--test/SemaObjC/unguarded-availability.m44
-rw-r--r--test/SemaObjC/warn-nontrivial-struct-memaccess.m39
-rw-r--r--test/SemaObjCXX/attr-trivial-abi.mm97
-rw-r--r--test/SemaObjCXX/instantiate-method-return.mm8
-rw-r--r--test/SemaObjCXX/parameterized_classes_subst.mm2
-rw-r--r--test/SemaOpenCL/address-spaces.cl6
-rw-r--r--test/SemaOpenCL/builtins-amdgcn-error.cl17
-rw-r--r--test/SemaOpenCL/extension-version.cl9
-rw-r--r--test/SemaOpenCL/invalid-kernel-attrs.cl8
-rw-r--r--test/SemaOpenCL/logical-ops.cl2
-rw-r--r--test/SemaOpenCL/multistep-explicit-cast.cl13
-rw-r--r--test/SemaOpenCL/predefined-expr.cl8
-rw-r--r--test/SemaOpenCL/storageclass.cl10
-rw-r--r--test/SemaOpenCLCXX/newdelete.cl55
-rw-r--r--test/SemaOpenCLCXX/restricted.cl63
-rw-r--r--test/SemaTemplate/alias-templates.cpp6
-rw-r--r--test/SemaTemplate/alignas.cpp11
-rw-r--r--test/SemaTemplate/argument-dependent-lookup.cpp45
-rw-r--r--test/SemaTemplate/attributes.cpp11
-rw-r--r--test/SemaTemplate/class-template-spec.cpp10
-rw-r--r--test/SemaTemplate/cxx17-inline-variables.cpp11
-rw-r--r--test/SemaTemplate/dependent-base-classes.cpp4
-rw-r--r--test/SemaTemplate/dependent-names.cpp40
-rw-r--r--test/SemaTemplate/dependent-template-recover.cpp64
-rw-r--r--test/SemaTemplate/ext_ms_template_spec.cpp8
-rw-r--r--test/SemaTemplate/function-pointer-qualifier.cpp29
-rw-r--r--test/SemaTemplate/function-template-specialization.cpp2
-rw-r--r--test/SemaTemplate/instantiate-after-fatal-cxx17.cpp16
-rw-r--r--test/SemaTemplate/instantiate-init.cpp14
-rw-r--r--test/SemaTemplate/instantiate-method.cpp2
-rw-r--r--test/SemaTemplate/late-parsing-eager-instantiation.cpp40
-rw-r--r--test/SemaTemplate/metafun-apply.cpp2
-rw-r--r--test/SemaTemplate/ms-function-specialization-class-scope.cpp24
-rw-r--r--test/SemaTemplate/nested-name-spec-template.cpp6
-rw-r--r--test/SemaTemplate/nested-template.cpp7
-rw-r--r--test/SemaTemplate/pack-deduction.cpp101
-rw-r--r--test/SemaTemplate/partial-spec-instantiate.cpp43
-rw-r--r--test/SemaTemplate/sizeof-pack.cpp7
-rw-r--r--test/SemaTemplate/stmt-expr.cpp39
-rw-r--r--test/SemaTemplate/temp-param-subst-linear.cpp56
-rw-r--r--test/SemaTemplate/temp_arg_nontype_cxx11.cpp12
-rw-r--r--test/SemaTemplate/temp_arg_pack.cpp8
-rw-r--r--test/SemaTemplate/temp_class_spec_neg.cpp6
-rw-r--r--test/SemaTemplate/template-id-expr.cpp79
-rw-r--r--test/SemaTemplate/typo-dependent-name.cpp35
-rw-r--r--test/SemaTemplate/undefined-template.cpp11
-rw-r--r--test/SemaTemplate/warn-thread-safety-analysis.cpp30
-rw-r--r--test/TableGen/DiagnosticBase.inc133
-rw-r--r--test/TableGen/DiagnosticDocs.inc75
-rw-r--r--test/TableGen/anonymous-groups.td22
-rw-r--r--test/TableGen/emit-diag-docs.td78
-rw-r--r--test/TableGen/text-substitution.td38
-rw-r--r--test/TableGen/tg-fixits.td24
-rw-r--r--test/Templight/templight-deduced-func.cpp44
-rw-r--r--test/Templight/templight-default-arg-inst.cpp82
-rw-r--r--test/Templight/templight-default-func-arg.cpp73
-rw-r--r--test/Templight/templight-default-template-arg.cpp69
-rw-r--r--test/Templight/templight-exception-spec-func.cpp73
-rw-r--r--test/Templight/templight-explicit-template-arg.cpp59
-rw-r--r--test/Templight/templight-memoization.cpp42
-rw-r--r--test/Templight/templight-nested-memoization.cpp174
-rw-r--r--test/Templight/templight-nested-template-instantiation.cpp84
-rw-r--r--test/Templight/templight-one-instantiation.cpp18
-rw-r--r--test/Templight/templight-prior-template-arg.cpp72
-rw-r--r--test/Tooling/clang-diff-json.cpp6
-rw-r--r--test/VFS/Inputs/MissingVFS/a.h1
-rw-r--r--test/VFS/Inputs/MissingVFS/module.modulemap3
-rw-r--r--test/VFS/Inputs/MissingVFS/vfsoverlay.yaml13
-rw-r--r--test/VFS/module_missing_vfs.m16
-rw-r--r--test/VFS/real-path-found-first.m2
-rw-r--r--test/VFS/umbrella-framework-import-skipnonexist.m2
-rw-r--r--test/VFS/umbrella-mismatch.m4
-rw-r--r--test/lit.cfg.py8
-rw-r--r--test/lit.site.cfg.py.in1
-rw-r--r--tools/c-index-test/CMakeLists.txt6
-rw-r--r--tools/c-index-test/c-index-test.c249
-rw-r--r--tools/c-index-test/core_main.cpp59
-rw-r--r--tools/clang-check/ClangCheck.cpp8
-rw-r--r--tools/clang-format-vs/ClangFormat/ClangFormatPackage.cs2
-rw-r--r--tools/clang-format-vs/ClangFormat/license.txt2
-rw-r--r--tools/clang-format/ClangFormat.cpp51
-rw-r--r--tools/clang-format/clang-format.el2
-rw-r--r--tools/clang-format/fuzzer/ClangFormatFuzzer.cpp2
-rwxr-xr-xtools/clang-format/git-clang-format1
-rw-r--r--tools/clang-fuzzer/CMakeLists.txt59
-rw-r--r--tools/clang-fuzzer/ClangFuzzer.cpp2
-rw-r--r--tools/clang-fuzzer/ExampleClangLLVMProtoFuzzer.cpp28
-rw-r--r--tools/clang-fuzzer/ExampleClangLoopProtoFuzzer.cpp30
-rw-r--r--tools/clang-fuzzer/ExampleClangProtoFuzzer.cpp22
-rw-r--r--tools/clang-fuzzer/cxx_loop_proto.proto80
-rw-r--r--tools/clang-fuzzer/cxx_proto.proto2
-rw-r--r--tools/clang-fuzzer/fuzzer-initialize/CMakeLists.txt3
-rw-r--r--tools/clang-fuzzer/fuzzer-initialize/fuzzer_initialize.cpp65
-rw-r--r--tools/clang-fuzzer/fuzzer-initialize/fuzzer_initialize.h19
-rw-r--r--tools/clang-fuzzer/handle-cxx/handle_cxx.cpp6
-rw-r--r--tools/clang-fuzzer/handle-llvm/CMakeLists.txt30
-rw-r--r--tools/clang-fuzzer/handle-llvm/handle_llvm.cpp178
-rw-r--r--tools/clang-fuzzer/handle-llvm/handle_llvm.h25
-rw-r--r--tools/clang-fuzzer/proto-to-cxx/CMakeLists.txt14
-rw-r--r--tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx.cpp131
-rw-r--r--tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx_main.cpp31
-rw-r--r--tools/clang-fuzzer/proto-to-cxx/proto_to_cxx.cpp2
-rw-r--r--tools/clang-fuzzer/proto-to-cxx/proto_to_cxx.h4
-rw-r--r--tools/clang-fuzzer/proto-to-llvm/CMakeLists.txt14
-rw-r--r--tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.cpp156
-rw-r--r--tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.h23
-rw-r--r--tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm_main.cpp31
-rw-r--r--tools/clang-import-test/CMakeLists.txt6
-rw-r--r--tools/clang-import-test/clang-import-test.cpp24
-rw-r--r--tools/clang-offload-bundler/ClangOffloadBundler.cpp39
-rw-r--r--tools/clang-refactor/CMakeLists.txt2
-rw-r--r--tools/clang-refactor/ClangRefactor.cpp2
-rw-r--r--tools/clang-refactor/TestSupport.cpp2
-rw-r--r--tools/clang-refactor/TestSupport.h2
-rw-r--r--tools/clang-rename/CMakeLists.txt4
-rw-r--r--tools/clang-rename/ClangRename.cpp6
-rw-r--r--tools/diagtool/CMakeLists.txt14
-rw-r--r--tools/diagtool/DiagTool.cpp2
-rw-r--r--tools/diagtool/DiagnosticNames.h6
-rw-r--r--tools/driver/CMakeLists.txt24
-rw-r--r--tools/driver/cc1_main.cpp25
-rw-r--r--tools/driver/cc1as_main.cpp87
-rw-r--r--tools/driver/cc1gen_reproducer_main.cpp196
-rw-r--r--tools/driver/driver.cpp40
-rw-r--r--tools/libclang/BuildSystem.cpp5
-rw-r--r--tools/libclang/CIndex.cpp344
-rw-r--r--tools/libclang/CIndexCodeCompletion.cpp97
-rw-r--r--tools/libclang/CIndexDiagnostic.h42
-rw-r--r--tools/libclang/CIndexHigh.cpp4
-rw-r--r--tools/libclang/CIndexer.cpp14
-rw-r--r--tools/libclang/CIndexer.h22
-rw-r--r--tools/libclang/CLog.h4
-rw-r--r--tools/libclang/CMakeLists.txt2
-rw-r--r--tools/libclang/CXCursor.cpp20
-rw-r--r--tools/libclang/CXCursor.h80
-rw-r--r--tools/libclang/CXIndexDataConsumer.cpp37
-rw-r--r--tools/libclang/CXIndexDataConsumer.h13
-rw-r--r--tools/libclang/CXLoadedDiagnostic.cpp2
-rw-r--r--tools/libclang/CXLoadedDiagnostic.h22
-rw-r--r--tools/libclang/CXSourceLocation.h8
-rw-r--r--tools/libclang/CXString.cpp2
-rw-r--r--tools/libclang/CXString.h20
-rw-r--r--tools/libclang/CXType.cpp46
-rw-r--r--tools/libclang/CursorVisitor.h24
-rw-r--r--tools/libclang/Index_Internal.h8
-rw-r--r--tools/libclang/Indexing.cpp25
-rw-r--r--tools/libclang/libclang.exports11
-rw-r--r--tools/scan-build-py/README.md32
-rw-r--r--tools/scan-build-py/libscanbuild/__init__.py3
-rw-r--r--tools/scan-build-py/libscanbuild/analyze.py285
-rw-r--r--tools/scan-build-py/libscanbuild/arguments.py78
-rw-r--r--tools/scan-build-py/libscanbuild/clang.py27
-rw-r--r--tools/scan-build-py/libscanbuild/report.py22
-rw-r--r--tools/scan-build-py/tests/unit/test_analyze.py84
-rw-r--r--tools/scan-build-py/tests/unit/test_clang.py12
-rwxr-xr-xtools/scan-build/bin/scan-build28
-rwxr-xr-xtools/scan-build/libexec/ccc-analyzer4
-rw-r--r--tools/scan-build/man/scan-build.14
-rw-r--r--tools/scan-view/share/startfile.py6
-rw-r--r--unittests/AST/ASTImporterTest.cpp3351
-rw-r--r--unittests/AST/CMakeLists.txt4
-rw-r--r--unittests/AST/CommentTextTest.cpp128
-rw-r--r--unittests/AST/DeclMatcher.h79
-rw-r--r--unittests/AST/Language.cpp46
-rw-r--r--unittests/AST/Language.h41
-rw-r--r--unittests/AST/MatchVerifier.h14
-rw-r--r--unittests/AST/NamedDeclPrinterTest.cpp7
-rw-r--r--unittests/AST/PostOrderASTVisitor.cpp128
-rw-r--r--unittests/AST/StructuralEquivalenceTest.cpp631
-rw-r--r--unittests/ASTMatchers/ASTMatchersInternalTest.cpp4
-rw-r--r--unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp147
-rw-r--r--unittests/ASTMatchers/ASTMatchersNodeTest.cpp43
-rw-r--r--unittests/ASTMatchers/ASTMatchersTest.h2
-rw-r--r--unittests/ASTMatchers/ASTMatchersTraversalTest.cpp50
-rw-r--r--unittests/ASTMatchers/CMakeLists.txt3
-rw-r--r--unittests/ASTMatchers/Dynamic/CMakeLists.txt3
-rw-r--r--unittests/ASTMatchers/Dynamic/ParserTest.cpp26
-rw-r--r--unittests/Basic/CharInfoTest.cpp5
-rw-r--r--unittests/Basic/FileManagerTest.cpp17
-rw-r--r--unittests/Basic/VirtualFileSystemTest.cpp99
-rw-r--r--unittests/CrossTU/CrossTranslationUnitTest.cpp1
-rw-r--r--unittests/Driver/CMakeLists.txt1
-rw-r--r--unittests/Driver/ModuleCacheTest.cpp28
-rw-r--r--unittests/Driver/ToolChainTest.cpp4
-rw-r--r--unittests/Format/CleanupTest.cpp513
-rw-r--r--unittests/Format/FormatTest.cpp683
-rw-r--r--unittests/Format/FormatTestComments.cpp22
-rw-r--r--unittests/Format/FormatTestJS.cpp32
-rw-r--r--unittests/Format/FormatTestJava.cpp8
-rw-r--r--unittests/Format/FormatTestObjC.cpp513
-rw-r--r--unittests/Format/FormatTestProto.cpp289
-rw-r--r--unittests/Format/FormatTestRawStrings.cpp269
-rw-r--r--unittests/Format/FormatTestSelective.cpp74
-rw-r--r--unittests/Format/FormatTestTextProto.cpp577
-rw-r--r--unittests/Format/NamespaceEndCommentsFixerTest.cpp6
-rw-r--r--unittests/Format/SortIncludesTest.cpp44
-rw-r--r--unittests/Format/UsingDeclarationsSorterTest.cpp6
-rw-r--r--unittests/Frontend/ASTUnitTest.cpp81
-rw-r--r--unittests/Frontend/CMakeLists.txt2
-rw-r--r--unittests/Frontend/OutputStreamTest.cpp46
-rw-r--r--unittests/Lex/CMakeLists.txt1
-rw-r--r--unittests/Lex/HeaderSearchTest.cpp96
-rw-r--r--unittests/Lex/LexerTest.cpp14
-rw-r--r--unittests/Lex/PPCallbacksTest.cpp58
-rw-r--r--unittests/Rename/RenameMemberTest.cpp2
-rw-r--r--unittests/Sema/CMakeLists.txt1
-rw-r--r--unittests/Sema/CodeCompleteTest.cpp145
-rw-r--r--unittests/StaticAnalyzer/AnalyzerOptionsTest.cpp6
-rw-r--r--unittests/StaticAnalyzer/CMakeLists.txt6
-rw-r--r--unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp80
-rw-r--r--unittests/Tooling/CMakeLists.txt24
-rw-r--r--unittests/Tooling/CompilationDatabaseTest.cpp138
-rw-r--r--unittests/Tooling/ExecutionTest.cpp80
-rw-r--r--unittests/Tooling/HeaderIncludesTest.cpp527
-rw-r--r--unittests/Tooling/QualTypeNamesTest.cpp30
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTest.cpp305
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTestExprVisitor.cpp271
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTestPostOrderVisitor.cpp116
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/Attr.cpp52
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/CXXBoolLiteralExpr.cpp37
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp (renamed from unittests/Tooling/RecursiveASTVisitorTestCallVisitor.cpp)24
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/CXXOperatorCallExprTraverser.cpp38
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/Class.cpp41
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/ConstructExpr.cpp76
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp125
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/ImplicitCtor.cpp43
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrder.cpp36
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp40
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp36
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp38
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/IntegerLiteral.cpp33
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/LambdaDefaultCapture.cpp35
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp63
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/NestedNameSpecifiers.cpp74
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/ParenExpr.cpp30
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp40
-rw-r--r--unittests/Tooling/RefactoringActionRulesTest.cpp2
-rw-r--r--unittests/Tooling/RefactoringTest.cpp6
-rw-r--r--unittests/Tooling/ToolingTest.cpp27
-rw-r--r--unittests/libclang/LibclangTest.cpp199
-rw-r--r--utils/TableGen/ClangAttrEmitter.cpp297
-rw-r--r--utils/TableGen/ClangCommentHTMLNamedCharacterReferenceEmitter.cpp2
-rw-r--r--utils/TableGen/ClangDiagnosticsEmitter.cpp1083
-rw-r--r--utils/TableGen/ClangOptionDocEmitter.cpp28
-rw-r--r--utils/TableGen/ClangSACheckersEmitter.cpp2
-rw-r--r--utils/TableGen/NeonEmitter.cpp180
-rw-r--r--utils/TableGen/TableGen.cpp5
-rw-r--r--utils/TableGen/TableGenBackends.h1
-rwxr-xr-xutils/analyzer/CmpRuns.py191
-rw-r--r--utils/analyzer/SATestAdd.py4
-rw-r--r--utils/analyzer/SATestBuild.py272
-rwxr-xr-xutils/analyzer/SATestUpdateDiffs.py37
-rw-r--r--utils/analyzer/SATestUtils.py21
-rwxr-xr-xutils/bash-autocomplete.sh46
-rwxr-xr-xutils/check_cfc/check_cfc.py2
-rwxr-xr-xutils/clangdiag.py4
-rw-r--r--utils/find-unused-diagnostics.sh2
-rw-r--r--utils/hmaptool/CMakeLists.txt16
-rwxr-xr-xutils/hmaptool/hmaptool296
-rw-r--r--www/OpenProjects.html2
-rw-r--r--www/analyzer/alpha_checks.html8
-rw-r--r--www/analyzer/available_checks.html36
-rw-r--r--www/analyzer/checker_dev_manual.html4
-rw-r--r--www/analyzer/open_projects.html2
-rw-r--r--www/analyzer/scan-build.html2
-rw-r--r--www/comparison.html28
-rw-r--r--www/cxx_dr_status.html1204
-rw-r--r--www/cxx_status.html228
-rw-r--r--www/diagnostics.html2
-rw-r--r--www/features.html2
-rw-r--r--www/get_involved.html2
-rw-r--r--www/hacking.html2
-rw-r--r--www/index.html18
-rwxr-xr-xwww/make_cxx_dr_status5
-rw-r--r--www/related.html22
4332 files changed, 230027 insertions, 101482 deletions
diff --git a/.clang-tidy b/.clang-tidy
index d10f688e5913..2cfcc2ac22b6 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -5,8 +5,13 @@ CheckOptions:
- key: readability-identifier-naming.EnumCase
value: CamelCase
- key: readability-identifier-naming.FunctionCase
- value: lowerCase
+ value: camelBack
+ - key: readability-identifier-naming.MemberCase
+ value: CamelCase
+ - key: readability-identifier-naming.ParameterCase
+ value: CamelCase
- key: readability-identifier-naming.UnionCase
value: CamelCase
- key: readability-identifier-naming.VariableCase
value: CamelCase
+
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2eee8e6148f7..52b881939499 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -212,6 +212,15 @@ set(ENABLE_LINKER_BUILD_ID OFF CACHE BOOL "pass --build-id to ld")
set(ENABLE_X86_RELAX_RELOCATIONS OFF CACHE BOOL
"enable x86 relax relocations by default")
+set(ENABLE_EXPERIMENTAL_NEW_PASS_MANAGER FALSE CACHE BOOL
+ "Enable the experimental new pass manager by default.")
+
+# TODO: verify the values against LangStandards.def?
+set(CLANG_DEFAULT_STD_C "" CACHE STRING
+ "Default standard to use for C/ObjC code (IDENT from LangStandards.def, empty for platform default)")
+set(CLANG_DEFAULT_STD_CXX "" CACHE STRING
+ "Default standard to use for C++/ObjC++ code (IDENT from LangStandards.def, empty for platform default)")
+
set(CLANG_DEFAULT_LINKER "" CACHE STRING
"Default linker to use (linker name or absolute path, empty for platform default)")
@@ -418,11 +427,11 @@ endif()
# Clang version information
set(CLANG_EXECUTABLE_VERSION
- "${CLANG_VERSION_MAJOR}.${CLANG_VERSION_MINOR}" CACHE STRING
- "Version number that will be placed into the clang executable, in the form XX.YY")
+ "${CLANG_VERSION_MAJOR}" CACHE STRING
+ "Major version number that will be appended to the clang executable name")
set(LIBCLANG_LIBRARY_VERSION
- "${CLANG_VERSION_MAJOR}.${CLANG_VERSION_MINOR}" CACHE STRING
- "Version number that will be placed into the libclang library , in the form XX.YY")
+ "${CLANG_VERSION_MAJOR}" CACHE STRING
+ "Major version number that will be appended to the libclang library")
mark_as_advanced(CLANG_EXECUTABLE_VERSION LIBCLANG_LIBRARY_VERSION)
option(CLANG_INCLUDE_TESTS
@@ -574,6 +583,10 @@ if (CLANG_ENABLE_BOOTSTRAP)
endif()
endif()
+ if(CLANG_BOOTSTRAP_EXTRA_DEPS)
+ add_dependencies(clang-bootstrap-deps ${CLANG_BOOTSTRAP_EXTRA_DEPS})
+ endif()
+
add_custom_target(${NEXT_CLANG_STAGE}-clear
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${NEXT_CLANG_STAGE}-cleared
)
@@ -608,10 +621,15 @@ if (CLANG_ENABLE_BOOTSTRAP)
LLVM_ENABLE_PROJECTS
LLVM_ENABLE_RUNTIMES)
- # We don't need to depend on compiler-rt if we're building instrumented
+ # We don't need to depend on compiler-rt/libcxx if we're building instrumented
# because the next stage will use the same compiler used to build this stage.
- if(TARGET compiler-rt AND NOT LLVM_BUILD_INSTRUMENTED)
- add_dependencies(clang-bootstrap-deps compiler-rt)
+ if(NOT LLVM_BUILD_INSTRUMENTED)
+ if(TARGET compiler-rt)
+ add_dependencies(clang-bootstrap-deps compiler-rt)
+ endif()
+ if(TARGET cxx-headers)
+ add_dependencies(clang-bootstrap-deps cxx-headers)
+ endif()
endif()
set(C_COMPILER "clang")
@@ -624,7 +642,8 @@ if (CLANG_ENABLE_BOOTSTRAP)
set(COMPILER_OPTIONS
-DCMAKE_CXX_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/${CXX_COMPILER}
-DCMAKE_C_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/${C_COMPILER}
- -DCMAKE_ASM_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/${C_COMPILER})
+ -DCMAKE_ASM_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/${C_COMPILER}
+ -DCMAKE_ASM_COMPILER_ID=Clang)
if(BOOTSTRAP_LLVM_BUILD_INSTRUMENTED)
add_dependencies(clang-bootstrap-deps llvm-profdata)
@@ -739,6 +758,7 @@ endif()
if (LLVM_ADD_NATIVE_VISUALIZERS_TO_SOLUTION)
add_subdirectory(utils/ClangVisualizers)
endif()
+add_subdirectory(utils/hmaptool)
configure_file(
${CLANG_SOURCE_DIR}/include/clang/Config/config.h.cmake
diff --git a/LICENSE.TXT b/LICENSE.TXT
index b452ca2efd8f..547f6a489382 100644
--- a/LICENSE.TXT
+++ b/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/bindings/python/clang/cindex.py b/bindings/python/clang/cindex.py
index b53661a4d0ae..56fcc78763e3 100644
--- a/bindings/python/clang/cindex.py
+++ b/bindings/python/clang/cindex.py
@@ -881,7 +881,7 @@ CursorKind.INVALID_CODE = CursorKind(73)
CursorKind.UNEXPOSED_EXPR = CursorKind(100)
# An expression that refers to some value declaration, such as a function,
-# varible, or enumerator.
+# variable, or enumerator.
CursorKind.DECL_REF_EXPR = CursorKind(101)
# An expression that refers to a member of a struct, union, class, Objective-C
@@ -1501,7 +1501,7 @@ class Cursor(Structure):
return conf.lib.clang_getCursorDefinition(self)
def get_usr(self):
- """Return the Unified Symbol Resultion (USR) for the entity referenced
+ """Return the Unified Symbol Resolution (USR) for the entity referenced
by the given cursor (or None).
A Unified Symbol Resolution (USR) is a string that identifies a
@@ -1511,6 +1511,12 @@ class Cursor(Structure):
another translation unit."""
return conf.lib.clang_getCursorUSR(self)
+ def get_included_file(self):
+ """Returns the File that is included by the current inclusion cursor."""
+ assert self.kind == CursorKind.INCLUSION_DIRECTIVE
+
+ return conf.lib.clang_getIncludedFile(self)
+
@property
def kind(self):
"""Return the kind of this cursor."""
@@ -1644,7 +1650,7 @@ class Cursor(Structure):
def result_type(self):
"""Retrieve the Type of the result for this Cursor."""
if not hasattr(self, '_result_type'):
- self._result_type = conf.lib.clang_getResultType(self.type)
+ self._result_type = conf.lib.clang_getCursorResultType(self)
return self._result_type
@@ -3085,8 +3091,9 @@ class File(ClangObject):
return "<File: %s>" % (self.name)
@staticmethod
- def from_cursor_result(res, fn, args):
- assert isinstance(res, File)
+ def from_result(res, fn, args):
+ assert isinstance(res, c_object_p)
+ res = File(res)
# Copy a reference to the TranslationUnit to prevent premature GC.
res._tu = args[0]._tu
@@ -3568,6 +3575,11 @@ functionList = [
[Cursor, c_uint, c_uint],
SourceRange),
+ ("clang_getCursorResultType",
+ [Cursor],
+ Type,
+ Type.from_result),
+
("clang_getCursorSemanticParent",
[Cursor],
Cursor,
@@ -3696,8 +3708,8 @@ functionList = [
("clang_getIncludedFile",
[Cursor],
- File,
- File.from_cursor_result),
+ c_object_p,
+ File.from_result),
("clang_getInclusions",
[TranslationUnit, callbacks['translation_unit_includes'], py_object]),
diff --git a/bindings/python/tests/cindex/test_cdb.py b/bindings/python/tests/cindex/test_cdb.py
index bd6e77329f69..64651af31732 100644
--- a/bindings/python/tests/cindex/test_cdb.py
+++ b/bindings/python/tests/cindex/test_cdb.py
@@ -5,11 +5,13 @@ from clang.cindex import CompileCommand
import os
import gc
import unittest
+import sys
kInputsDir = os.path.join(os.path.dirname(__file__), 'INPUTS')
+@unittest.skipIf(sys.platform == 'win32', "TODO: Fix these tests on Windows")
class TestCDB(unittest.TestCase):
def test_create_fail(self):
"""Check we fail loading a database with an assertion"""
diff --git a/bindings/python/tests/cindex/test_cursor.py b/bindings/python/tests/cindex/test_cursor.py
index c2a4eb57d02f..f5733fd15879 100644
--- a/bindings/python/tests/cindex/test_cursor.py
+++ b/bindings/python/tests/cindex/test_cursor.py
@@ -335,7 +335,7 @@ class TestCursor(unittest.TestCase):
self.assertEqual(enum.kind, CursorKind.ENUM_DECL)
enum_type = enum.enum_type
- self.assertEqual(enum_type.kind, TypeKind.UINT)
+ self.assertIn(enum_type.kind, (TypeKind.UINT, TypeKind.INT))
def test_enum_type_cpp(self):
tu = get_tu('enum TEST : long long { FOO=1, BAR=2 };', lang="cpp")
@@ -429,6 +429,18 @@ class TestCursor(unittest.TestCase):
t = foo.result_type
self.assertEqual(t.kind, TypeKind.INT)
+ def test_result_type_objc_method_decl(self):
+ code = """\
+ @interface Interface : NSObject
+ -(void)voidMethod;
+ @end
+ """
+ tu = get_tu(code, lang='objc')
+ cursor = get_cursor(tu, 'voidMethod')
+ result_type = cursor.result_type
+ self.assertEqual(cursor.kind, CursorKind.OBJC_INSTANCE_METHOD_DECL)
+ self.assertEqual(result_type.kind, TypeKind.VOID)
+
def test_availability(self):
tu = get_tu('class A { A(A const&) = delete; };', lang='cpp')
@@ -549,4 +561,4 @@ class TestCursor(unittest.TestCase):
# all valid manglings.
# [c-index-test handles this by running the source through clang, emitting
# an AST file and running libclang on that AST file]
- self.assertIn(foo.mangled_name, ('_Z3fooii', '__Z3fooii', '?foo@@YAHHH'))
+ self.assertIn(foo.mangled_name, ('_Z3fooii', '__Z3fooii', '?foo@@YAHHH', '?foo@@YAHHH@Z'))
diff --git a/bindings/python/tests/cindex/test_translation_unit.py b/bindings/python/tests/cindex/test_translation_unit.py
index 1b3973d59f63..d3ee535f4d0d 100644
--- a/bindings/python/tests/cindex/test_translation_unit.py
+++ b/bindings/python/tests/cindex/test_translation_unit.py
@@ -1,3 +1,4 @@
+from contextlib import contextmanager
import gc
import os
import tempfile
@@ -19,15 +20,15 @@ from .util import get_tu
kInputsDir = os.path.join(os.path.dirname(__file__), 'INPUTS')
+@contextmanager
def save_tu(tu):
"""Convenience API to save a TranslationUnit to a file.
Returns the filename it was saved to.
"""
- _, path = tempfile.mkstemp()
- tu.save(path)
-
- return path
+ with tempfile.NamedTemporaryFile() as t:
+ tu.save(t.name)
+ yield t.name
class TestTranslationUnit(unittest.TestCase):
@@ -108,15 +109,26 @@ int SOME_DEFINE;
for i in zip(inc, tu.get_includes()):
eq(i[0], i[1])
+ def test_inclusion_directive(self):
+ src = os.path.join(kInputsDir, 'include.cpp')
+ h1 = os.path.join(kInputsDir, "header1.h")
+ h2 = os.path.join(kInputsDir, "header2.h")
+ h3 = os.path.join(kInputsDir, "header3.h")
+ inc = [h1, h3, h2, h3, h1]
+
+ tu = TranslationUnit.from_source(src, options=TranslationUnit.PARSE_DETAILED_PROCESSING_RECORD)
+ inclusion_directive_files = [c.get_included_file().name for c in tu.cursor.get_children() if c.kind == CursorKind.INCLUSION_DIRECTIVE]
+ for i in zip(inc, inclusion_directive_files):
+ self.assert_normpaths_equal(i[0], i[1])
+
def test_save(self):
"""Ensure TranslationUnit.save() works."""
tu = get_tu('int foo();')
- path = save_tu(tu)
- self.assertTrue(os.path.exists(path))
- self.assertGreater(os.path.getsize(path), 0)
- os.unlink(path)
+ with save_tu(tu) as path:
+ self.assertTrue(os.path.exists(path))
+ self.assertGreater(os.path.getsize(path), 0)
def test_save_translation_errors(self):
"""Ensure that saving to an invalid directory raises."""
@@ -137,21 +149,18 @@ int SOME_DEFINE;
tu = get_tu('int foo();')
self.assertEqual(len(tu.diagnostics), 0)
- path = save_tu(tu)
-
- self.assertTrue(os.path.exists(path))
- self.assertGreater(os.path.getsize(path), 0)
-
- tu2 = TranslationUnit.from_ast_file(filename=path)
- self.assertEqual(len(tu2.diagnostics), 0)
+ with save_tu(tu) as path:
+ self.assertTrue(os.path.exists(path))
+ self.assertGreater(os.path.getsize(path), 0)
- foo = get_cursor(tu2, 'foo')
- self.assertIsNotNone(foo)
+ tu2 = TranslationUnit.from_ast_file(filename=path)
+ self.assertEqual(len(tu2.diagnostics), 0)
- # Just in case there is an open file descriptor somewhere.
- del tu2
+ foo = get_cursor(tu2, 'foo')
+ self.assertIsNotNone(foo)
- os.unlink(path)
+ # Just in case there is an open file descriptor somewhere.
+ del tu2
def test_index_parse(self):
path = os.path.join(kInputsDir, 'hello.cpp')
diff --git a/cmake/caches/Apple-stage2.cmake b/cmake/caches/Apple-stage2.cmake
index d58e4b6fafd5..c7f3f04b420a 100644
--- a/cmake/caches/Apple-stage2.cmake
+++ b/cmake/caches/Apple-stage2.cmake
@@ -21,7 +21,7 @@ set(BUG_REPORT_URL "http://developer.apple.com/bugreporter/" CACHE STRING "")
set(LLVM_BUILD_EXTERNAL_COMPILER_RT ON CACHE BOOL "Build Compiler-RT with just-built clang")
set(COMPILER_RT_ENABLE_IOS ON CACHE BOOL "Build iOS Compiler-RT libraries")
-set(LLVM_CREATE_XCODE_TOOLCHAIN ON CACHE BOOL "Generate targets to create and install an Xcode compatable toolchain")
+set(LLVM_CREATE_XCODE_TOOLCHAIN ON CACHE BOOL "Generate targets to create and install an Xcode compatible toolchain")
# Make unit tests (if present) part of the ALL target
set(LLVM_BUILD_TESTS ON CACHE BOOL "")
@@ -47,7 +47,7 @@ set(LLVM_CREATE_XCODE_TOOLCHAIN ON CACHE BOOL "")
# setup toolchain
set(LLVM_INSTALL_TOOLCHAIN_ONLY ON CACHE BOOL "")
set(LLVM_TOOLCHAIN_TOOLS
- llvm-dsymutil
+ dsymutil
llvm-cov
llvm-dwarfdump
llvm-profdata
diff --git a/cmake/caches/BaremetalARM.cmake b/cmake/caches/BaremetalARM.cmake
index 73f797d9c4b1..d9d2efcbb4bb 100644
--- a/cmake/caches/BaremetalARM.cmake
+++ b/cmake/caches/BaremetalARM.cmake
@@ -24,11 +24,11 @@ set(BUILTINS_armv7em-none-eabi_COMPILER_RT_OS_DIR "baremetal" CACHE STRING "armv
set(LLVM_INSTALL_TOOLCHAIN_ONLY ON CACHE BOOL "")
set(LLVM_TOOLCHAIN_TOOLS
+ dsymutil
llc
llvm-ar
llvm-cxxfilt
llvm-dwarfdump
- llvm-dsymutil
llvm-nm
llvm-objdump
llvm-ranlib
diff --git a/cmake/caches/DistributionExample-stage2.cmake b/cmake/caches/DistributionExample-stage2.cmake
index 894ea6af6c39..600ba56e4563 100644
--- a/cmake/caches/DistributionExample-stage2.cmake
+++ b/cmake/caches/DistributionExample-stage2.cmake
@@ -10,7 +10,7 @@ set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -gline-tables-only -DNDEBUG" CACHE STRIN
# setup toolchain
set(LLVM_INSTALL_TOOLCHAIN_ONLY ON CACHE BOOL "")
set(LLVM_TOOLCHAIN_TOOLS
- llvm-dsymutil
+ dsymutil
llvm-cov
llvm-dwarfdump
llvm-profdata
diff --git a/cmake/caches/Fuchsia-stage2.cmake b/cmake/caches/Fuchsia-stage2.cmake
index 7ad2d9c60765..28e179513475 100644
--- a/cmake/caches/Fuchsia-stage2.cmake
+++ b/cmake/caches/Fuchsia-stage2.cmake
@@ -8,6 +8,7 @@ set(PACKAGE_VENDOR Fuchsia CACHE STRING "")
set(LLVM_INCLUDE_EXAMPLES OFF CACHE BOOL "")
set(LLVM_INCLUDE_DOCS OFF CACHE BOOL "")
set(LLVM_ENABLE_BACKTRACES OFF CACHE BOOL "")
+set(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR ON CACHE BOOL "")
set(LLVM_ENABLE_TERMINFO OFF CACHE BOOL "")
set(LLVM_ENABLE_ZLIB ON CACHE BOOL "")
set(LLVM_EXTERNALIZE_DEBUGINFO ON CACHE BOOL "")
@@ -17,55 +18,115 @@ set(LLVM_ENABLE_LTO ON CACHE BOOL "")
if(NOT APPLE)
set(LLVM_ENABLE_LLD ON CACHE BOOL "")
set(CLANG_DEFAULT_LINKER lld CACHE STRING "")
+ set(CLANG_DEFAULT_OBJCOPY llvm-objcopy CACHE STRING "")
endif()
-
-if(APPLE)
- set(LLDB_CODESIGN_IDENTITY "" CACHE STRING "")
-endif()
+set(CLANG_DEFAULT_CXX_STDLIB libc++ CACHE STRING "")
+set(CLANG_DEFAULT_RTLIB compiler-rt CACHE STRING "")
set(LLVM_ENABLE_ASSERTIONS ON CACHE BOOL "")
set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O3 -gline-tables-only -DNDEBUG" CACHE STRING "")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -gline-tables-only -DNDEBUG" CACHE STRING "")
-set(LLVM_BUILTIN_TARGETS "default;x86_64-fuchsia;aarch64-fuchsia" CACHE STRING "")
-foreach(target x86_64;aarch64)
- set(BUILTINS_${target}-fuchsia_CMAKE_SYSROOT ${FUCHSIA_${target}_SYSROOT} CACHE PATH "")
- set(BUILTINS_${target}-fuchsia_CMAKE_SYSTEM_NAME Fuchsia CACHE STRING "")
-endforeach()
+if(APPLE)
+ list(APPEND BUILTIN_TARGETS "default")
+ list(APPEND RUNTIME_TARGETS "default")
+elseif(UNIX)
+ foreach(target i386;x86_64;armhf;aarch64)
+ if(LINUX_${target}_SYSROOT)
+ # Set the per-target builtins options.
+ list(APPEND BUILTIN_TARGETS "${target}-linux-gnu")
+ set(BUILTINS_${target}-linux-gnu_CMAKE_SYSTEM_NAME Linux CACHE STRING "")
+ set(BUILTINS_${target}-linux-gnu_CMAKE_BUILD_TYPE Release CACHE STRING "")
+ set(BUILTINS_${target}-linux-gnu_CMAKE_SYSROOT ${LINUX_${target}_SYSROOT} CACHE STRING "")
+
+ # Set the per-target runtimes options.
+ list(APPEND RUNTIME_TARGETS "${target}-linux-gnu")
+ set(RUNTIMES_${target}-linux-gnu_CMAKE_SYSTEM_NAME Linux CACHE STRING "")
+ set(RUNTIMES_${target}-linux-gnu_CMAKE_BUILD_TYPE Release CACHE STRING "")
+ set(RUNTIMES_${target}-linux-gnu_CMAKE_SYSROOT ${LINUX_${target}_SYSROOT} CACHE STRING "")
+ set(RUNTIMES_${target}-linux-gnu_LLVM_ENABLE_ASSERTIONS ON CACHE BOOL "")
+ set(RUNTIMES_${target}-linux-gnu_LIBUNWIND_ENABLE_SHARED OFF CACHE BOOL "")
+ set(RUNTIMES_${target}-linux-gnu_LIBUNWIND_USE_COMPILER_RT ON CACHE BOOL "")
+ set(RUNTIMES_${target}-linux-gnu_LIBUNWIND_INSTALL_LIBRARY OFF CACHE BOOL "")
+ set(RUNTIMES_${target}-linux-gnu_LIBCXXABI_USE_COMPILER_RT ON CACHE BOOL "")
+ set(RUNTIMES_${target}-linux-gnu_LIBCXXABI_ENABLE_SHARED OFF CACHE BOOL "")
+ set(RUNTIMES_${target}-linux-gnu_LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "")
+ set(RUNTIMES_${target}-linux-gnu_LIBCXXABI_ENABLE_STATIC_UNWINDER ON CACHE BOOL "")
+ set(RUNTIMES_${target}-linux-gnu_LIBCXXABI_INSTALL_LIBRARY OFF CACHE BOOL "")
+ set(RUNTIMES_${target}-linux-gnu_LIBCXX_USE_COMPILER_RT ON CACHE BOOL "")
+ set(RUNTIMES_${target}-linux-gnu_LIBCXX_ENABLE_SHARED OFF CACHE BOOL "")
+ set(RUNTIMES_${target}-linux-gnu_LIBCXX_ENABLE_STATIC_ABI_LIBRARY ON CACHE BOOL "")
+ set(RUNTIMES_${target}-linux-gnu_SANITIZER_CXX_ABI "libc++" CACHE STRING "")
+ set(RUNTIMES_${target}-linux-gnu_SANITIZER_CXX_ABI_INTREE ON CACHE BOOL "")
+ set(RUNTIMES_${target}-linux-gnu_COMPILER_RT_USE_BUILTINS_LIBRARY ON CACHE BOOL "")
+ endif()
+ endforeach()
+endif()
+
+if(FUCHSIA_SDK)
+ set(FUCHSIA_aarch64_NAME arm64)
+ set(FUCHSIA_x86_64_NAME x64)
+ foreach(target x86_64;aarch64)
+ set(FUCHSIA_${target}_COMPILER_FLAGS "-I${FUCHSIA_SDK}/pkg/fdio/include")
+ set(FUCHSIA_${target}_LINKER_FLAGS "-L${FUCHSIA_SDK}/arch/${FUCHSIA_${target}_NAME}/lib")
+ set(FUCHSIA_${target}_SYSROOT "${FUCHSIA_SDK}/arch/${FUCHSIA_${target}_NAME}/sysroot")
+ endforeach()
+
+ foreach(target x86_64;aarch64)
+ # Set the per-target builtins options.
+ list(APPEND BUILTIN_TARGETS "${target}-fuchsia")
+ set(BUILTINS_${target}-fuchsia_CMAKE_SYSTEM_NAME Fuchsia CACHE STRING "")
+ set(BUILTINS_${target}-fuchsia_CMAKE_BUILD_TYPE Release CACHE STRING "")
+ set(BUILTINS_${target}-fuchsia_CMAKE_ASM_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE PATH "")
+ set(BUILTINS_${target}-fuchsia_CMAKE_C_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE PATH "")
+ set(BUILTINS_${target}-fuchsia_CMAKE_CXX_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE PATH "")
+ set(BUILTINS_${target}-fuchsia_CMAKE_SHARED_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE PATH "")
+ set(BUILTINS_${target}-fuchsia_CMAKE_MODULE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE PATH "")
+ set(BUILTINS_${target}-fuchsia_CMAKE_EXE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE PATH "")
+ set(BUILTINS_${target}-fuchsia_CMAKE_SYSROOT ${FUCHSIA_${target}_SYSROOT} CACHE PATH "")
-set(LLVM_RUNTIME_TARGETS "default;x86_64-fuchsia;aarch64-fuchsia;x86_64-fuchsia-asan:x86_64-fuchsia;aarch64-fuchsia-asan:aarch64-fuchsia" CACHE STRING "")
-foreach(target x86_64;aarch64)
- set(RUNTIMES_${target}-fuchsia_CMAKE_BUILD_WITH_INSTALL_RPATH ON CACHE BOOL "")
- set(RUNTIMES_${target}-fuchsia_CMAKE_SYSROOT ${FUCHSIA_${target}_SYSROOT} CACHE PATH "")
- set(RUNTIMES_${target}-fuchsia_CMAKE_SYSTEM_NAME Fuchsia CACHE STRING "")
- set(RUNTIMES_${target}-fuchsia_UNIX 1 CACHE BOOL "")
- set(RUNTIMES_${target}-fuchsia_LLVM_ENABLE_LIBCXX ON CACHE BOOL "")
- set(RUNTIMES_${target}-fuchsia_LIBUNWIND_USE_COMPILER_RT ON CACHE BOOL "")
- set(RUNTIMES_${target}-fuchsia_LIBUNWIND_ENABLE_STATIC OFF CACHE BOOL "")
- set(RUNTIMES_${target}-fuchsia_LIBCXXABI_USE_COMPILER_RT ON CACHE BOOL "")
- set(RUNTIMES_${target}-fuchsia_LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "")
- set(RUNTIMES_${target}-fuchsia_LIBCXXABI_ENABLE_STATIC OFF CACHE BOOL "")
- set(RUNTIMES_${target}-fuchsia_LIBCXX_USE_COMPILER_RT ON CACHE BOOL "")
- set(RUNTIMES_${target}-fuchsia_LIBCXX_ABI_VERSION 2 CACHE STRING "")
- set(RUNTIMES_${target}-fuchsia_LIBCXX_ENABLE_STATIC OFF CACHE BOOL "")
- set(RUNTIMES_${target}-fuchsia_SANITIZER_USE_COMPILER_RT ON CACHE BOOL "")
+ # Set the per-target runtimes options.
+ list(APPEND RUNTIME_TARGETS "${target}-fuchsia")
+ set(RUNTIMES_${target}-fuchsia_CMAKE_SYSTEM_NAME Fuchsia CACHE STRING "")
+ set(RUNTIMES_${target}-fuchsia_CMAKE_BUILD_TYPE Release CACHE STRING "")
+ set(RUNTIMES_${target}-fuchsia_CMAKE_BUILD_WITH_INSTALL_RPATH ON CACHE STRING "")
+ set(RUNTIMES_${target}-fuchsia_CMAKE_ASM_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE PATH "")
+ set(RUNTIMES_${target}-fuchsia_CMAKE_C_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE PATH "")
+ set(RUNTIMES_${target}-fuchsia_CMAKE_CXX_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE PATH "")
+ set(RUNTIMES_${target}-fuchsia_CMAKE_SHARED_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE PATH "")
+ set(RUNTIMES_${target}-fuchsia_CMAKE_MODULE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE PATH "")
+ set(RUNTIMES_${target}-fuchsia_CMAKE_EXE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE PATH "")
+ set(RUNTIMES_${target}-fuchsia_CMAKE_SYSROOT ${FUCHSIA_${target}_SYSROOT} CACHE PATH "")
+ set(RUNTIMES_${target}-fuchsia_LLVM_ENABLE_ASSERTIONS ON CACHE BOOL "")
+ set(RUNTIMES_${target}-fuchsia_LIBUNWIND_USE_COMPILER_RT ON CACHE BOOL "")
+ set(RUNTIMES_${target}-fuchsia_LIBUNWIND_INSTALL_STATIC_LIBRARY OFF CACHE BOOL "")
+ set(RUNTIMES_${target}-fuchsia_LIBCXXABI_USE_COMPILER_RT ON CACHE BOOL "")
+ set(RUNTIMES_${target}-fuchsia_LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "")
+ set(RUNTIMES_${target}-fuchsia_LIBCXXABI_ENABLE_STATIC_UNWINDER ON CACHE BOOL "")
+ set(RUNTIMES_${target}-fuchsia_LIBCXXABI_INSTALL_STATIC_LIBRARY OFF CACHE BOOL "")
+ set(RUNTIMES_${target}-fuchsia_LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_SHARED_LIBRARY OFF CACHE BOOL "")
+ set(RUNTIMES_${target}-fuchsia_LIBCXX_USE_COMPILER_RT ON CACHE BOOL "")
+ set(RUNTIMES_${target}-fuchsia_LIBCXX_ENABLE_STATIC_ABI_LIBRARY ON CACHE BOOL "")
+ set(RUNTIMES_${target}-fuchsia_LIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY OFF CACHE BOOL "")
+ endforeach()
+
+ set(LLVM_RUNTIME_SANITIZERS "Address" CACHE STRING "")
+ set(LLVM_RUNTIME_SANITIZER_Address_TARGETS "x86_64-fuchsia;aarch64-fuchsia" CACHE STRING "")
+endif()
- set(RUNTIMES_${target}-fuchsia-asan_LLVM_USE_SANITIZER Address CACHE STRING "")
- set(RUNTIMES_${target}-fuchsia-asan_LLVM_RUNTIMES_PREFIX "${target}-fuchsia/" CACHE STRING "")
- set(RUNTIMES_${target}-fuchsia-asan_LLVM_RUNTIMES_LIBDIR_SUFFIX "/asan" CACHE STRING "")
- set(RUNTIMES_${target}-fuchsia-asan_LIBCXX_INSTALL_HEADERS OFF CACHE BOOL "")
-endforeach()
+set(LLVM_BUILTIN_TARGETS "${BUILTIN_TARGETS}" CACHE STRING "")
+set(LLVM_RUNTIME_TARGETS "${RUNTIME_TARGETS}" CACHE STRING "")
# Setup toolchain.
set(LLVM_INSTALL_TOOLCHAIN_ONLY ON CACHE BOOL "")
set(LLVM_TOOLCHAIN_TOOLS
+ dsymutil
llc
llvm-ar
llvm-cov
llvm-cxxfilt
llvm-dwarfdump
- llvm-dsymutil
llvm-lib
llvm-nm
llvm-objcopy
@@ -75,6 +136,7 @@ set(LLVM_TOOLCHAIN_TOOLS
llvm-readelf
llvm-readobj
llvm-size
+ llvm-strip
llvm-symbolizer
opt
sancov
@@ -82,12 +144,12 @@ set(LLVM_TOOLCHAIN_TOOLS
set(LLVM_DISTRIBUTION_COMPONENTS
clang
+ libclang
lld
- lldb
- liblldb
LTO
clang-format
clang-headers
+ clang-include-fixer
clang-refactor
clang-tidy
clangd
diff --git a/cmake/caches/Fuchsia.cmake b/cmake/caches/Fuchsia.cmake
index 0d8159294e27..fc7dae849935 100644
--- a/cmake/caches/Fuchsia.cmake
+++ b/cmake/caches/Fuchsia.cmake
@@ -7,10 +7,11 @@ set(PACKAGE_VENDOR Fuchsia CACHE STRING "")
set(LLVM_INCLUDE_EXAMPLES OFF CACHE BOOL "")
set(LLVM_INCLUDE_TESTS OFF CACHE BOOL "")
set(LLVM_INCLUDE_DOCS OFF CACHE BOOL "")
-set(CLANG_INCLUDE_TESTS OFF CACHE BOOL "")
set(LLVM_ENABLE_BACKTRACES OFF CACHE BOOL "")
+set(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR ON CACHE BOOL "")
set(LLVM_ENABLE_TERMINFO OFF CACHE BOOL "")
set(LLVM_ENABLE_ZLIB OFF CACHE BOOL "")
+set(CLANG_INCLUDE_TESTS OFF CACHE BOOL "")
set(CLANG_PLUGIN_SUPPORT OFF CACHE BOOL "")
set(LLVM_ENABLE_ASSERTIONS ON CACHE BOOL "")
@@ -21,10 +22,25 @@ if(NOT APPLE)
set(BOOTSTRAP_LLVM_ENABLE_LLD ON CACHE BOOL "")
endif()
+set(CLANG_DEFAULT_CXX_STDLIB libc++ CACHE STRING "")
+set(CLANG_DEFAULT_RTLIB compiler-rt CACHE STRING "")
+
if(APPLE)
set(COMPILER_RT_ENABLE_IOS OFF CACHE BOOL "")
set(COMPILER_RT_ENABLE_TVOS OFF CACHE BOOL "")
set(COMPILER_RT_ENABLE_WATCHOS OFF CACHE BOOL "")
+elseif(UNIX)
+ set(LIBUNWIND_ENABLE_SHARED OFF CACHE BOOL "")
+ set(LIBUNWIND_USE_COMPILER_RT ON CACHE BOOL "")
+ set(LIBUNWIND_INSTALL_LIBRARY OFF CACHE BOOL "")
+ set(LIBCXXABI_USE_COMPILER_RT ON CACHE BOOL "")
+ set(LIBCXXABI_ENABLE_SHARED OFF CACHE BOOL "")
+ set(LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "")
+ set(LIBCXXABI_ENABLE_STATIC_UNWINDER ON CACHE BOOL "")
+ set(LIBCXXABI_INSTALL_LIBRARY OFF CACHE BOOL "")
+ set(LIBCXX_USE_COMPILER_RT ON CACHE BOOL "")
+ set(LIBCXX_ENABLE_SHARED OFF CACHE BOOL "")
+ set(LIBCXX_ENABLE_STATIC_ABI_LIBRARY ON CACHE BOOL "")
endif()
set(CLANG_BOOTSTRAP_TARGETS
@@ -38,16 +54,23 @@ set(CLANG_BOOTSTRAP_TARGETS
clang-test-depends
distribution
install-distribution
+ install-distribution-stripped
clang CACHE STRING "")
-foreach(target x86_64;aarch64)
- if(FUCHSIA_${target}_SYSROOT)
- list(APPEND EXTRA_ARGS -DFUCHSIA_${target}_SYSROOT=${FUCHSIA_${target}_SYSROOT})
+get_cmake_property(variableNames VARIABLES)
+foreach(variableName ${variableNames})
+ if(variableName MATCHES "^STAGE2_")
+ string(REPLACE "STAGE2_" "" new_name ${variableName})
+ list(APPEND EXTRA_ARGS "-D${new_name}=${${variableName}}")
endif()
endforeach()
# Setup the bootstrap build.
set(CLANG_ENABLE_BOOTSTRAP ON CACHE BOOL "")
+set(CLANG_BOOTSTRAP_EXTRA_DEPS
+ builtins
+ runtimes
+ CACHE STRING "")
set(CLANG_BOOTSTRAP_CMAKE_ARGS
${EXTRA_ARGS}
-C ${CMAKE_CURRENT_LIST_DIR}/Fuchsia-stage2.cmake
diff --git a/docs/AddressSanitizer.rst b/docs/AddressSanitizer.rst
index f58995576f91..7549159a39ab 100644
--- a/docs/AddressSanitizer.rst
+++ b/docs/AddressSanitizer.rst
@@ -197,13 +197,17 @@ this purpose.
Disabling Instrumentation with ``__attribute__((no_sanitize("address")))``
--------------------------------------------------------------------------
-Some code should not be instrumented by AddressSanitizer. One may use the
-function attribute ``__attribute__((no_sanitize("address")))`` (which has
-deprecated synonyms `no_sanitize_address` and `no_address_safety_analysis`) to
-disable instrumentation of a particular function. This attribute may not be
-supported by other compilers, so we suggest to use it together with
+Some code should not be instrumented by AddressSanitizer. One may use
+the attribute ``__attribute__((no_sanitize("address")))`` (which has
+deprecated synonyms `no_sanitize_address` and
+`no_address_safety_analysis`) to disable instrumentation of a
+particular function. This attribute may not be supported by other
+compilers, so we suggest to use it together with
``__has_feature(address_sanitizer)``.
+The same attribute used on a global variable prevents AddressSanitizer
+from adding redzones around it and detecting out of bounds accesses.
+
Suppressing Errors in Recompiled Code (Blacklist)
-------------------------------------------------
@@ -272,6 +276,7 @@ AddressSanitizer is supported on:
* OS X 10.7 - 10.11 (i386/x86\_64)
* iOS Simulator
* Android ARM
+* NetBSD i386/x86\_64
* FreeBSD i386/x86\_64 (tested on FreeBSD 11-current)
Ports to various other platforms are in progress.
diff --git a/docs/AutomaticReferenceCounting.rst b/docs/AutomaticReferenceCounting.rst
index fbd1ba4c4d47..bf4d0945672a 100644
--- a/docs/AutomaticReferenceCounting.rst
+++ b/docs/AutomaticReferenceCounting.rst
@@ -974,28 +974,66 @@ It is undefined behavior to access an ownership-qualified object through an
lvalue of a differently-qualified type, except that any non-``__weak`` object
may be read through an ``__unsafe_unretained`` lvalue.
-It is undefined behavior if a managed operation is performed on a ``__strong``
-or ``__weak`` object without a guarantee that it contains a primitive zero
-bit-pattern, or if the storage for such an object is freed or reused without the
-object being first assigned a null pointer.
+It is undefined behavior if the storage of a ``__strong`` or ``__weak``
+object is not properly initialized before the first managed operation
+is performed on the object, or if the storage of such an object is freed
+or reused before the object has been properly deinitialized. Storage for
+a ``__strong`` or ``__weak`` object may be properly initialized by filling
+it with the representation of a null pointer, e.g. by acquiring the memory
+with ``calloc`` or using ``bzero`` to zero it out. A ``__strong`` or
+``__weak`` object may be properly deinitialized by assigning a null pointer
+into it. A ``__strong`` object may also be properly initialized
+by copying into it (e.g. with ``memcpy``) the representation of a
+different ``__strong`` object whose storage has been properly initialized;
+doing this properly deinitializes the source object and causes its storage
+to no longer be properly initialized. A ``__weak`` object may not be
+representation-copied in this way.
+
+These requirements are followed automatically for objects whose
+initialization and deinitialization are under the control of ARC:
+
+* objects of static, automatic, and temporary storage duration
+* instance variables of Objective-C objects
+* elements of arrays where the array object's initialization and
+ deinitialization are under the control of ARC
+* fields of Objective-C struct types where the struct object's
+ initialization and deinitialization are under the control of ARC
+* non-static data members of Objective-C++ non-union class types
+* Objective-C++ objects and arrays of dynamic storage duration created
+ with the ``new`` or ``new[]`` operators and destroyed with the
+ corresponding ``delete`` or ``delete[]`` operator
+
+They are not followed automatically for these objects:
+
+* objects of dynamic storage duration created in other memory, such as
+ that returned by ``malloc``
+* union members
.. admonition:: Rationale
- ARC cannot differentiate between an assignment operator which is intended to
- "initialize" dynamic memory and one which is intended to potentially replace
- a value. Therefore the object's pointer must be valid before letting ARC at
- it. Similarly, C and Objective-C do not provide any language hooks for
- destroying objects held in dynamic memory, so it is the programmer's
- responsibility to avoid leaks (``__strong`` objects) and consistency errors
- (``__weak`` objects).
-
-These requirements are followed automatically in Objective-C++ when creating
-objects of retainable object owner type with ``new`` or ``new[]`` and destroying
-them with ``delete``, ``delete[]``, or a pseudo-destructor expression. Note
-that arrays of nontrivially-ownership-qualified type are not ABI compatible with
-non-ARC code because the element type is non-POD: such arrays that are
-``new[]``'d in ARC translation units cannot be ``delete[]``'d in non-ARC
-translation units and vice-versa.
+ ARC must perform special operations when initializing an object and
+ when destroying it. In many common situations, ARC knows when an
+ object is created and when it is destroyed and can ensure that these
+ operations are performed correctly. Otherwise, however, ARC requires
+ programmer cooperation to establish its initialization invariants
+ because it is infeasible for ARC to dynamically infer whether they
+ are intact. For example, there is no syntactic difference in C between
+ an assignment that is intended by the programmer to initialize a variable
+ and one that is intended to replace the existing value stored there,
+ but ARC must perform one operation or the other. ARC chooses to always
+ assume that objects are initialized (except when it is in charge of
+ initializing them) because the only workable alternative would be to
+ ban all code patterns that could potentially be used to access
+ uninitialized memory, and that would be too limiting. In practice,
+ this is rarely a problem because programmers do not generally need to
+ work with objects for which the requirements are not handled
+ automatically.
+
+Note that dynamically-allocated Objective-C++ arrays of
+nontrivially-ownership-qualified type are not ABI-compatible with non-ARC
+code because the non-ARC code will consider the element type to be POD.
+Such arrays that are ``new[]``'d in ARC translation units cannot be
+``delete[]``'d in non-ARC translation units and vice-versa.
.. _arc.ownership.restrictions.pass_by_writeback:
diff --git a/docs/Block-ABI-Apple.rst b/docs/Block-ABI-Apple.rst
index 7f49bbd40d71..e48a24b43ce5 100644
--- a/docs/Block-ABI-Apple.rst
+++ b/docs/Block-ABI-Apple.rst
@@ -61,6 +61,14 @@ The following flags bits are in use thusly for a possible ABI.2010.3.16:
.. code-block:: c
enum {
+ // Set to true on blocks that have captures (and thus are not true
+ // global blocks) but are known not to escape for various other
+ // reasons. For backward compatiblity with old runtimes, whenever
+ // BLOCK_IS_NOESCAPE is set, BLOCK_IS_GLOBAL is set too. Copying a
+ // non-escaping block returns the original block and releasing such a
+ // block is a no-op, which is exactly how global blocks are handled.
+ BLOCK_IS_NOESCAPE = (1 << 23),
+
BLOCK_HAS_COPY_DISPOSE = (1 << 25),
BLOCK_HAS_CTOR = (1 << 26), // helpers have C++ code
BLOCK_IS_GLOBAL = (1 << 28),
diff --git a/docs/ClangCommandLineReference.rst b/docs/ClangCommandLineReference.rst
index 4d095883a4b7..5c15482cb251 100644
--- a/docs/ClangCommandLineReference.rst
+++ b/docs/ClangCommandLineReference.rst
@@ -36,10 +36,18 @@ Treat source input files as Objective-C inputs
Treat source input files as Objective-C++ inputs
+.. option:: -Qn
+
+Do not emit metadata containing compiler name and version
+
.. option:: -Qunused-arguments
Don't emit warning for unused driver arguments
+.. option:: -Qy
+
+Emit metadata containing compiler name and version
+
.. option:: -Wa,<arg>,<arg2>...
Pass the comma separated arguments in <arg> to the assembler
@@ -61,10 +69,10 @@ Pass <arg> to the ptxas assembler
Pass <arg> to the target offloading toolchain.
.. program:: clang1
-.. option:: -Xopenmp-target=<arg> <arg2>
+.. option:: -Xopenmp-target=<triple> <arg>
.. program:: clang
-Pass <arg> to the specified target offloading toolchain. The triple that identifies the toolchain must be provided after the equals sign.
+Pass <arg> to the target offloading toolchain identified by <triple>.
.. option:: -Z<arg>
@@ -116,10 +124,18 @@ Output path for the plist report
.. option:: -bundle\_loader <arg>
.. program:: clang
+.. option:: -cfguard
+
+Emit tables required for Windows Control Flow Guard.
+
.. option:: -client\_name<arg>
.. option:: -compatibility\_version<arg>
+.. option:: --config <arg>
+
+Specifies configuration file
+
.. option:: --constant-cfstrings
.. option:: -coverage, --coverage
@@ -140,6 +156,10 @@ CUDA GPU architecture (e.g. sm\_35). May be specified more than once.
Compile CUDA code for host only. Has no effect on non-CUDA compilations.
+.. option:: --cuda-include-ptx=<arg>, --no-cuda-include-ptx=<arg>
+
+Include PTX for the follwing GPU architecture (e.g. sm\_35) or 'all'. May be specified more than once.
+
.. option:: --cuda-noopt-device-debug, --no-cuda-noopt-device-debug
Enable device-side debug info generation. Disables ptxas optimizations.
@@ -190,6 +210,14 @@ Use approximate transcendental functions
Flush denormal floating point values to zero in CUDA device mode.
+.. option:: -fcuda-rdc, -fno-cuda-rdc
+
+Generate relocatable device code, also known as separate compilation mode.
+
+.. option:: -ffixed-r19
+
+Reserve the r19 register (Hexagon only)
+
.. option:: -fheinous-gnu-extensions
.. option:: -flat\_namespace
@@ -230,6 +258,8 @@ Display available options
.. option:: --help-hidden
+Display help for hidden options
+
.. option:: -image\_base <arg>
.. option:: -index-header-map
@@ -702,6 +732,14 @@ Print source range spans in numeric form
.. option:: -fdiagnostics-show-category=<arg>
+.. option:: -fdiscard-value-names, -fno-discard-value-names
+
+Discard value names in LLVM IR
+
+.. option:: -fexperimental-isel, -fno-experimental-isel
+
+Enables the experimental global instruction selector
+
.. option:: -fexperimental-new-pass-manager, -fno-experimental-new-pass-manager
Enables an experimental new pass manager in LLVM.
@@ -736,6 +774,10 @@ Level of field padding for AddressSanitizer
Enable linker dead stripping of globals in AddressSanitizer
+.. option:: -fsanitize-address-poison-class-member-array-new-cookie, -fno-sanitize-address-poison-class-member-array-new-cookie
+
+Enable poisoning array cookies when using class member operator new\[\] in AddressSanitizer
+
.. option:: -fsanitize-address-use-after-scope, -fno-sanitize-address-use-after-scope
Enable use-after-scope detection in AddressSanitizer
@@ -868,6 +910,10 @@ Add directory to include search path
Restrict all prior -I flags to double-quoted inclusion and remove current directory from include path
+.. option:: --cuda-path-ignore-env
+
+Ignore environment variables to detect CUDA installation
+
.. option:: --cuda-path=<arg>
CUDA installation path
@@ -912,7 +958,7 @@ Specify the module user build path
Don't verify input files for the modules if the module has been successfully validated or loaded during this build session
-.. option:: -fmodules-validate-system-headers
+.. option:: -fmodules-validate-system-headers, -fno-modules-validate-system-headers
Validate the system headers that a module depends on when loading the module
@@ -920,8 +966,6 @@ Validate the system headers that a module depends on when loading the module
Specify the prebuilt module path
-.. option:: -i<arg>
-
.. option:: -idirafter<arg>, --include-directory-after <arg>, --include-directory-after=<arg>
Add directory to AFTER include search path
@@ -1107,6 +1151,12 @@ Target-independent compilation options
.. option:: -faccess-control, -fno-access-control
+.. option:: -falign-functions, -fno-align-functions
+
+.. program:: clang1
+.. option:: -falign-functions=<arg>
+.. program:: clang
+
.. program:: clang1
.. option:: -faligned-allocation, -faligned-new, -fno-aligned-allocation
.. program:: clang
@@ -1175,6 +1225,10 @@ Load the clang builtins module map file.
.. option:: -fcaret-diagnostics, -fno-caret-diagnostics
+.. option:: -fcf-protection=<arg>, -fcf-protection (equivalent to -fcf-protection=full)
+
+Instrument control-flow architecture protection. Options: return, branch, full, none.
+
.. option:: -fclasspath=<arg>, --CLASSPATH <arg>, --CLASSPATH=<arg>, --classpath <arg>, --classpath=<arg>
.. option:: -fcolor-diagnostics, -fno-color-diagnostics
@@ -1305,6 +1359,8 @@ Use emutls functions to access thread\_local variables
.. option:: -ferror-limit=<arg>
+.. option:: -fescaping-block-tail-calls, -fno-escaping-block-tail-calls
+
.. option:: -fexceptions, -fno-exceptions
Enable support for exception handling
@@ -1321,6 +1377,10 @@ Allow aggressive, lossy floating-point optimizations
.. option:: -ffor-scope, -fno-for-scope
+.. option:: -fforce-enable-int128, -fno-force-enable-int128
+
+Enable support for int128\_t type
+
.. option:: -ffp-contract=<arg>
Form fused FP ops (e.g. FMAs): fast (everywhere) \| on (according to FP\_CONTRACT pragma, default) \| off (never fuse)
@@ -1409,6 +1469,8 @@ Specify the maximum alignment to enforce on pointers lacking an explicit alignme
.. option:: -fmerge-all-constants, -fno-merge-all-constants
+Allow merging of constants
+
.. option:: -fmessage-length=<arg>
.. option:: -fmodule-file-deps, -fno-module-file-deps
@@ -1481,6 +1543,14 @@ Specifies the largest alignment guaranteed by '::operator new(size\_t)'
Disable implicit builtin knowledge of a specific function
+.. option:: -fdelete-null-pointer-checks, -fno-delete-null-pointer-checks
+
+When enabled, treat null pointer dereference, creation of a reference to null,
+or passing a null pointer to a function parameter annotated with the "nonnull"
+attribute as undefined behavior. (And, thus the optimizer may assume that any
+pointer used in such a way must not have been null and optimize away the
+branches accordingly.) On by default.
+
.. option:: -fno-elide-type
Do not elide types when printing diagnostics
@@ -1491,15 +1561,15 @@ Do not elide types when printing diagnostics
Do not treat C++ operator name keywords as synonyms for operators
-.. option:: -fno-strict-modules-decluse
+.. option:: -fno-rtti-data
-.. option:: -fno-working-directory
+Control emission of RTTI data
-.. option:: -fnoopenmp-relocatable-target
+.. option:: -fno-strict-modules-decluse
-Do not compile OpenMP target code as relocatable.
+.. option:: -fno-working-directory
-.. option:: -fnoopenmp-use-tls
+.. option:: -fnoxray-link-deps
.. option:: -fobjc-abi-version=<arg>
@@ -1539,13 +1609,11 @@ Enable ARC-style weak references in Objective-C
.. option:: -fopenmp, -fno-openmp
-.. option:: -fopenmp-dump-offload-linker-script
-
-.. option:: -fopenmp-relocatable-target
+Parse OpenMP pragmas and generate parallel code.
-OpenMP target code is compiled as relocatable using the -c flag. For OpenMP targets the code is relocatable by default.
+.. option:: -fopenmp-simd, -fno-openmp-simd
-.. option:: -fopenmp-use-tls
+Emit OpenMP code only for SIMD-based constructs.
.. option:: -fopenmp-version=<arg>
@@ -1656,6 +1724,10 @@ Allow division operations to be reassociated
Override the default ABI to return small structs in registers
+.. option:: -fregister-global-dtors-with-atexit, -fno-register-global-dtors-with-atexit
+
+Use atexit or \_\_cxa\_atexit to register global destructors
+
.. option:: -frelaxed-template-template-args, -fno-relaxed-template-template-args
Enable C++17 relaxed template template argument matching
@@ -1732,7 +1804,7 @@ Enable the superword-level parallelism vectorization passes
.. option:: -fsplit-dwarf-inlining, -fno-split-dwarf-inlining
-Place debug types in their own section (ELF Only)
+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
.. option:: -fsplit-stack
@@ -1748,6 +1820,10 @@ Force the usage of stack protectors for all functions
Use a strong heuristic to apply stack protectors to functions
+.. option:: -fstack-size-section, -fno-stack-size-section
+
+Emit section containing metadata on function stack sizes
+
.. option:: -fstandalone-debug, -fno-limit-debug-info, -fno-standalone-debug
Emit full debug info for all types used by the program
@@ -1852,7 +1928,7 @@ Enable the loop vectorization passes
.. option:: -fvisibility-inlines-hidden
-Give inline C++ member functions default visibility by default
+Give inline C++ member functions hidden visibility by default
.. option:: -fvisibility-ms-compat
@@ -1866,6 +1942,12 @@ Set the default symbol visibility for all global declarations
Enables whole-program vtable optimization. Requires -flto
+.. option:: -fforce-emit-vtables, -fno-force-emit-vtables
+
+In order to improve devirtualization, forces emitting of vtables even in
+modules where it isn't necessary. It causes more inline virtual functions
+to be emitted.
+
.. option:: -fwrapv, -fno-wrapv
Treat signed integer overflow as two's complement
@@ -1878,9 +1960,17 @@ Store string literals as writable data
Determine whether to always emit \_\_xray\_customevent(...) calls even if the function it appears in is not always instrumented.
+.. option:: -fxray-always-emit-typedevents, -fno-xray-always-emit-typedevents
+
+Determine whether to always emit \_\_xray\_typedevent(...) calls even if the function it appears in is not always instrumented.
+
.. option:: -fxray-always-instrument=<arg>
-Filename defining the whitelist for imbuing the 'always instrument' XRay attribute.
+DEPRECATED: Filename defining the whitelist for imbuing the 'always instrument' XRay attribute.
+
+.. option:: -fxray-attr-list=<arg>
+
+Filename defining the list of functions/types for imbuing XRay attributes.
.. option:: -fxray-instruction-threshold<arg>
@@ -1894,9 +1984,21 @@ Sets the minimum function size to instrument with XRay
Generate XRay instrumentation sleds on function entry and exit
+.. option:: -fxray-instrumentation-bundle=<arg>
+
+Select which XRay instrumentation points to emit. Options: all, none, function, custom. Default is 'all'.
+
+.. option:: -fxray-link-deps
+
+Tells clang to add the link dependencies for XRay.
+
+.. option:: -fxray-modes=<arg>
+
+List of modes to link in by default into XRay instrumented binaries.
+
.. option:: -fxray-never-instrument=<arg>
-Filename defining the whitelist for imbuing the 'never instrument' XRay attribute.
+DEPRECATED: Filename defining the whitelist for imbuing the 'never instrument' XRay attribute.
.. option:: -fzero-initialized-in-bss, -fno-zero-initialized-in-bss
@@ -1954,6 +2056,10 @@ OpenCL language standard to compile for.
OpenCL only. This option is added for compatibility with OpenCL 1.0.
+.. option:: -cl-uniform-work-group-size
+
+OpenCL only. Defines that the global work-size be a multiple of the work-group size specified to clEnqueueNDRangeKernel
+
.. option:: -cl-unsafe-math-optimizations
OpenCL only. Allow unsafe floating-point optimizations. Also implies -cl-no-signed-zeros and -cl-mad-enable.
@@ -1998,7 +2104,7 @@ Link stack frames through backchain on System Z
.. option:: -mconsole<arg>
-.. option:: -mcpu=<arg>, -mv4 (equivalent to -mcpu=hexagonv4), -mv5 (equivalent to -mcpu=hexagonv5), -mv55 (equivalent to -mcpu=hexagonv55), -mv60 (equivalent to -mcpu=hexagonv60), -mv62 (equivalent to -mcpu=hexagonv62)
+.. option:: -mcpu=<arg>, -mv4 (equivalent to -mcpu=hexagonv4), -mv5 (equivalent to -mcpu=hexagonv5), -mv55 (equivalent to -mcpu=hexagonv55), -mv60 (equivalent to -mcpu=hexagonv60), -mv62 (equivalent to -mcpu=hexagonv62), -mv65 (equivalent to -mcpu=hexagonv65)
.. option:: -mdefault-build-attributes<arg>, -mno-default-build-attributes<arg>
@@ -2066,6 +2172,10 @@ Use Intel MCU ABI
(integrated-as) Emit an object file which can be used with an incremental linker
+.. option:: -mindirect-jump=<arg>
+
+Change indirect jump instructions to inhibit speculation
+
.. option:: -miphoneos-version-min=<arg>, -mios-version-min=<arg>
.. option:: -mips16
@@ -2156,6 +2266,10 @@ Use software floating point
Set the stack alignment
+.. option:: -mstack-arg-probe, -mno-stack-arg-probe
+
+Enable stack probes
+
.. option:: -mstack-probe-size=<arg>
Set the stack probe size
@@ -2196,6 +2310,10 @@ AARCH64
Reserve the x18 register (AArch64 only)
+.. option:: -ffixed-x20
+
+Reserve the x20 register (AArch64 only)
+
.. option:: -mfix-cortex-a53-835769, -mno-fix-cortex-a53-835769
Workaround Cortex-A53 erratum 835769 (AArch64 only)
@@ -2252,16 +2370,16 @@ Hexagon
-------
.. option:: -mieee-rnd-near
+.. option:: -mpackets, -mno-packets
+
+Enable generation of instruction packets
+
Hexagon
-------
.. option:: -mhvx, -mno-hvx
Enable Hexagon Vector eXtensions
-.. option:: -mhvx-double, -mno-hvx-double
-
-Enable Hexagon Double Vector eXtensions
-
.. option:: -mhvx-length=<arg>
Set Hexagon Vector Length
@@ -2306,12 +2424,18 @@ PowerPC
.. option:: -mqpx, -mno-qpx
+.. option:: -msecure-plt
+
.. option:: -mvsx, -mno-vsx
WebAssembly
-----------
+.. option:: -mexception-handling, -mno-exception-handling
+
.. option:: -mnontrapping-fptoint, -mno-nontrapping-fptoint
+.. option:: -msign-ext, -mno-sign-ext
+
.. option:: -msimd128, -mno-simd128
X86
@@ -2328,6 +2452,8 @@ X86
.. option:: -mavx2, -mno-avx2
+.. option:: -mavx512bitalg, -mno-avx512bitalg
+
.. option:: -mavx512bw, -mno-avx512bw
.. option:: -mavx512cd, -mno-avx512cd
@@ -2344,14 +2470,20 @@ X86
.. option:: -mavx512vbmi, -mno-avx512vbmi
+.. option:: -mavx512vbmi2, -mno-avx512vbmi2
+
.. option:: -mavx512vl, -mno-avx512vl
+.. option:: -mavx512vnni, -mno-avx512vnni
+
.. option:: -mavx512vpopcntdq, -mno-avx512vpopcntdq
.. option:: -mbmi, -mno-bmi
.. option:: -mbmi2, -mno-bmi2
+.. option:: -mcldemote, -mno-cldemote
+
.. option:: -mclflushopt, -mno-clflushopt
.. option:: -mclwb, -mno-clwb
@@ -2370,7 +2502,7 @@ X86
.. option:: -mfxsr, -mno-fxsr
-.. option:: -mibt, -mno-ibt
+.. option:: -mgfni, -mno-gfni
.. option:: -mlwp, -mno-lwp
@@ -2380,6 +2512,10 @@ X86
.. option:: -mmovbe, -mno-movbe
+.. option:: -mmovdiri, -mno-movdiri
+
+.. option:: -mmovdir64b, -mno-movdir64b
+
.. option:: -mmpx, -mno-mpx
.. option:: -mmwaitx, -mno-mwaitx
@@ -2394,12 +2530,20 @@ X86
.. option:: -mprfchw, -mno-prfchw
+.. option:: -mrdpid, -mno-rdpid
+
.. option:: -mrdrnd, -mno-rdrnd
.. option:: -mrdseed, -mno-rdseed
+.. option:: -mretpoline, -mno-retpoline
+
+.. option:: -mretpoline-external-thunk, -mno-retpoline-external-thunk
+
.. option:: -mrtm, -mno-rtm
+.. option:: -msahf, -mno-sahf
+
.. option:: -msgx, -mno-sgx
.. option:: -msha, -mno-sha
@@ -2424,6 +2568,14 @@ X86
.. option:: -mtbm, -mno-tbm
+.. option:: -mvaes, -mno-vaes
+
+.. option:: -mvpclmulqdq, -mno-vpclmulqdq
+
+.. option:: -mwaitpkg, -mno-waitpkg
+
+.. option:: -mwbnoinvd, -mno-wbnoinvd
+
.. option:: -mx87, -m80387, -mno-x87
.. option:: -mxop, -mno-xop
@@ -2515,6 +2667,10 @@ Debug information flags
.. option:: -gdwarf-aranges
+.. option:: -gembed-source, -gno-embed-source
+
+Embed source text in DWARF debug sections
+
.. option:: -ggnu-pubnames
.. option:: -grecord-gcc-switches, -gno-record-gcc-switches
@@ -2680,6 +2836,8 @@ a Fortran input.
.. option:: -fwhole-file, -fno-whole-file
+.. option:: -imultilib <arg>
+
.. option:: -nocpp
.. option:: -static-libgfortran
@@ -2704,11 +2862,11 @@ Set starting address of BSS to <addr>
.. option:: -Tdata<addr>
-Set starting address of BSS to <addr>
+Set starting address of DATA to <addr>
.. option:: -Ttext<addr>
-Set starting address of BSS to <addr>
+Set starting address of TEXT to <addr>
.. option:: -Wl,<arg>,<arg2>...
diff --git a/docs/ClangFormatStyleOptions.rst b/docs/ClangFormatStyleOptions.rst
index 04267928a92a..e4892d79b91f 100644
--- a/docs/ClangFormatStyleOptions.rst
+++ b/docs/ClangFormatStyleOptions.rst
@@ -490,15 +490,50 @@ the configuration (without a prefix: ``Auto``).
"bbbb" "cccc";
"cccc";
-**AlwaysBreakTemplateDeclarations** (``bool``)
- If ``true``, always break after the ``template<...>`` of a template
- declaration.
+**AlwaysBreakTemplateDeclarations** (``BreakTemplateDeclarationsStyle``)
+ The template declaration breaking style to use.
+
+ Possible values:
+
+ * ``BTDS_No`` (in configuration: ``No``)
+ Do not force break before declaration.
+ ``PenaltyBreakTemplateDeclaration`` is taken into account.
+
+ .. code-block:: c++
+
+ template <typename T> T foo() {
+ }
+ template <typename T> T foo(int aaaaaaaaaaaaaaaaaaaaa,
+ int bbbbbbbbbbbbbbbbbbbbb) {
+ }
+
+ * ``BTDS_MultiLine`` (in configuration: ``MultiLine``)
+ Force break after template declaration only when the following
+ declaration spans multiple lines.
+
+ .. code-block:: c++
+
+ template <typename T> T foo() {
+ }
+ template <typename T>
+ T foo(int aaaaaaaaaaaaaaaaaaaaa,
+ int bbbbbbbbbbbbbbbbbbbbb) {
+ }
+
+ * ``BTDS_Yes`` (in configuration: ``Yes``)
+ Always break after template declaration.
+
+ .. code-block:: c++
+
+ template <typename T>
+ T foo() {
+ }
+ template <typename T>
+ T foo(int aaaaaaaaaaaaaaaaaaaaa,
+ int bbbbbbbbbbbbbbbbbbbbb) {
+ }
- .. code-block:: c++
- true: false:
- template <typename T> vs. template <typename T> class C {};
- class C {};
**BinPackArguments** (``bool``)
If ``false``, a function call's arguments will either be all on the
@@ -629,7 +664,9 @@ the configuration (without a prefix: ``Auto``).
int bar();
}
- * ``bool AfterObjCDeclaration`` Wrap ObjC definitions (``@autoreleasepool``, interfaces, ..).
+ * ``bool AfterObjCDeclaration`` Wrap ObjC definitions (interfaces, implementations...).
+ @autoreleasepool and @synchronized blocks are wrapped
+ according to `AfterControlStatement` flag.
* ``bool AfterStruct`` Wrap struct definitions.
@@ -957,18 +994,6 @@ the configuration (without a prefix: ``Auto``).
-**BreakBeforeInheritanceComma** (``bool``)
- If ``true``, in the class inheritance expression clang-format will
- break before ``:`` and ``,`` if there is multiple inheritance.
-
- .. code-block:: c++
-
- true: false:
- class MyClass vs. class MyClass : public X, public Y {
- : public X };
- , public Y {
- };
-
**BreakBeforeTernaryOperators** (``bool``)
If ``true``, ternary operators will be placed after line breaks.
@@ -994,9 +1019,9 @@ the configuration (without a prefix: ``Auto``).
.. code-block:: c++
- Constructor()
- : initializer1(),
- initializer2()
+ Constructor()
+ : initializer1(),
+ initializer2()
* ``BCIS_BeforeComma`` (in configuration: ``BeforeComma``)
Break constructor initializers before the colon and commas, and align
@@ -1004,18 +1029,56 @@ the configuration (without a prefix: ``Auto``).
.. code-block:: c++
- Constructor()
- : initializer1()
- , initializer2()
+ Constructor()
+ : initializer1()
+ , initializer2()
* ``BCIS_AfterColon`` (in configuration: ``AfterColon``)
Break constructor initializers after the colon and commas.
.. code-block:: c++
- Constructor() :
- initializer1(),
- initializer2()
+ Constructor() :
+ initializer1(),
+ initializer2()
+
+
+
+**BreakInheritanceList** (``BreakInheritanceListStyle``)
+ The inheritance list style to use.
+
+ Possible values:
+
+ * ``BILS_BeforeColon`` (in configuration: ``BeforeColon``)
+ Break inheritance list before the colon and after the commas.
+
+ .. code-block:: c++
+
+ class Foo
+ : Base1,
+ Base2
+ {};
+
+ * ``BILS_BeforeComma`` (in configuration: ``BeforeComma``)
+ Break inheritance list before the colon and commas, and align
+ the commas with the colon.
+
+ .. code-block:: c++
+
+ class Foo
+ : Base1
+ , Base2
+ {};
+
+ * ``BILS_AfterColon`` (in configuration: ``AfterColon``)
+ Break inheritance list after the colon and commas.
+
+ .. code-block:: c++
+
+ class Foo :
+ Base1,
+ Base2
+ {};
@@ -1085,7 +1148,7 @@ the configuration (without a prefix: ``Auto``).
**ConstructorInitializerIndentWidth** (``unsigned``)
The number of characters to use for indentation of constructor
- initializer lists.
+ initializer lists as well as inheritance lists.
**ContinuationIndentWidth** (``unsigned``)
Indent width for line continuations.
@@ -1201,7 +1264,8 @@ the configuration (without a prefix: ``Auto``).
* ``IBS_Regroup`` (in configuration: ``Regroup``)
Merge multiple ``#include`` blocks together and sort as one.
- Then split into groups based on category priority. See ``IncludeCategories``.
+ Then split into groups based on category priority. See
+ ``IncludeCategories``.
.. code-block:: c++
@@ -1216,6 +1280,10 @@ the configuration (without a prefix: ``Auto``).
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
@@ -1238,6 +1306,8 @@ the configuration (without a prefix: ``Auto``).
Priority: 2
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
+ - Regex: '<[[:alnum:].]+>'
+ Priority: 4
- Regex: '.*'
Priority: 1
@@ -1507,6 +1577,52 @@ the configuration (without a prefix: ``Auto``).
+**ObjCBinPackProtocolList** (``BinPackStyle``)
+ 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-block:: 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> {
+ }
+
+ Possible values:
+
+ * ``BPS_Auto`` (in configuration: ``Auto``)
+ Automatically determine parameter bin-packing behavior.
+
+ * ``BPS_Always`` (in configuration: ``Always``)
+ Always bin-pack parameters.
+
+ * ``BPS_Never`` (in configuration: ``Never``)
+ Never bin-pack parameters.
+
+
+
**ObjCBlockIndentWidth** (``unsigned``)
The number of characters to use for indentation of ObjC blocks.
@@ -1541,6 +1657,9 @@ the configuration (without a prefix: ``Auto``).
**PenaltyBreakString** (``unsigned``)
The penalty for each line break introduced inside a string literal.
+**PenaltyBreakTemplateDeclaration** (``unsigned``)
+ The penalty for breaking after template declaration.
+
**PenaltyExcessCharacter** (``unsigned``)
The penalty for each character outside of the column limit.
@@ -1577,24 +1696,42 @@ the configuration (without a prefix: ``Auto``).
**RawStringFormats** (``std::vector<RawStringFormat>``)
- 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-block:: 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'
**ReflowComments** (``bool``)
If ``true``, clang-format will attempt to re-flow comments.
@@ -1643,7 +1780,7 @@ the configuration (without a prefix: ``Auto``).
.. code-block:: c++
true: false:
- (int)i; vs. (int) i;
+ (int) i; vs. (int)i;
**SpaceAfterTemplateKeyword** (``bool``)
If ``true``, a space will be inserted after the 'template' keyword.
@@ -1662,6 +1799,35 @@ the configuration (without a prefix: ``Auto``).
int a = 5; vs. int a=5;
a += 42 a+=42;
+**SpaceBeforeCpp11BracedList** (``bool``)
+ 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-block:: c++
+
+ 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 };
+
+**SpaceBeforeCtorInitializerColon** (``bool``)
+ If ``false``, spaces will be removed before constructor initializer
+ colon.
+
+ .. code-block:: c++
+
+ true: false:
+ Foo::Foo() : a(a) {} Foo::Foo(): a(a) {}
+
+**SpaceBeforeInheritanceColon** (``bool``)
+ If ``false``, spaces will be removed before inheritance colon.
+
+ .. code-block:: c++
+
+ true: false:
+ class Foo : Bar {} vs. class Foo: Bar {}
+
**SpaceBeforeParens** (``SpaceBeforeParensOptions``)
Defines in which cases to put a space before opening parentheses.
@@ -1706,6 +1872,15 @@ the configuration (without a prefix: ``Auto``).
+**SpaceBeforeRangeBasedForLoopColon** (``bool``)
+ If ``false``, spaces will be removed before range-based for loop
+ colon.
+
+ .. code-block:: c++
+
+ true: false:
+ for (auto v : values) {} vs. for(auto v: values) {}
+
**SpaceInEmptyParentheses** (``bool``)
If ``true``, spaces may be inserted into ``()``.
diff --git a/docs/CommandGuide/clang.rst b/docs/CommandGuide/clang.rst
index 16bb09f3c740..d440d915d686 100644
--- a/docs/CommandGuide/clang.rst
+++ b/docs/CommandGuide/clang.rst
@@ -98,10 +98,129 @@ Language Selection and Mode Options
Treat subsequent input files as having type language.
-.. option:: -std=<language>
+.. option:: -std=<standard>
Specify the language standard to compile for.
+ Supported values for the C language are:
+
+ | ``c89``
+ | ``c90``
+ | ``iso9899:1990``
+
+ ISO C 1990
+
+ | ``iso9899:199409``
+
+ ISO C 1990 with amendment 1
+
+ | ``gnu89``
+ | ``gnu90``
+
+ ISO C 1990 with GNU extensions
+
+ | ``c99``
+ | ``iso9899:1999``
+
+ ISO C 1999
+
+ | ``gnu99``
+
+ ISO C 1999 with GNU extensions
+
+ | ``c11``
+ | ``iso9899:2011``
+
+ ISO C 2011
+
+ | ``gnu11``
+
+ ISO C 2011 with GNU extensions
+
+ | ``c17``
+ | ``iso9899:2017``
+
+ ISO C 2017
+
+ | ``gnu17``
+
+ ISO C 2017 with GNU extensions
+
+ The default C language standard is ``gnu11``, except on PS4, where it is
+ ``gnu99``.
+
+ Supported values for the C++ language are:
+
+ | ``c++98``
+ | ``c++03``
+
+ ISO C++ 1998 with amendments
+
+ | ``gnu++98``
+ | ``gnu++03``
+
+ ISO C++ 1998 with amendments and GNU extensions
+
+ | ``c++11``
+
+ ISO C++ 2011 with amendments
+
+ | ``gnu++11``
+
+ ISO C++ 2011 with amendments and GNU extensions
+
+ | ``c++14``
+
+ ISO C++ 2014 with amendments
+
+ | ``gnu++14``
+
+ ISO C++ 2014 with amendments and GNU extensions
+
+ | ``c++17``
+
+ ISO C++ 2017 with amendments
+
+ | ``gnu++17``
+
+ ISO C++ 2017 with amendments and GNU extensions
+
+ | ``c++2a``
+
+ Working draft for ISO C++ 2020
+
+ | ``gnu++2a``
+
+ Working draft for ISO C++ 2020 with GNU extensions
+
+ The default C++ language standard is ``gnu++14``.
+
+ Supported values for the OpenCL language are:
+
+ | ``cl1.0``
+
+ OpenCL 1.0
+
+ | ``cl1.1``
+
+ OpenCL 1.1
+
+ | ``cl1.2``
+
+ OpenCL 1.2
+
+ | ``cl2.0``
+
+ OpenCL 2.0
+
+ The default OpenCL language standard is ``cl1.0``.
+
+ Supported values for the CUDA language are:
+
+ | ``cuda``
+
+ NVIDIA CUDA(tm)
+
.. option:: -stdlib=<library>
Specify the C++ standard library to use; supported options are libstdc++ and
diff --git a/docs/CommandGuide/diagtool.rst b/docs/CommandGuide/diagtool.rst
new file mode 100644
index 000000000000..59417f71f69d
--- /dev/null
+++ b/docs/CommandGuide/diagtool.rst
@@ -0,0 +1,52 @@
+diagtool - clang diagnostics tool
+=================================
+
+SYNOPSIS
+--------
+
+:program:`diagtool` *command* [*args*]
+
+DESCRIPTION
+-----------
+
+:program:`diagtool` is a combination of four tool for dealing with diagnostics in :program:`clang`.
+
+SUBCOMMANDS
+-----------
+
+:program:`diagtool` is separated into several subcommands each tailored to a
+different purpose. A brief summary of each command follows, with more detail in
+the sections that follow.
+
+ * :ref:`find_diagnostic_id` - Print the id of the given diagnostic.
+ * :ref:`list_warnings` - List warnings and their corresponding flags.
+ * :ref:`show_enabled` - Show which warnings are enabled for a given command line.
+ * :ref:`tree` - Show warning flags in a tree view.
+
+.. _find_diagnostic_id:
+
+find-diagnostic-id
+~~~~~~~~~~~~~~~~~~
+
+:program:`diagtool` find-diagnostic-id *diagnostic-name*
+
+.. _list_warnings:
+
+list-warnings
+~~~~~~~~~~~~~
+
+:program:`diagtool` list-warnings
+
+.. _show_enabled:
+
+show-enabled
+~~~~~~~~~~~~
+
+:program:`diagtool` show-enabled [*options*] *filename ...*
+
+.. _tree:
+
+tree
+~~~~
+
+:program:`diagtool` tree [*diagnostic-group*]
diff --git a/docs/CommandGuide/index.rst b/docs/CommandGuide/index.rst
index 826ed9711980..83a91182e9ca 100644
--- a/docs/CommandGuide/index.rst
+++ b/docs/CommandGuide/index.rst
@@ -15,3 +15,4 @@ Basic Commands
:maxdepth: 1
clang
+ diagtool
diff --git a/docs/ControlFlowIntegrity.rst b/docs/ControlFlowIntegrity.rst
index 12b4610f8a28..fcc640988897 100644
--- a/docs/ControlFlowIntegrity.rst
+++ b/docs/ControlFlowIntegrity.rst
@@ -66,6 +66,8 @@ Available schemes are:
wrong dynamic type.
- ``-fsanitize=cfi-icall``: Indirect call of a function with wrong dynamic
type.
+ - ``-fsanitize=cfi-mfcall``: Indirect call via a member function pointer with
+ wrong dynamic type.
You can use ``-fsanitize=cfi`` to enable all the schemes and use
``-fno-sanitize`` flag to narrow down the set of schemes as desired.
@@ -106,8 +108,9 @@ This CFI scheme can be enabled on its own using ``-fsanitize=cfi-vcall``.
For this scheme to work, all translation units containing the definition
of a virtual member function (whether inline or not), other than members
-of :ref:`blacklisted <cfi-blacklist>` types, must be compiled with
-``-fsanitize=cfi-vcall`` enabled and be statically linked into the program.
+of :ref:`blacklisted <cfi-blacklist>` types or types with public :doc:`LTO
+visibility <LTOVisibility>`, must be compiled with ``-flto`` or ``-flto=thin``
+enabled and be statically linked into the program.
Performance
-----------
@@ -152,9 +155,9 @@ functions may be :ref:`blacklisted <cfi-blacklist>`.
For this scheme to work, all translation units containing the definition
of a virtual member function (whether inline or not), other than members
-of :ref:`blacklisted <cfi-blacklist>` types, must be compiled with
-``-fsanitize=cfi-derived-cast`` or ``-fsanitize=cfi-unrelated-cast`` enabled
-and be statically linked into the program.
+of :ref:`blacklisted <cfi-blacklist>` types or types with public :doc:`LTO
+visibility <LTOVisibility>`, must be compiled with ``-flto`` or ``-flto=thin``
+enabled and be statically linked into the program.
Non-Virtual Member Function Call Checking
=========================================
@@ -168,8 +171,9 @@ polymorphic class type. This CFI scheme can be enabled on its own using
For this scheme to work, all translation units containing the definition
of a virtual member function (whether inline or not), other than members
-of :ref:`blacklisted <cfi-blacklist>` types, must be compiled with
-``-fsanitize=cfi-nvcall`` enabled and be statically linked into the program.
+of :ref:`blacklisted <cfi-blacklist>` types or types with public :doc:`LTO
+visibility <LTOVisibility>`, must be compiled with ``-flto`` or ``-flto=thin``
+enabled and be statically linked into the program.
.. _cfi-strictness:
@@ -224,8 +228,8 @@ flag relax pointer type checking for call sites in that translation unit,
applied across all functions compiled with ``-fsanitize=cfi-icall``.
Specifically, pointers in return and argument types are treated as equivalent as
-long as the qualifiers for the type they point to match. For example, ``char*``
-``char**`, and ``int*`` are considered equivalent types. However, ``char*`` and
+long as the qualifiers for the type they point to match. For example, ``char*``,
+``char**``, and ``int*`` are considered equivalent types. However, ``char*`` and
``const char*`` are considered separate types.
``-fsanitize-cfi-icall-generalize-pointers`` is not compatible with
@@ -253,6 +257,34 @@ the identity of function pointers is maintained, and calls across shared
library boundaries are no different from calls within a single program or
shared library.
+Member Function Pointer Call Checking
+=====================================
+
+This scheme checks that indirect calls via a member function pointer
+take place using an object of the correct dynamic type. Specifically, we
+check that the dynamic type of the member function referenced by the member
+function pointer matches the "function pointer" part of the member function
+pointer, and that the member function's class type is related to the base
+type of the member function. This CFI scheme can be enabled on its own using
+``-fsanitize=cfi-mfcall``.
+
+The compiler will only emit a full CFI check if the member function pointer's
+base type is complete. This is because the complete definition of the base
+type contains information that is necessary to correctly compile the CFI
+check. To ensure that the compiler always emits a full CFI check, it is
+recommended to also pass the flag ``-fcomplete-member-pointers``, which
+enables a non-conforming language extension that requires member pointer
+base types to be complete if they may be used for a call.
+
+For this scheme to work, all translation units containing the definition
+of a virtual member function (whether inline or not), other than members
+of :ref:`blacklisted <cfi-blacklist>` types or types with public :doc:`LTO
+visibility <LTOVisibility>`, must be compiled with ``-flto`` or ``-flto=thin``
+enabled and be statically linked into the program.
+
+This scheme is currently not compatible with cross-DSO CFI or the
+Microsoft ABI.
+
.. _cfi-blacklist:
Blacklist
diff --git a/docs/DiagnosticsReference.rst b/docs/DiagnosticsReference.rst
index e2b0bd7dd550..734a45902484 100644
--- a/docs/DiagnosticsReference.rst
+++ b/docs/DiagnosticsReference.rst
@@ -7555,9 +7555,9 @@ This diagnostic is enabled by default.
**Diagnostic text:**
-+------------------------------------------------------------------------------------------------------------+
-|:warning:`warning:` |nbsp| :diagtext:`default property attribute 'assign' not appropriate for non-GC object`|
-+------------------------------------------------------------------------------------------------------------+
++-----------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`default property attribute 'assign' not appropriate for object`|
++-----------------------------------------------------------------------------------------------------+
+--------------------------------------------------------------------------------------------------------------------+
|:warning:`warning:` |nbsp| :diagtext:`no 'assign', 'retain', or 'copy' attribute is specified - 'assign' is assumed`|
diff --git a/docs/HardwareAssistedAddressSanitizerDesign.rst b/docs/HardwareAssistedAddressSanitizerDesign.rst
index 5904cceaead2..2578914376ae 100644
--- a/docs/HardwareAssistedAddressSanitizerDesign.rst
+++ b/docs/HardwareAssistedAddressSanitizerDesign.rst
@@ -7,8 +7,6 @@ This page is a design document for
a tool similar to :doc:`AddressSanitizer`,
but based on partial hardware assistance.
-The document is a draft, suggestions are welcome.
-
Introduction
============
@@ -30,15 +28,16 @@ accuracy guarantees.
Algorithm
=========
-* Every heap/stack/global memory object is forcibly aligned by `N` bytes
- (`N` is e.g. 16 or 64). We call `N` the **granularity** of tagging.
-* For every such object a random `K`-bit tag `T` is chosen (`K` is e.g. 4 or 8)
+* Every heap/stack/global memory object is forcibly aligned by `TG` bytes
+ (`TG` is e.g. 16 or 64). We call `TG` the **tagging granularity**.
+* For every such object a random `TS`-bit tag `T` is chosen (`TS`, or tag size, is e.g. 4 or 8)
* The pointer to the object is tagged with `T`.
-* The memory for the object is also tagged with `T`
- (using a `N=>1` shadow memory)
+* The memory for the object is also tagged with `T` (using a `TG=>1` shadow memory)
* Every load and store is instrumented to read the memory tag and compare it
with the pointer tag, exception is raised on tag mismatch.
+For a more detailed discussion of this approach see https://arxiv.org/pdf/1802.09517.pdf
+
Instrumentation
===============
@@ -53,17 +52,16 @@ verifies the tags. Currently, the following sequence is used:
// int foo(int *a) { return *a; }
// clang -O2 --target=aarch64-linux -fsanitize=hwaddress -c load.c
foo:
- 0: 08 dc 44 d3 ubfx x8, x0, #4, #52 // shadow address
- 4: 08 01 40 39 ldrb w8, [x8] // load shadow
- 8: 09 fc 78 d3 lsr x9, x0, #56 // address tag
- c: 3f 01 08 6b cmp w9, w8 // compare tags
- 10: 61 00 00 54 b.ne #12 // jump on mismatch
- 14: 00 00 40 b9 ldr w0, [x0] // original load
- 18: c0 03 5f d6 ret
- 1c: 40 20 40 d4 hlt #0x102 // halt
- 20: 00 00 40 b9 ldr w0, [x0] // original load
- 24: c0 03 5f d6 ret
-
+ 0: 08 00 00 90 adrp x8, 0 <__hwasan_shadow>
+ 4: 08 01 40 f9 ldr x8, [x8] // shadow base (to be resolved by the loader)
+ 8: 09 dc 44 d3 ubfx x9, x0, #4, #52 // shadow offset
+ c: 28 69 68 38 ldrb w8, [x9, x8] // load shadow tag
+ 10: 09 fc 78 d3 lsr x9, x0, #56 // extract address tag
+ 14: 3f 01 08 6b cmp w9, w8 // compare tags
+ 18: 61 00 00 54 b.ne 24 // jump on mismatch
+ 1c: 00 00 40 b9 ldr w0, [x0] // original load
+ 20: c0 03 5f d6 ret
+ 24: 40 20 21 d4 brk #0x902 // trap
Alternatively, memory accesses are prefixed with a function call.
@@ -71,17 +69,24 @@ Heap
----
Tagging the heap memory/pointers is done by `malloc`.
-This can be based on any malloc that forces all objects to be N-aligned.
+This can be based on any malloc that forces all objects to be TG-aligned.
`free` tags the memory with a different tag.
Stack
-----
-Special compiler instrumentation is required to align the local variables
-by N, tag the memory and the pointers.
+Stack frames are instrumented by aligning all non-promotable allocas
+by `TG` and tagging stack memory in function prologue and epilogue.
+
+Tags for different allocas in one function are **not** generated
+independently; doing that in a function with `M` allocas would require
+maintaining `M` live stack pointers, significantly increasing register
+pressure. Instead we generate a single base tag value in the prologue,
+and build the tag for alloca number `M` as `ReTag(BaseTag, M)`, where
+ReTag can be as simple as exclusive-or with constant `M`.
+
Stack instrumentation is expected to be a major source of overhead,
but could be optional.
-TODO: details.
Globals
-------
@@ -126,15 +131,25 @@ HWASAN:
https://www.kernel.org/doc/Documentation/arm64/tagged-pointers.txt).
* **Does not require redzones to detect buffer overflows**,
but the buffer overflow detection is probabilistic, with roughly
- `(2**K-1)/(2**K)` probability of catching a bug.
+ `(2**TS-1)/(2**TS)` probability of catching a bug.
* **Does not require quarantine to detect heap-use-after-free,
or stack-use-after-return**.
The detection is similarly probabilistic.
The memory overhead of HWASAN is expected to be much smaller
than that of AddressSanitizer:
-`1/N` extra memory for the shadow
-and some overhead due to `N`-aligning all objects.
+`1/TG` extra memory for the shadow
+and some overhead due to `TG`-aligning all objects.
+
+Supported architectures
+=======================
+HWASAN relies on `Address Tagging`_ which is only available on AArch64.
+For other 64-bit architectures it is possible to remove the address tags
+before every load and store by compiler instrumentation, but this variant
+will have limited deployability since not all of the code is
+typically instrumented.
+
+The HWASAN's approach is not applicable to 32-bit architectures.
Related Work
diff --git a/docs/HowToSetupToolingForLLVM.rst b/docs/HowToSetupToolingForLLVM.rst
index 3812fc9f46e7..686aca840ada 100644
--- a/docs/HowToSetupToolingForLLVM.rst
+++ b/docs/HowToSetupToolingForLLVM.rst
@@ -133,7 +133,8 @@ Examples:
if (this->ASTList.operator _Bool())
return clang::CreateASTDeclNodeLister();
if (this->ASTDump.operator _Bool())
- return clang::CreateASTDumper(this->ASTDumpFilter);
+ return clang::CreateASTDumper(nullptr /*Dump to stdout.*/,
+ this->ASTDumpFilter);
if (this->ASTPrint.operator _Bool())
return clang::CreateASTPrinter(&llvm::outs(), this->ASTDumpFilter);
return new clang::ASTConsumer();
diff --git a/docs/InternalsManual.rst b/docs/InternalsManual.rst
index 058c63f0afd6..af15b2e51e1c 100644
--- a/docs/InternalsManual.rst
+++ b/docs/InternalsManual.rst
@@ -54,7 +54,7 @@ number of source ranges that related to the diagnostic.
In this section, we'll be giving examples produced by the Clang command line
driver, but diagnostics can be :ref:`rendered in many different ways
-<DiagnosticClient>` depending on how the ``DiagnosticClient`` interface is
+<DiagnosticConsumer>` depending on how the ``DiagnosticConsumer`` interface is
implemented. A representative example of a diagnostic is:
.. code-block:: text
@@ -188,7 +188,7 @@ Formatting a Diagnostic Argument
Arguments to diagnostics are fully typed internally, and come from a couple
different classes: integers, types, names, and random strings. Depending on
the class of the argument, it can be optionally formatted in different ways.
-This gives the ``DiagnosticClient`` information about what the argument means
+This gives the ``DiagnosticConsumer`` information about what the argument means
without requiring it to use a specific presentation (consider this MVC for
Clang :).
@@ -319,6 +319,32 @@ they should be discussed before they are added. If you are creating a lot of
repetitive diagnostics and/or have an idea for a useful formatter, please bring
it up on the cfe-dev mailing list.
+**"sub" format**
+
+Example:
+ Given the following record definition of type ``TextSubstitution``:
+
+ .. code-block:: text
+
+ def select_ovl_candidate : TextSubstitution<
+ "%select{function|constructor}0%select{| template| %2}1">;
+
+ which can be used as
+
+ .. code-block:: text
+
+ def note_ovl_candidate : Note<
+ "candidate %sub{select_ovl_candidate}3,2,1 not viable">;
+
+ and will act as if it was written
+ ``"candidate %select{function|constructor}3%select{| template| %1}2 not viable"``.
+Description:
+ This format specifier is used to avoid repeating strings verbatim in multiple
+ diagnostics. The argument to ``%sub`` must name a ``TextSubstitution`` tblgen
+ record. The substitution must specify all arguments used by the substitution,
+ and the modifier indexes in the substitution are re-numbered accordingly. The
+ substituted text must itself be a valid format string before substitution.
+
.. _internals-producing-diag:
Producing the Diagnostic
@@ -387,7 +413,7 @@ exactly where those parentheses would be inserted into the source code. The
fix-it hints themselves describe what changes to make to the source code in an
abstract manner, which the text diagnostic printer renders as a line of
"insertions" below the caret line. :ref:`Other diagnostic clients
-<DiagnosticClient>` might choose to render the code differently (e.g., as
+<DiagnosticConsumer>` might choose to render the code differently (e.g., as
markup inline) or even give the user the ability to automatically fix the
problem.
@@ -420,26 +446,26 @@ Fix-it hints can be created with one of three constructors:
Specifies that the code in the given source ``Range`` should be removed,
and replaced with the given ``Code`` string.
-.. _DiagnosticClient:
+.. _DiagnosticConsumer:
-The ``DiagnosticClient`` Interface
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+The ``DiagnosticConsumer`` Interface
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Once code generates a diagnostic with all of the arguments and the rest of the
relevant information, Clang needs to know what to do with it. As previously
mentioned, the diagnostic machinery goes through some filtering to map a
severity onto a diagnostic level, then (assuming the diagnostic is not mapped
-to "``Ignore``") it invokes an object that implements the ``DiagnosticClient``
+to "``Ignore``") it invokes an object that implements the ``DiagnosticConsumer``
interface with the information.
It is possible to implement this interface in many different ways. For
-example, the normal Clang ``DiagnosticClient`` (named
+example, the normal Clang ``DiagnosticConsumer`` (named
``TextDiagnosticPrinter``) turns the arguments into strings (according to the
various formatting rules), prints out the file/line/column information and the
string, then prints out the line of code, the source ranges, and the caret.
However, this behavior isn't required.
-Another implementation of the ``DiagnosticClient`` interface is the
+Another implementation of the ``DiagnosticConsumer`` interface is the
``TextDiagnosticBuffer`` class, which is used when Clang is in ``-verify``
mode. Instead of formatting and printing out the diagnostics, this
implementation just captures and remembers the diagnostics as they fly by.
@@ -1638,15 +1664,15 @@ and then the semantic handling of the attribute.
Parsing of the attribute is determined by the various syntactic forms attributes
can take, such as GNU, C++11, and Microsoft style attributes, as well as other
information provided by the table definition of the attribute. Ultimately, the
-parsed representation of an attribute object is an ``AttributeList`` object.
+parsed representation of an attribute object is an ``ParsedAttr`` object.
These parsed attributes chain together as a list of parsed attributes attached
to a declarator or declaration specifier. The parsing of attributes is handled
automatically by Clang, except for attributes spelled as keywords. When
implementing a keyword attribute, the parsing of the keyword and creation of the
-``AttributeList`` object must be done manually.
+``ParsedAttr`` object must be done manually.
Eventually, ``Sema::ProcessDeclAttributeList()`` is called with a ``Decl`` and
-an ``AttributeList``, at which point the parsed attribute can be transformed
+an ``ParsedAttr``, at which point the parsed attribute can be transformed
into a semantic attribute. The process by which a parsed attribute is converted
into a semantic attribute depends on the attribute definition and semantic
requirements of the attribute. The end result, however, is that the semantic
@@ -1725,8 +1751,8 @@ subjects in the list, but a custom diagnostic parameter can also be specified in
the ``SubjectList``. The diagnostics generated for subject list violations are
either ``diag::warn_attribute_wrong_decl_type`` or
``diag::err_attribute_wrong_decl_type``, and the parameter enumeration is found
-in `include/clang/Sema/AttributeList.h
-<http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/AttributeList.h?view=markup>`_
+in `include/clang/Sema/ParsedAttr.h
+<http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/ParsedAttr.h?view=markup>`_
If a previously unused Decl node is added to the ``SubjectList``, the logic used
to automatically determine the diagnostic parameter in `utils/TableGen/ClangAttrEmitter.cpp
<http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?view=markup>`_
@@ -1823,7 +1849,7 @@ Note that setting this member to 1 will opt out of common attribute semantic
handling, requiring extra implementation efforts to ensure the attribute
appertains to the appropriate subject, etc.
-If the attribute should not be propagated from from a template declaration to an
+If the attribute should not be propagated from a template declaration to an
instantiation of the template, set the ``Clone`` member to 0. By default, all
attributes will be cloned to template instantiations.
@@ -1861,15 +1887,10 @@ requirements. To support this feature, an attribute inheriting from
should be the same value between all arguments sharing a spelling, and
corresponds to the parsed attribute's ``Kind`` enumerator. This allows
attributes to share a parsed attribute kind, but have distinct semantic
-attribute classes. For instance, ``AttributeList::AT_Interrupt`` is the shared
+attribute classes. For instance, ``ParsedAttr`` is the shared
parsed attribute kind, but ARMInterruptAttr and MSP430InterruptAttr are the
semantic attributes generated.
-By default, when declarations are merging attributes, an attribute will not be
-duplicated. However, if an attribute can be duplicated during this merging
-stage, set ``DuplicatesAllowedWhileMerging`` to ``1``, and the attribute will
-be merged.
-
By default, attribute arguments are parsed in an evaluated context. If the
arguments for an attribute should be parsed in an unevaluated context (akin to
the way the argument to a ``sizeof`` expression is parsed), set
diff --git a/docs/LTOVisibility.rst b/docs/LTOVisibility.rst
index e1372d667a1a..ed15d8d78678 100644
--- a/docs/LTOVisibility.rst
+++ b/docs/LTOVisibility.rst
@@ -11,9 +11,9 @@ linkage unit's LTO unit is empty. Each linkage unit has only a single LTO unit.
The LTO visibility of a class is used by the compiler to determine which
classes the whole-program devirtualization (``-fwhole-program-vtables``) and
-control flow integrity (``-fsanitize=cfi-vcall``) features apply to. These
-features use whole-program information, so they require the entire class
-hierarchy to be visible in order to work correctly.
+control flow integrity (``-fsanitize=cfi-vcall`` and ``-fsanitize=cfi-mfcall``)
+features apply to. These features use whole-program information, so they
+require the entire class hierarchy to be visible in order to work correctly.
If any translation unit in the program uses either of the whole-program
devirtualization or control flow integrity features, it is effectively an ODR
diff --git a/docs/LanguageExtensions.rst b/docs/LanguageExtensions.rst
index 9b407f31d973..1aef265a8589 100644
--- a/docs/LanguageExtensions.rst
+++ b/docs/LanguageExtensions.rst
@@ -1096,6 +1096,11 @@ The following type trait primitives are supported by Clang:
* ``__is_constructible`` (MSVC 2013, clang)
* ``__is_nothrow_constructible`` (MSVC 2013, clang)
* ``__is_assignable`` (MSVC 2015, clang)
+* ``__reference_binds_to_temporary(T, U)`` (Clang): Determines whether a
+ reference of type ``T`` bound to an expression of type ``U`` would bind to a
+ materialized temporary object. If ``T`` is not a reference type the result
+ is false. Note this trait will also return false when the initialization of
+ ``T`` from ``U`` is ill-formed.
Blocks
======
@@ -1186,12 +1191,59 @@ Automatic reference counting
Clang provides support for :doc:`automated reference counting
<AutomaticReferenceCounting>` in Objective-C, which eliminates the need
-for manual ``retain``/``release``/``autorelease`` message sends. There are two
+for manual ``retain``/``release``/``autorelease`` message sends. There are three
feature macros associated with automatic reference counting:
``__has_feature(objc_arc)`` indicates the availability of automated reference
counting in general, while ``__has_feature(objc_arc_weak)`` indicates that
automated reference counting also includes support for ``__weak`` pointers to
-Objective-C objects.
+Objective-C objects. ``__has_feature(objc_arc_fields)`` indicates that C structs
+are allowed to have fields that are pointers to Objective-C objects managed by
+automatic reference counting.
+
+.. _objc-weak:
+
+Weak references
+---------------
+
+Clang supports ARC-style weak and unsafe references in Objective-C even
+outside of ARC mode. Weak references must be explicitly enabled with
+the ``-fobjc-weak`` option; use ``__has_feature((objc_arc_weak))``
+to test whether they are enabled. Unsafe references are enabled
+unconditionally. ARC-style weak and unsafe references cannot be used
+when Objective-C garbage collection is enabled.
+
+Except as noted below, the language rules for the ``__weak`` and
+``__unsafe_unretained`` qualifiers (and the ``weak`` and
+``unsafe_unretained`` property attributes) are just as laid out
+in the :doc:`ARC specification <AutomaticReferenceCounting>`.
+In particular, note that some classes do not support forming weak
+references to their instances, and note that special care must be
+taken when storing weak references in memory where initialization
+and deinitialization are outside the responsibility of the compiler
+(such as in ``malloc``-ed memory).
+
+Loading from a ``__weak`` variable always implicitly retains the
+loaded value. In non-ARC modes, this retain is normally balanced
+by an implicit autorelease. This autorelease can be suppressed
+by performing the load in the receiver position of a ``-retain``
+message send (e.g. ``[weakReference retain]``); note that this performs
+only a single retain (the retain done when primitively loading from
+the weak reference).
+
+For the most part, ``__unsafe_unretained`` in non-ARC modes is just the
+default behavior of variables and therefore is not needed. However,
+it does have an effect on the semantics of block captures: normally,
+copying a block which captures an Objective-C object or block pointer
+causes the captured pointer to be retained or copied, respectively,
+but that behavior is suppressed when the captured variable is qualified
+with ``__unsafe_unretained``.
+
+Note that the ``__weak`` qualifier formerly meant the GC qualifier in
+all non-ARC modes and was silently ignored outside of GC modes. It now
+means the ARC-style qualifier in all non-GC modes and is no longer
+allowed if not enabled by either ``-fobjc-arc`` or ``-fobjc-weak``.
+It is expected that ``-fobjc-weak`` will eventually be enabled by default
+in all non-GC Objective-C modes.
.. _objc-fixed-enum:
@@ -1968,6 +2020,32 @@ is disallowed in general).
Support for constant expression evaluation for the above builtins be detected
with ``__has_feature(cxx_constexpr_string_builtins)``.
+Atomic Min/Max builtins with memory ordering
+--------------------------------------------
+
+There are two atomic builtins with min/max in-memory comparison and swap.
+The syntax and semantics are similar to GCC-compatible __atomic_* builtins.
+
+* ``__atomic_fetch_min``
+* ``__atomic_fetch_max``
+
+The builtins work with signed and unsigned integers and require to specify memory ordering.
+The return value is the original value that was stored in memory before comparison.
+
+Example:
+
+.. code-block:: c
+
+ unsigned int val = __atomic_fetch_min(unsigned int *pi, unsigned int ui, __ATOMIC_RELAXED);
+
+The third argument is one of the memory ordering specifiers ``__ATOMIC_RELAXED``,
+``__ATOMIC_CONSUME``, ``__ATOMIC_ACQUIRE``, ``__ATOMIC_RELEASE``,
+``__ATOMIC_ACQ_REL``, or ``__ATOMIC_SEQ_CST`` following C++11 memory model semantics.
+
+In terms or aquire-release ordering barriers these two operations are always
+considered as operations with *load-store* semantics, even when the original value
+is not actually modified after comparison.
+
.. _langext-__c11_atomic:
__c11_atomic builtins
@@ -2720,3 +2798,10 @@ The ``#pragma clang section`` directive obeys the following rules:
* The decision about which section-kind applies to each global is taken in the back-end.
Once the section-kind is known, appropriate section name, as specified by the user using
``#pragma clang section`` directive, is applied to that global.
+
+Specifying Linker Options on ELF Targets
+========================================
+
+The ``#pragma comment(lib, ...)`` directive is supported on all ELF targets.
+The second parameter is the library name (without the traditional Unix prefix of
+``lib``). This allows you to provide an implicit link of dependent libraries.
diff --git a/docs/LibASTMatchersReference.html b/docs/LibASTMatchersReference.html
index ed1ec193d8df..cf32a5ce4a0f 100644
--- a/docs/LibASTMatchersReference.html
+++ b/docs/LibASTMatchersReference.html
@@ -124,6 +124,18 @@ accessSpecDecl()
</pre></td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('blockDecl0')"><a name="blockDecl0Anchor">blockDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1BlockDecl.html">BlockDecl</a>&gt;...</td></tr>
+<tr><td colspan="4" class="doc" id="blockDecl0"><pre>Matches block declarations.
+
+Example matches the declaration of the nameless block printing an input
+integer.
+
+ myFunc(^(int p) {
+ printf("%d", p);
+ })
+</pre></td></tr>
+
+
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('classTemplateDecl0')"><a name="classTemplateDecl0Anchor">classTemplateDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ClassTemplateDecl.html">ClassTemplateDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="classTemplateDecl0"><pre>Matches C++ class template declarations.
@@ -650,6 +662,18 @@ Example matches __atomic_load_n(ptr, 1)
</pre></td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('autoreleasePoolStmt0')"><a name="autoreleasePoolStmt0Anchor">autoreleasePoolStmt</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCAutoreleasePoolStmt.html">ObjCAutoreleasePoolStmt</a>&gt;...</td></tr>
+<tr><td colspan="4" class="doc" id="autoreleasePoolStmt0"><pre>Matches an Objective-C autorelease pool statement.
+
+Given
+ @autoreleasepool {
+ int x = 0;
+ }
+autoreleasePoolStmt(stmt()) matches the declaration of "x"
+inside the autorelease pool.
+</pre></td></tr>
+
+
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('binaryConditionalOperator0')"><a name="binaryConditionalOperator0Anchor">binaryConditionalOperator</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1BinaryConditionalOperator.html">BinaryConditionalOperator</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="binaryConditionalOperator0"><pre>Matches binary conditional operator expressions (GNU extension).
@@ -700,7 +724,7 @@ Example matches x.y() and y()
Given
switch(a) { case 42: break; default: break; }
caseStmt()
- matches 'case 42: break;'.
+ matches 'case 42:'.
</pre></td></tr>
@@ -741,7 +765,7 @@ Example match: {1}, (1, 2)
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('compoundStmt0')"><a name="compoundStmt0Anchor">compoundStmt</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CompoundStmt.html">CompoundStmt</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="compoundStmt0"><pre>Matches compound statements.
-Example matches '{}' and '{{}}'in 'for (;;) {{}}'
+Example matches '{}' and '{{}}' in 'for (;;) {{}}'
for (;;) {{}}
</pre></td></tr>
@@ -1028,7 +1052,7 @@ declStmt()
Given
switch(a) { case 42: break; default: break; }
defaultStmt()
- matches 'default: break;'.
+ matches 'default:'.
</pre></td></tr>
@@ -1197,9 +1221,9 @@ Example: Given
materializeTemporaryExpr() matches 'f()' in these statements
T u(f());
g(f());
+ f().func();
but does not match
f();
- f().func();
</pre></td></tr>
@@ -1243,6 +1267,20 @@ Example matches @finally
</pre></td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('objcIvarRefExpr0')"><a name="objcIvarRefExpr0Anchor">objcIvarRefExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCIvarRefExpr.html">ObjCIvarRefExpr</a>&gt;...</td></tr>
+<tr><td colspan="4" class="doc" id="objcIvarRefExpr0"><pre>Matches a reference to an ObjCIvar.
+
+Example: matches "a" in "init" method:
+@implementation A {
+ NSString *a;
+}
+- (void) init {
+ a = @"hello";
+}
+}
+</pre></td></tr>
+
+
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('objcMessageExpr0')"><a name="objcMessageExpr0Anchor">objcMessageExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="objcMessageExpr0"><pre>Matches ObjectiveC Message invocation expressions.
@@ -1255,10 +1293,9 @@ NSString's "alloc". This matcher should match both message sends.
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('objcThrowStmt0')"><a name="objcThrowStmt0Anchor">objcThrowStmt</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCAtThrowStmt.html">ObjCAtThrowStmt</a>&gt;...</td></tr>
-<tr><td colspan="4" class="doc" id="objcThrowStmt0"><pre>Matches Objective-C @throw statements.
+<tr><td colspan="4" class="doc" id="objcThrowStmt0"><pre>Matches Objective-C statements.
-Example matches @throw
- @throw obj;
+Example matches @throw obj;
</pre></td></tr>
@@ -1370,7 +1407,7 @@ substNonTypeTemplateParmExpr()
Given
switch(a) { case 42: break; default: break; }
switchCase()
- matches 'case 42: break;' and 'default: break;'.
+ matches 'case 42:' and 'default:'.
</pre></td></tr>
@@ -1554,6 +1591,18 @@ Example matches i[1].
</pre></td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('decltypeType0')"><a name="decltypeType0Anchor">decltypeType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DecltypeType.html">DecltypeType</a>&gt;...</td></tr>
+<tr><td colspan="4" class="doc" id="decltypeType0"><pre>Matches types nodes representing C++11 decltype(&lt;expr&gt;) types.
+
+Given:
+ short i = 1;
+ int j = 42;
+ decltype(i + j) result = i + j;
+decltypeType()
+ matches "decltype(i + j)"
+</pre></td></tr>
+
+
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('dependentSizedArrayType0')"><a name="dependentSizedArrayType0Anchor">dependentSizedArrayType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DependentSizedArrayType.html">DependentSizedArrayType</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="dependentSizedArrayType0"><pre>Matches C++ arrays whose size is a value-dependent expression.
@@ -1927,7 +1976,25 @@ Example matches a || b (matcher = binaryOperator(hasOperatorName("||")))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>&gt;</td><td class="name" onclick="toggle('equals2')"><a name="equals2Anchor">equals</a></td><td>ValueT Value</td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>&gt;</td><td class="name" onclick="toggle('isAssignmentOperator0')"><a name="isAssignmentOperator0Anchor">isAssignmentOperator</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="isAssignmentOperator0"><pre>Matches all kinds of assignment operators.
+
+Example 1: matches a += b (matcher = binaryOperator(isAssignmentOperator()))
+ if (a == b)
+ a += b;
+
+Example 2: matches s1 = s2
+ (matcher = cxxOperatorCallExpr(isAssignmentOperator()))
+ struct S { S&amp; operator=(const S&amp;); };
+ void x() { S s1, s2; s1 = s2; })
+</pre></td></tr>
+
+
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>&gt;</td><td class="name" onclick="toggle('equals5')"><a name="equals5Anchor">equals</a></td><td>bool Value</td></tr>
+<tr><td colspan="4" class="doc" id="equals5"><pre></pre></td></tr>
+
+
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>&gt;</td><td class="name" onclick="toggle('equals2')"><a name="equals2Anchor">equals</a></td><td>const ValueT Value</td></tr>
<tr><td colspan="4" class="doc" id="equals2"><pre>Matches literals that are equal to the given value of type ValueT.
Given
@@ -1953,10 +2020,6 @@ Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Chara
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>&gt;</td><td class="name" onclick="toggle('equals5')"><a name="equals5Anchor">equals</a></td><td>bool Value</td></tr>
-<tr><td colspan="4" class="doc" id="equals5"><pre></pre></td></tr>
-
-
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>&gt;</td><td class="name" onclick="toggle('equals11')"><a name="equals11Anchor">equals</a></td><td>double Value</td></tr>
<tr><td colspan="4" class="doc" id="equals11"><pre></pre></td></tr>
@@ -2307,6 +2370,20 @@ Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXOp
</pre></td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>&gt;</td><td class="name" onclick="toggle('isAssignmentOperator1')"><a name="isAssignmentOperator1Anchor">isAssignmentOperator</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="isAssignmentOperator1"><pre>Matches all kinds of assignment operators.
+
+Example 1: matches a += b (matcher = binaryOperator(isAssignmentOperator()))
+ if (a == b)
+ a += b;
+
+Example 2: matches s1 = s2
+ (matcher = cxxOperatorCallExpr(isAssignmentOperator()))
+ struct S { S&amp; operator=(const S&amp;); };
+ void x() { S s1, s2; s1 = s2; })
+</pre></td></tr>
+
+
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;</td><td class="name" onclick="toggle('hasDefinition0')"><a name="hasDefinition0Anchor">hasDefinition</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="hasDefinition0"><pre>Matches a class declaration that is defined.
@@ -2377,6 +2454,8 @@ Given
template &lt;typename T&gt; class X {}; class A {}; X&lt;A&gt; x;
or
template &lt;typename T&gt; class X {}; class A {}; template class X&lt;A&gt;;
+or
+ template &lt;typename T&gt; class X {}; class A {}; extern template class X&lt;A&gt;;
cxxRecordDecl(hasName("::X"), isTemplateInstantiation())
matches the template instantiation of X&lt;A&gt;.
@@ -2409,7 +2488,11 @@ Example: matches the implicit cast around 0
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;</td><td class="name" onclick="toggle('equals3')"><a name="equals3Anchor">equals</a></td><td>ValueT Value</td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;</td><td class="name" onclick="toggle('equals4')"><a name="equals4Anchor">equals</a></td><td>bool Value</td></tr>
+<tr><td colspan="4" class="doc" id="equals4"><pre></pre></td></tr>
+
+
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;</td><td class="name" onclick="toggle('equals3')"><a name="equals3Anchor">equals</a></td><td>const ValueT Value</td></tr>
<tr><td colspan="4" class="doc" id="equals3"><pre>Matches literals that are equal to the given value of type ValueT.
Given
@@ -2435,10 +2518,6 @@ Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Chara
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;</td><td class="name" onclick="toggle('equals4')"><a name="equals4Anchor">equals</a></td><td>bool Value</td></tr>
-<tr><td colspan="4" class="doc" id="equals4"><pre></pre></td></tr>
-
-
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;</td><td class="name" onclick="toggle('equals10')"><a name="equals10Anchor">equals</a></td><td>double Value</td></tr>
<tr><td colspan="4" class="doc" id="equals10"><pre></pre></td></tr>
@@ -2645,6 +2724,15 @@ designatorCountIs(2)
</pre></td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumDecl.html">EnumDecl</a>&gt;</td><td class="name" onclick="toggle('isScoped0')"><a name="isScoped0Anchor">isScoped</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="isScoped0"><pre>Matches C++11 scoped enum declaration.
+
+Example matches Y (matcher = enumDecl(isScoped()))
+enum X {};
+enum class Y {};
+</pre></td></tr>
+
+
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FieldDecl.html">FieldDecl</a>&gt;</td><td class="name" onclick="toggle('hasBitWidth0')"><a name="hasBitWidth0Anchor">hasBitWidth</a></td><td>unsigned Width</td></tr>
<tr><td colspan="4" class="doc" id="hasBitWidth0"><pre>Matches non-static data members that are bit-fields of the specified
bit width.
@@ -2673,7 +2761,7 @@ fieldDecl(isBitField())
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FloatingLiteral.html">FloatingLiteral</a>&gt;</td><td class="name" onclick="toggle('equals1')"><a name="equals1Anchor">equals</a></td><td>ValueT Value</td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FloatingLiteral.html">FloatingLiteral</a>&gt;</td><td class="name" onclick="toggle('equals1')"><a name="equals1Anchor">equals</a></td><td>const ValueT Value</td></tr>
<tr><td colspan="4" class="doc" id="equals1"><pre>Matches literals that are equal to the given value of type ValueT.
Given
@@ -2741,16 +2829,29 @@ Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXOp
</pre></td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('hasTrailingReturn0')"><a name="hasTrailingReturn0Anchor">hasTrailingReturn</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="hasTrailingReturn0"><pre>Matches a function declared with a trailing return type.
+
+Example matches Y (matcher = functionDecl(hasTrailingReturn()))
+int X() {}
+auto Y() -&gt; int {}
+</pre></td></tr>
+
+
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('isConstexpr1')"><a name="isConstexpr1Anchor">isConstexpr</a></td><td></td></tr>
-<tr><td colspan="4" class="doc" id="isConstexpr1"><pre>Matches constexpr variable and function declarations.
+<tr><td colspan="4" class="doc" id="isConstexpr1"><pre>Matches constexpr variable and function declarations,
+ and if constexpr.
Given:
constexpr int foo = 42;
constexpr int bar();
+ void baz() { if constexpr(1 &gt; 0) {} }
varDecl(isConstexpr())
matches the declaration of foo.
functionDecl(isConstexpr())
matches the declaration of bar.
+ifStmt(isConstexpr())
+ matches the if statement in baz.
</pre></td></tr>
@@ -2811,6 +2912,7 @@ functionDecl(isExplicitTemplateSpecialization())
Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;
</pre></td></tr>
+
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('isExternC0')"><a name="isExternC0Anchor">isExternC</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isExternC0"><pre>Matches extern "C" function or variable declarations.
@@ -2827,6 +2929,7 @@ varDecl(isExternC())
matches the declaration of x and y, but not the declaration of z.
</pre></td></tr>
+
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('isInline1')"><a name="isInline1Anchor">isInline</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isInline1"><pre>Matches function and namespace declarations that are marked with
the inline keyword.
@@ -2842,6 +2945,26 @@ namespaceDecl(isInline()) will match n::m.
</pre></td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('isMain0')"><a name="isMain0Anchor">isMain</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="isMain0"><pre>Determines whether the function is "main", which is the entry point
+into an executable program.
+</pre></td></tr>
+
+
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('isNoReturn0')"><a name="isNoReturn0Anchor">isNoReturn</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="isNoReturn0"><pre>Matches FunctionDecls that have a noreturn attribute.
+
+Given
+ void nope();
+ [[noreturn]] void a();
+ __attribute__((noreturn)) void b();
+ struct c { [[noreturn]] c(); };
+functionDecl(isNoReturn())
+ matches all of those except
+ void nope();
+</pre></td></tr>
+
+
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('isNoThrow0')"><a name="isNoThrow0Anchor">isNoThrow</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isNoThrow0"><pre>Matches functions that have a non-throwing exception specification.
@@ -2880,6 +3003,8 @@ Given
template &lt;typename T&gt; class X {}; class A {}; X&lt;A&gt; x;
or
template &lt;typename T&gt; class X {}; class A {}; template class X&lt;A&gt;;
+or
+ template &lt;typename T&gt; class X {}; class A {}; extern template class X&lt;A&gt;;
cxxRecordDecl(hasName("::X"), isTemplateInstantiation())
matches the template instantiation of X&lt;A&gt;.
@@ -2916,11 +3041,11 @@ Given
void j(int i);
void k(int x, int y, int z, ...);
functionDecl(parameterCountIs(2))
- matches void g(int i, int j) {}
+ matches g and h
functionProtoType(parameterCountIs(2))
- matches void h(int i, int j)
+ matches g and h
functionProtoType(parameterCountIs(3))
- matches void k(int x, int y, int z, ...);
+ matches k
</pre></td></tr>
@@ -2966,15 +3091,36 @@ Given
void j(int i);
void k(int x, int y, int z, ...);
functionDecl(parameterCountIs(2))
- matches void g(int i, int j) {}
+ matches g and h
functionProtoType(parameterCountIs(2))
- matches void h(int i, int j)
+ matches g and h
functionProtoType(parameterCountIs(3))
- matches void k(int x, int y, int z, ...);
+ matches k
+</pre></td></tr>
+
+
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1IfStmt.html">IfStmt</a>&gt;</td><td class="name" onclick="toggle('isConstexpr2')"><a name="isConstexpr2Anchor">isConstexpr</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="isConstexpr2"><pre>Matches constexpr variable and function declarations,
+ and if constexpr.
+
+Given:
+ constexpr int foo = 42;
+ constexpr int bar();
+ void baz() { if constexpr(1 &gt; 0) {} }
+varDecl(isConstexpr())
+ matches the declaration of foo.
+functionDecl(isConstexpr())
+ matches the declaration of bar.
+ifStmt(isConstexpr())
+ matches the if statement in baz.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>&gt;</td><td class="name" onclick="toggle('equals0')"><a name="equals0Anchor">equals</a></td><td>ValueT Value</td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>&gt;</td><td class="name" onclick="toggle('equals6')"><a name="equals6Anchor">equals</a></td><td>bool Value</td></tr>
+<tr><td colspan="4" class="doc" id="equals6"><pre></pre></td></tr>
+
+
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>&gt;</td><td class="name" onclick="toggle('equals0')"><a name="equals0Anchor">equals</a></td><td>const ValueT Value</td></tr>
<tr><td colspan="4" class="doc" id="equals0"><pre>Matches literals that are equal to the given value of type ValueT.
Given
@@ -3000,10 +3146,6 @@ Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Chara
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>&gt;</td><td class="name" onclick="toggle('equals6')"><a name="equals6Anchor">equals</a></td><td>bool Value</td></tr>
-<tr><td colspan="4" class="doc" id="equals6"><pre></pre></td></tr>
-
-
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>&gt;</td><td class="name" onclick="toggle('equals13')"><a name="equals13Anchor">equals</a></td><td>double Value</td></tr>
<tr><td colspan="4" class="doc" id="equals13"><pre></pre></td></tr>
@@ -3049,7 +3191,7 @@ void f() {}
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>&gt;</td><td class="name" onclick="toggle('hasName0')"><a name="hasName0Anchor">hasName</a></td><td>std::string Name</td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>&gt;</td><td class="name" onclick="toggle('hasName0')"><a name="hasName0Anchor">hasName</a></td><td>const std::string Name</td></tr>
<tr><td colspan="4" class="doc" id="hasName0"><pre>Matches NamedDecl nodes that have the specified name.
Supports specifying enclosing namespaces or classes by prefixing the name
@@ -3158,6 +3300,19 @@ represent an error condition in the tree!
</pre></td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;</td><td class="name" onclick="toggle('isInstanceMessage0')"><a name="isInstanceMessage0Anchor">isInstanceMessage</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="isInstanceMessage0"><pre>Returns true when the Objective-C message is sent to an instance.
+
+Example
+matcher = objcMessagaeExpr(isInstanceMessage())
+matches
+ NSString *x = @"hello";
+ [x containsString:@"h"];
+but not
+ [NSString stringWithFormat:@"format"];
+</pre></td></tr>
+
+
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;</td><td class="name" onclick="toggle('matchesSelector0')"><a name="matchesSelector0Anchor">matchesSelector</a></td><td>std::string RegExp</td></tr>
<tr><td colspan="4" class="doc" id="matchesSelector0"><pre>Matches ObjC selectors whose name contains
a substring matched by the given RegExp.
@@ -3510,7 +3665,7 @@ an arbitrary precision integer. 'Value' must be euqal to the canonical
representation of that integral value in base 10.
Given
- template&lt;int T&gt; struct A {};
+ template&lt;int T&gt; struct C {};
C&lt;42&gt; c;
classTemplateSpecializationDecl(
hasAnyTemplateArgument(equalsIntegralValue("42")))
@@ -3522,7 +3677,7 @@ classTemplateSpecializationDecl(
<tr><td colspan="4" class="doc" id="isIntegral0"><pre>Matches a TemplateArgument that is an integral value.
Given
- template&lt;int T&gt; struct A {};
+ template&lt;int T&gt; struct C {};
C&lt;42&gt; c;
classTemplateSpecializationDecl(
hasAnyTemplateArgument(isIntegral()))
@@ -3738,15 +3893,19 @@ int a;
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;</td><td class="name" onclick="toggle('isConstexpr0')"><a name="isConstexpr0Anchor">isConstexpr</a></td><td></td></tr>
-<tr><td colspan="4" class="doc" id="isConstexpr0"><pre>Matches constexpr variable and function declarations.
+<tr><td colspan="4" class="doc" id="isConstexpr0"><pre>Matches constexpr variable and function declarations,
+ and if constexpr.
Given:
constexpr int foo = 42;
constexpr int bar();
+ void baz() { if constexpr(1 &gt; 0) {} }
varDecl(isConstexpr())
matches the declaration of foo.
functionDecl(isConstexpr())
matches the declaration of bar.
+ifStmt(isConstexpr())
+ matches the if statement in baz.
</pre></td></tr>
@@ -3798,6 +3957,7 @@ functionDecl(isExplicitTemplateSpecialization())
Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;
</pre></td></tr>
+
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;</td><td class="name" onclick="toggle('isExternC1')"><a name="isExternC1Anchor">isExternC</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isExternC1"><pre>Matches extern "C" function or variable declarations.
@@ -3814,6 +3974,7 @@ varDecl(isExternC())
matches the declaration of x and y, but not the declaration of z.
</pre></td></tr>
+
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;</td><td class="name" onclick="toggle('isStaticStorageClass1')"><a name="isStaticStorageClass1Anchor">isStaticStorageClass</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isStaticStorageClass1"><pre>Matches variablefunction declarations that have "static" storage
class specifier ("static" keyword) written in the source.
@@ -3838,6 +3999,8 @@ Given
template &lt;typename T&gt; class X {}; class A {}; X&lt;A&gt; x;
or
template &lt;typename T&gt; class X {}; class A {}; template class X&lt;A&gt;;
+or
+ template &lt;typename T&gt; class X {}; class A {}; extern template class X&lt;A&gt;;
cxxRecordDecl(hasName("::X"), isTemplateInstantiation())
matches the template instantiation of X&lt;A&gt;.
@@ -3891,6 +4054,17 @@ This matcher is only provided as a performance optimization of hasName.
</pre></td></tr>
+<tr><td>Matcher&lt;internal::Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;&gt;</td><td class="name" onclick="toggle('hasAnySelector0')"><a name="hasAnySelector0Anchor">hasAnySelector</a></td><td>StringRef, ..., StringRef</td></tr>
+<tr><td colspan="4" class="doc" id="hasAnySelector0"><pre>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:
+ [myObj methodA:argA];
+ [myObj methodB:argB];
+</pre></td></tr>
+
+
<tr><td>Matcher&lt;internal::Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;&gt;</td><td class="name" onclick="toggle('isInTemplateInstantiation0')"><a name="isInTemplateInstantiation0Anchor">isInTemplateInstantiation</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isInTemplateInstantiation0"><pre>Matches statements inside of a template instantiation.
@@ -3947,10 +4121,11 @@ Usable as: Any Matcher
<tr><td colspan="4" class="doc" id="forEachDescendant0"><pre>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")))))
- 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 {}; }; };
DescendantT must be an AST base type.
@@ -3973,10 +4148,11 @@ Usable as: Any Matcher
<tr><td colspan="4" class="doc" id="forEach0"><pre>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")))
- 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.
ChildT must be an AST base type.
@@ -4079,7 +4255,7 @@ Example 2 (conditional binary operator): matches opaqueValueExpr(condition)
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration15')"><a name="hasDeclaration15Anchor">hasDeclaration</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration15')"><a name="hasDeclaration15Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration15"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
@@ -4089,9 +4265,19 @@ The associated declaration is:
- 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
-Also usable as Matcher&lt;T&gt; for any T supporting the getDecl() member
-function. e.g. various subtypes of clang::Type and various expressions.
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
+ class X {};
+ typedef X Y;
+ Y y;
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
+This can be achieved by using the hasUnqualifiedDesugaredType matcher:
+ varDecl(hasType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
@@ -4214,7 +4400,7 @@ Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AutoT
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>&gt;</td><td class="name" onclick="toggle('hasEitherOperand0')"><a name="hasEitherOperand0Anchor">hasEitherOperand</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>&gt;</td><td class="name" onclick="toggle('hasEitherOperand0')"><a name="hasEitherOperand0Anchor">hasEitherOperand</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasEitherOperand0"><pre>Matches if either the left hand side or the right hand side of a
binary operator matches.
</pre></td></tr>
@@ -4236,6 +4422,55 @@ Example matches b (matcher = binaryOperator(hasRHS()))
</pre></td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1BlockDecl.html">BlockDecl</a>&gt;</td><td class="name" onclick="toggle('hasAnyParameter2')"><a name="hasAnyParameter2Anchor">hasAnyParameter</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt; InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasAnyParameter2"><pre>Matches any parameter of a function or an ObjC method declaration or a
+block.
+
+Does not match the 'this' parameter of a method.
+
+Given
+ class X { void f(int x, int y, int z) {} };
+cxxMethodDecl(hasAnyParameter(hasName("y")))
+ matches f(int x, int y, int z) {}
+with hasAnyParameter(...)
+ matching int y
+
+For ObjectiveC, given
+ @interface I - (void) f:(int) y; @end
+
+the matcher objcMethodDecl(hasAnyParameter(hasName("y")))
+matches the declaration of method f with hasParameter
+matching y.
+
+For blocks, given
+ b = ^(int y) { printf("%d", y) };
+
+the matcher blockDecl(hasAnyParameter(hasName("y")))
+matches the declaration of the block b with hasParameter
+matching y.
+</pre></td></tr>
+
+
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1BlockDecl.html">BlockDecl</a>&gt;</td><td class="name" onclick="toggle('hasParameter2')"><a name="hasParameter2Anchor">hasParameter</a></td><td>unsigned N, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt; InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasParameter2"><pre>Matches the n'th parameter of a function or an ObjC method
+declaration or a block.
+
+Given
+ class X { void f(int x) {} };
+cxxMethodDecl(hasParameter(0, hasType(varDecl())))
+ matches f(int x) {}
+with hasParameter(...)
+ matching int x
+
+For ObjectiveC, given
+ @interface I - (void) f:(int) y; @end
+
+the matcher objcMethodDecl(hasParameter(0, hasName("y")))
+matches the declaration of method f with hasParameter
+matching y.
+</pre></td></tr>
+
+
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1BlockPointerTypeLoc.html">BlockPointerTypeLoc</a>&gt;</td><td class="name" onclick="toggle('pointeeLoc0')"><a name="pointeeLoc0Anchor">pointeeLoc</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;</td></tr>
<tr><td colspan="4" class="doc" id="pointeeLoc0"><pre>Narrows PointerType (and similar) matchers to those where the
pointee matches a given matcher.
@@ -4290,7 +4525,7 @@ and parmVarDecl(...)
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;</td><td class="name" onclick="toggle('hasAnyArgument1')"><a name="hasAnyArgument1Anchor">hasAnyArgument</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasAnyArgument1"><pre>Matches any argument of a call expression or a constructor call
-expression.
+expression, or an ObjC-message-send expression.
Given
void x(int, int, int) { int y; x(1, y, 42); }
@@ -4298,6 +4533,12 @@ callExpr(hasAnyArgument(declRefExpr()))
matches x(1, y, 42)
with hasAnyArgument(...)
matching y
+
+For ObjectiveC, given
+ @interface I - (void) f:(int) y; @end
+ void foo(I *i) { [i f:12]; }
+objcMessageExpr(hasAnyArgument(integerLiteral(equals(12))))
+ matches [i f:12]
</pre></td></tr>
@@ -4311,7 +4552,7 @@ Example matches y in x(y)
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration13')"><a name="hasDeclaration13Anchor">hasDeclaration</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration13')"><a name="hasDeclaration13Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration13"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
@@ -4321,9 +4562,19 @@ The associated declaration is:
- 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
-Also usable as Matcher&lt;T&gt; for any T supporting the getDecl() member
-function. e.g. various subtypes of clang::Type and various expressions.
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
+ class X {};
+ typedef X Y;
+ Y y;
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
+This can be achieved by using the hasUnqualifiedDesugaredType matcher:
+ varDecl(hasType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
@@ -4435,7 +4686,7 @@ matches 'a' in
Example matches y.x()
(matcher = cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("Y"))))))
class Y { public: void x(); };
- void z() { Y y; y.x(); }",
+ void z() { Y y; y.x(); }
FIXME: Overload to allow directly matching types?
</pre></td></tr>
@@ -4453,7 +4704,7 @@ matcher, or is a pointer to a type that matches the InnerMatcher.
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt;</td><td class="name" onclick="toggle('forEachOverridden0')"><a name="forEachOverridden0Anchor">forEachOverridden</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt; InnerMatcher</td></tr>
-<tr><td colspan="4" class="doc" id="forEachOverridden0"><pre>Matches each method overriden by the given method. This matcher may
+<tr><td colspan="4" class="doc" id="forEachOverridden0"><pre>Matches each method overridden by the given method. This matcher may
produce multiple matches.
Given
@@ -4505,7 +4756,7 @@ cxxNewExpr(hasArraySize(intgerLiteral(equals(10))))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration12')"><a name="hasDeclaration12Anchor">hasDeclaration</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration12')"><a name="hasDeclaration12Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration12"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
@@ -4515,9 +4766,19 @@ The associated declaration is:
- 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
-Also usable as Matcher&lt;T&gt; for any T supporting the getDecl() member
-function. e.g. various subtypes of clang::Type and various expressions.
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
+ class X {};
+ typedef X Y;
+ Y y;
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
+This can be achieved by using the hasUnqualifiedDesugaredType matcher:
+ varDecl(hasType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
@@ -4619,7 +4880,7 @@ and parmVarDecl(...)
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;</td><td class="name" onclick="toggle('hasAnyArgument0')"><a name="hasAnyArgument0Anchor">hasAnyArgument</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasAnyArgument0"><pre>Matches any argument of a call expression or a constructor call
-expression.
+expression, or an ObjC-message-send expression.
Given
void x(int, int, int) { int y; x(1, y, 42); }
@@ -4627,6 +4888,12 @@ callExpr(hasAnyArgument(declRefExpr()))
matches x(1, y, 42)
with hasAnyArgument(...)
matching y
+
+For ObjectiveC, given
+ @interface I - (void) f:(int) y; @end
+ void foo(I *i) { [i f:12]; }
+objcMessageExpr(hasAnyArgument(integerLiteral(equals(12))))
+ matches [i f:12]
</pre></td></tr>
@@ -4640,7 +4907,7 @@ Example matches y in x(y)
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration14')"><a name="hasDeclaration14Anchor">hasDeclaration</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration14')"><a name="hasDeclaration14Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration14"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
@@ -4650,9 +4917,19 @@ The associated declaration is:
- 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
-Also usable as Matcher&lt;T&gt; for any T supporting the getDecl() member
-function. e.g. various subtypes of clang::Type and various expressions.
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
+ class X {};
+ typedef X Y;
+ Y y;
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
+This can be achieved by using the hasUnqualifiedDesugaredType matcher:
+ varDecl(hasType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
@@ -4676,7 +4953,18 @@ caseStmt(hasCaseConstant(integerLiteral()))
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CastExpr.html">CastExpr</a>&gt;</td><td class="name" onclick="toggle('hasSourceExpression0')"><a name="hasSourceExpression0Anchor">hasSourceExpression</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
-<tr><td colspan="4" class="doc" id="hasSourceExpression0"><pre></pre></td></tr>
+<tr><td colspan="4" class="doc" id="hasSourceExpression0"><pre>Matches if the cast's source expression
+or opaque value's source expression matches the given matcher.
+
+Example 1: matches "a string"
+(matcher = castExpr(hasSourceExpression(cxxConstructExpr())))
+class URL { URL(string); };
+URL url = "a string";
+
+Example 2: matches 'b' (matcher =
+opaqueValueExpr(hasSourceExpression(implicitCastExpr(declRefExpr())))
+int a = b ?: 1;
+</pre></td></tr>
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>&gt;</td><td class="name" onclick="toggle('hasAnyTemplateArgument0')"><a name="hasAnyTemplateArgument0Anchor">hasAnyTemplateArgument</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt; InnerMatcher</td></tr>
@@ -4722,7 +5010,7 @@ Given
A&lt;bool, int&gt; b;
A&lt;int, bool&gt; c;
- template&lt;typename T&gt; f() {};
+ template&lt;typename T&gt; void f() {}
void func() { f&lt;int&gt;(); };
classTemplateSpecializationDecl(hasTemplateArgument(
1, refersToType(asString("int"))))
@@ -4781,7 +5069,7 @@ with compoundStmt()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration11')"><a name="hasDeclaration11Anchor">hasDeclaration</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration11')"><a name="hasDeclaration11Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration11"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
@@ -4791,9 +5079,19 @@ The associated declaration is:
- 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
-Also usable as Matcher&lt;T&gt; for any T supporting the getDecl() member
-function. e.g. various subtypes of clang::Type and various expressions.
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
+ class X {};
+ typedef X Y;
+ Y y;
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
+This can be achieved by using the hasUnqualifiedDesugaredType matcher:
+ varDecl(hasType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
@@ -4889,6 +5187,19 @@ declaration of class D.
</pre></td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DecltypeType.html">DecltypeType</a>&gt;</td><td class="name" onclick="toggle('hasUnderlyingType0')"><a name="hasUnderlyingType0Anchor">hasUnderlyingType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td></tr>
+<tr><td colspan="4" class="doc" id="hasUnderlyingType0"><pre>Matches DecltypeType nodes to find out the underlying type.
+
+Given
+ decltype(1) a = 1;
+ decltype(2.0) b = 2.0;
+decltypeType(hasUnderlyingType(isInteger()))
+ matches "auto a"
+
+Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DecltypeType.html">DecltypeType</a>&gt;
+</pre></td></tr>
+
+
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DoStmt.html">DoStmt</a>&gt;</td><td class="name" onclick="toggle('hasBody0')"><a name="hasBody0Anchor">hasBody</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasBody0"><pre>Matches a 'for', 'while', 'do while' statement or a function
definition that has a given body.
@@ -4945,7 +5256,7 @@ declaration of d.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration10')"><a name="hasDeclaration10Anchor">hasDeclaration</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration10')"><a name="hasDeclaration10Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration10"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
@@ -4955,9 +5266,19 @@ The associated declaration is:
- 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
-Also usable as Matcher&lt;T&gt; for any T supporting the getDecl() member
-function. e.g. various subtypes of clang::Type and various expressions.
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
+ class X {};
+ typedef X Y;
+ Y y;
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
+This can be achieved by using the hasUnqualifiedDesugaredType matcher:
+ varDecl(hasType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
@@ -4977,8 +5298,8 @@ actual casts "explicit" casts.)
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;</td><td class="name" onclick="toggle('hasType3')"><a name="hasType3Anchor">hasType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
-<tr><td colspan="4" class="doc" id="hasType3"><pre>Overloaded to match the declaration of the expression's or value
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;</td><td class="name" onclick="toggle('hasType4')"><a name="hasType4Anchor">hasType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasType4"><pre>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),
@@ -4989,8 +5310,10 @@ declaration of x.
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"))
class X {};
void y(X &amp;x) { x; X z; }
+ class Y { friend class X; };
Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>&gt;
</pre></td></tr>
@@ -5003,9 +5326,11 @@ 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"))
class X {};
void y(X &amp;x) { x; X z; }
typedef int U;
+ class Y { friend class X; };
</pre></td></tr>
@@ -5032,7 +5357,7 @@ only match the declarations for b, c, and d.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;</td><td class="name" onclick="toggle('ignoringImplicit0')"><a name="ignoringImplicit0Anchor">ignoringImplicit</a></td><td>ast_matchers::Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;</td><td class="name" onclick="toggle('ignoringImplicit0')"><a name="ignoringImplicit0Anchor">ignoringImplicit</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="ignoringImplicit0"><pre>Matches expressions that match InnerMatcher after any implicit AST
nodes are stripped off.
@@ -5151,8 +5476,45 @@ matches 'int x = 0' in
</pre></td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FriendDecl.html">FriendDecl</a>&gt;</td><td class="name" onclick="toggle('hasType5')"><a name="hasType5Anchor">hasType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasType5"><pre>Overloaded to match the declaration of the expression's or value
+declaration's type.
+
+In case of a value declaration (for example a variable declaration),
+this resolves one layer of indirection. For example, in the value
+declaration "X x;", cxxRecordDecl(hasName("X")) matches the declaration of
+X, while varDecl(hasType(cxxRecordDecl(hasName("X")))) matches the
+declaration of x.
+
+Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
+ and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
+ and friend class X (matcher = friendDecl(hasType("X"))
+ class X {};
+ void y(X &amp;x) { x; X z; }
+ class Y { friend class X; };
+
+Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>&gt;
+</pre></td></tr>
+
+
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FriendDecl.html">FriendDecl</a>&gt;</td><td class="name" onclick="toggle('hasType1')"><a name="hasType1Anchor">hasType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasType1"><pre>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"))
+ class X {};
+ void y(X &amp;x) { x; X z; }
+ typedef int U;
+ class Y { friend class X; };
+</pre></td></tr>
+
+
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('hasAnyParameter0')"><a name="hasAnyParameter0Anchor">hasAnyParameter</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt; InnerMatcher</td></tr>
-<tr><td colspan="4" class="doc" id="hasAnyParameter0"><pre>Matches any parameter of a function declaration.
+<tr><td colspan="4" class="doc" id="hasAnyParameter0"><pre>Matches any parameter of a function or an ObjC method declaration or a
+block.
Does not match the 'this' parameter of a method.
@@ -5162,6 +5524,20 @@ cxxMethodDecl(hasAnyParameter(hasName("y")))
matches f(int x, int y, int z) {}
with hasAnyParameter(...)
matching int y
+
+For ObjectiveC, given
+ @interface I - (void) f:(int) y; @end
+
+the matcher objcMethodDecl(hasAnyParameter(hasName("y")))
+matches the declaration of method f with hasParameter
+matching y.
+
+For blocks, given
+ b = ^(int y) { printf("%d", y) };
+
+the matcher blockDecl(hasAnyParameter(hasName("y")))
+matches the declaration of the block b with hasParameter
+matching y.
</pre></td></tr>
@@ -5201,7 +5577,8 @@ with compoundStmt()
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('hasParameter0')"><a name="hasParameter0Anchor">hasParameter</a></td><td>unsigned N, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt; InnerMatcher</td></tr>
-<tr><td colspan="4" class="doc" id="hasParameter0"><pre>Matches the n'th parameter of a function declaration.
+<tr><td colspan="4" class="doc" id="hasParameter0"><pre>Matches the n'th parameter of a function or an ObjC method
+declaration or a block.
Given
class X { void f(int x) {} };
@@ -5209,6 +5586,13 @@ cxxMethodDecl(hasParameter(0, hasType(varDecl())))
matches f(int x) {}
with hasParameter(...)
matching int x
+
+For ObjectiveC, given
+ @interface I - (void) f:(int) y; @end
+
+the matcher objcMethodDecl(hasParameter(0, hasName("y")))
+matches the declaration of method f with hasParameter
+matching y.
</pre></td></tr>
@@ -5221,7 +5605,7 @@ Given
A&lt;bool, int&gt; b;
A&lt;int, bool&gt; c;
- template&lt;typename T&gt; f() {};
+ template&lt;typename T&gt; void f() {}
void func() { f&lt;int&gt;(); };
classTemplateSpecializationDecl(hasTemplateArgument(
1, refersToType(asString("int"))))
@@ -5293,7 +5677,7 @@ FIXME: Unit test this matcher
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration9')"><a name="hasDeclaration9Anchor">hasDeclaration</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration9')"><a name="hasDeclaration9Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration9"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
@@ -5303,9 +5687,19 @@ The associated declaration is:
- 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
-Also usable as Matcher&lt;T&gt; for any T supporting the getDecl() member
-function. e.g. various subtypes of clang::Type and various expressions.
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
+ class X {};
+ typedef X Y;
+ Y y;
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
+This can be achieved by using the hasUnqualifiedDesugaredType matcher:
+ varDecl(hasType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
@@ -5317,7 +5711,7 @@ Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrL
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration8')"><a name="hasDeclaration8Anchor">hasDeclaration</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration8')"><a name="hasDeclaration8Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration8"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
@@ -5327,9 +5721,19 @@ The associated declaration is:
- 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
-Also usable as Matcher&lt;T&gt; for any T supporting the getDecl() member
-function. e.g. various subtypes of clang::Type and various expressions.
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
+ class X {};
+ typedef X Y;
+ Y y;
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
+This can be achieved by using the hasUnqualifiedDesugaredType matcher:
+ varDecl(hasType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
@@ -5341,7 +5745,7 @@ Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrL
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration7')"><a name="hasDeclaration7Anchor">hasDeclaration</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration7')"><a name="hasDeclaration7Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration7"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
@@ -5351,9 +5755,19 @@ The associated declaration is:
- 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
-Also usable as Matcher&lt;T&gt; for any T supporting the getDecl() member
-function. e.g. various subtypes of clang::Type and various expressions.
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
+ class X {};
+ typedef X Y;
+ Y y;
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
+This can be achieved by using the hasUnqualifiedDesugaredType matcher:
+ varDecl(hasType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
@@ -5499,6 +5913,25 @@ nestedNameSpecifier(specifiesType(
</pre></td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;</td><td class="name" onclick="toggle('hasAnyArgument2')"><a name="hasAnyArgument2Anchor">hasAnyArgument</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasAnyArgument2"><pre>Matches any argument of a call expression or a constructor call
+expression, or an ObjC-message-send expression.
+
+Given
+ void x(int, int, int) { int y; x(1, y, 42); }
+callExpr(hasAnyArgument(declRefExpr()))
+ matches x(1, y, 42)
+with hasAnyArgument(...)
+ matching y
+
+For ObjectiveC, given
+ @interface I - (void) f:(int) y; @end
+ void foo(I *i) { [i f:12]; }
+objcMessageExpr(hasAnyArgument(integerLiteral(equals(12))))
+ matches [i f:12]
+</pre></td></tr>
+
+
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;</td><td class="name" onclick="toggle('hasArgument2')"><a name="hasArgument2Anchor">hasArgument</a></td><td>unsigned N, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasArgument2"><pre>Matches the n'th argument of a call expression or a constructor
call expression.
@@ -5509,6 +5942,18 @@ Example matches y in x(y)
</pre></td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;</td><td class="name" onclick="toggle('hasReceiver0')"><a name="hasReceiver0Anchor">hasReceiver</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasReceiver0"><pre>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
+ NSString *x = @"hello";
+ [x containsString:@"h"];
+is matched by
+objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x"))))))
+</pre></td></tr>
+
+
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;</td><td class="name" onclick="toggle('hasReceiverType0')"><a name="hasReceiverType0Anchor">hasReceiverType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasReceiverType0"><pre>Matches on the receiver of an ObjectiveC Message expression.
@@ -5521,8 +5966,68 @@ matches the [webView ...] message invocation.
</pre></td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>&gt;</td><td class="name" onclick="toggle('hasAnyParameter1')"><a name="hasAnyParameter1Anchor">hasAnyParameter</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt; InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasAnyParameter1"><pre>Matches any parameter of a function or an ObjC method declaration or a
+block.
+
+Does not match the 'this' parameter of a method.
+
+Given
+ class X { void f(int x, int y, int z) {} };
+cxxMethodDecl(hasAnyParameter(hasName("y")))
+ matches f(int x, int y, int z) {}
+with hasAnyParameter(...)
+ matching int y
+
+For ObjectiveC, given
+ @interface I - (void) f:(int) y; @end
+
+the matcher objcMethodDecl(hasAnyParameter(hasName("y")))
+matches the declaration of method f with hasParameter
+matching y.
+
+For blocks, given
+ b = ^(int y) { printf("%d", y) };
+
+the matcher blockDecl(hasAnyParameter(hasName("y")))
+matches the declaration of the block b with hasParameter
+matching y.
+</pre></td></tr>
+
+
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>&gt;</td><td class="name" onclick="toggle('hasParameter1')"><a name="hasParameter1Anchor">hasParameter</a></td><td>unsigned N, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt; InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasParameter1"><pre>Matches the n'th parameter of a function or an ObjC method
+declaration or a block.
+
+Given
+ class X { void f(int x) {} };
+cxxMethodDecl(hasParameter(0, hasType(varDecl())))
+ matches f(int x) {}
+with hasParameter(...)
+ matching int x
+
+For ObjectiveC, given
+ @interface I - (void) f:(int) y; @end
+
+the matcher objcMethodDecl(hasParameter(0, hasName("y")))
+matches the declaration of method f with hasParameter
+matching y.
+</pre></td></tr>
+
+
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1OpaqueValueExpr.html">OpaqueValueExpr</a>&gt;</td><td class="name" onclick="toggle('hasSourceExpression1')"><a name="hasSourceExpression1Anchor">hasSourceExpression</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
-<tr><td colspan="4" class="doc" id="hasSourceExpression1"><pre></pre></td></tr>
+<tr><td colspan="4" class="doc" id="hasSourceExpression1"><pre>Matches if the cast's source expression
+or opaque value's source expression matches the given matcher.
+
+Example 1: matches "a string"
+(matcher = castExpr(hasSourceExpression(cxxConstructExpr())))
+class URL { URL(string); };
+URL url = "a string";
+
+Example 2: matches 'b' (matcher =
+opaqueValueExpr(hasSourceExpression(implicitCastExpr(declRefExpr())))
+int a = b ?: 1;
+</pre></td></tr>
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1OverloadExpr.html">OverloadExpr</a>&gt;</td><td class="name" onclick="toggle('hasAnyDeclaration0')"><a name="hasAnyDeclaration0Anchor">hasAnyDeclaration</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
@@ -5601,7 +6106,7 @@ declaration of b but varDecl(hasType(qualType(hasCanonicalType(referenceType()))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration6')"><a name="hasDeclaration6Anchor">hasDeclaration</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration6')"><a name="hasDeclaration6Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration6"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
@@ -5611,9 +6116,19 @@ The associated declaration is:
- 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
-Also usable as Matcher&lt;T&gt; for any T supporting the getDecl() member
-function. e.g. various subtypes of clang::Type and various expressions.
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
+ class X {};
+ typedef X Y;
+ Y y;
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
+This can be achieved by using the hasUnqualifiedDesugaredType matcher:
+ varDecl(hasType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
@@ -5673,7 +6188,7 @@ Example matches X &amp;x and const X &amp;y
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration5')"><a name="hasDeclaration5Anchor">hasDeclaration</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration5')"><a name="hasDeclaration5Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration5"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
@@ -5683,9 +6198,19 @@ The associated declaration is:
- 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
-Also usable as Matcher&lt;T&gt; for any T supporting the getDecl() member
-function. e.g. various subtypes of clang::Type and various expressions.
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
+ class X {};
+ typedef X Y;
+ Y y;
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
+This can be achieved by using the hasUnqualifiedDesugaredType matcher:
+ varDecl(hasType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
@@ -5754,7 +6279,7 @@ with compoundStmt()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('alignOfExpr0')"><a name="alignOfExpr0Anchor">alignOfExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnaryExprOrTypeTraitExpr.html">UnaryExprOrTypeTraitExpr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('alignOfExpr0')"><a name="alignOfExpr0Anchor">alignOfExpr</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnaryExprOrTypeTraitExpr.html">UnaryExprOrTypeTraitExpr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="alignOfExpr0"><pre>Same as unaryExprOrTypeTraitExpr, but only matching
alignof.
</pre></td></tr>
@@ -5774,7 +6299,7 @@ returnStmt(forFunction(hasName("operator=")))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('sizeOfExpr0')"><a name="sizeOfExpr0Anchor">sizeOfExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnaryExprOrTypeTraitExpr.html">UnaryExprOrTypeTraitExpr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('sizeOfExpr0')"><a name="sizeOfExpr0Anchor">sizeOfExpr</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnaryExprOrTypeTraitExpr.html">UnaryExprOrTypeTraitExpr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="sizeOfExpr0"><pre>Same as unaryExprOrTypeTraitExpr, but only matching
sizeof.
</pre></td></tr>
@@ -5816,7 +6341,7 @@ Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true))))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration4')"><a name="hasDeclaration4Anchor">hasDeclaration</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration4')"><a name="hasDeclaration4Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration4"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
@@ -5826,9 +6351,19 @@ The associated declaration is:
- 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
-Also usable as Matcher&lt;T&gt; for any T supporting the getDecl() member
-function. e.g. various subtypes of clang::Type and various expressions.
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
+ class X {};
+ typedef X Y;
+ Y y;
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
+This can be achieved by using the hasUnqualifiedDesugaredType matcher:
+ varDecl(hasType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
@@ -5844,8 +6379,8 @@ Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrL
<tr><td colspan="4" class="doc" id="isExpr0"><pre>Matches a sugar TemplateArgument that refers to a certain expression.
Given
- template&lt;typename T&gt; struct A {};
- struct B { B* next; };
+ struct B { int next; };
+ template&lt;int(B::*next_ptr)&gt; struct A {};
A&lt;&amp;B::next&gt; a;
templateSpecializationType(hasAnyTemplateArgument(
isExpr(hasDescendant(declRefExpr(to(fieldDecl(hasName("next"))))))))
@@ -5859,11 +6394,11 @@ templateSpecializationType(hasAnyTemplateArgument(
declaration.
Given
- template&lt;typename T&gt; struct A {};
- struct B { B* next; };
+ struct B { int next; };
+ template&lt;int(B::*next_ptr)&gt; struct A {};
A&lt;&amp;B::next&gt; a;
classTemplateSpecializationDecl(hasAnyTemplateArgument(
- refersToDeclaration(fieldDecl(hasName("next"))))
+ refersToDeclaration(fieldDecl(hasName("next")))))
matches the specialization A&lt;&amp;B::next&gt; with fieldDecl(...) matching
B::next
</pre></td></tr>
@@ -5873,7 +6408,7 @@ classTemplateSpecializationDecl(hasAnyTemplateArgument(
<tr><td colspan="4" class="doc" id="refersToIntegralType0"><pre>Matches a TemplateArgument that referes to an integral type.
Given
- template&lt;int T&gt; struct A {};
+ template&lt;int T&gt; struct C {};
C&lt;42&gt; c;
classTemplateSpecializationDecl(
hasAnyTemplateArgument(refersToIntegralType(asString("int"))))
@@ -5929,7 +6464,7 @@ functionDecl(hasAnyTemplateArgument(refersToType(asString("int"))))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration3')"><a name="hasDeclaration3Anchor">hasDeclaration</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration3')"><a name="hasDeclaration3Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration3"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
@@ -5939,9 +6474,19 @@ The associated declaration is:
- 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
-Also usable as Matcher&lt;T&gt; for any T supporting the getDecl() member
-function. e.g. various subtypes of clang::Type and various expressions.
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
+ class X {};
+ typedef X Y;
+ Y y;
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
+This can be achieved by using the hasUnqualifiedDesugaredType matcher:
+ varDecl(hasType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
@@ -5962,7 +6507,7 @@ Given
A&lt;bool, int&gt; b;
A&lt;int, bool&gt; c;
- template&lt;typename T&gt; f() {};
+ template&lt;typename T&gt; void f() {}
void func() { f&lt;int&gt;(); };
classTemplateSpecializationDecl(hasTemplateArgument(
1, refersToType(asString("int"))))
@@ -5973,7 +6518,7 @@ functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration2')"><a name="hasDeclaration2Anchor">hasDeclaration</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration2')"><a name="hasDeclaration2Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration2"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
@@ -5983,9 +6528,19 @@ The associated declaration is:
- 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
-Also usable as Matcher&lt;T&gt; for any T supporting the getDecl() member
-function. e.g. various subtypes of clang::Type and various expressions.
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
+ class X {};
+ typedef X Y;
+ Y y;
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
+This can be achieved by using the hasUnqualifiedDesugaredType matcher:
+ varDecl(hasType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
@@ -5997,7 +6552,7 @@ Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrL
</pre></td></tr>
-<tr><td>Matcher&lt;T&gt;</td><td class="name" onclick="toggle('findAll0')"><a name="findAll0Anchor">findAll</a></td><td>Matcher&lt;T&gt; Matcher</td></tr>
+<tr><td>Matcher&lt;T&gt;</td><td class="name" onclick="toggle('findAll0')"><a name="findAll0Anchor">findAll</a></td><td>const Matcher&lt;T&gt; Matcher</td></tr>
<tr><td colspan="4" class="doc" id="findAll0"><pre>Matches if the node or any descendant matches.
Generates results for each match.
@@ -6013,20 +6568,22 @@ Usable as: Any Matcher
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefNameDecl.html">TypedefNameDecl</a>&gt;</td><td class="name" onclick="toggle('hasType1')"><a name="hasType1Anchor">hasType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
-<tr><td colspan="4" class="doc" id="hasType1"><pre>Matches if the expression's or declaration's type matches a type
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefNameDecl.html">TypedefNameDecl</a>&gt;</td><td class="name" onclick="toggle('hasType2')"><a name="hasType2Anchor">hasType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasType2"><pre>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"))
class X {};
void y(X &amp;x) { x; X z; }
typedef int U;
+ class Y { friend class X; };
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration1')"><a name="hasDeclaration1Anchor">hasDeclaration</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration1')"><a name="hasDeclaration1Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration1"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
@@ -6036,9 +6593,19 @@ The associated declaration is:
- 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
-Also usable as Matcher&lt;T&gt; for any T supporting the getDecl() member
-function. e.g. various subtypes of clang::Type and various expressions.
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
+ class X {};
+ typedef X Y;
+ Y y;
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
+This can be achieved by using the hasUnqualifiedDesugaredType matcher:
+ varDecl(hasType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
@@ -6057,7 +6624,7 @@ type of the matched node.
For example, in:
class A {};
using B = A;
-The matcher type(hasUniqualifeidDesugaredType(recordType())) matches
+The matcher type(hasUnqualifiedDesugaredType(recordType())) matches
both B and A.
</pre></td></tr>
@@ -6081,7 +6648,7 @@ Example matches true (matcher = hasUnaryOperand(
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration0')"><a name="hasDeclaration0Anchor">hasDeclaration</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration0')"><a name="hasDeclaration0Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration0"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
@@ -6091,9 +6658,19 @@ The associated declaration is:
- 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
-Also usable as Matcher&lt;T&gt; for any T supporting the getDecl() member
-function. e.g. various subtypes of clang::Type and various expressions.
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
+ class X {};
+ typedef X Y;
+ Y y;
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
+This can be achieved by using the hasUnqualifiedDesugaredType matcher:
+ varDecl(hasType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
@@ -6127,8 +6704,8 @@ usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(functionDecl())))
matches using X::b but not using X::a </pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>&gt;</td><td class="name" onclick="toggle('hasType4')"><a name="hasType4Anchor">hasType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
-<tr><td colspan="4" class="doc" id="hasType4"><pre>Overloaded to match the declaration of the expression's or value
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>&gt;</td><td class="name" onclick="toggle('hasType6')"><a name="hasType6Anchor">hasType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasType6"><pre>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),
@@ -6139,23 +6716,27 @@ declaration of x.
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"))
class X {};
void y(X &amp;x) { x; X z; }
+ class Y { friend class X; };
Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>&gt;</td><td class="name" onclick="toggle('hasType2')"><a name="hasType2Anchor">hasType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
-<tr><td colspan="4" class="doc" id="hasType2"><pre>Matches if the expression's or declaration's type matches a type
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>&gt;</td><td class="name" onclick="toggle('hasType3')"><a name="hasType3Anchor">hasType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasType3"><pre>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"))
class X {};
void y(X &amp;x) { x; X z; }
typedef int U;
+ class Y { friend class X; };
</pre></td></tr>
diff --git a/docs/LibASTMatchersTutorial.rst b/docs/LibASTMatchersTutorial.rst
index baf2c1c3e699..832b47efd1b8 100644
--- a/docs/LibASTMatchersTutorial.rst
+++ b/docs/LibASTMatchersTutorial.rst
@@ -146,7 +146,7 @@ documentation <LibTooling.html>`_.
static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
// A help message for this specific tool can be added afterwards.
- static cl::extrahelp MoreHelp("\nMore help text...");
+ static cl::extrahelp MoreHelp("\nMore help text...\n");
int main(int argc, const char **argv) {
CommonOptionsParser OptionsParser(argc, argv, MyToolCategory);
diff --git a/docs/LibFormat.rst b/docs/LibFormat.rst
index 086a52827d8c..2863a076edf4 100644
--- a/docs/LibFormat.rst
+++ b/docs/LibFormat.rst
@@ -44,11 +44,11 @@ two style guides are hard-coded:
.. code-block:: c++
- /// \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 Google's C++ style guide:
+ /// Returns a format style complying with Google's C++ style guide:
/// http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml.
FormatStyle getGoogleStyle();
diff --git a/docs/LibTooling.rst b/docs/LibTooling.rst
index 75ef6a0fe7ea..a422a1d5665a 100644
--- a/docs/LibTooling.rst
+++ b/docs/LibTooling.rst
@@ -130,7 +130,7 @@ version of this example tool is also checked into the clang tree at
static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
// A help message for this specific tool can be added afterwards.
- static cl::extrahelp MoreHelp("\nMore help text...");
+ static cl::extrahelp MoreHelp("\nMore help text...\n");
int main(int argc, const char **argv) {
CommonOptionsParser OptionsParser(argc, argv, MyToolCategory);
diff --git a/docs/MemorySanitizer.rst b/docs/MemorySanitizer.rst
index 5bb19ed8a509..4e033fa1941d 100644
--- a/docs/MemorySanitizer.rst
+++ b/docs/MemorySanitizer.rst
@@ -185,7 +185,11 @@ self-built instrumented libc++ (as a replacement for libstdc++).
Supported Platforms
===================
-MemorySanitizer is supported on Linux x86\_64/MIPS64/AArch64.
+MemorySanitizer is supported on the following OS:
+
+* Linux
+* NetBSD
+* FreeBSD
Limitations
===========
diff --git a/docs/Modules.rst b/docs/Modules.rst
index 2fa38be6f493..493c54d3913a 100644
--- a/docs/Modules.rst
+++ b/docs/Modules.rst
@@ -430,6 +430,21 @@ cplusplus
cplusplus11
C++11 support is available.
+cplusplus14
+ C++14 support is available.
+
+cplusplus17
+ C++17 support is available.
+
+c99
+ C99 support is available.
+
+c11
+ C11 support is available.
+
+c17
+ C17 support is available.
+
freestanding
A freestanding environment is available.
diff --git a/docs/OpenMPSupport.rst b/docs/OpenMPSupport.rst
new file mode 100644
index 000000000000..e8ec1e371b04
--- /dev/null
+++ b/docs/OpenMPSupport.rst
@@ -0,0 +1,131 @@
+.. 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
+
+.. contents::
+ :local:
+
+==================
+OpenMP Support
+==================
+
+Clang fully supports OpenMP 4.5. Clang supports offloading to X86_64, AArch64,
+PPC64[LE] and has `basic support for Cuda devices`_.
+
+Standalone directives
+=====================
+
+* #pragma omp [for] simd: :good:`Complete`.
+
+* #pragma omp declare simd: :partial:`Partial`. We support parsing/semantic
+ analysis + generation of special attributes for X86 target, but still
+ missing the LLVM pass for vectorization.
+
+* #pragma omp taskloop [simd]: :good:`Complete`.
+
+* #pragma omp target [enter|exit] data: :good:`Complete`.
+
+* #pragma omp target update: :good:`Complete`.
+
+* #pragma omp target: :good:`Complete`.
+
+* #pragma omp declare target: :good:`Complete`.
+
+* #pragma omp teams: :good:`Complete`.
+
+* #pragma omp distribute [simd]: :good:`Complete`.
+
+* #pragma omp distribute parallel for [simd]: :good:`Complete`.
+
+Combined directives
+===================
+
+* #pragma omp parallel for simd: :good:`Complete`.
+
+* #pragma omp target parallel: :good:`Complete`.
+
+* #pragma omp target parallel for [simd]: :good:`Complete`.
+
+* #pragma omp target simd: :good:`Complete`.
+
+* #pragma omp target teams: :good:`Complete`.
+
+* #pragma omp teams distribute [simd]: :good:`Complete`.
+
+* #pragma omp target teams distribute [simd]: :good:`Complete`.
+
+* #pragma omp teams distribute parallel for [simd]: :good:`Complete`.
+
+* #pragma omp target teams distribute parallel for [simd]: :good:`Complete`.
+
+Clang does not support any constructs/updates from upcoming OpenMP 5.0 except
+for `reduction`-based clauses in the `task` and `target`-based directives.
+
+In addition, the LLVM OpenMP runtime `libomp` supports the OpenMP Tools
+Interface (OMPT) on x86, x86_64, AArch64, and PPC64 on Linux, Windows, and mac OS.
+ows, and mac OS.
+
+.. _basic support for Cuda devices:
+
+Cuda devices support
+====================
+
+Directives execution modes
+--------------------------
+
+Clang code generation for target regions supports two modes: the SPMD and
+non-SPMD modes. Clang chooses one of these two modes automatically based on the
+way directives and clauses on those directives are used. The SPMD mode uses a
+simplified set of runtime functions thus increasing performance at the cost of
+supporting some OpenMP features. The non-SPMD mode is the most generic mode and
+supports all currently available OpenMP features. The compiler will always
+attempt to use the SPMD mode wherever possible. SPMD mode will not be used if:
+
+ - The target region contains an `if()` clause that refers to a `parallel`
+ directive.
+
+ - The target region contains a `parallel` directive with a `num_threads()`
+ clause.
+
+ - The target region contains user code (other than OpenMP-specific
+ directives) in between the `target` and the `parallel` directives.
+
+Data-sharing modes
+------------------
+
+Clang supports two data-sharing models for Cuda devices: `Generic` and `Cuda`
+modes. The default mode is `Generic`. `Cuda` mode can give an additional
+performance and can be activated using the `-fopenmp-cuda-mode` flag. In
+`Generic` mode all local variables that can be shared in the parallel regions
+are stored in the global memory. In `Cuda` mode local variables are not shared
+between the threads and it is user responsibility to share the required data
+between the threads in the parallel regions.
+
+Features not supported or with limited support for Cuda devices
+---------------------------------------------------------------
+
+- Reductions across the teams are not supported yet.
+
+- Cancellation constructs are not supported.
+
+- Doacross loop nest is not supported.
+
+- User-defined reductions are supported only for trivial types.
+
+- Nested parallelism: inner parallel regions are executed sequentially.
+
+- Static linking of libraries containing device code is not supported yet.
+
+- Automatic translation of math functions in target regions to device-specific
+ math functions is not implemented yet.
+
+- Debug information for OpenMP target regions is not supported yet.
+
diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst
index 8dce92341c3b..342fed3393b1 100644
--- a/docs/ReleaseNotes.rst
+++ b/docs/ReleaseNotes.rst
@@ -1,5 +1,5 @@
=======================================
-Clang 6.0.0 (In-Progress) Release Notes
+Clang 7.0.0 (In-Progress) Release Notes
=======================================
.. contents::
@@ -10,7 +10,7 @@ Written by the `LLVM Team <http://llvm.org/>`_
.. warning::
- These are in-progress notes for the upcoming Clang 6 release.
+ These are in-progress notes for the upcoming Clang 7 release.
Release notes for previous releases can be found on
`the Download Page <http://releases.llvm.org/download.html>`_.
@@ -18,7 +18,7 @@ Introduction
============
This document contains the release notes for the Clang C/C++/Objective-C
-frontend, part of the LLVM Compiler Infrastructure, release 6.0.0. Here we
+frontend, part of the LLVM Compiler Infrastructure, release 7.0.0. Here we
describe the status of Clang in some detail, including major
improvements from the previous release and new feature work. For the
general LLVM release notes, see `the LLVM
@@ -35,7 +35,7 @@ main Clang web page, this document applies to the *next* release, not
the current one. To see the release notes for a specific release, please
see the `releases page <http://llvm.org/releases/>`_.
-What's New in Clang 6.0.0?
+What's New in Clang 7.0.0?
==========================
Some of the major new features and improvements to Clang are listed
@@ -51,86 +51,81 @@ Major New Features
Improvements to Clang's diagnostics
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-- ``-Wpragma-pack`` is a new warning that warns in the following cases:
+- ``-Wc++98-compat-extra-semi`` is a new flag, which was previously inseparable
+ from ``-Wc++98-compat-pedantic``. The latter still controls the new flag.
- - When a translation unit is missing terminating ``#pragma pack (pop)``
- directives.
+- ``-Wextra-semi`` now also controls ``-Wc++98-compat-extra-semi``.
+ Please do note that if you pass ``-Wno-c++98-compat-pedantic``, it implies
+ ``-Wno-c++98-compat-extra-semi``, so if you want that diagnostic, you need
+ to explicitly re-enable it (e.g. by appending ``-Wextra-semi``).
- - When leaving an included file that changes the current alignment value,
- i.e. when the alignment before ``#include`` is different to the alignment
- after ``#include``.
-
- - ``-Wpragma-pack-suspicious-include`` (disabled by default) warns on an
- ``#include`` when the included file contains structures or unions affected by
- a non-default alignment that has been specified using a ``#pragma pack``
- directive prior to the ``#include``.
-
-- ``-Wobjc-messaging-id`` is a new, non-default warning that warns about
- message sends to unqualified ``id`` in Objective-C. This warning is useful
- for projects that would like to avoid any potential future compiler
- errors/warnings, as the system frameworks might add a method with the same
- selector which could make the message send to ``id`` ambiguous.
-
-- ``-Wtautological-compare`` now warns when comparing an unsigned integer and 0
- regardless of whether the constant is signed or unsigned."
-
-- ``-Wtautological-compare`` now warns about comparing a signed integer and 0
- when the signed integer is coerced to an unsigned type for the comparison.
- ``-Wsign-compare`` was adjusted not to warn in this case.
-
-- ``-Wtautological-constant-compare`` is a new warning that warns on
- tautological comparisons between integer variable of the type ``T`` and the
- largest/smallest possible integer constant of that same type.
-
-- For C code, ``-Wsign-compare``, ``-Wsign-conversion``,
- ``-Wtautological-constant-compare`` and
- ``-Wtautological-constant-out-of-range-compare`` were adjusted to use the
- underlying datatype of ``enum``.
-
-- ``-Wnull-pointer-arithmetic`` now warns about performing pointer arithmetic
- on a null pointer. Such pointer arithmetic has an undefined behavior if the
- offset is nonzero. It also now warns about arithmetic on a null pointer
- treated as a cast from integer to pointer (GNU extension).
-
-- ``-Wzero-as-null-pointer-constant`` was adjusted not to warn on null pointer
- constants that originate from system macros, except ``NULL`` macro.
+- ``-Wself-assign`` and ``-Wself-assign-field`` were extended to diagnose
+ self-assignment operations using overloaded operators (i.e. classes).
+ If you are doing such an assignment intentionally, e.g. in a unit test for
+ a data structure, the first warning can be disabled by passing
+ ``-Wno-self-assign-overloaded``, also the warning can be suppressed by adding
+ ``*&`` to the right-hand side or casting it to the appropriate reference type.
Non-comprehensive list of changes in this release
-------------------------------------------------
-- Bitrig OS was merged back into OpenBSD, so Bitrig support has been
- removed from Clang/LLVM.
-
-- The default value of _MSC_VER was raised from 1800 to 1911, making it
- compatible with the Visual Studio 2015 and 2017 C++ standard library headers.
- Users should generally expect this to be regularly raised to match the most
- recently released version of the Visual C++ compiler.
+- Clang binary and libraries have been renamed from 7.0 to 7.
+ For example, the ``clang`` binary will be called ``clang-7``
+ instead of ``clang-7.0``.
+
+- Clang implements a collection of recent fixes to the C++ standard's definition
+ of "standard-layout". In particular, a class is only considered to be
+ standard-layout if all base classes and the first data member (or bit-field)
+ can be laid out at offset zero.
+
+- Clang's handling of the GCC ``packed`` class attribute in C++ has been fixed
+ to apply only to non-static data members and not to base classes. This fixes
+ an ABI difference between Clang and GCC, but creates an ABI difference between
+ Clang 7 and earlier versions. The old behavior can be restored by setting
+ ``-fclang-abi-compat`` to ``6`` or earlier.
+
+- Clang implements the proposed resolution of LWG issue 2358, along with the
+ `corresponding change to the Itanium C++ ABI
+ <https://github.com/itanium-cxx-abi/cxx-abi/pull/51>`_, which make classes
+ containing only unnamed non-zero-length bit-fields be considered non-empty.
+ This is an ABI break compared to prior Clang releases, but makes Clang
+ generate code that is ABI-compatible with other compilers. The old
+ behavior can be restored by setting ``-fclang-abi-compat`` to ``6`` or
+ lower.
+
+- An existing tool named ``diagtool`` has been added to the release. As the
+ name suggests, it helps with dealing with diagnostics in ``clang``, such as
+ finding out the warning hierarchy, and which of them are enabled by default
+ or for a particular compiler invocation.
+
+- By default, Clang emits an address-significance table into
+ every ELF object file when using the integrated assembler.
+ Address-significance tables allow linkers to implement `safe ICF
+ <https://research.google.com/pubs/archive/36912.pdf>`_ without the false
+ positives that can result from other implementation techniques such as
+ relocation scanning. The ``-faddrsig`` and ``-fno-addrsig`` flags can be
+ used to control whether to emit the address-significance table.
-- clang now defaults to ``.init_array`` if no gcc installation can be found.
- If a gcc installation is found, it still prefers ``.ctors`` if the found
- gcc is older than 4.7.0.
-
-- The new builtin preprocessor macros ``__is_target_arch``,
- ``__is_target_vendor``, ``__is_target_os``, and ``__is_target_environment``
- can be used to to examine the individual components of the target triple.
+- ...
New Compiler Flags
------------------
-- --autocomplete was implemented to obtain a list of flags and its arguments. This is used for shell autocompletion.
-
-- The ``-fdouble-square-bracket-attributes`` and corresponding
- ``-fno-double-square-bracket-attributes`` flags were added to enable or
- disable [[]] attributes in any language mode. Currently, only a limited
- number of attributes are supported outside of C++ mode. See the Clang
- attribute documentation for more information about which attributes are
- supported for each syntax.
-
-- Added the ``-std=c17``, ``-std=gnu17``, and ``-std=iso9899:2017`` language
- mode flags for compatibility with GCC. This enables support for the next
- version of the C standard, expected to be published by ISO in 2018. The only
- difference between the ``-std=c17`` and ``-std=c11`` language modes is the
- value of the ``__STDC_VERSION__`` macro, as C17 is a bug fix release.
+- ``-fstrict-float-cast-overflow`` and ``-fno-strict-float-cast-overflow``.
+
+ When a floating-point value is not representable in a destination integer
+ type, the code has undefined behavior according to the language standard. By
+ default, Clang will not guarantee any particular result in that case. With the
+ 'no-strict' option, Clang attempts to match the overflowing behavior of the
+ target's native float-to-int conversion instructions.
+
+- ``-fforce-emit-vtables`` and ``-fno-force-emit-vtables``.
+
+ In order to improve devirtualization, forces emitting of vtables even in
+ modules where it isn't necessary. It causes more inline virtual functions
+ to be emitted.
+
+- ...
Deprecated Compiler Flags
-------------------------
@@ -140,35 +135,50 @@ future versions of Clang.
- ...
-New Pragmas in Clang
+Modified Compiler Flags
-----------------------
+- Before Clang 7, we prepended the `#` character to the `--autocomplete`
+ argument to enable cc1 flags. For example, when the `-cc1` or `-Xclang` flag
+ is in the :program:`clang` invocation, the shell executed
+ `clang --autocomplete=#-<flag to be completed>`. Clang 7 now requires the
+ whole invocation including all flags to be passed to the `--autocomplete` like
+ this: `clang --autocomplete=-cc1,-xc++,-fsyn`.
+
+New Pragmas in Clang
+--------------------
+
Clang now supports the ...
Attribute Changes in Clang
--------------------------
-- Clang now supports the majority of its attributes under both the GNU-style
- spelling (``__attribute((name))``) and the double square-bracket spelling
- in the ``clang`` vendor namespace (``[[clang::name]]``). Attributes whose
- syntax is specified by some other standard (such as CUDA and OpenCL
- attributes) continue to follow their respective specification.
-
-- Added the ``__has_c_attribute()`` builtin preprocessor macro which allows
- users to dynamically detect whether a double square-bracket attribute is
- supported in C mode. This attribute syntax can be enabled with the
- ``-fdouble-square-bracket-attributes`` flag.
-
-- The presence of __attribute__((availability(...))) on a declaration no longer
- implies default visibility for that declaration on macOS.
+- Clang now supports function multiversioning with attribute 'target' on ELF
+ based x86/x86-64 environments by using indirect functions. This implementation
+ has a few minor limitations over the GCC implementation for the sake of AST
+ sanity, however it is otherwise compatible with existing code using this
+ feature for GCC. Consult the documentation for the target attribute for more
+ information.
- ...
Windows Support
---------------
-Clang's support for building native Windows programs ...
+- clang-cl's support for precompiled headers has been much improved:
+
+ - When using a pch file, clang-cl now no longer redundantly emits inline
+ methods that are already stored in the obj that was built together with
+ the pch file (matching cl.exe). This speeds up builds using pch files
+ by around 30%.
+
+ - The /Ycfoo.h and /Yufoo.h flags can now be used without /FIfoo.h when
+ foo.h is instead included by an explicit `#include` directive. This means
+ Visual Studio's default stdafx.h setup now uses precompiled headers with
+ clang-cl.
+
+- ...
C Language Changes in Clang
@@ -186,10 +196,7 @@ C11 Feature Support
C++ Language Changes in Clang
-----------------------------
-- Clang's default C++ dialect is now ``gnu++14`` instead of ``gnu++98``. This
- means Clang will by default accept code using features from C++14 and
- conforming GNU extensions. Projects incompatible with C++14 can add
- ``-std=gnu++98`` to their build settings to restore the previous behaviour.
+- ...
C++1z Feature Support
^^^^^^^^^^^^^^^^^^^^^
@@ -209,12 +216,38 @@ OpenCL C Language Changes in Clang
OpenMP Support in Clang
----------------------------------
-...
+- Clang gained basic support for OpenMP 4.5 offloading for NVPTX target.
+ To compile your program for NVPTX target use the following options:
+ `-fopenmp -fopenmp-targets=nvptx64-nvidia-cuda` for 64 bit platforms or
+ `-fopenmp -fopenmp-targets=nvptx-nvidia-cuda` for 32 bit platform.
+
+- Passing options to the OpenMP device offloading toolchain can be done using
+ the `-Xopenmp-target=<triple> -opt=val` flag. In this way the `-opt=val`
+ option will be forwarded to the respective OpenMP device offloading toolchain
+ described by the triple. For example passing the compute capability to
+ the OpenMP NVPTX offloading toolchain can be done as follows:
+ `-Xopenmp-target=nvptx64-nvidia-cuda -march=sm_60`. For the case when only one
+ target offload toolchain is specified under the `-fopenmp-targets=<triples>`
+ option, then the triple can be skipped: `-Xopenmp-target -march=sm_60`.
+
+- Other bugfixes.
+
+CUDA Support in Clang
+---------------------
+
+- Clang will now try to locate the CUDA installation next to :program:`ptxas`
+ in the `PATH` environment variable. This behavior can be turned off by passing
+ the new flag `--cuda-path-ignore-env`.
+
+- Clang now supports generating object files with relocatable device code. This
+ feature needs to be enabled with `-fcuda-rdc` and my result in performance
+ penalties compared to whole program compilation. Please note that NVIDIA's
+ :program:`nvcc` must be used for linking.
Internal API Changes
--------------------
-These are major API changes that have happened since the 4.0.0 release of
+These are major API changes that have happened since the 6.0.0 release of
Clang. If upgrading an external codebase that uses Clang as a library,
this section should help get you past the largest hurdles of upgrading.
@@ -223,67 +256,16 @@ this section should help get you past the largest hurdles of upgrading.
AST Matchers
------------
-The hasDeclaration matcher now works the same for Type and QualType and only
-ever looks through one level of sugaring in a limited number of cases.
-
-There are two main patterns affected by this:
-
-- qualType(hasDeclaration(recordDecl(...))): previously, we would look through
- sugar like TypedefType to get at the underlying recordDecl; now, we need
- to explicitly remove the sugaring:
- qualType(hasUnqualifiedDesugaredType(hasDeclaration(recordDecl(...))))
-
-- hasType(recordDecl(...)): hasType internally uses hasDeclaration; previously,
- this matcher used to match for example TypedefTypes of the RecordType, but
- after the change they don't; to fix, use:
-
-::
- hasType(hasUnqualifiedDesugaredType(
- recordType(hasDeclaration(recordDecl(...)))))
-
-- templateSpecializationType(hasDeclaration(classTemplateDecl(...))):
- previously, we would directly match the underlying ClassTemplateDecl;
- now, we can explicitly match the ClassTemplateSpecializationDecl, but that
- requires to explicitly get the ClassTemplateDecl:
-
-::
- templateSpecializationType(hasDeclaration(
- classTemplateSpecializationDecl(
- hasSpecializedTemplate(classTemplateDecl(...)))))
+- ...
clang-format
------------
-* Option *IndentPPDirectives* added to indent preprocessor directives on
- conditionals.
-
- +----------------------+----------------------+
- | Before | After |
- +======================+======================+
- | .. code-block:: c++ | .. code-block:: c++ |
- | | |
- | #if FOO | #if FOO |
- | #if BAR | # if BAR |
- | #include <foo> | # include <foo> |
- | #endif | # endif |
- | #endif | #endif |
- +----------------------+----------------------+
-
-* Option -verbose added to the command line.
- Shows the list of processed files.
-
-* Option *IncludeBlocks* added to merge and regroup multiple ``#include`` blocks during sorting.
-
- +-------------------------+-------------------------+-------------------------+
- | Before (Preserve) | Merge | Regroup |
- +=========================+=========================+=========================+
- | .. code-block:: c++ | .. code-block:: c++ | .. code-block:: c++ |
- | | | |
- | #include "b.h" | #include "a.h" | #include "a.h" |
- | | #include "b.h" | #include "b.h" |
- | #include "a.b" | #include <lib/main.h> | |
- | #include <lib/main.h> | | #include <lib/main.h> |
- +-------------------------+-------------------------+-------------------------+
+- Clang-format will now support detecting and formatting code snippets in raw
+ string literals. This is configured through the `RawStringFormats` style
+ option.
+
+- ...
libclang
--------
@@ -294,18 +276,14 @@ libclang
Static Analyzer
---------------
-- Static Analyzer can now properly detect and diagnose unary pre-/post-
- increment/decrement on an uninitialized value.
+- ...
...
Undefined Behavior Sanitizer (UBSan)
------------------------------------
-* A minimal runtime is now available. It is suitable for use in production
- environments, and has a small attack surface. It only provides very basic
- issue logging and deduplication, and does not support ``-fsanitize=vptr``
- checking.
+* ...
Core Analysis Improvements
==========================
diff --git a/docs/SafeStack.rst b/docs/SafeStack.rst
index f01b75f5cb37..b046aa616898 100644
--- a/docs/SafeStack.rst
+++ b/docs/SafeStack.rst
@@ -126,7 +126,7 @@ and link command lines.
Supported Platforms
-------------------
-SafeStack was tested on Linux, FreeBSD and MacOSX.
+SafeStack was tested on Linux, NetBSD, FreeBSD and MacOSX.
Low-level API
-------------
@@ -165,11 +165,23 @@ never be stored on the heap, as it would leak the location of the SafeStack.
This builtin function returns current unsafe stack pointer of the current
thread.
+``__builtin___get_unsafe_stack_bottom()``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This builtin function returns a pointer to the bottom of the unsafe stack of the
+current thread.
+
+``__builtin___get_unsafe_stack_top()``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This builtin function returns a pointer to the top of the unsafe stack of the
+current thread.
+
``__builtin___get_unsafe_stack_start()``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-This builtin function returns a pointer to the start of the unsafe stack of the
-current thread.
+Deprecated: This builtin function is an alias for
+``__builtin___get_unsafe_stack_bottom()``.
Design
======
diff --git a/docs/SanitizerStats.rst b/docs/SanitizerStats.rst
index cff68f6b5d53..cbc3b37d31c5 100644
--- a/docs/SanitizerStats.rst
+++ b/docs/SanitizerStats.rst
@@ -56,7 +56,7 @@ Example:
10 A a;
11 g(&a);
12 }
- $ clang++ -fsanitize=cfi -flto -fuse-ld=gold vcall.cc -fsanitize-stats -g
+ $ clang++ -fsanitize=cfi -fvisibility=hidden -flto -fuse-ld=gold vcall.cc -fsanitize-stats -g
$ SANITIZER_STATS_PATH=a.stats ./a.out
$ sanstats a.stats
vcall.cc:6 _Z1gP1A cfi-vcall 1
diff --git a/docs/ShadowCallStack.rst b/docs/ShadowCallStack.rst
new file mode 100644
index 000000000000..da609dcd9de4
--- /dev/null
+++ b/docs/ShadowCallStack.rst
@@ -0,0 +1,193 @@
+===============
+ShadowCallStack
+===============
+
+.. contents::
+ :local:
+
+Introduction
+============
+
+ShadowCallStack is an **experimental** instrumentation pass, currently only
+implemented for x86_64 and aarch64, that protects programs against return
+address overwrites (e.g. stack buffer overflows.) It works by saving a
+function's return address to a separately allocated 'shadow call stack'
+in the function prolog and checking the return address on the stack against
+the shadow call stack in the function epilog.
+
+Comparison
+----------
+
+To optimize for memory consumption and cache locality, the shadow call stack
+stores an index followed by an array of return addresses. This is in contrast
+to other schemes, like :doc:`SafeStack`, that mirror the entire stack and
+trade-off consuming more memory for shorter function prologs and epilogs with
+fewer memory accesses. Similarly, `Return Flow Guard`_ consumes more memory with
+shorter function prologs and epilogs than ShadowCallStack but suffers from the
+same race conditions (see `Security`_). Intel `Control-flow Enforcement Technology`_
+(CET) is a proposed hardware extension that would add native support to
+use a shadow stack to store/check return addresses at call/return time. It
+would not suffer from race conditions at calls and returns and not incur the
+overhead of function instrumentation, but it does require operating system
+support.
+
+.. _`Return Flow Guard`: https://xlab.tencent.com/en/2016/11/02/return-flow-guard/
+.. _`Control-flow Enforcement Technology`: https://software.intel.com/sites/default/files/managed/4d/2a/control-flow-enforcement-technology-preview.pdf
+
+Compatibility
+-------------
+
+ShadowCallStack currently only supports x86_64 and aarch64. A runtime is not
+currently provided in compiler-rt so one must be provided by the compiled
+application.
+
+On aarch64, the instrumentation makes use of the platform register ``x18``.
+On some platforms, ``x18`` is reserved, and on others, it is designated as
+a scratch register. This generally means that any code that may run on the
+same thread as code compiled with ShadowCallStack must either target one
+of the platforms whose ABI reserves ``x18`` (currently Darwin, Fuchsia and
+Windows) or be compiled with the flag ``-ffixed-x18``.
+
+Security
+========
+
+ShadowCallStack is intended to be a stronger alternative to
+``-fstack-protector``. It protects from non-linear overflows and arbitrary
+memory writes to the return address slot; however, similarly to
+``-fstack-protector`` this protection suffers from race conditions because of
+the call-return semantics on x86_64. There is a short race between the call
+instruction and the first instruction in the function that reads the return
+address where an attacker could overwrite the return address and bypass
+ShadowCallStack. Similarly, there is a time-of-check-to-time-of-use race in the
+function epilog where an attacker could overwrite the return address after it
+has been checked and before it has been returned to. Modifying the call-return
+semantics to fix this on x86_64 would incur an unacceptable performance overhead
+due to return branch prediction.
+
+The instrumentation makes use of the ``gs`` segment register on x86_64,
+or the ``x18`` register on aarch64, to reference the shadow call stack
+meaning that references to the shadow call stack do not have to be stored in
+memory. This makes it possible to implement a runtime that avoids exposing
+the address of the shadow call stack to attackers that can read arbitrary
+memory. However, attackers could still try to exploit side channels exposed
+by the operating system `[1]`_ `[2]`_ or processor `[3]`_ to discover the
+address of the shadow call stack.
+
+.. _`[1]`: https://eyalitkin.wordpress.com/2017/09/01/cartography-lighting-up-the-shadows/
+.. _`[2]`: https://www.blackhat.com/docs/eu-16/materials/eu-16-Goktas-Bypassing-Clangs-SafeStack.pdf
+.. _`[3]`: https://www.vusec.net/projects/anc/
+
+On x86_64, leaf functions are optimized to store the return address in a
+free register and avoid writing to the shadow call stack if a register is
+available. Very short leaf functions are uninstrumented if their execution
+is judged to be shorter than the race condition window intrinsic to the
+instrumentation.
+
+On aarch64, the architecture's call and return instructions (``bl`` and
+``ret``) operate on a register rather than the stack, which means that
+leaf functions are generally protected from return address overwrites even
+without ShadowCallStack. It also means that ShadowCallStack on aarch64 is not
+vulnerable to the same types of time-of-check-to-time-of-use races as x86_64.
+
+Usage
+=====
+
+To enable ShadowCallStack, just pass the ``-fsanitize=shadow-call-stack``
+flag to both compile and link command lines. On aarch64, you also need to pass
+``-ffixed-x18`` unless your target already reserves ``x18``.
+
+Low-level API
+-------------
+
+``__has_feature(shadow_call_stack)``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In some cases one may need to execute different code depending on whether
+ShadowCallStack is enabled. The macro ``__has_feature(shadow_call_stack)`` can
+be used for this purpose.
+
+.. code-block:: c
+
+ #if defined(__has_feature)
+ # if __has_feature(shadow_call_stack)
+ // code that builds only under ShadowCallStack
+ # endif
+ #endif
+
+``__attribute__((no_sanitize("shadow-call-stack")))``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Use ``__attribute__((no_sanitize("shadow-call-stack")))`` on a function
+declaration to specify that the shadow call stack instrumentation should not be
+applied to that function, even if enabled globally.
+
+Example
+=======
+
+The following example code:
+
+.. code-block:: c++
+
+ int foo() {
+ return bar() + 1;
+ }
+
+Generates the following x86_64 assembly when compiled with ``-O2``:
+
+.. code-block:: gas
+
+ push %rax
+ callq bar
+ add $0x1,%eax
+ pop %rcx
+ retq
+
+or the following aarch64 assembly:
+
+.. code-block:: none
+
+ stp x29, x30, [sp, #-16]!
+ mov x29, sp
+ bl bar
+ add w0, w0, #1
+ ldp x29, x30, [sp], #16
+ ret
+
+
+Adding ``-fsanitize=shadow-call-stack`` would output the following x86_64
+assembly:
+
+.. code-block:: gas
+
+ mov (%rsp),%r10
+ xor %r11,%r11
+ addq $0x8,%gs:(%r11)
+ mov %gs:(%r11),%r11
+ mov %r10,%gs:(%r11)
+ push %rax
+ callq bar
+ add $0x1,%eax
+ pop %rcx
+ xor %r11,%r11
+ mov %gs:(%r11),%r10
+ mov %gs:(%r10),%r10
+ subq $0x8,%gs:(%r11)
+ cmp %r10,(%rsp)
+ jne trap
+ retq
+
+ trap:
+ ud2
+
+or the following aarch64 assembly:
+
+.. code-block:: none
+
+ str x30, [x18], #8
+ stp x29, x30, [sp, #-16]!
+ mov x29, sp
+ bl bar
+ add w0, w0, #1
+ ldp x29, x30, [sp], #16
+ ldr x30, [x18, #-8]!
+ ret
diff --git a/docs/ThinLTO.rst b/docs/ThinLTO.rst
index 14c098b052df..38873f464c29 100644
--- a/docs/ThinLTO.rst
+++ b/docs/ThinLTO.rst
@@ -156,7 +156,7 @@ A policy string is a series of key-value pairs separated by ``:`` characters.
Possible key-value pairs are:
- ``cache_size=X%``: The maximum size for the cache directory is ``X`` percent
- of the available space on the the disk. Set to 100 to indicate no limit,
+ of the available space on the disk. Set to 100 to indicate no limit,
50 to indicate that the cache size will not be left over half the available
disk space. A value over 100 is invalid. A value of 0 disables the percentage
size-based pruning. The default is 75%.
diff --git a/docs/ThreadSanitizer.rst b/docs/ThreadSanitizer.rst
index cfbaa63d6432..d1e2c65ec5f1 100644
--- a/docs/ThreadSanitizer.rst
+++ b/docs/ThreadSanitizer.rst
@@ -17,7 +17,12 @@ Build LLVM/Clang with `CMake <http://llvm.org/docs/CMake.html>`_.
Supported Platforms
-------------------
-ThreadSanitizer is supported on Linux x86_64 (tested on Ubuntu 12.04).
+ThreadSanitizer is supported on the following OS:
+
+* Linux
+* NetBSD
+* FreeBSD
+
Support for other 64-bit architectures is possible, contributions are welcome.
Support for 32-bit platforms is problematic and is not planned.
diff --git a/docs/Toolchain.rst b/docs/Toolchain.rst
index e727ccdc7c1a..06bde35c3da6 100644
--- a/docs/Toolchain.rst
+++ b/docs/Toolchain.rst
@@ -106,7 +106,7 @@ Assember
Clang can either use LLVM's integrated assembler or an external system-specific
tool (for instance, the GNU Assembler on GNU OSes) to produce machine code from
assembly.
-By default, Clang uses LLVM's integrataed assembler on all targets where it is
+By default, Clang uses LLVM's integrated assembler on all targets where it is
supported. If you wish to use the system assember instead, use the
``-fno-integrated-as`` option.
diff --git a/docs/UndefinedBehaviorSanitizer.rst b/docs/UndefinedBehaviorSanitizer.rst
index e9f85c24dde0..71a8ebd4bc64 100644
--- a/docs/UndefinedBehaviorSanitizer.rst
+++ b/docs/UndefinedBehaviorSanitizer.rst
@@ -180,6 +180,13 @@ will need to:
``UBSAN_OPTIONS=print_stacktrace=1``.
#. Make sure ``llvm-symbolizer`` binary is in ``PATH``.
+Silencing Unsigned Integer Overflow
+===================================
+To silence reports from unsigned integer overflow, you can set
+``UBSAN_OPTIONS=silence_unsigned_overflow=1``. This feature, combined with
+``-fsanitize-recover=unsigned-integer-overflow``, is particularly useful for
+providing fuzzing signal without blowing up logs.
+
Issue Suppression
=================
@@ -245,17 +252,11 @@ UndefinedBehaviorSanitizer is supported on the following OS:
* Android
* Linux
+* NetBSD
* FreeBSD
+* OpenBSD
* OS X 10.6 onwards
-and for the following architectures:
-
-* i386/x86\_64
-* ARM
-* AArch64
-* PowerPC64
-* MIPS/MIPS64
-
Current Status
==============
diff --git a/docs/UsersManual.rst b/docs/UsersManual.rst
index 023f9f5528ba..418afb2d546c 100644
--- a/docs/UsersManual.rst
+++ b/docs/UsersManual.rst
@@ -694,6 +694,79 @@ a special character, which is the convention used by GNU Make. The -MV
option tells Clang to put double-quotes around the entire filename, which
is the convention used by NMake and Jom.
+Configuration files
+-------------------
+
+Configuration files group command-line options and allow all of them to be
+specified just by referencing the configuration file. They may be used, for
+example, to collect options required to tune compilation for particular
+target, such as -L, -I, -l, --sysroot, codegen options, etc.
+
+The command line option `--config` can be used to specify configuration
+file in a Clang invocation. For example:
+
+::
+
+ clang --config /home/user/cfgs/testing.txt
+ clang --config debug.cfg
+
+If the provided argument contains a directory separator, it is considered as
+a file path, and options are read from that file. Otherwise the argument is
+treated as a file name and is searched for sequentially in the directories:
+
+ - user directory,
+ - system directory,
+ - the directory where Clang executable resides.
+
+Both user and system directories for configuration files are specified during
+clang build using CMake parameters, CLANG_CONFIG_FILE_USER_DIR and
+CLANG_CONFIG_FILE_SYSTEM_DIR respectively. The first file found is used. It is
+an error if the required file cannot be found.
+
+Another way to specify a configuration file is to encode it in executable name.
+For example, if the Clang executable is named `armv7l-clang` (it may be a
+symbolic link to `clang`), then Clang will search for file `armv7l.cfg` in the
+directory where Clang resides.
+
+If a driver mode is specified in invocation, Clang tries to find a file specific
+for the specified mode. For example, if the executable file is named
+`x86_64-clang-cl`, Clang first looks for `x86_64-cl.cfg` and if it is not found,
+looks for `x86_64.cfg`.
+
+If the command line contains options that effectively change target architecture
+(these are -m32, -EL, and some others) and the configuration file starts with an
+architecture name, Clang tries to load the configuration file for the effective
+architecture. For example, invocation:
+
+::
+
+ x86_64-clang -m32 abc.c
+
+causes Clang search for a file `i368.cfg` first, and if no such file is found,
+Clang looks for the file `x86_64.cfg`.
+
+The configuration file consists of command-line options specified on one or
+more lines. Lines composed of whitespace characters only are ignored as well as
+lines in which the first non-blank character is `#`. Long options may be split
+between several lines by a trailing backslash. Here is example of a
+configuration file:
+
+::
+
+ # Several options on line
+ -c --target=x86_64-unknown-linux-gnu
+
+ # Long option split between lines
+ -I/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../\
+ include/c++/5.4.0
+
+ # other config files may be included
+ @linux.options
+
+Files included by `@file` directives in configuration files are resolved
+relative to the including file. For example, if a configuration file
+`~/.llvm/target.cfg` contains the directive `@os/linux.opts`, the file
+`linux.opts` is searched for in the directory `~/.llvm/os`.
Language and Target-Independent Features
========================================
@@ -1002,7 +1075,7 @@ location.
Building a relocatable precompiled header requires two additional
arguments. First, pass the ``--relocatable-pch`` flag to indicate that
the resulting PCH file should be relocatable. Second, pass
-`-isysroot /path/to/build`, which makes all includes for your library
+``-isysroot /path/to/build``, which makes all includes for your library
relative to the build directory. For example:
.. code-block:: console
@@ -1012,9 +1085,9 @@ relative to the build directory. For example:
When loading the relocatable PCH file, the various headers used in the
PCH file are found from the system header root. For example, ``mylib.h``
can be found in ``/usr/include/mylib.h``. If the headers are installed
-in some other system root, the `-isysroot` option can be used provide
+in some other system root, the ``-isysroot`` option can be used provide
a different system root from which the headers will be based. For
-example, `-isysroot /Developer/SDKs/MacOSX10.4u.sdk` will look for
+example, ``-isysroot /Developer/SDKs/MacOSX10.4u.sdk`` will look for
``mylib.h`` in ``/Developer/SDKs/MacOSX10.4u.sdk/usr/include/mylib.h``.
Relocatable precompiled headers are intended to be used in a limited
@@ -1182,12 +1255,26 @@ are listed below.
flushed-to-zero number is preserved in the sign of 0, denormals are
flushed to positive zero, respectively.
+.. option:: -f[no-]strict-float-cast-overflow
+
+ When a floating-point value is not representable in a destination integer
+ type, the code has undefined behavior according to the language standard.
+ By default, Clang will not guarantee any particular result in that case.
+ With the 'no-strict' option, Clang attempts to match the overflowing behavior
+ of the target's native float-to-int conversion instructions.
+
.. option:: -fwhole-program-vtables
Enable whole-program vtable optimizations, such as single-implementation
devirtualization and virtual constant propagation, for classes with
:doc:`hidden LTO visibility <LTOVisibility>`. Requires ``-flto``.
+.. option:: -fforce-emit-vtables
+
+ In order to improve devirtualization, forces emitting of vtables even in
+ modules where it isn't necessary. It causes more inline virtual functions
+ to be emitted.
+
.. option:: -fno-assume-sane-operator-new
Don't assume that the C++'s new operator is sane.
@@ -1295,6 +1382,15 @@ are listed below.
// value of -fmax-type-align.
}
+.. option:: -faddrsig, -fno-addrsig
+
+ Controls whether Clang emits an address-significance table into the object
+ file. Address-significance tables allow linkers to implement `safe ICF
+ <https://research.google.com/pubs/archive/36912.pdf>`_ without the false
+ positives that can result from other implementation techniques such as
+ relocation scanning. Address-significance tables are enabled by default
+ on ELF targets when using the integrated assembler. This flag currently
+ only has an effect on ELF targets.
Profile Guided Optimization
---------------------------
@@ -1302,7 +1398,8 @@ Profile Guided Optimization
Profile information enables better optimization. For example, knowing that a
branch is taken very frequently helps the compiler make better decisions when
ordering basic blocks. Knowing that a function ``foo`` is called more
-frequently than another function ``bar`` helps the inliner.
+frequently than another function ``bar`` helps the inliner. Optimization
+levels ``-O2`` and above are recommended for use of profile guided optimization.
Clang supports profile guided optimization with two different kinds of
profiling. A sampling profiler can generate a profile with very low runtime
@@ -1653,11 +1750,11 @@ profile creation and use.
.. option:: -fprofile-generate[=<dirname>]
The ``-fprofile-generate`` and ``-fprofile-generate=`` flags will use
- an alterantive instrumentation method for profile generation. When
+ an alternative instrumentation method for profile generation. When
given a directory name, it generates the profile file
``default_%m.profraw`` in the directory named ``dirname`` if specified.
If ``dirname`` does not exist, it will be created at runtime. ``%m`` specifier
- will be substibuted with a unique id documented in step 2 above. In other words,
+ will be substituted with a unique id documented in step 2 above. In other words,
with ``-fprofile-generate[=<dirname>]`` option, the "raw" profile data automatic
merging is turned on by default, so there will no longer any risk of profile
clobbering from different running processes. For example,
@@ -1781,6 +1878,27 @@ features. You can "tune" the debug info for one of several different debuggers.
must come first.)
+Controlling LLVM IR Output
+--------------------------
+
+Controlling Value Names in LLVM IR
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Emitting value names in LLVM IR increases the size and verbosity of the IR.
+By default, value names are only emitted in assertion-enabled builds of Clang.
+However, when reading IR it can be useful to re-enable the emission of value
+names to improve readability.
+
+.. option:: -fdiscard-value-names
+
+ Discard value names when generating LLVM IR.
+
+.. option:: -fno-discard-value-names
+
+ Do not discard value names when generating LLVM IR. This option can be used
+ to re-enable names for release builds of Clang.
+
+
Comment Parsing Options
-----------------------
@@ -1836,8 +1954,8 @@ Differences between various standard modes
------------------------------------------
clang supports the -std option, which changes what language mode clang
-uses. The supported modes for C are c89, gnu89, c94, c99, gnu99, c11,
-gnu11, and various aliases for those modes. If no -std option is
+uses. The supported modes for C are c89, gnu89, c99, gnu99, c11, gnu11,
+c17, gnu17, and various aliases for those modes. If no -std option is
specified, clang defaults to gnu11 mode. Many C99 and C11 features are
supported in earlier modes as a conforming extension, with a warning. Use
``-pedantic-errors`` to request an error if a feature from a later standard
@@ -1884,8 +2002,9 @@ Differences between ``*99`` and ``*11`` modes:
- Warnings for use of C11 features are disabled.
- ``__STDC_VERSION__`` is defined to ``201112L`` rather than ``199901L``.
-c94 mode is identical to c89 mode except that digraphs are enabled in
-c94 mode (FIXME: And ``__STDC_VERSION__`` should be defined!).
+Differences between ``*11`` and ``*17`` modes:
+
+- ``__STDC_VERSION__`` is defined to ``201710L`` rather than ``201112L``.
GCC extensions not implemented yet
----------------------------------
@@ -2006,10 +2125,15 @@ Controlling implementation limits
Sets the limit for recursive constexpr function invocations to N. The
default is 512.
+.. option:: -fconstexpr-steps=N
+
+ Sets the limit for the number of full-expressions evaluated in a single
+ constant expression evaluation. The default is 1048576.
+
.. option:: -ftemplate-depth=N
Sets the limit for recursively nested template instantiations to N. The
- default is 256.
+ default is 1024.
.. option:: -foperator-arrow-depth=N
@@ -2042,6 +2166,11 @@ directives, and ``#pragma omp taskgroup`` directive.
Use `-fopenmp` to enable OpenMP. Support for OpenMP can be disabled with
`-fno-openmp`.
+Use `-fopenmp-simd` to enable OpenMP simd features only, without linking
+the runtime library; for combined constructs
+(e.g. ``#pragma omp parallel for simd``) the non-simd directives and clauses
+will be ignored. This can be disabled with `-fno-openmp-simd`.
+
Controlling implementation limits
---------------------------------
@@ -2079,7 +2208,7 @@ to the target, for example:
.. code-block:: console
$ clang -target nvptx64-unknown-unknown test.cl
- $ clang -target amdgcn-amd-amdhsa-opencl test.cl
+ $ clang -target amdgcn-amd-amdhsa -mcpu=gfx900 test.cl
Compiling to bitcode can be done as follows:
@@ -2187,7 +2316,7 @@ There is a set of concrete HW architectures that OpenCL can be compiled for.
.. code-block:: console
- $ clang -target amdgcn-amd-amdhsa-opencl test.cl
+ $ clang -target amdgcn-amd-amdhsa -mcpu=gfx900 test.cl
- For Nvidia architectures:
@@ -2584,10 +2713,37 @@ compatibility with the Visual C++ compiler, cl.exe.
To enable clang-cl to find system headers, libraries, and the linker when run
from the command-line, it should be executed inside a Visual Studio Native Tools
Command Prompt or a regular Command Prompt where the environment has been set
-up using e.g. `vcvars32.bat <http://msdn.microsoft.com/en-us/library/f2ccy3wt.aspx>`_.
+up using e.g. `vcvarsall.bat <http://msdn.microsoft.com/en-us/library/f2ccy3wt.aspx>`_.
+
+clang-cl can also be used from inside Visual Studio by selecting the LLVM
+Platform Toolset. The toolset is installed by the LLVM installer, which can be
+downloaded from the `LLVM release <http://releases.llvm.org/download.html>`_ or
+`snapshot build <http://llvm.org/builds/>`_ web pages. To use the toolset,
+select a project in Solution Explorer, open its Property Page (Alt+F7), and in
+the "General" section of "Configuration Properties" change "Platform Toolset"
+to e.g. LLVM-vs2014.
+
+To use the toolset with MSBuild directly, invoke it with e.g.
+``/p:PlatformToolset=LLVM-vs2014``. This allows trying out the clang-cl
+toolchain without modifying your project files.
+
+It's also possible to point MSBuild at clang-cl without changing toolset by
+passing ``/p:CLToolPath=c:\llvm\bin /p:CLToolExe=clang-cl.exe``.
+
+When using CMake and the Visual Studio generators, the toolset can be set with the ``-T`` flag:
+
+ ::
+
+ cmake -G"Visual Studio 15 2017" -T LLVM-vs2014 ..
+
+When using CMake with the Ninja generator, set the ``CMAKE_C_COMPILER`` and
+``CMAKE_CXX_COMPILER`` variables to clang-cl:
+
+ ::
+
+ cmake -GNinja -DCMAKE_C_COMPILER="c:/Program Files (x86)/LLVM/bin/clang-cl.exe"
+ -DCMAKE_CXX_COMPILER="c:/Program Files (x86)/LLVM/bin/clang-cl.exe" ..
-clang-cl can also be used from inside Visual Studio by using an LLVM Platform
-Toolset.
Command-Line Options
--------------------
@@ -2654,6 +2810,7 @@ Execute ``clang-cl /?`` to see a list of supported options:
/Gd Set __cdecl as a default calling convention
/GF- Disable string pooling
/GR- Disable emission of RTTI data
+ /Gregcall Set __regcall as a default calling convention
/GR Enable emission of RTTI data
/Gr Set __fastcall as a default calling convention
/GS- Disable buffer security check
@@ -2662,7 +2819,7 @@ Execute ``clang-cl /?`` to see a list of supported options:
/Gv Set __vectorcall as a default calling convention
/Gw- Don't put each data item in its own section
/Gw Put each data item in its own section
- /GX- Enable exception handling
+ /GX- Disable exception handling
/GX Enable exception handling
/Gy- Don't put each function in its own section
/Gy Put each function in its own section
@@ -2710,7 +2867,7 @@ Execute ``clang-cl /?`` to see a list of supported options:
/W2 Enable -Wall
/W3 Enable -Wall
/W4 Enable -Wall and -Wextra
- /Wall Enable -Wall and -Wextra
+ /Wall Enable -Weverything
/WX- Do not treat warnings as errors
/WX Treat warnings as errors
/w Disable all warnings
@@ -2767,6 +2924,8 @@ Execute ``clang-cl /?`` to see a list of supported options:
Disable specified features of coverage instrumentation for Sanitizers
-fno-sanitize-memory-track-origins
Disable origins tracking in MemorySanitizer
+ -fno-sanitize-memory-use-after-dtor
+ Disable use-after-destroy detection in MemorySanitizer
-fno-sanitize-recover=<value>
Disable recovery for specified sanitizers
-fno-sanitize-stats Disable sanitizer statistics gathering.
@@ -2797,6 +2956,8 @@ Execute ``clang-cl /?`` to see a list of supported options:
Path to blacklist file for sanitizers
-fsanitize-cfi-cross-dso
Enable control flow integrity (CFI) checks for cross-DSO calls.
+ -fsanitize-cfi-icall-generalize-pointers
+ Generalize pointers in CFI indirect call type signature checks
-fsanitize-coverage=<value>
Specify the type of coverage instrumentation for Sanitizers
-fsanitize-memory-track-origins=<value>
@@ -2820,6 +2981,7 @@ Execute ``clang-cl /?`` to see a list of supported options:
-fsanitize=<check> Turn on runtime checks for various forms of undefined or suspicious
behavior. See user manual for available checks
-fstandalone-debug Emit full debug info for all types used by the program
+ -fwhole-program-vtables Enables whole-program vtable optimization. Requires -flto
-gcodeview Generate CodeView debug information
-gline-tables-only Emit debug line number tables only
-miamcu Use Intel MCU ABI
@@ -2828,6 +2990,7 @@ Execute ``clang-cl /?`` to see a list of supported options:
-Qunused-arguments Don't emit warning for unused driver arguments
-R<remark> Enable the specified remark
--target=<value> Generate code for the given target
+ --version Print version information
-v Show commands to run and use verbose output
-W<warning> Enable the specified warning
-Xclang <arg> Pass <arg> to the clang compiler
diff --git a/docs/analyzer/DesignDiscussions/InitializerLists.rst b/docs/analyzer/DesignDiscussions/InitializerLists.rst
index b826547bf12c..af41e4ec8f0a 100644
--- a/docs/analyzer/DesignDiscussions/InitializerLists.rst
+++ b/docs/analyzer/DesignDiscussions/InitializerLists.rst
@@ -21,7 +21,7 @@ This fix is overly conservative though. So i did a bit of investigation as to
how model std::initializer_list better.
According to the standard, std::initializer_list<T> is an object that has
-methods begin(), end(), and size(), where begin() returns a pointer to continous
+methods begin(), end(), and size(), where begin() returns a pointer to continuous
array of size() objects of type T, and end() is equal to begin() plus size().
The standard does hint that it should be possible to implement
std::initializer_list<T> as a pair of pointers, or as a pointer and a size
diff --git a/docs/conf.py b/docs/conf.py
index a12f99ad6d9a..b38c93af23c2 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -49,9 +49,9 @@ copyright = u'2007-%d, The Clang Team' % date.today().year
# built documents.
#
# The short version.
-version = '6'
+version = '7'
# The full version, including alpha/beta/rc tags.
-release = '6'
+release = '7'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff --git a/docs/doxygen.cfg.in b/docs/doxygen.cfg.in
index 13ed72222bea..61f9120017f1 100644
--- a/docs/doxygen.cfg.in
+++ b/docs/doxygen.cfg.in
@@ -174,7 +174,7 @@ JAVADOC_AUTOBRIEF = YES
# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
# line (until the first dot) of a Qt-style comment as the brief description. If
# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
-# requiring an explicit \brief command for a brief description.)
+# requiring an explicit command for a brief description.)
# The default value is: NO.
QT_AUTOBRIEF = YES
@@ -284,7 +284,7 @@ MARKDOWN_SUPPORT = YES
# When enabled doxygen tries to link words that correspond to documented
# classes, or namespaces to their corresponding documentation. Such a link can
-# be prevented in individual cases by by putting a % sign in front of the word
+# be prevented in individual cases by putting a % sign in front of the word
# or globally by setting AUTOLINK_SUPPORT to NO.
# The default value is: YES.
@@ -1065,7 +1065,7 @@ HTML_STYLESHEET =
# defined cascading style sheet that is included after the standard style sheets
# created by doxygen. Using this option one can overrule certain style aspects.
# This is preferred over using HTML_STYLESHEET since it does not replace the
-# standard style sheet and is therefor more robust against future updates.
+# standard style sheet and is therefore more robust against future updates.
# Doxygen will copy the style sheet file to the output directory. For an example
# see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
diff --git a/docs/index.rst b/docs/index.rst
index 342ab74d2d80..be7a371cd711 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -36,9 +36,11 @@ Using Clang as a Compiler
ControlFlowIntegrity
LTOVisibility
SafeStack
+ ShadowCallStack
SourceBasedCodeCoverage
Modules
MSVCCompatibility
+ OpenMPSupport
ThinLTO
CommandGuide/index
FAQ
diff --git a/docs/tools/dump_ast_matchers.py b/docs/tools/dump_ast_matchers.py
index 45540405de97..d38977548fd9 100644
--- a/docs/tools/dump_ast_matchers.py
+++ b/docs/tools/dump_ast_matchers.py
@@ -95,7 +95,7 @@ def strip_doxygen(comment):
def unify_arguments(args):
"""Gets rid of anything the user doesn't care about in the argument list."""
args = re.sub(r'internal::', r'', args)
- args = re.sub(r'const\s+(.*)&', r'\1 ', args)
+ args = re.sub(r'extern const\s+(.*)&', r'\1 ', args)
args = re.sub(r'&', r' ', args)
args = re.sub(r'(^|\s)M\d?(\s)', r'\1Matcher<*>\2', args)
return args
@@ -150,11 +150,11 @@ def act_on_decl(declaration, comment, allowed_types):
comment, is_dyncast=True)
return
- # Parse the various matcher definition macros.
- m = re.match(""".*AST_TYPE_MATCHER\(
- \s*([^\s,]+\s*),
- \s*([^\s,]+\s*)
- \)\s*;\s*$""", declaration, flags=re.X)
+ # Special case of type matchers:
+ # AstTypeMatcher<ArgumentType> name
+ m = re.match(r""".*AstTypeMatcher\s*<
+ \s*([^\s>]+)\s*>
+ \s*([^\s;]+)\s*;\s*$""", declaration, flags=re.X)
if m:
inner, name = m.groups()
add_matcher('Type', name, 'Matcher<%s>...' % inner,
@@ -165,7 +165,8 @@ def act_on_decl(declaration, comment, allowed_types):
# comment, is_dyncast=True)
return
- m = re.match(""".*AST_TYPE(LOC)?_TRAVERSE_MATCHER\(
+ # Parse the various matcher definition macros.
+ m = re.match(""".*AST_TYPE(LOC)?_TRAVERSE_MATCHER(?:_DECL)?\(
\s*([^\s,]+\s*),
\s*(?:[^\s,]+\s*),
\s*AST_POLYMORPHIC_SUPPORTED_TYPES\(([^)]*)\)
@@ -236,7 +237,7 @@ def act_on_decl(declaration, comment, allowed_types):
(?:,\s*([^\s,]+)\s*
,\s*([^\s,]+)\s*)?
(?:,\s*\d+\s*)?
- \)\s*{\s*$""", declaration, flags=re.X)
+ \)\s*{""", declaration, flags=re.X)
if m:
p, n, result, name = m.groups()[0:4]
args = m.groups()[4:]
@@ -256,8 +257,8 @@ def act_on_decl(declaration, comment, allowed_types):
# Parse ArgumentAdapting matchers.
m = re.match(
- r"""^.*ArgumentAdaptingMatcherFunc<.*>\s*(?:LLVM_ATTRIBUTE_UNUSED\s*)
- ([a-zA-Z]*)\s*=\s*{};$""",
+ r"""^.*ArgumentAdaptingMatcherFunc<.*>\s*
+ ([a-zA-Z]*);$""",
declaration, flags=re.X)
if m:
name = m.groups()[0]
@@ -267,7 +268,7 @@ def act_on_decl(declaration, comment, allowed_types):
# Parse Variadic functions.
m = re.match(
r"""^.*internal::VariadicFunction\s*<\s*([^,]+),\s*([^,]+),\s*[^>]+>\s*
- ([a-zA-Z]*)\s*=\s*{.*};$""",
+ ([a-zA-Z]*);$""",
declaration, flags=re.X)
if m:
result, arg, name = m.groups()[:3]
@@ -276,15 +277,15 @@ def act_on_decl(declaration, comment, allowed_types):
# Parse Variadic operator matchers.
m = re.match(
- r"""^.*VariadicOperatorMatcherFunc\s*<\s*([^,]+),\s*([^\s>]+)\s*>\s*
- ([a-zA-Z]*)\s*=\s*{.*};$""",
+ r"""^.*VariadicOperatorMatcherFunc\s*<\s*([^,]+),\s*([^\s]+)\s*>\s*
+ ([a-zA-Z]*);$""",
declaration, flags=re.X)
if m:
min_args, max_args, name = m.groups()[:3]
if max_args == '1':
add_matcher('*', name, 'Matcher<*>', comment)
return
- elif max_args == 'UINT_MAX':
+ elif max_args == 'std::numeric_limits<unsigned>::max()':
add_matcher('*', name, 'Matcher<*>, ..., Matcher<*>', comment)
return
diff --git a/docs/tools/dump_format_style.py b/docs/tools/dump_format_style.py
index 1ca050e062b7..3d61227f7361 100644
--- a/docs/tools/dump_format_style.py
+++ b/docs/tools/dump_format_style.py
@@ -10,6 +10,7 @@ import urllib2
CLANG_DIR = os.path.join(os.path.dirname(__file__), '../..')
FORMAT_STYLE_FILE = os.path.join(CLANG_DIR, 'include/clang/Format/Format.h')
+INCLUDE_STYLE_FILE = os.path.join(CLANG_DIR, 'include/clang/Tooling/Inclusions/IncludeStyle.h')
DOC_FILE = os.path.join(CLANG_DIR, 'docs/ClangFormatStyleOptions.rst')
@@ -115,7 +116,7 @@ def read_options(header):
for line in header:
line = line.strip()
if state == State.BeforeStruct:
- if line == 'struct FormatStyle {':
+ if line == 'struct FormatStyle {' or line == 'struct IncludeStyle {':
state = State.InStruct
elif state == State.InStruct:
if line.startswith('///'):
@@ -188,6 +189,7 @@ def read_options(header):
return options
options = read_options(open(FORMAT_STYLE_FILE))
+options += read_options(open(INCLUDE_STYLE_FILE))
options = sorted(options, key=lambda x: x.name)
options_text = '\n\n'.join(map(str, options))
diff --git a/examples/PrintFunctionNames/CMakeLists.txt b/examples/PrintFunctionNames/CMakeLists.txt
index f5f818866ca6..e582b2c45a86 100644
--- a/examples/PrintFunctionNames/CMakeLists.txt
+++ b/examples/PrintFunctionNames/CMakeLists.txt
@@ -1,7 +1,7 @@
# If we don't need RTTI or EH, there's no reason to export anything
# from the plugin.
if( NOT MSVC ) # MSVC mangles symbols differently, and
- # PrintFunctionNames.export contains C++ symbols.
+ # PrintFunctionNames.export contains C++ symbols.
if( NOT LLVM_REQUIRES_RTTI )
if( NOT LLVM_REQUIRES_EH )
set(LLVM_EXPORTED_SYMBOL_FILE ${CMAKE_CURRENT_SOURCE_DIR}/PrintFunctionNames.exports)
diff --git a/examples/analyzer-plugin/MainCallChecker.cpp b/examples/analyzer-plugin/MainCallChecker.cpp
index 7f08760e3d4c..74fe663e981f 100644
--- a/examples/analyzer-plugin/MainCallChecker.cpp
+++ b/examples/analyzer-plugin/MainCallChecker.cpp
@@ -16,10 +16,8 @@ public:
} // end anonymous namespace
void MainCallChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const {
- const ProgramStateRef state = C.getState();
- const LocationContext *LC = C.getLocationContext();
const Expr *Callee = CE->getCallee();
- const FunctionDecl *FD = state->getSVal(Callee, LC).getAsFunctionDecl();
+ const FunctionDecl *FD = C.getSVal(Callee).getAsFunctionDecl();
if (!FD)
return;
diff --git a/examples/clang-interpreter/CMakeLists.txt b/examples/clang-interpreter/CMakeLists.txt
index 308423884480..7b9657ec1abf 100644
--- a/examples/clang-interpreter/CMakeLists.txt
+++ b/examples/clang-interpreter/CMakeLists.txt
@@ -3,7 +3,10 @@ set(LLVM_LINK_COMPONENTS
ExecutionEngine
MC
MCJIT
+ Object
+ OrcJit
Option
+ RuntimeDyld
Support
native
)
@@ -23,3 +26,67 @@ target_link_libraries(clang-interpreter
clangDriver
clangFrontend
)
+
+export_executable_symbols(clang-interpreter)
+
+if (MSVC)
+ # Is this a CMake bug that even with export_executable_symbols, Windows
+ # needs to explictly export the type_info vtable
+ set_property(TARGET clang-interpreter
+ APPEND_STRING PROPERTY LINK_FLAGS " /EXPORT:??_7type_info@@6B@")
+endif()
+
+function(clang_enable_exceptions TARGET)
+ # Really have to jump through hoops to enable exception handling independent
+ # of how LLVM is being built.
+ if (NOT LLVM_REQUIRES_EH AND NOT LLVM_REQUIRES_RTTI)
+ if (MSVC)
+ # /EHs to allow throwing from extern "C"
+ set(excptnExceptions_ON "/D _HAS_EXCEPTIONS=1 /EHs /wd4714")
+ set(excptnExceptions_OFF "/D _HAS_EXCEPTIONS=0 /EHs-c-")
+ set(excptnRTTI_ON "/GR")
+ set(excptnRTTI_OFF "/GR-")
+ set(excptnEHRTTIRegEx "(/EHs(-c-?)|_HAS_EXCEPTIONS=(0|1))")
+ else()
+ set(excptnExceptions_ON "-fexceptions")
+ set(excptnExceptions_OFF "-fno-exceptions")
+ set(excptnRTTI_ON "-frtti")
+ set(excptnRTTI_OFF "-fno-rtti")
+ set(excptnEHRTTIRegEx "-f(exceptions|no-exceptions)")
+ endif()
+ if (LLVM_REQUIRES_EH)
+ set(excptnExceptions_DFLT ${excptnExceptions_ON})
+ else()
+ set(excptnExceptions_DFLT ${excptnExceptions_OFF})
+ endif()
+ if (LLVM_REQUIRES_RTTI)
+ set(excptnRTTI_DFLT ${excptnRTTI_ON})
+ else()
+ set(excptnRTTI_DFLT ${excptnRTTI_OFF})
+ endif()
+
+ # Strip the exception & rtti flags from the target
+ get_property(addedFlags TARGET ${TARGET} PROPERTY COMPILE_FLAGS)
+ string(REGEX REPLACE ${excptnEHRTTIRegEx} "" editedFlags "${addedFlags}")
+ string(REPLACE ${excptnRTTI_OFF} "" editedFlags "${editedFlags}")
+ set_property(TARGET ${TARGET} PROPERTY COMPILE_FLAGS "${editedFlags}")
+
+ get_property(addedFlags TARGET ${TARGET} PROPERTY COMPILE_DEFINITIONS)
+ string(REGEX REPLACE ${excptnEHRTTIRegEx} "" editedFlags "${addedFlags}")
+ string(REPLACE ${excptnRTTI_OFF} "" editedFlags "${editedFlags}")
+ set_property(TARGET ${TARGET} PROPERTY COMPILE_DEFINITIONS "${editedFlags}")
+
+ # Re-add the exception & rtti flags from LLVM
+ set_property(SOURCE main.cpp APPEND_STRING PROPERTY COMPILE_FLAGS
+ " ${excptnExceptions_DFLT} ${excptnRTTI_DFLT} ")
+ set_property(SOURCE Manager.cpp APPEND_STRING PROPERTY COMPILE_FLAGS
+ " ${excptnExceptions_DFLT} ${excptnRTTI_DFLT} ")
+
+ # Invoke with exceptions & rtti
+ set_property(SOURCE Invoke.cpp APPEND_STRING PROPERTY COMPILE_FLAGS
+ " ${excptnExceptions_ON} ${excptnRTTI_ON} ")
+
+ endif()
+endfunction(clang_enable_exceptions)
+
+clang_enable_exceptions(clang-interpreter)
diff --git a/examples/clang-interpreter/README.txt b/examples/clang-interpreter/README.txt
index 7dd45fad5048..b4f8a935cef8 100644
--- a/examples/clang-interpreter/README.txt
+++ b/examples/clang-interpreter/README.txt
@@ -1,4 +1,4 @@
-This is an example of Clang based interpreter, for executing standalone C
+This is an example of Clang based interpreter, for executing standalone C/C++
programs.
It demonstrates the following features:
@@ -12,6 +12,9 @@ It demonstrates the following features:
4. Use the LLVM JIT functionality to execute the final module.
+ 5. Intercepting a Win64 library call to allow throwing and catching exceptions
+ in and from the JIT.
+
The implementation has many limitations and is not designed to be a full fledged
-C interpreter. It is designed to demonstrate a simple but functional use of the
+interpreter. It is designed to demonstrate a simple but functional use of the
Clang compiler libraries.
diff --git a/examples/clang-interpreter/Test.cxx b/examples/clang-interpreter/Test.cxx
new file mode 100644
index 000000000000..d2cbb0baac5c
--- /dev/null
+++ b/examples/clang-interpreter/Test.cxx
@@ -0,0 +1,34 @@
+//===-- examples/clang-interpreter/Test.cxx - Clang C Interpreter Example -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// Example throwing in and from the JIT (particularly on Win64).
+//
+// ./bin/clang-interpreter <src>/tools/clang/examples/clang-interpreter/Test.cxx
+
+#include <stdexcept>
+#include <stdio.h>
+
+static void ThrowerAnError(const char* Name) {
+ throw std::runtime_error(Name);
+}
+
+int main(int argc, const char** argv) {
+ for (int I = 0; I < argc; ++I)
+ printf("arg[%d]='%s'\n", I, argv[I]);
+
+ try {
+ ThrowerAnError("In JIT");
+ } catch (const std::exception& E) {
+ printf("Caught: '%s'\n", E.what());
+ } catch (...) {
+ printf("Unknown exception\n");
+ }
+ ThrowerAnError("From JIT");
+ return 0;
+}
diff --git a/examples/clang-interpreter/main.cpp b/examples/clang-interpreter/main.cpp
index f7832291f2b6..3f87be29a979 100644
--- a/examples/clang-interpreter/main.cpp
+++ b/examples/clang-interpreter/main.cpp
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/CodeGen/CodeGenAction.h"
#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/CodeGen/CodeGenAction.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/Tool.h"
@@ -18,7 +18,12 @@
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
-#include "llvm/ExecutionEngine/MCJIT.h"
+#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
+#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
+#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
+#include "llvm/ExecutionEngine/SectionMemoryManager.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
@@ -26,7 +31,8 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"
-#include <memory>
+#include "llvm/Target/TargetMachine.h"
+
using namespace clang;
using namespace clang::driver;
@@ -35,51 +41,80 @@ using namespace clang::driver;
// GetMainExecutable (since some platforms don't support taking the
// address of main, and some platforms can't implement GetMainExecutable
// without being given the address of a function in the main executable).
-std::string GetExecutablePath(const char *Argv0) {
- // This just needs to be some symbol in the binary; C++ doesn't
- // allow taking the address of ::main however.
- void *MainAddr = (void*) (intptr_t) GetExecutablePath;
+std::string GetExecutablePath(const char *Argv0, void *MainAddr) {
return llvm::sys::fs::getMainExecutable(Argv0, MainAddr);
}
-static llvm::ExecutionEngine *
-createExecutionEngine(std::unique_ptr<llvm::Module> M, std::string *ErrorStr) {
- return llvm::EngineBuilder(std::move(M))
- .setEngineKind(llvm::EngineKind::Either)
- .setErrorStr(ErrorStr)
- .create();
-}
+namespace llvm {
+namespace orc {
+
+class SimpleJIT {
+private:
+ ExecutionSession ES;
+ std::shared_ptr<SymbolResolver> Resolver;
+ std::unique_ptr<TargetMachine> TM;
+ const DataLayout DL;
+ RTDyldObjectLinkingLayer ObjectLayer;
+ IRCompileLayer<decltype(ObjectLayer), SimpleCompiler> CompileLayer;
+
+public:
+ SimpleJIT()
+ : Resolver(createLegacyLookupResolver(
+ ES,
+ [this](const std::string &Name) -> JITSymbol {
+ if (auto Sym = CompileLayer.findSymbol(Name, false))
+ return Sym;
+ else if (auto Err = Sym.takeError())
+ return std::move(Err);
+ if (auto SymAddr =
+ RTDyldMemoryManager::getSymbolAddressInProcess(Name))
+ return JITSymbol(SymAddr, JITSymbolFlags::Exported);
+ return nullptr;
+ },
+ [](Error Err) { cantFail(std::move(Err), "lookupFlags failed"); })),
+ TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()),
+ ObjectLayer(ES,
+ [this](VModuleKey) {
+ return RTDyldObjectLinkingLayer::Resources{
+ std::make_shared<SectionMemoryManager>(), Resolver};
+ }),
+ CompileLayer(ObjectLayer, SimpleCompiler(*TM)) {
+ llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr);
+ }
-static int Execute(std::unique_ptr<llvm::Module> Mod, char *const *envp) {
- llvm::InitializeNativeTarget();
- llvm::InitializeNativeTargetAsmPrinter();
+ const TargetMachine &getTargetMachine() const { return *TM; }
+
+ VModuleKey addModule(std::unique_ptr<Module> M) {
+ // Add the module to the JIT with a new VModuleKey.
+ auto K = ES.allocateVModule();
+ cantFail(CompileLayer.addModule(K, std::move(M)));
+ return K;
+ }
- llvm::Module &M = *Mod;
- std::string Error;
- std::unique_ptr<llvm::ExecutionEngine> EE(
- createExecutionEngine(std::move(Mod), &Error));
- if (!EE) {
- llvm::errs() << "unable to make execution engine: " << Error << "\n";
- return 255;
+ JITSymbol findSymbol(const StringRef &Name) {
+ std::string MangledName;
+ raw_string_ostream MangledNameStream(MangledName);
+ Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
+ return CompileLayer.findSymbol(MangledNameStream.str(), true);
}
- llvm::Function *EntryFn = M.getFunction("main");
- if (!EntryFn) {
- llvm::errs() << "'main' function not found in module.\n";
- return 255;
+ JITTargetAddress getSymbolAddress(const StringRef &Name) {
+ return cantFail(findSymbol(Name).getAddress());
}
- // FIXME: Support passing arguments.
- std::vector<std::string> Args;
- Args.push_back(M.getModuleIdentifier());
+ void removeModule(VModuleKey K) {
+ cantFail(CompileLayer.removeModule(K));
+ }
+};
- EE->finalizeObject();
- return EE->runFunctionAsMain(EntryFn, Args, envp);
-}
+} // end namespace orc
+} // end namespace llvm
-int main(int argc, const char **argv, char * const *envp) {
+int main(int argc, const char **argv) {
+ // This just needs to be some symbol in the binary; C++ doesn't
+ // allow taking the address of ::main however.
void *MainAddr = (void*) (intptr_t) GetExecutablePath;
- std::string Path = GetExecutablePath(argv[0]);
+ std::string Path = GetExecutablePath(argv[0], MainAddr);
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
TextDiagnosticPrinter *DiagClient =
new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts);
@@ -87,11 +122,14 @@ int main(int argc, const char **argv, char * const *envp) {
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient);
- // Use ELF on windows for now.
- std::string TripleStr = llvm::sys::getProcessTriple();
+ const std::string TripleStr = llvm::sys::getProcessTriple();
llvm::Triple T(TripleStr);
+
+ // Use ELF on Windows-32 and MingW for now.
+#ifndef CLANG_INTERPRETER_COFF_FORMAT
if (T.isOSBinFormatCOFF())
T.setObjectFormat(llvm::Triple::ELF);
+#endif
Driver TheDriver(Path, T.str(), Diags);
TheDriver.setTitle("clang interpreter");
@@ -163,12 +201,21 @@ int main(int argc, const char **argv, char * const *envp) {
if (!Clang.ExecuteAction(*Act))
return 1;
+ llvm::InitializeNativeTarget();
+ llvm::InitializeNativeTargetAsmPrinter();
+
int Res = 255;
- if (std::unique_ptr<llvm::Module> Module = Act->takeModule())
- Res = Execute(std::move(Module), envp);
+ std::unique_ptr<llvm::Module> Module = Act->takeModule();
+
+ if (Module) {
+ llvm::orc::SimpleJIT J;
+ auto H = J.addModule(std::move(Module));
+ auto Main = (int(*)(...))J.getSymbolAddress("main");
+ Res = Main();
+ J.removeModule(H);
+ }
// Shutdown.
-
llvm::llvm_shutdown();
return Res;
diff --git a/include/clang-c/BuildSystem.h b/include/clang-c/BuildSystem.h
index 8d323a4e6cae..3cfec388308c 100644
--- a/include/clang-c/BuildSystem.h
+++ b/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/include/clang-c/CXCompilationDatabase.h b/include/clang-c/CXCompilationDatabase.h
index 29f89e52a6e3..6f483ee28b56 100644
--- a/include/clang-c/CXCompilationDatabase.h
+++ b/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/include/clang-c/CXErrorCode.h b/include/clang-c/CXErrorCode.h
index aff73b746763..caee48d76832 100644
--- a/include/clang-c/CXErrorCode.h
+++ b/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/include/clang-c/CXString.h b/include/clang-c/CXString.h
index 68ab7bc5244c..76eeda180109 100644
--- a/include/clang-c/CXString.h
+++ b/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/include/clang-c/Documentation.h b/include/clang-c/Documentation.h
index 89373b11457d..58c8af5aa47c 100644
--- a/include/clang-c/Documentation.h
+++ b/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/include/clang-c/Index.h b/include/clang-c/Index.h
index 587008a7210b..0ad90010ccd9 100644
--- a/include/clang-c/Index.h
+++ b/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
+ * 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,7 +383,7 @@ 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.
*/
@@ -391,7 +391,7 @@ 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.
@@ -798,36 +805,36 @@ CINDEX_LINKAGE CXDiagnostic clang_getDiagnosticInSet(CXDiagnosticSet Diags,
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,7 +882,7 @@ 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.
@@ -884,19 +891,19 @@ CINDEX_LINKAGE CXDiagnosticSet
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.
*
@@ -929,7 +936,7 @@ enum CXDiagnosticDisplayOptions {
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
@@ -938,7 +945,7 @@ enum CXDiagnosticDisplayOptions {
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
@@ -947,7 +954,7 @@ enum CXDiagnosticDisplayOptions {
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
@@ -957,7 +964,7 @@ enum CXDiagnosticDisplayOptions {
};
/**
- * \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.
@@ -1018,7 +1025,7 @@ 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
@@ -1030,7 +1037,7 @@ 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.
*
@@ -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
@@ -1237,7 +1244,7 @@ enum CXTranslationUnit_Flags {
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
@@ -1253,7 +1260,7 @@ enum CXTranslationUnit_Flags {
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,13 +1322,21 @@ 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,
+
+ /**
+ * 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_SingleFileParse = 0x400
+ 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()
@@ -1335,7 +1350,7 @@ enum CXTranslationUnit_Flags {
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
@@ -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,17 +1455,17 @@ 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
@@ -1459,7 +1474,7 @@ enum CXSaveError {
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
@@ -1468,14 +1483,14 @@ enum CXSaveError {
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
@@ -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,13 +1539,13 @@ 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
@@ -1542,7 +1557,7 @@ enum CXReparse_Flags {
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
@@ -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,
@@ -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. */
+ /* The memory usage category. */
enum CXTUResourceUsageKind kind;
- /* \brief Amount of resources used.
+ /* 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:
@@ -1805,21 +1820,21 @@ 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
* goto statement in the following example:
@@ -1836,7 +1851,7 @@ enum CXCursorKind {
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
@@ -1874,7 +1889,7 @@ enum CXCursorKind {
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,
@@ -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
@@ -2139,28 +2154,33 @@ enum CXCursorKind {
*/
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
@@ -2170,7 +2190,7 @@ enum CXCursorKind {
*/
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
* the following example:
@@ -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,7 +2778,7 @@ 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.
@@ -2764,39 +2794,39 @@ 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.
@@ -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,7 +2944,7 @@ 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
@@ -2949,7 +2979,7 @@ 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
@@ -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,
@@ -3032,13 +3062,13 @@ CINDEX_LINKAGE void clang_getOverriddenCursors(CXCursor cursor,
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
@@ -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);
@@ -3549,33 +3585,34 @@ CINDEX_LINKAGE CXString clang_getDeclObjCTypeEncoding(CXCursor C);
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.
@@ -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
@@ -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,19 +4093,19 @@ 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.
@@ -4082,7 +4120,90 @@ 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
@@ -4090,7 +4211,7 @@ CINDEX_LINKAGE CXSourceRange clang_Cursor_getSpellingNameRange(CXCursor,
*/
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
@@ -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,7 +4299,7 @@ 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.
@@ -4191,13 +4312,13 @@ CINDEX_LINKAGE int clang_Cursor_getObjCSelectorIndex(CXCursor);
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.
*
@@ -4503,7 +4624,7 @@ CINDEX_LINKAGE unsigned clang_CXXMethod_isConst(CXCursor C);
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.
*
@@ -4533,7 +4654,7 @@ CINDEX_LINKAGE enum CXCursorKind clang_getTemplateCursorKind(CXCursor C);
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
@@ -4556,19 +4677,19 @@ CINDEX_LINKAGE CXSourceRange clang_getCursorReferenceNameRange(CXCursor C,
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:
@@ -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,13 +5145,13 @@ 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
* particular completion is the completion that the user will select. The
@@ -5031,7 +5166,7 @@ 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.
@@ -5042,7 +5177,7 @@ 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,7 +5204,7 @@ 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 declaration (if any) that the code completion represents. For example,
@@ -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.
@@ -5108,7 +5243,7 @@ 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
+ * 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
@@ -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.
@@ -5380,20 +5592,20 @@ 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,7 +5618,7 @@ 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
@@ -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.
@@ -5476,13 +5688,13 @@ 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.
@@ -5490,7 +5702,7 @@ CINDEX_LINKAGE CXString clang_getClangVersion(void);
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,12 +5838,12 @@ 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.
*
@@ -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,7 +5895,7 @@ 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.
*
@@ -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,36 +6203,58 @@ 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;
@@ -6032,24 +6266,28 @@ typedef struct {
*/
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);
@@ -6058,13 +6296,13 @@ typedef struct {
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
@@ -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,7 +6490,7 @@ 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
@@ -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/include/clang/ARCMigrate/ARCMT.h b/include/clang/ARCMigrate/ARCMT.h
index 74081867eebc..30c24f1cdb10 100644
--- a/include/clang/ARCMigrate/ARCMT.h
+++ b/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/include/clang/ARCMigrate/ARCMTActions.h b/include/clang/ARCMigrate/ARCMTActions.h
index 554e0c0c6d02..2571ca75be51 100644
--- a/include/clang/ARCMigrate/ARCMTActions.h
+++ b/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/include/clang/AST/APValue.h b/include/clang/AST/APValue.h
index 7c431f3be8c4..d4057c9da5f3 100644
--- a/include/clang/AST/APValue.h
+++ b/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/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h
index ad368c86c79c..1167c566a35f 100644
--- a/include/clang/AST/ASTConsumer.h
+++ b/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/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index a5d080035df0..c6f8e2973e8e 100644
--- a/include/clang/AST/ASTContext.h
+++ b/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,35 @@ 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 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 +272,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 +329,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 +390,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 +400,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 +433,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 +463,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 +472,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 +496,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 +543,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 +604,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 +703,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 +763,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 +786,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 +817,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 +859,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 +880,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 +889,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 +921,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 +937,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 +959,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 +1001,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 +1050,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 +1072,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 +1082,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 +1101,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 +1109,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 +1117,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 +1148,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 +1157,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 +1166,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 +1215,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 +1223,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 +1235,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 +1262,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 +1301,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 +1347,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 +1355,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 +1386,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 +1432,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 +1483,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 +1610,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 +1618,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 +1631,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 +1644,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 +1704,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 +1773,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 +1791,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 +1813,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 +1829,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 +1851,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 +1898,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 +1922,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 +1953,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 +1989,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 +1997,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 +2010,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,48 +2031,48 @@ 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 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;
@@ -2045,31 +2084,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 +2120,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 +2133,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 +2152,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 +2194,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 +2202,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 +2218,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 +2233,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 +2248,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 +2288,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);
+
+ /// 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);
- /// \brief Retrieves the "canonical" nested name specifier for a
+ /// Retrieves the "canonical" nested name specifier for a
/// given nested name specifier.
///
/// The canonical nested name specifier is a nested name specifier
@@ -2277,11 +2329,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 +2353,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 +2384,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 +2420,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 +2573,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 +2601,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 +2630,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 +2655,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 +2684,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 +2692,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(const FunctionDecl *)> Pred) const;
+
const CXXConstructorDecl *
getCopyConstructorForExceptionObject(CXXRecordDecl *RD);
@@ -2653,21 +2718,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 +2741,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 +2821,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 +2839,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 +2855,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 +2906,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 +2922,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 +2955,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 +2993,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 +3003,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/include/clang/AST/ASTDiagnostic.h b/include/clang/AST/ASTDiagnostic.h
index 27c85e65f2c1..b08865dde3c1 100644
--- a/include/clang/AST/ASTDiagnostic.h
+++ b/include/clang/AST/ASTDiagnostic.h
@@ -24,7 +24,7 @@ namespace clang {
};
} // 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,
diff --git a/include/clang/AST/ASTFwd.h b/include/clang/AST/ASTFwd.h
index 003d489c1ca4..038d5c3d3611 100644
--- a/include/clang/AST/ASTFwd.h
+++ b/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/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h
index 66b9cd394b9d..6e6a1926254b 100644
--- a/include/clang/AST/ASTImporter.h
+++ b/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;
+ /// Whether the last diagnostic came from the "from" context.
+ bool LastDiagFromFrom = false;
- /// \brief Mapping from the already-imported types in the "from" context
+ /// 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.
///
@@ -105,135 +118,144 @@ namespace clang {
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
/// 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
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
@@ -265,41 +287,41 @@ namespace clang {
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
@@ -307,11 +329,12 @@ namespace clang {
/// 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/include/clang/AST/ASTLambda.h b/include/clang/AST/ASTLambda.h
index 69df2d8c0113..2fe4e2563b36 100644
--- a/include/clang/AST/ASTLambda.h
+++ b/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.
///
//===----------------------------------------------------------------------===//
diff --git a/include/clang/AST/ASTMutationListener.h b/include/clang/AST/ASTMutationListener.h
index 9395d36d87e5..31ae2b111e01 100644
--- a/include/clang/AST/ASTMutationListener.h
+++ b/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,14 +128,14 @@ 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
///
diff --git a/include/clang/AST/ASTStructuralEquivalence.h b/include/clang/AST/ASTStructuralEquivalence.h
index 23674c65f332..d32f87d43e04 100644
--- a/include/clang/AST/ASTStructuralEquivalence.h
+++ b/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/include/clang/AST/ASTTypeTraits.h b/include/clang/AST/ASTTypeTraits.h
index 51d60a90a146..9df9793370c4 100644
--- a/include/clang/AST/ASTTypeTraits.h
+++ b/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/include/clang/AST/ASTUnresolvedSet.h b/include/clang/AST/ASTUnresolvedSet.h
index 3693aeccfe14..9bf63bb6e2d7 100644
--- a/include/clang/AST/ASTUnresolvedSet.h
+++ b/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/include/clang/AST/Attr.h b/include/clang/AST/Attr.h
index bbe320c28a3b..32a61c59d236 100644
--- a/include/clang/AST/Attr.h
+++ b/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,10 +76,10 @@ 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:
@@ -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/include/clang/AST/Availability.h b/include/clang/AST/Availability.h
index 5ed831378456..28f3c3c01d20 100644
--- a/include/clang/AST/Availability.h
+++ b/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/include/clang/AST/BuiltinTypes.def b/include/clang/AST/BuiltinTypes.def
index e4f5f7db2f73..400efcb1981f 100644
--- a/include/clang/AST/BuiltinTypes.def
+++ b/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/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h
index 11fb229f0c09..2ae1d8b25823 100644
--- a/include/clang/AST/CXXInheritance.h
+++ b/include/clang/AST/CXXInheritance.h
@@ -35,7 +35,7 @@ namespace clang {
class ASTContext;
class NamedDecl;
-/// \brief Represents an element in a path from a derived class to a
+/// Represents an element in a path from a derived class to a
/// base class.
///
/// Each step in the path references the link from a
@@ -43,15 +43,15 @@ class NamedDecl;
/// 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
+ /// 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
@@ -60,7 +60,7 @@ 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.
///
@@ -70,14 +70,14 @@ struct CXXBasePathElement {
/// 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,24 +119,42 @@ 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
@@ -152,20 +170,7 @@ class CXXBasePaths {
/// 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,
@@ -196,53 +201,53 @@ public:
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/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h
index 6487613200de..63a0af66eec3 100644
--- a/include/clang/AST/CanonicalType.h
+++ b/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,35 +64,35 @@ 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());
}
- /// \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 {
@@ -101,7 +101,7 @@ public:
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/include/clang/AST/Comment.h b/include/clang/AST/Comment.h
index 94470cbf305f..e3a427d8aa0d 100644
--- a/include/clang/AST/Comment.h
+++ b/include/clang/AST/Comment.h
@@ -990,7 +990,7 @@ struct DeclInfo {
/// 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).
diff --git a/include/clang/AST/CommentBriefParser.h b/include/clang/AST/CommentBriefParser.h
index be5b8eeb80c3..baa22930539e 100644
--- a/include/clang/AST/CommentBriefParser.h
+++ b/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/include/clang/AST/CommentCommandTraits.h b/include/clang/AST/CommentCommandTraits.h
index 289f2fd345af..bac4e99dc7a4 100644
--- a/include/clang/AST/CommentCommandTraits.h
+++ b/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:
@@ -108,17 +108,17 @@ struct CommandInfo {
/// \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;
};
diff --git a/include/clang/AST/CommentLexer.h b/include/clang/AST/CommentLexer.h
index 5bb075807be5..52c4eb9e309a 100644
--- a/include/clang/AST/CommentLexer.h
+++ b/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,7 +72,7 @@ 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;
@@ -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;
@@ -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/include/clang/AST/CommentSema.h b/include/clang/AST/CommentSema.h
index 230e52739f24..0e94c33970ca 100644
--- a/include/clang/AST/CommentSema.h
+++ b/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,7 +187,7 @@ 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);
diff --git a/include/clang/AST/ComparisonCategories.h b/include/clang/AST/ComparisonCategories.h
new file mode 100644
index 000000000000..23bfd708e7eb
--- /dev/null
+++ b/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/include/clang/AST/DataCollection.h b/include/clang/AST/DataCollection.h
index 229ac2bd0f22..8b2a8345d941 100644
--- a/include/clang/AST/DataCollection.h
+++ b/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/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 04a832e552a4..dde94599636f 100644
--- a/include/clang/AST/Decl.h
+++ b/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;
@@ -501,18 +510,18 @@ public:
static bool classofKind(Kind K) { return K == Label; }
};
-/// NamespaceDecl - Represent a C++ namespace.
+/// 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
/// boolean value indicating whether this is an inline namespace.
@@ -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>;
@@ -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
@@ -2534,20 +2599,20 @@ public:
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.
@@ -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,12 +3800,12 @@ 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;
@@ -3653,7 +3815,7 @@ public:
const FieldDecl *findFirstNamedDataMember() const;
private:
- /// \brief Deserialize just the fields.
+ /// Deserialize just the fields.
void LoadFieldsFromExternalStorage() const;
};
@@ -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,7 +3924,7 @@ 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);
@@ -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,
@@ -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,7 +4143,7 @@ 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.
///
@@ -3983,7 +4151,7 @@ class ImportDecl final : public Decl,
/// 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;
@@ -3996,25 +4164,25 @@ class ImportDecl final : public Decl,
ImportDecl(EmptyShell Empty) : Decl(Import, Empty) {}
public:
- /// \brief Create a new module import declaration.
+ /// 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,
SourceLocation EndLoc);
- /// \brief Create a new, deserialized module import declaration.
+ /// 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)
@@ -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/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index f93c9f0b9aaa..f99bd627877c 100644
--- a/include/clang/AST/DeclBase.h
+++ b/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() &&
@@ -836,6 +842,10 @@ public:
void setLexicalDeclContext(DeclContext *DC);
+ /// Determine whether this declaration is a templated entity (whether it is
+ // within the scope of a template parameter).
+ bool isTemplated() const;
+
/// isDefinedOutsideFunctionOrMethod - This predicate returns true if this
/// scoped decl is defined outside the current function or method. This is
/// roughly global variables and functions, but also handles enums (which
@@ -844,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
@@ -853,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() {
@@ -861,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;
@@ -931,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());
@@ -943,26 +953,26 @@ 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 {
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 {
return const_cast<Decl *>(this)->getMostRecentDeclImpl();
@@ -973,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.
@@ -996,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;
@@ -1021,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
@@ -1042,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
@@ -1091,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.
@@ -1131,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;
@@ -1145,7 +1155,7 @@ 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;
@@ -1172,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 {
@@ -1253,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
@@ -1305,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 *>
@@ -1388,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;
@@ -1414,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;
@@ -1435,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();
@@ -1483,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().
///
@@ -1503,7 +1513,7 @@ 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
@@ -1659,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
@@ -1735,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
@@ -1749,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
@@ -1759,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
@@ -1767,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;
@@ -1783,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
@@ -1800,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,
@@ -1823,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;
@@ -1861,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
@@ -1873,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;
@@ -1902,7 +1918,7 @@ 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 ||
@@ -1933,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.
///
@@ -1943,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/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index 88dc9a655917..1d0489912c6b 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/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;
+
+ /// 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;
- /// \brief True when there are private non-static data members.
+ /// 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,108 +462,108 @@ 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
+ /// The first friend declaration in this class, or null if there
/// aren't any.
///
/// This is actually currently stored in reverse order.
@@ -554,14 +571,14 @@ class CXXRecordDecl : public RecordDecl {
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,11 +600,11 @@ 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
@@ -597,33 +614,33 @@ class CXXRecordDecl : public RecordDecl {
/// 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,
@@ -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,53 +1173,53 @@ 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;
- /// \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;
- /// \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;
- /// \brief Retrieve the generic lambda's template parameter list.
+ /// 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,7 +1897,7 @@ 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
@@ -1829,7 +1908,7 @@ public:
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
@@ -1840,17 +1919,17 @@ public:
/// 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,12 +2791,12 @@ 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;
@@ -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,
@@ -2785,13 +2863,13 @@ public:
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;
diff --git a/include/clang/AST/DeclContextInternals.h b/include/clang/AST/DeclContextInternals.h
index 6545f70f70b5..ccd82d2cf0d2 100644
--- a/include/clang/AST/DeclContextInternals.h
+++ b/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/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h
index 5d1c6b86fe11..47fb68bf42d3 100644
--- a/include/clang/AST/DeclFriend.h
+++ b/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();
}
diff --git a/include/clang/AST/DeclLookups.h b/include/clang/AST/DeclLookups.h
index 2fff05582563..64eb3f24b370 100644
--- a/include/clang/AST/DeclLookups.h
+++ b/include/clang/AST/DeclLookups.h
@@ -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/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index cef7d935370a..c81a5f805fc0 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/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.
@@ -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
};
@@ -1163,7 +1163,7 @@ public:
}
};
-/// \brief Represents an ObjC class declaration.
+/// Represents an ObjC class declaration.
///
/// For example:
///
@@ -1197,7 +1197,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
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;
@@ -1210,7 +1210,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
/// 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;
@@ -1248,7 +1248,7 @@ 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 location of the last location in this declaration, before
/// the properties/methods. For example, this will be the '>', '}', or
/// identifier,
SourceLocation EndLoc;
@@ -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,7 +1283,7 @@ 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>;
@@ -1338,7 +1338,7 @@ public:
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();
@@ -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 {
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.
@@ -1562,21 +1562,21 @@ public:
return Data.getPointer();
}
- /// \brief Retrieve the definition of this class, or NULL if this class
+ /// 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
+ /// 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();
@@ -1608,7 +1608,7 @@ public:
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
@@ -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,24 +1744,24 @@ 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);
@@ -1771,7 +1771,7 @@ public:
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,23 +1782,23 @@ 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.
@@ -1811,7 +1811,7 @@ public:
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;
@@ -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,
@@ -1988,7 +1988,7 @@ public:
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,
@@ -2051,7 +2051,7 @@ public:
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
+ /// 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
@@ -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
@@ -2310,7 +2310,7 @@ 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.
@@ -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;
@@ -2578,7 +2578,7 @@ class ObjCImplementationDecl : public ObjCImplDecl {
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;
@@ -2694,7 +2694,7 @@ 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 {
@@ -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/include/clang/AST/DeclOpenMP.h b/include/clang/AST/DeclOpenMP.h
index 2a329c3732cb..bec3acffc433 100644
--- a/include/clang/AST/DeclOpenMP.h
+++ b/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/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index 7842d7097174..a2f00ec9ffa2 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/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];
@@ -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,14 +880,14 @@ 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
+ /// Retrieve the member template from which this template was
/// instantiated, or nullptr if this template was not instantiated from a
/// member template.
///
@@ -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;
@@ -1180,7 +1181,7 @@ public:
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(
@@ -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,
@@ -1501,7 +1502,7 @@ public:
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.
///
@@ -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/include/clang/AST/DeclVisitor.h b/include/clang/AST/DeclVisitor.h
index 3ff274bd6a7a..520a4a10bfe1 100644
--- a/include/clang/AST/DeclVisitor.h
+++ b/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/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h
index 467b02c52b0c..9d3dad6bbd9d 100644
--- a/include/clang/AST/DeclarationName.h
+++ b/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,7 +211,7 @@ 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",
@@ -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;
diff --git a/include/clang/AST/EvaluatedExprVisitor.h b/include/clang/AST/EvaluatedExprVisitor.h
index aad7726f8484..e00986dbe9c8 100644
--- a/include/clang/AST/EvaluatedExprVisitor.h
+++ b/include/clang/AST/EvaluatedExprVisitor.h
@@ -24,7 +24,7 @@ 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/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index f2770940372f..7585231e62e5 100644
--- a/include/clang/AST/Expr.h
+++ b/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;
@@ -883,6 +890,7 @@ public:
(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) { }
@@ -2743,26 +2822,30 @@ protected:
(op && op->containsUnexpandedParameterPack()))),
Op(op) {
CastExprBits.Kind = kind;
+ CastExprBits.PartOfExplicitCast = false;
setBasePathSize(BasePathSize);
assert(CastConsistency());
}
- /// \brief Construct an empty cast.
+ /// Construct an empty cast.
CastExpr(StmtClass SC, EmptyShell Empty, unsigned BasePathSize)
: Expr(SC, Empty) {
+ CastExprBits.PartOfExplicitCast = false;
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,6 +2853,10 @@ 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; }
@@ -2828,7 +2915,7 @@ private:
: 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 +2926,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 +2988,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) { }
@@ -2931,7 +3023,7 @@ 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) { }
@@ -2964,7 +3056,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 +3107,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 +3136,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 +3170,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 +3183,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 +3296,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 +3386,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 +3464,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 +3543,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 +3590,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 +3636,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 +3658,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 +3776,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 +3843,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 +3916,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 +3974,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 +3987,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 +4032,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 +4043,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 +4052,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 +4063,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 +4175,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 +4199,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 +4219,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 +4264,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 +4289,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 +4298,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 +4308,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 +4394,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 +4418,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 +4437,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 +4453,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 +4480,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 +4563,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 +4631,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 +4661,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 +4675,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 +4704,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 +4747,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 +4893,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 +4951,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 +5203,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 +5217,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 +5300,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 +5311,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 {
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index 58054dda31aa..8206a26b2c4b 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/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,7 +295,7 @@ 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).
@@ -330,7 +330,7 @@ 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
@@ -369,7 +369,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).
@@ -410,7 +410,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).
@@ -445,7 +445,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 +455,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 +492,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 +512,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 +526,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 +559,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 +589,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 +619,7 @@ public:
return SubExpr->getLocEnd();
}
+ /// Retrieve the source range of the expression.
SourceRange getSourceRange() const LLVM_READONLY {
return SubExpr->getSourceRange();
}
@@ -677,11 +678,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 +716,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 +817,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 +885,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 +926,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 +978,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 +989,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 +1010,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 +1035,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 +1082,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 +1103,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 +1112,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 +1134,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 +1161,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 +1180,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 +1236,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 +1274,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 +1283,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 +1299,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 +1362,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 +1372,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 +1394,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 +1415,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 +1427,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 +1443,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 +1462,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:
@@ -1504,6 +1505,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 +1516,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 +1560,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,27 +1583,27 @@ 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
@@ -1609,7 +1613,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 +1621,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 +1638,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,143 +1646,143 @@ 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
+ /// Retrieve the function call operator associated with this
/// lambda expression.
CXXMethodDecl *getCallOperator() const;
- /// \brief If this is a generic lambda expression, retrieve the template
+ /// 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) {
@@ -1806,7 +1810,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 +1841,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 +1851,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 +1926,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 +1977,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 +1995,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 +2070,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 +2129,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 +2146,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 +2174,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 +2201,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 +2243,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 +2277,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 +2295,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 +2332,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,10 +2343,10 @@ 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
@@ -2364,7 +2368,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,
@@ -2374,7 +2378,7 @@ 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);
}
@@ -2384,16 +2388,16 @@ public:
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());
@@ -2412,7 +2416,7 @@ public:
}
};
-/// \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 +2425,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 +2487,7 @@ public:
}
};
-/// \brief An expression trait intrinsic.
+/// An expression trait intrinsic.
///
/// Example:
/// \code
@@ -2491,19 +2495,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 +2547,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 +2565,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 +2581,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 +2608,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 +2622,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 +2636,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 +2649,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 +2714,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 +2726,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 +2841,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 +2860,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 +2896,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 +2944,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 +3067,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 +3094,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 +3124,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 +3147,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 +3191,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 +3208,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 +3239,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 +3281,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 +3295,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 +3327,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 +3365,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 +3377,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 +3386,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 +3425,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 +3448,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 +3500,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 +3519,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 +3597,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 +3636,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 +3659,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 +3681,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 +3716,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 +3732,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 +3753,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 +3769,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 +3786,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 +3808,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 +3817,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 +3837,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 +3883,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 +3899,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 +3917,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 +3945,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 +3966,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 +3987,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 +4017,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 +4043,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 +4076,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 +4098,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 +4111,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 +4139,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 +4208,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 +4272,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 +4305,7 @@ public:
}
};
-/// \brief Represents a 'co_await' expression.
+/// Represents a 'co_await' expression.
class CoawaitExpr : public CoroutineSuspendExpr {
friend class ASTStmtReader;
@@ -4335,7 +4340,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 +4388,7 @@ public:
}
};
-/// \brief Represents a 'co_yield' expression.
+/// Represents a 'co_yield' expression.
class CoyieldExpr : public CoroutineSuspendExpr {
friend class ASTStmtReader;
diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h
index ab2df8a34819..5dac0e037da1 100644
--- a/include/clang/AST/ExprObjC.h
+++ b/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>
@@ -198,10 +198,10 @@ 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 *>();
}
@@ -212,11 +212,11 @@ public:
/// 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 {
@@ -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
@@ -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,
@@ -601,7 +601,7 @@ private:
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;
@@ -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 {
@@ -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;
@@ -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.
///
@@ -1098,7 +1098,7 @@ public:
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.
///
@@ -1132,7 +1132,7 @@ public:
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.
///
@@ -1166,7 +1166,7 @@ public:
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,14 +1213,14 @@ 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) {
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 {
if (TypeSourceInfo *TSInfo = getClassReceiverTypeInfo())
@@ -1229,7 +1229,7 @@ public:
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,7 +1242,7 @@ 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 {
if (getReceiverKind() == SuperInstance || getReceiverKind() == SuperClass)
@@ -1251,7 +1251,7 @@ public:
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
@@ -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);
@@ -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; }
@@ -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
@@ -1589,21 +1589,21 @@ public:
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.
+ /// 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; }
@@ -1617,7 +1617,7 @@ public:
}
};
-/// \brief A runtime availability query.
+/// A runtime availability query.
///
/// There are 2 ways to spell this node:
/// \code
@@ -1650,7 +1650,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/include/clang/AST/ExprOpenMP.h b/include/clang/AST/ExprOpenMP.h
index a4ef93ba8b14..2b4b5ec4d0e4 100644
--- a/include/clang/AST/ExprOpenMP.h
+++ b/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/include/clang/AST/ExternalASTMerger.h b/include/clang/AST/ExternalASTMerger.h
index 81492aec6e13..ae8a761e127e 100644
--- a/include/clang/AST/ExternalASTMerger.h
+++ b/include/clang/AST/ExternalASTMerger.h
@@ -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.
diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h
index be013c5d6b6a..82255bb1c44c 100644
--- a/include/clang/AST/ExternalASTSource.h
+++ b/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,35 +243,35 @@ 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
/// layout for a record, overriding the layout that would normally be
@@ -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,7 +509,7 @@ 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
@@ -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/include/clang/AST/LambdaCapture.h b/include/clang/AST/LambdaCapture.h
index 6517d656878e..bcc5352c1c9d 100644
--- a/include/clang/AST/LambdaCapture.h
+++ b/include/clang/AST/LambdaCapture.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines the LambdaCapture class.
+/// Defines the LambdaCapture class.
///
//===----------------------------------------------------------------------===//
@@ -21,21 +21,21 @@
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
};
@@ -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/include/clang/AST/LocInfoType.h b/include/clang/AST/LocInfoType.h
index 7e573bd7bac4..802d9134ebde 100644
--- a/include/clang/AST/LocInfoType.h
+++ b/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/include/clang/AST/Mangle.h b/include/clang/AST/Mangle.h
index 7a45d88c23c8..401574b265b0 100644
--- a/include/clang/AST/Mangle.h
+++ b/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;
@@ -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/include/clang/AST/MangleNumberingContext.h b/include/clang/AST/MangleNumberingContext.h
index 869221dbf31b..ff2148e3516d 100644
--- a/include/clang/AST/MangleNumberingContext.h
+++ b/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/include/clang/AST/NSAPI.h b/include/clang/AST/NSAPI.h
index 3757116e7c70..ee07745b1242 100644
--- a/include/clang/AST/NSAPI.h
+++ b/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,
@@ -114,13 +114,13 @@ public:
};
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/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h
index e2cb45c36de6..2255d5114350 100644
--- a/include/clang/AST/NestedNameSpecifier.h
+++ b/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
@@ -47,7 +47,7 @@ class TypeLoc;
/// 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
@@ -455,7 +455,7 @@ 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.
///
/// 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/include/clang/AST/NonTrivialTypeVisitor.h b/include/clang/AST/NonTrivialTypeVisitor.h
new file mode 100644
index 000000000000..bab373dbb298
--- /dev/null
+++ b/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/include/clang/AST/ODRHash.h b/include/clang/AST/ODRHash.h
index ed648bb8afb1..75b361789211 100644
--- a/include/clang/AST/ODRHash.h
+++ b/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/include/clang/AST/OpenMPClause.h b/include/clang/AST/OpenMPClause.h
index 1f732f67517a..a28609f8cdf9 100644
--- a/include/clang/AST/OpenMPClause.h
+++ b/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,7 +915,7 @@ 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)
@@ -925,17 +925,17 @@ public:
class OMPOrderedClause : 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 'ordered' clause.
+ /// Build 'ordered' clause.
///
/// \param Num Expression, possibly associated with this clause.
/// \param StartLoc Starting location of the clause.
@@ -946,17 +946,17 @@ public:
: OMPClause(OMPC_ordered, StartLoc, EndLoc), LParenLoc(LParenLoc),
NumForLoops(Num) {}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
explicit OMPOrderedClause()
: OMPClause(OMPC_ordered, 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); }
@@ -966,7 +966,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 +974,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 +994,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 +1002,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 +1022,7 @@ public:
}
};
-/// \brief This represents 'mergeable' clause in the '#pragma omp ...'
+/// This represents 'mergeable' clause in the '#pragma omp ...'
/// directive.
///
/// \code
@@ -1031,14 +1031,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 +1051,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 +1059,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 +1078,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 +1086,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 +1106,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 +1115,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 +1135,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 +1144,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 +1164,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 +1173,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 +1193,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 +1207,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 +1218,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 +1226,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 +1241,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 +1254,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 +1286,7 @@ public:
}
};
-/// \brief This represents clause 'firstprivate' in the '#pragma omp ...'
+/// This represents clause 'firstprivate' in the '#pragma omp ...'
/// directives.
///
/// \code
@@ -1302,7 +1302,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 +1314,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 +1323,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 +1337,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 +1352,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 +1370,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 +1413,7 @@ public:
}
};
-/// \brief This represents clause 'lastprivate' in the '#pragma omp ...'
+/// This represents clause 'lastprivate' in the '#pragma omp ...'
/// directives.
///
/// \code
@@ -1445,7 +1445,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 +1457,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 +1466,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 +1475,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 +1489,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 +1503,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 +1517,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 +1547,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 +1559,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 +1612,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 +1625,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 +1636,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 +1645,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 +1656,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 +1672,7 @@ public:
}
};
-/// \brief This represents clause 'reduction' in the '#pragma omp ...'
+/// This represents clause 'reduction' in the '#pragma omp ...'
/// directives.
///
/// \code
@@ -1688,16 +1688,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 +1715,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 +1724,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 +1746,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 +1759,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 +1774,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 +1789,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 +1829,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 +2357,7 @@ public:
}
};
-/// \brief This represents clause 'linear' in the '#pragma omp ...'
+/// This represents clause 'linear' in the '#pragma omp ...'
/// directives.
///
/// \code
@@ -2373,22 +2373,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 +2404,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 +2413,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 +2439,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 +2447,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 +2455,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 +2490,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 +2596,7 @@ public:
}
};
-/// \brief This represents clause 'aligned' in the '#pragma omp ...'
+/// This represents clause 'aligned' in the '#pragma omp ...'
/// directives.
///
/// \code
@@ -2611,13 +2611,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 +2631,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 +2640,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 +2655,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 +2683,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 +2710,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 +2721,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 +2729,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 +2742,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 +2755,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 +2770,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 +2796,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 +2847,7 @@ public:
}
};
-/// \brief This represents clause 'copyprivate' in the '#pragma omp ...'
+/// This represents clause 'copyprivate' in the '#pragma omp ...'
/// directives.
///
/// \code
@@ -2862,7 +2862,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 +2873,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 +2881,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 +2894,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 +2907,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 +2922,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 +2947,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 +2998,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 +3016,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 +3027,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 +3036,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 +3047,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 +3063,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,16 +3078,16 @@ 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.
+ /// Build clause with number of variables \a N.
///
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
@@ -3098,7 +3098,7 @@ class OMPDependClause final
: OMPVarListClause<OMPDependClause>(OMPC_depend, StartLoc, LParenLoc,
EndLoc, N) {}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
///
/// \param N Number of variables.
explicit OMPDependClause(unsigned N)
@@ -3106,17 +3106,17 @@ class OMPDependClause final
SourceLocation(), SourceLocation(),
N) {}
- /// \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.
@@ -3131,19 +3131,19 @@ public:
SourceLocation EndLoc, OpenMPDependClauseKind DepKind,
SourceLocation DepLoc, SourceLocation ColonLoc, 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.
static OMPDependClause *CreateEmpty(const ASTContext &C, unsigned N);
- /// \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
@@ -3166,7 +3166,7 @@ public:
}
};
-/// \brief This represents 'device' clause in the '#pragma omp ...'
+/// This represents 'device' clause in the '#pragma omp ...'
/// directive.
///
/// \code
@@ -3177,46 +3177,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 +3229,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 +3237,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 +3257,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 +3265,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 +3284,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 +3320,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 +3351,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 +3383,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 +3391,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 +3400,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 +3408,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 +3416,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 +3424,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 +3432,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 +3441,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 +3450,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 +3458,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 +3466,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 +3474,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 +3486,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 +3563,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 +3603,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 +3619,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 +3709,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 +3725,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 +3778,7 @@ public:
}
};
-/// \brief This represents clause 'map' in the '#pragma omp ...'
+/// This represents clause 'map' in the '#pragma omp ...'
/// directives.
///
/// \code
@@ -3804,22 +3807,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 +3849,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 +3862,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 +3902,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 +3918,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 +3950,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 +3961,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 +3990,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 +4014,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 +4025,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 +4055,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 +4079,7 @@ public:
}
};
-/// \brief This represents 'priority' clause in the '#pragma omp ...'
+/// This represents 'priority' clause in the '#pragma omp ...'
/// directive.
///
/// \code
@@ -4087,19 +4090,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 +4113,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 +4136,7 @@ public:
}
};
-/// \brief This represents 'grainsize' clause in the '#pragma omp ...'
+/// This represents 'grainsize' clause in the '#pragma omp ...'
/// directive.
///
/// \code
@@ -4144,17 +4147,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 +4167,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 +4187,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 +4195,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 +4215,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 +4226,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 +4246,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 +4266,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 +4276,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 +4297,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 +4316,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 +4327,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 +4390,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 +4423,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 +4433,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 +4492,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 +4524,7 @@ public:
}
};
-/// \brief This represents clause 'to' in the '#pragma omp ...'
+/// This represents clause 'to' in the '#pragma omp ...'
/// directives.
///
/// \code
@@ -4538,7 +4541,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 +4558,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 +4584,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 +4598,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 +4622,7 @@ public:
}
};
-/// \brief This represents clause 'from' in the '#pragma omp ...'
+/// This represents clause 'from' in the '#pragma omp ...'
/// directives.
///
/// \code
@@ -4637,7 +4640,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 +4657,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 +4683,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 +4697,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/include/clang/AST/OperationKinds.def b/include/clang/AST/OperationKinds.def
index b13cf3b63276..823e32424f1e 100644
--- a/include/clang/AST/OperationKinds.def
+++ b/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
diff --git a/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h
index e3832689d64b..c7e01fa1834e 100644
--- a/include/clang/AST/OperationKinds.h
+++ b/include/clang/AST/OperationKinds.h
@@ -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/include/clang/AST/ParentMap.h b/include/clang/AST/ParentMap.h
index 8945c413d268..c1c76ceaaf69 100644
--- a/include/clang/AST/ParentMap.h
+++ b/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/include/clang/Sema/PrettyDeclStackTrace.h b/include/clang/AST/PrettyDeclStackTrace.h
index ca22e640deb4..8eb519eae26d 100644
--- a/include/clang/Sema/PrettyDeclStackTrace.h
+++ b/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/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h
index e831b903cbae..41c804486c35 100644
--- a/include/clang/AST/PrettyPrinter.h
+++ b/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),
diff --git a/include/clang/AST/QualTypeNames.h b/include/clang/AST/QualTypeNames.h
index 86d805feeed7..422ed9e4c8fc 100644
--- a/include/clang/AST/QualTypeNames.h
+++ b/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/include/clang/AST/RawCommentList.h b/include/clang/AST/RawCommentList.h
index 2e005ddbd027..8327efc750fd 100644
--- a/include/clang/AST/RawCommentList.h
+++ b/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/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h
index 696d44efa0d9..dc60ef892b07 100644
--- a/include/clang/AST/RecordLayout.h
+++ b/include/clang/AST/RecordLayout.h
@@ -111,7 +111,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;
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index ba76ea0a0df5..0d2b670507c1 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/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/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h
index 86b0f356e7b5..c2bd6e6fd136 100644
--- a/include/clang/AST/Redeclarable.h
+++ b/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/include/clang/AST/SelectorLocationsKind.h b/include/clang/AST/SelectorLocationsKind.h
index 6d903f820cd4..6ca2dba47558 100644
--- a/include/clang/AST/SelectorLocationsKind.h
+++ b/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/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index b27dbfacf6a6..91dbcb71a600 100644
--- a/include/clang/AST/Stmt.h
+++ b/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 BasePathSize : 32 - 6 - 1 - NumExprBits;
};
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;
@@ -262,14 +274,14 @@ protected:
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 ---===//
@@ -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/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h
index 77f81838e5eb..34553741eb38 100644
--- a/include/clang/AST/StmtCXX.h
+++ b/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/include/clang/AST/StmtObjC.h b/include/clang/AST/StmtObjC.h
index 5260b6985bf5..571ad76be8a9 100644
--- a/include/clang/AST/StmtObjC.h
+++ b/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;
@@ -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,7 +150,7 @@ 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.
@@ -162,7 +162,7 @@ private:
// 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)
@@ -189,38 +189,38 @@ public:
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;
@@ -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/include/clang/AST/StmtOpenMP.h b/include/clang/AST/StmtOpenMP.h
index 66fb037fc33c..84a35db938b0 100644
--- a/include/clang/AST/StmtOpenMP.h
+++ b/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,45 +164,49 @@ 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.
- Stmt *getAssociatedStmt() const {
+ /// Returns statement associated with the directive.
+ const Stmt *getAssociatedStmt() const {
assert(hasAssociatedStmt() && "no associated statement.");
- return const_cast<Stmt *>(*child_begin());
+ return *child_begin();
+ }
+ Stmt *getAssociatedStmt() {
+ assert(hasAssociatedStmt() && "no associated statement.");
+ 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.
- CapturedStmt *getCapturedStmt(OpenMPDirectiveKind RegionKind) const {
+ const CapturedStmt *getCapturedStmt(OpenMPDirectiveKind RegionKind) const {
SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
getOpenMPCaptureRegions(CaptureRegions, getDirectiveKind());
assert(std::any_of(
@@ -218,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) {
@@ -229,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(); }
@@ -239,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)
@@ -250,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.
@@ -264,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.
///
@@ -274,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.
@@ -291,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.
@@ -299,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) {
@@ -307,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,
@@ -372,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(),
@@ -394,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(),
@@ -402,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(),
@@ -411,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.
@@ -431,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;
@@ -441,7 +466,7 @@ protected:
return DefaultEnd;
}
- /// \brief Children number.
+ /// Children number.
static unsigned numLoopChildren(unsigned CollapsedNum,
OpenMPDirectiveKind Kind) {
return getArraysOffset(Kind) + 5 * CollapsedNum; // Counters,
@@ -606,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;
@@ -679,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 &&
@@ -687,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;
@@ -732,7 +757,7 @@ public:
}
};
- /// \brief Get number of collapsed loops.
+ /// Get number of collapsed loops.
unsigned getCollapsedNumber() const { return CollapsedNum; }
Expr *getIterationVariable() const {
@@ -899,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();
@@ -969,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)
@@ -980,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.
@@ -992,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.
@@ -1003,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.
@@ -1019,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.
@@ -1034,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)
@@ -1046,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.
@@ -1062,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.
@@ -1072,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.
@@ -1093,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.
@@ -1103,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) {
@@ -1111,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)
@@ -1122,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.
@@ -1134,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.
@@ -1145,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.
@@ -1160,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.
@@ -1176,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)
@@ -1188,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.
@@ -1203,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.
///
@@ -1213,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.
@@ -1230,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.
@@ -1239,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) {
@@ -1247,7 +1271,7 @@ public:
}
};
-/// \brief This represents '#pragma omp section' directive.
+/// This represents '#pragma omp section' directive.
///
/// \code
/// #pragma omp section
@@ -1256,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.
@@ -1269,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,
@@ -1277,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.
@@ -1290,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) {
@@ -1307,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)
@@ -1317,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.
@@ -1328,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.
///
@@ -1338,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.
@@ -1350,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.
@@ -1364,7 +1388,7 @@ public:
}
};
-/// \brief This represents '#pragma omp master' directive.
+/// This represents '#pragma omp master' directive.
///
/// \code
/// #pragma omp master
@@ -1372,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.
@@ -1381,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.
@@ -1400,7 +1424,7 @@ public:
SourceLocation EndLoc,
Stmt *AssociatedStmt);
- /// \brief Creates an empty directive.
+ /// Creates an empty directive.
///
/// \param C AST context.
///
@@ -1411,7 +1435,7 @@ public:
}
};
-/// \brief This represents '#pragma omp critical' directive.
+/// This represents '#pragma omp critical' directive.
///
/// \code
/// #pragma omp critical
@@ -1419,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.
@@ -1434,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.
///
@@ -1444,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.
@@ -1465,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.
@@ -1473,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; }
@@ -1482,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)
@@ -1494,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.
@@ -1510,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.
@@ -1521,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.
@@ -1541,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.
@@ -1553,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) {
@@ -1561,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)
@@ -1573,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.
@@ -1586,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.
@@ -1598,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.
@@ -1613,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.
@@ -1630,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)
@@ -1642,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.
@@ -1658,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.
///
@@ -1668,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.
@@ -1685,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.
@@ -1694,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) {
@@ -1702,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)
@@ -1712,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.
@@ -1727,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.
///
@@ -1737,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.
@@ -1755,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.
@@ -1764,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) {
@@ -1772,7 +1796,7 @@ public:
}
};
-/// \brief This represents '#pragma omp taskyield' directive.
+/// This represents '#pragma omp taskyield' directive.
///
/// \code
/// #pragma omp taskyield
@@ -1780,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.
@@ -1789,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.
@@ -1805,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.
///
@@ -1816,7 +1840,7 @@ public:
}
};
-/// \brief This represents '#pragma omp barrier' directive.
+/// This represents '#pragma omp barrier' directive.
///
/// \code
/// #pragma omp barrier
@@ -1824,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.
@@ -1833,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.
@@ -1849,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.
///
@@ -1860,7 +1884,7 @@ public:
}
};
-/// \brief This represents '#pragma omp taskwait' directive.
+/// This represents '#pragma omp taskwait' directive.
///
/// \code
/// #pragma omp taskwait
@@ -1868,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.
@@ -1877,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.
@@ -1893,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.
///
@@ -1973,7 +1997,7 @@ public:
}
};
-/// \brief This represents '#pragma omp flush' directive.
+/// This represents '#pragma omp flush' directive.
///
/// \code
/// #pragma omp flush(a,b)
@@ -1985,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.
@@ -1996,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.
///
@@ -2006,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.
@@ -2018,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.
@@ -2032,7 +2056,7 @@ public:
}
};
-/// \brief This represents '#pragma omp ordered' directive.
+/// This represents '#pragma omp ordered' directive.
///
/// \code
/// #pragma omp ordered
@@ -2040,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.
@@ -2051,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.
///
@@ -2061,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.
@@ -2073,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.
@@ -2086,7 +2110,7 @@ public:
}
};
-/// \brief This represents '#pragma omp atomic' directive.
+/// This represents '#pragma omp atomic' directive.
///
/// \code
/// #pragma omp atomic capture
@@ -2095,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;
@@ -2105,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>;
@@ -2115,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.
@@ -2127,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.
///
@@ -2137,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').
///
@@ -2173,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.
@@ -2182,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() {
@@ -2196,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));
@@ -2219,7 +2243,7 @@ public:
}
};
-/// \brief This represents '#pragma omp target' directive.
+/// This represents '#pragma omp target' directive.
///
/// \code
/// #pragma omp target if(a)
@@ -2229,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.
@@ -2240,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.
///
@@ -2250,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.
@@ -2262,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.
@@ -2276,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[:])
@@ -2287,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,7 +2323,7 @@ class OMPTargetDataDirective : public OMPExecutableDirective {
OMPD_target_data, StartLoc, EndLoc, NumClauses,
1) {}
- /// \brief Build an empty directive.
+ /// Build an empty directive.
///
/// \param NumClauses Number of clauses.
///
@@ -2309,7 +2333,7 @@ class OMPTargetDataDirective : 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.
@@ -2321,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.
@@ -2334,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[:])
@@ -2345,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.
@@ -2357,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.
///
@@ -2368,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.
@@ -2380,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.
@@ -2393,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[:])
@@ -2404,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.
@@ -2416,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.
///
@@ -2427,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.
@@ -2439,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.
@@ -2452,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)
@@ -2462,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.
@@ -2474,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.
///
@@ -2485,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.
@@ -2497,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.
@@ -2511,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)
@@ -2523,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.
@@ -2540,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.
@@ -2552,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.
@@ -2572,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.
@@ -2584,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) {
@@ -2592,7 +2616,7 @@ public:
}
};
-/// \brief This represents '#pragma omp teams' directive.
+/// This represents '#pragma omp teams' directive.
///
/// \code
/// #pragma omp teams if(a)
@@ -2602,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.
@@ -2613,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.
///
@@ -2623,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.
@@ -2636,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.
@@ -2650,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
@@ -2660,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.
@@ -2670,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,
@@ -2678,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.
@@ -2693,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) {
@@ -2708,7 +2732,7 @@ public:
}
};
-/// \brief This represents '#pragma omp cancel' directive.
+/// This represents '#pragma omp cancel' directive.
///
/// \code
/// #pragma omp cancel for
@@ -2718,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.
@@ -2730,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)
@@ -2739,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.
@@ -2755,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.
@@ -2763,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) {
@@ -2771,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)
@@ -2782,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.
@@ -2794,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.
@@ -2805,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.
@@ -2820,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.
@@ -2836,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)
@@ -2847,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.
@@ -2860,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.
@@ -2871,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.
@@ -2886,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.
@@ -2903,7 +2927,7 @@ public:
}
};
-/// \brief This represents '#pragma omp distribute' directive.
+/// This represents '#pragma omp distribute' directive.
///
/// \code
/// #pragma omp distribute private(a,b)
@@ -2914,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.
@@ -2927,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.
@@ -2939,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.
@@ -2954,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.
@@ -2970,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)
@@ -2981,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.
@@ -2993,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.
///
@@ -3003,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.
@@ -3015,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.
@@ -3029,7 +3053,7 @@ public:
}
};
-/// \brief This represents '#pragma omp distribute parallel for' composite
+/// This represents '#pragma omp distribute parallel for' composite
/// directive.
///
/// \code
@@ -3043,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.
@@ -3057,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.
@@ -3073,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.
@@ -3089,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.
diff --git a/include/clang/AST/StmtVisitor.h b/include/clang/AST/StmtVisitor.h
index 98fa11327406..30bc257c7e79 100644
--- a/include/clang/AST/StmtVisitor.h
+++ b/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/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h
index 850250b9c0a2..a1920253de78 100644
--- a/include/clang/AST/TemplateBase.h
+++ b/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,19 +271,19 @@ 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) &&
@@ -292,11 +292,11 @@ public:
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;
};
@@ -478,7 +478,7 @@ public:
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)
@@ -487,7 +487,7 @@ public:
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 {
@@ -588,7 +588,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 +602,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 +628,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 +636,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,
diff --git a/include/clang/AST/TemplateName.h b/include/clang/AST/TemplateName.h
index fb33cf58d796..50549e1a0a6a 100644
--- a/include/clang/AST/TemplateName.h
+++ b/include/clang/AST/TemplateName.h
@@ -39,7 +39,7 @@ 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;
};
@@ -90,7 +90,7 @@ public:
}
};
-/// \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;
@@ -112,7 +112,7 @@ 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
@@ -131,12 +131,12 @@ public:
: 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;
@@ -148,7 +148,7 @@ public:
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 {
@@ -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
@@ -474,23 +474,23 @@ class DependentTemplateName : public llvm::FoldingSetNode {
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.
+ /// 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.
+ /// Return the overloaded operator to which this template name refers.
OverloadedOperatorKind getOperator() const {
assert(isOverloadedOperator() &&
"Template name isn't an overloaded operator?");
@@ -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/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 882878bb7e1e..c692707847a6 100644
--- a/include/clang/AST/Type.h
+++ b/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
@@ -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,18 @@ 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 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 +2121,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 +2217,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 +2256,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 +2267,7 @@ public:
BuiltinTypeBits.Kind = K;
}
+public:
Kind getKind() const { return static_cast<Kind>(BuiltinTypeBits.Kind); }
StringRef getName(const PrintingPolicy &Policy) const;
@@ -2637,13 +2744,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 +2881,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
@@ -2979,6 +3086,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 +3233,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 +3259,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 +3279,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 +3322,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 +3375,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 +3528,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 +3570,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 +3625,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 +3683,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 +3723,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 +3746,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 +3758,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 +3875,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 +3946,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 +3995,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 +4018,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 +4083,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 +4210,7 @@ public:
// No operand.
attr_noreturn,
+ attr_nocf_check,
attr_cdecl,
attr_fastcall,
attr_stdcall,
@@ -4246,7 +4403,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 +4454,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 +4469,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 +4506,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 +4539,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 +4554,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 +4590,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 +4627,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 +4647,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 +4687,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 +4756,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 +4839,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 +4930,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 +4947,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 +4979,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 +5001,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 +5016,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 +5065,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 +5076,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 +5098,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 +5136,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 +5161,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 +5182,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)
@@ -5418,8 +5585,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();
@@ -5841,10 +6008,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 +6056,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 +6131,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 +6142,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 +6221,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 +6308,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 +6322,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 +6368,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 +6380,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 +6434,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;
}
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 +6457,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 +6524,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 +6540,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 +6570,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 +6586,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 +6613,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/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h
index b805160a2780..25cd014efe5f 100644
--- a/include/clang/AST/TypeLoc.h
+++ b/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,
@@ -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,
@@ -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());
@@ -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/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def
index 66697fa0d0fa..8638f94bda14 100644
--- a/include/clang/AST/TypeNodes.def
+++ b/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/include/clang/AST/TypeOrdering.h b/include/clang/AST/TypeOrdering.h
index fa64fae8824f..d29dd6d60124 100644
--- a/include/clang/AST/TypeOrdering.h
+++ b/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());
diff --git a/include/clang/AST/TypeVisitor.h b/include/clang/AST/TypeVisitor.h
index 11e5a47f1f29..75fa0ec15ce2 100644
--- a/include/clang/AST/TypeVisitor.h
+++ b/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/include/clang/AST/UnresolvedSet.h b/include/clang/AST/UnresolvedSet.h
index 614ff9bf2efd..d6b01cb57334 100644
--- a/include/clang/AST/UnresolvedSet.h
+++ b/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,7 +140,7 @@ private:
}
};
-/// \brief A set of unresolved declarations.
+/// A set of unresolved declarations.
template <unsigned InlineCapacity> class UnresolvedSet :
public UnresolvedSetImpl {
SmallVector<DeclAccessPair, InlineCapacity> Decls;
diff --git a/include/clang/AST/VTTBuilder.h b/include/clang/AST/VTTBuilder.h
index 178139477d00..84661c8cc7f2 100644
--- a/include/clang/AST/VTTBuilder.h
+++ b/include/clang/AST/VTTBuilder.h
@@ -68,48 +68,48 @@ 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
@@ -120,17 +120,17 @@ class VTTBuilder {
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,
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);
@@ -138,22 +138,22 @@ 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/include/clang/AST/VTableBuilder.h b/include/clang/AST/VTableBuilder.h
index b0b71e473516..643103916149 100644
--- a/include/clang/AST/VTableBuilder.h
+++ b/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.
@@ -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/include/clang/ASTMatchers/ASTMatchFinder.h b/include/clang/ASTMatchers/ASTMatchFinder.h
index 389af1b6e259..324c02db3fe0 100644
--- a/include/clang/ASTMatchers/ASTMatchFinder.h
+++ b/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/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
index 64e7e908d51e..58f65a39fb48 100644
--- a/include/clang/ASTMatchers/ASTMatchers.h
+++ b/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,22 @@ 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 +1667,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 +1676,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 +1691,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 +1705,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 +1715,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 +1729,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 +1743,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 +1753,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 +1763,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 +1773,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 +1784,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 +1794,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 +1805,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 +1816,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 +1829,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 +1839,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 +1889,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 +1898,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 +1908,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 +1917,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 +1927,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 +1936,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 +1946,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 +1959,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 +1976,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 +1992,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 +2015,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 +2024,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 +2033,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 +2042,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 +2052,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 +2063,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 +2079,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 +2092,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 +2108,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 +2123,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 +2134,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 +2143,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 +2167,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 +2189,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 +2200,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 +2209,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 +2218,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 +2227,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 +2242,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 +2274,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 +2301,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 +2315,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 +2328,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 +2336,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 +2344,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 +2360,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 +2377,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 +2400,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 +2428,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 +2454,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 +2468,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 +2476,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 +2493,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 +2506,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 +2526,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 +2544,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 +2565,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 +2596,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 +2617,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 +2633,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 +2650,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 +2661,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 +2670,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 +2704,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 +2723,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 +2742,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 +2757,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 +2806,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 +2836,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 +2844,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 +2856,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 +2872,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
@@ -2790,7 +2887,7 @@ 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 +2910,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 +2924,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 +2959,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 +2992,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 +3005,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 +3022,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 +3037,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 +3045,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 +3064,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 +3083,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 +3097,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 +3106,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 +3114,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 +3130,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 +3152,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 +3173,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 +3190,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 +3206,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 +3221,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 +3235,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 +3251,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 +3271,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 +3287,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 +3302,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 +3318,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 +3336,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 +3351,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 +3380,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 +3397,7 @@ AST_MATCHER(CXXCatchStmt, isCatchAll) {
return Node.getExceptionDecl() == nullptr;
}
-/// \brief Matches a constructor initializer.
+/// Matches a constructor initializer.
///
/// Given
/// \code
@@ -3310,7 +3416,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 +3436,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 +3456,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 +3473,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 +3493,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 +3513,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 +3524,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 +3547,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 +3568,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 +3579,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 +3652,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 +3665,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 +3705,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 +3717,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 +3746,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 +3766,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 +3786,7 @@ AST_POLYMORPHIC_MATCHER(isStaticStorageClass,
return Node.getStorageClass() == SC_Static;
}
-/// \brief Matches deleted function declarations.
+/// Matches deleted function declarations.
///
/// Given:
/// \code
@@ -3633,7 +3799,7 @@ AST_MATCHER(FunctionDecl, isDeleted) {
return Node.isDeleted();
}
-/// \brief Matches defaulted function declarations.
+/// Matches defaulted function declarations.
///
/// Given:
/// \code
@@ -3646,7 +3812,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 +3835,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 +3862,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 +3904,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 +3916,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 +3928,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 +3965,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 +3981,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 +3997,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 +4014,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 +4036,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 +4056,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 +4070,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 +4131,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 +4145,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 +4180,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 +4195,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 +4216,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 +4241,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 +4252,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 +4262,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 +4271,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 +4283,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 +4295,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 +4307,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 +4325,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 +4340,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 +4367,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 +4381,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 +4405,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 +4446,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 +4460,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 +4478,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 +4499,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 +4513,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 +4528,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 +4545,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 +4562,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 +4580,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 +4595,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 +4614,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 +4628,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 +4642,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 +4656,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 +4670,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 +4690,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 +4709,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 +4728,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 +4745,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 +4762,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 +4779,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 +4794,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 +4811,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 +4822,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 +4843,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 +4865,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 +4885,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 +4903,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 +4911,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 +4923,7 @@ AST_MATCHER(Type, booleanType) {
return Node.isBooleanType();
}
-/// \brief Matches type \c void.
+/// Matches type \c void.
///
/// Given
/// \code
@@ -4741,7 +4938,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 +4952,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 +4964,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 +4974,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 +4987,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 +5004,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 +5018,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 +5040,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 +5053,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 +5065,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 +5080,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 +5097,7 @@ AST_MATCHER_P(VariableArrayType, hasSizeExpr,
return InnerMatcher.matches(*Node.getSizeExpr(), Finder, Builder);
}
-/// \brief Matches atomic types.
+/// Matches atomic types.
///
/// Given
/// \code
@@ -4910,7 +5107,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 +5121,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 +5133,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 +5162,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 +5187,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 +5199,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 +5211,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 +5226,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 +5242,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 +5259,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 +5274,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 +5290,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 +5307,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 +5324,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 +5343,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 +5353,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 +5368,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 +5384,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 +5394,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 +5409,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 +5424,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 +5444,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 +5467,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 +5487,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 +5502,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 +5518,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 +5527,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 +5539,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 +5551,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 +5577,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 +5593,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 +5607,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 +5626,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 +5639,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 +5661,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 +5679,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 +5696,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 +5721,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 +5753,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 +5778,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 +5793,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 +5808,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 +5823,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 +5840,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 +5860,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 +5885,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 +5898,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 +5915,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 +5932,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 +5949,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 +5958,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 +5979,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 +6017,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,7 +6041,7 @@ 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
@@ -5828,7 +6052,7 @@ AST_MATCHER(ParmVarDecl, hasDefaultArgument) {
return Node.hasDefaultArg();
}
-/// \brief Matches array new expressions.
+/// Matches array new expressions.
///
/// Given:
/// \code
@@ -5840,7 +6064,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 +6077,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 +6088,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/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h
index 8bd61a76e185..9d9f867d053a 100644
--- a/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/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/include/clang/ASTMatchers/ASTMatchersMacros.h b/include/clang/ASTMatchers/ASTMatchersMacros.h
index 6a48da821a53..3080f86699b5 100644
--- a/include/clang/ASTMatchers/ASTMatchersMacros.h
+++ b/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/include/clang/ASTMatchers/Dynamic/Diagnostics.h b/include/clang/ASTMatchers/Dynamic/Diagnostics.h
index 908fa0db622d..ccd9590f4bb4 100644
--- a/include/clang/ASTMatchers/Dynamic/Diagnostics.h
+++ b/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/include/clang/ASTMatchers/Dynamic/Parser.h b/include/clang/ASTMatchers/Dynamic/Parser.h
index e8fcf0a9d6cc..907db69529d2 100644
--- a/include/clang/ASTMatchers/Dynamic/Parser.h
+++ b/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/include/clang/ASTMatchers/Dynamic/Registry.h b/include/clang/ASTMatchers/Dynamic/Registry.h
index 277491250db8..ad8628b4b0d9 100644
--- a/include/clang/ASTMatchers/Dynamic/Registry.h
+++ b/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/include/clang/ASTMatchers/Dynamic/VariantValue.h b/include/clang/ASTMatchers/Dynamic/VariantValue.h
index f9efe0f16f43..45ac3cadf685 100644
--- a/include/clang/ASTMatchers/Dynamic/VariantValue.h
+++ b/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/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h b/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h
index cc14c7bd33db..da59514c4fa6 100644
--- a/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h
+++ b/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
//
@@ -30,10 +30,12 @@ class CFGBlock;
// 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);
@@ -44,6 +46,6 @@ private:
void mapReachability(const CFGBlock *Dst);
};
-}
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_ANALYSIS_ANALYSES_CFGREACHABILITYANALYSIS_H
diff --git a/include/clang/Analysis/Analyses/Consumed.h b/include/clang/Analysis/Analyses/Consumed.h
index 5ba42b475c83..6003d665fd88 100644
--- a/include/clang/Analysis/Analyses/Consumed.h
+++ b/include/clang/Analysis/Analyses/Consumed.h
@@ -1,4 +1,4 @@
-//===- Consumed.h ----------------------------------------------*- C++ --*-===//
+//===- Consumed.h -----------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,16 +15,32 @@
#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,
@@ -34,22 +50,18 @@ namespace consumed {
CS_Consumed
};
- class ConsumedStmtVisitor;
-
- typedef SmallVector<PartialDiagnosticAt, 1> OptionalNotes;
- typedef std::pair<PartialDiagnosticAt, OptionalNotes> DelayedDiag;
- typedef std::list<DelayedDiag> DiagList;
+ 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.
@@ -59,7 +71,7 @@ namespace consumed {
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.
///
@@ -80,7 +92,7 @@ namespace consumed {
// 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.
///
@@ -88,7 +100,7 @@ namespace consumed {
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,66 +141,64 @@ 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() {}
+ : Reachable(Other.Reachable), From(Other.From), VarMap(Other.VarMap),
+ TmpMap() {}
- /// \brief Warn if any of the parameters being tracked are not in the state
+ /// 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.
@@ -205,10 +215,8 @@ namespace consumed {
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,
@@ -231,7 +239,6 @@ namespace consumed {
/// A class that handles the analysis of uniqueness violations.
class ConsumedAnalyzer {
-
ConsumedBlockInfo BlockInfo;
std::unique_ptr<ConsumedStateMap> CurrStates;
@@ -243,7 +250,6 @@ namespace consumed {
const ConsumedStmtVisitor &Visitor);
public:
-
ConsumedWarningsHandlerBase &WarningsHandler;
ConsumedAnalyzer(ConsumedWarningsHandlerBase &WarningsHandler)
@@ -251,7 +257,7 @@ namespace consumed {
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/include/clang/Analysis/Analyses/Dominators.h b/include/clang/Analysis/Analyses/Dominators.h
index 6cb161ab37c8..a9cdc5560bc0 100644
--- a/include/clang/Analysis/Analyses/Dominators.h
+++ b/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/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/include/clang/Analysis/Analyses/FormatString.h b/include/clang/Analysis/Analyses/FormatString.h
index 8c531d638cc2..6f8bb9b4095f 100644
--- a/include/clang/Analysis/Analyses/FormatString.h
+++ b/include/clang/Analysis/Analyses/FormatString.h
@@ -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/include/clang/Analysis/Analyses/LiveVariables.h b/include/clang/Analysis/Analyses/LiveVariables.h
index 6a1222386bae..21c3ba255c36 100644
--- a/include/clang/Analysis/Analyses/LiveVariables.h
+++ b/include/clang/Analysis/Analyses/LiveVariables.h
@@ -33,15 +33,18 @@ 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;
diff --git a/include/clang/Analysis/Analyses/PostOrderCFGView.h b/include/clang/Analysis/Analyses/PostOrderCFGView.h
index c0a93528373e..7df3dc66c311 100644
--- a/include/clang/Analysis/Analyses/PostOrderCFGView.h
+++ b/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/include/clang/Analysis/Analyses/ThreadSafety.h b/include/clang/Analysis/Analyses/ThreadSafety.h
index 7e403b1f4090..c72db6f2b24b 100644
--- a/include/clang/Analysis/Analyses/ThreadSafety.h
+++ b/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/include/clang/Analysis/Analyses/ThreadSafetyCommon.h b/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
index 414645b7231b..580872e17ef4 100644
--- a/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
+++ b/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/include/clang/Analysis/Analyses/ThreadSafetyLogical.h b/include/clang/Analysis/Analyses/ThreadSafetyLogical.h
index bc78021343a4..2508af1af107 100644
--- a/include/clang/Analysis/Analyses/ThreadSafetyLogical.h
+++ b/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/include/clang/Analysis/Analyses/ThreadSafetyTIL.h b/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
index 0a58d2a80250..810f2052b7a5 100644
--- a/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
+++ b/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/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h b/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
index 705fe910d092..49031010a75b 100644
--- a/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
+++ b/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/include/clang/Analysis/Analyses/ThreadSafetyUtil.h b/include/clang/Analysis/Analyses/ThreadSafetyUtil.h
index cb80ce5da8d2..16583939d542 100644
--- a/include/clang/Analysis/Analyses/ThreadSafetyUtil.h
+++ b/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/include/clang/Analysis/Analyses/UninitializedValues.h b/include/clang/Analysis/Analyses/UninitializedValues.h
index 53ff20c23560..79d89e0633fd 100644
--- a/include/clang/Analysis/Analyses/UninitializedValues.h
+++ b/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/include/clang/Analysis/AnalysisDeclContext.h b/include/clang/Analysis/AnalysisDeclContext.h
index 03ff4a9516da..8c391b5ee1e5 100644
--- a/include/clang/Analysis/AnalysisDeclContext.h
+++ b/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,
@@ -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);
@@ -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,20 +356,20 @@ 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; }
@@ -379,6 +391,7 @@ public:
class LocationContextManager {
llvm::FoldingSet<LocationContext> Contexts;
+
public:
~LocationContextManager();
@@ -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);
@@ -488,5 +505,6 @@ private:
}
};
-} // end clang namespace
-#endif
+} // namespace clang
+
+#endif // LLVM_CLANG_ANALYSIS_ANALYSISDECLCONTEXT_H
diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h
index cfedb2aa8ed5..f25789822d16 100644
--- a/include/clang/Analysis/CFG.h
+++ b/include/clang/Analysis/CFG.h
@@ -15,8 +15,9 @@
#ifndef LLVM_CLANG_ANALYSIS_CFG_H
#define LLVM_CLANG_ANALYSIS_CFG_H
-#include "clang/AST/Stmt.h"
+#include "clang/AST/ExprCXX.h"
#include "clang/Analysis/Support/BumpVector.h"
+#include "clang/Analysis/ConstructionContext.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/GraphTraits.h"
@@ -55,11 +56,18 @@ 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 +92,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 +103,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 +125,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,10 +136,77 @@ public:
private:
friend class CFGElement;
+ static bool isKind(const CFGElement &E) {
+ return E.getKind() >= STMT_BEGIN && E.getKind() <= STMT_END;
+ }
+
+protected:
CFGStmt() = default;
+};
+
+/// CFGConstructor - 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() == Constructor;
+ }
+};
+
+/// CFGCXXRecordTypedCall - 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(CallExpr *CE, const ASTContext &ACtx) {
+ return CE->getCallReturnType(ACtx).getCanonicalType()->getAsCXXRecordDecl();
+ }
+
+ explicit CFGCXXRecordTypedCall(CallExpr *CE, const ConstructionContext *C)
+ : CFGStmt(CE, CXXRecordTypedCall) {
+ // FIXME: This is not protected against squeezing a non-record-typed-call
+ // into the constructor. An assertion would require passing an ASTContext
+ // which would mean paying for something we don't use.
+ 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)));
+ 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() == Statement;
+ return E.getKind() == CXXRecordTypedCall;
}
};
@@ -137,7 +214,7 @@ private:
/// constructor's initialization list.
class CFGInitializer : public CFGElement {
public:
- CFGInitializer(CXXCtorInitializer *initializer)
+ explicit CFGInitializer(CXXCtorInitializer *initializer)
: CFGElement(Initializer, initializer) {}
CXXCtorInitializer* getInitializer() const {
@@ -223,6 +300,55 @@ private:
}
};
+/// 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;
+ }
+};
+
/// CFGImplicitDtor - Represents C++ object destructor implicitly generated
/// by compiler on various occasions.
class CFGImplicitDtor : public CFGElement {
@@ -747,6 +873,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(CallExpr *CE,
+ const ConstructionContext *CC,
+ BumpVectorContext &C) {
+ Elements.push_back(CFGCXXRecordTypedCall(CE, CC), C);
+ }
+
void appendInitializer(CXXCtorInitializer *initializer,
BumpVectorContext &C) {
Elements.push_back(CFGInitializer(initializer), C);
@@ -757,6 +894,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 +965,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:
@@ -852,9 +1020,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;
diff --git a/include/clang/Analysis/CallGraph.h b/include/clang/Analysis/CallGraph.h
index bdcdfecddc3e..ae0f392ed969 100644
--- a/include/clang/Analysis/CallGraph.h
+++ b/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/include/clang/Analysis/CloneDetection.h b/include/clang/Analysis/CloneDetection.h
index 051b9236658c..955777a11a65 100644
--- a/include/clang/Analysis/CloneDetection.h
+++ b/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 {
@@ -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/include/clang/Analysis/CodeInjector.h b/include/clang/Analysis/CodeInjector.h
index 413a55b05b07..2c87cde996f2 100644
--- a/include/clang/Analysis/CodeInjector.h
+++ b/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/include/clang/Analysis/ConstructionContext.h b/include/clang/Analysis/ConstructionContext.h
new file mode 100644
index 000000000000..40cb0e7e5dda
--- /dev/null
+++ b/include/clang/Analysis/ConstructionContext.h
@@ -0,0 +1,474 @@
+//===- 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 {
+
+/// Construction context is a linked list of multiple layers. 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 {
+public:
+ typedef llvm::PointerUnion<Stmt *, CXXCtorInitializer *> TriggerTy;
+
+private:
+ /// 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).
+ TriggerTy Trigger;
+
+ /// Sometimes a single trigger is not enough to describe the construction
+ /// site. In this case we'd 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.
+ const ConstructionContextLayer *Parent = nullptr;
+
+ ConstructionContextLayer(TriggerTy Trigger,
+ const ConstructionContextLayer *Parent)
+ : Trigger(Trigger), Parent(Parent) {}
+
+public:
+ static const ConstructionContextLayer *
+ create(BumpVectorContext &C, TriggerTy Trigger,
+ const ConstructionContextLayer *Parent = nullptr);
+
+ const ConstructionContextLayer *getParent() const { return Parent; }
+ bool isLast() const { return !Parent; }
+
+ const Stmt *getTriggerStmt() const {
+ return Trigger.dyn_cast<Stmt *>();
+ }
+
+ const CXXCtorInitializer *getTriggerInit() const {
+ return Trigger.dyn_cast<CXXCtorInitializer *>();
+ }
+
+ /// Returns true if these layers are equal as individual layers, even if
+ /// their parents are different.
+ bool isSameLayer(const ConstructionContextLayer *Other) const {
+ assert(Other);
+ return (Trigger == Other->Trigger);
+ }
+
+ /// 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
+ };
+
+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...);
+ }
+
+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;
+ }
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H
diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h
index 2d59dec48a88..e8f0d61617eb 100644
--- a/include/clang/Analysis/ProgramPoint.h
+++ b/include/clang/Analysis/ProgramPoint.h
@@ -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,
@@ -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;
@@ -233,7 +238,7 @@ public:
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,7 +346,7 @@ 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) {}
@@ -362,7 +367,7 @@ public:
private:
friend class ProgramPoint;
- PreLoad() {}
+ PreLoad() = default;
static bool isKind(const ProgramPoint &location) {
return location.getKind() == PreLoadKind;
}
@@ -376,7 +381,7 @@ public:
private:
friend class ProgramPoint;
- PreStore() {}
+ PreStore() = default;
static bool isKind(const ProgramPoint &location) {
return location.getKind() == PreStoreKind;
}
@@ -390,13 +395,13 @@ 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.
@@ -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;
}
@@ -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,12 +579,26 @@ 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 {
@@ -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;
}
diff --git a/include/clang/Basic/ABI.h b/include/clang/Basic/ABI.h
index 75e9faf4617e..bd919ce24f81 100644
--- a/include/clang/Basic/ABI.h
+++ b/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;
@@ -104,31 +104,31 @@ struct ReturnAdjustment {
}
};
-/// \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;
@@ -174,16 +174,16 @@ struct ThisAdjustment {
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
diff --git a/include/clang/Basic/AddressSpaces.h b/include/clang/Basic/AddressSpaces.h
index 6b0090813e9b..217fbd763ff2 100644
--- a/include/clang/Basic/AddressSpaces.h
+++ b/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/include/clang/Basic/AlignedAllocation.h b/include/clang/Basic/AlignedAllocation.h
index b3496949f39a..9751f4118447 100644
--- a/include/clang/Basic/AlignedAllocation.h
+++ b/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/include/clang/Basic/AllDiagnostics.h b/include/clang/Basic/AllDiagnostics.h
index 1c83e2d0f8a0..20c29d459d22 100644
--- a/include/clang/Basic/AllDiagnostics.h
+++ b/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.
///
//===----------------------------------------------------------------------===//
diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td
index 8b84c4b8b50d..0bbe52bf5f36 100644
--- a/include/clang/Basic/Attr.td
+++ b/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,
@@ -162,6 +168,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 +185,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 +245,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 +308,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,9 +456,6 @@ 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
// in a class template definition.
bit MeaningfulToClassTemplateDefinition = 0;
@@ -475,7 +490,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 +511,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
@@ -584,6 +608,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">];
@@ -598,6 +628,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];
}
@@ -660,9 +696,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">,
@@ -706,7 +740,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];
}
@@ -739,7 +773,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];
@@ -813,6 +847,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 {
@@ -1007,7 +1062,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];
}
@@ -1039,14 +1095,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];
}
@@ -1094,7 +1150,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];
}
@@ -1155,6 +1211,15 @@ def LayoutVersion : InheritableAttr, TargetSpecificAttr<TargetMicrosoftCXXABI> {
let Documentation = [LayoutVersionDocs];
}
+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 = [];
@@ -1169,7 +1234,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];
@@ -1310,6 +1375,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.
//
@@ -1328,28 +1404,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">;
@@ -1365,18 +1441,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];
}
@@ -1432,7 +1508,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];
}
@@ -1454,6 +1530,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]>;
@@ -1483,13 +1565,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];
}
@@ -1643,7 +1723,8 @@ def Ownership : InheritableAttr {
Returns;
}
}];
- let Args = [IdentifierArgument<"Module">, VariadicUnsignedArgument<"Args">];
+ let Args = [IdentifierArgument<"Module">,
+ VariadicParamIdxArgument<"Args">];
let Subjects = SubjectList<[HasFunctionProto]>;
let Documentation = [Undocumented];
}
@@ -1654,13 +1735,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"],
@@ -1690,7 +1771,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];
@@ -1721,6 +1804,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 = [];
@@ -1761,13 +1851,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];
@@ -1794,38 +1884,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];
}
@@ -1840,12 +1930,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, ",");
@@ -1861,7 +1966,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=")) {
@@ -1879,6 +1984,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]>;
@@ -1913,7 +2025,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; }
@@ -1958,6 +2070,7 @@ def Unused : InheritableAttr {
def Used : InheritableAttr {
let Spellings = [GCC<"used">];
+ let Subjects = SubjectList<[NonLocalVar, Function, ObjCMethod]>;
let Documentation = [Undocumented];
}
@@ -2006,7 +2119,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];
}
@@ -2066,6 +2182,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
@@ -2112,13 +2234,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];
}
@@ -2131,17 +2253,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"); }
@@ -2150,83 +2272,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];
}
@@ -2242,7 +2364,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];
}
@@ -2253,7 +2375,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];
}
@@ -2264,7 +2386,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];
}
@@ -2275,7 +2397,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];
}
@@ -2286,7 +2408,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];
}
@@ -2297,7 +2419,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];
}
@@ -2310,7 +2432,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];
}
@@ -2323,7 +2445,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];
}
@@ -2344,7 +2466,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];
}
@@ -2352,7 +2474,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"],
@@ -2361,19 +2486,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"],
@@ -2382,7 +2516,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"],
@@ -2391,7 +2528,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"],
@@ -2400,7 +2540,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"],
@@ -2409,7 +2552,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"],
@@ -2420,18 +2566,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">,
@@ -2469,6 +2615,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 {
@@ -2510,7 +2666,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">,
@@ -2565,7 +2721,7 @@ def InitSeg : Attr {
let Documentation = [InitSegDocs];
let AdditionalMembers = [{
void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {
- OS << '(' << getSection() << ')';
+ OS << " (" << getSection() << ')';
}
}];
}
@@ -2575,7 +2731,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
@@ -2620,12 +2776,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
@@ -2693,6 +2849,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]>;
@@ -2712,37 +2876,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);
@@ -2752,7 +2916,7 @@ def OMPDeclareSimdDecl : Attr {
OS << ": ";
(*I)->printPretty(OS, nullptr, Policy);
}
- OS << ") ";
+ OS << ")";
++I;
++MI;
}
@@ -2773,7 +2937,7 @@ 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());
}
}];
}
diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td
index ecff329c4ccb..5a5ab78b49d1 100644
--- a/include/clang/Basic/AttrDocs.td
+++ b/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.
}];
@@ -353,7 +424,7 @@ available in C.
int isdigit(int c);
int isdigit(int c) __attribute__((enable_if(c <= -1 || c > 255, "chosen when 'c' is out of range"))) __attribute__((unavailable("'c' must have the value of an unsigned char or EOF")));
-
+
void foo(char c) {
isdigit(c);
isdigit(10);
@@ -406,7 +477,7 @@ overload out of a number of viable overloads using enable_if.
void f() __attribute__((enable_if(true, ""))); // #1
void f() __attribute__((enable_if(true, ""))) __attribute__((enable_if(true, ""))); // #2
-
+
void g(int i, int j) __attribute__((enable_if(i, ""))); // #1
void g(int i, int j) __attribute__((enable_if(j, ""))) __attribute__((enable_if(true))); // #2
@@ -913,16 +984,16 @@ in the metadata name for that object. The `objc_runtime_name`
attribute allows annotated interfaces or protocols to use the
specified string argument in the object's metadata name instead of the
default name.
-
+
**Usage**: ``__attribute__((objc_runtime_name("MyLocalName")))``. This attribute
can only be placed before an @protocol or @interface declaration:
-
+
.. code-block:: objc
-
+
__attribute__((objc_runtime_name("MyLocalName")))
@interface Message
@end
-
+
}];
}
@@ -1228,7 +1299,7 @@ potentially-evaluated discarded-value expression that is not explicitly cast to
.. code-block: c++
struct [[nodiscard]] error_info { /*...*/ };
error_info enable_missile_safety_mode();
-
+
void launch_missiles();
void test_missiles() {
enable_missile_safety_mode(); // diagnoses
@@ -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,48 @@ It is only supported when using the Microsoft C++ ABI.
}];
}
+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 +2745,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.
}];
}
@@ -2641,23 +2821,23 @@ used to process multiple arguments from a single invocation from a SIMD loop
concurrently.
The syntax of the `declare simd` construct is as follows:
- .. code-block:: c
+ .. code-block:: none
- #pragma omp declare simd [clause[[,] clause] ...] new-line
- [#pragma omp declare simd [clause[[,] clause] ...] new-line]
- [...]
- function definition or declaration
+ #pragma omp declare simd [clause[[,] clause] ...] new-line
+ [#pragma omp declare simd [clause[[,] clause] ...] new-line]
+ [...]
+ function definition or declaration
where clause is one of the following:
- .. code-block:: c
+ .. code-block:: none
- simdlen(length)
- linear(argument-list[:constant-linear-step])
- aligned(argument-list[:alignment])
- uniform(argument-list)
- inbranch
- notinbranch
+ simdlen(length)
+ linear(argument-list[:constant-linear-step])
+ aligned(argument-list[:alignment])
+ uniform(argument-list)
+ inbranch
+ notinbranch
}];
}
@@ -2673,12 +2853,34 @@ The syntax of the declare target directive is as follows:
.. code-block:: c
- #pragma omp declare target new-line
- declarations-definition-seq
- #pragma omp end declare target new-line
+ #pragma omp declare target new-line
+ declarations-definition-seq
+ #pragma omp end declare target new-line
}];
}
+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 +2939,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 +3002,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 +3054,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 +3250,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 +3432,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/include/clang/Basic/AttrKinds.h b/include/clang/Basic/AttrKinds.h
index 8f7394f59d4d..d82dbb032be9 100644
--- a/include/clang/Basic/AttrKinds.h
+++ b/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/include/clang/Basic/AttrSubjectMatchRules.h b/include/clang/Basic/AttrSubjectMatchRules.h
index 4c88adf57f17..81aa634dfeb8 100644
--- a/include/clang/Basic/AttrSubjectMatchRules.h
+++ b/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/include/clang/Basic/Attributes.h b/include/clang/Basic/Attributes.h
index c651abacd482..3152453694c9 100644
--- a/include/clang/Basic/Attributes.h
+++ b/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/include/clang/Basic/BitmaskEnum.h b/include/clang/Basic/BitmaskEnum.h
new file mode 100644
index 000000000000..12ff3cf207be
--- /dev/null
+++ b/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/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def
index 3d4deb5ed306..edd823754a37 100644
--- a/include/clang/Basic/Builtins.def
+++ b/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)
@@ -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/include/clang/Basic/Builtins.h b/include/clang/Basic/Builtins.h
index 963c72ea82e0..fa2bcc4c7ab0 100644
--- a/include/clang/Basic/Builtins.h
+++ b/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/include/clang/Basic/BuiltinsAArch64.def b/include/clang/Basic/BuiltinsAArch64.def
index 55a4f70176d0..b5d971d0bc6e 100644
--- a/include/clang/Basic/BuiltinsAArch64.def
+++ b/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/include/clang/Basic/BuiltinsAMDGPU.def b/include/clang/Basic/BuiltinsAMDGPU.def
index ec6a0fb91765..46cd738ae43f 100644
--- a/include/clang/Basic/BuiltinsAMDGPU.def
+++ b/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, "fV2hV2hf", "nc", "dl-insts")
+TARGET_BUILTIN(__builtin_amdgcn_sdot2, "SiV2SsV2SsSi", "nc", "dl-insts")
+TARGET_BUILTIN(__builtin_amdgcn_udot2, "UiV2UsV2UsUi", "nc", "dl-insts")
+TARGET_BUILTIN(__builtin_amdgcn_sdot4, "SiSiSiSi", "nc", "dl-insts")
+TARGET_BUILTIN(__builtin_amdgcn_udot4, "UiUiUiUi", "nc", "dl-insts")
+TARGET_BUILTIN(__builtin_amdgcn_sdot8, "SiSiSiSi", "nc", "dl-insts")
+TARGET_BUILTIN(__builtin_amdgcn_udot8, "UiUiUiUi", "nc", "dl-insts")
+
+//===----------------------------------------------------------------------===//
// Special builtins.
//===----------------------------------------------------------------------===//
BUILTIN(__builtin_amdgcn_read_exec, "LUi", "nc")
diff --git a/include/clang/Basic/BuiltinsHexagon.def b/include/clang/Basic/BuiltinsHexagon.def
index fda50b53589b..f976720d116d 100644
--- a/include/clang/Basic/BuiltinsHexagon.def
+++ b/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/include/clang/Basic/BuiltinsNEON.def b/include/clang/Basic/BuiltinsNEON.def
index 7800ae69c4c9..241b93a915a9 100644
--- a/include/clang/Basic/BuiltinsNEON.def
+++ b/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/include/clang/Basic/BuiltinsNVPTX.def b/include/clang/Basic/BuiltinsNVPTX.def
index 7bab73a3b110..08c60979779b 100644
--- a/include/clang/Basic/BuiltinsNVPTX.def
+++ b/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/include/clang/Basic/BuiltinsPPC.def b/include/clang/Basic/BuiltinsPPC.def
index faa70a48edc3..8cd8a2be2003 100644
--- a/include/clang/Basic/BuiltinsPPC.def
+++ b/include/clang/Basic/BuiltinsPPC.def
@@ -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/include/clang/Basic/BuiltinsWebAssembly.def b/include/clang/Basic/BuiltinsWebAssembly.def
index 19318dcebb9e..b3d877dcedf3 100644
--- a/include/clang/Basic/BuiltinsWebAssembly.def
+++ b/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/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def
index 465551be7742..e98f7d612c3c 100644
--- a/include/clang/Basic/BuiltinsX86.def
+++ b/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, "V4iV4iV4iiV4iUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdd256_mask, "V8iV8iV8iiV8iUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdd512_mask, "V16iV16iV16iiV16iUs", "", "avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdq128_mask, "V2LLiV2LLiV2LLiiV2LLiUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdq256_mask, "V4LLiV4LLiV4LLiiV4LLiUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdq512_mask, "V8LLiV8LLiV8LLiiV8LLiUc", "", "avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdw128_mask, "V8sV8sV8siV8sUc", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdw256_mask, "V16sV16sV16siV16sUs", "", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdw512_mask, "V32sV32sV32siV32sUi", "", "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/include/clang/Basic/BuiltinsX86_64.def b/include/clang/Basic/BuiltinsX86_64.def
index fe2c887c7e0f..cc400c0697f9 100644
--- a/include/clang/Basic/BuiltinsX86_64.def
+++ b/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/include/clang/Basic/CMakeLists.txt b/include/clang/Basic/CMakeLists.txt
index 821c405913c8..15bed5adec9e 100644
--- a/include/clang/Basic/CMakeLists.txt
+++ b/include/clang/Basic/CMakeLists.txt
@@ -43,6 +43,8 @@ clang_tablegen(AttrHasAttributeImpl.inc -gen-clang-attr-has-attribute-impl
# ARM NEON
clang_tablegen(arm_neon.inc -gen-arm-neon-sema
- -I ${CMAKE_CURRENT_SOURCE_DIR}/../../
SOURCE arm_neon.td
TARGET ClangARMNeon)
+clang_tablegen(arm_fp16.inc -gen-arm-neon-sema
+ SOURCE arm_fp16.td
+ TARGET ClangARMFP16)
diff --git a/include/clang/Basic/CapturedStmt.h b/include/clang/Basic/CapturedStmt.h
index c4a289b696dd..324e1b1d3d09 100644
--- a/include/clang/Basic/CapturedStmt.h
+++ b/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/include/clang/Basic/CharInfo.h b/include/clang/Basic/CharInfo.h
index cc27bbb48e0d..e6c5e90d346c 100644
--- a/include/clang/Basic/CharInfo.h
+++ b/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/include/clang/Basic/CommentOptions.h b/include/clang/Basic/CommentOptions.h
index 92419f91b741..6cc9cf6b199c 100644
--- a/include/clang/Basic/CommentOptions.h
+++ b/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/include/clang/Basic/Cuda.h b/include/clang/Basic/Cuda.h
index 1a0731c37a35..24159e160f3f 100644
--- a/include/clang/Basic/Cuda.h
+++ b/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/include/clang/Basic/DebugInfoOptions.h b/include/clang/Basic/DebugInfoOptions.h
index e7ff4a662b63..037c813c6114 100644
--- a/include/clang/Basic/DebugInfoOptions.h
+++ b/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/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h
index a7458d45618e..5205b4c210a6 100644
--- a/include/clang/Basic/Diagnostic.h
+++ b/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,
@@ -98,7 +100,7 @@ public:
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;
@@ -122,7 +124,7 @@ public:
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) {
@@ -138,7 +140,7 @@ public:
}
};
-/// \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,7 +626,7 @@ 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) {
@@ -550,22 +634,22 @@ public:
}
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.
@@ -574,7 +658,7 @@ public:
}
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,14 +745,14 @@ 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;
}
@@ -679,7 +763,7 @@ public:
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,13 +793,13 @@ 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();
@@ -723,7 +807,7 @@ public:
// 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
@@ -790,38 +876,39 @@ public:
void SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1 = "",
StringRef Arg2 = "");
- /// \brief Clear out the current diagnostic.
- void Clear() { CurDiagID = ~0U; }
+ /// Clear out the current diagnostic.
+ void Clear() { CurDiagID = std::numeric_limits<unsigned>::max(); }
- /// \brief Return the value associated with this diagnostic flag.
+ /// 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;
+ friend class DiagnosticIDs;
+ friend class PartialDiagnostic;
- /// \brief The location of the current diagnostic that is in flight.
+ /// 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.
@@ -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,20 +1417,20 @@ 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
+ * Represents a diagnostic in a form that can be retained until its
* corresponding source manager is destroyed.
*/
class StoredDiagnostic {
@@ -1363,7 +1451,7 @@ public:
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,7 +1461,8 @@ 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(); }
@@ -1382,7 +1471,8 @@ public:
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(); }
@@ -1392,7 +1482,7 @@ public:
}
};
-/// \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:
@@ -1401,14 +1491,13 @@ protected:
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
@@ -1422,25 +1511,25 @@ public:
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/include/clang/Basic/Diagnostic.td b/include/clang/Basic/Diagnostic.td
index 52ccf350e651..2a0f1e6385d3 100644
--- a/include/clang/Basic/Diagnostic.td
+++ b/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/include/clang/Basic/DiagnosticASTKinds.td b/include/clang/Basic/DiagnosticASTKinds.td
index 215580b2e9b6..4fa1db96cb89 100644
--- a/include/clang/Basic/DiagnosticASTKinds.td
+++ b/include/clang/Basic/DiagnosticASTKinds.td
@@ -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/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td
index 82ca27b7345e..61a73541d0b3 100644
--- a/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/include/clang/Basic/DiagnosticCommonKinds.td
@@ -94,6 +94,9 @@ 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_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<
@@ -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;
@@ -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/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td
index 41b5e42b4432..a6be0595e1ae 100644
--- a/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/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<
@@ -112,6 +119,18 @@ def err_drv_invalid_argument_to_fdebug_prefix_map : Error<
"invalid argument '%0' to -fdebug-prefix-map">;
def err_drv_malformed_sanitizer_blacklist : Error<
"malformed sanitizer blacklist: '%0'">;
+def err_drv_duplicate_config : Error<
+ "no more than one option '--config' is allowed">;
+def err_drv_config_file_not_exist : Error<
+ "configuration file '%0' does not exist">;
+def err_drv_config_file_not_found : Error<
+ "configuration file '%0' cannot be found">;
+def note_drv_config_file_searched_in : Note<
+ "was searched for in the directory: %0">;
+def err_drv_cannot_read_config_file : Error<
+ "cannot read configuration file '%0'">;
+def err_drv_nested_config_file: Error<
+ "option '--config' is not allowed inside configuration file">;
def err_target_unsupported_arch
: Error<"the target architecture '%0' is not supported by the target '%1'">;
@@ -123,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">,
@@ -169,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<
@@ -184,6 +210,9 @@ def err_drv_expecting_fopenmp_with_fopenmp_targets : Error<
def warn_drv_omp_offload_target_duplicate : Warning<
"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">;
@@ -239,15 +268,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">;
@@ -266,6 +292,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 "
@@ -310,10 +339,16 @@ 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<
+ "unknown '-mindirect-jump=' option '%0'">;
def warn_drv_unable_to_find_directory_expected : Warning<
"unable to find %0 directory, expected to be in '%1'">,
@@ -342,4 +377,16 @@ def warn_drv_fine_grained_bitfield_accesses_ignored : Warning<
def note_drv_verify_prefix_spelling : Note<
"-verify prefixes must start with a letter and contain only alphanumeric"
" characters, hyphens, and underscores">;
+
+def warn_drv_experimental_isel_incomplete : Warning<
+ "-fexperimental-isel support for the '%0' architecture is incomplete">,
+ InGroup<ExperimentalISel>;
+
+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/include/clang/Basic/DiagnosticError.h b/include/clang/Basic/DiagnosticError.h
index 6b4b073736a8..3f7be46c9505 100644
--- a/include/clang/Basic/DiagnosticError.h
+++ b/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/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td
index b25181f25658..6add448871fe 100644
--- a/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -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">,
@@ -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/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index c23183c81ac8..7087db7f0fb8 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/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">;
@@ -116,6 +120,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 +129,7 @@ def Deprecated : DiagGroup<"deprecated", [DeprecatedAttributes,
DeprecatedDynamicExceptionSpec,
DeprecatedIncrementBool,
DeprecatedRegister,
+ DeprecatedThisCapture,
DeprecatedWritableStr]>,
DiagCategory<"Deprecations">;
@@ -151,8 +157,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 +204,7 @@ def CXX98Compat : DiagGroup<"c++98-compat",
def CXX98CompatPedantic : DiagGroup<"c++98-compat-pedantic",
[CXX98Compat,
CXX98CompatBindToTemporaryCopy,
+ CXX98CompatExtraSemi,
CXXPre14CompatPedantic,
CXXPre17CompatPedantic,
CXXPre2aCompatPedantic]>;
@@ -263,6 +272,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">;
@@ -282,6 +296,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",
@@ -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">;
@@ -435,13 +462,16 @@ def StringCompare : DiagGroup<"string-compare">;
def StringPlusInt : DiagGroup<"string-plus-int">;
def StringPlusChar : DiagGroup<"string-plus-char">;
def StrncatSize : DiagGroup<"strncat-size">;
+def TautologicalTypeLimitCompare : DiagGroup<"tautological-type-limit-compare">;
def TautologicalUnsignedZeroCompare : DiagGroup<"tautological-unsigned-zero-compare">;
def TautologicalUnsignedEnumZeroCompare : DiagGroup<"tautological-unsigned-enum-zero-compare">;
+def TautologicalInRangeCompare : DiagGroup<"tautological-constant-in-range-compare",
+ [TautologicalTypeLimitCompare,
+ TautologicalUnsignedZeroCompare,
+ TautologicalUnsignedEnumZeroCompare]>;
def TautologicalOutOfRangeCompare : DiagGroup<"tautological-constant-out-of-range-compare">;
def TautologicalConstantCompare : DiagGroup<"tautological-constant-compare",
- [TautologicalUnsignedZeroCompare,
- TautologicalUnsignedEnumZeroCompare,
- TautologicalOutOfRangeCompare]>;
+ [TautologicalOutOfRangeCompare]>;
def TautologicalPointerCompare : DiagGroup<"tautological-pointer-compare">;
def TautologicalOverlapCompare : DiagGroup<"tautological-overlap-compare">;
def TautologicalUndefinedCompare : DiagGroup<"tautological-undefined-compare">;
@@ -509,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]>;
@@ -712,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,
@@ -982,3 +1022,10 @@ def UnknownArgument : DiagGroup<"unknown-argument">;
// A warning group for warnings about code that clang accepts when
// compiling OpenCL C/C++ but which is not compatible with the SPIR spec.
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/include/clang/Basic/DiagnosticIDs.h b/include/clang/Basic/DiagnosticIDs.h
index b4ea85ba853c..b610af953fba 100644
--- a/include/clang/Basic/DiagnosticIDs.h
+++ b/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
@@ -225,53 +225,53 @@ public:
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
/// 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.,
/// 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,30 +281,30 @@ 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
@@ -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/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td
index c391470cb1c8..b5b5e8f654bc 100644
--- a/include/clang/Basic/DiagnosticLexKinds.td
+++ b/include/clang/Basic/DiagnosticLexKinds.td
@@ -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'">,
@@ -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,6 +722,14 @@ 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;
diff --git a/include/clang/Basic/DiagnosticOptions.h b/include/clang/Basic/DiagnosticOptions.h
index 3844eb63f0ea..391e252eaddd 100644
--- a/include/clang/Basic/DiagnosticOptions.h
+++ b/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/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index 7936cdd96f80..dd4c81922592 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/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|"
@@ -173,6 +173,9 @@ def warn_attribute_on_function_definition : Warning<
def warn_gcc_attribute_location : Warning<
"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">,
InGroup<IgnoredAttributes>;
@@ -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<
@@ -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<
@@ -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">,
@@ -973,6 +995,12 @@ def warn_pragma_init_seg_unsupported_target : Warning<
def err_pragma_fp_contract_scope : Error<
"'#pragma fp_contract' can only appear at file scope or at the start of a "
"compound statement">;
+// - #pragma 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/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 01e819942f68..d0a2bec78052 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/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">;
@@ -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;
@@ -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,11 +625,18 @@ 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<
@@ -645,7 +665,19 @@ 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 "
"buffer overflow">, InGroup<StrncatSize>;
@@ -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>;
@@ -759,6 +791,10 @@ def warn_cxx_ms_struct :
Warning<"ms_struct may not produce Microsoft-compatible layouts for classes "
"with base classes or virtual functions">,
DefaultError, InGroup<IncompatibleMSStruct>;
+def warn_npot_ms_struct :
+ Warning<"ms_struct may not produce Microsoft-compatible layouts with fundamental "
+ "data types with sizes that aren't a power of two">,
+ DefaultError, InGroup<IncompatibleMSStruct>;
def err_section_conflict : Error<"%0 causes a section type conflict with %1">;
def err_no_base_classes : Error<"invalid use of '__super', %0 has no base classes">;
def err_invalid_super_scope : Error<"invalid use of '__super', "
@@ -1027,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">,
@@ -1325,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|"
@@ -1582,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<
@@ -1589,24 +1627,35 @@ def err_non_virtual_pure : Error<
def ext_pure_function_definition : ExtWarn<
"function definition with pure-specifier is a Microsoft extension">,
InGroup<MicrosoftPureDefinition>;
-def err_implicit_object_parameter_init : Error<
- "cannot initialize object parameter of type %0 with an expression "
- "of type %1">;
def err_qualified_member_of_unrelated : Error<
"%q0 is not a member of class %1">;
+def err_member_function_call_bad_cvr : Error<
+ "'this' argument to member function %0 has type %1, but function is not marked "
+ "%select{const|restrict|const or restrict|volatile|const or volatile|"
+ "volatile or restrict|const, volatile, or restrict}2">;
+def err_member_function_call_bad_ref : Error<
+ "'this' argument to member function %0 is an %select{lvalue|rvalue}1, "
+ "but function has %select{non-const lvalue|rvalue}2 ref-qualifier">;
+def err_member_function_call_bad_type : Error<
+ "cannot initialize object parameter of type %0 with an expression "
+ "of type %1">;
+
def warn_call_to_pure_virtual_member_function_from_ctor_dtor : Warning<
"call to pure virtual member function %0 has undefined behavior; "
"overrides of %0 in subclasses are not available in the "
"%select{constructor|destructor}1 of %2">;
+def 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|"
@@ -1615,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<
@@ -1643,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<
@@ -1711,9 +1757,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
@@ -1768,7 +1812,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 "
@@ -1808,17 +1853,9 @@ 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">;
-def err_member_function_call_bad_cvr : Error<"member function %0 not viable: "
- "'this' argument has type %1, but function is not marked "
- "%select{const|restrict|const or restrict|volatile|const or volatile|"
- "volatile or restrict|const, volatile, or restrict}2">;
def err_reference_bind_to_bitfield : Error<
"%select{non-const|volatile}0 reference cannot bind to "
@@ -1907,34 +1944,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">,
@@ -2031,10 +2063,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<
@@ -2099,9 +2127,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<
@@ -2363,6 +2398,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>;
@@ -2403,6 +2440,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<
@@ -2441,8 +2481,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">;
@@ -2546,6 +2586,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<
@@ -2639,11 +2682,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">;
@@ -2683,6 +2734,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>;
@@ -2796,7 +2850,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<
@@ -2821,8 +2875,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<
@@ -2877,6 +2930,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>;
@@ -2896,6 +2952,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<
@@ -2970,11 +3030,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<
@@ -2998,25 +3058,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
@@ -3034,7 +3094,7 @@ def note_found_mutex_near_match : Note<"found near match '%0'">;
// Verbose thread safety warnings
def warn_thread_safety_verbose : Warning<"Thread safety verbose warning.">,
InGroup<ThreadSafetyVerbose>, DefaultIgnore;
-def note_thread_warning_in_fun : Note<"Thread warning in function '%0'">;
+def note_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.
@@ -3082,6 +3142,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;
@@ -3107,13 +3170,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">,
@@ -3303,6 +3371,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<
@@ -3484,27 +3555,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">;
@@ -3518,6 +3591,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">;
@@ -3574,233 +3650,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">;
@@ -3842,16 +3784,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">;
@@ -3961,8 +3901,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<
@@ -4130,42 +4068,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|"
@@ -4187,16 +4103,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<
@@ -4493,6 +4411,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<
@@ -4554,6 +4474,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">;
@@ -5112,12 +5035,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))">;
@@ -5158,6 +5086,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">,
@@ -5411,8 +5342,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">;
@@ -5601,9 +5530,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;
@@ -5619,6 +5551,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>;
@@ -5797,6 +5742,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">;
@@ -5881,6 +5833,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++">;
@@ -5894,7 +5848,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<
@@ -5942,15 +5897,15 @@ def note_typecheck_assign_const : Note<
def warn_unsigned_always_true_comparison : Warning<
"result of comparison of %select{%3|unsigned expression}0 %2 "
"%select{unsigned expression|%3}0 is always %4">,
- InGroup<TautologicalUnsignedZeroCompare>;
+ InGroup<TautologicalUnsignedZeroCompare>, DefaultIgnore;
def warn_unsigned_enum_always_true_comparison : Warning<
"result of comparison of %select{%3|unsigned enum expression}0 %2 "
"%select{unsigned enum expression|%3}0 is always %4">,
- InGroup<TautologicalUnsignedEnumZeroCompare>;
+ InGroup<TautologicalUnsignedEnumZeroCompare>, DefaultIgnore;
def warn_tautological_constant_compare : Warning<
"result of comparison %select{%3|%1}0 %2 "
"%select{%1|%3}0 is always %4">,
- InGroup<TautologicalConstantCompare>;
+ InGroup<TautologicalTypeLimitCompare>, DefaultIgnore;
def warn_mixed_sign_comparison : Warning<
"comparison of integers of different signs: %0 and %1">,
@@ -6186,9 +6141,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">,
@@ -6260,6 +6215,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">;
@@ -6440,6 +6401,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>;
@@ -6561,6 +6524,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<
@@ -6619,6 +6584,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<
@@ -6688,9 +6658,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">;
@@ -7055,6 +7025,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)">;
@@ -7079,6 +7051,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)">;
@@ -7087,6 +7061,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)">;
@@ -7137,7 +7114,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<
@@ -7176,6 +7153,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 "
@@ -7623,6 +7604,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<
@@ -7705,9 +7691,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">;
@@ -7719,17 +7704,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 "
@@ -7784,6 +7765,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>;
@@ -7868,8 +7853,8 @@ def warn_null_ret : Warning<
// 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">,
@@ -7879,30 +7864,69 @@ 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 %1 here">;
+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|bound to}3 "
+ "%select{%select{|reference }3member of local variable|"
+ "local %select{variable|reference}3}1|"
+ "array backing "
+ "%select{initializer list subobject of local variable|"
+ "local initializer list}1}0 "
+ "%2 will 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">,
@@ -7958,7 +7982,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">;
@@ -8197,7 +8221,10 @@ def err_altivec_empty_initializer : Error<"expected initializer">;
def err_invalid_neon_type_code : Error<
"incompatible constant for this __builtin_neon function">;
def err_argument_invalid_range : Error<
- "argument should be a value from %0 to %1">;
+ "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<
@@ -8214,6 +8241,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<
@@ -8222,7 +8251,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<
@@ -8296,12 +8333,16 @@ 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">;
@@ -8497,7 +8538,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<
@@ -8545,7 +8586,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<
@@ -8635,8 +8677,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<
@@ -8972,6 +9014,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 {
@@ -9072,9 +9117,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 {
@@ -9115,7 +9160,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<
@@ -9320,8 +9365,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/include/clang/Basic/DiagnosticSerializationKinds.td b/include/clang/Basic/DiagnosticSerializationKinds.td
index 250b49f2cac4..3a552e2f3db4 100644
--- a/include/clang/Basic/DiagnosticSerializationKinds.td
+++ b/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">;
@@ -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/include/clang/Basic/ExceptionSpecificationType.h b/include/clang/Basic/ExceptionSpecificationType.h
index 132b5ba1e5a7..0c2c8e6d860a 100644
--- a/include/clang/Basic/ExceptionSpecificationType.h
+++ b/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/include/clang/Basic/ExpressionTraits.h b/include/clang/Basic/ExpressionTraits.h
index 0363a1d2c74c..2983adde1ed6 100644
--- a/include/clang/Basic/ExpressionTraits.h
+++ b/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/include/clang/Basic/Features.def b/include/clang/Basic/Features.def
new file mode 100644
index 000000000000..a0e0ce4560ab
--- /dev/null
+++ b/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/include/clang/Basic/FileManager.h b/include/clang/Basic/FileManager.h
index b817dd20c301..ab5dfca71639 100644
--- a/include/clang/Basic/FileManager.h
+++ b/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/include/clang/Basic/FileSystemOptions.h b/include/clang/Basic/FileSystemOptions.h
index 38f134631248..8b8b13bb5686 100644
--- a/include/clang/Basic/FileSystemOptions.h
+++ b/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/include/clang/Basic/FileSystemStatCache.h b/include/clang/Basic/FileSystemStatCache.h
index 75f986b59bdd..45aded527c1b 100644
--- a/include/clang/Basic/FileSystemStatCache.h
+++ b/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/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h
index 8e3c15afbfcd..f43df5c64829 100644
--- a/include/clang/Basic/IdentifierTable.h
+++ b/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
@@ -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;
@@ -335,10 +341,10 @@ public:
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
@@ -420,7 +426,7 @@ public:
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,17 +473,20 @@ 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;
}
@@ -486,7 +495,7 @@ public:
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
@@ -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.
@@ -720,7 +731,7 @@ 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,
@@ -735,7 +746,7 @@ public:
/// 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
@@ -745,14 +756,16 @@ public:
/// 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);
}
@@ -772,7 +785,7 @@ public:
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,
diff --git a/include/clang/Basic/LLVM.h b/include/clang/Basic/LLVM.h
index e60284d1b445..8a432db911da 100644
--- a/include/clang/Basic/LLVM.h
+++ b/include/clang/Basic/LLVM.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
/// \file
-/// \brief Forward-declares and imports various common LLVM datatypes that
+/// 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;
@@ -60,17 +61,18 @@ namespace clang {
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/include/clang/Basic/Lambda.h b/include/clang/Basic/Lambda.h
index 1c19f1dcc8b1..675854e67e7a 100644
--- a/include/clang/Basic/Lambda.h
+++ b/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/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def
index ca3a0e349d62..fc38af5b03f6 100644
--- a/include/clang/Basic/LangOptions.def
+++ b/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,21 +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")
@@ -225,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")
@@ -233,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,
@@ -276,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
@@ -289,4 +317,3 @@ BENIGN_LANGOPT(AllowEditorPlaceholders, 1, 0,
#undef VALUE_LANGOPT
#undef COMPATIBLE_VALUE_LANGOPT
#undef BENIGN_VALUE_LANGOPT
-
diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h
index f7a43adefad0..f3a6292e5ade 100644
--- a/include/clang/Basic/LangOptions.h
+++ b/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,69 +102,109 @@ 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();
@@ -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
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_BASIC_LANGOPTIONS_H
diff --git a/include/clang/Basic/Linkage.h b/include/clang/Basic/Linkage.h
index 6ec8763f2491..94dcfd445b0b 100644
--- a/include/clang/Basic/Linkage.h
+++ b/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/include/clang/Basic/MacroBuilder.h b/include/clang/Basic/MacroBuilder.h
index 9a9eaa24983c..b2edc972fee2 100644
--- a/include/clang/Basic/MacroBuilder.h
+++ b/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/include/clang/Basic/Module.h b/include/clang/Basic/Module.h
index 6631721e3531..4aebda1887c4 100644
--- a/include/clang/Basic/Module.h
+++ b/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.
//
//===----------------------------------------------------------------------===//
@@ -48,7 +48,7 @@ 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,22 +386,29 @@ 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.
+ /// \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 {
@@ -401,7 +419,7 @@ public:
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
@@ -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/include/clang/Basic/ObjCRuntime.h b/include/clang/Basic/ObjCRuntime.h
index 8dc259c7ab66..d5f4f50fe36f 100644
--- a/include/clang/Basic/ObjCRuntime.h
+++ b/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/include/clang/Basic/OpenCLExtensions.def b/include/clang/Basic/OpenCLExtensions.def
index c3319d2d808b..13cb12e7c581 100644
--- a/include/clang/Basic/OpenCLExtensions.def
+++ b/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/include/clang/Basic/OpenCLOptions.h b/include/clang/Basic/OpenCLOptions.h
index cc850f0b0b24..cc4e9922dca0 100644
--- a/include/clang/Basic/OpenCLOptions.h
+++ b/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/include/clang/Basic/OpenMPKinds.def b/include/clang/Basic/OpenMPKinds.def
index 6a0bed7ab15f..4ed7053b679b 100644
--- a/include/clang/Basic/OpenMPKinds.def
+++ b/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/include/clang/Basic/OpenMPKinds.h b/include/clang/Basic/OpenMPKinds.h
index e00333153f9b..c47973e53a8a 100644
--- a/include/clang/Basic/OpenMPKinds.h
+++ b/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/include/clang/Basic/OperatorKinds.h b/include/clang/Basic/OperatorKinds.h
index 7120baeef675..b0064cfb4e5a 100644
--- a/include/clang/Basic/OperatorKinds.h
+++ b/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/include/clang/Basic/OperatorPrecedence.h b/include/clang/Basic/OperatorPrecedence.h
index 94978f81e543..4389e3bbd257 100644
--- a/include/clang/Basic/OperatorPrecedence.h
+++ b/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/include/clang/Basic/PartialDiagnostic.h b/include/clang/Basic/PartialDiagnostic.h
index b2f14afe5695..9727af86f649 100644
--- a/include/clang/Basic/PartialDiagnostic.h
+++ b/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/include/clang/Basic/PlistSupport.h b/include/clang/Basic/PlistSupport.h
index 61de82450cf7..be92bbfde185 100644
--- a/include/clang/Basic/PlistSupport.h
+++ b/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/include/clang/Basic/PrettyStackTrace.h b/include/clang/Basic/PrettyStackTrace.h
index 6badae5c0349..e652f52055d6 100644
--- a/include/clang/Basic/PrettyStackTrace.h
+++ b/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/include/clang/Basic/Sanitizers.def b/include/clang/Basic/Sanitizers.def
index 30d5cc8166dc..5a36822a6303 100644
--- a/include/clang/Basic/Sanitizers.def
+++ b/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,
diff --git a/include/clang/Basic/Sanitizers.h b/include/clang/Basic/Sanitizers.h
index 1b936c7d115c..469d9e2e9591 100644
--- a/include/clang/Basic/Sanitizers.h
+++ b/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;
};
@@ -85,6 +87,6 @@ inline SanitizerMask getPPTransparentSanitizers() {
SanitizerKind::Nullability | SanitizerKind::Undefined;
}
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_BASIC_SANITIZERS_H
diff --git a/include/clang/Basic/SourceLocation.h b/include/clang/Basic/SourceLocation.h
index 7418b50f9d83..f174f83abf4a 100644
--- a/include/clang/Basic/SourceLocation.h
+++ b/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;
@@ -219,7 +222,7 @@ public:
}
};
-/// \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
@@ -245,11 +248,12 @@ public:
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; }
@@ -261,12 +265,13 @@ public:
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();
}
@@ -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/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h
index 397ad2e77fb5..99c36f4cdfcc 100644
--- a/include/clang/Basic/SourceManager.h
+++ b/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;
@@ -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;
@@ -1043,7 +1073,7 @@ public:
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;
@@ -1055,7 +1085,7 @@ public:
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());
+ }
+
+ /// 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;
}
- /// \brief Given a SourceLocation object, return the spelling
+ /// 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/include/clang/Basic/SourceManagerInternals.h b/include/clang/Basic/SourceManagerInternals.h
index edd910e70412..68873be594d4 100644
--- a/include/clang/Basic/SourceManagerInternals.h
+++ b/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/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h
index 377534baab06..303b77e44805 100644
--- a/include/clang/Basic/Specifiers.h
+++ b/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,7 +21,7 @@
#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,
@@ -29,7 +29,7 @@ namespace clang {
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,
@@ -41,18 +41,21 @@ namespace clang {
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.
@@ -138,7 +141,7 @@ namespace clang {
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/include/clang/Basic/Stack.h b/include/clang/Basic/Stack.h
new file mode 100644
index 000000000000..15a37c6d5949
--- /dev/null
+++ b/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/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td
index 0d21845fbf8b..506da0720338 100644
--- a/include/clang/Basic/StmtNodes.td
+++ b/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>;
diff --git a/include/clang/Basic/SyncScope.h b/include/clang/Basic/SyncScope.h
index 09ac0052185a..db4461eda013 100644
--- a/include/clang/Basic/SyncScope.h
+++ b/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/include/clang/Basic/TargetBuiltins.h b/include/clang/Basic/TargetBuiltins.h
index 8f4f5e9a74dd..75a3811007cc 100644
--- a/include/clang/Basic/TargetBuiltins.h
+++ b/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/include/clang/Basic/TargetCXXABI.h b/include/clang/Basic/TargetCXXABI.h
index 7fb1f826b0f6..455121a98f33 100644
--- a/include/clang/Basic/TargetCXXABI.h
+++ b/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/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h
index 6ba58779114f..ec5c59b23906 100644
--- a/include/clang/Basic/TargetInfo.h
+++ b/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,17 @@ 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);
}
- /// \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 +1152,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 +1160,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 +1175,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 +1192,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 +1207,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 +1220,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 +1276,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 +1294,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 +1314,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/include/clang/Basic/TargetOptions.h b/include/clang/Basic/TargetOptions.h
index 60becfb8ee76..31a674287915 100644
--- a/include/clang/Basic/TargetOptions.h
+++ b/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/include/clang/Basic/TemplateKinds.h b/include/clang/Basic/TemplateKinds.h
index ac99ad185f33..3b68cba73655 100644
--- a/include/clang/Basic/TemplateKinds.h
+++ b/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.
diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
index 6ae8821a834d..30cb022f1cba 100644
--- a/include/clang/Basic/TokenKinds.def
+++ b/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)
@@ -398,7 +409,6 @@ TYPE_TRAIT_2(__builtin_types_compatible_p, TypeCompatible, KEYNOCXX)
KEYWORD(__builtin_va_arg , KEYALL)
KEYWORD(__extension__ , KEYALL)
KEYWORD(__float128 , KEYALL)
-ALIAS("_Float128", __float128 , KEYNOCXX)
KEYWORD(__imag , KEYALL)
KEYWORD(__int128 , KEYALL)
KEYWORD(__label__ , KEYALL)
@@ -415,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)
@@ -464,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
@@ -521,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/include/clang/Basic/TokenKinds.h b/include/clang/Basic/TokenKinds.h
index f4ecb3eb306f..fb4b5252b70b 100644
--- a/include/clang/Basic/TokenKinds.h
+++ b/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/include/clang/Basic/TypeTraits.h b/include/clang/Basic/TypeTraits.h
index 8ecd63f9c3cb..bdb426834a8c 100644
--- a/include/clang/Basic/TypeTraits.h
+++ b/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/include/clang/Basic/Version.h b/include/clang/Basic/Version.h
index 57dcf92c3b28..6d625c6ddb80 100644
--- a/include/clang/Basic/Version.h
+++ b/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/include/clang/Basic/VersionTuple.h b/include/clang/Basic/VersionTuple.h
deleted file mode 100644
index da3b01903ed9..000000000000
--- a/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/include/clang/Basic/VirtualFileSystem.h b/include/clang/Basic/VirtualFileSystem.h
index 245452dd12b5..2480b91123c1 100644
--- a/include/clang/Basic/VirtualFileSystem.h
+++ b/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/include/clang/Basic/Visibility.h b/include/clang/Basic/Visibility.h
index cc839d789e7f..c5ab62436fe0 100644
--- a/include/clang/Basic/Visibility.h
+++ b/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/include/clang/Basic/X86Target.def b/include/clang/Basic/X86Target.def
index 21550fe2dd55..d2d2540e5005 100644
--- a/include/clang/Basic/X86Target.def
+++ b/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/include/clang/Basic/XRayInstr.h b/include/clang/Basic/XRayInstr.h
new file mode 100644
index 000000000000..13c3032a5cca
--- /dev/null
+++ b/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/include/clang/Basic/XRayLists.h b/include/clang/Basic/XRayLists.h
index 8cfea70e280a..244b1d533b7c 100644
--- a/include/clang/Basic/XRayLists.h
+++ b/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/include/clang/Basic/arm_fp16.td b/include/clang/Basic/arm_fp16.td
new file mode 100644
index 000000000000..bc15a22d84a6
--- /dev/null
+++ b/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/include/clang/Basic/arm_neon.td b/include/clang/Basic/arm_neon.td
index d5c16a91a34f..d405aac10650 100644
--- a/include/clang/Basic/arm_neon.td
+++ b/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>;
@@ -1214,7 +934,7 @@ 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/include/clang/Basic/arm_neon_incl.td b/include/clang/Basic/arm_neon_incl.td
new file mode 100644
index 000000000000..46708a52aa3a
--- /dev/null
+++ b/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/include/clang/CodeGen/BackendUtil.h b/include/clang/CodeGen/BackendUtil.h
index bb105cb533a4..3d1221a43b14 100644
--- a/include/clang/CodeGen/BackendUtil.h
+++ b/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/include/clang/CodeGen/CGFunctionInfo.h b/include/clang/CodeGen/CGFunctionInfo.h
index d1f05124d5e5..cf64e9f3eeff 100644
--- a/include/clang/CodeGen/CGFunctionInfo.h
+++ b/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/include/clang/CodeGen/ConstantInitBuilder.h b/include/clang/CodeGen/ConstantInitBuilder.h
index 113d86d82c10..f2e78adb8ceb 100644
--- a/include/clang/CodeGen/ConstantInitBuilder.h
+++ b/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/include/clang/CodeGen/SwiftCallingConv.h b/include/clang/CodeGen/SwiftCallingConv.h
index 23db43e6739c..45b3145ed9f1 100644
--- a/include/clang/CodeGen/SwiftCallingConv.h
+++ b/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/include/clang/Config/config.h.cmake b/include/clang/Config/config.h.cmake
index daac9b7b45d1..1d624450b9d9 100644
--- a/include/clang/Config/config.h.cmake
+++ b/include/clang/Config/config.h.cmake
@@ -11,6 +11,12 @@
/* Default linker to use. */
#define CLANG_DEFAULT_LINKER "${CLANG_DEFAULT_LINKER}"
+/* Default C/ObjC standard to use. */
+#cmakedefine CLANG_DEFAULT_STD_C LangStandard::lang_${CLANG_DEFAULT_STD_C}
+
+/* Default C++/ObjC++ standard to use. */
+#cmakedefine CLANG_DEFAULT_STD_CXX LangStandard::lang_${CLANG_DEFAULT_STD_CXX}
+
/* Default C++ stdlib to use. */
#define CLANG_DEFAULT_CXX_STDLIB "${CLANG_DEFAULT_CXX_STDLIB}"
@@ -35,6 +41,10 @@
/* Directories clang will search for headers */
#define C_INCLUDE_DIRS "${C_INCLUDE_DIRS}"
+/* Directories clang will search for configuration files */
+#cmakedefine CLANG_CONFIG_FILE_SYSTEM_DIR "${CLANG_CONFIG_FILE_SYSTEM_DIR}"
+#cmakedefine CLANG_CONFIG_FILE_USER_DIR "${CLANG_CONFIG_FILE_USER_DIR}"
+
/* Default <path> to all compiler invocations for --sysroot=<path>. */
#define DEFAULT_SYSROOT "${DEFAULT_SYSROOT}"
@@ -62,6 +72,9 @@
/* enable x86 relax relocations by default */
#cmakedefine01 ENABLE_X86_RELAX_RELOCATIONS
+/* Enable the experimental new pass manager by default */
+#cmakedefine01 ENABLE_EXPERIMENTAL_NEW_PASS_MANAGER
+
/* Enable each functionality of modules */
#cmakedefine01 CLANG_ENABLE_ARCMT
#cmakedefine01 CLANG_ENABLE_OBJC_REWRITER
diff --git a/include/clang/CrossTU/CrossTranslationUnit.h b/include/clang/CrossTU/CrossTranslationUnit.h
index f2a169025009..041f1a8eea59 100644
--- a/include/clang/CrossTU/CrossTranslationUnit.h
+++ b/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/include/clang/Driver/Action.h b/include/clang/Driver/Action.h
index 72456d34a0d9..723fbbed3598 100644
--- a/include/clang/Driver/Action.h
+++ b/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/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td
index 7dea88b62cc1..7cb9724a57e1 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/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
//===----------------------------------------------------------------------===//
@@ -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">,
diff --git a/include/clang/Driver/CLCompatOptions.td b/include/clang/Driver/CLCompatOptions.td
index c1f0a89b5dc8..78667851ca19 100644
--- a/include/clang/Driver/CLCompatOptions.td
+++ b/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,10 +240,12 @@ 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-">,
- HelpText<"Enable exception handling">;
+ HelpText<"Disable exception handling">;
def _SLASH_imsvc : CLJoinedOrSeparate<"imsvc">,
HelpText<"Add directory to system include search path, as if part of %INCLUDE%">,
MetaVarName<"<dir>">;
@@ -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/include/clang/Driver/Compilation.h b/include/clang/Driver/Compilation.h
index 89c0def6c57a..20eb07f6de8b 100644
--- a/include/clang/Driver/Compilation.h
+++ b/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/include/clang/Driver/Distro.h b/include/clang/Driver/Distro.h
index 4ab4e2ae9937..7b34a0925603 100644
--- a/include/clang/Driver/Distro.h
+++ b/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/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h
index a3662872a953..017248c3690f 100644
--- a/include/clang/Driver/Driver.h
+++ b/include/clang/Driver/Driver.h
@@ -19,6 +19,8 @@
#include "clang/Driver/Util.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Support/StringSaver.h"
#include <list>
#include <map>
@@ -26,14 +28,6 @@
namespace llvm {
class Triple;
-
-namespace opt {
- class Arg;
- class ArgList;
- class DerivedArgList;
- class InputArgList;
- class OptTable;
-}
}
namespace clang {
@@ -138,6 +132,12 @@ public:
/// The path to the compiler resource directory.
std::string ResourceDir;
+ /// System directory for config files.
+ std::string SystemConfigDir;
+
+ /// User directory for config files.
+ std::string UserConfigDir;
+
/// A prefix directory used to emulate a limited subset of GCC's '-Bprefix'
/// functionality.
/// FIXME: This type of customization should be removed in favor of the
@@ -202,12 +202,27 @@ 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;
+ /// Name of configuration file if used.
+ std::string ConfigFile;
+
+ /// Allocator for string saver.
+ llvm::BumpPtrAllocator Alloc;
+
+ /// Object that stores strings read from configuration file.
+ llvm::StringSaver Saver;
+
+ /// Arguments originated from configuration file.
+ std::unique_ptr<llvm::opt::InputArgList> CfgOptions;
+
+ /// Arguments originated from command line.
+ std::unique_ptr<llvm::opt::InputArgList> CLOptions;
+
/// Whether to check that input files exist when constructing compilation
/// jobs.
unsigned CheckInputsExist : 1;
@@ -228,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
@@ -252,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.
@@ -267,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);
@@ -277,6 +292,8 @@ public:
/// Name to use when invoking gcc/g++.
const std::string &getCCCGenericGCCName() const { return CCCGenericGCCName; }
+ const std::string &getConfigFile() const { return ConfigFile; }
+
const llvm::opt::OptTable &getOpts() const { return *Opts; }
const DiagnosticsEngine &getDiags() const { return Diags; }
@@ -292,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();
@@ -388,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
@@ -425,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.
@@ -439,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
@@ -493,6 +522,18 @@ public:
LTOKind getLTOMode() const { return LTOMode; }
private:
+
+ /// Tries to load options from configuration file.
+ ///
+ /// \returns true if error occurred.
+ bool loadConfigFile();
+
+ /// Read options from the specified file.
+ ///
+ /// \param [in] FileName File to read.
+ /// \returns true, if error occurred while reading.
+ bool readConfigFile(StringRef FileName);
+
/// Set the driver mode (cl, gcc, etc) from an option string of the form
/// --driver-mode=<mode>.
void setDriverModeFromOption(StringRef Opt);
@@ -501,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.
@@ -510,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;
@@ -543,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/include/clang/Driver/Job.h b/include/clang/Driver/Job.h
index b74b3b4b35e1..47d9e992ba50 100644
--- a/include/clang/Driver/Job.h
+++ b/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/include/clang/Driver/Multilib.h b/include/clang/Driver/Multilib.h
index 36d2493b1afc..132d981854fc 100644
--- a/include/clang/Driver/Multilib.h
+++ b/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/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index 09efd7b0af63..2470638bec66 100644
--- a/include/clang/Driver/Options.td
+++ b/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,14 +523,22 @@ 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">;
+def config : Separate<["--"], "config">, Flags<[DriverOption]>,
+ HelpText<"Specifies configuration file">;
+def config_system_dir_EQ : Joined<["--"], "config-system-dir=">, Flags<[DriverOption, HelpHidden]>,
+ HelpText<"System directory for configuration files">;
+def config_user_dir_EQ : Joined<["--"], "config-user-dir=">, Flags<[DriverOption, HelpHidden]>,
+ HelpText<"User directory for configuration files">;
def coverage : Flag<["-", "--"], "coverage">, Flags<[CoreOption]>;
def cpp_precomp : Flag<["-"], "cpp-precomp">, Group<clang_ignored_f_Group>;
def current__version : JoinedOrSeparate<["-"], "current_version">;
@@ -535,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.">;
@@ -548,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">,
@@ -556,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">;
@@ -591,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">;
@@ -687,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]>,
@@ -715,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>;
@@ -741,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>;
@@ -749,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]>;
@@ -780,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>;
@@ -795,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]>,
@@ -829,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.
@@ -881,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">;
@@ -985,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>;
@@ -996,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 ]>;
@@ -1025,6 +1116,8 @@ def finline_functions : Flag<["-"], "finline-functions">, Group<f_clang_Group>,
def finline_hint_functions: Flag<["-"], "finline-hint-functions">, Group<f_clang_Group>, Flags<[CC1Option]>,
HelpText<"Inline functions which are (explicitly or implicitly) marked inline">;
def finline : Flag<["-"], "finline">, Group<clang_ignored_f_Group>;
+def fexperimental_isel : Flag<["-"], "fexperimental-isel">, Group<f_clang_Group>,
+ HelpText<"Enables the experimental global instruction selector">;
def fexperimental_new_pass_manager : Flag<["-"], "fexperimental-new-pass-manager">,
Group<f_clang_Group>, Flags<[CC1Option]>,
HelpText<"Enables an experimental new pass manager in LLVM.">;
@@ -1036,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]>,
@@ -1054,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]>,
@@ -1066,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.">;
@@ -1092,7 +1215,8 @@ def fthinlto_index_EQ : Joined<["-"], "fthinlto-index=">,
HelpText<"Perform ThinLTO importing using provided function summary index">;
def fmacro_backtrace_limit_EQ : Joined<["-"], "fmacro-backtrace-limit=">,
Group<f_Group>, Flags<[DriverOption, CoreOption]>;
-def fmerge_all_constants : Flag<["-"], "fmerge-all-constants">, Group<f_Group>;
+def fmerge_all_constants : Flag<["-"], "fmerge-all-constants">, Group<f_Group>,
+ 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">;
@@ -1146,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">;
@@ -1194,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]>;
@@ -1220,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>,
@@ -1231,6 +1361,8 @@ def fno_exceptions : Flag<["-"], "fno-exceptions">, Group<f_Group>;
def fno_gnu_keywords : Flag<["-"], "fno-gnu-keywords">, Group<f_Group>, Flags<[CC1Option]>;
def fno_inline_functions : Flag<["-"], "fno-inline-functions">, Group<f_clang_Group>, Flags<[CC1Option]>;
def fno_inline : Flag<["-"], "fno-inline">, Group<f_clang_Group>, Flags<[CC1Option]>;
+def fno_experimental_isel : Flag<["-"], "fno-experimental-isel">, Group<f_clang_Group>,
+ HelpText<"Disables the experimental global instruction selector">;
def fno_experimental_new_pass_manager : Flag<["-"], "fno-experimental-new-pass-manager">,
Group<f_clang_Group>, Flags<[CC1Option]>,
HelpText<"Disables an experimental new pass manager in LLVM.">;
@@ -1239,7 +1371,7 @@ def fveclib : Joined<["-"], "fveclib=">, Group<f_Group>, Flags<[CC1Option]>,
def fno_lax_vector_conversions : Flag<["-"], "fno-lax-vector-conversions">, Group<f_Group>,
HelpText<"Disallow implicit conversions between vectors with a different number of elements or different element types">, Flags<[CC1Option]>;
def fno_merge_all_constants : Flag<["-"], "fno-merge-all-constants">, Group<f_Group>,
- Flags<[CC1Option]>, HelpText<"Disallow merging of constants">;
+ HelpText<"Disallow merging of constants">;
def fno_modules : Flag <["-"], "fno-modules">, Group<f_Group>,
Flags<[DriverOption]>;
def fno_implicit_module_maps : Flag <["-"], "fno-implicit-module-maps">, Group<f_Group>,
@@ -1272,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">;
@@ -1295,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>;
@@ -1361,22 +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]>;
+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">;
@@ -1421,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>,
@@ -1533,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>;
@@ -1540,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 "
@@ -1550,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]>,
@@ -1564,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]>,
@@ -1589,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">;
@@ -1642,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"
@@ -1650,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">;
@@ -1700,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>;
@@ -1787,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]>,
@@ -1795,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]>,
@@ -1811,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>,
@@ -1827,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>,
@@ -1844,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]>,
@@ -1866,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">,
@@ -1962,124 +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 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 mindirect_jump_EQ : Joined<["-"], "mindirect-jump=">,
+ Group<m_mips_Features_Group>,
+ HelpText<"Change indirect jump instructions to inhibit speculation">;
+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]>;
@@ -2092,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]>;
@@ -2175,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"]>,
@@ -2326,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>;
@@ -2396,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
@@ -2499,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>;
@@ -2517,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>;
@@ -2525,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>;
@@ -2533,18 +2762,26 @@ 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>;
def mno_rtm : Flag<["-"], "mno-rtm">, Group<m_x86_Features_Group>;
def mrdseed : Flag<["-"], "mrdseed">, Group<m_x86_Features_Group>;
def mno_rdseed : Flag<["-"], "mno-rdseed">, Group<m_x86_Features_Group>;
+def msahf : Flag<["-"], "msahf">, Group<m_x86_Features_Group>;
+def mno_sahf : Flag<["-"], "mno-sahf">, Group<m_x86_Features_Group>;
def msgx : Flag<["-"], "msgx">, Group<m_x86_Features_Group>;
def mno_sgx : Flag<["-"], "mno-sgx">, Group<m_x86_Features_Group>;
def msha : Flag<["-"], "msha">, Group<m_x86_Features_Group>;
@@ -2555,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>;
@@ -2567,8 +2806,10 @@ 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>;
+def mno_retpoline_external_thunk : Flag<["-"], "mno-retpoline-external-thunk">, Group<m_x86_Features_Group>;
// These are legacy user-facing driver-level option spellings. They are always
// aliases for options that are spelled using the more common Unix / GNU flag
@@ -2604,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>;
@@ -2623,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>;
@@ -2634,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/include/clang/Driver/SanitizerArgs.h b/include/clang/Driver/SanitizerArgs.h
index a31ac05afc1b..d144e488b56b 100644
--- a/include/clang/Driver/SanitizerArgs.h
+++ b/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/include/clang/Driver/Tool.h b/include/clang/Driver/Tool.h
index 8f76e17c48ba..b02ac66d3b5c 100644
--- a/include/clang/Driver/Tool.h
+++ b/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/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h
index 13f54d3718b4..addf7aa6a9c8 100644
--- a/include/clang/Driver/ToolChain.h
+++ b/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.
@@ -404,9 +418,7 @@ public:
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 +454,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 +462,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 +509,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 +547,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/include/clang/Driver/Types.def b/include/clang/Driver/Types.def
index 2430b5b924c3..c23f1f13361f 100644
--- a/include/clang/Driver/Types.def
+++ b/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/include/clang/Driver/Types.h b/include/clang/Driver/Types.h
index 22a26ae46a0b..5bc6668a0d1d 100644
--- a/include/clang/Driver/Types.h
+++ b/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/include/clang/Driver/XRayArgs.h b/include/clang/Driver/XRayArgs.h
index e5b76162de8e..c7ca94529175 100644
--- a/include/clang/Driver/XRayArgs.h
+++ b/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/include/clang/Edit/Commit.h b/include/clang/Edit/Commit.h
index ac4bb471fe1c..a574b8ef4cd2 100644
--- a/include/clang/Edit/Commit.h
+++ b/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,9 +53,9 @@ 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;
@@ -59,21 +64,23 @@ 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/include/clang/Edit/EditedSource.h b/include/clang/Edit/EditedSource.h
index d95a0c2be805..3d33688f5f73 100644
--- a/include/clang/Edit/EditedSource.h
+++ b/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;
}
@@ -103,8 +111,8 @@ private:
void finishedCommit();
};
-}
+} // namespace edit
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_EDIT_EDITEDSOURCE_H
diff --git a/include/clang/Edit/EditsReceiver.h b/include/clang/Edit/EditsReceiver.h
index 600ac28ea920..1bebbeb873a7 100644
--- a/include/clang/Edit/EditsReceiver.h
+++ b/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/include/clang/Edit/FileOffset.h b/include/clang/Edit/FileOffset.h
index 0c1e72b84e51..02c1b96b3331 100644
--- a/include/clang/Edit/FileOffset.h
+++ b/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/include/clang/Format/Format.h b/include/clang/Format/Format.h
index d27d934f7679..85dda948c11f 100644
--- a/include/clang/Format/Format.h
+++ b/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/include/clang/Frontend/ASTConsumers.h b/include/clang/Frontend/ASTConsumers.h
index 53975a07ea94..2a13527df135 100644
--- a/include/clang/Frontend/ASTConsumers.h
+++ b/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/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h
index 5d04dcd19119..9f529ba0e0e8 100644
--- a/include/clang/Frontend/ASTUnit.h
+++ b/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,22 +143,22 @@ 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;
+ unsigned NumStoredDiagnosticsFromDriver = 0;
- /// \brief Counter that determines when we want to try building a
+ /// Counter that determines when we want to try building a
/// precompiled preamble.
///
/// If zero, we will never build a precompiled preamble. Otherwise,
@@ -190,45 +207,44 @@ 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;
@@ -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
@@ -259,20 +275,20 @@ public:
/// 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
@@ -281,13 +297,13 @@ public:
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() {
+ 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
/// 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
/// 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;
+ unsigned CurrentTopLevelHashValue = 0;
- /// \brief Bit used by CIndex to mark when a translation unit may be in an
+ /// 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,22 +423,32 @@ 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 {
assert(TheSema && "ASTUnit does not have a Sema object!");
return *TheSema;
@@ -442,7 +470,7 @@ public:
}
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.
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;
@@ -549,20 +577,25 @@ public:
}
// Retrieve the diagnostics associated with this AST
- typedef StoredDiagnostic *stored_diag_iterator;
- typedef const StoredDiagnostic *stored_diag_const_iterator;
+ 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_const_iterator stored_diag_end() const {
return StoredDiagnostics.end();
}
+
stored_diag_iterator stored_diag_end() {
return StoredDiagnostics.end();
}
+
unsigned stored_diag_size() const { return StoredDiagnostics.size(); }
stored_diag_iterator stored_diag_afterDriver_begin() {
@@ -571,8 +604,8 @@ public:
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();
@@ -586,43 +619,43 @@ public:
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,8 +711,7 @@ private:
IntrusiveRefCntPtr<vfs::FileSystem> VFS);
public:
-
- /// \brief Create an ASTUnit from a source file, via a CompilerInvocation
+ /// 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
@@ -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.
@@ -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/include/clang/Frontend/ChainedDiagnosticConsumer.h b/include/clang/Frontend/ChainedDiagnosticConsumer.h
index eb33273c2fb3..04c6077dc35e 100644
--- a/include/clang/Frontend/ChainedDiagnosticConsumer.h
+++ b/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/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def
index bb91cf5f742b..a7e71f7ac016 100644
--- a/include/clang/Frontend/CodeGenOptions.def
+++ b/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/include/clang/Frontend/CodeGenOptions.h b/include/clang/Frontend/CodeGenOptions.h
index 6b8d2b935fdd..a6d061acf0f4 100644
--- a/include/clang/Frontend/CodeGenOptions.h
+++ b/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/include/clang/Frontend/CommandLineSourceLoc.h b/include/clang/Frontend/CommandLineSourceLoc.h
index f5c1e1a8a67d..7ae98e079264 100644
--- a/include/clang/Frontend/CommandLineSourceLoc.h
+++ b/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/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h
index 90a9501475b5..977d1b2ed65f 100644
--- a/include/clang/Frontend/CompilerInstance.h
+++ b/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
+ /// 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;
@@ -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.
@@ -412,7 +415,7 @@ public:
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);
/// }
@@ -475,7 +478,7 @@ 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);
@@ -687,7 +690,7 @@ 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);
@@ -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/include/clang/Frontend/CompilerInvocation.h b/include/clang/Frontend/CompilerInvocation.h
index 8c4c932190bc..3d302051d298 100644
--- a/include/clang/Frontend/CompilerInvocation.h
+++ b/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
@@ -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.
@@ -168,7 +173,7 @@ public:
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;
@@ -176,40 +181,35 @@ public:
/// @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/include/clang/Frontend/DependencyOutputOptions.h b/include/clang/Frontend/DependencyOutputOptions.h
index 0be36cd9aa6e..f419d2643649 100644
--- a/include/clang/Frontend/DependencyOutputOptions.h
+++ b/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/include/clang/Frontend/DiagnosticRenderer.h b/include/clang/Frontend/DiagnosticRenderer.h
index e453d7db624c..191d32accf2f 100644
--- a/include/clang/Frontend/DiagnosticRenderer.h
+++ b/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;
+using DiagOrStoredDiag =
+ llvm::PointerUnion<const Diagnostic *, const StoredDiagnostic *>;
-/// \brief Class to encapsulate the logic for formatting a diagnostic message.
+/// Class to encapsulate the logic for formatting a diagnostic message.
///
/// Actual "printing" logic is implemented by subclasses.
///
@@ -47,24 +50,24 @@ 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);
@@ -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
@@ -142,7 +144,7 @@ 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/include/clang/Frontend/FrontendAction.h b/include/clang/Frontend/FrontendAction.h
index 7ae6173512a6..2a4077d34391 100644
--- a/include/clang/Frontend/FrontendAction.h
+++ b/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/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h
index fa1529a3d65d..20f1b3e11bdb 100644
--- a/include/clang/Frontend/FrontendActions.h
+++ b/include/clang/Frontend/FrontendActions.h
@@ -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:
diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h
index 5192a3774cc1..668df83274eb 100644
--- a/include/clang/Frontend/FrontendOptions.h
+++ b/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/include/clang/Frontend/FrontendPluginRegistry.h b/include/clang/Frontend/FrontendPluginRegistry.h
index 9d7ee08d95d4..9a85e89d905d 100644
--- a/include/clang/Frontend/FrontendPluginRegistry.h
+++ b/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/include/clang/Frontend/LangStandards.def b/include/clang/Frontend/LangStandards.def
index e7a081dc2aa7..1e895d785d15 100644
--- a/include/clang/Frontend/LangStandards.def
+++ b/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/include/clang/Frontend/LayoutOverrideSource.h b/include/clang/Frontend/LayoutOverrideSource.h
index 16d032b7dd72..0b7f7dc7a7d6 100644
--- a/include/clang/Frontend/LayoutOverrideSource.h
+++ b/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,
@@ -55,7 +55,7 @@ namespace clang {
llvm::DenseMap<const CXXRecordDecl *,
CharUnits> &VirtualBaseOffsets) override;
- /// \brief Dump the overridden layouts.
+ /// Dump the overridden layouts.
void dump();
};
}
diff --git a/include/clang/Frontend/MultiplexConsumer.h b/include/clang/Frontend/MultiplexConsumer.h
index d13565c27bc3..214fefb219cd 100644
--- a/include/clang/Frontend/MultiplexConsumer.h
+++ b/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/include/clang/Frontend/PrecompiledPreamble.h b/include/clang/Frontend/PrecompiledPreamble.h
index 130fe60704a7..6abdbe3a1e1b 100644
--- a/include/clang/Frontend/PrecompiledPreamble.h
+++ b/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/include/clang/Frontend/SerializedDiagnosticPrinter.h b/include/clang/Frontend/SerializedDiagnosticPrinter.h
index 4c57e9d404f0..dc68c32fb15a 100644
--- a/include/clang/Frontend/SerializedDiagnosticPrinter.h
+++ b/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/include/clang/Frontend/SerializedDiagnosticReader.h b/include/clang/Frontend/SerializedDiagnosticReader.h
index 07479844d465..595bdf1f4d7a 100644
--- a/include/clang/Frontend/SerializedDiagnosticReader.h
+++ b/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/include/clang/Frontend/SerializedDiagnostics.h b/include/clang/Frontend/SerializedDiagnostics.h
index 2032cd3988db..dacbc678b700 100644
--- a/include/clang/Frontend/SerializedDiagnostics.h
+++ b/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/include/clang/Frontend/TextDiagnostic.h b/include/clang/Frontend/TextDiagnostic.h
index 1bbfe9fa02e3..9f33b866a1eb 100644
--- a/include/clang/Frontend/TextDiagnostic.h
+++ b/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/include/clang/Frontend/TextDiagnosticBuffer.h b/include/clang/Frontend/TextDiagnosticBuffer.h
index 23f168e2232d..2295f9dbf3bf 100644
--- a/include/clang/Frontend/TextDiagnosticBuffer.h
+++ b/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/include/clang/Frontend/TextDiagnosticPrinter.h b/include/clang/Frontend/TextDiagnosticPrinter.h
index 07cee9f8ad8a..3cb4e02edf0d 100644
--- a/include/clang/Frontend/TextDiagnosticPrinter.h
+++ b/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/include/clang/Frontend/Utils.h b/include/clang/Frontend/Utils.h
index 8ccc31982dab..67912a8dfcdd 100644
--- a/include/clang/Frontend/Utils.h
+++ b/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/include/clang/Frontend/VerifyDiagnosticConsumer.h b/include/clang/Frontend/VerifyDiagnosticConsumer.h
index 8d71fb98b0bb..9d985bc4955f 100644
--- a/include/clang/Frontend/VerifyDiagnosticConsumer.h
+++ b/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,14 +235,18 @@ 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;
@@ -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/include/clang/FrontendTool/Utils.h b/include/clang/FrontendTool/Utils.h
index 031ee7df70ae..2e6b7b5076bb 100644
--- a/include/clang/FrontendTool/Utils.h
+++ b/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/include/clang/Index/IndexDataConsumer.h b/include/clang/Index/IndexDataConsumer.h
index 080f4cb4d097..6e11455661a0 100644
--- a/include/clang/Index/IndexDataConsumer.h
+++ b/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/include/clang/Index/IndexSymbol.h b/include/clang/Index/IndexSymbol.h
index 08f2839f37e8..068796141df8 100644
--- a/include/clang/Index/IndexSymbol.h
+++ b/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/include/clang/Index/IndexingAction.h b/include/clang/Index/IndexingAction.h
index fb703be4e5f5..0d09c403483d 100644
--- a/include/clang/Index/IndexingAction.h
+++ b/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/include/clang/Index/USRGeneration.h b/include/clang/Index/USRGeneration.h
index 8c661bd63cd8..1ece321746a6 100644
--- a/include/clang/Index/USRGeneration.h
+++ b/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/include/clang/Lex/CodeCompletionHandler.h b/include/clang/Lex/CodeCompletionHandler.h
index 91c3b7811f07..be153cc1ad50 100644
--- a/include/clang/Lex/CodeCompletionHandler.h
+++ b/include/clang/Lex/CodeCompletionHandler.h
@@ -19,13 +19,13 @@ 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
@@ -35,22 +35,22 @@ public:
/// 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,7 +60,7 @@ public:
MacroInfo *MacroInfo,
unsigned ArgumentIndex) { }
- /// \brief Callback invoked when performing code completion in a part of the
+ /// 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() { }
diff --git a/include/clang/Lex/DirectoryLookup.h b/include/clang/Lex/DirectoryLookup.h
index dcd58f434fa2..222ebf025ac0 100644
--- a/include/clang/Lex/DirectoryLookup.h
+++ b/include/clang/Lex/DirectoryLookup.h
@@ -55,10 +55,10 @@ private:
/// 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;
@@ -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,12 +134,12 @@ 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.
+ /// Whether this header map is building a framework or not.
bool isIndexHeaderMap() const {
return isHeaderMap() && IsIndexHeaderMap;
}
diff --git a/include/clang/Lex/ExternalPreprocessorSource.h b/include/clang/Lex/ExternalPreprocessorSource.h
index adf8e713e99e..f34be682617c 100644
--- a/include/clang/Lex/ExternalPreprocessorSource.h
+++ b/include/clang/Lex/ExternalPreprocessorSource.h
@@ -19,7 +19,7 @@ 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)
@@ -28,18 +28,18 @@ 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;
};
diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h
index 6b9dbfcd1e93..b7147c54faac 100644
--- a/include/clang/Lex/HeaderSearch.h
+++ b/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,21 +61,21 @@ 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
+ /// 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
@@ -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,7 +107,7 @@ 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;
@@ -116,12 +116,12 @@ struct HeaderFileInfo {
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 ||
@@ -129,13 +129,13 @@ struct HeaderFileInfo {
}
};
-/// \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
@@ -143,7 +143,7 @@ public:
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,26 +230,26 @@ 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.
@@ -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,15 +296,15 @@ 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
/// should not. This allows for distinction between <> and "" headers.
@@ -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();
}
@@ -352,16 +354,16 @@ public:
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.
///
@@ -551,14 +557,14 @@ public:
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.
@@ -611,11 +621,11 @@ private:
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/include/clang/Lex/HeaderSearchOptions.h b/include/clang/Lex/HeaderSearchOptions.h
index 937ad9863db3..298179e91a6f 100644
--- a/include/clang/Lex/HeaderSearchOptions.h
+++ b/include/clang/Lex/HeaderSearchOptions.h
@@ -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/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h
index d58849654cb8..624151ef877b 100644
--- a/include/clang/Lex/Lexer.h
+++ b/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/include/clang/Lex/LiteralSupport.h b/include/clang/Lex/LiteralSupport.h
index cc9223eb7dbb..1b6bf6bcffb0 100644
--- a/include/clang/Lex/LiteralSupport.h
+++ b/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);
diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h
index 3029294209ec..13e5313a9c30 100644
--- a/include/clang/Lex/MacroInfo.h
+++ b/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) {
@@ -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/include/clang/Lex/ModuleLoader.h b/include/clang/Lex/ModuleLoader.h
index 30ea583b71e0..a2766fa35984 100644
--- a/include/clang/Lex/ModuleLoader.h
+++ b/include/clang/Lex/ModuleLoader.h
@@ -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
@@ -81,17 +81,17 @@ public:
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
/// parameters.
@@ -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.
diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h
index 41ed8e49b6c1..577f4008978e 100644
--- a/include/clang/Lex/ModuleMap.h
+++ b/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,12 +57,12 @@ 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.
@@ -78,11 +79,11 @@ class ModuleMap {
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.
@@ -264,7 +289,7 @@ private:
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,7 +490,7 @@ 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.
@@ -461,7 +501,7 @@ public:
/// \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,11 +666,11 @@ 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;
diff --git a/include/clang/Lex/MultipleIncludeOpt.h b/include/clang/Lex/MultipleIncludeOpt.h
index 3967f8688966..ac0dcc7b51c2 100644
--- a/include/clang/Lex/MultipleIncludeOpt.h
+++ b/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/include/clang/Lex/PPCallbacks.h b/include/clang/Lex/PPCallbacks.h
index 19bce4dd32e8..eb85bda840af 100644
--- a/include/clang/Lex/PPCallbacks.h
+++ b/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,7 +63,7 @@ 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
@@ -80,7 +80,7 @@ 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.
///
@@ -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,
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.
@@ -265,13 +270,13 @@ public:
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/include/clang/Lex/PPConditionalDirectiveRecord.h b/include/clang/Lex/PPConditionalDirectiveRecord.h
index 8c5227561b83..a653b8339948 100644
--- a/include/clang/Lex/PPConditionalDirectiveRecord.h
+++ b/include/clang/Lex/PPConditionalDirectiveRecord.h
@@ -21,7 +21,7 @@
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;
@@ -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/include/clang/Lex/Pragma.h b/include/clang/Lex/Pragma.h
index 090ae2a98236..9348388bc28c 100644
--- a/include/clang/Lex/Pragma.h
+++ b/include/clang/Lex/Pragma.h
@@ -26,22 +26,22 @@ 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
diff --git a/include/clang/Lex/PreprocessingRecord.h b/include/clang/Lex/PreprocessingRecord.h
index 5f7a6efcef10..54e28a52f5b3 100644
--- a/include/clang/Lex/PreprocessingRecord.h
+++ b/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,10 +84,10 @@ 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:
@@ -97,14 +97,14 @@ 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; }
@@ -131,7 +131,7 @@ class Token;
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)
@@ -144,9 +144,9 @@ class Token;
}
};
- /// \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,10 +154,10 @@ 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.
@@ -166,9 +166,9 @@ class Token;
}
};
- /// \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,45 +203,45 @@ 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:
@@ -250,21 +250,21 @@ class Token;
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; }
@@ -274,55 +274,60 @@ class Token;
}
};
- /// \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,
+ /// 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,23 +498,24 @@ 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;
}
@@ -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/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h
index 485600f12232..4ec29fe8f331 100644
--- a/include/clang/Lex/Preprocessor.h
+++ b/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,10 +808,10 @@ 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; }
@@ -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
+ /// 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,7 +1629,7 @@ public:
return Lexer::getImmediateMacroName(Loc, SourceMgr, getLangOpts());
}
- /// \brief Plop the specified string into a scratch buffer and set the
+ /// 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
@@ -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,7 +1768,7 @@ private:
public:
void PoisonSEHIdentifiers(bool Poison = true); // Borland
- /// \brief Callback invoked when the lexer reads an identifier and has
+ /// 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
@@ -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,13 +1815,13 @@ 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
+ /// 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
@@ -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,17 +1845,17 @@ public:
ModuleMap::KnownHeader *SuggestedModule,
bool *IsMapped, bool SkipCache = false);
- /// \brief Get the DirectoryLookup structure used to find the current
+ /// 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
+ /// 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:
@@ -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.
@@ -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/include/clang/Lex/PreprocessorLexer.h b/include/clang/Lex/PreprocessorLexer.h
index ff71d11b4511..bb02725b116f 100644
--- a/include/clang/Lex/PreprocessorLexer.h
+++ b/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,7 +164,7 @@ 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;
diff --git a/include/clang/Lex/PreprocessorOptions.h b/include/clang/Lex/PreprocessorOptions.h
index 55fc305dc295..3d7e5ab4a8dc 100644
--- a/include/clang/Lex/PreprocessorOptions.h
+++ b/include/clang/Lex/PreprocessorOptions.h
@@ -27,14 +27,14 @@ 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
};
@@ -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,22 +117,22 @@ 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
@@ -128,12 +140,12 @@ public:
/// 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;
@@ -147,7 +159,7 @@ public:
}
};
- /// \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,
@@ -174,7 +186,7 @@ public:
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/include/clang/Lex/Token.h b/include/clang/Lex/Token.h
index 02a1fef70f2b..633e1d15697b 100644
--- a/include/clang/Lex/Token.h
+++ b/include/clang/Lex/Token.h
@@ -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/include/clang/Lex/TokenLexer.h b/include/clang/Lex/TokenLexer.h
index b8b0beabf2ba..e616d497eec6 100644
--- a/include/clang/Lex/TokenLexer.h
+++ b/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/include/clang/Lex/VariadicMacroSupport.h b/include/clang/Lex/VariadicMacroSupport.h
index cebaf15187de..55202ffc34d7 100644
--- a/include/clang/Lex/VariadicMacroSupport.h
+++ b/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,7 +66,7 @@ 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.
@@ -116,7 +116,7 @@ namespace clang {
};
- /// \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 {
diff --git a/include/clang/Parse/ParseAST.h b/include/clang/Parse/ParseAST.h
index 34c96816ebdf..34b04060346f 100644
--- a/include/clang/Parse/ParseAST.h
+++ b/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/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 4a25c70956a3..d7b83803af20 100644
--- a/include/clang/Parse/Parser.h
+++ b/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
@@ -1103,7 +1197,7 @@ private:
/// 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;
};
@@ -1135,7 +1229,7 @@ private:
/// 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);
@@ -1447,7 +1550,7 @@ private:
bool isTokIdentifier_in() const;
- ParsedType ParseObjCTypeName(ObjCDeclSpec &DS, Declarator::TheContext Ctx,
+ ParsedType ParseObjCTypeName(ObjCDeclSpec &DS, DeclaratorContext Ctx,
ParsedAttributes *ParamAttrs);
void ParseObjCMethodRequirement();
Decl *ParseObjCMethodPrototype(
@@ -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();
@@ -1641,7 +1753,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
@@ -1737,11 +1850,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 +1895,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 +1931,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,
@@ -1856,7 +1970,7 @@ private:
/// A context for parsing declaration specifiers. TODO: flesh this
/// out, there are other significant restrictions on specifiers than
/// would be best implemented in the parser.
- enum DeclSpecContext {
+ enum class DeclSpecContext {
DSC_normal, // normal context
DSC_class, // class context, enables 'friend'
DSC_type_specifier, // C++ type-specifier-seq or C specifier-qualifier-list
@@ -1873,18 +1987,18 @@ private:
/// trailing-type-specifier)?
static bool isTypeSpecifier(DeclSpecContext DSC) {
switch (DSC) {
- case DSC_normal:
- case DSC_template_param:
- case DSC_class:
- case DSC_top_level:
- case DSC_objc_method_result:
- case DSC_condition:
+ case DeclSpecContext::DSC_normal:
+ case DeclSpecContext::DSC_template_param:
+ case DeclSpecContext::DSC_class:
+ case DeclSpecContext::DSC_top_level:
+ case DeclSpecContext::DSC_objc_method_result:
+ case DeclSpecContext::DSC_condition:
return false;
- case DSC_template_type_arg:
- case DSC_type_specifier:
- case DSC_trailing:
- case DSC_alias_declaration:
+ case DeclSpecContext::DSC_template_type_arg:
+ case DeclSpecContext::DSC_type_specifier:
+ case DeclSpecContext::DSC_trailing:
+ case DeclSpecContext::DSC_alias_declaration:
return true;
}
llvm_unreachable("Missing DeclSpecContext case");
@@ -1894,18 +2008,18 @@ private:
/// deduction?
static bool isClassTemplateDeductionContext(DeclSpecContext DSC) {
switch (DSC) {
- case DSC_normal:
- case DSC_template_param:
- case DSC_class:
- case DSC_top_level:
- case DSC_condition:
- case DSC_type_specifier:
+ case DeclSpecContext::DSC_normal:
+ case DeclSpecContext::DSC_template_param:
+ case DeclSpecContext::DSC_class:
+ case DeclSpecContext::DSC_top_level:
+ case DeclSpecContext::DSC_condition:
+ case DeclSpecContext::DSC_type_specifier:
return true;
- case DSC_objc_method_result:
- case DSC_template_type_arg:
- case DSC_trailing:
- case DSC_alias_declaration:
+ case DeclSpecContext::DSC_objc_method_result:
+ case DeclSpecContext::DSC_template_type_arg:
+ case DeclSpecContext::DSC_trailing:
+ case DeclSpecContext::DSC_alias_declaration:
return false;
}
llvm_unreachable("Missing DeclSpecContext case");
@@ -1920,15 +2034,16 @@ private:
bool ParsedForRangeDecl() { return !ColonLoc.isInvalid(); }
};
- DeclGroupPtrTy ParseDeclaration(unsigned Context, SourceLocation &DeclEnd,
+ DeclGroupPtrTy ParseDeclaration(DeclaratorContext Context,
+ SourceLocation &DeclEnd,
ParsedAttributesWithRange &attrs);
- DeclGroupPtrTy ParseSimpleDeclaration(unsigned Context,
+ DeclGroupPtrTy ParseSimpleDeclaration(DeclaratorContext Context,
SourceLocation &DeclEnd,
ParsedAttributesWithRange &attrs,
bool RequireSemi,
ForRangeInit *FRI = nullptr);
- bool MightBeDeclarator(unsigned Context);
- DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context,
+ bool MightBeDeclarator(DeclaratorContext Context);
+ DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, DeclaratorContext Context,
SourceLocation *DeclEnd = nullptr,
ForRangeInit *FRI = nullptr);
Decl *ParseDeclarationAfterDeclarator(Declarator &D,
@@ -1941,7 +2056,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.
@@ -1951,21 +2066,24 @@ private:
const ParsedTemplateInfo &TemplateInfo,
AccessSpecifier AS, DeclSpecContext DSC,
ParsedAttributesWithRange &Attrs);
- DeclSpecContext getDeclSpecContextFromDeclaratorContext(unsigned Context);
- void ParseDeclarationSpecifiers(DeclSpec &DS,
- const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
- AccessSpecifier AS = AS_none,
- DeclSpecContext DSC = DSC_normal,
- LateParsedAttrList *LateAttrs = nullptr);
- bool DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS,
- DeclSpecContext DSContext,
- LateParsedAttrList *LateAttrs = nullptr);
-
- void ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS = AS_none,
- DeclSpecContext DSC = DSC_normal);
+ DeclSpecContext
+ getDeclSpecContextFromDeclaratorContext(DeclaratorContext Context);
+ void ParseDeclarationSpecifiers(
+ DeclSpec &DS,
+ const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
+ AccessSpecifier AS = AS_none,
+ DeclSpecContext DSC = DeclSpecContext::DSC_normal,
+ LateParsedAttrList *LateAttrs = nullptr);
+ bool DiagnoseMissingSemiAfterTagDefinition(
+ DeclSpec &DS, AccessSpecifier AS, DeclSpecContext DSContext,
+ LateParsedAttrList *LateAttrs = nullptr);
+
+ void ParseSpecifierQualifierList(
+ DeclSpec &DS, AccessSpecifier AS = AS_none,
+ DeclSpecContext DSC = DeclSpecContext::DSC_normal);
void ParseObjCTypeQualifierList(ObjCDeclSpec &DS,
- Declarator::TheContext Context);
+ DeclaratorContext Context);
void ParseEnumSpecifier(SourceLocation TagLoc, DeclSpec &DS,
const ParsedTemplateInfo &TemplateInfo,
@@ -1986,7 +2104,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() {
@@ -2014,19 +2132,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,
@@ -2049,7 +2167,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() {
@@ -2087,7 +2205,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
@@ -2105,7 +2223,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++).
///
@@ -2133,7 +2251,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);
@@ -2151,7 +2269,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);
@@ -2161,8 +2280,8 @@ private:
public:
TypeResult ParseTypeName(SourceRange *Range = nullptr,
- Declarator::TheContext Context
- = Declarator::TypeNameContext,
+ DeclaratorContext Context
+ = DeclaratorContext::TypeNameContext,
AccessSpecifier AS = AS_none,
Decl **OwnedType = nullptr,
ParsedAttributes *Attrs = nullptr);
@@ -2202,14 +2321,23 @@ private:
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.isInvalid())
+ return;
+ DiagnoseProhibitedAttributes(Attrs.Range, FixItLoc);
+ Attrs.clear();
+ }
+
+ void ProhibitAttributes(ParsedAttributesViewWithRange &Attrs,
SourceLocation FixItLoc = SourceLocation()) {
- if (!attrs.Range.isValid()) return;
- DiagnoseProhibitedAttributes(attrs, FixItLoc);
- attrs.clear();
+ 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
@@ -2217,16 +2345,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.
@@ -2234,7 +2362,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) {
@@ -2257,19 +2385,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()) {
@@ -2299,7 +2424,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,
@@ -2335,7 +2460,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) {
@@ -2343,7 +2468,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);
@@ -2355,7 +2480,7 @@ private:
SourceLocation *endLoc,
IdentifierInfo *ScopeName,
SourceLocation ScopeLoc,
- AttributeList::Syntax Syntax);
+ ParsedAttr::Syntax Syntax);
Optional<AvailabilitySpec> ParseAvailabilitySpec();
ExprResult ParseAvailabilityCheckExpr(SourceLocation StartLoc);
@@ -2366,7 +2491,7 @@ private:
SourceLocation *EndLoc,
IdentifierInfo *ScopeName,
SourceLocation ScopeLoc,
- AttributeList::Syntax Syntax);
+ ParsedAttr::Syntax Syntax);
void ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated,
SourceLocation ObjCBridgeRelatedLoc,
@@ -2374,7 +2499,7 @@ private:
SourceLocation *endLoc,
IdentifierInfo *ScopeName,
SourceLocation ScopeLoc,
- AttributeList::Syntax Syntax);
+ ParsedAttr::Syntax Syntax);
void ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName,
SourceLocation AttrNameLoc,
@@ -2382,15 +2507,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);
@@ -2512,20 +2635,21 @@ private:
void DiagnoseUnexpectedNamespace(NamedDecl *Context);
- DeclGroupPtrTy ParseNamespace(unsigned Context, SourceLocation &DeclEnd,
+ DeclGroupPtrTy ParseNamespace(DeclaratorContext Context,
+ SourceLocation &DeclEnd,
SourceLocation InlineLoc = SourceLocation());
- void ParseInnerNamespace(std::vector<SourceLocation>& IdentLoc,
- std::vector<IdentifierInfo*>& Ident,
- std::vector<SourceLocation>& NamespaceLoc,
- unsigned int index, SourceLocation& InlineLoc,
- ParsedAttributes& attrs,
+ void ParseInnerNamespace(std::vector<SourceLocation> &IdentLoc,
+ std::vector<IdentifierInfo *> &Ident,
+ std::vector<SourceLocation> &NamespaceLoc,
+ unsigned int index, SourceLocation &InlineLoc,
+ ParsedAttributes &attrs,
BalancedDelimiterTracker &Tracker);
- Decl *ParseLinkage(ParsingDeclSpec &DS, unsigned Context);
+ Decl *ParseLinkage(ParsingDeclSpec &DS, DeclaratorContext Context);
Decl *ParseExportDeclaration();
DeclGroupPtrTy ParseUsingDirectiveOrDeclaration(
- unsigned Context, const ParsedTemplateInfo &TemplateInfo,
+ DeclaratorContext Context, const ParsedTemplateInfo &TemplateInfo,
SourceLocation &DeclEnd, ParsedAttributesWithRange &attrs);
- Decl *ParseUsingDirective(unsigned Context,
+ Decl *ParseUsingDirective(DeclaratorContext Context,
SourceLocation UsingLoc,
SourceLocation &DeclEnd,
ParsedAttributes &attrs);
@@ -2533,19 +2657,18 @@ 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();
}
};
- bool ParseUsingDeclarator(unsigned Context, UsingDeclarator &D);
- DeclGroupPtrTy ParseUsingDeclaration(unsigned Context,
+ bool ParseUsingDeclarator(DeclaratorContext Context, UsingDeclarator &D);
+ DeclGroupPtrTy ParseUsingDeclaration(DeclaratorContext Context,
const ParsedTemplateInfo &TemplateInfo,
SourceLocation UsingLoc,
SourceLocation &DeclEnd,
@@ -2586,7 +2709,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(
@@ -2623,18 +2746,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.
@@ -2646,7 +2769,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
@@ -2655,7 +2778,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.
@@ -2664,33 +2787,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
@@ -2702,6 +2837,7 @@ public:
struct OpenMPVarListDataTy {
Expr *TailExpr = nullptr;
SourceLocation ColonLoc;
+ SourceLocation RLoc;
CXXScopeSpec ReductionIdScopeSpec;
DeclarationNameInfo ReductionId;
OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown;
@@ -2721,7 +2857,7 @@ public:
bool AllowConstructorName,
bool AllowDeductionGuide,
ParsedType ObjectType,
- SourceLocation& TemplateKWLoc,
+ SourceLocation *TemplateKWLoc,
UnqualifiedId &Result);
private:
@@ -2729,21 +2865,18 @@ private:
// C++ 14: Templates [temp]
// C++ 14.1: Template Parameters [temp.param]
- Decl *ParseDeclarationStartingWithTemplate(unsigned Context,
- SourceLocation &DeclEnd,
- AccessSpecifier AS = AS_none,
- AttributeList *AccessAttrs = nullptr);
- Decl *ParseTemplateDeclarationOrSpecialization(unsigned Context,
+ Decl *ParseDeclarationStartingWithTemplate(DeclaratorContext Context,
+ SourceLocation &DeclEnd,
+ ParsedAttributes &AccessAttrs,
+ AccessSpecifier AS = AS_none);
+ Decl *ParseTemplateDeclarationOrSpecialization(DeclaratorContext Context,
SourceLocation &DeclEnd,
- AccessSpecifier AS,
- AttributeList *AccessAttrs);
+ ParsedAttributes &AccessAttrs,
+ AccessSpecifier AS);
Decl *ParseSingleDeclarationAfterTemplate(
- unsigned 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,
@@ -2782,10 +2915,11 @@ private:
bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs);
ParsedTemplateArgument ParseTemplateTemplateArgument();
ParsedTemplateArgument ParseTemplateArgument();
- Decl *ParseExplicitInstantiation(unsigned Context,
+ Decl *ParseExplicitInstantiation(DeclaratorContext Context,
SourceLocation ExternLoc,
SourceLocation TemplateLoc,
SourceLocation &DeclEnd,
+ ParsedAttributes &AccessAttrs,
AccessSpecifier AS = AS_none);
//===--------------------------------------------------------------------===//
diff --git a/include/clang/Parse/RAIIObjectsForParser.h b/include/clang/Parse/RAIIObjectsForParser.h
index 0422b038da65..f45d6434833e 100644
--- a/include/clang/Parse/RAIIObjectsForParser.h
+++ b/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
@@ -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.
@@ -202,7 +202,7 @@ namespace clang {
ParsingDeclRAIIObject ParsingRAII;
public:
- ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS, TheContext C)
+ ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS, DeclaratorContext C)
: Declarator(DS, C), ParsingRAII(P, &DS.getDelayedDiagnosticPool()) {
}
@@ -288,7 +288,7 @@ namespace clang {
}
};
- /// \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;
@@ -320,7 +320,7 @@ namespace clang {
}
};
- /// \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;
@@ -331,6 +331,7 @@ namespace clang {
BraceCount(p.BraceCount) { }
~ParenBraceBracketBalancer() {
+ P.AngleBrackets.clear(P);
P.ParenCount = ParenCount;
P.BracketCount = BracketCount;
P.BraceCount = BraceCount;
@@ -361,7 +362,7 @@ 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;
@@ -378,8 +379,6 @@ namespace clang {
}
}
- enum { MaxDepth = 256 };
-
bool diagnoseOverflow();
bool diagnoseMissingClose();
@@ -443,7 +442,7 @@ namespace clang {
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/include/clang/Rewrite/Core/DeltaTree.h b/include/clang/Rewrite/Core/DeltaTree.h
index fbffb38e377d..f798e9fc41eb 100644
--- a/include/clang/Rewrite/Core/DeltaTree.h
+++ b/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/include/clang/Rewrite/Core/HTMLRewrite.h b/include/clang/Rewrite/Core/HTMLRewrite.h
index 1fd7c7a3f84e..0f1f490d8305 100644
--- a/include/clang/Rewrite/Core/HTMLRewrite.h
+++ b/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/include/clang/Rewrite/Core/RewriteBuffer.h b/include/clang/Rewrite/Core/RewriteBuffer.h
index d69c69b81e48..c618298f5e82 100644
--- a/include/clang/Rewrite/Core/RewriteBuffer.h
+++ b/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/include/clang/Rewrite/Core/RewriteRope.h b/include/clang/Rewrite/Core/RewriteRope.h
index 50025544854a..2a0e0a4a639b 100644
--- a/include/clang/Rewrite/Core/RewriteRope.h
+++ b/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/include/clang/Rewrite/Core/Rewriter.h b/include/clang/Rewrite/Core/Rewriter.h
index 800372ea557f..107968a9fb43 100644
--- a/include/clang/Rewrite/Core/Rewriter.h
+++ b/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/include/clang/Rewrite/Core/TokenRewriter.h b/include/clang/Rewrite/Core/TokenRewriter.h
index 0f71e81c313e..ab2c2c8b0adb 100644
--- a/include/clang/Rewrite/Core/TokenRewriter.h
+++ b/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/include/clang/Rewrite/Frontend/FixItRewriter.h b/include/clang/Rewrite/Frontend/FixItRewriter.h
index 3b1b31e0cdee..7456840bc5c1 100644
--- a/include/clang/Rewrite/Frontend/FixItRewriter.h
+++ b/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/include/clang/Rewrite/Frontend/FrontendActions.h b/include/clang/Rewrite/Frontend/FrontendActions.h
index 5f83ac16fedf..40d2f4c22afe 100644
--- a/include/clang/Rewrite/Frontend/FrontendActions.h
+++ b/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/include/clang/Sema/AnalysisBasedWarnings.h b/include/clang/Sema/AnalysisBasedWarnings.h
index 64dd2d36bef8..6e8d83974e5b 100644
--- a/include/clang/Sema/AnalysisBasedWarnings.h
+++ b/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/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h
index 5d280b5608e7..ede3ddf91993 100644
--- a/include/clang/Sema/CodeCompleteConsumer.h
+++ b/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/include/clang/Sema/CodeCompleteOptions.h b/include/clang/Sema/CodeCompleteOptions.h
index 091d8ca60505..1d3bbb4e585d 100644
--- a/include/clang/Sema/CodeCompleteOptions.h
+++ b/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/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h
index 760a04d3c8d2..83d5ab2cff85 100644
--- a/include/clang/Sema/DeclSpec.h
+++ b/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()
@@ -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.
+ /// 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
@@ -134,11 +134,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
@@ -154,7 +154,7 @@ 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
@@ -163,18 +163,18 @@ 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 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,7 +195,7 @@ 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.
+ /// 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())
@@ -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,
@@ -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));
@@ -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,42 +892,45 @@ private:
};
-/// \brief Represents a C++ unqualified-id that has been parsed.
+/// Describes the kind of unqualified-id parsed.
+enum class UnqualifiedIdKind {
+ /// An identifier.
+ IK_Identifier,
+ /// An overloaded operator name, e.g., operator+.
+ IK_OperatorFunctionId,
+ /// A conversion function name, e.g., operator int.
+ IK_ConversionFunctionId,
+ /// A user-defined literal name, e.g., operator "" _i.
+ IK_LiteralOperatorId,
+ /// A constructor name.
+ IK_ConstructorName,
+ /// A constructor named via a template-id.
+ IK_ConstructorTemplateId,
+ /// A destructor name.
+ IK_DestructorName,
+ /// A template-id, e.g., f<int>.
+ IK_TemplateId,
+ /// An implicit 'self' parameter
+ IK_ImplicitSelfParam,
+ /// A deduction-guide name (a template-name)
+ IK_DeductionGuideName
+};
+
+/// Represents a C++ unqualified-id that has been parsed.
class UnqualifiedId {
private:
UnqualifiedId(const UnqualifiedId &Other) = delete;
const UnqualifiedId &operator=(const UnqualifiedId &) = delete;
public:
- /// \brief Describes the kind of unqualified-id parsed.
- enum IdKind {
- /// \brief An identifier.
- IK_Identifier,
- /// \brief An overloaded operator name, e.g., operator+.
- IK_OperatorFunctionId,
- /// \brief A conversion function name, e.g., operator int.
- IK_ConversionFunctionId,
- /// \brief A user-defined literal name, e.g., operator "" _i.
- IK_LiteralOperatorId,
- /// \brief A constructor name.
- IK_ConstructorName,
- /// \brief A constructor named via a template-id.
- IK_ConstructorTemplateId,
- /// \brief A destructor name.
- IK_DestructorName,
- /// \brief A template-id, e.g., f<int>.
- IK_TemplateId,
- /// \brief An implicit 'self' parameter
- IK_ImplicitSelfParam,
- /// \brief A deduction-guide name (a template-name)
- IK_DeductionGuideName
- } Kind;
+ /// 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 source locations of the individual tokens that name
/// the operator, e.g., the "new", "[", and "]" tokens in
/// operator new [].
///
@@ -927,78 +940,79 @@ 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(IK_Identifier), Identifier(nullptr) { }
- /// \brief Clear out this unqualified-id, setting it to default (invalid)
+ UnqualifiedId()
+ : Kind(UnqualifiedIdKind::IK_Identifier), Identifier(nullptr) {}
+
+ /// Clear out this unqualified-id, setting it to default (invalid)
/// state.
void clear() {
- Kind = IK_Identifier;
+ Kind = UnqualifiedIdKind::IK_Identifier;
Identifier = nullptr;
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.
- IdKind getKind() const { return Kind; }
- void setKind(IdKind kind) { Kind = kind; }
+ /// 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.
+ /// Specify that this unqualified-id was parsed as an identifier.
///
/// \param Id the parsed identifier.
/// \param IdLoc the location of the parsed identifier.
void setIdentifier(const IdentifierInfo *Id, SourceLocation IdLoc) {
- Kind = IK_Identifier;
+ Kind = UnqualifiedIdKind::IK_Identifier;
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,7 +1025,7 @@ public:
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.
@@ -1022,13 +1036,13 @@ public:
void setConversionFunctionId(SourceLocation OperatorLoc,
ParsedType Ty,
SourceLocation EndLoc) {
- Kind = IK_ConversionFunctionId;
+ Kind = UnqualifiedIdKind::IK_ConversionFunctionId;
StartLocation = OperatorLoc;
EndLocation = EndLoc;
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.
@@ -1038,13 +1052,13 @@ public:
/// \param IdLoc the location of the identifier.
void setLiteralOperatorId(const IdentifierInfo *Id, SourceLocation OpLoc,
SourceLocation IdLoc) {
- Kind = IK_LiteralOperatorId;
+ Kind = UnqualifiedIdKind::IK_LiteralOperatorId;
Identifier = const_cast<IdentifierInfo *>(Id);
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.
///
@@ -1054,13 +1068,13 @@ public:
void setConstructorName(ParsedType ClassType,
SourceLocation ClassNameLoc,
SourceLocation EndLoc) {
- Kind = IK_ConstructorName;
+ Kind = UnqualifiedIdKind::IK_ConstructorName;
StartLocation = ClassNameLoc;
EndLocation = EndLoc;
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
@@ -1068,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.
@@ -1077,32 +1091,32 @@ public:
void setDestructorName(SourceLocation TildeLoc,
ParsedType ClassType,
SourceLocation EndLoc) {
- Kind = IK_DestructorName;
+ Kind = UnqualifiedIdKind::IK_DestructorName;
StartLocation = TildeLoc;
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.
/// \param TemplateLoc The location of the parsed template-name.
void setDeductionGuideName(ParsedTemplateTy Template,
SourceLocation TemplateLoc) {
- Kind = IK_DeductionGuideName;
+ Kind = UnqualifiedIdKind::IK_DeductionGuideName;
TemplateName = Template;
StartLocation = EndLocation = TemplateLoc;
}
- /// \brief Return the source range that covers this unqualified-id.
+ /// Return the source range that covers this unqualified-id.
SourceRange getSourceRange() const LLVM_READONLY {
return SourceRange(StartLocation, EndLocation);
}
@@ -1110,10 +1124,10 @@ public:
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.
@@ -1133,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;
@@ -1160,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.
@@ -1169,7 +1181,7 @@ struct DeclaratorChunk {
}
};
- struct ArrayTypeInfo : TypeInfoCommon {
+ struct ArrayTypeInfo {
/// The type qualifiers for the array:
/// const/volatile/restrict/__unaligned/_Atomic.
unsigned TypeQuals : 5;
@@ -1220,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.
@@ -1234,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;
@@ -1270,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
@@ -1306,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;
@@ -1325,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() {
@@ -1343,8 +1355,7 @@ struct DeclaratorChunk {
}
void destroy() {
- if (DeleteParams)
- delete[] Params;
+ freeParams();
switch (getExceptionSpecType()) {
default:
break;
@@ -1390,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;
@@ -1458,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.
@@ -1475,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;
@@ -1506,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,
@@ -1532,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;
@@ -1544,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) {
@@ -1556,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;
@@ -1593,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;
}
@@ -1623,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;
}
@@ -1696,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,
@@ -1705,21 +1703,7 @@ enum FunctionDefinitionKind {
FDK_Deleted
};
-/// \brief Information about one declarator, including the parsed type
-/// information and the identifier.
-///
-/// When the declarator is fully formed, this is turned into the appropriate
-/// Decl object.
-///
-/// Declarators come in two types: normal declarators and abstract declarators.
-/// Abstract declarators are used when parsing types, and don't have an
-/// identifier. Normal declarators do have ID's.
-///
-/// Instances of this class should be a transient object that lives on the
-/// stack, not objects that are allocated in large quantities on the heap.
-class Declarator {
-public:
- enum TheContext {
+enum class DeclaratorContext {
FileContext, // File scope declaration.
PrototypeContext, // Within a function prototype.
ObjCResultContext, // An ObjC method result type.
@@ -1741,19 +1725,36 @@ public:
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.
- };
+};
+
+/// Information about one declarator, including the parsed type
+/// information and the identifier.
+///
+/// When the declarator is fully formed, this is turned into the appropriate
+/// Decl object.
+///
+/// Declarators come in two types: normal declarators and abstract declarators.
+/// Abstract declarators are used when parsing types, and don't have an
+/// identifier. Normal declarators do have ID's.
+///
+/// Instances of this class should be a transient object that lives on the
+/// stack, not objects that are allocated in large quantities on the heap.
+class Declarator {
+
private:
const DeclSpec &DS;
CXXScopeSpec SS;
UnqualifiedId Name;
SourceRange Range;
- /// \brief Where we are parsing this declarator.
- TheContext Context;
+ /// Where we are parsing this declarator.
+ DeclaratorContext Context;
/// The C++17 structured binding, if any. This is an alternative to a Name.
DecompositionDeclarator BindingGroup;
@@ -1776,10 +1777,10 @@ private:
/// 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.
@@ -1794,7 +1795,7 @@ private:
/// Attrs - Attributes.
ParsedAttributes Attrs;
- /// \brief The asm label, if specified.
+ /// The asm label, if specified.
Expr *AsmLabel;
#ifndef _MSC_VER
@@ -1809,18 +1810,18 @@ 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:
- Declarator(const DeclSpec &ds, TheContext C)
+ Declarator(const DeclSpec &ds, DeclaratorContext C)
: DS(ds), Range(ds.getSourceRange()), Context(C),
InvalidType(DS.getTypeSpecType() == DeclSpec::TST_error),
GroupingParens(false), FunctionDefinition(FDK_Declaration),
@@ -1851,23 +1852,23 @@ 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;
}
- TheContext getContext() const { return Context; }
+ DeclaratorContext getContext() const { return Context; }
bool isPrototypeContext() const {
- return (Context == PrototypeContext ||
- Context == ObjCParameterContext ||
- Context == ObjCResultContext ||
- Context == LambdaExprParameterContext);
+ return (Context == DeclaratorContext::PrototypeContext ||
+ Context == DeclaratorContext::ObjCParameterContext ||
+ Context == DeclaratorContext::ObjCResultContext ||
+ 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(); }
@@ -1895,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();
@@ -1919,32 +1920,34 @@ public:
/// parameter lists.
bool mayOmitIdentifier() const {
switch (Context) {
- case FileContext:
- case KNRTypeListContext:
- case MemberContext:
- case BlockContext:
- case ForContext:
- case InitStmtContext:
- case ConditionContext:
+ case DeclaratorContext::FileContext:
+ case DeclaratorContext::KNRTypeListContext:
+ case DeclaratorContext::MemberContext:
+ case DeclaratorContext::BlockContext:
+ case DeclaratorContext::ForContext:
+ case DeclaratorContext::InitStmtContext:
+ case DeclaratorContext::ConditionContext:
return false;
- case TypeNameContext:
- case FunctionalCastContext:
- case AliasDeclContext:
- case AliasTemplateContext:
- case PrototypeContext:
- case LambdaExprParameterContext:
- case ObjCParameterContext:
- case ObjCResultContext:
- case TemplateParamContext:
- case CXXNewContext:
- case CXXCatchContext:
- case ObjCCatchContext:
- case BlockLiteralContext:
- case LambdaExprContext:
- case ConversionIdContext:
- case TemplateTypeArgContext:
- case TrailingReturnContext:
+ case DeclaratorContext::TypeNameContext:
+ case DeclaratorContext::FunctionalCastContext:
+ case DeclaratorContext::AliasDeclContext:
+ case DeclaratorContext::AliasTemplateContext:
+ case DeclaratorContext::PrototypeContext:
+ case DeclaratorContext::LambdaExprParameterContext:
+ case DeclaratorContext::ObjCParameterContext:
+ case DeclaratorContext::ObjCResultContext:
+ case DeclaratorContext::TemplateParamContext:
+ case DeclaratorContext::CXXNewContext:
+ case DeclaratorContext::CXXCatchContext:
+ case DeclaratorContext::ObjCCatchContext:
+ 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!");
@@ -1955,32 +1958,34 @@ public:
/// typenames.
bool mayHaveIdentifier() const {
switch (Context) {
- case FileContext:
- case KNRTypeListContext:
- case MemberContext:
- case BlockContext:
- case ForContext:
- case InitStmtContext:
- case ConditionContext:
- case PrototypeContext:
- case LambdaExprParameterContext:
- case TemplateParamContext:
- case CXXCatchContext:
- case ObjCCatchContext:
+ case DeclaratorContext::FileContext:
+ case DeclaratorContext::KNRTypeListContext:
+ case DeclaratorContext::MemberContext:
+ case DeclaratorContext::BlockContext:
+ case DeclaratorContext::ForContext:
+ case DeclaratorContext::InitStmtContext:
+ case DeclaratorContext::ConditionContext:
+ case DeclaratorContext::PrototypeContext:
+ case DeclaratorContext::LambdaExprParameterContext:
+ case DeclaratorContext::TemplateParamContext:
+ case DeclaratorContext::CXXCatchContext:
+ case DeclaratorContext::ObjCCatchContext:
return true;
- case TypeNameContext:
- case FunctionalCastContext:
- case CXXNewContext:
- case AliasDeclContext:
- case AliasTemplateContext:
- case ObjCParameterContext:
- case ObjCResultContext:
- case BlockLiteralContext:
- case LambdaExprContext:
- case ConversionIdContext:
- case TemplateTypeArgContext:
- case TrailingReturnContext:
+ case DeclaratorContext::TypeNameContext:
+ case DeclaratorContext::FunctionalCastContext:
+ case DeclaratorContext::CXXNewContext:
+ case DeclaratorContext::AliasDeclContext:
+ case DeclaratorContext::AliasTemplateContext:
+ case DeclaratorContext::ObjCParameterContext:
+ case DeclaratorContext::ObjCResultContext:
+ 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!");
@@ -1989,38 +1994,40 @@ public:
/// Return true if the context permits a C++17 decomposition declarator.
bool mayHaveDecompositionDeclarator() const {
switch (Context) {
- case FileContext:
+ case DeclaratorContext::FileContext:
// FIXME: It's not clear that the proposal meant to allow file-scope
// structured bindings, but it does.
- case BlockContext:
- case ForContext:
- case InitStmtContext:
- case ConditionContext:
+ case DeclaratorContext::BlockContext:
+ case DeclaratorContext::ForContext:
+ case DeclaratorContext::InitStmtContext:
+ case DeclaratorContext::ConditionContext:
return true;
- case MemberContext:
- case PrototypeContext:
- case TemplateParamContext:
+ case DeclaratorContext::MemberContext:
+ case DeclaratorContext::PrototypeContext:
+ case DeclaratorContext::TemplateParamContext:
// Maybe one day...
return false;
// These contexts don't allow any kind of non-abstract declarator.
- case KNRTypeListContext:
- case TypeNameContext:
- case FunctionalCastContext:
- case AliasDeclContext:
- case AliasTemplateContext:
- case LambdaExprParameterContext:
- case ObjCParameterContext:
- case ObjCResultContext:
- case CXXNewContext:
- case CXXCatchContext:
- case ObjCCatchContext:
- case BlockLiteralContext:
- case LambdaExprContext:
- case ConversionIdContext:
- case TemplateTypeArgContext:
- case TrailingReturnContext:
+ case DeclaratorContext::KNRTypeListContext:
+ case DeclaratorContext::TypeNameContext:
+ case DeclaratorContext::FunctionalCastContext:
+ case DeclaratorContext::AliasDeclContext:
+ case DeclaratorContext::AliasTemplateContext:
+ case DeclaratorContext::LambdaExprParameterContext:
+ case DeclaratorContext::ObjCParameterContext:
+ case DeclaratorContext::ObjCResultContext:
+ case DeclaratorContext::CXXNewContext:
+ case DeclaratorContext::CXXCatchContext:
+ case DeclaratorContext::ObjCCatchContext:
+ 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!");
@@ -2035,45 +2042,47 @@ public:
return false;
if (getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_extern &&
- Context != FileContext)
+ Context != DeclaratorContext::FileContext)
return false;
// Special names can't have direct initializers.
- if (Name.getKind() != UnqualifiedId::IK_Identifier)
+ if (Name.getKind() != UnqualifiedIdKind::IK_Identifier)
return false;
switch (Context) {
- case FileContext:
- case BlockContext:
- case ForContext:
- case InitStmtContext:
+ case DeclaratorContext::FileContext:
+ case DeclaratorContext::BlockContext:
+ case DeclaratorContext::ForContext:
+ case DeclaratorContext::InitStmtContext:
+ case DeclaratorContext::TrailingReturnVarContext:
return true;
- case ConditionContext:
+ case DeclaratorContext::ConditionContext:
// This may not be followed by a direct initializer, but it can't be a
// function declaration either, and we'd prefer to perform a tentative
// parse in order to produce the right diagnostic.
return true;
- case KNRTypeListContext:
- case MemberContext:
- case PrototypeContext:
- case LambdaExprParameterContext:
- case ObjCParameterContext:
- case ObjCResultContext:
- case TemplateParamContext:
- case CXXCatchContext:
- case ObjCCatchContext:
- case TypeNameContext:
- case FunctionalCastContext: // FIXME
- case CXXNewContext:
- case AliasDeclContext:
- case AliasTemplateContext:
- case BlockLiteralContext:
- case LambdaExprContext:
- case ConversionIdContext:
- case TemplateTypeArgContext:
- case TrailingReturnContext:
+ case DeclaratorContext::KNRTypeListContext:
+ case DeclaratorContext::MemberContext:
+ case DeclaratorContext::PrototypeContext:
+ case DeclaratorContext::LambdaExprParameterContext:
+ case DeclaratorContext::ObjCParameterContext:
+ case DeclaratorContext::ObjCResultContext:
+ case DeclaratorContext::TemplateParamContext:
+ case DeclaratorContext::CXXCatchContext:
+ case DeclaratorContext::ObjCCatchContext:
+ case DeclaratorContext::TypeNameContext:
+ case DeclaratorContext::FunctionalCastContext: // FIXME
+ case DeclaratorContext::CXXNewContext:
+ case DeclaratorContext::AliasDeclContext:
+ case DeclaratorContext::AliasTemplateContext:
+ case DeclaratorContext::BlockLiteralContext:
+ case DeclaratorContext::LambdaExprContext:
+ case DeclaratorContext::ConversionIdContext:
+ case DeclaratorContext::TemplateArgContext:
+ case DeclaratorContext::TemplateTypeArgContext:
+ case DeclaratorContext::TrailingReturnContext:
return false;
}
llvm_unreachable("unknown context kind!");
@@ -2089,8 +2098,8 @@ public:
/// special C++ name (constructor, destructor, etc.), or a structured
/// binding (which is not exactly a name, but occupies the same position).
bool hasName() const {
- return Name.getKind() != UnqualifiedId::IK_Identifier || Name.Identifier ||
- isDecompositionDeclarator();
+ return Name.getKind() != UnqualifiedIdKind::IK_Identifier ||
+ Name.Identifier || isDecompositionDeclarator();
}
/// Return whether this declarator is a decomposition declarator.
@@ -2099,14 +2108,14 @@ public:
}
IdentifierInfo *getIdentifier() const {
- if (Name.getKind() == UnqualifiedId::IK_Identifier)
+ 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);
}
@@ -2119,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
@@ -2242,7 +2261,7 @@ 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
@@ -2250,39 +2269,41 @@ public:
/// 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)
return false;
switch (Context) {
- case FileContext:
- case MemberContext:
- case BlockContext:
- case ForContext:
- case InitStmtContext:
+ case DeclaratorContext::FileContext:
+ case DeclaratorContext::MemberContext:
+ case DeclaratorContext::BlockContext:
+ case DeclaratorContext::ForContext:
+ case DeclaratorContext::InitStmtContext:
return true;
- case ConditionContext:
- case KNRTypeListContext:
- case TypeNameContext:
- case FunctionalCastContext:
- case AliasDeclContext:
- case AliasTemplateContext:
- case PrototypeContext:
- case LambdaExprParameterContext:
- case ObjCParameterContext:
- case ObjCResultContext:
- case TemplateParamContext:
- case CXXNewContext:
- case CXXCatchContext:
- case ObjCCatchContext:
- case BlockLiteralContext:
- case LambdaExprContext:
- case ConversionIdContext:
- case TemplateTypeArgContext:
- case TrailingReturnContext:
+ case DeclaratorContext::ConditionContext:
+ case DeclaratorContext::KNRTypeListContext:
+ case DeclaratorContext::TypeNameContext:
+ case DeclaratorContext::FunctionalCastContext:
+ case DeclaratorContext::AliasDeclContext:
+ case DeclaratorContext::AliasTemplateContext:
+ case DeclaratorContext::PrototypeContext:
+ case DeclaratorContext::LambdaExprParameterContext:
+ case DeclaratorContext::ObjCParameterContext:
+ case DeclaratorContext::ObjCResultContext:
+ case DeclaratorContext::TemplateParamContext:
+ case DeclaratorContext::CXXNewContext:
+ case DeclaratorContext::CXXCatchContext:
+ case DeclaratorContext::ObjCCatchContext:
+ 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!");
@@ -2292,39 +2313,44 @@ public:
/// expression could appear.
bool isExpressionContext() const {
switch (Context) {
- case FileContext:
- case KNRTypeListContext:
- case MemberContext:
- case TypeNameContext: // FIXME: sizeof(...) permits an expression.
- case FunctionalCastContext:
- case AliasDeclContext:
- case AliasTemplateContext:
- case PrototypeContext:
- case LambdaExprParameterContext:
- case ObjCParameterContext:
- case ObjCResultContext:
- case TemplateParamContext:
- case CXXNewContext:
- case CXXCatchContext:
- case ObjCCatchContext:
- case BlockLiteralContext:
- case LambdaExprContext:
- case ConversionIdContext:
- case TrailingReturnContext:
+ case DeclaratorContext::FileContext:
+ case DeclaratorContext::KNRTypeListContext:
+ case DeclaratorContext::MemberContext:
+
+ // FIXME: sizeof(...) permits an expression.
+ case DeclaratorContext::TypeNameContext:
+
+ case DeclaratorContext::FunctionalCastContext:
+ case DeclaratorContext::AliasDeclContext:
+ case DeclaratorContext::AliasTemplateContext:
+ case DeclaratorContext::PrototypeContext:
+ case DeclaratorContext::LambdaExprParameterContext:
+ case DeclaratorContext::ObjCParameterContext:
+ case DeclaratorContext::ObjCResultContext:
+ case DeclaratorContext::TemplateParamContext:
+ case DeclaratorContext::CXXNewContext:
+ case DeclaratorContext::CXXCatchContext:
+ case DeclaratorContext::ObjCCatchContext:
+ case DeclaratorContext::BlockLiteralContext:
+ case DeclaratorContext::LambdaExprContext:
+ case DeclaratorContext::ConversionIdContext:
+ case DeclaratorContext::TrailingReturnContext:
+ case DeclaratorContext::TrailingReturnVarContext:
+ case DeclaratorContext::TemplateTypeArgContext:
return false;
- case BlockContext:
- case ForContext:
- case InitStmtContext:
- case ConditionContext:
- case TemplateTypeArgContext:
+ case DeclaratorContext::BlockContext:
+ case DeclaratorContext::ForContext:
+ case DeclaratorContext::InitStmtContext:
+ case DeclaratorContext::ConditionContext:
+ 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())
@@ -2337,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())
@@ -2363,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; }
@@ -2430,7 +2452,8 @@ public:
/// Returns true if this declares a real member and not a friend.
bool isFirstDeclarationOfMember() {
- return getContext() == MemberContext && !getDeclSpec().isFriendSpecified();
+ return getContext() == DeclaratorContext::MemberContext &&
+ !getDeclSpec().isFriendSpecified();
}
/// Returns true if this declares a static member. This cannot be called on a
@@ -2445,16 +2468,17 @@ 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;
Expr *BitfieldSize;
explicit FieldDeclarator(const DeclSpec &DS)
- : D(DS, Declarator::MemberContext), BitfieldSize(nullptr) { }
+ : D(DS, DeclaratorContext::MemberContext),
+ BitfieldSize(nullptr) {}
};
-/// \brief Represents a C++11 virt-specifier-seq.
+/// Represents a C++11 virt-specifier-seq.
class VirtSpecifiers {
public:
enum Specifier {
@@ -2504,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;
@@ -2515,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;
@@ -2531,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) {
+ ParsedType InitCaptureType,
+ SourceRange ExplicitRange) {
Captures.push_back(LambdaCapture(Kind, Loc, Id, EllipsisLoc, InitKind, Init,
- InitCaptureType));
+ InitCaptureType, ExplicitRange));
}
};
diff --git a/include/clang/Sema/DelayedDiagnostic.h b/include/clang/Sema/DelayedDiagnostic.h
index d65dbf0cd34e..76aa4546d749 100644
--- a/include/clang/Sema/DelayedDiagnostic.h
+++ b/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/include/clang/Sema/ExternalSemaSource.h b/include/clang/Sema/ExternalSemaSource.h
index c5cb7b12b3f1..42754b33e2df 100644
--- a/include/clang/Sema/ExternalSemaSource.h
+++ b/include/clang/Sema/ExternalSemaSource.h
@@ -39,7 +39,7 @@ 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;
@@ -47,7 +47,7 @@ struct ExternalVTableUse {
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
@@ -107,7 +107,7 @@ public:
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
@@ -117,7 +117,7 @@ public:
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,7 +145,7 @@ 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
@@ -155,7 +155,7 @@ public:
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
@@ -165,14 +165,14 @@ public:
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
@@ -183,7 +183,7 @@ public:
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
diff --git a/include/clang/Sema/IdentifierResolver.h b/include/clang/Sema/IdentifierResolver.h
index 382fe80bea7d..ea6c3df74af0 100644
--- a/include/clang/Sema/IdentifierResolver.h
+++ b/include/clang/Sema/IdentifierResolver.h
@@ -15,16 +15,20 @@
#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;
@@ -33,17 +37,16 @@ class Scope;
/// 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,7 +54,7 @@ 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);
}
@@ -61,30 +64,32 @@ class IdentifierResolver {
};
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.
@@ -170,9 +177,6 @@ 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;
@@ -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/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h
index bd07b9ea9aee..7a510f391bda 100644
--- a/include/clang/Sema/Initialization.h
+++ b/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,75 +126,79 @@ 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.
unsigned Index;
@@ -172,57 +206,52 @@ private:
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} { }
+ : Kind(EK), Type(Var->getType()), Variable{Var, false, false} {}
- /// \brief Create the initialization entity for the result of a
+ /// 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} {
- }
+ bool Implicit, bool DefaultMemberInit)
+ : Kind(EK_Member), Parent(Parent), Type(Member->getType()),
+ Variable{Member, Implicit, DefaultMemberInit} {}
- /// \brief Create the initialization entity for an array element.
+ /// 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,28 +304,28 @@ 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);
@@ -299,7 +333,7 @@ public:
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.
+ /// 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,19 +401,18 @@ 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)
@@ -383,17 +421,17 @@ public:
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,71 +439,81 @@ 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!");
@@ -486,51 +534,70 @@ 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,
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,7 +643,7 @@ public:
TypeRange.getBegin(), TypeRange.getEnd());
}
- /// \brief Create a copy initialization.
+ /// Create a copy initialization.
static InitializationKind CreateCopy(SourceLocation InitLoc,
SourceLocation EqualLoc,
bool AllowExplicitConvs = false) {
@@ -578,12 +652,12 @@ public:
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.
+ /// 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.
+ /// 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;
}
+
+ /// 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;
+ }
- /// \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");
+ /// 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,7 +915,7 @@ public:
};
union {
- /// \brief When Kind == SK_ResolvedOverloadedFunction or Kind ==
+ /// 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,
@@ -807,11 +927,11 @@ 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;
};
@@ -820,114 +940,154 @@ public:
};
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,13 +1095,12 @@ 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
@@ -972,7 +1131,7 @@ public:
~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.
@@ -999,7 +1158,7 @@ public:
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,
/// false otherwise.
@@ -1008,37 +1167,39 @@ public:
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.
@@ -1068,14 +1229,14 @@ public:
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,59 +1292,59 @@ 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;
@@ -1191,44 +1352,44 @@ public:
"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/include/clang/Sema/Lookup.h b/include/clang/Sema/Lookup.h
index 546df8842a35..c06952064dd9 100644
--- a/include/clang/Sema/Lookup.h
+++ b/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
+ /// 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;
+ bool Changed = false;
+ bool CalledDone = false;
- friend class LookupResult;
- Filter(LookupResult &Results)
- : Results(Results), I(Results.begin()), Changed(false), 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/include/clang/Sema/LoopHint.h b/include/clang/Sema/LoopHint.h
index c8b2ee845e59..171435e69bc8 100644
--- a/include/clang/Sema/LoopHint.h
+++ b/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/include/clang/Sema/MultiplexExternalSemaSource.h b/include/clang/Sema/MultiplexExternalSemaSource.h
index 1d681a00552f..4c242c89f3f4 100644
--- a/include/clang/Sema/MultiplexExternalSemaSource.h
+++ b/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 {
@@ -43,7 +43,7 @@ private:
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,17 +111,17 @@ 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.
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
@@ -129,28 +129,32 @@ public:
/// \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
/// layout for a record, overriding the layout that would normally be
@@ -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,7 +284,7 @@ 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
@@ -290,7 +294,7 @@ public:
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
@@ -300,14 +304,14 @@ public:
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.
///
diff --git a/include/clang/Sema/ObjCMethodList.h b/include/clang/Sema/ObjCMethodList.h
index 80ccd363d272..d0af4d15fb9f 100644
--- a/include/clang/Sema/ObjCMethodList.h
+++ b/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/include/clang/Sema/Overload.h b/include/clang/Sema/Overload.h
index 05cfe53666ca..f75faf049625 100644
--- a/include/clang/Sema/Overload.h
+++ b/include/clang/Sema/Overload.h
@@ -1,4 +1,4 @@
-//===--- Overload.h - C++ Overloading ---------------------------*- C++ -*-===//
+//===- Overload.h - C++ Overloading -----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,32 +16,51 @@
#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 {
@@ -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,12 +244,12 @@ 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;
@@ -176,21 +265,21 @@ 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;
@@ -213,10 +302,12 @@ namespace clang {
DeclAccessPair FoundCopyConstructor;
void setFromType(QualType T) { FromTypePtr = T.getAsOpaquePtr(); }
+
void setToType(unsigned Idx, QualType T) {
assert(Idx < 3 && "To type index is out of range");
ToTypePtrs[Idx] = T.getAsOpaquePtr();
}
+
void setAllToTypes(QualType T) {
ToTypePtrs[0] = T.getAsOpaquePtr();
ToTypePtrs[1] = ToTypePtrs[0];
@@ -226,6 +317,7 @@ 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]);
@@ -238,9 +330,10 @@ namespace clang {
}
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.
///
@@ -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,7 +775,7 @@ 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;
@@ -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/include/clang/Sema/Ownership.h b/include/clang/Sema/Ownership.h
index 1e35316fd5dd..ae2f178df1ec 100644
--- a/include/clang/Sema/Ownership.h
+++ b/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/include/clang/Sema/AttributeList.h b/include/clang/Sema/ParsedAttr.h
index 4e806116c4d9..3f293247787c 100644
--- a/include/clang/Sema/AttributeList.h
+++ b/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,18 +176,12 @@ 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;
-
/// Arguments, if any, are stored immediately following the object.
ArgsUnion *getArgsBuffer() { return reinterpret_cast<ArgsUnion *>(this + 1); }
ArgsUnion const *getArgsBuffer() const {
@@ -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,17 +250,15 @@ 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;
@@ -298,15 +267,15 @@ private:
}
/// 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,36 +286,72 @@ 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:
+ 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"
@@ -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*>();
}
@@ -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/include/clang/Sema/ParsedTemplate.h b/include/clang/Sema/ParsedTemplate.h
index 01a4ab3f37a5..f79157ba813e 100644
--- a/include/clang/Sema/ParsedTemplate.h
+++ b/include/clang/Sema/ParsedTemplate.h
@@ -26,32 +26,32 @@
#include <new>
namespace clang {
- /// \brief Represents the parsed form of a C++ template argument.
+ /// 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.
@@ -67,34 +67,34 @@ namespace clang {
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 &&
@@ -102,7 +102,7 @@ namespace clang {
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 &&
@@ -110,7 +110,7 @@ namespace clang {
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.
@@ -120,24 +120,24 @@ namespace clang {
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,
@@ -149,7 +149,7 @@ namespace clang {
: 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.
@@ -184,12 +184,12 @@ namespace clang {
/// NumArgs - The number of template arguments.
unsigned NumArgs;
- /// \brief Retrieves a pointer to the template arguments
+ /// 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,
diff --git a/include/clang/Sema/Scope.h b/include/clang/Sema/Scope.h
index cd58a9910f98..a3379ff34f12 100644
--- a/include/clang/Sema/Scope.h
+++ b/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) {
@@ -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/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h
index c707a3e8ef07..5eac2845fd33 100644
--- a/include/clang/Sema/ScopeInfo.h
+++ b/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;
@@ -74,10 +88,10 @@ public:
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:
@@ -89,30 +103,29 @@ protected:
};
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,179 +468,165 @@ 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 CapturingScopeInfo : public FunctionScopeInfo {
-protected:
- CapturingScopeInfo(const CapturingScopeInfo&) = default;
+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:
- enum ImplicitCaptureStyle {
- ImpCap_None, ImpCap_LambdaByval, ImpCap_LambdaByref, ImpCap_Block,
- ImpCap_CapturedRegion
- };
+ 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) {}
- ImplicitCaptureStyle ImpCaptureStyle;
+ 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) {}
- 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;
+ bool isThisCapture() const {
+ return VarAndNestedAndThis.getInt() & IsThisCaptured;
+ }
- /// \brief The location of the ellipsis that expands a parameter pack.
- SourceLocation EllipsisLoc;
+ bool isVariableCapture() const {
+ return !isThisCapture() && !isVLATypeCapture();
+ }
- /// \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;
+ bool isCopyCapture() const {
+ return InitExprAndCaptureKind.getInt() == Cap_ByCopy;
+ }
- /// \brief Whether an explicit capture has been odr-used in the body of the
- /// lambda.
- bool ODRUsed;
+ bool isReferenceCapture() const {
+ return InitExprAndCaptureKind.getInt() == Cap_ByRef;
+ }
- /// \brief Whether an explicit capture has been non-odr-used in the body of
- /// the lambda.
- bool NonODRUsed;
+ bool isBlockCapture() const {
+ return InitExprAndCaptureKind.getInt() == Cap_Block;
+ }
- 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; }
+ bool isVLATypeCapture() const {
+ return InitExprAndCaptureKind.getInt() == Cap_VLA;
+ }
- 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;
- }
+ bool isNested() const {
+ return VarAndNestedAndThis.getInt() & IsNestedCapture;
+ }
- Expr *getInitExpr() const {
- assert(!isVLATypeCapture() && "no init expression for type capture");
- return static_cast<Expr *>(InitExprAndCaptureKind.getPointer());
- }
+ 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;
+
+public:
+ enum ImplicitCaptureStyle {
+ ImpCap_None, ImpCap_LambdaByval, ImpCap_LambdaByref, ImpCap_Block,
+ ImpCap_CapturedRegion
};
+ ImplicitCaptureStyle ImpCaptureStyle;
+
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.
@@ -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");
@@ -666,7 +690,7 @@ public:
}
};
-/// \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;
@@ -680,9 +704,8 @@ 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;
}
@@ -693,38 +716,44 @@ public:
}
};
-/// \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,40 +767,40 @@ 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.
+ /// 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
@@ -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;
+ TemplateParameterList *GLTemplateParameterList = nullptr;
- /// \brief Contains all variable-referring-expressions (i.e. DeclRefExprs
+ /// Contains all variable-referring-expressions (i.e. DeclRefExprs
/// or MemberExprs) that refer to local variables in a generic lambda
/// or a lambda in a potentially-evaluated-if-used context.
///
/// Potentially capturable variables of a nested lambda that might need
/// to be captured by the lambda are housed here.
/// This is specifically useful for generic lambdas or
- /// lambdas within a a potentially evaluated-if-used context.
+ /// 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
/// will truly be odr-used (i.e. need to be captured) by that nested lambda,
/// until its instantiation. But we still need to capture it in the
/// enclosing lambda if all intervening lambdas can capture the variable.
-
llvm::SmallVector<Expr*, 4> PotentiallyCapturingExprs;
- /// \brief Contains all variable-referring-expressions that refer
+ /// 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,8 +867,7 @@ public:
return !AutoTemplateParams.empty() || GLTemplateParameterList;
}
- ///
- /// \brief Add a variable that might potentially be captured by the
+ /// 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
@@ -866,11 +892,12 @@ public:
void addPotentialThisCapture(SourceLocation Loc) {
PotentialThisCaptureLocation = Loc;
}
+
bool hasPotentialThisCapture() const {
return PotentialThisCaptureLocation.isValid();
}
- /// \brief Mark a variable's reference in a lambda as non-odr using.
+ /// 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
@@ -909,7 +936,6 @@ 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)
|| isa<MemberExpr>(CapturingVarExpr));
@@ -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/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 9cbe8e5cd63e..b1077c620f8a 100644
--- a/include/clang/Sema/Sema.h
+++ b/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,18 +5609,25 @@ 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);
- /// \brief Define the "body" of the conversion from a lambda object to a
+ /// Get the return type to use for a lambda's conversion function(s) to
+ /// function pointer type, given the type of the call operator.
+ QualType
+ getLambdaConversionFunctionResultType(const FunctionProtoType *CallOpType);
+
+ /// 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
@@ -5557,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
@@ -5645,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,
@@ -5726,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);
@@ -5759,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.
///
@@ -5773,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();
@@ -5786,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);
@@ -5984,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;
@@ -6027,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,
@@ -6102,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,
@@ -6123,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,
@@ -6142,6 +6225,8 @@ public:
void translateTemplateArguments(const ASTTemplateArgsPtr &In,
TemplateArgumentListInfo &Out);
+ ParsedTemplateArgument ActOnTemplateTypeArgument(TypeResult ParsedType);
+
void NoteAllFoundTemplates(TemplateName Name);
QualType CheckTemplateIdType(TemplateName Template,
@@ -6158,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,
@@ -6187,6 +6272,8 @@ public:
SourceLocation TemplateLoc,
const TemplateArgumentListInfo *TemplateArgs);
+ void diagnoseMissingTemplateArguments(TemplateName Name, SourceLocation Loc);
+
ExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
LookupResult &R,
@@ -6200,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,
@@ -6243,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,
@@ -6282,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
};
@@ -6307,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
@@ -6349,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,
@@ -6361,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
@@ -6373,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.
///
@@ -6383,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.
///
@@ -6404,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.
@@ -6417,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>".
///
@@ -6474,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.
///
@@ -6555,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.
@@ -6567,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
@@ -6577,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
@@ -6587,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
@@ -6597,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.
@@ -6610,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
@@ -6620,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
@@ -6628,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
@@ -6636,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
@@ -6644,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
@@ -6652,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
@@ -6660,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
@@ -6668,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
@@ -6678,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
@@ -6687,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
@@ -6709,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
@@ -6719,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.
///
@@ -6761,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
@@ -6771,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
@@ -6788,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.
///
@@ -6820,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
@@ -6830,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
};
@@ -6947,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,
@@ -6973,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);
@@ -7054,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).
@@ -7102,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;
};
@@ -7137,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;
@@ -7150,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.
@@ -7168,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.
///
@@ -7202,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
@@ -7210,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
@@ -7218,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.
@@ -7239,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.
///
@@ -7248,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
@@ -7260,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,
@@ -7268,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,
@@ -7290,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,
@@ -7298,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,
@@ -7307,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,
@@ -7316,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,
@@ -7331,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,
@@ -7339,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,
@@ -7348,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; }
@@ -7402,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.
///
@@ -7412,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() &&
@@ -7420,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 {
@@ -7453,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.
@@ -7479,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
@@ -7512,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)
@@ -7554,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
@@ -7653,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.
@@ -7673,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);
@@ -7760,6 +7858,9 @@ public:
void InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
FunctionDecl *Function);
+ FunctionDecl *InstantiateFunctionDeclaration(FunctionTemplateDecl *FTD,
+ const TemplateArgumentList *Args,
+ SourceLocation Loc);
void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
FunctionDecl *Function,
bool Recursive = false,
@@ -7827,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,
@@ -7868,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,
@@ -7908,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,
@@ -8045,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,
@@ -8088,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
};
@@ -8204,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,
@@ -8266,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);
@@ -8285,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
@@ -8376,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);
@@ -8465,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.
@@ -8485,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.
@@ -8527,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
@@ -8562,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);
@@ -8674,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.
@@ -8687,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,
@@ -8921,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,
@@ -8963,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);
@@ -9017,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,
@@ -9035,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,
@@ -9044,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);
@@ -9087,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,
@@ -9128,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,
@@ -9217,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.
@@ -9462,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);
@@ -9515,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);
@@ -9572,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);
@@ -9609,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);
@@ -9625,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);
@@ -9644,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,
@@ -9687,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);
@@ -9772,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);
@@ -9791,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:
@@ -9987,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() {
@@ -10086,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,
@@ -10095,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
};
@@ -10151,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);
@@ -10301,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);
@@ -10333,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,
@@ -10396,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);
@@ -10415,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);
@@ -10427,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);
@@ -10453,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;
@@ -10482,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.
@@ -10505,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
@@ -10536,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) {
@@ -10581,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;
@@ -10598,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(
@@ -10628,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 };
@@ -10666,7 +10768,7 @@ public:
if (ShouldEnter && Actions.isUnevaluatedContext() &&
Actions.getLangOpts().CPlusPlus11) {
Actions.PushExpressionEvaluationContext(
- Sema::ExpressionEvaluationContext::UnevaluatedList, nullptr, false);
+ Sema::ExpressionEvaluationContext::UnevaluatedList);
Entered = true;
}
}
@@ -10681,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/include/clang/Sema/SemaConsumer.h b/include/clang/Sema/SemaConsumer.h
index 676646afbd59..a2caf86c3653 100644
--- a/include/clang/Sema/SemaConsumer.h
+++ b/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/include/clang/Sema/SemaFixItUtils.h b/include/clang/Sema/SemaFixItUtils.h
index 343ccfb3d630..84dc58754b7b 100644
--- a/include/clang/Sema/SemaFixItUtils.h
+++ b/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/include/clang/Sema/SemaInternal.h b/include/clang/Sema/SemaInternal.h
index 4dc215ba21cb..86ab703a5b3a 100644
--- a/include/clang/Sema/SemaInternal.h
+++ b/include/clang/Sema/SemaInternal.h
@@ -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/include/clang/Sema/SemaLambda.h b/include/clang/Sema/SemaLambda.h
index df40b134f0a7..dfdc4ebc3643 100644
--- a/include/clang/Sema/SemaLambda.h
+++ b/include/clang/Sema/SemaLambda.h
@@ -8,19 +8,23 @@
//===----------------------------------------------------------------------===//
///
/// \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
+/// 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
diff --git a/include/clang/Sema/Template.h b/include/clang/Sema/Template.h
index 644d55b93f1b..c0dee3e82d58 100644
--- a/include/clang/Sema/Template.h
+++ b/include/clang/Sema/Template.h
@@ -1,26 +1,49 @@
-//===------- 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
@@ -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() { }
+ /// Construct an empty set of template argument lists.
+ MultiLevelTemplateArgumentList() = default;
- /// \brief Construct a single-level template argument list.
+ /// 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.
@@ -96,7 +119,7 @@ namespace clang {
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());
@@ -106,14 +129,14 @@ namespace clang {
= 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,27 +144,29 @@ 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 {
+ /// 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.,
+
+ /// 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,55 +259,52 @@ 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;
+ NamedDecl *PartiallySubstitutedPack = nullptr;
- /// \brief If \c PartiallySubstitutedPack is non-null, the set of
+ /// 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
+ /// 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;
@@ -293,7 +316,7 @@ namespace clang {
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.
@@ -359,7 +382,7 @@ namespace clang {
void InstantiatedLocalPackArg(const Decl *D, ParmVarDecl *Inst);
void MakeInstantiatedLocalArgPack(const Decl *D);
- /// \brief Note that the given parameter pack has been partially substituted
+ /// Note that the given parameter pack has been partially substituted
/// via explicit specification of template arguments
/// (C++0x [temp.arg.explicit]p9).
///
@@ -375,7 +398,7 @@ namespace clang {
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 *
@@ -399,17 +422,17 @@ namespace clang {
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.
@@ -545,6 +563,7 @@ namespace clang {
Decl *instantiateUnresolvedUsingDecl(T *D,
bool InstantiatingPackElement = false);
};
-}
+
+} // namespace clang
#endif // LLVM_CLANG_SEMA_TEMPLATE_H
diff --git a/include/clang/Sema/TemplateDeduction.h b/include/clang/Sema/TemplateDeduction.h
index cd9ed6abfaf9..93395b4945d5 100644
--- a/include/clang/Sema/TemplateDeduction.h
+++ b/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/include/clang/Sema/TemplateInstCallback.h b/include/clang/Sema/TemplateInstCallback.h
new file mode 100644
index 000000000000..dc729d52243c
--- /dev/null
+++ b/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/include/clang/Sema/TypoCorrection.h b/include/clang/Sema/TypoCorrection.h
index 5bebe52325c6..d8fe82799845 100644
--- a/include/clang/Sema/TypoCorrection.h
+++ b/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/include/clang/Sema/Weak.h b/include/clang/Sema/Weak.h
index 9c7212e0c8ee..115e97bcd2ce 100644
--- a/include/clang/Sema/Weak.h
+++ b/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/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index 34a7bb330174..76bc818557a9 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/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,13 +54,13 @@ 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.
@@ -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;
@@ -131,58 +131,58 @@ namespace serialization {
}
};
- /// \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
/// 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,155 +1387,155 @@ 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
@@ -1443,310 +1543,310 @@ namespace serialization {
/// 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
@@ -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,7 +1991,7 @@ 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;
@@ -1920,7 +2020,7 @@ namespace serialization {
}
};
- /// \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;
@@ -1949,7 +2049,7 @@ namespace serialization {
}
};
- /// \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/include/clang/Serialization/ASTDeserializationListener.h b/include/clang/Serialization/ASTDeserializationListener.h
index c26f3e0b425e..c462a90dde54 100644
--- a/include/clang/Serialization/ASTDeserializationListener.h
+++ b/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/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h
index 37920fc143ea..82a74a64443d 100644
--- a/include/clang/Serialization/ASTReader.h
+++ b/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,12 +652,12 @@ 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.
@@ -670,45 +666,45 @@ private:
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,22 +1091,26 @@ 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;
@@ -1111,41 +1118,41 @@ private:
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;
}
- /// \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,7 +1839,7 @@ 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
@@ -1830,20 +1848,20 @@ public:
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
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/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h
index 9437bf7f2c9f..a93579930ff5 100644
--- a/include/clang/Serialization/ASTWriter.h
+++ b/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();
@@ -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/include/clang/Serialization/ContinuousRangeMap.h b/include/clang/Serialization/ContinuousRangeMap.h
index 24bfadd0f867..2f909965db7e 100644
--- a/include/clang/Serialization/ContinuousRangeMap.h
+++ b/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.
@@ -106,7 +107,7 @@ 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;
@@ -117,7 +118,7 @@ public:
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
diff --git a/include/clang/Serialization/GlobalModuleIndex.h b/include/clang/Serialization/GlobalModuleIndex.h
index 0f14eca0fd86..f48d0cf17c49 100644
--- a/include/clang/Serialization/GlobalModuleIndex.h
+++ b/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/include/clang/Serialization/Module.h b/include/clang/Serialization/Module.h
index 4e4bf44f3492..653981b1427c 100644
--- a/include/clang/Serialization/Module.h
+++ b/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.
+
+ /// 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/include/clang/Serialization/ModuleManager.h b/include/clang/Serialization/ModuleManager.h
index 147a6910aa29..e101e60b21a3 100644
--- a/include/clang/Serialization/ModuleManager.h
+++ b/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/include/clang/StaticAnalyzer/Checkers/CMakeLists.txt b/include/clang/StaticAnalyzer/Checkers/CMakeLists.txt
index 37dd9e848296..236647c53485 100644
--- a/include/clang/StaticAnalyzer/Checkers/CMakeLists.txt
+++ b/include/clang/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -1,4 +1,3 @@
clang_tablegen(Checkers.inc -gen-clang-sa-checkers
- -I ${CMAKE_CURRENT_SOURCE_DIR}/../../../
SOURCE Checkers.td
TARGET ClangSACheckers)
diff --git a/include/clang/StaticAnalyzer/Checkers/Checkers.td b/include/clang/StaticAnalyzer/Checkers/Checkers.td
index e510e84e938a..ab0e4af1361b 100644
--- a/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/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.
//===----------------------------------------------------------------------===//
@@ -297,6 +305,10 @@ def DeleteWithNonVirtualDtorChecker : Checker<"DeleteWithNonVirtualDtor">,
"destructor in their base class">,
DescFile<"DeleteWithNonVirtualDtorChecker.cpp">;
+def InnerPointerChecker : Checker<"InnerPointer">,
+ HelpText<"Check for inner pointers of C++ containers used after re/deallocation">,
+ DescFile<"InnerPointerChecker.cpp">;
+
def IteratorRangeChecker : Checker<"IteratorRange">,
HelpText<"Check for iterators used outside their valid ranges">,
DescFile<"IteratorChecker.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/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
index ce50cc582d1e..9d292cfddb0c 100644
--- a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
+++ b/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;
+ /// 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.
+ /// 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;
+
+ /// Store full compiler invocation for reproducible instructions in the
+ /// generated report.
+ std::string FullCompilerInvocation;
- /// \brief The maximum number of times the analyzer visits a block.
+ /// 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 =
@@ -174,22 +177,36 @@ public:
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;
+ /// The inlining stack depth limit.
+ // Cap the stack depth at 4 calls (5 stack frames, base + 4 calls).
+ unsigned InlineMaxStackDepth = 5;
- /// \brief The mode of function selection used during inlining.
- AnalysisInliningMode InliningMode;
+ /// 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
};
@@ -197,10 +214,10 @@ private:
/// 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;
@@ -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;
+using AnalyzerOptionsRef = IntrusiveRefCntPtr<AnalyzerOptions>;
-}
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
index cd1355d03b63..111e1d1e8e20 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
+++ b/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:
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.
@@ -218,10 +231,6 @@ public:
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
@@ -242,13 +251,6 @@ public:
void markInvalid(const void *Tag, const void *Data) {
Invalidations.insert(std::make_pair(Tag, Data));
}
-
- /// Reverses the effects of a previous invalidation.
- ///
- /// \sa markInvalid
- void removeInvalidation(const void *Tag, const void *Data) {
- Invalidations.erase(std::make_pair(Tag, Data));
- }
/// Return the canonical declaration, be it a method or class, where
/// this issue semantically occurred.
@@ -286,7 +288,7 @@ 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.
void addExtraText(StringRef 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/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
index 2043896fd26f..92118b0fbee2 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
+++ b/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/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
index 18fa85c9657f..c723f31aec26 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
+++ b/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
//
@@ -32,27 +32,39 @@ private:
const CheckName Check;
const std::string Name;
const std::string Category;
- bool SuppressonSink;
+ const CheckerBase *Checker;
+ bool SuppressOnSink;
virtual void anchor();
+
public:
- BugType(class CheckName check, StringRef name, StringRef cat)
- : Check(check), Name(name), Category(cat), SuppressonSink(false) {}
- BugType(const CheckerBase *checker, StringRef name, StringRef cat)
- : Check(checker->getCheckName()), Name(name), Category(cat),
- SuppressonSink(false) {}
- virtual ~BugType() {}
-
- // FIXME: Should these be made strings as well?
+ BugType(CheckName Check, StringRef Name, StringRef Cat)
+ : Check(Check), Name(Name), Category(Cat), Checker(nullptr),
+ SuppressOnSink(false) {}
+ BugType(const CheckerBase *Checker, StringRef Name, StringRef Cat)
+ : Check(Checker->getCheckName()), Name(Name), Category(Cat),
+ Checker(Checker), SuppressOnSink(false) {}
+ virtual ~BugType() = default;
+
StringRef getName() const { return Name; }
StringRef getCategory() const { return Category; }
- StringRef getCheckName() const { return Check.getName(); }
+ StringRef getCheckName() const {
+ // 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
+ // CheckerBase whenever it is possible.
+ StringRef CheckName =
+ Checker ? Checker->getCheckName().getName() : Check.getName();
+ assert(!CheckName.empty() && "Check name is not set properly.");
+ return CheckName;
+ }
/// isSuppressOnSink - Returns true if bug reports associated with this bug
/// type should be suppressed if the end node of the report is post-dominated
/// by a sink node.
- bool isSuppressOnSink() const { return SuppressonSink; }
- void setSuppressOnSink(bool x) { SuppressonSink = x; }
+ bool isSuppressOnSink() const { return SuppressOnSink; }
+ void setSuppressOnSink(bool x) { SuppressOnSink = x; }
virtual void FlushReports(BugReporter& BR);
};
@@ -74,7 +86,7 @@ public:
StringRef getDescription() const { return desc; }
};
-} // end GR namespace
+} // end ento namespace
} // end clang namespace
#endif
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
index f31ab2cd81cd..b18d3c9b3031 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
+++ b/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,15 +70,15 @@ public:
public:
PDFileEntry(llvm::FoldingSetNodeID &NodeID) : NodeID(NodeID) {}
- typedef std::vector<std::pair<StringRef, StringRef> > ConsumerFiles;
+ using ConsumerFiles = std::vector<std::pair<StringRef, StringRef>>;
- /// \brief A vector of <consumer,file> pairs.
+ /// 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; }
};
@@ -88,8 +100,9 @@ public:
private:
virtual void anchor();
+
public:
- PathDiagnosticConsumer() : flushed(false) {}
+ PathDiagnosticConsumer() = default;
virtual ~PathDiagnosticConsumer();
void FlushDiagnostics(FilesMade *FilesMade);
@@ -101,7 +114,17 @@ 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; }
@@ -110,7 +133,7 @@ public:
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; }
@@ -297,21 +327,22 @@ public:
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; }
@@ -344,9 +375,9 @@ 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
@@ -356,16 +387,14 @@ 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; }
@@ -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,7 +486,7 @@ 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
/// diagnostic the hints can be used to summarize the effect of the call.
@@ -464,11 +494,11 @@ 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
@@ -537,30 +568,19 @@ public:
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,12 +588,20 @@ 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;
@@ -588,13 +616,9 @@ public:
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,8 +721,7 @@ public:
class PathDiagnosticMacroPiece : public PathDiagnosticSpotPiece {
public:
PathDiagnosticMacroPiece(const PathDiagnosticLocation &pos)
- : PathDiagnosticSpotPiece(pos, "", Macro) {}
-
+ : PathDiagnosticSpotPiece(pos, "", Macro) {}
~PathDiagnosticMacroPiece() override;
PathPieces subPieces;
@@ -703,11 +730,11 @@ public:
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,24 +774,27 @@ 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;
@@ -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.
@@ -864,8 +900,8 @@ public:
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/include/clang/StaticAnalyzer/Core/Checker.h b/include/clang/StaticAnalyzer/Core/Checker.h
index f9477762c758..45b7a61139ea 100644
--- a/include/clang/StaticAnalyzer/Core/Checker.h
+++ b/include/clang/StaticAnalyzer/Core/Checker.h
@@ -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,
@@ -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/include/clang/StaticAnalyzer/Core/CheckerManager.h b/include/clang/StaticAnalyzer/Core/CheckerManager.h
index 88cb08a4b647..33a794061a38 100644
--- a/include/clang/StaticAnalyzer/Core/CheckerManager.h
+++ b/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
@@ -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() {
+ 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();
- checker->Name = CurrentCheckName;
- CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>));
- CHECKER::_register(checker, *this);
- ref = checker;
- return checker;
- }
-
- template <typename CHECKER>
- CHECKER *registerChecker(AnalyzerOptions &AOpts) {
- CheckerTag tag = getTag<CHECKER>();
- CheckerRef &ref = CheckerTags[tag];
- if (ref)
- return static_cast<CHECKER *>(ref); // already registered.
-
- CHECKER *checker = new CHECKER(AOpts);
+ CHECKER *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,7 +349,7 @@ 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
@@ -361,25 +369,25 @@ public:
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;
+ using CheckStmtFunc = CheckerFn<void (const Stmt *, CheckerContext &)>;
- typedef CheckerFn<void (const ObjCMethodCall &, CheckerContext &)>
- CheckObjCMessageFunc;
+ using CheckObjCMessageFunc =
+ CheckerFn<void (const ObjCMethodCall &, CheckerContext &)>;
- typedef CheckerFn<void (const CallEvent &, CheckerContext &)>
- CheckCallFunc;
+ using CheckCallFunc =
+ CheckerFn<void (const CallEvent &, CheckerContext &)>;
- typedef CheckerFn<void (const SVal &location, bool isLoad,
- const Stmt *S,
- CheckerContext &)>
- CheckLocationFunc;
+ using CheckLocationFunc =
+ CheckerFn<void (const SVal &location, bool isLoad, const Stmt *S,
+ CheckerContext &)>;
- typedef CheckerFn<void (const SVal &location, const SVal &val,
- const Stmt *S, CheckerContext &)>
- CheckBindFunc;
+ using CheckBindFunc =
+ CheckerFn<void (const SVal &location, const SVal &val, const Stmt *S,
+ CheckerContext &)>;
- typedef CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)>
- CheckEndAnalysisFunc;
+ using CheckEndAnalysisFunc =
+ CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)>;
- typedef CheckerFn<void (CheckerContext &)>
- CheckBeginFunctionFunc;
+ using CheckBeginFunctionFunc = CheckerFn<void (CheckerContext &)>;
- typedef CheckerFn<void (CheckerContext &)>
- CheckEndFunctionFunc;
+ using CheckEndFunctionFunc =
+ CheckerFn<void (const ReturnStmt *, CheckerContext &)>;
- typedef CheckerFn<void (const Stmt *, CheckerContext &)>
- CheckBranchConditionFunc;
+ using CheckBranchConditionFunc =
+ CheckerFn<void (const Stmt *, CheckerContext &)>;
+
+ using CheckNewAllocatorFunc =
+ CheckerFn<void (const CXXNewExpr *, SVal, CheckerContext &)>;
- typedef CheckerFn<void (SymbolReaper &, CheckerContext &)>
- CheckDeadSymbolsFunc;
+ using CheckDeadSymbolsFunc =
+ CheckerFn<void (SymbolReaper &, CheckerContext &)>;
- typedef CheckerFn<void (ProgramStateRef,SymbolReaper &)> CheckLiveSymbolsFunc;
+ using CheckLiveSymbolsFunc = CheckerFn<void (ProgramStateRef,SymbolReaper &)>;
- typedef CheckerFn<ProgramStateRef (ProgramStateRef,
- const InvalidatedSymbols *symbols,
- ArrayRef<const MemRegion *> ExplicitRegions,
- ArrayRef<const MemRegion *> Regions,
- const LocationContext *LCtx,
- const CallEvent *Call)>
- CheckRegionChangesFunc;
+ using CheckRegionChangesFunc =
+ CheckerFn<ProgramStateRef (ProgramStateRef,
+ const InvalidatedSymbols *symbols,
+ ArrayRef<const MemRegion *> ExplicitRegions,
+ ArrayRef<const MemRegion *> Regions,
+ const LocationContext *LCtx,
+ const CallEvent *Call)>;
- typedef CheckerFn<ProgramStateRef (ProgramStateRef,
- const InvalidatedSymbols &Escaped,
- const CallEvent *Call,
- PointerEscapeKind Kind,
- RegionAndSymbolInvalidationTraits *ITraits)>
- CheckPointerEscapeFunc;
+ using CheckPointerEscapeFunc =
+ CheckerFn<ProgramStateRef (ProgramStateRef,
+ const InvalidatedSymbols &Escaped,
+ const CallEvent *Call, PointerEscapeKind Kind,
+ RegionAndSymbolInvalidationTraits *ITraits)>;
- typedef CheckerFn<ProgramStateRef (ProgramStateRef,
- const SVal &cond, bool assumption)>
- EvalAssumeFunc;
+ using EvalAssumeFunc =
+ CheckerFn<ProgramStateRef (ProgramStateRef, const SVal &cond,
+ bool assumption)>;
- typedef CheckerFn<bool (const CallExpr *, CheckerContext &)>
- EvalCallFunc;
+ using EvalCallFunc = CheckerFn<bool (const CallExpr *, CheckerContext &)>;
- typedef CheckerFn<void (const TranslationUnitDecl *,
- AnalysisManager&, BugReporter &)>
- CheckEndOfTranslationUnit;
+ using CheckEndOfTranslationUnit =
+ CheckerFn<void (const TranslationUnitDecl *, AnalysisManager &,
+ BugReporter &)>;
+
+ using HandlesStmtFunc = bool (*)(const Stmt *D);
- typedef bool (*HandlesStmtFunc)(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,8 +525,8 @@ 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) {
@@ -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/include/clang/StaticAnalyzer/Core/CheckerRegistry.h b/include/clang/StaticAnalyzer/Core/CheckerRegistry.h
index 3b26ed3e1a09..912a601b61c4 100644
--- a/include/clang/StaticAnalyzer/Core/CheckerRegistry.h
+++ b/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/.
@@ -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/include/clang/StaticAnalyzer/Core/IssueHash.h b/include/clang/StaticAnalyzer/Core/IssueHash.h
index b3c4f1465594..8cb6631fae74 100644
--- a/include/clang/StaticAnalyzer/Core/IssueHash.h
+++ b/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
@@ -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/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h b/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h
index ce512fd301ee..2e81aa38c8de 100644
--- a/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h
+++ b/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/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h b/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h
index cc8a9b8ef071..93edfcef2d5a 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h
+++ b/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).
@@ -93,7 +93,7 @@ public:
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.
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
index 15b930bc3f1e..02b335761e70 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
@@ -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/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
index 4aa87443e4c2..0bbc6500d6ec 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
+++ b/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();
@@ -147,57 +164,57 @@ public:
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/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h b/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h
index 1d779e6cb6ec..b94dadff2342 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h
+++ b/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;
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
index 9fec217aca72..9c667f912e9f 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
+++ b/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,42 @@
#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/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 +71,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; }
};
@@ -95,7 +118,7 @@ public:
};
/// \class RuntimeDefinition
-/// \brief Defines the runtime definition of the called function.
+/// 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
@@ -104,21 +127,22 @@ public:
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.
+ /// 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; }
@@ -128,7 +152,7 @@ public:
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 +163,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 +180,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 +191,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 +271,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 +330,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 +348,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 +356,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,16 +390,16 @@ 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);
@@ -393,10 +416,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 +439,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 +473,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 +482,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 +509,7 @@ public:
}
};
-/// \brief Represents a call to a block.
+/// Represents a call to a block.
///
/// Example: <tt>^{ /* ... */ }()</tt>
class BlockCall : public CallEvent {
@@ -496,9 +518,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 +537,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 +557,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 +616,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 +651,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 +660,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 +691,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 +701,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 +716,7 @@ public:
unsigned getNumArgs() const override {
return getOriginExpr()->getNumArgs() - 1;
}
+
const Expr *getArgExpr(unsigned Index) const override {
return getOriginExpr()->getArg(Index + 1);
}
@@ -710,7 +730,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 +738,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 +750,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 +765,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 +780,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 +796,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 +822,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 +835,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 +844,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 +876,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 +886,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 +897,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 +916,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 +932,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 +957,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 +999,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 +1011,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 +1060,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 +1093,6 @@ public:
}
};
-
template <typename T>
CallEventRef<T> CallEvent::cloneWithState(ProgramStateRef NewState) const {
assert(isa<T>(*this) && "Cloning to unrelated type");
@@ -1099,19 +1124,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/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
index 78d38a3d598d..f3a0ca7b6608 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
@@ -111,17 +111,17 @@ public:
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();
@@ -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/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h
index 8dda6367c2e0..7f34a7a5b19d 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h
+++ b/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/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
index c01600d5c969..d4f8fbaa43df 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
+++ b/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/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
index 7472a7147fca..5755818cd971 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
+++ b/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;
+ using BlocksExhausted =
+ std::vector<std::pair<BlockEdge, const ExplodedNode *>>;
- typedef std::vector<std::pair<const CFGBlock*, const ExplodedNode*> >
- BlocksAborted;
+ using BlocksAborted =
+ std::vector<std::pair<const CFGBlock *, const ExplodedNode *>>;
private:
-
- SubEngine& SubEng;
+ SubEngine &SubEng;
/// G - The simulation graph. Each node is a (location,state) pair.
mutable ExplodedGraph G;
@@ -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,6 +137,7 @@ 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,
@@ -154,28 +167,31 @@ public:
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,29 +227,29 @@ 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;
}
@@ -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);
}
@@ -455,15 +476,16 @@ class IndirectGotoNodeBuilder {
public:
IndirectGotoNodeBuilder(ExplodedNode *pred, const CFGBlock *src,
const Expr *e, const CFGBlock *dispatch, CoreEngine* eng)
- : Eng(*eng), Src(src), DispatchBlock(*dispatch), E(e), Pred(pred) {}
+ : 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; }
@@ -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:
@@ -545,7 +568,8 @@ public:
}
};
-} // end ento namespace
-} // end clang namespace
+} // namespace ento
+
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_COREENGINE_H
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h
index e13c6410c7be..092e23ce73c8 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h
+++ b/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/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h
index 555191d99709..2f8ead0746ca 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h
+++ b/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/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
index c63ed4a013aa..d49aa81bc958 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
+++ b/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,7 +33,7 @@ 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);
@@ -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/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
index dcea5e461d27..c12198db6598 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
+++ b/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.
///
@@ -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,10 +243,10 @@ public:
// For debugging.
public:
-
class Auditor {
public:
virtual ~Auditor();
+
virtual void AddEdge(ExplodedNode *Src, ExplodedNode *Dst) = 0;
};
@@ -240,15 +257,15 @@ private:
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,7 +285,7 @@ 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;
@@ -279,14 +296,16 @@ protected:
/// 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/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index 712cd6361e11..25849e94c8ff 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/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,11 +87,35 @@ 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;
@@ -63,19 +123,19 @@ private:
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.
@@ -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;
@@ -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);
@@ -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(); }
@@ -363,7 +428,7 @@ 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,
@@ -390,9 +455,9 @@ public:
/// VisitMemberExpr - Transfer function for member expressions.
void VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,
- ExplodedNodeSet &Dst);
+ 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);
@@ -422,7 +487,7 @@ public:
/// 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,
@@ -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,
@@ -471,7 +537,7 @@ public:
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);
@@ -539,6 +604,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 +631,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 +648,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 +676,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 +726,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 +744,69 @@ 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,
+ llvm::PointerUnion<const Stmt *, const CXXCtorInitializer *> P,
+ 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,
+ llvm::PointerUnion<const Stmt *, const CXXCtorInitializer *> P,
+ const LocationContext *LC);
+
+ /// If the given statement corresponds to an object under construction,
+ /// being part of its construciton context, retrieve that object's location.
+ static Optional<SVal> getObjectUnderConstruction(
+ ProgramStateRef State,
+ llvm::PointerUnion<const Stmt *, const CXXCtorInitializer *> P,
+ 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 +820,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/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h b/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h
index ce81c98c206b..b70faa10f0b2 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h
+++ b/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/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h b/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h
index 3168733e4258..f494c5d6dab8 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h
+++ b/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/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
index 8ab665623088..f3846eba6b96 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
+++ b/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,11 +119,12 @@ 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;
@@ -122,24 +139,24 @@ public:
/// 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
@@ -240,7 +255,7 @@ class StaticGlobalSpaceRegion : public GlobalsSpaceRegion {
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) {
@@ -339,9 +350,9 @@ 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) {
@@ -351,11 +362,11 @@ public:
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 {
@@ -601,7 +614,6 @@ public:
}
};
-
/// 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,
@@ -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;
@@ -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;
@@ -817,7 +829,7 @@ public:
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(); }
@@ -943,13 +951,13 @@ 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
@@ -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;
@@ -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,11 +1193,10 @@ 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 *>
StackLocalsSpaceRegions;
llvm::DenseMap<const StackFrameContext *, StackArgumentsSpaceRegion *>
@@ -1199,16 +1204,12 @@ class MemRegionManager {
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; }
@@ -1256,13 +1257,13 @@ public:
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);
@@ -1381,24 +1382,28 @@ 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
@@ -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/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
index dd2564b0a3c3..17ab7379fdba 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
@@ -177,20 +177,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 +198,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 +232,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 +277,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 +293,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 +326,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 +352,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 +372,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 +409,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 +429,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 +462,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 +740,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/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h
index a04fa9005955..5555b292534c 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h
+++ b/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/lib/StaticAnalyzer/Core/RangedConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h
index a4e6062a4f57..d2ba1f7c9529 100644
--- a/lib/StaticAnalyzer/Core/RangedConstraintManager.h
+++ b/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/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h
new file mode 100644
index 000000000000..19d3d5973e0f
--- /dev/null
+++ b/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/include/clang/StaticAnalyzer/Core/PathSensitive/SMTContext.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTContext.h
new file mode 100644
index 000000000000..45c9df4ef401
--- /dev/null
+++ b/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/include/clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h
new file mode 100644
index 000000000000..9dedf96cfaf8
--- /dev/null
+++ b/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/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h
new file mode 100644
index 000000000000..a43ca486901b
--- /dev/null
+++ b/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/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h
new file mode 100644
index 000000000000..41ef573f0c71
--- /dev/null
+++ b/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/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
index d58d0a690c88..31300d69f2ff 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
@@ -16,21 +16,43 @@
#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;
@@ -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());
@@ -124,7 +144,12 @@ public:
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);
@@ -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,
@@ -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/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
index 06132587b4aa..0fde63e9eb09 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
+++ b/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,7 +195,7 @@ 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
@@ -206,28 +218,28 @@ 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();
}
@@ -239,37 +251,43 @@ public:
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) {
+ 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/include/clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h
index 2c9802bbc536..d64b90e2d380 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h
+++ b/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/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
index 25d20a17afaa..dc0644df8aab 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
+++ b/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;
- /// \brief Create a new store with the specified binding removed.
+ /// 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;
+
+ /// 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;
@@ -147,7 +170,7 @@ 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).
@@ -168,7 +191,7 @@ 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;
@@ -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
@@ -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,22 +290,21 @@ 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);
@@ -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/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h b/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h
index 958c8c377ea2..c5b4e5036bdf 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h
+++ b/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
//
@@ -19,33 +19,36 @@
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/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
index 8ccd34751bbe..e574ffdd6a15 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
@@ -24,6 +24,10 @@ class CFGElement;
class LocationContext;
class Stmt;
+namespace cross_tu {
+class CrossTranslationUnitContext;
+}
+
namespace ento {
struct NodeBuilderContext;
@@ -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
@@ -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/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h
index 9780d0144746..69b9858d3feb 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h
+++ b/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/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
index 7d2e5ad8ba91..cc3ce72f9e56 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
+++ b/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;
}
};
@@ -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,16 +542,16 @@ 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;
@@ -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,13 +600,14 @@ 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(); }
@@ -588,11 +615,12 @@ public:
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.)
@@ -603,7 +631,7 @@ public:
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/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h
index 7b76263f040c..ce19b7131d42 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h
+++ b/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/include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h b/include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h
index 0c56e7d8ea69..50c4b8194cff 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h
+++ b/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/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h b/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h
index 4f1a60e67556..7df8f373b366 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h
@@ -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/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h b/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h
index a9dad6c5e9a2..59fbbc3ca80f 100644
--- a/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h
+++ b/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/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h b/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h
index 2985b7c117ef..216a2359efba 100644
--- a/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h
+++ b/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/include/clang/StaticAnalyzer/Frontend/FrontendActions.h b/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
index e66d48b1be1d..ba37b7f59a02 100644
--- a/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
+++ b/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/include/clang/StaticAnalyzer/Frontend/ModelConsumer.h b/include/clang/StaticAnalyzer/Frontend/ModelConsumer.h
index 24f8042587f3..fa00ffd16553 100644
--- a/include/clang/StaticAnalyzer/Frontend/ModelConsumer.h
+++ b/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/include/clang/Tooling/AllTUsExecution.h b/include/clang/Tooling/AllTUsExecution.h
new file mode 100644
index 000000000000..f199365dc815
--- /dev/null
+++ b/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/include/clang/Tooling/ArgumentsAdjusters.h b/include/clang/Tooling/ArgumentsAdjusters.h
index 4eb02251a775..94ccf1f34e57 100644
--- a/include/clang/Tooling/ArgumentsAdjusters.h
+++ b/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/include/clang/Tooling/CommonOptionsParser.h b/include/clang/Tooling/CommonOptionsParser.h
index 15e8161dd76f..7aaa712f9baf 100644
--- a/include/clang/Tooling/CommonOptionsParser.h
+++ b/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/include/clang/Tooling/CompilationDatabase.h b/include/clang/Tooling/CompilationDatabase.h
index bc3e67b77de2..37e515fdc09e 100644
--- a/include/clang/Tooling/CompilationDatabase.h
+++ b/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/include/clang/Tooling/CompilationDatabasePluginRegistry.h b/include/clang/Tooling/CompilationDatabasePluginRegistry.h
index 7323ec897403..051a08e2a91e 100644
--- a/include/clang/Tooling/CompilationDatabasePluginRegistry.h
+++ b/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/include/clang/Tooling/Core/Diagnostic.h b/include/clang/Tooling/Core/Diagnostic.h
index b4920d4fe456..ddb40103e211 100644
--- a/include/clang/Tooling/Core/Diagnostic.h
+++ b/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/include/clang/Tooling/Core/Replacement.h b/include/clang/Tooling/Core/Replacement.h
index 3fea9aee604c..ba11ca4a7fee 100644
--- a/include/clang/Tooling/Core/Replacement.h
+++ b/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/include/clang/Tooling/DiagnosticsYaml.h b/include/clang/Tooling/DiagnosticsYaml.h
index 4d6ff063641b..bf0732bf0042 100644
--- a/include/clang/Tooling/DiagnosticsYaml.h
+++ b/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/include/clang/Tooling/Execution.h b/include/clang/Tooling/Execution.h
index 1a44c4788c49..68aef53cb58f 100644
--- a/include/clang/Tooling/Execution.h
+++ b/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/include/clang/Tooling/FileMatchTrie.h b/include/clang/Tooling/FileMatchTrie.h
index 882979ef8ff6..11d12f3d30ce 100644
--- a/include/clang/Tooling/FileMatchTrie.h
+++ b/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/include/clang/Tooling/FixIt.h b/include/clang/Tooling/FixIt.h
index c1e508849280..b36f378d6361 100644
--- a/include/clang/Tooling/FixIt.h
+++ b/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/include/clang/Tooling/Inclusions/HeaderIncludes.h b/include/clang/Tooling/Inclusions/HeaderIncludes.h
new file mode 100644
index 000000000000..d99a3283168c
--- /dev/null
+++ b/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/include/clang/Tooling/Inclusions/IncludeStyle.h b/include/clang/Tooling/Inclusions/IncludeStyle.h
new file mode 100644
index 000000000000..a093dff27728
--- /dev/null
+++ b/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/include/clang/Tooling/JSONCompilationDatabase.h b/include/clang/Tooling/JSONCompilationDatabase.h
index 9a6866240b08..882afc6d9ece 100644
--- a/include/clang/Tooling/JSONCompilationDatabase.h
+++ b/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/include/clang/Tooling/Refactoring.h b/include/clang/Tooling/Refactoring.h
index bc95c3b09ec2..64b018ea26c2 100644
--- a/include/clang/Tooling/Refactoring.h
+++ b/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/include/clang/Tooling/Refactoring/AtomicChange.h b/include/clang/Tooling/Refactoring/AtomicChange.h
index 8a468a6de84e..bfe042fc53c5 100644
--- a/include/clang/Tooling/Refactoring/AtomicChange.h
+++ b/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/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h b/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h
index d96ad78ad876..d2d47ddc2c61 100644
--- a/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h
+++ b/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/include/clang/Tooling/Refactoring/RefactoringActionRule.h b/include/clang/Tooling/Refactoring/RefactoringActionRule.h
index 4130e29d8dea..ce4a91cbbadc 100644
--- a/include/clang/Tooling/Refactoring/RefactoringActionRule.h
+++ b/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/include/clang/Tooling/Refactoring/RefactoringResultConsumer.h b/include/clang/Tooling/Refactoring/RefactoringResultConsumer.h
index fe7738e73499..005eb877bf0f 100644
--- a/include/clang/Tooling/Refactoring/RefactoringResultConsumer.h
+++ b/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/include/clang/Tooling/Refactoring/Rename/RenamingAction.h b/include/clang/Tooling/Refactoring/Rename/RenamingAction.h
index 734b624d777b..5771a1c2d132 100644
--- a/include/clang/Tooling/Refactoring/Rename/RenamingAction.h
+++ b/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/include/clang/Tooling/Refactoring/Rename/SymbolName.h b/include/clang/Tooling/Refactoring/Rename/SymbolName.h
index e69d2908b5d3..42e0a5cb6697 100644
--- a/include/clang/Tooling/Refactoring/Rename/SymbolName.h
+++ b/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/include/clang/Tooling/Refactoring/Rename/USRFinder.h b/include/clang/Tooling/Refactoring/Rename/USRFinder.h
index b74a5d7f70af..3622bd0daf85 100644
--- a/include/clang/Tooling/Refactoring/Rename/USRFinder.h
+++ b/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/include/clang/Tooling/Refactoring/Rename/USRFindingAction.h b/include/clang/Tooling/Refactoring/Rename/USRFindingAction.h
index f1c5ae60f875..ebc9790e9cb6 100644
--- a/include/clang/Tooling/Refactoring/Rename/USRFindingAction.h
+++ b/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/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h b/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h
index 801a8ad9e99c..e1228e9f39f7 100644
--- a/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h
+++ b/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/include/clang/Tooling/RefactoringCallbacks.h b/include/clang/Tooling/RefactoringCallbacks.h
index 9862951149a3..2137e0035d62 100644
--- a/include/clang/Tooling/RefactoringCallbacks.h
+++ b/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/include/clang/Tooling/ReplacementsYaml.h b/include/clang/Tooling/ReplacementsYaml.h
index 0b1dc4c77423..8e41525a9412 100644
--- a/include/clang/Tooling/ReplacementsYaml.h
+++ b/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/include/clang/Tooling/StandaloneExecution.h b/include/clang/Tooling/StandaloneExecution.h
index f5f32d737a45..572330e4cc22 100644
--- a/include/clang/Tooling/StandaloneExecution.h
+++ b/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/include/clang/Tooling/ToolExecutorPluginRegistry.h b/include/clang/Tooling/ToolExecutorPluginRegistry.h
index 11ba89546e9e..921689dff86f 100644
--- a/include/clang/Tooling/ToolExecutorPluginRegistry.h
+++ b/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/include/clang/Tooling/Tooling.h b/include/clang/Tooling/Tooling.h
index e64be07d9ab4..c056894b1a7a 100644
--- a/include/clang/Tooling/Tooling.h
+++ b/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/include/clang/module.modulemap b/include/clang/module.modulemap
index 4097ad2dc716..8d525c5ffbac 100644
--- a/include/clang/module.modulemap
+++ b/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/lib/ARCMigrate/ARCMT.cpp b/lib/ARCMigrate/ARCMT.cpp
index cf7cddefc03d..74c9974cc810 100644
--- a/lib/ARCMigrate/ARCMT.cpp
+++ b/lib/ARCMigrate/ARCMT.cpp
@@ -503,7 +503,7 @@ public:
} // end anonymous namespace.
-/// \brief Anchor for VTable.
+/// Anchor for VTable.
MigrationProcess::RewriteListener::~RewriteListener() { }
MigrationProcess::MigrationProcess(
diff --git a/lib/ARCMigrate/ObjCMT.cpp b/lib/ARCMigrate/ObjCMT.cpp
index fcc67da1f774..433e6194a2c2 100644
--- a/lib/ARCMigrate/ObjCMT.cpp
+++ b/lib/ARCMigrate/ObjCMT.cpp
@@ -226,7 +226,7 @@ namespace {
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,
@@ -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);
}
@@ -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()) {
diff --git a/lib/ARCMigrate/PlistReporter.cpp b/lib/ARCMigrate/PlistReporter.cpp
index 9a51690c0ce7..2ad1c8591a9e 100644
--- a/lib/ARCMigrate/PlistReporter.cpp
+++ b/lib/ARCMigrate/PlistReporter.cpp
@@ -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/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp b/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
index d45d5d60b78a..cbc22ed60172 100644
--- a/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
+++ b/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;
diff --git a/lib/ARCMigrate/TransGCAttrs.cpp b/lib/ARCMigrate/TransGCAttrs.cpp
index 2ae6b78a4634..4fd21aa6c269 100644
--- a/lib/ARCMigrate/TransGCAttrs.cpp
+++ b/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;
@@ -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(
@@ -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/lib/ARCMigrate/TransProperties.cpp b/lib/ARCMigrate/TransProperties.cpp
index 389b03666bf7..1468c21a0093 100644
--- a/lib/ARCMigrate/TransProperties.cpp
+++ b/lib/ARCMigrate/TransProperties.cpp
@@ -330,7 +330,7 @@ private:
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/lib/ARCMigrate/TransRetainReleaseDealloc.cpp b/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
index 389f3655aa52..ebe289b34df8 100644
--- a/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
+++ b/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:
@@ -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]; })
diff --git a/lib/ARCMigrate/TransUnbridgedCasts.cpp b/lib/ARCMigrate/TransUnbridgedCasts.cpp
index 7ca49558a7f0..de52bef4d206 100644
--- a/lib/ARCMigrate/TransUnbridgedCasts.cpp
+++ b/lib/ARCMigrate/TransUnbridgedCasts.cpp
@@ -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/lib/ARCMigrate/TransformActions.cpp b/lib/ARCMigrate/TransformActions.cpp
index 4f3fb5845925..704be4374d3d 100644
--- a/lib/ARCMigrate/TransformActions.cpp
+++ b/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;
@@ -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,
@@ -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/lib/ARCMigrate/Transforms.cpp b/lib/ARCMigrate/Transforms.cpp
index cb96a547fbac..1f4e6a297fc3 100644
--- a/lib/ARCMigrate/Transforms.cpp
+++ b/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.
diff --git a/lib/ARCMigrate/Transforms.h b/lib/ARCMigrate/Transforms.h
index 7e3dd34e7607..8ea4f79456a8 100644
--- a/lib/ARCMigrate/Transforms.h
+++ b/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,7 +97,7 @@ 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;
@@ -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/lib/AST/APValue.cpp b/lib/AST/APValue.cpp
index 488ad3373ca3..c45b52a65a4d 100644
--- a/lib/AST/APValue.cpp
+++ b/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/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 3dc961d4f12b..25dc4441aafd 100644
--- a/lib/AST/ASTContext.cpp
+++ b/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();
@@ -511,7 +512,7 @@ comments::FullComment *ASTContext::getCommentForDecl(
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.
@@ -604,13 +605,13 @@ ASTContext::CanonicalTemplateTemplateParm::Profile(llvm::FoldingSetNodeID &ID,
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());
@@ -626,7 +627,7 @@ ASTContext::CanonicalTemplateTemplateParm::Profile(llvm::FoldingSetNodeID &ID,
continue;
}
- TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
+ auto *TTP = cast<TemplateTemplateParmDecl>(*P);
ID.AddInteger(2);
Profile(ID, TTP);
}
@@ -651,7 +652,7 @@ ASTContext::getCanonicalTemplateTemplateParmDecl(
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(),
SourceLocation(),
@@ -659,8 +660,7 @@ ASTContext::getCanonicalTemplateTemplateParmDecl(
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;
@@ -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,13 +814,13 @@ 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);
}
@@ -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,7 +999,7 @@ 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())
return None;
@@ -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);
}
@@ -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
@@ -1254,7 +1285,7 @@ AttrVec& ASTContext::getDeclAttrs(const Decl *D) {
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;
}
@@ -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;
@@ -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!");
@@ -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();
@@ -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);
@@ -2033,9 +2113,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,7 +2171,7 @@ void ASTContext::DeepCollectObjCIvars(const ObjCInterfaceDecl *OI,
for (const auto *I : OI->ivars())
Ivars.push_back(I);
} else {
- ObjCInterfaceDecl *IDecl = const_cast<ObjCInterfaceDecl *>(OI);
+ auto *IDecl = const_cast<ObjCInterfaceDecl *>(OI);
for (const ObjCIvarDecl *Iv = IDecl->all_declared_ivar_begin(); Iv;
Iv= Iv->getNextIvar())
Ivars.push_back(Iv);
@@ -2102,7 +2182,7 @@ 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.
for (auto *Proto : OI->all_referenced_protocols()) {
@@ -2118,11 +2198,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)
@@ -2145,7 +2225,7 @@ static bool unionHasUniqueObjectRepresentations(const ASTContext &Context,
if (FieldSize != UnionSize)
return false;
}
- return true;
+ return !RD->field_empty();
}
static bool isStructEmpty(QualType Ty) {
@@ -2184,7 +2264,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 +2344,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;
}
@@ -2330,7 +2410,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 +2420,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 +2430,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,20 +2457,17 @@ 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");
@@ -2398,10 +2475,10 @@ Expr *ASTContext::getBlockVarCopyInits(const VarDecl*VD) {
"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>() &&
@@ -2417,7 +2494,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 +2547,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 +2599,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 +2627,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 +2643,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 +2659,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 +2685,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 +2694,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 +2705,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 +2739,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 +2767,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 +2858,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);
@@ -2807,7 +2881,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 +2896,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 +2917,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 +2932,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 +2962,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 +3006,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 +3035,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 +3079,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 +3087,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 +3110,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 +3122,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 +3134,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,
@@ -3096,7 +3168,7 @@ QualType ASTContext::getVariableArrayType(QualType EltTy,
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);
@@ -3121,7 +3193,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 +3239,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 +3275,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 +3307,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 +3377,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);
@@ -3342,7 +3453,7 @@ QualType ASTContext::getDependentAddressSpaceType(QualType PointeeType,
canonTy->getAddrSpaceExpr() == AddrSpaceExpr)
return QualType(canonTy, 0);
- DependentAddressSpaceType *sugaredType
+ auto *sugaredType
= new (*this, TypeAlignment)
DependentAddressSpaceType(*this, PointeeType, QualType(canonTy, 0),
AddrSpaceExpr, AttrLoc);
@@ -3350,7 +3461,7 @@ QualType ASTContext::getDependentAddressSpaceType(QualType PointeeType,
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 +3493,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 +3527,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 +3546,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 +3573,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 +3620,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 +3642,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 +3672,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 +3687,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 +3715,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 +3738,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 +3774,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 +3806,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);
@@ -3724,7 +3820,7 @@ QualType ASTContext::getRecordType(const RecordDecl *Decl) const {
if (PrevDecl->TypeForDecl)
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);
@@ -3737,7 +3833,7 @@ QualType ASTContext::getEnumType(const EnumDecl *Decl) const {
if (PrevDecl->TypeForDecl)
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 +3859,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 +3882,7 @@ ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm,
return QualType(SubstParm, 0);
}
-/// \brief Retrieve a
+/// Retrieve a
QualType ASTContext::getSubstTemplateTypeParmPackType(
const TemplateTypeParmType *Parm,
const TemplateArgument &ArgPack) {
@@ -3812,7 +3908,7 @@ QualType ASTContext::getSubstTemplateTypeParmPackType(
SubstTemplateTypeParmPackTypes.FindNodeOrInsertPos(ID, InsertPos);
}
- SubstTemplateTypeParmPackType *SubstParm
+ auto *SubstParm
= new (*this, TypeAlignment) SubstTemplateTypeParmPackType(Parm, Canon,
ArgPack);
Types.push_back(SubstParm);
@@ -3820,7 +3916,7 @@ QualType ASTContext::getSubstTemplateTypeParmPackType(
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,
@@ -3931,7 +4027,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());
@@ -3983,12 +4079,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 +4099,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);
@@ -4126,7 +4223,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);
@@ -4265,7 +4362,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 +4410,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 +4428,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 +4453,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 +4475,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 +4483,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 +4520,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);
@@ -4440,7 +4535,7 @@ bool ASTContext::ObjCObjectAdoptsQTypeProtocols(QualType QT,
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 +4553,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 +4562,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()) {
@@ -4520,7 +4615,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);
@@ -4546,7 +4641,7 @@ QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
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 +4688,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 +4778,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 +4800,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 +4830,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);
@@ -4820,14 +4914,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 +4957,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 +4982,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,31 +4999,66 @@ 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>();
+
+ const auto *T1MPType = T1->getAs<MemberPointerType>();
+ const auto *T2MPType = T2->getAs<MemberPointerType>();
if (T1MPType && T2MPType &&
hasSameUnqualifiedType(QualType(T1MPType->getClass(), 0),
QualType(T2MPType->getClass(), 0))) {
@@ -4939,8 +5068,8 @@ bool ASTContext::UnwrapSimilarPointerTypes(QualType &T1, QualType &T2) {
}
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();
@@ -4953,6 +5082,37 @@ bool ASTContext::UnwrapSimilarPointerTypes(QualType &T1, QualType &T2) {
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,8 +5168,7 @@ 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.
@@ -5061,7 +5220,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());
}
@@ -5087,8 +5246,7 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const {
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();
@@ -5139,7 +5297,7 @@ 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>())
+ if (const auto *DNT = T->getAs<DependentNameType>())
return NestedNameSpecifier::Create(*this, DNT->getQualifier(),
const_cast<IdentifierInfo *>(DNT->getIdentifier()));
@@ -5163,7 +5321,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 +5341,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 +5349,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 +5366,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 +5460,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 +5553,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 +5574,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 +5594,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 +5616,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 +5628,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 +5655,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 +5663,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 +5690,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 +5799,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 +5883,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))
@@ -5768,6 +5934,11 @@ bool ASTContext::BlockRequiresCopying(QualType Ty,
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();
@@ -5781,13 +5952,12 @@ bool ASTContext::BlockRequiresCopying(QualType Ty,
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!");
}
@@ -5827,7 +5997,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");
@@ -5879,8 +6049,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());
}
@@ -5921,8 +6090,8 @@ std::string ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr) const {
ParmOffset = PtrSize;
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))
@@ -5964,8 +6133,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))
@@ -6034,8 +6203,8 @@ 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))
@@ -6057,13 +6226,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 +6338,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 +6375,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 +6404,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 ' ';
@@ -6270,7 +6463,7 @@ static char ObjCEncodingForEnumType(const ASTContext *C, const EnumType *ET) {
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 +6500,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 +6528,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 +6554,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 +6598,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 +6623,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 +6634,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 +6663,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,10 +6705,10 @@ 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
@@ -6528,7 +6720,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,7 +6744,7 @@ 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;
}
@@ -6567,7 +6759,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 +6774,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 +6783,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 +6820,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 += '}';
@@ -6702,7 +6894,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);
@@ -6795,7 +6987,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 +6999,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();
@@ -7250,6 +7442,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 +7453,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 +7463,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,7 +7478,7 @@ 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,
@@ -7305,7 +7502,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,7 +7538,7 @@ 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
ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS,
@@ -7399,7 +7596,7 @@ ASTContext::getSubstTemplateTemplateParm(TemplateTemplateParmDecl *param,
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);
@@ -7422,7 +7619,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 +7662,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 +7693,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 &&
@@ -7530,8 +7727,8 @@ ASTContext::ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto,
/// Class<pr1, ...>.
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()) {
@@ -7561,7 +7758,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;
@@ -7847,14 +8044,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 +8111,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 +8136,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 +8187,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 +8222,7 @@ QualType ASTContext::areCommonBaseCompatible(
RHS = RHSSuperType->castAs<ObjCObjectType>();
}
- return QualType();
+ return {};
}
bool ASTContext::canAssignObjCInterfaces(const ObjCObjectType *LHS,
@@ -8092,8 +8289,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 +8343,7 @@ QualType ASTContext::mergeTransparentUnionType(QualType T, QualType SubType,
}
}
- return QualType();
+ return {};
}
/// mergeFunctionParameterTypes - merge two types which appear as function
@@ -8173,10 +8370,10 @@ QualType ASTContext::mergeFunctionParameterTypes(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,7 +8390,8 @@ 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();
@@ -8219,18 +8417,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 +8447,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 +8475,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();
@@ -8308,7 +8508,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 +8520,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 +8552,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,7 +8563,7 @@ 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,
@@ -8397,7 +8599,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 +8611,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 +8619,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 +8650,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>()) {
@@ -8462,7 +8664,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
return RHS;
}
- return QualType();
+ return {};
}
// The canonical type classes match.
@@ -8500,7 +8702,8 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
}
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 +8725,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 +8735,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))
@@ -8550,7 +8754,8 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
}
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 +8767,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();
@@ -8572,7 +8777,40 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
}
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 +8819,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 +8844,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 +8875,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,7 +8953,7 @@ 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 =
@@ -8725,12 +8961,12 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) {
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,7 +8974,7 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) {
return ResultType;
}
}
- return QualType();
+ return {};
}
// If the qualifiers are different, the types can still be merged.
@@ -8748,7 +8984,7 @@ 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
@@ -8760,13 +8996,13 @@ QualType ASTContext::mergeObjCGCQualifiers(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)
return LHS;
if (GC_R == Qualifiers::Strong)
return RHS;
- return QualType();
+ return {};
}
if (LHSCan->isObjCObjectPointerType() && RHSCan->isObjCObjectPointerType()) {
@@ -8778,7 +9014,7 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) {
if (ResQT == RHSBaseQT)
return RHS;
}
- return QualType();
+ return {};
}
//===----------------------------------------------------------------------===//
@@ -8786,7 +9022,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 +9031,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 +9059,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");
}
}
@@ -8931,10 +9193,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;
@@ -9050,7 +9314,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 +9325,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 +9334,7 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
if (Type.isNull()) {
Error = ASTContext::GE_Missing_ucontext;
- return QualType();
+ return {};
}
break;
case 'p':
@@ -9132,14 +9396,14 @@ 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.
@@ -9154,7 +9418,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 +9449,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;
@@ -9240,6 +9504,21 @@ static GVALinkage basicGVALinkageForFunction(const ASTContext &Context,
return GVA_DiscardableODR;
}
+static bool isDeclareTargetToDeclaration(const Decl *VD) {
+ for (const Decl *D : VD->redecls()) {
+ if (!D->hasAttrs())
+ continue;
+ if (const auto *Attr = D->getAttr<OMPDeclareTargetDeclAttr>())
+ return Attr->getMapType() == OMPDeclareTargetDeclAttr::MT_To;
+ }
+ if (const auto *V = dyn_cast<VarDecl>(VD)) {
+ if (const VarDecl *TD = V->getTemplateInstantiationPattern())
+ return isDeclareTargetToDeclaration(TD);
+ }
+
+ return false;
+}
+
static GVALinkage adjustGVALinkageForAttributes(const ASTContext &Context,
const Decl *D, GVALinkage L) {
// See http://msdn.microsoft.com/en-us/library/xa0d9ste.aspx
@@ -9256,6 +9535,12 @@ static GVALinkage adjustGVALinkageForAttributes(const ASTContext &Context,
// visible externally so they can be launched from host.
if (L == GVA_DiscardableODR || L == GVA_Internal)
return GVA_StrongODR;
+ } else if (Context.getLangOpts().OpenMP && Context.getLangOpts().OpenMPIsDevice &&
+ isDeclareTargetToDeclaration(D)) {
+ // Static variables must be visible externally so they can be mapped from
+ // host.
+ if (L == GVA_Internal)
+ return GVA_StrongODR;
}
return L;
}
@@ -9375,7 +9660,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 +9669,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 +9688,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 +9723,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 +9731,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 +9752,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 +9781,41 @@ 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.
+ for (const auto *Decl : D->redecls()) {
+ if (!Decl->hasAttrs())
+ continue;
+ if (const auto *Attr = Decl->getAttr<OMPDeclareTargetDeclAttr>())
+ if (Attr->getMapType() != OMPDeclareTargetDeclAttr::MT_Link)
+ return true;
+ }
+
return false;
}
+void ASTContext::forEachMultiversionedFunctionVersion(
+ const FunctionDecl *FD,
+ llvm::function_ref<void(const 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 +9928,7 @@ QualType ASTContext::getRealTypeForBitwidth(unsigned DestWidth) const {
case TargetInfo::Float128:
return Float128Ty;
case TargetInfo::NoFloat:
- return QualType();
+ return {};
}
llvm_unreachable("Unhandled TargetInfo::RealType value");
@@ -9739,7 +10072,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 +10082,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 +10207,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);
@@ -9942,6 +10276,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 +10320,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/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp
index b43c28deb362..c4c0f6e5ebe3 100644
--- a/lib/AST/ASTDiagnostic.cpp
+++ b/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
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index 92be6d95e898..f46ae58d192d 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/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);
@@ -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/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index 0d1d9807549f..6668067233e4 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/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,14 +212,15 @@ 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
+
+ // Importing declarations
bool ImportDeclParts(NamedDecl *D, DeclContext *&DC,
DeclContext *&LexicalDC, DeclarationName &Name,
NamedDecl *&ToD, SourceLocation &Loc);
@@ -91,22 +228,27 @@ namespace clang {
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);
+ Optional<LambdaCapture> ImportLambdaCapture(const LambdaCapture &From);
- /// \brief What we should import from the definition.
+ /// What we should import from the definition.
enum ImportDefinitionKind {
- /// \brief Import the default subset of the definition, which might be
+ /// 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
};
@@ -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);
}
@@ -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,7 +638,7 @@ 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);
}
@@ -429,7 +646,7 @@ QualType ASTNodeImporter::VisitComplexType(const ComplexType *T) {
QualType ASTNodeImporter::VisitPointerType(const PointerType *T) {
QualType ToPointeeType = Importer.Import(T->getPointeeType());
if (ToPointeeType.isNull())
- return QualType();
+ return {};
return Importer.getToContext().getPointerType(ToPointeeType);
}
@@ -438,7 +655,7 @@ 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,7 +665,7 @@ 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,7 +675,7 @@ 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 {};
return Importer.getToContext().getRValueReferenceType(ToPointeeType);
}
@@ -467,7 +684,7 @@ 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,
@@ -477,7 +694,7 @@ QualType ASTNodeImporter::VisitMemberPointerType(const MemberPointerType *T) {
QualType ASTNodeImporter::VisitConstantArrayType(const ConstantArrayType *T) {
QualType ToElementType = Importer.Import(T->getElementType());
if (ToElementType.isNull())
- return QualType();
+ return {};
return Importer.getToContext().getConstantArrayType(ToElementType,
T->getSize(),
@@ -489,7 +706,7 @@ QualType
ASTNodeImporter::VisitIncompleteArrayType(const IncompleteArrayType *T) {
QualType ToElementType = Importer.Import(T->getElementType());
if (ToElementType.isNull())
- return QualType();
+ return {};
return Importer.getToContext().getIncompleteArrayType(ToElementType,
T->getSizeModifier(),
@@ -499,11 +716,11 @@ 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,
@@ -512,10 +729,28 @@ 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 {};
return Importer.getToContext().getVectorType(ToElementType,
T->getNumElements(),
@@ -525,7 +760,7 @@ QualType ASTNodeImporter::VisitVectorType(const VectorType *T) {
QualType ASTNodeImporter::VisitExtVectorType(const ExtVectorType *T) {
QualType ToElementType = Importer.Import(T->getElementType());
if (ToElementType.isNull())
- return QualType();
+ return {};
return Importer.getToContext().getExtVectorType(ToElementType,
T->getNumElements());
@@ -537,7 +772,7 @@ ASTNodeImporter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
// 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,14 +781,14 @@ 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);
}
@@ -562,7 +797,7 @@ QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) {
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,16 +840,16 @@ 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);
}
@@ -622,7 +857,7 @@ QualType ASTNodeImporter::VisitTypedefType(const TypedefType *T) {
QualType ASTNodeImporter::VisitTypeOfExprType(const TypeOfExprType *T) {
Expr *ToExpr = Importer.Import(T->getUnderlyingExpr());
if (!ToExpr)
- return QualType();
+ return {};
return Importer.getToContext().getTypeOfExprType(ToExpr);
}
@@ -630,7 +865,7 @@ QualType ASTNodeImporter::VisitTypeOfExprType(const TypeOfExprType *T) {
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,7 +901,7 @@ 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(),
@@ -675,13 +910,13 @@ QualType ASTNodeImporter::VisitAutoType(const AutoType *T) {
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,11 +999,11 @@ 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()) {
@@ -779,7 +1011,7 @@ QualType ASTNodeImporter::VisitTemplateSpecializationType(
= Importer.getFromContext().getCanonicalType(QualType(T, 0));
ToCanonType =Importer.Import(FromCanonType);
if (ToCanonType.isNull())
- return QualType();
+ return {};
}
return Importer.getToContext().getTemplateSpecializationType(ToTemplate,
ToTemplateArgs,
@@ -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);
}
@@ -866,8 +1141,26 @@ bool ASTNodeImporter::ImportDeclParts(NamedDecl *D, DeclContext *&DC,
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;
@@ -899,8 +1192,8 @@ void ASTNodeImporter::ImportDefinitionIfNeeded(Decl *FromD, Decl *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);
}
@@ -963,6 +1256,27 @@ void ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) {
Importer.Import(From);
}
+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()) {
@@ -973,10 +1287,12 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To,
}
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()) {
@@ -1103,6 +1420,8 @@ bool ASTNodeImporter::ImportDefinition(EnumDecl *From, EnumDecl *To,
To->startDefinition();
+ setTypedefNameForAnonDecl(From, To, Importer);
+
QualType T = Importer.Import(Importer.getFromContext().getTypeDeclType(From));
if (T.isNull())
return true;
@@ -1154,36 +1473,36 @@ ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) {
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);
}
@@ -1192,7 +1511,7 @@ ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) {
TemplateName ToTemplate
= Importer.Import(From.getAsTemplateOrTemplatePattern());
if (ToTemplate.isNull())
- return TemplateArgument();
+ return {};
return TemplateArgument(ToTemplate, From.getNumTemplateExpansions());
}
@@ -1206,7 +1525,7 @@ ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) {
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()));
@@ -1254,6 +1573,9 @@ bool ASTNodeImporter::ImportTemplateArguments(const TemplateArgument *FromArgs,
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,9 +1704,11 @@ 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;
}
@@ -1367,13 +1717,12 @@ Decl *ASTNodeImporter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
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,17 +1798,17 @@ 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()) {
@@ -1473,24 +1821,24 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) {
// 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);
@@ -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,17 +1904,16 @@ 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()) {
@@ -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;
@@ -1727,22 +2082,22 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
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()) {
@@ -1751,18 +2106,19 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
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.
@@ -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,8 +2220,19 @@ 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
@@ -1889,7 +2259,7 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
}
}
- ConflictingDecls.push_back(FoundDecls[I]);
+ ConflictingDecls.push_back(FoundDecl);
}
if (!ConflictingDecls.empty() && SearchName) {
@@ -1904,53 +2274,80 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
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;
@@ -2005,17 +2399,16 @@ Decl *ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *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 (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()) {
@@ -2031,18 +2424,120 @@ Decl *ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) {
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
@@ -2098,7 +2614,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
}
}
- ConflictingDecls.push_back(FoundDecls[I]);
+ ConflictingDecls.push_back(FoundDecl);
}
if (!ConflictingDecls.empty()) {
@@ -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;
@@ -2308,15 +2854,15 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) {
// 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;
}
@@ -2373,8 +2920,7 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
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()) {
@@ -2607,14 +3154,15 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) {
}
}
- 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(),
@@ -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))
@@ -2695,10 +3243,12 @@ Decl *ASTNodeImporter::VisitImplicitParamDecl(ImplicitParamDecl *D) {
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) {
@@ -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;
@@ -2822,7 +3379,7 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
}
// 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,7 +3405,7 @@ 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;
@@ -2853,16 +3413,19 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
}
// 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,18 +3478,18 @@ 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(
@@ -2943,8 +3504,8 @@ 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);
@@ -2954,9 +3515,8 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
// 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.
@@ -2964,8 +3524,8 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *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;
@@ -2997,8 +3557,7 @@ bool ASTNodeImporter::ImportDefinition(ObjCProtocolDecl *From,
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);
@@ -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,7 +3831,6 @@ Decl *ASTNodeImporter::VisitUnresolvedUsingTypenameDecl(
return ToUsing;
}
-
bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From,
ObjCInterfaceDecl *To,
ImportDefinitionKind Kind) {
@@ -3330,8 +3891,7 @@ bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From,
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);
@@ -3349,8 +3909,8 @@ bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From,
// 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;
@@ -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,27 +3972,27 @@ 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(
@@ -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());
@@ -3477,15 +4037,15 @@ Decl *ASTNodeImporter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
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()) ||
@@ -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,16 +4221,15 @@ 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
@@ -3705,7 +4262,7 @@ Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
}
// Merge the existing implementation with the new implementation.
- Importer.Imported(D, ToImpl);
+ Importer.MapImported(D, ToImpl);
}
return ToImpl;
@@ -3717,15 +4274,14 @@ Decl *ASTNodeImporter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
// 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,69 +4384,73 @@ 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!
}
@@ -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;
@@ -3941,23 +4515,18 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl(
// 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,19 +4539,18 @@ 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());
@@ -3993,8 +4561,6 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl(
// 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;
@@ -4891,16 +5489,11 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
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;
}
@@ -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;
@@ -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;
@@ -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,14 +5713,13 @@ 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()) {
@@ -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;
@@ -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;
@@ -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,
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;
@@ -6029,14 +6856,13 @@ Expr *ASTNodeImporter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
}
}
-
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,19 +6929,18 @@ 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();
@@ -6129,10 +6976,17 @@ TypeSourceInfo *ASTImporter::Import(TypeSourceInfo *FromTSI) {
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
// 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()) {
@@ -6217,8 +7049,8 @@ DeclContext *ASTImporter::ImportContext(DeclContext *FromDC) {
} 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()) {
@@ -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);
}
@@ -6396,22 +7228,20 @@ 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(),
ToTemplates.end());
@@ -6421,22 +7251,22 @@ TemplateName ASTImporter::Import(TemplateName From) {
QualifiedTemplateName *QTN = From.getAsQualifiedTemplateName();
NestedNameSpecifier *Qualifier = Import(QTN->getQualifier());
if (!Qualifier)
- return TemplateName();
+ return {};
- if (TemplateDecl *ToTemplate
- = cast_or_null<TemplateDecl>(Import(From.getAsTemplateDecl())))
+ 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,
@@ -6449,13 +7279,14 @@ TemplateName ASTImporter::Import(TemplateName From) {
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);
}
@@ -6463,17 +7294,17 @@ TemplateName ASTImporter::Import(TemplateName From) {
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
= Importer.ImportTemplateArgument(SubstPack->getArgumentPack());
if (ArgPack.isNull())
- return TemplateName();
+ return {};
return ToContext.getSubstTemplateTemplateParmPack(Param, ArgPack);
}
@@ -6484,22 +7315,16 @@ TemplateName ASTImporter::Import(TemplateName From) {
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())
@@ -6616,10 +7453,10 @@ void ASTImporter::ImportDefinition(Decl *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,
ASTNodeImporter::IDK_Everything);
@@ -6627,7 +7464,7 @@ void ASTImporter::ImportDefinition(Decl *From) {
}
}
- if (EnumDecl *ToEnum = dyn_cast<EnumDecl>(To)) {
+ if (auto *ToEnum = dyn_cast<EnumDecl>(To)) {
if (!ToEnum->getDefinition()) {
Importer.ImportDefinition(cast<EnumDecl>(FromDC), ToEnum,
ASTNodeImporter::IDK_Everything);
@@ -6635,7 +7472,7 @@ void ASTImporter::ImportDefinition(Decl *From) {
}
}
- 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,7 +7480,7 @@ 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);
@@ -6657,7 +7494,7 @@ void ASTImporter::ImportDefinition(Decl *From) {
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/lib/AST/ASTStructuralEquivalence.cpp b/lib/AST/ASTStructuralEquivalence.cpp
index 0df8e5653f3b..7853ab28810b 100644
--- a/lib/AST/ASTStructuralEquivalence.cpp
+++ b/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;
- if (Proto1->getExceptionSpecType() == EST_Dynamic) {
- if (Proto1->getNumExceptions() != Proto2->getNumExceptions())
+
+ // 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 (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/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt
index a6f1027856c7..4f868a3af59e 100644
--- a/lib/AST/CMakeLists.txt
+++ b/lib/AST/CMakeLists.txt
@@ -20,6 +20,7 @@ add_clang_library(clangAST
CommentLexer.cpp
CommentParser.cpp
CommentSema.cpp
+ ComparisonCategories.cpp
DataCollection.cpp
Decl.cpp
DeclarationName.cpp
diff --git a/lib/AST/CXXInheritance.cpp b/lib/AST/CXXInheritance.cpp
index 24e96ba38015..2825329775ed 100644
--- a/lib/AST/CXXInheritance.cpp
+++ b/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);
@@ -217,21 +217,21 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context,
// 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.
@@ -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;
@@ -637,8 +637,7 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD,
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();
diff --git a/lib/AST/CommentBriefParser.cpp b/lib/AST/CommentBriefParser.cpp
index eecea8fc11df..5ec7586a475d 100644
--- a/lib/AST/CommentBriefParser.cpp
+++ b/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/lib/AST/CommentLexer.cpp b/lib/AST/CommentLexer.cpp
index 65d0f56f09ab..6ff4d45a9572 100644
--- a/lib/AST/CommentLexer.cpp
+++ b/lib/AST/CommentLexer.cpp
@@ -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/lib/AST/CommentSema.cpp b/lib/AST/CommentSema.cpp
index 6c2019e1a72b..4bc98bf10765 100644
--- a/lib/AST/CommentSema.cpp
+++ b/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/lib/AST/ComparisonCategories.cpp b/lib/AST/ComparisonCategories.cpp
new file mode 100644
index 000000000000..87f51facc59b
--- /dev/null
+++ b/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/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 4c1d591b41e9..3b9b85a20af6 100644
--- a/lib/AST/Decl.cpp
+++ b/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()));
@@ -779,7 +798,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
// unique-external linkage, it's not legally usable from outside
// this translation unit. However, we should use the C linkage
// rules instead for extern "C" declarations.
- if (Context.getLangOpts().CPlusPlus && !Function->isInExternCContext()) {
+ if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Function)) {
// Only look at the type-as-written. Otherwise, deducing the return type
// of a function could change its linkage.
QualType TypeAsWritten = Function->getType();
@@ -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)) {
@@ -1165,7 +1193,7 @@ LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D,
LVComputationKind computation) {
if (const auto *Function = dyn_cast<FunctionDecl>(D)) {
if (Function->isInAnonymousNamespace() &&
- !Function->isInExternCContext())
+ !isFirstInExternCContext(Function))
return getInternalLinkageFor(Function);
// This is a "void f();" which got merged with a file static.
@@ -1188,7 +1216,7 @@ LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D,
if (const auto *Var = dyn_cast<VarDecl>(D)) {
if (Var->hasExternalStorage()) {
- if (Var->isInAnonymousNamespace() && !Var->isInExternCContext())
+ if (Var->isInAnonymousNamespace() && !isFirstInExternCContext(Var))
return getInternalLinkageFor(Var);
LinkageInfo LV;
@@ -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();
}
@@ -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);
@@ -2844,7 +2898,7 @@ FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) {
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()
@@ -2988,7 +3049,7 @@ static bool RedeclForcesDefC99(const FunctionDecl *Redecl) {
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
@@ -3103,7 +3164,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.
@@ -3605,16 +3666,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 +3722,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 +3973,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 +3995,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 +4448,7 @@ bool TypedefNameDecl::isTransparentTagSlow() const {
};
bool isTransparent = determineIsTransparent();
- CacheIsTransparentTag = 1;
- if (isTransparent)
- CacheIsTransparentTag |= 0x2;
+ MaybeModedTInfo.setInt((isTransparent << 1) | 1);
return isTransparent;
}
@@ -4433,7 +4514,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;
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index 29ce7ae034b5..e3817c0abc38 100644
--- a/lib/AST/DeclBase.cpp
+++ b/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 =
@@ -145,8 +145,8 @@ void Decl::setInvalidDecl(bool Invalid) {
// 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;
}
@@ -236,10 +234,23 @@ TemplateDecl *Decl::getDescribedTemplate() const {
return RD->getDescribedClassTemplate();
else if (auto *VD = dyn_cast<VarDecl>(this))
return VD->getDescribedVarTemplate();
+ else if (auto *AD = dyn_cast<TypeAliasDecl>(this))
+ return AD->getDescribedAliasTemplate();
return nullptr;
}
+bool Decl::isTemplated() const {
+ // A declaration is dependent if it is a template or a template pattern, or
+ // is within (lexcially for a friend, semantically otherwise) a dependent
+ // context.
+ // FIXME: Should local extern declarations be treated like friends?
+ if (auto *AsDC = dyn_cast<DeclContext>(this))
+ return AsDC->isDependentContext();
+ auto *DC = getFriendObjectKind() ? getLexicalDeclContext() : getDeclContext();
+ return DC->isDependentContext() || isTemplateDecl() || getDescribedTemplate();
+}
+
const DeclContext *Decl::getParentFunctionOrMethod() const {
for (const DeclContext *DC = getDeclContext();
DC && !DC->isTranslationUnit() && !DC->isNamespace();
@@ -266,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 << '\'';
@@ -314,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;
@@ -335,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;
}
@@ -348,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();
@@ -413,7 +424,7 @@ bool Decl::isReferenced() const {
return true;
// Check redeclarations.
- for (auto I : redecls())
+ for (const auto *I : redecls())
if (I->Referenced)
return true;
@@ -438,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)
@@ -462,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;
}
@@ -482,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,
@@ -539,7 +550,6 @@ static AvailabilityResult CheckAvailability(ASTContext &Context,
Message->clear();
llvm::raw_string_ostream Out(*Message);
VersionTuple VTI(A->getIntroduced());
- VTI.UseDotAsSeparator();
Out << "introduced in " << PrettyPlatformName << ' '
<< VTI << HintMessage;
}
@@ -553,7 +563,6 @@ static AvailabilityResult CheckAvailability(ASTContext &Context,
Message->clear();
llvm::raw_string_ostream Out(*Message);
VersionTuple VTO(A->getObsoleted());
- VTO.UseDotAsSeparator();
Out << "obsoleted in " << PrettyPlatformName << ' '
<< VTO << HintMessage;
}
@@ -567,7 +576,6 @@ 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;
}
@@ -579,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;
@@ -608,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;
@@ -636,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;
@@ -651,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;
@@ -834,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");
}
@@ -853,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");
}
@@ -869,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 {
@@ -891,12 +904,14 @@ bool Decl::AccessDeclContextSanity() const {
// 4. the context is not a record
// 5. it's invalid
// 6. it's a C++0x static_assert.
+ // 7. it's a block literal declaration
if (isa<TranslationUnitDecl>(this) ||
isa<TemplateTypeParmDecl>(this) ||
isa<NonTypeTemplateParmDecl>(this) ||
!isa<CXXRecordDecl>(getDeclContext()) ||
isInvalidDecl() ||
isa<StaticAssertDecl>(this) ||
+ isa<BlockDecl>(this) ||
// FIXME: a ParmVarDecl can have ClassTemplateSpecialization
// as DeclContext (?).
isa<ParmVarDecl>(this) ||
@@ -917,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;
@@ -936,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() {
@@ -986,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
@@ -1011,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();
}
@@ -1030,7 +1044,7 @@ 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;
@@ -1038,7 +1052,7 @@ bool DeclContext::isDependentContext() const {
return true;
}
- if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(this)) {
+ if (const auto *Function = dyn_cast<FunctionDecl>(this)) {
if (Function->getDescribedFunctionTemplate())
return true;
@@ -1117,18 +1131,18 @@ 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;
@@ -1143,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())
@@ -1175,7 +1189,7 @@ DeclContext::collectAllContexts(SmallVectorImpl<DeclContext *> &Contexts){
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);
@@ -1184,16 +1198,15 @@ DeclContext::collectAllContexts(SmallVectorImpl<DeclContext *> &Contexts){
}
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
@@ -1205,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 {
@@ -1216,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
@@ -1238,7 +1251,7 @@ 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
@@ -1305,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);
}
}
@@ -1335,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");
@@ -1357,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 {
@@ -1396,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);
}
}
@@ -1410,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);
}
@@ -1418,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.
@@ -1490,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.
@@ -1499,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() &&
@@ -1509,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);
}
@@ -1562,7 +1586,7 @@ DeclContext::lookup(DeclarationName Name) const {
}
}
- return lookup_result();
+ return {};
}
StoredDeclsMap *Map = LookupPtr;
@@ -1570,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();
}
@@ -1588,26 +1612,29 @@ 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();
@@ -1639,7 +1666,7 @@ void DeclContext::localUncachedLookup(DeclarationName Name,
// 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);
}
@@ -1681,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();
@@ -1740,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())
@@ -1858,8 +1885,7 @@ 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.
@@ -1867,7 +1893,7 @@ DependentDiagnostic *DependentDiagnostic::Create(ASTContext &C,
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/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 41f2449a9d6a..076e6376d157 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/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) {
@@ -197,29 +217,40 @@ 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)
@@ -228,14 +259,20 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
// C++ [class.virtual]p1:
// 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))
@@ -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;
@@ -376,6 +425,10 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
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,6 +443,16 @@ 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;
@@ -490,6 +553,81 @@ void CXXRecordDecl::markedVirtualFunctionPure() {
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) &&
@@ -502,7 +640,7 @@ void CXXRecordDecl::addedMember(Decl *D) {
if (D->getFriendObjectKind() || D->isInvalidDecl())
return;
- FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D);
+ auto *FunTmpl = dyn_cast<FunctionTemplateDecl>(D);
if (FunTmpl)
D = FunTmpl->getTemplatedDecl();
@@ -510,12 +648,11 @@ 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.
@@ -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,14 +861,39 @@ 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
// 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).
@@ -725,6 +904,11 @@ void CXXRecordDecl::addedMember(Decl *D) {
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()) {
@@ -758,7 +944,6 @@ void CXXRecordDecl::addedMember(Decl *D) {
//
// 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,6 +957,17 @@ 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);
@@ -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())
@@ -1128,8 +1337,7 @@ CXXMethodDecl* CXXRecordDecl::getLambdaCallOperator() const {
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);
@@ -1143,8 +1351,7 @@ CXXMethodDecl* CXXRecordDecl::getLambdaStaticInvoker() const {
if (Invoker.empty()) return nullptr;
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);
@@ -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);
}
@@ -1384,8 +1591,7 @@ 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())
@@ -1396,8 +1602,7 @@ TemplateSpecializationKind CXXRecordDecl::getTemplateSpecializationKind() const{
void
CXXRecordDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
- if (ClassTemplateSpecializationDecl *Spec
- = dyn_cast<ClassTemplateSpecializationDecl>(this)) {
+ if (auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(this)) {
Spec->setSpecializationKind(TSK);
return;
}
@@ -1575,7 +1780,7 @@ void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) {
SOEnd = M->second.end();
SO != SOEnd && !Done; ++SO) {
assert(SO->second.size() > 0 &&
- "All virtual functions have overridding virtual functions");
+ "All virtual functions have overriding virtual functions");
// C++ [class.abstract]p4:
// A class is abstract if it contains or inherits at least one
@@ -1602,8 +1807,8 @@ bool CXXRecordDecl::mayBeAbstract() const {
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;
}
@@ -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.
@@ -1848,7 +2054,7 @@ bool CXXMethodDecl::isUsualDeallocationFunction() const {
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;
}
@@ -1868,7 +2074,7 @@ bool CXXMethodDecl::isCopyAssignmentOperator() const {
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();
@@ -2006,7 +2212,7 @@ TypeLoc CXXCtorInitializer::getBaseClassLoc() const {
if (isBaseInitializer())
return Initializee.get<TypeSourceInfo*>()->getTypeLoc();
else
- return TypeLoc();
+ return {};
}
const Type *CXXCtorInitializer::getBaseClass() const {
@@ -2023,10 +2229,10 @@ SourceLocation CXXCtorInitializer::getSourceLocation() const {
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
@@ -2124,7 +2330,7 @@ bool CXXConstructorDecl::isCopyOrMoveConstructor(unsigned &TypeQuals) const {
const ParmVarDecl *Param = getParamDecl(0);
// Do we have a reference type?
- const ReferenceType *ParamRefType = Param->getType()->getAs<ReferenceType>();
+ const auto *ParamRefType = Param->getType()->getAs<ReferenceType>();
if (!ParamRefType)
return false;
@@ -2174,7 +2380,7 @@ bool CXXConstructorDecl::isSpecializationCopyingObject() const {
ASTContext &Context = getASTContext();
CanQualType ParamType = Context.getCanonicalType(Param->getType());
- // Is it the same as our our class type?
+ // Is it the same as our class type?
CanQualType ClassTy
= Context.getCanonicalType(Context.getTagDeclType(getParent()));
if (ParamType.getUnqualifiedType() != ClassTy)
@@ -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/lib/AST/DeclFriend.cpp b/lib/AST/DeclFriend.cpp
index 461bf36858b7..08fbed361579 100644
--- a/lib/AST/DeclFriend.cpp
+++ b/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/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp
index f95d5def47ac..5db045099997 100644
--- a/lib/AST/DeclObjC.cpp
+++ b/lib/AST/DeclObjC.cpp
@@ -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()) {
@@ -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,7 +230,7 @@ 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;
@@ -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);
}
@@ -437,7 +438,7 @@ void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
// 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];
@@ -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;
}
@@ -710,9 +711,8 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel,
// 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;
}
@@ -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;
@@ -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;
}
@@ -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();
@@ -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;
@@ -1881,7 +1871,7 @@ 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();
@@ -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
//===----------------------------------------------------------------------===//
@@ -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/lib/AST/DeclOpenMP.cpp b/lib/AST/DeclOpenMP.cpp
index 95e44acca032..f5c3599ef6c6 100644
--- a/lib/AST/DeclOpenMP.cpp
+++ b/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/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index b792c5920a55..d3d9c23cca6e 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -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;
}
@@ -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;
}
@@ -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) {
@@ -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,
@@ -1526,7 +1533,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/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index a7949b310cef..8854f7879ac6 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/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;
@@ -118,11 +119,9 @@ unsigned TemplateParameterList::getDepth() const {
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;
@@ -349,7 +348,7 @@ ClassTemplateDecl::getPartialSpecializations() {
RedeclarableTemplateDecl::CommonBase *
ClassTemplateDecl::newCommon(ASTContext &C) const {
- Common *CommonPtr = new (C) Common;
+ auto *CommonPtr = new (C) Common;
C.addDestruction(CommonPtr);
return CommonPtr;
}
@@ -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/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 7ddab9356b54..193efa4e097d 100644
--- a/lib/AST/Expr.cpp
+++ b/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 =
@@ -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,
@@ -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";
}
@@ -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;
@@ -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,33 @@ 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;
+ 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;
}
CXXBaseSpecifier **CastExpr::path_buffer() {
@@ -2049,6 +2101,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);
@@ -2628,7 +2684,7 @@ bool Expr::isDefaultArgument() const {
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))
@@ -2917,8 +2973,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 +3042,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
case ObjCIvarRefExprClass:
case PredefinedExprClass:
case IntegerLiteralClass:
+ case FixedPointLiteralClass:
case FloatingLiteralClass:
case ImaginaryLiteralClass:
case StringLiteralClass:
@@ -3214,7 +3283,7 @@ 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;
@@ -3390,7 +3459,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 +3515,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()))
@@ -3813,7 +3883,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 +4104,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/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index a0d611381123..3a204c244f68 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -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) {
@@ -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;
}
@@ -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.
@@ -561,9 +560,9 @@ CXXStaticCastExpr *CXXStaticCastExpr::Create(const ASTContext &C, QualType T,
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);
+ 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 *>());
@@ -586,9 +585,9 @@ CXXDynamicCastExpr *CXXDynamicCastExpr::Create(const ASTContext &C, QualType T,
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);
+ 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 *>());
@@ -614,7 +613,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 +621,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);
}
@@ -643,9 +642,9 @@ CXXReinterpretCastExpr::Create(const ASTContext &C, QualType T,
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);
+ 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 *>());
@@ -678,8 +677,8 @@ CXXFunctionalCastExpr::Create(const ASTContext &C, QualType T, ExprValueKind VK,
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);
+ 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 *>());
@@ -1079,7 +1078,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 +1175,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;
}
@@ -1274,7 +1273,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,7 +1296,7 @@ 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();
}
@@ -1330,10 +1329,11 @@ SizeOfPackExpr *SizeOfPackExpr::CreateDeserialized(ASTContext &Context,
SubstNonTypeTemplateParmPackExpr::
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 +1378,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 +1402,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())
diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp
index 3bb2b4eb5fc1..c5b3b361a0a5 100644
--- a/lib/AST/ExprClassification.cpp
+++ b/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:
@@ -348,14 +350,14 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
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());
}
@@ -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;
}
@@ -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.
@@ -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/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 8d9b3c3bebc0..e69914f25da2 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/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;
@@ -61,14 +63,22 @@ namespace {
static QualType getType(APValue::LValueBase B) {
if (!B) return QualType();
- if (const ValueDecl *D = B.dyn_cast<const ValueDecl*>())
+ if (const ValueDecl *D = B.dyn_cast<const ValueDecl*>()) {
// FIXME: It's unclear where we're supposed to take the type from, and
- // this actually matters for arrays of unknown bound. Using the type of
- // the most recent declaration isn't clearly correct in general. Eg:
+ // this actually matters for arrays of unknown bound. Eg:
//
// extern int arr[]; void f() { extern int arr[3]; };
// constexpr int *p = &arr[1]; // valid?
- return cast<ValueDecl>(D->getMostRecentDecl())->getType();
+ //
+ // For now, we take the array bound from the most recent declaration.
+ for (auto *Redecl = cast<ValueDecl>(D->getMostRecentDecl()); Redecl;
+ Redecl = cast_or_null<ValueDecl>(Redecl->getPreviousDecl())) {
+ QualType T = Redecl->getType();
+ if (!T->isIncompleteArrayType())
+ return T;
+ }
+ return D->getType();
+ }
const Expr *Base = B.get<const Expr*>();
@@ -131,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();
@@ -438,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;
@@ -449,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.)
@@ -465,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);
};
@@ -598,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.
@@ -617,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
@@ -629,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 {
@@ -714,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(); }
@@ -1078,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) {
@@ -1162,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;
@@ -1254,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) {
@@ -1282,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) {
@@ -1300,7 +1362,6 @@ namespace {
Base = B;
Offset = CharUnits::fromQuantity(0);
InvalidBase = BInvalid;
- CallIndex = I;
Designator = SubobjectDesignator(getType(B));
IsNullPtr = false;
}
@@ -1309,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
@@ -1517,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) {
@@ -1651,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();
@@ -1684,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)) {
@@ -1698,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;
}
}
@@ -1731,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,
@@ -1774,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;
@@ -1794,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()) {
@@ -1823,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;
}
}
@@ -1831,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;
@@ -1846,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);
@@ -2173,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");
}
}
@@ -2396,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.
@@ -2415,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
@@ -2644,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");
}
@@ -2677,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) {
@@ -2692,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))
@@ -2772,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);
@@ -2992,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*>();
@@ -3018,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.
@@ -3105,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*>();
@@ -3129,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() &&
@@ -3142,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");
}
@@ -3167,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
@@ -3182,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.
///
@@ -3204,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
@@ -3216,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);
}
}
@@ -3247,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;
@@ -3373,7 +3461,7 @@ static bool handleCompoundAssignment(
namespace {
struct IncDecSubobjectHandler {
EvalInfo &Info;
- const Expr *E;
+ const UnaryOperator *E;
AccessKinds AccessKind;
APValue *Old;
@@ -3445,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);
@@ -3515,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);
}
@@ -3707,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) {
@@ -3756,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.
@@ -3764,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,
@@ -4290,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};
@@ -4321,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
@@ -4376,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.
@@ -4406,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
@@ -4422,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())
@@ -4433,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())
@@ -4570,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);
@@ -4650,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();
@@ -4828,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);
@@ -4948,7 +5068,7 @@ public:
}
};
-}
+} // namespace
//===----------------------------------------------------------------------===//
// Common base class for lvalue and temporary evaluation.
@@ -5170,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
@@ -5208,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())
@@ -5247,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();
@@ -5433,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`.
///
@@ -5444,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;
@@ -5464,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;
@@ -5484,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,
@@ -5496,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.
@@ -5662,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:
@@ -5680,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();
@@ -5728,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;
@@ -5744,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.
@@ -6117,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);
};
}
@@ -6512,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) {
@@ -6787,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)
@@ -6816,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
@@ -6939,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() &&
@@ -6974,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;
@@ -7076,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
@@ -7133,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
- };
+static GCCTypeClass
+EvaluateBuiltinClassifyType(QualType T, const LangOptions &LangOpts) {
+ assert(!T->isDependentType() && "unexpected dependent type");
- // 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;
-
- QualType CanTy = E->getArg(0)->getType().getCanonicalType();
+ QualType CanTy = T.getCanonicalType();
const BuiltinType *BT = dyn_cast<BuiltinType>(CanTy);
switch (CanTy->getTypeClass()) {
@@ -7165,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:
@@ -7206,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
@@ -7592,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
@@ -7697,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
@@ -7913,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()));
@@ -7979,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);
+ }
}
}
@@ -7999,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) {
@@ -8031,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
@@ -8076,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());
}
@@ -8119,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);
@@ -8363,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;
@@ -8408,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);
}
}
@@ -8446,246 +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;
-
- // 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.
- // (Note that clang defaults to -fmerge-all-constants, which can
- // lead to inconsistent results for comparisons involving the address
- // of a constant; this generally doesn't matter in practice.)
- 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();
+ LValue LHSValue, RHSValue;
- 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;
@@ -8702,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()) {
@@ -8728,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);
}
@@ -8878,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;
@@ -9083,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
//===----------------------------------------------------------------------===//
@@ -9170,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);
@@ -9182,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);
@@ -9190,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),
@@ -9200,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;
@@ -9213,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))
@@ -9928,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))
@@ -9936,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;
@@ -9958,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 {
@@ -10120,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 {
@@ -10367,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:
@@ -10389,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,
@@ -10475,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.
@@ -10497,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 ||
@@ -10644,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;
}
@@ -10781,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/lib/AST/ExternalASTMerger.cpp b/lib/AST/ExternalASTMerger.cpp
index 6b75c51c6420..ae28c588ca31 100644
--- a/lib/AST/ExternalASTMerger.cpp
+++ b/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/lib/AST/ItaniumCXXABI.cpp b/lib/AST/ItaniumCXXABI.cpp
index d6bc16b6350f..a75ae14f9015 100644
--- a/lib/AST/ItaniumCXXABI.cpp
+++ b/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];
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index 3c7e26d41370..3b99a3d9afda 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -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;
@@ -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)
@@ -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:
//
@@ -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:
@@ -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,7 +2354,11 @@ 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;
}
@@ -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;
@@ -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";
}
@@ -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));
}
@@ -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) {
@@ -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.
diff --git a/lib/AST/MicrosoftCXXABI.cpp b/lib/AST/MicrosoftCXXABI.cpp
index b19491f31304..3b417c135285 100644
--- a/lib/AST/MicrosoftCXXABI.cpp
+++ b/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/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp
index 0c55c1a92287..e45f9f7902e2 100644
--- a/lib/AST/MicrosoftMangle.cpp
+++ b/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);
};
}
@@ -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));
@@ -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";
@@ -950,11 +957,10 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
}
}
+// <postfix> ::= <unqualified-name> [<postfix>]
+// ::= <substitution> [<postfix>]
void MicrosoftCXXNameMangler::mangleNestedName(const NamedDecl *ND) {
- // <postfix> ::= <unqualified-name> [<postfix>]
- // ::= <substitution> [<postfix>]
const DeclContext *DC = getEffectiveDeclContext(ND);
-
while (!DC->isTranslationUnit()) {
if (isa<TagDecl>(ND) || isa<VarDecl>(ND)) {
unsigned Disc;
@@ -1007,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);
@@ -1365,15 +1371,15 @@ 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<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);
@@ -1457,6 +1463,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>
@@ -1559,12 +1606,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() ||
@@ -1685,6 +1731,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)) {
@@ -1703,7 +1751,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);
}
@@ -1833,15 +1883,12 @@ 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");
break;
case BuiltinType::ObjCClass:
- Out << "PA";
mangleArtificalTagType(TTK_Struct, "objc_class");
break;
case BuiltinType::ObjCSel:
- Out << "PA";
mangleArtificalTagType(TTK_Struct, "objc_selector");
break;
@@ -1876,8 +1923,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 +2218,8 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(CallingConv CC) {
case CC_X86StdCall: Out << 'G'; break;
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,6 +2282,8 @@ 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) {
// <name> ::= <unscoped-name> {[<named-scope>]+ | [<nested-name>]}? @
@@ -2337,10 +2419,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 +2472,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 +2538,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();
@@ -2457,9 +2575,33 @@ void MicrosoftCXXNameMangler::mangleType(const ObjCInterfaceType *T, Qualifiers,
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(T->getInterface()->getName());
+
+ for (const auto &Q : T->quals())
+ mangleObjCProtocol(Q);
+ Out << '@';
+
+ Out << '@';
+
+ TypeBackReferences.swap(OuterArgsContext);
+ NameBackReferences.swap(OuterTemplateContext);
}
void MicrosoftCXXNameMangler::mangleType(const BlockPointerType *T,
@@ -2700,17 +2842,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 +2856,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 +2877,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 +2893,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 +2912,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 +2923,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 +2939,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 +2985,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 +2997,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 +3016,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 +3029,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 +3038,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 +3054,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 +3074,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 +3086,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 +3119,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 +3128,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 +3150,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 +3172,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 +3198,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 +3218,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 +3239,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 +3253,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 +3262,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 +3299,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/lib/AST/NSAPI.cpp b/lib/AST/NSAPI.cpp
index 8adaef1fb640..536bf2c378fa 100644
--- a/lib/AST/NSAPI.cpp
+++ b/lib/AST/NSAPI.cpp
@@ -436,10 +436,35 @@ NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
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:
@@ -470,15 +495,15 @@ NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
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);
}
diff --git a/lib/AST/NestedNameSpecifier.cpp b/lib/AST/NestedNameSpecifier.cpp
index 889f8308a93c..503d0eb65e1e 100644
--- a/lib/AST/NestedNameSpecifier.cpp
+++ b/lib/AST/NestedNameSpecifier.cpp
@@ -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,7 +227,7 @@ 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()) {
@@ -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,
@@ -387,7 +387,7 @@ 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;
@@ -395,7 +395,7 @@ static SourceLocation LoadSourceLocation(void *Data, unsigned Offset) {
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;
@@ -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);
@@ -479,7 +479,7 @@ static void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize,
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();
@@ -488,7 +488,7 @@ static void SaveSourceLocation(SourceLocation Loc, char *&Buffer,
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),
diff --git a/lib/AST/ODRHash.cpp b/lib/AST/ODRHash.cpp
index 088d8bedd453..e710d3780337 100644
--- a/lib/AST/ODRHash.cpp
+++ b/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,28 +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;
-
// 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());
@@ -496,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 {
@@ -642,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);
@@ -710,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/lib/AST/OpenMPClause.cpp b/lib/AST/OpenMPClause.cpp
index 4feac0cfd041..50729264bfe1 100644
--- a/lib/AST/OpenMPClause.cpp
+++ b/lib/AST/OpenMPClause.cpp
@@ -702,10 +702,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/lib/AST/ParentMap.cpp b/lib/AST/ParentMap.cpp
index d8882c9030b2..bc57b20790d9 100644
--- a/lib/AST/ParentMap.cpp
+++ b/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;
@@ -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/lib/AST/QualTypeNames.cpp b/lib/AST/QualTypeNames.cpp
index 86c0eff9f78c..8b605ef295a0 100644
--- a/lib/AST/QualTypeNames.cpp
+++ b/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/lib/AST/RawCommentList.cpp b/lib/AST/RawCommentList.cpp
index 881a7d9c61be..95da9ed6d238 100644
--- a/lib/AST/RawCommentList.cpp
+++ b/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/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp
index a9d43dfa80c5..b4b09c7cecd7 100644
--- a/lib/AST/RecordLayoutBuilder.cpp
+++ b/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
@@ -579,16 +579,16 @@ 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;
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;
@@ -632,7 +632,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;
@@ -749,7 +749,7 @@ 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.
@@ -967,7 +967,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()) {
@@ -1175,9 +1175,16 @@ ItaniumRecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) {
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()) &&
@@ -1504,9 +1511,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;
@@ -1751,7 +1759,34 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D,
QualType T = Context.getBaseElementType(D->getType());
if (const BuiltinType *BTy = T->getAs<BuiltinType>()) {
CharUnits TypeSize = Context.getTypeSizeInChars(BTy);
- if (TypeSize > FieldAlign)
+
+ if (!llvm::isPowerOf2_64(TypeSize.getQuantity())) {
+ assert(
+ !Context.getTargetInfo().getTriple().isWindowsMSVCEnvironment() &&
+ "Non PowerOf2 size in MSVC mode");
+ // Base types with sizes that aren't a power of two don't work
+ // with the layout rules for MS structs. This isn't an issue in
+ // MSVC itself since there are no such base data types there.
+ // On e.g. x86_32 mingw and linux, long double is 12 bytes though.
+ // Any structs involving that data type obviously can't be ABI
+ // compatible with MSVC regardless of how it is laid out.
+
+ // Since ms_struct can be mass enabled (via a pragma or via the
+ // -mms-bitfields command line parameter), this can trigger for
+ // structs that don't actually need MSVC compatibility, so we
+ // need to be able to sidestep the ms_struct layout for these types.
+
+ // Since the combination of -mms-bitfields together with structs
+ // like max_align_t (which contains a long double) for mingw is
+ // quite comon (and GCC handles it silently), just handle it
+ // silently there. For other targets that have ms_struct enabled
+ // (most probably via a pragma or attribute), trigger a diagnostic
+ // that defaults to an error.
+ if (!Context.getTargetInfo().getTriple().isWindowsGNUEnvironment())
+ Diag(D->getLocation(), diag::warn_npot_ms_struct);
+ }
+ if (TypeSize > FieldAlign &&
+ llvm::isPowerOf2_64(TypeSize.getQuantity()))
FieldAlign = TypeSize;
}
}
@@ -1929,7 +1964,7 @@ ItaniumRecordLayoutBuilder::updateExternalFieldOffset(const FieldDecl *Field,
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!
///
@@ -2106,7 +2141,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");
@@ -2220,9 +2255,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);
@@ -2233,93 +2268,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;
};
@@ -2584,8 +2619,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.
@@ -2642,7 +2677,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;
@@ -2654,6 +2689,14 @@ void MicrosoftRecordLayoutBuilder::layoutBitField(const FieldDecl *FD) {
placeFieldAtOffset(CharUnits::Zero());
Size = std::max(Size, Info.Size);
// TODO: Add a Sema warning that MS ignores bitfield alignment in unions.
+ } else if (UseExternalLayout) {
+ auto FieldBitOffset = External.getExternalFieldOffset(FD);
+ placeFieldAtBitOffset(FieldBitOffset);
+ auto NewSize = Context.toCharUnitsFromBits(
+ llvm::alignTo(FieldBitOffset + Width, Context.getCharWidth()));
+ assert(NewSize >= Size && "bit field offset already allocated");
+ Size = NewSize;
+ Alignment = std::max(Alignment, Info.Alignment);
} else {
// Allocate a new block of memory and place the bitfield in it.
CharUnits FieldOffset = Size.alignTo(Info.Alignment);
@@ -3010,7 +3053,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
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
index 982fd458493f..a041006c905e 100644
--- a/lib/AST/Stmt.cpp
+++ b/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/lib/AST/StmtCXX.cpp b/lib/AST/StmtCXX.cpp
index 666f5dcc9d97..bf2d6a16fb5f 100644
--- a/lib/AST/StmtCXX.cpp
+++ b/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/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index d7e668a83280..dad57de8940b 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/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 {
@@ -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
@@ -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());
@@ -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());
@@ -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 << "...";
@@ -2755,4 +2818,4 @@ void Stmt::printPretty(raw_ostream &OS, PrinterHelper *Helper,
//===----------------------------------------------------------------------===//
// Implement virtual destructor.
-PrinterHelper::~PrinterHelper() {}
+PrinterHelper::~PrinterHelper() = default;
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index 00ef0da18bbb..791ec569cc41 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/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());
@@ -1659,7 +1691,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());
diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp
index e81c11a77825..394e9f38bcfd 100644
--- a/lib/AST/TemplateBase.cpp
+++ b/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.
///
@@ -406,7 +406,7 @@ void TemplateArgument::print(const PrintingPolicy &Policy,
}
case Declaration: {
- NamedDecl *ND = cast<NamedDecl>(getAsDecl());
+ NamedDecl *ND = getAsDecl();
Out << '&';
if (ND->getDeclName()) {
// FIXME: distinguish between pointer and reference args?
diff --git a/lib/AST/TemplateName.cpp b/lib/AST/TemplateName.cpp
index bd04fd8366b3..548468ed17cd 100644
--- a/lib/AST/TemplateName.cpp
+++ b/lib/AST/TemplateName.cpp
@@ -185,6 +185,11 @@ bool TemplateName::isInstantiationDependent() const {
}
bool TemplateName::containsUnexpandedParameterPack() const {
+ if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
+ if (QTN->getQualifier()->containsUnexpandedParameterPack())
+ return true;
+ }
+
if (TemplateDecl *Template = getAsTemplateDecl()) {
if (TemplateTemplateParmDecl *TTP
= dyn_cast<TemplateTemplateParmDecl>(Template))
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 38f2a16fa16f..fad8c0d1c6b2 100644
--- a/lib/AST/Type.cpp
+++ b/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;
@@ -166,6 +177,27 @@ 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,
@@ -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;
@@ -622,7 +663,7 @@ bool ObjCObjectType::isSpecialized() const {
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),
@@ -733,7 +772,7 @@ public:
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,7 +805,7 @@ public:
QualType VisitLValueReferenceType(const LValueReferenceType *T) {
QualType pointeeType = recurse(T->getPointeeTypeAsWritten());
if (pointeeType.isNull())
- return QualType();
+ return {};
if (pointeeType.getAsOpaquePtr()
== T->getPointeeTypeAsWritten().getAsOpaquePtr())
@@ -778,7 +817,7 @@ public:
QualType VisitRValueReferenceType(const RValueReferenceType *T) {
QualType pointeeType = recurse(T->getPointeeTypeAsWritten());
if (pointeeType.isNull())
- return QualType();
+ return {};
if (pointeeType.getAsOpaquePtr()
== T->getPointeeTypeAsWritten().getAsOpaquePtr())
@@ -790,7 +829,7 @@ 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);
@@ -801,7 +840,7 @@ public:
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);
@@ -840,7 +879,7 @@ public:
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);
@@ -852,7 +891,7 @@ public:
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);
@@ -863,7 +902,7 @@ public:
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);
@@ -874,7 +913,7 @@ public:
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();
+ return {};
- if (newExceptionType.getAsOpaquePtr()
- != exceptionType.getAsOpaquePtr())
+ if (newExceptionType.getAsOpaquePtr() != exceptionType.getAsOpaquePtr())
exceptionChanged = true;
exceptionTypes.push_back(newExceptionType);
@@ -923,7 +961,7 @@ public:
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);
@@ -937,11 +975,11 @@ public:
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()
== T->getOriginalType().getAsOpaquePtr() &&
@@ -954,7 +992,7 @@ public:
QualType VisitDecayedType(const DecayedType *T) {
QualType originalType = recurse(T->getOriginalType());
if (originalType.isNull())
- return QualType();
+ return {};
if (originalType.getAsOpaquePtr()
== T->getOriginalType().getAsOpaquePtr())
@@ -976,11 +1014,11 @@ public:
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()
== T->getModifiedType().getAsOpaquePtr() &&
@@ -995,7 +1033,7 @@ public:
QualType VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {
QualType replacementType = recurse(T->getReplacementType());
if (replacementType.isNull())
- return QualType();
+ return {};
if (replacementType.getAsOpaquePtr()
== T->getReplacementType().getAsOpaquePtr())
@@ -1014,7 +1052,7 @@ public:
QualType deducedType = recurse(T->getDeducedType());
if (deducedType.isNull())
- return QualType();
+ return {};
if (deducedType.getAsOpaquePtr()
== T->getDeducedType().getAsOpaquePtr())
@@ -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;
@@ -1061,7 +1099,7 @@ public:
QualType VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
QualType pointeeType = recurse(T->getPointeeType());
if (pointeeType.isNull())
- return QualType();
+ return {};
if (pointeeType.getAsOpaquePtr()
== T->getPointeeType().getAsOpaquePtr())
@@ -1073,7 +1111,7 @@ public:
QualType VisitAtomicType(const AtomicType *T) {
QualType valueType = recurse(T->getValueType());
if (valueType.isNull())
- return QualType();
+ return {};
if (valueType.getAsOpaquePtr()
== T->getValueType().getAsOpaquePtr())
@@ -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;
@@ -1593,7 +1630,7 @@ CXXRecordDecl *Type::getAsCXXRecordDecl() const {
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,13 +1731,13 @@ 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
/// C++ [basic.fundamental]p7. Although the C standard does not define the
@@ -1720,20 +1757,20 @@ bool Type::hasIntegerRepresentation() const {
///
/// \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 +1778,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 +1794,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 +1842,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,12 +1858,12 @@ 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();
}
@@ -1828,7 +1872,7 @@ bool Type::isSignedIntegerOrEnumerationType() const {
}
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 +1882,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,12 +1898,12 @@ 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();
}
@@ -1868,48 +1912,48 @@ bool Type::isUnsignedIntegerOrEnumerationType() const {
}
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 +1968,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 +1985,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 +1994,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 +2004,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 +2041,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 +2077,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;
@@ -2105,8 +2144,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.
@@ -2144,9 +2183,8 @@ bool QualType::isTrivialType(const ASTContext &Context) const {
// 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
@@ -2188,9 +2226,8 @@ bool QualType::isTriviallyCopyableType(const ASTContext &Context) const {
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 +2244,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 +2319,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 +2330,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 +2366,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 +2405,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 +2434,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 +2443,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 +2452,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 +2463,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,7 +2473,7 @@ 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;
@@ -2506,7 +2580,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 +2628,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;
@@ -2619,6 +2693,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 +2748,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,7 +2798,7 @@ 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]:
@@ -2732,7 +2856,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 +2885,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 +2911,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 +2919,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 +2929,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,52 +2957,36 @@ 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.");
-
- return value.getBoolValue() ? NR_Nothrow : NR_Throw;
-}
+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");
-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 {
@@ -2928,8 +3036,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) {
@@ -3048,7 +3155,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;
}
@@ -3097,6 +3204,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 +3242,7 @@ bool AttributedType::isCallingConv() const {
case attr_nullable:
case attr_null_unspecified:
case attr_objc_kindof:
+ case attr_nocf_check:
return false;
case attr_pcs:
@@ -3229,8 +3338,7 @@ TemplateSpecializationType(TemplateName T,
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 +3360,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 +3428,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;
@@ -3450,7 +3558,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 +3572,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 +3595,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 +3642,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 +3657,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));
@@ -3702,6 +3810,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 +3853,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 +3898,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 +3913,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 +3924,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 +3938,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,15 +3956,15 @@ bool Type::isObjCLifetimeType() const {
return type->isObjCRetainableType();
}
-/// \brief Determine whether the given type T is a "bridgable" Objective-C type,
+/// 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;
@@ -3867,9 +3975,9 @@ 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) &&
@@ -3895,16 +4003,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/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp
index 0ac50b31acec..6fa76e14a590 100644
--- a/lib/AST/TypeLoc.cpp
+++ b/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,13 +118,13 @@ 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,
@@ -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,6 +344,30 @@ 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.
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index c28ada7dcb8b..c5e2244e26c5 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/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,20 +14,40 @@
#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;
@@ -35,7 +55,7 @@ namespace {
public:
explicit IncludeStrongLifetimeRAII(PrintingPolicy &Policy)
- : Policy(Policy), Old(Policy.SuppressStrongLifetime) {
+ : Policy(Policy), Old(Policy.SuppressStrongLifetime) {
if (!Policy.SuppressLifetimeQualifiers)
Policy.SuppressStrongLifetime = false;
}
@@ -51,7 +71,7 @@ namespace {
public:
explicit ParamPolicyRAII(PrintingPolicy &Policy)
- : Policy(Policy), Old(Policy.SuppressSpecifiers) {
+ : Policy(Policy), Old(Policy.SuppressSpecifiers) {
Policy.SuppressSpecifiers = false;
}
@@ -82,13 +102,12 @@ namespace {
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,10 +189,9 @@ 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) {
@@ -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,54 +379,69 @@ 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,
@@ -423,6 +460,7 @@ void TypePrinter::printMemberPointerBefore(const MemberPointerType *T,
OS << "::*";
}
+
void TypePrinter::printMemberPointerAfter(const MemberPointerType *T,
raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
@@ -440,6 +478,7 @@ void TypePrinter::printConstantArrayBefore(const ConstantArrayType *T,
SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
printBefore(T->getElementType(), OS);
}
+
void TypePrinter::printConstantArrayAfter(const ConstantArrayType *T,
raw_ostream &OS) {
OS << '[';
@@ -462,6 +501,7 @@ void TypePrinter::printIncompleteArrayBefore(const IncompleteArrayType *T,
SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
printBefore(T->getElementType(), OS);
}
+
void TypePrinter::printIncompleteArrayAfter(const IncompleteArrayType *T,
raw_ostream &OS) {
OS << "[]";
@@ -474,6 +514,7 @@ void TypePrinter::printVariableArrayBefore(const VariableArrayType *T,
SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
printBefore(T->getElementType(), OS);
}
+
void TypePrinter::printVariableArrayAfter(const VariableArrayType *T,
raw_ostream &OS) {
OS << '[';
@@ -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,6 +549,7 @@ 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);
}
@@ -518,6 +561,7 @@ void TypePrinter::printDependentSizedArrayBefore(
SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
printBefore(T->getElementType(), OS);
}
+
void TypePrinter::printDependentSizedArrayAfter(
const DependentSizedArrayType *T,
raw_ostream &OS) {
@@ -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(";
@@ -546,6 +591,7 @@ void TypePrinter::printDependentSizedExtVectorBefore(
raw_ostream &OS) {
printBefore(T->getElementType(), OS);
}
+
void TypePrinter::printDependentSizedExtVectorAfter(
const DependentSizedExtVectorType *T,
raw_ostream &OS) {
@@ -592,14 +638,64 @@ void TypePrinter::printVectorBefore(const VectorType *T, raw_ostream &OS) {
}
}
}
+
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) {
printBefore(T->getElementType(), OS);
}
+
void TypePrinter::printExtVectorAfter(const ExtVectorType *T, raw_ostream &OS) {
printAfter(T->getElementType(), OS);
OS << " __attribute__((ext_vector_type(";
@@ -611,7 +707,6 @@ void
FunctionProtoType::printExceptionSpecification(raw_ostream &OS,
const PrintingPolicy &Policy)
const {
-
if (hasDynamicExceptionSpec()) {
OS << " throw(";
if (getExceptionSpecType() == EST_MSAny)
@@ -626,7 +721,9 @@ FunctionProtoType::printExceptionSpecification(raw_ostream &OS,
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);
@@ -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");
@@ -801,6 +898,8 @@ 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,
@@ -811,6 +910,7 @@ void TypePrinter::printFunctionNoProtoBefore(const FunctionNoProtoType *T,
if (!PrevPHIsEmpty.get())
OS << '(';
}
+
void TypePrinter::printFunctionNoProtoAfter(const FunctionNoProtoType *T,
raw_ostream &OS) {
// If needed for precedence reasons, wrap the inner part in grouping parens.
@@ -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) {
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,8 +957,9 @@ 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) {
OS << "typeof(";
@@ -864,7 +967,8 @@ void TypePrinter::printTypeOfBefore(const TypeOfType *T, raw_ostream &OS) {
OS << ')';
spaceBeforePlaceHolder(OS);
}
-void TypePrinter::printTypeOfAfter(const TypeOfType *T, raw_ostream &OS) { }
+
+void TypePrinter::printTypeOfAfter(const TypeOfType *T, raw_ostream &OS) {}
void TypePrinter::printDecltypeBefore(const DecltypeType *T, raw_ostream &OS) {
OS << "decltype(";
@@ -873,7 +977,8 @@ void TypePrinter::printDecltypeBefore(const DecltypeType *T, raw_ostream &OS) {
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);
@@ -915,6 +1021,7 @@ void TypePrinter::printAutoBefore(const AutoType *T, raw_ostream &OS) {
spaceBeforePlaceHolder(OS);
}
}
+
void TypePrinter::printAutoAfter(const AutoType *T, raw_ostream &OS) {
// If the type has been deduced, do not print 'auto'.
if (!T->getDeducedType().isNull())
@@ -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,15 +1070,15 @@ 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 (const auto *NS = dyn_cast<NamespaceDecl>(DC)) {
if (Policy.SuppressUnwrittenScope &&
(NS->isAnonymousNamespace() || NS->isInline()))
return;
@@ -977,14 +1086,13 @@ void TypePrinter::AppendScope(DeclContext *DC, raw_ostream &OS) {
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())
@@ -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,12 +1185,14 @@ 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::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::printEnumAfter(const EnumType *T, raw_ostream &OS) {}
void TypePrinter::printTemplateTypeParmBefore(const TemplateTypeParmType *T,
raw_ostream &OS) {
@@ -1093,8 +1202,9 @@ void TypePrinter::printTemplateTypeParmBefore(const TemplateTypeParmType *T,
OS << "type-parameter-" << T->getDepth() << '-' << T->getIndex();
spaceBeforePlaceHolder(OS);
}
+
void TypePrinter::printTemplateTypeParmAfter(const TemplateTypeParmType *T,
- raw_ostream &OS) { }
+ raw_ostream &OS) {}
void TypePrinter::printSubstTemplateTypeParmBefore(
const SubstTemplateTypeParmType *T,
@@ -1102,6 +1212,7 @@ void TypePrinter::printSubstTemplateTypeParmBefore(
IncludeStrongLifetimeRAII Strong(Policy);
printBefore(T->getReplacementType(), OS);
}
+
void TypePrinter::printSubstTemplateTypeParmAfter(
const SubstTemplateTypeParmType *T,
raw_ostream &OS) {
@@ -1115,6 +1226,7 @@ void TypePrinter::printSubstTemplateTypeParmPackBefore(
IncludeStrongLifetimeRAII Strong(Policy);
printTemplateTypeParmBefore(T->getReplacedParameter(), OS);
}
+
void TypePrinter::printSubstTemplateTypeParmPackAfter(
const SubstTemplateTypeParmPackType *T,
raw_ostream &OS) {
@@ -1131,26 +1243,39 @@ void TypePrinter::printTemplateSpecializationBefore(
printTemplateArgumentList(OS, T->template_arguments(), Policy);
spaceBeforePlaceHolder(OS);
}
+
void TypePrinter::printTemplateSpecializationAfter(
const TemplateSpecializationType *T,
- raw_ostream &OS) { }
+ 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);
}
@@ -1158,8 +1283,11 @@ void TypePrinter::printElaboratedBefore(const ElaboratedType *T,
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 << ')';
@@ -1190,8 +1319,9 @@ void TypePrinter::printDependentNameBefore(const DependentNameType *T,
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) {
@@ -1209,12 +1339,13 @@ void TypePrinter::printDependentTemplateSpecializationBefore(
}
void TypePrinter::printDependentTemplateSpecializationAfter(
- const DependentTemplateSpecializationType *T, raw_ostream &OS) { }
+ const DependentTemplateSpecializationType *T, raw_ostream &OS) {}
void TypePrinter::printPackExpansionBefore(const PackExpansionType *T,
raw_ostream &OS) {
printBefore(T->getPattern(), OS);
}
+
void TypePrinter::printPackExpansionAfter(const PackExpansionType *T,
raw_ostream &OS) {
printAfter(T->getPattern(), OS);
@@ -1323,9 +1454,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 +1464,6 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
}
OS << ')';
break;
- }
case AttributedType::attr_neon_vector_type:
case AttributedType::attr_neon_polyvector_type: {
@@ -1341,7 +1471,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;
@@ -1396,7 +1526,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 +1548,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;
@@ -1434,8 +1566,9 @@ void TypePrinter::printObjCInterfaceBefore(const ObjCInterfaceType *T,
OS << T->getDecl()->getName();
spaceBeforePlaceHolder(OS);
}
+
void TypePrinter::printObjCInterfaceAfter(const ObjCInterfaceType *T,
- raw_ostream &OS) { }
+ raw_ostream &OS) {}
void TypePrinter::printObjCTypeParamBefore(const ObjCTypeParamType *T,
raw_ostream &OS) {
@@ -1457,7 +1590,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 +1632,7 @@ void TypePrinter::printObjCObjectBefore(const ObjCObjectType *T,
spaceBeforePlaceHolder(OS);
}
+
void TypePrinter::printObjCObjectAfter(const ObjCObjectType *T,
raw_ostream &OS) {
if (T->qual_empty() && T->isUnspecializedAsWritten() &&
@@ -1520,7 +1654,7 @@ void TypePrinter::printObjCObjectPointerBefore(const ObjCObjectPointerType *T,
}
void TypePrinter::printObjCObjectPointerAfter(const ObjCObjectPointerType *T,
- raw_ostream &OS) { }
+ raw_ostream &OS) {}
static
const TemplateArgument &getArgument(const TemplateArgument &A) { return A; }
diff --git a/lib/AST/VTableBuilder.cpp b/lib/AST/VTableBuilder.cpp
index 347c516ef6a5..0a3da024f147 100644
--- a/lib/AST/VTableBuilder.cpp
+++ b/lib/AST/VTableBuilder.cpp
@@ -2105,8 +2105,8 @@ 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);
});
@@ -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,6 +2223,7 @@ 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;
@@ -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/lib/ASTMatchers/ASTMatchFinder.cpp b/lib/ASTMatchers/ASTMatchFinder.cpp
index 02aee4b46ddd..63f8395b8277 100644
--- a/lib/ASTMatchers/ASTMatchFinder.cpp
+++ b/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/lib/ASTMatchers/ASTMatchersInternal.cpp b/lib/ASTMatchers/ASTMatchersInternal.cpp
index 0bcdd8e32804..9cea2f5efc5b 100644
--- a/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ b/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/lib/ASTMatchers/Dynamic/Marshallers.h b/lib/ASTMatchers/Dynamic/Marshallers.h
index af90e2c7eca1..c6c89351afd3 100644
--- a/lib/ASTMatchers/Dynamic/Marshallers.h
+++ b/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/lib/ASTMatchers/Dynamic/Parser.cpp b/lib/ASTMatchers/Dynamic/Parser.cpp
index 89e1a2695860..da8df907ba7f 100644
--- a/lib/ASTMatchers/Dynamic/Parser.cpp
+++ b/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/lib/ASTMatchers/Dynamic/Registry.cpp b/lib/ASTMatchers/Dynamic/Registry.cpp
index 2b7bb7a2120d..4d2d76f6a75b 100644
--- a/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/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/lib/ASTMatchers/Dynamic/VariantValue.cpp b/lib/ASTMatchers/Dynamic/VariantValue.cpp
index 57858d00acb4..06d95eaa7563 100644
--- a/lib/ASTMatchers/Dynamic/VariantValue.cpp
+++ b/lib/ASTMatchers/Dynamic/VariantValue.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Polymorphic value type.
+/// Polymorphic value type.
///
//===----------------------------------------------------------------------===//
diff --git a/lib/Analysis/AnalysisDeclContext.cpp b/lib/Analysis/AnalysisDeclContext.cpp
index 181edff0a03f..486fffbe1299 100644
--- a/lib/Analysis/AnalysisDeclContext.cpp
+++ b/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,9 +146,9 @@ 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();
@@ -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,7 +189,7 @@ 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 =
forcedBlkExprs->find(stmt);
@@ -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,7 +343,7 @@ 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();
@@ -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);
@@ -533,15 +567,16 @@ public:
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/lib/Analysis/BodyFarm.cpp b/lib/Analysis/BodyFarm.cpp
index 89ca8484819d..b9fb15b2db25 100644
--- a/lib/Analysis/BodyFarm.cpp
+++ b/lib/Analysis/BodyFarm.cpp
@@ -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)
@@ -341,9 +345,9 @@ static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) {
auto *FlagRecordDecl = dyn_cast_or_null<RecordDecl>(FlagType->getAsTagDecl());
if (!FlagRecordDecl) {
- DEBUG(llvm::dbgs() << "Flag field is not a record: "
- << "unknown std::call_once implementation, "
- << "ignoring the call.\n");
+ 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(
@@ -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(
@@ -813,4 +830,3 @@ Stmt *BodyFarm::getBody(const ObjCMethodDecl *D) {
return Val.getValue();
}
-
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp
index 714b85d3a9ff..8a3ab15458dd 100644
--- a/lib/Analysis/CFG.cpp
+++ b/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"
@@ -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,6 +274,7 @@ public:
int distance(const_iterator L);
const_iterator shared_parent(const_iterator L);
+ bool pointsToFirstDeclaredVar() { return VarIter == 1; }
};
private:
@@ -472,6 +481,15 @@ 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;
@@ -491,7 +509,8 @@ 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);
@@ -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);
@@ -566,6 +587,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 +670,24 @@ 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);
+
+ // 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 +705,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);
@@ -682,6 +732,45 @@ private:
B->appendStmt(const_cast<Stmt*>(S), cfg->getBumpVectorContext());
}
+ void appendConstructor(CFGBlock *B, CXXConstructExpr *CE) {
+ if (BuildOpts.AddRichCXXConstructors) {
+ if (const ConstructionContextLayer *Layer =
+ ConstructionContextMap.lookup(CE)) {
+ cleanupConstructionContext(CE);
+ if (const auto *CC = ConstructionContext::createFromLayers(
+ cfg->getBumpVectorContext(), Layer)) {
+ 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 (BuildOpts.AddRichCXXConstructors) {
+ if (CFGCXXRecordTypedCall::isCXXRecordTypedCall(CE, *Context)) {
+ if (const ConstructionContextLayer *Layer =
+ ConstructionContextMap.lookup(CE)) {
+ cleanupConstructionContext(CE);
+ if (const auto *CC = ConstructionContext::createFromLayers(
+ cfg->getBumpVectorContext(), Layer)) {
+ 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());
}
@@ -725,6 +814,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 +831,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 +964,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)
@@ -1006,7 +1120,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()) {
@@ -1116,6 +1230,127 @@ static const VariableArrayType *FindVA(const Type *t) {
return nullptr;
}
+void CFGBuilder::consumeConstructionContext(
+ const ConstructionContextLayer *Layer, Expr *E) {
+ 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](Stmt *S) {
+ return ConstructionContextLayer::create(cfg->getBumpVectorContext(), S,
+ 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: {
+ auto *CE = cast<CallExpr>(Child);
+ if (CFGCXXRecordTypedCall::isCXXRecordTypedCall(CE, *Context))
+ consumeConstructionContext(Layer, CE);
+ 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 (const auto *CE =
+ dyn_cast_or_null<CXXConstructExpr>(Layer->getTriggerStmt())) {
+ if (CE->isElidable()) {
+ auto *MTE = cast<MaterializeTemporaryExpr>(Child);
+ findConstructionContexts(withExtraLayer(MTE), MTE->GetTemporaryExpr());
+ }
+ }
+ break;
+ }
+ case Stmt::ConditionalOperatorClass: {
+ auto *CO = cast<ConditionalOperator>(Child);
+ if (!dyn_cast_or_null<MaterializeTemporaryExpr>(Layer->getTriggerStmt())) {
+ // 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 +1411,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);
}
@@ -1196,6 +1434,10 @@ std::unique_ptr<CFG> CFGBuilder::buildCFG(const Decl *D, Stmt *Statement) {
// 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 +1485,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 +1513,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 +1535,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 +1561,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 +1640,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 +1680,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 +1703,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);
}
}
@@ -1478,7 +1768,8 @@ LocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope* Scope) {
/// addLocalScopeForStmt - Add LocalScope to local scopes tree for statement
/// 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 +1794,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 +1807,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 +1817,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 +1851,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 +1865,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 +1925,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 +2073,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);
@@ -2045,7 +2366,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 +2383,13 @@ CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) {
if (!boundType.isNull()) calleeType = boundType;
}
+ // FIXME: Once actually implemented, this construction context layer should
+ // include the number of the argument as well.
+ for (auto Arg: C->arguments()) {
+ findConstructionContexts(
+ ConstructionContextLayer::create(cfg->getBumpVectorContext(), C), Arg);
+ }
+
// If this is a call to a no-return function, this stops the block here.
bool NoReturn = getFunctionExtInfo(*calleeType).getNoReturn();
@@ -2078,7 +2406,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 +2426,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 +2443,7 @@ CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) {
else
Block = createBlock();
- appendStmt(Block, C);
+ appendCall(Block, C);
if (AddEHEdge) {
// Add exceptional edges.
@@ -2326,7 +2657,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 +2688,8 @@ CFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt *DS) {
LastBlock = newBlock;
}
+ maybeAddScopeBeginForVarDecl(Block, VD, DS);
+
// Remove variable from local scope.
if (ScopePos && VD == *ScopePos)
++ScopePos;
@@ -2517,6 +2854,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())
@@ -2813,6 +3154,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 +3185,16 @@ 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(),
+ const_cast<DeclStmt *>(DS)),
+ Init);
+ appendStmt(Block, DS);
EntryConditionBlock = addStmt(Init);
assert(Block == EntryConditionBlock);
+ maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD, C);
}
}
@@ -2872,6 +3221,8 @@ CFGBlock *CFGBuilder::VisitForStmt(ForStmt *F) {
// 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 +3234,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();
@@ -3155,9 +3516,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);
}
}
@@ -3483,6 +3851,7 @@ CFGBlock *CFGBuilder::VisitSwitchStmt(SwitchStmt *Terminator) {
autoCreateBlock();
appendStmt(Block, Terminator->getConditionVariableDeclStmt());
LastBlock = addStmt(Init);
+ maybeAddScopeBeginForVarDecl(LastBlock, VD, Init);
}
}
@@ -3863,6 +4232,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);
}
@@ -3872,7 +4245,7 @@ CFGBlock *CFGBuilder::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E,
CFGBlock *CFGBuilder::VisitCXXConstructExpr(CXXConstructExpr *C,
AddStmtChoice asc) {
autoCreateBlock();
- appendStmt(Block, C);
+ appendConstructor(Block, C);
return VisitChildren(C);
}
@@ -3882,15 +4255,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 +4306,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 +4408,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 +4593,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 +4614,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);
}
}
@@ -4343,8 +4730,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 +4931,95 @@ 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());
+ break;
+ }
+ 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;
+ }
+ }
+ 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 +5049,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 +5076,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 +5100,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())
diff --git a/lib/Analysis/CFGReachabilityAnalysis.cpp b/lib/Analysis/CFGReachabilityAnalysis.cpp
index 4ae135f1ea77..6f557e092fd7 100644
--- a/lib/Analysis/CFGReachabilityAnalysis.cpp
+++ b/lib/Analysis/CFGReachabilityAnalysis.cpp
@@ -1,4 +1,4 @@
-//==- CFGReachabilityAnalysis.cpp - Basic reachability analysis --*- C++ -*-==//
+//===- CFGReachabilityAnalysis.cpp - Basic reachability analysis ----------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,18 +13,19 @@
//
//===----------------------------------------------------------------------===//
-#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
diff --git a/lib/Analysis/CMakeLists.txt b/lib/Analysis/CMakeLists.txt
index fdc9e6cee8e1..432067d98157 100644
--- a/lib/Analysis/CMakeLists.txt
+++ b/lib/Analysis/CMakeLists.txt
@@ -11,6 +11,7 @@ add_clang_library(clangAnalysis
CallGraph.cpp
CloneDetection.cpp
CocoaConventions.cpp
+ ConstructionContext.cpp
Consumed.cpp
CodeInjector.cpp
Dominators.cpp
diff --git a/lib/Analysis/CloneDetection.cpp b/lib/Analysis/CloneDetection.cpp
index 098803f9a417..8912b3b76751 100644
--- a/lib/Analysis/CloneDetection.cpp
+++ b/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/lib/Analysis/ConstructionContext.cpp b/lib/Analysis/ConstructionContext.cpp
new file mode 100644
index 000000000000..ed1e63243217
--- /dev/null
+++ b/lib/Analysis/ConstructionContext.cpp
@@ -0,0 +1,184 @@
+//===- 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"
+
+using namespace clang;
+
+const ConstructionContextLayer *
+ConstructionContextLayer::create(BumpVectorContext &C, TriggerTy Trigger,
+ const ConstructionContextLayer *Parent) {
+ ConstructionContextLayer *CC =
+ C.getAllocator().Allocate<ConstructionContextLayer>();
+ return new (CC) ConstructionContextLayer(Trigger, Parent);
+}
+
+bool ConstructionContextLayer::isStrictlyMoreSpecificThan(
+ const ConstructionContextLayer *Other) const {
+ const ConstructionContextLayer *Self = this;
+ while (true) {
+ if (!Other)
+ return Self;
+ if (!Self || !Self->isSameLayer(Other))
+ return false;
+ Self = Self->getParent();
+ Other = Other->getParent();
+ }
+ llvm_unreachable("The above loop can only be terminated via return!");
+}
+
+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.
+ if (const Stmt *S = TopLayer->getTriggerStmt()) {
+ if (const auto *DS = dyn_cast<DeclStmt>(S)) {
+ assert(TopLayer->isLast());
+ return create<SimpleVariableConstructionContext>(C, DS);
+ }
+ if (const auto *NE = dyn_cast<CXXNewExpr>(S)) {
+ assert(TopLayer->isLast());
+ return create<NewAllocatedObjectConstructionContext>(C, NE);
+ }
+ if (const auto *BTE = dyn_cast<CXXBindTemporaryExpr>(S)) {
+ const MaterializeTemporaryExpr *MTE = nullptr;
+ assert(BTE->getType().getCanonicalType()
+ ->getAsCXXRecordDecl()->hasNonTrivialDestructor());
+ // For temporaries with destructors, there may or may not be
+ // lifetime extension on the parent layer.
+ if (const ConstructionContextLayer *ParentLayer = TopLayer->getParent()) {
+ // C++17 *requires* elision of the constructor at the return site
+ // and at variable/member initialization site, while previous standards
+ // were allowing an optional elidable constructor.
+ // This is the C++17 copy-elided construction into a ctor initializer.
+ if (const CXXCtorInitializer *I = ParentLayer->getTriggerInit()) {
+ return create<
+ CXX17ElidedCopyConstructorInitializerConstructionContext>(C,
+ I, BTE);
+ }
+ assert(ParentLayer->getTriggerStmt() &&
+ "Non-statement-based layers have been handled above!");
+ // This is the normal, non-C++17 case: a temporary object which has
+ // both destruction and materialization info attached to it in the AST.
+ if ((MTE = dyn_cast<MaterializeTemporaryExpr>(
+ ParentLayer->getTriggerStmt()))) {
+ if (MTE->getStorageDuration() != SD_FullExpression) {
+ // If the temporary is lifetime-extended, don't save the BTE,
+ // because we don't need a temporary destructor, but an automatic
+ // destructor.
+ BTE = nullptr;
+ }
+
+ // Handle pre-C++17 copy and move elision.
+ const CXXConstructExpr *ElidedCE = nullptr;
+ const ConstructionContext *ElidedCC = nullptr;
+ if (const ConstructionContextLayer *ElidedLayer =
+ ParentLayer->getParent()) {
+ ElidedCE = cast<CXXConstructExpr>(ElidedLayer->getTriggerStmt());
+ 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, ElidedLayer->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);
+ } else {
+ return create<ElidedTemporaryObjectConstructionContext>(
+ C, BTE, MTE, ElidedCE, ElidedCC);
+ }
+ }
+ assert(ParentLayer->isLast());
+ return create<SimpleTemporaryObjectConstructionContext>(C, BTE, MTE);
+ }
+ assert(ParentLayer->isLast());
+
+ // This is a constructor into a function argument. Not implemented yet.
+ if (isa<CallExpr>(ParentLayer->getTriggerStmt()))
+ return nullptr;
+ // This is C++17 copy-elided construction into return statement.
+ if (auto *RS = dyn_cast<ReturnStmt>(ParentLayer->getTriggerStmt())) {
+ assert(!RS->getRetValue()->getType().getCanonicalType()
+ ->getAsCXXRecordDecl()->hasTrivialDestructor());
+ return create<CXX17ElidedCopyReturnedValueConstructionContext>(C,
+ RS, BTE);
+ }
+ // This is C++17 copy-elided construction into a simple variable.
+ if (auto *DS = dyn_cast<DeclStmt>(ParentLayer->getTriggerStmt())) {
+ assert(!cast<VarDecl>(DS->getSingleDecl())->getType()
+ .getCanonicalType()->getAsCXXRecordDecl()
+ ->hasTrivialDestructor());
+ return create<CXX17ElidedCopyVariableConstructionContext>(C, DS, BTE);
+ }
+ llvm_unreachable("Unexpected construction context with destructor!");
+ }
+ // 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);
+ }
+ if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(S)) {
+ // If the object requires destruction and is not lifetime-extended,
+ // then it must have a BTE within its MTE.
+ // FIXME: This should be an assertion.
+ if (!(MTE->getType().getCanonicalType()
+ ->getAsCXXRecordDecl()->hasTrivialDestructor() ||
+ MTE->getStorageDuration() != SD_FullExpression))
+ return nullptr;
+
+ // Handle pre-C++17 copy and move elision.
+ const CXXConstructExpr *ElidedCE = nullptr;
+ const ConstructionContext *ElidedCC = nullptr;
+ if (const ConstructionContextLayer *ElidedLayer = TopLayer->getParent()) {
+ ElidedCE = cast<CXXConstructExpr>(ElidedLayer->getTriggerStmt());
+ 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, ElidedLayer->getParent());
+ if (!ElidedCC) {
+ // We may fail to create the elided construction context.
+ // In this case, skip copy elision entirely.
+ return create<SimpleTemporaryObjectConstructionContext>(C, nullptr,
+ MTE);
+ }
+ return create<ElidedTemporaryObjectConstructionContext>(
+ C, nullptr, MTE, ElidedCE, ElidedCC);
+ }
+ assert(TopLayer->isLast());
+ return create<SimpleTemporaryObjectConstructionContext>(C, nullptr, MTE);
+ }
+ if (const auto *RS = dyn_cast<ReturnStmt>(S)) {
+ assert(TopLayer->isLast());
+ return create<SimpleReturnedValueConstructionContext>(C, RS);
+ }
+ // This is a constructor into a function argument. Not implemented yet.
+ if (isa<CallExpr>(TopLayer->getTriggerStmt()))
+ return nullptr;
+ llvm_unreachable("Unexpected construction context with statement!");
+ } else if (const CXXCtorInitializer *I = TopLayer->getTriggerInit()) {
+ assert(TopLayer->isLast());
+ return create<SimpleConstructorInitializerConstructionContext>(C, I);
+ }
+ llvm_unreachable("Unexpected construction context!");
+}
diff --git a/lib/Analysis/Consumed.cpp b/lib/Analysis/Consumed.cpp
index 96edad0c3019..a46386e2d13d 100644
--- a/lib/Analysis/Consumed.cpp
+++ b/lib/Analysis/Consumed.cpp
@@ -1,4 +1,4 @@
-//===- Consumed.cpp --------------------------------------------*- C++ --*-===//
+//===- Consumed.cpp -------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,21 +13,29 @@
//===----------------------------------------------------------------------===//
#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.
@@ -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;
@@ -134,7 +141,6 @@ static bool isCallableInState(const CallableWhenAttr *CWAttr,
return false;
}
-
static bool isConsumableType(const QualType &QT) {
if (QT->isPointerType() || QT->isReferenceType())
return false;
@@ -161,7 +167,6 @@ static bool isSetOnReadPtrType(const QualType &QT) {
return false;
}
-
static bool isKnownState(ConsumedState State) {
switch (State) {
case CS_Unconsumed:
@@ -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;
@@ -310,22 +317,19 @@ class PropagationInfo {
};
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;
@@ -335,8 +339,7 @@ public:
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;
@@ -346,38 +349,37 @@ public:
}
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) {}
+ : InfoType(IT_Tmp), Tmp(Tmp) {}
- const ConsumedState & getState() const {
+ 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;
}
@@ -405,12 +407,12 @@ public:
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;
@@ -433,15 +435,17 @@ public:
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())
@@ -450,12 +454,14 @@ setStateForVarOrTmp(ConsumedStateMap *StateMap, const PropagationInfo &PInfo,
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;
@@ -463,17 +469,19 @@ class ConsumedStmtVisitor : public ConstStmtVisitor<ConsumedStmtVisitor> {
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));
}
@@ -517,7 +525,7 @@ public:
if (Entry != PropagationMap.end())
return Entry->second;
else
- return PropagationInfo();
+ return {};
}
void reset(ConsumedStateMap *NewStateMap) {
@@ -525,6 +533,8 @@ public:
}
};
+} // 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();
@@ -699,7 +701,6 @@ void ConsumedStmtVisitor::propagateReturnType(const Expr *Call,
}
}
-
void ConsumedStmtVisitor::VisitBinaryOperator(const BinaryOperator *BinOp) {
switch (BinOp->getOpcode()) {
case BO_LAnd:
@@ -711,7 +712,6 @@ void ConsumedStmtVisitor::VisitBinaryOperator(const BinaryOperator *BinOp) {
if (LEntry != PropagationMap.end() && LEntry->second.isVarTest()) {
LTest = LEntry->second.getVarTest();
-
} else {
LTest.Var = nullptr;
LTest.TestsFor = CS_None;
@@ -719,7 +719,6 @@ void ConsumedStmtVisitor::VisitBinaryOperator(const BinaryOperator *BinOp) {
if (REntry != PropagationMap.end() && REntry->second.isVarTest()) {
RTest = REntry->second.getVarTest();
-
} else {
RTest.Var = nullptr;
RTest.TestsFor = CS_None;
@@ -728,7 +727,6 @@ 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;
}
@@ -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,7 +834,7 @@ 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)));
}
@@ -851,13 +845,12 @@ void ConsumedStmtVisitor::VisitDeclStmt(const DeclStmt *DeclS) {
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,7 +858,6 @@ 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;
@@ -943,10 +935,6 @@ 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,
@@ -956,10 +944,8 @@ static void splitVarStateForIf(const IfStmt *IfNode, const VarTestResult &Test,
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();
}
@@ -978,28 +964,22 @@ static void splitVarStateForIfBinOp(const PropagationInfo &PInfo,
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
@@ -1014,7 +994,6 @@ static void splitVarStateForIfBinOp(const PropagationInfo &PInfo,
ThenStates->setState(RTest.Var, RTest.TestsFor);
else if (RState == invertConsumedUnconsumed(RTest.TestsFor))
ThenStates->markUnreachable();
-
} else {
if (RState == CS_Unknown)
ElseStates->setState(RTest.Var,
@@ -1027,7 +1006,6 @@ 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");
@@ -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()];
@@ -1119,7 +1095,7 @@ void ConsumedStateMap::checkParamsForReturnTypestate(SourceLocation BlameLoc,
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)
@@ -1226,7 +1202,7 @@ bool ConsumedStateMap::operator!=(const ConsumedStateMap *Other) const {
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,14 +1232,12 @@ 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);
@@ -1275,19 +1249,15 @@ bool ConsumedAnalyzer::splitState(const CFGBlock *CurrBlock,
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()))) {
@@ -1295,7 +1265,6 @@ bool ConsumedAnalyzer::splitState(const CFGBlock *CurrBlock,
if (!PInfo.isVarTest())
return false;
-
} else {
return false;
}
@@ -1320,7 +1289,6 @@ bool ConsumedAnalyzer::splitState(const CFGBlock *CurrBlock,
else if (VarState == Test.TestsFor)
FalseStates->markUnreachable();
}
-
} else {
return false;
}
@@ -1339,7 +1307,7 @@ 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;
@@ -1368,7 +1336,6 @@ void ConsumedAnalyzer::run(AnalysisDeclContext &AC) {
if (!CurrStates) {
continue;
-
} else if (!CurrStates->isReachable()) {
CurrStates = nullptr;
continue;
@@ -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)) {
@@ -1452,4 +1418,3 @@ void ConsumedAnalyzer::run(AnalysisDeclContext &AC) {
WarningsHandler.emitDiagnostics();
}
-}} // end namespace clang::consumed
diff --git a/lib/Analysis/Dominators.cpp b/lib/Analysis/Dominators.cpp
index 0e02c6d7174a..1b7dd8c804e1 100644
--- a/lib/Analysis/Dominators.cpp
+++ b/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/lib/Analysis/LiveVariables.cpp b/lib/Analysis/LiveVariables.cpp
index 4752c2b020ae..b8ea1e960095 100644
--- a/lib/Analysis/LiveVariables.cpp
+++ b/lib/Analysis/LiveVariables.cpp
@@ -77,6 +77,7 @@ 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;
@@ -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);
}
@@ -145,14 +153,19 @@ LiveVariablesImpl::merge(LiveVariables::LivenessValues valsA,
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 {
@@ -322,6 +335,11 @@ 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)
@@ -329,21 +347,25 @@ void TransferFunctions::VisitBinaryOperator(BinaryOperator *B) {
// 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) {
@@ -422,12 +454,14 @@ void TransferFunctions::VisitUnaryOperator(UnaryOperator *UO) {
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
@@ -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;
}
@@ -563,7 +597,7 @@ void LiveVariablesImpl::dumpBlockLiveness(const SourceManager &M) {
it != ei; ++it) {
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();
});
@@ -583,7 +617,8 @@ void LiveVariablesImpl::dumpBlockLiveness(const SourceManager &M) {
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();
});
diff --git a/lib/Analysis/PostOrderCFGView.cpp b/lib/Analysis/PostOrderCFGView.cpp
index 5a3c8182a140..124424bf2567 100644
--- a/lib/Analysis/PostOrderCFGView.cpp
+++ b/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,10 +12,12 @@
//===----------------------------------------------------------------------===//
#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());
@@ -46,4 +48,3 @@ bool PostOrderCFGView::BlockOrderCompare::operator()(const CFGBlock *b1,
unsigned b2V = (b2It == POV.BlockOrder.end()) ? 0 : b2It->second;
return b1V > b2V;
}
-
diff --git a/lib/Analysis/PrintfFormatString.cpp b/lib/Analysis/PrintfFormatString.cpp
index dfaed26564e6..00591ab2b048 100644
--- a/lib/Analysis/PrintfFormatString.cpp
+++ b/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");
}
}
@@ -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/lib/Analysis/ReachableCode.cpp b/lib/Analysis/ReachableCode.cpp
index 7e72795a47f6..f644d503dc49 100644
--- a/lib/Analysis/ReachableCode.cpp
+++ b/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
@@ -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)) {
@@ -693,7 +710,7 @@ void FindUnreachableCode(AnalysisDeclContext &AC, Preprocessor &PP,
if (reachable[block->getBlockID()])
continue;
- DeadCodeScan DS(reachable, PP);
+ DeadCodeScan DS(reachable, PP, AC.getASTContext());
numReachable += DS.scanBackwards(block, CB);
if (numReachable == cfg->getNumBlockIDs())
diff --git a/lib/Analysis/ThreadSafety.cpp b/lib/Analysis/ThreadSafety.cpp
index 6a9c9a04c55d..03cc234dce5c 100644
--- a/lib/Analysis/ThreadSafety.cpp
+++ b/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/lib/Analysis/ThreadSafetyCommon.cpp b/lib/Analysis/ThreadSafetyCommon.cpp
index 99284f07b45b..fced17ff9197 100644
--- a/lib/Analysis/ThreadSafetyCommon.cpp
+++ b/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/lib/Analysis/ThreadSafetyTIL.cpp b/lib/Analysis/ThreadSafetyTIL.cpp
index cd7cdc69ab73..798bbfb29d7b 100644
--- a/lib/Analysis/ThreadSafetyTIL.cpp
+++ b/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/lib/Analysis/UninitializedValues.cpp b/lib/Analysis/UninitializedValues.cpp
index 5f11d8a2a36b..63353292349b 100644
--- a/lib/Analysis/UninitializedValues.cpp
+++ b/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,10 +56,12 @@ 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);
@@ -62,7 +72,8 @@ public:
/// 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);
+
ValueVector &getValueVector(const CFGBlock *block) {
return vals[block->getBlockID()];
}
@@ -138,7 +152,8 @@ public:
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);
@@ -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;
}
@@ -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/lib/Basic/Builtins.cpp b/lib/Basic/Builtins.cpp
index ed7f87c9b95c..a3210ba09068 100644
--- a/lib/Basic/Builtins.cpp
+++ b/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/lib/Basic/CMakeLists.txt b/lib/Basic/CMakeLists.txt
index d0c9b902f67e..e82f451dea17 100644
--- a/lib/Basic/CMakeLists.txt
+++ b/lib/Basic/CMakeLists.txt
@@ -83,6 +83,7 @@ add_clang_library(clangBasic
Targets/OSTargets.cpp
Targets/PNaCl.cpp
Targets/PPC.cpp
+ Targets/RISCV.cpp
Targets/SPIR.cpp
Targets/Sparc.cpp
Targets/SystemZ.cpp
@@ -92,9 +93,9 @@ add_clang_library(clangBasic
Targets/XCore.cpp
TokenKinds.cpp
Version.cpp
- VersionTuple.cpp
VirtualFileSystem.cpp
Warnings.cpp
+ XRayInstr.cpp
XRayLists.cpp
${version_inc}
)
diff --git a/lib/Basic/Cuda.cpp b/lib/Basic/Cuda.cpp
index 58b99a3b58cb..dc7e61c02b24 100644
--- a/lib/Basic/Cuda.cpp
+++ b/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/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp
index 26baa838f8c6..519e835e32a2 100644
--- a/lib/Basic/Diagnostic.cpp
+++ b/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();
}
@@ -121,7 +122,7 @@ void DiagnosticsEngine::Reset() {
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) {
@@ -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.
@@ -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,6 +1055,7 @@ 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
@@ -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,
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/lib/Basic/DiagnosticIDs.cpp b/lib/Basic/DiagnosticIDs.cpp
index c4c425d9eb1d..697de68a5afb 100644
--- a/lib/Basic/DiagnosticIDs.cpp
+++ b/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())
diff --git a/lib/Basic/DiagnosticOptions.cpp b/lib/Basic/DiagnosticOptions.cpp
index 93c2196ca979..ebd9bb45f380 100644
--- a/lib/Basic/DiagnosticOptions.cpp
+++ b/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/lib/Basic/FileManager.cpp b/lib/Basic/FileManager.cpp
index a3e226d6cc96..7e2d01c4981d 100644
--- a/lib/Basic/FileManager.cpp
+++ b/lib/Basic/FileManager.cpp
@@ -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;
@@ -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,
@@ -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/lib/Basic/FileSystemStatCache.cpp b/lib/Basic/FileSystemStatCache.cpp
index 799df1d3c3a6..ebee32670e0a 100644
--- a/lib/Basic/FileSystemStatCache.cpp
+++ b/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) {
diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp
index 2bed531ae3d7..2fef481ae2c5 100644
--- a/lib/Basic/IdentifierTable.cpp
+++ b/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))
@@ -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.
@@ -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/lib/Basic/LangOptions.cpp b/lib/Basic/LangOptions.cpp
index db81507aa209..763ba33683bc 100644
--- a/lib/Basic/LangOptions.cpp
+++ b/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/lib/Basic/Module.cpp b/lib/Basic/Module.cpp
index 7124184865c6..2714b98120c0 100644
--- a/lib/Basic/Module.cpp
+++ b/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,6 +55,8 @@ 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();
@@ -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) {
diff --git a/lib/Basic/ObjCRuntime.cpp b/lib/Basic/ObjCRuntime.cpp
index 133c66945dde..8fa0afbe03f2 100644
--- a/lib/Basic/ObjCRuntime.cpp
+++ b/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;
diff --git a/lib/Basic/OpenMPKinds.cpp b/lib/Basic/OpenMPKinds.cpp
index 09c919e2b072..67b7d91e6292 100644
--- a/lib/Basic/OpenMPKinds.cpp
+++ b/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/lib/Basic/OperatorPrecedence.cpp b/lib/Basic/OperatorPrecedence.cpp
index 3743b6ad5fef..bf805fc7deb1 100644
--- a/lib/Basic/OperatorPrecedence.cpp
+++ b/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/lib/Basic/Sanitizers.cpp b/lib/Basic/Sanitizers.cpp
index 91b6b2dc74eb..8faf17b8f22e 100644
--- a/lib/Basic/Sanitizers.cpp
+++ b/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/lib/Basic/SourceLocation.cpp b/lib/Basic/SourceLocation.cpp
index 89ddbc946a49..fef1f44fc8a5 100644
--- a/lib/Basic/SourceLocation.cpp
+++ b/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;
//===----------------------------------------------------------------------===//
@@ -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/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp
index 0a51985614c8..ae76817826e1 100644
--- a/lib/Basic/SourceManager.cpp
+++ b/lib/Basic/SourceManager.cpp
@@ -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")
@@ -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,
@@ -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.
@@ -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;
}
@@ -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.
@@ -1698,7 +1719,7 @@ FileID SourceManager::translateFile(const FileEntry *SourceFile) const {
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.
@@ -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,
@@ -2237,3 +2258,29 @@ size_t SourceManager::getDataStructureSizes() const {
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/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp
index ddd292c1b743..3400c8721f7a 100644
--- a/lib/Basic/TargetInfo.cpp
+++ b/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/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index 7deebc06c3ef..1ef2fe3b8141 100644
--- a/lib/Basic/Targets.cpp
+++ b/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/lib/Basic/Targets.h b/lib/Basic/Targets.h
index 6fc967ddabee..d450aa3f37ed 100644
--- a/lib/Basic/Targets.h
+++ b/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/lib/Basic/Targets/AArch64.cpp b/lib/Basic/Targets/AArch64.cpp
index 4d3cd121f705..3444591ac593 100644
--- a/lib/Basic/Targets/AArch64.cpp
+++ b/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();
@@ -299,7 +313,40 @@ ArrayRef<const char *> AArch64TargetInfo::getGCCRegNames() const {
}
const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = {
- {{"w31"}, "wsp"}, {{"x29"}, "fp"}, {{"x30"}, "lr"}, {{"x31"}, "sp"},
+ {{"w31"}, "wsp"},
+ {{"x31"}, "sp"},
+ // GCC rN registers are aliases of xN registers.
+ {{"r0"}, "x0"},
+ {{"r1"}, "x1"},
+ {{"r2"}, "x2"},
+ {{"r3"}, "x3"},
+ {{"r4"}, "x4"},
+ {{"r5"}, "x5"},
+ {{"r6"}, "x6"},
+ {{"r7"}, "x7"},
+ {{"r8"}, "x8"},
+ {{"r9"}, "x9"},
+ {{"r10"}, "x10"},
+ {{"r11"}, "x11"},
+ {{"r12"}, "x12"},
+ {{"r13"}, "x13"},
+ {{"r14"}, "x14"},
+ {{"r15"}, "x15"},
+ {{"r16"}, "x16"},
+ {{"r17"}, "x17"},
+ {{"r18"}, "x18"},
+ {{"r19"}, "x19"},
+ {{"r20"}, "x20"},
+ {{"r21"}, "x21"},
+ {{"r22"}, "x22"},
+ {{"r23"}, "x23"},
+ {{"r24"}, "x24"},
+ {{"r25"}, "x25"},
+ {{"r26"}, "x26"},
+ {{"r27"}, "x27"},
+ {{"r28"}, "x28"},
+ {{"r29", "x29"}, "fp"},
+ {{"r30", "x30"}, "lr"},
// The S/D/Q and W/X registers overlap, but aren't really aliases; we
// don't want to substitute one of these for a different-sized one.
};
@@ -486,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/lib/Basic/Targets/AArch64.h b/lib/Basic/Targets/AArch64.h
index 33268f0f8d99..a9df895e4dad 100644
--- a/lib/Basic/Targets/AArch64.h
+++ b/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/lib/Basic/Targets/AMDGPU.cpp b/lib/Basic/Targets/AMDGPU.cpp
index 4c510e47379f..b6b9aa2f1244 100644
--- a/lib/Basic/Targets/AMDGPU.cpp
+++ b/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/lib/Basic/Targets/AMDGPU.h b/lib/Basic/Targets/AMDGPU.h
index a4e070f1cb12..b0221031addf 100644
--- a/lib/Basic/Targets/AMDGPU.h
+++ b/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/lib/Basic/Targets/ARM.cpp b/lib/Basic/Targets/ARM.cpp
index 6fb0ab41ff5b..efed9b096d56 100644
--- a/lib/Basic/Targets/ARM.cpp
+++ b/lib/Basic/Targets/ARM.cpp
@@ -334,9 +334,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 +390,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 +431,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 +494,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 +726,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 +988,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/lib/Basic/Targets/ARM.h b/lib/Basic/Targets/ARM.h
index fb0e7e66bea3..9c72c3387f7a 100644
--- a/lib/Basic/Targets/ARM.h
+++ b/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/lib/Basic/Targets/AVR.cpp b/lib/Basic/Targets/AVR.cpp
index 3022fe33d76c..9b66449cbca6 100644
--- a/lib/Basic/Targets/AVR.cpp
+++ b/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/lib/Basic/Targets/AVR.h b/lib/Basic/Targets/AVR.h
index 3dfb84f75668..d595f48e8ef7 100644
--- a/lib/Basic/Targets/AVR.h
+++ b/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/lib/Basic/Targets/BPF.cpp b/lib/Basic/Targets/BPF.cpp
index 54e34f15532d..cf41a09d76f5 100644
--- a/lib/Basic/Targets/BPF.cpp
+++ b/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/lib/Basic/Targets/BPF.h b/lib/Basic/Targets/BPF.h
index 4dd9cbd9d221..7f97f8189145 100644
--- a/lib/Basic/Targets/BPF.h
+++ b/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/lib/Basic/Targets/Hexagon.cpp b/lib/Basic/Targets/Hexagon.cpp
index 71d4c1e0f161..0ef1f6db281e 100644
--- a/lib/Basic/Targets/Hexagon.cpp
+++ b/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/lib/Basic/Targets/Hexagon.h b/lib/Basic/Targets/Hexagon.h
index 7b0966457c4b..fb4956a9e53d 100644
--- a/lib/Basic/Targets/Hexagon.h
+++ b/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/lib/Basic/Targets/Lanai.cpp b/lib/Basic/Targets/Lanai.cpp
index 1d8314af99fb..0e8030c04e5c 100644
--- a/lib/Basic/Targets/Lanai.cpp
+++ b/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/lib/Basic/Targets/Lanai.h b/lib/Basic/Targets/Lanai.h
index 5f99c17a5344..b9e6dbe04433 100644
--- a/lib/Basic/Targets/Lanai.h
+++ b/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/lib/Basic/Targets/Mips.cpp b/lib/Basic/Targets/Mips.cpp
index a8a1bcc36361..cbd5a01c3da8 100644
--- a/lib/Basic/Targets/Mips.cpp
+++ b/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/lib/Basic/Targets/Mips.h b/lib/Basic/Targets/Mips.h
index 28900f21f86b..11e9ac914430 100644
--- a/lib/Basic/Targets/Mips.h
+++ b/lib/Basic/Targets/Mips.h
@@ -54,6 +54,7 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo {
enum DspRevEnum { NoDSP, DSP1, DSP2 } DspRev;
bool HasMSA;
bool DisableMadd4;
+ bool UseIndirectJumpHazard;
protected:
bool HasFP64;
@@ -64,13 +65,11 @@ public:
: TargetInfo(Triple), IsMips16(false), IsMicromips(false),
IsNan2008(false), IsAbs2008(false), IsSingleFloat(false),
IsNoABICalls(false), CanUseBSDABICalls(false), FloatABI(HardFloat),
- DspRev(NoDSP), HasMSA(false), DisableMadd4(false), HasFP64(false) {
+ DspRev(NoDSP), HasMSA(false), DisableMadd4(false),
+ 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";
@@ -161,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;
@@ -338,6 +338,8 @@ public:
IsAbs2008 = false;
else if (Feature == "+noabicalls")
IsNoABICalls = true;
+ else if (Feature == "+use-indirect-jump-hazard")
+ UseIndirectJumpHazard = true;
}
setDataLayout();
@@ -387,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/lib/Basic/Targets/NVPTX.cpp b/lib/Basic/Targets/NVPTX.cpp
index add3b318aeb6..fd4ee1606061 100644
--- a/lib/Basic/Targets/NVPTX.cpp
+++ b/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/lib/Basic/Targets/NVPTX.h b/lib/Basic/Targets/NVPTX.h
index a84870763f54..84d466d2f49f 100644
--- a/lib/Basic/Targets/NVPTX.h
+++ b/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/lib/Basic/Targets/Nios2.h b/lib/Basic/Targets/Nios2.h
index aa02f8f6262f..ffeb414d4778 100644
--- a/lib/Basic/Targets/Nios2.h
+++ b/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/lib/Basic/Targets/OSTargets.h b/lib/Basic/Targets/OSTargets.h
index 5af63615dc5e..d0354784acf9 100644
--- a/lib/Basic/Targets/OSTargets.h
+++ b/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/lib/Basic/Targets/PPC.cpp b/lib/Basic/Targets/PPC.cpp
index a44aa0cd96f0..b4eb3b1b97b7 100644
--- a/lib/Basic/Targets/PPC.cpp
+++ b/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/lib/Basic/Targets/PPC.h b/lib/Basic/Targets/PPC.h
index 04bef258e386..439c73a0e326 100644
--- a/lib/Basic/Targets/PPC.h
+++ b/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/lib/Basic/Targets/RISCV.cpp b/lib/Basic/Targets/RISCV.cpp
new file mode 100644
index 000000000000..7eb5e6a686a9
--- /dev/null
+++ b/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/lib/Basic/Targets/RISCV.h b/lib/Basic/Targets/RISCV.h
new file mode 100644
index 000000000000..f83aae539391
--- /dev/null
+++ b/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/lib/Basic/Targets/SPIR.h b/lib/Basic/Targets/SPIR.h
index c384d4260ca9..9815292fc276 100644
--- a/lib/Basic/Targets/SPIR.h
+++ b/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/lib/Basic/Targets/Sparc.cpp b/lib/Basic/Targets/Sparc.cpp
index 429c1ee3a23c..ee4f309363af 100644
--- a/lib/Basic/Targets/Sparc.cpp
+++ b/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/lib/Basic/Targets/Sparc.h b/lib/Basic/Targets/Sparc.h
index aacc26119dfb..af2189f21468 100644
--- a/lib/Basic/Targets/Sparc.h
+++ b/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/lib/Basic/Targets/SystemZ.cpp b/lib/Basic/Targets/SystemZ.cpp
index 98f3ae2f72b4..6f06f1fc760c 100644
--- a/lib/Basic/Targets/SystemZ.cpp
+++ b/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/lib/Basic/Targets/SystemZ.h b/lib/Basic/Targets/SystemZ.h
index 3023c1d2ea26..842316005ed9 100644
--- a/lib/Basic/Targets/SystemZ.h
+++ b/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/lib/Basic/Targets/WebAssembly.cpp b/lib/Basic/Targets/WebAssembly.cpp
index 915aad4b563b..b8a2a092aff4 100644
--- a/lib/Basic/Targets/WebAssembly.cpp
+++ b/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/lib/Basic/Targets/WebAssembly.h b/lib/Basic/Targets/WebAssembly.h
index ee0073d081e0..c04c5cb6fb3a 100644
--- a/lib/Basic/Targets/WebAssembly.h
+++ b/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/lib/Basic/Targets/X86.cpp b/lib/Basic/Targets/X86.cpp
index 3efba26a8373..7ae0696ce7e7 100644
--- a/lib/Basic/Targets/X86.cpp
+++ b/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,7 +145,7 @@ bool X86TargetInfo::initFeatureMap(
setFeatureEnabledImpl(Features, "avx512vnni", true);
setFeatureEnabledImpl(Features, "avx512vbmi2", true);
setFeatureEnabledImpl(Features, "avx512vpopcntdq", true);
- setFeatureEnabledImpl(Features, "clwb", true);
+ setFeatureEnabledImpl(Features, "rdpid", true);
LLVM_FALLTHROUGH;
case CK_Cannonlake:
setFeatureEnabledImpl(Features, "avx512ifma", true);
@@ -152,16 +158,16 @@ bool X86TargetInfo::initFeatureMap(
setFeatureEnabledImpl(Features, "avx512dq", true);
setFeatureEnabledImpl(Features, "avx512bw", true);
setFeatureEnabledImpl(Features, "avx512vl", true);
- if (Kind == CK_SkylakeServer) {
- setFeatureEnabledImpl(Features, "pku", true);
+ setFeatureEnabledImpl(Features, "pku", true);
+ if (Kind != CK_Cannonlake) // CNL inherits all SKX features, except CLWB
setFeatureEnabledImpl(Features, "clwb", true);
- }
LLVM_FALLTHROUGH;
case CK_SkylakeClient:
setFeatureEnabledImpl(Features, "xsavec", true);
setFeatureEnabledImpl(Features, "xsaves", true);
setFeatureEnabledImpl(Features, "mpx", true);
- setFeatureEnabledImpl(Features, "sgx", true);
+ 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;
@@ -176,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:
@@ -200,6 +207,7 @@ bool X86TargetInfo::initFeatureMap(
LLVM_FALLTHROUGH;
case CK_Core2:
setFeatureEnabledImpl(Features, "ssse3", true);
+ setFeatureEnabledImpl(Features, "sahf", true);
LLVM_FALLTHROUGH;
case CK_Yonah:
case CK_Prescott:
@@ -218,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);
@@ -231,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);
@@ -241,6 +261,7 @@ bool X86TargetInfo::initFeatureMap(
setFeatureEnabledImpl(Features, "ssse3", true);
setFeatureEnabledImpl(Features, "fxsr", true);
setFeatureEnabledImpl(Features, "cx16", true);
+ setFeatureEnabledImpl(Features, "sahf", true);
break;
case CK_KNM:
@@ -271,6 +292,7 @@ bool X86TargetInfo::initFeatureMap(
setFeatureEnabledImpl(Features, "xsaveopt", true);
setFeatureEnabledImpl(Features, "xsave", true);
setFeatureEnabledImpl(Features, "movbe", true);
+ setFeatureEnabledImpl(Features, "sahf", true);
break;
case CK_K6_2:
@@ -284,6 +306,7 @@ bool X86TargetInfo::initFeatureMap(
setFeatureEnabledImpl(Features, "sse4a", true);
setFeatureEnabledImpl(Features, "lzcnt", true);
setFeatureEnabledImpl(Features, "popcnt", true);
+ setFeatureEnabledImpl(Features, "sahf", true);
LLVM_FALLTHROUGH;
case CK_K8SSE3:
setFeatureEnabledImpl(Features, "sse3", true);
@@ -317,6 +340,7 @@ bool X86TargetInfo::initFeatureMap(
setFeatureEnabledImpl(Features, "prfchw", true);
setFeatureEnabledImpl(Features, "cx16", true);
setFeatureEnabledImpl(Features, "fxsr", true);
+ setFeatureEnabledImpl(Features, "sahf", true);
break;
case CK_ZNVER1:
@@ -340,6 +364,7 @@ bool X86TargetInfo::initFeatureMap(
setFeatureEnabledImpl(Features, "prfchw", true);
setFeatureEnabledImpl(Features, "rdrnd", true);
setFeatureEnabledImpl(Features, "rdseed", true);
+ setFeatureEnabledImpl(Features, "sahf", true);
setFeatureEnabledImpl(Features, "sha", true);
setFeatureEnabledImpl(Features, "sse4a", true);
setFeatureEnabledImpl(Features, "xsave", true);
@@ -374,6 +399,7 @@ bool X86TargetInfo::initFeatureMap(
setFeatureEnabledImpl(Features, "cx16", true);
setFeatureEnabledImpl(Features, "fxsr", true);
setFeatureEnabledImpl(Features, "xsave", true);
+ setFeatureEnabledImpl(Features, "sahf", true);
break;
}
if (!TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec))
@@ -412,7 +438,7 @@ void X86TargetInfo::setSSELevel(llvm::StringMap<bool> &Features,
if (Enabled) {
switch (Level) {
case AVX512F:
- Features["avx512f"] = true;
+ Features["avx512f"] = Features["fma"] = Features["f16c"] = true;
LLVM_FALLTHROUGH;
case AVX2:
Features["avx2"] = true;
@@ -626,6 +652,8 @@ void X86TargetInfo::setFeatureEnabledImpl(llvm::StringMap<bool> &Features,
} else if (Name == "fma") {
if (Enabled)
setSSELevel(Features, AVX, Enabled);
+ else
+ setSSELevel(Features, AVX512F, Enabled);
} else if (Name == "fma4") {
setXOPLevel(Features, FMA4, Enabled);
} else if (Name == "xop") {
@@ -635,6 +663,8 @@ void X86TargetInfo::setFeatureEnabledImpl(llvm::StringMap<bool> &Features,
} else if (Name == "f16c") {
if (Enabled)
setSSELevel(Features, AVX, Enabled);
+ else
+ setSSELevel(Features, AVX512F, Enabled);
} else if (Name == "sha") {
if (Enabled)
setSSELevel(Features, SSE2, Enabled);
@@ -732,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") {
@@ -758,10 +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)
@@ -882,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:
@@ -891,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.
@@ -1087,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)
@@ -1103,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) {
@@ -1182,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");
@@ -1210,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)
@@ -1220,20 +1298,27 @@ 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)
+ .Case("sahf", true)
.Case("sgx", true)
.Case("sha", true)
.Case("shstk", true)
@@ -1248,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)
@@ -1278,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)
@@ -1288,23 +1376,31 @@ 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)
+ .Case("retpoline-external-thunk", HasRetpolineExternalThunk)
.Case("rtm", HasRTM)
+ .Case("sahf", HasLAHFSAHF)
.Case("sgx", HasSGX)
.Case("sha", HasSHA)
.Case("shstk", HasSHSTK)
@@ -1318,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)
@@ -1341,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
@@ -1426,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.
@@ -1554,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!
@@ -1568,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/lib/Basic/Targets/X86.h b/lib/Basic/Targets/X86.h
index cbd6a2d24fb5..b6cb27977b69 100644
--- a/lib/Basic/Targets/X86.h
+++ b/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,13 +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;
-
- /// \brief Enumeration of all of the X86 CPUs supported by Clang.
+ bool HasRDPID = false;
+ bool HasRetpoline = false;
+ bool HasRetpolineExternalThunk = false;
+ bool HasLAHFSAHF = false;
+ 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.
@@ -111,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:
@@ -136,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;
@@ -156,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;
@@ -163,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))
@@ -252,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 {
@@ -267,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:
@@ -309,9 +350,11 @@ public:
(1 << TargetInfo::LongDouble));
// x86-32 has atomics up to 8 bytes
- // FIXME: Check that we actually have cmpxchg8b before setting
- // MaxAtomicInlineWidth. (cmpxchg8b is an i586 instruction.)
- MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
+ CPUKind Kind = getCPUKind(Opts.CPU);
+ if (Kind >= CK_i586 || Kind == CK_Generic)
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
+ else if (Kind >= CK_i486)
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32;
}
BuiltinVaListKind getBuiltinVaListKind() const override {
@@ -706,6 +749,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/lib/Basic/VersionTuple.cpp b/lib/Basic/VersionTuple.cpp
deleted file mode 100644
index 9c73fd98a174..000000000000
--- a/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/lib/Basic/VirtualFileSystem.cpp b/lib/Basic/VirtualFileSystem.cpp
index 9d44597dc3fb..bcfcbdbb9014 100644
--- a/lib/Basic/VirtualFileSystem.cpp
+++ b/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/lib/Basic/XRayInstr.cpp b/lib/Basic/XRayInstr.cpp
new file mode 100644
index 000000000000..8cc36df79468
--- /dev/null
+++ b/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/lib/Basic/XRayLists.cpp b/lib/Basic/XRayLists.cpp
index 462777d53400..ad331899d2e2 100644
--- a/lib/Basic/XRayLists.cpp
+++ b/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/lib/CodeGen/ABIInfo.h b/lib/CodeGen/ABIInfo.h
index 575506da84d4..feed3833f24a 100644
--- a/lib/CodeGen/ABIInfo.h
+++ b/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/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp
index e2349da5f0a4..415bd9626220 100644
--- a/lib/CodeGen/BackendUtil.cpp
+++ b/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/lib/CodeGen/CGAtomic.cpp b/lib/CodeGen/CGAtomic.cpp
index 6862fd811186..b34bcdc1fc38 100644
--- a/lib/CodeGen/CGAtomic.cpp
+++ b/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/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index 5f73d4cf7913..617856a7b43e 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/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;
@@ -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));
@@ -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()));
@@ -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 =
@@ -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 =
@@ -1255,14 +1226,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));
@@ -1287,6 +1258,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;
}
@@ -1479,8 +1454,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 +1488,7 @@ enum class BlockCaptureEntityKind {
CXXRecord, // Copy or destroy
ARCWeak,
ARCStrong,
+ NonTrivialCStruct,
BlockObject, // Assign or release
None
};
@@ -1548,39 +1524,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();
- // Otherwise the memcpy is fine.
- return std::make_pair(BlockCaptureEntityKind::None, Flags);
+ // 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, BlockFieldFlags());
+ }
+ }
+ llvm_unreachable("after exhaustive PrimitiveCopyKind switch");
}
/// Find the set of block captures that need to be explicitly copied or destroy.
@@ -1602,6 +1585,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 +1685,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 +1706,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 +1719,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 +1744,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 +1776,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 +1788,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 +1871,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 +1896,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();
@@ -2020,6 +2056,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 +2125,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);
@@ -2133,7 +2199,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 +2271,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;
@@ -2503,30 +2576,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 +2612,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/lib/CodeGen/CGBlocks.h b/lib/CodeGen/CGBlocks.h
index 80e255f75417..5a8e960ffcc1 100644
--- a/lib/CodeGen/CGBlocks.h
+++ b/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),
@@ -214,7 +215,8 @@ public:
/// 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
@@ -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/lib/CodeGen/CGBuilder.h b/lib/CodeGen/CGBuilder.h
index 61fe4aac3afa..d2e5eb256d3b 100644
--- a/lib/CodeGen/CGBuilder.h
+++ b/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;
@@ -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/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index ba54f8342f1b..0892e84a044c 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/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(
@@ -915,7 +1147,11 @@ EmitCheckedMixedSignMultiply(CodeGenFunction &CGF, const clang::Expr *Op1,
Overflow = CGF.Builder.CreateOr(Overflow, TruncOverflow);
}
- Result = CGF.Builder.CreateTrunc(UnsignedResult, ResTy);
+ // Negate the product if it would be negative in infinite precision.
+ Result = CGF.Builder.CreateSelect(
+ IsNegative, CGF.Builder.CreateNeg(UnsignedResult), UnsignedResult);
+
+ Result = CGF.Builder.CreateTrunc(Result, ResTy);
}
assert(Overflow && Result && "Missing overflow or result");
@@ -926,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) {
@@ -962,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:
@@ -994,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:
@@ -1154,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:
@@ -1190,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:
@@ -1300,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:
@@ -1326,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: {
@@ -1735,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.
//
@@ -2033,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
@@ -2548,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));
@@ -2639,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:
@@ -2652,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 =
@@ -2732,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:
@@ -2882,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));
@@ -2992,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 =
@@ -3063,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);
@@ -3104,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:
@@ -3175,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();
@@ -3198,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(
@@ -3246,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;
@@ -3253,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)
@@ -3378,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()) {
@@ -3389,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));
@@ -3454,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) {
@@ -3557,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),
@@ -3583,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),
@@ -3627,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),
@@ -3642,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),
@@ -3652,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),
@@ -3722,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),
@@ -3755,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),
@@ -3795,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),
@@ -3826,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),
@@ -3834,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),
@@ -3874,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),
@@ -3897,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),
@@ -4095,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
@@ -4244,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;
@@ -4310,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
@@ -4319,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:
@@ -4374,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:
@@ -4448,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);
@@ -4552,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",
@@ -4603,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);
@@ -4685,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");
@@ -4893,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) {
@@ -5135,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) {
@@ -5308,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));
@@ -5345,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:
@@ -5434,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;
@@ -5479,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;
@@ -5680,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;
@@ -5799,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;
}
@@ -6077,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);
@@ -6119,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));
@@ -6160,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())),
@@ -6167,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())),
@@ -6174,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())),
@@ -6181,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())),
@@ -6188,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())),
@@ -6240,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:
@@ -6377,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");
@@ -6534,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;
@@ -6599,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);
@@ -6651,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.
@@ -6695,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");
@@ -6724,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");
}
@@ -6797,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");
}
@@ -6805,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:
@@ -6886,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
@@ -6894,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]);
@@ -6902,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;
@@ -6912,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;
@@ -7289,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));
@@ -7653,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);
}
}
@@ -7704,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);
@@ -7751,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) {
@@ -7784,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;
@@ -7809,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) {
@@ -7834,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,
@@ -7844,11 +8641,211 @@ 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 *
+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,
@@ -7914,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)
@@ -7927,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;
@@ -8063,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());
@@ -8141,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:
@@ -8173,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:
@@ -8211,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:
@@ -8230,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: {
@@ -8246,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);
@@ -8285,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 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 EmitX86Select(*this, Ops[4], Align, Ops[3]);
+ return Builder.CreateShuffleVector(Ops[0], Ops[1],
+ makeArrayRef(Indices, NumElts),
+ "shuf");
}
case X86::BI__builtin_ia32_vperm2f128_pd256:
@@ -8335,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:
@@ -8380,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:
@@ -8411,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:
@@ -8427,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: {
@@ -8549,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);
@@ -8577,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
@@ -9195,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)};
@@ -9398,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:
@@ -10028,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));
@@ -10040,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) {
@@ -10078,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));
@@ -10092,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)),
@@ -10118,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));
@@ -10140,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
@@ -10162,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;
@@ -10231,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);
@@ -10262,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: {
@@ -10307,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/lib/CodeGen/CGCUDANV.cpp b/lib/CodeGen/CGCUDANV.cpp
index d24ef0a8a974..5fcc9e011bcb 100644
--- a/lib/CodeGen/CGCUDANV.cpp
+++ b/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/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index 5ef4dc45fba1..475f17b77d92 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/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;
}
diff --git a/lib/CodeGen/CGCXXABI.cpp b/lib/CodeGen/CGCXXABI.cpp
index a27c3e9d27e3..0611749acf17 100644
--- a/lib/CodeGen/CGCXXABI.cpp
+++ b/lib/CodeGen/CGCXXABI.cpp
@@ -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/lib/CodeGen/CGCXXABI.h b/lib/CodeGen/CGCXXABI.h
index 83426dc3a03c..65b50e14f436 100644
--- a/lib/CodeGen/CGCXXABI.h
+++ b/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/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index 38d7344572d3..f066ce168588 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/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,
@@ -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.");
@@ -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) {
@@ -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);
}
@@ -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) {
@@ -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.
@@ -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,8 +3709,8 @@ 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 =
@@ -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/lib/CodeGen/CGCall.h b/lib/CodeGen/CGCall.h
index 7e10407fc31c..8adbe76fa6c3 100644
--- a/lib/CodeGen/CGCall.h
+++ b/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; }
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index a6915071ec17..0b9311f7771c 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/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,7 +649,7 @@ 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.
@@ -671,10 +680,12 @@ 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));
EmitAggExpr(Init, Slot);
break;
}
@@ -905,15 +916,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 +1276,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 +1293,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 +1477,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 +1739,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.
///
@@ -1954,7 +1965,8 @@ void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor,
}
EmitCXXConstructorCall(ctor, Ctor_Complete, /*ForVirtualBase=*/false,
- /*Delegating=*/false, curAddr, E);
+ /*Delegating=*/false, curAddr, E,
+ AggValueSlot::DoesNotOverlap);
}
// Go to the next element.
@@ -1989,7 +2001,8 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
CXXCtorType Type,
bool ForVirtualBase,
bool Delegating, Address This,
- const CXXConstructExpr *E) {
+ const CXXConstructExpr *E,
+ AggValueSlot::Overlap_t Overlap) {
CallArgList Args;
// Push the this ptr.
@@ -2002,10 +2015,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 +2030,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());
}
static bool canEmitDelegateCallArgs(CodeGenFunction &CGF,
@@ -2049,14 +2063,15 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
bool ForVirtualBase,
bool Delegating,
Address This,
- CallArgList &Args) {
+ CallArgList &Args,
+ AggValueSlot::Overlap_t Overlap,
+ SourceLocation Loc) {
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(),
+ EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, Loc,
This.getPointer(), getContext().getRecordType(ClassDecl));
if (D->isTrivial() && D->isDefaultConstructor()) {
@@ -2071,9 +2086,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 +2141,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 +2180,8 @@ void CodeGenFunction::EmitInheritedCXXConstructorCall(
}
EmitCXXConstructorCall(D, Ctor_Base, ForVirtualBase, /*Delegating*/false,
- This, Args);
+ This, Args, AggValueSlot::MayOverlap,
+ E->getLocation());
}
void CodeGenFunction::EmitInlinedInheritingCXXConstructorCall(
@@ -2188,7 +2206,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 +2277,8 @@ 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, false, false, This, Args,
+ AggValueSlot::MayOverlap, E->getExprLoc());
}
void
@@ -2294,7 +2313,8 @@ CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor,
}
EmitCXXConstructorCall(Ctor, CtorType, /*ForVirtualBase=*/false,
- /*Delegating=*/true, This, DelegateArgs);
+ /*Delegating=*/true, This, DelegateArgs,
+ AggValueSlot::MayOverlap, Loc);
}
namespace {
@@ -2325,7 +2345,8 @@ CodeGenFunction::EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor
AggValueSlot::forAddr(ThisPtr, Qualifiers(),
AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased);
+ AggValueSlot::IsNotAliased,
+ AggValueSlot::MayOverlap);
EmitAggExpr(Ctor->init_begin()[0]->getInit(), AggSlot);
@@ -2667,7 +2688,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/lib/CodeGen/CGCleanup.cpp b/lib/CodeGen/CGCleanup.cpp
index 22055b2cb902..cfd230997ed0 100644
--- a/lib/CodeGen/CGCleanup.cpp
+++ b/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();
@@ -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);
}
@@ -624,7 +635,7 @@ 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();
}
@@ -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);
@@ -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) {
@@ -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/lib/CodeGen/CGCleanup.h b/lib/CodeGen/CGCleanup.h
index 105c5629d50c..93be3e6c1502 100644
--- a/lib/CodeGen/CGCleanup.h
+++ b/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;
@@ -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/lib/CodeGen/CGCoroutine.cpp b/lib/CodeGen/CGCoroutine.cpp
index 5842e7b3ff93..4f525c8aac85 100644
--- a/lib/CodeGen/CGCoroutine.cpp
+++ b/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/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index aeed4d658a4e..097a1e043047 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/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(),
@@ -926,9 +993,8 @@ llvm::DIType *CGDebugInfo::CreateType(const BlockPointerType *Ty,
// 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 +1009,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 +1048,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 +1177,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 +1298,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 +1307,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 +1330,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 +1466,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 +1587,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 +1601,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 +1613,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 +1688,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 +1761,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 +1806,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 +1822,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 +2162,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 +2171,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 +2195,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 +2251,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 +2273,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 +2354,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 +2382,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 +2446,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 +2519,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 +2533,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 +2556,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 +2576,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 +2595,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 +2683,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 +2721,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 +2899,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 +2930,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 +3012,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 +3042,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 +3070,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 +3083,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 +3110,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 +3245,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 +3282,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 +3324,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 +3353,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 +3466,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 +3598,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 +3623,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 +3674,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 +3707,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 +3823,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,
@@ -3725,9 +3862,10 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
blockLayout->getElementOffsetInBits(3),
tunit, tunit));
fields.push_back(createFieldType(
- "__descriptor", C.getPointerType(block.NeedsCopyDispose
- ? C.getBlockDescriptorExtendedType()
- : C.getBlockDescriptorType()),
+ "__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
@@ -3806,8 +3944,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 +3961,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 +4000,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 +4227,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 +4238,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 +4316,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/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h
index 4f7b7f2a0d9c..e632806138f0 100644
--- a/lib/CodeGen/CGDebugInfo.h
+++ b/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/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 04585a8afbb6..57b2fbadbeec 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/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/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp
index 042997831702..5e237d7e0b69 100644
--- a/lib/CodeGen/CGDeclCXX.cpp
+++ b/lib/CodeGen/CGDeclCXX.cpp
@@ -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");
@@ -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;
@@ -173,10 +175,12 @@ void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
ConstantAddress DeclAddr(DeclPtr, getContext().getDeclAlign(&D));
if (!T->isReferenceType()) {
- if (getLangOpts().OpenMP && D.hasAttr<OMPThreadPrivateDeclAttr>())
+ if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd &&
+ D.hasAttr<OMPThreadPrivateDeclAttr>()) {
(void)CGM.getOpenMPRuntime().emitThreadPrivateVarDefinition(
&D, DeclAddr, D.getAttr<OMPThreadPrivateDeclAttr>()->getLocation(),
PerformInit, this);
+ }
if (PerformInit)
EmitDeclInit(*this, D, DeclAddr);
if (CGM.isTypeConstant(D.getType(), true))
@@ -232,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);
@@ -309,7 +316,7 @@ llvm::Function *CodeGenModule::CreateGlobalInitOrDestructFunction(
Fn->setSection(Section);
}
- SetInternalFunctionAttributes(nullptr, Fn, FI);
+ SetInternalFunctionAttributes(GlobalDecl(), Fn, FI);
Fn->setCallingConv(getRuntimeCC());
@@ -328,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);
@@ -340,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;
}
@@ -376,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)
diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp
index 1ec084ff3f5b..c9820c242554 100644
--- a/lib/CodeGen/CGException.cpp
+++ b/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;
@@ -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.
@@ -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())
@@ -646,7 +652,7 @@ CodeGenFunction::getMSVCDispatchBlock(EHScopeStack::stable_iterator SI) {
return DispatchBlock;
if (EHS.getKind() == EHScope::Terminate)
- DispatchBlock = getTerminateHandler();
+ DispatchBlock = getTerminateFunclet();
else
DispatchBlock = createBasicBlock();
CGBuilderTy Builder(*this, DispatchBlock);
@@ -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);
}
@@ -1334,23 +1491,59 @@ llvm::BasicBlock *CodeGenFunction::getTerminateHandler() {
if (TerminateHandler)
return TerminateHandler;
- CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
-
// Set up the terminate handler. This block is inserted at the very
// end of the function by FinishFunction.
TerminateHandler = createBasicBlock("terminate.handler");
+ CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
Builder.SetInsertPoint(TerminateHandler);
+
llvm::Value *Exn = nullptr;
+ if (getLangOpts().CPlusPlus)
+ Exn = getExceptionFromSlot();
+ llvm::CallInst *terminateCall =
+ CGM.getCXXABI().emitTerminateForUnexpectedException(*this, Exn);
+ terminateCall->setDoesNotReturn();
+ Builder.CreateUnreachable();
+
+ // Restore the saved insertion state.
+ Builder.restoreIP(SavedIP);
+
+ return TerminateHandler;
+}
+
+llvm::BasicBlock *CodeGenFunction::getTerminateFunclet() {
+ assert(EHPersonality::get(*this).usesFuncletPads() &&
+ "use getTerminateLandingPad for non-funclet EH");
+
+ llvm::BasicBlock *&TerminateFunclet = TerminateFunclets[CurrentFuncletPad];
+ if (TerminateFunclet)
+ return TerminateFunclet;
+
+ CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
+
+ // Set up the terminate handler. This block is inserted at the very
+ // end of the function by FinishFunction.
+ TerminateFunclet = createBasicBlock("terminate.handler");
+ Builder.SetInsertPoint(TerminateFunclet);
+
+ // Create the cleanuppad using the current parent pad as its token. Use 'none'
+ // if this is a top-level terminate scope, which is the common case.
SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad(
CurrentFuncletPad);
- if (EHPersonality::get(*this).usesFuncletPads()) {
- llvm::Value *ParentPad = CurrentFuncletPad;
- if (!ParentPad)
- ParentPad = llvm::ConstantTokenNone::get(CGM.getLLVMContext());
- CurrentFuncletPad = Builder.CreateCleanupPad(ParentPad);
- } else {
- if (getLangOpts().CPlusPlus)
- Exn = getExceptionFromSlot();
+ llvm::Value *ParentPad = CurrentFuncletPad;
+ if (!ParentPad)
+ ParentPad = llvm::ConstantTokenNone::get(CGM.getLLVMContext());
+ 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, Exn);
@@ -1360,7 +1553,7 @@ llvm::BasicBlock *CodeGenFunction::getTerminateHandler() {
// Restore the saved insertion state.
Builder.restoreIP(SavedIP);
- return TerminateHandler;
+ return TerminateFunclet;
}
llvm::BasicBlock *CodeGenFunction::getEHResumeBlock(bool isCleanup) {
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index c7dc8337e19e..3097caacb31c 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/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.
}
}
@@ -1034,8 +1059,12 @@ Address CodeGenFunction::EmitPointerWithAlignment(const Expr *E,
// Derived-to-base conversions.
case CK_UncheckedDerivedToBase:
case CK_DerivedToBase: {
- Address Addr = EmitPointerWithAlignment(CE->getSubExpr(), BaseInfo,
- TBAAInfo);
+ // TODO: Support accesses to members of base classes in TBAA. For now, we
+ // conservatively pretend that the complete object is of the base class
+ // type.
+ if (TBAAInfo)
+ *TBAAInfo = CGM.getTBAAAccessInfo(E->getType());
+ Address Addr = EmitPointerWithAlignment(CE->getSubExpr(), BaseInfo);
auto Derived = CE->getSubExpr()->getType()->getPointeeCXXRecordDecl();
return GetAddressOfBaseClass(Addr, Derived,
CE->path_begin(), CE->path_end(),
@@ -1785,7 +1814,7 @@ 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>();
@@ -1807,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");
@@ -2067,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");
@@ -2206,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,
@@ -2255,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());
@@ -2263,9 +2315,11 @@ static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF,
Address Addr(V, Alignment);
// Emit reference to the private copy of the variable if it is an OpenMP
// threadprivate variable.
- if (CGF.getLangOpts().OpenMP && VD->hasAttr<OMPThreadPrivateDeclAttr>())
+ if (CGF.getLangOpts().OpenMP && !CGF.getLangOpts().OpenMPSimd &&
+ VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
return EmitThreadPrivateVarDeclLValue(CGF, VD, T, Addr, RealVarTy,
E->getExprLoc());
+ }
LValue LV = VD->getType()->isReferenceType() ?
CGF.EmitLoadOfReferenceLValue(Addr, VD->getType(),
AlignmentSource::Decl) :
@@ -2446,7 +2500,8 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
// Check for OpenMP threadprivate variables.
- if (getLangOpts().OpenMP && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
+ if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd &&
+ VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
return EmitThreadPrivateVarDeclLValue(
*this, VD, T, addr, getTypes().ConvertTypeForMem(VD->getType()),
E->getExprLoc());
@@ -2579,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 =
@@ -2678,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 {
@@ -2737,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,
@@ -2945,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 =
@@ -2953,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);
@@ -2980,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)
@@ -3018,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());
@@ -3306,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
@@ -3540,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
@@ -3808,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.
@@ -3816,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.
@@ -4160,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,
@@ -4476,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;
@@ -4486,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);
@@ -4527,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) &&
@@ -4707,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/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index 0f05cab66d7e..291740478329 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/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
@@ -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,6 +763,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
valueDest.isExternallyDestructed(),
valueDest.requiresGCollection(),
valueDest.isPotentiallyAliased(),
+ AggValueSlot::DoesNotOverlap,
AggValueSlot::IsZeroed);
}
@@ -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,7 +1135,8 @@ 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;
}
@@ -911,7 +1157,8 @@ void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) {
AggValueSlot LHSSlot =
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()))
@@ -1089,6 +1336,7 @@ AggExprEmitter::EmitInitializationToLValue(Expr *E, LValue LV) {
AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
AggValueSlot::IsNotAliased,
+ AggValueSlot::MayOverlap,
Dest.isZeroed()));
return;
case TEK_Scalar:
@@ -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 =
@@ -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,6 +1673,8 @@ 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());
@@ -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;
@@ -1537,16 +1787,42 @@ 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());
@@ -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) {
@@ -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/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp
index c32f1e5415da..8955d8a4a83c 100644
--- a/lib/CodeGen/CGExprCXX.cpp
+++ b/lib/CodeGen/CGExprCXX.cpp
@@ -242,11 +242,15 @@ 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())) {
@@ -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");
@@ -335,7 +344,8 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
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)
@@ -364,15 +374,15 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
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(
@@ -622,7 +634,7 @@ CodeGenFunction::EmitCXXConstructExpr(const CXXConstructExpr *E,
// Call the constructor.
EmitCXXConstructorCall(CD, Type, ForVirtualBase, Delegating,
- Dest.getAddress(), E);
+ Dest.getAddress(), E, Dest.mayOverlap());
}
}
@@ -924,7 +936,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 +953,8 @@ static void StoreAnyExprIntoOneUnit(CodeGenFunction &CGF, const Expr *Init,
= AggValueSlot::forAddr(NewPtr, AllocType.getQualifiers(),
AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased);
+ AggValueSlot::IsNotAliased,
+ MayOverlap);
CGF.EmitAggExpr(Init, Slot);
return;
}
@@ -1009,7 +1023,8 @@ void CodeGenFunction::EmitNewArrayInitializer(
AggValueSlot::forAddr(CurPtr, ElementType.getQualifiers(),
AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased);
+ AggValueSlot::IsNotAliased,
+ AggValueSlot::DoesNotOverlap);
EmitAggExpr(ILE->getInit(0), Slot);
// Move past these elements.
@@ -1074,7 +1089,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"),
@@ -1227,7 +1243,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 +1275,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 +1316,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 +1499,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 +1530,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,13 +1696,13 @@ 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());
EmitNewInitializer(*this, E, allocType, elementTy, result, numElements,
diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp
index 9094d3f8a91c..fb176093a741 100644
--- a/lib/CodeGen/CGExprComplex.cpp
+++ b/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/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index d1b9e13a6f93..cfd0b859233a 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -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) {
@@ -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);
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index c46215067a68..783f74c5026d 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/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.
@@ -387,6 +387,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 +425,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,
@@ -1144,7 +1148,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 +1621,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 +1775,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;
@@ -1873,7 +1914,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 +1996,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 +2014,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 +2312,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;
}
@@ -2769,7 +2805,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 +3000,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 +3278,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 +3485,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/lib/CodeGen/CGGPUBuiltin.cpp b/lib/CodeGen/CGGPUBuiltin.cpp
index 48156b1b26b7..b5375ffb8db7 100644
--- a/lib/CodeGen/CGGPUBuiltin.cpp
+++ b/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/lib/CodeGen/CGLoopInfo.h b/lib/CodeGen/CGLoopInfo.h
index 15608c105dc7..9d5f23ff9a2a 100644
--- a/lib/CodeGen/CGLoopInfo.h
+++ b/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/lib/CodeGen/CGNonTrivialStruct.cpp b/lib/CodeGen/CGNonTrivialStruct.cpp
new file mode 100644
index 000000000000..922e0934b866
--- /dev/null
+++ b/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/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp
index f26263d9472d..81c1201c0e06 100644
--- a/lib/CodeGen/CGObjC.cpp
+++ b/lib/CodeGen/CGObjC.cpp
@@ -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,
@@ -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.
@@ -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()) {
@@ -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.
@@ -1438,7 +1440,8 @@ void CodeGenFunction::GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP,
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;
@@ -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() {
@@ -3261,19 +3260,19 @@ CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction(
"__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());
@@ -3342,8 +3341,8 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction(
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);
@@ -3351,7 +3350,7 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction(
VK_RValue, SourceLocation());
UnaryOperator SRC(&SrcExpr, UO_Deref, SrcTy->getPointeeType(),
- VK_LValue, OK_Ordinary, SourceLocation());
+ VK_LValue, OK_Ordinary, SourceLocation(), false);
CXXConstructExpr *CXXConstExpr =
cast<CXXConstructExpr>(PID->getGetterCXXConstructor());
@@ -3384,7 +3383,8 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction(
Qualifiers(),
AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased));
+ AggValueSlot::IsNotAliased,
+ AggValueSlot::DoesNotOverlap));
FinishFunction();
HelperFn = llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy);
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp
index c8b8be7f4552..6a0554b46b1c 100644
--- a/lib/CodeGen/CGObjCGNU.cpp
+++ b/lib/CodeGen/CGObjCGNU.cpp
@@ -34,11 +34,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 +93,7 @@ public:
if (!Function) {
if (!FunctionName)
return nullptr;
- Function =
- cast<llvm::Constant>(CGM->CreateRuntimeFunction(FTy, FunctionName));
+ Function = CGM->CreateRuntimeFunction(FTy, FunctionName);
}
return Function;
}
@@ -114,6 +126,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
@@ -156,11 +172,29 @@ 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;
+ /// 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*.
@@ -174,39 +208,28 @@ 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);
+ 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);
@@ -222,7 +245,7 @@ protected:
/// 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 +272,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 +331,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
@@ -352,6 +416,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 +427,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 +447,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 +491,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,
+ virtual llvm::Value *GetSelector(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
@@ -476,7 +565,7 @@ protected:
public:
CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion,
- unsigned protocolClassVersion);
+ unsigned protocolClassVersion, unsigned classABI=1);
ConstantAddress GenerateConstantString(const StringLiteral *) override;
@@ -499,6 +588,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 +795,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,7 +807,7 @@ 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
@@ -784,6 +884,951 @@ 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 {
+ /// The section for selectors.
+ static constexpr const char *const SelSection = "__objc_selectors";
+ /// The section for classes.
+ static constexpr const char *const ClsSection = "__objc_classes";
+ /// The section for references to classes.
+ static constexpr const char *const ClsRefSection = "__objc_class_refs";
+ /// The section for categories.
+ static constexpr const char *const CatSection = "__objc_cats";
+ /// The section for protocols.
+ static constexpr const char *const ProtocolSection = "__objc_protocols";
+ /// The section for protocol references.
+ static constexpr const char *const ProtocolRefSection = "__objc_protocol_refs";
+ /// The section for class aliases
+ static constexpr const char *const ClassAliasSection = "__objc_class_aliases";
+ /// The section for constexpr constant strings
+ static constexpr const char *const ConstantStringSection = "__objc_constant_string";
+ /// 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(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::ExternalLinkage,
+ llvm::ConstantExpr::getBitCast(Protocol, ProtocolPtrTy), RefName);
+ GV->setSection(ProtocolRefSection);
+ 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;
+
+ // Use the protocol definition, if there is one.
+ if (const ObjCProtocolDecl *Def = PD->getDefinition())
+ PD = Def;
+
+ 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);
+
+ auto SymName = SymbolForProtocol(ProtocolName);
+ auto *OldGV = TheModule.getGlobalVariable(SymName);
+ // 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(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 *GetSelector(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->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(SelSection);
+ auto *SelVal = EnforceType(GV, SelectorTy);
+ return SelVal;
+ }
+ std::pair<llvm::Constant*,llvm::Constant*>
+ GetSectionBounds(StringRef Section) {
+ 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 };
+ }
+ 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);
+ auto addSection = [&](const char *section) {
+ auto bounds = GetSectionBounds(section);
+ InitStructBuilder.add(bounds.first);
+ InitStructBuilder.add(bounds.second);
+ };
+ addSection(SelSection);
+ addSection(ClsSection);
+ addSection(ClsRefSection);
+ addSection(CatSection);
+ addSection(ProtocolSection);
+ addSection(ProtocolRefSection);
+ addSection(ClassAliasSection);
+ addSection(ConstantStringSection);
+ 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");
+ InitVar->setSection(".ctors");
+ InitVar->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ InitVar->setComdat(TheModule.getOrInsertComdat(".objc_ctor"));
+ CGM.addCompilerUsedGlobal(InitVar);
+ for (auto *C : Categories) {
+ auto *Cat = cast<llvm::GlobalVariable>(C->stripPointerCasts());
+ Cat->setSection(CatSection);
+ CGM.addUsedGlobal(Cat);
+ }
+ // Add a null value fore each special section so that we can always
+ // guarantee that the _start and _stop symbols will exist and be
+ // meaningful.
+ 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;
+ };
+ createNullGlobal(".objc_null_selector", {NULLPtr, NULLPtr}, SelSection);
+ if (Categories.empty())
+ createNullGlobal(".objc_null_category", {NULLPtr, NULLPtr,
+ NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr}, CatSection);
+ if (!EmittedClass) {
+ createNullGlobal(".objc_null_cls_init_ref", NULLPtr, ClsSection);
+ createNullGlobal(".objc_null_class_ref", { NULLPtr, NULLPtr },
+ ClsRefSection);
+ }
+ if (!EmittedProtocol)
+ createNullGlobal(".objc_null_protocol", {NULLPtr, NULLPtr, NULLPtr,
+ NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr,
+ NULLPtr}, ProtocolSection);
+ if (!EmittedProtocolRef)
+ createNullGlobal(".objc_null_protocol_ref", {NULLPtr}, ProtocolRefSection);
+ if (!ClassAliases.empty())
+ for (auto clsAlias : ClassAliases)
+ createNullGlobal(std::string(".objc_class_alias") +
+ clsAlias.second, { MakeConstantString(clsAlias.second),
+ GetClassVar(clsAlias.first) }, ClassAliasSection);
+ else
+ createNullGlobal(".objc_null_class_alias", { NULLPtr, NULLPtr },
+ ClassAliasSection);
+ if (ConstantStrings.empty()) {
+ auto i32Zero = llvm::ConstantInt::get(Int32Ty, 0);
+ createNullGlobal(".objc_null_constant_string", { NULLPtr, i32Zero,
+ i32Zero, i32Zero, i32Zero, NULLPtr }, ConstantStringSection);
+ }
+ ConstantStrings.clear();
+ Categories.clear();
+ Classes.clear();
+ return nullptr;//CGObjCGNU::ModuleInitFunction();
+ }
+ /// 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(ClsRefSection);
+ 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(ClsSection);
+ 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 });
+ }
+
+};
+
/// Support for the ObjFW runtime.
class CGObjCObjFW: public CGObjCGNU {
protected:
@@ -878,22 +1923,12 @@ 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");
@@ -911,6 +1946,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 +1979,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 +2097,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,13 +2115,7 @@ 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;
@@ -1217,7 +2265,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 +2326,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,
@@ -1456,7 +2517,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 +2567,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 +2585,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 +2637,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;
@@ -1664,7 +2754,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 +2783,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 +2832,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,17 +2856,18 @@ 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.
@@ -1783,51 +2877,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 +2909,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 +2923,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 +2938,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 +2948,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);
@@ -2016,25 +3019,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 +3036,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());
+ 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(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());
- }
- 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);
@@ -2179,6 +3207,8 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
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 +3231,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 +3243,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 +3252,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 +3280,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 +3320,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 +3337,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 +3357,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 +3368,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 +3379,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) {
@@ -2785,8 +3807,7 @@ 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).
@@ -2895,8 +3916,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/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index ef4e6cd4f01b..0c766575dc21 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -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;
@@ -1708,7 +1708,7 @@ struct NullReturnState {
e = Method->param_end(); i != e; ++i, ++I) {
const ParmVarDecl *ParamDecl = (*i);
if (ParamDecl->hasAttr<NSConsumedAttr>()) {
- RValue RV = I->RV;
+ RValue RV = I->getRValue(CGF);
assert(RV.isScalar() &&
"NullReturnState::complete - arg not on object");
CGF.EmitARCRelease(RV.getScalarVal(), ARCImpreciseLifetime);
@@ -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
@@ -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());
}
@@ -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) {
@@ -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);
}
@@ -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");
@@ -7079,7 +7075,7 @@ CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
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 =
@@ -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/lib/CodeGen/CGOpenCLRuntime.cpp b/lib/CodeGen/CGOpenCLRuntime.cpp
index d140e7f09e9a..1da19a90c387 100644
--- a/lib/CodeGen/CGOpenCLRuntime.cpp
+++ b/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/lib/CodeGen/CGOpenCLRuntime.h b/lib/CodeGen/CGOpenCLRuntime.h
index ead303d1d0d5..a513340827a8 100644
--- a/lib/CodeGen/CGOpenCLRuntime.h
+++ b/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/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp
index fa38ee80bf41..3730b9af12fa 100644
--- a/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/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,14 +393,15 @@ 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;
FieldDecl *LambdaThisCaptureField = nullptr;
+ 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.
@@ -412,6 +414,8 @@ public:
std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
LambdaThisCaptureField = CGF.LambdaThisCaptureField;
CGF.LambdaThisCaptureField = nullptr;
+ BlockInfo = CGF.BlockInfo;
+ CGF.BlockInfo = nullptr;
}
~InlinedOpenMPRegionRAII() {
@@ -422,28 +426,29 @@ public:
CGF.CapturedStmtInfo = OldCSI;
std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
CGF.LambdaThisCaptureField = LambdaThisCaptureField;
+ CGF.BlockInfo = BlockInfo;
}
};
-/// \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,
@@ -454,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:
@@ -481,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,
@@ -508,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,
@@ -517,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.
@@ -528,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);
@@ -742,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;
}
@@ -759,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.
@@ -814,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)
@@ -825,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);
@@ -871,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());
@@ -889,6 +897,25 @@ static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr,
CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
}
+static llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy>
+isDeclareTargetDeclaration(const ValueDecl *VD) {
+ for (const Decl *D : VD->redecls()) {
+ if (!D->hasAttrs())
+ continue;
+ if (const auto *Attr = D->getAttr<OMPDeclareTargetDeclAttr>())
+ return Attr->getMapType();
+ }
+ if (const auto *V = dyn_cast<VarDecl>(VD)) {
+ if (const VarDecl *TD = V->getTemplateInstantiationPattern())
+ return isDeclareTargetDeclaration(TD);
+ } else if (const auto *FD = dyn_cast<FunctionDecl>(VD)) {
+ if (const auto *TD = FD->getTemplateInstantiationPattern())
+ return isDeclareTargetDeclaration(TD);
+ }
+
+ return llvm::None;
+}
+
LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) {
return CGF.EmitOMPSharedLValue(E);
}
@@ -906,7 +933,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());
@@ -926,7 +953,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);
@@ -942,7 +969,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);
@@ -955,7 +982,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);
@@ -981,7 +1008,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()) {
@@ -1002,9 +1029,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));
@@ -1029,7 +1057,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();
@@ -1038,7 +1066,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();
@@ -1054,9 +1082,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);
}
@@ -1097,28 +1125,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);
@@ -1140,7 +1172,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();
}
@@ -1170,12 +1203,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();
@@ -1185,12 +1244,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(),
@@ -1199,28 +1269,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();
});
@@ -1242,7 +1314,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");
@@ -1252,7 +1324,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");
@@ -1265,7 +1337,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);
@@ -1281,25 +1353,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,
@@ -1308,19 +1361,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,
@@ -1352,8 +1406,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),
@@ -1366,21 +1420,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) {
@@ -1394,17 +1496,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;
}
@@ -1422,17 +1522,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;
@@ -1440,29 +1540,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.
@@ -1490,8 +1591,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()) {
@@ -1509,7 +1610,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());
@@ -1523,17 +1624,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() {
@@ -1555,7 +1653,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;
@@ -1563,7 +1661,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;
@@ -1574,7 +1672,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;
@@ -1585,7 +1683,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;
@@ -1596,7 +1694,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;
@@ -1605,21 +1703,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;
@@ -1630,7 +1729,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;
@@ -1639,7 +1738,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;
@@ -1647,7 +1746,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;
@@ -1655,7 +1754,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;
@@ -1665,7 +1764,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;
@@ -1674,7 +1773,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;
@@ -1683,7 +1782,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;
@@ -1691,7 +1790,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;
@@ -1699,7 +1798,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;
@@ -1707,7 +1806,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;
@@ -1716,7 +1815,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;
@@ -1724,7 +1823,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;
@@ -1732,7 +1831,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;
@@ -1746,7 +1845,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;
@@ -1756,7 +1855,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;
@@ -1771,7 +1870,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;
@@ -1787,7 +1886,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;
@@ -1804,7 +1903,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;
@@ -1815,7 +1914,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;
@@ -1826,7 +1925,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");
@@ -1837,7 +1936,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");
@@ -1848,7 +1947,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");
@@ -1857,7 +1956,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;
@@ -1865,7 +1964,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;
@@ -1873,7 +1972,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;
@@ -1881,7 +1980,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;
@@ -1889,7 +1988,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;
@@ -1898,7 +1997,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;
@@ -1910,7 +2009,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");
@@ -1923,7 +2022,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;
@@ -1932,7 +2031,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;
@@ -1941,7 +2040,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;
@@ -1951,7 +2050,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;
@@ -1961,7 +2060,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;
@@ -1981,7 +2080,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;
@@ -1993,7 +2092,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;
@@ -2001,7 +2100,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;
@@ -2011,7 +2110,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;
@@ -2021,7 +2120,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;
@@ -2030,7 +2129,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");
@@ -2040,7 +2139,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");
@@ -2057,7 +2156,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;
@@ -2073,7 +2172,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;
@@ -2091,7 +2190,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;
@@ -2109,7 +2208,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;
@@ -2119,7 +2218,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;
@@ -2129,7 +2228,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;
@@ -2143,7 +2242,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;
@@ -2172,7 +2271,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;
@@ -2201,7 +2300,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;
@@ -2230,12 +2329,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
@@ -2247,7 +2346,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);
}
@@ -2256,11 +2355,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
@@ -2269,7 +2368,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);
}
@@ -2278,7 +2377,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");
@@ -2286,7 +2385,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);
}
@@ -2295,12 +2394,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
@@ -2309,18 +2408,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 =
+ 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,
@@ -2331,7 +2460,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),
@@ -2347,15 +2476,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);
}
@@ -2373,29 +2501,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(
@@ -2410,21 +2540,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,
@@ -2438,34 +2570,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;
@@ -2475,19 +2609,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 =
+ 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(
@@ -2496,13 +2767,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) {
@@ -2521,9 +2785,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.
@@ -2548,11 +2812,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
@@ -2561,13 +2825,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};
@@ -2575,13 +2839,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);
@@ -2592,9 +2855,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);
}
@@ -2613,10 +2876,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));
@@ -2629,8 +2892,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");
@@ -2644,8 +2907,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 {
@@ -2779,21 +3043,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(
@@ -2807,13 +3078,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]);
}
@@ -2833,7 +3106,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();
@@ -2846,7 +3119,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);
}
@@ -2866,7 +3140,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.
@@ -2882,14 +3156,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>
@@ -2948,19 +3222,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);
@@ -2971,7 +3245,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) {
@@ -2993,7 +3267,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
@@ -3002,19 +3276,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;
@@ -3147,12 +3422,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);
@@ -3164,10 +3439,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,
@@ -3223,7 +3498,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);
}
@@ -3285,13 +3560,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,
@@ -3311,11 +3586,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,
@@ -3325,7 +3600,7 @@ void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
"code generation.");
OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] =
OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr,
- /*Flags=*/0);
+ OMPTargetRegionEntryTargetRegion);
++OffloadingEntriesNum;
}
@@ -3333,22 +3608,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;
}
}
@@ -3376,48 +3656,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.
@@ -3425,46 +3726,49 @@ 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));
+ /*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));
+ /*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
@@ -3472,49 +3776,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);
@@ -3525,48 +3844,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() {
@@ -3579,71 +3885,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
@@ -3656,44 +4033,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;
}
}
@@ -3702,7 +4092,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(
@@ -3711,19 +4101,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{
@@ -3736,7 +4114,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));
@@ -3746,6 +4124,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;
@@ -3765,7 +4144,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);
@@ -3789,7 +4168,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));
@@ -3818,17 +4197,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());
@@ -3846,7 +4224,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;
@@ -3860,13 +4238,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);
@@ -3891,22 +4269,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) {
@@ -3924,7 +4301,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);
@@ -3933,49 +4310,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,
@@ -3987,20 +4368,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);
@@ -4011,9 +4392,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;
}
@@ -4023,7 +4403,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);
@@ -4032,30 +4412,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());
}
}
@@ -4063,7 +4447,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>
@@ -4080,7 +4464,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,
@@ -4089,67 +4473,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;
@@ -4171,9 +4557,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()) ||
@@ -4182,40 +4573,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)),
@@ -4226,8 +4615,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.
@@ -4258,8 +4646,9 @@ static void emitPrivatesInit(CodeGenFunction &CGF,
CGF.EmitExprAsInit(Init, VD, PrivateLValue,
/*capturedByInit=*/false);
}
- } else
+ } else {
CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
+ }
}
++FI;
}
@@ -4269,11 +4658,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;
}
@@ -4297,7 +4688,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,
@@ -4310,16 +4701,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),
@@ -4362,9 +4754,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;
@@ -4377,41 +4769,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).
@@ -4432,21 +4824,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());
@@ -4461,7 +4855,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);
@@ -4487,23 +4881,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 =
@@ -4519,7 +4914,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;
@@ -4539,7 +4936,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,
@@ -4582,8 +4980,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();
@@ -4603,8 +5001,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(
@@ -4613,12 +5012,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 =
@@ -4627,24 +5027,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;
@@ -4658,7 +5059,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);
@@ -4668,14 +5069,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) {
@@ -4692,7 +5093,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) {
@@ -4720,7 +5121,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
@@ -4750,9 +5151,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);
}
@@ -4768,7 +5169,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
@@ -4779,27 +5180,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);
@@ -4807,9 +5209,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);
}
@@ -4821,7 +5223,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(
@@ -4838,7 +5240,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
@@ -4860,22 +5262,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);
@@ -4896,19 +5298,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());
@@ -4923,11 +5325,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);
@@ -4939,24 +5342,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);
@@ -4974,12 +5382,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();
@@ -4989,8 +5399,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);
@@ -5000,19 +5411,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;
@@ -5029,16 +5441,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,
@@ -5088,14 +5501,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;
@@ -5108,7 +5521,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;
@@ -5136,7 +5549,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);
@@ -5144,19 +5557,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>
@@ -5167,14 +5581,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:
// ...
@@ -5182,7 +5597,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);
@@ -5192,13 +5607,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;
@@ -5222,44 +5637,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) {
@@ -5273,7 +5688,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,
@@ -5286,19 +5701,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);
@@ -5306,12 +5724,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;
@@ -5331,20 +5752,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();
}
@@ -5359,19 +5789,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>());
@@ -5381,10 +5813,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;
@@ -5395,7 +5826,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(
@@ -5427,40 +5861,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),
@@ -5468,7 +5904,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),
@@ -5500,19 +5936,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>());
@@ -5522,10 +5960,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:
@@ -5551,7 +5988,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());
@@ -5652,14 +6089,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),
@@ -5749,18 +6186,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);
@@ -5779,70 +6216,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);
}
@@ -5872,7 +6281,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);
@@ -5898,22 +6307,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;
@@ -5931,12 +6343,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.
@@ -5944,8 +6355,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);
}
@@ -5965,12 +6376,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());
@@ -6000,12 +6411,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:
@@ -6030,8 +6440,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);
}
@@ -6068,12 +6479,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());
@@ -6092,42 +6503,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
@@ -6147,21 +6566,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.
@@ -6171,10 +6629,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
@@ -6191,10 +6649,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());
}
@@ -6204,7 +6662,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);
@@ -6212,14 +6670,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:
@@ -6229,20 +6689,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;
@@ -6253,10 +6713,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)
@@ -6266,16 +6726,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
@@ -6291,7 +6751,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.
@@ -6300,10 +6760,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).
//
@@ -6326,96 +6786,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(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(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(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();
@@ -6425,16 +6930,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 =
+ 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
@@ -6442,10 +6956,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.
@@ -6453,8 +6964,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
@@ -6472,14 +7016,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 ||
@@ -6488,44 +7030,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)
@@ -6541,11 +7107,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
@@ -6554,15 +7120,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:
@@ -6573,58 +7153,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.
@@ -6636,7 +7212,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,
@@ -6644,33 +7220,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.
@@ -6686,113 +7268,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);
@@ -6800,35 +7404,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 =
+ 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);
@@ -6843,7 +7475,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 {
@@ -6851,30 +7483,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
@@ -6884,8 +7516,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();
@@ -6895,7 +7527,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;
@@ -6924,48 +7556,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));
@@ -6976,22 +7613,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),
@@ -7023,86 +7660,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
@@ -7125,13 +7703,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
@@ -7169,25 +7748,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);
}
@@ -7200,17 +7784,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
@@ -7218,14 +7905,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);
}
}
@@ -7236,13 +7923,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;
@@ -7255,66 +7942,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.
@@ -7322,12 +8061,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 !isDeclareTargetDeclaration(FD) &&
+ AlreadyEmittedTargetFunctions.count(FD->getCanonicalDecl()) == 0;
}
bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
@@ -7338,33 +8076,101 @@ 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 =
+ 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 =
+ 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);
+ 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 (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.
@@ -7384,7 +8190,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);
@@ -7396,7 +8202,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);
}
@@ -7407,16 +8213,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);
@@ -7473,7 +8279,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,
@@ -7509,7 +8315,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,
@@ -7596,9 +8402,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;
@@ -7611,6 +8414,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);
};
@@ -7644,13 +8499,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);
}
@@ -7693,11 +8548,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;
@@ -7755,17 +8610,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;
@@ -7794,90 +8650,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();
}
}
@@ -7926,8 +8787,9 @@ void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF,
addFieldToRecordDecl(C, RD, Int64Ty);
RD->completeDefinition();
KmpDimTy = C.getRecordType(RD);
- } else
+ } else {
RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl());
+ }
Address DimsAddr = CGF.CreateMemTemp(KmpDimTy, "dims");
CGF.EmitNullInitialization(DimsAddr, KmpDimTy);
@@ -7979,18 +8841,19 @@ void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
getThreadID(CGF, C->getLocStart()),
CntAddr.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)) {
@@ -8005,8 +8868,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,
@@ -8014,3 +8876,303 @@ Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF,
const VarDecl *TargetParam) const {
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) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+llvm::Value *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction(
+ const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
+ OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+llvm::Value *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction(
+ const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
+ const VarDecl *PartIDVar, const VarDecl *TaskTVar,
+ OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
+ bool Tied, unsigned &NumberOfParts) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF,
+ SourceLocation Loc,
+ llvm::Value *OutlinedFn,
+ ArrayRef<llvm::Value *> CapturedVars,
+ const Expr *IfCond) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitCriticalRegion(
+ CodeGenFunction &CGF, StringRef CriticalName,
+ const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc,
+ const Expr *Hint) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF,
+ const RegionCodeGenTy &MasterOpGen,
+ SourceLocation Loc) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
+ SourceLocation Loc) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitTaskgroupRegion(
+ CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen,
+ SourceLocation Loc) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitSingleRegion(
+ CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen,
+ SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars,
+ ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs,
+ ArrayRef<const Expr *> AssignmentOps) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF,
+ const RegionCodeGenTy &OrderedOpGen,
+ SourceLocation Loc,
+ bool IsThreads) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF,
+ SourceLocation Loc,
+ OpenMPDirectiveKind Kind,
+ bool EmitChecks,
+ bool ForceSimpleCall) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitForDispatchInit(
+ CodeGenFunction &CGF, SourceLocation Loc,
+ const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
+ bool Ordered, const DispatchRTInput &DispatchValues) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitForStaticInit(
+ CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind,
+ const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitDistributeStaticInit(
+ CodeGenFunction &CGF, SourceLocation Loc,
+ OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
+ SourceLocation Loc,
+ unsigned IVSize,
+ bool IVSigned) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF,
+ SourceLocation Loc,
+ OpenMPDirectiveKind DKind) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF,
+ SourceLocation Loc,
+ unsigned IVSize, bool IVSigned,
+ Address IL, Address LB,
+ Address UB, Address ST) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
+ llvm::Value *NumThreads,
+ SourceLocation Loc) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF,
+ OpenMPProcBindClauseKind ProcBind,
+ SourceLocation Loc) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
+ const VarDecl *VD,
+ Address VDAddr,
+ SourceLocation Loc) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition(
+ const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit,
+ CodeGenFunction *CGF) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate(
+ CodeGenFunction &CGF, QualType VarType, StringRef Name) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF,
+ ArrayRef<const Expr *> Vars,
+ SourceLocation Loc) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
+ const OMPExecutableDirective &D,
+ llvm::Value *TaskFunction,
+ QualType SharedsTy, Address Shareds,
+ const Expr *IfCond,
+ const OMPTaskDataTy &Data) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitTaskLoopCall(
+ CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D,
+ llvm::Value *TaskFunction, QualType SharedsTy, Address Shareds,
+ const Expr *IfCond, const OMPTaskDataTy &Data) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitReduction(
+ CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates,
+ ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
+ ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) {
+ assert(Options.SimpleReduction && "Only simple reduction is expected.");
+ CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs,
+ ReductionOps, Options);
+}
+
+llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit(
+ CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
+ ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
+ SourceLocation Loc,
+ ReductionCodeGen &RCG,
+ unsigned N) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF,
+ SourceLocation Loc,
+ llvm::Value *ReductionsPtr,
+ LValue SharedLVal) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
+ SourceLocation Loc) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitCancellationPointCall(
+ CodeGenFunction &CGF, SourceLocation Loc,
+ OpenMPDirectiveKind CancelRegion) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF,
+ SourceLocation Loc, const Expr *IfCond,
+ OpenMPDirectiveKind CancelRegion) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction(
+ const OMPExecutableDirective &D, StringRef ParentName,
+ llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
+ bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitTargetCall(CodeGenFunction &CGF,
+ const OMPExecutableDirective &D,
+ llvm::Value *OutlinedFn,
+ llvm::Value *OutlinedFnID,
+ const Expr *IfCond, const Expr *Device) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) {
+ return false;
+}
+
+llvm::Function *CGOpenMPSIMDRuntime::emitRegistrationFunction() {
+ return nullptr;
+}
+
+void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF,
+ const OMPExecutableDirective &D,
+ SourceLocation Loc,
+ llvm::Value *OutlinedFn,
+ ArrayRef<llvm::Value *> CapturedVars) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
+ const Expr *NumTeams,
+ const Expr *ThreadLimit,
+ SourceLocation Loc) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitTargetDataCalls(
+ CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
+ const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall(
+ CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
+ const Expr *Device) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF,
+ const OMPLoopDirective &D) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
+ const OMPDependClause *C) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+const VarDecl *
+CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD,
+ const VarDecl *NativeParam) const {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+Address
+CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF,
+ const VarDecl *NativeParam,
+ const VarDecl *TargetParam) const {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
diff --git a/lib/CodeGen/CGOpenMPRuntime.h b/lib/CodeGen/CGOpenMPRuntime.h
index 94a143841373..01ff0c20fd66 100644
--- a/lib/CodeGen/CGOpenMPRuntime.h
+++ b/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
@@ -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,582 @@ 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.
+class CGOpenMPSIMDRuntime final : public CGOpenMPRuntime {
+public:
+ explicit CGOpenMPSIMDRuntime(CodeGenModule &CGM) : CGOpenMPRuntime(CGM) {}
+ ~CGOpenMPSIMDRuntime() override {}
+
+ /// 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.
+ /// \param ThreadIDVar Variable for thread id in the current OpenMP region.
+ /// \param InnermostKind Kind of innermost directive (for simple directives it
+ /// is a directive itself, for combined - its innermost directive).
+ /// \param CodeGen Code generation sequence for the \a D directive.
+ llvm::Value *
+ emitParallelOutlinedFunction(const OMPExecutableDirective &D,
+ const VarDecl *ThreadIDVar,
+ OpenMPDirectiveKind InnermostKind,
+ const RegionCodeGenTy &CodeGen) override;
+
+ /// 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.
+ /// \param ThreadIDVar Variable for thread id in the current OpenMP region.
+ /// \param InnermostKind Kind of innermost directive (for simple directives it
+ /// is a directive itself, for combined - its innermost directive).
+ /// \param CodeGen Code generation sequence for the \a D directive.
+ llvm::Value *
+ emitTeamsOutlinedFunction(const OMPExecutableDirective &D,
+ const VarDecl *ThreadIDVar,
+ OpenMPDirectiveKind InnermostKind,
+ const RegionCodeGenTy &CodeGen) override;
+
+ /// 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.
+ /// \param ThreadIDVar Variable for thread id in the current OpenMP region.
+ /// \param PartIDVar Variable for partition id in the current OpenMP untied
+ /// task region.
+ /// \param TaskTVar Variable for task_t argument.
+ /// \param InnermostKind Kind of innermost directive (for simple directives it
+ /// is a directive itself, for combined - its innermost directive).
+ /// \param CodeGen Code generation sequence for the \a D directive.
+ /// \param Tied true if task is generated for tied task, false otherwise.
+ /// \param NumberOfParts Number of parts in untied task. Ignored for tied
+ /// tasks.
+ ///
+ llvm::Value *emitTaskOutlinedFunction(
+ const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
+ const VarDecl *PartIDVar, const VarDecl *TaskTVar,
+ OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
+ bool Tied, unsigned &NumberOfParts) override;
+
+ /// 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
+ /// 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 emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
+ llvm::Value *OutlinedFn,
+ 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;
+
+ /// 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;
+
+ /// Emits code for a taskyield directive.
+ void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc) override;
+
+ /// 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;
+
+ /// Emits a single region.
+ /// \param SingleOpGen Generator for the statement associated with the given
+ /// single region.
+ void emitSingleRegion(CodeGenFunction &CGF,
+ const RegionCodeGenTy &SingleOpGen, SourceLocation Loc,
+ ArrayRef<const Expr *> CopyprivateVars,
+ ArrayRef<const Expr *> DestExprs,
+ ArrayRef<const Expr *> SrcExprs,
+ ArrayRef<const Expr *> AssignmentOps) override;
+
+ /// 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;
+
+ /// 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.
+ /// \param ForceSimpleCall true simple barrier call must be emitted, false if
+ /// runtime class decides which one to emit (simple or with cancellation
+ /// checks).
+ ///
+ void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
+ OpenMPDirectiveKind Kind, bool EmitChecks = true,
+ bool ForceSimpleCall = false) override;
+
+ /// This is used for non static scheduled types and when the ordered
+ /// clause is present on the loop construct.
+ /// Depending on the loop schedule, it is necessary to call some runtime
+ /// routine before start of the OpenMP loop to get the loop upper / lower
+ /// bounds \a LB and \a UB and stride \a ST.
+ ///
+ /// \param CGF Reference to current CodeGenFunction.
+ /// \param Loc Clang source location.
+ /// \param ScheduleKind Schedule kind, specified by the 'schedule' clause.
+ /// \param IVSize Size of the iteration variable in bits.
+ /// \param IVSigned Sign of the iteration variable.
+ /// \param Ordered true if loop is ordered, false otherwise.
+ /// \param DispatchValues struct containing llvm values for lower bound, upper
+ /// bound, and chunk expression.
+ /// For the default (nullptr) value, the chunk 1 will be used.
+ ///
+ void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc,
+ const OpenMPScheduleTy &ScheduleKind,
+ unsigned IVSize, bool IVSigned, bool Ordered,
+ const DispatchRTInput &DispatchValues) override;
+
+ /// 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
+ /// specify a ordered clause on the loop construct.
+ /// Depending on the loop schedule, it is necessary to call some runtime
+ /// routine before start of the OpenMP loop to get the loop upper / lower
+ /// bounds LB and UB and stride ST.
+ ///
+ /// \param CGF Reference to current CodeGenFunction.
+ /// \param Loc Clang source location.
+ /// \param DKind Kind of the directive.
+ /// \param ScheduleKind Schedule kind, specified by the 'schedule' clause.
+ /// \param Values Input arguments for the construct.
+ ///
+ void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc,
+ OpenMPDirectiveKind DKind,
+ const OpenMPScheduleTy &ScheduleKind,
+ const StaticRTInput &Values) override;
+
+ ///
+ /// \param CGF Reference to current CodeGenFunction.
+ /// \param Loc Clang source location.
+ /// \param SchedKind Schedule kind, specified by the 'dist_schedule' clause.
+ /// \param Values Input arguments for the construct.
+ ///
+ void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc,
+ OpenMPDistScheduleClauseKind SchedKind,
+ const StaticRTInput &Values) override;
+
+ /// 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.
+ /// \param Loc Clang source location.
+ /// \param IVSize Size of the iteration variable in bits.
+ /// \param IVSigned Sign of the iteration variable.
+ ///
+ void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc,
+ unsigned IVSize, bool IVSigned) override;
+
+ /// Call the appropriate runtime routine to notify that we finished
+ /// all the work with current loop.
+ ///
+ /// \param CGF Reference to current CodeGenFunction.
+ /// \param Loc Clang source location.
+ /// \param DKind Kind of the directive for which the static finish is emitted.
+ ///
+ void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc,
+ OpenMPDirectiveKind DKind) override;
+
+ /// Call __kmpc_dispatch_next(
+ /// ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
+ /// kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
+ /// kmp_int[32|64] *p_stride);
+ /// \param IVSize Size of the iteration variable in bits.
+ /// \param IVSigned Sign of the iteration variable.
+ /// \param IL Address of the output variable in which the flag of the
+ /// last iteration is returned.
+ /// \param LB Address of the output variable in which the lower iteration
+ /// number is returned.
+ /// \param UB Address of the output variable in which the upper iteration
+ /// number is returned.
+ /// \param ST Address of the output variable in which the stride value is
+ /// returned.
+ llvm::Value *emitForNext(CodeGenFunction &CGF, SourceLocation Loc,
+ unsigned IVSize, bool IVSigned, Address IL,
+ Address LB, Address UB, Address ST) override;
+
+ /// 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;
+
+ /// 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;
+
+ /// Returns address of the threadprivate variable for the current
+ /// thread.
+ /// \param VD Threadprivate variable.
+ /// \param VDAddr Address of the global variable \a VD.
+ /// \param Loc Location of the reference to threadprivate var.
+ /// \return Address of the threadprivate variable for the current thread.
+ Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD,
+ Address VDAddr, SourceLocation Loc) override;
+
+ /// 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).
+ /// \param VD Threadprivate variable.
+ /// \param VDAddr Address of the global variable \a VD.
+ /// \param Loc Location of threadprivate declaration.
+ /// \param PerformInit true if initialization expression is not constant.
+ llvm::Function *
+ emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr,
+ SourceLocation Loc, bool PerformInit,
+ CodeGenFunction *CGF = nullptr) override;
+
+ /// Creates artificial threadprivate variable with name \p Name and type \p
+ /// VarType.
+ /// \param VarType Type of the artificial threadprivate variable.
+ /// \param Name Name of the artificial threadprivate variable.
+ Address getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF,
+ QualType VarType,
+ StringRef Name) override;
+
+ /// 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;
+
+ /// 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,
+ /// kmp_routine_entry_t *task_entry). Here task_entry is a pointer to the
+ /// function:
+ /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
+ /// TaskFunction(gtid, tt->part_id, tt->shareds);
+ /// return 0;
+ /// }
+ /// 2. Copy a list of shared variables to field shareds of the resulting
+ /// structure kmp_task_t returned by the previous call (if any).
+ /// 3. Copy a pointer to destructions function to field destructions of the
+ /// resulting structure kmp_task_t.
+ /// 4. Emit a call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid,
+ /// kmp_task_t *new_task), where new_task is a resulting structure from
+ /// previous items.
+ /// \param D Current task directive.
+ /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32
+ /// /*part_id*/, captured_struct */*__context*/);
+ /// \param SharedsTy A type which contains references the shared variables.
+ /// \param Shareds Context with the list of shared variables from the \p
+ /// TaskFunction.
+ /// \param IfCond Not a nullptr if 'if' clause was specified, nullptr
+ /// otherwise.
+ /// \param Data Additional data for task generation like tiednsee, final
+ /// state, list of privates etc.
+ void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
+ const OMPExecutableDirective &D, llvm::Value *TaskFunction,
+ QualType SharedsTy, Address Shareds, const Expr *IfCond,
+ const OMPTaskDataTy &Data) override;
+
+ /// Emit task region for the taskloop directive. The taskloop 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,
+ /// kmp_routine_entry_t *task_entry). Here task_entry is a pointer to the
+ /// function:
+ /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
+ /// TaskFunction(gtid, tt->part_id, tt->shareds);
+ /// return 0;
+ /// }
+ /// 2. Copy a list of shared variables to field shareds of the resulting
+ /// structure kmp_task_t returned by the previous call (if any).
+ /// 3. Copy a pointer to destructions function to field destructions of the
+ /// resulting structure kmp_task_t.
+ /// 4. Emit a 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 sched, kmp_uint64 grainsize, void *task_dup ), where new_task
+ /// is a resulting structure from
+ /// previous items.
+ /// \param D Current task directive.
+ /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32
+ /// /*part_id*/, captured_struct */*__context*/);
+ /// \param SharedsTy A type which contains references the shared variables.
+ /// \param Shareds Context with the list of shared variables from the \p
+ /// TaskFunction.
+ /// \param IfCond Not a nullptr if 'if' clause was specified, nullptr
+ /// otherwise.
+ /// \param Data Additional data for task generation like tiednsee, final
+ /// state, list of privates etc.
+ void emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
+ const OMPLoopDirective &D, llvm::Value *TaskFunction,
+ QualType SharedsTy, Address Shareds, const Expr *IfCond,
+ const OMPTaskDataTy &Data) override;
+
+ /// Emit a code for reduction clause. Next code should be emitted for
+ /// reduction:
+ /// \code
+ ///
+ /// static kmp_critical_name lock = { 0 };
+ ///
+ /// void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
+ /// ...
+ /// *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
+ /// ...
+ /// }
+ ///
+ /// ...
+ /// void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
+ /// switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
+ /// RedList, reduce_func, &<lock>)) {
+ /// case 1:
+ /// ...
+ /// <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
+ /// ...
+ /// __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
+ /// break;
+ /// case 2:
+ /// ...
+ /// Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
+ /// ...
+ /// break;
+ /// default:;
+ /// }
+ /// \endcode
+ ///
+ /// \param Privates List of private copies for original reduction arguments.
+ /// \param LHSExprs List of LHS in \a ReductionOps reduction operations.
+ /// \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)'.
+ /// \param Options List of options for reduction codegen:
+ /// WithNowait true if parent directive has also nowait clause, false
+ /// otherwise.
+ /// SimpleReduction Emit reduction operation only. Used for omp simd
+ /// directive on the host.
+ /// ReductionKind The kind of reduction to perform.
+ void emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
+ ArrayRef<const Expr *> Privates,
+ ArrayRef<const Expr *> LHSExprs,
+ ArrayRef<const Expr *> RHSExprs,
+ ArrayRef<const Expr *> ReductionOps,
+ ReductionOptionsTy Options) override;
+
+ /// Emit a code for initialization of task reduction clause. Next code
+ /// should be emitted for reduction:
+ /// \code
+ ///
+ /// _task_red_item_t red_data[n];
+ /// ...
+ /// red_data[i].shar = &origs[i];
+ /// red_data[i].size = sizeof(origs[i]);
+ /// red_data[i].f_init = (void*)RedInit<i>;
+ /// red_data[i].f_fini = (void*)RedDest<i>;
+ /// red_data[i].f_comb = (void*)RedOp<i>;
+ /// red_data[i].flags = <Flag_i>;
+ /// ...
+ /// void* tg1 = __kmpc_task_reduction_init(gtid, n, red_data);
+ /// \endcode
+ ///
+ /// \param LHSExprs List of LHS in \a Data.ReductionOps reduction operations.
+ /// \param RHSExprs List of RHS in \a Data.ReductionOps reduction operations.
+ /// \param Data Additional data for task generation like tiedness, final
+ /// state, list of privates, reductions etc.
+ llvm::Value *emitTaskReductionInit(CodeGenFunction &CGF, SourceLocation Loc,
+ ArrayRef<const Expr *> LHSExprs,
+ ArrayRef<const Expr *> RHSExprs,
+ const OMPTaskDataTy &Data) override;
+
+ /// Required to resolve existing problems in the runtime. Emits threadprivate
+ /// variables to store the size of the VLAs/array sections for
+ /// initializer/combiner/finalizer functions + emits threadprivate variable to
+ /// store the pointer to the original reduction item for the custom
+ /// initializer defined by declare reduction construct.
+ /// \param RCG Allows to reuse an existing data for the reductions.
+ /// \param N Reduction item for which fixups must be emitted.
+ void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc,
+ ReductionCodeGen &RCG, unsigned N) override;
+
+ /// Get the address of `void *` type of the privatue copy of the reduction
+ /// item specified by the \p SharedLVal.
+ /// \param ReductionsPtr Pointer to the reduction data returned by the
+ /// emitTaskReductionInit function.
+ /// \param SharedLVal Address of the original reduction item.
+ Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc,
+ llvm::Value *ReductionsPtr,
+ LValue SharedLVal) override;
+
+ /// Emit code for 'taskwait' directive.
+ void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc) override;
+
+ /// 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;
+
+ /// 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.
+ ///
+ void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
+ const Expr *IfCond,
+ OpenMPDirectiveKind CancelRegion) override;
+
+ /// 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.
+ /// \param OutlinedFnID Outlined function ID value to be defined by this call.
+ /// \param IsOffloadEntry True if the outlined function is an offload entry.
+ /// \param CodeGen Code generation sequence for the \a D directive.
+ /// An outlined function may not be an entry if, e.g. the if clause always
+ /// evaluates to false.
+ void emitTargetOutlinedFunction(const OMPExecutableDirective &D,
+ StringRef ParentName,
+ llvm::Function *&OutlinedFn,
+ llvm::Constant *&OutlinedFnID,
+ bool IsOffloadEntry,
+ const RegionCodeGenTy &CodeGen) override;
+
+ /// 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.
+ /// \param OutlinedFn Host version of the code to be offloaded.
+ /// \param OutlinedFnID ID of host version of the code to be offloaded.
+ /// \param IfCond Expression evaluated in if clause associated with the target
+ /// 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.
+ void emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D,
+ llvm::Value *OutlinedFn, llvm::Value *OutlinedFnID,
+ const Expr *IfCond, const Expr *Device) override;
+
+ /// 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;
+
+ /// 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;
+
+ /// 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;
+
+ /// 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;
+
+ /// 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
+ /// 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.
+ ///
+ void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D,
+ SourceLocation Loc, llvm::Value *OutlinedFn,
+ ArrayRef<llvm::Value *> CapturedVars) override;
+
+ /// 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.
+ /// \param ThreadLimit An integer expression of threads.
+ void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams,
+ const Expr *ThreadLimit, SourceLocation Loc) override;
+
+ /// 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.
+ /// \param Device Expression evaluated in device clause associated with the
+ /// target directive, or null if no device clause is used.
+ /// \param Info A record used to store information that needs to be preserved
+ /// until the region is closed.
+ void emitTargetDataCalls(CodeGenFunction &CGF,
+ const OMPExecutableDirective &D, const Expr *IfCond,
+ const Expr *Device, const RegionCodeGenTy &CodeGen,
+ TargetDataInfo &Info) override;
+
+ /// 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
+ /// 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.
+ void emitTargetDataStandAloneCall(CodeGenFunction &CGF,
+ const OMPExecutableDirective &D,
+ const Expr *IfCond,
+ const Expr *Device) override;
+
+ /// 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;
+
+ /// Emit code for doacross ordered directive with 'depend' clause.
+ /// \param C 'depend' clause with 'sink|source' dependency kind.
+ void emitDoacrossOrdered(CodeGenFunction &CGF,
+ const OMPDependClause *C) override;
+
+ /// Translates the native parameter of outlined function if this is required
+ /// for target.
+ /// \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;
+
+ /// Gets the address of the native argument basing on the address of the
+ /// target-specific parameter.
+ /// \param NativeParam Parameter itself.
+ /// \param TargetParam Corresponding target-specific parameter.
+ Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam,
+ const VarDecl *TargetParam) const override;
};
} // namespace CodeGen
diff --git a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
index 7b2993cfd38d..036b5371fe0b 100644
--- a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
+++ b/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,353 @@ 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;
+
+ static llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy>
+ isDeclareTargetDeclaration(const ValueDecl *VD) {
+ for (const Decl *D : VD->redecls()) {
+ if (!D->hasAttrs())
+ continue;
+ if (const auto *Attr = D->getAttr<OMPDeclareTargetDeclAttr>())
+ return Attr->getMapType();
+ }
+ return llvm::None;
+ }
+
+ void markAsEscaped(const ValueDecl *VD) {
+ // Do not globalize declare target variables.
+ if (!isa<VarDecl>(VD) || 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 +599,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 +619,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();
}
-bool CGOpenMPRuntimeNVPTX::isInSpmdExecutionMode() const {
- return CurrentExecutionMode == CGOpenMPRuntimeNVPTX::ExecutionMode::Spmd;
+CGOpenMPRuntimeNVPTX::ExecutionMode
+CGOpenMPRuntimeNVPTX::getExecutionMode() const {
+ return CurrentExecutionMode;
+}
+
+static CGOpenMPRuntimeNVPTX::DataSharingMode
+getDataSharingMode(CodeGenModule &CGM) {
+ return CGM.getLangOpts().OpenMPCUDAMode ? CGOpenMPRuntimeNVPTX::CUDA
+ : CGOpenMPRuntimeNVPTX::Generic;
+}
+
+/// 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;
}
-static CGOpenMPRuntimeNVPTX::ExecutionMode
-getExecutionModeForDirective(CodeGenModule &CGM,
- const OMPExecutableDirective &D) {
+/// 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 +917,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 +940,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 +978,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 +999,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 +1010,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 +1022,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 +1069,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 +1122,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 +1143,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 +1159,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 +1204,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 +1216,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 +1224,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 +1233,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 +1275,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 +1284,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 +1293,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 +1302,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 +1328,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 +1398,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 +1407,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 +1519,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 +1539,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 +1549,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 +1564,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 +1600,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 +1628,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 +1749,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 +1766,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 +1876,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 +2232,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 +2263,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 +2281,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 +2345,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 +2387,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 +2410,7 @@ static void emitReductionListCopy(
SrcBase = Address(ScratchpadBasePtr, CGF.getPointerAlign());
}
- Idx++;
+ ++Idx;
}
}
@@ -1319,27 +2425,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 +2458,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 +2518,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 +2528,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 +2553,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 +2581,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 +2645,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 +2683,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 +2696,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 +2715,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 +2725,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 +2739,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 +2750,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 +2775,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 +2788,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 +2802,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 +2814,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 +2835,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 +2908,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 +2998,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 +3024,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 +3036,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 +3309,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 +3352,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 +3360,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 +3413,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 +3471,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 +3533,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 +3545,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 +3556,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/lib/CodeGen/CGOpenMPRuntimeNVPTX.h b/lib/CodeGen/CGOpenMPRuntimeNVPTX.h
index 5d13408318a5..f83e99f8a3b7 100644
--- a/lib/CodeGen/CGOpenMPRuntimeNVPTX.h
+++ b/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/lib/CodeGen/CGRecordLayout.h b/lib/CodeGen/CGRecordLayout.h
index 7b9c27d1d772..41084294ab9a 100644
--- a/lib/CodeGen/CGRecordLayout.h
+++ b/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/lib/CodeGen/CGRecordLayoutBuilder.cpp b/lib/CodeGen/CGRecordLayoutBuilder.cpp
index 1644ab4c0725..4ee6c8e71457 100644
--- a/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ b/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();
}
@@ -168,7 +168,7 @@ struct CGRecordLowering {
// Layout routines.
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) {
@@ -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))
@@ -380,7 +380,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 +404,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 +432,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 +632,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));
}
@@ -785,8 +791,7 @@ CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D,
}
// 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);
@@ -808,7 +813,7 @@ CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D,
continue;
// Don't inspect zero-length bitfields.
- if (FD->getBitWidthValue(getContext()) == 0)
+ if (FD->isZeroLengthBitField(getContext()))
continue;
const CGBitFieldInfo &Info = RL->getBitFieldInfo(FD);
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index 91fa49a46ef1..79662ec0099f 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -74,6 +74,15 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) {
// Generate a stoppoint if we are emitting debug info.
EmitStopPoint(S);
+ // Ignore all OpenMP directives except for simd if OpenMP with Simd is
+ // enabled.
+ if (getLangOpts().OpenMP && getLangOpts().OpenMPSimd) {
+ if (const auto *D = dyn_cast<OMPExecutableDirective>(S)) {
+ EmitSimpleOMPExecutableDirective(*D);
+ return;
+ }
+ }
+
switch (S->getStmtClass()) {
case Stmt::NoStmtClass:
case Stmt::CXXCatchStmtClass:
@@ -599,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.
@@ -696,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
@@ -768,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);
@@ -781,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."
@@ -856,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();
@@ -996,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);
@@ -1026,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
@@ -1074,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;
}
}
@@ -1563,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
@@ -1592,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
@@ -1915,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());
@@ -2122,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/lib/CodeGen/CGStmtOpenMP.cpp b/lib/CodeGen/CGStmtOpenMP.cpp
index f9861735832b..0d343f84c71f 100644
--- a/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/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:
@@ -144,6 +142,72 @@ public:
}
};
+class OMPSimdLexicalScope : public CodeGenFunction::LexicalScope {
+ CodeGenFunction::OMPPrivateScope InlinedShareds;
+
+ static bool isCapturedVar(CodeGenFunction &CGF, const VarDecl *VD) {
+ return CGF.LambdaCaptureFields.lookup(VD) ||
+ (CGF.CapturedStmtInfo && CGF.CapturedStmtInfo->lookup(VD)) ||
+ (CGF.CurCodeDecl && isa<BlockDecl>(CGF.CurCodeDecl) &&
+ cast<BlockDecl>(CGF.CurCodeDecl)->capturesVariable(VD));
+ }
+
+public:
+ OMPSimdLexicalScope(CodeGenFunction &CGF, const OMPExecutableDirective &S)
+ : CodeGenFunction::LexicalScope(CGF, S.getSourceRange()),
+ InlinedShareds(CGF) {
+ for (const auto *C : S.clauses()) {
+ 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>()) {
+ CGF.EmitVarDecl(cast<VarDecl>(*I));
+ } else {
+ CodeGenFunction::AutoVarEmission Emission =
+ CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
+ CGF.EmitAutoVarCleanups(Emission);
+ }
+ }
+ }
+ } else if (const auto *UDP = dyn_cast<OMPUseDevicePtrClause>(C)) {
+ for (const Expr *E : UDP->varlists()) {
+ const Decl *D = cast<DeclRefExpr>(E)->getDecl();
+ if (const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
+ CGF.EmitVarDecl(*OED);
+ }
+ }
+ }
+ if (!isOpenMPSimdDirective(S.getDirectiveKind()))
+ CGF.EmitOMPPrivateClause(S, InlinedShareds);
+ if (const auto *TG = dyn_cast<OMPTaskgroupDirective>(&S)) {
+ if (const Expr *E = TG->getReductionRef())
+ CGF.EmitVarDecl(*cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()));
+ }
+ const auto *CS = cast_or_null<CapturedStmt>(S.getAssociatedStmt());
+ while (CS) {
+ 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,
+ C.getLocation());
+ InlinedShareds.addPrivate(VD, [&CGF, &DRE]() -> Address {
+ return CGF.EmitLValue(&DRE).getAddress();
+ });
+ }
+ }
+ CS = dyn_cast<CapturedStmt>(CS->getCapturedStmt());
+ }
+ (void)InlinedShareds.Privatize();
+ }
+};
+
} // namespace
static void emitCommonOMPTargetDirective(CodeGenFunction &CGF,
@@ -151,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) ||
@@ -167,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(
@@ -195,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());
@@ -223,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 {
@@ -233,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();
@@ -249,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);
@@ -329,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;
@@ -339,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");
}
@@ -387,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]) {
@@ -431,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>());
@@ -461,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;
@@ -524,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();
@@ -539,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()));
@@ -564,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);
@@ -608,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());
@@ -627,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.
@@ -641,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);
});
@@ -653,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);
@@ -673,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;
@@ -693,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");
@@ -762,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;
@@ -794,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
@@ -826,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;
@@ -854,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());
}
@@ -863,19 +938,21 @@ bool CodeGenFunction::EmitOMPLastprivateClauseInit(
llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) {
HasAtLeastOneLastprivate = true;
- if (isOpenMPTaskLoopDirective(D.getDirectiveKind()))
+ if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) &&
+ !getLangOpts().OpenMPSimd)
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(
@@ -887,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);
@@ -926,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);
@@ -942,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()));
@@ -968,7 +1048,7 @@ void CodeGenFunction::EmitOMPLastprivateClauseFinal(
++ISrcRef;
++IDestRef;
}
- if (auto *PostUpdate = C->getPostUpdateExpr())
+ if (const Expr *PostUpdate = C->getPostUpdateExpr())
EmitIgnoredExpr(PostUpdate);
}
if (IsLastIterCond)
@@ -990,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);
@@ -1007,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) {
@@ -1023,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");
@@ -1063,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),
@@ -1100,9 +1178,8 @@ void CodeGenFunction::EmitOMPReductionClauseFinal(
if (HasAtLeastOneReduction) {
bool WithNowait = D.getSingleClause<OMPNowaitClause>() ||
isOpenMPParallelDirective(D.getDirectiveKind()) ||
- D.getDirectiveKind() == OMPD_simd;
- bool SimpleReduction = D.getDirectiveKind() == OMPD_simd ||
- D.getDirectiveKind() == OMPD_distribute_simd;
+ ReductionKind == OMPD_simd;
+ bool SimpleReduction = ReductionKind == OMPD_simd;
// Emit nowait reduction if nowait clause is present or directive is a
// parallel directive (it always has implicit barrier).
CGM.getOpenMPRuntime().emitReduction(
@@ -1113,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);
@@ -1151,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());
}
@@ -1192,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);
@@ -1207,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());
@@ -1246,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));
@@ -1276,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);
@@ -1298,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,
@@ -1312,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);
@@ -1329,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)
@@ -1371,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]
@@ -1403,28 +1484,28 @@ 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;
}
@@ -1440,7 +1521,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);
}
}
@@ -1454,20 +1535,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);
@@ -1475,8 +1556,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;
}
}
@@ -1490,7 +1572,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
@@ -1500,12 +1582,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);
}
}
@@ -1513,46 +1595,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);
}
@@ -1570,6 +1651,14 @@ static void emitOMPLoopBodyWithStopPoint(CodeGenFunction &CGF,
CGF.EmitStopPoint(&S);
}
+/// Emit a helper variable and return corresponding lvalue.
+static LValue EmitOMPHelperVar(CodeGenFunction &CGF,
+ const DeclRefExpr *Helper) {
+ auto VDecl = cast<VarDecl>(Helper->getDecl());
+ CGF.EmitVarDecl(*VDecl);
+ return CGF.EmitLValue(Helper);
+}
+
static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S,
PrePostActionTy &Action) {
Action.Enter(CGF);
@@ -1581,6 +1670,12 @@ static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S,
// <Final counter/linear vars updates>;
// }
//
+ if (isOpenMPDistributeDirective(S.getDirectiveKind()) ||
+ isOpenMPWorksharingDirective(S.getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(S.getDirectiveKind())) {
+ (void)EmitOMPHelperVar(CGF, cast<DeclRefExpr>(S.getLowerBoundVariable()));
+ (void)EmitOMPHelperVar(CGF, cast<DeclRefExpr>(S.getUpperBoundVariable()));
+ }
// Emit: if (PreCond) - begin.
// If the condition constant folds and can be elided, avoid emitting the
@@ -1591,7 +1686,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));
@@ -1601,14 +1696,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());
@@ -1633,17 +1728,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);
@@ -1655,7 +1748,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);
}
@@ -1665,18 +1758,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()));
@@ -1698,11 +1791,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);
@@ -1716,7 +1809,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
@@ -1769,7 +1862,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 =
@@ -1835,7 +1928,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,
@@ -1878,7 +1972,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
@@ -1933,14 +2027,6 @@ void CodeGenFunction::EmitOMPDistributeOuterLoop(
emitEmptyOrdered);
}
-/// Emit a helper variable and return corresponding lvalue.
-static LValue EmitOMPHelperVar(CodeGenFunction &CGF,
- const DeclRefExpr *Helper) {
- auto VDecl = cast<VarDecl>(Helper->getDecl());
- CGF.EmitVarDecl(*VDecl);
- return CGF.EmitLValue(Helper);
-}
-
static std::pair<LValue, LValue>
emitDistributeParallelForInnerBounds(CodeGenFunction &CGF,
const OMPExecutableDirective &S) {
@@ -1958,14 +2044,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);
@@ -1991,10 +2081,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};
}
@@ -2004,13 +2094,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);
}
@@ -2020,7 +2110,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))
@@ -2051,7 +2142,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);
}
@@ -2061,7 +2152,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);
}
@@ -2070,7 +2161,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);
}
@@ -2096,28 +2187,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;
@@ -2135,20 +2204,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.
@@ -2163,7 +2232,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));
@@ -2171,8 +2240,9 @@ 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);
else
@@ -2213,11 +2283,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(),
@@ -2245,7 +2315,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());
@@ -2282,7 +2352,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()));
});
@@ -2293,7 +2363,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()));
});
@@ -2303,14 +2373,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;
@@ -2321,7 +2392,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 =
@@ -2336,7 +2407,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);
@@ -2354,15 +2425,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) {
@@ -2374,38 +2444,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.",
@@ -2423,8 +2494,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:
@@ -2436,13 +2507,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);
@@ -2451,10 +2522,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);
@@ -2483,8 +2554,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;
@@ -2500,11 +2571,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)
@@ -2535,7 +2605,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.
@@ -2547,9 +2617,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());
}
@@ -2578,10 +2648,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);
@@ -2598,21 +2668,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);
@@ -2622,7 +2692,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);
@@ -2635,7 +2706,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);
};
@@ -2647,27 +2719,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);
@@ -2679,7 +2752,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(),
@@ -2692,8 +2765,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);
@@ -2706,8 +2779,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);
@@ -2722,8 +2795,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);
@@ -2742,7 +2815,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);
@@ -2758,50 +2831,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(
@@ -2811,14 +2885,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(
@@ -2826,6 +2900,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 =
@@ -2833,16 +2912,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.
@@ -2855,7 +2929,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);
@@ -2875,24 +2949,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();
@@ -2900,7 +2975,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);
@@ -2909,27 +2984,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,
@@ -2944,12 +3016,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);
@@ -2976,14 +3048,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,
@@ -2994,33 +3067,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; });
@@ -3028,19 +3101,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);
@@ -3054,9 +3128,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 ||
@@ -3079,7 +3153,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(
@@ -3108,7 +3182,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);
@@ -3128,40 +3202,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.
@@ -3176,7 +3252,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));
@@ -3225,9 +3301,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(),
@@ -3254,7 +3330,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())
@@ -3265,9 +3341,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; }
@@ -3291,31 +3368,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(
@@ -3335,10 +3416,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);
}
@@ -3347,34 +3427,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);
}
@@ -3384,11 +3465,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
@@ -3399,15 +3479,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(
@@ -3446,7 +3528,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;
@@ -3470,7 +3552,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;
@@ -3489,7 +3571,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.
@@ -3567,20 +3649,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;
@@ -3601,13 +3684,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;
@@ -3617,18 +3700,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
@@ -3656,7 +3739,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,
@@ -3667,27 +3750,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);
@@ -3714,7 +3798,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;
};
@@ -3737,24 +3821,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:
@@ -3810,7 +3894,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();
@@ -3818,28 +3902,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);
}
@@ -3848,7 +3929,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;
@@ -3865,9 +3955,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
@@ -3885,9 +3974,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 =
@@ -3896,22 +3985,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,
@@ -3940,14 +4026,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());
@@ -3962,18 +4049,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,
@@ -3982,18 +4070,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(
@@ -4028,7 +4116,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();
@@ -4073,7 +4162,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();
@@ -4117,7 +4207,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();
@@ -4138,7 +4229,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();
@@ -4160,7 +4252,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();
@@ -4182,7 +4275,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();
@@ -4195,6 +4289,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(),
@@ -4234,19 +4431,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();
@@ -4258,7 +4455,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
@@ -4275,7 +4474,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.
@@ -4312,13 +4511,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) {
@@ -4337,8 +4535,9 @@ void CodeGenFunction::EmitOMPTargetDataDirective(
Info.CaptureDeviceAddrMap);
(void)PrivateScope.Privatize();
RCG(CGF);
- } else
+ } else {
RCG(CGF);
+ }
};
// Forward the provided action to the privatization codegen.
@@ -4364,12 +4563,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.
@@ -4389,15 +4588,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);
}
@@ -4410,15 +4609,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);
}
@@ -4426,9 +4625,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);
@@ -4440,8 +4640,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(
@@ -4472,7 +4672,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,
@@ -4512,7 +4713,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);
};
@@ -4547,17 +4749,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 ||
@@ -4600,7 +4802,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));
@@ -4631,14 +4833,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());
@@ -4668,7 +4870,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,
@@ -4677,15 +4880,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());
}
@@ -4710,14 +4914,44 @@ 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);
}
+
+void CodeGenFunction::EmitSimpleOMPExecutableDirective(
+ const OMPExecutableDirective &D) {
+ if (!D.hasAssociatedStmt() || !D.getAssociatedStmt())
+ return;
+ auto &&CodeGen = [&D](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ if (isOpenMPSimdDirective(D.getDirectiveKind())) {
+ emitOMPSimdRegion(CGF, cast<OMPLoopDirective>(D), Action);
+ } else {
+ if (const auto *LD = dyn_cast<OMPLoopDirective>(&D)) {
+ 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.
+ if (!CGF.LocalDeclMap.count(VD))
+ CGF.EmitVarDecl(*VD);
+ }
+ }
+ }
+ CGF.EmitStmt(D.getInnermostCapturedStmt()->getCapturedStmt());
+ }
+ };
+ OMPSimdLexicalScope Scope(*this, D);
+ CGM.getOpenMPRuntime().emitInlinedDirective(
+ *this,
+ isOpenMPSimdDirective(D.getDirectiveKind()) ? OMPD_simd
+ : D.getDirectiveKind(),
+ CodeGen);
+}
+
diff --git a/lib/CodeGen/CGVTT.cpp b/lib/CodeGen/CGVTT.cpp
index 78928d04220d..41c8c943f54d 100644
--- a/lib/CodeGen/CGVTT.cpp
+++ b/lib/CodeGen/CGVTT.cpp
@@ -100,7 +100,7 @@ CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT,
VTT->setComdat(CGM.getModule().getOrInsertComdat(VTT->getName()));
// Set the right visibility.
- CGM.setGlobalVisibility(VTT, RD, ForDefinition);
+ CGM.setGVProperties(VTT, RD);
}
llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTT(const CXXRecordDecl *RD) {
diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp
index 2d9bf3bce926..5a2ec65f7763 100644
--- a/lib/CodeGen/CGVTables.cpp
+++ b/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()));
@@ -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/lib/CodeGen/CGVTables.h b/lib/CodeGen/CGVTables.h
index b92212c368a9..a11474a15ea4 100644
--- a/lib/CodeGen/CGVTables.h
+++ b/lib/CodeGen/CGVTables.h
@@ -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,
diff --git a/lib/CodeGen/CGValue.h b/lib/CodeGen/CGValue.h
index 7d07ea4516c9..418bda1f41bb 100644
--- a/lib/CodeGen/CGValue.h
+++ b/lib/CodeGen/CGValue.h
@@ -193,7 +193,7 @@ 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;
@@ -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;
@@ -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.
@@ -469,17 +472,25 @@ 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;
+
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 };
/// 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,6 +508,7 @@ public:
IsDestructed_t isDestructed,
NeedsGCBarriers_t needsGC,
IsAliased_t isAliased,
+ Overlap_t mayOverlap,
IsZeroed_t isZeroed = IsNotZeroed) {
AggValueSlot AV;
if (addr.isValid()) {
@@ -511,6 +523,7 @@ public:
AV.ObjCGCFlag = needsGC;
AV.ZeroedFlag = isZeroed;
AV.AliasedFlag = isAliased;
+ AV.OverlapFlag = mayOverlap;
return AV;
}
@@ -518,9 +531,10 @@ public:
IsDestructed_t isDestructed,
NeedsGCBarriers_t needsGC,
IsAliased_t isAliased,
+ Overlap_t mayOverlap,
IsZeroed_t isZeroed = IsNotZeroed) {
- return forAddr(LV.getAddress(),
- LV.getQuals(), isDestructed, needsGC, isAliased, isZeroed);
+ return forAddr(LV.getAddress(), LV.getQuals(), isDestructed, needsGC,
+ isAliased, mayOverlap, isZeroed);
}
IsDestructed_t isExternallyDestructed() const {
@@ -568,6 +582,10 @@ public:
return IsAliased_t(AliasedFlag);
}
+ Overlap_t mayOverlap() const {
+ return Overlap_t(OverlapFlag);
+ }
+
RValue asRValue() const {
if (isIgnored()) {
return RValue::getIgnored();
@@ -580,6 +598,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/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt
index 84248cc64719..2a0f4f0e83ec 100644
--- a/lib/CodeGen/CMakeLists.txt
+++ b/lib/CodeGen/CMakeLists.txt
@@ -7,6 +7,7 @@ set(LLVM_LINK_COMPONENTS
Coverage
IPO
IRReader
+ AggressiveInstCombine
InstCombine
Instrumentation
LTO
@@ -31,6 +32,10 @@ if (CLANG_BUILT_STANDALONE)
set(codegen_deps)
endif()
+if (MSVC)
+ set_source_files_properties(CodeGenModule.cpp PROPERTIES COMPILE_FLAGS /bigobj)
+endif()
+
add_clang_library(clangCodeGen
BackendUtil.cpp
CGAtomic.cpp
@@ -56,6 +61,7 @@ add_clang_library(clangCodeGen
CGExprScalar.cpp
CGGPUBuiltin.cpp
CGLoopInfo.cpp
+ CGNonTrivialStruct.cpp
CGObjC.cpp
CGObjCGNU.cpp
CGObjCMac.cpp
@@ -93,7 +99,6 @@ add_clang_library(clangCodeGen
LINK_LIBS
clangAnalysis
clangAST
- clangAnalysis
clangBasic
clangFrontend
clangLex
diff --git a/lib/CodeGen/CodeGenAction.cpp b/lib/CodeGen/CodeGenAction.cpp
index 6ca69d63cdce..7ca55070d4a0 100644
--- a/lib/CodeGen/CodeGenAction.cpp
+++ b/lib/CodeGen/CodeGenAction.cpp
@@ -126,7 +126,7 @@ namespace clang {
Gen(CreateLLVMCodeGen(Diags, InFile, HeaderSearchOpts, PPOpts,
CodeGenOpts, C, CoverageInfo)),
LinkModules(std::move(LinkModules)) {
- llvm::TimePassesIsEnabled = TimePasses;
+ FrontendTimesIsEnabled = TimePasses;
}
llvm::Module *getModule() const { return Gen->GetModule(); }
std::unique_ptr<llvm::Module> takeModule() {
@@ -144,12 +144,12 @@ namespace clang {
Context = &Ctx;
- if (llvm::TimePassesIsEnabled)
+ if (FrontendTimesIsEnabled)
LLVMIRGeneration.startTimer();
Gen->Initialize(Ctx);
- if (llvm::TimePassesIsEnabled)
+ if (FrontendTimesIsEnabled)
LLVMIRGeneration.stopTimer();
}
@@ -159,7 +159,7 @@ namespace clang {
"LLVM IR generation of declaration");
// Recurse.
- if (llvm::TimePassesIsEnabled) {
+ if (FrontendTimesIsEnabled) {
LLVMIRGenerationRefCount += 1;
if (LLVMIRGenerationRefCount == 1)
LLVMIRGeneration.startTimer();
@@ -167,7 +167,7 @@ namespace clang {
Gen->HandleTopLevelDecl(D);
- if (llvm::TimePassesIsEnabled) {
+ if (FrontendTimesIsEnabled) {
LLVMIRGenerationRefCount -= 1;
if (LLVMIRGenerationRefCount == 0)
LLVMIRGeneration.stopTimer();
@@ -180,12 +180,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 +227,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 +235,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 +341,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 +697,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 +846,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 +950,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/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index 9dbd7cc3fcbf..3c582688e91e 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/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();
@@ -419,6 +403,9 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
EmitIfUsed(*this, TerminateHandler);
EmitIfUsed(*this, UnreachableBlock);
+ for (const auto &FuncletAndParent : TerminateFunclets)
+ EmitIfUsed(*this, FuncletAndParent.second);
+
if (CGM.getCodeGenOpts().EmitDeclMetadata)
EmitDeclMetadata();
@@ -436,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
@@ -462,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 *
@@ -842,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);
@@ -857,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.
@@ -884,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");
@@ -921,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,
@@ -987,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()) {
@@ -1006,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());
}
@@ -1055,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()) {
@@ -1108,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
@@ -1141,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,
@@ -1748,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;
@@ -1836,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.
@@ -1917,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;
@@ -1945,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) {
@@ -2228,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)) {
@@ -2266,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())
@@ -2297,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/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index dd4c2e43ef64..79870ed59c96 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -34,6 +34,7 @@
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Support/Debug.h"
@@ -137,6 +138,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 {
@@ -200,7 +283,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,
@@ -213,7 +296,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
@@ -241,7 +324,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 {
@@ -254,7 +337,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)
@@ -282,10 +365,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());
}
@@ -297,32 +380,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;
@@ -361,13 +444,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:
@@ -377,28 +460,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;
/// 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;
@@ -426,30 +509,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
@@ -524,28 +610,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
@@ -583,10 +693,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:
@@ -600,7 +710,7 @@ public:
CodeGenFunction& CGF;
public:
- /// \brief Enter a new cleanup scope.
+ /// Enter a new cleanup scope.
explicit RunCleanupsScope(CodeGenFunction &CGF)
: PerformCleanup(true), CGF(CGF)
{
@@ -609,20 +719,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
@@ -634,9 +746,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;
@@ -646,7 +763,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;
@@ -659,7 +776,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())
@@ -673,7 +790,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;
@@ -692,57 +809,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
@@ -750,19 +917,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();
@@ -773,34 +935,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
@@ -843,7 +986,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 {
@@ -1052,22 +1196,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.
@@ -1119,7 +1268,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());
@@ -1207,13 +1356,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.
@@ -1230,13 +1379,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;
@@ -1356,9 +1505,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;
@@ -1376,16 +1525,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.
@@ -1416,14 +1565,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);
@@ -1532,6 +1688,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 &&
@@ -1579,10 +1736,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,
@@ -1604,7 +1758,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);
@@ -1627,7 +1799,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,
@@ -1653,7 +1825,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.
@@ -1664,10 +1836,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();
@@ -1677,7 +1849,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,
@@ -1688,7 +1861,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;
@@ -1723,9 +1896,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,
@@ -1775,6 +1950,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);
@@ -1808,6 +1987,10 @@ public:
/// getTerminateLandingPad - Return a landing pad that just calls terminate.
llvm::BasicBlock *getTerminateLandingPad();
+ /// getTerminateLandingPad - Return a cleanup funclet that just calls
+ /// terminate.
+ llvm::BasicBlock *getTerminateFunclet();
+
/// getTerminateHandler - Return a handler (not a landing pad, just
/// a catch handler) that just calls terminate. This is used when
/// a terminate scope encloses a try.
@@ -1841,11 +2024,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
@@ -1975,15 +2154,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.
@@ -2018,12 +2202,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.
@@ -2032,7 +2222,8 @@ public:
T.getQualifiers(),
AggValueSlot::IsNotDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased);
+ AggValueSlot::IsNotAliased,
+ AggValueSlot::DoesNotOverlap);
}
/// Emit a cast to void* in the appropriate address space.
@@ -2089,31 +2280,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) {
@@ -2123,27 +2335,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; }
@@ -2193,12 +2391,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.
@@ -2279,11 +2489,14 @@ 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);
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);
/// Emit assumption load for all bases. Requires to be be called only on
/// most-derived class and not under construction of the object.
@@ -2333,13 +2546,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.
@@ -2383,17 +2596,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,
@@ -2434,7 +2647,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);
@@ -2448,7 +2661,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;
@@ -2464,13 +2679,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(); }
@@ -2486,11 +2707,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.
@@ -2506,6 +2731,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);
@@ -2655,6 +2889,9 @@ public:
llvm::Value *EmitSEHExceptionInfo();
llvm::Value *EmitSEHAbnormalTermination();
+ /// Emit simple code for OpenMP directives in Simd-only mode.
+ void EmitSimpleOMPExecutableDirective(const OMPExecutableDirective &D);
+
/// Scan the outlined statement for captures from the parent function. For
/// each capture, mark the capture as escaped and emit a call to
/// llvm.localrecover. Insert the localrecover result into the LocalDeclMap.
@@ -2697,7 +2934,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.
///
@@ -2708,8 +2945,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.
@@ -2724,7 +2961,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.
@@ -2740,7 +2977,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,
@@ -2748,7 +2985,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;
@@ -2760,7 +2997,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.
@@ -2773,7 +3010,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.
@@ -2791,8 +3028,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.
@@ -2801,14 +3038,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.
@@ -2821,6 +3058,7 @@ public:
const OMPTaskDataTy & /*Data*/)>
TaskGenTy;
void EmitOMPTaskBasedDirective(const OMPExecutableDirective &S,
+ const OpenMPDirectiveKind CapturedRegion,
const RegionCodeGenTy &BodyGen,
const TaskGenTy &TaskGen, OMPTaskDataTy &Data);
struct OMPTargetDataInfo {
@@ -2930,7 +3168,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
@@ -2943,8 +3190,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.
@@ -2954,7 +3201,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,
@@ -2969,17 +3216,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 {
@@ -3030,7 +3274,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:
@@ -3071,7 +3315,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);
@@ -3332,6 +3576,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 = "");
@@ -3351,6 +3598,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,
@@ -3424,6 +3681,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);
@@ -3482,6 +3743,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);
@@ -3525,6 +3788,7 @@ public:
static Destroyer destroyARCStrongPrecise;
static Destroyer destroyARCWeak;
static Destroyer emitARCIntrinsicUse;
+ static Destroyer destroyNonTrivialCStruct;
void EmitObjCAutoreleasePoolPop(llvm::Value *Ptr);
llvm::Value *EmitObjCAutoreleasePoolPush();
@@ -3532,7 +3796,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);
//===--------------------------------------------------------------------===//
@@ -3610,6 +3874,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
@@ -3746,26 +4013,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,
@@ -3775,21 +4042,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);
@@ -3829,10 +4096,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);
@@ -3844,7 +4111,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.
///
@@ -3853,7 +4120,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,
@@ -3973,6 +4240,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);
@@ -3988,110 +4297,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));
- }
-};
-
-/// 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 };
+inline DominatingLLVMValue::saved_type
+DominatingLLVMValue::save(CodeGenFunction &CGF, llvm::Value *value) {
+ if (!needsSaving(value)) return saved_type(value, false);
- 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) {}
+ // 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);
- 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/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 5bdf81aaf66e..ecdf78d4b347 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/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();
@@ -208,7 +207,10 @@ void CodeGenModule::createOpenMPRuntime() {
OpenMPRuntime.reset(new CGOpenMPRuntimeNVPTX(*this));
break;
default:
- OpenMPRuntime.reset(new CGOpenMPRuntime(*this));
+ if (LangOpts.OpenMPSimd)
+ OpenMPRuntime.reset(new CGOpenMPSIMDRuntime(*this));
+ else
+ OpenMPRuntime.reset(new CGOpenMPRuntime(*this));
break;
}
}
@@ -392,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())
@@ -453,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
@@ -498,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.
@@ -533,6 +556,9 @@ void CodeGenModule::Release() {
getModule().setPIELevel(static_cast<llvm::PIELevel::Level>(PLevel));
}
+ if (CodeGenOpts.NoPLT)
+ getModule().setRtLibUseGOT();
+
SimplifyPersonality();
if (getCodeGenOpts().EmitDeclMetadata)
@@ -544,7 +570,8 @@ void CodeGenModule::Release() {
if (DebugInfo)
DebugInfo->finalize();
- EmitVersionIdentMetadata();
+ if (getCodeGenOpts().EmitVersionIdentMetadata)
+ EmitVersionIdentMetadata();
EmitTargetMetadata();
}
@@ -580,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
@@ -629,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))
@@ -670,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)
@@ -722,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.");
@@ -761,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();
}
@@ -808,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));
}
@@ -855,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() &&
@@ -876,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;
@@ -902,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) {
@@ -937,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;
@@ -947,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
@@ -1044,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
@@ -1056,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);
@@ -1070,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)) {
@@ -1096,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;
@@ -1168,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
@@ -1183,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
@@ -1204,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
@@ -1238,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);
@@ -1299,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);
@@ -1306,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,
@@ -1325,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.
@@ -1586,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();
@@ -1615,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)
@@ -1662,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;
@@ -1691,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);
}
@@ -1742,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) {
@@ -2058,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
@@ -2071,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) {
@@ -2081,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.
@@ -2094,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);
}
@@ -2157,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);
@@ -2234,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(),
@@ -2255,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);
@@ -2302,6 +2801,7 @@ CodeGenModule::CreateRuntimeFunction(llvm::FunctionType *FTy, StringRef Name,
F->setLinkage(llvm::GlobalValue::ExternalLinkage);
}
}
+ setDSOLocal(F);
}
}
@@ -2313,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
@@ -2350,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 *
@@ -2370,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;
@@ -2386,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);
}
@@ -2438,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));
@@ -2445,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)
@@ -2453,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)) {
@@ -2501,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);
@@ -2602,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,
@@ -2625,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) {
@@ -2679,6 +3183,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) {
@@ -2753,6 +3290,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;
@@ -2989,7 +3532,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>() ||
@@ -3261,18 +3804,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>())
@@ -3281,6 +3824,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) {
@@ -3356,7 +3908,7 @@ void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
if (VD->getTLSKind())
setTLSMode(GA, *VD);
- setAliasAttributes(D, GA);
+ SetCommonAttributes(GD, GA);
}
void CodeGenModule::emitIFuncDefinition(GlobalDecl GD) {
@@ -3377,7 +3929,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);
}
@@ -3415,7 +3968,7 @@ void CodeGenModule::emitIFuncDefinition(GlobalDecl GD) {
} else
GIF->setName(MangledName);
- SetCommonAttributes(D, GIF);
+ SetCommonAttributes(GD, GIF);
}
llvm::Function *CodeGenModule::getIntrinsic(unsigned IID,
@@ -3477,14 +4030,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))
@@ -3492,13 +4044,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 =
@@ -3666,10 +4219,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
@@ -3682,6 +4233,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;
}
@@ -3730,7 +4282,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
@@ -3774,7 +4328,9 @@ ConstantAddress CodeGenModule::GetAddrOfConstantCString(
GlobalName, Alignment);
if (Entry)
*Entry = GV;
- return ConstantAddress(GV, Alignment);
+
+ return ConstantAddress(castStringLiteralToDefaultAddressSpace(*this, GV),
+ Alignment);
}
ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary(
@@ -3847,7 +4403,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
@@ -3860,7 +4416,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()));
@@ -3997,18 +4553,13 @@ void CodeGenModule::EmitDeclContext(const DeclContext *DC) {
/// EmitTopLevelDecl - Emit code for a single top level declaration.
void CodeGenModule::EmitTopLevelDecl(Decl *D) {
// Ignore dependent declarations.
- if (D->getDeclContext() && D->getDeclContext()->isDependentContext())
+ if (D->isTemplated())
return;
switch (D->getKind()) {
case Decl::CXXConversion:
case Decl::CXXMethod:
case Decl::Function:
- // Skip function templates
- if (cast<FunctionDecl>(D)->getDescribedFunctionTemplate() ||
- cast<FunctionDecl>(D)->isLateTemplateParsed())
- return;
-
EmitGlobal(cast<FunctionDecl>(D));
// Always provide some coverage mapping
// even for the functions that aren't emitted.
@@ -4021,10 +4572,6 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
case Decl::Var:
case Decl::Decomposition:
- // Skip variable templates
- if (cast<VarDecl>(D)->getDescribedVarTemplate())
- return;
- LLVM_FALLTHROUGH;
case Decl::VarTemplateSpecialization:
EmitGlobal(cast<VarDecl>(D));
if (auto *DD = dyn_cast<DecompositionDecl>(D))
@@ -4083,16 +4630,9 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
DI->EmitUsingDirective(cast<UsingDirectiveDecl>(*D));
return;
case Decl::CXXConstructor:
- // Skip function templates
- if (cast<FunctionDecl>(D)->getDescribedFunctionTemplate() ||
- cast<FunctionDecl>(D)->isLateTemplateParsed())
- return;
-
getCXXABI().EmitCXXConstructors(cast<CXXConstructorDecl>(D));
break;
case Decl::CXXDestructor:
- if (cast<FunctionDecl>(D)->isLateTemplateParsed())
- return;
getCXXABI().EmitCXXDestructors(cast<CXXDestructorDecl>(D));
break;
@@ -4152,7 +4692,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:
@@ -4358,9 +4902,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;
@@ -4504,7 +5046,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() &&
@@ -4515,6 +5057,9 @@ llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty,
}
void CodeGenModule::EmitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D) {
+ // Do not emit threadprivates in simd-only mode.
+ if (LangOpts.OpenMP && LangOpts.OpenMPSimd)
+ return;
for (auto RefExpr : D->varlists()) {
auto *VD = cast<VarDecl>(cast<DeclRefExpr>(RefExpr)->getDecl());
bool PerformInit =
@@ -4529,8 +5074,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;
@@ -4538,6 +5085,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 {
@@ -4548,6 +5096,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
@@ -4581,25 +5138,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.
@@ -4634,22 +5174,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.
@@ -4667,6 +5213,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/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 22c4463b2c81..ee64ed4f2ae2 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -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;
@@ -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,7 +449,7 @@ 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;
@@ -499,6 +510,7 @@ private:
/// MDNodes.
typedef llvm::DenseMap<QualType, llvm::Metadata *> MetadataTypeMap;
MetadataTypeMap MetadataIdMap;
+ MetadataTypeMap VirtualMetadataIdMap;
MetadataTypeMap GeneralizedMetadataIdMap;
public:
@@ -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);
@@ -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,25 +1115,24 @@ 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);
@@ -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,6 +1313,7 @@ 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);
@@ -1274,7 +1322,7 @@ private:
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/lib/CodeGen/CodeGenPGO.cpp b/lib/CodeGen/CodeGenPGO.cpp
index 295893c64fbc..c8c2a1b956b8 100644
--- a/lib/CodeGen/CodeGenPGO.cpp
+++ b/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/lib/CodeGen/CodeGenTBAA.cpp b/lib/CodeGen/CodeGenTBAA.cpp
index ad473032db17..ec48231e5247 100644
--- a/lib/CodeGen/CodeGenTBAA.cpp
+++ b/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/lib/CodeGen/CodeGenTBAA.h b/lib/CodeGen/CodeGenTBAA.h
index a5b1f66bcd1a..86ba407c05c6 100644
--- a/lib/CodeGen/CodeGenTBAA.h
+++ b/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/lib/CodeGen/CodeGenTypeCache.h b/lib/CodeGen/CodeGenTypeCache.h
index fb096ac89987..901aed6c00b2 100644
--- a/lib/CodeGen/CodeGenTypeCache.h
+++ b/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/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp
index 529a13b7adc8..16ec1dd301aa 100644
--- a/lib/CodeGen/CodeGenTypes.cpp
+++ b/lib/CodeGen/CodeGenTypes.cpp
@@ -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;
@@ -767,7 +792,7 @@ 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);
}
diff --git a/lib/CodeGen/CodeGenTypes.h b/lib/CodeGen/CodeGenTypes.h
index d082342bf592..fb8d31684290 100644
--- a/lib/CodeGen/CodeGenTypes.h
+++ b/lib/CodeGen/CodeGenTypes.h
@@ -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);
diff --git a/lib/CodeGen/ConstantEmitter.h b/lib/CodeGen/ConstantEmitter.h
index 90c9fcd8cf81..b4d1b65743c7 100644
--- a/lib/CodeGen/ConstantEmitter.h
+++ b/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/lib/CodeGen/CoverageMappingGen.cpp b/lib/CodeGen/CoverageMappingGen.cpp
index 89a30dc7040c..2d8446463594 100644
--- a/lib/CodeGen/CoverageMappingGen.cpp
+++ b/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/lib/CodeGen/CoverageMappingGen.h b/lib/CodeGen/CoverageMappingGen.h
index d07ed5ebcf2b..b08ad896d7a5 100644
--- a/lib/CodeGen/CoverageMappingGen.h
+++ b/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/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp
index c375b82ea936..16fdd1c16a1d 100644
--- a/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/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:
@@ -2761,6 +2911,11 @@ static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM,
// N.B. We must always emit the RTTI data ourselves if there exists a key
// function.
bool IsDLLImport = RD->hasAttr<DLLImportAttr>();
+
+ // Don't import the RTTI but emit it locally.
+ if (CGM.getTriple().isWindowsGNUEnvironment() && IsDLLImport)
+ return false;
+
if (CGM.getVTables().isVTableExternal(RD))
return IsDLLImport && !CGM.getTriple().isWindowsItaniumEnvironment()
? false
@@ -2953,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());
@@ -2966,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) {
@@ -3020,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();
@@ -3039,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));
@@ -3163,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);
@@ -3195,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);
}
@@ -3433,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);
}
}
@@ -3502,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,
@@ -3527,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
@@ -3583,12 +3744,22 @@ static StructorCodegen getCodegenToUse(CodeGenModule &CGM,
}
llvm::GlobalValue::LinkageTypes Linkage = CGM.getFunctionLinkage(AliasDecl);
- if (llvm::GlobalValue::isDiscardableIfUnused(Linkage))
- return StructorCodegen::RAUW;
+ // All discardable structors can be RAUWed, but we don't want to do that in
+ // unoptimized code, as that makes complete structor symbol disappear
+ // completely, which degrades debugging experience.
+ // Symbols with private linkage can be safely aliased, so we special case them
+ // here.
+ if (llvm::GlobalValue::isLocalLinkage(Linkage))
+ return CGM.getCodeGenOpts().OptimizationLevel > 0 ? StructorCodegen::RAUW
+ : StructorCodegen::Alias;
+ // Linkonce structors cannot be aliased nor placed in a comdat, so these need
+ // to be emitted separately.
// FIXME: Should we allow available_externally aliases?
- if (!llvm::GlobalAlias::isValidLinkage(Linkage))
- return StructorCodegen::RAUW;
+ if (llvm::GlobalValue::isDiscardableIfUnused(Linkage) ||
+ !llvm::GlobalAlias::isValidLinkage(Linkage))
+ return CGM.getCodeGenOpts().OptimizationLevel > 0 ? StructorCodegen::RAUW
+ : StructorCodegen::Emit;
if (llvm::GlobalValue::isWeakForLinker(Linkage)) {
// Only ELF and wasm support COMDATs with arbitrary names (C5/D5).
@@ -3616,6 +3787,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() &&
@@ -3628,7 +3802,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,
@@ -3904,7 +4078,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;
}
@@ -3931,7 +4107,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();
@@ -4051,3 +4228,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/lib/CodeGen/MacroPPCallbacks.cpp b/lib/CodeGen/MacroPPCallbacks.cpp
index a6f21d8ddcfb..48dea7d54b1e 100644
--- a/lib/CodeGen/MacroPPCallbacks.cpp
+++ b/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/lib/CodeGen/MacroPPCallbacks.h b/lib/CodeGen/MacroPPCallbacks.h
index e117f96f47df..48c67e2d36ad 100644
--- a/lib/CodeGen/MacroPPCallbacks.h
+++ b/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/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp
index ffb3681c2585..81ed05059546 100644
--- a/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -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;
}
@@ -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;
@@ -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);
@@ -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/lib/CodeGen/ObjectFilePCHContainerOperations.cpp b/lib/CodeGen/ObjectFilePCHContainerOperations.cpp
index d0760b9cc2a6..c164cec5d942 100644
--- a/lib/CodeGen/ObjectFilePCHContainerOperations.cpp
+++ b/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;
}
@@ -229,6 +228,11 @@ public:
Builder->getModuleDebugInfo()->completeRequiredType(RD);
}
+ void HandleImplicitImportDecl(ImportDecl *D) override {
+ if (!D->getImportedOwningModule())
+ Builder->getModuleDebugInfo()->EmitImportDecl(*D);
+ }
+
/// Emit a container holding the serialized AST.
void HandleTranslationUnit(ASTContext &Ctx) override {
assert(M && VMContext && Builder);
@@ -286,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/lib/CodeGen/SanitizerMetadata.cpp b/lib/CodeGen/SanitizerMetadata.cpp
index f891cfbe4bb2..23cf9e490828 100644
--- a/lib/CodeGen/SanitizerMetadata.cpp
+++ b/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/lib/CodeGen/SwiftCallingConv.cpp b/lib/CodeGen/SwiftCallingConv.cpp
index fc8e36d2c599..3673a5597eac 100644
--- a/lib/CodeGen/SwiftCallingConv.cpp
+++ b/lib/CodeGen/SwiftCallingConv.cpp
@@ -579,11 +579,9 @@ 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);
}
@@ -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/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp
index 4b8006428f8f..fa9b0a27af28 100644
--- a/lib/CodeGen/TargetInfo.cpp
+++ b/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=";
@@ -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;
@@ -1028,8 +1050,7 @@ public:
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
@@ -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) {
@@ -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,19 +1945,13 @@ 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>()) {
- // Get the LLVM function.
llvm::Function *Fn = cast<llvm::Function>(GV);
-
- // Now add the 'alignstack' attribute with a value of 16.
- llvm::AttrBuilder B;
- B.addStackAlignmentAttr(16);
- Fn->addAttributes(llvm::AttributeList::FunctionIndex, B);
+ Fn->addFnAttr("stackrealign");
}
if (FD->hasAttr<AnyX86InterruptAttr>()) {
llvm::Function *Fn = cast<llvm::Function>(GV);
@@ -2121,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();
@@ -2168,8 +2182,7 @@ 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);
}
@@ -2201,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);
}
@@ -2286,19 +2298,13 @@ 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>()) {
- // Get the LLVM function.
- auto *Fn = cast<llvm::Function>(GV);
-
- // Now add the 'alignstack' attribute with a value of 16.
- llvm::AttrBuilder B;
- B.addStackAlignmentAttr(16);
- Fn->addAttributes(llvm::AttributeList::FunctionIndex, B);
+ llvm::Function *Fn = cast<llvm::Function>(GV);
+ Fn->addFnAttr("stackrealign");
}
if (FD->hasAttr<AnyX86InterruptAttr>()) {
llvm::Function *Fn = cast<llvm::Function>(GV);
@@ -2346,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 {
@@ -2362,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 {
@@ -2391,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;
@@ -2422,20 +2424,14 @@ 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>()) {
- // Get the LLVM function.
- auto *Fn = cast<llvm::Function>(GV);
-
- // Now add the 'alignstack' attribute with a value of 16.
- llvm::AttrBuilder B;
- B.addStackAlignmentAttr(16);
- Fn->addAttributes(llvm::AttributeList::FunctionIndex, B);
+ llvm::Function *Fn = cast<llvm::Function>(GV);
+ Fn->addFnAttr("stackrealign");
}
if (FD->hasAttr<AnyX86InterruptAttr>()) {
llvm::Function *Fn = cast<llvm::Function>(GV);
@@ -2443,7 +2439,7 @@ void WinX86_64TargetCodeGenInfo::setTargetAttributes(
}
}
- addStackProbeSizeTargetAttribute(D, GV, CGM);
+ addStackProbeTargetAttributes(D, GV, CGM);
}
}
@@ -2868,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);
@@ -2901,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()))
@@ -3271,7 +3267,7 @@ classifyReturnType(QualType RetTy) const {
if (RetTy->isIntegralOrEnumerationType() &&
RetTy->isPromotableIntegerType())
- return ABIArgInfo::getExtend();
+ return ABIArgInfo::getExtend(RetTy);
}
break;
@@ -3416,7 +3412,7 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(
if (Ty->isIntegralOrEnumerationType() &&
Ty->isPromotableIntegerType())
- return ABIArgInfo::getExtend();
+ return ABIArgInfo::getExtend(Ty);
}
break;
@@ -3543,14 +3539,24 @@ ABIArgInfo X86_64ABIInfo::classifyRegCallStructType(QualType Ty,
void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
- bool IsRegCall = FI.getCallingConvention() == llvm::CallingConv::X86_RegCall;
+ const unsigned CallingConv = FI.getCallingConvention();
+ // It is possible to force Win64 calling convention on any x86_64 target by
+ // using __attribute__((ms_abi)). In such case to correctly emit Win64
+ // compatible code delegate this call to WinX86_64ABIInfo::computeInfo.
+ if (CallingConv == llvm::CallingConv::Win64) {
+ WinX86_64ABIInfo Win64ABIInfo(CGT);
+ Win64ABIInfo.computeInfo(FI);
+ return;
+ }
+
+ bool IsRegCall = CallingConv == llvm::CallingConv::X86_RegCall;
// Keep track of the number of assigned registers.
unsigned FreeIntRegs = IsRegCall ? 11 : 6;
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() =
@@ -3797,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)));
@@ -3941,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.
@@ -4289,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,
@@ -4333,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;
@@ -4376,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 {
@@ -4543,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;
@@ -4603,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;
@@ -4618,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;
@@ -4694,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
@@ -4749,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.
@@ -4899,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())
@@ -4922,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);
}
@@ -5002,7 +5022,7 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty) const {
Ty = EnumTy->getDecl()->getIntegerType();
return (Ty->isPromotableIntegerType() && isDarwinPCS()
- ? ABIArgInfo::getExtend()
+ ? ABIArgInfo::getExtend(Ty)
: ABIArgInfo::getDirect());
}
@@ -5072,7 +5092,7 @@ ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy) const {
RetTy = EnumTy->getDecl()->getIntegerType();
return (RetTy->isPromotableIntegerType() && isDarwinPCS()
- ? ABIArgInfo::getExtend()
+ ? ABIArgInfo::getExtend(RetTy)
: ABIArgInfo::getDirect());
}
@@ -5521,8 +5541,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);
}
@@ -5565,9 +5584,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)
@@ -5610,8 +5628,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 {
@@ -5625,17 +5642,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());
@@ -5682,18 +5698,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,
@@ -5730,10 +5734,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());
@@ -5746,7 +5751,7 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty,
Ty = EnumTy->getDecl()->getIntegerType();
}
- return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend()
+ return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend(Ty)
: ABIArgInfo::getDirect());
}
@@ -5928,10 +5933,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());
@@ -5943,7 +5949,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();
}
@@ -6155,8 +6161,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
@@ -6176,8 +6182,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 {
@@ -6189,8 +6195,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 {
@@ -6212,9 +6218,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;
@@ -6279,6 +6284,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;
+}
}
//===----------------------------------------------------------------------===//
@@ -6313,8 +6322,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);
}
@@ -6402,7 +6410,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.
@@ -6586,8 +6594,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 {
@@ -6597,7 +6605,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
@@ -6651,16 +6659,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>()) {
@@ -6705,7 +6711,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 {
@@ -6720,8 +6726,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);
@@ -6732,7 +6737,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>()) {
@@ -6898,7 +6903,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));
@@ -6980,8 +6985,8 @@ ABIArgInfo MipsABIInfo::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());
}
void MipsABIInfo::computeInfo(CGFunctionInfo &FI) const {
@@ -7047,14 +7052,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
@@ -7096,9 +7101,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;
@@ -7127,14 +7131,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;
@@ -7227,8 +7229,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()))
@@ -7265,8 +7267,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))
@@ -7409,7 +7411,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();
@@ -7639,8 +7641,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,
@@ -7658,13 +7659,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)
@@ -7674,6 +7676,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;
@@ -7785,6 +7792,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.
@@ -7991,7 +8008,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))
@@ -8521,7 +8538,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) {
@@ -8565,7 +8582,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)
@@ -8780,6 +8797,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
@@ -8894,6 +9108,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/lib/CodeGen/TargetInfo.h b/lib/CodeGen/TargetInfo.h
index d745e420c4a5..b530260ea48f 100644
--- a/lib/CodeGen/TargetInfo.h
+++ b/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/lib/CodeGen/VarBypassDetector.cpp b/lib/CodeGen/VarBypassDetector.cpp
index cfb93d6a9fcc..2f8a591a3e7f 100644
--- a/lib/CodeGen/VarBypassDetector.cpp
+++ b/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/lib/Driver/Action.cpp b/lib/Driver/Action.cpp
index 85e466a4409d..99d588d9c009 100644
--- a/lib/Driver/Action.cpp
+++ b/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/lib/Driver/CMakeLists.txt b/lib/Driver/CMakeLists.txt
index 5bf91f2be981..471ffe0f1b00 100644
--- a/lib/Driver/CMakeLists.txt
+++ b/lib/Driver/CMakeLists.txt
@@ -25,6 +25,7 @@ add_clang_library(clangDriver
ToolChains/Arch/ARM.cpp
ToolChains/Arch/Mips.cpp
ToolChains/Arch/PPC.cpp
+ ToolChains/Arch/RISCV.cpp
ToolChains/Arch/Sparc.cpp
ToolChains/Arch/SystemZ.cpp
ToolChains/Arch/X86.cpp
@@ -44,6 +45,7 @@ add_clang_library(clangDriver
ToolChains/Fuchsia.cpp
ToolChains/Gnu.cpp
ToolChains/Haiku.cpp
+ ToolChains/HIP.cpp
ToolChains/Hexagon.cpp
ToolChains/Linux.cpp
ToolChains/MipsLinux.cpp
diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp
index 645da5059587..ca2525dd07fb 100644
--- a/lib/Driver/Compilation.cpp
+++ b/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/lib/Driver/Distro.cpp b/lib/Driver/Distro.cpp
index f15c919b9aae..2c4d44faf8d0 100644
--- a/lib/Driver/Distro.cpp
+++ b/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/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index 9ae33b80f889..1dfcacc75ea5 100644
--- a/lib/Driver/Driver.cpp
+++ b/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,15 +23,15 @@
#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"
@@ -57,17 +58,20 @@
#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"
#include "llvm/Option/OptTable.h"
#include "llvm/Option/Option.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#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 <map>
@@ -81,19 +85,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(""), 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)
@@ -103,6 +108,13 @@ Driver::Driver(StringRef ClangExecutable, StringRef DefaultTargetTriple,
Dir = llvm::sys::path::parent_path(ClangExecutable);
InstalledDir = Dir; // Provide a sensible default installed dir.
+#if defined(CLANG_CONFIG_FILE_SYSTEM_DIR)
+ SystemConfigDir = CLANG_CONFIG_FILE_SYSTEM_DIR;
+#endif
+#if defined(CLANG_CONFIG_FILE_USER_DIR)
+ UserConfigDir = CLANG_CONFIG_FILE_USER_DIR;
+#endif
+
// Compute the path to the resource directory.
StringRef ClangResourceDir(CLANG_RESOURCE_DIR);
SmallString<128> P(Dir);
@@ -119,11 +131,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;
@@ -138,15 +151,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;
}
@@ -178,9 +189,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;
}
@@ -195,11 +216,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;
}
@@ -256,11 +286,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;
}
@@ -328,7 +359,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;
}
@@ -353,23 +384,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;
@@ -452,7 +483,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;
@@ -508,24 +539,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(), 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(CudaTC.get(), Action::OFK_Cuda);
+ C.addOffloadDeviceToolChain(HIPTC.get(), OFK);
}
//
@@ -600,6 +662,216 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
//
}
+/// Looks the given directories for the specified file.
+///
+/// \param[out] FilePath File path, if the file was found.
+/// \param[in] Dirs Directories used for the search.
+/// \param[in] FileName Name of the file to search for.
+/// \return True if file was found.
+///
+/// Looks for file specified by FileName sequentially in directories specified
+/// by Dirs.
+///
+static bool searchForFile(SmallVectorImpl<char> &FilePath,
+ ArrayRef<std::string> Dirs,
+ StringRef FileName) {
+ SmallString<128> WPath;
+ for (const StringRef &Dir : Dirs) {
+ if (Dir.empty())
+ continue;
+ WPath.clear();
+ llvm::sys::path::append(WPath, Dir, FileName);
+ llvm::sys::path::native(WPath);
+ if (llvm::sys::fs::is_regular_file(WPath)) {
+ FilePath = std::move(WPath);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool Driver::readConfigFile(StringRef FileName) {
+ // Try reading the given file.
+ SmallVector<const char *, 32> NewCfgArgs;
+ if (!llvm::cl::readConfigFile(FileName, Saver, NewCfgArgs)) {
+ Diag(diag::err_drv_cannot_read_config_file) << FileName;
+ return true;
+ }
+
+ // Read options from config file.
+ llvm::SmallString<128> CfgFileName(FileName);
+ llvm::sys::path::native(CfgFileName);
+ ConfigFile = CfgFileName.str();
+ bool ContainErrors;
+ CfgOptions = llvm::make_unique<InputArgList>(
+ ParseArgStrings(NewCfgArgs, ContainErrors));
+ if (ContainErrors) {
+ CfgOptions.reset();
+ return true;
+ }
+
+ if (CfgOptions->hasArg(options::OPT_config)) {
+ CfgOptions.reset();
+ Diag(diag::err_drv_nested_config_file);
+ return true;
+ }
+
+ // Claim all arguments that come from a configuration file so that the driver
+ // does not warn on any that is unused.
+ for (Arg *A : *CfgOptions)
+ A->claim();
+ return false;
+}
+
+bool Driver::loadConfigFile() {
+ std::string CfgFileName;
+ bool FileSpecifiedExplicitly = false;
+
+ // Process options that change search path for config files.
+ if (CLOptions) {
+ if (CLOptions->hasArg(options::OPT_config_system_dir_EQ)) {
+ SmallString<128> CfgDir;
+ CfgDir.append(
+ CLOptions->getLastArgValue(options::OPT_config_system_dir_EQ));
+ if (!CfgDir.empty()) {
+ if (llvm::sys::fs::make_absolute(CfgDir).value() != 0)
+ SystemConfigDir.clear();
+ else
+ SystemConfigDir = std::string(CfgDir.begin(), CfgDir.end());
+ }
+ }
+ if (CLOptions->hasArg(options::OPT_config_user_dir_EQ)) {
+ SmallString<128> CfgDir;
+ CfgDir.append(
+ CLOptions->getLastArgValue(options::OPT_config_user_dir_EQ));
+ if (!CfgDir.empty()) {
+ if (llvm::sys::fs::make_absolute(CfgDir).value() != 0)
+ UserConfigDir.clear();
+ else
+ UserConfigDir = std::string(CfgDir.begin(), CfgDir.end());
+ }
+ }
+ }
+
+ // First try to find config file specified in command line.
+ if (CLOptions) {
+ std::vector<std::string> ConfigFiles =
+ CLOptions->getAllArgValues(options::OPT_config);
+ if (ConfigFiles.size() > 1) {
+ Diag(diag::err_drv_duplicate_config);
+ return true;
+ }
+
+ if (!ConfigFiles.empty()) {
+ CfgFileName = ConfigFiles.front();
+ assert(!CfgFileName.empty());
+
+ // If argument contains directory separator, treat it as a path to
+ // configuration file.
+ if (llvm::sys::path::has_parent_path(CfgFileName)) {
+ SmallString<128> CfgFilePath;
+ if (llvm::sys::path::is_relative(CfgFileName))
+ llvm::sys::fs::current_path(CfgFilePath);
+ llvm::sys::path::append(CfgFilePath, CfgFileName);
+ if (!llvm::sys::fs::is_regular_file(CfgFilePath)) {
+ Diag(diag::err_drv_config_file_not_exist) << CfgFilePath;
+ return true;
+ }
+ return readConfigFile(CfgFilePath);
+ }
+
+ FileSpecifiedExplicitly = true;
+ }
+ }
+
+ // If config file is not specified explicitly, try to deduce configuration
+ // from executable name. For instance, an executable 'armv7l-clang' will
+ // search for config file 'armv7l-clang.cfg'.
+ if (CfgFileName.empty() && !ClangNameParts.TargetPrefix.empty())
+ CfgFileName = ClangNameParts.TargetPrefix + '-' + ClangNameParts.ModeSuffix;
+
+ if (CfgFileName.empty())
+ return false;
+
+ // Determine architecture part of the file name, if it is present.
+ StringRef CfgFileArch = CfgFileName;
+ size_t ArchPrefixLen = CfgFileArch.find('-');
+ if (ArchPrefixLen == StringRef::npos)
+ ArchPrefixLen = CfgFileArch.size();
+ llvm::Triple CfgTriple;
+ CfgFileArch = CfgFileArch.take_front(ArchPrefixLen);
+ CfgTriple = llvm::Triple(llvm::Triple::normalize(CfgFileArch));
+ if (CfgTriple.getArch() == llvm::Triple::ArchType::UnknownArch)
+ ArchPrefixLen = 0;
+
+ if (!StringRef(CfgFileName).endswith(".cfg"))
+ CfgFileName += ".cfg";
+
+ // If config file starts with architecture name and command line options
+ // redefine architecture (with options like -m32 -LE etc), try finding new
+ // config file with that architecture.
+ SmallString<128> FixedConfigFile;
+ size_t FixedArchPrefixLen = 0;
+ if (ArchPrefixLen) {
+ // Get architecture name from config file name like 'i386.cfg' or
+ // 'armv7l-clang.cfg'.
+ // Check if command line options changes effective triple.
+ llvm::Triple EffectiveTriple = computeTargetTriple(*this,
+ CfgTriple.getTriple(), *CLOptions);
+ if (CfgTriple.getArch() != EffectiveTriple.getArch()) {
+ FixedConfigFile = EffectiveTriple.getArchName();
+ FixedArchPrefixLen = FixedConfigFile.size();
+ // Append the rest of original file name so that file name transforms
+ // like: i386-clang.cfg -> x86_64-clang.cfg.
+ if (ArchPrefixLen < CfgFileName.size())
+ FixedConfigFile += CfgFileName.substr(ArchPrefixLen);
+ }
+ }
+
+ // Prepare list of directories where config file is searched for.
+ SmallVector<std::string, 3> CfgFileSearchDirs;
+ CfgFileSearchDirs.push_back(UserConfigDir);
+ CfgFileSearchDirs.push_back(SystemConfigDir);
+ CfgFileSearchDirs.push_back(Dir);
+
+ // Try to find config file. First try file with corrected architecture.
+ llvm::SmallString<128> CfgFilePath;
+ if (!FixedConfigFile.empty()) {
+ if (searchForFile(CfgFilePath, CfgFileSearchDirs, FixedConfigFile))
+ return readConfigFile(CfgFilePath);
+ // If 'x86_64-clang.cfg' was not found, try 'x86_64.cfg'.
+ FixedConfigFile.resize(FixedArchPrefixLen);
+ FixedConfigFile.append(".cfg");
+ if (searchForFile(CfgFilePath, CfgFileSearchDirs, FixedConfigFile))
+ return readConfigFile(CfgFilePath);
+ }
+
+ // Then try original file name.
+ if (searchForFile(CfgFilePath, CfgFileSearchDirs, CfgFileName))
+ return readConfigFile(CfgFilePath);
+
+ // Finally try removing driver mode part: 'x86_64-clang.cfg' -> 'x86_64.cfg'.
+ if (!ClangNameParts.ModeSuffix.empty() &&
+ !ClangNameParts.TargetPrefix.empty()) {
+ CfgFileName.assign(ClangNameParts.TargetPrefix);
+ CfgFileName.append(".cfg");
+ if (searchForFile(CfgFilePath, CfgFileSearchDirs, CfgFileName))
+ return readConfigFile(CfgFilePath);
+ }
+
+ // Report error but only if config file was specified explicitly, by option
+ // --config. If it was deduced from executable name, it is not an error.
+ if (FileSpecifiedExplicitly) {
+ Diag(diag::err_drv_config_file_not_found) << CfgFileName;
+ for (const std::string &SearchDir : CfgFileSearchDirs)
+ if (!SearchDir.empty())
+ Diag(diag::note_drv_config_file_searched_in) << SearchDir;
+ return true;
+ }
+
+ return false;
+}
+
Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
llvm::PrettyStackTraceString CrashInfo("Compilation construction");
@@ -623,12 +895,38 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
// FIXME: What are we going to do with -V and -b?
+ // Arguments specified in command line.
+ bool ContainsError;
+ CLOptions = llvm::make_unique<InputArgList>(
+ ParseArgStrings(ArgList.slice(1), ContainsError));
+
+ // Try parsing configuration file.
+ if (!ContainsError)
+ ContainsError = loadConfigFile();
+ bool HasConfigFile = !ContainsError && (CfgOptions.get() != nullptr);
+
+ // All arguments, from both config file and command line.
+ InputArgList Args = std::move(HasConfigFile ? std::move(*CfgOptions)
+ : std::move(*CLOptions));
+ if (HasConfigFile)
+ for (auto *Opt : *CLOptions) {
+ if (Opt->getOption().matches(options::OPT_config))
+ continue;
+ unsigned Index = Args.MakeIndex(Opt->getSpelling());
+ const Arg *BaseArg = &Opt->getBaseArg();
+ if (BaseArg == Opt)
+ BaseArg = nullptr;
+ Arg *Copy = new llvm::opt::Arg(Opt->getOption(), Opt->getSpelling(),
+ Index, BaseArg);
+ Copy->getValues() = Opt->getValues();
+ if (Opt->isClaimed())
+ Copy->claim();
+ Args.append(Copy);
+ }
+
// FIXME: This stuff needs to go into the Compilation, not the driver.
bool CCCPrintPhases;
- bool ContainsError;
- InputArgList Args = ParseArgStrings(ArgList.slice(1), ContainsError);
-
// Silence driver warnings if requested
Diags.setIgnoreAllWarnings(Args.hasArg(options::OPT_w));
@@ -653,19 +951,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)) {
@@ -713,7 +1011,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,
@@ -851,8 +1149,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;
@@ -954,9 +1253,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;
@@ -978,6 +1274,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");
@@ -993,12 +1291,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: ";
@@ -1006,6 +1305,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;
}
@@ -1066,9 +1370,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;
@@ -1144,6 +1445,10 @@ void Driver::PrintVersion(const Compilation &C, raw_ostream &OS) const {
// Print out the install directory.
OS << "InstalledDir: " << InstalledDir << '\n';
+
+ // If configuration file was used, print its path.
+ if (!ConfigFile.empty())
+ OS << "Configuration file: " << ConfigFile << '\n';
}
/// PrintDiagnosticCategories - Implement the --print-diagnostic-categories
@@ -1155,53 +1460,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';
@@ -1250,6 +1568,15 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
SuppressMissingInputWarning = true;
}
+ if (C.getArgs().hasArg(options::OPT_v)) {
+ if (!SystemConfigDir.empty())
+ llvm::errs() << "System configuration file directory: "
+ << SystemConfigDir << "\n";
+ if (!UserConfigDir.empty())
+ llvm::errs() << "User configuration file directory: "
+ << UserConfigDir << "\n";
+ }
+
const ToolChain &TC = C.getDefaultToolChain();
if (C.getArgs().hasArg(options::OPT_v))
@@ -1295,13 +1622,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;
}
@@ -1427,7 +1760,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) ||
@@ -1528,7 +1861,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) {
@@ -1823,9 +2156,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;
@@ -1842,115 +2176,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
@@ -1963,9 +2193,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;
@@ -1978,10 +2209,24 @@ 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;
}
@@ -1993,7 +2238,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()));
};
@@ -2022,21 +2267,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,
@@ -2089,6 +2348,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 {
@@ -2255,6 +2695,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));
@@ -2549,22 +2992,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);
@@ -2597,6 +3024,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();
@@ -2631,11 +3061,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);
@@ -2643,6 +3071,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.
}
}
@@ -2725,8 +3155,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
@@ -2788,7 +3219,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);
@@ -3084,19 +3515,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();
@@ -3312,7 +3758,7 @@ InputInfo Driver::BuildJobsForActionNoCache(
if (!ArchName.empty())
TC = &getToolChain(C.getArgs(),
- computeTargetTriple(*this, DefaultTargetTriple,
+ computeTargetTriple(*this, TargetTriple,
C.getArgs(), ArchName));
else
TC = &C.getDefaultToolChain();
@@ -3407,18 +3853,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
@@ -3478,11 +3936,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.
@@ -3540,8 +3998,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?
@@ -3562,8 +4019,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));
}
@@ -3717,14 +4188,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,
@@ -3795,6 +4266,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");
diff --git a/lib/Driver/Job.cpp b/lib/Driver/Job.cpp
index 765c05752d8f..bd1a9bd8e3eb 100644
--- a/lib/Driver/Job.cpp
+++ b/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/lib/Driver/Multilib.cpp b/lib/Driver/Multilib.cpp
index 16a81603b31e..178a60db60e5 100644
--- a/lib/Driver/Multilib.cpp
+++ b/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/lib/Driver/SanitizerArgs.cpp b/lib/Driver/SanitizerArgs.cpp
index 3c985a1f71d7..bdc17d11c92b 100644
--- a/lib/Driver/SanitizerArgs.cpp
+++ b/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;
@@ -30,20 +31,22 @@ enum : SanitizerMask {
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,
+ SupportsCoverage = Address | HWAddress | KernelAddress | KernelHWAddress |
+ Memory | Leak | Undefined | Integer | Nullability |
+ DataFlow | Fuzzer | FuzzerNoLink,
RecoverableByDefault = Undefined | Integer | Nullability,
Unrecoverable = Unreachable | Return,
+ AlwaysRecoverable = KernelAddress | KernelHWAddress,
LegacyFsanitizeRecoverMask = Undefined | Integer,
NeedsLTO = CFI,
TrappingSupported = (Undefined & ~Vptr) | UnsignedIntegerOverflow |
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/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp
index f96a1182e3ca..d62ba1253348 100644
--- a/lib/Driver/ToolChain.cpp
+++ b/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;
}
@@ -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,7 +799,9 @@ 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;
@@ -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/lib/Driver/ToolChains/AMDGPU.cpp b/lib/Driver/ToolChains/AMDGPU.cpp
index a313bc5c35de..6b673feeadfc 100644
--- a/lib/Driver/ToolChains/AMDGPU.cpp
+++ b/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/lib/Driver/ToolChains/Ananas.cpp b/lib/Driver/ToolChains/Ananas.cpp
index ee072cc03e7c..006fdc029ef8 100644
--- a/lib/Driver/ToolChains/Ananas.cpp
+++ b/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/lib/Driver/ToolChains/Arch/AArch64.cpp b/lib/Driver/ToolChains/Arch/AArch64.cpp
index ad04aedd098e..5114279b4b45 100644
--- a/lib/Driver/ToolChains/Arch/AArch64.cpp
+++ b/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/lib/Driver/ToolChains/Arch/ARM.cpp b/lib/Driver/ToolChains/Arch/ARM.cpp
index 44c8871d0e1f..886d947c586b 100644
--- a/lib/Driver/ToolChains/Arch/ARM.cpp
+++ b/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/lib/Driver/ToolChains/Arch/Mips.cpp b/lib/Driver/ToolChains/Arch/Mips.cpp
index 61481a92d0b7..6d814631d05f 100644
--- a/lib/Driver/ToolChains/Arch/Mips.cpp
+++ b/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,34 @@ 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());
+ if (Val == "hazard") {
+ Arg *B =
+ Args.getLastArg(options::OPT_mmicromips, options::OPT_mno_micromips);
+ Arg *C = Args.getLastArg(options::OPT_mips16, options::OPT_mno_mips16);
+
+ if (B && B->getOption().matches(options::OPT_mmicromips))
+ D.Diag(diag::err_drv_unsupported_indirect_jump_opt)
+ << "hazard" << "micromips";
+ else if (C && C->getOption().matches(options::OPT_mips16))
+ D.Diag(diag::err_drv_unsupported_indirect_jump_opt)
+ << "hazard" << "mips16";
+ else if (mips::supportsIndirectJumpHazardBarrier(CPUName))
+ Features.push_back("+use-indirect-jump-hazard");
+ else
+ D.Diag(diag::err_drv_unsupported_indirect_jump_opt)
+ << "hazard" << CPUName;
+ } else
+ D.Diag(diag::err_drv_unknown_indirect_jump_opt) << Val;
+ }
}
mips::IEEE754Standard mips::getIEEE754Standard(StringRef &CPU) {
@@ -447,3 +482,20 @@ bool mips::shouldUseFPXX(const ArgList &Args, const llvm::Triple &Triple,
return UseFPXX;
}
+
+bool mips::supportsIndirectJumpHazardBarrier(StringRef &CPU) {
+ // Supporting the hazard barrier method of dealing with indirect
+ // jumps requires MIPSR2 support.
+ return llvm::StringSwitch<bool>(CPU)
+ .Case("mips32r2", true)
+ .Case("mips32r3", true)
+ .Case("mips32r5", true)
+ .Case("mips32r6", true)
+ .Case("mips64r2", true)
+ .Case("mips64r3", true)
+ .Case("mips64r5", true)
+ .Case("mips64r6", true)
+ .Case("octeon", true)
+ .Case("p5600", true)
+ .Default(false);
+}
diff --git a/lib/Driver/ToolChains/Arch/Mips.h b/lib/Driver/ToolChains/Arch/Mips.h
index 89eea9a1514c..a232ddbc8f3d 100644
--- a/lib/Driver/ToolChains/Arch/Mips.h
+++ b/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;
@@ -53,6 +51,7 @@ bool isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName,
bool shouldUseFPXX(const llvm::opt::ArgList &Args, const llvm::Triple &Triple,
StringRef CPUName, StringRef ABIName,
mips::FloatABI FloatABI);
+bool supportsIndirectJumpHazardBarrier(StringRef &CPU);
} // end namespace mips
} // end namespace target
diff --git a/lib/Driver/ToolChains/Arch/PPC.cpp b/lib/Driver/ToolChains/Arch/PPC.cpp
index 7c7e1c70e550..f6a95962ace3 100644
--- a/lib/Driver/ToolChains/Arch/PPC.cpp
+++ b/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/lib/Driver/ToolChains/Arch/PPC.h b/lib/Driver/ToolChains/Arch/PPC.h
index 7d7c68101b7b..3acee91a2ac3 100644
--- a/lib/Driver/ToolChains/Arch/PPC.h
+++ b/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/lib/Driver/ToolChains/Arch/RISCV.cpp b/lib/Driver/ToolChains/Arch/RISCV.cpp
new file mode 100644
index 000000000000..11ce8a1fd769
--- /dev/null
+++ b/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/lib/Driver/ToolChains/Arch/RISCV.h b/lib/Driver/ToolChains/Arch/RISCV.h
new file mode 100644
index 000000000000..beda14979fab
--- /dev/null
+++ b/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/lib/Driver/ToolChains/Arch/Sparc.cpp b/lib/Driver/ToolChains/Arch/Sparc.cpp
index 594ec9986d8e..c177031b9f75 100644
--- a/lib/Driver/ToolChains/Arch/Sparc.cpp
+++ b/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/lib/Driver/ToolChains/Arch/X86.cpp b/lib/Driver/ToolChains/Arch/X86.cpp
index a18b2aa35b03..7a4f836d2e1a 100644
--- a/lib/Driver/ToolChains/Arch/X86.cpp
+++ b/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/lib/Driver/ToolChains/BareMetal.cpp b/lib/Driver/ToolChains/BareMetal.cpp
index 57a668650e6b..c302d647b973 100644
--- a/lib/Driver/ToolChains/BareMetal.cpp
+++ b/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/lib/Driver/ToolChains/BareMetal.h b/lib/Driver/ToolChains/BareMetal.h
index 0bed63332cad..43a6a8b4bec3 100644
--- a/lib/Driver/ToolChains/BareMetal.h
+++ b/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/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp
index 8b895c4514c4..eaff940a1c2b 100644
--- a/lib/Driver/ToolChains/Clang.cpp
+++ b/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;
@@ -1064,73 +1076,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 +1249,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 +1260,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 +1309,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 +1362,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 +1423,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 +1644,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 +1717,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 +2041,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 +2200,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 +2340,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 +2462,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 +2510,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 +2531,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 +2623,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 +2646,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)) {
@@ -2919,7 +2936,7 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
// Forward -gcodeview. EmitCodeView might have been set by CL-compatibility
// argument parsing.
- if (Args.hasArg(options::OPT_gcodeview) || EmitCodeView) {
+ if (EmitCodeView) {
// DWARFVersion remains at 0 if no explicit choice was made.
CmdArgs.push_back("-gcodeview");
} else if (DWARFVersion == 0 &&
@@ -2937,7 +2954,7 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
// debuggers don't handle missing end columns well, so it's better not to
// include any column info.
if (Args.hasFlag(options::OPT_gcolumn_info, options::OPT_gno_column_info,
- /*Default=*/!(IsWindowsMSVC && EmitCodeView) &&
+ /*Default=*/!EmitCodeView &&
DebuggerTuning != llvm::DebuggerKind::SCE))
CmdArgs.push_back("-dwarf-column-info");
@@ -2975,6 +2992,18 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
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.
+ if (DWARFVersion < 5)
+ D.Diag(diag::err_drv_argument_only_allowed_with)
+ << Args.getLastArg(options::OPT_gembed_source)->getAsString(Args)
+ << "-gdwarf-5";
+ CmdArgs.push_back("-gembed-source");
+ }
+
RenderDebugEnablingArgs(Args, CmdArgs, DebugInfoKind, DWARFVersion,
DebuggerTuning);
@@ -2984,7 +3013,8 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
CmdArgs.push_back("-debug-info-macro");
// -ggnu-pubnames turns on gnu style pubnames in the backend.
- if (Args.hasArg(options::OPT_ggnu_pubnames))
+ if (Args.hasFlag(options::OPT_ggnu_pubnames, options::OPT_gno_gnu_pubnames,
+ false))
CmdArgs.push_back("-ggnu-pubnames");
// -gdwarf-aranges turns on the emission of the aranges section in the
@@ -2992,13 +3022,18 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
// Always enabled for SCE tuning.
if (Args.hasArg(options::OPT_gdwarf_aranges) ||
DebuggerTuning == llvm::DebuggerKind::SCE) {
- CmdArgs.push_back("-backend-option");
+ 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");
+ if (!T.isOSBinFormatELF())
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << Args.getLastArg(options::OPT_fdebug_types_section)
+ ->getAsString(Args)
+ << T.getTriple();
+ CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-generate-type-units");
}
@@ -3029,13 +3064,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 +3083,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 +3110,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 +3227,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 +3250,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 +3270,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 +3300,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;
@@ -3288,9 +3349,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fveclib);
- if (!Args.hasFlag(options::OPT_fmerge_all_constants,
- options::OPT_fno_merge_all_constants))
- CmdArgs.push_back("-fno-merge-all-constants");
+ if (Args.hasFlag(options::OPT_fmerge_all_constants,
+ 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.
@@ -3382,9 +3447,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 +3476,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 +3569,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 +3656,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 +3736,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 +3825,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 +3875,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 +3938,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 +3968,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
@@ -3901,6 +3986,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// semantic analysis, etc.
break;
}
+ } else {
+ Args.AddLastArg(CmdArgs, options::OPT_fopenmp_simd,
+ options::OPT_fno_openmp_simd);
+ Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_version_EQ);
}
const SanitizerArgs &Sanitize = getToolChain().getSanitizerArgs();
@@ -3980,26 +4069,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)) {
@@ -4058,8 +4156,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.
@@ -4081,6 +4178,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))
@@ -4147,7 +4249,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.
@@ -4292,6 +4394,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,
@@ -4473,31 +4578,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.
@@ -4584,14 +4667,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
@@ -4607,7 +4698,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);
@@ -4635,6 +4726,71 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fwhole-program-vtables");
}
+ if (Arg *A = Args.getLastArg(options::OPT_fexperimental_isel,
+ options::OPT_fno_experimental_isel)) {
+ CmdArgs.push_back("-mllvm");
+ if (A->getOption().matches(options::OPT_fexperimental_isel)) {
+ CmdArgs.push_back("-global-isel=1");
+
+ // GISel is on by default on AArch64 -O0, so don't bother adding
+ // the fallback remarks for it. Other combinations will add a warning of
+ // some kind.
+ bool IsArchSupported = Triple.getArch() == llvm::Triple::aarch64;
+ bool IsOptLevelSupported = false;
+
+ Arg *A = Args.getLastArg(options::OPT_O_Group);
+ if (Triple.getArch() == llvm::Triple::aarch64) {
+ if (!A || A->getOption().matches(options::OPT_O0))
+ IsOptLevelSupported = true;
+ }
+ if (!IsArchSupported || !IsOptLevelSupported) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-global-isel-abort=2");
+
+ if (!IsArchSupported)
+ D.Diag(diag::warn_drv_experimental_isel_incomplete) << Triple.getArchName();
+ else
+ D.Diag(diag::warn_drv_experimental_isel_incomplete_opt);
+ }
+ } else {
+ CmdArgs.push_back("-global-isel=0");
+ }
+ }
+
+ 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 &&
@@ -4653,12 +4809,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"
@@ -4709,6 +4859,13 @@ 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().getDriver().Diag(
+ diag::err_drv_gnustep_objc_runtime_incompatible_binary)
+ << runtime.getVersion().getMajor();
+ }
runtimeArg->render(args, cmdArgs);
return runtime;
@@ -4802,7 +4959,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());
}
@@ -4930,13 +5087,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,
@@ -5066,6 +5218,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 {
@@ -5220,6 +5376,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");
@@ -5316,19 +5474,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
@@ -5379,6 +5535,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));
@@ -5448,6 +5608,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/lib/Driver/ToolChains/Clang.h b/lib/Driver/ToolChains/Clang.h
index e23822b9c678..df67fb2cb331 100644
--- a/lib/Driver/ToolChains/Clang.h
+++ b/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/lib/Driver/ToolChains/CloudABI.cpp b/lib/Driver/ToolChains/CloudABI.cpp
index cdf807f7f91f..80f9fc493fd8 100644
--- a/lib/Driver/ToolChains/CloudABI.cpp
+++ b/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/lib/Driver/ToolChains/CloudABI.h b/lib/Driver/ToolChains/CloudABI.h
index a284eb3dc0a4..7464c5954555 100644
--- a/lib/Driver/ToolChains/CloudABI.h
+++ b/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/lib/Driver/ToolChains/CommonArgs.cpp b/lib/Driver/ToolChains/CommonArgs.cpp
index f26880123d8c..1e093b25b909 100644
--- a/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/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/lib/Driver/ToolChains/CommonArgs.h b/lib/Driver/ToolChains/CommonArgs.h
index 012f5b9f87ae..e8ebe2225e1c 100644
--- a/lib/Driver/ToolChains/CommonArgs.h
+++ b/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/lib/Driver/ToolChains/Contiki.h b/lib/Driver/ToolChains/Contiki.h
index f6e15073887b..86d59ac92b16 100644
--- a/lib/Driver/ToolChains/Contiki.h
+++ b/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/lib/Driver/ToolChains/CrossWindows.cpp b/lib/Driver/ToolChains/CrossWindows.cpp
index 5049033c4137..6ca04a8a3abb 100644
--- a/lib/Driver/ToolChains/CrossWindows.cpp
+++ b/lib/Driver/ToolChains/CrossWindows.cpp
@@ -127,7 +127,8 @@ void tools::CrossWindows::Linker::ConstructJob(
}
CmdArgs.push_back("-shared");
- CmdArgs.push_back("-Bdynamic");
+ CmdArgs.push_back(Args.hasArg(options::OPT_static) ? "-Bstatic"
+ : "-Bdynamic");
CmdArgs.push_back("--enable-auto-image-base");
diff --git a/lib/Driver/ToolChains/Cuda.cpp b/lib/Driver/ToolChains/Cuda.cpp
index bc4820797b2f..d17c4c39532a 100644
--- a/lib/Driver/ToolChains/Cuda.cpp
+++ b/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,16 +624,58 @@ 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;
}
}
diff --git a/lib/Driver/ToolChains/Cuda.h b/lib/Driver/ToolChains/Cuda.h
index 3d08cec1643e..99d5a4a628ce 100644
--- a/lib/Driver/ToolChains/Cuda.h
+++ b/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; }
@@ -180,6 +180,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/lib/Driver/ToolChains/Darwin.cpp b/lib/Driver/ToolChains/Darwin.cpp
index 2250e82d9dbf..95ec8d64c2c7 100644
--- a/lib/Driver/ToolChains/Darwin.cpp
+++ b/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");
}
}
@@ -895,13 +916,26 @@ unsigned DarwinClang::GetDefaultDwarfVersion() const {
return 4;
}
+SmallString<128> MachO::runtimeLibDir(bool IsEmbedded) const {
+ SmallString<128> Dir(getDriver().ResourceDir);
+ llvm::sys::path::append(
+ Dir, "lib", IsEmbedded ? "macho_embedded" : "darwin");
+ return Dir;
+}
+
+std::string Darwin::getFileNameForSanitizerLib(StringRef SanitizerName,
+ bool Shared) const {
+ return (Twine("libclang_rt.") + SanitizerName + "_" +
+ getOSLibraryNameSuffix() +
+ (Shared ? "_dynamic.dylib" : ".a")).str();
+
+}
+
void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs,
StringRef DarwinLibName,
RuntimeLinkOptions Opts) const {
- SmallString<128> Dir(getDriver().ResourceDir);
- llvm::sys::path::append(
- Dir, "lib", (Opts & RLO_IsEmbedded) ? "macho_embedded" : "darwin");
+ SmallString<128> Dir = runtimeLibDir(Opts & RLO_IsEmbedded);
SmallString<128> P(Dir);
llvm::sys::path::append(P, DarwinLibName);
@@ -979,6 +1013,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 +1044,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");
@@ -1020,12 +1055,9 @@ void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args,
StringRef Sanitizer,
bool Shared) const {
auto RLO = RuntimeLinkOptions(RLO_AlwaysLink | (Shared ? RLO_AddRPath : 0U));
- AddLinkRuntimeLib(Args, CmdArgs,
- (Twine("libclang_rt.") + Sanitizer + "_" +
- getOSLibraryNameSuffix() +
- (Shared ? "_dynamic.dylib" : ".a"))
- .str(),
- RLO);
+ std::string SanitizerRelFilename =
+ getFileNameForSanitizerLib(Sanitizer, Shared);
+ AddLinkRuntimeLib(Args, CmdArgs, SanitizerRelFilename, RLO);
}
ToolChain::RuntimeLibType DarwinClang::GetRuntimeLibType(
@@ -1186,15 +1218,30 @@ struct DarwinPlatform {
DarwinEnvironmentKind getEnvironment() const { return Environment; }
+ void setEnvironment(DarwinEnvironmentKind Kind) {
+ Environment = Kind;
+ InferSimulatorFromArch = false;
+ }
+
StringRef getOSVersion() const {
if (Kind == OSVersionArg)
return Argument->getValue();
return OSVersion;
}
+ void setOSVersion(StringRef S) {
+ assert(Kind == TargetArg && "Unexpected kind!");
+ OSVersion = S;
+ }
+
+ bool hasOSVersion() const { return HasOSVersion; }
+
/// 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)
@@ -1235,17 +1282,21 @@ struct DarwinPlatform {
llvm_unreachable("Unsupported Darwin Source Kind");
}
- static DarwinPlatform createFromTarget(llvm::Triple::OSType OS,
- StringRef OSVersion, Arg *A,
- llvm::Triple::EnvironmentType Env) {
- DarwinPlatform Result(TargetArg, getPlatformFromOS(OS), OSVersion, A);
- switch (Env) {
+ static DarwinPlatform createFromTarget(const llvm::Triple &TT,
+ StringRef OSVersion, Arg *A) {
+ DarwinPlatform Result(TargetArg, getPlatformFromOS(TT.getOS()), OSVersion,
+ A);
+ switch (TT.getEnvironment()) {
case llvm::Triple::Simulator:
Result.Environment = DarwinEnvironmentKind::Simulator;
break;
default:
break;
}
+ unsigned Major, Minor, Micro;
+ TT.getOSVersion(Major, Minor, Micro);
+ if (Major == 0)
+ Result.HasOSVersion = false;
return Result;
}
static DarwinPlatform createOSVersionArg(DarwinPlatformKind Platform,
@@ -1260,8 +1311,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) {
@@ -1295,6 +1351,7 @@ private:
DarwinPlatformKind Platform;
DarwinEnvironmentKind Environment = DarwinEnvironmentKind::NativeEnvironment;
std::string OSVersion;
+ bool HasOSVersion = true, InferSimulatorFromArch = true;
Arg *Argument;
StringRef EnvVarName;
};
@@ -1416,14 +1473,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;
}
@@ -1431,10 +1494,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;
@@ -1489,9 +1558,8 @@ Optional<DarwinPlatform> getDeploymentTargetFromTargetArg(
Triple.getOS() == llvm::Triple::UnknownOS)
return None;
std::string OSVersion = getOSVersion(Triple.getOS(), Triple, TheDriver);
- return DarwinPlatform::createFromTarget(Triple.getOS(), OSVersion,
- Args.getLastArg(options::OPT_target),
- Triple.getEnvironment());
+ return DarwinPlatform::createFromTarget(Triple, OSVersion,
+ Args.getLastArg(options::OPT_target));
}
} // namespace
@@ -1537,12 +1605,20 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
(VersionTuple(TargetMajor, TargetMinor, TargetMicro) !=
VersionTuple(ArgMajor, ArgMinor, ArgMicro) ||
TargetExtra != ArgExtra))) {
- // Warn about -m<os>-version-min that doesn't match the OS version
- // that's specified in the target.
- std::string OSVersionArg = OSVersionArgTarget->getAsString(Args, Opts);
- std::string TargetArg = OSTarget->getAsString(Args, Opts);
- getDriver().Diag(clang::diag::warn_drv_overriding_flag_option)
- << OSVersionArg << TargetArg;
+ // Select the OS version from the -m<os>-version-min argument when
+ // the -target does not include an OS version.
+ if (OSTarget->getPlatform() == OSVersionArgTarget->getPlatform() &&
+ !OSTarget->hasOSVersion()) {
+ OSTarget->setOSVersion(OSVersionArgTarget->getOSVersion());
+ } else {
+ // Warn about -m<os>-version-min that doesn't match the OS version
+ // that's specified in the target.
+ std::string OSVersionArg =
+ OSVersionArgTarget->getAsString(Args, Opts);
+ std::string TargetArg = OSTarget->getAsString(Args, Opts);
+ getDriver().Diag(clang::diag::warn_drv_overriding_flag_option)
+ << OSVersionArg << TargetArg;
+ }
}
}
} else {
@@ -1550,9 +1626,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.
@@ -1617,6 +1700,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;
@@ -2211,24 +2295,43 @@ void Darwin::CheckObjCARC() const {
SanitizerMask Darwin::getSupportedSanitizers() const {
const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
SanitizerMask Res = ToolChain::getSupportedSanitizers();
- Res |= SanitizerKind::Address;
- Res |= SanitizerKind::Leak;
- Res |= SanitizerKind::Fuzzer;
- Res |= SanitizerKind::FuzzerNoLink;
+
+ {
+ using namespace SanitizerKind;
+ assert(!(Res & (Address | Leak | Fuzzer | FuzzerNoLink | Thread)) &&
+ "Sanitizer is already registered as supported");
+ }
+
+ if (sanitizerRuntimeExists("asan"))
+ Res |= SanitizerKind::Address;
+ if (sanitizerRuntimeExists("lsan"))
+ Res |= SanitizerKind::Leak;
+ if (sanitizerRuntimeExists("fuzzer", /*Shared=*/false)) {
+ Res |= SanitizerKind::Fuzzer;
+ Res |= SanitizerKind::FuzzerNoLink;
+ }
Res |= SanitizerKind::Function;
- if (isTargetMacOS()) {
- if (!isMacosxVersionLT(10, 9))
- Res |= SanitizerKind::Vptr;
+ if (isTargetMacOS() && !isMacosxVersionLT(10, 9))
+ Res |= SanitizerKind::Vptr;
+ if (isTargetMacOS())
Res |= SanitizerKind::SafeStack;
- if (IsX86_64)
- Res |= SanitizerKind::Thread;
- } else if (isTargetIOSSimulator() || isTargetTvOSSimulator()) {
- if (IsX86_64)
- Res |= SanitizerKind::Thread;
- }
+
+ if (sanitizerRuntimeExists("tsan") && IsX86_64 &&
+ (isTargetMacOS() || isTargetIOSSimulator() || isTargetTvOSSimulator()))
+ Res |= SanitizerKind::Thread;
+
return Res;
}
void Darwin::printVerboseInfo(raw_ostream &OS) const {
CudaInstallation.print(OS);
}
+
+bool Darwin::sanitizerRuntimeExists(StringRef SanitizerName,
+ bool Shared) const {
+ std::string RelName = getFileNameForSanitizerLib(SanitizerName, Shared);
+ SmallString<128> Dir = runtimeLibDir();
+ SmallString<128> AbsName(Dir);
+ llvm::sys::path::append(AbsName, RelName);
+ return getVFS().exists(AbsName);
+}
diff --git a/lib/Driver/ToolChains/Darwin.h b/lib/Driver/ToolChains/Darwin.h
index 87d553bd7e0b..eee6e966718b 100644
--- a/lib/Driver/ToolChains/Darwin.h
+++ b/lib/Driver/ToolChains/Darwin.h
@@ -130,6 +130,9 @@ protected:
Tool *buildLinker() const override;
Tool *getTool(Action::ActionClass AC) const override;
+ /// \return Directory to find the runtime library in.
+ SmallString<128> runtimeLibDir(bool IsEmbedded=false) const;
+
private:
mutable std::unique_ptr<tools::darwin::Lipo> Lipo;
mutable std::unique_ptr<tools::darwin::Dsymutil> Dsymutil;
@@ -251,7 +254,6 @@ public:
GetExceptionModel(const llvm::opt::ArgList &Args) const override {
return llvm::ExceptionHandling::None;
}
-
/// }
};
@@ -420,6 +422,11 @@ protected:
StringRef getPlatformFamily() const;
StringRef getOSLibraryNameSuffix() const;
+ /// \return Relative path to the filename for the library
+ /// containing the sanitizer {@code SanitizerName}.
+ std::string getFileNameForSanitizerLib(StringRef SanitizerName,
+ bool Shared = true) const;
+
public:
static StringRef getSDKName(StringRef isysroot);
@@ -473,6 +480,12 @@ public:
SanitizerMask getSupportedSanitizers() const override;
void printVerboseInfo(raw_ostream &OS) const override;
+
+private:
+ /// \return Whether the runtime corresponding to the given
+ /// sanitizer exists in the toolchain.
+ bool sanitizerRuntimeExists(StringRef SanitizerName,
+ bool Shared = true) const;
};
/// DarwinClang - The Darwin toolchain used by Clang.
diff --git a/lib/Driver/ToolChains/FreeBSD.cpp b/lib/Driver/ToolChains/FreeBSD.cpp
index dd0334b9c28b..c16eabf06961 100644
--- a/lib/Driver/ToolChains/FreeBSD.cpp
+++ b/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/lib/Driver/ToolChains/Fuchsia.cpp b/lib/Driver/ToolChains/Fuchsia.cpp
index 269d34d18f1e..54c34ff159b1 100644
--- a/lib/Driver/ToolChains/Fuchsia.cpp
+++ b/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/lib/Driver/ToolChains/Fuchsia.h b/lib/Driver/ToolChains/Fuchsia.h
index 6f438deca7ff..e61eddc2aad1 100644
--- a/lib/Driver/ToolChains/Fuchsia.h
+++ b/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/lib/Driver/ToolChains/Gnu.cpp b/lib/Driver/ToolChains/Gnu.cpp
index 7845781f12c4..2c83598f3d77 100644
--- a/lib/Driver/ToolChains/Gnu.cpp
+++ b/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,10 @@ 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"};
+
static const char *const SPARCv8LibDirs[] = {"/lib32", "/lib"};
static const char *const SPARCv8Triples[] = {"sparc-linux-gnu",
"sparcv8-linux-gnu"};
@@ -1795,17 +1891,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 +2058,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 +2071,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 +2093,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 +2131,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 +2143,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 +2164,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 +2176,33 @@ 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},
+
+ // 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 +2240,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 +2268,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 +2405,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 +2434,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 +2444,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 +2459,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,
@@ -2375,6 +2544,8 @@ void Generic_ELF::addClangTargetOptions(const ArgList &DriverArgs,
bool UseInitArrayDefault =
getTriple().getArch() == llvm::Triple::aarch64 ||
getTriple().getArch() == llvm::Triple::aarch64_be ||
+ (getTriple().getOS() == llvm::Triple::FreeBSD &&
+ getTriple().getOSMajorVersion() >= 12) ||
(getTriple().getOS() == llvm::Triple::Linux &&
((!GCCInstallation.isValid() || !V.isOlderThan(4, 7, 0)) ||
getTriple().isAndroid())) ||
diff --git a/lib/Driver/ToolChains/Gnu.h b/lib/Driver/ToolChains/Gnu.h
index f29342b95a07..e8e74e4d80fd 100644
--- a/lib/Driver/ToolChains/Gnu.h
+++ b/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/lib/Driver/ToolChains/HIP.cpp b/lib/Driver/ToolChains/HIP.cpp
new file mode 100644
index 000000000000..03acf45a9b31
--- /dev/null
+++ b/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/lib/Driver/ToolChains/HIP.h b/lib/Driver/ToolChains/HIP.h
new file mode 100644
index 000000000000..40c9128e2f59
--- /dev/null
+++ b/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/lib/Driver/ToolChains/Haiku.cpp b/lib/Driver/ToolChains/Haiku.cpp
index 284d269a0c1b..12461ec9c4bd 100644
--- a/lib/Driver/ToolChains/Haiku.cpp
+++ b/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/lib/Driver/ToolChains/Haiku.h b/lib/Driver/ToolChains/Haiku.h
index 8b5b48e59023..a12a48e00976 100644
--- a/lib/Driver/ToolChains/Haiku.h
+++ b/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/lib/Driver/ToolChains/Hexagon.cpp b/lib/Driver/ToolChains/Hexagon.cpp
index 2debf0e2de54..c2b27b6d9ac6 100644
--- a/lib/Driver/ToolChains/Hexagon.cpp
+++ b/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,16 +36,10 @@ 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();
- if (Val != "64B" && Val != "128B")
+ if (!Val.equals_lower("64b") && !Val.equals_lower("128b"))
D.Diag(diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Val;
}
@@ -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/lib/Driver/ToolChains/Hexagon.h b/lib/Driver/ToolChains/Hexagon.h
index 229a08c76dfb..e43b8a5b8800 100644
--- a/lib/Driver/ToolChains/Hexagon.h
+++ b/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/lib/Driver/ToolChains/Lanai.h b/lib/Driver/ToolChains/Lanai.h
index 4ce658dc7775..bb92bfaea7e2 100644
--- a/lib/Driver/ToolChains/Lanai.h
+++ b/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/lib/Driver/ToolChains/Linux.cpp b/lib/Driver/ToolChains/Linux.cpp
index 1301cdf114ae..d27f994d32ab 100644
--- a/lib/Driver/ToolChains/Linux.cpp
+++ b/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,28 @@ 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);
+ 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 +438,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 +539,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 +547,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 +568,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 +763,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 +808,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 +903,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 +918,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 +927,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/lib/Driver/ToolChains/Linux.h b/lib/Driver/ToolChains/Linux.h
index 9778c1832ccc..22dbbecf6b96 100644
--- a/lib/Driver/ToolChains/Linux.h
+++ b/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/lib/Driver/ToolChains/MSVC.cpp b/lib/Driver/ToolChains/MSVC.cpp
index ae41ee9e22cf..d062c6abc955 100644
--- a/lib/Driver/ToolChains/MSVC.cpp
+++ b/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/lib/Driver/ToolChains/MSVC.h b/lib/Driver/ToolChains/MSVC.h
index 854f88a36fd2..1db589ec9706 100644
--- a/lib/Driver/ToolChains/MSVC.h
+++ b/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/lib/Driver/ToolChains/MinGW.cpp b/lib/Driver/ToolChains/MinGW.cpp
index 572ea803f2dc..a88e00f0c8e8 100644
--- a/lib/Driver/ToolChains/MinGW.cpp
+++ b/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");
}
@@ -141,22 +141,21 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("console");
}
+ if (Args.hasArg(options::OPT_mdll))
+ CmdArgs.push_back("--dll");
+ else if (Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back("--shared");
if (Args.hasArg(options::OPT_static))
CmdArgs.push_back("-Bstatic");
- else {
- if (Args.hasArg(options::OPT_mdll))
- CmdArgs.push_back("--dll");
- else if (Args.hasArg(options::OPT_shared))
- CmdArgs.push_back("--shared");
+ else
CmdArgs.push_back("-Bdynamic");
- if (Args.hasArg(options::OPT_mdll) || Args.hasArg(options::OPT_shared)) {
- CmdArgs.push_back("-e");
- if (TC.getArch() == llvm::Triple::x86)
- CmdArgs.push_back("_DllMainCRTStartup@12");
- else
- CmdArgs.push_back("DllMainCRTStartup");
- CmdArgs.push_back("--enable-auto-image-base");
- }
+ if (Args.hasArg(options::OPT_mdll) || Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back("-e");
+ if (TC.getArch() == llvm::Triple::x86)
+ CmdArgs.push_back("_DllMainCRTStartup@12");
+ else
+ CmdArgs.push_back("DllMainCRTStartup");
+ CmdArgs.push_back("--enable-auto-image-base");
}
CmdArgs.push_back("-o");
@@ -202,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))
@@ -224,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");
@@ -276,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"}) {
@@ -303,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) {
@@ -310,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()));
@@ -454,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:
@@ -473,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/lib/Driver/ToolChains/MinGW.h b/lib/Driver/ToolChains/MinGW.h
index f8dbcae62756..0c3919d29f77 100644
--- a/lib/Driver/ToolChains/MinGW.h
+++ b/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/lib/Driver/ToolChains/MipsLinux.cpp b/lib/Driver/ToolChains/MipsLinux.cpp
index b394208336ed..9f23996b764a 100644
--- a/lib/Driver/ToolChains/MipsLinux.cpp
+++ b/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/lib/Driver/ToolChains/MipsLinux.h b/lib/Driver/ToolChains/MipsLinux.h
index fa82efbbfc8f..d4b476d883e6 100644
--- a/lib/Driver/ToolChains/MipsLinux.h
+++ b/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/lib/Driver/ToolChains/Myriad.cpp b/lib/Driver/ToolChains/Myriad.cpp
index 06079b109dd1..2b4c1d165576 100644
--- a/lib/Driver/ToolChains/Myriad.cpp
+++ b/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/lib/Driver/ToolChains/Myriad.h b/lib/Driver/ToolChains/Myriad.h
index 4c213c726219..33307c3f871a 100644
--- a/lib/Driver/ToolChains/Myriad.h
+++ b/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/lib/Driver/ToolChains/NaCl.cpp b/lib/Driver/ToolChains/NaCl.cpp
index 128478d63871..89a18944c319 100644
--- a/lib/Driver/ToolChains/NaCl.cpp
+++ b/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/lib/Driver/ToolChains/NaCl.h b/lib/Driver/ToolChains/NaCl.h
index 31af3a53ad3c..e0885b526d70 100644
--- a/lib/Driver/ToolChains/NaCl.h
+++ b/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/lib/Driver/ToolChains/NetBSD.cpp b/lib/Driver/ToolChains/NetBSD.cpp
index 0db6578f7407..02caafda1657 100644
--- a/lib/Driver/ToolChains/NetBSD.cpp
+++ b/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/lib/Driver/ToolChains/NetBSD.h b/lib/Driver/ToolChains/NetBSD.h
index e98df72ce65c..49e3a58d02c3 100644
--- a/lib/Driver/ToolChains/NetBSD.h
+++ b/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/lib/Driver/ToolChains/OpenBSD.cpp b/lib/Driver/ToolChains/OpenBSD.cpp
index fbb84a62ca89..7b98cd62bbfc 100644
--- a/lib/Driver/ToolChains/OpenBSD.cpp
+++ b/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/lib/Driver/ToolChains/OpenBSD.h b/lib/Driver/ToolChains/OpenBSD.h
index 1cc0ca71984a..bf8dfa4653cb 100644
--- a/lib/Driver/ToolChains/OpenBSD.h
+++ b/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/lib/Driver/ToolChains/PS4CPU.cpp b/lib/Driver/ToolChains/PS4CPU.cpp
index b37fe7d1f9b9..a4b74d492331 100644
--- a/lib/Driver/ToolChains/PS4CPU.cpp
+++ b/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/lib/Driver/ToolChains/PS4CPU.h b/lib/Driver/ToolChains/PS4CPU.h
index e507edbad4d5..bd0a44352f4d 100644
--- a/lib/Driver/ToolChains/PS4CPU.h
+++ b/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/lib/Driver/ToolChains/Solaris.cpp b/lib/Driver/ToolChains/Solaris.cpp
index 9fe6e9d520d0..b48edbb08ee6 100644
--- a/lib/Driver/ToolChains/Solaris.cpp
+++ b/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/lib/Driver/ToolChains/Solaris.h b/lib/Driver/ToolChains/Solaris.h
index 787917afab6e..9e14269b393e 100644
--- a/lib/Driver/ToolChains/Solaris.h
+++ b/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/lib/Driver/ToolChains/WebAssembly.cpp b/lib/Driver/ToolChains/WebAssembly.cpp
index 8ae1b6c2f55d..94f7279bbdba 100644
--- a/lib/Driver/ToolChains/WebAssembly.cpp
+++ b/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/lib/Driver/ToolChains/WebAssembly.h b/lib/Driver/ToolChains/WebAssembly.h
index 8784e12dfb0e..cdbb34ff919f 100644
--- a/lib/Driver/ToolChains/WebAssembly.h
+++ b/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/lib/Driver/Types.cpp b/lib/Driver/Types.cpp
index ab63f0e81b12..45bb699cfb88 100644
--- a/lib/Driver/Types.cpp
+++ b/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/lib/Driver/XRayArgs.cpp b/lib/Driver/XRayArgs.cpp
index 232bacd5f095..30b0e72760c9 100644
--- a/lib/Driver/XRayArgs.cpp
+++ b/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/lib/Edit/Commit.cpp b/lib/Edit/Commit.cpp
index cb7a784a41af..afc1a131eb25 100644
--- a/lib/Edit/Commit.cpp
+++ b/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) {
@@ -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;
@@ -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/lib/Edit/EditedSource.cpp b/lib/Edit/EditedSource.cpp
index 444d0393cccd..b38f8fd0d9cb 100644
--- a/lib/Edit/EditedSource.cpp
+++ b/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/lib/Edit/RewriteObjCFoundationAPI.cpp b/lib/Edit/RewriteObjCFoundationAPI.cpp
index dc501b564eea..f89526a71da2 100644
--- a/lib/Edit/RewriteObjCFoundationAPI.cpp
+++ b/lib/Edit/RewriteObjCFoundationAPI.cpp
@@ -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,
diff --git a/lib/Format/AffectedRangeManager.cpp b/lib/Format/AffectedRangeManager.cpp
index 5d4df1941209..b14316a14cd9 100644
--- a/lib/Format/AffectedRangeManager.cpp
+++ b/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/lib/Format/AffectedRangeManager.h b/lib/Format/AffectedRangeManager.h
index d8d5ee55acd8..b0c9dd259fb8 100644
--- a/lib/Format/AffectedRangeManager.h
+++ b/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/lib/Format/BreakableToken.cpp b/lib/Format/BreakableToken.cpp
index 4735ab3564f0..cc68f70100e3 100644
--- a/lib/Format/BreakableToken.cpp
+++ b/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());
@@ -284,10 +286,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 +298,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 +426,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) {
@@ -788,16 +789,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/lib/Format/BreakableToken.h b/lib/Format/BreakableToken.h
index 8ef26ef464da..0fac8f08c026 100644
--- a/lib/Format/BreakableToken.h
+++ b/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.
@@ -27,13 +27,13 @@
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 +88,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 +108,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 +125,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 +135,7 @@ public:
virtual unsigned getContentStartColumn(unsigned LineIndex,
bool Break) const = 0;
- /// \brief Returns a range (offset, length) at which to break the line at
+ /// 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 +144,27 @@ 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,
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 +180,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,7 +204,7 @@ 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,
@@ -213,7 +213,7 @@ public:
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,17 +232,17 @@ 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,
WhitespaceManager &Whitespaces) const override;
@@ -272,7 +272,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 +284,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;
@@ -453,7 +453,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/lib/Format/CMakeLists.txt b/lib/Format/CMakeLists.txt
index 42e6d53d9fe6..0019d045cd06 100644
--- a/lib/Format/CMakeLists.txt
+++ b/lib/Format/CMakeLists.txt
@@ -20,4 +20,5 @@ add_clang_library(clangFormat
clangBasic
clangLex
clangToolingCore
+ clangToolingInclusions
)
diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp
index a3d38b244c5c..90d2a9997111 100644
--- a/lib/Format/ContinuationIndenter.cpp
+++ b/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 ||
@@ -1559,12 +1810,12 @@ ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
Token->adaptStartOfLine(0, Whitespaces);
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 +1823,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 +1842,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 +1869,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 +1889,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 +1904,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,7 +1929,7 @@ ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
continue;
}
}
- DEBUG(llvm::dbgs() << " Breaking...\n");
+ LLVM_DEBUG(llvm::dbgs() << " Breaking...\n");
ContentStartColumn =
Token->getContentStartColumn(LineIndex, /*Break=*/true);
unsigned NewRemainingTokenColumns = Token->getRemainingLength(
@@ -1693,8 +1945,8 @@ 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);
@@ -1732,11 +1984,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 +1997,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 +2011,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 +2020,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 +2033,7 @@ ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
}
}
} else {
- DEBUG(llvm::dbgs() << "not found.\n");
+ LLVM_DEBUG(llvm::dbgs() << "not found.\n");
}
}
if (!Reflow) {
@@ -1821,7 +2075,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 +2129,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/lib/Format/ContinuationIndenter.h b/lib/Format/ContinuationIndenter.h
index ded7bfab4267..4ff05ba99f1a 100644
--- a/lib/Format/ContinuationIndenter.h
+++ b/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,28 +85,28 @@ 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,
@@ -110,17 +114,17 @@ private:
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/lib/Format/Encoding.h b/lib/Format/Encoding.h
index 3339597b4edd..4c877e7e49d5 100644
--- a/lib/Format/Encoding.h
+++ b/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/lib/Format/Format.cpp b/lib/Format/Format.cpp
index 217c6729ee39..59d34308c0a9 100644
--- a/lib/Format/Format.cpp
+++ b/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,57 @@ 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_TEST_PROTO",
+ "PARSE_TEXT_PROTO",
+ "ParseTextOrDie",
+ },
+ /*CanonicalDelimiter=*/"",
+ /*BasedOnStyle=*/"google",
+ },
+ };
GoogleStyle.SpacesBeforeTrailingComments = 2;
GoogleStyle.Standard = FormatStyle::LS_Auto;
@@ -729,8 +819,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 +866,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 +902,7 @@ FormatStyle getWebKitStyle() {
Style.ObjCBlockIndentWidth = 4;
Style.ObjCSpaceAfterProperty = true;
Style.PointerAlignment = FormatStyle::PAS_Left;
+ Style.SpaceBeforeCpp11BracedList = true;
return Style;
}
@@ -859,7 +959,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 +978,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 +988,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 +1018,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 +1061,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 +1151,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 +1275,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 +1478,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 +1695,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 +1725,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 +1748,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 +1765,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 +1878,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 +1906,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 +1933,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 +2008,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 +2023,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 +2052,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 +2069,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 +2132,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 +2161,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 +2198,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 +2207,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 +2229,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/lib/Format/FormatInternal.h b/lib/Format/FormatInternal.h
index 3984158467b3..5c59e7656eee 100644
--- a/lib/Format/FormatInternal.h
+++ b/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/lib/Format/FormatToken.cpp b/lib/Format/FormatToken.cpp
index 10ac392abbf2..62b08c576e05 100644
--- a/lib/Format/FormatToken.cpp
+++ b/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/lib/Format/FormatToken.h b/lib/Format/FormatToken.h
index 3dc0ab0e7cca..9094e7689e1d 100644
--- a/lib/Format/FormatToken.h
+++ b/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/lib/Format/FormatTokenLexer.cpp b/lib/Format/FormatTokenLexer.cpp
index 199d2974c5c7..c7f720a443d3 100644
--- a/lib/Format/FormatTokenLexer.cpp
+++ b/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/lib/Format/FormatTokenLexer.h b/lib/Format/FormatTokenLexer.h
index 59dc2a752f1f..3b79d27480e3 100644
--- a/lib/Format/FormatTokenLexer.h
+++ b/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/lib/Format/NamespaceEndCommentsFixer.cpp b/lib/Format/NamespaceEndCommentsFixer.cpp
index df99bb2e1381..995b3219a1f4 100644
--- a/lib/Format/NamespaceEndCommentsFixer.cpp
+++ b/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/lib/Format/NamespaceEndCommentsFixer.h b/lib/Format/NamespaceEndCommentsFixer.h
index 4779f0d27c92..07a1c7bb0c35 100644
--- a/lib/Format/NamespaceEndCommentsFixer.h
+++ b/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/lib/Format/SortJavaScriptImports.cpp b/lib/Format/SortJavaScriptImports.cpp
index d0b979e100d5..2ec577382ffb 100644
--- a/lib/Format/SortJavaScriptImports.cpp
+++ b/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/lib/Format/SortJavaScriptImports.h b/lib/Format/SortJavaScriptImports.h
index f22a051008f0..ecab0ae54cb3 100644
--- a/lib/Format/SortJavaScriptImports.h
+++ b/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/lib/Format/TokenAnalyzer.cpp b/lib/Format/TokenAnalyzer.cpp
index d1dfb1fea32b..99fc61ef1c32 100644
--- a/lib/Format/TokenAnalyzer.cpp
+++ b/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/lib/Format/TokenAnalyzer.h b/lib/Format/TokenAnalyzer.h
index 96ea00b25ba1..e43a860e46cf 100644
--- a/lib/Format/TokenAnalyzer.h
+++ b/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/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp
index 298c72b002f8..3a19215e1803 100644
--- a/lib/Format/TokenAnnotator.cpp
+++ b/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;
@@ -1723,15 +1902,18 @@ void TokenAnnotator::setCommentLineLevels(
}
}
- if (NextNonCommentLine && CommentLine) {
- // If the comment is currently aligned with the line immediately following
- // it, that's probably intentional and we should keep it.
- bool AlignedWithNextLine =
- NextNonCommentLine->First->NewlinesBefore <= 1 &&
- NextNonCommentLine->First->OriginalColumn ==
- (*I)->First->OriginalColumn;
- if (AlignedWithNextLine)
- (*I)->Level = NextNonCommentLine->Level;
+ // If the comment is currently aligned with the line immediately following
+ // it, that's probably intentional and we should keep it.
+ if (NextNonCommentLine && CommentLine &&
+ NextNonCommentLine->First->NewlinesBefore <= 1 &&
+ NextNonCommentLine->First->OriginalColumn ==
+ (*I)->First->OriginalColumn) {
+ // Align comments for preprocessor lines with the # in column 0.
+ // Otherwise, align with the next line.
+ (*I)->Level = (NextNonCommentLine->Type == LT_PreprocessorDirective ||
+ NextNonCommentLine->Type == LT_ImportStatement)
+ ? 0
+ : NextNonCommentLine->Level;
} else {
NextNonCommentLine = (*I)->First->isNot(tok::r_brace) ? (*I) : nullptr;
}
@@ -1962,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;
}
@@ -1983,7 +2177,7 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) {
++IndentLevel;
}
- DEBUG({ printDebugInfo(Line); });
+ LLVM_DEBUG({ printDebugInfo(Line); });
}
void TokenAnnotator::calculateUnbreakableTailLengths(AnnotatedLine &Line) {
@@ -2043,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;
}
@@ -2128,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;
@@ -2144,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;
}
@@ -2169,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();
@@ -2205,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))
@@ -2221,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));
@@ -2263,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))
@@ -2291,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 &&
@@ -2329,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;
}
@@ -2340,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) &&
@@ -2351,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;
@@ -2402,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;
@@ -2455,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 &&
@@ -2472,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))
@@ -2486,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))
@@ -2497,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)))
@@ -2517,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.
@@ -2597,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;
}
@@ -2639,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 &&
@@ -2650,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))) &&
@@ -2683,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;
}
@@ -2708,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;
@@ -2774,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.
@@ -2806,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 &&
@@ -2831,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))
@@ -2850,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)))
@@ -2872,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() ||
@@ -2898,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/lib/Format/TokenAnnotator.h b/lib/Format/TokenAnnotator.h
index 04a18d45b82e..a3124fcb3d65 100644
--- a/lib/Format/TokenAnnotator.h
+++ b/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/lib/Format/UnwrappedLineFormatter.cpp b/lib/Format/UnwrappedLineFormatter.cpp
index 60dc1a7169d1..906dae40cbee 100644
--- a/lib/Format/UnwrappedLineFormatter.cpp
+++ b/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/lib/Format/UnwrappedLineFormatter.h b/lib/Format/UnwrappedLineFormatter.h
index 6432ca83a4c9..dac210ea62b1 100644
--- a/lib/Format/UnwrappedLineFormatter.h
+++ b/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/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp
index b8608dcac9c7..e5afa1264abb 100644
--- a/lib/Format/UnwrappedLineParser.cpp
+++ b/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;
@@ -234,14 +226,17 @@ UnwrappedLineParser::UnwrappedLineParser(const FormatStyle &Style,
CurrentLines(&Lines), Style(Style), Keywords(Keywords),
CommentPragmasRegex(Style.CommentPragmas), Tokens(nullptr),
Callback(Callback), AllTokens(Tokens), PPBranchLevel(-1),
- IfNdefCondition(nullptr), FoundIncludeGuardStart(false),
- IncludeGuardRejected(false), FirstStartColumn(FirstStartColumn) {}
+ IncludeGuard(Style.IndentPPDirectives == FormatStyle::PPDIS_None
+ ? IG_Rejected
+ : IG_Inited),
+ IncludeGuardToken(nullptr), FirstStartColumn(FirstStartColumn) {}
void UnwrappedLineParser::reset() {
PPBranchLevel = -1;
- IfNdefCondition = nullptr;
- FoundIncludeGuardStart = false;
- IncludeGuardRejected = false;
+ IncludeGuard = Style.IndentPPDirectives == FormatStyle::PPDIS_None
+ ? IG_Rejected
+ : IG_Inited;
+ IncludeGuardToken = nullptr;
Line.reset(new UnwrappedLine);
CommentsBeforeNextToken.clear();
FormatTok = nullptr;
@@ -257,13 +252,21 @@ void UnwrappedLineParser::parse() {
IndexedTokenSource TokenSource(AllTokens);
Line->FirstStartColumn = FirstStartColumn;
do {
- DEBUG(llvm::dbgs() << "----\n");
+ LLVM_DEBUG(llvm::dbgs() << "----\n");
reset();
Tokens = &TokenSource;
TokenSource.reset();
readToken();
parseFile();
+
+ // If we found an include guard then all preprocessor directives (other than
+ // the guard) are over-indented by one.
+ if (IncludeGuard == IG_Found)
+ for (auto &Line : Lines)
+ if (Line.InPPDirective && Line.Level > 0)
+ --Line.Level;
+
// Create line with eof token.
pushToken(FormatTok);
addUnwrappedLine();
@@ -300,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();
}
@@ -333,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) {
@@ -426,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;
@@ -540,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;
}
}
@@ -712,26 +746,27 @@ void UnwrappedLineParser::parsePPIf(bool IfDef) {
// If there's a #ifndef on the first line, and the only lines before it are
// comments, it could be an include guard.
bool MaybeIncludeGuard = IfNDef;
- if (!IncludeGuardRejected && !FoundIncludeGuardStart && MaybeIncludeGuard) {
+ if (IncludeGuard == IG_Inited && MaybeIncludeGuard)
for (auto &Line : Lines) {
if (!Line.Tokens.front().Tok->is(tok::comment)) {
MaybeIncludeGuard = false;
- IncludeGuardRejected = true;
+ IncludeGuard = IG_Rejected;
break;
}
}
- }
--PPBranchLevel;
parsePPUnknown();
++PPBranchLevel;
- if (!IncludeGuardRejected && !FoundIncludeGuardStart && MaybeIncludeGuard)
- IfNdefCondition = IfCondition;
+ if (IncludeGuard == IG_Inited && MaybeIncludeGuard) {
+ IncludeGuard = IG_IfNdefed;
+ IncludeGuardToken = IfCondition;
+ }
}
void UnwrappedLineParser::parsePPElse() {
// If a potential include guard has an #else, it's not an include guard.
- if (FoundIncludeGuardStart && PPBranchLevel == 0)
- FoundIncludeGuardStart = false;
+ if (IncludeGuard == IG_Defined && PPBranchLevel == 0)
+ IncludeGuard = IG_Rejected;
conditionalCompilationAlternative();
if (PPBranchLevel > -1)
--PPBranchLevel;
@@ -745,34 +780,37 @@ void UnwrappedLineParser::parsePPEndIf() {
conditionalCompilationEnd();
parsePPUnknown();
// If the #endif of a potential include guard is the last thing in the file,
- // then we count it as a real include guard and subtract one from every
- // preprocessor indent.
+ // then we found an include guard.
unsigned TokenPosition = Tokens->getPosition();
FormatToken *PeekNext = AllTokens[TokenPosition];
- if (FoundIncludeGuardStart && PPBranchLevel == -1 && PeekNext->is(tok::eof) &&
+ if (IncludeGuard == IG_Defined && PPBranchLevel == -1 &&
+ PeekNext->is(tok::eof) &&
Style.IndentPPDirectives != FormatStyle::PPDIS_None)
- for (auto &Line : Lines)
- if (Line.InPPDirective && Line.Level > 0)
- --Line.Level;
+ IncludeGuard = IG_Found;
}
void UnwrappedLineParser::parsePPDefine() {
nextToken();
if (FormatTok->Tok.getKind() != tok::identifier) {
+ IncludeGuard = IG_Rejected;
+ IncludeGuardToken = nullptr;
parsePPUnknown();
return;
}
- if (IfNdefCondition && IfNdefCondition->TokenText == FormatTok->TokenText) {
- FoundIncludeGuardStart = true;
+
+ if (IncludeGuard == IG_IfNdefed &&
+ IncludeGuardToken->TokenText == FormatTok->TokenText) {
+ IncludeGuard = IG_Defined;
+ IncludeGuardToken = nullptr;
for (auto &Line : Lines) {
if (!Line.Tokens.front().Tok->isOneOf(tok::comment, tok::hash)) {
- FoundIncludeGuardStart = false;
+ IncludeGuard = IG_Rejected;
break;
}
}
}
- IfNdefCondition = nullptr;
+
nextToken();
if (FormatTok->Tok.getKind() == tok::l_paren &&
FormatTok->WhitespaceRange.getBegin() ==
@@ -799,7 +837,6 @@ void UnwrappedLineParser::parsePPUnknown() {
if (Style.IndentPPDirectives == FormatStyle::PPDIS_AfterHash)
Line->Level += PPBranchLevel + 1;
addUnwrappedLine();
- IfNdefCondition = nullptr;
}
// Here we blacklist certain tokens that are not usually the first token in an
@@ -932,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)) {
@@ -1032,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.
@@ -1117,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:
@@ -1369,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;
}
@@ -2083,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 '>'.
}
@@ -2106,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();
}
@@ -2113,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
@@ -2140,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))
@@ -2150,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() {
@@ -2231,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/lib/Format/UnwrappedLineParser.h b/lib/Format/UnwrappedLineParser.h
index 1d8ccabbd0f8..87254832c635 100644
--- a/lib/Format/UnwrappedLineParser.h
+++ b/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);
@@ -248,10 +253,23 @@ private:
// sequence.
std::stack<int> PPChainBranchIndex;
- // Contains the #ifndef condition for a potential include guard.
- FormatToken *IfNdefCondition;
- bool FoundIncludeGuardStart;
- bool IncludeGuardRejected;
+ // Include guard search state. Used to fixup preprocessor indent levels
+ // so that include guards do not participate in indentation.
+ enum IncludeGuardState {
+ IG_Inited, // Search started, looking for #ifndef.
+ IG_IfNdefed, // #ifndef found, IncludeGuardToken points to condition.
+ IG_Defined, // Matching #define found, checking other requirements.
+ IG_Found, // All requirements met, need to fix indents.
+ IG_Rejected, // Search failed or never started.
+ };
+
+ // Current state of include guard search.
+ IncludeGuardState IncludeGuard;
+
+ // Points to the #ifndef condition for a potential include guard. Null unless
+ // IncludeGuardState == IG_IfNdefed.
+ FormatToken *IncludeGuardToken;
+
// Contains the first start column where the source begins. This is zero for
// normal source code and may be nonzero when formatting a code fragment that
// does not start at the beginning of the file.
diff --git a/lib/Format/UsingDeclarationsSorter.cpp b/lib/Format/UsingDeclarationsSorter.cpp
index ef0c7a7d5a45..9e49e7913033 100644
--- a/lib/Format/UsingDeclarationsSorter.cpp
+++ b/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/lib/Format/UsingDeclarationsSorter.h b/lib/Format/UsingDeclarationsSorter.h
index 6f137712d841..7e5cf7610d67 100644
--- a/lib/Format/UsingDeclarationsSorter.h
+++ b/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/lib/Format/WhitespaceManager.cpp b/lib/Format/WhitespaceManager.cpp
index a5477a996327..7070ce03c864 100644
--- a/lib/Format/WhitespaceManager.cpp
+++ b/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/lib/Format/WhitespaceManager.h b/lib/Format/WhitespaceManager.h
index af20dc5616a7..db90343f7294 100644
--- a/lib/Format/WhitespaceManager.h
+++ b/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/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp
index 7dc475e26f76..b67c019baed8 100644
--- a/lib/Frontend/ASTConsumers.cpp
+++ b/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,
diff --git a/lib/Frontend/ASTMerge.cpp b/lib/Frontend/ASTMerge.cpp
index 354527db7bad..6ec0e2a98c1b 100644
--- a/lib/Frontend/ASTMerge.cpp
+++ b/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
//
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index 1160df15a920..e4c313fed30f 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/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;
@@ -1259,6 +1313,7 @@ ASTUnit::getMainBufferWithPrecompiledPreamble(
Preamble.reset();
PreambleDiagnostics.clear();
TopLevelDeclsInPreamble.clear();
+ PreambleSrcLocCache.clear();
PreambleRebuildCounter = 1;
}
}
@@ -1290,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;
@@ -1306,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;
@@ -1344,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))
@@ -1388,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();
@@ -1408,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);
@@ -1442,7 +1503,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
if (!AST)
return nullptr;
}
-
+
if (!ResourceFilesPath.empty()) {
// Override the resources path.
CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath;
@@ -1460,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.
@@ -1478,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));
@@ -1494,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() ==
@@ -1512,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());
@@ -1558,7 +1619,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
// Steal the created target, context, and preprocessor.
AST->transferASTDataFromCompilerInstance(*Clang);
-
+
Act->EndSourceFile();
if (OwnAST)
@@ -1623,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),
@@ -1646,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) {
@@ -1657,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;
@@ -1676,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();
@@ -1688,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;
@@ -1705,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.
@@ -1745,7 +1805,7 @@ bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
}
clearFileLevelDecls();
-
+
SimpleTimer ParsingTimer(WantTiming);
ParsingTimer.setOutput("Reparsing " + getMainFileName());
@@ -1767,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();
@@ -1779,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)
@@ -1788,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;
}
@@ -1810,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)
@@ -1865,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,
@@ -1895,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:
@@ -1919,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();
@@ -1932,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());
@@ -1954,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 =
@@ -1962,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;
@@ -1994,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(
@@ -2013,7 +2073,7 @@ void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
}
}
}
-
+
// Adjust the completion string, if required.
if (C->Kind == CXCursor_MacroDefinition &&
Context.getKind() == CodeCompletionContext::CCC_MacroNameUse) {
@@ -2025,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());
}
@@ -2068,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);
@@ -2092,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());
@@ -2107,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() ==
@@ -2122,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);
@@ -2209,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);
@@ -2257,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,
@@ -2271,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;
@@ -2303,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;
@@ -2312,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);
@@ -2320,7 +2382,7 @@ void ASTUnit::TranslateStoredDiagnostics(
void ASTUnit::addFileLevelDecl(Decl *D) {
assert(D);
-
+
// We only care about local declarations.
if (D->isFromASTFile())
return;
@@ -2397,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);
}
@@ -2416,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 {
@@ -2437,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 {
@@ -2462,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);
}
@@ -2473,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);
}
@@ -2484,9 +2546,9 @@ SourceLocation ASTUnit::getEndOfPreambleFileID() const {
FileID FID;
if (SourceMgr)
FID = SourceMgr->getPreambleFileID();
-
+
if (FID.isInvalid())
- return SourceLocation();
+ return {};
return SourceMgr->getLocForEndOfFile(FID);
}
@@ -2495,10 +2557,10 @@ SourceLocation ASTUnit::getStartOfMainFileID() const {
FileID FID;
if (SourceMgr)
FID = SourceMgr->getMainFileID();
-
+
if (FID.isInvalid())
- return SourceLocation();
-
+ return {};
+
return SourceMgr->getLocForStartOfFile(FID);
}
@@ -2521,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/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt
index ba3bd7d28c70..6161b46a9dc5 100644
--- a/lib/Frontend/CMakeLists.txt
+++ b/lib/Frontend/CMakeLists.txt
@@ -29,6 +29,7 @@ add_clang_library(clangFrontend
FrontendAction.cpp
FrontendActions.cpp
FrontendOptions.cpp
+ FrontendTiming.cpp
HeaderIncludeGen.cpp
InitHeaderSearch.cpp
InitPreprocessor.cpp
diff --git a/lib/Frontend/CacheTokens.cpp b/lib/Frontend/CacheTokens.cpp
index 72e8f68dc051..c4504a14456d 100644
--- a/lib/Frontend/CacheTokens.cpp
+++ b/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/lib/Frontend/CodeGenOptions.cpp b/lib/Frontend/CodeGenOptions.cpp
index 50bb9f951be4..84a39f2d570d 100644
--- a/lib/Frontend/CodeGenOptions.cpp
+++ b/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/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index 7208177aa012..155ead4ac8e8 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/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"
@@ -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;
@@ -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
@@ -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;
@@ -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,
@@ -1202,6 +1188,13 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance,
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,7 +1321,7 @@ 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) {
@@ -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.
@@ -1653,8 +1653,10 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
// Retrieve the cached top-level module.
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
@@ -1859,6 +1863,40 @@ 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 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
+ // @import Foo_Private instead. FIXME: remove this when existing clients
+ // migrate off of Foo.Private syntax.
+ if (!Sub && PP->getLangOpts().ImplicitModules && Name == "Private" &&
+ Module == Module->getTopLevelModule()) {
+ SmallString<128> PrivateModule(Module->Name);
+ PrivateModule.append("_Private");
+
+ SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> PrivPath;
+ auto &II = PP->getIdentifierTable().get(
+ PrivateModule, PP->getIdentifierInfo(Module->Name)->getTokenID());
+ PrivPath.push_back(std::make_pair(&II, Path[0].second));
+
+ if (PP->getHeaderSearchInfo().lookupModule(PrivateModule, true,
+ !IsInclusionDirective))
+ Sub =
+ loadModule(ImportLoc, PrivPath, Visibility, IsInclusionDirective);
+ if (Sub) {
+ MapPrivateSubModToTopLevel = true;
+ if (!getDiagnostics().isIgnored(
+ diag::warn_no_priv_submodule_use_toplevel, ImportLoc)) {
+ getDiagnostics().Report(Path[I].second,
+ diag::warn_no_priv_submodule_use_toplevel)
+ << Path[I].first << Module->getFullModuleName() << PrivateModule
+ << SourceRange(Path[0].second, Path[I].second)
+ << FixItHint::CreateReplacement(SourceRange(Path[0].second),
+ PrivateModule);
+ getDiagnostics().Report(Sub->DefinitionLoc,
+ diag::note_private_top_level_defined);
+ }
+ }
+ }
if (!Sub) {
// Attempt to perform typo correction to find a module name that works.
@@ -1894,39 +1932,6 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
}
}
- // 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
- // @import Foo_Private instead. FIXME: remove this when existing clients
- // migrate off of Foo.Private syntax.
- if (!Sub && PP->getLangOpts().ImplicitModules && Name == "Private" &&
- Module == Module->getTopLevelModule()) {
- SmallString<128> PrivateModule(Module->Name);
- PrivateModule.append("_Private");
-
- SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> PrivPath;
- auto &II = PP->getIdentifierTable().get(
- PrivateModule, PP->getIdentifierInfo(Module->Name)->getTokenID());
- PrivPath.push_back(std::make_pair(&II, Path[0].second));
-
- if (PP->getHeaderSearchInfo().lookupModule(PrivateModule))
- Sub =
- loadModule(ImportLoc, PrivPath, Visibility, IsInclusionDirective);
- if (Sub) {
- MapPrivateSubModToTopLevel = true;
- if (!getDiagnostics().isIgnored(
- diag::warn_no_priv_submodule_use_toplevel, ImportLoc)) {
- getDiagnostics().Report(Path[I].second,
- diag::warn_no_priv_submodule_use_toplevel)
- << Path[I].first << Module->getFullModuleName() << PrivateModule
- << SourceRange(Path[0].second, Path[I].second)
- << FixItHint::CreateReplacement(SourceRange(Path[0].second),
- PrivateModule);
- getDiagnostics().Report(Sub->DefinitionLoc,
- diag::note_private_top_level_defined);
- }
- }
- }
-
if (!Sub) {
// No submodule by this name. Complain, and don't look for further
// submodules.
@@ -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/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 2e8a737de4e4..78e6babd0251 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/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('='));
@@ -552,7 +625,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Args.hasFlag(OPT_ffine_grained_bitfield_accesses,
OPT_fno_fine_grained_bitfield_accesses, false);
Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags);
- Opts.MergeAllConstants = !Args.hasArg(OPT_fno_merge_all_constants);
+ Opts.MergeAllConstants = Args.hasArg(OPT_fmerge_all_constants);
Opts.NoCommon = Args.hasArg(OPT_fno_common);
Opts.NoImplicitFloat = Args.hasArg(OPT_no_implicit_float);
Opts.OptimizeSize = getOptimizationLevelSize(Args);
@@ -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
@@ -2407,16 +2585,25 @@ 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.
+ 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) {
- int Version =
- getLastArgIntValue(Args, OPT_fopenmp_version_EQ, Opts.OpenMP, Diags);
- if (Version != 0)
+ if (Opts.OpenMP || Opts.OpenMPSimd) {
+ if (int Version = getLastArgIntValue(
+ Args, OPT_fopenmp_version_EQ,
+ (IsSimdSpecified || IsTargetSpecified) ? 45 : Opts.OpenMP, Diags))
Opts.OpenMP = Version;
+ else if (IsSimdSpecified || IsTargetSpecified)
+ Opts.OpenMP = 45;
// Provide diagnostic when a given target is not expected to be an OpenMP
// device or host.
if (!Opts.OpenMPIsDevice) {
@@ -2426,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;
}
@@ -2435,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;
}
@@ -2454,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);
}
@@ -2465,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,
@@ -2543,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) {
@@ -2579,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:
@@ -2595,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
@@ -2611,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)) {
@@ -2630,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
@@ -2641,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()) {
@@ -2681,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
@@ -2700,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();
@@ -2720,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,
@@ -2750,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;
}
@@ -2768,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 ||
@@ -2793,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.
@@ -2811,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);
@@ -2864,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.
@@ -2919,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,
@@ -2936,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,
@@ -2980,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/lib/Frontend/DependencyFile.cpp b/lib/Frontend/DependencyFile.cpp
index 561eb9c4a316..f89722eeb9ed 100644
--- a/lib/Frontend/DependencyFile.cpp
+++ b/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/lib/Frontend/DependencyGraph.cpp b/lib/Frontend/DependencyGraph.cpp
index 67a977e38be2..660f664447ab 100644
--- a/lib/Frontend/DependencyGraph.cpp
+++ b/lib/Frontend/DependencyGraph.cpp
@@ -50,7 +50,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 EndOfMainFile() override {
OutputGraphFile();
@@ -65,15 +66,17 @@ 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;
diff --git a/lib/Frontend/DiagnosticRenderer.cpp b/lib/Frontend/DiagnosticRenderer.cpp
index e3263843e29b..fb0a92d1f8c6 100644
--- a/lib/Frontend/DiagnosticRenderer.cpp
+++ b/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
@@ -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()) {
@@ -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/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp
index 12226b231417..a5929424e52a 100644
--- a/lib/Frontend/FrontendAction.cpp
+++ b/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.
@@ -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/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp
index ffa5b410d2d8..9344e673c7ac 100644
--- a/lib/Frontend/FrontendActions.cpp
+++ b/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
};
}
@@ -579,6 +772,7 @@ void PrintPreambleAction::ExecuteAction() {
case InputKind::ObjCXX:
case InputKind::OpenCL:
case InputKind::CUDA:
+ case InputKind::HIP:
break;
case InputKind::Unknown:
@@ -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/lib/Frontend/FrontendOptions.cpp b/lib/Frontend/FrontendOptions.cpp
index dca434588fb1..0744d447e816 100644
--- a/lib/Frontend/FrontendOptions.cpp
+++ b/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/lib/Frontend/FrontendTiming.cpp b/lib/Frontend/FrontendTiming.cpp
new file mode 100644
index 000000000000..9ea7347e7797
--- /dev/null
+++ b/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/lib/Frontend/HeaderIncludeGen.cpp b/lib/Frontend/HeaderIncludeGen.cpp
index 5bff4ecd0b46..9dc107c9d546 100644
--- a/lib/Frontend/HeaderIncludeGen.cpp
+++ b/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/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp
index 8c6faced76ac..8a70404629d3 100644
--- a/lib/Frontend/InitHeaderSearch.cpp
+++ b/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/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp
index d39890494323..e3f4f92b9d1e 100644
--- a/lib/Frontend/InitPreprocessor.cpp
+++ b/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");
+ 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();
@@ -817,10 +852,6 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
DefineFloatMacros(Builder, "FLT", &TI.getFloatFormat(), "F");
DefineFloatMacros(Builder, "DBL", &TI.getDoubleFormat(), "");
DefineFloatMacros(Builder, "LDBL", &TI.getLongDoubleFormat(), "L");
- if (TI.hasFloat128Type())
- // FIXME: Switch away from the non-standard "Q" when we can
- DefineFloatMacros(Builder, "FLT128", &TI.getFloat128Format(), "Q");
-
// Define a __POINTER_WIDTH__ macro for stdint.h.
Builder.defineMacro("__POINTER_WIDTH__",
@@ -929,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);
@@ -1011,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
- Builder.defineMacro("_OPENMP", "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/lib/Frontend/LayoutOverrideSource.cpp b/lib/Frontend/LayoutOverrideSource.cpp
index 06e9a7dc50b4..93e07eb81f72 100644
--- a/lib/Frontend/LayoutOverrideSource.cpp
+++ b/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 "";
diff --git a/lib/Frontend/ModuleDependencyCollector.cpp b/lib/Frontend/ModuleDependencyCollector.cpp
index ede12aab6e69..25cad8be6d00 100644
--- a/lib/Frontend/ModuleDependencyCollector.cpp
+++ b/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/lib/Frontend/MultiplexConsumer.cpp b/lib/Frontend/MultiplexConsumer.cpp
index 04a8f6c1cdfb..df36c88ec38e 100644
--- a/lib/Frontend/MultiplexConsumer.cpp
+++ b/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) {
diff --git a/lib/Frontend/PCHContainerOperations.cpp b/lib/Frontend/PCHContainerOperations.cpp
index eebebf327a19..340e8ce63ff4 100644
--- a/lib/Frontend/PCHContainerOperations.cpp
+++ b/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/lib/Frontend/PrecompiledPreamble.cpp b/lib/Frontend/PrecompiledPreamble.cpp
index 7e1323fd83bb..30ae2db26d86 100644
--- a/lib/Frontend/PrecompiledPreamble.cpp
+++ b/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/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp
index 2e023294f1e8..1b35b32656e7 100644
--- a/lib/Frontend/PrintPreprocessedOutput.cpp
+++ b/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;
@@ -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/lib/Frontend/Rewrite/FixItRewriter.cpp b/lib/Frontend/Rewrite/FixItRewriter.cpp
index dc787ac9557c..64785e301236 100644
--- a/lib/Frontend/Rewrite/FixItRewriter.cpp
+++ b/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;
@@ -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/lib/Frontend/Rewrite/HTMLPrint.cpp b/lib/Frontend/Rewrite/HTMLPrint.cpp
index 11e431de0a31..34ee9673cc54 100644
--- a/lib/Frontend/Rewrite/HTMLPrint.cpp
+++ b/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/lib/Frontend/Rewrite/InclusionRewriter.cpp b/lib/Frontend/Rewrite/InclusionRewriter.cpp
index e0477069b340..1631eccd7013 100644
--- a/lib/Frontend/Rewrite/InclusionRewriter.cpp
+++ b/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/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/lib/Frontend/Rewrite/RewriteModernObjC.cpp
index 1954b24aedad..52b979c85f15 100644
--- a/lib/Frontend/Rewrite/RewriteModernObjC.cpp
+++ b/lib/Frontend/Rewrite/RewriteModernObjC.cpp
@@ -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.
@@ -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);
@@ -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;
@@ -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);
@@ -4720,7 +4720,7 @@ 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(),
Exp);
@@ -5314,7 +5314,7 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
UO_AddrOf,
Context->getPointerType(Context->VoidPtrTy),
VK_RValue, OK_Ordinary,
- SourceLocation());
+ SourceLocation(), false);
InitExprs.push_back(DescRefExpr);
// Add initializers for any closure decl refs.
@@ -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,7 +5349,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);
}
}
@@ -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);
}
@@ -5414,7 +5417,7 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
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.
@@ -6744,9 +6747,9 @@ 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";
@@ -7558,7 +7561,7 @@ Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
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);
diff --git a/lib/Frontend/Rewrite/RewriteObjC.cpp b/lib/Frontend/Rewrite/RewriteObjC.cpp
index 096b81bc3f08..9938f89eb869 100644
--- a/lib/Frontend/Rewrite/RewriteObjC.cpp
+++ b/lib/Frontend/Rewrite/RewriteObjC.cpp
@@ -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.
@@ -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);
@@ -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;
@@ -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);
@@ -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);
@@ -3875,7 +3875,7 @@ 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(),
Exp);
@@ -4438,7 +4438,7 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
UO_AddrOf,
Context->getPointerType(Context->VoidPtrTy),
VK_RValue, OK_Ordinary,
- SourceLocation());
+ SourceLocation(), false);
InitExprs.push_back(DescRefExpr);
// Add initializers for any closure decl refs.
@@ -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);
@@ -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);
}
@@ -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();
diff --git a/lib/Frontend/SerializedDiagnosticPrinter.cpp b/lib/Frontend/SerializedDiagnosticPrinter.cpp
index 7666fe10b381..ca60c4812f72 100644
--- a/lib/Frontend/SerializedDiagnosticPrinter.cpp
+++ b/lib/Frontend/SerializedDiagnosticPrinter.cpp
@@ -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,7 +305,7 @@ 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) {
@@ -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){
@@ -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);
@@ -462,7 +462,7 @@ void SDiagsWriter::EmitBlockInfoBlock() {
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,7 +470,7 @@ 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);
diff --git a/lib/Frontend/SerializedDiagnosticReader.cpp b/lib/Frontend/SerializedDiagnosticReader.cpp
index 08b7087fbad6..458717819c41 100644
--- a/lib/Frontend/SerializedDiagnosticReader.cpp
+++ b/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/lib/Frontend/TextDiagnostic.cpp b/lib/Frontend/TextDiagnostic.cpp
index 6a72b00c602b..85cd019005da 100644
--- a/lib/Frontend/TextDiagnostic.cpp
+++ b/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
@@ -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) {}
@@ -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
@@ -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();
+ auto &SM = Loc.getManager();
+ SourceLocation B = SM.getExpansionLoc(RI->getBegin());
+ CharSourceRange ERange = SM.getExpansionRange(RI->getEnd());
+ SourceLocation E = ERange.getEnd();
+ bool IsTokenRange = ERange.isTokenRange();
- // 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;
-
- 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;
}
@@ -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..
///
diff --git a/lib/Frontend/TextDiagnosticBuffer.cpp b/lib/Frontend/TextDiagnosticBuffer.cpp
index 288507310baa..44bb2bc29bc0 100644
--- a/lib/Frontend/TextDiagnosticBuffer.cpp
+++ b/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/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp
index 5dd3252d5b1e..a37382c116ae 100644
--- a/lib/Frontend/TextDiagnosticPrinter.cpp
+++ b/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/lib/Frontend/VerifyDiagnosticConsumer.cpp b/lib/Frontend/VerifyDiagnosticConsumer.cpp
index 0df5393a309b..21933f474ff5 100644
--- a/lib/Frontend/VerifyDiagnosticConsumer.cpp
+++ b/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/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index 4167e1fe20b8..ac2ee50a1e4b 100644
--- a/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/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);
@@ -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/lib/Headers/CMakeLists.txt b/lib/Headers/CMakeLists.txt
index 97ba3edea1c5..1930d8e225c7 100644
--- a/lib/Headers/CMakeLists.txt
+++ b/lib/Headers/CMakeLists.txt
@@ -34,10 +34,13 @@ set(files
__clang_cuda_builtin_vars.h
__clang_cuda_cmath.h
__clang_cuda_complex_builtins.h
+ __clang_cuda_device_functions.h
__clang_cuda_intrinsics.h
+ __clang_cuda_libdevice_declares.h
__clang_cuda_math_forward_declares.h
__clang_cuda_runtime_wrapper.h
cetintrin.h
+ cldemoteintrin.h
clzerointrin.h
cpuid.h
clflushoptintrin.h
@@ -55,6 +58,7 @@ set(files
immintrin.h
intrin.h
inttypes.h
+ invpcidintrin.h
iso646.h
limits.h
lwpintrin.h
@@ -63,16 +67,20 @@ set(files
mmintrin.h
mm_malloc.h
module.modulemap
+ movdirintrin.h
msa.h
mwaitxintrin.h
nmmintrin.h
opencl-c.h
pkuintrin.h
pmmintrin.h
+ pconfigintrin.h
popcntintrin.h
prfchwintrin.h
+ ptwriteintrin.h
rdseedintrin.h
rtmintrin.h
+ sgxintrin.h
s390intrin.h
shaintrin.h
smmintrin.h
@@ -93,6 +101,8 @@ set(files
varargs.h
vecintrin.h
vpclmulqdqintrin.h
+ waitpkgintrin.h
+ wbnoinvdintrin.h
wmmintrin.h
__wmmintrin_aes.h
__wmmintrin_pclmul.h
@@ -116,7 +126,12 @@ set(output_dir ${LLVM_LIBRARY_OUTPUT_INTDIR}/clang/${CLANG_VERSION}/include)
# Generate arm_neon.h
clang_tablegen(arm_neon.h -gen-arm-neon
+ -I ${CLANG_SOURCE_DIR}/include/clang/Basic/
SOURCE ${CLANG_SOURCE_DIR}/include/clang/Basic/arm_neon.td)
+# Generate arm_fp16.h
+clang_tablegen(arm_fp16.h -gen-arm-fp16
+ -I ${CLANG_SOURCE_DIR}/include/clang/Basic/
+ SOURCE ${CLANG_SOURCE_DIR}/include/clang/Basic/arm_fp16.td)
set(out_files)
foreach( f ${files} ${cuda_wrapper_files} )
@@ -134,6 +149,11 @@ add_custom_command(OUTPUT ${output_dir}/arm_neon.h
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/arm_neon.h ${output_dir}/arm_neon.h
COMMENT "Copying clang's arm_neon.h...")
list(APPEND out_files ${output_dir}/arm_neon.h)
+add_custom_command(OUTPUT ${output_dir}/arm_fp16.h
+ DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/arm_fp16.h
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/arm_fp16.h ${output_dir}/arm_fp16.h
+ COMMENT "Copying clang's arm_fp16.h...")
+list(APPEND out_files ${output_dir}/arm_fp16.h)
add_custom_target(clang-headers ALL DEPENDS ${out_files})
set_target_properties(clang-headers PROPERTIES FOLDER "Misc")
@@ -145,6 +165,12 @@ install(
DESTINATION lib${LLVM_LIBDIR_SUFFIX}/clang/${CLANG_VERSION}/include)
install(
+ FILES ${files} ${CMAKE_CURRENT_BINARY_DIR}/arm_fp16.h
+ COMPONENT clang-headers
+ PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
+ DESTINATION lib${LLVM_LIBDIR_SUFFIX}/clang/${CLANG_VERSION}/include)
+
+install(
FILES ${cuda_wrapper_files}
COMPONENT clang-headers
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
diff --git a/lib/Headers/__clang_cuda_builtin_vars.h b/lib/Headers/__clang_cuda_builtin_vars.h
index 6f5eb9c78d85..290c4b298433 100644
--- a/lib/Headers/__clang_cuda_builtin_vars.h
+++ b/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/lib/Headers/__clang_cuda_device_functions.h b/lib/Headers/__clang_cuda_device_functions.h
new file mode 100644
index 000000000000..67bbc68b1637
--- /dev/null
+++ b/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/lib/Headers/__clang_cuda_intrinsics.h b/lib/Headers/__clang_cuda_intrinsics.h
index 1794eb3dc1d6..3c0cde94ed44 100644
--- a/lib/Headers/__clang_cuda_intrinsics.h
+++ b/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/lib/Headers/__clang_cuda_libdevice_declares.h b/lib/Headers/__clang_cuda_libdevice_declares.h
new file mode 100644
index 000000000000..71df7f849d15
--- /dev/null
+++ b/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/lib/Headers/__clang_cuda_runtime_wrapper.h b/lib/Headers/__clang_cuda_runtime_wrapper.h
index a82a8490f367..09705a273a47 100644
--- a/lib/Headers/__clang_cuda_runtime_wrapper.h
+++ b/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/lib/Headers/__wmmintrin_aes.h b/lib/Headers/__wmmintrin_aes.h
index 3a2ee1b2ef2e..70c355efc48c 100644
--- a/lib/Headers/__wmmintrin_aes.h
+++ b/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/lib/Headers/__wmmintrin_pclmul.h b/lib/Headers/__wmmintrin_pclmul.h
index e9c6a9f6d415..e0f928796ac1 100644
--- a/lib/Headers/__wmmintrin_pclmul.h
+++ b/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/lib/Headers/ammintrin.h b/lib/Headers/ammintrin.h
index 2843a7a2677f..680b4465eaae 100644
--- a/lib/Headers/ammintrin.h
+++ b/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/lib/Headers/avx2intrin.h b/lib/Headers/avx2intrin.h
index caf4ced92054..9688a96fde18 100644
--- a/lib/Headers/avx2intrin.h
+++ b/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/lib/Headers/avx512bitalgintrin.h b/lib/Headers/avx512bitalgintrin.h
index 2dd1471d2f7e..56046f8c4999 100644
--- a/lib/Headers/avx512bitalgintrin.h
+++ b/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/lib/Headers/avx512bwintrin.h b/lib/Headers/avx512bwintrin.h
index 3ff0e3aafdcc..fc4632374977 100644
--- a/lib/Headers/avx512bwintrin.h
+++ b/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
@@ -1854,13 +1575,15 @@ _mm512_maskz_set1_epi8 (__mmask64 __M, char __A)
static __inline__ __mmask64 __DEFAULT_FN_ATTRS
_mm512_kunpackd (__mmask64 __A, __mmask64 __B)
{
- return (__mmask64) (( __A & 0xFFFFFFFF) | ( __B << 32));
+ return (__mmask64) __builtin_ia32_kunpckdi ((__mmask64) __A,
+ (__mmask64) __B);
}
static __inline__ __mmask32 __DEFAULT_FN_ATTRS
_mm512_kunpackw (__mmask32 __A, __mmask32 __B)
{
-return (__mmask32) (( __A & 0xFFFF) | ( __B << 16));
+ return (__mmask32) __builtin_ia32_kunpcksi ((__mmask32) __A,
+ (__mmask32) __B);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -1876,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);
}
@@ -1893,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
@@ -1916,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
@@ -1994,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,
@@ -2037,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);
}
@@ -2062,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/lib/Headers/avx512cdintrin.h b/lib/Headers/avx512cdintrin.h
index ec7e0cd443b4..e63902743c06 100644
--- a/lib/Headers/avx512cdintrin.h
+++ b/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/lib/Headers/avx512dqintrin.h b/lib/Headers/avx512dqintrin.h
index 2c431d9740cd..8a00b3afa9d5 100644
--- a/lib/Headers/avx512dqintrin.h
+++ b/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/lib/Headers/avx512erintrin.h b/lib/Headers/avx512erintrin.h
index 8ff212c42211..6348275c8d31 100644
--- a/lib/Headers/avx512erintrin.h
+++ b/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/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h
index d34f0b1327ae..81696953b76e 100644
--- a/lib/Headers/avx512fintrin.h
+++ b/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,64 +258,67 @@ _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
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_set1_epi32(__mmask16 __M, int __A)
{
return (__m512i)__builtin_ia32_selectd_512(__M,
@@ -324,57 +326,54 @@ _mm512_maskz_set1_epi32(__mmask16 __M, int __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)); })
+ (__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)); })
-
-
-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) (( __A & 0xFF) | ( __B << 8));
+ 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/lib/Headers/avx512ifmaintrin.h b/lib/Headers/avx512ifmaintrin.h
index 5defbaea8bcc..159713049c1a 100644
--- a/lib/Headers/avx512ifmaintrin.h
+++ b/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/lib/Headers/avx512ifmavlintrin.h b/lib/Headers/avx512ifmavlintrin.h
index 131ee5cb4f88..afdea888c55b 100644
--- a/lib/Headers/avx512ifmavlintrin.h
+++ b/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/lib/Headers/avx512pfintrin.h b/lib/Headers/avx512pfintrin.h
index c7fa3cf313e3..5b8260b77c63 100644
--- a/lib/Headers/avx512pfintrin.h
+++ b/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/lib/Headers/avx512vbmi2intrin.h b/lib/Headers/avx512vbmi2intrin.h
index 43e97b40a098..d2a58094fd07 100644
--- a/lib/Headers/avx512vbmi2intrin.h
+++ b/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/lib/Headers/avx512vbmiintrin.h b/lib/Headers/avx512vbmiintrin.h
index 837238eda97f..b6e93c285871 100644
--- a/lib/Headers/avx512vbmiintrin.h
+++ b/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/lib/Headers/avx512vbmivlintrin.h b/lib/Headers/avx512vbmivlintrin.h
index 105c6d142fa6..9a0400b2b5d5 100644
--- a/lib/Headers/avx512vbmivlintrin.h
+++ b/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/lib/Headers/avx512vlbitalgintrin.h b/lib/Headers/avx512vlbitalgintrin.h
index 76eb87721b8b..64860b29254f 100644
--- a/lib/Headers/avx512vlbitalgintrin.h
+++ b/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,35 +54,35 @@ _mm256_maskz_popcnt_epi16(__mmask16 __U, __m256i __B)
__B);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm128_popcnt_epi16(__m128i __A)
+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
-_mm128_mask_popcnt_epi16(__m128i __A, __mmask8 __U, __m128i __B)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_mask_popcnt_epi16(__m128i __A, __mmask8 __U, __m128i __B)
{
return (__m128i) __builtin_ia32_selectw_128((__mmask8) __U,
- (__v8hi) _mm128_popcnt_epi16(__B),
+ (__v8hi) _mm_popcnt_epi16(__B),
(__v8hi) __A);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm128_maskz_popcnt_epi16(__mmask8 __U, __m128i __B)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_maskz_popcnt_epi16(__mmask8 __U, __m128i __B)
{
- return _mm128_mask_popcnt_epi16((__m128i) _mm_setzero_si128(),
+ return _mm_mask_popcnt_epi16((__m128i) _mm_setzero_si128(),
__U,
__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,61 +98,62 @@ _mm256_maskz_popcnt_epi8(__mmask32 __U, __m256i __B)
__B);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm128_popcnt_epi8(__m128i __A)
+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
-_mm128_mask_popcnt_epi8(__m128i __A, __mmask16 __U, __m128i __B)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_mask_popcnt_epi8(__m128i __A, __mmask16 __U, __m128i __B)
{
return (__m128i) __builtin_ia32_selectb_128((__mmask16) __U,
- (__v16qi) _mm128_popcnt_epi8(__B),
+ (__v16qi) _mm_popcnt_epi8(__B),
(__v16qi) __A);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm128_maskz_popcnt_epi8(__mmask16 __U, __m128i __B)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_maskz_popcnt_epi8(__mmask16 __U, __m128i __B)
{
- return _mm128_mask_popcnt_epi8((__m128i) _mm_setzero_si128(),
+ return _mm_mask_popcnt_epi8((__m128i) _mm_setzero_si128(),
__U,
__B);
}
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm256_mask_bitshuffle_epi32_mask(__mmask32 __U, __m256i __A, __m256i __B)
+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,
(__v32qi) __B,
__U);
}
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm256_bitshuffle_epi32_mask(__m256i __A, __m256i __B)
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS256
+_mm256_bitshuffle_epi64_mask(__m256i __A, __m256i __B)
{
- return _mm256_mask_bitshuffle_epi32_mask((__mmask32) -1,
+ return _mm256_mask_bitshuffle_epi64_mask((__mmask32) -1,
__A,
__B);
}
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm128_mask_bitshuffle_epi16_mask(__mmask16 __U, __m128i __A, __m128i __B)
+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,
(__v16qi) __B,
__U);
}
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm128_bitshuffle_epi16_mask(__m128i __A, __m128i __B)
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS128
+_mm_bitshuffle_epi64_mask(__m128i __A, __m128i __B)
{
- return _mm128_mask_bitshuffle_epi16_mask((__mmask16) -1,
+ return _mm_mask_bitshuffle_epi64_mask((__mmask16) -1,
__A,
__B);
}
-#undef __DEFAULT_FN_ATTRS
+#undef __DEFAULT_FN_ATTRS128
+#undef __DEFAULT_FN_ATTRS256
#endif
diff --git a/lib/Headers/avx512vlbwintrin.h b/lib/Headers/avx512vlbwintrin.h
index e940e2b68533..1b038dd04df6 100644
--- a/lib/Headers/avx512vlbwintrin.h
+++ b/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/lib/Headers/avx512vlcdintrin.h b/lib/Headers/avx512vlcdintrin.h
index 8f1cd25f0b50..127c5b132ac7 100644
--- a/lib/Headers/avx512vlcdintrin.h
+++ b/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/lib/Headers/avx512vldqintrin.h b/lib/Headers/avx512vldqintrin.h
index d80df9eaffea..9d13846e8964 100644
--- a/lib/Headers/avx512vldqintrin.h
+++ b/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/lib/Headers/avx512vlintrin.h b/lib/Headers/avx512vlintrin.h
index fb8056e3f8d8..0ee1d00ef4d2 100644
--- a/lib/Headers/avx512vlintrin.h
+++ b/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/lib/Headers/avx512vlvbmi2intrin.h b/lib/Headers/avx512vlvbmi2intrin.h
index d1ec4976f274..baaf5654631c 100644
--- a/lib/Headers/avx512vlvbmi2intrin.h
+++ b/lib/Headers/avx512vlvbmi2intrin.h
@@ -29,130 +29,120 @@
#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
-_mm128_setzero_hi(void) {
- return (__m128i)(__v8hi){ 0, 0, 0, 0, 0, 0, 0, 0 };
-}
-
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm128_mask_compress_epi16(__m128i __S, __mmask8 __U, __m128i __D)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_mask_compress_epi16(__m128i __S, __mmask8 __U, __m128i __D)
{
return (__m128i) __builtin_ia32_compresshi128_mask ((__v8hi) __D,
(__v8hi) __S,
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm128_maskz_compress_epi16(__mmask8 __U, __m128i __D)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_maskz_compress_epi16(__mmask8 __U, __m128i __D)
{
return (__m128i) __builtin_ia32_compresshi128_mask ((__v8hi) __D,
- (__v8hi) _mm128_setzero_hi(),
+ (__v8hi) _mm_setzero_si128(),
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm128_mask_compress_epi8(__m128i __S, __mmask16 __U, __m128i __D)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_mask_compress_epi8(__m128i __S, __mmask16 __U, __m128i __D)
{
return (__m128i) __builtin_ia32_compressqi128_mask ((__v16qi) __D,
(__v16qi) __S,
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm128_maskz_compress_epi8(__mmask16 __U, __m128i __D)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_maskz_compress_epi8(__mmask16 __U, __m128i __D)
{
return (__m128i) __builtin_ia32_compressqi128_mask ((__v16qi) __D,
- (__v16qi) _mm128_setzero_hi(),
+ (__v16qi) _mm_setzero_si128(),
__U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
-_mm128_mask_compressstoreu_epi16(void *__P, __mmask8 __U, __m128i __D)
+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
-_mm128_mask_compressstoreu_epi8(void *__P, __mmask16 __U, __m128i __D)
+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
-_mm128_mask_expand_epi16(__m128i __S, __mmask8 __U, __m128i __D)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_mask_expand_epi16(__m128i __S, __mmask8 __U, __m128i __D)
{
return (__m128i) __builtin_ia32_expandhi128_mask ((__v8hi) __D,
(__v8hi) __S,
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm128_maskz_expand_epi16(__mmask8 __U, __m128i __D)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_maskz_expand_epi16(__mmask8 __U, __m128i __D)
{
return (__m128i) __builtin_ia32_expandhi128_mask ((__v8hi) __D,
- (__v8hi) _mm128_setzero_hi(),
+ (__v8hi) _mm_setzero_si128(),
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm128_mask_expand_epi8(__m128i __S, __mmask16 __U, __m128i __D)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_mask_expand_epi8(__m128i __S, __mmask16 __U, __m128i __D)
{
return (__m128i) __builtin_ia32_expandqi128_mask ((__v16qi) __D,
(__v16qi) __S,
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm128_maskz_expand_epi8(__mmask16 __U, __m128i __D)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_maskz_expand_epi8(__mmask16 __U, __m128i __D)
{
return (__m128i) __builtin_ia32_expandqi128_mask ((__v16qi) __D,
- (__v16qi) _mm128_setzero_hi(),
+ (__v16qi) _mm_setzero_si128(),
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm128_mask_expandloadu_epi16(__m128i __S, __mmask8 __U, void const *__P)
+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,
(__v8hi) __S,
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm128_maskz_expandloadu_epi16(__mmask8 __U, void const *__P)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_maskz_expandloadu_epi16(__mmask8 __U, void const *__P)
{
return (__m128i) __builtin_ia32_expandloadhi128_mask ((const __v8hi *)__P,
- (__v8hi) _mm128_setzero_hi(),
+ (__v8hi) _mm_setzero_si128(),
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm128_mask_expandloadu_epi8(__m128i __S, __mmask16 __U, void const *__P)
+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,
(__v16qi) __S,
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm128_maskz_expandloadu_epi8(__mmask16 __U, void const *__P)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_maskz_expandloadu_epi8(__mmask16 __U, void const *__P)
{
return (__m128i) __builtin_ia32_expandloadqi128_mask ((const __v16qi *)__P,
- (__v16qi) _mm128_setzero_hi(),
+ (__v16qi) _mm_setzero_si128(),
__U);
}
-static __inline __m256i __DEFAULT_FN_ATTRS
-_mm256_setzero_hi(void) {
- return (__m256i)(__v16hi){ 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_mask_compress_epi16(__m256i __S, __mmask16 __U, __m256i __D)
{
return (__m256i) __builtin_ia32_compresshi256_mask ((__v16hi) __D,
@@ -160,15 +150,15 @@ _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,
- (__v16hi) _mm256_setzero_hi(),
+ (__v16hi) _mm256_setzero_si256(),
__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,
@@ -176,29 +166,29 @@ _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,
- (__v32qi) _mm256_setzero_hi(),
+ (__v32qi) _mm256_setzero_si256(),
__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,
@@ -206,15 +196,15 @@ _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,
- (__v16hi) _mm256_setzero_hi(),
+ (__v16hi) _mm256_setzero_si256(),
__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,
@@ -222,15 +212,15 @@ _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,
- (__v32qi) _mm256_setzero_hi(),
+ (__v32qi) _mm256_setzero_si256(),
__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,
@@ -238,15 +228,15 @@ _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,
- (__v16hi) _mm256_setzero_hi(),
+ (__v16hi) _mm256_setzero_si256(),
__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,
@@ -254,171 +244,183 @@ _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,
- (__v32qi) _mm256_setzero_hi(),
+ (__v32qi) _mm256_setzero_si256(),
__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_hi(), (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 _mm128_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 _mm128_maskz_shldi_epi64(U, A, B, I) \
- _mm128_mask_shldi_epi64(_mm128_setzero_hi(), (U), (A), (B), (I))
+#define _mm_maskz_shldi_epi64(U, A, B, I) \
+ (__m128i)__builtin_ia32_selectq_128((__mmask8)(U), \
+ (__v2di)_mm_shldi_epi64((A), (B), (I)), \
+ (__v2di)_mm_setzero_si128())
-#define _mm128_shldi_epi64(A, B, I) \
- _mm128_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_hi(), (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 _mm128_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 _mm128_maskz_shldi_epi32(U, A, B, I) \
- _mm128_mask_shldi_epi32(_mm128_setzero_hi(), (U), (A), (B), (I))
+#define _mm_maskz_shldi_epi32(U, A, B, I) \
+ (__m128i)__builtin_ia32_selectd_128((__mmask8)(U), \
+ (__v4si)_mm_shldi_epi32((A), (B), (I)), \
+ (__v4si)_mm_setzero_si128())
-#define _mm128_shldi_epi32(A, B, I) \
- _mm128_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_hi(), (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 _mm128_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 _mm128_maskz_shldi_epi16(U, A, B, I) \
- _mm128_mask_shldi_epi16(_mm128_setzero_hi(), (U), (A), (B), (I))
+#define _mm_maskz_shldi_epi16(U, A, B, I) \
+ (__m128i)__builtin_ia32_selectw_128((__mmask8)(U), \
+ (__v8hi)_mm_shldi_epi16((A), (B), (I)), \
+ (__v8hi)_mm_setzero_si128())
-#define _mm128_shldi_epi16(A, B, I) \
- _mm128_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_hi(), (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 _mm128_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 _mm128_maskz_shrdi_epi64(U, A, B, I) \
- _mm128_mask_shrdi_epi64(_mm128_setzero_hi(), (U), (A), (B), (I))
+#define _mm_maskz_shrdi_epi64(U, A, B, I) \
+ (__m128i)__builtin_ia32_selectq_128((__mmask8)(U), \
+ (__v2di)_mm_shrdi_epi64((A), (B), (I)), \
+ (__v2di)_mm_setzero_si128())
-#define _mm128_shrdi_epi64(A, B, I) \
- _mm128_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_hi(), (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 _mm128_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 _mm128_maskz_shrdi_epi32(U, A, B, I) \
- _mm128_mask_shrdi_epi32(_mm128_setzero_hi(), (U), (A), (B), (I))
+#define _mm_maskz_shrdi_epi32(U, A, B, I) \
+ (__m128i)__builtin_ia32_selectd_128((__mmask8)(U), \
+ (__v4si)_mm_shrdi_epi32((A), (B), (I)), \
+ (__v4si)_mm_setzero_si128())
-#define _mm128_shrdi_epi32(A, B, I) \
- _mm128_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_hi(), (U), (A), (B), (I))
-
-#define _mm256_shrdi_epi16(A, B, I) \
- _mm256_mask_shrdi_epi16(_mm256_undefined_si256(), (__mmask8)(-1), (A), (B), (I))
+ (__m256i)__builtin_ia32_selectw_256((__mmask16)(U), \
+ (__v16hi)_mm256_shrdi_epi16((A), (B), (I)), \
+ (__v16hi)_mm256_setzero_si256())
-#define _mm128_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_shrdi_epi16(A, B, I) \
+ (__m128i)__builtin_ia32_vpshrdw128((__v8hi)(__m128i)(A), \
+ (__v8hi)(__m128i)(B), (int)(I))
-#define _mm128_maskz_shrdi_epi16(U, A, B, I) \
- _mm128_mask_shrdi_epi16(_mm128_setzero_hi(), (U), (A), (B), (I))
+#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 _mm128_shrdi_epi16(A, B, I) \
- _mm128_mask_shrdi_epi16(_mm_undefined_si128(), (__mmask8)(-1), (A), (B), (I))
+#define _mm_maskz_shrdi_epi16(U, 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,
@@ -427,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,
@@ -436,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,
@@ -445,8 +447,8 @@ _mm256_shldv_epi64(__m256i __S, __m256i __A, __m256i __B)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm128_mask_shldv_epi64(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
+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,
(__v2di) __A,
@@ -454,8 +456,8 @@ _mm128_mask_shldv_epi64(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm128_maskz_shldv_epi64(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
+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,
(__v2di) __A,
@@ -463,8 +465,8 @@ _mm128_maskz_shldv_epi64(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm128_shldv_epi64(__m128i __S, __m128i __A, __m128i __B)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_shldv_epi64(__m128i __S, __m128i __A, __m128i __B)
{
return (__m128i) __builtin_ia32_vpshldvq128_mask ((__v2di) __S,
(__v2di) __A,
@@ -472,7 +474,7 @@ _mm128_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,
@@ -481,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,
@@ -490,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,
@@ -499,8 +501,8 @@ _mm256_shldv_epi32(__m256i __S, __m256i __A, __m256i __B)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm128_mask_shldv_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
+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,
(__v4si) __A,
@@ -508,8 +510,8 @@ _mm128_mask_shldv_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm128_maskz_shldv_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
+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,
(__v4si) __A,
@@ -517,8 +519,8 @@ _mm128_maskz_shldv_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm128_shldv_epi32(__m128i __S, __m128i __A, __m128i __B)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_shldv_epi32(__m128i __S, __m128i __A, __m128i __B)
{
return (__m128i) __builtin_ia32_vpshldvd128_mask ((__v4si) __S,
(__v4si) __A,
@@ -526,7 +528,7 @@ _mm128_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,
@@ -535,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,
@@ -544,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,
@@ -553,8 +555,8 @@ _mm256_shldv_epi16(__m256i __S, __m256i __A, __m256i __B)
(__mmask16) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm128_mask_shldv_epi16(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
+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,
(__v8hi) __A,
@@ -562,8 +564,8 @@ _mm128_mask_shldv_epi16(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm128_maskz_shldv_epi16(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
+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,
(__v8hi) __A,
@@ -571,8 +573,8 @@ _mm128_maskz_shldv_epi16(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm128_shldv_epi16(__m128i __S, __m128i __A, __m128i __B)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_shldv_epi16(__m128i __S, __m128i __A, __m128i __B)
{
return (__m128i) __builtin_ia32_vpshldvw128_mask ((__v8hi) __S,
(__v8hi) __A,
@@ -580,7 +582,7 @@ _mm128_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,
@@ -589,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,
@@ -598,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,
@@ -607,8 +609,8 @@ _mm256_shrdv_epi64(__m256i __S, __m256i __A, __m256i __B)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm128_mask_shrdv_epi64(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
+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,
(__v2di) __A,
@@ -616,8 +618,8 @@ _mm128_mask_shrdv_epi64(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm128_maskz_shrdv_epi64(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
+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,
(__v2di) __A,
@@ -625,8 +627,8 @@ _mm128_maskz_shrdv_epi64(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm128_shrdv_epi64(__m128i __S, __m128i __A, __m128i __B)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_shrdv_epi64(__m128i __S, __m128i __A, __m128i __B)
{
return (__m128i) __builtin_ia32_vpshrdvq128_mask ((__v2di) __S,
(__v2di) __A,
@@ -634,7 +636,7 @@ _mm128_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,
@@ -643,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,
@@ -652,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,
@@ -661,8 +663,8 @@ _mm256_shrdv_epi32(__m256i __S, __m256i __A, __m256i __B)
(__mmask8) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm128_mask_shrdv_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
+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,
(__v4si) __A,
@@ -670,8 +672,8 @@ _mm128_mask_shrdv_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm128_maskz_shrdv_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
+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,
(__v4si) __A,
@@ -679,8 +681,8 @@ _mm128_maskz_shrdv_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm128_shrdv_epi32(__m128i __S, __m128i __A, __m128i __B)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_shrdv_epi32(__m128i __S, __m128i __A, __m128i __B)
{
return (__m128i) __builtin_ia32_vpshrdvd128_mask ((__v4si) __S,
(__v4si) __A,
@@ -688,7 +690,7 @@ _mm128_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,
@@ -697,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,
@@ -706,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,
@@ -715,8 +717,8 @@ _mm256_shrdv_epi16(__m256i __S, __m256i __A, __m256i __B)
(__mmask16) -1);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm128_mask_shrdv_epi16(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
+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,
(__v8hi) __A,
@@ -724,8 +726,8 @@ _mm128_mask_shrdv_epi16(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm128_maskz_shrdv_epi16(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
+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,
(__v8hi) __A,
@@ -733,8 +735,8 @@ _mm128_maskz_shrdv_epi16(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
__U);
}
-static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm128_shrdv_epi16(__m128i __S, __m128i __A, __m128i __B)
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_shrdv_epi16(__m128i __S, __m128i __A, __m128i __B)
{
return (__m128i) __builtin_ia32_vpshrdvw128_mask ((__v8hi) __S,
(__v8hi) __A,
@@ -743,6 +745,7 @@ _mm128_shrdv_epi16(__m128i __S, __m128i __A, __m128i __B)
}
-#undef __DEFAULT_FN_ATTRS
+#undef __DEFAULT_FN_ATTRS128
+#undef __DEFAULT_FN_ATTRS256
#endif
diff --git a/lib/Headers/avx512vlvnniintrin.h b/lib/Headers/avx512vlvnniintrin.h
index 745ae8b7ad3d..62382268ec9f 100644
--- a/lib/Headers/avx512vlvnniintrin.h
+++ b/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
-_mm128_mask_dpbusd_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
+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
-_mm128_maskz_dpbusd_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
+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
-_mm128_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
-_mm128_mask_dpbusds_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
+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
-_mm128_maskz_dpbusds_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
+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
-_mm128_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
-_mm128_mask_dpwssd_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
+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
-_mm128_maskz_dpwssd_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
+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
-_mm128_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
-_mm128_mask_dpwssds_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
+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
-_mm128_maskz_dpwssds_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
+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
-_mm128_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/lib/Headers/avx512vnniintrin.h b/lib/Headers/avx512vnniintrin.h
index 0c6badd231aa..620ef5a78959 100644
--- a/lib/Headers/avx512vnniintrin.h
+++ b/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/lib/Headers/avx512vpopcntdqintrin.h b/lib/Headers/avx512vpopcntdqintrin.h
index 34ab84932e7a..c99f5945699e 100644
--- a/lib/Headers/avx512vpopcntdqintrin.h
+++ b/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/lib/Headers/avx512vpopcntdqvlintrin.h b/lib/Headers/avx512vpopcntdqvlintrin.h
index c2058a8f5154..681a75fa07cd 100644
--- a/lib/Headers/avx512vpopcntdqvlintrin.h
+++ b/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/lib/Headers/avxintrin.h b/lib/Headers/avxintrin.h
index dff5897b6bb6..cb15396b3faf 100644
--- a/lib/Headers/avxintrin.h
+++ b/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/lib/Headers/bmiintrin.h b/lib/Headers/bmiintrin.h
index e812a1632b91..d03bef442a28 100644
--- a/lib/Headers/bmiintrin.h
+++ b/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/lib/Headers/cetintrin.h b/lib/Headers/cetintrin.h
index 1256a3f63a16..120c95424da1 100644
--- a/lib/Headers/cetintrin.h
+++ b/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/lib/Headers/cldemoteintrin.h b/lib/Headers/cldemoteintrin.h
new file mode 100644
index 000000000000..fa78148ebf02
--- /dev/null
+++ b/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/lib/Headers/clflushoptintrin.h b/lib/Headers/clflushoptintrin.h
index f1f133023441..79bb4589fc75 100644
--- a/lib/Headers/clflushoptintrin.h
+++ b/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/lib/Headers/clwbintrin.h b/lib/Headers/clwbintrin.h
index 2594a6c38756..c09286ba6748 100644
--- a/lib/Headers/clwbintrin.h
+++ b/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/lib/Headers/clzerointrin.h b/lib/Headers/clzerointrin.h
index ed7478ff87ea..07628acd8005 100644
--- a/lib/Headers/clzerointrin.h
+++ b/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>
///
@@ -47,4 +47,4 @@ _mm_clzero (void * __line)
#undef __DEFAULT_FN_ATTRS
-#endif /* _CLZEROINTRIN_H */
+#endif /* __CLZEROINTRIN_H */
diff --git a/lib/Headers/cpuid.h b/lib/Headers/cpuid.h
index 3ae90de0b91f..fce6af52dd3f 100644
--- a/lib/Headers/cpuid.h
+++ b/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/lib/Headers/cuda_wrappers/algorithm b/lib/Headers/cuda_wrappers/algorithm
index cedd70762c48..01af18360d8d 100644
--- a/lib/Headers/cuda_wrappers/algorithm
+++ b/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/lib/Headers/emmintrin.h b/lib/Headers/emmintrin.h
index 3372508a7f81..f0ea7cd05c63 100644
--- a/lib/Headers/emmintrin.h
+++ b/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,10 +214,10 @@ _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.
+/// The upper 64 bits of the result are copied from the upper
+/// double-precision value of the first operand.
///
/// \headerfile <x86intrin.h>
///
@@ -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,10 +257,10 @@ _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.
+/// result. The upper 64 bits of the result are copied from the upper
+/// double-precision value of the first operand.
///
/// \headerfile <x86intrin.h>
///
@@ -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,10 +301,10 @@ _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.
+/// result. The upper 64 bits of the result are copied from the upper
+/// double-precision value of the first operand.
///
/// \headerfile <x86intrin.h>
///
@@ -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,12 +978,14 @@ 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
-/// the two 128-bit floating-point vectors of [2 x double] for equality. The
-/// comparison yields 0 for false, 1 for true.
+/// 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
+/// lower double-precision values is NaN, 0 is returned.
///
/// \headerfile <x86intrin.h>
///
@@ -996,19 +997,21 @@ _mm_cmpnge_sd(__m128d __a, __m128d __b)
/// \param __b
/// A 128-bit vector of [2 x double]. The lower double-precision value is
/// compared to the lower double-precision value of \a __a.
-/// \returns An integer containing the comparison results.
+/// \returns An integer containing the comparison results. If either of the two
+/// lower double-precision values is NaN, 0 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_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.
///
-/// The comparison yields 0 for false, 1 for true.
+/// The comparison yields 0 for false, 1 for true. If either of the two
+/// lower double-precision values is NaN, 0 is returned.
///
/// \headerfile <x86intrin.h>
///
@@ -1020,19 +1023,21 @@ _mm_comieq_sd(__m128d __a, __m128d __b)
/// \param __b
/// A 128-bit vector of [2 x double]. The lower double-precision value is
/// compared to the lower double-precision value of \a __a.
-/// \returns An integer containing the comparison results.
+/// \returns An integer containing the comparison results. If either of the two
+/// lower double-precision values is NaN, 0 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_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.
///
-/// The comparison yields 0 for false, 1 for true.
+/// The comparison yields 0 for false, 1 for true. If either of the two
+/// lower double-precision values is NaN, 0 is returned.
///
/// \headerfile <x86intrin.h>
///
@@ -1044,19 +1049,21 @@ _mm_comilt_sd(__m128d __a, __m128d __b)
/// \param __b
/// A 128-bit vector of [2 x double]. The lower double-precision value is
/// compared to the lower double-precision value of \a __a.
-/// \returns An integer containing the comparison results.
+/// \returns An integer containing the comparison results. If either of the two
+/// lower double-precision values is NaN, 0 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_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.
///
-/// The comparison yields 0 for false, 1 for true.
+/// The comparison yields 0 for false, 1 for true. If either of the two
+/// lower double-precision values is NaN, 0 is returned.
///
/// \headerfile <x86intrin.h>
///
@@ -1068,19 +1075,21 @@ _mm_comile_sd(__m128d __a, __m128d __b)
/// \param __b
/// A 128-bit vector of [2 x double]. The lower double-precision value is
/// compared to the lower double-precision value of \a __a.
-/// \returns An integer containing the comparison results.
+/// \returns An integer containing the comparison results. If either of the two
+/// lower double-precision values is NaN, 0 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_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.
///
-/// The comparison yields 0 for false, 1 for true.
+/// The comparison yields 0 for false, 1 for true. If either of the two
+/// lower double-precision values is NaN, 0 is returned.
///
/// \headerfile <x86intrin.h>
///
@@ -1092,19 +1101,21 @@ _mm_comigt_sd(__m128d __a, __m128d __b)
/// \param __b
/// A 128-bit vector of [2 x double]. The lower double-precision value is
/// compared to the lower double-precision value of \a __a.
-/// \returns An integer containing the comparison results.
+/// \returns An integer containing the comparison results. If either of the two
+/// lower double-precision values is NaN, 0 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_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.
///
-/// The comparison yields 0 for false, 1 for true.
+/// The comparison yields 0 for false, 1 for true. If either of the two
+/// lower double-precision values is NaN, 1 is returned.
///
/// \headerfile <x86intrin.h>
///
@@ -1116,18 +1127,19 @@ _mm_comige_sd(__m128d __a, __m128d __b)
/// \param __b
/// A 128-bit vector of [2 x double]. The lower double-precision value is
/// compared to the lower double-precision value of \a __a.
-/// \returns An integer containing the comparison results.
+/// \returns An integer containing the comparison results. If either of the two
+/// lower double-precision values is NaN, 1 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_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.
///
-/// If either of the two lower double-precision values is NaN, 1 is returned.
+/// If either of the two lower double-precision values is NaN, 0 is returned.
///
/// \headerfile <x86intrin.h>
///
@@ -1140,20 +1152,20 @@ _mm_comineq_sd(__m128d __a, __m128d __b)
/// A 128-bit vector of [2 x double]. The lower double-precision value is
/// compared to the lower double-precision value of \a __a.
/// \returns An integer containing the comparison results. If either of the two
-/// lower double-precision values is NaN, 1 is returned.
+/// lower double-precision values is NaN, 0 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_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.
///
/// The comparison yields 0 for false, 1 for true. If either of the two lower
-/// double-precision values is NaN, 1 is returned.
+/// double-precision values is NaN, 0 is returned.
///
/// \headerfile <x86intrin.h>
///
@@ -1166,20 +1178,20 @@ _mm_ucomieq_sd(__m128d __a, __m128d __b)
/// A 128-bit vector of [2 x double]. The lower double-precision value is
/// compared to the lower double-precision value of \a __a.
/// \returns An integer containing the comparison results. If either of the two
-/// lower double-precision values is NaN, 1 is returned.
+/// lower double-precision values is NaN, 0 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_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.
///
/// The comparison yields 0 for false, 1 for true. If either of the two lower
-/// double-precision values is NaN, 1 is returned.
+/// double-precision values is NaN, 0 is returned.
///
/// \headerfile <x86intrin.h>
///
@@ -1192,14 +1204,14 @@ _mm_ucomilt_sd(__m128d __a, __m128d __b)
/// A 128-bit vector of [2 x double]. The lower double-precision value is
/// compared to the lower double-precision value of \a __a.
/// \returns An integer containing the comparison results. If either of the two
-/// lower double-precision values is NaN, 1 is returned.
+/// lower double-precision values is NaN, 0 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_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.
@@ -1225,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.
@@ -1251,13 +1263,13 @@ _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.
///
/// The comparison yields 0 for false, 1 for true. If either of the two lower
-/// double-precision values is NaN, 0 is returned.
+/// double-precision values is NaN, 1 is returned.
///
/// \headerfile <x86intrin.h>
///
@@ -1270,14 +1282,14 @@ _mm_ucomige_sd(__m128d __a, __m128d __b)
/// A 128-bit vector of [2 x double]. The lower double-precision value is
/// compared to the lower double-precision value of \a __a.
/// \returns An integer containing the comparison result. If either of the two
-/// lower double-precision values is NaN, 0 is returned.
+/// lower double-precision values is NaN, 1 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_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.
@@ -1296,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.
@@ -1317,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].
///
@@ -1340,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.
@@ -1359,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>
@@ -1376,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
@@ -1401,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.
@@ -1425,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
@@ -1451,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].
///
@@ -1474,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>
@@ -1492,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].
///
@@ -1503,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].
///
@@ -1523,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].
///
@@ -1540,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>
@@ -1563,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>
@@ -1580,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].
///
@@ -1599,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>
@@ -1625,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>
@@ -1645,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>
@@ -1663,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>
@@ -1684,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.
///
@@ -1711,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.
///
@@ -1738,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.
@@ -1758,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.
///
@@ -1775,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.
///
@@ -1793,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.
///
@@ -1814,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>
@@ -1831,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.
///
@@ -1852,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>
@@ -1867,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.
///
@@ -1888,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>
@@ -1911,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>
@@ -1930,19 +1943,20 @@ _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>
///
-/// This intrinsic corresponds to the <c>VMOVDDUP + VMOVAPD / MOVLHPS + MOVAPS </c> instruction.
+/// This intrinsic corresponds to the
+/// <c> VMOVDDUP + VMOVAPD / MOVLHPS + MOVAPS </c> instruction.
///
/// \param __dp
/// A pointer to a memory location that can store two double-precision
/// values.
/// \param __a
/// A 128-bit vector of [2 x double] whose lower 64 bits are copied to each
-/// of the values in \a dp.
+/// of the values in \a __dp.
static __inline__ void __DEFAULT_FN_ATTRS
_mm_store1_pd(double *__dp, __m128d __a)
{
@@ -1950,25 +1964,27 @@ _mm_store1_pd(double *__dp, __m128d __a)
_mm_store_pd(__dp, __a);
}
-/// \brief Stores a 128-bit vector of [2 x double] into an aligned memory
-/// location.
+/// 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>
///
-/// This intrinsic corresponds to the <c> VMOVAPD / MOVAPD </c> instruction.
+/// This intrinsic corresponds to the
+/// <c> VMOVDDUP + VMOVAPD / MOVLHPS + MOVAPS </c> instruction.
///
/// \param __dp
-/// A pointer to a 128-bit memory location. The address of the memory
-/// location has to be 16-byte aligned.
+/// A pointer to a memory location that can store two double-precision
+/// values.
/// \param __a
-/// A 128-bit vector of [2 x double] containing the values to be stored.
+/// A 128-bit vector of [2 x double] whose lower 64 bits are copied to each
+/// of the values in \a __dp.
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>
@@ -1989,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>
@@ -2010,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>
@@ -2030,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>
@@ -2050,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].
///
@@ -2072,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].
///
@@ -2094,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].
///
@@ -2116,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>
@@ -2128,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].
///
@@ -2156,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>
///
@@ -2177,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>
///
@@ -2199,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>
///
@@ -2220,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>
///
@@ -2241,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].
///
@@ -2265,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].
///
@@ -2289,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.
@@ -2315,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].
///
@@ -2335,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].
///
@@ -2355,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].
///
@@ -2375,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].
///
@@ -2395,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.
///
@@ -2415,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.
///
@@ -2435,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.
///
@@ -2455,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.
///
@@ -2468,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.
///
@@ -2493,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
@@ -2515,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>
///
@@ -2533,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>
///
@@ -2551,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>
///
@@ -2569,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>
@@ -2582,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>
///
@@ -2606,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>
///
@@ -2627,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>
///
@@ -2648,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>
///
@@ -2668,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>
///
@@ -2688,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>
///
@@ -2706,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>
@@ -2725,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>
///
@@ -2743,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>
///
@@ -2761,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>
@@ -2778,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>
@@ -2821,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>
@@ -2840,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>
@@ -2859,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>
@@ -2878,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>
@@ -2897,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>
@@ -2916,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.
///
@@ -2936,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.
///
@@ -2956,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.
///
@@ -2976,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.
///
@@ -2996,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>
@@ -3013,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>
@@ -3056,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>
@@ -3075,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>
@@ -3094,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>
@@ -3113,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>
@@ -3132,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>
@@ -3151,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>
@@ -3170,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>
///
@@ -3189,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>
///
@@ -3208,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>
///
@@ -3230,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>
///
@@ -3251,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>
///
@@ -3272,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>
///
@@ -3293,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>
///
@@ -3314,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>
///
@@ -3336,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.
@@ -3360,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>
@@ -3377,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>
@@ -3396,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>
///
@@ -3408,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>
///
@@ -3427,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>
@@ -3444,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>
@@ -3457,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>
@@ -3474,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>
@@ -3497,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>
@@ -3515,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>
@@ -3531,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>
@@ -3550,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>
@@ -3568,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.
///
@@ -3586,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>
@@ -3605,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>
@@ -3627,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>
@@ -3655,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>
@@ -3695,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>
@@ -3743,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>
@@ -3762,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>
@@ -3781,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>
@@ -3800,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>
@@ -3819,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>
@@ -3838,16 +3818,15 @@ _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>
///
-/// This intrinsic corresponds to the <c> VPUNPCKLQDQ / PUNPCKLQDQ </c>
-/// instruction.
+/// This intrinsic does not correspond to a specific instruction.
///
/// \param __q0
/// A 64-bit integral value used to initialize the lower 64 bits of the
@@ -3859,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>
@@ -3882,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>
@@ -3913,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>
@@ -3960,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>
///
@@ -3974,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>
@@ -3995,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>
///
@@ -4014,11 +3993,11 @@ _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.
///
-/// To minimize caching, the date is flagged as non-temporal (unlikely to be
+/// To minimize caching, the data is flagged as non-temporal (unlikely to be
/// used again soon). Exception and trap behavior for elements not selected
/// for storage to memory are implementation dependent.
///
@@ -4041,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>
@@ -4063,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
@@ -4083,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).
@@ -4102,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).
@@ -4115,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).
@@ -4135,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);
@@ -4146,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>
@@ -4158,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.
@@ -4169,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.
@@ -4184,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.
@@ -4212,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.
@@ -4240,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.
@@ -4268,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>
@@ -4290,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.
@@ -4317,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.
///
@@ -4343,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.
///
@@ -4371,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.
///
@@ -4404,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.
///
@@ -4438,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>
@@ -4482,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>
@@ -4509,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>
@@ -4532,8 +4491,8 @@ _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 (odd-indexed) values from two 128-bit vectors
-/// of [2 x i64] and interleaves them into a 128-bit vector of [2 x i64].
+/// 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>
///
@@ -4553,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>
@@ -4588,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].
///
@@ -4616,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>
@@ -4639,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>
@@ -4660,12 +4619,12 @@ _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>
///
-/// This intrinsic has no corresponding instruction.
+/// This intrinsic corresponds to the <c> MOVDQ2Q </c> instruction.
///
/// \param __a
/// A 128-bit integer vector operand. The lower 64 bits are moved to the
@@ -4677,12 +4636,12 @@ _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>
///
-/// This intrinsic corresponds to the <c> VMOVQ / MOVQ / MOVD </c> instruction.
+/// This intrinsic corresponds to the <c> MOVD+VMOVQ </c> instruction.
///
/// \param __a
/// A 64-bit value.
@@ -4691,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>
@@ -4709,11 +4668,11 @@ _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 (odd-indexed) values from two 128-bit vectors
-/// of [2 x double] and interleaves them into a 128-bit vector of [2 x
+/// 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].
///
/// \headerfile <x86intrin.h>
@@ -4733,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 (even-indexed) values 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].
///
@@ -4754,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.
///
@@ -4774,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.
///
@@ -4792,18 +4751,17 @@ _mm_movemask_pd(__m128d __a)
/// A 128-bit vector of [2 x double].
/// \param i
/// An 8-bit immediate value. The least significant two bits specify which
-/// elements to copy from a and b: \n
-/// Bit[0] = 0: lower element of a copied to lower element of result. \n
-/// Bit[0] = 1: upper element of a copied to lower element of result. \n
+/// elements to copy from \a a and \a b: \n
+/// Bit[0] = 0: lower element of \a a copied to lower element of result. \n
+/// Bit[0] = 1: upper element of \a a copied to lower element of result. \n
/// 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>
@@ -4820,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>
@@ -4837,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>
@@ -4854,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>
@@ -4871,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>
@@ -4888,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>
@@ -4909,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>
@@ -4922,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/lib/Headers/f16cintrin.h b/lib/Headers/f16cintrin.h
index b796cc84316f..3d35f28eb356 100644
--- a/lib/Headers/f16cintrin.h
+++ b/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/lib/Headers/fma4intrin.h b/lib/Headers/fma4intrin.h
index 962b1a60a258..7bae2f4a3155 100644
--- a/lib/Headers/fma4intrin.h
+++ b/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/lib/Headers/fmaintrin.h b/lib/Headers/fmaintrin.h
index 478a0ac81cf2..094d13afea09 100644
--- a/lib/Headers/fmaintrin.h
+++ b/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/lib/Headers/fxsrintrin.h b/lib/Headers/fxsrintrin.h
index 786081ca8eab..704b5ad60aa5 100644
--- a/lib/Headers/fxsrintrin.h
+++ b/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/lib/Headers/gfniintrin.h b/lib/Headers/gfniintrin.h
index 20fadccfaaed..804d4f3d068c 100644
--- a/lib/Headers/gfniintrin.h
+++ b/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/lib/Headers/htmxlintrin.h b/lib/Headers/htmxlintrin.h
index 28f7d025bb30..049dbd61df75 100644
--- a/lib/Headers/htmxlintrin.h
+++ b/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/lib/Headers/ia32intrin.h b/lib/Headers/ia32intrin.h
index 4928300103ad..f8972e3053a3 100644
--- a/lib/Headers/ia32intrin.h
+++ b/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/lib/Headers/immintrin.h b/lib/Headers/immintrin.h
index d3421dc86c99..e7bfbf964d56 100644
--- a/lib/Headers/immintrin.h
+++ b/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/lib/Headers/intrin.h b/lib/Headers/intrin.h
index b30aa215a452..91914214e299 100644
--- a/lib/Headers/intrin.h
+++ b/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/lib/Headers/invpcidintrin.h b/lib/Headers/invpcidintrin.h
new file mode 100644
index 000000000000..c30a19fa3d22
--- /dev/null
+++ b/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/lib/Headers/lwpintrin.h b/lib/Headers/lwpintrin.h
index c95fdd9a201a..3455575cced6 100644
--- a/lib/Headers/lwpintrin.h
+++ b/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/lib/Headers/lzcntintrin.h b/lib/Headers/lzcntintrin.h
index 3d2769da3bae..558f1828f0e7 100644
--- a/lib/Headers/lzcntintrin.h
+++ b/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/lib/Headers/mm3dnow.h b/lib/Headers/mm3dnow.h
index 294866c1dc0d..b0288757a396 100644
--- a/lib/Headers/mm3dnow.h
+++ b/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/lib/Headers/mmintrin.h b/lib/Headers/mmintrin.h
index 4b38d51713d8..a73539942a92 100644
--- a/lib/Headers/mmintrin.h
+++ b/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/lib/Headers/module.modulemap b/lib/Headers/module.modulemap
index 95d26cefa6f7..1d1af57fd030 100644
--- a/lib/Headers/module.modulemap
+++ b/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/lib/Headers/movdirintrin.h b/lib/Headers/movdirintrin.h
new file mode 100644
index 000000000000..ec20c53709bc
--- /dev/null
+++ b/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/lib/Headers/mwaitxintrin.h b/lib/Headers/mwaitxintrin.h
index 635f2ac6cab5..2921eadfa540 100644
--- a/lib/Headers/mwaitxintrin.h
+++ b/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/lib/Headers/nmmintrin.h b/lib/Headers/nmmintrin.h
index 57fec15963d1..348fb8c7c18f 100644
--- a/lib/Headers/nmmintrin.h
+++ b/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/lib/Headers/opencl-c.h b/lib/Headers/opencl-c.h
index ce204b04c030..e648b0f2f370 100644
--- a/lib/Headers/opencl-c.h
+++ b/lib/Headers/opencl-c.h
@@ -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
@@ -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/lib/Headers/pconfigintrin.h b/lib/Headers/pconfigintrin.h
new file mode 100644
index 000000000000..fee3cad38854
--- /dev/null
+++ b/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/lib/Headers/pkuintrin.h b/lib/Headers/pkuintrin.h
index 9e5459450b62..6976924d829e 100644
--- a/lib/Headers/pkuintrin.h
+++ b/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/lib/Headers/pmmintrin.h b/lib/Headers/pmmintrin.h
index 559ece2e3974..7e1a9eae59f6 100644
--- a/lib/Headers/pmmintrin.h
+++ b/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,8 +115,8 @@ _mm_hsub_ps(__m128 __a, __m128 __b)
return __builtin_ia32_hsubps((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Moves and duplicates high-order (odd-indexed) values from a 128-bit
-/// vector of [4 x float] to float values stored in a 128-bit vector of
+/// 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].
///
/// \headerfile <x86intrin.h>
@@ -137,7 +137,7 @@ _mm_movehdup_ps(__m128 __a)
return __builtin_shufflevector((__v4sf)__a, (__v4sf)__a, 1, 1, 3, 3);
}
-/// \brief Duplicates low-order (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/lib/Headers/popcntintrin.h b/lib/Headers/popcntintrin.h
index 0b4793e58bcb..75ceab9e150b 100644
--- a/lib/Headers/popcntintrin.h
+++ b/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/lib/Headers/prfchwintrin.h b/lib/Headers/prfchwintrin.h
index b52f31da2706..70851396f48e 100644
--- a/lib/Headers/prfchwintrin.h
+++ b/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/lib/Headers/ptwriteintrin.h b/lib/Headers/ptwriteintrin.h
new file mode 100644
index 000000000000..1bb1df0a2edf
--- /dev/null
+++ b/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/lib/Headers/rdseedintrin.h b/lib/Headers/rdseedintrin.h
index 421f4ea48702..419466932cf5 100644
--- a/lib/Headers/rdseedintrin.h
+++ b/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/lib/Headers/sgxintrin.h b/lib/Headers/sgxintrin.h
new file mode 100644
index 000000000000..20aee766103c
--- /dev/null
+++ b/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/lib/Headers/shaintrin.h b/lib/Headers/shaintrin.h
index 9b5d21800819..3df4718ced4d 100644
--- a/lib/Headers/shaintrin.h
+++ b/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/lib/Headers/smmintrin.h b/lib/Headers/smmintrin.h
index c2fa5a452bce..4806b3e4e150 100644
--- a/lib/Headers/smmintrin.h
+++ b/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].
///
@@ -648,15 +635,15 @@ _mm_mul_epi32 (__m128i __V1, __m128i __V2)
/// input vectors are used as an input for dot product; otherwise that input
/// is treated as zero. Bits [1:0] determine which elements of the result
/// will receive a copy of the final dot product, with bit [0] corresponding
-/// to the lowest element and bit [3] corresponding to the highest element of
+/// 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.
@@ -866,11 +853,11 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2)
/// 11: Copies the selected bits from \a Y to result bits [127:96]. \n
/// Bits[3:0]: If any of these bits are set, the corresponding result
/// element is cleared.
-/// \returns A 128-bit vector of [4 x float] containing the copied single-
-/// precision floating point elements from the operands.
+/// \returns A 128-bit vector of [4 x float] containing the copied
+/// 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/lib/Headers/stdint.h b/lib/Headers/stdint.h
index c48815314b51..0afcca3a9daa 100644
--- a/lib/Headers/stdint.h
+++ b/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/lib/Headers/tmmintrin.h b/lib/Headers/tmmintrin.h
index 042bfc7e3b0d..734cd391be60 100644
--- a/lib/Headers/tmmintrin.h
+++ b/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/lib/Headers/vaesintrin.h b/lib/Headers/vaesintrin.h
index efbb8a565292..e4174bb82ff0 100644
--- a/lib/Headers/vaesintrin.h
+++ b/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/lib/Headers/vpclmulqdqintrin.h b/lib/Headers/vpclmulqdqintrin.h
index 21cda2221007..86174a457e11 100644
--- a/lib/Headers/vpclmulqdqintrin.h
+++ b/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/lib/Headers/waitpkgintrin.h b/lib/Headers/waitpkgintrin.h
new file mode 100644
index 000000000000..e29d6cfa5a51
--- /dev/null
+++ b/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/lib/Headers/wbnoinvdintrin.h b/lib/Headers/wbnoinvdintrin.h
new file mode 100644
index 000000000000..cad83368dbe7
--- /dev/null
+++ b/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/lib/Headers/wmmintrin.h b/lib/Headers/wmmintrin.h
index a2d931010aea..569a8d838dad 100644
--- a/lib/Headers/wmmintrin.h
+++ b/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/lib/Headers/x86intrin.h b/lib/Headers/x86intrin.h
index 31ee7b82dd53..728c58c3ebbc 100644
--- a/lib/Headers/x86intrin.h
+++ b/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/lib/Headers/xmmintrin.h b/lib/Headers/xmmintrin.h
index 279c0275d93f..17af17267c83 100644
--- a/lib/Headers/xmmintrin.h
+++ b/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/lib/Headers/xopintrin.h b/lib/Headers/xopintrin.h
index 4a34f770d58d..9d540a2abdbe 100644
--- a/lib/Headers/xopintrin.h
+++ b/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/lib/Headers/xsavecintrin.h b/lib/Headers/xsavecintrin.h
index 598470a682e2..25577a95fc9a 100644
--- a/lib/Headers/xsavecintrin.h
+++ b/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/lib/Headers/xsaveintrin.h b/lib/Headers/xsaveintrin.h
index a2e6b2e742ff..16f3a78d3f5b 100644
--- a/lib/Headers/xsaveintrin.h
+++ b/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/lib/Headers/xsaveoptintrin.h b/lib/Headers/xsaveoptintrin.h
index d3faae78be4f..792cf92d46e8 100644
--- a/lib/Headers/xsaveoptintrin.h
+++ b/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/lib/Headers/xsavesintrin.h b/lib/Headers/xsavesintrin.h
index c5e540a86edb..fe2bc4b93b22 100644
--- a/lib/Headers/xsavesintrin.h
+++ b/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/lib/Headers/xtestintrin.h b/lib/Headers/xtestintrin.h
index 9d3378fd1eea..924424386b94 100644
--- a/lib/Headers/xtestintrin.h
+++ b/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/lib/Index/CMakeLists.txt b/lib/Index/CMakeLists.txt
index c9fbfafcf946..1362143fb0d4 100644
--- a/lib/Index/CMakeLists.txt
+++ b/lib/Index/CMakeLists.txt
@@ -23,6 +23,7 @@ add_clang_library(clangIndex
clangBasic
clangFormat
clangFrontend
+ clangLex
clangRewrite
clangSerialization
clangToolingCore
diff --git a/lib/Index/IndexDecl.cpp b/lib/Index/IndexDecl.cpp
index e14750e046eb..01ad3a277216 100644
--- a/lib/Index/IndexDecl.cpp
+++ b/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/lib/Index/IndexSymbol.cpp b/lib/Index/IndexSymbol.cpp
index 733d4dbc2f94..03b55ffe8a4e 100644
--- a/lib/Index/IndexSymbol.cpp
+++ b/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/lib/Index/IndexTypeSourceInfo.cpp b/lib/Index/IndexTypeSourceInfo.cpp
index c8ff3d72d4be..7a7a156478f8 100644
--- a/lib/Index/IndexTypeSourceInfo.cpp
+++ b/lib/Index/IndexTypeSourceInfo.cpp
@@ -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);
diff --git a/lib/Index/IndexingAction.cpp b/lib/Index/IndexingAction.cpp
index 411657bf3dcd..16f6c21745ef 100644
--- a/lib/Index/IndexingAction.cpp
+++ b/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/lib/Index/IndexingContext.cpp b/lib/Index/IndexingContext.cpp
index de9fe39df031..80d851b43d73 100644
--- a/lib/Index/IndexingContext.cpp
+++ b/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) {
@@ -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/lib/Index/IndexingContext.h b/lib/Index/IndexingContext.h
index 566651c83a75..04960086d092 100644
--- a/lib/Index/IndexingContext.h
+++ b/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/lib/Index/SimpleFormatContext.h b/lib/Index/SimpleFormatContext.h
index 2c26e4d82e08..9c6d29bec329 100644
--- a/lib/Index/SimpleFormatContext.h
+++ b/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/lib/Index/USRGeneration.cpp b/lib/Index/USRGeneration.cpp
index 3a06554b256c..e69fa749b45f 100644
--- a/lib/Index/USRGeneration.cpp
+++ b/lib/Index/USRGeneration.cpp
@@ -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) {
@@ -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) {
@@ -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:
diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp
index 6976294a2eaf..b1a2ef121288 100644
--- a/lib/Lex/HeaderSearch.cpp
+++ b/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
@@ -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.
@@ -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
@@ -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
@@ -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,7 +1077,7 @@ 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,
const HeaderFileInfo &OtherHFI) {
@@ -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/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp
index 830354ab23f0..e8588a771a43 100644
--- a/lib/Lex/Lexer.cpp
+++ b/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;
}
@@ -2009,18 +2023,21 @@ bool Lexer::LexAngledStringLiteral(Token &Result, const char *CurPtr) {
const char *AfterLessPos = CurPtr;
char C = getAndAdvanceChar(CurPtr, Result);
while (C != '>') {
- // Skip escaped characters.
- if (C == '\\' && CurPtr < BufferEnd) {
- // Skip the escaped character.
- getAndAdvanceChar(CurPtr, Result);
- } else if (C == '\n' || C == '\r' || // Newline.
- (C == 0 && (CurPtr-1 == BufferEnd || // End of file.
- isCodeCompletionPoint(CurPtr-1)))) {
+ // Skip escaped characters. Escaped newlines will already be processed by
+ // getAndAdvanceChar.
+ if (C == '\\')
+ C = getAndAdvanceChar(CurPtr, Result);
+
+ if (C == '\n' || C == '\r' || // Newline.
+ (C == 0 && (CurPtr-1 == BufferEnd || // End of file.
+ isCodeCompletionPoint(CurPtr-1)))) {
// If the filename is unterminated, then it must just be a lone <
// character. Return this as such.
FormTokenWithChars(Result, AfterLessPos, tok::less);
return true;
- } else if (C == 0) {
+ }
+
+ if (C == 0) {
NulCharacter = CurPtr-1;
}
C = getAndAdvanceChar(CurPtr, Result);
@@ -2160,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
@@ -2738,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" : ">>>>>>>";
@@ -3509,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/lib/Lex/LiteralSupport.cpp b/lib/Lex/LiteralSupport.cpp
index cbec5e6b6385..966dafca2719 100644
--- a/lib/Lex/LiteralSupport.cpp
+++ b/lib/Lex/LiteralSupport.cpp
@@ -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
@@ -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;
@@ -738,15 +773,17 @@ void NumericLiteralParser::ParseDecimalOrOctalCommon(SourceLocation TokLoc){
s++;
radix = 10;
saw_exponent = true;
- if (*s == '+' || *s == '-') s++; // sign
+ if (s != ThisTokEnd && (*s == '+' || *s == '-')) s++; // sign
const char *first_non_digit = SkipDigits(s);
if (containsDigits(s, first_non_digit)) {
checkSeparator(TokLoc, s, CSK_BeforeDigits);
s = first_non_digit;
} else {
- PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Exponent-ThisTokBegin),
- diag::err_exponent_has_no_digits);
- hadError = true;
+ if (!hadError) {
+ PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Exponent-ThisTokBegin),
+ diag::err_exponent_has_no_digits);
+ hadError = true;
+ }
return;
}
}
@@ -768,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);
}
@@ -787,10 +826,12 @@ void NumericLiteralParser::checkSeparator(SourceLocation TokLoc,
} else if (Pos == ThisTokEnd)
return;
- if (isDigitSeparator(*Pos))
+ if (isDigitSeparator(*Pos)) {
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Pos - ThisTokBegin),
diag::err_digit_separator_not_between_digits)
<< IsAfterDigits;
+ hadError = true;
+ }
}
/// ParseNumberStartingWithZero - This method is called when the first character
@@ -840,12 +881,14 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) {
const char *Exponent = s;
s++;
saw_exponent = true;
- if (*s == '+' || *s == '-') s++; // sign
+ if (s != ThisTokEnd && (*s == '+' || *s == '-')) s++; // sign
const char *first_non_digit = SkipDigits(s);
if (!containsDigits(s, first_non_digit)) {
- PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Exponent-ThisTokBegin),
- diag::err_exponent_has_no_digits);
- hadError = true;
+ if (!hadError) {
+ PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Exponent-ThisTokBegin),
+ diag::err_exponent_has_no_digits);
+ hadError = true;
+ }
return;
}
checkSeparator(TokLoc, s, CSK_BeforeDigits);
@@ -882,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;
@@ -1006,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
@@ -1585,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/lib/Lex/MacroArgs.cpp b/lib/Lex/MacroArgs.cpp
index 5c0f0623c3e1..3b6e2dc2411a 100644
--- a/lib/Lex/MacroArgs.cpp
+++ b/lib/Lex/MacroArgs.cpp
@@ -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;
@@ -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/lib/Lex/MacroInfo.cpp b/lib/Lex/MacroInfo.cpp
index b13767aa1d67..4ed69ecc465d 100644
--- a/lib/Lex/MacroInfo.cpp
+++ b/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/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp
index b3ac10c5c5ae..f048a73a8ccc 100644
--- a/lib/Lex/ModuleMap.cpp
+++ b/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");
@@ -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) {
@@ -152,10 +170,13 @@ static void appendSubframeworkPaths(Module *Mod,
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,6 +320,8 @@ 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) {
@@ -289,7 +330,7 @@ void ModuleMap::setTarget(const TargetInfo &Target) {
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,7 +525,7 @@ 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.
@@ -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) {
@@ -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;
@@ -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();
}
@@ -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,
@@ -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; }
@@ -1559,7 +1626,7 @@ void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
} while (true);
}
-/// \brief Parse a module-id.
+/// Parse a module-id.
///
/// module-id:
/// identifier
@@ -1588,21 +1655,21 @@ bool ModuleMapParser::parseModuleId(ModuleId &Id) {
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,12 +1730,13 @@ 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
@@ -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,7 +1776,7 @@ void ModuleMapParser::parseModuleDecl() {
// Parse 'framework' keyword, if present.
if (Tok.is(MMToken::FrameworkKeyword)) {
- consumeToken();
+ FrameworkLoc = consumeToken();
Framework = true;
}
@@ -1706,7 +1787,7 @@ 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.
@@ -1787,6 +1868,7 @@ void ModuleMapParser::parseModuleDecl() {
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:
@@ -1812,23 +1894,35 @@ void ModuleMapParser::parseModuleDecl() {
}
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 {
@@ -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
@@ -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,7 +2323,7 @@ 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
@@ -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
@@ -2346,7 +2449,7 @@ void ModuleMapParser::parseExportDecl() {
ActiveModule->UnresolvedExports.push_back(Unresolved);
}
-/// \brief Parse a module export_as declaration.
+/// Parse a module export_as declaration.
///
/// export-as-declaration:
/// 'export_as' identifier
@@ -2378,10 +2481,12 @@ void ModuleMapParser::parseExportAsDecl() {
}
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]
@@ -2687,7 +2792,7 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
}
}
-/// \brief Parse optional attributes.
+/// Parse optional attributes.
///
/// attributes:
/// attribute attributes
@@ -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*
@@ -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/lib/Lex/PPCaching.cpp b/lib/Lex/PPCaching.cpp
index f5e8cdc25d38..9758557d7b44 100644
--- a/lib/Lex/PPCaching.cpp
+++ b/lib/Lex/PPCaching.cpp
@@ -105,8 +105,10 @@ void Preprocessor::CachingLex(Token &Result) {
}
void Preprocessor::EnterCachingLexMode() {
- if (InCachingLexMode())
+ if (InCachingLexMode()) {
+ assert(CurLexerKind == CLK_CachingLexer && "Unexpected lexer kind");
return;
+ }
PushIncludeMacroStack();
CurLexerKind = CLK_CachingLexer;
diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp
index ca3e70fd1060..d8dae73037a8 100644
--- a/lib/Lex/PPDirectives.cpp
+++ b/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");
@@ -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.
diff --git a/lib/Lex/PPExpressions.cpp b/lib/Lex/PPExpressions.cpp
index d8431827e9cd..b1ed0e10c6fc 100644
--- a/lib/Lex/PPExpressions.cpp
+++ b/lib/Lex/PPExpressions.cpp
@@ -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.
diff --git a/lib/Lex/PPLexerChange.cpp b/lib/Lex/PPLexerChange.cpp
index e484e9c4c3a3..352814d715fa 100644
--- a/lib/Lex/PPLexerChange.cpp
+++ b/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"
@@ -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,
@@ -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()) {
@@ -444,6 +447,7 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
}
CurPPLexer = nullptr;
+ recomputeCurLexerKind();
return true;
}
@@ -480,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();
@@ -499,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.
@@ -521,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();
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
index 41633f90c34d..d9992e00f8c0 100644
--- a/lib/Lex/PPMacroExpansion.cpp
+++ b/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);
@@ -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.
@@ -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/lib/Lex/PTHLexer.cpp b/lib/Lex/PTHLexer.cpp
index d6c20a13d27b..45cff56dcaa1 100644
--- a/lib/Lex/PTHLexer.cpp
+++ b/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/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp
index b8acd92521fb..930c5f6b069c 100644
--- a/lib/Lex/Pragma.cpp
+++ b/lib/Lex/Pragma.cpp
@@ -148,7 +148,7 @@ void Preprocessor::HandlePragmaDirective(SourceLocation IntroducerLoc,
namespace {
-/// \brief Helper class for \see Preprocessor::Handle_Pragma.
+/// Helper class for \see Preprocessor::Handle_Pragma.
class LexingFor_PragmaRAII {
Preprocessor &PP;
bool InMacroArgPreExpansion;
@@ -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
@@ -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
@@ -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,44 +1615,6 @@ 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 -
/// \#pragma clang arc_cf_code_audited begin/end
struct PragmaARCCFCodeAuditedHandler : public PragmaHandler {
@@ -1754,7 +1730,7 @@ struct PragmaAssumeNonNullHandler : public PragmaHandler {
}
};
-/// \brief Handle "\#pragma region [...]"
+/// Handle "\#pragma region [...]"
///
/// The syntax is
/// \code
@@ -1814,17 +1790,15 @@ void Preprocessor::RegisterBuiltinPragmas() {
ModuleHandler->AddPragma(new PragmaModuleEndHandler());
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/lib/Lex/PreprocessingRecord.cpp b/lib/Lex/PreprocessingRecord.cpp
index af439dbfa584..b59820003b56 100644
--- a/lib/Lex/PreprocessingRecord.cpp
+++ b/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) {
@@ -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,7 +132,7 @@ 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) {
@@ -329,12 +329,29 @@ unsigned PreprocessingRecord::allocateLoadedEntities(unsigned 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,7 +368,7 @@ 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() &&
@@ -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,7 +471,8 @@ 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()) {
@@ -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/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp
index 7d789e780113..0217a2e60ede 100644
--- a/lib/Lex/Preprocessor.cpp
+++ b/lib/Lex/Preprocessor.cpp
@@ -85,12 +85,14 @@ 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;
@@ -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() &&
@@ -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) {
@@ -773,13 +865,18 @@ 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.
diff --git a/lib/Lex/PreprocessorLexer.cpp b/lib/Lex/PreprocessorLexer.cpp
index 2e85f46f52c5..9f930c3a3c6a 100644
--- a/lib/Lex/PreprocessorLexer.cpp
+++ b/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/lib/Lex/ScratchBuffer.cpp b/lib/Lex/ScratchBuffer.cpp
index e0f3966fce48..dc03e16daa8b 100644
--- a/lib/Lex/ScratchBuffer.cpp
+++ b/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/lib/Lex/TokenLexer.cpp b/lib/Lex/TokenLexer.cpp
index d7f1c7a93fda..184b1b390287 100644
--- a/lib/Lex/TokenLexer.cpp
+++ b/lib/Lex/TokenLexer.cpp
@@ -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) &&
@@ -865,9 +865,9 @@ 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.
@@ -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
diff --git a/lib/Parse/ParseAST.cpp b/lib/Parse/ParseAST.cpp
index d018d4c08ed9..696506099e58 100644
--- a/lib/Parse/ParseAST.cpp
+++ b/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>
@@ -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;
@@ -158,6 +169,13 @@ void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) {
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/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp
index 2b3d4ba85bd8..27d48be0e3eb 100644
--- a/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/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;
@@ -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);
@@ -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/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 2a999399fb50..4f6bb08bdc64 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/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;
@@ -43,18 +42,18 @@ using namespace clang;
///
/// Called type-id in C++.
TypeResult Parser::ParseTypeName(SourceRange *Range,
- Declarator::TheContext Context,
+ DeclaratorContext Context,
AccessSpecifier AS,
Decl **OwnedType,
ParsedAttributes *Attrs) {
DeclSpecContext DSC = getDeclSpecContextFromDeclaratorContext(Context);
- if (DSC == DSC_normal)
- DSC = DSC_type_specifier;
+ if (DSC == DeclSpecContext::DSC_normal)
+ DSC = DeclSpecContext::DSC_type_specifier;
// 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) {
@@ -732,7 +758,7 @@ void Parser::ParseNullabilityTypeSpecifiers(ParsedAttributes &attrs) {
Diag(AttrNameLoc, diag::ext_nullability)
<< AttrName;
attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
- AttributeList::AS_Keyword);
+ 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];
@@ -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;
@@ -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,7 +1252,7 @@ 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()) {
@@ -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();
@@ -1263,7 +1293,8 @@ void Parser::ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated,
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();
@@ -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,52 +1622,24 @@ 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
/// declaration-specifiers, some number of declarators, and a semicolon.
-/// 'Context' should be a Declarator::TheContext value. This returns the
+/// 'Context' should be a DeclaratorContext value. This returns the
/// location of the semicolon in DeclEnd.
///
/// declaration: [C99 6.7]
@@ -1653,7 +1653,7 @@ void Parser::stripTypeAttributesOffDeclSpec(ParsedAttributesWithRange &Attrs,
/// [C++11/C11] static_assert-declaration
/// others... [FIXME]
///
-Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context,
+Parser::DeclGroupPtrTy Parser::ParseDeclaration(DeclaratorContext Context,
SourceLocation &DeclEnd,
ParsedAttributesWithRange &attrs) {
ParenBraceBracketBalancer BalancerRAIIObj(*this);
@@ -1666,7 +1666,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned 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.
@@ -1714,7 +1714,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context,
/// of a simple-declaration. If we find that we are, we also parse the
/// for-range-initializer, and place it here.
Parser::DeclGroupPtrTy
-Parser::ParseSimpleDeclaration(unsigned Context,
+Parser::ParseSimpleDeclaration(DeclaratorContext Context,
SourceLocation &DeclEnd,
ParsedAttributesWithRange &Attrs,
bool RequireSemi, ForRangeInit *FRI) {
@@ -1753,7 +1753,7 @@ Parser::ParseSimpleDeclaration(unsigned Context,
/// Returns true if this might be the start of a declarator, or a common typo
/// for a declarator.
-bool Parser::MightBeDeclarator(unsigned Context) {
+bool Parser::MightBeDeclarator(DeclaratorContext Context) {
switch (Tok.getKind()) {
case tok::annot_cxxscope:
case tok::annot_template_id:
@@ -1772,11 +1772,12 @@ bool Parser::MightBeDeclarator(unsigned Context) {
return getLangOpts().CPlusPlus;
case tok::l_square: // Might be an attribute on an unnamed bit-field.
- return Context == Declarator::MemberContext && getLangOpts().CPlusPlus11 &&
- NextToken().is(tok::l_square);
+ return Context == DeclaratorContext::MemberContext &&
+ getLangOpts().CPlusPlus11 && NextToken().is(tok::l_square);
case tok::colon: // Might be a typo for '::' or an unnamed bit-field.
- return Context == Declarator::MemberContext || getLangOpts().CPlusPlus;
+ return Context == DeclaratorContext::MemberContext ||
+ getLangOpts().CPlusPlus;
case tok::identifier:
switch (NextToken().getKind()) {
@@ -1802,8 +1803,9 @@ bool Parser::MightBeDeclarator(unsigned Context) {
// At namespace scope, 'identifier:' is probably a typo for 'identifier::'
// and in block scope it's probably a label. Inside a class definition,
// this is a bit-field.
- return Context == Declarator::MemberContext ||
- (getLangOpts().CPlusPlus && Context == Declarator::FileContext);
+ return Context == DeclaratorContext::MemberContext ||
+ (getLangOpts().CPlusPlus &&
+ Context == DeclaratorContext::FileContext);
case tok::identifier: // Possible virt-specifier.
return getLangOpts().CPlusPlus11 && isCXX11VirtSpecifier(NextToken());
@@ -1902,11 +1904,11 @@ void Parser::SkipMalformedDecl() {
/// definition or a group of object declarations, actually parse the
/// result.
Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
- unsigned Context,
+ DeclaratorContext Context,
SourceLocation *DeclEnd,
ForRangeInit *FRI) {
// Parse the first declarator.
- ParsingDeclarator D(*this, DS, static_cast<Declarator::TheContext>(Context));
+ ParsingDeclarator D(*this, DS, Context);
ParseDeclarator(D);
// Bail out if the first declarator didn't seem well-formed.
@@ -1953,7 +1955,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
// Function definitions are only allowed at file scope and in C++ classes.
// The C++ inline method definition case is handled elsewhere, so we only
// need to handle the file scope definition case.
- if (Context == Declarator::FileContext) {
+ if (Context == DeclaratorContext::FileContext) {
if (isStartOfFunctionDefinition(D)) {
if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
Diag(Tok, diag::err_function_declared_typedef);
@@ -2008,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);
@@ -2024,7 +2031,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
if (FirstDecl)
DeclsInGroup.push_back(FirstDecl);
- bool ExpectSemi = Context != Declarator::ForContext;
+ 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.
@@ -2070,7 +2077,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
*DeclEnd = Tok.getLocation();
if (ExpectSemi &&
- ExpectAndConsumeSemi(Context == Declarator::FileContext
+ ExpectAndConsumeSemi(Context == DeclaratorContext::FileContext
? diag::err_invalid_token_after_toplevel_declarator
: diag::err_expected_semi_declaration)) {
// Okay, there was no semicolon and one was expected. If we see a
@@ -2105,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.
@@ -2199,7 +2206,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
// FIXME: This check should be for a variable template instantiation only.
// Check that this is a valid instantiation
- if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
+ if (D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) {
// If the declarator-id is not a template-id, issue a diagnostic and
// recover by ignoring the 'template' keyword.
Diag(Tok, diag::err_template_defn_explicit_instantiation)
@@ -2273,8 +2280,8 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
if (Init.isInvalid()) {
SmallVector<tok::TokenKind, 2> StopTokens;
StopTokens.push_back(tok::comma);
- if (D.getContext() == Declarator::ForContext ||
- D.getContext() == Declarator::InitStmtContext)
+ if (D.getContext() == DeclaratorContext::ForContext ||
+ D.getContext() == DeclaratorContext::InitStmtContext)
StopTokens.push_back(tok::r_paren);
SkipUntil(StopTokens, StopAtSemi | StopBeforeMatch);
Actions.ActOnInitializerError(ThisDecl);
@@ -2397,7 +2404,7 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS,
}
// Issue diagnostic and remove constexpr specfier if present.
- if (DS.isConstexprSpecified() && DSC != DSC_condition) {
+ if (DS.isConstexprSpecified() && DSC != DeclSpecContext::DSC_condition) {
Diag(DS.getConstexprSpecLoc(), diag::err_typename_invalid_constexpr);
DS.ClearConstexprSpec();
}
@@ -2444,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.
@@ -2486,7 +2493,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
// classes.
if (ParsedType T = Actions.ActOnMSVCUnknownTypeName(
*Tok.getIdentifierInfo(), Tok.getLocation(),
- DSC == DSC_template_type_arg)) {
+ DSC == DeclSpecContext::DSC_template_type_arg)) {
const char *PrevSpec;
unsigned DiagID;
DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, T,
@@ -2540,18 +2547,20 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
// Parse this as a tag as if the missing tag were present.
if (TagKind == tok::kw_enum)
- ParseEnumSpecifier(Loc, DS, TemplateInfo, AS, DSC_normal);
+ ParseEnumSpecifier(Loc, DS, TemplateInfo, AS,
+ DeclSpecContext::DSC_normal);
else
ParseClassSpecifier(TagKind, Loc, DS, TemplateInfo, AS,
- /*EnteringContext*/ false, DSC_normal, Attrs);
+ /*EnteringContext*/ false,
+ DeclSpecContext::DSC_normal, Attrs);
return true;
}
}
// Determine whether this identifier could plausibly be the name of something
// being declared (with a missing type).
- if (!isTypeSpecifier(DSC) &&
- (!SS || DSC == DSC_top_level || DSC == DSC_class)) {
+ if (!isTypeSpecifier(DSC) && (!SS || DSC == DeclSpecContext::DSC_top_level ||
+ DSC == DeclSpecContext::DSC_class)) {
// Look ahead to the next token to try to figure out what this declaration
// was supposed to be.
switch (NextToken().getKind()) {
@@ -2575,7 +2584,8 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
// If we're in a context where we could be declaring a constructor,
// check whether this is a constructor declaration with a bogus name.
- if (DSC == DSC_class || (DSC == DSC_top_level && SS)) {
+ if (DSC == DeclSpecContext::DSC_class ||
+ (DSC == DeclSpecContext::DSC_top_level && SS)) {
IdentifierInfo *II = Tok.getIdentifierInfo();
if (Actions.isCurrentClassNameTypo(II, SS)) {
Diag(Loc, diag::err_constructor_bad_name)
@@ -2651,27 +2661,29 @@ 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
-/// Declarator::TheContext enumerator values.
+/// DeclaratorContext enumerator values.
Parser::DeclSpecContext
-Parser::getDeclSpecContextFromDeclaratorContext(unsigned Context) {
- if (Context == Declarator::MemberContext)
- return DSC_class;
- if (Context == Declarator::FileContext)
- return DSC_top_level;
- if (Context == Declarator::TemplateParamContext)
- return DSC_template_param;
- if (Context == Declarator::TemplateTypeArgContext)
- return DSC_template_type_arg;
- if (Context == Declarator::TrailingReturnContext)
- return DSC_trailing;
- if (Context == Declarator::AliasDeclContext ||
- Context == Declarator::AliasTemplateContext)
- return DSC_alias_declaration;
- return DSC_normal;
+Parser::getDeclSpecContextFromDeclaratorContext(DeclaratorContext Context) {
+ if (Context == DeclaratorContext::MemberContext)
+ return DeclSpecContext::DSC_class;
+ if (Context == DeclaratorContext::FileContext)
+ return DeclSpecContext::DSC_top_level;
+ if (Context == DeclaratorContext::TemplateParamContext)
+ return DeclSpecContext::DSC_template_param;
+ if (Context == DeclaratorContext::TemplateArgContext ||
+ Context == DeclaratorContext::TemplateTypeArgContext)
+ return DeclSpecContext::DSC_template_type_arg;
+ if (Context == DeclaratorContext::TrailingReturnContext ||
+ Context == DeclaratorContext::TrailingReturnVarContext)
+ return DeclSpecContext::DSC_trailing;
+ if (Context == DeclaratorContext::AliasDeclContext ||
+ Context == DeclaratorContext::AliasTemplateContext)
+ return DeclSpecContext::DSC_alias_declaration;
+ return DeclSpecContext::DSC_normal;
}
/// ParseAlignArgument - Parse the argument to an alignment-specifier.
@@ -2735,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
@@ -2751,7 +2763,8 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS,
LateParsedAttrList *LateAttrs) {
assert(DS.hasTagDefinition() && "shouldn't call this");
- bool EnteringContext = (DSContext == DSC_class || DSContext == DSC_top_level);
+ bool EnteringContext = (DSContext == DeclSpecContext::DSC_class ||
+ DSContext == DeclSpecContext::DSC_top_level);
if (getLangOpts().CPlusPlus &&
Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw_decltype,
@@ -2845,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]
@@ -2885,7 +2909,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
DS.SetRangeEnd(SourceLocation());
}
- bool EnteringContext = (DSContext == DSC_class || DSContext == DSC_top_level);
+ bool EnteringContext = (DSContext == DeclSpecContext::DSC_class ||
+ DSContext == DeclSpecContext::DSC_top_level);
bool AttrsLastTime = false;
ParsedAttributesWithRange attrs(AttrFactory);
// We use Sema's policy to get bool macros right.
@@ -2955,8 +2980,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
Scope::FunctionPrototypeScope |
Scope::AtCatchScope)) == 0;
bool AllowNestedNameSpecifiers
- = DSContext == DSC_top_level ||
- (DSContext == DSC_class && DS.isFriendSpecified());
+ = DSContext == DeclSpecContext::DSC_top_level ||
+ (DSContext == DeclSpecContext::DSC_class && DS.isFriendSpecified());
Actions.CodeCompleteDeclSpec(getCurScope(), DS,
AllowNonIdentifiers,
@@ -2967,9 +2992,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
if (getCurScope()->getFnParent() || getCurScope()->getBlockParent())
CCC = Sema::PCC_LocalDeclarationSpecifiers;
else if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate)
- CCC = DSContext == DSC_class? Sema::PCC_MemberTemplate
- : Sema::PCC_Template;
- else if (DSContext == DSC_class)
+ CCC = DSContext == DeclSpecContext::DSC_class ? Sema::PCC_MemberTemplate
+ : Sema::PCC_Template;
+ else if (DSContext == DeclSpecContext::DSC_class)
CCC = Sema::PCC_Class;
else if (CurParsedObjCImpl)
CCC = Sema::PCC_ObjCImplementation;
@@ -3013,10 +3038,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// To improve diagnostics for this case, parse the declaration as a
// constructor (and reject the extra template arguments later).
TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Next);
- if ((DSContext == DSC_top_level || DSContext == DSC_class) &&
+ if ((DSContext == DeclSpecContext::DSC_top_level ||
+ DSContext == DeclSpecContext::DSC_class) &&
TemplateId->Name &&
Actions.isCurrentClassName(*TemplateId->Name, getCurScope(), &SS) &&
- isConstructorDeclarator(/*Unqualified*/false)) {
+ isConstructorDeclarator(/*Unqualified*/ false)) {
// The user meant this to be an out-of-line constructor
// definition, but template arguments are not allowed
// there. Just allow this as a constructor; we'll
@@ -3055,7 +3081,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// Check whether this is a constructor declaration. If we're in a
// context where the identifier could be a class name, and it has the
// shape of a constructor declaration, process it as one.
- if ((DSContext == DSC_top_level || DSContext == DSC_class) &&
+ if ((DSContext == DeclSpecContext::DSC_top_level ||
+ DSContext == DeclSpecContext::DSC_class) &&
Actions.isCurrentClassName(*Next.getIdentifierInfo(), getCurScope(),
&SS) &&
isConstructorDeclarator(/*Unqualified*/ false))
@@ -3193,7 +3220,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
if (DS.isTypeAltiVecVector())
goto DoneWithDeclSpec;
- if (DSContext == DSC_objc_method_result && isObjCInstancetype()) {
+ if (DSContext == DeclSpecContext::DSC_objc_method_result &&
+ isObjCInstancetype()) {
ParsedType TypeRep = Actions.ActOnObjCInstanceType(Loc);
assert(TypeRep);
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
@@ -3206,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,
@@ -3225,17 +3260,11 @@ 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 == 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 &&
- (DSContext == DSC_class || DSContext == DSC_top_level) &&
+ (DSContext == DeclSpecContext::DSC_class ||
+ DSContext == DeclSpecContext::DSC_top_level) &&
Actions.isDeductionGuideName(getCurScope(), *Tok.getIdentifierInfo(),
Tok.getLocation()) &&
isConstructorDeclarator(/*Unqualified*/ true,
@@ -3281,7 +3310,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// If we're in a context where the template-id could be a
// constructor name or specialization, check whether this is a
// constructor declaration.
- if (getLangOpts().CPlusPlus && DSContext == DSC_class &&
+ if (getLangOpts().CPlusPlus && DSContext == DeclSpecContext::DSC_class &&
Actions.isCurrentClassName(*TemplateId->Name, getCurScope()) &&
isConstructorDeclarator(TemplateId->SS.isEmpty()))
goto DoneWithDeclSpec;
@@ -3308,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;
}
@@ -3351,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;
@@ -3419,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,
@@ -3431,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);
@@ -3451,7 +3489,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// friend
case tok::kw_friend:
- if (DSContext == DSC_class)
+ if (DSContext == DeclSpecContext::DSC_class)
isInvalid = DS.SetFriendSpec(Loc, PrevSpec, DiagID);
else {
PrevSpec = ""; // not actually used by the diagnostic
@@ -3535,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);
@@ -3543,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);
@@ -3703,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;
@@ -3718,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;
@@ -3758,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;
}
@@ -3878,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");
@@ -3984,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());
}
@@ -4070,7 +4143,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
SuppressAccessChecks diagsFromTag(*this, shouldDelayDiagsInTag);
// Enum definitions should not be parsed in a trailing-return-type.
- bool AllowDeclaration = DSC != DSC_trailing;
+ bool AllowDeclaration = DSC != DeclSpecContext::DSC_trailing;
bool AllowFixedUnderlyingType = AllowDeclaration &&
(getLangOpts().CPlusPlus11 || getLangOpts().MicrosoftExt ||
@@ -4296,14 +4369,14 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
bool IsDependent = false;
const char *PrevSpec = nullptr;
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,
- DSC == DSC_type_specifier,
- DSC == DSC_template_param ||
- DSC == DSC_template_type_arg, &SkipBody);
+ Decl *TagDecl = Actions.ActOnTag(
+ getCurScope(), DeclSpec::TST_enum, TUK, StartLoc, SS, Name, NameLoc,
+ 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,
+ &SkipBody);
if (SkipBody.ShouldSkip) {
assert(TUK == Sema::TUK_Definition && "can only skip a definition");
@@ -4440,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);
@@ -4493,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());
@@ -4540,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:
@@ -4616,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:
@@ -4645,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:
@@ -4772,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:
@@ -4779,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:
@@ -4800,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:
@@ -5089,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)) {
@@ -5129,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;
@@ -5175,7 +5257,7 @@ void Parser::ParseDeclarator(Declarator &D) {
}
static bool isPtrOperatorToken(tok::TokenKind Kind, const LangOptions &Lang,
- unsigned TheContext) {
+ DeclaratorContext TheContext) {
if (Kind == tok::star || Kind == tok::caret)
return true;
@@ -5194,8 +5276,9 @@ static bool isPtrOperatorToken(tok::TokenKind Kind, const LangOptions &Lang,
// (The same thing can in theory happen after a trailing-return-type, but
// since those are a C++11 feature, there is no rejects-valid issue there.)
if (Kind == tok::ampamp)
- return Lang.CPlusPlus11 || (TheContext != Declarator::ConversionIdContext &&
- TheContext != Declarator::CXXNewContext);
+ return Lang.CPlusPlus11 ||
+ (TheContext != DeclaratorContext::ConversionIdContext &&
+ TheContext != DeclaratorContext::CXXNewContext);
return false;
}
@@ -5249,8 +5332,9 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
(Tok.is(tok::identifier) &&
(NextToken().is(tok::coloncolon) || NextToken().is(tok::less))) ||
Tok.is(tok::annot_cxxscope))) {
- bool EnteringContext = D.getContext() == Declarator::FileContext ||
- D.getContext() == Declarator::MemberContext;
+ bool EnteringContext =
+ D.getContext() == DeclaratorContext::FileContext ||
+ D.getContext() == DeclaratorContext::MemberContext;
CXXScopeSpec SS;
ParseOptionalCXXScopeSpecifier(SS, nullptr, EnteringContext);
@@ -5278,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;
}
}
@@ -5294,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.
@@ -5316,9 +5400,9 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
// GNU attributes are not allowed here in a new-type-id, but Declspec and
// C++11 attributes are allowed.
unsigned Reqs = AR_CXX11AttributesParsed | AR_DeclspecAttributesParsed |
- ((D.getContext() != Declarator::CXXNewContext)
- ? AR_GNUAttributesParsed
- : AR_GNUAttributesParsedAndRejected);
+ ((D.getContext() != DeclaratorContext::CXXNewContext)
+ ? AR_GNUAttributesParsed
+ : AR_GNUAttributesParsedAndRejected);
ParseTypeQualifierListOpt(DS, Reqs, true, !D.mayOmitIdentifier());
D.ExtendWithDeclSpec(DS);
@@ -5326,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);
@@ -5394,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());
}
}
@@ -5470,15 +5549,16 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
// Don't parse FOO:BAR as if it were a typo for FOO::BAR inside a class, in
// this context it is a bitfield. Also in range-based for statement colon
// may delimit for-range-declaration.
- ColonProtectionRAIIObject X(*this,
- D.getContext() == Declarator::MemberContext ||
- (D.getContext() == Declarator::ForContext &&
- getLangOpts().CPlusPlus11));
+ ColonProtectionRAIIObject X(
+ *this, D.getContext() == DeclaratorContext::MemberContext ||
+ (D.getContext() == DeclaratorContext::ForContext &&
+ getLangOpts().CPlusPlus11));
// ParseDeclaratorInternal might already have parsed the scope.
if (D.getCXXScopeSpec().isEmpty()) {
- bool EnteringContext = D.getContext() == Declarator::FileContext ||
- D.getContext() == Declarator::MemberContext;
+ bool EnteringContext =
+ D.getContext() == DeclaratorContext::FileContext ||
+ D.getContext() == DeclaratorContext::MemberContext;
ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), nullptr,
EnteringContext);
}
@@ -5507,9 +5587,9 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
// been expanded or contains auto; otherwise, it is parsed as part of the
// parameter-declaration-clause.
if (Tok.is(tok::ellipsis) && D.getCXXScopeSpec().isEmpty() &&
- !((D.getContext() == Declarator::PrototypeContext ||
- D.getContext() == Declarator::LambdaExprParameterContext ||
- D.getContext() == Declarator::BlockLiteralContext) &&
+ !((D.getContext() == DeclaratorContext::PrototypeContext ||
+ D.getContext() == DeclaratorContext::LambdaExprParameterContext ||
+ D.getContext() == DeclaratorContext::BlockLiteralContext) &&
NextToken().is(tok::r_paren) &&
!D.hasGroupingParens() &&
!Actions.containsUnexpandedParameterPacks(D) &&
@@ -5541,22 +5621,22 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
AllowDeductionGuide = false;
} else if (D.getCXXScopeSpec().isSet()) {
AllowConstructorName =
- (D.getContext() == Declarator::FileContext ||
- D.getContext() == Declarator::MemberContext);
+ (D.getContext() == DeclaratorContext::FileContext ||
+ D.getContext() == DeclaratorContext::MemberContext);
AllowDeductionGuide = false;
} else {
- AllowConstructorName = (D.getContext() == Declarator::MemberContext);
+ AllowConstructorName =
+ (D.getContext() == DeclaratorContext::MemberContext);
AllowDeductionGuide =
- (D.getContext() == Declarator::FileContext ||
- D.getContext() == Declarator::MemberContext);
+ (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.
@@ -5604,15 +5684,16 @@ 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() == Declarator::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);
- else if (D.getContext() == Declarator::AliasDeclContext ||
- D.getContext() == Declarator::AliasTemplateContext)
+ else if (D.getContext() == DeclaratorContext::AliasDeclContext ||
+ D.getContext() == DeclaratorContext::AliasTemplateContext)
// The most likely error is that the ';' was forgotten.
DiagnoseIdentifier = NextToken().isOneOf(tok::comma, tok::semi);
- else if (D.getContext() == Declarator::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);
@@ -5626,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)'
@@ -5659,7 +5752,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
LLVM_BUILTIN_TRAP;
if (Tok.is(tok::l_square))
return ParseMisplacedBracketDeclarator(D);
- if (D.getContext() == Declarator::MemberContext) {
+ if (D.getContext() == DeclaratorContext::MemberContext) {
// Objective-C++: Detect C++ keywords and try to prevent further errors by
// treating these keyword as valid member names.
if (getLangOpts().ObjC1 && getLangOpts().CPlusPlus &&
@@ -5889,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);
@@ -6042,9 +6135,9 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
bool IsCXX11MemberFunction =
getLangOpts().CPlusPlus11 &&
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
- (D.getContext() == Declarator::MemberContext
+ (D.getContext() == DeclaratorContext::MemberContext
? !D.getDeclSpec().isFriendSpecified()
- : D.getContext() == Declarator::FileContext &&
+ : D.getContext() == DeclaratorContext::FileContext &&
D.getCXXScopeSpec().isValid() &&
Actions.CurContext->isRecord());
Sema::CXXThisScopeRAII ThisScope(Actions,
@@ -6096,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()) {
@@ -6120,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
@@ -6309,10 +6394,10 @@ void Parser::ParseParameterDeclarationClause(
// Parse the declarator. This is "PrototypeContext" or
// "LambdaExprParameterContext", because we must accept either
// 'declarator' or 'abstract-declarator' here.
- Declarator ParmDeclarator(DS,
- D.getContext() == Declarator::LambdaExprContext ?
- Declarator::LambdaExprParameterContext :
- Declarator::PrototypeContext);
+ Declarator ParmDeclarator(
+ DS, D.getContext() == DeclaratorContext::LambdaExprContext
+ ? DeclaratorContext::LambdaExprParameterContext
+ : DeclaratorContext::PrototypeContext);
ParseDeclarator(ParmDeclarator);
// Parse GNU attributes, if present.
@@ -6355,7 +6440,7 @@ void Parser::ParseParameterDeclarationClause(
SourceLocation EqualLoc = Tok.getLocation();
// Parse the default argument
- if (D.getContext() == Declarator::MemberContext) {
+ if (D.getContext() == DeclaratorContext::MemberContext) {
// If we're inside a class definition, cache the tokens
// corresponding to the default argument. We'll actually parse
// them when we see the end of the class definition.
@@ -6463,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)) {
@@ -6476,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());
@@ -6553,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.
@@ -6610,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/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 44e7a3512098..7c4c83d032b6 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/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"
@@ -55,7 +55,7 @@ using namespace clang;
/// namespace-alias-definition: [C++ 7.3.2: namespace.alias]
/// 'namespace' identifier '=' qualified-namespace-specifier ';'
///
-Parser::DeclGroupPtrTy Parser::ParseNamespace(unsigned Context,
+Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context,
SourceLocation &DeclEnd,
SourceLocation InlineLoc) {
assert(Tok.is(tok::kw_namespace) && "Not a namespace!");
@@ -183,13 +183,12 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(unsigned 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
// any improperly nested namespaces.
@@ -233,11 +232,10 @@ 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);
+ 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");
@@ -307,7 +305,7 @@ Decl *Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
/// 'extern' string-literal '{' declaration-seq[opt] '}'
/// 'extern' string-literal declaration
///
-Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) {
+Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, DeclaratorContext Context) {
assert(isTokenStringLiteral() && "Not a string literal!");
ExprResult Lang = ParseStringLiteralExpression(false);
@@ -434,7 +432,7 @@ Decl *Parser::ParseExportDeclaration() {
/// ParseUsingDirectiveOrDeclaration - Parse C++ using using-declaration or
/// using-directive. Assumes that current token is 'using'.
Parser::DeclGroupPtrTy
-Parser::ParseUsingDirectiveOrDeclaration(unsigned Context,
+Parser::ParseUsingDirectiveOrDeclaration(DeclaratorContext Context,
const ParsedTemplateInfo &TemplateInfo,
SourceLocation &DeclEnd,
ParsedAttributesWithRange &attrs) {
@@ -482,7 +480,7 @@ Parser::ParseUsingDirectiveOrDeclaration(unsigned Context,
/// 'using' 'namespace' ::[opt] nested-name-specifier[opt]
/// namespace-name attributes[opt] ;
///
-Decl *Parser::ParseUsingDirective(unsigned Context,
+Decl *Parser::ParseUsingDirective(DeclaratorContext Context,
SourceLocation UsingLoc,
SourceLocation &DeclEnd,
ParsedAttributes &attrs) {
@@ -543,7 +541,7 @@ Decl *Parser::ParseUsingDirective(unsigned 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).
@@ -551,7 +549,8 @@ Decl *Parser::ParseUsingDirective(unsigned Context,
/// using-declarator:
/// 'typename'[opt] nested-name-specifier unqualified-id
///
-bool Parser::ParseUsingDeclarator(unsigned Context, UsingDeclarator &D) {
+bool Parser::ParseUsingDeclarator(DeclaratorContext Context,
+ UsingDeclarator &D) {
D.clear();
// Ignore optional 'typename'.
@@ -582,7 +581,8 @@ bool Parser::ParseUsingDeclarator(unsigned Context, UsingDeclarator &D) {
// or the simple-template-id's template-name in the last component of the
// nested-name-specifier, the name is [...] considered to name the
// constructor.
- if (getLangOpts().CPlusPlus11 && Context == Declarator::MemberContext &&
+ if (getLangOpts().CPlusPlus11 &&
+ Context == DeclaratorContext::MemberContext &&
Tok.is(tok::identifier) &&
(NextToken().is(tok::semi) || NextToken().is(tok::comma) ||
NextToken().is(tok::ellipsis)) &&
@@ -600,7 +600,7 @@ bool Parser::ParseUsingDeclarator(unsigned Context, UsingDeclarator &D) {
/*AllowConstructorName=*/!(Tok.is(tok::identifier) &&
NextToken().is(tok::equal)),
/*AllowDeductionGuide=*/false,
- nullptr, D.TemplateKWLoc, D.Name))
+ nullptr, nullptr, D.Name))
return true;
}
@@ -629,7 +629,7 @@ bool Parser::ParseUsingDeclarator(unsigned Context, UsingDeclarator &D) {
/// 'using' identifier attribute-specifier-seq[opt] = type-id ;
///
Parser::DeclGroupPtrTy
-Parser::ParseUsingDeclaration(unsigned Context,
+Parser::ParseUsingDeclaration(DeclaratorContext Context,
const ParsedTemplateInfo &TemplateInfo,
SourceLocation UsingLoc, SourceLocation &DeclEnd,
AccessSpecifier AS) {
@@ -699,7 +699,7 @@ Parser::ParseUsingDeclaration(unsigned Context,
// "typename" keyword is allowed for identifiers only,
// because it may be a type definition.
if (D.TypenameLoc.isValid() &&
- D.Name.getKind() != UnqualifiedId::IK_Identifier) {
+ D.Name.getKind() != UnqualifiedIdKind::IK_Identifier) {
Diag(D.Name.getSourceRange().getBegin(),
diag::err_typename_identifiers_only)
<< FixItHint::CreateRemoval(SourceRange(D.TypenameLoc));
@@ -709,7 +709,7 @@ Parser::ParseUsingDeclaration(unsigned 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);
}
@@ -753,7 +753,7 @@ Decl *Parser::ParseAliasDeclarationAfterDeclarator(
// Type alias templates cannot be specialized.
int SpecKind = -1;
if (TemplateInfo.Kind == ParsedTemplateInfo::Template &&
- D.Name.getKind() == UnqualifiedId::IK_TemplateId)
+ D.Name.getKind() == UnqualifiedIdKind::IK_TemplateId)
SpecKind = 0;
if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization)
SpecKind = 1;
@@ -773,7 +773,7 @@ Decl *Parser::ParseAliasDeclarationAfterDeclarator(
}
// Name must be an identifier.
- if (D.Name.getKind() != UnqualifiedId::IK_Identifier) {
+ if (D.Name.getKind() != UnqualifiedIdKind::IK_Identifier) {
Diag(D.Name.StartLocation, diag::err_alias_declaration_not_identifier);
// No removal fixit: can't recover from this.
SkipUntil(tok::semi);
@@ -791,11 +791,11 @@ Decl *Parser::ParseAliasDeclarationAfterDeclarator(
<< FixItHint::CreateRemoval(SourceRange(D.EllipsisLoc));
Decl *DeclFromDeclSpec = nullptr;
- TypeResult TypeAlias =
- ParseTypeName(nullptr,
- TemplateInfo.Kind ? Declarator::AliasTemplateContext
- : Declarator::AliasDeclContext,
- AS, &DeclFromDeclSpec, &Attrs);
+ TypeResult TypeAlias = ParseTypeName(
+ nullptr,
+ TemplateInfo.Kind ? DeclaratorContext::AliasTemplateContext
+ : DeclaratorContext::AliasDeclContext,
+ AS, &DeclFromDeclSpec, &Attrs);
if (OwnedType)
*OwnedType = DeclFromDeclSpec;
@@ -811,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.
@@ -940,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;
@@ -1094,7 +1094,7 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
EndLocation = ParseDecltypeSpecifier(DS);
- Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+ Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
}
@@ -1195,7 +1195,7 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
DS.SetTypeSpecType(TST_typename, IdLoc, PrevSpec, DiagID, Type,
Actions.getASTContext().getPrintingPolicy());
- Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+ Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
}
@@ -1206,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);
}
}
@@ -1612,14 +1612,15 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// new struct s;
// or
// &T::operator struct s;
- // For these, DSC is DSC_type_specifier or DSC_alias_declaration.
+ // For these, DSC is DeclSpecContext::DSC_type_specifier or
+ // DeclSpecContext::DSC_alias_declaration.
// If there are attributes after class name, parse them.
MaybeParseCXX11Attributes(Attributes);
const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();
Sema::TagUseKind TUK;
- if (DSC == DSC_trailing)
+ if (DSC == DeclSpecContext::DSC_trailing)
TUK = Sema::TUK_Reference;
else if (Tok.is(tok::l_brace) ||
(getLangOpts().CPlusPlus && Tok.is(tok::colon)) ||
@@ -1749,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)) {
@@ -1822,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),
@@ -1837,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);
@@ -1881,15 +1868,14 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
stripTypeAttributesOffDeclSpec(attrs, DS, TUK);
// 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(),
- DSC == DSC_type_specifier,
- DSC == DSC_template_param ||
- DSC == DSC_template_type_arg, &SkipBody);
+ TagOrTempResult = Actions.ActOnTag(
+ 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,
+ &SkipBody);
// If ActOnTag said the type was dependent, try again with the
// less common call.
@@ -1927,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;
@@ -2107,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.
@@ -2247,7 +2233,7 @@ bool Parser::isCXX11FinalKeyword() const {
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,
@@ -2298,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);
}
}
@@ -2318,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,
@@ -2422,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)) {
@@ -2474,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;
}
@@ -2486,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())));
}
}
@@ -2509,7 +2495,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
SourceLocation DeclEnd;
return DeclGroupPtrTy::make(
DeclGroupRef(ParseTemplateDeclarationOrSpecialization(
- Declarator::MemberContext, DeclEnd, AS, AccessAttrs)));
+ DeclaratorContext::MemberContext, DeclEnd, AccessAttrs, AS)));
}
// Handle: member-declaration ::= '__extension__' member-declaration
@@ -2522,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);
@@ -2545,7 +2531,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
}
SourceLocation DeclEnd;
// Otherwise, it must be a using-declaration or an alias-declaration.
- return ParseUsingDeclaration(Declarator::MemberContext, TemplateInfo,
+ return ParseUsingDeclaration(DeclaratorContext::MemberContext, TemplateInfo,
UsingLoc, DeclEnd, AS);
}
@@ -2559,7 +2545,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
if (MalformedTypeSpec)
DS.SetTypeSpecError();
- ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class,
+ ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DeclSpecContext::DSC_class,
&CommonLateParsedAttrs);
// Turn off colon protection that was set for declspec.
@@ -2569,7 +2555,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// may get this far before the problem becomes obvious.
if (DS.hasTagDefinition() &&
TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate &&
- DiagnoseMissingSemiAfterTagDefinition(DS, AS, DSC_class,
+ DiagnoseMissingSemiAfterTagDefinition(DS, AS, DeclSpecContext::DSC_class,
&CommonLateParsedAttrs))
return nullptr;
@@ -2593,7 +2579,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
return Actions.ConvertDeclToDeclGroup(TheDecl);
}
- ParsingDeclarator DeclaratorInfo(*this, DS, Declarator::MemberContext);
+ ParsingDeclarator DeclaratorInfo(*this, DS, DeclaratorContext::MemberContext);
VirtSpecifiers VS;
// Hold late-parsed attributes so we can attach a Decl to them later.
@@ -2774,7 +2760,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// initialize it.
ThisDecl = VT->getTemplatedDecl();
- if (ThisDecl && AccessAttrs)
+ if (ThisDecl)
Actions.ProcessDeclAttributeList(getCurScope(), ThisDecl, AccessAttrs);
}
@@ -2852,7 +2838,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
break;
if (Tok.isAtStartOfLine() &&
- !MightBeDeclarator(Declarator::MemberContext)) {
+ !MightBeDeclarator(DeclaratorContext::MemberContext)) {
// This comma was followed by a line-break and something which can't be
// the start of a declarator. The comma was probably a typo for a
// semicolon.
@@ -3006,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:
@@ -3075,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();
}
@@ -3089,7 +3076,7 @@ Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas(
TagDecl);
default:
- return ParseCXXClassMemberDeclaration(AS, AccessAttrs.getList());
+ return ParseCXXClassMemberDeclaration(AS, AccessAttrs);
}
}
@@ -3108,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
@@ -3277,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
@@ -3502,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
@@ -3583,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;
@@ -3704,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, Declarator::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
@@ -3724,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)
@@ -3732,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
@@ -3770,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.
@@ -3818,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;
@@ -3857,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.
@@ -3889,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;
@@ -4026,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))
@@ -4179,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);
}
}
@@ -4217,8 +4201,9 @@ 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;
@@ -4248,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;
}
@@ -4265,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();
@@ -4273,7 +4260,7 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType,
}
// Parse all the comma separated declarators.
- ParseCXXClassMemberDeclaration(CurAS, nullptr);
+ ParseCXXClassMemberDeclaration(CurAS, AccessAttrs);
}
Braces.consumeClose();
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index bc587628c954..4a0e1c5e3413 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/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
@@ -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 ')'
@@ -820,6 +820,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:
@@ -1000,7 +1002,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
DS.SetTypeSpecType(TST_typename, ILoc, PrevSpec, DiagID, Typ,
Actions.getASTContext().getPrintingPolicy());
- Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+ Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
TypeResult Ty = Actions.ActOnTypeName(getCurScope(),
DeclaratorInfo);
if (Ty.isInvalid())
@@ -1039,11 +1041,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 +1063,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();
@@ -1209,7 +1214,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
PrevSpec, DiagID, Type,
Actions.getASTContext().getPrintingPolicy());
- Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+ Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
TypeResult Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
if (Ty.isInvalid())
break;
@@ -1224,6 +1229,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:
@@ -1449,7 +1455,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
@@ -1686,8 +1692,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() ||
@@ -1712,11 +1720,25 @@ 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();
@@ -1755,7 +1777,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
/*AllowConstructorName=*/
getLangOpts().MicrosoftExt,
/*AllowDeductionGuide=*/false,
- ObjectType, TemplateKWLoc, Name)) {
+ ObjectType, &TemplateKWLoc, Name)) {
(void)Actions.CorrectDelayedTyposInExpr(LHS);
LHS = ExprError();
}
@@ -1765,6 +1787,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
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 '++'
@@ -1824,7 +1848,7 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
if (isTypeIdUnambiguously()) {
DeclSpec DS(AttrFactory);
ParseSpecifierQualifierList(DS);
- Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+ Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
ParseDeclarator(DeclaratorInfo);
SourceLocation LParenLoc = PP.getLocForEndOfToken(OpTok.getLocation());
@@ -1881,7 +1905,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]
@@ -2381,7 +2405,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
// Parse the type declarator.
DeclSpec DS(AttrFactory);
ParseSpecifierQualifierList(DS);
- Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+ Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
ParseDeclarator(DeclaratorInfo);
// If our type is followed by an identifier and either ':' or ']', then
@@ -2694,7 +2718,7 @@ ExprResult Parser::ParseGenericSelectionExpression() {
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
@@ -2802,7 +2826,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 +2864,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);
}
}
@@ -2858,7 +2888,7 @@ void Parser::ParseBlockId(SourceLocation CaretLoc) {
ParseSpecifierQualifierList(DS);
// Parse the block-declarator.
- Declarator DeclaratorInfo(DS, Declarator::BlockLiteralContext);
+ Declarator DeclaratorInfo(DS, DeclaratorContext::BlockLiteralContext);
DeclaratorInfo.setFunctionDefinitionKind(FDK_Definition);
ParseDeclarator(DeclaratorInfo);
@@ -2897,7 +2927,7 @@ ExprResult Parser::ParseBlockLiteralExpression() {
// Parse the return type if present.
DeclSpec DS(AttrFactory);
- Declarator ParamInfo(DS, Declarator::BlockLiteralContext);
+ Declarator ParamInfo(DS, DeclaratorContext::BlockLiteralContext);
ParamInfo.setFunctionDefinitionKind(FDK_Definition);
// FIXME: Since the return type isn't actually parsed, it can't be used to
// fill ParamInfo with an initial valid range, so do it manually.
@@ -2929,33 +2959,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/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 959cb7a61d3a..26e75999518a 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/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
@@ -292,8 +292,8 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
break;
}
- if (TemplateName.getKind() != UnqualifiedId::IK_OperatorFunctionId &&
- TemplateName.getKind() != UnqualifiedId::IK_LiteralOperatorId) {
+ if (TemplateName.getKind() != UnqualifiedIdKind::IK_OperatorFunctionId &&
+ TemplateName.getKind() != UnqualifiedIdKind::IK_LiteralOperatorId) {
Diag(TemplateName.getSourceRange().getBegin(),
diag::err_id_after_template_in_nested_name_spec)
<< TemplateName.getSourceRange();
@@ -515,7 +515,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
<< 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();
@@ -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.
@@ -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
@@ -805,6 +808,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
IdentifierInfo *Id = nullptr;
SourceLocation EllipsisLoc;
ExprResult Init;
+ SourceLocation LocStart = Tok.getLocation();
if (Tok.is(tok::star)) {
Loc = ConsumeToken();
@@ -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();
@@ -1090,7 +1097,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
// Parse lambda-declarator[opt].
DeclSpec DS(AttrFactory);
- Declarator D(DS, Declarator::LambdaExprContext);
+ Declarator D(DS, DeclaratorContext::LambdaExprContext);
TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
Actions.PushLambdaScope();
@@ -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;
@@ -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
@@ -1353,7 +1354,7 @@ ExprResult Parser::ParseCXXCasts() {
ParseSpecifierQualifierList(DS);
// Parse the abstract-declarator, if present.
- Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+ Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
ParseDeclarator(DeclaratorInfo);
SourceLocation RAngleBracketLoc = Tok.getLocation();
@@ -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.
///
@@ -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]
@@ -1660,7 +1661,7 @@ ExprResult Parser::ParseCXXThis() {
/// In C++1z onwards, the type specifier can also be a template-name.
ExprResult
Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
- Declarator DeclaratorInfo(DS, Declarator::FunctionalCastContext);
+ Declarator DeclaratorInfo(DS, DeclaratorContext::FunctionalCastContext);
ParsedType TypeRep = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get();
assert((Tok.is(tok::l_paren) ||
@@ -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,13 +1782,11 @@ 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(
- Declarator::InitStmtContext, DeclEnd, attrs, /*RequireSemi=*/true);
+ DeclGroupPtrTy DG =
+ ParseSimpleDeclaration(DeclaratorContext::InitStmtContext, DeclEnd,
+ attrs, /*RequireSemi=*/true);
*InitStmt = Actions.ActOnDeclStmt(DG, DeclStart, DeclEnd);
return ParseCXXCondition(nullptr, Loc, CK);
}
@@ -1781,10 +1799,10 @@ Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt,
// type-specifier-seq
DeclSpec DS(AttrFactory);
DS.takeAttributesFrom(attrs);
- ParseSpecifierQualifierList(DS, AS_none, DSC_condition);
+ ParseSpecifierQualifierList(DS, AS_none, DeclSpecContext::DSC_condition);
// declarator
- Declarator DeclaratorInfo(DS, Declarator::ConditionContext);
+ Declarator DeclaratorInfo(DS, DeclaratorContext::ConditionContext);
ParseDeclarator(DeclaratorInfo);
// simple-asm-expr[opt]
@@ -1945,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;
@@ -1982,12 +2003,12 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
/// type-specifier type-specifier-seq[opt]
///
bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
- ParseSpecifierQualifierList(DS, AS_none, DSC_type_specifier);
+ ParseSpecifierQualifierList(DS, AS_none, DeclSpecContext::DSC_type_specifier);
DS.Finish(Actions, Actions.getASTContext().getPrintingPolicy());
return false;
}
-/// \brief Finish parsing a C++ unqualified-id that is a template-id of
+/// 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
@@ -2027,15 +2048,14 @@ 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()) {
- case UnqualifiedId::IK_Identifier:
- case UnqualifiedId::IK_OperatorFunctionId:
- case UnqualifiedId::IK_LiteralOperatorId:
+ case UnqualifiedIdKind::IK_Identifier:
+ case UnqualifiedIdKind::IK_OperatorFunctionId:
+ case UnqualifiedIdKind::IK_LiteralOperatorId:
if (AssumeTemplateId) {
// We defer the injected-class-name checks until we've found whether
// this template-id is used to form a nested-name-specifier or not.
@@ -2058,11 +2078,11 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
// parse correctly as a template, so suggest the keyword 'template'
// before 'getAs' and treat this as a dependent template name.
std::string Name;
- if (Id.getKind() == UnqualifiedId::IK_Identifier)
+ if (Id.getKind() == UnqualifiedIdKind::IK_Identifier)
Name = Id.Identifier->getName();
else {
Name = "operator ";
- if (Id.getKind() == UnqualifiedId::IK_OperatorFunctionId)
+ if (Id.getKind() == UnqualifiedIdKind::IK_OperatorFunctionId)
Name += getOperatorSpelling(Id.OperatorFunctionId.Operator);
else
Name += Id.Identifier->getName();
@@ -2079,7 +2099,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
}
break;
- case UnqualifiedId::IK_ConstructorName: {
+ case UnqualifiedIdKind::IK_ConstructorName: {
UnqualifiedId TemplateName;
bool MemberOfUnknownSpecialization;
TemplateName.setIdentifier(Name, NameLoc);
@@ -2090,7 +2110,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
break;
}
- case UnqualifiedId::IK_DestructorName: {
+ case UnqualifiedIdKind::IK_DestructorName: {
UnqualifiedId TemplateName;
bool MemberOfUnknownSpecialization;
TemplateName.setIdentifier(Name, NameLoc);
@@ -2125,22 +2145,24 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
// 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() == UnqualifiedId::IK_Identifier ||
- Id.getKind() == UnqualifiedId::IK_OperatorFunctionId ||
- Id.getKind() == UnqualifiedId::IK_LiteralOperatorId) {
+
+ if (Id.getKind() == UnqualifiedIdKind::IK_Identifier ||
+ Id.getKind() == UnqualifiedIdKind::IK_OperatorFunctionId ||
+ Id.getKind() == UnqualifiedIdKind::IK_LiteralOperatorId) {
// Form a parsed representation of the template-id to be stored in the
// UnqualifiedId.
// FIXME: Store name for literal operator too.
IdentifierInfo *TemplateII =
- Id.getKind() == UnqualifiedId::IK_Identifier ? Id.Identifier : nullptr;
- OverloadedOperatorKind OpKind = Id.getKind() == UnqualifiedId::IK_Identifier
- ? OO_None
- : Id.OperatorFunctionId.Operator;
+ Id.getKind() == UnqualifiedIdKind::IK_Identifier ? Id.Identifier
+ : nullptr;
+ OverloadedOperatorKind OpKind =
+ Id.getKind() == UnqualifiedIdKind::IK_Identifier
+ ? OO_None
+ : Id.OperatorFunctionId.Operator;
TemplateIdAnnotation *TemplateId = TemplateIdAnnotation::Create(
SS, TemplateKWLoc, Id.StartLocation, TemplateII, OpKind, Template, TNK,
@@ -2162,7 +2184,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
if (Type.isInvalid())
return true;
- if (Id.getKind() == UnqualifiedId::IK_ConstructorName)
+ if (Id.getKind() == UnqualifiedIdKind::IK_ConstructorName)
Id.setConstructorName(Type.get(), NameLoc, RAngleLoc);
else
Id.setDestructorName(Id.StartLocation, Type.get(), RAngleLoc);
@@ -2170,7 +2192,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
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
@@ -2395,7 +2417,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
// Parse the conversion-declarator, which is merely a sequence of
// ptr-operators.
- Declarator D(DS, Declarator::ConversionIdContext);
+ Declarator D(DS, DeclaratorContext::ConversionIdContext);
ParseDeclaratorInternal(D, /*DirectDeclParser=*/nullptr);
// Finish up the type.
@@ -2409,7 +2431,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
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
@@ -2446,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,10 +2506,10 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
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() &&
@@ -2494,11 +2523,18 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
}
// 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;
}
@@ -2520,11 +2556,11 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
<< 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();
@@ -2539,7 +2575,14 @@ 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;
}
@@ -2556,13 +2599,20 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
//
// template-id:
// operator-function-id < template-argument-list[opt] >
- if ((Result.getKind() == UnqualifiedId::IK_OperatorFunctionId ||
- Result.getKind() == UnqualifiedId::IK_LiteralOperatorId) &&
- (TemplateSpecified || Tok.is(tok::less)))
- return ParseUnqualifiedIdTemplateId(SS, TemplateKWLoc,
- nullptr, SourceLocation(),
- EnteringContext, ObjectType,
- Result, TemplateSpecified);
+ TemplateTy Template;
+ if ((Result.getKind() == UnqualifiedIdKind::IK_OperatorFunctionId ||
+ Result.getKind() == UnqualifiedIdKind::IK_LiteralOperatorId) &&
+ 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;
}
@@ -2630,12 +2680,11 @@ 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.
@@ -2696,7 +2745,7 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
SourceRange TypeIdParens;
DeclSpec DS(AttrFactory);
- Declarator DeclaratorInfo(DS, Declarator::CXXNewContext);
+ Declarator DeclaratorInfo(DS, DeclaratorContext::CXXNewContext);
if (Tok.is(tok::l_paren)) {
// If it turns out to be a placement, we change the type location.
BalancedDelimiterTracker T(*this, tok::l_paren);
@@ -2836,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;
@@ -2954,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:
@@ -3172,7 +3220,7 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
if (ParseAs >= CompoundLiteral) {
// Parse the type declarator.
DeclSpec DS(AttrFactory);
- Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+ Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
{
ColonProtectionRAIIObject InnerColonProtection(*this);
ParseSpecifierQualifierList(DS);
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index fb8624a324b9..5c5b3cdfcf33 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/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:
@@ -290,7 +287,7 @@ 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);
@@ -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;
}
}
@@ -1140,14 +1128,14 @@ bool Parser::isTokIdentifier_in() const {
/// 'null_unspecified'
///
void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS,
- Declarator::TheContext Context) {
- assert(Context == Declarator::ObjCParameterContext ||
- Context == Declarator::ObjCResultContext);
+ DeclaratorContext Context) {
+ assert(Context == DeclaratorContext::ObjCParameterContext ||
+ Context == DeclaratorContext::ObjCResultContext);
while (1) {
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCPassingType(getCurScope(), DS,
- Context == Declarator::ObjCParameterContext);
+ Context == DeclaratorContext::ObjCParameterContext);
return cutOffParsing();
}
@@ -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,11 +1212,10 @@ 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:
@@ -1242,12 +1223,12 @@ static void takeDeclAttributes(ParsedAttributes &attrs,
/// '(' objc-type-qualifiers[opt] ')'
///
ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS,
- Declarator::TheContext context,
+ DeclaratorContext context,
ParsedAttributes *paramAttrs) {
- assert(context == Declarator::ObjCParameterContext ||
- context == Declarator::ObjCResultContext);
+ assert(context == DeclaratorContext::ObjCParameterContext ||
+ context == DeclaratorContext::ObjCResultContext);
assert((paramAttrs != nullptr) ==
- (context == Declarator::ObjCParameterContext));
+ (context == DeclaratorContext::ObjCParameterContext));
assert(Tok.is(tok::l_paren) && "expected (");
@@ -1265,9 +1246,9 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS,
// Parse an abstract declarator.
DeclSpec declSpec(AttrFactory);
declSpec.setObjCQualifiers(&DS);
- DeclSpecContext dsContext = DSC_normal;
- if (context == Declarator::ObjCResultContext)
- dsContext = DSC_objc_method_result;
+ DeclSpecContext dsContext = DeclSpecContext::DSC_normal;
+ if (context == DeclaratorContext::ObjCResultContext)
+ dsContext = DeclSpecContext::DSC_objc_method_result;
ParseSpecifierQualifierList(declSpec, AS_none, dsContext);
Declarator declarator(declSpec, context);
ParseDeclarator(declarator);
@@ -1288,7 +1269,7 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS,
// If we're parsing a parameter, steal all the decl attributes
// and add them to the decl spec.
- if (context == Declarator::ObjCParameterContext)
+ if (context == DeclaratorContext::ObjCParameterContext)
takeDeclAttributes(*paramAttrs, declarator);
}
}
@@ -1352,13 +1333,14 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
ParsedType ReturnType;
ObjCDeclSpec DSRet;
if (Tok.is(tok::l_paren))
- ReturnType = ParseObjCTypeName(DSRet, Declarator::ObjCResultContext,
+ ReturnType = ParseObjCTypeName(DSRet, DeclaratorContext::ObjCResultContext,
nullptr);
// If attributes exist before the method, parse them.
ParsedAttributes methodAttrs(AttrFactory);
if (getLangOpts().ObjC2)
MaybeParseGNUAttributes(methodAttrs);
+ MaybeParseCXX11Attributes(methodAttrs);
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus,
@@ -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;
}
@@ -1416,16 +1396,15 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
ArgInfo.Type = nullptr;
if (Tok.is(tok::l_paren)) // Parse the argument type if present.
ArgInfo.Type = ParseObjCTypeName(ArgInfo.DeclSpec,
- Declarator::ObjCParameterContext,
+ DeclaratorContext::ObjCParameterContext,
&paramAttrs);
// 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)) {
@@ -1494,7 +1473,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
DeclSpec DS(AttrFactory);
ParseDeclarationSpecifiers(DS);
// Parse the declarator.
- Declarator ParmDecl(DS, Declarator::PrototypeContext);
+ Declarator ParmDecl(DS, DeclaratorContext::PrototypeContext);
ParseDeclarator(ParmDecl);
IdentifierInfo *ParmII = ParmDecl.getIdentifier();
Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDecl);
@@ -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;
}
@@ -1703,7 +1680,7 @@ void Parser::parseObjCTypeArgsOrProtocolQualifiers(
typeArg, Actions.getASTContext().getPrintingPolicy());
// Form a declarator to turn this into a type.
- Declarator D(DS, Declarator::TypeNameContext);
+ Declarator D(DS, DeclaratorContext::TypeNameContext);
TypeResult fullTypeArg = Actions.ActOnTypeName(getCurScope(), D);
if (fullTypeArg.isUsable()) {
typeArgs.push_back(fullTypeArg.get());
@@ -1886,9 +1863,9 @@ void Parser::HelperActionsForIvarDeclarations(Decl *interfaceDecl, SourceLocatio
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:
@@ -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);
@@ -2273,7 +2245,7 @@ void Parser::ObjCImplParsingDataRAII::finish(SourceRange AtEnd) {
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)
@@ -2543,7 +2515,7 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
if (Tok.isNot(tok::ellipsis)) {
DeclSpec DS(AttrFactory);
ParseDeclarationSpecifiers(DS);
- Declarator ParmDecl(DS, Declarator::ObjCCatchContext);
+ Declarator ParmDecl(DS, DeclaratorContext::ObjCCatchContext);
ParseDeclarator(ParmDecl);
// Inform the actions module about the declarator, so it
@@ -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;
@@ -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 ';'
@@ -2865,7 +2850,7 @@ 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
@@ -2945,7 +2930,7 @@ bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) {
// 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.
- Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+ Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
TypeResult Type = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
if (Type.isInvalid())
return true;
@@ -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
@@ -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
diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp
index a67a5bbe0dea..a413e96a91e7 100644
--- a/lib/Parse/ParseOpenMP.cpp
+++ b/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'
@@ -250,9 +255,10 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
do {
ColonProtectionRAIIObject ColonRAII(*this);
SourceRange Range;
- TypeResult TR = ParseTypeName(&Range, Declarator::PrototypeContext, 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(
@@ -299,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 |
@@ -322,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;
@@ -418,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);
}
@@ -550,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)
@@ -560,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;
@@ -612,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
@@ -642,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: {
@@ -665,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)) {
@@ -694,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);
@@ -718,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;
@@ -734,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 ','.
@@ -748,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.
@@ -757,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;
@@ -771,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
@@ -796,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);
@@ -850,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))
@@ -859,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
@@ -902,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;
@@ -935,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)) {
@@ -946,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)) {
@@ -1026,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();
}
@@ -1079,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(
@@ -1109,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:
@@ -1140,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;
@@ -1152,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);
@@ -1184,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 |
@@ -1204,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) {
@@ -1252,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:
@@ -1269,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:
@@ -1286,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:
@@ -1309,7 +1326,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
ErrorFound = true;
}
- Clause = ParseOpenMPClause(CKind);
+ Clause = ParseOpenMPClause(CKind, WrongDirective);
break;
case OMPC_private:
case OMPC_firstprivate:
@@ -1329,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)
@@ -1338,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;
}
@@ -1362,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'.
///
@@ -1399,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;
@@ -1409,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' ')
@@ -1420,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 '('.
@@ -1437,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'
@@ -1469,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:
@@ -1490,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 '('.
@@ -1509,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'
@@ -1582,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) {
@@ -1592,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()) ||
@@ -1607,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()) {
@@ -1661,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.
@@ -1723,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";
@@ -1774,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();
@@ -1799,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();
@@ -1847,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);
}
@@ -1885,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'.
///
@@ -1939,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;
@@ -1948,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/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp
index 198d5c6e9cb0..9a25f9c25c03 100644
--- a/lib/Parse/ParsePragma.cpp
+++ b/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)) {
@@ -2030,7 +2099,7 @@ PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
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) {
@@ -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/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index 3f25610f4471..deb10af4b17b 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/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 {
@@ -211,7 +211,7 @@ Retry:
Allowed == ACK_Any) &&
isDeclarationStatement()) {
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
- DeclGroupPtrTy Decl = ParseDeclaration(Declarator::BlockContext,
+ DeclGroupPtrTy Decl = ParseDeclaration(DeclaratorContext::BlockContext,
DeclEnd, Attrs);
return Actions.ActOnDeclStmt(Decl, DeclStart, DeclEnd);
}
@@ -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();
@@ -1021,8 +1007,8 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
ExtensionRAIIObject O(Diags);
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
- DeclGroupPtrTy Res = ParseDeclaration(Declarator::BlockContext, DeclEnd,
- attrs);
+ DeclGroupPtrTy Res =
+ ParseDeclaration(DeclaratorContext::BlockContext, DeclEnd, attrs);
R = Actions.ActOnDeclStmt(Res, DeclStart, DeclEnd);
} else {
// Otherwise this was a unary __extension__ marker.
@@ -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;
@@ -1631,7 +1621,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
DeclGroupPtrTy DG = ParseSimpleDeclaration(
- Declarator::ForContext, DeclEnd, attrs, false,
+ DeclaratorContext::ForContext, DeclEnd, attrs, false,
MightBeForRangeStmt ? &ForRangeInit : nullptr);
FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
if (ForRangeInit.ParsedForRangeDecl()) {
@@ -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?
@@ -2181,7 +2171,7 @@ StmtResult Parser::ParseCXXCatchBlock(bool FnCatch) {
if (ParseCXXTypeSpecifierSeq(DS))
return StmtError();
- Declarator ExDecl(DS, Declarator::CXXCatchContext);
+ Declarator ExDecl(DS, DeclaratorContext::CXXCatchContext);
ParseDeclarator(ExDecl);
ExceptionDecl = Actions.ActOnExceptionDeclarator(getCurScope(), ExDecl);
} else
@@ -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/lib/Parse/ParseStmtAsm.cpp b/lib/Parse/ParseStmtAsm.cpp
index d81029e27974..290723c29532 100644
--- a/lib/Parse/ParseStmtAsm.cpp
+++ b/lib/Parse/ParseStmtAsm.cpp
@@ -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/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 56a16b9e0271..f7a69c482e17 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/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(unsigned 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(unsigned Context,
///
/// explicit-specialization: [ C++ temp.expl.spec]
/// 'template' '<' '>' declaration
-Decl *
-Parser::ParseTemplateDeclarationOrSpecialization(unsigned 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(unsigned 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(unsigned Context,
/// declaration. Will be AS_none for namespace-scope declarations.
///
/// \returns the new declaration.
-Decl *
-Parser::ParseSingleDeclarationAfterTemplate(
- unsigned 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");
@@ -186,7 +173,7 @@ Parser::ParseSingleDeclarationAfterTemplate(
return ParseStaticAssertDeclaration(DeclEnd);
}
- if (Context == Declarator::MemberContext) {
+ if (Context == DeclaratorContext::MemberContext) {
// We are parsing a member template.
ParseCXXClassMemberDeclaration(AS, AccessAttrs, TemplateInfo,
&DiagsFromTParams);
@@ -234,7 +221,7 @@ Parser::ParseSingleDeclarationAfterTemplate(
DS.takeAttributesFrom(prefixAttrs);
// Parse the declarator.
- ParsingDeclarator DeclaratorInfo(*this, DS, (Declarator::TheContext)Context);
+ ParsingDeclarator DeclaratorInfo(*this, DS, (DeclaratorContext)Context);
ParseDeclarator(DeclaratorInfo);
// Error parsing the declarator?
if (!DeclaratorInfo.hasName()) {
@@ -255,7 +242,7 @@ Parser::ParseSingleDeclarationAfterTemplate(
// Function definitions are only allowed at file scope and in C++ classes.
// The C++ inline method definition case is handled elsewhere, so we only
// need to handle the file scope definition case.
- if (Context != Declarator::FileContext) {
+ if (Context != DeclaratorContext::FileContext) {
Diag(Tok, diag::err_function_definition_not_allowed);
SkipMalformedDecl();
return nullptr;
@@ -271,7 +258,8 @@ Parser::ParseSingleDeclarationAfterTemplate(
}
if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) {
- if (DeclaratorInfo.getName().getKind() != UnqualifiedId::IK_TemplateId) {
+ if (DeclaratorInfo.getName().getKind() !=
+ UnqualifiedIdKind::IK_TemplateId) {
// If the declarator-id is not a template-id, issue a diagnostic and
// recover by ignoring the 'template' keyword.
Diag(Tok, diag::err_template_defn_explicit_instantiation) << 0;
@@ -369,7 +357,7 @@ bool Parser::ParseTemplateParameters(
/// template-parameter
/// template-parameter-list ',' template-parameter
bool
-Parser::ParseTemplateParameterList(unsigned Depth,
+Parser::ParseTemplateParameterList(const unsigned Depth,
SmallVectorImpl<NamedDecl*> &TemplateParams) {
while (1) {
@@ -402,7 +390,7 @@ Parser::ParseTemplateParameterList(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)) {
@@ -487,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.
@@ -546,7 +548,7 @@ NamedDecl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
ParsedType DefaultArg;
if (TryConsumeToken(tok::equal, EqualLoc))
DefaultArg = ParseTypeName(/*Range=*/nullptr,
- Declarator::TemplateTypeArgContext).get();
+ DeclaratorContext::TemplateTypeArgContext).get();
return Actions.ActOnTypeParameter(getCurScope(), TypenameKeyword, EllipsisLoc,
KeyLoc, ParamName, NameLoc, Depth, Position,
@@ -676,10 +678,10 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
// declarators (parts of declarators?) are accepted for parameters.
DeclSpec DS(AttrFactory);
ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none,
- DSC_template_param);
+ DeclSpecContext::DSC_template_param);
// Parse this as a typename.
- Declarator ParamDecl(DS, Declarator::TemplateParamContext);
+ Declarator ParamDecl(DS, DeclaratorContext::TemplateParamContext);
ParseDeclarator(ParamDecl);
if (DS.getTypeSpecType() == DeclSpec::TST_unspecified) {
Diag(Tok.getLocation(), diag::err_expected_template_parameter);
@@ -739,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
@@ -760,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:
@@ -785,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:
@@ -792,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
@@ -818,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;
@@ -833,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
@@ -923,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
@@ -1015,12 +1047,12 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
Tok.setKind(tok::annot_template_id);
IdentifierInfo *TemplateII =
- TemplateName.getKind() == UnqualifiedId::IK_Identifier
+ TemplateName.getKind() == UnqualifiedIdKind::IK_Identifier
? TemplateName.Identifier
: nullptr;
OverloadedOperatorKind OpKind =
- TemplateName.getKind() == UnqualifiedId::IK_Identifier
+ TemplateName.getKind() == UnqualifiedIdKind::IK_Identifier
? OO_None
: TemplateName.OperatorFunctionId.Operator;
@@ -1044,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,
@@ -1089,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))
@@ -1190,17 +1222,13 @@ 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,
- Declarator::TemplateTypeArgContext);
- if (TypeArg.isInvalid())
- return ParsedTemplateArgument();
-
- return ParsedTemplateArgument(ParsedTemplateArgument::Type,
- TypeArg.get().getAsOpaquePtr(),
- Loc);
+ TypeResult TypeArg = ParseTypeName(
+ /*Range=*/nullptr, DeclaratorContext::TemplateArgContext);
+ return Actions.ActOnTemplateTypeArgument(TypeArg);
}
// Try to parse a template template argument.
@@ -1228,7 +1256,7 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() {
ExprArg.get(), Loc);
}
-/// \brief Determine whether the current tokens can only be parsed 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) {
@@ -1290,27 +1318,26 @@ Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) {
return false;
}
-/// \brief Parse a C++ explicit template instantiation
+/// Parse a C++ explicit template instantiation
/// (C++ [temp.explicit]).
///
/// explicit-instantiation:
/// 'extern' [opt] 'template' declaration
///
/// Note that the 'extern' is a GNU extension and C++11 feature.
-Decl *Parser::ParseExplicitInstantiation(unsigned Context,
+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 {
@@ -1328,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;
@@ -1419,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)) {
@@ -1435,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/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp
index 5c206f4eab90..0603d8e75eea 100644
--- a/lib/Parse/ParseTentative.cpp
+++ b/lib/Parse/ParseTentative.cpp
@@ -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);
@@ -1015,6 +1019,7 @@ 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) \
@@ -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:
@@ -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;
@@ -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:
@@ -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;
@@ -1496,6 +1530,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
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:
@@ -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:
@@ -1867,7 +1903,8 @@ 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]
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 8aa50a2c7f2a..7a0b29cbae86 100644
--- a/lib/Parse/Parser.cpp
+++ b/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;
@@ -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.
@@ -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) {
@@ -783,7 +783,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
// A function definition cannot start with any of these keywords.
{
SourceLocation DeclEnd;
- return ParseDeclaration(Declarator::FileContext, DeclEnd, attrs);
+ return ParseDeclaration(DeclaratorContext::FileContext, DeclEnd, attrs);
}
case tok::kw_static:
@@ -793,7 +793,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
Diag(ConsumeToken(), diag::warn_static_inline_explicit_inst_ignored)
<< 0;
SourceLocation DeclEnd;
- return ParseDeclaration(Declarator::FileContext, DeclEnd, attrs);
+ return ParseDeclaration(DeclaratorContext::FileContext, DeclEnd, attrs);
}
goto dont_know;
@@ -804,7 +804,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
// Inline namespaces. Allowed as an extension even in C++03.
if (NextKind == tok::kw_namespace) {
SourceLocation DeclEnd;
- return ParseDeclaration(Declarator::FileContext, DeclEnd, attrs);
+ return ParseDeclaration(DeclaratorContext::FileContext, DeclEnd, attrs);
}
// Parse (then ignore) 'inline' prior to a template instantiation. This is
@@ -813,7 +813,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
Diag(ConsumeToken(), diag::warn_static_inline_explicit_inst_ignored)
<< 1;
SourceLocation DeclEnd;
- return ParseDeclaration(Declarator::FileContext, DeclEnd, attrs);
+ return ParseDeclaration(DeclaratorContext::FileContext, DeclEnd, attrs);
}
}
goto dont_know;
@@ -828,8 +828,8 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
diag::ext_extern_template) << SourceRange(ExternLoc, TemplateLoc);
SourceLocation DeclEnd;
return Actions.ConvertDeclToDeclGroup(
- ParseExplicitInstantiation(Declarator::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'
@@ -877,7 +877,7 @@ 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");
@@ -919,12 +919,13 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs,
AccessSpecifier AS) {
MaybeParseMicrosoftAttributes(DS.getAttributes());
// Parse the common declaration-specifiers piece.
- ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS, DSC_top_level);
+ ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS,
+ DeclSpecContext::DSC_top_level);
// If we had a free-standing type definition with a missing semicolon, we
// may get this far before the problem becomes obvious.
- if (DS.hasTagDefinition() &&
- DiagnoseMissingSemiAfterTagDefinition(DS, AS, DSC_top_level))
+ if (DS.hasTagDefinition() && DiagnoseMissingSemiAfterTagDefinition(
+ DS, AS, DeclSpecContext::DSC_top_level))
return nullptr;
// C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
@@ -1004,11 +1005,11 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs,
if (getLangOpts().CPlusPlus && isTokenStringLiteral() &&
DS.getStorageClassSpec() == DeclSpec::SCS_extern &&
DS.getParsedSpecifiers() == DeclSpec::PQ_StorageClassSpecifier) {
- Decl *TheDecl = ParseLinkage(DS, Declarator::FileContext);
+ Decl *TheDecl = ParseLinkage(DS, DeclaratorContext::FileContext);
return Actions.ConvertDeclToDeclGroup(TheDecl);
}
- return ParseDeclGroup(DS, Declarator::FileContext);
+ return ParseDeclGroup(DS, DeclaratorContext::FileContext);
}
Parser::DeclGroupPtrTy
@@ -1088,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
@@ -1313,7 +1309,7 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) {
}
// Parse the first declarator attached to this declspec.
- Declarator ParmDeclarator(DS, Declarator::KNRTypeListContext);
+ Declarator ParmDeclarator(DS, DeclaratorContext::KNRTypeListContext);
ParseDeclarator(ParmDeclarator);
// Handle the full declarator list.
@@ -1450,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) {
@@ -1478,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.
@@ -1763,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,
@@ -1774,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();
@@ -2001,7 +1997,7 @@ 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;
}
@@ -2122,6 +2118,7 @@ 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;
@@ -2145,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();
}
@@ -2184,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.
@@ -2249,7 +2256,7 @@ bool BalancedDelimiterTracker::expectAndConsume(unsigned DiagID,
return true;
}
- if (getDepth() < MaxDepth)
+ if (getDepth() < P.getLangOpts().BracketDepth)
return false;
return diagnoseOverflow();
diff --git a/lib/Rewrite/DeltaTree.cpp b/lib/Rewrite/DeltaTree.cpp
index 352fab077a2e..1dfc26cc918f 100644
--- a/lib/Rewrite/DeltaTree.cpp
+++ b/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.
@@ -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/lib/Rewrite/HTMLRewrite.cpp b/lib/Rewrite/HTMLRewrite.cpp
index 618c0179f100..d93961f3582e 100644
--- a/lib/Rewrite/HTMLRewrite.cpp
+++ b/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,7 +42,8 @@ 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();
@@ -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/lib/Rewrite/RewriteRope.cpp b/lib/Rewrite/RewriteRope.cpp
index 030ab7732fc3..5bc79f3eddc9 100644
--- a/lib/Rewrite/RewriteRope.cpp
+++ b/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/lib/Rewrite/Rewriter.cpp b/lib/Rewrite/Rewriter.cpp
index ae41decc64a3..cb59a161fe68 100644
--- a/lib/Rewrite/Rewriter.cpp
+++ b/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) {
@@ -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);
@@ -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/lib/Rewrite/TokenRewriter.cpp b/lib/Rewrite/TokenRewriter.cpp
index 494defdedaa9..1f5dec499c92 100644
--- a/lib/Rewrite/TokenRewriter.cpp
+++ b/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/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp
index 0033edf326ac..82d9df25d934 100644
--- a/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/lib/Sema/AnalysisBasedWarnings.cpp
@@ -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;
-
- // Make the processing stack and seed it with the entry block.
- SmallVector<CFGBlock *, 16> Stack;
- Stack.push_back(&cfg->getEntry());
-
- while (!Stack.empty()) {
- CFGBlock *CurBlock = Stack.back();
- Stack.pop_back();
+ // Seed the work list with the entry block.
+ WorkList.push_back(&cfg->getEntry());
- unsigned ID = CurBlock->getBlockID();
- RecursiveState CurState = States[ID];
+ while (!WorkList.empty()) {
+ CFGBlock *Block = WorkList.pop_back_val();
- 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,
@@ -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;
@@ -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:
@@ -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());
});
@@ -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();
@@ -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());
@@ -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/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt
index 7d9ae621c93d..bad42a2ce252 100644
--- a/lib/Sema/CMakeLists.txt
+++ b/lib/Sema/CMakeLists.txt
@@ -9,13 +9,13 @@ endif()
add_clang_library(clangSema
AnalysisBasedWarnings.cpp
- AttributeList.cpp
CodeCompleteConsumer.cpp
DeclSpec.cpp
DelayedDiagnostic.cpp
IdentifierResolver.cpp
JumpDiagnostics.cpp
MultiplexExternalSemaSource.cpp
+ ParsedAttr.cpp
Scope.cpp
ScopeInfo.cpp
Sema.cpp
diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp
index 3431ddcf70a2..9c4d315a692f 100644
--- a/lib/Sema/CodeCompleteConsumer.cpp
+++ b/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,7 +42,7 @@ using namespace clang;
//===----------------------------------------------------------------------===//
bool CodeCompletionContext::wantConstructorResults() const {
- switch (Kind) {
+ switch (CCKind) {
case CCC_Recovery:
case CCC_Statement:
case CCC_Expression:
@@ -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("")
-{
+ : Kind(Kind), Text("") {
switch (Kind) {
case CK_TypedText:
case CK_Text:
@@ -195,10 +279,9 @@ CodeCompletionString::CodeCompletionString(const Chunk *Chunks,
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,7 +305,6 @@ const char *CodeCompletionString::getAnnotation(unsigned AnnotationNr) const {
return nullptr;
}
-
std::string CodeCompletionString::getAsString() const {
std::string Result;
llvm::raw_string_ostream OS(Result);
@@ -267,7 +349,7 @@ 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];
@@ -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;
@@ -311,7 +393,7 @@ StringRef CodeCompletionTUInfo::getParentName(const DeclContext *DC) {
// 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() << ')';
@@ -375,9 +457,8 @@ void CodeCompletionBuilder::AddChunk(CodeCompletionString::ChunkKind CK,
}
void CodeCompletionBuilder::addParentContext(const DeclContext *DC) {
- if (DC->isTranslationUnit()) {
+ if (DC->isTranslationUnit())
return;
- }
if (DC->isFunctionOrMethod())
return;
@@ -427,25 +508,21 @@ 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.");
}
@@ -477,7 +554,24 @@ 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;
@@ -485,7 +579,7 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
OS << Results[I].Keyword << '\n';
break;
- case CodeCompletionResult::RK_Macro: {
+ case CodeCompletionResult::RK_Macro:
OS << Results[I].Macro->getName();
if (CodeCompletionString *CCS
= Results[I].CreateCodeCompletionString(SemaRef, Context,
@@ -496,14 +590,12 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
}
OS << '\n';
break;
- }
- case CodeCompletionResult::RK_Pattern: {
+ case CodeCompletionResult::RK_Pattern:
OS << "Pattern : "
<< Results[I].Pattern->getAsString() << '\n';
break;
}
- }
}
}
@@ -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))
@@ -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.
diff --git a/lib/Sema/CoroutineStmtBuilder.h b/lib/Sema/CoroutineStmtBuilder.h
index 33a368d92ff4..d15cf0b756e7 100644
--- a/lib/Sema/CoroutineStmtBuilder.h
+++ b/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/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp
index 6fe2dcc9895f..ccca5d37ea39 100644
--- a/lib/Sema/DeclSpec.cpp
+++ b/lib/Sema/DeclSpec.cpp
@@ -30,7 +30,7 @@ using namespace clang;
void UnqualifiedId::setTemplateId(TemplateIdAnnotation *TemplateId) {
assert(TemplateId && "NULL template-id annotation?");
- Kind = IK_TemplateId;
+ Kind = UnqualifiedIdKind::IK_TemplateId;
this->TemplateId = TemplateId;
StartLocation = TemplateId->TemplateNameLoc;
EndLocation = TemplateId->RAngleLoc;
@@ -38,7 +38,7 @@ void UnqualifiedId::setTemplateId(TemplateIdAnnotation *TemplateId) {
void UnqualifiedId::setConstructorTemplateId(TemplateIdAnnotation *TemplateId) {
assert(TemplateId && "NULL template-id annotation?");
- Kind = IK_ConstructorTemplateId;
+ Kind = UnqualifiedIdKind::IK_ConstructorTemplateId;
this->TemplateId = TemplateId;
StartLocation = TemplateId->TemplateNameLoc;
EndLocation = TemplateId->RAngleLoc;
@@ -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;
@@ -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;
@@ -329,6 +330,7 @@ bool Declarator::isDeclarationOfFunction() const {
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:
@@ -387,16 +391,16 @@ bool Declarator::isDeclarationOfFunction() const {
}
bool Declarator::isStaticMember() {
- assert(getContext() == MemberContext);
+ assert(getContext() == DeclaratorContext::MemberContext);
return getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static ||
- (getName().Kind == UnqualifiedId::IK_OperatorFunctionId &&
+ (getName().Kind == UnqualifiedIdKind::IK_OperatorFunctionId &&
CXXMethodDecl::isStaticOverloadedOperator(
getName().OperatorFunctionId.Operator));
}
bool Declarator::isCtorOrDtor() {
- return (getName().getKind() == UnqualifiedId::IK_ConstructorName) ||
- (getName().getKind() == UnqualifiedId::IK_DestructorName);
+ return (getName().getKind() == UnqualifiedIdKind::IK_ConstructorName) ||
+ (getName().getKind() == UnqualifiedIdKind::IK_DestructorName);
}
bool DeclSpec::hasTagDefinition() const {
@@ -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) {
@@ -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)
@@ -1281,7 +1303,7 @@ bool DeclSpec::isMissingDeclaratorOk() {
void UnqualifiedId::setOperatorFunctionId(SourceLocation OperatorLoc,
OverloadedOperatorKind Op,
SourceLocation SymbolLocations[3]) {
- Kind = IK_OperatorFunctionId;
+ Kind = UnqualifiedIdKind::IK_OperatorFunctionId;
StartLocation = OperatorLoc;
EndLocation = OperatorLoc;
OperatorFunctionId.Operator = Op;
diff --git a/lib/Sema/DelayedDiagnostic.cpp b/lib/Sema/DelayedDiagnostic.cpp
index 3d321d561e60..122b477d5522 100644
--- a/lib/Sema/DelayedDiagnostic.cpp
+++ b/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;
@@ -57,6 +65,7 @@ void DelayedDiagnostic::Destroy() {
case Availability:
delete[] AvailabilityData.Message;
+ delete[] AvailabilityData.SelectorLocs;
break;
case ForbiddenType:
diff --git a/lib/Sema/IdentifierResolver.cpp b/lib/Sema/IdentifierResolver.cpp
index 0bdb19490bc5..dbd52dee1eea 100644
--- a/lib/Sema/IdentifierResolver.cpp
+++ b/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;
@@ -245,14 +248,16 @@ IdentifierResolver::begin(DeclarationName Name) {
}
namespace {
- enum DeclMatchKind {
- DMK_Different,
- DMK_Replace,
- DMK_Ignore
- };
-}
-/// \brief Compare two declarations to see whether they are different or,
+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) {
diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp
index 64fa2c34b238..58a7862370cc 100644
--- a/lib/Sema/JumpDiagnostics.cpp
+++ b/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/lib/Sema/MultiplexExternalSemaSource.cpp b/lib/Sema/MultiplexExternalSemaSource.cpp
index 77ace0cfa579..7e61ccbb1068 100644
--- a/lib/Sema/MultiplexExternalSemaSource.cpp
+++ b/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.
///
@@ -164,6 +164,20 @@ 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 &Alignment,
diff --git a/lib/Sema/AttributeList.cpp b/lib/Sema/ParsedAttr.cpp
index 14d334746f1f..6509df9985ef 100644
--- a/lib/Sema/AttributeList.cpp
+++ b/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/lib/Sema/Scope.cpp b/lib/Sema/Scope.cpp
index ae5b181c6728..eae5a328bfa2 100644
--- a/lib/Sema/Scope.cpp
+++ b/lib/Sema/Scope.cpp
@@ -143,72 +143,43 @@ void Scope::dumpImpl(raw_ostream &OS) const {
if (HasFlags)
OS << "Flags: ";
- while (Flags) {
- if (Flags & FnScope) {
- OS << "FnScope";
- Flags &= ~FnScope;
- } else if (Flags & BreakScope) {
- OS << "BreakScope";
- Flags &= ~BreakScope;
- } else if (Flags & ContinueScope) {
- OS << "ContinueScope";
- Flags &= ~ContinueScope;
- } else if (Flags & DeclScope) {
- OS << "DeclScope";
- Flags &= ~DeclScope;
- } else if (Flags & ControlScope) {
- OS << "ControlScope";
- Flags &= ~ControlScope;
- } else if (Flags & ClassScope) {
- OS << "ClassScope";
- Flags &= ~ClassScope;
- } else if (Flags & BlockScope) {
- OS << "BlockScope";
- Flags &= ~BlockScope;
- } else if (Flags & TemplateParamScope) {
- OS << "TemplateParamScope";
- Flags &= ~TemplateParamScope;
- } else if (Flags & FunctionPrototypeScope) {
- OS << "FunctionPrototypeScope";
- Flags &= ~FunctionPrototypeScope;
- } else if (Flags & FunctionDeclarationScope) {
- OS << "FunctionDeclarationScope";
- Flags &= ~FunctionDeclarationScope;
- } else if (Flags & AtCatchScope) {
- OS << "AtCatchScope";
- Flags &= ~AtCatchScope;
- } else if (Flags & ObjCMethodScope) {
- OS << "ObjCMethodScope";
- Flags &= ~ObjCMethodScope;
- } else if (Flags & SwitchScope) {
- OS << "SwitchScope";
- Flags &= ~SwitchScope;
- } else if (Flags & TryScope) {
- OS << "TryScope";
- Flags &= ~TryScope;
- } else if (Flags & FnTryCatchScope) {
- OS << "FnTryCatchScope";
- Flags &= ~FnTryCatchScope;
- } else if (Flags & SEHTryScope) {
- OS << "SEHTryScope";
- Flags &= ~SEHTryScope;
- } else if (Flags & SEHExceptScope) {
- OS << "SEHExceptScope";
- Flags &= ~SEHExceptScope;
- } else if (Flags & OpenMPDirectiveScope) {
- OS << "OpenMPDirectiveScope";
- Flags &= ~OpenMPDirectiveScope;
- } else if (Flags & OpenMPLoopDirectiveScope) {
- OS << "OpenMPLoopDirectiveScope";
- Flags &= ~OpenMPLoopDirectiveScope;
- } else if (Flags & OpenMPSimdDirectiveScope) {
- OS << "OpenMPSimdDirectiveScope";
- Flags &= ~OpenMPSimdDirectiveScope;
+ std::pair<unsigned, const char *> FlagInfo[] = {
+ {FnScope, "FnScope"},
+ {BreakScope, "BreakScope"},
+ {ContinueScope, "ContinueScope"},
+ {DeclScope, "DeclScope"},
+ {ControlScope, "ControlScope"},
+ {ClassScope, "ClassScope"},
+ {BlockScope, "BlockScope"},
+ {TemplateParamScope, "TemplateParamScope"},
+ {FunctionPrototypeScope, "FunctionPrototypeScope"},
+ {FunctionDeclarationScope, "FunctionDeclarationScope"},
+ {AtCatchScope, "AtCatchScope"},
+ {ObjCMethodScope, "ObjCMethodScope"},
+ {SwitchScope, "SwitchScope"},
+ {TryScope, "TryScope"},
+ {FnTryCatchScope, "FnTryCatchScope"},
+ {OpenMPDirectiveScope, "OpenMPDirectiveScope"},
+ {OpenMPLoopDirectiveScope, "OpenMPLoopDirectiveScope"},
+ {OpenMPSimdDirectiveScope, "OpenMPSimdDirectiveScope"},
+ {EnumScope, "EnumScope"},
+ {SEHTryScope, "SEHTryScope"},
+ {SEHExceptScope, "SEHExceptScope"},
+ {SEHFilterScope, "SEHFilterScope"},
+ {CompoundStmtScope, "CompoundStmtScope"},
+ {ClassInheritanceScope, "ClassInheritanceScope"}};
+
+ for (auto Info : FlagInfo) {
+ if (Flags & Info.first) {
+ OS << Info.second;
+ Flags &= ~Info.first;
+ if (Flags)
+ OS << " | ";
}
-
- if (Flags)
- OS << " | ";
}
+
+ assert(Flags == 0 && "Unknown scope flags");
+
if (HasFlags)
OS << '\n';
diff --git a/lib/Sema/ScopeInfo.cpp b/lib/Sema/ScopeInfo.cpp
index b309a36a30a3..62a83ccb70aa 100644
--- a/lib/Sema/ScopeInfo.cpp
+++ b/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/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 4e57e5ef81c6..d57473c5616f 100644
--- a/lib/Sema/Sema.cpp
+++ b/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;
@@ -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/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp
index 98a918bd7d63..9fbae2ca297f 100644
--- a/lib/Sema/SemaAccess.cpp
+++ b/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"
@@ -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) {
@@ -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)
diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp
index 4ba2a317e1f9..4f3cf4633c80 100644
--- a/lib/Sema/SemaAttr.cpp
+++ b/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";
}
@@ -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;
}
}
diff --git a/lib/Sema/SemaCUDA.cpp b/lib/Sema/SemaCUDA.cpp
index cac5f682275e..13dd8d936fd2 100644
--- a/lib/Sema/SemaCUDA.cpp
+++ b/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/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp
index 6da4d2a26191..f2fad825c3e7 100644
--- a/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/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.
@@ -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.
@@ -846,6 +846,9 @@ 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)
<< T << getLangOpts().CPlusPlus;
@@ -967,7 +970,7 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
}
namespace {
- /// \brief A structure that stores a nested-name-specifier annotation,
+ /// A structure that stores a nested-name-specifier annotation,
/// including both the nested-name-specifier
struct NestedNameSpecifierAnnotation {
NestedNameSpecifier *NNS;
diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp
index ad6348685b64..b7f4629fbab7 100644
--- a/lib/Sema/SemaCast.cpp
+++ b/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;
}
@@ -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())
@@ -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.");
+ 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,
// 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.
@@ -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
@@ -890,8 +953,7 @@ void CastOperation::CheckReinterpretCast() {
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) {
@@ -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();
}
}
@@ -967,14 +1032,15 @@ void CastOperation::CheckStaticCast() {
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();
}
}
@@ -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;
@@ -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,6 +1964,12 @@ 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,
@@ -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;
@@ -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,7 +2258,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;
}
// C++ 5.2.10p7: A pointer to an object can be explicitly converted to
@@ -2208,8 +2266,8 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
// 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) {
@@ -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,13 +2394,14 @@ 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
@@ -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;
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 803f87b3c568..8d953b6ef341 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/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"
@@ -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) {
@@ -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,
@@ -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);
}
}
}
@@ -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:
@@ -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:
@@ -3598,7 +4875,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
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:
@@ -4115,15 +5392,19 @@ 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);
}
@@ -4519,7 +5800,7 @@ bool Sema::SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum,
/// 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;
}
@@ -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);
@@ -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
@@ -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(),
@@ -6469,9 +7768,11 @@ 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 {
@@ -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;
@@ -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);
@@ -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(
@@ -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) {
@@ -8972,6 +10059,16 @@ static void AnalyzeComparison(Sema &S, BinaryOperator *E) {
LHS = LHS->IgnoreParenImpCasts();
RHS = RHS->IgnoreParenImpCasts();
+ if (!S.getLangOpts().CPlusPlus) {
+ // Avoid warning about comparison of integers with different signs when
+ // RHS/LHS has a `typeof(E)` type whose sign is different from the sign of
+ // the type of `E`.
+ if (const auto *TET = dyn_cast<TypeOfExprType>(LHS->getType()))
+ LHS = TET->getUnderlyingExpr()->IgnoreParenImpCasts();
+ if (const auto *TET = dyn_cast<TypeOfExprType>(RHS->getType()))
+ RHS = TET->getUnderlyingExpr()->IgnoreParenImpCasts();
+ }
+
// Check to see if one of the (unmodified) operands is of different
// signedness.
Expr *signedOperand, *unsignedOperand;
@@ -9195,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,
@@ -9223,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.
@@ -9364,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.
@@ -9565,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))
@@ -9842,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)) {
@@ -9886,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,
@@ -9929,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.
@@ -9992,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
@@ -10096,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;
}
@@ -10218,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
@@ -10254,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;
@@ -10270,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) {
@@ -10278,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) {
@@ -10298,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.
@@ -10419,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();
@@ -10441,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)) {
@@ -10452,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)
@@ -10831,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());
}
}
}
@@ -10930,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
@@ -11000,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();
@@ -11085,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)
@@ -11105,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);
@@ -11515,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 {
@@ -11531,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;
}
}
}
@@ -11545,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;
}
}
}
@@ -11941,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
@@ -11950,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()))
@@ -11971,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) {
@@ -12015,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) {
@@ -12054,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;
@@ -12092,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.
///
@@ -12163,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.
///
@@ -12257,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,
@@ -12277,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/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 9aed178763dc..4e571eba17e9 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/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,69 @@ 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);
+ if (Ctx) {
+ DeclContext *AccessingCtx = Ctx;
+ // If ND comes from a base class, set the naming class back to the
+ // derived class if the search starts from the derived class (i.e.
+ // InBaseClass is true).
+ //
+ // Example:
+ // class B { protected: int X; }
+ // class D : public B { void f(); }
+ // void D::f() { this->^; }
+ // The completion after "this->" will have `InBaseClass` set to true and
+ // `Ctx` set to "B", when looking up in `B`. We need to set the actual
+ // accessing context (i.e. naming class) to "D" so that access can be
+ // calculated correctly.
+ if (InBaseClass && isa<CXXRecordDecl>(Ctx)) {
+ CXXRecordDecl *RC = nullptr;
+ // Get the enclosing record.
+ for (DeclContext *DC = CurContext; !DC->isFileContext();
+ DC = DC->getParent()) {
+ if ((RC = dyn_cast<CXXRecordDecl>(DC)))
+ break;
+ }
+ if (RC)
+ AccessingCtx = RC;
+ }
+ Accessible = Results.getSema().IsSimplyAccessible(ND, AccessingCtx);
+ }
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 +1368,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 +1385,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 +1400,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 +1426,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 +1452,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 +1463,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 +1491,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 +1508,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 +1525,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 +1551,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 +1569,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 +1583,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 +1622,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 +1645,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 +1662,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 +1677,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 +1693,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 +1754,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 +1788,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 +1817,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 +1879,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 +1900,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 +1914,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 +1944,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 +1952,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 +1960,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 +1969,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 +1989,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 +2000,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 +2010,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 +2020,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 +2029,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 +2039,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 +2051,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 +2078,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddPlaceholderChunk("expression");
Results.AddResult(Result(Builder.TakeString()));
}
-
+
// FIXME: Rethrow?
if (SemaRef.getLangOpts().CPlusPlus11) {
@@ -2079,7 +2123,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 +2155,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Results.AddResult(Result(Builder.TakeString()));
break;
}
-
+
case Sema::PCC_Type:
case Sema::PCC_LocalDeclarationSpecifiers:
break;
@@ -2124,7 +2168,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 +2180,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 +2210,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 +2232,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 +2267,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 +2329,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 +2376,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 +2390,7 @@ static std::string FormatFunctionParameter(const PrintingPolicy &Policy,
} else {
Type.getAsStringInternal(Result, Policy);
}
-
+
return Result;
}
@@ -2357,14 +2401,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 +2493,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 +2501,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 +2516,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 +2536,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 +2547,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 +2565,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 +2574,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 +2590,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 +2598,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 +2614,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 +2650,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 +2659,7 @@ AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
return;
// FIXME: Add ref-qualifier!
-
+
// Handle single qualifiers without copying
if (Proto->getTypeQuals() == Qualifiers::Const) {
Result.AddInformativeChunk(" const");
@@ -2643,29 +2687,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 +2720,7 @@ static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
Result.AddTypedTextChunk(OperatorName);
break;
}
-
+
case DeclarationName::Identifier:
case DeclarationName::CXXConversionFunctionName:
case DeclarationName::CXXDestructorName:
@@ -2684,14 +2728,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 +2749,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 +2771,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 +2830,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 +2879,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 +2890,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 +2913,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 +2944,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 +2955,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 +2970,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 +2989,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 +3018,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 +3039,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 +3055,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 +3191,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 +3203,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 +3224,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 +3243,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 +3292,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 +3323,7 @@ CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
}
}
}
-
+
return CXCursor_UnexposedDecl;
}
@@ -3250,10 +3331,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 +3349,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 +3376,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 +3401,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 +3415,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 +3424,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 +3432,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 +3464,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 +3478,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 +3502,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 +3521,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 +3534,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 +3549,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 +3586,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 +3602,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 +3619,7 @@ void Sema::CodeCompleteOrdinaryName(Scope *S,
if (S->getFnParent())
AddPrettyFunctionResults(getLangOpts(), Results);
break;
-
+
case PCC_Namespace:
case PCC_Class:
case PCC_ObjCInterface:
@@ -3551,15 +3633,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 +3658,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 +3672,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 +3701,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 +3711,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 +3747,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 +3785,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 +3854,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 +3973,7 @@ static void AddObjCProperties(
}
}
}
-
+
// Add properties in referenced protocols.
if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
for (auto *P : Protocol->protocols())
@@ -3929,17 +4013,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 +4051,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 +4221,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 +4245,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 +4281,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());
}
@@ -4171,8 +4295,8 @@ void Sema::CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D,
AddTypeQualifierResults(DS, Results, LangOpts);
if (LangOpts.CPlusPlus11) {
Results.AddResult("noexcept");
- if (D.getContext() == Declarator::MemberContext && !D.isCtorOrDtor() &&
- !D.isStaticMember()) {
+ if (D.getContext() == DeclaratorContext::MemberContext &&
+ !D.isCtorOrDtor() && !D.isStaticMember()) {
if (!VS || !VS->isFinalSpecified())
Results.AddResult("final");
if (!VS || !VS->isOverrideSpecified())
@@ -4192,7 +4316,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 +4324,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 +4345,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 +4369,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 +4385,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 +4434,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 +4588,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 +4627,7 @@ void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
CodeCompleteOrdinaryName(S, PCC_Expression);
return;
}
-
+
CodeCompleteExpression(S, VD->getType());
}
@@ -4537,13 +4653,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 +4697,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 +4766,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 +4780,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 +4816,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 +4865,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 +4874,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 +4882,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 +4899,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 +4932,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 +4949,7 @@ void Sema::CodeCompleteConstructorInitializer(
InitializedFields.insert(cast<FieldDecl>(
Initializers[I]->getAnyMember()));
}
-
+
// Add completions for base classes.
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
@@ -4841,69 +4960,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 +5031,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 +5060,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 +5072,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 +5082,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 +5099,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 +5108,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 +5141,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 +5199,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 +5219,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 +5272,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 +5293,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 +5332,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 +5344,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 +5355,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 +5388,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 +5450,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 +5469,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 +5495,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 +5536,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 +5552,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 +5581,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 +5595,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 +5633,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 +5661,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 +5671,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 +5698,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 +5723,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 +5814,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 +5827,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 +5845,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 +5871,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 +5879,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 +5894,7 @@ static ObjCMethodDecl *AddSuperSendCompletion(
Builder.AddTypedTextChunk("super");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
}
-
+
Selector Sel = CurMethod->getSelector();
if (Sel.isUnarySelector()) {
if (NeedSuperKeyword)
@@ -5796,7 +5908,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 +5924,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 +5942,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 +5980,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 +6000,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 +6029,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 +6068,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 +6081,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 +6142,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 +6176,7 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
return;
}
- HandleCodeCompleteResults(this, CodeCompleter,
+ HandleCodeCompleteResults(this, CodeCompleter,
Results.getCompletionContext(),
Results.data(), Results.size());
}
@@ -6073,9 +6186,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 +6197,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 +6229,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 +6274,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 +6302,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 +6319,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 +6335,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 +6353,7 @@ void Sema::CodeCompleteObjCForCollection(Scope *S,
Data.IgnoreDecls.push_back(*I);
}
}
-
+
CodeCompleteExpression(S, Data);
}
@@ -6254,11 +6367,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 +6379,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 +6392,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 +6402,7 @@ void Sema::CodeCompleteObjCSelector(Scope *S,
Accumulator.clear();
}
}
-
+
Accumulator += Sel.getNameForSlot(I);
Accumulator += ':';
}
@@ -6297,19 +6410,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 +6436,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 +6454,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 +6496,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 +6532,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 +6550,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 +6579,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 +6604,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 +6622,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 +6641,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 +6681,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 +6700,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 +6717,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 +6753,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 +6768,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 +6785,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 +6797,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 +6812,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 +6830,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 +6856,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 +6872,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 +6896,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 +6920,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 +6943,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 +6966,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 +6985,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 +7025,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 +7038,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 +7061,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 +7088,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 +7106,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 +7126,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 +7140,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 +7160,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 +7172,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 +7191,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 +7248,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 +7267,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 +7300,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 +7322,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 +7341,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 +7371,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 +7393,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 +7415,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 +7437,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 +7458,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 +7487,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 +7497,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 +7509,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 +7525,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 +7534,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 +7548,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 +7566,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 +7597,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 +7623,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 +7647,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 +7655,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 +7688,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 +7718,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 +7748,7 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
Results.AddResult(Builder.TakeString());
}
}
-
+
continue;
}
@@ -7658,7 +7760,7 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
Results.MaybeAddResult(R, CurContext);
}
}
-
+
Results.ExitScope();
if (!AtParameterName && !SelIdents.empty() &&
@@ -7677,9 +7779,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 +7788,7 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_PreprocessorDirective);
Results.EnterNewScope();
-
+
// #if <condition>
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
@@ -7695,13 +7796,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 +7824,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 +7840,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 +7855,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 +7867,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 +7877,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 +7898,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 +7907,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 +7915,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 +7936,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 +7953,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 +7970,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 +7994,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 +8005,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 +8028,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 +8038,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/lib/Sema/SemaCoroutine.cpp b/lib/Sema/SemaCoroutine.cpp
index e6b640f878c2..1d5454ca778b 100644
--- a/lib/Sema/SemaCoroutine.cpp
+++ b/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/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index a1fc725f8df4..55542828f783 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/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) =
@@ -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 ");
@@ -4746,7 +4808,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
}
// Mock up a declarator.
- Declarator Dc(DS, Declarator::MemberContext);
+ Declarator Dc(DS, DeclaratorContext::MemberContext);
TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S);
assert(TInfo && "couldn't build declarator info for anonymous struct/union");
@@ -4843,7 +4905,7 @@ Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS,
assert(Record && "expected a record!");
// Mock up a declarator.
- Declarator Dc(DS, Declarator::TypeNameContext);
+ Declarator Dc(DS, DeclaratorContext::TypeNameContext);
TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S);
assert(TInfo && "couldn't build declarator info for anonymous struct");
@@ -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;
@@ -4897,13 +4959,13 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
switch (Name.getKind()) {
- case UnqualifiedId::IK_ImplicitSelfParam:
- case UnqualifiedId::IK_Identifier:
+ case UnqualifiedIdKind::IK_ImplicitSelfParam:
+ case UnqualifiedIdKind::IK_Identifier:
NameInfo.setName(Name.Identifier);
NameInfo.setLoc(Name.StartLocation);
return NameInfo;
- case UnqualifiedId::IK_DeductionGuideName: {
+ case UnqualifiedIdKind::IK_DeductionGuideName: {
// C++ [temp.deduct.guide]p3:
// The simple-template-id shall name a class template specialization.
// The template-name shall be the same identifier as the template-name
@@ -4931,7 +4993,7 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
return NameInfo;
}
- case UnqualifiedId::IK_OperatorFunctionId:
+ case UnqualifiedIdKind::IK_OperatorFunctionId:
NameInfo.setName(Context.DeclarationNames.getCXXOperatorName(
Name.OperatorFunctionId.Operator));
NameInfo.setLoc(Name.StartLocation);
@@ -4941,14 +5003,14 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
= Name.EndLocation.getRawEncoding();
return NameInfo;
- case UnqualifiedId::IK_LiteralOperatorId:
+ case UnqualifiedIdKind::IK_LiteralOperatorId:
NameInfo.setName(Context.DeclarationNames.getCXXLiteralOperatorName(
Name.Identifier));
NameInfo.setLoc(Name.StartLocation);
NameInfo.setCXXLiteralOperatorNameLoc(Name.EndLocation);
return NameInfo;
- case UnqualifiedId::IK_ConversionFunctionId: {
+ case UnqualifiedIdKind::IK_ConversionFunctionId: {
TypeSourceInfo *TInfo;
QualType Ty = GetTypeFromParser(Name.ConversionFunctionId, &TInfo);
if (Ty.isNull())
@@ -4960,7 +5022,7 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
return NameInfo;
}
- case UnqualifiedId::IK_ConstructorName: {
+ case UnqualifiedIdKind::IK_ConstructorName: {
TypeSourceInfo *TInfo;
QualType Ty = GetTypeFromParser(Name.ConstructorName, &TInfo);
if (Ty.isNull())
@@ -4972,7 +5034,7 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
return NameInfo;
}
- case UnqualifiedId::IK_ConstructorTemplateId: {
+ case UnqualifiedIdKind::IK_ConstructorTemplateId: {
// In well-formed code, we can only have a constructor
// template-id that refers to the current context, so go there
// to find the actual type being constructed.
@@ -4995,7 +5057,7 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
return NameInfo;
}
- case UnqualifiedId::IK_DestructorName: {
+ case UnqualifiedIdKind::IK_DestructorName: {
TypeSourceInfo *TInfo;
QualType Ty = GetTypeFromParser(Name.DestructorName, &TInfo);
if (Ty.isNull())
@@ -5007,7 +5069,7 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
return NameInfo;
}
- case UnqualifiedId::IK_TemplateId: {
+ case UnqualifiedIdKind::IK_TemplateId: {
TemplateName TName = Name.TemplateId->Template.get();
SourceLocation TNameLoc = Name.TemplateId->TemplateNameLoc;
return Context.getNameForTemplate(TName, TNameLoc);
@@ -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
@@ -5670,8 +5737,8 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr)
<< 1;
- if (D.getName().Kind != UnqualifiedId::IK_Identifier) {
- if (D.getName().Kind == UnqualifiedId::IK_DeductionGuideName)
+ if (D.getName().Kind != UnqualifiedIdKind::IK_Identifier) {
+ if (D.getName().Kind == UnqualifiedIdKind::IK_DeductionGuideName)
Diag(D.getName().StartLocation,
diag::err_deduction_guide_invalid_specifier)
<< "typedef";
@@ -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
@@ -6148,29 +6215,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 +6256,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 +6362,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 +6384,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;
@@ -6425,7 +6498,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
TemplateParams = MatchTemplateParametersToScopeSpecifier(
D.getDeclSpec().getLocStart(), D.getIdentifierLoc(),
D.getCXXScopeSpec(),
- D.getName().getKind() == UnqualifiedId::IK_TemplateId
+ D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId
? D.getName().TemplateId
: nullptr,
TemplateParamLists,
@@ -6433,7 +6506,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
if (TemplateParams) {
if (!TemplateParams->size() &&
- D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
+ D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) {
// There is an extraneous 'template<>' for this variable. Complain
// about it, but allow the declaration of the variable.
Diag(TemplateParams->getTemplateLoc(),
@@ -6443,7 +6516,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
TemplateParams->getRAngleLoc());
TemplateParams = nullptr;
} else {
- if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
+ if (D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId) {
// This is an explicit specialization or a partial specialization.
// FIXME: Check that we can declare a specialization here.
IsVariableTemplateSpecialization = true;
@@ -6464,9 +6537,9 @@ NamedDecl *Sema::ActOnVariableDeclarator(
}
}
} else {
- assert(
- (Invalid || D.getName().getKind() != UnqualifiedId::IK_TemplateId) &&
- "should have a 'template<>' for this decl");
+ assert((Invalid ||
+ D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) &&
+ "should have a 'template<>' for this decl");
}
if (IsVariableTemplateSpecialization) {
@@ -6842,9 +6915,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 +6960,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 +6977,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 +6994,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 +7009,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 +7140,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 +7298,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 +7436,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 +7482,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 +7517,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 +7588,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 +7704,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
@@ -8176,7 +8256,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);
@@ -8261,7 +8341,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
MatchTemplateParametersToScopeSpecifier(
D.getDeclSpec().getLocStart(), D.getIdentifierLoc(),
D.getCXXScopeSpec(),
- D.getName().getKind() == UnqualifiedId::IK_TemplateId
+ D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId
? D.getName().TemplateId
: nullptr,
TemplateParamLists, isFriend, isMemberSpecialization,
@@ -8318,7 +8398,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// and clearly the user wants a template specialization. So
// we need to insert '<>' after the name.
SourceLocation InsertLoc;
- if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
+ if (D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) {
InsertLoc = D.getName().getSourceRange().getEnd();
InsertLoc = getLocForEndOfToken(InsertLoc);
}
@@ -8655,6 +8735,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);
@@ -8719,7 +8808,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// If the declarator is a template-id, translate the parser's template
// argument list into our AST format.
- if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
+ if (D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId) {
TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc);
TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc);
@@ -8785,10 +8874,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 +9079,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 +9161,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 +9275,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 +9879,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 +9932,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 +9953,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 +10123,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 +10634,7 @@ namespace {
S.DiagRuntimeBehavior(DRE->getLocStart(), DRE,
S.PDiag(diag)
- << DRE->getNameInfo().getName()
+ << DRE->getDecl()
<< OrigDecl->getLocation()
<< DRE->getSourceRange());
}
@@ -10011,12 +10694,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();
@@ -10260,7 +10953,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 +11053,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 +11165,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 +11218,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 +11491,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();
}
}
@@ -10893,13 +11590,13 @@ Sema::ActOnCXXForRangeIdentifier(Scope *S, SourceLocation IdentLoc,
DS.SetTypeSpecType(DeclSpec::TST_auto, IdentLoc, PrevSpec, DiagID,
getPrintingPolicy());
- Declarator D(DS, Declarator::ForContext);
+ Declarator D(DS, DeclaratorContext::ForContext);
D.SetIdentifier(Ident, 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 +11631,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
@@ -10947,6 +11648,8 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
if (var->isThisDeclarationADefinition() &&
var->getDeclContext()->getRedeclContext()->isFileContext() &&
var->isExternallyVisible() && var->hasLinkage() &&
+ !var->isInline() && !var->getDescribedVarTemplate() &&
+ !isTemplateInstantiation(var->getTemplateSpecializationKind()) &&
!getDiagnostics().isIgnored(diag::warn_missing_variable_declarations,
var->getLocation())) {
// Find a previous declaration that's not a definition.
@@ -11140,7 +11843,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;
@@ -11227,58 +11930,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);
@@ -11657,7 +12310,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,
@@ -11809,7 +12462,7 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
// Use the identifier location for the type source range.
DS.SetRangeStart(FTI.Params[i].IdentLoc);
DS.SetRangeEnd(FTI.Params[i].IdentLoc);
- Declarator ParamD(DS, Declarator::KNRTypeListContext);
+ Declarator ParamD(DS, DeclaratorContext::KNRTypeListContext);
ParamD.SetIdentifier(FTI.Params[i].Ident, FTI.Params[i].IdentLoc);
FTI.Params[i].Param = ActOnParamDeclarator(S, ParamD);
}
@@ -11894,9 +12547,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;
@@ -11981,8 +12670,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))
@@ -12119,7 +12813,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.
///
@@ -12172,9 +12866,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);
}
@@ -12270,8 +12970,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());
}
@@ -12314,6 +13014,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()) &&
@@ -12391,6 +13098,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;
}
@@ -12496,7 +13206,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())
@@ -12507,10 +13217,20 @@ void Sema::ActOnFinishDelayedAttribute(Scope *S, Decl *D,
/// call, forming a call to an implicitly defined function (per C99 6.5.1p2).
NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
IdentifierInfo &II, Scope *S) {
+ // Find the scope in which the identifier is injected and the corresponding
+ // DeclContext.
+ // FIXME: C89 does not say what happens if there is no enclosing block scope.
+ // In that case, we inject the declaration into the translation unit scope
+ // instead.
Scope *BlockScope = S;
while (!BlockScope->isCompoundStmtScope() && BlockScope->getParent())
BlockScope = BlockScope->getParent();
+ Scope *ContextScope = BlockScope;
+ while (!ContextScope->getEntity())
+ ContextScope = ContextScope->getParent();
+ ContextRAII SavedContext(*this, ContextScope->getEntity());
+
// Before we produce a declaration for an implicitly defined
// function, see whether there was a locally-scoped declaration of
// this name as a function or variable. If so, use that
@@ -12574,7 +13294,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
(void)Error; // Silence warning.
assert(!Error && "Error setting up implicit decl!");
SourceLocation NoLoc;
- Declarator D(DS, Declarator::BlockContext);
+ Declarator D(DS, DeclaratorContext::BlockContext);
D.AddTypeInfo(DeclaratorChunk::getFunction(/*HasProto=*/false,
/*IsAmbiguous=*/false,
/*LParenLoc=*/NoLoc,
@@ -12588,18 +13308,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.
@@ -12611,7 +13329,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
@@ -12661,11 +13379,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:
@@ -12741,7 +13459,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()));
}
}
@@ -12803,7 +13521,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();
@@ -12821,11 +13539,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();
@@ -12845,10 +13561,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();
@@ -12859,7 +13571,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!
///
@@ -12873,7 +13585,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.
@@ -12907,7 +13619,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.
@@ -13043,8 +13755,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,
@@ -13064,7 +13776,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.
@@ -13077,13 +13789,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.
@@ -13122,14 +13833,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.
@@ -13144,14 +13852,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;
@@ -13167,11 +13875,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;
- }
}
}
@@ -13197,8 +13906,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;
@@ -13577,7 +14285,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;
}
@@ -13595,7 +14303,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 &&
@@ -13787,13 +14495,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);
@@ -13801,8 +14508,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.
@@ -13818,12 +14524,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;
}
}
@@ -13834,6 +14534,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
@@ -13872,13 +14573,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));
@@ -13965,8 +14663,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.
@@ -13983,9 +14680,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);
}
@@ -14369,7 +15064,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
@@ -14420,6 +15115,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()) {
@@ -14752,7 +15454,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) {
@@ -14780,7 +15482,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
@@ -14963,8 +15666,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.
@@ -15000,6 +15702,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.
@@ -15027,10 +15750,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.
@@ -15045,7 +15768,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;
@@ -15077,6 +15800,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();
@@ -15119,7 +15845,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;
@@ -15207,12 +15933,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,
@@ -15229,7 +15952,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
@@ -15292,7 +16015,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
@@ -15456,7 +16179,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 =
@@ -15507,7 +16230,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.
@@ -15559,39 +16282,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;
@@ -15600,20 +16294,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.
@@ -15621,45 +16323,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;
}
@@ -15672,26 +16374,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();
}
}
@@ -15725,14 +16422,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) {
@@ -15803,7 +16498,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/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 21fe46ad9dd1..320eabd5ec2f 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/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,45 +1027,44 @@ 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;
@@ -1120,33 +1074,32 @@ static bool checkForConsumableClass(Sema &S, const CXXMethodDecl *MD,
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;
}
@@ -1154,27 +1107,26 @@ static void handleCallableWhenAttr(Sema &S, Decl *D,
}
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;
}
@@ -1185,31 +1137,30 @@ 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;
}
@@ -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);
+ 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()));
-}
-
-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()));
+ D->addAttr(::new (S.Context) AliasAttr(AL.getRange(), S.Context, Str,
+ AL.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 handleCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+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 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()));
-}
-
-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()));
+ AL.getRange(), S.Context,
+ AL.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,21 +2516,21 @@ 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;
}
@@ -2637,62 +2538,60 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr,
// (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);
@@ -2709,12 +2608,12 @@ static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) {
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()));
+ 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)) {
@@ -3302,20 +3274,20 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {
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.
@@ -3485,14 +3456,13 @@ static void handleAnnotateAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
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,40 +4783,40 @@ 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;
@@ -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;
}
// 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, AL);
+}
+
+
+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;
+ }
- handleSimpleAttribute<AVRSignalAttr>(S, D, Attr);
+ D->addAttr(::new (S.Context) RISCVInterruptAttr(
+ AL.getLoc(), S.Context, Kind, AL.getAttributeSpellingListIndex()));
}
-static void handleInterruptAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+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,659 @@ 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_MayAlias:
+ handleSimpleAttribute<MayAliasAttr>(S, D, AL);
break;
- case AttributeList::AT_Mode:
- handleModeAttr(S, D, Attr);
+ case ParsedAttr::AT_Mode:
+ handleModeAttr(S, D, AL);
break;
- case AttributeList::AT_NoAlias:
- handleSimpleAttribute<NoAliasAttr>(S, D, Attr);
+ case ParsedAttr::AT_NoAlias:
+ handleSimpleAttribute<NoAliasAttr>(S, D, AL);
break;
- case AttributeList::AT_NoCommon:
- handleSimpleAttribute<NoCommonAttr>(S, D, Attr);
+ case ParsedAttr::AT_NoCommon:
+ handleSimpleAttribute<NoCommonAttr>(S, D, AL);
break;
- case AttributeList::AT_NoSplitStack:
- handleSimpleAttribute<NoSplitStackAttr>(S, D, Attr);
+ case ParsedAttr::AT_NoSplitStack:
+ handleSimpleAttribute<NoSplitStackAttr>(S, D, AL);
break;
- case AttributeList::AT_NonNull:
- if (ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(D))
- handleNonNullAttrParameter(S, PVD, Attr);
+ 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 AttributeList::AT_ReturnsNonNull:
- handleReturnsNonNullAttr(S, D, Attr);
+ case ParsedAttr::AT_AssumeAligned:
+ handleAssumeAlignedAttr(S, D, AL);
break;
- case AttributeList::AT_NoEscape:
- handleNoEscapeAttr(S, D, Attr);
+ case ParsedAttr::AT_AllocAlign:
+ handleAllocAlignAttr(S, D, AL);
break;
- case AttributeList::AT_AssumeAligned:
- handleAssumeAlignedAttr(S, D, Attr);
+ case ParsedAttr::AT_Overloadable:
+ handleSimpleAttribute<OverloadableAttr>(S, D, AL);
break;
- case AttributeList::AT_AllocAlign:
- handleAllocAlignAttr(S, D, Attr);
+ case ParsedAttr::AT_Ownership:
+ handleOwnershipAttr(S, D, AL);
break;
- case AttributeList::AT_Overloadable:
- handleSimpleAttribute<OverloadableAttr>(S, D, Attr);
+ case ParsedAttr::AT_Cold:
+ handleSimpleAttributeWithExclusions<ColdAttr, HotAttr>(S, D, AL);
break;
- case AttributeList::AT_Ownership:
- handleOwnershipAttr(S, D, Attr);
+ case ParsedAttr::AT_Hot:
+ handleSimpleAttributeWithExclusions<HotAttr, ColdAttr>(S, D, AL);
break;
- case AttributeList::AT_Cold:
- handleColdAttr(S, D, Attr);
+ case ParsedAttr::AT_Naked:
+ handleNakedAttr(S, D, AL);
break;
- case AttributeList::AT_Hot:
- handleHotAttr(S, D, Attr);
+ case ParsedAttr::AT_NoReturn:
+ handleNoReturnAttr(S, D, AL);
break;
- case AttributeList::AT_Naked:
- handleNakedAttr(S, D, Attr);
+ case ParsedAttr::AT_AnyX86NoCfCheck:
+ handleNoCfCheckAttr(S, D, AL);
break;
- case AttributeList::AT_NoReturn:
- handleNoReturnAttr(S, D, Attr);
+ case ParsedAttr::AT_NoThrow:
+ handleSimpleAttribute<NoThrowAttr>(S, D, AL);
break;
- case AttributeList::AT_NoThrow:
- handleSimpleAttribute<NoThrowAttr>(S, D, Attr);
+ case ParsedAttr::AT_CUDAShared:
+ handleSharedAttr(S, D, AL);
break;
- case AttributeList::AT_CUDAShared:
- handleSharedAttr(S, D, Attr);
+ case ParsedAttr::AT_VecReturn:
+ handleVecReturnAttr(S, D, AL);
break;
- case AttributeList::AT_VecReturn:
- handleVecReturnAttr(S, D, Attr);
+ case ParsedAttr::AT_ObjCOwnership:
+ handleObjCOwnershipAttr(S, D, AL);
break;
- case AttributeList::AT_ObjCOwnership:
- handleObjCOwnershipAttr(S, D, Attr);
+ case ParsedAttr::AT_ObjCPreciseLifetime:
+ handleObjCPreciseLifetimeAttr(S, D, AL);
break;
- case AttributeList::AT_ObjCPreciseLifetime:
- handleObjCPreciseLifetimeAttr(S, D, Attr);
+ case ParsedAttr::AT_ObjCReturnsInnerPointer:
+ handleObjCReturnsInnerPointerAttr(S, D, AL);
break;
- case AttributeList::AT_ObjCReturnsInnerPointer:
- handleObjCReturnsInnerPointerAttr(S, D, Attr);
+ case ParsedAttr::AT_ObjCRequiresSuper:
+ handleObjCRequiresSuperAttr(S, D, AL);
break;
- case AttributeList::AT_ObjCRequiresSuper:
- handleObjCRequiresSuperAttr(S, D, Attr);
+ case ParsedAttr::AT_ObjCBridge:
+ handleObjCBridgeAttr(S, D, AL);
break;
- case AttributeList::AT_ObjCBridge:
- handleObjCBridgeAttr(S, scope, D, Attr);
+ case ParsedAttr::AT_ObjCBridgeMutable:
+ handleObjCBridgeMutableAttr(S, D, AL);
break;
- case AttributeList::AT_ObjCBridgeMutable:
- handleObjCBridgeMutableAttr(S, scope, D, Attr);
+ case ParsedAttr::AT_ObjCBridgeRelated:
+ handleObjCBridgeRelatedAttr(S, D, AL);
break;
- case AttributeList::AT_ObjCBridgeRelated:
- handleObjCBridgeRelatedAttr(S, scope, D, Attr);
+ case ParsedAttr::AT_ObjCDesignatedInitializer:
+ handleObjCDesignatedInitializer(S, D, AL);
break;
- case AttributeList::AT_ObjCDesignatedInitializer:
- handleObjCDesignatedInitializer(S, D, Attr);
+ case ParsedAttr::AT_ObjCRuntimeName:
+ handleObjCRuntimeName(S, D, AL);
break;
- case AttributeList::AT_ObjCRuntimeName:
- handleObjCRuntimeName(S, D, Attr);
+ case ParsedAttr::AT_ObjCRuntimeVisible:
+ handleSimpleAttribute<ObjCRuntimeVisibleAttr>(S, D, AL);
break;
- case AttributeList::AT_ObjCRuntimeVisible:
- handleSimpleAttribute<ObjCRuntimeVisibleAttr>(S, D, Attr);
+ case ParsedAttr::AT_ObjCBoxable:
+ handleObjCBoxable(S, D, AL);
break;
- case AttributeList::AT_ObjCBoxable:
- handleObjCBoxable(S, D, Attr);
+ case ParsedAttr::AT_CFAuditedTransfer:
+ handleSimpleAttributeWithExclusions<CFAuditedTransferAttr,
+ CFUnknownTransferAttr>(S, D, AL);
break;
- case AttributeList::AT_CFAuditedTransfer:
- handleCFAuditedTransferAttr(S, D, Attr);
+ case ParsedAttr::AT_CFUnknownTransfer:
+ handleSimpleAttributeWithExclusions<CFUnknownTransferAttr,
+ CFAuditedTransferAttr>(S, D, AL);
break;
- case AttributeList::AT_CFUnknownTransfer:
- handleCFUnknownTransferAttr(S, D, Attr);
+ case ParsedAttr::AT_CFConsumed:
+ case ParsedAttr::AT_NSConsumed:
+ handleNSConsumedAttr(S, D, AL);
break;
- case AttributeList::AT_CFConsumed:
- case AttributeList::AT_NSConsumed:
- handleNSConsumedAttr(S, D, Attr);
+ case ParsedAttr::AT_NSConsumesSelf:
+ handleSimpleAttribute<NSConsumesSelfAttr>(S, D, AL);
break;
- case AttributeList::AT_NSConsumesSelf:
- handleSimpleAttribute<NSConsumesSelfAttr>(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_NSReturnsAutoreleased:
- case AttributeList::AT_NSReturnsNotRetained:
- case AttributeList::AT_CFReturnsNotRetained:
- case AttributeList::AT_NSReturnsRetained:
- case AttributeList::AT_CFReturnsRetained:
- handleNSReturnsRetainedAttr(S, D, Attr);
+ case ParsedAttr::AT_WorkGroupSizeHint:
+ handleWorkGroupSize<WorkGroupSizeHintAttr>(S, D, AL);
break;
- case AttributeList::AT_WorkGroupSizeHint:
- handleWorkGroupSize<WorkGroupSizeHintAttr>(S, D, Attr);
+ case ParsedAttr::AT_ReqdWorkGroupSize:
+ handleWorkGroupSize<ReqdWorkGroupSizeAttr>(S, D, AL);
break;
- case AttributeList::AT_ReqdWorkGroupSize:
- handleWorkGroupSize<ReqdWorkGroupSizeAttr>(S, D, Attr);
+ case ParsedAttr::AT_OpenCLIntelReqdSubGroupSize:
+ handleSubGroupSize(S, D, AL);
break;
- case AttributeList::AT_OpenCLIntelReqdSubGroupSize:
- handleSubGroupSize(S, D, Attr);
+ case ParsedAttr::AT_VecTypeHint:
+ handleVecTypeHint(S, D, AL);
break;
- case AttributeList::AT_VecTypeHint:
- handleVecTypeHint(S, D, Attr);
+ case ParsedAttr::AT_RequireConstantInit:
+ handleSimpleAttribute<RequireConstantInitAttr>(S, D, AL);
break;
- case AttributeList::AT_RequireConstantInit:
- handleSimpleAttribute<RequireConstantInitAttr>(S, D, Attr);
+ case ParsedAttr::AT_InitPriority:
+ handleInitPriorityAttr(S, D, AL);
break;
- case AttributeList::AT_InitPriority:
- handleInitPriorityAttr(S, D, Attr);
+ case ParsedAttr::AT_Packed:
+ handlePackedAttr(S, D, AL);
break;
- case AttributeList::AT_Packed:
- handlePackedAttr(S, D, Attr);
+ case ParsedAttr::AT_Section:
+ handleSectionAttr(S, D, AL);
break;
- case AttributeList::AT_Section:
- handleSectionAttr(S, D, Attr);
+ case ParsedAttr::AT_CodeSeg:
+ handleCodeSegAttr(S, D, AL);
break;
- case AttributeList::AT_Target:
- handleTargetAttr(S, D, Attr);
+ case ParsedAttr::AT_Target:
+ handleTargetAttr(S, D, AL);
break;
- case AttributeList::AT_Unavailable:
- handleAttrWithMessage<UnavailableAttr>(S, D, Attr);
+ case ParsedAttr::AT_MinVectorWidth:
+ handleMinVectorWidthAttr(S, D, AL);
break;
- case AttributeList::AT_ArcWeakrefUnavailable:
- handleSimpleAttribute<ArcWeakrefUnavailableAttr>(S, D, Attr);
+ case ParsedAttr::AT_Unavailable:
+ handleAttrWithMessage<UnavailableAttr>(S, D, AL);
break;
- case AttributeList::AT_ObjCRootClass:
- handleSimpleAttribute<ObjCRootClassAttr>(S, D, Attr);
+ case ParsedAttr::AT_ArcWeakrefUnavailable:
+ handleSimpleAttribute<ArcWeakrefUnavailableAttr>(S, D, AL);
break;
- case AttributeList::AT_ObjCSubclassingRestricted:
- handleSimpleAttribute<ObjCSubclassingRestrictedAttr>(S, D, Attr);
+ case ParsedAttr::AT_ObjCRootClass:
+ handleSimpleAttribute<ObjCRootClassAttr>(S, D, AL);
break;
- case AttributeList::AT_ObjCExplicitProtocolImpl:
- handleObjCSuppresProtocolAttr(S, D, Attr);
+ case ParsedAttr::AT_ObjCSubclassingRestricted:
+ handleSimpleAttribute<ObjCSubclassingRestrictedAttr>(S, D, AL);
break;
- case AttributeList::AT_ObjCRequiresPropertyDefs:
- handleSimpleAttribute<ObjCRequiresPropertyDefsAttr>(S, D, Attr);
+ case ParsedAttr::AT_ObjCExplicitProtocolImpl:
+ handleObjCSuppresProtocolAttr(S, D, AL);
break;
- case AttributeList::AT_Unused:
- handleUnusedAttr(S, D, Attr);
+ case ParsedAttr::AT_ObjCRequiresPropertyDefs:
+ handleSimpleAttribute<ObjCRequiresPropertyDefsAttr>(S, D, AL);
break;
- case AttributeList::AT_ReturnsTwice:
- handleSimpleAttribute<ReturnsTwiceAttr>(S, D, Attr);
+ case ParsedAttr::AT_Unused:
+ handleUnusedAttr(S, D, AL);
break;
- case AttributeList::AT_NotTailCalled:
- handleNotTailCalledAttr(S, D, Attr);
+ case ParsedAttr::AT_ReturnsTwice:
+ handleSimpleAttribute<ReturnsTwiceAttr>(S, D, AL);
break;
- case AttributeList::AT_DisableTailCalls:
- handleDisableTailCallsAttr(S, D, Attr);
+ case ParsedAttr::AT_NotTailCalled:
+ handleSimpleAttributeWithExclusions<NotTailCalledAttr, AlwaysInlineAttr>(
+ S, D, AL);
break;
- case AttributeList::AT_Used:
- handleUsedAttr(S, D, Attr);
+ case ParsedAttr::AT_DisableTailCalls:
+ handleSimpleAttributeWithExclusions<DisableTailCallsAttr, NakedAttr>(S, D,
+ AL);
break;
- case AttributeList::AT_Visibility:
- handleVisibilityAttr(S, D, Attr, false);
+ case ParsedAttr::AT_Used:
+ handleSimpleAttribute<UsedAttr>(S, D, AL);
break;
- case AttributeList::AT_TypeVisibility:
- handleVisibilityAttr(S, D, Attr, true);
+ case ParsedAttr::AT_Visibility:
+ handleVisibilityAttr(S, D, AL, false);
break;
- case AttributeList::AT_WarnUnused:
- handleSimpleAttribute<WarnUnusedAttr>(S, D, Attr);
+ case ParsedAttr::AT_TypeVisibility:
+ handleVisibilityAttr(S, D, AL, true);
break;
- case AttributeList::AT_WarnUnusedResult:
- handleWarnUnusedResult(S, D, Attr);
+ case ParsedAttr::AT_WarnUnused:
+ handleSimpleAttribute<WarnUnusedAttr>(S, D, AL);
break;
- case AttributeList::AT_Weak:
- handleSimpleAttribute<WeakAttr>(S, D, Attr);
+ case ParsedAttr::AT_WarnUnusedResult:
+ handleWarnUnusedResult(S, D, AL);
break;
- case AttributeList::AT_WeakRef:
- handleWeakRefAttr(S, D, Attr);
+ case ParsedAttr::AT_Weak:
+ handleSimpleAttribute<WeakAttr>(S, D, AL);
break;
- case AttributeList::AT_WeakImport:
- handleWeakImportAttr(S, D, Attr);
+ case ParsedAttr::AT_WeakRef:
+ handleWeakRefAttr(S, D, AL);
break;
- case AttributeList::AT_TransparentUnion:
- handleTransparentUnionAttr(S, D, Attr);
+ case ParsedAttr::AT_WeakImport:
+ handleWeakImportAttr(S, D, AL);
break;
- case AttributeList::AT_ObjCException:
- handleSimpleAttribute<ObjCExceptionAttr>(S, D, Attr);
+ case ParsedAttr::AT_TransparentUnion:
+ handleTransparentUnionAttr(S, D, AL);
break;
- case AttributeList::AT_ObjCMethodFamily:
- handleObjCMethodFamilyAttr(S, D, Attr);
+ case ParsedAttr::AT_ObjCException:
+ handleSimpleAttribute<ObjCExceptionAttr>(S, D, AL);
break;
- case AttributeList::AT_ObjCNSObject:
- handleObjCNSObject(S, D, Attr);
+ case ParsedAttr::AT_ObjCMethodFamily:
+ handleObjCMethodFamilyAttr(S, D, AL);
break;
- case AttributeList::AT_ObjCIndependentClass:
- handleObjCIndependentClass(S, D, Attr);
+ case ParsedAttr::AT_ObjCNSObject:
+ handleObjCNSObject(S, D, AL);
break;
- case AttributeList::AT_Blocks:
- handleBlocksAttr(S, D, Attr);
+ case ParsedAttr::AT_ObjCIndependentClass:
+ handleObjCIndependentClass(S, D, AL);
break;
- case AttributeList::AT_Sentinel:
- handleSentinelAttr(S, D, Attr);
+ case ParsedAttr::AT_Blocks:
+ handleBlocksAttr(S, D, AL);
break;
- case AttributeList::AT_Const:
- handleSimpleAttribute<ConstAttr>(S, D, Attr);
+ case ParsedAttr::AT_Sentinel:
+ handleSentinelAttr(S, D, AL);
break;
- case AttributeList::AT_Pure:
- handleSimpleAttribute<PureAttr>(S, D, Attr);
+ case ParsedAttr::AT_Const:
+ handleSimpleAttribute<ConstAttr>(S, D, AL);
break;
- case AttributeList::AT_Cleanup:
- handleCleanupAttr(S, D, Attr);
+ case ParsedAttr::AT_Pure:
+ handleSimpleAttribute<PureAttr>(S, D, AL);
break;
- case AttributeList::AT_NoDebug:
- handleNoDebugAttr(S, D, Attr);
+ case ParsedAttr::AT_Cleanup:
+ handleCleanupAttr(S, D, AL);
break;
- case AttributeList::AT_NoDuplicate:
- handleSimpleAttribute<NoDuplicateAttr>(S, D, Attr);
+ case ParsedAttr::AT_NoDebug:
+ handleNoDebugAttr(S, D, AL);
break;
- case AttributeList::AT_Convergent:
- handleSimpleAttribute<ConvergentAttr>(S, D, Attr);
+ case ParsedAttr::AT_NoDuplicate:
+ handleSimpleAttribute<NoDuplicateAttr>(S, D, AL);
break;
- case AttributeList::AT_NoInline:
- handleSimpleAttribute<NoInlineAttr>(S, D, Attr);
+ case ParsedAttr::AT_Convergent:
+ handleSimpleAttribute<ConvergentAttr>(S, D, AL);
break;
- case AttributeList::AT_NoInstrumentFunction: // Interacts with -pg.
- handleSimpleAttribute<NoInstrumentFunctionAttr>(S, D, Attr);
+ case ParsedAttr::AT_NoInline:
+ handleSimpleAttribute<NoInlineAttr>(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_NoInstrumentFunction: // Interacts with -pg.
+ handleSimpleAttribute<NoInstrumentFunctionAttr>(S, D, AL);
break;
- case AttributeList::AT_Suppress:
- handleSuppressAttr(S, D, Attr);
+ case ParsedAttr::AT_NoStackProtector:
+ // Interacts with -fstack-protector options.
+ handleSimpleAttribute<NoStackProtectorAttr>(S, D, AL);
break;
- case AttributeList::AT_OpenCLKernel:
- handleSimpleAttribute<OpenCLKernelAttr>(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_OpenCLAccess:
- handleOpenCLAccessAttr(S, D, Attr);
+ case ParsedAttr::AT_Suppress:
+ handleSuppressAttr(S, D, AL);
break;
- case AttributeList::AT_OpenCLNoSVM:
- handleOpenCLNoSVMAttr(S, D, Attr);
+ case ParsedAttr::AT_OpenCLKernel:
+ handleSimpleAttribute<OpenCLKernelAttr>(S, D, AL);
break;
- case AttributeList::AT_SwiftContext:
- handleParameterABIAttr(S, D, Attr, ParameterABI::SwiftContext);
+ case ParsedAttr::AT_OpenCLAccess:
+ handleOpenCLAccessAttr(S, D, AL);
break;
- case AttributeList::AT_SwiftErrorResult:
- handleParameterABIAttr(S, D, Attr, ParameterABI::SwiftErrorResult);
+ case ParsedAttr::AT_OpenCLNoSVM:
+ handleOpenCLNoSVMAttr(S, D, AL);
break;
- case AttributeList::AT_SwiftIndirectResult:
- handleParameterABIAttr(S, D, Attr, ParameterABI::SwiftIndirectResult);
+ case ParsedAttr::AT_SwiftContext:
+ handleParameterABIAttr(S, D, AL, ParameterABI::SwiftContext);
break;
- case AttributeList::AT_InternalLinkage:
- handleInternalLinkageAttr(S, D, Attr);
+ case ParsedAttr::AT_SwiftErrorResult:
+ handleParameterABIAttr(S, D, AL, ParameterABI::SwiftErrorResult);
break;
- case AttributeList::AT_LTOVisibilityPublic:
- handleSimpleAttribute<LTOVisibilityPublicAttr>(S, D, Attr);
+ case ParsedAttr::AT_SwiftIndirectResult:
+ handleParameterABIAttr(S, D, AL, ParameterABI::SwiftIndirectResult);
+ break;
+ case ParsedAttr::AT_InternalLinkage:
+ handleInternalLinkageAttr(S, D, AL);
+ break;
+ 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 ParsedAttr::AT_LayoutVersion:
+ handleLayoutVersion(S, D, AL);
break;
- case AttributeList::AT_LayoutVersion:
- handleLayoutVersion(S, D, Attr);
+ case ParsedAttr::AT_TrivialABI:
+ handleSimpleAttribute<TrivialABIAttr>(S, D, AL);
break;
- case AttributeList::AT_MSNoVTable:
- handleSimpleAttribute<MSNoVTableAttr>(S, D, Attr);
+ case ParsedAttr::AT_MSNoVTable:
+ handleSimpleAttribute<MSNoVTableAttr>(S, D, AL);
break;
- case AttributeList::AT_MSStruct:
- handleSimpleAttribute<MSStructAttr>(S, D, Attr);
+ case ParsedAttr::AT_MSStruct:
+ handleSimpleAttribute<MSStructAttr>(S, D, AL);
break;
- case AttributeList::AT_Uuid:
- handleUuidAttr(S, D, Attr);
+ case ParsedAttr::AT_Uuid:
+ handleUuidAttr(S, D, AL);
break;
- case AttributeList::AT_MSInheritance:
- handleMSInheritanceAttr(S, D, Attr);
+ case ParsedAttr::AT_MSInheritance:
+ handleMSInheritanceAttr(S, D, AL);
break;
- case AttributeList::AT_SelectAny:
- handleSimpleAttribute<SelectAnyAttr>(S, D, Attr);
+ case ParsedAttr::AT_SelectAny:
+ handleSimpleAttribute<SelectAnyAttr>(S, D, AL);
break;
- case AttributeList::AT_Thread:
- handleDeclspecThreadAttr(S, D, Attr);
+ 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 +6607,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 +6632,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 +6717,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 +6729,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 +6749,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 +6758,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 +6800,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 +6824,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 +6845,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 +6860,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 +6869,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 +6880,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 +6945,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 +6957,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 +6977,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 +7000,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 +7087,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 +7155,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 +7185,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 +7230,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 +7271,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 +7283,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 +7294,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 +7332,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 +7396,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 +7459,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 +7468,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 +7544,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 +7715,7 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability(
SourceLocation StmtEndLoc =
SM.getExpansionRange(
(LastStmtOfUse ? LastStmtOfUse : StmtOfUse)->getLocEnd())
- .second;
+ .getEnd();
if (SM.getFileID(IfInsertionLoc) != SM.getFileID(StmtEndLoc))
return;
@@ -7681,11 +7754,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 +7813,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 +7843,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 +7851,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/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index aa26b37f444d..4cf3abdf5745 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/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.");
@@ -712,7 +710,7 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D,
Diag(Decomp.getLSquareLoc(),
!getLangOpts().CPlusPlus17
? diag::ext_decomp_decl
- : D.getContext() == Declarator::ConditionContext
+ : D.getContext() == DeclaratorContext::ConditionContext
? diag::ext_decomp_decl_cond
: diag::warn_cxx14_compat_decomp_decl)
<< Decomp.getSourceRange();
@@ -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);
+
+ 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);
- Record->setCanPassInRegisters(computeCanPassInRegisters(*this, Record));
+ // 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()) {
@@ -8986,15 +9354,15 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S,
}
switch (Name.getKind()) {
- case UnqualifiedId::IK_ImplicitSelfParam:
- case UnqualifiedId::IK_Identifier:
- case UnqualifiedId::IK_OperatorFunctionId:
- case UnqualifiedId::IK_LiteralOperatorId:
- case UnqualifiedId::IK_ConversionFunctionId:
+ case UnqualifiedIdKind::IK_ImplicitSelfParam:
+ case UnqualifiedIdKind::IK_Identifier:
+ case UnqualifiedIdKind::IK_OperatorFunctionId:
+ case UnqualifiedIdKind::IK_LiteralOperatorId:
+ case UnqualifiedIdKind::IK_ConversionFunctionId:
break;
- case UnqualifiedId::IK_ConstructorName:
- case UnqualifiedId::IK_ConstructorTemplateId:
+ case UnqualifiedIdKind::IK_ConstructorName:
+ case UnqualifiedIdKind::IK_ConstructorTemplateId:
// C++11 inheriting constructors.
Diag(Name.getLocStart(),
getLangOpts().CPlusPlus11 ?
@@ -9006,17 +9374,17 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S,
return nullptr;
- case UnqualifiedId::IK_DestructorName:
+ case UnqualifiedIdKind::IK_DestructorName:
Diag(Name.getLocStart(), diag::err_using_decl_destructor)
<< SS.getRange();
return nullptr;
- case UnqualifiedId::IK_TemplateId:
+ case UnqualifiedIdKind::IK_TemplateId:
Diag(Name.getLocStart(), diag::err_using_decl_template_id)
<< SourceRange(Name.TemplateId->LAngleLoc, Name.TemplateId->RAngleLoc);
return nullptr;
- case UnqualifiedId::IK_DeductionGuideName:
+ case UnqualifiedIdKind::IK_DeductionGuideName:
llvm_unreachable("cannot parse qualified deduction guide name");
}
@@ -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();
@@ -10040,7 +10414,7 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S,
Previous.clear();
}
- assert(Name.Kind == UnqualifiedId::IK_Identifier &&
+ assert(Name.Kind == UnqualifiedIdKind::IK_Identifier &&
"name in alias declaration must be an identifier");
TypeAliasDecl *NewTD = TypeAliasDecl::Create(Context, CurContext, UsingLoc,
Name.StartLocation,
@@ -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;
@@ -12215,30 +12607,27 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion(
SourceLocation CurrentLocation,
CXXConversionDecl *Conv) {
SynthesizedFunctionScope Scope(*this, Conv);
+ assert(!Conv->getReturnType()->isUndeducedType());
CXXRecordDecl *Lambda = Conv->getParent();
- CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator();
- // If we are defining a specialization of a conversion to function-ptr
- // cache the deduced template arguments for this specialization
- // so that we can use them to retrieve the corresponding call-operator
- // and static-invoker.
- const TemplateArgumentList *DeducedTemplateArgs = nullptr;
-
- // Retrieve the corresponding call-operator specialization.
- if (Lambda->isGenericLambda()) {
- assert(Conv->isFunctionTemplateSpecialization());
- FunctionTemplateDecl *CallOpTemplate =
- CallOp->getDescribedFunctionTemplate();
- DeducedTemplateArgs = Conv->getTemplateSpecializationArgs();
- void *InsertPos = nullptr;
- FunctionDecl *CallOpSpec = CallOpTemplate->findSpecialization(
- DeducedTemplateArgs->asArray(),
- InsertPos);
- assert(CallOpSpec &&
- "Conversion operator must have a corresponding call operator");
- CallOp = cast<CXXMethodDecl>(CallOpSpec);
+ FunctionDecl *CallOp = Lambda->getLambdaCallOperator();
+ FunctionDecl *Invoker = Lambda->getLambdaStaticInvoker();
+
+ if (auto *TemplateArgs = Conv->getTemplateSpecializationArgs()) {
+ CallOp = InstantiateFunctionDeclaration(
+ CallOp->getDescribedFunctionTemplate(), TemplateArgs, CurrentLocation);
+ if (!CallOp)
+ return;
+
+ Invoker = InstantiateFunctionDeclaration(
+ Invoker->getDescribedFunctionTemplate(), TemplateArgs, CurrentLocation);
+ if (!Invoker)
+ return;
}
+ if (CallOp->isInvalidDecl())
+ return;
+
// Mark the call operator referenced (and add to pending instantiations
// if necessary).
// For both the conversion and static-invoker template specializations
@@ -12246,39 +12635,24 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion(
// to the PendingInstantiations.
MarkFunctionReferenced(CurrentLocation, CallOp);
- // Retrieve the static invoker...
- CXXMethodDecl *Invoker = Lambda->getLambdaStaticInvoker();
- // ... and get the corresponding specialization for a generic lambda.
- if (Lambda->isGenericLambda()) {
- assert(DeducedTemplateArgs &&
- "Must have deduced template arguments from Conversion Operator");
- FunctionTemplateDecl *InvokeTemplate =
- Invoker->getDescribedFunctionTemplate();
- void *InsertPos = nullptr;
- FunctionDecl *InvokeSpec = InvokeTemplate->findSpecialization(
- DeducedTemplateArgs->asArray(),
- InsertPos);
- assert(InvokeSpec &&
- "Must have a corresponding static invoker specialization");
- Invoker = cast<CXXMethodDecl>(InvokeSpec);
- }
+ // Fill in the __invoke function with a dummy implementation. IR generation
+ // will fill in the actual details. Update its type in case it contained
+ // an 'auto'.
+ Invoker->markUsed(Context);
+ Invoker->setReferenced();
+ Invoker->setType(Conv->getReturnType()->getPointeeType());
+ Invoker->setBody(new (Context) CompoundStmt(Conv->getLocation()));
+
// Construct the body of the conversion function { return __invoke; }.
Expr *FunctionRef = BuildDeclRefExpr(Invoker, Invoker->getType(),
- VK_LValue, Conv->getLocation()).get();
+ VK_LValue, Conv->getLocation()).get();
assert(FunctionRef && "Can't refer to __invoke function?");
Stmt *Return = BuildReturnStmt(Conv->getLocation(), FunctionRef).get();
Conv->setBody(CompoundStmt::Create(Context, Return, Conv->getLocation(),
Conv->getLocation()));
-
Conv->markUsed(Context);
Conv->setReferenced();
- // Fill in the __invoke function with a dummy implementation. IR generation
- // will fill in the actual details.
- Invoker->markUsed(Context);
- Invoker->setReferenced();
- Invoker->setBody(new (Context) CompoundStmt(Conv->getLocation()));
-
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(Conv);
L->CompletedImplicitDefinition(Invoker);
@@ -12339,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()) {
@@ -12550,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.
///
@@ -12617,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,
@@ -12632,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(),
@@ -12657,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)
@@ -12966,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>()) {
@@ -13026,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(),
@@ -13136,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,
@@ -13404,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,
@@ -13481,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);
@@ -13597,7 +13993,6 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
return Friend;
}
-
/// Handle a friend type declaration. This works in tandem with
/// ActOnTag.
///
@@ -13625,7 +14020,7 @@ Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
// Try to convert the decl specifier to a type. This works for
// friend templates because ActOnTag never produces a ClassTemplateDecl
// for a TUK_Friend.
- Declarator TheDeclarator(DS, Declarator::MemberContext);
+ Declarator TheDeclarator(DS, DeclaratorContext::MemberContext);
TypeSourceInfo *TSI = GetTypeForDeclarator(TheDeclarator, S);
QualType T = TSI->getType();
if (TheDeclarator.isInvalidType())
@@ -13799,7 +14194,8 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
// elaborated-type-specifier, the lookup to determine whether
// the entity has been previously declared shall not consider
// any scopes outside the innermost enclosing namespace.
- bool isTemplateId = D.getName().getKind() == UnqualifiedId::IK_TemplateId;
+ bool isTemplateId =
+ D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId;
// Find the appropriate context according to the above.
DC = CurContext;
@@ -13910,24 +14306,24 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
if (!DC->isRecord()) {
int DiagArg = -1;
switch (D.getName().getKind()) {
- case UnqualifiedId::IK_ConstructorTemplateId:
- case UnqualifiedId::IK_ConstructorName:
+ case UnqualifiedIdKind::IK_ConstructorTemplateId:
+ case UnqualifiedIdKind::IK_ConstructorName:
DiagArg = 0;
break;
- case UnqualifiedId::IK_DestructorName:
+ case UnqualifiedIdKind::IK_DestructorName:
DiagArg = 1;
break;
- case UnqualifiedId::IK_ConversionFunctionId:
+ case UnqualifiedIdKind::IK_ConversionFunctionId:
DiagArg = 2;
break;
- case UnqualifiedId::IK_DeductionGuideName:
+ case UnqualifiedIdKind::IK_DeductionGuideName:
DiagArg = 3;
break;
- case UnqualifiedId::IK_Identifier:
- case UnqualifiedId::IK_ImplicitSelfParam:
- case UnqualifiedId::IK_LiteralOperatorId:
- case UnqualifiedId::IK_OperatorFunctionId:
- case UnqualifiedId::IK_TemplateId:
+ case UnqualifiedIdKind::IK_Identifier:
+ case UnqualifiedIdKind::IK_ImplicitSelfParam:
+ case UnqualifiedIdKind::IK_LiteralOperatorId:
+ case UnqualifiedIdKind::IK_OperatorFunctionId:
+ case UnqualifiedIdKind::IK_TemplateId:
break;
}
// This implies that it has to be an operator or function.
@@ -14168,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
@@ -14294,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.
///
@@ -14324,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))
@@ -14431,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) {
@@ -14543,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);
@@ -14666,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;
@@ -14730,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),
@@ -14738,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;
@@ -14815,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;
@@ -14912,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;
}
}
@@ -14981,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);
@@ -15048,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/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index abbdc9574b8c..e1b033ea8282 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -156,23 +156,23 @@ void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod,
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,7 +185,10 @@ 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";
}
@@ -199,7 +202,7 @@ void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod,
}
}
-/// \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();
@@ -263,12 +266,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();
@@ -338,6 +349,13 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
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();
@@ -930,16 +948,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.
@@ -1024,9 +1040,8 @@ ActOnStartClassInterface(Scope *S, SourceLocation AtInterfaceLoc,
IDecl->setInvalidDecl();
}
}
-
- if (AttrList)
- ProcessDeclAttributeList(TUScope, IDecl, AttrList);
+
+ ProcessDeclAttributeList(TUScope, IDecl, AttrList);
AddPragmaAttributes(TUScope, IDecl);
PushOnScopeChains(IDecl, TUScope);
@@ -1165,15 +1180,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 +1203,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) {
@@ -1211,9 +1227,8 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
PushOnScopeChains(PDecl, TUScope);
PDecl->startDefinition();
}
-
- if (AttrList)
- ProcessDeclAttributeList(TUScope, PDecl, AttrList);
+
+ ProcessDeclAttributeList(TUScope, PDecl, AttrList);
AddPragmaAttributes(TUScope, PDecl);
// Merge attributes from previous declarations.
@@ -1538,20 +1553,18 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers(
DS.SetRangeEnd(loc);
// Form the declarator.
- Declarator D(DS, Declarator::TypeNameContext);
+ Declarator D(DS, DeclaratorContext::TypeNameContext);
// If we have a typedef of an Objective-C class type that is missing a '*',
// 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,7 +1742,7 @@ 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;
@@ -1742,9 +1755,8 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc,
PushOnScopeChains(PDecl, TUScope);
CheckObjCDeclScope(PDecl);
-
- if (attrList)
- ProcessDeclAttributeList(TUScope, PDecl, attrList);
+
+ ProcessDeclAttributeList(TUScope, PDecl, attrList);
AddPragmaAttributes(TUScope, PDecl);
if (PrevDecl)
@@ -1756,17 +1768,13 @@ 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);
@@ -1832,6 +1840,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);
@@ -1843,10 +1857,6 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
NumProtoRefs, Context);
}
- if (AttrList)
- ProcessDeclAttributeList(TUScope, CDecl, AttrList);
- AddPragmaAttributes(TUScope, CDecl);
-
CheckObjCDeclScope(CDecl);
return ActOnObjCContainerStartDefinition(CDecl);
}
@@ -2162,17 +2172,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
@@ -2717,7 +2719,7 @@ static void CheckProtocolMethodDefs(Sema &S,
// 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 =
@@ -3345,7 +3347,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");
@@ -3427,7 +3429,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
@@ -3859,9 +3861,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);
@@ -4084,7 +4086,7 @@ 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
@@ -4130,7 +4132,7 @@ class OverrideSearch {
public:
Sema &S;
ObjCMethodDecl *Method;
- llvm::SmallPtrSet<ObjCMethodDecl*, 4> Overridden;
+ llvm::SmallSetVector<ObjCMethodDecl*, 4> Overridden;
bool Recursive;
public:
@@ -4167,7 +4169,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(); }
@@ -4335,10 +4337,6 @@ 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.
@@ -4502,25 +4500,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;
@@ -4621,8 +4615,7 @@ Decl *Sema::ActOnMethodDeclaration(
ObjCMethod->setObjCDeclQualifier(
CvtQTToAstBitMask(ReturnQT.getObjCDeclQualifier()));
- if (AttrList)
- ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList);
+ ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList);
AddPragmaAttributes(TUScope, ObjCMethod);
// Add the method now.
@@ -4726,6 +4719,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;
@@ -4769,7 +4773,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,13 +4788,13 @@ 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,
@@ -4811,12 +4815,17 @@ VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType T,
// 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,
diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp
index 67d1b02d1fca..df5bc9b82b96 100644
--- a/lib/Sema/SemaExceptionSpec.cpp
+++ b/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;
@@ -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/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 4746355e9800..60abd718e228 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/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.
@@ -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) {
@@ -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)
@@ -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,
@@ -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,
@@ -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))
@@ -1711,7 +1717,7 @@ Sema::DecomposeUnqualifiedId(const UnqualifiedId &Id,
TemplateArgumentListInfo &Buffer,
DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *&TemplateArgs) {
- if (Id.getKind() == UnqualifiedId::IK_TemplateId) {
+ if (Id.getKind() == UnqualifiedIdKind::IK_TemplateId) {
Buffer.setLAngleLoc(Id.TemplateId->LAngleLoc);
Buffer.setRAngleLoc(Id.TemplateId->RAngleLoc);
@@ -2070,19 +2076,21 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
IsAddressOfOperand, TemplateArgs);
// Perform the required lookup.
- LookupResult R(*this, NameInfo,
- (Id.getKind() == UnqualifiedId::IK_ImplicitSelfParam)
- ? LookupObjCImplicitSelfParam : LookupOrdinaryName);
- if (TemplateArgs) {
+ LookupResult R(*this, NameInfo,
+ (Id.getKind() == UnqualifiedIdKind::IK_ImplicitSelfParam)
+ ? LookupObjCImplicitSelfParam
+ : LookupOrdinaryName);
+ 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,
@@ -2148,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)) {
@@ -2243,7 +2254,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
// In C++1y, if this is a variable template id, then check it
// in BuildTemplateIdExpr().
// The single lookup result must be a variable template declaration.
- if (Id.getKind() == UnqualifiedId::IK_TemplateId && Id.TemplateId &&
+ if (Id.getKind() == UnqualifiedIdKind::IK_TemplateId && Id.TemplateId &&
Id.TemplateId->Kind == TNK_Var_template) {
assert(R.getAsSingle<VarTemplateDecl>() &&
"There should only be one declaration found.");
@@ -2401,7 +2412,7 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
IdentifierInfo &II = Context.Idents.get("self");
UnqualifiedId SelfName;
SelfName.setIdentifier(&II, SourceLocation());
- SelfName.setKind(UnqualifiedId::IK_ImplicitSelfParam);
+ SelfName.setKind(UnqualifiedIdKind::IK_ImplicitSelfParam);
CXXScopeSpec SelfScopeSpec;
SourceLocation TemplateKWLoc;
ExprResult SelfExpr = ActOnIdExpression(S, SelfScopeSpec, TemplateKWLoc,
@@ -2425,8 +2436,9 @@ 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())
@@ -2470,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:
///
@@ -2716,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);
@@ -2729,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();
@@ -2752,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,
@@ -2768,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();
}
@@ -3033,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);
@@ -3043,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,
@@ -3063,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;
}
@@ -3085,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())
@@ -3280,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);
@@ -3313,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"))
@@ -3553,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) {
@@ -3571,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
@@ -3655,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
@@ -3909,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,
@@ -3953,7 +4023,7 @@ 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,
@@ -4071,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,
@@ -4327,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>()) {
@@ -4391,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
@@ -4830,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)
@@ -5495,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())
@@ -5505,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());
}
}
@@ -5704,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);
@@ -6238,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,
@@ -6279,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();
@@ -6298,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();
@@ -6315,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) {
@@ -6328,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,
@@ -6462,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,
@@ -6487,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,
@@ -6526,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,
@@ -6546,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.
@@ -6601,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
@@ -6646,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
@@ -6661,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
@@ -6691,7 +6780,7 @@ 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
@@ -6726,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();
@@ -7049,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)) {
@@ -7096,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;
}
@@ -7847,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,
@@ -8014,7 +8109,7 @@ 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;
}
}
@@ -8053,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();
}
@@ -8215,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;
@@ -8593,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
@@ -8603,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
@@ -8612,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.
@@ -8627,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());
@@ -8643,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());
@@ -8655,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,
@@ -8671,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
@@ -8702,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
@@ -8804,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;
@@ -8855,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());
@@ -9153,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) {
@@ -9299,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) {
@@ -9338,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) {
@@ -9348,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) {
@@ -9586,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;
+ }
+
+ // 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();
- if (isa<CastExpr>(LHSStripped))
- LHSStripped = LHSStripped->IgnoreParenCasts();
- if (isa<CastExpr>(RHSStripped))
- RHSStripped = RHSStripped->IgnoreParenCasts();
+ assert(!Type.isNull() && "composite type for <=> has not been set");
- // 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;
+ 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");
+ }();
- if (literalString) {
- DiagRuntimeBehavior(Loc, nullptr,
- PDiag(diag::warn_stringcompare)
- << isa<ObjCEncodeExpr>(literalStringStripped)
- << literalString->getSourceRange());
- }
- }
+ 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());
- LHSType = LHS.get()->getType();
- RHSType = RHS.get()->getType();
+ checkEnumComparison(S, Loc, LHS.get(), RHS.get());
+
+ 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 =
@@ -9724,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)
@@ -9751,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
@@ -9824,7 +10218,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
else
RHS = ImpCastExprToType(RHS.get(), LHSType, Kind);
}
- return ResultTy;
+ return computeResultTy();
}
if (getLangOpts().CPlusPlus) {
@@ -9834,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();
}
}
@@ -9847,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 &&
@@ -9875,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();
}
}
}
@@ -9888,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.
@@ -9912,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.
@@ -9936,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() ||
@@ -9969,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()) {
@@ -9983,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()) ||
@@ -10023,30 +10423,30 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
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();
}
}
@@ -10100,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,
@@ -10120,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());
}
@@ -10417,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;
}
@@ -10659,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
@@ -11045,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,
@@ -11418,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();
@@ -11446,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
@@ -11583,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);
@@ -11641,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());
@@ -11677,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);
@@ -11739,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);
@@ -11857,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
@@ -11872,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;
@@ -11880,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;
@@ -11888,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)) {
@@ -11910,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)) {
@@ -11925,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,
@@ -12038,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
@@ -12160,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) {
@@ -12167,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();
@@ -12192,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);
@@ -12205,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
@@ -12241,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.
@@ -12337,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 "
@@ -12355,17 +12806,17 @@ 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;
@@ -12548,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())
@@ -12783,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();
@@ -12834,7 +13282,7 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
Scope *CurScope) {
assert(ParamInfo.getIdentifier() == nullptr &&
"block-id should have no identifier!");
- assert(ParamInfo.getContext() == Declarator::BlockLiteralContext);
+ assert(ParamInfo.getContext() == DeclaratorContext::BlockLiteralContext);
BlockScopeInfo *CurBlock = getCurBlock();
TypeSourceInfo *Sig = GetTypeForDeclarator(ParamInfo, CurScope);
@@ -12989,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(),
@@ -13069,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;
}
}
@@ -13335,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;
@@ -13459,7 +13906,7 @@ 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,
@@ -13700,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() {
@@ -13723,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.
@@ -13805,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;
@@ -13855,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) {
@@ -14088,7 +14535,7 @@ static bool isVariableAlreadyCapturedInScopeInfo(CapturingScopeInfo *CSI, VarDec
// 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) &&
@@ -14241,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);
}
}
@@ -14272,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;
@@ -14332,7 +14755,7 @@ 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,
@@ -14345,14 +14768,14 @@ static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI,
bool ByRef = true;
// Using an LValue reference type is consistent with Lambdas (see below).
if (S.getLangOpts().OpenMP && RSI->CapRegionKind == CR_OpenMP) {
- if (S.IsOpenMPCapturedDecl(Var)) {
+ if (S.isOpenMPCapturedDecl(Var)) {
bool HasConst = DeclRefType.isConstQualified();
DeclRefType = DeclRefType.getUnqualifiedType();
// Don't lose diagnostics about assignments to const.
if (HasConst)
DeclRefType.addConst();
}
- ByRef = S.IsOpenMPCapturedByRef(Var, RSI->OpenMPLevel);
+ ByRef = S.isOpenMPCapturedByRef(Var, RSI->OpenMPLevel);
}
if (ByRef)
@@ -14392,7 +14815,7 @@ static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI,
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,
QualType FieldType, QualType DeclRefType,
@@ -14410,7 +14833,7 @@ 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,
@@ -14544,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();
@@ -14909,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,
@@ -14925,7 +15348,8 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
if (RefersToEnclosingScope) {
LambdaScopeInfo *const LSI =
SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true);
- if (LSI && !LSI->CallOperator->Encloses(Var->getDeclContext())) {
+ if (LSI && (!LSI->CallOperator ||
+ !LSI->CallOperator->Encloses(Var->getDeclContext()))) {
// If a variable could potentially be odr-used, defer marking it so
// until we finish analyzing the full expression for any
// lvalue-to-rvalue
@@ -14943,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) {
@@ -14984,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
@@ -14997,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
@@ -15016,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.
@@ -15079,7 +15503,7 @@ 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;
@@ -15152,7 +15576,7 @@ 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
@@ -15162,7 +15586,7 @@ void Sema::MarkDeclarationsReferencedInExpr(Expr *E,
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
@@ -15228,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;
}
@@ -15319,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.
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index cff9fbbf491b..a1168fa34d56 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/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,50 @@ 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 && CurClass->isInvalidDecl())
+ return ParsedType();
+ assert(InjectedClassName && "couldn't find injected class name");
+
+ 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,
@@ -356,7 +400,7 @@ ParsedType Sema::getDestructorTypeForDecltype(const DeclSpec &DS,
bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS,
const UnqualifiedId &Name) {
- assert(Name.getKind() == UnqualifiedId::IK_LiteralOperatorId);
+ assert(Name.getKind() == UnqualifiedIdKind::IK_LiteralOperatorId);
if (!SS.isValid())
return false;
@@ -383,7 +427,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 +452,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 +524,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 +610,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 +630,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 +745,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 +782,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 +1168,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 +1196,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 +1251,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 +1299,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 +1317,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 +1328,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 +1382,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 +1431,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 +1497,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 +1610,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 +1660,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);
@@ -1728,7 +1795,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 +1864,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 +1893,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 +2022,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 +2162,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 +2183,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 +2201,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 +2250,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 +2267,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 +2382,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 +2393,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 +2412,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 +2440,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 +2450,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 +2640,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 +2931,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 +2954,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 +2965,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 +2978,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 +2992,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 +3000,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 +3009,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 +3278,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 +3354,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 +3414,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 +3592,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 +3762,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 +3825,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 +4294,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 +4451,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 +4699,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 +4792,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 +4831,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 +4869,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 +4953,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 +5465,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 +5504,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 +5529,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 +5598,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 +5660,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 +5676,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 +5980,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 +6009,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 +6038,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 +6428,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 +6511,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 +6555,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 +6809,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,
@@ -6716,11 +6953,11 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
SourceLocation CCLoc,
SourceLocation TildeLoc,
UnqualifiedId &SecondTypeName) {
- assert((FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId ||
- FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) &&
+ assert((FirstTypeName.getKind() == UnqualifiedIdKind::IK_TemplateId ||
+ FirstTypeName.getKind() == UnqualifiedIdKind::IK_Identifier) &&
"Invalid first type name in pseudo-destructor");
- assert((SecondTypeName.getKind() == UnqualifiedId::IK_TemplateId ||
- SecondTypeName.getKind() == UnqualifiedId::IK_Identifier) &&
+ assert((SecondTypeName.getKind() == UnqualifiedIdKind::IK_TemplateId ||
+ SecondTypeName.getKind() == UnqualifiedIdKind::IK_Identifier) &&
"Invalid second type name in pseudo-destructor");
QualType ObjectType;
@@ -6742,7 +6979,7 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
QualType DestructedType;
TypeSourceInfo *DestructedTypeInfo = nullptr;
PseudoDestructorTypeStorage Destructed;
- if (SecondTypeName.getKind() == UnqualifiedId::IK_Identifier) {
+ if (SecondTypeName.getKind() == UnqualifiedIdKind::IK_Identifier) {
ParsedType T = getTypeName(*SecondTypeName.Identifier,
SecondTypeName.StartLocation,
S, &SS, true, false, ObjectTypePtrForLookup,
@@ -6800,9 +7037,9 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
// Convert the name of the scope type (the type prior to '::') into a type.
TypeSourceInfo *ScopeTypeInfo = nullptr;
QualType ScopeType;
- if (FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId ||
+ if (FirstTypeName.getKind() == UnqualifiedIdKind::IK_TemplateId ||
FirstTypeName.Identifier) {
- if (FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) {
+ if (FirstTypeName.getKind() == UnqualifiedIdKind::IK_Identifier) {
ParsedType T = getTypeName(*FirstTypeName.Identifier,
FirstTypeName.StartLocation,
S, &SS, true, false, ObjectTypePtrForLookup,
@@ -6877,10 +7114,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 +7141,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 +7361,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 +7384,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 +7412,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 +7448,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 +7541,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 +7567,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 +7738,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/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp
index dd516ea3b428..3a8fee862c91 100644
--- a/lib/Sema/SemaExprMember.cpp
+++ b/lib/Sema/SemaExprMember.cpp
@@ -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,16 +804,13 @@ 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,
@@ -824,68 +823,37 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
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.
@@ -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())
@@ -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;
}
@@ -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)
@@ -1707,7 +1677,7 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base,
// Warn about the explicit constructor calls Microsoft extension.
if (getLangOpts().MicrosoftExt &&
- Id.getKind() == UnqualifiedId::IK_ConstructorName)
+ Id.getKind() == UnqualifiedIdKind::IK_ConstructorName)
Diag(Id.getSourceRange().getBegin(),
diag::ext_ms_explicit_constructor_call);
@@ -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());
}
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index cd0c2c47ae4c..bf0ffeba06b2 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -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,
@@ -379,7 +379,7 @@ ExprResult Sema::ActOnObjCBoolLiteral(SourceLocation AtLoc,
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,
QualType 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))
@@ -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) &&
@@ -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,
@@ -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.
@@ -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
@@ -2432,7 +2443,7 @@ 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
@@ -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();
}
@@ -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.
@@ -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)
@@ -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())) {
@@ -2822,7 +2834,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
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()) {
@@ -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).
@@ -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;
@@ -3644,11 +3657,13 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
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
@@ -3690,7 +3705,7 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
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
@@ -3727,7 +3742,7 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
}
S.Diag(loc, diag::err_arc_mismatched_cast)
- << (CCK != Sema::CCK_ImplicitConversion)
+ << !convKindForDiag
<< srcKind << castExprType << castType
<< castRange << castExpr->getSourceRange();
}
@@ -4180,7 +4195,7 @@ Sema::CheckObjCConversion(SourceRange castRange, QualType castType,
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
@@ -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());
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 011051da58e5..3ee5ec4a4929 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/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;
@@ -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.,
@@ -352,6 +364,7 @@ class InitListChecker {
bool FillWithNoInit = false);
void FillInEmptyInitializations(const InitializedEntity &Entity,
InitListExpr *ILE, bool &RequiresSecondPass,
+ InitListExpr *OuterILE, unsigned OuterIndex,
bool FillWithNoInit = false);
bool CheckFlexibleArrayInit(const InitializedEntity &Entity,
Expr *InitExpr, FieldDecl *Field,
@@ -365,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; }
};
@@ -517,12 +530,13 @@ void InitListChecker::FillInEmptyInitForBase(
ILE->setInit(Init, BaseInit.getAs<Expr>());
} else if (InitListExpr *InnerILE =
dyn_cast<InitListExpr>(ILE->getInit(Init))) {
- FillInEmptyInitializations(BaseEntity, InnerILE,
- RequiresSecondPass, FillWithNoInit);
+ FillInEmptyInitializations(BaseEntity, InnerILE, RequiresSecondPass,
+ ILE, Init, FillWithNoInit);
} else if (DesignatedInitUpdateExpr *InnerDIUE =
dyn_cast<DesignatedInitUpdateExpr>(ILE->getInit(Init))) {
FillInEmptyInitializations(BaseEntity, InnerDIUE->getUpdater(),
- RequiresSecondPass, /*FillWithNoInit =*/true);
+ RequiresSecondPass, ILE, Init,
+ /*FillWithNoInit =*/true);
}
}
@@ -559,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 {
@@ -605,24 +620,43 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
} else if (InitListExpr *InnerILE
= dyn_cast<InitListExpr>(ILE->getInit(Init)))
FillInEmptyInitializations(MemberEntity, InnerILE,
- RequiresSecondPass, FillWithNoInit);
+ RequiresSecondPass, ILE, Init, FillWithNoInit);
else if (DesignatedInitUpdateExpr *InnerDIUE
= dyn_cast<DesignatedInitUpdateExpr>(ILE->getInit(Init)))
FillInEmptyInitializations(MemberEntity, InnerDIUE->getUpdater(),
- RequiresSecondPass, /*FillWithNoInit =*/ true);
+ RequiresSecondPass, ILE, Init,
+ /*FillWithNoInit =*/true);
}
/// Recursively replaces NULL values within the given initializer list
/// with expressions that perform value-initialization of the
-/// appropriate type.
+/// appropriate type, and finish off the InitListExpr formation.
void
InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity,
InitListExpr *ILE,
bool &RequiresSecondPass,
+ InitListExpr *OuterILE,
+ unsigned OuterIndex,
bool FillWithNoInit) {
assert((ILE->getType() != SemaRef.Context.VoidTy) &&
"Should not have void type");
+ // If this is a nested initializer list, we might have changed its contents
+ // (and therefore some of its properties, such as instantiation-dependence)
+ // while filling it in. Inform the outer initializer list so that its state
+ // can be updated to match.
+ // FIXME: We should fully build the inner initializers before constructing
+ // the outer InitListExpr instead of mutating AST nodes after they have
+ // been used as subexpressions of other nodes.
+ struct UpdateOuterILEWithUpdatedInit {
+ InitListExpr *Outer;
+ unsigned OuterIndex;
+ ~UpdateOuterILEWithUpdatedInit() {
+ if (Outer)
+ Outer->setInit(OuterIndex, Outer->getInit(OuterIndex));
+ }
+ } UpdateOuterRAII = {OuterILE, OuterIndex};
+
// A transparent ILE is not performing aggregate initialization and should
// not be filled in.
if (ILE->isTransparent())
@@ -719,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());
@@ -769,11 +806,12 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity,
} else if (InitListExpr *InnerILE
= dyn_cast_or_null<InitListExpr>(InitExpr))
FillInEmptyInitializations(ElementEntity, InnerILE, RequiresSecondPass,
- FillWithNoInit);
+ ILE, Init, FillWithNoInit);
else if (DesignatedInitUpdateExpr *InnerDIUE
= dyn_cast_or_null<DesignatedInitUpdateExpr>(InitExpr))
FillInEmptyInitializations(ElementEntity, InnerDIUE->getUpdater(),
- RequiresSecondPass, /*FillWithNoInit =*/ true);
+ RequiresSecondPass, ILE, Init,
+ /*FillWithNoInit =*/true);
}
}
@@ -795,10 +833,11 @@ InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity,
if (!hadError && !VerifyOnly) {
bool RequiresSecondPass = false;
- FillInEmptyInitializations(Entity, FullyStructuredList, RequiresSecondPass);
+ FillInEmptyInitializations(Entity, FullyStructuredList, RequiresSecondPass,
+ /*OuterILE=*/nullptr, /*OuterIndex=*/0);
if (RequiresSecondPass && !hadError)
FillInEmptyInitializations(Entity, FullyStructuredList,
- RequiresSecondPass);
+ RequiresSecondPass, nullptr, 0);
}
}
@@ -982,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");
}
@@ -1162,10 +1202,12 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
if (!hadError && !VerifyOnly) {
bool RequiresSecondPass = false;
FillInEmptyInitializations(Entity, InnerStructuredList,
- RequiresSecondPass);
+ RequiresSecondPass, StructuredList,
+ StructuredIndex);
if (RequiresSecondPass && !hadError)
FillInEmptyInitializations(Entity, InnerStructuredList,
- RequiresSecondPass);
+ RequiresSecondPass, StructuredList,
+ StructuredIndex);
}
++StructuredIndex;
++Index;
@@ -1989,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.
///
@@ -2053,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
@@ -2960,6 +3002,7 @@ DeclarationName InitializedEntity::getName() const {
return DeclarationName(Capture.VarID);
case EK_Result:
+ case EK_StmtExprResult:
case EK_Exception:
case EK_New:
case EK_Temporary:
@@ -2990,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:
@@ -3015,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:
@@ -3050,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;
@@ -3160,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:
@@ -3492,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;
@@ -3507,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
@@ -3533,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)
@@ -3668,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.
@@ -3885,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,
@@ -3959,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,
@@ -4154,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,
@@ -4183,9 +4232,11 @@ static OverloadingResult TryRefInitWithConversionFunction(
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;
@@ -4201,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,
@@ -4344,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,
@@ -4371,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,
@@ -4637,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,
@@ -4647,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,
@@ -4725,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,
@@ -4764,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,
@@ -5043,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) {
@@ -5337,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;
}
@@ -5582,6 +5639,7 @@ getAssignmentAction(const InitializedEntity &Entity, bool Diagnose = false) {
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:
@@ -5604,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:
@@ -5635,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:
@@ -5666,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:
@@ -5702,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.
///
@@ -5867,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,
@@ -6031,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())) {
@@ -6068,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.
@@ -6109,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:
@@ -6200,56 +6264,122 @@ 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,
+ } Kind;
+ Expr *E;
+ Decl *D = nullptr;
+ IndirectLocalPathEntry() {}
+ IndirectLocalPathEntry(EntryKind K, Expr *E) : Kind(K), E(E) {}
+ IndirectLocalPathEntry(EntryKind K, Expr *E, 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);
+
+/// 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
@@ -6263,43 +6393,134 @@ 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);
+ }
+
+ 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;
+ }
+
+ case Stmt::OMPArraySectionExprClass: {
+ visitLocalsRetainedByInitializer(
+ Path, cast<OMPArraySectionExpr>(Init)->getBase(), Visit, true);
+ break;
+ }
+
+ 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;
+ }
+
+ // FIXME: Visit the left-hand side of an -> or ->*.
+
+ default:
+ break;
+ }
}
-/// Update a prvalue expression that is going to be materialized as a
-/// lifetime-extended temporary.
-static void performLifetimeExtension(Expr *Init,
- const InitializedEntity *ExtendingEntity) {
+/// 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);
+
+ // 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();
- if (CXXStdInitializerListExpr *ILE =
- dyn_cast<CXXStdInitializerListExpr>(Init)) {
- performReferenceExtension(ILE->getSubExpr(), ExtendingEntity);
- return;
- }
+ // 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;
}
@@ -6311,7 +6532,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()) {
@@ -6321,51 +6543,365 @@ 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;
}
-}
-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;
+ // Step over value-preserving rvalue casts.
+ while (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()) {
+ 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_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;
}
- bool IsSubobjectMember = false;
- for (const InitializedEntity *Ent = Entity.getParent(); Ent;
- Ent = Ent->getParent()) {
- if (Ent->getKind() != InitializedEntity::EK_Base) {
- IsSubobjectMember = true;
+ Init = CE->getSubExpr();
+ }
+
+ Init = Init->IgnoreParens();
+ 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;
+ }
+}
+
+/// 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:
+ // 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()
+ << Init->isGLValue() << DiagRange;
+ }
+ break;
+ }
+
+ 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::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->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,
@@ -6402,13 +6938,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();
@@ -6465,7 +6995,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())
@@ -6594,7 +7124,7 @@ 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);
}
@@ -6633,20 +7163,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,
@@ -6797,16 +7313,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;
@@ -6821,23 +7327,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;
}
@@ -6910,16 +7406,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())
@@ -7114,14 +7600,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;
}
@@ -7277,15 +7766,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);
@@ -7407,6 +7887,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())
@@ -7524,6 +8009,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:
@@ -7566,6 +8064,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(),
@@ -7573,7 +8082,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;
@@ -7584,7 +8093,7 @@ bool InitializationSequence::Diagnose(Sema &S,
case FK_AddressOfOverloadFailed: {
DeclAccessPair Found;
- S.ResolveAddressOfOverloadedFunction(Args[0],
+ S.ResolveAddressOfOverloadedFunction(OnlyArg,
DestType.getNonReferenceType(),
true,
Found);
@@ -7592,9 +8101,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;
}
@@ -7604,11 +8113,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);
@@ -7618,10 +8127,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);
@@ -7629,7 +8138,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
@@ -7665,7 +8174,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;
@@ -7690,12 +8199,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();
@@ -7711,18 +8220,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);
@@ -7975,6 +8484,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;
@@ -8265,6 +8782,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,
@@ -8298,35 +8820,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;
}
@@ -8599,6 +9120,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/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp
index cbfc330ca60b..a42b2e827e9b 100644
--- a/lib/Sema/SemaLambda.cpp
+++ b/lib/Sema/SemaLambda.cpp
@@ -24,7 +24,7 @@
using namespace clang;
using namespace sema;
-/// \brief Examines the FunctionScopeInfo stack to determine the nearest
+/// 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
@@ -135,7 +135,7 @@ getStackIndexOfNearestEnclosingCaptureReadyLambda(
return NoLambdaIsCaptureReady;
}
-/// \brief Examines the FunctionScopeInfo stack to determine the nearest
+/// 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
@@ -263,7 +263,7 @@ CXXRecordDecl *Sema::createLambdaClosureType(SourceRange IntroducerRange,
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()) {
@@ -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.
@@ -904,6 +909,14 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
ParamInfo.getDeclSpec().isConstexprSpecified());
if (ExplicitParams)
CheckCXXDefaultArguments(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);
@@ -984,6 +997,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
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;
}
@@ -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,13 +1178,31 @@ 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();
}
-/// \brief Add a lambda's conversion to function pointer, as described in
+QualType Sema::getLambdaConversionFunctionResultType(
+ const FunctionProtoType *CallOpProto) {
+ // 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();
+ 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 &&
+ "Lambda's call operator should not have a reference qualifier");
+ return Context.getFunctionType(CallOpProto->getReturnType(),
+ CallOpProto->getParamTypes(), InvokerExtInfo);
+}
+
+/// Add a lambda's conversion to function pointer, as described in
/// C++11 [expr.prim.lambda]p6.
static void addFunctionPointerConversion(Sema &S,
SourceRange IntroducerRange,
@@ -1182,25 +1217,9 @@ static void addFunctionPointerConversion(Sema &S,
return;
// Add the conversion to function pointer.
- const FunctionProtoType *CallOpProto =
- CallOperator->getType()->getAs<FunctionProtoType>();
- const FunctionProtoType::ExtProtoInfo CallOpExtInfo =
- CallOpProto->getExtProtoInfo();
- QualType PtrToFunctionTy;
- QualType InvokerFunctionTy;
- {
- FunctionProtoType::ExtProtoInfo InvokerExtInfo = CallOpExtInfo;
- CallingConv CC = S.Context.getDefaultCallingConvention(
- CallOpProto->isVariadic(), /*IsCXXMethod=*/false);
- InvokerExtInfo.ExtInfo = InvokerExtInfo.ExtInfo.withCallingConv(CC);
- InvokerExtInfo.TypeQuals = 0;
- assert(InvokerExtInfo.RefQualifier == RQ_None &&
- "Lambda's call operator should not have a reference qualifier");
- InvokerFunctionTy =
- S.Context.getFunctionType(CallOpProto->getReturnType(),
- CallOpProto->getParamTypes(), InvokerExtInfo);
- PtrToFunctionTy = S.Context.getPointerType(InvokerFunctionTy);
- }
+ QualType InvokerFunctionTy = S.getLambdaConversionFunctionResultType(
+ CallOperator->getType()->castAs<FunctionProtoType>());
+ QualType PtrToFunctionTy = S.Context.getPointerType(InvokerFunctionTy);
// Create the type of the conversion function.
FunctionProtoType::ExtProtoInfo ConvExtInfo(
@@ -1352,24 +1371,13 @@ static void addFunctionPointerConversion(Sema &S,
Class->addDecl(Invoke);
}
-/// \brief Add a lambda's conversion to block pointer.
+/// Add a lambda's conversion to block pointer.
static void addBlockPointerConversion(Sema &S,
SourceRange IntroducerRange,
CXXRecordDecl *Class,
CXXMethodDecl *CallOperator) {
- const FunctionProtoType *Proto =
- CallOperator->getType()->getAs<FunctionProtoType>();
-
- // The function type inside the block 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.
- FunctionProtoType::ExtProtoInfo BlockEPI = Proto->getExtProtoInfo();
- BlockEPI.ExtInfo =
- BlockEPI.ExtInfo.withCallingConv(S.Context.getDefaultCallingConvention(
- Proto->isVariadic(), /*IsCXXMethod=*/false));
- BlockEPI.TypeQuals = 0;
- QualType FunctionTy = S.Context.getFunctionType(
- Proto->getReturnType(), Proto->getParamTypes(), BlockEPI);
+ QualType FunctionTy = S.getLambdaConversionFunctionResultType(
+ CallOperator->getType()->castAs<FunctionProtoType>());
QualType BlockPtrTy = S.Context.getBlockPointerType(FunctionTy);
FunctionProtoType::ExtProtoInfo ConversionEPI(
@@ -1397,8 +1405,9 @@ static void addBlockPointerConversion(Sema &S,
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();
@@ -1452,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))
@@ -1477,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())
@@ -1490,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,
@@ -1531,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));
@@ -1596,7 +1650,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
// Finalize the lambda class.
SmallVector<Decl*, 4> Fields(Class->fields());
ActOnFields(nullptr, Class->getLocation(), Class, Fields, SourceLocation(),
- SourceLocation(), nullptr);
+ SourceLocation(), ParsedAttributesView());
CheckCompletedCXXClass(Class);
}
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index a9db973851df..2732112c00b6 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/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
@@ -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
@@ -1841,7 +1850,7 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
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.,
@@ -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
@@ -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,
@@ -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/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp
index ea5b1da46f32..2983ec51f49e 100644
--- a/lib/Sema/SemaObjCProperty.cpp
+++ b/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,
@@ -618,7 +618,7 @@ 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,
@@ -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)");
@@ -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,
diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp
index 24b58e8fd12b..e1a4c420d402 100644
--- a/lib/Sema/SemaOpenMP.cpp
+++ b/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>;
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>>;
+ using DoacrossDependMapTy =
+ llvm::DenseMap<OMPDependClause *, OperatorOffsetTy>;
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::PointerIntPair<const Expr *, 1, bool> 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,66 @@ 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) {
assert(!isStackEmpty());
Stack.back().first.back().OrderedRegion.setInt(IsOrdered);
Stack.back().first.back().OrderedRegion.setPointer(Param);
}
- /// \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();
}
- /// \brief Returns optional parameter for the ordered region.
- Expr *getParentOrderedRegionParam() const {
+ /// Returns optional parameter for the ordered region.
+ const Expr *getParentOrderedRegionParam() const {
if (isStackEmpty() || Stack.back().first.size() == 1)
return nullptr;
return std::next(Stack.back().first.rbegin())->OrderedRegion.getPointer();
}
- /// \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 +458,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 +471,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 +479,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 +492,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 +511,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 +527,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 +537,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 +554,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 +577,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 +616,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 +633,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 +664,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 +702,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 +730,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 +813,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 +822,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 +837,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 +854,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 +870,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 +893,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 +929,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 +958,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 +977,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 +1064,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 +1081,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 +1103,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 +1120,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 +1157,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 +1186,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 +1209,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 +1239,26 @@ void Sema::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
DSAStack->popFunction(OldFSI);
}
-bool Sema::IsOpenMPCapturedByRef(ValueDecl *D, unsigned Level) {
+static llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy>
+isDeclareTargetDeclaration(const ValueDecl *VD) {
+ for (const Decl *D : VD->redecls()) {
+ if (!D->hasAttrs())
+ continue;
+ if (const auto *Attr = D->getAttr<OMPDeclareTargetDeclAttr>())
+ return Attr->getMapType();
+ }
+ return llvm::None;
+}
+
+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 +1325,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 +1417,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 (isDeclareTargetDeclaration(VD))
+ return nullptr;
return VD;
+ }
if (DSAStack->getCurrentDirective() != OMPD_unknown &&
(!DSAStack->isClauseParsingMode() ||
@@ -1355,12 +1443,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 +1463,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 +1477,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 +1503,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 +1515,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 +1550,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 +1602,7 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
namespace {
-class VarDeclFilterCCC : public CorrectionCandidateCallback {
+class VarDeclFilterCCC final : public CorrectionCandidateCallback {
private:
Sema &SemaRef;
@@ -1515,7 +1610,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 +1619,7 @@ public:
}
};
-class VarOrFuncDeclFilterCCC : public CorrectionCandidateCallback {
+class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
private:
Sema &SemaRef;
@@ -1568,12 +1663,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 +1684,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 +1772,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 +1791,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 +1804,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 +1860,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 +1870,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 +1882,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 +1940,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 +1961,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 =
+ 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 +2017,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 +2031,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 +2040,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 +2060,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 +2088,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 +2103,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 +2116,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 +2139,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 +2153,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 +2173,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 +2202,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 +2220,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 +2262,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 +2306,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 +2315,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 +2339,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 +2381,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 +2476,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 +2489,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 +2513,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 +2562,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 +2571,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 +2613,7 @@ class CaptureRegionUnwinderRAII {
private:
Sema &S;
bool &ErrorFound;
- OpenMPDirectiveKind DKind;
+ OpenMPDirectiveKind DKind = OMPD_unknown;
public:
CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
@@ -2425,16 +2643,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 +2663,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 +2674,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 +2701,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 +2723,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 +2733,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 +2760,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 +2860,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 +2950,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 +2983,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 +3049,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 +3069,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 +3093,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 +3107,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 +3119,9 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
ClausesWithImplicit.emplace_back(Implicit);
ErrorFound |=
cast<OMPMapClause>(Implicit)->varlist_size() != ImplicitMaps.size();
- } else
+ } else {
ErrorFound = true;
+ }
}
}
@@ -3153,7 +3373,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 +3403,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 +3425,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 +3452,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 +3503,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 +3519,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 +3588,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 +3641,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 +3649,110 @@ 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;
+ /// 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 +3762,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 +3782,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 +3797,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 +3854,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 +3878,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 +3900,28 @@ 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, nullptr, 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 +3930,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 +3967,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 +3986,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 +4000,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 +4017,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 +4064,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 +4088,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 +4118,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 +4134,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 +4173,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 +4192,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 +4231,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 +4260,16 @@ 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 +4280,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 +4296,35 @@ 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; }
-/// \brief Build step of the counter be used for codegen.
-Expr *OpenMPIterationSpaceChecker::BuildCounterStep() const { return Step; }
+/// Build step of the counter be used for codegen.
+Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
-/// \brief Iteration space of a single for loop.
+/// 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 +4337,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,15 +4356,15 @@ 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,
+ 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);
@@ -4168,22 +4395,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 +4441,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 +4457,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 +4474,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 ||
@@ -4283,13 +4510,13 @@ static bool CheckOpenMPIterationSpace(
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 +4528,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 +4604,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 +4620,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 +4645,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 +4659,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 +4675,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) {
@@ -4482,12 +4708,12 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
}
// 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);
Stmt *CurStmt = AStmt->IgnoreContainers(/* IgnoreCaptured */ true);
for (unsigned Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
- if (CheckOpenMPIterationSpace(DKind, CurStmt, SemaRef, DSA, Cnt,
+ if (checkOpenMPIterationSpace(DKind, CurStmt, SemaRef, DSA, Cnt,
NestedLoopCount, CollapseLoopCountExpr,
OrderedLoopCountExpr, VarsWithImplicitDSA,
IterSpaces[Cnt], Captures))
@@ -4537,26 +4763,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 +4794,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 +4820,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 +4909,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 +4920,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 +4944,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 +4952,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 +4992,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 +5005,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 +5072,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 +5088,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(
@@ -4905,16 +5133,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 +5151,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()) {
@@ -4996,10 +5224,10 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
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)
+ for (const auto &Pair : DSA.getDoacrossDependClauses()) {
+ if (Pair.first->getDependencyKind() == OMPC_DEPEND_source) {
Pair.first->setCounterValue(CounterVal);
- else {
+ } else {
if (NestedLoopCount != Pair.second.size() ||
NestedLoopCount != LoopMultipliers.size() + 1) {
// Erroneous case - clause has some problems.
@@ -5064,10 +5292,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 +5306,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 +5332,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 +5343,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 +5354,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 +5366,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 +5382,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 +5393,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 +5402,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 +5418,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 +5429,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 +5441,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 +5478,7 @@ StmtResult Sema::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,
return StmtError();
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPSectionsDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
DSAStack->isCancelRegion());
@@ -5265,7 +5492,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 +5508,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 +5538,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 +5555,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 +5563,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 +5573,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 +5604,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 +5620,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 +5631,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 +5640,7 @@ StmtResult Sema::ActOnOpenMPParallelForDirective(
}
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPParallelForDirective::Create(Context, StartLoc, EndLoc,
NestedLoopCount, Clauses, AStmt, B,
DSAStack->isCancelRegion());
@@ -5421,12 +5648,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 +5664,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 +5672,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 +5684,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 +5722,7 @@ Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses,
return StmtError();
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPParallelSectionsDirective::Create(
Context, StartLoc, EndLoc, Clauses, AStmt, DSAStack->isCancelRegion());
@@ -5516,7 +5742,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 +5772,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 +5790,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 +5805,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 +5821,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())) {
@@ -5615,7 +5843,7 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
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()) {
SourceLocation ErrLoc = TC ? TC->getLocStart() : StartLoc;
Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
<< (TC != nullptr);
@@ -5629,57 +5857,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 +5915,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 +5923,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 +5955,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 +6007,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 +6030,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 +6044,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 +6080,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 +6091,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 +6120,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 +6136,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 +6180,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 +6189,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 +6198,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 +6228,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 +6243,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 +6260,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 +6290,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 +6325,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 +6334,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 +6363,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 +6386,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 +6409,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 +6439,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 +6480,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 +6525,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 +6545,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 +6583,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 +6596,7 @@ StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
}
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTargetDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
}
@@ -6366,15 +6608,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 +6634,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 +6660,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 +6671,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 +6680,7 @@ StmtResult Sema::ActOnOpenMPTargetParallelForDirective(
}
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTargetParallelForDirective::Create(Context, StartLoc, EndLoc,
NestedLoopCount, Clauses, AStmt,
B, DSAStack->isCancelRegion());
@@ -6466,7 +6717,7 @@ StmtResult Sema::ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses,
return StmtError();
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTargetDataDirective::Create(Context, StartLoc, EndLoc, Clauses,
AStmt);
@@ -6479,7 +6730,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 +6767,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 +6804,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 +6836,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 +6844,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 +6886,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 +6910,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 +6937,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 +6946,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 +6966,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 +6982,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 +6993,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 +7015,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 +7031,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 +7040,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 +7073,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 +7083,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 +7091,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 +7117,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 +7129,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 +7141,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 +7174,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 +7185,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 +7197,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 +7229,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 +7241,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 +7252,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 +7285,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 +7296,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 +7308,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 +7341,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 +7350,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 +7360,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 +7387,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 +7400,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 +7412,7 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeSimdDirective(
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
DSAStack->setParentTeamsRegionLoc(StartLoc);
@@ -7181,12 +7422,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 +7449,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 +7462,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 +7474,7 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForSimdDirective(
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
DSAStack->setParentTeamsRegionLoc(StartLoc);
@@ -7244,12 +7484,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 +7511,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 +7522,7 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForDirective(
assert((CurContext->isDependentContext() || B.builtAll()) &&
"omp for loop exprs were not built");
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
DSAStack->setParentTeamsRegionLoc(StartLoc);
@@ -7299,7 +7538,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 +7556,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 +7564,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 +7590,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 +7600,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 +7643,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 +7662,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 +7702,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 +7714,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 +7747,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 +7759,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 +7771,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 +7879,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 +7954,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 +8142,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 +8209,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 +8271,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 +8401,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 +8473,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 +8509,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 +8518,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,8 +8616,9 @@ 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);
@@ -8431,24 +8696,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 +8946,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 +9250,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 +9274,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 +9296,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 +9328,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 +9355,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 +9368,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 +9383,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 +9415,7 @@ class DiagsUninitializedSeveretyRAII {
private:
DiagnosticsEngine &Diags;
SourceLocation SavedLoc;
- bool IsIgnored;
+ bool IsIgnored = false;
public:
DiagsUninitializedSeveretyRAII(DiagnosticsEngine &Diags, SourceLocation Loc,
@@ -9184,9 +9443,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 +9477,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 +9501,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 +9521,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 +9552,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 +9569,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 +9582,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 +9594,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 +9604,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 +9626,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 +9639,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 +9659,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 +9675,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 +9714,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 +9751,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 +9759,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 +9778,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 +9792,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 +9814,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 +9859,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 +9881,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 +9911,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 +9940,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 +9959,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 +9983,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 +9997,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 +10008,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 +10117,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 +10179,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 +10260,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 +10277,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 +10318,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 +10380,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 +10409,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 +10475,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 +10487,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 +10517,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 +10566,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 +10587,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 +10598,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 +10659,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 +10771,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 +10816,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 +10836,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 +10856,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 +10880,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 +10940,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 +10964,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 +10977,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 +11010,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 +11074,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 +11123,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 +11162,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 +11200,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 +11208,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 +11242,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 +11258,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 +11266,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 +11291,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 +11336,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 +11361,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 +11381,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 +11407,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 +11426,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));
@@ -11214,143 +11478,139 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind,
llvm::APSInt DepCounter(/*BitWidth=*/32);
llvm::APSInt TotalDepCount(/*BitWidth=*/32);
if (DepKind == OMPC_DEPEND_sink) {
- if (auto *OrderedCountExpr = DSAStack->getParentOrderedRegionParam()) {
+ if (const Expr *OrderedCountExpr = DSAStack->getParentOrderedRegionParam()) {
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() &&
+ 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() &&
+ 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() &&
+ 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)
+ if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
+ DSAStack->isParentOrderedRegion())
DSAStack->addDoacrossDependClause(C, OpsOffs);
return C;
}
@@ -11363,7 +11623,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 +11632,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 +11698,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 +11712,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 +11723,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 +11747,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 +11773,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 +11812,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 +11856,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 +11892,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 +11920,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 +11960,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 +11983,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 +12038,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 +12061,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 +12071,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 +12105,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 +12128,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 +12182,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 +12222,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 +12237,7 @@ checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS,
continue;
}
- auto *SimpleExpr = RE->IgnoreParenCasts();
+ Expr *SimpleExpr = RE->IgnoreParenCasts();
if (!RE->IgnoreParenImpCasts()->isLValue()) {
SemaRef.Diag(ELoc,
@@ -11981,8 +12251,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 +12269,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 +12279,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 +12294,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 +12306,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 +12355,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 +12463,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 +12478,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 +12494,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 +12524,7 @@ void Sema::ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D) {
// Enter new function scope.
PushFunctionScope();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
getCurFunction()->setHasOMPDeclareReductionCombiner();
if (S != nullptr)
@@ -12269,7 +12542,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 +12550,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 +12580,7 @@ VarDecl *Sema::ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D) {
// Enter new function scope.
PushFunctionScope();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
if (S != nullptr)
PushDeclContext(S, DRD);
@@ -12324,7 +12597,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 +12605,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 +12640,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 +12661,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 +12670,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 +12688,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 +12697,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 +12714,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 +12730,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 +12746,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 +12808,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 +12873,6 @@ bool Sema::ActOnStartOpenMPDeclareTargetDirective(SourceLocation Loc) {
void Sema::ActOnFinishOpenMPDeclareTargetDirective() {
assert(IsInOpenMPDeclareTargetContext &&
"Unexpected ActOnFinishOpenMPDeclareTargetDirective");
-
IsInOpenMPDeclareTargetContext = false;
}
@@ -12634,9 +12907,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 +12917,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 +12935,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 +13002,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 +13013,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 +13042,7 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
return;
}
}
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
if (FD->hasAttr<OMPDeclareTargetDeclAttr>() &&
(FD->getAttr<OMPDeclareTargetDeclAttr>()->getMapType() ==
OMPDeclareTargetDeclAttr::MT_Link)) {
@@ -12769,11 +13052,22 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
return;
}
}
+ if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D)) {
+ if (FTD->hasAttr<OMPDeclareTargetDeclAttr>() &&
+ (FTD->getAttr<OMPDeclareTargetDeclAttr>()->getMapType() ==
+ OMPDeclareTargetDeclAttr::MT_Link)) {
+ assert(IdLoc.isValid() && "Source location is expected");
+ Diag(IdLoc, diag::err_omp_function_in_link_clause);
+ Diag(FTD->getLocation(), diag::note_defined_here) << FTD;
+ return;
+ }
+ }
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 +13114,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 +13143,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 +13198,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 +13223,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/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 2144845f4dd3..08af485ef4c7 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/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
@@ -5145,7 +5180,8 @@ Sema::PerformObjectArgumentInitialization(Expr *From,
*this, From->getLocStart(), From->getType(), FromClassification, Method,
Method->getParent());
if (ICS.isBad()) {
- if (ICS.Bad.Kind == BadConversionSequence::bad_qualifiers) {
+ switch (ICS.Bad.Kind) {
+ case BadConversionSequence::bad_qualifiers: {
Qualifiers FromQs = FromRecordType.getQualifiers();
Qualifiers ToQs = DestType.getQualifiers();
unsigned CVR = FromQs.getCVRQualifiers() & ~ToQs.getCVRQualifiers();
@@ -5158,10 +5194,28 @@ Sema::PerformObjectArgumentInitialization(Expr *From,
<< Method->getDeclName();
return ExprError();
}
+ break;
+ }
+
+ case BadConversionSequence::lvalue_ref_to_rvalue:
+ case BadConversionSequence::rvalue_ref_to_lvalue: {
+ bool IsRValueQualified =
+ Method->getRefQualifier() == RefQualifierKind::RQ_RValue;
+ Diag(From->getLocStart(), diag::err_member_function_call_bad_ref)
+ << Method->getDeclName() << FromClassification.isRValue()
+ << IsRValueQualified;
+ Diag(Method->getLocation(), diag::note_previous_decl)
+ << Method->getDeclName();
+ return ExprError();
+ }
+
+ case BadConversionSequence::no_conversion:
+ case BadConversionSequence::unrelated_class:
+ break;
}
return Diag(From->getLocStart(),
- diag::err_implicit_object_parameter_init)
+ diag::err_member_function_call_bad_type)
<< ImplicitParamRecordType << FromRecordType << From->getSourceRange();
}
@@ -5380,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.
@@ -5622,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
@@ -5940,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
@@ -6220,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());
@@ -6336,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);
}
}
}
@@ -6564,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
@@ -6634,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
@@ -6967,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++
@@ -7124,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
@@ -7260,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;
@@ -7524,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,
@@ -7602,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.
@@ -7658,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);
@@ -7673,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,
@@ -7733,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);
@@ -7754,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());
}
@@ -7929,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, [...]
@@ -8002,7 +8090,6 @@ public:
UserDefinedBinaryOperators.count(std::make_pair(CanonType,
CanonType)))
continue;
-
QualType ParamTypes[2] = { *Enum, *Enum };
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
}
@@ -8120,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
@@ -8688,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:
@@ -8764,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
@@ -8870,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(
@@ -9067,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
@@ -9137,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
@@ -9228,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;
+
+ assert(isa<CXXConversionDecl>(Meth) && "expected conversion");
+ return oc_method;
+ }
- return isTemplate ? oc_function_template : oc_function;
+ return oc_function;
+ }();
+
+ return std::make_pair(Kind, Select);
}
void MaybeEmitInheritedConstructorNote(Sema &S, Decl *FoundDecl) {
@@ -9313,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
@@ -9375,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);
@@ -9453,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;
@@ -9468,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;
}
@@ -9497,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;
}
@@ -9543,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;
@@ -9560,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;
}
@@ -9576,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;
@@ -9617,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;
}
@@ -9642,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;
}
@@ -9656,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(),
@@ -9732,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);
}
@@ -9783,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);
@@ -10017,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.
@@ -10030,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:
@@ -10102,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;
}
@@ -10176,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;
}
}
@@ -10257,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:
@@ -10493,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,
@@ -10642,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 (?).
@@ -10912,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.
@@ -10993,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()) {
@@ -11157,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.
///
@@ -11193,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.
@@ -11207,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
@@ -11223,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
@@ -11309,9 +11509,6 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
return Matched;
}
-
-
-
// Resolve and fix an overloaded expression that can be resolved
// because it identifies a single function template specialization.
//
@@ -11395,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,
@@ -11434,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,
@@ -11726,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,
@@ -11866,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);
@@ -11932,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., '*').
@@ -11978,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
@@ -12077,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();
@@ -12123,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., '+').
@@ -12321,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();
@@ -12346,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();
@@ -12533,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();
@@ -13508,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(),
@@ -13519,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/lib/Sema/SemaPseudoObject.cpp b/lib/Sema/SemaPseudoObject.cpp
index 58980be64a30..4484e9b3513b 100644
--- a/lib/Sema/SemaPseudoObject.cpp
+++ b/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);
@@ -313,11 +321,10 @@ namespace {
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);
}
@@ -364,7 +371,9 @@ OpaqueValueExpr *PseudoOpBuilder::capture(Expr *e) {
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;
@@ -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);
}
@@ -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);
}
@@ -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/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 4474d62949a2..b2f9783d44f1 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -14,6 +14,7 @@
#include "clang/Sema/SemaInternal.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
+#include "clang/AST/ASTLambda.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclObjC.h"
@@ -120,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
@@ -336,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() {
@@ -391,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;
}
@@ -472,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;
}
@@ -556,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);
@@ -678,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");
+
+ 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();
+ }
+ }
- getCurFunction()->setHasBranchIntoScope();
+ 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;
}
@@ -704,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?
@@ -758,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>();
@@ -786,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();
@@ -799,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).
//
@@ -810,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.
@@ -877,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;
}
@@ -1001,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.
@@ -1031,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)
@@ -1103,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)
@@ -1119,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;
@@ -1872,7 +1864,7 @@ StmtResult
Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
Stmt *First, Expr *collection,
SourceLocation RParenLoc) {
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
ExprResult CollectionExprResult =
CheckObjCForCollectionOperand(ForLoc, collection);
@@ -2024,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);
@@ -2093,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();
@@ -2118,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.
@@ -2339,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;
@@ -2386,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
@@ -2656,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();
@@ -2717,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.
@@ -2779,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);
}
@@ -2806,7 +2802,7 @@ Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc,
return StmtError();
E = ExprRes.get();
- getCurFunction()->setHasIndirectGoto();
+ setFunctionHasIndirectGoto();
return new (Context) IndirectGotoStmt(GotoLoc, StarLoc, E);
}
@@ -2846,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
@@ -2857,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
@@ -2866,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());
@@ -2879,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 ...
@@ -2894,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;
@@ -2913,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...
@@ -2928,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
@@ -2951,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);
+ }
+ }
}
}
}
@@ -3010,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 =
@@ -3144,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);
@@ -3157,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) {
@@ -3182,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() {
@@ -3228,6 +3340,12 @@ bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
SourceLocation ReturnLoc,
Expr *&RetExpr,
AutoType *AT) {
+ // If this is the conversion function for a lambda, we choose to deduce it
+ // type from the corresponding call operator, not from the synthesized return
+ // statement within it. See Sema::DeduceReturnType.
+ if (isLambdaConversionOperator(FD))
+ return false;
+
TypeLoc OrigResultType = getReturnTypeLoc(FD);
QualType Deduced;
@@ -3521,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,
@@ -3596,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);
@@ -3687,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);
}
@@ -3703,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);
}
@@ -3815,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.
@@ -4029,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());
}
}
@@ -4104,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);
@@ -4153,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/lib/Sema/SemaStmtAsm.cpp b/lib/Sema/SemaStmtAsm.cpp
index fc1cc7bbe544..7e26b71c0482 100644
--- a/lib/Sema/SemaStmtAsm.cpp
+++ b/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,
@@ -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/lib/Sema/SemaStmtAttr.cpp b/lib/Sema/SemaStmtAttr.cpp
index e55e20c2827f..e39a65c6ce0c 100644
--- a/lib/Sema/SemaStmtAttr.cpp
+++ b/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/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index d94cb0d0f485..dd1163267119 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/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,
@@ -169,16 +175,16 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
MemberOfUnknownSpecialization = false;
switch (Name.getKind()) {
- case UnqualifiedId::IK_Identifier:
+ case UnqualifiedIdKind::IK_Identifier:
TName = DeclarationName(Name.Identifier);
break;
- case UnqualifiedId::IK_OperatorFunctionId:
+ case UnqualifiedIdKind::IK_OperatorFunctionId:
TName = Context.DeclarationNames.getCXXOperatorName(
Name.OperatorFunctionId.Operator);
break;
- case UnqualifiedId::IK_LiteralOperatorId:
+ case UnqualifiedIdKind::IK_LiteralOperatorId:
TName = Context.DeclarationNames.getCXXLiteralOperatorName(Name.Identifier);
break;
@@ -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;
@@ -933,9 +1045,9 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
auto CheckValidDeclSpecifiers = [this, &D] {
// C++ [temp.param]
// p1
- // template-parameter:
- // ...
- // parameter-declaration
+ // template-parameter:
+ // ...
+ // parameter-declaration
// p2
// ... A storage class shall not be specified in a template-parameter
// declaration.
@@ -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());
@@ -1885,6 +1992,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 +2034,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 +2090,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 +2121,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 +2488,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 +3585,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();
@@ -3557,7 +3666,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
TemplateParameterList *TemplateParams, StorageClass SC,
bool IsPartialSpecialization) {
// D must be variable template id.
- assert(D.getName().getKind() == UnqualifiedId::IK_TemplateId &&
+ assert(D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId &&
"Variable template specialization is declared with a template it.");
TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
@@ -3754,7 +3863,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 +4047,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 +4076,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 +4128,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 +4153,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 +4163,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,24 +4201,27 @@ 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.
auto *LookupRD = dyn_cast<CXXRecordDecl>(LookupCtx);
if (!AllowInjectedClassName && SS.isSet() && LookupRD &&
- Name.getKind() == UnqualifiedId::IK_Identifier && Name.Identifier &&
- LookupRD->getIdentifier() == Name.Identifier) {
+ Name.getKind() == UnqualifiedIdKind::IK_Identifier &&
+ Name.Identifier && LookupRD->getIdentifier() == Name.Identifier) {
// C++14 [class.qual]p2:
// In a lookup in which function names are not ignored and the
// nested-name-specifier nominates a class C, if the name specified
@@ -4107,17 +4243,17 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,
NestedNameSpecifier *Qualifier = SS.getScopeRep();
switch (Name.getKind()) {
- case UnqualifiedId::IK_Identifier:
+ case UnqualifiedIdKind::IK_Identifier:
Result = TemplateTy::make(Context.getDependentTemplateName(Qualifier,
Name.Identifier));
return TNK_Dependent_template_name;
- case UnqualifiedId::IK_OperatorFunctionId:
+ case UnqualifiedIdKind::IK_OperatorFunctionId:
Result = TemplateTy::make(Context.getDependentTemplateName(Qualifier,
Name.OperatorFunctionId.Operator));
return TNK_Function_template;
- case UnqualifiedId::IK_LiteralOperatorId:
+ case UnqualifiedIdKind::IK_LiteralOperatorId:
llvm_unreachable("literal operator id cannot have a dependent scope");
default:
@@ -4148,16 +4284,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 +4383,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 +4439,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 +4487,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 +4551,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 +4652,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 +4699,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 +4732,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 +4844,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 +4863,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 +4886,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 +4914,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 +4967,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 +5027,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 +5222,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 +5336,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 +5498,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 +5536,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 +5632,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 +5689,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 +5977,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 +6027,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 +6106,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 +6261,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 +6624,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 +6665,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 +6691,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 +6722,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 +6814,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 +6839,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 +6874,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 +6977,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 +6999,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 +7091,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 +7140,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 +7156,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 +7210,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 +7272,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 +7360,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 +7396,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 +7642,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 +7701,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 +7768,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 +7778,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 +7795,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 +7941,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 +7980,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 +8003,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 +8260,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 +8470,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 +8524,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 +8570,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 +8616,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 +8640,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 +8753,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 +8851,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;
@@ -9044,7 +9100,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
return true;
}
- if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
+ if (D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) {
// C++1y [temp.explicit]p3:
// If the explicit instantiation is for a variable, the unqualified-id
// in the declaration shall be a template-id.
@@ -9101,8 +9157,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);
@@ -9126,7 +9181,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
// argument list into our AST format.
bool HasExplicitTemplateArgs = false;
TemplateArgumentListInfo TemplateArgs;
- if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
+ if (D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId) {
TemplateArgs = makeTemplateArgumentListInfo(*this, *D.getName().TemplateId);
HasExplicitTemplateArgs = true;
}
@@ -9138,7 +9193,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 +9240,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 +9319,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.
@@ -9292,7 +9345,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
//
// C++98 has the same restriction, just worded differently.
FunctionTemplateDecl *FunTmpl = Specialization->getPrimaryTemplate();
- if (D.getName().getKind() != UnqualifiedId::IK_TemplateId && !FunTmpl &&
+ if (D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId && !FunTmpl &&
D.getCXXScopeSpec().isSet() &&
!ScopeSpecifierHasTemplateId(D.getCXXScopeSpec()))
Diag(D.getIdentifierLoc(),
@@ -9478,8 +9531,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 +9563,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 +9738,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 +9747,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 +9768,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 +9826,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 +9865,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 +9943,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 +10079,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/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index f8ee60251698..633b2837e1fe 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/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
@@ -502,6 +546,10 @@ DeduceTemplateArguments(Sema &S,
SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
assert(Arg.isCanonical() && "Argument type must be canonical");
+ // Treat an injected-class-name as its underlying template-id.
+ if (auto *Injected = dyn_cast<InjectedClassNameType>(Arg))
+ Arg = Injected->getInjectedSpecializationType();
+
// Check whether the template argument is a dependent template-id.
if (const TemplateSpecializationType *SpecArg
= dyn_cast<TemplateSpecializationType>(Arg)) {
@@ -556,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()) {
@@ -580,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))
@@ -614,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;
@@ -632,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;
@@ -652,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];
@@ -724,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;
@@ -739,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
@@ -761,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()) {
@@ -826,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;
}
@@ -847,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).
///
@@ -891,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
@@ -933,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
@@ -950,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
@@ -974,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();
@@ -999,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.
///
@@ -1057,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
@@ -1228,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");
@@ -1303,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;
@@ -1353,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;
@@ -1363,7 +1511,6 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
}
return Param == Arg? Sema::TDK_Success : Sema::TDK_NonDeducedMismatch;
- }
// _Complex T [placeholder extension]
case Type::Complex:
@@ -1557,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;
@@ -1578,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)
@@ -1590,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>
@@ -1788,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))))
@@ -1992,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)
@@ -2021,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!");
}
@@ -2029,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
@@ -2052,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;
@@ -2063,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;
}
@@ -2126,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],
@@ -2167,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,
@@ -2228,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
@@ -2303,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,
@@ -2409,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
@@ -2443,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);
@@ -2659,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
@@ -2702,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
@@ -2743,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>())
@@ -2763,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
@@ -2837,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;
}
@@ -2846,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
@@ -2858,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());
+ }
}
}
@@ -2955,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);
@@ -2970,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,
@@ -3080,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();
@@ -3116,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.
///
@@ -3267,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());
@@ -3322,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.
@@ -3339,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;
@@ -3379,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
@@ -3493,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,
@@ -3554,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,
@@ -3587,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
@@ -3725,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;
@@ -3753,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,
@@ -3798,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.
///
@@ -3940,118 +4126,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
return TDK_Success;
}
-/// \brief Given a function declaration (e.g. a generic lambda conversion
-/// function) that contains an 'auto' in its result type, substitute it
-/// with TypeToReplaceAutoWith. Be careful to pass in the type you want
-/// to replace 'auto' with and not the actual result type you want
-/// to set the function to.
-static inline void
-SubstAutoWithinFunctionReturnType(FunctionDecl *F,
- QualType TypeToReplaceAutoWith, Sema &S) {
- assert(!TypeToReplaceAutoWith->getContainedAutoType());
- QualType AutoResultType = F->getReturnType();
- assert(AutoResultType->getContainedAutoType());
- QualType DeducedResultType = S.SubstAutoType(AutoResultType,
- TypeToReplaceAutoWith);
- S.Context.adjustDeducedFunctionResultType(F, DeducedResultType);
-}
-
-/// \brief Given a specialized conversion operator of a generic lambda
-/// create the corresponding specializations of the call operator and
-/// the static-invoker. If the return type of the call operator is auto,
-/// deduce its return type and check if that matches the
-/// return type of the destination function ptr.
-
-static inline Sema::TemplateDeductionResult
-SpecializeCorrespondingLambdaCallOperatorAndInvoker(
- CXXConversionDecl *ConversionSpecialized,
- SmallVectorImpl<DeducedTemplateArgument> &DeducedArguments,
- QualType ReturnTypeOfDestFunctionPtr,
- TemplateDeductionInfo &TDInfo,
- Sema &S) {
-
- CXXRecordDecl *LambdaClass = ConversionSpecialized->getParent();
- assert(LambdaClass && LambdaClass->isGenericLambda());
-
- CXXMethodDecl *CallOpGeneric = LambdaClass->getLambdaCallOperator();
- QualType CallOpResultType = CallOpGeneric->getReturnType();
- const bool GenericLambdaCallOperatorHasDeducedReturnType =
- CallOpResultType->getContainedAutoType();
-
- FunctionTemplateDecl *CallOpTemplate =
- CallOpGeneric->getDescribedFunctionTemplate();
-
- FunctionDecl *CallOpSpecialized = nullptr;
- // Use the deduced arguments of the conversion function, to specialize our
- // generic lambda's call operator.
- if (Sema::TemplateDeductionResult Result
- = S.FinishTemplateArgumentDeduction(CallOpTemplate,
- DeducedArguments,
- 0, CallOpSpecialized, TDInfo))
- return Result;
-
- // If we need to deduce the return type, do so (instantiates the callop).
- if (GenericLambdaCallOperatorHasDeducedReturnType &&
- CallOpSpecialized->getReturnType()->isUndeducedType())
- S.DeduceReturnType(CallOpSpecialized,
- CallOpSpecialized->getPointOfInstantiation(),
- /*Diagnose*/ true);
-
- // Check to see if the return type of the destination ptr-to-function
- // matches the return type of the call operator.
- if (!S.Context.hasSameType(CallOpSpecialized->getReturnType(),
- ReturnTypeOfDestFunctionPtr))
- return Sema::TDK_NonDeducedMismatch;
- // Since we have succeeded in matching the source and destination
- // ptr-to-functions (now including return type), and have successfully
- // specialized our corresponding call operator, we are ready to
- // specialize the static invoker with the deduced arguments of our
- // ptr-to-function.
- FunctionDecl *InvokerSpecialized = nullptr;
- FunctionTemplateDecl *InvokerTemplate = LambdaClass->
- getLambdaStaticInvoker()->getDescribedFunctionTemplate();
-
-#ifndef NDEBUG
- Sema::TemplateDeductionResult LLVM_ATTRIBUTE_UNUSED Result =
-#endif
- S.FinishTemplateArgumentDeduction(InvokerTemplate, DeducedArguments, 0,
- InvokerSpecialized, TDInfo);
- assert(Result == Sema::TDK_Success &&
- "If the call operator succeeded so should the invoker!");
- // Set the result type to match the corresponding call operator
- // specialization's result type.
- if (GenericLambdaCallOperatorHasDeducedReturnType &&
- InvokerSpecialized->getReturnType()->isUndeducedType()) {
- // Be sure to get the type to replace 'auto' with and not
- // the full result type of the call op specialization
- // to substitute into the 'auto' of the invoker and conversion
- // function.
- // For e.g.
- // int* (*fp)(int*) = [](auto* a) -> auto* { return a; };
- // We don't want to subst 'int*' into 'auto' to get int**.
-
- QualType TypeToReplaceAutoWith = CallOpSpecialized->getReturnType()
- ->getContainedAutoType()
- ->getDeducedType();
- SubstAutoWithinFunctionReturnType(InvokerSpecialized,
- TypeToReplaceAutoWith, S);
- SubstAutoWithinFunctionReturnType(ConversionSpecialized,
- TypeToReplaceAutoWith, S);
- }
-
- // Ensure that static invoker doesn't have a const qualifier.
- // FIXME: When creating the InvokerTemplate in SemaLambda.cpp
- // do not use the CallOperator's TypeSourceInfo which allows
- // the const qualifier to leak through.
- const FunctionProtoType *InvokerFPT = InvokerSpecialized->
- getType().getTypePtr()->castAs<FunctionProtoType>();
- FunctionProtoType::ExtProtoInfo EPI = InvokerFPT->getExtProtoInfo();
- EPI.TypeQuals = 0;
- InvokerSpecialized->setType(S.Context.getFunctionType(
- InvokerFPT->getReturnType(), InvokerFPT->getParamTypes(), EPI));
- return Sema::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
@@ -4080,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
@@ -4134,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.
@@ -4158,39 +4241,10 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate,
= FinishTemplateArgumentDeduction(ConversionTemplate, Deduced, 0,
ConversionSpecialized, Info);
Specialization = cast_or_null<CXXConversionDecl>(ConversionSpecialized);
-
- // If the conversion operator is being invoked on a lambda closure to convert
- // to a ptr-to-function, use the deduced arguments from the conversion
- // function to specialize the corresponding call operator.
- // e.g., int (*fp)(int) = [](auto a) { return a; };
- if (Result == TDK_Success && isLambdaConversionOperator(ConversionGeneric)) {
-
- // Get the return type of the destination ptr-to-function we are converting
- // to. This is necessary for matching the lambda call operator's return
- // type to that of the destination ptr-to-function's return type.
- assert(A->isPointerType() &&
- "Can only convert from lambda to ptr-to-function");
- const FunctionType *ToFunType =
- A->getPointeeType().getTypePtr()->getAs<FunctionType>();
- const QualType DestFunctionPtrReturnType = ToFunType->getReturnType();
-
- // Create the corresponding specializations of the call operator and
- // the static-invoker; and if the return type is auto,
- // deduce the return type and check if it matches the
- // DestFunctionPtrReturnType.
- // For instance:
- // auto L = [](auto a) { return f(a); };
- // int (*fp)(int) = L;
- // char (*fp2)(int) = L; <-- Not OK.
-
- Result = SpecializeCorrespondingLambdaCallOperatorAndInvoker(
- Specialization, Deduced, DestFunctionPtrReturnType,
- Info, *this);
- }
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
@@ -4225,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)
@@ -4292,7 +4348,8 @@ namespace {
return TransformType(TLB, TL);
}
};
-}
+
+} // namespace
Sema::DeduceAutoResult
Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *&Init, QualType &Result,
@@ -4326,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'.)
@@ -4536,6 +4593,43 @@ bool Sema::DeduceReturnType(FunctionDecl *FD, SourceLocation Loc,
bool Diagnose) {
assert(FD->getReturnType()->isUndeducedType());
+ // For a lambda's conversion operator, deduce any 'auto' or 'decltype(auto)'
+ // within the return type from the call operator's type.
+ if (isLambdaConversionOperator(FD)) {
+ CXXRecordDecl *Lambda = cast<CXXMethodDecl>(FD)->getParent();
+ FunctionDecl *CallOp = Lambda->getLambdaCallOperator();
+
+ // For a generic lambda, instantiate the call operator if needed.
+ if (auto *Args = FD->getTemplateSpecializationArgs()) {
+ CallOp = InstantiateFunctionDeclaration(
+ CallOp->getDescribedFunctionTemplate(), Args, Loc);
+ if (!CallOp || CallOp->isInvalidDecl())
+ return true;
+
+ // We might need to deduce the return type by instantiating the definition
+ // of the operator() function.
+ if (CallOp->getReturnType()->isUndeducedType())
+ InstantiateFunctionDefinition(Loc, CallOp);
+ }
+
+ if (CallOp->isInvalidDecl())
+ return true;
+ assert(!CallOp->getReturnType()->isUndeducedType() &&
+ "failed to deduce lambda return type");
+
+ // Build the new return type from scratch.
+ QualType RetType = getLambdaConversionFunctionResultType(
+ CallOp->getType()->castAs<FunctionProtoType>());
+ if (FD->getReturnType()->getAs<PointerType>())
+ RetType = Context.getPointerType(RetType);
+ else {
+ assert(FD->getReturnType()->getAs<BlockPointerType>());
+ RetType = Context.getBlockPointerType(RetType);
+ }
+ Context.adjustDeducedFunctionResultType(FD, RetType);
+ return false;
+ }
+
if (FD->getTemplateInstantiationPattern())
InstantiateFunctionDefinition(Loc, FD);
@@ -4548,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,
@@ -4570,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,
@@ -4721,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();
@@ -4742,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
@@ -4789,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;
@@ -4800,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
@@ -4959,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]).
///
@@ -5114,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,
@@ -5128,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 =
@@ -5158,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,
@@ -5175,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,
@@ -5200,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,
@@ -5271,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);
@@ -5296,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;
@@ -5453,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,
@@ -5496,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
@@ -5522,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/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index a48e2466a84d..bc2ee42400b7 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/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
@@ -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;
}
}
@@ -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.
@@ -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;
+ }
}
}
@@ -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;
@@ -793,7 +795,7 @@ 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);
@@ -824,15 +826,15 @@ namespace {
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,
TypeSourceInfo *Declarator,
@@ -840,12 +842,12 @@ namespace {
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,
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,
@@ -1197,11 +1199,11 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
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.
@@ -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
@@ -1820,7 +1822,7 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
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(
@@ -1840,7 +1842,7 @@ bool Sema::SubstParmTypes(
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
@@ -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,7 +1998,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
return true;
Pattern = PatternDef;
- // \brief Record the point of instantiation.
+ // Record the point of instantiation.
if (MemberSpecializationInfo *MSInfo
= Instantiation->getMemberSpecializationInfo()) {
MSInfo->setTemplateSpecializationKind(TSK);
@@ -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;
+ }
+ }
+
+ 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;
+ 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
@@ -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
@@ -2808,7 +2825,7 @@ Sema::SubstNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
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) {
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index d8af8f34530b..5109dc8290f9 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/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);
}
}
@@ -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;
+ }
}
}
}
@@ -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
@@ -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).
///
@@ -3729,6 +3715,30 @@ TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New,
return false;
}
+/// Instantiate (or find existing instantiation of) a function template with a
+/// given set of template arguments.
+///
+/// Usually this should not be used, and template argument deduction should be
+/// used in its place.
+FunctionDecl *
+Sema::InstantiateFunctionDeclaration(FunctionTemplateDecl *FTD,
+ const TemplateArgumentList *Args,
+ SourceLocation Loc) {
+ FunctionDecl *FD = FTD->getTemplatedDecl();
+
+ sema::TemplateDeductionInfo Info(Loc);
+ InstantiatingTemplate Inst(
+ *this, Loc, FTD, Args->asArray(),
+ CodeSynthesisContext::ExplicitTemplateArgumentSubstitution, Info);
+ if (Inst.isInvalid())
+ return nullptr;
+
+ ContextRAII SavedContext(*this, FD);
+ MultiLevelTemplateArgumentList MArgs(*Args);
+
+ return cast_or_null<FunctionDecl>(SubstDecl(FD, FD->getParent(), MArgs));
+}
+
/// In the MS ABI, we need to instantiate default arguments of dllexported
/// default constructors along with the constructor definition. This allows IR
/// gen to emit a constructor closure which calls the default constructor with
@@ -3750,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
@@ -3812,7 +3822,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
PendingInstantiations.push_back(
std::make_pair(Function, PointOfInstantiation));
} else if (TSK == TSK_ImplicitInstantiation) {
- if (AtEndOfTU && !getDiagnostics().hasErrorOccurred()) {
+ if (AtEndOfTU && !getDiagnostics().hasErrorOccurred() &&
+ !getSourceManager().isInSystemHeader(PatternDecl->getLocStart())) {
Diag(PointOfInstantiation, diag::warn_func_template_missing)
<< Function;
Diag(PatternDecl->getLocation(), diag::note_forward_template_decl);
@@ -3829,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;
}
@@ -3887,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
@@ -3932,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.
@@ -3949,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);
@@ -4025,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,
@@ -4075,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(
@@ -4135,7 +4147,8 @@ void Sema::BuildVariableInstantiation(
// it right away if the type contains 'auto'.
if ((!isa<VarTemplateSpecializationDecl>(NewVar) &&
!InstantiatingVarTemplate &&
- !(OldVar->isInline() && OldVar->isThisDeclarationADefinition())) ||
+ !(OldVar->isInline() && OldVar->isThisDeclarationADefinition() &&
+ !NewVar->isThisDeclarationADefinition())) ||
NewVar->getType()->isUndeducedType())
InstantiateVariableInitializer(NewVar, OldVar, TemplateArgs);
@@ -4147,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) {
@@ -4193,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;
@@ -4204,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
@@ -4295,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
@@ -4347,7 +4365,8 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
std::make_pair(Var, PointOfInstantiation));
} else if (TSK == TSK_ImplicitInstantiation) {
// Warn about missing definition at the end of translation unit.
- if (AtEndOfTU && !getDiagnostics().hasErrorOccurred()) {
+ if (AtEndOfTU && !getDiagnostics().hasErrorOccurred() &&
+ !getSourceManager().isInSystemHeader(PatternDecl->getLocStart())) {
Diag(PointOfInstantiation, diag::warn_var_template_missing)
<< Var;
Diag(PatternDecl->getLocation(), diag::note_forward_template_decl);
@@ -4407,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
@@ -4829,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
@@ -4841,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
@@ -5154,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() ||
@@ -5211,7 +5230,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/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp
index d81837dad508..fc1641334273 100644
--- a/lib/Sema/SemaTemplateVariadic.cpp
+++ b/lib/Sema/SemaTemplateVariadic.cpp
@@ -26,21 +26,8 @@ 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>
{
@@ -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,7 +89,7 @@ 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())
@@ -111,7 +98,7 @@ namespace {
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())) {
@@ -122,7 +109,7 @@ namespace {
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,7 +129,7 @@ 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) {
Expr *E = dyn_cast_or_null<Expr>(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,7 +148,7 @@ 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() &&
@@ -172,7 +159,7 @@ namespace {
return true;
}
- /// \brief Suppress traversal of parameter packs.
+ /// 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
@@ -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,7 +211,7 @@ 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;
@@ -232,7 +219,7 @@ namespace {
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>(
@@ -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) {
@@ -701,8 +700,13 @@ bool Sema::CheckParameterPacksForExpansion(
= 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;
+ }
}
}
@@ -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;
}
@@ -812,6 +838,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
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:
@@ -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
@@ -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/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 2530b766f5f7..ac04cecaf774 100644
--- a/lib/Sema/SemaType.cpp
+++ b/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"
@@ -47,7 +48,7 @@ enum TypeDiagSelector {
/// isOmittedBlockReturnType - Return true if this declarator is missing a
/// return type because this is a omitted return type on a block literal.
static bool isOmittedBlockReturnType(const Declarator &D) {
- if (D.getContext() != Declarator::BlockLiteralContext ||
+ if (D.getContext() != DeclaratorContext::BlockLiteralContext ||
D.getDeclSpec().hasTypeSpecifier())
return false;
@@ -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");
@@ -1291,11 +1244,12 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// The declspec is always missing in a lambda expr context; it is either
// specified with a trailing return type or inferred.
if (S.getLangOpts().CPlusPlus14 &&
- declarator.getContext() == Declarator::LambdaExprContext) {
+ declarator.getContext() == DeclaratorContext::LambdaExprContext) {
// In C++1y, a lambda's implicit return type is 'auto'.
Result = Context.getAutoDeductType();
break;
- } else if (declarator.getContext() == Declarator::LambdaExprContext ||
+ } else if (declarator.getContext() ==
+ DeclaratorContext::LambdaExprContext ||
checkOmittedBlockReturnType(S, declarator,
Context.DependentTy)) {
Result = Context.DependentTy;
@@ -1383,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)
@@ -1421,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;
@@ -1441,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: {
@@ -1527,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"
@@ -1550,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)
@@ -1572,7 +1585,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// Before we process any type attributes, synthesize a block literal
// function declarator if necessary.
- if (declarator.getContext() == Declarator::BlockLiteralContext)
+ if (declarator.getContext() == DeclaratorContext::BlockLiteralContext)
maybeSynthesizeBlockSignature(state, Result);
// Apply any type attributes from the decl spec. This may cause the
@@ -1580,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()) {
@@ -1747,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);
}
@@ -1857,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.
///
@@ -1897,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.
///
@@ -1959,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.
///
@@ -1971,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.
///
@@ -2005,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.
///
@@ -2230,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,
@@ -2401,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.
@@ -2450,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.
///
@@ -2582,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,
@@ -2702,7 +2766,7 @@ static void diagnoseRedundantReturnTypeQualifiers(Sema &S, QualType RetTy,
// If the qualifiers come from a conversion function type, don't diagnose
// them -- they're not necessarily redundant, since such a conversion
// operator can be explicitly called as "x.operator const int()".
- if (D.getName().getKind() == UnqualifiedId::IK_ConversionFunctionId)
+ if (D.getName().getKind() == UnqualifiedIdKind::IK_ConversionFunctionId)
return;
// Just parens all the way out to the decl specifiers. Diagnose any qualifiers
@@ -2728,11 +2792,11 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
TagDecl *OwnedTagDecl = nullptr;
switch (D.getName().getKind()) {
- case UnqualifiedId::IK_ImplicitSelfParam:
- case UnqualifiedId::IK_OperatorFunctionId:
- case UnqualifiedId::IK_Identifier:
- case UnqualifiedId::IK_LiteralOperatorId:
- case UnqualifiedId::IK_TemplateId:
+ case UnqualifiedIdKind::IK_ImplicitSelfParam:
+ case UnqualifiedIdKind::IK_OperatorFunctionId:
+ case UnqualifiedIdKind::IK_Identifier:
+ case UnqualifiedIdKind::IK_LiteralOperatorId:
+ case UnqualifiedIdKind::IK_TemplateId:
T = ConvertDeclSpecToType(state);
if (!D.isInvalidType() && D.getDeclSpec().isTypeSpecOwned()) {
@@ -2742,23 +2806,23 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
}
break;
- case UnqualifiedId::IK_ConstructorName:
- case UnqualifiedId::IK_ConstructorTemplateId:
- case UnqualifiedId::IK_DestructorName:
+ case UnqualifiedIdKind::IK_ConstructorName:
+ case UnqualifiedIdKind::IK_ConstructorTemplateId:
+ case UnqualifiedIdKind::IK_DestructorName:
// Constructors and destructors don't have return types. Use
// "void" instead.
T = SemaRef.Context.VoidTy;
processTypeAttrs(state, T, TAL_DeclSpec,
- D.getDeclSpec().getAttributes().getList());
+ D.getMutableDeclSpec().getAttributes());
break;
- case UnqualifiedId::IK_DeductionGuideName:
+ case UnqualifiedIdKind::IK_DeductionGuideName:
// Deduction guides have a trailing return type and no type in their
// decl-specifier sequence. Use a placeholder return type for now.
T = SemaRef.Context.DependentTy;
break;
- case UnqualifiedId::IK_ConversionFunctionId:
+ case UnqualifiedIdKind::IK_ConversionFunctionId:
// The result type of a conversion function is the type that it
// converts to.
T = SemaRef.GetTypeFromParser(D.getName().ConversionFunctionId,
@@ -2766,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.
@@ -2780,16 +2844,16 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
(Auto && Auto->getKeyword() != AutoTypeKeyword::GNUAutoType);
switch (D.getContext()) {
- case Declarator::LambdaExprContext:
+ case DeclaratorContext::LambdaExprContext:
// Declared return type of a lambda-declarator is implicit and is always
// 'auto'.
break;
- case Declarator::ObjCParameterContext:
- case Declarator::ObjCResultContext:
- case Declarator::PrototypeContext:
+ case DeclaratorContext::ObjCParameterContext:
+ case DeclaratorContext::ObjCResultContext:
+ case DeclaratorContext::PrototypeContext:
Error = 0;
break;
- case Declarator::LambdaExprParameterContext:
+ case DeclaratorContext::LambdaExprParameterContext:
// In C++14, generic lambdas allow 'auto' in their parameters.
if (!SemaRef.getLangOpts().CPlusPlus14 ||
!Auto || Auto->getKeyword() != AutoTypeKeyword::Auto)
@@ -2821,7 +2885,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
T, QualType(CorrespondingTemplateParam->getTypeForDecl(), 0));
}
break;
- case Declarator::MemberContext: {
+ case DeclaratorContext::MemberContext: {
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static ||
D.isFunctionDeclarator())
break;
@@ -2837,57 +2901,66 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
Error = 20; // Friend type
break;
}
- case Declarator::CXXCatchContext:
- case Declarator::ObjCCatchContext:
+ case DeclaratorContext::CXXCatchContext:
+ case DeclaratorContext::ObjCCatchContext:
Error = 7; // Exception declaration
break;
- case Declarator::TemplateParamContext:
+ case DeclaratorContext::TemplateParamContext:
if (isa<DeducedTemplateSpecializationType>(Deduced))
Error = 19; // Template parameter
else if (!SemaRef.getLangOpts().CPlusPlus17)
Error = 8; // Template parameter (until C++17)
break;
- case Declarator::BlockLiteralContext:
+ case DeclaratorContext::BlockLiteralContext:
Error = 9; // Block literal
break;
- case Declarator::TemplateTypeArgContext:
+ 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;
- case Declarator::AliasDeclContext:
- case Declarator::AliasTemplateContext:
+ case DeclaratorContext::AliasDeclContext:
+ case DeclaratorContext::AliasTemplateContext:
Error = 12; // Type alias
break;
- case Declarator::TrailingReturnContext:
+ case DeclaratorContext::TrailingReturnContext:
+ case DeclaratorContext::TrailingReturnVarContext:
if (!SemaRef.getLangOpts().CPlusPlus14 || !IsCXXAutoType)
Error = 13; // Function return type
break;
- case Declarator::ConversionIdContext:
+ case DeclaratorContext::ConversionIdContext:
if (!SemaRef.getLangOpts().CPlusPlus14 || !IsCXXAutoType)
Error = 14; // conversion-type-id
break;
- case Declarator::FunctionalCastContext:
+ case DeclaratorContext::FunctionalCastContext:
if (isa<DeducedTemplateSpecializationType>(Deduced))
break;
LLVM_FALLTHROUGH;
- case Declarator::TypeNameContext:
+ case DeclaratorContext::TypeNameContext:
Error = 15; // Generic
break;
- case Declarator::FileContext:
- case Declarator::BlockContext:
- case Declarator::ForContext:
- case Declarator::InitStmtContext:
- case Declarator::ConditionContext:
+ case DeclaratorContext::FileContext:
+ case DeclaratorContext::BlockContext:
+ case DeclaratorContext::ForContext:
+ case DeclaratorContext::InitStmtContext:
+ case DeclaratorContext::ConditionContext:
// FIXME: P0091R3 (erroneously) does not permit class template argument
// deduction in conditions, for-init-statements, and other declarations
// that are not simple-declarations.
break;
- case Declarator::CXXNewContext:
+ case DeclaratorContext::CXXNewContext:
// FIXME: P0091R3 does not permit class template argument deduction here,
// but we follow GCC and allow it anyway.
if (!IsCXXAutoType && !isa<DeducedTemplateSpecializationType>(Deduced))
Error = 17; // 'new' type
break;
- case Declarator::KNRTypeListContext:
+ case DeclaratorContext::KNRTypeListContext:
Error = 18; // K&R function parameter
break;
}
@@ -2916,7 +2989,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
}
SourceRange AutoRange = D.getDeclSpec().getTypeSpecTypeLoc();
- if (D.getName().getKind() == UnqualifiedId::IK_ConversionFunctionId)
+ if (D.getName().getKind() == UnqualifiedIdKind::IK_ConversionFunctionId)
AutoRange = D.getName().getSourceRange();
if (Error != -1) {
@@ -2944,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;
@@ -2959,47 +3034,49 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
// or enumeration in a type-specifier-seq.
unsigned DiagID = 0;
switch (D.getContext()) {
- case Declarator::TrailingReturnContext:
+ 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");
break;
- case Declarator::FileContext:
- case Declarator::MemberContext:
- case Declarator::BlockContext:
- case Declarator::ForContext:
- case Declarator::InitStmtContext:
- case Declarator::BlockLiteralContext:
- case Declarator::LambdaExprContext:
+ case DeclaratorContext::FileContext:
+ case DeclaratorContext::MemberContext:
+ case DeclaratorContext::BlockContext:
+ case DeclaratorContext::ForContext:
+ case DeclaratorContext::InitStmtContext:
+ case DeclaratorContext::BlockLiteralContext:
+ case DeclaratorContext::LambdaExprContext:
// C++11 [dcl.type]p3:
// A type-specifier-seq shall not define a class or enumeration unless
// it appears in the type-id of an alias-declaration (7.1.3) that is not
// the declaration of a template-declaration.
- case Declarator::AliasDeclContext:
+ case DeclaratorContext::AliasDeclContext:
break;
- case Declarator::AliasTemplateContext:
+ case DeclaratorContext::AliasTemplateContext:
DiagID = diag::err_type_defined_in_alias_template;
break;
- case Declarator::TypeNameContext:
- case Declarator::FunctionalCastContext:
- case Declarator::ConversionIdContext:
- case Declarator::TemplateParamContext:
- case Declarator::CXXNewContext:
- case Declarator::CXXCatchContext:
- case Declarator::ObjCCatchContext:
- case Declarator::TemplateTypeArgContext:
+ case DeclaratorContext::TypeNameContext:
+ case DeclaratorContext::FunctionalCastContext:
+ case DeclaratorContext::ConversionIdContext:
+ case DeclaratorContext::TemplateParamContext:
+ case DeclaratorContext::CXXNewContext:
+ case DeclaratorContext::CXXCatchContext:
+ case DeclaratorContext::ObjCCatchContext:
+ case DeclaratorContext::TemplateArgContext:
+ case DeclaratorContext::TemplateTypeArgContext:
DiagID = diag::err_type_defined_in_type_specifier;
break;
- case Declarator::PrototypeContext:
- case Declarator::LambdaExprParameterContext:
- case Declarator::ObjCParameterContext:
- case Declarator::ObjCResultContext:
- case Declarator::KNRTypeListContext:
+ case DeclaratorContext::PrototypeContext:
+ case DeclaratorContext::LambdaExprParameterContext:
+ case DeclaratorContext::ObjCParameterContext:
+ case DeclaratorContext::ObjCResultContext:
+ case DeclaratorContext::KNRTypeListContext:
// C++ [dcl.fct]p6:
// Types shall not be defined in return or parameter types.
DiagID = diag::err_type_defined_in_param_type;
break;
- case Declarator::ConditionContext:
+ case DeclaratorContext::ConditionContext:
// C++ 6.4p2:
// The type-specifier-seq shall not contain typedef and shall not declare
// a new class or enumeration.
@@ -3048,7 +3125,7 @@ static void warnAboutAmbiguousFunction(Sema &S, Declarator &D,
// Inside a condition, a direct initializer is not permitted. We allow one to
// be parsed in order to give better diagnostics in condition parsing.
- if (D.getContext() == Declarator::ConditionContext)
+ if (D.getContext() == DeclaratorContext::ConditionContext)
return;
SourceRange ParenRange(DeclType.Loc, DeclType.EndLoc);
@@ -3164,7 +3241,7 @@ static void warnAboutRedundantParens(Sema &S, Declarator &D, QualType T) {
case DeclaratorChunk::Function:
// In a new-type-id, function chunks require parentheses.
- if (D.getContext() == Declarator::CXXNewContext)
+ if (D.getContext() == DeclaratorContext::CXXNewContext)
return;
// FIXME: "A(f())" deserves a vexing-parse warning, not just a
// redundant-parens warning, but we don't know whether the function
@@ -3237,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;
}
@@ -3282,7 +3358,7 @@ getCCForDeclaratorChunk(Sema &S, Declarator &D,
// in a member pointer.
IsCXXInstanceMethod =
D.getTypeObject(I).Kind == DeclaratorChunk::MemberPointer;
- } else if (D.getContext() == Declarator::LambdaExprContext) {
+ } else if (D.getContext() == DeclaratorContext::LambdaExprContext) {
// This can only be a call operator for a lambda, which is an instance
// method.
IsCXXInstanceMethod = true;
@@ -3307,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;
}
@@ -3360,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;
}
@@ -3779,8 +3853,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Does this declaration declare a typedef-name?
bool IsTypedefName =
D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef ||
- D.getContext() == Declarator::AliasDeclContext ||
- D.getContext() == Declarator::AliasTemplateContext;
+ D.getContext() == DeclaratorContext::AliasDeclContext ||
+ D.getContext() == DeclaratorContext::AliasTemplateContext;
// Does T refer to a function type with a cv-qualifier or a ref-qualifier?
bool IsQualifiedFunction = T->isFunctionProtoType() &&
@@ -3909,14 +3983,15 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
} else {
bool isFunctionOrMethod = false;
switch (auto context = state.getDeclarator().getContext()) {
- case Declarator::ObjCParameterContext:
- case Declarator::ObjCResultContext:
- case Declarator::PrototypeContext:
- case Declarator::TrailingReturnContext:
+ case DeclaratorContext::ObjCParameterContext:
+ case DeclaratorContext::ObjCResultContext:
+ case DeclaratorContext::PrototypeContext:
+ case DeclaratorContext::TrailingReturnContext:
+ case DeclaratorContext::TrailingReturnVarContext:
isFunctionOrMethod = true;
LLVM_FALLTHROUGH;
- case Declarator::MemberContext:
+ case DeclaratorContext::MemberContext:
if (state.getDeclarator().isObjCIvar() && !isFunctionOrMethod) {
complainAboutMissingNullability = CAMN_No;
break;
@@ -3930,8 +4005,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
LLVM_FALLTHROUGH;
- case Declarator::FileContext:
- case Declarator::KNRTypeListContext: {
+ case DeclaratorContext::FileContext:
+ case DeclaratorContext::KNRTypeListContext: {
complainAboutMissingNullability = CAMN_Yes;
// Nullability inference depends on the type and declarator.
@@ -3947,8 +4022,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
if (inAssumeNonNullRegion) {
complainAboutInferringWithinChunk = wrappingKind;
inferNullability = NullabilityKind::NonNull;
- inferNullabilityCS = (context == Declarator::ObjCParameterContext ||
- context == Declarator::ObjCResultContext);
+ inferNullabilityCS =
+ (context == DeclaratorContext::ObjCParameterContext ||
+ context == DeclaratorContext::ObjCResultContext);
}
break;
@@ -3965,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;
}
@@ -3988,26 +4060,27 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
break;
}
- case Declarator::ConversionIdContext:
+ case DeclaratorContext::ConversionIdContext:
complainAboutMissingNullability = CAMN_Yes;
break;
- case Declarator::AliasDeclContext:
- case Declarator::AliasTemplateContext:
- case Declarator::BlockContext:
- case Declarator::BlockLiteralContext:
- case Declarator::ConditionContext:
- case Declarator::CXXCatchContext:
- case Declarator::CXXNewContext:
- case Declarator::ForContext:
- case Declarator::InitStmtContext:
- case Declarator::LambdaExprContext:
- case Declarator::LambdaExprParameterContext:
- case Declarator::ObjCCatchContext:
- case Declarator::TemplateParamContext:
- case Declarator::TemplateTypeArgContext:
- case Declarator::TypeNameContext:
- case Declarator::FunctionalCastContext:
+ case DeclaratorContext::AliasDeclContext:
+ case DeclaratorContext::AliasTemplateContext:
+ case DeclaratorContext::BlockContext:
+ case DeclaratorContext::BlockLiteralContext:
+ case DeclaratorContext::ConditionContext:
+ case DeclaratorContext::CXXCatchContext:
+ case DeclaratorContext::CXXNewContext:
+ case DeclaratorContext::ForContext:
+ case DeclaratorContext::InitStmtContext:
+ case DeclaratorContext::LambdaExprContext:
+ case DeclaratorContext::LambdaExprParameterContext:
+ case DeclaratorContext::ObjCCatchContext:
+ case DeclaratorContext::TemplateParamContext:
+ case DeclaratorContext::TemplateArgContext:
+ case DeclaratorContext::TemplateTypeArgContext:
+ case DeclaratorContext::TypeNameContext:
+ case DeclaratorContext::FunctionalCastContext:
// Don't infer in these contexts.
break;
}
@@ -4032,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;
@@ -4046,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()
@@ -4112,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();
@@ -4152,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) {
@@ -4174,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);
@@ -4243,7 +4314,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// array type, ...
if (ASM == ArrayType::Static || ATI.TypeQuals) {
if (!(D.isPrototypeContext() ||
- D.getContext() == Declarator::KNRTypeListContext)) {
+ D.getContext() == DeclaratorContext::KNRTypeListContext)) {
S.Diag(DeclType.Loc, diag::err_array_static_outside_prototype) <<
(ASM == ArrayType::Static ? "'static'" : "type qualifier");
// Remove the 'static' and the type qualifiers.
@@ -4267,7 +4338,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
const AutoType *AT = T->getContainedAutoType();
// Allow arrays of auto if we are a generic lambda parameter.
// i.e. [](auto (&array)[5]) { return array[0]; }; OK
- if (AT && D.getContext() != Declarator::LambdaExprParameterContext) {
+ if (AT &&
+ D.getContext() != DeclaratorContext::LambdaExprParameterContext) {
// We've already diagnosed this for decltype(auto).
if (!AT->isDecltypeAuto())
S.Diag(DeclType.Loc, diag::err_illegal_decl_array_of_auto)
@@ -4319,14 +4391,14 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
<< T << D.getSourceRange();
D.setInvalidType(true);
} else if (D.getName().getKind() ==
- UnqualifiedId::IK_DeductionGuideName) {
+ UnqualifiedIdKind::IK_DeductionGuideName) {
if (T != Context.DependentTy) {
S.Diag(D.getDeclSpec().getLocStart(),
diag::err_deduction_guide_with_complex_decl)
<< D.getSourceRange();
D.setInvalidType(true);
}
- } else if (D.getContext() != Declarator::LambdaExprContext &&
+ } else if (D.getContext() != DeclaratorContext::LambdaExprContext &&
(T.hasQualifiers() || !isa<AutoType>(T) ||
cast<AutoType>(T)->getKeyword() !=
AutoTypeKeyword::Auto)) {
@@ -4347,12 +4419,13 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// C99 6.7.5.3p1: The return type may not be a function or array type.
// For conversion functions, we'll diagnose this particular error later.
if (!D.isInvalidType() && (T->isArrayType() || T->isFunctionType()) &&
- (D.getName().getKind() != UnqualifiedId::IK_ConversionFunctionId)) {
+ (D.getName().getKind() !=
+ UnqualifiedIdKind::IK_ConversionFunctionId)) {
unsigned diagID = diag::err_func_returning_array_function;
// Last processing chunk in block context means this function chunk
// represents the block.
if (chunkIndex == 0 &&
- D.getContext() == Declarator::BlockLiteralContext)
+ D.getContext() == DeclaratorContext::BlockLiteralContext)
diagID = diag::err_block_returning_array_function;
S.Diag(DeclType.Loc, diagID) << T->isFunctionType() << T;
T = Context.IntTy;
@@ -4446,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;
}
}
@@ -4470,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();
@@ -4490,15 +4561,16 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
if (IsTypedefName && FTI.getExceptionSpecType() && !LangOpts.CPlusPlus17)
S.Diag(FTI.getExceptionSpecLocBeg(),
diag::err_exception_spec_in_typedef)
- << (D.getContext() == Declarator::AliasDeclContext ||
- D.getContext() == Declarator::AliasTemplateContext);
+ << (D.getContext() == DeclaratorContext::AliasDeclContext ||
+ D.getContext() == DeclaratorContext::AliasTemplateContext);
// If we see "T var();" or "T var(T());" at block scope, it is probably
// an attempt to initialize a variable, not a function declaration.
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) {
@@ -4508,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
@@ -4652,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;
}
@@ -4675,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.
@@ -4731,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;
}
}
@@ -4742,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
@@ -4763,7 +4824,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
break;
case DeclaratorChunk::Function: {
const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
- if (FTI.NumParams == 0)
+ if (FTI.NumParams == 0 && !FTI.isVariadic)
S.Diag(DeclType.Loc, diag::warn_strict_prototypes)
<< IsBlock
<< FixItHint::CreateInsertion(FTI.getRParenLoc(), "void");
@@ -4791,11 +4852,11 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Core issue 547 also allows cv-qualifiers on function types that are
// top-level template type arguments.
enum { NonMember, Member, DeductionGuide } Kind = NonMember;
- if (D.getName().getKind() == UnqualifiedId::IK_DeductionGuideName)
+ if (D.getName().getKind() == UnqualifiedIdKind::IK_DeductionGuideName)
Kind = DeductionGuide;
else if (!D.getCXXScopeSpec().isSet()) {
- if ((D.getContext() == Declarator::MemberContext ||
- D.getContext() == Declarator::LambdaExprContext) &&
+ if ((D.getContext() == DeclaratorContext::MemberContext ||
+ D.getContext() == DeclaratorContext::LambdaExprContext) &&
!D.getDeclSpec().isFriendSpecified())
Kind = Member;
} else {
@@ -4824,7 +4885,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
!(Kind == Member &&
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) &&
!IsTypedefName &&
- D.getContext() != Declarator::TemplateTypeArgContext) {
+ D.getContext() != DeclaratorContext::TemplateArgContext &&
+ D.getContext() != DeclaratorContext::TemplateTypeArgContext) {
SourceLocation Loc = D.getLocStart();
SourceRange RemovalRange;
unsigned I;
@@ -4841,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();
}
@@ -4890,8 +4952,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// only be used in a parameter-declaration. Such a parameter-declaration
// is a parameter pack (14.5.3). [...]
switch (D.getContext()) {
- case Declarator::PrototypeContext:
- case Declarator::LambdaExprParameterContext:
+ case DeclaratorContext::PrototypeContext:
+ case DeclaratorContext::LambdaExprParameterContext:
// C++0x [dcl.fct]p13:
// [...] When it is part of a parameter-declaration-clause, the
// parameter pack is a function parameter pack (14.5.3). The type T
@@ -4910,7 +4972,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
T = Context.getPackExpansionType(T, None);
}
break;
- case Declarator::TemplateParamContext:
+ case DeclaratorContext::TemplateParamContext:
// C++0x [temp.param]p15:
// If a template-parameter is a [...] is a parameter-declaration that
// declares a parameter pack (8.3.5), then the template-parameter is a
@@ -4928,27 +4990,31 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
: diag::ext_variadic_templates);
break;
- case Declarator::FileContext:
- case Declarator::KNRTypeListContext:
- case Declarator::ObjCParameterContext: // FIXME: special diagnostic here?
- case Declarator::ObjCResultContext: // FIXME: special diagnostic here?
- case Declarator::TypeNameContext:
- case Declarator::FunctionalCastContext:
- case Declarator::CXXNewContext:
- case Declarator::AliasDeclContext:
- case Declarator::AliasTemplateContext:
- case Declarator::MemberContext:
- case Declarator::BlockContext:
- case Declarator::ForContext:
- case Declarator::InitStmtContext:
- case Declarator::ConditionContext:
- case Declarator::CXXCatchContext:
- case Declarator::ObjCCatchContext:
- case Declarator::BlockLiteralContext:
- case Declarator::LambdaExprContext:
- case Declarator::ConversionIdContext:
- case Declarator::TrailingReturnContext:
- case Declarator::TemplateTypeArgContext:
+ case DeclaratorContext::FileContext:
+ case DeclaratorContext::KNRTypeListContext:
+ case DeclaratorContext::ObjCParameterContext: // FIXME: special diagnostic
+ // here?
+ case DeclaratorContext::ObjCResultContext: // FIXME: special diagnostic
+ // here?
+ case DeclaratorContext::TypeNameContext:
+ case DeclaratorContext::FunctionalCastContext:
+ case DeclaratorContext::CXXNewContext:
+ case DeclaratorContext::AliasDeclContext:
+ case DeclaratorContext::AliasTemplateContext:
+ case DeclaratorContext::MemberContext:
+ case DeclaratorContext::BlockContext:
+ case DeclaratorContext::ForContext:
+ case DeclaratorContext::InitStmtContext:
+ case DeclaratorContext::ConditionContext:
+ case DeclaratorContext::CXXCatchContext:
+ case DeclaratorContext::ObjCCatchContext:
+ case DeclaratorContext::BlockLiteralContext:
+ 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.
S.Diag(D.getEllipsisLoc(),
@@ -5003,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) {
@@ -5025,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) {
@@ -5101,110 +5164,91 @@ 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;
}
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.
@@ -5212,6 +5256,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;
@@ -5222,7 +5285,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) {
@@ -5394,7 +5457,7 @@ namespace {
}
void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
- fillAttributedTypeLoc(TL, Chunk.getAttrs());
+ fillAttributedTypeLoc(TL, Chunk.getAttrs(), ParsedAttributesView{});
}
void VisitAdjustedTypeLoc(AdjustedTypeLoc TL) {
// nothing
@@ -5527,19 +5590,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.
///
@@ -5552,7 +5619,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)) {
@@ -5576,7 +5642,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();
}
@@ -5601,7 +5668,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
@@ -5637,9 +5704,9 @@ TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
// to apply them to the actual parameter declaration.
// Likewise, we don't want to do this for alias declarations, because
// we are actually going to build a declaration from this eventually.
- if (D.getContext() != Declarator::ObjCParameterContext &&
- D.getContext() != Declarator::AliasDeclContext &&
- D.getContext() != Declarator::AliasTemplateContext)
+ if (D.getContext() != DeclaratorContext::ObjCParameterContext &&
+ D.getContext() != DeclaratorContext::AliasDeclContext &&
+ D.getContext() != DeclaratorContext::AliasTemplateContext)
checkUnusedDeclAttributes(D);
if (getLangOpts().CPlusPlus) {
@@ -5668,14 +5735,6 @@ QualType Sema::BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace,
SourceLocation AttrLoc) {
if (!AddrSpace->isValueDependent()) {
- // If this type is already address space qualified, reject it.
- // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "No type shall be qualified
- // by qualifiers for two or more different address spaces."
- if (T.getAddressSpace() != LangAS::Default) {
- Diag(AttrLoc, diag::err_attribute_address_multiple_qualifiers);
- return QualType();
- }
-
llvm::APSInt addrSpace(32);
if (!AddrSpace->isIntegerConstantExpr(addrSpace, Context)) {
Diag(AttrLoc, diag::err_attribute_argument_type)
@@ -5706,6 +5765,20 @@ 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);
}
@@ -5726,16 +5799,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()) {
@@ -5745,7 +5809,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) {
@@ -5784,20 +5848,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);
}
}
@@ -5837,8 +5916,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()) {
@@ -5867,7 +5945,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)
@@ -6022,8 +6101,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();
@@ -6215,11 +6293,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) {
@@ -6236,16 +6313,16 @@ 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;
@@ -6270,10 +6347,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);
@@ -6424,15 +6509,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:
@@ -6447,15 +6532,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
@@ -6488,8 +6572,8 @@ static bool distributeNullabilityTypeAttr(TypeProcessingState &state,
" " + attr.getName()->getName().str() + " ");
}
- moveAttrFromListToList(attr, state.getCurrentAttrListRef(),
- chunk.getAttrListRef());
+ moveAttrFromListToList(attr, state.getCurrentAttributes(),
+ chunk.getAttrs());
return true;
};
@@ -6528,28 +6612,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.
@@ -6562,15 +6646,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!");
@@ -6578,15 +6662,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.
@@ -6601,7 +6684,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.
@@ -6625,8 +6708,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.
@@ -6639,7 +6722,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;
@@ -6796,7 +6900,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) {
@@ -6805,58 +6909,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) {
@@ -6945,9 +7026,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();
@@ -6993,7 +7073,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())) {
@@ -7033,12 +7113,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.
//
@@ -7066,7 +7146,7 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State,
IsFuncReturnType || IsFuncType ||
// Do not deduce addr space for member types of struct, except the pointee
// type of a pointer member type.
- (D.getContext() == Declarator::MemberContext && !IsPointee) ||
+ (D.getContext() == DeclaratorContext::MemberContext && !IsPointee) ||
// Do not deduce addr space for types used to define a typedef and the
// typedef itself, except the pointee type of a pointer type which is used
// to define the typedef.
@@ -7083,8 +7163,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:
@@ -7098,7 +7179,7 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State,
if (IsPointee) {
ImpAddr = LangAS::opencl_generic;
} else {
- if (D.getContext() == Declarator::FileContext) {
+ if (D.getContext() == DeclaratorContext::FileContext) {
ImpAddr = LangAS::opencl_global;
} else {
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static ||
@@ -7114,16 +7195,18 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State,
}
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())
@@ -7131,14 +7214,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
@@ -7159,27 +7247,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;
@@ -7188,25 +7276,25 @@ 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;
@@ -7245,7 +7333,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:
@@ -7331,7 +7419,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
@@ -7368,7 +7456,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
@@ -7407,12 +7495,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
@@ -7482,7 +7571,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;
@@ -7512,7 +7601,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.
@@ -7523,11 +7612,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());
}
@@ -7551,10 +7646,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;
@@ -7683,7 +7786,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!
///
@@ -7697,7 +7800,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
@@ -7741,6 +7844,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
@@ -7784,7 +7894,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;
@@ -7795,10 +7906,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;
@@ -7809,7 +7922,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) {
@@ -7845,11 +7958,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)) {
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 96969ea87a13..3b3953991000 100644
--- a/lib/Sema/TreeTransform.h
+++ b/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,7 +1808,7 @@ 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.
@@ -1809,7 +1819,7 @@ public:
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,
@@ -3038,7 +3036,7 @@ public:
}
- /// \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();
@@ -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>
@@ -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/lib/Sema/TypeLocBuilder.h b/lib/Sema/TypeLocBuilder.h
index 9c77045d2e12..a088fe9de667 100644
--- a/lib/Sema/TypeLocBuilder.h
+++ b/lib/Sema/TypeLocBuilder.h
@@ -83,7 +83,7 @@ class TypeLocBuilder {
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
@@ -112,7 +112,7 @@ 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
@@ -132,7 +132,7 @@ 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
diff --git a/lib/Serialization/ASTCommon.cpp b/lib/Serialization/ASTCommon.cpp
index 9c6f03cd0bb7..da482717f450 100644
--- a/lib/Serialization/ASTCommon.cpp
+++ b/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/lib/Serialization/ASTCommon.h b/lib/Serialization/ASTCommon.h
index 6aca453bbb89..12e26c1fc2b9 100644
--- a/lib/Serialization/ASTCommon.h
+++ b/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/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 4ed822e04f6c..9a3b9e1da39a 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/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,7 +2626,9 @@ 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.
@@ -3215,6 +3232,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");
@@ -3648,7 +3683,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 +3836,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 +4103,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 +4594,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 +4620,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 +4826,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 +4997,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 +5015,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)
@@ -5026,6 +5063,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 +5190,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 +5223,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 +5427,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 +5528,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 +5631,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 +5645,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 +5669,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 +5783,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 +5805,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 +5849,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 +5857,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 +6026,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 +6046,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 +6201,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 +6371,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 +6420,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 +6562,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 +6762,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 +6777,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 +6855,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 +6951,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 +7395,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 +7588,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 +7891,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 +8045,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 +8068,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 +8307,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 +8484,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 +8843,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 +9064,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 +9073,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 +9128,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 +9142,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 +9193,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 +9201,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 +9390,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 +9415,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 +9443,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 +9480,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 +9572,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 +9602,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 +9968,7 @@ void ASTReader::diagnoseOdrViolations() {
TypeDef,
Var,
Friend,
+ FunctionTemplate,
Other
} FirstDiffType = Other,
SecondDiffType = Other;
@@ -9798,6 +10006,8 @@ void ASTReader::diagnoseOdrViolations() {
return Var;
case Decl::Friend:
return Friend;
+ case Decl::FunctionTemplate:
+ return FunctionTemplate;
}
};
@@ -9884,7 +10094,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 +10107,7 @@ void ASTReader::diagnoseOdrViolations() {
FieldDifferentInitializers,
MethodName,
MethodDeleted,
+ MethodDefaulted,
MethodVirtual,
MethodStatic,
MethodVolatile,
@@ -9907,6 +10118,11 @@ void ASTReader::diagnoseOdrViolations() {
MethodParameterName,
MethodParameterSingleDefaultArgument,
MethodParameterDifferentDefaultArgument,
+ MethodNoTemplateArguments,
+ MethodDifferentNumberTemplateArguments,
+ MethodDifferentTemplateArgument,
+ MethodSingleBody,
+ MethodDifferentBody,
TypedefName,
TypedefType,
VarName,
@@ -9917,6 +10133,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 +10356,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 +10370,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 +10566,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 +10839,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 +11317,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/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index efbaf92a849a..7e2c4829b14c 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/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).
@@ -523,8 +571,8 @@ void ASTDeclReader::VisitDecl(Decl *D) {
LexicalDCIDForTemplateParmDecl);
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
@@ -667,7 +715,7 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitTagDecl(TagDecl *TD) {
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,7 +1715,7 @@ 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_This:
@@ -1636,7 +1724,7 @@ void ASTDeclReader::ReadCXXDefinitionData(
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
@@ -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)
@@ -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");
@@ -3326,7 +3482,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 +3491,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 +3513,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 +3529,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;
@@ -3639,7 +3797,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,7 +3813,7 @@ 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() ||
@@ -3706,7 +3864,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 +3921,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,13 +3970,14 @@ 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;
@@ -3868,10 +4027,8 @@ namespace {
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())
@@ -3920,7 +4077,8 @@ namespace {
return true;
}
};
-} // end anonymous namespace
+
+} // namespace
void ASTReader::loadObjCCategories(serialization::GlobalDeclID ID,
ObjCInterfaceDecl *D,
@@ -3973,13 +4131,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 +4146,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 +4163,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 +4180,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 +4195,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 +4212,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 +4239,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 +4258,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 +4336,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/lib/Serialization/ASTReaderInternals.h b/lib/Serialization/ASTReaderInternals.h
index 2b92ae65ea84..b5a1493a4f7e 100644
--- a/lib/Serialization/ASTReaderInternals.h
+++ b/lib/Serialization/ASTReaderInternals.h
@@ -40,7 +40,7 @@ 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;
@@ -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
@@ -156,7 +156,7 @@ public:
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;
@@ -182,12 +182,12 @@ public:
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;
@@ -229,11 +229,11 @@ public:
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
@@ -280,7 +280,7 @@ public:
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>;
diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp
index 6163b811c769..d9d780b25b31 100644
--- a/lib/Serialization/ASTReaderStmt.cpp
+++ b/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;
@@ -2393,7 +2448,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 +2542,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 +2584,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 +2634,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 +2677,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 +2687,7 @@ void OMPClauseReader::VisitOMPIsDevicePtrClause(OMPIsDevicePtrClause *C) {
//===----------------------------------------------------------------------===//
// OpenMP Directives.
//===----------------------------------------------------------------------===//
+
void ASTStmtReader::VisitOMPExecutableDirective(OMPExecutableDirective *E) {
E->setLocStart(ReadSourceLocation());
E->setLocEnd(ReadSourceLocation());
@@ -2917,6 +2973,7 @@ void ASTStmtReader::VisitOMPTargetUpdateDirective(OMPTargetUpdateDirective *D) {
Record.skipInts(1);
VisitOMPExecutableDirective(D);
}
+
void ASTStmtReader::VisitOMPDistributeParallelForDirective(
OMPDistributeParallelForDirective *D) {
VisitOMPLoopDirective(D);
@@ -3025,7 +3082,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 +3310,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 +3438,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 +3834,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 +3930,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 +3978,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 +4130,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/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index 1e72ced2ee36..1a8d806e9d24 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/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/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp
index bb72a3b383ea..77e578f6bc57 100644
--- a/lib/Serialization/ASTWriterDecl.cpp
+++ b/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,7 +265,8 @@ 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
@@ -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) {
@@ -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());
@@ -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());
@@ -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;
@@ -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));
@@ -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,6 +2243,9 @@ 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");
diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp
index c5f4495d2f01..3efb6482dd42 100644
--- a/lib/Serialization/ASTWriterStmt.cpp
+++ b/lib/Serialization/ASTWriterStmt.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Implements serialization for Statements and Expressions.
+/// Implements serialization for Statements and Expressions.
///
//===----------------------------------------------------------------------===//
@@ -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();
@@ -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;
}
@@ -2675,7 +2685,7 @@ 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;
@@ -2719,7 +2729,7 @@ void ASTWriter::WriteSubStmt(Stmt *S) {
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,
diff --git a/lib/Serialization/GlobalModuleIndex.cpp b/lib/Serialization/GlobalModuleIndex.cpp
index 20c114297b99..3733638d2977 100644
--- a/lib/Serialization/GlobalModuleIndex.cpp
+++ b/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/lib/Serialization/Module.cpp b/lib/Serialization/Module.cpp
index 5a44d26fe399..f0ada809ad99 100644
--- a/lib/Serialization/Module.cpp
+++ b/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;
@@ -32,7 +36,8 @@ dumpLocalRemap(StringRef Name,
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();
I != IEnd; ++I) {
diff --git a/lib/Serialization/MultiOnDiskHashTable.h b/lib/Serialization/MultiOnDiskHashTable.h
index 44d1616a0110..ded7cd146449 100644
--- a/lib/Serialization/MultiOnDiskHashTable.h
+++ b/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/lib/StaticAnalyzer/Checkers/AllocationDiagnostics.h b/lib/StaticAnalyzer/Checkers/AllocationDiagnostics.h
index 048418ef62db..62b7fab0739a 100644
--- a/lib/StaticAnalyzer/Checkers/AllocationDiagnostics.h
+++ b/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/lib/StaticAnalyzer/Checkers/AllocationState.h b/lib/StaticAnalyzer/Checkers/AllocationState.h
new file mode 100644
index 000000000000..a6908bd7a651
--- /dev/null
+++ b/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/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp b/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
index 90d5c0e36a47..e4cdc500de6a 100644
--- a/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp b/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp
index 64c30e7a82c1..aadc6bac8d00 100644
--- a/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp b/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
index b944f90539d4..933380d494a4 100644
--- a/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
index 371187747f03..7d6358acbbac 100644
--- a/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp b/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
index 097d4198800d..0e781d08e24c 100644
--- a/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/CMakeLists.txt b/lib/StaticAnalyzer/Checkers/CMakeLists.txt
index 7ab9c6114eae..5bb4770b5675 100644
--- a/lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ b/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -37,9 +37,11 @@ add_clang_library(clangStaticAnalyzerCheckers
DynamicTypeChecker.cpp
ExprInspectionChecker.cpp
FixedAddressChecker.cpp
+ GCDAntipatternChecker.cpp
GenericTaintChecker.cpp
GTestChecker.cpp
IdenticalExprChecker.cpp
+ InnerPointerChecker.cpp
IteratorChecker.cpp
IvarInvalidationChecker.cpp
LLVMConventionsChecker.cpp
@@ -49,6 +51,7 @@ add_clang_library(clangStaticAnalyzerCheckers
MallocChecker.cpp
MallocOverflowSecurityChecker.cpp
MallocSizeofChecker.cpp
+ MmapWriteExecChecker.cpp
MisusedMovedObjectChecker.cpp
MPI-Checker/MPIBugReporter.cpp
MPI-Checker/MPIChecker.cpp
@@ -61,6 +64,7 @@ add_clang_library(clangStaticAnalyzerCheckers
NullabilityChecker.cpp
NumberObjectConversionChecker.cpp
ObjCAtSyncChecker.cpp
+ ObjCAutoreleaseWriteChecker.cpp
ObjCContainersASTChecker.cpp
ObjCContainersChecker.cpp
ObjCMissingSuperCallChecker.cpp
@@ -75,6 +79,7 @@ add_clang_library(clangStaticAnalyzerCheckers
RetainCountChecker.cpp
ReturnPointerRangeChecker.cpp
ReturnUndefChecker.cpp
+ RunLoopAutoreleaseLeakChecker.cpp
SimpleStreamChecker.cpp
StackAddrEscapeChecker.cpp
StdLibraryFunctionsChecker.cpp
@@ -82,11 +87,13 @@ add_clang_library(clangStaticAnalyzerCheckers
TaintTesterChecker.cpp
TestAfterDivZeroChecker.cpp
TraversalChecker.cpp
+ TrustNonnullChecker.cpp
UndefBranchChecker.cpp
UndefCapturedBlockVarChecker.cpp
UndefResultChecker.cpp
UndefinedArraySubscriptChecker.cpp
UndefinedAssignmentChecker.cpp
+ UninitializedObjectChecker.cpp
UnixAPIChecker.cpp
UnreachableCodeChecker.cpp
VforkChecker.cpp
diff --git a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
index 28ad7e9e5071..278452ec994a 100644
--- a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ b/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,79 @@ 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);
+ 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 +658,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 +758,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 +766,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 +805,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 +817,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 +867,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 +1003,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 +1489,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 +1523,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 +1575,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 +1652,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 +1787,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 +1810,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 +1821,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 +1833,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 +1845,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 +1866,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 +1895,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 +1904,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 +1913,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 +1958,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 +1977,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 +2012,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 +2026,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 +2078,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 +2106,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 +2128,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 +2145,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 +2178,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 +2230,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 +2301,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 +2314,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 +2328,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 +2343,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 +2367,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 +2393,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 +2412,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/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp b/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
index 4b5e97b69295..8b4aa857e775 100644
--- a/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp b/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp
index 668e772fe1b3..d1d37c75dfcc 100644
--- a/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp b/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
index 3e178152d925..059553b21995 100644
--- a/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp b/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
index 65e81315f095..00e903355720 100644
--- a/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp b/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
index 2818c9d9fd4a..f4d2e32cef11 100644
--- a/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp b/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
index 6dbacad7f2ea..202233acffab 100644
--- a/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp b/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
index 95b6c4d3775d..7862a4c25681 100644
--- a/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp b/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
index 9e9939ae25c0..b38992b0e030 100644
--- a/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/DeleteWithNonVirtualDtorChecker.cpp b/lib/StaticAnalyzer/Checkers/DeleteWithNonVirtualDtorChecker.cpp
index e04e2ab2c320..d3489282ab62 100644
--- a/lib/StaticAnalyzer/Checkers/DeleteWithNonVirtualDtorChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp b/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
index 598502305633..bc39c92ea970 100644
--- a/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp b/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp
index 109897be2931..4e4d81cd6714 100644
--- a/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp b/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
index db9179e018a1..126e57645a43 100644
--- a/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp b/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
index 0005ec470d20..8de653c10f7e 100644
--- a/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp b/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
index 3fe89f96a43b..059203fca730 100644
--- a/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp b/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp
new file mode 100644
index 000000000000..5cb51b01f044
--- /dev/null
+++ b/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/lib/StaticAnalyzer/Checkers/GTestChecker.cpp b/lib/StaticAnalyzer/Checkers/GTestChecker.cpp
index f0be41b293e4..3ef95e673b87 100644
--- a/lib/StaticAnalyzer/Checkers/GTestChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp b/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
index 43966656cd8d..899586745a0b 100644
--- a/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp b/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp
index cf57b8dca063..f102ca96a5c1 100644
--- a/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp b/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp
new file mode 100644
index 000000000000..ed877ab34518
--- /dev/null
+++ b/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp
@@ -0,0 +1,252 @@
+//=== 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 whether the function called on the container object is a
+ /// member function that potentially invalidates pointers referring
+ /// to the objects's internal buffer.
+ bool mayInvalidateBuffer(const CallEvent &Call) const;
+
+ /// Record the connection between the symbol returned by c_str() and the
+ /// corresponding string object region in the ProgramState. Mark the symbol
+ /// released if the string object is destroyed.
+ void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
+
+ /// Clean up the ProgramState map.
+ void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
+};
+
+} // end anonymous namespace
+
+// [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:
+//
+// -- TODO: 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."
+//
+bool InnerPointerChecker::mayInvalidateBuffer(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::checkPostCall(const CallEvent &Call,
+ CheckerContext &C) const {
+ const auto *ICall = dyn_cast<CXXInstanceCall>(&Call);
+ if (!ICall)
+ return;
+
+ SVal Obj = ICall->getCXXThisVal();
+ const auto *ObjRegion = dyn_cast_or_null<TypedValueRegion>(Obj.getAsRegion());
+ if (!ObjRegion)
+ return;
+
+ auto *TypeDecl = ObjRegion->getValueType()->getAsCXXRecordDecl();
+ if (TypeDecl->getName() != "basic_string")
+ return;
+
+ ProgramStateRef State = C.getState();
+
+ 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;
+ }
+
+ if (mayInvalidateBuffer(Call)) {
+ if (const PtrSet *PS = State->get<RawPtrMap>(ObjRegion)) {
+ // Mark all pointer symbols associated with the deleted object released.
+ 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>(ObjRegion);
+ C.addTransition(State);
+ return;
+ }
+ }
+}
+
+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/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp b/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
index 0f9b749506fa..56c250cd1678 100644
--- a/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
+++ b/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,
@@ -255,6 +292,7 @@ const ContainerData *getContainerData(ProgramStateRef State,
ProgramStateRef setContainerData(ProgramStateRef State, const MemRegion *Cont,
const ContainerData &CData);
bool isOutOfRange(ProgramStateRef State, const IteratorPosition &Pos);
+bool isZero(ProgramStateRef State, const NonLoc &Val);
} // namespace
IteratorChecker::IteratorChecker() {
@@ -272,6 +310,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 +354,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 +399,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 +440,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
@@ -471,13 +621,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 +842,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 +861,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 +877,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 +936,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 +959,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 +1031,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 +1047,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 +1070,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 +1160,39 @@ 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 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 +1204,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 +1221,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 +1258,4 @@ bool compare(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2,
}
REGISTER_CHECKER(IteratorRangeChecker)
+
diff --git a/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp b/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp
index 8076ca09591f..2fb627184eb9 100644
--- a/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp b/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
index 655ce33390c9..849b1193c042 100644
--- a/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.h b/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.h
index 0ee91cca4793..40eb0631d7c5 100644
--- a/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.h
+++ b/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/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp b/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
index f8473dbd7647..b8ef6701c0df 100644
--- a/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index 851114004b96..8f07f413e81f 100644
--- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/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,
@@ -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;
@@ -253,20 +258,20 @@ private:
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,
@@ -337,7 +353,7 @@ private:
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);
}
@@ -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.
@@ -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,133 @@ 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();
+ }
+ 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 +3004,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 +3049,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>();
@@ -2900,8 +3073,13 @@ void ento::registerNewDeleteLeaksChecker(CheckerManager &mgr) {
mgr.getCurrentCheckName();
// We currently treat NewDeleteLeaks checker as a subchecker of NewDelete
// checker.
- if (!checker->ChecksEnabled[MallocChecker::CK_NewDeleteChecker])
+ if (!checker->ChecksEnabled[MallocChecker::CK_NewDeleteChecker]) {
checker->ChecksEnabled[MallocChecker::CK_NewDeleteChecker] = true;
+ // FIXME: This does not set the correct name, but without this workaround
+ // no name will be set at all.
+ checker->CheckNames[MallocChecker::CK_NewDeleteChecker] =
+ mgr.getCurrentCheckName();
+ }
}
#define REGISTER_CHECKER(name) \
diff --git a/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp b/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp
index 497978f07815..19c1d077afa1 100644
--- a/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp b/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp
new file mode 100644
index 000000000000..5060b0e0a6e0
--- /dev/null
+++ b/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/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp b/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
index 559c75d7a5b0..2bd68b625c1f 100644
--- a/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp b/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
index 6d05159e51b0..01d2c0491b85 100644
--- a/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp b/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp
index 0b4ecb41d20f..6f3180eb839a 100644
--- a/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp b/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
index fa9a317683ba..7d1ca61c97a9 100644
--- a/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp b/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp
index 40e379cb2efc..d1749cfdbe27 100644
--- a/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
index cbaa5c23592d..b7339fe79f69 100644
--- a/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp
new file mode 100644
index 000000000000..81bcda51b8f8
--- /dev/null
+++ b/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/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp
index 58ebf72660b6..fb05ca630b45 100644
--- a/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp
index 32a1adb587bf..d01c6ae6e093 100644
--- a/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
index ffa3a2700616..629520437369 100644
--- a/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp
index 69b19a785938..fcba3b33f3e0 100644
--- a/lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp b/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
index 6c0c53dd64cb..f69f3492edb1 100644
--- a/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp b/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
index 8caf6df4d970..63f82b275ba2 100644
--- a/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp b/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
index 2d33ebc2610d..9aa5348e4c34 100644
--- a/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp b/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
index dab29be1c8fb..10ab952e069b 100644
--- a/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
index e47494a3e90b..2c1e139330d6 100644
--- a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
+++ b/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();
diff --git a/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp b/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
index 19fa0fb193cc..1952715a9b7c 100644
--- a/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp b/lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp
new file mode 100644
index 000000000000..64b61a0213d2
--- /dev/null
+++ b/lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp
@@ -0,0 +1,217 @@
+//=- 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";
+
+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 == 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);
+ 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);
+ if (HasAutoreleasePool && seenBefore(AP, RLR, ME))
+ return;
+
+ if (!HasAutoreleasePool && seenBefore(DeclBody, RLR, ME))
+ 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();
+
+ 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/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp b/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
index 25975628c553..feae9e59b343 100644
--- a/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
+++ b/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 {
@@ -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;
@@ -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/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
index 915514b42133..d77975559e3f 100644
--- a/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp b/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp
index 5268bbf5562e..f4c0edbab3f0 100644
--- a/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp b/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp
index 8ad962875b06..ee185b813611 100644
--- a/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp b/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp
new file mode 100644
index 000000000000..f3d68014224d
--- /dev/null
+++ b/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/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp b/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
index 0a274292aa39..934ee63318fa 100644
--- a/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp b/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
index 17fe8610da06..6a93c10c7644 100644
--- a/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp b/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
index 172ce346f1ba..b9a93bedca2e 100644
--- a/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp b/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
index c3dcf1fac197..2ef6855ba6b7 100644
--- a/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp b/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp
new file mode 100644
index 000000000000..398228a9d887
--- /dev/null
+++ b/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/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
index 7f9a00ff876d..a6b50dc37740 100644
--- a/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp b/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
index 6f21e868b174..dbd12cc9b65a 100644
--- a/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp b/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
index 40217bdee892..2584f2011819 100644
--- a/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
+++ b/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/lib/StaticAnalyzer/Checkers/ValistChecker.cpp b/lib/StaticAnalyzer/Checkers/ValistChecker.cpp
index 06c4ef71d80b..bd657340fcfb 100644
--- a/lib/StaticAnalyzer/Checkers/ValistChecker.cpp
+++ b/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;
@@ -64,13 +63,13 @@ private:
CheckerContext &C) const;
void reportLeakedVALists(const RegionVector &LeakedVALists, StringRef Msg1,
StringRef Msg2, CheckerContext &C, ExplodedNode *N,
- bool ForceReport = false) const;
+ bool ReportUninit = false) const;
void checkVAListStartCall(const CallEvent &Call, CheckerContext &C,
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);
@@ -267,15 +265,19 @@ void ValistChecker::reportUninitializedAccess(const MemRegion *VAList,
void ValistChecker::reportLeakedVALists(const RegionVector &LeakedVALists,
StringRef Msg1, StringRef Msg2,
CheckerContext &C, ExplodedNode *N,
- bool ForceReport) const {
+ bool ReportUninit) const {
if (!(ChecksEnabled[CK_Unterminated] ||
- (ChecksEnabled[CK_Uninitialized] && ForceReport)))
+ (ChecksEnabled[CK_Uninitialized] && ReportUninit)))
return;
for (auto Reg : LeakedVALists) {
if (!BT_leakedvalist) {
- BT_leakedvalist.reset(new BugType(CheckNames[CK_Unterminated],
- "Leaked va_list",
- categories::MemoryError));
+ // FIXME: maybe creating a new check name for this type of bug is a better
+ // solution.
+ BT_leakedvalist.reset(
+ new BugType(CheckNames[CK_Unterminated].getName().empty()
+ ? CheckNames[CK_Uninitialized]
+ : CheckNames[CK_Unterminated],
+ "Leaked va_list", categories::MemoryError));
BT_leakedvalist->setSuppressOnSink(true);
}
@@ -375,7 +377,7 @@ void ValistChecker::checkVAListEndCall(const CallEvent &Call,
std::shared_ptr<PathDiagnosticPiece> ValistChecker::ValistBugVisitor::VisitNode(
const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC,
- BugReport &BR) {
+ BugReport &) {
ProgramStateRef State = N->getState();
ProgramStateRef StatePrev = PrevN->getState();
diff --git a/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp b/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
index c5010f53785a..5b602468cdd4 100644
--- a/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
+++ b/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/lib/StaticAnalyzer/Core/AnalysisManager.cpp b/lib/StaticAnalyzer/Core/AnalysisManager.cpp
index 1cc08f0d9fe7..dc0d3ec8493a 100644
--- a/lib/StaticAnalyzer/Core/AnalysisManager.cpp
+++ b/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/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
index 48e3e22af04a..9b2dc32e0600 100644
--- a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
+++ b/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/lib/StaticAnalyzer/Core/BasicValueFactory.cpp b/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
index ec7a7e9e4b1c..db4c1432ccc3 100644
--- a/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
+++ b/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/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp
index dc284888eb03..f990eb6a058d 100644
--- a/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/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,13 +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) {
- assert((*I)->getLocation().asLocation().isValid());
+ if (!Call)
continue;
- }
if (LastCallLocation) {
bool CallerIsImplicit = hasImplicitBody(Call->getCaller());
@@ -314,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);
@@ -353,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) {
@@ -379,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 << ' ';
@@ -433,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;
@@ -504,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
@@ -557,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
@@ -1257,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,
@@ -1276,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);
@@ -1296,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();
@@ -1339,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)
@@ -1376,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))
@@ -1385,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;
}
@@ -1405,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,
@@ -1639,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;
}
@@ -1652,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) {
@@ -1941,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;
@@ -1963,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;
@@ -1971,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:
@@ -1980,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.
///
@@ -2001,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;
@@ -2023,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?
@@ -2046,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;
}
@@ -2067,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
@@ -2077,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;
@@ -2102,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 ||
@@ -2120,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;
@@ -2152,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()))
@@ -2204,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) {
@@ -2236,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;
@@ -2256,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;
@@ -2269,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;
@@ -2327,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;
@@ -2336,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;
@@ -2377,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);
@@ -2386,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);
@@ -2412,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);
@@ -2427,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
@@ -2493,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());
@@ -2532,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());
@@ -2548,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) {}
@@ -2570,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() {
@@ -2595,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 {
@@ -2623,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());
}
@@ -2635,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());
}
@@ -2674,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;
}
@@ -2734,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());
@@ -2762,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(); }
@@ -2775,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() {
@@ -2791,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.
@@ -2819,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 {
@@ -2833,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;
@@ -2874,7 +2323,8 @@ public:
bool popNextReportGraph(ReportGraph &GraphWrapper);
};
-}
+
+} // namespace
TrimmedGraph::TrimmedGraph(const ExplodedGraph *OriginalGraph,
ArrayRef<const ExplodedNode *> Nodes) {
@@ -2930,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) {
@@ -2987,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)) {
@@ -3082,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.
@@ -3126,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) {
@@ -3294,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();
@@ -3397,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();
@@ -3407,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);
}
}
@@ -3451,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;
@@ -3502,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,
@@ -3596,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);
@@ -3622,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/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index 972f4c5f3da2..c87bc685d8b9 100644
--- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/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,465 @@ 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;
+ 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) {}
+
+ 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);
+ const PrintingPolicy &PP = BRC.getASTContext().getPrintingPolicy();
+ const SourceManager &SM = BRC.getSourceManager();
+
+ // 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, SM, PP, *CallExitLoc, Call,
+ MC->getReceiverSVal().getAsRegion());
+
+ if (const auto *CCall = dyn_cast<CXXConstructorCall>(Call)) {
+ const MemRegion *ThisRegion = CCall->getCXXThisVal().getAsRegion();
+ if (RegionOfInterest->isSubRegionOf(ThisRegion)
+ && !CCall->getDecl()->isImplicit()
+ && !isRegionOfInterestModifiedInFrame(N))
+ return notModifiedMemberDiagnostics(Ctx, SM, PP, *CallExitLoc,
+ CCall, ThisRegion);
+ }
+
+ 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, SM, PP, *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,
+ const SourceManager &SM,
+ const PrintingPolicy &PP,
+ 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,
+ const SourceManager &SM,
+ const PrintingPolicy &PP,
+ 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()->getStateManager()
+ .getOwningEngine()->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 +664,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 +732,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())
@@ -274,7 +771,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 +826,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 +848,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 +864,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 +901,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 +927,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 +959,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 +970,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 +1103,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 +1149,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 +1164,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 +1194,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 +1206,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 +1218,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 +1282,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 +1319,20 @@ 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.
+ 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;
- 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 +1381,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 +1401,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 +1416,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 +1438,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 +1453,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 +1474,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 +1546,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 +1573,43 @@ 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 +1618,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 +1643,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 +1652,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 +1708,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 +1741,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 +1790,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 +1811,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 +1908,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 +1951,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 +1981,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 +2005,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 +2031,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 +2135,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 +2152,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 +2200,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 +2214,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 +2222,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 +2255,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 +2263,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 +2277,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 +2298,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 +2340,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 +2367,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 +2385,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/lib/StaticAnalyzer/Core/CMakeLists.txt b/lib/StaticAnalyzer/Core/CMakeLists.txt
index 5ac4f942f373..de994b598e59 100644
--- a/lib/StaticAnalyzer/Core/CMakeLists.txt
+++ b/lib/StaticAnalyzer/Core/CMakeLists.txt
@@ -13,7 +13,6 @@ add_clang_library(clangStaticAnalyzerCore
AnalyzerOptions.cpp
BasicValueFactory.cpp
BlockCounter.cpp
- IssueHash.cpp
BugReporter.cpp
BugReporterVisitors.cpp
CallEvent.cpp
@@ -35,6 +34,7 @@ add_clang_library(clangStaticAnalyzerCore
ExprEngineObjC.cpp
FunctionSummary.cpp
HTMLDiagnostics.cpp
+ IssueHash.cpp
LoopUnrolling.cpp
LoopWidening.cpp
MemRegion.cpp
@@ -48,9 +48,11 @@ add_clang_library(clangStaticAnalyzerCore
SVals.cpp
SimpleConstraintManager.cpp
SimpleSValBuilder.cpp
+ SMTConstraintManager.cpp
Store.cpp
SubEngine.cpp
SymbolManager.cpp
+ WorkList.cpp
Z3ConstraintManager.cpp
LINK_LIBS
@@ -58,6 +60,7 @@ add_clang_library(clangStaticAnalyzerCore
clangASTMatchers
clangAnalysis
clangBasic
+ clangCrossTU
clangLex
clangRewrite
${Z3_LINK_FILES}
diff --git a/lib/StaticAnalyzer/Core/CallEvent.cpp b/lib/StaticAnalyzer/Core/CallEvent.cpp
index 776369be9dba..8db7b06f186d 100644
--- a/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/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,52 @@
//===----------------------------------------------------------------------===//
#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/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 +67,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 +118,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 +159,14 @@ 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
+/// 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 +275,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 +306,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 +314,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 +335,7 @@ QualType CallEvent::getDeclaredResultType(const Decl *D) {
return Ty;
}
- return QualType();
+ return {};
}
llvm_unreachable("unknown callable kind");
@@ -305,11 +344,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 +389,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);
+ }
+
+ 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();
+ 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 +502,6 @@ bool AnyFunctionCall::argumentsMayEscape() const {
return false;
}
-
const FunctionDecl *SimpleFunctionCall::getDecl() const {
const FunctionDecl *D = getOriginExpr()->getDirectCallee();
if (D)
@@ -451,9 +510,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 +528,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 +564,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 +591,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 +609,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 +636,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 +649,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 +665,6 @@ void CXXInstanceCall::getInitialStackFrameContents(
}
}
-
-
const Expr *CXXMemberCall::getCXXThisExpr() const {
return getOriginExpr()->getImplicitObjectArgument();
}
@@ -606,19 +674,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 +729,6 @@ void BlockCall::getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
Params);
}
-
SVal CXXConstructorCall::getCXXThisVal() const {
if (Data)
return loc::MemRegionVal(static_cast<const MemRegion *>(Data));
@@ -672,8 +737,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 +754,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 +855,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 +869,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 +877,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 +944,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 +973,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 +1033,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 +1047,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 +1108,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 +1155,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 +1165,7 @@ RuntimeDefinition ObjCMethodCall::getRuntimeDefinition() const {
}
}
- return RuntimeDefinition();
+ return {};
}
bool ObjCMethodCall::argumentsMayEscape() const {
@@ -1118,7 +1182,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 +1199,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 +1217,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 +1234,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 +1255,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 +1267,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/lib/StaticAnalyzer/Core/CheckerContext.cpp b/lib/StaticAnalyzer/Core/CheckerContext.cpp
index 61cbf3854bb2..6cf931abbddd 100644
--- a/lib/StaticAnalyzer/Core/CheckerContext.cpp
+++ b/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/lib/StaticAnalyzer/Core/CheckerHelpers.cpp b/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
index ed41914ebd05..b9facffcc8b5 100644
--- a/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
+++ b/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/lib/StaticAnalyzer/Core/CheckerManager.cpp b/lib/StaticAnalyzer/Core/CheckerManager.cpp
index 49f3edef2a2d..712872a15d8a 100644
--- a/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ b/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/lib/StaticAnalyzer/Core/CheckerRegistry.cpp b/lib/StaticAnalyzer/Core/CheckerRegistry.cpp
index c9cb189a5b72..645845ec2181 100644
--- a/lib/StaticAnalyzer/Core/CheckerRegistry.cpp
+++ b/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/lib/StaticAnalyzer/Core/ConstraintManager.cpp b/lib/StaticAnalyzer/Core/ConstraintManager.cpp
index 8de2b0e8d271..ef9c44c51be4 100644
--- a/lib/StaticAnalyzer/Core/ConstraintManager.cpp
+++ b/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/lib/StaticAnalyzer/Core/CoreEngine.cpp b/lib/StaticAnalyzer/Core/CoreEngine.cpp
index e2e9ddf5048e..c17b6aae37e2 100644
--- a/lib/StaticAnalyzer/Core/CoreEngine.cpp
+++ b/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/lib/StaticAnalyzer/Core/DynamicTypeMap.cpp b/lib/StaticAnalyzer/Core/DynamicTypeMap.cpp
index a01ff36a8aae..530933916889 100644
--- a/lib/StaticAnalyzer/Core/DynamicTypeMap.cpp
+++ b/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/lib/StaticAnalyzer/Core/Environment.cpp b/lib/StaticAnalyzer/Core/Environment.cpp
index c6acb9d1851c..eccaee292c40 100644
--- a/lib/StaticAnalyzer/Core/Environment.cpp
+++ b/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/lib/StaticAnalyzer/Core/ExplodedGraph.cpp b/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
index 3bc8e09333b9..ece103d9d09a 100644
--- a/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
+++ b/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/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 3be37e7ae301..188316c096e3 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/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,100 @@ 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<
+ llvm::PointerUnion<const Stmt *, const CXXCtorInitializer *>,
+ const LocationContext *> ConstructedObjectKeyImpl;
+
+ ConstructedObjectKeyImpl Impl;
+
+ const void *getAnyASTNodePtr() const {
+ if (const Stmt *S = getStmt())
+ return S;
+ else
+ return getCXXCtorInitializer();
+ }
+
+public:
+ ConstructedObjectKey(
+ llvm::PointerUnion<const Stmt *, const CXXCtorInitializer *> P,
+ const LocationContext *LC)
+ : Impl(P, LC) {
+ // This is the full list of statements that require additional actions when
+ // encountered. This list may be expanded when new actions are implemented.
+ assert(getCXXCtorInitializer() || isa<DeclStmt>(getStmt()) ||
+ isa<CXXNewExpr>(getStmt()) || isa<CXXBindTemporaryExpr>(getStmt()) ||
+ isa<MaterializeTemporaryExpr>(getStmt()) ||
+ isa<CXXConstructExpr>(getStmt()));
+ }
+
+ const Stmt *getStmt() const {
+ return Impl.first.dyn_cast<const Stmt *>();
+ }
+
+ const CXXCtorInitializer *getCXXCtorInitializer() const {
+ return Impl.first.dyn_cast<const CXXCtorInitializer *>();
+ }
+
+ const LocationContext *getLocationContext() const {
+ return Impl.second;
+ }
+
+ void print(llvm::raw_ostream &OS, PrinterHelper *Helper, PrintingPolicy &PP) {
+ OS << '(' << getLocationContext() << ',' << getAnyASTNodePtr() << ") ";
+ if (const Stmt *S = getStmt()) {
+ S->printPretty(OS, Helper, PP);
+ } else {
+ const CXXCtorInitializer *I = getCXXCtorInitializer();
+ OS << I->getAnyMember()->getNameAsString();
+ }
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddPointer(Impl.first.getOpaqueValue());
+ 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)
+
+// Additionally, track a set of destructors that correspond to elided
+// constructors when copy elision occurs.
+typedef std::pair<const CXXBindTemporaryExpr *, const LocationContext *>
+ ElidedDestructorItem;
+typedef llvm::ImmutableSet<ElidedDestructorItem>
+ ElidedDestructorSet;
+REGISTER_TRAIT_WITH_PROGRAMSTATE(ElidedDestructors,
+ ElidedDestructorSet)
//===----------------------------------------------------------------------===//
// Engine construction and deletion.
@@ -69,25 +199,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 +237,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 +246,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 +270,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 +286,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 +362,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 +402,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 +423,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 +449,79 @@ ExprEngine::createTemporaryRegionIfNeeded(ProgramStateRef State,
return State;
}
+ProgramStateRef ExprEngine::addObjectUnderConstruction(
+ ProgramStateRef State,
+ llvm::PointerUnion<const Stmt *, const CXXCtorInitializer *> P,
+ const LocationContext *LC, SVal V) {
+ ConstructedObjectKey Key(P, 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) ||
+ isa<CXXBindTemporaryExpr>(Key.getStmt()));
+ return State->set<ObjectsUnderConstruction>(Key, V);
+}
+
+Optional<SVal> ExprEngine::getObjectUnderConstruction(
+ ProgramStateRef State,
+ llvm::PointerUnion<const Stmt *, const CXXCtorInitializer *> P,
+ const LocationContext *LC) {
+ ConstructedObjectKey Key(P, LC->getStackFrame());
+ return Optional<SVal>::create(State->get<ObjectsUnderConstruction>(Key));
+}
+
+ProgramStateRef ExprEngine::finishObjectConstruction(
+ ProgramStateRef State,
+ llvm::PointerUnion<const Stmt *, const CXXCtorInitializer *> P,
+ const LocationContext *LC) {
+ ConstructedObjectKey Key(P, LC->getStackFrame());
+ assert(State->contains<ObjectsUnderConstruction>(Key));
+ return State->remove<ObjectsUnderConstruction>(Key);
+}
+
+ProgramStateRef ExprEngine::elideDestructor(ProgramStateRef State,
+ const CXXBindTemporaryExpr *BTE,
+ const LocationContext *LC) {
+ ElidedDestructorItem I(BTE, LC);
+ assert(!State->contains<ElidedDestructors>(I));
+ return State->add<ElidedDestructors>(I);
+}
+
+ProgramStateRef
+ExprEngine::cleanupElidedDestructor(ProgramStateRef State,
+ const CXXBindTemporaryExpr *BTE,
+ const LocationContext *LC) {
+ ElidedDestructorItem I(BTE, LC);
+ assert(State->contains<ElidedDestructors>(I));
+ return State->remove<ElidedDestructors>(I);
+}
+
+bool ExprEngine::isDestructorElided(ProgramStateRef State,
+ const CXXBindTemporaryExpr *BTE,
+ const LocationContext *LC) {
+ ElidedDestructorItem I(BTE, LC);
+ return State->contains<ElidedDestructors>(I);
+}
+
+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;
+
+ for (auto I: State->get<ElidedDestructors>())
+ if (I.second == LC)
+ return false;
+
+ LC = LC->getParent();
+ }
+ return true;
+}
+
+
//===----------------------------------------------------------------------===//
// Top-level transfer function logic (Dispatcher).
//===----------------------------------------------------------------------===//
@@ -331,8 +545,44 @@ 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;
+ }
+
+ for (auto I : State->get<ElidedDestructors>()) {
+ if (I.second != LC)
+ continue;
+ Out << '(' << I.second << ',' << (const void *)I.first << ") ";
+ I.first->printPretty(Out, nullptr, PP);
+ Out << " : (constructor elided)" << 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 +598,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 +620,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 +639,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 +679,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 +717,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 +735,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 +788,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 +853,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 +867,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 +945,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 +963,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 +979,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 +1012,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 +1109,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 +1135,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 +1257,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 +1352,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 +1387,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 +1405,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 +1433,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 +1450,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 +1498,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 +1530,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 +1553,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 +1593,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 +1607,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 +1628,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 +1642,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 +1663,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 +1675,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 +1735,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 +1757,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 +1766,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 +1779,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 +1794,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 +1813,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 +1826,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 +1925,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 +1962,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 +1997,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 +2023,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 +2074,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 +2090,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 +2099,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 +2156,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 +2180,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 +2190,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 +2216,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 +2233,59 @@ 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
+ // CXXBindTemporaryExpr. If any other statements are found here,
+ // it must be a separate problem.
+ assert(isa<CXXBindTemporaryExpr>(I.first.getStmt()));
+ State = State->remove<ObjectsUnderConstruction>(I.first);
+ // Also cleanup the elided destructor info.
+ ElidedDestructorItem Item(
+ cast<CXXBindTemporaryExpr>(I.first.getStmt()),
+ I.first.getLocationContext());
+ State = State->remove<ElidedDestructors>(Item);
+ }
+
+ // Also suppress the assertion for elided destructors when temporary
+ // destructors are not provided at all by the CFG, because there's no
+ // good place to clean them up.
+ if (!AMgr.getAnalyzerOptions().includeTemporaryDtorsInCFG())
+ for (auto I : State->get<ElidedDestructors>())
+ if (I.second == LC)
+ State = State->remove<ElidedDestructors>(I);
+
+ 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 +2296,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 +2308,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());
@@ -2046,16 +2398,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 +2416,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 +2446,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 +2468,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 +2506,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,41 +2534,36 @@ 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);
- ExplodedNodeSet EvalSet;
- ValueDecl *Member = M->getMemberDecl();
+ ExplodedNodeSet EvalSet;
+ ValueDecl *Member = M->getMemberDecl();
// 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);
- }
+ if (isa<VarDecl>(Member) || isa<EnumConstantDecl>(Member)) {
+ 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 +2571,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 +2581,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 +2595,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 +2619,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 +2638,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 +2681,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 +2692,6 @@ ExprEngine::notifyCheckersOfPointerEscape(ProgramStateRef State,
ArrayRef<const MemRegion *> Regions,
const CallEvent *Call,
RegionAndSymbolInvalidationTraits &ITraits) {
-
if (!Invalidated || Invalidated->empty())
return State;
@@ -2357,16 +2705,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 +2735,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 +2758,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 +2807,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 +2818,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 +2833,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 +2844,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 +2901,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 +2951,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 +2975,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 +2996,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 +3005,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 +3102,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 +3116,7 @@ struct DOTGraphTraits<ExplodedNode*> :
Out << ":";
}
else {
- assert (isa<DefaultStmt>(Label));
+ assert(isa<DefaultStmt>(Label));
Out << "\\ldefault:";
}
}
@@ -2863,6 +3157,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 +3168,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 +3179,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/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 3e7a50365f50..c7b1a9ac82f0 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/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()) {
@@ -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/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index dad93111966f..dc124fc3ff2d 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/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,134 @@ 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;
+ std::tie(State, V) = prepareForObjectConstruction(
+ CE, State, LCtx, TCC->getConstructionContextAfterElision(), CallOpts);
+
+ // 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);
+ }
+ case ConstructionContext::SimpleTemporaryObjectKind: {
+ const auto *TCC = cast<SimpleTemporaryObjectConstructionContext>(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);
+ }
}
}
-
- 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 +289,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 +353,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 +418,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 +433,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 +444,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 +456,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 +492,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 +517,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 +540,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 +602,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 +678,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/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
index caf86b26b66d..3ee67f3d6882 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ b/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/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp b/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
index f5e64f4a5a8c..d76b9cbcfaca 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
+++ b/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/lib/StaticAnalyzer/Core/FunctionSummary.cpp b/lib/StaticAnalyzer/Core/FunctionSummary.cpp
index c21735b8b882..94edd84d15d2 100644
--- a/lib/StaticAnalyzer/Core/FunctionSummary.cpp
+++ b/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/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
index ebf1487d4bfc..d5e5f96dee0f 100644
--- a/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
+++ b/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/lib/StaticAnalyzer/Core/LoopUnrolling.cpp b/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
index a8c4b05cea13..da4574c61515 100644
--- a/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
+++ b/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/lib/StaticAnalyzer/Core/LoopWidening.cpp b/lib/StaticAnalyzer/Core/LoopWidening.cpp
index 05865c294cb7..9192f49eac6d 100644
--- a/lib/StaticAnalyzer/Core/LoopWidening.cpp
+++ b/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/lib/StaticAnalyzer/Core/MemRegion.cpp b/lib/StaticAnalyzer/Core/MemRegion.cpp
index cb8ba6de3626..cb2122c7749e 100644
--- a/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ b/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/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
index 669748c0127a..1b698ec5c086 100644
--- a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
+++ b/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/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp b/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
index 66812ed8ff5b..cfe780db9ec9 100644
--- a/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
+++ b/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/lib/StaticAnalyzer/Core/ProgramState.cpp b/lib/StaticAnalyzer/Core/ProgramState.cpp
index 5b6b7339697f..2b401607293b 100644
--- a/lib/StaticAnalyzer/Core/ProgramState.cpp
+++ b/lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -17,6 +17,7 @@
#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 +126,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 +266,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 +336,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 +365,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 +448,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 +483,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;
@@ -781,8 +809,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/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
index 5a4031c0b4a5..e8c7bdbde385 100644
--- a/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ b/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/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp b/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp
index 55ff15806efe..f99853f07073 100644
--- a/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp
+++ b/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/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp
index e2e69bb28ec2..db6449e6d5f3 100644
--- a/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/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/lib/StaticAnalyzer/Core/SMTConstraintManager.cpp b/lib/StaticAnalyzer/Core/SMTConstraintManager.cpp
new file mode 100644
index 000000000000..d379562bf325
--- /dev/null
+++ b/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/lib/StaticAnalyzer/Core/SValBuilder.cpp b/lib/StaticAnalyzer/Core/SValBuilder.cpp
index 04452e3e7cc2..f292dca8e99f 100644
--- a/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ b/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/lib/StaticAnalyzer/Core/SVals.cpp b/lib/StaticAnalyzer/Core/SVals.cpp
index a83421426a13..559ca2c9840d 100644
--- a/lib/StaticAnalyzer/Core/SVals.cpp
+++ b/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/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
index 94d29d5a6ba3..beae0dfae289 100644
--- a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
+++ b/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,42 @@ 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();
+ }
+
public:
Simplifier(ProgramStateRef State)
: State(State), SVB(State->getStateManager().getSValBuilder()) {}
SVal VisitSymbolData(const SymbolData *S) {
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)) {
+ SVal V = SVB.makeSymbolVal(S);
+ Cached[S] = V;
+ return V;
+ }
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 +1280,27 @@ SVal SimpleSValBuilder::simplifySVal(ProgramStateRef State, SVal V) {
} else {
RHS = SVB.makeIntVal(S->getRHS());
}
- return SVB.evalBinOp(State, S->getOpcode(), LHS, RHS, S->getType());
+
+ SVal V = SVB.evalBinOp(State, S->getOpcode(), LHS, RHS, S->getType());
+ Cached[S] = V;
+ return V;
}
SVal VisitSymSymExpr(const SymSymExpr *S) {
+ auto I = Cached.find(S);
+ if (I != Cached.end())
+ return I->second;
+
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)) {
+ SVal V = SVB.makeSymbolVal(S);
+ Cached[S] = V;
+ return V;
+ }
+ SVal V = SVB.evalBinOp(State, S->getOpcode(), LHS, RHS, S->getType());
+ Cached[S] = V;
+ return V;
}
SVal VisitSymExpr(SymbolRef S) { return nonloc::SymbolVal(S); }
@@ -1075,13 +1310,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/lib/StaticAnalyzer/Core/Store.cpp b/lib/StaticAnalyzer/Core/Store.cpp
index 173fdd8d0056..5ab5c082269b 100644
--- a/lib/StaticAnalyzer/Core/Store.cpp
+++ b/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,7 +442,6 @@ 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
@@ -448,13 +456,12 @@ SVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset,
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/lib/StaticAnalyzer/Core/SymbolManager.cpp b/lib/StaticAnalyzer/Core/SymbolManager.cpp
index f2d5ee83f3cc..ed197010ebb7 100644
--- a/lib/StaticAnalyzer/Core/SymbolManager.cpp
+++ b/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/lib/StaticAnalyzer/Core/WorkList.cpp b/lib/StaticAnalyzer/Core/WorkList.cpp
new file mode 100644
index 000000000000..4b227375da9b
--- /dev/null
+++ b/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/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
index f9f9057a89cd..7379ded49c80 100644
--- a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
+++ b/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/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
index fccea9ee53bf..44abde5da6d1 100644
--- a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ b/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/lib/StaticAnalyzer/Frontend/CMakeLists.txt b/lib/StaticAnalyzer/Frontend/CMakeLists.txt
index e3ca91aec9cd..ff0a6e19fc97 100644
--- a/lib/StaticAnalyzer/Frontend/CMakeLists.txt
+++ b/lib/StaticAnalyzer/Frontend/CMakeLists.txt
@@ -7,14 +7,15 @@ set(LLVM_LINK_COMPONENTS
add_clang_library(clangStaticAnalyzerFrontend
AnalysisConsumer.cpp
CheckerRegistration.cpp
- ModelConsumer.cpp
FrontendActions.cpp
+ ModelConsumer.cpp
ModelInjector.cpp
LINK_LIBS
clangAST
clangAnalysis
clangBasic
+ clangCrossTU
clangFrontend
clangLex
clangStaticAnalyzerCheckers
diff --git a/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp b/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
index 6792f89876cd..a260c2d85b11 100644
--- a/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
+++ b/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/lib/StaticAnalyzer/Frontend/ModelConsumer.cpp b/lib/StaticAnalyzer/Frontend/ModelConsumer.cpp
index a65a5ee0a451..60825ef7411d 100644
--- a/lib/StaticAnalyzer/Frontend/ModelConsumer.cpp
+++ b/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/lib/StaticAnalyzer/Frontend/ModelInjector.cpp b/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
index cdb1ed9b3815..c43d30440c8f 100644
--- a/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
+++ b/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/lib/StaticAnalyzer/Frontend/ModelInjector.h b/lib/StaticAnalyzer/Frontend/ModelInjector.h
index 98a5f69d68e8..b1b6de9ef9d9 100644
--- a/lib/StaticAnalyzer/Frontend/ModelInjector.h
+++ b/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/lib/Tooling/ASTDiff/ASTDiff.cpp b/lib/Tooling/ASTDiff/ASTDiff.cpp
index 6da0de7edf9a..a5d2d1d24729 100644
--- a/lib/Tooling/ASTDiff/ASTDiff.cpp
+++ b/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/lib/Tooling/AllTUsExecution.cpp b/lib/Tooling/AllTUsExecution.cpp
new file mode 100644
index 000000000000..b761556ee76b
--- /dev/null
+++ b/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/lib/Tooling/ArgumentsAdjusters.cpp b/lib/Tooling/ArgumentsAdjusters.cpp
index 7068ec2c4010..c8e9c167422e 100644
--- a/lib/Tooling/ArgumentsAdjusters.cpp
+++ b/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/lib/Tooling/CMakeLists.txt b/lib/Tooling/CMakeLists.txt
index ee681bbb45ae..031d8b51dec4 100644
--- a/lib/Tooling/CMakeLists.txt
+++ b/lib/Tooling/CMakeLists.txt
@@ -4,16 +4,19 @@ set(LLVM_LINK_COMPONENTS
)
add_subdirectory(Core)
+add_subdirectory(Inclusions)
add_subdirectory(Refactoring)
add_subdirectory(ASTDiff)
add_clang_library(clangTooling
+ AllTUsExecution.cpp
ArgumentsAdjusters.cpp
CommonOptionsParser.cpp
CompilationDatabase.cpp
Execution.cpp
FileMatchTrie.cpp
FixIt.cpp
+ InterpolatingCompilationDatabase.cpp
JSONCompilationDatabase.cpp
Refactoring.cpp
RefactoringCallbacks.cpp
diff --git a/lib/Tooling/CompilationDatabase.cpp b/lib/Tooling/CompilationDatabase.cpp
index 92b76b157dcb..31a769fa21e5 100644
--- a/lib/Tooling/CompilationDatabase.cpp
+++ b/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/lib/Tooling/Core/CMakeLists.txt b/lib/Tooling/Core/CMakeLists.txt
index b3024793580f..f7f423c52228 100644
--- a/lib/Tooling/Core/CMakeLists.txt
+++ b/lib/Tooling/Core/CMakeLists.txt
@@ -1,9 +1,9 @@
set(LLVM_LINK_COMPONENTS support)
add_clang_library(clangToolingCore
+ Diagnostic.cpp
Lookup.cpp
Replacement.cpp
- Diagnostic.cpp
LINK_LIBS
clangAST
diff --git a/lib/Tooling/Core/Replacement.cpp b/lib/Tooling/Core/Replacement.cpp
index 6d4f3a340142..67e2dcfd73c1 100644
--- a/lib/Tooling/Core/Replacement.cpp
+++ b/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/lib/Tooling/Execution.cpp b/lib/Tooling/Execution.cpp
index 498d683f8924..7ae67747acb2 100644
--- a/lib/Tooling/Execution.cpp
+++ b/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/lib/Tooling/FileMatchTrie.cpp b/lib/Tooling/FileMatchTrie.cpp
index 86ed036e2dbe..202b3f00f3fb 100644
--- a/lib/Tooling/FileMatchTrie.cpp
+++ b/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/lib/Tooling/Inclusions/CMakeLists.txt b/lib/Tooling/Inclusions/CMakeLists.txt
new file mode 100644
index 000000000000..00afb50f3a69
--- /dev/null
+++ b/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/lib/Tooling/Inclusions/HeaderIncludes.cpp b/lib/Tooling/Inclusions/HeaderIncludes.cpp
new file mode 100644
index 000000000000..99c0866a6855
--- /dev/null
+++ b/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/lib/Tooling/Inclusions/IncludeStyle.cpp b/lib/Tooling/Inclusions/IncludeStyle.cpp
new file mode 100644
index 000000000000..3597710f1f6e
--- /dev/null
+++ b/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/lib/Tooling/InterpolatingCompilationDatabase.cpp b/lib/Tooling/InterpolatingCompilationDatabase.cpp
new file mode 100644
index 000000000000..bc564584bd01
--- /dev/null
+++ b/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/lib/Tooling/JSONCompilationDatabase.cpp b/lib/Tooling/JSONCompilationDatabase.cpp
index f9a230eb63a0..2fa5fce279d6 100644
--- a/lib/Tooling/JSONCompilationDatabase.cpp
+++ b/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/lib/Tooling/Refactoring/AtomicChange.cpp b/lib/Tooling/Refactoring/AtomicChange.cpp
index e4cc6a5617b6..e8b0fdbeb662 100644
--- a/lib/Tooling/Refactoring/AtomicChange.cpp
+++ b/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/lib/Tooling/Refactoring/Extract/Extract.cpp b/lib/Tooling/Refactoring/Extract/Extract.cpp
index b0847a740048..a12454cd29ef 100644
--- a/lib/Tooling/Refactoring/Extract/Extract.cpp
+++ b/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/lib/Tooling/Refactoring/Rename/RenamingAction.cpp b/lib/Tooling/Refactoring/Rename/RenamingAction.cpp
index c8ed9dd19a8e..44ffae90efa7 100644
--- a/lib/Tooling/Refactoring/Rename/RenamingAction.cpp
+++ b/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/lib/Tooling/Refactoring/Rename/USRFinder.cpp b/lib/Tooling/Refactoring/Rename/USRFinder.cpp
index 3bfb5bbe35e4..63f536c72a6f 100644
--- a/lib/Tooling/Refactoring/Rename/USRFinder.cpp
+++ b/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/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp b/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
index 40b70d8a0590..2e7c9b0cc31b 100644
--- a/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
+++ b/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/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp b/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp
index c77304a17332..fb06b91118b0 100644
--- a/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp
+++ b/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/lib/Tooling/StandaloneExecution.cpp b/lib/Tooling/StandaloneExecution.cpp
index eea8e39d134c..7312baf9dc77 100644
--- a/lib/Tooling/StandaloneExecution.cpp
+++ b/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/lib/Tooling/Tooling.cpp b/lib/Tooling/Tooling.cpp
index 4fbfa4f00473..a106154f4b28 100644
--- a/lib/Tooling/Tooling.cpp
+++ b/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/runtime/CMakeLists.txt b/runtime/CMakeLists.txt
index af8ab163c7cd..9c2f5cd9cf12 100644
--- a/runtime/CMakeLists.txt
+++ b/runtime/CMakeLists.txt
@@ -58,8 +58,12 @@ if(LLVM_BUILD_EXTERNAL_COMPILER_RT AND EXISTS ${COMPILER_RT_SRC_ROOT}/)
endif()
endforeach()
+ if(TARGET cxx-headers)
+ set(COMPILER_RT_LIBCXX_DEPENDENCY "cxx-headers")
+ endif()
+
ExternalProject_Add(compiler-rt
- DEPENDS llvm-config clang
+ DEPENDS llvm-config clang ${COMPILER_RT_LIBCXX_DEPENDENCY}
PREFIX ${COMPILER_RT_PREFIX}
SOURCE_DIR ${COMPILER_RT_SRC_ROOT}
STAMP_DIR ${STAMP_DIR}
diff --git a/test/ARCMT/checking.m b/test/ARCMT/checking.m
index 0ce894cb42a9..182260c18e59 100644
--- a/test/ARCMT/checking.m
+++ b/test/ARCMT/checking.m
@@ -116,7 +116,7 @@ void test1(A *a, BOOL b, struct UnsafeS *unsafeS) {
}
struct S {
- A* a; // expected-error {{ARC forbids Objective-C objects in struct}}
+ A* a;
};
@interface B
diff --git a/test/ARCMT/releases-driver.m b/test/ARCMT/releases-driver.m
index 7b1d2fb8e5b2..3dd546fd6cd5 100644
--- a/test/ARCMT/releases-driver.m
+++ b/test/ARCMT/releases-driver.m
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -fblocks -fsyntax-only -fobjc-arc -x objective-c %s.result
-// RUN: cp %s %t
+// RUN: cat %s > %t
// RUN: %clang_cc1 -arcmt-modify -triple x86_64-apple-macosx10.6 -x objective-c %t
// RUN: diff %t %s.result
// RUN: rm %t
diff --git a/test/ARCMT/releases-driver.m.result b/test/ARCMT/releases-driver.m.result
index 4c864bd2a874..e9aa2d5ac44e 100644
--- a/test/ARCMT/releases-driver.m.result
+++ b/test/ARCMT/releases-driver.m.result
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -fblocks -fsyntax-only -fobjc-arc -x objective-c %s.result
-// RUN: cp %s %t
+// RUN: cat %s > %t
// RUN: %clang_cc1 -arcmt-modify -triple x86_64-apple-macosx10.6 -x objective-c %t
// RUN: diff %t %s.result
// RUN: rm %t
diff --git a/test/ARCMT/with-arc-mode-modify.m b/test/ARCMT/with-arc-mode-modify.m
index fbbd630700f4..bc4662de23e8 100644
--- a/test/ARCMT/with-arc-mode-modify.m
+++ b/test/ARCMT/with-arc-mode-modify.m
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -fobjc-arc -x objective-c %s.result
-// RUN: cp %s %t
+// RUN: cat %s > %t
// RUN: %clang_cc1 -arcmt-modify -fsyntax-only -fobjc-arc -x objective-c %t
// RUN: diff %t %s.result
// RUN: rm %t
diff --git a/test/ARCMT/with-arc-mode-modify.m.result b/test/ARCMT/with-arc-mode-modify.m.result
index 631f276516f6..b847c13f6b4c 100644
--- a/test/ARCMT/with-arc-mode-modify.m.result
+++ b/test/ARCMT/with-arc-mode-modify.m.result
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -fobjc-arc -x objective-c %s.result
-// RUN: cp %s %t
+// RUN: cat %s > %t
// RUN: %clang_cc1 -arcmt-modify -fsyntax-only -fobjc-arc -x objective-c %t
// RUN: diff %t %s.result
// RUN: rm %t
diff --git a/test/ASTMerge/class-template/Inputs/class-template1.cpp b/test/ASTMerge/class-template/Inputs/class-template1.cpp
index 440b5abfc869..fb5b229e0ac8 100644
--- a/test/ASTMerge/class-template/Inputs/class-template1.cpp
+++ b/test/ASTMerge/class-template/Inputs/class-template1.cpp
@@ -1,5 +1,7 @@
template<typename T>
-struct X0;
+struct X0 {
+ T getValue(T arg) { return arg; }
+};
template<int I>
struct X1;
@@ -26,6 +28,7 @@ extern X0<float> *x0r;
template<>
struct X0<char> {
int member;
+ char getValue(char ch) { return static_cast<char>(member); }
};
template<>
diff --git a/test/ASTMerge/class-template/Inputs/class-template2.cpp b/test/ASTMerge/class-template/Inputs/class-template2.cpp
index 6300301a4ffa..b5d0add13f15 100644
--- a/test/ASTMerge/class-template/Inputs/class-template2.cpp
+++ b/test/ASTMerge/class-template/Inputs/class-template2.cpp
@@ -1,5 +1,7 @@
template<class T>
-struct X0;
+struct X0 {
+ T getValue(T arg);
+};
template<int I>
struct X1;
diff --git a/test/ASTMerge/class-template/test.cpp b/test/ASTMerge/class-template/test.cpp
index 0ab5443db7f6..7e25c5d6ccc3 100644
--- a/test/ASTMerge/class-template/test.cpp
+++ b/test/ASTMerge/class-template/test.cpp
@@ -1,24 +1,28 @@
-// RUN: %clang_cc1 -emit-pch -o %t.1.ast %S/Inputs/class-template1.cpp
-// RUN: %clang_cc1 -emit-pch -o %t.2.ast %S/Inputs/class-template2.cpp
-// RUN: not %clang_cc1 -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -std=c++1z -emit-pch -o %t.1.ast %S/Inputs/class-template1.cpp
+// RUN: %clang_cc1 -std=c++1z -emit-pch -o %t.2.ast %S/Inputs/class-template2.cpp
+// RUN: not %clang_cc1 -std=c++1z -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only %s 2>&1 | FileCheck %s
-// CHECK: class-template1.cpp:7:14: error: non-type template parameter declared with incompatible types in different translation units ('int' vs. 'long')
-// CHECK: class-template2.cpp:7:15: note: declared here with type 'long'
+static_assert(sizeof(X0<char>().getValue(1)) == sizeof(char));
+static_assert(sizeof(X0<int>().getValue(1)) == sizeof(int));
-// CHECK: class-template1.cpp:10:14: error: template parameter has different kinds in different translation units
-// CHECK: class-template2.cpp:10:10: note: template parameter declared here
+// CHECK: class-template1.cpp:9:14: error: non-type template parameter declared with incompatible types in different translation units ('int' vs. 'long')
+// CHECK: class-template2.cpp:9:15: note: declared here with type 'long'
-// CHECK: class-template1.cpp:16:23: error: non-type template parameter declared with incompatible types in different translation units ('long' vs. 'int')
-// CHECK: class-template2.cpp:16:23: note: declared here with type 'int'
+// CHECK: class-template1.cpp:12:14: error: template parameter has different kinds in different translation units
+// CHECK: class-template2.cpp:12:10: note: template parameter declared here
-// CHECK: class-template1.cpp:19:10: error: template parameter has different kinds in different translation units
-// CHECK: class-template2.cpp:19:10: note: template parameter declared here
+// CHECK: class-template1.cpp:18:23: error: non-type template parameter declared with incompatible types in different translation units ('long' vs. 'int')
+// CHECK: class-template2.cpp:18:23: note: declared here with type 'int'
-// CHECK: class-template2.cpp:25:20: error: external variable 'x0r' declared with incompatible types in different translation units ('X0<double> *' vs. 'X0<float> *')
-// CHECK: class-template1.cpp:24:19: note: declared here with type 'X0<float> *'
+// CHECK: class-template1.cpp:21:10: error: template parameter has different kinds in different translation units
+// CHECK: class-template2.cpp:21:10: note: template parameter declared here
-// CHECK: class-template1.cpp:32:8: warning: type 'X0<wchar_t>' has incompatible definitions in different translation units
-// CHECK: class-template1.cpp:33:7: note: field 'member' has type 'int' here
-// CHECK: class-template2.cpp:34:9: note: field 'member' has type 'float' here
+// CHECK: class-template2.cpp:27:20: error: external variable 'x0r' declared with incompatible types in different translation units ('X0<double> *' vs. 'X0<float> *')
+// CHECK: class-template1.cpp:26:19: note: declared here with type 'X0<float> *'
+
+// CHECK: class-template1.cpp:35:8: warning: type 'X0<wchar_t>' has incompatible definitions in different translation units
+// CHECK: class-template1.cpp:36:7: note: field 'member' has type 'int' here
+// CHECK: class-template2.cpp:36:9: note: field 'member' has type 'float' here
// CHECK: 1 warning and 5 errors generated.
+// CHECK-NOT: static_assert
diff --git a/test/ASTMerge/class/Inputs/class1.cpp b/test/ASTMerge/class/Inputs/class1.cpp
index b0a7645cfe63..2bd5503ecf3d 100644
--- a/test/ASTMerge/class/Inputs/class1.cpp
+++ b/test/ASTMerge/class/Inputs/class1.cpp
@@ -18,3 +18,31 @@ struct C {
enum E {
b = 1
};
+
+//Friend import tests
+void f();
+int g(int a);
+struct X;
+struct Y;
+
+struct F1 {
+public:
+ int x;
+ friend struct X;
+ friend int g(int);
+ friend void f();
+};
+
+struct F2 {
+public:
+ int x;
+ friend struct X;
+ friend void f();
+};
+
+struct F3 {
+public:
+ int x;
+ friend int g(int);
+ friend void f();
+};
diff --git a/test/ASTMerge/class/Inputs/class2.cpp b/test/ASTMerge/class/Inputs/class2.cpp
index 2bed6d775bc4..6fe38b920662 100644
--- a/test/ASTMerge/class/Inputs/class2.cpp
+++ b/test/ASTMerge/class/Inputs/class2.cpp
@@ -12,3 +12,29 @@ enum E {
a = 0,
b = 1
};
+
+//Friend import tests
+void f();
+int g(int a);
+struct X;
+struct Y;
+
+struct F1 {
+public:
+ int x;
+ friend struct X;
+ friend int g(int);
+ friend void f();
+};
+
+struct F2 {
+public:
+ int x;
+ friend struct X;
+};
+
+struct F3 {
+public:
+ int x;
+ friend void f();
+};
diff --git a/test/ASTMerge/class/test.cpp b/test/ASTMerge/class/test.cpp
index a68a2d1d7690..ba553af40720 100644
--- a/test/ASTMerge/class/test.cpp
+++ b/test/ASTMerge/class/test.cpp
@@ -12,3 +12,13 @@
// CHECK: class1.cpp:18:6: warning: type 'E' has incompatible definitions in different translation units
// CHECK: class1.cpp:19:3: note: enumerator 'b' with value 1 here
// CHECK: class2.cpp:12:3: note: enumerator 'a' with value 0 here
+
+// CHECK: class1.cpp:43:8: warning: type 'F3' has incompatible definitions in different translation units
+// CHECK: class1.cpp:46:3: note: friend declared here
+// CHECK: class2.cpp:36:8: note: no corresponding friend here
+
+// CHECK: class1.cpp:36:8: warning: type 'F2' has incompatible definitions in different translation units
+// CHECK: class1.cpp:39:3: note: friend declared here
+// CHECK: class2.cpp:30:8: note: no corresponding friend here
+
+// CHECK: 4 warnings generated.
diff --git a/test/ASTMerge/exprs-cpp/Inputs/exprs3.cpp b/test/ASTMerge/exprs-cpp/Inputs/exprs3.cpp
index 2a33c35d9ea6..6fdc33fb3919 100644
--- a/test/ASTMerge/exprs-cpp/Inputs/exprs3.cpp
+++ b/test/ASTMerge/exprs-cpp/Inputs/exprs3.cpp
@@ -122,3 +122,20 @@ void useTemplateType() {
const bool ExpressionTrait = __is_lvalue_expr(1);
const unsigned ArrayRank = __array_rank(int[10][20]);
const unsigned ArrayExtent = __array_extent(int[10][20], 1);
+
+constexpr int testLambdaAdd(int toAdd) {
+ const int Captured1 = 1, Captured2 = 2;
+ constexpr auto LambdaAdd = [Captured1, Captured2](int k) -> int {
+ return Captured1 + Captured2 + k;
+ };
+ return LambdaAdd(toAdd);
+}
+
+template<typename T>
+struct TestLambdaTemplate {
+ T i, j;
+ TestLambdaTemplate(T i, const T &j) : i(i), j(j) {}
+ T testLambda(T k) {
+ return [this](T k) -> decltype(auto) { return i + j + k; }(k);
+ }
+};
diff --git a/test/ASTMerge/exprs-cpp/test.cpp b/test/ASTMerge/exprs-cpp/test.cpp
index 0535aa85330f..c0b282ec0288 100644
--- a/test/ASTMerge/exprs-cpp/test.cpp
+++ b/test/ASTMerge/exprs-cpp/test.cpp
@@ -30,6 +30,8 @@ static_assert(ExpressionTrait == false);
static_assert(ArrayRank == 2);
static_assert(ArrayExtent == 20);
+static_assert(testLambdaAdd(3) == 6);
+
void testImport(int *x, const S1 &cs1, S1 &s1) {
testNewThrowDelete();
testArrayElement(nullptr, 12);
@@ -44,4 +46,5 @@ void testImport(int *x, const S1 &cs1, S1 &s1) {
testDefaultArg();
testDefaultArgExpr();
useTemplateType();
+ TestLambdaTemplate<int>(1, 2).testLambda(3);
}
diff --git a/test/ASTMerge/function-cpp/Inputs/function-1.cpp b/test/ASTMerge/function-cpp/Inputs/function-1.cpp
new file mode 100644
index 000000000000..ee97a1a8a5da
--- /dev/null
+++ b/test/ASTMerge/function-cpp/Inputs/function-1.cpp
@@ -0,0 +1,8 @@
+
+template<typename T> constexpr T add(T arg1, T arg2) {
+ return arg1 + arg2;
+}
+
+template<> constexpr int add(int arg1, int arg2) {
+ return arg1 + arg2 + 2;
+}
diff --git a/test/ASTMerge/function-cpp/test.cpp b/test/ASTMerge/function-cpp/test.cpp
new file mode 100644
index 000000000000..304ce3c634c2
--- /dev/null
+++ b/test/ASTMerge/function-cpp/test.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -std=c++1z -emit-pch -o %t.1.ast %S/Inputs/function-1.cpp
+// RUN: %clang_cc1 -std=c++1z -ast-merge %t.1.ast -fsyntax-only %s 2>&1 | FileCheck %s
+// XFAIL: *
+
+static_assert(add(1, 2) == 5);
+
+// FIXME: support of templated function overload is still not implemented.
+static_assert(add('\1', '\2') == 3);
+
+// CHECK-NOT: static_assert
diff --git a/test/ASTMerge/injected-class-name-decl/Inputs/inject1.cpp b/test/ASTMerge/injected-class-name-decl/Inputs/inject1.cpp
new file mode 100644
index 000000000000..f6f769746d10
--- /dev/null
+++ b/test/ASTMerge/injected-class-name-decl/Inputs/inject1.cpp
@@ -0,0 +1,2 @@
+template <class X>
+class C { static X x; };
diff --git a/test/ASTMerge/injected-class-name-decl/Inputs/inject2.cpp b/test/ASTMerge/injected-class-name-decl/Inputs/inject2.cpp
new file mode 100644
index 000000000000..7cf5fc223285
--- /dev/null
+++ b/test/ASTMerge/injected-class-name-decl/Inputs/inject2.cpp
@@ -0,0 +1,2 @@
+template <class X>
+X C<X>::x;
diff --git a/test/ASTMerge/injected-class-name-decl/test.cpp b/test/ASTMerge/injected-class-name-decl/test.cpp
new file mode 100644
index 000000000000..9f31674108ad
--- /dev/null
+++ b/test/ASTMerge/injected-class-name-decl/test.cpp
@@ -0,0 +1,3 @@
+// RUN: %clang_cc1 -std=c++1z -emit-pch -o %t.ast %S/Inputs/inject1.cpp
+// RUN: %clang_cc1 -std=c++1z -emit-obj -o /dev/null -ast-merge %t.ast %S/Inputs/inject2.cpp
+// expected-no-diagnostics
diff --git a/test/ASTMerge/interface/Inputs/interface1.m b/test/ASTMerge/interface/Inputs/interface1.m
index 5865c0eff070..6192150089fe 100644
--- a/test/ASTMerge/interface/Inputs/interface1.m
+++ b/test/ASTMerge/interface/Inputs/interface1.m
@@ -100,4 +100,6 @@
@implementation I15 : I12
@end
-
+@interface ImportSelectorSLoc { }
+-(int)addInt:(int)a toInt:(int)b moduloInt:(int)c; // don't crash here
+@end
diff --git a/test/ASTMerge/namespace/test.cpp b/test/ASTMerge/namespace/test.cpp
index f1796c03b07e..ab05f6d72758 100644
--- a/test/ASTMerge/namespace/test.cpp
+++ b/test/ASTMerge/namespace/test.cpp
@@ -7,7 +7,7 @@ static_assert(ContainsInline::z == 10);
void testImport() {
typedef TestUnresolvedTypenameAndValueDecls::Derived<int> Imported;
- Imported a; // Successfull instantiation
+ Imported a; // Successful instantiation
static_assert(sizeof(Imported::foo) == sizeof(int));
static_assert(sizeof(TestUnresolvedTypenameAndValueDecls::Derived<double>::NewUnresolvedUsingType) == sizeof(double));
}
diff --git a/test/ASTMerge/std-initializer-list/Inputs/il.cpp b/test/ASTMerge/std-initializer-list/Inputs/il.cpp
new file mode 100644
index 000000000000..3b2ac187c886
--- /dev/null
+++ b/test/ASTMerge/std-initializer-list/Inputs/il.cpp
@@ -0,0 +1,9 @@
+namespace std {
+template <typename T>
+struct initializer_list {
+ const T *begin, *end;
+ initializer_list();
+};
+} // namespace std
+
+std::initializer_list<int> IL = {1, 2, 3, 4};
diff --git a/test/ASTMerge/std-initializer-list/test.cpp b/test/ASTMerge/std-initializer-list/test.cpp
new file mode 100644
index 000000000000..ca7330d308a8
--- /dev/null
+++ b/test/ASTMerge/std-initializer-list/test.cpp
@@ -0,0 +1,3 @@
+// RUN: %clang_cc1 -emit-pch -o %t.1.ast %S/Inputs/il.cpp
+// RUN: %clang_cc1 -ast-merge %t.1.ast -fsyntax-only %s 2>&1 | FileCheck --allow-empty %s
+// CHECK-NOT: unsupported AST node
diff --git a/test/ASTMerge/struct/Inputs/struct1.c b/test/ASTMerge/struct/Inputs/struct1.c
index 0f3e8b9bc3eb..a85aec70a84c 100644
--- a/test/ASTMerge/struct/Inputs/struct1.c
+++ b/test/ASTMerge/struct/Inputs/struct1.c
@@ -77,3 +77,65 @@ typedef struct {
} S13;
S13 x13;
+
+// Matches
+struct Unnamed {
+ union {
+ struct {
+ int i;
+ } S;
+ struct {
+ float i;
+ } R;
+ } U;
+} x14;
+
+// Matches
+struct DeepUnnamed {
+ union {
+ union {
+ struct {
+ long i;
+ } S;
+ struct {
+ int i;
+ } R;
+ } U1;
+ union {
+ struct {
+ long i;
+ } S;
+ struct {
+ float i;
+ } T;
+ } U2;
+ } U;
+ struct {
+ long i;
+ } V;
+} x15;
+
+// Mismatch due to unnamed struct used internally
+struct DeepUnnamedError {
+ union {
+ union {
+ struct {
+ long i;
+ } S;
+ struct {
+ int i;
+ } R;
+ } U1;
+ union {
+ struct {
+ long i; // Mismatch here.
+ } S;
+ struct {
+ float i;
+ } T;
+ } U2;
+ } U;
+ struct {
+ long i;
+ } V;
+} x16;
diff --git a/test/ASTMerge/struct/Inputs/struct2.c b/test/ASTMerge/struct/Inputs/struct2.c
index 7fe17a576b23..49fe36d823d0 100644
--- a/test/ASTMerge/struct/Inputs/struct2.c
+++ b/test/ASTMerge/struct/Inputs/struct2.c
@@ -74,3 +74,65 @@ typedef struct {
} S13;
S13 x13;
+
+// Matches
+struct Unnamed {
+ union {
+ struct {
+ int i;
+ } S;
+ struct {
+ float i;
+ } R;
+ } U;
+} x14;
+
+// Matches
+struct DeepUnnamed {
+ union {
+ union {
+ struct {
+ long i;
+ } S;
+ struct {
+ int i;
+ } R;
+ } U1;
+ union {
+ struct {
+ long i;
+ } S;
+ struct {
+ float i;
+ } T;
+ } U2;
+ } U;
+ struct {
+ long i;
+ } V;
+} x15;
+
+// Mismatch due to unnamed struct used internally
+struct DeepUnnamedError {
+ union {
+ union {
+ struct {
+ long i;
+ } S;
+ struct {
+ int i;
+ } R;
+ } U1;
+ union {
+ struct {
+ float i; // Mismatch here.
+ } S;
+ struct {
+ float i;
+ } T;
+ } U2;
+ } U;
+ struct {
+ long i;
+ } V;
+} x16;
diff --git a/test/ASTMerge/struct/test.c b/test/ASTMerge/struct/test.c
index ed7750f6becc..ef339396971d 100644
--- a/test/ASTMerge/struct/test.c
+++ b/test/ASTMerge/struct/test.c
@@ -44,4 +44,12 @@
// CHECK: struct2.c:72:7: note: field 'i' has type 'int' here
// CHECK: struct2.c:76:5: error: external variable 'x13' declared with incompatible types in different translation units ('S13' vs. 'S13')
// CHECK: struct1.c:79:5: note: declared here with type 'S13'
-// CHECK: 9 warnings and 8 errors generated
+// CHECK: struct1.c:130:7: warning: type 'struct DeepUnnamedError::(anonymous at [[PATH_TO_INPUTS:.+]]struct1.c:130:7)' has incompatible definitions in different translation units
+// CHECK: struct1.c:131:14: note: field 'i' has type 'long' here
+// CHECK: struct2.c:128:15: note: field 'i' has type 'float' here
+// CHECK: struct1.c:129:5: warning: type 'union DeepUnnamedError::(anonymous at [[PATH_TO_INPUTS]]struct1.c:129:5)' has incompatible definitions in different translation units
+// CHECK: struct1.c:132:9: note: field 'S' has type 'struct (anonymous struct at [[PATH_TO_INPUTS]]struct1.c:130:7)' here
+// CHECK: struct2.c:129:9: note: field 'S' has type 'struct (anonymous struct at [[PATH_TO_INPUTS]]struct2.c:127:7)' here
+// CHECK: struct2.c:138:3: error: external variable 'x16' declared with incompatible types in different translation units ('struct DeepUnnamedError' vs. 'struct DeepUnnamedError')
+// CHECK: struct1.c:141:3: note: declared here with type 'struct DeepUnnamedError'
+// CHECK: 11 warnings and 9 errors generated
diff --git a/test/ASTMerge/var-cpp/Inputs/var1.cpp b/test/ASTMerge/var-cpp/Inputs/var1.cpp
new file mode 100644
index 000000000000..e29db9d43fbb
--- /dev/null
+++ b/test/ASTMerge/var-cpp/Inputs/var1.cpp
@@ -0,0 +1,17 @@
+
+template <typename T>
+constexpr T my_pi = T(3.1415926535897932385L); // variable template
+
+template <> constexpr char my_pi<char> = '3'; // variable template specialization
+
+template <typename T>
+struct Wrapper {
+ template <typename U> static constexpr U my_const = U(1);
+ // Variable template partial specialization with member variable.
+ template <typename U> static constexpr U *my_const<const U *> = (U *)(0);
+};
+
+constexpr char a[] = "hello";
+
+template <> template <>
+constexpr const char *Wrapper<float>::my_const<const char *> = a;
diff --git a/test/ASTMerge/var-cpp/test.cpp b/test/ASTMerge/var-cpp/test.cpp
new file mode 100644
index 000000000000..28d38d581241
--- /dev/null
+++ b/test/ASTMerge/var-cpp/test.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -emit-pch -std=c++17 -o %t.1.ast %S/Inputs/var1.cpp
+// RUN: %clang_cc1 -std=c++17 -ast-merge %t.1.ast -fsyntax-only %s 2>&1
+
+static_assert(my_pi<double> == (double)3.1415926535897932385L);
+static_assert(my_pi<char> == '3');
+
+static_assert(Wrapper<int>::my_const<float> == 1.f);
+static_assert(Wrapper<char>::my_const<const float *> == nullptr);
+static_assert(Wrapper<float>::my_const<const char *> == a);
diff --git a/test/Analysis/Checkers/RunLoopAutoreleaseLeakChecker.m b/test/Analysis/Checkers/RunLoopAutoreleaseLeakChecker.m
new file mode 100644
index 000000000000..4dde40e210a0
--- /dev/null
+++ b/test/Analysis/Checkers/RunLoopAutoreleaseLeakChecker.m
@@ -0,0 +1,104 @@
+// UNSUPPORTED: system-windows
+// RUN: %clang_analyze_cc1 -fobjc-arc -analyzer-checker=core,osx.cocoa.RunLoopAutoreleaseLeak %s -triple x86_64-darwin -verify
+// RUN: %clang_analyze_cc1 -DEXTRA=1 -DAP1=1 -fobjc-arc -analyzer-checker=core,osx.cocoa.RunLoopAutoreleaseLeak %s -triple x86_64-darwin -verify
+// RUN: %clang_analyze_cc1 -DEXTRA=1 -DAP2=1 -fobjc-arc -analyzer-checker=core,osx.cocoa.RunLoopAutoreleaseLeak %s -triple x86_64-darwin -verify
+// RUN: %clang_analyze_cc1 -DEXTRA=1 -DAP3=1 -fobjc-arc -analyzer-checker=core,osx.cocoa.RunLoopAutoreleaseLeak %s -triple x86_64-darwin -verify
+// RUN: %clang_analyze_cc1 -DEXTRA=1 -DAP4=1 -fobjc-arc -analyzer-checker=core,osx.cocoa.RunLoopAutoreleaseLeak %s -triple x86_64-darwin -verify
+
+#include "../Inputs/system-header-simulator-for-objc-dealloc.h"
+
+#ifndef EXTRA
+
+void just_runloop() { // No warning: no statements in between
+ @autoreleasepool {
+ [[NSRunLoop mainRunLoop] run]; // no-warning
+ }
+}
+
+void just_xpcmain() { // No warning: no statements in between
+ @autoreleasepool {
+ xpc_main(); // no-warning
+ }
+}
+
+void runloop_init_before() { // Warning: object created before the loop.
+ @autoreleasepool {
+ NSObject *object = [[NSObject alloc] init]; // expected-warning{{Temporary objects allocated in the autorelease pool followed by the launch of main run loop may never get released; consider moving them to a separate autorelease pool}}
+ (void) object;
+ [[NSRunLoop mainRunLoop] run];
+ }
+}
+
+void xpcmain_init_before() { // Warning: object created before the loop.
+ @autoreleasepool {
+ NSObject *object = [[NSObject alloc] init]; // expected-warning{{Temporary objects allocated in the autorelease pool followed by the launch of xpc_main may never get released; consider moving them to a separate autorelease pool}}
+ (void) object;
+ xpc_main();
+ }
+}
+
+void runloop_init_before_two_objects() { // Warning: object created before the loop.
+ @autoreleasepool {
+ NSObject *object = [[NSObject alloc] init]; // expected-warning{{Temporary objects allocated in the autorelease pool followed by the launch of main run loop may never get released; consider moving them to a separate autorelease pool}}
+ NSObject *object2 = [[NSObject alloc] init]; // no-warning, warning on the first one is enough.
+ (void) object;
+ (void) object2;
+ [[NSRunLoop mainRunLoop] run];
+ }
+}
+
+void runloop_no_autoreleasepool() {
+ NSObject *object = [[NSObject alloc] init]; // no-warning
+ (void)object;
+ [[NSRunLoop mainRunLoop] run];
+}
+
+void runloop_init_after() { // No warning: objects created after the loop
+ @autoreleasepool {
+ [[NSRunLoop mainRunLoop] run];
+ NSObject *object = [[NSObject alloc] init]; // no-warning
+ (void) object;
+ }
+}
+
+#endif
+
+#ifdef AP1
+int main() {
+ NSObject *object = [[NSObject alloc] init]; // expected-warning{{Temporary objects allocated in the autorelease pool of last resort followed by the launch of main run loop may never get released; consider moving them to a separate autorelease pool}}
+ (void) object;
+ [[NSRunLoop mainRunLoop] run];
+ return 0;
+}
+#endif
+
+#ifdef AP2
+// expected-no-diagnostics
+int main() {
+ NSObject *object = [[NSObject alloc] init]; // no-warning
+ (void) object;
+ @autoreleasepool {
+ [[NSRunLoop mainRunLoop] run];
+ }
+ return 0;
+}
+#endif
+
+#ifdef AP3
+// expected-no-diagnostics
+int main() {
+ [[NSRunLoop mainRunLoop] run];
+ NSObject *object = [[NSObject alloc] init]; // no-warning
+ (void) object;
+ return 0;
+}
+#endif
+
+#ifdef AP4
+int main() {
+ NSObject *object = [[NSObject alloc] init]; // expected-warning{{Temporary objects allocated in the autorelease pool of last resort followed by the launch of xpc_main may never get released; consider moving them to a separate autorelease pool}}
+ (void) object;
+ xpc_main();
+ return 0;
+}
+#endif
diff --git a/test/Analysis/Inputs/ctu-chain.cpp b/test/Analysis/Inputs/ctu-chain.cpp
new file mode 100644
index 000000000000..2314dde1df0d
--- /dev/null
+++ b/test/Analysis/Inputs/ctu-chain.cpp
@@ -0,0 +1,20 @@
+int h_chain(int x) {
+ return x * 2;
+}
+
+namespace chns {
+int chf3(int x);
+
+int chf2(int x) {
+ return chf3(x);
+}
+
+class chcls {
+public:
+ int chf4(int x);
+};
+
+int chcls::chf4(int x) {
+ return x * 3;
+}
+}
diff --git a/test/Analysis/Inputs/ctu-other.cpp b/test/Analysis/Inputs/ctu-other.cpp
new file mode 100644
index 000000000000..8cad861578b4
--- /dev/null
+++ b/test/Analysis/Inputs/ctu-other.cpp
@@ -0,0 +1,77 @@
+#include "../ctu-hdr.h"
+
+int callback_to_main(int x);
+int f(int x) {
+ return x - 1;
+}
+
+int g(int x) {
+ return callback_to_main(x) + 1;
+}
+
+int h_chain(int);
+
+int h(int x) {
+ return 2 * h_chain(x);
+}
+
+namespace myns {
+int fns(int x) {
+ return x + 7;
+}
+
+namespace embed_ns {
+int fens(int x) {
+ return x - 3;
+}
+}
+
+class embed_cls {
+public:
+ int fecl(int x) {
+ return x - 7;
+ }
+};
+}
+
+class mycls {
+public:
+ int fcl(int x) {
+ return x + 5;
+ }
+ static int fscl(int x) {
+ return x + 6;
+ }
+
+ class embed_cls2 {
+ public:
+ int fecl2(int x) {
+ return x - 11;
+ }
+ };
+};
+
+namespace chns {
+int chf2(int x);
+
+class chcls {
+public:
+ int chf4(int x);
+};
+
+int chf3(int x) {
+ return chcls().chf4(x);
+}
+
+int chf1(int x) {
+ return chf2(x);
+}
+}
+
+typedef struct { int n; } Anonymous;
+int fun_using_anon_struct(int n) { Anonymous anon; anon.n = n; return anon.n; }
+
+int other_macro_diag(int x) {
+ MACRODIAG();
+ return x;
+}
diff --git a/test/Analysis/Inputs/externalFnMap.txt b/test/Analysis/Inputs/externalFnMap.txt
new file mode 100644
index 000000000000..5461685dc62b
--- /dev/null
+++ b/test/Analysis/Inputs/externalFnMap.txt
@@ -0,0 +1,15 @@
+c:@N@chns@F@chf1#I# ctu-other.cpp.ast
+c:@N@myns@N@embed_ns@F@fens#I# ctu-other.cpp.ast
+c:@F@g#I# ctu-other.cpp.ast
+c:@S@mycls@F@fscl#I#S ctu-other.cpp.ast
+c:@S@mycls@F@fcl#I# ctu-other.cpp.ast
+c:@N@myns@S@embed_cls@F@fecl#I# ctu-other.cpp.ast
+c:@S@mycls@S@embed_cls2@F@fecl2#I# ctu-other.cpp.ast
+c:@F@f#I# ctu-other.cpp.ast
+c:@N@myns@F@fns#I# ctu-other.cpp.ast
+c:@F@h#I# ctu-other.cpp.ast
+c:@F@h_chain#I# ctu-chain.cpp.ast
+c:@N@chns@S@chcls@F@chf4#I# ctu-chain.cpp.ast
+c:@N@chns@F@chf2#I# ctu-chain.cpp.ast
+c:@F@fun_using_anon_struct#I# ctu-other.cpp.ast
+c:@F@other_macro_diag#I# ctu-other.cpp.ast
diff --git a/test/Analysis/Inputs/system-header-simulator-cxx.h b/test/Analysis/Inputs/system-header-simulator-cxx.h
index 809b768d71e0..5d7e553ed5f4 100644
--- a/test/Analysis/Inputs/system-header-simulator-cxx.h
+++ b/test/Analysis/Inputs/system-header-simulator-cxx.h
@@ -252,6 +252,12 @@ namespace std {
return size_t(_finish - _start);
}
+ void clear();
+
+ void push_back(const T &value);
+ void push_back(T &&value);
+ void pop_back();
+
T &operator[](size_t n) {
return _start[n];
}
@@ -295,6 +301,8 @@ namespace std {
list& operator=(list &&other);
list& operator=(std::initializer_list<T> ilist);
+ void clear();
+
iterator begin() { return iterator(_start); }
const_iterator begin() const { return const_iterator(_start); }
const_iterator cbegin() const { return const_iterator(_start); }
@@ -330,6 +338,16 @@ namespace std {
return size_t(_finish - _start);
}
+ void clear();
+
+ void push_back(const T &value);
+ void push_back(T &&value);
+ void pop_back();
+
+ void push_front(const T &value);
+ void push_front(T &&value);
+ void pop_front();
+
T &operator[](size_t n) {
return _start[n];
}
@@ -369,6 +387,12 @@ namespace std {
forward_list(forward_list &&other);
~forward_list();
+ void clear();
+
+ void push_front(const T &value);
+ void push_front(T &&value);
+ void pop_front();
+
iterator begin() { return iterator(_start); }
const_iterator begin() const { return const_iterator(_start); }
const_iterator cbegin() const { return const_iterator(_start); }
@@ -584,10 +608,21 @@ namespace std {
}
+#ifdef TEST_INLINABLE_ALLOCATORS
+namespace std {
+ void *malloc(size_t);
+ void free(void *);
+}
+void* operator new(std::size_t size, const std::nothrow_t&) throw() { return std::malloc(size); }
+void* operator new[](std::size_t size, const std::nothrow_t&) throw() { return std::malloc(size); }
+void operator delete(void* ptr, const std::nothrow_t&) throw() { std::free(ptr); }
+void operator delete[](void* ptr, const std::nothrow_t&) throw() { std::free(ptr); }
+#else
void* operator new(std::size_t, const std::nothrow_t&) throw();
void* operator new[](std::size_t, const std::nothrow_t&) throw();
void operator delete(void*, const std::nothrow_t&) throw();
void operator delete[](void*, const std::nothrow_t&) throw();
+#endif
void* operator new (std::size_t size, void* ptr) throw() { return ptr; };
void* operator new[] (std::size_t size, void* ptr) throw() { return ptr; };
diff --git a/test/Analysis/Inputs/system-header-simulator-for-cxx-uninitialized-object.h b/test/Analysis/Inputs/system-header-simulator-for-cxx-uninitialized-object.h
new file mode 100644
index 000000000000..2397824fc965
--- /dev/null
+++ b/test/Analysis/Inputs/system-header-simulator-for-cxx-uninitialized-object.h
@@ -0,0 +1,18 @@
+// Like the compiler, the static analyzer treats some functions differently if
+// they come from a system header -- for example, it is assumed that system
+// functions do not arbitrarily free() their parameters, and that some bugs
+// found in system headers cannot be fixed by the user and should be
+// suppressed.
+
+#pragma clang system_header
+
+struct RecordInSystemHeader {
+ int a;
+ int b;
+};
+
+template <class T>
+struct ContainerInSystemHeader {
+ T &t;
+ ContainerInSystemHeader(T& t) : t(t) {}
+};
diff --git a/test/Analysis/Inputs/system-header-simulator-for-nullability-cxx.h b/test/Analysis/Inputs/system-header-simulator-for-nullability-cxx.h
new file mode 100644
index 000000000000..fe620c9ff197
--- /dev/null
+++ b/test/Analysis/Inputs/system-header-simulator-for-nullability-cxx.h
@@ -0,0 +1,9 @@
+#pragma clang system_header
+
+struct S {
+ ~S(){}
+};
+
+void foo() {
+ S s;
+}
diff --git a/test/Analysis/Inputs/system-header-simulator-for-nullability.h b/test/Analysis/Inputs/system-header-simulator-for-nullability.h
index 8d49f323bc1d..751057dd450e 100644
--- a/test/Analysis/Inputs/system-header-simulator-for-nullability.h
+++ b/test/Analysis/Inputs/system-header-simulator-for-nullability.h
@@ -32,6 +32,10 @@ NSObject<NSObject>
@interface NSString : NSObject<NSCopying>
- (BOOL)isEqualToString : (NSString *)aString;
- (NSString *)stringByAppendingString:(NSString *)aString;
+- (nullable NSString *)nullableStringByAppendingString:(NSString *)aString;
++ (NSString * _Nonnull) generateString;
++ (NSString *) generateImplicitlyNonnullString;
++ (NSString * _Nullable) generatePossiblyNullString;
@end
void NSSystemFunctionTakingNonnull(NSString *s);
@@ -40,4 +44,11 @@ void NSSystemFunctionTakingNonnull(NSString *s);
- (void) takesNonnull:(NSString *)s;
@end
+NSString* _Nullable getPossiblyNullString();
+NSString* _Nonnull getString();
+
+@protocol MyProtocol
+- (NSString * _Nonnull) getString;
+@end
+
NS_ASSUME_NONNULL_END
diff --git a/test/Analysis/Inputs/system-header-simulator-for-objc-dealloc.h b/test/Analysis/Inputs/system-header-simulator-for-objc-dealloc.h
index 231c0bf5640e..f1343e30a754 100644
--- a/test/Analysis/Inputs/system-header-simulator-for-objc-dealloc.h
+++ b/test/Analysis/Inputs/system-header-simulator-for-objc-dealloc.h
@@ -18,6 +18,8 @@ typedef signed char BOOL;
@interface NSRunLoop : NSObject
+ (NSRunLoop *)currentRunLoop;
++ (NSRunLoop *)mainRunLoop;
+- (void) run;
- (void)cancelPerformSelectorsWithTarget:(id)target;
@end
@@ -33,3 +35,5 @@ void _Block_release(const void *aBlock);
@interface CIFilter : NSObject
@end
+
+extern void xpc_main(void);
diff --git a/test/Analysis/Inputs/system-header-simulator.h b/test/Analysis/Inputs/system-header-simulator.h
index 2e6f1e7d4a96..8542387d4277 100644
--- a/test/Analysis/Inputs/system-header-simulator.h
+++ b/test/Analysis/Inputs/system-header-simulator.h
@@ -32,6 +32,7 @@ typedef __typeof(sizeof(int)) size_t;
size_t strlen(const char *);
char *strcpy(char *restrict, const char *restrict);
+char *strncpy(char *dst, const char *src, size_t n);
void *memcpy(void *dst, const void *src, size_t n);
typedef unsigned long __darwin_pthread_key_t;
@@ -109,4 +110,6 @@ void _Exit(int status) __attribute__ ((__noreturn__));
#ifndef NULL
#define __DARWIN_NULL 0
#define NULL __DARWIN_NULL
-#endif \ No newline at end of file
+#endif
+
+#define offsetof(t, d) __builtin_offsetof(t, d) \ No newline at end of file
diff --git a/test/Analysis/MismatchedDeallocator-checker-test.mm b/test/Analysis/MismatchedDeallocator-checker-test.mm
index b80f7df233dd..013d677e515c 100644
--- a/test/Analysis/MismatchedDeallocator-checker-test.mm
+++ b/test/Analysis/MismatchedDeallocator-checker-test.mm
@@ -1,4 +1,5 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.MismatchedDeallocator -fblocks -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.MismatchedDeallocator -fblocks -DTEST_INLINABLE_ALLOCATORS -verify %s
#include "Inputs/system-header-simulator-objc.h"
#include "Inputs/system-header-simulator-cxx.h"
diff --git a/test/Analysis/MismatchedDeallocator-path-notes.cpp b/test/Analysis/MismatchedDeallocator-path-notes.cpp
index 1354386fc8b7..4e4ffc42423e 100644
--- a/test/Analysis/MismatchedDeallocator-path-notes.cpp
+++ b/test/Analysis/MismatchedDeallocator-path-notes.cpp
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.MismatchedDeallocator -analyzer-output=text -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.MismatchedDeallocator -analyzer-output=plist -analyzer-config path-diagnostics-alternate=false %s -o %t.plist
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.MismatchedDeallocator -analyzer-output=plist %s -o %t.plist
// RUN: FileCheck --input-file=%t.plist %s
void changePointee(int *p);
@@ -131,40 +131,6 @@ void test() {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -243,6 +209,40 @@ void test() {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>10</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>10</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>10</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>10</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>13</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
diff --git a/test/Analysis/MisusedMovedObject.cpp b/test/Analysis/MisusedMovedObject.cpp
index 132a65de104e..07d52c8236da 100644
--- a/test/Analysis/MisusedMovedObject.cpp
+++ b/test/Analysis/MisusedMovedObject.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.cplusplus.MisusedMovedObject -std=c++11 -verify -analyzer-output=text %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.cplusplus.MisusedMovedObject -std=c++11 -verify -analyzer-output=text -analyzer-config exploration_strategy=unexplored_first_queue %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.cplusplus.MisusedMovedObject -std=c++11 -analyzer-config exploration_strategy=dfs -verify -analyzer-output=text -DDFS=1 %s
namespace std {
@@ -474,12 +475,16 @@ void differentBranchesTest(int i) {
// A variation on the theme above.
{
A a;
+#ifdef DFS
a.foo() > 0 ? a.foo() : A(std::move(a)).foo(); // expected-note {{Assuming the condition is false}} expected-note {{'?' condition is false}}
+#else
+ a.foo() > 0 ? a.foo() : A(std::move(a)).foo(); // expected-note {{Assuming the condition is true}} expected-note {{'?' condition is true}}
+#endif
}
// Same thing, but with a switch statement.
{
A a, b;
- switch (i) { // expected-note {{Control jumps to 'case 1:' at line 483}}
+ switch (i) { // expected-note {{Control jumps to 'case 1:'}}
case 1:
b = std::move(a); // no-warning
break; // expected-note {{Execution jumps to the end of the function}}
@@ -491,7 +496,7 @@ void differentBranchesTest(int i) {
// However, if there's a fallthrough, we do warn.
{
A a, b;
- switch (i) { // expected-note {{Control jumps to 'case 1:' at line 495}}
+ switch (i) { // expected-note {{Control jumps to 'case 1:'}}
case 1:
b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
case 2:
diff --git a/test/Analysis/NewDelete-atomics.cpp b/test/Analysis/NewDelete-atomics.cpp
new file mode 100644
index 000000000000..54fce17ea7bd
--- /dev/null
+++ b/test/Analysis/NewDelete-atomics.cpp
@@ -0,0 +1,78 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -DTEST_INLINABLE_ALLOCATORS -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -DTEST_INLINABLE_ALLOCATORS -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-inline-max-stack-depth 2 -analyzer-config ipa-always-inline-size=2 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-inline-max-stack-depth 2 -analyzer-config ipa-always-inline-size=2 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-inline-max-stack-depth 2 -analyzer-config ipa-always-inline-size=2 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -DTEST_INLINABLE_ALLOCATORS -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-inline-max-stack-depth 2 -analyzer-config ipa-always-inline-size=2 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -DTEST_INLINABLE_ALLOCATORS -verify %s
+
+// expected-no-diagnostics
+
+#include "Inputs/system-header-simulator-cxx.h"
+
+typedef enum memory_order {
+ memory_order_relaxed = __ATOMIC_RELAXED,
+ memory_order_consume = __ATOMIC_CONSUME,
+ memory_order_acquire = __ATOMIC_ACQUIRE,
+ memory_order_release = __ATOMIC_RELEASE,
+ memory_order_acq_rel = __ATOMIC_ACQ_REL,
+ memory_order_seq_cst = __ATOMIC_SEQ_CST
+} memory_order;
+
+class Obj {
+ int RefCnt;
+
+public:
+ int incRef() {
+ return __c11_atomic_fetch_add((volatile _Atomic(int) *)&RefCnt, 1,
+ memory_order_relaxed);
+ }
+
+ int decRef() {
+ return __c11_atomic_fetch_sub((volatile _Atomic(int) *)&RefCnt, 1,
+ memory_order_relaxed);
+ }
+
+ void foo();
+};
+
+class IntrusivePtr {
+ Obj *Ptr;
+
+public:
+ IntrusivePtr(Obj *Ptr) : Ptr(Ptr) {
+ Ptr->incRef();
+ }
+
+ IntrusivePtr(const IntrusivePtr &Other) : Ptr(Other.Ptr) {
+ Ptr->incRef();
+ }
+
+ ~IntrusivePtr() {
+ // We should not take the path on which the object is deleted.
+ if (Ptr->decRef() == 1)
+ delete Ptr;
+ }
+
+ Obj *getPtr() const { return Ptr; } // no-warning
+};
+
+void testDestroyLocalRefPtr() {
+ IntrusivePtr p1(new Obj());
+ {
+ IntrusivePtr p2(p1);
+ }
+
+ // p1 still maintains ownership. The object is not deleted.
+ p1.getPtr()->foo(); // no-warning
+}
+
+void testDestroySymbolicRefPtr(const IntrusivePtr &p1) {
+ {
+ IntrusivePtr p2(p1);
+ }
+
+ // p1 still maintains ownership. The object is not deleted.
+ p1.getPtr()->foo(); // no-warning
+}
diff --git a/test/Analysis/NewDelete-checker-test.cpp b/test/Analysis/NewDelete-checker-test.cpp
index 66e837572bb0..620237cd6ede 100644
--- a/test/Analysis/NewDelete-checker-test.cpp
+++ b/test/Analysis/NewDelete-checker-test.cpp
@@ -1,5 +1,12 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -fblocks -verify %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -fblocks -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -fblocks -analyzer-config c++-allocator-inlining=true -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -fblocks -analyzer-config c++-allocator-inlining=true -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -fblocks -DTEST_INLINABLE_ALLOCATORS -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -fblocks -DTEST_INLINABLE_ALLOCATORS -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -fblocks -analyzer-config c++-allocator-inlining=true -DTEST_INLINABLE_ALLOCATORS -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -fblocks -analyzer-config c++-allocator-inlining=true -DTEST_INLINABLE_ALLOCATORS -verify %s
+
#include "Inputs/system-header-simulator-cxx.h"
typedef __typeof__(sizeof(int)) size_t;
@@ -45,14 +52,18 @@ void testGlobalNoThrowPlacementOpNewBeforeOverload() {
void *p = operator new(0, std::nothrow);
}
#ifdef LEAKS
-// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
+#ifndef TEST_INLINABLE_ALLOCATORS
+// expected-warning@-3{{Potential leak of memory pointed to by 'p'}}
+#endif
#endif
void testGlobalNoThrowPlacementExprNewBeforeOverload() {
int *p = new(std::nothrow) int;
}
#ifdef LEAKS
-// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
+#ifndef TEST_INLINABLE_ALLOCATORS
+// expected-warning@-3{{Potential leak of memory pointed to by 'p'}}
+#endif
#endif
//----- Standard pointer placement operators
@@ -186,7 +197,10 @@ void testExprDeleteArrArg() {
void testAllocDeallocNames() {
int *p = new(std::nothrow) int[1];
- delete[] (++p); // expected-warning{{Argument to 'delete[]' is offset by 4 bytes from the start of memory allocated by 'new[]'}}
+ delete[] (++p);
+#ifndef TEST_INLINABLE_ALLOCATORS
+ // expected-warning@-2{{Argument to 'delete[]' is offset by 4 bytes from the start of memory allocated by 'new[]'}}
+#endif
}
//--------------------------------
diff --git a/test/Analysis/NewDelete-custom.cpp b/test/Analysis/NewDelete-custom.cpp
index f06ff4a858e5..f5a2952699ff 100644
--- a/test/Analysis/NewDelete-custom.cpp
+++ b/test/Analysis/NewDelete-custom.cpp
@@ -1,8 +1,10 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete,unix.Malloc -std=c++11 -fblocks -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete,cplusplus.NewDeleteLeaks,unix.Malloc -std=c++11 -DLEAKS -fblocks -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete,unix.Malloc -std=c++11 -analyzer-config c++-allocator-inlining=false -fblocks -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete,cplusplus.NewDeleteLeaks,unix.Malloc -std=c++11 -analyzer-config c++-allocator-inlining=false -DLEAKS=1 -fblocks -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete,unix.Malloc -std=c++11 -DALLOCATOR_INLINING=1 -fblocks -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete,cplusplus.NewDeleteLeaks,unix.Malloc -std=c++11 -DLEAKS=1 -DALLOCATOR_INLINING=1 -fblocks -verify %s
#include "Inputs/system-header-simulator-cxx.h"
-#ifndef LEAKS
+#if !(LEAKS && !ALLOCATOR_INLINING)
// expected-no-diagnostics
#endif
@@ -11,7 +13,7 @@ void *allocator(std::size_t size);
void *operator new[](std::size_t size) throw() { return allocator(size); }
void *operator new(std::size_t size) throw() { return allocator(size); }
-void *operator new(std::size_t size, std::nothrow_t& nothrow) throw() { return allocator(size); }
+void *operator new(std::size_t size, const std::nothrow_t &nothrow) throw() { return allocator(size); }
void *operator new(std::size_t, double d);
class C {
@@ -26,7 +28,7 @@ void testNewMethod() {
C *c3 = ::new C;
}
-#ifdef LEAKS
+#if LEAKS && !ALLOCATOR_INLINING
// expected-warning@-2{{Potential leak of memory pointed to by 'c3'}}
#endif
@@ -37,7 +39,7 @@ void testOpNewArray() {
void testNewExprArray() {
int *p = new int[0];
}
-#ifdef LEAKS
+#if LEAKS && !ALLOCATOR_INLINING
// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
#endif
@@ -50,30 +52,27 @@ void testOpNew() {
void testNewExpr() {
int *p = new int;
}
-#ifdef LEAKS
+#if LEAKS && !ALLOCATOR_INLINING
// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
#endif
//----- Custom NoThrow placement operators
void testOpNewNoThrow() {
- void *p = operator new(0, std::nothrow);
+ void *p = operator new(0, std::nothrow); // call is inlined, no warn
}
-#ifdef LEAKS
-// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
-#endif
void testNewExprNoThrow() {
int *p = new(std::nothrow) int;
}
-#ifdef LEAKS
+#if LEAKS && !ALLOCATOR_INLINING
// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
#endif
//----- Custom placement operators
void testOpNewPlacement() {
void *p = operator new(0, 0.1); // no warn
-}
+}
void testNewExprPlacement() {
int *p = new(0.1) int; // no warn
diff --git a/test/Analysis/NewDelete-intersections.mm b/test/Analysis/NewDelete-intersections.mm
index aa52c7902888..b3707858f00c 100644
--- a/test/Analysis/NewDelete-intersections.mm
+++ b/test/Analysis/NewDelete-intersections.mm
@@ -1,5 +1,7 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -fblocks -verify %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete,cplusplus.NewDeleteLeaks -std=c++11 -DLEAKS -fblocks -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -fblocks -DTEST_INLINABLE_ALLOCATORS -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete,cplusplus.NewDeleteLeaks -std=c++11 -DLEAKS -fblocks -DTEST_INLINABLE_ALLOCATORS -verify %s
#include "Inputs/system-header-simulator-cxx.h"
#include "Inputs/system-header-simulator-objc.h"
diff --git a/test/Analysis/NewDelete-path-notes.cpp b/test/Analysis/NewDelete-path-notes.cpp
index ac760ca60eb4..48c402d25c60 100644
--- a/test/Analysis/NewDelete-path-notes.cpp
+++ b/test/Analysis/NewDelete-path-notes.cpp
@@ -1,5 +1,6 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.NewDelete,unix.Malloc -analyzer-output=text -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.NewDelete,unix.Malloc -analyzer-output=plist -analyzer-config path-diagnostics-alternate=false %s -o %t.plist
+// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.NewDelete,unix.Malloc -analyzer-output=text -analyzer-config c++-allocator-inlining=true -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.NewDelete,unix.Malloc -analyzer-output=plist %s -o %t.plist
// RUN: FileCheck --input-file=%t.plist %s
void test() {
@@ -33,44 +34,10 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
+// CHECK-NEXT: <key>line</key><integer>7</integer>
// CHECK-NEXT: <key>col</key><integer>12</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -78,12 +45,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
+// CHECK-NEXT: <key>line</key><integer>7</integer>
// CHECK-NEXT: <key>col</key><integer>12</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
+// CHECK-NEXT: <key>line</key><integer>7</integer>
// CHECK-NEXT: <key>col</key><integer>18</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -103,25 +70,25 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
+// CHECK-NEXT: <key>line</key><integer>7</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
+// CHECK-NEXT: <key>line</key><integer>7</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>8</integer>
+// CHECK-NEXT: <key>line</key><integer>9</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>8</integer>
+// CHECK-NEXT: <key>line</key><integer>9</integer>
// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -137,12 +104,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>8</integer>
+// CHECK-NEXT: <key>line</key><integer>9</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>8</integer>
+// CHECK-NEXT: <key>line</key><integer>9</integer>
// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -150,12 +117,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
+// CHECK-NEXT: <key>line</key><integer>11</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
+// CHECK-NEXT: <key>line</key><integer>11</integer>
// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -167,7 +134,7 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
+// CHECK-NEXT: <key>line</key><integer>11</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -175,12 +142,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
+// CHECK-NEXT: <key>line</key><integer>11</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
+// CHECK-NEXT: <key>line</key><integer>11</integer>
// CHECK-NEXT: <key>col</key><integer>12</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -200,12 +167,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
+// CHECK-NEXT: <key>line</key><integer>11</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
+// CHECK-NEXT: <key>line</key><integer>11</integer>
// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -213,12 +180,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
+// CHECK-NEXT: <key>line</key><integer>14</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
+// CHECK-NEXT: <key>line</key><integer>14</integer>
// CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -230,7 +197,7 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
+// CHECK-NEXT: <key>line</key><integer>14</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -238,12 +205,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
+// CHECK-NEXT: <key>line</key><integer>14</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
+// CHECK-NEXT: <key>line</key><integer>14</integer>
// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -267,7 +234,7 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>issue_hash_function_offset</key><string>8</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
+// CHECK-NEXT: <key>line</key><integer>14</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -279,7 +246,7 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
+// CHECK-NEXT: <key>line</key><integer>25</integer>
// CHECK-NEXT: <key>col</key><integer>2</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -287,12 +254,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
+// CHECK-NEXT: <key>line</key><integer>25</integer>
// CHECK-NEXT: <key>col</key><integer>2</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
+// CHECK-NEXT: <key>line</key><integer>25</integer>
// CHECK-NEXT: <key>col</key><integer>12</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -308,7 +275,7 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
+// CHECK-NEXT: <key>line</key><integer>19</integer>
// CHECK-NEXT: <key>col</key><integer>2</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -326,12 +293,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
+// CHECK-NEXT: <key>line</key><integer>19</integer>
// CHECK-NEXT: <key>col</key><integer>2</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
+// CHECK-NEXT: <key>line</key><integer>19</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -339,12 +306,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
+// CHECK-NEXT: <key>line</key><integer>20</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
+// CHECK-NEXT: <key>line</key><integer>20</integer>
// CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -356,7 +323,7 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
+// CHECK-NEXT: <key>line</key><integer>20</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -364,12 +331,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
+// CHECK-NEXT: <key>line</key><integer>20</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
+// CHECK-NEXT: <key>line</key><integer>20</integer>
// CHECK-NEXT: <key>col</key><integer>13</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -385,7 +352,7 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
+// CHECK-NEXT: <key>line</key><integer>25</integer>
// CHECK-NEXT: <key>col</key><integer>2</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -393,12 +360,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
+// CHECK-NEXT: <key>line</key><integer>25</integer>
// CHECK-NEXT: <key>col</key><integer>2</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
+// CHECK-NEXT: <key>line</key><integer>25</integer>
// CHECK-NEXT: <key>col</key><integer>12</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -418,12 +385,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
+// CHECK-NEXT: <key>line</key><integer>25</integer>
// CHECK-NEXT: <key>col</key><integer>2</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
+// CHECK-NEXT: <key>line</key><integer>25</integer>
// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -431,12 +398,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>26</integer>
+// CHECK-NEXT: <key>line</key><integer>27</integer>
// CHECK-NEXT: <key>col</key><integer>2</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>26</integer>
+// CHECK-NEXT: <key>line</key><integer>27</integer>
// CHECK-NEXT: <key>col</key><integer>7</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -448,7 +415,7 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>26</integer>
+// CHECK-NEXT: <key>line</key><integer>27</integer>
// CHECK-NEXT: <key>col</key><integer>2</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -456,12 +423,12 @@ void test(Odd *odd) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>26</integer>
+// CHECK-NEXT: <key>line</key><integer>27</integer>
// CHECK-NEXT: <key>col</key><integer>2</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>26</integer>
+// CHECK-NEXT: <key>line</key><integer>27</integer>
// CHECK-NEXT: <key>col</key><integer>11</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -485,7 +452,7 @@ void test(Odd *odd) {
// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>26</integer>
+// CHECK-NEXT: <key>line</key><integer>27</integer>
// CHECK-NEXT: <key>col</key><integer>2</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
diff --git a/test/Analysis/NewDeleteLeaks-PR19102.cpp b/test/Analysis/NewDeleteLeaks-PR19102.cpp
index 502db6122f5c..625b2d4b7af4 100644
--- a/test/Analysis/NewDeleteLeaks-PR19102.cpp
+++ b/test/Analysis/NewDeleteLeaks-PR19102.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDeleteLeaks -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDeleteLeaks -analyzer-config c++-allocator-inlining=true -verify %s
class A0 {};
diff --git a/test/Analysis/PR24184.cpp b/test/Analysis/PR24184.cpp
index 1280334d4d6a..bfc5ae6ea56b 100644
--- a/test/Analysis/PR24184.cpp
+++ b/test/Analysis/PR24184.cpp
@@ -1,3 +1,4 @@
+// UNSUPPORTED: z3
// RUN: %clang_analyze_cc1 -w -analyzer-eagerly-assume -fcxx-exceptions -analyzer-checker=core -analyzer-checker=alpha.core.PointerArithm,alpha.core.CastToStruct -analyzer-max-loop 64 -verify %s
// RUN: %clang_analyze_cc1 -w -analyzer-checker=core -analyzer-checker=cplusplus -fcxx-exceptions -analyzer-checker alpha.core.PointerArithm,alpha.core.CastToStruct -analyzer-max-loop 63 -verify %s
diff --git a/test/Analysis/PR37855.c b/test/Analysis/PR37855.c
new file mode 100644
index 000000000000..0779796531fd
--- /dev/null
+++ b/test/Analysis/PR37855.c
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -analyze -analyzer-eagerly-assume -analyzer-checker=core -w -DNO_CROSSCHECK -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-eagerly-assume -analyzer-checker=core -w -analyzer-config crosscheck-with-z3=true -verify %s
+// REQUIRES: z3
+
+typedef struct o p;
+struct o {
+ struct {
+ } s;
+};
+
+void q(*r, p2) { r < p2; }
+
+void k(l, node) {
+ struct {
+ p *node;
+ } * n, *nodep, path[sizeof(void)];
+ path->node = l;
+ for (n = path; node != l;) {
+ q(node, n->node);
+ nodep = n;
+ }
+ if (nodep) // expected-warning {{Branch condition evaluates to a garbage value}}
+ n[1].node->s;
+}
diff --git a/test/Analysis/PR38208.c b/test/Analysis/PR38208.c
new file mode 100644
index 000000000000..fb0a5a15eac6
--- /dev/null
+++ b/test/Analysis/PR38208.c
@@ -0,0 +1,43 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s
+
+// expected-no-diagnostics
+
+int foo(int a, int b) {
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ a += b; b -= a;
+ return a + b;
+}
diff --git a/test/Analysis/_Bool-increment-decrement.c b/test/Analysis/_Bool-increment-decrement.c
new file mode 100644
index 000000000000..477b6ed43830
--- /dev/null
+++ b/test/Analysis/_Bool-increment-decrement.c
@@ -0,0 +1,140 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection -verify -std=c99 -Dbool=_Bool -Dtrue=1 -Dfalse=0 %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection -verify -std=c11 -Dbool=_Bool -Dtrue=1 -Dfalse=0 %s
+extern void clang_analyzer_eval(bool);
+
+void test__Bool_value() {
+ {
+ bool b = true;
+ clang_analyzer_eval(b == 1); // expected-warning{{TRUE}}
+ }
+
+ {
+ bool b = false;
+ clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
+ }
+
+ {
+ bool b = -10;
+ clang_analyzer_eval(b == 1); // expected-warning{{TRUE}}
+ }
+
+ {
+ bool b = 10;
+ clang_analyzer_eval(b == 1); // expected-warning{{TRUE}}
+ }
+
+ {
+ bool b = 10;
+ b++;
+ clang_analyzer_eval(b == 1); // expected-warning{{TRUE}}
+ }
+
+ {
+ bool b = 0;
+ b++;
+ clang_analyzer_eval(b == 1); // expected-warning{{TRUE}}
+ }
+}
+
+void test__Bool_increment() {
+ {
+ bool b = true;
+ b++;
+ clang_analyzer_eval(b == 1); // expected-warning{{TRUE}}
+ }
+
+ {
+ bool b = false;
+ b++;
+ clang_analyzer_eval(b == 1); // expected-warning{{TRUE}}
+ }
+
+ {
+ bool b = true;
+ ++b;
+ clang_analyzer_eval(b == 1); // expected-warning{{TRUE}}
+ }
+
+ {
+ bool b = false;
+ ++b;
+ clang_analyzer_eval(b == 1); // expected-warning{{TRUE}}
+ }
+
+ {
+ bool b = 0;
+ ++b;
+ clang_analyzer_eval(b == 1); // expected-warning{{TRUE}}
+ }
+
+ {
+ bool b = 10;
+ ++b;
+ ++b;
+ clang_analyzer_eval(b == 1); // expected-warning{{TRUE}}
+ }
+
+ {
+ bool b = -10;
+ ++b;
+ clang_analyzer_eval(b == 1); // expected-warning{{TRUE}}
+ }
+
+ {
+ bool b = -1;
+ ++b;
+ clang_analyzer_eval(b == 1); // expected-warning{{TRUE}}
+ }
+}
+
+void test__Bool_decrement() {
+ {
+ bool b = true;
+ b--;
+ clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
+ }
+
+ {
+ bool b = false;
+ b--;
+ clang_analyzer_eval(b == 1); // expected-warning{{TRUE}}
+ }
+
+ {
+ bool b = true;
+ --b;
+ clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
+ }
+
+ {
+ bool b = false;
+ --b;
+ clang_analyzer_eval(b == 1); // expected-warning{{TRUE}}
+ }
+
+ {
+ bool b = 0;
+ --b;
+ clang_analyzer_eval(b == 1); // expected-warning{{TRUE}}
+ }
+
+ {
+ bool b = 10;
+ --b;
+ clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
+ --b;
+ clang_analyzer_eval(b == 1); // expected-warning{{TRUE}}
+ }
+
+ {
+ bool b = -10;
+ --b;
+ clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
+ }
+
+ {
+ bool b = 1;
+ --b;
+ clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
+ }
+}
diff --git a/test/Analysis/analyzeOneFunction.m b/test/Analysis/analyzeOneFunction.m
index a77abe1246b8..80f34ad525e2 100644
--- a/test/Analysis/analyzeOneFunction.m
+++ b/test/Analysis/analyzeOneFunction.m
@@ -38,7 +38,7 @@ typedef struct _NSZone NSZone;
-(id)myMethod {
Test1 *cell = [[[Test1 alloc] init] autorelease];
- NSString *string1 = [[NSString alloc] initWithFormat:@"test %f", 0.0]; // No warning: this function is not analized.
+ NSString *string1 = [[NSString alloc] initWithFormat:@"test %f", 0.0]; // No warning: this function is not analyzed.
cell.text = string1;
return cell;
diff --git a/test/Analysis/analyzer-config.c b/test/Analysis/analyzer-config.c
index 4daea898ecd0..c09800f44b63 100644
--- a/test/Analysis/analyzer-config.c
+++ b/test/Analysis/analyzer-config.c
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 %s -o /dev/null -analyzer-checker=core,osx.cocoa,debug.ConfigDumper -analyzer-max-loop 34 > %t 2>&1
-// RUN: FileCheck --input-file=%t %s
+// RUN: FileCheck --input-file=%t %s --match-full-lines
void bar() {}
void foo() {
@@ -15,20 +15,24 @@ void foo() {
// CHECK-NEXT: cfg-implicit-dtors = true
// CHECK-NEXT: cfg-lifetime = false
// CHECK-NEXT: cfg-loopexit = false
-// CHECK-NEXT: cfg-temporary-dtors = false
+// CHECK-NEXT: cfg-rich-constructors = true
+// CHECK-NEXT: cfg-scopes = false
+// CHECK-NEXT: cfg-temporary-dtors = true
+// CHECK-NEXT: elide-constructors = true
+// CHECK-NEXT: exploration_strategy = unexplored_first_queue
// CHECK-NEXT: faux-bodies = true
// CHECK-NEXT: graph-trim-interval = 1000
// CHECK-NEXT: inline-lambdas = true
// CHECK-NEXT: ipa = dynamic-bifurcate
// CHECK-NEXT: ipa-always-inline-size = 3
-// CHECK-NEXT: leak-diagnostics-reference-allocation = false
// CHECK-NEXT: max-inlinable-size = 100
// CHECK-NEXT: max-nodes = 225000
// CHECK-NEXT: max-times-inline-large = 32
// CHECK-NEXT: min-cfg-size-treat-functions-as-large = 14
// CHECK-NEXT: mode = deep
// CHECK-NEXT: region-store-small-struct-limit = 2
+// CHECK-NEXT: serialize-stats = false
// CHECK-NEXT: unroll-loops = false
// CHECK-NEXT: widen-loops = false
// CHECK-NEXT: [stats]
-// CHECK-NEXT: num-entries = 19
+// CHECK-NEXT: num-entries = 23
diff --git a/test/Analysis/analyzer-config.cpp b/test/Analysis/analyzer-config.cpp
index a08e85e53e48..e87045448d3a 100644
--- a/test/Analysis/analyzer-config.cpp
+++ b/test/Analysis/analyzer-config.cpp
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 %s -o /dev/null -analyzer-checker=core,osx.cocoa,debug.ConfigDumper -analyzer-max-loop 34 > %t 2>&1
-// RUN: FileCheck --input-file=%t %s
+// RUN: FileCheck --input-file=%t %s --match-full-lines
void bar() {}
void foo() {
@@ -12,7 +12,9 @@ void foo() {
class Foo {
public:
- void bar() {}
+ ~Foo() {}
+ void baz() { Foo(); }
+ void bar() { const Foo &f = Foo(); }
void foo() { bar(); }
};
@@ -21,25 +23,31 @@ public:
// CHECK-NEXT: c++-inlining = destructors
// CHECK-NEXT: c++-shared_ptr-inlining = false
// CHECK-NEXT: c++-stdlib-inlining = true
+// CHECK-NEXT: c++-temp-dtor-inlining = true
// CHECK-NEXT: c++-template-inlining = true
// CHECK-NEXT: cfg-conditional-static-initializers = true
// CHECK-NEXT: cfg-implicit-dtors = true
// CHECK-NEXT: cfg-lifetime = false
// CHECK-NEXT: cfg-loopexit = false
-// CHECK-NEXT: cfg-temporary-dtors = false
+// CHECK-NEXT: cfg-rich-constructors = true
+// CHECK-NEXT: cfg-scopes = false
+// CHECK-NEXT: cfg-temporary-dtors = true
+// CHECK-NEXT: elide-constructors = true
+// CHECK-NEXT: experimental-enable-naive-ctu-analysis = false
+// CHECK-NEXT: exploration_strategy = unexplored_first_queue
// CHECK-NEXT: faux-bodies = true
// CHECK-NEXT: graph-trim-interval = 1000
// CHECK-NEXT: inline-lambdas = true
// CHECK-NEXT: ipa = dynamic-bifurcate
// CHECK-NEXT: ipa-always-inline-size = 3
-// CHECK-NEXT: leak-diagnostics-reference-allocation = false
// CHECK-NEXT: max-inlinable-size = 100
// CHECK-NEXT: max-nodes = 225000
// CHECK-NEXT: max-times-inline-large = 32
// CHECK-NEXT: min-cfg-size-treat-functions-as-large = 14
// CHECK-NEXT: mode = deep
// CHECK-NEXT: region-store-small-struct-limit = 2
+// CHECK-NEXT: serialize-stats = false
// CHECK-NEXT: unroll-loops = false
// CHECK-NEXT: widen-loops = false
// CHECK-NEXT: [stats]
-// CHECK-NEXT: num-entries = 24
+// CHECK-NEXT: num-entries = 30
diff --git a/test/Analysis/analyzer-stats.c b/test/Analysis/analyzer-stats.c
index 5a40d196bb1f..b58e862f6c65 100644
--- a/test/Analysis/analyzer-stats.c
+++ b/test/Analysis/analyzer-stats.c
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,deadcode.DeadStores,debug.Stats -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,deadcode.DeadStores,debug.Stats -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks -analyzer-max-loop 4 %s
int foo();
@@ -12,3 +12,19 @@ int test() { // expected-warning-re{{test -> Total CFGBlocks: {{[0-9]+}} | Unrea
a /= 4;
return a;
}
+
+
+int sink() // expected-warning-re{{sink -> Total CFGBlocks: {{[0-9]+}} | Unreachable CFGBlocks: 1 | Exhausted Block: yes | Empty WorkList: yes}}
+{
+ for (int i = 0; i < 10; ++i) // expected-warning {{(sink): The analyzer generated a sink at this point}}
+ ++i;
+
+ return 0;
+}
+
+int emptyConditionLoop() // expected-warning-re{{emptyConditionLoop -> Total CFGBlocks: {{[0-9]+}} | Unreachable CFGBlocks: 0 | Exhausted Block: yes | Empty WorkList: yes}}
+{
+ int num = 1;
+ for (;;)
+ num++;
+}
diff --git a/test/Analysis/auto-obj-dtors-cfg-output.cpp b/test/Analysis/auto-obj-dtors-cfg-output.cpp
index cc47c92360a5..7e678a1ec78d 100644
--- a/test/Analysis/auto-obj-dtors-cfg-output.cpp
+++ b/test/Analysis/auto-obj-dtors-cfg-output.cpp
@@ -1,8 +1,25 @@
-// RUN: %clang_analyze_cc1 -fcxx-exceptions -fexceptions -analyzer-checker=debug.DumpCFG %s > %t 2>&1
-// RUN: FileCheck --input-file=%t %s
+// RUN: %clang_analyze_cc1 -std=c++98 -fcxx-exceptions -fexceptions -analyzer-checker=debug.DumpCFG -analyzer-config cfg-rich-constructors=false %s > %t 2>&1
+// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX98,WARNINGS,CXX98-WARNINGS %s
+// RUN: %clang_analyze_cc1 -std=c++98 -fcxx-exceptions -fexceptions -analyzer-checker=debug.DumpCFG -analyzer-config cfg-rich-constructors=true %s > %t 2>&1
+// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX98,ANALYZER,CXX98-ANALYZER %s
+// RUN: %clang_analyze_cc1 -std=c++11 -fcxx-exceptions -fexceptions -analyzer-checker=debug.DumpCFG -analyzer-config cfg-rich-constructors=false %s > %t 2>&1
+// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX11,WARNINGS,CXX11-WARNINGS %s
+// RUN: %clang_analyze_cc1 -std=c++11 -fcxx-exceptions -fexceptions -analyzer-checker=debug.DumpCFG -analyzer-config cfg-rich-constructors=true %s > %t 2>&1
+// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX11,ANALYZER,CXX11-ANALYZER %s
+
+// This file tests how we construct two different flavors of the Clang CFG -
+// the CFG used by the Sema analysis-based warnings and the CFG used by the
+// static analyzer. The difference in the behavior is checked via FileCheck
+// prefixes (WARNINGS and ANALYZER respectively). When introducing new analyzer
+// flags, no new run lines should be added - just these flags would go to the
+// respective line depending on where is it turned on and where is it turned
+// off. Feel free to add tests that test only one of the CFG flavors if you're
+// not sure how the other flavor is supposed to work in your case.
class A {
public:
+ int x;
+
// CHECK: [B1 (ENTRY)]
// CHECK-NEXT: Succs (1): B0
// CHECK: [B0 (EXIT)]
@@ -32,12 +49,14 @@ extern const bool UV;
// CHECK: [B2 (ENTRY)]
// CHECK-NEXT: Succs (1): B1
// CHECK: [B1]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B1.2], class A)
// CHECK-NEXT: 2: A a;
// CHECK-NEXT: 3: a
// CHECK-NEXT: 4: [B1.3] (ImplicitCastExpr, NoOp, const class A)
// CHECK-NEXT: 5: const A &b = a;
-// CHECK-NEXT: 6: A() (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 6: A() (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 6: A() (CXXConstructExpr, [B1.9], class A)
// CHECK-NEXT: 7: [B1.6] (BindTemporary)
// CHECK-NEXT: 8: [B1.7] (ImplicitCastExpr, NoOp, const class A)
// CHECK-NEXT: 9: [B1.8]
@@ -57,9 +76,292 @@ void test_const_ref() {
// CHECK: [B2 (ENTRY)]
// CHECK-NEXT: Succs (1): B1
// CHECK: [B1]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A [2])
+// WARNINGS-NEXT: 1: A() (CXXConstructExpr, class A)
+// CXX98-ANALYZER-NEXT: 1: A() (CXXConstructExpr, [B1.2], class A)
+// CXX11-ANALYZER-NEXT: 1: A() (CXXConstructExpr, [B1.3], class A)
+// CHECK-NEXT: 2: [B1.1] (BindTemporary)
+// CXX98-NEXT: 3: [B1.2].x
+// CXX98-NEXT: 4: [B1.3]
+// CXX98-NEXT: 5: const int &x = A().x;
+// CXX98-NEXT: 6: [B1.5].~A() (Implicit destructor)
+// CXX11-NEXT: 3: [B1.2]
+// CXX11-NEXT: 4: [B1.3].x
+// CXX11-NEXT: 5: [B1.4] (ImplicitCastExpr, NoOp, const int)
+// CXX11-NEXT: 6: const int &x = A().x;
+// CXX11-NEXT: 7: [B1.6].~A() (Implicit destructor)
+// CHECK-NEXT: Preds (1): B2
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+void test_const_ref_to_field() {
+ const int &x = A().x;
+}
+
+// CHECK: [B2 (ENTRY)]
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B1]
+// WARNINGS-NEXT: 1: A() (CXXConstructExpr, class A)
+// CXX98-ANALYZER-NEXT: 1: A() (CXXConstructExpr, [B1.2], class A)
+// CXX11-ANALYZER-NEXT: 1: A() (CXXConstructExpr, [B1.3], class A)
+// CHECK-NEXT: 2: [B1.1] (BindTemporary)
+// CXX98-NEXT: 3: A::x
+// CXX98-NEXT: 4: &[B1.3]
+// CXX98-NEXT: 5: [B1.2] .* [B1.4]
+// CXX98-NEXT: 6: [B1.5]
+// CXX98-NEXT: 7: const int &x = A() .* &A::x;
+// CXX98-NEXT: 8: [B1.7].~A() (Implicit destructor)
+// CXX11-NEXT: 3: [B1.2]
+// CXX11-NEXT: 4: A::x
+// CXX11-NEXT: 5: &[B1.4]
+// CXX11-NEXT: 6: [B1.3] .* [B1.5]
+// CXX11-NEXT: 7: [B1.6] (ImplicitCastExpr, NoOp, const int)
+// CXX11-NEXT: 8: const int &x = A() .* &A::x;
+// CXX11-NEXT: 9: [B1.8].~A() (Implicit destructor)
+// CHECK-NEXT: Preds (1): B2
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+void test_pointer_to_member() {
+ const int &x = A().*&A::x;
+}
+
+// FIXME: There should be automatic destructors at the end of scope.
+// CHECK: [B2 (ENTRY)]
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B1]
+// WARNINGS-NEXT: 1: A() (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: A() (CXXConstructExpr, [B1.4], class A)
+// CHECK-NEXT: 2: [B1.1] (BindTemporary)
+// CHECK-NEXT: 3: [B1.2] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 4: [B1.3]
+// CHECK-NEXT: 5: {[B1.4]}
+// CHECK-NEXT: 6: B b = {A()};
+// WARNINGS-NEXT: 7: A() (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 7: A() (CXXConstructExpr, [B1.10], class A)
+// CHECK-NEXT: 8: [B1.7] (BindTemporary)
+// CHECK-NEXT: 9: [B1.8] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 10: [B1.9]
+// CHECK-NEXT: 11: {[B1.10]}
+// WARNINGS-NEXT: 12: A() (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 12: A() (CXXConstructExpr, [B1.15], class A)
+// CHECK-NEXT: 13: [B1.12] (BindTemporary)
+// CHECK-NEXT: 14: [B1.13] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 15: [B1.14]
+// CHECK-NEXT: 16: {[B1.15]}
+// CHECK-NEXT: 17: {[B1.10], [B1.15]}
+// CHECK-NEXT: 18: B bb[2] = {A(), A()};
+// CHECK-NEXT: Preds (1): B2
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+void test_aggregate_lifetime_extension() {
+ struct B {
+ const A &x;
+ };
+
+ B b = {A()};
+ B bb[2] = {A(), A()};
+}
+
+// In C++98 such class 'C' will not be an aggregate.
+#if __cplusplus >= 201103L
+// FIXME: There should be automatic destructors at the end of the scope.
+// CXX11: [B2 (ENTRY)]
+// CXX11-NEXT: Succs (1): B1
+// CXX11: [B1]
+// CXX11-WARNINGS-NEXT: 1: A() (CXXConstructExpr, class A)
+// CXX11-ANALYZER-NEXT: 1: A() (CXXConstructExpr, [B1.2], [B1.4], class A)
+// CXX11-NEXT: 2: [B1.1] (BindTemporary)
+// CXX11-NEXT: 3: [B1.2] (ImplicitCastExpr, NoOp, const class A)
+// CXX11-NEXT: 4: [B1.3]
+// CXX11-NEXT: 5: [B1.4] (CXXConstructExpr, const class A)
+// CXX11-WARNINGS-NEXT: 6: A() (CXXConstructExpr, class A)
+// CXX11-ANALYZER-NEXT: 6: A() (CXXConstructExpr, [B1.7], [B1.9], class A)
+// CXX11-NEXT: 7: [B1.6] (BindTemporary)
+// CXX11-NEXT: 8: [B1.7] (ImplicitCastExpr, NoOp, const class A)
+// CXX11-NEXT: 9: [B1.8]
+// CXX11-NEXT: 10: [B1.9] (CXXConstructExpr, const class A)
+// FIXME: Why does it look as if the initializer list consumes uncopied objects?
+// CXX11-NEXT: 11: {[B1.2], [B1.7]}
+// CXX11-NEXT: 12: [B1.11] (BindTemporary)
+// CXX11-NEXT: 13: [B1.12]
+// CXX11-NEXT: 14: {[B1.13]}
+// Double curly braces trigger regexps, escape as per FileCheck manual.
+// CXX11-NEXT: 15: C c = {{[{][{]}}A(), A(){{[}][}]}};
+// CXX11-NEXT: 16: ~A() (Temporary object destructor)
+// CXX11-NEXT: 17: ~A() (Temporary object destructor)
+// CXX11-WARNINGS-NEXT: 18: A() (CXXConstructExpr, class A)
+// CXX11-ANALYZER-NEXT: 18: A() (CXXConstructExpr, [B1.19], [B1.21], class A)
+// CXX11-NEXT: 19: [B1.18] (BindTemporary)
+// CXX11-NEXT: 20: [B1.19] (ImplicitCastExpr, NoOp, const class A)
+// CXX11-NEXT: 21: [B1.20]
+// CXX11-NEXT: 22: [B1.21] (CXXConstructExpr, const class A)
+// CXX11-WARNINGS-NEXT: 23: A() (CXXConstructExpr, class A)
+// CXX11-ANALYZER-NEXT: 23: A() (CXXConstructExpr, [B1.24], [B1.26], class A)
+// CXX11-NEXT: 24: [B1.23] (BindTemporary)
+// CXX11-NEXT: 25: [B1.24] (ImplicitCastExpr, NoOp, const class A)
+// CXX11-NEXT: 26: [B1.25]
+// CXX11-NEXT: 27: [B1.26] (CXXConstructExpr, const class A)
+// FIXME: Why does it look as if the initializer list consumes uncopied objects?
+// CXX11-NEXT: 28: {[B1.19], [B1.24]}
+// CXX11-NEXT: 29: [B1.28] (BindTemporary)
+// CXX11-NEXT: 30: [B1.29]
+// CXX11-NEXT: 31: {[B1.30]}
+// CXX11-WARNINGS-NEXT: 32: A() (CXXConstructExpr, class A)
+// CXX11-ANALYZER-NEXT: 32: A() (CXXConstructExpr, [B1.33], [B1.35], class A)
+// CXX11-NEXT: 33: [B1.32] (BindTemporary)
+// CXX11-NEXT: 34: [B1.33] (ImplicitCastExpr, NoOp, const class A)
+// CXX11-NEXT: 35: [B1.34]
+// CXX11-NEXT: 36: [B1.35] (CXXConstructExpr, const class A)
+// CXX11-WARNINGS-NEXT: 37: A() (CXXConstructExpr, class A)
+// CXX11-ANALYZER-NEXT: 37: A() (CXXConstructExpr, [B1.38], [B1.40], class A)
+// CXX11-NEXT: 38: [B1.37] (BindTemporary)
+// CXX11-NEXT: 39: [B1.38] (ImplicitCastExpr, NoOp, const class A)
+// CXX11-NEXT: 40: [B1.39]
+// CXX11-NEXT: 41: [B1.40] (CXXConstructExpr, const class A)
+// FIXME: Why does it look as if the initializer list consumes uncopied objects?
+// CXX11-NEXT: 42: {[B1.33], [B1.38]}
+// CXX11-NEXT: 43: [B1.42] (BindTemporary)
+// CXX11-NEXT: 44: [B1.43]
+// CXX11-NEXT: 45: {[B1.44]}
+// Double curly braces trigger regexps, escape as per FileCheck manual.
+// CXX11-NEXT: 46: {{[{][{]}}[B1.30]}, {[B1.44]{{[}][}]}}
+// Double curly braces trigger regexps, escape as per FileCheck manual.
+// CXX11-NEXT: 47: C cc[2] = {{[{][{][{]}}A(), A(){{[}][}]}}, {{[{][{]}}A(), A(){{[}][}][}]}};
+// CXX11-NEXT: 48: ~A() (Temporary object destructor)
+// CXX11-NEXT: 49: ~A() (Temporary object destructor)
+// CXX11-NEXT: 50: ~A() (Temporary object destructor)
+// CXX11-NEXT: 51: ~A() (Temporary object destructor)
+// CXX11-NEXT: Preds (1): B2
+// CXX11-NEXT: Succs (1): B0
+// CXX11: [B0 (EXIT)]
+// CXX11-NEXT: Preds (1): B1
+void test_aggregate_array_lifetime_extension() {
+ struct C {
+ const A (&z)[2];
+ };
+
+ // Until C++17 there are elidable copies here, so there should be 9 temporary
+ // destructors of A()s. There are no destructors of 'c' and 'cc' because this
+ // aggregate has no destructor. Instead, arrays are lifetime-extended,
+ // and copies of A()s within them need to be destroyed via automatic
+ // destructors.
+ C c = {{A(), A()}};
+ C cc[2] = {{{A(), A()}}, {{A(), A()}}};
+}
+#endif
+
+// CHECK: [B2 (ENTRY)]
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B1]
+// WARNINGS-NEXT: 1: A() (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: A() (CXXConstructExpr, [B1.2], [B1.4], class A)
+// CHECK-NEXT: 2: [B1.1] (BindTemporary)
+// CHECK-NEXT: 3: [B1.2] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 4: [B1.3]
+// CHECK-NEXT: 5: [B1.4] (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 6: A() (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 6: A() (CXXConstructExpr, [B1.7], [B1.9], class A)
+// CHECK-NEXT: 7: [B1.6] (BindTemporary)
+// CHECK-NEXT: 8: [B1.7] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 9: [B1.8]
+// CHECK-NEXT: 10: [B1.9] (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 11: A() (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 11: A() (CXXConstructExpr, [B1.12], [B1.14], class A)
+// CHECK-NEXT: 12: [B1.11] (BindTemporary)
+// CHECK-NEXT: 13: [B1.12] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 14: [B1.13]
+// CHECK-NEXT: 15: [B1.14] (CXXConstructExpr, class A)
+// FIXME: Why does it look as if the initializer list consumes uncopied objects?
+// CHECK-NEXT: 16: {[B1.7], [B1.12]}
+// FIXME: Why does it look as if the initializer list consumes uncopied objects?
+// CHECK-NEXT: 17: {[B1.2], {[B1.7], [B1.12]}}
+// CHECK-NEXT: 18: D d = {A(), {A(), A()}};
+// CHECK-NEXT: 19: ~A() (Temporary object destructor)
+// CHECK-NEXT: 20: ~A() (Temporary object destructor)
+// CHECK-NEXT: 21: ~A() (Temporary object destructor)
+// WARNINGS-NEXT: 22: A() (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 22: A() (CXXConstructExpr, [B1.23], [B1.25], class A)
+// CHECK-NEXT: 23: [B1.22] (BindTemporary)
+// CHECK-NEXT: 24: [B1.23] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 25: [B1.24]
+// CHECK-NEXT: 26: [B1.25] (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 27: A() (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 27: A() (CXXConstructExpr, [B1.28], [B1.30], class A)
+// CHECK-NEXT: 28: [B1.27] (BindTemporary)
+// CHECK-NEXT: 29: [B1.28] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 30: [B1.29]
+// CHECK-NEXT: 31: [B1.30] (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 32: A() (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 32: A() (CXXConstructExpr, [B1.33], [B1.35], class A)
+// CHECK-NEXT: 33: [B1.32] (BindTemporary)
+// CHECK-NEXT: 34: [B1.33] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 35: [B1.34]
+// CHECK-NEXT: 36: [B1.35] (CXXConstructExpr, class A)
+// FIXME: Why does it look as if the initializer list consumes uncopied objects?
+// CHECK-NEXT: 37: {[B1.28], [B1.33]}
+// FIXME: Why does it look as if the initializer list consumes uncopied objects?
+// CHECK-NEXT: 38: {[B1.23], {[B1.28], [B1.33]}}
+// WARNINGS-NEXT: 39: A() (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 39: A() (CXXConstructExpr, [B1.40], [B1.42], class A)
+// CHECK-NEXT: 40: [B1.39] (BindTemporary)
+// CHECK-NEXT: 41: [B1.40] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 42: [B1.41]
+// CHECK-NEXT: 43: [B1.42] (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 44: A() (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 44: A() (CXXConstructExpr, [B1.45], [B1.47], class A)
+// CHECK-NEXT: 45: [B1.44] (BindTemporary)
+// CHECK-NEXT: 46: [B1.45] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 47: [B1.46]
+// CHECK-NEXT: 48: [B1.47] (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 49: A() (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 49: A() (CXXConstructExpr, [B1.50], [B1.52], class A)
+// CHECK-NEXT: 50: [B1.49] (BindTemporary)
+// CHECK-NEXT: 51: [B1.50] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 52: [B1.51]
+// CHECK-NEXT: 53: [B1.52] (CXXConstructExpr, class A)
+// FIXME: Why does it look as if the initializer list consumes uncopied objects?
+// CHECK-NEXT: 54: {[B1.45], [B1.50]}
+// FIXME: Why does it look as if the initializer list consumes uncopied objects?
+// CHECK-NEXT: 55: {[B1.40], {[B1.45], [B1.50]}}
+// Double curly braces trigger regexps, escape as per FileCheck manual.
+// CHECK-NEXT: 56: {{[{][{]}}[B1.23], {[B1.28], [B1.33]{{[}][}]}}, {[B1.40], {[B1.45], [B1.50]{{[}][}][}]}}
+// Double curly braces trigger regexps, escape as per FileCheck manual.
+// CHECK-NEXT: 57: D dd[2] = {{[{][{]}}A(), {A(), A(){{[}][}]}}, {A(), {A(), A(){{[}][}][}]}};
+// CHECK-NEXT: 58: ~A() (Temporary object destructor)
+// CHECK-NEXT: 59: ~A() (Temporary object destructor)
+// CHECK-NEXT: 60: ~A() (Temporary object destructor)
+// CHECK-NEXT: 61: ~A() (Temporary object destructor)
+// CHECK-NEXT: 62: ~A() (Temporary object destructor)
+// CHECK-NEXT: 63: ~A() (Temporary object destructor)
+// CHECK-NEXT: 64: [B1.57].~D() (Implicit destructor)
+// CHECK-NEXT: 65: [B1.18].~D() (Implicit destructor)
+// CHECK-NEXT: Preds (1): B2
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+void test_aggregate_with_nontrivial_own_destructor() {
+ struct D {
+ A y;
+ A w[2];
+ };
+
+ // Until C++17 there are elidable copies here, so there should be 9 temporary
+ // destructors of A()s. Destructors of 'd' and 'dd' should implicitly
+ // take care of the copies, so there should not be automatic destructors
+ // for copies of A()s.
+ D d = {A(), {A(), A()}};
+ D dd[2] = {{A(), {A(), A()}}, {A(), {A(), A()}}};
+}
+
+// CHECK: [B2 (ENTRY)]
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B1]
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A [2])
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B1.2], class A [2])
// CHECK-NEXT: 2: A a[2];
-// CHECK-NEXT: 3: (CXXConstructExpr, class A [0])
+// WARNINGS-NEXT: 3: (CXXConstructExpr, class A [0])
+// ANALYZER-NEXT: 3: (CXXConstructExpr, [B1.4], class A [0])
// CHECK-NEXT: 4: A b[0];
// CHECK-NEXT: 5: [B1.2].~A() (Implicit destructor)
// CHECK-NEXT: Preds (1): B2
@@ -74,15 +376,19 @@ void test_array() {
// CHECK: [B2 (ENTRY)]
// CHECK-NEXT: Succs (1): B1
// CHECK: [B1]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B1.2], class A)
// CHECK-NEXT: 2: A a;
-// CHECK-NEXT: 3: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 3: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 3: (CXXConstructExpr, [B1.4], class A)
// CHECK-NEXT: 4: A c;
-// CHECK-NEXT: 5: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 5: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 5: (CXXConstructExpr, [B1.6], class A)
// CHECK-NEXT: 6: A d;
// CHECK-NEXT: 7: [B1.6].~A() (Implicit destructor)
// CHECK-NEXT: 8: [B1.4].~A() (Implicit destructor)
-// CHECK-NEXT: 9: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 9: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 9: (CXXConstructExpr, [B1.10], class A)
// CHECK: 10: A b;
// CHECK: 11: [B1.10].~A() (Implicit destructor)
// CHECK: 12: [B1.2].~A() (Implicit destructor)
@@ -101,7 +407,8 @@ void test_scope() {
// CHECK: [B4 (ENTRY)]
// CHECK-NEXT: Succs (1): B3
// CHECK: [B1]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B1.2], class A)
// CHECK-NEXT: 2: A c;
// CHECK-NEXT: 3: [B1.2].~A() (Implicit destructor)
// CHECK-NEXT: 4: [B3.4].~A() (Implicit destructor)
@@ -115,9 +422,11 @@ void test_scope() {
// CHECK-NEXT: Preds (1): B3
// CHECK-NEXT: Succs (1): B0
// CHECK: [B3]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B3.2], class A)
// CHECK-NEXT: 2: A a;
-// CHECK-NEXT: 3: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 3: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 3: (CXXConstructExpr, [B3.4], class A)
// CHECK-NEXT: 4: A b;
// CHECK-NEXT: 5: UV
// CHECK-NEXT: 6: [B3.5] (ImplicitCastExpr, LValueToRValue, _Bool)
@@ -137,7 +446,8 @@ void test_return() {
// CHECK-NEXT: Succs (1): B7
// CHECK: [B1]
// CHECK: l1:
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B1.2], class A)
// CHECK-NEXT: 2: A c;
// CHECK-NEXT: 3: [B1.2].~A() (Implicit destructor)
// CHECK-NEXT: 4: [B6.2].~A() (Implicit destructor)
@@ -145,7 +455,8 @@ void test_return() {
// CHECK-NEXT: Preds (2): B2 B3
// CHECK-NEXT: Succs (1): B0
// CHECK: [B2]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B2.2], class A)
// CHECK-NEXT: 2: A b;
// CHECK-NEXT: 3: [B2.2].~A() (Implicit destructor)
// CHECK-NEXT: 4: [B6.4].~A() (Implicit destructor)
@@ -170,9 +481,11 @@ void test_return() {
// CHECK-NEXT: Succs (1): B6
// CHECK: [B6]
// CHECK: l0:
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B6.2], class A)
// CHECK-NEXT: 2: A b;
-// CHECK-NEXT: 3: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 3: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 3: (CXXConstructExpr, [B6.4], class A)
// CHECK-NEXT: 4: A a;
// CHECK-NEXT: 5: UV
// CHECK-NEXT: 6: [B6.5] (ImplicitCastExpr, LValueToRValue, _Bool)
@@ -180,7 +493,8 @@ void test_return() {
// CHECK-NEXT: Preds (2): B7 B5
// CHECK-NEXT: Succs (2): B5 B4
// CHECK: [B7]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B7.2], class A)
// CHECK-NEXT: 2: A a;
// CHECK-NEXT: Preds (1): B8
// CHECK-NEXT: Succs (1): B6
@@ -207,23 +521,27 @@ l1:
// CHECK-NEXT: Preds (2): B2 B3
// CHECK-NEXT: Succs (1): B0
// CHECK: [B2]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B2.2], class A)
// CHECK-NEXT: 2: A c;
// CHECK-NEXT: 3: [B2.2].~A() (Implicit destructor)
// CHECK-NEXT: Preds (1): B4
// CHECK-NEXT: Succs (1): B1
// CHECK: [B3]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B3.2], class A)
// CHECK-NEXT: 2: A c;
// CHECK-NEXT: 3: [B3.2].~A() (Implicit destructor)
// CHECK-NEXT: Preds (1): B4
// CHECK-NEXT: Succs (1): B1
// CHECK: [B4]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B4.2], class A)
// CHECK-NEXT: 2: A a;
// CHECK-NEXT: 3: a
// CHECK-NEXT: 4: [B4.3] (ImplicitCastExpr, NoOp, const class A)
-// CHECK-NEXT: 5: [B4.4] (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 5: [B4.4] (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 5: [B4.4] (CXXConstructExpr, [B4.6], class A)
// CHECK-NEXT: 6: A b = a;
// CHECK-NEXT: 7: b
// CHECK-NEXT: 8: [B4.7] (ImplicitCastExpr, NoOp, const class A)
@@ -247,14 +565,16 @@ void test_if_implicit_scope() {
// CHECK-NEXT: Succs (1): B8
// CHECK: [B1]
// CHECK-NEXT: 1: [B8.6].~A() (Implicit destructor)
-// CHECK-NEXT: 2: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 2: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 2: (CXXConstructExpr, [B1.3], class A)
// CHECK-NEXT: 3: A e;
// CHECK-NEXT: 4: [B1.3].~A() (Implicit destructor)
// CHECK-NEXT: 5: [B8.2].~A() (Implicit destructor)
// CHECK-NEXT: Preds (2): B2 B5
// CHECK-NEXT: Succs (1): B0
// CHECK: [B2]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B2.2], class A)
// CHECK-NEXT: 2: A d;
// CHECK-NEXT: 3: [B2.2].~A() (Implicit destructor)
// CHECK-NEXT: 4: [B4.2].~A() (Implicit destructor)
@@ -268,7 +588,8 @@ void test_if_implicit_scope() {
// CHECK-NEXT: Preds (1): B4
// CHECK-NEXT: Succs (1): B0
// CHECK: [B4]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B4.2], class A)
// CHECK-NEXT: 2: A c;
// CHECK-NEXT: 3: UV
// CHECK-NEXT: 4: [B4.3] (ImplicitCastExpr, LValueToRValue, _Bool)
@@ -276,7 +597,8 @@ void test_if_implicit_scope() {
// CHECK-NEXT: Preds (1): B8
// CHECK-NEXT: Succs (2): B3 B2
// CHECK: [B5]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B5.2], class A)
// CHECK-NEXT: 2: A d;
// CHECK-NEXT: 3: [B5.2].~A() (Implicit destructor)
// CHECK-NEXT: 4: [B7.2].~A() (Implicit destructor)
@@ -290,7 +612,8 @@ void test_if_implicit_scope() {
// CHECK-NEXT: Preds (1): B7
// CHECK-NEXT: Succs (1): B0
// CHECK: [B7]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B7.2], class A)
// CHECK-NEXT: 2: A c;
// CHECK-NEXT: 3: UV
// CHECK-NEXT: 4: [B7.3] (ImplicitCastExpr, LValueToRValue, _Bool)
@@ -298,11 +621,13 @@ void test_if_implicit_scope() {
// CHECK-NEXT: Preds (1): B8
// CHECK-NEXT: Succs (2): B6 B5
// CHECK: [B8]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B8.2], class A)
// CHECK-NEXT: 2: A a;
// CHECK-NEXT: 3: a
// CHECK-NEXT: 4: [B8.3] (ImplicitCastExpr, NoOp, const class A)
-// CHECK-NEXT: 5: [B8.4] (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 5: [B8.4] (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 5: [B8.4] (CXXConstructExpr, [B8.6], class A)
// CHECK-NEXT: 6: A b = a;
// CHECK-NEXT: 7: b
// CHECK-NEXT: 8: [B8.7] (ImplicitCastExpr, NoOp, const class A)
@@ -340,7 +665,8 @@ void test_if_jumps() {
// CHECK-NEXT: Preds (1): B3
// CHECK-NEXT: Succs (1): B4
// CHECK: [B3]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B3.2], class A)
// CHECK-NEXT: 2: A c;
// CHECK-NEXT: 3: [B3.2].~A() (Implicit destructor)
// CHECK-NEXT: 4: [B4.4].~A() (Implicit destructor)
@@ -349,7 +675,8 @@ void test_if_jumps() {
// CHECK: [B4]
// CHECK-NEXT: 1: a
// CHECK-NEXT: 2: [B4.1] (ImplicitCastExpr, NoOp, const class A)
-// CHECK-NEXT: 3: [B4.2] (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 3: [B4.2] (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 3: [B4.2] (CXXConstructExpr, [B4.4], class A)
// CHECK-NEXT: 4: A b = a;
// CHECK-NEXT: 5: b
// CHECK-NEXT: 6: [B4.5] (ImplicitCastExpr, NoOp, const class A)
@@ -361,7 +688,8 @@ void test_if_jumps() {
// CHECK-NEXT: Preds (2): B2 B5
// CHECK-NEXT: Succs (2): B3 B1
// CHECK: [B5]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B5.2], class A)
// CHECK-NEXT: 2: A a;
// CHECK-NEXT: Preds (1): B6
// CHECK-NEXT: Succs (1): B4
@@ -377,7 +705,8 @@ void test_while_implicit_scope() {
// CHECK-NEXT: Succs (1): B11
// CHECK: [B1]
// CHECK-NEXT: 1: [B10.4].~A() (Implicit destructor)
-// CHECK-NEXT: 2: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 2: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 2: (CXXConstructExpr, [B1.3], class A)
// CHECK-NEXT: 3: A e;
// CHECK-NEXT: 4: [B1.3].~A() (Implicit destructor)
// CHECK-NEXT: 5: [B11.2].~A() (Implicit destructor)
@@ -387,7 +716,8 @@ void test_while_implicit_scope() {
// CHECK-NEXT: Preds (2): B3 B6
// CHECK-NEXT: Succs (1): B10
// CHECK: [B3]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B3.2], class A)
// CHECK-NEXT: 2: A d;
// CHECK-NEXT: 3: [B3.2].~A() (Implicit destructor)
// CHECK-NEXT: 4: [B9.2].~A() (Implicit destructor)
@@ -425,7 +755,8 @@ void test_while_implicit_scope() {
// CHECK: Preds (1): B9
// CHECK-NEXT: Succs (1): B1
// CHECK: [B9]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B9.2], class A)
// CHECK-NEXT: 2: A c;
// CHECK-NEXT: 3: UV
// CHECK-NEXT: 4: [B9.3] (ImplicitCastExpr, LValueToRValue, _Bool)
@@ -435,7 +766,8 @@ void test_while_implicit_scope() {
// CHECK: [B10]
// CHECK-NEXT: 1: a
// CHECK-NEXT: 2: [B10.1] (ImplicitCastExpr, NoOp, const class A)
-// CHECK-NEXT: 3: [B10.2] (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 3: [B10.2] (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 3: [B10.2] (CXXConstructExpr, [B10.4], class A)
// CHECK-NEXT: 4: A b = a;
// CHECK-NEXT: 5: b
// CHECK-NEXT: 6: [B10.5] (ImplicitCastExpr, NoOp, const class A)
@@ -447,7 +779,8 @@ void test_while_implicit_scope() {
// CHECK-NEXT: Preds (2): B2 B11
// CHECK-NEXT: Succs (2): B9 B1
// CHECK: [B11]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B11.2], class A)
// CHECK-NEXT: 2: A a;
// CHECK-NEXT: Preds (1): B12
// CHECK-NEXT: Succs (1): B10
@@ -474,7 +807,8 @@ void test_while_jumps() {
// CHECK-NEXT: Preds (1): B2
// CHECK-NEXT: Succs (2): B3 B0
// CHECK: [B2]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B2.2], class A)
// CHECK-NEXT: 2: A a;
// CHECK-NEXT: 3: [B2.2].~A() (Implicit destructor)
// CHECK-NEXT: Preds (2): B3 B4
@@ -492,7 +826,8 @@ void test_do_implicit_scope() {
// CHECK: [B12 (ENTRY)]
// CHECK-NEXT: Succs (1): B11
// CHECK: [B1]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B1.2], class A)
// CHECK-NEXT: 2: A d;
// CHECK-NEXT: 3: [B1.2].~A() (Implicit destructor)
// CHECK-NEXT: 4: [B11.2].~A() (Implicit destructor)
@@ -505,7 +840,8 @@ void test_do_implicit_scope() {
// CHECK-NEXT: Preds (2): B3 B6
// CHECK-NEXT: Succs (2): B10 B1
// CHECK: [B3]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B3.2], class A)
// CHECK-NEXT: 2: A c;
// CHECK-NEXT: 3: [B3.2].~A() (Implicit destructor)
// CHECK-NEXT: 4: [B9.2].~A() (Implicit destructor)
@@ -540,7 +876,8 @@ void test_do_implicit_scope() {
// CHECK: Preds (1): B9
// CHECK-NEXT: Succs (1): B1
// CHECK: [B9]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B9.2], class A)
// CHECK-NEXT: 2: A b;
// CHECK-NEXT: 3: UV
// CHECK-NEXT: 4: [B9.3] (ImplicitCastExpr, LValueToRValue, _Bool)
@@ -551,7 +888,8 @@ void test_do_implicit_scope() {
// CHECK-NEXT: Preds (1): B2
// CHECK-NEXT: Succs (1): B9
// CHECK: [B11]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B11.2], class A)
// CHECK-NEXT: 2: A a;
// CHECK-NEXT: Preds (1): B12
// CHECK-NEXT: Succs (1): B9
@@ -577,7 +915,8 @@ void test_do_jumps() {
// CHECK-NEXT: Preds (2): B3 B2
// CHECK-NEXT: Succs (1): B0
// CHECK: [B2]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B2.2], class A)
// CHECK-NEXT: 2: A a;
// CHECK-NEXT: 3: a
// CHECK-NEXT: 4: [B2.3] (ImplicitCastExpr, NoOp, const class A)
@@ -592,7 +931,8 @@ void test_do_jumps() {
// CHECK-NEXT: Preds (1): B4
// CHECK-NEXT: Succs (1): B1
// CHECK: [B3]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B3.2], class A)
// CHECK-NEXT: 2: A c;
// CHECK-NEXT: 3: [B3.2].~A() (Implicit destructor)
// CHECK-NEXT: Succs (1): B1
@@ -608,14 +948,16 @@ void test_switch_implicit_scope() {
// CHECK-NEXT: Succs (1): B2
// CHECK: [B1]
// CHECK-NEXT: 1: [B2.6].~A() (Implicit destructor)
-// CHECK-NEXT: 2: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 2: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 2: (CXXConstructExpr, [B1.3], class A)
// CHECK-NEXT: 3: A g;
// CHECK-NEXT: 4: [B1.3].~A() (Implicit destructor)
// CHECK-NEXT: 5: [B2.2].~A() (Implicit destructor)
// CHECK-NEXT: Preds (3): B3 B7 B2
// CHECK-NEXT: Succs (1): B0
// CHECK: [B2]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B2.2], class A)
// CHECK-NEXT: 2: A a;
// CHECK-NEXT: 3: a
// CHECK-NEXT: 4: [B2.3] (ImplicitCastExpr, NoOp, const class A)
@@ -635,7 +977,8 @@ void test_switch_implicit_scope() {
// CHECK: Preds (2): B2 B4
// CHECK-NEXT: Succs (1): B1
// CHECK: [B4]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B4.2], class A)
// CHECK-NEXT: 2: A f;
// CHECK-NEXT: 3: [B4.2].~A() (Implicit destructor)
// CHECK-NEXT: 4: [B8.2].~A() (Implicit destructor)
@@ -661,7 +1004,8 @@ void test_switch_implicit_scope() {
// CHECK-NEXT: Succs (1): B1
// CHECK: [B8]
// CHECK: case 0:
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B8.2], class A)
// CHECK-NEXT: 2: A c;
// CHECK-NEXT: 3: UV
// CHECK-NEXT: 4: [B8.3] (ImplicitCastExpr, LValueToRValue, _Bool)
@@ -696,7 +1040,8 @@ void test_switch_jumps() {
// CHECK-NEXT: Preds (1): B3
// CHECK-NEXT: Succs (1): B4
// CHECK: [B3]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B3.2], class A)
// CHECK-NEXT: 2: A c;
// CHECK-NEXT: 3: [B3.2].~A() (Implicit destructor)
// CHECK-NEXT: 4: [B4.4].~A() (Implicit destructor)
@@ -705,7 +1050,8 @@ void test_switch_jumps() {
// CHECK: [B4]
// CHECK-NEXT: 1: a
// CHECK-NEXT: 2: [B4.1] (ImplicitCastExpr, NoOp, const class A)
-// CHECK-NEXT: 3: [B4.2] (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 3: [B4.2] (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 3: [B4.2] (CXXConstructExpr, [B4.4], class A)
// CHECK-NEXT: 4: A b = a;
// CHECK-NEXT: 5: b
// CHECK-NEXT: 6: [B4.5] (ImplicitCastExpr, NoOp, const class A)
@@ -717,7 +1063,8 @@ void test_switch_jumps() {
// CHECK-NEXT: Preds (2): B2 B5
// CHECK-NEXT: Succs (2): B3 B1
// CHECK: [B5]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B5.2], class A)
// CHECK-NEXT: 2: A a;
// CHECK-NEXT: Preds (1): B6
// CHECK-NEXT: Succs (1): B4
@@ -733,7 +1080,8 @@ void test_for_implicit_scope() {
// CHECK: [B1]
// CHECK-NEXT: 1: [B10.4].~A() (Implicit destructor)
// CHECK-NEXT: 2: [B11.4].~A() (Implicit destructor)
-// CHECK-NEXT: 3: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 3: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 3: (CXXConstructExpr, [B1.4], class A)
// CHECK-NEXT: 4: A f;
// CHECK-NEXT: 5: [B1.4].~A() (Implicit destructor)
// CHECK-NEXT: 6: [B11.2].~A() (Implicit destructor)
@@ -743,7 +1091,8 @@ void test_for_implicit_scope() {
// CHECK-NEXT: Preds (2): B3 B6
// CHECK-NEXT: Succs (1): B10
// CHECK: [B3]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B3.2], class A)
// CHECK-NEXT: 2: A e;
// CHECK-NEXT: 3: [B3.2].~A() (Implicit destructor)
// CHECK-NEXT: 4: [B9.2].~A() (Implicit destructor)
@@ -781,7 +1130,8 @@ void test_for_implicit_scope() {
// CHECK: Preds (1): B9
// CHECK-NEXT: Succs (1): B1
// CHECK: [B9]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B9.2], class A)
// CHECK-NEXT: 2: A d;
// CHECK-NEXT: 3: UV
// CHECK-NEXT: 4: [B9.3] (ImplicitCastExpr, LValueToRValue, _Bool)
@@ -791,7 +1141,8 @@ void test_for_implicit_scope() {
// CHECK: [B10]
// CHECK-NEXT: 1: b
// CHECK-NEXT: 2: [B10.1] (ImplicitCastExpr, NoOp, const class A)
-// CHECK-NEXT: 3: [B10.2] (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 3: [B10.2] (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 3: [B10.2] (CXXConstructExpr, [B10.4], class A)
// CHECK-NEXT: 4: A c = b;
// CHECK-NEXT: 5: c
// CHECK-NEXT: 6: [B10.5] (ImplicitCastExpr, NoOp, const class A)
@@ -803,9 +1154,11 @@ void test_for_implicit_scope() {
// CHECK-NEXT: Preds (2): B2 B11
// CHECK-NEXT: Succs (2): B9 B1
// CHECK: [B11]
-// CHECK-NEXT: 1: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 1: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B11.2], class A)
// CHECK-NEXT: 2: A a;
-// CHECK-NEXT: 3: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 3: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 3: (CXXConstructExpr, [B11.4], class A)
// CHECK-NEXT: 4: A b;
// CHECK-NEXT: Preds (1): B12
// CHECK-NEXT: Succs (1): B10
diff --git a/test/Analysis/autoreleasewritechecker_test.m b/test/Analysis/autoreleasewritechecker_test.m
new file mode 100644
index 000000000000..b3d34b9b11fa
--- /dev/null
+++ b/test/Analysis/autoreleasewritechecker_test.m
@@ -0,0 +1,281 @@
+// UNSUPPORTED: system-windows
+// RUN: %clang_analyze_cc1 -DARC -fobjc-arc -analyzer-checker=core,osx.cocoa.AutoreleaseWrite %s -triple x86_64-darwin -fblocks -verify
+// RUN: %clang_analyze_cc1 -DNOARC -analyzer-checker=core,osx.cocoa.AutoreleaseWrite %s -fblocks -triple x86_64-darwin -verify
+
+
+typedef signed char BOOL;
+#define YES ((BOOL)1)
+@protocol NSObject - (BOOL)isEqual:(id)object; @end
+@interface NSObject <NSObject> {}
++(id)alloc;
+-(id)init;
+-(id)autorelease;
+-(id)copy;
+-(id)retain;
+@end
+typedef int NSZone;
+typedef int NSCoder;
+typedef unsigned long NSUInteger;
+
+@protocol NSCopying - (id)copyWithZone:(NSZone *)zone; @end
+@protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; @end
+@interface NSError : NSObject <NSCopying, NSCoding> {}
++ (id)errorWithDomain:(int)domain;
+@end
+
+typedef int dispatch_semaphore_t;
+typedef void (^block_t)();
+
+typedef enum {
+ NSEnumerationConcurrent = (1UL << 0),
+ NSEnumerationReverse = (1UL << 1)
+} NSEnumerationOptions;
+
+@interface NSArray
+- (void)enumerateObjectsUsingBlock:(block_t)block;
+@end
+
+@interface NSSet
+- (void)objectsPassingTest:(block_t)block;
+@end
+
+@interface NSDictionary
+- (void)enumerateKeysAndObjectsUsingBlock:(block_t)block;
+@end
+
+@interface NSIndexSet
+- (void)indexesPassingTest:(block_t)block;
+- (NSUInteger)indexWithOptions:(NSEnumerationOptions)opts
+ passingTest:(BOOL (^)(NSUInteger idx, BOOL *stop))predicate;
+@end
+
+typedef int group_t;
+typedef struct dispatch_queue_s *dispatch_queue_t;
+typedef void (^dispatch_block_t)(void);
+extern dispatch_queue_t queue;
+
+void dispatch_group_async(dispatch_queue_t queue,
+ group_t group,
+ dispatch_block_t block);
+void dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
+dispatch_semaphore_t dispatch_semaphore_create(int);
+
+void dispatch_semaphore_wait(dispatch_semaphore_t, int);
+void dispatch_semaphore_signal(dispatch_semaphore_t);
+
+// No warnings without ARC.
+#ifdef NOARC
+
+// expected-no-diagnostics
+BOOL writeToErrorWithIterator(NSError ** error, NSArray *a) {
+ [a enumerateObjectsUsingBlock:^{
+ *error = [NSError errorWithDomain:1]; // no-warning
+ }];
+ return 0;
+}
+#endif
+
+#ifdef ARC
+@interface I : NSObject
+- (BOOL) writeToStrongErrorInBlock:(NSError *__strong *)error;
+- (BOOL) writeToErrorInBlock:(NSError *__autoreleasing *)error;
+- (BOOL) writeToLocalErrorInBlock:(NSError **)error;
+- (BOOL) writeToErrorInBlockMultipleTimes:(NSError *__autoreleasing *)error;
+- (BOOL) writeToError:(NSError *__autoreleasing *)error;
+- (BOOL) writeToErrorWithDispatchGroup:(NSError *__autoreleasing *)error;
+@end
+
+@implementation I
+
+- (BOOL) writeToErrorInBlock:(NSError *__autoreleasing *)error {
+ dispatch_semaphore_t sem = dispatch_semaphore_create(0l);
+ dispatch_async(queue, ^{
+ if (error) {
+ *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter inside autorelease pool that may exit before method returns; consider writing first to a strong local variable declared outside of the block}}
+ }
+ dispatch_semaphore_signal(sem);
+ });
+
+ dispatch_semaphore_wait(sem, 100);
+ return 0;
+}
+
+- (BOOL) writeToErrorWithDispatchGroup:(NSError *__autoreleasing *)error {
+ dispatch_semaphore_t sem = dispatch_semaphore_create(0l);
+ dispatch_group_async(queue, 0, ^{
+ if (error) {
+ *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter inside autorelease pool that may exit before method returns; consider writing first to a strong local variable declared outside of the block}}
+ }
+ dispatch_semaphore_signal(sem);
+ });
+
+ dispatch_semaphore_wait(sem, 100);
+ return 0;
+}
+
+- (BOOL) writeToLocalErrorInBlock:(NSError *__autoreleasing *)error {
+ dispatch_semaphore_t sem = dispatch_semaphore_create(0l);
+ dispatch_async(queue, ^{
+ NSError* error2;
+ NSError*__strong* error3 = &error2;
+ if (error) {
+ *error3 = [NSError errorWithDomain:1]; // no-warning
+ }
+ dispatch_semaphore_signal(sem);
+ });
+
+ dispatch_semaphore_wait(sem, 100);
+ return 0;
+}
+
+- (BOOL) writeToStrongErrorInBlock:(NSError *__strong *)error {
+ dispatch_semaphore_t sem = dispatch_semaphore_create(0l);
+ dispatch_async(queue, ^{
+ if (error) {
+ *error = [NSError errorWithDomain:2]; // no-warning
+ }
+ dispatch_semaphore_signal(sem);
+ });
+
+ dispatch_semaphore_wait(sem, 100);
+ return 0;
+}
+
+- (BOOL) writeToErrorInBlockMultipleTimes:(NSError *__autoreleasing *)error {
+ dispatch_semaphore_t sem = dispatch_semaphore_create(0l);
+ dispatch_async(queue, ^{
+ if (error) {
+ *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter inside autorelease pool that may exit before method returns; consider writing first to a strong local variable declared outside of the block}}
+ }
+ dispatch_semaphore_signal(sem);
+ });
+ dispatch_async(queue, ^{
+ if (error) {
+ *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter inside autorelease pool that may exit before method returns; consider writing first to a strong local variable declared outside of the block}}
+ *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter inside autorelease pool that may exit before method returns; consider writing first to a strong local variable declared outside of the block}}
+ }
+ dispatch_semaphore_signal(sem);
+ });
+ *error = [NSError errorWithDomain:1]; // no-warning
+
+ dispatch_semaphore_wait(sem, 100);
+ return 0;
+}
+
+- (BOOL) writeToError:(NSError *__autoreleasing *)error {
+ *error = [NSError errorWithDomain:1]; // no-warning
+ return 0;
+}
+@end
+
+BOOL writeToErrorInBlockFromCFunc(NSError *__autoreleasing* error) {
+ dispatch_semaphore_t sem = dispatch_semaphore_create(0l);
+ dispatch_async(queue, ^{
+ if (error) {
+ *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter inside autorelease pool that may exit before function returns; consider writing first to a strong local variable declared outside of the block}}
+ }
+ dispatch_semaphore_signal(sem);
+ });
+
+ dispatch_semaphore_wait(sem, 100);
+ return 0;
+}
+
+BOOL writeToErrorNoWarning(NSError *__autoreleasing* error) {
+ *error = [NSError errorWithDomain:1]; // no-warning
+ return 0;
+}
+
+BOOL writeToErrorWithIterator(NSError *__autoreleasing* error, NSArray *a, NSSet *s, NSDictionary *d, NSIndexSet *i) { [a enumerateObjectsUsingBlock:^{
+ *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter inside autorelease pool that may exit before function returns; consider writing first to a strong local variable declared outside of the block}}
+ }];
+ [d enumerateKeysAndObjectsUsingBlock:^{
+ *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter inside autorelease pool that may exit before function returns; consider writing first to a strong local variable declared outside of the block}}
+ }];
+ [s objectsPassingTest:^{
+ *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter inside autorelease pool that may exit before function returns; consider writing first to a strong local variable declared outside of the block}}
+ }];
+ [i indexesPassingTest:^{
+ *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter inside autorelease pool that may exit before function returns; consider writing first to a strong local variable declared outside of the block}}
+ }];
+ [i indexWithOptions: NSEnumerationReverse passingTest:^(NSUInteger idx, BOOL *stop) {
+ *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter inside autorelease pool that may exit before function returns; consider writing first to a strong local variable declared outside of the block}}
+ return YES;
+ }];
+ return 0;
+}
+
+void writeIntoError(NSError **error) {
+ *error = [NSError errorWithDomain:1];
+}
+
+extern void readError(NSError *error);
+
+void writeToErrorWithIteratorNonnull(NSError *__autoreleasing* _Nonnull error, NSDictionary *a) {
+ [a enumerateKeysAndObjectsUsingBlock:^{
+ *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter}}
+ }];
+}
+
+
+void escapeErrorFromIterator(NSError *__autoreleasing* _Nonnull error, NSDictionary *a) {
+ [a enumerateKeysAndObjectsUsingBlock:^{
+ writeIntoError(error); // expected-warning{{Capture of autoreleasing out parameter}}
+ }];
+}
+
+void noWarningOnRead(NSError *__autoreleasing* error, NSDictionary *a) {
+ [a enumerateKeysAndObjectsUsingBlock:^{
+ NSError* local = *error; // no-warning
+ }];
+}
+
+void noWarningOnEscapeRead(NSError *__autoreleasing* error, NSDictionary *a) {
+ [a enumerateKeysAndObjectsUsingBlock:^{
+ readError(*error); // no-warning
+ }];
+}
+
+@interface ErrorCapture
+- (void) captureErrorOut:(NSError**) error;
+- (void) captureError:(NSError*) error;
+@end
+
+void escapeErrorFromIteratorMethod(NSError *__autoreleasing* _Nonnull error,
+ NSDictionary *a,
+ ErrorCapture *capturer) {
+ [a enumerateKeysAndObjectsUsingBlock:^{
+ [capturer captureErrorOut:error]; // expected-warning{{Capture of autoreleasing out parameter}}
+ }];
+}
+
+void noWarningOnEscapeReadMethod(NSError *__autoreleasing* error,
+ NSDictionary *a,
+ ErrorCapture *capturer) {
+ [a enumerateKeysAndObjectsUsingBlock:^{
+ [capturer captureError:*error]; // no-warning
+ }];
+}
+
+void multipleErrors(NSError *__autoreleasing* error, NSDictionary *a) {
+ [a enumerateKeysAndObjectsUsingBlock:^{
+ writeIntoError(error); // expected-warning{{Capture of autoreleasing out parameter}}
+ *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter}}
+ writeIntoError(error); // expected-warning{{Capture of autoreleasing out parameter}}
+ }];
+}
+
+typedef void (^errBlock)(NSError *__autoreleasing *error);
+
+extern void expectError(errBlock);
+
+void captureAutoreleasingVarFromBlock(NSDictionary *dict) {
+ expectError(^(NSError *__autoreleasing *err) {
+ [dict enumerateKeysAndObjectsUsingBlock:^{
+ writeIntoError(err); // expected-warning{{Capture of autoreleasing out parameter 'err'}}
+ }];
+ });
+}
+
+#endif
+
diff --git a/test/Analysis/bitwise-ops.c b/test/Analysis/bitwise-ops.c
index fe546580be3d..fcd3d7dbc7cf 100644
--- a/test/Analysis/bitwise-ops.c
+++ b/test/Analysis/bitwise-ops.c
@@ -8,9 +8,8 @@ void testPersistentConstraints(int x, int y) {
CHECK(x); // expected-warning{{TRUE}}
CHECK(x & 1); // expected-warning{{TRUE}}
- // False positives due to SValBuilder giving up on certain kinds of exprs.
- CHECK(1 - x); // expected-warning{{UNKNOWN}}
- CHECK(x & y); // expected-warning{{UNKNOWN}}
+ CHECK(1 - x); // expected-warning{{TRUE}}
+ CHECK(x & y); // expected-warning{{TRUE}}
}
int testConstantShifts_PR18073(int which) {
@@ -51,3 +50,9 @@ int testNegativeLeftShift(int a) {
}
return 0;
}
+
+int testUnrepresentableLeftShift(int a) {
+ if (a == 8)
+ return a << 30; // expected-warning{{The result of the left shift is undefined due to shifting '8' by '30', which is unrepresentable in the unsigned version of the return type 'int'}}
+ return 0;
+}
diff --git a/test/Analysis/blocks.mm b/test/Analysis/blocks.mm
index 6cff9b47f169..8a3f1708514e 100644
--- a/test/Analysis/blocks.mm
+++ b/test/Analysis/blocks.mm
@@ -1,6 +1,17 @@
// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core -fblocks -analyzer-opt-analyze-nested-blocks -verify -x objective-c++ %s
-// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,debug.DumpCFG -fblocks -analyzer-opt-analyze-nested-blocks %s > %t 2>&1
-// RUN: FileCheck --input-file=%t %s
+// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,debug.DumpCFG -fblocks -analyzer-opt-analyze-nested-blocks -analyzer-config cfg-rich-constructors=false %s > %t 2>&1
+// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,WARNINGS %s
+// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,debug.DumpCFG -fblocks -analyzer-opt-analyze-nested-blocks -analyzer-config cfg-rich-constructors=true %s > %t 2>&1
+// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,ANALYZER %s
+
+// This file tests how we construct two different flavors of the Clang CFG -
+// the CFG used by the Sema analysis-based warnings and the CFG used by the
+// static analyzer. The difference in the behavior is checked via FileCheck
+// prefixes (WARNINGS and ANALYZER respectively). When introducing new analyzer
+// flags, no new run lines should be added - just these flags would go to the
+// respective line depending on where is it turned on and where is it turned
+// off. Feel free to add tests that test only one of the CFG flavors if you're
+// not sure how the other flavor is supposed to work in your case.
// expected-no-diagnostics
@@ -64,7 +75,8 @@ void testBlockWithCaptureByReference() {
// CHECK: [B1]
// CHECK-NEXT: 1: 5
-// CHECK-NEXT: 2: [B1.1] (CXXConstructExpr, struct StructWithCopyConstructor)
+// WARNINGS-NEXT: 2: [B1.1] (CXXConstructExpr, struct StructWithCopyConstructor)
+// ANALYZER-NEXT: 2: [B1.1] (CXXConstructExpr, [B1.3], struct StructWithCopyConstructor)
// CHECK-NEXT: 3: StructWithCopyConstructor s(5) __attribute__((blocks("byref")));
// CHECK-NEXT: 4: ^{ }
// CHECK-NEXT: 5: (void)([B1.4]) (CStyleCastExpr, ToVoid, void)
diff --git a/test/Analysis/bool-increment.cpp b/test/Analysis/bool-increment.cpp
new file mode 100644
index 000000000000..93002d3b61ec
--- /dev/null
+++ b/test/Analysis/bool-increment.cpp
@@ -0,0 +1,84 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection -verify -std=c++98 -Wno-deprecated %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection -verify -std=c++11 -Wno-deprecated %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection -verify -std=c++14 -Wno-deprecated %s
+
+extern void clang_analyzer_eval(bool);
+
+void test_bool_value() {
+ {
+ bool b = true;
+ clang_analyzer_eval(b == 1); // expected-warning{{TRUE}}
+ }
+
+ {
+ bool b = false;
+ clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
+ }
+
+ {
+ bool b = -10;
+ clang_analyzer_eval(b == 1); // expected-warning{{TRUE}}
+ }
+
+ {
+ bool b = 10;
+ clang_analyzer_eval(b == 1); // expected-warning{{TRUE}}
+ }
+
+ {
+ bool b = 10;
+ b++;
+ clang_analyzer_eval(b == 1); // expected-warning{{TRUE}}
+ }
+
+ {
+ bool b = 0;
+ b++;
+ clang_analyzer_eval(b == 1); // expected-warning{{TRUE}}
+ }
+}
+
+void test_bool_increment() {
+ {
+ bool b = true;
+ b++;
+ clang_analyzer_eval(b); // expected-warning{{TRUE}}
+ }
+
+ {
+ bool b = false;
+ b++;
+ clang_analyzer_eval(b); // expected-warning{{TRUE}}
+ }
+
+ {
+ bool b = true;
+ ++b;
+ clang_analyzer_eval(b); // expected-warning{{TRUE}}
+ }
+
+ {
+ bool b = false;
+ ++b;
+ clang_analyzer_eval(b); // expected-warning{{TRUE}}
+ }
+
+ {
+ bool b = 0;
+ ++b;
+ clang_analyzer_eval(b); // expected-warning{{TRUE}}
+ }
+
+ {
+ bool b = 10;
+ ++b;
+ ++b;
+ clang_analyzer_eval(b); // expected-warning{{TRUE}}
+ }
+
+ {
+ bool b = -10;
+ ++b;
+ clang_analyzer_eval(b); // expected-warning{{TRUE}}
+ }
+}
diff --git a/test/Analysis/bsd-string.c b/test/Analysis/bsd-string.c
new file mode 100644
index 000000000000..bca42ca89643
--- /dev/null
+++ b/test/Analysis/bsd-string.c
@@ -0,0 +1,45 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring.NullArg,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s
+
+#define NULL ((void *)0)
+
+typedef __typeof(sizeof(int)) size_t;
+size_t strlcpy(char *dst, const char *src, size_t n);
+size_t strlcat(char *dst, const char *src, size_t n);
+void clang_analyzer_eval(int);
+
+void f1() {
+ char overlap[] = "123456789";
+ strlcpy(overlap, overlap + 1, 3); // expected-warning{{Arguments must not be overlapping buffers}}
+}
+
+void f2() {
+ char buf[5];
+ strlcpy(buf, "abcd", sizeof(buf)); // expected-no-warning
+ strlcat(buf, "efgh", sizeof(buf)); // expected-warning{{Size argument is greater than the free space in the destination buffer}}
+}
+
+void f3() {
+ char dst[2];
+ const char *src = "abdef";
+ strlcpy(dst, src, 5); // expected-warning{{Size argument is greater than the length of the destination buffer}}
+}
+
+void f4() {
+ strlcpy(NULL, "abcdef", 6); // expected-warning{{Null pointer argument in call to string copy function}}
+}
+
+void f5() {
+ strlcat(NULL, "abcdef", 6); // expected-warning{{Null pointer argument in call to string copy function}}
+}
+
+void f6() {
+ char buf[8];
+ strlcpy(buf, "abc", 3);
+ size_t len = strlcat(buf, "defg", 4);
+ clang_analyzer_eval(len == 7); // expected-warning{{TRUE}}
+}
+
+int f7() {
+ char buf[8];
+ return strlcpy(buf, "1234567", 0); // no-crash
+}
diff --git a/test/Analysis/bstring.c b/test/Analysis/bstring.c
index a671d9ee8d4e..89a77cdff866 100644
--- a/test/Analysis/bstring.c
+++ b/test/Analysis/bstring.c
@@ -474,3 +474,12 @@ char radar_11125445_memcopythenlogfirstbyte(const char *input, size_t length) {
free(bytes);
return x;
}
+
+struct S {
+ char f;
+};
+
+void nocrash_on_locint_offset(void *addr, void* from, struct S s) {
+ int iAdd = (int) addr;
+ memcpy(((void *) &(s.f)), from, iAdd);
+}
diff --git a/test/Analysis/bstring.cpp b/test/Analysis/bstring.cpp
index fea76cc082fa..19978f913cb1 100644
--- a/test/Analysis/bstring.cpp
+++ b/test/Analysis/bstring.cpp
@@ -1,7 +1,8 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s
-// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s
-// RUN: %clang_analyze_cc1 -DVARIANT -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s
-// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -DVARIANT -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s
+// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s
+// RUN: %clang_analyze_cc1 -DVARIANT -analyzer-checker=core,unix.cstring,alpha.unix.cstring,unix.Malloc,debug.ExprInspection -analyzer-store=region -verify %s
+// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -DVARIANT -analyzer-checker=core,unix.cstring,alpha.unix.cstring,unix.Malloc,debug.ExprInspection -analyzer-store=region -verify %s
+// RUN: %clang_analyze_cc1 -DSUPPRESS_OUT_OF_BOUND -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring.BufferOverlap,alpha.unix.cstring.NotNullTerminated,debug.ExprInspection -analyzer-store=region -verify %s
#include "Inputs/system-header-simulator-cxx.h"
#include "Inputs/system-header-simulator-for-malloc.h"
@@ -77,3 +78,118 @@ class b {
unsigned *f;
};
}
+
+void *memset(void *dest, int ch, std::size_t count);
+namespace memset_non_pod {
+class Base {
+public:
+ int b_mem;
+ Base() : b_mem(1) {}
+};
+
+class Derived : public Base {
+public:
+ int d_mem;
+ Derived() : d_mem(2) {}
+};
+
+void memset1_inheritance() {
+ Derived d;
+ memset(&d, 0, sizeof(Derived));
+ clang_analyzer_eval(d.b_mem == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(d.d_mem == 0); // expected-warning{{TRUE}}
+}
+
+#ifdef SUPPRESS_OUT_OF_BOUND
+void memset2_inheritance_field() {
+ Derived d;
+ memset(&d.d_mem, 0, sizeof(Derived));
+ clang_analyzer_eval(d.b_mem == 0); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(d.d_mem == 0); // expected-warning{{UNKNOWN}}
+}
+
+void memset3_inheritance_field() {
+ Derived d;
+ memset(&d.b_mem, 0, sizeof(Derived));
+ clang_analyzer_eval(d.b_mem == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(d.d_mem == 0); // expected-warning{{TRUE}}
+}
+#endif
+
+void memset4_array_nonpod_object() {
+ Derived array[10];
+ clang_analyzer_eval(array[1].b_mem == 1); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(array[1].d_mem == 2); // expected-warning{{UNKNOWN}}
+ memset(&array[1], 0, sizeof(Derived));
+ clang_analyzer_eval(array[1].b_mem == 0); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(array[1].d_mem == 0); // expected-warning{{UNKNOWN}}
+}
+
+void memset5_array_nonpod_object() {
+ Derived array[10];
+ clang_analyzer_eval(array[1].b_mem == 1); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(array[1].d_mem == 2); // expected-warning{{UNKNOWN}}
+ memset(array, 0, sizeof(array));
+ clang_analyzer_eval(array[1].b_mem == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(array[1].d_mem == 0); // expected-warning{{TRUE}}
+}
+
+void memset6_new_array_nonpod_object() {
+ Derived *array = new Derived[10];
+ clang_analyzer_eval(array[2].b_mem == 1); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(array[2].d_mem == 2); // expected-warning{{UNKNOWN}}
+ memset(array, 0, 10 * sizeof(Derived));
+ clang_analyzer_eval(array[2].b_mem == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(array[2].d_mem == 0); // expected-warning{{TRUE}}
+ delete[] array;
+}
+
+void memset7_placement_new() {
+ Derived *d = new Derived();
+ clang_analyzer_eval(d->b_mem == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(d->d_mem == 2); // expected-warning{{TRUE}}
+
+ memset(d, 0, sizeof(Derived));
+ clang_analyzer_eval(d->b_mem == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(d->d_mem == 0); // expected-warning{{TRUE}}
+
+ Derived *d1 = new (d) Derived();
+ clang_analyzer_eval(d1->b_mem == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(d1->d_mem == 2); // expected-warning{{TRUE}}
+
+ memset(d1, 0, sizeof(Derived));
+ clang_analyzer_eval(d->b_mem == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(d->d_mem == 0); // expected-warning{{TRUE}}
+}
+
+class BaseVirtual {
+public:
+ int b_mem;
+ virtual int get() { return 1; }
+};
+
+class DerivedVirtual : public BaseVirtual {
+public:
+ int d_mem;
+};
+
+#ifdef SUPPRESS_OUT_OF_BOUND
+void memset8_virtual_inheritance_field() {
+ DerivedVirtual d;
+ memset(&d.b_mem, 0, sizeof(Derived));
+ clang_analyzer_eval(d.b_mem == 0); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(d.d_mem == 0); // expected-warning{{UNKNOWN}}
+}
+#endif
+} // namespace memset_non_pod
+
+#ifdef SUPPRESS_OUT_OF_BOUND
+void memset1_new_array() {
+ int *array = new int[10];
+ memset(array, 0, 10 * sizeof(int));
+ clang_analyzer_eval(array[2] == 0); // expected-warning{{TRUE}}
+ memset(array + 1, 'a', 10 * sizeof(9));
+ clang_analyzer_eval(array[2] == 0); // expected-warning{{UNKNOWN}}
+ delete[] array;
+}
+#endif
diff --git a/test/Analysis/builtin-functions.cpp b/test/Analysis/builtin-functions.cpp
index 2c1950251145..19984963b4fa 100644
--- a/test/Analysis/builtin-functions.cpp
+++ b/test/Analysis/builtin-functions.cpp
@@ -64,3 +64,20 @@ void g(int i) {
// We give up the analysis on this path.
}
}
+
+void test_constant_p() {
+ int i = 1;
+ const int j = 2;
+ constexpr int k = 3;
+ clang_analyzer_eval(__builtin_constant_p(42) == 1); // expected-warning {{TRUE}}
+ clang_analyzer_eval(__builtin_constant_p(i) == 0); // expected-warning {{TRUE}}
+ clang_analyzer_eval(__builtin_constant_p(j) == 1); // expected-warning {{TRUE}}
+ clang_analyzer_eval(__builtin_constant_p(k) == 1); // expected-warning {{TRUE}}
+ clang_analyzer_eval(__builtin_constant_p(i + 42) == 0); // expected-warning {{TRUE}}
+ clang_analyzer_eval(__builtin_constant_p(j + 42) == 1); // expected-warning {{TRUE}}
+ clang_analyzer_eval(__builtin_constant_p(k + 42) == 1); // expected-warning {{TRUE}}
+ clang_analyzer_eval(__builtin_constant_p(" ") == 1); // expected-warning {{TRUE}}
+ clang_analyzer_eval(__builtin_constant_p(test_constant_p) == 0); // expected-warning {{TRUE}}
+ clang_analyzer_eval(__builtin_constant_p(k - 3) == 0); // expected-warning {{FALSE}}
+ clang_analyzer_eval(__builtin_constant_p(k - 3) == 1); // expected-warning {{TRUE}}
+}
diff --git a/test/Analysis/call_once.cpp b/test/Analysis/call_once.cpp
index db9e5cc7ca16..344de8090787 100644
--- a/test/Analysis/call_once.cpp
+++ b/test/Analysis/call_once.cpp
@@ -1,16 +1,34 @@
-// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -verify %s
-// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -DEMULATE_LIBSTDCPP -verify %s
+// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -verify %s -o %t.report
+// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -DEMULATE_LIBSTDCPP -verify %s -o %t.report
// We do NOT model libcxx03 implementation, but the analyzer should still
// not crash.
-// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -DEMULATE_LIBCXX03 -verify %s
-// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -DEMULATE_LIBCXX03 -DEMULATE_LIBSTDCPP -verify %s
+// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -DEMULATE_LIBCXX03 -verify %s -o %t.report
+// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -DEMULATE_LIBCXX03 -DEMULATE_LIBSTDCPP -verify %s -o %t.report
+// RUN: rm -rf %t.report
void clang_analyzer_eval(bool);
-// Faking std::std::call_once implementation.
+// Faking std::call_once implementation.
namespace std {
+// Fake std::function implementation.
+template <typename>
+class function;
+class function_base {
+ public:
+ long field;
+};
+template <typename R, typename... P>
+class function<R(P...)> : function_base {
+ public:
+ R operator()(P...) const {
+
+ // Read from a super-class necessary to reproduce a crash.
+ bool a = field;
+ }
+};
+
#ifndef EMULATE_LIBSTDCPP
typedef struct once_flag_s {
unsigned long __state_ = 0;
@@ -359,3 +377,38 @@ void test_implicit_funcptr() {
clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
#endif
}
+
+int param_passed(int *x) {
+ return *x; // no-warning, as std::function is not working yet.
+}
+
+void callback_taking_func_ok(std::function<void(int*)> &innerCallback) {
+ innerCallback(nullptr);
+}
+
+// The provided callback expects an std::function, but instead a pointer
+// to a C++ function is provided.
+void callback_with_implicit_cast_ok() {
+ std::once_flag flag;
+ call_once(flag, callback_taking_func_ok, &param_passed);
+}
+
+void callback_taking_func(std::function<void()> &innerCallback) {
+ innerCallback();
+}
+
+// The provided callback expects an std::function, but instead a C function
+// name is provided, and C++ implicitly auto-constructs a pointer from it.
+void callback_with_implicit_cast() {
+ std::once_flag flag;
+ call_once(flag, callback_taking_func, callback_with_implicit_cast);
+}
+
+std::once_flag another_once_flag;
+typedef void (*my_callback_t)(int *);
+my_callback_t callback;
+int global_int;
+
+void rdar40270582() {
+ call_once(another_once_flag, callback, &global_int);
+}
diff --git a/test/Analysis/casts.c b/test/Analysis/casts.c
index 24bba8a30a00..eccb67812a02 100644
--- a/test/Analysis/casts.c
+++ b/test/Analysis/casts.c
@@ -149,3 +149,29 @@ void multiDimensionalArrayPointerCasts() {
clang_analyzer_eval(*((char *)y1) == *((char *) y3)); // expected-warning{{TRUE}}
}
+
+void *getVoidPtr();
+
+void testCastVoidPtrToIntPtrThroughIntTypedAssignment() {
+ int *x;
+ (*((int *)(&x))) = (int)getVoidPtr();
+ *x = 1; // no-crash
+}
+
+void testCastUIntPtrToIntPtrThroughIntTypedAssignment() {
+ unsigned u;
+ int *x;
+ (*((int *)(&x))) = (int)&u;
+ *x = 1;
+ clang_analyzer_eval(u == 1); // expected-warning{{TRUE}}
+}
+
+void testCastVoidPtrToIntPtrThroughUIntTypedAssignment() {
+ int *x;
+ (*((int *)(&x))) = (int)(unsigned *)getVoidPtr();
+ *x = 1; // no-crash
+}
+
+void testLocNonLocSymbolAssume(int a, int *b) {
+ if ((int)b < a) {} // no-crash
+}
diff --git a/test/Analysis/casts.cpp b/test/Analysis/casts.cpp
index f96f19b0ac33..757eb6da6623 100644
--- a/test/Analysis/casts.cpp
+++ b/test/Analysis/casts.cpp
@@ -21,3 +21,23 @@ void intAsBoolAsSwitchCondition(int c) {
break;
}
}
+
+int *&castToIntPtrLValueRef(char *p) {
+ return (int *&)*(int *)p;
+}
+bool testCastToIntPtrLValueRef(char *p, int *s) {
+ return castToIntPtrLValueRef(p) != s; // no-crash
+}
+
+int *&&castToIntPtrRValueRef(char *p) {
+ return (int *&&)*(int *)p;
+}
+bool testCastToIntPtrRValueRef(char *p, int *s) {
+ return castToIntPtrRValueRef(p) != s; // no-crash
+}
+
+bool retrievePointerFromBoolean(int *p) {
+ bool q;
+ *reinterpret_cast<int **>(&q) = p;
+ return q;
+}
diff --git a/test/Analysis/cfg-rich-constructors.cpp b/test/Analysis/cfg-rich-constructors.cpp
new file mode 100644
index 000000000000..6780cf1a7be9
--- /dev/null
+++ b/test/Analysis/cfg-rich-constructors.cpp
@@ -0,0 +1,906 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -std=c++11 -w %s > %t 2>&1
+// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX11,ELIDE,CXX11-ELIDE %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -std=c++17 -w %s > %t 2>&1
+// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX17,ELIDE,CXX17-ELIDE %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -std=c++11 -w -analyzer-config elide-constructors=false %s > %t 2>&1
+// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX11,NOELIDE,CXX11-NOELIDE %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -std=c++17 -w -analyzer-config elide-constructors=false %s > %t 2>&1
+// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX17,NOELIDE,CXX17-NOELIDE %s
+
+class C {
+public:
+ C();
+ C(C *);
+ C(int, int);
+
+ static C get();
+ operator bool() const;
+};
+
+typedef __typeof(sizeof(int)) size_t;
+void *operator new(size_t size, void *placement);
+
+namespace operator_new {
+
+// CHECK: void operatorNewWithConstructor()
+// CHECK: 1: CFGNewAllocator(C *)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B1.3], class C)
+// CHECK-NEXT: 3: new C([B1.2])
+void operatorNewWithConstructor() {
+ new C();
+}
+
+// CHECK: void operatorNewWithConstructorWithOperatorNewWithContstructor()
+// CHECK: 1: CFGNewAllocator(C *)
+// CHECK-NEXT: 2: CFGNewAllocator(C *)
+// CHECK-NEXT: 3: (CXXConstructExpr, [B1.4], class C)
+// CHECK-NEXT: 4: new C([B1.3])
+// CHECK-NEXT: 5: [B1.4] (CXXConstructExpr, [B1.6], class C)
+// CHECK-NEXT: 6: new C([B1.5])
+void operatorNewWithConstructorWithOperatorNewWithContstructor() {
+ new C(new C());
+}
+
+// CHECK: void operatorPlacementNewWithConstructorWithinPlacementArgument()
+// CHECK: 1: CFGNewAllocator(C *)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B1.3], class C)
+// CHECK-NEXT: 3: new C([B1.2])
+// CHECK-NEXT: 4: [B1.3] (ImplicitCastExpr, BitCast, void *)
+// CHECK-NEXT: 5: CFGNewAllocator(C *)
+// CHECK-NEXT: 6: (CXXConstructExpr, [B1.7], class C)
+// CHECK-NEXT: 7: new ([B1.4]) C([B1.6])
+void operatorPlacementNewWithConstructorWithinPlacementArgument() {
+ new (new C()) C();
+}
+
+} // namespace operator_new
+
+namespace decl_stmt {
+
+// CHECK: void simpleVariable()
+// CHECK: 1: (CXXConstructExpr, [B1.2], class C)
+// CHECK-NEXT: 2: C c;
+void simpleVariable() {
+ C c;
+}
+
+// CHECK: void simpleVariableWithBraces()
+// CHECK: 1: {} (CXXConstructExpr, [B1.2], class C)
+// CHECK-NEXT: 2: C c{};
+void simpleVariableWithBraces() {
+ C c{};
+}
+
+// CHECK: void simpleVariableWithConstructorArgument()
+// CHECK: 1: 0
+// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, NullToPointer, class C *)
+// CHECK-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.4], class C)
+// CHECK-NEXT: 4: C c(0);
+void simpleVariableWithConstructorArgument() {
+ C c(0);
+}
+
+// CHECK: void simpleVariableWithOperatorNewInConstructorArgument()
+// CHECK: 1: CFGNewAllocator(C *)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B1.3], class C)
+// CHECK-NEXT: 3: new C([B1.2])
+// CHECK-NEXT: 4: [B1.3] (CXXConstructExpr, [B1.5], class C)
+// CHECK-NEXT: 5: C c(new C());
+void simpleVariableWithOperatorNewInConstructorArgument() {
+ C c(new C());
+}
+
+// CHECK: void simpleVariableWithOperatorNewInBraces()
+// CHECK: 1: CFGNewAllocator(C *)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B1.3], class C)
+// CHECK-NEXT: 3: new C([B1.2])
+// CHECK-NEXT: 4: {[B1.3]} (CXXConstructExpr, [B1.5], class C)
+// CHECK-NEXT: 5: C c{new C()};
+void simpleVariableWithOperatorNewInBraces() {
+ C c{new C()};
+}
+
+// CHECK: void simpleVariableInitializedByValue()
+// CHECK: 1: C::get
+// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void))
+// CXX11-ELIDE-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.5])
+// CXX11-NOELIDE-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4])
+// CXX11-NEXT: 4: [B1.3]
+// CXX11-NEXT: 5: [B1.4] (CXXConstructExpr, [B1.6], class C)
+// CXX11-NEXT: 6: C c = C::get();
+// CXX17-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4])
+// CXX17-NEXT: 4: C c = C::get();
+void simpleVariableInitializedByValue() {
+ C c = C::get();
+}
+
+// FIXME: Find construction contexts for both branches in C++17.
+// Note that once it gets detected, the test for the get() branch would not
+// fail, because FileCheck allows partial matches.
+// CHECK: void simpleVariableWithTernaryOperator(bool coin)
+// CHECK: [B1]
+// CXX11-NEXT: 1: [B4.2] ? [B2.5] : [B3.6]
+// CXX11-NEXT: 2: [B1.1]
+// CXX11-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.4], class C)
+// CXX11-NEXT: 4: C c = coin ? C::get() : C(0);
+// CXX17-NEXT: 1: [B4.2] ? [B2.3] : [B3.4]
+// CXX17-NEXT: 2: C c = coin ? C::get() : C(0);
+// CHECK: [B2]
+// CHECK-NEXT: 1: C::get
+// CHECK-NEXT: 2: [B2.1] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void))
+// CXX11-ELIDE-NEXT: 3: [B2.2]() (CXXRecordTypedCall, [B2.4], [B2.5])
+// CXX11-NOELIDE-NEXT: 3: [B2.2]() (CXXRecordTypedCall, [B2.4])
+// CXX11-NEXT: 4: [B2.3]
+// CXX11-ELIDE-NEXT: 5: [B2.4] (CXXConstructExpr, [B1.2], [B1.3], class C)
+// CXX11-NOELIDE-NEXT: 5: [B2.4] (CXXConstructExpr, [B1.2], class C)
+// CXX17-NEXT: 3: [B2.2]()
+// CHECK: [B3]
+// CHECK-NEXT: 1: 0
+// CHECK-NEXT: 2: [B3.1] (ImplicitCastExpr, NullToPointer, class C *)
+// CXX11-ELIDE-NEXT: 3: [B3.2] (CXXConstructExpr, [B3.5], [B3.6], class C)
+// CXX11-NOELIDE-NEXT: 3: [B3.2] (CXXConstructExpr, [B3.5], class C)
+// CXX11-NEXT: 4: C([B3.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C)
+// CXX11-NEXT: 5: [B3.4]
+// CXX11-ELIDE-NEXT: 6: [B3.5] (CXXConstructExpr, [B1.2], [B1.3], class C)
+// CXX11-NOELIDE-NEXT: 6: [B3.5] (CXXConstructExpr, [B1.2], class C)
+// CXX17-NEXT: 3: [B3.2] (CXXConstructExpr, class C)
+// CXX17-NEXT: 4: C([B3.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C)
+// CHECK: [B4]
+// CHECK-NEXT: 1: coin
+// CHECK-NEXT: 2: [B4.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT: T: [B4.2] ? ... : ...
+void simpleVariableWithTernaryOperator(bool coin) {
+ C c = coin ? C::get() : C(0);
+}
+
+// CHECK: void simpleVariableWithElidableCopy()
+// CHECK: 1: 0
+// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, NullToPointer, class C *)
+// CXX11-ELIDE-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.5], [B1.6], class C)
+// CXX11-NOELIDE-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.5], class C)
+// CXX17-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.5], class C)
+// CHECK-NEXT: 4: C([B1.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C)
+// CXX11-NEXT: 5: [B1.4]
+// CXX11-NEXT: 6: [B1.5] (CXXConstructExpr, [B1.7], class C)
+// CXX11-NEXT: 7: C c = C(0);
+// CXX17-NEXT: 5: C c = C(0);
+void simpleVariableWithElidableCopy() {
+ C c = C(0);
+}
+
+// CHECK: void referenceVariableWithConstructor()
+// CHECK: 1: 0
+// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, NullToPointer, class C *)
+// CHECK-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.4], const class C)
+// CHECK-NEXT: 4: [B1.3]
+// CHECK-NEXT: 5: const C &c(0);
+void referenceVariableWithConstructor() {
+ const C &c(0);
+}
+
+// CHECK: void referenceVariableWithInitializer()
+// CHECK: 1: C() (CXXConstructExpr, [B1.3], class C)
+// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, NoOp, const class C)
+// CHECK-NEXT: 3: [B1.2]
+// CHECK-NEXT: 4: const C &c = C();
+void referenceVariableWithInitializer() {
+ const C &c = C();
+}
+
+// CHECK: void referenceVariableWithTernaryOperator(bool coin)
+// CHECK: [B1]
+// CXX11-NEXT: 1: [B4.2] ? [B2.5] : [B3.6]
+// CXX17-NEXT: 1: [B4.2] ? [B2.3] : [B3.4]
+// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, NoOp, const class C)
+// CHECK-NEXT: 3: [B1.2]
+// CHECK-NEXT: 4: const C &c = coin ? C::get() : C(0);
+// CHECK: [B2]
+// CHECK-NEXT: 1: C::get
+// CHECK-NEXT: 2: [B2.1] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void))
+// CXX11-ELIDE-NEXT: 3: [B2.2]() (CXXRecordTypedCall, [B2.4], [B2.5])
+// CXX11-NOELIDE-NEXT: 3: [B2.2]() (CXXRecordTypedCall, [B2.4])
+// CXX11-NEXT: 4: [B2.3]
+// CXX11-NEXT: 5: [B2.4] (CXXConstructExpr, [B1.3], class C)
+// CXX17-NEXT: 3: [B2.2]() (CXXRecordTypedCall, [B1.3])
+// CHECK: [B3]
+// CHECK-NEXT: 1: 0
+// CHECK-NEXT: 2: [B3.1] (ImplicitCastExpr, NullToPointer, class C *)
+// CXX11-ELIDE-NEXT: 3: [B3.2] (CXXConstructExpr, [B3.5], [B3.6], class C)
+// CXX11-NOELIDE-NEXT: 3: [B3.2] (CXXConstructExpr, [B3.5], class C)
+// CXX11-NEXT: 4: C([B3.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C)
+// CXX11-NEXT: 5: [B3.4]
+// CXX11-NEXT: 6: [B3.5] (CXXConstructExpr, [B1.3], class C)
+// CXX17-NEXT: 3: [B3.2] (CXXConstructExpr, [B1.3], class C)
+// CXX17-NEXT: 4: C([B3.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C)
+// CHECK: [B4]
+// CHECK-NEXT: 1: coin
+// CHECK-NEXT: 2: [B4.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT: T: [B4.2] ? ... : ...
+void referenceVariableWithTernaryOperator(bool coin) {
+ const C &c = coin ? C::get() : C(0);
+}
+
+} // end namespace decl_stmt
+
+namespace ctor_initializers {
+
+class D: public C {
+ C c1;
+
+public:
+
+// CHECK: D()
+// CHECK: 1: (CXXConstructExpr, C() (Base initializer), class C)
+// CHECK-NEXT: 2: C([B1.1]) (Base initializer)
+// CHECK-NEXT: 3: CFGNewAllocator(C *)
+// CHECK-NEXT: 4: (CXXConstructExpr, [B1.5], class C)
+// CHECK-NEXT: 5: new C([B1.4])
+// CHECK-NEXT: 6: [B1.5] (CXXConstructExpr, c1([B1.5]) (Member initializer), class C)
+// CHECK-NEXT: 7: c1([B1.6]) (Member initializer)
+ D(): C(), c1(new C()) {}
+
+// CHECK: D(int)
+// CHECK: 1: (CXXConstructExpr, D() (Delegating initializer), class ctor_initializers::D)
+// CHECK-NEXT: 2: D([B1.1]) (Delegating initializer)
+ D(int): D() {}
+
+// FIXME: Why is CXXRecordTypedCall not present in C++17? Note that once it gets
+// detected the test would not fail, because FileCheck allows partial matches.
+// CHECK: D(double)
+// CHECK: 1: C::get
+// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void))
+// CHECK-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4])
+// CHECK-NEXT: 4: [B1.3]
+// CHECK-NEXT: 5: [B1.4] (CXXConstructExpr, C([B1.4]) (Base initializer), class C)
+// CHECK-NEXT: 6: C([B1.5]) (Base initializer)
+// CHECK-NEXT: 7: CFGNewAllocator(C *)
+// CHECK-NEXT: 8: C::get
+// CHECK-NEXT: 9: [B1.8] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void))
+// CXX11-ELIDE-NEXT: 10: [B1.9]() (CXXRecordTypedCall, [B1.11], [B1.12])
+// CXX11-NOELIDE-NEXT: 10: [B1.9]() (CXXRecordTypedCall, [B1.11])
+// CXX11-NEXT: 11: [B1.10]
+// CXX11-NEXT: 12: [B1.11] (CXXConstructExpr, [B1.13], class C)
+// CXX11-NEXT: 13: new C([B1.12])
+// CXX11-NEXT: 14: [B1.13] (CXXConstructExpr, c1([B1.13]) (Member initializer), class C)
+// CXX11-NEXT: 15: c1([B1.14]) (Member initializer)
+// CXX17-NEXT: 10: [B1.9]()
+// CXX17-NEXT: 11: new C([B1.10])
+// CXX17-NEXT: 12: [B1.11] (CXXConstructExpr, c1([B1.11]) (Member initializer), class C)
+// CXX17-NEXT: 13: c1([B1.12]) (Member initializer)
+ D(double): C(C::get()), c1(new C(C::get())) {}
+};
+
+// Let's see if initializers work well for fields with destructors.
+class E {
+public:
+ static E get();
+ ~E();
+};
+
+class F {
+ E e;
+
+public:
+// FIXME: There should be no temporary destructor in C++17.
+// CHECK: F()
+// CHECK: 1: E::get
+// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class ctor_initializers::E (*)(
+// CXX11-ELIDE-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.6], [B1.7])
+// CXX11-NOELIDE-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.6])
+// CXX11-NEXT: 4: [B1.3] (BindTemporary)
+// CXX11-NEXT: 5: [B1.4] (ImplicitCastExpr, NoOp, const class ctor_initializers::E)
+// CXX11-NEXT: 6: [B1.5]
+// CXX11-NEXT: 7: [B1.6] (CXXConstructExpr, e([B1.6]) (Member initializer), class ctor_initializers
+// CXX11-NEXT: 8: e([B1.7]) (Member initializer)
+// CXX11-NEXT: 9: ~ctor_initializers::E() (Temporary object destructor)
+// CXX17-NEXT: 3: [B1.2]() (CXXRecordTypedCall, e([B1.4]) (Member initializer), [B1.4])
+// CXX17-NEXT: 4: [B1.3] (BindTemporary)
+// CXX17-NEXT: 5: e([B1.4]) (Member initializer)
+// CXX17-NEXT: 6: ~ctor_initializers::E() (Temporary object destructor)
+ F(): e(E::get()) {}
+};
+} // end namespace ctor_initializers
+
+namespace return_stmt_without_dtor {
+
+// CHECK: C returnVariable()
+// CHECK: 1: (CXXConstructExpr, [B1.2], class C)
+// CHECK-NEXT: 2: C c;
+// CHECK-NEXT: 3: c
+// CHECK-NEXT: 4: [B1.3] (ImplicitCastExpr, NoOp, class C)
+// CHECK-NEXT: 5: [B1.4] (CXXConstructExpr, [B1.6], class C)
+// CHECK-NEXT: 6: return [B1.5];
+C returnVariable() {
+ C c;
+ return c;
+}
+
+// CHECK: C returnEmptyBraces()
+// CHECK: 1: {} (CXXConstructExpr, [B1.2], class C)
+// CHECK-NEXT: 2: return [B1.1];
+C returnEmptyBraces() {
+ return {};
+}
+
+// CHECK: C returnBracesWithOperatorNew()
+// CHECK: 1: CFGNewAllocator(C *)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B1.3], class C)
+// CHECK-NEXT: 3: new C([B1.2])
+// CHECK-NEXT: 4: {[B1.3]} (CXXConstructExpr, [B1.5], class C)
+// CHECK-NEXT: 5: return [B1.4];
+C returnBracesWithOperatorNew() {
+ return {new C()};
+}
+
+// CHECK: C returnBracesWithMultipleItems()
+// CHECK: 1: 123
+// CHECK-NEXT: 2: 456
+// CHECK-NEXT: 3: {[B1.1], [B1.2]} (CXXConstructExpr, [B1.4], class C)
+// CHECK-NEXT: 4: return [B1.3];
+C returnBracesWithMultipleItems() {
+ return {123, 456};
+}
+
+// CHECK: C returnTemporary()
+// CXX11-ELIDE: 1: C() (CXXConstructExpr, [B1.2], [B1.3], class C)
+// CXX11-NOELIDE: 1: C() (CXXConstructExpr, [B1.2], class C)
+// CXX11-NEXT: 2: [B1.1]
+// CXX11-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.4], class C)
+// CXX11-NEXT: 4: return [B1.3];
+// CXX17: 1: C() (CXXConstructExpr, [B1.2], class C)
+// CXX17-NEXT: 2: return [B1.1];
+C returnTemporary() {
+ return C();
+}
+
+// CHECK: C returnTemporaryWithArgument()
+// CHECK: 1: nullptr
+// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, NullToPointer, class C *)
+// CXX11-ELIDE-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.5], [B1.6], class C)
+// CXX11-NOELIDE-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.5], class C)
+// CXX17-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.5], class C)
+// CHECK-NEXT: 4: C([B1.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C)
+// CXX11-NEXT: 5: [B1.4]
+// CXX11-NEXT: 6: [B1.5] (CXXConstructExpr, [B1.7], class C)
+// CXX11-NEXT: 7: return [B1.6];
+// CXX17-NEXT: 5: return [B1.4];
+
+C returnTemporaryWithArgument() {
+ return C(nullptr);
+}
+
+// CHECK: C returnTemporaryConstructedByFunction()
+// CHECK: 1: C::get
+// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void))
+// CXX11-ELIDE-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.5])
+// CXX11-NOELIDE-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4])
+// CXX11-NEXT: 4: [B1.3]
+// CXX11-NEXT: 5: [B1.4] (CXXConstructExpr, [B1.6], class C)
+// CXX11-NEXT: 6: return [B1.5];
+// CXX17-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4])
+// CXX17-NEXT: 4: return [B1.3];
+C returnTemporaryConstructedByFunction() {
+ return C::get();
+}
+
+// CHECK: C returnChainOfCopies()
+// CHECK: 1: C::get
+// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void))
+// CXX11-ELIDE-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.5])
+// CXX11-NOELIDE-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4])
+// CXX11-NEXT: 4: [B1.3]
+// CXX11-ELIDE-NEXT: 5: [B1.4] (CXXConstructExpr, [B1.7], [B1.8], class C)
+// CXX11-NOELIDE-NEXT: 5: [B1.4] (CXXConstructExpr, [B1.7], class C)
+// CXX11-NEXT: 6: C([B1.5]) (CXXFunctionalCastExpr, ConstructorConversion, class C)
+// CXX11-NEXT: 7: [B1.6]
+// CXX11-NEXT: 8: [B1.7] (CXXConstructExpr, [B1.9], class C)
+// CXX11-NEXT: 9: return [B1.8];
+// CXX17-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.5])
+// CXX17-NEXT: 4: C([B1.3]) (CXXFunctionalCastExpr, NoOp, class C)
+// CXX17-NEXT: 5: return [B1.4];
+C returnChainOfCopies() {
+ return C(C::get());
+}
+
+} // end namespace return_stmt_without_dtor
+
+namespace return_stmt_with_dtor {
+
+class D {
+public:
+ D();
+ ~D();
+};
+
+// FIXME: There should be no temporary destructor in C++17.
+// CHECK: return_stmt_with_dtor::D returnTemporary()
+// CXX11-ELIDE: 1: return_stmt_with_dtor::D() (CXXConstructExpr, [B1.2], [B1.4], [B1.5], class return_stmt_with_dtor::D)
+// CXX11-NOELIDE: 1: return_stmt_with_dtor::D() (CXXConstructExpr, [B1.2], [B1.4], class return_stmt_with_dtor::D)
+// CXX11-NEXT: 2: [B1.1] (BindTemporary)
+// CXX11-NEXT: 3: [B1.2] (ImplicitCastExpr, NoOp, const class return_stmt_with_dtor::D)
+// CXX11-NEXT: 4: [B1.3]
+// CXX11-NEXT: 5: [B1.4] (CXXConstructExpr, [B1.7], class return_stmt_with_dtor::D)
+// CXX11-NEXT: 6: ~return_stmt_with_dtor::D() (Temporary object destructor)
+// CXX11-NEXT: 7: return [B1.5];
+// CXX17: 1: return_stmt_with_dtor::D() (CXXConstructExpr, [B1.4], [B1.2], class return_stmt_w
+// CXX17-NEXT: 2: [B1.1] (BindTemporary)
+// CXX17-NEXT: 3: ~return_stmt_with_dtor::D() (Temporary object destructor)
+// CXX17-NEXT: 4: return [B1.2];
+D returnTemporary() {
+ return D();
+}
+
+// FIXME: There should be no temporary destructor in C++17.
+// CHECK: void returnByValueIntoVariable()
+// CHECK: 1: returnTemporary
+// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class return_stmt_with_dtor::D (*)(void))
+// CXX11-ELIDE-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.6], [B1.7])
+// CXX11-NOELIDE-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.6])
+// CXX11-NEXT: 4: [B1.3] (BindTemporary)
+// CXX11-NEXT: 5: [B1.4] (ImplicitCastExpr, NoOp, const class return_stmt_with_dtor::D)
+// CXX11-NEXT: 6: [B1.5]
+// CXX11-NEXT: 7: [B1.6] (CXXConstructExpr, [B1.8], class return_stmt_with_dtor::D)
+// CXX11-NEXT: 8: return_stmt_with_dtor::D d = returnTemporary();
+// CXX11-NEXT: 9: ~return_stmt_with_dtor::D() (Temporary object destructor)
+// CXX11-NEXT: 10: [B1.8].~D() (Implicit destructor)
+// CXX17-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.5], [B1.4])
+// CXX17-NEXT: 4: [B1.3] (BindTemporary)
+// CXX17-NEXT: 5: return_stmt_with_dtor::D d = returnTemporary();
+// CXX17-NEXT: 6: ~return_stmt_with_dtor::D() (Temporary object destructor)
+// CXX17-NEXT: 7: [B1.5].~D() (Implicit destructor)
+void returnByValueIntoVariable() {
+ D d = returnTemporary();
+}
+
+} // end namespace return_stmt_with_dtor
+
+namespace temporary_object_expr_without_dtors {
+
+// TODO: Should provide construction context for the constructor,
+// even if there is no specific trigger statement here.
+// CHECK: void simpleTemporary()
+// CHECK 1: C() (CXXConstructExpr, class C)
+void simpleTemporary() {
+ C();
+}
+
+// CHECK: void temporaryInCondition()
+// CHECK: 1: C() (CXXConstructExpr, [B2.2], class C)
+// CHECK-NEXT: 2: [B2.1]
+// CHECK-NEXT: 3: [B2.2] (ImplicitCastExpr, NoOp, const class C)
+// CHECK-NEXT: 4: [B2.3].operator bool
+// CHECK-NEXT: 5: [B2.3]
+// CHECK-NEXT: 6: [B2.5] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CHECK-NEXT: T: if [B2.6]
+void temporaryInCondition() {
+ if (C());
+}
+
+// CHECK: void temporaryInConditionVariable()
+// CXX11-ELIDE: 1: C() (CXXConstructExpr, [B2.2], [B2.3], class C)
+// CXX11-NOELIDE: 1: C() (CXXConstructExpr, [B2.2], class C)
+// CXX11-NEXT: 2: [B2.1]
+// CXX11-NEXT: 3: [B2.2] (CXXConstructExpr, [B2.4], class C)
+// CXX11-NEXT: 4: C c = C();
+// CXX11-NEXT: 5: c
+// CXX11-NEXT: 6: [B2.5] (ImplicitCastExpr, NoOp, const class C)
+// CXX11-NEXT: 7: [B2.6].operator bool
+// CXX11-NEXT: 8: [B2.6]
+// CXX11-NEXT: 9: [B2.8] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CXX11-NEXT: T: if [B2.9]
+// CXX17: 1: C() (CXXConstructExpr, [B2.2], class C)
+// CXX17-NEXT: 2: C c = C();
+// CXX17-NEXT: 3: c
+// CXX17-NEXT: 4: [B2.3] (ImplicitCastExpr, NoOp, const class C)
+// CXX17-NEXT: 5: [B2.4].operator bool
+// CXX17-NEXT: 6: [B2.4]
+// CXX17-NEXT: 7: [B2.6] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CXX17-NEXT: T: if [B2.7]
+void temporaryInConditionVariable() {
+ if (C c = C());
+}
+
+
+// CHECK: void temporaryInForLoopConditionVariable()
+// CHECK: [B2]
+// CXX11-ELIDE-NEXT: 1: C() (CXXConstructExpr, [B2.2], [B2.3], class C)
+// CXX11-NOELIDE-NEXT: 1: C() (CXXConstructExpr, [B2.2], class C)
+// CXX11-NEXT: 2: [B2.1]
+// CXX11-NEXT: 3: [B2.2] (CXXConstructExpr, [B2.4], class C)
+// CXX11-NEXT: 4: C c2 = C();
+// CXX11-NEXT: 5: c2
+// CXX11-NEXT: 6: [B2.5] (ImplicitCastExpr, NoOp, const class C)
+// CXX11-NEXT: 7: [B2.6].operator bool
+// CXX11-NEXT: 8: [B2.6]
+// CXX11-NEXT: 9: [B2.8] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CXX11-NEXT: T: for (...; [B2.9]; )
+// CXX17-NEXT: 1: C() (CXXConstructExpr, [B2.2], class C)
+// CXX17-NEXT: 2: C c2 = C();
+// CXX17-NEXT: 3: c2
+// CXX17-NEXT: 4: [B2.3] (ImplicitCastExpr, NoOp, const class C)
+// CXX17-NEXT: 5: [B2.4].operator bool
+// CXX17-NEXT: 6: [B2.4]
+// CXX17-NEXT: 7: [B2.6] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CXX17-NEXT: T: for (...; [B2.7]; )
+// CHECK: [B3]
+// CXX11-ELIDE-NEXT: 1: C() (CXXConstructExpr, [B3.2], [B3.3], class C)
+// CXX11-NOELIDE-NEXT: 1: C() (CXXConstructExpr, [B3.2], class C)
+// CXX11-NEXT: 2: [B3.1]
+// CXX11-NEXT: 3: [B3.2] (CXXConstructExpr, [B3.4], class C)
+// CXX11-NEXT: 4: C c1 = C();
+// CXX17-NEXT: 1: C() (CXXConstructExpr, [B3.2], class C)
+// CXX17-NEXT: 2: C c1 = C();
+void temporaryInForLoopConditionVariable() {
+ for (C c1 = C(); C c2 = C(); );
+}
+
+
+// CHECK: void temporaryInWhileLoopConditionVariable()
+// CXX11-ELIDE: 1: C() (CXXConstructExpr, [B2.2], [B2.3], class C)
+// CXX11-NOELIDE: 1: C() (CXXConstructExpr, [B2.2], class C)
+// CXX11-NEXT: 2: [B2.1]
+// CXX11-NEXT: 3: [B2.2] (CXXConstructExpr, [B2.4], class C)
+// CXX11-NEXT: 4: C c = C();
+// CXX11-NEXT: 5: c
+// CXX11-NEXT: 6: [B2.5] (ImplicitCastExpr, NoOp, const class C)
+// CXX11-NEXT: 7: [B2.6].operator bool
+// CXX11-NEXT: 8: [B2.6]
+// CXX11-NEXT: 9: [B2.8] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CXX11-NEXT: T: while [B2.9]
+// CXX17: 1: C() (CXXConstructExpr, [B2.2], class C)
+// CXX17-NEXT: 2: C c = C();
+// CXX17-NEXT: 3: c
+// CXX17-NEXT: 4: [B2.3] (ImplicitCastExpr, NoOp, const class C)
+// CXX17-NEXT: 5: [B2.4].operator bool
+// CXX17-NEXT: 6: [B2.4]
+// CXX17-NEXT: 7: [B2.6] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CXX17-NEXT: T: while [B2.7]
+void temporaryInWhileLoopConditionVariable() {
+ while (C c = C());
+}
+
+} // end namespace temporary_object_expr_without_dtors
+
+namespace temporary_object_expr_with_dtors {
+
+class D {
+public:
+ D();
+ D(int);
+ ~D();
+
+ static D get();
+
+ operator bool() const;
+};
+
+// CHECK: void simpleTemporary()
+// CHECK: 1: temporary_object_expr_with_dtors::D() (CXXConstructExpr, [B1.2], class temporary_object_expr_with_dtors::D)
+// CHECK-NEXT: 2: [B1.1] (BindTemporary)
+// CHECK-NEXT: 3: ~temporary_object_expr_with_dtors::D() (Temporary object destructor)
+void simpleTemporary() {
+ D();
+}
+
+// CHECK: void temporaryInCondition()
+// CHECK: 1: temporary_object_expr_with_dtors::D() (CXXConstructExpr, [B2.2], [B2.3], class temporary_object_expr_with_dtors::D)
+// CHECK-NEXT: 2: [B2.1] (BindTemporary)
+// CHECK-NEXT: 3: [B2.2]
+// CHECK-NEXT: 4: [B2.3] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D)
+// CHECK-NEXT: 5: [B2.4].operator bool
+// CHECK-NEXT: 6: [B2.4]
+// CHECK-NEXT: 7: [B2.6] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CHECK-NEXT: 8: ~temporary_object_expr_with_dtors::D() (Temporary object destructor)
+// CHECK-NEXT: T: if [B2.7]
+void temporaryInCondition() {
+ if (D());
+}
+
+// CHECK: void referenceVariableWithConstructor()
+// CHECK: 1: 0
+// CHECK-NEXT: 2: [B1.1] (CXXConstructExpr, [B1.4], const class temporary_object_expr_with_dtors::D)
+// CHECK-NEXT: 3: [B1.2] (BindTemporary)
+// CHECK-NEXT: 4: [B1.3]
+// CHECK-NEXT: 5: const temporary_object_expr_with_dtors::D &d(0);
+// CHECK-NEXT: 6: [B1.5].~D() (Implicit destructor)
+void referenceVariableWithConstructor() {
+ const D &d(0);
+}
+
+// CHECK: void referenceVariableWithInitializer()
+// CHECK: 1: temporary_object_expr_with_dtors::D() (CXXConstructExpr, [B1.4], class temporary_object_expr_with_dtors::D)
+// CHECK-NEXT: 2: [B1.1] (BindTemporary)
+// CHECK-NEXT: 3: [B1.2] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D)
+// CHECK-NEXT: 4: [B1.3]
+// CHECK-NEXT: 5: const temporary_object_expr_with_dtors::D &d = temporary_object_expr_with_dtors::D();
+// CHECK-NEXT: 6: [B1.5].~D() (Implicit destructor)
+void referenceVariableWithInitializer() {
+ const D &d = D();
+}
+
+// CHECK: void referenceVariableWithTernaryOperator(bool coin)
+// CXX11: [B1]
+// CXX11-NEXT: 1: [B4.4].~D() (Implicit destructor)
+// CXX11: [B2]
+// CXX11-NEXT: 1: ~temporary_object_expr_with_dtors::D() (Temporary object destructor)
+// CXX11: [B3]
+// CXX11-NEXT: 1: ~temporary_object_expr_with_dtors::D() (Temporary object destructor)
+// CXX11: [B4]
+// CXX11-NEXT: 1: [B7.2] ? [B5.8] : [B6.8]
+// CXX11-NEXT: 2: [B4.1] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D)
+// CXX11-NEXT: 3: [B4.2]
+// CXX11-NEXT: 4: const temporary_object_expr_with_dtors::D &d = coin ? D::get() : temporary_object_expr_with_dtors::D(0);
+// CXX11-NEXT: T: (Temp Dtor) [B6.3]
+// CXX11: [B5]
+// CXX11-NEXT: 1: D::get
+// CXX11-NEXT: 2: [B5.1] (ImplicitCastExpr, FunctionToPointerDecay, class temporary_object_expr_with_dtors::D (*)(void))
+// CXX11-ELIDE-NEXT: 3: [B5.2]() (CXXRecordTypedCall, [B5.4], [B5.6], [B5.7])
+// CXX11-NOELIDE-NEXT: 3: [B5.2]() (CXXRecordTypedCall, [B5.4], [B5.6])
+// CXX11-NEXT: 4: [B5.3] (BindTemporary)
+// CXX11-NEXT: 5: [B5.4] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D)
+// CXX11-NEXT: 6: [B5.5]
+// CXX11-NEXT: 7: [B5.6] (CXXConstructExpr, [B4.3], class temporary_object_expr_with_dtors::D)
+// CXX11-NEXT: 8: [B5.7] (BindTemporary)
+// CXX11: [B6]
+// CXX11-NEXT: 1: 0
+// CXX11-ELIDE-NEXT: 2: [B6.1] (CXXConstructExpr, [B6.3], [B6.6], [B6.7], class temporary_object_expr_with_dtors::D)
+// CXX11-NOELIDE-NEXT: 2: [B6.1] (CXXConstructExpr, [B6.3], [B6.6], class temporary_object_expr_with_dtors::D)
+// CXX11-NEXT: 3: [B6.2] (BindTemporary)
+// CXX11-NEXT: 4: temporary_object_expr_with_dtors::D([B6.3]) (CXXFunctionalCastExpr, ConstructorConversion, class temporary_object_expr_with_dtors::D)
+// CXX11-NEXT: 5: [B6.4] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D)
+// CXX11-NEXT: 6: [B6.5]
+// CXX11-NEXT: 7: [B6.6] (CXXConstructExpr, [B4.3], class temporary_object_expr_with_dtors::D)
+// CXX11-NEXT: 8: [B6.7] (BindTemporary)
+// CXX11: [B7]
+// CXX11-NEXT: 1: coin
+// CXX11-NEXT: 2: [B7.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CXX11-NEXT: T: [B7.2] ? ... : ...
+// CXX17: [B1]
+// CXX17-NEXT: 1: [B4.2] ? [B2.4] : [B3.4]
+// CXX17-NEXT: 2: [B1.1] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D)
+// CXX17-NEXT: 3: [B1.2]
+// CXX17-NEXT: 4: const temporary_object_expr_with_dtors::D &d = coin ? D::get() : temporary_object_expr_with_dtors::D(0);
+// CXX17-NEXT: 5: [B1.4].~D() (Implicit destructor)
+// CXX17: [B2]
+// CXX17-NEXT: 1: D::get
+// CXX17-NEXT: 2: [B2.1] (ImplicitCastExpr, FunctionToPointerDecay, class temporary_object_expr_with_dtors::D (*)(void))
+// CXX17-NEXT: 3: [B2.2]() (CXXRecordTypedCall, [B1.3])
+// CXX17-NEXT: 4: [B2.3] (BindTemporary)
+// CXX17: [B3]
+// CXX17-NEXT: 1: 0
+// CXX17-NEXT: 2: [B3.1] (CXXConstructExpr, [B1.3], class temporary_object_expr_with_dtors::D)
+// CXX17-NEXT: 3: [B3.2] (BindTemporary)
+// CXX17-NEXT: 4: temporary_object_expr_with_dtors::D([B3.3]) (CXXFunctionalCastExpr, ConstructorConversion, class temporary_object_expr_with_dtors::D)
+// CXX17: [B4]
+// CXX17-NEXT: 1: coin
+// CXX17-NEXT: 2: [B4.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CXX17-NEXT: T: [B4.2] ? ... : ...
+void referenceVariableWithTernaryOperator(bool coin) {
+ const D &d = coin ? D::get() : D(0);
+}
+
+// CHECK: void referenceWithFunctionalCast()
+// CHECK: 1: 1
+// CHECK-NEXT: 2: [B1.1] (CXXConstructExpr, [B1.5], class temporary_object_expr_with_dtors::D)
+// CHECK-NEXT: 3: [B1.2] (BindTemporary)
+// CHECK-NEXT: 4: temporary_object_expr_with_dtors::D([B1.3]) (CXXFunctionalCastExpr, ConstructorCon
+// CHECK-NEXT: 5: [B1.4]
+// CHECK-NEXT: 6: temporary_object_expr_with_dtors::D &&d = temporary_object_expr_with_dtors::D(1);
+// CHECK-NEXT: 7: [B1.6].~D() (Implicit destructor)
+void referenceWithFunctionalCast() {
+ D &&d = D(1);
+}
+
+// Test the condition constructor, we don't care about branch constructors here.
+// CHECK: void constructorInTernaryCondition()
+// CXX11: 1: 1
+// CXX11-NEXT: 2: [B7.1] (CXXConstructExpr, [B7.3], [B7.5], class temporary_object_expr_with_dtors::D)
+// CXX11-NEXT: 3: [B7.2] (BindTemporary)
+// CXX11-NEXT: 4: temporary_object_expr_with_dtors::D([B7.3]) (CXXFunctionalCastExpr, ConstructorConversion, class temporary_object_expr_with_dtors::D)
+// CXX11-NEXT: 5: [B7.4]
+// CXX11-NEXT: 6: [B7.5] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D)
+// CXX11-NEXT: 7: [B7.6].operator bool
+// CXX11-NEXT: 8: [B7.6]
+// CXX11-NEXT: 9: [B7.8] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CXX11-NEXT: T: [B7.9] ? ... : ...
+// CXX17: 1: 1
+// CXX17-NEXT: 2: [B4.1] (CXXConstructExpr, [B4.3], [B4.5], class temporary_object_expr_with_dtors::D)
+// CXX17-NEXT: 3: [B4.2] (BindTemporary)
+// CXX17-NEXT: 4: temporary_object_expr_with_dtors::D([B4.3]) (CXXFunctionalCastExpr, ConstructorConversion, class temporary_object_expr_with_dtors::D)
+// CXX17-NEXT: 5: [B4.4]
+// CXX17-NEXT: 6: [B4.5] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D)
+// CXX17-NEXT: 7: [B4.6].operator bool
+// CXX17-NEXT: 8: [B4.6]
+// CXX17-NEXT: 9: [B4.8] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CXX17-NEXT: T: [B4.9] ? ... : ...
+void constructorInTernaryCondition() {
+ const D &d = D(1) ? D(2) : D(3);
+}
+
+} // end namespace temporary_object_expr_with_dtors
+
+namespace implicit_constructor_conversion {
+
+class A {};
+A get();
+
+class B {
+public:
+ B(const A &);
+ ~B() {}
+};
+
+// CHECK: void implicitConstructionConversionFromTemporary()
+// CHECK: 1: implicit_constructor_conversion::A() (CXXConstructExpr, [B1.3], class implicit_constructor_conversion::A)
+// CXX11-NEXT: 2: [B1.1] (ImplicitCastExpr, NoOp, const class implicit_constructor_conversion::A)
+// CXX11-NEXT: 3: [B1.2]
+// CXX11-ELIDE-NEXT: 4: [B1.3] (CXXConstructExpr, [B1.6], [B1.8], [B1.9], class implicit_constructor_conversion::B)
+// CXX11-NOELIDE-NEXT: 4: [B1.3] (CXXConstructExpr, [B1.6], [B1.8], class implicit_constructor_conversion::B)
+// CXX11-NEXT: 5: [B1.4] (ImplicitCastExpr, ConstructorConversion, class implicit_constructor_conversion::B)
+// CXX11-NEXT: 6: [B1.5] (BindTemporary)
+// CXX11-NEXT: 7: [B1.6] (ImplicitCastExpr, NoOp, const class implicit_constructor_conversion::B)
+// CXX11-NEXT: 8: [B1.7]
+// CXX11-NEXT: 9: [B1.8] (CXXConstructExpr, [B1.10], class implicit_constructor_conversion::B)
+// CXX11-NEXT: 10: implicit_constructor_conversion::B b = implicit_constructor_conversion::A();
+// CXX11-NEXT: 11: ~implicit_constructor_conversion::B() (Temporary object destructor)
+// CXX11-NEXT: 12: [B1.10].~B() (Implicit destructor)
+// CXX17-NEXT: 2: [B1.1] (ImplicitCastExpr, NoOp, const class implicit_constructor_conversion::A)
+// CXX17-NEXT: 3: [B1.2]
+// CXX17-NEXT: 4: [B1.3] (CXXConstructExpr, [B1.6], class implicit_constructor_conversion::B)
+// CXX17-NEXT: 5: [B1.4] (ImplicitCastExpr, ConstructorConversion, class implicit_constructor_conversion::B)
+// CXX17-NEXT: 6: implicit_constructor_conversion::B b = implicit_constructor_conversion::A();
+// CXX17-NEXT: 7: [B1.6].~B() (Implicit destructor)
+void implicitConstructionConversionFromTemporary() {
+ B b = A();
+}
+
+// CHECK: void implicitConstructionConversionFromFunctionValue()
+// CHECK: 1: get
+// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class implicit_constructor_conversion::A (*)(void))
+// CHECK-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.5])
+// CHECK-NEXT: 4: [B1.3] (ImplicitCastExpr, NoOp, const class implicit_constructor_conversion::A)
+// CHECK-NEXT: 5: [B1.4]
+// CXX11-ELIDE-NEXT: 6: [B1.5] (CXXConstructExpr, [B1.8], [B1.10], [B1.11], class implicit_constructor_conversion::B)
+// CXX11-NOELIDE-NEXT: 6: [B1.5] (CXXConstructExpr, [B1.8], [B1.10], class implicit_constructor_conversion::B)
+// CXX11-NEXT: 7: [B1.6] (ImplicitCastExpr, ConstructorConversion, class implicit_constructor_conversion::B)
+// CXX11-NEXT: 8: [B1.7] (BindTemporary)
+// CXX11-NEXT: 9: [B1.8] (ImplicitCastExpr, NoOp, const class implicit_constructor_conversion::B)
+// CXX11-NEXT: 10: [B1.9]
+// CXX11-NEXT: 11: [B1.10] (CXXConstructExpr, [B1.12], class implicit_constructor_conversion::B)
+// CXX11-NEXT: 12: implicit_constructor_conversion::B b = get();
+// CXX11-NEXT: 13: ~implicit_constructor_conversion::B() (Temporary object destructor)
+// CXX11-NEXT: 14: [B1.12].~B() (Implicit destructor)
+// CXX17-NEXT: 6: [B1.5] (CXXConstructExpr, [B1.8], class implicit_constructor_conversion::B)
+// CXX17-NEXT: 7: [B1.6] (ImplicitCastExpr, ConstructorConversion, class implicit_constructor_conversion::B)
+// CXX17-NEXT: 8: implicit_constructor_conversion::B b = get();
+// CXX17-NEXT: 9: [B1.8].~B() (Implicit destructor)
+void implicitConstructionConversionFromFunctionValue() {
+ B b = get();
+}
+
+// CHECK: void implicitConstructionConversionFromTemporaryWithLifetimeExtension()
+// CHECK: 1: implicit_constructor_conversion::A() (CXXConstructExpr, [B1.3], class implicit_constructor_conversion::A)
+// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, NoOp, const class implicit_constructor_conversion::A)
+// CHECK-NEXT: 3: [B1.2]
+// CHECK-NEXT: 4: [B1.3] (CXXConstructExpr, [B1.7], class implicit_constructor_conversion::B)
+// CHECK-NEXT: 5: [B1.4] (ImplicitCastExpr, ConstructorConversion, class implicit_constructor_conversion::B)
+// CHECK-NEXT: 6: [B1.5] (ImplicitCastExpr, NoOp, const class implicit_constructor_conversion::B)
+// CHECK-NEXT: 7: [B1.6]
+// CHECK-NEXT: 8: const implicit_constructor_conversion::B &b = implicit_constructor_conversion::A();
+// CHECK-NEXT: 9: [B1.8].~B() (Implicit destructor)
+void implicitConstructionConversionFromTemporaryWithLifetimeExtension() {
+ const B &b = A();
+}
+
+// CHECK: void implicitConstructionConversionFromFunctionValueWithLifetimeExtension()
+// CHECK: 1: get
+// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class implicit_constructor_conver
+// CHECK-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.5])
+// CHECK-NEXT: 4: [B1.3] (ImplicitCastExpr, NoOp, const class implicit_constructor_conversion::A)
+// CHECK-NEXT: 5: [B1.4]
+// CHECK-NEXT: 6: [B1.5] (CXXConstructExpr, [B1.9], class implicit_constructor_conversion::B)
+// CHECK-NEXT: 7: [B1.6] (ImplicitCastExpr, ConstructorConversion, class implicit_constructor_convers
+// CHECK-NEXT: 8: [B1.7] (ImplicitCastExpr, NoOp, const class implicit_constructor_conversion::B)
+// CHECK-NEXT: 9: [B1.8]
+// CHECK-NEXT: 10: const implicit_constructor_conversion::B &b = get();
+// CHECK-NEXT: 11: [B1.10].~B() (Implicit destructor)
+void implicitConstructionConversionFromFunctionValueWithLifetimeExtension() {
+ const B &b = get(); // no-crash
+}
+
+} // end namespace implicit_constructor_conversion
+
+namespace argument_constructors {
+class D {
+public:
+ D();
+ ~D();
+};
+
+void useC(C c);
+void useCByReference(const C &c);
+void useD(D d);
+void useDByReference(const D &d);
+
+// FIXME: Find construction context for the argument.
+// CHECK: void passArgument()
+// CHECK: 1: useC
+// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(class C))
+// CXX11-NEXT: 3: C() (CXXConstructExpr, [B1.4], class C)
+// CXX11-NEXT: 4: [B1.3]
+// CXX11-NEXT: 5: [B1.4] (CXXConstructExpr, class C)
+// CXX11-NEXT: 6: [B1.2]([B1.5])
+// CXX17-NEXT: 3: C() (CXXConstructExpr, class C)
+// CXX17-NEXT: 4: [B1.2]([B1.3])
+void passArgument() {
+ useC(C());
+}
+
+// CHECK: void passArgumentByReference()
+// CHECK: 1: useCByReference
+// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class C &))
+// CHECK-NEXT: 3: C() (CXXConstructExpr, [B1.5], class C)
+// CHECK-NEXT: 4: [B1.3] (ImplicitCastExpr, NoOp, const class C)
+// CHECK-NEXT: 5: [B1.4]
+// CHECK-NEXT: 6: [B1.2]([B1.5])
+void passArgumentByReference() {
+ useCByReference(C());
+}
+
+// FIXME: Find construction context for the argument.
+// CHECK: void passArgumentWithDestructor()
+// CHECK: 1: useD
+// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(class argument_constructors::D))
+// CXX11-NEXT: 3: argument_constructors::D() (CXXConstructExpr, [B1.4], [B1.6], class argument_constructors::D)
+// CXX11-NEXT: 4: [B1.3] (BindTemporary)
+// CXX11-NEXT: 5: [B1.4] (ImplicitCastExpr, NoOp, const class argument_constructors::D)
+// CXX11-NEXT: 6: [B1.5]
+// CXX11-NEXT: 7: [B1.6] (CXXConstructExpr, class argument_constructors::D)
+// CXX11-NEXT: 8: [B1.7] (BindTemporary)
+// CXX11-NEXT: 9: [B1.2]([B1.8])
+// CXX11-NEXT: 10: ~argument_constructors::D() (Temporary object destructor)
+// CXX11-NEXT: 11: ~argument_constructors::D() (Temporary object destructor)
+// CXX17-NEXT: 3: argument_constructors::D() (CXXConstructExpr, class argument_constructors::D)
+// CXX17-NEXT: 4: [B1.3] (BindTemporary)
+// CXX17-NEXT: 5: [B1.2]([B1.4])
+// CXX17-NEXT: 6: ~argument_constructors::D() (Temporary object destructor)
+void passArgumentWithDestructor() {
+ useD(D());
+}
+
+// CHECK: void passArgumentWithDestructorByReference()
+// CHECK: 1: useDByReference
+// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class argumen
+// CHECK-NEXT: 3: argument_constructors::D() (CXXConstructExpr, [B1.4], [B1.6], class argument_c
+// CHECK-NEXT: 4: [B1.3] (BindTemporary)
+// CHECK-NEXT: 5: [B1.4] (ImplicitCastExpr, NoOp, const class argument_constructors::D)
+// CHECK-NEXT: 6: [B1.5]
+// CHECK-NEXT: 7: [B1.2]([B1.6])
+// CHECK-NEXT: 8: ~argument_constructors::D() (Temporary object destructor)
+void passArgumentWithDestructorByReference() {
+ useDByReference(D());
+}
+} // end namespace argument_constructors
+
+namespace copy_elision_with_extra_arguments {
+class C {
+public:
+ C();
+ C(const C &c, int x = 0);
+};
+
+// CHECK: void testCopyElisionWhenCopyConstructorHasExtraArguments()
+// CHECK: [B1]
+// CXX11-ELIDE-NEXT: 1: copy_elision_with_extra_arguments::C() (CXXConstructExpr, [B1.3], [B1.5], class copy_elision_with_extra_arguments::C)
+// CXX11-NOELIDE-NEXT: 1: copy_elision_with_extra_arguments::C() (CXXConstructExpr, [B1.3], class copy_elision_with_extra_arguments::C)
+// CXX11-NEXT: 2: [B1.1] (ImplicitCastExpr, NoOp, const class copy_elision_with_extra_arguments::C)
+// CXX11-NEXT: 3: [B1.2]
+// CXX11-NEXT: 4:
+// CXX11-NEXT: 5: [B1.3] (CXXConstructExpr, [B1.6], class copy_elision_with_extra_arguments::C)
+// CXX11-NEXT: 6: copy_elision_with_extra_arguments::C c = copy_elision_with_extra_arguments::C();
+// CXX17-NEXT: 1: copy_elision_with_extra_arguments::C() (CXXConstructExpr, [B1.2], class copy_elision_with_extra_arguments::C)
+// CXX17-NEXT: 2: copy_elision_with_extra_arguments::C c = copy_elision_with_extra_arguments::C();
+void testCopyElisionWhenCopyConstructorHasExtraArguments() {
+ C c = C();
+}
+} // namespace copy_elision_with_extra_arguments
diff --git a/test/Analysis/cfg.cpp b/test/Analysis/cfg.cpp
index 208277343cdc..85c5be5a9819 100644
--- a/test/Analysis/cfg.cpp
+++ b/test/Analysis/cfg.cpp
@@ -1,5 +1,16 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -analyzer-config cfg-temporary-dtors=true -std=c++11 %s > %t 2>&1
-// RUN: FileCheck --input-file=%t %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -std=c++11 -analyzer-config cfg-rich-constructors=false %s > %t 2>&1
+// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,WARNINGS %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -std=c++11 -analyzer-config cfg-rich-constructors=true %s > %t 2>&1
+// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,ANALYZER %s
+
+// This file tests how we construct two different flavors of the Clang CFG -
+// the CFG used by the Sema analysis-based warnings and the CFG used by the
+// static analyzer. The difference in the behavior is checked via FileCheck
+// prefixes (WARNINGS and ANALYZER respectively). When introducing new analyzer
+// flags, no new run lines should be added - just these flags would go to the
+// respective line depending on where is it turned on and where is it turned
+// off. Feel free to add tests that test only one of the CFG flavors if you're
+// not sure how the other flavor is supposed to work in your case.
// CHECK-LABEL: void checkWrap(int i)
// CHECK: ENTRY
@@ -48,11 +59,14 @@ void checkWrap(int i) {
// CHECK-NEXT: 5: int l;
// CHECK-NEXT: 6: 2
// CHECK-NEXT: 7: int m = 2;
-// CHECK-NEXT: CXXConstructExpr
+// WARNINGS-NEXT: (CXXConstructExpr, struct standalone)
+// ANALYZER-NEXT: (CXXConstructExpr, [B1.9], struct standalone)
// CHECK-NEXT: 9: struct standalone myStandalone;
-// CHECK-NEXT: CXXConstructExpr
+// WARNINGS-NEXT: (CXXConstructExpr, struct (anonymous struct at {{.*}}))
+// ANALYZER-NEXT: (CXXConstructExpr, [B1.11], struct (anonymous struct at {{.*}}))
// CHECK-NEXT: 11: struct (anonymous struct at {{.*}}) myAnon;
-// CHECK-NEXT: CXXConstructExpr
+// WARNINGS-NEXT: (CXXConstructExpr, struct named)
+// ANALYZER-NEXT: (CXXConstructExpr, [B1.13], struct named)
// CHECK-NEXT: 13: struct named myNamed;
// CHECK-NEXT: Preds (1): B2
// CHECK-NEXT: Succs (1): B0
@@ -116,7 +130,8 @@ public:
// CHECK-NEXT: Succs (1): B1
// CHECK: [B1]
// CHECK-NEXT: 1: CFGNewAllocator(A *)
-// CHECK-NEXT: 2: (CXXConstructExpr, class A)
+// WARNINGS-NEXT: 2: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 2: (CXXConstructExpr, [B1.3], class A)
// CHECK-NEXT: 3: new A([B1.2])
// CHECK-NEXT: 4: A *a = new A();
// CHECK-NEXT: 5: a
@@ -138,7 +153,8 @@ void test_deletedtor() {
// CHECK: [B1]
// CHECK-NEXT: 1: 5
// CHECK-NEXT: 2: CFGNewAllocator(A *)
-// CHECK-NEXT: 3: (CXXConstructExpr, class A [5])
+// WARNINGS-NEXT: 3: (CXXConstructExpr, class A [5])
+// ANALYZER-NEXT: 3: (CXXConstructExpr, [B1.4], class A [5])
// CHECK-NEXT: 4: new A {{\[\[}}B1.1]]
// CHECK-NEXT: 5: A *a = new A [5];
// CHECK-NEXT: 6: a
@@ -331,7 +347,8 @@ int test_enum_with_extension_default(enum MyEnum value) {
// CHECK-NEXT: 3: [B1.2] (ImplicitCastExpr, ArrayToPointerDecay, int *)
// CHECK-NEXT: 4: [B1.3] (ImplicitCastExpr, BitCast, void *)
// CHECK-NEXT: 5: CFGNewAllocator(MyClass *)
-// CHECK-NEXT: 6: (CXXConstructExpr, class MyClass)
+// WARNINGS-NEXT: 6: (CXXConstructExpr, class MyClass)
+// ANALYZER-NEXT: 6: (CXXConstructExpr, [B1.7], class MyClass)
// CHECK-NEXT: 7: new ([B1.4]) MyClass([B1.6])
// CHECK-NEXT: 8: MyClass *obj = new (buffer) MyClass();
// CHECK-NEXT: Preds (1): B2
@@ -363,7 +380,8 @@ void test_placement_new() {
// CHECK-NEXT: 4: [B1.3] (ImplicitCastExpr, BitCast, void *)
// CHECK-NEXT: 5: 5
// CHECK-NEXT: 6: CFGNewAllocator(MyClass *)
-// CHECK-NEXT: 7: (CXXConstructExpr, class MyClass [5])
+// WARNINGS-NEXT: 7: (CXXConstructExpr, class MyClass [5])
+// ANALYZER-NEXT: 7: (CXXConstructExpr, [B1.8], class MyClass [5])
// CHECK-NEXT: 8: new ([B1.4]) MyClass {{\[\[}}B1.5]]
// CHECK-NEXT: 9: MyClass *obj = new (buffer) MyClass [5];
// CHECK-NEXT: Preds (1): B2
diff --git a/test/Analysis/conditional-path-notes.c b/test/Analysis/conditional-path-notes.c
index d842b7fc6eef..8fc27be391be 100644
--- a/test/Analysis/conditional-path-notes.c
+++ b/test/Analysis/conditional-path-notes.c
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 %s -analyzer-checker=core.NullDereference -analyzer-output=text -verify
-// RUN: %clang_analyze_cc1 %s -analyzer-checker=core.NullDereference -analyzer-output=plist -analyzer-config path-diagnostics-alternate=false -o %t
+// RUN: %clang_analyze_cc1 %s -analyzer-checker=core.NullDereference -analyzer-output=plist -o %t
// RUN: FileCheck --input-file=%t %s
void testCondOp(int *p) {
@@ -78,6 +78,7 @@ void testDiagnosableBranchLogical(int a, int b) {
void testNonDiagnosableBranchArithmetic(int a, int b) {
if (a - b) {
// expected-note@-1 {{Taking true branch}}
+ // expected-note@-2 {{Assuming the condition is true}}
*(volatile int *)0 = 1; // expected-warning{{Dereference of null pointer}}
// expected-note@-1 {{Dereference of null pointer}}
}
@@ -270,6 +271,40 @@ void testNonDiagnosableBranchArithmetic(int a, int b) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>10</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>10</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>10</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>10</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>10</integer>
// CHECK-NEXT: <key>col</key><integer>6</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -416,6 +451,40 @@ void testNonDiagnosableBranchArithmetic(int a, int b) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>19</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>19</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>19</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>19</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>19</integer>
// CHECK-NEXT: <key>col</key><integer>11</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -770,108 +839,6 @@ void testNonDiagnosableBranchArithmetic(int a, int b) {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -922,6 +889,40 @@ void testNonDiagnosableBranchArithmetic(int a, int b) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>44</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>44</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>44</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>44</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>44</integer>
// CHECK-NEXT: <key>col</key><integer>6</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1068,6 +1069,40 @@ void testNonDiagnosableBranchArithmetic(int a, int b) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>53</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>53</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>53</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>53</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>53</integer>
// CHECK-NEXT: <key>col</key><integer>11</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1573,12 +1608,75 @@ void testNonDiagnosableBranchArithmetic(int a, int b) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>81</integer>
+// CHECK-NEXT: <key>line</key><integer>79</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>79</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>79</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>79</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>79</integer>
+// CHECK-NEXT: <key>col</key><integer>11</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Assuming the condition is true</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Assuming the condition is true</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>79</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>79</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>82</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>81</integer>
+// CHECK-NEXT: <key>line</key><integer>82</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1594,12 +1692,12 @@ void testNonDiagnosableBranchArithmetic(int a, int b) {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>81</integer>
+// CHECK-NEXT: <key>line</key><integer>82</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>81</integer>
+// CHECK-NEXT: <key>line</key><integer>82</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1607,12 +1705,12 @@ void testNonDiagnosableBranchArithmetic(int a, int b) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>81</integer>
+// CHECK-NEXT: <key>line</key><integer>82</integer>
// CHECK-NEXT: <key>col</key><integer>24</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>81</integer>
+// CHECK-NEXT: <key>line</key><integer>82</integer>
// CHECK-NEXT: <key>col</key><integer>24</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1624,7 +1722,7 @@ void testNonDiagnosableBranchArithmetic(int a, int b) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>81</integer>
+// CHECK-NEXT: <key>line</key><integer>82</integer>
// CHECK-NEXT: <key>col</key><integer>24</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1632,12 +1730,12 @@ void testNonDiagnosableBranchArithmetic(int a, int b) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>81</integer>
+// CHECK-NEXT: <key>line</key><integer>82</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>81</integer>
+// CHECK-NEXT: <key>line</key><integer>82</integer>
// CHECK-NEXT: <key>col</key><integer>26</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1658,10 +1756,10 @@ void testNonDiagnosableBranchArithmetic(int a, int b) {
// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>f56671e5f67c73abef619b56f7c29fa4</string>
// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
// CHECK-NEXT: <key>issue_context</key><string>testNonDiagnosableBranchArithmetic</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
+// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>81</integer>
+// CHECK-NEXT: <key>line</key><integer>82</integer>
// CHECK-NEXT: <key>col</key><integer>24</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
diff --git a/test/Analysis/const-method-call.cpp b/test/Analysis/const-method-call.cpp
index 17df2a016b89..a5a38929c22f 100644
--- a/test/Analysis/const-method-call.cpp
+++ b/test/Analysis/const-method-call.cpp
@@ -6,6 +6,14 @@ struct A {
int x;
void foo() const;
void bar();
+
+ void testImplicitThisSyntax() {
+ x = 3;
+ foo();
+ clang_analyzer_eval(x == 3); // expected-warning{{TRUE}}
+ bar();
+ clang_analyzer_eval(x == 3); // expected-warning{{UNKNOWN}}
+ }
};
struct B {
@@ -108,6 +116,22 @@ void checkThatContainedConstMethodDoesNotInvalidateObjects() {
clang_analyzer_eval(t.in.x == 2); // expected-warning{{TRUE}}
}
+void checkPointerTypedThisExpression(A *a) {
+ a->x = 3;
+ a->foo();
+ clang_analyzer_eval(a->x == 3); // expected-warning{{TRUE}}
+ a->bar();
+ clang_analyzer_eval(a->x == 3); // expected-warning{{UNKNOWN}}
+}
+
+void checkReferenceTypedThisExpression(A &a) {
+ a.x = 3;
+ a.foo();
+ clang_analyzer_eval(a.x == 3); // expected-warning{{TRUE}}
+ a.bar();
+ clang_analyzer_eval(a.x == 3); // expected-warning{{UNKNOWN}}
+}
+
// --- Versions of the above tests where the const method is inherited --- //
struct B1 {
diff --git a/test/Analysis/constant-folding.c b/test/Analysis/constant-folding.c
index 8189868be2ec..e21d629e9a41 100644
--- a/test/Analysis/constant-folding.c
+++ b/test/Analysis/constant-folding.c
@@ -108,7 +108,11 @@ void testBitwiseRules(unsigned int a, int b) {
clang_analyzer_eval((b | -2) == 0); // expected-warning{{FALSE}}
clang_analyzer_eval((b | 10) == 0); // expected-warning{{FALSE}}
clang_analyzer_eval((b | 0) == 0); // expected-warning{{UNKNOWN}}
+#ifdef ANALYZER_CM_Z3
+ clang_analyzer_eval((b | -2) >= 0); // expected-warning{{FALSE}}
+#else
clang_analyzer_eval((b | -2) >= 0); // expected-warning{{UNKNOWN}}
+#endif
// Check that dynamically computed constants also work.
int constant = 1 << 3;
diff --git a/test/Analysis/constraint_manager_negate_difference.c b/test/Analysis/constraint_manager_negate_difference.c
new file mode 100644
index 000000000000..2236c1693b90
--- /dev/null
+++ b/test/Analysis/constraint_manager_negate_difference.c
@@ -0,0 +1,98 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection,core.builtin -analyzer-config aggressive-binary-operation-simplification=true -verify %s
+
+void clang_analyzer_eval(int);
+
+void exit(int);
+
+#define UINT_MAX (~0U)
+#define INT_MAX (UINT_MAX & (UINT_MAX >> 1))
+#define INT_MIN (UINT_MAX & ~(UINT_MAX >> 1))
+
+extern void __assert_fail (__const char *__assertion, __const char *__file,
+ unsigned int __line, __const char *__function)
+ __attribute__ ((__noreturn__));
+#define assert(expr) \
+ ((expr) ? (void)(0) : __assert_fail (#expr, __FILE__, __LINE__, __func__))
+
+void assert_in_range(int x) {
+ assert(x <= ((int)INT_MAX / 4));
+ assert(x >= -(((int)INT_MAX) / 4));
+}
+
+void assert_in_wide_range(int x) {
+ assert(x <= ((int)INT_MAX / 2));
+ assert(x >= -(((int)INT_MAX) / 2));
+}
+
+void assert_in_range_2(int m, int n) {
+ assert_in_range(m);
+ assert_in_range(n);
+}
+
+void equal(int m, int n) {
+ assert_in_range_2(m, n);
+ if (m != n)
+ return;
+ assert_in_wide_range(m - n);
+ clang_analyzer_eval(n == m); // expected-warning{{TRUE}}
+}
+
+void non_equal(int m, int n) {
+ assert_in_range_2(m, n);
+ if (m == n)
+ return;
+ assert_in_wide_range(m - n);
+ clang_analyzer_eval(n != m); // expected-warning{{TRUE}}
+}
+
+void less_or_equal(int m, int n) {
+ assert_in_range_2(m, n);
+ if (m < n)
+ return;
+ assert_in_wide_range(m - n);
+ clang_analyzer_eval(n <= m); // expected-warning{{TRUE}}
+}
+
+void less(int m, int n) {
+ assert_in_range_2(m, n);
+ if (m <= n)
+ return;
+ assert_in_wide_range(m - n);
+ clang_analyzer_eval(n < m); // expected-warning{{TRUE}}
+}
+
+void greater_or_equal(int m, int n) {
+ assert_in_range_2(m, n);
+ if (m > n)
+ return;
+ assert_in_wide_range(m - n);
+ clang_analyzer_eval(n >= m); // expected-warning{{TRUE}}
+}
+
+void greater(int m, int n) {
+ assert_in_range_2(m, n);
+ if (m >= n)
+ return;
+ assert_in_wide_range(m - n);
+ clang_analyzer_eval(n > m); // expected-warning{{TRUE}}
+}
+
+void negate_positive_range(int m, int n) {
+ if (m - n <= 0)
+ return;
+ clang_analyzer_eval(n - m < 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(n - m > INT_MIN); // expected-warning{{TRUE}}
+ clang_analyzer_eval(n - m == INT_MIN); // expected-warning{{FALSE}}
+}
+
+void negate_int_min(int m, int n) {
+ if (m - n != INT_MIN)
+ return;
+ clang_analyzer_eval(n - m == INT_MIN); // expected-warning{{TRUE}}
+}
+
+void negate_mixed(int m, int n) {
+ if (m -n > INT_MIN && m - n <= 0)
+ return;
+ clang_analyzer_eval(n - m <= 0); // expected-warning{{TRUE}}
+}
diff --git a/test/Analysis/copypaste/macro-complexity.cpp b/test/Analysis/copypaste/macro-complexity.cpp
index 70d3f0c74820..656f91189b4f 100644
--- a/test/Analysis/copypaste/macro-complexity.cpp
+++ b/test/Analysis/copypaste/macro-complexity.cpp
@@ -1,7 +1,7 @@
// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=alpha.clone.CloneChecker -analyzer-config alpha.clone.CloneChecker:MinimumCloneComplexity=10 -verify %s
// Tests that the complexity value of a macro expansion is about the same as
-// the complexity value of a normal function call and the the macro body doesn't
+// the complexity value of a normal function call and the macro body doesn't
// influence the complexity. See the CloneSignature class in CloneDetection.h
// for more information about complexity values of clones.
@@ -20,7 +20,7 @@ int manualMacroClone(int a, int b) { // expected-note{{Similar code here}}
}
// Now we actually use the macro to generate the same AST as above. They
-// shouldn't be reported because the macros only slighly increase the complexity
+// shouldn't be reported because the macros only slightly increase the complexity
// value and the resulting code will never pass the MinimumCloneComplexity
// constraint.
diff --git a/test/Analysis/copypaste/plist-diagnostics.cpp b/test/Analysis/copypaste/plist-diagnostics.cpp
index c138c6f1f92a..38237b03c95f 100644
--- a/test/Analysis/copypaste/plist-diagnostics.cpp
+++ b/test/Analysis/copypaste/plist-diagnostics.cpp
@@ -17,12 +17,39 @@ int maxClone(int a, int b) { // expected-note{{Similar code here}}
return b;
}
-// FIXME: This plist output doesn't include the extra note on line 13.
-// It should be updated once the format for extra notes in plists is defined.
-
// CHECK: <key>diagnostics</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>notes</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>13</integer>
+// CHECK-NEXT: <key>col</key><integer>28</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>13</integer>
+// CHECK-NEXT: <key>col</key><integer>28</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>18</integer>
+// CHECK-NEXT: <key>col</key><integer>1</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Similar code here</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Similar code here</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
diff --git a/test/Analysis/crash-trace.c b/test/Analysis/crash-trace.c
index b79dd02e6b43..ef1763ef97a5 100644
--- a/test/Analysis/crash-trace.c
+++ b/test/Analysis/crash-trace.c
@@ -18,6 +18,6 @@ void test() {
// CHECK: 0. Program arguments: {{.*}}clang
// CHECK-NEXT: 1. <eof> parser at end of file
// CHECK-NEXT: 2. While analyzing stack:
-// CHECK-NEXT: #0 void inlined()
-// CHECK-NEXT: #1 void test()
+// CHECK-NEXT: #0 Calling inlined at line 15
+// CHECK-NEXT: #1 Calling test
// CHECK-NEXT: 3. {{.*}}crash-trace.c:{{[0-9]+}}:3: Error evaluating statement
diff --git a/test/Analysis/cstring-plist.c b/test/Analysis/cstring-plist.c
new file mode 100644
index 000000000000..19d0e46fd366
--- /dev/null
+++ b/test/Analysis/cstring-plist.c
@@ -0,0 +1,22 @@
+// RUN: rm -f %t
+// RUN: %clang_analyze_cc1 -fblocks -analyzer-checker=core,unix.Malloc,unix.cstring.NullArg -analyzer-disable-checker=alpha.unix.cstring.OutOfBounds -analyzer-output=plist -analyzer-config path-diagnostics-alternate=false -o %t %s
+// RUN: FileCheck -input-file %t %s
+
+typedef __typeof(sizeof(int)) size_t;
+void *malloc(size_t);
+void free(void *);
+char *strncpy(char *restrict s1, const char *restrict s2, size_t n);
+
+
+
+void cstringchecker_bounds_nocrash() {
+ char *p = malloc(2);
+ strncpy(p, "AAA", sizeof("AAA")); // we don't expect warning as the checker is disabled
+ free(p);
+}
+
+// CHECK: <key>diagnostics</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </plist>
diff --git a/test/Analysis/cstring-syntax.c b/test/Analysis/cstring-syntax.c
index 313ac5449540..fe1253bedba3 100644
--- a/test/Analysis/cstring-syntax.c
+++ b/test/Analysis/cstring-syntax.c
@@ -1,8 +1,12 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=unix.cstring.BadSizeArg -analyzer-store=region -Wno-strncat-size -Wno-strlcpy-strlcat-size -Wno-sizeof-array-argument -Wno-sizeof-pointer-memaccess -verify %s
+// RUN: %clang_analyze_cc1 -triple armv7-a15-linux -analyzer-checker=unix.cstring.BadSizeArg -analyzer-store=region -Wno-strncat-size -Wno-strlcpy-strlcat-size -Wno-sizeof-array-argument -Wno-sizeof-pointer-memaccess -verify %s
+// RUN: %clang_analyze_cc1 -triple aarch64_be-none-linux-gnu -analyzer-checker=unix.cstring.BadSizeArg -analyzer-store=region -Wno-strncat-size -Wno-strlcpy-strlcat-size -Wno-sizeof-array-argument -Wno-sizeof-pointer-memaccess -verify %s
+// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -analyzer-checker=unix.cstring.BadSizeArg -analyzer-store=region -Wno-strncat-size -Wno-strlcpy-strlcat-size -Wno-sizeof-array-argument -Wno-sizeof-pointer-memaccess -verify %s
typedef __SIZE_TYPE__ size_t;
char *strncat(char *, const char *, size_t);
size_t strlen (const char *s);
+size_t strlcpy(char *, const char *, size_t);
void testStrncat(const char *src) {
char dest[10];
@@ -13,3 +17,19 @@ void testStrncat(const char *src) {
// Should not crash when sizeof has a type argument.
strncat(dest, "AAAAAAAAAAAAAAAAAAAAAAAAAAA", sizeof(char));
}
+
+void testStrlcpy(const char *src) {
+ char dest[10];
+ size_t destlen = sizeof(dest);
+ size_t srclen = sizeof(src);
+ size_t badlen = 20;
+ size_t ulen;
+ strlcpy(dest, src, sizeof(dest));
+ strlcpy(dest, src, destlen);
+ strlcpy(dest, src, 10);
+ strlcpy(dest, src, 20); // expected-warning {{The third argument is larger than the size of the input buffer. Replace with the value 'sizeof(dest)` or lower}}
+ strlcpy(dest, src, badlen); // expected-warning {{The third argument is larger than the size of the input buffer. Replace with the value 'sizeof(dest)` or lower}}
+ strlcpy(dest, src, ulen);
+ strlcpy(dest + 5, src, 5);
+ strlcpy(dest + 5, src, 10); // expected-warning {{The third argument is larger than the size of the input buffer.}}
+}
diff --git a/test/Analysis/ctor.mm b/test/Analysis/ctor.mm
index e903263431fc..751cdb944dc7 100644
--- a/test/Analysis/ctor.mm
+++ b/test/Analysis/ctor.mm
@@ -1,4 +1,7 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -fobjc-arc -analyzer-config c++-inlining=constructors -Wno-null-dereference -std=c++11 -verify %s
+// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -DI386 -analyzer-checker=core,debug.ExprInspection -fobjc-arc -analyzer-config c++-inlining=constructors -Wno-null-dereference -std=c++11 -verify %s
+// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -DI386 -analyzer-checker=core,debug.ExprInspection -fobjc-arc -analyzer-config c++-inlining=constructors -Wno-null-dereference -std=c++11 -verify -DTEST_INLINABLE_ALLOCATORS %s
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin12 -analyzer-checker=core,debug.ExprInspection -fobjc-arc -analyzer-config c++-inlining=constructors -Wno-null-dereference -std=c++11 -verify %s
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin12 -analyzer-checker=core,debug.ExprInspection -fobjc-arc -analyzer-config c++-inlining=constructors -Wno-null-dereference -std=c++11 -verify -DTEST_INLINABLE_ALLOCATORS %s
#include "Inputs/system-header-simulator-cxx.h"
@@ -572,10 +575,9 @@ namespace ZeroInitialization {
}
void testNew() {
- // FIXME: Pending proper implementation of constructors for 'new'.
raw_pair *pp = new raw_pair();
- clang_analyzer_eval(pp->p1 == 0); // expected-warning{{UNKNOWN}}
- clang_analyzer_eval(pp->p2 == 0); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(pp->p1 == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(pp->p2 == 0); // expected-warning{{TRUE}}
}
void testArrayNew() {
@@ -638,12 +640,15 @@ namespace ZeroInitialization {
class Empty {
public:
- Empty();
+ static int glob;
+ Empty(); // No body.
+ Empty(int x); // Body below.
};
class PairContainer : public Empty {
- raw_pair p;
public:
+ raw_pair p;
+ int q;
PairContainer() : Empty(), p() {
// This previously caused a crash because the empty base class looked
// like an initialization of 'p'.
@@ -651,8 +656,52 @@ namespace ZeroInitialization {
PairContainer(int) : Empty(), p() {
// Test inlining something else here.
}
+ PairContainer(double): Empty(1), p() {
+ clang_analyzer_eval(p.p1 == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(p.p2 == 0); // expected-warning{{TRUE}}
+
+ clang_analyzer_eval(q == 1); // expected-warning{{TRUE}}
+
+ // This one's indeed UNKNOWN. Definitely not TRUE.
+ clang_analyzer_eval(p.p2 == glob); // expected-warning{{UNKNOWN}}
+ }
};
+ Empty::Empty(int x) {
+ static_cast<PairContainer *>(this)->p.p1 = x;
+ static_cast<PairContainer *>(this)->q = x;
+ // Our static member will store the old garbage values of fields that aren't
+ // yet initialized. It's not certainly garbage though (i.e. the constructor
+ // could have been called on an initialized piece of memory), so no
+ // uninitialized value warning here, and it should be a symbol, not
+ // undefined value, for later comparison.
+ glob = static_cast<PairContainer *>(this)->p.p2;
+ }
+
+ class Empty2 {
+ public:
+ static int glob_p1, glob_p2;
+ Empty2(); // Body below.
+ };
+
+ class PairDoubleEmptyContainer: public Empty, public Empty2 {
+ public:
+ raw_pair p;
+ PairDoubleEmptyContainer(): Empty(), Empty2(), p() {
+ clang_analyzer_eval(p.p1 == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(p.p2 == 0); // expected-warning{{TRUE}}
+
+ // This is indeed UNKNOWN.
+ clang_analyzer_eval(p.p1 == glob_p1); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(p.p2 == glob_p2); // expected-warning{{UNKNOWN}}
+ }
+ };
+
+ Empty2::Empty2() {
+ glob_p1 = static_cast<PairDoubleEmptyContainer *>(this)->p.p1;
+ glob_p2 = static_cast<PairDoubleEmptyContainer *>(this)->p.p2;
+ }
+
class PairContainerContainer {
int padding;
PairContainer pc;
@@ -679,8 +728,7 @@ namespace InitializerList {
void testDynamic() {
List *list = new List{1, 2};
- // FIXME: When we handle constructors with 'new', this will be TRUE.
- clang_analyzer_eval(list->usedInitializerList); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(list->usedInitializerList); // expected-warning{{TRUE}}
}
}
@@ -730,3 +778,87 @@ namespace NoCrashOnEmptyBaseOptimization {
S s;
}
}
+
+namespace EmptyBaseAssign {
+struct B1 {};
+struct B2 { int x; };
+struct D: public B1, public B2 {
+const D &operator=(const D &d) {
+ *((B2 *)this) = d;
+ *((B1 *)this) = d;
+ return *this;
+}
+};
+
+void test() {
+ D d1;
+ d1.x = 1;
+ D d2;
+ d2 = d1;
+ clang_analyzer_eval(d2.x == 1); // expected-warning{{TRUE}}
+}
+}
+
+namespace vbase_zero_init {
+class A {
+ virtual void foo();
+};
+
+class B {
+ virtual void bar();
+public:
+ static int glob_y, glob_z, glob_w;
+ int x;
+ B(); // Body below.
+};
+
+class C : virtual public A {
+public:
+ int y;
+};
+
+class D : public B, public C {
+public:
+ // 'z', unlike 'w', resides in an area that would have been within padding of
+ // base class 'C' if it wasn't part of 'D', but only on 64-bit systems.
+ int z, w;
+ // Initialization order: A(), B(), C().
+ D() : A(), C() {
+ clang_analyzer_eval(x == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(y == 0); // expected-warning{{TRUE}}
+#ifdef I386
+ clang_analyzer_eval(z == 3); // expected-warning{{TRUE}}
+#else
+ // FIXME: Should be TRUE. Initialized in B().
+ clang_analyzer_eval(z == 3); // expected-warning{{UNKNOWN}}
+#endif
+ clang_analyzer_eval(w == 4); // expected-warning{{TRUE}}
+
+ // FIXME: Should be UNKNOWN. Changed in B() since glob_y was assigned.
+ clang_analyzer_eval(y == glob_y); // expected-warning{{TRUE}}
+
+#ifdef I386
+ clang_analyzer_eval(z == glob_z); // expected-warning{{UNKNOWN}}
+#else
+ // FIXME: Should be UNKNOWN. Changed in B() since glob_z was assigned.
+ clang_analyzer_eval(z == glob_z); // expected-warning{{TRUE}}
+#endif
+
+ clang_analyzer_eval(w == glob_w); // expected-warning{{UNKNOWN}}
+ } // no-crash
+};
+
+B::B() : x(1) {
+ // Our static members will store the old garbage values of fields that aren't
+ // yet initialized. These aren't certainly garbage though (i.e. the
+ // constructor could have been called on an initialized piece of memory),
+ // so no uninitialized value warning here, and these should be symbols, not
+ // undefined values, for later comparison.
+ glob_y = static_cast<D *>(this)->y;
+ glob_z = static_cast<D *>(this)->z;
+ glob_w = static_cast<D *>(this)->w;
+ static_cast<D *>(this)->y = 2;
+ static_cast<D *>(this)->z = 3;
+ static_cast<D *>(this)->w = 4;
+}
+}
diff --git a/test/Analysis/ctu-hdr.h b/test/Analysis/ctu-hdr.h
new file mode 100644
index 000000000000..5a1e694d0686
--- /dev/null
+++ b/test/Analysis/ctu-hdr.h
@@ -0,0 +1,3 @@
+#define MACRODIAG() clang_analyzer_warnIfReached()
+
+void clang_analyzer_warnIfReached();
diff --git a/test/Analysis/ctu-main.cpp b/test/Analysis/ctu-main.cpp
new file mode 100644
index 000000000000..33da84962cef
--- /dev/null
+++ b/test/Analysis/ctu-main.cpp
@@ -0,0 +1,68 @@
+// RUN: mkdir -p %T/ctudir
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o %T/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o %T/ctudir/ctu-chain.cpp.ast %S/Inputs/ctu-chain.cpp
+// RUN: cp %S/Inputs/externalFnMap.txt %T/ctudir/
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-config experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%T/ctudir -verify %s
+
+#include "ctu-hdr.h"
+
+void clang_analyzer_eval(int);
+
+int f(int);
+int g(int);
+int h(int);
+
+int callback_to_main(int x) { return x + 1; }
+
+namespace myns {
+int fns(int x);
+
+namespace embed_ns {
+int fens(int x);
+}
+
+class embed_cls {
+public:
+ int fecl(int x);
+};
+}
+
+class mycls {
+public:
+ int fcl(int x);
+ static int fscl(int x);
+
+ class embed_cls2 {
+ public:
+ int fecl2(int x);
+ };
+};
+
+namespace chns {
+int chf1(int x);
+}
+
+int fun_using_anon_struct(int);
+int other_macro_diag(int);
+
+int main() {
+ clang_analyzer_eval(f(3) == 2); // expected-warning{{TRUE}}
+ clang_analyzer_eval(f(4) == 3); // expected-warning{{TRUE}}
+ clang_analyzer_eval(f(5) == 3); // expected-warning{{FALSE}}
+ clang_analyzer_eval(g(4) == 6); // expected-warning{{TRUE}}
+ clang_analyzer_eval(h(2) == 8); // expected-warning{{TRUE}}
+
+ clang_analyzer_eval(myns::fns(2) == 9); // expected-warning{{TRUE}}
+ clang_analyzer_eval(myns::embed_ns::fens(2) == -1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(mycls().fcl(1) == 6); // expected-warning{{TRUE}}
+ clang_analyzer_eval(mycls::fscl(1) == 7); // expected-warning{{TRUE}}
+ clang_analyzer_eval(myns::embed_cls().fecl(1) == -6); // expected-warning{{TRUE}}
+ clang_analyzer_eval(mycls::embed_cls2().fecl2(0) == -11); // expected-warning{{TRUE}}
+
+ clang_analyzer_eval(chns::chf1(4) == 12); // expected-warning{{TRUE}}
+ clang_analyzer_eval(fun_using_anon_struct(8) == 8); // expected-warning{{TRUE}}
+
+ clang_analyzer_eval(other_macro_diag(1) == 1); // expected-warning{{TRUE}}
+ // expected-warning@Inputs/ctu-other.cpp:75{{REACHABLE}}
+ MACRODIAG(); // expected-warning{{REACHABLE}}
+}
diff --git a/test/Analysis/cxx-for-range.cpp b/test/Analysis/cxx-for-range.cpp
index bf3cfbff1231..d1a689b62cdb 100644
--- a/test/Analysis/cxx-for-range.cpp
+++ b/test/Analysis/cxx-for-range.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core -analyzer-config path-diagnostics-alternate=true -analyzer-output=plist-multi-file -o %t.plist -verify %s
+// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core -analyzer-output=plist-multi-file -o %t.plist -verify %s
// RUN: FileCheck --input-file=%t.plist %s
extern void work();
diff --git a/test/Analysis/cxx-uninitialized-object-inheritance.cpp b/test/Analysis/cxx-uninitialized-object-inheritance.cpp
new file mode 100644
index 000000000000..3b048b759e13
--- /dev/null
+++ b/test/Analysis/cxx-uninitialized-object-inheritance.cpp
@@ -0,0 +1,775 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject -analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true -std=c++11 -verify %s
+
+//===----------------------------------------------------------------------===//
+// Non-polymorphic inheritance tests
+//===----------------------------------------------------------------------===//
+
+class NonPolymorphicLeft1 {
+ int x;
+
+protected:
+ int y;
+
+public:
+ NonPolymorphicLeft1() = default;
+ NonPolymorphicLeft1(int) : x(1) {}
+};
+
+class NonPolymorphicInheritanceTest1 : public NonPolymorphicLeft1 {
+ int z;
+
+public:
+ NonPolymorphicInheritanceTest1()
+ : NonPolymorphicLeft1(int{}) {
+ y = 2;
+ z = 3;
+ // All good!
+ }
+};
+
+void fNonPolymorphicInheritanceTest1() {
+ NonPolymorphicInheritanceTest1();
+}
+
+class NonPolymorphicBaseClass2 {
+ int x; // expected-note{{uninitialized field 'this->x'}}
+protected:
+ int y;
+
+public:
+ NonPolymorphicBaseClass2() = default;
+ NonPolymorphicBaseClass2(int) : x(4) {}
+};
+
+class NonPolymorphicInheritanceTest2 : public NonPolymorphicBaseClass2 {
+ int z;
+
+public:
+ NonPolymorphicInheritanceTest2() {
+ y = 5;
+ z = 6; // expected-warning{{1 uninitialized field}}
+ }
+};
+
+void fNonPolymorphicInheritanceTest2() {
+ NonPolymorphicInheritanceTest2();
+}
+
+class NonPolymorphicBaseClass3 {
+ int x;
+
+protected:
+ int y; // expected-note{{uninitialized field 'this->y'}}
+public:
+ NonPolymorphicBaseClass3() = default;
+ NonPolymorphicBaseClass3(int) : x(7) {}
+};
+
+class NonPolymorphicInheritanceTest3 : public NonPolymorphicBaseClass3 {
+ int z;
+
+public:
+ NonPolymorphicInheritanceTest3()
+ : NonPolymorphicBaseClass3(int{}) {
+ z = 8; // expected-warning{{1 uninitialized field}}
+ }
+};
+
+void fNonPolymorphicInheritanceTest3() {
+ NonPolymorphicInheritanceTest3();
+}
+
+class NonPolymorphicBaseClass4 {
+ int x;
+
+protected:
+ int y;
+
+public:
+ NonPolymorphicBaseClass4() = default;
+ NonPolymorphicBaseClass4(int) : x(9) {}
+};
+
+class NonPolymorphicInheritanceTest4 : public NonPolymorphicBaseClass4 {
+ int z; // expected-note{{uninitialized field 'this->z'}}
+
+public:
+ NonPolymorphicInheritanceTest4()
+ : NonPolymorphicBaseClass4(int{}) {
+ y = 10; // expected-warning{{1 uninitialized field}}
+ }
+};
+
+void fNonPolymorphicInheritanceTest4() {
+ NonPolymorphicInheritanceTest4();
+}
+
+//===----------------------------------------------------------------------===//
+// Polymorphic inheritance tests
+//===----------------------------------------------------------------------===//
+
+class PolymorphicLeft1 {
+ int x;
+
+protected:
+ int y;
+
+public:
+ virtual ~PolymorphicLeft1() = default;
+ PolymorphicLeft1() = default;
+ PolymorphicLeft1(int) : x(11) {}
+};
+
+class PolymorphicInheritanceTest1 : public PolymorphicLeft1 {
+ int z;
+
+public:
+ PolymorphicInheritanceTest1()
+ : PolymorphicLeft1(int{}) {
+ y = 12;
+ z = 13;
+ // All good!
+ }
+};
+
+void fPolymorphicInheritanceTest1() {
+ PolymorphicInheritanceTest1();
+}
+
+class PolymorphicRight1 {
+ int x; // expected-note{{uninitialized field 'this->x'}}
+protected:
+ int y;
+
+public:
+ virtual ~PolymorphicRight1() = default;
+ PolymorphicRight1() = default;
+ PolymorphicRight1(int) : x(14) {}
+};
+
+class PolymorphicInheritanceTest2 : public PolymorphicRight1 {
+ int z;
+
+public:
+ PolymorphicInheritanceTest2() {
+ y = 15;
+ z = 16; // expected-warning{{1 uninitialized field}}
+ }
+};
+
+void fPolymorphicInheritanceTest2() {
+ PolymorphicInheritanceTest2();
+}
+
+class PolymorphicBaseClass3 {
+ int x;
+
+protected:
+ int y; // expected-note{{uninitialized field 'this->y'}}
+public:
+ virtual ~PolymorphicBaseClass3() = default;
+ PolymorphicBaseClass3() = default;
+ PolymorphicBaseClass3(int) : x(17) {}
+};
+
+class PolymorphicInheritanceTest3 : public PolymorphicBaseClass3 {
+ int z;
+
+public:
+ PolymorphicInheritanceTest3()
+ : PolymorphicBaseClass3(int{}) {
+ z = 18; // expected-warning{{1 uninitialized field}}
+ }
+};
+
+void fPolymorphicInheritanceTest3() {
+ PolymorphicInheritanceTest3();
+}
+
+class PolymorphicBaseClass4 {
+ int x;
+
+protected:
+ int y;
+
+public:
+ virtual ~PolymorphicBaseClass4() = default;
+ PolymorphicBaseClass4() = default;
+ PolymorphicBaseClass4(int) : x(19) {}
+};
+
+class PolymorphicInheritanceTest4 : public PolymorphicBaseClass4 {
+ int z; // expected-note{{uninitialized field 'this->z'}}
+
+public:
+ PolymorphicInheritanceTest4()
+ : PolymorphicBaseClass4(int{}) {
+ y = 20; // expected-warning{{1 uninitialized field}}
+ }
+};
+
+void fPolymorphicInheritanceTest4() {
+ PolymorphicInheritanceTest4();
+}
+
+//===----------------------------------------------------------------------===//
+// Virtual inheritance tests
+//===----------------------------------------------------------------------===//
+
+class VirtualPolymorphicLeft1 {
+ int x;
+
+protected:
+ int y;
+
+public:
+ virtual ~VirtualPolymorphicLeft1() = default;
+ VirtualPolymorphicLeft1() = default;
+ VirtualPolymorphicLeft1(int) : x(21) {}
+};
+
+class VirtualInheritanceTest1 : virtual public VirtualPolymorphicLeft1 {
+ int z;
+
+public:
+ VirtualInheritanceTest1()
+ : VirtualPolymorphicLeft1(int()) {
+ y = 22;
+ z = 23;
+ // All good!
+ }
+};
+
+void fVirtualInheritanceTest1() {
+ VirtualInheritanceTest1();
+}
+
+class VirtualPolymorphicRight1 {
+ int x; // expected-note{{uninitialized field 'this->x'}}
+protected:
+ int y;
+
+public:
+ virtual ~VirtualPolymorphicRight1() = default;
+ VirtualPolymorphicRight1() = default;
+ VirtualPolymorphicRight1(int) : x(24) {}
+};
+
+class VirtualInheritanceTest2 : virtual public VirtualPolymorphicRight1 {
+ int z;
+
+public:
+ VirtualInheritanceTest2() {
+ y = 25;
+ z = 26; // expected-warning{{1 uninitialized field}}
+ }
+};
+
+void fVirtualInheritanceTest2() {
+ VirtualInheritanceTest2();
+}
+
+class VirtualPolymorphicBaseClass3 {
+ int x;
+
+protected:
+ int y; // expected-note{{uninitialized field 'this->y'}}
+public:
+ virtual ~VirtualPolymorphicBaseClass3() = default;
+ VirtualPolymorphicBaseClass3() = default;
+ VirtualPolymorphicBaseClass3(int) : x(27) {}
+};
+
+class VirtualInheritanceTest3 : virtual public VirtualPolymorphicBaseClass3 {
+ int z;
+
+public:
+ VirtualInheritanceTest3()
+ : VirtualPolymorphicBaseClass3(int{}) {
+ z = 28; // expected-warning{{1 uninitialized field}}
+ }
+};
+
+void fVirtualInheritanceTest3() {
+ VirtualInheritanceTest3();
+}
+
+//===----------------------------------------------------------------------===//
+// Multiple inheritance tests
+//===----------------------------------------------------------------------===//
+
+/*
+ Left Right
+ \ /
+ \ /
+ \ /
+ MultipleInheritanceTest
+*/
+
+struct Left1 {
+ int x;
+ Left1() = default;
+ Left1(int) : x(29) {}
+};
+struct Right1 {
+ int y;
+ Right1() = default;
+ Right1(int) : y(30) {}
+};
+
+class MultipleInheritanceTest1 : public Left1, public Right1 {
+ int z;
+
+public:
+ MultipleInheritanceTest1()
+ : Left1(int{}),
+ Right1(char{}) {
+ z = 31;
+ // All good!
+ }
+
+ MultipleInheritanceTest1(int)
+ : Left1(int{}) {
+ y = 32;
+ z = 33;
+ // All good!
+ }
+
+ MultipleInheritanceTest1(int, int)
+ : Right1(char{}) {
+ x = 34;
+ z = 35;
+ // All good!
+ }
+};
+
+void fMultipleInheritanceTest1() {
+ MultipleInheritanceTest1();
+ MultipleInheritanceTest1(int());
+ MultipleInheritanceTest1(int(), int());
+}
+
+struct Left2 {
+ int x;
+ Left2() = default;
+ Left2(int) : x(36) {}
+};
+struct Right2 {
+ int y; // expected-note{{uninitialized field 'this->y'}}
+ Right2() = default;
+ Right2(int) : y(37) {}
+};
+
+class MultipleInheritanceTest2 : public Left2, public Right2 {
+ int z;
+
+public:
+ MultipleInheritanceTest2()
+ : Left2(int{}) {
+ z = 38; // expected-warning{{1 uninitialized field}}
+ }
+};
+
+void fMultipleInheritanceTest2() {
+ MultipleInheritanceTest2();
+}
+
+struct Left3 {
+ int x; // expected-note{{uninitialized field 'this->x'}}
+ Left3() = default;
+ Left3(int) : x(39) {}
+};
+struct Right3 {
+ int y;
+ Right3() = default;
+ Right3(int) : y(40) {}
+};
+
+class MultipleInheritanceTest3 : public Left3, public Right3 {
+ int z;
+
+public:
+ MultipleInheritanceTest3()
+ : Right3(char{}) {
+ z = 41; // expected-warning{{1 uninitialized field}}
+ }
+};
+
+void fMultipleInheritanceTest3() {
+ MultipleInheritanceTest3();
+}
+
+struct Left4 {
+ int x;
+ Left4() = default;
+ Left4(int) : x(42) {}
+};
+struct Right4 {
+ int y;
+ Right4() = default;
+ Right4(int) : y(43) {}
+};
+
+class MultipleInheritanceTest4 : public Left4, public Right4 {
+ int z; // expected-note{{uninitialized field 'this->z'}}
+
+public:
+ MultipleInheritanceTest4()
+ : Left4(int{}),
+ Right4(char{}) { // expected-warning{{1 uninitialized field}}
+ }
+};
+
+void fMultipleInheritanceTest4() {
+ MultipleInheritanceTest4();
+}
+
+struct Left5 {
+ int x;
+ Left5() = default;
+ Left5(int) : x(44) {}
+};
+struct Right5 {
+ int y; // expected-note{{uninitialized field 'this->y'}}
+ Right5() = default;
+ Right5(int) : y(45) {}
+};
+
+class MultipleInheritanceTest5 : public Left5, public Right5 {
+ int z; // expected-note{{uninitialized field 'this->z'}}
+
+public:
+ MultipleInheritanceTest5() // expected-warning{{2 uninitialized fields}}
+ : Left5(int{}) {
+ }
+};
+
+void fMultipleInheritanceTest5() {
+ MultipleInheritanceTest5();
+}
+
+//===----------------------------------------------------------------------===//
+// Non-virtual diamond inheritance tests
+//===----------------------------------------------------------------------===//
+
+/*
+ NonVirtualBase NonVirtualBase
+ | |
+ | |
+ | |
+ First Second
+ \ /
+ \ /
+ \ /
+ NonVirtualDiamondInheritanceTest
+*/
+
+struct NonVirtualBase1 {
+ int x;
+ NonVirtualBase1() = default;
+ NonVirtualBase1(int) : x(46) {}
+};
+struct First1 : public NonVirtualBase1 {
+ First1() = default;
+ First1(int) : NonVirtualBase1(int{}) {}
+};
+struct Second1 : public NonVirtualBase1 {
+ Second1() = default;
+ Second1(int) : NonVirtualBase1(int{}) {}
+};
+
+class NonVirtualDiamondInheritanceTest1 : public First1, public Second1 {
+ int z;
+
+public:
+ NonVirtualDiamondInheritanceTest1()
+ : First1(int{}),
+ Second1(int{}) {
+ z = 47;
+ // All good!
+ }
+
+ NonVirtualDiamondInheritanceTest1(int)
+ : First1(int{}) {
+ Second1::x = 48;
+ z = 49;
+ // All good!
+ }
+
+ NonVirtualDiamondInheritanceTest1(int, int)
+ : Second1(int{}) {
+ First1::x = 50;
+ z = 51;
+ // All good!
+ }
+};
+
+void fNonVirtualDiamondInheritanceTest1() {
+ NonVirtualDiamondInheritanceTest1();
+ NonVirtualDiamondInheritanceTest1(int());
+ NonVirtualDiamondInheritanceTest1(int(), int());
+}
+
+struct NonVirtualBase2 {
+ int x; // expected-note{{uninitialized field 'this->x'}}
+ NonVirtualBase2() = default;
+ NonVirtualBase2(int) : x(52) {}
+};
+struct First2 : public NonVirtualBase2 {
+ First2() = default;
+ First2(int) : NonVirtualBase2(int{}) {}
+};
+struct Second2 : public NonVirtualBase2 {
+ Second2() = default;
+ Second2(int) : NonVirtualBase2(int{}) {}
+};
+
+class NonVirtualDiamondInheritanceTest2 : public First2, public Second2 {
+ int z;
+
+public:
+ NonVirtualDiamondInheritanceTest2()
+ : First2(int{}) {
+ z = 53; // expected-warning{{1 uninitialized field}}
+ }
+};
+
+void fNonVirtualDiamondInheritanceTest2() {
+ NonVirtualDiamondInheritanceTest2();
+}
+
+struct NonVirtualBase3 {
+ int x; // expected-note{{uninitialized field 'this->x'}}
+ NonVirtualBase3() = default;
+ NonVirtualBase3(int) : x(54) {}
+};
+struct First3 : public NonVirtualBase3 {
+ First3() = default;
+ First3(int) : NonVirtualBase3(int{}) {}
+};
+struct Second3 : public NonVirtualBase3 {
+ Second3() = default;
+ Second3(int) : NonVirtualBase3(int{}) {}
+};
+
+class NonVirtualDiamondInheritanceTest3 : public First3, public Second3 {
+ int z;
+
+public:
+ NonVirtualDiamondInheritanceTest3()
+ : Second3(int{}) {
+ z = 55; // expected-warning{{1 uninitialized field}}
+ }
+};
+
+void fNonVirtualDiamondInheritanceTest3() {
+ NonVirtualDiamondInheritanceTest3();
+}
+
+struct NonVirtualBase4 {
+ int x; // expected-note{{uninitialized field 'this->x'}}
+ // expected-note@-1{{uninitialized field 'this->x'}}
+ NonVirtualBase4() = default;
+ NonVirtualBase4(int) : x(56) {}
+};
+struct First4 : public NonVirtualBase4 {
+ First4() = default;
+ First4(int) : NonVirtualBase4(int{}) {}
+};
+struct Second4 : public NonVirtualBase4 {
+ Second4() = default;
+ Second4(int) : NonVirtualBase4(int{}) {}
+};
+
+class NonVirtualDiamondInheritanceTest4 : public First4, public Second4 {
+ int z;
+
+public:
+ NonVirtualDiamondInheritanceTest4() {
+ z = 57; // expected-warning{{2 uninitialized fields}}
+ }
+};
+
+void fNonVirtualDiamondInheritanceTest4() {
+ NonVirtualDiamondInheritanceTest4();
+}
+
+struct NonVirtualBase5 {
+ int x;
+ NonVirtualBase5() = default;
+ NonVirtualBase5(int) : x(58) {}
+};
+struct First5 : public NonVirtualBase5 {
+ First5() = default;
+ First5(int) : NonVirtualBase5(int{}) {}
+};
+struct Second5 : public NonVirtualBase5 {
+ Second5() = default;
+ Second5(int) : NonVirtualBase5(int{}) {}
+};
+
+class NonVirtualDiamondInheritanceTest5 : public First5, public Second5 {
+ int z; // expected-note{{uninitialized field 'this->z'}}
+
+public:
+ NonVirtualDiamondInheritanceTest5()
+ : First5(int{}),
+ Second5(int{}) { // expected-warning{{1 uninitialized field}}
+ }
+};
+
+void fNonVirtualDiamondInheritanceTest5() {
+ NonVirtualDiamondInheritanceTest5();
+}
+
+struct NonVirtualBase6 {
+ int x; // expected-note{{uninitialized field 'this->x'}}
+ NonVirtualBase6() = default;
+ NonVirtualBase6(int) : x(59) {}
+};
+struct First6 : public NonVirtualBase6 {
+ First6() = default;
+ First6(int) : NonVirtualBase6(int{}) {}
+};
+struct Second6 : public NonVirtualBase6 {
+ Second6() = default;
+ Second6(int) : NonVirtualBase6(int{}) {}
+};
+
+class NonVirtualDiamondInheritanceTest6 : public First6, public Second6 {
+ int z; // expected-note{{uninitialized field 'this->z'}}
+
+public:
+ NonVirtualDiamondInheritanceTest6() // expected-warning{{2 uninitialized fields}}
+ : First6(int{}) {
+ // 'z' and 'Second::x' unintialized
+ }
+};
+
+void fNonVirtualDiamondInheritanceTest6() {
+ NonVirtualDiamondInheritanceTest6();
+}
+
+//===----------------------------------------------------------------------===//
+// Virtual diamond inheritance tests
+//===----------------------------------------------------------------------===//
+
+/*
+ VirtualBase
+ / \
+ / \
+ / \
+ VirtualFirst VirtualSecond
+ \ /
+ \ /
+ \ /
+ VirtualDiamondInheritanceTest
+*/
+
+struct VirtualBase1 {
+ int x;
+ VirtualBase1() = default;
+ VirtualBase1(int) : x(60) {}
+};
+struct VirtualFirst1 : virtual public VirtualBase1 {
+ VirtualFirst1() = default;
+ VirtualFirst1(int) : VirtualBase1(int{}) {}
+ VirtualFirst1(int, int) { x = 61; }
+};
+struct VirtualSecond1 : virtual public VirtualBase1 {
+ VirtualSecond1() = default;
+ VirtualSecond1(int) : VirtualBase1(int{}) {}
+ VirtualSecond1(int, int) { x = 62; }
+};
+
+class VirtualDiamondInheritanceTest1 : public VirtualFirst1, public VirtualSecond1 {
+
+public:
+ VirtualDiamondInheritanceTest1() {
+ x = 0;
+ // All good!
+ }
+
+ VirtualDiamondInheritanceTest1(int)
+ : VirtualFirst1(int{}, int{}),
+ VirtualSecond1(int{}, int{}) {
+ // All good!
+ }
+
+ VirtualDiamondInheritanceTest1(int, int)
+ : VirtualFirst1(int{}, int{}) {
+ // All good!
+ }
+};
+
+void fVirtualDiamondInheritanceTest1() {
+ VirtualDiamondInheritanceTest1();
+ VirtualDiamondInheritanceTest1(int());
+ VirtualDiamondInheritanceTest1(int(), int());
+}
+
+struct VirtualBase2 {
+ int x; // expected-note{{uninitialized field 'this->x'}}
+ VirtualBase2() = default;
+ VirtualBase2(int) : x(63) {}
+};
+struct VirtualFirst2 : virtual public VirtualBase2 {
+ VirtualFirst2() = default;
+ VirtualFirst2(int) : VirtualBase2(int{}) {}
+ VirtualFirst2(int, int) { x = 64; }
+};
+struct VirtualSecond2 : virtual public VirtualBase2 {
+ VirtualSecond2() = default;
+ VirtualSecond2(int) : VirtualBase2(int{}) {}
+ VirtualSecond2(int, int) { x = 65; }
+};
+
+class VirtualDiamondInheritanceTest2 : public VirtualFirst2, public VirtualSecond2 {
+
+public:
+ VirtualDiamondInheritanceTest2() // expected-warning{{1 uninitialized field}}
+ : VirtualFirst2(int{}) {
+ // From the N4659 C++ Standard Working Draft:
+ //
+ // (15.6.2.7)
+ // [...] A 'mem-initializer' where the 'mem-initializer-id' denotes a
+ // virtual base class is ignored during execution of a constructor of any
+ // class that is not the most derived class.
+ //
+ // This means that Left1::x will not be initialized, because in both
+ // VirtualFirst::VirtualFirst(int) and VirtualSecond::VirtualSecond(int)
+ // the constructor delegation to Left1::Left1(int) will be
+ // ignored.
+ }
+};
+
+void fVirtualDiamondInheritanceTest2() {
+ VirtualDiamondInheritanceTest2();
+}
+
+struct VirtualBase3 {
+ int x; // expected-note{{uninitialized field 'this->x'}}
+ VirtualBase3() = default;
+ VirtualBase3(int) : x(66) {}
+};
+struct VirtualFirst3 : virtual public VirtualBase3 {
+ VirtualFirst3() = default;
+ VirtualFirst3(int) : VirtualBase3(int{}) {}
+ VirtualFirst3(int, int) { x = 67; }
+};
+struct VirtualSecond3 : virtual public VirtualBase3 {
+ VirtualSecond3() = default;
+ VirtualSecond3(int) : VirtualBase3(int{}) {}
+ VirtualSecond3(int, int) { x = 68; }
+};
+
+class VirtualDiamondInheritanceTest3 : public VirtualFirst3, public VirtualSecond3 {
+
+public:
+ VirtualDiamondInheritanceTest3() // expected-warning{{1 uninitialized field}}
+ : VirtualFirst3(int{}) {}
+};
+
+void fVirtualDiamondInheritanceTest3() {
+ VirtualDiamondInheritanceTest3();
+}
diff --git a/test/Analysis/cxx-uninitialized-object-notes-as-warnings.cpp b/test/Analysis/cxx-uninitialized-object-notes-as-warnings.cpp
new file mode 100644
index 000000000000..a49507a1aa5d
--- /dev/null
+++ b/test/Analysis/cxx-uninitialized-object-notes-as-warnings.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject -analyzer-config alpha.cplusplus.UninitializedObject:NotesAsWarnings=true -std=c++11 -verify %s
+
+class NotesAsWarningsTest {
+ int a;
+ int b;
+ int dontGetFilteredByNonPedanticMode = 0;
+
+public:
+ NotesAsWarningsTest() {} // expected-warning{{uninitialized field 'this->a'}}
+ // expected-warning@-1{{uninitialized field 'this->b'}}
+};
+
+void fNotesAsWarningsTest() {
+ NotesAsWarningsTest();
+}
diff --git a/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp b/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp
new file mode 100644
index 000000000000..1507098c5e75
--- /dev/null
+++ b/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp
@@ -0,0 +1,695 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject -analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true -std=c++11 -DPEDANTIC -verify %s
+
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject -std=c++11 -verify %s
+
+//===----------------------------------------------------------------------===//
+// Concrete location tests.
+//===----------------------------------------------------------------------===//
+
+struct ConcreteIntLocTest {
+ int *ptr;
+
+ ConcreteIntLocTest() : ptr(reinterpret_cast<int *>(0xDEADBEEF)) {}
+};
+
+void fConcreteIntLocTest() {
+ ConcreteIntLocTest();
+}
+
+//===----------------------------------------------------------------------===//
+// Null pointer tests.
+//===----------------------------------------------------------------------===//
+
+class NullPtrTest {
+ struct RecordType {
+ int x;
+ int y;
+ };
+
+ float *fptr = nullptr;
+ int *ptr;
+ RecordType *recPtr;
+
+public:
+ NullPtrTest() : ptr(nullptr), recPtr(nullptr) {
+ // All good!
+ }
+};
+
+void fNullPtrTest() {
+ NullPtrTest();
+}
+
+//===----------------------------------------------------------------------===//
+// Heap pointer tests.
+//===----------------------------------------------------------------------===//
+
+class HeapPointerTest1 {
+ struct RecordType {
+ // TODO: we'd expect the note: {{uninitialized field 'this->recPtr->y'}}
+ int x; // no-note
+ // TODO: we'd expect the note: {{uninitialized field 'this->recPtr->y'}}
+ int y; // no-note
+ };
+ // TODO: we'd expect the note: {{uninitialized pointee 'this->fptr'}}
+ float *fptr = new float; // no-note
+ // TODO: we'd expect the note: {{uninitialized pointee 'this->ptr'}}
+ int *ptr; // no-note
+ RecordType *recPtr;
+
+public:
+ // TODO: we'd expect the warning: {{4 uninitialized fields}}
+ HeapPointerTest1() : ptr(new int), recPtr(new RecordType) { // no-note
+ }
+};
+
+void fHeapPointerTest1() {
+ HeapPointerTest1();
+}
+
+class HeapPointerTest2 {
+ struct RecordType {
+ int x;
+ int y;
+ };
+
+ float *fptr = new float(); // initializes to 0
+ int *ptr;
+ RecordType *recPtr;
+
+public:
+ HeapPointerTest2() : ptr(new int{25}), recPtr(new RecordType{26, 27}) {
+ // All good!
+ }
+};
+
+void fHeapPointerTest2() {
+ HeapPointerTest2();
+}
+
+//===----------------------------------------------------------------------===//
+// Stack pointer tests.
+//===----------------------------------------------------------------------===//
+
+class StackPointerTest1 {
+public:
+ struct RecordType {
+ int x;
+ int y;
+ };
+
+private:
+ int *ptr;
+ RecordType *recPtr;
+
+public:
+ StackPointerTest1(int *_ptr, StackPointerTest1::RecordType *_recPtr) : ptr(_ptr), recPtr(_recPtr) {
+ // All good!
+ }
+};
+
+void fStackPointerTest1() {
+ int ok_a = 28;
+ StackPointerTest1::RecordType ok_rec{29, 30};
+ StackPointerTest1(&ok_a, &ok_rec); // 'a', 'rec.x', 'rec.y' uninitialized
+}
+
+#ifdef PEDANTIC
+class StackPointerTest2 {
+public:
+ struct RecordType {
+ int x; // expected-note{{uninitialized field 'this->recPtr->x'}}
+ int y; // expected-note{{uninitialized field 'this->recPtr->y'}}
+ };
+
+private:
+ int *ptr; // expected-note{{uninitialized pointee 'this->ptr'}}
+ RecordType *recPtr;
+
+public:
+ StackPointerTest2(int *_ptr, RecordType *_recPtr) : ptr(_ptr), recPtr(_recPtr) { // expected-warning{{3 uninitialized fields}}
+ }
+};
+
+void fStackPointerTest2() {
+ int a;
+ StackPointerTest2::RecordType rec;
+ StackPointerTest2(&a, &rec); // 'a', 'rec.x', 'rec.y' uninitialized
+}
+#else
+class StackPointerTest2 {
+public:
+ struct RecordType {
+ int x;
+ int y;
+ };
+
+private:
+ int *ptr;
+ RecordType *recPtr;
+
+public:
+ StackPointerTest2(int *_ptr, RecordType *_recPtr) : ptr(_ptr), recPtr(_recPtr) {
+ }
+};
+
+void fStackPointerTest2() {
+ int a;
+ StackPointerTest2::RecordType rec;
+ StackPointerTest2(&a, &rec); // 'a', 'rec.x', 'rec.y' uninitialized
+}
+#endif // PEDANTIC
+
+class UninitPointerTest {
+ struct RecordType {
+ int x;
+ int y;
+ };
+
+ int *ptr; // expected-note{{uninitialized pointer 'this->ptr'}}
+ RecordType *recPtr;
+
+public:
+ UninitPointerTest() : recPtr(new RecordType{13, 13}) { // expected-warning{{1 uninitialized field}}
+ }
+};
+
+void fUninitPointerTest() {
+ UninitPointerTest();
+}
+
+struct CharPointerTest {
+ const char *str;
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ CharPointerTest() : str("") {}
+};
+
+void fCharPointerTest() {
+ CharPointerTest();
+}
+
+struct CyclicPointerTest {
+ int *ptr;
+ CyclicPointerTest() : ptr(reinterpret_cast<int*>(&ptr)) {}
+};
+
+void fCyclicPointerTest() {
+ CyclicPointerTest();
+}
+
+//===----------------------------------------------------------------------===//
+// Void pointer tests.
+//===----------------------------------------------------------------------===//
+
+// Void pointer tests are mainly no-crash tests.
+
+void *malloc(int size);
+
+class VoidPointerTest1 {
+ void *vptr;
+
+public:
+ VoidPointerTest1(void *vptr, char) : vptr(vptr) {
+ // All good!
+ }
+};
+
+void fVoidPointerTest1() {
+ void *vptr = malloc(sizeof(int));
+ VoidPointerTest1(vptr, char());
+}
+
+class VoidPointerTest2 {
+ void **vpptr;
+
+public:
+ VoidPointerTest2(void **vpptr, char) : vpptr(vpptr) {
+ // All good!
+ }
+};
+
+void fVoidPointerTest2() {
+ void *vptr = malloc(sizeof(int));
+ VoidPointerTest2(&vptr, char());
+}
+
+class VoidPointerRRefTest1 {
+ void *&&vptrrref; // expected-note {{here}}
+
+public:
+ VoidPointerRRefTest1(void *vptr, char) : vptrrref(static_cast<void *&&>(vptr)) { // expected-warning {{binding reference member 'vptrrref' to stack allocated parameter 'vptr'}}
+ // All good!
+ }
+};
+
+void fVoidPointerRRefTest1() {
+ void *vptr = malloc(sizeof(int));
+ VoidPointerRRefTest1(vptr, char());
+}
+
+class VoidPointerRRefTest2 {
+ void **&&vpptrrref; // expected-note {{here}}
+
+public:
+ VoidPointerRRefTest2(void **vptr, char) : vpptrrref(static_cast<void **&&>(vptr)) { // expected-warning {{binding reference member 'vpptrrref' to stack allocated parameter 'vptr'}}
+ // All good!
+ }
+};
+
+void fVoidPointerRRefTest2() {
+ void *vptr = malloc(sizeof(int));
+ VoidPointerRRefTest2(&vptr, char());
+}
+
+class VoidPointerLRefTest {
+ void *&vptrrref; // expected-note {{here}}
+
+public:
+ VoidPointerLRefTest(void *vptr, char) : vptrrref(static_cast<void *&>(vptr)) { // expected-warning {{binding reference member 'vptrrref' to stack allocated parameter 'vptr'}}
+ // All good!
+ }
+};
+
+void fVoidPointerLRefTest() {
+ void *vptr = malloc(sizeof(int));
+ VoidPointerLRefTest(vptr, char());
+}
+
+struct CyclicVoidPointerTest {
+ void *vptr; // no-crash
+
+ CyclicVoidPointerTest() : vptr(&vptr) {}
+
+};
+
+void fCyclicVoidPointerTest() {
+ CyclicVoidPointerTest();
+}
+
+//===----------------------------------------------------------------------===//
+// Multipointer tests.
+//===----------------------------------------------------------------------===//
+
+#ifdef PEDANTIC
+class MultiPointerTest1 {
+public:
+ struct RecordType {
+ int x;
+ int y;
+ };
+
+private:
+ RecordType **mptr; // expected-note{{uninitialized pointee 'this->mptr'}}
+
+public:
+ MultiPointerTest1(RecordType **p, int) : mptr(p) { // expected-warning{{1 uninitialized field}}
+ }
+};
+
+void fMultiPointerTest1() {
+ MultiPointerTest1::RecordType *p1;
+ MultiPointerTest1::RecordType **mptr = &p1;
+ MultiPointerTest1(mptr, int()); // '*mptr' uninitialized
+}
+#else
+class MultiPointerTest1 {
+public:
+ struct RecordType {
+ int x;
+ int y;
+ };
+
+private:
+ RecordType **mptr;
+
+public:
+ MultiPointerTest1(RecordType **p, int) : mptr(p) {}
+};
+
+void fMultiPointerTest1() {
+ MultiPointerTest1::RecordType *p1;
+ MultiPointerTest1::RecordType **mptr = &p1;
+ MultiPointerTest1(mptr, int()); // '*mptr' uninitialized
+}
+#endif // PEDANTIC
+
+#ifdef PEDANTIC
+class MultiPointerTest2 {
+public:
+ struct RecordType {
+ int x; // expected-note{{uninitialized field 'this->mptr->x'}}
+ int y; // expected-note{{uninitialized field 'this->mptr->y'}}
+ };
+
+private:
+ RecordType **mptr;
+
+public:
+ MultiPointerTest2(RecordType **p, int) : mptr(p) { // expected-warning{{2 uninitialized fields}}
+ }
+};
+
+void fMultiPointerTest2() {
+ MultiPointerTest2::RecordType i;
+ MultiPointerTest2::RecordType *p1 = &i;
+ MultiPointerTest2::RecordType **mptr = &p1;
+ MultiPointerTest2(mptr, int()); // '**mptr' uninitialized
+}
+#else
+class MultiPointerTest2 {
+public:
+ struct RecordType {
+ int x;
+ int y;
+ };
+
+private:
+ RecordType **mptr;
+
+public:
+ MultiPointerTest2(RecordType **p, int) : mptr(p) {
+ }
+};
+
+void fMultiPointerTest2() {
+ MultiPointerTest2::RecordType i;
+ MultiPointerTest2::RecordType *p1 = &i;
+ MultiPointerTest2::RecordType **mptr = &p1;
+ MultiPointerTest2(mptr, int()); // '**mptr' uninitialized
+}
+#endif // PEDANTIC
+
+class MultiPointerTest3 {
+public:
+ struct RecordType {
+ int x;
+ int y;
+ };
+
+private:
+ RecordType **mptr;
+
+public:
+ MultiPointerTest3(RecordType **p, int) : mptr(p) {
+ // All good!
+ }
+};
+
+void fMultiPointerTest3() {
+ MultiPointerTest3::RecordType i{31, 32};
+ MultiPointerTest3::RecordType *p1 = &i;
+ MultiPointerTest3::RecordType **mptr = &p1;
+ MultiPointerTest3(mptr, int()); // '**mptr' uninitialized
+}
+
+//===----------------------------------------------------------------------===//
+// Member pointer tests.
+//===----------------------------------------------------------------------===//
+
+struct UsefulFunctions {
+ int a, b;
+
+ void print() {}
+ void dump() {}
+};
+
+#ifdef PEDANTIC
+struct PointerToMemberFunctionTest1 {
+ void (UsefulFunctions::*f)(void); // expected-note{{uninitialized field 'this->f'}}
+ PointerToMemberFunctionTest1() {}
+};
+
+void fPointerToMemberFunctionTest1() {
+ PointerToMemberFunctionTest1(); // expected-warning{{1 uninitialized field}}
+}
+
+struct PointerToMemberFunctionTest2 {
+ void (UsefulFunctions::*f)(void);
+ PointerToMemberFunctionTest2(void (UsefulFunctions::*f)(void)) : f(f) {
+ // All good!
+ }
+};
+
+void fPointerToMemberFunctionTest2() {
+ void (UsefulFunctions::*f)(void) = &UsefulFunctions::print;
+ PointerToMemberFunctionTest2 a(f);
+}
+
+struct MultiPointerToMemberFunctionTest1 {
+ void (UsefulFunctions::**f)(void); // expected-note{{uninitialized pointer 'this->f'}}
+ MultiPointerToMemberFunctionTest1() {}
+};
+
+void fMultiPointerToMemberFunctionTest1() {
+ MultiPointerToMemberFunctionTest1(); // expected-warning{{1 uninitialized field}}
+}
+
+struct MultiPointerToMemberFunctionTest2 {
+ void (UsefulFunctions::**f)(void);
+ MultiPointerToMemberFunctionTest2(void (UsefulFunctions::**f)(void)) : f(f) {
+ // All good!
+ }
+};
+
+void fMultiPointerToMemberFunctionTest2() {
+ void (UsefulFunctions::*f)(void) = &UsefulFunctions::print;
+ MultiPointerToMemberFunctionTest2 a(&f);
+}
+
+struct PointerToMemberDataTest1 {
+ int UsefulFunctions::*d; // expected-note{{uninitialized field 'this->d'}}
+ PointerToMemberDataTest1() {}
+};
+
+void fPointerToMemberDataTest1() {
+ PointerToMemberDataTest1(); // expected-warning{{1 uninitialized field}}
+}
+
+struct PointerToMemberDataTest2 {
+ int UsefulFunctions::*d;
+ PointerToMemberDataTest2(int UsefulFunctions::*d) : d(d) {
+ // All good!
+ }
+};
+
+void fPointerToMemberDataTest2() {
+ int UsefulFunctions::*d = &UsefulFunctions::a;
+ PointerToMemberDataTest2 a(d);
+}
+
+struct MultiPointerToMemberDataTest1 {
+ int UsefulFunctions::**d; // expected-note{{uninitialized pointer 'this->d'}}
+ MultiPointerToMemberDataTest1() {}
+};
+
+void fMultiPointerToMemberDataTest1() {
+ MultiPointerToMemberDataTest1(); // expected-warning{{1 uninitialized field}}
+}
+
+struct MultiPointerToMemberDataTest2 {
+ int UsefulFunctions::**d;
+ MultiPointerToMemberDataTest2(int UsefulFunctions::**d) : d(d) {
+ // All good!
+ }
+};
+
+void fMultiPointerToMemberDataTest2() {
+ int UsefulFunctions::*d = &UsefulFunctions::a;
+ MultiPointerToMemberDataTest2 a(&d);
+}
+#endif // PEDANTIC
+
+//===----------------------------------------------------------------------===//
+// Tests for list-like records.
+//===----------------------------------------------------------------------===//
+
+class ListTest1 {
+public:
+ struct Node {
+ Node *next = nullptr; // no crash
+ int i;
+ };
+
+private:
+ Node *head = nullptr;
+
+public:
+ ListTest1() {
+ // All good!
+ }
+};
+
+void fListTest1() {
+ ListTest1();
+}
+
+class ListTest2 {
+public:
+ struct Node {
+ Node *next = nullptr;
+ int i; // expected-note{{uninitialized field 'this->head->i'}}
+ };
+
+private:
+ Node *head = nullptr;
+
+public:
+ ListTest2(Node *node, int) : head(node) { // expected-warning{{1 uninitialized field}}
+ }
+};
+
+void fListTest2() {
+ ListTest2::Node n;
+ ListTest2(&n, int());
+}
+
+class CyclicList {
+public:
+ struct Node {
+ Node *next = nullptr;
+ int i; // expected-note{{uninitialized field 'this->head->i'}}
+ };
+
+private:
+ Node *head = nullptr;
+
+public:
+ CyclicList(Node *node, int) : head(node) { // expected-warning{{1 uninitialized field}}
+ }
+};
+
+void fCyclicList() {
+ /*
+ n3
+ / \
+ this -- n1 -- n2
+ */
+
+ CyclicList::Node n1;
+ CyclicList::Node n2;
+ n2.next = &n1;
+ n2.i = 50;
+ CyclicList::Node n3;
+ n3.next = &n2;
+ n3.i = 50;
+ n1.next = &n3;
+ // note that n1.i is uninitialized
+ CyclicList(&n1, int());
+}
+
+//===----------------------------------------------------------------------===//
+// Tests for classes containing references.
+//===----------------------------------------------------------------------===//
+
+class ReferenceTest1 {
+public:
+ struct RecordType {
+ int x;
+ int y;
+ };
+
+private:
+ RecordType &lref;
+ RecordType &&rref;
+
+public:
+ ReferenceTest1(RecordType &lref, RecordType &rref) : lref(lref), rref(static_cast<RecordType &&>(rref)) {
+ // All good!
+ }
+};
+
+void fReferenceTest1() {
+ ReferenceTest1::RecordType d{33, 34};
+ ReferenceTest1(d, d);
+}
+
+#ifdef PEDANTIC
+class ReferenceTest2 {
+public:
+ struct RecordType {
+ int x; // expected-note{{uninitialized field 'this->lref.x'}}
+ int y; // expected-note{{uninitialized field 'this->lref.y'}}
+ };
+
+private:
+ RecordType &lref;
+ RecordType &&rref;
+
+public:
+ ReferenceTest2(RecordType &lref, RecordType &rref)
+ : lref(lref), rref(static_cast<RecordType &&>(rref)) { // expected-warning{{2 uninitialized fields}}
+ }
+};
+
+void fReferenceTest2() {
+ ReferenceTest2::RecordType c;
+ ReferenceTest2(c, c);
+}
+#else
+class ReferenceTest2 {
+public:
+ struct RecordType {
+ int x;
+ int y;
+ };
+
+private:
+ RecordType &lref;
+ RecordType &&rref;
+
+public:
+ ReferenceTest2(RecordType &lref, RecordType &rref)
+ : lref(lref), rref(static_cast<RecordType &&>(rref)) {
+ }
+};
+
+void fReferenceTest2() {
+ ReferenceTest2::RecordType c;
+ ReferenceTest2(c, c);
+}
+#endif // PEDANTIC
+
+class ReferenceTest3 {
+public:
+ struct RecordType {
+ int x; // expected-note{{uninitialized field 'this->lref.x'}}
+ int y; // expected-note{{uninitialized field 'this->lref.y'}}
+ };
+
+private:
+ RecordType &lref;
+ RecordType &&rref;
+
+public:
+ ReferenceTest3(RecordType &lref, RecordType &rref)
+ : lref(lref), rref(static_cast<RecordType &&>(rref)) { // expected-warning{{2 uninitialized fields}}
+ }
+};
+
+void fReferenceTest3() {
+ ReferenceTest3::RecordType c, d{35, 36};
+ ReferenceTest3(c, d);
+}
+
+class ReferenceTest4 {
+public:
+ struct RecordType {
+ int x; // expected-note{{uninitialized field 'this->rref.x'}}
+ int y; // expected-note{{uninitialized field 'this->rref.y'}}
+ };
+
+private:
+ RecordType &lref;
+ RecordType &&rref;
+
+public:
+ ReferenceTest4(RecordType &lref, RecordType &rref)
+ : lref(lref), rref(static_cast<RecordType &&>(rref)) { // expected-warning{{2 uninitialized fields}}
+ }
+};
+
+void fReferenceTest5() {
+ ReferenceTest4::RecordType c, d{37, 38};
+ ReferenceTest4(d, c);
+}
diff --git a/test/Analysis/cxx-uninitialized-object.cpp b/test/Analysis/cxx-uninitialized-object.cpp
new file mode 100644
index 000000000000..39d4a7f80183
--- /dev/null
+++ b/test/Analysis/cxx-uninitialized-object.cpp
@@ -0,0 +1,1103 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject -analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true -std=c++11 -DPEDANTIC -verify %s
+
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject -std=c++11 -verify %s
+
+//===----------------------------------------------------------------------===//
+// Default constructor test.
+//===----------------------------------------------------------------------===//
+
+class CompilerGeneratedConstructorTest {
+ int a, b, c, d, e, f, g, h, i, j;
+
+public:
+ CompilerGeneratedConstructorTest() = default;
+};
+
+void fCompilerGeneratedConstructorTest() {
+ CompilerGeneratedConstructorTest();
+}
+
+#ifdef PEDANTIC
+class DefaultConstructorTest {
+ int a; // expected-note{{uninitialized field 'this->a'}}
+
+public:
+ DefaultConstructorTest();
+};
+
+DefaultConstructorTest::DefaultConstructorTest() = default;
+
+void fDefaultConstructorTest() {
+ DefaultConstructorTest(); // expected-warning{{1 uninitialized field}}
+}
+#else
+class DefaultConstructorTest {
+ int a;
+
+public:
+ DefaultConstructorTest();
+};
+
+DefaultConstructorTest::DefaultConstructorTest() = default;
+
+void fDefaultConstructorTest() {
+ DefaultConstructorTest();
+}
+#endif // PEDANTIC
+
+//===----------------------------------------------------------------------===//
+// Initializer list test.
+//===----------------------------------------------------------------------===//
+
+class InitListTest1 {
+ int a;
+ int b;
+
+public:
+ InitListTest1()
+ : a(1),
+ b(2) {
+ // All good!
+ }
+};
+
+void fInitListTest1() {
+ InitListTest1();
+}
+
+class InitListTest2 {
+ int a;
+ int b; // expected-note{{uninitialized field 'this->b'}}
+
+public:
+ InitListTest2()
+ : a(3) {} // expected-warning{{1 uninitialized field}}
+};
+
+void fInitListTest2() {
+ InitListTest2();
+}
+
+class InitListTest3 {
+ int a; // expected-note{{uninitialized field 'this->a'}}
+ int b;
+
+public:
+ InitListTest3()
+ : b(4) {} // expected-warning{{1 uninitialized field}}
+};
+
+void fInitListTest3() {
+ InitListTest3();
+}
+
+//===----------------------------------------------------------------------===//
+// Constructor body test.
+//===----------------------------------------------------------------------===//
+
+class CtorBodyTest1 {
+ int a, b;
+
+public:
+ CtorBodyTest1() {
+ a = 5;
+ b = 6;
+ // All good!
+ }
+};
+
+void fCtorBodyTest1() {
+ CtorBodyTest1();
+}
+
+class CtorBodyTest2 {
+ int a;
+ int b; // expected-note{{uninitialized field 'this->b'}}
+
+public:
+ CtorBodyTest2() {
+ a = 7; // expected-warning{{1 uninitialized field}}
+ }
+};
+
+void fCtorBodyTest2() {
+ CtorBodyTest2();
+}
+
+class CtorBodyTest3 {
+ int a; // expected-note{{uninitialized field 'this->a'}}
+ int b;
+
+public:
+ CtorBodyTest3() {
+ b = 8; // expected-warning{{1 uninitialized field}}
+ }
+};
+
+void fCtorBodyTest3() {
+ CtorBodyTest3();
+}
+
+#ifdef PEDANTIC
+class CtorBodyTest4 {
+ int a; // expected-note{{uninitialized field 'this->a'}}
+ int b; // expected-note{{uninitialized field 'this->b'}}
+
+public:
+ CtorBodyTest4() {}
+};
+
+void fCtorBodyTest4() {
+ CtorBodyTest4(); // expected-warning{{2 uninitialized fields}}
+}
+#else
+class CtorBodyTest4 {
+ int a;
+ int b;
+
+public:
+ CtorBodyTest4() {}
+};
+
+void fCtorBodyTest4() {
+ CtorBodyTest4();
+}
+#endif
+
+//===----------------------------------------------------------------------===//
+// Constructor delegation test.
+//===----------------------------------------------------------------------===//
+
+class CtorDelegationTest1 {
+ int a;
+ int b;
+
+public:
+ CtorDelegationTest1(int)
+ : a(9) {
+ // leaves 'b' unintialized, but we'll never check this function
+ }
+
+ CtorDelegationTest1()
+ : CtorDelegationTest1(int{}) { // Initializing 'a'
+ b = 10;
+ // All good!
+ }
+};
+
+void fCtorDelegationTest1() {
+ CtorDelegationTest1();
+}
+
+class CtorDelegationTest2 {
+ int a; // expected-note{{uninitialized field 'this->a'}}
+ int b;
+
+public:
+ CtorDelegationTest2(int)
+ : b(11) {
+ // leaves 'a' unintialized, but we'll never check this function
+ }
+
+ CtorDelegationTest2()
+ : CtorDelegationTest2(int{}) { // expected-warning{{1 uninitialized field}}
+ }
+};
+
+void fCtorDelegationTest2() {
+ CtorDelegationTest2();
+}
+
+//===----------------------------------------------------------------------===//
+// Tests for classes containing records.
+//===----------------------------------------------------------------------===//
+
+class ContainsRecordTest1 {
+ struct RecordType {
+ int x;
+ int y;
+ } rec;
+ int c, d;
+
+public:
+ ContainsRecordTest1()
+ : rec({12, 13}),
+ c(14),
+ d(15) {
+ // All good!
+ }
+};
+
+void fContainsRecordTest1() {
+ ContainsRecordTest1();
+}
+
+class ContainsRecordTest2 {
+ struct RecordType {
+ int x;
+ int y; // expected-note{{uninitialized field 'this->rec.y'}}
+ } rec;
+ int c, d;
+
+public:
+ ContainsRecordTest2()
+ : c(16),
+ d(17) {
+ rec.x = 18; // expected-warning{{1 uninitialized field}}
+ }
+};
+
+void fContainsRecordTest2() {
+ ContainsRecordTest2();
+}
+
+class ContainsRecordTest3 {
+ struct RecordType {
+ int x; // expected-note{{uninitialized field 'this->rec.x'}}
+ int y; // expected-note{{uninitialized field 'this->rec.y'}}
+ } rec;
+ int c, d;
+
+public:
+ ContainsRecordTest3()
+ : c(19),
+ d(20) { // expected-warning{{2 uninitialized fields}}
+ }
+};
+
+void fContainsRecordTest3() {
+ ContainsRecordTest3();
+}
+
+class ContainsRecordTest4 {
+ struct RecordType {
+ int x; // expected-note{{uninitialized field 'this->rec.x'}}
+ int y; // expected-note{{uninitialized field 'this->rec.y'}}
+ } rec;
+ int c, d; // expected-note{{uninitialized field 'this->d'}}
+
+public:
+ ContainsRecordTest4()
+ : c(19) { // expected-warning{{3 uninitialized fields}}
+ }
+};
+
+void fContainsRecordTest4() {
+ ContainsRecordTest4();
+}
+
+//===----------------------------------------------------------------------===//
+// Tests for template classes.
+//===----------------------------------------------------------------------===//
+
+template <class T>
+class IntTemplateClassTest1 {
+ T t;
+ int b;
+
+public:
+ IntTemplateClassTest1(T i) {
+ b = 21;
+ t = i;
+ // All good!
+ }
+};
+
+void fIntTemplateClassTest1() {
+ IntTemplateClassTest1<int>(22);
+}
+
+template <class T>
+class IntTemplateClassTest2 {
+ T t; // expected-note{{uninitialized field 'this->t'}}
+ int b;
+
+public:
+ IntTemplateClassTest2() {
+ b = 23; // expected-warning{{1 uninitialized field}}
+ }
+};
+
+void fIntTemplateClassTest2() {
+ IntTemplateClassTest2<int>();
+}
+
+struct Record {
+ int x; // expected-note{{uninitialized field 'this->t.x'}}
+ int y; // expected-note{{uninitialized field 'this->t.y'}}
+};
+
+template <class T>
+class RecordTemplateClassTest {
+ T t;
+ int b;
+
+public:
+ RecordTemplateClassTest() {
+ b = 24; // expected-warning{{2 uninitialized fields}}
+ }
+};
+
+void fRecordTemplateClassTest() {
+ RecordTemplateClassTest<Record>();
+}
+
+//===----------------------------------------------------------------------===//
+// Tests involving functions with unknown implementations.
+//===----------------------------------------------------------------------===//
+
+template <class T>
+void mayInitialize(T &);
+
+template <class T>
+void wontInitialize(const T &);
+
+class PassingToUnknownFunctionTest1 {
+ int a, b;
+
+public:
+ PassingToUnknownFunctionTest1() {
+ mayInitialize(a);
+ mayInitialize(b);
+ // All good!
+ }
+
+ PassingToUnknownFunctionTest1(int) {
+ mayInitialize(a);
+ // All good!
+ }
+
+ PassingToUnknownFunctionTest1(int, int) {
+ mayInitialize(*this);
+ // All good!
+ }
+};
+
+void fPassingToUnknownFunctionTest1() {
+ PassingToUnknownFunctionTest1();
+ PassingToUnknownFunctionTest1(int());
+ PassingToUnknownFunctionTest1(int(), int());
+}
+
+class PassingToUnknownFunctionTest2 {
+ int a; // expected-note{{uninitialized field 'this->a'}}
+ int b;
+
+public:
+ PassingToUnknownFunctionTest2() {
+ wontInitialize(a);
+ b = 4; // expected-warning{{1 uninitialized field}}
+ }
+};
+
+void fPassingToUnknownFunctionTest2() {
+ PassingToUnknownFunctionTest2();
+}
+
+//===----------------------------------------------------------------------===//
+// Tests for classes containing unions.
+//===----------------------------------------------------------------------===//
+
+// FIXME: As of writing this checker, there is no good support for union types
+// in the Static Analyzer. Here is non-exhaustive list of cases.
+// Note that the rules for unions are different in C and C++.
+// http://lists.llvm.org/pipermail/cfe-dev/2017-March/052910.html
+
+class ContainsSimpleUnionTest1 {
+ union SimpleUnion {
+ float uf;
+ int ui;
+ char uc;
+ } u;
+
+public:
+ ContainsSimpleUnionTest1() {
+ u.uf = 3.14;
+ // All good!
+ }
+};
+
+void fContainsSimpleUnionTest1() {
+ ContainsSimpleUnionTest1();
+}
+
+class ContainsSimpleUnionTest2 {
+ union SimpleUnion {
+ float uf;
+ int ui;
+ char uc;
+ // TODO: we'd expect the note: {{uninitialized field 'this->u'}}
+ } u; // no-note
+
+public:
+ ContainsSimpleUnionTest2() {}
+};
+
+void fContainsSimpleUnionTest2() {
+ // TODO: we'd expect the warning: {{1 uninitialized field}}
+ ContainsSimpleUnionTest2(); // no-warning
+}
+
+class UnionPointerTest1 {
+public:
+ union SimpleUnion {
+ float uf;
+ int ui;
+ char uc;
+ };
+
+private:
+ SimpleUnion *uptr;
+
+public:
+ UnionPointerTest1(SimpleUnion *uptr, int) : uptr(uptr) {
+ // All good!
+ }
+};
+
+void fUnionPointerTest1() {
+ UnionPointerTest1::SimpleUnion u;
+ u.uf = 41;
+ UnionPointerTest1(&u, int());
+}
+
+class UnionPointerTest2 {
+public:
+ union SimpleUnion {
+ float uf;
+ int ui;
+ char uc;
+ };
+
+private:
+ // TODO: we'd expect the note: {{uninitialized field 'this->uptr'}}
+ SimpleUnion *uptr; // no-note
+
+public:
+ UnionPointerTest2(SimpleUnion *uptr, char) : uptr(uptr) {}
+};
+
+void fUnionPointerTest2() {
+ UnionPointerTest2::SimpleUnion u;
+ // TODO: we'd expect the warning: {{1 uninitialized field}}
+ UnionPointerTest2(&u, int()); // no-warning
+}
+
+class ContainsUnionWithRecordTest1 {
+ union UnionWithRecord {
+ struct RecordType {
+ int x;
+ int y;
+ } us;
+ double ud;
+ long ul;
+
+ UnionWithRecord(){};
+ } u;
+
+public:
+ ContainsUnionWithRecordTest1() {
+ u.ud = 3.14;
+ // All good!
+ }
+};
+
+void fContainsUnionWithRecordTest1() {
+ ContainsUnionWithRecordTest1();
+}
+
+class ContainsUnionWithRecordTest2 {
+ union UnionWithRecord {
+ struct RecordType {
+ int x;
+ int y;
+ } us;
+ double ud;
+ long ul;
+
+ UnionWithRecord(){};
+ } u;
+
+public:
+ ContainsUnionWithRecordTest2() {
+ u.us = UnionWithRecord::RecordType{42, 43};
+ // All good!
+ }
+};
+
+void fContainsUnionWithRecordTest2() {
+ ContainsUnionWithRecordTest1();
+}
+
+class ContainsUnionWithRecordTest3 {
+ union UnionWithRecord {
+ struct RecordType {
+ int x;
+ int y;
+ } us;
+ double ud;
+ long ul;
+
+ UnionWithRecord(){};
+ // TODO: we'd expect the note: {{uninitialized field 'this->u'}}
+ } u; // no-note
+
+public:
+ ContainsUnionWithRecordTest3() {
+ UnionWithRecord::RecordType rec;
+ rec.x = 44;
+ // TODO: we'd expect the warning: {{1 uninitialized field}}
+ u.us = rec; // no-warning
+ }
+};
+
+void fContainsUnionWithRecordTest3() {
+ ContainsUnionWithRecordTest3();
+}
+
+class ContainsUnionWithSimpleUnionTest1 {
+ union UnionWithSimpleUnion {
+ union SimpleUnion {
+ float uf;
+ int ui;
+ char uc;
+ } usu;
+ long ul;
+ unsigned uu;
+ } u;
+
+public:
+ ContainsUnionWithSimpleUnionTest1() {
+ u.usu.ui = 5;
+ // All good!
+ }
+};
+
+void fContainsUnionWithSimpleUnionTest1() {
+ ContainsUnionWithSimpleUnionTest1();
+}
+
+class ContainsUnionWithSimpleUnionTest2 {
+ union UnionWithSimpleUnion {
+ union SimpleUnion {
+ float uf;
+ int ui;
+ char uc;
+ } usu;
+ long ul;
+ unsigned uu;
+ // TODO: we'd expect the note: {{uninitialized field 'this->u'}}
+ } u; // no-note
+
+public:
+ ContainsUnionWithSimpleUnionTest2() {}
+};
+
+void fContainsUnionWithSimpleUnionTest2() {
+ // TODO: we'd expect the warning: {{1 uninitialized field}}
+ ContainsUnionWithSimpleUnionTest2(); // no-warning
+}
+
+//===----------------------------------------------------------------------===//
+// Zero initialization tests.
+//===----------------------------------------------------------------------===//
+
+struct GlobalVariableTest {
+ int i;
+
+ GlobalVariableTest() {}
+};
+
+GlobalVariableTest gvt; // no-warning
+
+//===----------------------------------------------------------------------===//
+// Copy and move constructor tests.
+//===----------------------------------------------------------------------===//
+
+template <class T>
+void funcToSquelchCompilerWarnings(const T &t);
+
+#ifdef PEDANTIC
+struct CopyConstructorTest {
+ int i; // expected-note{{uninitialized field 'this->i'}}
+
+ CopyConstructorTest() : i(1337) {}
+ CopyConstructorTest(const CopyConstructorTest &other) {}
+};
+
+void fCopyConstructorTest() {
+ CopyConstructorTest cct;
+ CopyConstructorTest copy = cct; // expected-warning{{1 uninitialized field}}
+ funcToSquelchCompilerWarnings(copy);
+}
+#else
+struct CopyConstructorTest {
+ int i;
+
+ CopyConstructorTest() : i(1337) {}
+ CopyConstructorTest(const CopyConstructorTest &other) {}
+};
+
+void fCopyConstructorTest() {
+ CopyConstructorTest cct;
+ CopyConstructorTest copy = cct;
+ funcToSquelchCompilerWarnings(copy);
+}
+#endif // PEDANTIC
+
+struct MoveConstructorTest {
+ // TODO: we'd expect the note: {{uninitialized field 'this->i'}}
+ int i; // no-note
+
+ MoveConstructorTest() : i(1337) {}
+ MoveConstructorTest(const CopyConstructorTest &other) = delete;
+ MoveConstructorTest(const CopyConstructorTest &&other) {}
+};
+
+void fMoveConstructorTest() {
+ MoveConstructorTest cct;
+ // TODO: we'd expect the warning: {{1 uninitialized field}}
+ MoveConstructorTest copy(static_cast<MoveConstructorTest &&>(cct)); // no-warning
+ funcToSquelchCompilerWarnings(copy);
+}
+
+//===----------------------------------------------------------------------===//
+// Array tests.
+//===----------------------------------------------------------------------===//
+
+struct IntArrayTest {
+ int arr[256];
+
+ IntArrayTest() {
+ // All good!
+ }
+};
+
+void fIntArrayTest() {
+ IntArrayTest();
+}
+
+struct RecordTypeArrayTest {
+ struct RecordType {
+ int x, y;
+ } arr[256];
+
+ RecordTypeArrayTest() {
+ // All good!
+ }
+};
+
+void fRecordTypeArrayTest() {
+ RecordTypeArrayTest();
+}
+
+template <class T>
+class CharArrayPointerTest {
+ T *t; // no-crash
+
+public:
+ CharArrayPointerTest(T *t, int) : t(t) {}
+};
+
+void fCharArrayPointerTest() {
+ char str[16] = "012345678912345";
+ CharArrayPointerTest<char[16]>(&str, int());
+}
+
+//===----------------------------------------------------------------------===//
+// Memset tests.
+//===----------------------------------------------------------------------===//
+
+struct MemsetTest1 {
+ int a, b, c;
+
+ MemsetTest1() {
+ __builtin_memset(this, 0, sizeof(decltype(*this)));
+ }
+};
+
+void fMemsetTest1() {
+ MemsetTest1();
+}
+
+struct MemsetTest2 {
+ int a;
+
+ MemsetTest2() {
+ __builtin_memset(&a, 0, sizeof(int));
+ }
+};
+
+void fMemsetTest2() {
+ MemsetTest2();
+}
+
+//===----------------------------------------------------------------------===//
+// Lambda tests.
+//===----------------------------------------------------------------------===//
+
+template <class Callable>
+struct LambdaThisTest {
+ Callable functor;
+
+ LambdaThisTest(const Callable &functor, int) : functor(functor) {
+ // All good!
+ }
+};
+
+struct HasCapturableThis {
+ void fLambdaThisTest() {
+ auto isEven = [this](int a) { return a % 2 == 0; }; // no-crash
+ LambdaThisTest<decltype(isEven)>(isEven, int());
+ }
+};
+
+template <class Callable>
+struct LambdaTest1 {
+ Callable functor;
+
+ LambdaTest1(const Callable &functor, int) : functor(functor) {
+ // All good!
+ }
+};
+
+void fLambdaTest1() {
+ auto isEven = [](int a) { return a % 2 == 0; };
+ LambdaTest1<decltype(isEven)>(isEven, int());
+}
+
+#ifdef PEDANTIC
+template <class Callable>
+struct LambdaTest2 {
+ Callable functor;
+
+ LambdaTest2(const Callable &functor, int) : functor(functor) {} // expected-warning{{1 uninitialized field}}
+};
+
+void fLambdaTest2() {
+ int b;
+ auto equals = [&b](int a) { return a == b; }; // expected-note{{uninitialized field 'this->functor.b'}}
+ LambdaTest2<decltype(equals)>(equals, int());
+}
+#else
+template <class Callable>
+struct LambdaTest2 {
+ Callable functor;
+
+ LambdaTest2(const Callable &functor, int) : functor(functor) {}
+};
+
+void fLambdaTest2() {
+ int b;
+ auto equals = [&b](int a) { return a == b; };
+ LambdaTest2<decltype(equals)>(equals, int());
+}
+#endif //PEDANTIC
+
+#ifdef PEDANTIC
+namespace LT3Detail {
+
+struct RecordType {
+ int x; // expected-note{{uninitialized field 'this->functor.rec1.x'}}
+ int y; // expected-note{{uninitialized field 'this->functor.rec1.y'}}
+};
+
+} // namespace LT3Detail
+template <class Callable>
+struct LambdaTest3 {
+ Callable functor;
+
+ LambdaTest3(const Callable &functor, int) : functor(functor) {} // expected-warning{{2 uninitialized fields}}
+};
+
+void fLambdaTest3() {
+ LT3Detail::RecordType rec1;
+ auto equals = [&rec1](LT3Detail::RecordType rec2) {
+ return rec1.x == rec2.x;
+ };
+ LambdaTest3<decltype(equals)>(equals, int());
+}
+#else
+namespace LT3Detail {
+
+struct RecordType {
+ int x;
+ int y;
+};
+
+} // namespace LT3Detail
+template <class Callable>
+struct LambdaTest3 {
+ Callable functor;
+
+ LambdaTest3(const Callable &functor, int) : functor(functor) {}
+};
+
+void fLambdaTest3() {
+ LT3Detail::RecordType rec1;
+ auto equals = [&rec1](LT3Detail::RecordType rec2) {
+ return rec1.x == rec2.x;
+ };
+ LambdaTest3<decltype(equals)>(equals, int());
+}
+#endif //PEDANTIC
+
+template <class Callable>
+struct MultipleLambdaCapturesTest1 {
+ Callable functor;
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ MultipleLambdaCapturesTest1(const Callable &functor, int) : functor(functor) {} // expected-warning{{2 uninitialized field}}
+};
+
+void fMultipleLambdaCapturesTest1() {
+ int b1, b2 = 3, b3;
+ auto equals = [&b1, &b2, &b3](int a) { return a == b1 == b2 == b3; }; // expected-note{{uninitialized field 'this->functor.b1'}}
+ // expected-note@-1{{uninitialized field 'this->functor.b3'}}
+ MultipleLambdaCapturesTest1<decltype(equals)>(equals, int());
+}
+
+template <class Callable>
+struct MultipleLambdaCapturesTest2 {
+ Callable functor;
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ MultipleLambdaCapturesTest2(const Callable &functor, int) : functor(functor) {} // expected-warning{{1 uninitialized field}}
+};
+
+void fMultipleLambdaCapturesTest2() {
+ int b1, b2 = 3, b3;
+ auto equals = [b1, &b2, &b3](int a) { return a == b1 == b2 == b3; }; // expected-note{{uninitialized field 'this->functor.b3'}}
+ MultipleLambdaCapturesTest2<decltype(equals)>(equals, int());
+}
+
+//===----------------------------------------------------------------------===//
+// System header tests.
+//===----------------------------------------------------------------------===//
+
+#include "Inputs/system-header-simulator-for-cxx-uninitialized-object.h"
+
+struct SystemHeaderTest1 {
+ RecordInSystemHeader rec; // defined in the system header simulator
+
+ SystemHeaderTest1() {
+ // All good!
+ }
+};
+
+void fSystemHeaderTest1() {
+ SystemHeaderTest1();
+}
+
+#ifdef PEDANTIC
+struct SystemHeaderTest2 {
+ struct RecordType {
+ int x; // expected-note{{uninitialized field 'this->container.t.x}}
+ int y; // expected-note{{uninitialized field 'this->container.t.y}}
+ };
+ ContainerInSystemHeader<RecordType> container;
+
+ SystemHeaderTest2(RecordType &rec, int) : container(rec) {} // expected-warning{{2 uninitialized fields}}
+};
+
+void fSystemHeaderTest2() {
+ SystemHeaderTest2::RecordType rec;
+ SystemHeaderTest2(rec, int());
+}
+#else
+struct SystemHeaderTest2 {
+ struct RecordType {
+ int x;
+ int y;
+ };
+ ContainerInSystemHeader<RecordType> container;
+
+ SystemHeaderTest2(RecordType &rec, int) : container(rec) {}
+};
+
+void fSystemHeaderTest2() {
+ SystemHeaderTest2::RecordType rec;
+ SystemHeaderTest2(rec, int());
+}
+#endif //PEDANTIC
+
+//===----------------------------------------------------------------------===//
+// Incomplete type tests.
+//===----------------------------------------------------------------------===//
+
+struct IncompleteTypeTest1 {
+ struct RecordType;
+ // no-crash
+ RecordType *recptr; // expected-note{{uninitialized pointer 'this->recptr}}
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ IncompleteTypeTest1() {} // expected-warning{{1 uninitialized field}}
+};
+
+void fIncompleteTypeTest1() {
+ IncompleteTypeTest1();
+}
+
+struct IncompleteTypeTest2 {
+ struct RecordType;
+ RecordType *recptr; // no-crash
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ RecordType *recordTypeFactory();
+
+ IncompleteTypeTest2() : recptr(recordTypeFactory()) {}
+};
+
+void fIncompleteTypeTest2() {
+ IncompleteTypeTest2();
+}
+
+struct IncompleteTypeTest3 {
+ struct RecordType;
+ RecordType &recref; // no-crash
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ RecordType &recordTypeFactory();
+
+ IncompleteTypeTest3() : recref(recordTypeFactory()) {}
+};
+
+void fIncompleteTypeTest3() {
+ IncompleteTypeTest3();
+}
+
+//===----------------------------------------------------------------------===//
+// Builtin type or enumeration type related tests.
+//===----------------------------------------------------------------------===//
+
+struct IntegralTypeTest {
+ int a; // expected-note{{uninitialized field 'this->a'}}
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ IntegralTypeTest() {} // expected-warning{{1 uninitialized field}}
+};
+
+void fIntegralTypeTest() {
+ IntegralTypeTest();
+}
+
+struct FloatingTypeTest {
+ float a; // expected-note{{uninitialized field 'this->a'}}
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ FloatingTypeTest() {} // expected-warning{{1 uninitialized field}}
+};
+
+void fFloatingTypeTest() {
+ FloatingTypeTest();
+}
+
+struct NullptrTypeTypeTest {
+ decltype(nullptr) a; // expected-note{{uninitialized field 'this->a'}}
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ NullptrTypeTypeTest() {} // expected-warning{{1 uninitialized field}}
+};
+
+void fNullptrTypeTypeTest() {
+ NullptrTypeTypeTest();
+}
+
+struct EnumTest {
+ enum Enum {
+ A,
+ B
+ } enum1; // expected-note{{uninitialized field 'this->enum1'}}
+ enum class Enum2 {
+ A,
+ B
+ } enum2; // expected-note{{uninitialized field 'this->enum2'}}
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ EnumTest() {} // expected-warning{{2 uninitialized fields}}
+};
+
+void fEnumTest() {
+ EnumTest();
+}
+
+//===----------------------------------------------------------------------===//
+// Tests for constructor calls within another cunstructor, without the two
+// records being in any relation.
+//===----------------------------------------------------------------------===//
+
+void halt() __attribute__((__noreturn__));
+void assert(int b) {
+ if (!b)
+ halt();
+}
+
+// While a singleton would make more sense as a static variable, that would zero
+// initialize all of its fields, hence the not too practical implementation.
+struct Singleton {
+ // TODO: we'd expect the note: {{uninitialized field 'this->i'}}
+ int i; // no-note
+
+ Singleton() {
+ assert(!isInstantiated);
+ // TODO: we'd expect the warning: {{1 uninitialized field}}
+ isInstantiated = true; // no-warning
+ }
+
+ ~Singleton() {
+ isInstantiated = false;
+ }
+
+ static bool isInstantiated;
+};
+
+bool Singleton::isInstantiated = false;
+
+struct SingletonTest {
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ SingletonTest() {
+ Singleton();
+ }
+};
+
+void fSingletonTest() {
+ SingletonTest();
+}
+
+//===----------------------------------------------------------------------===//
+// C++11 member initializer tests.
+//===----------------------------------------------------------------------===//
+
+struct CXX11MemberInitTest1 {
+ int a = 3;
+ int b;
+ CXX11MemberInitTest1() : b(2) {
+ // All good!
+ }
+};
+
+void fCXX11MemberInitTest1() {
+ CXX11MemberInitTest1();
+}
+
+struct CXX11MemberInitTest2 {
+ struct RecordType {
+ // TODO: we'd expect the note: {{uninitialized field 'this->rec.a'}}
+ int a; // no-note
+ // TODO: we'd expect the note: {{uninitialized field 'this->rec.b'}}
+ int b; // no-note
+
+ RecordType(int) {}
+ };
+
+ RecordType rec = RecordType(int());
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ CXX11MemberInitTest2() {}
+};
+
+void fCXX11MemberInitTest2() {
+ // TODO: we'd expect the warning: {{2 uninitializeds field}}
+ CXX11MemberInitTest2(); // no-warning
+}
diff --git a/test/Analysis/cxx17-mandatory-elision.cpp b/test/Analysis/cxx17-mandatory-elision.cpp
new file mode 100644
index 000000000000..cf77912ea6c4
--- /dev/null
+++ b/test/Analysis/cxx17-mandatory-elision.cpp
@@ -0,0 +1,304 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -std=c++11 -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -std=c++17 -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -std=c++11 -analyzer-config elide-constructors=false -DNO_ELIDE_FLAG -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -std=c++17 -analyzer-config elide-constructors=false -DNO_ELIDE_FLAG -verify %s
+
+// Copy elision always occurs in C++17, otherwise it's under
+// an on-by-default flag.
+#if __cplusplus >= 201703L
+ #define ELIDE 1
+#else
+ #ifndef NO_ELIDE_FLAG
+ #define ELIDE 1
+ #endif
+#endif
+
+void clang_analyzer_eval(bool);
+
+namespace variable_functional_cast_crash {
+
+struct A {
+ A(int) {}
+};
+
+void foo() {
+ A a = A(0);
+}
+
+struct B {
+ A a;
+ B(): a(A(0)) {}
+};
+
+} // namespace variable_functional_cast_crash
+
+
+namespace ctor_initializer {
+
+struct S {
+ int x, y, z;
+};
+
+struct T {
+ S s;
+ int w;
+ T(int w): s(), w(w) {}
+};
+
+class C {
+ T t;
+public:
+ C() : t(T(4)) {
+ S s = {1, 2, 3};
+ t.s = s;
+ // FIXME: Should be TRUE regardless of copy elision.
+ clang_analyzer_eval(t.w == 4);
+#ifdef ELIDE
+ // expected-warning@-2{{TRUE}}
+#else
+ // expected-warning@-4{{UNKNOWN}}
+#endif
+ }
+};
+
+
+struct A {
+ int x;
+ A(): x(0) {}
+ ~A() {}
+};
+
+struct B {
+ A a;
+ B() : a(A()) {}
+};
+
+void foo() {
+ B b;
+ clang_analyzer_eval(b.a.x == 0); // expected-warning{{TRUE}}
+}
+
+} // namespace ctor_initializer
+
+
+namespace elision_on_ternary_op_branches {
+class C1 {
+ int x;
+public:
+ C1(int x): x(x) {}
+ int getX() const { return x; }
+ ~C1();
+};
+
+class C2 {
+ int x;
+ int y;
+public:
+ C2(int x, int y): x(x), y(y) {}
+ int getX() const { return x; }
+ int getY() const { return y; }
+ ~C2();
+};
+
+void foo(int coin) {
+ C1 c1 = coin ? C1(1) : C1(2);
+ if (coin) {
+ clang_analyzer_eval(c1.getX() == 1); // expected-warning{{TRUE}}
+ } else {
+ clang_analyzer_eval(c1.getX() == 2); // expected-warning{{TRUE}}
+ }
+ C2 c2 = coin ? C2(3, 4) : C2(5, 6);
+ if (coin) {
+ clang_analyzer_eval(c2.getX() == 3); // expected-warning{{TRUE}}
+ clang_analyzer_eval(c2.getY() == 4); // expected-warning{{TRUE}}
+ } else {
+ clang_analyzer_eval(c2.getX() == 5); // expected-warning{{TRUE}}
+ clang_analyzer_eval(c2.getY() == 6); // expected-warning{{TRUE}}
+ }
+}
+} // namespace elision_on_ternary_op_branches
+
+
+namespace address_vector_tests {
+
+template <typename T> struct AddressVector {
+ T *buf[10];
+ int len;
+
+ AddressVector() : len(0) {}
+
+ void push(T *t) {
+ buf[len] = t;
+ ++len;
+ }
+};
+
+class ClassWithoutDestructor {
+ AddressVector<ClassWithoutDestructor> &v;
+
+public:
+ ClassWithoutDestructor(AddressVector<ClassWithoutDestructor> &v) : v(v) {
+ v.push(this);
+ }
+
+ ClassWithoutDestructor(ClassWithoutDestructor &&c) : v(c.v) { v.push(this); }
+ ClassWithoutDestructor(const ClassWithoutDestructor &c) : v(c.v) {
+ v.push(this);
+ }
+};
+
+ClassWithoutDestructor make1(AddressVector<ClassWithoutDestructor> &v) {
+ return ClassWithoutDestructor(v);
+}
+ClassWithoutDestructor make2(AddressVector<ClassWithoutDestructor> &v) {
+ return make1(v);
+}
+ClassWithoutDestructor make3(AddressVector<ClassWithoutDestructor> &v) {
+ return make2(v);
+}
+
+void testMultipleReturns() {
+ AddressVector<ClassWithoutDestructor> v;
+ ClassWithoutDestructor c = make3(v);
+
+#if ELIDE
+ clang_analyzer_eval(v.len == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[0] == &c); // expected-warning{{TRUE}}
+#else
+ clang_analyzer_eval(v.len == 5); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[0] != v.buf[1]); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[1] != v.buf[2]); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[2] != v.buf[3]); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[3] != v.buf[4]); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[4] == &c); // expected-warning{{TRUE}}
+#endif
+}
+
+class ClassWithDestructor {
+ AddressVector<ClassWithDestructor> &v;
+
+public:
+ ClassWithDestructor(AddressVector<ClassWithDestructor> &v) : v(v) {
+ v.push(this);
+ }
+
+ ClassWithDestructor(ClassWithDestructor &&c) : v(c.v) { v.push(this); }
+ ClassWithDestructor(const ClassWithDestructor &c) : v(c.v) {
+ v.push(this);
+ }
+
+ ~ClassWithDestructor() { v.push(this); }
+};
+
+void testVariable() {
+ AddressVector<ClassWithDestructor> v;
+ {
+ ClassWithDestructor c = ClassWithDestructor(v);
+ // Check if the last destructor is an automatic destructor.
+ // A temporary destructor would have fired by now.
+#if ELIDE
+ clang_analyzer_eval(v.len == 1); // expected-warning{{TRUE}}
+#else
+ clang_analyzer_eval(v.len == 3); // expected-warning{{TRUE}}
+#endif
+ }
+#if ELIDE
+ // 0. Construct the variable.
+ // 1. Destroy the variable.
+ clang_analyzer_eval(v.len == 2); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[0] == v.buf[1]); // expected-warning{{TRUE}}
+#else
+ // 0. Construct the temporary.
+ // 1. Construct the variable.
+ // 2. Destroy the temporary.
+ // 3. Destroy the variable.
+ clang_analyzer_eval(v.len == 4); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[0] == v.buf[2]); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[1] == v.buf[3]); // expected-warning{{TRUE}}
+#endif
+}
+
+struct TestCtorInitializer {
+ ClassWithDestructor c;
+ TestCtorInitializer(AddressVector<ClassWithDestructor> &v)
+ : c(ClassWithDestructor(v)) {}
+};
+
+void testCtorInitializer() {
+ AddressVector<ClassWithDestructor> v;
+ {
+ TestCtorInitializer t(v);
+ // Check if the last destructor is an automatic destructor.
+ // A temporary destructor would have fired by now.
+#if ELIDE
+ clang_analyzer_eval(v.len == 1); // expected-warning{{TRUE}}
+#else
+ clang_analyzer_eval(v.len == 3); // expected-warning{{TRUE}}
+#endif
+ }
+#if ELIDE
+ // 0. Construct the member variable.
+ // 1. Destroy the member variable.
+ clang_analyzer_eval(v.len == 2); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[0] == v.buf[1]); // expected-warning{{TRUE}}
+#else
+ // 0. Construct the temporary.
+ // 1. Construct the member variable.
+ // 2. Destroy the temporary.
+ // 3. Destroy the member variable.
+ clang_analyzer_eval(v.len == 4); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[0] == v.buf[2]); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[1] == v.buf[3]); // expected-warning{{TRUE}}
+#endif
+}
+
+
+ClassWithDestructor make1(AddressVector<ClassWithDestructor> &v) {
+ return ClassWithDestructor(v);
+}
+ClassWithDestructor make2(AddressVector<ClassWithDestructor> &v) {
+ return make1(v);
+}
+ClassWithDestructor make3(AddressVector<ClassWithDestructor> &v) {
+ return make2(v);
+}
+
+void testMultipleReturnsWithDestructors() {
+ AddressVector<ClassWithDestructor> v;
+ {
+ ClassWithDestructor c = make3(v);
+ // Check if the last destructor is an automatic destructor.
+ // A temporary destructor would have fired by now.
+#if ELIDE
+ clang_analyzer_eval(v.len == 1); // expected-warning{{TRUE}}
+#else
+ clang_analyzer_eval(v.len == 9); // expected-warning{{TRUE}}
+#endif
+ }
+
+#if ELIDE
+ // 0. Construct the variable. Yes, constructor in make1() constructs
+ // the variable 'c'.
+ // 1. Destroy the variable.
+ clang_analyzer_eval(v.len == 2); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[0] == v.buf[1]); // expected-warning{{TRUE}}
+#else
+ // 0. Construct the temporary in make1().
+ // 1. Construct the temporary in make2().
+ // 2. Destroy the temporary in make1().
+ // 3. Construct the temporary in make3().
+ // 4. Destroy the temporary in make2().
+ // 5. Construct the temporary here.
+ // 6. Destroy the temporary in make3().
+ // 7. Construct the variable.
+ // 8. Destroy the temporary here.
+ // 9. Destroy the variable.
+ clang_analyzer_eval(v.len == 10); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[0] == v.buf[2]); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[1] == v.buf[4]); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[3] == v.buf[6]); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[5] == v.buf[8]); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[7] == v.buf[9]); // expected-warning{{TRUE}}
+#endif
+}
+} // namespace address_vector_tests
diff --git a/test/Analysis/cxxnewexpr-callback-inline.cpp b/test/Analysis/cxxnewexpr-callback-inline.cpp
new file mode 100644
index 000000000000..c823de85821d
--- /dev/null
+++ b/test/Analysis/cxxnewexpr-callback-inline.cpp
@@ -0,0 +1,32 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.AnalysisOrder -analyzer-config c++-allocator-inlining=true,debug.AnalysisOrder:PreStmtCXXNewExpr=true,debug.AnalysisOrder:PostStmtCXXNewExpr=true,debug.AnalysisOrder:PreCall=true,debug.AnalysisOrder:PostCall=true,debug.AnalysisOrder:NewAllocator=true %s 2>&1 | FileCheck %s
+
+#include "Inputs/system-header-simulator-cxx.h"
+
+namespace std {
+ void *malloc(size_t);
+}
+
+void *operator new(size_t size) { return std::malloc(size); }
+
+struct S {
+ S() {}
+};
+
+void foo();
+
+void test() {
+ S *s = new S();
+ foo();
+}
+
+// CHECK: PreCall (operator new)
+// CHECK-NEXT: PreCall (std::malloc)
+// CHECK-NEXT: PostCall (std::malloc)
+// CHECK-NEXT: PostCall (operator new)
+// CHECK-NEXT: NewAllocator
+// CHECK-NEXT: PreCall (S::S)
+// CHECK-NEXT: PostCall (S::S)
+// CHECK-NEXT: PreStmt<CXXNewExpr>
+// CHECK-NEXT: PostStmt<CXXNewExpr>
+// CHECK-NEXT: PreCall (foo)
+// CHECK-NEXT: PostCall (foo)
diff --git a/test/Analysis/cxxnewexpr-callback-noinline.cpp b/test/Analysis/cxxnewexpr-callback-noinline.cpp
new file mode 100644
index 000000000000..87edeac3fd58
--- /dev/null
+++ b/test/Analysis/cxxnewexpr-callback-noinline.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.AnalysisOrder -analyzer-config c++-allocator-inlining=false,debug.AnalysisOrder:PreStmtCXXNewExpr=true,debug.AnalysisOrder:PostStmtCXXNewExpr=true,debug.AnalysisOrder:PreCall=true,debug.AnalysisOrder:PostCall=true,debug.AnalysisOrder:NewAllocator=true %s 2>&1 | FileCheck %s
+
+#include "Inputs/system-header-simulator-cxx.h"
+
+namespace std {
+ void *malloc(size_t);
+}
+
+void *operator new(size_t size) { return std::malloc(size); }
+
+struct S {
+ S() {}
+};
+
+void foo();
+
+void test() {
+ S *s = new S();
+ foo();
+}
+
+// CHECK: PreCall (S::S)
+// CHECK-NEXT: PostCall (S::S)
+// CHECK-NEXT: PreStmt<CXXNewExpr>
+// CHECK-NEXT: PostStmt<CXXNewExpr>
+// CHECK-NEXT: PreCall (foo)
+// CHECK-NEXT: PostCall (foo)
+// CHECK-NEXT: PreCall (std::malloc)
+// CHECK-NEXT: PostCall (std::malloc)
diff --git a/test/Analysis/dead-stores.c b/test/Analysis/dead-stores.c
index 05bc64af7a37..84217a286a55 100644
--- a/test/Analysis/dead-stores.c
+++ b/test/Analysis/dead-stores.c
@@ -525,7 +525,7 @@ void rdar8405222() {
rdar8405222_aux(i);
}
-// Look through chains of assignements, e.g.: int x = y = 0, when employing
+// Look through chains of assignments, e.g.: int x = y = 0, when employing
// silencing heuristics.
int radar11185138_foo() {
int x, y;
diff --git a/test/Analysis/diagnostics/deref-track-symbolic-region.c b/test/Analysis/diagnostics/deref-track-symbolic-region.c
index 179e736ee18b..48c659f2b8e6 100644
--- a/test/Analysis/diagnostics/deref-track-symbolic-region.c
+++ b/test/Analysis/diagnostics/deref-track-symbolic-region.c
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=text -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file -analyzer-config path-diagnostics-alternate=false %s -o %t.plist
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file %s -o %t.plist
// RUN: FileCheck --input-file=%t.plist %s
struct S {
diff --git a/test/Analysis/diagnostics/explicit-suppression.cpp b/test/Analysis/diagnostics/explicit-suppression.cpp
index 96d2b4a7d095..092591836baa 100644
--- a/test/Analysis/diagnostics/explicit-suppression.cpp
+++ b/test/Analysis/diagnostics/explicit-suppression.cpp
@@ -19,6 +19,6 @@ class C {
void testCopyNull(C *I, C *E) {
std::copy(I, E, (C *)0);
#ifndef SUPPRESSED
- // expected-warning@../Inputs/system-header-simulator-cxx.h:490 {{Called C++ object pointer is null}}
+ // expected-warning@../Inputs/system-header-simulator-cxx.h:514 {{Called C++ object pointer is null}}
#endif
}
diff --git a/test/Analysis/diagnostics/implicit-cxx-std-suppression.cpp b/test/Analysis/diagnostics/implicit-cxx-std-suppression.cpp
index 197fad5d0b7d..35f8798c81ae 100644
--- a/test/Analysis/diagnostics/implicit-cxx-std-suppression.cpp
+++ b/test/Analysis/diagnostics/implicit-cxx-std-suppression.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,cplusplus.NewDelete,debug.ExprInspection -analyzer-config c++-container-inlining=true -analyzer-config c++-stdlib-inlining=false -std=c++11 -verify %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,cplusplus.NewDelete,debug.ExprInspection -analyzer-config c++-container-inlining=true -analyzer-config c++-stdlib-inlining=true -std=c++11 -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,cplusplus.NewDelete,debug.ExprInspection -analyzer-config c++-container-inlining=true -analyzer-config c++-stdlib-inlining=false -std=c++11 -DTEST_INLINABLE_ALLOCATORS -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,cplusplus.NewDelete,debug.ExprInspection -analyzer-config c++-container-inlining=true -analyzer-config c++-stdlib-inlining=true -std=c++11 -DTEST_INLINABLE_ALLOCATORS -verify %s
// expected-no-diagnostics
diff --git a/test/Analysis/diagnostics/macro-null-return-suppression.cpp b/test/Analysis/diagnostics/macro-null-return-suppression.cpp
new file mode 100644
index 000000000000..a2928f15c1e3
--- /dev/null
+++ b/test/Analysis/diagnostics/macro-null-return-suppression.cpp
@@ -0,0 +1,68 @@
+// RUN: %clang_analyze_cc1 -x c -analyzer-checker=core -analyzer-output=text -verify %s
+
+#define NULL 0
+
+int test_noparammacro() {
+ int *x = NULL; // expected-note{{'x' initialized to a null pointer value}}
+ return *x; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
+ // expected-note@-1{{Dereference of null pointer (loaded from variable 'x')}}
+}
+
+#define DYN_CAST(X) (X ? (char*)X : 0)
+#define GENERATE_NUMBER(X) (0)
+
+char test_assignment(int *param) {
+ char *param2;
+ param2 = DYN_CAST(param);
+ return *param2;
+}
+
+char test_declaration(int *param) {
+ char *param2 = DYN_CAST(param);
+ return *param2;
+}
+
+int coin();
+
+int test_multi_decl(int *paramA, int *paramB) {
+ char *param1 = DYN_CAST(paramA), *param2 = DYN_CAST(paramB);
+ if (coin())
+ return *param1;
+ return *param2;
+}
+
+int testDivision(int a) {
+ int divider = GENERATE_NUMBER(2); // expected-note{{'divider' initialized to 0}}
+ return 1/divider; // expected-warning{{Division by zero}}
+ // expected-note@-1{{Division by zero}}
+}
+
+// Warning should not be suppressed if it happens in the same macro.
+#define DEREF_IN_MACRO(X) int fn() {int *p = 0; return *p; }
+
+DEREF_IN_MACRO(0) // expected-warning{{Dereference of null pointer}}
+ // expected-note@-1{{'p' initialized to a null}}
+ // expected-note@-2{{Dereference of null pointer}}
+
+// Warning should not be suppressed if the null returned by the macro
+// is not related to the warning.
+#define RETURN_NULL() (0)
+extern int* returnFreshPointer();
+int noSuppressMacroUnrelated() {
+ int *x = RETURN_NULL();
+ x = returnFreshPointer(); // expected-note{{Value assigned to 'x'}}
+ if (x) {} // expected-note{{Taking false branch}}
+ // expected-note@-1{{Assuming 'x' is null}}
+ return *x; // expected-warning{{Dereference of null pointer}}
+ // expected-note@-1{{Dereference}}
+}
+
+// Value haven't changed by the assignment, but the null pointer
+// did not come from the macro.
+int noSuppressMacroUnrelatedOtherReason() {
+ int *x = RETURN_NULL();
+ x = returnFreshPointer();
+ x = 0; // expected-note{{Null pointer value stored to 'x'}}
+ return *x; // expected-warning{{Dereference of null pointer}}
+ // expected-note@-1{{Dereference}}
+}
diff --git a/test/Analysis/diagnostics/no-store-func-path-notes.c b/test/Analysis/diagnostics/no-store-func-path-notes.c
new file mode 100644
index 000000000000..a444ab60261b
--- /dev/null
+++ b/test/Analysis/diagnostics/no-store-func-path-notes.c
@@ -0,0 +1,226 @@
+// RUN: %clang_analyze_cc1 -x c -analyzer-checker=core -analyzer-output=text -verify %s
+
+typedef __typeof(sizeof(int)) size_t;
+void *memset(void *__s, int __c, size_t __n);
+
+int initializer1(int *p, int x) {
+ if (x) { // expected-note{{Taking false branch}}
+ *p = 1;
+ return 0;
+ } else {
+ return 1; // expected-note {{Returning without writing to '*p'}}
+ }
+}
+
+int param_not_initialized_by_func() {
+ int p; // expected-note {{'p' declared without an initial value}}
+ int out = initializer1(&p, 0); // expected-note{{Calling 'initializer1'}}
+ // expected-note@-1{{Returning from 'initializer1'}}
+ return p; // expected-note{{Undefined or garbage value returned to caller}}
+ // expected-warning@-1{{Undefined or garbage value returned to caller}}
+}
+
+int param_initialized_properly() {
+ int p;
+ int out = initializer1(&p, 1);
+ return p; //no-warning
+}
+
+static int global;
+
+int initializer2(int **p, int x) {
+ if (x) { // expected-note{{Taking false branch}}
+ *p = &global;
+ return 0;
+ } else {
+ return 1; // expected-note {{Returning without writing to '*p'}}
+ }
+}
+
+int param_not_written_into_by_func() {
+ int *p = 0; // expected-note{{'p' initialized to a null pointer value}}
+ int out = initializer2(&p, 0); // expected-note{{Calling 'initializer2'}}
+ // expected-note@-1{{Returning from 'initializer2'}}
+ return *p; // expected-warning{{Dereference of null pointer (loaded from variable 'p')}}
+ // expected-note@-1{{Dereference of null pointer (loaded from variable 'p')}}
+}
+
+void initializer3(int *p, int param) {
+ if (param) // expected-note{{Taking false branch}}
+ *p = 0;
+} // expected-note{{Returning without writing to '*p'}}
+
+int param_written_into_by_void_func() {
+ int p; // expected-note{{'p' declared without an initial value}}
+ initializer3(&p, 0); // expected-note{{Calling 'initializer3'}}
+ // expected-note@-1{{Returning from 'initializer3'}}
+ return p; // expected-warning{{Undefined or garbage value returned to caller}}
+ // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
+
+void initializer4(int *p, int param) {
+ if (param) // expected-note{{Taking false branch}}
+ *p = 0;
+} // expected-note{{Returning without writing to '*p'}}
+
+void initializer5(int *p, int param) {
+ if (!param) // expected-note{{Taking false branch}}
+ *p = 0;
+} // expected-note{{Returning without writing to '*p'}}
+
+int multi_init_tries_func() {
+ int p; // expected-note{{'p' declared without an initial value}}
+ initializer4(&p, 0); // expected-note{{Calling 'initializer4'}}
+ // expected-note@-1{{Returning from 'initializer4'}}
+ initializer5(&p, 1); // expected-note{{Calling 'initializer5'}}
+ // expected-note@-1{{Returning from 'initializer5'}}
+ return p; // expected-warning{{Undefined or garbage value returned to caller}}
+ // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
+
+int initializer6(const int *p) {
+ return 0;
+}
+
+int no_msg_on_const() {
+ int p; // expected-note{{'p' declared without an initial value}}
+ initializer6(&p);
+ return p; // expected-warning{{Undefined or garbage value returned to caller}}
+ // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
+
+typedef struct {
+ int x;
+} S;
+
+int initializer7(S *s, int param) {
+ if (param) { // expected-note{{Taking false branch}}
+ s->x = 0;
+ return 0;
+ }
+ return 1; // expected-note{{Returning without writing to 's->x'}}
+}
+
+int initialize_struct_field() {
+ S local;
+ initializer7(&local, 0); // expected-note{{Calling 'initializer7'}}
+ // expected-note@-1{{Returning from 'initializer7'}}
+ return local.x; // expected-warning{{Undefined or garbage value returned to caller}}
+ // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
+
+void nullwriter(int **p) {
+ *p = 0; // expected-note{{Null pointer value stored to 'p'}}
+} // no extra note
+
+int usage() {
+ int x = 0;
+ int *p = &x;
+ nullwriter(&p); // expected-note{{Calling 'nullwriter'}}
+ // expected-note@-1{{Returning from 'nullwriter'}}
+ return *p; // expected-warning{{Dereference of null pointer (loaded from variable 'p')}}
+ // expected-note@-1{{Dereference of null pointer (loaded from variable 'p')}}
+}
+
+typedef struct {
+ int x;
+ int y;
+} A;
+
+void partial_initializer(A *a) {
+ a->x = 0;
+} // expected-note{{Returning without writing to 'a->y'}}
+
+int use_partial_initializer() {
+ A a;
+ partial_initializer(&a); // expected-note{{Calling 'partial_initializer'}}
+ // expected-note@-1{{Returning from 'partial_initializer'}}
+ return a.y; // expected-warning{{Undefined or garbage value returned to caller}}
+ // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
+
+typedef struct {
+ int x;
+ int y;
+} B;
+
+typedef struct {
+ B b;
+} C;
+
+void partial_nested_initializer(C *c) {
+ c->b.x = 0;
+} // expected-note{{Returning without writing to 'c->b.y'}}
+
+int use_partial_nested_initializer() {
+ B localB;
+ C localC;
+ localC.b = localB;
+ partial_nested_initializer(&localC); // expected-note{{Calling 'partial_nested_initializer'}}
+ // expected-note@-1{{Returning from 'partial_nested_initializer'}}
+ return localC.b.y; // expected-warning{{Undefined or garbage value returned to caller}}
+ // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
+
+void test_subregion_assignment(C* c) {
+ B b;
+ c->b = b;
+}
+
+int use_subregion_assignment() {
+ C c;
+ test_subregion_assignment(&c); // expected-note{{Calling 'test_subregion_assignment'}}
+ // expected-note@-1{{Returning from 'test_subregion_assignment'}}
+ return c.b.x; // expected-warning{{Undefined or garbage value returned to caller}}
+ // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
+
+int confusing_signature(int *);
+int confusing_signature(int *p) {
+ return 0; // expected-note{{Returning without writing to '*p'}}
+}
+
+int use_confusing_signature() {
+ int a; // expected-note {{'a' declared without an initial value}}
+ confusing_signature(&a); // expected-note{{Calling 'confusing_signature'}}
+ // expected-note@-1{{Returning from 'confusing_signature'}}
+ return a; // expected-note{{Undefined or garbage value returned to caller}}
+ // expected-warning@-1{{Undefined or garbage value returned to caller}}
+}
+
+int coin();
+
+int multiindirection(int **p) {
+ if (coin()) // expected-note{{Assuming the condition is true}}
+ // expected-note@-1{{Taking true branch}}
+ return 1; // expected-note{{Returning without writing to '**p'}}
+ *(*p) = 0;
+ return 0;
+}
+
+int usemultiindirection() {
+ int a; // expected-note {{'a' declared without an initial value}}
+ int *b = &a;
+ multiindirection(&b); // expected-note{{Calling 'multiindirection'}}
+ // expected-note@-1{{Returning from 'multiindirection'}}
+ return a; // expected-note{{Undefined or garbage value returned to caller}}
+ // expected-warning@-1{{Undefined or garbage value returned to caller}}
+}
+
+int indirectingstruct(S** s) {
+ if (coin()) // expected-note{{Assuming the condition is true}}
+ // expected-note@-1{{Taking true branch}}
+ return 1; // expected-note{{Returning without writing to '(*s)->x'}}
+
+ (*s)->x = 0;
+ return 0;
+}
+
+int useindirectingstruct() {
+ S s;
+ S* p = &s;
+ indirectingstruct(&p); //expected-note{{Calling 'indirectingstruct'}}
+ //expected-note@-1{{Returning from 'indirectingstruct'}}
+ return s.x; // expected-warning{{Undefined or garbage value returned to caller}}
+ // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
diff --git a/test/Analysis/diagnostics/no-store-func-path-notes.cpp b/test/Analysis/diagnostics/no-store-func-path-notes.cpp
new file mode 100644
index 000000000000..17ec96ae5b75
--- /dev/null
+++ b/test/Analysis/diagnostics/no-store-func-path-notes.cpp
@@ -0,0 +1,177 @@
+// RUN: %clang_analyze_cc1 -x c++ -analyzer-checker=core -analyzer-output=text -verify %s
+
+int initializer1(int &p, int x) {
+ if (x) { // expected-note{{Taking false branch}}
+ p = 1;
+ return 0;
+ } else {
+ return 1; // expected-note {{Returning without writing to 'p'}}
+ }
+}
+
+int param_not_initialized_by_func() {
+ int p; // expected-note {{'p' declared without an initial value}}
+ int out = initializer1(p, 0); // expected-note{{Calling 'initializer1'}}
+ // expected-note@-1{{Returning from 'initializer1'}}
+ return p; // expected-note{{Undefined or garbage value returned to caller}}
+ // expected-warning@-1{{Undefined or garbage value returned to caller}}
+}
+
+struct S {
+ int initialize(int *p, int param) {
+ if (param) { //expected-note{{Taking false branch}}
+ *p = 1;
+ return 1;
+ }
+ return 0; // expected-note{{Returning without writing to '*p'}}
+ }
+};
+
+int use(S *s) {
+ int p; //expected-note{{'p' declared without an initial value}}
+ s->initialize(&p, 0); //expected-note{{Calling 'S::initialize'}}
+ //expected-note@-1{{Returning from 'S::initialize'}}
+ return p; // expected-warning{{Undefined or garbage value returned to caller}}
+ // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
+
+int initializer2(const int &p) {
+ return 0;
+}
+
+int no_msg_const_ref() {
+ int p; //expected-note{{'p' declared without an initial value}}
+ initializer2(p);
+ return p; // expected-warning{{Undefined or garbage value returned to caller}}
+ // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
+
+void nested() {}
+void init_in_nested_func(int **x) {
+ *x = 0; // expected-note{{Null pointer value stored to 'y'}}
+ nested();
+} // no-note
+
+int call_init_nested() {
+ int x = 0;
+ int *y = &x;
+ init_in_nested_func(&y); // expected-note{{Calling 'init_in_nested_func'}}
+ // expected-note@-1{{Returning from 'init_in_nested_func'}}
+ return *y; //expected-warning{{Dereference of null pointer (loaded from variable 'y')}}
+ //expected-note@-1{{Dereference of null pointer (loaded from variable 'y')}}
+}
+
+struct A {
+ int x;
+ int y;
+};
+
+void partial_init_by_reference(A &a) {
+ a.x = 0;
+} // expected-note {{Returning without writing to 'a.y'}}
+
+int use_partial_init_by_reference() {
+ A a;
+ partial_init_by_reference(a); // expected-note{{Calling 'partial_init_by_reference'}}
+ // expected-note@-1{{Returning from 'partial_init_by_reference'}}
+ return a.y; // expected-warning{{Undefined or garbage value returned to caller}}
+ // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
+
+struct B : A {
+};
+
+void partially_init_inherited_struct(B *b) {
+ b->x = 0;
+} // expected-note{{Returning without writing to 'b->y'}}
+
+int use_partially_init_inherited_struct() {
+ B b;
+ partially_init_inherited_struct(&b); // expected-note{{Calling 'partially_init_inherited_struct'}}
+ // expected-note@-1{{Returning from 'partially_init_inherited_struct'}}
+ return b.y; // expected-warning{{Undefined or garbage value returned to caller}}
+ // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
+
+struct C {
+ int x;
+ int y;
+ C(int pX, int pY) : x(pX) {} // expected-note{{Returning without writing to 'this->y'}}
+
+ C(int pX, int pY, bool Flag) {
+ x = pX;
+ if (Flag) // expected-note{{Assuming 'Flag' is not equal to 0}}
+ // expected-note@-1{{Taking true branch}}
+ return; // expected-note{{Returning without writing to 'this->y'}}
+ y = pY;
+ }
+};
+
+int use_constructor() {
+ C c(0, 0); // expected-note{{Calling constructor for 'C'}}
+ // expected-note@-1{{Returning from constructor for 'C'}}
+ return c.y; // expected-note{{Undefined or garbage value returned to caller}}
+ // expected-warning@-1{{Undefined or garbage value returned to caller}}
+}
+
+int coin();
+
+int use_other_constructor() {
+ C c(0, 0, coin()); // expected-note{{Calling constructor for 'C'}}
+ // expected-note@-1{{Returning from constructor for 'C'}}
+ return c.y; // expected-note{{Undefined or garbage value returned to caller}}
+ // expected-warning@-1{{Undefined or garbage value returned to caller}}
+}
+
+struct D {
+ void initialize(int *);
+};
+
+void D::initialize(int *p) {
+
+} // expected-note{{Returning without writing to '*p'}}
+
+int use_d_initializer(D* d) {
+ int p; // expected-note {{'p' declared without an initial value}}
+ d->initialize(&p); // expected-note{{Calling 'D::initialize'}}
+ // expected-note@-1{{Returning from 'D::initialize'}}
+ return p; // expected-note{{Undefined or garbage value returned to caller}}
+ // expected-warning@-1{{Undefined or garbage value returned to caller}}
+}
+
+struct S2 {
+ int x;
+};
+
+int pointerreference(S2* &s) {
+ if (coin()) // expected-note{{Assuming the condition is true}}
+ // expected-note@-1{{Taking true branch}}
+ return 1; // expected-note{{Returning without writing to 's->x'}}
+
+ s->x = 0;
+ return 0;
+}
+
+int usepointerreference() {
+ S2 s;
+ S2* p = &s;
+ pointerreference(p); //expected-note{{Calling 'pointerreference'}}
+ //expected-note@-1{{Returning from 'pointerreference'}}
+ return s.x; // expected-warning{{Undefined or garbage value returned to caller}}
+ // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
+
+void *has_no_argument_and_returns_null(void) {
+ return 0;
+}
+
+void rdar40335545() {
+ int local; // expected-note{{}}
+ void (*takes_int_ptr_argument)(int *) = (void (*)(int*))has_no_argument_and_returns_null;
+
+ takes_int_ptr_argument(&local); // no-crash
+
+ int useLocal = local; //expected-warning{{}}
+ //expected-note@-1{{}}
+ (void)useLocal;
+}
diff --git a/test/Analysis/diagnostics/no-store-func-path-notes.m b/test/Analysis/diagnostics/no-store-func-path-notes.m
new file mode 100644
index 000000000000..51d1515e860a
--- /dev/null
+++ b/test/Analysis/diagnostics/no-store-func-path-notes.m
@@ -0,0 +1,77 @@
+// RUN: %clang_analyze_cc1 -x objective-c -analyzer-checker=core,nullability -analyzer-output=text -Wno-objc-root-class -fblocks -verify %s
+
+#include "../Inputs/system-header-simulator-for-nullability.h"
+
+extern int coin();
+
+@interface I : NSObject
+- (int)initVar:(int *)var param:(int)param;
+@end
+
+@implementation I
+- (int)initVar:(int *)var param:(int)param {
+ if (param) { // expected-note{{Taking false branch}}
+ *var = 1;
+ return 0;
+ }
+ return 1; // expected-note{{Returning without writing to '*var'}}
+}
+@end
+
+int foo(I *i) {
+ int x; //expected-note{{'x' declared without an initial value}}
+ int out = [i initVar:&x param:0]; //expected-note{{Calling 'initVar:param:'}}
+ //expected-note@-1{{Returning from 'initVar:param:'}}
+ if (out) // expected-note{{Taking true branch}}
+ return x; //expected-warning{{Undefined or garbage value returned to caller}}
+ //expected-note@-1{{Undefined or garbage value returned to caller}}
+ return 0;
+}
+
+int initializer1(int *p, int x) {
+ if (x) { // expected-note{{Taking false branch}}
+ *p = 1;
+ return 0;
+ } else {
+ return 1; // expected-note {{Returning without writing to '*p'}}
+ }
+}
+
+int initFromBlock() {
+ __block int z;
+ ^{ // expected-note {{Calling anonymous block}}
+ int p; // expected-note{{'p' declared without an initial value}}
+ initializer1(&p, 0); // expected-note{{Calling 'initializer1'}}
+ // expected-note@-1{{Returning from 'initializer1'}}
+ z = p; // expected-warning{{Assigned value is garbage or undefined}}
+ // expected-note@-1{{Assigned value is garbage or undefined}}
+ }();
+ return z;
+}
+
+extern void expectNonNull(NSString * _Nonnull a);
+
+@interface A : NSObject
+- (void) func;
+- (void) initAMaybe;
+@end
+
+@implementation A {
+ NSString * a;
+}
+
+- (void) initAMaybe {
+ if (coin()) // expected-note{{Assuming the condition is false}}
+ // expected-note@-1{{Taking false branch}}
+ a = @"string";
+} // expected-note{{Returning without writing to 'self->a'}}
+
+- (void) func {
+ a = nil; // expected-note{{nil object reference stored to 'a'}}
+ [self initAMaybe]; // expected-note{{Calling 'initAMaybe'}}
+ // expected-note@-1{{Returning from 'initAMaybe'}}
+ expectNonNull(a); // expected-warning{{nil passed to a callee that requires a non-null 1st parameter}}
+ // expected-note@-1{{nil passed to a callee that requires a non-null 1st parameter}}
+}
+
+@end
diff --git a/test/Analysis/diagnostics/plist-multi-file.c b/test/Analysis/diagnostics/plist-multi-file.c
new file mode 100644
index 000000000000..ff68d4850862
--- /dev/null
+++ b/test/Analysis/diagnostics/plist-multi-file.c
@@ -0,0 +1,205 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-html -o %t.plist -verify %s
+// RUN: FileCheck --input-file=%t.plist %s
+
+#include "plist-multi-file.h"
+
+void bar() {
+ foo(0);
+}
+
+// CHECK: <key>diagnostics</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>path</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>7</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>7</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>7</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;ptr&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;ptr&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>7</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>7</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>7</integer>
+// CHECK-NEXT: <key>col</key><integer>8</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Calling &apos;foo&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Calling &apos;foo&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>1</integer>
+// CHECK-NEXT: <key>col</key><integer>1</integer>
+// CHECK-NEXT: <key>file</key><integer>1</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>depth</key><integer>1</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Entered call from &apos;bar&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Entered call from &apos;bar&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>1</integer>
+// CHECK-NEXT: <key>col</key><integer>1</integer>
+// CHECK-NEXT: <key>file</key><integer>1</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>1</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
+// CHECK-NEXT: <key>file</key><integer>1</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>2</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>1</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>2</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>1</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>2</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>1</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>2</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>1</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>2</integer>
+// CHECK-NEXT: <key>col</key><integer>8</integer>
+// CHECK-NEXT: <key>file</key><integer>1</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>2</integer>
+// CHECK-NEXT: <key>col</key><integer>8</integer>
+// CHECK-NEXT: <key>file</key><integer>1</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>2</integer>
+// CHECK-NEXT: <key>col</key><integer>8</integer>
+// CHECK-NEXT: <key>file</key><integer>1</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>2</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
+// CHECK-NEXT: <key>file</key><integer>1</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>2</integer>
+// CHECK-NEXT: <key>col</key><integer>6</integer>
+// CHECK-NEXT: <key>file</key><integer>1</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>1</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+// CHECK-NEXT: <key>category</key><string>Logic error</string>
+// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
+// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>2058c95994cab381890af28e7bf354bf</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>foo</string>
+// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>2</integer>
+// CHECK-NEXT: <key>col</key><integer>8</integer>
+// CHECK-NEXT: <key>file</key><integer>1</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>HTMLDiagnostics_files</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <string>report-{{([0-9a-f]{6})}}.html</string>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
diff --git a/test/Analysis/diagnostics/plist-multi-file.h b/test/Analysis/diagnostics/plist-multi-file.h
new file mode 100644
index 000000000000..c0674f9dfcf0
--- /dev/null
+++ b/test/Analysis/diagnostics/plist-multi-file.h
@@ -0,0 +1,3 @@
+void foo(int *ptr) {
+ *ptr = 1; // expected-warning{{Dereference of null pointer (loaded from variable 'ptr')}}
+}
diff --git a/test/Analysis/diagnostics/report-issues-within-main-file.cpp b/test/Analysis/diagnostics/report-issues-within-main-file.cpp
index e1dccc8e3204..18795d25bd85 100644
--- a/test/Analysis/diagnostics/report-issues-within-main-file.cpp
+++ b/test/Analysis/diagnostics/report-issues-within-main-file.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix -analyzer-output=plist-multi-file -analyzer-config report-in-main-source-file=true -analyzer-config path-diagnostics-alternate=false %s -o %t.plist
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix -analyzer-output=plist-multi-file -analyzer-config report-in-main-source-file=true %s -o %t.plist
// RUN: FileCheck --input-file=%t.plist %s
#include "Inputs/include/report-issues-within-main-file.h"
@@ -77,6 +77,40 @@ void callInMacroArg() {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>49</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>49</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>51</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>51</integer>
+// CHECK-NEXT: <key>col</key><integer>23</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -343,6 +377,40 @@ void callInMacroArg() {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>56</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>56</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>58</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>58</integer>
+// CHECK-NEXT: <key>col</key><integer>23</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -532,6 +600,40 @@ void callInMacroArg() {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>67</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>67</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>69</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>69</integer>
+// CHECK-NEXT: <key>col</key><integer>18</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -721,40 +823,6 @@ void callInMacroArg() {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -792,46 +860,12 @@ void callInMacroArg() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
+// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -1542,40 +1576,6 @@ void callInMacroArg() {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>43</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>43</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>43</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>43</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>44</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
diff --git a/test/Analysis/diagnostics/undef-value-caller.c b/test/Analysis/diagnostics/undef-value-caller.c
index 4f273bd9a72d..60a885afe292 100644
--- a/test/Analysis/diagnostics/undef-value-caller.c
+++ b/test/Analysis/diagnostics/undef-value-caller.c
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist -analyzer-config path-diagnostics-alternate=false -o %t %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist -o %t %s
// RUN: FileCheck --input-file %t %s
#include "undef-value-callee.h"
@@ -66,40 +66,6 @@ int test_calling_unimportant_callee(int argc, char *argv[]) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>11</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
diff --git a/test/Analysis/diagnostics/undef-value-param.c b/test/Analysis/diagnostics/undef-value-param.c
index 837b0419ef20..99e31d2e6c55 100644
--- a/test/Analysis/diagnostics/undef-value-param.c
+++ b/test/Analysis/diagnostics/undef-value-param.c
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=text -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file -analyzer-config path-diagnostics-alternate=false %s -o %t.plist
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file %s -o %t.plist
// RUN: FileCheck --input-file=%t.plist %s
void foo_irrelevant(int c) {
@@ -12,7 +12,7 @@ void foo(int c, int *x) {
if (c)
//expected-note@-1{{Assuming 'c' is not equal to 0}}
//expected-note@-2{{Taking true branch}}
- return;
+ return; // expected-note{{Returning without writing to '*x'}}
*x = 5;
}
@@ -51,7 +51,7 @@ void initStruct(int x, struct WithFields *X) {
if (x <= 0) //expected-note {{Taking true branch}}
//expected-note@-1 {{Assuming 'x' is <= 0}}
- return;
+ return; //expected-note{{Returning without writing to 'X->f1'}}
X->f1 = getValidPtr();
}
double testPassingParentRegionStruct(int x) {
@@ -293,12 +293,94 @@ double testPassingParentRegionStruct(int x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
+// CHECK-NEXT: <key>col</key><integer>12</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
+// CHECK-NEXT: <key>col</key><integer>17</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>12</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>17</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>12</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>17</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>12</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>depth</key><integer>1</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Returning without writing to &apos;*x&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Returning without writing to &apos;*x&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>12</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>17</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>12</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>17</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -1043,6 +1125,88 @@ double testPassingParentRegionStruct(int x) {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>54</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>54</integer>
+// CHECK-NEXT: <key>col</key><integer>10</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>54</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>54</integer>
+// CHECK-NEXT: <key>col</key><integer>10</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>54</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>depth</key><integer>1</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Returning without writing to &apos;X-&gt;f1&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Returning without writing to &apos;X-&gt;f1&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>54</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>54</integer>
+// CHECK-NEXT: <key>col</key><integer>10</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>54</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>54</integer>
+// CHECK-NEXT: <key>col</key><integer>10</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
diff --git a/test/Analysis/diagnostics/undef-value-param.m b/test/Analysis/diagnostics/undef-value-param.m
index f8212e0b9df3..69bc9b991da6 100644
--- a/test/Analysis/diagnostics/undef-value-param.m
+++ b/test/Analysis/diagnostics/undef-value-param.m
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx -analyzer-output=text -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx -analyzer-output=plist-multi-file -analyzer-config path-diagnostics-alternate=false %s -o %t.plist
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx -analyzer-output=plist-multi-file %s -o %t.plist
// RUN: FileCheck --input-file=%t.plist %s
typedef signed char BOOL;
@@ -69,7 +69,7 @@ static void CreateRefUndef(SCDynamicStoreRef *storeRef, unsigned x) {
//expected-note@-1{{Assuming 'err' is not equal to 0}}
//expected-note@-2{{Taking true branch}}
CFRelease(ref);
- return;
+ return; // expected-note{{Returning without writing to '*storeRef'}}
}
*storeRef = ref;
}
@@ -831,6 +831,122 @@ static void CreateRefUndef(SCDynamicStoreRef *storeRef, unsigned x) {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>71</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>71</integer>
+// CHECK-NEXT: <key>col</key><integer>13</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
+// CHECK-NEXT: <key>col</key><integer>10</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
+// CHECK-NEXT: <key>col</key><integer>10</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
+// CHECK-NEXT: <key>col</key><integer>10</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>depth</key><integer>1</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Returning without writing to &apos;*storeRef&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Returning without writing to &apos;*storeRef&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
+// CHECK-NEXT: <key>col</key><integer>10</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>72</integer>
+// CHECK-NEXT: <key>col</key><integer>10</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
diff --git a/test/Analysis/dtor-cxx11.cpp b/test/Analysis/dtor-cxx11.cpp
index 76d5e6c5065d..33e13e99bd3b 100644
--- a/test/Analysis/dtor-cxx11.cpp
+++ b/test/Analysis/dtor-cxx11.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config cfg-temporary-dtors=true -Wno-null-dereference -verify %s
+// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -Wno-null-dereference -verify %s
// expected-no-diagnostics
#include "Inputs/system-header-simulator-cxx.h"
diff --git a/test/Analysis/dtor.cpp b/test/Analysis/dtor.cpp
index bc74130b2fdf..c31bbe774b81 100644
--- a/test/Analysis/dtor.cpp
+++ b/test/Analysis/dtor.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection,cplusplus -analyzer-config c++-inlining=destructors,cfg-temporary-dtors=true -Wno-null-dereference -Wno-inaccessible-base -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection,cplusplus -analyzer-config c++-inlining=destructors -Wno-null-dereference -Wno-inaccessible-base -verify %s
void clang_analyzer_eval(bool);
void clang_analyzer_checkInlined(bool);
diff --git a/test/Analysis/dynamic_type_check.m b/test/Analysis/dynamic_type_check.m
index 3dc9465cfedf..6753892e1d52 100644
--- a/test/Analysis/dynamic_type_check.m
+++ b/test/Analysis/dynamic_type_check.m
@@ -36,7 +36,7 @@ void testTypeCheck(NSString* str) {
void testForwardDeclarations(NSString* str) {
id obj = str;
- // Do not warn, since no information is available wether MyType is a sub or
+ // Do not warn, since no information is available whether MyType is a sub or
// super class of any other type.
MyType *num = obj; // no warning
(void)num;
diff --git a/test/Analysis/edges-new.mm b/test/Analysis/edges-new.mm
index f310f1bfa12e..3e9615b94b6c 100644
--- a/test/Analysis/edges-new.mm
+++ b/test/Analysis/edges-new.mm
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,deadcode.DeadStores,osx.cocoa.RetainCount,unix.Malloc,unix.MismatchedDeallocator -analyzer-eagerly-assume -analyzer-config path-diagnostics-alternate=true -analyzer-output=plist -o %t -w %s
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,deadcode.DeadStores,osx.cocoa.RetainCount,unix.Malloc,unix.MismatchedDeallocator -analyzer-eagerly-assume -analyzer-output=plist -o %t -w %s
// RUN: FileCheck --input-file %t %s
//===----------------------------------------------------------------------===//
diff --git a/test/Analysis/explain-svals.cpp b/test/Analysis/explain-svals.cpp
index d4b56a348252..c1b5200eb8e9 100644
--- a/test/Analysis/explain-svals.cpp
+++ b/test/Analysis/explain-svals.cpp
@@ -69,7 +69,7 @@ void test_4(int x, int y) {
static int stat;
clang_analyzer_explain(x + 1); // expected-warning-re{{{{^\(argument 'x'\) \+ 1$}}}}
clang_analyzer_explain(1 + y); // expected-warning-re{{{{^\(argument 'y'\) \+ 1$}}}}
- clang_analyzer_explain(x + y); // expected-warning-re{{{{^unknown value$}}}}
+ clang_analyzer_explain(x + y); // expected-warning-re{{{{^\(argument 'x'\) \+ \(argument 'y'\)$}}}}
clang_analyzer_explain(z); // expected-warning-re{{{{^undefined value$}}}}
clang_analyzer_explain(&z); // expected-warning-re{{{{^pointer to local variable 'z'$}}}}
clang_analyzer_explain(stat); // expected-warning-re{{{{^signed 32-bit integer '0'$}}}}
@@ -94,5 +94,5 @@ public:
void test_6() {
clang_analyzer_explain(conjure_S()); // expected-warning-re{{{{^lazily frozen compound value of temporary object constructed at statement 'conjure_S\(\)'$}}}}
- clang_analyzer_explain(conjure_S().z); // expected-warning-re{{{{^value derived from \(symbol of type 'struct S' conjured at statement 'conjure_S\(\)'\) for field 'z' of temporary object constructed at statement 'conjure_S\(\)'$}}}}
+ clang_analyzer_explain(conjure_S().z); // expected-warning-re{{{{^value derived from \(symbol of type 'int' conjured at statement 'conjure_S\(\)'\) for field 'z' of temporary object constructed at statement 'conjure_S\(\)'$}}}}
}
diff --git a/test/Analysis/exploration_order/noexprcrash.c b/test/Analysis/exploration_order/noexprcrash.c
new file mode 100644
index 000000000000..75c2f0e6798a
--- /dev/null
+++ b/test/Analysis/exploration_order/noexprcrash.c
@@ -0,0 +1,17 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify -analyzer-config exploration_strategy=unexplored_first %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify -analyzer-config exploration_strategy=dfs %s
+
+extern void clang_analyzer_eval(int);
+
+typedef struct { char a; } b;
+int c(b* input) {
+ int x = (input->a ?: input) ? 1 : 0; // expected-warning{{pointer/integer type mismatch}}
+ if (input->a) {
+ // FIXME: The value should actually be "TRUE",
+ // but is incorrect due to a bug.
+ clang_analyzer_eval(x); // expected-warning{{FALSE}}
+ } else {
+ clang_analyzer_eval(x); // expected-warning{{TRUE}}
+ }
+ return x;
+}
diff --git a/test/Analysis/exploration_order/prefer_unexplored.cpp b/test/Analysis/exploration_order/prefer_unexplored.cpp
new file mode 100644
index 000000000000..29e763357727
--- /dev/null
+++ b/test/Analysis/exploration_order/prefer_unexplored.cpp
@@ -0,0 +1,43 @@
+// RUN: %clang_analyze_cc1 -w -analyzer-checker=core -analyzer-config exploration_strategy=unexplored_first -analyzer-output=text -verify %s
+// RUN: %clang_analyze_cc1 -w -analyzer-checker=core -analyzer-config exploration_strategy=unexplored_first_queue -analyzer-output=text -verify %s
+
+extern int coin();
+
+int foo() {
+ int *x = 0; // expected-note {{'x' initialized to a null pointer value}}
+ while (coin()) { // expected-note{{Loop condition is true}}
+ if (coin()) // expected-note {{Taking true branch}}
+ // expected-note@-1 {{Assuming the condition is true}}
+ return *x; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
+ // expected-note@-1{{Dereference of null pointer (loaded from variable 'x')}}
+ }
+ return 0;
+}
+
+void bar() {
+ while(coin())
+ if (coin())
+ foo();
+}
+
+int foo2() {
+ int *x = 0; // expected-note {{'x' initialized to a null pointer value}}
+ while (coin()) { // expected-note{{Loop condition is true}}
+ if (coin()) // expected-note {{Taking false branch}}
+ // expected-note@-1 {{Assuming the condition is false}}
+ return false;
+ else
+ return *x; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
+ // expected-note@-1{{Dereference of null pointer (loaded from variable 'x')}}
+ }
+ return 0;
+}
+
+void bar2() {
+ while(coin()) // expected-note{{Loop condition is true}}
+ if (coin()) // expected-note {{Assuming the condition is false}}
+ // expected-note@-1 {{Taking false branch}}
+ return;
+ else
+ foo(); // expected-note{{Calling 'foo'}}
+}
diff --git a/test/Analysis/expr-inspection.c b/test/Analysis/expr-inspection.c
index ec0e682b6536..841954288932 100644
--- a/test/Analysis/expr-inspection.c
+++ b/test/Analysis/expr-inspection.c
@@ -18,6 +18,8 @@ void foo(int x) {
// CHECK: Store (direct and default bindings)
// CHECK-NEXT: (y,0,direct) : 1 S32b
-// CHECK: Expressions:
+// CHECK: Expressions by stack frame:
+// CHECK-NEXT: #0 Calling foo
// CHECK-NEXT: clang_analyzer_printState : &code{clang_analyzer_printState}
-// CHECK-NEXT: {{(Ranges are empty.)|(Constraints:[[:space:]]*$)}}
+
+// CHECK: {{(Ranges are empty.)|(Constraints:[[:space:]]*$)}}
diff --git a/test/Analysis/gcdantipatternchecker_test.m b/test/Analysis/gcdantipatternchecker_test.m
new file mode 100644
index 000000000000..24ffe8975dd9
--- /dev/null
+++ b/test/Analysis/gcdantipatternchecker_test.m
@@ -0,0 +1,345 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,optin.performance.GCDAntipattern %s -fblocks -verify
+typedef signed char BOOL;
+@protocol NSObject - (BOOL)isEqual:(id)object; @end
+@interface NSObject <NSObject> {}
++(id)alloc;
+-(id)init;
+-(id)autorelease;
+-(id)copy;
+-(id)retain;
+@end
+
+typedef int dispatch_semaphore_t;
+typedef int dispatch_group_t;
+typedef void (^block_t)();
+
+dispatch_semaphore_t dispatch_semaphore_create(int);
+dispatch_group_t dispatch_group_create();
+void dispatch_group_enter(dispatch_group_t);
+void dispatch_group_leave(dispatch_group_t);
+void dispatch_group_wait(dispatch_group_t, int);
+
+
+void dispatch_semaphore_wait(dispatch_semaphore_t, int);
+void dispatch_semaphore_signal(dispatch_semaphore_t);
+
+void func(void (^)(void));
+void func_w_typedef(block_t);
+
+int coin();
+
+void use_semaphor_antipattern() {
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+
+ func(^{
+ dispatch_semaphore_signal(sema);
+ });
+ dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a callback using a semaphore}}
+}
+
+// It's OK to use pattern in tests.
+// We simply match the containing function name against ^test.
+void test_no_warning() {
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+
+ func(^{
+ dispatch_semaphore_signal(sema);
+ });
+ dispatch_semaphore_wait(sema, 100);
+}
+
+void use_semaphor_antipattern_multiple_times() {
+ dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);
+
+ func(^{
+ dispatch_semaphore_signal(sema1);
+ });
+ dispatch_semaphore_wait(sema1, 100); // expected-warning{{Waiting on a callback using a semaphore}}
+
+ dispatch_semaphore_t sema2 = dispatch_semaphore_create(0);
+
+ func(^{
+ dispatch_semaphore_signal(sema2);
+ });
+ dispatch_semaphore_wait(sema2, 100); // expected-warning{{Waiting on a callback using a semaphore}}
+}
+
+void use_semaphor_antipattern_multiple_wait() {
+ dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);
+
+ func(^{
+ dispatch_semaphore_signal(sema1);
+ });
+ // FIXME: multiple waits on same semaphor should not raise a warning.
+ dispatch_semaphore_wait(sema1, 100); // expected-warning{{Waiting on a callback using a semaphore}}
+ dispatch_semaphore_wait(sema1, 100); // expected-warning{{Waiting on a callback using a semaphore}}
+}
+
+void warn_incorrect_order() {
+ // FIXME: ASTMatchers do not allow ordered matching, so would match even
+ // if out of order.
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+
+ dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a callback}}
+ func(^{
+ dispatch_semaphore_signal(sema);
+ });
+}
+
+void warn_w_typedef() {
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+
+ func_w_typedef(^{
+ dispatch_semaphore_signal(sema);
+ });
+ dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a callback using a semaphore}}
+}
+
+void warn_nested_ast() {
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+
+ if (coin()) {
+ func(^{
+ dispatch_semaphore_signal(sema);
+ });
+ } else {
+ func(^{
+ dispatch_semaphore_signal(sema);
+ });
+ }
+ dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a callback using a semaphore}}
+}
+
+void use_semaphore_assignment() {
+ dispatch_semaphore_t sema;
+ sema = dispatch_semaphore_create(0);
+
+ func(^{
+ dispatch_semaphore_signal(sema);
+ });
+ dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a callback using a semaphore}}
+}
+
+void use_semaphore_assignment_init() {
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+ sema = dispatch_semaphore_create(1);
+
+ func(^{
+ dispatch_semaphore_signal(sema);
+ });
+ dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a callback using a semaphore}}
+}
+
+void differentsemaphoreok() {
+ dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);
+ dispatch_semaphore_t sema2 = dispatch_semaphore_create(0);
+
+ func(^{
+ dispatch_semaphore_signal(sema1);
+ });
+ dispatch_semaphore_wait(sema2, 100); // no-warning
+}
+
+void nosignalok() {
+ dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);
+ dispatch_semaphore_wait(sema1, 100);
+}
+
+void nowaitok() {
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+ func(^{
+ dispatch_semaphore_signal(sema);
+ });
+}
+
+void noblockok() {
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+ dispatch_semaphore_signal(sema);
+ dispatch_semaphore_wait(sema, 100);
+}
+
+void storedblockok() {
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+ block_t b = ^{
+ dispatch_semaphore_signal(sema);
+ };
+ dispatch_semaphore_wait(sema, 100);
+}
+
+void passed_semaphore_ok(dispatch_semaphore_t sema) {
+ func(^{
+ dispatch_semaphore_signal(sema);
+ });
+ dispatch_semaphore_wait(sema, 100);
+}
+
+void warn_with_cast() {
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+
+ func(^{
+ dispatch_semaphore_signal((int)sema);
+ });
+ dispatch_semaphore_wait((int)sema, 100); // expected-warning{{Waiting on a callback using a semaphore}}
+}
+
+@interface MyInterface1 : NSObject
+-(void)use_method_warn;
+-(void) pass_block_as_second_param_warn;
+-(void)use_objc_callback_warn;
+-(void) use_dispatch_group;
+-(void)testNoWarn;
+-(void)acceptBlock:(block_t)callback;
+-(void)flag:(int)flag acceptBlock:(block_t)callback;
+@end
+
+@implementation MyInterface1
+
+-(void)use_method_warn {
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+
+ func(^{
+ dispatch_semaphore_signal(sema);
+ });
+ dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a callback}}
+}
+
+-(void) pass_block_as_second_param_warn {
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+
+ [self flag:1 acceptBlock:^{
+ dispatch_semaphore_signal(sema);
+ }];
+ dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a callback}}
+}
+
+-(void)testNoWarn {
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+
+ func(^{
+ dispatch_semaphore_signal(sema);
+ });
+ dispatch_semaphore_wait(sema, 100);
+}
+
+-(void)acceptBlock:(block_t) callback {
+ callback();
+}
+
+-(void)flag:(int)flag acceptBlock:(block_t)callback {
+ callback();
+}
+
+-(void)use_objc_callback_warn {
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+
+ [self acceptBlock:^{
+ dispatch_semaphore_signal(sema);
+ }];
+ dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a callback}}
+}
+
+-(void)use_dispatch_group {
+ dispatch_group_t group = dispatch_group_create();
+ dispatch_group_enter(group);
+ [self acceptBlock:^{
+ dispatch_group_leave(group);
+ }];
+ dispatch_group_wait(group, 100); // expected-warning{{Waiting on a callback using a group}}
+
+}
+
+void use_objc_and_c_callback(MyInterface1 *t) {
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+
+ func(^{
+ dispatch_semaphore_signal(sema);
+ });
+ dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a callback using a semaphore}}
+
+ dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);
+
+ [t acceptBlock:^{
+ dispatch_semaphore_signal(sema1);
+ }];
+ dispatch_semaphore_wait(sema1, 100); // expected-warning{{Waiting on a callback}}
+}
+@end
+
+// No warnings: class name contains "test"
+@interface Test1 : NSObject
+-(void)use_method_warn;
+@end
+
+@implementation Test1
+-(void)use_method_warn {
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+
+ func(^{
+ dispatch_semaphore_signal(sema);
+ });
+ dispatch_semaphore_wait(sema, 100);
+}
+@end
+
+
+// No warnings: class name contains "mock"
+@interface Mock1 : NSObject
+-(void)use_method_warn;
+@end
+
+@implementation Mock1
+-(void)use_method_warn {
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+
+ func(^{
+ dispatch_semaphore_signal(sema);
+ });
+ dispatch_semaphore_wait(sema, 100);
+}
+@end
+
+void dispatch_group_wait_func(MyInterface1 *M) {
+ dispatch_group_t group = dispatch_group_create();
+ dispatch_group_enter(group);
+
+ func(^{
+ dispatch_group_leave(group);
+ });
+ dispatch_group_wait(group, 100); // expected-warning{{Waiting on a callback using a group}}
+}
+
+
+void dispatch_group_wait_cfunc(MyInterface1 *M) {
+ dispatch_group_t group = dispatch_group_create();
+ dispatch_group_enter(group);
+ [M acceptBlock:^{
+ dispatch_group_leave(group);
+ }];
+ dispatch_group_wait(group, 100); // expected-warning{{Waiting on a callback using a group}}
+}
+
+void dispatch_group_and_semaphore_use(MyInterface1 *M) {
+ dispatch_group_t group = dispatch_group_create();
+ dispatch_group_enter(group);
+ [M acceptBlock:^{
+ dispatch_group_leave(group);
+ }];
+ dispatch_group_wait(group, 100); // expected-warning{{Waiting on a callback using a group}}
+
+ dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);
+
+ [M acceptBlock:^{
+ dispatch_semaphore_signal(sema1);
+ }];
+ dispatch_semaphore_wait(sema1, 100); // expected-warning{{Waiting on a callback using a semaphore}}
+}
+
+void no_warn_on_nonzero_semaphore(MyInterface1 *M) {
+ dispatch_semaphore_t sema1 = dispatch_semaphore_create(1);
+
+ [M acceptBlock:^{
+ dispatch_semaphore_signal(sema1);
+ }];
+ dispatch_semaphore_wait(sema1, 100); // no-warning
+}
+
diff --git a/test/Analysis/globals.cpp b/test/Analysis/globals.cpp
new file mode 100644
index 000000000000..5bbb241bdcf3
--- /dev/null
+++ b/test/Analysis/globals.cpp
@@ -0,0 +1,111 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s
+
+
+static const unsigned long long scull = 0;
+void static_int()
+{
+ *(int*)scull = 0; // expected-warning{{Dereference of null pointer}}
+}
+
+const unsigned long long cull = 0;
+void const_int()
+{
+ *(int*)cull = 0; // expected-warning{{Dereference of null pointer}}
+}
+
+static int * const spc = 0;
+void static_ptr()
+{
+ *spc = 0; // expected-warning{{Dereference of null pointer}}
+}
+
+int * const pc = 0;
+void const_ptr()
+{
+ *pc = 0; // expected-warning{{Dereference of null pointer}}
+}
+
+const unsigned long long cull_nonnull = 4;
+void nonnull_int()
+{
+ *(int*)(cull_nonnull - 4) = 0; // expected-warning{{Dereference of null pointer}}
+}
+
+int * const pc_nonnull = (int*)sizeof(int);
+void nonnull_ptr()
+{
+ *(pc_nonnull - 1) = 0; // expected-warning{{Dereference of null pointer}}
+}
+
+int * const constcast = const_cast<int * const>((int*)sizeof(int));
+void cast1()
+{
+ *(constcast - 1) = 0; // expected-warning{{Dereference of null pointer}}
+}
+
+int * const recast = reinterpret_cast<int*>(sizeof(int));
+void cast2()
+{
+ *(recast - 1) = 0; // expected-warning{{Dereference of null pointer}}
+}
+
+int * const staticcast = static_cast<int * const>((int*)sizeof(int));
+void cast3()
+{
+ *(staticcast - 1) = 0; // expected-warning{{Dereference of null pointer}}
+}
+
+struct Foo { int a; };
+Foo * const dyncast = dynamic_cast<Foo * const>((Foo*)sizeof(Foo));
+void cast4()
+{
+ // Do not handle dynamic_cast for now, because it may change the pointer value.
+ (dyncast - 1)->a = 0; // no-warning
+}
+
+typedef int * const intptrconst;
+int * const funccast = intptrconst(sizeof(int));
+void cast5()
+{
+ *(funccast - 1) = 0; // expected-warning{{Dereference of null pointer}}
+}
+
+struct S1
+{
+ int * p;
+};
+const S1 s1 = {
+ .p = (int*)sizeof(int)
+};
+void conststruct()
+{
+ *(s1.p - 1) = 0; // expected-warning{{Dereference of null pointer}}
+}
+
+struct S2
+{
+ int * const p;
+};
+S2 s2 = {
+ .p = (int*)sizeof(int)
+};
+void constfield()
+{
+ *(s2.p - 1) = 0; // expected-warning{{Dereference of null pointer}}
+}
+
+int * const parr[1] = { (int*)sizeof(int) };
+void constarr()
+{
+ *(parr[0] - 1) = 0; // expected-warning{{Dereference of null pointer}}
+}
+
+struct S3
+{
+ int * p = (int*)sizeof(int);
+};
+void recordinit()
+{
+ S3 s3;
+ *(s3.p - 1) = 0; // expected-warning{{Dereference of null pointer}}
+}
diff --git a/test/Analysis/gtest.cpp b/test/Analysis/gtest.cpp
index 98f415eea456..e68303d5492a 100644
--- a/test/Analysis/gtest.cpp
+++ b/test/Analysis/gtest.cpp
@@ -1,6 +1,5 @@
//RUN: %clang_analyze_cc1 -cc1 -std=c++11 -analyzer-checker=core,apiModeling.google.GTest,debug.ExprInspection -analyzer-eagerly-assume %s -verify
//RUN: %clang_analyze_cc1 -cc1 -std=c++11 -analyzer-checker=core,apiModeling.google.GTest,debug.ExprInspection -analyzer-eagerly-assume -DGTEST_VERSION_1_8_AND_LATER=1 %s -verify
-//RUN: %clang_analyze_cc1 -cc1 -std=c++11 -analyzer-checker=core,apiModeling.google.GTest,debug.ExprInspection -analyzer-eagerly-assume -analyzer-config cfg-temporary-dtors=true %s -verify
void clang_analyzer_eval(int);
void clang_analyzer_warnIfReached();
@@ -155,13 +154,11 @@ void testConstrainState(int p) {
void testAssertSymbolicPtr(const bool *b) {
ASSERT_TRUE(*b); // no-crash
- // FIXME: Our solver doesn't handle this well yet.
- clang_analyzer_eval(*b); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(*b); // expected-warning{{TRUE}}
}
void testAssertSymbolicRef(const bool &b) {
ASSERT_TRUE(b); // no-crash
- // FIXME: Our solver doesn't handle this well yet.
- clang_analyzer_eval(b); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(b); // expected-warning{{TRUE}}
}
diff --git a/test/Analysis/hangs.c b/test/Analysis/hangs.c
new file mode 100644
index 000000000000..b109bcb52fdb
--- /dev/null
+++ b/test/Analysis/hangs.c
@@ -0,0 +1,30 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker core -verify %s
+
+// expected-no-diagnostics
+
+// Stuff that used to hang.
+
+int g();
+
+int f(int y) {
+ return y + g();
+}
+
+int produce_a_very_large_symbol(int x) {
+ return f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(
+ f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(x))))))))))))))))))))))))))))))));
+}
+
+void produce_an_exponentially_exploding_symbol(int x, int y) {
+ x += y; y += x + g();
+ x += y; y += x + g();
+ x += y; y += x + g();
+ x += y; y += x + g();
+ x += y; y += x + g();
+ x += y; y += x + g();
+ x += y; y += x + g();
+ x += y; y += x + g();
+ x += y; y += x + g();
+ x += y; y += x + g();
+ x += y; y += x + g();
+}
diff --git a/test/Analysis/html_diagnostics/relevant_lines/goto.c b/test/Analysis/html_diagnostics/relevant_lines/goto.c
new file mode 100644
index 000000000000..fc90f1334f07
--- /dev/null
+++ b/test/Analysis/html_diagnostics/relevant_lines/goto.c
@@ -0,0 +1,13 @@
+int goto_test(int input) {
+ int *p = 0;
+ if (input)
+ goto mylabel;
+ return 0;
+mylabel:
+ return *p;
+}
+
+// RUN: rm -rf %t.output
+// RUN: %clang_analyze_cc1 -analyze -analyzer-checker=core -analyzer-output html -o %t.output %s
+// RUN: cat %t.output/* | FileCheck %s --match-full-lines
+// CHECK: var relevant_lines = {"1": {"1": 1, "2": 1, "3": 1, "4": 1, "6": 1, "7": 1}};
diff --git a/test/Analysis/html_diagnostics/relevant_lines/header.h b/test/Analysis/html_diagnostics/relevant_lines/header.h
new file mode 100644
index 000000000000..579b66a1cb31
--- /dev/null
+++ b/test/Analysis/html_diagnostics/relevant_lines/header.h
@@ -0,0 +1,12 @@
+#define deref(X) (*X)
+
+char helper(
+ char *out,
+ int doDereference) {
+ if (doDereference) {
+ return deref(out);
+ } else {
+ return 'x';
+ }
+ return 'c';
+}
diff --git a/test/Analysis/html_diagnostics/relevant_lines/macros_same_file.c b/test/Analysis/html_diagnostics/relevant_lines/macros_same_file.c
new file mode 100644
index 000000000000..5b3556526add
--- /dev/null
+++ b/test/Analysis/html_diagnostics/relevant_lines/macros_same_file.c
@@ -0,0 +1,15 @@
+#define deref(X) (*X)
+
+int f(int coin) {
+ if (coin) {
+ int *x = 0;
+ return deref(x);
+ } else {
+ return 0;
+ }
+}
+
+// RUN: rm -rf %t.output
+// RUN: %clang_analyze_cc1 -analyze -analyzer-checker=core -analyzer-output html -o %t.output %s
+// RUN: cat %t.output/* | FileCheck %s --match-full-lines
+// CHECK: var relevant_lines = {"1": {"3": 1, "4": 1, "5": 1, "6": 1}};
diff --git a/test/Analysis/html_diagnostics/relevant_lines/multifile.c b/test/Analysis/html_diagnostics/relevant_lines/multifile.c
new file mode 100644
index 000000000000..3abffd609b5b
--- /dev/null
+++ b/test/Analysis/html_diagnostics/relevant_lines/multifile.c
@@ -0,0 +1,14 @@
+#include "header.h"
+
+int f(int coin) {
+ char *p = 0;
+ if (coin) {
+ return helper(p, coin);
+ }
+ return 0;
+}
+
+// RUN: rm -rf %t.output
+// RUN: %clang_analyze_cc1 -analyze -analyzer-checker=core -analyzer-output html -o %t.output %s
+// RUN: cat %t.output/* | FileCheck %s --match-full-lines
+// CHECK: var relevant_lines = {"1": {"3": 1, "4": 1, "5": 1, "6": 1}, "3": {"3": 1, "4": 1, "5": 1, "6": 1, "7": 1}};
diff --git a/test/Analysis/html_diagnostics/relevant_lines/multiline_func_def.c b/test/Analysis/html_diagnostics/relevant_lines/multiline_func_def.c
new file mode 100644
index 000000000000..35158a46868c
--- /dev/null
+++ b/test/Analysis/html_diagnostics/relevant_lines/multiline_func_def.c
@@ -0,0 +1,16 @@
+int f(
+ int coin,
+ int paramA,
+ int paramB) {
+ if (coin) {
+ int *x = 0;
+ return *x;
+ } else {
+ return 0;
+ }
+}
+
+// RUN: rm -rf %t.output
+// RUN: %clang_analyze_cc1 -analyze -analyzer-checker=core -analyzer-output html -o %t.output %s
+// RUN: cat %t.output/* | FileCheck %s --match-full-lines
+// CHECK: var relevant_lines = {"1": {"1": 1, "2": 1, "3": 1, "4": 1, "5": 1, "6": 1, "7": 1}};
diff --git a/test/Analysis/html_diagnostics/relevant_lines/notexecutedlines.c b/test/Analysis/html_diagnostics/relevant_lines/notexecutedlines.c
new file mode 100644
index 000000000000..3c723aa93349
--- /dev/null
+++ b/test/Analysis/html_diagnostics/relevant_lines/notexecutedlines.c
@@ -0,0 +1,12 @@
+int f() {
+ int zzz = 200;
+ zzz += 100;
+ return 0;
+}
+
+// Show line with the warning even if it wasn't executed (e.g. warning given
+// by path-insensitive analysis).
+// RUN: rm -rf %t.output
+// RUN: %clang_analyze_cc1 -analyze -analyzer-checker=core,deadcode -analyzer-output html -o %t.output %s
+// RUN: cat %t.output/* | FileCheck %s --match-full-lines
+// CHECK: var relevant_lines = {"1": {"3": 1}};
diff --git a/test/Analysis/html_diagnostics/relevant_lines/objcmethods.m b/test/Analysis/html_diagnostics/relevant_lines/objcmethods.m
new file mode 100644
index 000000000000..41a4c1d2e097
--- /dev/null
+++ b/test/Analysis/html_diagnostics/relevant_lines/objcmethods.m
@@ -0,0 +1,19 @@
+@interface I
+- (int)func;
+@end
+
+@implementation I
+- (int)func:(int *)param {
+ return *param;
+}
+@end
+
+void foo(I *i) {
+ int *x = 0;
+ [i func:x];
+}
+
+// RUN: rm -rf %t.output
+// RUN: %clang_analyze_cc1 -analyze -analyzer-checker=core -analyzer-output html -o %t.output -Wno-objc-root-class %s
+// RUN: cat %t.output/* | FileCheck %s
+// CHECK: var relevant_lines = {"1": {"6": 1, "7": 1, "11": 1, "12": 1, "13": 1}};
diff --git a/test/Analysis/html_diagnostics/relevant_lines/simple_conditional.c b/test/Analysis/html_diagnostics/relevant_lines/simple_conditional.c
new file mode 100644
index 000000000000..769859dea5ef
--- /dev/null
+++ b/test/Analysis/html_diagnostics/relevant_lines/simple_conditional.c
@@ -0,0 +1,13 @@
+int f(int coin) {
+ if (coin) {
+ int *x = 0;
+ return *x;
+ } else {
+ return 0;
+ }
+}
+
+// RUN: rm -rf %t.output
+// RUN: %clang_analyze_cc1 -analyze -analyzer-checker=core -analyzer-output html -o %t.output %s
+// RUN: cat %t.output/* | FileCheck %s --match-full-lines
+// CHECK: var relevant_lines = {"1": {"1": 1, "2": 1, "3": 1, "4": 1}};
diff --git a/test/Analysis/html_diagnostics/relevant_lines/switch.c b/test/Analysis/html_diagnostics/relevant_lines/switch.c
new file mode 100644
index 000000000000..e9032cdece9d
--- /dev/null
+++ b/test/Analysis/html_diagnostics/relevant_lines/switch.c
@@ -0,0 +1,20 @@
+enum E {
+ A, B, C
+};
+
+int f(enum E input) {
+ int *x = 0;
+ switch (input) {
+ case A:
+ return 1;
+ case B:
+ return 0;
+ case C:
+ return *x;
+ }
+}
+
+// RUN: rm -rf %t.output
+// RUN: %clang_analyze_cc1 -analyze -analyzer-checker=core -analyzer-output html -o %t.output %s
+// RUN: cat %t.output/* | FileCheck %s --match-full-lines
+// CHECK: var relevant_lines = {"1": {"5": 1, "6": 1, "7": 1, "12": 1, "13": 1}};
diff --git a/test/Analysis/html_diagnostics/relevant_lines/switch_default.c b/test/Analysis/html_diagnostics/relevant_lines/switch_default.c
new file mode 100644
index 000000000000..b14e3f9fa8fd
--- /dev/null
+++ b/test/Analysis/html_diagnostics/relevant_lines/switch_default.c
@@ -0,0 +1,20 @@
+enum E {
+ A, B, C
+};
+
+int f(enum E input) {
+ int *x = 0;
+ switch (input) {
+ case A:
+ return 1;
+ case B:
+ return 0;
+ default:
+ return *x;
+ }
+}
+
+// RUN: rm -rf %t.output
+// RUN: %clang_analyze_cc1 -analyze -analyzer-checker=core -analyzer-output html -o %t.output %s
+// RUN: cat %t.output/* | FileCheck %s --match-full-lines
+// CHECK: var relevant_lines = {"1": {"5": 1, "6": 1, "7": 1, "12": 1, "13": 1}};
diff --git a/test/Analysis/html_diagnostics/relevant_lines/unused_header.c b/test/Analysis/html_diagnostics/relevant_lines/unused_header.c
new file mode 100644
index 000000000000..4b77c651eddd
--- /dev/null
+++ b/test/Analysis/html_diagnostics/relevant_lines/unused_header.c
@@ -0,0 +1,19 @@
+#include "header.h"
+
+int f(int coin) {
+ if (coin) {
+ int *x = 0;
+ return *x;
+ } else {
+ return 0;
+ }
+}
+
+int v(int coin) {
+ return coin;
+}
+
+// RUN: rm -rf %t.output
+// RUN: %clang_analyze_cc1 -analyze -analyzer-checker=core -analyzer-output html -o %t.output %s
+// RUN: cat %t.output/* | FileCheck %s --match-full-lines
+// CHECK: var relevant_lines = {"1": {"3": 1, "4": 1, "5": 1, "6": 1}};
diff --git a/test/Analysis/implicit-ctor-undef-value.cpp b/test/Analysis/implicit-ctor-undef-value.cpp
new file mode 100644
index 000000000000..87824c0533a0
--- /dev/null
+++ b/test/Analysis/implicit-ctor-undef-value.cpp
@@ -0,0 +1,75 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=text -verify %s
+
+namespace implicit_constructor {
+struct S {
+public:
+ S() {}
+ S(const S &) {}
+};
+
+// Warning is in a weird position because the body of the constructor is
+// missing. Specify which field is being assigned.
+class C { // expected-warning{{Value assigned to field 'y' in implicit constructor is garbage or undefined}}
+ // expected-note@-1{{Value assigned to field 'y' in implicit constructor is garbage or undefined}}
+ int x, y;
+ S s;
+
+public:
+ C(): x(0) {}
+};
+
+void test() {
+ C c1;
+ C c2(c1); // expected-note{{Calling implicit copy constructor for 'C'}}
+}
+} // end namespace implicit_constructor
+
+
+namespace explicit_constructor {
+class C {
+ int x, y;
+
+public:
+ C(): x(0) {}
+ // It is not necessary to specify which field is being assigned to.
+ C(const C &c):
+ x(c.x),
+ y(c.y) // expected-warning{{Assigned value is garbage or undefined}}
+ // expected-note@-1{{Assigned value is garbage or undefined}}
+ {}
+};
+
+void test() {
+ C c1;
+ C c2(c1); // expected-note{{Calling copy constructor for 'C'}}
+}
+} // end namespace explicit_constructor
+
+
+namespace base_class_constructor {
+struct S {
+public:
+ S() {}
+ S(const S &) {}
+};
+
+class C { // expected-warning{{Value assigned to field 'y' in implicit constructor is garbage or undefined}}
+ // expected-note@-1{{Value assigned to field 'y' in implicit constructor is garbage or undefined}}
+ int x, y;
+ S s;
+
+public:
+ C(): x(0) {}
+};
+
+class D: public C {
+public:
+ D(): C() {}
+};
+
+void test() {
+ D d1;
+ D d2(d1); // expected-note {{Calling implicit copy constructor for 'D'}}
+ // expected-note@-1{{Calling implicit copy constructor for 'C'}}
+}
+} // end namespace base_class_constructor
diff --git a/test/Analysis/index-type.c b/test/Analysis/index-type.c
index b86913b996f6..123dcd65bd7c 100644
--- a/test/Analysis/index-type.c
+++ b/test/Analysis/index-type.c
@@ -1,5 +1,5 @@
-// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,alpha.security.ArrayBoundV2 -verify %s
-// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -analyzer-checker=core,alpha.security.ArrayBoundV2 -DM32 -verify %s
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,alpha.security.ArrayBoundV2 -Wno-implicit-function-declaration -verify %s
+// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -analyzer-checker=core,alpha.security.ArrayBoundV2 -Wno-implicit-function-declaration -DM32 -verify %s
// expected-no-diagnostics
#define UINT_MAX (~0u)
@@ -36,4 +36,23 @@ void testIndexTooBig64() {
*ptr = 42; // no-warning
}
+#define SIZE 4294967296
+
+static unsigned size;
+static void * addr;
+static unsigned buf[SIZE];
+
+void testOutOfBounds() {
+ // Not out of bounds.
+ buf[SIZE-1] = 1; // no-warning
+}
+
+void testOutOfBoundsCopy1() {
+ memcpy(buf, addr, size); // no-warning
+}
+
+void testOutOfBoundsCopy2() {
+ memcpy(addr, buf, size); // no-warning
+}
+
#endif
diff --git a/test/Analysis/initialization.c b/test/Analysis/initialization.c
new file mode 100644
index 000000000000..c1d6361f1245
--- /dev/null
+++ b/test/Analysis/initialization.c
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.builtin,debug.ExprInspection -verify %s
+
+void clang_analyzer_eval(int);
+
+void initbug() {
+ const union { float a; } u = {};
+ (void)u.a; // no-crash
+}
+
+int const parr[2] = {1};
+void constarr() {
+ int i = 2;
+ clang_analyzer_eval(parr[i]); // expected-warning{{UNDEFINED}}
+ i = 1;
+ clang_analyzer_eval(parr[i] == 0); // expected-warning{{TRUE}}
+ i = -1;
+ clang_analyzer_eval(parr[i]); // expected-warning{{UNDEFINED}}
+}
+
+struct SM {
+ int a;
+ int b;
+};
+const struct SM sm = {.a = 1};
+void multinit() {
+ clang_analyzer_eval(sm.a == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(sm.b == 0); // expected-warning{{TRUE}}
+}
diff --git a/test/Analysis/initialization.cpp b/test/Analysis/initialization.cpp
new file mode 100644
index 000000000000..db765930b6e5
--- /dev/null
+++ b/test/Analysis/initialization.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.builtin,debug.ExprInspection -verify %s
+
+void clang_analyzer_eval(int);
+
+struct S {
+ int a = 3;
+};
+S const sarr[2] = {};
+void definit() {
+ int i = 1;
+ // FIXME: Should recognize that it is 3.
+ clang_analyzer_eval(sarr[i].a); // expected-warning{{UNKNOWN}}
+}
+
+int const arr[2][2] = {};
+void arr2init() {
+ int i = 1;
+ // FIXME: Should recognize that it is 0.
+ clang_analyzer_eval(arr[i][0]); // expected-warning{{UNKNOWN}}
+}
diff --git a/test/Analysis/initializer.cpp b/test/Analysis/initializer.cpp
index 55f0a8950287..0cb68c4a9780 100644
--- a/test/Analysis/initializer.cpp
+++ b/test/Analysis/initializer.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,cplusplus.NewDeleteLeaks,debug.ExprInspection -analyzer-config c++-inlining=constructors -std=c++11 -verify %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,cplusplus.NewDeleteLeaks,debug.ExprInspection -analyzer-config c++-inlining=constructors -std=c++17 -DCPLUSPLUS17 -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,cplusplus.NewDeleteLeaks,debug.ExprInspection -analyzer-config c++-inlining=constructors -std=c++11 -DTEST_INLINABLE_ALLOCATORS -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,cplusplus.NewDeleteLeaks,debug.ExprInspection -analyzer-config c++-inlining=constructors -std=c++17 -DCPLUSPLUS17 -DTEST_INLINABLE_ALLOCATORS -verify %s
void clang_analyzer_eval(bool);
@@ -176,29 +178,6 @@ namespace ReferenceInitialization {
const MyStruct &myStruct(OtherStruct(5));
myStruct.method(); // no-warning
}
-
- struct HasMyStruct {
- const MyStruct &ms; // expected-note {{reference member declared here}}
- const MyStruct &msWithCleanups; // expected-note {{reference member declared here}}
-
- // clang's Sema issues a warning when binding a reference member to a
- // temporary value.
- HasMyStruct() : ms(5), msWithCleanups(OtherStruct(5)) {
- // expected-warning@-1 {{binding reference member 'ms' to a temporary value}}
- // expected-warning@-2 {{binding reference member 'msWithCleanups' to a temporary value}}
-
- // At this point the members are not garbage so we should not expect an
- // analyzer warning here even though binding a reference member
- // to a member is a terrible idea.
- ms.method(); // no-warning
- msWithCleanups.method(); // no-warning
- }
- };
-
- void referenceInitializeField() {
- HasMyStruct hms;
- }
-
};
namespace PR31592 {
diff --git a/test/Analysis/initializers-cfg-output.cpp b/test/Analysis/initializers-cfg-output.cpp
index ccf4db519d79..8d1039ddf34e 100644
--- a/test/Analysis/initializers-cfg-output.cpp
+++ b/test/Analysis/initializers-cfg-output.cpp
@@ -1,4 +1,14 @@
-// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=debug.DumpCFG %s 2>&1 | FileCheck %s
+// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=debug.DumpCFG -analyzer-config cfg-rich-constructors=false %s 2>&1 | FileCheck -check-prefixes=CHECK,WARNINGS %s
+// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=debug.DumpCFG -analyzer-config cfg-rich-constructors=true %s 2>&1 | FileCheck -check-prefixes=CHECK,ANALYZER %s
+
+// This file tests how we construct two different flavors of the Clang CFG -
+// the CFG used by the Sema analysis-based warnings and the CFG used by the
+// static analyzer. The difference in the behavior is checked via FileCheck
+// prefixes (WARNINGS and ANALYZER respectively). When introducing new analyzer
+// flags, no new run lines should be added - just these flags would go to the
+// respective line depending on where is it turned on and where is it turned
+// off. Feel free to add tests that test only one of the CFG flavors if you're
+// not sure how the other flavor is supposed to work in your case.
class A {
public:
@@ -53,20 +63,25 @@ class TestDelegating {
// CHECK: [B2 (ENTRY)]
// CHECK: Succs (1): B1
// CHECK: [B1]
-// CHECK: 1: (CXXConstructExpr, class A)
+// WARNINGS: 1: (CXXConstructExpr, class A)
+// ANALYZER: 1: (CXXConstructExpr, A() (Base initializer), class A)
// CHECK: 2: A([B1.1]) (Base initializer)
-// CHECK: 3: (CXXConstructExpr, class C)
+// WARNINGS: 3: (CXXConstructExpr, class C)
+// ANALYZER: 3: (CXXConstructExpr, C() (Base initializer), class C)
// CHECK: 4: C([B1.3]) (Base initializer)
-// CHECK: 5: (CXXConstructExpr, class B)
+// WARNINGS: 5: (CXXConstructExpr, class B)
+// ANALYZER: 5: (CXXConstructExpr, B() (Base initializer), class B)
// CHECK: 6: B([B1.5]) (Base initializer)
-// CHECK: 7: (CXXConstructExpr, class A)
+// WARNINGS: 7: (CXXConstructExpr, class A)
+// ANALYZER: 7: (CXXConstructExpr, A() (Base initializer), class A)
// CHECK: 8: A([B1.7]) (Base initializer)
// CHECK: 9: /*implicit*/(int)0
// CHECK: 10: i([B1.9]) (Member initializer)
// CHECK: 11: this
// CHECK: 12: [B1.11]->i
// CHECK: 13: r([B1.12]) (Member initializer)
-// CHECK: 14: (CXXConstructExpr, class A)
+// WARNINGS: 14: (CXXConstructExpr, class A)
+// ANALYZER: 14: (CXXConstructExpr, [B1.15], class A)
// CHECK: 15: A a;
// CHECK: Preds (1): B2
// CHECK: Succs (1): B0
@@ -107,7 +122,8 @@ class TestDelegating {
// CHECK: [B1]
// CHECK: 1: 2
// CHECK: 2: 3
-// CHECK: 3: [B1.1], [B1.2] (CXXConstructExpr, class TestDelegating)
+// WARNINGS: 3: [B1.1], [B1.2] (CXXConstructExpr, class TestDelegating)
+// ANALYZER: 3: [B1.1], [B1.2] (CXXConstructExpr, TestDelegating([B1.1], [B1.2]) (Delegating initializer), class TestDelegating)
// CHECK: 4: TestDelegating([B1.3]) (Delegating initializer)
// CHECK: Preds (1): B2
// CHECK: Succs (1): B0
diff --git a/test/Analysis/inline-plist.c b/test/Analysis/inline-plist.c
index 441bb48b1055..457fb266420f 100644
--- a/test/Analysis/inline-plist.c
+++ b/test/Analysis/inline-plist.c
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 %s -analyzer-checker=core.NullDereference,core.DivideZero -fblocks -analyzer-output=text -analyzer-config suppress-null-return-paths=false -verify %s
-// RUN: %clang_analyze_cc1 %s -analyzer-checker=core.NullDereference,core.DivideZero -fblocks -analyzer-output=plist -analyzer-config suppress-null-return-paths=false -analyzer-config path-diagnostics-alternate=false -o %t
+// RUN: %clang_analyze_cc1 %s -analyzer-checker=core.NullDereference,core.DivideZero -fblocks -analyzer-output=plist -analyzer-config suppress-null-return-paths=false -o %t
// RUN: FileCheck -input-file %t %s
// <rdar://problem/10967815>
@@ -210,40 +210,6 @@ void test_block_arg() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
// CHECK-NEXT: <key>col</key><integer>11</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -306,40 +272,6 @@ void test_block_arg() {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>27</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>27</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>27</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>27</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -660,40 +592,6 @@ void test_block_arg() {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -1419,6 +1317,40 @@ void test_block_arg() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>70</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>70</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>70</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>70</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>70</integer>
// CHECK-NEXT: <key>col</key><integer>6</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1671,6 +1603,40 @@ void test_block_arg() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>78</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>78</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>78</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>78</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>78</integer>
// CHECK-NEXT: <key>col</key><integer>6</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1923,6 +1889,40 @@ void test_block_arg() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>86</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>86</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>86</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>86</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>86</integer>
// CHECK-NEXT: <key>col</key><integer>6</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
diff --git a/test/Analysis/inline-unique-reports.c b/test/Analysis/inline-unique-reports.c
index f827f88deb1d..0044d14e5224 100644
--- a/test/Analysis/inline-unique-reports.c
+++ b/test/Analysis/inline-unique-reports.c
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 %s -analyzer-checker=core.NullDereference -analyzer-output=plist -analyzer-config path-diagnostics-alternate=false -o %t > /dev/null 2>&1
+// RUN: %clang_analyze_cc1 %s -analyzer-checker=core.NullDereference -analyzer-output=plist -o %t > /dev/null 2>&1
// RUN: FileCheck -input-file %t %s
static inline bug(int *p) {
@@ -85,40 +85,6 @@ void test_bug_2() {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
diff --git a/test/Analysis/inline.cpp b/test/Analysis/inline.cpp
index 76eee5beffac..c362fc93090b 100644
--- a/test/Analysis/inline.cpp
+++ b/test/Analysis/inline.cpp
@@ -315,17 +315,13 @@ namespace OperatorNew {
int value;
IntWrapper(int input) : value(input) {
- // We don't want this constructor to be inlined unless we can actually
- // use the proper region for operator new.
- // See PR12014 and <rdar://problem/12180598>.
- clang_analyzer_checkInlined(false); // no-warning
+ clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
}
};
void test() {
IntWrapper *obj = new IntWrapper(42);
- // should be TRUE
- clang_analyzer_eval(obj->value == 42); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(obj->value == 42); // expected-warning{{TRUE}}
delete obj;
}
@@ -335,8 +331,9 @@ namespace OperatorNew {
clang_analyzer_eval(alias == obj); // expected-warning{{TRUE}}
- // should be TRUE
- clang_analyzer_eval(obj->value == 42); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(obj->value == 42); // expected-warning{{TRUE}}
+ // Because malloc() was never free()d:
+ // expected-warning@-2{{Potential leak of memory pointed to by 'alias'}}
}
}
diff --git a/test/Analysis/inlining/containers.cpp b/test/Analysis/inlining/containers.cpp
index 16e006b345f2..ffa3b511344a 100644
--- a/test/Analysis/inlining/containers.cpp
+++ b/test/Analysis/inlining/containers.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config c++-inlining=destructors -analyzer-config c++-container-inlining=false -verify %s
// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config c++-inlining=destructors -analyzer-config c++-container-inlining=true -DINLINE=1 -verify %s
+// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config c++-inlining=destructors -analyzer-config c++-container-inlining=false -DTEST_INLINABLE_ALLOCATORS -verify %s
+// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config c++-inlining=destructors -analyzer-config c++-container-inlining=true -DTEST_INLINABLE_ALLOCATORS -DINLINE=1 -verify %s
#ifndef HEADER
diff --git a/test/Analysis/inlining/eager-reclamation-path-notes.c b/test/Analysis/inlining/eager-reclamation-path-notes.c
index 7c0f0ec8f52e..a31ab9ed0ad9 100644
--- a/test/Analysis/inlining/eager-reclamation-path-notes.c
+++ b/test/Analysis/inlining/eager-reclamation-path-notes.c
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=text -analyzer-config graph-trim-interval=5 -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file -analyzer-config graph-trim-interval=5 -analyzer-config path-diagnostics-alternate=false %s -o %t.plist
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file -analyzer-config graph-trim-interval=5 %s -o %t.plist
// RUN: FileCheck --input-file=%t.plist %s
void use(int *ptr, int val) {
@@ -99,46 +99,12 @@ void testChainedCalls() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -398,40 +364,6 @@ void testChainedCalls() {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -538,74 +470,6 @@ void testChainedCalls() {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
diff --git a/test/Analysis/inlining/eager-reclamation-path-notes.cpp b/test/Analysis/inlining/eager-reclamation-path-notes.cpp
index f77a19f9965f..9a9b01c3bdd4 100644
--- a/test/Analysis/inlining/eager-reclamation-path-notes.cpp
+++ b/test/Analysis/inlining/eager-reclamation-path-notes.cpp
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=text -analyzer-config graph-trim-interval=5 -analyzer-config suppress-null-return-paths=false -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file -analyzer-config graph-trim-interval=5 -analyzer-config suppress-null-return-paths=false -analyzer-config path-diagnostics-alternate=false %s -o %t.plist
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file -analyzer-config graph-trim-interval=5 -analyzer-config suppress-null-return-paths=false %s -o %t.plist
// RUN: FileCheck --input-file=%t.plist %s
typedef struct {
diff --git a/test/Analysis/inlining/false-positive-suppression.c b/test/Analysis/inlining/false-positive-suppression.c
index 4931695ef127..4d472e0861e0 100644
--- a/test/Analysis/inlining/false-positive-suppression.c
+++ b/test/Analysis/inlining/false-positive-suppression.c
@@ -111,14 +111,12 @@ void testInlineCheckInNestedMacro(int *p) {
*p = 1; // no-warning
}
-// If there is a check in a macro that is not function-like, don't treat
-// it like a function so don't suppress.
#define NON_FUNCTION_MACRO_WITH_CHECK ( ((p) != 0) ? *p : 17)
void testNonFunctionMacro(int *p) {
int i = NON_FUNCTION_MACRO_WITH_CHECK ;
(void)i;
- *p = 1; // expected-warning {{Dereference of null pointer (loaded from variable 'p')}}
+ *p = 1; // no-warning
}
@@ -163,6 +161,7 @@ void testNestedDisjunctiveMacro2(int *p, int *q) {
}
+
// Here the check is entirely in non-macro code even though the code itself
// is a macro argument.
#define MACRO_DO_IT(a) (a)
@@ -171,6 +170,15 @@ void testErrorInArgument(int *p) {
(void)i;
}
+// No warning should be emitted if dereference is performed from a different
+// macro.
+#define MACRO_CHECK(a) if (a) {}
+#define MACRO_DEREF(a) (*a)
+int testDifferentMacro(int *p) {
+ MACRO_CHECK(p);
+ return MACRO_DEREF(p); // no-warning
+}
+
// --------------------------
// "Suppression suppression"
// --------------------------
diff --git a/test/Analysis/inlining/inline-defensive-checks.c b/test/Analysis/inlining/inline-defensive-checks.c
index ca61395fc0d4..d290cf25f42f 100644
--- a/test/Analysis/inlining/inline-defensive-checks.c
+++ b/test/Analysis/inlining/inline-defensive-checks.c
@@ -159,8 +159,7 @@ void idcTrackZeroValueThroughUnaryPointerOperatorsWithOffset1(struct S *s) {
void idcTrackZeroValueThroughUnaryPointerOperatorsWithOffset2(struct S *s) {
idc(s);
int *x = &(s->f2) - 1;
- // FIXME: Should not warn.
- *x = 7; // expected-warning{{Dereference of null pointer}}
+ *x = 7; // no-warning
}
void idcTrackZeroValueThroughUnaryPointerOperatorsWithAssignment(struct S *s) {
diff --git a/test/Analysis/inlining/inline-defensive-checks.cpp b/test/Analysis/inlining/inline-defensive-checks.cpp
index eaae8d2ae28f..6fb0e1cd70b0 100644
--- a/test/Analysis/inlining/inline-defensive-checks.cpp
+++ b/test/Analysis/inlining/inline-defensive-checks.cpp
@@ -84,3 +84,20 @@ void testRefToField(Bar *b) {
int &x = b->x; // no-warning
x = 5;
}
+
+namespace get_deref_expr_with_cleanups {
+struct S {
+~S();
+};
+S *conjure();
+// The argument won't be used, but it'll cause cleanups
+// to appear around the call site.
+S *get_conjured(S _) {
+ S *s = conjure();
+ if (s) {}
+ return s;
+}
+void test_conjured() {
+ S &s = *get_conjured(S()); // no-warning
+}
+} // namespace get_deref_expr_with_cleanups
diff --git a/test/Analysis/inlining/path-notes.c b/test/Analysis/inlining/path-notes.c
index 95adee30a9af..15441d4a3ccd 100644
--- a/test/Analysis/inlining/path-notes.c
+++ b/test/Analysis/inlining/path-notes.c
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=text -analyzer-config suppress-null-return-paths=false -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file -analyzer-config suppress-null-return-paths=false -analyzer-config path-diagnostics-alternate=false %s -o %t.plist
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file -analyzer-config suppress-null-return-paths=false %s -o %t.plist
// RUN: FileCheck --input-file=%t.plist %s
void zero(int **p) {
@@ -140,6 +140,22 @@ void test4(int **p) {
// expected-note@-1 {{Dereference of null pointer}}
}
+void boringCallee() {
+}
+
+void interestingCallee(int *x) {
+ *x = 0; // expected-note{{The value 0 is assigned to 'x'}}
+ boringCallee(); // no-note
+}
+
+int testBoringCalleeOfInterestingCallee() {
+ int x;
+ interestingCallee(&x); // expected-note{{Calling 'interestingCallee'}}
+ // expected-note@-1{{Returning from 'interestingCallee'}}
+ return 1 / x; // expected-warning{{Division by zero}}
+ // expected-note@-1{{Division by zero}}
+}
+
// CHECK: <key>diagnostics</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
@@ -302,6 +318,40 @@ void test4(int **p) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>14</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>14</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>14</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>14</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>14</integer>
// CHECK-NEXT: <key>col</key><integer>6</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1030,40 +1080,6 @@ void test4(int **p) {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -1270,12 +1286,12 @@ void test4(int **p) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -1577,40 +1593,6 @@ void test4(int **p) {
// CHECK-NEXT: <string>Returning from &apos;getZero&apos;</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -1976,6 +1958,40 @@ void test4(int **p) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>83</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>83</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>83</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>83</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>83</integer>
// CHECK-NEXT: <key>col</key><integer>6</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -2354,6 +2370,40 @@ void test4(int **p) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>92</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>92</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>92</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>92</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>92</integer>
// CHECK-NEXT: <key>col</key><integer>6</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -2677,6 +2727,40 @@ void test4(int **p) {
// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>103</integer>
+// CHECK-NEXT: <key>col</key><integer>14</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>103</integer>
+// CHECK-NEXT: <key>col</key><integer>20</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>103</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>103</integer>
+// CHECK-NEXT: <key>col</key><integer>12</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -3139,6 +3223,40 @@ void test4(int **p) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>132</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>132</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>132</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>132</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>132</integer>
// CHECK-NEXT: <key>col</key><integer>24</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -3377,4 +3495,290 @@ void test4(int **p) {
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>path</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>152</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>152</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>153</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>153</integer>
+// CHECK-NEXT: <key>col</key><integer>19</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>153</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>153</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>153</integer>
+// CHECK-NEXT: <key>col</key><integer>23</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Calling &apos;interestingCallee&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Calling &apos;interestingCallee&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>146</integer>
+// CHECK-NEXT: <key>col</key><integer>1</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>depth</key><integer>1</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Entered call from &apos;testBoringCalleeOfInterestingCallee&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Entered call from &apos;testBoringCalleeOfInterestingCallee&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>146</integer>
+// CHECK-NEXT: <key>col</key><integer>1</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>146</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>147</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>147</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>147</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>147</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>147</integer>
+// CHECK-NEXT: <key>col</key><integer>8</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>1</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>The value 0 is assigned to &apos;x&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>The value 0 is assigned to &apos;x&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>147</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>147</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>148</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>148</integer>
+// CHECK-NEXT: <key>col</key><integer>14</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>153</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>153</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>153</integer>
+// CHECK-NEXT: <key>col</key><integer>23</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Returning from &apos;interestingCallee&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Returning from &apos;interestingCallee&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>153</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>153</integer>
+// CHECK-NEXT: <key>col</key><integer>19</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>155</integer>
+// CHECK-NEXT: <key>col</key><integer>12</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>155</integer>
+// CHECK-NEXT: <key>col</key><integer>12</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>155</integer>
+// CHECK-NEXT: <key>col</key><integer>12</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>155</integer>
+// CHECK-NEXT: <key>col</key><integer>10</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>155</integer>
+// CHECK-NEXT: <key>col</key><integer>14</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Division by zero</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Division by zero</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Division by zero</string>
+// CHECK-NEXT: <key>category</key><string>Logic error</string>
+// CHECK-NEXT: <key>type</key><string>Division by zero</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DivideZero</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>fcd480c0f73d071bac6f908387893e26</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>testBoringCalleeOfInterestingCallee</string>
+// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>155</integer>
+// CHECK-NEXT: <key>col</key><integer>12</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
diff --git a/test/Analysis/inlining/path-notes.cpp b/test/Analysis/inlining/path-notes.cpp
index 4d0b899e7cf7..e475399f605f 100644
--- a/test/Analysis/inlining/path-notes.cpp
+++ b/test/Analysis/inlining/path-notes.cpp
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=text -analyzer-config c++-inlining=destructors -std=c++11 -verify -Wno-tautological-undefined-compare %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file -analyzer-config c++-inlining=destructors -std=c++11 -analyzer-config path-diagnostics-alternate=false %s -o %t.plist -Wno-tautological-undefined-compare
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file -analyzer-config c++-inlining=destructors -std=c++11 %s -o %t.plist -Wno-tautological-undefined-compare
// RUN: FileCheck --input-file=%t.plist %s
class Foo {
@@ -324,40 +324,6 @@ namespace PR17746 {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>32</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
@@ -560,40 +526,6 @@ namespace PR17746 {
// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -671,40 +603,6 @@ namespace PR17746 {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -901,40 +799,6 @@ namespace PR17746 {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>44</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
@@ -962,40 +826,6 @@ namespace PR17746 {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -1235,6 +1065,40 @@ namespace PR17746 {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>112</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>112</integer>
+// CHECK-NEXT: <key>col</key><integer>11</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>112</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>112</integer>
+// CHECK-NEXT: <key>col</key><integer>11</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>112</integer>
// CHECK-NEXT: <key>col</key><integer>13</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1277,6 +1141,40 @@ namespace PR17746 {
// CHECK-NEXT: <string>Calling implicit default constructor for &apos;Wrapper&apos;</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>93</integer>
+// CHECK-NEXT: <key>col</key><integer>9</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>93</integer>
+// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>93</integer>
+// CHECK-NEXT: <key>col</key><integer>9</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>93</integer>
+// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -1485,6 +1383,40 @@ namespace PR17746 {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>120</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>120</integer>
+// CHECK-NEXT: <key>col</key><integer>11</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>120</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>120</integer>
+// CHECK-NEXT: <key>col</key><integer>11</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>120</integer>
// CHECK-NEXT: <key>col</key><integer>13</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1527,6 +1459,40 @@ namespace PR17746 {
// CHECK-NEXT: <string>Calling implicit copy constructor for &apos;Wrapper&apos;</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>93</integer>
+// CHECK-NEXT: <key>col</key><integer>9</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>93</integer>
+// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>93</integer>
+// CHECK-NEXT: <key>col</key><integer>9</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>93</integer>
+// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -1735,12 +1701,12 @@ namespace PR17746 {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
+// CHECK-NEXT: <key>col</key><integer>18</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -1756,12 +1722,12 @@ namespace PR17746 {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
+// CHECK-NEXT: <key>col</key><integer>18</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -1811,6 +1777,40 @@ namespace PR17746 {
// CHECK-NEXT: <string>Calling defaulted move constructor for &apos;MovableWrapper&apos;</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>102</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>102</integer>
+// CHECK-NEXT: <key>col</key><integer>18</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>102</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>102</integer>
+// CHECK-NEXT: <key>col</key><integer>18</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -1989,40 +1989,6 @@ namespace PR17746 {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>133</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>133</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>133</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>133</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>134</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
@@ -2129,6 +2095,40 @@ namespace PR17746 {
// CHECK-NEXT: <string>Calling implicit copy assignment operator for &apos;Wrapper&apos;</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>93</integer>
+// CHECK-NEXT: <key>col</key><integer>9</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>93</integer>
+// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>93</integer>
+// CHECK-NEXT: <key>col</key><integer>9</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>93</integer>
+// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -2309,40 +2309,6 @@ namespace PR17746 {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>142</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>142</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>142</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>142</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>143</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
@@ -2407,12 +2373,12 @@ namespace PR17746 {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -2663,40 +2629,6 @@ namespace PR17746 {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>151</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
@@ -2788,6 +2720,40 @@ namespace PR17746 {
// CHECK-NEXT: <string>Calling implicit destructor for &apos;Wrapper&apos;</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>93</integer>
+// CHECK-NEXT: <key>col</key><integer>9</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>93</integer>
+// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>93</integer>
+// CHECK-NEXT: <key>col</key><integer>9</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>93</integer>
+// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -3770,40 +3736,6 @@ namespace PR17746 {
// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>205</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>205</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>205</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>205</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -3950,6 +3882,40 @@ namespace PR17746 {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>197</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>197</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>197</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>197</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>197</integer>
// CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -4269,6 +4235,40 @@ namespace PR17746 {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>221</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>221</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>221</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>221</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>221</integer>
// CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -4561,6 +4561,40 @@ namespace PR17746 {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>243</integer>
+// CHECK-NEXT: <key>col</key><integer>2</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>243</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>243</integer>
+// CHECK-NEXT: <key>col</key><integer>2</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>243</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>243</integer>
// CHECK-NEXT: <key>col</key><integer>11</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -4959,40 +4993,6 @@ namespace PR17746 {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>269</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>269</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>269</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>269</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>269</integer>
// CHECK-NEXT: <key>col</key><integer>13</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
diff --git a/test/Analysis/inlining/path-notes.m b/test/Analysis/inlining/path-notes.m
index 5bfd41d95a75..a372dab6bb4d 100644
--- a/test/Analysis/inlining/path-notes.m
+++ b/test/Analysis/inlining/path-notes.m
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount -analyzer-output=text -analyzer-config suppress-null-return-paths=false -fblocks -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount -analyzer-output=plist-multi-file -analyzer-config suppress-null-return-paths=false -analyzer-config path-diagnostics-alternate=false -fblocks %s -o %t.plist
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount -analyzer-output=plist-multi-file -analyzer-config suppress-null-return-paths=false -fblocks %s -o %t.plist
// RUN: FileCheck --input-file=%t.plist %s
typedef struct dispatch_queue_s *dispatch_queue_t;
@@ -362,40 +362,6 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -425,40 +391,6 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <string>&apos;p&apos; not called because the receiver is nil</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -525,12 +457,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -1513,6 +1445,35 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <string>&apos;getPtr&apos; not called because the receiver is nil</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>152</integer>
+// CHECK-NEXT: <key>col</key><integer>25</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>152</integer>
+// CHECK-NEXT: <key>col</key><integer>25</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>152</integer>
+// CHECK-NEXT: <key>col</key><integer>35</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;x&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;x&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
// CHECK-NEXT: <key>edges</key>
// CHECK-NEXT: <array>
@@ -1521,12 +1482,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
+// CHECK-NEXT: <key>col</key><integer>25</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
+// CHECK-NEXT: <key>col</key><integer>25</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -1534,12 +1495,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
+// CHECK-NEXT: <key>col</key><integer>23</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -1551,35 +1512,6 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>35</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;x&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;x&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1936,40 +1868,6 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>168</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>168</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>168</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>168</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>170</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
@@ -2047,40 +1945,6 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <string>Method returns an instance of NSObject with a +1 retain count</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -2130,81 +1994,6 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>60</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>47</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -2217,13 +2006,13 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>175</integer>
+// CHECK-NEXT: <key>line</key><integer>170</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>175</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>line</key><integer>170</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -2238,13 +2027,13 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>175</integer>
+// CHECK-NEXT: <key>line</key><integer>170</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>175</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>line</key><integer>170</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
diff --git a/test/Analysis/inlining/temp-dtors-path-notes.cpp b/test/Analysis/inlining/temp-dtors-path-notes.cpp
new file mode 100644
index 000000000000..40b26b5c91ae
--- /dev/null
+++ b/test/Analysis/inlining/temp-dtors-path-notes.cpp
@@ -0,0 +1,59 @@
+// RUN: %clang_analyze_cc1 -analyze -analyzer-checker core -analyzer-config cfg-temporary-dtors=true,c++-temp-dtor-inlining=true -analyzer-output=text -verify %s
+
+namespace test_simple_temporary {
+class C {
+ int x;
+
+public:
+ C(int x): x(x) {} // expected-note{{The value 0 is assigned to field 'x'}}
+ ~C() { x = 1 / x; } // expected-warning{{Division by zero}}
+ // expected-note@-1{{Division by zero}}
+};
+
+void test() {
+ C(0); // expected-note {{Passing the value 0 via 1st parameter 'x'}}
+ // expected-note@-1{{Calling constructor for 'C'}}
+ // expected-note@-2{{Returning from constructor for 'C'}}
+ // expected-note@-3{{Calling '~C'}}
+}
+} // end namespace test_simple_temporary
+
+namespace test_lifetime_extended_temporary {
+class C {
+ int x;
+
+public:
+ C(int x): x(x) {} // expected-note{{The value 0 is assigned to field 'x'}}
+ void nop() const {}
+ ~C() { x = 1 / x; } // expected-warning{{Division by zero}}
+ // expected-note@-1{{Division by zero}}
+};
+
+void test(int coin) {
+ // We'd divide by zero in the automatic destructor for variable 'c'.
+ const C &c = coin ? C(1) : C(0); // expected-note {{Assuming 'coin' is 0}}
+ // expected-note@-1{{'?' condition is false}}
+ // expected-note@-2{{Passing the value 0 via 1st parameter 'x'}}
+ // expected-note@-3{{Calling constructor for 'C'}}
+ // expected-note@-4{{Returning from constructor for 'C'}}
+ c.nop();
+} // expected-note{{Calling '~C'}}
+} // end namespace test_lifetime_extended_temporary
+
+namespace test_bug_after_dtor {
+int glob;
+
+class C {
+public:
+ C() { glob += 1; }
+ ~C() { glob -= 2; } // expected-note{{The value 0 is assigned to 'glob'}}
+};
+
+void test() {
+ glob = 1;
+ C(); // expected-note {{Calling '~C'}}
+ // expected-note@-1{{Returning from '~C'}}
+ glob = 1 / glob; // expected-warning{{Division by zero}}
+ // expected-note@-1{{Division by zero}}
+}
+} // end namespace test_bug_after_dtor
diff --git a/test/Analysis/inner-pointer.cpp b/test/Analysis/inner-pointer.cpp
new file mode 100644
index 000000000000..db9bf43109b2
--- /dev/null
+++ b/test/Analysis/inner-pointer.cpp
@@ -0,0 +1,291 @@
+//RUN: %clang_analyze_cc1 -analyzer-checker=alpha.cplusplus.InnerPointer %s -analyzer-output=text -verify
+
+namespace std {
+
+typedef int size_type;
+
+template <typename CharT>
+class basic_string {
+public:
+ basic_string();
+ basic_string(const CharT *s);
+
+ ~basic_string();
+ void clear();
+
+ basic_string &operator=(const basic_string &str);
+ basic_string &operator+=(const basic_string &str);
+
+ const CharT *c_str() const;
+ const CharT *data() const;
+ CharT *data();
+
+ basic_string &append(size_type count, CharT ch);
+ basic_string &assign(size_type count, CharT ch);
+ basic_string &erase(size_type index, size_type count);
+ basic_string &insert(size_type index, size_type count, CharT ch);
+ basic_string &replace(size_type pos, size_type count, const basic_string &str);
+ void pop_back();
+ void push_back(CharT ch);
+ void reserve(size_type new_cap);
+ void resize(size_type count);
+ void shrink_to_fit();
+ void swap(basic_string &other);
+};
+
+typedef basic_string<char> string;
+typedef basic_string<wchar_t> wstring;
+typedef basic_string<char16_t> u16string;
+typedef basic_string<char32_t> u32string;
+
+} // end namespace std
+
+void consume(const char *) {}
+void consume(const wchar_t *) {}
+void consume(const char16_t *) {}
+void consume(const char32_t *) {}
+
+void deref_after_scope_char(bool cond) {
+ const char *c, *d;
+ {
+ std::string s;
+ c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
+ d = s.data(); // expected-note {{Dangling inner pointer obtained here}}
+ } // expected-note {{Inner pointer invalidated by call to destructor}}
+ // expected-note@-1 {{Inner pointer invalidated by call to destructor}}
+ std::string s;
+ const char *c2 = s.c_str();
+ if (cond) {
+ // expected-note@-1 {{Assuming 'cond' is not equal to 0}}
+ // expected-note@-2 {{Taking true branch}}
+ // expected-note@-3 {{Assuming 'cond' is 0}}
+ // expected-note@-4 {{Taking false branch}}
+ consume(c); // expected-warning {{Use of memory after it is freed}}
+ // expected-note@-1 {{Use of memory after it is freed}}
+ } else {
+ consume(d); // expected-warning {{Use of memory after it is freed}}
+ // expected-note@-1 {{Use of memory after it is freed}}
+ }
+}
+
+void deref_after_scope_char_data_non_const() {
+ char *c;
+ {
+ std::string s;
+ c = s.data(); // expected-note {{Dangling inner pointer obtained here}}
+ } // expected-note {{Inner pointer invalidated by call to destructor}}
+ std::string s;
+ char *c2 = s.data();
+ consume(c); // expected-warning {{Use of memory after it is freed}}
+ // expected-note@-1 {{Use of memory after it is freed}}
+}
+
+void deref_after_scope_wchar_t(bool cond) {
+ const wchar_t *c, *d;
+ {
+ std::wstring s;
+ c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
+ d = s.data(); // expected-note {{Dangling inner pointer obtained here}}
+ } // expected-note {{Inner pointer invalidated by call to destructor}}
+ // expected-note@-1 {{Inner pointer invalidated by call to destructor}}
+ std::wstring s;
+ const wchar_t *c2 = s.c_str();
+ if (cond) {
+ // expected-note@-1 {{Assuming 'cond' is not equal to 0}}
+ // expected-note@-2 {{Taking true branch}}
+ // expected-note@-3 {{Assuming 'cond' is 0}}
+ // expected-note@-4 {{Taking false branch}}
+ consume(c); // expected-warning {{Use of memory after it is freed}}
+ // expected-note@-1 {{Use of memory after it is freed}}
+ } else {
+ consume(d); // expected-warning {{Use of memory after it is freed}}
+ // expected-note@-1 {{Use of memory after it is freed}}
+ }
+}
+
+void deref_after_scope_char16_t_cstr() {
+ const char16_t *c16;
+ {
+ std::u16string s16;
+ c16 = s16.c_str(); // expected-note {{Dangling inner pointer obtained here}}
+ } // expected-note {{Inner pointer invalidated by call to destructor}}
+ std::u16string s16;
+ const char16_t *c16_2 = s16.c_str();
+ consume(c16); // expected-warning {{Use of memory after it is freed}}
+ // expected-note@-1 {{Use of memory after it is freed}}
+}
+
+void deref_after_scope_char32_t_data() {
+ const char32_t *c32;
+ {
+ std::u32string s32;
+ c32 = s32.data(); // expected-note {{Dangling inner pointer obtained here}}
+ } // expected-note {{Inner pointer invalidated by call to destructor}}
+ std::u32string s32;
+ const char32_t *c32_2 = s32.data();
+ consume(c32); // expected-warning {{Use of memory after it is freed}}
+ // expected-note@-1 {{Use of memory after it is freed}}
+}
+
+void multiple_symbols(bool cond) {
+ const char *c1, *d1;
+ {
+ std::string s1;
+ c1 = s1.c_str(); // expected-note {{Dangling inner pointer obtained here}}
+ d1 = s1.data(); // expected-note {{Dangling inner pointer obtained here}}
+ const char *local = s1.c_str();
+ consume(local); // no-warning
+ } // expected-note {{Inner pointer invalidated by call to destructor}}
+ // expected-note@-1 {{Inner pointer invalidated by call to destructor}}
+ std::string s2;
+ const char *c2 = s2.c_str();
+ if (cond) {
+ // expected-note@-1 {{Assuming 'cond' is not equal to 0}}
+ // expected-note@-2 {{Taking true branch}}
+ // expected-note@-3 {{Assuming 'cond' is 0}}
+ // expected-note@-4 {{Taking false branch}}
+ consume(c1); // expected-warning {{Use of memory after it is freed}}
+ // expected-note@-1 {{Use of memory after it is freed}}
+ } else {
+ consume(d1); // expected-warning {{Use of memory after it is freed}}
+ } // expected-note@-1 {{Use of memory after it is freed}}
+}
+
+void deref_after_equals() {
+ const char *c;
+ std::string s = "hello";
+ c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
+ s = "world"; // expected-note {{Inner pointer invalidated by call to 'operator='}}
+ consume(c); // expected-warning {{Use of memory after it is freed}}
+ // expected-note@-1 {{Use of memory after it is freed}}
+}
+
+void deref_after_plus_equals() {
+ const char *c;
+ std::string s = "hello";
+ c = s.data(); // expected-note {{Dangling inner pointer obtained here}}
+ s += " world"; // expected-note {{Inner pointer invalidated by call to 'operator+='}}
+ consume(c); // expected-warning {{Use of memory after it is freed}}
+ // expected-note@-1 {{Use of memory after it is freed}}
+}
+
+void deref_after_clear() {
+ const char *c;
+ std::string s;
+ c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
+ s.clear(); // expected-note {{Inner pointer invalidated by call to 'clear'}}
+ consume(c); // expected-warning {{Use of memory after it is freed}}
+ // expected-note@-1 {{Use of memory after it is freed}}
+}
+
+void deref_after_append() {
+ const char *c;
+ std::string s = "hello";
+ c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
+ s.append(2, 'x'); // expected-note {{Inner pointer invalidated by call to 'append'}}
+ consume(c); // expected-warning {{Use of memory after it is freed}}
+ // expected-note@-1 {{Use of memory after it is freed}}
+}
+
+void deref_after_assign() {
+ const char *c;
+ std::string s;
+ c = s.data(); // expected-note {{Dangling inner pointer obtained here}}
+ s.assign(4, 'a'); // expected-note {{Inner pointer invalidated by call to 'assign'}}
+ consume(c); // expected-warning {{Use of memory after it is freed}}
+ // expected-note@-1 {{Use of memory after it is freed}}
+}
+
+void deref_after_erase() {
+ const char *c;
+ std::string s = "hello";
+ c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
+ s.erase(0, 2); // expected-note {{Inner pointer invalidated by call to 'erase'}}
+ consume(c); // expected-warning {{Use of memory after it is freed}}
+ // expected-note@-1 {{Use of memory after it is freed}}
+}
+
+void deref_after_insert() {
+ const char *c;
+ std::string s = "ello";
+ c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
+ s.insert(0, 1, 'h'); // expected-note {{Inner pointer invalidated by call to 'insert'}}
+ consume(c); // expected-warning {{Use of memory after it is freed}}
+ // expected-note@-1 {{Use of memory after it is freed}}
+}
+
+void deref_after_replace() {
+ const char *c;
+ std::string s = "hello world";
+ c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
+ s.replace(6, 5, "string"); // expected-note {{Inner pointer invalidated by call to 'replace'}}
+ consume(c); // expected-warning {{Use of memory after it is freed}}
+ // expected-note@-1 {{Use of memory after it is freed}}
+}
+
+void deref_after_pop_back() {
+ const char *c;
+ std::string s;
+ c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
+ s.pop_back(); // expected-note {{Inner pointer invalidated by call to 'pop_back'}}
+ consume(c); // expected-warning {{Use of memory after it is freed}}
+ // expected-note@-1 {{Use of memory after it is freed}}
+}
+
+void deref_after_push_back() {
+ const char *c;
+ std::string s;
+ c = s.data(); // expected-note {{Dangling inner pointer obtained here}}
+ s.push_back('c'); // expected-note {{Inner pointer invalidated by call to 'push_back'}}
+ consume(c); // expected-warning {{Use of memory after it is freed}}
+ // expected-note@-1 {{Use of memory after it is freed}}
+}
+
+void deref_after_reserve() {
+ const char *c;
+ std::string s;
+ c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
+ s.reserve(5); // expected-note {{Inner pointer invalidated by call to 'reserve'}}
+ consume(c); // expected-warning {{Use of memory after it is freed}}
+ // expected-note@-1 {{Use of memory after it is freed}}
+}
+
+void deref_after_resize() {
+ const char *c;
+ std::string s;
+ c = s.data(); // expected-note {{Dangling inner pointer obtained here}}
+ s.resize(5); // expected-note {{Inner pointer invalidated by call to 'resize'}}
+ consume(c); // expected-warning {{Use of memory after it is freed}}
+ // expected-note@-1 {{Use of memory after it is freed}}
+}
+
+void deref_after_shrink_to_fit() {
+ const char *c;
+ std::string s;
+ c = s.data(); // expected-note {{Dangling inner pointer obtained here}}
+ s.shrink_to_fit(); // expected-note {{Inner pointer invalidated by call to 'shrink_to_fit'}}
+ consume(c); // expected-warning {{Use of memory after it is freed}}
+ // expected-note@-1 {{Use of memory after it is freed}}
+}
+
+void deref_after_swap() {
+ const char *c;
+ std::string s1, s2;
+ c = s1.data(); // expected-note {{Dangling inner pointer obtained here}}
+ s1.swap(s2); // expected-note {{Inner pointer invalidated by call to 'swap'}}
+ consume(c); // expected-warning {{Use of memory after it is freed}}
+ // expected-note@-1 {{Use of memory after it is freed}}
+}
+
+void deref_after_scope_ok(bool cond) {
+ const char *c, *d;
+ std::string s;
+ {
+ c = s.c_str();
+ d = s.data();
+ }
+ if (cond)
+ consume(c); // no-warning
+ else
+ consume(d); // no-warning
+}
diff --git a/test/Analysis/iterator-range.cpp b/test/Analysis/iterator-range.cpp
index 79b45188ab5d..8a4ba29b0cd7 100644
--- a/test/Analysis/iterator-range.cpp
+++ b/test/Analysis/iterator-range.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,alpha.cplusplus.IteratorRange -analyzer-eagerly-assume -analyzer-config c++-container-inlining=false %s -verify
-// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,alpha.cplusplus.IteratorRange -analyzer-eagerly-assume -analyzer-config c++-container-inlining=true -DINLINE=1 %s -verify
+// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,alpha.cplusplus.IteratorRange -analyzer-eagerly-assume -analyzer-config aggressive-binary-operation-simplification=true -analyzer-config c++-container-inlining=false %s -verify
+// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,alpha.cplusplus.IteratorRange -analyzer-eagerly-assume -analyzer-config aggressive-binary-operation-simplification=true -analyzer-config c++-container-inlining=true -DINLINE=1 %s -verify
#include "Inputs/system-header-simulator-cxx.h"
@@ -13,7 +13,110 @@ void simple_good_end(const std::vector<int> &v) {
}
}
+void simple_good_end_negated(const std::vector<int> &v) {
+ auto i = v.end();
+ if (!(i == v.end())) {
+ clang_analyzer_warnIfReached();
+ *i; // no-warning
+ }
+}
+
void simple_bad_end(const std::vector<int> &v) {
auto i = v.end();
*i; // expected-warning{{Iterator accessed outside of its range}}
}
+
+void simple_good_begin(const std::vector<int> &v) {
+ auto i = v.begin();
+ if (i != v.begin()) {
+ clang_analyzer_warnIfReached();
+ *--i; // no-warning
+ }
+}
+
+void simple_good_begin_negated(const std::vector<int> &v) {
+ auto i = v.begin();
+ if (!(i == v.begin())) {
+ clang_analyzer_warnIfReached();
+ *--i; // no-warning
+ }
+}
+
+void simple_bad_begin(const std::vector<int> &v) {
+ auto i = v.begin();
+ *--i; // expected-warning{{Iterator accessed outside of its range}}
+}
+
+void copy(const std::vector<int> &v) {
+ auto i1 = v.end();
+ auto i2 = i1;
+ *i2; // expected-warning{{Iterator accessed outside of its range}}
+}
+
+void decrease(const std::vector<int> &v) {
+ auto i = v.end();
+ --i;
+ *i; // no-warning
+}
+
+void copy_and_decrease1(const std::vector<int> &v) {
+ auto i1 = v.end();
+ auto i2 = i1;
+ --i1;
+ *i1; // no-warning
+}
+
+void copy_and_decrease2(const std::vector<int> &v) {
+ auto i1 = v.end();
+ auto i2 = i1;
+ --i1;
+ *i2; // expected-warning{{Iterator accessed outside of its range}}
+}
+
+void copy_and_increase1(const std::vector<int> &v) {
+ auto i1 = v.begin();
+ auto i2 = i1;
+ ++i1;
+ if (i1 == v.end())
+ *i2; // no-warning
+}
+
+void copy_and_increase2(const std::vector<int> &v) {
+ auto i1 = v.begin();
+ auto i2 = i1;
+ ++i1;
+ if (i2 == v.end())
+ *i2; // expected-warning{{Iterator accessed outside of its range}}
+}
+
+void copy_and_increase3(const std::vector<int> &v) {
+ auto i1 = v.begin();
+ auto i2 = i1;
+ ++i1;
+ if (v.end() == i2)
+ *i2; // expected-warning{{Iterator accessed outside of its range}}
+}
+
+void tricky(std::vector<int> &V, int e) {
+ const auto first = V.begin();
+ const auto comp1 = (first != V.end()), comp2 = (first == V.end());
+ if (comp1)
+ *first;
+}
+
+void loop(std::vector<int> &V, int e) {
+ auto start = V.begin();
+ while (true) {
+ auto item = std::find(start, V.end(), e);
+ if (item == V.end())
+ break;
+ *item; // no-warning
+ start = ++item; // no-warning
+ }
+}
+
+void bad_move(std::list<int> &L1, std::list<int> &L2) {
+ auto i0 = --L2.cend();
+ L1 = std::move(L2);
+ *++i0; // expected-warning{{Iterator accessed outside of its range}}
+}
diff --git a/test/Analysis/lambda-notes.cpp b/test/Analysis/lambda-notes.cpp
index 7abff35df124..d4318284df01 100644
--- a/test/Analysis/lambda-notes.cpp
+++ b/test/Analysis/lambda-notes.cpp
@@ -69,7 +69,7 @@ void diagnosticFromLambda() {
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
diff --git a/test/Analysis/lambdas.cpp b/test/Analysis/lambdas.cpp
index 38a2e3a84fb1..320ba2aabc22 100644
--- a/test/Analysis/lambdas.cpp
+++ b/test/Analysis/lambdas.cpp
@@ -348,6 +348,23 @@ void testCapturedConstExprFloat() {
lambda();
}
+
+static int b = 0;
+
+int f() {
+ b = 0;
+ auto &bm = b;
+ [&] {
+ bm++;
+ bm++;
+ }();
+ if (bm != 2) {
+ int *y = 0;
+ return *y; // no-warning
+ }
+ return 0;
+}
+
// CHECK: [B2 (ENTRY)]
// CHECK: Succs (1): B1
// CHECK: [B1]
diff --git a/test/Analysis/lifetime-cfg-output.cpp b/test/Analysis/lifetime-cfg-output.cpp
index 1e6f56df6a47..dc2849db1b63 100644
--- a/test/Analysis/lifetime-cfg-output.cpp
+++ b/test/Analysis/lifetime-cfg-output.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -analyze -analyzer-checker=debug.DumpCFG -analyzer-config cfg-lifetime=true -analyzer-config cfg-implicit-dtors=false %s > %t 2>&1
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -analyze -analyzer-checker=debug.DumpCFG -analyzer-config cfg-lifetime=true,cfg-temporary-dtors=false,cfg-rich-constructors=false -analyzer-config cfg-implicit-dtors=false %s > %t 2>&1
// RUN: FileCheck --input-file=%t %s
extern bool UV;
diff --git a/test/Analysis/lifetime-extension.cpp b/test/Analysis/lifetime-extension.cpp
index 5e3c5dde0a8b..4337632b31c8 100644
--- a/test/Analysis/lifetime-extension.cpp
+++ b/test/Analysis/lifetime-extension.cpp
@@ -1,6 +1,14 @@
-// RUN: %clang_analyze_cc1 -Wno-unused -std=c++11 -analyzer-checker=debug.ExprInspection -verify %s
+// RUN: %clang_analyze_cc1 -Wno-unused -std=c++11 -analyzer-checker=core,debug.ExprInspection -analyzer-config cfg-temporary-dtors=false -verify %s
+// RUN: %clang_analyze_cc1 -Wno-unused -std=c++11 -analyzer-checker=core,debug.ExprInspection -analyzer-config cfg-temporary-dtors=true,c++-temp-dtor-inlining=true -DTEMPORARIES -verify %s
+// RUN: %clang_analyze_cc1 -Wno-unused -std=c++17 -analyzer-checker=core,debug.ExprInspection -analyzer-config cfg-temporary-dtors=true,c++-temp-dtor-inlining=true -DTEMPORARIES %s
+// RUN: %clang_analyze_cc1 -Wno-unused -std=c++11 -analyzer-checker=core,debug.ExprInspection -analyzer-config cfg-temporary-dtors=false -DMOVES -verify %s
+// RUN: %clang_analyze_cc1 -Wno-unused -std=c++11 -analyzer-checker=core,debug.ExprInspection -analyzer-config cfg-temporary-dtors=true,c++-temp-dtor-inlining=true -DTEMPORARIES -DMOVES -verify %s
+// RUN: %clang_analyze_cc1 -Wno-unused -std=c++17 -analyzer-checker=core,debug.ExprInspection -analyzer-config cfg-temporary-dtors=true,c++-temp-dtor-inlining=true -DTEMPORARIES -DMOVES %s
+
+// Note: The C++17 run-lines don't -verify yet - it is a no-crash test.
void clang_analyzer_eval(bool);
+void clang_analyzer_checkInlined(bool);
namespace pr17001_call_wrong_destructor {
bool x;
@@ -38,9 +46,289 @@ void f() {
const int &y = A().j[1]; // no-crash
const int &z = (A().j[1], A().j[0]); // no-crash
- // FIXME: All of these should be TRUE, but constructors aren't inlined.
- clang_analyzer_eval(x == 1); // expected-warning{{UNKNOWN}}
- clang_analyzer_eval(y == 3); // expected-warning{{UNKNOWN}}
- clang_analyzer_eval(z == 2); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(x == 1);
+ clang_analyzer_eval(y == 3);
+ clang_analyzer_eval(z == 2);
+#ifdef TEMPORARIES
+ // expected-warning@-4{{TRUE}}
+ // expected-warning@-4{{TRUE}}
+ // expected-warning@-4{{TRUE}}
+#else
+ // expected-warning@-8{{UNKNOWN}}
+ // expected-warning@-8{{UNKNOWN}}
+ // expected-warning@-8{{UNKNOWN}}
+#endif
}
} // end namespace pr19539_crash_on_destroying_an_integer
+
+namespace maintain_original_object_address_on_lifetime_extension {
+class C {
+ C **after, **before;
+
+public:
+ bool x;
+
+ C(bool x, C **after, C **before) : x(x), after(after), before(before) {
+ *before = this;
+ }
+
+ // Don't track copies in our tests.
+ C(const C &c) : x(c.x), after(nullptr), before(nullptr) {}
+
+ ~C() { if (after) *after = this; }
+
+ operator bool() const { return x; }
+
+ static C make(C **after, C **before) { return C(false, after, before); }
+};
+
+void f1() {
+ C *after, *before;
+ {
+ const C &c = C(true, &after, &before);
+ }
+ clang_analyzer_eval(after == before);
+#ifdef TEMPORARIES
+ // expected-warning@-2{{TRUE}}
+#else
+ // expected-warning@-4{{UNKNOWN}}
+#endif
+}
+
+void f2() {
+ C *after, *before;
+ {
+ C c = C(1, &after, &before);
+ }
+ clang_analyzer_eval(after == before); // expected-warning{{TRUE}}
+}
+
+void f3(bool coin) {
+ C *after, *before;
+ {
+ const C &c = coin ? C(true, &after, &before) : C(false, &after, &before);
+ }
+ clang_analyzer_eval(after == before);
+#ifdef TEMPORARIES
+ // expected-warning@-2{{TRUE}}
+#else
+ // expected-warning@-4{{UNKNOWN}}
+#endif
+}
+
+void f4(bool coin) {
+ C *after, *before;
+ {
+ // no-crash
+ const C &c = C(coin, &after, &before) ?: C(false, &after, &before);
+ }
+ // FIXME: Add support for lifetime extension through binary conditional
+ // operator. Ideally also add support for the binary conditional operator in
+ // C++. Because for now it calls the constructor for the condition twice.
+ if (coin) {
+ // FIXME: Should not warn.
+ clang_analyzer_eval(after == before);
+#ifdef TEMPORARIES
+ // expected-warning@-2{{The left operand of '==' is a garbage value}}
+#else
+ // expected-warning@-4{{UNKNOWN}}
+#endif
+ } else {
+ // FIXME: Should be TRUE.
+ clang_analyzer_eval(after == before);
+#ifdef TEMPORARIES
+ // expected-warning@-2{{FALSE}}
+#else
+ // expected-warning@-4{{UNKNOWN}}
+#endif
+ }
+}
+
+void f5() {
+ C *after, *before;
+ {
+ const bool &x = C(true, &after, &before).x; // no-crash
+ }
+ clang_analyzer_eval(after == before);
+#ifdef TEMPORARIES
+ // expected-warning@-2{{TRUE}}
+#else
+ // expected-warning@-4{{UNKNOWN}}
+#endif
+}
+
+struct A { // A is an aggregate.
+ const C &c;
+};
+
+void f6() {
+ C *after, *before;
+ {
+ A a{C(true, &after, &before)};
+ }
+ // FIXME: Should be TRUE. Should not warn about garbage value.
+ clang_analyzer_eval(after == before); // expected-warning{{UNKNOWN}}
+}
+
+void f7() {
+ C *after, *before;
+ {
+ A a = {C(true, &after, &before)};
+ }
+ // FIXME: Should be TRUE. Should not warn about garbage value.
+ clang_analyzer_eval(after == before); // expected-warning{{UNKNOWN}}
+}
+
+void f8() {
+ C *after, *before;
+ {
+ A a[2] = {C(false, nullptr, nullptr), C(true, &after, &before)};
+ }
+ // FIXME: Should be TRUE. Should not warn about garbage value.
+ clang_analyzer_eval(after == before); // expected-warning{{UNKNOWN}}
+}
+} // end namespace maintain_original_object_address_on_lifetime_extension
+
+namespace maintain_original_object_address_on_move {
+class C {
+ int *x;
+
+public:
+ C() : x(nullptr) {}
+ C(int *x) : x(x) {}
+ C(const C &c) = delete;
+ C(C &&c) : x(c.x) { c.x = nullptr; }
+ C &operator=(C &&c) {
+ x = c.x;
+ c.x = nullptr;
+ return *this;
+ }
+ ~C() {
+ // This was triggering the division by zero warning in f1() and f2():
+ // Because move-elision materialization was incorrectly causing the object
+ // to be relocated from one address to another before move, but destructor
+ // was operating on the old address, it was still thinking that 'x' is set.
+ if (x)
+ *x = 0;
+ }
+};
+
+void f1() {
+ int x = 1;
+ // &x is replaced with nullptr in move-constructor before the temporary dies.
+ C c = C(&x);
+ // Hence x was not set to 0 yet.
+ 1 / x; // no-warning
+}
+void f2() {
+ int x = 1;
+ C c;
+ // &x is replaced with nullptr in move-assignment before the temporary dies.
+ c = C(&x);
+ // Hence x was not set to 0 yet.
+ 1 / x; // no-warning
+}
+} // end namespace maintain_original_object_address_on_move
+
+namespace maintain_address_of_copies {
+class C;
+
+struct AddressVector {
+ C *buf[10];
+ int len;
+
+ AddressVector() : len(0) {}
+
+ void push(C *c) {
+ buf[len] = c;
+ ++len;
+ }
+};
+
+class C {
+ AddressVector &v;
+
+public:
+ C(AddressVector &v) : v(v) { v.push(this); }
+ ~C() { v.push(this); }
+
+#ifdef MOVES
+ C(C &&c) : v(c.v) { v.push(this); }
+#endif
+
+ // Note how return-statements prefer move-constructors when available.
+ C(const C &c) : v(c.v) {
+#ifdef MOVES
+ clang_analyzer_checkInlined(false); // no-warning
+#else
+ v.push(this);
+#endif
+ } // no-warning
+
+ static C make(AddressVector &v) { return C(v); }
+};
+
+void f1() {
+ AddressVector v;
+ {
+ C c = C(v);
+ }
+ // 0. Construct variable 'c' (copy/move elided).
+ // 1. Destroy variable 'c'.
+ clang_analyzer_eval(v.len == 2); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[0] == v.buf[1]); // expected-warning{{TRUE}}
+}
+
+void f2() {
+ AddressVector v;
+ {
+ const C &c = C::make(v);
+ }
+ // 0. Construct the return value of make() (copy/move elided) and
+ // lifetime-extend it directly via reference 'c',
+ // 1. Destroy the temporary lifetime-extended by 'c'.
+ clang_analyzer_eval(v.len == 2);
+ clang_analyzer_eval(v.buf[0] == v.buf[1]);
+#ifdef TEMPORARIES
+ // expected-warning@-3{{TRUE}}
+ // expected-warning@-3{{TRUE}}
+#else
+ // expected-warning@-6{{UNKNOWN}}
+ // expected-warning@-6{{UNKNOWN}}
+#endif
+}
+
+void f3() {
+ AddressVector v;
+ {
+ C &&c = C::make(v);
+ }
+ // 0. Construct the return value of make() (copy/move elided) and
+ // lifetime-extend it directly via reference 'c',
+ // 1. Destroy the temporary lifetime-extended by 'c'.
+ clang_analyzer_eval(v.len == 2);
+ clang_analyzer_eval(v.buf[0] == v.buf[1]);
+#ifdef TEMPORARIES
+ // expected-warning@-3{{TRUE}}
+ // expected-warning@-3{{TRUE}}
+#else
+ // expected-warning@-6{{UNKNOWN}}
+ // expected-warning@-6{{UNKNOWN}}
+#endif
+}
+
+C doubleMake(AddressVector &v) {
+ return C::make(v);
+}
+
+void f4() {
+ AddressVector v;
+ {
+ C c = doubleMake(v);
+ }
+ // 0. Construct variable 'c' (all copies/moves elided),
+ // 1. Destroy variable 'c'.
+ clang_analyzer_eval(v.len == 2); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[0] == v.buf[1]); // expected-warning{{TRUE}}
+}
+} // end namespace maintain_address_of_copies
diff --git a/test/Analysis/live-bindings-test.cpp b/test/Analysis/live-bindings-test.cpp
new file mode 100644
index 000000000000..afbb1b399fcd
--- /dev/null
+++ b/test/Analysis/live-bindings-test.cpp
@@ -0,0 +1,124 @@
+// RUN: %clang_analyze_cc1 -std=c++17 -analyzer-checker=core,deadcode -verify %s
+
+typedef unsigned long size_t;
+
+// Machinery required for custom structured bindings decomposition.
+namespace std {
+template <class T> class tuple_size;
+template <class T>
+ constexpr size_t tuple_size_v = tuple_size<T>::value;
+template <size_t I, class T> class tuple_element;
+
+template<class T, T v>
+struct integral_constant {
+ static constexpr T value = v;
+ typedef T value_type;
+ typedef integral_constant type;
+ constexpr operator value_type() const noexcept { return value; }
+};
+}
+
+struct S {
+ int a;
+ double b;
+ S(int a, double b) : a(a), b(b) {};
+};
+
+S GetNumbers();
+
+int used_binding() {
+ const auto [a, b] = GetNumbers(); // no-warning
+ return a + b;
+}
+
+void no_warning_on_copy(S s) {
+ // Copy constructor might have side effects.
+ const auto [a, b] = s; // no-warning
+}
+
+
+int unused_binding_ignored() {
+ const auto [a, b] = GetNumbers(); // expected-warning{{Value stored to '[a, b]' during its initialization is never read}}
+ return 0;
+}
+
+int unused_binding_liveness_required() {
+ auto [a2, b2] = GetNumbers(); // expected-warning{{Value stored to '[a2, b2]' during its initialization is never read}}
+ a2 = 10;
+ b2 = 20;
+ return a2 + b2;
+}
+
+int kill_one_binding() {
+ auto [a, b] = GetNumbers(); // no-warning
+ a = 100;
+ return a + b;
+
+}
+
+int kill_one_binding2() {
+ auto [a, b] = GetNumbers(); // expected-warning{{Value stored to '[a, b]' during its initialization is never read}}
+ a = 100;
+ return a;
+}
+
+void use_const_reference_bindings() {
+ const auto &[a, b] = GetNumbers(); // no-warning
+}
+
+void use_reference_bindings() {
+ S s(0, 0);
+ auto &[a, b] = s; // no-warning
+ a = 200;
+}
+
+int read_through_pointer() {
+ auto [a, b] = GetNumbers(); // no-warning
+ int *z = &a;
+ return *z;
+}
+
+auto [globalA, globalB] = GetNumbers(); // no-warning, globals
+auto [globalC, globalD] = GetNumbers(); // no-warning, globals
+
+void use_globals() {
+ globalA = 300; // no-warning
+ globalB = 200;
+}
+
+struct Mytuple {
+ int a;
+ int b;
+
+ template <size_t N>
+ int get() const {
+ if constexpr (N == 0) return a;
+ else if constexpr (N == 1) return b;
+ }
+};
+
+namespace std {
+ template<>
+ struct tuple_size<Mytuple>
+ : std::integral_constant<size_t, 2> {};
+
+ template<size_t N>
+ struct tuple_element<N, Mytuple> {
+ using type = int;
+ };
+}
+
+void no_warning_on_tuple_types_copy(Mytuple t) {
+ auto [a, b] = t; // no-warning
+}
+
+Mytuple getMytuple();
+
+void deconstruct_tuple_types_warning() {
+ auto [a, b] = getMytuple(); // expected-warning{{Value stored to '[a, b]' during its initialization is never read}}
+}
+
+int deconstruct_tuple_types_no_warning() {
+ auto [a, b] = getMytuple(); // no-warning
+ return a + b;
+}
diff --git a/test/Analysis/localization.m b/test/Analysis/localization.m
index 3a6a0d707373..a9fd2445eb15 100644
--- a/test/Analysis/localization.m
+++ b/test/Analysis/localization.m
@@ -118,14 +118,14 @@ NSString *KHLocalizedString(NSString* key, NSString* comment) {
- (NSString *)test1:(int)plural {
if (plural) {
- return MCLocalizedString(@"TYPE_PLURAL"); // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}} expected-note {{Plural}}
+ return MCLocalizedString(@"TYPE_PLURAL"); // expected-warning {{Plural cases are not supported across all languages. Use a .stringsdict file}} expected-note {{Plural}}
}
return MCLocalizedString(@"TYPE");
}
- (NSString *)test2:(int)numOfReminders {
if (numOfReminders > 0) {
- return [NSString stringWithFormat:@"%@, %@", @"Test", (numOfReminders != 1) ? [NSString stringWithFormat:NSLocalizedString(@"%@ Reminders", @"Plural count of reminders"), numOfReminders] : [NSString stringWithFormat:NSLocalizedString(@"1 reminder", @"One reminder")]]; // expected-warning 2 {{Plural cases are not supported accross all languages. Use a .stringsdict file}} expected-note 2 {{Plural}}
+ return [NSString stringWithFormat:@"%@, %@", @"Test", (numOfReminders != 1) ? [NSString stringWithFormat:NSLocalizedString(@"%@ Reminders", @"Plural count of reminders"), numOfReminders] : [NSString stringWithFormat:NSLocalizedString(@"1 reminder", @"One reminder")]]; // expected-warning 2 {{Plural cases are not supported across all languages. Use a .stringsdict file}} expected-note 2 {{Plural}}
}
return nil;
}
@@ -134,18 +134,18 @@ NSString *KHLocalizedString(NSString* key, NSString* comment) {
NSString *count;
if (self.unreadArticlesCount > 1)
{
- count = [count stringByAppendingFormat:@"%@", KHLocalizedString(@"New Stories", @"Plural count for new stories")]; // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}} expected-note {{Plural}}
+ count = [count stringByAppendingFormat:@"%@", KHLocalizedString(@"New Stories", @"Plural count for new stories")]; // expected-warning {{Plural cases are not supported across all languages. Use a .stringsdict file}} expected-note {{Plural}}
} else {
- count = [count stringByAppendingFormat:@"%@", KHLocalizedString(@"New Story", @"One new story")]; // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}} expected-note {{Plural}}
+ count = [count stringByAppendingFormat:@"%@", KHLocalizedString(@"New Story", @"One new story")]; // expected-warning {{Plural cases are not supported across all languages. Use a .stringsdict file}} expected-note {{Plural}}
}
}
- (NSString *)test4:(int)count {
if ( count == 1 )
{
- return [NSString stringWithFormat:KHLocalizedString(@"value.singular",nil), count]; // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}} expected-note {{Plural}}
+ return [NSString stringWithFormat:KHLocalizedString(@"value.singular",nil), count]; // expected-warning {{Plural cases are not supported across all languages. Use a .stringsdict file}} expected-note {{Plural}}
} else {
- return [NSString stringWithFormat:KHLocalizedString(@"value.plural",nil), count]; // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}} expected-note {{Plural}}
+ return [NSString stringWithFormat:KHLocalizedString(@"value.plural",nil), count]; // expected-warning {{Plural cases are not supported across all languages. Use a .stringsdict file}} expected-note {{Plural}}
}
}
@@ -153,9 +153,9 @@ NSString *KHLocalizedString(NSString* key, NSString* comment) {
int test = count == 1;
if (test)
{
- return [NSString stringWithFormat:KHLocalizedString(@"value.singular",nil), count]; // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}} expected-note {{Plural}}
+ return [NSString stringWithFormat:KHLocalizedString(@"value.singular",nil), count]; // expected-warning {{Plural cases are not supported across all languages. Use a .stringsdict file}} expected-note {{Plural}}
} else {
- return [NSString stringWithFormat:KHLocalizedString(@"value.plural",nil), count]; // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}} expected-note {{Plural}}
+ return [NSString stringWithFormat:KHLocalizedString(@"value.plural",nil), count]; // expected-warning {{Plural cases are not supported across all languages. Use a .stringsdict file}} expected-note {{Plural}}
}
}
@@ -169,7 +169,7 @@ NSString *KHLocalizedString(NSString* key, NSString* comment) {
if (someOtherVariable)
return KHLocalizedString(@"OK",nil); // no-warning
} else {
- return KHLocalizedString(@"value.plural",nil); // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}} expected-note {{Plural}}
+ return KHLocalizedString(@"value.plural",nil); // expected-warning {{Plural cases are not supported across all languages. Use a .stringsdict file}} expected-note {{Plural}}
}
return nil;
}
diff --git a/test/Analysis/loop-unrolling.cpp b/test/Analysis/loop-unrolling.cpp
index 844d1f18ea57..b7375df38b69 100644
--- a/test/Analysis/loop-unrolling.cpp
+++ b/test/Analysis/loop-unrolling.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config unroll-loops=true,cfg-loopexit=true -verify -std=c++11 %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config unroll-loops=true,cfg-loopexit=true -verify -std=c++11 -analyzer-config exploration_strategy=unexplored_first_queue %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config unroll-loops=true,cfg-loopexit=true,exploration_strategy=dfs -verify -std=c++11 -DDFS=1 %s
void clang_analyzer_numTimesReached();
void clang_analyzer_warnIfReached();
@@ -35,6 +36,29 @@ int simple_unroll2() {
return 0;
}
+int simple_unroll3_unsigned() {
+ int a[9];
+ int k = 42;
+ for (unsigned i = 0; i < 9; i++) {
+ clang_analyzer_numTimesReached(); // expected-warning {{9}}
+ a[i] = 42;
+ }
+ int b = 22 / (k - 42); // expected-warning {{Division by zero}}
+ return 0;
+}
+
+int simple_unroll4_unsigned() {
+ int a[9];
+ int k = 42;
+ unsigned i;
+ for (i = (0); i < 9; i++) {
+ clang_analyzer_numTimesReached(); // expected-warning {{9}}
+ a[i] = 42;
+ }
+ int b = 22 / (k - 42); // expected-warning {{Division by zero}}
+ return 0;
+}
+
int simple_no_unroll1() {
int a[9];
int k = 42;
@@ -98,13 +122,101 @@ int simple_no_unroll5() {
return 0;
}
+int no_unroll_assignment() {
+ for (int i = 0; i < 9; i++) {
+ i = i + 1;
+ clang_analyzer_numTimesReached(); // expected-warning {{4}}
+ }
+ return 0;
+}
+
+int no_unroll_assignment2() {
+ for (int i = 0; i < 9; i++) {
+ i *= 2;
+ clang_analyzer_numTimesReached(); // expected-warning {{4}}
+ }
+ return 0;
+}
+
+int no_unroll_assignment3() {
+ for (int i = 128; i > 0; i--) {
+ i /= 2;
+ clang_analyzer_numTimesReached(); // expected-warning {{4}}
+ }
+ return 0;
+}
+
+int no_unroll_assignment4() {
+ for (int i = 0; i < 9; i++) {
+ i -= 2;
+ clang_analyzer_numTimesReached(); // expected-warning {{4}}
+ }
+ return 0;
+}
+
+int no_unroll_assignment5() {
+ for (int i = 0; i < 9; i++) {
+ i += 1;
+ clang_analyzer_numTimesReached(); // expected-warning {{4}}
+ }
+ return 0;
+}
+
+int no_unroll_assignment6() {
+ for (int i = 128; i > 0; i--) {
+ i >>= 1;
+ clang_analyzer_numTimesReached(); // expected-warning {{4}}
+ }
+ return 0;
+}
+
+int no_unroll_assignment7() {
+ for (int i = 0; i < 512; i++) {
+ i <<= 1;
+ clang_analyzer_numTimesReached(); // expected-warning {{4}}
+ }
+ return 0;
+}
+
+int no_unroll_assignment8() {
+ for (int i = 0; i < 9; i++) {
+ i %= 8;
+ clang_analyzer_numTimesReached(); // expected-warning {{4}}
+ }
+ return 0;
+}
+
+int no_unroll_assignment9() {
+ for (int i = 0; i < 9; i++) {
+ i &= 31;
+ clang_analyzer_numTimesReached(); // expected-warning {{4}}
+ }
+ return 0;
+}
+
+int no_unroll_assignment10() {
+ for (int i = 0; i < 9; i++) {
+ i |= 2;
+ clang_analyzer_numTimesReached(); // expected-warning {{4}}
+ }
+ return 0;
+}
+
+int no_unroll_assignment11() {
+ for (int i = 0; i < 9; i++) {
+ i ^= 2;
+ clang_analyzer_numTimesReached(); // expected-warning {{4}}
+ }
+ return 0;
+}
+
int make_new_branches_loop_cached() {
for (int i = 0; i < 8; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{4}}
- if(getNum()){
- (void) i; // Since this Stmt does not change the State the analyzer
- // won't make a new execution path but reuse the earlier nodes.
- }
+ if (getNum()) {
+ (void)i; // Since this Stmt does not change the State the analyzer
+ // won't make a new execution path but reuse the earlier nodes.
+ }
}
clang_analyzer_warnIfReached(); // no-warning
return 0;
@@ -114,7 +226,7 @@ int make_new_branches_loop_uncached() {
int l = 2;
for (int i = 0; i < 8; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{10}}
- if(getNum()){
+ if (getNum()) {
++l;
}
}
@@ -126,7 +238,7 @@ int make_new_branches_loop_uncached2() {
int l = 2;
for (int i = 0; i < 8; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{10}}
- if(getNum()){
+ if (getNum()) {
++l;
}
(void)&i; // This ensures that the loop won't be unrolled.
@@ -184,7 +296,7 @@ int nested_outer_unrolled() {
for (j = 0; j < 9; ++j) {
clang_analyzer_numTimesReached(); // expected-warning {{4}}
a[j] = 22;
- (void) &j; // ensures that the inner loop won't be unrolled
+ (void)&j; // ensures that the inner loop won't be unrolled
}
a[i] = 42;
}
@@ -234,7 +346,11 @@ int simple_known_bound_loop() {
int simple_unknown_bound_loop() {
for (int i = 2; i < getNum(); i++) {
+#ifdef DFS
clang_analyzer_numTimesReached(); // expected-warning {{10}}
+#else
+ clang_analyzer_numTimesReached(); // expected-warning {{13}}
+#endif
}
return 0;
}
@@ -252,7 +368,11 @@ int nested_inlined_unroll1() {
int nested_inlined_no_unroll1() {
int k;
for (int i = 0; i < 9; i++) {
+#ifdef ANALYZER_CM_Z3
+ clang_analyzer_numTimesReached(); // expected-warning {{13}}
+#else
clang_analyzer_numTimesReached(); // expected-warning {{15}}
+#endif
k = simple_unknown_bound_loop(); // reevaluation without inlining, splits the state as well
}
int a = 22 / k; // no-warning
@@ -263,8 +383,8 @@ int recursion_unroll1(bool b) {
int k = 2;
for (int i = 0; i < 5; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{13}}
- if(i == 0 && b) // Splits the state in the first iteration but the recursion
- // call will be unrolled anyway since the condition is known there.
+ if (i == 0 && b) // Splits the state in the first iteration but the recursion
+ // call will be unrolled anyway since the condition is known there.
recursion_unroll1(false);
clang_analyzer_numTimesReached(); // expected-warning {{14}}
}
@@ -276,7 +396,7 @@ int recursion_unroll2(bool b) {
int k = 0;
for (int i = 0; i < 5; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{9}}
- if(i == 0 && b)
+ if (i == 0 && b)
recursion_unroll2(false);
clang_analyzer_numTimesReached(); // expected-warning {{9}}
}
@@ -302,7 +422,7 @@ int recursion_unroll4(bool b) {
int k = 2;
for (int i = 0; i < 5; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{13}}
- if(i == 0 && b) {
+ if (i == 0 && b) {
recursion_unroll4(false);
continue;
}
diff --git a/test/Analysis/loop-widening-preserve-reference-type.cpp b/test/Analysis/loop-widening-preserve-reference-type.cpp
new file mode 100644
index 000000000000..b5746d1fe767
--- /dev/null
+++ b/test/Analysis/loop-widening-preserve-reference-type.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-max-loop 4 -analyzer-config widen-loops=true -verify %s
+
+void clang_analyzer_eval(int);
+
+struct A {
+ ~A() {}
+};
+struct B : public A {};
+
+void invalid_type_region_access() {
+ const A &x = B();
+ for (int i = 0; i < 10; ++i) { }
+ clang_analyzer_eval(&x != 0); // expected-warning{{TRUE}}
+} // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to true}}
diff --git a/test/Analysis/loop-widening.c b/test/Analysis/loop-widening.c
index de17951d180f..3378893b3257 100644
--- a/test/Analysis/loop-widening.c
+++ b/test/Analysis/loop-widening.c
@@ -1,4 +1,5 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-max-loop 4 -analyzer-config widen-loops=true -verify %s
+// RUN: %clang_analyze_cc1 -DTEST_NULL_TERM -analyzer-checker=core,unix.Malloc,debug.ExprInspection,alpha.cplusplus.IteratorRange -analyzer-max-loop 4 -analyzer-config widen-loops=true -verify %s
void clang_analyzer_eval(int);
void clang_analyzer_warnIfReached();
@@ -188,3 +189,16 @@ void nested_loop_inner_widen() {
}
clang_analyzer_eval(i >= 2); // expected-warning {{TRUE}}
}
+
+#ifdef TEST_NULL_TERM
+void null_terminator_loop_widen(int *a) {
+ int c;
+ // Loop widening will call 'invalidateRegions()' and 'invalidateRegions()'
+ // will construct the SymbolConjured with null Stmt because of the null
+ // terminator statement. Accessing the null Stmt will cause a crash.
+ for (;;) {
+ c = *a; // no-crash
+ a++;
+ }
+}
+#endif
diff --git a/test/Analysis/malloc-custom.c b/test/Analysis/malloc-custom.c
index f33b150de678..053d0ee31ca8 100644
--- a/test/Analysis/malloc-custom.c
+++ b/test/Analysis/malloc-custom.c
@@ -1,6 +1,6 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc -Wno-incompatible-library-redeclaration -verify %s
-// Various tests to make the the analyzer is robust against custom
+// Various tests to make the analyzer is robust against custom
// redeclarations of memory routines.
//
// You wouldn't expect to see much of this in normal code, but, for example,
diff --git a/test/Analysis/malloc-fnptr-plist.c b/test/Analysis/malloc-fnptr-plist.c
new file mode 100644
index 000000000000..6490eeb1cc03
--- /dev/null
+++ b/test/Analysis/malloc-fnptr-plist.c
@@ -0,0 +1,11 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker core,unix.Malloc -analyzer-output=plist -o %t.plist -verify %s
+// RUN: FileCheck --input-file=%t.plist %s
+
+void free(void *);
+void (*fnptr)(int);
+void foo() {
+ free((void *)fnptr); // expected-warning{{Argument to free() is a function pointer}}
+}
+
+// Make sure the bug category is correct.
+// CHECK: <key>category</key><string>Memory error</string>
diff --git a/test/Analysis/malloc-plist.c b/test/Analysis/malloc-plist.c
index 513bf7766706..1f2870863cc7 100644
--- a/test/Analysis/malloc-plist.c
+++ b/test/Analysis/malloc-plist.c
@@ -1,5 +1,5 @@
// RUN: rm -f %t
-// RUN: %clang_analyze_cc1 -fblocks -analyzer-checker=core,unix.Malloc -analyzer-output=plist -analyzer-config path-diagnostics-alternate=false -o %t %s
+// RUN: %clang_analyze_cc1 -fblocks -analyzer-checker=core,unix.Malloc -analyzer-output=plist -verify -o %t %s
// RUN: FileCheck -input-file %t %s
typedef __typeof(sizeof(int)) size_t;
@@ -19,8 +19,8 @@ void diagnosticTest(int in) {
void myArrayAllocation() {
int **A;
A = malloc(2*sizeof(int*));
- A[0] = 0;// expected-warning {{leak}}
-}
+ A[0] = 0;
+}//expected-warning{{Potential leak}}
void reallocDiagnostics() {
char * buf = malloc(100);
@@ -44,7 +44,7 @@ void *wrapper() {
void test_wrapper() {
void *buf = wrapper();
(void) buf;
-}
+}//expected-warning{{Potential leak}}
// Test what happens when the same call frees and allocated memory.
// Also tests the stack hint for parameters, when they are passed directly or via pointer.
@@ -60,7 +60,7 @@ void my_malloc_and_free(void **x) {
void *test_double_action_call() {
void *buf;
my_malloc_and_free(&buf);
- return buf;
+ return buf; //expected-warning{{Use of memory after it is freed}}
}
// Test stack hint for 'reallocation failed'.
@@ -75,7 +75,7 @@ char *my_realloc(char *buf) {
void reallocIntra() {
char *buf = (char *)malloc(100);
buf = my_realloc(buf);
- free(buf);
+ free(buf);//expected-warning{{Potential leak}}
}
// Test stack hint when returning a result.
@@ -85,7 +85,7 @@ static char *malloc_wrapper_ret() {
void use_ret() {
char *v;
v = malloc_wrapper_ret();
-}
+}//expected-warning{{Potential leak}}
// Passing a block as a parameter to an inlined call for which we generate
// a stack hint message caused crashes.
@@ -99,7 +99,7 @@ void call_myfree_takingblock() {
int *p = malloc(sizeof(int));
myfree_takingblock(some_block, p);
- *p = 3;
+ *p = 3;//expected-warning{{Use of memory after it is freed}}
}
// Test that we refer to the last symbol used in the leak diagnostic.
@@ -112,13 +112,13 @@ void LeakedSymbol(int in) {
m = p;
p = 0;
(*m)++;
- in++;
+ in++;//expected-warning{{Potential leak}}
}
// Tests that exercise running remove dead bindings at Call exit.
static void function_with_leak1() {
char *x = (char*)malloc(12);
-}
+} //expected-warning{{Potential leak}}
void use_function_with_leak1() {
function_with_leak1();
int y = 0;
@@ -126,7 +126,7 @@ void use_function_with_leak1() {
static void function_with_leak2() {
char *x = (char*)malloc(12);
- int m = 0;
+ int m = 0; //expected-warning{{Potential leak}}
}
void use_function_with_leak2() {
function_with_leak2();
@@ -136,7 +136,7 @@ static void function_with_leak3(int y) {
char *x = (char*)malloc(12);
if (y)
y++;
-}
+}//expected-warning{{Potential leak}}
void use_function_with_leak3(int y) {
function_with_leak3(y);
}
@@ -146,7 +146,7 @@ static void function_with_leak4(int y) {
if (y)
y++;
else
- y--;
+ y--;//expected-warning{{Potential leak}}
}
void use_function_with_leak4(int y) {
function_with_leak4(y);
@@ -157,7 +157,7 @@ int anotherFunction5() {
}
static int function_with_leak5() {
char *x = (char*)malloc(12);
- return anotherFunction5();
+ return anotherFunction5();//expected-warning{{Potential leak}}
}
void use_function_with_leak5() {
function_with_leak5();
@@ -168,7 +168,7 @@ void anotherFunction6(int m) {
}
static void function_with_leak6() {
char *x = (char*)malloc(12);
- anotherFunction6(3);
+ anotherFunction6(3);//expected-warning{{Potential leak}}
}
void use_function_with_leak6() {
function_with_leak6();
@@ -184,7 +184,7 @@ static char *function_with_leak7() {
}
void use_function_with_leak7() {
function_with_leak7();
-}
+}//expected-warning{{Potential memory leak}}
// Test that we do not print the name of a variable not visible from where
// the issue is reported.
@@ -194,7 +194,7 @@ int *my_malloc() {
}
void testOnlyRefferToVisibleVariables() {
my_malloc();
-} // expected-warning {{Potential leak of memory}}
+} // expected-warning{{Potential memory leak}}
struct PointerWrapper{
int*p;
@@ -205,8 +205,8 @@ int *my_malloc_into_struct() {
return w.p;
}
void testMyMalloc() {
- my_malloc_into_struct(); // expected-warning {{Potential leak of memory}}
-}
+ my_malloc_into_struct();
+} // expected-warning{{Potential memory leak}}
// CHECK: <key>diagnostics</key>
// CHECK-NEXT: <array>
@@ -311,40 +311,6 @@ void testMyMalloc() {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -382,12 +348,46 @@ void testMyMalloc() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
+// CHECK-NEXT: <key>col</key><integer>9</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
+// CHECK-NEXT: <key>col</key><integer>11</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>14</integer>
+// CHECK-NEXT: <key>col</key><integer>9</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>14</integer>
+// CHECK-NEXT: <key>col</key><integer>9</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>14</integer>
+// CHECK-NEXT: <key>col</key><integer>9</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>14</integer>
+// CHECK-NEXT: <key>col</key><integer>9</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -476,40 +476,6 @@ void testMyMalloc() {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -547,12 +513,46 @@ void testMyMalloc() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>22</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>22</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>22</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>22</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -607,40 +607,6 @@ void testMyMalloc() {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>26</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>26</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>26</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>26</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -678,12 +644,12 @@ void testMyMalloc() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>26</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>26</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
+// CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -704,40 +670,6 @@ void testMyMalloc() {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -775,12 +707,12 @@ void testMyMalloc() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -1106,40 +1038,6 @@ void testMyMalloc() {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -1177,12 +1075,12 @@ void testMyMalloc() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
+// CHECK-NEXT: <key>col</key><integer>6</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -1349,6 +1247,74 @@ void testMyMalloc() {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>45</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>45</integer>
+// CHECK-NEXT: <key>col</key><integer>6</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>45</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>45</integer>
+// CHECK-NEXT: <key>col</key><integer>6</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>46</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>46</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>46</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>46</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>47</integer>
// CHECK-NEXT: <key>col</key><integer>1</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
@@ -1508,40 +1474,6 @@ void testMyMalloc() {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>55</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>55</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>55</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>55</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -1579,12 +1511,12 @@ void testMyMalloc() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>55</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>55</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -1983,40 +1915,6 @@ void testMyMalloc() {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -2054,12 +1952,46 @@ void testMyMalloc() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
+// CHECK-NEXT: <key>col</key><integer>8</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>77</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>77</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>77</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>77</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -2191,40 +2123,6 @@ void testMyMalloc() {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>69</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>69</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>69</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>69</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -2262,12 +2160,12 @@ void testMyMalloc() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>69</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>69</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -2497,6 +2395,40 @@ void testMyMalloc() {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>77</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>77</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>77</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>77</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>78</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
@@ -2566,6 +2498,40 @@ void testMyMalloc() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>87</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>87</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>87</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>87</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>87</integer>
// CHECK-NEXT: <key>col</key><integer>9</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -2656,40 +2622,6 @@ void testMyMalloc() {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -2768,6 +2700,40 @@ void testMyMalloc() {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>87</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>87</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>87</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>87</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>88</integer>
// CHECK-NEXT: <key>col</key><integer>1</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
@@ -2850,40 +2816,6 @@ void testMyMalloc() {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -2921,12 +2853,12 @@ void testMyMalloc() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -3103,6 +3035,40 @@ void testMyMalloc() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>102</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>102</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>102</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>102</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>102</integer>
// CHECK-NEXT: <key>col</key><integer>6</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -3199,40 +3165,6 @@ void testMyMalloc() {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>109</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>109</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>109</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>109</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -3270,12 +3202,12 @@ void testMyMalloc() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>109</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>109</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -3407,40 +3339,6 @@ void testMyMalloc() {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -3478,12 +3376,12 @@ void testMyMalloc() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
+// CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -3615,40 +3513,6 @@ void testMyMalloc() {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -3686,12 +3550,12 @@ void testMyMalloc() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
+// CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -3823,40 +3687,6 @@ void testMyMalloc() {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -3894,12 +3724,12 @@ void testMyMalloc() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
+// CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -4128,40 +3958,6 @@ void testMyMalloc() {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -4199,12 +3995,12 @@ void testMyMalloc() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
+// CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -4433,40 +4229,6 @@ void testMyMalloc() {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -4504,12 +4266,46 @@ void testMyMalloc() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
+// CHECK-NEXT: <key>col</key><integer>8</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>160</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>160</integer>
+// CHECK-NEXT: <key>col</key><integer>10</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>160</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>160</integer>
+// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -4641,40 +4437,6 @@ void testMyMalloc() {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -4712,12 +4474,12 @@ void testMyMalloc() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
+// CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -4849,40 +4611,6 @@ void testMyMalloc() {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>183</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>183</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>183</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>183</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -5086,6 +4814,35 @@ void testMyMalloc() {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>192</integer>
+// CHECK-NEXT: <key>col</key><integer>12</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>192</integer>
+// CHECK-NEXT: <key>col</key><integer>12</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>192</integer>
+// CHECK-NEXT: <key>col</key><integer>21</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>1</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Memory is allocated</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Memory is allocated</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
// CHECK-NEXT: <key>edges</key>
// CHECK-NEXT: <array>
@@ -5106,13 +4863,13 @@ void testMyMalloc() {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
+// CHECK-NEXT: <key>line</key><integer>193</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
+// CHECK-NEXT: <key>line</key><integer>193</integer>
+// CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -5123,35 +4880,6 @@ void testMyMalloc() {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>196</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
@@ -5357,6 +5085,35 @@ void testMyMalloc() {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>204</integer>
+// CHECK-NEXT: <key>col</key><integer>9</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>204</integer>
+// CHECK-NEXT: <key>col</key><integer>9</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>204</integer>
+// CHECK-NEXT: <key>col</key><integer>18</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>1</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Memory is allocated</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Memory is allocated</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
// CHECK-NEXT: <key>edges</key>
// CHECK-NEXT: <array>
@@ -5377,13 +5134,13 @@ void testMyMalloc() {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>204</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
+// CHECK-NEXT: <key>line</key><integer>205</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>204</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
+// CHECK-NEXT: <key>line</key><integer>205</integer>
+// CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -5394,35 +5151,6 @@ void testMyMalloc() {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>204</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>204</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>204</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>208</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
@@ -5514,5 +5242,3 @@ void testMyMalloc() {
// CHECK-NEXT: </dict>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </plist>
diff --git a/test/Analysis/malloc.c b/test/Analysis/malloc.c
index 4c364ebd9a2f..3e86c29a55a5 100644
--- a/test/Analysis/malloc.c
+++ b/test/Analysis/malloc.c
@@ -375,7 +375,7 @@ void CheckUseZeroReallocatedPathWarn(_Bool b) {
// or inter-procedural analysis, this is a conservative answer.
int *f3() {
static int *p = 0;
- p = malloc(12);
+ p = malloc(12);
return p; // no-warning
}
@@ -384,7 +384,7 @@ int *f3() {
// functions or inter-procedural analysis, this is a conservative answer.
static int *p_f4 = 0;
int *f4() {
- p_f4 = malloc(12);
+ p_f4 = malloc(12);
return p_f4; // no-warning
}
@@ -1232,7 +1232,7 @@ void radar10978247(int myValueSize) {
if (myValueSize <= sizeof(stackBuffer))
buffer = stackBuffer;
- else
+ else
buffer = malloc(myValueSize);
// do stuff with the buffer
@@ -1246,7 +1246,7 @@ void radar10978247_positive(int myValueSize) {
if (myValueSize <= sizeof(stackBuffer))
buffer = stackBuffer;
- else
+ else
buffer = malloc(myValueSize);
// do stuff with the buffer
@@ -1254,7 +1254,7 @@ void radar10978247_positive(int myValueSize) {
return;
else
return; // expected-warning {{leak}}
-}
+}
// <rdar://problem/11269741> Previously this triggered a false positive
// because malloc() is known to return uninitialized memory and the binding
// of 'o' to 'p->n' was not getting propertly handled. Now we report a leak.
@@ -1698,7 +1698,7 @@ void testReallocEscaped(void **memory) {
void *smallocNoWarn(size_t size) {
if (size == 0) {
return malloc(1); // this branch is never called
- }
+ }
else {
return malloc(size);
}
@@ -1720,13 +1720,6 @@ void *smallocWarn(size_t size) {
}
}
-char *dupstrWarn(const char *s) {
- const int len = strlen(s);
- char *p = (char*) smallocWarn(len + 1);
- strcpy(p, s); // expected-warning{{String copy function overflows destination buffer}}
- return p;
-}
-
int *radar15580979() {
int *data = (int *)malloc(32);
int *p = data ?: (int*)malloc(32); // no warning
@@ -1784,6 +1777,18 @@ void freeFunctionPtr() {
free((void *)fnptr); // expected-warning {{Argument to free() is a function pointer}}
}
+void allocateSomeMemory(void *offendingParameter, void **ptr) {
+ *ptr = malloc(1);
+}
+
+void testNoCrashOnOffendingParameter() {
+ // "extern" is necessary to avoid unrelated warnings
+ // on passing uninitialized value.
+ extern void *offendingParameter;
+ void* ptr;
+ allocateSomeMemory(offendingParameter, &ptr);
+} // expected-warning {{Potential leak of memory pointed to by 'ptr'}}
+
// ----------------------------------------------------------------------------
// False negatives.
diff --git a/test/Analysis/malloc.cpp b/test/Analysis/malloc.cpp
index c323754bb467..b93c73e591cd 100644
--- a/test/Analysis/malloc.cpp
+++ b/test/Analysis/malloc.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_analyze_cc1 -w -analyzer-checker=core,alpha.deadcode.UnreachableCode,alpha.core.CastSize,unix.Malloc,cplusplus.NewDelete -analyzer-store=region -verify %s
// RUN: %clang_analyze_cc1 -triple i386-unknown-linux-gnu -w -analyzer-checker=core,alpha.deadcode.UnreachableCode,alpha.core.CastSize,unix.Malloc,cplusplus.NewDelete -analyzer-store=region -verify %s
+// RUN: %clang_analyze_cc1 -w -analyzer-checker=core,alpha.deadcode.UnreachableCode,alpha.core.CastSize,unix.Malloc,cplusplus.NewDelete -analyzer-store=region -DTEST_INLINABLE_ALLOCATORS -verify %s
+// RUN: %clang_analyze_cc1 -triple i386-unknown-linux-gnu -w -analyzer-checker=core,alpha.deadcode.UnreachableCode,alpha.core.CastSize,unix.Malloc,cplusplus.NewDelete -analyzer-store=region -DTEST_INLINABLE_ALLOCATORS -verify %s
#include "Inputs/system-header-simulator-cxx.h"
diff --git a/test/Analysis/malloc.mm b/test/Analysis/malloc.mm
index e3daa858be87..d7bfbf3f34f3 100644
--- a/test/Analysis/malloc.mm
+++ b/test/Analysis/malloc.mm
@@ -320,3 +320,13 @@ void test12365078_check_positive() {
NSString *string = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
if (string) free(characters); // expected-warning{{Attempt to free non-owned memory}}
}
+
+void *test_reinterpret_cast_to_block() {
+ // Used to leak because the pointer was disappearing
+ // during the reinterpret_cast.
+ using BlockPtrTy = void (^)();
+ struct Block {};
+ Block* block = static_cast<Block*>(malloc(sizeof(Block)));
+ BlockPtrTy blockPtr = reinterpret_cast<BlockPtrTy>(block); // no-warning
+ return blockPtr;
+}
diff --git a/test/Analysis/method-call-path-notes.cpp b/test/Analysis/method-call-path-notes.cpp
index e6253d4f89c3..7c93c99bfd8c 100644
--- a/test/Analysis/method-call-path-notes.cpp
+++ b/test/Analysis/method-call-path-notes.cpp
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=text -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file -analyzer-config path-diagnostics-alternate=false %s -o %t.plist
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file %s -o %t.plist
// RUN: FileCheck --input-file=%t.plist %s
// Test warning about null or uninitialized pointer values used as instance member
diff --git a/test/Analysis/misc-ps-region-store.m b/test/Analysis/misc-ps-region-store.m
index 9bd207326350..1ef100563126 100644
--- a/test/Analysis/misc-ps-region-store.m
+++ b/test/Analysis/misc-ps-region-store.m
@@ -1109,7 +1109,7 @@ void pr8015_C() {
}
// Tests that we correctly handle that 'number' is perfectly constrained
-// after 'if (nunber == 0)', allowing us to resolve that
+// after 'if (number == 0)', allowing us to resolve that
// numbers[number] == numbers[0].
void pr8015_D_FIXME() {
int number = pr8015_A();
diff --git a/test/Analysis/missing-bind-temporary.cpp b/test/Analysis/missing-bind-temporary.cpp
new file mode 100644
index 000000000000..6071f5b5fae1
--- /dev/null
+++ b/test/Analysis/missing-bind-temporary.cpp
@@ -0,0 +1,130 @@
+// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux -analyzer-checker=debug.DumpCFG -std=c++14 %s > %t 2>&1
+// RUN: FileCheck --input-file=%t %s
+// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux -analyzer-checker=core,debug.ExprInspection -std=c++14 -verify %s
+
+void clang_analyzer_eval(bool);
+
+int global;
+
+namespace variant_0 {
+// This variant of the code works correctly. Function foo() is not a template
+// function. Note that there are two destructors within foo().
+
+class A {
+public:
+ ~A() { ++global; }
+};
+
+class B {
+ A a;
+};
+
+// CHECK: void foo(int)
+// CHECK: [B1]
+// CHECK-NEXT: 1: (CXXConstructExpr, [B1.2], class variant_0::B)
+// CHECK-NEXT: 2: variant_0::B i;
+// CHECK-NEXT: 3: operator=
+// CHECK-NEXT: 4: [B1.3] (ImplicitCastExpr, FunctionToPointerDecay, class variant_0::B &(*)(class variant_0::B &&) noexcept)
+// CHECK-NEXT: 5: i
+// CHECK-NEXT: 6: {} (CXXConstructExpr, [B1.7], [B1.8], class variant_0::B)
+// CHECK-NEXT: 7: [B1.6] (BindTemporary)
+// CHECK-NEXT: 8: [B1.7]
+// CHECK-NEXT: 9: [B1.5] = [B1.8] (OperatorCall)
+// CHECK-NEXT: 10: ~variant_0::B() (Temporary object destructor)
+// CHECK-NEXT: 11: [B1.2].~B() (Implicit destructor)
+void foo(int) {
+ B i;
+ i = {};
+}
+
+void bar() {
+ global = 0;
+ foo(1);
+ clang_analyzer_eval(global == 2); // expected-warning{{TRUE}}
+}
+
+} // end namespace variant_0
+
+namespace variant_1 {
+// Suddenly, if we turn foo() into a template, we are missing a
+// CXXBindTemporaryExpr in the AST, and therefore we're missing a
+// temporary destructor in the CFG.
+
+class A {
+public:
+ ~A() { ++global; }
+};
+
+class B {
+ A a;
+};
+
+// FIXME: Find the construction context for {} and enforce the temporary
+// destructor.
+// CHECK: template<> void foo<int>(int)
+// CHECK: [B1]
+// CHECK-NEXT: 1: (CXXConstructExpr, [B1.2], class variant_1::B)
+// CHECK-NEXT: 2: variant_1::B i;
+// CHECK-NEXT: 3: operator=
+// CHECK-NEXT: 4: [B1.3] (ImplicitCastExpr, FunctionToPointerDecay, class variant_1::B &(*)(class variant_1::B &&) noexcept)
+// CHECK-NEXT: 5: i
+// CHECK-NEXT: 6: {} (CXXConstructExpr, class variant_1::B)
+// CHECK-NEXT: 7: [B1.6]
+// CHECK-NEXT: 8: [B1.5] = [B1.7] (OperatorCall)
+// CHECK-NEXT: 9: [B1.2].~B() (Implicit destructor)
+template <typename T> void foo(T) {
+ B i;
+ i = {};
+}
+
+void bar() {
+ global = 0;
+ foo(1);
+ // FIXME: Should be TRUE, i.e. we should call (and inline) two destructors.
+ clang_analyzer_eval(global == 2); // expected-warning{{UNKNOWN}}
+}
+
+} // end namespace variant_1
+
+namespace variant_2 {
+// Making field 'a' in class 'B' public turns the class into an aggregate.
+// In this case there is no constructor at {} - only an aggregate
+// initialization. Aggregate initialization is unsupported for now.
+
+class A {
+public:
+ ~A() { ++global; }
+};
+
+class B {
+public:
+ A a;
+};
+
+// CHECK: template<> void foo<int>(int)
+// CHECK: [B1]
+// CHECK-NEXT: 1: (CXXConstructExpr, [B1.2], class variant_2::B)
+// CHECK-NEXT: 2: variant_2::B i;
+// CHECK-NEXT: 3: operator=
+// CHECK-NEXT: 4: [B1.3] (ImplicitCastExpr, FunctionToPointerDecay, class variant_2::B &(*)(class variant_2::B &&) noexcept)
+// CHECK-NEXT: 5: i
+// CHECK-NEXT: 6: {}
+// CHECK-NEXT: 7: {}
+// CHECK-NEXT: 8: [B1.7] (BindTemporary)
+// CHECK-NEXT: 9: [B1.8]
+// CHECK-NEXT: 10: [B1.5] = [B1.9] (OperatorCall)
+// CHECK-NEXT: 11: ~variant_2::B() (Temporary object destructor)
+// CHECK-NEXT: 12: [B1.2].~B() (Implicit destructor)
+template <typename T> void foo(T) {
+ B i;
+ i = {};
+}
+
+void bar() {
+ global = 0;
+ foo(1);
+ // FIXME: Should be TRUE, i.e. we should call (and inline) two destructors.
+ clang_analyzer_eval(global == 2); // expected-warning{{UNKNOWN}}
+}
+
+} // end namespace variant_2
diff --git a/test/Analysis/mmap-writeexec.c b/test/Analysis/mmap-writeexec.c
new file mode 100644
index 000000000000..2ebc96110342
--- /dev/null
+++ b/test/Analysis/mmap-writeexec.c
@@ -0,0 +1,44 @@
+// RUN: %clang_analyze_cc1 -triple i686-unknown-linux -analyzer-checker=alpha.security.MmapWriteExec -analyzer-config alpha.security.MmapWriteExec:MmapProtExec=1 -analyzer-config alpha.security.MmapWriteExec:MmapProtRead=4 -DUSE_ALTERNATIVE_PROT_EXEC_DEFINITION -verify %s
+// RUN: %clang_analyze_cc1 -triple x86_64-unknown-apple-darwin10 -analyzer-checker=alpha.security.MmapWriteExec -verify %s
+
+#define PROT_WRITE 0x02
+#ifndef USE_ALTERNATIVE_PROT_EXEC_DEFINITION
+#define PROT_EXEC 0x04
+#define PROT_READ 0x01
+#else
+#define PROT_EXEC 0x01
+#define PROT_READ 0x04
+#endif
+#define MAP_PRIVATE 0x0002
+#define MAP_ANON 0x1000
+#define MAP_FIXED 0x0010
+#define NULL ((void *)0)
+
+typedef __typeof(sizeof(int)) size_t;
+void *mmap(void *, size_t, int, int, int, long);
+int mprotect(void *, size_t, int);
+
+void f1()
+{
+ void *a = mmap(NULL, 16, PROT_READ | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0); // no-warning
+ void *b = mmap(a, 16, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED | MAP_ANON, -1, 0); // no-warning
+ void *c = mmap(NULL, 32, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0); // expected-warning{{Both PROT_WRITE and PROT_EXEC flags are set. This can lead to exploitable memory regions, which could be overwritten with malicious code}}
+ (void)a;
+ (void)b;
+ (void)c;
+}
+
+void f2()
+{
+ void *(*callm)(void *, size_t, int, int, int, long);
+ callm = mmap;
+ int prot = PROT_WRITE | PROT_EXEC;
+ (void)callm(NULL, 1024, prot, MAP_PRIVATE | MAP_ANON, -1, 0); // expected-warning{{Both PROT_WRITE and PROT_EXEC flags are set. This can lead to exploitable memory regions, which could be overwritten with malicious code}}
+}
+
+void f3()
+{
+ void *p = mmap(NULL, 1024, PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); // no-warning
+ int m = mprotect(p, 1024, PROT_WRITE | PROT_EXEC); // expected-warning{{Both PROT_WRITE and PROT_EXEC flags are set. This can lead to exploitable memory regions, which could be overwritten with malicious code}}
+ (void)m;
+}
diff --git a/test/Analysis/new-ctor-conservative.cpp b/test/Analysis/new-ctor-conservative.cpp
new file mode 100644
index 000000000000..b82df9abf1e2
--- /dev/null
+++ b/test/Analysis/new-ctor-conservative.cpp
@@ -0,0 +1,46 @@
+// RUN: %clang_analyze_cc1 -w -analyzer-checker=core,debug.ExprInspection -analyzer-config c++-allocator-inlining=true -std=c++11 -verify %s
+
+void clang_analyzer_eval(bool);
+void clang_analyzer_warnIfReached();
+
+struct S {
+ int x;
+ S() : x(1) {}
+ ~S() {}
+};
+
+void checkConstructorInlining() {
+ S *s = new S;
+ clang_analyzer_eval(s->x == 1); // expected-warning{{TRUE}}
+}
+
+void checkNewPOD() {
+ int *i = new int;
+ clang_analyzer_eval(*i == 0); // expected-warning{{UNKNOWN}}
+ int *j = new int();
+ clang_analyzer_eval(*j == 0); // expected-warning{{TRUE}}
+ int *k = new int(5);
+ clang_analyzer_eval(*k == 5); // expected-warning{{TRUE}}
+}
+
+void checkNewArray() {
+ S *s = new S[10];
+ // FIXME: Should be true once we inline array constructors.
+ clang_analyzer_eval(s[0].x == 1); // expected-warning{{UNKNOWN}}
+}
+
+struct NullS {
+ NullS() {
+ if (this) {}
+ }
+ NullS(int x) {
+ if (!this) {
+ clang_analyzer_warnIfReached(); // no-warning
+ }
+ }
+};
+
+void checkNullThis() {
+ NullS *nulls = new NullS(); // no-crash
+ NullS *nulls2 = new NullS(0);
+}
diff --git a/test/Analysis/new-ctor-inlined.cpp b/test/Analysis/new-ctor-inlined.cpp
new file mode 100644
index 000000000000..1506bf27f353
--- /dev/null
+++ b/test/Analysis/new-ctor-inlined.cpp
@@ -0,0 +1,55 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config c++-allocator-inlining=true -std=c++11 -verify %s
+
+void clang_analyzer_eval(bool);
+
+typedef __typeof__(sizeof(int)) size_t;
+
+void *conjure();
+void exit(int);
+
+void *operator new(size_t size) throw() {
+ void *x = conjure();
+ if (x == 0)
+ exit(1);
+ return x;
+}
+
+struct S {
+ int x;
+ S() : x(1) {}
+ ~S() {}
+};
+
+void checkNewAndConstructorInlining() {
+ S *s = new S;
+ // Check that the symbol for 's' is not dying.
+ clang_analyzer_eval(s != 0); // expected-warning{{TRUE}}
+ // Check that bindings are correct (and also not dying).
+ clang_analyzer_eval(s->x == 1); // expected-warning{{TRUE}}
+}
+
+struct Sp {
+ Sp *p;
+ Sp(Sp *p): p(p) {}
+ ~Sp() {}
+};
+
+void checkNestedNew() {
+ Sp *p = new Sp(new Sp(0));
+ clang_analyzer_eval(p->p->p == 0); // expected-warning{{TRUE}}
+}
+
+void checkNewPOD() {
+ int *i = new int;
+ clang_analyzer_eval(*i == 0); // expected-warning{{UNKNOWN}}
+ int *j = new int();
+ clang_analyzer_eval(*j == 0); // expected-warning{{TRUE}}
+ int *k = new int(5);
+ clang_analyzer_eval(*k == 5); // expected-warning{{TRUE}}
+}
+
+void checkTrivialCopy() {
+ S s;
+ S *t = new S(s); // no-crash
+ clang_analyzer_eval(t->x == 1); // expected-warning{{TRUE}}
+}
diff --git a/test/Analysis/new-ctor-malloc.cpp b/test/Analysis/new-ctor-malloc.cpp
new file mode 100644
index 000000000000..74b1e21a5c97
--- /dev/null
+++ b/test/Analysis/new-ctor-malloc.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection,unix.Malloc -analyzer-config c++-allocator-inlining=true -analyzer-output=text -std=c++11 -verify %s
+
+void clang_analyzer_eval(bool);
+
+typedef __typeof__(sizeof(int)) size_t;
+
+void *malloc(size_t size);
+
+void *operator new(size_t size) throw() {
+ void *x = malloc(size); // expected-note {{Memory is allocated}}
+ if (!x) // expected-note {{Assuming 'x' is non-null}}
+ // expected-note@-1 {{Taking false branch}}
+ return nullptr;
+ return x;
+}
+
+void checkNewAndConstructorInlining() {
+ int *s = new int; // expected-note {{Calling 'operator new'}}
+ // expected-note@-1{{Returning from 'operator new'}}
+} // expected-warning {{Potential leak of memory pointed to by 's'}}
+ // expected-note@-1 {{Potential leak of memory pointed to by 's'}}
diff --git a/test/Analysis/new-ctor-null-throw.cpp b/test/Analysis/new-ctor-null-throw.cpp
new file mode 100644
index 000000000000..cdaf01d8de67
--- /dev/null
+++ b/test/Analysis/new-ctor-null-throw.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_analyze_cc1 -w -analyzer-checker=core,debug.ExprInspection -analyzer-config c++-allocator-inlining=true -std=c++11 -verify %s
+
+void clang_analyzer_eval(bool);
+
+typedef __typeof__(sizeof(int)) size_t;
+
+
+// These are ill-formed. One cannot return nullptr from a throwing version of an
+// operator new.
+void *operator new(size_t size) {
+ return nullptr;
+}
+void *operator new[](size_t size) {
+ return nullptr;
+}
+
+struct S {
+ int x;
+ S() : x(1) {}
+ ~S() {}
+};
+
+void testArrays() {
+ S *s = new S[10]; // no-crash
+ s[0].x = 2; // expected-warning{{Dereference of null pointer}}
+}
diff --git a/test/Analysis/new-ctor-null.cpp b/test/Analysis/new-ctor-null.cpp
new file mode 100644
index 000000000000..ac2a39a02840
--- /dev/null
+++ b/test/Analysis/new-ctor-null.cpp
@@ -0,0 +1,36 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config c++-allocator-inlining=true -std=c++11 -verify %s
+
+void clang_analyzer_eval(bool);
+void clang_analyzer_warnIfReached();
+
+typedef __typeof__(sizeof(int)) size_t;
+
+void *operator new(size_t size) throw() {
+ return nullptr;
+}
+void *operator new[](size_t size) throw() {
+ return nullptr;
+}
+
+struct S {
+ int x;
+ S() : x(1) {
+ // FIXME: Constructor should not be called with null this, even if it was
+ // returned by operator new().
+ clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
+ }
+ ~S() {}
+};
+
+void testArrays() {
+ S *s = new S[10]; // no-crash
+ s[0].x = 2; // expected-warning{{Dereference of null pointer}}
+}
+
+int global;
+void testInvalidationOnConstructionIntoNull() {
+ global = 0;
+ S *s = new S();
+ // FIXME: Should be FALSE - we should not invalidate globals.
+ clang_analyzer_eval(global); // expected-warning{{UNKNOWN}}
+}
diff --git a/test/Analysis/new-ctor-recursive.cpp b/test/Analysis/new-ctor-recursive.cpp
new file mode 100644
index 000000000000..e0c654bc74ab
--- /dev/null
+++ b/test/Analysis/new-ctor-recursive.cpp
@@ -0,0 +1,118 @@
+// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus.NewDelete,cplusplus.NewDeleteLeaks,debug.ExprInspection -analyzer-config c++-allocator-inlining=true -std=c++11 -verify %s
+
+void clang_analyzer_eval(bool);
+void clang_analyzer_dump(int);
+
+typedef __typeof__(sizeof(int)) size_t;
+
+void *conjure();
+void exit(int);
+
+struct S;
+
+S *global_s;
+
+// Recursive operator kinda placement new.
+void *operator new(size_t size, S *place);
+
+enum class ConstructionKind : char {
+ Garbage,
+ Recursive
+};
+
+struct S {
+public:
+ int x;
+ S(): x(1) {}
+ S(int y): x(y) {}
+
+ S(ConstructionKind k) {
+ switch (k) {
+ case ConstructionKind::Recursive: { // Call one more operator new 'r'ecursively.
+ S *s = new (nullptr) S(5);
+ x = s->x + 1;
+ global_s = s;
+ return;
+ }
+ case ConstructionKind::Garbage: {
+ // Leaves garbage in 'x'.
+ }
+ }
+ }
+ ~S() {}
+};
+
+// Do not try this at home!
+void *operator new(size_t size, S *place) {
+ if (!place)
+ return new S();
+ return place;
+}
+
+void testThatCharConstructorIndeedYieldsGarbage() {
+ S *s = new S(ConstructionKind::Garbage);
+ clang_analyzer_eval(s->x == 0); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(s->x == 1); // expected-warning{{UNKNOWN}}
+ // FIXME: This should warn, but MallocChecker doesn't default-bind regions
+ // returned by standard operator new to garbage.
+ s->x += 1; // no-warning
+ delete s;
+}
+
+
+void testChainedOperatorNew() {
+ S *s;
+ // * Evaluate standard new.
+ // * Evaluate constructor S(3).
+ // * Bind value for standard new.
+ // * Evaluate our custom new.
+ // * Evaluate constructor S(Garbage).
+ // * Bind value for our custom new.
+ s = new (new S(3)) S(ConstructionKind::Garbage);
+ clang_analyzer_eval(s->x == 3); // expected-warning{{TRUE}}
+ // expected-warning@+9{{Potential leak of memory pointed to by 's'}}
+
+ // * Evaluate standard new.
+ // * Evaluate constructor S(Garbage).
+ // * Bind value for standard new.
+ // * Evaluate our custom new.
+ // * Evaluate constructor S(4).
+ // * Bind value for our custom new.
+ s = new (new S(ConstructionKind::Garbage)) S(4);
+ clang_analyzer_eval(s->x == 4); // expected-warning{{TRUE}}
+ delete s;
+
+ // -> Enter our custom new (nullptr).
+ // * Evaluate standard new.
+ // * Inline constructor S().
+ // * Bind value for standard new.
+ // <- Exit our custom new (nullptr).
+ // * Evaluate constructor S(Garbage).
+ // * Bind value for our custom new.
+ s = new (nullptr) S(ConstructionKind::Garbage);
+ clang_analyzer_eval(s->x == 1); // expected-warning{{TRUE}}
+ delete s;
+
+ // -> Enter our custom new (nullptr).
+ // * Evaluate standard new.
+ // * Inline constructor S().
+ // * Bind value for standard new.
+ // <- Exit our custom new (nullptr).
+ // -> Enter constructor S(Recursive).
+ // -> Enter our custom new (nullptr).
+ // * Evaluate standard new.
+ // * Inline constructor S().
+ // * Bind value for standard new.
+ // <- Exit our custom new (nullptr).
+ // * Evaluate constructor S(5).
+ // * Bind value for our custom new (nullptr).
+ // * Assign that value to global_s.
+ // <- Exit constructor S(Recursive).
+ // * Bind value for our custom new (nullptr).
+ global_s = nullptr;
+ s = new (nullptr) S(ConstructionKind::Recursive);
+ clang_analyzer_eval(global_s); // expected-warning{{TRUE}}
+ clang_analyzer_eval(global_s->x == 5); // expected-warning{{TRUE}}
+ clang_analyzer_eval(s->x == 6); // expected-warning{{TRUE}}
+ delete s;
+}
diff --git a/test/Analysis/new-ctor-symbolic.cpp b/test/Analysis/new-ctor-symbolic.cpp
new file mode 100644
index 000000000000..8bef2ed2402c
--- /dev/null
+++ b/test/Analysis/new-ctor-symbolic.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config c++-allocator-inlining=true -std=c++11 -verify %s
+
+void clang_analyzer_eval(bool);
+void clang_analyzer_warnOnDeadSymbol(int);
+
+typedef __typeof__(sizeof(int)) size_t;
+
+int conjure();
+void exit(int);
+
+struct S {
+ S() {}
+ ~S() {}
+
+ static S buffer[1000];
+
+ // This operator allocates stuff within the buffer. Additionally, it never
+ // places anything at the beginning of the buffer.
+ void *operator new(size_t size) {
+ int i = conjure();
+ if (i == 0)
+ exit(1);
+ // Let's see if the symbol dies before new-expression is evaluated.
+ // It shouldn't.
+ clang_analyzer_warnOnDeadSymbol(i);
+ return buffer + i;
+ }
+};
+
+void testIndexLiveness() {
+ S *s = new S();
+ clang_analyzer_eval(s == S::buffer); // expected-warning{{FALSE}}
+} // expected-warning{{SYMBOL DEAD}}
diff --git a/test/Analysis/new-dynamic-types.cpp b/test/Analysis/new-dynamic-types.cpp
new file mode 100644
index 000000000000..e0a460e3928e
--- /dev/null
+++ b/test/Analysis/new-dynamic-types.cpp
@@ -0,0 +1,28 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -std=c++11 -verify %s
+
+// expected-no-diagnostics
+
+typedef __typeof(sizeof(int)) size_t;
+
+void *operator new(size_t size, void *ptr);
+
+struct B {
+ virtual void foo();
+};
+
+struct D : public B {
+ virtual void foo() override {}
+};
+
+void test_ub() {
+ // FIXME: Potentially warn because this code is pretty weird.
+ B b;
+ new (&b) D;
+ b.foo(); // no-crash
+}
+
+void test_non_ub() {
+ char c[sizeof(D)]; // Should be enough storage.
+ new (c) D;
+ ((B *)c)->foo(); // no-crash
+}
diff --git a/test/Analysis/new.cpp b/test/Analysis/new.cpp
index 6cfcb1d92719..31f763266c38 100644
--- a/test/Analysis/new.cpp
+++ b/test/Analysis/new.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-store region -std=c++11 -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-store region -std=c++11 -DTEST_INLINABLE_ALLOCATORS -verify %s
#include "Inputs/system-header-simulator-cxx.h"
void clang_analyzer_eval(bool);
@@ -34,7 +35,7 @@ void *testPlacementNew() {
void *y = new (x) int;
clang_analyzer_eval(x == y); // expected-warning{{TRUE}};
- clang_analyzer_eval(*x == 1); // expected-warning{{UNKNOWN}};
+ clang_analyzer_eval(*x == 1); // expected-warning{{TRUE}};
return y;
}
@@ -137,7 +138,7 @@ void testNewDeleteNoWarn() {
// unix.Malloc does not know about operators new/delete.
void testDeleteMallocked() {
int *x = (int *)malloc(sizeof(int));
- delete x; // FIXME: Shoud detect pointer escape and keep silent after 'delete' is modeled properly.
+ delete x; // FIXME: Should detect pointer escape and keep silent after 'delete' is modeled properly.
} // expected-warning{{Potential leak of memory pointed to by 'x'}}
void testDeleteOpAfterFree() {
@@ -200,8 +201,7 @@ int testNoInitializationPlacement() {
int n;
new (&n) int;
- // Should warn that n is uninitialized.
- if (n) { // no-warning
+ if (n) { // expected-warning{{Branch condition evaluates to a garbage value}}
return 0;
}
return 1;
@@ -274,6 +274,24 @@ void test_var_delete() {
clang_analyzer_eval(true); // expected-warning{{TRUE}}
}
+void test_array_delete() {
+ class C {
+ public:
+ ~C() {}
+ };
+
+ auto c1 = new C[2][3];
+ delete[] c1; // no-crash // no-warning
+
+ C c2[4];
+ // FIXME: Should warn.
+ delete[] &c2; // no-crash
+
+ C c3[7][6];
+ // FIXME: Should warn.
+ delete[] &c3; // no-crash
+}
+
void testDeleteNull() {
NoReturnDtor *foo = 0;
delete foo; // should not call destructor, checked below
@@ -311,7 +329,7 @@ void testArrayNull() {
void testArrayDestr() {
NoReturnDtor *p = new NoReturnDtor[2];
delete[] p; // Calls the base destructor which aborts, checked below
- //TODO: clang_analyzer_eval should not be called
+ //TODO: clang_analyzer_eval should not be called
clang_analyzer_eval(true); // expected-warning{{TRUE}}
}
diff --git a/test/Analysis/nonnullparamchecker-crash.cpp b/test/Analysis/nonnullparamchecker-crash.cpp
new file mode 100644
index 000000000000..76480f4d92f2
--- /dev/null
+++ b/test/Analysis/nonnullparamchecker-crash.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -std=c++11 -verify %s
+class C {};
+
+// expected-no-diagnostics
+void f(C i) {
+ auto lambda = [&] { f(i); };
+ typedef decltype(lambda) T;
+ T* blah = new T(lambda);
+ (*blah)();
+ delete blah;
+}
diff --git a/test/Analysis/novoidtypecrash.c b/test/Analysis/novoidtypecrash.c
new file mode 100644
index 000000000000..c04cfca29b4f
--- /dev/null
+++ b/test/Analysis/novoidtypecrash.c
@@ -0,0 +1,8 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core %s
+a;
+b(void **c) { // no-crash
+ *c = a;
+ int *d;
+ b(&d);
+ *d;
+}
diff --git a/test/Analysis/null-deref-path-notes.c b/test/Analysis/null-deref-path-notes.c
index a1477a6226a7..c73f64066b28 100644
--- a/test/Analysis/null-deref-path-notes.c
+++ b/test/Analysis/null-deref-path-notes.c
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -w -x c -analyzer-checker=core -analyzer-output=text -verify %s
+// RUN: %clang_analyze_cc1 -w -x c -analyzer-checker=core,unix -analyzer-output=text -verify %s
// Avoid the crash when finding the expression for tracking the origins
// of the null pointer for path notes.
@@ -7,3 +7,46 @@ void pr34373() {
(a + 0)[0]; // expected-warning{{Array access results in a null pointer dereference}}
// expected-note@-1{{Array access results in a null pointer dereference}}
}
+
+typedef __typeof(sizeof(int)) size_t;
+void *memcpy(void *dest, const void *src, unsigned long count);
+
+void f1(char *source) {
+ char *destination = 0; // expected-note{{'destination' initialized to a null pointer value}}
+ memcpy(destination + 0, source, 10); // expected-warning{{Null pointer argument in call to memory copy function}}
+ // expected-note@-1{{Null pointer argument in call to memory copy function}}
+}
+
+void f2(char *source) {
+ char *destination = 0; // expected-note{{'destination' initialized to a null pointer value}}
+ memcpy(destination - 0, source, 10); // expected-warning{{Null pointer argument in call to memory copy function}}
+ // expected-note@-1{{Null pointer argument in call to memory copy function}}
+}
+
+void f3(char *source) {
+ char *destination = 0; // expected-note{{'destination' initialized to a null pointer value}}
+ destination = destination + 0; // expected-note{{Null pointer value stored to 'destination'}}
+ memcpy(destination, source, 10); // expected-warning{{Null pointer argument in call to memory copy function}}
+ // expected-note@-1{{Null pointer argument in call to memory copy function}}
+}
+
+void f4(char *source) {
+ char *destination = 0; // expected-note{{'destination' initialized to a null pointer value}}
+ destination = destination - 0; // expected-note{{Null pointer value stored to 'destination'}}
+ memcpy(destination, source, 10); // expected-warning{{Null pointer argument in call to memory copy function}}
+ // expected-note@-1{{Null pointer argument in call to memory copy function}}
+}
+
+void f5(char *source) {
+ char *destination1 = 0; // expected-note{{'destination1' initialized to a null pointer value}}
+ char *destination2 = destination1 + 0; // expected-note{{'destination2' initialized to a null pointer value}}
+ memcpy(destination2, source, 10); // expected-warning{{Null pointer argument in call to memory copy function}}
+ // expected-note@-1{{Null pointer argument in call to memory copy function}}
+}
+
+void f6(char *source) {
+ char *destination1 = 0; // expected-note{{'destination1' initialized to a null pointer value}}
+ char *destination2 = destination1 - 0; // expected-note{{'destination2' initialized to a null pointer value}}
+ memcpy(destination2, source, 10); // expected-warning{{Null pointer argument in call to memory copy function}}
+ // expected-note@-1{{Null pointer argument in call to memory copy function}}
+}
diff --git a/test/Analysis/null-deref-path-notes.m b/test/Analysis/null-deref-path-notes.m
index 39cf9c79f311..4a68d8f6fbae 100644
--- a/test/Analysis/null-deref-path-notes.m
+++ b/test/Analysis/null-deref-path-notes.m
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-store=region -analyzer-output=text -fblocks -verify -Wno-objc-root-class %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-store=region -analyzer-output=plist-multi-file -analyzer-config path-diagnostics-alternate=false -fblocks -Wno-objc-root-class %s -o %t
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-store=region -analyzer-output=plist-multi-file -fblocks -Wno-objc-root-class %s -o %t
// RUN: FileCheck --input-file=%t %s
@interface Root {
diff --git a/test/Analysis/null-deref-ps-region.c b/test/Analysis/null-deref-ps-region.c
index c46ca6c52ae3..f5e6956ff723 100644
--- a/test/Analysis/null-deref-ps-region.c
+++ b/test/Analysis/null-deref-ps-region.c
@@ -22,7 +22,7 @@ void f14(int *a) {
void foo() {
int *x = malloc(sizeof(int));
memset(x, 0, sizeof(int));
- int n = 1 / *x; // FIXME: no-warning
+ int n = 1 / *x; // expected-warning {{Division by zero}}
free(x);
}
diff --git a/test/Analysis/nullability-notes.m b/test/Analysis/nullability-notes.m
index c93aa02c4200..8b6e1b02b642 100644
--- a/test/Analysis/nullability-notes.m
+++ b/test/Analysis/nullability-notes.m
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 -fblocks -analyzer-checker=core,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull,nullability.NullablePassedToNonnull,nullability.NullableReturnedFromNonnull,nullability.NullableDereferenced -analyzer-output=text -verify %s
-// RUN: %clang_analyze_cc1 -fblocks -analyzer-checker=core,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull,nullability.NullablePassedToNonnull,nullability.NullableReturnedFromNonnull,nullability.NullableDereferenced -analyzer-output=plist -analyzer-config path-diagnostics-alternate=true -o %t.plist %s
+// RUN: %clang_analyze_cc1 -fblocks -analyzer-checker=core,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull,nullability.NullablePassedToNonnull,nullability.NullableReturnedFromNonnull,nullability.NullableDereferenced -analyzer-output=plist -o %t.plist %s
// RUN: FileCheck --input-file=%t.plist %s
#include "Inputs/system-header-simulator-for-nullability.h"
diff --git a/test/Analysis/nullability.mm b/test/Analysis/nullability.mm
index ddfede53b59d..2278efff3e99 100644
--- a/test/Analysis/nullability.mm
+++ b/test/Analysis/nullability.mm
@@ -418,7 +418,7 @@ Dummy *_Nonnull testDefensiveInlineChecks(Dummy * p) {
@end
@implementation SubClassWithInitializers
-// Note: Because this is overridding
+// Note: Because this is overriding
// -[ClassWithInitializers initWithNonnullReturnAndSelfCheckingIdiom],
// the return type of this method becomes implicitly id _Nonnull.
- (id)initWithNonnullReturnAndSelfCheckingIdiom {
diff --git a/test/Analysis/number-object-conversion.mm b/test/Analysis/number-object-conversion.mm
new file mode 100644
index 000000000000..32628b2e8f20
--- /dev/null
+++ b/test/Analysis/number-object-conversion.mm
@@ -0,0 +1,13 @@
+// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -fblocks -fobjc-arc -w -analyzer-checker=osx.NumberObjectConversion -analyzer-config osx.NumberObjectConversion:Pedantic=true %s -verify
+
+#include "Inputs/system-header-simulator-objc.h"
+
+NSNumber* generateNumber();
+
+// expected-no-diagnostics
+int test_initialization_in_ifstmt() { // Don't warn on initialization in guard.
+ if (NSNumber* number = generateNumber()) { // no-warning
+ return 0;
+ }
+ return 1;
+}
diff --git a/test/Analysis/objc-arc.m b/test/Analysis/objc-arc.m
index 4b446abc906f..687d63e24ee5 100644
--- a/test/Analysis/objc-arc.m
+++ b/test/Analysis/objc-arc.m
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.cocoa.RetainCount,deadcode -verify -fblocks -analyzer-opt-analyze-nested-blocks -fobjc-arc -analyzer-config path-diagnostics-alternate=true -analyzer-output=plist-multi-file -o %t.plist %s
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.cocoa.RetainCount,deadcode -verify -fblocks -analyzer-opt-analyze-nested-blocks -fobjc-arc -analyzer-output=plist-multi-file -o %t.plist %s
// RUN: FileCheck --input-file=%t.plist %s
typedef signed char BOOL;
diff --git a/test/Analysis/objc-for.m b/test/Analysis/objc-for.m
index f191e86cc4e4..b59a5c2cf177 100644
--- a/test/Analysis/objc-for.m
+++ b/test/Analysis/objc-for.m
@@ -32,6 +32,7 @@ typedef unsigned long NSUInteger;
@interface NSDictionary (SomeCategory)
- (void)categoryMethodOnNSDictionary;
+- (id) allKeys;
@end
@interface NSMutableDictionary : NSDictionary
@@ -343,3 +344,10 @@ void boxedArrayEscape(NSMutableArray *array) {
for (id key in array)
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
}
+
+int not_reachable_on_iteration_through_nil() {
+ NSDictionary* d = nil;
+ for (NSString* s in [d allKeys])
+ clang_analyzer_warnIfReached(); // no-warning
+ return 0;
+}
diff --git a/test/Analysis/objc-properties.m b/test/Analysis/objc-properties.m
index 88a19a13c514..7f2ef52a9141 100644
--- a/test/Analysis/objc-properties.m
+++ b/test/Analysis/objc-properties.m
@@ -17,7 +17,7 @@ typedef signed char BOOL;
id _nonSynth;
}
- @property (assign, nonatomic) MyClass* A; // explicitely synthesized, not implemented, non-default ivar name
+ @property (assign, nonatomic) MyClass* A; // explicitly synthesized, not implemented, non-default ivar name
@property (assign) MyClass* X; // automatically synthesized, not implemented
diff --git a/test/Analysis/objc-radar17039661.m b/test/Analysis/objc-radar17039661.m
index bfb8ef02306b..0d2ddbfc3060 100644
--- a/test/Analysis/objc-radar17039661.m
+++ b/test/Analysis/objc-radar17039661.m
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount -fblocks -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount -fblocks -analyzer-output=plist-multi-file -analyzer-config path-diagnostics-alternate=false %s -o %t
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount -fblocks -analyzer-output=plist-multi-file %s -o %t
// RUN: FileCheck --input-file=%t %s
@class NSString;
typedef long NSInteger;
@@ -86,6 +86,40 @@ void runTest() {
// CHECK: <array>
// CHECK: <dict>
// CHECK: <key>line</key><integer>49</integer>
+// CHECK: <key>col</key><integer>3</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>49</integer>
+// CHECK: <key>col</key><integer>6</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>kind</key><string>control</string>
+// CHECK: <key>edges</key>
+// CHECK: <array>
+// CHECK: <dict>
+// CHECK: <key>start</key>
+// CHECK: <array>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>49</integer>
+// CHECK: <key>col</key><integer>3</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>49</integer>
+// CHECK: <key>col</key><integer>6</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: <key>end</key>
+// CHECK: <array>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>49</integer>
// CHECK: <key>col</key><integer>26</integer>
// CHECK: <key>file</key><integer>0</integer>
// CHECK: </dict>
@@ -461,40 +495,6 @@ void runTest() {
// CHECK: </array>
// CHECK: </dict>
// CHECK: <dict>
-// CHECK: <key>kind</key><string>control</string>
-// CHECK: <key>edges</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>start</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>33</integer>
-// CHECK: <key>col</key><integer>7</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>33</integer>
-// CHECK: <key>col</key><integer>14</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: <key>end</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>33</integer>
-// CHECK: <key>col</key><integer>30</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>33</integer>
-// CHECK: <key>col</key><integer>30</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: <dict>
// CHECK: <key>kind</key><string>event</string>
// CHECK: <key>location</key>
// CHECK: <dict>
@@ -532,12 +532,46 @@ void runTest() {
// CHECK: <array>
// CHECK: <dict>
// CHECK: <key>line</key><integer>33</integer>
-// CHECK: <key>col</key><integer>30</integer>
+// CHECK: <key>col</key><integer>7</integer>
// CHECK: <key>file</key><integer>0</integer>
// CHECK: </dict>
// CHECK: <dict>
// CHECK: <key>line</key><integer>33</integer>
-// CHECK: <key>col</key><integer>30</integer>
+// CHECK: <key>col</key><integer>14</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: <key>end</key>
+// CHECK: <array>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>35</integer>
+// CHECK: <key>col</key><integer>7</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>35</integer>
+// CHECK: <key>col</key><integer>14</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>kind</key><string>control</string>
+// CHECK: <key>edges</key>
+// CHECK: <array>
+// CHECK: <dict>
+// CHECK: <key>start</key>
+// CHECK: <array>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>35</integer>
+// CHECK: <key>col</key><integer>7</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>35</integer>
+// CHECK: <key>col</key><integer>14</integer>
// CHECK: <key>file</key><integer>0</integer>
// CHECK: </dict>
// CHECK: </array>
@@ -635,40 +669,6 @@ void runTest() {
// CHECK: </array>
// CHECK: </dict>
// CHECK: <dict>
-// CHECK: <key>kind</key><string>control</string>
-// CHECK: <key>edges</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>start</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>50</integer>
-// CHECK: <key>col</key><integer>5</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>50</integer>
-// CHECK: <key>col</key><integer>17</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: <key>end</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>50</integer>
-// CHECK: <key>col</key><integer>21</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>50</integer>
-// CHECK: <key>col</key><integer>21</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: <dict>
// CHECK: <key>kind</key><string>event</string>
// CHECK: <key>location</key>
// CHECK: <dict>
@@ -710,6 +710,40 @@ void runTest() {
// CHECK: <string>Reference count incremented. The object now has a +1 retain count</string>
// CHECK: </dict>
// CHECK: <dict>
+// CHECK: <key>kind</key><string>control</string>
+// CHECK: <key>edges</key>
+// CHECK: <array>
+// CHECK: <dict>
+// CHECK: <key>start</key>
+// CHECK: <array>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>50</integer>
+// CHECK: <key>col</key><integer>5</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>50</integer>
+// CHECK: <key>col</key><integer>17</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: <key>end</key>
+// CHECK: <array>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>52</integer>
+// CHECK: <key>col</key><integer>5</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>52</integer>
+// CHECK: <key>col</key><integer>10</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: </dict>
+// CHECK: <dict>
// CHECK: <key>kind</key><string>event</string>
// CHECK: <key>location</key>
// CHECK: <dict>
@@ -759,6 +793,40 @@ void runTest() {
// CHECK: <key>end</key>
// CHECK: <array>
// CHECK: <dict>
+// CHECK: <key>line</key><integer>35</integer>
+// CHECK: <key>col</key><integer>7</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>35</integer>
+// CHECK: <key>col</key><integer>14</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>kind</key><string>control</string>
+// CHECK: <key>edges</key>
+// CHECK: <array>
+// CHECK: <dict>
+// CHECK: <key>start</key>
+// CHECK: <array>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>35</integer>
+// CHECK: <key>col</key><integer>7</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>35</integer>
+// CHECK: <key>col</key><integer>14</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: <key>end</key>
+// CHECK: <array>
+// CHECK: <dict>
// CHECK: <key>line</key><integer>37</integer>
// CHECK: <key>col</key><integer>7</integer>
// CHECK: <key>file</key><integer>0</integer>
@@ -1065,6 +1133,40 @@ void runTest() {
// CHECK: <array>
// CHECK: <dict>
// CHECK: <key>line</key><integer>35</integer>
+// CHECK: <key>col</key><integer>7</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>35</integer>
+// CHECK: <key>col</key><integer>14</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>kind</key><string>control</string>
+// CHECK: <key>edges</key>
+// CHECK: <array>
+// CHECK: <dict>
+// CHECK: <key>start</key>
+// CHECK: <array>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>35</integer>
+// CHECK: <key>col</key><integer>7</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>35</integer>
+// CHECK: <key>col</key><integer>14</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: <key>end</key>
+// CHECK: <array>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>35</integer>
// CHECK: <key>col</key><integer>33</integer>
// CHECK: <key>file</key><integer>0</integer>
// CHECK: </dict>
@@ -1229,5 +1331,3 @@ void runTest() {
// CHECK: </dict>
// CHECK: </dict>
// CHECK: </array>
-// CHECK:</dict>
-// CHECK:</plist>
diff --git a/test/Analysis/objc/direct-ivar-assignment-in-annotated-functions.m b/test/Analysis/objc/direct-ivar-assignment-in-annotated-functions.m
index 1603a57fea40..782fcecd43f9 100644
--- a/test/Analysis/objc/direct-ivar-assignment-in-annotated-functions.m
+++ b/test/Analysis/objc/direct-ivar-assignment-in-annotated-functions.m
@@ -26,7 +26,7 @@ typedef signed char BOOL;
MyClass* _NotA __attribute__((annotate("objc_allow_direct_instance_variable_assignment")));
}
- @property (assign, nonatomic) MyClass* A; // explicitely synthesized, not implemented, non-default ivar name
+ @property (assign, nonatomic) MyClass* A; // explicitly synthesized, not implemented, non-default ivar name
@property (assign) MyClass* X; // automatically synthesized, not implemented
diff --git a/test/Analysis/offsetofexpr-callback.c b/test/Analysis/offsetofexpr-callback.c
new file mode 100644
index 000000000000..0fcb90797d2b
--- /dev/null
+++ b/test/Analysis/offsetofexpr-callback.c
@@ -0,0 +1,13 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.AnalysisOrder -analyzer-config debug.AnalysisOrder:PreStmtOffsetOfExpr=true,debug.AnalysisOrder:PostStmtOffsetOfExpr=true %s 2>&1 | FileCheck %s
+#include "Inputs/system-header-simulator.h"
+
+struct S {
+ char c;
+};
+
+void test() {
+ offsetof(struct S, c);
+}
+
+// CHECK: PreStmt<OffsetOfExpr>
+// CHECK-NEXT: PostStmt<OffsetOfExpr> \ No newline at end of file
diff --git a/test/Analysis/plist-diagnostics-template-function.cpp b/test/Analysis/plist-diagnostics-template-function.cpp
new file mode 100644
index 000000000000..1f44a789cc92
--- /dev/null
+++ b/test/Analysis/plist-diagnostics-template-function.cpp
@@ -0,0 +1,41 @@
+// RUN: %clang_analyze_cc1 -analyzer-output=plist -o %t.plist -std=c++11 -analyzer-checker=core %s
+// RUN: FileCheck --input-file=%t.plist %s
+
+bool ret();
+
+template <class T>
+void f(int i) {
+ if (ret())
+ i = i / (i - 5);
+}
+
+template <>
+void f<int>(int i) {
+ if (ret())
+ i = i / (i - 5);
+}
+
+template <int N = 0>
+void defaultTemplateParameterFunction(int i) {
+ if (ret())
+ int a = 10 / i;
+}
+
+template <typename... Args>
+void variadicTemplateFunction(int i) {
+ if (ret())
+ int a = 10 / i;
+}
+
+int main() {
+ f<int>(5);
+ f<float>(5);
+ defaultTemplateParameterFunction<>(0);
+ variadicTemplateFunction<char, float, double, int *>(0);
+}
+
+// CHECK: <string>Calling &apos;f&lt;float&gt;&apos;</string>
+// CHECK: <string>Calling &apos;f&lt;int&gt;&apos;</string>
+// CHECK: <string>Calling &apos;defaultTemplateParameterFunction&lt;0&gt;&apos;</string>
+// CHECK: <string>Calling &apos;variadicTemplateFunction&lt;char, float, double, int *&gt;&apos;</string>
+
diff --git a/test/Analysis/plist-diagnostics-template-record.cpp b/test/Analysis/plist-diagnostics-template-record.cpp
new file mode 100644
index 000000000000..ffd6d0308836
--- /dev/null
+++ b/test/Analysis/plist-diagnostics-template-record.cpp
@@ -0,0 +1,42 @@
+// RUN: %clang_analyze_cc1 -analyzer-output=plist -o %t.plist -std=c++11 -analyzer-checker=core %s
+// RUN: FileCheck --input-file=%t.plist %s
+
+bool ret();
+
+template <class A, class B, class C, int N>
+struct DivByZero {
+ int i;
+ DivByZero(bool b) {
+ if (ret())
+ i = 50 / (b - 1);
+ }
+};
+
+template <class B, class C, int N>
+struct DivByZero<char, B, C, N> {
+ int i;
+ DivByZero(bool b) {
+ if (ret())
+ i = 50 / (b - 1);
+ }
+};
+
+template <typename... Args>
+struct DivByZeroVariadic {
+ int i;
+ DivByZeroVariadic(bool b) {
+ if (ret())
+ i = 50 / (b - 1);
+ }
+};
+
+int main() {
+ DivByZero<int, float, double, 0> a(1);
+ DivByZero<char, float, double, 0> a2(1);
+ DivByZeroVariadic<char, float, double, decltype(nullptr)> a3(1);
+}
+
+// CHECK: <string>Calling constructor for &apos;DivByZero&lt;int, float, double, 0&gt;&apos;</string>
+// CHECK: <string>Calling constructor for &apos;DivByZero&lt;char, float, double, 0&gt;&apos;</string>
+// CHECK: <string>Calling constructor for &apos;DivByZeroVariadic&lt;char, float, double, nullptr_t&gt;&apos;</string>
+
diff --git a/test/Analysis/plist-macros.cpp b/test/Analysis/plist-macros.cpp
index 18d3ce11e67e..4f7d3a254574 100644
--- a/test/Analysis/plist-macros.cpp
+++ b/test/Analysis/plist-macros.cpp
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix -analyzer-eagerly-assume -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix -analyzer-eagerly-assume -analyzer-output=plist-multi-file -analyzer-config path-diagnostics-alternate=ture %s -o %t.plist
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix -analyzer-eagerly-assume -analyzer-output=plist-multi-file %s -o %t.plist
// RUN: FileCheck --input-file=%t.plist %s
@@ -65,6 +65,7 @@ if (y) \
;
int useMultiNote(int *p, int y) {;
y++;
+ if (p) {}
multiNoteMacro
return *p; // expected-warning {{Dereference of null pointer}}
@@ -636,6 +637,69 @@ void test2(int *p) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>36</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>36</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>36</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>36</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>36</integer>
+// CHECK-NEXT: <key>col</key><integer>25</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Assuming the condition is true</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Assuming the condition is true</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>36</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>36</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>37</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
@@ -1216,7 +1280,41 @@ void test2(int *p) {
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>68</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>68</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>68</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>68</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -1228,7 +1326,7 @@ void test2(int *p) {
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <key>ranges</key>
@@ -1236,12 +1334,12 @@ void test2(int *p) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -1253,10 +1351,44 @@ void test2(int *p) {
// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>68</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>68</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>69</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>69</integer>
+// CHECK-NEXT: <key>col</key><integer>16</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
+// CHECK-NEXT: <key>line</key><integer>69</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1264,12 +1396,12 @@ void test2(int *p) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
+// CHECK-NEXT: <key>line</key><integer>69</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
+// CHECK-NEXT: <key>line</key><integer>69</integer>
// CHECK-NEXT: <key>col</key><integer>16</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1289,12 +1421,12 @@ void test2(int *p) {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
+// CHECK-NEXT: <key>line</key><integer>69</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
+// CHECK-NEXT: <key>line</key><integer>69</integer>
// CHECK-NEXT: <key>col</key><integer>16</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1302,12 +1434,12 @@ void test2(int *p) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
+// CHECK-NEXT: <key>line</key><integer>71</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
+// CHECK-NEXT: <key>line</key><integer>71</integer>
// CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1323,12 +1455,12 @@ void test2(int *p) {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
+// CHECK-NEXT: <key>line</key><integer>71</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
+// CHECK-NEXT: <key>line</key><integer>71</integer>
// CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1336,12 +1468,12 @@ void test2(int *p) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
+// CHECK-NEXT: <key>line</key><integer>71</integer>
// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
+// CHECK-NEXT: <key>line</key><integer>71</integer>
// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1353,7 +1485,7 @@ void test2(int *p) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
+// CHECK-NEXT: <key>line</key><integer>71</integer>
// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1361,12 +1493,12 @@ void test2(int *p) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
+// CHECK-NEXT: <key>line</key><integer>71</integer>
// CHECK-NEXT: <key>col</key><integer>11</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
+// CHECK-NEXT: <key>line</key><integer>71</integer>
// CHECK-NEXT: <key>col</key><integer>11</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1387,10 +1519,10 @@ void test2(int *p) {
// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>41f58f9549aa1867e461a7996a8d335c</string>
// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
// CHECK-NEXT: <key>issue_context</key><string>useMultiNote</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
+// CHECK-NEXT: <key>issue_hash_function_offset</key><string>5</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
+// CHECK-NEXT: <key>line</key><integer>71</integer>
// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1402,7 +1534,7 @@ void test2(int *p) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
+// CHECK-NEXT: <key>line</key><integer>83</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1410,12 +1542,12 @@ void test2(int *p) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
+// CHECK-NEXT: <key>line</key><integer>83</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
+// CHECK-NEXT: <key>line</key><integer>83</integer>
// CHECK-NEXT: <key>col</key><integer>12</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1431,7 +1563,7 @@ void test2(int *p) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
+// CHECK-NEXT: <key>line</key><integer>83</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1439,12 +1571,12 @@ void test2(int *p) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
+// CHECK-NEXT: <key>line</key><integer>83</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
+// CHECK-NEXT: <key>line</key><integer>83</integer>
// CHECK-NEXT: <key>col</key><integer>12</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1460,7 +1592,7 @@ void test2(int *p) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>75</integer>
+// CHECK-NEXT: <key>line</key><integer>76</integer>
// CHECK-NEXT: <key>col</key><integer>1</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1478,12 +1610,12 @@ void test2(int *p) {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>75</integer>
+// CHECK-NEXT: <key>line</key><integer>76</integer>
// CHECK-NEXT: <key>col</key><integer>1</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>75</integer>
+// CHECK-NEXT: <key>line</key><integer>76</integer>
// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1491,12 +1623,12 @@ void test2(int *p) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
+// CHECK-NEXT: <key>line</key><integer>77</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
+// CHECK-NEXT: <key>line</key><integer>77</integer>
// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1512,12 +1644,12 @@ void test2(int *p) {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
+// CHECK-NEXT: <key>line</key><integer>77</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
+// CHECK-NEXT: <key>line</key><integer>77</integer>
// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1525,12 +1657,12 @@ void test2(int *p) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
+// CHECK-NEXT: <key>line</key><integer>79</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
+// CHECK-NEXT: <key>line</key><integer>79</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1546,12 +1678,12 @@ void test2(int *p) {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
+// CHECK-NEXT: <key>line</key><integer>79</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
+// CHECK-NEXT: <key>line</key><integer>79</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1559,12 +1691,12 @@ void test2(int *p) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
+// CHECK-NEXT: <key>line</key><integer>79</integer>
// CHECK-NEXT: <key>col</key><integer>6</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
+// CHECK-NEXT: <key>line</key><integer>79</integer>
// CHECK-NEXT: <key>col</key><integer>6</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1576,7 +1708,7 @@ void test2(int *p) {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
+// CHECK-NEXT: <key>line</key><integer>79</integer>
// CHECK-NEXT: <key>col</key><integer>6</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1584,12 +1716,12 @@ void test2(int *p) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
+// CHECK-NEXT: <key>line</key><integer>79</integer>
// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
+// CHECK-NEXT: <key>line</key><integer>79</integer>
// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1613,7 +1745,7 @@ void test2(int *p) {
// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
+// CHECK-NEXT: <key>line</key><integer>79</integer>
// CHECK-NEXT: <key>col</key><integer>6</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
diff --git a/test/Analysis/plist-output-alternate.m b/test/Analysis/plist-output-alternate.m
index 03f3393af8a7..1a80a4d5c637 100644
--- a/test/Analysis/plist-output-alternate.m
+++ b/test/Analysis/plist-output-alternate.m
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,alpha.core -fblocks -analyzer-output=plist -analyzer-config path-diagnostics-alternate=false -o %t %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,alpha.core -fblocks -analyzer-output=plist -o %t %s
// RUN: FileCheck --input-file %t %s
void test_null_init(void) {
@@ -113,6 +113,40 @@ void rdar8331641(int x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>6</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>6</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>6</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>6</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>6</integer>
// CHECK-NEXT: <key>col</key><integer>6</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -259,6 +293,40 @@ void rdar8331641(int x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>12</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>12</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>12</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>12</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>12</integer>
// CHECK-NEXT: <key>col</key><integer>6</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -468,6 +536,40 @@ void rdar8331641(int x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>19</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>19</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>19</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>19</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>19</integer>
// CHECK-NEXT: <key>col</key><integer>6</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -857,6 +959,40 @@ void rdar8331641(int x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>31</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>31</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>31</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>31</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>31</integer>
// CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -927,40 +1063,6 @@ void rdar8331641(int x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
// CHECK-NEXT: <key>col</key><integer>24</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1037,6 +1139,40 @@ void rdar8331641(int x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>38</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>38</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>38</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>38</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>38</integer>
// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1133,40 +1269,6 @@ void rdar8331641(int x) {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>36</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -1204,12 +1306,12 @@ void rdar8331641(int x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>36</integer>
+// CHECK-NEXT: <key>col</key><integer>13</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -1314,12 +1416,12 @@ void rdar8331641(int x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -1335,12 +1437,12 @@ void rdar8331641(int x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
diff --git a/test/Analysis/plist-output.m b/test/Analysis/plist-output.m
index a80ab5c31c66..6b39e31e0e30 100644
--- a/test/Analysis/plist-output.m
+++ b/test/Analysis/plist-output.m
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 %s -analyzer-checker=osx.cocoa.RetainCount,deadcode.DeadStores,core -analyzer-output=plist -analyzer-config path-diagnostics-alternate=false -o %t.plist
+// RUN: %clang_analyze_cc1 %s -analyzer-checker=osx.cocoa.RetainCount,deadcode.DeadStores,core -analyzer-output=plist -o %t.plist
// RUN: FileCheck --input-file=%t.plist %s
void test_null_init(void) {
@@ -250,6 +250,40 @@ int testFoo(Foo *x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>6</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>6</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>6</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>6</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>6</integer>
// CHECK-NEXT: <key>col</key><integer>6</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -396,6 +430,40 @@ int testFoo(Foo *x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>12</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>12</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>12</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>12</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>12</integer>
// CHECK-NEXT: <key>col</key><integer>6</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -605,6 +673,40 @@ int testFoo(Foo *x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>19</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>19</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>19</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>19</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>19</integer>
// CHECK-NEXT: <key>col</key><integer>6</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -994,6 +1096,40 @@ int testFoo(Foo *x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>31</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>31</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>31</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>31</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>31</integer>
// CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1064,40 +1200,6 @@ int testFoo(Foo *x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
// CHECK-NEXT: <key>col</key><integer>24</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1174,6 +1276,40 @@ int testFoo(Foo *x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>38</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>38</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>38</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>38</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>38</integer>
// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1480,6 +1616,40 @@ int testFoo(Foo *x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>50</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>50</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>50</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>50</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>50</integer>
// CHECK-NEXT: <key>col</key><integer>6</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1961,6 +2131,40 @@ int testFoo(Foo *x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>77</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>77</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>77</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>77</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>77</integer>
// CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -2181,40 +2385,6 @@ int testFoo(Foo *x) {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -2252,12 +2422,12 @@ int testFoo(Foo *x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
+// CHECK-NEXT: <key>col</key><integer>6</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -2312,6 +2482,35 @@ int testFoo(Foo *x) {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>95</integer>
+// CHECK-NEXT: <key>col</key><integer>24</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>95</integer>
+// CHECK-NEXT: <key>col</key><integer>24</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>95</integer>
+// CHECK-NEXT: <key>col</key><integer>28</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Entering loop body</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Entering loop body</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
// CHECK-NEXT: <key>edges</key>
// CHECK-NEXT: <array>
@@ -2366,6 +2565,40 @@ int testFoo(Foo *x) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>96</integer>
+// CHECK-NEXT: <key>col</key><integer>8</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>96</integer>
+// CHECK-NEXT: <key>col</key><integer>8</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>96</integer>
+// CHECK-NEXT: <key>col</key><integer>8</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>96</integer>
+// CHECK-NEXT: <key>col</key><integer>8</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>100</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
@@ -2443,6 +2676,35 @@ int testFoo(Foo *x) {
// CHECK-NEXT: <string>Looping back to the head of the loop</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>95</integer>
+// CHECK-NEXT: <key>col</key><integer>24</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>95</integer>
+// CHECK-NEXT: <key>col</key><integer>24</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>95</integer>
+// CHECK-NEXT: <key>col</key><integer>28</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Entering loop body</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Entering loop body</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
// CHECK-NEXT: <key>edges</key>
// CHECK-NEXT: <array>
@@ -2561,6 +2823,40 @@ int testFoo(Foo *x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>98</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>98</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>98</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>98</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>98</integer>
// CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -2690,7 +2986,7 @@ int testFoo(Foo *x) {
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>108</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>col</key><integer>24</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <key>ranges</key>
@@ -2698,12 +2994,12 @@ int testFoo(Foo *x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>108</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>col</key><integer>24</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>108</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>col</key><integer>28</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -2899,7 +3195,7 @@ int testFoo(Foo *x) {
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>117</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>col</key><integer>11</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <key>ranges</key>
@@ -2907,12 +3203,12 @@ int testFoo(Foo *x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>117</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>col</key><integer>11</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>117</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>col</key><integer>15</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -3104,6 +3400,35 @@ int testFoo(Foo *x) {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>126</integer>
+// CHECK-NEXT: <key>col</key><integer>24</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>126</integer>
+// CHECK-NEXT: <key>col</key><integer>24</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>126</integer>
+// CHECK-NEXT: <key>col</key><integer>28</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Entering loop body</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Entering loop body</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
// CHECK-NEXT: <key>edges</key>
// CHECK-NEXT: <array>
@@ -3158,6 +3483,40 @@ int testFoo(Foo *x) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>127</integer>
+// CHECK-NEXT: <key>col</key><integer>9</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>127</integer>
+// CHECK-NEXT: <key>col</key><integer>9</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>127</integer>
+// CHECK-NEXT: <key>col</key><integer>9</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>127</integer>
+// CHECK-NEXT: <key>col</key><integer>9</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>129</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
@@ -3235,6 +3594,35 @@ int testFoo(Foo *x) {
// CHECK-NEXT: <string>Looping back to the head of the loop</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>126</integer>
+// CHECK-NEXT: <key>col</key><integer>24</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>126</integer>
+// CHECK-NEXT: <key>col</key><integer>24</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>126</integer>
+// CHECK-NEXT: <key>col</key><integer>28</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Entering loop body</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Entering loop body</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
// CHECK-NEXT: <key>edges</key>
// CHECK-NEXT: <array>
@@ -3454,6 +3842,35 @@ int testFoo(Foo *x) {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>135</integer>
+// CHECK-NEXT: <key>col</key><integer>19</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>135</integer>
+// CHECK-NEXT: <key>col</key><integer>19</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>135</integer>
+// CHECK-NEXT: <key>col</key><integer>23</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Entering loop body</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Entering loop body</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
// CHECK-NEXT: <key>edges</key>
// CHECK-NEXT: <array>
@@ -3585,6 +4002,35 @@ int testFoo(Foo *x) {
// CHECK-NEXT: <string>Looping back to the head of the loop</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>135</integer>
+// CHECK-NEXT: <key>col</key><integer>19</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>135</integer>
+// CHECK-NEXT: <key>col</key><integer>19</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>135</integer>
+// CHECK-NEXT: <key>col</key><integer>23</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Entering loop body</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Entering loop body</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
// CHECK-NEXT: <key>edges</key>
// CHECK-NEXT: <array>
@@ -3896,6 +4342,35 @@ int testFoo(Foo *x) {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>141</integer>
+// CHECK-NEXT: <key>col</key><integer>19</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>141</integer>
+// CHECK-NEXT: <key>col</key><integer>19</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>141</integer>
+// CHECK-NEXT: <key>col</key><integer>23</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Entering loop body</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Entering loop body</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
// CHECK-NEXT: <key>edges</key>
// CHECK-NEXT: <array>
@@ -3950,6 +4425,40 @@ int testFoo(Foo *x) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>143</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>143</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>143</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>143</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>144</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
@@ -4027,6 +4536,35 @@ int testFoo(Foo *x) {
// CHECK-NEXT: <string>Looping back to the head of the loop</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>141</integer>
+// CHECK-NEXT: <key>col</key><integer>19</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>141</integer>
+// CHECK-NEXT: <key>col</key><integer>19</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>141</integer>
+// CHECK-NEXT: <key>col</key><integer>23</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Entering loop body</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Entering loop body</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
// CHECK-NEXT: <key>edges</key>
// CHECK-NEXT: <array>
@@ -4372,6 +4910,35 @@ int testFoo(Foo *x) {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>151</integer>
+// CHECK-NEXT: <key>col</key><integer>10</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>151</integer>
+// CHECK-NEXT: <key>col</key><integer>10</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>151</integer>
+// CHECK-NEXT: <key>col</key><integer>14</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Entering loop body</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Entering loop body</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
// CHECK-NEXT: <key>edges</key>
// CHECK-NEXT: <array>
@@ -4426,6 +4993,40 @@ int testFoo(Foo *x) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>153</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>153</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>153</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>153</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>154</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
@@ -4503,6 +5104,35 @@ int testFoo(Foo *x) {
// CHECK-NEXT: <string>Looping back to the head of the loop</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>151</integer>
+// CHECK-NEXT: <key>col</key><integer>10</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>151</integer>
+// CHECK-NEXT: <key>col</key><integer>10</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>151</integer>
+// CHECK-NEXT: <key>col</key><integer>14</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Entering loop body</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Entering loop body</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
// CHECK-NEXT: <key>edges</key>
// CHECK-NEXT: <array>
@@ -4930,7 +5560,7 @@ int testFoo(Foo *x) {
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>160</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <key>ranges</key>
@@ -4938,21 +5568,21 @@ int testFoo(Foo *x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>160</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>160</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>col</key><integer>13</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
+// CHECK-NEXT: <string>Loop body skipped when collection is empty</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
+// CHECK-NEXT: <string>Loop body skipped when collection is empty</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
@@ -5122,6 +5752,40 @@ int testFoo(Foo *x) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>172</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>172</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>172</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>172</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>172</integer>
// CHECK-NEXT: <key>col</key><integer>6</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -5456,40 +6120,6 @@ int testFoo(Foo *x) {
// CHECK-NEXT: <string>&apos;returnsPointer&apos; not called because the receiver is nil</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>194</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>194</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>194</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>194</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
diff --git a/test/Analysis/plist-stats-output.c b/test/Analysis/plist-stats-output.c
new file mode 100644
index 000000000000..072fe5e2971a
--- /dev/null
+++ b/test/Analysis/plist-stats-output.c
@@ -0,0 +1,14 @@
+// RUN: %clang_analyze_cc1 %s -analyzer-checker=core -analyzer-output=plist -analyzer-config serialize-stats=true -o %t.plist
+// REQUIRES: asserts
+// RUN: FileCheck --input-file=%t.plist %s
+
+int foo() {}
+
+
+// CHECK: <key>diagnostics</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>statistics</key>
+// CHECK-NEXT: <string>{
+// CHECK: }
+// CHECK-NEXT: </string>
diff --git a/test/Analysis/pr22954.c b/test/Analysis/pr22954.c
index 64a00c5ec087..b4273c0a8943 100644
--- a/test/Analysis/pr22954.c
+++ b/test/Analysis/pr22954.c
@@ -624,9 +624,10 @@ int f29(int i, int j, int k, int l, int m) {
clang_analyzer_eval(m29[i].s3[1] == 1); // expected-warning{{UNKNOWN}}
clang_analyzer_eval(m29[i].s3[2] == 1); // expected-warning{{UNKNOWN}}
clang_analyzer_eval(m29[i].s3[3] == 1); // expected-warning{{UNKNOWN}}
- clang_analyzer_eval(m29[j].s3[k] == 1); // expected-warning{{TRUE}}\
- expected-warning{{Potential leak of memory pointed to by field 's4'}}
+ clang_analyzer_eval(m29[j].s3[k] == 1); // expected-warning{{TRUE}}
clang_analyzer_eval(l29->s1[m] == 2); // expected-warning{{UNKNOWN}}
+ // FIXME: Should warn that m29[i].s4 leaks. But not on the previous line,
+ // because l29 and m29 alias.
return 0;
}
diff --git a/test/Analysis/pr37802.cpp b/test/Analysis/pr37802.cpp
new file mode 100644
index 000000000000..9acfebaae860
--- /dev/null
+++ b/test/Analysis/pr37802.cpp
@@ -0,0 +1,107 @@
+// RUN: %clang_analyze_cc1 -w -analyzer-checker=core -verify %s
+
+// expected-no-diagnostics
+
+typedef __typeof(sizeof(int)) size_t;
+void *operator new(size_t, void *h) { return h; }
+
+// I've no idea what this code does, but it used to crash, so let's keep it.
+namespace pr37802_v1 {
+struct J {
+ int *p;
+};
+class X {
+ void *ar;
+
+public:
+ X(void *t) : ar(t) {}
+ template <typename T>
+ void f(const T &t) {
+ new (ar) T(t);
+ }
+};
+class Y {
+public:
+ template <typename T>
+ void f(T &&);
+ void f(J t) {
+ f(*t.p);
+ }
+};
+class Z {
+ int at() const {}
+
+public:
+ Z(const Z &other) {
+ other.au(X(this));
+ }
+ template <typename T>
+ void au(T t) const {
+ void *c = const_cast<Z *>(this);
+ if (at()) {
+ t.f(*static_cast<J *>(c));
+ } else {
+ t.f(*static_cast<bool *>(c));
+ }
+ }
+};
+Z g() {
+ Z az = g();
+ Z e = az;
+ Y d;
+ e.au(d);
+}
+} // namespace pr37802_v1
+
+
+// This slightly modified code crashed differently.
+namespace pr37802_v2 {
+struct J {
+ int *p;
+};
+
+class X {
+ void *ar;
+
+public:
+ X(void *t) : ar(t) {}
+ void f(const J &t) { new (ar) J(t); }
+ void f(const bool &t) { new (ar) bool(t); }
+};
+
+class Y {
+public:
+ void boolf(bool &&);
+ void f(J &&);
+ void f(J t) { boolf(*t.p); }
+};
+
+class Z {
+ int at() const {}
+
+public:
+ Z(const Z &other) { other.au(X(this)); }
+ void au(X t) const {
+ void *c = const_cast<Z *>(this);
+ if (at()) {
+ t.f(*static_cast<J *>(c));
+ } else {
+ t.f(*static_cast<bool *>(c));
+ }
+ }
+ void au(Y t) const {
+ void *c = const_cast<Z *>(this);
+ if (at()) {
+ t.f(*static_cast<J *>(c));
+ } else {
+ }
+ }
+};
+
+Z g() {
+ Z az = g();
+ Z e = az;
+ Y d;
+ e.au(d);
+}
+} // namespace pr37802_v2
diff --git a/test/Analysis/ptr-arith.c b/test/Analysis/ptr-arith.c
index 93cb4ee9a66a..c0b20508d8f5 100644
--- a/test/Analysis/ptr-arith.c
+++ b/test/Analysis/ptr-arith.c
@@ -265,49 +265,26 @@ void size_implies_comparison(int *lhs, int *rhs) {
clang_analyzer_eval((rhs - lhs) > 0); // expected-warning{{TRUE}}
}
-//-------------------------------
-// False positives
-//-------------------------------
-
void zero_implies_reversed_equal(int *lhs, int *rhs) {
clang_analyzer_eval((rhs - lhs) == 0); // expected-warning{{UNKNOWN}}
if ((rhs - lhs) == 0) {
-#ifdef ANALYZER_CM_Z3
clang_analyzer_eval(rhs != lhs); // expected-warning{{FALSE}}
clang_analyzer_eval(rhs == lhs); // expected-warning{{TRUE}}
-#else
- clang_analyzer_eval(rhs != lhs); // expected-warning{{UNKNOWN}}
- clang_analyzer_eval(rhs == lhs); // expected-warning{{UNKNOWN}}
-#endif
return;
}
clang_analyzer_eval((rhs - lhs) == 0); // expected-warning{{FALSE}}
-#ifdef ANALYZER_CM_Z3
clang_analyzer_eval(rhs == lhs); // expected-warning{{FALSE}}
clang_analyzer_eval(rhs != lhs); // expected-warning{{TRUE}}
-#else
- clang_analyzer_eval(rhs == lhs); // expected-warning{{UNKNOWN}}
- clang_analyzer_eval(rhs != lhs); // expected-warning{{UNKNOWN}}
-#endif
}
void canonical_equal(int *lhs, int *rhs) {
clang_analyzer_eval(lhs == rhs); // expected-warning{{UNKNOWN}}
if (lhs == rhs) {
-#ifdef ANALYZER_CM_Z3
clang_analyzer_eval(rhs == lhs); // expected-warning{{TRUE}}
-#else
- clang_analyzer_eval(rhs == lhs); // expected-warning{{UNKNOWN}}
-#endif
return;
}
clang_analyzer_eval(lhs == rhs); // expected-warning{{FALSE}}
-
-#ifdef ANALYZER_CM_Z3
clang_analyzer_eval(rhs == lhs); // expected-warning{{FALSE}}
-#else
- clang_analyzer_eval(rhs == lhs); // expected-warning{{UNKNOWN}}
-#endif
}
void compare_element_region_and_base(int *p) {
@@ -347,3 +324,9 @@ void test_no_crash_on_pointer_to_label() {
a[0] = 0;
label:;
}
+
+typedef __attribute__((__ext_vector_type__(2))) float simd_float2;
+float test_nowarning_on_vector_deref() {
+ simd_float2 x = {0, 1};
+ return x[1]; // no-warning
+}
diff --git a/test/Analysis/region-store.cpp b/test/Analysis/region-store.cpp
index cb49f4837d81..ab179ceb1acc 100644
--- a/test/Analysis/region-store.cpp
+++ b/test/Analysis/region-store.cpp
@@ -25,4 +25,4 @@ int radar13445834(Derived *Builder, Loc l) {
Builder->setLoc(l);
return Builder->accessBase();
-} \ No newline at end of file
+}
diff --git a/test/Analysis/region_store_overflow.c b/test/Analysis/region_store_overflow.c
new file mode 100644
index 000000000000..505965301bc2
--- /dev/null
+++ b/test/Analysis/region_store_overflow.c
@@ -0,0 +1,16 @@
+// RUN: %clang_analyze_cc1 -analyze -analyzer-checker=core -verify %s
+
+int **h;
+int overflow_in_memregion(long j) {
+ for (int l = 0;; ++l) {
+ if (j - l > 0)
+ return h[j - l][0]; // no-crash
+ }
+ return 0;
+}
+
+void rdar39593879(long long *d) {
+ long e, f;
+ e = f = d[1]; // no-crash
+ for (; d[e];) f-- > 0; // expected-warning{{relational comparison result unused}};
+}
diff --git a/test/Analysis/retain-release-path-notes-gc.m b/test/Analysis/retain-release-path-notes-gc.m
index 04f991263c00..307aef1a5e20 100644
--- a/test/Analysis/retain-release-path-notes-gc.m
+++ b/test/Analysis/retain-release-path-notes-gc.m
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -fobjc-gc-only -analyzer-output=text -verify %s
-// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -fobjc-gc-only -analyzer-output=plist-multi-file -analyzer-config path-diagnostics-alternate=false %s -o %t.plist
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -fobjc-gc-only -analyzer-output=plist-multi-file %s -o %t.plist
// RUN: FileCheck --input-file=%t.plist %s
/***
@@ -79,40 +79,6 @@ void retainReleaseIgnored () {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>43</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>43</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>43</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>43</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -150,12 +116,12 @@ void retainReleaseIgnored () {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>43</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>43</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
+// CHECK-NEXT: <key>col</key><integer>11</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -225,40 +191,6 @@ void retainReleaseIgnored () {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>48</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>48</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>48</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>48</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -296,12 +228,12 @@ void retainReleaseIgnored () {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>48</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>48</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
+// CHECK-NEXT: <key>col</key><integer>11</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -671,40 +603,6 @@ void retainReleaseIgnored () {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -742,12 +640,12 @@ void retainReleaseIgnored () {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -1042,40 +940,6 @@ void retainReleaseIgnored () {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>36</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -1113,12 +977,12 @@ void retainReleaseIgnored () {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>36</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -1229,40 +1093,6 @@ void retainReleaseIgnored () {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>36</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -1300,12 +1130,12 @@ void retainReleaseIgnored () {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>36</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
diff --git a/test/Analysis/retain-release-path-notes.m b/test/Analysis/retain-release-path-notes.m
index f44d40fa495b..719a4d488cc0 100644
--- a/test/Analysis/retain-release-path-notes.m
+++ b/test/Analysis/retain-release-path-notes.m
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -analyzer-output=text -verify %s
-// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -analyzer-output=plist-multi-file -analyzer-config path-diagnostics-alternate=false %s -o %t
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -analyzer-output=plist-multi-file %s -o %t
// RUN: FileCheck --input-file=%t %s
/***
@@ -222,7 +222,7 @@ static int Cond;
}
+(void)test {
- // initX is inlined since we explicitely mark it as interesting
+ // initX is inlined since we explicitly mark it as interesting
id x = [[MyObj alloc] initX]; // expected-warning {{Potential leak of an object}}
// expected-note@-1 {{Method returns an instance of MyObj with a +1 retain count}}
// expected-note@-2 {{Calling 'initX'}}
@@ -335,40 +335,6 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -406,12 +372,12 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -481,40 +447,6 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>52</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>52</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>52</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>52</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -552,12 +484,12 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>52</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>52</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
+// CHECK-NEXT: <key>col</key><integer>11</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -627,40 +559,6 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -698,12 +596,12 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -998,40 +896,6 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -1069,12 +933,12 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -1219,40 +1083,6 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>35</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -1290,12 +1120,12 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>35</integer>
+// CHECK-NEXT: <key>col</key><integer>11</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -1440,40 +1270,6 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -1511,12 +1307,12 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -1661,40 +1457,6 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -1732,12 +1494,12 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -1882,40 +1644,6 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>89</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>89</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>89</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>89</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -1953,12 +1681,12 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>89</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>89</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -2178,40 +1906,6 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -2249,12 +1943,12 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -2399,40 +2093,6 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>102</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>102</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>102</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>102</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -2470,12 +2130,12 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>102</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>102</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
+// CHECK-NEXT: <key>col</key><integer>11</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -2695,40 +2355,6 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>109</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>109</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>109</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>109</integer>
-// CHECK-NEXT: <key>col</key><integer>35</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -2766,12 +2392,12 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>109</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>109</integer>
-// CHECK-NEXT: <key>col</key><integer>35</integer>
+// CHECK-NEXT: <key>col</key><integer>11</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -2882,40 +2508,6 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>114</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>114</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>114</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>114</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -2953,12 +2545,12 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>114</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>114</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
+// CHECK-NEXT: <key>col</key><integer>11</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -3069,40 +2661,6 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>32</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -3140,12 +2698,12 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>32</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -3256,40 +2814,6 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>125</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>125</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>125</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>125</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -3327,12 +2851,12 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>125</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>125</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -3443,40 +2967,6 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>130</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>130</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>130</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>130</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -3514,12 +3004,12 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>130</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>130</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -3630,40 +3120,6 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -3701,12 +3157,12 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -3817,40 +3273,6 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -3888,12 +3310,12 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>140</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>140</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -4038,40 +3460,6 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -4109,12 +3497,12 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -4184,40 +3572,6 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>175</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>175</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>175</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>175</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -4255,12 +3609,12 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>175</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>175</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -4330,40 +3684,6 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>180</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>180</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>180</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>180</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -4401,12 +3721,12 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>180</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>180</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -4476,40 +3796,6 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>185</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>185</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>185</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>185</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -4547,12 +3833,12 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>185</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>185</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -4622,40 +3908,6 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>190</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>190</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>190</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>190</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -4693,12 +3945,12 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>190</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>190</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -4831,40 +4083,6 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <string>Method returns an instance of MyObj with a +1 retain count</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>226</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>226</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>226</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>226</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -5171,13 +4389,13 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>226</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
+// CHECK-NEXT: <key>line</key><integer>232</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>226</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
+// CHECK-NEXT: <key>line</key><integer>232</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -5192,13 +4410,13 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>226</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
+// CHECK-NEXT: <key>line</key><integer>232</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>226</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
+// CHECK-NEXT: <key>line</key><integer>232</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -5296,6 +4514,35 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>215</integer>
+// CHECK-NEXT: <key>col</key><integer>10</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>215</integer>
+// CHECK-NEXT: <key>col</key><integer>10</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>215</integer>
+// CHECK-NEXT: <key>col</key><integer>21</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>1</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Method returns an instance of MyObj with a +1 retain count</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Method returns an instance of MyObj with a +1 retain count</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
// CHECK-NEXT: <key>edges</key>
// CHECK-NEXT: <array>
@@ -5316,13 +4563,13 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
+// CHECK-NEXT: <key>line</key><integer>216</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
+// CHECK-NEXT: <key>line</key><integer>216</integer>
+// CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -5333,35 +4580,6 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an instance of MyObj with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an instance of MyObj with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>232</integer>
// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
@@ -5408,6 +4626,40 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>232</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>232</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>232</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>232</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>237</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
@@ -5505,40 +4757,6 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>247</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>247</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>247</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>247</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -5576,12 +4794,12 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>247</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>247</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
+// CHECK-NEXT: <key>col</key><integer>11</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -5801,40 +5019,6 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>254</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>254</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>254</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>254</integer>
-// CHECK-NEXT: <key>col</key><integer>35</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -5872,12 +5056,12 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>254</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>254</integer>
-// CHECK-NEXT: <key>col</key><integer>35</integer>
+// CHECK-NEXT: <key>col</key><integer>11</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -6022,40 +5206,6 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>260</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>260</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>260</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>260</integer>
-// CHECK-NEXT: <key>col</key><integer>35</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -6093,12 +5243,12 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>260</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>260</integer>
-// CHECK-NEXT: <key>col</key><integer>35</integer>
+// CHECK-NEXT: <key>col</key><integer>11</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
diff --git a/test/Analysis/retain-release-safe.c b/test/Analysis/retain-release-safe.c
index de743552428c..6cd150093679 100644
--- a/test/Analysis/retain-release-safe.c
+++ b/test/Analysis/retain-release-safe.c
@@ -1,4 +1,5 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.RetainCount -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.RetainCount -analyzer-inline-max-stack-depth=0 -verify %s
#pragma clang arc_cf_code_audited begin
typedef const void * CFTypeRef;
@@ -35,6 +36,19 @@ void SafeCFRelease(CFTypeRef CF_CONSUMED cf) {
CFRelease(cf); // no-warning (when inlined)
}
+// The same thing, just with a different naming style.
+CFTypeRef retainCFType(CFTypeRef cf) CF_RETURNS_RETAINED {
+ if (cf) {
+ return CFRetain(cf);
+ }
+ return cf;
+}
+
+void releaseCFType(CFTypeRef CF_CONSUMED cf) {
+ if (cf)
+ CFRelease(cf); // no-warning (when inlined)
+}
+
void escape(CFTypeRef cf);
void makeSureTestsWork() {
@@ -70,3 +84,10 @@ void falseReleaseNotOwned(CFTypeRef cf) {
SafeCFRelease(cf);
SafeCFRelease(cf); // no-warning after inlining this.
}
+
+void testTheOtherNamingConvention(CFTypeRef cf) {
+ retainCFType(cf);
+ retainCFType(cf);
+ releaseCFType(cf);
+ releaseCFType(cf); // no-warning
+}
diff --git a/test/Analysis/retaincountchecker-compoundregion.m b/test/Analysis/retaincountchecker-compoundregion.m
new file mode 100644
index 000000000000..d9967b7fabfc
--- /dev/null
+++ b/test/Analysis/retaincountchecker-compoundregion.m
@@ -0,0 +1,25 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx -fblocks -verify -Wno-objc-root-class %s
+typedef const void *CFTypeRef;
+enum { kCFNumberSInt8Type = 1, kCFNumberSInt16Type = 2,
+ kCFNumberSInt32Type = 3, kCFNumberSInt64Type = 4,
+ kCFNumberFloat32Type = 5, kCFNumberFloat64Type = 6,
+ kCFNumberCharType = 7, kCFNumberShortType = 8,
+ kCFNumberIntType = 9, kCFNumberLongType = 10,
+ kCFNumberLongLongType = 11, kCFNumberFloatType = 12,
+ kCFNumberDoubleType = 13, kCFNumberCFIndexType = 14,
+ kCFNumberNSIntegerType = 15, kCFNumberCGFloatType = 16,
+ kCFNumberMaxType = 16 };
+typedef const struct __CFAllocator * CFAllocatorRef;
+typedef signed long CFIndex;
+typedef CFIndex CFNumberType;
+typedef const struct __CFNumber * CFNumberRef;
+extern CFNumberRef CFNumberCreate(CFAllocatorRef allocator, CFNumberType theType, const void *valuePtr);
+
+void foo(CFAllocatorRef allocator) {
+ int width = 0;
+ int height = 0;
+ CFTypeRef* values = (CFTypeRef[]){
+ CFNumberCreate(allocator, kCFNumberSInt32Type, &width), //expected-warning-re{{Potential leak of an object{{$}}}}
+ CFNumberCreate(allocator, kCFNumberSInt32Type, &height), //expected-warning-re{{Potential leak of an object{{$}}}}
+ };
+}
diff --git a/test/Analysis/return-stmt-merge.cpp b/test/Analysis/return-stmt-merge.cpp
new file mode 100644
index 000000000000..a6bacc514575
--- /dev/null
+++ b/test/Analysis/return-stmt-merge.cpp
@@ -0,0 +1,37 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.AnalysisOrder,debug.ExprInspection -analyzer-config debug.AnalysisOrder:PreCall=true,debug.AnalysisOrder:PostCall=true,debug.AnalysisOrder:LiveSymbols=true %s 2>&1 | FileCheck %s
+
+// This test ensures that check::LiveSymbols is called as many times on the
+// path through the second "return" as it is through the first "return"
+// (three), and therefore the two paths were not merged prematurely before the
+// respective return statement is evaluated.
+// The paths would still be merged later, so we'd have only one post-call for
+// foo(), but it is incorrect to merge them in the middle of evaluating two
+// different statements.
+int coin();
+
+void foo() {
+ int x = coin();
+ if (x > 0)
+ return;
+ else
+ return;
+}
+
+void bar() {
+ foo();
+}
+
+// CHECK: LiveSymbols
+// CHECK-NEXT: LiveSymbols
+// CHECK-NEXT: PreCall (foo)
+// CHECK-NEXT: LiveSymbols
+// CHECK-NEXT: LiveSymbols
+// CHECK-NEXT: PreCall (coin)
+// CHECK-NEXT: PostCall (coin)
+// CHECK-NEXT: LiveSymbols
+// CHECK-NEXT: LiveSymbols
+// CHECK-NEXT: LiveSymbols
+// CHECK-NEXT: PostCall (foo)
+// CHECK-NEXT: LiveSymbols
+// CHECK-NEXT: LiveSymbols
+// CHECK-NEXT: LiveSymbols
diff --git a/test/Analysis/scopes-cfg-output.cpp b/test/Analysis/scopes-cfg-output.cpp
new file mode 100644
index 000000000000..0f2201abb096
--- /dev/null
+++ b/test/Analysis/scopes-cfg-output.cpp
@@ -0,0 +1,1171 @@
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -analyze -analyzer-checker=debug.DumpCFG -analyzer-config cfg-scopes=true %s > %t 2>&1
+// RUN: FileCheck --input-file=%t %s
+
+class A {
+public:
+// CHECK: [B1 (ENTRY)]
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+ A() {}
+
+// CHECK: [B1 (ENTRY)]
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+ ~A() {}
+
+// CHECK: [B2 (ENTRY)]
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B1]
+// CHECK-NEXT: 1: 1
+// CHECK-NEXT: 2: return [B1.1];
+// CHECK-NEXT: Preds (1): B2
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+ operator int() const { return 1; }
+};
+
+int getX();
+extern const bool UV;
+
+// CHECK: [B2 (ENTRY)]
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B1]
+// CHECK-NEXT: 1: CFGScopeBegin(a)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B1.3], class A [2])
+// CHECK-NEXT: 3: A a[2];
+// CHECK-NEXT: 4: (CXXConstructExpr, [B1.5], class A [0])
+// CHECK-NEXT: 5: A b[0];
+// CHECK-NEXT: 6: [B1.3].~A() (Implicit destructor)
+// CHECK-NEXT: 7: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (1): B2
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+void test_array() {
+ A a[2];
+ A b[0];
+}
+
+// CHECK: [B2 (ENTRY)]
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B1]
+// CHECK-NEXT: 1: CFGScopeBegin(a)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B1.3], class A)
+// CHECK-NEXT: 3: A a;
+// CHECK-NEXT: 4: CFGScopeBegin(c)
+// CHECK-NEXT: 5: (CXXConstructExpr, [B1.6], class A)
+// CHECK-NEXT: 6: A c;
+// CHECK-NEXT: 7: (CXXConstructExpr, [B1.8], class A)
+// CHECK-NEXT: 8: A d;
+// CHECK-NEXT: 9: [B1.8].~A() (Implicit destructor)
+// CHECK-NEXT: 10: [B1.6].~A() (Implicit destructor)
+// CHECK-NEXT: 11: CFGScopeEnd(c)
+// CHECK-NEXT: 12: (CXXConstructExpr, [B1.13], class A)
+// CHECK-NEXT: 13: A b;
+// CHECK-NEXT: 14: [B1.13].~A() (Implicit destructor)
+// CHECK-NEXT: 15: [B1.3].~A() (Implicit destructor)
+// CHECK-NEXT: 16: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (1): B2
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+void test_scope() {
+ A a;
+ { A c;
+ A d;
+ }
+ A b;
+}
+
+// CHECK: [B4 (ENTRY)]
+// CHECK-NEXT: Succs (1): B3
+// CHECK: [B1]
+// CHECK-NEXT: 1: (CXXConstructExpr, [B1.2], class A)
+// CHECK-NEXT: 2: A c;
+// CHECK-NEXT: 3: [B1.2].~A() (Implicit destructor)
+// CHECK-NEXT: 4: [B3.5].~A() (Implicit destructor)
+// CHECK-NEXT: 5: [B3.3].~A() (Implicit destructor)
+// CHECK-NEXT: 6: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (1): B3
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B2]
+// CHECK-NEXT: 1: return;
+// CHECK-NEXT: 2: [B3.5].~A() (Implicit destructor)
+// CHECK-NEXT: 3: [B3.3].~A() (Implicit destructor)
+// CHECK-NEXT: 4: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (1): B3
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B3]
+// CHECK-NEXT: 1: CFGScopeBegin(a)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B3.3], class A)
+// CHECK-NEXT: 3: A a;
+// CHECK-NEXT: 4: (CXXConstructExpr, [B3.5], class A)
+// CHECK-NEXT: 5: A b;
+// CHECK-NEXT: 6: UV
+// CHECK-NEXT: 7: [B3.6] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT: T: if [B3.7]
+// CHECK-NEXT: Preds (1): B4
+// CHECK-NEXT: Succs (2): B2 B1
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (2): B1 B2
+void test_return() {
+ A a;
+ A b;
+ if (UV) return;
+ A c;
+}
+
+// CHECK: [B5 (ENTRY)]
+// CHECK-NEXT: Succs (1): B4
+// CHECK: [B1]
+// CHECK-NEXT: 1: [B4.8].~A() (Implicit destructor)
+// CHECK-NEXT: 2: CFGScopeEnd(b)
+// CHECK-NEXT: 3: [B4.3].~A() (Implicit destructor)
+// CHECK-NEXT: 4: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (2): B2 B3
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B2]
+// CHECK-NEXT: 1: CFGScopeBegin(c)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B2.3], class A)
+// CHECK-NEXT: 3: A c;
+// CHECK-NEXT: 4: [B2.3].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(c)
+// CHECK-NEXT: Preds (1): B4
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B3]
+// CHECK-NEXT: 1: CFGScopeBegin(c)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B3.3], class A)
+// CHECK-NEXT: 3: A c;
+// CHECK-NEXT: 4: [B3.3].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(c)
+// CHECK-NEXT: Preds (1): B4
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B4]
+// CHECK-NEXT: 1: CFGScopeBegin(a)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B4.3], class A)
+// CHECK-NEXT: 3: A a;
+// CHECK-NEXT: 4: CFGScopeBegin(b)
+// CHECK-NEXT: 5: a
+// CHECK-NEXT: 6: [B4.5] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 7: [B4.6] (CXXConstructExpr, [B4.8], class A)
+// CHECK-NEXT: 8: A b = a;
+// CHECK-NEXT: 9: b
+// CHECK-NEXT: 10: [B4.9] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 11: [B4.10].operator int
+// CHECK-NEXT: 12: [B4.10]
+// CHECK-NEXT: 13: [B4.12] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK-NEXT: 14: [B4.13] (ImplicitCastExpr, IntegralToBoolean, _Bool)
+// CHECK-NEXT: T: if [B4.14]
+// CHECK-NEXT: Preds (1): B5
+// CHECK-NEXT: Succs (2): B3 B2
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+void test_if_implicit_scope() {
+ A a;
+ if (A b = a)
+ A c;
+ else A c;
+}
+
+// CHECK: [B9 (ENTRY)]
+// CHECK-NEXT: Succs (1): B8
+// CHECK: [B1]
+// CHECK-NEXT: 1: [B8.8].~A() (Implicit destructor)
+// CHECK-NEXT: 2: CFGScopeEnd(b)
+// CHECK-NEXT: 3: (CXXConstructExpr, [B1.4], class A)
+// CHECK-NEXT: 4: A e;
+// CHECK-NEXT: 5: [B1.4].~A() (Implicit destructor)
+// CHECK-NEXT: 6: [B8.3].~A() (Implicit destructor)
+// CHECK-NEXT: 7: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (2): B2 B5
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B2]
+// CHECK-NEXT: 1: (CXXConstructExpr, [B2.2], class A)
+// CHECK-NEXT: 2: A d;
+// CHECK-NEXT: 3: [B2.2].~A() (Implicit destructor)
+// CHECK-NEXT: 4: [B4.3].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(c)
+// CHECK-NEXT: Preds (1): B4
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B3]
+// CHECK-NEXT: 1: return;
+// CHECK-NEXT: 2: [B4.3].~A() (Implicit destructor)
+// CHECK-NEXT: 3: CFGScopeEnd(c)
+// CHECK-NEXT: 4: [B8.8].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(b)
+// CHECK-NEXT: 6: [B8.3].~A() (Implicit destructor)
+// CHECK-NEXT: 7: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (1): B4
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B4]
+// CHECK-NEXT: 1: CFGScopeBegin(c)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B4.3], class A)
+// CHECK-NEXT: 3: A c;
+// CHECK-NEXT: 4: UV
+// CHECK-NEXT: 5: [B4.4] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT: T: if [B4.5]
+// CHECK-NEXT: Preds (1): B8
+// CHECK-NEXT: Succs (2): B3 B2
+// CHECK: [B5]
+// CHECK-NEXT: 1: (CXXConstructExpr, [B5.2], class A)
+// CHECK-NEXT: 2: A d;
+// CHECK-NEXT: 3: [B5.2].~A() (Implicit destructor)
+// CHECK-NEXT: 4: [B7.3].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(c)
+// CHECK-NEXT: Preds (1): B7
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B6]
+// CHECK-NEXT: 1: return;
+// CHECK-NEXT: 2: [B7.3].~A() (Implicit destructor)
+// CHECK-NEXT: 3: CFGScopeEnd(c)
+// CHECK-NEXT: 4: [B8.8].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(b)
+// CHECK-NEXT: 6: [B8.3].~A() (Implicit destructor)
+// CHECK-NEXT: 7: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (1): B7
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B7]
+// CHECK-NEXT: 1: CFGScopeBegin(c)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B7.3], class A)
+// CHECK-NEXT: 3: A c;
+// CHECK-NEXT: 4: UV
+// CHECK-NEXT: 5: [B7.4] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT: T: if [B7.5]
+// CHECK-NEXT: Preds (1): B8
+// CHECK-NEXT: Succs (2): B6 B5
+// CHECK: [B8]
+// CHECK-NEXT: 1: CFGScopeBegin(a)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B8.3], class A)
+// CHECK-NEXT: 3: A a;
+// CHECK-NEXT: 4: CFGScopeBegin(b)
+// CHECK-NEXT: 5: a
+// CHECK-NEXT: 6: [B8.5] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 7: [B8.6] (CXXConstructExpr, [B8.8], class A)
+// CHECK-NEXT: 8: A b = a;
+// CHECK-NEXT: 9: b
+// CHECK-NEXT: 10: [B8.9] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 11: [B8.10].operator int
+// CHECK-NEXT: 12: [B8.10]
+// CHECK-NEXT: 13: [B8.12] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK-NEXT: 14: [B8.13] (ImplicitCastExpr, IntegralToBoolean, _Bool)
+// CHECK-NEXT: T: if [B8.14]
+// CHECK-NEXT: Preds (1): B9
+// CHECK-NEXT: Succs (2): B7 B4
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (3): B1 B3 B6
+void test_if_jumps() {
+ A a;
+ if (A b = a) {
+ A c;
+ if (UV) return;
+ A d;
+ } else {
+ A c;
+ if (UV) return;
+ A d;
+ }
+ A e;
+}
+
+// CHECK: [B6 (ENTRY)]
+// CHECK-NEXT: Succs (1): B5
+// CHECK: [B1]
+// CHECK-NEXT: 1: [B4.5].~A() (Implicit destructor)
+// CHECK-NEXT: 2: CFGScopeEnd(b)
+// CHECK-NEXT: 3: [B5.3].~A() (Implicit destructor)
+// CHECK-NEXT: 4: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (1): B4
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B2]
+// CHECK-NEXT: Preds (1): B3
+// CHECK-NEXT: Succs (1): B4
+// CHECK: [B3]
+// CHECK-NEXT: 1: CFGScopeBegin(c)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B3.3], class A)
+// CHECK-NEXT: 3: A c;
+// CHECK-NEXT: 4: [B3.3].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(c)
+// CHECK-NEXT: 6: [B4.5].~A() (Implicit destructor)
+// CHECK-NEXT: 7: CFGScopeEnd(b)
+// CHECK-NEXT: Preds (1): B4
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B4]
+// CHECK-NEXT: 1: CFGScopeBegin(b)
+// CHECK-NEXT: 2: a
+// CHECK-NEXT: 3: [B4.2] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 4: [B4.3] (CXXConstructExpr, [B4.5], class A)
+// CHECK-NEXT: 5: A b = a;
+// CHECK-NEXT: 6: b
+// CHECK-NEXT: 7: [B4.6] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 8: [B4.7].operator int
+// CHECK-NEXT: 9: [B4.7]
+// CHECK-NEXT: 10: [B4.9] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK-NEXT: 11: [B4.10] (ImplicitCastExpr, IntegralToBoolean, _Bool)
+// CHECK-NEXT: T: while [B4.11]
+// CHECK-NEXT: Preds (2): B2 B5
+// CHECK-NEXT: Succs (2): B3 B1
+// CHECK: [B5]
+// CHECK-NEXT: 1: CFGScopeBegin(a)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B5.3], class A)
+// CHECK-NEXT: 3: A a;
+// CHECK-NEXT: Preds (1): B6
+// CHECK-NEXT: Succs (1): B4
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+void test_while_implicit_scope() {
+ A a;
+ while (A b = a)
+ A c;
+}
+
+// CHECK: [B12 (ENTRY)]
+// CHECK-NEXT: Succs (1): B11
+// CHECK: [B1]
+// CHECK-NEXT: 1: [B10.5].~A() (Implicit destructor)
+// CHECK-NEXT: 2: CFGScopeEnd(b)
+// CHECK-NEXT: 3: (CXXConstructExpr, [B1.4], class A)
+// CHECK-NEXT: 4: A e;
+// CHECK-NEXT: 5: [B1.4].~A() (Implicit destructor)
+// CHECK-NEXT: 6: [B11.3].~A() (Implicit destructor)
+// CHECK-NEXT: 7: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (2): B8 B10
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B2]
+// CHECK-NEXT: Preds (2): B3 B6
+// CHECK-NEXT: Succs (1): B10
+// CHECK: [B3]
+// CHECK-NEXT: 1: (CXXConstructExpr, [B3.2], class A)
+// CHECK-NEXT: 2: A d;
+// CHECK-NEXT: 3: [B3.2].~A() (Implicit destructor)
+// CHECK-NEXT: 4: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(c)
+// CHECK-NEXT: 6: [B10.5].~A() (Implicit destructor)
+// CHECK-NEXT: 7: CFGScopeEnd(b)
+// CHECK-NEXT: Preds (1): B5
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B4]
+// CHECK-NEXT: 1: return;
+// CHECK-NEXT: 2: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT: 3: CFGScopeEnd(c)
+// CHECK-NEXT: 4: [B10.5].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(b)
+// CHECK-NEXT: 6: [B11.3].~A() (Implicit destructor)
+// CHECK-NEXT: 7: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (1): B5
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B5]
+// CHECK-NEXT: 1: UV
+// CHECK-NEXT: 2: [B5.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT: T: if [B5.2]
+// CHECK-NEXT: Preds (1): B7
+// CHECK-NEXT: Succs (2): B4 B3
+// CHECK: [B6]
+// CHECK-NEXT: 1: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT: 2: CFGScopeEnd(c)
+// CHECK-NEXT: 3: [B10.5].~A() (Implicit destructor)
+// CHECK-NEXT: 4: CFGScopeEnd(b)
+// CHECK-NEXT: T: continue;
+// CHECK-NEXT: Preds (1): B7
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B7]
+// CHECK-NEXT: 1: UV
+// CHECK-NEXT: 2: [B7.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT: T: if [B7.2]
+// CHECK-NEXT: Preds (1): B9
+// CHECK-NEXT: Succs (2): B6 B5
+// CHECK: [B8]
+// CHECK-NEXT: 1: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT: 2: CFGScopeEnd(c)
+// CHECK-NEXT: T: break;
+// CHECK-NEXT: Preds (1): B9
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B9]
+// CHECK-NEXT: 1: CFGScopeBegin(c)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B9.3], class A)
+// CHECK-NEXT: 3: A c;
+// CHECK-NEXT: 4: UV
+// CHECK-NEXT: 5: [B9.4] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT: T: if [B9.5]
+// CHECK-NEXT: Preds (1): B10
+// CHECK-NEXT: Succs (2): B8 B7
+// CHECK: [B10]
+// CHECK-NEXT: 1: CFGScopeBegin(b)
+// CHECK-NEXT: 2: a
+// CHECK-NEXT: 3: [B10.2] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 4: [B10.3] (CXXConstructExpr, [B10.5], class A)
+// CHECK-NEXT: 5: A b = a;
+// CHECK-NEXT: 6: b
+// CHECK-NEXT: 7: [B10.6] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 8: [B10.7].operator int
+// CHECK-NEXT: 9: [B10.7]
+// CHECK-NEXT: 10: [B10.9] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK-NEXT: 11: [B10.10] (ImplicitCastExpr, IntegralToBoolean, _Bool)
+// CHECK-NEXT: T: while [B10.11]
+// CHECK-NEXT: Preds (2): B2 B11
+// CHECK-NEXT: Succs (2): B9 B1
+// CHECK: [B11]
+// CHECK-NEXT: 1: CFGScopeBegin(a)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B11.3], class A)
+// CHECK-NEXT: 3: A a;
+// CHECK-NEXT: Preds (1): B12
+// CHECK-NEXT: Succs (1): B10
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (2): B1 B4
+void test_while_jumps() {
+ A a;
+ while (A b = a) {
+ A c;
+ if (UV) break;
+ if (UV) continue;
+ if (UV) return;
+ A d;
+ }
+ A e;
+}
+
+// CHECK: [B12 (ENTRY)]
+// CHECK-NEXT: Succs (1): B11
+// CHECK: [B1]
+// CHECK-NEXT: 1: (CXXConstructExpr, [B1.2], class A)
+// CHECK-NEXT: 2: A d;
+// CHECK-NEXT: 3: [B1.2].~A() (Implicit destructor)
+// CHECK-NEXT: 4: [B11.3].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (2): B8 B2
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B2]
+// CHECK-NEXT: 1: UV
+// CHECK-NEXT: 2: [B2.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT: T: do ... while [B2.2]
+// CHECK-NEXT: Preds (2): B3 B6
+// CHECK-NEXT: Succs (2): B10 B1
+// CHECK: [B3]
+// CHECK-NEXT: 1: (CXXConstructExpr, [B3.2], class A)
+// CHECK-NEXT: 2: A c;
+// CHECK-NEXT: 3: [B3.2].~A() (Implicit destructor)
+// CHECK-NEXT: 4: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(b)
+// CHECK-NEXT: Preds (1): B5
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B4]
+// CHECK-NEXT: 1: return;
+// CHECK-NEXT: 2: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT: 3: CFGScopeEnd(b)
+// CHECK-NEXT: 4: [B11.3].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (1): B5
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B5]
+// CHECK-NEXT: 1: UV
+// CHECK-NEXT: 2: [B5.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT: T: if [B5.2]
+// CHECK-NEXT: Preds (1): B7
+// CHECK-NEXT: Succs (2): B4 B3
+// CHECK: [B6]
+// CHECK-NEXT: 1: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT: 2: CFGScopeEnd(b)
+// CHECK-NEXT: T: continue;
+// CHECK-NEXT: Preds (1): B7
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B7]
+// CHECK-NEXT: 1: UV
+// CHECK-NEXT: 2: [B7.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT: T: if [B7.2]
+// CHECK-NEXT: Preds (1): B9
+// CHECK-NEXT: Succs (2): B6 B5
+// CHECK: [B8]
+// CHECK-NEXT: 1: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT: 2: CFGScopeEnd(b)
+// CHECK-NEXT: T: break;
+// CHECK-NEXT: Preds (1): B9
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B9]
+// CHECK-NEXT: 1: CFGScopeBegin(b)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B9.3], class A)
+// CHECK-NEXT: 3: A b;
+// CHECK-NEXT: 4: UV
+// CHECK-NEXT: 5: [B9.4] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT: T: if [B9.5]
+// CHECK-NEXT: Preds (2): B10 B11
+// CHECK-NEXT: Succs (2): B8 B7
+// CHECK: [B10]
+// CHECK-NEXT: Preds (1): B2
+// CHECK-NEXT: Succs (1): B9
+// CHECK: [B11]
+// CHECK-NEXT: 1: CFGScopeBegin(a)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B11.3], class A)
+// CHECK-NEXT: 3: A a;
+// CHECK-NEXT: Preds (1): B12
+// CHECK-NEXT: Succs (1): B9
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (2): B1 B4
+void test_do_jumps() {
+ A a;
+ do {
+ A b;
+ if (UV) break;
+ if (UV) continue;
+ if (UV) return;
+ A c;
+ } while (UV);
+ A d;
+}
+
+// CHECK: [B6 (ENTRY)]
+// CHECK-NEXT: Succs (1): B5
+// CHECK: [B1]
+// CHECK-NEXT: 1: [B4.5].~A() (Implicit destructor)
+// CHECK-NEXT: 2: CFGScopeEnd(b)
+// CHECK-NEXT: 3: [B5.3].~A() (Implicit destructor)
+// CHECK-NEXT: 4: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (1): B4
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B2]
+// CHECK-NEXT: Preds (1): B3
+// CHECK-NEXT: Succs (1): B4
+// CHECK: [B3]
+// CHECK-NEXT: 1: CFGScopeBegin(c)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B3.3], class A)
+// CHECK-NEXT: 3: A c;
+// CHECK-NEXT: 4: [B3.3].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(c)
+// CHECK-NEXT: 6: [B4.5].~A() (Implicit destructor)
+// CHECK-NEXT: 7: CFGScopeEnd(b)
+// CHECK-NEXT: Preds (1): B4
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B4]
+// CHECK-NEXT: 1: CFGScopeBegin(b)
+// CHECK-NEXT: 2: a
+// CHECK-NEXT: 3: [B4.2] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 4: [B4.3] (CXXConstructExpr, [B4.5], class A)
+// CHECK-NEXT: 5: A b = a;
+// CHECK-NEXT: 6: b
+// CHECK-NEXT: 7: [B4.6] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 8: [B4.7].operator int
+// CHECK-NEXT: 9: [B4.7]
+// CHECK-NEXT: 10: [B4.9] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK-NEXT: 11: [B4.10] (ImplicitCastExpr, IntegralToBoolean, _Bool)
+// CHECK-NEXT: T: for (...; [B4.11]; )
+// CHECK-NEXT: Preds (2): B2 B5
+// CHECK-NEXT: Succs (2): B3 B1
+// CHECK: [B5]
+// CHECK-NEXT: 1: CFGScopeBegin(a)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B5.3], class A)
+// CHECK-NEXT: 3: A a;
+// CHECK-NEXT: Preds (1): B6
+// CHECK-NEXT: Succs (1): B4
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+void test_for_implicit_scope() {
+ for (A a; A b = a; )
+ A c;
+}
+
+// CHECK: [B12 (ENTRY)]
+// CHECK-NEXT: Succs (1): B11
+// CHECK: [B1]
+// CHECK-NEXT: 1: [B10.5].~A() (Implicit destructor)
+// CHECK-NEXT: 2: CFGScopeEnd(c)
+// CHECK-NEXT: 3: [B11.6].~A() (Implicit destructor)
+// CHECK-NEXT: 4: CFGScopeEnd(b)
+// CHECK-NEXT: 5: (CXXConstructExpr, [B1.6], class A)
+// CHECK-NEXT: 6: A f;
+// CHECK-NEXT: 7: [B1.6].~A() (Implicit destructor)
+// CHECK-NEXT: 8: [B11.3].~A() (Implicit destructor)
+// CHECK-NEXT: 9: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (2): B8 B10
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B2]
+// CHECK-NEXT: Preds (2): B3 B6
+// CHECK-NEXT: Succs (1): B10
+// CHECK: [B3]
+// CHECK-NEXT: 1: (CXXConstructExpr, [B3.2], class A)
+// CHECK-NEXT: 2: A e;
+// CHECK-NEXT: 3: [B3.2].~A() (Implicit destructor)
+// CHECK-NEXT: 4: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(d)
+// CHECK-NEXT: 6: [B10.5].~A() (Implicit destructor)
+// CHECK-NEXT: 7: CFGScopeEnd(c)
+// CHECK-NEXT: Preds (1): B5
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B4]
+// CHECK-NEXT: 1: return;
+// CHECK-NEXT: 2: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT: 3: CFGScopeEnd(d)
+// CHECK-NEXT: 4: [B10.5].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(c)
+// CHECK-NEXT: 6: [B11.6].~A() (Implicit destructor)
+// CHECK-NEXT: 7: CFGScopeEnd(b)
+// CHECK-NEXT: 8: [B11.3].~A() (Implicit destructor)
+// CHECK-NEXT: 9: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (1): B5
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B5]
+// CHECK-NEXT: 1: UV
+// CHECK-NEXT: 2: [B5.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT: T: if [B5.2]
+// CHECK-NEXT: Preds (1): B7
+// CHECK-NEXT: Succs (2): B4 B3
+// CHECK: [B6]
+// CHECK-NEXT: 1: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT: 2: CFGScopeEnd(d)
+// CHECK-NEXT: T: continue;
+// CHECK-NEXT: Preds (1): B7
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B7]
+// CHECK-NEXT: 1: UV
+// CHECK-NEXT: 2: [B7.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT: T: if [B7.2]
+// CHECK-NEXT: Preds (1): B9
+// CHECK-NEXT: Succs (2): B6 B5
+// CHECK: [B8]
+// CHECK-NEXT: 1: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT: 2: CFGScopeEnd(d)
+// CHECK-NEXT: T: break;
+// CHECK-NEXT: Preds (1): B9
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B9]
+// CHECK-NEXT: 1: CFGScopeBegin(d)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B9.3], class A)
+// CHECK-NEXT: 3: A d;
+// CHECK-NEXT: 4: UV
+// CHECK-NEXT: 5: [B9.4] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT: T: if [B9.5]
+// CHECK-NEXT: Preds (1): B10
+// CHECK-NEXT: Succs (2): B8 B7
+// CHECK: [B10]
+// CHECK-NEXT: 1: CFGScopeBegin(c)
+// CHECK-NEXT: 2: b
+// CHECK-NEXT: 3: [B10.2] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 4: [B10.3] (CXXConstructExpr, [B10.5], class A)
+// CHECK-NEXT: 5: A c = b;
+// CHECK-NEXT: 6: c
+// CHECK-NEXT: 7: [B10.6] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 8: [B10.7].operator int
+// CHECK-NEXT: 9: [B10.7]
+// CHECK-NEXT: 10: [B10.9] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK-NEXT: 11: [B10.10] (ImplicitCastExpr, IntegralToBoolean, _Bool)
+// CHECK-NEXT: T: for (...; [B10.11]; )
+// CHECK-NEXT: Preds (2): B2 B11
+// CHECK-NEXT: Succs (2): B9 B1
+// CHECK: [B11]
+// CHECK-NEXT: 1: CFGScopeBegin(a)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B11.3], class A)
+// CHECK-NEXT: 3: A a;
+// CHECK-NEXT: 4: CFGScopeBegin(b)
+// CHECK-NEXT: 5: (CXXConstructExpr, [B11.6], class A)
+// CHECK-NEXT: 6: A b;
+// CHECK-NEXT: Preds (1): B12
+// CHECK-NEXT: Succs (1): B10
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (2): B1 B4
+void test_for_jumps() {
+ A a;
+ for (A b; A c = b; ) {
+ A d;
+ if (UV) break;
+ if (UV) continue;
+ if (UV) return;
+ A e;
+ }
+ A f;
+}
+
+// CHECK: [B8 (ENTRY)]
+// CHECK-NEXT: Succs (1): B7
+// CHECK: [B1]
+// CHECK-NEXT: l1:
+// CHECK-NEXT: 1: (CXXConstructExpr, [B1.2], class A)
+// CHECK-NEXT: 2: A c;
+// CHECK-NEXT: 3: [B1.2].~A() (Implicit destructor)
+// CHECK-NEXT: 4: [B6.5].~A() (Implicit destructor)
+// CHECK-NEXT: 5: [B6.3].~A() (Implicit destructor)
+// CHECK-NEXT: 6: [B7.3].~A() (Implicit destructor)
+// CHECK-NEXT: 7: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (2): B2 B3
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B2]
+// CHECK-NEXT: 1: (CXXConstructExpr, [B2.2], class A)
+// CHECK-NEXT: 2: A b;
+// CHECK-NEXT: 3: [B2.2].~A() (Implicit destructor)
+// CHECK-NEXT: 4: [B6.8].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (1): B4
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B3]
+// CHECK-NEXT: 1: [B6.8].~A() (Implicit destructor)
+// CHECK-NEXT: 2: CFGScopeEnd(a)
+// CHECK-NEXT: T: goto l1;
+// CHECK-NEXT: Preds (1): B4
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B4]
+// CHECK-NEXT: 1: UV
+// CHECK-NEXT: 2: [B4.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT: T: if [B4.2]
+// CHECK-NEXT: Preds (1): B6
+// CHECK-NEXT: Succs (2): B3 B2
+// CHECK: [B5]
+// CHECK-NEXT: 1: [B6.8].~A() (Implicit destructor)
+// CHECK-NEXT: 2: [B6.5].~A() (Implicit destructor)
+// CHECK-NEXT: 3: [B6.3].~A() (Implicit destructor)
+// CHECK-NEXT: 4: CFGScopeEnd(cb)
+// CHECK-NEXT: T: goto l0;
+// CHECK-NEXT: Preds (1): B6
+// CHECK-NEXT: Succs (1): B6
+// CHECK: [B6]
+// CHECK-NEXT: l0:
+// CHECK-NEXT: 1: CFGScopeBegin(cb)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B6.3], class A)
+// CHECK-NEXT: 3: A cb;
+// CHECK-NEXT: 4: (CXXConstructExpr, [B6.5], class A)
+// CHECK-NEXT: 5: A b;
+// CHECK-NEXT: 6: CFGScopeBegin(a)
+// CHECK-NEXT: 7: (CXXConstructExpr, [B6.8], class A)
+// CHECK-NEXT: 8: A a;
+// CHECK-NEXT: 9: UV
+// CHECK-NEXT: 10: [B6.9] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT: T: if [B6.10]
+// CHECK-NEXT: Preds (2): B7 B5
+// CHECK-NEXT: Succs (2): B5 B4
+// CHECK: [B7]
+// CHECK-NEXT: 1: CFGScopeBegin(a)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B7.3], class A)
+// CHECK-NEXT: 3: A a;
+// CHECK-NEXT: Preds (1): B8
+// CHECK-NEXT: Succs (1): B6
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+void test_goto() {
+ A a;
+l0:
+ A cb;
+ A b;
+ { A a;
+ if (UV) goto l0;
+ if (UV) goto l1;
+ A b;
+ }
+l1:
+ A c;
+}
+
+// CHECK: [B7 (ENTRY)]
+// CHECK-NEXT: Succs (1): B6
+// CHECK: [B1]
+// CHECK-NEXT: 1: CFGScopeEnd(i)
+// CHECK-NEXT: 2: CFGScopeBegin(unused2)
+// CHECK-NEXT: 3: int unused2;
+// CHECK-NEXT: 4: CFGScopeEnd(unused2)
+// CHECK-NEXT: Preds (2): B4 B5
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B2]
+// CHECK-NEXT: 1: i
+// CHECK-NEXT: 2: ++[B2.1]
+// CHECK-NEXT: Preds (1): B3
+// CHECK-NEXT: Succs (1): B5
+// CHECK: [B3]
+// CHECK-NEXT: 1: CFGScopeEnd(unused1)
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B4]
+// CHECK-NEXT: 1: CFGScopeBegin(unused1)
+// CHECK-NEXT: 2: int unused1;
+// CHECK-NEXT: 3: CFGScopeEnd(unused1)
+// CHECK-NEXT: T: break;
+// CHECK-NEXT: Preds (1): B5
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B5]
+// CHECK-NEXT: 1: i
+// CHECK-NEXT: 2: [B5.1] (ImplicitCastExpr, LValueToRValue, int)
+// CHECK-NEXT: 3: 3
+// CHECK-NEXT: 4: [B5.2] < [B5.3]
+// CHECK-NEXT: T: for (...; [B5.4]; ...)
+// CHECK-NEXT: Preds (2): B2 B6
+// CHECK-NEXT: Succs (2): B4 B1
+// CHECK: [B6]
+// CHECK-NEXT: 1: CFGScopeBegin(i)
+// CHECK-NEXT: 2: 0
+// CHECK-NEXT: 3: int i = 0;
+// CHECK-NEXT: Preds (1): B7
+// CHECK-NEXT: Succs (1): B5
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+void test_for_compound_and_break() {
+ for (int i = 0; i < 3; ++i) {
+ {
+ int unused1;
+ break;
+ }
+ }
+ {
+ int unused2;
+ }
+}
+
+// CHECK: [B6 (ENTRY)]
+// CHECK-NEXT: Succs (1): B5
+// CHECK: [B1]
+// CHECK-NEXT: 1: CFGScopeEnd(__end1)
+// CHECK-NEXT: 2: CFGScopeEnd(__begin1)
+// CHECK-NEXT: 3: CFGScopeEnd(__range1)
+// CHECK-NEXT: 4: [B5.3].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (1): B2
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B2]
+// CHECK-NEXT: 1: __begin1
+// CHECK-NEXT: 2: [B2.1] (ImplicitCastExpr, LValueToRValue, class A *)
+// CHECK-NEXT: 3: __end1
+// CHECK-NEXT: 4: [B2.3] (ImplicitCastExpr, LValueToRValue, class A *)
+// CHECK-NEXT: 5: [B2.2] != [B2.4]
+// CHECK-NEXT: T: for (auto &i : [B5.4]) {
+// CHECK: [B4.11];
+// CHECK-NEXT:}
+// CHECK-NEXT: Preds (2): B3 B5
+// CHECK-NEXT: Succs (2): B4 B1
+// CHECK: [B3]
+// CHECK-NEXT: 1: __begin1
+// CHECK-NEXT: 2: ++[B3.1]
+// CHECK-NEXT: Preds (1): B4
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B4]
+// CHECK-NEXT: 1: CFGScopeBegin(i)
+// CHECK-NEXT: 2: __begin1
+// CHECK-NEXT: 3: [B4.2] (ImplicitCastExpr, LValueToRValue, class A *)
+// CHECK-NEXT: 4: *[B4.3]
+// CHECK-NEXT: 5: auto &i = *__begin1;
+// CHECK-NEXT: 6: operator=
+// CHECK-NEXT: 7: [B4.6] (ImplicitCastExpr, FunctionToPointerDecay, class A &(*)(const class A &)
+// CHECK-NEXT: 8: i
+// CHECK-NEXT: 9: b
+// CHECK-NEXT: 10: [B4.9] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 11: [B4.8] = [B4.10] (OperatorCall)
+// CHECK-NEXT: 12: CFGScopeEnd(i)
+// CHECK-NEXT: Preds (1): B2
+// CHECK-NEXT: Succs (1): B3
+// CHECK: [B5]
+// CHECK-NEXT: 1: CFGScopeBegin(a)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B5.3], class A [10])
+// CHECK-NEXT: 3: A a[10];
+// CHECK-NEXT: 4: a
+// CHECK-NEXT: 5: auto &&__range1 = a;
+// CHECK-NEXT: 6: CFGScopeBegin(__end1)
+// CHECK-NEXT: 7: __range1
+// CHECK-NEXT: 8: [B5.7] (ImplicitCastExpr, ArrayToPointerDecay, class A *)
+// CHECK-NEXT: 9: 10
+// CHECK-NEXT: 10: [B5.8] + [B5.9]
+// CHECK-NEXT: 11: auto __end1 = __range1 + 10
+// CHECK-NEXT: 12: __range1
+// CHECK-NEXT: 13: [B5.12] (ImplicitCastExpr, ArrayToPointerDecay, class A *)
+// CHECK-NEXT: 14: auto __begin1 = __range1;
+// CHECK-NEXT: Preds (1): B6
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+void test_range_for(A &b) {
+ A a[10];
+ for (auto &i : a)
+ i = b;
+}
+
+// CHECK: [B8 (ENTRY)]
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B1]
+// CHECK-NEXT: 1: CFGScopeEnd(i)
+// CHECK-NEXT: 2: 1
+// CHECK-NEXT: 3: int k = 1;
+// CHECK-NEXT: 4: CFGScopeEnd(c)
+// CHECK-NEXT: Preds (3): B3 B5 B6
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B2]
+// CHECK-NEXT: 1: CFGScopeBegin(c)
+// CHECK-NEXT: 2: '1'
+// CHECK-NEXT: 3: char c = '1';
+// CHECK-NEXT: 4: CFGScopeBegin(i)
+// CHECK-NEXT: 5: getX
+// CHECK-NEXT: 6: [B2.5] (ImplicitCastExpr, FunctionToPointerDecay, int (*)(void))
+// CHECK-NEXT: 7: [B2.6]()
+// CHECK-NEXT: 8: int i = getX();
+// CHECK-NEXT: 9: i
+// CHECK-NEXT: 10: [B2.9] (ImplicitCastExpr, LValueToRValue, int)
+// CHECK-NEXT: T: switch [B2.10]
+// CHECK-NEXT: Preds (1): B8
+// CHECK-NEXT: Succs (5): B4 B5 B6 B7 B3
+// CHECK: [B3]
+// CHECK-NEXT: default:
+// CHECK-NEXT: 1: CFGScopeBegin(a)
+// CHECK-NEXT: 2: 0
+// CHECK-NEXT: 3: int a = 0;
+// CHECK-NEXT: 4: i
+// CHECK-NEXT: 5: ++[B3.4]
+// CHECK-NEXT: 6: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (2): B4 B2
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B4]
+// CHECK-NEXT: case 3:
+// CHECK-NEXT: 1: '2'
+// CHECK-NEXT: 2: c
+// CHECK-NEXT: 3: [B4.2] = [B4.1]
+// CHECK-NEXT: Preds (1): B2
+// CHECK-NEXT: Succs (1): B3
+// CHECK: [B5]
+// CHECK-NEXT: case 2:
+// CHECK-NEXT: 1: '2'
+// CHECK-NEXT: 2: c
+// CHECK-NEXT: 3: [B5.2] = [B5.1]
+// CHECK-NEXT: T: break;
+// CHECK-NEXT: Preds (1): B2
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B6]
+// CHECK-NEXT: case 1:
+// CHECK-NEXT: 1: '3'
+// CHECK-NEXT: 2: c
+// CHECK-NEXT: 3: [B6.2] = [B6.1]
+// CHECK-NEXT: T: break;
+// CHECK-NEXT: Preds (2): B2 B7
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B7]
+// CHECK-NEXT: case 0:
+// CHECK-NEXT: 1: '2'
+// CHECK-NEXT: 2: c
+// CHECK-NEXT: 3: [B7.2] = [B7.1]
+// CHECK-NEXT: Preds (1): B2
+// CHECK-NEXT: Succs (1): B6
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+void test_switch_with_compound_with_default() {
+ char c = '1';
+ switch (int i = getX()) {
+ case 0:
+ c = '2';
+ case 1:
+ c = '3';
+ break;
+ case 2: {
+ c = '2';
+ break;
+ }
+ case 3:
+ c = '2';
+ default: {
+ int a = 0;
+ ++i;
+ }
+ }
+ int k = 1;
+}
+
+// CHECK: [B6 (ENTRY)]
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B1]
+// CHECK-NEXT: 1: CFGScopeEnd(i)
+// CHECK-NEXT: 2: 3
+// CHECK-NEXT: 3: int k = 3;
+// CHECK-NEXT: 4: CFGScopeEnd(c)
+// CHECK-NEXT: Preds (3): B3 B4 B2
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B2]
+// CHECK-NEXT: 1: CFGScopeBegin(c)
+// CHECK-NEXT: 2: '1'
+// CHECK-NEXT: 3: char c = '1';
+// CHECK-NEXT: 4: CFGScopeBegin(i)
+// CHECK-NEXT: 5: getX
+// CHECK-NEXT: 6: [B2.5] (ImplicitCastExpr, FunctionToPointerDecay, int (*)(void))
+// CHECK-NEXT: 7: [B2.6]()
+// CHECK-NEXT: 8: int i = getX();
+// CHECK-NEXT: 9: i
+// CHECK-NEXT: 10: [B2.9] (ImplicitCastExpr, LValueToRValue, int)
+// CHECK-NEXT: T: switch [B2.10]
+// CHECK-NEXT: Preds (1): B6
+// CHECK-NEXT: Succs (4): B3 B4 B5 B1
+// CHECK: [B3]
+// CHECK-NEXT: case 2:
+// CHECK-NEXT: 1: '3'
+// CHECK-NEXT: 2: c
+// CHECK-NEXT: 3: [B3.2] = [B3.1]
+// CHECK-NEXT: T: break;
+// CHECK-NEXT: Preds (1): B2
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B4]
+// CHECK-NEXT: case 1:
+// CHECK-NEXT: 1: '1'
+// CHECK-NEXT: 2: c
+// CHECK-NEXT: 3: [B4.2] = [B4.1]
+// CHECK-NEXT: T: break;
+// CHECK-NEXT: Preds (2): B2 B5
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B5]
+// CHECK-NEXT: case 0:
+// CHECK-NEXT: 1: '2'
+// CHECK-NEXT: 2: c
+// CHECK-NEXT: 3: [B5.2] = [B5.1]
+// CHECK-NEXT: Preds (1): B2
+// CHECK-NEXT: Succs (1): B4
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+int test_switch_with_compound_without_default() {
+ char c = '1';
+ switch (int i = getX()) {
+ case 0:
+ c = '2';
+ case 1:
+ c = '1';
+ break;
+ case 2:
+ c = '3';
+ break;
+ }
+ int k = 3;
+}
+
+// CHECK: [B5 (ENTRY)]
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B1]
+// CHECK-NEXT: 1: CFGScopeEnd(i)
+// CHECK-NEXT: 2: 1
+// CHECK-NEXT: 3: int k = 1;
+// CHECK-NEXT: 4: CFGScopeEnd(s)
+// CHECK-NEXT: Preds (1): B3
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B2]
+// CHECK-NEXT: 1: CFGScopeBegin(s)
+// CHECK-NEXT: 2: '1'
+// CHECK-NEXT: 3: char s = '1';
+// CHECK-NEXT: 4: CFGScopeBegin(i)
+// CHECK-NEXT: 5: getX
+// CHECK-NEXT: 6: [B2.5] (ImplicitCastExpr, FunctionToPointerDecay, int (*)(void))
+// CHECK-NEXT: 7: [B2.6]()
+// CHECK-NEXT: 8: int i = getX();
+// CHECK-NEXT: 9: i
+// CHECK-NEXT: 10: [B2.9] (ImplicitCastExpr, LValueToRValue, int)
+// CHECK-NEXT: T: switch [B2.10]
+// CHECK-NEXT: Preds (1): B5
+// CHECK-NEXT: Succs (2): B4 B3
+// CHECK: [B3]
+// CHECK-NEXT: default:
+// CHECK-NEXT: 1: CFGScopeBegin(a)
+// CHECK-NEXT: 2: 0
+// CHECK-NEXT: 3: int a = 0;
+// CHECK-NEXT: 4: i
+// CHECK-NEXT: 5: ++[B3.4]
+// CHECK-NEXT: 6: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (2): B4 B2
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B4]
+// CHECK-NEXT: case 0:
+// CHECK-NEXT: Preds (1): B2
+// CHECK-NEXT: Succs (1): B3
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+void test_without_compound() {
+ char s = '1';
+ switch (int i = getX())
+ case 0:
+ default: {
+ int a = 0;
+ ++i;
+ }
+ int k = 1;
+}
+
+// CHECK: [B12 (ENTRY)]
+// CHECK-NEXT: Succs (1): B11
+// CHECK: [B1]
+// CHECK-NEXT: 1: CFGScopeEnd(i)
+// CHECK-NEXT: Preds (2): B4 B10
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B2]
+// CHECK-NEXT: 1: i
+// CHECK-NEXT: 2: ++[B2.1]
+// CHECK-NEXT: Preds (2): B3 B7
+// CHECK-NEXT: Succs (1): B10
+// CHECK: [B3]
+// CHECK-NEXT: 1: CFGScopeEnd(z)
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B4]
+// CHECK-NEXT: 1: CFGScopeBegin(z)
+// CHECK-NEXT: 2: 5
+// CHECK-NEXT: 3: int z = 5;
+// CHECK-NEXT: 4: CFGScopeEnd(z)
+// CHECK-NEXT: T: break;
+// CHECK-NEXT: Preds (2): B6 B8
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B5]
+// CHECK-NEXT: 1: x
+// CHECK-NEXT: 2: [B5.1] (ImplicitCastExpr, LValueToRValue, int)
+// CHECK-NEXT: T: switch [B5.2]
+// CHECK-NEXT: Preds (1): B10
+// CHECK-NEXT: Succs (4): B7 B8 B9 B6
+// CHECK: [B6]
+// CHECK-NEXT: default:
+// CHECK-NEXT: 1: 3
+// CHECK-NEXT: 2: y
+// CHECK-NEXT: 3: [B6.2] = [B6.1]
+// CHECK-NEXT: Preds (1): B5
+// CHECK-NEXT: Succs (1): B4
+// CHECK: [B7]
+// CHECK-NEXT: case 2:
+// CHECK-NEXT: 1: 4
+// CHECK-NEXT: 2: y
+// CHECK-NEXT: 3: [B7.2] = [B7.1]
+// CHECK-NEXT: T: continue;
+// CHECK-NEXT: Preds (1): B5
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B8]
+// CHECK-NEXT: case 1:
+// CHECK-NEXT: 1: 2
+// CHECK-NEXT: 2: y
+// CHECK-NEXT: 3: [B8.2] = [B8.1]
+// CHECK-NEXT: T: break;
+// CHECK-NEXT: Preds (2): B5 B9
+// CHECK-NEXT: Succs (1): B4
+// CHECK: [B9]
+// CHECK-NEXT: case 0:
+// CHECK-NEXT: 1: 1
+// CHECK-NEXT: 2: y
+// CHECK-NEXT: 3: [B9.2] = [B9.1]
+// CHECK-NEXT: Preds (1): B5
+// CHECK-NEXT: Succs (1): B8
+// CHECK: [B10]
+// CHECK-NEXT: 1: i
+// CHECK-NEXT: 2: [B10.1] (ImplicitCastExpr, LValueToRValue, int)
+// CHECK-NEXT: 3: 1000
+// CHECK-NEXT: 4: [B10.2] < [B10.3]
+// CHECK-NEXT: T: for (...; [B10.4]; ...)
+// CHECK-NEXT: Preds (2): B2 B11
+// CHECK-NEXT: Succs (2): B5 B1
+// CHECK: [B11]
+// CHECK-NEXT: 1: CFGScopeBegin(i)
+// CHECK-NEXT: 2: int i;
+// CHECK-NEXT: 3: int x;
+// CHECK-NEXT: 4: int y;
+// CHECK-NEXT: 5: 0
+// CHECK-NEXT: 6: i
+// CHECK-NEXT: 7: [B11.6] = [B11.5]
+// CHECK-NEXT: Preds (1): B12
+// CHECK-NEXT: Succs (1): B10
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+void test_for_switch_in_for() {
+ int i, x, y;
+ for (i = 0; i < 1000; ++i) {
+ switch (x) {
+ case 0:
+ y = 1;
+ case 1:
+ y = 2;
+ break; // break from switch
+ case 2:
+ y = 4;
+ continue; // continue in loop
+ default:
+ y = 3;
+ }
+ {
+ int z = 5;
+ break; // break from loop
+ }
+ }
+}
diff --git a/test/Analysis/security-syntax-checks.m b/test/Analysis/security-syntax-checks.m
index 04a4c7d86655..2c569727addd 100644
--- a/test/Analysis/security-syntax-checks.m
+++ b/test/Analysis/security-syntax-checks.m
@@ -37,6 +37,27 @@ void test_float_condition() {
for (FooType x = 100000001.0f; x <= 100000010.0f; x++ ) {} // expected-warning{{Variable 'x' with floating point type 'FooType'}}
}
+// Obsolete function bcmp
+int bcmp(void *, void *, size_t);
+
+int test_bcmp(void *a, void *b, size_t n) {
+ return bcmp(a, b, n); // expected-warning{{The bcmp() function is obsoleted by memcmp()}}
+}
+
+// Obsolete function bcopy
+void bcopy(void *, void *, size_t);
+
+void test_bcopy(void *a, void *b, size_t n) {
+ bcopy(a, b, n); // expected-warning{{The bcopy() function is obsoleted by memcpy() or memmove(}}
+}
+
+// Obsolete function bzero
+void bzero(void *, size_t);
+
+void test_bzero(void *a, size_t n) {
+ bzero(a, n); // expected-warning{{The bzero() function is obsoleted by memset()}}
+}
+
// <rdar://problem/6335715> rule request: gets() buffer overflow
// Part of recommendation: 300-BSI (buildsecurityin.us-cert.gov)
char* gets(char *buf);
@@ -146,6 +167,16 @@ void test_strcpy() {
strcpy(x, y); //expected-warning{{Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119}}
}
+void test_strcpy_2() {
+ char x[4];
+ strcpy(x, "abcd"); //expected-warning{{Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119}}
+}
+
+void test_strcpy_safe() {
+ char x[5];
+ strcpy(x, "abcd");
+}
+
//===----------------------------------------------------------------------===
// strcat()
//===----------------------------------------------------------------------===
diff --git a/test/Analysis/stack-addr-ps.c b/test/Analysis/stack-addr-ps.c
index 4026cee90b04..721051ffaf11 100644
--- a/test/Analysis/stack-addr-ps.c
+++ b/test/Analysis/stack-addr-ps.c
@@ -6,7 +6,7 @@ int* f1() {
}
int* f2(int y) {
- return &y; // expected-warning{{Address of stack memory associated with local variable 'y' returned}} expected-warning{{address of stack memory associated with local variable 'y' returned}}
+ return &y; // expected-warning{{Address of stack memory associated with local variable 'y' returned}} expected-warning{{address of stack memory associated with parameter 'y' returned}}
}
int* f3(int x, int *y) {
diff --git a/test/Analysis/stack-addr-ps.cpp b/test/Analysis/stack-addr-ps.cpp
index 79afd18e1889..e1f06835c784 100644
--- a/test/Analysis/stack-addr-ps.cpp
+++ b/test/Analysis/stack-addr-ps.cpp
@@ -91,8 +91,8 @@ struct TS {
// rdar://11345441
int* f5() {
- int& i = i; // expected-warning {{Assigned value is garbage or undefined}} expected-note {{binding reference variable 'i' here}} expected-warning{{reference 'i' is not yet bound to a value when used within its own initialization}}
- return &i; // expected-warning {{address of stack memory associated with local variable 'i' returned}}
+ int& i = i; // expected-warning {{Assigned value is garbage or undefined}} expected-warning{{reference 'i' is not yet bound to a value when used within its own initialization}}
+ return &i;
}
void *radar13226577() {
diff --git a/test/Analysis/stackaddrleak.c b/test/Analysis/stackaddrleak.c
index a037d12fe40c..8a1519e7874f 100644
--- a/test/Analysis/stackaddrleak.c
+++ b/test/Analysis/stackaddrleak.c
@@ -37,7 +37,7 @@ void test_multi_return() {
intptr_t returnAsNonLoc() {
int x;
- return (intptr_t)&x; // expected-warning{{Address of stack memory associated with local variable 'x' returned to caller}}
+ return (intptr_t)&x; // expected-warning{{Address of stack memory associated with local variable 'x' returned to caller}} expected-warning{{address of stack memory associated with local variable 'x' returned}}
}
bool returnAsBool() {
diff --git a/test/Analysis/std-c-library-functions.c b/test/Analysis/std-c-library-functions.c
index 042b035f8bdf..b8eb3e54bdf0 100644
--- a/test/Analysis/std-c-library-functions.c
+++ b/test/Analysis/std-c-library-functions.c
@@ -57,8 +57,7 @@ void test_fread_fwrite(FILE *fp, int *buf) {
size_t y = fread(buf, sizeof(int), 10, fp);
clang_analyzer_eval(y <= 10); // expected-warning{{TRUE}}
size_t z = fwrite(buf, sizeof(int), y, fp);
- // FIXME: should be TRUE once symbol-symbol constraint support is improved.
- clang_analyzer_eval(z <= y); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(z <= y); // expected-warning{{TRUE}}
}
ssize_t getline(char **, size_t *, FILE *);
diff --git a/test/Analysis/string.c b/test/Analysis/string.c
index 8ea2068c5613..7e8a7361cd4b 100644
--- a/test/Analysis/string.c
+++ b/test/Analysis/string.c
@@ -1,7 +1,8 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s
-// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s
-// RUN: %clang_analyze_cc1 -DVARIANT -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s
-// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -DVARIANT -analyzer-checker=alpha.security.taint,core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s
+// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s
+// RUN: %clang_analyze_cc1 -DVARIANT -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s
+// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -DVARIANT -analyzer-checker=alpha.security.taint,core,unix.cstring,unix.Malloc,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s
+// RUN: %clang_analyze_cc1 -DSUPPRESS_OUT_OF_BOUND -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring.BufferOverlap,alpha.unix.cstring.NotNullTerminated,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s
//===----------------------------------------------------------------------===
// Declarations
@@ -30,6 +31,8 @@ typedef typeof(sizeof(int)) size_t;
void clang_analyzer_eval(int);
int scanf(const char *restrict format, ...);
+void *malloc(size_t);
+void free(void *);
//===----------------------------------------------------------------------===
// strlen()
@@ -109,7 +112,7 @@ void strlen_global() {
if (a == 0) {
clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
// Make sure clang_analyzer_eval does not invalidate globals.
- clang_analyzer_eval(strlen(global_str) == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strlen(global_str) == 0); // expected-warning{{TRUE}}
}
// Call a function with unknown effects, which should invalidate globals.
@@ -308,11 +311,13 @@ void strcpy_effects(char *x, char *y) {
clang_analyzer_eval(globalInt == 42); // expected-warning{{TRUE}}
}
+#ifndef SUPPRESS_OUT_OF_BOUND
void strcpy_overflow(char *y) {
char x[4];
if (strlen(y) == 4)
strcpy(x, y); // expected-warning{{String copy function overflows destination buffer}}
}
+#endif
void strcpy_no_overflow(char *y) {
char x[4];
@@ -347,11 +352,13 @@ void stpcpy_effect(char *x, char *y) {
clang_analyzer_eval(a == x[0]); // expected-warning{{UNKNOWN}}
}
+#ifndef SUPPRESS_OUT_OF_BOUND
void stpcpy_overflow(char *y) {
char x[4];
if (strlen(y) == 4)
stpcpy(x, y); // expected-warning{{String copy function overflows destination buffer}}
}
+#endif
void stpcpy_no_overflow(char *y) {
char x[4];
@@ -402,6 +409,7 @@ void strcat_effects(char *y) {
clang_analyzer_eval((int)strlen(x) == (orig_len + strlen(y))); // expected-warning{{TRUE}}
}
+#ifndef SUPPRESS_OUT_OF_BOUND
void strcat_overflow_0(char *y) {
char x[4] = "12";
if (strlen(y) == 4)
@@ -419,6 +427,7 @@ void strcat_overflow_2(char *y) {
if (strlen(y) == 2)
strcat(x, y); // expected-warning{{String copy function overflows destination buffer}}
}
+#endif
void strcat_no_overflow(char *y) {
char x[5] = "12";
@@ -495,6 +504,15 @@ void strncpy_effects(char *x, char *y) {
clang_analyzer_eval(a == x[0]); // expected-warning{{UNKNOWN}}
}
+#ifndef SUPPRESS_OUT_OF_BOUND
+// Enabling the malloc checker enables some of the buffer-checking portions
+// of the C-string checker.
+void cstringchecker_bounds_nocrash() {
+ char *p = malloc(2);
+ strncpy(p, "AAA", sizeof("AAA")); // expected-warning {{Size argument is greater than the length of the destination buffer}}
+ free(p);
+}
+
void strncpy_overflow(char *y) {
char x[4];
if (strlen(y) == 4)
@@ -515,6 +533,7 @@ void strncpy_no_overflow2(char *y, int n) {
if (strlen(y) == 3)
strncpy(x, y, n); // expected-warning{{Size argument is greater than the length of the destination buffer}}
}
+#endif
void strncpy_truncate(char *y) {
char x[4];
@@ -591,6 +610,7 @@ void strncat_effects(char *y) {
clang_analyzer_eval(strlen(x) == (orig_len + strlen(y))); // expected-warning{{TRUE}}
}
+#ifndef SUPPRESS_OUT_OF_BOUND
void strncat_overflow_0(char *y) {
char x[4] = "12";
if (strlen(y) == 4)
@@ -614,6 +634,8 @@ void strncat_overflow_3(char *y) {
if (strlen(y) == 4)
strncat(x, y, 2); // expected-warning{{Size argument is greater than the free space in the destination buffer}}
}
+#endif
+
void strncat_no_overflow_1(char *y) {
char x[5] = "12";
if (strlen(y) == 2)
@@ -631,6 +653,7 @@ void strncat_symbolic_dst_length(char *dst) {
clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
}
+#ifndef SUPPRESS_OUT_OF_BOUND
void strncat_symbolic_src_length(char *src) {
char dst[8] = "1234";
strncat(dst, src, 3);
@@ -648,6 +671,7 @@ void strncat_unknown_src_length(char *src, int offset) {
char dst2[8] = "1234";
strncat(dst2, &src[offset], 4); // expected-warning{{Size argument is greater than the free space in the destination buffer}}
}
+#endif
// There is no strncat_unknown_dst_length because if we can't get a symbolic
// length for the "before" strlen, we won't be able to set one for "after".
@@ -1160,12 +1184,212 @@ void strsep_changes_input_string() {
}
//===----------------------------------------------------------------------===
+// memset()
+//===----------------------------------------------------------------------===
+
+void *memset(void *dest, int ch, size_t count);
+
+void *malloc(size_t size);
+void free(void *);
+
+void memset1_char_array_null() {
+ char str[] = "abcd";
+ clang_analyzer_eval(strlen(str) == 4); // expected-warning{{TRUE}}
+ memset(str, '\0', 2);
+ clang_analyzer_eval(strlen(str) == 0); // expected-warning{{TRUE}}
+}
+
+void memset2_char_array_null() {
+ char str[] = "abcd";
+ clang_analyzer_eval(strlen(str) == 4); // expected-warning{{TRUE}}
+ memset(str, '\0', strlen(str) + 1);
+ clang_analyzer_eval(strlen(str) == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(str[2] == 0); // expected-warning{{TRUE}}
+}
+
+void memset3_char_malloc_null() {
+ char *str = (char *)malloc(10 * sizeof(char));
+ memset(str + 1, '\0', 8);
+ clang_analyzer_eval(str[1] == 0); // expected-warning{{UNKNOWN}}
+ free(str);
+}
+
+void memset4_char_malloc_null() {
+ char *str = (char *)malloc(10 * sizeof(char));
+ //void *str = malloc(10 * sizeof(char));
+ memset(str, '\0', 10);
+ clang_analyzer_eval(str[1] == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strlen(str) == 0); // expected-warning{{TRUE}}
+ free(str);
+}
+
+#ifdef SUPPRESS_OUT_OF_BOUND
+void memset5_char_malloc_overflow_null() {
+ char *str = (char *)malloc(10 * sizeof(char));
+ memset(str, '\0', 12);
+ clang_analyzer_eval(str[1] == 0); // expected-warning{{UNKNOWN}}
+ free(str);
+}
+#endif
+
+void memset6_char_array_nonnull() {
+ char str[] = "abcd";
+ clang_analyzer_eval(strlen(str) == 4); // expected-warning{{TRUE}}
+ memset(str, '0', 2);
+ clang_analyzer_eval(str[0] == 'a'); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(strlen(str) == 4); // expected-warning{{UNKNOWN}}
+}
+
+#ifdef SUPPRESS_OUT_OF_BOUND
+void memset8_char_array_nonnull() {
+ char str[5] = "abcd";
+ clang_analyzer_eval(strlen(str) == 4); // expected-warning{{TRUE}}
+ memset(str, '0', 10);
+ clang_analyzer_eval(str[0] != '0'); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(strlen(str) >= 10); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strlen(str) < 10); // expected-warning{{FALSE}}
+}
+#endif
+
+struct POD_memset {
+ int num;
+ char c;
+};
+
+void memset10_struct() {
+ struct POD_memset pod;
+ char *str = (char *)&pod;
+ pod.num = 1;
+ pod.c = 1;
+ clang_analyzer_eval(pod.num == 0); // expected-warning{{FALSE}}
+ memset(str, 0, sizeof(struct POD_memset));
+ clang_analyzer_eval(pod.num == 0); // expected-warning{{TRUE}}
+}
+
+#ifdef SUPPRESS_OUT_OF_BOUND
+void memset11_struct_field() {
+ struct POD_memset pod;
+ pod.num = 1;
+ pod.c = '1';
+ memset(&pod.num, 0, sizeof(struct POD_memset));
+
+ clang_analyzer_eval(pod.num == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(pod.c == '\0'); // expected-warning{{TRUE}}
+}
+
+void memset12_struct_field() {
+ struct POD_memset pod;
+ pod.num = 1;
+ pod.c = '1';
+ memset(&pod.c, 0, sizeof(struct POD_memset));
+ clang_analyzer_eval(pod.num == 0); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(pod.c == 0); // expected-warning{{UNKNOWN}}
+}
+
+union U_memset {
+ int i;
+ double d;
+ char c;
+};
+
+void memset13_union_field() {
+ union U_memset u;
+ u.i = 5;
+ memset(&u.i, '\0', sizeof(union U_memset));
+ // Note: This should be TRUE, analyzer can't handle union perfectly now.
+ clang_analyzer_eval(u.d == 0); // expected-warning{{UNKNOWN}}
+}
+#endif
+
+void memset14_region_cast() {
+ char *str = (char *)malloc(10 * sizeof(int));
+ int *array = (int *)str;
+ memset(array, 0, 10 * sizeof(int));
+ clang_analyzer_eval(str[10] == '\0'); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strlen((char *)array) == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strlen(str) == 0); // expected-warning{{TRUE}}
+ free(str);
+}
+
+void memset15_region_cast() {
+ char *str = (char *)malloc(10 * sizeof(int));
+ int *array = (int *)str;
+ memset(array, 0, 5 * sizeof(int));
+ clang_analyzer_eval(str[10] == '\0'); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(strlen((char *)array) == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strlen(str) == 0); // expected-warning{{TRUE}}
+ free(str);
+}
+
+int memset20_scalar() {
+ int *x = malloc(sizeof(int));
+ *x = 10;
+ memset(x, 0, sizeof(int));
+ int num = 1 / *x; // expected-warning{{Division by zero}}
+ free(x);
+ return num;
+}
+
+int memset21_scalar() {
+ int *x = malloc(sizeof(int));
+ memset(x, 0, 1);
+ int num = 1 / *x;
+ free(x);
+ return num;
+}
+
+void memset22_array() {
+ int array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
+ clang_analyzer_eval(array[1] == 2); // expected-warning{{TRUE}}
+ memset(array, 0, sizeof(array));
+ clang_analyzer_eval(array[1] == 0); // expected-warning{{TRUE}}
+}
+
+void memset23_array_pod_object() {
+ struct POD_memset array[10];
+ array[1].num = 10;
+ array[1].c = 'c';
+ clang_analyzer_eval(array[1].num == 10); // expected-warning{{TRUE}}
+ memset(&array[1], 0, sizeof(struct POD_memset));
+ clang_analyzer_eval(array[1].num == 0); // expected-warning{{UNKNOWN}}
+}
+
+void memset24_array_pod_object() {
+ struct POD_memset array[10];
+ array[1].num = 10;
+ array[1].c = 'c';
+ clang_analyzer_eval(array[1].num == 10); // expected-warning{{TRUE}}
+ memset(array, 0, sizeof(array));
+ clang_analyzer_eval(array[1].num == 0); // expected-warning{{TRUE}}
+}
+
+void memset25_symbol(char c) {
+ char array[10] = {1};
+ if (c != 0)
+ return;
+
+ memset(array, c, 10);
+
+ clang_analyzer_eval(strlen(array) == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(array[4] == 0); // expected-warning{{TRUE}}
+}
+
+void memset26_upper_UCHAR_MAX() {
+ char array[10] = {1};
+
+ memset(array, 1024, 10);
+
+ clang_analyzer_eval(strlen(array) == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(array[4] == 0); // expected-warning{{TRUE}}
+}
+
+//===----------------------------------------------------------------------===
// FIXMEs
//===----------------------------------------------------------------------===
-// The analyzer_eval call below should evaluate to true. We are being too
-// aggressive in marking the (length of) src symbol dead. The length of dst
-// depends on src. This could be explicitely specified in the checker or the
+// The analyzer_eval call below should evaluate to true. We are being too
+// aggressive in marking the (length of) src symbol dead. The length of dst
+// depends on src. This could be explicitly specified in the checker or the
// logic for handling MetadataSymbol in SymbolManager needs to change.
void strcat_symbolic_src_length(char *src) {
char dst[8] = "1234";
@@ -1173,6 +1397,7 @@ void strcat_symbolic_src_length(char *src) {
clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{UNKNOWN}}
}
+
// The analyzer_eval call below should evaluate to true. Most likely the same
// issue as the test above.
void strncpy_exactly_matching_buffer2(char *y) {
@@ -1185,3 +1410,87 @@ void strncpy_exactly_matching_buffer2(char *y) {
// This time, we know that y fits in x anyway.
clang_analyzer_eval(strlen(x) <= 3); // expected-warning{{UNKNOWN}}
}
+
+void memset7_char_array_nonnull() {
+ char str[5] = "abcd";
+ clang_analyzer_eval(strlen(str) == 4); // expected-warning{{TRUE}}
+ memset(str, '0', 5);
+ // FIXME: This should be TRUE.
+ clang_analyzer_eval(str[0] == '0'); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(strlen(str) >= 5); // expected-warning{{TRUE}}
+}
+
+void memset16_region_cast() {
+ char *str = (char *)malloc(10 * sizeof(int));
+ int *array = (int *)str;
+ memset(array, '0', 10 * sizeof(int));
+ // FIXME: This should be TRUE.
+ clang_analyzer_eval(str[10] == '0'); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(strlen((char *)array) >= 10 * sizeof(int)); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strlen(str) >= 10 * sizeof(int)); // expected-warning{{TRUE}}
+ free(str);
+}
+
+#ifdef SUPPRESS_OUT_OF_BOUND
+void memset17_region_cast() {
+ char *str = (char *)malloc(10 * sizeof(int));
+ int *array = (int *)str;
+ memset(array, '0', 12 * sizeof(int));
+ clang_analyzer_eval(str[10] == '0'); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(strlen((char *)array) >= 12 * sizeof(int)); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strlen(str) >= 12 * sizeof(int)); // expected-warning{{TRUE}}
+ free(str);
+}
+
+void memset18_memset_multiple_times() {
+ char *str = (char *)malloc(10 * sizeof(char));
+ clang_analyzer_eval(strlen(str) == 0); // expected-warning{{UNKNOWN}}
+
+ memset(str + 2, '\0', 10 * sizeof(char));
+ clang_analyzer_eval(strlen(str) == 0); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(str[1] == '\0'); // expected-warning{{UNKNOWN}}
+
+ memset(str, '0', 10 * sizeof(char));
+ clang_analyzer_eval(strlen(str) >= 10); // expected-warning{{TRUE}}
+ // FIXME: This should be TRUE.
+ clang_analyzer_eval(str[1] == '0'); // expected-warning{{UNKNOWN}}
+
+ free(str);
+}
+
+void memset19_memset_multiple_times() {
+ char *str = (char *)malloc(10 * sizeof(char));
+ clang_analyzer_eval(strlen(str) == 0); // expected-warning{{UNKNOWN}}
+
+ memset(str, '0', 10 * sizeof(char));
+ clang_analyzer_eval(strlen(str) >= 10); // expected-warning{{TRUE}}
+ // FIXME: This should be TRUE.
+ clang_analyzer_eval(str[1] == '0'); // expected-warning{{UNKNOWN}}
+
+ memset(str + 2, '\0', 10 * sizeof(char));
+ clang_analyzer_eval(strlen(str) >= 10); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(str[1] == '0'); // expected-warning{{UNKNOWN}}
+
+ free(str);
+}
+#endif
+
+// The analyzer does not support binding a symbol with default binding.
+void memset27_symbol(char c) {
+ char array[10] = {0};
+ if (c < 10)
+ return;
+
+ memset(array, c, 10);
+
+ clang_analyzer_eval(strlen(array) >= 10); // expected-warning{{TRUE}}
+ // FIXME: This should be TRUE.
+ clang_analyzer_eval(array[4] >= 10); // expected-warning{{UNKNOWN}}
+}
+
+void memset28() {
+ short x;
+ memset(&x, 1, sizeof(short));
+ // This should be true.
+ clang_analyzer_eval(x == 0x101); // expected-warning{{UNKNOWN}}
+}
diff --git a/test/Analysis/structured_bindings.cc b/test/Analysis/structured_bindings.cc
new file mode 100644
index 000000000000..1e23246f9a12
--- /dev/null
+++ b/test/Analysis/structured_bindings.cc
@@ -0,0 +1,10 @@
+// RUN: %clang_analyze_cc1 -std=c++17 -analyzer-checker=core -verify %s
+
+// expected-no-diagnostics
+struct s { int a; };
+int foo() {
+ auto[a] = s{1}; // FIXME: proper modelling
+ if (a) {
+ }
+}
+
diff --git a/test/Analysis/sval-dump-int128.c b/test/Analysis/sval-dump-int128.c
new file mode 100644
index 000000000000..3c28f1bd1bb6
--- /dev/null
+++ b/test/Analysis/sval-dump-int128.c
@@ -0,0 +1,7 @@
+// RUN: %clang_analyze_cc1 -triple x86_64-linux-gnu -analyzer-checker=debug.ExprInspection %s -verify
+
+void clang_analyzer_dump(unsigned __int128 x);
+
+void testDumpInt128() {
+ clang_analyzer_dump((unsigned __int128)5 << 64); // expected-warning{{92233720368547758080 U128b}}
+}
diff --git a/test/Analysis/svalbuilder-rearrange-comparisons.c b/test/Analysis/svalbuilder-rearrange-comparisons.c
new file mode 100644
index 000000000000..ac186120fe11
--- /dev/null
+++ b/test/Analysis/svalbuilder-rearrange-comparisons.c
@@ -0,0 +1,936 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection,core.builtin -analyzer-config aggressive-binary-operation-simplification=true -verify %s
+
+void clang_analyzer_dump(int x);
+void clang_analyzer_eval(int x);
+
+void exit(int);
+
+#define UINT_MAX (~0U)
+#define INT_MAX (UINT_MAX & (UINT_MAX >> 1))
+
+extern void __assert_fail (__const char *__assertion, __const char *__file,
+ unsigned int __line, __const char *__function)
+ __attribute__ ((__noreturn__));
+#define assert(expr) \
+ ((expr) ? (void)(0) : __assert_fail (#expr, __FILE__, __LINE__, __func__))
+
+int g();
+int f() {
+ int x = g();
+ // Assert that no overflows occur in this test file.
+ // Assuming that concrete integers are also within that range.
+ assert(x <= ((int)INT_MAX / 4));
+ assert(x >= -((int)INT_MAX / 4));
+ return x;
+}
+
+void compare_different_symbol_equal() {
+ int x = f(), y = f();
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
+ clang_analyzer_dump(x == y);
+ // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) == 0}}
+}
+
+void compare_different_symbol_plus_left_int_equal() {
+ int x = f()+1, y = f();
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
+ clang_analyzer_dump(x == y);
+ // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) == 1}}
+}
+
+void compare_different_symbol_minus_left_int_equal() {
+ int x = f()-1, y = f();
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
+ clang_analyzer_dump(x == y);
+ // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) == 1}}
+}
+
+void compare_different_symbol_plus_right_int_equal() {
+ int x = f(), y = f()+2;
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 2}}
+ clang_analyzer_dump(x == y);
+ // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) == 2}}
+}
+
+void compare_different_symbol_minus_right_int_equal() {
+ int x = f(), y = f()-2;
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 2}}
+ clang_analyzer_dump(x == y);
+ // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) == 2}}
+}
+
+void compare_different_symbol_plus_left_plus_right_int_equal() {
+ int x = f()+2, y = f()+1;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 2}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 1}}
+ clang_analyzer_dump(x == y);
+ // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) == 1}}
+}
+
+void compare_different_symbol_plus_left_minus_right_int_equal() {
+ int x = f()+2, y = f()-1;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 2}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 1}}
+ clang_analyzer_dump(x == y);
+ // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) == 3}}
+}
+
+void compare_different_symbol_minus_left_plus_right_int_equal() {
+ int x = f()-2, y = f()+1;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 2}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 1}}
+ clang_analyzer_dump(x == y);
+ // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) == 3}}
+}
+
+void compare_different_symbol_minus_left_minus_right_int_equal() {
+ int x = f()-2, y = f()-1;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 2}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 1}}
+ clang_analyzer_dump(x == y);
+ // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) == 1}}
+}
+
+void compare_same_symbol_equal() {
+ int x = f(), y = x;
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_eval(x == y);
+ // expected-warning@-1{{TRUE}}
+}
+
+void compare_same_symbol_plus_left_int_equal() {
+ int x = f(), y = x;
+ ++x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_eval(x == y);
+ // expected-warning@-1{{FALSE}}
+}
+
+void compare_same_symbol_minus_left_int_equal() {
+ int x = f(), y = x;
+ --x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_eval(x == y);
+ // expected-warning@-1{{FALSE}}
+}
+
+void compare_same_symbol_plus_right_int_equal() {
+ int x = f(), y = x+1;
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_eval(x == y);
+ // expected-warning@-1{{FALSE}}
+}
+
+void compare_same_symbol_minus_right_int_equal() {
+ int x = f(), y = x-1;
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_eval(x == y);
+ // expected-warning@-1{{FALSE}}
+}
+
+void compare_same_symbol_plus_left_plus_right_int_equal() {
+ int x = f(), y = x+1;
+ ++x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_eval(x == y);
+ // expected-warning@-1{{TRUE}}
+}
+
+void compare_same_symbol_plus_left_minus_right_int_equal() {
+ int x = f(), y = x-1;
+ ++x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_eval(x == y);
+ // expected-warning@-1{{FALSE}}
+}
+
+void compare_same_symbol_minus_left_plus_right_int_equal() {
+ int x = f(), y = x+1;
+ --x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_eval(x == y);
+ // expected-warning@-1{{FALSE}}
+}
+
+void compare_same_symbol_minus_left_minus_right_int_equal() {
+ int x = f(), y = x-1;
+ --x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_eval(x == y);
+ // expected-warning@-1{{TRUE}}
+}
+
+void compare_different_symbol_less_or_equal() {
+ int x = f(), y = f();
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
+ clang_analyzer_dump(x <= y);
+ // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) <= 0}}
+}
+
+void compare_different_symbol_plus_left_int_less_or_equal() {
+ int x = f()+1, y = f();
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
+ clang_analyzer_dump(x <= y);
+ // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) >= 1}}
+}
+
+void compare_different_symbol_minus_left_int_less_or_equal() {
+ int x = f()-1, y = f();
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
+ clang_analyzer_dump(x <= y);
+ // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) <= 1}}
+}
+
+void compare_different_symbol_plus_right_int_less_or_equal() {
+ int x = f(), y = f()+2;
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 2}}
+ clang_analyzer_dump(x <= y);
+ // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) <= 2}}
+}
+
+void compare_different_symbol_minus_right_int_less_or_equal() {
+ int x = f(), y = f()-2;
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 2}}
+ clang_analyzer_dump(x <= y);
+ // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) >= 2}}
+}
+
+void compare_different_symbol_plus_left_plus_right_int_less_or_equal() {
+ int x = f()+2, y = f()+1;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 2}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 1}}
+ clang_analyzer_dump(x <= y);
+ // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) >= 1}}
+}
+
+void compare_different_symbol_plus_left_minus_right_int_less_or_equal() {
+ int x = f()+2, y = f()-1;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 2}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 1}}
+ clang_analyzer_dump(x <= y);
+ // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) >= 3}}
+}
+
+void compare_different_symbol_minus_left_plus_right_int_less_or_equal() {
+ int x = f()-2, y = f()+1;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 2}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 1}}
+ clang_analyzer_dump(x <= y);
+ // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) <= 3}}
+}
+
+void compare_different_symbol_minus_left_minus_right_int_less_or_equal() {
+ int x = f()-2, y = f()-1;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 2}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 1}}
+ clang_analyzer_dump(x <= y);
+ // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) <= 1}}
+}
+
+void compare_same_symbol_less_or_equal() {
+ int x = f(), y = x;
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_eval(x <= y);
+ // expected-warning@-1{{TRUE}}
+}
+
+void compare_same_symbol_plus_left_int_less_or_equal() {
+ int x = f(), y = x;
+ ++x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_eval(x <= y);
+ // expected-warning@-1{{FALSE}}
+}
+
+void compare_same_symbol_minus_left_int_less_or_equal() {
+ int x = f(), y = x;
+ --x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_eval(x <= y);
+ // expected-warning@-1{{TRUE}}
+}
+
+void compare_same_symbol_plus_right_int_less_or_equal() {
+ int x = f(), y = x+1;
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_eval(x <= y);
+ // expected-warning@-1{{TRUE}}
+}
+
+void compare_same_symbol_minus_right_int_less_or_equal() {
+ int x = f(), y = x-1;
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_eval(x <= y);
+ // expected-warning@-1{{FALSE}}
+}
+
+void compare_same_symbol_plus_left_plus_right_int_less_or_equal() {
+ int x = f(), y = x+1;
+ ++x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_eval(x <= y);
+ // expected-warning@-1{{TRUE}}
+}
+
+void compare_same_symbol_plus_left_minus_right_int_less_or_equal() {
+ int x = f(), y = x-1;
+ ++x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_eval(x <= y);
+ // expected-warning@-1{{FALSE}}
+}
+
+void compare_same_symbol_minus_left_plus_right_int_less_or_equal() {
+ int x = f(), y = x+1;
+ --x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_eval(x <= y);
+ // expected-warning@-1{{TRUE}}
+}
+
+void compare_same_symbol_minus_left_minus_right_int_less_or_equal() {
+ int x = f(), y = x-1;
+ --x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_eval(x <= y);
+ // expected-warning@-1{{TRUE}}
+}
+
+void compare_different_symbol_less() {
+ int x = f(), y = f();
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
+ clang_analyzer_dump(x < y);
+ // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) < 0}}
+}
+
+void compare_different_symbol_plus_left_int_less() {
+ int x = f()+1, y = f();
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
+ clang_analyzer_dump(x < y);
+ // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) > 1}}
+}
+
+void compare_different_symbol_minus_left_int_less() {
+ int x = f()-1, y = f();
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
+ clang_analyzer_dump(x < y);
+ // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) < 1}}
+}
+
+void compare_different_symbol_plus_right_int_less() {
+ int x = f(), y = f()+2;
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 2}}
+ clang_analyzer_dump(x < y);
+ // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) < 2}}
+}
+
+void compare_different_symbol_minus_right_int_less() {
+ int x = f(), y = f()-2;
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 2}}
+ clang_analyzer_dump(x < y);
+ // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) > 2}}
+}
+
+void compare_different_symbol_plus_left_plus_right_int_less() {
+ int x = f()+2, y = f()+1;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 2}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 1}}
+ clang_analyzer_dump(x < y);
+ // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) > 1}}
+}
+
+void compare_different_symbol_plus_left_minus_right_int_less() {
+ int x = f()+2, y = f()-1;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 2}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 1}}
+ clang_analyzer_dump(x < y);
+ // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) > 3}}
+}
+
+void compare_different_symbol_minus_left_plus_right_int_less() {
+ int x = f()-2, y = f()+1;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 2}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 1}}
+ clang_analyzer_dump(x < y);
+ // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) < 3}}
+}
+
+void compare_different_symbol_minus_left_minus_right_int_less() {
+ int x = f()-2, y = f()-1;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 2}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 1}}
+ clang_analyzer_dump(x < y);
+ // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) < 1}}
+}
+
+void compare_same_symbol_less() {
+ int x = f(), y = x;
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_eval(x < y);
+ // expected-warning@-1{{FALSE}}
+}
+
+void compare_same_symbol_plus_left_int_less() {
+ int x = f(), y = x;
+ ++x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_eval(x < y);
+ // expected-warning@-1{{FALSE}}
+}
+
+void compare_same_symbol_minus_left_int_less() {
+ int x = f(), y = x;
+ --x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_eval(x < y);
+ // expected-warning@-1{{TRUE}}
+}
+
+void compare_same_symbol_plus_right_int_less() {
+ int x = f(), y = x+1;
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_eval(x < y);
+ // expected-warning@-1{{TRUE}}
+}
+
+void compare_same_symbol_minus_right_int_less() {
+ int x = f(), y = x-1;
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_eval(x < y);
+ // expected-warning@-1{{FALSE}}
+}
+
+void compare_same_symbol_plus_left_plus_right_int_less() {
+ int x = f(), y = x+1;
+ ++x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_eval(x < y);
+ // expected-warning@-1{{FALSE}}
+}
+
+void compare_same_symbol_plus_left_minus_right_int_less() {
+ int x = f(), y = x-1;
+ ++x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_eval(x < y);
+ // expected-warning@-1{{FALSE}}
+}
+
+void compare_same_symbol_minus_left_plus_right_int_less() {
+ int x = f(), y = x+1;
+ --x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_eval(x < y);
+ // expected-warning@-1{{TRUE}}
+}
+
+void compare_same_symbol_minus_left_minus_right_int_less() {
+ int x = f(), y = x-1;
+ --x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_eval(x < y);
+ // expected-warning@-1{{FALSE}}
+}
+
+void compare_different_symbol_equal_unsigned() {
+ unsigned x = f(), y = f();
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
+ clang_analyzer_dump(x == y);
+ // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) == 0}}
+}
+
+void compare_different_symbol_plus_left_int_equal_unsigned() {
+ unsigned x = f()+1, y = f();
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
+ clang_analyzer_dump(x == y);
+ // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) == 1}}
+}
+
+void compare_different_symbol_minus_left_int_equal_unsigned() {
+ unsigned x = f()-1, y = f();
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
+ clang_analyzer_dump(x == y);
+ // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) == 1}}
+}
+
+void compare_different_symbol_plus_right_int_equal_unsigned() {
+ unsigned x = f(), y = f()+2;
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 2}}
+ clang_analyzer_dump(x == y);
+ // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) == 2}}
+}
+
+void compare_different_symbol_minus_right_int_equal_unsigned() {
+ unsigned x = f(), y = f()-2;
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 2}}
+ clang_analyzer_dump(x == y);
+ // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) == 2}}
+}
+
+void compare_different_symbol_plus_left_plus_right_int_equal_unsigned() {
+ unsigned x = f()+2, y = f()+1;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 2}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 1}}
+ clang_analyzer_dump(x == y);
+ // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) == 1}}
+}
+
+void compare_different_symbol_plus_left_minus_right_int_equal_unsigned() {
+ unsigned x = f()+2, y = f()-1;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 2}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 1}}
+ clang_analyzer_dump(x == y);
+ // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) == 3}}
+}
+
+void compare_different_symbol_minus_left_plus_right_int_equal_unsigned() {
+ unsigned x = f()-2, y = f()+1;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 2}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 1}}
+ clang_analyzer_dump(x == y);
+ // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) == 3}}
+}
+
+void compare_different_symbol_minus_left_minus_right_int_equal_unsigned() {
+ unsigned x = f()-2, y = f()-1;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 2}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 1}}
+ clang_analyzer_dump(x == y);
+ // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) == 1}}
+}
+
+void compare_same_symbol_equal_unsigned() {
+ unsigned x = f(), y = x;
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_eval(x == y);
+ // expected-warning@-1{{TRUE}}
+}
+
+void compare_same_symbol_plus_left_int_equal_unsigned() {
+ unsigned x = f(), y = x;
+ ++x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(x == y);
+ // expected-warning@-1{{((conj_$2{int}) + 1U) == (conj_$2{int})}}
+}
+
+void compare_same_symbol_minus_left_int_equal_unsigned() {
+ unsigned x = f(), y = x;
+ --x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(x == y);
+ // expected-warning@-1{{((conj_$2{int}) - 1U) == (conj_$2{int})}}
+}
+
+void compare_same_symbol_plus_right_int_equal_unsigned() {
+ unsigned x = f(), y = x+1;
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_dump(x == y);
+ // expected-warning@-1{{(conj_$2{int}) == ((conj_$2{int}) + 1U)}}
+}
+
+void compare_same_symbol_minus_right_int_equal_unsigned() {
+ unsigned x = f(), y = x-1;
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_dump(x == y);
+ // expected-warning@-1{{(conj_$2{int}) == ((conj_$2{int}) - 1U)}}
+}
+
+void compare_same_symbol_plus_left_plus_right_int_equal_unsigned() {
+ unsigned x = f(), y = x+1;
+ ++x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_eval(x == y);
+ // expected-warning@-1{{TRUE}}
+}
+
+void compare_same_symbol_plus_left_minus_right_int_equal_unsigned() {
+ unsigned x = f(), y = x-1;
+ ++x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_dump(x == y);
+ // expected-warning@-1{{((conj_$2{int}) + 1U) == ((conj_$2{int}) - 1U)}}
+}
+
+void compare_same_symbol_minus_left_plus_right_int_equal_unsigned() {
+ unsigned x = f(), y = x+1;
+ --x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_dump(x == y);
+ // expected-warning@-1{{((conj_$2{int}) - 1U) == ((conj_$2{int}) + 1U)}}
+}
+
+void compare_same_symbol_minus_left_minus_right_int_equal_unsigned() {
+ unsigned x = f(), y = x-1;
+ --x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_eval(x == y);
+ // expected-warning@-1{{TRUE}}
+}
+
+void compare_different_symbol_less_or_equal_unsigned() {
+ unsigned x = f(), y = f();
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
+ clang_analyzer_dump(x <= y);
+ // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) <= 0}}
+}
+
+void compare_different_symbol_plus_left_int_less_or_equal_unsigned() {
+ unsigned x = f()+1, y = f();
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
+ clang_analyzer_dump(x <= y);
+ // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) >= 1}}
+}
+
+void compare_different_symbol_minus_left_int_less_or_equal_unsigned() {
+ unsigned x = f()-1, y = f();
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
+ clang_analyzer_dump(x <= y);
+ // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) <= 1}}
+}
+
+void compare_different_symbol_plus_right_int_less_or_equal_unsigned() {
+ unsigned x = f(), y = f()+2;
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 2}}
+ clang_analyzer_dump(x <= y);
+ // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) <= 2}}
+}
+
+void compare_different_symbol_minus_right_int_less_or_equal_unsigned() {
+ unsigned x = f(), y = f()-2;
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 2}}
+ clang_analyzer_dump(x <= y);
+ // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) >= 2}}
+}
+
+void compare_different_symbol_plus_left_plus_right_int_less_or_equal_unsigned() {
+ unsigned x = f()+2, y = f()+1;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 2}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 1}}
+ clang_analyzer_dump(x <= y);
+ // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) >= 1}}
+}
+
+void compare_different_symbol_plus_left_minus_right_int_less_or_equal_unsigned() {
+ unsigned x = f()+2, y = f()-1;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 2}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 1}}
+ clang_analyzer_dump(x <= y);
+ // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) >= 3}}
+}
+
+void compare_different_symbol_minus_left_plus_right_int_less_or_equal_unsigned() {
+ unsigned x = f()-2, y = f()+1;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 2}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 1}}
+ clang_analyzer_dump(x <= y);
+ // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) <= 3}}
+}
+
+void compare_different_symbol_minus_left_minus_right_int_less_or_equal_unsigned() {
+ unsigned x = f()-2, y = f()-1;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 2}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 1}}
+ clang_analyzer_dump(x <= y);
+ // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) <= 1}}
+}
+
+void compare_same_symbol_less_or_equal_unsigned() {
+ unsigned x = f(), y = x;
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_eval(x <= y);
+ // expected-warning@-1{{TRUE}}
+}
+
+void compare_same_symbol_plus_left_int_less_or_equal_unsigned() {
+ unsigned x = f(), y = x;
+ ++x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(x <= y);
+ // expected-warning@-1{{((conj_$2{int}) + 1U) <= (conj_$2{int})}}
+}
+
+void compare_same_symbol_minus_left_int_less_or_equal_unsigned() {
+ unsigned x = f(), y = x;
+ --x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(x <= y);
+ // expected-warning@-1{{((conj_$2{int}) - 1U) <= (conj_$2{int})}}
+}
+
+void compare_same_symbol_plus_right_int_less_or_equal_unsigned() {
+ unsigned x = f(), y = x+1;
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_dump(x <= y);
+ // expected-warning@-1{{(conj_$2{int}) <= ((conj_$2{int}) + 1U)}}
+}
+
+void compare_same_symbol_minus_right_int_less_or_equal_unsigned() {
+ unsigned x = f(), y = x-1;
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_dump(x <= y);
+ // expected-warning@-1{{(conj_$2{int}) <= ((conj_$2{int}) - 1U)}}
+}
+
+void compare_same_symbol_plus_left_plus_right_int_less_or_equal_unsigned() {
+ unsigned x = f(), y = x+1;
+ ++x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_eval(x <= y);
+ // expected-warning@-1{{TRUE}}
+}
+
+void compare_same_symbol_plus_left_minus_right_int_less_or_equal_unsigned() {
+ unsigned x = f(), y = x-1;
+ ++x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_dump(x <= y);
+ // expected-warning@-1{{((conj_$2{int}) + 1U) <= ((conj_$2{int}) - 1U)}}
+}
+
+void compare_same_symbol_minus_left_plus_right_int_less_or_equal_unsigned() {
+ unsigned x = f(), y = x+1;
+ --x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_dump(x <= y);
+ // expected-warning@-1{{((conj_$2{int}) - 1U) <= ((conj_$2{int}) + 1U)}}
+}
+
+void compare_same_symbol_minus_left_minus_right_int_less_or_equal_unsigned() {
+ unsigned x = f(), y = x-1;
+ --x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_eval(x <= y);
+ // expected-warning@-1{{TRUE}}
+}
+
+void compare_different_symbol_less_unsigned() {
+ unsigned x = f(), y = f();
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
+ clang_analyzer_dump(x < y);
+ // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) < 0}}
+}
+
+void compare_different_symbol_plus_left_int_less_unsigned() {
+ unsigned x = f()+1, y = f();
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
+ clang_analyzer_dump(x < y);
+ // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) > 1}}
+}
+
+void compare_different_symbol_minus_left_int_less_unsigned() {
+ unsigned x = f()-1, y = f();
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
+ clang_analyzer_dump(x < y);
+ // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) < 1}}
+}
+
+void compare_different_symbol_plus_right_int_less_unsigned() {
+ unsigned x = f(), y = f()+2;
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 2}}
+ clang_analyzer_dump(x < y);
+ // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) < 2}}
+}
+
+void compare_different_symbol_minus_right_int_less_unsigned() {
+ unsigned x = f(), y = f()-2;
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 2}}
+ clang_analyzer_dump(x < y);
+ // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) > 2}}
+}
+
+void compare_different_symbol_plus_left_plus_right_int_less_unsigned() {
+ unsigned x = f()+2, y = f()+1;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 2}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 1}}
+ clang_analyzer_dump(x < y);
+ // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) > 1}}
+}
+
+void compare_different_symbol_plus_left_minus_right_int_less_unsigned() {
+ unsigned x = f()+2, y = f()-1;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 2}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 1}}
+ clang_analyzer_dump(x < y);
+ // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) > 3}}
+}
+
+void compare_different_symbol_minus_left_plus_right_int_less_unsigned() {
+ unsigned x = f()-2, y = f()+1;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 2}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 1}}
+ clang_analyzer_dump(x < y);
+ // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) < 3}}
+}
+
+void compare_different_symbol_minus_left_minus_right_int_less_unsigned() {
+ unsigned x = f()-2, y = f()-1;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 2}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 1}}
+ clang_analyzer_dump(x < y);
+ // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) < 1}}
+}
+
+void compare_same_symbol_less_unsigned() {
+ unsigned x = f(), y = x;
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_eval(x < y);
+ // expected-warning@-1{{FALSE}}
+}
+
+void compare_same_symbol_plus_left_int_less_unsigned() {
+ unsigned x = f(), y = x;
+ ++x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(x < y);
+ // expected-warning@-1{{((conj_$2{int}) + 1U) < (conj_$2{int})}}
+}
+
+void compare_same_symbol_minus_left_int_less_unsigned() {
+ unsigned x = f(), y = x;
+ --x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(x < y);
+ // expected-warning@-1{{((conj_$2{int}) - 1U) < (conj_$2{int})}}
+}
+
+void compare_same_symbol_plus_right_int_less_unsigned() {
+ unsigned x = f(), y = x+1;
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_dump(x < y);
+ // expected-warning@-1{{(conj_$2{int}) < ((conj_$2{int}) + 1U)}}
+}
+
+void compare_same_symbol_minus_right_int_less_unsigned() {
+ unsigned x = f(), y = x-1;
+ clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_dump(x < y);
+ // expected-warning@-1{{(conj_$2{int}) < ((conj_$2{int}) - 1U)}}
+}
+
+void compare_same_symbol_plus_left_plus_right_int_less_unsigned() {
+ unsigned x = f(), y = x+1;
+ ++x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_eval(x < y);
+ // expected-warning@-1{{FALSE}}
+}
+
+void compare_same_symbol_plus_left_minus_right_int_less_unsigned() {
+ unsigned x = f(), y = x-1;
+ ++x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_dump(x < y);
+ // expected-warning@-1{{((conj_$2{int}) + 1U) < ((conj_$2{int}) - 1U)}}
+}
+
+void compare_same_symbol_minus_left_plus_right_int_less_unsigned() {
+ unsigned x = f(), y = x+1;
+ --x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
+ clang_analyzer_dump(x < y);
+ // expected-warning@-1{{((conj_$2{int}) - 1U) < ((conj_$2{int}) + 1U)}}
+}
+
+void compare_same_symbol_minus_left_minus_right_int_less_unsigned() {
+ unsigned x = f(), y = x-1;
+ --x;
+ clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
+ clang_analyzer_eval(x < y);
+ // expected-warning@-1{{FALSE}}
+}
+
+void overflow(signed char n, signed char m) {
+ if (n + 0 > m + 0) {
+ clang_analyzer_eval(n - 126 == m + 3); // expected-warning{{UNKNOWN}}
+ }
+}
+
+int mixed_integer_types(int x, int y) {
+ short a = x - 1U;
+ return a - y;
+}
diff --git a/test/Analysis/symbol-reaper.c b/test/Analysis/symbol-reaper.c
index 72fcc7e2b9df..a47161bea2e3 100644
--- a/test/Analysis/symbol-reaper.c
+++ b/test/Analysis/symbol-reaper.c
@@ -3,6 +3,9 @@
void clang_analyzer_eval(int);
void clang_analyzer_warnOnDeadSymbol(int);
void clang_analyzer_numTimesReached();
+void clang_analyzer_warnIfReached();
+
+void exit(int);
int conjure_index();
@@ -58,6 +61,12 @@ struct S1 {
struct S2 {
struct S1 array[5];
} s2;
+struct S3 {
+ void *field;
+};
+
+struct S1 *conjure_S1();
+struct S3 *conjure_S3();
void test_element_index_lifetime_with_complicated_hierarchy_of_regions() {
do {
@@ -68,6 +77,18 @@ void test_element_index_lifetime_with_complicated_hierarchy_of_regions() {
} while (0); // no-warning
}
+void test_loc_as_integer_element_index_lifetime() {
+ do {
+ int x;
+ struct S3 *s = conjure_S3();
+ clang_analyzer_warnOnDeadSymbol((int)s);
+ x = (int)&(s->field);
+ ptr = &arr[x];
+ if (s) {}
+ // FIXME: Should not warn. The symbol is still alive within the ptr's index.
+ } while (0); // expected-warning{{SYMBOL DEAD}}
+}
+
// Test below checks lifetime of SymbolRegionValue in certain conditions.
int **ptrptr;
@@ -78,3 +99,38 @@ void test_region_lifetime_as_store_value(int *x) {
(void)0; // No-op; make sure the environment forgets things and the GC runs.
clang_analyzer_eval(**ptrptr); // expected-warning{{TRUE}}
} // no-warning
+
+int *produce_region_referenced_only_through_field_in_environment_value() {
+ struct S1 *s = conjure_S1();
+ clang_analyzer_warnOnDeadSymbol((int) s);
+ int *x = &s->field;
+ return x;
+}
+
+void test_region_referenced_only_through_field_in_environment_value() {
+ produce_region_referenced_only_through_field_in_environment_value();
+} // expected-warning{{SYMBOL DEAD}}
+
+void test_region_referenced_only_through_field_in_store_value() {
+ struct S1 *s = conjure_S1();
+ clang_analyzer_warnOnDeadSymbol((int) s);
+ ptr = &s->field; // Write the symbol into a global. It should live forever.
+ if (!s) {
+ exit(0); // no-warning (symbol should not die here)
+ // exit() is noreturn.
+ clang_analyzer_warnIfReached(); // no-warning
+ }
+ if (!ptr) { // no-warning (symbol should not die here)
+ // We exit()ed under these constraints earlier.
+ clang_analyzer_warnIfReached(); // no-warning
+ }
+ // The exit() call invalidates globals. The symbol will die here because
+ // the exit() statement itself is already over and there's no better statement
+ // to put the diagnostic on.
+} // expected-warning{{SYMBOL DEAD}}
+
+void test_zombie_referenced_only_through_field_in_store_value() {
+ struct S1 *s = conjure_S1();
+ clang_analyzer_warnOnDeadSymbol((int) s);
+ int *x = &s->field;
+} // expected-warning{{SYMBOL DEAD}}
diff --git a/test/Analysis/taint-diagnostic-visitor.c b/test/Analysis/taint-diagnostic-visitor.c
index 50fc0b6a4e26..6533cd7625ca 100644
--- a/test/Analysis/taint-diagnostic-visitor.c
+++ b/test/Analysis/taint-diagnostic-visitor.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.security.taint,core -analyzer-output=text -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -analyzer-output=text -verify %s
// This file is for testing enhanced diagnostics produced by the GenericTaintChecker
@@ -11,3 +11,26 @@ void taintDiagnostic()
scanf("%s", buf); // expected-note {{Taint originated here}}
system(buf); // expected-warning {{Untrusted data is passed to a system call}} // expected-note {{Untrusted data is passed to a system call (CERT/STR02-C. Sanitize data passed to complex subsystems)}}
}
+
+int taintDiagnosticOutOfBound() {
+ int index;
+ int Array[] = {1, 2, 3, 4, 5};
+ scanf("%d", &index); // expected-note {{Taint originated here}}
+ return Array[index]; // expected-warning {{Out of bound memory access (index is tainted)}}
+ // expected-note@-1 {{Out of bound memory access (index is tainted)}}
+}
+
+int taintDiagnosticDivZero(int operand) {
+ scanf("%d", &operand); // expected-note {{Value assigned to 'operand'}}
+ // expected-note@-1 {{Taint originated here}}
+ return 10 / operand; // expected-warning {{Division by a tainted value, possibly zero}}
+ // expected-note@-1 {{Division by a tainted value, possibly zero}}
+}
+
+void taintDiagnosticVLA() {
+ int x;
+ scanf("%d", &x); // expected-note {{Value assigned to 'x'}}
+ // expected-note@-1 {{Taint originated here}}
+ int vla[x]; // expected-warning {{Declared variable-length array (VLA) has tainted size}}
+ // expected-note@-1 {{Declared variable-length array (VLA) has tainted size}}
+}
diff --git a/test/Analysis/taint-generic.c b/test/Analysis/taint-generic.c
index d3ca246b82a8..2717e91b4304 100644
--- a/test/Analysis/taint-generic.c
+++ b/test/Analysis/taint-generic.c
@@ -1,10 +1,16 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -Wno-format-security -verify %s
+// RUN: %clang_analyze_cc1 -DFILE_IS_STRUCT -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -Wno-format-security -verify %s
int scanf(const char *restrict format, ...);
int getchar(void);
typedef struct _FILE FILE;
+#ifdef FILE_IS_STRUCT
+extern struct _FILE *stdin;
+#else
extern FILE *stdin;
+#endif
+
int fscanf(FILE *restrict stream, const char *restrict format, ...);
int sprintf(char *str, const char *format, ...);
void setproctitle(const char *fmt, ...);
diff --git a/test/Analysis/temp-obj-dtors-cfg-output.cpp b/test/Analysis/temp-obj-dtors-cfg-output.cpp
index 05b6a31059b4..d08b01cd3964 100644
--- a/test/Analysis/temp-obj-dtors-cfg-output.cpp
+++ b/test/Analysis/temp-obj-dtors-cfg-output.cpp
@@ -1,8 +1,23 @@
// RUN: rm -f %t
-// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -analyzer-config cfg-temporary-dtors=true -std=c++98 %s > %t 2>&1
-// RUN: FileCheck --input-file=%t -check-prefix=CXX98 -check-prefix=CHECK %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -analyzer-config cfg-temporary-dtors=true -std=c++11 %s > %t 2>&1
-// RUN: FileCheck --input-file=%t -check-prefix=CXX11 -check-prefix=CHECK %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -analyzer-config cfg-rich-constructors=false -std=c++98 %s > %t 2>&1
+// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX98,WARNINGS,CXX98-WARNINGS %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -analyzer-config cfg-rich-constructors=false -std=c++11 %s > %t 2>&1
+// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX11,WARNINGS,CXX11-WARNINGS %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -analyzer-config cfg-rich-constructors=true -std=c++98 %s > %t 2>&1
+// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX98,ANALYZER,CXX98-ANALYZER %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -analyzer-config cfg-rich-constructors=true -std=c++11 %s > %t 2>&1
+// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX11,ANALYZER,CXX11-ANALYZER %s
+
+// This file tests how we construct two different flavors of the Clang CFG -
+// the CFG used by the Sema analysis-based warnings and the CFG used by the
+// static analyzer. The difference in the behavior is checked via FileCheck
+// prefixes (WARNINGS and ANALYZER respectively). When introducing new analyzer
+// flags, no new run lines should be added - just these flags would go to the
+// respective line depending on where is it turned on and where is it turned
+// off. Feel free to add tests that test only one of the CFG flavors if you're
+// not sure how the other flavor is supposed to work in your case.
+
+// Additionally, different C++ standards are checked.
class A {
public:
@@ -190,6 +205,24 @@ int testConsistencyNestedNormalReturn(bool value) {
return 0;
}
+namespace pass_references_through {
+class C {
+public:
+ ~C() {}
+};
+
+const C &foo1();
+C &&foo2();
+
+// In these examples the foo() expression has record type, not reference type.
+// Don't try to figure out how to perform construction of the record here.
+const C &bar1() { return foo1(); } // no-crash
+C &&bar2() { return foo2(); } // no-crash
+const C &bar3(bool coin) {
+ return coin ? foo1() : foo1(); // no-crash
+}
+} // end namespace pass_references_through
+
// CHECK: [B1 (ENTRY)]
// CHECK: Succs (1): B0
// CHECK: [B0 (EXIT)]
@@ -201,11 +234,13 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: [B2 (ENTRY)]
// CHECK: Succs (1): B1
// CHECK: [B1]
-// CHECK: 1: A() (CXXConstructExpr, class A)
+// WARNINGS: 1: A() (CXXConstructExpr, class A)
+// ANALYZER: 1: A() (CXXConstructExpr, [B1.2], [B1.4], [B1.5], class A)
// CHECK: 2: [B1.1] (BindTemporary)
// CHECK: 3: [B1.2] (ImplicitCastExpr, NoOp, const class A)
// CHECK: 4: [B1.3]
-// CHECK: 5: [B1.4] (CXXConstructExpr, class A)
+// WARNINGS: 5: [B1.4] (CXXConstructExpr, class A)
+// ANALYZER: 5: [B1.4] (CXXConstructExpr, [B1.7], class A)
// CHECK: 6: ~A() (Temporary object destructor)
// CHECK: 7: return [B1.5];
// CHECK: Preds (1): B2
@@ -259,11 +294,13 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: [B2 (ENTRY)]
// CHECK: Succs (1): B1
// CHECK: [B1]
-// CHECK: 1: A() (CXXConstructExpr, class A)
+// WARNINGS: 1: A() (CXXConstructExpr, class A)
+// ANALYZER: 1: A() (CXXConstructExpr, [B1.2], [B1.4], [B1.5], class A)
// CHECK: 2: [B1.1] (BindTemporary)
// CHECK: 3: [B1.2] (ImplicitCastExpr, NoOp, const class A)
// CHECK: 4: [B1.3]
-// CHECK: 5: [B1.4] (CXXConstructExpr, class A)
+// WARNINGS: 5: [B1.4] (CXXConstructExpr, class A)
+// ANALYZER: 5: [B1.4] (CXXConstructExpr, [B1.7], class A)
// CHECK: 6: ~A() (Temporary object destructor)
// CHECK: 7: return [B1.5];
// CHECK: Preds (1): B2
@@ -273,41 +310,49 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: [B2 (ENTRY)]
// CHECK: Succs (1): B1
// CHECK: [B1]
-// CHECK: 1: A() (CXXConstructExpr, class A)
+// WARNINGS: 1: A() (CXXConstructExpr, class A)
+// ANALYZER: 1: A() (CXXConstructExpr, [B1.2], [B1.3], class A)
// CHECK: 2: [B1.1] (BindTemporary)
-// CHECK: 3: [B1.2].operator int
-// CHECK: 4: [B1.2]
-// CHECK: 5: [B1.4] (ImplicitCastExpr, UserDefinedConversion, int)
-// CHECK: 6: int([B1.5]) (CXXFunctionalCastExpr, NoOp, int)
-// CHECK: 7: B() (CXXConstructExpr, class B)
-// CHECK: 8: [B1.7] (BindTemporary)
-// CHECK: 9: [B1.8].operator int
-// CHECK: 10: [B1.8]
-// CHECK: 11: [B1.10] (ImplicitCastExpr, UserDefinedConversion, int)
-// CHECK: 12: int([B1.11]) (CXXFunctionalCastExpr, NoOp, int)
-// CHECK: 13: [B1.6] + [B1.12]
-// CHECK: 14: int a = int(A()) + int(B());
-// CHECK: 15: ~B() (Temporary object destructor)
-// CHECK: 16: ~A() (Temporary object destructor)
-// CHECK: 17: foo
-// CHECK: 18: [B1.17] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(int))
-// CHECK: 19: A() (CXXConstructExpr, class A)
-// CHECK: 20: [B1.19] (BindTemporary)
-// CHECK: 21: [B1.20].operator int
-// CHECK: 22: [B1.20]
-// CHECK: 23: [B1.22] (ImplicitCastExpr, UserDefinedConversion, int)
-// CHECK: 24: int([B1.23]) (CXXFunctionalCastExpr, NoOp, int)
-// CHECK: 25: B() (CXXConstructExpr, class B)
-// CHECK: 26: [B1.25] (BindTemporary)
-// CHECK: 27: [B1.26].operator int
-// CHECK: 28: [B1.26]
-// CHECK: 29: [B1.28] (ImplicitCastExpr, UserDefinedConversion, int)
-// CHECK: 30: int([B1.29]) (CXXFunctionalCastExpr, NoOp, int)
-// CHECK: 31: [B1.24] + [B1.30]
-// CHECK: 32: [B1.18]([B1.31])
-// CHECK: 33: ~B() (Temporary object destructor)
-// CHECK: 34: ~A() (Temporary object destructor)
-// CHECK: 35: int b;
+// CHECK: 3: [B1.2]
+// CHECK: 4: [B1.3].operator int
+// CHECK: 5: [B1.3]
+// CHECK: 6: [B1.5] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK: 7: int([B1.6]) (CXXFunctionalCastExpr, NoOp, int)
+// WARNINGS: 8: B() (CXXConstructExpr, class B)
+// ANALYZER: 8: B() (CXXConstructExpr, [B1.9], [B1.10], class B)
+// CHECK: 9: [B1.8] (BindTemporary)
+// CHECK: 10: [B1.9]
+// CHECK: 11: [B1.10].operator int
+// CHECK: 12: [B1.10]
+// CHECK: 13: [B1.12] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK: 14: int([B1.13]) (CXXFunctionalCastExpr, NoOp, int)
+// CHECK: 15: [B1.7] + [B1.14]
+// CHECK: 16: int a = int(A()) + int(B());
+// CHECK: 17: ~B() (Temporary object destructor)
+// CHECK: 18: ~A() (Temporary object destructor)
+// CHECK: 19: foo
+// CHECK: 20: [B1.19] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(int))
+// WARNINGS: 21: A() (CXXConstructExpr, class A)
+// ANALYZER: 21: A() (CXXConstructExpr, [B1.22], [B1.23], class A)
+// CHECK: 22: [B1.21] (BindTemporary)
+// CHECK: 23: [B1.22]
+// CHECK: 24: [B1.23].operator int
+// CHECK: 25: [B1.23]
+// CHECK: 26: [B1.25] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK: 27: int([B1.26]) (CXXFunctionalCastExpr, NoOp, int)
+// WARNINGS: 28: B() (CXXConstructExpr, class B)
+// ANALYZER: 28: B() (CXXConstructExpr, [B1.29], [B1.30], class B)
+// CHECK: 29: [B1.28] (BindTemporary)
+// CHECK: 30: [B1.29]
+// CHECK: 31: [B1.30].operator int
+// CHECK: 32: [B1.30]
+// CHECK: 33: [B1.32] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK: 34: int([B1.33]) (CXXFunctionalCastExpr, NoOp, int)
+// CHECK: 35: [B1.27] + [B1.34]
+// CHECK: 36: [B1.20]([B1.35])
+// CHECK: 37: ~B() (Temporary object destructor)
+// CHECK: 38: ~A() (Temporary object destructor)
+// CHECK: 39: int b;
// CHECK: Preds (1): B2
// CHECK: Succs (1): B0
// CHECK: [B0 (EXIT)]
@@ -324,29 +369,33 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: Preds (1): B3
// CHECK: Succs (1): B1
// CHECK: [B3]
-// CHECK: 1: [B5.8] && [B4.5]
+// CHECK: 1: [B5.9] && [B4.6]
// CHECK: 2: [B5.3]([B3.1])
// CHECK: T: (Temp Dtor) [B4.2]
// CHECK: Preds (2): B4 B5
// CHECK: Succs (2): B2 B1
// CHECK: [B4]
-// CHECK: 1: B() (CXXConstructExpr, class B)
+// WARNINGS: 1: B() (CXXConstructExpr, class B)
+// ANALYZER: 1: B() (CXXConstructExpr, [B4.2], [B4.3], class B)
// CHECK: 2: [B4.1] (BindTemporary)
-// CHECK: 3: [B4.2].operator bool
-// CHECK: 4: [B4.2]
-// CHECK: 5: [B4.4] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CHECK: 3: [B4.2]
+// CHECK: 4: [B4.3].operator bool
+// CHECK: 5: [B4.3]
+// CHECK: 6: [B4.5] (ImplicitCastExpr, UserDefinedConversion, _Bool)
// CHECK: Preds (1): B5
// CHECK: Succs (1): B3
// CHECK: [B5]
// CHECK: 1: ~A() (Temporary object destructor)
// CHECK: 2: foo
// CHECK: 3: [B5.2] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(_Bool))
-// CHECK: 4: A() (CXXConstructExpr, class A)
+// WARNINGS: 4: A() (CXXConstructExpr, class A)
+// ANALYZER: 4: A() (CXXConstructExpr, [B5.5], [B5.6], class A)
// CHECK: 5: [B5.4] (BindTemporary)
-// CHECK: 6: [B5.5].operator bool
-// CHECK: 7: [B5.5]
-// CHECK: 8: [B5.7] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CHECK: T: [B5.8] && ...
+// CHECK: 6: [B5.5]
+// CHECK: 7: [B5.6].operator bool
+// CHECK: 8: [B5.6]
+// CHECK: 9: [B5.8] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CHECK: T: [B5.9] && ...
// CHECK: Preds (2): B6 B7
// CHECK: Succs (2): B4 B3
// CHECK: [B6]
@@ -354,26 +403,30 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: Preds (1): B7
// CHECK: Succs (1): B5
// CHECK: [B7]
-// CHECK: 1: [B9.5] && [B8.5]
+// CHECK: 1: [B9.6] && [B8.6]
// CHECK: 2: bool a = A() && B();
// CHECK: T: (Temp Dtor) [B8.2]
// CHECK: Preds (2): B8 B9
// CHECK: Succs (2): B6 B5
// CHECK: [B8]
-// CHECK: 1: B() (CXXConstructExpr, class B)
+// WARNINGS: 1: B() (CXXConstructExpr, class B)
+// ANALYZER: 1: B() (CXXConstructExpr, [B8.2], [B8.3], class B)
// CHECK: 2: [B8.1] (BindTemporary)
-// CHECK: 3: [B8.2].operator bool
-// CHECK: 4: [B8.2]
-// CHECK: 5: [B8.4] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CHECK: 3: [B8.2]
+// CHECK: 4: [B8.3].operator bool
+// CHECK: 5: [B8.3]
+// CHECK: 6: [B8.5] (ImplicitCastExpr, UserDefinedConversion, _Bool)
// CHECK: Preds (1): B9
// CHECK: Succs (1): B7
// CHECK: [B9]
-// CHECK: 1: A() (CXXConstructExpr, class A)
+// WARNINGS: 1: A() (CXXConstructExpr, class A)
+// ANALYZER: 1: A() (CXXConstructExpr, [B9.2], [B9.3], class A)
// CHECK: 2: [B9.1] (BindTemporary)
-// CHECK: 3: [B9.2].operator bool
-// CHECK: 4: [B9.2]
-// CHECK: 5: [B9.4] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CHECK: T: [B9.5] && ...
+// CHECK: 3: [B9.2]
+// CHECK: 4: [B9.3].operator bool
+// CHECK: 5: [B9.3]
+// CHECK: 6: [B9.5] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CHECK: T: [B9.6] && ...
// CHECK: Preds (1): B10
// CHECK: Succs (2): B8 B7
// CHECK: [B0 (EXIT)]
@@ -390,29 +443,33 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: Preds (1): B3
// CHECK: Succs (1): B1
// CHECK: [B3]
-// CHECK: 1: [B5.8] || [B4.5]
+// CHECK: 1: [B5.9] || [B4.6]
// CHECK: 2: [B5.3]([B3.1])
// CHECK: T: (Temp Dtor) [B4.2]
// CHECK: Preds (2): B4 B5
// CHECK: Succs (2): B2 B1
// CHECK: [B4]
-// CHECK: 1: B() (CXXConstructExpr, class B)
+// WARNINGS: 1: B() (CXXConstructExpr, class B)
+// ANALYZER: 1: B() (CXXConstructExpr, [B4.2], [B4.3], class B)
// CHECK: 2: [B4.1] (BindTemporary)
-// CHECK: 3: [B4.2].operator bool
-// CHECK: 4: [B4.2]
-// CHECK: 5: [B4.4] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CHECK: 3: [B4.2]
+// CHECK: 4: [B4.3].operator bool
+// CHECK: 5: [B4.3]
+// CHECK: 6: [B4.5] (ImplicitCastExpr, UserDefinedConversion, _Bool)
// CHECK: Preds (1): B5
// CHECK: Succs (1): B3
// CHECK: [B5]
// CHECK: 1: ~A() (Temporary object destructor)
// CHECK: 2: foo
// CHECK: 3: [B5.2] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(_Bool))
-// CHECK: 4: A() (CXXConstructExpr, class A)
+// WARNINGS: 4: A() (CXXConstructExpr, class A)
+// ANALYZER: 4: A() (CXXConstructExpr, [B5.5], [B5.6], class A)
// CHECK: 5: [B5.4] (BindTemporary)
-// CHECK: 6: [B5.5].operator bool
-// CHECK: 7: [B5.5]
-// CHECK: 8: [B5.7] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CHECK: T: [B5.8] || ...
+// CHECK: 6: [B5.5]
+// CHECK: 7: [B5.6].operator bool
+// CHECK: 8: [B5.6]
+// CHECK: 9: [B5.8] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CHECK: T: [B5.9] || ...
// CHECK: Preds (2): B6 B7
// CHECK: Succs (2): B3 B4
// CHECK: [B6]
@@ -420,26 +477,30 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: Preds (1): B7
// CHECK: Succs (1): B5
// CHECK: [B7]
-// CHECK: 1: [B9.5] || [B8.5]
+// CHECK: 1: [B9.6] || [B8.6]
// CHECK: 2: bool a = A() || B();
// CHECK: T: (Temp Dtor) [B8.2]
// CHECK: Preds (2): B8 B9
// CHECK: Succs (2): B6 B5
// CHECK: [B8]
-// CHECK: 1: B() (CXXConstructExpr, class B)
+// WARNINGS: 1: B() (CXXConstructExpr, class B)
+// ANALYZER: 1: B() (CXXConstructExpr, [B8.2], [B8.3], class B)
// CHECK: 2: [B8.1] (BindTemporary)
-// CHECK: 3: [B8.2].operator bool
-// CHECK: 4: [B8.2]
-// CHECK: 5: [B8.4] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CHECK: 3: [B8.2]
+// CHECK: 4: [B8.3].operator bool
+// CHECK: 5: [B8.3]
+// CHECK: 6: [B8.5] (ImplicitCastExpr, UserDefinedConversion, _Bool)
// CHECK: Preds (1): B9
// CHECK: Succs (1): B7
// CHECK: [B9]
-// CHECK: 1: A() (CXXConstructExpr, class A)
+// WARNINGS: 1: A() (CXXConstructExpr, class A)
+// ANALYZER: 1: A() (CXXConstructExpr, [B9.2], [B9.3], class A)
// CHECK: 2: [B9.1] (BindTemporary)
-// CHECK: 3: [B9.2].operator bool
-// CHECK: 4: [B9.2]
-// CHECK: 5: [B9.4] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CHECK: T: [B9.5] || ...
+// CHECK: 3: [B9.2]
+// CHECK: 4: [B9.3].operator bool
+// CHECK: 5: [B9.3]
+// CHECK: 6: [B9.5] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CHECK: T: [B9.6] || ...
// CHECK: Preds (1): B10
// CHECK: Succs (2): B7 B8
// CHECK: [B0 (EXIT)]
@@ -467,13 +528,15 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: Succs (1): B1
// CHECK: [B4]
// CHECK: 1: ~B() (Temporary object destructor)
-// CHECK: 2: B() (CXXConstructExpr, class B)
+// WARNINGS: 2: B() (CXXConstructExpr, class B)
+// ANALYZER: 2: B() (CXXConstructExpr, [B4.3], [B4.4], class B)
// CHECK: 3: [B4.2] (BindTemporary)
-// CHECK: 4: [B4.3].operator bool
-// CHECK: 5: [B4.3]
-// CHECK: 6: [B4.5] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CHECK: 7: ~B() (Temporary object destructor)
-// CHECK: T: if [B4.6]
+// CHECK: 4: [B4.3]
+// CHECK: 5: [B4.4].operator bool
+// CHECK: 6: [B4.4]
+// CHECK: 7: [B4.6] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CHECK: 8: ~B() (Temporary object destructor)
+// CHECK: T: if [B4.7]
// CHECK: Preds (2): B5 B6
// CHECK: Succs (2): B3 B2
// CHECK: [B5]
@@ -489,48 +552,57 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: Preds (1): B7
// CHECK: Succs (1): B4
// CHECK: [B7]
-// CHECK: 1: [B10.5] ? [B8.6] : [B9.15]
+// CHECK: 1: [B10.6] ? [B8.6] : [B9.16]
// CHECK: 2: [B7.1] (ImplicitCastExpr, NoOp, const class A)
// CHECK: 3: [B7.2]
-// CHECK: 4: [B7.3] (CXXConstructExpr, class A)
+// WARNINGS: 4: [B7.3] (CXXConstructExpr, class A)
+// ANALYZER: 4: [B7.3] (CXXConstructExpr, [B7.5], class A)
// CHECK: 5: A a = B() ? A() : A(B());
// CHECK: T: (Temp Dtor) [B9.2]
// CHECK: Preds (2): B8 B9
// CHECK: Succs (2): B6 B5
// CHECK: [B8]
-// CHECK: 1: A() (CXXConstructExpr, class A)
+// WARNINGS: 1: A() (CXXConstructExpr, class A)
+// ANALYZER: 1: A() (CXXConstructExpr, [B8.2], [B8.4], [B8.5], class A)
// CHECK: 2: [B8.1] (BindTemporary)
// CHECK: 3: [B8.2] (ImplicitCastExpr, NoOp, const class A)
// CHECK: 4: [B8.3]
-// CHECK: 5: [B8.4] (CXXConstructExpr, class A)
+// WARNINGS: 5: [B8.4] (CXXConstructExpr, class A)
+// ANALYZER: 5: [B8.4] (CXXConstructExpr, [B8.6], [B7.3], [B7.4], class A)
// CHECK: 6: [B8.5] (BindTemporary)
// CHECK: Preds (1): B10
// CHECK: Succs (1): B7
// CHECK: [B9]
-// CHECK: 1: B() (CXXConstructExpr, class B)
+// WARNINGS: 1: B() (CXXConstructExpr, class B)
+// ANALYZER: 1: B() (CXXConstructExpr, [B9.2], [B9.3], class B)
// CHECK: 2: [B9.1] (BindTemporary)
-// CHECK: 3: [B9.2].operator A
-// CHECK: 4: [B9.2]
-// CHECK: 5: [B9.4] (ImplicitCastExpr, UserDefinedConversion, class A)
-// CHECK: 6: [B9.5] (BindTemporary)
-// CHECK: 7: [B9.6] (ImplicitCastExpr, NoOp, const class A)
-// CHECK: 8: [B9.7]
-// CHECK: 9: [B9.8] (CXXConstructExpr, class A)
-// CHECK: 10: [B9.9] (BindTemporary)
-// CHECK: 11: A([B9.10]) (CXXFunctionalCastExpr, ConstructorConversion, class A)
-// CHECK: 12: [B9.11] (ImplicitCastExpr, NoOp, const class A)
-// CHECK: 13: [B9.12]
-// CHECK: 14: [B9.13] (CXXConstructExpr, class A)
-// CHECK: 15: [B9.14] (BindTemporary)
+// CHECK: 3: [B9.2]
+// CHECK: 4: [B9.3].operator A
+// CHECK: 5: [B9.3]
+// CHECK: 6: [B9.5] (ImplicitCastExpr, UserDefinedConversion, class A)
+// CHECK: 7: [B9.6] (BindTemporary)
+// CHECK: 8: [B9.7] (ImplicitCastExpr, NoOp, const class A)
+// CHECK: 9: [B9.8]
+// WARNINGS: 10: [B9.9] (CXXConstructExpr, class A)
+// ANALYZER: 10: [B9.9] (CXXConstructExpr, [B9.11], [B9.14], [B9.15], class A)
+// CHECK: 11: [B9.10] (BindTemporary)
+// CHECK: 12: A([B9.11]) (CXXFunctionalCastExpr, ConstructorConversion, class A)
+// CHECK: 13: [B9.12] (ImplicitCastExpr, NoOp, const class A)
+// CHECK: 14: [B9.13]
+// WARNINGS: 15: [B9.14] (CXXConstructExpr, class A)
+// ANALYZER: 15: [B9.14] (CXXConstructExpr, [B9.16], [B7.3], [B7.4], class A)
+// CHECK: 16: [B9.15] (BindTemporary)
// CHECK: Preds (1): B10
// CHECK: Succs (1): B7
// CHECK: [B10]
-// CHECK: 1: B() (CXXConstructExpr, class B)
+// WARNINGS: 1: B() (CXXConstructExpr, class B)
+// ANALYZER: 1: B() (CXXConstructExpr, [B10.2], [B10.3], class B)
// CHECK: 2: [B10.1] (BindTemporary)
-// CHECK: 3: [B10.2].operator bool
-// CHECK: 4: [B10.2]
-// CHECK: 5: [B10.4] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CHECK: T: [B10.5] ? ... : ...
+// CHECK: 3: [B10.2]
+// CHECK: 4: [B10.3].operator bool
+// CHECK: 5: [B10.3]
+// CHECK: 6: [B10.5] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CHECK: T: [B10.6] ? ... : ...
// CHECK: Preds (1): B11
// CHECK: Succs (2): B8 B9
// CHECK: [B0 (EXIT)]
@@ -592,13 +664,15 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: Preds (1): B3
// CHECK: Succs (1): B0
// CHECK: [B3]
-// CHECK: 1: C() (CXXConstructExpr, struct C)
+// WARNINGS: 1: C() (CXXConstructExpr, struct C)
+// ANALYZER: 1: C() (CXXConstructExpr, [B3.2], [B3.3], struct C)
// CHECK: 2: [B3.1] (BindTemporary)
-// CHECK: 3: [B3.2].operator bool
-// CHECK: 4: [B3.2]
-// CHECK: 5: [B3.4] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CHECK: 6: ~C() (Temporary object destructor)
-// CHECK: T: if [B3.5]
+// CHECK: 3: [B3.2]
+// CHECK: 4: [B3.3].operator bool
+// CHECK: 5: [B3.3]
+// CHECK: 6: [B3.5] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CHECK: 7: ~C() (Temporary object destructor)
+// CHECK: T: if [B3.6]
// CHECK: Preds (1): B4
// CHECK: Succs (2): B2 B1
// CHECK: [B0 (EXIT)]
@@ -621,11 +695,13 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: Preds (1): B4
// CHECK: Succs (1): B0
// CHECK: [B4]
-// CHECK: 1: C() (CXXConstructExpr, struct C)
+// WARNINGS: 1: C() (CXXConstructExpr, struct C)
+// ANALYZER: 1: C() (CXXConstructExpr, [B4.2], [B4.4], [B4.5], struct C)
// CHECK: 2: [B4.1] (BindTemporary)
// CHECK: 3: [B4.2] (ImplicitCastExpr, NoOp, const struct C)
// CHECK: 4: [B4.3]
-// CHECK: 5: [B4.4] (CXXConstructExpr, struct C)
+// WARNINGS: 5: [B4.4] (CXXConstructExpr, struct C)
+// ANALYZER: 5: [B4.4] (CXXConstructExpr, [B4.6], struct C)
// CHECK: 6: C c = C();
// CHECK: 7: ~C() (Temporary object destructor)
// CHECK: 8: c
@@ -650,11 +726,13 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: Preds (1): B3
// CHECK: Succs (1): B0
// CHECK: [B3]
-// CHECK: 1: D() (CXXConstructExpr, struct D)
-// CHECK: 2: [B3.1].operator bool
-// CHECK: 3: [B3.1]
-// CHECK: 4: [B3.3] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CHECK: T: if [B3.4]
+// WARNINGS: 1: D() (CXXConstructExpr, struct D)
+// ANALYZER: 1: D() (CXXConstructExpr, [B3.2], struct D)
+// CHECK: 2: [B3.1]
+// CHECK: 3: [B3.2].operator bool
+// CHECK: 4: [B3.2]
+// CHECK: 5: [B3.4] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CHECK: T: if [B3.5]
// CHECK: Preds (1): B4
// CHECK: Succs (2): B2 B1
// CHECK: [B0 (EXIT)]
@@ -672,18 +750,23 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: Preds (1): B3
// CHECK: Succs (1): B0
// CHECK: [B3]
-// CHECK: 1: D() (CXXConstructExpr, struct D)
+// CXX98-WARNINGS: 1: D() (CXXConstructExpr, struct D)
+// CXX98-ANALYZER: 1: D() (CXXConstructExpr, [B3.3], [B3.4], struct D)
// CXX98: 2: [B3.1] (ImplicitCastExpr, NoOp, const struct D)
// CXX98: 3: [B3.2]
-// CXX98: 4: [B3.3] (CXXConstructExpr, struct D)
+// CXX98-WARNINGS: 4: [B3.3] (CXXConstructExpr, struct D)
+// CXX98-ANALYZER: 4: [B3.3] (CXXConstructExpr, [B3.5], struct D)
// CXX98: 5: D d = D();
// CXX98: 6: d
// CXX98: 7: [B3.6].operator bool
// CXX98: 8: [B3.6]
// CXX98: 9: [B3.8] (ImplicitCastExpr, UserDefinedConversion, _Bool)
// CXX98: T: if [B3.9]
+// CXX11-WARNINGS: 1: D() (CXXConstructExpr, struct D)
+// CXX11-ANALYZER: 1: D() (CXXConstructExpr, [B3.2], [B3.3], struct D)
// CXX11: 2: [B3.1]
-// CXX11: 3: [B3.2] (CXXConstructExpr, struct D)
+// CXX11-WARNINGS: 3: [B3.2] (CXXConstructExpr, struct D)
+// CXX11-ANALYZER: 3: [B3.2] (CXXConstructExpr, [B3.4], struct D)
// CXX11: 4: D d = D();
// CXX11: 5: d
// CXX11: 6: [B3.5].operator bool
@@ -715,7 +798,7 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: Preds (1): B4
// CHECK: Succs (1): B1
// CHECK: [B4]
-// CHECK: 1: [B7.8] ? [B5.6] : [B6.15]
+// CHECK: 1: [B7.9] ? [B5.6] : [B6.16]
// CHECK: 2: [B4.1] (ImplicitCastExpr, NoOp, const class A)
// CHECK: 3: [B4.2]
// CHECK: 4: [B7.3]([B4.3])
@@ -723,42 +806,50 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: Preds (2): B5 B6
// CHECK: Succs (2): B3 B2
// CHECK: [B5]
-// CHECK: 1: A() (CXXConstructExpr, class A)
+// WARNINGS: 1: A() (CXXConstructExpr, class A)
+// ANALYZER: 1: A() (CXXConstructExpr, [B5.2], [B5.4], [B5.5], class A)
// CHECK: 2: [B5.1] (BindTemporary)
// CHECK: 3: [B5.2] (ImplicitCastExpr, NoOp, const class A)
// CHECK: 4: [B5.3]
-// CHECK: 5: [B5.4] (CXXConstructExpr, class A)
+// WARNINGS: 5: [B5.4] (CXXConstructExpr, class A)
+// ANALYZER: 5: [B5.4] (CXXConstructExpr, [B5.6], [B4.3], class A)
// CHECK: 6: [B5.5] (BindTemporary)
// CHECK: Preds (1): B7
// CHECK: Succs (1): B4
// CHECK: [B6]
-// CHECK: 1: B() (CXXConstructExpr, class B)
+// WARNINGS: 1: B() (CXXConstructExpr, class B)
+// ANALYZER: 1: B() (CXXConstructExpr, [B6.2], [B6.3], class B)
// CHECK: 2: [B6.1] (BindTemporary)
-// CHECK: 3: [B6.2].operator A
-// CHECK: 4: [B6.2]
-// CHECK: 5: [B6.4] (ImplicitCastExpr, UserDefinedConversion, class A)
-// CHECK: 6: [B6.5] (BindTemporary)
-// CHECK: 7: [B6.6] (ImplicitCastExpr, NoOp, const class A)
-// CHECK: 8: [B6.7]
-// CHECK: 9: [B6.8] (CXXConstructExpr, class A)
-// CHECK: 10: [B6.9] (BindTemporary)
-// CHECK: 11: A([B6.10]) (CXXFunctionalCastExpr, ConstructorConversion, class A)
-// CHECK: 12: [B6.11] (ImplicitCastExpr, NoOp, const class A)
-// CHECK: 13: [B6.12]
-// CHECK: 14: [B6.13] (CXXConstructExpr, class A)
-// CHECK: 15: [B6.14] (BindTemporary)
+// CHECK: 3: [B6.2]
+// CHECK: 4: [B6.3].operator A
+// CHECK: 5: [B6.3]
+// CHECK: 6: [B6.5] (ImplicitCastExpr, UserDefinedConversion, class A)
+// CHECK: 7: [B6.6] (BindTemporary)
+// CHECK: 8: [B6.7] (ImplicitCastExpr, NoOp, const class A)
+// CHECK: 9: [B6.8]
+// WARNINGS: 10: [B6.9] (CXXConstructExpr, class A)
+// ANALYZER: 10: [B6.9] (CXXConstructExpr, [B6.11], [B6.14], [B6.15], class A)
+// CHECK: 11: [B6.10] (BindTemporary)
+// CHECK: 12: A([B6.11]) (CXXFunctionalCastExpr, ConstructorConversion, class A)
+// CHECK: 13: [B6.12] (ImplicitCastExpr, NoOp, const class A)
+// CHECK: 14: [B6.13]
+// WARNINGS: 15: [B6.14] (CXXConstructExpr, class A)
+// ANALYZER: 15: [B6.14] (CXXConstructExpr, [B6.16], [B4.3], class A)
+// CHECK: 16: [B6.15] (BindTemporary)
// CHECK: Preds (1): B7
// CHECK: Succs (1): B4
// CHECK: [B7]
// CHECK: 1: ~B() (Temporary object destructor)
// CHECK: 2: foo
// CHECK: 3: [B7.2] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class A &))
-// CHECK: 4: B() (CXXConstructExpr, class B)
+// WARNINGS: 4: B() (CXXConstructExpr, class B)
+// ANALYZER: 4: B() (CXXConstructExpr, [B7.5], [B7.6], class B)
// CHECK: 5: [B7.4] (BindTemporary)
-// CHECK: 6: [B7.5].operator bool
-// CHECK: 7: [B7.5]
-// CHECK: 8: [B7.7] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CHECK: T: [B7.8] ? ... : ...
+// CHECK: 6: [B7.5]
+// CHECK: 7: [B7.6].operator bool
+// CHECK: 8: [B7.6]
+// CHECK: 9: [B7.8] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CHECK: T: [B7.9] ? ... : ...
// CHECK: Preds (2): B8 B9
// CHECK: Succs (2): B5 B6
// CHECK: [B8]
@@ -772,7 +863,7 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: Preds (1): B10
// CHECK: Succs (1): B7
// CHECK: [B10]
-// CHECK: 1: [B13.5] ? [B11.6] : [B12.15]
+// CHECK: 1: [B13.6] ? [B11.6] : [B12.16]
// CHECK: 2: [B10.1] (ImplicitCastExpr, NoOp, const class A)
// CHECK: 3: [B10.2]
// CHECK: 4: const A &a = B() ? A() : A(B());
@@ -780,39 +871,47 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: Preds (2): B11 B12
// CHECK: Succs (2): B9 B8
// CHECK: [B11]
-// CHECK: 1: A() (CXXConstructExpr, class A)
+// WARNINGS: 1: A() (CXXConstructExpr, class A)
+// ANALYZER: 1: A() (CXXConstructExpr, [B11.2], [B11.4], [B11.5], class A)
// CHECK: 2: [B11.1] (BindTemporary)
// CHECK: 3: [B11.2] (ImplicitCastExpr, NoOp, const class A)
// CHECK: 4: [B11.3]
-// CHECK: 5: [B11.4] (CXXConstructExpr, class A)
+// WARNINGS: 5: [B11.4] (CXXConstructExpr, class A)
+// ANALYZER: 5: [B11.4] (CXXConstructExpr, [B10.3], class A)
// CHECK: 6: [B11.5] (BindTemporary)
// CHECK: Preds (1): B13
// CHECK: Succs (1): B10
// CHECK: [B12]
-// CHECK: 1: B() (CXXConstructExpr, class B)
+// WARNINGS: 1: B() (CXXConstructExpr, class B)
+// ANALYZER: 1: B() (CXXConstructExpr, [B12.2], [B12.3], class B)
// CHECK: 2: [B12.1] (BindTemporary)
-// CHECK: 3: [B12.2].operator A
-// CHECK: 4: [B12.2]
-// CHECK: 5: [B12.4] (ImplicitCastExpr, UserDefinedConversion, class A)
-// CHECK: 6: [B12.5] (BindTemporary)
-// CHECK: 7: [B12.6] (ImplicitCastExpr, NoOp, const class A)
-// CHECK: 8: [B12.7]
-// CHECK: 9: [B12.8] (CXXConstructExpr, class A)
-// CHECK: 10: [B12.9] (BindTemporary)
-// CHECK: 11: A([B12.10]) (CXXFunctionalCastExpr, ConstructorConversion, class A)
-// CHECK: 12: [B12.11] (ImplicitCastExpr, NoOp, const class A)
-// CHECK: 13: [B12.12]
-// CHECK: 14: [B12.13] (CXXConstructExpr, class A)
-// CHECK: 15: [B12.14] (BindTemporary)
+// CHECK: 3: [B12.2]
+// CHECK: 4: [B12.3].operator A
+// CHECK: 5: [B12.3]
+// CHECK: 6: [B12.5] (ImplicitCastExpr, UserDefinedConversion, class A)
+// CHECK: 7: [B12.6] (BindTemporary)
+// CHECK: 8: [B12.7] (ImplicitCastExpr, NoOp, const class A)
+// CHECK: 9: [B12.8]
+// WARNINGS: 10: [B12.9] (CXXConstructExpr, class A)
+// ANALYZER: 10: [B12.9] (CXXConstructExpr, [B12.11], [B12.14], [B12.15], class A)
+// CHECK: 11: [B12.10] (BindTemporary)
+// CHECK: 12: A([B12.11]) (CXXFunctionalCastExpr, ConstructorConversion, class A)
+// CHECK: 13: [B12.12] (ImplicitCastExpr, NoOp, const class A)
+// CHECK: 14: [B12.13]
+// WARNINGS: 15: [B12.14] (CXXConstructExpr, class A)
+// ANALYZER: 15: [B12.14] (CXXConstructExpr, [B10.3], class A)
+// CHECK: 16: [B12.15] (BindTemporary)
// CHECK: Preds (1): B13
// CHECK: Succs (1): B10
// CHECK: [B13]
-// CHECK: 1: B() (CXXConstructExpr, class B)
+// WARNINGS: 1: B() (CXXConstructExpr, class B)
+// ANALYZER: 1: B() (CXXConstructExpr, [B13.2], [B13.3], class B)
// CHECK: 2: [B13.1] (BindTemporary)
-// CHECK: 3: [B13.2].operator bool
-// CHECK: 4: [B13.2]
-// CHECK: 5: [B13.4] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CHECK: T: [B13.5] ? ... : ...
+// CHECK: 3: [B13.2]
+// CHECK: 4: [B13.3].operator bool
+// CHECK: 5: [B13.3]
+// CHECK: 6: [B13.5] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CHECK: T: [B13.6] ? ... : ...
// CHECK: Preds (1): B14
// CHECK: Succs (2): B11 B12
// CHECK: [B0 (EXIT)]
@@ -838,7 +937,8 @@ int testConsistencyNestedNormalReturn(bool value) {
// CXX11: 1: [B7.3] ?: [B6.6]
// CHECK: 2: [B4.1] (ImplicitCastExpr, NoOp, const class A)
// CHECK: 3: [B4.2]
-// CHECK: 4: [B4.3] (CXXConstructExpr, class A)
+// WARNINGS: 4: [B4.3] (CXXConstructExpr, class A)
+// ANALYZER: 4: [B4.3] (CXXConstructExpr, [B4.5], class A)
// CHECK: 5: A a = A() ?: A();
// CHECK: T: (Temp Dtor) [B6.2]
// CHECK: Preds (2): B5 B6
@@ -846,34 +946,36 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: [B5]
// CXX98: 1: [B7.2] (ImplicitCastExpr, NoOp, const class A)
// CXX98: 2: [B5.1]
-// CXX98: 3: [B5.2] (CXXConstructExpr, class A)
+// WARNINGS-CXX98: 3: [B5.2] (CXXConstructExpr, class A)
+// ANALYZER-CXX98: 3: [B5.2] (CXXConstructExpr, [B5.4], class A)
// CXX98: 4: [B5.3] (BindTemporary)
// CXX11: 1: [B7.3] (ImplicitCastExpr, NoOp, const class A)
-// CXX11: 2: [B5.1] (CXXConstructExpr, class A)
+// WARNINGS-CXX11: 2: [B5.1] (CXXConstructExpr, class A)
+// ANALYZER-CXX11: 2: [B5.1] (CXXConstructExpr, [B5.3], class A)
// CXX11: 3: [B5.2] (BindTemporary)
// CHECK: Preds (1): B7
// CHECK: Succs (1): B4
// CHECK: [B6]
-// CHECK: 1: A() (CXXConstructExpr, class A)
+// WARNINGS: 1: A() (CXXConstructExpr, class A)
+// ANALYZER: 1: A() (CXXConstructExpr, [B6.2], [B6.4], [B6.5], class A)
// CHECK: 2: [B6.1] (BindTemporary)
// CHECK: 3: [B6.2] (ImplicitCastExpr, NoOp, const class A)
// CHECK: 4: [B6.3]
-// CHECK: 5: [B6.4] (CXXConstructExpr, class A)
+// WARNINGS: 5: [B6.4] (CXXConstructExpr, class A)
+// ANALYZER: 5: [B6.4] (CXXConstructExpr, [B6.6], class A)
// CHECK: 6: [B6.5] (BindTemporary)
// CHECK: Preds (1): B7
// CHECK: Succs (1): B4
// CHECK: [B7]
-// CHECK: 1: A() (CXXConstructExpr, class A)
+// WARNINGS: 1: A() (CXXConstructExpr, class A)
+// ANALYZER-CXX98: 1: A() (CXXConstructExpr, [B7.2], [B7.3], class A)
+// ANALYZER-CXX11: 1: A() (CXXConstructExpr, [B7.2], class A)
// CHECK: 2: [B7.1] (BindTemporary)
-// CXX98: 3: [B7.2].operator bool
-// CXX98: 4: [B7.2]
-// CXX98: 5: [B7.4] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CXX98: T: [B7.5] ? ... : ...
-// CXX11: 3: [B7.2]
-// CXX11: 4: [B7.3].operator bool
-// CXX11: 5: [B7.3]
-// CXX11: 6: [B7.5] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CXX11: T: [B7.6] ? ... : ...
+// CHECK: 3: [B7.2]
+// CHECK: 4: [B7.3].operator bool
+// CHECK: 5: [B7.3]
+// CHECK: 6: [B7.5] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CHECK: T: [B7.6] ? ... : ...
// CHECK: Preds (1): B8
// CHECK: Succs (2): B5 B6
// CHECK: [B0 (EXIT)]
@@ -906,36 +1008,38 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: [B5]
// CXX98: 1: [B7.4] (ImplicitCastExpr, NoOp, const class A)
// CXX98: 2: [B5.1]
-// CXX98: 3: [B5.2] (CXXConstructExpr, class A)
+// WARNINGS-CXX98: 3: [B5.2] (CXXConstructExpr, class A)
+// ANALYZER-CXX98: 3: [B5.2] (CXXConstructExpr, [B5.4], class A)
// CXX98: 4: [B5.3] (BindTemporary)
// CXX11: 1: [B7.5] (ImplicitCastExpr, NoOp, const class A)
-// CXX11: 2: [B5.1] (CXXConstructExpr, class A)
+// WARNINGS-CXX11: 2: [B5.1] (CXXConstructExpr, class A)
+// ANALYZER-CXX11: 2: [B5.1] (CXXConstructExpr, [B5.3], class A)
// CXX11: 3: [B5.2] (BindTemporary)
// CHECK: Preds (1): B7
// CHECK: Succs (1): B4
// CHECK: [B6]
-// CHECK: 1: A() (CXXConstructExpr, class A)
+// WARNINGS: 1: A() (CXXConstructExpr, class A)
+// ANALYZER: 1: A() (CXXConstructExpr, [B6.2], [B6.4], [B6.5], class A)
// CHECK: 2: [B6.1] (BindTemporary)
// CHECK: 3: [B6.2] (ImplicitCastExpr, NoOp, const class A)
// CHECK: 4: [B6.3]
-// CHECK: 5: [B6.4] (CXXConstructExpr, class A)
+// WARNINGS: 5: [B6.4] (CXXConstructExpr, class A)
+// ANALYZER: 5: [B6.4] (CXXConstructExpr, [B6.6], class A)
// CHECK: 6: [B6.5] (BindTemporary)
// CHECK: Preds (1): B7
// CHECK: Succs (1): B4
// CHECK: [B7]
// CHECK: 1: foo
// CHECK: 2: [B7.1] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class A &))
-// CHECK: 3: A() (CXXConstructExpr, class A)
+// WARNINGS: 3: A() (CXXConstructExpr, class A)
+// ANALYZER-CXX98: 3: A() (CXXConstructExpr, [B7.4], class A)
+// ANALYZER-CXX11: 3: A() (CXXConstructExpr, class A)
// CHECK: 4: [B7.3] (BindTemporary)
-// CXX98: 5: [B7.4].operator bool
-// CXX98: 6: [B7.4]
-// CXX98: 7: [B7.6] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CXX98: T: [B7.7] ? ... : ...
-// CXX11: 5: [B7.4]
-// CXX11: 6: [B7.5].operator bool
-// CXX11: 7: [B7.5]
-// CXX11: 8: [B7.7] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CXX11: T: [B7.8] ? ... : ...
+// CHECK: 5: [B7.4]
+// CHECK: 6: [B7.5].operator bool
+// CHECK: 7: [B7.5]
+// CHECK: 8: [B7.7] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CHECK: T: [B7.8] ? ... : ...
// CHECK: Preds (2): B8 B9
// CHECK: Succs (2): B5 B6
// CHECK: [B8]
@@ -954,34 +1058,36 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: [B10]
// CXX98: 1: [B12.2] (ImplicitCastExpr, NoOp, const class A)
// CXX98: 2: [B10.1]
-// CXX98: 3: [B10.2] (CXXConstructExpr, class A)
+// WARNINGS-CXX98: 3: [B10.2] (CXXConstructExpr, class A)
+// ANALYZER-CXX98: 3: [B10.2] (CXXConstructExpr, [B10.4], class A)
// CXX98: 4: [B10.3] (BindTemporary)
// CXX11: 1: [B12.3] (ImplicitCastExpr, NoOp, const class A)
-// CXX11: 2: [B10.1] (CXXConstructExpr, class A)
+// WARNINGS-CXX11: 2: [B10.1] (CXXConstructExpr, class A)
+// ANALYZER-CXX11: 2: [B10.1] (CXXConstructExpr, [B10.3], class A)
// CXX11: 3: [B10.2] (BindTemporary)
// CHECK: Preds (1): B12
// CHECK: Succs (1): B9
// CHECK: [B11]
-// CHECK: 1: A() (CXXConstructExpr, class A)
+// WARNINGS-CHECK: 1: A() (CXXConstructExpr, class A)
+// ANALYZER-CHECK: 1: A() (CXXConstructExpr, [B11.2], class A)
// CHECK: 2: [B11.1] (BindTemporary)
// CHECK: 3: [B11.2] (ImplicitCastExpr, NoOp, const class A)
// CHECK: 4: [B11.3]
-// CHECK: 5: [B11.4] (CXXConstructExpr, class A)
+// WARNINGS: 5: [B11.4] (CXXConstructExpr, class A)
+// ANALYZER: 5: [B11.4] (CXXConstructExpr, [B11.6], class A)
// CHECK: 6: [B11.5] (BindTemporary)
// CHECK: Preds (1): B12
// CHECK: Succs (1): B9
// CHECK: [B12]
-// CHECK: 1: A() (CXXConstructExpr, class A)
+// WARNINGS: 1: A() (CXXConstructExpr, class A)
+// ANALYZER-CXX98: 1: A() (CXXConstructExpr, [B12.2], [B12.3], class A)
+// ANALYZER-CXX11: 1: A() (CXXConstructExpr, [B12.2], class A)
// CHECK: 2: [B12.1] (BindTemporary)
-// CXX98: 3: [B12.2].operator bool
-// CXX98: 4: [B12.2]
-// CXX98: 5: [B12.4] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CXX98: T: [B12.5] ? ... : ...
-// CXX11: 3: [B12.2]
-// CXX11: 4: [B12.3].operator bool
-// CXX11: 5: [B12.3]
-// CXX11: 6: [B12.5] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CXX11: T: [B12.6] ? ... : ...
+// CHECK: 3: [B12.2]
+// CHECK: 4: [B12.3].operator bool
+// CHECK: 5: [B12.3]
+// CHECK: 6: [B12.5] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CHECK: T: [B12.6] ? ... : ...
// CHECK: Preds (1): B13
// CHECK: Succs (2): B10 B11
// CHECK: [B0 (EXIT)]
@@ -989,11 +1095,13 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: [B2 (ENTRY)]
// CHECK: Succs (1): B1
// CHECK: [B1]
-// CHECK: 1: A() (CXXConstructExpr, class A)
+// WARNINGS: 1: A() (CXXConstructExpr, class A)
+// ANALYZER: 1: A() (CXXConstructExpr, [B1.2], [B1.4], [B1.5], class A)
// CHECK: 2: [B1.1] (BindTemporary)
// CHECK: 3: [B1.2] (ImplicitCastExpr, NoOp, const class A)
// CHECK: 4: [B1.3]
-// CHECK: 5: [B1.4] (CXXConstructExpr, class A)
+// WARNINGS: 5: [B1.4] (CXXConstructExpr, class A)
+// ANALYZER: 5: [B1.4] (CXXConstructExpr, [B1.6], class A)
// CHECK: 6: A a = A();
// CHECK: 7: ~A() (Temporary object destructor)
// CHECK: 8: int b;
@@ -1005,14 +1113,16 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: [B2 (ENTRY)]
// CHECK: Succs (1): B1
// CHECK: [B1]
-// CHECK: 1: A() (CXXConstructExpr, class A)
+// WARNINGS: 1: A() (CXXConstructExpr, class A)
+// ANALYZER: 1: A() (CXXConstructExpr, [B1.4], class A)
// CHECK: 2: [B1.1] (BindTemporary)
// CHECK: 3: [B1.2] (ImplicitCastExpr, NoOp, const class A)
// CHECK: 4: [B1.3]
// CHECK: 5: const A &a = A();
// CHECK: 6: foo
// CHECK: 7: [B1.6] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class A &))
-// CHECK: 8: A() (CXXConstructExpr, class A)
+// WARNINGS: 8: A() (CXXConstructExpr, class A)
+// ANALYZER: 8: A() (CXXConstructExpr, [B1.9], [B1.11], class A)
// CHECK: 9: [B1.8] (BindTemporary)
// CHECK: 10: [B1.9] (ImplicitCastExpr, NoOp, const class A)
// CHECK: 11: [B1.10]
@@ -1029,11 +1139,13 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: [B1]
// CHECK: 1: A::make
// CHECK: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class A (*)(void))
-// CHECK: 3: [B1.2]()
+// WARNINGS: 3: [B1.2]()
+// ANALYZER: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.6], [B1.7])
// CHECK: 4: [B1.3] (BindTemporary)
// CHECK: 5: [B1.4] (ImplicitCastExpr, NoOp, const class A)
// CHECK: 6: [B1.5]
-// CHECK: 7: [B1.6] (CXXConstructExpr, class A)
+// WARNINGS: 7: [B1.6] (CXXConstructExpr, class A)
+// ANALYZER: 7: [B1.6] (CXXConstructExpr, [B1.8], class A)
// CHECK: 8: A a = A::make();
// CHECK: 9: ~A() (Temporary object destructor)
// CHECK: 10: int b;
@@ -1047,7 +1159,8 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: [B1]
// CHECK: 1: A::make
// CHECK: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class A (*)(void))
-// CHECK: 3: [B1.2]()
+// WARNINGS: 3: [B1.2]()
+// ANALYZER: 3: [B1.2]() (CXXRecordTypedCall, [B1.6])
// CHECK: 4: [B1.3] (BindTemporary)
// CHECK: 5: [B1.4] (ImplicitCastExpr, NoOp, const class A)
// CHECK: 6: [B1.5]
@@ -1056,7 +1169,8 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: 9: [B1.8] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class A &))
// CHECK: 10: A::make
// CHECK: 11: [B1.10] (ImplicitCastExpr, FunctionToPointerDecay, class A (*)(void))
-// CHECK: 12: [B1.11]()
+// WARNINGS: 12: [B1.11]()
+// ANALYZER: 12: [B1.11]() (CXXRecordTypedCall, [B1.13], [B1.15])
// CHECK: 13: [B1.12] (BindTemporary)
// CHECK: 14: [B1.13] (ImplicitCastExpr, NoOp, const class A)
// CHECK: 15: [B1.14]
@@ -1072,15 +1186,17 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: Succs (1): B1
// CHECK: [B1]
// CHECK: 1: int a;
-// CHECK: 2: A() (CXXConstructExpr, class A)
+// WARNINGS: 2: A() (CXXConstructExpr, class A)
+// ANALYZER: 2: A() (CXXConstructExpr, [B1.3], [B1.4], class A)
// CHECK: 3: [B1.2] (BindTemporary)
-// CHECK: 4: [B1.3].operator int
-// CHECK: 5: [B1.3]
-// CHECK: 6: [B1.5] (ImplicitCastExpr, UserDefinedConversion, int)
-// CHECK: 7: a
-// CHECK: 8: [B1.7] = [B1.6]
-// CHECK: 9: ~A() (Temporary object destructor)
-// CHECK: 10: int b;
+// CHECK: 4: [B1.3]
+// CHECK: 5: [B1.4].operator int
+// CHECK: 6: [B1.4]
+// CHECK: 7: [B1.6] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK: 8: a
+// CHECK: 9: [B1.8] = [B1.7]
+// CHECK: 10: ~A() (Temporary object destructor)
+// CHECK: 11: int b;
// CHECK: Preds (1): B2
// CHECK: Succs (1): B0
// CHECK: [B0 (EXIT)]
@@ -1088,24 +1204,28 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: [B2 (ENTRY)]
// CHECK: Succs (1): B1
// CHECK: [B1]
-// CHECK: 1: A() (CXXConstructExpr, class A)
+// WARNINGS: 1: A() (CXXConstructExpr, class A)
+// ANALYZER: 1: A() (CXXConstructExpr, [B1.2], [B1.3], class A)
// CHECK: 2: [B1.1] (BindTemporary)
-// CHECK: 3: [B1.2].operator int
-// CHECK: 4: [B1.2]
-// CHECK: 5: [B1.4] (ImplicitCastExpr, UserDefinedConversion, int)
-// CHECK: 6: int([B1.5]) (CXXFunctionalCastExpr, NoOp, int)
-// CHECK: 7: B() (CXXConstructExpr, class B)
-// CHECK: 8: [B1.7] (BindTemporary)
-// CHECK: 9: [B1.8].operator int
-// CHECK: 10: [B1.8]
-// CHECK: 11: [B1.10] (ImplicitCastExpr, UserDefinedConversion, int)
-// CHECK: 12: int([B1.11]) (CXXFunctionalCastExpr, NoOp, int)
-// CHECK: 13: [B1.6] + [B1.12]
-// CHECK: 14: a([B1.13]) (Member initializer)
-// CHECK: 15: ~B() (Temporary object destructor)
-// CHECK: 16: ~A() (Temporary object destructor)
-// CHECK: 17: /*implicit*/(int)0
-// CHECK: 18: b([B1.17]) (Member initializer)
+// CHECK: 3: [B1.2]
+// CHECK: 4: [B1.3].operator int
+// CHECK: 5: [B1.3]
+// CHECK: 6: [B1.5] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK: 7: int([B1.6]) (CXXFunctionalCastExpr, NoOp, int)
+// WARNINGS: 8: B() (CXXConstructExpr, class B)
+// ANALYZER: 8: B() (CXXConstructExpr, [B1.9], [B1.10], class B)
+// CHECK: 9: [B1.8] (BindTemporary)
+// CHECK: 10: [B1.9]
+// CHECK: 11: [B1.10].operator int
+// CHECK: 12: [B1.10]
+// CHECK: 13: [B1.12] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK: 14: int([B1.13]) (CXXFunctionalCastExpr, NoOp, int)
+// CHECK: 15: [B1.7] + [B1.14]
+// CHECK: 16: a([B1.15]) (Member initializer)
+// CHECK: 17: ~B() (Temporary object destructor)
+// CHECK: 18: ~A() (Temporary object destructor)
+// CHECK: 19: /*implicit*/(int)0
+// CHECK: 20: b([B1.19]) (Member initializer)
// CHECK: Preds (1): B2
// CHECK: Succs (1): B0
// CHECK: [B0 (EXIT)]
@@ -1118,7 +1238,9 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: Succs (1): B0
// CHECK: [B2 (NORETURN)]
// CHECK: 1: int a;
-// CHECK: 2: NoReturn() (CXXConstructExpr, class NoReturn)
+// WARNINGS: 2: NoReturn() (CXXConstructExpr, class NoReturn)
+// ANALYZER-CXX98: 2: NoReturn() (CXXConstructExpr, [B2.3], [B2.4], class NoReturn)
+// ANALYZER-CXX11: 2: NoReturn() (CXXConstructExpr, [B2.3], class NoReturn)
// CHECK: 3: [B2.2] (BindTemporary)
// CHECK: [[MEMBER:[45]]]: [B2.{{[34]}}].f
// CHECK: {{[56]}}: [B2.[[MEMBER]]]()
@@ -1135,7 +1257,8 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: Succs (1): B0
// CHECK: [B2 (NORETURN)]
// CHECK: 1: int a;
-// CHECK: 2: NoReturn() (CXXConstructExpr, class NoReturn)
+// WARNINGS: 2: NoReturn() (CXXConstructExpr, class NoReturn)
+// ANALYZER: 2: NoReturn() (CXXConstructExpr, [B2.3], class NoReturn)
// CHECK: 3: [B2.2] (BindTemporary)
// CHECK: 4: 47
// CHECK: 5: ... , [B2.4]
@@ -1172,7 +1295,8 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: [B6]
// CHECK: 1: check
// CHECK: 2: [B6.1] (ImplicitCastExpr, FunctionToPointerDecay, _Bool (*)(const class NoReturn &))
-// CHECK: 3: NoReturn() (CXXConstructExpr, class NoReturn)
+// WARNINGS: 3: NoReturn() (CXXConstructExpr, class NoReturn)
+// ANALYZER: 3: NoReturn() (CXXConstructExpr, [B6.4], [B6.6], class NoReturn)
// CHECK: 4: [B6.3] (BindTemporary)
// CHECK: 5: [B6.4] (ImplicitCastExpr, NoOp, const class NoReturn)
// CHECK: 6: [B6.5]
@@ -1222,7 +1346,8 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: [B6]
// CHECK: 1: check
// CHECK: 2: [B6.1] (ImplicitCastExpr, FunctionToPointerDecay, _Bool (*)(const class NoReturn &))
-// CHECK: 3: NoReturn() (CXXConstructExpr, class NoReturn)
+// WARNINGS: 3: NoReturn() (CXXConstructExpr, class NoReturn)
+// ANALYZER: 3: NoReturn() (CXXConstructExpr, [B6.4], [B6.6], class NoReturn)
// CHECK: 4: [B6.3] (BindTemporary)
// CHECK: 5: [B6.4] (ImplicitCastExpr, NoOp, const class NoReturn)
// CHECK: 6: [B6.5]
@@ -1279,7 +1404,8 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: [B6]
// CHECK: 1: check
// CHECK: 2: [B6.1] (ImplicitCastExpr, FunctionToPointerDecay, _Bool (*)(const class NoReturn &))
-// CHECK: 3: NoReturn() (CXXConstructExpr, class NoReturn)
+// WARNINGS: 3: NoReturn() (CXXConstructExpr, class NoReturn)
+// ANALYZER: 3: NoReturn() (CXXConstructExpr, [B6.4], [B6.6], class NoReturn)
// CHECK: 4: [B6.3] (BindTemporary)
// CHECK: 5: [B6.4] (ImplicitCastExpr, NoOp, const class NoReturn)
// CHECK: 6: [B6.5]
@@ -1307,3 +1433,29 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: Succs (2): B8 B1
// CHECK: [B0 (EXIT)]
// CHECK: Preds (3): B1 B2 B4
+// CHECK: [B1 (ENTRY)]
+// CHECK: Succs (1): B0
+// CHECK: [B0 (EXIT)]
+// CHECK: Preds (1): B1
+// CHECK: [B2 (ENTRY)]
+// CHECK: Succs (1): B1
+// CHECK: [B1]
+// CHECK: 1: foo1
+// CHECK: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, const class pass_references_through::C &(*)(void))
+// CHECK: 3: [B1.2]()
+// CHECK: 4: return [B1.3];
+// CHECK: Preds (1): B2
+// CHECK: Succs (1): B0
+// CHECK: [B0 (EXIT)]
+// CHECK: Preds (1): B1
+// CHECK: [B2 (ENTRY)]
+// CHECK: Succs (1): B1
+// CHECK: [B1]
+// CHECK: 1: foo2
+// CHECK: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class pass_references_through::C &&(*)(void))
+// CHECK: 3: [B1.2]()
+// CHECK: 4: return [B1.3];
+// CHECK: Preds (1): B2
+// CHECK: Succs (1): B0
+// CHECK: [B0 (EXIT)]
+// CHECK: Preds (1): B1
diff --git a/test/Analysis/temp-obj-dtors-option.cpp b/test/Analysis/temp-obj-dtors-option.cpp
new file mode 100644
index 000000000000..25cc86ebde43
--- /dev/null
+++ b/test/Analysis/temp-obj-dtors-option.cpp
@@ -0,0 +1,22 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config c++-temp-dtor-inlining=false -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config c++-temp-dtor-inlining=true -DINLINE -verify %s
+
+void clang_analyzer_eval(bool);
+
+struct S {
+ int &x;
+
+ S(int &x) : x(x) { ++x; }
+ ~S() { --x; }
+};
+
+void foo() {
+ int x = 0;
+ S(x).x += 1;
+ clang_analyzer_eval(x == 1);
+#ifdef INLINE
+ // expected-warning@-2{{TRUE}}
+#else
+ // expected-warning@-4{{UNKNOWN}}
+#endif
+}
diff --git a/test/Analysis/temporaries-callback-order.cpp b/test/Analysis/temporaries-callback-order.cpp
index df916cc4e767..120fabc10478 100644
--- a/test/Analysis/temporaries-callback-order.cpp
+++ b/test/Analysis/temporaries-callback-order.cpp
@@ -8,11 +8,7 @@ struct Sub : Super {
};
void testTemporaries() {
- // This triggers RegionChanges twice:
- // - Once for zero-initialization of the structure.
- // - Once for creating a temporary region and copying the structure there.
- // FIXME: This code shouldn't really produce the extra temporary, however
- // that's how we behave for now.
+ // This triggers RegionChanges once for zero-initialization of the structure.
Sub().m();
}
@@ -29,7 +25,6 @@ void seeIfCheckBindWorks() {
// testTemporaries():
// CHECK-NEXT: RegionChanges
-// CHECK-NEXT: RegionChanges
// Make sure there's no further output.
// CHECK-NOT: Bind
diff --git a/test/Analysis/temporaries.cpp b/test/Analysis/temporaries.cpp
index 99851dd68539..de3420e70891 100644
--- a/test/Analysis/temporaries.cpp
+++ b/test/Analysis/temporaries.cpp
@@ -1,9 +1,15 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify -w -std=c++03 %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify -w -std=c++11 %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -DTEMPORARY_DTORS -verify -w -analyzer-config cfg-temporary-dtors=true %s -std=c++11
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config cfg-temporary-dtors=false -verify -w -std=c++03 %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config cfg-temporary-dtors=false -verify -w -std=c++11 %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -DTEMPORARY_DTORS -verify -w -analyzer-config cfg-temporary-dtors=true,c++-temp-dtor-inlining=true %s -std=c++11
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -DTEMPORARY_DTORS -w -analyzer-config cfg-temporary-dtors=true,c++-temp-dtor-inlining=true %s -std=c++17
+
+// Note: The C++17 run-line doesn't -verify yet - it is a no-crash test.
extern bool clang_analyzer_eval(bool);
extern bool clang_analyzer_warnIfReached();
+void clang_analyzer_checkInlined(bool);
+
+#include "Inputs/system-header-simulator-cxx.h";
struct Trivial {
Trivial(int x) : value(x) {}
@@ -422,6 +428,10 @@ namespace destructors {
struct CtorWithNoReturnDtor {
CtorWithNoReturnDtor() = default;
+ CtorWithNoReturnDtor(int x) {
+ clang_analyzer_checkInlined(false); // no-warning
+ }
+
~CtorWithNoReturnDtor() __attribute__((noreturn));
};
@@ -434,11 +444,17 @@ namespace destructors {
const CtorWithNoReturnDtor &c = CtorWithNoReturnDtor();
// This represents an (expected) loss of coverage, since the destructor
- // of the lifetime-exended temporary is executed at at the end of
+ // of the lifetime-exended temporary is executed at the end of
// scope.
clang_analyzer_warnIfReached(); // no-warning
}
+#if __cplusplus >= 201103L
+ CtorWithNoReturnDtor returnNoReturnDtor() {
+ return {1}; // no-crash
+ }
+#endif
+
#endif // TEMPORARY_DTORS
}
@@ -530,3 +546,402 @@ void run() {
Sub(i).m();
}
}
+
+namespace test_return_temporary {
+class C {
+ int x, y;
+
+public:
+ C(int x, int y) : x(x), y(y) {}
+ int getX() const { return x; }
+ int getY() const { return y; }
+ ~C() {}
+};
+
+class D: public C {
+public:
+ D() : C(1, 2) {}
+ D(const D &d): C(d.getX(), d.getY()) {}
+};
+
+C returnTemporaryWithVariable() { C c(1, 2); return c; }
+C returnTemporaryWithAnotherFunctionWithVariable() {
+ return returnTemporaryWithVariable();
+}
+C returnTemporaryWithCopyConstructionWithVariable() {
+ return C(returnTemporaryWithVariable());
+}
+
+C returnTemporaryWithConstruction() { return C(1, 2); }
+C returnTemporaryWithAnotherFunctionWithConstruction() {
+ return returnTemporaryWithConstruction();
+}
+C returnTemporaryWithCopyConstructionWithConstruction() {
+ return C(returnTemporaryWithConstruction());
+}
+
+D returnTemporaryWithVariableAndNonTrivialCopy() { D d; return d; }
+D returnTemporaryWithAnotherFunctionWithVariableAndNonTrivialCopy() {
+ return returnTemporaryWithVariableAndNonTrivialCopy();
+}
+D returnTemporaryWithCopyConstructionWithVariableAndNonTrivialCopy() {
+ return D(returnTemporaryWithVariableAndNonTrivialCopy());
+}
+
+#if __cplusplus >= 201103L
+C returnTemporaryWithBraces() { return {1, 2}; }
+C returnTemporaryWithAnotherFunctionWithBraces() {
+ return returnTemporaryWithBraces();
+}
+C returnTemporaryWithCopyConstructionWithBraces() {
+ return C(returnTemporaryWithBraces());
+}
+#endif // C++11
+
+void test() {
+ C c1 = returnTemporaryWithVariable();
+ clang_analyzer_eval(c1.getX() == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(c1.getY() == 2); // expected-warning{{TRUE}}
+
+ C c2 = returnTemporaryWithAnotherFunctionWithVariable();
+ clang_analyzer_eval(c2.getX() == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(c2.getY() == 2); // expected-warning{{TRUE}}
+
+ C c3 = returnTemporaryWithCopyConstructionWithVariable();
+ clang_analyzer_eval(c3.getX() == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(c3.getY() == 2); // expected-warning{{TRUE}}
+
+ C c4 = returnTemporaryWithConstruction();
+ clang_analyzer_eval(c4.getX() == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(c4.getY() == 2); // expected-warning{{TRUE}}
+
+ C c5 = returnTemporaryWithAnotherFunctionWithConstruction();
+ clang_analyzer_eval(c5.getX() == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(c5.getY() == 2); // expected-warning{{TRUE}}
+
+ C c6 = returnTemporaryWithCopyConstructionWithConstruction();
+ clang_analyzer_eval(c5.getX() == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(c5.getY() == 2); // expected-warning{{TRUE}}
+
+#if __cplusplus >= 201103L
+
+ C c7 = returnTemporaryWithBraces();
+ clang_analyzer_eval(c7.getX() == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(c7.getY() == 2); // expected-warning{{TRUE}}
+
+ C c8 = returnTemporaryWithAnotherFunctionWithBraces();
+ clang_analyzer_eval(c8.getX() == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(c8.getY() == 2); // expected-warning{{TRUE}}
+
+ C c9 = returnTemporaryWithCopyConstructionWithBraces();
+ clang_analyzer_eval(c9.getX() == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(c9.getY() == 2); // expected-warning{{TRUE}}
+
+#endif // C++11
+
+ D d1 = returnTemporaryWithVariableAndNonTrivialCopy();
+ clang_analyzer_eval(d1.getX() == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(d1.getY() == 2); // expected-warning{{TRUE}}
+
+ D d2 = returnTemporaryWithAnotherFunctionWithVariableAndNonTrivialCopy();
+ clang_analyzer_eval(d2.getX() == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(d2.getY() == 2); // expected-warning{{TRUE}}
+
+ D d3 = returnTemporaryWithCopyConstructionWithVariableAndNonTrivialCopy();
+ clang_analyzer_eval(d3.getX() == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(d3.getY() == 2); // expected-warning{{TRUE}}
+}
+} // namespace test_return_temporary
+
+
+namespace test_temporary_object_expr_without_dtor {
+class C {
+ int x;
+public:
+ C(int x) : x(x) {}
+ int getX() const { return x; }
+};
+
+void test() {
+ clang_analyzer_eval(C(3).getX() == 3); // expected-warning{{TRUE}}
+};
+}
+
+namespace test_temporary_object_expr_with_dtor {
+class C {
+ int x;
+
+public:
+ C(int x) : x(x) {}
+ ~C() {}
+ int getX() const { return x; }
+};
+
+void test(int coin) {
+ clang_analyzer_eval(C(3).getX() == 3);
+#ifdef TEMPORARY_DTORS
+ // expected-warning@-2{{TRUE}}
+#else
+ // expected-warning@-4{{UNKNOWN}}
+#endif
+
+ const C &c1 = coin ? C(1) : C(2);
+ if (coin) {
+ clang_analyzer_eval(c1.getX() == 1);
+#ifdef TEMPORARY_DTORS
+ // expected-warning@-2{{TRUE}}
+#else
+ // expected-warning@-4{{UNKNOWN}}
+#endif
+ } else {
+ clang_analyzer_eval(c1.getX() == 2);
+#ifdef TEMPORARY_DTORS
+ // expected-warning@-2{{TRUE}}
+#else
+ // expected-warning@-4{{UNKNOWN}}
+#endif
+ }
+
+ C c2 = coin ? C(1) : C(2);
+ if (coin) {
+ clang_analyzer_eval(c2.getX() == 1); // expected-warning{{TRUE}}
+ } else {
+ clang_analyzer_eval(c2.getX() == 2); // expected-warning{{TRUE}}
+ }
+}
+
+} // namespace test_temporary_object_expr
+
+namespace test_match_constructors_and_destructors {
+class C {
+public:
+ int &x, &y;
+ C(int &_x, int &_y) : x(_x), y(_y) { ++x; }
+ C(const C &c): x(c.x), y(c.y) { ++x; }
+ ~C() { ++y; }
+};
+
+void test_simple_temporary() {
+ int x = 0, y = 0;
+ {
+ const C &c = C(x, y);
+ }
+ // One constructor and one destructor.
+ clang_analyzer_eval(x == 1);
+ clang_analyzer_eval(y == 1);
+#ifdef TEMPORARY_DTORS
+ // expected-warning@-3{{TRUE}}
+ // expected-warning@-3{{TRUE}}
+#else
+ // expected-warning@-6{{UNKNOWN}}
+ // expected-warning@-6{{UNKNOWN}}
+#endif
+}
+
+void test_simple_temporary_with_copy() {
+ int x = 0, y = 0;
+ {
+ C c = C(x, y);
+ }
+ // Only one constructor directly into the variable, and one destructor.
+ clang_analyzer_eval(x == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(y == 1); // expected-warning{{TRUE}}
+}
+
+void test_ternary_temporary(int coin) {
+ int x = 0, y = 0, z = 0, w = 0;
+ {
+ const C &c = coin ? C(x, y) : C(z, w);
+ }
+ // Only one constructor on every branch, and one automatic destructor.
+ if (coin) {
+ clang_analyzer_eval(x == 1);
+ clang_analyzer_eval(y == 1);
+#ifdef TEMPORARY_DTORS
+ // expected-warning@-3{{TRUE}}
+ // expected-warning@-3{{TRUE}}
+#else
+ // expected-warning@-6{{UNKNOWN}}
+ // expected-warning@-6{{UNKNOWN}}
+#endif
+ clang_analyzer_eval(z == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(w == 0); // expected-warning{{TRUE}}
+
+ } else {
+ clang_analyzer_eval(x == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(y == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(z == 1);
+ clang_analyzer_eval(w == 1);
+#ifdef TEMPORARY_DTORS
+ // expected-warning@-3{{TRUE}}
+ // expected-warning@-3{{TRUE}}
+#else
+ // expected-warning@-6{{UNKNOWN}}
+ // expected-warning@-6{{UNKNOWN}}
+#endif
+ }
+}
+
+void test_ternary_temporary_with_copy(int coin) {
+ int x = 0, y = 0, z = 0, w = 0;
+ {
+ C c = coin ? C(x, y) : C(z, w);
+ }
+ // On each branch the variable is constructed directly.
+ if (coin) {
+ clang_analyzer_eval(x == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(y == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(z == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(w == 0); // expected-warning{{TRUE}}
+
+ } else {
+ clang_analyzer_eval(x == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(y == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(z == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(w == 1); // expected-warning{{TRUE}}
+ }
+}
+} // namespace test_match_constructors_and_destructors
+
+namespace destructors_for_return_values {
+
+class C {
+public:
+ ~C() {
+ 1 / 0; // expected-warning{{Division by zero}}
+ }
+};
+
+C make();
+
+void testFloatingCall() {
+ make();
+ // Should have divided by zero in the destructor.
+ clang_analyzer_warnIfReached();
+#ifndef TEMPORARY_DTORS
+ // expected-warning@-2{{REACHABLE}}
+#endif
+}
+
+void testLifetimeExtendedCall() {
+ {
+ const C &c = make();
+ clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
+ }
+ // Should have divided by zero in the destructor.
+ clang_analyzer_warnIfReached(); // no-warning
+}
+
+void testCopiedCall() {
+ {
+ C c = make();
+ // Should have elided the constructor/destructor for the temporary
+ clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
+ }
+ // Should have divided by zero in the destructor.
+ clang_analyzer_warnIfReached(); // no-warning
+}
+} // namespace destructors_for_return_values
+
+namespace dont_forget_destructor_around_logical_op {
+int glob;
+
+class C {
+public:
+ ~C() {
+ glob = 1;
+ clang_analyzer_checkInlined(true);
+#ifdef TEMPORARY_DTORS
+ // expected-warning@-2{{TRUE}}
+#endif
+ }
+};
+
+C get();
+
+bool is(C);
+
+
+void test(int coin) {
+ // Here temporaries are being cleaned up after && is evaluated. There are two
+ // temporaries: the return value of get() and the elidable copy constructor
+ // of that return value into is(). According to the CFG, we need to cleanup
+ // both of them depending on whether the temporary corresponding to the
+ // return value of get() was initialized. However, we didn't track
+ // temporaries returned from functions, so we took the wrong branch.
+ coin && is(get()); // no-crash
+ if (coin) {
+ clang_analyzer_eval(glob);
+#ifdef TEMPORARY_DTORS
+ // expected-warning@-2{{TRUE}}
+#else
+ // expected-warning@-4{{UNKNOWN}}
+#endif
+ } else {
+ // The destructor is not called on this branch.
+ clang_analyzer_eval(glob); // expected-warning{{UNKNOWN}}
+ }
+}
+} // namespace dont_forget_destructor_around_logical_op
+
+#if __cplusplus >= 201103L
+namespace temporary_list_crash {
+class C {
+public:
+ C() {}
+ ~C() {}
+};
+
+void test() {
+ std::initializer_list<C>{C(), C()}; // no-crash
+}
+} // namespace temporary_list_crash
+#endif // C++11
+
+namespace implicit_constructor_conversion {
+struct S {
+ int x;
+ S(int x) : x(x) {}
+ ~S() {}
+};
+
+class C {
+ int x;
+
+public:
+ C(const S &s) : x(s.x) {}
+ ~C() {}
+ int getX() const { return x; }
+};
+
+void test() {
+ const C &c1 = S(10);
+ clang_analyzer_eval(c1.getX() == 10);
+#ifdef TEMPORARY_DTORS
+ // expected-warning@-2{{TRUE}}
+#else
+ // expected-warning@-4{{UNKNOWN}}
+#endif
+
+ S s = 20;
+ clang_analyzer_eval(s.x == 20); // expected-warning{{TRUE}}
+
+ C c2 = s;
+ clang_analyzer_eval(c2.getX() == 20); // expected-warning{{TRUE}}
+}
+} // end namespace implicit_constructor_conversion
+
+namespace pass_references_through {
+class C {
+public:
+ ~C() {}
+};
+
+const C &foo1();
+C &&foo2();
+
+// In these examples the foo() expression has record type, not reference type.
+// Don't try to figure out how to perform construction of the record here.
+const C &bar1() { return foo1(); } // no-crash
+C &&bar2() { return foo2(); } // no-crash
+} // end namespace pass_references_through
diff --git a/test/Analysis/this-pointer.cpp b/test/Analysis/this-pointer.cpp
new file mode 100644
index 000000000000..d160a942ef28
--- /dev/null
+++ b/test/Analysis/this-pointer.cpp
@@ -0,0 +1,88 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config widen-loops=true -analyzer-disable-retry-exhausted -verify %s
+
+void clang_analyzer_eval(bool);
+void clang_analyzer_dump(int);
+
+// 'this' pointer is not an lvalue, we should not invalidate it.
+namespace this_pointer_after_loop_widen {
+class A {
+public:
+ A() {
+ int count = 10;
+ do {
+ } while (count--);
+ }
+};
+
+void goo(A a);
+void test_temporary_object() {
+ goo(A()); // no-crash
+}
+
+struct B {
+ int mem;
+ B() : mem(0) {
+ for (int i = 0; i < 10; ++i) {
+ }
+ mem = 0;
+ }
+};
+
+void test_ctor() {
+ B b;
+ clang_analyzer_eval(b.mem == 0); // expected-warning{{TRUE}}
+}
+
+struct C {
+ int mem;
+ C() : mem(0) {}
+ void set() {
+ for (int i = 0; i < 10; ++i) {
+ }
+ mem = 10;
+ }
+};
+
+void test_method() {
+ C c;
+ clang_analyzer_eval(c.mem == 0); // expected-warning{{TRUE}}
+ c.set();
+ clang_analyzer_eval(c.mem == 10); // expected-warning{{TRUE}}
+}
+
+struct D {
+ int mem;
+ D() : mem(0) {}
+ void set() {
+ for (int i = 0; i < 10; ++i) {
+ }
+ mem = 10;
+ }
+};
+
+void test_new() {
+ D *d = new D;
+ clang_analyzer_eval(d->mem == 0); // expected-warning{{TRUE}}
+ d->set();
+ clang_analyzer_eval(d->mem == 10); // expected-warning{{TRUE}}
+}
+
+struct E {
+ int mem;
+ E() : mem(0) {}
+ void set() {
+ for (int i = 0; i < 10; ++i) {
+ }
+ setAux();
+ }
+ void setAux() {
+ this->mem = 10;
+ }
+};
+
+void test_chained_method_call() {
+ E e;
+ e.set();
+ clang_analyzer_eval(e.mem == 10); // expected-warning{{TRUE}}
+}
+} // namespace this_pointer_after_loop_widen
diff --git a/test/Analysis/trustnonnullchecker_test.m b/test/Analysis/trustnonnullchecker_test.m
new file mode 100644
index 000000000000..67b6bd27c918
--- /dev/null
+++ b/test/Analysis/trustnonnullchecker_test.m
@@ -0,0 +1,69 @@
+// RUN: %clang_analyze_cc1 -fblocks -analyze -analyzer-checker=core,nullability,apiModeling -verify %s
+
+#include "Inputs/system-header-simulator-for-nullability.h"
+
+NSString* _Nonnull trust_nonnull_framework_annotation() {
+ NSString* out = [NSString generateString];
+ if (out) {}
+ return out; // no-warning
+}
+
+NSString* _Nonnull trust_instancemsg_annotation(NSString* _Nonnull param) {
+ NSString* out = [param stringByAppendingString:@"string"];
+ if (out) {}
+ return out; // no-warning
+}
+
+NSString* _Nonnull distrust_instancemsg_noannotation(NSString* param) {
+ if (param) {}
+ NSString* out = [param stringByAppendingString:@"string"];
+ if (out) {}
+ return out; // expected-warning{{}}
+}
+
+NSString* _Nonnull trust_analyzer_knowledge(NSString* param) {
+ if (!param)
+ return @"";
+ NSString* out = [param stringByAppendingString:@"string"];
+ if (out) {}
+ return out; // no-warning
+}
+
+NSString* _Nonnull trust_assume_nonnull_macro() {
+ NSString* out = [NSString generateImplicitlyNonnullString];
+ if (out) {}
+ return out; // no-warning
+}
+
+NSString* _Nonnull distrust_without_annotation() {
+ NSString* out = [NSString generatePossiblyNullString];
+ if (out) {}
+ return out; // expected-warning{{}}
+}
+
+NSString* _Nonnull nonnull_please_trust_me();
+
+NSString* _Nonnull distrust_local_nonnull_annotation() {
+ NSString* out = nonnull_please_trust_me();
+ if (out) {}
+ return out; // expected-warning{{}}
+}
+
+NSString* _Nonnull trust_c_function() {
+ NSString* out = getString();
+ if (out) {};
+ return out; // no-warning
+}
+
+NSString* _Nonnull distrust_unannoted_function() {
+ NSString* out = getPossiblyNullString();
+ if (out) {};
+ return out; // expected-warning{{}}
+}
+
+NSString * _Nonnull distrustProtocol(id<MyProtocol> o) {
+ NSString* out = [o getString];
+ if (out) {};
+ return out; // expected-warning{{}}
+}
+
diff --git a/test/Analysis/trustnonnullchecker_test.mm b/test/Analysis/trustnonnullchecker_test.mm
new file mode 100644
index 000000000000..fa84673492be
--- /dev/null
+++ b/test/Analysis/trustnonnullchecker_test.mm
@@ -0,0 +1,9 @@
+// RUN: %clang_analyze_cc1 -fblocks -analyze -analyzer-checker=core,nullability,apiModeling -verify %s
+
+#include "Inputs/system-header-simulator-for-nullability-cxx.h"
+
+// expected-no-diagnostics
+
+void blah() {
+ foo(); // no-crash
+}
diff --git a/test/Analysis/undef-call.c b/test/Analysis/undef-call.c
new file mode 100644
index 000000000000..35c0b685ce7e
--- /dev/null
+++ b/test/Analysis/undef-call.c
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -fsyntax-only -analyze -analyzer-checker=debug.ExprInspection -analyzer-config experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%T/ctudir -verify %s
+// expected-no-diagnostics
+
+struct S {
+ void (*fp)();
+};
+
+int main() {
+ struct S s;
+ // This will cause the analyzer to look for a function definition that has
+ // no FunctionDecl. It used to cause a crash in AnyFunctionCall::getRuntimeDefinition.
+ // It would only occur when CTU analysis is enabled.
+ s.fp();
+}
diff --git a/test/Analysis/unified-sources/UnifiedSource-1.cpp b/test/Analysis/unified-sources/UnifiedSource-1.cpp
new file mode 100644
index 000000000000..02569f247ee0
--- /dev/null
+++ b/test/Analysis/unified-sources/UnifiedSource-1.cpp
@@ -0,0 +1,5 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s
+
+// There should still be diagnostics within included files.
+#include "source1.cpp"
+#include "source2.cpp"
diff --git a/test/Analysis/unified-sources/container.h b/test/Analysis/unified-sources/container.h
new file mode 100644
index 000000000000..d0bcd778899a
--- /dev/null
+++ b/test/Analysis/unified-sources/container.h
@@ -0,0 +1,10 @@
+class ContainerInHeaderFile {
+ class Iterator {
+ };
+
+public:
+ Iterator begin() const;
+ Iterator end() const;
+
+ int method() { return 0; }
+};
diff --git a/test/Analysis/unified-sources/source1.cpp b/test/Analysis/unified-sources/source1.cpp
new file mode 100644
index 000000000000..886afed8d417
--- /dev/null
+++ b/test/Analysis/unified-sources/source1.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s
+
+// This test tests that the warning is here when it is included from
+// the unified sources file. The run-line in this file is there
+// only to suppress LIT warning for the complete lack of run-line.
+int foo(int x) {
+ if (x) {}
+ return 1 / x; // expected-warning{{}}
+}
+
+// Let's see if the container inlining heuristic still works.
+#include "container.h"
+int testContainerMethodInHeaderFile(ContainerInHeaderFile Cont) {
+ return 1 / Cont.method(); // no-warning
+}
diff --git a/test/Analysis/unified-sources/source2.cpp b/test/Analysis/unified-sources/source2.cpp
new file mode 100644
index 000000000000..cd85e3522343
--- /dev/null
+++ b/test/Analysis/unified-sources/source2.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s
+
+// This test tests that the warning is here when it is included from
+// the unified sources file. The run-line in this file is there
+// only to suppress LIT warning for the complete lack of run-line.
+int testNullDereference() {
+ int *x = 0;
+ return *x; // expected-warning{{}}
+}
+
+// Let's see if the container inlining heuristic still works.
+class ContainerInCodeFile {
+ class Iterator {
+ };
+
+public:
+ Iterator begin() const;
+ Iterator end() const;
+
+ int method() { return 0; }
+};
+
+int testContainerMethodInCodeFile(ContainerInCodeFile Cont) {
+ return 1 / Cont.method(); // expected-warning{{}}
+}
diff --git a/test/Analysis/uninit-const.cpp b/test/Analysis/uninit-const.cpp
index 2ffc71bcbd66..f5166e6b27b2 100644
--- a/test/Analysis/uninit-const.cpp
+++ b/test/Analysis/uninit-const.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.NewDelete,core,alpha.core.CallAndMessageUnInitRefArg -analyzer-output=text -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.NewDelete,core,alpha.core.CallAndMessageUnInitRefArg -analyzer-output=text -DTEST_INLINABLE_ALLOCATORS -verify %s
// Passing uninitialized const data to unknown function
#include "Inputs/system-header-simulator-cxx.h"
diff --git a/test/Analysis/unions.cpp b/test/Analysis/unions.cpp
index 2758cdaa26b3..2d6d0ae4a0db 100644
--- a/test/Analysis/unions.cpp
+++ b/test/Analysis/unions.cpp
@@ -79,8 +79,7 @@ namespace PR17596 {
IntOrString vv;
vv.i = 5;
uu = vv;
- // FIXME: Should be true.
- clang_analyzer_eval(uu.i == 5); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(uu.i == 5); // expected-warning{{TRUE}}
}
void testInvalidation() {
@@ -106,3 +105,20 @@ namespace PR17596 {
clang_analyzer_eval(uu.s[0] == 'a'); // expected-warning{{UNKNOWN}}
}
}
+
+namespace assume_union_contents {
+union U {
+ int x;
+};
+
+U get();
+
+void test() {
+ U u = get();
+ int y = 0;
+ if (u.x)
+ y = 1;
+ if (u.x)
+ y = 1 / y; // no-warning
+}
+} // end namespace assume_union_contents
diff --git a/test/Analysis/unix-fns.c b/test/Analysis/unix-fns.c
index 9126e1bb39b4..44e7a2e643e3 100644
--- a/test/Analysis/unix-fns.c
+++ b/test/Analysis/unix-fns.c
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,unix.API,osx.API,optin.portability %s -analyzer-store=region -analyzer-output=plist -analyzer-eagerly-assume -analyzer-config faux-bodies=true -analyzer-config path-diagnostics-alternate=false -fblocks -verify -o %t.plist
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,unix.API,osx.API,optin.portability %s -analyzer-store=region -analyzer-output=plist -analyzer-eagerly-assume -analyzer-config faux-bodies=true -fblocks -verify -o %t.plist
// RUN: FileCheck --input-file=%t.plist %s
// RUN: mkdir -p %t.dir
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.API,osx.API,optin.portability -analyzer-output=html -analyzer-config faux-bodies=true -fblocks -o %t.dir %s
@@ -700,40 +700,6 @@ void test_inline_dispatch_once_reachable() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
// CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1786,6 +1752,40 @@ void test_inline_dispatch_once_reachable() {
// CHECK-NEXT: <string>&apos;p&apos; captured by block as a null pointer value</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>221</integer>
+// CHECK-NEXT: <key>col</key><integer>24</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>221</integer>
+// CHECK-NEXT: <key>col</key><integer>24</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>221</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>221</integer>
+// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -2153,6 +2153,40 @@ void test_inline_dispatch_once_reachable() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>232</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>232</integer>
+// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>232</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>232</integer>
+// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>232</integer>
// CHECK-NEXT: <key>col</key><integer>24</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -2195,6 +2229,40 @@ void test_inline_dispatch_once_reachable() {
// CHECK-NEXT: <string>&apos;p&apos; captured by block as a null pointer value</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>232</integer>
+// CHECK-NEXT: <key>col</key><integer>24</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>232</integer>
+// CHECK-NEXT: <key>col</key><integer>24</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>232</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>232</integer>
+// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -2492,6 +2560,40 @@ void test_inline_dispatch_once_reachable() {
// CHECK-NEXT: <key>path</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>239</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>239</integer>
+// CHECK-NEXT: <key>col</key><integer>8</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>241</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>241</integer>
+// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -2880,6 +2982,40 @@ void test_inline_dispatch_once_reachable() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>245</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>245</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>245</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>245</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>245</integer>
// CHECK-NEXT: <key>col</key><integer>6</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
diff --git a/test/Analysis/unreachable-code-path.c b/test/Analysis/unreachable-code-path.c
index effa4d9bfa6f..95cc4eab50db 100644
--- a/test/Analysis/unreachable-code-path.c
+++ b/test/Analysis/unreachable-code-path.c
@@ -63,6 +63,7 @@ void test6(const char *c) {
if (c) return;
if (!c) return;
__builtin_unreachable(); // no-warning
+ __builtin_assume(0); // no-warning
}
// Compile-time constant false positives
diff --git a/test/Analysis/virtualcall.cpp b/test/Analysis/virtualcall.cpp
index c22a8463c04a..1929abf6f0aa 100644
--- a/test/Analysis/virtualcall.cpp
+++ b/test/Analysis/virtualcall.cpp
@@ -262,6 +262,9 @@ int main() {
//expected-note-re@-2 {{{{^}}Calling default constructor for 'M'}}
#endif
Y *y = new Y;
+#if !PUREONLY
+ //expected-note-re@-2 {{{{^}}Calling default constructor for 'Y'}}
+#endif
delete y;
header::Z z;
#if !PUREONLY
diff --git a/test/Analysis/yaccignore.c b/test/Analysis/yaccignore.c
new file mode 100644
index 000000000000..c9edfadaf2f8
--- /dev/null
+++ b/test/Analysis/yaccignore.c
@@ -0,0 +1,13 @@
+/* A Bison parser, made by GNU Bison 1.875. */
+
+// RUN: rm -rf %t.plist
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist -o %t.plist -verify %s
+// RUN: FileCheck --input-file=%t.plist %s
+
+// expected-no-diagnostics
+int foo() {
+ int *x = 0;
+ return *x; // no-warning
+}
+
+// CHECK: <key>diagnostics</key>
diff --git a/test/Analysis/z3-crosscheck.c b/test/Analysis/z3-crosscheck.c
new file mode 100644
index 000000000000..67d410434fbb
--- /dev/null
+++ b/test/Analysis/z3-crosscheck.c
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection -DNO_CROSSCHECK -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config crosscheck-with-z3=true -verify %s
+// REQUIRES: z3
+
+int foo(int x)
+{
+ int *z = 0;
+ if ((x & 1) && ((x & 1) ^ 1))
+#ifdef NO_CROSSCHECK
+ return *z; // expected-warning {{Dereference of null pointer (loaded from variable 'z')}}
+#else
+ return *z; // no-warning
+#endif
+ return 0;
+}
+
+void g(int d);
+
+void f(int *a, int *b) {
+ int c = 5;
+ if ((a - b) == 0)
+ c = 0;
+ if (a != b)
+ g(3 / c); // no-warning
+}
+
+_Bool nondet_bool();
+
+void h(int d) {
+ int x, y, k, z = 1;
+ while (z < k) { // expected-warning {{The right operand of '<' is a garbage value}}
+ z = 2 * z;
+ }
+}
+
+void i() {
+ _Bool c = nondet_bool();
+ if (c) {
+ h(1);
+ } else {
+ h(2);
+ }
+}
diff --git a/test/Analysis/z3/apsint.c b/test/Analysis/z3/apsint.c
new file mode 100644
index 000000000000..670ef2be1c59
--- /dev/null
+++ b/test/Analysis/z3/apsint.c
@@ -0,0 +1,16 @@
+// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux-gnu -analyzer-checker=core -verify %s
+// expected-no-diagnostics
+
+// https://bugs.llvm.org/show_bug.cgi?id=37622
+_Bool a() {
+ return !({ a(); });
+}
+
+// https://bugs.llvm.org/show_bug.cgi?id=37646
+_Bool b;
+void c() {
+ _Bool a = b | 0;
+ for (;;)
+ if (a)
+ ;
+}
diff --git a/test/Analysis/z3/enabled.c b/test/Analysis/z3/enabled.c
new file mode 100644
index 000000000000..9f44233b266c
--- /dev/null
+++ b/test/Analysis/z3/enabled.c
@@ -0,0 +1,3 @@
+// REQUIRES: z3
+// RUN: echo %clang_analyze_cc1 | FileCheck %s
+// CHECK: -analyzer-constraints=z3
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 4b0e94b666b4..4951d8669806 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -23,7 +23,8 @@ llvm_canonicalize_cmake_booleans(
CLANG_ENABLE_ARCMT
CLANG_ENABLE_STATIC_ANALYZER
ENABLE_BACKTRACES
- HAVE_LIBZ)
+ HAVE_LIBZ
+ LLVM_ENABLE_PER_TARGET_RUNTIME_DIR)
configure_lit_site_cfg(
${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in
@@ -54,6 +55,7 @@ list(APPEND CLANG_TEST_DEPS
clang-rename
clang-refactor
clang-diff
+ hmaptool
)
if(CLANG_ENABLE_STATIC_ANALYZER)
@@ -93,9 +95,11 @@ if( NOT CLANG_BUILT_STANDALONE )
llvm-config
FileCheck count not
llc
+ llvm-as
llvm-bcanalyzer
llvm-cat
llvm-dis
+ llvm-lto2
llvm-modextract
llvm-nm
llvm-objdump
diff --git a/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp b/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp
index cf58a85d849c..73e0369e608e 100644
--- a/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp
+++ b/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp
@@ -199,5 +199,20 @@ namespace InhCtor {
using T::T; // expected-error {{type 'int' cannot be used prior to '::' because it has no members}}
};
UsingIntTemplate<int> uit; // expected-note {{here}}
+
+ // This case is odd: we don't name the constructor of a dependent base as
+ // Base::Base, but we still happen to have enough information to identify
+ // when parsing the template that we're inheriting constructors.
+ //
+ // FIXME: Once CWG 2070 is resolved, check whether this case should be
+ // accepted or not.
+ namespace DependentCtorName {
+ template <typename T> struct B { B(int); };
+ template <typename T> struct A : B<T> {
+ using X = B<T>;
+ using X::B;
+ };
+ A<int> ab = 0;
+ }
#endif
}
diff --git a/test/CXX/class/class.bit/p2.cpp b/test/CXX/class/class.bit/p2.cpp
index 7962330d1612..8b2436a869ba 100644
--- a/test/CXX/class/class.bit/p2.cpp
+++ b/test/CXX/class/class.bit/p2.cpp
@@ -9,7 +9,7 @@ A a = { };
A a2 = { 1 }; // expected-error{{excess elements in struct initializer}}
struct B {
- const int : 0;
+ const int : 0; // expected-error{{anonymous bit-field cannot have qualifiers}}
};
B b;
diff --git a/test/CXX/class/class.mem/p13.cpp b/test/CXX/class/class.mem/p13.cpp
index bc01fd4d30c5..1b1c0c7f8fc3 100644
--- a/test/CXX/class/class.mem/p13.cpp
+++ b/test/CXX/class/class.mem/p13.cpp
@@ -67,3 +67,50 @@ struct X4 { // expected-note{{previous}}
};
};
};
+
+// This includes such things inherited from base classes.
+struct B {
+ static int D0;
+ int Da() {};
+ enum D1 {};
+ struct D1a;
+ typedef int D2;
+ using D2a = int;
+ template<typename T> struct D2b;
+ template<typename T> void D2c();
+ template<typename T> static int D2d;
+ template<typename T> using D2e = int;
+ union { int D4; };
+ int Dtemplate;
+ int Dtemplate_with_ctors;
+};
+struct B2 { int Dtemplate(); };
+
+struct D0 : B { using B::D0; }; // expected-error {{member 'D0' has the same name as its class}}
+struct Da : B { using B::Da; }; // expected-error {{member 'Da' has the same name as its class}}
+struct D1 : B { using B::D1; }; // expected-error {{member 'D1' has the same name as its class}}
+struct D1a : B { using B::D1a; }; // expected-error {{member 'D1a' has the same name as its class}}
+struct D2 : B { using B::D2; }; // expected-error {{member 'D2' has the same name as its class}}
+struct D2a : B { using B::D2a; }; // expected-error {{member 'D2a' has the same name as its class}}
+struct D2b : B { using B::D2b; }; // expected-error {{member 'D2b' has the same name as its class}}
+struct D2c : B { using B::D2c; }; // expected-error {{member 'D2c' has the same name as its class}}
+struct D2d : B { using B::D2d; }; // expected-error {{member 'D2d' has the same name as its class}}
+struct D2e : B { using B::D2e; }; // expected-error {{member 'D2e' has the same name as its class}}
+struct D4 : B { using B::D4; }; // expected-error {{member 'D4' has the same name as its class}}
+
+template<typename B> struct Dtemplate : B {
+ using B::Dtemplate; // expected-error {{member 'Dtemplate' has the same name as its class}}
+};
+Dtemplate<B> ok;
+Dtemplate<B2> error; // expected-note {{in instantiation of}}
+
+template<typename B> struct Dtemplate_with_ctors : B {
+ Dtemplate_with_ctors();
+ using B::Dtemplate_with_ctors; // expected-error {{member 'Dtemplate_with_ctors' has the same name as its class}}
+};
+
+template<typename B> struct CtorDtorName : B {
+ using B::CtorDtorName; // expected-error {{member 'CtorDtorName' has the same name as its class}}
+ CtorDtorName();
+ ~CtorDtorName(); // expected-error {{expected the class name after '~' to name a destructor}}
+};
diff --git a/test/CXX/class/class.mem/p14.cpp b/test/CXX/class/class.mem/p14.cpp
index 3f14099ef896..a2f60618565d 100644
--- a/test/CXX/class/class.mem/p14.cpp
+++ b/test/CXX/class/class.mem/p14.cpp
@@ -9,9 +9,8 @@ struct X0 {
};
struct X1 {
- int X1; // expected-note{{hidden by a non-type declaration of 'X1' here}}
- X1(); // expected-error{{must use 'struct' tag to refer to type 'X1' in this scope}} \
- // expected-error{{expected member name or ';' after declaration specifiers}}
+ int X1; // expected-error{{member 'X1' has the same name as its class}}
+ X1();
};
struct X2 {
diff --git a/test/CXX/class/class.union/p1.cpp b/test/CXX/class/class.union/p1.cpp
index 84ce1c991533..bf7f2ad24f98 100644
--- a/test/CXX/class/class.union/p1.cpp
+++ b/test/CXX/class/class.union/p1.cpp
@@ -38,9 +38,9 @@ class Dtor {
union U1 {
Virtual v; // expected-error {{union member 'v' has a non-trivial copy constructor}}
VirtualBase vbase; // expected-error {{union member 'vbase' has a non-trivial copy constructor}}
- Ctor ctor; // expected-error {{union member 'ctor' has a non-trivial constructor}}
- Ctor2 ctor2; // expected-error {{union member 'ctor2' has a non-trivial constructor}}
- CtorTmpl ctortmpl; // expected-error {{union member 'ctortmpl' has a non-trivial constructor}}
+ Ctor ctor; // expected-error {{union member 'ctor' has a non-trivial default constructor}}
+ Ctor2 ctor2; // expected-error {{union member 'ctor2' has a non-trivial default constructor}}
+ CtorTmpl ctortmpl; // expected-error {{union member 'ctortmpl' has a non-trivial default constructor}}
CopyCtor copyctor; // expected-error {{union member 'copyctor' has a non-trivial copy constructor}}
CopyAssign copyassign; // expected-error {{union member 'copyassign' has a non-trivial copy assignment operator}}
Dtor dtor; // expected-error {{union member 'dtor' has a non-trivial destructor}}
@@ -56,10 +56,10 @@ union U2 {
} m2; // expected-error {{union member 'm2' has a non-trivial copy constructor}}
struct {
Ctor ctor; // expected-note {{because field of type 'Ctor' has a user-provided default constructor}}
- } m3; // expected-error {{union member 'm3' has a non-trivial constructor}}
+ } m3; // expected-error {{union member 'm3' has a non-trivial default constructor}}
struct {
Ctor2 ctor2; // expected-note {{because field of type 'Ctor2' has a user-provided default constructor}}
- } m3a; // expected-error {{union member 'm3a' has a non-trivial constructor}}
+ } m3a; // expected-error {{union member 'm3a' has a non-trivial default constructor}}
struct { // expected-note {{no constructor can be used to copy an object of type 'const}}
CopyCtor copyctor;
} m4; // expected-error {{union member 'm4' has a non-trivial copy constructor}}
@@ -80,9 +80,9 @@ union U3 {
struct s2 : VirtualBase { // expected-note {{because the function selected to copy base class of type 'VirtualBase' is not trivial}}
} m2; // expected-error {{union member 'm2' has a non-trivial copy constructor}}
struct s3 : Ctor { // expected-note {{because base class of type 'Ctor' has a user-provided default constructor}}
- } m3; // expected-error {{union member 'm3' has a non-trivial constructor}}
+ } m3; // expected-error {{union member 'm3' has a non-trivial default constructor}}
struct s3a : Ctor2 { // expected-note {{because base class of type 'Ctor2' has a user-provided default constructor}}
- } m3a; // expected-error {{union member 'm3a' has a non-trivial constructor}}
+ } m3a; // expected-error {{union member 'm3a' has a non-trivial default constructor}}
struct s4 : CopyCtor { // expected-note {{because no constructor can be used to copy an object of type 'const U3::s4'}}
} m4; // expected-error {{union member 'm4' has a non-trivial copy constructor}}
struct s5 : CopyAssign { // expected-note {{because no assignment operator can be used to copy an object of type 'const U3::s5'}}
@@ -93,7 +93,7 @@ union U3 {
} m7;
struct s8 {
s8(...) = delete; // expected-note {{because it is a variadic function}} expected-warning {{C++11}}
- } m8; // expected-error {{union member 'm8' has a non-trivial constructor}}
+ } m8; // expected-error {{union member 'm8' has a non-trivial default constructor}}
};
union U4 {
diff --git a/test/CXX/conv/conv.prom/p5.cpp b/test/CXX/conv/conv.prom/p5.cpp
new file mode 100644
index 000000000000..0c72ebce4aa9
--- /dev/null
+++ b/test/CXX/conv/conv.prom/p5.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -verify %s
+// expected-no-diagnostics
+
+// A prvalue for an integral bit-field can be converted to a prvalue of type
+// int if int can represent all the values of the bit-field
+struct X { long long e : 1; };
+static_assert(sizeof(+X().e) == sizeof(int), "");
+static_assert(sizeof(X().e + 1) == sizeof(int), "");
+static_assert(sizeof(true ? X().e : 0) == sizeof(int), "");
+
+enum E : long long { a = __LONG_LONG_MAX__ };
+static_assert(sizeof(E{}) == sizeof(long long), "");
+
+// If the bit-field has an enumerated type, it is treated as any other value of
+// that [enumerated] type for promotion purposes.
+struct Y { E e : 1; };
+static_assert(sizeof(+Y().e) == sizeof(long long), "");
+static_assert(sizeof(Y().e + 1) == sizeof(long long), "");
+static_assert(sizeof(true ? Y().e : 0) == sizeof(long long), "");
diff --git a/test/CXX/dcl.dcl/dcl.attr/dcl.align/p1.cpp b/test/CXX/dcl.dcl/dcl.attr/dcl.align/p1.cpp
new file mode 100644
index 000000000000..ec7b22f753f1
--- /dev/null
+++ b/test/CXX/dcl.dcl/dcl.attr/dcl.align/p1.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -std=c++11 -verify %s
+
+typedef int A alignas(4); // expected-error {{'alignas' attribute only applies to variables, data members and tag types}}
+template<int N> void f() {
+ typedef int B alignas(N); // expected-error {{'alignas' attribute only applies to variables, data members and tag types}}
+}
diff --git a/test/CXX/dcl.dcl/dcl.attr/dcl.attr.unused/p2.cpp b/test/CXX/dcl.dcl/dcl.attr/dcl.attr.unused/p2.cpp
index b539ca48ae34..db1886894d74 100644
--- a/test/CXX/dcl.dcl/dcl.attr/dcl.attr.unused/p2.cpp
+++ b/test/CXX/dcl.dcl/dcl.attr/dcl.attr.unused/p2.cpp
@@ -2,7 +2,7 @@
struct [[maybe_unused]] S {
int I [[maybe_unused]];
- static int SI [[maybe_unused]]; // expected-warning {{'maybe_unused' attribute only applies to variables, functions, methods, types, enumerations, enumerators, labels, and non-static data members}}
+ static int SI [[maybe_unused]];
};
enum [[maybe_unused]] E1 {
diff --git a/test/CXX/dcl.dcl/dcl.link/p7.cpp b/test/CXX/dcl.dcl/dcl.link/p7.cpp
index 7d80a22ca300..81cb28cef40f 100644
--- a/test/CXX/dcl.dcl/dcl.link/p7.cpp
+++ b/test/CXX/dcl.dcl/dcl.link/p7.cpp
@@ -2,10 +2,10 @@
struct X { };
-// CHECK: @x1 = global %struct.X zeroinitializer
-// CHECK: @x4 = global %struct.X zeroinitializer
-// CHECK: @x2 = external global %struct.X
-// CHECK: @x3 = external global %struct.X
+// CHECK: @x1 = {{(dso_local )?}}global %struct.X zeroinitializer
+// CHECK: @x4 = {{(dso_local )?}}global %struct.X zeroinitializer
+// CHECK: @x2 = external {{(dso_local )?}}global %struct.X
+// CHECK: @x3 = external {{(dso_local )?}}global %struct.X
extern "C" {
X x1;
}
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp
index 370f732fd92b..88ad6a4a3c4b 100644
--- a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp
@@ -35,7 +35,7 @@ template<typename R> struct ConstexprMember {
constexpr R F() const { return 0; }
};
constexpr int d = ConstexprMember<int>().F(); // ok
-constexpr int e = ConstexprMember<NonLiteral>().F(); // expected-error {{constant expression}} expected-note {{non-literal type 'const NonLiteral' cannot be used in a constant expression}}
+constexpr int e = ConstexprMember<NonLiteral>().F(); // expected-error {{constant expression}} expected-note {{non-literal type 'NonLiteral' cannot be used in a constant expression}}
template<typename ...P> struct ConstexprCtor {
constexpr ConstexprCtor(P...) {}
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
index cfb9a61f1ac4..96be58f8eb5f 100644
--- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
@@ -5,8 +5,7 @@ A() -> A<int>;
A(int) -> A<char>;
static constexpr inline const volatile A a = {}; // ok, specifiers are permitted
-// FIXME: There isn't really a good reason to reject this.
-A b; // expected-error {{requires an initializer}}
+A b;
A c [[]] {};
A d = {}, e = {};
@@ -16,3 +15,5 @@ struct B {
static A a; // expected-error {{requires an initializer}}
};
extern A x; // expected-error {{requires an initializer}}
+static A y;
+
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p4-cxx0x.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p4-cxx0x.cpp
index 53227ea37ce9..ee952aeaf0c9 100644
--- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p4-cxx0x.cpp
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p4-cxx0x.cpp
@@ -12,13 +12,18 @@ struct is_same<T, T> {
const int&& foo();
int i;
-struct A { double x; };
+struct A {
+ double x;
+ static int y;
+};
const A* a = new A();
static_assert(is_same<decltype(foo()), const int&&>::value, "");
static_assert(is_same<decltype(i), int>::value, "");
static_assert(is_same<decltype(a->x), double>::value, "");
static_assert(is_same<decltype((a->x)), const double&>::value, "");
+static_assert(is_same<decltype(a->y), int>::value, "");
+static_assert(is_same<decltype((a->y)), int&>::value, "");
static_assert(is_same<decltype(static_cast<int&&>(i)), int&&>::value, "");
int f0(int); // expected-note{{possible target}}
diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1.cpp
index f4f73a5af8ce..e9e9ce57fa7f 100644
--- a/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1.cpp
+++ b/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1.cpp
@@ -111,6 +111,11 @@ struct NonAggr6 { // expected-note 3 {{candidate constructor}}
};
NonAggr6 na6 = { 42 }; // expected-error {{no matching constructor for initialization of 'NonAggr6'}}
+struct NonAggr7 : NonAggr6 { // expected-note 3 {{candidate constructor}}
+ int n;
+};
+NonAggr7 na7 = {{}, 42}; // expected-error {{no matching constructor for initialization of 'NonAggr7'}}
+
struct DefaultedAggr {
int n;
diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp
index 48c5b23207c5..4436cb0aac60 100644
--- a/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp
+++ b/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp
@@ -24,6 +24,10 @@ void std_example() {
{ 2, f(2), f(2.0) }; // OK: the double-to-int conversion is not at the top level
}
+enum UnscopedEnum {
+ EnumVal = 300
+};
+
// Test each rule individually.
template<typename T>
@@ -115,15 +119,21 @@ void shrink_float() {
void int_to_float() {
// Not a constant expression.
char c = 1;
+ UnscopedEnum e = EnumVal;
// Variables. Yes, even though all char's will fit into any floating type.
Agg<float> f1 = {c}; // expected-error {{ cannot be narrowed }} expected-note {{silence}}
Agg<double> f2 = {c}; // expected-error {{ cannot be narrowed }} expected-note {{silence}}
Agg<long double> f3 = {c}; // expected-error {{ cannot be narrowed }} expected-note {{silence}}
+ Agg<float> f4 = {e}; // expected-error {{ cannot be narrowed }} expected-note {{silence}}
+ Agg<double> f5 = {e}; // expected-error {{ cannot be narrowed }} expected-note {{silence}}
+ Agg<long double> f6 = {e}; // expected-error {{ cannot be narrowed }} expected-note {{silence}}
+
// Constants.
- Agg<float> f4 = {12345678}; // OK (exactly fits in a float)
- Agg<float> f5 = {123456789}; // expected-error {{ cannot be narrowed }} expected-note {{silence}}
+ Agg<float> f7 = {12345678}; // OK (exactly fits in a float)
+ Agg<float> f8 = {EnumVal}; // OK
+ Agg<float> f9 = {123456789}; // expected-error {{ cannot be narrowed }} expected-note {{silence}}
Agg<float> ce1 = { Convert<int>(123456789) }; // expected-error {{constant expression evaluates to 123456789 which cannot be narrowed to type 'float'}} expected-note {{silence}}
Agg<double> ce2 = { ConvertVar<long long>() }; // expected-error {{non-constant-expression cannot be narrowed from type 'long long' to 'double'}} expected-note {{silence}}
@@ -137,8 +147,10 @@ void int_to_float() {
void shrink_int() {
// Not a constant expression.
short s = 1;
+ UnscopedEnum e = EnumVal;
unsigned short us = 1;
Agg<char> c1 = {s}; // expected-error {{ cannot be narrowed }} expected-note {{silence}}
+ Agg<char> c2 = {e}; // expected-error {{ cannot be narrowed }} expected-note {{silence}}
Agg<unsigned short> s1 = {s}; // expected-error {{ cannot be narrowed }} expected-note {{silence}}
Agg<short> s2 = {us}; // expected-error {{ cannot be narrowed }} expected-note {{silence}}
@@ -148,16 +160,19 @@ void shrink_int() {
// long).
long l1 = 1;
Agg<int> i1 = {l1}; // expected-error {{ cannot be narrowed }} expected-note {{silence}}
+ Agg<int> i2 = {e}; // OK
long long ll = 1;
Agg<long> l2 = {ll}; // OK
// Constants.
- Agg<char> c2 = {127}; // OK
- Agg<char> c3 = {300}; // expected-error {{ cannot be narrowed }} expected-note {{silence}} expected-warning {{changes value}}
-
- Agg<int> i2 = {0x7FFFFFFFU}; // OK
- Agg<int> i3 = {0x80000000U}; // expected-error {{ cannot be narrowed }} expected-note {{silence}}
- Agg<unsigned int> i4 = {-0x80000000L}; // expected-error {{ cannot be narrowed }} expected-note {{silence}}
+ Agg<char> c3 = {127}; // OK
+ Agg<char> c4 = {300}; // expected-error {{ cannot be narrowed }} expected-note {{silence}} expected-warning {{changes value}}
+ Agg<char> c5 = {EnumVal}; // expected-error {{ cannot be narrowed }} expected-note {{silence}} expected-warning {{changes value}}
+
+ Agg<int> i3 = {0x7FFFFFFFU}; // OK
+ Agg<int> i4 = {EnumVal}; // OK
+ Agg<int> i5 = {0x80000000U}; // expected-error {{ cannot be narrowed }} expected-note {{silence}}
+ Agg<unsigned int> i6 = {-0x80000000L}; // expected-error {{ cannot be narrowed }} expected-note {{silence}}
// Bool is also an integer type, but conversions to it are a different AST
// node.
diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp
index e775e8f0e3cc..869fc4f01493 100644
--- a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp
+++ b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp
@@ -61,3 +61,12 @@ namespace test3 {
unsigned &t9 = (a->bitY += 3); // expected-error {{non-const reference cannot bind to bit-field 'bitY'}}
}
}
+
+namespace explicit_ctor {
+ struct A {};
+ struct B { // expected-note 2{{candidate}}
+ explicit B(const A&);
+ };
+ A a;
+ const B &b(a); // expected-error {{no viable conversion}}
+}
diff --git a/test/CXX/dcl.decl/dcl.meaning/p1-0x.cpp b/test/CXX/dcl.decl/dcl.meaning/p1-0x.cpp
index 1d04d7d2a700..fbe9c0895aea 100644
--- a/test/CXX/dcl.decl/dcl.meaning/p1-0x.cpp
+++ b/test/CXX/dcl.decl/dcl.meaning/p1-0x.cpp
@@ -101,4 +101,25 @@ namespace inline_namespaces {
template<> struct N::V<int> {};
template struct N::V<int*>;
template struct N::V<char>; // expected-error {{undefined}}
+
+ struct Q {};
+
+ // Perversely, inline anonymous namespaces can cause an ostensibly
+ // external-linkage declaration to acquire internal linkage when
+ // redeclared with a qualified name.
+ inline namespace {
+ struct Q {} q;
+ int f_in_inline();
+ extern int v_in_inline;
+ typedef int t_in_inline;
+ }
+ // FIXME: These "extra qualification" warnings are bogus: the qualification
+ // changes the meaning of the program.
+ int inline_namespaces::f_in_inline() { // expected-warning {{extra qualification}}
+ // Finds <anon>::Q, not inline_namespaces::Q
+ Q x = q;
+ return 0;
+ }
+ int inline_namespaces::v_in_inline = // expected-warning {{extra qualification}}
+ (Q(q), 0);
}
diff --git a/test/CXX/drs/dr0xx.cpp b/test/CXX/drs/dr0xx.cpp
index fbca6635ec18..048187814db6 100644
--- a/test/CXX/drs/dr0xx.cpp
+++ b/test/CXX/drs/dr0xx.cpp
@@ -499,10 +499,10 @@ namespace dr42 { // dr42: yes
// dr43: na
-namespace dr44 { // dr44: yes
+namespace dr44 { // dr44: sup 727
struct A {
template<int> void f();
- template<> void f<0>(); // expected-error {{explicit specialization of 'f' in class scope}}
+ template<> void f<0>();
};
}
@@ -911,9 +911,8 @@ namespace dr80 { // dr80: yes
static int B; // expected-error {{same name as its class}}
};
struct C {
- int C; // expected-note {{hidden by}}
- // FIXME: These diagnostics aren't very good.
- C(); // expected-error {{must use 'struct' tag to refer to}} expected-error {{expected member name}}
+ int C; // expected-error {{same name as its class}}
+ C();
};
struct D {
D();
diff --git a/test/CXX/drs/dr10xx.cpp b/test/CXX/drs/dr10xx.cpp
index e1db9ef54adf..7f5fd8c7ec27 100644
--- a/test/CXX/drs/dr10xx.cpp
+++ b/test/CXX/drs/dr10xx.cpp
@@ -31,9 +31,8 @@ namespace dr1004 { // dr1004: 5
// This example (from the standard) is actually ill-formed, because
// name lookup of "T::template A" names the constructor.
- // FIXME: Only issue one diagnostic for this case.
- template<class T, template<class> class U = T::template A> struct Third { }; // expected-error 2{{is a constructor name}}
- Third<A<int> > t; // expected-note {{in instantiation of}} expected-note {{while substituting}} expected-note {{while checking}}
+ template<class T, template<class> class U = T::template A> struct Third { }; // expected-error {{is a constructor name}}
+ Third<A<int> > t; // expected-note {{in instantiation of default argument}}
}
namespace dr1048 { // dr1048: 3.6
diff --git a/test/CXX/drs/dr12xx.cpp b/test/CXX/drs/dr12xx.cpp
index 24039a1cd240..1bc4c3973443 100644
--- a/test/CXX/drs/dr12xx.cpp
+++ b/test/CXX/drs/dr12xx.cpp
@@ -3,7 +3,7 @@
// RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++1z %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
-namespace dr1213 { // dr1213: 4
+namespace dr1213 { // dr1213: 7
#if __cplusplus >= 201103L
using T = int[3];
int &&r = T{}[1];
@@ -11,6 +11,19 @@ namespace dr1213 { // dr1213: 4
using T = decltype((T{}));
using U = decltype((T{}[2]));
using U = int &&;
+
+ // Same thing but in a case where we consider overloaded operator[].
+ struct ConvertsToInt {
+ operator int();
+ };
+ struct X { int array[1]; };
+ using U = decltype(X().array[ConvertsToInt()]);
+
+ // We apply the same rule to vector subscripting.
+ typedef int V4Int __attribute__((__vector_size__(sizeof(int) * 4)));
+ typedef int EV4Int __attribute__((__ext_vector_type__(4)));
+ using U = decltype(V4Int()[0]);
+ using U = decltype(EV4Int()[0]);
#endif
}
diff --git a/test/CXX/drs/dr14xx.cpp b/test/CXX/drs/dr14xx.cpp
index 116437b1ab3c..eb5ba3db448e 100644
--- a/test/CXX/drs/dr14xx.cpp
+++ b/test/CXX/drs/dr14xx.cpp
@@ -7,6 +7,8 @@
// expected-no-diagnostics
#endif
+// dr1425: na abi
+
namespace dr1460 { // dr1460: 3.5
#if __cplusplus >= 201103L
namespace DRExample {
diff --git a/test/CXX/drs/dr15xx.cpp b/test/CXX/drs/dr15xx.cpp
index a68928f727ef..cca4509fa0c1 100644
--- a/test/CXX/drs/dr15xx.cpp
+++ b/test/CXX/drs/dr15xx.cpp
@@ -112,9 +112,9 @@ namespace dr1512 { // dr1512: 4
#endif
}
- template<typename T> struct Wrap { operator T(); };
- void test_overload() {
#if __cplusplus >= 201103L
+ template<typename T> struct Wrap { operator T(); }; // expected-note 4{{converted to type 'nullptr_t'}} expected-note 4{{converted to type 'int *'}}
+ void test_overload() {
using nullptr_t = decltype(nullptr);
void(Wrap<nullptr_t>() == Wrap<nullptr_t>());
void(Wrap<nullptr_t>() != Wrap<nullptr_t>());
@@ -123,16 +123,16 @@ namespace dr1512 { // dr1512: 4
void(Wrap<nullptr_t>() <= Wrap<nullptr_t>()); // expected-error {{invalid operands}}
void(Wrap<nullptr_t>() >= Wrap<nullptr_t>()); // expected-error {{invalid operands}}
- // The wording change fails to actually disallow this. This is valid
- // via the builtin operator<(int*, int*) etc.
+ // Under dr1213, this is ill-formed: we select the builtin operator<(int*, int*)
+ // but then only convert as far as 'nullptr_t', which we then can't convert to 'int*'.
void(Wrap<nullptr_t>() == Wrap<int*>());
void(Wrap<nullptr_t>() != Wrap<int*>());
- void(Wrap<nullptr_t>() < Wrap<int*>());
- void(Wrap<nullptr_t>() > Wrap<int*>());
- void(Wrap<nullptr_t>() <= Wrap<int*>());
- void(Wrap<nullptr_t>() >= Wrap<int*>());
-#endif
+ void(Wrap<nullptr_t>() < Wrap<int*>()); // expected-error {{invalid operands to binary expression ('Wrap<nullptr_t>' and 'Wrap<int *>')}}
+ void(Wrap<nullptr_t>() > Wrap<int*>()); // expected-error {{invalid operands}}
+ void(Wrap<nullptr_t>() <= Wrap<int*>()); // expected-error {{invalid operands}}
+ void(Wrap<nullptr_t>() >= Wrap<int*>()); // expected-error {{invalid operands}}
}
+#endif
}
namespace dr1518 { // dr1518: 4
@@ -357,6 +357,19 @@ auto DR1579_lambda_invalid = []() -> GenericMoveOnly<char> {
};
} // end namespace dr1579
+namespace dr1584 {
+ // Deducing function types from cv-qualified types
+ template<typename T> void f(const T *); // expected-note {{candidate template ignored}}
+ template<typename T> void g(T *, const T * = 0);
+ template<typename T> void h(T *) { T::error; } // expected-error {{no members}}
+ template<typename T> void h(const T *);
+ void i() {
+ f(&i); // expected-error {{no matching function}}
+ g(&i);
+ h(&i); // expected-note {{here}}
+ }
+}
+
namespace dr1589 { // dr1589: 3.7 c++11
// Ambiguous ranking of list-initialization sequences
diff --git a/test/CXX/drs/dr16xx.cpp b/test/CXX/drs/dr16xx.cpp
index 08ae92570cec..4f2f06e0d020 100644
--- a/test/CXX/drs/dr16xx.cpp
+++ b/test/CXX/drs/dr16xx.cpp
@@ -1,7 +1,27 @@
// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++1z -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++2a -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+
+#if __cplusplus < 201103L
+// expected-error@+1 {{variadic macro}}
+#define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
+#endif
+
+#if __cplusplus >= 201103L
+namespace std {
+ typedef decltype(sizeof(int)) size_t;
+
+ template<typename E> class initializer_list {
+ const E *begin;
+ size_t size;
+
+ public:
+ initializer_list();
+ };
+} // std
+#endif
namespace dr1611 { // dr1611: dup 1658
struct A { A(int); };
@@ -219,3 +239,129 @@ namespace dr1658 { // dr1658: 5
// assignment case is superseded by dr2180
}
+
+namespace dr1672 { // dr1672: 7
+ struct Empty {};
+ struct A : Empty {};
+ struct B { Empty e; };
+ struct C : A { B b; int n; };
+ struct D : A { int n; B b; };
+
+ static_assert(!__is_standard_layout(C), "");
+ static_assert(__is_standard_layout(D), "");
+
+ struct E { B b; int n; };
+ struct F { int n; B b; };
+ union G { B b; int n; };
+ union H { int n; B b; };
+
+ struct X {};
+ template<typename T> struct Y : X, A { T t; };
+
+ static_assert(!__is_standard_layout(Y<E>), "");
+ static_assert(__is_standard_layout(Y<F>), "");
+ static_assert(!__is_standard_layout(Y<G>), "");
+ static_assert(!__is_standard_layout(Y<H>), "");
+ static_assert(!__is_standard_layout(Y<X>), "");
+}
+
+namespace dr1687 { // dr1687: 7
+ template<typename T> struct To {
+ operator T(); // expected-note 2{{first operand was implicitly converted to type 'int *'}}
+ // expected-note@-1 {{second operand was implicitly converted to type 'double'}}
+#if __cplusplus > 201703L
+ // expected-note@-3 2{{operand was implicitly converted to type 'dr1687::E}}
+#endif
+ };
+
+ int *a = To<int*>() + 100.0; // expected-error {{invalid operands to binary expression ('To<int *>' and 'double')}}
+ int *b = To<int*>() + To<double>(); // expected-error {{invalid operands to binary expression ('To<int *>' and 'To<double>')}}
+
+#if __cplusplus > 201703L
+ enum E1 {};
+ enum E2 {};
+ auto c = To<E1>() <=> To<E2>(); // expected-error {{invalid operands to binary expression ('To<dr1687::E1>' and 'To<dr1687::E2>')}}
+#endif
+}
+
+namespace dr1696 { // dr1696: 7
+ namespace std_examples {
+#if __cplusplus >= 201402L
+ extern struct A a;
+ struct A {
+ const A &x = { A{a, a} };
+ const A &y = { A{} }; // expected-error {{default member initializer for 'y' needed within definition of enclosing class 'A' outside of member functions}} expected-note {{here}}
+ };
+ A a{a, a};
+#endif
+ }
+
+ struct A { A(); ~A(); };
+#if __cplusplus >= 201103L
+ struct B {
+ A &&a; // expected-note {{declared here}}
+ B() : a{} {} // expected-error {{reference member 'a' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}}
+ } b;
+#endif
+
+ struct C {
+ C();
+ const A &a; // expected-note {{declared here}}
+ };
+ C::C() : a(A()) {} // expected-error {{reference member 'a' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}}
+
+#if __cplusplus >= 201103L
+ // This is OK in C++14 onwards, per DR1815, though we don't support that yet:
+ // D1 d1 = {};
+ // is equivalent to
+ // D1 d1 = {A()};
+ // ... which lifetime-extends the A temporary.
+ struct D1 {
+#if __cplusplus < 201402L
+ // expected-error@-2 {{binds to a temporary}}
+#endif
+ const A &a = A(); // expected-note {{default member init}}
+ };
+ D1 d1 = {};
+#if __cplusplus < 201402L
+ // expected-note@-2 {{first required here}}
+#else
+ // expected-warning-re@-4 {{sorry, lifetime extension {{.*}} not supported}}
+#endif
+
+ struct D2 {
+ const A &a = A(); // expected-note {{default member init}}
+ D2() {} // expected-error {{binds to a temporary}}
+ };
+
+ struct D3 { // expected-error {{binds to a temporary}}
+ const A &a = A(); // expected-note {{default member init}}
+ };
+ D3 d3; // expected-note {{first required here}}
+
+ struct haslist1 {
+ std::initializer_list<int> il; // expected-note {{'std::initializer_list' member}}
+ haslist1(int i) : il{i, 2, 3} {} // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}}
+ };
+
+ struct haslist2 {
+ std::initializer_list<int> il; // expected-note {{'std::initializer_list' member}}
+ haslist2();
+ };
+ haslist2::haslist2() : il{1, 2} {} // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}}
+
+ struct haslist3 {
+ std::initializer_list<int> il = {1, 2, 3};
+ };
+
+ struct haslist4 { // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}}
+ std::initializer_list<int> il = {1, 2, 3}; // expected-note {{default member initializer}}
+ };
+ haslist4 hl4; // expected-note {{in implicit default constructor}}
+
+ struct haslist5 {
+ std::initializer_list<int> il = {1, 2, 3}; // expected-note {{default member initializer}}
+ haslist5() {} // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}}
+ };
+#endif
+}
diff --git a/test/CXX/drs/dr18xx.cpp b/test/CXX/drs/dr18xx.cpp
index e4ec199fcae8..16f967b65654 100644
--- a/test/CXX/drs/dr18xx.cpp
+++ b/test/CXX/drs/dr18xx.cpp
@@ -4,9 +4,55 @@
// RUN: %clang_cc1 -std=c++1z -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
#if __cplusplus < 201103L
-// expected-no-diagnostics
+// expected-error@+1 {{variadic macro}}
+#define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
#endif
+namespace dr1813 { // dr1813: 7
+ struct B { int i; };
+ struct C : B {};
+ struct D : C {};
+ struct E : D { char : 4; };
+
+ static_assert(__is_standard_layout(B), "");
+ static_assert(__is_standard_layout(C), "");
+ static_assert(__is_standard_layout(D), "");
+ static_assert(!__is_standard_layout(E), "");
+
+ struct Q {};
+ struct S : Q {};
+ struct T : Q {};
+ struct U : S, T {};
+
+ static_assert(__is_standard_layout(Q), "");
+ static_assert(__is_standard_layout(S), "");
+ static_assert(__is_standard_layout(T), "");
+ static_assert(!__is_standard_layout(U), "");
+}
+
+namespace dr1815 { // dr1815: no
+#if __cplusplus >= 201402L
+ // FIXME: needs codegen test
+ struct A { int &&r = 0; }; // expected-note {{default member init}}
+ A a = {}; // FIXME expected-warning {{not supported}}
+
+ struct B { int &&r = 0; }; // expected-error {{binds to a temporary}} expected-note {{default member init}}
+ B b; // expected-note {{here}}
+#endif
+}
+
+namespace dr1881 { // dr1881: 7
+ struct A { int a : 4; };
+ struct B : A { int b : 3; };
+ static_assert(__is_standard_layout(A), "");
+ static_assert(!__is_standard_layout(B), "");
+
+ struct C { int : 0; };
+ struct D : C { int : 0; };
+ static_assert(__is_standard_layout(C), "");
+ static_assert(!__is_standard_layout(D), "");
+}
+
void dr1891() { // dr1891: 4
#if __cplusplus >= 201103L
int n;
diff --git a/test/CXX/drs/dr1xx.cpp b/test/CXX/drs/dr1xx.cpp
index d62ed9f0d36d..a92501128b5f 100644
--- a/test/CXX/drs/dr1xx.cpp
+++ b/test/CXX/drs/dr1xx.cpp
@@ -67,8 +67,11 @@ namespace dr108 { // dr108: yes
namespace dr109 { // dr109: yes
struct A { template<typename T> void f(T); };
template<typename T> struct B : T {
- using T::template f; // expected-error {{using declaration cannot refer to a template}}
- void g() { this->f<int>(123); } // expected-error {{use 'template'}}
+ using T::template f; // expected-error {{'template' keyword not permitted here}}
+ using T::template f<int>; // expected-error {{'template' keyword not permitted here}} expected-error {{using declaration cannot refer to a template specialization}}
+ // FIXME: We shouldn't suggest using the 'template' keyword in a location where it's not valid.
+ using T::f<int>; // expected-error {{use 'template' keyword}} expected-error {{using declaration cannot refer to a template specialization}}
+ void g() { this->f<int>(123); } // expected-error {{use 'template' keyword}}
};
}
@@ -238,7 +241,20 @@ namespace dr125 {
};
}
-namespace dr126 { // dr126: no
+namespace dr126 { // dr126: partial
+ // FIXME: We do not yet generate correct code for this change:
+ // eg:
+ // catch (void*&) should catch void* but not int*
+ // catch (void*) and catch (void*const&) should catch both
+ // Likewise:
+ // catch (Base *&) should catch Base* but not Derived*
+ // catch (Base *) should catch both
+ // In each case, we emit the same code for both catches.
+ //
+ // The ABI does not let us represent the language rule in the unwind tables.
+ // So, when catching by non-const (or volatile) reference to pointer, we
+ // should compare the exception type to the caught type and only accept an
+ // exact match.
#if __cplusplus <= 201402L
struct C {};
struct D : C {};
@@ -262,12 +278,13 @@ namespace dr126 { // dr126: no
virtual void gr() throw(C&);
virtual void hr() throw(C&); // expected-note {{overridden}}
- virtual void pv() throw(void*); // expected-note {{overridden}}
+ virtual void pv() throw(void*);
#if __cplusplus >= 201103L
- virtual void np() throw(C*); // expected-note {{overridden}}
- virtual void npm() throw(int C::*); // expected-note {{overridden}}
- virtual void nr() throw(C&); // expected-note {{overridden}}
+ virtual void np() throw(C*);
+ virtual void npm() throw(int C::*);
+ virtual void nr() throw(C*&); // expected-note {{overridden}}
+ virtual void ncr() throw(C*const&);
#endif
virtual void ref1() throw(C *const&);
@@ -275,7 +292,7 @@ namespace dr126 { // dr126: no
virtual void v() throw(int);
virtual void w() throw(const int);
- virtual void x() throw(int*);
+ virtual void x() throw(int*); // expected-note {{overridden}}
virtual void y() throw(const int*);
virtual void z() throw(int); // expected-note {{overridden}}
};
@@ -294,13 +311,14 @@ namespace dr126 { // dr126: no
virtual void gr() throw(G&);
virtual void hr() throw(H&); // expected-error {{more lax}}
- virtual void pv() throw(C*); // expected-error {{more lax}} FIXME: This is valid.
+ virtual void pv() throw(C*);
#if __cplusplus >= 201103L
using nullptr_t = decltype(nullptr);
- virtual void np() throw(nullptr_t*); // expected-error {{more lax}} FIXME: This is valid.
- virtual void npm() throw(nullptr_t*); // expected-error {{more lax}} FIXME: This is valid.
- virtual void nr() throw(nullptr_t&); // expected-error {{more lax}} This is not.
+ virtual void np() throw(nullptr_t);
+ virtual void npm() throw(nullptr_t&);
+ virtual void nr() throw(nullptr_t); // expected-error {{more lax}}
+ virtual void ncr() throw(nullptr_t);
#endif
virtual void ref1() throw(D *const &);
@@ -308,7 +326,7 @@ namespace dr126 { // dr126: no
virtual void v() throw(const int);
virtual void w() throw(int);
- virtual void x() throw(const int*); // FIXME: 'const int*' is not allowed by A::h.
+ virtual void x() throw(const int*); // expected-error {{more lax}}
virtual void y() throw(int*); // ok
virtual void z() throw(long); // expected-error {{more lax}}
};
diff --git a/test/CXX/drs/dr21xx.cpp b/test/CXX/drs/dr21xx.cpp
index 78fc0bec40bf..2522ff7dbdef 100644
--- a/test/CXX/drs/dr21xx.cpp
+++ b/test/CXX/drs/dr21xx.cpp
@@ -3,6 +3,22 @@
// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++1z -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+#if __cplusplus < 201103L
+// expected-error@+1 {{variadic macro}}
+#define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
+#endif
+
+namespace dr2120 { // dr2120: 7
+ struct A {};
+ struct B : A {};
+ struct C { A a; };
+ struct D { C c[5]; };
+ struct E : B { D d; };
+ static_assert(__is_standard_layout(B), "");
+ static_assert(__is_standard_layout(D), "");
+ static_assert(!__is_standard_layout(E), "");
+}
+
namespace dr2180 { // dr2180: yes
class A {
A &operator=(const A &); // expected-note 0-2{{here}}
diff --git a/test/CXX/drs/dr22xx.cpp b/test/CXX/drs/dr22xx.cpp
new file mode 100644
index 000000000000..021707d876b7
--- /dev/null
+++ b/test/CXX/drs/dr22xx.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++1z -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+
+namespace dr2229 { // dr2229: 7
+struct AnonBitfieldQualifiers {
+ const unsigned : 1; // expected-error {{anonymous bit-field cannot have qualifiers}}
+ volatile unsigned : 1; // expected-error {{anonymous bit-field cannot have qualifiers}}
+ const volatile unsigned : 1; // expected-error {{anonymous bit-field cannot have qualifiers}}
+
+ unsigned : 1;
+ const unsigned i1 : 1;
+ volatile unsigned i2 : 1;
+ const volatile unsigned i3 : 1;
+};
+}
diff --git a/test/CXX/drs/dr3xx.cpp b/test/CXX/drs/dr3xx.cpp
index 3342148461ad..d723c5b78cdf 100644
--- a/test/CXX/drs/dr3xx.cpp
+++ b/test/CXX/drs/dr3xx.cpp
@@ -123,8 +123,7 @@ namespace dr305 { // dr305: no
template<typename T> using T2 = T;
};
void k(Z *z) {
- // FIXME: This diagnostic is terrible.
- z->~T1<int>(); // expected-error {{'T1' following the 'template' keyword does not refer to a template}} expected-error +{{}}
+ z->~T1<int>(); // expected-error {{no member named 'T1' in 'dr305::Z'}} expected-error +{{}}
z->~T2<int>(); // expected-error {{no member named '~int'}}
z->~T2<Z>();
}
@@ -355,6 +354,79 @@ namespace dr329 { // dr329: 3.5
}
}
+namespace dr330 { // dr330: 7
+ // Conversions between P and Q will be allowed by P0388.
+ typedef int *(*P)[3];
+ typedef const int *const (*Q)[3];
+ typedef const int *Qinner[3];
+ typedef Qinner const *Q2; // same as Q, but 'const' written outside the array type
+ typedef const int *const (*R)[4];
+ typedef const int *const (*S)[];
+ typedef const int *(*T)[];
+ void f(P p, Q q, Q2 q2, R r, S s, T t) {
+ q = p; // ok
+ q2 = p; // ok
+ r = p; // expected-error {{incompatible}}
+ s = p; // expected-error {{incompatible}} (for now)
+ t = p; // expected-error {{incompatible}}
+ s = q; // expected-error {{incompatible}}
+ s = q2; // expected-error {{incompatible}}
+ s = t; // ok, adding const
+ t = s; // expected-error {{incompatible}}
+ (void) const_cast<P>(q);
+ (void) const_cast<P>(q2);
+ (void) const_cast<Q>(p);
+ (void) const_cast<Q2>(p);
+ (void) const_cast<S>(p); // expected-error {{not allowed}} (for now)
+ (void) const_cast<P>(s); // expected-error {{not allowed}} (for now)
+ (void) const_cast<S>(q); // expected-error {{not allowed}}
+ (void) const_cast<S>(q2); // expected-error {{not allowed}}
+ (void) const_cast<Q>(s); // expected-error {{not allowed}}
+ (void) const_cast<Q2>(s); // expected-error {{not allowed}}
+ (void) const_cast<T>(s);
+ (void) const_cast<S>(t);
+ (void) const_cast<T>(q); // expected-error {{not allowed}}
+ (void) const_cast<Q>(t); // expected-error {{not allowed}}
+
+ (void) reinterpret_cast<P>(q); // expected-error {{casts away qualifiers}}
+ (void) reinterpret_cast<P>(q2); // expected-error {{casts away qualifiers}}
+ (void) reinterpret_cast<Q>(p);
+ (void) reinterpret_cast<Q2>(p);
+ (void) reinterpret_cast<S>(p);
+ (void) reinterpret_cast<P>(s); // expected-error {{casts away qualifiers}}
+ (void) reinterpret_cast<S>(q);
+ (void) reinterpret_cast<S>(q2);
+ (void) reinterpret_cast<Q>(s);
+ (void) reinterpret_cast<Q2>(s);
+ (void) reinterpret_cast<T>(s); // expected-error {{casts away qualifiers}}
+ (void) reinterpret_cast<S>(t);
+ (void) reinterpret_cast<T>(q); // expected-error {{casts away qualifiers}}
+ (void) reinterpret_cast<Q>(t);
+ }
+
+ namespace swift_17882 {
+ typedef const char P[72];
+ typedef int *Q;
+ void f(P &pr, P *pp) {
+ (void) reinterpret_cast<const Q&>(pr);
+ (void) reinterpret_cast<const Q*>(pp);
+ }
+
+ struct X {};
+ typedef const volatile int A[1][2][3];
+ typedef int *const X::*volatile *B1;
+ typedef int *const X::* *B2;
+ typedef int *X::* volatile *B3;
+ typedef volatile int *(*const B4)[4];
+ void f(A *a) {
+ (void) reinterpret_cast<B1*>(a);
+ (void) reinterpret_cast<B2*>(a); // expected-error {{casts away qualifiers}}
+ (void) reinterpret_cast<B3*>(a); // expected-error {{casts away qualifiers}}
+ (void) reinterpret_cast<B4*>(a);
+ }
+ }
+}
+
namespace dr331 { // dr331: yes
struct A {
A(volatile A&); // expected-note {{candidate}}
@@ -906,6 +978,25 @@ namespace dr372 { // dr372: no
};
};
}
+
+ // FIXME: This is valid: deriving from A gives D access to A::B
+ namespace std_example {
+ class A {
+ protected:
+ struct B {}; // expected-note {{here}}
+ };
+ struct D : A::B, A {}; // expected-error {{protected}}
+ }
+
+ // FIXME: This is valid: deriving from A::B gives access to A::B!
+ namespace badwolf {
+ class A {
+ protected:
+ struct B; // expected-note {{here}}
+ };
+ struct A::B : A {};
+ struct C : A::B {}; // expected-error {{protected}}
+ }
}
namespace dr373 { // dr373: 5
@@ -925,7 +1016,7 @@ namespace dr373 { // dr373: 5
using namespace A::B; // expected-error {{expected namespace name}}
}
-namespace dr374 { // dr374: yes c++11
+namespace dr374 { // dr374: yes
namespace N {
template<typename T> void f();
template<typename T> struct A { void f(); };
@@ -933,11 +1024,6 @@ namespace dr374 { // dr374: yes c++11
template<> void N::f<char>() {}
template<> void N::A<char>::f() {}
template<> struct N::A<int> {};
-#if __cplusplus < 201103L
- // expected-error@-4 {{extension}} expected-note@-7 {{here}}
- // expected-error@-4 {{extension}} expected-note@-7 {{here}}
- // expected-error@-4 {{extension}} expected-note@-8 {{here}}
-#endif
}
// dr375: dup 345
diff --git a/test/CXX/drs/dr4xx.cpp b/test/CXX/drs/dr4xx.cpp
index d27adc428d51..00393cc2e4c0 100644
--- a/test/CXX/drs/dr4xx.cpp
+++ b/test/CXX/drs/dr4xx.cpp
@@ -318,8 +318,8 @@ namespace dr420 { // dr420: yes
q->~id<int>();
p->id<int>::~id<int>();
q->id<int>::~id<int>();
- p->template id<int>::~id<int>(); // expected-error {{expected unqualified-id}}
- q->template id<int>::~id<int>(); // expected-error {{expected unqualified-id}}
+ p->template id<int>::~id<int>(); // expected-error {{'template' keyword not permitted here}} expected-error {{base type 'int' is not a struct}}
+ q->template id<int>::~id<int>(); // expected-error {{'template' keyword not permitted here}} expected-error {{base type 'int' is not a struct}}
p->A::template id<int>::~id<int>();
q->A::template id<int>::~id<int>();
}
@@ -533,10 +533,10 @@ namespace dr437 { // dr437: sup 1308
namespace dr444 { // dr444: yes
struct D;
- struct B { // expected-note {{candidate is the implicit copy}} expected-note 0-1 {{implicit move}}
+ struct B { // expected-note {{candidate function (the implicit copy}} expected-note 0-1 {{implicit move}}
D &operator=(D &) = delete; // expected-error 0-1{{extension}} expected-note {{deleted}}
};
- struct D : B { // expected-note {{candidate is the implicit}} expected-note 0-1 {{implicit move}}
+ struct D : B { // expected-note {{candidate function (the implicit copy}} expected-note 0-1 {{implicit move}}
using B::operator=;
} extern d;
void f() {
@@ -796,24 +796,9 @@ namespace dr468 { // dr468: yes c++11
}
namespace dr469 { // dr469: no
- // FIXME: The core issue here didn't really answer the question. We don't
- // deduce 'const T' from a function or reference type in a class template...
- template<typename T> struct X; // expected-note 2{{here}}
+ template<typename T> struct X; // expected-note {{here}}
template<typename T> struct X<const T> {};
X<int&> x; // expected-error {{undefined}}
- X<int()> y; // expected-error {{undefined}}
-
- // ... but we do in a function template. GCC and EDG fail deduction of 'f'
- // and the second 'h'.
- template<typename T> void f(const T *);
- template<typename T> void g(T *, const T * = 0);
- template<typename T> void h(T *) { T::error; }
- template<typename T> void h(const T *);
- void i() {
- f(&i);
- g(&i);
- h(&i);
- }
}
namespace dr470 { // dr470: yes
diff --git a/test/CXX/drs/dr5xx.cpp b/test/CXX/drs/dr5xx.cpp
index 5122398b7ca3..c20a873fc1c7 100644
--- a/test/CXX/drs/dr5xx.cpp
+++ b/test/CXX/drs/dr5xx.cpp
@@ -74,7 +74,7 @@ namespace dr512 { // dr512: yes
};
union U { A a; };
#if __cplusplus < 201103L
- // expected-error@-2 {{has a non-trivial constructor}}
+ // expected-error@-2 {{has a non-trivial default constructor}}
// expected-note@-6 {{no default constructor}}
// expected-note@-6 {{suppressed by user-declared constructor}}
#endif
diff --git a/test/CXX/drs/dr6xx.cpp b/test/CXX/drs/dr6xx.cpp
index 8b9a69960767..c3c867b7a54d 100644
--- a/test/CXX/drs/dr6xx.cpp
+++ b/test/CXX/drs/dr6xx.cpp
@@ -1,9 +1,13 @@
-// RUN: %clang_cc1 -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++1z %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
+// RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
+// RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
+// RUN: %clang_cc1 -std=c++17 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
+// RUN: %clang_cc1 -std=c++2a %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
-namespace std { struct type_info {}; }
+namespace std {
+ struct type_info {};
+ __extension__ typedef __SIZE_TYPE__ size_t;
+} // namespace std
namespace dr601 { // dr601: yes
#if __cplusplus >= 201103L
@@ -354,6 +358,672 @@ namespace dr639 { // dr639: yes
}
}
+namespace dr641 { // dr641: yes
+ namespace std_example {
+ struct abc;
+
+ struct xyz {
+ xyz(); // expected-note 0-1{{candidate}}
+ xyz(xyz &); // expected-note 0-1{{candidate}}
+
+ operator xyz &() = delete; // expected-error 0-1{{extension}} expected-warning {{will never be used}}
+ operator abc &() = delete; // expected-error 0-1{{extension}}
+ };
+
+ struct abc : xyz {};
+
+ template<typename T>
+ void use(T &); // expected-note {{expects an l-value}}
+ void test() {
+ use<xyz>(xyz()); // expected-error {{no match}}
+ use<const xyz>(xyz());
+#if __cplusplus < 201103L
+ // expected-error-re@-2 {{no viable constructor copying parameter of type '{{.*}}xyz'}}
+#endif
+ }
+ }
+
+ template<typename T> struct error { typedef typename T::error type; };
+
+ struct A {
+ template<typename T, typename error<T>::type = 0> operator T() const; // expected-error 0-1{{extension}}
+ };
+ A a;
+ void f(A&); // expected-note 2{{candidate}}
+ void g(const A ca) {
+ f(A()); // expected-error {{no match}}
+ f(ca); // expected-error {{no match}}
+ (void)A();
+ (void)ca;
+ }
+}
+
+namespace dr642 { // dr642: yes
+ void f() {
+ const int i = 2;
+ {
+ char i[i];
+ _Static_assert(sizeof(i) == 2, ""); // expected-error {{C11}}
+ }
+ }
+
+ struct s { int a; };
+ void g(int s) {
+ struct s *p = new struct s;
+ p->a = s;
+ }
+}
+
+#if __cplusplus >= 201103L
+namespace dr643 { // dr643: yes
+ struct A {
+ int x;
+ auto f() -> decltype(this->x);
+ auto f(A &a) -> decltype(a.x);
+ auto g() -> decltype(x);
+ auto h() -> decltype(this->y); // expected-error {{no member named 'y'}}
+ auto h(A &a) -> decltype(a.y); // expected-error {{no member named 'y'}}
+ auto i() -> decltype(y); // expected-error {{undeclared identifier 'y'}}
+ int y;
+ };
+}
+#endif
+
+#if __cplusplus >= 201103L
+namespace dr644 { // dr644: partial
+ struct A {
+ A() = default;
+ int x, y;
+ };
+ static_assert(__is_literal_type(A), "");
+
+ struct B : A {};
+ static_assert(__is_literal_type(B), "");
+
+ struct C : virtual A {};
+ static_assert(!__is_literal_type(C), "");
+
+ struct D { C c; };
+ static_assert(!__is_literal_type(D), "");
+
+ // FIXME: According to DR644, E<C> is a literal type despite having virtual
+ // base classes. This appears to be a wording defect.
+ template<typename T>
+ struct E : T {
+ constexpr E() = default;
+ };
+ static_assert(!__is_literal_type(E<C>), "");
+}
+#endif
+
+// dr645 increases permission to optimize; it's not clear that it's possible to
+// test for this.
+// dr645: na
+
+#if __cplusplus >= 201103L
+namespace dr646 { // dr646: sup 981
+ struct A {
+ constexpr A(const A&) = default; // ok
+ };
+
+ struct B {
+ constexpr B() {}
+ B(B&);
+ };
+ constexpr B b = {}; // ok
+}
+#endif
+
+#if __cplusplus >= 201103L
+namespace dr647 { // dr647: yes
+ // This is partially superseded by dr1358.
+ struct A {
+ constexpr virtual void f() const;
+ constexpr virtual void g() const {} // expected-error {{virtual function cannot be constexpr}}
+ };
+
+ struct X { virtual void f() const; }; // expected-note {{overridden}}
+ struct B : X {
+ constexpr void f() const {} // expected-error {{virtual function cannot be constexpr}}
+ };
+
+ struct NonLiteral { NonLiteral() {} }; // expected-note {{not an aggregate and has no constexpr constructors}}
+
+ struct C {
+ constexpr C(NonLiteral);
+ constexpr C(NonLiteral, int) {} // expected-error {{not a literal type}}
+ constexpr C() try {} catch (...) {} // expected-error {{function try block}}
+ };
+
+ struct D {
+ operator int() const;
+ constexpr D(int) {}
+ D(float); // expected-note 2{{declared here}}
+ };
+ constexpr int get();
+ struct E {
+ int n;
+ D d;
+
+ // FIXME: We should diagnose this, as the conversion function is not
+ // constexpr. However, that part of this issue is supreseded by dr1364 and
+ // others; no diagnostic is required for this any more.
+ constexpr E()
+ : n(D(0)),
+ d(0) {}
+
+ constexpr E(int) // expected-error {{never produces a constant expression}}
+ : n(0),
+ d(0.0f) {} // expected-note {{non-constexpr constructor}}
+ constexpr E(float f) // expected-error {{never produces a constant expression}}
+ : n(get()),
+ d(D(0) + f) {} // expected-note {{non-constexpr constructor}}
+ };
+}
+#endif
+
+#if __cplusplus >= 201103L
+namespace dr648 { // dr648: yes
+ int f();
+ constexpr int a = (true ? 1 : f());
+ constexpr int b = false && f();
+ constexpr int c = true || f();
+}
+#endif
+
+#if __cplusplus >= 201103L
+namespace dr649 { // dr649: yes
+ alignas(0x20000000) int n; // expected-error {{requested alignment}}
+ struct alignas(0x20000000) X {}; // expected-error {{requested alignment}}
+ struct Y { int n alignas(0x20000000); }; // expected-error {{requested alignment}}
+ struct alignas(256) Z {};
+ // This part is superseded by dr2130 and eventually by aligned allocation support.
+ auto *p = new Z;
+}
+#endif
+
+// dr650 FIXME: add codegen test
+
+#if __cplusplus >= 201103L
+namespace dr651 { // dr651: yes
+ struct X {
+ virtual X &f();
+ };
+ struct Y : X {
+ Y &f();
+ };
+ using T = decltype(((X&&)Y()).f());
+ using T = X &;
+}
+#endif
+
+#if __cplusplus >= 201103L
+namespace dr652 { // dr652: yes
+ constexpr int n = 1.2 * 3.4;
+ static_assert(n == 4, "");
+}
+#endif
+
+// dr653 FIXME: add codegen test
+
+#if __cplusplus >= 201103L
+namespace dr654 { // dr654: yes
+ void f() {
+ if (nullptr) {} // expected-warning {{implicit conversion of nullptr constant to 'bool'}}
+ bool b = nullptr; // expected-warning {{implicit conversion of nullptr constant to 'bool'}}
+ if (nullptr == 0) {}
+ if (nullptr != 0) {}
+ if (nullptr <= 0) {} // expected-error {{invalid operands}}
+ if (nullptr == 1) {} // expected-error {{invalid operands}}
+ if (!nullptr) {} // expected-warning {{implicit conversion of nullptr constant to 'bool'}}
+ decltype(nullptr) n = 0;
+ static_cast<int>(nullptr); // expected-error {{not allowed}}
+ (void)static_cast<decltype(nullptr)>(0);
+ static_cast<decltype(nullptr)>(1); // expected-error {{not allowed}}
+ void(true ? nullptr : 0);
+ void(true ? 0 : nullptr);
+ }
+}
+#endif
+
+namespace dr655 { // dr655: yes
+ struct A { A(int); }; // expected-note 2-3{{not viable}}
+ struct B : A {
+ A a;
+ B();
+ B(int) : B() {} // expected-error 0-1 {{C++11}}
+ B(int*) : A() {} // expected-error {{no matching constructor}}
+ };
+}
+
+namespace dr656 { // dr656: yes
+ struct A { A(const A&) = delete; }; // expected-error 0-1 {{C++11}}
+ struct B : A {};
+ struct X { operator B(); } x;
+ const A &r = x;
+ struct Y : private A { // expected-note 2{{here}} expected-note 2{{candidate}}
+ operator B() volatile;
+ };
+ extern Y y;
+ extern volatile Y vy;
+ // Conversion not considered due to reference-related types.
+ const A &s = y; // expected-error {{private base class}}
+ const A &t = vy; // expected-error {{drops 'volatile'}}
+
+ struct C { operator struct D(); } c;
+ struct D : C {};
+ const D &d = c; // ok, D not reference-related to C
+
+ template<typename T> void accept(T); // expected-note {{candidate}}
+ template<typename T> void accept(...) = delete; // expected-error 0-1 {{C++11}} expected-note {{candidate}}
+ void f() {
+ accept<const A&>(x);
+ accept<const A&>(y); // expected-error {{private base class}}
+ accept<const A&>(vy); // expected-error {{call to deleted}} expected-error {{no matching constructor}}
+ accept<const D&>(c);
+ }
+}
+
+namespace dr657 { // dr657: partial
+ struct Abs { virtual void x() = 0; };
+ struct Der : public Abs { virtual void x(); };
+
+ struct Cnvt { template<typename F> Cnvt(F); };
+
+ void foo(Cnvt a);
+ void foo(Abs &a);
+ void f(Abs *a) { foo(*a); }
+
+ void bar(Abs &a);
+ template<typename T> void bar(T);
+ void g(Abs *a) { bar(*a); }
+
+ // FIXME: The following examples demonstrate that we might be accepting the
+ // above cases for the wrong reason.
+
+ // FIXME: We should reject this.
+ struct C { C(Abs) {} };
+ // FIXME: We should reject this.
+ struct Q { operator Abs() { __builtin_unreachable(); } } q;
+#if __cplusplus >= 201703L
+ // FIXME: We should *definitely* reject this.
+ C c = Q().operator Abs();
+#endif
+
+ template<typename F> struct Cnvt2 { Cnvt2(F); typedef int type; };
+
+ // FIXME: We should reject this.
+ void baz(Abs &a);
+ template<typename T> typename Cnvt2<T>::type baz(T);
+ void h(Abs *a) { baz(*a); }
+
+ // FIXME: We should reject this too.
+ Cnvt2<Abs>::type err;
+}
+
+// dr658 FIXME: add codegen test
+
+#if __cplusplus >= 201103L
+namespace dr659 { // dr659: yes
+ static_assert(alignof(char) == alignof(char&), "");
+ static_assert(alignof(int) == alignof(int&), "");
+ int n = alignof(int(&)()); // expected-error {{application of 'alignof' to a function type}}
+ struct A; // expected-note {{forward}}
+ int m = alignof(A&); // expected-error {{application of 'alignof' to an incomplete type}}
+}
+#endif
+
+#if __cplusplus >= 201103L
+namespace dr660 { // dr660: yes
+ enum : int { a };
+ enum class { b }; // expected-error {{requires a name}}
+ auto x = a;
+
+ struct X {
+ enum : int { a };
+ enum class { b }; // expected-error {{requires a name}}
+ };
+ auto y = X::a;
+}
+#endif
+
+// dr661 FIXME: add codegen test
+
+namespace dr662 { // dr662: yes
+ template <typename T> void f(T t) {
+ T &tr = t;
+ T *tp = &t; // expected-error {{pointer to a reference}}
+#if __cplusplus >= 201103L
+ auto *ap = &t;
+#endif
+ }
+ void g(int n) { f<int&>(n); } // expected-note {{instantiation of}}
+}
+
+namespace dr663 { // dr663: yes c++11
+ int ЍЎ = 123;
+#if __cplusplus < 201103L
+ // expected-error@-2 {{non-ASCII}}
+#endif
+}
+
+#if __cplusplus >= 201103L
+namespace dr664 { // dr664: yes
+ struct A { A(const A&) = delete; };
+ A &&f(A &&a, int n) {
+ if (n)
+ return f(static_cast<A&&>(a), n - 1);
+ return static_cast<A&&>(a);
+ }
+}
+#endif
+
+namespace dr665 { // dr665: yes
+ struct A { virtual ~A(); };
+ struct B : A {} *b;
+ struct C : private A {} *c; // expected-note {{here}}
+ struct D : B, C {} *d;
+
+ struct VB : virtual A {} *vb;
+ struct VC : private virtual A {} *vc; // expected-note {{here}}
+ struct VD : VB, VC {} *vd;
+
+ void f() {
+ (void)dynamic_cast<A*>(b);
+ (void)dynamic_cast<A*>(c); // expected-error {{private}}
+ (void)dynamic_cast<A*>(d); // expected-error {{ambiguous}}
+ (void)dynamic_cast<A*>(vb);
+ (void)dynamic_cast<A*>(vc); // expected-error {{private}}, even though it could be valid at runtime
+ (void)dynamic_cast<A*>(vd);
+ }
+}
+
+namespace dr666 { // dr666: yes
+ struct P { friend P operator*(P, P); P(int); } p(0);
+
+ template<int> int f();
+ template<typename T> int f() {
+ T::type *p = 0; // expected-error {{missing 'typename'}}
+ int a(T::type); // expected-error {{missing 'typename'}}
+ return f<T::type>(); // expected-error {{missing 'typename'}}
+ }
+ struct X { static const int type = 0; };
+ struct Y { typedef int type; };
+ int a = f<X>();
+ int b = f<Y>(); // expected-note {{instantiation of}}
+}
+
+// Triviality is entirely different in C++98.
+#if __cplusplus >= 201103L
+namespace dr667 { // dr667: yes
+ struct A {
+ A() = default;
+ int &r;
+ };
+ static_assert(!__is_trivially_constructible(A), "");
+
+ struct B { ~B() = delete; };
+ union C { B b; };
+ static_assert(!__is_trivially_destructible(C), "");
+
+ struct D { D(const D&) = delete; };
+ struct E : D {};
+ static_assert(!__is_trivially_constructible(E, const E&), "");
+
+ struct F { F &operator=(F&&) = delete; };
+ struct G : F {};
+ static_assert(!__is_trivially_assignable(G, G&&), "");
+}
+#endif
+
+// dr668 FIXME: add codegen test
+
+#if __cplusplus >= 201103L
+namespace dr669 { // dr669: yes
+ void f() {
+ int n;
+ using T = decltype(n);
+ using T = int;
+ using U = decltype((n));
+ using U = int &;
+
+ [=] {
+ using V = decltype(n);
+ using V = int;
+ using W = decltype((n));
+ using W = const int&;
+ } ();
+
+ struct X {
+ int n;
+ void f() const {
+ using X = decltype(n);
+ using X = int;
+ using Y = decltype((n));
+ using Y = const int&;
+ }
+ };
+ }
+}
+#endif
+
+namespace dr671 { // dr671: yes
+ enum class E { e }; // expected-error 0-1 {{C++11}}
+ E e = static_cast<E>(0);
+ int n = static_cast<int>(E::e); // expected-error 0-1 {{C++11}}
+ int m = static_cast<int>(e); // expected-error 0-1 {{C++11}}
+}
+
+// dr672 FIXME: add codegen test
+
+namespace dr673 { // dr673: yes
+ template<typename> struct X { static const int n = 0; };
+
+ class A {
+ friend class B *f();
+ class C *f();
+ void f(class D *);
+ enum { e = X<struct E>::n };
+ void g() { extern struct F *p; }
+ };
+ B *b;
+ C *c;
+ D *d;
+ E *e;
+ F *f; // expected-error {{unknown type name}}
+}
+
+namespace dr674 { // dr674: no
+ template<typename T> int f(T);
+
+ int g(int);
+ template<typename T> int g(T);
+
+ int h(int);
+ template<typename T> int h(T);
+
+ class X {
+ // FIXME: This should deduce dr674::f<int>.
+ friend int dr674::f(int); // expected-error {{does not match any}}
+ friend int dr674::g(int);
+ friend int dr674::h<>(int);
+ int n;
+ };
+
+ template<typename T> int f(T) { return X().n; }
+ int g(int) { return X().n; }
+ template<typename T> int g(T) { return X().n; }
+ int h(int) { return X().n; }
+ template<typename T> int h(T) { return X().n; }
+
+ template int f(int);
+ template int g(int);
+ template int h(int);
+}
+
+namespace dr675 { // dr675: dup 739
+ template<typename T> struct A { T n : 1; };
+#if __cplusplus >= 201103L
+ static_assert(A<char>{1}.n < 0, "");
+ static_assert(A<int>{1}.n < 0, "");
+ static_assert(A<long long>{1}.n < 0, "");
+#endif
+}
+
+// dr676: na
+
+namespace dr677 { // dr677: no
+ struct A {
+ void *operator new(std::size_t);
+ void operator delete(void*) = delete; // expected-error 0-1{{C++11}} expected-note {{deleted}}
+ };
+ struct B {
+ void *operator new(std::size_t);
+ void operator delete(void*) = delete; // expected-error 0-1{{C++11}} expected-note 2{{deleted}}
+ virtual ~B();
+ };
+ void f(A *p) { delete p; } // expected-error {{deleted}}
+ // FIXME: This appears to be valid; we shouldn't even be looking up the 'operator delete' here.
+ void f(B *p) { delete p; } // expected-error {{deleted}}
+ B::~B() {} // expected-error {{deleted}}
+}
+
+// dr678 FIXME: check that the modules ODR check catches this
+
+namespace dr679 { // dr679: yes
+ struct X {};
+ template<int> void operator+(X, X);
+ template<> void operator+<0>(X, X) {} // expected-note {{previous}}
+ template<> void operator+<0>(X, X) {} // expected-error {{redefinition}}
+}
+
+// dr680: na
+
+#if __cplusplus >= 201103L
+namespace dr681 { // dr681: partial
+ auto *a() -> int; // expected-error {{must specify return type 'auto', not 'auto *'}}
+ auto (*b)() -> int;
+ // FIXME: The errors here aren't great.
+ auto (*c()) -> int; // expected-error {{expected function body}}
+ auto ((*d)()) -> int; // expected-error {{expected ';'}} expected-error {{requires an initializer}}
+
+ // FIXME: This is definitely wrong. This should be
+ // "function of () returning pointer to function of () returning int"
+ // not a function with a deduced return type.
+ auto (*e())() -> int; // expected-error 0-1{{C++14}}
+
+ auto f() -> int (*)();
+ auto g() -> auto (*)() -> int;
+}
+#endif
+
+#if __cplusplus >= 201103L
+namespace dr683 { // dr683: yes
+ struct A {
+ A() = default;
+ A(const A&) = default;
+ A(A&);
+ };
+ static_assert(__is_trivially_constructible(A, const A&), "");
+ static_assert(!__is_trivially_constructible(A, A&), "");
+ static_assert(!__is_trivial(A), "");
+
+ struct B : A {};
+ static_assert(__is_trivially_constructible(B, const B&), "");
+ static_assert(__is_trivially_constructible(B, B&), "");
+ static_assert(__is_trivial(B), "");
+}
+#endif
+
+#if __cplusplus >= 201103L
+namespace dr684 { // dr684: sup 1454
+ void f() {
+ int a; // expected-note {{here}}
+ constexpr int *p = &a; // expected-error {{constant expression}} expected-note {{pointer to 'a'}}
+ }
+}
+#endif
+
+#if __cplusplus >= 201103L
+namespace dr685 { // dr685: yes
+ enum E : long { e };
+ void f(int);
+ int f(long);
+ int a = f(e);
+
+ enum G : short { g };
+ int h(short);
+ void h(long);
+ int b = h(g);
+
+ int i(int);
+ void i(long);
+ int c = i(g);
+
+ int j(unsigned int); // expected-note {{candidate}}
+ void j(long); // expected-note {{candidate}}
+ int d = j(g); // expected-error {{ambiguous}}
+
+ int k(short); // expected-note {{candidate}}
+ void k(int); // expected-note {{candidate}}
+ int x = k(g); // expected-error {{ambiguous}}
+}
+#endif
+
+namespace dr686 { // dr686: yes
+ void f() {
+ (void)dynamic_cast<struct A*>(0); // expected-error {{incomplete}} expected-note {{forward}}
+ (void)dynamic_cast<struct A{}*>(0); // expected-error {{cannot be defined in a type specifier}}
+ (void)typeid(struct B*);
+ (void)typeid(struct B{}*); // expected-error {{cannot be defined in a type specifier}}
+ (void)static_cast<struct C*>(0);
+ (void)static_cast<struct C{}*>(0); // expected-error {{cannot be defined in a type specifier}}
+ (void)reinterpret_cast<struct D*>(0);
+ (void)reinterpret_cast<struct D{}*>(0); // expected-error {{cannot be defined in a type specifier}}
+ (void)const_cast<struct E*>(0); // expected-error {{not allowed}}
+ (void)const_cast<struct E{}*>(0); // expected-error {{cannot be defined in a type specifier}}
+ (void)sizeof(struct F*);
+ (void)sizeof(struct F{}*); // expected-error {{cannot be defined in a type specifier}}
+ (void)new struct G*;
+ (void)new struct G{}*; // expected-error {{cannot be defined in a type specifier}}
+#if __cplusplus >= 201103L
+ (void)alignof(struct H*);
+ (void)alignof(struct H{}*); // expected-error {{cannot be defined in a type specifier}}
+#endif
+ (void)(struct I*)0;
+ (void)(struct I{}*)0; // expected-error {{cannot be defined in a type specifier}}
+ if (struct J *p = 0) {}
+ if (struct J {} *p = 0) {} // expected-error {{cannot be defined in a condition}}
+ for (struct K *p = 0; struct L *q = 0; ) {}
+ for (struct K {} *p = 0; struct L {} *q = 0; ) {} // expected-error {{'L' cannot be defined in a condition}}
+#if __cplusplus >= 201103L
+ using M = struct {};
+#endif
+ struct N {
+ operator struct O{}(){}; // expected-error {{cannot be defined in a type specifier}}
+ };
+ try {}
+ catch (struct P *) {} // expected-error {{incomplete}} expected-note {{forward}}
+ catch (struct P {} *) {} // expected-error {{cannot be defined in a type specifier}}
+#if __cplusplus < 201703L
+ void g() throw(struct Q); // expected-error {{incomplete}} expected-note {{forward}}
+ void h() throw(struct Q {}); // expected-error {{cannot be defined in a type specifier}}
+#endif
+ }
+ template<struct R *> struct X;
+ template<struct R {} *> struct Y; // expected-error {{cannot be defined in a type specifier}}
+}
+
+namespace dr687 { // dr687 still open
+ template<typename T> void f(T a) {
+ // FIXME: This is valid in C++20.
+ g<int>(a); // expected-error {{undeclared}} expected-error {{'('}}
+
+ // This is not.
+ template g<int>(a); // expected-error {{expected expression}}
+ }
+}
+
namespace dr692 { // dr692: no
namespace temp_func_order_example2 {
template <typename T, typename U> struct A {};
diff --git a/test/CXX/drs/dr7xx.cpp b/test/CXX/drs/dr7xx.cpp
index fe4a2dc5ee4a..d02582b5b40c 100644
--- a/test/CXX/drs/dr7xx.cpp
+++ b/test/CXX/drs/dr7xx.cpp
@@ -3,6 +3,80 @@
// RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++1z %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+namespace dr727 { // dr727: partial
+ struct A {
+ template<typename T> struct C; // expected-note 6{{here}}
+ template<typename T> void f(); // expected-note {{here}}
+ template<typename T> static int N; // expected-error 0-1{{C++14}} expected-note 6{{here}}
+
+ template<> struct C<int>;
+ template<> void f<int>();
+ template<> static int N<int>;
+
+ template<typename T> struct C<T*>;
+ template<typename T> static int N<T*>;
+
+ struct B {
+ template<> struct C<float>; // expected-error {{not in class 'A' or an enclosing namespace}}
+ template<> void f<float>(); // expected-error {{no function template matches}}
+ template<> static int N<float>; // expected-error {{not in class 'A' or an enclosing namespace}}
+
+ template<typename T> struct C<T**>; // expected-error {{not in class 'A' or an enclosing namespace}}
+ template<typename T> static int N<T**>; // expected-error {{not in class 'A' or an enclosing namespace}}
+
+ template<> struct A::C<double>; // expected-error {{not in class 'A' or an enclosing namespace}}
+ template<> void A::f<double>(); // expected-error {{no function template matches}} expected-error {{cannot have a qualified name}}
+ template<> static int A::N<double>; // expected-error {{not in class 'A' or an enclosing namespace}} expected-error {{cannot have a qualified name}}
+
+ template<typename T> struct A::C<T***>; // expected-error {{not in class 'A' or an enclosing namespace}}
+ template<typename T> static int A::N<T***>; // expected-error {{not in class 'A' or an enclosing namespace}} expected-error {{cannot have a qualified name}}
+ };
+ };
+
+ template<> struct A::C<char>;
+ template<> void A::f<char>();
+ template<> int A::N<char>;
+
+ template<typename T> struct A::C<T****>;
+ template<typename T> int A::N<T****>;
+
+ namespace C {
+ template<> struct A::C<long>; // expected-error {{not in class 'A' or an enclosing namespace}}
+ template<> void A::f<long>(); // expected-error {{not in class 'A' or an enclosing namespace}}
+ template<> int A::N<long>; // expected-error {{not in class 'A' or an enclosing namespace}}
+
+ template<typename T> struct A::C<T*****>; // expected-error {{not in class 'A' or an enclosing namespace}}
+ template<typename T> int A::N<T*****>; // expected-error {{not in class 'A' or an enclosing namespace}}
+ }
+
+ template<typename>
+ struct D {
+ template<typename T> struct C { typename T::error e; }; // expected-error {{no members}}
+ template<typename T> void f() { T::error; } // expected-error {{no members}}
+ template<typename T> static const int N = T::error; // expected-error 2{{no members}} expected-error 0-1{{C++14}}
+
+ template<> struct C<int> {};
+ template<> void f<int>() {}
+ template<> static const int N<int>;
+
+ template<typename T> struct C<T*> {};
+ template<typename T> static const int N<T*>;
+ };
+
+ void d(D<int> di) {
+ D<int>::C<int>();
+ di.f<int>();
+ int a = D<int>::N<int>; // FIXME: expected-note {{instantiation of}}
+
+ D<int>::C<int*>();
+ int b = D<int>::N<int*>;
+
+ D<int>::C<float>(); // expected-note {{instantiation of}}
+ di.f<float>(); // expected-note {{instantiation of}}
+ int c = D<int>::N<float>; // expected-note {{instantiation of}}
+ }
+}
+
namespace dr777 { // dr777: 3.7
#if __cplusplus >= 201103L
template <typename... T>
@@ -16,5 +90,3 @@ template <typename... T>
void h(int i = 0, T ...args, int j = 1) {}
#endif
}
-
-// expected-no-diagnostics
diff --git a/test/CXX/except/except.spec/p3.cpp b/test/CXX/except/except.spec/p3.cpp
index 03f1d7626c0d..d5af4651047f 100644
--- a/test/CXX/except/except.spec/p3.cpp
+++ b/test/CXX/except/except.spec/p3.cpp
@@ -104,3 +104,13 @@ void* operator new(mysize_t);
void* operator new[](mysize_t);
void* operator new[](mysize_t) throw(std::bad_alloc);
+template<bool X> void equivalent() noexcept (X);
+template<bool X> void equivalent() noexcept (X);
+
+template<bool X, bool Y> void not_equivalent() noexcept (X); // expected-note {{previous}}
+template<bool X, bool Y> void not_equivalent() noexcept (Y); // expected-error {{does not match}}
+
+template<bool X> void missing() noexcept (X); // expected-note {{previous}}
+// FIXME: The missing exception specification that we report here doesn't make
+// sense in the context of this declaration.
+template<bool P> void missing(); // expected-error {{missing exception specification 'noexcept(X)'}}
diff --git a/test/CXX/expr/expr.post/expr.reinterpret.cast/p2.cpp b/test/CXX/expr/expr.post/expr.reinterpret.cast/p2.cpp
new file mode 100644
index 000000000000..b03db27ee1d0
--- /dev/null
+++ b/test/CXX/expr/expr.post/expr.reinterpret.cast/p2.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 %s -verify
+
+// The reinterpret_cast operator shall not cast away constness.
+struct X {};
+struct Y {};
+void f(const int * X::* Y::* *p) {
+ // This applies for similar types...
+ (void)reinterpret_cast<int * X::* Y::* *>(p); // expected-error {{casts away qualifiers}}
+ // ... and for cases where the base type is different ...
+ (void)reinterpret_cast<float * X::* Y::* *>(p); // expected-error {{casts away qualifiers}}
+ // ... and for cases where pointers to members point to members of different classes ...
+ (void)reinterpret_cast<int * Y::* X::* *>(p); // expected-error {{casts away qualifiers}}
+ // ... and even for cases where the path is wholly different!
+ // (Though we accept such cases as an extension.)
+ (void)reinterpret_cast<double Y::* X::* * *>(p); // expected-warning {{casts away qualifiers}}
+
+ // If qualifiers are added, we need a 'const' at every level above.
+ (void)reinterpret_cast<const volatile double Y::* X::* * *>(p); // expected-warning {{casts away qualifiers}}
+ (void)reinterpret_cast<const volatile double Y::*const X::*const **>(p); // expected-warning {{casts away qualifiers}}
+ (void)reinterpret_cast<const volatile double Y::*const X::**const *>(p); // expected-warning {{casts away qualifiers}}
+ (void)reinterpret_cast<const volatile double Y::*X::*const *const *>(p); // expected-warning {{casts away qualifiers}}
+ (void)reinterpret_cast<const volatile double Y::*const X::*const *const *>(p); // ok
+
+ (void)reinterpret_cast<const double Y::*volatile X::**const *>(p); // expected-warning {{casts away qualifiers}}
+ (void)reinterpret_cast<const double Y::*volatile X::*const *const *>(p); // ok
+}
diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p2-template-parameter.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p2-template-parameter.cpp
new file mode 100644
index 000000000000..f120a63badcb
--- /dev/null
+++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p2-template-parameter.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -std=c++17 %s -verify
+
+template<auto> struct Nothing {};
+
+void pr33696() {
+ Nothing<[]() { return 0; }()> nothing; // expected-error{{a lambda expression cannot appear in this context}}
+}
diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p3.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p3.cpp
index 80771d7a229a..db40bd5d1420 100644
--- a/test/CXX/expr/expr.prim/expr.prim.lambda/p3.cpp
+++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p3.cpp
@@ -1,11 +1,19 @@
// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 %s -verify
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 %s -verify
void test_nonaggregate(int i) {
auto lambda = [i]() -> void {}; // expected-note 2{{candidate constructor}}
decltype(lambda) foo = { 1 }; // expected-error{{no matching constructor}}
- static_assert(!__is_literal(decltype(lambda)), "");
+ static_assert(__is_literal(decltype(lambda)) == (__cplusplus >= 201703L), "");
auto lambda2 = []{}; // expected-note 2{{candidate constructor}}
decltype(lambda2) bar = {}; // expected-error{{no matching constructor}}
- static_assert(!__is_literal(decltype(lambda2)), "");
+ static_assert(__is_literal(decltype(lambda2)) == (__cplusplus >= 201703L), "");
}
+
+constexpr auto literal = []{};
+#if __cplusplus < 201703L
+// expected-error@-2 {{constexpr variable cannot have non-literal type}}
+// expected-note@-3 {{lambda closure types are non-literal types before C++17}}
+#endif
diff --git a/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cpp b/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cpp
index 79e68655b45b..ad03191363e5 100644
--- a/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cpp
+++ b/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cpp
@@ -1,15 +1,15 @@
// RUN: %clang_cc1 -fmodules-ts %S/module.cppm -triple %itanium_abi_triple -emit-module-interface -o %t
// RUN: %clang_cc1 -fmodules-ts %s -triple %itanium_abi_triple -fmodule-file=%t -emit-llvm -o - | FileCheck %s --implicit-check-not=unused --implicit-check-not=global_module
-// CHECK-DAG: @extern_var_exported = external global
-// CHECK-DAG: @inline_var_exported = linkonce_odr global
-// CHECK-DAG: @_ZW6ModuleE19static_var_exported = available_externally global i32 0,
-// CHECK-DAG: @const_var_exported = available_externally constant i32 3,
+// CHECK-DAG: @extern_var_exported = external {{(dso_local )?}}global
+// CHECK-DAG: @inline_var_exported = linkonce_odr {{(dso_local )?}}global
+// CHECK-DAG: @_ZW6ModuleE19static_var_exported = available_externally {{(dso_local )?}}global i32 0,
+// CHECK-DAG: @const_var_exported = available_externally {{(dso_local )?}}constant i32 3,
//
-// CHECK-DAG: @_ZW6ModuleE25extern_var_module_linkage = external global
-// CHECK-DAG: @_ZW6ModuleE25inline_var_module_linkage = linkonce_odr global
-// CHECK-DAG: @_ZW6ModuleE25static_var_module_linkage = available_externally global i32 0,
-// CHECK-DAG: @_ZW6ModuleE24const_var_module_linkage = available_externally constant i32 3,
+// CHECK-DAG: @_ZW6ModuleE25extern_var_module_linkage = external {{(dso_local )?}}global
+// CHECK-DAG: @_ZW6ModuleE25inline_var_module_linkage = linkonce_odr {{(dso_local )?}}global
+// CHECK-DAG: @_ZW6ModuleE25static_var_module_linkage = available_externally {{(dso_local )?}}global i32 0,
+// CHECK-DAG: @_ZW6ModuleE24const_var_module_linkage = available_externally {{(dso_local )?}}constant i32 3,
module Module;
diff --git a/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cppm b/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cppm
index 15d1114fb03f..0f2c0db66e9c 100644
--- a/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cppm
+++ b/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cppm
@@ -1,30 +1,30 @@
// RUN: %clang_cc1 -fmodules-ts %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s --implicit-check-not unused_inline --implicit-check-not unused_stastic_global_module
-// CHECK-DAG: @extern_var_global_module = external global
-// CHECK-DAG: @inline_var_global_module = linkonce_odr global
+// CHECK-DAG: @extern_var_global_module = external {{(dso_local )?}}global
+// CHECK-DAG: @inline_var_global_module = linkonce_odr {{(dso_local )?}}global
// CHECK-DAG: @_ZL24static_var_global_module = internal global
// CHECK-DAG: @_ZL23const_var_global_module = internal constant
//
// For ABI compatibility, these symbols do not include the module name.
-// CHECK-DAG: @extern_var_exported = external global
+// CHECK-DAG: @extern_var_exported = external {{(dso_local )?}}global
// FIXME: Should this be 'weak_odr global'? Presumably it must be, since we
// can discard this global and its initializer (if any), and other TUs are not
// permitted to run the initializer for this variable.
-// CHECK-DAG: @inline_var_exported = linkonce_odr global
-// CHECK-DAG: @_ZW6ModuleE19static_var_exported = global
-// CHECK-DAG: @const_var_exported = constant
+// CHECK-DAG: @inline_var_exported = linkonce_odr {{(dso_local )?}}global
+// CHECK-DAG: @_ZW6ModuleE19static_var_exported = {{(dso_local )?}}global
+// CHECK-DAG: @const_var_exported = {{(dso_local )?}}constant
//
-// CHECK-DAG: @_ZW6ModuleE25extern_var_module_linkage = external global
+// CHECK-DAG: @_ZW6ModuleE25extern_var_module_linkage = external {{(dso_local )?}}global
// FIXME: Should this be 'weak_odr global'? Presumably it must be, since we
// can discard this global and its initializer (if any), and other TUs are not
// permitted to run the initializer for this variable.
-// CHECK-DAG: @_ZW6ModuleE25inline_var_module_linkage = linkonce_odr global
-// CHECK-DAG: @_ZW6ModuleE25static_var_module_linkage = global
-// CHECK-DAG: @_ZW6ModuleE24const_var_module_linkage = constant
+// CHECK-DAG: @_ZW6ModuleE25inline_var_module_linkage = linkonce_odr {{(dso_local )?}}global
+// CHECK-DAG: @_ZW6ModuleE25static_var_module_linkage = {{(dso_local )?}}global
+// CHECK-DAG: @_ZW6ModuleE24const_var_module_linkage = {{(dso_local )?}}constant
//
-// CHECK-DAG: @_ZW6ModuleE25unused_var_module_linkage = global i32 4
-// CHECK-DAG: @_ZW6ModuleE32unused_static_var_module_linkage = global i32 5
-// CHECK-DAG: @_ZW6ModuleE31unused_const_var_module_linkage = constant i32 7
+// CHECK-DAG: @_ZW6ModuleE25unused_var_module_linkage = {{(dso_local )?}}global i32 4
+// CHECK-DAG: @_ZW6ModuleE32unused_static_var_module_linkage = {{(dso_local )?}}global i32 5
+// CHECK-DAG: @_ZW6ModuleE31unused_const_var_module_linkage = {{(dso_local )?}}constant i32 7
static void unused_static_global_module() {}
static void used_static_global_module() {}
@@ -37,7 +37,7 @@ inline int inline_var_global_module;
static int static_var_global_module;
const int const_var_global_module = 3;
-// CHECK: define void {{.*}}@_Z23noninline_global_modulev
+// CHECK: define {{(dso_local )?}}void {{.*}}@_Z23noninline_global_modulev
void noninline_global_module() {
// FIXME: This should be promoted to module linkage and given a
// module-mangled name, if it's called from an inline function within
@@ -60,9 +60,9 @@ export module Module;
export {
// FIXME: These should be ill-formed: you can't export an internal linkage
// symbol, per [dcl.module.interface]p2.
- // CHECK: define void {{.*}}@_ZW6ModuleE22unused_static_exportedv
+ // CHECK: define {{(dso_local )?}}void {{.*}}@_ZW6ModuleE22unused_static_exportedv
static void unused_static_exported() {}
- // CHECK: define void {{.*}}@_ZW6ModuleE20used_static_exportedv
+ // CHECK: define {{(dso_local )?}}void {{.*}}@_ZW6ModuleE20used_static_exportedv
static void used_static_exported() {}
inline void unused_inline_exported() {}
@@ -75,7 +75,7 @@ export {
static int static_var_exported;
const int const_var_exported = 3;
- // CHECK: define void {{.*}}@_Z18noninline_exportedv
+ // CHECK: define {{(dso_local )?}}void {{.*}}@_Z18noninline_exportedv
void noninline_exported() {
used_static_exported();
// CHECK: define linkonce_odr {{.*}}@_Z20used_inline_exportedv
@@ -91,9 +91,9 @@ export {
// FIXME: Ideally we wouldn't emit this as its name is not visible outside this
// TU, but this module interface might contain a template that can use this
// function so we conservatively emit it for now.
-// CHECK: define void {{.*}}@_ZW6ModuleE28unused_static_module_linkagev
+// CHECK: define {{(dso_local )?}}void {{.*}}@_ZW6ModuleE28unused_static_module_linkagev
static void unused_static_module_linkage() {}
-// CHECK: define void {{.*}}@_ZW6ModuleE26used_static_module_linkagev
+// CHECK: define {{(dso_local )?}}void {{.*}}@_ZW6ModuleE26used_static_module_linkagev
static void used_static_module_linkage() {}
inline void unused_inline_module_linkage() {}
@@ -104,7 +104,7 @@ inline int inline_var_module_linkage;
static int static_var_module_linkage;
const int const_var_module_linkage = 3;
-// CHECK: define void {{.*}}@_ZW6ModuleE24noninline_module_linkagev
+// CHECK: define {{(dso_local )?}}void {{.*}}@_ZW6ModuleE24noninline_module_linkagev
void noninline_module_linkage() {
used_static_module_linkage();
// CHECK: define linkonce_odr {{.*}}@_ZW6ModuleE26used_inline_module_linkagev
@@ -125,5 +125,5 @@ struct a {
struct b {};
struct c {};
};
-// CHECK: define void @_ZW6ModuleE1fW_0EN1a1bEW_0ENS_1cE(
+// CHECK: define {{(dso_local )?}}void @_ZW6ModuleE1fW_0EN1a1bEW_0ENS_1cE(
void f(a::b, a::c) {}
diff --git a/test/CXX/modules-ts/basic/basic.def.odr/p4/user.cpp b/test/CXX/modules-ts/basic/basic.def.odr/p4/user.cpp
index 5e9f7ecf5bab..97c69fa0bbee 100644
--- a/test/CXX/modules-ts/basic/basic.def.odr/p4/user.cpp
+++ b/test/CXX/modules-ts/basic/basic.def.odr/p4/user.cpp
@@ -1,10 +1,10 @@
// RUN: %clang_cc1 -fmodules-ts %S/module.cppm -triple %itanium_abi_triple -emit-module-interface -o %t
// RUN: %clang_cc1 -fmodules-ts %s -triple %itanium_abi_triple -fmodule-file=%t -emit-llvm -o - | FileCheck %s --implicit-check-not=unused --implicit-check-not=global_module
-// CHECK-DAG: @extern_var_exported = external global
-// CHECK-DAG: @inline_var_exported = linkonce_odr global
-// CHECK-DAG: @_ZW6ModuleE19static_var_exported = available_externally global i32 0
-// CHECK-DAG: @const_var_exported = available_externally constant i32 3
+// CHECK-DAG: @extern_var_exported = external {{(dso_local )?}}global
+// CHECK-DAG: @inline_var_exported = linkonce_odr {{(dso_local )?}}global
+// CHECK-DAG: @_ZW6ModuleE19static_var_exported = available_externally {{(dso_local )?}}global i32 0
+// CHECK-DAG: @const_var_exported = available_externally {{(dso_local )?}}constant i32 3
import Module;
diff --git a/test/CXX/over/over.built/p15.cpp b/test/CXX/over/over.built/p15.cpp
index 64ed3e7b83de..9b223bcbc24d 100644
--- a/test/CXX/over/over.built/p15.cpp
+++ b/test/CXX/over/over.built/p15.cpp
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-tautological-compare
-struct A { operator decltype(nullptr)(); };
-struct B { operator const int *(); };
+struct A { operator decltype(nullptr)(); }; // expected-note 16{{implicitly converted}}
+struct B { operator const int *(); }; // expected-note 8{{implicitly converted}}
void f(A a, B b, volatile int *pi) {
(void)(a == a);
(void)(a != a);
@@ -12,39 +12,31 @@ void f(A a, B b, volatile int *pi) {
(void)(a == b);
(void)(a != b);
- // FIXME: These cases were intended to be made ill-formed by N3624, but it
- // fails to actually achieve this goal.
- (void)(a < b);
- (void)(a > b);
- (void)(a <= b);
- (void)(a >= b);
+ (void)(a < b); // expected-error {{invalid operands}}
+ (void)(a > b); // expected-error {{invalid operands}}
+ (void)(a <= b); // expected-error {{invalid operands}}
+ (void)(a >= b); // expected-error {{invalid operands}}
(void)(b == a);
(void)(b != a);
- // FIXME: These cases were intended to be made ill-formed by N3624, but it
- // fails to actually achieve this goal.
- (void)(b < a);
- (void)(b > a);
- (void)(b <= a);
- (void)(b >= a);
+ (void)(b < a); // expected-error {{invalid operands}}
+ (void)(b > a); // expected-error {{invalid operands}}
+ (void)(b <= a); // expected-error {{invalid operands}}
+ (void)(b >= a); // expected-error {{invalid operands}}
(void)(a == pi);
(void)(a != pi);
- // FIXME: These cases were intended to be made ill-formed by N3624, but it
- // fails to actually achieve this goal.
- (void)(a < pi);
- (void)(a > pi);
- (void)(a <= pi);
- (void)(a >= pi);
+ (void)(a < pi); // expected-error {{invalid operands}}
+ (void)(a > pi); // expected-error {{invalid operands}}
+ (void)(a <= pi); // expected-error {{invalid operands}}
+ (void)(a >= pi); // expected-error {{invalid operands}}
(void)(pi == a);
(void)(pi != a);
- // FIXME: These cases were intended to be made ill-formed by N3624, but it
- // fails to actually achieve this goal.
- (void)(pi < a);
- (void)(pi > a);
- (void)(pi <= a);
- (void)(pi >= a);
+ (void)(pi < a); // expected-error {{invalid operands}}
+ (void)(pi > a); // expected-error {{invalid operands}}
+ (void)(pi <= a); // expected-error {{invalid operands}}
+ (void)(pi >= a); // expected-error {{invalid operands}}
(void)(b == pi);
(void)(b != pi);
diff --git a/test/CXX/over/over.match/over.match.funcs/p4-0x.cpp b/test/CXX/over/over.match/over.match.funcs/p4-0x.cpp
index 68c79900b951..df7762703c0f 100644
--- a/test/CXX/over/over.match/over.match.funcs/p4-0x.cpp
+++ b/test/CXX/over/over.match/over.match.funcs/p4-0x.cpp
@@ -1,5 +1,4 @@
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
-// expected-no-diagnostics
template<typename T> T &lvalue();
template<typename T> T &&xvalue();
@@ -20,6 +19,18 @@ struct X0 {
void g();
+ void c() const; // expected-note {{'c' declared here}}
+ void v() volatile; // expected-note {{'v' declared here}}
+ void r() __restrict__; // expected-note {{'r' declared here}}
+ void cr() const __restrict__; // expected-note {{'cr' declared here}}
+ void cv() const volatile;
+ void vr() volatile __restrict__; // expected-note {{'vr' declared here}}
+ void cvr() const volatile __restrict__;
+
+ void lvalue() &; // expected-note 2 {{'lvalue' declared here}}
+ void const_lvalue() const&;
+ void rvalue() &&; // expected-note {{'rvalue' declared here}}
+
int &operator+(const X0&) &;
float &operator+(const X0&) &&;
@@ -32,7 +43,7 @@ struct X0 {
float &h2() const&&;
};
-void X0::g() {
+void X0::g() { // expected-note {{'g' declared here}}
int &ir1 = f();
int &ir2 = X0::f();
}
@@ -69,3 +80,26 @@ void test_ref_qualifier_overloading() {
float &fr3 = xvalue<X0>().h2();
float &fr4 = prvalue<X0>().h2();
}
+
+void test_diagnostics(const volatile X0 &__restrict__ cvr) {
+ cvr.g(); // expected-error {{'this' argument to member function 'g' has type 'const volatile X0', but function is not marked const or volatile}}
+ cvr.c(); // expected-error {{not marked volatile}}
+ cvr.v(); // expected-error {{not marked const}}
+ cvr.r(); // expected-error {{not marked const or volatile}}
+ cvr.cr(); // expected-error {{not marked volatile}}
+ cvr.cv();
+ cvr.vr(); // expected-error {{not marked const}}
+ cvr.cvr();
+
+ lvalue<X0>().lvalue();
+ lvalue<X0>().const_lvalue();
+ lvalue<X0>().rvalue(); // expected-error {{'this' argument to member function 'rvalue' is an lvalue, but function has rvalue ref-qualifier}}
+
+ xvalue<X0>().lvalue(); // expected-error {{'this' argument to member function 'lvalue' is an rvalue, but function has non-const lvalue ref-qualifier}}
+ xvalue<X0>().const_lvalue();
+ xvalue<X0>().rvalue();
+
+ prvalue<X0>().lvalue(); // expected-error {{'this' argument to member function 'lvalue' is an rvalue, but function has non-const lvalue ref-qualifier}}
+ prvalue<X0>().const_lvalue();
+ prvalue<X0>().rvalue();
+}
diff --git a/test/CXX/special/class.copy/p11.0x.copy.cpp b/test/CXX/special/class.copy/p11.0x.copy.cpp
index 1ca0143d0930..e7256bcf9485 100644
--- a/test/CXX/special/class.copy/p11.0x.copy.cpp
+++ b/test/CXX/special/class.copy/p11.0x.copy.cpp
@@ -121,13 +121,21 @@ extern HasNoAccessDtorBase HNADBa;
HasNoAccessDtorBase HNADBb(HNADBa); // expected-error{{implicitly-deleted copy constructor}}
// -- a non-static data member of rvalue reference type
+int some_int;
struct RValue {
- int && ri = 1; // expected-note{{copy constructor of 'RValue' is implicitly deleted because field 'ri' is of rvalue reference type 'int &&'}}
- // expected-warning@-1{{binding reference member 'ri' to a temporary}} expected-note@-1 {{here}}
+ int && ri = static_cast<int&&>(some_int); // expected-note{{copy constructor of 'RValue' is implicitly deleted because field 'ri' is of rvalue reference type 'int &&'}}
};
RValue RVa;
RValue RVb(RVa); // expected-error{{call to implicitly-deleted copy constructor}}
+// FIXME: The error on the class-name is attached to the location of the
+// constructor. This is not especially clear.
+struct RValueTmp { // expected-error {{reference member 'ri' binds to a temporary}}
+ int && ri = 1; // expected-note{{copy constructor of 'RValueTmp' is implicitly deleted because field 'ri' is of rvalue reference type 'int &&'}} // expected-note {{default member init}}
+};
+RValueTmp RVTa; // expected-note {{implicit default constructor for 'RValueTmp' first required here}}
+RValueTmp RVTb(RVTa); // expected-error{{call to implicitly-deleted copy constructor}}
+
namespace PR13381 {
struct S {
S(const S&);
diff --git a/test/CXX/special/class.copy/p11.0x.move.cpp b/test/CXX/special/class.copy/p11.0x.move.cpp
index ab4259548e74..5b016836e9ef 100644
--- a/test/CXX/special/class.copy/p11.0x.move.cpp
+++ b/test/CXX/special/class.copy/p11.0x.move.cpp
@@ -145,7 +145,7 @@ HasNoAccessDtorBase HNADBb(HNADBa); // expected-error{{implicitly-deleted copy c
// The restriction on rvalue reference members applies to only the copy
// constructor.
struct RValue {
- int &&ri = 1; // expected-warning {{binding reference member 'ri' to a temporary}} expected-note {{here}}
+ int &&ri = 1;
RValue(RValue&&);
};
RValue::RValue(RValue&&) = default;
diff --git a/test/CXX/special/class.ctor/p5-0x.cpp b/test/CXX/special/class.ctor/p5-0x.cpp
index 2360345a4846..061a3d1f0738 100644
--- a/test/CXX/special/class.ctor/p5-0x.cpp
+++ b/test/CXX/special/class.ctor/p5-0x.cpp
@@ -43,8 +43,12 @@ class NotDeleted2a { int &a = n; };
NotDeleted2a nd2a;
class NotDeleted2b { int &a = error; }; // expected-error {{undeclared identifier}}
NotDeleted2b nd2b;
-class NotDeleted2c { int &&a = 0; }; // expected-warning {{binding reference member 'a' to a temporary}} expected-note {{here}}
+class NotDeleted2c { int &&a = static_cast<int&&>(n); };
NotDeleted2c nd2c;
+// Note: this one does not have a deleted default constructor even though the
+// implicit default constructor is ill-formed!
+class NotDeleted2d { int &&a = 0; }; // expected-error {{reference member 'a' binds to a temporary object}} expected-note {{default member init}}
+NotDeleted2d nd2d; // expected-note {{first required here}}
// - any non-variant non-static data member of const qualified type (or array
// thereof) with no brace-or-equal-initializer does not have a user-provided
diff --git a/test/CXX/special/class.inhctor/p1.cpp b/test/CXX/special/class.inhctor/p1.cpp
index 45f6049b4598..842b725cb0b3 100644
--- a/test/CXX/special/class.inhctor/p1.cpp
+++ b/test/CXX/special/class.inhctor/p1.cpp
@@ -3,7 +3,7 @@
// Note: [class.inhctor] was removed by P0136R1. This tests the new behavior
// for the wording that used to be there.
-struct A { // expected-note 4{{candidate is the implicit}}
+struct A { // expected-note 4{{candidate constructor (the implicit}}
A(...); // expected-note 4{{candidate constructor}} expected-note 4{{candidate inherited constructor}}
A(int = 0, int = 0, int = 0, int = 0, ...); // expected-note 3{{candidate constructor}} expected-note 3{{candidate inherited constructor}}
A(int = 0, int = 0, ...); // expected-note 3{{candidate constructor}} expected-note 3{{candidate inherited constructor}}
@@ -14,7 +14,7 @@ struct A { // expected-note 4{{candidate is the implicit}}
template<typename T, int N> A(const T (&)[N], int = 0); // expected-note {{candidate constructor}} expected-note {{candidate inherited constructor}}
};
-struct B : A { // expected-note 4{{candidate is the implicit}}
+struct B : A { // expected-note 4{{candidate constructor (the implicit}}
using A::A; // expected-note 15{{inherited here}}
B(void*);
};
diff --git a/test/CXX/special/class.init/class.inhctor.init/p1.cpp b/test/CXX/special/class.init/class.inhctor.init/p1.cpp
index 1f4362740b00..87fb195604d3 100644
--- a/test/CXX/special/class.init/class.inhctor.init/p1.cpp
+++ b/test/CXX/special/class.init/class.inhctor.init/p1.cpp
@@ -114,7 +114,7 @@ namespace constexpr_init_order {
constexpr B b(1);
constexpr B c(1);
static_assert(b.a == 1, "p should be initialized before B() is executed");
- static_assert(c.a == 7, "b not initialzed properly");
+ static_assert(c.a == 7, "b not initialized properly");
}
namespace default_args {
diff --git a/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp b/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
index ad6086835876..34202494c0d8 100644
--- a/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
+++ b/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
@@ -215,7 +215,7 @@ template void h<A(&)[13], int>(A(&)[13]); // expected-note {{requested here}}
template<typename T>
void i(T t) {
for (auto u : t) { // expected-error {{invalid range expression of type 'X::A *'; no viable 'begin' function available}} \
- expected-error {{member function 'begin' not viable}} \
+ expected-error {{'this' argument to member function 'begin' has type 'const X::A', but function is not marked const}} \
expected-note {{when looking up 'begin' function}}
}
diff --git a/test/CXX/stmt.stmt/stmt.select/p3.cpp b/test/CXX/stmt.stmt/stmt.select/p3.cpp
index 35e5c919fb6c..7a6a408ec955 100644
--- a/test/CXX/stmt.stmt/stmt.select/p3.cpp
+++ b/test/CXX/stmt.stmt/stmt.select/p3.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++1z -Wc++14-compat -verify %s -DCPP17
int f();
@@ -10,10 +11,67 @@ void g() {
}
}
-
void h() {
if (int x = f()) // expected-note 2{{previous definition}}
int x; // expected-error{{redefinition of 'x'}}
else
int x; // expected-error{{redefinition of 'x'}}
}
+
+void ifInitStatement() {
+ int Var = 0;
+
+ if (int I = 0; true) {}
+ if (Var + Var; true) {}
+ if (; true) {}
+#ifdef CPP17
+ // expected-warning@-4 {{if initialization statements are incompatible with C++ standards before C++17}}
+ // expected-warning@-4 {{if initialization statements are incompatible with C++ standards before C++17}}
+ // expected-warning@-4 {{if initialization statements are incompatible with C++ standards before C++17}}
+#else
+ // expected-warning@-8 {{'if' initialization statements are a C++17 extension}}
+ // expected-warning@-8 {{'if' initialization statements are a C++17 extension}}
+ // expected-warning@-8 {{'if' initialization statements are a C++17 extension}}
+#endif
+}
+
+void switchInitStatement() {
+ int Var = 0;
+
+ switch (int I = 0; Var) {}
+ switch (Var + Var; Var) {}
+ switch (; Var) {}
+#ifdef CPP17
+ // expected-warning@-4 {{switch initialization statements are incompatible with C++ standards before C++17}}
+ // expected-warning@-4 {{switch initialization statements are incompatible with C++ standards before C++17}}
+ // expected-warning@-4 {{switch initialization statements are incompatible with C++ standards before C++17}}
+#else
+ // expected-warning@-8 {{'switch' initialization statements are a C++17 extension}}
+ // expected-warning@-8 {{'switch' initialization statements are a C++17 extension}}
+ // expected-warning@-8 {{'switch' initialization statements are a C++17 extension}}
+#endif
+}
+
+// TODO: Better diagnostics for while init statements.
+void whileInitStatement() {
+ while (int I = 10; I--); // expected-error {{expected ')'}}
+ // expected-note@-1 {{to match this '('}}
+ // expected-error@-2 {{use of undeclared identifier 'I'}}
+
+ int Var = 10;
+ while (Var + Var; Var--) {} // expected-error {{expected ')'}}
+ // expected-note@-1 {{to match this '('}}
+ // expected-error@-2 {{expected ';' after expression}}
+ // expected-error@-3 {{expected expression}}
+ // expected-warning@-4 {{while loop has empty body}}
+ // expected-note@-5 {{put the semicolon on a separate line to silence this warning}}
+}
+
+// TODO: This is needed because clang can't seem to diagnose invalid syntax after the
+// last loop above. It would be nice to remove this.
+void whileInitStatement2() {
+ while (; false) {} // expected-error {{expected expression}}
+ // expected-warning@-1 {{expression result unused}}
+ // expected-error@-2 {{expected ';' after expression}}
+ // expected-error@-3 {{expected expression}}
+}
diff --git a/test/CXX/temp/temp.decls/temp.friend/p1.cpp b/test/CXX/temp/temp.decls/temp.friend/p1.cpp
index f1f3f7016242..849728a448bd 100644
--- a/test/CXX/temp/temp.decls/temp.friend/p1.cpp
+++ b/test/CXX/temp/temp.decls/temp.friend/p1.cpp
@@ -359,3 +359,31 @@ namespace PR10913 {
template void f2<int>(X<int> *);
template void f2<float>(X<int> *); // expected-note{{in instantiation of function template specialization 'PR10913::f2<float, int>' requested here}}
}
+
+namespace test16 {
+template <class T> struct foo {}; // expected-note{{candidate ignored: not a function template}}
+template <class T> class A {
+ friend void foo<T>(); // expected-error{{no candidate function template was found for dependent friend function template specialization}}
+};
+}
+
+namespace test17 {
+namespace ns {
+template <class T> void foo() {} // expected-note{{candidate ignored: not a member of the enclosing namespace; did you mean to explicitly qualify the specialization?}}
+}
+using ns::foo;
+template <class T> struct A {
+ friend void foo<T>() {} // expected-error{{no candidate function template was found for dependent friend function template specialization}}
+};
+}
+
+namespace test18 {
+namespace ns1 { template <class T> struct foo {}; } // expected-note{{candidate ignored: not a function template}}
+namespace ns2 { void foo() {} } // expected-note{{candidate ignored: not a function template}}
+using ns1::foo;
+using ns2::foo;
+
+template <class T> class A {
+ friend void foo<T>() {} // expected-error{{no candidate function template was found for dependent friend function template specialization}}
+};
+}
diff --git a/test/CXX/temp/temp.deduct.guide/p1.cpp b/test/CXX/temp/temp.deduct.guide/p1.cpp
index c0a2ba1129e2..8bb9da8a9723 100644
--- a/test/CXX/temp/temp.deduct.guide/p1.cpp
+++ b/test/CXX/temp/temp.deduct.guide/p1.cpp
@@ -101,7 +101,7 @@ namespace ExplicitInst {
struct X {
template<typename T> struct C {};
template<typename T> C(T) -> C<T>;
- template<> C(int) -> C<int>; // expected-error {{explicit specialization of '<deduction guide for C>' in class scope}}
+ template<> C(int) -> C<int>; // expected-error {{deduction guide cannot be explicitly specialized}}
extern template C(float) -> C<float>; // expected-error {{expected member name or ';'}}
template C(char) -> C<char>; // expected-error {{expected '<' after 'template'}}
};
diff --git a/test/CXX/temp/temp.deduct.guide/p3.cpp b/test/CXX/temp/temp.deduct.guide/p3.cpp
index e12f7b6ef255..07d1be0593f4 100644
--- a/test/CXX/temp/temp.deduct.guide/p3.cpp
+++ b/test/CXX/temp/temp.deduct.guide/p3.cpp
@@ -65,8 +65,8 @@ namespace WrongScope {
};
template<typename T> struct Local {};
void f() {
- Local(int) -> Local<int>; // expected-error 2{{expected}} expected-note {{to match}}
+ Local(int) -> Local<int>; // expected-error {{expected}}
using WrongScope::Local;
- Local(int) -> Local<int>; // expected-error 2{{expected}} expected-note {{to match}}
+ Local(int) -> Local<int>; // expected-error {{expected}}
}
}
diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp
index b45ed96d1445..085976b08133 100644
--- a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp
+++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp
@@ -1,4 +1,6 @@
// RUN: %clang_cc1 -fsyntax-only %s -verify
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s -verify
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only %s -verify
struct AnyT {
template<typename T>
@@ -62,3 +64,86 @@ void test_deduce_two_level_ptrmem_with_qual(TwoLevelPtrMem apm) {
// deduce T = 'const double'
const double X::* X::* pm1 = apm; // expected-note {{instantiation of}}
}
+
+namespace non_ptr_ref_cv_qual {
+ template<typename Expected>
+ struct ConvToT {
+ template<typename T> operator T() {
+ using Check = T;
+ using Check = Expected;
+ }
+ };
+ const int test_conv_to_t_1 = ConvToT<int>();
+ // We intentionally deviate from [temp.deduct.conv]p4 here, and also remove
+ // the top-level cv-quaifiers from A *after* removing the reference type, if
+ // P is not also a reference type. This matches what other compilers are
+ // doing, and is necessary to support real-world code.
+ const int &test_conv_to_t_2 = ConvToT<int>();
+
+ // Example code that would be broken by the standard's rule.
+ struct Dest {};
+ Dest d1a((ConvToT<Dest>()));
+ Dest d1b = ConvToT<Dest>();
+ Dest &d2 = (d1a = ConvToT<Dest>());
+
+ template<typename Expected>
+ struct ConvToTRef {
+ template<typename T> operator T&() {
+ using Check = T;
+ using Check = Expected;
+ }
+ };
+ const int test_conv_to_t_ref_1 = ConvToTRef<int>();
+ const int &test_conv_to_t_ref_2 = ConvToTRef<const int>();
+
+ Dest d3a((ConvToTRef<const Dest>())); // initialize the copy ctor parameter with 'const Dest&'
+ Dest d3b = ConvToTRef<Dest>(); // convert to non-const T via [over.match.copy]/1.2
+ Dest &d4 = (d3a = ConvToTRef<const Dest>());
+
+ template<typename Expected>
+ struct ConvToConstT {
+ template<typename T> operator const T() {
+ using Check = T;
+ using Check = Expected;
+ }
+ };
+ const int test_conv_to_const_t_1 = ConvToConstT<int>();
+ const int &test_conv_to_const_t_2 = ConvToConstT<int>();
+
+ template<typename Expected>
+ struct ConvToConstTRef {
+ template<typename T> operator const T&() {
+ using Check = T;
+ using Check = Expected;
+ }
+ };
+ const int test_conv_to_const_t_ref_1 = ConvToConstTRef<int>();
+ const int &test_conv_to_const_t_ref_2 = ConvToConstTRef<int>();
+
+ template <typename T, int N> using Arr = T[N];
+ struct ConvToArr {
+ template <int N>
+ operator Arr<int, N> &() {
+ static_assert(N == 3, "");
+ }
+ };
+ int (&test_conv_to_arr_1)[3] = ConvToArr(); // ok
+ const int (&test_conv_to_arr_2)[3] = ConvToArr(); // ok, with qualification conversion
+
+#if __cplusplus >= 201702L
+ template<bool Noexcept, typename T, typename ...U> using Function = T(U...) noexcept(Noexcept);
+ template<bool Noexcept> struct ConvToFunction {
+ template <typename T, typename ...U> operator Function<Noexcept, T, U...>&(); // expected-note {{candidate}}
+ };
+ void (&fn1)(int) noexcept(false) = ConvToFunction<false>();
+ void (&fn2)(int) noexcept(true) = ConvToFunction<false>(); // expected-error {{no viable}}
+ void (&fn3)(int) noexcept(false) = ConvToFunction<true>();
+ void (&fn4)(int) noexcept(true) = ConvToFunction<true>();
+
+ struct ConvToFunctionDeducingNoexcept {
+ template <bool Noexcept, typename T, typename ...U> operator Function<Noexcept, T, U...>&();
+ };
+ void (&fn5)(int) noexcept(false) = ConvToFunctionDeducingNoexcept();
+ void (&fn6)(int) noexcept(true) = ConvToFunctionDeducingNoexcept();
+#endif
+}
diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p1.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p1.cpp
new file mode 100644
index 000000000000..33d8182ab14e
--- /dev/null
+++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p1.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -verify %s
+
+// an attempt is made to find template argument values that will make P, after
+// substitution of the deduced values, compatible with A
+
+namespace cv_mismatch {
+ template<typename> struct X {};
+ template<typename T> void f(X<const T>); // expected-note {{cannot deduce a type for 'T' that would make 'const T' equal 'volatile int'}}
+ void g() { f(X<volatile int>()); } // expected-error {{no matching}}
+}
diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p5-0x.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p5-0x.cpp
index d239a5e17200..697412995b33 100644
--- a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p5-0x.cpp
+++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p5-0x.cpp
@@ -1,5 +1,4 @@
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
-// expected-no-diagnostics
// FIXME: More bullets to go!
@@ -16,8 +15,23 @@ struct has_nondeduced_pack_test<R(FirstType, Types..., int),
// - A function parameter pack that does not occur at the end of the
// parameter-declaration-clause.
+//
+// We interpret [temp.deduct.call]p1's
+//
+// "When a function parameter pack appears in a non-deduced context
+// (12.9.2.5), the type of that pack is never deduced."
+//
+// as applying in all deduction contexts, not just [temp.deduct.call],
+// so we do *not* deduce Types from the second argument here. (More
+// precisely, we deduce it as <> when processing the first argument,
+// and then fail because 'int' doesn't match 'double, int'.)
int check_nondeduced_pack_test0[
has_nondeduced_pack_test<int(float, double, int),
- int(float, double)>::value? 1 : -1];
+ int(float, double)>::value? -1 : 1];
+template<typename ...T> void has_non_trailing_pack(T ..., int);
+void (*ptr_has_non_trailing_pack)(char, int) = has_non_trailing_pack<char>;
+template<typename ...T, typename U> void has_non_trailing_pack_and_more(T ..., U); // expected-note {{failed}}
+void (*ptr_has_non_trailing_pack_and_more_1)(float, double, int) = &has_non_trailing_pack_and_more<float, double>;
+void (*ptr_has_non_trailing_pack_and_more_2)(float, double, int) = &has_non_trailing_pack_and_more<float>; // expected-error {{does not match}}
diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp
index 54a54b0c486b..fccac8f1e5a4 100644
--- a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp
+++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp
@@ -35,6 +35,44 @@ namespace PackExpansionNotAtEnd {
struct UselessPartialSpec<Types..., Tail>; // expected-error{{class template partial specialization contains template parameters that cannot be deduced; this partial specialization will never be used}}
}
+// When a pack expansion occurs within a template argument list, the entire
+// list is a non-deduced context. For the corresponding case in a function
+// parameter list, only that parameter is non-deduced.
+//
+// FIXME: It's not clear that this difference is intended, but the wording is
+// explicit.
+namespace PackExpansionNotAtEndFunctionVersusTemplate {
+ template<typename ...T> struct X {};
+ template<typename ...T, typename U> void f1(void(T..., U));
+ // expected-note@+1 {{couldn't infer template argument 'U'}}
+ template<typename ...T, typename U> void f2(X<T..., U>); // FIXME: ill-formed, U is not deducible
+
+ void g(int, int, int);
+ X<int, int, int> h;
+ void test() {
+ // This is deducible: the T... parameter is a non-deduced context, but
+ // that's OK because we don't need to deduce it.
+ f1<int, int>(g);
+ // This is not deducible: the T... parameter renders the entire
+ // template-argument-list a non-deduced context, so U is not deducible.
+ f2<int, int>(h); // expected-error {{no matching function}}
+ }
+
+ template<typename T> struct Y;
+ template<typename ...T, // expected-note {{non-deducible template parameter 'T'}}
+ typename U>
+ struct Y<void(T..., U)> {}; // expected-error {{cannot be deduced}}
+ template<typename ...T, // expected-note {{non-deducible template parameter 'T'}}
+ typename U> // expected-note {{non-deducible template parameter 'U'}}
+ struct Y<X<T..., U>>; // expected-error {{cannot be deduced}}
+ // FIXME: T is not deducible here, due to [temp.deduct.call]p1:
+ // "When a function parameter pack appears in a non-deduced context,
+ // the type of that pack is never deduced."
+ template<typename ...T,
+ typename U>
+ struct Y<void(T..., U, T...)> {};
+}
+
namespace DeduceNonTypeTemplateArgsInArray {
template<typename ...ArrayTypes>
struct split_arrays;
diff --git a/test/CXX/temp/temp.param/p2.cpp b/test/CXX/temp/temp.param/p2.cpp
index 20e0b8ef35f8..656bd26ff08d 100644
--- a/test/CXX/temp/temp.param/p2.cpp
+++ b/test/CXX/temp/temp.param/p2.cpp
@@ -15,29 +15,29 @@ template<typename T, typename X<T>::type Value> struct Y1;
// A storage class shall not be specified in a template-parameter declaration.
template<static int Value> struct Z; //expected-error{{invalid declaration specifier}}
-template<typedef int Value> struct Z0; //expected-error{{invalid declaration specifier}}
-template<extern inline int Value> struct Z0; //expected-error2{{invalid declaration specifier}}
-template<virtual int Value> struct Z0; //expected-error{{invalid declaration specifier}}
-template<explicit int Value> struct Z0; //expected-error{{invalid declaration specifier}}
-template<inline int Value> struct Z0; //expected-error{{invalid declaration specifier}}
-template<extern int> struct Z0; //expected-error{{invalid declaration specifier}}
-template<static int> struct Z0; //expected-error{{invalid declaration specifier}}
-template<explicit int Value> struct Z0; //expected-error{{invalid declaration specifier}}
-template<mutable int> struct Z0; //expected-error{{invalid declaration specifier}}
+template<typedef int Value> struct Z0; //expected-error{{expected template parameter}} expected-error{{expected identifier}} expected-error{{extraneous 'template<>' in declaration of struct 'Z0'}} expected-note{{did you mean to use 'typename'?}}
+template<extern inline int Value> struct Z1; //expected-error2{{invalid declaration specifier}}
+template<virtual int Value> struct Z2; //expected-error{{invalid declaration specifier}}
+template<explicit int Value> struct Z3; //expected-error{{invalid declaration specifier}}
+template<inline int Value> struct Z4; //expected-error{{invalid declaration specifier}}
+template<extern int> struct Z5; //expected-error{{invalid declaration specifier}}
+template<static int> struct Z6; //expected-error{{invalid declaration specifier}}
+template<explicit int Value> struct Z7; //expected-error{{invalid declaration specifier}}
+template<mutable int> struct Z8; //expected-error{{invalid declaration specifier}}
-template<const int> struct Z0; // OK
-template<volatile int> struct Z0; // OK
+template<const int> struct Z9; // OK
+template<volatile int> struct Z10; // OK
#ifdef CPP11
-template<thread_local int> struct Z0; //expected-error{{invalid declaration specifier}}
-template<constexpr int> struct Z0; //expected-error{{invalid declaration specifier}}
+template<thread_local int> struct Z11; //expected-error{{invalid declaration specifier}}
+template<constexpr int> struct Z12; //expected-error{{invalid declaration specifier}}
#endif
#ifdef CPP17
-template<auto> struct Z1; // OK
+template<auto> struct Z13; // OK
#endif
// Make sure that we properly disambiguate non-type template parameters that
diff --git a/test/CXX/temp/temp.param/p5.cpp b/test/CXX/temp/temp.param/p5.cpp
index aa0d7e92b9ec..4cb2d4343a33 100644
--- a/test/CXX/temp/temp.param/p5.cpp
+++ b/test/CXX/temp/temp.param/p5.cpp
@@ -1,13 +1,13 @@
// RUN: %clang_cc1 -verify %s -std=c++14
-template<const int I> struct S {
+template<const int I> struct S { // expected-error {{reference member 'r' binds to a temporary object}}
decltype(I) n;
- int &&r = I; // expected-warning 2{{binding reference member 'r' to a temporary value}} expected-note 2{{declared here}}
+ int &&r = I; // expected-note {{default member initializer}}
};
-S<5> s; // expected-note {{instantiation}}
+S<5> s; // expected-note {{implicit default constructor}}
-template<typename T, T v> struct U {
+template<typename T, T v> struct U { // expected-error {{reference member 'r' binds to a temporary object}}
decltype(v) n;
- int &&r = v; // expected-warning {{binding reference member 'r' to a temporary value}} expected-note {{declared here}}
+ int &&r = v; // expected-note {{default member initializer}}
};
-U<const int, 6> u; // expected-note {{instantiation}}
+U<const int, 6> u; // expected-note {{implicit default constructor}}
diff --git a/test/CXX/temp/temp.res/p3.cpp b/test/CXX/temp/temp.res/p3.cpp
index ea87b8d10546..8984ce349496 100644
--- a/test/CXX/temp/temp.res/p3.cpp
+++ b/test/CXX/temp/temp.res/p3.cpp
@@ -34,5 +34,5 @@ template<typename T> template<typename U> struct A<T>::B {
// a type, and then complain about the rest of the tokens, and then complain
// that we didn't get a function declaration.
friend A<U>::C<T> f7(); // expected-error {{use 'template' keyword to treat 'C' as a dependent template name}} expected-error 3{{}}
- friend A<U>::template C<T> f8(); // expected-error 3{{}}
+ friend A<U>::template C<T> f8(); // expected-error 4{{}}
};
diff --git a/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp b/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp
index 425d527e5212..741ebc5de41f 100644
--- a/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp
+++ b/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp
@@ -28,10 +28,8 @@ T pi1 = T(3.1415926535897932385); // expected-note 0-2 {{here}}
// Should recover as if specialization
template float pi1<float> = 1.0; // expected-error {{explicit template instantiation cannot have a definition; if this definition is meant to be an explicit specialization, add '<>' after the 'template' keyword}}
-#ifndef FIXING
namespace expected_global {
- template<> double pi1<double> = 1.5; // expected-error {{variable template specialization of 'pi1' must originally be declared in the global scope}}
- template int pi1<int> = 10; // expected-error {{explicit template instantiation cannot have a definition; if this definition is meant to be an explicit specialization, add '<>' after the 'template' keyword}} \
- expected-error {{variable template specialization of 'pi1' must originally be declared in the global scope}}
-}
+#ifndef FIXING
+ template int pi1<int> = 10; // expected-error {{explicit template instantiation cannot have a definition; if this definition is meant to be an explicit specialization, add '<>' after the 'template' keyword}} expected-error {{must occur at global scope}}
#endif
+}
diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp
index d0e24f547723..c29646dd9455 100644
--- a/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp
+++ b/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp
@@ -10,9 +10,6 @@ struct NonDefaultConstructible {
NonDefaultConstructible(int);
};
-// FIXME: The "must originally be declared in namespace" diagnostics throughout
-// this file are wrong.
-
// C++ [temp.expl.spec]p1:
// An explicit specialization of any of the following:
@@ -43,7 +40,7 @@ template<> void N0::f0(double) { }
struct X1 {
template<typename T> void f(T);
- template<> void f(int); // expected-error{{in class scope}}
+ template<> void f(int); // OK (DR727)
};
// -- class template
@@ -94,7 +91,7 @@ template<> struct N0::X0<volatile void> {
// -- variable template [C++1y]
namespace N0 {
-template<typename T> int v0; // expected-note +{{here}}
+template<typename T> int v0; // expected-note 4{{explicitly specialized declaration is here}}
template<> extern int v0<char[1]>;
template<> extern int v0<char[2]>;
template<> extern int v0<char[5]>;
@@ -102,32 +99,32 @@ template<> extern int v0<char[6]>;
}
using N0::v0;
-template<typename T> int v1; // expected-note +{{here}}
+template<typename T> int v1; // expected-note 4{{explicitly specialized declaration is here}}
template<> extern int v1<char[3]>;
template<> extern int v1<char[4]>;
template<> extern int v1<char[7]>;
template<> extern int v1<char[8]>;
template<> int N0::v0<int[1]>;
-template<> int v0<int[2]>; // FIXME: ill-formed
+template<> int v0<int[2]>;
template<> int ::v1<int[3]>; // expected-warning {{extra qualification}}
template<> int v1<int[4]>;
template<> int N0::v0<char[1]>;
-template<> int v0<char[2]>; // FIXME: ill-formed
+template<> int v0<char[2]>;
template<> int ::v1<char[3]>; // expected-warning {{extra qualification}}
template<> int v1<char[4]>;
namespace N1 {
-template<> int N0::v0<int[5]>; // expected-error {{must originally be declared in namespace 'N0'}} expected-error {{does not enclose namespace}}
-template<> int v0<int[6]>; // expected-error {{must originally be declared in namespace 'N0'}}
-template<> int ::v1<int[7]>; // expected-error {{must originally be declared in the global scope}} expected-error {{cannot name the global scope}}
-template<> int v1<int[8]>; // expected-error {{must originally be declared in the global scope}}
-
-template<> int N0::v0<char[5]>; // expected-error {{does not enclose namespace 'N0'}}
-template<> int v0<char[6]>; // FIXME: ill-formed
-template<> int ::v1<char[7]>; // expected-error {{cannot name the global scope}}
-template<> int v1<char[8]>; // FIXME: ill-formed
+template<> int N0::v0<int[5]>; // expected-error {{not in a namespace enclosing 'N0'}}
+template<> int v0<int[6]>; // expected-error {{not in a namespace enclosing 'N0'}}
+template<> int ::v1<int[7]>; // expected-error {{must occur at global scope}}
+template<> int v1<int[8]>; // expected-error {{must occur at global scope}}
+
+template<> int N0::v0<char[5]>; // expected-error {{not in a namespace enclosing 'N0'}}
+template<> int v0<char[6]>; // expected-error {{not in a namespace enclosing 'N0'}}
+template<> int ::v1<char[7]>; // expected-error {{must occur at global scope}}
+template<> int v1<char[8]>; // expected-error {{must occur at global scope}}
}
// -- member function of a class template
diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp
index 21399b62046d..904f950df443 100644
--- a/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp
+++ b/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp
@@ -20,9 +20,6 @@ struct NonDefaultConstructible {
// -- function template
namespace N0 {
template<typename T> void f0(T) {
-#if __cplusplus <= 199711L
- // expected-note@-2 {{explicitly specialized declaration is here}}
-#endif
T t;
}
@@ -43,16 +40,13 @@ namespace N1 {
}
template<> void N0::f0(double);
-#if __cplusplus <= 199711L
-// expected-warning@-2 {{first declaration of function template specialization of 'f0' outside namespace 'N0' is a C++11 extension}}
-#endif
template<> void N0::f0(double) { }
struct X1 {
template<typename T> void f(T);
- template<> void f(int); // expected-error{{in class scope}}
+ template<> void f(int);
};
// -- class template
@@ -60,38 +54,20 @@ namespace N0 {
template<typename T>
struct X0 { // expected-note {{explicitly specialized declaration is here}}
-#if __cplusplus <= 199711L
-// expected-note@-2 {{explicitly specialized declaration is here}}
-#endif
static T member;
-#if __cplusplus <= 199711L
- // expected-note@-2 {{explicitly specialized declaration is here}}
-#endif
void f1(T t) {
-#if __cplusplus <= 199711L
- // expected-note@-2 {{explicitly specialized declaration is here}}
-#endif
t = 17;
}
struct Inner : public T { }; // expected-note 2{{explicitly specialized declaration is here}}
-#if __cplusplus <= 199711L
- // expected-note@-2 {{explicitly specialized declaration is here}}
-#endif
template<typename U>
struct InnerTemplate : public T { }; // expected-note {{explicitly specialized declaration is here}}
-#if __cplusplus <= 199711L
- // expected-note@-2 {{explicitly specialized declaration is here}}
-#endif
- // expected-error@-4 {{base specifier must name a class}}
+ // expected-error@-1 {{base specifier must name a class}}
template<typename U>
void ft1(T t, U u);
-#if __cplusplus <= 199711L
- // expected-note@-2 {{explicitly specialized declaration is here}}
-#endif
};
}
@@ -105,9 +81,6 @@ void N0::X0<T>::ft1(T t, U u) {
template<typename T> T N0::X0<T>::member;
template<> struct N0::X0<void> { };
-#if __cplusplus <= 199711L
-// expected-warning@-2 {{first declaration of class template specialization of 'X0' outside namespace 'N0' is a C++11 extension}}
-#endif
N0::X0<void> test_X0;
namespace N1 {
@@ -124,9 +97,6 @@ template<> struct N0::X0<volatile void> {
// -- member function of a class template
template<> void N0::X0<void*>::f1(void *) { }
-#if __cplusplus <= 199711L
-// expected-warning@-2 {{first declaration of member function specialization of 'f1' outside namespace 'N0' is a C++11 extension}}
-#endif
void test_spec(N0::X0<void*> xvp, void *vp) {
xvp.f1(vp);
@@ -160,9 +130,6 @@ NonDefaultConstructible &get_static_member() {
}
template<> int N0::X0<int>::member;
-#if __cplusplus <= 199711L
-// expected-warning@-2 {{first declaration of static data member specialization of 'member' outside namespace 'N0' is a C++11 extension}}
-#endif
template<> float N0::X0<float>::member = 3.14f;
@@ -191,9 +158,6 @@ namespace N0 {
template<>
struct N0::X0<long>::Inner { };
-#if __cplusplus <= 199711L
-// expected-warning@-2 {{first declaration of member class specialization of 'Inner' outside namespace 'N0' is a C++11 extension}}
-#endif
template<>
struct N0::X0<float>::Inner { };
@@ -233,9 +197,6 @@ struct N0::X0<int>::InnerTemplate<long> { }; // okay
template<> template<>
struct N0::X0<int>::InnerTemplate<float> { };
-#if __cplusplus <= 199711L
-// expected-warning@-2 {{first declaration of class template specialization of 'InnerTemplate' outside namespace 'N0' is a C++11 extension}}
-#endif
namespace N1 {
template<> template<>
@@ -268,9 +229,6 @@ void N0::X0<void*>::ft1(void *, unsigned) { } // okay
template<> template<>
void N0::X0<void*>::ft1(void *, float) { }
-#if __cplusplus <= 199711L
-// expected-warning@-2 {{first declaration of function template specialization of 'ft1' outside namespace 'N0' is a C++11 extension}}
-#endif
namespace N1 {
template<> template<>
@@ -293,6 +251,6 @@ namespace PR8979 {
template<typename T, typename U> void f(Inner<T, U>&);
typedef Inner<OtherInner, OtherInner> MyInner;
- template<> void f(MyInner&); // expected-error{{cannot specialize a function 'f' within class scope}}
+ template<> void f(MyInner&);
};
}
diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp
index d82691c7c868..ca55c54a5e92 100644
--- a/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp
+++ b/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp
@@ -4,17 +4,9 @@
namespace N {
template<class T> class X; // expected-note {{'N::X' declared here}}
-#if __cplusplus <= 199711L
- // expected-note@-2 {{explicitly specialized declaration is here}}
-#endif
}
-// TODO: Don't add a namespace qualifier to the template if it would trigger
-// the warning about the specialization being outside of the namespace.
template<> class X<int> { /* ... */ }; // expected-error {{no template named 'X'; did you mean 'N::X'?}}
-#if __cplusplus <= 199711L
-// expected-warning@-2 {{first declaration of class template specialization of 'X' outside namespace 'N' is a C++11 extension}}
-#endif
namespace N {
diff --git a/test/CodeCompletion/Inputs/comments.h b/test/CodeCompletion/Inputs/comments.h
new file mode 100644
index 000000000000..7b4b5daa0bd5
--- /dev/null
+++ b/test/CodeCompletion/Inputs/comments.h
@@ -0,0 +1,4 @@
+// PR32732
+struct B {
+ // <- code completion
+};
diff --git a/test/CodeCompletion/comments.cpp b/test/CodeCompletion/comments.cpp
new file mode 100644
index 000000000000..21f1465ebc04
--- /dev/null
+++ b/test/CodeCompletion/comments.cpp
@@ -0,0 +1,13 @@
+// Note: the run lines follow their respective tests, since line/column
+// matter in this test.
+
+#include "comments.h"
+
+struct A {
+ // <- code completion
+ /* <- code completion */
+};
+
+// RUN: %clang_cc1 -I %S/Inputs -fsyntax-only -code-completion-at=%s:7:6 %s
+// RUN: %clang_cc1 -I %S/Inputs -fsyntax-only -code-completion-at=%s:8:6 %s
+// RUN: %clang_cc1 -I %S/Inputs -fsyntax-only -code-completion-at=%S/Inputs/comments.h:3:6 %s
diff --git a/test/CodeCompletion/crash-skipped-bodies-template-inst.cpp b/test/CodeCompletion/crash-skipped-bodies-template-inst.cpp
new file mode 100644
index 000000000000..6161f100cb55
--- /dev/null
+++ b/test/CodeCompletion/crash-skipped-bodies-template-inst.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:24:5 %s -o - 2>&1 | FileCheck %s
+template <class T>
+auto make_func() {
+ struct impl {
+ impl* func() {
+ int x;
+ if (x = 10) {}
+ // Check that body of this function is actually skipped.
+ // CHECK-NOT: crash-skipped-bodies-template-inst.cpp:7:{{[0-9]+}}: warning: using the result of an assignment as a condition without parentheses
+ return this;
+ }
+ };
+
+ int x;
+ if (x = 10) {}
+ // Check that this function is not skipped.
+ // CHECK: crash-skipped-bodies-template-inst.cpp:15:9: warning: using the result of an assignment as a condition without parentheses
+ return impl();
+}
+
+void foo() {
+ []() {
+ make_func<int>();
+ m
+ // CHECK: COMPLETION: make_func : [#auto#]make_func<<#class T#>>()
+ };
+}
diff --git a/test/CodeCompletion/ctor-initializer.cpp b/test/CodeCompletion/ctor-initializer.cpp
index e54b347f9fa4..e1a0d1436874 100644
--- a/test/CodeCompletion/ctor-initializer.cpp
+++ b/test/CodeCompletion/ctor-initializer.cpp
@@ -58,5 +58,9 @@ struct B {
// RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:57:9 %s -o - | FileCheck -check-prefix=CHECK-CC7 %s
// RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:57:9 %s -o - | FileCheck -check-prefix=CHECK-CC7 %s
// CHECK-CC7: COMPLETION: Pattern : member1(<#args#>
+ // Check in the middle and at the end of identifier too.
+ // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:57:13 %s -o - | FileCheck -check-prefix=CHECK-CC8 %s
+ // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:57:16 %s -o - | FileCheck -check-prefix=CHECK-CC8 %s
+ // CHECK-CC8: COMPLETION: Pattern : member2(<#args#>
int member1, member2;
};
diff --git a/test/CodeCompletion/enable-if-attr-crash.cpp b/test/CodeCompletion/enable-if-attr-crash.cpp
new file mode 100644
index 000000000000..cca84b28ecfb
--- /dev/null
+++ b/test/CodeCompletion/enable-if-attr-crash.cpp
@@ -0,0 +1,8 @@
+int foo(bool x) __attribute__((enable_if(x, "")));
+
+int test() {
+ bool fffffff;
+ // RUN: %clang_cc1 -std=c++11 -code-completion-at=%s:7:8 %s | FileCheck %s
+ // CHECK: COMPLETION: fffffff : [#bool#]fffffff
+ foo(ff
+}
diff --git a/test/CodeCompletion/end-of-file.cpp b/test/CodeCompletion/end-of-file.cpp
new file mode 100644
index 000000000000..178ef4561f56
--- /dev/null
+++ b/test/CodeCompletion/end-of-file.cpp
@@ -0,0 +1,7 @@
+// Check that clang does not crash when completing at the last char in the
+// buffer.
+// NOTE: This file must *NOT* have newline at the end.
+// RUN: %clang_cc1 -code-completion-at=%s:7:2 %s | FileCheck %s
+// CHECK: COMPLETION: foo
+using foo = int***;
+f \ No newline at end of file
diff --git a/test/CodeCompletion/end-of-ident-macro.cpp b/test/CodeCompletion/end-of-ident-macro.cpp
new file mode 100644
index 000000000000..f288979a2c4d
--- /dev/null
+++ b/test/CodeCompletion/end-of-ident-macro.cpp
@@ -0,0 +1,16 @@
+#define FUNC(X) X
+#define FUNCTOR
+using FUNCTION = int();
+// We should get all three completions when the cursor is at the beginning,
+// middle, or end.
+FUNC(int) a = 10;
+// ^FUNC(int)
+// RUN: %clang_cc1 -code-completion-at=%s:6:1 -code-completion-macros %s | FileCheck %s
+// FU^NC(int)
+// RUN: %clang_cc1 -code-completion-at=%s:6:3 -code-completion-macros %s | FileCheck %s
+// FUNC^(int)
+// RUN: %clang_cc1 -code-completion-at=%s:6:5 -code-completion-macros %s | FileCheck %s
+
+// CHECK: COMPLETION: FUNC : FUNC(<#X#>)
+// CHECK: COMPLETION: FUNCTION : FUNCTION
+// CHECK: COMPLETION: FUNCTOR : FUNCTOR \ No newline at end of file
diff --git a/test/CodeCompletion/end-of-ident.cpp b/test/CodeCompletion/end-of-ident.cpp
new file mode 100644
index 000000000000..f1d3700ce28d
--- /dev/null
+++ b/test/CodeCompletion/end-of-ident.cpp
@@ -0,0 +1,20 @@
+class classifier {};
+// We should get all three completions when the cursor is at the beginning,
+// middle, or end.
+class cls
+// ^class cls
+// RUN: %clang_cc1 -code-completion-at=%s:4:1 %s | FileCheck --check-prefix=CHECK-CLS %s
+// cl^ass cls
+// RUN: %clang_cc1 -code-completion-at=%s:4:3 %s | FileCheck --check-prefix=CHECK-CLS %s
+// class^ cls
+// RUN: %clang_cc1 -code-completion-at=%s:4:6 %s | FileCheck --check-prefix=CHECK-CLS %s
+
+// CHECK-CLS: COMPLETION: class{{$}}
+// CHECK-CLS: COMPLETION: classifier : classifier
+
+// class ^cls
+// RUN: %clang_cc1 -code-completion-at=%s:4:7 %s | FileCheck --check-prefix=CHECK-NO-CLS %s
+// class c^ls
+// RUN: %clang_cc1 -code-completion-at=%s:4:8 %s | FileCheck --check-prefix=CHECK-NO-CLS %s
+// CHECK-NO-CLS-NOT: COMPLETION: class{{$}}
+// CHECK-NO-CLS: COMPLETION: classifier : classifier
diff --git a/test/CodeCompletion/incomplete-ret-type.cpp b/test/CodeCompletion/incomplete-ret-type.cpp
new file mode 100644
index 000000000000..669105e1416a
--- /dev/null
+++ b/test/CodeCompletion/incomplete-ret-type.cpp
@@ -0,0 +1,13 @@
+struct IncompleteType;
+int int_value;
+typedef int int_typedef;
+
+void f(in);
+IncompleteType g(in);
+// Completing should produce results even if types are incomplete.
+// Note that clang is expected to return an error code since 'in' does not resolve.
+// RUN: not %clang_cc1 -fsyntax-only -code-completion-at=%s:5:9 %s -o - | FileCheck %s
+// RUN: not %clang_cc1 -fsyntax-only -code-completion-at=%s:6:19 %s -o - | FileCheck %s
+// CHECK: COMPLETION: int{{$}}
+// CHECK: COMPLETION: int_typedef
+// CHECK: COMPLETION: int_value
diff --git a/test/CodeCompletion/inside-macros.cpp b/test/CodeCompletion/inside-macros.cpp
new file mode 100644
index 000000000000..dc40c6ad318c
--- /dev/null
+++ b/test/CodeCompletion/inside-macros.cpp
@@ -0,0 +1,13 @@
+#define ID(X) X
+
+void test(bool input_var) {
+ ID(input_var) = true;
+ // Check that input_var shows up when completing at the start, in the middle
+ // and at the end of the identifier.
+ //
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:4:6 %s -o - | FileCheck %s
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:4:8 %s -o - | FileCheck %s
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:4:15 %s -o - | FileCheck %s
+
+ // CHECK: input_var
+}
diff --git a/test/CodeCompletion/macros.c b/test/CodeCompletion/macros.c
index 28f69b2e1b1f..3cbad800202c 100644
--- a/test/CodeCompletion/macros.c
+++ b/test/CodeCompletion/macros.c
@@ -10,18 +10,18 @@ struct Point {
void test(struct Point *p) {
// RUN: %clang_cc1 -include %S/Inputs/macros.h -fsyntax-only -code-completion-macros -code-completion-at=%s:12:14 %s -o - | FileCheck -check-prefix=CC1 %s
switch (p->IDENTITY(color)) {
- // RUN: %clang_cc1 -include %S/Inputs/macros.h -fsyntax-only -code-completion-macros -code-completion-at=%s:14:9 %s -o - | FileCheck -check-prefix=CC2 %s
+ // RUN: %clang_cc1 -include %S/Inputs/macros.h -fsyntax-only -code-completion-macros -code-completion-at=%s:14:10 %s -o - | FileCheck -check-prefix=CC2 %s
case
}
- // RUN: %clang_cc1 -include %S/Inputs/macros.h -fsyntax-only -code-completion-macros -code-completion-at=%s:17:7 %s -o - | FileCheck -check-prefix=CC3 %s
+ // RUN: %clang_cc1 -include %S/Inputs/macros.h -fsyntax-only -code-completion-macros -code-completion-at=%s:17:8 %s -o - | FileCheck -check-prefix=CC3 %s
#ifdef Q
#endif
// Run the same tests, this time with macros loaded from the PCH file.
// RUN: %clang_cc1 -emit-pch -o %t %S/Inputs/macros.h
// RUN: %clang_cc1 -include-pch %t -fsyntax-only -code-completion-macros -code-completion-at=%s:12:14 %s -o - | FileCheck -check-prefix=CC1 %s
- // RUN: %clang_cc1 -include-pch %t -fsyntax-only -code-completion-macros -code-completion-at=%s:14:9 %s -o - | FileCheck -check-prefix=CC2 %s
- // RUN: %clang_cc1 -include-pch %t -fsyntax-only -code-completion-macros -code-completion-at=%s:17:7 %s -o - | FileCheck -check-prefix=CC3 %s
+ // RUN: %clang_cc1 -include-pch %t -fsyntax-only -code-completion-macros -code-completion-at=%s:14:10 %s -o - | FileCheck -check-prefix=CC2 %s
+ // RUN: %clang_cc1 -include-pch %t -fsyntax-only -code-completion-macros -code-completion-at=%s:17:8 %s -o - | FileCheck -check-prefix=CC3 %s
// CC1: color
// CC1: x
diff --git a/test/CodeCompletion/member-access.cpp b/test/CodeCompletion/member-access.cpp
index a0dc7b485679..008e223716bb 100644
--- a/test/CodeCompletion/member-access.cpp
+++ b/test/CodeCompletion/member-access.cpp
@@ -16,6 +16,8 @@ struct Base3 : Base1, Base2 {
};
struct Derived : Base3 {
+ template <typename T> Derived(T);
+ Derived(int);
int member4;
int memfun3(int);
};
@@ -48,7 +50,7 @@ struct Bar {
}
};
- // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:29:6 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:31:6 %s -o - | FileCheck -check-prefix=CHECK-CC1 --implicit-check-not="Derived : Derived(" %s
// CHECK-CC1: Base1 : Base1::
// CHECK-CC1: member1 : [#int#][#Base1::#]member1
// CHECK-CC1: member1 : [#int#][#Base2::#]member1
@@ -62,10 +64,10 @@ struct Bar {
// CHECK-CC1: memfun3 : [#int#]memfun3(<#int#>)
// Make sure this doesn't crash
-// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:36:7 %s -verify
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:38:7 %s -verify
// Make sure this also doesn't crash
-// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:47:14 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:49:14 %s
template<typename T>
@@ -100,8 +102,8 @@ void completeDependentMembers(TemplateClass<T, S> &object,
// CHECK-CC2: overload1 : [#void#]overload1(<#const T &#>)
// CHECK-CC2: overload1 : [#void#]overload1(<#const S &#>)
-// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:92:10 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
-// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:93:12 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:94:10 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:95:12 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
}
@@ -118,8 +120,8 @@ void completeDependentSpecializedMembers(TemplateClass<int, double> &object,
// CHECK-CC3: overload1 : [#void#]overload1(<#const int &#>)
// CHECK-CC3: overload1 : [#void#]overload1(<#const double &#>)
-// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:110:10 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
-// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:111:12 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:112:10 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:113:12 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
}
template <typename T>
@@ -133,17 +135,17 @@ public:
// CHECK-CC4: BaseTemplate : BaseTemplate::
// CHECK-CC4: baseTemplateField : [#int#]baseTemplateField
// CHECK-CC4: baseTemplateFunction : [#int#]baseTemplateFunction()
-// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:132:8 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:134:8 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s
o2.baseTemplateField;
// CHECK-CC5: BaseTemplate : BaseTemplate::
// CHECK-CC5: baseTemplateField : [#T#]baseTemplateField
// CHECK-CC5: baseTemplateFunction : [#T#]baseTemplateFunction()
-// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:137:8 %s -o - | FileCheck -check-prefix=CHECK-CC5 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:139:8 %s -o - | FileCheck -check-prefix=CHECK-CC5 %s
this->o1;
// CHECK-CC6: [#void#]function()
// CHECK-CC6: o1 : [#BaseTemplate<int>#]o1
// CHECK-CC6: o2 : [#BaseTemplate<T>#]o2
-// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:142:11 %s -o - | FileCheck -check-prefix=CHECK-CC6 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:144:11 %s -o - | FileCheck -check-prefix=CHECK-CC6 %s
}
static void staticFn(T &obj);
@@ -160,7 +162,51 @@ void dependentColonColonCompletion() {
// CHECK-CC7: o2 : [#BaseTemplate<T>#]o2
// CHECK-CC7: staticFn : [#void#]staticFn(<#T &obj#>)
// CHECK-CC7: Template : Template
-// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:156:16 %s -o - | FileCheck -check-prefix=CHECK-CC7 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:158:16 %s -o - | FileCheck -check-prefix=CHECK-CC7 %s
typename Template<T>::Nested m;
-// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:164:25 %s -o - | FileCheck -check-prefix=CHECK-CC7 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:166:25 %s -o - | FileCheck -check-prefix=CHECK-CC7 %s
}
+
+class Proxy2 {
+public:
+ Derived *operator->() const;
+ int member5;
+};
+
+void test2(const Proxy2 &p) {
+ p->
+}
+
+void test3(const Proxy2 &p) {
+ p.
+}
+
+// RUN: %clang_cc1 -fsyntax-only -code-completion-with-fixits -code-completion-at=%s:177:6 %s -o - | FileCheck -check-prefix=CHECK-CC8 --implicit-check-not="Derived : Derived(" %s
+// CHECK-CC8: Base1 : Base1::
+// CHECK-CC8: member1 : [#int#][#Base1::#]member1
+// CHECK-CC8: member1 : [#int#][#Base2::#]member1
+// CHECK-CC8: member2 : [#float#][#Base1::#]member2
+// CHECK-CC8: member3 : [#double#][#Base2::#]member3
+// CHECK-CC8: member4 : [#int#]member4
+// CHECK-CC8: member5 : [#int#]member5 (requires fix-it: {177:4-177:6} to ".")
+// CHECK-CC8: memfun1 : [#void#][#Base3::#]memfun1(<#float#>)
+// CHECK-CC8: memfun1 : [#void#][#Base3::#]memfun1(<#double#>)[# const#]
+// CHECK-CC8: memfun1 (Hidden) : [#void#]Base2::memfun1(<#int#>)
+// CHECK-CC8: memfun2 : [#void#][#Base3::#]memfun2(<#int#>)
+// CHECK-CC8: memfun3 : [#int#]memfun3(<#int#>)
+// CHECK-CC8: operator-> : [#Derived *#]operator->()[# const#] (requires fix-it: {177:4-177:6} to ".")
+
+// RUN: %clang_cc1 -fsyntax-only -code-completion-with-fixits -code-completion-at=%s:181:6 %s -o - | FileCheck -check-prefix=CHECK-CC9 --implicit-check-not="Derived : Derived(" %s
+// CHECK-CC9: Base1 : Base1::
+// CHECK-CC9: member1 : [#int#][#Base1::#]member1 (requires fix-it: {181:4-181:5} to "->")
+// CHECK-CC9: member1 : [#int#][#Base2::#]member1 (requires fix-it: {181:4-181:5} to "->")
+// CHECK-CC9: member2 : [#float#][#Base1::#]member2 (requires fix-it: {181:4-181:5} to "->")
+// CHECK-CC9: member3 : [#double#][#Base2::#]member3 (requires fix-it: {181:4-181:5} to "->")
+// CHECK-CC9: member4 : [#int#]member4 (requires fix-it: {181:4-181:5} to "->")
+// CHECK-CC9: member5 : [#int#]member5
+// CHECK-CC9: memfun1 : [#void#][#Base3::#]memfun1(<#float#>) (requires fix-it: {181:4-181:5} to "->")
+// CHECK-CC9: memfun1 : [#void#][#Base3::#]memfun1(<#double#>)[# const#] (requires fix-it: {181:4-181:5} to "->")
+// CHECK-CC9: memfun1 (Hidden) : [#void#]Base2::memfun1(<#int#>) (requires fix-it: {181:4-181:5} to "->")
+// CHECK-CC9: memfun2 : [#void#][#Base3::#]memfun2(<#int#>) (requires fix-it: {181:4-181:5} to "->")
+// CHECK-CC9: memfun3 : [#int#]memfun3(<#int#>) (requires fix-it: {181:4-181:5} to "->")
+// CHECK-CC9: operator-> : [#Derived *#]operator->()[# const#]
diff --git a/test/CodeCompletion/namespace.cpp b/test/CodeCompletion/namespace.cpp
index 8d3908a17889..6024a3494aaa 100644
--- a/test/CodeCompletion/namespace.cpp
+++ b/test/CodeCompletion/namespace.cpp
@@ -7,8 +7,8 @@ namespace N2 {
namespace I5 { }
namespace I1 { }
- namespace
- // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:12 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+ namespace
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:13 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
// CHECK-CC1: I1
// CHECK-CC1-NEXT: I5
diff --git a/test/CodeCompletion/operator.cpp b/test/CodeCompletion/operator.cpp
index e0a21860bbc7..4a57f0ac58ec 100644
--- a/test/CodeCompletion/operator.cpp
+++ b/test/CodeCompletion/operator.cpp
@@ -7,8 +7,8 @@ namespace N { }
void f() {
typedef float Float;
- operator
- // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:11 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+ operator
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:12 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
// CHECK-CC1: +
// CHECK-CC1: Float
// CHECK-CC1: Integer
diff --git a/test/CodeCompletion/skip-auto-funcs.cpp b/test/CodeCompletion/skip-auto-funcs.cpp
new file mode 100644
index 000000000000..ab2465d7fb04
--- /dev/null
+++ b/test/CodeCompletion/skip-auto-funcs.cpp
@@ -0,0 +1,61 @@
+// We run clang in completion mode to force skipping of function bodies and
+// check if the function bodies were skipped by observing the warnings that
+// clang produces.
+// RUN: not %clang_cc1 -fsyntax-only -code-completion-at=%s:60:1 %s -o - 2>&1 | FileCheck %s
+template <class T>
+auto not_skipped() {
+ int x;
+ if (x = 10) {}
+ // Check that this function is not skipped.
+ // CHECK: 8:9: warning: using the result of an assignment as a condition without parentheses
+ return 1;
+}
+
+template <class T>
+auto lambda_not_skipped = []() {
+ int x;
+ if (x = 10) {}
+ // Check that this function is not skipped.
+ // CHECK: 17:9: warning: using the result of an assignment as a condition without parentheses
+ return 1;
+}
+
+template <class T>
+auto skipped() -> T {
+ int x;
+ if (x = 10) {}
+ // Check that this function is skipped.
+ // CHECK-NOT: 26:9: warning: using the result of an assignment as a condition without parentheses
+ return 1;
+};
+
+auto lambda_skipped = []() -> int {
+ int x;
+ if (x = 10) {}
+ // This could potentially be skipped, but it isn't at the moment.
+ // CHECK: 34:9: warning: using the result of an assignment as a condition without parentheses
+ return 1;
+};
+
+template <class T>
+decltype(auto)** not_skipped_ptr() {
+ int x;
+ if (x = 10) {}
+ // Check that this function is not skipped.
+ // CHECK: 43:9: warning: using the result of an assignment as a condition without parentheses
+ return T();
+}
+
+template <class T>
+decltype(auto) not_skipped_decltypeauto() {
+ int x;
+ if (x = 10) {}
+ // Check that this function is not skipped.
+ // CHECK: 52:9: warning: using the result of an assignment as a condition without parentheses
+ return 1;
+}
+
+int test() {
+ int complete_in_this_function;
+ // CHECK: COMPLETION: complete_in_this_function
+}
diff --git a/test/CodeCompletion/tag.c b/test/CodeCompletion/tag.c
index d49fb0423618..4a34c4c77222 100644
--- a/test/CodeCompletion/tag.c
+++ b/test/CodeCompletion/tag.c
@@ -6,7 +6,7 @@ void X();
void test() {
enum X { x };
- enum
- // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:9:7 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+ enum
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:9:8 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
// CHECK-CC1: X
// CHECK-CC1: Y
diff --git a/test/CodeCompletion/tag.cpp b/test/CodeCompletion/tag.cpp
index c5ba6d31c47b..d99ca05bda4a 100644
--- a/test/CodeCompletion/tag.cpp
+++ b/test/CodeCompletion/tag.cpp
@@ -14,8 +14,8 @@ namespace N {
class Y;
void test() {
- class
- // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:17:10 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+ class
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:17:11 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
// FIXME: the redundant Y is really annoying... it needs qualification to
// actually be useful. Here, it just looks redundant :(
// CHECK-CC1: A
diff --git a/test/CodeCompletion/using-namespace.cpp b/test/CodeCompletion/using-namespace.cpp
index 63cb5898ee9a..4b93d02388b5 100644
--- a/test/CodeCompletion/using-namespace.cpp
+++ b/test/CodeCompletion/using-namespace.cpp
@@ -11,8 +11,8 @@ namespace N2 {
namespace I1 { }
void foo() {
- using namespace
- // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:14:20 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+ using namespace
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:14:21 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
// CHECK-CC1: I1
// CHECK-CC1: I4
// CHECK-CC1: I5
diff --git a/test/CodeCompletion/using.cpp b/test/CodeCompletion/using.cpp
index 13ebb4b2d8d0..aaad8c976b82 100644
--- a/test/CodeCompletion/using.cpp
+++ b/test/CodeCompletion/using.cpp
@@ -13,8 +13,8 @@ namespace N2 {
void foo() {
int N3;
- using
- // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:16:10 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+ using
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:16:11 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
// CHECK-CC1: I1
// CHECK-CC1: I4
// CHECK-CC1: I5
diff --git a/test/CodeGen/2004-03-07-ExternalConstant.c b/test/CodeGen/2004-03-07-ExternalConstant.c
index 2de3a69bd679..36371c073d8d 100644
--- a/test/CodeGen/2004-03-07-ExternalConstant.c
+++ b/test/CodeGen/2004-03-07-ExternalConstant.c
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
-// CHECK: @a = external constan
+// CHECK: @a = external {{(dso_local )?}}constan
extern const int a[]; // 'a' should be marked constant even though it's external!
int foo () {
return a[0];
diff --git a/test/CodeGen/2007-06-18-SextAttrAggregate.c b/test/CodeGen/2007-06-18-SextAttrAggregate.c
index 23c211d3ba04..e781bd567374 100644
--- a/test/CodeGen/2007-06-18-SextAttrAggregate.c
+++ b/test/CodeGen/2007-06-18-SextAttrAggregate.c
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 %s -o - -emit-llvm | FileCheck %s
-// XFAIL: aarch64, arm64, x86_64-pc-win32, x86_64-w64-mingw32
+// XFAIL: aarch64, arm64, x86_64-pc-win32, x86_64-w64-mingw32, x86_64-pc-windows-gnu
// PR1513
diff --git a/test/CodeGen/2007-11-07-CopyAggregateAlign.c b/test/CodeGen/2007-11-07-CopyAggregateAlign.c
index 08d97702e69a..769a38a7695b 100644
--- a/test/CodeGen/2007-11-07-CopyAggregateAlign.c
+++ b/test/CodeGen/2007-11-07-CopyAggregateAlign.c
@@ -2,6 +2,6 @@
struct A { char s, t, u, v; short a; };
// CHECK: %a = alloca %struct.A, align 2
// CHECK: %b = alloca %struct.A, align 2
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{.*}}, i32 2, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{.*}} align 2 {{.*}} align 2 {{.*}}, i1 false)
void q() { struct A a, b; a = b; }
diff --git a/test/CodeGen/2007-11-07-ZeroAggregateAlign.c b/test/CodeGen/2007-11-07-ZeroAggregateAlign.c
index b059607ba586..2b8cfe1f8f77 100644
--- a/test/CodeGen/2007-11-07-ZeroAggregateAlign.c
+++ b/test/CodeGen/2007-11-07-ZeroAggregateAlign.c
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s
struct A { short s; short t; int i; };
// CHECK: %a = alloca %struct.A, align 4
-// CHECK: call void @llvm.memset.p0i8.{{.*}}i32 4, i1 false)
+// CHECK: call void @llvm.memset.p0i8.{{.*}} align 4 {{.*}}, i1 false)
void q() { struct A a = {0}; }
diff --git a/test/CodeGen/2008-07-21-mixed-var-fn-decl.c b/test/CodeGen/2008-07-21-mixed-var-fn-decl.c
index ac132604399e..3c9591e2945e 100644
--- a/test/CodeGen/2008-07-21-mixed-var-fn-decl.c
+++ b/test/CodeGen/2008-07-21-mixed-var-fn-decl.c
@@ -3,6 +3,6 @@
int g0, f0();
int f1(), g1;
-// CHECK: @g0 = common global i32 0, align 4
-// CHECK: @g1 = common global i32 0, align 4
+// CHECK: @g0 = common {{(dso_local )?}}global i32 0, align 4
+// CHECK: @g1 = common {{(dso_local )?}}global i32 0, align 4
diff --git a/test/CodeGen/64bit-swiftcall.c b/test/CodeGen/64bit-swiftcall.c
index 92ba37cd7fe6..7486e44406ed 100644
--- a/test/CodeGen/64bit-swiftcall.c
+++ b/test/CodeGen/64bit-swiftcall.c
@@ -108,9 +108,7 @@ typedef struct {
TEST(struct_1);
// CHECK-LABEL: define swiftcc { i64, i64 } @return_struct_1() {{.*}}{
// CHECK: [[RET:%.*]] = alloca [[STRUCT1:%.*]], align 4
-// CHECK: [[VAR:%.*]] = alloca [[STRUCT1]], align 4
// CHECK: call void @llvm.memset
-// CHECK: call void @llvm.memcpy
// CHECK: [[CAST:%.*]] = bitcast [[STRUCT1]]* %retval to { i64, i64 }*
// CHECK: [[GEP0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
// CHECK: [[T0:%.*]] = load i64, i64* [[GEP0]], align 4
@@ -158,12 +156,8 @@ typedef struct {
TEST(struct_2);
// CHECK-LABEL: define swiftcc { i64, i64 } @return_struct_2() {{.*}}{
// CHECK: [[RET:%.*]] = alloca [[STRUCT2_TYPE]], align 4
-// CHECK: [[VAR:%.*]] = alloca [[STRUCT2_TYPE]], align 4
-// CHECK: [[CASTVAR:%.*]] = bitcast {{.*}} [[VAR]]
+// CHECK: [[CASTVAR:%.*]] = bitcast {{.*}} [[RET]]
// CHECK: call void @llvm.memcpy{{.*}}({{.*}}[[CASTVAR]], {{.*}}[[STRUCT2_RESULT]]
-// CHECK: [[CASTRET:%.*]] = bitcast {{.*}} [[RET]]
-// CHECK: [[CASTVAR:%.*]] = bitcast {{.*}} [[VAR]]
-// CHECK: call void @llvm.memcpy{{.*}}({{.*}}[[CASTRET]], {{.*}}[[CASTVAR]]
// CHECK: [[CAST:%.*]] = bitcast [[STRUCT2_TYPE]]* [[RET]] to { i64, i64 }*
// CHECK: [[GEP0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
// CHECK: [[T0:%.*]] = load i64, i64* [[GEP0]], align 4
@@ -214,12 +208,8 @@ typedef struct {
TEST(struct_misaligned_1)
// CHECK-LABEL: define swiftcc i64 @return_struct_misaligned_1()
// CHECK: [[RET:%.*]] = alloca [[STRUCT:%.*]], align 1
-// CHECK: [[RES:%.*]] = alloca [[STRUCT]], align 1
-// CHECK: [[CAST:%.*]] = bitcast [[STRUCT]]* [[RES]] to i8*
-// CHECK: call void @llvm.memset{{.*}}(i8* [[CAST]], i8 0, i64 5
-// CHECK: [[CASTRET:%.*]] = bitcast [[STRUCT]]* [[RET]] to i8*
-// CHECK: [[CASTRES:%.*]] = bitcast [[STRUCT]]* [[RES]] to i8*
-// CHECK: call void @llvm.memcpy{{.*}}(i8* [[CASTRET]], i8* [[CASTRES]], i64 5
+// CHECK: [[CAST:%.*]] = bitcast [[STRUCT]]* [[RET]] to i8*
+// CHECK: call void @llvm.memset{{.*}}(i8* align 1 [[CAST]], i8 0, i64 5
// CHECK: [[CAST:%.*]] = bitcast [[STRUCT]]* [[RET]] to { i64 }*
// CHECK: [[GEP:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[CAST]], i32 0, i32 0
// CHECK: [[R0:%.*]] = load i64, i64* [[GEP]], align 1
@@ -267,12 +257,8 @@ typedef union {
TEST(union_het_fp)
// CHECK-LABEL: define swiftcc i64 @return_union_het_fp()
// CHECK: [[RET:%.*]] = alloca [[UNION:%.*]], align 8
-// CHECK: [[RES:%.*]] = alloca [[UNION]], align 8
-// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[RES]] to i8*
-// CHECK: call void @llvm.memcpy{{.*}}(i8* [[CAST]]
-// CHECK: [[CASTRET:%.*]] = bitcast [[UNION]]* [[RET]] to i8*
-// CHECK: [[CASTRES:%.*]] = bitcast [[UNION]]* [[RES]] to i8*
-// CHECK: call void @llvm.memcpy{{.*}}(i8* [[CASTRET]], i8* [[CASTRES]]
+// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[RET]] to i8*
+// CHECK: call void @llvm.memcpy{{.*}}(i8* align 8 [[CAST]]
// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[RET]] to { i64 }*
// CHECK: [[GEP:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[CAST]], i32 0, i32 0
// CHECK: [[R0:%.*]] = load i64, i64* [[GEP]], align 8
@@ -1032,3 +1018,12 @@ typedef union {
TEST(union_hom_fp_partial2)
// X86-64-LABEL: take_union_hom_fp_partial2(i64, float)
// ARM64-LABEL: take_union_hom_fp_partial2(i64, float)
+
+// At one point, we emitted lifetime.ends without a matching lifetime.start for
+// CoerceAndExpanded args. Since we're not performing optimizations, neither
+// intrinsic should be emitted.
+// CHECK-LABEL: define void @no_lifetime_markers
+void no_lifetime_markers() {
+ // CHECK-NOT: call void @llvm.lifetime.
+ take_int5(return_int5());
+}
diff --git a/test/CodeGen/Atomics.c b/test/CodeGen/Atomics.c
index f957883575de..d960ac6df2f9 100644
--- a/test/CodeGen/Atomics.c
+++ b/test/CodeGen/Atomics.c
@@ -291,3 +291,10 @@ void test_lock (void)
__sync_lock_release (&sll); // CHECK: store atomic {{.*}} release, align 8
__sync_lock_release (&ull); // CHECK: store atomic {{.*}} release, align 8
}
+
+void test_atomic(void) {
+ ui = __atomic_fetch_min(&ui, 5, __ATOMIC_RELAXED); // CHECK: atomicrmw umin {{.*}} monotonic
+ si = __atomic_fetch_min(&si, 5, __ATOMIC_SEQ_CST); // CHECK: atomicrmw min {{.*}} seq_cst
+ ui = __atomic_fetch_max(&ui, 5, __ATOMIC_ACQUIRE); // CHECK: atomicrmw umax {{.*}} acquire
+ si = __atomic_fetch_max(&si, 5, __ATOMIC_RELEASE); // CHECK: atomicrmw max {{.*}} release
+}
diff --git a/test/CodeGen/Inputs/debug-info-embed-source.c b/test/CodeGen/Inputs/debug-info-embed-source.c
new file mode 100644
index 000000000000..2fb55eed6b26
--- /dev/null
+++ b/test/CodeGen/Inputs/debug-info-embed-source.c
@@ -0,0 +1 @@
+void foo() { }
diff --git a/test/CodeGen/Inputs/thinlto-distributed-backend-skip.bc b/test/CodeGen/Inputs/thinlto-distributed-backend-skip.bc
new file mode 100644
index 000000000000..0243eb696055
--- /dev/null
+++ b/test/CodeGen/Inputs/thinlto-distributed-backend-skip.bc
Binary files differ
diff --git a/test/CodeGen/aarch64-inline-asm.c b/test/CodeGen/aarch64-inline-asm.c
index a1078f1bab83..0889a7157f0b 100644
--- a/test/CodeGen/aarch64-inline-asm.c
+++ b/test/CodeGen/aarch64-inline-asm.c
@@ -44,9 +44,9 @@ void test_constraints_immed(void) {
void test_constraint_S(void) {
int *addr;
- asm("adrp %0, %A1\n\t"
- "add %0, %0, %L1" : "=r"(addr) : "S"(&var));
-// CHECK: call i32* asm "adrp $0, ${1:A}\0A\09add $0, $0, ${1:L}", "=r,S"(i64* @var)
+ asm("adrp %0, %1\n\t"
+ "add %0, %0, :lo12:%1" : "=r"(addr) : "S"(&var));
+// CHECK: call i32* asm "adrp $0, $1\0A\09add $0, $0, :lo12:$1", "=r,S"(i64* @var)
}
void test_constraint_Q(void) {
@@ -54,3 +54,23 @@ void test_constraint_Q(void) {
asm("ldxr %0, %1" : "=r"(val) : "Q"(var));
// CHECK: call i32 asm "ldxr $0, $1", "=r,*Q"(i64* @var)
}
+
+void test_gcc_registers(void) {
+ register unsigned long reg0 asm("r0") = 0;
+ register unsigned long reg1 asm("r1") = 1;
+ register unsigned int reg29 asm("r29") = 2;
+ register unsigned int reg30 asm("r30") = 3;
+
+ // Test remapping register names in register ... asm("rN") statments.
+ // rN register operands in these two inline assembly lines
+ // should get renamed to valid AArch64 registers.
+ asm volatile("hvc #0" : : "r" (reg0), "r" (reg1));
+ // CHECK: call void asm sideeffect "hvc #0", "{x0},{x1}"
+ asm volatile("hvc #0" : : "r" (reg29), "r" (reg30));
+ // CHECK: call void asm sideeffect "hvc #0", "{fp},{lr}"
+
+ // rN registers when used without register ... asm("rN") syntax
+ // should not be remapped.
+ asm volatile("mov r0, r1\n");
+ // CHECK: call void asm sideeffect "mov r0, r1\0A", ""()
+}
diff --git a/test/CodeGen/aarch64-neon-2velem.c b/test/CodeGen/aarch64-neon-2velem.c
index 3867b01afb7a..320ce0286bed 100644
--- a/test/CodeGen/aarch64-neon-2velem.c
+++ b/test/CodeGen/aarch64-neon-2velem.c
@@ -3083,6 +3083,17 @@ float32x2_t test_vfma_n_f32(float32x2_t a, float32x2_t b, float32_t n) {
return vfma_n_f32(a, b, n);
}
+// CHECK-LABEL: @test_vfma_n_f64(
+// CHECK: [[VECINIT_I:%.*]] = insertelement <1 x double> undef, double %n, i32 0
+// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
+// CHECK: [[TMP1:%.*]] = bitcast <1 x double> %b to <8 x i8>
+// CHECK: [[TMP2:%.*]] = bitcast <1 x double> [[VECINIT_I]] to <8 x i8>
+// CHECK: [[TMP3:%.*]] = call <1 x double> @llvm.fma.v1f64(<1 x double> %b, <1 x double> [[VECINIT_I]], <1 x double> %a)
+// CHECK: ret <1 x double> [[TMP3]]
+float64x1_t test_vfma_n_f64(float64x1_t a, float64x1_t b, float64_t n) {
+ return vfma_n_f64(a, b, n);
+}
+
// CHECK-LABEL: @test_vfmaq_n_f32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x float> undef, float %n, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x float> [[VECINIT_I]], float %n, i32 1
@@ -3110,6 +3121,18 @@ float32x2_t test_vfms_n_f32(float32x2_t a, float32x2_t b, float32_t n) {
return vfms_n_f32(a, b, n);
}
+// CHECK-LABEL: @test_vfms_n_f64(
+// CHECK: [[SUB_I:%.*]] = fsub <1 x double> <double -0.000000e+00>, %b
+// CHECK: [[VECINIT_I:%.*]] = insertelement <1 x double> undef, double %n, i32 0
+// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
+// CHECK: [[TMP1:%.*]] = bitcast <1 x double> [[SUB_I]] to <8 x i8>
+// CHECK: [[TMP2:%.*]] = bitcast <1 x double> [[VECINIT_I]] to <8 x i8>
+// CHECK: [[TMP3:%.*]] = call <1 x double> @llvm.fma.v1f64(<1 x double> [[SUB_I]], <1 x double> [[VECINIT_I]], <1 x double> %a)
+// CHECK: ret <1 x double> [[TMP3]]
+float64x1_t test_vfms_n_f64(float64x1_t a, float64x1_t b, float64_t n) {
+ return vfms_n_f64(a, b, n);
+}
+
// CHECK-LABEL: @test_vfmsq_n_f32(
// CHECK: [[SUB_I:%.*]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %b
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x float> undef, float %n, i32 0
diff --git a/test/CodeGen/aarch64-neon-dot-product.c b/test/CodeGen/aarch64-neon-dot-product.c
new file mode 100644
index 000000000000..de18db5655c1
--- /dev/null
+++ b/test/CodeGen/aarch64-neon-dot-product.c
@@ -0,0 +1,117 @@
+// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon -target-feature +dotprod \
+// RUN: -disable-O0-optnone -emit-llvm -o - %s | opt -S -instcombine | FileCheck %s
+
+// REQUIRES: aarch64-registered-target
+
+// Test AArch64 Armv8.2-A dot product intrinsics
+
+#include <arm_neon.h>
+
+uint32x2_t test_vdot_u32(uint32x2_t a, uint8x8_t b, uint8x8_t c) {
+// CHECK-LABEL: define <2 x i32> @test_vdot_u32(<2 x i32> %a, <8 x i8> %b, <8 x i8> %c)
+// CHECK: [[RESULT:%.*]] = call <2 x i32> @llvm.aarch64.neon.udot.v2i32.v8i8(<2 x i32> %a, <8 x i8> %b, <8 x i8> %c)
+// CHECK: ret <2 x i32> [[RESULT]]
+ return vdot_u32(a, b, c);
+}
+
+uint32x4_t test_vdotq_u32(uint32x4_t a, uint8x16_t b, uint8x16_t c) {
+// CHECK-LABEL: define <4 x i32> @test_vdotq_u32(<4 x i32> %a, <16 x i8> %b, <16 x i8> %c)
+// CHECK: [[RESULT:%.*]] = call <4 x i32> @llvm.aarch64.neon.udot.v4i32.v16i8(<4 x i32> %a, <16 x i8> %b, <16 x i8> %c)
+// CHECK: ret <4 x i32> [[RESULT]]
+ return vdotq_u32(a, b, c);
+}
+
+int32x2_t test_vdot_s32(int32x2_t a, int8x8_t b, int8x8_t c) {
+// CHECK-LABEL: define <2 x i32> @test_vdot_s32(<2 x i32> %a, <8 x i8> %b, <8 x i8> %c)
+// CHECK: [[RESULT:%.*]] = call <2 x i32> @llvm.aarch64.neon.sdot.v2i32.v8i8(<2 x i32> %a, <8 x i8> %b, <8 x i8> %c)
+// CHECK: ret <2 x i32> [[RESULT]]
+ return vdot_s32(a, b, c);
+}
+
+int32x4_t test_vdotq_s32(int32x4_t a, int8x16_t b, int8x16_t c) {
+// CHECK-LABEL: define <4 x i32> @test_vdotq_s32(<4 x i32> %a, <16 x i8> %b, <16 x i8> %c)
+// CHECK: [[RESULT:%.*]] = call <4 x i32> @llvm.aarch64.neon.sdot.v4i32.v16i8(<4 x i32> %a, <16 x i8> %b, <16 x i8> %c)
+// CHECK: ret <4 x i32> [[RESULT]]
+ return vdotq_s32(a, b, c);
+}
+
+uint32x2_t test_vdot_lane_u32(uint32x2_t a, uint8x8_t b, uint8x8_t c) {
+// CHECK-LABEL: define <2 x i32> @test_vdot_lane_u32(<2 x i32> %a, <8 x i8> %b, <8 x i8> %c)
+// CHECK: [[CAST1:%.*]] = bitcast <8 x i8> %c to <2 x i32>
+// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> [[CAST1]], <2 x i32> undef, <2 x i32> <i32 1, i32 1>
+// CHECK: [[CAST2:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
+// CHECK: [[RESULT:%.*]] = call <2 x i32> @llvm.aarch64.neon.udot.v2i32.v8i8(<2 x i32> %a, <8 x i8> %b, <8 x i8> [[CAST2]])
+// CHECK: ret <2 x i32> [[RESULT]]
+ return vdot_lane_u32(a, b, c, 1);
+}
+
+uint32x4_t test_vdotq_lane_u32(uint32x4_t a, uint8x16_t b, uint8x8_t c) {
+// CHECK-LABEL: define <4 x i32> @test_vdotq_lane_u32(<4 x i32> %a, <16 x i8> %b, <8 x i8> %c)
+// CHECK: [[CAST1:%.*]] = bitcast <8 x i8> %c to <2 x i32>
+// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> [[CAST1]], <2 x i32> undef, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
+// CHECK: [[CAST2:%.*]] = bitcast <4 x i32> [[SHUFFLE]] to <16 x i8>
+// CHECK: [[RESULT:%.*]] = call <4 x i32> @llvm.aarch64.neon.udot.v4i32.v16i8(<4 x i32> %a, <16 x i8> %b, <16 x i8> [[CAST2]])
+// CHECK: ret <4 x i32> [[RESULT]]
+ return vdotq_lane_u32(a, b, c, 1);
+}
+
+uint32x2_t test_vdot_laneq_u32(uint32x2_t a, uint8x8_t b, uint8x16_t c) {
+// CHECK-LABEL: define <2 x i32> @test_vdot_laneq_u32(<2 x i32> %a, <8 x i8> %b, <16 x i8> %c)
+// CHECK: [[CAST1:%.*]] = bitcast <16 x i8> %c to <4 x i32>
+// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> [[CAST1]], <4 x i32> undef, <2 x i32> <i32 1, i32 1>
+// CHECK: [[CAST2:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
+// CHECK: [[RESULT:%.*]] = call <2 x i32> @llvm.aarch64.neon.udot.v2i32.v8i8(<2 x i32> %a, <8 x i8> %b, <8 x i8> [[CAST2]])
+// CHECK: ret <2 x i32> [[RESULT]]
+ return vdot_laneq_u32(a, b, c, 1);
+}
+
+uint32x4_t test_vdotq_laneq_u32(uint32x4_t a, uint8x16_t b, uint8x16_t c) {
+// CHECK-LABEL: define <4 x i32> @test_vdotq_laneq_u32(<4 x i32> %a, <16 x i8> %b, <16 x i8> %c)
+// CHECK: [[CAST1:%.*]] = bitcast <16 x i8> %c to <4 x i32>
+// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> [[CAST1]], <4 x i32> undef, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
+// CHECK: [[CAST2:%.*]] = bitcast <4 x i32> [[SHUFFLE]] to <16 x i8>
+// CHECK: [[RESULT:%.*]] = call <4 x i32> @llvm.aarch64.neon.udot.v4i32.v16i8(<4 x i32> %a, <16 x i8> %b, <16 x i8> [[CAST2]])
+// CHECK: ret <4 x i32> [[RESULT]]
+ return vdotq_laneq_u32(a, b, c, 1);
+}
+
+int32x2_t test_vdot_lane_s32(int32x2_t a, int8x8_t b, int8x8_t c) {
+// CHECK-LABEL: define <2 x i32> @test_vdot_lane_s32(<2 x i32> %a, <8 x i8> %b, <8 x i8> %c)
+// CHECK: [[CAST1:%.*]] = bitcast <8 x i8> %c to <2 x i32>
+// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> [[CAST1]], <2 x i32> undef, <2 x i32> <i32 1, i32 1>
+// CHECK: [[CAST2:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
+// CHECK: [[RESULT:%.*]] = call <2 x i32> @llvm.aarch64.neon.sdot.v2i32.v8i8(<2 x i32> %a, <8 x i8> %b, <8 x i8> [[CAST2]])
+// CHECK: ret <2 x i32> [[RESULT]]
+ return vdot_lane_s32(a, b, c, 1);
+}
+
+int32x4_t test_vdotq_lane_s32(int32x4_t a, int8x16_t b, int8x8_t c) {
+// CHECK-LABEL: define <4 x i32> @test_vdotq_lane_s32(<4 x i32> %a, <16 x i8> %b, <8 x i8> %c)
+// CHECK: [[CAST1:%.*]] = bitcast <8 x i8> %c to <2 x i32>
+// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> [[CAST1]], <2 x i32> undef, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
+// CHECK: [[CAST2:%.*]] = bitcast <4 x i32> [[SHUFFLE]] to <16 x i8>
+// CHECK: [[RESULT:%.*]] = call <4 x i32> @llvm.aarch64.neon.sdot.v4i32.v16i8(<4 x i32> %a, <16 x i8> %b, <16 x i8> [[CAST2]])
+// CHECK: ret <4 x i32> [[RESULT]]
+ return vdotq_lane_s32(a, b, c, 1);
+}
+
+int32x2_t test_vdot_laneq_s32(int32x2_t a, int8x8_t b, int8x16_t c) {
+// CHECK-LABEL: define <2 x i32> @test_vdot_laneq_s32(<2 x i32> %a, <8 x i8> %b, <16 x i8> %c)
+// CHECK: [[CAST1:%.*]] = bitcast <16 x i8> %c to <4 x i32>
+// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> [[CAST1]], <4 x i32> undef, <2 x i32> <i32 1, i32 1>
+// CHECK: [[CAST2:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
+// CHECK: [[RESULT:%.*]] = call <2 x i32> @llvm.aarch64.neon.sdot.v2i32.v8i8(<2 x i32> %a, <8 x i8> %b, <8 x i8> [[CAST2]])
+// CHECK: ret <2 x i32> [[RESULT]]
+ return vdot_laneq_s32(a, b, c, 1);
+}
+
+int32x4_t test_vdotq_laneq_s32(int32x4_t a, int8x16_t b, int8x16_t c) {
+// CHECK-LABEL: define <4 x i32> @test_vdotq_laneq_s32(<4 x i32> %a, <16 x i8> %b, <16 x i8> %c)
+// CHECK: [[CAST1:%.*]] = bitcast <16 x i8> %c to <4 x i32>
+// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> [[CAST1]], <4 x i32> undef, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
+// CHECK: [[CAST2:%.*]] = bitcast <4 x i32> [[SHUFFLE]] to <16 x i8>
+// CHECK: [[RESULT:%.*]] = call <4 x i32> @llvm.aarch64.neon.sdot.v4i32.v16i8(<4 x i32> %a, <16 x i8> %b, <16 x i8> [[CAST2]])
+// CHECK: ret <4 x i32> [[RESULT]]
+ return vdotq_laneq_s32(a, b, c, 1);
+}
+
diff --git a/test/CodeGen/aarch64-neon-intrinsics.c b/test/CodeGen/aarch64-neon-intrinsics.c
index cbc2e72fcbac..40e39912be9a 100644
--- a/test/CodeGen/aarch64-neon-intrinsics.c
+++ b/test/CodeGen/aarch64-neon-intrinsics.c
@@ -9203,7 +9203,7 @@ poly16x4_t test_vld1_p16(poly16_t const *a) {
// CHECK: store { <16 x i8>, <16 x i8> } [[VLD2]], { <16 x i8>, <16 x i8> }* [[TMP2]]
// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP3]], i8* align 16 [[TMP4]], i64 32, i1 false)
// CHECK: [[TMP5:%.*]] = load %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.uint8x16x2_t [[TMP5]]
uint8x16x2_t test_vld2q_u8(uint8_t const *a) {
@@ -9221,7 +9221,7 @@ uint8x16x2_t test_vld2q_u8(uint8_t const *a) {
// CHECK: store { <8 x i16>, <8 x i16> } [[VLD2]], { <8 x i16>, <8 x i16> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x8x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 32, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.uint16x8x2_t [[TMP6]]
uint16x8x2_t test_vld2q_u16(uint16_t const *a) {
@@ -9239,7 +9239,7 @@ uint16x8x2_t test_vld2q_u16(uint16_t const *a) {
// CHECK: store { <4 x i32>, <4 x i32> } [[VLD2]], { <4 x i32>, <4 x i32> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x4x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 32, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.uint32x4x2_t [[TMP6]]
uint32x4x2_t test_vld2q_u32(uint32_t const *a) {
@@ -9257,7 +9257,7 @@ uint32x4x2_t test_vld2q_u32(uint32_t const *a) {
// CHECK: store { <2 x i64>, <2 x i64> } [[VLD2]], { <2 x i64>, <2 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x2x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.uint64x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 32, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.uint64x2x2_t, %struct.uint64x2x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.uint64x2x2_t [[TMP6]]
uint64x2x2_t test_vld2q_u64(uint64_t const *a) {
@@ -9274,7 +9274,7 @@ uint64x2x2_t test_vld2q_u64(uint64_t const *a) {
// CHECK: store { <16 x i8>, <16 x i8> } [[VLD2]], { <16 x i8>, <16 x i8> }* [[TMP2]]
// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast %struct.int8x16x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP3]], i8* align 16 [[TMP4]], i64 32, i1 false)
// CHECK: [[TMP5:%.*]] = load %struct.int8x16x2_t, %struct.int8x16x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.int8x16x2_t [[TMP5]]
int8x16x2_t test_vld2q_s8(int8_t const *a) {
@@ -9292,7 +9292,7 @@ int8x16x2_t test_vld2q_s8(int8_t const *a) {
// CHECK: store { <8 x i16>, <8 x i16> } [[VLD2]], { <8 x i16>, <8 x i16> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x8x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 32, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.int16x8x2_t, %struct.int16x8x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.int16x8x2_t [[TMP6]]
int16x8x2_t test_vld2q_s16(int16_t const *a) {
@@ -9310,7 +9310,7 @@ int16x8x2_t test_vld2q_s16(int16_t const *a) {
// CHECK: store { <4 x i32>, <4 x i32> } [[VLD2]], { <4 x i32>, <4 x i32> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x4x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 32, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.int32x4x2_t, %struct.int32x4x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.int32x4x2_t [[TMP6]]
int32x4x2_t test_vld2q_s32(int32_t const *a) {
@@ -9328,7 +9328,7 @@ int32x4x2_t test_vld2q_s32(int32_t const *a) {
// CHECK: store { <2 x i64>, <2 x i64> } [[VLD2]], { <2 x i64>, <2 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x2x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.int64x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 32, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.int64x2x2_t, %struct.int64x2x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.int64x2x2_t [[TMP6]]
int64x2x2_t test_vld2q_s64(int64_t const *a) {
@@ -9346,7 +9346,7 @@ int64x2x2_t test_vld2q_s64(int64_t const *a) {
// CHECK: store { <8 x half>, <8 x half> } [[VLD2]], { <8 x half>, <8 x half> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x8x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 32, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.float16x8x2_t, %struct.float16x8x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.float16x8x2_t [[TMP6]]
float16x8x2_t test_vld2q_f16(float16_t const *a) {
@@ -9364,7 +9364,7 @@ float16x8x2_t test_vld2q_f16(float16_t const *a) {
// CHECK: store { <4 x float>, <4 x float> } [[VLD2]], { <4 x float>, <4 x float> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x4x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 32, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.float32x4x2_t, %struct.float32x4x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.float32x4x2_t [[TMP6]]
float32x4x2_t test_vld2q_f32(float32_t const *a) {
@@ -9382,7 +9382,7 @@ float32x4x2_t test_vld2q_f32(float32_t const *a) {
// CHECK: store { <2 x double>, <2 x double> } [[VLD2]], { <2 x double>, <2 x double> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float64x2x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float64x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 32, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.float64x2x2_t, %struct.float64x2x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.float64x2x2_t [[TMP6]]
float64x2x2_t test_vld2q_f64(float64_t const *a) {
@@ -9399,7 +9399,7 @@ float64x2x2_t test_vld2q_f64(float64_t const *a) {
// CHECK: store { <16 x i8>, <16 x i8> } [[VLD2]], { <16 x i8>, <16 x i8> }* [[TMP2]]
// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP3]], i8* align 16 [[TMP4]], i64 32, i1 false)
// CHECK: [[TMP5:%.*]] = load %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.poly8x16x2_t [[TMP5]]
poly8x16x2_t test_vld2q_p8(poly8_t const *a) {
@@ -9417,7 +9417,7 @@ poly8x16x2_t test_vld2q_p8(poly8_t const *a) {
// CHECK: store { <8 x i16>, <8 x i16> } [[VLD2]], { <8 x i16>, <8 x i16> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x8x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 32, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.poly16x8x2_t [[TMP6]]
poly16x8x2_t test_vld2q_p16(poly16_t const *a) {
@@ -9434,7 +9434,7 @@ poly16x8x2_t test_vld2q_p16(poly16_t const *a) {
// CHECK: store { <8 x i8>, <8 x i8> } [[VLD2]], { <8 x i8>, <8 x i8> }* [[TMP2]]
// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP3]], i8* align 8 [[TMP4]], i64 16, i1 false)
// CHECK: [[TMP5:%.*]] = load %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[RETVAL]], align 8
// CHECK: ret %struct.uint8x8x2_t [[TMP5]]
uint8x8x2_t test_vld2_u8(uint8_t const *a) {
@@ -9452,7 +9452,7 @@ uint8x8x2_t test_vld2_u8(uint8_t const *a) {
// CHECK: store { <4 x i16>, <4 x i16> } [[VLD2]], { <4 x i16>, <4 x i16> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x4x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 16, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[RETVAL]], align 8
// CHECK: ret %struct.uint16x4x2_t [[TMP6]]
uint16x4x2_t test_vld2_u16(uint16_t const *a) {
@@ -9470,7 +9470,7 @@ uint16x4x2_t test_vld2_u16(uint16_t const *a) {
// CHECK: store { <2 x i32>, <2 x i32> } [[VLD2]], { <2 x i32>, <2 x i32> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x2x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 16, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[RETVAL]], align 8
// CHECK: ret %struct.uint32x2x2_t [[TMP6]]
uint32x2x2_t test_vld2_u32(uint32_t const *a) {
@@ -9488,7 +9488,7 @@ uint32x2x2_t test_vld2_u32(uint32_t const *a) {
// CHECK: store { <1 x i64>, <1 x i64> } [[VLD2]], { <1 x i64>, <1 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x1x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.uint64x1x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 16, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.uint64x1x2_t, %struct.uint64x1x2_t* [[RETVAL]], align 8
// CHECK: ret %struct.uint64x1x2_t [[TMP6]]
uint64x1x2_t test_vld2_u64(uint64_t const *a) {
@@ -9505,7 +9505,7 @@ uint64x1x2_t test_vld2_u64(uint64_t const *a) {
// CHECK: store { <8 x i8>, <8 x i8> } [[VLD2]], { <8 x i8>, <8 x i8> }* [[TMP2]]
// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast %struct.int8x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP3]], i8* align 8 [[TMP4]], i64 16, i1 false)
// CHECK: [[TMP5:%.*]] = load %struct.int8x8x2_t, %struct.int8x8x2_t* [[RETVAL]], align 8
// CHECK: ret %struct.int8x8x2_t [[TMP5]]
int8x8x2_t test_vld2_s8(int8_t const *a) {
@@ -9523,7 +9523,7 @@ int8x8x2_t test_vld2_s8(int8_t const *a) {
// CHECK: store { <4 x i16>, <4 x i16> } [[VLD2]], { <4 x i16>, <4 x i16> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x4x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 16, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.int16x4x2_t, %struct.int16x4x2_t* [[RETVAL]], align 8
// CHECK: ret %struct.int16x4x2_t [[TMP6]]
int16x4x2_t test_vld2_s16(int16_t const *a) {
@@ -9541,7 +9541,7 @@ int16x4x2_t test_vld2_s16(int16_t const *a) {
// CHECK: store { <2 x i32>, <2 x i32> } [[VLD2]], { <2 x i32>, <2 x i32> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x2x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 16, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.int32x2x2_t, %struct.int32x2x2_t* [[RETVAL]], align 8
// CHECK: ret %struct.int32x2x2_t [[TMP6]]
int32x2x2_t test_vld2_s32(int32_t const *a) {
@@ -9559,7 +9559,7 @@ int32x2x2_t test_vld2_s32(int32_t const *a) {
// CHECK: store { <1 x i64>, <1 x i64> } [[VLD2]], { <1 x i64>, <1 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x1x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.int64x1x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 16, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.int64x1x2_t, %struct.int64x1x2_t* [[RETVAL]], align 8
// CHECK: ret %struct.int64x1x2_t [[TMP6]]
int64x1x2_t test_vld2_s64(int64_t const *a) {
@@ -9577,7 +9577,7 @@ int64x1x2_t test_vld2_s64(int64_t const *a) {
// CHECK: store { <4 x half>, <4 x half> } [[VLD2]], { <4 x half>, <4 x half> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x4x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 16, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.float16x4x2_t, %struct.float16x4x2_t* [[RETVAL]], align 8
// CHECK: ret %struct.float16x4x2_t [[TMP6]]
float16x4x2_t test_vld2_f16(float16_t const *a) {
@@ -9595,7 +9595,7 @@ float16x4x2_t test_vld2_f16(float16_t const *a) {
// CHECK: store { <2 x float>, <2 x float> } [[VLD2]], { <2 x float>, <2 x float> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x2x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 16, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.float32x2x2_t, %struct.float32x2x2_t* [[RETVAL]], align 8
// CHECK: ret %struct.float32x2x2_t [[TMP6]]
float32x2x2_t test_vld2_f32(float32_t const *a) {
@@ -9613,7 +9613,7 @@ float32x2x2_t test_vld2_f32(float32_t const *a) {
// CHECK: store { <1 x double>, <1 x double> } [[VLD2]], { <1 x double>, <1 x double> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float64x1x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float64x1x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 16, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.float64x1x2_t, %struct.float64x1x2_t* [[RETVAL]], align 8
// CHECK: ret %struct.float64x1x2_t [[TMP6]]
float64x1x2_t test_vld2_f64(float64_t const *a) {
@@ -9630,7 +9630,7 @@ float64x1x2_t test_vld2_f64(float64_t const *a) {
// CHECK: store { <8 x i8>, <8 x i8> } [[VLD2]], { <8 x i8>, <8 x i8> }* [[TMP2]]
// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP3]], i8* align 8 [[TMP4]], i64 16, i1 false)
// CHECK: [[TMP5:%.*]] = load %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[RETVAL]], align 8
// CHECK: ret %struct.poly8x8x2_t [[TMP5]]
poly8x8x2_t test_vld2_p8(poly8_t const *a) {
@@ -9648,7 +9648,7 @@ poly8x8x2_t test_vld2_p8(poly8_t const *a) {
// CHECK: store { <4 x i16>, <4 x i16> } [[VLD2]], { <4 x i16>, <4 x i16> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x4x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 16, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[RETVAL]], align 8
// CHECK: ret %struct.poly16x4x2_t [[TMP6]]
poly16x4x2_t test_vld2_p16(poly16_t const *a) {
@@ -9665,7 +9665,7 @@ poly16x4x2_t test_vld2_p16(poly16_t const *a) {
// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8> } [[VLD3]], { <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP2]]
// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast %struct.uint8x16x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP3]], i8* align 16 [[TMP4]], i64 48, i1 false)
// CHECK: [[TMP5:%.*]] = load %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.uint8x16x3_t [[TMP5]]
uint8x16x3_t test_vld3q_u8(uint8_t const *a) {
@@ -9683,7 +9683,7 @@ uint8x16x3_t test_vld3q_u8(uint8_t const *a) {
// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD3]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x8x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 48, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.uint16x8x3_t [[TMP6]]
uint16x8x3_t test_vld3q_u16(uint16_t const *a) {
@@ -9701,7 +9701,7 @@ uint16x8x3_t test_vld3q_u16(uint16_t const *a) {
// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32> } [[VLD3]], { <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x4x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 48, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.uint32x4x3_t [[TMP6]]
uint32x4x3_t test_vld3q_u32(uint32_t const *a) {
@@ -9719,7 +9719,7 @@ uint32x4x3_t test_vld3q_u32(uint32_t const *a) {
// CHECK: store { <2 x i64>, <2 x i64>, <2 x i64> } [[VLD3]], { <2 x i64>, <2 x i64>, <2 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x2x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.uint64x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 48, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.uint64x2x3_t, %struct.uint64x2x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.uint64x2x3_t [[TMP6]]
uint64x2x3_t test_vld3q_u64(uint64_t const *a) {
@@ -9736,7 +9736,7 @@ uint64x2x3_t test_vld3q_u64(uint64_t const *a) {
// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8> } [[VLD3]], { <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP2]]
// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast %struct.int8x16x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP3]], i8* align 16 [[TMP4]], i64 48, i1 false)
// CHECK: [[TMP5:%.*]] = load %struct.int8x16x3_t, %struct.int8x16x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.int8x16x3_t [[TMP5]]
int8x16x3_t test_vld3q_s8(int8_t const *a) {
@@ -9754,7 +9754,7 @@ int8x16x3_t test_vld3q_s8(int8_t const *a) {
// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD3]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x8x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 48, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.int16x8x3_t, %struct.int16x8x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.int16x8x3_t [[TMP6]]
int16x8x3_t test_vld3q_s16(int16_t const *a) {
@@ -9772,7 +9772,7 @@ int16x8x3_t test_vld3q_s16(int16_t const *a) {
// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32> } [[VLD3]], { <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x4x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 48, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.int32x4x3_t, %struct.int32x4x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.int32x4x3_t [[TMP6]]
int32x4x3_t test_vld3q_s32(int32_t const *a) {
@@ -9790,7 +9790,7 @@ int32x4x3_t test_vld3q_s32(int32_t const *a) {
// CHECK: store { <2 x i64>, <2 x i64>, <2 x i64> } [[VLD3]], { <2 x i64>, <2 x i64>, <2 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x2x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.int64x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 48, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.int64x2x3_t, %struct.int64x2x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.int64x2x3_t [[TMP6]]
int64x2x3_t test_vld3q_s64(int64_t const *a) {
@@ -9808,7 +9808,7 @@ int64x2x3_t test_vld3q_s64(int64_t const *a) {
// CHECK: store { <8 x half>, <8 x half>, <8 x half> } [[VLD3]], { <8 x half>, <8 x half>, <8 x half> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x8x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 48, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.float16x8x3_t, %struct.float16x8x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.float16x8x3_t [[TMP6]]
float16x8x3_t test_vld3q_f16(float16_t const *a) {
@@ -9826,7 +9826,7 @@ float16x8x3_t test_vld3q_f16(float16_t const *a) {
// CHECK: store { <4 x float>, <4 x float>, <4 x float> } [[VLD3]], { <4 x float>, <4 x float>, <4 x float> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x4x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 48, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.float32x4x3_t, %struct.float32x4x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.float32x4x3_t [[TMP6]]
float32x4x3_t test_vld3q_f32(float32_t const *a) {
@@ -9844,7 +9844,7 @@ float32x4x3_t test_vld3q_f32(float32_t const *a) {
// CHECK: store { <2 x double>, <2 x double>, <2 x double> } [[VLD3]], { <2 x double>, <2 x double>, <2 x double> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float64x2x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float64x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 48, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.float64x2x3_t, %struct.float64x2x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.float64x2x3_t [[TMP6]]
float64x2x3_t test_vld3q_f64(float64_t const *a) {
@@ -9861,7 +9861,7 @@ float64x2x3_t test_vld3q_f64(float64_t const *a) {
// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8> } [[VLD3]], { <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP2]]
// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast %struct.poly8x16x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP3]], i8* align 16 [[TMP4]], i64 48, i1 false)
// CHECK: [[TMP5:%.*]] = load %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.poly8x16x3_t [[TMP5]]
poly8x16x3_t test_vld3q_p8(poly8_t const *a) {
@@ -9879,7 +9879,7 @@ poly8x16x3_t test_vld3q_p8(poly8_t const *a) {
// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD3]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x8x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 48, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.poly16x8x3_t [[TMP6]]
poly16x8x3_t test_vld3q_p16(poly16_t const *a) {
@@ -9896,7 +9896,7 @@ poly16x8x3_t test_vld3q_p16(poly16_t const *a) {
// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD3]], { <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP2]]
// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast %struct.uint8x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP3]], i8* align 8 [[TMP4]], i64 24, i1 false)
// CHECK: [[TMP5:%.*]] = load %struct.uint8x8x3_t, %struct.uint8x8x3_t* [[RETVAL]], align 8
// CHECK: ret %struct.uint8x8x3_t [[TMP5]]
uint8x8x3_t test_vld3_u8(uint8_t const *a) {
@@ -9914,7 +9914,7 @@ uint8x8x3_t test_vld3_u8(uint8_t const *a) {
// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD3]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x4x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 24, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.uint16x4x3_t, %struct.uint16x4x3_t* [[RETVAL]], align 8
// CHECK: ret %struct.uint16x4x3_t [[TMP6]]
uint16x4x3_t test_vld3_u16(uint16_t const *a) {
@@ -9932,7 +9932,7 @@ uint16x4x3_t test_vld3_u16(uint16_t const *a) {
// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32> } [[VLD3]], { <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x2x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 24, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.uint32x2x3_t, %struct.uint32x2x3_t* [[RETVAL]], align 8
// CHECK: ret %struct.uint32x2x3_t [[TMP6]]
uint32x2x3_t test_vld3_u32(uint32_t const *a) {
@@ -9950,7 +9950,7 @@ uint32x2x3_t test_vld3_u32(uint32_t const *a) {
// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64> } [[VLD3]], { <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x1x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.uint64x1x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 24, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.uint64x1x3_t, %struct.uint64x1x3_t* [[RETVAL]], align 8
// CHECK: ret %struct.uint64x1x3_t [[TMP6]]
uint64x1x3_t test_vld3_u64(uint64_t const *a) {
@@ -9967,7 +9967,7 @@ uint64x1x3_t test_vld3_u64(uint64_t const *a) {
// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD3]], { <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP2]]
// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast %struct.int8x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP3]], i8* align 8 [[TMP4]], i64 24, i1 false)
// CHECK: [[TMP5:%.*]] = load %struct.int8x8x3_t, %struct.int8x8x3_t* [[RETVAL]], align 8
// CHECK: ret %struct.int8x8x3_t [[TMP5]]
int8x8x3_t test_vld3_s8(int8_t const *a) {
@@ -9985,7 +9985,7 @@ int8x8x3_t test_vld3_s8(int8_t const *a) {
// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD3]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x4x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 24, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.int16x4x3_t, %struct.int16x4x3_t* [[RETVAL]], align 8
// CHECK: ret %struct.int16x4x3_t [[TMP6]]
int16x4x3_t test_vld3_s16(int16_t const *a) {
@@ -10003,7 +10003,7 @@ int16x4x3_t test_vld3_s16(int16_t const *a) {
// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32> } [[VLD3]], { <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x2x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 24, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.int32x2x3_t, %struct.int32x2x3_t* [[RETVAL]], align 8
// CHECK: ret %struct.int32x2x3_t [[TMP6]]
int32x2x3_t test_vld3_s32(int32_t const *a) {
@@ -10021,7 +10021,7 @@ int32x2x3_t test_vld3_s32(int32_t const *a) {
// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64> } [[VLD3]], { <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x1x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.int64x1x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 24, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.int64x1x3_t, %struct.int64x1x3_t* [[RETVAL]], align 8
// CHECK: ret %struct.int64x1x3_t [[TMP6]]
int64x1x3_t test_vld3_s64(int64_t const *a) {
@@ -10039,7 +10039,7 @@ int64x1x3_t test_vld3_s64(int64_t const *a) {
// CHECK: store { <4 x half>, <4 x half>, <4 x half> } [[VLD3]], { <4 x half>, <4 x half>, <4 x half> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x4x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 24, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.float16x4x3_t, %struct.float16x4x3_t* [[RETVAL]], align 8
// CHECK: ret %struct.float16x4x3_t [[TMP6]]
float16x4x3_t test_vld3_f16(float16_t const *a) {
@@ -10057,7 +10057,7 @@ float16x4x3_t test_vld3_f16(float16_t const *a) {
// CHECK: store { <2 x float>, <2 x float>, <2 x float> } [[VLD3]], { <2 x float>, <2 x float>, <2 x float> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x2x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 24, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.float32x2x3_t, %struct.float32x2x3_t* [[RETVAL]], align 8
// CHECK: ret %struct.float32x2x3_t [[TMP6]]
float32x2x3_t test_vld3_f32(float32_t const *a) {
@@ -10075,7 +10075,7 @@ float32x2x3_t test_vld3_f32(float32_t const *a) {
// CHECK: store { <1 x double>, <1 x double>, <1 x double> } [[VLD3]], { <1 x double>, <1 x double>, <1 x double> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float64x1x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float64x1x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 24, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.float64x1x3_t, %struct.float64x1x3_t* [[RETVAL]], align 8
// CHECK: ret %struct.float64x1x3_t [[TMP6]]
float64x1x3_t test_vld3_f64(float64_t const *a) {
@@ -10092,7 +10092,7 @@ float64x1x3_t test_vld3_f64(float64_t const *a) {
// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD3]], { <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP2]]
// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast %struct.poly8x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP3]], i8* align 8 [[TMP4]], i64 24, i1 false)
// CHECK: [[TMP5:%.*]] = load %struct.poly8x8x3_t, %struct.poly8x8x3_t* [[RETVAL]], align 8
// CHECK: ret %struct.poly8x8x3_t [[TMP5]]
poly8x8x3_t test_vld3_p8(poly8_t const *a) {
@@ -10110,7 +10110,7 @@ poly8x8x3_t test_vld3_p8(poly8_t const *a) {
// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD3]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x4x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 24, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.poly16x4x3_t, %struct.poly16x4x3_t* [[RETVAL]], align 8
// CHECK: ret %struct.poly16x4x3_t [[TMP6]]
poly16x4x3_t test_vld3_p16(poly16_t const *a) {
@@ -10127,7 +10127,7 @@ poly16x4x3_t test_vld3_p16(poly16_t const *a) {
// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } [[VLD4]], { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP2]]
// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast %struct.uint8x16x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP3]], i8* align 16 [[TMP4]], i64 64, i1 false)
// CHECK: [[TMP5:%.*]] = load %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.uint8x16x4_t [[TMP5]]
uint8x16x4_t test_vld4q_u8(uint8_t const *a) {
@@ -10145,7 +10145,7 @@ uint8x16x4_t test_vld4q_u8(uint8_t const *a) {
// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } [[VLD4]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x8x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 64, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.uint16x8x4_t [[TMP6]]
uint16x8x4_t test_vld4q_u16(uint16_t const *a) {
@@ -10163,7 +10163,7 @@ uint16x8x4_t test_vld4q_u16(uint16_t const *a) {
// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLD4]], { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x4x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 64, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.uint32x4x4_t [[TMP6]]
uint32x4x4_t test_vld4q_u32(uint32_t const *a) {
@@ -10181,7 +10181,7 @@ uint32x4x4_t test_vld4q_u32(uint32_t const *a) {
// CHECK: store { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } [[VLD4]], { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x2x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.uint64x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 64, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.uint64x2x4_t, %struct.uint64x2x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.uint64x2x4_t [[TMP6]]
uint64x2x4_t test_vld4q_u64(uint64_t const *a) {
@@ -10198,7 +10198,7 @@ uint64x2x4_t test_vld4q_u64(uint64_t const *a) {
// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } [[VLD4]], { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP2]]
// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast %struct.int8x16x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP3]], i8* align 16 [[TMP4]], i64 64, i1 false)
// CHECK: [[TMP5:%.*]] = load %struct.int8x16x4_t, %struct.int8x16x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.int8x16x4_t [[TMP5]]
int8x16x4_t test_vld4q_s8(int8_t const *a) {
@@ -10216,7 +10216,7 @@ int8x16x4_t test_vld4q_s8(int8_t const *a) {
// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } [[VLD4]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x8x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 64, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.int16x8x4_t, %struct.int16x8x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.int16x8x4_t [[TMP6]]
int16x8x4_t test_vld4q_s16(int16_t const *a) {
@@ -10234,7 +10234,7 @@ int16x8x4_t test_vld4q_s16(int16_t const *a) {
// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLD4]], { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x4x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 64, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.int32x4x4_t, %struct.int32x4x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.int32x4x4_t [[TMP6]]
int32x4x4_t test_vld4q_s32(int32_t const *a) {
@@ -10252,7 +10252,7 @@ int32x4x4_t test_vld4q_s32(int32_t const *a) {
// CHECK: store { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } [[VLD4]], { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x2x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.int64x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 64, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.int64x2x4_t, %struct.int64x2x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.int64x2x4_t [[TMP6]]
int64x2x4_t test_vld4q_s64(int64_t const *a) {
@@ -10270,7 +10270,7 @@ int64x2x4_t test_vld4q_s64(int64_t const *a) {
// CHECK: store { <8 x half>, <8 x half>, <8 x half>, <8 x half> } [[VLD4]], { <8 x half>, <8 x half>, <8 x half>, <8 x half> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x8x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 64, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.float16x8x4_t, %struct.float16x8x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.float16x8x4_t [[TMP6]]
float16x8x4_t test_vld4q_f16(float16_t const *a) {
@@ -10288,7 +10288,7 @@ float16x8x4_t test_vld4q_f16(float16_t const *a) {
// CHECK: store { <4 x float>, <4 x float>, <4 x float>, <4 x float> } [[VLD4]], { <4 x float>, <4 x float>, <4 x float>, <4 x float> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x4x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 64, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.float32x4x4_t, %struct.float32x4x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.float32x4x4_t [[TMP6]]
float32x4x4_t test_vld4q_f32(float32_t const *a) {
@@ -10306,7 +10306,7 @@ float32x4x4_t test_vld4q_f32(float32_t const *a) {
// CHECK: store { <2 x double>, <2 x double>, <2 x double>, <2 x double> } [[VLD4]], { <2 x double>, <2 x double>, <2 x double>, <2 x double> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float64x2x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float64x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 64, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.float64x2x4_t, %struct.float64x2x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.float64x2x4_t [[TMP6]]
float64x2x4_t test_vld4q_f64(float64_t const *a) {
@@ -10323,7 +10323,7 @@ float64x2x4_t test_vld4q_f64(float64_t const *a) {
// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } [[VLD4]], { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP2]]
// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast %struct.poly8x16x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP3]], i8* align 16 [[TMP4]], i64 64, i1 false)
// CHECK: [[TMP5:%.*]] = load %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.poly8x16x4_t [[TMP5]]
poly8x16x4_t test_vld4q_p8(poly8_t const *a) {
@@ -10341,7 +10341,7 @@ poly8x16x4_t test_vld4q_p8(poly8_t const *a) {
// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } [[VLD4]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x8x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 64, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.poly16x8x4_t [[TMP6]]
poly16x8x4_t test_vld4q_p16(poly16_t const *a) {
@@ -10358,7 +10358,7 @@ poly16x8x4_t test_vld4q_p16(poly16_t const *a) {
// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[VLD4]], { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP2]]
// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast %struct.uint8x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP3]], i8* align 8 [[TMP4]], i64 32, i1 false)
// CHECK: [[TMP5:%.*]] = load %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[RETVAL]], align 8
// CHECK: ret %struct.uint8x8x4_t [[TMP5]]
uint8x8x4_t test_vld4_u8(uint8_t const *a) {
@@ -10376,7 +10376,7 @@ uint8x8x4_t test_vld4_u8(uint8_t const *a) {
// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD4]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x4x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 32, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.uint16x4x4_t, %struct.uint16x4x4_t* [[RETVAL]], align 8
// CHECK: ret %struct.uint16x4x4_t [[TMP6]]
uint16x4x4_t test_vld4_u16(uint16_t const *a) {
@@ -10394,7 +10394,7 @@ uint16x4x4_t test_vld4_u16(uint16_t const *a) {
// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[VLD4]], { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x2x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 32, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.uint32x2x4_t, %struct.uint32x2x4_t* [[RETVAL]], align 8
// CHECK: ret %struct.uint32x2x4_t [[TMP6]]
uint32x2x4_t test_vld4_u32(uint32_t const *a) {
@@ -10412,7 +10412,7 @@ uint32x2x4_t test_vld4_u32(uint32_t const *a) {
// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } [[VLD4]], { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x1x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.uint64x1x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 32, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.uint64x1x4_t, %struct.uint64x1x4_t* [[RETVAL]], align 8
// CHECK: ret %struct.uint64x1x4_t [[TMP6]]
uint64x1x4_t test_vld4_u64(uint64_t const *a) {
@@ -10429,7 +10429,7 @@ uint64x1x4_t test_vld4_u64(uint64_t const *a) {
// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[VLD4]], { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP2]]
// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast %struct.int8x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP3]], i8* align 8 [[TMP4]], i64 32, i1 false)
// CHECK: [[TMP5:%.*]] = load %struct.int8x8x4_t, %struct.int8x8x4_t* [[RETVAL]], align 8
// CHECK: ret %struct.int8x8x4_t [[TMP5]]
int8x8x4_t test_vld4_s8(int8_t const *a) {
@@ -10447,7 +10447,7 @@ int8x8x4_t test_vld4_s8(int8_t const *a) {
// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD4]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x4x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 32, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.int16x4x4_t, %struct.int16x4x4_t* [[RETVAL]], align 8
// CHECK: ret %struct.int16x4x4_t [[TMP6]]
int16x4x4_t test_vld4_s16(int16_t const *a) {
@@ -10465,7 +10465,7 @@ int16x4x4_t test_vld4_s16(int16_t const *a) {
// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[VLD4]], { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x2x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 32, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.int32x2x4_t, %struct.int32x2x4_t* [[RETVAL]], align 8
// CHECK: ret %struct.int32x2x4_t [[TMP6]]
int32x2x4_t test_vld4_s32(int32_t const *a) {
@@ -10483,7 +10483,7 @@ int32x2x4_t test_vld4_s32(int32_t const *a) {
// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } [[VLD4]], { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x1x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.int64x1x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 32, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.int64x1x4_t, %struct.int64x1x4_t* [[RETVAL]], align 8
// CHECK: ret %struct.int64x1x4_t [[TMP6]]
int64x1x4_t test_vld4_s64(int64_t const *a) {
@@ -10501,7 +10501,7 @@ int64x1x4_t test_vld4_s64(int64_t const *a) {
// CHECK: store { <4 x half>, <4 x half>, <4 x half>, <4 x half> } [[VLD4]], { <4 x half>, <4 x half>, <4 x half>, <4 x half> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x4x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 32, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.float16x4x4_t, %struct.float16x4x4_t* [[RETVAL]], align 8
// CHECK: ret %struct.float16x4x4_t [[TMP6]]
float16x4x4_t test_vld4_f16(float16_t const *a) {
@@ -10519,7 +10519,7 @@ float16x4x4_t test_vld4_f16(float16_t const *a) {
// CHECK: store { <2 x float>, <2 x float>, <2 x float>, <2 x float> } [[VLD4]], { <2 x float>, <2 x float>, <2 x float>, <2 x float> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x2x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 32, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.float32x2x4_t, %struct.float32x2x4_t* [[RETVAL]], align 8
// CHECK: ret %struct.float32x2x4_t [[TMP6]]
float32x2x4_t test_vld4_f32(float32_t const *a) {
@@ -10537,7 +10537,7 @@ float32x2x4_t test_vld4_f32(float32_t const *a) {
// CHECK: store { <1 x double>, <1 x double>, <1 x double>, <1 x double> } [[VLD4]], { <1 x double>, <1 x double>, <1 x double>, <1 x double> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float64x1x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float64x1x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 32, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.float64x1x4_t, %struct.float64x1x4_t* [[RETVAL]], align 8
// CHECK: ret %struct.float64x1x4_t [[TMP6]]
float64x1x4_t test_vld4_f64(float64_t const *a) {
@@ -10554,7 +10554,7 @@ float64x1x4_t test_vld4_f64(float64_t const *a) {
// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[VLD4]], { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP2]]
// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast %struct.poly8x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP3]], i8* align 8 [[TMP4]], i64 32, i1 false)
// CHECK: [[TMP5:%.*]] = load %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[RETVAL]], align 8
// CHECK: ret %struct.poly8x8x4_t [[TMP5]]
poly8x8x4_t test_vld4_p8(poly8_t const *a) {
@@ -10572,7 +10572,7 @@ poly8x8x4_t test_vld4_p8(poly8_t const *a) {
// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD4]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x4x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 32, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.poly16x4x4_t, %struct.poly16x4x4_t* [[RETVAL]], align 8
// CHECK: ret %struct.poly16x4x4_t [[TMP6]]
poly16x4x4_t test_vld4_p16(poly16_t const *a) {
@@ -10854,7 +10854,7 @@ void test_vst1_p16(poly16_t *a, poly16x4_t b) {
// CHECK: store [2 x <16 x i8>] [[B]].coerce, [2 x <16 x i8>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x16x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
@@ -10874,7 +10874,7 @@ void test_vst2q_u8(uint8_t *a, uint8x16x2_t b) {
// CHECK: store [2 x <8 x i16>] [[B]].coerce, [2 x <8 x i16>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL]], i64 0, i64 0
@@ -10899,7 +10899,7 @@ void test_vst2q_u16(uint16_t *a, uint16x8x2_t b) {
// CHECK: store [2 x <4 x i32>] [[B]].coerce, [2 x <4 x i32>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL]], i64 0, i64 0
@@ -10924,7 +10924,7 @@ void test_vst2q_u32(uint32_t *a, uint32x4x2_t b) {
// CHECK: store [2 x <2 x i64>] [[B]].coerce, [2 x <2 x i64>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x2x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x2x2_t, %struct.uint64x2x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x i64>], [2 x <2 x i64>]* [[VAL]], i64 0, i64 0
@@ -10949,7 +10949,7 @@ void test_vst2q_u64(uint64_t *a, uint64x2x2_t b) {
// CHECK: store [2 x <16 x i8>] [[B]].coerce, [2 x <16 x i8>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x16x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x16x2_t, %struct.int8x16x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
@@ -10969,7 +10969,7 @@ void test_vst2q_s8(int8_t *a, int8x16x2_t b) {
// CHECK: store [2 x <8 x i16>] [[B]].coerce, [2 x <8 x i16>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL]], i64 0, i64 0
@@ -10994,7 +10994,7 @@ void test_vst2q_s16(int16_t *a, int16x8x2_t b) {
// CHECK: store [2 x <4 x i32>] [[B]].coerce, [2 x <4 x i32>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL]], i64 0, i64 0
@@ -11019,7 +11019,7 @@ void test_vst2q_s32(int32_t *a, int32x4x2_t b) {
// CHECK: store [2 x <2 x i64>] [[B]].coerce, [2 x <2 x i64>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x2x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x2x2_t, %struct.int64x2x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x i64>], [2 x <2 x i64>]* [[VAL]], i64 0, i64 0
@@ -11044,7 +11044,7 @@ void test_vst2q_s64(int64_t *a, int64x2x2_t b) {
// CHECK: store [2 x <8 x half>] [[B]].coerce, [2 x <8 x half>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x2_t, %struct.float16x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x half>], [2 x <8 x half>]* [[VAL]], i64 0, i64 0
@@ -11069,7 +11069,7 @@ void test_vst2q_f16(float16_t *a, float16x8x2_t b) {
// CHECK: store [2 x <4 x float>] [[B]].coerce, [2 x <4 x float>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x float>], [2 x <4 x float>]* [[VAL]], i64 0, i64 0
@@ -11094,7 +11094,7 @@ void test_vst2q_f32(float32_t *a, float32x4x2_t b) {
// CHECK: store [2 x <2 x double>] [[B]].coerce, [2 x <2 x double>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x2x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float64x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast double* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float64x2x2_t, %struct.float64x2x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x double>], [2 x <2 x double>]* [[VAL]], i64 0, i64 0
@@ -11119,7 +11119,7 @@ void test_vst2q_f64(float64_t *a, float64x2x2_t b) {
// CHECK: store [2 x <16 x i8>] [[B]].coerce, [2 x <16 x i8>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x16x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
@@ -11139,7 +11139,7 @@ void test_vst2q_p8(poly8_t *a, poly8x16x2_t b) {
// CHECK: store [2 x <8 x i16>] [[B]].coerce, [2 x <8 x i16>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL]], i64 0, i64 0
@@ -11164,7 +11164,7 @@ void test_vst2q_p16(poly16_t *a, poly16x8x2_t b) {
// CHECK: store [2 x <8 x i8>] [[B]].coerce, [2 x <8 x i8>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -11184,7 +11184,7 @@ void test_vst2_u8(uint8_t *a, uint8x8x2_t b) {
// CHECK: store [2 x <4 x i16>] [[B]].coerce, [2 x <4 x i16>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL]], i64 0, i64 0
@@ -11209,7 +11209,7 @@ void test_vst2_u16(uint16_t *a, uint16x4x2_t b) {
// CHECK: store [2 x <2 x i32>] [[B]].coerce, [2 x <2 x i32>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x i32>], [2 x <2 x i32>]* [[VAL]], i64 0, i64 0
@@ -11234,7 +11234,7 @@ void test_vst2_u32(uint32_t *a, uint32x2x2_t b) {
// CHECK: store [2 x <1 x i64>] [[B]].coerce, [2 x <1 x i64>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x1x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x1x2_t, %struct.uint64x1x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <1 x i64>], [2 x <1 x i64>]* [[VAL]], i64 0, i64 0
@@ -11259,7 +11259,7 @@ void test_vst2_u64(uint64_t *a, uint64x1x2_t b) {
// CHECK: store [2 x <8 x i8>] [[B]].coerce, [2 x <8 x i8>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x8x2_t, %struct.int8x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -11279,7 +11279,7 @@ void test_vst2_s8(int8_t *a, int8x8x2_t b) {
// CHECK: store [2 x <4 x i16>] [[B]].coerce, [2 x <4 x i16>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x4x2_t, %struct.int16x4x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL]], i64 0, i64 0
@@ -11304,7 +11304,7 @@ void test_vst2_s16(int16_t *a, int16x4x2_t b) {
// CHECK: store [2 x <2 x i32>] [[B]].coerce, [2 x <2 x i32>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x2x2_t, %struct.int32x2x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x i32>], [2 x <2 x i32>]* [[VAL]], i64 0, i64 0
@@ -11329,7 +11329,7 @@ void test_vst2_s32(int32_t *a, int32x2x2_t b) {
// CHECK: store [2 x <1 x i64>] [[B]].coerce, [2 x <1 x i64>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x1x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x1x2_t, %struct.int64x1x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <1 x i64>], [2 x <1 x i64>]* [[VAL]], i64 0, i64 0
@@ -11354,7 +11354,7 @@ void test_vst2_s64(int64_t *a, int64x1x2_t b) {
// CHECK: store [2 x <4 x half>] [[B]].coerce, [2 x <4 x half>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x4x2_t, %struct.float16x4x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x half>], [2 x <4 x half>]* [[VAL]], i64 0, i64 0
@@ -11379,7 +11379,7 @@ void test_vst2_f16(float16_t *a, float16x4x2_t b) {
// CHECK: store [2 x <2 x float>] [[B]].coerce, [2 x <2 x float>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x2x2_t, %struct.float32x2x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x float>], [2 x <2 x float>]* [[VAL]], i64 0, i64 0
@@ -11404,7 +11404,7 @@ void test_vst2_f32(float32_t *a, float32x2x2_t b) {
// CHECK: store [2 x <1 x double>] [[B]].coerce, [2 x <1 x double>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x1x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float64x1x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast double* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float64x1x2_t, %struct.float64x1x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <1 x double>], [2 x <1 x double>]* [[VAL]], i64 0, i64 0
@@ -11429,7 +11429,7 @@ void test_vst2_f64(float64_t *a, float64x1x2_t b) {
// CHECK: store [2 x <8 x i8>] [[B]].coerce, [2 x <8 x i8>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -11449,7 +11449,7 @@ void test_vst2_p8(poly8_t *a, poly8x8x2_t b) {
// CHECK: store [2 x <4 x i16>] [[B]].coerce, [2 x <4 x i16>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL]], i64 0, i64 0
@@ -11474,7 +11474,7 @@ void test_vst2_p16(poly16_t *a, poly16x4x2_t b) {
// CHECK: store [3 x <16 x i8>] [[B]].coerce, [3 x <16 x i8>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x16x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
@@ -11497,7 +11497,7 @@ void test_vst3q_u8(uint8_t *a, uint8x16x3_t b) {
// CHECK: store [3 x <8 x i16>] [[B]].coerce, [3 x <8 x i16>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL]], i64 0, i64 0
@@ -11527,7 +11527,7 @@ void test_vst3q_u16(uint16_t *a, uint16x8x3_t b) {
// CHECK: store [3 x <4 x i32>] [[B]].coerce, [3 x <4 x i32>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL]], i64 0, i64 0
@@ -11557,7 +11557,7 @@ void test_vst3q_u32(uint32_t *a, uint32x4x3_t b) {
// CHECK: store [3 x <2 x i64>] [[B]].coerce, [3 x <2 x i64>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x2x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x2x3_t, %struct.uint64x2x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x i64>], [3 x <2 x i64>]* [[VAL]], i64 0, i64 0
@@ -11587,7 +11587,7 @@ void test_vst3q_u64(uint64_t *a, uint64x2x3_t b) {
// CHECK: store [3 x <16 x i8>] [[B]].coerce, [3 x <16 x i8>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x16x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x16x3_t, %struct.int8x16x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
@@ -11610,7 +11610,7 @@ void test_vst3q_s8(int8_t *a, int8x16x3_t b) {
// CHECK: store [3 x <8 x i16>] [[B]].coerce, [3 x <8 x i16>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL]], i64 0, i64 0
@@ -11640,7 +11640,7 @@ void test_vst3q_s16(int16_t *a, int16x8x3_t b) {
// CHECK: store [3 x <4 x i32>] [[B]].coerce, [3 x <4 x i32>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL]], i64 0, i64 0
@@ -11670,7 +11670,7 @@ void test_vst3q_s32(int32_t *a, int32x4x3_t b) {
// CHECK: store [3 x <2 x i64>] [[B]].coerce, [3 x <2 x i64>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x2x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x2x3_t, %struct.int64x2x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x i64>], [3 x <2 x i64>]* [[VAL]], i64 0, i64 0
@@ -11700,7 +11700,7 @@ void test_vst3q_s64(int64_t *a, int64x2x3_t b) {
// CHECK: store [3 x <8 x half>] [[B]].coerce, [3 x <8 x half>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x half>], [3 x <8 x half>]* [[VAL]], i64 0, i64 0
@@ -11730,7 +11730,7 @@ void test_vst3q_f16(float16_t *a, float16x8x3_t b) {
// CHECK: store [3 x <4 x float>] [[B]].coerce, [3 x <4 x float>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x float>], [3 x <4 x float>]* [[VAL]], i64 0, i64 0
@@ -11760,7 +11760,7 @@ void test_vst3q_f32(float32_t *a, float32x4x3_t b) {
// CHECK: store [3 x <2 x double>] [[B]].coerce, [3 x <2 x double>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x2x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float64x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast double* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float64x2x3_t, %struct.float64x2x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x double>], [3 x <2 x double>]* [[VAL]], i64 0, i64 0
@@ -11790,7 +11790,7 @@ void test_vst3q_f64(float64_t *a, float64x2x3_t b) {
// CHECK: store [3 x <16 x i8>] [[B]].coerce, [3 x <16 x i8>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x16x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
@@ -11813,7 +11813,7 @@ void test_vst3q_p8(poly8_t *a, poly8x16x3_t b) {
// CHECK: store [3 x <8 x i16>] [[B]].coerce, [3 x <8 x i16>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL]], i64 0, i64 0
@@ -11843,7 +11843,7 @@ void test_vst3q_p16(poly16_t *a, poly16x8x3_t b) {
// CHECK: store [3 x <8 x i8>] [[B]].coerce, [3 x <8 x i8>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x8x3_t, %struct.uint8x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -11866,7 +11866,7 @@ void test_vst3_u8(uint8_t *a, uint8x8x3_t b) {
// CHECK: store [3 x <4 x i16>] [[B]].coerce, [3 x <4 x i16>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x4x3_t, %struct.uint16x4x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL]], i64 0, i64 0
@@ -11896,7 +11896,7 @@ void test_vst3_u16(uint16_t *a, uint16x4x3_t b) {
// CHECK: store [3 x <2 x i32>] [[B]].coerce, [3 x <2 x i32>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x2x3_t, %struct.uint32x2x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x i32>], [3 x <2 x i32>]* [[VAL]], i64 0, i64 0
@@ -11926,7 +11926,7 @@ void test_vst3_u32(uint32_t *a, uint32x2x3_t b) {
// CHECK: store [3 x <1 x i64>] [[B]].coerce, [3 x <1 x i64>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x1x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x1x3_t, %struct.uint64x1x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL]], i64 0, i64 0
@@ -11956,7 +11956,7 @@ void test_vst3_u64(uint64_t *a, uint64x1x3_t b) {
// CHECK: store [3 x <8 x i8>] [[B]].coerce, [3 x <8 x i8>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x8x3_t, %struct.int8x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -11979,7 +11979,7 @@ void test_vst3_s8(int8_t *a, int8x8x3_t b) {
// CHECK: store [3 x <4 x i16>] [[B]].coerce, [3 x <4 x i16>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x4x3_t, %struct.int16x4x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL]], i64 0, i64 0
@@ -12009,7 +12009,7 @@ void test_vst3_s16(int16_t *a, int16x4x3_t b) {
// CHECK: store [3 x <2 x i32>] [[B]].coerce, [3 x <2 x i32>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x2x3_t, %struct.int32x2x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x i32>], [3 x <2 x i32>]* [[VAL]], i64 0, i64 0
@@ -12039,7 +12039,7 @@ void test_vst3_s32(int32_t *a, int32x2x3_t b) {
// CHECK: store [3 x <1 x i64>] [[B]].coerce, [3 x <1 x i64>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x1x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x1x3_t, %struct.int64x1x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL]], i64 0, i64 0
@@ -12069,7 +12069,7 @@ void test_vst3_s64(int64_t *a, int64x1x3_t b) {
// CHECK: store [3 x <4 x half>] [[B]].coerce, [3 x <4 x half>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x4x3_t, %struct.float16x4x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x half>], [3 x <4 x half>]* [[VAL]], i64 0, i64 0
@@ -12099,7 +12099,7 @@ void test_vst3_f16(float16_t *a, float16x4x3_t b) {
// CHECK: store [3 x <2 x float>] [[B]].coerce, [3 x <2 x float>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x2x3_t, %struct.float32x2x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x float>], [3 x <2 x float>]* [[VAL]], i64 0, i64 0
@@ -12129,7 +12129,7 @@ void test_vst3_f32(float32_t *a, float32x2x3_t b) {
// CHECK: store [3 x <1 x double>] [[B]].coerce, [3 x <1 x double>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x1x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float64x1x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast double* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float64x1x3_t, %struct.float64x1x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <1 x double>], [3 x <1 x double>]* [[VAL]], i64 0, i64 0
@@ -12159,7 +12159,7 @@ void test_vst3_f64(float64_t *a, float64x1x3_t b) {
// CHECK: store [3 x <8 x i8>] [[B]].coerce, [3 x <8 x i8>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x8x3_t, %struct.poly8x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -12182,7 +12182,7 @@ void test_vst3_p8(poly8_t *a, poly8x8x3_t b) {
// CHECK: store [3 x <4 x i16>] [[B]].coerce, [3 x <4 x i16>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x4x3_t, %struct.poly16x4x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL]], i64 0, i64 0
@@ -12212,7 +12212,7 @@ void test_vst3_p16(poly16_t *a, poly16x4x3_t b) {
// CHECK: store [4 x <16 x i8>] [[B]].coerce, [4 x <16 x i8>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x16x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
@@ -12238,7 +12238,7 @@ void test_vst4q_u8(uint8_t *a, uint8x16x4_t b) {
// CHECK: store [4 x <8 x i16>] [[B]].coerce, [4 x <8 x i16>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL]], i64 0, i64 0
@@ -12273,7 +12273,7 @@ void test_vst4q_u16(uint16_t *a, uint16x8x4_t b) {
// CHECK: store [4 x <4 x i32>] [[B]].coerce, [4 x <4 x i32>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL]], i64 0, i64 0
@@ -12308,7 +12308,7 @@ void test_vst4q_u32(uint32_t *a, uint32x4x4_t b) {
// CHECK: store [4 x <2 x i64>] [[B]].coerce, [4 x <2 x i64>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x2x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x2x4_t, %struct.uint64x2x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL]], i64 0, i64 0
@@ -12343,7 +12343,7 @@ void test_vst4q_u64(uint64_t *a, uint64x2x4_t b) {
// CHECK: store [4 x <16 x i8>] [[B]].coerce, [4 x <16 x i8>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x16x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
@@ -12369,7 +12369,7 @@ void test_vst4q_s8(int8_t *a, int8x16x4_t b) {
// CHECK: store [4 x <8 x i16>] [[B]].coerce, [4 x <8 x i16>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL]], i64 0, i64 0
@@ -12404,7 +12404,7 @@ void test_vst4q_s16(int16_t *a, int16x8x4_t b) {
// CHECK: store [4 x <4 x i32>] [[B]].coerce, [4 x <4 x i32>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL]], i64 0, i64 0
@@ -12439,7 +12439,7 @@ void test_vst4q_s32(int32_t *a, int32x4x4_t b) {
// CHECK: store [4 x <2 x i64>] [[B]].coerce, [4 x <2 x i64>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x2x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x2x4_t, %struct.int64x2x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL]], i64 0, i64 0
@@ -12474,7 +12474,7 @@ void test_vst4q_s64(int64_t *a, int64x2x4_t b) {
// CHECK: store [4 x <8 x half>] [[B]].coerce, [4 x <8 x half>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL]], i64 0, i64 0
@@ -12509,7 +12509,7 @@ void test_vst4q_f16(float16_t *a, float16x8x4_t b) {
// CHECK: store [4 x <4 x float>] [[B]].coerce, [4 x <4 x float>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x float>], [4 x <4 x float>]* [[VAL]], i64 0, i64 0
@@ -12544,7 +12544,7 @@ void test_vst4q_f32(float32_t *a, float32x4x4_t b) {
// CHECK: store [4 x <2 x double>] [[B]].coerce, [4 x <2 x double>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x2x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float64x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast double* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float64x2x4_t, %struct.float64x2x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x double>], [4 x <2 x double>]* [[VAL]], i64 0, i64 0
@@ -12579,7 +12579,7 @@ void test_vst4q_f64(float64_t *a, float64x2x4_t b) {
// CHECK: store [4 x <16 x i8>] [[B]].coerce, [4 x <16 x i8>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x16x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
@@ -12605,7 +12605,7 @@ void test_vst4q_p8(poly8_t *a, poly8x16x4_t b) {
// CHECK: store [4 x <8 x i16>] [[B]].coerce, [4 x <8 x i16>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL]], i64 0, i64 0
@@ -12640,7 +12640,7 @@ void test_vst4q_p16(poly16_t *a, poly16x8x4_t b) {
// CHECK: store [4 x <8 x i8>] [[B]].coerce, [4 x <8 x i8>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -12666,7 +12666,7 @@ void test_vst4_u8(uint8_t *a, uint8x8x4_t b) {
// CHECK: store [4 x <4 x i16>] [[B]].coerce, [4 x <4 x i16>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x4x4_t, %struct.uint16x4x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL]], i64 0, i64 0
@@ -12701,7 +12701,7 @@ void test_vst4_u16(uint16_t *a, uint16x4x4_t b) {
// CHECK: store [4 x <2 x i32>] [[B]].coerce, [4 x <2 x i32>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x2x4_t, %struct.uint32x2x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL]], i64 0, i64 0
@@ -12736,7 +12736,7 @@ void test_vst4_u32(uint32_t *a, uint32x2x4_t b) {
// CHECK: store [4 x <1 x i64>] [[B]].coerce, [4 x <1 x i64>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x1x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x1x4_t, %struct.uint64x1x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL]], i64 0, i64 0
@@ -12771,7 +12771,7 @@ void test_vst4_u64(uint64_t *a, uint64x1x4_t b) {
// CHECK: store [4 x <8 x i8>] [[B]].coerce, [4 x <8 x i8>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x8x4_t, %struct.int8x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -12797,7 +12797,7 @@ void test_vst4_s8(int8_t *a, int8x8x4_t b) {
// CHECK: store [4 x <4 x i16>] [[B]].coerce, [4 x <4 x i16>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x4x4_t, %struct.int16x4x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL]], i64 0, i64 0
@@ -12832,7 +12832,7 @@ void test_vst4_s16(int16_t *a, int16x4x4_t b) {
// CHECK: store [4 x <2 x i32>] [[B]].coerce, [4 x <2 x i32>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x2x4_t, %struct.int32x2x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL]], i64 0, i64 0
@@ -12867,7 +12867,7 @@ void test_vst4_s32(int32_t *a, int32x2x4_t b) {
// CHECK: store [4 x <1 x i64>] [[B]].coerce, [4 x <1 x i64>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x1x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x1x4_t, %struct.int64x1x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL]], i64 0, i64 0
@@ -12902,7 +12902,7 @@ void test_vst4_s64(int64_t *a, int64x1x4_t b) {
// CHECK: store [4 x <4 x half>] [[B]].coerce, [4 x <4 x half>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x4x4_t, %struct.float16x4x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x half>], [4 x <4 x half>]* [[VAL]], i64 0, i64 0
@@ -12937,7 +12937,7 @@ void test_vst4_f16(float16_t *a, float16x4x4_t b) {
// CHECK: store [4 x <2 x float>] [[B]].coerce, [4 x <2 x float>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x2x4_t, %struct.float32x2x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x float>], [4 x <2 x float>]* [[VAL]], i64 0, i64 0
@@ -12972,7 +12972,7 @@ void test_vst4_f32(float32_t *a, float32x2x4_t b) {
// CHECK: store [4 x <1 x double>] [[B]].coerce, [4 x <1 x double>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x1x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float64x1x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast double* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float64x1x4_t, %struct.float64x1x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <1 x double>], [4 x <1 x double>]* [[VAL]], i64 0, i64 0
@@ -13007,7 +13007,7 @@ void test_vst4_f64(float64_t *a, float64x1x4_t b) {
// CHECK: store [4 x <8 x i8>] [[B]].coerce, [4 x <8 x i8>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -13033,7 +13033,7 @@ void test_vst4_p8(poly8_t *a, poly8x8x4_t b) {
// CHECK: store [4 x <4 x i16>] [[B]].coerce, [4 x <4 x i16>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x4x4_t, %struct.poly16x4x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL]], i64 0, i64 0
@@ -13061,182 +13061,6 @@ void test_vst4_p16(poly16_t *a, poly16x4x4_t b) {
vst4_p16(a, b);
}
-// CHECK-LABEL: @test_vld1q_u8_x2(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x16x2_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.uint8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET]] to i8*
-// CHECK: [[VLD1XN:%.*]] = call { <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld1x2.v16i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8> }*
-// CHECK: store { <16 x i8>, <16 x i8> } [[VLD1XN]], { <16 x i8>, <16 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x16x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 32, i32 16, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.uint8x16x2_t [[TMP4]]
-uint8x16x2_t test_vld1q_u8_x2(uint8_t const *a) {
- return vld1q_u8_x2(a);
-}
-
-// CHECK-LABEL: @test_vld1q_u16_x2(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x8x2_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD1XN:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld1x2.v8i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16> } [[VLD1XN]], { <8 x i16>, <8 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x8x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.uint16x8x2_t [[TMP6]]
-uint16x8x2_t test_vld1q_u16_x2(uint16_t const *a) {
- return vld1q_u16_x2(a);
-}
-
-// CHECK-LABEL: @test_vld1q_u32_x2(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x4x2_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
-// CHECK: [[VLD1XN:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld1x2.v4i32.p0i32(i32* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32> }*
-// CHECK: store { <4 x i32>, <4 x i32> } [[VLD1XN]], { <4 x i32>, <4 x i32> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x4x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.uint32x4x2_t [[TMP6]]
-uint32x4x2_t test_vld1q_u32_x2(uint32_t const *a) {
- return vld1q_u32_x2(a);
-}
-
-// CHECK-LABEL: @test_vld1q_u64_x2(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint64x2x2_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.uint64x2x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x2x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
-// CHECK: [[VLD1XN:%.*]] = call { <2 x i64>, <2 x i64> } @llvm.aarch64.neon.ld1x2.v2i64.p0i64(i64* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i64>, <2 x i64> }*
-// CHECK: store { <2 x i64>, <2 x i64> } [[VLD1XN]], { <2 x i64>, <2 x i64> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x2x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint64x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.uint64x2x2_t, %struct.uint64x2x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.uint64x2x2_t [[TMP6]]
-uint64x2x2_t test_vld1q_u64_x2(uint64_t const *a) {
- return vld1q_u64_x2(a);
-}
-
-// CHECK-LABEL: @test_vld1q_s8_x2(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x16x2_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.int8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[__RET]] to i8*
-// CHECK: [[VLD1XN:%.*]] = call { <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld1x2.v16i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8> }*
-// CHECK: store { <16 x i8>, <16 x i8> } [[VLD1XN]], { <16 x i8>, <16 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x16x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 32, i32 16, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.int8x16x2_t, %struct.int8x16x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.int8x16x2_t [[TMP4]]
-int8x16x2_t test_vld1q_s8_x2(int8_t const *a) {
- return vld1q_s8_x2(a);
-}
-
-// CHECK-LABEL: @test_vld1q_s16_x2(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x8x2_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.int16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD1XN:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld1x2.v8i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16> } [[VLD1XN]], { <8 x i16>, <8 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x8x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.int16x8x2_t, %struct.int16x8x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.int16x8x2_t [[TMP6]]
-int16x8x2_t test_vld1q_s16_x2(int16_t const *a) {
- return vld1q_s16_x2(a);
-}
-
-// CHECK-LABEL: @test_vld1q_s32_x2(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x4x2_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.int32x4x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
-// CHECK: [[VLD1XN:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld1x2.v4i32.p0i32(i32* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32> }*
-// CHECK: store { <4 x i32>, <4 x i32> } [[VLD1XN]], { <4 x i32>, <4 x i32> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x4x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.int32x4x2_t, %struct.int32x4x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.int32x4x2_t [[TMP6]]
-int32x4x2_t test_vld1q_s32_x2(int32_t const *a) {
- return vld1q_s32_x2(a);
-}
-
-// CHECK-LABEL: @test_vld1q_s64_x2(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int64x2x2_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.int64x2x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x2x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
-// CHECK: [[VLD1XN:%.*]] = call { <2 x i64>, <2 x i64> } @llvm.aarch64.neon.ld1x2.v2i64.p0i64(i64* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i64>, <2 x i64> }*
-// CHECK: store { <2 x i64>, <2 x i64> } [[VLD1XN]], { <2 x i64>, <2 x i64> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x2x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int64x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.int64x2x2_t, %struct.int64x2x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.int64x2x2_t [[TMP6]]
-int64x2x2_t test_vld1q_s64_x2(int64_t const *a) {
- return vld1q_s64_x2(a);
-}
-
-// CHECK-LABEL: @test_vld1q_f16_x2(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x8x2_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half*
-// CHECK: [[VLD1XN:%.*]] = call { <8 x half>, <8 x half> } @llvm.aarch64.neon.ld1x2.v8f16.p0f16(half* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x half>, <8 x half> }*
-// CHECK: store { <8 x half>, <8 x half> } [[VLD1XN]], { <8 x half>, <8 x half> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x8x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.float16x8x2_t, %struct.float16x8x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.float16x8x2_t [[TMP6]]
-float16x8x2_t test_vld1q_f16_x2(float16_t const *a) {
- return vld1q_f16_x2(a);
-}
-
-// CHECK-LABEL: @test_vld1q_f32_x2(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x4x2_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.float32x4x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast float* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float*
-// CHECK: [[VLD1XN:%.*]] = call { <4 x float>, <4 x float> } @llvm.aarch64.neon.ld1x2.v4f32.p0f32(float* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x float>, <4 x float> }*
-// CHECK: store { <4 x float>, <4 x float> } [[VLD1XN]], { <4 x float>, <4 x float> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x4x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.float32x4x2_t, %struct.float32x4x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.float32x4x2_t [[TMP6]]
-float32x4x2_t test_vld1q_f32_x2(float32_t const *a) {
- return vld1q_f32_x2(a);
-}
-
// CHECK-LABEL: @test_vld1q_f64_x2(
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x2x2_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.float64x2x2_t, align 16
@@ -13248,47 +13072,13 @@ float32x4x2_t test_vld1q_f32_x2(float32_t const *a) {
// CHECK: store { <2 x double>, <2 x double> } [[VLD1XN]], { <2 x double>, <2 x double> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float64x2x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float64x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 32, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.float64x2x2_t, %struct.float64x2x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.float64x2x2_t [[TMP6]]
float64x2x2_t test_vld1q_f64_x2(float64_t const *a) {
return vld1q_f64_x2(a);
}
-// CHECK-LABEL: @test_vld1q_p8_x2(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x16x2_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.poly8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET]] to i8*
-// CHECK: [[VLD1XN:%.*]] = call { <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld1x2.v16i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8> }*
-// CHECK: store { <16 x i8>, <16 x i8> } [[VLD1XN]], { <16 x i8>, <16 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x16x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 32, i32 16, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.poly8x16x2_t [[TMP4]]
-poly8x16x2_t test_vld1q_p8_x2(poly8_t const *a) {
- return vld1q_p8_x2(a);
-}
-
-// CHECK-LABEL: @test_vld1q_p16_x2(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x8x2_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD1XN:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld1x2.v8i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16> } [[VLD1XN]], { <8 x i16>, <8 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x8x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.poly16x8x2_t [[TMP6]]
-poly16x8x2_t test_vld1q_p16_x2(poly16_t const *a) {
- return vld1q_p16_x2(a);
-}
-
// CHECK-LABEL: @test_vld1q_p64_x2(
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x2x2_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.poly64x2x2_t, align 16
@@ -13300,189 +13090,13 @@ poly16x8x2_t test_vld1q_p16_x2(poly16_t const *a) {
// CHECK: store { <2 x i64>, <2 x i64> } [[VLD1XN]], { <2 x i64>, <2 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.poly64x2x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.poly64x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 32, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.poly64x2x2_t, %struct.poly64x2x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.poly64x2x2_t [[TMP6]]
poly64x2x2_t test_vld1q_p64_x2(poly64_t const *a) {
return vld1q_p64_x2(a);
}
-// CHECK-LABEL: @test_vld1_u8_x2(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x8x2_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.uint8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET]] to i8*
-// CHECK: [[VLD1XN:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld1x2.v8i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8> }*
-// CHECK: store { <8 x i8>, <8 x i8> } [[VLD1XN]], { <8 x i8>, <8 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x8x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 16, i32 8, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.uint8x8x2_t [[TMP4]]
-uint8x8x2_t test_vld1_u8_x2(uint8_t const *a) {
- return vld1_u8_x2(a);
-}
-
-// CHECK-LABEL: @test_vld1_u16_x2(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x4x2_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.uint16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD1XN:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld1x2.v4i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16> } [[VLD1XN]], { <4 x i16>, <4 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x4x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.uint16x4x2_t [[TMP6]]
-uint16x4x2_t test_vld1_u16_x2(uint16_t const *a) {
- return vld1_u16_x2(a);
-}
-
-// CHECK-LABEL: @test_vld1_u32_x2(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x2x2_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.uint32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
-// CHECK: [[VLD1XN:%.*]] = call { <2 x i32>, <2 x i32> } @llvm.aarch64.neon.ld1x2.v2i32.p0i32(i32* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32> }*
-// CHECK: store { <2 x i32>, <2 x i32> } [[VLD1XN]], { <2 x i32>, <2 x i32> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x2x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.uint32x2x2_t [[TMP6]]
-uint32x2x2_t test_vld1_u32_x2(uint32_t const *a) {
- return vld1_u32_x2(a);
-}
-
-// CHECK-LABEL: @test_vld1_u64_x2(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint64x1x2_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.uint64x1x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
-// CHECK: [[VLD1XN:%.*]] = call { <1 x i64>, <1 x i64> } @llvm.aarch64.neon.ld1x2.v1i64.p0i64(i64* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64> }*
-// CHECK: store { <1 x i64>, <1 x i64> } [[VLD1XN]], { <1 x i64>, <1 x i64> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x1x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint64x1x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.uint64x1x2_t, %struct.uint64x1x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.uint64x1x2_t [[TMP6]]
-uint64x1x2_t test_vld1_u64_x2(uint64_t const *a) {
- return vld1_u64_x2(a);
-}
-
-// CHECK-LABEL: @test_vld1_s8_x2(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x8x2_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.int8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[__RET]] to i8*
-// CHECK: [[VLD1XN:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld1x2.v8i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8> }*
-// CHECK: store { <8 x i8>, <8 x i8> } [[VLD1XN]], { <8 x i8>, <8 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x8x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 16, i32 8, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.int8x8x2_t, %struct.int8x8x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.int8x8x2_t [[TMP4]]
-int8x8x2_t test_vld1_s8_x2(int8_t const *a) {
- return vld1_s8_x2(a);
-}
-
-// CHECK-LABEL: @test_vld1_s16_x2(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x4x2_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.int16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD1XN:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld1x2.v4i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16> } [[VLD1XN]], { <4 x i16>, <4 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x4x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.int16x4x2_t, %struct.int16x4x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.int16x4x2_t [[TMP6]]
-int16x4x2_t test_vld1_s16_x2(int16_t const *a) {
- return vld1_s16_x2(a);
-}
-
-// CHECK-LABEL: @test_vld1_s32_x2(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x2x2_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.int32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
-// CHECK: [[VLD1XN:%.*]] = call { <2 x i32>, <2 x i32> } @llvm.aarch64.neon.ld1x2.v2i32.p0i32(i32* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32> }*
-// CHECK: store { <2 x i32>, <2 x i32> } [[VLD1XN]], { <2 x i32>, <2 x i32> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x2x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.int32x2x2_t, %struct.int32x2x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.int32x2x2_t [[TMP6]]
-int32x2x2_t test_vld1_s32_x2(int32_t const *a) {
- return vld1_s32_x2(a);
-}
-
-// CHECK-LABEL: @test_vld1_s64_x2(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int64x1x2_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.int64x1x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
-// CHECK: [[VLD1XN:%.*]] = call { <1 x i64>, <1 x i64> } @llvm.aarch64.neon.ld1x2.v1i64.p0i64(i64* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64> }*
-// CHECK: store { <1 x i64>, <1 x i64> } [[VLD1XN]], { <1 x i64>, <1 x i64> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x1x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int64x1x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.int64x1x2_t, %struct.int64x1x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.int64x1x2_t [[TMP6]]
-int64x1x2_t test_vld1_s64_x2(int64_t const *a) {
- return vld1_s64_x2(a);
-}
-
-// CHECK-LABEL: @test_vld1_f16_x2(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x4x2_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half*
-// CHECK: [[VLD1XN:%.*]] = call { <4 x half>, <4 x half> } @llvm.aarch64.neon.ld1x2.v4f16.p0f16(half* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x half>, <4 x half> }*
-// CHECK: store { <4 x half>, <4 x half> } [[VLD1XN]], { <4 x half>, <4 x half> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x4x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.float16x4x2_t, %struct.float16x4x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.float16x4x2_t [[TMP6]]
-float16x4x2_t test_vld1_f16_x2(float16_t const *a) {
- return vld1_f16_x2(a);
-}
-
-// CHECK-LABEL: @test_vld1_f32_x2(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x2x2_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.float32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast float* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float*
-// CHECK: [[VLD1XN:%.*]] = call { <2 x float>, <2 x float> } @llvm.aarch64.neon.ld1x2.v2f32.p0f32(float* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x float>, <2 x float> }*
-// CHECK: store { <2 x float>, <2 x float> } [[VLD1XN]], { <2 x float>, <2 x float> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x2x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.float32x2x2_t, %struct.float32x2x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.float32x2x2_t [[TMP6]]
-float32x2x2_t test_vld1_f32_x2(float32_t const *a) {
- return vld1_f32_x2(a);
-}
-
// CHECK-LABEL: @test_vld1_f64_x2(
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x1x2_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.float64x1x2_t, align 8
@@ -13494,47 +13108,13 @@ float32x2x2_t test_vld1_f32_x2(float32_t const *a) {
// CHECK: store { <1 x double>, <1 x double> } [[VLD1XN]], { <1 x double>, <1 x double> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float64x1x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float64x1x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 16, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.float64x1x2_t, %struct.float64x1x2_t* [[RETVAL]], align 8
// CHECK: ret %struct.float64x1x2_t [[TMP6]]
float64x1x2_t test_vld1_f64_x2(float64_t const *a) {
return vld1_f64_x2(a);
}
-// CHECK-LABEL: @test_vld1_p8_x2(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x8x2_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.poly8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET]] to i8*
-// CHECK: [[VLD1XN:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld1x2.v8i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8> }*
-// CHECK: store { <8 x i8>, <8 x i8> } [[VLD1XN]], { <8 x i8>, <8 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x8x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 16, i32 8, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.poly8x8x2_t [[TMP4]]
-poly8x8x2_t test_vld1_p8_x2(poly8_t const *a) {
- return vld1_p8_x2(a);
-}
-
-// CHECK-LABEL: @test_vld1_p16_x2(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x4x2_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.poly16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD1XN:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld1x2.v4i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16> } [[VLD1XN]], { <4 x i16>, <4 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x4x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.poly16x4x2_t [[TMP6]]
-poly16x4x2_t test_vld1_p16_x2(poly16_t const *a) {
- return vld1_p16_x2(a);
-}
-
// CHECK-LABEL: @test_vld1_p64_x2(
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x1x2_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.poly64x1x2_t, align 8
@@ -13546,189 +13126,13 @@ poly16x4x2_t test_vld1_p16_x2(poly16_t const *a) {
// CHECK: store { <1 x i64>, <1 x i64> } [[VLD1XN]], { <1 x i64>, <1 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.poly64x1x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.poly64x1x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 16, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.poly64x1x2_t, %struct.poly64x1x2_t* [[RETVAL]], align 8
// CHECK: ret %struct.poly64x1x2_t [[TMP6]]
poly64x1x2_t test_vld1_p64_x2(poly64_t const *a) {
return vld1_p64_x2(a);
}
-// CHECK-LABEL: @test_vld1q_u8_x3(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x16x3_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.uint8x16x3_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x3_t* [[__RET]] to i8*
-// CHECK: [[VLD1XN:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld1x3.v16i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8> }*
-// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8> } [[VLD1XN]], { <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x16x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 48, i32 16, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[RETVAL]], align 16
-// CHECK: ret %struct.uint8x16x3_t [[TMP4]]
-uint8x16x3_t test_vld1q_u8_x3(uint8_t const *a) {
- return vld1q_u8_x3(a);
-}
-
-// CHECK-LABEL: @test_vld1q_u16_x3(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x8x3_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x3_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD1XN:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld1x3.v8i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD1XN]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x8x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[RETVAL]], align 16
-// CHECK: ret %struct.uint16x8x3_t [[TMP6]]
-uint16x8x3_t test_vld1q_u16_x3(uint16_t const *a) {
- return vld1q_u16_x3(a);
-}
-
-// CHECK-LABEL: @test_vld1q_u32_x3(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x4x3_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x3_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
-// CHECK: [[VLD1XN:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld1x3.v4i32.p0i32(i32* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32>, <4 x i32> }*
-// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32> } [[VLD1XN]], { <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x4x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[RETVAL]], align 16
-// CHECK: ret %struct.uint32x4x3_t [[TMP6]]
-uint32x4x3_t test_vld1q_u32_x3(uint32_t const *a) {
- return vld1q_u32_x3(a);
-}
-
-// CHECK-LABEL: @test_vld1q_u64_x3(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint64x2x3_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.uint64x2x3_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x2x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
-// CHECK: [[VLD1XN:%.*]] = call { <2 x i64>, <2 x i64>, <2 x i64> } @llvm.aarch64.neon.ld1x3.v2i64.p0i64(i64* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i64>, <2 x i64>, <2 x i64> }*
-// CHECK: store { <2 x i64>, <2 x i64>, <2 x i64> } [[VLD1XN]], { <2 x i64>, <2 x i64>, <2 x i64> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x2x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint64x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.uint64x2x3_t, %struct.uint64x2x3_t* [[RETVAL]], align 16
-// CHECK: ret %struct.uint64x2x3_t [[TMP6]]
-uint64x2x3_t test_vld1q_u64_x3(uint64_t const *a) {
- return vld1q_u64_x3(a);
-}
-
-// CHECK-LABEL: @test_vld1q_s8_x3(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x16x3_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.int8x16x3_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x3_t* [[__RET]] to i8*
-// CHECK: [[VLD1XN:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld1x3.v16i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8> }*
-// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8> } [[VLD1XN]], { <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x16x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 48, i32 16, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.int8x16x3_t, %struct.int8x16x3_t* [[RETVAL]], align 16
-// CHECK: ret %struct.int8x16x3_t [[TMP4]]
-int8x16x3_t test_vld1q_s8_x3(int8_t const *a) {
- return vld1q_s8_x3(a);
-}
-
-// CHECK-LABEL: @test_vld1q_s16_x3(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x8x3_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.int16x8x3_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD1XN:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld1x3.v8i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD1XN]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x8x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.int16x8x3_t, %struct.int16x8x3_t* [[RETVAL]], align 16
-// CHECK: ret %struct.int16x8x3_t [[TMP6]]
-int16x8x3_t test_vld1q_s16_x3(int16_t const *a) {
- return vld1q_s16_x3(a);
-}
-
-// CHECK-LABEL: @test_vld1q_s32_x3(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x4x3_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.int32x4x3_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
-// CHECK: [[VLD1XN:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld1x3.v4i32.p0i32(i32* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32>, <4 x i32> }*
-// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32> } [[VLD1XN]], { <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x4x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.int32x4x3_t, %struct.int32x4x3_t* [[RETVAL]], align 16
-// CHECK: ret %struct.int32x4x3_t [[TMP6]]
-int32x4x3_t test_vld1q_s32_x3(int32_t const *a) {
- return vld1q_s32_x3(a);
-}
-
-// CHECK-LABEL: @test_vld1q_s64_x3(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int64x2x3_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.int64x2x3_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x2x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
-// CHECK: [[VLD1XN:%.*]] = call { <2 x i64>, <2 x i64>, <2 x i64> } @llvm.aarch64.neon.ld1x3.v2i64.p0i64(i64* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i64>, <2 x i64>, <2 x i64> }*
-// CHECK: store { <2 x i64>, <2 x i64>, <2 x i64> } [[VLD1XN]], { <2 x i64>, <2 x i64>, <2 x i64> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x2x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int64x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.int64x2x3_t, %struct.int64x2x3_t* [[RETVAL]], align 16
-// CHECK: ret %struct.int64x2x3_t [[TMP6]]
-int64x2x3_t test_vld1q_s64_x3(int64_t const *a) {
- return vld1q_s64_x3(a);
-}
-
-// CHECK-LABEL: @test_vld1q_f16_x3(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x8x3_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x3_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half*
-// CHECK: [[VLD1XN:%.*]] = call { <8 x half>, <8 x half>, <8 x half> } @llvm.aarch64.neon.ld1x3.v8f16.p0f16(half* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x half>, <8 x half>, <8 x half> }*
-// CHECK: store { <8 x half>, <8 x half>, <8 x half> } [[VLD1XN]], { <8 x half>, <8 x half>, <8 x half> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x8x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.float16x8x3_t, %struct.float16x8x3_t* [[RETVAL]], align 16
-// CHECK: ret %struct.float16x8x3_t [[TMP6]]
-float16x8x3_t test_vld1q_f16_x3(float16_t const *a) {
- return vld1q_f16_x3(a);
-}
-
-// CHECK-LABEL: @test_vld1q_f32_x3(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x4x3_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.float32x4x3_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast float* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float*
-// CHECK: [[VLD1XN:%.*]] = call { <4 x float>, <4 x float>, <4 x float> } @llvm.aarch64.neon.ld1x3.v4f32.p0f32(float* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x float>, <4 x float>, <4 x float> }*
-// CHECK: store { <4 x float>, <4 x float>, <4 x float> } [[VLD1XN]], { <4 x float>, <4 x float>, <4 x float> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x4x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.float32x4x3_t, %struct.float32x4x3_t* [[RETVAL]], align 16
-// CHECK: ret %struct.float32x4x3_t [[TMP6]]
-float32x4x3_t test_vld1q_f32_x3(float32_t const *a) {
- return vld1q_f32_x3(a);
-}
-
// CHECK-LABEL: @test_vld1q_f64_x3(
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x2x3_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.float64x2x3_t, align 16
@@ -13740,47 +13144,13 @@ float32x4x3_t test_vld1q_f32_x3(float32_t const *a) {
// CHECK: store { <2 x double>, <2 x double>, <2 x double> } [[VLD1XN]], { <2 x double>, <2 x double>, <2 x double> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float64x2x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float64x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 48, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.float64x2x3_t, %struct.float64x2x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.float64x2x3_t [[TMP6]]
float64x2x3_t test_vld1q_f64_x3(float64_t const *a) {
return vld1q_f64_x3(a);
}
-// CHECK-LABEL: @test_vld1q_p8_x3(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x16x3_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.poly8x16x3_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x3_t* [[__RET]] to i8*
-// CHECK: [[VLD1XN:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld1x3.v16i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8> }*
-// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8> } [[VLD1XN]], { <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x16x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 48, i32 16, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[RETVAL]], align 16
-// CHECK: ret %struct.poly8x16x3_t [[TMP4]]
-poly8x16x3_t test_vld1q_p8_x3(poly8_t const *a) {
- return vld1q_p8_x3(a);
-}
-
-// CHECK-LABEL: @test_vld1q_p16_x3(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x8x3_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x3_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD1XN:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld1x3.v8i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD1XN]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x8x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[RETVAL]], align 16
-// CHECK: ret %struct.poly16x8x3_t [[TMP6]]
-poly16x8x3_t test_vld1q_p16_x3(poly16_t const *a) {
- return vld1q_p16_x3(a);
-}
-
// CHECK-LABEL: @test_vld1q_p64_x3(
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x2x3_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.poly64x2x3_t, align 16
@@ -13792,189 +13162,13 @@ poly16x8x3_t test_vld1q_p16_x3(poly16_t const *a) {
// CHECK: store { <2 x i64>, <2 x i64>, <2 x i64> } [[VLD1XN]], { <2 x i64>, <2 x i64>, <2 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.poly64x2x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.poly64x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 48, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.poly64x2x3_t, %struct.poly64x2x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.poly64x2x3_t [[TMP6]]
poly64x2x3_t test_vld1q_p64_x3(poly64_t const *a) {
return vld1q_p64_x3(a);
}
-// CHECK-LABEL: @test_vld1_u8_x3(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x8x3_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.uint8x8x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x3_t* [[__RET]] to i8*
-// CHECK: [[VLD1XN:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld1x3.v8i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8> }*
-// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD1XN]], { <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x8x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 24, i32 8, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.uint8x8x3_t, %struct.uint8x8x3_t* [[RETVAL]], align 8
-// CHECK: ret %struct.uint8x8x3_t [[TMP4]]
-uint8x8x3_t test_vld1_u8_x3(uint8_t const *a) {
- return vld1_u8_x3(a);
-}
-
-// CHECK-LABEL: @test_vld1_u16_x3(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x4x3_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.uint16x4x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD1XN:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld1x3.v4i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD1XN]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x4x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.uint16x4x3_t, %struct.uint16x4x3_t* [[RETVAL]], align 8
-// CHECK: ret %struct.uint16x4x3_t [[TMP6]]
-uint16x4x3_t test_vld1_u16_x3(uint16_t const *a) {
- return vld1_u16_x3(a);
-}
-
-// CHECK-LABEL: @test_vld1_u32_x3(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x2x3_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.uint32x2x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
-// CHECK: [[VLD1XN:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32> } @llvm.aarch64.neon.ld1x3.v2i32.p0i32(i32* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32>, <2 x i32> }*
-// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32> } [[VLD1XN]], { <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x2x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.uint32x2x3_t, %struct.uint32x2x3_t* [[RETVAL]], align 8
-// CHECK: ret %struct.uint32x2x3_t [[TMP6]]
-uint32x2x3_t test_vld1_u32_x3(uint32_t const *a) {
- return vld1_u32_x3(a);
-}
-
-// CHECK-LABEL: @test_vld1_u64_x3(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint64x1x3_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.uint64x1x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
-// CHECK: [[VLD1XN:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64> } @llvm.aarch64.neon.ld1x3.v1i64.p0i64(i64* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64>, <1 x i64> }*
-// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64> } [[VLD1XN]], { <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x1x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint64x1x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.uint64x1x3_t, %struct.uint64x1x3_t* [[RETVAL]], align 8
-// CHECK: ret %struct.uint64x1x3_t [[TMP6]]
-uint64x1x3_t test_vld1_u64_x3(uint64_t const *a) {
- return vld1_u64_x3(a);
-}
-
-// CHECK-LABEL: @test_vld1_s8_x3(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x8x3_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.int8x8x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x3_t* [[__RET]] to i8*
-// CHECK: [[VLD1XN:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld1x3.v8i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8> }*
-// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD1XN]], { <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x8x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 24, i32 8, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.int8x8x3_t, %struct.int8x8x3_t* [[RETVAL]], align 8
-// CHECK: ret %struct.int8x8x3_t [[TMP4]]
-int8x8x3_t test_vld1_s8_x3(int8_t const *a) {
- return vld1_s8_x3(a);
-}
-
-// CHECK-LABEL: @test_vld1_s16_x3(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x4x3_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.int16x4x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD1XN:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld1x3.v4i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD1XN]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x4x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.int16x4x3_t, %struct.int16x4x3_t* [[RETVAL]], align 8
-// CHECK: ret %struct.int16x4x3_t [[TMP6]]
-int16x4x3_t test_vld1_s16_x3(int16_t const *a) {
- return vld1_s16_x3(a);
-}
-
-// CHECK-LABEL: @test_vld1_s32_x3(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x2x3_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.int32x2x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
-// CHECK: [[VLD1XN:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32> } @llvm.aarch64.neon.ld1x3.v2i32.p0i32(i32* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32>, <2 x i32> }*
-// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32> } [[VLD1XN]], { <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x2x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.int32x2x3_t, %struct.int32x2x3_t* [[RETVAL]], align 8
-// CHECK: ret %struct.int32x2x3_t [[TMP6]]
-int32x2x3_t test_vld1_s32_x3(int32_t const *a) {
- return vld1_s32_x3(a);
-}
-
-// CHECK-LABEL: @test_vld1_s64_x3(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int64x1x3_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.int64x1x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
-// CHECK: [[VLD1XN:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64> } @llvm.aarch64.neon.ld1x3.v1i64.p0i64(i64* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64>, <1 x i64> }*
-// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64> } [[VLD1XN]], { <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x1x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int64x1x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.int64x1x3_t, %struct.int64x1x3_t* [[RETVAL]], align 8
-// CHECK: ret %struct.int64x1x3_t [[TMP6]]
-int64x1x3_t test_vld1_s64_x3(int64_t const *a) {
- return vld1_s64_x3(a);
-}
-
-// CHECK-LABEL: @test_vld1_f16_x3(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x4x3_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half*
-// CHECK: [[VLD1XN:%.*]] = call { <4 x half>, <4 x half>, <4 x half> } @llvm.aarch64.neon.ld1x3.v4f16.p0f16(half* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x half>, <4 x half>, <4 x half> }*
-// CHECK: store { <4 x half>, <4 x half>, <4 x half> } [[VLD1XN]], { <4 x half>, <4 x half>, <4 x half> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x4x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.float16x4x3_t, %struct.float16x4x3_t* [[RETVAL]], align 8
-// CHECK: ret %struct.float16x4x3_t [[TMP6]]
-float16x4x3_t test_vld1_f16_x3(float16_t const *a) {
- return vld1_f16_x3(a);
-}
-
-// CHECK-LABEL: @test_vld1_f32_x3(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x2x3_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.float32x2x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast float* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float*
-// CHECK: [[VLD1XN:%.*]] = call { <2 x float>, <2 x float>, <2 x float> } @llvm.aarch64.neon.ld1x3.v2f32.p0f32(float* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x float>, <2 x float>, <2 x float> }*
-// CHECK: store { <2 x float>, <2 x float>, <2 x float> } [[VLD1XN]], { <2 x float>, <2 x float>, <2 x float> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x2x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.float32x2x3_t, %struct.float32x2x3_t* [[RETVAL]], align 8
-// CHECK: ret %struct.float32x2x3_t [[TMP6]]
-float32x2x3_t test_vld1_f32_x3(float32_t const *a) {
- return vld1_f32_x3(a);
-}
-
// CHECK-LABEL: @test_vld1_f64_x3(
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x1x3_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.float64x1x3_t, align 8
@@ -13986,47 +13180,13 @@ float32x2x3_t test_vld1_f32_x3(float32_t const *a) {
// CHECK: store { <1 x double>, <1 x double>, <1 x double> } [[VLD1XN]], { <1 x double>, <1 x double>, <1 x double> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float64x1x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float64x1x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 24, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.float64x1x3_t, %struct.float64x1x3_t* [[RETVAL]], align 8
// CHECK: ret %struct.float64x1x3_t [[TMP6]]
float64x1x3_t test_vld1_f64_x3(float64_t const *a) {
return vld1_f64_x3(a);
}
-// CHECK-LABEL: @test_vld1_p8_x3(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x8x3_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.poly8x8x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x3_t* [[__RET]] to i8*
-// CHECK: [[VLD1XN:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld1x3.v8i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8> }*
-// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD1XN]], { <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x8x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 24, i32 8, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.poly8x8x3_t, %struct.poly8x8x3_t* [[RETVAL]], align 8
-// CHECK: ret %struct.poly8x8x3_t [[TMP4]]
-poly8x8x3_t test_vld1_p8_x3(poly8_t const *a) {
- return vld1_p8_x3(a);
-}
-
-// CHECK-LABEL: @test_vld1_p16_x3(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x4x3_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.poly16x4x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD1XN:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld1x3.v4i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD1XN]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x4x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.poly16x4x3_t, %struct.poly16x4x3_t* [[RETVAL]], align 8
-// CHECK: ret %struct.poly16x4x3_t [[TMP6]]
-poly16x4x3_t test_vld1_p16_x3(poly16_t const *a) {
- return vld1_p16_x3(a);
-}
-
// CHECK-LABEL: @test_vld1_p64_x3(
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x1x3_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.poly64x1x3_t, align 8
@@ -14038,189 +13198,13 @@ poly16x4x3_t test_vld1_p16_x3(poly16_t const *a) {
// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64> } [[VLD1XN]], { <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.poly64x1x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.poly64x1x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 24, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.poly64x1x3_t, %struct.poly64x1x3_t* [[RETVAL]], align 8
// CHECK: ret %struct.poly64x1x3_t [[TMP6]]
poly64x1x3_t test_vld1_p64_x3(poly64_t const *a) {
return vld1_p64_x3(a);
}
-// CHECK-LABEL: @test_vld1q_u8_x4(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x16x4_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.uint8x16x4_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x4_t* [[__RET]] to i8*
-// CHECK: [[VLD1XN:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld1x4.v16i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }*
-// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } [[VLD1XN]], { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x16x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 64, i32 16, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[RETVAL]], align 16
-// CHECK: ret %struct.uint8x16x4_t [[TMP4]]
-uint8x16x4_t test_vld1q_u8_x4(uint8_t const *a) {
- return vld1q_u8_x4(a);
-}
-
-// CHECK-LABEL: @test_vld1q_u16_x4(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x8x4_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x4_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD1XN:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld1x4.v8i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } [[VLD1XN]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x8x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[RETVAL]], align 16
-// CHECK: ret %struct.uint16x8x4_t [[TMP6]]
-uint16x8x4_t test_vld1q_u16_x4(uint16_t const *a) {
- return vld1q_u16_x4(a);
-}
-
-// CHECK-LABEL: @test_vld1q_u32_x4(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x4x4_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x4_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
-// CHECK: [[VLD1XN:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld1x4.v4i32.p0i32(i32* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> }*
-// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLD1XN]], { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x4x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[RETVAL]], align 16
-// CHECK: ret %struct.uint32x4x4_t [[TMP6]]
-uint32x4x4_t test_vld1q_u32_x4(uint32_t const *a) {
- return vld1q_u32_x4(a);
-}
-
-// CHECK-LABEL: @test_vld1q_u64_x4(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint64x2x4_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.uint64x2x4_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x2x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
-// CHECK: [[VLD1XN:%.*]] = call { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } @llvm.aarch64.neon.ld1x4.v2i64.p0i64(i64* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> }*
-// CHECK: store { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } [[VLD1XN]], { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x2x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint64x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.uint64x2x4_t, %struct.uint64x2x4_t* [[RETVAL]], align 16
-// CHECK: ret %struct.uint64x2x4_t [[TMP6]]
-uint64x2x4_t test_vld1q_u64_x4(uint64_t const *a) {
- return vld1q_u64_x4(a);
-}
-
-// CHECK-LABEL: @test_vld1q_s8_x4(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x16x4_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.int8x16x4_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x4_t* [[__RET]] to i8*
-// CHECK: [[VLD1XN:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld1x4.v16i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }*
-// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } [[VLD1XN]], { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x16x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 64, i32 16, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.int8x16x4_t, %struct.int8x16x4_t* [[RETVAL]], align 16
-// CHECK: ret %struct.int8x16x4_t [[TMP4]]
-int8x16x4_t test_vld1q_s8_x4(int8_t const *a) {
- return vld1q_s8_x4(a);
-}
-
-// CHECK-LABEL: @test_vld1q_s16_x4(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x8x4_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.int16x8x4_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD1XN:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld1x4.v8i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } [[VLD1XN]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x8x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.int16x8x4_t, %struct.int16x8x4_t* [[RETVAL]], align 16
-// CHECK: ret %struct.int16x8x4_t [[TMP6]]
-int16x8x4_t test_vld1q_s16_x4(int16_t const *a) {
- return vld1q_s16_x4(a);
-}
-
-// CHECK-LABEL: @test_vld1q_s32_x4(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x4x4_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.int32x4x4_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
-// CHECK: [[VLD1XN:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld1x4.v4i32.p0i32(i32* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> }*
-// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLD1XN]], { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x4x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.int32x4x4_t, %struct.int32x4x4_t* [[RETVAL]], align 16
-// CHECK: ret %struct.int32x4x4_t [[TMP6]]
-int32x4x4_t test_vld1q_s32_x4(int32_t const *a) {
- return vld1q_s32_x4(a);
-}
-
-// CHECK-LABEL: @test_vld1q_s64_x4(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int64x2x4_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.int64x2x4_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x2x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
-// CHECK: [[VLD1XN:%.*]] = call { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } @llvm.aarch64.neon.ld1x4.v2i64.p0i64(i64* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> }*
-// CHECK: store { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } [[VLD1XN]], { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x2x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int64x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.int64x2x4_t, %struct.int64x2x4_t* [[RETVAL]], align 16
-// CHECK: ret %struct.int64x2x4_t [[TMP6]]
-int64x2x4_t test_vld1q_s64_x4(int64_t const *a) {
- return vld1q_s64_x4(a);
-}
-
-// CHECK-LABEL: @test_vld1q_f16_x4(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x8x4_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x4_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half*
-// CHECK: [[VLD1XN:%.*]] = call { <8 x half>, <8 x half>, <8 x half>, <8 x half> } @llvm.aarch64.neon.ld1x4.v8f16.p0f16(half* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x half>, <8 x half>, <8 x half>, <8 x half> }*
-// CHECK: store { <8 x half>, <8 x half>, <8 x half>, <8 x half> } [[VLD1XN]], { <8 x half>, <8 x half>, <8 x half>, <8 x half> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x8x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.float16x8x4_t, %struct.float16x8x4_t* [[RETVAL]], align 16
-// CHECK: ret %struct.float16x8x4_t [[TMP6]]
-float16x8x4_t test_vld1q_f16_x4(float16_t const *a) {
- return vld1q_f16_x4(a);
-}
-
-// CHECK-LABEL: @test_vld1q_f32_x4(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x4x4_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.float32x4x4_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast float* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float*
-// CHECK: [[VLD1XN:%.*]] = call { <4 x float>, <4 x float>, <4 x float>, <4 x float> } @llvm.aarch64.neon.ld1x4.v4f32.p0f32(float* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x float>, <4 x float>, <4 x float>, <4 x float> }*
-// CHECK: store { <4 x float>, <4 x float>, <4 x float>, <4 x float> } [[VLD1XN]], { <4 x float>, <4 x float>, <4 x float>, <4 x float> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x4x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.float32x4x4_t, %struct.float32x4x4_t* [[RETVAL]], align 16
-// CHECK: ret %struct.float32x4x4_t [[TMP6]]
-float32x4x4_t test_vld1q_f32_x4(float32_t const *a) {
- return vld1q_f32_x4(a);
-}
-
// CHECK-LABEL: @test_vld1q_f64_x4(
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x2x4_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.float64x2x4_t, align 16
@@ -14232,47 +13216,13 @@ float32x4x4_t test_vld1q_f32_x4(float32_t const *a) {
// CHECK: store { <2 x double>, <2 x double>, <2 x double>, <2 x double> } [[VLD1XN]], { <2 x double>, <2 x double>, <2 x double>, <2 x double> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float64x2x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float64x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 64, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.float64x2x4_t, %struct.float64x2x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.float64x2x4_t [[TMP6]]
float64x2x4_t test_vld1q_f64_x4(float64_t const *a) {
return vld1q_f64_x4(a);
}
-// CHECK-LABEL: @test_vld1q_p8_x4(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x16x4_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.poly8x16x4_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x4_t* [[__RET]] to i8*
-// CHECK: [[VLD1XN:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld1x4.v16i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }*
-// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } [[VLD1XN]], { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x16x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 64, i32 16, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[RETVAL]], align 16
-// CHECK: ret %struct.poly8x16x4_t [[TMP4]]
-poly8x16x4_t test_vld1q_p8_x4(poly8_t const *a) {
- return vld1q_p8_x4(a);
-}
-
-// CHECK-LABEL: @test_vld1q_p16_x4(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x8x4_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x4_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD1XN:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld1x4.v8i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } [[VLD1XN]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x8x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[RETVAL]], align 16
-// CHECK: ret %struct.poly16x8x4_t [[TMP6]]
-poly16x8x4_t test_vld1q_p16_x4(poly16_t const *a) {
- return vld1q_p16_x4(a);
-}
-
// CHECK-LABEL: @test_vld1q_p64_x4(
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x2x4_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.poly64x2x4_t, align 16
@@ -14284,189 +13234,13 @@ poly16x8x4_t test_vld1q_p16_x4(poly16_t const *a) {
// CHECK: store { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } [[VLD1XN]], { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.poly64x2x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.poly64x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 64, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.poly64x2x4_t, %struct.poly64x2x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.poly64x2x4_t [[TMP6]]
poly64x2x4_t test_vld1q_p64_x4(poly64_t const *a) {
return vld1q_p64_x4(a);
}
-// CHECK-LABEL: @test_vld1_u8_x4(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x8x4_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.uint8x8x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x4_t* [[__RET]] to i8*
-// CHECK: [[VLD1XN:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld1x4.v8i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }*
-// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[VLD1XN]], { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x8x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 32, i32 8, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[RETVAL]], align 8
-// CHECK: ret %struct.uint8x8x4_t [[TMP4]]
-uint8x8x4_t test_vld1_u8_x4(uint8_t const *a) {
- return vld1_u8_x4(a);
-}
-
-// CHECK-LABEL: @test_vld1_u16_x4(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x4x4_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.uint16x4x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD1XN:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld1x4.v4i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD1XN]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x4x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.uint16x4x4_t, %struct.uint16x4x4_t* [[RETVAL]], align 8
-// CHECK: ret %struct.uint16x4x4_t [[TMP6]]
-uint16x4x4_t test_vld1_u16_x4(uint16_t const *a) {
- return vld1_u16_x4(a);
-}
-
-// CHECK-LABEL: @test_vld1_u32_x4(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x2x4_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.uint32x2x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
-// CHECK: [[VLD1XN:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } @llvm.aarch64.neon.ld1x4.v2i32.p0i32(i32* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }*
-// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[VLD1XN]], { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x2x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.uint32x2x4_t, %struct.uint32x2x4_t* [[RETVAL]], align 8
-// CHECK: ret %struct.uint32x2x4_t [[TMP6]]
-uint32x2x4_t test_vld1_u32_x4(uint32_t const *a) {
- return vld1_u32_x4(a);
-}
-
-// CHECK-LABEL: @test_vld1_u64_x4(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint64x1x4_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.uint64x1x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
-// CHECK: [[VLD1XN:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } @llvm.aarch64.neon.ld1x4.v1i64.p0i64(i64* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }*
-// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } [[VLD1XN]], { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x1x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint64x1x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.uint64x1x4_t, %struct.uint64x1x4_t* [[RETVAL]], align 8
-// CHECK: ret %struct.uint64x1x4_t [[TMP6]]
-uint64x1x4_t test_vld1_u64_x4(uint64_t const *a) {
- return vld1_u64_x4(a);
-}
-
-// CHECK-LABEL: @test_vld1_s8_x4(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x8x4_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.int8x8x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x4_t* [[__RET]] to i8*
-// CHECK: [[VLD1XN:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld1x4.v8i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }*
-// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[VLD1XN]], { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x8x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 32, i32 8, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.int8x8x4_t, %struct.int8x8x4_t* [[RETVAL]], align 8
-// CHECK: ret %struct.int8x8x4_t [[TMP4]]
-int8x8x4_t test_vld1_s8_x4(int8_t const *a) {
- return vld1_s8_x4(a);
-}
-
-// CHECK-LABEL: @test_vld1_s16_x4(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x4x4_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.int16x4x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD1XN:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld1x4.v4i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD1XN]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x4x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.int16x4x4_t, %struct.int16x4x4_t* [[RETVAL]], align 8
-// CHECK: ret %struct.int16x4x4_t [[TMP6]]
-int16x4x4_t test_vld1_s16_x4(int16_t const *a) {
- return vld1_s16_x4(a);
-}
-
-// CHECK-LABEL: @test_vld1_s32_x4(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x2x4_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.int32x2x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
-// CHECK: [[VLD1XN:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } @llvm.aarch64.neon.ld1x4.v2i32.p0i32(i32* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }*
-// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[VLD1XN]], { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x2x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.int32x2x4_t, %struct.int32x2x4_t* [[RETVAL]], align 8
-// CHECK: ret %struct.int32x2x4_t [[TMP6]]
-int32x2x4_t test_vld1_s32_x4(int32_t const *a) {
- return vld1_s32_x4(a);
-}
-
-// CHECK-LABEL: @test_vld1_s64_x4(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int64x1x4_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.int64x1x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
-// CHECK: [[VLD1XN:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } @llvm.aarch64.neon.ld1x4.v1i64.p0i64(i64* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }*
-// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } [[VLD1XN]], { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x1x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int64x1x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.int64x1x4_t, %struct.int64x1x4_t* [[RETVAL]], align 8
-// CHECK: ret %struct.int64x1x4_t [[TMP6]]
-int64x1x4_t test_vld1_s64_x4(int64_t const *a) {
- return vld1_s64_x4(a);
-}
-
-// CHECK-LABEL: @test_vld1_f16_x4(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x4x4_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half*
-// CHECK: [[VLD1XN:%.*]] = call { <4 x half>, <4 x half>, <4 x half>, <4 x half> } @llvm.aarch64.neon.ld1x4.v4f16.p0f16(half* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x half>, <4 x half>, <4 x half>, <4 x half> }*
-// CHECK: store { <4 x half>, <4 x half>, <4 x half>, <4 x half> } [[VLD1XN]], { <4 x half>, <4 x half>, <4 x half>, <4 x half> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x4x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.float16x4x4_t, %struct.float16x4x4_t* [[RETVAL]], align 8
-// CHECK: ret %struct.float16x4x4_t [[TMP6]]
-float16x4x4_t test_vld1_f16_x4(float16_t const *a) {
- return vld1_f16_x4(a);
-}
-
-// CHECK-LABEL: @test_vld1_f32_x4(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x2x4_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.float32x2x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast float* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float*
-// CHECK: [[VLD1XN:%.*]] = call { <2 x float>, <2 x float>, <2 x float>, <2 x float> } @llvm.aarch64.neon.ld1x4.v2f32.p0f32(float* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x float>, <2 x float>, <2 x float>, <2 x float> }*
-// CHECK: store { <2 x float>, <2 x float>, <2 x float>, <2 x float> } [[VLD1XN]], { <2 x float>, <2 x float>, <2 x float>, <2 x float> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x2x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.float32x2x4_t, %struct.float32x2x4_t* [[RETVAL]], align 8
-// CHECK: ret %struct.float32x2x4_t [[TMP6]]
-float32x2x4_t test_vld1_f32_x4(float32_t const *a) {
- return vld1_f32_x4(a);
-}
-
// CHECK-LABEL: @test_vld1_f64_x4(
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x1x4_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.float64x1x4_t, align 8
@@ -14478,47 +13252,13 @@ float32x2x4_t test_vld1_f32_x4(float32_t const *a) {
// CHECK: store { <1 x double>, <1 x double>, <1 x double>, <1 x double> } [[VLD1XN]], { <1 x double>, <1 x double>, <1 x double>, <1 x double> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float64x1x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float64x1x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 32, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.float64x1x4_t, %struct.float64x1x4_t* [[RETVAL]], align 8
// CHECK: ret %struct.float64x1x4_t [[TMP6]]
float64x1x4_t test_vld1_f64_x4(float64_t const *a) {
return vld1_f64_x4(a);
}
-// CHECK-LABEL: @test_vld1_p8_x4(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x8x4_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.poly8x8x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x4_t* [[__RET]] to i8*
-// CHECK: [[VLD1XN:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld1x4.v8i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }*
-// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[VLD1XN]], { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x8x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 32, i32 8, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[RETVAL]], align 8
-// CHECK: ret %struct.poly8x8x4_t [[TMP4]]
-poly8x8x4_t test_vld1_p8_x4(poly8_t const *a) {
- return vld1_p8_x4(a);
-}
-
-// CHECK-LABEL: @test_vld1_p16_x4(
-// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x4x4_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.poly16x4x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD1XN:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld1x4.v4i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD1XN]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x4x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.poly16x4x4_t, %struct.poly16x4x4_t* [[RETVAL]], align 8
-// CHECK: ret %struct.poly16x4x4_t [[TMP6]]
-poly16x4x4_t test_vld1_p16_x4(poly16_t const *a) {
- return vld1_p16_x4(a);
-}
-
// CHECK-LABEL: @test_vld1_p64_x4(
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x1x4_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.poly64x1x4_t, align 8
@@ -14530,261 +13270,13 @@ poly16x4x4_t test_vld1_p16_x4(poly16_t const *a) {
// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } [[VLD1XN]], { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.poly64x1x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.poly64x1x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 32, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.poly64x1x4_t, %struct.poly64x1x4_t* [[RETVAL]], align 8
// CHECK: ret %struct.poly64x1x4_t [[TMP6]]
poly64x1x4_t test_vld1_p64_x4(poly64_t const *a) {
return vld1_p64_x4(a);
}
-// CHECK-LABEL: @test_vst1q_u8_x2(
-// CHECK: [[B:%.*]] = alloca %struct.uint8x16x2_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.uint8x16x2_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[B]], i32 0, i32 0
-// CHECK: store [2 x <16 x i8>] [[B]].coerce, [2 x <16 x i8>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x16x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 16
-// CHECK: call void @llvm.aarch64.neon.st1x2.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], i8* %a)
-// CHECK: ret void
-void test_vst1q_u8_x2(uint8_t *a, uint8x16x2_t b) {
- vst1q_u8_x2(a, b);
-}
-
-// CHECK-LABEL: @test_vst1q_u16_x2(
-// CHECK: [[B:%.*]] = alloca %struct.uint16x8x2_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x2_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[B]], i32 0, i32 0
-// CHECK: store [2 x <8 x i16>] [[B]].coerce, [2 x <8 x i16>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16
-// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8>
-// CHECK: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16>
-// CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
-// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i16*
-// CHECK: call void @llvm.aarch64.neon.st1x2.v8i16.p0i16(<8 x i16> [[TMP7]], <8 x i16> [[TMP8]], i16* [[TMP9]])
-// CHECK: ret void
-void test_vst1q_u16_x2(uint16_t *a, uint16x8x2_t b) {
- vst1q_u16_x2(a, b);
-}
-
-// CHECK-LABEL: @test_vst1q_u32_x2(
-// CHECK: [[B:%.*]] = alloca %struct.uint32x4x2_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x2_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[B]], i32 0, i32 0
-// CHECK: store [2 x <4 x i32>] [[B]].coerce, [2 x <4 x i32>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 16
-// CHECK: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP3]] to <16 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 16
-// CHECK: [[TMP6:%.*]] = bitcast <4 x i32> [[TMP5]] to <16 x i8>
-// CHECK: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x i32>
-// CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32>
-// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i32*
-// CHECK: call void @llvm.aarch64.neon.st1x2.v4i32.p0i32(<4 x i32> [[TMP7]], <4 x i32> [[TMP8]], i32* [[TMP9]])
-// CHECK: ret void
-void test_vst1q_u32_x2(uint32_t *a, uint32x4x2_t b) {
- vst1q_u32_x2(a, b);
-}
-
-// CHECK-LABEL: @test_vst1q_u64_x2(
-// CHECK: [[B:%.*]] = alloca %struct.uint64x2x2_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.uint64x2x2_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint64x2x2_t, %struct.uint64x2x2_t* [[B]], i32 0, i32 0
-// CHECK: store [2 x <2 x i64>] [[B]].coerce, [2 x <2 x i64>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x2x2_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x2x2_t, %struct.uint64x2x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x i64>], [2 x <2 x i64>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX]], align 16
-// CHECK: [[TMP4:%.*]] = bitcast <2 x i64> [[TMP3]] to <16 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint64x2x2_t, %struct.uint64x2x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <2 x i64>], [2 x <2 x i64>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX2]], align 16
-// CHECK: [[TMP6:%.*]] = bitcast <2 x i64> [[TMP5]] to <16 x i8>
-// CHECK: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <2 x i64>
-// CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <2 x i64>
-// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i64*
-// CHECK: call void @llvm.aarch64.neon.st1x2.v2i64.p0i64(<2 x i64> [[TMP7]], <2 x i64> [[TMP8]], i64* [[TMP9]])
-// CHECK: ret void
-void test_vst1q_u64_x2(uint64_t *a, uint64x2x2_t b) {
- vst1q_u64_x2(a, b);
-}
-
-// CHECK-LABEL: @test_vst1q_s8_x2(
-// CHECK: [[B:%.*]] = alloca %struct.int8x16x2_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.int8x16x2_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x16x2_t, %struct.int8x16x2_t* [[B]], i32 0, i32 0
-// CHECK: store [2 x <16 x i8>] [[B]].coerce, [2 x <16 x i8>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x16x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x16x2_t, %struct.int8x16x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int8x16x2_t, %struct.int8x16x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 16
-// CHECK: call void @llvm.aarch64.neon.st1x2.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], i8* %a)
-// CHECK: ret void
-void test_vst1q_s8_x2(int8_t *a, int8x16x2_t b) {
- vst1q_s8_x2(a, b);
-}
-
-// CHECK-LABEL: @test_vst1q_s16_x2(
-// CHECK: [[B:%.*]] = alloca %struct.int16x8x2_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x2_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[B]], i32 0, i32 0
-// CHECK: store [2 x <8 x i16>] [[B]].coerce, [2 x <8 x i16>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16
-// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8>
-// CHECK: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16>
-// CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
-// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i16*
-// CHECK: call void @llvm.aarch64.neon.st1x2.v8i16.p0i16(<8 x i16> [[TMP7]], <8 x i16> [[TMP8]], i16* [[TMP9]])
-// CHECK: ret void
-void test_vst1q_s16_x2(int16_t *a, int16x8x2_t b) {
- vst1q_s16_x2(a, b);
-}
-
-// CHECK-LABEL: @test_vst1q_s32_x2(
-// CHECK: [[B:%.*]] = alloca %struct.int32x4x2_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x2_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[B]], i32 0, i32 0
-// CHECK: store [2 x <4 x i32>] [[B]].coerce, [2 x <4 x i32>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 16
-// CHECK: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP3]] to <16 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 16
-// CHECK: [[TMP6:%.*]] = bitcast <4 x i32> [[TMP5]] to <16 x i8>
-// CHECK: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x i32>
-// CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32>
-// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i32*
-// CHECK: call void @llvm.aarch64.neon.st1x2.v4i32.p0i32(<4 x i32> [[TMP7]], <4 x i32> [[TMP8]], i32* [[TMP9]])
-// CHECK: ret void
-void test_vst1q_s32_x2(int32_t *a, int32x4x2_t b) {
- vst1q_s32_x2(a, b);
-}
-
-// CHECK-LABEL: @test_vst1q_s64_x2(
-// CHECK: [[B:%.*]] = alloca %struct.int64x2x2_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.int64x2x2_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int64x2x2_t, %struct.int64x2x2_t* [[B]], i32 0, i32 0
-// CHECK: store [2 x <2 x i64>] [[B]].coerce, [2 x <2 x i64>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x2x2_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x2x2_t, %struct.int64x2x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x i64>], [2 x <2 x i64>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX]], align 16
-// CHECK: [[TMP4:%.*]] = bitcast <2 x i64> [[TMP3]] to <16 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int64x2x2_t, %struct.int64x2x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <2 x i64>], [2 x <2 x i64>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX2]], align 16
-// CHECK: [[TMP6:%.*]] = bitcast <2 x i64> [[TMP5]] to <16 x i8>
-// CHECK: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <2 x i64>
-// CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <2 x i64>
-// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i64*
-// CHECK: call void @llvm.aarch64.neon.st1x2.v2i64.p0i64(<2 x i64> [[TMP7]], <2 x i64> [[TMP8]], i64* [[TMP9]])
-// CHECK: ret void
-void test_vst1q_s64_x2(int64_t *a, int64x2x2_t b) {
- vst1q_s64_x2(a, b);
-}
-
-// CHECK-LABEL: @test_vst1q_f16_x2(
-// CHECK: [[B:%.*]] = alloca %struct.float16x8x2_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x2_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x8x2_t, %struct.float16x8x2_t* [[B]], i32 0, i32 0
-// CHECK: store [2 x <8 x half>] [[B]].coerce, [2 x <8 x half>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x2_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x2_t, %struct.float16x8x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x half>], [2 x <8 x half>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX]], align 16
-// CHECK: [[TMP4:%.*]] = bitcast <8 x half> [[TMP3]] to <16 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float16x8x2_t, %struct.float16x8x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x half>], [2 x <8 x half>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align 16
-// CHECK: [[TMP6:%.*]] = bitcast <8 x half> [[TMP5]] to <16 x i8>
-// CHECK: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x half>
-// CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x half>
-// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to half*
-// CHECK: call void @llvm.aarch64.neon.st1x2.v8f16.p0f16(<8 x half> [[TMP7]], <8 x half> [[TMP8]], half* [[TMP9]])
-// CHECK: ret void
-void test_vst1q_f16_x2(float16_t *a, float16x8x2_t b) {
- vst1q_f16_x2(a, b);
-}
-
-// CHECK-LABEL: @test_vst1q_f32_x2(
-// CHECK: [[B:%.*]] = alloca %struct.float32x4x2_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x2_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[B]], i32 0, i32 0
-// CHECK: store [2 x <4 x float>] [[B]].coerce, [2 x <4 x float>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x float>], [2 x <4 x float>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX]], align 16
-// CHECK: [[TMP4:%.*]] = bitcast <4 x float> [[TMP3]] to <16 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x float>], [2 x <4 x float>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX2]], align 16
-// CHECK: [[TMP6:%.*]] = bitcast <4 x float> [[TMP5]] to <16 x i8>
-// CHECK: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x float>
-// CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x float>
-// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to float*
-// CHECK: call void @llvm.aarch64.neon.st1x2.v4f32.p0f32(<4 x float> [[TMP7]], <4 x float> [[TMP8]], float* [[TMP9]])
-// CHECK: ret void
-void test_vst1q_f32_x2(float32_t *a, float32x4x2_t b) {
- vst1q_f32_x2(a, b);
-}
-
// CHECK-LABEL: @test_vst1q_f64_x2(
// CHECK: [[B:%.*]] = alloca %struct.float64x2x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.float64x2x2_t, align 16
@@ -14792,7 +13284,7 @@ void test_vst1q_f32_x2(float32_t *a, float32x4x2_t b) {
// CHECK: store [2 x <2 x double>] [[B]].coerce, [2 x <2 x double>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x2x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float64x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast double* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float64x2x2_t, %struct.float64x2x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x double>], [2 x <2 x double>]* [[VAL]], i64 0, i64 0
@@ -14811,52 +13303,6 @@ void test_vst1q_f64_x2(float64_t *a, float64x2x2_t b) {
vst1q_f64_x2(a, b);
}
-// CHECK-LABEL: @test_vst1q_p8_x2(
-// CHECK: [[B:%.*]] = alloca %struct.poly8x16x2_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.poly8x16x2_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[B]], i32 0, i32 0
-// CHECK: store [2 x <16 x i8>] [[B]].coerce, [2 x <16 x i8>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x16x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 16
-// CHECK: call void @llvm.aarch64.neon.st1x2.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], i8* %a)
-// CHECK: ret void
-void test_vst1q_p8_x2(poly8_t *a, poly8x16x2_t b) {
- vst1q_p8_x2(a, b);
-}
-
-// CHECK-LABEL: @test_vst1q_p16_x2(
-// CHECK: [[B:%.*]] = alloca %struct.poly16x8x2_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x2_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[B]], i32 0, i32 0
-// CHECK: store [2 x <8 x i16>] [[B]].coerce, [2 x <8 x i16>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16
-// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8>
-// CHECK: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16>
-// CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
-// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i16*
-// CHECK: call void @llvm.aarch64.neon.st1x2.v8i16.p0i16(<8 x i16> [[TMP7]], <8 x i16> [[TMP8]], i16* [[TMP9]])
-// CHECK: ret void
-void test_vst1q_p16_x2(poly16_t *a, poly16x8x2_t b) {
- vst1q_p16_x2(a, b);
-}
-
// CHECK-LABEL: @test_vst1q_p64_x2(
// CHECK: [[B:%.*]] = alloca %struct.poly64x2x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.poly64x2x2_t, align 16
@@ -14864,7 +13310,7 @@ void test_vst1q_p16_x2(poly16_t *a, poly16x8x2_t b) {
// CHECK: store [2 x <2 x i64>] [[B]].coerce, [2 x <2 x i64>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x2x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly64x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly64x2x2_t, %struct.poly64x2x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x i64>], [2 x <2 x i64>]* [[VAL]], i64 0, i64 0
@@ -14883,254 +13329,6 @@ void test_vst1q_p64_x2(poly64_t *a, poly64x2x2_t b) {
vst1q_p64_x2(a, b);
}
-// CHECK-LABEL: @test_vst1_u8_x2(
-// CHECK: [[B:%.*]] = alloca %struct.uint8x8x2_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.uint8x8x2_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[B]], i32 0, i32 0
-// CHECK: store [2 x <8 x i8>] [[B]].coerce, [2 x <8 x i8>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8
-// CHECK: call void @llvm.aarch64.neon.st1x2.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], i8* %a)
-// CHECK: ret void
-void test_vst1_u8_x2(uint8_t *a, uint8x8x2_t b) {
- vst1_u8_x2(a, b);
-}
-
-// CHECK-LABEL: @test_vst1_u16_x2(
-// CHECK: [[B:%.*]] = alloca %struct.uint16x4x2_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.uint16x4x2_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[B]], i32 0, i32 0
-// CHECK: store [2 x <4 x i16>] [[B]].coerce, [2 x <4 x i16>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8
-// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8
-// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8>
-// CHECK: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16>
-// CHECK: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
-// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i16*
-// CHECK: call void @llvm.aarch64.neon.st1x2.v4i16.p0i16(<4 x i16> [[TMP7]], <4 x i16> [[TMP8]], i16* [[TMP9]])
-// CHECK: ret void
-void test_vst1_u16_x2(uint16_t *a, uint16x4x2_t b) {
- vst1_u16_x2(a, b);
-}
-
-// CHECK-LABEL: @test_vst1_u32_x2(
-// CHECK: [[B:%.*]] = alloca %struct.uint32x2x2_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.uint32x2x2_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[B]], i32 0, i32 0
-// CHECK: store [2 x <2 x i32>] [[B]].coerce, [2 x <2 x i32>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x i32>], [2 x <2 x i32>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX]], align 8
-// CHECK: [[TMP4:%.*]] = bitcast <2 x i32> [[TMP3]] to <8 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <2 x i32>], [2 x <2 x i32>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX2]], align 8
-// CHECK: [[TMP6:%.*]] = bitcast <2 x i32> [[TMP5]] to <8 x i8>
-// CHECK: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x i32>
-// CHECK: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x i32>
-// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i32*
-// CHECK: call void @llvm.aarch64.neon.st1x2.v2i32.p0i32(<2 x i32> [[TMP7]], <2 x i32> [[TMP8]], i32* [[TMP9]])
-// CHECK: ret void
-void test_vst1_u32_x2(uint32_t *a, uint32x2x2_t b) {
- vst1_u32_x2(a, b);
-}
-
-// CHECK-LABEL: @test_vst1_u64_x2(
-// CHECK: [[B:%.*]] = alloca %struct.uint64x1x2_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.uint64x1x2_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint64x1x2_t, %struct.uint64x1x2_t* [[B]], i32 0, i32 0
-// CHECK: store [2 x <1 x i64>] [[B]].coerce, [2 x <1 x i64>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x2_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x1x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x1x2_t, %struct.uint64x1x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <1 x i64>], [2 x <1 x i64>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX]], align 8
-// CHECK: [[TMP4:%.*]] = bitcast <1 x i64> [[TMP3]] to <8 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint64x1x2_t, %struct.uint64x1x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <1 x i64>], [2 x <1 x i64>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX2]], align 8
-// CHECK: [[TMP6:%.*]] = bitcast <1 x i64> [[TMP5]] to <8 x i8>
-// CHECK: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <1 x i64>
-// CHECK: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <1 x i64>
-// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i64*
-// CHECK: call void @llvm.aarch64.neon.st1x2.v1i64.p0i64(<1 x i64> [[TMP7]], <1 x i64> [[TMP8]], i64* [[TMP9]])
-// CHECK: ret void
-void test_vst1_u64_x2(uint64_t *a, uint64x1x2_t b) {
- vst1_u64_x2(a, b);
-}
-
-// CHECK-LABEL: @test_vst1_s8_x2(
-// CHECK: [[B:%.*]] = alloca %struct.int8x8x2_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.int8x8x2_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x8x2_t, %struct.int8x8x2_t* [[B]], i32 0, i32 0
-// CHECK: store [2 x <8 x i8>] [[B]].coerce, [2 x <8 x i8>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x8x2_t, %struct.int8x8x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int8x8x2_t, %struct.int8x8x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8
-// CHECK: call void @llvm.aarch64.neon.st1x2.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], i8* %a)
-// CHECK: ret void
-void test_vst1_s8_x2(int8_t *a, int8x8x2_t b) {
- vst1_s8_x2(a, b);
-}
-
-// CHECK-LABEL: @test_vst1_s16_x2(
-// CHECK: [[B:%.*]] = alloca %struct.int16x4x2_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.int16x4x2_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x4x2_t, %struct.int16x4x2_t* [[B]], i32 0, i32 0
-// CHECK: store [2 x <4 x i16>] [[B]].coerce, [2 x <4 x i16>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x4x2_t, %struct.int16x4x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8
-// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int16x4x2_t, %struct.int16x4x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8
-// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8>
-// CHECK: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16>
-// CHECK: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
-// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i16*
-// CHECK: call void @llvm.aarch64.neon.st1x2.v4i16.p0i16(<4 x i16> [[TMP7]], <4 x i16> [[TMP8]], i16* [[TMP9]])
-// CHECK: ret void
-void test_vst1_s16_x2(int16_t *a, int16x4x2_t b) {
- vst1_s16_x2(a, b);
-}
-
-// CHECK-LABEL: @test_vst1_s32_x2(
-// CHECK: [[B:%.*]] = alloca %struct.int32x2x2_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.int32x2x2_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x2x2_t, %struct.int32x2x2_t* [[B]], i32 0, i32 0
-// CHECK: store [2 x <2 x i32>] [[B]].coerce, [2 x <2 x i32>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x2x2_t, %struct.int32x2x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x i32>], [2 x <2 x i32>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX]], align 8
-// CHECK: [[TMP4:%.*]] = bitcast <2 x i32> [[TMP3]] to <8 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int32x2x2_t, %struct.int32x2x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <2 x i32>], [2 x <2 x i32>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX2]], align 8
-// CHECK: [[TMP6:%.*]] = bitcast <2 x i32> [[TMP5]] to <8 x i8>
-// CHECK: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x i32>
-// CHECK: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x i32>
-// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i32*
-// CHECK: call void @llvm.aarch64.neon.st1x2.v2i32.p0i32(<2 x i32> [[TMP7]], <2 x i32> [[TMP8]], i32* [[TMP9]])
-// CHECK: ret void
-void test_vst1_s32_x2(int32_t *a, int32x2x2_t b) {
- vst1_s32_x2(a, b);
-}
-
-// CHECK-LABEL: @test_vst1_s64_x2(
-// CHECK: [[B:%.*]] = alloca %struct.int64x1x2_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.int64x1x2_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int64x1x2_t, %struct.int64x1x2_t* [[B]], i32 0, i32 0
-// CHECK: store [2 x <1 x i64>] [[B]].coerce, [2 x <1 x i64>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x2_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x1x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x1x2_t, %struct.int64x1x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <1 x i64>], [2 x <1 x i64>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX]], align 8
-// CHECK: [[TMP4:%.*]] = bitcast <1 x i64> [[TMP3]] to <8 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int64x1x2_t, %struct.int64x1x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <1 x i64>], [2 x <1 x i64>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX2]], align 8
-// CHECK: [[TMP6:%.*]] = bitcast <1 x i64> [[TMP5]] to <8 x i8>
-// CHECK: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <1 x i64>
-// CHECK: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <1 x i64>
-// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i64*
-// CHECK: call void @llvm.aarch64.neon.st1x2.v1i64.p0i64(<1 x i64> [[TMP7]], <1 x i64> [[TMP8]], i64* [[TMP9]])
-// CHECK: ret void
-void test_vst1_s64_x2(int64_t *a, int64x1x2_t b) {
- vst1_s64_x2(a, b);
-}
-
-// CHECK-LABEL: @test_vst1_f16_x2(
-// CHECK: [[B:%.*]] = alloca %struct.float16x4x2_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.float16x4x2_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x4x2_t, %struct.float16x4x2_t* [[B]], i32 0, i32 0
-// CHECK: store [2 x <4 x half>] [[B]].coerce, [2 x <4 x half>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x2_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x4x2_t, %struct.float16x4x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x half>], [2 x <4 x half>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX]], align 8
-// CHECK: [[TMP4:%.*]] = bitcast <4 x half> [[TMP3]] to <8 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float16x4x2_t, %struct.float16x4x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x half>], [2 x <4 x half>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX2]], align 8
-// CHECK: [[TMP6:%.*]] = bitcast <4 x half> [[TMP5]] to <8 x i8>
-// CHECK: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x half>
-// CHECK: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x half>
-// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to half*
-// CHECK: call void @llvm.aarch64.neon.st1x2.v4f16.p0f16(<4 x half> [[TMP7]], <4 x half> [[TMP8]], half* [[TMP9]])
-// CHECK: ret void
-void test_vst1_f16_x2(float16_t *a, float16x4x2_t b) {
- vst1_f16_x2(a, b);
-}
-
-// CHECK-LABEL: @test_vst1_f32_x2(
-// CHECK: [[B:%.*]] = alloca %struct.float32x2x2_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.float32x2x2_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x2x2_t, %struct.float32x2x2_t* [[B]], i32 0, i32 0
-// CHECK: store [2 x <2 x float>] [[B]].coerce, [2 x <2 x float>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x2x2_t, %struct.float32x2x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x float>], [2 x <2 x float>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX]], align 8
-// CHECK: [[TMP4:%.*]] = bitcast <2 x float> [[TMP3]] to <8 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float32x2x2_t, %struct.float32x2x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <2 x float>], [2 x <2 x float>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX2]], align 8
-// CHECK: [[TMP6:%.*]] = bitcast <2 x float> [[TMP5]] to <8 x i8>
-// CHECK: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x float>
-// CHECK: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x float>
-// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to float*
-// CHECK: call void @llvm.aarch64.neon.st1x2.v2f32.p0f32(<2 x float> [[TMP7]], <2 x float> [[TMP8]], float* [[TMP9]])
-// CHECK: ret void
-void test_vst1_f32_x2(float32_t *a, float32x2x2_t b) {
- vst1_f32_x2(a, b);
-}
-
// CHECK-LABEL: @test_vst1_f64_x2(
// CHECK: [[B:%.*]] = alloca %struct.float64x1x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.float64x1x2_t, align 8
@@ -15138,7 +13336,7 @@ void test_vst1_f32_x2(float32_t *a, float32x2x2_t b) {
// CHECK: store [2 x <1 x double>] [[B]].coerce, [2 x <1 x double>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x1x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float64x1x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast double* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float64x1x2_t, %struct.float64x1x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <1 x double>], [2 x <1 x double>]* [[VAL]], i64 0, i64 0
@@ -15157,52 +13355,6 @@ void test_vst1_f64_x2(float64_t *a, float64x1x2_t b) {
vst1_f64_x2(a, b);
}
-// CHECK-LABEL: @test_vst1_p8_x2(
-// CHECK: [[B:%.*]] = alloca %struct.poly8x8x2_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.poly8x8x2_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[B]], i32 0, i32 0
-// CHECK: store [2 x <8 x i8>] [[B]].coerce, [2 x <8 x i8>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8
-// CHECK: call void @llvm.aarch64.neon.st1x2.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], i8* %a)
-// CHECK: ret void
-void test_vst1_p8_x2(poly8_t *a, poly8x8x2_t b) {
- vst1_p8_x2(a, b);
-}
-
-// CHECK-LABEL: @test_vst1_p16_x2(
-// CHECK: [[B:%.*]] = alloca %struct.poly16x4x2_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.poly16x4x2_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[B]], i32 0, i32 0
-// CHECK: store [2 x <4 x i16>] [[B]].coerce, [2 x <4 x i16>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8
-// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8
-// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8>
-// CHECK: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16>
-// CHECK: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
-// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i16*
-// CHECK: call void @llvm.aarch64.neon.st1x2.v4i16.p0i16(<4 x i16> [[TMP7]], <4 x i16> [[TMP8]], i16* [[TMP9]])
-// CHECK: ret void
-void test_vst1_p16_x2(poly16_t *a, poly16x4x2_t b) {
- vst1_p16_x2(a, b);
-}
-
// CHECK-LABEL: @test_vst1_p64_x2(
// CHECK: [[B:%.*]] = alloca %struct.poly64x1x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.poly64x1x2_t, align 8
@@ -15210,7 +13362,7 @@ void test_vst1_p16_x2(poly16_t *a, poly16x4x2_t b) {
// CHECK: store [2 x <1 x i64>] [[B]].coerce, [2 x <1 x i64>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x1x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly64x1x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly64x1x2_t, %struct.poly64x1x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <1 x i64>], [2 x <1 x i64>]* [[VAL]], i64 0, i64 0
@@ -15229,300 +13381,6 @@ void test_vst1_p64_x2(poly64_t *a, poly64x1x2_t b) {
vst1_p64_x2(a, b);
}
-// CHECK-LABEL: @test_vst1q_u8_x3(
-// CHECK: [[B:%.*]] = alloca %struct.uint8x16x3_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.uint8x16x3_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[B]], i32 0, i32 0
-// CHECK: store [3 x <16 x i8>] [[B]].coerce, [3 x <16 x i8>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x3_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x16x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 16
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align 16
-// CHECK: call void @llvm.aarch64.neon.st1x3.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], i8* %a)
-// CHECK: ret void
-void test_vst1q_u8_x3(uint8_t *a, uint8x16x3_t b) {
- vst1q_u8_x3(a, b);
-}
-
-// CHECK-LABEL: @test_vst1q_u16_x3(
-// CHECK: [[B:%.*]] = alloca %struct.uint16x8x3_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x3_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[B]], i32 0, i32 0
-// CHECK: store [3 x <8 x i16>] [[B]].coerce, [3 x <8 x i16>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x3_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16
-// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 16
-// CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8>
-// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16>
-// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
-// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16>
-// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i16*
-// CHECK: call void @llvm.aarch64.neon.st1x3.v8i16.p0i16(<8 x i16> [[TMP9]], <8 x i16> [[TMP10]], <8 x i16> [[TMP11]], i16* [[TMP12]])
-// CHECK: ret void
-void test_vst1q_u16_x3(uint16_t *a, uint16x8x3_t b) {
- vst1q_u16_x3(a, b);
-}
-
-// CHECK-LABEL: @test_vst1q_u32_x3(
-// CHECK: [[B:%.*]] = alloca %struct.uint32x4x3_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x3_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[B]], i32 0, i32 0
-// CHECK: store [3 x <4 x i32>] [[B]].coerce, [3 x <4 x i32>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x3_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 16
-// CHECK: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP3]] to <16 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 16
-// CHECK: [[TMP6:%.*]] = bitcast <4 x i32> [[TMP5]] to <16 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align 16
-// CHECK: [[TMP8:%.*]] = bitcast <4 x i32> [[TMP7]] to <16 x i8>
-// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x i32>
-// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32>
-// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x i32>
-// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i32*
-// CHECK: call void @llvm.aarch64.neon.st1x3.v4i32.p0i32(<4 x i32> [[TMP9]], <4 x i32> [[TMP10]], <4 x i32> [[TMP11]], i32* [[TMP12]])
-// CHECK: ret void
-void test_vst1q_u32_x3(uint32_t *a, uint32x4x3_t b) {
- vst1q_u32_x3(a, b);
-}
-
-// CHECK-LABEL: @test_vst1q_u64_x3(
-// CHECK: [[B:%.*]] = alloca %struct.uint64x2x3_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.uint64x2x3_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint64x2x3_t, %struct.uint64x2x3_t* [[B]], i32 0, i32 0
-// CHECK: store [3 x <2 x i64>] [[B]].coerce, [3 x <2 x i64>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x2x3_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x2x3_t, %struct.uint64x2x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x i64>], [3 x <2 x i64>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX]], align 16
-// CHECK: [[TMP4:%.*]] = bitcast <2 x i64> [[TMP3]] to <16 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint64x2x3_t, %struct.uint64x2x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <2 x i64>], [3 x <2 x i64>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX2]], align 16
-// CHECK: [[TMP6:%.*]] = bitcast <2 x i64> [[TMP5]] to <16 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint64x2x3_t, %struct.uint64x2x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <2 x i64>], [3 x <2 x i64>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX4]], align 16
-// CHECK: [[TMP8:%.*]] = bitcast <2 x i64> [[TMP7]] to <16 x i8>
-// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <2 x i64>
-// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <2 x i64>
-// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <2 x i64>
-// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i64*
-// CHECK: call void @llvm.aarch64.neon.st1x3.v2i64.p0i64(<2 x i64> [[TMP9]], <2 x i64> [[TMP10]], <2 x i64> [[TMP11]], i64* [[TMP12]])
-// CHECK: ret void
-void test_vst1q_u64_x3(uint64_t *a, uint64x2x3_t b) {
- vst1q_u64_x3(a, b);
-}
-
-// CHECK-LABEL: @test_vst1q_s8_x3(
-// CHECK: [[B:%.*]] = alloca %struct.int8x16x3_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.int8x16x3_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x16x3_t, %struct.int8x16x3_t* [[B]], i32 0, i32 0
-// CHECK: store [3 x <16 x i8>] [[B]].coerce, [3 x <16 x i8>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x3_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x16x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x16x3_t, %struct.int8x16x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int8x16x3_t, %struct.int8x16x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 16
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int8x16x3_t, %struct.int8x16x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align 16
-// CHECK: call void @llvm.aarch64.neon.st1x3.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], i8* %a)
-// CHECK: ret void
-void test_vst1q_s8_x3(int8_t *a, int8x16x3_t b) {
- vst1q_s8_x3(a, b);
-}
-
-// CHECK-LABEL: @test_vst1q_s16_x3(
-// CHECK: [[B:%.*]] = alloca %struct.int16x8x3_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x3_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[B]], i32 0, i32 0
-// CHECK: store [3 x <8 x i16>] [[B]].coerce, [3 x <8 x i16>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x3_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16
-// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 16
-// CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8>
-// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16>
-// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
-// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16>
-// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i16*
-// CHECK: call void @llvm.aarch64.neon.st1x3.v8i16.p0i16(<8 x i16> [[TMP9]], <8 x i16> [[TMP10]], <8 x i16> [[TMP11]], i16* [[TMP12]])
-// CHECK: ret void
-void test_vst1q_s16_x3(int16_t *a, int16x8x3_t b) {
- vst1q_s16_x3(a, b);
-}
-
-// CHECK-LABEL: @test_vst1q_s32_x3(
-// CHECK: [[B:%.*]] = alloca %struct.int32x4x3_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x3_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[B]], i32 0, i32 0
-// CHECK: store [3 x <4 x i32>] [[B]].coerce, [3 x <4 x i32>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x3_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 16
-// CHECK: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP3]] to <16 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 16
-// CHECK: [[TMP6:%.*]] = bitcast <4 x i32> [[TMP5]] to <16 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align 16
-// CHECK: [[TMP8:%.*]] = bitcast <4 x i32> [[TMP7]] to <16 x i8>
-// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x i32>
-// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32>
-// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x i32>
-// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i32*
-// CHECK: call void @llvm.aarch64.neon.st1x3.v4i32.p0i32(<4 x i32> [[TMP9]], <4 x i32> [[TMP10]], <4 x i32> [[TMP11]], i32* [[TMP12]])
-// CHECK: ret void
-void test_vst1q_s32_x3(int32_t *a, int32x4x3_t b) {
- vst1q_s32_x3(a, b);
-}
-
-// CHECK-LABEL: @test_vst1q_s64_x3(
-// CHECK: [[B:%.*]] = alloca %struct.int64x2x3_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.int64x2x3_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int64x2x3_t, %struct.int64x2x3_t* [[B]], i32 0, i32 0
-// CHECK: store [3 x <2 x i64>] [[B]].coerce, [3 x <2 x i64>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x2x3_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x2x3_t, %struct.int64x2x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x i64>], [3 x <2 x i64>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX]], align 16
-// CHECK: [[TMP4:%.*]] = bitcast <2 x i64> [[TMP3]] to <16 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int64x2x3_t, %struct.int64x2x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <2 x i64>], [3 x <2 x i64>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX2]], align 16
-// CHECK: [[TMP6:%.*]] = bitcast <2 x i64> [[TMP5]] to <16 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int64x2x3_t, %struct.int64x2x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <2 x i64>], [3 x <2 x i64>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX4]], align 16
-// CHECK: [[TMP8:%.*]] = bitcast <2 x i64> [[TMP7]] to <16 x i8>
-// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <2 x i64>
-// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <2 x i64>
-// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <2 x i64>
-// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i64*
-// CHECK: call void @llvm.aarch64.neon.st1x3.v2i64.p0i64(<2 x i64> [[TMP9]], <2 x i64> [[TMP10]], <2 x i64> [[TMP11]], i64* [[TMP12]])
-// CHECK: ret void
-void test_vst1q_s64_x3(int64_t *a, int64x2x3_t b) {
- vst1q_s64_x3(a, b);
-}
-
-// CHECK-LABEL: @test_vst1q_f16_x3(
-// CHECK: [[B:%.*]] = alloca %struct.float16x8x3_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x3_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[B]], i32 0, i32 0
-// CHECK: store [3 x <8 x half>] [[B]].coerce, [3 x <8 x half>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x3_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x half>], [3 x <8 x half>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX]], align 16
-// CHECK: [[TMP4:%.*]] = bitcast <8 x half> [[TMP3]] to <16 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x half>], [3 x <8 x half>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align 16
-// CHECK: [[TMP6:%.*]] = bitcast <8 x half> [[TMP5]] to <16 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x half>], [3 x <8 x half>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX4]], align 16
-// CHECK: [[TMP8:%.*]] = bitcast <8 x half> [[TMP7]] to <16 x i8>
-// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x half>
-// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x half>
-// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x half>
-// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to half*
-// CHECK: call void @llvm.aarch64.neon.st1x3.v8f16.p0f16(<8 x half> [[TMP9]], <8 x half> [[TMP10]], <8 x half> [[TMP11]], half* [[TMP12]])
-// CHECK: ret void
-void test_vst1q_f16_x3(float16_t *a, float16x8x3_t b) {
- vst1q_f16_x3(a, b);
-}
-
-// CHECK-LABEL: @test_vst1q_f32_x3(
-// CHECK: [[B:%.*]] = alloca %struct.float32x4x3_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x3_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[B]], i32 0, i32 0
-// CHECK: store [3 x <4 x float>] [[B]].coerce, [3 x <4 x float>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x3_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x float>], [3 x <4 x float>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX]], align 16
-// CHECK: [[TMP4:%.*]] = bitcast <4 x float> [[TMP3]] to <16 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x float>], [3 x <4 x float>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX2]], align 16
-// CHECK: [[TMP6:%.*]] = bitcast <4 x float> [[TMP5]] to <16 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x float>], [3 x <4 x float>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX4]], align 16
-// CHECK: [[TMP8:%.*]] = bitcast <4 x float> [[TMP7]] to <16 x i8>
-// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x float>
-// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x float>
-// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x float>
-// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to float*
-// CHECK: call void @llvm.aarch64.neon.st1x3.v4f32.p0f32(<4 x float> [[TMP9]], <4 x float> [[TMP10]], <4 x float> [[TMP11]], float* [[TMP12]])
-// CHECK: ret void
-void test_vst1q_f32_x3(float32_t *a, float32x4x3_t b) {
- vst1q_f32_x3(a, b);
-}
-
// CHECK-LABEL: @test_vst1q_f64_x3(
// CHECK: [[B:%.*]] = alloca %struct.float64x2x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.float64x2x3_t, align 16
@@ -15530,7 +13388,7 @@ void test_vst1q_f32_x3(float32_t *a, float32x4x3_t b) {
// CHECK: store [3 x <2 x double>] [[B]].coerce, [3 x <2 x double>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x2x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float64x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast double* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float64x2x3_t, %struct.float64x2x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x double>], [3 x <2 x double>]* [[VAL]], i64 0, i64 0
@@ -15554,60 +13412,6 @@ void test_vst1q_f64_x3(float64_t *a, float64x2x3_t b) {
vst1q_f64_x3(a, b);
}
-// CHECK-LABEL: @test_vst1q_p8_x3(
-// CHECK: [[B:%.*]] = alloca %struct.poly8x16x3_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.poly8x16x3_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[B]], i32 0, i32 0
-// CHECK: store [3 x <16 x i8>] [[B]].coerce, [3 x <16 x i8>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x3_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x16x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 16
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align 16
-// CHECK: call void @llvm.aarch64.neon.st1x3.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], i8* %a)
-// CHECK: ret void
-void test_vst1q_p8_x3(poly8_t *a, poly8x16x3_t b) {
- vst1q_p8_x3(a, b);
-}
-
-// CHECK-LABEL: @test_vst1q_p16_x3(
-// CHECK: [[B:%.*]] = alloca %struct.poly16x8x3_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x3_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[B]], i32 0, i32 0
-// CHECK: store [3 x <8 x i16>] [[B]].coerce, [3 x <8 x i16>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x3_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16
-// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 16
-// CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8>
-// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16>
-// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
-// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16>
-// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i16*
-// CHECK: call void @llvm.aarch64.neon.st1x3.v8i16.p0i16(<8 x i16> [[TMP9]], <8 x i16> [[TMP10]], <8 x i16> [[TMP11]], i16* [[TMP12]])
-// CHECK: ret void
-void test_vst1q_p16_x3(poly16_t *a, poly16x8x3_t b) {
- vst1q_p16_x3(a, b);
-}
-
// CHECK-LABEL: @test_vst1q_p64_x3(
// CHECK: [[B:%.*]] = alloca %struct.poly64x2x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.poly64x2x3_t, align 16
@@ -15615,7 +13419,7 @@ void test_vst1q_p16_x3(poly16_t *a, poly16x8x3_t b) {
// CHECK: store [3 x <2 x i64>] [[B]].coerce, [3 x <2 x i64>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x2x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly64x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly64x2x3_t, %struct.poly64x2x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x i64>], [3 x <2 x i64>]* [[VAL]], i64 0, i64 0
@@ -15639,300 +13443,6 @@ void test_vst1q_p64_x3(poly64_t *a, poly64x2x3_t b) {
vst1q_p64_x3(a, b);
}
-// CHECK-LABEL: @test_vst1_u8_x3(
-// CHECK: [[B:%.*]] = alloca %struct.uint8x8x3_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.uint8x8x3_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x8x3_t, %struct.uint8x8x3_t* [[B]], i32 0, i32 0
-// CHECK: store [3 x <8 x i8>] [[B]].coerce, [3 x <8 x i8>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x3_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x8x3_t, %struct.uint8x8x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint8x8x3_t, %struct.uint8x8x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint8x8x3_t, %struct.uint8x8x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP4:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX4]], align 8
-// CHECK: call void @llvm.aarch64.neon.st1x3.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], i8* %a)
-// CHECK: ret void
-void test_vst1_u8_x3(uint8_t *a, uint8x8x3_t b) {
- vst1_u8_x3(a, b);
-}
-
-// CHECK-LABEL: @test_vst1_u16_x3(
-// CHECK: [[B:%.*]] = alloca %struct.uint16x4x3_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.uint16x4x3_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x4x3_t, %struct.uint16x4x3_t* [[B]], i32 0, i32 0
-// CHECK: store [3 x <4 x i16>] [[B]].coerce, [3 x <4 x i16>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x3_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x4x3_t, %struct.uint16x4x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8
-// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint16x4x3_t, %struct.uint16x4x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8
-// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint16x4x3_t, %struct.uint16x4x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX4]], align 8
-// CHECK: [[TMP8:%.*]] = bitcast <4 x i16> [[TMP7]] to <8 x i8>
-// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16>
-// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
-// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16>
-// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i16*
-// CHECK: call void @llvm.aarch64.neon.st1x3.v4i16.p0i16(<4 x i16> [[TMP9]], <4 x i16> [[TMP10]], <4 x i16> [[TMP11]], i16* [[TMP12]])
-// CHECK: ret void
-void test_vst1_u16_x3(uint16_t *a, uint16x4x3_t b) {
- vst1_u16_x3(a, b);
-}
-
-// CHECK-LABEL: @test_vst1_u32_x3(
-// CHECK: [[B:%.*]] = alloca %struct.uint32x2x3_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.uint32x2x3_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x2x3_t, %struct.uint32x2x3_t* [[B]], i32 0, i32 0
-// CHECK: store [3 x <2 x i32>] [[B]].coerce, [3 x <2 x i32>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x3_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x2x3_t, %struct.uint32x2x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x i32>], [3 x <2 x i32>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX]], align 8
-// CHECK: [[TMP4:%.*]] = bitcast <2 x i32> [[TMP3]] to <8 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint32x2x3_t, %struct.uint32x2x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <2 x i32>], [3 x <2 x i32>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX2]], align 8
-// CHECK: [[TMP6:%.*]] = bitcast <2 x i32> [[TMP5]] to <8 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint32x2x3_t, %struct.uint32x2x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <2 x i32>], [3 x <2 x i32>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX4]], align 8
-// CHECK: [[TMP8:%.*]] = bitcast <2 x i32> [[TMP7]] to <8 x i8>
-// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x i32>
-// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x i32>
-// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <2 x i32>
-// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i32*
-// CHECK: call void @llvm.aarch64.neon.st1x3.v2i32.p0i32(<2 x i32> [[TMP9]], <2 x i32> [[TMP10]], <2 x i32> [[TMP11]], i32* [[TMP12]])
-// CHECK: ret void
-void test_vst1_u32_x3(uint32_t *a, uint32x2x3_t b) {
- vst1_u32_x3(a, b);
-}
-
-// CHECK-LABEL: @test_vst1_u64_x3(
-// CHECK: [[B:%.*]] = alloca %struct.uint64x1x3_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.uint64x1x3_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint64x1x3_t, %struct.uint64x1x3_t* [[B]], i32 0, i32 0
-// CHECK: store [3 x <1 x i64>] [[B]].coerce, [3 x <1 x i64>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x3_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x1x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x1x3_t, %struct.uint64x1x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX]], align 8
-// CHECK: [[TMP4:%.*]] = bitcast <1 x i64> [[TMP3]] to <8 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint64x1x3_t, %struct.uint64x1x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX2]], align 8
-// CHECK: [[TMP6:%.*]] = bitcast <1 x i64> [[TMP5]] to <8 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint64x1x3_t, %struct.uint64x1x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX4]], align 8
-// CHECK: [[TMP8:%.*]] = bitcast <1 x i64> [[TMP7]] to <8 x i8>
-// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <1 x i64>
-// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <1 x i64>
-// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <1 x i64>
-// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i64*
-// CHECK: call void @llvm.aarch64.neon.st1x3.v1i64.p0i64(<1 x i64> [[TMP9]], <1 x i64> [[TMP10]], <1 x i64> [[TMP11]], i64* [[TMP12]])
-// CHECK: ret void
-void test_vst1_u64_x3(uint64_t *a, uint64x1x3_t b) {
- vst1_u64_x3(a, b);
-}
-
-// CHECK-LABEL: @test_vst1_s8_x3(
-// CHECK: [[B:%.*]] = alloca %struct.int8x8x3_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.int8x8x3_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x8x3_t, %struct.int8x8x3_t* [[B]], i32 0, i32 0
-// CHECK: store [3 x <8 x i8>] [[B]].coerce, [3 x <8 x i8>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x3_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x8x3_t, %struct.int8x8x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int8x8x3_t, %struct.int8x8x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int8x8x3_t, %struct.int8x8x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP4:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX4]], align 8
-// CHECK: call void @llvm.aarch64.neon.st1x3.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], i8* %a)
-// CHECK: ret void
-void test_vst1_s8_x3(int8_t *a, int8x8x3_t b) {
- vst1_s8_x3(a, b);
-}
-
-// CHECK-LABEL: @test_vst1_s16_x3(
-// CHECK: [[B:%.*]] = alloca %struct.int16x4x3_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.int16x4x3_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x4x3_t, %struct.int16x4x3_t* [[B]], i32 0, i32 0
-// CHECK: store [3 x <4 x i16>] [[B]].coerce, [3 x <4 x i16>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x3_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x4x3_t, %struct.int16x4x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8
-// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int16x4x3_t, %struct.int16x4x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8
-// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int16x4x3_t, %struct.int16x4x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX4]], align 8
-// CHECK: [[TMP8:%.*]] = bitcast <4 x i16> [[TMP7]] to <8 x i8>
-// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16>
-// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
-// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16>
-// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i16*
-// CHECK: call void @llvm.aarch64.neon.st1x3.v4i16.p0i16(<4 x i16> [[TMP9]], <4 x i16> [[TMP10]], <4 x i16> [[TMP11]], i16* [[TMP12]])
-// CHECK: ret void
-void test_vst1_s16_x3(int16_t *a, int16x4x3_t b) {
- vst1_s16_x3(a, b);
-}
-
-// CHECK-LABEL: @test_vst1_s32_x3(
-// CHECK: [[B:%.*]] = alloca %struct.int32x2x3_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.int32x2x3_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x2x3_t, %struct.int32x2x3_t* [[B]], i32 0, i32 0
-// CHECK: store [3 x <2 x i32>] [[B]].coerce, [3 x <2 x i32>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x3_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x2x3_t, %struct.int32x2x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x i32>], [3 x <2 x i32>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX]], align 8
-// CHECK: [[TMP4:%.*]] = bitcast <2 x i32> [[TMP3]] to <8 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int32x2x3_t, %struct.int32x2x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <2 x i32>], [3 x <2 x i32>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX2]], align 8
-// CHECK: [[TMP6:%.*]] = bitcast <2 x i32> [[TMP5]] to <8 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int32x2x3_t, %struct.int32x2x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <2 x i32>], [3 x <2 x i32>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX4]], align 8
-// CHECK: [[TMP8:%.*]] = bitcast <2 x i32> [[TMP7]] to <8 x i8>
-// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x i32>
-// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x i32>
-// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <2 x i32>
-// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i32*
-// CHECK: call void @llvm.aarch64.neon.st1x3.v2i32.p0i32(<2 x i32> [[TMP9]], <2 x i32> [[TMP10]], <2 x i32> [[TMP11]], i32* [[TMP12]])
-// CHECK: ret void
-void test_vst1_s32_x3(int32_t *a, int32x2x3_t b) {
- vst1_s32_x3(a, b);
-}
-
-// CHECK-LABEL: @test_vst1_s64_x3(
-// CHECK: [[B:%.*]] = alloca %struct.int64x1x3_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.int64x1x3_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int64x1x3_t, %struct.int64x1x3_t* [[B]], i32 0, i32 0
-// CHECK: store [3 x <1 x i64>] [[B]].coerce, [3 x <1 x i64>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x3_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x1x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x1x3_t, %struct.int64x1x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX]], align 8
-// CHECK: [[TMP4:%.*]] = bitcast <1 x i64> [[TMP3]] to <8 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int64x1x3_t, %struct.int64x1x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX2]], align 8
-// CHECK: [[TMP6:%.*]] = bitcast <1 x i64> [[TMP5]] to <8 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int64x1x3_t, %struct.int64x1x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX4]], align 8
-// CHECK: [[TMP8:%.*]] = bitcast <1 x i64> [[TMP7]] to <8 x i8>
-// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <1 x i64>
-// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <1 x i64>
-// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <1 x i64>
-// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i64*
-// CHECK: call void @llvm.aarch64.neon.st1x3.v1i64.p0i64(<1 x i64> [[TMP9]], <1 x i64> [[TMP10]], <1 x i64> [[TMP11]], i64* [[TMP12]])
-// CHECK: ret void
-void test_vst1_s64_x3(int64_t *a, int64x1x3_t b) {
- vst1_s64_x3(a, b);
-}
-
-// CHECK-LABEL: @test_vst1_f16_x3(
-// CHECK: [[B:%.*]] = alloca %struct.float16x4x3_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.float16x4x3_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x4x3_t, %struct.float16x4x3_t* [[B]], i32 0, i32 0
-// CHECK: store [3 x <4 x half>] [[B]].coerce, [3 x <4 x half>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x3_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x4x3_t, %struct.float16x4x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x half>], [3 x <4 x half>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX]], align 8
-// CHECK: [[TMP4:%.*]] = bitcast <4 x half> [[TMP3]] to <8 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float16x4x3_t, %struct.float16x4x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x half>], [3 x <4 x half>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX2]], align 8
-// CHECK: [[TMP6:%.*]] = bitcast <4 x half> [[TMP5]] to <8 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float16x4x3_t, %struct.float16x4x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x half>], [3 x <4 x half>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX4]], align 8
-// CHECK: [[TMP8:%.*]] = bitcast <4 x half> [[TMP7]] to <8 x i8>
-// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x half>
-// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x half>
-// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x half>
-// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to half*
-// CHECK: call void @llvm.aarch64.neon.st1x3.v4f16.p0f16(<4 x half> [[TMP9]], <4 x half> [[TMP10]], <4 x half> [[TMP11]], half* [[TMP12]])
-// CHECK: ret void
-void test_vst1_f16_x3(float16_t *a, float16x4x3_t b) {
- vst1_f16_x3(a, b);
-}
-
-// CHECK-LABEL: @test_vst1_f32_x3(
-// CHECK: [[B:%.*]] = alloca %struct.float32x2x3_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.float32x2x3_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x2x3_t, %struct.float32x2x3_t* [[B]], i32 0, i32 0
-// CHECK: store [3 x <2 x float>] [[B]].coerce, [3 x <2 x float>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x3_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x2x3_t, %struct.float32x2x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x float>], [3 x <2 x float>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX]], align 8
-// CHECK: [[TMP4:%.*]] = bitcast <2 x float> [[TMP3]] to <8 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float32x2x3_t, %struct.float32x2x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <2 x float>], [3 x <2 x float>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX2]], align 8
-// CHECK: [[TMP6:%.*]] = bitcast <2 x float> [[TMP5]] to <8 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float32x2x3_t, %struct.float32x2x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <2 x float>], [3 x <2 x float>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX4]], align 8
-// CHECK: [[TMP8:%.*]] = bitcast <2 x float> [[TMP7]] to <8 x i8>
-// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x float>
-// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x float>
-// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <2 x float>
-// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to float*
-// CHECK: call void @llvm.aarch64.neon.st1x3.v2f32.p0f32(<2 x float> [[TMP9]], <2 x float> [[TMP10]], <2 x float> [[TMP11]], float* [[TMP12]])
-// CHECK: ret void
-void test_vst1_f32_x3(float32_t *a, float32x2x3_t b) {
- vst1_f32_x3(a, b);
-}
-
// CHECK-LABEL: @test_vst1_f64_x3(
// CHECK: [[B:%.*]] = alloca %struct.float64x1x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.float64x1x3_t, align 8
@@ -15940,7 +13450,7 @@ void test_vst1_f32_x3(float32_t *a, float32x2x3_t b) {
// CHECK: store [3 x <1 x double>] [[B]].coerce, [3 x <1 x double>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x1x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float64x1x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast double* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float64x1x3_t, %struct.float64x1x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <1 x double>], [3 x <1 x double>]* [[VAL]], i64 0, i64 0
@@ -15964,60 +13474,6 @@ void test_vst1_f64_x3(float64_t *a, float64x1x3_t b) {
vst1_f64_x3(a, b);
}
-// CHECK-LABEL: @test_vst1_p8_x3(
-// CHECK: [[B:%.*]] = alloca %struct.poly8x8x3_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.poly8x8x3_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x8x3_t, %struct.poly8x8x3_t* [[B]], i32 0, i32 0
-// CHECK: store [3 x <8 x i8>] [[B]].coerce, [3 x <8 x i8>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x3_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x8x3_t, %struct.poly8x8x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly8x8x3_t, %struct.poly8x8x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly8x8x3_t, %struct.poly8x8x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP4:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX4]], align 8
-// CHECK: call void @llvm.aarch64.neon.st1x3.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], i8* %a)
-// CHECK: ret void
-void test_vst1_p8_x3(poly8_t *a, poly8x8x3_t b) {
- vst1_p8_x3(a, b);
-}
-
-// CHECK-LABEL: @test_vst1_p16_x3(
-// CHECK: [[B:%.*]] = alloca %struct.poly16x4x3_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.poly16x4x3_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x4x3_t, %struct.poly16x4x3_t* [[B]], i32 0, i32 0
-// CHECK: store [3 x <4 x i16>] [[B]].coerce, [3 x <4 x i16>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x3_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x4x3_t, %struct.poly16x4x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8
-// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly16x4x3_t, %struct.poly16x4x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8
-// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly16x4x3_t, %struct.poly16x4x3_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX4]], align 8
-// CHECK: [[TMP8:%.*]] = bitcast <4 x i16> [[TMP7]] to <8 x i8>
-// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16>
-// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
-// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16>
-// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i16*
-// CHECK: call void @llvm.aarch64.neon.st1x3.v4i16.p0i16(<4 x i16> [[TMP9]], <4 x i16> [[TMP10]], <4 x i16> [[TMP11]], i16* [[TMP12]])
-// CHECK: ret void
-void test_vst1_p16_x3(poly16_t *a, poly16x4x3_t b) {
- vst1_p16_x3(a, b);
-}
-
// CHECK-LABEL: @test_vst1_p64_x3(
// CHECK: [[B:%.*]] = alloca %struct.poly64x1x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.poly64x1x3_t, align 8
@@ -16025,7 +13481,7 @@ void test_vst1_p16_x3(poly16_t *a, poly16x4x3_t b) {
// CHECK: store [3 x <1 x i64>] [[B]].coerce, [3 x <1 x i64>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x1x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly64x1x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly64x1x3_t, %struct.poly64x1x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL]], i64 0, i64 0
@@ -16049,346 +13505,6 @@ void test_vst1_p64_x3(poly64_t *a, poly64x1x3_t b) {
vst1_p64_x3(a, b);
}
-// CHECK-LABEL: @test_vst1q_u8_x4(
-// CHECK: [[B:%.*]] = alloca %struct.uint8x16x4_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.uint8x16x4_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[B]], i32 0, i32 0
-// CHECK: store [4 x <16 x i8>] [[B]].coerce, [4 x <16 x i8>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x4_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x16x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 16
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align 16
-// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL5]], i64 0, i64 3
-// CHECK: [[TMP5:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX6]], align 16
-// CHECK: call void @llvm.aarch64.neon.st1x4.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> [[TMP5]], i8* %a)
-// CHECK: ret void
-void test_vst1q_u8_x4(uint8_t *a, uint8x16x4_t b) {
- vst1q_u8_x4(a, b);
-}
-
-// CHECK-LABEL: @test_vst1q_u16_x4(
-// CHECK: [[B:%.*]] = alloca %struct.uint16x8x4_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x4_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[B]], i32 0, i32 0
-// CHECK: store [4 x <8 x i16>] [[B]].coerce, [4 x <8 x i16>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x4_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16
-// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 16
-// CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8>
-// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL5]], i64 0, i64 3
-// CHECK: [[TMP9:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX6]], align 16
-// CHECK: [[TMP10:%.*]] = bitcast <8 x i16> [[TMP9]] to <16 x i8>
-// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16>
-// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
-// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16>
-// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x i16>
-// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i16*
-// CHECK: call void @llvm.aarch64.neon.st1x4.v8i16.p0i16(<8 x i16> [[TMP11]], <8 x i16> [[TMP12]], <8 x i16> [[TMP13]], <8 x i16> [[TMP14]], i16* [[TMP15]])
-// CHECK: ret void
-void test_vst1q_u16_x4(uint16_t *a, uint16x8x4_t b) {
- vst1q_u16_x4(a, b);
-}
-
-// CHECK-LABEL: @test_vst1q_u32_x4(
-// CHECK: [[B:%.*]] = alloca %struct.uint32x4x4_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x4_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[B]], i32 0, i32 0
-// CHECK: store [4 x <4 x i32>] [[B]].coerce, [4 x <4 x i32>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x4_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 16
-// CHECK: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP3]] to <16 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 16
-// CHECK: [[TMP6:%.*]] = bitcast <4 x i32> [[TMP5]] to <16 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align 16
-// CHECK: [[TMP8:%.*]] = bitcast <4 x i32> [[TMP7]] to <16 x i8>
-// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL5]], i64 0, i64 3
-// CHECK: [[TMP9:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX6]], align 16
-// CHECK: [[TMP10:%.*]] = bitcast <4 x i32> [[TMP9]] to <16 x i8>
-// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x i32>
-// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32>
-// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x i32>
-// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <4 x i32>
-// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i32*
-// CHECK: call void @llvm.aarch64.neon.st1x4.v4i32.p0i32(<4 x i32> [[TMP11]], <4 x i32> [[TMP12]], <4 x i32> [[TMP13]], <4 x i32> [[TMP14]], i32* [[TMP15]])
-// CHECK: ret void
-void test_vst1q_u32_x4(uint32_t *a, uint32x4x4_t b) {
- vst1q_u32_x4(a, b);
-}
-
-// CHECK-LABEL: @test_vst1q_u64_x4(
-// CHECK: [[B:%.*]] = alloca %struct.uint64x2x4_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.uint64x2x4_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint64x2x4_t, %struct.uint64x2x4_t* [[B]], i32 0, i32 0
-// CHECK: store [4 x <2 x i64>] [[B]].coerce, [4 x <2 x i64>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x2x4_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x2x4_t, %struct.uint64x2x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX]], align 16
-// CHECK: [[TMP4:%.*]] = bitcast <2 x i64> [[TMP3]] to <16 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint64x2x4_t, %struct.uint64x2x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX2]], align 16
-// CHECK: [[TMP6:%.*]] = bitcast <2 x i64> [[TMP5]] to <16 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint64x2x4_t, %struct.uint64x2x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX4]], align 16
-// CHECK: [[TMP8:%.*]] = bitcast <2 x i64> [[TMP7]] to <16 x i8>
-// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint64x2x4_t, %struct.uint64x2x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL5]], i64 0, i64 3
-// CHECK: [[TMP9:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX6]], align 16
-// CHECK: [[TMP10:%.*]] = bitcast <2 x i64> [[TMP9]] to <16 x i8>
-// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <2 x i64>
-// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <2 x i64>
-// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <2 x i64>
-// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <2 x i64>
-// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i64*
-// CHECK: call void @llvm.aarch64.neon.st1x4.v2i64.p0i64(<2 x i64> [[TMP11]], <2 x i64> [[TMP12]], <2 x i64> [[TMP13]], <2 x i64> [[TMP14]], i64* [[TMP15]])
-// CHECK: ret void
-void test_vst1q_u64_x4(uint64_t *a, uint64x2x4_t b) {
- vst1q_u64_x4(a, b);
-}
-
-// CHECK-LABEL: @test_vst1q_s8_x4(
-// CHECK: [[B:%.*]] = alloca %struct.int8x16x4_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.int8x16x4_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[B]], i32 0, i32 0
-// CHECK: store [4 x <16 x i8>] [[B]].coerce, [4 x <16 x i8>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x4_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x16x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 16
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align 16
-// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL5]], i64 0, i64 3
-// CHECK: [[TMP5:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX6]], align 16
-// CHECK: call void @llvm.aarch64.neon.st1x4.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> [[TMP5]], i8* %a)
-// CHECK: ret void
-void test_vst1q_s8_x4(int8_t *a, int8x16x4_t b) {
- vst1q_s8_x4(a, b);
-}
-
-// CHECK-LABEL: @test_vst1q_s16_x4(
-// CHECK: [[B:%.*]] = alloca %struct.int16x8x4_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x4_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[B]], i32 0, i32 0
-// CHECK: store [4 x <8 x i16>] [[B]].coerce, [4 x <8 x i16>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x4_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16
-// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 16
-// CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8>
-// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL5]], i64 0, i64 3
-// CHECK: [[TMP9:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX6]], align 16
-// CHECK: [[TMP10:%.*]] = bitcast <8 x i16> [[TMP9]] to <16 x i8>
-// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16>
-// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
-// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16>
-// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x i16>
-// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i16*
-// CHECK: call void @llvm.aarch64.neon.st1x4.v8i16.p0i16(<8 x i16> [[TMP11]], <8 x i16> [[TMP12]], <8 x i16> [[TMP13]], <8 x i16> [[TMP14]], i16* [[TMP15]])
-// CHECK: ret void
-void test_vst1q_s16_x4(int16_t *a, int16x8x4_t b) {
- vst1q_s16_x4(a, b);
-}
-
-// CHECK-LABEL: @test_vst1q_s32_x4(
-// CHECK: [[B:%.*]] = alloca %struct.int32x4x4_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x4_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[B]], i32 0, i32 0
-// CHECK: store [4 x <4 x i32>] [[B]].coerce, [4 x <4 x i32>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x4_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 16
-// CHECK: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP3]] to <16 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 16
-// CHECK: [[TMP6:%.*]] = bitcast <4 x i32> [[TMP5]] to <16 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align 16
-// CHECK: [[TMP8:%.*]] = bitcast <4 x i32> [[TMP7]] to <16 x i8>
-// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL5]], i64 0, i64 3
-// CHECK: [[TMP9:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX6]], align 16
-// CHECK: [[TMP10:%.*]] = bitcast <4 x i32> [[TMP9]] to <16 x i8>
-// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x i32>
-// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32>
-// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x i32>
-// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <4 x i32>
-// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i32*
-// CHECK: call void @llvm.aarch64.neon.st1x4.v4i32.p0i32(<4 x i32> [[TMP11]], <4 x i32> [[TMP12]], <4 x i32> [[TMP13]], <4 x i32> [[TMP14]], i32* [[TMP15]])
-// CHECK: ret void
-void test_vst1q_s32_x4(int32_t *a, int32x4x4_t b) {
- vst1q_s32_x4(a, b);
-}
-
-// CHECK-LABEL: @test_vst1q_s64_x4(
-// CHECK: [[B:%.*]] = alloca %struct.int64x2x4_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.int64x2x4_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int64x2x4_t, %struct.int64x2x4_t* [[B]], i32 0, i32 0
-// CHECK: store [4 x <2 x i64>] [[B]].coerce, [4 x <2 x i64>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x2x4_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x2x4_t, %struct.int64x2x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX]], align 16
-// CHECK: [[TMP4:%.*]] = bitcast <2 x i64> [[TMP3]] to <16 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int64x2x4_t, %struct.int64x2x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX2]], align 16
-// CHECK: [[TMP6:%.*]] = bitcast <2 x i64> [[TMP5]] to <16 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int64x2x4_t, %struct.int64x2x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX4]], align 16
-// CHECK: [[TMP8:%.*]] = bitcast <2 x i64> [[TMP7]] to <16 x i8>
-// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int64x2x4_t, %struct.int64x2x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL5]], i64 0, i64 3
-// CHECK: [[TMP9:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX6]], align 16
-// CHECK: [[TMP10:%.*]] = bitcast <2 x i64> [[TMP9]] to <16 x i8>
-// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <2 x i64>
-// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <2 x i64>
-// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <2 x i64>
-// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <2 x i64>
-// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i64*
-// CHECK: call void @llvm.aarch64.neon.st1x4.v2i64.p0i64(<2 x i64> [[TMP11]], <2 x i64> [[TMP12]], <2 x i64> [[TMP13]], <2 x i64> [[TMP14]], i64* [[TMP15]])
-// CHECK: ret void
-void test_vst1q_s64_x4(int64_t *a, int64x2x4_t b) {
- vst1q_s64_x4(a, b);
-}
-
-// CHECK-LABEL: @test_vst1q_f16_x4(
-// CHECK: [[B:%.*]] = alloca %struct.float16x8x4_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x4_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[B]], i32 0, i32 0
-// CHECK: store [4 x <8 x half>] [[B]].coerce, [4 x <8 x half>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x4_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX]], align 16
-// CHECK: [[TMP4:%.*]] = bitcast <8 x half> [[TMP3]] to <16 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align 16
-// CHECK: [[TMP6:%.*]] = bitcast <8 x half> [[TMP5]] to <16 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX4]], align 16
-// CHECK: [[TMP8:%.*]] = bitcast <8 x half> [[TMP7]] to <16 x i8>
-// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL5]], i64 0, i64 3
-// CHECK: [[TMP9:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX6]], align 16
-// CHECK: [[TMP10:%.*]] = bitcast <8 x half> [[TMP9]] to <16 x i8>
-// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x half>
-// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x half>
-// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x half>
-// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x half>
-// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to half*
-// CHECK: call void @llvm.aarch64.neon.st1x4.v8f16.p0f16(<8 x half> [[TMP11]], <8 x half> [[TMP12]], <8 x half> [[TMP13]], <8 x half> [[TMP14]], half* [[TMP15]])
-// CHECK: ret void
-void test_vst1q_f16_x4(float16_t *a, float16x8x4_t b) {
- vst1q_f16_x4(a, b);
-}
-
-// CHECK-LABEL: @test_vst1q_f32_x4(
-// CHECK: [[B:%.*]] = alloca %struct.float32x4x4_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x4_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[B]], i32 0, i32 0
-// CHECK: store [4 x <4 x float>] [[B]].coerce, [4 x <4 x float>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x4_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x float>], [4 x <4 x float>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX]], align 16
-// CHECK: [[TMP4:%.*]] = bitcast <4 x float> [[TMP3]] to <16 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x float>], [4 x <4 x float>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX2]], align 16
-// CHECK: [[TMP6:%.*]] = bitcast <4 x float> [[TMP5]] to <16 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x float>], [4 x <4 x float>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX4]], align 16
-// CHECK: [[TMP8:%.*]] = bitcast <4 x float> [[TMP7]] to <16 x i8>
-// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x float>], [4 x <4 x float>]* [[VAL5]], i64 0, i64 3
-// CHECK: [[TMP9:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX6]], align 16
-// CHECK: [[TMP10:%.*]] = bitcast <4 x float> [[TMP9]] to <16 x i8>
-// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x float>
-// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x float>
-// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x float>
-// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <4 x float>
-// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to float*
-// CHECK: call void @llvm.aarch64.neon.st1x4.v4f32.p0f32(<4 x float> [[TMP11]], <4 x float> [[TMP12]], <4 x float> [[TMP13]], <4 x float> [[TMP14]], float* [[TMP15]])
-// CHECK: ret void
-void test_vst1q_f32_x4(float32_t *a, float32x4x4_t b) {
- vst1q_f32_x4(a, b);
-}
-
// CHECK-LABEL: @test_vst1q_f64_x4(
// CHECK: [[B:%.*]] = alloca %struct.float64x2x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.float64x2x4_t, align 16
@@ -16396,7 +13512,7 @@ void test_vst1q_f32_x4(float32_t *a, float32x4x4_t b) {
// CHECK: store [4 x <2 x double>] [[B]].coerce, [4 x <2 x double>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x2x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float64x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast double* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float64x2x4_t, %struct.float64x2x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x double>], [4 x <2 x double>]* [[VAL]], i64 0, i64 0
@@ -16425,68 +13541,6 @@ void test_vst1q_f64_x4(float64_t *a, float64x2x4_t b) {
vst1q_f64_x4(a, b);
}
-// CHECK-LABEL: @test_vst1q_p8_x4(
-// CHECK: [[B:%.*]] = alloca %struct.poly8x16x4_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.poly8x16x4_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[B]], i32 0, i32 0
-// CHECK: store [4 x <16 x i8>] [[B]].coerce, [4 x <16 x i8>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x4_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x16x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 16
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align 16
-// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL5]], i64 0, i64 3
-// CHECK: [[TMP5:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX6]], align 16
-// CHECK: call void @llvm.aarch64.neon.st1x4.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> [[TMP5]], i8* %a)
-// CHECK: ret void
-void test_vst1q_p8_x4(poly8_t *a, poly8x16x4_t b) {
- vst1q_p8_x4(a, b);
-}
-
-// CHECK-LABEL: @test_vst1q_p16_x4(
-// CHECK: [[B:%.*]] = alloca %struct.poly16x8x4_t, align 16
-// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x4_t, align 16
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[B]], i32 0, i32 0
-// CHECK: store [4 x <8 x i16>] [[B]].coerce, [4 x <8 x i16>]* [[COERCE_DIVE]], align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x4_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16
-// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 16
-// CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8>
-// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL5]], i64 0, i64 3
-// CHECK: [[TMP9:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX6]], align 16
-// CHECK: [[TMP10:%.*]] = bitcast <8 x i16> [[TMP9]] to <16 x i8>
-// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16>
-// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
-// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16>
-// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x i16>
-// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i16*
-// CHECK: call void @llvm.aarch64.neon.st1x4.v8i16.p0i16(<8 x i16> [[TMP11]], <8 x i16> [[TMP12]], <8 x i16> [[TMP13]], <8 x i16> [[TMP14]], i16* [[TMP15]])
-// CHECK: ret void
-void test_vst1q_p16_x4(poly16_t *a, poly16x8x4_t b) {
- vst1q_p16_x4(a, b);
-}
-
// CHECK-LABEL: @test_vst1q_p64_x4(
// CHECK: [[B:%.*]] = alloca %struct.poly64x2x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.poly64x2x4_t, align 16
@@ -16494,7 +13548,7 @@ void test_vst1q_p16_x4(poly16_t *a, poly16x8x4_t b) {
// CHECK: store [4 x <2 x i64>] [[B]].coerce, [4 x <2 x i64>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x2x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly64x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly64x2x4_t, %struct.poly64x2x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL]], i64 0, i64 0
@@ -16523,346 +13577,6 @@ void test_vst1q_p64_x4(poly64_t *a, poly64x2x4_t b) {
vst1q_p64_x4(a, b);
}
-// CHECK-LABEL: @test_vst1_u8_x4(
-// CHECK: [[B:%.*]] = alloca %struct.uint8x8x4_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.uint8x8x4_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[B]], i32 0, i32 0
-// CHECK: store [4 x <8 x i8>] [[B]].coerce, [4 x <8 x i8>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x4_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP4:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX4]], align 8
-// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL5]], i64 0, i64 3
-// CHECK: [[TMP5:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX6]], align 8
-// CHECK: call void @llvm.aarch64.neon.st1x4.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], <8 x i8> [[TMP5]], i8* %a)
-// CHECK: ret void
-void test_vst1_u8_x4(uint8_t *a, uint8x8x4_t b) {
- vst1_u8_x4(a, b);
-}
-
-// CHECK-LABEL: @test_vst1_u16_x4(
-// CHECK: [[B:%.*]] = alloca %struct.uint16x4x4_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.uint16x4x4_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x4x4_t, %struct.uint16x4x4_t* [[B]], i32 0, i32 0
-// CHECK: store [4 x <4 x i16>] [[B]].coerce, [4 x <4 x i16>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x4_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x4x4_t, %struct.uint16x4x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8
-// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint16x4x4_t, %struct.uint16x4x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8
-// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint16x4x4_t, %struct.uint16x4x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX4]], align 8
-// CHECK: [[TMP8:%.*]] = bitcast <4 x i16> [[TMP7]] to <8 x i8>
-// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint16x4x4_t, %struct.uint16x4x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL5]], i64 0, i64 3
-// CHECK: [[TMP9:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX6]], align 8
-// CHECK: [[TMP10:%.*]] = bitcast <4 x i16> [[TMP9]] to <8 x i8>
-// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16>
-// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
-// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16>
-// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x i16>
-// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i16*
-// CHECK: call void @llvm.aarch64.neon.st1x4.v4i16.p0i16(<4 x i16> [[TMP11]], <4 x i16> [[TMP12]], <4 x i16> [[TMP13]], <4 x i16> [[TMP14]], i16* [[TMP15]])
-// CHECK: ret void
-void test_vst1_u16_x4(uint16_t *a, uint16x4x4_t b) {
- vst1_u16_x4(a, b);
-}
-
-// CHECK-LABEL: @test_vst1_u32_x4(
-// CHECK: [[B:%.*]] = alloca %struct.uint32x2x4_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.uint32x2x4_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x2x4_t, %struct.uint32x2x4_t* [[B]], i32 0, i32 0
-// CHECK: store [4 x <2 x i32>] [[B]].coerce, [4 x <2 x i32>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x4_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x2x4_t, %struct.uint32x2x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX]], align 8
-// CHECK: [[TMP4:%.*]] = bitcast <2 x i32> [[TMP3]] to <8 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint32x2x4_t, %struct.uint32x2x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX2]], align 8
-// CHECK: [[TMP6:%.*]] = bitcast <2 x i32> [[TMP5]] to <8 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint32x2x4_t, %struct.uint32x2x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX4]], align 8
-// CHECK: [[TMP8:%.*]] = bitcast <2 x i32> [[TMP7]] to <8 x i8>
-// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint32x2x4_t, %struct.uint32x2x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL5]], i64 0, i64 3
-// CHECK: [[TMP9:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX6]], align 8
-// CHECK: [[TMP10:%.*]] = bitcast <2 x i32> [[TMP9]] to <8 x i8>
-// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x i32>
-// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x i32>
-// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <2 x i32>
-// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <2 x i32>
-// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i32*
-// CHECK: call void @llvm.aarch64.neon.st1x4.v2i32.p0i32(<2 x i32> [[TMP11]], <2 x i32> [[TMP12]], <2 x i32> [[TMP13]], <2 x i32> [[TMP14]], i32* [[TMP15]])
-// CHECK: ret void
-void test_vst1_u32_x4(uint32_t *a, uint32x2x4_t b) {
- vst1_u32_x4(a, b);
-}
-
-// CHECK-LABEL: @test_vst1_u64_x4(
-// CHECK: [[B:%.*]] = alloca %struct.uint64x1x4_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.uint64x1x4_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint64x1x4_t, %struct.uint64x1x4_t* [[B]], i32 0, i32 0
-// CHECK: store [4 x <1 x i64>] [[B]].coerce, [4 x <1 x i64>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x4_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x1x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x1x4_t, %struct.uint64x1x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX]], align 8
-// CHECK: [[TMP4:%.*]] = bitcast <1 x i64> [[TMP3]] to <8 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint64x1x4_t, %struct.uint64x1x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX2]], align 8
-// CHECK: [[TMP6:%.*]] = bitcast <1 x i64> [[TMP5]] to <8 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint64x1x4_t, %struct.uint64x1x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX4]], align 8
-// CHECK: [[TMP8:%.*]] = bitcast <1 x i64> [[TMP7]] to <8 x i8>
-// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint64x1x4_t, %struct.uint64x1x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL5]], i64 0, i64 3
-// CHECK: [[TMP9:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX6]], align 8
-// CHECK: [[TMP10:%.*]] = bitcast <1 x i64> [[TMP9]] to <8 x i8>
-// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <1 x i64>
-// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <1 x i64>
-// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <1 x i64>
-// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <1 x i64>
-// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i64*
-// CHECK: call void @llvm.aarch64.neon.st1x4.v1i64.p0i64(<1 x i64> [[TMP11]], <1 x i64> [[TMP12]], <1 x i64> [[TMP13]], <1 x i64> [[TMP14]], i64* [[TMP15]])
-// CHECK: ret void
-void test_vst1_u64_x4(uint64_t *a, uint64x1x4_t b) {
- vst1_u64_x4(a, b);
-}
-
-// CHECK-LABEL: @test_vst1_s8_x4(
-// CHECK: [[B:%.*]] = alloca %struct.int8x8x4_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.int8x8x4_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x8x4_t, %struct.int8x8x4_t* [[B]], i32 0, i32 0
-// CHECK: store [4 x <8 x i8>] [[B]].coerce, [4 x <8 x i8>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x4_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x8x4_t, %struct.int8x8x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int8x8x4_t, %struct.int8x8x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int8x8x4_t, %struct.int8x8x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP4:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX4]], align 8
-// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int8x8x4_t, %struct.int8x8x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL5]], i64 0, i64 3
-// CHECK: [[TMP5:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX6]], align 8
-// CHECK: call void @llvm.aarch64.neon.st1x4.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], <8 x i8> [[TMP5]], i8* %a)
-// CHECK: ret void
-void test_vst1_s8_x4(int8_t *a, int8x8x4_t b) {
- vst1_s8_x4(a, b);
-}
-
-// CHECK-LABEL: @test_vst1_s16_x4(
-// CHECK: [[B:%.*]] = alloca %struct.int16x4x4_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.int16x4x4_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x4x4_t, %struct.int16x4x4_t* [[B]], i32 0, i32 0
-// CHECK: store [4 x <4 x i16>] [[B]].coerce, [4 x <4 x i16>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x4_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x4x4_t, %struct.int16x4x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8
-// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int16x4x4_t, %struct.int16x4x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8
-// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int16x4x4_t, %struct.int16x4x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX4]], align 8
-// CHECK: [[TMP8:%.*]] = bitcast <4 x i16> [[TMP7]] to <8 x i8>
-// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int16x4x4_t, %struct.int16x4x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL5]], i64 0, i64 3
-// CHECK: [[TMP9:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX6]], align 8
-// CHECK: [[TMP10:%.*]] = bitcast <4 x i16> [[TMP9]] to <8 x i8>
-// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16>
-// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
-// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16>
-// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x i16>
-// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i16*
-// CHECK: call void @llvm.aarch64.neon.st1x4.v4i16.p0i16(<4 x i16> [[TMP11]], <4 x i16> [[TMP12]], <4 x i16> [[TMP13]], <4 x i16> [[TMP14]], i16* [[TMP15]])
-// CHECK: ret void
-void test_vst1_s16_x4(int16_t *a, int16x4x4_t b) {
- vst1_s16_x4(a, b);
-}
-
-// CHECK-LABEL: @test_vst1_s32_x4(
-// CHECK: [[B:%.*]] = alloca %struct.int32x2x4_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.int32x2x4_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x2x4_t, %struct.int32x2x4_t* [[B]], i32 0, i32 0
-// CHECK: store [4 x <2 x i32>] [[B]].coerce, [4 x <2 x i32>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x4_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x2x4_t, %struct.int32x2x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX]], align 8
-// CHECK: [[TMP4:%.*]] = bitcast <2 x i32> [[TMP3]] to <8 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int32x2x4_t, %struct.int32x2x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX2]], align 8
-// CHECK: [[TMP6:%.*]] = bitcast <2 x i32> [[TMP5]] to <8 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int32x2x4_t, %struct.int32x2x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX4]], align 8
-// CHECK: [[TMP8:%.*]] = bitcast <2 x i32> [[TMP7]] to <8 x i8>
-// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int32x2x4_t, %struct.int32x2x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL5]], i64 0, i64 3
-// CHECK: [[TMP9:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX6]], align 8
-// CHECK: [[TMP10:%.*]] = bitcast <2 x i32> [[TMP9]] to <8 x i8>
-// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x i32>
-// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x i32>
-// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <2 x i32>
-// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <2 x i32>
-// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i32*
-// CHECK: call void @llvm.aarch64.neon.st1x4.v2i32.p0i32(<2 x i32> [[TMP11]], <2 x i32> [[TMP12]], <2 x i32> [[TMP13]], <2 x i32> [[TMP14]], i32* [[TMP15]])
-// CHECK: ret void
-void test_vst1_s32_x4(int32_t *a, int32x2x4_t b) {
- vst1_s32_x4(a, b);
-}
-
-// CHECK-LABEL: @test_vst1_s64_x4(
-// CHECK: [[B:%.*]] = alloca %struct.int64x1x4_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.int64x1x4_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int64x1x4_t, %struct.int64x1x4_t* [[B]], i32 0, i32 0
-// CHECK: store [4 x <1 x i64>] [[B]].coerce, [4 x <1 x i64>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x4_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x1x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x1x4_t, %struct.int64x1x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX]], align 8
-// CHECK: [[TMP4:%.*]] = bitcast <1 x i64> [[TMP3]] to <8 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int64x1x4_t, %struct.int64x1x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX2]], align 8
-// CHECK: [[TMP6:%.*]] = bitcast <1 x i64> [[TMP5]] to <8 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int64x1x4_t, %struct.int64x1x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX4]], align 8
-// CHECK: [[TMP8:%.*]] = bitcast <1 x i64> [[TMP7]] to <8 x i8>
-// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int64x1x4_t, %struct.int64x1x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL5]], i64 0, i64 3
-// CHECK: [[TMP9:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX6]], align 8
-// CHECK: [[TMP10:%.*]] = bitcast <1 x i64> [[TMP9]] to <8 x i8>
-// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <1 x i64>
-// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <1 x i64>
-// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <1 x i64>
-// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <1 x i64>
-// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i64*
-// CHECK: call void @llvm.aarch64.neon.st1x4.v1i64.p0i64(<1 x i64> [[TMP11]], <1 x i64> [[TMP12]], <1 x i64> [[TMP13]], <1 x i64> [[TMP14]], i64* [[TMP15]])
-// CHECK: ret void
-void test_vst1_s64_x4(int64_t *a, int64x1x4_t b) {
- vst1_s64_x4(a, b);
-}
-
-// CHECK-LABEL: @test_vst1_f16_x4(
-// CHECK: [[B:%.*]] = alloca %struct.float16x4x4_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.float16x4x4_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x4x4_t, %struct.float16x4x4_t* [[B]], i32 0, i32 0
-// CHECK: store [4 x <4 x half>] [[B]].coerce, [4 x <4 x half>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x4_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x4x4_t, %struct.float16x4x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x half>], [4 x <4 x half>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX]], align 8
-// CHECK: [[TMP4:%.*]] = bitcast <4 x half> [[TMP3]] to <8 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float16x4x4_t, %struct.float16x4x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x half>], [4 x <4 x half>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX2]], align 8
-// CHECK: [[TMP6:%.*]] = bitcast <4 x half> [[TMP5]] to <8 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float16x4x4_t, %struct.float16x4x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x half>], [4 x <4 x half>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX4]], align 8
-// CHECK: [[TMP8:%.*]] = bitcast <4 x half> [[TMP7]] to <8 x i8>
-// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.float16x4x4_t, %struct.float16x4x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x half>], [4 x <4 x half>]* [[VAL5]], i64 0, i64 3
-// CHECK: [[TMP9:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX6]], align 8
-// CHECK: [[TMP10:%.*]] = bitcast <4 x half> [[TMP9]] to <8 x i8>
-// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x half>
-// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x half>
-// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x half>
-// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x half>
-// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to half*
-// CHECK: call void @llvm.aarch64.neon.st1x4.v4f16.p0f16(<4 x half> [[TMP11]], <4 x half> [[TMP12]], <4 x half> [[TMP13]], <4 x half> [[TMP14]], half* [[TMP15]])
-// CHECK: ret void
-void test_vst1_f16_x4(float16_t *a, float16x4x4_t b) {
- vst1_f16_x4(a, b);
-}
-
-// CHECK-LABEL: @test_vst1_f32_x4(
-// CHECK: [[B:%.*]] = alloca %struct.float32x2x4_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.float32x2x4_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x2x4_t, %struct.float32x2x4_t* [[B]], i32 0, i32 0
-// CHECK: store [4 x <2 x float>] [[B]].coerce, [4 x <2 x float>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x4_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x2x4_t, %struct.float32x2x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x float>], [4 x <2 x float>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX]], align 8
-// CHECK: [[TMP4:%.*]] = bitcast <2 x float> [[TMP3]] to <8 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float32x2x4_t, %struct.float32x2x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <2 x float>], [4 x <2 x float>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX2]], align 8
-// CHECK: [[TMP6:%.*]] = bitcast <2 x float> [[TMP5]] to <8 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float32x2x4_t, %struct.float32x2x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <2 x float>], [4 x <2 x float>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX4]], align 8
-// CHECK: [[TMP8:%.*]] = bitcast <2 x float> [[TMP7]] to <8 x i8>
-// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.float32x2x4_t, %struct.float32x2x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <2 x float>], [4 x <2 x float>]* [[VAL5]], i64 0, i64 3
-// CHECK: [[TMP9:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX6]], align 8
-// CHECK: [[TMP10:%.*]] = bitcast <2 x float> [[TMP9]] to <8 x i8>
-// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x float>
-// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x float>
-// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <2 x float>
-// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <2 x float>
-// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to float*
-// CHECK: call void @llvm.aarch64.neon.st1x4.v2f32.p0f32(<2 x float> [[TMP11]], <2 x float> [[TMP12]], <2 x float> [[TMP13]], <2 x float> [[TMP14]], float* [[TMP15]])
-// CHECK: ret void
-void test_vst1_f32_x4(float32_t *a, float32x2x4_t b) {
- vst1_f32_x4(a, b);
-}
-
// CHECK-LABEL: @test_vst1_f64_x4(
// CHECK: [[B:%.*]] = alloca %struct.float64x1x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.float64x1x4_t, align 8
@@ -16870,7 +13584,7 @@ void test_vst1_f32_x4(float32_t *a, float32x2x4_t b) {
// CHECK: store [4 x <1 x double>] [[B]].coerce, [4 x <1 x double>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x1x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float64x1x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast double* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float64x1x4_t, %struct.float64x1x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <1 x double>], [4 x <1 x double>]* [[VAL]], i64 0, i64 0
@@ -16899,68 +13613,6 @@ void test_vst1_f64_x4(float64_t *a, float64x1x4_t b) {
vst1_f64_x4(a, b);
}
-// CHECK-LABEL: @test_vst1_p8_x4(
-// CHECK: [[B:%.*]] = alloca %struct.poly8x8x4_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.poly8x8x4_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[B]], i32 0, i32 0
-// CHECK: store [4 x <8 x i8>] [[B]].coerce, [4 x <8 x i8>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x4_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP4:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX4]], align 8
-// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL5]], i64 0, i64 3
-// CHECK: [[TMP5:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX6]], align 8
-// CHECK: call void @llvm.aarch64.neon.st1x4.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], <8 x i8> [[TMP5]], i8* %a)
-// CHECK: ret void
-void test_vst1_p8_x4(poly8_t *a, poly8x8x4_t b) {
- vst1_p8_x4(a, b);
-}
-
-// CHECK-LABEL: @test_vst1_p16_x4(
-// CHECK: [[B:%.*]] = alloca %struct.poly16x4x4_t, align 8
-// CHECK: [[__S1:%.*]] = alloca %struct.poly16x4x4_t, align 8
-// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x4x4_t, %struct.poly16x4x4_t* [[B]], i32 0, i32 0
-// CHECK: store [4 x <4 x i16>] [[B]].coerce, [4 x <4 x i16>]* [[COERCE_DIVE]], align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x4_t* [[__S1]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
-// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x4x4_t, %struct.poly16x4x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL]], i64 0, i64 0
-// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8
-// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8>
-// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly16x4x4_t, %struct.poly16x4x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL1]], i64 0, i64 1
-// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8
-// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8>
-// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly16x4x4_t, %struct.poly16x4x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL3]], i64 0, i64 2
-// CHECK: [[TMP7:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX4]], align 8
-// CHECK: [[TMP8:%.*]] = bitcast <4 x i16> [[TMP7]] to <8 x i8>
-// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.poly16x4x4_t, %struct.poly16x4x4_t* [[__S1]], i32 0, i32 0
-// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL5]], i64 0, i64 3
-// CHECK: [[TMP9:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX6]], align 8
-// CHECK: [[TMP10:%.*]] = bitcast <4 x i16> [[TMP9]] to <8 x i8>
-// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16>
-// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
-// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16>
-// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x i16>
-// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i16*
-// CHECK: call void @llvm.aarch64.neon.st1x4.v4i16.p0i16(<4 x i16> [[TMP11]], <4 x i16> [[TMP12]], <4 x i16> [[TMP13]], <4 x i16> [[TMP14]], i16* [[TMP15]])
-// CHECK: ret void
-void test_vst1_p16_x4(poly16_t *a, poly16x4x4_t b) {
- vst1_p16_x4(a, b);
-}
-
// CHECK-LABEL: @test_vst1_p64_x4(
// CHECK: [[B:%.*]] = alloca %struct.poly64x1x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.poly64x1x4_t, align 8
@@ -16968,7 +13620,7 @@ void test_vst1_p16_x4(poly16_t *a, poly16x4x4_t b) {
// CHECK: store [4 x <1 x i64>] [[B]].coerce, [4 x <1 x i64>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x1x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly64x1x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly64x1x4_t, %struct.poly64x1x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL]], i64 0, i64 0
diff --git a/test/CodeGen/aarch64-neon-ldst-one.c b/test/CodeGen/aarch64-neon-ldst-one.c
index a3c5b140a0d2..592b2ceffa6a 100644
--- a/test/CodeGen/aarch64-neon-ldst-one.c
+++ b/test/CodeGen/aarch64-neon-ldst-one.c
@@ -300,58 +300,6 @@ poly64x1_t test_vld1_dup_p64(poly64_t *a) {
return vld1_dup_p64(a);
}
-// CHECK-LABEL: define %struct.uint8x16x2_t @test_vld2q_dup_u8(i8* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x16x2_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.uint8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET]] to i8*
-// CHECK: [[VLD2:%.*]] = call { <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld2r.v16i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8> }*
-// CHECK: store { <16 x i8>, <16 x i8> } [[VLD2]], { <16 x i8>, <16 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x16x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 32, i32 16, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.uint8x16x2_t [[TMP4]]
-uint8x16x2_t test_vld2q_dup_u8(uint8_t *a) {
- return vld2q_dup_u8(a);
-}
-
-// CHECK-LABEL: define %struct.uint16x8x2_t @test_vld2q_dup_u16(i16* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x8x2_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD2:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld2r.v8i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16> } [[VLD2]], { <8 x i16>, <8 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x8x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.uint16x8x2_t [[TMP6]]
-uint16x8x2_t test_vld2q_dup_u16(uint16_t *a) {
- return vld2q_dup_u16(a);
-}
-
-// CHECK-LABEL: define %struct.uint32x4x2_t @test_vld2q_dup_u32(i32* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x4x2_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
-// CHECK: [[VLD2:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2r.v4i32.p0i32(i32* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32> }*
-// CHECK: store { <4 x i32>, <4 x i32> } [[VLD2]], { <4 x i32>, <4 x i32> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x4x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.uint32x4x2_t [[TMP6]]
-uint32x4x2_t test_vld2q_dup_u32(uint32_t *a) {
- return vld2q_dup_u32(a);
-}
-
// CHECK-LABEL: define %struct.uint64x2x2_t @test_vld2q_dup_u64(i64* %a) #0 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint64x2x2_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.uint64x2x2_t, align 16
@@ -363,65 +311,13 @@ uint32x4x2_t test_vld2q_dup_u32(uint32_t *a) {
// CHECK: store { <2 x i64>, <2 x i64> } [[VLD2]], { <2 x i64>, <2 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x2x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.uint64x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 32, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.uint64x2x2_t, %struct.uint64x2x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.uint64x2x2_t [[TMP6]]
uint64x2x2_t test_vld2q_dup_u64(uint64_t *a) {
return vld2q_dup_u64(a);
}
-// CHECK-LABEL: define %struct.int8x16x2_t @test_vld2q_dup_s8(i8* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x16x2_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.int8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[__RET]] to i8*
-// CHECK: [[VLD2:%.*]] = call { <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld2r.v16i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8> }*
-// CHECK: store { <16 x i8>, <16 x i8> } [[VLD2]], { <16 x i8>, <16 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x16x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 32, i32 16, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.int8x16x2_t, %struct.int8x16x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.int8x16x2_t [[TMP4]]
-int8x16x2_t test_vld2q_dup_s8(int8_t *a) {
- return vld2q_dup_s8(a);
-}
-
-// CHECK-LABEL: define %struct.int16x8x2_t @test_vld2q_dup_s16(i16* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x8x2_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.int16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD2:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld2r.v8i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16> } [[VLD2]], { <8 x i16>, <8 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x8x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.int16x8x2_t, %struct.int16x8x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.int16x8x2_t [[TMP6]]
-int16x8x2_t test_vld2q_dup_s16(int16_t *a) {
- return vld2q_dup_s16(a);
-}
-
-// CHECK-LABEL: define %struct.int32x4x2_t @test_vld2q_dup_s32(i32* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x4x2_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.int32x4x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
-// CHECK: [[VLD2:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2r.v4i32.p0i32(i32* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32> }*
-// CHECK: store { <4 x i32>, <4 x i32> } [[VLD2]], { <4 x i32>, <4 x i32> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x4x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.int32x4x2_t, %struct.int32x4x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.int32x4x2_t [[TMP6]]
-int32x4x2_t test_vld2q_dup_s32(int32_t *a) {
- return vld2q_dup_s32(a);
-}
-
// CHECK-LABEL: define %struct.int64x2x2_t @test_vld2q_dup_s64(i64* %a) #0 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.int64x2x2_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.int64x2x2_t, align 16
@@ -433,49 +329,13 @@ int32x4x2_t test_vld2q_dup_s32(int32_t *a) {
// CHECK: store { <2 x i64>, <2 x i64> } [[VLD2]], { <2 x i64>, <2 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x2x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.int64x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 32, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.int64x2x2_t, %struct.int64x2x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.int64x2x2_t [[TMP6]]
int64x2x2_t test_vld2q_dup_s64(int64_t *a) {
return vld2q_dup_s64(a);
}
-// CHECK-LABEL: define %struct.float16x8x2_t @test_vld2q_dup_f16(half* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x8x2_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half*
-// CHECK: [[VLD2:%.*]] = call { <8 x half>, <8 x half> } @llvm.aarch64.neon.ld2r.v8f16.p0f16(half* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x half>, <8 x half> }*
-// CHECK: store { <8 x half>, <8 x half> } [[VLD2]], { <8 x half>, <8 x half> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x8x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.float16x8x2_t, %struct.float16x8x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.float16x8x2_t [[TMP6]]
-float16x8x2_t test_vld2q_dup_f16(float16_t *a) {
- return vld2q_dup_f16(a);
-}
-
-// CHECK-LABEL: define %struct.float32x4x2_t @test_vld2q_dup_f32(float* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x4x2_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.float32x4x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast float* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float*
-// CHECK: [[VLD2:%.*]] = call { <4 x float>, <4 x float> } @llvm.aarch64.neon.ld2r.v4f32.p0f32(float* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x float>, <4 x float> }*
-// CHECK: store { <4 x float>, <4 x float> } [[VLD2]], { <4 x float>, <4 x float> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x4x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.float32x4x2_t, %struct.float32x4x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.float32x4x2_t [[TMP6]]
-float32x4x2_t test_vld2q_dup_f32(float32_t *a) {
- return vld2q_dup_f32(a);
-}
-
// CHECK-LABEL: define %struct.float64x2x2_t @test_vld2q_dup_f64(double* %a) #0 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x2x2_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.float64x2x2_t, align 16
@@ -487,47 +347,13 @@ float32x4x2_t test_vld2q_dup_f32(float32_t *a) {
// CHECK: store { <2 x double>, <2 x double> } [[VLD2]], { <2 x double>, <2 x double> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float64x2x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float64x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 32, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.float64x2x2_t, %struct.float64x2x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.float64x2x2_t [[TMP6]]
float64x2x2_t test_vld2q_dup_f64(float64_t *a) {
return vld2q_dup_f64(a);
}
-// CHECK-LABEL: define %struct.poly8x16x2_t @test_vld2q_dup_p8(i8* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x16x2_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.poly8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET]] to i8*
-// CHECK: [[VLD2:%.*]] = call { <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld2r.v16i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8> }*
-// CHECK: store { <16 x i8>, <16 x i8> } [[VLD2]], { <16 x i8>, <16 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x16x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 32, i32 16, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.poly8x16x2_t [[TMP4]]
-poly8x16x2_t test_vld2q_dup_p8(poly8_t *a) {
- return vld2q_dup_p8(a);
-}
-
-// CHECK-LABEL: define %struct.poly16x8x2_t @test_vld2q_dup_p16(i16* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x8x2_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD2:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld2r.v8i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16> } [[VLD2]], { <8 x i16>, <8 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x8x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.poly16x8x2_t [[TMP6]]
-poly16x8x2_t test_vld2q_dup_p16(poly16_t *a) {
- return vld2q_dup_p16(a);
-}
-
// CHECK-LABEL: define %struct.poly64x2x2_t @test_vld2q_dup_p64(i64* %a) #0 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x2x2_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.poly64x2x2_t, align 16
@@ -539,189 +365,13 @@ poly16x8x2_t test_vld2q_dup_p16(poly16_t *a) {
// CHECK: store { <2 x i64>, <2 x i64> } [[VLD2]], { <2 x i64>, <2 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.poly64x2x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.poly64x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 32, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.poly64x2x2_t, %struct.poly64x2x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.poly64x2x2_t [[TMP6]]
poly64x2x2_t test_vld2q_dup_p64(poly64_t *a) {
return vld2q_dup_p64(a);
}
-// CHECK-LABEL: define %struct.uint8x8x2_t @test_vld2_dup_u8(i8* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x8x2_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.uint8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET]] to i8*
-// CHECK: [[VLD2:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld2r.v8i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8> }*
-// CHECK: store { <8 x i8>, <8 x i8> } [[VLD2]], { <8 x i8>, <8 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x8x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 16, i32 8, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.uint8x8x2_t [[TMP4]]
-uint8x8x2_t test_vld2_dup_u8(uint8_t *a) {
- return vld2_dup_u8(a);
-}
-
-// CHECK-LABEL: define %struct.uint16x4x2_t @test_vld2_dup_u16(i16* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x4x2_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.uint16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD2:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld2r.v4i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16> } [[VLD2]], { <4 x i16>, <4 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x4x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.uint16x4x2_t [[TMP6]]
-uint16x4x2_t test_vld2_dup_u16(uint16_t *a) {
- return vld2_dup_u16(a);
-}
-
-// CHECK-LABEL: define %struct.uint32x2x2_t @test_vld2_dup_u32(i32* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x2x2_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.uint32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
-// CHECK: [[VLD2:%.*]] = call { <2 x i32>, <2 x i32> } @llvm.aarch64.neon.ld2r.v2i32.p0i32(i32* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32> }*
-// CHECK: store { <2 x i32>, <2 x i32> } [[VLD2]], { <2 x i32>, <2 x i32> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x2x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.uint32x2x2_t [[TMP6]]
-uint32x2x2_t test_vld2_dup_u32(uint32_t *a) {
- return vld2_dup_u32(a);
-}
-
-// CHECK-LABEL: define %struct.uint64x1x2_t @test_vld2_dup_u64(i64* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint64x1x2_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.uint64x1x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
-// CHECK: [[VLD2:%.*]] = call { <1 x i64>, <1 x i64> } @llvm.aarch64.neon.ld2r.v1i64.p0i64(i64* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64> }*
-// CHECK: store { <1 x i64>, <1 x i64> } [[VLD2]], { <1 x i64>, <1 x i64> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x1x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint64x1x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.uint64x1x2_t, %struct.uint64x1x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.uint64x1x2_t [[TMP6]]
-uint64x1x2_t test_vld2_dup_u64(uint64_t *a) {
- return vld2_dup_u64(a);
-}
-
-// CHECK-LABEL: define %struct.int8x8x2_t @test_vld2_dup_s8(i8* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x8x2_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.int8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[__RET]] to i8*
-// CHECK: [[VLD2:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld2r.v8i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8> }*
-// CHECK: store { <8 x i8>, <8 x i8> } [[VLD2]], { <8 x i8>, <8 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x8x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 16, i32 8, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.int8x8x2_t, %struct.int8x8x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.int8x8x2_t [[TMP4]]
-int8x8x2_t test_vld2_dup_s8(int8_t *a) {
- return vld2_dup_s8(a);
-}
-
-// CHECK-LABEL: define %struct.int16x4x2_t @test_vld2_dup_s16(i16* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x4x2_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.int16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD2:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld2r.v4i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16> } [[VLD2]], { <4 x i16>, <4 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x4x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.int16x4x2_t, %struct.int16x4x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.int16x4x2_t [[TMP6]]
-int16x4x2_t test_vld2_dup_s16(int16_t *a) {
- return vld2_dup_s16(a);
-}
-
-// CHECK-LABEL: define %struct.int32x2x2_t @test_vld2_dup_s32(i32* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x2x2_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.int32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
-// CHECK: [[VLD2:%.*]] = call { <2 x i32>, <2 x i32> } @llvm.aarch64.neon.ld2r.v2i32.p0i32(i32* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32> }*
-// CHECK: store { <2 x i32>, <2 x i32> } [[VLD2]], { <2 x i32>, <2 x i32> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x2x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.int32x2x2_t, %struct.int32x2x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.int32x2x2_t [[TMP6]]
-int32x2x2_t test_vld2_dup_s32(int32_t *a) {
- return vld2_dup_s32(a);
-}
-
-// CHECK-LABEL: define %struct.int64x1x2_t @test_vld2_dup_s64(i64* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int64x1x2_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.int64x1x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
-// CHECK: [[VLD2:%.*]] = call { <1 x i64>, <1 x i64> } @llvm.aarch64.neon.ld2r.v1i64.p0i64(i64* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64> }*
-// CHECK: store { <1 x i64>, <1 x i64> } [[VLD2]], { <1 x i64>, <1 x i64> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x1x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int64x1x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.int64x1x2_t, %struct.int64x1x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.int64x1x2_t [[TMP6]]
-int64x1x2_t test_vld2_dup_s64(int64_t *a) {
- return vld2_dup_s64(a);
-}
-
-// CHECK-LABEL: define %struct.float16x4x2_t @test_vld2_dup_f16(half* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x4x2_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half*
-// CHECK: [[VLD2:%.*]] = call { <4 x half>, <4 x half> } @llvm.aarch64.neon.ld2r.v4f16.p0f16(half* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x half>, <4 x half> }*
-// CHECK: store { <4 x half>, <4 x half> } [[VLD2]], { <4 x half>, <4 x half> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x4x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.float16x4x2_t, %struct.float16x4x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.float16x4x2_t [[TMP6]]
-float16x4x2_t test_vld2_dup_f16(float16_t *a) {
- return vld2_dup_f16(a);
-}
-
-// CHECK-LABEL: define %struct.float32x2x2_t @test_vld2_dup_f32(float* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x2x2_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.float32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast float* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float*
-// CHECK: [[VLD2:%.*]] = call { <2 x float>, <2 x float> } @llvm.aarch64.neon.ld2r.v2f32.p0f32(float* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x float>, <2 x float> }*
-// CHECK: store { <2 x float>, <2 x float> } [[VLD2]], { <2 x float>, <2 x float> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x2x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.float32x2x2_t, %struct.float32x2x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.float32x2x2_t [[TMP6]]
-float32x2x2_t test_vld2_dup_f32(float32_t *a) {
- return vld2_dup_f32(a);
-}
-
// CHECK-LABEL: define %struct.float64x1x2_t @test_vld2_dup_f64(double* %a) #0 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x1x2_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.float64x1x2_t, align 8
@@ -733,47 +383,13 @@ float32x2x2_t test_vld2_dup_f32(float32_t *a) {
// CHECK: store { <1 x double>, <1 x double> } [[VLD2]], { <1 x double>, <1 x double> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float64x1x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float64x1x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 16, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.float64x1x2_t, %struct.float64x1x2_t* [[RETVAL]], align 8
// CHECK: ret %struct.float64x1x2_t [[TMP6]]
float64x1x2_t test_vld2_dup_f64(float64_t *a) {
return vld2_dup_f64(a);
}
-// CHECK-LABEL: define %struct.poly8x8x2_t @test_vld2_dup_p8(i8* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x8x2_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.poly8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET]] to i8*
-// CHECK: [[VLD2:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld2r.v8i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8> }*
-// CHECK: store { <8 x i8>, <8 x i8> } [[VLD2]], { <8 x i8>, <8 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x8x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 16, i32 8, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.poly8x8x2_t [[TMP4]]
-poly8x8x2_t test_vld2_dup_p8(poly8_t *a) {
- return vld2_dup_p8(a);
-}
-
-// CHECK-LABEL: define %struct.poly16x4x2_t @test_vld2_dup_p16(i16* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x4x2_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.poly16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD2:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld2r.v4i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16> } [[VLD2]], { <4 x i16>, <4 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x4x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.poly16x4x2_t [[TMP6]]
-poly16x4x2_t test_vld2_dup_p16(poly16_t *a) {
- return vld2_dup_p16(a);
-}
-
// CHECK-LABEL: define %struct.poly64x1x2_t @test_vld2_dup_p64(i64* %a) #0 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x1x2_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.poly64x1x2_t, align 8
@@ -785,68 +401,13 @@ poly16x4x2_t test_vld2_dup_p16(poly16_t *a) {
// CHECK: store { <1 x i64>, <1 x i64> } [[VLD2]], { <1 x i64>, <1 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.poly64x1x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.poly64x1x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 16, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.poly64x1x2_t, %struct.poly64x1x2_t* [[RETVAL]], align 8
// CHECK: ret %struct.poly64x1x2_t [[TMP6]]
poly64x1x2_t test_vld2_dup_p64(poly64_t *a) {
return vld2_dup_p64(a);
}
-// CHECK-LABEL: define %struct.uint8x16x3_t @test_vld3q_dup_u8(i8* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x16x3_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.uint8x16x3_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x3_t* [[__RET]] to i8*
-// CHECK: [[VLD3:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld3r.v16i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8> }*
-// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8> } [[VLD3]], { <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x16x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 48, i32 16, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[RETVAL]], align 16
-// CHECK: ret %struct.uint8x16x3_t [[TMP4]]
-uint8x16x3_t test_vld3q_dup_u8(uint8_t *a) {
- return vld3q_dup_u8(a);
- // [{{x[0-9]+|sp}}]
-}
-
-// CHECK-LABEL: define %struct.uint16x8x3_t @test_vld3q_dup_u16(i16* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x8x3_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x3_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD3:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld3r.v8i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD3]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x8x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[RETVAL]], align 16
-// CHECK: ret %struct.uint16x8x3_t [[TMP6]]
-uint16x8x3_t test_vld3q_dup_u16(uint16_t *a) {
- return vld3q_dup_u16(a);
- // [{{x[0-9]+|sp}}]
-}
-
-// CHECK-LABEL: define %struct.uint32x4x3_t @test_vld3q_dup_u32(i32* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x4x3_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x3_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
-// CHECK: [[VLD3:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld3r.v4i32.p0i32(i32* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32>, <4 x i32> }*
-// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32> } [[VLD3]], { <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x4x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[RETVAL]], align 16
-// CHECK: ret %struct.uint32x4x3_t [[TMP6]]
-uint32x4x3_t test_vld3q_dup_u32(uint32_t *a) {
- return vld3q_dup_u32(a);
- // [{{x[0-9]+|sp}}]
-}
-
// CHECK-LABEL: define %struct.uint64x2x3_t @test_vld3q_dup_u64(i64* %a) #0 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint64x2x3_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.uint64x2x3_t, align 16
@@ -858,7 +419,7 @@ uint32x4x3_t test_vld3q_dup_u32(uint32_t *a) {
// CHECK: store { <2 x i64>, <2 x i64>, <2 x i64> } [[VLD3]], { <2 x i64>, <2 x i64>, <2 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x2x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.uint64x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 48, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.uint64x2x3_t, %struct.uint64x2x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.uint64x2x3_t [[TMP6]]
uint64x2x3_t test_vld3q_dup_u64(uint64_t *a) {
@@ -866,61 +427,6 @@ uint64x2x3_t test_vld3q_dup_u64(uint64_t *a) {
// [{{x[0-9]+|sp}}]
}
-// CHECK-LABEL: define %struct.int8x16x3_t @test_vld3q_dup_s8(i8* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x16x3_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.int8x16x3_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x3_t* [[__RET]] to i8*
-// CHECK: [[VLD3:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld3r.v16i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8> }*
-// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8> } [[VLD3]], { <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x16x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 48, i32 16, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.int8x16x3_t, %struct.int8x16x3_t* [[RETVAL]], align 16
-// CHECK: ret %struct.int8x16x3_t [[TMP4]]
-int8x16x3_t test_vld3q_dup_s8(int8_t *a) {
- return vld3q_dup_s8(a);
- // [{{x[0-9]+|sp}}]
-}
-
-// CHECK-LABEL: define %struct.int16x8x3_t @test_vld3q_dup_s16(i16* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x8x3_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.int16x8x3_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD3:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld3r.v8i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD3]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x8x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.int16x8x3_t, %struct.int16x8x3_t* [[RETVAL]], align 16
-// CHECK: ret %struct.int16x8x3_t [[TMP6]]
-int16x8x3_t test_vld3q_dup_s16(int16_t *a) {
- return vld3q_dup_s16(a);
- // [{{x[0-9]+|sp}}]
-}
-
-// CHECK-LABEL: define %struct.int32x4x3_t @test_vld3q_dup_s32(i32* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x4x3_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.int32x4x3_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
-// CHECK: [[VLD3:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld3r.v4i32.p0i32(i32* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32>, <4 x i32> }*
-// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32> } [[VLD3]], { <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x4x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.int32x4x3_t, %struct.int32x4x3_t* [[RETVAL]], align 16
-// CHECK: ret %struct.int32x4x3_t [[TMP6]]
-int32x4x3_t test_vld3q_dup_s32(int32_t *a) {
- return vld3q_dup_s32(a);
- // [{{x[0-9]+|sp}}]
-}
-
// CHECK-LABEL: define %struct.int64x2x3_t @test_vld3q_dup_s64(i64* %a) #0 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.int64x2x3_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.int64x2x3_t, align 16
@@ -932,7 +438,7 @@ int32x4x3_t test_vld3q_dup_s32(int32_t *a) {
// CHECK: store { <2 x i64>, <2 x i64>, <2 x i64> } [[VLD3]], { <2 x i64>, <2 x i64>, <2 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x2x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.int64x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 48, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.int64x2x3_t, %struct.int64x2x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.int64x2x3_t [[TMP6]]
int64x2x3_t test_vld3q_dup_s64(int64_t *a) {
@@ -940,44 +446,6 @@ int64x2x3_t test_vld3q_dup_s64(int64_t *a) {
// [{{x[0-9]+|sp}}]
}
-// CHECK-LABEL: define %struct.float16x8x3_t @test_vld3q_dup_f16(half* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x8x3_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x3_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half*
-// CHECK: [[VLD3:%.*]] = call { <8 x half>, <8 x half>, <8 x half> } @llvm.aarch64.neon.ld3r.v8f16.p0f16(half* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x half>, <8 x half>, <8 x half> }*
-// CHECK: store { <8 x half>, <8 x half>, <8 x half> } [[VLD3]], { <8 x half>, <8 x half>, <8 x half> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x8x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.float16x8x3_t, %struct.float16x8x3_t* [[RETVAL]], align 16
-// CHECK: ret %struct.float16x8x3_t [[TMP6]]
-float16x8x3_t test_vld3q_dup_f16(float16_t *a) {
- return vld3q_dup_f16(a);
- // [{{x[0-9]+|sp}}]
-}
-
-// CHECK-LABEL: define %struct.float32x4x3_t @test_vld3q_dup_f32(float* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x4x3_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.float32x4x3_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast float* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float*
-// CHECK: [[VLD3:%.*]] = call { <4 x float>, <4 x float>, <4 x float> } @llvm.aarch64.neon.ld3r.v4f32.p0f32(float* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x float>, <4 x float>, <4 x float> }*
-// CHECK: store { <4 x float>, <4 x float>, <4 x float> } [[VLD3]], { <4 x float>, <4 x float>, <4 x float> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x4x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.float32x4x3_t, %struct.float32x4x3_t* [[RETVAL]], align 16
-// CHECK: ret %struct.float32x4x3_t [[TMP6]]
-float32x4x3_t test_vld3q_dup_f32(float32_t *a) {
- return vld3q_dup_f32(a);
- // [{{x[0-9]+|sp}}]
-}
-
// CHECK-LABEL: define %struct.float64x2x3_t @test_vld3q_dup_f64(double* %a) #0 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x2x3_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.float64x2x3_t, align 16
@@ -989,7 +457,7 @@ float32x4x3_t test_vld3q_dup_f32(float32_t *a) {
// CHECK: store { <2 x double>, <2 x double>, <2 x double> } [[VLD3]], { <2 x double>, <2 x double>, <2 x double> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float64x2x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float64x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 48, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.float64x2x3_t, %struct.float64x2x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.float64x2x3_t [[TMP6]]
float64x2x3_t test_vld3q_dup_f64(float64_t *a) {
@@ -997,42 +465,6 @@ float64x2x3_t test_vld3q_dup_f64(float64_t *a) {
// [{{x[0-9]+|sp}}]
}
-// CHECK-LABEL: define %struct.poly8x16x3_t @test_vld3q_dup_p8(i8* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x16x3_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.poly8x16x3_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x3_t* [[__RET]] to i8*
-// CHECK: [[VLD3:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld3r.v16i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8> }*
-// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8> } [[VLD3]], { <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x16x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 48, i32 16, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[RETVAL]], align 16
-// CHECK: ret %struct.poly8x16x3_t [[TMP4]]
-poly8x16x3_t test_vld3q_dup_p8(poly8_t *a) {
- return vld3q_dup_p8(a);
- // [{{x[0-9]+|sp}}]
-}
-
-// CHECK-LABEL: define %struct.poly16x8x3_t @test_vld3q_dup_p16(i16* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x8x3_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x3_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD3:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld3r.v8i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD3]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x8x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[RETVAL]], align 16
-// CHECK: ret %struct.poly16x8x3_t [[TMP6]]
-poly16x8x3_t test_vld3q_dup_p16(poly16_t *a) {
- return vld3q_dup_p16(a);
- // [{{x[0-9]+|sp}}]
-}
-
// CHECK-LABEL: define %struct.poly64x2x3_t @test_vld3q_dup_p64(i64* %a) #0 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x2x3_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.poly64x2x3_t, align 16
@@ -1044,7 +476,7 @@ poly16x8x3_t test_vld3q_dup_p16(poly16_t *a) {
// CHECK: store { <2 x i64>, <2 x i64>, <2 x i64> } [[VLD3]], { <2 x i64>, <2 x i64>, <2 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.poly64x2x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.poly64x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 48, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.poly64x2x3_t, %struct.poly64x2x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.poly64x2x3_t [[TMP6]]
poly64x2x3_t test_vld3q_dup_p64(poly64_t *a) {
@@ -1052,192 +484,6 @@ poly64x2x3_t test_vld3q_dup_p64(poly64_t *a) {
// [{{x[0-9]+|sp}}]
}
-// CHECK-LABEL: define %struct.uint8x8x3_t @test_vld3_dup_u8(i8* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x8x3_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.uint8x8x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x3_t* [[__RET]] to i8*
-// CHECK: [[VLD3:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld3r.v8i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8> }*
-// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD3]], { <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x8x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 24, i32 8, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.uint8x8x3_t, %struct.uint8x8x3_t* [[RETVAL]], align 8
-// CHECK: ret %struct.uint8x8x3_t [[TMP4]]
-uint8x8x3_t test_vld3_dup_u8(uint8_t *a) {
- return vld3_dup_u8(a);
- // [{{x[0-9]+|sp}}]
-}
-
-// CHECK-LABEL: define %struct.uint16x4x3_t @test_vld3_dup_u16(i16* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x4x3_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.uint16x4x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD3:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld3r.v4i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD3]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x4x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.uint16x4x3_t, %struct.uint16x4x3_t* [[RETVAL]], align 8
-// CHECK: ret %struct.uint16x4x3_t [[TMP6]]
-uint16x4x3_t test_vld3_dup_u16(uint16_t *a) {
- return vld3_dup_u16(a);
- // [{{x[0-9]+|sp}}]
-}
-
-// CHECK-LABEL: define %struct.uint32x2x3_t @test_vld3_dup_u32(i32* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x2x3_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.uint32x2x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
-// CHECK: [[VLD3:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32> } @llvm.aarch64.neon.ld3r.v2i32.p0i32(i32* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32>, <2 x i32> }*
-// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32> } [[VLD3]], { <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x2x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.uint32x2x3_t, %struct.uint32x2x3_t* [[RETVAL]], align 8
-// CHECK: ret %struct.uint32x2x3_t [[TMP6]]
-uint32x2x3_t test_vld3_dup_u32(uint32_t *a) {
- return vld3_dup_u32(a);
- // [{{x[0-9]+|sp}}]
-}
-
-// CHECK-LABEL: define %struct.uint64x1x3_t @test_vld3_dup_u64(i64* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint64x1x3_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.uint64x1x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
-// CHECK: [[VLD3:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64> } @llvm.aarch64.neon.ld3r.v1i64.p0i64(i64* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64>, <1 x i64> }*
-// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64> } [[VLD3]], { <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x1x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint64x1x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.uint64x1x3_t, %struct.uint64x1x3_t* [[RETVAL]], align 8
-// CHECK: ret %struct.uint64x1x3_t [[TMP6]]
-uint64x1x3_t test_vld3_dup_u64(uint64_t *a) {
- return vld3_dup_u64(a);
- // [{{x[0-9]+|sp}}]
-}
-
-// CHECK-LABEL: define %struct.int8x8x3_t @test_vld3_dup_s8(i8* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x8x3_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.int8x8x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x3_t* [[__RET]] to i8*
-// CHECK: [[VLD3:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld3r.v8i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8> }*
-// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD3]], { <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x8x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 24, i32 8, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.int8x8x3_t, %struct.int8x8x3_t* [[RETVAL]], align 8
-// CHECK: ret %struct.int8x8x3_t [[TMP4]]
-int8x8x3_t test_vld3_dup_s8(int8_t *a) {
- return vld3_dup_s8(a);
- // [{{x[0-9]+|sp}}]
-}
-
-// CHECK-LABEL: define %struct.int16x4x3_t @test_vld3_dup_s16(i16* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x4x3_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.int16x4x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD3:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld3r.v4i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD3]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x4x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.int16x4x3_t, %struct.int16x4x3_t* [[RETVAL]], align 8
-// CHECK: ret %struct.int16x4x3_t [[TMP6]]
-int16x4x3_t test_vld3_dup_s16(int16_t *a) {
- return vld3_dup_s16(a);
- // [{{x[0-9]+|sp}}]
-}
-
-// CHECK-LABEL: define %struct.int32x2x3_t @test_vld3_dup_s32(i32* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x2x3_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.int32x2x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
-// CHECK: [[VLD3:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32> } @llvm.aarch64.neon.ld3r.v2i32.p0i32(i32* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32>, <2 x i32> }*
-// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32> } [[VLD3]], { <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x2x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.int32x2x3_t, %struct.int32x2x3_t* [[RETVAL]], align 8
-// CHECK: ret %struct.int32x2x3_t [[TMP6]]
-int32x2x3_t test_vld3_dup_s32(int32_t *a) {
- return vld3_dup_s32(a);
- // [{{x[0-9]+|sp}}]
-}
-
-// CHECK-LABEL: define %struct.int64x1x3_t @test_vld3_dup_s64(i64* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int64x1x3_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.int64x1x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
-// CHECK: [[VLD3:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64> } @llvm.aarch64.neon.ld3r.v1i64.p0i64(i64* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64>, <1 x i64> }*
-// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64> } [[VLD3]], { <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x1x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int64x1x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.int64x1x3_t, %struct.int64x1x3_t* [[RETVAL]], align 8
-// CHECK: ret %struct.int64x1x3_t [[TMP6]]
-int64x1x3_t test_vld3_dup_s64(int64_t *a) {
- return vld3_dup_s64(a);
- // [{{x[0-9]+|sp}}]
-}
-
-// CHECK-LABEL: define %struct.float16x4x3_t @test_vld3_dup_f16(half* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x4x3_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half*
-// CHECK: [[VLD3:%.*]] = call { <4 x half>, <4 x half>, <4 x half> } @llvm.aarch64.neon.ld3r.v4f16.p0f16(half* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x half>, <4 x half>, <4 x half> }*
-// CHECK: store { <4 x half>, <4 x half>, <4 x half> } [[VLD3]], { <4 x half>, <4 x half>, <4 x half> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x4x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.float16x4x3_t, %struct.float16x4x3_t* [[RETVAL]], align 8
-// CHECK: ret %struct.float16x4x3_t [[TMP6]]
-float16x4x3_t test_vld3_dup_f16(float16_t *a) {
- return vld3_dup_f16(a);
- // [{{x[0-9]+|sp}}]
-}
-
-// CHECK-LABEL: define %struct.float32x2x3_t @test_vld3_dup_f32(float* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x2x3_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.float32x2x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast float* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float*
-// CHECK: [[VLD3:%.*]] = call { <2 x float>, <2 x float>, <2 x float> } @llvm.aarch64.neon.ld3r.v2f32.p0f32(float* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x float>, <2 x float>, <2 x float> }*
-// CHECK: store { <2 x float>, <2 x float>, <2 x float> } [[VLD3]], { <2 x float>, <2 x float>, <2 x float> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x2x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.float32x2x3_t, %struct.float32x2x3_t* [[RETVAL]], align 8
-// CHECK: ret %struct.float32x2x3_t [[TMP6]]
-float32x2x3_t test_vld3_dup_f32(float32_t *a) {
- return vld3_dup_f32(a);
- // [{{x[0-9]+|sp}}]
-}
-
// CHECK-LABEL: define %struct.float64x1x3_t @test_vld3_dup_f64(double* %a) #0 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x1x3_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.float64x1x3_t, align 8
@@ -1249,7 +495,7 @@ float32x2x3_t test_vld3_dup_f32(float32_t *a) {
// CHECK: store { <1 x double>, <1 x double>, <1 x double> } [[VLD3]], { <1 x double>, <1 x double>, <1 x double> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float64x1x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float64x1x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 24, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.float64x1x3_t, %struct.float64x1x3_t* [[RETVAL]], align 8
// CHECK: ret %struct.float64x1x3_t [[TMP6]]
float64x1x3_t test_vld3_dup_f64(float64_t *a) {
@@ -1257,42 +503,6 @@ float64x1x3_t test_vld3_dup_f64(float64_t *a) {
// [{{x[0-9]+|sp}}]
}
-// CHECK-LABEL: define %struct.poly8x8x3_t @test_vld3_dup_p8(i8* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x8x3_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.poly8x8x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x3_t* [[__RET]] to i8*
-// CHECK: [[VLD3:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld3r.v8i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8> }*
-// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD3]], { <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x8x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 24, i32 8, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.poly8x8x3_t, %struct.poly8x8x3_t* [[RETVAL]], align 8
-// CHECK: ret %struct.poly8x8x3_t [[TMP4]]
-poly8x8x3_t test_vld3_dup_p8(poly8_t *a) {
- return vld3_dup_p8(a);
- // [{{x[0-9]+|sp}}]
-}
-
-// CHECK-LABEL: define %struct.poly16x4x3_t @test_vld3_dup_p16(i16* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x4x3_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.poly16x4x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD3:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld3r.v4i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD3]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x4x3_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.poly16x4x3_t, %struct.poly16x4x3_t* [[RETVAL]], align 8
-// CHECK: ret %struct.poly16x4x3_t [[TMP6]]
-poly16x4x3_t test_vld3_dup_p16(poly16_t *a) {
- return vld3_dup_p16(a);
- // [{{x[0-9]+|sp}}]
-}
-
// CHECK-LABEL: define %struct.poly64x1x3_t @test_vld3_dup_p64(i64* %a) #0 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x1x3_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.poly64x1x3_t, align 8
@@ -1304,7 +514,7 @@ poly16x4x3_t test_vld3_dup_p16(poly16_t *a) {
// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64> } [[VLD3]], { <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.poly64x1x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.poly64x1x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 24, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.poly64x1x3_t, %struct.poly64x1x3_t* [[RETVAL]], align 8
// CHECK: ret %struct.poly64x1x3_t [[TMP6]]
poly64x1x3_t test_vld3_dup_p64(poly64_t *a) {
@@ -1312,58 +522,6 @@ poly64x1x3_t test_vld3_dup_p64(poly64_t *a) {
// [{{x[0-9]+|sp}}]
}
-// CHECK-LABEL: define %struct.uint8x16x4_t @test_vld4q_dup_u8(i8* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x16x4_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.uint8x16x4_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x4_t* [[__RET]] to i8*
-// CHECK: [[VLD4:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld4r.v16i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }*
-// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } [[VLD4]], { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x16x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 64, i32 16, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[RETVAL]], align 16
-// CHECK: ret %struct.uint8x16x4_t [[TMP4]]
-uint8x16x4_t test_vld4q_dup_u8(uint8_t *a) {
- return vld4q_dup_u8(a);
-}
-
-// CHECK-LABEL: define %struct.uint16x8x4_t @test_vld4q_dup_u16(i16* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x8x4_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x4_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD4:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld4r.v8i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } [[VLD4]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x8x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[RETVAL]], align 16
-// CHECK: ret %struct.uint16x8x4_t [[TMP6]]
-uint16x8x4_t test_vld4q_dup_u16(uint16_t *a) {
- return vld4q_dup_u16(a);
-}
-
-// CHECK-LABEL: define %struct.uint32x4x4_t @test_vld4q_dup_u32(i32* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x4x4_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x4_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
-// CHECK: [[VLD4:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld4r.v4i32.p0i32(i32* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> }*
-// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLD4]], { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x4x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[RETVAL]], align 16
-// CHECK: ret %struct.uint32x4x4_t [[TMP6]]
-uint32x4x4_t test_vld4q_dup_u32(uint32_t *a) {
- return vld4q_dup_u32(a);
-}
-
// CHECK-LABEL: define %struct.uint64x2x4_t @test_vld4q_dup_u64(i64* %a) #0 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint64x2x4_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.uint64x2x4_t, align 16
@@ -1375,65 +533,13 @@ uint32x4x4_t test_vld4q_dup_u32(uint32_t *a) {
// CHECK: store { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } [[VLD4]], { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x2x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.uint64x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 64, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.uint64x2x4_t, %struct.uint64x2x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.uint64x2x4_t [[TMP6]]
uint64x2x4_t test_vld4q_dup_u64(uint64_t *a) {
return vld4q_dup_u64(a);
}
-// CHECK-LABEL: define %struct.int8x16x4_t @test_vld4q_dup_s8(i8* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x16x4_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.int8x16x4_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x4_t* [[__RET]] to i8*
-// CHECK: [[VLD4:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld4r.v16i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }*
-// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } [[VLD4]], { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x16x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 64, i32 16, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.int8x16x4_t, %struct.int8x16x4_t* [[RETVAL]], align 16
-// CHECK: ret %struct.int8x16x4_t [[TMP4]]
-int8x16x4_t test_vld4q_dup_s8(int8_t *a) {
- return vld4q_dup_s8(a);
-}
-
-// CHECK-LABEL: define %struct.int16x8x4_t @test_vld4q_dup_s16(i16* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x8x4_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.int16x8x4_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD4:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld4r.v8i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } [[VLD4]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x8x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.int16x8x4_t, %struct.int16x8x4_t* [[RETVAL]], align 16
-// CHECK: ret %struct.int16x8x4_t [[TMP6]]
-int16x8x4_t test_vld4q_dup_s16(int16_t *a) {
- return vld4q_dup_s16(a);
-}
-
-// CHECK-LABEL: define %struct.int32x4x4_t @test_vld4q_dup_s32(i32* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x4x4_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.int32x4x4_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
-// CHECK: [[VLD4:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld4r.v4i32.p0i32(i32* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> }*
-// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLD4]], { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x4x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.int32x4x4_t, %struct.int32x4x4_t* [[RETVAL]], align 16
-// CHECK: ret %struct.int32x4x4_t [[TMP6]]
-int32x4x4_t test_vld4q_dup_s32(int32_t *a) {
- return vld4q_dup_s32(a);
-}
-
// CHECK-LABEL: define %struct.int64x2x4_t @test_vld4q_dup_s64(i64* %a) #0 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.int64x2x4_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.int64x2x4_t, align 16
@@ -1445,49 +551,13 @@ int32x4x4_t test_vld4q_dup_s32(int32_t *a) {
// CHECK: store { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } [[VLD4]], { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x2x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.int64x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 64, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.int64x2x4_t, %struct.int64x2x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.int64x2x4_t [[TMP6]]
int64x2x4_t test_vld4q_dup_s64(int64_t *a) {
return vld4q_dup_s64(a);
}
-// CHECK-LABEL: define %struct.float16x8x4_t @test_vld4q_dup_f16(half* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x8x4_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x4_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half*
-// CHECK: [[VLD4:%.*]] = call { <8 x half>, <8 x half>, <8 x half>, <8 x half> } @llvm.aarch64.neon.ld4r.v8f16.p0f16(half* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x half>, <8 x half>, <8 x half>, <8 x half> }*
-// CHECK: store { <8 x half>, <8 x half>, <8 x half>, <8 x half> } [[VLD4]], { <8 x half>, <8 x half>, <8 x half>, <8 x half> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x8x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.float16x8x4_t, %struct.float16x8x4_t* [[RETVAL]], align 16
-// CHECK: ret %struct.float16x8x4_t [[TMP6]]
-float16x8x4_t test_vld4q_dup_f16(float16_t *a) {
- return vld4q_dup_f16(a);
-}
-
-// CHECK-LABEL: define %struct.float32x4x4_t @test_vld4q_dup_f32(float* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x4x4_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.float32x4x4_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast float* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float*
-// CHECK: [[VLD4:%.*]] = call { <4 x float>, <4 x float>, <4 x float>, <4 x float> } @llvm.aarch64.neon.ld4r.v4f32.p0f32(float* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x float>, <4 x float>, <4 x float>, <4 x float> }*
-// CHECK: store { <4 x float>, <4 x float>, <4 x float>, <4 x float> } [[VLD4]], { <4 x float>, <4 x float>, <4 x float>, <4 x float> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x4x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.float32x4x4_t, %struct.float32x4x4_t* [[RETVAL]], align 16
-// CHECK: ret %struct.float32x4x4_t [[TMP6]]
-float32x4x4_t test_vld4q_dup_f32(float32_t *a) {
- return vld4q_dup_f32(a);
-}
-
// CHECK-LABEL: define %struct.float64x2x4_t @test_vld4q_dup_f64(double* %a) #0 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x2x4_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.float64x2x4_t, align 16
@@ -1499,47 +569,13 @@ float32x4x4_t test_vld4q_dup_f32(float32_t *a) {
// CHECK: store { <2 x double>, <2 x double>, <2 x double>, <2 x double> } [[VLD4]], { <2 x double>, <2 x double>, <2 x double>, <2 x double> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float64x2x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float64x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 64, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.float64x2x4_t, %struct.float64x2x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.float64x2x4_t [[TMP6]]
float64x2x4_t test_vld4q_dup_f64(float64_t *a) {
return vld4q_dup_f64(a);
}
-// CHECK-LABEL: define %struct.poly8x16x4_t @test_vld4q_dup_p8(i8* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x16x4_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.poly8x16x4_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x4_t* [[__RET]] to i8*
-// CHECK: [[VLD4:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld4r.v16i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }*
-// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } [[VLD4]], { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x16x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 64, i32 16, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[RETVAL]], align 16
-// CHECK: ret %struct.poly8x16x4_t [[TMP4]]
-poly8x16x4_t test_vld4q_dup_p8(poly8_t *a) {
- return vld4q_dup_p8(a);
-}
-
-// CHECK-LABEL: define %struct.poly16x8x4_t @test_vld4q_dup_p16(i16* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x8x4_t, align 16
-// CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x4_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD4:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld4r.v8i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } [[VLD4]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x8x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[RETVAL]], align 16
-// CHECK: ret %struct.poly16x8x4_t [[TMP6]]
-poly16x8x4_t test_vld4q_dup_p16(poly16_t *a) {
- return vld4q_dup_p16(a);
-}
-
// CHECK-LABEL: define %struct.poly64x2x4_t @test_vld4q_dup_p64(i64* %a) #0 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x2x4_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.poly64x2x4_t, align 16
@@ -1551,189 +587,13 @@ poly16x8x4_t test_vld4q_dup_p16(poly16_t *a) {
// CHECK: store { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } [[VLD4]], { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.poly64x2x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.poly64x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 64, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.poly64x2x4_t, %struct.poly64x2x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.poly64x2x4_t [[TMP6]]
poly64x2x4_t test_vld4q_dup_p64(poly64_t *a) {
return vld4q_dup_p64(a);
}
-// CHECK-LABEL: define %struct.uint8x8x4_t @test_vld4_dup_u8(i8* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x8x4_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.uint8x8x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x4_t* [[__RET]] to i8*
-// CHECK: [[VLD4:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld4r.v8i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }*
-// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[VLD4]], { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x8x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 32, i32 8, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[RETVAL]], align 8
-// CHECK: ret %struct.uint8x8x4_t [[TMP4]]
-uint8x8x4_t test_vld4_dup_u8(uint8_t *a) {
- return vld4_dup_u8(a);
-}
-
-// CHECK-LABEL: define %struct.uint16x4x4_t @test_vld4_dup_u16(i16* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x4x4_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.uint16x4x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD4:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld4r.v4i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD4]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x4x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.uint16x4x4_t, %struct.uint16x4x4_t* [[RETVAL]], align 8
-// CHECK: ret %struct.uint16x4x4_t [[TMP6]]
-uint16x4x4_t test_vld4_dup_u16(uint16_t *a) {
- return vld4_dup_u16(a);
-}
-
-// CHECK-LABEL: define %struct.uint32x2x4_t @test_vld4_dup_u32(i32* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x2x4_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.uint32x2x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
-// CHECK: [[VLD4:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } @llvm.aarch64.neon.ld4r.v2i32.p0i32(i32* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }*
-// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[VLD4]], { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x2x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.uint32x2x4_t, %struct.uint32x2x4_t* [[RETVAL]], align 8
-// CHECK: ret %struct.uint32x2x4_t [[TMP6]]
-uint32x2x4_t test_vld4_dup_u32(uint32_t *a) {
- return vld4_dup_u32(a);
-}
-
-// CHECK-LABEL: define %struct.uint64x1x4_t @test_vld4_dup_u64(i64* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.uint64x1x4_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.uint64x1x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
-// CHECK: [[VLD4:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } @llvm.aarch64.neon.ld4r.v1i64.p0i64(i64* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }*
-// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } [[VLD4]], { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x1x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint64x1x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.uint64x1x4_t, %struct.uint64x1x4_t* [[RETVAL]], align 8
-// CHECK: ret %struct.uint64x1x4_t [[TMP6]]
-uint64x1x4_t test_vld4_dup_u64(uint64_t *a) {
- return vld4_dup_u64(a);
-}
-
-// CHECK-LABEL: define %struct.int8x8x4_t @test_vld4_dup_s8(i8* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x8x4_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.int8x8x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x4_t* [[__RET]] to i8*
-// CHECK: [[VLD4:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld4r.v8i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }*
-// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[VLD4]], { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x8x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 32, i32 8, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.int8x8x4_t, %struct.int8x8x4_t* [[RETVAL]], align 8
-// CHECK: ret %struct.int8x8x4_t [[TMP4]]
-int8x8x4_t test_vld4_dup_s8(int8_t *a) {
- return vld4_dup_s8(a);
-}
-
-// CHECK-LABEL: define %struct.int16x4x4_t @test_vld4_dup_s16(i16* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x4x4_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.int16x4x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD4:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld4r.v4i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD4]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x4x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.int16x4x4_t, %struct.int16x4x4_t* [[RETVAL]], align 8
-// CHECK: ret %struct.int16x4x4_t [[TMP6]]
-int16x4x4_t test_vld4_dup_s16(int16_t *a) {
- return vld4_dup_s16(a);
-}
-
-// CHECK-LABEL: define %struct.int32x2x4_t @test_vld4_dup_s32(i32* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x2x4_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.int32x2x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
-// CHECK: [[VLD4:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } @llvm.aarch64.neon.ld4r.v2i32.p0i32(i32* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }*
-// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[VLD4]], { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x2x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.int32x2x4_t, %struct.int32x2x4_t* [[RETVAL]], align 8
-// CHECK: ret %struct.int32x2x4_t [[TMP6]]
-int32x2x4_t test_vld4_dup_s32(int32_t *a) {
- return vld4_dup_s32(a);
-}
-
-// CHECK-LABEL: define %struct.int64x1x4_t @test_vld4_dup_s64(i64* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.int64x1x4_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.int64x1x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
-// CHECK: [[VLD4:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } @llvm.aarch64.neon.ld4r.v1i64.p0i64(i64* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }*
-// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } [[VLD4]], { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x1x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int64x1x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.int64x1x4_t, %struct.int64x1x4_t* [[RETVAL]], align 8
-// CHECK: ret %struct.int64x1x4_t [[TMP6]]
-int64x1x4_t test_vld4_dup_s64(int64_t *a) {
- return vld4_dup_s64(a);
-}
-
-// CHECK-LABEL: define %struct.float16x4x4_t @test_vld4_dup_f16(half* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x4x4_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half*
-// CHECK: [[VLD4:%.*]] = call { <4 x half>, <4 x half>, <4 x half>, <4 x half> } @llvm.aarch64.neon.ld4r.v4f16.p0f16(half* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x half>, <4 x half>, <4 x half>, <4 x half> }*
-// CHECK: store { <4 x half>, <4 x half>, <4 x half>, <4 x half> } [[VLD4]], { <4 x half>, <4 x half>, <4 x half>, <4 x half> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x4x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.float16x4x4_t, %struct.float16x4x4_t* [[RETVAL]], align 8
-// CHECK: ret %struct.float16x4x4_t [[TMP6]]
-float16x4x4_t test_vld4_dup_f16(float16_t *a) {
- return vld4_dup_f16(a);
-}
-
-// CHECK-LABEL: define %struct.float32x2x4_t @test_vld4_dup_f32(float* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x2x4_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.float32x2x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast float* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float*
-// CHECK: [[VLD4:%.*]] = call { <2 x float>, <2 x float>, <2 x float>, <2 x float> } @llvm.aarch64.neon.ld4r.v2f32.p0f32(float* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x float>, <2 x float>, <2 x float>, <2 x float> }*
-// CHECK: store { <2 x float>, <2 x float>, <2 x float>, <2 x float> } [[VLD4]], { <2 x float>, <2 x float>, <2 x float>, <2 x float> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x2x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.float32x2x4_t, %struct.float32x2x4_t* [[RETVAL]], align 8
-// CHECK: ret %struct.float32x2x4_t [[TMP6]]
-float32x2x4_t test_vld4_dup_f32(float32_t *a) {
- return vld4_dup_f32(a);
-}
-
// CHECK-LABEL: define %struct.float64x1x4_t @test_vld4_dup_f64(double* %a) #0 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x1x4_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.float64x1x4_t, align 8
@@ -1745,47 +605,13 @@ float32x2x4_t test_vld4_dup_f32(float32_t *a) {
// CHECK: store { <1 x double>, <1 x double>, <1 x double>, <1 x double> } [[VLD4]], { <1 x double>, <1 x double>, <1 x double>, <1 x double> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float64x1x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float64x1x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 32, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.float64x1x4_t, %struct.float64x1x4_t* [[RETVAL]], align 8
// CHECK: ret %struct.float64x1x4_t [[TMP6]]
float64x1x4_t test_vld4_dup_f64(float64_t *a) {
return vld4_dup_f64(a);
}
-// CHECK-LABEL: define %struct.poly8x8x4_t @test_vld4_dup_p8(i8* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x8x4_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.poly8x8x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x4_t* [[__RET]] to i8*
-// CHECK: [[VLD4:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld4r.v8i8.p0i8(i8* %a)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }*
-// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[VLD4]], { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x8x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP2]], i8* [[TMP3]], i64 32, i32 8, i1 false)
-// CHECK: [[TMP4:%.*]] = load %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[RETVAL]], align 8
-// CHECK: ret %struct.poly8x8x4_t [[TMP4]]
-poly8x8x4_t test_vld4_dup_p8(poly8_t *a) {
- return vld4_dup_p8(a);
-}
-
-// CHECK-LABEL: define %struct.poly16x4x4_t @test_vld4_dup_p16(i16* %a) #0 {
-// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x4x4_t, align 8
-// CHECK: [[__RET:%.*]] = alloca %struct.poly16x4x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD4:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld4r.v4i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD4]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x4x4_t* [[RETVAL]] to i8*
-// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
-// CHECK: [[TMP6:%.*]] = load %struct.poly16x4x4_t, %struct.poly16x4x4_t* [[RETVAL]], align 8
-// CHECK: ret %struct.poly16x4x4_t [[TMP6]]
-poly16x4x4_t test_vld4_dup_p16(poly16_t *a) {
- return vld4_dup_p16(a);
-}
-
// CHECK-LABEL: define %struct.poly64x1x4_t @test_vld4_dup_p64(i64* %a) #0 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x1x4_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.poly64x1x4_t, align 8
@@ -1797,7 +623,7 @@ poly16x4x4_t test_vld4_dup_p16(poly16_t *a) {
// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } [[VLD4]], { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.poly64x1x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.poly64x1x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 32, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.poly64x1x4_t, %struct.poly64x1x4_t* [[RETVAL]], align 8
// CHECK: ret %struct.poly64x1x4_t [[TMP6]]
poly64x1x4_t test_vld4_dup_p64(poly64_t *a) {
@@ -2125,7 +951,7 @@ poly64x1_t test_vld1_lane_p64(poly64_t *a, poly64x1_t b) {
// CHECK: store [2 x <16 x i8>] [[SRC]].coerce, [2 x <16 x i8>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x16x2_t* [[SRC]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x16x2_t* [[__RET]] to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x16x2_t, %struct.int8x16x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL]], i64 0, i64 0
@@ -2138,7 +964,7 @@ poly64x1_t test_vld1_lane_p64(poly64_t *a, poly64x1_t b) {
// CHECK: store { <16 x i8>, <16 x i8> } [[VLD2_LANE]], { <16 x i8>, <16 x i8> }* [[TMP5]]
// CHECK: [[TMP6:%.*]] = bitcast %struct.int8x16x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP7:%.*]] = bitcast %struct.int8x16x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP6]], i8* [[TMP7]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP6]], i8* align 16 [[TMP7]], i64 32, i1 false)
// CHECK: [[TMP8:%.*]] = load %struct.int8x16x2_t, %struct.int8x16x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.int8x16x2_t [[TMP8]]
int8x16x2_t test_vld2q_lane_s8(int8_t const * ptr, int8x16x2_t src) {
@@ -2154,7 +980,7 @@ int8x16x2_t test_vld2q_lane_s8(int8_t const * ptr, int8x16x2_t src) {
// CHECK: store [2 x <16 x i8>] [[SRC]].coerce, [2 x <16 x i8>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x16x2_t* [[SRC]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET]] to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL]], i64 0, i64 0
@@ -2167,7 +993,7 @@ int8x16x2_t test_vld2q_lane_s8(int8_t const * ptr, int8x16x2_t src) {
// CHECK: store { <16 x i8>, <16 x i8> } [[VLD2_LANE]], { <16 x i8>, <16 x i8> }* [[TMP5]]
// CHECK: [[TMP6:%.*]] = bitcast %struct.uint8x16x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP7:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP6]], i8* [[TMP7]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP6]], i8* align 16 [[TMP7]], i64 32, i1 false)
// CHECK: [[TMP8:%.*]] = load %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.uint8x16x2_t [[TMP8]]
uint8x16x2_t test_vld2q_lane_u8(uint8_t const * ptr, uint8x16x2_t src) {
@@ -2183,7 +1009,7 @@ uint8x16x2_t test_vld2q_lane_u8(uint8_t const * ptr, uint8x16x2_t src) {
// CHECK: store [2 x <16 x i8>] [[SRC]].coerce, [2 x <16 x i8>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x16x2_t* [[SRC]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET]] to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL]], i64 0, i64 0
@@ -2196,7 +1022,7 @@ uint8x16x2_t test_vld2q_lane_u8(uint8_t const * ptr, uint8x16x2_t src) {
// CHECK: store { <16 x i8>, <16 x i8> } [[VLD2_LANE]], { <16 x i8>, <16 x i8> }* [[TMP5]]
// CHECK: [[TMP6:%.*]] = bitcast %struct.poly8x16x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP7:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP6]], i8* [[TMP7]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP6]], i8* align 16 [[TMP7]], i64 32, i1 false)
// CHECK: [[TMP8:%.*]] = load %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.poly8x16x2_t [[TMP8]]
poly8x16x2_t test_vld2q_lane_p8(poly8_t const * ptr, poly8x16x2_t src) {
@@ -2212,7 +1038,7 @@ poly8x16x2_t test_vld2q_lane_p8(poly8_t const * ptr, poly8x16x2_t src) {
// CHECK: store [3 x <16 x i8>] [[SRC]].coerce, [3 x <16 x i8>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x16x3_t* [[SRC]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x16x3_t* [[__RET]] to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x16x3_t, %struct.int8x16x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL]], i64 0, i64 0
@@ -2228,7 +1054,7 @@ poly8x16x2_t test_vld2q_lane_p8(poly8_t const * ptr, poly8x16x2_t src) {
// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8> } [[VLD3_LANE]], { <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP6]]
// CHECK: [[TMP7:%.*]] = bitcast %struct.int8x16x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP8:%.*]] = bitcast %struct.int8x16x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP7]], i8* align 16 [[TMP8]], i64 48, i1 false)
// CHECK: [[TMP9:%.*]] = load %struct.int8x16x3_t, %struct.int8x16x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.int8x16x3_t [[TMP9]]
int8x16x3_t test_vld3q_lane_s8(int8_t const * ptr, int8x16x3_t src) {
@@ -2244,7 +1070,7 @@ int8x16x3_t test_vld3q_lane_s8(int8_t const * ptr, int8x16x3_t src) {
// CHECK: store [3 x <16 x i8>] [[SRC]].coerce, [3 x <16 x i8>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x16x3_t* [[SRC]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x16x3_t* [[__RET]] to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL]], i64 0, i64 0
@@ -2260,7 +1086,7 @@ int8x16x3_t test_vld3q_lane_s8(int8_t const * ptr, int8x16x3_t src) {
// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8> } [[VLD3_LANE]], { <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP6]]
// CHECK: [[TMP7:%.*]] = bitcast %struct.uint8x16x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP8:%.*]] = bitcast %struct.uint8x16x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP7]], i8* align 16 [[TMP8]], i64 48, i1 false)
// CHECK: [[TMP9:%.*]] = load %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.uint8x16x3_t [[TMP9]]
uint8x16x3_t test_vld3q_lane_u8(uint8_t const * ptr, uint8x16x3_t src) {
@@ -2276,7 +1102,7 @@ uint8x16x3_t test_vld3q_lane_u8(uint8_t const * ptr, uint8x16x3_t src) {
// CHECK: store [2 x <8 x i16>] [[B]].coerce, [2 x <8 x i16>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[__S1]], i32 0, i32 0
@@ -2294,7 +1120,7 @@ uint8x16x3_t test_vld3q_lane_u8(uint8_t const * ptr, uint8x16x3_t src) {
// CHECK: store { <8 x i16>, <8 x i16> } [[VLD2_LANE]], { <8 x i16>, <8 x i16> }* [[TMP10]]
// CHECK: [[TMP11:%.*]] = bitcast %struct.uint16x8x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP12:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP11]], i8* [[TMP12]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP11]], i8* align 16 [[TMP12]], i64 32, i1 false)
// CHECK: [[TMP13:%.*]] = load %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.uint16x8x2_t [[TMP13]]
uint16x8x2_t test_vld2q_lane_u16(uint16_t *a, uint16x8x2_t b) {
@@ -2310,7 +1136,7 @@ uint16x8x2_t test_vld2q_lane_u16(uint16_t *a, uint16x8x2_t b) {
// CHECK: store [2 x <4 x i32>] [[B]].coerce, [2 x <4 x i32>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[__S1]], i32 0, i32 0
@@ -2328,7 +1154,7 @@ uint16x8x2_t test_vld2q_lane_u16(uint16_t *a, uint16x8x2_t b) {
// CHECK: store { <4 x i32>, <4 x i32> } [[VLD2_LANE]], { <4 x i32>, <4 x i32> }* [[TMP10]]
// CHECK: [[TMP11:%.*]] = bitcast %struct.uint32x4x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP12:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP11]], i8* [[TMP12]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP11]], i8* align 16 [[TMP12]], i64 32, i1 false)
// CHECK: [[TMP13:%.*]] = load %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.uint32x4x2_t [[TMP13]]
uint32x4x2_t test_vld2q_lane_u32(uint32_t *a, uint32x4x2_t b) {
@@ -2344,7 +1170,7 @@ uint32x4x2_t test_vld2q_lane_u32(uint32_t *a, uint32x4x2_t b) {
// CHECK: store [2 x <2 x i64>] [[B]].coerce, [2 x <2 x i64>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x2x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint64x2x2_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x2x2_t, %struct.uint64x2x2_t* [[__S1]], i32 0, i32 0
@@ -2362,7 +1188,7 @@ uint32x4x2_t test_vld2q_lane_u32(uint32_t *a, uint32x4x2_t b) {
// CHECK: store { <2 x i64>, <2 x i64> } [[VLD2_LANE]], { <2 x i64>, <2 x i64> }* [[TMP10]]
// CHECK: [[TMP11:%.*]] = bitcast %struct.uint64x2x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP12:%.*]] = bitcast %struct.uint64x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP11]], i8* [[TMP12]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP11]], i8* align 16 [[TMP12]], i64 32, i1 false)
// CHECK: [[TMP13:%.*]] = load %struct.uint64x2x2_t, %struct.uint64x2x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.uint64x2x2_t [[TMP13]]
uint64x2x2_t test_vld2q_lane_u64(uint64_t *a, uint64x2x2_t b) {
@@ -2378,7 +1204,7 @@ uint64x2x2_t test_vld2q_lane_u64(uint64_t *a, uint64x2x2_t b) {
// CHECK: store [2 x <8 x i16>] [[B]].coerce, [2 x <8 x i16>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.int16x8x2_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[__S1]], i32 0, i32 0
@@ -2396,7 +1222,7 @@ uint64x2x2_t test_vld2q_lane_u64(uint64_t *a, uint64x2x2_t b) {
// CHECK: store { <8 x i16>, <8 x i16> } [[VLD2_LANE]], { <8 x i16>, <8 x i16> }* [[TMP10]]
// CHECK: [[TMP11:%.*]] = bitcast %struct.int16x8x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP12:%.*]] = bitcast %struct.int16x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP11]], i8* [[TMP12]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP11]], i8* align 16 [[TMP12]], i64 32, i1 false)
// CHECK: [[TMP13:%.*]] = load %struct.int16x8x2_t, %struct.int16x8x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.int16x8x2_t [[TMP13]]
int16x8x2_t test_vld2q_lane_s16(int16_t *a, int16x8x2_t b) {
@@ -2412,7 +1238,7 @@ int16x8x2_t test_vld2q_lane_s16(int16_t *a, int16x8x2_t b) {
// CHECK: store [2 x <4 x i32>] [[B]].coerce, [2 x <4 x i32>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.int32x4x2_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[__S1]], i32 0, i32 0
@@ -2430,7 +1256,7 @@ int16x8x2_t test_vld2q_lane_s16(int16_t *a, int16x8x2_t b) {
// CHECK: store { <4 x i32>, <4 x i32> } [[VLD2_LANE]], { <4 x i32>, <4 x i32> }* [[TMP10]]
// CHECK: [[TMP11:%.*]] = bitcast %struct.int32x4x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP12:%.*]] = bitcast %struct.int32x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP11]], i8* [[TMP12]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP11]], i8* align 16 [[TMP12]], i64 32, i1 false)
// CHECK: [[TMP13:%.*]] = load %struct.int32x4x2_t, %struct.int32x4x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.int32x4x2_t [[TMP13]]
int32x4x2_t test_vld2q_lane_s32(int32_t *a, int32x4x2_t b) {
@@ -2446,7 +1272,7 @@ int32x4x2_t test_vld2q_lane_s32(int32_t *a, int32x4x2_t b) {
// CHECK: store [2 x <2 x i64>] [[B]].coerce, [2 x <2 x i64>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x2x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.int64x2x2_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x2x2_t, %struct.int64x2x2_t* [[__S1]], i32 0, i32 0
@@ -2464,7 +1290,7 @@ int32x4x2_t test_vld2q_lane_s32(int32_t *a, int32x4x2_t b) {
// CHECK: store { <2 x i64>, <2 x i64> } [[VLD2_LANE]], { <2 x i64>, <2 x i64> }* [[TMP10]]
// CHECK: [[TMP11:%.*]] = bitcast %struct.int64x2x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP12:%.*]] = bitcast %struct.int64x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP11]], i8* [[TMP12]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP11]], i8* align 16 [[TMP12]], i64 32, i1 false)
// CHECK: [[TMP13:%.*]] = load %struct.int64x2x2_t, %struct.int64x2x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.int64x2x2_t [[TMP13]]
int64x2x2_t test_vld2q_lane_s64(int64_t *a, int64x2x2_t b) {
@@ -2480,7 +1306,7 @@ int64x2x2_t test_vld2q_lane_s64(int64_t *a, int64x2x2_t b) {
// CHECK: store [2 x <8 x half>] [[B]].coerce, [2 x <8 x half>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.float16x8x2_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x2_t, %struct.float16x8x2_t* [[__S1]], i32 0, i32 0
@@ -2498,7 +1324,7 @@ int64x2x2_t test_vld2q_lane_s64(int64_t *a, int64x2x2_t b) {
// CHECK: store { <8 x half>, <8 x half> } [[VLD2_LANE]], { <8 x half>, <8 x half> }* [[TMP10]]
// CHECK: [[TMP11:%.*]] = bitcast %struct.float16x8x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP12:%.*]] = bitcast %struct.float16x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP11]], i8* [[TMP12]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP11]], i8* align 16 [[TMP12]], i64 32, i1 false)
// CHECK: [[TMP13:%.*]] = load %struct.float16x8x2_t, %struct.float16x8x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.float16x8x2_t [[TMP13]]
float16x8x2_t test_vld2q_lane_f16(float16_t *a, float16x8x2_t b) {
@@ -2514,7 +1340,7 @@ float16x8x2_t test_vld2q_lane_f16(float16_t *a, float16x8x2_t b) {
// CHECK: store [2 x <4 x float>] [[B]].coerce, [2 x <4 x float>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.float32x4x2_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[__S1]], i32 0, i32 0
@@ -2532,7 +1358,7 @@ float16x8x2_t test_vld2q_lane_f16(float16_t *a, float16x8x2_t b) {
// CHECK: store { <4 x float>, <4 x float> } [[VLD2_LANE]], { <4 x float>, <4 x float> }* [[TMP10]]
// CHECK: [[TMP11:%.*]] = bitcast %struct.float32x4x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP12:%.*]] = bitcast %struct.float32x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP11]], i8* [[TMP12]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP11]], i8* align 16 [[TMP12]], i64 32, i1 false)
// CHECK: [[TMP13:%.*]] = load %struct.float32x4x2_t, %struct.float32x4x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.float32x4x2_t [[TMP13]]
float32x4x2_t test_vld2q_lane_f32(float32_t *a, float32x4x2_t b) {
@@ -2548,7 +1374,7 @@ float32x4x2_t test_vld2q_lane_f32(float32_t *a, float32x4x2_t b) {
// CHECK: store [2 x <2 x double>] [[B]].coerce, [2 x <2 x double>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x2x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float64x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.float64x2x2_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast double* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float64x2x2_t, %struct.float64x2x2_t* [[__S1]], i32 0, i32 0
@@ -2566,7 +1392,7 @@ float32x4x2_t test_vld2q_lane_f32(float32_t *a, float32x4x2_t b) {
// CHECK: store { <2 x double>, <2 x double> } [[VLD2_LANE]], { <2 x double>, <2 x double> }* [[TMP10]]
// CHECK: [[TMP11:%.*]] = bitcast %struct.float64x2x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP12:%.*]] = bitcast %struct.float64x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP11]], i8* [[TMP12]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP11]], i8* align 16 [[TMP12]], i64 32, i1 false)
// CHECK: [[TMP13:%.*]] = load %struct.float64x2x2_t, %struct.float64x2x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.float64x2x2_t [[TMP13]]
float64x2x2_t test_vld2q_lane_f64(float64_t *a, float64x2x2_t b) {
@@ -2582,7 +1408,7 @@ float64x2x2_t test_vld2q_lane_f64(float64_t *a, float64x2x2_t b) {
// CHECK: store [2 x <8 x i16>] [[B]].coerce, [2 x <8 x i16>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[__S1]], i32 0, i32 0
@@ -2600,7 +1426,7 @@ float64x2x2_t test_vld2q_lane_f64(float64_t *a, float64x2x2_t b) {
// CHECK: store { <8 x i16>, <8 x i16> } [[VLD2_LANE]], { <8 x i16>, <8 x i16> }* [[TMP10]]
// CHECK: [[TMP11:%.*]] = bitcast %struct.poly16x8x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP12:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP11]], i8* [[TMP12]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP11]], i8* align 16 [[TMP12]], i64 32, i1 false)
// CHECK: [[TMP13:%.*]] = load %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.poly16x8x2_t [[TMP13]]
poly16x8x2_t test_vld2q_lane_p16(poly16_t *a, poly16x8x2_t b) {
@@ -2616,7 +1442,7 @@ poly16x8x2_t test_vld2q_lane_p16(poly16_t *a, poly16x8x2_t b) {
// CHECK: store [2 x <2 x i64>] [[B]].coerce, [2 x <2 x i64>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x2x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly64x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly64x2x2_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly64x2x2_t, %struct.poly64x2x2_t* [[__S1]], i32 0, i32 0
@@ -2634,7 +1460,7 @@ poly16x8x2_t test_vld2q_lane_p16(poly16_t *a, poly16x8x2_t b) {
// CHECK: store { <2 x i64>, <2 x i64> } [[VLD2_LANE]], { <2 x i64>, <2 x i64> }* [[TMP10]]
// CHECK: [[TMP11:%.*]] = bitcast %struct.poly64x2x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP12:%.*]] = bitcast %struct.poly64x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP11]], i8* [[TMP12]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP11]], i8* align 16 [[TMP12]], i64 32, i1 false)
// CHECK: [[TMP13:%.*]] = load %struct.poly64x2x2_t, %struct.poly64x2x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.poly64x2x2_t [[TMP13]]
poly64x2x2_t test_vld2q_lane_p64(poly64_t *a, poly64x2x2_t b) {
@@ -2650,7 +1476,7 @@ poly64x2x2_t test_vld2q_lane_p64(poly64_t *a, poly64x2x2_t b) {
// CHECK: store [2 x <8 x i8>] [[B]].coerce, [2 x <8 x i8>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET]] to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL]], i64 0, i64 0
@@ -2663,7 +1489,7 @@ poly64x2x2_t test_vld2q_lane_p64(poly64_t *a, poly64x2x2_t b) {
// CHECK: store { <8 x i8>, <8 x i8> } [[VLD2_LANE]], { <8 x i8>, <8 x i8> }* [[TMP5]]
// CHECK: [[TMP6:%.*]] = bitcast %struct.uint8x8x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP7:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP6]], i8* [[TMP7]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP6]], i8* align 8 [[TMP7]], i64 16, i1 false)
// CHECK: [[TMP8:%.*]] = load %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[RETVAL]], align 8
// CHECK: ret %struct.uint8x8x2_t [[TMP8]]
uint8x8x2_t test_vld2_lane_u8(uint8_t *a, uint8x8x2_t b) {
@@ -2679,7 +1505,7 @@ uint8x8x2_t test_vld2_lane_u8(uint8_t *a, uint8x8x2_t b) {
// CHECK: store [2 x <4 x i16>] [[B]].coerce, [2 x <4 x i16>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[__S1]], i32 0, i32 0
@@ -2697,7 +1523,7 @@ uint8x8x2_t test_vld2_lane_u8(uint8_t *a, uint8x8x2_t b) {
// CHECK: store { <4 x i16>, <4 x i16> } [[VLD2_LANE]], { <4 x i16>, <4 x i16> }* [[TMP10]]
// CHECK: [[TMP11:%.*]] = bitcast %struct.uint16x4x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP12:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP11]], i8* [[TMP12]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP11]], i8* align 8 [[TMP12]], i64 16, i1 false)
// CHECK: [[TMP13:%.*]] = load %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[RETVAL]], align 8
// CHECK: ret %struct.uint16x4x2_t [[TMP13]]
uint16x4x2_t test_vld2_lane_u16(uint16_t *a, uint16x4x2_t b) {
@@ -2713,7 +1539,7 @@ uint16x4x2_t test_vld2_lane_u16(uint16_t *a, uint16x4x2_t b) {
// CHECK: store [2 x <2 x i32>] [[B]].coerce, [2 x <2 x i32>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[__S1]], i32 0, i32 0
@@ -2731,7 +1557,7 @@ uint16x4x2_t test_vld2_lane_u16(uint16_t *a, uint16x4x2_t b) {
// CHECK: store { <2 x i32>, <2 x i32> } [[VLD2_LANE]], { <2 x i32>, <2 x i32> }* [[TMP10]]
// CHECK: [[TMP11:%.*]] = bitcast %struct.uint32x2x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP12:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP11]], i8* [[TMP12]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP11]], i8* align 8 [[TMP12]], i64 16, i1 false)
// CHECK: [[TMP13:%.*]] = load %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[RETVAL]], align 8
// CHECK: ret %struct.uint32x2x2_t [[TMP13]]
uint32x2x2_t test_vld2_lane_u32(uint32_t *a, uint32x2x2_t b) {
@@ -2747,7 +1573,7 @@ uint32x2x2_t test_vld2_lane_u32(uint32_t *a, uint32x2x2_t b) {
// CHECK: store [2 x <1 x i64>] [[B]].coerce, [2 x <1 x i64>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x1x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint64x1x2_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x1x2_t, %struct.uint64x1x2_t* [[__S1]], i32 0, i32 0
@@ -2765,7 +1591,7 @@ uint32x2x2_t test_vld2_lane_u32(uint32_t *a, uint32x2x2_t b) {
// CHECK: store { <1 x i64>, <1 x i64> } [[VLD2_LANE]], { <1 x i64>, <1 x i64> }* [[TMP10]]
// CHECK: [[TMP11:%.*]] = bitcast %struct.uint64x1x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP12:%.*]] = bitcast %struct.uint64x1x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP11]], i8* [[TMP12]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP11]], i8* align 8 [[TMP12]], i64 16, i1 false)
// CHECK: [[TMP13:%.*]] = load %struct.uint64x1x2_t, %struct.uint64x1x2_t* [[RETVAL]], align 8
// CHECK: ret %struct.uint64x1x2_t [[TMP13]]
uint64x1x2_t test_vld2_lane_u64(uint64_t *a, uint64x1x2_t b) {
@@ -2781,7 +1607,7 @@ uint64x1x2_t test_vld2_lane_u64(uint64_t *a, uint64x1x2_t b) {
// CHECK: store [2 x <8 x i8>] [[B]].coerce, [2 x <8 x i8>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x8x2_t* [[__RET]] to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x8x2_t, %struct.int8x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL]], i64 0, i64 0
@@ -2794,7 +1620,7 @@ uint64x1x2_t test_vld2_lane_u64(uint64_t *a, uint64x1x2_t b) {
// CHECK: store { <8 x i8>, <8 x i8> } [[VLD2_LANE]], { <8 x i8>, <8 x i8> }* [[TMP5]]
// CHECK: [[TMP6:%.*]] = bitcast %struct.int8x8x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP7:%.*]] = bitcast %struct.int8x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP6]], i8* [[TMP7]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP6]], i8* align 8 [[TMP7]], i64 16, i1 false)
// CHECK: [[TMP8:%.*]] = load %struct.int8x8x2_t, %struct.int8x8x2_t* [[RETVAL]], align 8
// CHECK: ret %struct.int8x8x2_t [[TMP8]]
int8x8x2_t test_vld2_lane_s8(int8_t *a, int8x8x2_t b) {
@@ -2810,7 +1636,7 @@ int8x8x2_t test_vld2_lane_s8(int8_t *a, int8x8x2_t b) {
// CHECK: store [2 x <4 x i16>] [[B]].coerce, [2 x <4 x i16>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.int16x4x2_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x4x2_t, %struct.int16x4x2_t* [[__S1]], i32 0, i32 0
@@ -2828,7 +1654,7 @@ int8x8x2_t test_vld2_lane_s8(int8_t *a, int8x8x2_t b) {
// CHECK: store { <4 x i16>, <4 x i16> } [[VLD2_LANE]], { <4 x i16>, <4 x i16> }* [[TMP10]]
// CHECK: [[TMP11:%.*]] = bitcast %struct.int16x4x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP12:%.*]] = bitcast %struct.int16x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP11]], i8* [[TMP12]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP11]], i8* align 8 [[TMP12]], i64 16, i1 false)
// CHECK: [[TMP13:%.*]] = load %struct.int16x4x2_t, %struct.int16x4x2_t* [[RETVAL]], align 8
// CHECK: ret %struct.int16x4x2_t [[TMP13]]
int16x4x2_t test_vld2_lane_s16(int16_t *a, int16x4x2_t b) {
@@ -2844,7 +1670,7 @@ int16x4x2_t test_vld2_lane_s16(int16_t *a, int16x4x2_t b) {
// CHECK: store [2 x <2 x i32>] [[B]].coerce, [2 x <2 x i32>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.int32x2x2_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x2x2_t, %struct.int32x2x2_t* [[__S1]], i32 0, i32 0
@@ -2862,7 +1688,7 @@ int16x4x2_t test_vld2_lane_s16(int16_t *a, int16x4x2_t b) {
// CHECK: store { <2 x i32>, <2 x i32> } [[VLD2_LANE]], { <2 x i32>, <2 x i32> }* [[TMP10]]
// CHECK: [[TMP11:%.*]] = bitcast %struct.int32x2x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP12:%.*]] = bitcast %struct.int32x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP11]], i8* [[TMP12]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP11]], i8* align 8 [[TMP12]], i64 16, i1 false)
// CHECK: [[TMP13:%.*]] = load %struct.int32x2x2_t, %struct.int32x2x2_t* [[RETVAL]], align 8
// CHECK: ret %struct.int32x2x2_t [[TMP13]]
int32x2x2_t test_vld2_lane_s32(int32_t *a, int32x2x2_t b) {
@@ -2878,7 +1704,7 @@ int32x2x2_t test_vld2_lane_s32(int32_t *a, int32x2x2_t b) {
// CHECK: store [2 x <1 x i64>] [[B]].coerce, [2 x <1 x i64>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x1x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.int64x1x2_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x1x2_t, %struct.int64x1x2_t* [[__S1]], i32 0, i32 0
@@ -2896,7 +1722,7 @@ int32x2x2_t test_vld2_lane_s32(int32_t *a, int32x2x2_t b) {
// CHECK: store { <1 x i64>, <1 x i64> } [[VLD2_LANE]], { <1 x i64>, <1 x i64> }* [[TMP10]]
// CHECK: [[TMP11:%.*]] = bitcast %struct.int64x1x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP12:%.*]] = bitcast %struct.int64x1x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP11]], i8* [[TMP12]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP11]], i8* align 8 [[TMP12]], i64 16, i1 false)
// CHECK: [[TMP13:%.*]] = load %struct.int64x1x2_t, %struct.int64x1x2_t* [[RETVAL]], align 8
// CHECK: ret %struct.int64x1x2_t [[TMP13]]
int64x1x2_t test_vld2_lane_s64(int64_t *a, int64x1x2_t b) {
@@ -2912,7 +1738,7 @@ int64x1x2_t test_vld2_lane_s64(int64_t *a, int64x1x2_t b) {
// CHECK: store [2 x <4 x half>] [[B]].coerce, [2 x <4 x half>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.float16x4x2_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x4x2_t, %struct.float16x4x2_t* [[__S1]], i32 0, i32 0
@@ -2930,7 +1756,7 @@ int64x1x2_t test_vld2_lane_s64(int64_t *a, int64x1x2_t b) {
// CHECK: store { <4 x half>, <4 x half> } [[VLD2_LANE]], { <4 x half>, <4 x half> }* [[TMP10]]
// CHECK: [[TMP11:%.*]] = bitcast %struct.float16x4x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP12:%.*]] = bitcast %struct.float16x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP11]], i8* [[TMP12]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP11]], i8* align 8 [[TMP12]], i64 16, i1 false)
// CHECK: [[TMP13:%.*]] = load %struct.float16x4x2_t, %struct.float16x4x2_t* [[RETVAL]], align 8
// CHECK: ret %struct.float16x4x2_t [[TMP13]]
float16x4x2_t test_vld2_lane_f16(float16_t *a, float16x4x2_t b) {
@@ -2946,7 +1772,7 @@ float16x4x2_t test_vld2_lane_f16(float16_t *a, float16x4x2_t b) {
// CHECK: store [2 x <2 x float>] [[B]].coerce, [2 x <2 x float>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.float32x2x2_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x2x2_t, %struct.float32x2x2_t* [[__S1]], i32 0, i32 0
@@ -2964,7 +1790,7 @@ float16x4x2_t test_vld2_lane_f16(float16_t *a, float16x4x2_t b) {
// CHECK: store { <2 x float>, <2 x float> } [[VLD2_LANE]], { <2 x float>, <2 x float> }* [[TMP10]]
// CHECK: [[TMP11:%.*]] = bitcast %struct.float32x2x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP12:%.*]] = bitcast %struct.float32x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP11]], i8* [[TMP12]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP11]], i8* align 8 [[TMP12]], i64 16, i1 false)
// CHECK: [[TMP13:%.*]] = load %struct.float32x2x2_t, %struct.float32x2x2_t* [[RETVAL]], align 8
// CHECK: ret %struct.float32x2x2_t [[TMP13]]
float32x2x2_t test_vld2_lane_f32(float32_t *a, float32x2x2_t b) {
@@ -2980,7 +1806,7 @@ float32x2x2_t test_vld2_lane_f32(float32_t *a, float32x2x2_t b) {
// CHECK: store [2 x <1 x double>] [[B]].coerce, [2 x <1 x double>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x1x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float64x1x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.float64x1x2_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast double* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float64x1x2_t, %struct.float64x1x2_t* [[__S1]], i32 0, i32 0
@@ -2998,7 +1824,7 @@ float32x2x2_t test_vld2_lane_f32(float32_t *a, float32x2x2_t b) {
// CHECK: store { <1 x double>, <1 x double> } [[VLD2_LANE]], { <1 x double>, <1 x double> }* [[TMP10]]
// CHECK: [[TMP11:%.*]] = bitcast %struct.float64x1x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP12:%.*]] = bitcast %struct.float64x1x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP11]], i8* [[TMP12]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP11]], i8* align 8 [[TMP12]], i64 16, i1 false)
// CHECK: [[TMP13:%.*]] = load %struct.float64x1x2_t, %struct.float64x1x2_t* [[RETVAL]], align 8
// CHECK: ret %struct.float64x1x2_t [[TMP13]]
float64x1x2_t test_vld2_lane_f64(float64_t *a, float64x1x2_t b) {
@@ -3014,7 +1840,7 @@ float64x1x2_t test_vld2_lane_f64(float64_t *a, float64x1x2_t b) {
// CHECK: store [2 x <8 x i8>] [[B]].coerce, [2 x <8 x i8>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET]] to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL]], i64 0, i64 0
@@ -3027,7 +1853,7 @@ float64x1x2_t test_vld2_lane_f64(float64_t *a, float64x1x2_t b) {
// CHECK: store { <8 x i8>, <8 x i8> } [[VLD2_LANE]], { <8 x i8>, <8 x i8> }* [[TMP5]]
// CHECK: [[TMP6:%.*]] = bitcast %struct.poly8x8x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP7:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP6]], i8* [[TMP7]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP6]], i8* align 8 [[TMP7]], i64 16, i1 false)
// CHECK: [[TMP8:%.*]] = load %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[RETVAL]], align 8
// CHECK: ret %struct.poly8x8x2_t [[TMP8]]
poly8x8x2_t test_vld2_lane_p8(poly8_t *a, poly8x8x2_t b) {
@@ -3043,7 +1869,7 @@ poly8x8x2_t test_vld2_lane_p8(poly8_t *a, poly8x8x2_t b) {
// CHECK: store [2 x <4 x i16>] [[B]].coerce, [2 x <4 x i16>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[__S1]], i32 0, i32 0
@@ -3061,7 +1887,7 @@ poly8x8x2_t test_vld2_lane_p8(poly8_t *a, poly8x8x2_t b) {
// CHECK: store { <4 x i16>, <4 x i16> } [[VLD2_LANE]], { <4 x i16>, <4 x i16> }* [[TMP10]]
// CHECK: [[TMP11:%.*]] = bitcast %struct.poly16x4x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP12:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP11]], i8* [[TMP12]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP11]], i8* align 8 [[TMP12]], i64 16, i1 false)
// CHECK: [[TMP13:%.*]] = load %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[RETVAL]], align 8
// CHECK: ret %struct.poly16x4x2_t [[TMP13]]
poly16x4x2_t test_vld2_lane_p16(poly16_t *a, poly16x4x2_t b) {
@@ -3077,7 +1903,7 @@ poly16x4x2_t test_vld2_lane_p16(poly16_t *a, poly16x4x2_t b) {
// CHECK: store [2 x <1 x i64>] [[B]].coerce, [2 x <1 x i64>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x1x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly64x1x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly64x1x2_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly64x1x2_t, %struct.poly64x1x2_t* [[__S1]], i32 0, i32 0
@@ -3095,7 +1921,7 @@ poly16x4x2_t test_vld2_lane_p16(poly16_t *a, poly16x4x2_t b) {
// CHECK: store { <1 x i64>, <1 x i64> } [[VLD2_LANE]], { <1 x i64>, <1 x i64> }* [[TMP10]]
// CHECK: [[TMP11:%.*]] = bitcast %struct.poly64x1x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP12:%.*]] = bitcast %struct.poly64x1x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP11]], i8* [[TMP12]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP11]], i8* align 8 [[TMP12]], i64 16, i1 false)
// CHECK: [[TMP13:%.*]] = load %struct.poly64x1x2_t, %struct.poly64x1x2_t* [[RETVAL]], align 8
// CHECK: ret %struct.poly64x1x2_t [[TMP13]]
poly64x1x2_t test_vld2_lane_p64(poly64_t *a, poly64x1x2_t b) {
@@ -3111,7 +1937,7 @@ poly64x1x2_t test_vld2_lane_p64(poly64_t *a, poly64x1x2_t b) {
// CHECK: store [3 x <8 x i16>] [[B]].coerce, [3 x <8 x i16>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint16x8x3_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[__S1]], i32 0, i32 0
@@ -3134,7 +1960,7 @@ poly64x1x2_t test_vld2_lane_p64(poly64_t *a, poly64x1x2_t b) {
// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD3_LANE]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP13]]
// CHECK: [[TMP14:%.*]] = bitcast %struct.uint16x8x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP15:%.*]] = bitcast %struct.uint16x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP14]], i8* [[TMP15]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP14]], i8* align 16 [[TMP15]], i64 48, i1 false)
// CHECK: [[TMP16:%.*]] = load %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.uint16x8x3_t [[TMP16]]
uint16x8x3_t test_vld3q_lane_u16(uint16_t *a, uint16x8x3_t b) {
@@ -3150,7 +1976,7 @@ uint16x8x3_t test_vld3q_lane_u16(uint16_t *a, uint16x8x3_t b) {
// CHECK: store [3 x <4 x i32>] [[B]].coerce, [3 x <4 x i32>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint32x4x3_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[__S1]], i32 0, i32 0
@@ -3173,7 +1999,7 @@ uint16x8x3_t test_vld3q_lane_u16(uint16_t *a, uint16x8x3_t b) {
// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32> } [[VLD3_LANE]], { <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP13]]
// CHECK: [[TMP14:%.*]] = bitcast %struct.uint32x4x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP15:%.*]] = bitcast %struct.uint32x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP14]], i8* [[TMP15]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP14]], i8* align 16 [[TMP15]], i64 48, i1 false)
// CHECK: [[TMP16:%.*]] = load %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.uint32x4x3_t [[TMP16]]
uint32x4x3_t test_vld3q_lane_u32(uint32_t *a, uint32x4x3_t b) {
@@ -3189,7 +2015,7 @@ uint32x4x3_t test_vld3q_lane_u32(uint32_t *a, uint32x4x3_t b) {
// CHECK: store [3 x <2 x i64>] [[B]].coerce, [3 x <2 x i64>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x2x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint64x2x3_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x2x3_t, %struct.uint64x2x3_t* [[__S1]], i32 0, i32 0
@@ -3212,7 +2038,7 @@ uint32x4x3_t test_vld3q_lane_u32(uint32_t *a, uint32x4x3_t b) {
// CHECK: store { <2 x i64>, <2 x i64>, <2 x i64> } [[VLD3_LANE]], { <2 x i64>, <2 x i64>, <2 x i64> }* [[TMP13]]
// CHECK: [[TMP14:%.*]] = bitcast %struct.uint64x2x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP15:%.*]] = bitcast %struct.uint64x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP14]], i8* [[TMP15]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP14]], i8* align 16 [[TMP15]], i64 48, i1 false)
// CHECK: [[TMP16:%.*]] = load %struct.uint64x2x3_t, %struct.uint64x2x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.uint64x2x3_t [[TMP16]]
uint64x2x3_t test_vld3q_lane_u64(uint64_t *a, uint64x2x3_t b) {
@@ -3228,7 +2054,7 @@ uint64x2x3_t test_vld3q_lane_u64(uint64_t *a, uint64x2x3_t b) {
// CHECK: store [3 x <8 x i16>] [[B]].coerce, [3 x <8 x i16>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.int16x8x3_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[__S1]], i32 0, i32 0
@@ -3251,7 +2077,7 @@ uint64x2x3_t test_vld3q_lane_u64(uint64_t *a, uint64x2x3_t b) {
// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD3_LANE]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP13]]
// CHECK: [[TMP14:%.*]] = bitcast %struct.int16x8x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP15:%.*]] = bitcast %struct.int16x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP14]], i8* [[TMP15]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP14]], i8* align 16 [[TMP15]], i64 48, i1 false)
// CHECK: [[TMP16:%.*]] = load %struct.int16x8x3_t, %struct.int16x8x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.int16x8x3_t [[TMP16]]
int16x8x3_t test_vld3q_lane_s16(int16_t *a, int16x8x3_t b) {
@@ -3267,7 +2093,7 @@ int16x8x3_t test_vld3q_lane_s16(int16_t *a, int16x8x3_t b) {
// CHECK: store [3 x <4 x i32>] [[B]].coerce, [3 x <4 x i32>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.int32x4x3_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[__S1]], i32 0, i32 0
@@ -3290,7 +2116,7 @@ int16x8x3_t test_vld3q_lane_s16(int16_t *a, int16x8x3_t b) {
// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32> } [[VLD3_LANE]], { <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP13]]
// CHECK: [[TMP14:%.*]] = bitcast %struct.int32x4x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP15:%.*]] = bitcast %struct.int32x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP14]], i8* [[TMP15]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP14]], i8* align 16 [[TMP15]], i64 48, i1 false)
// CHECK: [[TMP16:%.*]] = load %struct.int32x4x3_t, %struct.int32x4x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.int32x4x3_t [[TMP16]]
int32x4x3_t test_vld3q_lane_s32(int32_t *a, int32x4x3_t b) {
@@ -3306,7 +2132,7 @@ int32x4x3_t test_vld3q_lane_s32(int32_t *a, int32x4x3_t b) {
// CHECK: store [3 x <2 x i64>] [[B]].coerce, [3 x <2 x i64>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x2x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.int64x2x3_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x2x3_t, %struct.int64x2x3_t* [[__S1]], i32 0, i32 0
@@ -3329,7 +2155,7 @@ int32x4x3_t test_vld3q_lane_s32(int32_t *a, int32x4x3_t b) {
// CHECK: store { <2 x i64>, <2 x i64>, <2 x i64> } [[VLD3_LANE]], { <2 x i64>, <2 x i64>, <2 x i64> }* [[TMP13]]
// CHECK: [[TMP14:%.*]] = bitcast %struct.int64x2x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP15:%.*]] = bitcast %struct.int64x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP14]], i8* [[TMP15]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP14]], i8* align 16 [[TMP15]], i64 48, i1 false)
// CHECK: [[TMP16:%.*]] = load %struct.int64x2x3_t, %struct.int64x2x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.int64x2x3_t [[TMP16]]
int64x2x3_t test_vld3q_lane_s64(int64_t *a, int64x2x3_t b) {
@@ -3345,7 +2171,7 @@ int64x2x3_t test_vld3q_lane_s64(int64_t *a, int64x2x3_t b) {
// CHECK: store [3 x <8 x half>] [[B]].coerce, [3 x <8 x half>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.float16x8x3_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[__S1]], i32 0, i32 0
@@ -3368,7 +2194,7 @@ int64x2x3_t test_vld3q_lane_s64(int64_t *a, int64x2x3_t b) {
// CHECK: store { <8 x half>, <8 x half>, <8 x half> } [[VLD3_LANE]], { <8 x half>, <8 x half>, <8 x half> }* [[TMP13]]
// CHECK: [[TMP14:%.*]] = bitcast %struct.float16x8x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP15:%.*]] = bitcast %struct.float16x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP14]], i8* [[TMP15]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP14]], i8* align 16 [[TMP15]], i64 48, i1 false)
// CHECK: [[TMP16:%.*]] = load %struct.float16x8x3_t, %struct.float16x8x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.float16x8x3_t [[TMP16]]
float16x8x3_t test_vld3q_lane_f16(float16_t *a, float16x8x3_t b) {
@@ -3384,7 +2210,7 @@ float16x8x3_t test_vld3q_lane_f16(float16_t *a, float16x8x3_t b) {
// CHECK: store [3 x <4 x float>] [[B]].coerce, [3 x <4 x float>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.float32x4x3_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[__S1]], i32 0, i32 0
@@ -3407,7 +2233,7 @@ float16x8x3_t test_vld3q_lane_f16(float16_t *a, float16x8x3_t b) {
// CHECK: store { <4 x float>, <4 x float>, <4 x float> } [[VLD3_LANE]], { <4 x float>, <4 x float>, <4 x float> }* [[TMP13]]
// CHECK: [[TMP14:%.*]] = bitcast %struct.float32x4x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP15:%.*]] = bitcast %struct.float32x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP14]], i8* [[TMP15]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP14]], i8* align 16 [[TMP15]], i64 48, i1 false)
// CHECK: [[TMP16:%.*]] = load %struct.float32x4x3_t, %struct.float32x4x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.float32x4x3_t [[TMP16]]
float32x4x3_t test_vld3q_lane_f32(float32_t *a, float32x4x3_t b) {
@@ -3423,7 +2249,7 @@ float32x4x3_t test_vld3q_lane_f32(float32_t *a, float32x4x3_t b) {
// CHECK: store [3 x <2 x double>] [[B]].coerce, [3 x <2 x double>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x2x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float64x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.float64x2x3_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast double* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float64x2x3_t, %struct.float64x2x3_t* [[__S1]], i32 0, i32 0
@@ -3446,7 +2272,7 @@ float32x4x3_t test_vld3q_lane_f32(float32_t *a, float32x4x3_t b) {
// CHECK: store { <2 x double>, <2 x double>, <2 x double> } [[VLD3_LANE]], { <2 x double>, <2 x double>, <2 x double> }* [[TMP13]]
// CHECK: [[TMP14:%.*]] = bitcast %struct.float64x2x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP15:%.*]] = bitcast %struct.float64x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP14]], i8* [[TMP15]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP14]], i8* align 16 [[TMP15]], i64 48, i1 false)
// CHECK: [[TMP16:%.*]] = load %struct.float64x2x3_t, %struct.float64x2x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.float64x2x3_t [[TMP16]]
float64x2x3_t test_vld3q_lane_f64(float64_t *a, float64x2x3_t b) {
@@ -3462,7 +2288,7 @@ float64x2x3_t test_vld3q_lane_f64(float64_t *a, float64x2x3_t b) {
// CHECK: store [3 x <16 x i8>] [[B]].coerce, [3 x <16 x i8>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x16x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x16x3_t* [[__RET]] to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL]], i64 0, i64 0
@@ -3478,7 +2304,7 @@ float64x2x3_t test_vld3q_lane_f64(float64_t *a, float64x2x3_t b) {
// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8> } [[VLD3_LANE]], { <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP6]]
// CHECK: [[TMP7:%.*]] = bitcast %struct.poly8x16x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP8:%.*]] = bitcast %struct.poly8x16x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP7]], i8* align 16 [[TMP8]], i64 48, i1 false)
// CHECK: [[TMP9:%.*]] = load %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.poly8x16x3_t [[TMP9]]
poly8x16x3_t test_vld3q_lane_p8(poly8_t *a, poly8x16x3_t b) {
@@ -3494,7 +2320,7 @@ poly8x16x3_t test_vld3q_lane_p8(poly8_t *a, poly8x16x3_t b) {
// CHECK: store [3 x <8 x i16>] [[B]].coerce, [3 x <8 x i16>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly16x8x3_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[__S1]], i32 0, i32 0
@@ -3517,7 +2343,7 @@ poly8x16x3_t test_vld3q_lane_p8(poly8_t *a, poly8x16x3_t b) {
// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD3_LANE]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP13]]
// CHECK: [[TMP14:%.*]] = bitcast %struct.poly16x8x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP15:%.*]] = bitcast %struct.poly16x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP14]], i8* [[TMP15]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP14]], i8* align 16 [[TMP15]], i64 48, i1 false)
// CHECK: [[TMP16:%.*]] = load %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.poly16x8x3_t [[TMP16]]
poly16x8x3_t test_vld3q_lane_p16(poly16_t *a, poly16x8x3_t b) {
@@ -3533,7 +2359,7 @@ poly16x8x3_t test_vld3q_lane_p16(poly16_t *a, poly16x8x3_t b) {
// CHECK: store [3 x <2 x i64>] [[B]].coerce, [3 x <2 x i64>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x2x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly64x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly64x2x3_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly64x2x3_t, %struct.poly64x2x3_t* [[__S1]], i32 0, i32 0
@@ -3556,7 +2382,7 @@ poly16x8x3_t test_vld3q_lane_p16(poly16_t *a, poly16x8x3_t b) {
// CHECK: store { <2 x i64>, <2 x i64>, <2 x i64> } [[VLD3_LANE]], { <2 x i64>, <2 x i64>, <2 x i64> }* [[TMP13]]
// CHECK: [[TMP14:%.*]] = bitcast %struct.poly64x2x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP15:%.*]] = bitcast %struct.poly64x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP14]], i8* [[TMP15]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP14]], i8* align 16 [[TMP15]], i64 48, i1 false)
// CHECK: [[TMP16:%.*]] = load %struct.poly64x2x3_t, %struct.poly64x2x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.poly64x2x3_t [[TMP16]]
poly64x2x3_t test_vld3q_lane_p64(poly64_t *a, poly64x2x3_t b) {
@@ -3572,7 +2398,7 @@ poly64x2x3_t test_vld3q_lane_p64(poly64_t *a, poly64x2x3_t b) {
// CHECK: store [3 x <8 x i8>] [[B]].coerce, [3 x <8 x i8>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x8x3_t* [[__RET]] to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x8x3_t, %struct.uint8x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL]], i64 0, i64 0
@@ -3588,7 +2414,7 @@ poly64x2x3_t test_vld3q_lane_p64(poly64_t *a, poly64x2x3_t b) {
// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD3_LANE]], { <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP6]]
// CHECK: [[TMP7:%.*]] = bitcast %struct.uint8x8x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP8:%.*]] = bitcast %struct.uint8x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP7]], i8* align 8 [[TMP8]], i64 24, i1 false)
// CHECK: [[TMP9:%.*]] = load %struct.uint8x8x3_t, %struct.uint8x8x3_t* [[RETVAL]], align 8
// CHECK: ret %struct.uint8x8x3_t [[TMP9]]
uint8x8x3_t test_vld3_lane_u8(uint8_t *a, uint8x8x3_t b) {
@@ -3604,7 +2430,7 @@ uint8x8x3_t test_vld3_lane_u8(uint8_t *a, uint8x8x3_t b) {
// CHECK: store [3 x <4 x i16>] [[B]].coerce, [3 x <4 x i16>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint16x4x3_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x4x3_t, %struct.uint16x4x3_t* [[__S1]], i32 0, i32 0
@@ -3627,7 +2453,7 @@ uint8x8x3_t test_vld3_lane_u8(uint8_t *a, uint8x8x3_t b) {
// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD3_LANE]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP13]]
// CHECK: [[TMP14:%.*]] = bitcast %struct.uint16x4x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP15:%.*]] = bitcast %struct.uint16x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP14]], i8* [[TMP15]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP14]], i8* align 8 [[TMP15]], i64 24, i1 false)
// CHECK: [[TMP16:%.*]] = load %struct.uint16x4x3_t, %struct.uint16x4x3_t* [[RETVAL]], align 8
// CHECK: ret %struct.uint16x4x3_t [[TMP16]]
uint16x4x3_t test_vld3_lane_u16(uint16_t *a, uint16x4x3_t b) {
@@ -3643,7 +2469,7 @@ uint16x4x3_t test_vld3_lane_u16(uint16_t *a, uint16x4x3_t b) {
// CHECK: store [3 x <2 x i32>] [[B]].coerce, [3 x <2 x i32>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint32x2x3_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x2x3_t, %struct.uint32x2x3_t* [[__S1]], i32 0, i32 0
@@ -3666,7 +2492,7 @@ uint16x4x3_t test_vld3_lane_u16(uint16_t *a, uint16x4x3_t b) {
// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32> } [[VLD3_LANE]], { <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP13]]
// CHECK: [[TMP14:%.*]] = bitcast %struct.uint32x2x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP15:%.*]] = bitcast %struct.uint32x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP14]], i8* [[TMP15]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP14]], i8* align 8 [[TMP15]], i64 24, i1 false)
// CHECK: [[TMP16:%.*]] = load %struct.uint32x2x3_t, %struct.uint32x2x3_t* [[RETVAL]], align 8
// CHECK: ret %struct.uint32x2x3_t [[TMP16]]
uint32x2x3_t test_vld3_lane_u32(uint32_t *a, uint32x2x3_t b) {
@@ -3682,7 +2508,7 @@ uint32x2x3_t test_vld3_lane_u32(uint32_t *a, uint32x2x3_t b) {
// CHECK: store [3 x <1 x i64>] [[B]].coerce, [3 x <1 x i64>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x1x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint64x1x3_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x1x3_t, %struct.uint64x1x3_t* [[__S1]], i32 0, i32 0
@@ -3705,7 +2531,7 @@ uint32x2x3_t test_vld3_lane_u32(uint32_t *a, uint32x2x3_t b) {
// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64> } [[VLD3_LANE]], { <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP13]]
// CHECK: [[TMP14:%.*]] = bitcast %struct.uint64x1x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP15:%.*]] = bitcast %struct.uint64x1x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP14]], i8* [[TMP15]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP14]], i8* align 8 [[TMP15]], i64 24, i1 false)
// CHECK: [[TMP16:%.*]] = load %struct.uint64x1x3_t, %struct.uint64x1x3_t* [[RETVAL]], align 8
// CHECK: ret %struct.uint64x1x3_t [[TMP16]]
uint64x1x3_t test_vld3_lane_u64(uint64_t *a, uint64x1x3_t b) {
@@ -3721,7 +2547,7 @@ uint64x1x3_t test_vld3_lane_u64(uint64_t *a, uint64x1x3_t b) {
// CHECK: store [3 x <8 x i8>] [[B]].coerce, [3 x <8 x i8>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x8x3_t* [[__RET]] to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x8x3_t, %struct.int8x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL]], i64 0, i64 0
@@ -3737,7 +2563,7 @@ uint64x1x3_t test_vld3_lane_u64(uint64_t *a, uint64x1x3_t b) {
// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD3_LANE]], { <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP6]]
// CHECK: [[TMP7:%.*]] = bitcast %struct.int8x8x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP8:%.*]] = bitcast %struct.int8x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP7]], i8* align 8 [[TMP8]], i64 24, i1 false)
// CHECK: [[TMP9:%.*]] = load %struct.int8x8x3_t, %struct.int8x8x3_t* [[RETVAL]], align 8
// CHECK: ret %struct.int8x8x3_t [[TMP9]]
int8x8x3_t test_vld3_lane_s8(int8_t *a, int8x8x3_t b) {
@@ -3753,7 +2579,7 @@ int8x8x3_t test_vld3_lane_s8(int8_t *a, int8x8x3_t b) {
// CHECK: store [3 x <4 x i16>] [[B]].coerce, [3 x <4 x i16>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.int16x4x3_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x4x3_t, %struct.int16x4x3_t* [[__S1]], i32 0, i32 0
@@ -3776,7 +2602,7 @@ int8x8x3_t test_vld3_lane_s8(int8_t *a, int8x8x3_t b) {
// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD3_LANE]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP13]]
// CHECK: [[TMP14:%.*]] = bitcast %struct.int16x4x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP15:%.*]] = bitcast %struct.int16x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP14]], i8* [[TMP15]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP14]], i8* align 8 [[TMP15]], i64 24, i1 false)
// CHECK: [[TMP16:%.*]] = load %struct.int16x4x3_t, %struct.int16x4x3_t* [[RETVAL]], align 8
// CHECK: ret %struct.int16x4x3_t [[TMP16]]
int16x4x3_t test_vld3_lane_s16(int16_t *a, int16x4x3_t b) {
@@ -3792,7 +2618,7 @@ int16x4x3_t test_vld3_lane_s16(int16_t *a, int16x4x3_t b) {
// CHECK: store [3 x <2 x i32>] [[B]].coerce, [3 x <2 x i32>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.int32x2x3_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x2x3_t, %struct.int32x2x3_t* [[__S1]], i32 0, i32 0
@@ -3815,7 +2641,7 @@ int16x4x3_t test_vld3_lane_s16(int16_t *a, int16x4x3_t b) {
// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32> } [[VLD3_LANE]], { <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP13]]
// CHECK: [[TMP14:%.*]] = bitcast %struct.int32x2x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP15:%.*]] = bitcast %struct.int32x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP14]], i8* [[TMP15]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP14]], i8* align 8 [[TMP15]], i64 24, i1 false)
// CHECK: [[TMP16:%.*]] = load %struct.int32x2x3_t, %struct.int32x2x3_t* [[RETVAL]], align 8
// CHECK: ret %struct.int32x2x3_t [[TMP16]]
int32x2x3_t test_vld3_lane_s32(int32_t *a, int32x2x3_t b) {
@@ -3831,7 +2657,7 @@ int32x2x3_t test_vld3_lane_s32(int32_t *a, int32x2x3_t b) {
// CHECK: store [3 x <1 x i64>] [[B]].coerce, [3 x <1 x i64>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x1x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.int64x1x3_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x1x3_t, %struct.int64x1x3_t* [[__S1]], i32 0, i32 0
@@ -3854,7 +2680,7 @@ int32x2x3_t test_vld3_lane_s32(int32_t *a, int32x2x3_t b) {
// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64> } [[VLD3_LANE]], { <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP13]]
// CHECK: [[TMP14:%.*]] = bitcast %struct.int64x1x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP15:%.*]] = bitcast %struct.int64x1x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP14]], i8* [[TMP15]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP14]], i8* align 8 [[TMP15]], i64 24, i1 false)
// CHECK: [[TMP16:%.*]] = load %struct.int64x1x3_t, %struct.int64x1x3_t* [[RETVAL]], align 8
// CHECK: ret %struct.int64x1x3_t [[TMP16]]
int64x1x3_t test_vld3_lane_s64(int64_t *a, int64x1x3_t b) {
@@ -3870,7 +2696,7 @@ int64x1x3_t test_vld3_lane_s64(int64_t *a, int64x1x3_t b) {
// CHECK: store [3 x <4 x half>] [[B]].coerce, [3 x <4 x half>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.float16x4x3_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x4x3_t, %struct.float16x4x3_t* [[__S1]], i32 0, i32 0
@@ -3893,7 +2719,7 @@ int64x1x3_t test_vld3_lane_s64(int64_t *a, int64x1x3_t b) {
// CHECK: store { <4 x half>, <4 x half>, <4 x half> } [[VLD3_LANE]], { <4 x half>, <4 x half>, <4 x half> }* [[TMP13]]
// CHECK: [[TMP14:%.*]] = bitcast %struct.float16x4x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP15:%.*]] = bitcast %struct.float16x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP14]], i8* [[TMP15]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP14]], i8* align 8 [[TMP15]], i64 24, i1 false)
// CHECK: [[TMP16:%.*]] = load %struct.float16x4x3_t, %struct.float16x4x3_t* [[RETVAL]], align 8
// CHECK: ret %struct.float16x4x3_t [[TMP16]]
float16x4x3_t test_vld3_lane_f16(float16_t *a, float16x4x3_t b) {
@@ -3909,7 +2735,7 @@ float16x4x3_t test_vld3_lane_f16(float16_t *a, float16x4x3_t b) {
// CHECK: store [3 x <2 x float>] [[B]].coerce, [3 x <2 x float>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.float32x2x3_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x2x3_t, %struct.float32x2x3_t* [[__S1]], i32 0, i32 0
@@ -3932,7 +2758,7 @@ float16x4x3_t test_vld3_lane_f16(float16_t *a, float16x4x3_t b) {
// CHECK: store { <2 x float>, <2 x float>, <2 x float> } [[VLD3_LANE]], { <2 x float>, <2 x float>, <2 x float> }* [[TMP13]]
// CHECK: [[TMP14:%.*]] = bitcast %struct.float32x2x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP15:%.*]] = bitcast %struct.float32x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP14]], i8* [[TMP15]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP14]], i8* align 8 [[TMP15]], i64 24, i1 false)
// CHECK: [[TMP16:%.*]] = load %struct.float32x2x3_t, %struct.float32x2x3_t* [[RETVAL]], align 8
// CHECK: ret %struct.float32x2x3_t [[TMP16]]
float32x2x3_t test_vld3_lane_f32(float32_t *a, float32x2x3_t b) {
@@ -3948,7 +2774,7 @@ float32x2x3_t test_vld3_lane_f32(float32_t *a, float32x2x3_t b) {
// CHECK: store [3 x <1 x double>] [[B]].coerce, [3 x <1 x double>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x1x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float64x1x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.float64x1x3_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast double* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float64x1x3_t, %struct.float64x1x3_t* [[__S1]], i32 0, i32 0
@@ -3971,7 +2797,7 @@ float32x2x3_t test_vld3_lane_f32(float32_t *a, float32x2x3_t b) {
// CHECK: store { <1 x double>, <1 x double>, <1 x double> } [[VLD3_LANE]], { <1 x double>, <1 x double>, <1 x double> }* [[TMP13]]
// CHECK: [[TMP14:%.*]] = bitcast %struct.float64x1x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP15:%.*]] = bitcast %struct.float64x1x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP14]], i8* [[TMP15]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP14]], i8* align 8 [[TMP15]], i64 24, i1 false)
// CHECK: [[TMP16:%.*]] = load %struct.float64x1x3_t, %struct.float64x1x3_t* [[RETVAL]], align 8
// CHECK: ret %struct.float64x1x3_t [[TMP16]]
float64x1x3_t test_vld3_lane_f64(float64_t *a, float64x1x3_t b) {
@@ -3987,7 +2813,7 @@ float64x1x3_t test_vld3_lane_f64(float64_t *a, float64x1x3_t b) {
// CHECK: store [3 x <8 x i8>] [[B]].coerce, [3 x <8 x i8>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x8x3_t* [[__RET]] to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x8x3_t, %struct.poly8x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL]], i64 0, i64 0
@@ -4003,7 +2829,7 @@ float64x1x3_t test_vld3_lane_f64(float64_t *a, float64x1x3_t b) {
// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD3_LANE]], { <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP6]]
// CHECK: [[TMP7:%.*]] = bitcast %struct.poly8x8x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP8:%.*]] = bitcast %struct.poly8x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP7]], i8* align 8 [[TMP8]], i64 24, i1 false)
// CHECK: [[TMP9:%.*]] = load %struct.poly8x8x3_t, %struct.poly8x8x3_t* [[RETVAL]], align 8
// CHECK: ret %struct.poly8x8x3_t [[TMP9]]
poly8x8x3_t test_vld3_lane_p8(poly8_t *a, poly8x8x3_t b) {
@@ -4019,7 +2845,7 @@ poly8x8x3_t test_vld3_lane_p8(poly8_t *a, poly8x8x3_t b) {
// CHECK: store [3 x <4 x i16>] [[B]].coerce, [3 x <4 x i16>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly16x4x3_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x4x3_t, %struct.poly16x4x3_t* [[__S1]], i32 0, i32 0
@@ -4042,7 +2868,7 @@ poly8x8x3_t test_vld3_lane_p8(poly8_t *a, poly8x8x3_t b) {
// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD3_LANE]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP13]]
// CHECK: [[TMP14:%.*]] = bitcast %struct.poly16x4x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP15:%.*]] = bitcast %struct.poly16x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP14]], i8* [[TMP15]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP14]], i8* align 8 [[TMP15]], i64 24, i1 false)
// CHECK: [[TMP16:%.*]] = load %struct.poly16x4x3_t, %struct.poly16x4x3_t* [[RETVAL]], align 8
// CHECK: ret %struct.poly16x4x3_t [[TMP16]]
poly16x4x3_t test_vld3_lane_p16(poly16_t *a, poly16x4x3_t b) {
@@ -4058,7 +2884,7 @@ poly16x4x3_t test_vld3_lane_p16(poly16_t *a, poly16x4x3_t b) {
// CHECK: store [3 x <1 x i64>] [[B]].coerce, [3 x <1 x i64>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x1x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly64x1x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly64x1x3_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly64x1x3_t, %struct.poly64x1x3_t* [[__S1]], i32 0, i32 0
@@ -4081,7 +2907,7 @@ poly16x4x3_t test_vld3_lane_p16(poly16_t *a, poly16x4x3_t b) {
// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64> } [[VLD3_LANE]], { <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP13]]
// CHECK: [[TMP14:%.*]] = bitcast %struct.poly64x1x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP15:%.*]] = bitcast %struct.poly64x1x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP14]], i8* [[TMP15]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP14]], i8* align 8 [[TMP15]], i64 24, i1 false)
// CHECK: [[TMP16:%.*]] = load %struct.poly64x1x3_t, %struct.poly64x1x3_t* [[RETVAL]], align 8
// CHECK: ret %struct.poly64x1x3_t [[TMP16]]
poly64x1x3_t test_vld3_lane_p64(poly64_t *a, poly64x1x3_t b) {
@@ -4097,7 +2923,7 @@ poly64x1x3_t test_vld3_lane_p64(poly64_t *a, poly64x1x3_t b) {
// CHECK: store [4 x <16 x i8>] [[B]].coerce, [4 x <16 x i8>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x16x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x16x4_t* [[__RET]] to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL]], i64 0, i64 0
@@ -4116,7 +2942,7 @@ poly64x1x3_t test_vld3_lane_p64(poly64_t *a, poly64x1x3_t b) {
// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } [[VLD4_LANE]], { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP7]]
// CHECK: [[TMP8:%.*]] = bitcast %struct.uint8x16x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP9:%.*]] = bitcast %struct.uint8x16x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP8]], i8* [[TMP9]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP8]], i8* align 16 [[TMP9]], i64 64, i1 false)
// CHECK: [[TMP10:%.*]] = load %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.uint8x16x4_t [[TMP10]]
uint8x16x4_t test_vld4q_lane_u8(uint8_t *a, uint8x16x4_t b) {
@@ -4132,7 +2958,7 @@ uint8x16x4_t test_vld4q_lane_u8(uint8_t *a, uint8x16x4_t b) {
// CHECK: store [4 x <8 x i16>] [[B]].coerce, [4 x <8 x i16>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint16x8x4_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0
@@ -4160,7 +2986,7 @@ uint8x16x4_t test_vld4q_lane_u8(uint8_t *a, uint8x16x4_t b) {
// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } [[VLD4_LANE]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP16]]
// CHECK: [[TMP17:%.*]] = bitcast %struct.uint16x8x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP18:%.*]] = bitcast %struct.uint16x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP17]], i8* [[TMP18]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP17]], i8* align 16 [[TMP18]], i64 64, i1 false)
// CHECK: [[TMP19:%.*]] = load %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.uint16x8x4_t [[TMP19]]
uint16x8x4_t test_vld4q_lane_u16(uint16_t *a, uint16x8x4_t b) {
@@ -4176,7 +3002,7 @@ uint16x8x4_t test_vld4q_lane_u16(uint16_t *a, uint16x8x4_t b) {
// CHECK: store [4 x <4 x i32>] [[B]].coerce, [4 x <4 x i32>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint32x4x4_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0
@@ -4204,7 +3030,7 @@ uint16x8x4_t test_vld4q_lane_u16(uint16_t *a, uint16x8x4_t b) {
// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLD4_LANE]], { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP16]]
// CHECK: [[TMP17:%.*]] = bitcast %struct.uint32x4x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP18:%.*]] = bitcast %struct.uint32x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP17]], i8* [[TMP18]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP17]], i8* align 16 [[TMP18]], i64 64, i1 false)
// CHECK: [[TMP19:%.*]] = load %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.uint32x4x4_t [[TMP19]]
uint32x4x4_t test_vld4q_lane_u32(uint32_t *a, uint32x4x4_t b) {
@@ -4220,7 +3046,7 @@ uint32x4x4_t test_vld4q_lane_u32(uint32_t *a, uint32x4x4_t b) {
// CHECK: store [4 x <2 x i64>] [[B]].coerce, [4 x <2 x i64>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x2x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint64x2x4_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x2x4_t, %struct.uint64x2x4_t* [[__S1]], i32 0, i32 0
@@ -4248,7 +3074,7 @@ uint32x4x4_t test_vld4q_lane_u32(uint32_t *a, uint32x4x4_t b) {
// CHECK: store { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } [[VLD4_LANE]], { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> }* [[TMP16]]
// CHECK: [[TMP17:%.*]] = bitcast %struct.uint64x2x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP18:%.*]] = bitcast %struct.uint64x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP17]], i8* [[TMP18]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP17]], i8* align 16 [[TMP18]], i64 64, i1 false)
// CHECK: [[TMP19:%.*]] = load %struct.uint64x2x4_t, %struct.uint64x2x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.uint64x2x4_t [[TMP19]]
uint64x2x4_t test_vld4q_lane_u64(uint64_t *a, uint64x2x4_t b) {
@@ -4264,7 +3090,7 @@ uint64x2x4_t test_vld4q_lane_u64(uint64_t *a, uint64x2x4_t b) {
// CHECK: store [4 x <16 x i8>] [[B]].coerce, [4 x <16 x i8>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x16x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x16x4_t* [[__RET]] to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL]], i64 0, i64 0
@@ -4283,7 +3109,7 @@ uint64x2x4_t test_vld4q_lane_u64(uint64_t *a, uint64x2x4_t b) {
// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } [[VLD4_LANE]], { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP7]]
// CHECK: [[TMP8:%.*]] = bitcast %struct.int8x16x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP9:%.*]] = bitcast %struct.int8x16x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP8]], i8* [[TMP9]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP8]], i8* align 16 [[TMP9]], i64 64, i1 false)
// CHECK: [[TMP10:%.*]] = load %struct.int8x16x4_t, %struct.int8x16x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.int8x16x4_t [[TMP10]]
int8x16x4_t test_vld4q_lane_s8(int8_t *a, int8x16x4_t b) {
@@ -4299,7 +3125,7 @@ int8x16x4_t test_vld4q_lane_s8(int8_t *a, int8x16x4_t b) {
// CHECK: store [4 x <8 x i16>] [[B]].coerce, [4 x <8 x i16>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.int16x8x4_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0
@@ -4327,7 +3153,7 @@ int8x16x4_t test_vld4q_lane_s8(int8_t *a, int8x16x4_t b) {
// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } [[VLD4_LANE]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP16]]
// CHECK: [[TMP17:%.*]] = bitcast %struct.int16x8x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP18:%.*]] = bitcast %struct.int16x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP17]], i8* [[TMP18]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP17]], i8* align 16 [[TMP18]], i64 64, i1 false)
// CHECK: [[TMP19:%.*]] = load %struct.int16x8x4_t, %struct.int16x8x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.int16x8x4_t [[TMP19]]
int16x8x4_t test_vld4q_lane_s16(int16_t *a, int16x8x4_t b) {
@@ -4343,7 +3169,7 @@ int16x8x4_t test_vld4q_lane_s16(int16_t *a, int16x8x4_t b) {
// CHECK: store [4 x <4 x i32>] [[B]].coerce, [4 x <4 x i32>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.int32x4x4_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0
@@ -4371,7 +3197,7 @@ int16x8x4_t test_vld4q_lane_s16(int16_t *a, int16x8x4_t b) {
// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLD4_LANE]], { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP16]]
// CHECK: [[TMP17:%.*]] = bitcast %struct.int32x4x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP18:%.*]] = bitcast %struct.int32x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP17]], i8* [[TMP18]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP17]], i8* align 16 [[TMP18]], i64 64, i1 false)
// CHECK: [[TMP19:%.*]] = load %struct.int32x4x4_t, %struct.int32x4x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.int32x4x4_t [[TMP19]]
int32x4x4_t test_vld4q_lane_s32(int32_t *a, int32x4x4_t b) {
@@ -4387,7 +3213,7 @@ int32x4x4_t test_vld4q_lane_s32(int32_t *a, int32x4x4_t b) {
// CHECK: store [4 x <2 x i64>] [[B]].coerce, [4 x <2 x i64>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x2x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.int64x2x4_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x2x4_t, %struct.int64x2x4_t* [[__S1]], i32 0, i32 0
@@ -4415,7 +3241,7 @@ int32x4x4_t test_vld4q_lane_s32(int32_t *a, int32x4x4_t b) {
// CHECK: store { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } [[VLD4_LANE]], { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> }* [[TMP16]]
// CHECK: [[TMP17:%.*]] = bitcast %struct.int64x2x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP18:%.*]] = bitcast %struct.int64x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP17]], i8* [[TMP18]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP17]], i8* align 16 [[TMP18]], i64 64, i1 false)
// CHECK: [[TMP19:%.*]] = load %struct.int64x2x4_t, %struct.int64x2x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.int64x2x4_t [[TMP19]]
int64x2x4_t test_vld4q_lane_s64(int64_t *a, int64x2x4_t b) {
@@ -4431,7 +3257,7 @@ int64x2x4_t test_vld4q_lane_s64(int64_t *a, int64x2x4_t b) {
// CHECK: store [4 x <8 x half>] [[B]].coerce, [4 x <8 x half>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.float16x8x4_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0
@@ -4459,7 +3285,7 @@ int64x2x4_t test_vld4q_lane_s64(int64_t *a, int64x2x4_t b) {
// CHECK: store { <8 x half>, <8 x half>, <8 x half>, <8 x half> } [[VLD4_LANE]], { <8 x half>, <8 x half>, <8 x half>, <8 x half> }* [[TMP16]]
// CHECK: [[TMP17:%.*]] = bitcast %struct.float16x8x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP18:%.*]] = bitcast %struct.float16x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP17]], i8* [[TMP18]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP17]], i8* align 16 [[TMP18]], i64 64, i1 false)
// CHECK: [[TMP19:%.*]] = load %struct.float16x8x4_t, %struct.float16x8x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.float16x8x4_t [[TMP19]]
float16x8x4_t test_vld4q_lane_f16(float16_t *a, float16x8x4_t b) {
@@ -4475,7 +3301,7 @@ float16x8x4_t test_vld4q_lane_f16(float16_t *a, float16x8x4_t b) {
// CHECK: store [4 x <4 x float>] [[B]].coerce, [4 x <4 x float>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.float32x4x4_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0
@@ -4503,7 +3329,7 @@ float16x8x4_t test_vld4q_lane_f16(float16_t *a, float16x8x4_t b) {
// CHECK: store { <4 x float>, <4 x float>, <4 x float>, <4 x float> } [[VLD4_LANE]], { <4 x float>, <4 x float>, <4 x float>, <4 x float> }* [[TMP16]]
// CHECK: [[TMP17:%.*]] = bitcast %struct.float32x4x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP18:%.*]] = bitcast %struct.float32x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP17]], i8* [[TMP18]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP17]], i8* align 16 [[TMP18]], i64 64, i1 false)
// CHECK: [[TMP19:%.*]] = load %struct.float32x4x4_t, %struct.float32x4x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.float32x4x4_t [[TMP19]]
float32x4x4_t test_vld4q_lane_f32(float32_t *a, float32x4x4_t b) {
@@ -4519,7 +3345,7 @@ float32x4x4_t test_vld4q_lane_f32(float32_t *a, float32x4x4_t b) {
// CHECK: store [4 x <2 x double>] [[B]].coerce, [4 x <2 x double>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x2x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float64x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.float64x2x4_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast double* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float64x2x4_t, %struct.float64x2x4_t* [[__S1]], i32 0, i32 0
@@ -4547,7 +3373,7 @@ float32x4x4_t test_vld4q_lane_f32(float32_t *a, float32x4x4_t b) {
// CHECK: store { <2 x double>, <2 x double>, <2 x double>, <2 x double> } [[VLD4_LANE]], { <2 x double>, <2 x double>, <2 x double>, <2 x double> }* [[TMP16]]
// CHECK: [[TMP17:%.*]] = bitcast %struct.float64x2x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP18:%.*]] = bitcast %struct.float64x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP17]], i8* [[TMP18]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP17]], i8* align 16 [[TMP18]], i64 64, i1 false)
// CHECK: [[TMP19:%.*]] = load %struct.float64x2x4_t, %struct.float64x2x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.float64x2x4_t [[TMP19]]
float64x2x4_t test_vld4q_lane_f64(float64_t *a, float64x2x4_t b) {
@@ -4563,7 +3389,7 @@ float64x2x4_t test_vld4q_lane_f64(float64_t *a, float64x2x4_t b) {
// CHECK: store [4 x <16 x i8>] [[B]].coerce, [4 x <16 x i8>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x16x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x16x4_t* [[__RET]] to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL]], i64 0, i64 0
@@ -4582,7 +3408,7 @@ float64x2x4_t test_vld4q_lane_f64(float64_t *a, float64x2x4_t b) {
// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } [[VLD4_LANE]], { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP7]]
// CHECK: [[TMP8:%.*]] = bitcast %struct.poly8x16x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP9:%.*]] = bitcast %struct.poly8x16x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP8]], i8* [[TMP9]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP8]], i8* align 16 [[TMP9]], i64 64, i1 false)
// CHECK: [[TMP10:%.*]] = load %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.poly8x16x4_t [[TMP10]]
poly8x16x4_t test_vld4q_lane_p8(poly8_t *a, poly8x16x4_t b) {
@@ -4598,7 +3424,7 @@ poly8x16x4_t test_vld4q_lane_p8(poly8_t *a, poly8x16x4_t b) {
// CHECK: store [4 x <8 x i16>] [[B]].coerce, [4 x <8 x i16>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly16x8x4_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0
@@ -4626,7 +3452,7 @@ poly8x16x4_t test_vld4q_lane_p8(poly8_t *a, poly8x16x4_t b) {
// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } [[VLD4_LANE]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP16]]
// CHECK: [[TMP17:%.*]] = bitcast %struct.poly16x8x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP18:%.*]] = bitcast %struct.poly16x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP17]], i8* [[TMP18]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP17]], i8* align 16 [[TMP18]], i64 64, i1 false)
// CHECK: [[TMP19:%.*]] = load %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.poly16x8x4_t [[TMP19]]
poly16x8x4_t test_vld4q_lane_p16(poly16_t *a, poly16x8x4_t b) {
@@ -4642,7 +3468,7 @@ poly16x8x4_t test_vld4q_lane_p16(poly16_t *a, poly16x8x4_t b) {
// CHECK: store [4 x <2 x i64>] [[B]].coerce, [4 x <2 x i64>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x2x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly64x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly64x2x4_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly64x2x4_t, %struct.poly64x2x4_t* [[__S1]], i32 0, i32 0
@@ -4670,7 +3496,7 @@ poly16x8x4_t test_vld4q_lane_p16(poly16_t *a, poly16x8x4_t b) {
// CHECK: store { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } [[VLD4_LANE]], { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> }* [[TMP16]]
// CHECK: [[TMP17:%.*]] = bitcast %struct.poly64x2x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP18:%.*]] = bitcast %struct.poly64x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP17]], i8* [[TMP18]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP17]], i8* align 16 [[TMP18]], i64 64, i1 false)
// CHECK: [[TMP19:%.*]] = load %struct.poly64x2x4_t, %struct.poly64x2x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.poly64x2x4_t [[TMP19]]
poly64x2x4_t test_vld4q_lane_p64(poly64_t *a, poly64x2x4_t b) {
@@ -4686,7 +3512,7 @@ poly64x2x4_t test_vld4q_lane_p64(poly64_t *a, poly64x2x4_t b) {
// CHECK: store [4 x <8 x i8>] [[B]].coerce, [4 x <8 x i8>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x8x4_t* [[__RET]] to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL]], i64 0, i64 0
@@ -4705,7 +3531,7 @@ poly64x2x4_t test_vld4q_lane_p64(poly64_t *a, poly64x2x4_t b) {
// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[VLD4_LANE]], { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP7]]
// CHECK: [[TMP8:%.*]] = bitcast %struct.uint8x8x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP9:%.*]] = bitcast %struct.uint8x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP8]], i8* [[TMP9]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP8]], i8* align 8 [[TMP9]], i64 32, i1 false)
// CHECK: [[TMP10:%.*]] = load %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[RETVAL]], align 8
// CHECK: ret %struct.uint8x8x4_t [[TMP10]]
uint8x8x4_t test_vld4_lane_u8(uint8_t *a, uint8x8x4_t b) {
@@ -4721,7 +3547,7 @@ uint8x8x4_t test_vld4_lane_u8(uint8_t *a, uint8x8x4_t b) {
// CHECK: store [4 x <4 x i16>] [[B]].coerce, [4 x <4 x i16>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint16x4x4_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x4x4_t, %struct.uint16x4x4_t* [[__S1]], i32 0, i32 0
@@ -4749,7 +3575,7 @@ uint8x8x4_t test_vld4_lane_u8(uint8_t *a, uint8x8x4_t b) {
// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD4_LANE]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP16]]
// CHECK: [[TMP17:%.*]] = bitcast %struct.uint16x4x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP18:%.*]] = bitcast %struct.uint16x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP17]], i8* [[TMP18]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP17]], i8* align 8 [[TMP18]], i64 32, i1 false)
// CHECK: [[TMP19:%.*]] = load %struct.uint16x4x4_t, %struct.uint16x4x4_t* [[RETVAL]], align 8
// CHECK: ret %struct.uint16x4x4_t [[TMP19]]
uint16x4x4_t test_vld4_lane_u16(uint16_t *a, uint16x4x4_t b) {
@@ -4765,7 +3591,7 @@ uint16x4x4_t test_vld4_lane_u16(uint16_t *a, uint16x4x4_t b) {
// CHECK: store [4 x <2 x i32>] [[B]].coerce, [4 x <2 x i32>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint32x2x4_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x2x4_t, %struct.uint32x2x4_t* [[__S1]], i32 0, i32 0
@@ -4793,7 +3619,7 @@ uint16x4x4_t test_vld4_lane_u16(uint16_t *a, uint16x4x4_t b) {
// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[VLD4_LANE]], { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP16]]
// CHECK: [[TMP17:%.*]] = bitcast %struct.uint32x2x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP18:%.*]] = bitcast %struct.uint32x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP17]], i8* [[TMP18]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP17]], i8* align 8 [[TMP18]], i64 32, i1 false)
// CHECK: [[TMP19:%.*]] = load %struct.uint32x2x4_t, %struct.uint32x2x4_t* [[RETVAL]], align 8
// CHECK: ret %struct.uint32x2x4_t [[TMP19]]
uint32x2x4_t test_vld4_lane_u32(uint32_t *a, uint32x2x4_t b) {
@@ -4809,7 +3635,7 @@ uint32x2x4_t test_vld4_lane_u32(uint32_t *a, uint32x2x4_t b) {
// CHECK: store [4 x <1 x i64>] [[B]].coerce, [4 x <1 x i64>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x1x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint64x1x4_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x1x4_t, %struct.uint64x1x4_t* [[__S1]], i32 0, i32 0
@@ -4837,7 +3663,7 @@ uint32x2x4_t test_vld4_lane_u32(uint32_t *a, uint32x2x4_t b) {
// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } [[VLD4_LANE]], { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP16]]
// CHECK: [[TMP17:%.*]] = bitcast %struct.uint64x1x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP18:%.*]] = bitcast %struct.uint64x1x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP17]], i8* [[TMP18]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP17]], i8* align 8 [[TMP18]], i64 32, i1 false)
// CHECK: [[TMP19:%.*]] = load %struct.uint64x1x4_t, %struct.uint64x1x4_t* [[RETVAL]], align 8
// CHECK: ret %struct.uint64x1x4_t [[TMP19]]
uint64x1x4_t test_vld4_lane_u64(uint64_t *a, uint64x1x4_t b) {
@@ -4853,7 +3679,7 @@ uint64x1x4_t test_vld4_lane_u64(uint64_t *a, uint64x1x4_t b) {
// CHECK: store [4 x <8 x i8>] [[B]].coerce, [4 x <8 x i8>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x8x4_t* [[__RET]] to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x8x4_t, %struct.int8x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL]], i64 0, i64 0
@@ -4872,7 +3698,7 @@ uint64x1x4_t test_vld4_lane_u64(uint64_t *a, uint64x1x4_t b) {
// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[VLD4_LANE]], { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP7]]
// CHECK: [[TMP8:%.*]] = bitcast %struct.int8x8x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP9:%.*]] = bitcast %struct.int8x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP8]], i8* [[TMP9]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP8]], i8* align 8 [[TMP9]], i64 32, i1 false)
// CHECK: [[TMP10:%.*]] = load %struct.int8x8x4_t, %struct.int8x8x4_t* [[RETVAL]], align 8
// CHECK: ret %struct.int8x8x4_t [[TMP10]]
int8x8x4_t test_vld4_lane_s8(int8_t *a, int8x8x4_t b) {
@@ -4888,7 +3714,7 @@ int8x8x4_t test_vld4_lane_s8(int8_t *a, int8x8x4_t b) {
// CHECK: store [4 x <4 x i16>] [[B]].coerce, [4 x <4 x i16>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.int16x4x4_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x4x4_t, %struct.int16x4x4_t* [[__S1]], i32 0, i32 0
@@ -4916,7 +3742,7 @@ int8x8x4_t test_vld4_lane_s8(int8_t *a, int8x8x4_t b) {
// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD4_LANE]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP16]]
// CHECK: [[TMP17:%.*]] = bitcast %struct.int16x4x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP18:%.*]] = bitcast %struct.int16x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP17]], i8* [[TMP18]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP17]], i8* align 8 [[TMP18]], i64 32, i1 false)
// CHECK: [[TMP19:%.*]] = load %struct.int16x4x4_t, %struct.int16x4x4_t* [[RETVAL]], align 8
// CHECK: ret %struct.int16x4x4_t [[TMP19]]
int16x4x4_t test_vld4_lane_s16(int16_t *a, int16x4x4_t b) {
@@ -4932,7 +3758,7 @@ int16x4x4_t test_vld4_lane_s16(int16_t *a, int16x4x4_t b) {
// CHECK: store [4 x <2 x i32>] [[B]].coerce, [4 x <2 x i32>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.int32x2x4_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x2x4_t, %struct.int32x2x4_t* [[__S1]], i32 0, i32 0
@@ -4960,7 +3786,7 @@ int16x4x4_t test_vld4_lane_s16(int16_t *a, int16x4x4_t b) {
// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[VLD4_LANE]], { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP16]]
// CHECK: [[TMP17:%.*]] = bitcast %struct.int32x2x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP18:%.*]] = bitcast %struct.int32x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP17]], i8* [[TMP18]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP17]], i8* align 8 [[TMP18]], i64 32, i1 false)
// CHECK: [[TMP19:%.*]] = load %struct.int32x2x4_t, %struct.int32x2x4_t* [[RETVAL]], align 8
// CHECK: ret %struct.int32x2x4_t [[TMP19]]
int32x2x4_t test_vld4_lane_s32(int32_t *a, int32x2x4_t b) {
@@ -4976,7 +3802,7 @@ int32x2x4_t test_vld4_lane_s32(int32_t *a, int32x2x4_t b) {
// CHECK: store [4 x <1 x i64>] [[B]].coerce, [4 x <1 x i64>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x1x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.int64x1x4_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x1x4_t, %struct.int64x1x4_t* [[__S1]], i32 0, i32 0
@@ -5004,7 +3830,7 @@ int32x2x4_t test_vld4_lane_s32(int32_t *a, int32x2x4_t b) {
// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } [[VLD4_LANE]], { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP16]]
// CHECK: [[TMP17:%.*]] = bitcast %struct.int64x1x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP18:%.*]] = bitcast %struct.int64x1x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP17]], i8* [[TMP18]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP17]], i8* align 8 [[TMP18]], i64 32, i1 false)
// CHECK: [[TMP19:%.*]] = load %struct.int64x1x4_t, %struct.int64x1x4_t* [[RETVAL]], align 8
// CHECK: ret %struct.int64x1x4_t [[TMP19]]
int64x1x4_t test_vld4_lane_s64(int64_t *a, int64x1x4_t b) {
@@ -5020,7 +3846,7 @@ int64x1x4_t test_vld4_lane_s64(int64_t *a, int64x1x4_t b) {
// CHECK: store [4 x <4 x half>] [[B]].coerce, [4 x <4 x half>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.float16x4x4_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x4x4_t, %struct.float16x4x4_t* [[__S1]], i32 0, i32 0
@@ -5048,7 +3874,7 @@ int64x1x4_t test_vld4_lane_s64(int64_t *a, int64x1x4_t b) {
// CHECK: store { <4 x half>, <4 x half>, <4 x half>, <4 x half> } [[VLD4_LANE]], { <4 x half>, <4 x half>, <4 x half>, <4 x half> }* [[TMP16]]
// CHECK: [[TMP17:%.*]] = bitcast %struct.float16x4x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP18:%.*]] = bitcast %struct.float16x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP17]], i8* [[TMP18]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP17]], i8* align 8 [[TMP18]], i64 32, i1 false)
// CHECK: [[TMP19:%.*]] = load %struct.float16x4x4_t, %struct.float16x4x4_t* [[RETVAL]], align 8
// CHECK: ret %struct.float16x4x4_t [[TMP19]]
float16x4x4_t test_vld4_lane_f16(float16_t *a, float16x4x4_t b) {
@@ -5064,7 +3890,7 @@ float16x4x4_t test_vld4_lane_f16(float16_t *a, float16x4x4_t b) {
// CHECK: store [4 x <2 x float>] [[B]].coerce, [4 x <2 x float>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.float32x2x4_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x2x4_t, %struct.float32x2x4_t* [[__S1]], i32 0, i32 0
@@ -5092,7 +3918,7 @@ float16x4x4_t test_vld4_lane_f16(float16_t *a, float16x4x4_t b) {
// CHECK: store { <2 x float>, <2 x float>, <2 x float>, <2 x float> } [[VLD4_LANE]], { <2 x float>, <2 x float>, <2 x float>, <2 x float> }* [[TMP16]]
// CHECK: [[TMP17:%.*]] = bitcast %struct.float32x2x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP18:%.*]] = bitcast %struct.float32x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP17]], i8* [[TMP18]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP17]], i8* align 8 [[TMP18]], i64 32, i1 false)
// CHECK: [[TMP19:%.*]] = load %struct.float32x2x4_t, %struct.float32x2x4_t* [[RETVAL]], align 8
// CHECK: ret %struct.float32x2x4_t [[TMP19]]
float32x2x4_t test_vld4_lane_f32(float32_t *a, float32x2x4_t b) {
@@ -5108,7 +3934,7 @@ float32x2x4_t test_vld4_lane_f32(float32_t *a, float32x2x4_t b) {
// CHECK: store [4 x <1 x double>] [[B]].coerce, [4 x <1 x double>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x1x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float64x1x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.float64x1x4_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast double* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float64x1x4_t, %struct.float64x1x4_t* [[__S1]], i32 0, i32 0
@@ -5136,7 +3962,7 @@ float32x2x4_t test_vld4_lane_f32(float32_t *a, float32x2x4_t b) {
// CHECK: store { <1 x double>, <1 x double>, <1 x double>, <1 x double> } [[VLD4_LANE]], { <1 x double>, <1 x double>, <1 x double>, <1 x double> }* [[TMP16]]
// CHECK: [[TMP17:%.*]] = bitcast %struct.float64x1x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP18:%.*]] = bitcast %struct.float64x1x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP17]], i8* [[TMP18]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP17]], i8* align 8 [[TMP18]], i64 32, i1 false)
// CHECK: [[TMP19:%.*]] = load %struct.float64x1x4_t, %struct.float64x1x4_t* [[RETVAL]], align 8
// CHECK: ret %struct.float64x1x4_t [[TMP19]]
float64x1x4_t test_vld4_lane_f64(float64_t *a, float64x1x4_t b) {
@@ -5152,7 +3978,7 @@ float64x1x4_t test_vld4_lane_f64(float64_t *a, float64x1x4_t b) {
// CHECK: store [4 x <8 x i8>] [[B]].coerce, [4 x <8 x i8>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x8x4_t* [[__RET]] to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL]], i64 0, i64 0
@@ -5171,7 +3997,7 @@ float64x1x4_t test_vld4_lane_f64(float64_t *a, float64x1x4_t b) {
// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[VLD4_LANE]], { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP7]]
// CHECK: [[TMP8:%.*]] = bitcast %struct.poly8x8x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP9:%.*]] = bitcast %struct.poly8x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP8]], i8* [[TMP9]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP8]], i8* align 8 [[TMP9]], i64 32, i1 false)
// CHECK: [[TMP10:%.*]] = load %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[RETVAL]], align 8
// CHECK: ret %struct.poly8x8x4_t [[TMP10]]
poly8x8x4_t test_vld4_lane_p8(poly8_t *a, poly8x8x4_t b) {
@@ -5187,7 +4013,7 @@ poly8x8x4_t test_vld4_lane_p8(poly8_t *a, poly8x8x4_t b) {
// CHECK: store [4 x <4 x i16>] [[B]].coerce, [4 x <4 x i16>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly16x4x4_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x4x4_t, %struct.poly16x4x4_t* [[__S1]], i32 0, i32 0
@@ -5215,7 +4041,7 @@ poly8x8x4_t test_vld4_lane_p8(poly8_t *a, poly8x8x4_t b) {
// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD4_LANE]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP16]]
// CHECK: [[TMP17:%.*]] = bitcast %struct.poly16x4x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP18:%.*]] = bitcast %struct.poly16x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP17]], i8* [[TMP18]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP17]], i8* align 8 [[TMP18]], i64 32, i1 false)
// CHECK: [[TMP19:%.*]] = load %struct.poly16x4x4_t, %struct.poly16x4x4_t* [[RETVAL]], align 8
// CHECK: ret %struct.poly16x4x4_t [[TMP19]]
poly16x4x4_t test_vld4_lane_p16(poly16_t *a, poly16x4x4_t b) {
@@ -5231,7 +4057,7 @@ poly16x4x4_t test_vld4_lane_p16(poly16_t *a, poly16x4x4_t b) {
// CHECK: store [4 x <1 x i64>] [[B]].coerce, [4 x <1 x i64>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x1x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly64x1x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly64x1x4_t* [[__RET]] to i8*
// CHECK: [[TMP3:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly64x1x4_t, %struct.poly64x1x4_t* [[__S1]], i32 0, i32 0
@@ -5259,7 +4085,7 @@ poly16x4x4_t test_vld4_lane_p16(poly16_t *a, poly16x4x4_t b) {
// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } [[VLD4_LANE]], { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP16]]
// CHECK: [[TMP17:%.*]] = bitcast %struct.poly64x1x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP18:%.*]] = bitcast %struct.poly64x1x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP17]], i8* [[TMP18]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP17]], i8* align 8 [[TMP18]], i64 32, i1 false)
// CHECK: [[TMP19:%.*]] = load %struct.poly64x1x4_t, %struct.poly64x1x4_t* [[RETVAL]], align 8
// CHECK: ret %struct.poly64x1x4_t [[TMP19]]
poly64x1x4_t test_vld4_lane_p64(poly64_t *a, poly64x1x4_t b) {
@@ -5585,7 +4411,7 @@ void test_vst1_lane_p64(poly64_t *a, poly64x1_t b) {
// CHECK: store [2 x <16 x i8>] [[B]].coerce, [2 x <16 x i8>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x16x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
@@ -5605,7 +4431,7 @@ void test_vst2q_lane_u8(uint8_t *a, uint8x16x2_t b) {
// CHECK: store [2 x <8 x i16>] [[B]].coerce, [2 x <8 x i16>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL]], i64 0, i64 0
@@ -5630,7 +4456,7 @@ void test_vst2q_lane_u16(uint16_t *a, uint16x8x2_t b) {
// CHECK: store [2 x <4 x i32>] [[B]].coerce, [2 x <4 x i32>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL]], i64 0, i64 0
@@ -5655,7 +4481,7 @@ void test_vst2q_lane_u32(uint32_t *a, uint32x4x2_t b) {
// CHECK: store [2 x <2 x i64>] [[B]].coerce, [2 x <2 x i64>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x2x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x2x2_t, %struct.uint64x2x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x i64>], [2 x <2 x i64>]* [[VAL]], i64 0, i64 0
@@ -5680,7 +4506,7 @@ void test_vst2q_lane_u64(uint64_t *a, uint64x2x2_t b) {
// CHECK: store [2 x <16 x i8>] [[B]].coerce, [2 x <16 x i8>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x16x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x16x2_t, %struct.int8x16x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
@@ -5700,7 +4526,7 @@ void test_vst2q_lane_s8(int8_t *a, int8x16x2_t b) {
// CHECK: store [2 x <8 x i16>] [[B]].coerce, [2 x <8 x i16>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL]], i64 0, i64 0
@@ -5725,7 +4551,7 @@ void test_vst2q_lane_s16(int16_t *a, int16x8x2_t b) {
// CHECK: store [2 x <4 x i32>] [[B]].coerce, [2 x <4 x i32>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL]], i64 0, i64 0
@@ -5750,7 +4576,7 @@ void test_vst2q_lane_s32(int32_t *a, int32x4x2_t b) {
// CHECK: store [2 x <2 x i64>] [[B]].coerce, [2 x <2 x i64>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x2x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x2x2_t, %struct.int64x2x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x i64>], [2 x <2 x i64>]* [[VAL]], i64 0, i64 0
@@ -5775,7 +4601,7 @@ void test_vst2q_lane_s64(int64_t *a, int64x2x2_t b) {
// CHECK: store [2 x <8 x half>] [[B]].coerce, [2 x <8 x half>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x2_t, %struct.float16x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x half>], [2 x <8 x half>]* [[VAL]], i64 0, i64 0
@@ -5800,7 +4626,7 @@ void test_vst2q_lane_f16(float16_t *a, float16x8x2_t b) {
// CHECK: store [2 x <4 x float>] [[B]].coerce, [2 x <4 x float>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x float>], [2 x <4 x float>]* [[VAL]], i64 0, i64 0
@@ -5825,7 +4651,7 @@ void test_vst2q_lane_f32(float32_t *a, float32x4x2_t b) {
// CHECK: store [2 x <2 x double>] [[B]].coerce, [2 x <2 x double>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x2x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float64x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast double* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float64x2x2_t, %struct.float64x2x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x double>], [2 x <2 x double>]* [[VAL]], i64 0, i64 0
@@ -5850,7 +4676,7 @@ void test_vst2q_lane_f64(float64_t *a, float64x2x2_t b) {
// CHECK: store [2 x <16 x i8>] [[B]].coerce, [2 x <16 x i8>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x16x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
@@ -5870,7 +4696,7 @@ void test_vst2q_lane_p8(poly8_t *a, poly8x16x2_t b) {
// CHECK: store [2 x <8 x i16>] [[B]].coerce, [2 x <8 x i16>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL]], i64 0, i64 0
@@ -5895,7 +4721,7 @@ void test_vst2q_lane_p16(poly16_t *a, poly16x8x2_t b) {
// CHECK: store [2 x <2 x i64>] [[B]].coerce, [2 x <2 x i64>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x2x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly64x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly64x2x2_t, %struct.poly64x2x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x i64>], [2 x <2 x i64>]* [[VAL]], i64 0, i64 0
@@ -5920,7 +4746,7 @@ void test_vst2q_lane_p64(poly64_t *a, poly64x2x2_t b) {
// CHECK: store [2 x <8 x i8>] [[B]].coerce, [2 x <8 x i8>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -5940,7 +4766,7 @@ void test_vst2_lane_u8(uint8_t *a, uint8x8x2_t b) {
// CHECK: store [2 x <4 x i16>] [[B]].coerce, [2 x <4 x i16>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL]], i64 0, i64 0
@@ -5965,7 +4791,7 @@ void test_vst2_lane_u16(uint16_t *a, uint16x4x2_t b) {
// CHECK: store [2 x <2 x i32>] [[B]].coerce, [2 x <2 x i32>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x i32>], [2 x <2 x i32>]* [[VAL]], i64 0, i64 0
@@ -5990,7 +4816,7 @@ void test_vst2_lane_u32(uint32_t *a, uint32x2x2_t b) {
// CHECK: store [2 x <1 x i64>] [[B]].coerce, [2 x <1 x i64>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x1x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x1x2_t, %struct.uint64x1x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <1 x i64>], [2 x <1 x i64>]* [[VAL]], i64 0, i64 0
@@ -6015,7 +4841,7 @@ void test_vst2_lane_u64(uint64_t *a, uint64x1x2_t b) {
// CHECK: store [2 x <8 x i8>] [[B]].coerce, [2 x <8 x i8>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x8x2_t, %struct.int8x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -6035,7 +4861,7 @@ void test_vst2_lane_s8(int8_t *a, int8x8x2_t b) {
// CHECK: store [2 x <4 x i16>] [[B]].coerce, [2 x <4 x i16>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x4x2_t, %struct.int16x4x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL]], i64 0, i64 0
@@ -6060,7 +4886,7 @@ void test_vst2_lane_s16(int16_t *a, int16x4x2_t b) {
// CHECK: store [2 x <2 x i32>] [[B]].coerce, [2 x <2 x i32>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x2x2_t, %struct.int32x2x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x i32>], [2 x <2 x i32>]* [[VAL]], i64 0, i64 0
@@ -6085,7 +4911,7 @@ void test_vst2_lane_s32(int32_t *a, int32x2x2_t b) {
// CHECK: store [2 x <1 x i64>] [[B]].coerce, [2 x <1 x i64>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x1x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x1x2_t, %struct.int64x1x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <1 x i64>], [2 x <1 x i64>]* [[VAL]], i64 0, i64 0
@@ -6110,7 +4936,7 @@ void test_vst2_lane_s64(int64_t *a, int64x1x2_t b) {
// CHECK: store [2 x <4 x half>] [[B]].coerce, [2 x <4 x half>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x4x2_t, %struct.float16x4x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x half>], [2 x <4 x half>]* [[VAL]], i64 0, i64 0
@@ -6135,7 +4961,7 @@ void test_vst2_lane_f16(float16_t *a, float16x4x2_t b) {
// CHECK: store [2 x <2 x float>] [[B]].coerce, [2 x <2 x float>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x2x2_t, %struct.float32x2x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x float>], [2 x <2 x float>]* [[VAL]], i64 0, i64 0
@@ -6160,7 +4986,7 @@ void test_vst2_lane_f32(float32_t *a, float32x2x2_t b) {
// CHECK: store [2 x <1 x double>] [[B]].coerce, [2 x <1 x double>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x1x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float64x1x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast double* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float64x1x2_t, %struct.float64x1x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <1 x double>], [2 x <1 x double>]* [[VAL]], i64 0, i64 0
@@ -6185,7 +5011,7 @@ void test_vst2_lane_f64(float64_t *a, float64x1x2_t b) {
// CHECK: store [2 x <8 x i8>] [[B]].coerce, [2 x <8 x i8>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -6205,7 +5031,7 @@ void test_vst2_lane_p8(poly8_t *a, poly8x8x2_t b) {
// CHECK: store [2 x <4 x i16>] [[B]].coerce, [2 x <4 x i16>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL]], i64 0, i64 0
@@ -6230,7 +5056,7 @@ void test_vst2_lane_p16(poly16_t *a, poly16x4x2_t b) {
// CHECK: store [2 x <1 x i64>] [[B]].coerce, [2 x <1 x i64>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x1x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly64x1x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly64x1x2_t, %struct.poly64x1x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <1 x i64>], [2 x <1 x i64>]* [[VAL]], i64 0, i64 0
@@ -6255,7 +5081,7 @@ void test_vst2_lane_p64(poly64_t *a, poly64x1x2_t b) {
// CHECK: store [3 x <16 x i8>] [[B]].coerce, [3 x <16 x i8>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x16x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
@@ -6278,7 +5104,7 @@ void test_vst3q_lane_u8(uint8_t *a, uint8x16x3_t b) {
// CHECK: store [3 x <8 x i16>] [[B]].coerce, [3 x <8 x i16>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL]], i64 0, i64 0
@@ -6308,7 +5134,7 @@ void test_vst3q_lane_u16(uint16_t *a, uint16x8x3_t b) {
// CHECK: store [3 x <4 x i32>] [[B]].coerce, [3 x <4 x i32>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL]], i64 0, i64 0
@@ -6338,7 +5164,7 @@ void test_vst3q_lane_u32(uint32_t *a, uint32x4x3_t b) {
// CHECK: store [3 x <2 x i64>] [[B]].coerce, [3 x <2 x i64>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x2x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x2x3_t, %struct.uint64x2x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x i64>], [3 x <2 x i64>]* [[VAL]], i64 0, i64 0
@@ -6368,7 +5194,7 @@ void test_vst3q_lane_u64(uint64_t *a, uint64x2x3_t b) {
// CHECK: store [3 x <16 x i8>] [[B]].coerce, [3 x <16 x i8>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x16x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x16x3_t, %struct.int8x16x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
@@ -6391,7 +5217,7 @@ void test_vst3q_lane_s8(int8_t *a, int8x16x3_t b) {
// CHECK: store [3 x <8 x i16>] [[B]].coerce, [3 x <8 x i16>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL]], i64 0, i64 0
@@ -6421,7 +5247,7 @@ void test_vst3q_lane_s16(int16_t *a, int16x8x3_t b) {
// CHECK: store [3 x <4 x i32>] [[B]].coerce, [3 x <4 x i32>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL]], i64 0, i64 0
@@ -6451,7 +5277,7 @@ void test_vst3q_lane_s32(int32_t *a, int32x4x3_t b) {
// CHECK: store [3 x <2 x i64>] [[B]].coerce, [3 x <2 x i64>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x2x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x2x3_t, %struct.int64x2x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x i64>], [3 x <2 x i64>]* [[VAL]], i64 0, i64 0
@@ -6481,7 +5307,7 @@ void test_vst3q_lane_s64(int64_t *a, int64x2x3_t b) {
// CHECK: store [3 x <8 x half>] [[B]].coerce, [3 x <8 x half>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x half>], [3 x <8 x half>]* [[VAL]], i64 0, i64 0
@@ -6511,7 +5337,7 @@ void test_vst3q_lane_f16(float16_t *a, float16x8x3_t b) {
// CHECK: store [3 x <4 x float>] [[B]].coerce, [3 x <4 x float>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x float>], [3 x <4 x float>]* [[VAL]], i64 0, i64 0
@@ -6541,7 +5367,7 @@ void test_vst3q_lane_f32(float32_t *a, float32x4x3_t b) {
// CHECK: store [3 x <2 x double>] [[B]].coerce, [3 x <2 x double>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x2x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float64x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast double* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float64x2x3_t, %struct.float64x2x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x double>], [3 x <2 x double>]* [[VAL]], i64 0, i64 0
@@ -6571,7 +5397,7 @@ void test_vst3q_lane_f64(float64_t *a, float64x2x3_t b) {
// CHECK: store [3 x <16 x i8>] [[B]].coerce, [3 x <16 x i8>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x16x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
@@ -6594,7 +5420,7 @@ void test_vst3q_lane_p8(poly8_t *a, poly8x16x3_t b) {
// CHECK: store [3 x <8 x i16>] [[B]].coerce, [3 x <8 x i16>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL]], i64 0, i64 0
@@ -6624,7 +5450,7 @@ void test_vst3q_lane_p16(poly16_t *a, poly16x8x3_t b) {
// CHECK: store [3 x <2 x i64>] [[B]].coerce, [3 x <2 x i64>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x2x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly64x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly64x2x3_t, %struct.poly64x2x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x i64>], [3 x <2 x i64>]* [[VAL]], i64 0, i64 0
@@ -6654,7 +5480,7 @@ void test_vst3q_lane_p64(poly64_t *a, poly64x2x3_t b) {
// CHECK: store [3 x <8 x i8>] [[B]].coerce, [3 x <8 x i8>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x8x3_t, %struct.uint8x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -6677,7 +5503,7 @@ void test_vst3_lane_u8(uint8_t *a, uint8x8x3_t b) {
// CHECK: store [3 x <4 x i16>] [[B]].coerce, [3 x <4 x i16>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x4x3_t, %struct.uint16x4x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL]], i64 0, i64 0
@@ -6707,7 +5533,7 @@ void test_vst3_lane_u16(uint16_t *a, uint16x4x3_t b) {
// CHECK: store [3 x <2 x i32>] [[B]].coerce, [3 x <2 x i32>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x2x3_t, %struct.uint32x2x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x i32>], [3 x <2 x i32>]* [[VAL]], i64 0, i64 0
@@ -6737,7 +5563,7 @@ void test_vst3_lane_u32(uint32_t *a, uint32x2x3_t b) {
// CHECK: store [3 x <1 x i64>] [[B]].coerce, [3 x <1 x i64>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x1x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x1x3_t, %struct.uint64x1x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL]], i64 0, i64 0
@@ -6767,7 +5593,7 @@ void test_vst3_lane_u64(uint64_t *a, uint64x1x3_t b) {
// CHECK: store [3 x <8 x i8>] [[B]].coerce, [3 x <8 x i8>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x8x3_t, %struct.int8x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -6790,7 +5616,7 @@ void test_vst3_lane_s8(int8_t *a, int8x8x3_t b) {
// CHECK: store [3 x <4 x i16>] [[B]].coerce, [3 x <4 x i16>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x4x3_t, %struct.int16x4x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL]], i64 0, i64 0
@@ -6820,7 +5646,7 @@ void test_vst3_lane_s16(int16_t *a, int16x4x3_t b) {
// CHECK: store [3 x <2 x i32>] [[B]].coerce, [3 x <2 x i32>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x2x3_t, %struct.int32x2x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x i32>], [3 x <2 x i32>]* [[VAL]], i64 0, i64 0
@@ -6850,7 +5676,7 @@ void test_vst3_lane_s32(int32_t *a, int32x2x3_t b) {
// CHECK: store [3 x <1 x i64>] [[B]].coerce, [3 x <1 x i64>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x1x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x1x3_t, %struct.int64x1x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL]], i64 0, i64 0
@@ -6880,7 +5706,7 @@ void test_vst3_lane_s64(int64_t *a, int64x1x3_t b) {
// CHECK: store [3 x <4 x half>] [[B]].coerce, [3 x <4 x half>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x4x3_t, %struct.float16x4x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x half>], [3 x <4 x half>]* [[VAL]], i64 0, i64 0
@@ -6910,7 +5736,7 @@ void test_vst3_lane_f16(float16_t *a, float16x4x3_t b) {
// CHECK: store [3 x <2 x float>] [[B]].coerce, [3 x <2 x float>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x2x3_t, %struct.float32x2x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x float>], [3 x <2 x float>]* [[VAL]], i64 0, i64 0
@@ -6940,7 +5766,7 @@ void test_vst3_lane_f32(float32_t *a, float32x2x3_t b) {
// CHECK: store [3 x <1 x double>] [[B]].coerce, [3 x <1 x double>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x1x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float64x1x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast double* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float64x1x3_t, %struct.float64x1x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <1 x double>], [3 x <1 x double>]* [[VAL]], i64 0, i64 0
@@ -6970,7 +5796,7 @@ void test_vst3_lane_f64(float64_t *a, float64x1x3_t b) {
// CHECK: store [3 x <8 x i8>] [[B]].coerce, [3 x <8 x i8>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x8x3_t, %struct.poly8x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -6993,7 +5819,7 @@ void test_vst3_lane_p8(poly8_t *a, poly8x8x3_t b) {
// CHECK: store [3 x <4 x i16>] [[B]].coerce, [3 x <4 x i16>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x4x3_t, %struct.poly16x4x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL]], i64 0, i64 0
@@ -7023,7 +5849,7 @@ void test_vst3_lane_p16(poly16_t *a, poly16x4x3_t b) {
// CHECK: store [3 x <1 x i64>] [[B]].coerce, [3 x <1 x i64>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x1x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly64x1x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly64x1x3_t, %struct.poly64x1x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL]], i64 0, i64 0
@@ -7053,7 +5879,7 @@ void test_vst3_lane_p64(poly64_t *a, poly64x1x3_t b) {
// CHECK: store [4 x <16 x i8>] [[B]].coerce, [4 x <16 x i8>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x16x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
@@ -7079,7 +5905,7 @@ void test_vst4q_lane_u8(uint8_t *a, uint8x16x4_t b) {
// CHECK: store [4 x <8 x i16>] [[B]].coerce, [4 x <8 x i16>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL]], i64 0, i64 0
@@ -7114,7 +5940,7 @@ void test_vst4q_lane_u16(uint16_t *a, uint16x8x4_t b) {
// CHECK: store [4 x <4 x i32>] [[B]].coerce, [4 x <4 x i32>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL]], i64 0, i64 0
@@ -7149,7 +5975,7 @@ void test_vst4q_lane_u32(uint32_t *a, uint32x4x4_t b) {
// CHECK: store [4 x <2 x i64>] [[B]].coerce, [4 x <2 x i64>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x2x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x2x4_t, %struct.uint64x2x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL]], i64 0, i64 0
@@ -7184,7 +6010,7 @@ void test_vst4q_lane_u64(uint64_t *a, uint64x2x4_t b) {
// CHECK: store [4 x <16 x i8>] [[B]].coerce, [4 x <16 x i8>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x16x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
@@ -7210,7 +6036,7 @@ void test_vst4q_lane_s8(int8_t *a, int8x16x4_t b) {
// CHECK: store [4 x <8 x i16>] [[B]].coerce, [4 x <8 x i16>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL]], i64 0, i64 0
@@ -7245,7 +6071,7 @@ void test_vst4q_lane_s16(int16_t *a, int16x8x4_t b) {
// CHECK: store [4 x <4 x i32>] [[B]].coerce, [4 x <4 x i32>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL]], i64 0, i64 0
@@ -7280,7 +6106,7 @@ void test_vst4q_lane_s32(int32_t *a, int32x4x4_t b) {
// CHECK: store [4 x <2 x i64>] [[B]].coerce, [4 x <2 x i64>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x2x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x2x4_t, %struct.int64x2x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL]], i64 0, i64 0
@@ -7315,7 +6141,7 @@ void test_vst4q_lane_s64(int64_t *a, int64x2x4_t b) {
// CHECK: store [4 x <8 x half>] [[B]].coerce, [4 x <8 x half>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL]], i64 0, i64 0
@@ -7350,7 +6176,7 @@ void test_vst4q_lane_f16(float16_t *a, float16x8x4_t b) {
// CHECK: store [4 x <4 x float>] [[B]].coerce, [4 x <4 x float>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x float>], [4 x <4 x float>]* [[VAL]], i64 0, i64 0
@@ -7385,7 +6211,7 @@ void test_vst4q_lane_f32(float32_t *a, float32x4x4_t b) {
// CHECK: store [4 x <2 x double>] [[B]].coerce, [4 x <2 x double>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x2x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float64x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast double* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float64x2x4_t, %struct.float64x2x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x double>], [4 x <2 x double>]* [[VAL]], i64 0, i64 0
@@ -7420,7 +6246,7 @@ void test_vst4q_lane_f64(float64_t *a, float64x2x4_t b) {
// CHECK: store [4 x <16 x i8>] [[B]].coerce, [4 x <16 x i8>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x16x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
@@ -7446,7 +6272,7 @@ void test_vst4q_lane_p8(poly8_t *a, poly8x16x4_t b) {
// CHECK: store [4 x <8 x i16>] [[B]].coerce, [4 x <8 x i16>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL]], i64 0, i64 0
@@ -7481,7 +6307,7 @@ void test_vst4q_lane_p16(poly16_t *a, poly16x8x4_t b) {
// CHECK: store [4 x <2 x i64>] [[B]].coerce, [4 x <2 x i64>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x2x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly64x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly64x2x4_t, %struct.poly64x2x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL]], i64 0, i64 0
@@ -7516,7 +6342,7 @@ void test_vst4q_lane_p64(poly64_t *a, poly64x2x4_t b) {
// CHECK: store [4 x <8 x i8>] [[B]].coerce, [4 x <8 x i8>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -7542,7 +6368,7 @@ void test_vst4_lane_u8(uint8_t *a, uint8x8x4_t b) {
// CHECK: store [4 x <4 x i16>] [[B]].coerce, [4 x <4 x i16>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x4x4_t, %struct.uint16x4x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL]], i64 0, i64 0
@@ -7577,7 +6403,7 @@ void test_vst4_lane_u16(uint16_t *a, uint16x4x4_t b) {
// CHECK: store [4 x <2 x i32>] [[B]].coerce, [4 x <2 x i32>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x2x4_t, %struct.uint32x2x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL]], i64 0, i64 0
@@ -7612,7 +6438,7 @@ void test_vst4_lane_u32(uint32_t *a, uint32x2x4_t b) {
// CHECK: store [4 x <1 x i64>] [[B]].coerce, [4 x <1 x i64>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x1x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x1x4_t, %struct.uint64x1x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL]], i64 0, i64 0
@@ -7647,7 +6473,7 @@ void test_vst4_lane_u64(uint64_t *a, uint64x1x4_t b) {
// CHECK: store [4 x <8 x i8>] [[B]].coerce, [4 x <8 x i8>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x8x4_t, %struct.int8x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -7673,7 +6499,7 @@ void test_vst4_lane_s8(int8_t *a, int8x8x4_t b) {
// CHECK: store [4 x <4 x i16>] [[B]].coerce, [4 x <4 x i16>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x4x4_t, %struct.int16x4x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL]], i64 0, i64 0
@@ -7708,7 +6534,7 @@ void test_vst4_lane_s16(int16_t *a, int16x4x4_t b) {
// CHECK: store [4 x <2 x i32>] [[B]].coerce, [4 x <2 x i32>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x2x4_t, %struct.int32x2x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL]], i64 0, i64 0
@@ -7743,7 +6569,7 @@ void test_vst4_lane_s32(int32_t *a, int32x2x4_t b) {
// CHECK: store [4 x <1 x i64>] [[B]].coerce, [4 x <1 x i64>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x1x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x1x4_t, %struct.int64x1x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL]], i64 0, i64 0
@@ -7778,7 +6604,7 @@ void test_vst4_lane_s64(int64_t *a, int64x1x4_t b) {
// CHECK: store [4 x <4 x half>] [[B]].coerce, [4 x <4 x half>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x4x4_t, %struct.float16x4x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x half>], [4 x <4 x half>]* [[VAL]], i64 0, i64 0
@@ -7813,7 +6639,7 @@ void test_vst4_lane_f16(float16_t *a, float16x4x4_t b) {
// CHECK: store [4 x <2 x float>] [[B]].coerce, [4 x <2 x float>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x2x4_t, %struct.float32x2x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x float>], [4 x <2 x float>]* [[VAL]], i64 0, i64 0
@@ -7848,7 +6674,7 @@ void test_vst4_lane_f32(float32_t *a, float32x2x4_t b) {
// CHECK: store [4 x <1 x double>] [[B]].coerce, [4 x <1 x double>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x1x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.float64x1x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast double* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float64x1x4_t, %struct.float64x1x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <1 x double>], [4 x <1 x double>]* [[VAL]], i64 0, i64 0
@@ -7883,7 +6709,7 @@ void test_vst4_lane_f64(float64_t *a, float64x1x4_t b) {
// CHECK: store [4 x <8 x i8>] [[B]].coerce, [4 x <8 x i8>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL]], i64 0, i64 0
// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -7909,7 +6735,7 @@ void test_vst4_lane_p8(poly8_t *a, poly8x8x4_t b) {
// CHECK: store [4 x <4 x i16>] [[B]].coerce, [4 x <4 x i16>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x4x4_t, %struct.poly16x4x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL]], i64 0, i64 0
@@ -7944,7 +6770,7 @@ void test_vst4_lane_p16(poly16_t *a, poly16x4x4_t b) {
// CHECK: store [4 x <1 x i64>] [[B]].coerce, [4 x <1 x i64>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x1x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly64x1x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly64x1x4_t, %struct.poly64x1x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL]], i64 0, i64 0
diff --git a/test/CodeGen/aarch64-neon-misc.c b/test/CodeGen/aarch64-neon-misc.c
index 0772d4fc677d..f8ba7ee7121b 100644
--- a/test/CodeGen/aarch64-neon-misc.c
+++ b/test/CodeGen/aarch64-neon-misc.c
@@ -2253,22 +2253,6 @@ float64x2_t test_vcvt_high_f64_f32(float32x4_t a) {
return vcvt_high_f64_f32(a);
}
-// CHECK-LABEL: @test_vrndn_f32(
-// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VRNDN1_I:%.*]] = call <2 x float> @llvm.aarch64.neon.frintn.v2f32(<2 x float> %a)
-// CHECK: ret <2 x float> [[VRNDN1_I]]
-float32x2_t test_vrndn_f32(float32x2_t a) {
- return vrndn_f32(a);
-}
-
-// CHECK-LABEL: @test_vrndnq_f32(
-// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VRNDN1_I:%.*]] = call <4 x float> @llvm.aarch64.neon.frintn.v4f32(<4 x float> %a)
-// CHECK: ret <4 x float> [[VRNDN1_I]]
-float32x4_t test_vrndnq_f32(float32x4_t a) {
- return vrndnq_f32(a);
-}
-
// CHECK-LABEL: @test_vrndnq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: [[VRNDN1_I:%.*]] = call <2 x double> @llvm.aarch64.neon.frintn.v2f64(<2 x double> %a)
@@ -2277,22 +2261,6 @@ float64x2_t test_vrndnq_f64(float64x2_t a) {
return vrndnq_f64(a);
}
-// CHECK-LABEL: @test_vrnda_f32(
-// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VRNDA1_I:%.*]] = call <2 x float> @llvm.round.v2f32(<2 x float> %a)
-// CHECK: ret <2 x float> [[VRNDA1_I]]
-float32x2_t test_vrnda_f32(float32x2_t a) {
- return vrnda_f32(a);
-}
-
-// CHECK-LABEL: @test_vrndaq_f32(
-// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VRNDA1_I:%.*]] = call <4 x float> @llvm.round.v4f32(<4 x float> %a)
-// CHECK: ret <4 x float> [[VRNDA1_I]]
-float32x4_t test_vrndaq_f32(float32x4_t a) {
- return vrndaq_f32(a);
-}
-
// CHECK-LABEL: @test_vrndaq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: [[VRNDA1_I:%.*]] = call <2 x double> @llvm.round.v2f64(<2 x double> %a)
@@ -2301,22 +2269,6 @@ float64x2_t test_vrndaq_f64(float64x2_t a) {
return vrndaq_f64(a);
}
-// CHECK-LABEL: @test_vrndp_f32(
-// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VRNDP1_I:%.*]] = call <2 x float> @llvm.ceil.v2f32(<2 x float> %a)
-// CHECK: ret <2 x float> [[VRNDP1_I]]
-float32x2_t test_vrndp_f32(float32x2_t a) {
- return vrndp_f32(a);
-}
-
-// CHECK-LABEL: @test_vrndpq_f32(
-// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VRNDP1_I:%.*]] = call <4 x float> @llvm.ceil.v4f32(<4 x float> %a)
-// CHECK: ret <4 x float> [[VRNDP1_I]]
-float32x4_t test_vrndpq_f32(float32x4_t a) {
- return vrndpq_f32(a);
-}
-
// CHECK-LABEL: @test_vrndpq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: [[VRNDP1_I:%.*]] = call <2 x double> @llvm.ceil.v2f64(<2 x double> %a)
@@ -2325,22 +2277,6 @@ float64x2_t test_vrndpq_f64(float64x2_t a) {
return vrndpq_f64(a);
}
-// CHECK-LABEL: @test_vrndm_f32(
-// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VRNDM1_I:%.*]] = call <2 x float> @llvm.floor.v2f32(<2 x float> %a)
-// CHECK: ret <2 x float> [[VRNDM1_I]]
-float32x2_t test_vrndm_f32(float32x2_t a) {
- return vrndm_f32(a);
-}
-
-// CHECK-LABEL: @test_vrndmq_f32(
-// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VRNDM1_I:%.*]] = call <4 x float> @llvm.floor.v4f32(<4 x float> %a)
-// CHECK: ret <4 x float> [[VRNDM1_I]]
-float32x4_t test_vrndmq_f32(float32x4_t a) {
- return vrndmq_f32(a);
-}
-
// CHECK-LABEL: @test_vrndmq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: [[VRNDM1_I:%.*]] = call <2 x double> @llvm.floor.v2f64(<2 x double> %a)
@@ -2349,22 +2285,6 @@ float64x2_t test_vrndmq_f64(float64x2_t a) {
return vrndmq_f64(a);
}
-// CHECK-LABEL: @test_vrndx_f32(
-// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VRNDX1_I:%.*]] = call <2 x float> @llvm.rint.v2f32(<2 x float> %a)
-// CHECK: ret <2 x float> [[VRNDX1_I]]
-float32x2_t test_vrndx_f32(float32x2_t a) {
- return vrndx_f32(a);
-}
-
-// CHECK-LABEL: @test_vrndxq_f32(
-// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VRNDX1_I:%.*]] = call <4 x float> @llvm.rint.v4f32(<4 x float> %a)
-// CHECK: ret <4 x float> [[VRNDX1_I]]
-float32x4_t test_vrndxq_f32(float32x4_t a) {
- return vrndxq_f32(a);
-}
-
// CHECK-LABEL: @test_vrndxq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: [[VRNDX1_I:%.*]] = call <2 x double> @llvm.rint.v2f64(<2 x double> %a)
@@ -2373,22 +2293,6 @@ float64x2_t test_vrndxq_f64(float64x2_t a) {
return vrndxq_f64(a);
}
-// CHECK-LABEL: @test_vrnd_f32(
-// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VRNDZ1_I:%.*]] = call <2 x float> @llvm.trunc.v2f32(<2 x float> %a)
-// CHECK: ret <2 x float> [[VRNDZ1_I]]
-float32x2_t test_vrnd_f32(float32x2_t a) {
- return vrnd_f32(a);
-}
-
-// CHECK-LABEL: @test_vrndq_f32(
-// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VRNDZ1_I:%.*]] = call <4 x float> @llvm.trunc.v4f32(<4 x float> %a)
-// CHECK: ret <4 x float> [[VRNDZ1_I]]
-float32x4_t test_vrndq_f32(float32x4_t a) {
- return vrndq_f32(a);
-}
-
// CHECK-LABEL: @test_vrndq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: [[VRNDZ1_I:%.*]] = call <2 x double> @llvm.trunc.v2f64(<2 x double> %a)
@@ -2397,22 +2301,6 @@ float64x2_t test_vrndq_f64(float64x2_t a) {
return vrndq_f64(a);
}
-// CHECK-LABEL: @test_vrndi_f32(
-// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VRNDI1_I:%.*]] = call <2 x float> @llvm.nearbyint.v2f32(<2 x float> %a)
-// CHECK: ret <2 x float> [[VRNDI1_I]]
-float32x2_t test_vrndi_f32(float32x2_t a) {
- return vrndi_f32(a);
-}
-
-// CHECK-LABEL: @test_vrndiq_f32(
-// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VRNDI1_I:%.*]] = call <4 x float> @llvm.nearbyint.v4f32(<4 x float> %a)
-// CHECK: ret <4 x float> [[VRNDI1_I]]
-float32x4_t test_vrndiq_f32(float32x4_t a) {
- return vrndiq_f32(a);
-}
-
// CHECK-LABEL: @test_vrndiq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: [[VRNDI1_I:%.*]] = call <2 x double> @llvm.nearbyint.v2f64(<2 x double> %a)
diff --git a/test/CodeGen/aarch64-neon-perm.c b/test/CodeGen/aarch64-neon-perm.c
index 471017a99bbd..c5d5ab18070c 100644
--- a/test/CodeGen/aarch64-neon-perm.c
+++ b/test/CodeGen/aarch64-neon-perm.c
@@ -888,18 +888,14 @@ poly16x8_t test_vtrn2q_p16(poly16x8_t a, poly16x8_t b) {
// CHECK-LABEL: @test_vuzp_s8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int8x8x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int8x8x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
// CHECK: store <8 x i8> [[VUZP_I]], <8 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
// CHECK: store <8 x i8> [[VUZP1_I]], <8 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 16, i32 8, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.int8x8x2_t, %struct.int8x8x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.int8x8x2_t, %struct.int8x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.int8x8x2_t [[TMP5]], 0
@@ -912,9 +908,8 @@ int8x8x2_t test_vuzp_s8(int8x8_t a, int8x8_t b) {
// CHECK-LABEL: @test_vuzp_s16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int16x4x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int16x4x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
@@ -923,9 +918,6 @@ int8x8x2_t test_vuzp_s8(int8x8_t a, int8x8_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
// CHECK: store <4 x i16> [[VUZP1_I]], <4 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 16, i32 8, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.int16x4x2_t, %struct.int16x4x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.int16x4x2_t, %struct.int16x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.int16x4x2_t [[TMP7]], 0
@@ -938,9 +930,8 @@ int16x4x2_t test_vuzp_s16(int16x4_t a, int16x4_t b) {
// CHECK-LABEL: @test_vuzp_s32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int32x2x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int32x2x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x i32>*
@@ -949,9 +940,6 @@ int16x4x2_t test_vuzp_s16(int16x4_t a, int16x4_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 1, i32 3>
// CHECK: store <2 x i32> [[VUZP1_I]], <2 x i32>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x2x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 16, i32 8, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.int32x2x2_t, %struct.int32x2x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.int32x2x2_t, %struct.int32x2x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.int32x2x2_t [[TMP7]], 0
@@ -964,18 +952,14 @@ int32x2x2_t test_vuzp_s32(int32x2_t a, int32x2_t b) {
// CHECK-LABEL: @test_vuzp_u8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint8x8x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint8x8x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
// CHECK: store <8 x i8> [[VUZP_I]], <8 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
// CHECK: store <8 x i8> [[VUZP1_I]], <8 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 16, i32 8, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.uint8x8x2_t [[TMP5]], 0
@@ -988,9 +972,8 @@ uint8x8x2_t test_vuzp_u8(uint8x8_t a, uint8x8_t b) {
// CHECK-LABEL: @test_vuzp_u16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint16x4x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint16x4x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
@@ -999,9 +982,6 @@ uint8x8x2_t test_vuzp_u8(uint8x8_t a, uint8x8_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
// CHECK: store <4 x i16> [[VUZP1_I]], <4 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 16, i32 8, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.uint16x4x2_t [[TMP7]], 0
@@ -1014,9 +994,8 @@ uint16x4x2_t test_vuzp_u16(uint16x4_t a, uint16x4_t b) {
// CHECK-LABEL: @test_vuzp_u32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint32x2x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint32x2x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x i32>*
@@ -1025,9 +1004,6 @@ uint16x4x2_t test_vuzp_u16(uint16x4_t a, uint16x4_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 1, i32 3>
// CHECK: store <2 x i32> [[VUZP1_I]], <2 x i32>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x2x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 16, i32 8, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.uint32x2x2_t [[TMP7]], 0
@@ -1040,9 +1016,8 @@ uint32x2x2_t test_vuzp_u32(uint32x2_t a, uint32x2_t b) {
// CHECK-LABEL: @test_vuzp_f32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.float32x2x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.float32x2x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x float> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x float>*
@@ -1051,9 +1026,6 @@ uint32x2x2_t test_vuzp_u32(uint32x2_t a, uint32x2_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x float>, <2 x float>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <2 x float> %a, <2 x float> %b, <2 x i32> <i32 1, i32 3>
// CHECK: store <2 x float> [[VUZP1_I]], <2 x float>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x2x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.float32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 16, i32 8, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.float32x2x2_t, %struct.float32x2x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.float32x2x2_t, %struct.float32x2x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.float32x2x2_t [[TMP7]], 0
@@ -1066,18 +1038,14 @@ float32x2x2_t test_vuzp_f32(float32x2_t a, float32x2_t b) {
// CHECK-LABEL: @test_vuzp_p8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.poly8x8x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly8x8x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
// CHECK: store <8 x i8> [[VUZP_I]], <8 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
// CHECK: store <8 x i8> [[VUZP1_I]], <8 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 16, i32 8, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.poly8x8x2_t [[TMP5]], 0
@@ -1090,9 +1058,8 @@ poly8x8x2_t test_vuzp_p8(poly8x8_t a, poly8x8_t b) {
// CHECK-LABEL: @test_vuzp_p16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.poly16x4x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly16x4x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
@@ -1101,9 +1068,6 @@ poly8x8x2_t test_vuzp_p8(poly8x8_t a, poly8x8_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
// CHECK: store <4 x i16> [[VUZP1_I]], <4 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 16, i32 8, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.poly16x4x2_t [[TMP7]], 0
@@ -1116,18 +1080,14 @@ poly16x4x2_t test_vuzp_p16(poly16x4_t a, poly16x4_t b) {
// CHECK-LABEL: @test_vuzpq_s8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int8x16x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int8x16x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <16 x i8>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14, i32 16, i32 18, i32 20, i32 22, i32 24, i32 26, i32 28, i32 30>
// CHECK: store <16 x i8> [[VUZP_I]], <16 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15, i32 17, i32 19, i32 21, i32 23, i32 25, i32 27, i32 29, i32 31>
// CHECK: store <16 x i8> [[VUZP1_I]], <16 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int8x16x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 32, i32 16, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.int8x16x2_t, %struct.int8x16x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.int8x16x2_t, %struct.int8x16x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.int8x16x2_t [[TMP5]], 0
@@ -1140,9 +1100,8 @@ int8x16x2_t test_vuzpq_s8(int8x16_t a, int8x16_t b) {
// CHECK-LABEL: @test_vuzpq_s16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int16x8x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int16x8x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
@@ -1151,9 +1110,6 @@ int8x16x2_t test_vuzpq_s8(int8x16_t a, int8x16_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
// CHECK: store <8 x i16> [[VUZP1_I]], <8 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 32, i32 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.int16x8x2_t, %struct.int16x8x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.int16x8x2_t [[TMP7]], 0
@@ -1166,9 +1122,8 @@ int16x8x2_t test_vuzpq_s16(int16x8_t a, int16x8_t b) {
// CHECK-LABEL: @test_vuzpq_s32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int32x4x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int32x4x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x4x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i32>*
@@ -1177,9 +1132,6 @@ int16x8x2_t test_vuzpq_s16(int16x8_t a, int16x8_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
// CHECK: store <4 x i32> [[VUZP1_I]], <4 x i32>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 32, i32 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.int32x4x2_t, %struct.int32x4x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.int32x4x2_t [[TMP7]], 0
@@ -1192,18 +1144,14 @@ int32x4x2_t test_vuzpq_s32(int32x4_t a, int32x4_t b) {
// CHECK-LABEL: @test_vuzpq_u8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint8x16x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint8x16x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <16 x i8>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14, i32 16, i32 18, i32 20, i32 22, i32 24, i32 26, i32 28, i32 30>
// CHECK: store <16 x i8> [[VUZP_I]], <16 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15, i32 17, i32 19, i32 21, i32 23, i32 25, i32 27, i32 29, i32 31>
// CHECK: store <16 x i8> [[VUZP1_I]], <16 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 32, i32 16, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.uint8x16x2_t [[TMP5]], 0
@@ -1216,9 +1164,8 @@ uint8x16x2_t test_vuzpq_u8(uint8x16_t a, uint8x16_t b) {
// CHECK-LABEL: @test_vuzpq_u16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint16x8x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint16x8x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
@@ -1227,9 +1174,6 @@ uint8x16x2_t test_vuzpq_u8(uint8x16_t a, uint8x16_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
// CHECK: store <8 x i16> [[VUZP1_I]], <8 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 32, i32 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.uint16x8x2_t [[TMP7]], 0
@@ -1242,9 +1186,8 @@ uint16x8x2_t test_vuzpq_u16(uint16x8_t a, uint16x8_t b) {
// CHECK-LABEL: @test_vuzpq_u32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint32x4x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint32x4x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x4x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i32>*
@@ -1253,9 +1196,6 @@ uint16x8x2_t test_vuzpq_u16(uint16x8_t a, uint16x8_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
// CHECK: store <4 x i32> [[VUZP1_I]], <4 x i32>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 32, i32 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.uint32x4x2_t [[TMP7]], 0
@@ -1268,9 +1208,8 @@ uint32x4x2_t test_vuzpq_u32(uint32x4_t a, uint32x4_t b) {
// CHECK-LABEL: @test_vuzpq_f32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.float32x4x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.float32x4x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x4x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x float> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x float>*
@@ -1279,9 +1218,6 @@ uint32x4x2_t test_vuzpq_u32(uint32x4_t a, uint32x4_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x float>, <4 x float>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
// CHECK: store <4 x float> [[VUZP1_I]], <4 x float>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.float32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 32, i32 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.float32x4x2_t, %struct.float32x4x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.float32x4x2_t [[TMP7]], 0
@@ -1294,18 +1230,14 @@ float32x4x2_t test_vuzpq_f32(float32x4_t a, float32x4_t b) {
// CHECK-LABEL: @test_vuzpq_p8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.poly8x16x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly8x16x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <16 x i8>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14, i32 16, i32 18, i32 20, i32 22, i32 24, i32 26, i32 28, i32 30>
// CHECK: store <16 x i8> [[VUZP_I]], <16 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15, i32 17, i32 19, i32 21, i32 23, i32 25, i32 27, i32 29, i32 31>
// CHECK: store <16 x i8> [[VUZP1_I]], <16 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 32, i32 16, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.poly8x16x2_t [[TMP5]], 0
@@ -1318,9 +1250,8 @@ poly8x16x2_t test_vuzpq_p8(poly8x16_t a, poly8x16_t b) {
// CHECK-LABEL: @test_vuzpq_p16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.poly16x8x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly16x8x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
@@ -1329,9 +1260,6 @@ poly8x16x2_t test_vuzpq_p8(poly8x16_t a, poly8x16_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
// CHECK: store <8 x i16> [[VUZP1_I]], <8 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 32, i32 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.poly16x8x2_t [[TMP7]], 0
@@ -1344,18 +1272,14 @@ poly16x8x2_t test_vuzpq_p16(poly16x8_t a, poly16x8_t b) {
// CHECK-LABEL: @test_vzip_s8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int8x8x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int8x8x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
// CHECK: store <8 x i8> [[VZIP_I]], <8 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
// CHECK: store <8 x i8> [[VZIP1_I]], <8 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 16, i32 8, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.int8x8x2_t, %struct.int8x8x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.int8x8x2_t, %struct.int8x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.int8x8x2_t [[TMP5]], 0
@@ -1368,9 +1292,8 @@ int8x8x2_t test_vzip_s8(int8x8_t a, int8x8_t b) {
// CHECK-LABEL: @test_vzip_s16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int16x4x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int16x4x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
@@ -1379,9 +1302,6 @@ int8x8x2_t test_vzip_s8(int8x8_t a, int8x8_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
// CHECK: store <4 x i16> [[VZIP1_I]], <4 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 16, i32 8, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.int16x4x2_t, %struct.int16x4x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.int16x4x2_t, %struct.int16x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.int16x4x2_t [[TMP7]], 0
@@ -1394,9 +1314,8 @@ int16x4x2_t test_vzip_s16(int16x4_t a, int16x4_t b) {
// CHECK-LABEL: @test_vzip_s32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int32x2x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int32x2x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x i32>*
@@ -1405,9 +1324,6 @@ int16x4x2_t test_vzip_s16(int16x4_t a, int16x4_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 1, i32 3>
// CHECK: store <2 x i32> [[VZIP1_I]], <2 x i32>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x2x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 16, i32 8, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.int32x2x2_t, %struct.int32x2x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.int32x2x2_t, %struct.int32x2x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.int32x2x2_t [[TMP7]], 0
@@ -1420,18 +1336,14 @@ int32x2x2_t test_vzip_s32(int32x2_t a, int32x2_t b) {
// CHECK-LABEL: @test_vzip_u8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint8x8x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint8x8x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
// CHECK: store <8 x i8> [[VZIP_I]], <8 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
// CHECK: store <8 x i8> [[VZIP1_I]], <8 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 16, i32 8, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.uint8x8x2_t [[TMP5]], 0
@@ -1444,9 +1356,8 @@ uint8x8x2_t test_vzip_u8(uint8x8_t a, uint8x8_t b) {
// CHECK-LABEL: @test_vzip_u16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint16x4x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint16x4x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
@@ -1455,9 +1366,6 @@ uint8x8x2_t test_vzip_u8(uint8x8_t a, uint8x8_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
// CHECK: store <4 x i16> [[VZIP1_I]], <4 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 16, i32 8, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.uint16x4x2_t [[TMP7]], 0
@@ -1470,9 +1378,8 @@ uint16x4x2_t test_vzip_u16(uint16x4_t a, uint16x4_t b) {
// CHECK-LABEL: @test_vzip_u32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint32x2x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint32x2x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x i32>*
@@ -1481,9 +1388,6 @@ uint16x4x2_t test_vzip_u16(uint16x4_t a, uint16x4_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 1, i32 3>
// CHECK: store <2 x i32> [[VZIP1_I]], <2 x i32>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x2x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 16, i32 8, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.uint32x2x2_t [[TMP7]], 0
@@ -1496,9 +1400,8 @@ uint32x2x2_t test_vzip_u32(uint32x2_t a, uint32x2_t b) {
// CHECK-LABEL: @test_vzip_f32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.float32x2x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.float32x2x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x float> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x float>*
@@ -1507,9 +1410,6 @@ uint32x2x2_t test_vzip_u32(uint32x2_t a, uint32x2_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x float>, <2 x float>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <2 x float> %a, <2 x float> %b, <2 x i32> <i32 1, i32 3>
// CHECK: store <2 x float> [[VZIP1_I]], <2 x float>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x2x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.float32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 16, i32 8, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.float32x2x2_t, %struct.float32x2x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.float32x2x2_t, %struct.float32x2x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.float32x2x2_t [[TMP7]], 0
@@ -1522,18 +1422,14 @@ float32x2x2_t test_vzip_f32(float32x2_t a, float32x2_t b) {
// CHECK-LABEL: @test_vzip_p8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.poly8x8x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly8x8x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
// CHECK: store <8 x i8> [[VZIP_I]], <8 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
// CHECK: store <8 x i8> [[VZIP1_I]], <8 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 16, i32 8, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.poly8x8x2_t [[TMP5]], 0
@@ -1546,9 +1442,8 @@ poly8x8x2_t test_vzip_p8(poly8x8_t a, poly8x8_t b) {
// CHECK-LABEL: @test_vzip_p16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.poly16x4x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly16x4x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
@@ -1557,9 +1452,6 @@ poly8x8x2_t test_vzip_p8(poly8x8_t a, poly8x8_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
// CHECK: store <4 x i16> [[VZIP1_I]], <4 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 16, i32 8, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.poly16x4x2_t [[TMP7]], 0
@@ -1572,18 +1464,14 @@ poly16x4x2_t test_vzip_p16(poly16x4_t a, poly16x4_t b) {
// CHECK-LABEL: @test_vzipq_s8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int8x16x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int8x16x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <16 x i8>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 0, i32 16, i32 1, i32 17, i32 2, i32 18, i32 3, i32 19, i32 4, i32 20, i32 5, i32 21, i32 6, i32 22, i32 7, i32 23>
// CHECK: store <16 x i8> [[VZIP_I]], <16 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 8, i32 24, i32 9, i32 25, i32 10, i32 26, i32 11, i32 27, i32 12, i32 28, i32 13, i32 29, i32 14, i32 30, i32 15, i32 31>
// CHECK: store <16 x i8> [[VZIP1_I]], <16 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int8x16x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 32, i32 16, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.int8x16x2_t, %struct.int8x16x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.int8x16x2_t, %struct.int8x16x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.int8x16x2_t [[TMP5]], 0
@@ -1596,9 +1484,8 @@ int8x16x2_t test_vzipq_s8(int8x16_t a, int8x16_t b) {
// CHECK-LABEL: @test_vzipq_s16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int16x8x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int16x8x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
@@ -1607,9 +1494,6 @@ int8x16x2_t test_vzipq_s8(int8x16_t a, int8x16_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
// CHECK: store <8 x i16> [[VZIP1_I]], <8 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 32, i32 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.int16x8x2_t, %struct.int16x8x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.int16x8x2_t [[TMP7]], 0
@@ -1622,9 +1506,8 @@ int16x8x2_t test_vzipq_s16(int16x8_t a, int16x8_t b) {
// CHECK-LABEL: @test_vzipq_s32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int32x4x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int32x4x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x4x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i32>*
@@ -1633,9 +1516,6 @@ int16x8x2_t test_vzipq_s16(int16x8_t a, int16x8_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
// CHECK: store <4 x i32> [[VZIP1_I]], <4 x i32>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 32, i32 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.int32x4x2_t, %struct.int32x4x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.int32x4x2_t [[TMP7]], 0
@@ -1648,18 +1528,14 @@ int32x4x2_t test_vzipq_s32(int32x4_t a, int32x4_t b) {
// CHECK-LABEL: @test_vzipq_u8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint8x16x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint8x16x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <16 x i8>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 0, i32 16, i32 1, i32 17, i32 2, i32 18, i32 3, i32 19, i32 4, i32 20, i32 5, i32 21, i32 6, i32 22, i32 7, i32 23>
// CHECK: store <16 x i8> [[VZIP_I]], <16 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 8, i32 24, i32 9, i32 25, i32 10, i32 26, i32 11, i32 27, i32 12, i32 28, i32 13, i32 29, i32 14, i32 30, i32 15, i32 31>
// CHECK: store <16 x i8> [[VZIP1_I]], <16 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 32, i32 16, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.uint8x16x2_t [[TMP5]], 0
@@ -1672,9 +1548,8 @@ uint8x16x2_t test_vzipq_u8(uint8x16_t a, uint8x16_t b) {
// CHECK-LABEL: @test_vzipq_u16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint16x8x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint16x8x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
@@ -1683,9 +1558,6 @@ uint8x16x2_t test_vzipq_u8(uint8x16_t a, uint8x16_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
// CHECK: store <8 x i16> [[VZIP1_I]], <8 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 32, i32 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.uint16x8x2_t [[TMP7]], 0
@@ -1698,9 +1570,8 @@ uint16x8x2_t test_vzipq_u16(uint16x8_t a, uint16x8_t b) {
// CHECK-LABEL: @test_vzipq_u32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint32x4x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint32x4x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x4x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i32>*
@@ -1709,9 +1580,6 @@ uint16x8x2_t test_vzipq_u16(uint16x8_t a, uint16x8_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
// CHECK: store <4 x i32> [[VZIP1_I]], <4 x i32>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 32, i32 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.uint32x4x2_t [[TMP7]], 0
@@ -1724,9 +1592,8 @@ uint32x4x2_t test_vzipq_u32(uint32x4_t a, uint32x4_t b) {
// CHECK-LABEL: @test_vzipq_f32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.float32x4x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.float32x4x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x4x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x float> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x float>*
@@ -1735,9 +1602,6 @@ uint32x4x2_t test_vzipq_u32(uint32x4_t a, uint32x4_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x float>, <4 x float>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
// CHECK: store <4 x float> [[VZIP1_I]], <4 x float>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.float32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 32, i32 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.float32x4x2_t, %struct.float32x4x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.float32x4x2_t [[TMP7]], 0
@@ -1750,18 +1614,14 @@ float32x4x2_t test_vzipq_f32(float32x4_t a, float32x4_t b) {
// CHECK-LABEL: @test_vzipq_p8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.poly8x16x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly8x16x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <16 x i8>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 0, i32 16, i32 1, i32 17, i32 2, i32 18, i32 3, i32 19, i32 4, i32 20, i32 5, i32 21, i32 6, i32 22, i32 7, i32 23>
// CHECK: store <16 x i8> [[VZIP_I]], <16 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 8, i32 24, i32 9, i32 25, i32 10, i32 26, i32 11, i32 27, i32 12, i32 28, i32 13, i32 29, i32 14, i32 30, i32 15, i32 31>
// CHECK: store <16 x i8> [[VZIP1_I]], <16 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 32, i32 16, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.poly8x16x2_t [[TMP5]], 0
@@ -1774,9 +1634,8 @@ poly8x16x2_t test_vzipq_p8(poly8x16_t a, poly8x16_t b) {
// CHECK-LABEL: @test_vzipq_p16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.poly16x8x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly16x8x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
@@ -1785,9 +1644,6 @@ poly8x16x2_t test_vzipq_p8(poly8x16_t a, poly8x16_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
// CHECK: store <8 x i16> [[VZIP1_I]], <8 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 32, i32 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.poly16x8x2_t [[TMP7]], 0
@@ -1800,18 +1656,14 @@ poly16x8x2_t test_vzipq_p16(poly16x8_t a, poly16x8_t b) {
// CHECK-LABEL: @test_vtrn_s8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int8x8x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int8x8x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14>
// CHECK: store <8 x i8> [[VTRN_I]], <8 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
// CHECK: store <8 x i8> [[VTRN1_I]], <8 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 16, i32 8, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.int8x8x2_t, %struct.int8x8x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.int8x8x2_t, %struct.int8x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.int8x8x2_t [[TMP5]], 0
@@ -1824,9 +1676,8 @@ int8x8x2_t test_vtrn_s8(int8x8_t a, int8x8_t b) {
// CHECK-LABEL: @test_vtrn_s16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int16x4x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int16x4x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
@@ -1835,9 +1686,6 @@ int8x8x2_t test_vtrn_s8(int8x8_t a, int8x8_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
// CHECK: store <4 x i16> [[VTRN1_I]], <4 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 16, i32 8, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.int16x4x2_t, %struct.int16x4x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.int16x4x2_t, %struct.int16x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.int16x4x2_t [[TMP7]], 0
@@ -1850,9 +1698,8 @@ int16x4x2_t test_vtrn_s16(int16x4_t a, int16x4_t b) {
// CHECK-LABEL: @test_vtrn_s32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int32x2x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int32x2x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x i32>*
@@ -1861,9 +1708,6 @@ int16x4x2_t test_vtrn_s16(int16x4_t a, int16x4_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 1, i32 3>
// CHECK: store <2 x i32> [[VTRN1_I]], <2 x i32>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x2x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 16, i32 8, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.int32x2x2_t, %struct.int32x2x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.int32x2x2_t, %struct.int32x2x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.int32x2x2_t [[TMP7]], 0
@@ -1876,18 +1720,14 @@ int32x2x2_t test_vtrn_s32(int32x2_t a, int32x2_t b) {
// CHECK-LABEL: @test_vtrn_u8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint8x8x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint8x8x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14>
// CHECK: store <8 x i8> [[VTRN_I]], <8 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
// CHECK: store <8 x i8> [[VTRN1_I]], <8 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 16, i32 8, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.uint8x8x2_t [[TMP5]], 0
@@ -1900,9 +1740,8 @@ uint8x8x2_t test_vtrn_u8(uint8x8_t a, uint8x8_t b) {
// CHECK-LABEL: @test_vtrn_u16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint16x4x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint16x4x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
@@ -1911,9 +1750,6 @@ uint8x8x2_t test_vtrn_u8(uint8x8_t a, uint8x8_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
// CHECK: store <4 x i16> [[VTRN1_I]], <4 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 16, i32 8, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.uint16x4x2_t [[TMP7]], 0
@@ -1926,9 +1762,8 @@ uint16x4x2_t test_vtrn_u16(uint16x4_t a, uint16x4_t b) {
// CHECK-LABEL: @test_vtrn_u32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint32x2x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint32x2x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x i32>*
@@ -1937,9 +1772,6 @@ uint16x4x2_t test_vtrn_u16(uint16x4_t a, uint16x4_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 1, i32 3>
// CHECK: store <2 x i32> [[VTRN1_I]], <2 x i32>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x2x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 16, i32 8, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.uint32x2x2_t [[TMP7]], 0
@@ -1952,9 +1784,8 @@ uint32x2x2_t test_vtrn_u32(uint32x2_t a, uint32x2_t b) {
// CHECK-LABEL: @test_vtrn_f32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.float32x2x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.float32x2x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x float> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x float>*
@@ -1963,9 +1794,6 @@ uint32x2x2_t test_vtrn_u32(uint32x2_t a, uint32x2_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x float>, <2 x float>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <2 x float> %a, <2 x float> %b, <2 x i32> <i32 1, i32 3>
// CHECK: store <2 x float> [[VTRN1_I]], <2 x float>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x2x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.float32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 16, i32 8, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.float32x2x2_t, %struct.float32x2x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.float32x2x2_t, %struct.float32x2x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.float32x2x2_t [[TMP7]], 0
@@ -1978,18 +1806,14 @@ float32x2x2_t test_vtrn_f32(float32x2_t a, float32x2_t b) {
// CHECK-LABEL: @test_vtrn_p8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.poly8x8x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly8x8x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14>
// CHECK: store <8 x i8> [[VTRN_I]], <8 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
// CHECK: store <8 x i8> [[VTRN1_I]], <8 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 16, i32 8, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.poly8x8x2_t [[TMP5]], 0
@@ -2002,9 +1826,8 @@ poly8x8x2_t test_vtrn_p8(poly8x8_t a, poly8x8_t b) {
// CHECK-LABEL: @test_vtrn_p16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.poly16x4x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly16x4x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
@@ -2013,9 +1836,6 @@ poly8x8x2_t test_vtrn_p8(poly8x8_t a, poly8x8_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
// CHECK: store <4 x i16> [[VTRN1_I]], <4 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 16, i32 8, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.poly16x4x2_t [[TMP7]], 0
@@ -2028,18 +1848,14 @@ poly16x4x2_t test_vtrn_p16(poly16x4_t a, poly16x4_t b) {
// CHECK-LABEL: @test_vtrnq_s8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int8x16x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int8x16x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <16 x i8>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 0, i32 16, i32 2, i32 18, i32 4, i32 20, i32 6, i32 22, i32 8, i32 24, i32 10, i32 26, i32 12, i32 28, i32 14, i32 30>
// CHECK: store <16 x i8> [[VTRN_I]], <16 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 1, i32 17, i32 3, i32 19, i32 5, i32 21, i32 7, i32 23, i32 9, i32 25, i32 11, i32 27, i32 13, i32 29, i32 15, i32 31>
// CHECK: store <16 x i8> [[VTRN1_I]], <16 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int8x16x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 32, i32 16, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.int8x16x2_t, %struct.int8x16x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.int8x16x2_t, %struct.int8x16x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.int8x16x2_t [[TMP5]], 0
@@ -2052,9 +1868,8 @@ int8x16x2_t test_vtrnq_s8(int8x16_t a, int8x16_t b) {
// CHECK-LABEL: @test_vtrnq_s16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int16x8x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int16x8x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
@@ -2063,9 +1878,6 @@ int8x16x2_t test_vtrnq_s8(int8x16_t a, int8x16_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
// CHECK: store <8 x i16> [[VTRN1_I]], <8 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 32, i32 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.int16x8x2_t, %struct.int16x8x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.int16x8x2_t [[TMP7]], 0
@@ -2078,9 +1890,8 @@ int16x8x2_t test_vtrnq_s16(int16x8_t a, int16x8_t b) {
// CHECK-LABEL: @test_vtrnq_s32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int32x4x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int32x4x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x4x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i32>*
@@ -2089,9 +1900,6 @@ int16x8x2_t test_vtrnq_s16(int16x8_t a, int16x8_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
// CHECK: store <4 x i32> [[VTRN1_I]], <4 x i32>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 32, i32 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.int32x4x2_t, %struct.int32x4x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.int32x4x2_t [[TMP7]], 0
@@ -2104,18 +1912,14 @@ int32x4x2_t test_vtrnq_s32(int32x4_t a, int32x4_t b) {
// CHECK-LABEL: @test_vtrnq_u8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint8x16x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint8x16x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <16 x i8>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 0, i32 16, i32 2, i32 18, i32 4, i32 20, i32 6, i32 22, i32 8, i32 24, i32 10, i32 26, i32 12, i32 28, i32 14, i32 30>
// CHECK: store <16 x i8> [[VTRN_I]], <16 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 1, i32 17, i32 3, i32 19, i32 5, i32 21, i32 7, i32 23, i32 9, i32 25, i32 11, i32 27, i32 13, i32 29, i32 15, i32 31>
// CHECK: store <16 x i8> [[VTRN1_I]], <16 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 32, i32 16, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.uint8x16x2_t [[TMP5]], 0
@@ -2128,9 +1932,8 @@ uint8x16x2_t test_vtrnq_u8(uint8x16_t a, uint8x16_t b) {
// CHECK-LABEL: @test_vtrnq_u16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint16x8x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint16x8x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
@@ -2139,9 +1942,6 @@ uint8x16x2_t test_vtrnq_u8(uint8x16_t a, uint8x16_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
// CHECK: store <8 x i16> [[VTRN1_I]], <8 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 32, i32 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.uint16x8x2_t [[TMP7]], 0
@@ -2154,9 +1954,8 @@ uint16x8x2_t test_vtrnq_u16(uint16x8_t a, uint16x8_t b) {
// CHECK-LABEL: @test_vtrnq_u32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint32x4x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint32x4x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x4x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i32>*
@@ -2165,9 +1964,6 @@ uint16x8x2_t test_vtrnq_u16(uint16x8_t a, uint16x8_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
// CHECK: store <4 x i32> [[VTRN1_I]], <4 x i32>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 32, i32 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.uint32x4x2_t [[TMP7]], 0
@@ -2180,9 +1976,8 @@ uint32x4x2_t test_vtrnq_u32(uint32x4_t a, uint32x4_t b) {
// CHECK-LABEL: @test_vtrnq_f32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.float32x4x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.float32x4x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x4x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x float> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x float>*
@@ -2191,9 +1986,6 @@ uint32x4x2_t test_vtrnq_u32(uint32x4_t a, uint32x4_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x float>, <4 x float>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
// CHECK: store <4 x float> [[VTRN1_I]], <4 x float>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.float32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 32, i32 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.float32x4x2_t, %struct.float32x4x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.float32x4x2_t [[TMP7]], 0
@@ -2206,18 +1998,14 @@ float32x4x2_t test_vtrnq_f32(float32x4_t a, float32x4_t b) {
// CHECK-LABEL: @test_vtrnq_p8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.poly8x16x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly8x16x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <16 x i8>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 0, i32 16, i32 2, i32 18, i32 4, i32 20, i32 6, i32 22, i32 8, i32 24, i32 10, i32 26, i32 12, i32 28, i32 14, i32 30>
// CHECK: store <16 x i8> [[VTRN_I]], <16 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 1, i32 17, i32 3, i32 19, i32 5, i32 21, i32 7, i32 23, i32 9, i32 25, i32 11, i32 27, i32 13, i32 29, i32 15, i32 31>
// CHECK: store <16 x i8> [[VTRN1_I]], <16 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP3]], i8* [[TMP4]], i64 32, i32 16, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.poly8x16x2_t [[TMP5]], 0
@@ -2230,9 +2018,8 @@ poly8x16x2_t test_vtrnq_p8(poly8x16_t a, poly8x16_t b) {
// CHECK-LABEL: @test_vtrnq_p16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.poly16x8x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly16x8x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
@@ -2241,9 +2028,6 @@ poly8x16x2_t test_vtrnq_p8(poly8x16_t a, poly8x16_t b) {
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
// CHECK: store <8 x i16> [[VTRN1_I]], <8 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 32, i32 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.poly16x8x2_t [[TMP7]], 0
diff --git a/test/CodeGen/aarch64-poly64.c b/test/CodeGen/aarch64-poly64.c
index 3fb8048fb39e..b70e5f0765e2 100644
--- a/test/CodeGen/aarch64-poly64.c
+++ b/test/CodeGen/aarch64-poly64.c
@@ -248,7 +248,7 @@ void test_vst1q_p64(poly64_t * ptr, poly64x2_t val) {
// CHECK: store { <1 x i64>, <1 x i64> } [[VLD2]], { <1 x i64>, <1 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.poly64x1x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.poly64x1x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 16, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.poly64x1x2_t, %struct.poly64x1x2_t* [[RETVAL]], align 8
// CHECK: ret %struct.poly64x1x2_t [[TMP6]]
poly64x1x2_t test_vld2_p64(poly64_t const * ptr) {
@@ -266,7 +266,7 @@ poly64x1x2_t test_vld2_p64(poly64_t const * ptr) {
// CHECK: store { <2 x i64>, <2 x i64> } [[VLD2]], { <2 x i64>, <2 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.poly64x2x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.poly64x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 32, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.poly64x2x2_t, %struct.poly64x2x2_t* [[RETVAL]], align 16
// CHECK: ret %struct.poly64x2x2_t [[TMP6]]
poly64x2x2_t test_vld2q_p64(poly64_t const * ptr) {
@@ -284,7 +284,7 @@ poly64x2x2_t test_vld2q_p64(poly64_t const * ptr) {
// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64> } [[VLD3]], { <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.poly64x1x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.poly64x1x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 24, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.poly64x1x3_t, %struct.poly64x1x3_t* [[RETVAL]], align 8
// CHECK: ret %struct.poly64x1x3_t [[TMP6]]
poly64x1x3_t test_vld3_p64(poly64_t const * ptr) {
@@ -302,7 +302,7 @@ poly64x1x3_t test_vld3_p64(poly64_t const * ptr) {
// CHECK: store { <2 x i64>, <2 x i64>, <2 x i64> } [[VLD3]], { <2 x i64>, <2 x i64>, <2 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.poly64x2x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.poly64x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 48, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.poly64x2x3_t, %struct.poly64x2x3_t* [[RETVAL]], align 16
// CHECK: ret %struct.poly64x2x3_t [[TMP6]]
poly64x2x3_t test_vld3q_p64(poly64_t const * ptr) {
@@ -320,7 +320,7 @@ poly64x2x3_t test_vld3q_p64(poly64_t const * ptr) {
// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } [[VLD4]], { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.poly64x1x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.poly64x1x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 32, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.poly64x1x4_t, %struct.poly64x1x4_t* [[RETVAL]], align 8
// CHECK: ret %struct.poly64x1x4_t [[TMP6]]
poly64x1x4_t test_vld4_p64(poly64_t const * ptr) {
@@ -338,7 +338,7 @@ poly64x1x4_t test_vld4_p64(poly64_t const * ptr) {
// CHECK: store { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } [[VLD4]], { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.poly64x2x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.poly64x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 64, i1 false)
// CHECK: [[TMP6:%.*]] = load %struct.poly64x2x4_t, %struct.poly64x2x4_t* [[RETVAL]], align 16
// CHECK: ret %struct.poly64x2x4_t [[TMP6]]
poly64x2x4_t test_vld4q_p64(poly64_t const * ptr) {
@@ -352,7 +352,7 @@ poly64x2x4_t test_vld4q_p64(poly64_t const * ptr) {
// CHECK: store [2 x <1 x i64>] [[VAL]].coerce, [2 x <1 x i64>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x1x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly64x1x2_t* [[VAL]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %ptr to i8*
// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly64x1x2_t, %struct.poly64x1x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <1 x i64>], [2 x <1 x i64>]* [[VAL1]], i64 0, i64 0
@@ -377,7 +377,7 @@ void test_vst2_p64(poly64_t * ptr, poly64x1x2_t val) {
// CHECK: store [2 x <2 x i64>] [[VAL]].coerce, [2 x <2 x i64>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x2x2_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly64x2x2_t* [[VAL]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %ptr to i8*
// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly64x2x2_t, %struct.poly64x2x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x i64>], [2 x <2 x i64>]* [[VAL1]], i64 0, i64 0
@@ -402,7 +402,7 @@ void test_vst2q_p64(poly64_t * ptr, poly64x2x2_t val) {
// CHECK: store [3 x <1 x i64>] [[VAL]].coerce, [3 x <1 x i64>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x1x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly64x1x3_t* [[VAL]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %ptr to i8*
// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly64x1x3_t, %struct.poly64x1x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL1]], i64 0, i64 0
@@ -432,7 +432,7 @@ void test_vst3_p64(poly64_t * ptr, poly64x1x3_t val) {
// CHECK: store [3 x <2 x i64>] [[VAL]].coerce, [3 x <2 x i64>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x2x3_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly64x2x3_t* [[VAL]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %ptr to i8*
// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly64x2x3_t, %struct.poly64x2x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x i64>], [3 x <2 x i64>]* [[VAL1]], i64 0, i64 0
@@ -462,7 +462,7 @@ void test_vst3q_p64(poly64_t * ptr, poly64x2x3_t val) {
// CHECK: store [4 x <1 x i64>] [[VAL]].coerce, [4 x <1 x i64>]* [[COERCE_DIVE]], align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x1x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly64x1x4_t* [[VAL]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %ptr to i8*
// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly64x1x4_t, %struct.poly64x1x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL1]], i64 0, i64 0
@@ -497,7 +497,7 @@ void test_vst4_p64(poly64_t * ptr, poly64x1x4_t val) {
// CHECK: store [4 x <2 x i64>] [[VAL]].coerce, [4 x <2 x i64>]* [[COERCE_DIVE]], align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x2x4_t* [[__S1]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly64x2x4_t* [[VAL]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP0]], i8* [[TMP1]], i64 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false)
// CHECK: [[TMP2:%.*]] = bitcast i64* %ptr to i8*
// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly64x2x4_t, %struct.poly64x2x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL1]], i64 0, i64 0
diff --git a/test/CodeGen/aarch64-v8.2a-fp16-intrinsics.c b/test/CodeGen/aarch64-v8.2a-fp16-intrinsics.c
new file mode 100644
index 000000000000..b8e1f92a2579
--- /dev/null
+++ b/test/CodeGen/aarch64-v8.2a-fp16-intrinsics.c
@@ -0,0 +1,659 @@
+// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +fullfp16\
+// RUN: -fallow-half-arguments-and-returns -S -disable-O0-optnone -emit-llvm -o - %s \
+// RUN: | opt -S -mem2reg \
+// RUN: | FileCheck %s
+
+// REQUIRES: aarch64-registered-target
+
+#include <arm_fp16.h>
+
+// CHECK-LABEL: test_vabsh_f16
+// CHECK: [[ABS:%.*]] = call half @llvm.fabs.f16(half %a)
+// CHECK: ret half [[ABS]]
+float16_t test_vabsh_f16(float16_t a) {
+ return vabsh_f16(a);
+}
+
+// CHECK-LABEL: test_vceqzh_f16
+// CHECK: [[TMP1:%.*]] = fcmp oeq half %a, 0xH0000
+// CHECK: [[TMP2:%.*]] = sext i1 [[TMP1]] to i16
+// CHECK: ret i16 [[TMP2]]
+uint16_t test_vceqzh_f16(float16_t a) {
+ return vceqzh_f16(a);
+}
+
+// CHECK-LABEL: test_vcgezh_f16
+// CHECK: [[TMP1:%.*]] = fcmp oge half %a, 0xH0000
+// CHECK: [[TMP2:%.*]] = sext i1 [[TMP1]] to i16
+// CHECK: ret i16 [[TMP2]]
+uint16_t test_vcgezh_f16(float16_t a) {
+ return vcgezh_f16(a);
+}
+
+// CHECK-LABEL: test_vcgtzh_f16
+// CHECK: [[TMP1:%.*]] = fcmp ogt half %a, 0xH0000
+// CHECK: [[TMP2:%.*]] = sext i1 [[TMP1]] to i16
+// CHECK: ret i16 [[TMP2]]
+uint16_t test_vcgtzh_f16(float16_t a) {
+ return vcgtzh_f16(a);
+}
+
+// CHECK-LABEL: test_vclezh_f16
+// CHECK: [[TMP1:%.*]] = fcmp ole half %a, 0xH0000
+// CHECK: [[TMP2:%.*]] = sext i1 [[TMP1]] to i16
+// CHECK: ret i16 [[TMP2]]
+uint16_t test_vclezh_f16(float16_t a) {
+ return vclezh_f16(a);
+}
+
+// CHECK-LABEL: test_vcltzh_f16
+// CHECK: [[TMP1:%.*]] = fcmp olt half %a, 0xH0000
+// CHECK: [[TMP2:%.*]] = sext i1 [[TMP1]] to i16
+// CHECK: ret i16 [[TMP2]]
+uint16_t test_vcltzh_f16(float16_t a) {
+ return vcltzh_f16(a);
+}
+
+// CHECK-LABEL: test_vcvth_f16_s16
+// CHECK: [[VCVT:%.*]] = sitofp i16 %a to half
+// CHECK: ret half [[VCVT]]
+float16_t test_vcvth_f16_s16 (int16_t a) {
+ return vcvth_f16_s16(a);
+}
+
+// CHECK-LABEL: test_vcvth_f16_s32
+// CHECK: [[VCVT:%.*]] = sitofp i32 %a to half
+// CHECK: ret half [[VCVT]]
+float16_t test_vcvth_f16_s32 (int32_t a) {
+ return vcvth_f16_s32(a);
+}
+
+// CHECK-LABEL: test_vcvth_f16_s64
+// CHECK: [[VCVT:%.*]] = sitofp i64 %a to half
+// CHECK: ret half [[VCVT]]
+float16_t test_vcvth_f16_s64 (int64_t a) {
+ return vcvth_f16_s64(a);
+}
+
+// CHECK-LABEL: test_vcvth_f16_u16
+// CHECK: [[VCVT:%.*]] = uitofp i16 %a to half
+// CHECK: ret half [[VCVT]]
+float16_t test_vcvth_f16_u16 (uint16_t a) {
+ return vcvth_f16_u16(a);
+}
+
+// CHECK-LABEL: test_vcvth_f16_u32
+// CHECK: [[VCVT:%.*]] = uitofp i32 %a to half
+// CHECK: ret half [[VCVT]]
+float16_t test_vcvth_f16_u32 (uint32_t a) {
+ return vcvth_f16_u32(a);
+}
+
+// CHECK-LABEL: test_vcvth_f16_u64
+// CHECK: [[VCVT:%.*]] = uitofp i64 %a to half
+// CHECK: ret half [[VCVT]]
+float16_t test_vcvth_f16_u64 (uint64_t a) {
+ return vcvth_f16_u64(a);
+}
+
+// CHECK-LABEL: test_vcvth_s16_f16
+// CHECK: [[VCVT:%.*]] = fptosi half %a to i16
+// CHECK: ret i16 [[VCVT]]
+int16_t test_vcvth_s16_f16 (float16_t a) {
+ return vcvth_s16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvth_s32_f16
+// CHECK: [[VCVT:%.*]] = fptosi half %a to i32
+// CHECK: ret i32 [[VCVT]]
+int32_t test_vcvth_s32_f16 (float16_t a) {
+ return vcvth_s32_f16(a);
+}
+
+// CHECK-LABEL: test_vcvth_s64_f16
+// CHECK: [[VCVT:%.*]] = fptosi half %a to i64
+// CHECK: ret i64 [[VCVT]]
+int64_t test_vcvth_s64_f16 (float16_t a) {
+ return vcvth_s64_f16(a);
+}
+
+// CHECK-LABEL: test_vcvth_u16_f16
+// CHECK: [[VCVT:%.*]] = fptoui half %a to i16
+// CHECK: ret i16 [[VCVT]]
+uint16_t test_vcvth_u16_f16 (float16_t a) {
+ return vcvth_u16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvth_u32_f16
+// CHECK: [[VCVT:%.*]] = fptoui half %a to i32
+// CHECK: ret i32 [[VCVT]]
+uint32_t test_vcvth_u32_f16 (float16_t a) {
+ return vcvth_u32_f16(a);
+}
+
+// CHECK-LABEL: test_vcvth_u64_f16
+// CHECK: [[VCVT:%.*]] = fptoui half %a to i64
+// CHECK: ret i64 [[VCVT]]
+uint64_t test_vcvth_u64_f16 (float16_t a) {
+ return vcvth_u64_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtah_s16_f16
+// CHECK: [[FCVT:%.*]] = call i32 @llvm.aarch64.neon.fcvtas.i32.f16(half %a)
+// CHECK: [[RET:%.*]] = trunc i32 [[FCVT]] to i16
+// CHECK: ret i16 [[RET]]
+int16_t test_vcvtah_s16_f16 (float16_t a) {
+ return vcvtah_s16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtah_s32_f16
+// CHECK: [[VCVT:%.*]] = call i32 @llvm.aarch64.neon.fcvtas.i32.f16(half %a)
+// CHECK: ret i32 [[VCVT]]
+int32_t test_vcvtah_s32_f16 (float16_t a) {
+ return vcvtah_s32_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtah_s64_f16
+// CHECK: [[VCVT:%.*]] = call i64 @llvm.aarch64.neon.fcvtas.i64.f16(half %a)
+// CHECK: ret i64 [[VCVT]]
+int64_t test_vcvtah_s64_f16 (float16_t a) {
+ return vcvtah_s64_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtah_u16_f16
+// CHECK: [[FCVT:%.*]] = call i32 @llvm.aarch64.neon.fcvtau.i32.f16(half %a)
+// CHECK: [[RET:%.*]] = trunc i32 [[FCVT]] to i16
+// CHECK: ret i16 [[RET]]
+uint16_t test_vcvtah_u16_f16 (float16_t a) {
+ return vcvtah_u16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtah_u32_f16
+// CHECK: [[VCVT:%.*]] = call i32 @llvm.aarch64.neon.fcvtau.i32.f16(half %a)
+// CHECK: ret i32 [[VCVT]]
+uint32_t test_vcvtah_u32_f16 (float16_t a) {
+ return vcvtah_u32_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtah_u64_f16
+// CHECK: [[VCVT:%.*]] = call i64 @llvm.aarch64.neon.fcvtau.i64.f16(half %a)
+// CHECK: ret i64 [[VCVT]]
+uint64_t test_vcvtah_u64_f16 (float16_t a) {
+ return vcvtah_u64_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtmh_s16_f16
+// CHECK: [[FCVT:%.*]] = call i32 @llvm.aarch64.neon.fcvtms.i32.f16(half %a)
+// CHECK: [[RET:%.*]] = trunc i32 [[FCVT]] to i16
+// CHECK: ret i16 [[RET]]
+int16_t test_vcvtmh_s16_f16 (float16_t a) {
+ return vcvtmh_s16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtmh_s32_f16
+// CHECK: [[VCVT:%.*]] = call i32 @llvm.aarch64.neon.fcvtms.i32.f16(half %a)
+// CHECK: ret i32 [[VCVT]]
+int32_t test_vcvtmh_s32_f16 (float16_t a) {
+ return vcvtmh_s32_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtmh_s64_f16
+// CHECK: [[VCVT:%.*]] = call i64 @llvm.aarch64.neon.fcvtms.i64.f16(half %a)
+// CHECK: ret i64 [[VCVT]]
+int64_t test_vcvtmh_s64_f16 (float16_t a) {
+ return vcvtmh_s64_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtmh_u16_f16
+// CHECK: [[FCVT:%.*]] = call i32 @llvm.aarch64.neon.fcvtmu.i32.f16(half %a)
+// CHECK: [[RET:%.*]] = trunc i32 [[FCVT]] to i16
+// CHECK: ret i16 [[RET]]
+uint16_t test_vcvtmh_u16_f16 (float16_t a) {
+ return vcvtmh_u16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtmh_u32_f16
+// CHECK: [[VCVT:%.*]] = call i32 @llvm.aarch64.neon.fcvtmu.i32.f16(half %a)
+// CHECK: ret i32 [[VCVT]]
+uint32_t test_vcvtmh_u32_f16 (float16_t a) {
+ return vcvtmh_u32_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtmh_u64_f16
+// CHECK: [[VCVT:%.*]] = call i64 @llvm.aarch64.neon.fcvtmu.i64.f16(half %a)
+// CHECK: ret i64 [[VCVT]]
+uint64_t test_vcvtmh_u64_f16 (float16_t a) {
+ return vcvtmh_u64_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtnh_s16_f16
+// CHECK: [[FCVT:%.*]] = call i32 @llvm.aarch64.neon.fcvtns.i32.f16(half %a)
+// CHECK: [[RET:%.*]] = trunc i32 [[FCVT]] to i16
+// CHECK: ret i16 [[RET]]
+int16_t test_vcvtnh_s16_f16 (float16_t a) {
+ return vcvtnh_s16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtnh_s32_f16
+// CHECK: [[VCVT:%.*]] = call i32 @llvm.aarch64.neon.fcvtns.i32.f16(half %a)
+// CHECK: ret i32 [[VCVT]]
+int32_t test_vcvtnh_s32_f16 (float16_t a) {
+ return vcvtnh_s32_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtnh_s64_f16
+// CHECK: [[VCVT:%.*]] = call i64 @llvm.aarch64.neon.fcvtns.i64.f16(half %a)
+// CHECK: ret i64 [[VCVT]]
+int64_t test_vcvtnh_s64_f16 (float16_t a) {
+ return vcvtnh_s64_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtnh_u16_f16
+// CHECK: [[FCVT:%.*]] = call i32 @llvm.aarch64.neon.fcvtnu.i32.f16(half %a)
+// CHECK: [[RET:%.*]] = trunc i32 [[FCVT]] to i16
+// CHECK: ret i16 [[RET]]
+uint16_t test_vcvtnh_u16_f16 (float16_t a) {
+ return vcvtnh_u16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtnh_u32_f16
+// CHECK: [[VCVT:%.*]] = call i32 @llvm.aarch64.neon.fcvtnu.i32.f16(half %a)
+// CHECK: ret i32 [[VCVT]]
+uint32_t test_vcvtnh_u32_f16 (float16_t a) {
+ return vcvtnh_u32_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtnh_u64_f16
+// CHECK: [[VCVT:%.*]] = call i64 @llvm.aarch64.neon.fcvtnu.i64.f16(half %a)
+// CHECK: ret i64 [[VCVT]]
+uint64_t test_vcvtnh_u64_f16 (float16_t a) {
+ return vcvtnh_u64_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtph_s16_f16
+// CHECK: [[FCVT:%.*]] = call i32 @llvm.aarch64.neon.fcvtps.i32.f16(half %a)
+// CHECK: [[RET:%.*]] = trunc i32 [[FCVT]] to i16
+// CHECK: ret i16 [[RET]]
+int16_t test_vcvtph_s16_f16 (float16_t a) {
+ return vcvtph_s16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtph_s32_f16
+// CHECK: [[VCVT:%.*]] = call i32 @llvm.aarch64.neon.fcvtps.i32.f16(half %a)
+// CHECK: ret i32 [[VCVT]]
+int32_t test_vcvtph_s32_f16 (float16_t a) {
+ return vcvtph_s32_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtph_s64_f16
+// CHECK: [[VCVT:%.*]] = call i64 @llvm.aarch64.neon.fcvtps.i64.f16(half %a)
+// CHECK: ret i64 [[VCVT]]
+int64_t test_vcvtph_s64_f16 (float16_t a) {
+ return vcvtph_s64_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtph_u16_f16
+// CHECK: [[FCVT:%.*]] = call i32 @llvm.aarch64.neon.fcvtpu.i32.f16(half %a)
+// CHECK: [[RET:%.*]] = trunc i32 [[FCVT]] to i16
+// CHECK: ret i16 [[RET]]
+uint16_t test_vcvtph_u16_f16 (float16_t a) {
+ return vcvtph_u16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtph_u32_f16
+// CHECK: [[VCVT:%.*]] = call i32 @llvm.aarch64.neon.fcvtpu.i32.f16(half %a)
+// CHECK: ret i32 [[VCVT]]
+uint32_t test_vcvtph_u32_f16 (float16_t a) {
+ return vcvtph_u32_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtph_u64_f16
+// CHECK: [[VCVT:%.*]] = call i64 @llvm.aarch64.neon.fcvtpu.i64.f16(half %a)
+// CHECK: ret i64 [[VCVT]]
+uint64_t test_vcvtph_u64_f16 (float16_t a) {
+ return vcvtph_u64_f16(a);
+}
+
+// CHECK-LABEL: test_vnegh_f16
+// CHECK: [[NEG:%.*]] = fsub half 0xH8000, %a
+// CHECK: ret half [[NEG]]
+float16_t test_vnegh_f16(float16_t a) {
+ return vnegh_f16(a);
+}
+
+// CHECK-LABEL: test_vrecpeh_f16
+// CHECK: [[VREC:%.*]] = call half @llvm.aarch64.neon.frecpe.f16(half %a)
+// CHECK: ret half [[VREC]]
+float16_t test_vrecpeh_f16(float16_t a) {
+ return vrecpeh_f16(a);
+}
+
+// CHECK-LABEL: test_vrecpxh_f16
+// CHECK: [[VREC:%.*]] = call half @llvm.aarch64.neon.frecpx.f16(half %a)
+// CHECK: ret half [[VREC]]
+float16_t test_vrecpxh_f16(float16_t a) {
+ return vrecpxh_f16(a);
+}
+
+// CHECK-LABEL: test_vrndh_f16
+// CHECK: [[RND:%.*]] = call half @llvm.trunc.f16(half %a)
+// CHECK: ret half [[RND]]
+float16_t test_vrndh_f16(float16_t a) {
+ return vrndh_f16(a);
+}
+
+// CHECK-LABEL: test_vrndah_f16
+// CHECK: [[RND:%.*]] = call half @llvm.round.f16(half %a)
+// CHECK: ret half [[RND]]
+float16_t test_vrndah_f16(float16_t a) {
+ return vrndah_f16(a);
+}
+
+// CHECK-LABEL: test_vrndih_f16
+// CHECK: [[RND:%.*]] = call half @llvm.nearbyint.f16(half %a)
+// CHECK: ret half [[RND]]
+float16_t test_vrndih_f16(float16_t a) {
+ return vrndih_f16(a);
+}
+
+// CHECK-LABEL: test_vrndmh_f16
+// CHECK: [[RND:%.*]] = call half @llvm.floor.f16(half %a)
+// CHECK: ret half [[RND]]
+float16_t test_vrndmh_f16(float16_t a) {
+ return vrndmh_f16(a);
+}
+
+// CHECK-LABEL: test_vrndnh_f16
+// CHECK: [[RND:%.*]] = call half @llvm.aarch64.neon.frintn.f16(half %a)
+// CHECK: ret half [[RND]]
+float16_t test_vrndnh_f16(float16_t a) {
+ return vrndnh_f16(a);
+}
+
+// CHECK-LABEL: test_vrndph_f16
+// CHECK: [[RND:%.*]] = call half @llvm.ceil.f16(half %a)
+// CHECK: ret half [[RND]]
+float16_t test_vrndph_f16(float16_t a) {
+ return vrndph_f16(a);
+}
+
+// CHECK-LABEL: test_vrndxh_f16
+// CHECK: [[RND:%.*]] = call half @llvm.rint.f16(half %a)
+// CHECK: ret half [[RND]]
+float16_t test_vrndxh_f16(float16_t a) {
+ return vrndxh_f16(a);
+}
+
+// CHECK-LABEL: test_vrsqrteh_f16
+// CHECK: [[RND:%.*]] = call half @llvm.aarch64.neon.frsqrte.f16(half %a)
+// CHECK: ret half [[RND]]
+float16_t test_vrsqrteh_f16(float16_t a) {
+ return vrsqrteh_f16(a);
+}
+
+// CHECK-LABEL: test_vsqrth_f16
+// CHECK: [[SQR:%.*]] = call half @llvm.sqrt.f16(half %a)
+// CHECK: ret half [[SQR]]
+float16_t test_vsqrth_f16(float16_t a) {
+ return vsqrth_f16(a);
+}
+
+// CHECK-LABEL: test_vaddh_f16
+// CHECK: [[ADD:%.*]] = fadd half %a, %b
+// CHECK: ret half [[ADD]]
+float16_t test_vaddh_f16(float16_t a, float16_t b) {
+ return vaddh_f16(a, b);
+}
+
+// CHECK-LABEL: test_vabdh_f16
+// CHECK: [[ABD:%.*]] = call half @llvm.aarch64.sisd.fabd.f16(half %a, half %b)
+// CHECK: ret half [[ABD]]
+float16_t test_vabdh_f16(float16_t a, float16_t b) {
+ return vabdh_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcageh_f16
+// CHECK: [[FACG:%.*]] = call i32 @llvm.aarch64.neon.facge.i32.f16(half %a, half %b)
+// CHECK: [[RET:%.*]] = trunc i32 [[FACG]] to i16
+// CHECK: ret i16 [[RET]]
+uint16_t test_vcageh_f16(float16_t a, float16_t b) {
+ return vcageh_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcagth_f16
+// CHECK: [[FACG:%.*]] = call i32 @llvm.aarch64.neon.facgt.i32.f16(half %a, half %b)
+// CHECK: [[RET:%.*]] = trunc i32 [[FACG]] to i16
+// CHECK: ret i16 [[RET]]
+uint16_t test_vcagth_f16(float16_t a, float16_t b) {
+ return vcagth_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcaleh_f16
+// CHECK: [[FACG:%.*]] = call i32 @llvm.aarch64.neon.facge.i32.f16(half %b, half %a)
+// CHECK: [[RET:%.*]] = trunc i32 [[FACG]] to i16
+// CHECK: ret i16 [[RET]]
+uint16_t test_vcaleh_f16(float16_t a, float16_t b) {
+ return vcaleh_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcalth_f16
+// CHECK: [[FACG:%.*]] = call i32 @llvm.aarch64.neon.facgt.i32.f16(half %b, half %a)
+// CHECK: [[RET:%.*]] = trunc i32 [[FACG]] to i16
+// CHECK: ret i16 [[RET]]
+uint16_t test_vcalth_f16(float16_t a, float16_t b) {
+ return vcalth_f16(a, b);
+}
+
+// CHECK-LABEL: test_vceqh_f16
+// CHECK: [[TMP1:%.*]] = fcmp oeq half %a, %b
+// CHECK: [[TMP2:%.*]] = sext i1 [[TMP1]] to i16
+// CHECK: ret i16 [[TMP2]]
+uint16_t test_vceqh_f16(float16_t a, float16_t b) {
+ return vceqh_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcgeh_f16
+// CHECK: [[TMP1:%.*]] = fcmp oge half %a, %b
+// CHECK: [[TMP2:%.*]] = sext i1 [[TMP1]] to i16
+// CHECK: ret i16 [[TMP2]]
+uint16_t test_vcgeh_f16(float16_t a, float16_t b) {
+ return vcgeh_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcgth_f16
+//CHECK: [[TMP1:%.*]] = fcmp ogt half %a, %b
+// CHECK: [[TMP2:%.*]] = sext i1 [[TMP1]] to i16
+// CHECK: ret i16 [[TMP2]]
+uint16_t test_vcgth_f16(float16_t a, float16_t b) {
+ return vcgth_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcleh_f16
+// CHECK: [[TMP1:%.*]] = fcmp ole half %a, %b
+// CHECK: [[TMP2:%.*]] = sext i1 [[TMP1]] to i16
+// CHECK: ret i16 [[TMP2]]
+uint16_t test_vcleh_f16(float16_t a, float16_t b) {
+ return vcleh_f16(a, b);
+}
+
+// CHECK-LABEL: test_vclth_f16
+// CHECK: [[TMP1:%.*]] = fcmp olt half %a, %b
+// CHECK: [[TMP2:%.*]] = sext i1 [[TMP1]] to i16
+// CHECK: ret i16 [[TMP2]]
+uint16_t test_vclth_f16(float16_t a, float16_t b) {
+ return vclth_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcvth_n_f16_s16
+// CHECK: [[SEXT:%.*]] = sext i16 %a to i32
+// CHECK: [[CVT:%.*]] = call half @llvm.aarch64.neon.vcvtfxs2fp.f16.i32(i32 [[SEXT]], i32 1)
+// CHECK: ret half [[CVT]]
+float16_t test_vcvth_n_f16_s16(int16_t a) {
+ return vcvth_n_f16_s16(a, 1);
+}
+
+// CHECK-LABEL: test_vcvth_n_f16_s32
+// CHECK: [[CVT:%.*]] = call half @llvm.aarch64.neon.vcvtfxs2fp.f16.i32(i32 %a, i32 1)
+// CHECK: ret half [[CVT]]
+float16_t test_vcvth_n_f16_s32(int32_t a) {
+ return vcvth_n_f16_s32(a, 1);
+}
+
+// CHECK-LABEL: test_vcvth_n_f16_s64
+// CHECK: [[CVT:%.*]] = call half @llvm.aarch64.neon.vcvtfxs2fp.f16.i64(i64 %a, i32 1)
+// CHECK: ret half [[CVT]]
+float16_t test_vcvth_n_f16_s64(int64_t a) {
+ return vcvth_n_f16_s64(a, 1);
+}
+
+// CHECK-LABEL: test_vcvth_n_s16_f16
+// CHECK: [[CVT:%.*]] = call i32 @llvm.aarch64.neon.vcvtfp2fxs.i32.f16(half %a, i32 1)
+// CHECK: [[RET:%.*]] = trunc i32 [[CVT]] to i16
+// CHECK: ret i16 [[RET]]
+int16_t test_vcvth_n_s16_f16(float16_t a) {
+ return vcvth_n_s16_f16(a, 1);
+}
+
+// CHECK-LABEL: test_vcvth_n_s32_f16
+// CHECK: [[CVT:%.*]] = call i32 @llvm.aarch64.neon.vcvtfp2fxs.i32.f16(half %a, i32 1)
+// CHECK: ret i32 [[CVT]]
+int32_t test_vcvth_n_s32_f16(float16_t a) {
+ return vcvth_n_s32_f16(a, 1);
+}
+
+// CHECK-LABEL: test_vcvth_n_s64_f16
+// CHECK: [[CVT:%.*]] = call i64 @llvm.aarch64.neon.vcvtfp2fxs.i64.f16(half %a, i32 1)
+// CHECK: ret i64 [[CVT]]
+int64_t test_vcvth_n_s64_f16(float16_t a) {
+ return vcvth_n_s64_f16(a, 1);
+}
+
+// CHECK-LABEL: test_vcvth_n_f16_u16
+// CHECK: [[SEXT:%.*]] = zext i16 %a to i32
+// CHECK: [[CVT:%.*]] = call half @llvm.aarch64.neon.vcvtfxu2fp.f16.i32(i32 [[SEXT]], i32 1)
+// CHECK: ret half [[CVT]]
+float16_t test_vcvth_n_f16_u16(int16_t a) {
+ return vcvth_n_f16_u16(a, 1);
+}
+
+// CHECK-LABEL: test_vcvth_n_f16_u32
+// CHECK: [[CVT:%.*]] = call half @llvm.aarch64.neon.vcvtfxu2fp.f16.i32(i32 %a, i32 1)
+// CHECK: ret half [[CVT]]
+float16_t test_vcvth_n_f16_u32(int32_t a) {
+ return vcvth_n_f16_u32(a, 1);
+}
+
+// CHECK-LABEL: test_vcvth_n_f16_u64
+// CHECK: [[CVT:%.*]] = call half @llvm.aarch64.neon.vcvtfxu2fp.f16.i64(i64 %a, i32 1)
+// CHECK: ret half [[CVT]]
+float16_t test_vcvth_n_f16_u64(int64_t a) {
+ return vcvth_n_f16_u64(a, 1);
+}
+
+// CHECK-LABEL: test_vcvth_n_u16_f16
+// CHECK: [[CVT:%.*]] = call i32 @llvm.aarch64.neon.vcvtfp2fxu.i32.f16(half %a, i32 1)
+// CHECK: [[RET:%.*]] = trunc i32 [[CVT]] to i16
+// CHECK: ret i16 [[RET]]
+int16_t test_vcvth_n_u16_f16(float16_t a) {
+ return vcvth_n_u16_f16(a, 1);
+}
+
+// CHECK-LABEL: test_vcvth_n_u32_f16
+// CHECK: [[CVT:%.*]] = call i32 @llvm.aarch64.neon.vcvtfp2fxu.i32.f16(half %a, i32 1)
+// CHECK: ret i32 [[CVT]]
+int32_t test_vcvth_n_u32_f16(float16_t a) {
+ return vcvth_n_u32_f16(a, 1);
+}
+
+// CHECK-LABEL: test_vcvth_n_u64_f16
+// CHECK: [[CVT:%.*]] = call i64 @llvm.aarch64.neon.vcvtfp2fxu.i64.f16(half %a, i32 1)
+// CHECK: ret i64 [[CVT]]
+int64_t test_vcvth_n_u64_f16(float16_t a) {
+ return vcvth_n_u64_f16(a, 1);
+}
+
+// CHECK-LABEL: test_vdivh_f16
+// CHECK: [[DIV:%.*]] = fdiv half %a, %b
+// CHECK: ret half [[DIV]]
+float16_t test_vdivh_f16(float16_t a, float16_t b) {
+ return vdivh_f16(a, b);
+}
+
+// CHECK-LABEL: test_vmaxh_f16
+// CHECK: [[MAX:%.*]] = call half @llvm.aarch64.neon.fmax.f16(half %a, half %b)
+// CHECK: ret half [[MAX]]
+float16_t test_vmaxh_f16(float16_t a, float16_t b) {
+ return vmaxh_f16(a, b);
+}
+
+// CHECK-LABEL: test_vmaxnmh_f16
+// CHECK: [[MAX:%.*]] = call half @llvm.aarch64.neon.fmaxnm.f16(half %a, half %b)
+// CHECK: ret half [[MAX]]
+float16_t test_vmaxnmh_f16(float16_t a, float16_t b) {
+ return vmaxnmh_f16(a, b);
+}
+
+// CHECK-LABEL: test_vminh_f16
+// CHECK: [[MIN:%.*]] = call half @llvm.aarch64.neon.fmin.f16(half %a, half %b)
+// CHECK: ret half [[MIN]]
+float16_t test_vminh_f16(float16_t a, float16_t b) {
+ return vminh_f16(a, b);
+}
+
+// CHECK-LABEL: test_vminnmh_f16
+// CHECK: [[MIN:%.*]] = call half @llvm.aarch64.neon.fminnm.f16(half %a, half %b)
+// CHECK: ret half [[MIN]]
+float16_t test_vminnmh_f16(float16_t a, float16_t b) {
+ return vminnmh_f16(a, b);
+}
+
+// CHECK-LABEL: test_vmulh_f16
+// CHECK: [[MUL:%.*]] = fmul half %a, %b
+// CHECK: ret half [[MUL]]
+float16_t test_vmulh_f16(float16_t a, float16_t b) {
+ return vmulh_f16(a, b);
+}
+
+// CHECK-LABEL: test_vmulxh_f16
+// CHECK: [[MUL:%.*]] = call half @llvm.aarch64.neon.fmulx.f16(half %a, half %b)
+// CHECK: ret half [[MUL]]
+float16_t test_vmulxh_f16(float16_t a, float16_t b) {
+ return vmulxh_f16(a, b);
+}
+
+// CHECK-LABEL: test_vrecpsh_f16
+// CHECK: [[RECPS:%.*]] = call half @llvm.aarch64.neon.frecps.f16(half %a, half %b)
+// CHECK: ret half [[RECPS]]
+float16_t test_vrecpsh_f16(float16_t a, float16_t b) {
+ return vrecpsh_f16(a, b);
+}
+
+// CHECK-LABEL: test_vrsqrtsh_f16
+// CHECK: [[RSQRTS:%.*]] = call half @llvm.aarch64.neon.frsqrts.f16(half %a, half %b)
+// CHECK: ret half [[RSQRTS]]
+float16_t test_vrsqrtsh_f16(float16_t a, float16_t b) {
+ return vrsqrtsh_f16(a, b);
+}
+
+// CHECK-LABEL: test_vsubh_f16
+// CHECK: [[SUB:%.*]] = fsub half %a, %b
+// CHECK: ret half [[SUB]]
+float16_t test_vsubh_f16(float16_t a, float16_t b) {
+ return vsubh_f16(a, b);
+}
+
+// CHECK-LABEL: test_vfmah_f16
+// CHECK: [[FMA:%.*]] = call half @llvm.fma.f16(half %b, half %c, half %a)
+// CHECK: ret half [[FMA]]
+float16_t test_vfmah_f16(float16_t a, float16_t b, float16_t c) {
+ return vfmah_f16(a, b, c);
+}
+
+// CHECK-LABEL: test_vfmsh_f16
+// CHECK: [[SUB:%.*]] = fsub half 0xH8000, %b
+// CHECK: [[ADD:%.*]] = call half @llvm.fma.f16(half [[SUB]], half %c, half %a)
+// CHECK: ret half [[ADD]]
+float16_t test_vfmsh_f16(float16_t a, float16_t b, float16_t c) {
+ return vfmsh_f16(a, b, c);
+}
+
diff --git a/test/CodeGen/aarch64-v8.2a-neon-intrinsics.c b/test/CodeGen/aarch64-v8.2a-neon-intrinsics.c
index 3f61238b64fb..e1a2e3fb92dd 100644
--- a/test/CodeGen/aarch64-v8.2a-neon-intrinsics.c
+++ b/test/CodeGen/aarch64-v8.2a-neon-intrinsics.c
@@ -164,6 +164,13 @@ int16x4_t test_vcvta_s16_f16 (float16x4_t a) {
return vcvta_s16_f16(a);
}
+// CHECK-LABEL: test_vcvta_u16_f16
+// CHECK: [[VCVT:%.*]] = call <4 x i16> @llvm.aarch64.neon.fcvtau.v4i16.v4f16(<4 x half> %a)
+// CHECK: ret <4 x i16> [[VCVT]]
+int16x4_t test_vcvta_u16_f16 (float16x4_t a) {
+ return vcvta_u16_f16(a);
+}
+
// CHECK-LABEL: test_vcvtaq_s16_f16
// CHECK: [[VCVT:%.*]] = call <8 x i16> @llvm.aarch64.neon.fcvtas.v8i16.v8f16(<8 x half> %a)
// CHECK: ret <8 x i16> [[VCVT]]
@@ -1223,27 +1230,25 @@ float16x8_t test_vmulxq_n_f16(float16x8_t a, float16_t b) {
return vmulxq_n_f16(a, b);
}
-/* TODO: Not implemented yet (needs scalar intrinsic from arm_fp16.h)
-// CCHECK-LABEL: test_vmulxh_lane_f16
-// CCHECK: [[CONV0:%.*]] = fpext half %a to float
-// CCHECK: [[CONV1:%.*]] = fpext half %{{.*}} to float
-// CCHECK: [[MUL:%.*]] = fmul float [[CONV0:%.*]], [[CONV0:%.*]]
-// CCHECK: [[CONV3:%.*]] = fptrunc float %mul to half
-// CCHECK: ret half [[CONV3:%.*]]
+// CHECK-LABEL: test_vmulxh_lane_f16
+// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %b to <8 x i8>
+// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x half>
+// CHECK: [[EXTR:%.*]] = extractelement <4 x half> [[TMP1]], i32 3
+// CHECK: [[MULX:%.*]] = call half @llvm.aarch64.neon.fmulx.f16(half %a, half [[EXTR]]
+// CHECK: ret half [[MULX]]
float16_t test_vmulxh_lane_f16(float16_t a, float16x4_t b) {
return vmulxh_lane_f16(a, b, 3);
}
-// CCHECK-LABEL: test_vmulxh_laneq_f16
-// CCHECK: [[CONV0:%.*]] = fpext half %a to float
-// CCHECK: [[CONV1:%.*]] = fpext half %{{.*}} to float
-// CCHECK: [[MUL:%.*]] = fmul float [[CONV0:%.*]], [[CONV0:%.*]]
-// CCHECK: [[CONV3:%.*]] = fptrunc float %mul to half
-// CCHECK: ret half [[CONV3:%.*]]
+// CHECK-LABEL: test_vmulxh_laneq_f16
+// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %b to <16 x i8>
+// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x half>
+// CHECK: [[EXTR:%.*]] = extractelement <8 x half> [[TMP1]], i32 7
+// CHECK: [[MULX:%.*]] = call half @llvm.aarch64.neon.fmulx.f16(half %a, half [[EXTR]])
+// CHECK: ret half [[MULX]]
float16_t test_vmulxh_laneq_f16(float16_t a, float16x8_t b) {
return vmulxh_laneq_f16(a, b, 7);
}
-*/
// CHECK-LABEL: test_vmaxv_f16
// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <8 x i8>
@@ -1350,16 +1355,13 @@ float16x8_t test_vbslq_f16(uint16x8_t a, float16x8_t b, float16x8_t c) {
// CHECK-LABEL: test_vzip_f16
// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x4x2_t, align 8
// CHECK: [[__RET_I:%.*]] = alloca %struct.float16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <4 x half>*
// CHECK: [[VZIP0_I:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 0, i32 4, i32 1, i32 5>
// CHECK: store <4 x half> [[VZIP0_I]], <4 x half>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <4 x half>, <4 x half>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
// CHECK: store <4 x half> [[VZIP1_I]], <4 x half>* [[TMP2]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.float16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 16, i32 8, i1 false)
float16x4x2_t test_vzip_f16(float16x4_t a, float16x4_t b) {
return vzip_f16(a, b);
}
@@ -1367,16 +1369,13 @@ float16x4x2_t test_vzip_f16(float16x4_t a, float16x4_t b) {
// CHECK-LABEL: test_vzipq_f16
// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x8x2_t, align 16
// CHECK: [[__RET_I:%.*]] = alloca %struct.float16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x half>*
// CHECK: [[VZIP0_I:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
// CHECK: store <8 x half> [[VZIP0_I]], <8 x half>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x half>, <8 x half>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
// CHECK: store <8 x half> [[VZIP1_I]], <8 x half>* [[TMP2]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.float16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 32, i32 16, i1 false)
float16x8x2_t test_vzipq_f16(float16x8_t a, float16x8_t b) {
return vzipq_f16(a, b);
}
@@ -1384,16 +1383,13 @@ float16x8x2_t test_vzipq_f16(float16x8_t a, float16x8_t b) {
// CHECK-LABEL: test_vuzp_f16
// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x4x2_t, align 8
// CHECK: [[__RET_I:%.*]] = alloca %struct.float16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <4 x half>*
// CHECK: [[VZIP0_I:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
// CHECK: store <4 x half> [[VZIP0_I]], <4 x half>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <4 x half>, <4 x half>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
// CHECK: store <4 x half> [[VZIP1_I]], <4 x half>* [[TMP2]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.float16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 16, i32 8, i1 false)
float16x4x2_t test_vuzp_f16(float16x4_t a, float16x4_t b) {
return vuzp_f16(a, b);
}
@@ -1401,16 +1397,13 @@ float16x4x2_t test_vuzp_f16(float16x4_t a, float16x4_t b) {
// CHECK-LABEL: test_vuzpq_f16
// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x8x2_t, align 16
// CHECK: [[__RET_I:%.*]] = alloca %struct.float16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x half>*
// CHECK: [[VZIP0_I:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
// CHECK: store <8 x half> [[VZIP0_I]], <8 x half>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x half>, <8 x half>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
// CHECK: store <8 x half> [[VZIP1_I]], <8 x half>* [[TMP2]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.float16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 32, i32 16, i1 false)
float16x8x2_t test_vuzpq_f16(float16x8_t a, float16x8_t b) {
return vuzpq_f16(a, b);
}
@@ -1418,16 +1411,13 @@ float16x8x2_t test_vuzpq_f16(float16x8_t a, float16x8_t b) {
// CHECK-LABEL: test_vtrn_f16
// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x4x2_t, align 8
// CHECK: [[__RET_I:%.*]] = alloca %struct.float16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <4 x half>*
// CHECK: [[VZIP0_I:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 0, i32 4, i32 2, i32 6>
// CHECK: store <4 x half> [[VZIP0_I]], <4 x half>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <4 x half>, <4 x half>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
// CHECK: store <4 x half> [[VZIP1_I]], <4 x half>* [[TMP2]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.float16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 16, i32 8, i1 false)
float16x4x2_t test_vtrn_f16(float16x4_t a, float16x4_t b) {
return vtrn_f16(a, b);
}
@@ -1435,16 +1425,13 @@ float16x4x2_t test_vtrn_f16(float16x4_t a, float16x4_t b) {
// CHECK-LABEL: test_vtrnq_f16
// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x8x2_t, align 16
// CHECK: [[__RET_I:%.*]] = alloca %struct.float16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x half>*
// CHECK: [[VZIP0_I:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14>
// CHECK: store <8 x half> [[VZIP0_I]], <8 x half>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x half>, <8 x half>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
// CHECK: store <8 x half> [[VZIP1_I]], <8 x half>* [[TMP2]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.float16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP5]], i8* [[TMP6]], i64 32, i32 16, i1 false)
float16x8x2_t test_vtrnq_f16(float16x8_t a, float16x8_t b) {
return vtrnq_f16(a, b);
}
diff --git a/test/CodeGen/aarch64-varargs-ms.c b/test/CodeGen/aarch64-varargs-ms.c
index f3ff9603c9c2..c27e78570baa 100644
--- a/test/CodeGen/aarch64-varargs-ms.c
+++ b/test/CodeGen/aarch64-varargs-ms.c
@@ -3,7 +3,7 @@
#include <stdarg.h>
int simple_int(va_list ap) {
-// CHECK-LABEL: define i32 @simple_int
+// CHECK-LABEL: define dso_local i32 @simple_int
return va_arg(ap, int);
// CHECK: [[ADDR:%[a-z_0-9]+]] = bitcast i8* %argp.cur to i32*
// CHECK: [[RESULT:%[a-z_0-9]+]] = load i32, i32* [[ADDR]]
diff --git a/test/CodeGen/address-safety-attr-flavors.cpp b/test/CodeGen/address-safety-attr-flavors.cpp
new file mode 100644
index 000000000000..815cbae78a67
--- /dev/null
+++ b/test/CodeGen/address-safety-attr-flavors.cpp
@@ -0,0 +1,75 @@
+// Make sure the sanitize_address attribute is emitted when using ASan, KASan or
+// HWASan. Either __attribute__((no_sanitize("address")) or
+// __attribute__((no_sanitize("kernel-address")) disables both ASan and KASan
+// instrumentation.
+// Same for __attribute__((no_sanitize("hwaddress")) and
+// __attribute__((no_sanitize("kernel-hwddress")) and HWASan and KHWASan.
+
+// RUN: %clang_cc1 -triple i386-unknown-linux -disable-O0-optnone \
+// RUN: -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-NOASAN %s
+
+// RUN: %clang_cc1 -triple i386-unknown-linux -fsanitize=address \
+// RUN: -disable-O0-optnone -emit-llvm -o - %s | \
+// RUN: FileCheck -check-prefix=CHECK-ASAN %s
+
+// RUN: %clang_cc1 -triple i386-unknown-linux -fsanitize=kernel-address \
+// RUN: -disable-O0-optnone -emit-llvm -o - %s | \
+// RUN: FileCheck -check-prefix=CHECK-KASAN %s
+
+// RUN: %clang_cc1 -triple i386-unknown-linux -fsanitize=hwaddress \
+// RUN: -disable-O0-optnone -emit-llvm -o - %s | \
+// RUN: FileCheck -check-prefix=CHECK-HWASAN %s
+
+// RUN: %clang_cc1 -triple i386-unknown-linux -fsanitize=kernel-hwaddress \
+// RUN: -disable-O0-optnone -emit-llvm -o - %s | \
+// RUN: FileCheck -check-prefix=CHECK-KHWASAN %s
+
+int HasSanitizeAddress() { return 1; }
+// CHECK-NOASAN: {{Function Attrs: noinline nounwind$}}
+// CHECK-ASAN: Function Attrs: noinline nounwind sanitize_address
+// CHECK-KASAN: Function Attrs: noinline nounwind sanitize_address
+// CHECK-HWASAN: Function Attrs: noinline nounwind sanitize_hwaddress
+// CHECK-KHWASAN: Function Attrs: noinline nounwind sanitize_hwaddress
+
+__attribute__((no_sanitize("address"))) int NoSanitizeQuoteAddress() {
+ return 0;
+}
+// CHECK-NOASAN: {{Function Attrs: noinline nounwind$}}
+// CHECK-ASAN: {{Function Attrs: noinline nounwind$}}
+// CHECK-KASAN: {{Function Attrs: noinline nounwind$}}
+// CHECK-HWASAN: {{Function Attrs: noinline nounwind sanitize_hwaddress$}}
+// CHECK-KHWASAN: {{Function Attrs: noinline nounwind sanitize_hwaddress$}}
+
+__attribute__((no_sanitize_address)) int NoSanitizeAddress() { return 0; }
+// CHECK-NOASAN: {{Function Attrs: noinline nounwind$}}
+// CHECK-ASAN: {{Function Attrs: noinline nounwind$}}
+// CHECK-KASAN: {{Function Attrs: noinline nounwind$}}
+// CHECK-HWASAN: {{Function Attrs: noinline nounwind sanitize_hwaddress$}}
+// CHECK-KHWASAN: {{Function Attrs: noinline nounwind sanitize_hwaddress$}}
+
+__attribute__((no_sanitize("kernel-address"))) int NoSanitizeKernelAddress() {
+ return 0;
+}
+// CHECK-NOASAN: {{Function Attrs: noinline nounwind$}}
+// CHECK-ASAN: {{Function Attrs: noinline nounwind$}}
+// CHECK-KASAN: {{Function Attrs: noinline nounwind$}}
+// CHECK-HWASAN: {{Function Attrs: noinline nounwind sanitize_hwaddress$}}
+// CHECK-KHWASAN: {{Function Attrs: noinline nounwind sanitize_hwaddress$}}
+
+__attribute__((no_sanitize("hwaddress"))) int NoSanitizeHWAddress() {
+ return 0;
+}
+// CHECK-NOASAN: {{Function Attrs: noinline nounwind$}}
+// CHECK-ASAN: {{Function Attrs: noinline nounwind sanitize_address$}}
+// CHECK-KASAN: {{Function Attrs: noinline nounwind sanitize_address$}}
+// CHECK-HWASAN: {{Function Attrs: noinline nounwind$}}
+// CHECK-KHWASAN: {{Function Attrs: noinline nounwind$}}
+
+__attribute__((no_sanitize("kernel-hwaddress"))) int NoSanitizeKernelHWAddress() {
+ return 0;
+}
+// CHECK-NOASAN: {{Function Attrs: noinline nounwind$}}
+// CHECK-ASAN: {{Function Attrs: noinline nounwind sanitize_address$}}
+// CHECK-KASAN: {{Function Attrs: noinline nounwind sanitize_address$}}
+// CHECK-HWASAN: {{Function Attrs: noinline nounwind$}}
+// CHECK-KHWASAN: {{Function Attrs: noinline nounwind$}}
diff --git a/test/CodeGen/address-safety-attr-kasan-hwasan.cpp b/test/CodeGen/address-safety-attr-kasan-hwasan.cpp
deleted file mode 100644
index 7a84b798e4b9..000000000000
--- a/test/CodeGen/address-safety-attr-kasan-hwasan.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-// Make sure the sanitize_address attribute is emitted when using both ASan and KASan.
-// Also document that __attribute__((no_sanitize_address)) doesn't disable KASan instrumentation.
-
-/// RUN: %clang_cc1 -triple i386-unknown-linux -disable-O0-optnone -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-NOASAN %s
-/// RUN: %clang_cc1 -triple i386-unknown-linux -fsanitize=address -disable-O0-optnone -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-ASAN %s
-/// RUN: %clang_cc1 -triple i386-unknown-linux -fsanitize=kernel-address -disable-O0-optnone -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-KASAN %s
-/// RUN: %clang_cc1 -triple i386-unknown-linux -fsanitize=hwaddress -disable-O0-optnone -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-HWASAN %s
-
-int HasSanitizeAddress() {
- return 1;
-}
-// CHECK-NOASAN: {{Function Attrs: noinline nounwind$}}
-// CHECK-ASAN: Function Attrs: noinline nounwind sanitize_address
-// CHECK-KASAN: Function Attrs: noinline nounwind sanitize_address
-// CHECK-HWASAN: Function Attrs: noinline nounwind sanitize_hwaddress
-
-__attribute__((no_sanitize("address")))
-int NoSanitizeQuoteAddress() {
- return 0;
-}
-// CHECK-NOASAN: {{Function Attrs: noinline nounwind$}}
-// CHECK-ASAN: {{Function Attrs: noinline nounwind$}}
-// CHECK-KASAN: {{Function Attrs: noinline nounwind sanitize_address$}}
-// CHECK-HWASAN: {{Function Attrs: noinline nounwind sanitize_hwaddress$}}
-
-__attribute__((no_sanitize_address))
-int NoSanitizeAddress() {
- return 0;
-}
-// CHECK-NOASAN: {{Function Attrs: noinline nounwind$}}
-// CHECK-ASAN: {{Function Attrs: noinline nounwind$}}
-// CHECK-KASAN: {{Function Attrs: noinline nounwind sanitize_address$}}
-// CHECK-HWASAN: {{Function Attrs: noinline nounwind sanitize_hwaddress$}}
-
-__attribute__((no_sanitize("kernel-address")))
-int NoSanitizeKernelAddress() {
- return 0;
-}
-
-// CHECK-NOASAN: {{Function Attrs: noinline nounwind$}}
-// CHECK-ASAN: {{Function Attrs: noinline nounwind sanitize_address$}}
-// CHECK-KASAN: {{Function Attrs: noinline nounwind$}}
-// CHECK-HWASAN: {{Function Attrs: noinline nounwind sanitize_hwaddress$}}
-
-__attribute__((no_sanitize("hwaddress")))
-int NoSanitizeHWAddress() {
- return 0;
-}
-
-// CHECK-NOASAN: {{Function Attrs: noinline nounwind$}}
-// CHECK-ASAN: {{Function Attrs: noinline nounwind sanitize_address$}}
-// CHECK-KASAN: {{Function Attrs: noinline nounwind sanitize_address$}}
-// CHECK-HWASAN: {{Function Attrs: noinline nounwind$}}
diff --git a/test/CodeGen/address-safety-attr-kasan.cpp b/test/CodeGen/address-safety-attr-kasan.cpp
deleted file mode 100644
index 603134db69fb..000000000000
--- a/test/CodeGen/address-safety-attr-kasan.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-// Make sure the sanitize_address attribute is emitted when using both ASan and KASan.
-// Also document that __attribute__((no_sanitize_address)) doesn't disable KASan instrumentation.
-
-/// RUN: %clang_cc1 -triple i386-unknown-linux -disable-O0-optnone -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-NOASAN %s
-/// RUN: %clang_cc1 -triple i386-unknown-linux -fsanitize=address -disable-O0-optnone -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-ASAN %s
-/// RUN: %clang_cc1 -triple i386-unknown-linux -fsanitize=kernel-address -disable-O0-optnone -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-KASAN %s
-
-int HasSanitizeAddress() {
- return 1;
-}
-// CHECK-NOASAN: {{Function Attrs: noinline nounwind$}}
-// CHECK-ASAN: Function Attrs: noinline nounwind sanitize_address
-// CHECK-KASAN: Function Attrs: noinline nounwind sanitize_address
-
-__attribute__((no_sanitize("address")))
-int NoSanitizeQuoteAddress() {
- return 0;
-}
-// CHECK-NOASAN: {{Function Attrs: noinline nounwind$}}
-// CHECK-ASAN: {{Function Attrs: noinline nounwind$}}
-// CHECK-KASAN: {{Function Attrs: noinline nounwind sanitize_address$}}
-
-__attribute__((no_sanitize_address))
-int NoSanitizeAddress() {
- return 0;
-}
-// CHECK-NOASAN: {{Function Attrs: noinline nounwind$}}
-// CHECK-ASAN: {{Function Attrs: noinline nounwind$}}
-// CHECK-KASAN: {{Function Attrs: noinline nounwind sanitize_address$}}
-
-__attribute__((no_sanitize("kernel-address")))
-int NoSanitizeKernelAddress() {
- return 0;
-}
-
-// CHECK-NOASAN: {{Function Attrs: noinline nounwind$}}
-// CHECK-ASAN: {{Function Attrs: noinline nounwind sanitize_address$}}
-// CHECK-KASAN: {{Function Attrs: noinline nounwind$}}
diff --git a/test/CodeGen/address-sanitizer-and-array-cookie.cpp b/test/CodeGen/address-sanitizer-and-array-cookie.cpp
index ea8953778916..e2267a10c2be 100644
--- a/test/CodeGen/address-sanitizer-and-array-cookie.cpp
+++ b/test/CodeGen/address-sanitizer-and-array-cookie.cpp
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 -triple x86_64-gnu-linux -emit-llvm -o - %s | FileCheck %s -check-prefix=PLAIN
// RUN: %clang_cc1 -triple x86_64-gnu-linux -emit-llvm -o - -fsanitize=address %s | FileCheck %s -check-prefix=ASAN
+// RUN: %clang_cc1 -triple x86_64-gnu-linux -emit-llvm -o - -fsanitize=address -fsanitize-address-poison-class-member-array-new-cookie %s | FileCheck %s -check-prefix=ASAN-POISON-ALL-NEW-ARRAY
typedef __typeof__(sizeof(0)) size_t;
namespace std {
@@ -8,6 +9,7 @@ namespace std {
}
void *operator new[](size_t, const std::nothrow_t &) throw();
void *operator new[](size_t, char *);
+void *operator new[](size_t, int, int);
struct C {
int x;
@@ -53,3 +55,10 @@ C *CallPlacementNew() {
}
// ASAN-LABEL: CallPlacementNew
// ASAN-NOT: __asan_poison_cxx_array_cookie
+
+C *CallNewWithArgs() {
+// ASAN-LABEL: CallNewWithArgs
+// ASAN-NOT: call void @__asan_poison_cxx_array_cookie
+// ASAN-POISON-ALL-NEW-ARRAY: call void @__asan_poison_cxx_array_cookie
+ return new (123, 456) C[20];
+}
diff --git a/test/CodeGen/address-space.c b/test/CodeGen/address-space.c
index 28b3954ab7d2..d6a40f33029f 100644
--- a/test/CodeGen/address-space.c
+++ b/test/CodeGen/address-space.c
@@ -1,6 +1,5 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm < %s | FileCheck -check-prefixes=CHECK,X86,GIZ %s
-// RUN: %clang_cc1 -triple amdgcn -emit-llvm < %s | FileCheck -check-prefixes=CHECK,PIZ %s
-// RUN: %clang_cc1 -triple amdgcn---amdgiz -emit-llvm < %s | FileCheck -check-prefixes=CHECK,AMDGIZ,GIZ %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm < %s | FileCheck -check-prefixes=CHECK,X86 %s
+// RUN: %clang_cc1 -triple amdgcn -emit-llvm < %s | FileCheck -check-prefixes=CHECK,AMDGCN %s
// CHECK: @foo = common addrspace(1) global
int foo __attribute__((address_space(1)));
@@ -25,12 +24,10 @@ __attribute__((address_space(2))) int *A, *B;
// CHECK-LABEL: define void @test3()
// X86: load i32 addrspace(2)*, i32 addrspace(2)** @B
-// AMDGIZ: load i32 addrspace(2)*, i32 addrspace(2)** addrspacecast (i32 addrspace(2)* addrspace(1)* @B to i32 addrspace(2)**)
-// PIZ: load i32 addrspace(2)*, i32 addrspace(2)* addrspace(4)* addrspacecast (i32 addrspace(2)* addrspace(1)* @B to i32 addrspace(2)* addrspace(4)*)
+// AMDGCN: load i32 addrspace(2)*, i32 addrspace(2)** addrspacecast (i32 addrspace(2)* addrspace(1)* @B to i32 addrspace(2)**)
// CHECK: load i32, i32 addrspace(2)*
// X86: load i32 addrspace(2)*, i32 addrspace(2)** @A
-// AMDGIZ: load i32 addrspace(2)*, i32 addrspace(2)** addrspacecast (i32 addrspace(2)* addrspace(1)* @A to i32 addrspace(2)**)
-// PIZ: load i32 addrspace(2)*, i32 addrspace(2)* addrspace(4)* addrspacecast (i32 addrspace(2)* addrspace(1)* @A to i32 addrspace(2)* addrspace(4)*)
+// AMDGCN: load i32 addrspace(2)*, i32 addrspace(2)** addrspacecast (i32 addrspace(2)* addrspace(1)* @A to i32 addrspace(2)**)
// CHECK: store i32 {{.*}}, i32 addrspace(2)*
void test3() {
*A = *B;
@@ -42,10 +39,8 @@ typedef struct {
} MyStruct;
// CHECK-LABEL: define void @test4(
-// GIZ: call void @llvm.memcpy.p0i8.p2i8
-// GIZ: call void @llvm.memcpy.p2i8.p0i8
-// PIZ: call void @llvm.memcpy.p4i8.p2i8
-// PIZ: call void @llvm.memcpy.p2i8.p4i8
+// CHECK: call void @llvm.memcpy.p0i8.p2i8
+// CHECK: call void @llvm.memcpy.p2i8.p0i8
void test4(MyStruct __attribute__((address_space(2))) *pPtr) {
MyStruct s = pPtr[0];
pPtr[0] = s;
diff --git a/test/CodeGen/addrsig.c b/test/CodeGen/addrsig.c
new file mode 100644
index 000000000000..d7141092bb35
--- /dev/null
+++ b/test/CodeGen/addrsig.c
@@ -0,0 +1,20 @@
+// REQUIRES: x86-registered-target
+
+// RUN: %clang_cc1 -triple=x86_64-unknown-linux -S %s -faddrsig -O -o - | FileCheck --check-prefix=ADDRSIG %s
+// RUN: %clang_cc1 -triple=x86_64-unknown-linux -S %s -O -o - | FileCheck --check-prefix=NO-ADDRSIG %s
+
+// ADDRSIG: .addrsig
+// ADDRSIG: .addrsig_sym g1
+// ADDRSIG-NOT: .addrsig_sym g2
+
+// NO-ADDRSIG-NOT: .addrsig
+
+extern const int g1[], g2[];
+
+const int *f1() {
+ return g1;
+}
+
+int f2() {
+ return g2[0];
+}
diff --git a/test/CodeGen/adx-builtins.c b/test/CodeGen/adx-builtins.c
index 8738c5d17715..ac33367d0ebd 100644
--- a/test/CodeGen/adx-builtins.c
+++ b/test/CodeGen/adx-builtins.c
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -ffreestanding -target-feature +adx -emit-llvm -o - %s | FileCheck %s
-#include <x86intrin.h>
+#include <immintrin.h>
unsigned char test_addcarryx_u32(unsigned char __cf, unsigned int __x,
unsigned int __y, unsigned int *__p) {
diff --git a/test/CodeGen/aggregate-assign-call.c b/test/CodeGen/aggregate-assign-call.c
new file mode 100644
index 000000000000..83983722db94
--- /dev/null
+++ b/test/CodeGen/aggregate-assign-call.c
@@ -0,0 +1,93 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O1 -S -emit-llvm -o - %s | FileCheck %s --check-prefix=O1
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O0 -S -emit-llvm -o - %s | FileCheck %s --check-prefix=O0
+//
+// Ensure that we place appropriate lifetime markers around indirectly returned
+// temporaries, and that the lifetime.ends appear in a timely manner.
+//
+// -O1 is used so lifetime markers actually get emitted.
+
+struct S {
+ int ns[40];
+};
+
+struct S foo(void);
+
+// CHECK-LABEL: define dso_local void @bar
+struct S bar() {
+ // O0-NOT: @llvm.lifetime.start
+ // O0-NOT: @llvm.lifetime.end
+
+ struct S r;
+ // O1: call void @llvm.lifetime.start.p0i8({{[^,]*}}, i8* nonnull %[[TMP1:[^)]+]])
+ // O1: call void @foo
+ r = foo();
+ // O1: call void @llvm.lifetime.end.p0i8({{[^,]*}}, i8* nonnull %[[TMP1]])
+
+ // O1: call void @llvm.lifetime.start.p0i8({{[^,]*}}, i8* nonnull %[[TMP2:[^)]+]])
+ // O1: call void @foo
+ r = foo();
+ // O1: call void @llvm.lifetime.end.p0i8({{[^,]*}}, i8* nonnull %[[TMP2]])
+
+ // O1: call void @llvm.lifetime.start.p0i8({{[^,]*}}, i8* nonnull %[[TMP3:[^)]+]])
+ // O1: call void @foo
+ r = foo();
+ // O1: call void @llvm.lifetime.end.p0i8({{[^,]*}}, i8* nonnull %[[TMP3]])
+
+ return r;
+}
+
+struct S foo_int(int);
+
+// Be sure that we're placing the lifetime.end so that all paths go through it.
+// Since this function turns out to be large-ish, optnone to hopefully keep it
+// stable.
+// CHECK-LABEL: define dso_local void @baz
+__attribute__((optnone))
+struct S baz(int i, volatile int *j) {
+ // O0-NOT: @llvm.lifetime.start
+ // O0-NOT: @llvm.lifetime.end
+
+ struct S r;
+ // O1: %[[TMP1_ALLOCA:[^ ]+]] = alloca %struct.S
+ // O1: %[[TMP2_ALLOCA:[^ ]+]] = alloca %struct.S
+ // O1: br label %[[DO_BODY:.+]]
+
+ do {
+ // O1: [[DO_BODY]]:
+ // O1: %[[P:[^ ]+]] = bitcast %struct.S* %[[TMP1_ALLOCA]] to i8*
+ // O1: call void @llvm.lifetime.start.p0i8({{[^,]*}}, i8* %[[P]])
+ // O1: br i1 {{[^,]+}}, label %[[IF_THEN:[^,]+]], label %[[IF_END:[^,]+]]
+ //
+ // O1: [[IF_THEN]]:
+ // O1: %[[P:[^ ]+]] = bitcast %struct.S* %[[TMP1_ALLOCA]] to i8*
+ // O1: call void @llvm.lifetime.end.p0i8({{[^,]*}}, i8* %[[P]])
+ // O1: br label %[[DO_END:.*]]
+ //
+ // O1: [[IF_END]]:
+ // O1: call void @foo_int(%struct.S* sret %[[TMP1_ALLOCA]],
+ // O1: call void @llvm.memcpy
+ // O1: %[[P:[^ ]+]] = bitcast %struct.S* %[[TMP1_ALLOCA]] to i8*
+ // O1: call void @llvm.lifetime.end.p0i8({{[^,]*}}, i8* %[[P]])
+ // O1: %[[P:[^ ]+]] = bitcast %struct.S* %[[TMP2_ALLOCA]] to i8*
+ // O1: call void @llvm.lifetime.start.p0i8({{[^,]*}}, i8* %[[P]])
+ // O1: call void @foo_int(%struct.S* sret %[[TMP2_ALLOCA]],
+ // O1: call void @llvm.memcpy
+ // O1: %[[P:[^ ]+]] = bitcast %struct.S* %[[TMP2_ALLOCA]] to i8*
+ // O1: call void @llvm.lifetime.end.p0i8({{[^,]*}}, i8* %[[P]])
+ // O1: br label %[[DO_COND:.*]]
+ //
+ // O1: [[DO_COND]]:
+ // O1: br label %[[DO_BODY]]
+ r = foo_int(({
+ if (*j)
+ break;
+ i++;
+ }));
+
+ r = foo_int(i++);
+ } while (1);
+
+ // O1: [[DO_END]]:
+ // O1-NEXT: ret void
+ return r;
+}
diff --git a/test/CodeGen/alias.c b/test/CodeGen/alias.c
index 6ec12702d86b..78b020454a9f 100644
--- a/test/CodeGen/alias.c
+++ b/test/CodeGen/alias.c
@@ -23,20 +23,20 @@ const int wacom_usb_ids[] = {1, 1, 2, 3, 5, 8, 13, 0};
extern const int __mod_usb_device_table __attribute__ ((alias("wacom_usb_ids")));
// CHECKBASIC-DAG: @__mod_usb_device_table = alias i32, getelementptr inbounds ([8 x i32], [8 x i32]* @wacom_usb_ids, i32 0, i32 0)
// CHECKASM-DAG: .globl __mod_usb_device_table
-// CHECKASM-DAG: __mod_usb_device_table = wacom_usb_ids
+// CHECKASM-DAG: .set __mod_usb_device_table, wacom_usb_ids
// CHECKASM-NOT: .size __mod_usb_device_table
extern int g1;
extern int g1 __attribute((alias("g0")));
// CHECKBASIC-DAG: @g1 = alias i32, i32* @g0
// CHECKASM-DAG: .globl g1
-// CHECKASM-DAG: g1 = g0
+// CHECKASM-DAG: .set g1, g0
// CHECKASM-NOT: .size g1
extern __thread int __libc_errno __attribute__ ((alias ("TL_WITH_ALIAS")));
// CHECKBASIC-DAG: @__libc_errno = thread_local alias i32, i32* @TL_WITH_ALIAS
// CHECKASM-DAG: .globl __libc_errno
-// CHECKASM-DAG: __libc_errno = TL_WITH_ALIAS
+// CHECKASM-DAG: .set __libc_errno, TL_WITH_ALIAS
// CHECKASM-NOT: .size __libc_errno
void f0(void) { }
diff --git a/test/CodeGen/arm-aapcs-vfp.c b/test/CodeGen/arm-aapcs-vfp.c
index 38044cbb1e23..ba5a969b0edc 100644
--- a/test/CodeGen/arm-aapcs-vfp.c
+++ b/test/CodeGen/arm-aapcs-vfp.c
@@ -17,11 +17,7 @@
// RUN: -ffreestanding \
// RUN: -emit-llvm -w -o - %s | FileCheck -check-prefix=CHECK64 %s
-#ifdef __arm64__
#include <arm_neon.h>
-#else
-#include <arm_neon.h>
-#endif
struct homogeneous_struct {
float f[2];
diff --git a/test/CodeGen/arm-arguments.c b/test/CodeGen/arm-arguments.c
index ec3e1734b0c3..ef4e76054ff8 100644
--- a/test/CodeGen/arm-arguments.c
+++ b/test/CodeGen/arm-arguments.c
@@ -208,13 +208,13 @@ float32x4_t f35(int i, s35_with_align s1, s35_with_align s2) {
// APCS-GNU: %[[a:.*]] = alloca %struct.s35, align 16
// APCS-GNU: %[[b:.*]] = bitcast %struct.s35* %[[a]] to i8*
// APCS-GNU: %[[c:.*]] = bitcast %struct.s35* %0 to i8*
-// APCS-GNU: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %[[b]], i8* %[[c]]
+// APCS-GNU: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align {{[0-9]+}} %[[b]], i8* align {{[0-9]+}} %[[c]]
// APCS-GNU: %[[d:.*]] = bitcast %struct.s35* %[[a]] to <4 x float>*
// APCS-GNU: load <4 x float>, <4 x float>* %[[d]], align 16
// AAPCS-LABEL: define arm_aapcscc <4 x float> @f35(i32 %i, %struct.s35* byval align 8, %struct.s35* byval align 8)
// AAPCS: %[[a:.*]] = alloca %struct.s35, align 16
// AAPCS: %[[b:.*]] = bitcast %struct.s35* %[[a]] to i8*
// AAPCS: %[[c:.*]] = bitcast %struct.s35* %0 to i8*
-// AAPCS: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %[[b]], i8* %[[c]]
+// AAPCS: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 %[[b]], i8* align 8 %[[c]]
// AAPCS: %[[d:.*]] = bitcast %struct.s35* %[[a]] to <4 x float>*
// AAPCS: load <4 x float>, <4 x float>* %[[d]], align 16
diff --git a/test/CodeGen/arm-build-attributes.c b/test/CodeGen/arm-build-attributes.c
new file mode 100644
index 000000000000..ceb97d153f81
--- /dev/null
+++ b/test/CodeGen/arm-build-attributes.c
@@ -0,0 +1,4 @@
+// RUN: %clang --target=arm-none-eabi -x c - -o - -S < %s -mcpu=cortex-a5 -mfpu=vfpv4-d16 | FileCheck %s
+// REQUIRES: arm-registered-target
+// CHECK: .fpu vfpv4-d16
+void foo() {}
diff --git a/test/CodeGen/arm-fp16-arguments.c b/test/CodeGen/arm-fp16-arguments.c
index 65f076ac3ca8..d739f4b9c66a 100644
--- a/test/CodeGen/arm-fp16-arguments.c
+++ b/test/CodeGen/arm-fp16-arguments.c
@@ -25,3 +25,27 @@ __fp16 t2() { return g; }
// HARD: ret float [[BITCAST]]
// NATIVE: [[LOAD:%.*]] = load half, half* @g
// NATIVE: ret half [[LOAD]]
+
+_Float16 h;
+
+void t3(_Float16 a) { h = a; }
+// SOFT: define void @t3(i32 [[PARAM:%.*]])
+// SOFT: [[TRUNC:%.*]] = trunc i32 [[PARAM]] to i16
+// HARD: define arm_aapcs_vfpcc void @t3(float [[PARAM:%.*]])
+// HARD: [[BITCAST:%.*]] = bitcast float [[PARAM]] to i32
+// HARD: [[TRUNC:%.*]] = trunc i32 [[BITCAST]] to i16
+// CHECK: store i16 [[TRUNC]], i16* bitcast (half* @h to i16*)
+// NATIVE: define void @t3(half [[PARAM:%.*]])
+// NATIVE: store half [[PARAM]], half* @h
+
+_Float16 t4() { return h; }
+// SOFT: define i32 @t4()
+// HARD: define arm_aapcs_vfpcc float @t4()
+// NATIVE: define half @t4()
+// CHECK: [[LOAD:%.*]] = load i16, i16* bitcast (half* @h to i16*)
+// CHECK: [[ZEXT:%.*]] = zext i16 [[LOAD]] to i32
+// SOFT: ret i32 [[ZEXT]]
+// HARD: [[BITCAST:%.*]] = bitcast i32 [[ZEXT]] to float
+// HARD: ret float [[BITCAST]]
+// NATIVE: [[LOAD:%.*]] = load half, half* @h
+// NATIVE: ret half [[LOAD]]
diff --git a/test/CodeGen/arm-long-calls.c b/test/CodeGen/arm-long-calls.c
index cff2d6607113..78aee77c8f6d 100644
--- a/test/CodeGen/arm-long-calls.c
+++ b/test/CodeGen/arm-long-calls.c
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -triple thumbv7-apple-ios5 -target-feature +long-calls -emit-llvm -o - %s | FileCheck -check-prefix=LONGCALL %s
// RUN: %clang_cc1 -triple thumbv7-apple-ios5 -emit-llvm -o - %s | FileCheck -check-prefix=NOLONGCALL %s
-// LONGCALL: attributes #0 = { {{.*}} "target-features"="+long-calls,+thumb-mode"
-// NOLONGCALL-NOT: attributes #0 = { {{.*}} "target-features"="+long-calls,+thumb-mode"
+// LONGCALL: attributes #0 = { {{.*}} "target-features"="+armv7-a,+long-calls,+thumb-mode"
+// NOLONGCALL-NOT: attributes #0 = { {{.*}} "target-features"="+armv7-a,+long-calls,+thumb-mode"
int foo1(int a) { return a; }
diff --git a/test/CodeGen/arm-neon-directed-rounding.c b/test/CodeGen/arm-neon-directed-rounding.c
index b06808a77cd1..5119f9dbf413 100644
--- a/test/CodeGen/arm-neon-directed-rounding.c
+++ b/test/CodeGen/arm-neon-directed-rounding.c
@@ -1,87 +1,128 @@
-// RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu cortex-a57 -ffreestanding -disable-O0-optnone -emit-llvm %s -o - | opt -S -mem2reg | FileCheck %s
+// RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu cortex-a57 \
+// RUN: -ffreestanding -disable-O0-optnone -emit-llvm %s -o - | \
+// RUN: opt -S -mem2reg | FileCheck -check-prefixes=CHECK,CHECK-A32 %s
+// RUN: %clang_cc1 -triple arm64-linux-gnueabihf -target-feature +neon \
+// RUN: -ffreestanding -disable-O0-optnone -emit-llvm %s -o - | \
+// RUN: opt -S -mem2reg | FileCheck -check-prefixes=CHECK,CHECK-A64 %s
#include <arm_neon.h>
-// CHECK-LABEL: define <2 x float> @test_vrnda_f32(<2 x float> %a) #0 {
-// CHECK: [[VRNDA_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrinta.v2f32(<2 x float> %a) #2
-// CHECK: ret <2 x float> [[VRNDA_V1_I]]
+// CHECK-LABEL: define <2 x float> @test_vrnda_f32(<2 x float> %a)
+// CHECK-A32: [[VRNDA_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrinta.v2f32(<2 x float> %a)
+// CHECK-A64: [[VRNDA_V1_I:%.*]] = call <2 x float> @llvm.round.v2f32(<2 x float> %a)
+// CHECK: ret <2 x float> [[VRNDA_V1_I]]
float32x2_t test_vrnda_f32(float32x2_t a) {
return vrnda_f32(a);
}
-// CHECK-LABEL: define <4 x float> @test_vrndaq_f32(<4 x float> %a) #0 {
-// CHECK: [[VRNDAQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrinta.v4f32(<4 x float> %a) #2
-// CHECK: ret <4 x float> [[VRNDAQ_V1_I]]
+// CHECK-LABEL: define <4 x float> @test_vrndaq_f32(<4 x float> %a)
+// CHECK-A32: [[VRNDAQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrinta.v4f32(<4 x float> %a)
+// CHECK-A64: [[VRNDAQ_V1_I:%.*]] = call <4 x float> @llvm.round.v4f32(<4 x float> %a)
+// CHECK: ret <4 x float> [[VRNDAQ_V1_I]]
float32x4_t test_vrndaq_f32(float32x4_t a) {
return vrndaq_f32(a);
}
-// CHECK-LABEL: define <2 x float> @test_vrndm_f32(<2 x float> %a) #0 {
-// CHECK: [[VRNDM_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrintm.v2f32(<2 x float> %a) #2
-// CHECK: ret <2 x float> [[VRNDM_V1_I]]
+// CHECK-LABEL: define <2 x float> @test_vrndm_f32(<2 x float> %a)
+// CHECK-A32: [[VRNDM_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrintm.v2f32(<2 x float> %a)
+// CHECK-A64: [[VRNDM_V1_I:%.*]] = call <2 x float> @llvm.floor.v2f32(<2 x float> %a)
+// CHECK: ret <2 x float> [[VRNDM_V1_I]]
float32x2_t test_vrndm_f32(float32x2_t a) {
return vrndm_f32(a);
}
-// CHECK-LABEL: define <4 x float> @test_vrndmq_f32(<4 x float> %a) #0 {
-// CHECK: [[VRNDMQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrintm.v4f32(<4 x float> %a) #2
-// CHECK: ret <4 x float> [[VRNDMQ_V1_I]]
+// CHECK-LABEL: define <4 x float> @test_vrndmq_f32(<4 x float> %a)
+// CHECK-A32: [[VRNDMQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrintm.v4f32(<4 x float> %a)
+// CHECK-A64: [[VRNDMQ_V1_I:%.*]] = call <4 x float> @llvm.floor.v4f32(<4 x float> %a)
+// CHECK: ret <4 x float> [[VRNDMQ_V1_I]]
float32x4_t test_vrndmq_f32(float32x4_t a) {
return vrndmq_f32(a);
}
-// CHECK-LABEL: define <2 x float> @test_vrndn_f32(<2 x float> %a) #0 {
-// CHECK: [[VRNDN_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrintn.v2f32(<2 x float> %a) #2
-// CHECK: ret <2 x float> [[VRNDN_V1_I]]
+// CHECK-LABEL: define <2 x float> @test_vrndn_f32(<2 x float> %a)
+// CHECK-A32: [[VRNDN_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrintn.v2f32(<2 x float> %a)
+// CHECK-A64: [[VRNDN_V1_I:%.*]] = call <2 x float> @llvm.aarch64.neon.frintn.v2f32(<2 x float> %a)
+// CHECK: ret <2 x float> [[VRNDN_V1_I]]
float32x2_t test_vrndn_f32(float32x2_t a) {
return vrndn_f32(a);
}
-// CHECK-LABEL: define <4 x float> @test_vrndnq_f32(<4 x float> %a) #0 {
-// CHECK: [[VRNDNQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrintn.v4f32(<4 x float> %a) #2
-// CHECK: ret <4 x float> [[VRNDNQ_V1_I]]
+// CHECK-LABEL: define <4 x float> @test_vrndnq_f32(<4 x float> %a)
+// CHECK-A32: [[VRNDNQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrintn.v4f32(<4 x float> %a)
+// CHECK-A64: [[VRNDNQ_V1_I:%.*]] = call <4 x float> @llvm.aarch64.neon.frintn.v4f32(<4 x float> %a)
+// CHECK: ret <4 x float> [[VRNDNQ_V1_I]]
float32x4_t test_vrndnq_f32(float32x4_t a) {
return vrndnq_f32(a);
}
-// CHECK-LABEL: define <2 x float> @test_vrndp_f32(<2 x float> %a) #0 {
-// CHECK: [[VRNDP_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrintp.v2f32(<2 x float> %a) #2
-// CHECK: ret <2 x float> [[VRNDP_V1_I]]
+// CHECK-LABEL: define <2 x float> @test_vrndp_f32(<2 x float> %a)
+// CHECK-A32: [[VRNDP_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrintp.v2f32(<2 x float> %a)
+// CHECK-A64: [[VRNDP_V1_I:%.*]] = call <2 x float> @llvm.ceil.v2f32(<2 x float> %a)
+// CHECK: ret <2 x float> [[VRNDP_V1_I]]
float32x2_t test_vrndp_f32(float32x2_t a) {
return vrndp_f32(a);
}
-// CHECK-LABEL: define <4 x float> @test_vrndpq_f32(<4 x float> %a) #0 {
-// CHECK: [[VRNDPQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrintp.v4f32(<4 x float> %a) #2
-// CHECK: ret <4 x float> [[VRNDPQ_V1_I]]
+// CHECK-LABEL: define <4 x float> @test_vrndpq_f32(<4 x float> %a)
+// CHECK-A32: [[VRNDPQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrintp.v4f32(<4 x float> %a)
+// CHECK-A64: [[VRNDPQ_V1_I:%.*]] = call <4 x float> @llvm.ceil.v4f32(<4 x float> %a)
+// CHECK: ret <4 x float> [[VRNDPQ_V1_I]]
float32x4_t test_vrndpq_f32(float32x4_t a) {
return vrndpq_f32(a);
}
-// CHECK-LABEL: define <2 x float> @test_vrndx_f32(<2 x float> %a) #0 {
-// CHECK: [[VRNDX_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrintx.v2f32(<2 x float> %a) #2
-// CHECK: ret <2 x float> [[VRNDX_V1_I]]
+// CHECK-LABEL: define <2 x float> @test_vrndx_f32(<2 x float> %a)
+// CHECK-A32: [[VRNDX_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrintx.v2f32(<2 x float> %a)
+// CHECK-A64: [[VRNDX_V1_I:%.*]] = call <2 x float> @llvm.rint.v2f32(<2 x float> %a)
+// CHECK: ret <2 x float> [[VRNDX_V1_I]]
float32x2_t test_vrndx_f32(float32x2_t a) {
return vrndx_f32(a);
}
-// CHECK-LABEL: define <4 x float> @test_vrndxq_f32(<4 x float> %a) #0 {
-// CHECK: [[VRNDXQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrintx.v4f32(<4 x float> %a) #2
-// CHECK: ret <4 x float> [[VRNDXQ_V1_I]]
+// CHECK-LABEL: define <4 x float> @test_vrndxq_f32(<4 x float> %a)
+// CHECK-A32: [[VRNDXQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrintx.v4f32(<4 x float> %a)
+// CHECK-A64: [[VRNDXQ_V1_I:%.*]] = call <4 x float> @llvm.rint.v4f32(<4 x float> %a)
+// CHECK: ret <4 x float> [[VRNDXQ_V1_I]]
float32x4_t test_vrndxq_f32(float32x4_t a) {
return vrndxq_f32(a);
}
-// CHECK-LABEL: define <2 x float> @test_vrnd_f32(<2 x float> %a) #0 {
-// CHECK: [[VRND_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrintz.v2f32(<2 x float> %a) #2
-// CHECK: ret <2 x float> [[VRND_V1_I]]
+// CHECK-LABEL: define <2 x float> @test_vrnd_f32(<2 x float> %a)
+// CHECK-A32: [[VRND_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrintz.v2f32(<2 x float> %a)
+// CHECK-A64: [[VRND_V1_I:%.*]] = call <2 x float> @llvm.trunc.v2f32(<2 x float> %a)
+// CHECK: ret <2 x float> [[VRND_V1_I]]
float32x2_t test_vrnd_f32(float32x2_t a) {
return vrnd_f32(a);
}
-// CHECK-LABEL: define <4 x float> @test_vrndq_f32(<4 x float> %a) #0 {
-// CHECK: [[VRNDQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrintz.v4f32(<4 x float> %a) #2
-// CHECK: ret <4 x float> [[VRNDQ_V1_I]]
+// CHECK-LABEL: define <4 x float> @test_vrndq_f32(<4 x float> %a)
+// CHECK-A32: [[VRNDQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrintz.v4f32(<4 x float> %a)
+// CHECK-A64: [[VRNDQ_V1_I:%.*]] = call <4 x float> @llvm.trunc.v4f32(<4 x float> %a)
+// CHECK: ret <4 x float> [[VRNDQ_V1_I]]
float32x4_t test_vrndq_f32(float32x4_t a) {
return vrndq_f32(a);
}
+
+// CHECK-LABEL: define float @test_vrndns_f32(float %a)
+// CHECK-A32: [[VRNDN_I:%.*]] = call float @llvm.arm.neon.vrintn.f32(float %a)
+// CHECK-A64: [[VRNDN_I:%.*]] = call float @llvm.aarch64.neon.frintn.f32(float %a)
+// CHECK: ret float [[VRNDN_I]]
+float32_t test_vrndns_f32(float32_t a) {
+ return vrndns_f32(a);
+}
+
+// CHECK-LABEL: define <2 x float> @test_vrndi_f32(<2 x float> %a)
+// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
+// CHECK: [[VRNDI1_I:%.*]] = call <2 x float> @llvm.nearbyint.v2f32(<2 x float> %a)
+// CHECK: ret <2 x float> [[VRNDI1_I]]
+float32x2_t test_vrndi_f32(float32x2_t a) {
+ return vrndi_f32(a);
+}
+
+// CHECK-LABEL: define <4 x float> @test_vrndiq_f32(<4 x float> %a)
+// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
+// CHECK: [[VRNDI1_I:%.*]] = call <4 x float> @llvm.nearbyint.v4f32(<4 x float> %a)
+// CHECK: ret <4 x float> [[VRNDI1_I]]
+float32x4_t test_vrndiq_f32(float32x4_t a) {
+ return vrndiq_f32(a);
+}
diff --git a/test/CodeGen/arm-neon-dot-product.c b/test/CodeGen/arm-neon-dot-product.c
new file mode 100644
index 000000000000..34acd02c61c6
--- /dev/null
+++ b/test/CodeGen/arm-neon-dot-product.c
@@ -0,0 +1,76 @@
+// RUN: %clang_cc1 -triple armv8-linux-gnueabihf -target-cpu cortex-a75 -target-feature +dotprod \
+// RUN: -disable-O0-optnone -emit-llvm -o - %s | opt -S -instcombine | FileCheck %s
+
+// REQUIRES: arm-registered-target
+
+// Test ARM v8.2-A dot product intrinsics
+
+#include <arm_neon.h>
+
+uint32x2_t test_vdot_u32(uint32x2_t a, uint8x8_t b, uint8x8_t c) {
+// CHECK-LABEL: define <2 x i32> @test_vdot_u32(<2 x i32> %a, <8 x i8> %b, <8 x i8> %c)
+// CHECK: [[RESULT:%.*]] = call <2 x i32> @llvm.arm.neon.udot.v2i32.v8i8(<2 x i32> %a, <8 x i8> %b, <8 x i8> %c)
+// CHECK: ret <2 x i32> [[RESULT]]
+ return vdot_u32(a, b, c);
+}
+
+uint32x4_t test_vdotq_u32(uint32x4_t a, uint8x16_t b, uint8x16_t c) {
+// CHECK-LABEL: define <4 x i32> @test_vdotq_u32(<4 x i32> %a, <16 x i8> %b, <16 x i8> %c)
+// CHECK: [[RESULT:%.*]] = call <4 x i32> @llvm.arm.neon.udot.v4i32.v16i8(<4 x i32> %a, <16 x i8> %b, <16 x i8> %c)
+// CHECK: ret <4 x i32> [[RESULT]]
+ return vdotq_u32(a, b, c);
+}
+
+int32x2_t test_vdot_s32(int32x2_t a, int8x8_t b, int8x8_t c) {
+// CHECK-LABEL: define <2 x i32> @test_vdot_s32(<2 x i32> %a, <8 x i8> %b, <8 x i8> %c)
+// CHECK: [[RESULT:%.*]] = call <2 x i32> @llvm.arm.neon.sdot.v2i32.v8i8(<2 x i32> %a, <8 x i8> %b, <8 x i8> %c)
+// CHECK: ret <2 x i32> [[RESULT]]
+ return vdot_s32(a, b, c);
+}
+
+int32x4_t test_vdotq_s32(int32x4_t a, int8x16_t b, int8x16_t c) {
+// CHECK-LABEL: define <4 x i32> @test_vdotq_s32(<4 x i32> %a, <16 x i8> %b, <16 x i8> %c)
+// CHECK: [[RESULT:%.*]] = call <4 x i32> @llvm.arm.neon.sdot.v4i32.v16i8(<4 x i32> %a, <16 x i8> %b, <16 x i8> %c)
+// CHECK: ret <4 x i32> [[RESULT]]
+ return vdotq_s32(a, b, c);
+}
+
+uint32x2_t test_vdot_lane_u32(uint32x2_t a, uint8x8_t b, uint8x8_t c) {
+// CHECK-LABEL: define <2 x i32> @test_vdot_lane_u32(<2 x i32> %a, <8 x i8> %b, <8 x i8> %c)
+// CHECK: [[CAST1:%.*]] = bitcast <8 x i8> %c to <2 x i32>
+// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> [[CAST1]], <2 x i32> undef, <2 x i32> <i32 1, i32 1>
+// CHECK: [[CAST2:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
+// CHECK: [[RESULT:%.*]] = call <2 x i32> @llvm.arm.neon.udot.v2i32.v8i8(<2 x i32> %a, <8 x i8> %b, <8 x i8> [[CAST2]])
+// CHECK: ret <2 x i32> [[RESULT]]
+ return vdot_lane_u32(a, b, c, 1);
+}
+
+uint32x4_t test_vdotq_lane_u32(uint32x4_t a, uint8x16_t b, uint8x8_t c) {
+// CHECK-LABEL: define <4 x i32> @test_vdotq_lane_u32(<4 x i32> %a, <16 x i8> %b, <8 x i8> %c)
+// CHECK: [[CAST1:%.*]] = bitcast <8 x i8> %c to <2 x i32>
+// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> [[CAST1]], <2 x i32> undef, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
+// CHECK: [[CAST2:%.*]] = bitcast <4 x i32> [[SHUFFLE]] to <16 x i8>
+// CHECK: [[RESULT:%.*]] = call <4 x i32> @llvm.arm.neon.udot.v4i32.v16i8(<4 x i32> %a, <16 x i8> %b, <16 x i8> [[CAST2]])
+// CHECK: ret <4 x i32> [[RESULT]]
+ return vdotq_lane_u32(a, b, c, 1);
+}
+
+int32x2_t test_vdot_lane_s32(int32x2_t a, int8x8_t b, int8x8_t c) {
+// CHECK-LABEL: define <2 x i32> @test_vdot_lane_s32(<2 x i32> %a, <8 x i8> %b, <8 x i8> %c)
+// CHECK: [[CAST1:%.*]] = bitcast <8 x i8> %c to <2 x i32>
+// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> [[CAST1]], <2 x i32> undef, <2 x i32> <i32 1, i32 1>
+// CHECK: [[CAST2:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
+// CHECK: [[RESULT:%.*]] = call <2 x i32> @llvm.arm.neon.sdot.v2i32.v8i8(<2 x i32> %a, <8 x i8> %b, <8 x i8> [[CAST2]])
+// CHECK: ret <2 x i32> [[RESULT]]
+ return vdot_lane_s32(a, b, c, 1);
+}
+
+int32x4_t test_vdotq_lane_s32(int32x4_t a, int8x16_t b, int8x8_t c) {
+// CHECK-LABEL: define <4 x i32> @test_vdotq_lane_s32(<4 x i32> %a, <16 x i8> %b, <8 x i8> %c)
+// CHECK: [[CAST1:%.*]] = bitcast <8 x i8> %c to <2 x i32>
+// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> [[CAST1]], <2 x i32> undef, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
+// CHECK: [[CAST2:%.*]] = bitcast <4 x i32> [[SHUFFLE]] to <16 x i8>
+// CHECK: [[RESULT:%.*]] = call <4 x i32> @llvm.arm.neon.sdot.v4i32.v16i8(<4 x i32> %a, <16 x i8> %b, <16 x i8> [[CAST2]])
+// CHECK: ret <4 x i32> [[RESULT]]
+ return vdotq_lane_s32(a, b, c, 1);
+}
diff --git a/test/CodeGen/arm-neon-fma.c b/test/CodeGen/arm-neon-fma.c
index b5184c195e40..5f6737aaa771 100644
--- a/test/CodeGen/arm-neon-fma.c
+++ b/test/CodeGen/arm-neon-fma.c
@@ -20,3 +20,27 @@ float32x2_t test_fma_order(float32x2_t accum, float32x2_t lhs, float32x2_t rhs)
float32x4_t test_fmaq_order(float32x4_t accum, float32x4_t lhs, float32x4_t rhs) {
return vfmaq_f32(accum, lhs, rhs);
}
+
+// CHECK-LABEL: define <2 x float> @test_vfma_n_f32(<2 x float> %a, <2 x float> %b, float %n) #0 {
+// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x float> undef, float %n, i32 0
+// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x float> [[VECINIT_I]], float %n, i32 1
+// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
+// CHECK: [[TMP2:%.*]] = bitcast <2 x float> [[VECINIT1_I]] to <8 x i8>
+// CHECK: [[TMP3:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> %b, <2 x float> [[VECINIT1_I]], <2 x float> %a)
+// CHECK: ret <2 x float> [[TMP3]]
+float32x2_t test_vfma_n_f32(float32x2_t a, float32x2_t b, float32_t n) {
+ return vfma_n_f32(a, b, n);
+}
+
+// CHECK-LABEL: define <4 x float> @test_vfmaq_n_f32(<4 x float> %a, <4 x float> %b, float %n) #0 {
+// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x float> undef, float %n, i32 0
+// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x float> [[VECINIT_I]], float %n, i32 1
+// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x float> [[VECINIT1_I]], float %n, i32 2
+// CHECK: [[VECINIT3_I:%.*]] = insertelement <4 x float> [[VECINIT2_I]], float %n, i32 3
+// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
+// CHECK: [[TMP2:%.*]] = bitcast <4 x float> [[VECINIT3_I]] to <16 x i8>
+// CHECK: [[TMP3:%.*]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %b, <4 x float> [[VECINIT3_I]], <4 x float> %a)
+// CHECK: ret <4 x float> [[TMP3]]
+float32x4_t test_vfmaq_n_f32(float32x4_t a, float32x4_t b, float32_t n) {
+ return vfmaq_n_f32(a, b, n);
+}
diff --git a/test/CodeGen/arm-neon-vld.c b/test/CodeGen/arm-neon-vld.c
new file mode 100644
index 000000000000..2bf55bb1c6cb
--- /dev/null
+++ b/test/CodeGen/arm-neon-vld.c
@@ -0,0 +1,2498 @@
+// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon \
+// RUN: -S -disable-O0-optnone -emit-llvm -o - %s | opt -S -mem2reg | \
+// RUN: FileCheck -check-prefixes=CHECK,CHECK-A64 %s
+// RUN: %clang_cc1 -triple armv8-none-linux-gnueabi -target-feature +neon \
+// RUN: -S -disable-O0-optnone -emit-llvm -o - %s | opt -S -mem2reg | \
+// RUN: FileCheck -check-prefixes=CHECK,CHECK-A32 %s
+
+#include <arm_neon.h>
+
+// CHECK-LABEL: @test_vld1_f16_x2(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.float16x4x2_t, align 8
+// CHECK-A32: %struct.float16x4x2_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x2_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to [[HALF:(half|i16)]]*
+// CHECK: [[VLD1XN:%.*]] = call { <4 x [[HALF]]>, <4 x [[HALF]]> } @llvm.{{aarch64.neon.ld1x2.v4f16.p0f16|arm.neon.vld1x2.v4i16.p0i16}}([[HALF]]* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x [[HALF]]>, <4 x [[HALF]]> }*
+// CHECK: store { <4 x [[HALF]]>, <4 x [[HALF]]> } [[VLD1XN]], { <4 x [[HALF]]>, <4 x [[HALF]]> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x4x2_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 16, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.float16x4x2_t, %struct.float16x4x2_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.float16x4x2_t [[TMP6]]
+// CHECK-A32: ret void
+float16x4x2_t test_vld1_f16_x2(float16_t const *a) {
+ return vld1_f16_x2(a);
+}
+
+// CHECK-LABEL: @test_vld1_f16_x3(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.float16x4x3_t, align 8
+// CHECK-A32: %struct.float16x4x3_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x3_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to [[HALF]]*
+// CHECK: [[VLD1XN:%.*]] = call { <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]> } @llvm.{{aarch64.neon.ld1x3.v4f16.p0f16|arm.neon.vld1x3.v4i16.p0i16}}([[HALF]]* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]> }*
+// CHECK: store { <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]> } [[VLD1XN]], { <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x4x3_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 24, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.float16x4x3_t, %struct.float16x4x3_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.float16x4x3_t [[TMP6]]
+// CHECK-A32: ret void
+float16x4x3_t test_vld1_f16_x3(float16_t const *a) {
+ return vld1_f16_x3(a);
+}
+
+// CHECK-LABEL: @test_vld1_f16_x4(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.float16x4x4_t, align 8
+// CHECK-A32: %struct.float16x4x4_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x4_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to [[HALF]]*
+// CHECK: [[VLD1XN:%.*]] = call { <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]> } @llvm.{{aarch64.neon.ld1x4.v4f16.p0f16|arm.neon.vld1x4.v4i16.p0i16}}([[HALF]]* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]> }*
+// CHECK: store { <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]> } [[VLD1XN]], { <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x4x4_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.float16x4x4_t, %struct.float16x4x4_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.float16x4x4_t [[TMP6]]
+// CHECK-A32: ret void
+float16x4x4_t test_vld1_f16_x4(float16_t const *a) {
+ return vld1_f16_x4(a);
+}
+
+// CHECK-LABEL: @test_vld1_f32_x2(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.float32x2x2_t, align 8
+// CHECK-A32: %struct.float32x2x2_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.float32x2x2_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast float* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float*
+// CHECK: [[VLD1XN:%.*]] = call { <2 x float>, <2 x float> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v2f32.p0f32(float* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x float>, <2 x float> }*
+// CHECK: store { <2 x float>, <2 x float> } [[VLD1XN]], { <2 x float>, <2 x float> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x2x2_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x2x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 16, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.float32x2x2_t, %struct.float32x2x2_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.float32x2x2_t [[TMP6]]
+// CHECK-A32: ret void
+float32x2x2_t test_vld1_f32_x2(float32_t const *a) {
+ return vld1_f32_x2(a);
+}
+
+// CHECK-LABEL: @test_vld1_f32_x3(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.float32x2x3_t, align 8
+// CHECK-A32: %struct.float32x2x3_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.float32x2x3_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast float* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float*
+// CHECK: [[VLD1XN:%.*]] = call { <2 x float>, <2 x float>, <2 x float> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v2f32.p0f32(float* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x float>, <2 x float>, <2 x float> }*
+// CHECK: store { <2 x float>, <2 x float>, <2 x float> } [[VLD1XN]], { <2 x float>, <2 x float>, <2 x float> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x2x3_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x2x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 24, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.float32x2x3_t, %struct.float32x2x3_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.float32x2x3_t [[TMP6]]
+float32x2x3_t test_vld1_f32_x3(float32_t const *a) {
+ return vld1_f32_x3(a);
+}
+
+// CHECK-LABEL: @test_vld1_f32_x4(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.float32x2x4_t, align 8
+// CHECK-A32: %struct.float32x2x4_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.float32x2x4_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast float* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float*
+// CHECK: [[VLD1XN:%.*]] = call { <2 x float>, <2 x float>, <2 x float>, <2 x float> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v2f32.p0f32(float* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x float>, <2 x float>, <2 x float>, <2 x float> }*
+// CHECK: store { <2 x float>, <2 x float>, <2 x float>, <2 x float> } [[VLD1XN]], { <2 x float>, <2 x float>, <2 x float>, <2 x float> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x2x4_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x2x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.float32x2x4_t, %struct.float32x2x4_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.float32x2x4_t [[TMP6]]
+// CHECK-A32: ret void
+float32x2x4_t test_vld1_f32_x4(float32_t const *a) {
+ return vld1_f32_x4(a);
+}
+
+// CHECK-LABEL: @test_vld1_p16_x2(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.poly16x4x2_t, align 8
+// CHECK-A32: %struct.poly16x4x2_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.poly16x4x2_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK: [[VLD1XN:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v4i16.p0i16(i16* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16> }*
+// CHECK: store { <4 x i16>, <4 x i16> } [[VLD1XN]], { <4 x i16>, <4 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x4x2_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 16, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.poly16x4x2_t [[TMP6]]
+// CHECK-A32: ret void
+poly16x4x2_t test_vld1_p16_x2(poly16_t const *a) {
+ return vld1_p16_x2(a);
+}
+
+// CHECK-LABEL: @test_vld1_p16_x3(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.poly16x4x3_t, align 8
+// CHECK-A32: %struct.poly16x4x3_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.poly16x4x3_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK: [[VLD1XN:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v4i16.p0i16(i16* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16> }*
+// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD1XN]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x4x3_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x4x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 24, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.poly16x4x3_t, %struct.poly16x4x3_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.poly16x4x3_t [[TMP6]]
+// CHECK-A32: ret void
+poly16x4x3_t test_vld1_p16_x3(poly16_t const *a) {
+ return vld1_p16_x3(a);
+}
+
+// CHECK-LABEL: @test_vld1_p16_x4(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.poly16x4x4_t, align 8
+// CHECK-A32: %struct.poly16x4x4_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.poly16x4x4_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK: [[VLD1XN:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v4i16.p0i16(i16* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }*
+// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD1XN]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x4x4_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x4x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.poly16x4x4_t, %struct.poly16x4x4_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.poly16x4x4_t [[TMP6]]
+// CHECK-A32: ret void
+poly16x4x4_t test_vld1_p16_x4(poly16_t const *a) {
+ return vld1_p16_x4(a);
+}
+
+// CHECK-LABEL: @test_vld1_p8_x2(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.poly8x8x2_t, align 8
+// CHECK-A32: %struct.poly8x8x2_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.poly8x8x2_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET]] to i8*
+// CHECK: [[VLD1XN:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v8i8.p0i8(i8* %a)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8> }*
+// CHECK: store { <8 x i8>, <8 x i8> } [[VLD1XN]], { <8 x i8>, <8 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x8x2_t* [[RETVAL]] to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], {{i64|i32}} 16, i1 false)
+// CHECK-A64: [[TMP4:%.*]] = load %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.poly8x8x2_t [[TMP4]]
+// CHECK-A32: ret void
+poly8x8x2_t test_vld1_p8_x2(poly8_t const *a) {
+ return vld1_p8_x2(a);
+}
+
+// CHECK-LABEL: @test_vld1_p8_x3(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.poly8x8x3_t, align 8
+// CHECK-A32: %struct.poly8x8x3_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.poly8x8x3_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x3_t* [[__RET]] to i8*
+// CHECK: [[VLD1XN:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v8i8.p0i8(i8* %a)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8> }*
+// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD1XN]], { <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x8x3_t* [[RETVAL]] to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], {{i64|i32}} 24, i1 false)
+// CHECK-A64: [[TMP4:%.*]] = load %struct.poly8x8x3_t, %struct.poly8x8x3_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.poly8x8x3_t [[TMP4]]
+// CHECK-A32: ret void
+poly8x8x3_t test_vld1_p8_x3(poly8_t const *a) {
+ return vld1_p8_x3(a);
+}
+
+// CHECK-LABEL: @test_vld1_p8_x4(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.poly8x8x4_t, align 8
+// CHECK-A32: %struct.poly8x8x4_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.poly8x8x4_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x4_t* [[__RET]] to i8*
+// CHECK: [[VLD1XN:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v8i8.p0i8(i8* %a)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }*
+// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[VLD1XN]], { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x8x4_t* [[RETVAL]] to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], {{i64|i32}} 32, i1 false)
+// CHECK-A64: [[TMP4:%.*]] = load %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.poly8x8x4_t [[TMP4]]
+// CHECK-A32: ret void
+poly8x8x4_t test_vld1_p8_x4(poly8_t const *a) {
+ return vld1_p8_x4(a);
+}
+
+// CHECK-LABEL: @test_vld1_s16_x2(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int16x4x2_t, align 8
+// CHECK-A32: %struct.int16x4x2_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.int16x4x2_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK: [[VLD1XN:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v4i16.p0i16(i16* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16> }*
+// CHECK: store { <4 x i16>, <4 x i16> } [[VLD1XN]], { <4 x i16>, <4 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x4x2_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x4x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 16, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.int16x4x2_t, %struct.int16x4x2_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.int16x4x2_t [[TMP6]]
+// CHECK-A32: ret void
+int16x4x2_t test_vld1_s16_x2(int16_t const *a) {
+ return vld1_s16_x2(a);
+}
+
+// CHECK-LABEL: @test_vld1_s16_x3(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int16x4x3_t, align 8
+// CHECK-A32: %struct.int16x4x3_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.int16x4x3_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK: [[VLD1XN:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v4i16.p0i16(i16* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16> }*
+// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD1XN]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x4x3_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x4x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 24, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.int16x4x3_t, %struct.int16x4x3_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.int16x4x3_t [[TMP6]]
+// CHECK-A32: ret void
+int16x4x3_t test_vld1_s16_x3(int16_t const *a) {
+ return vld1_s16_x3(a);
+}
+
+// CHECK-LABEL: @test_vld1_s16_x4(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int16x4x4_t, align 8
+// CHECK-A32: %struct.int16x4x4_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.int16x4x4_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK: [[VLD1XN:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v4i16.p0i16(i16* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }*
+// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD1XN]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x4x4_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x4x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.int16x4x4_t, %struct.int16x4x4_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.int16x4x4_t [[TMP6]]
+// CHECK-A32: ret void
+int16x4x4_t test_vld1_s16_x4(int16_t const *a) {
+ return vld1_s16_x4(a);
+}
+
+// CHECK-LABEL: @test_vld1_s32_x2(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int32x2x2_t, align 8
+// CHECK-A32: %struct.int32x2x2_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.int32x2x2_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
+// CHECK: [[VLD1XN:%.*]] = call { <2 x i32>, <2 x i32> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v2i32.p0i32(i32* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32> }*
+// CHECK: store { <2 x i32>, <2 x i32> } [[VLD1XN]], { <2 x i32>, <2 x i32> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x2x2_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x2x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 16, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.int32x2x2_t, %struct.int32x2x2_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.int32x2x2_t [[TMP6]]
+// CHECK-A32: ret void
+int32x2x2_t test_vld1_s32_x2(int32_t const *a) {
+ return vld1_s32_x2(a);
+}
+
+// CHECK-LABEL: @test_vld1_s32_x3(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int32x2x3_t, align 8
+// CHECK-A32: %struct.int32x2x3_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.int32x2x3_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
+// CHECK: [[VLD1XN:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v2i32.p0i32(i32* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32>, <2 x i32> }*
+// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32> } [[VLD1XN]], { <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x2x3_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x2x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 24, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.int32x2x3_t, %struct.int32x2x3_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.int32x2x3_t [[TMP6]]
+// CHECK-A32: ret void
+int32x2x3_t test_vld1_s32_x3(int32_t const *a) {
+ return vld1_s32_x3(a);
+}
+
+// CHECK-LABEL: @test_vld1_s32_x4(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int32x2x4_t, align 8
+// CHECK-A32: %struct.int32x2x4_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.int32x2x4_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
+// CHECK: [[VLD1XN:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v2i32.p0i32(i32* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }*
+// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[VLD1XN]], { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x2x4_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x2x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.int32x2x4_t, %struct.int32x2x4_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.int32x2x4_t [[TMP6]]
+// CHECK-A32: ret void
+int32x2x4_t test_vld1_s32_x4(int32_t const *a) {
+ return vld1_s32_x4(a);
+}
+
+// CHECK-LABEL: @test_vld1_s64_x2(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int64x1x2_t, align 8
+// CHECK-A32: %struct.int64x1x2_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.int64x1x2_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
+// CHECK: [[VLD1XN:%.*]] = call { <1 x i64>, <1 x i64> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v1i64.p0i64(i64* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64> }*
+// CHECK: store { <1 x i64>, <1 x i64> } [[VLD1XN]], { <1 x i64>, <1 x i64> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x1x2_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.int64x1x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 16, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.int64x1x2_t, %struct.int64x1x2_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.int64x1x2_t [[TMP6]]
+// CHECK-A32: ret void
+int64x1x2_t test_vld1_s64_x2(int64_t const *a) {
+ return vld1_s64_x2(a);
+}
+
+// CHECK-LABEL: @test_vld1_s64_x3(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int64x1x3_t, align 8
+// CHECK-A32: %struct.int64x1x3_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.int64x1x3_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
+// CHECK: [[VLD1XN:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v1i64.p0i64(i64* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64>, <1 x i64> }*
+// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64> } [[VLD1XN]], { <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x1x3_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.int64x1x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 24, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.int64x1x3_t, %struct.int64x1x3_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.int64x1x3_t [[TMP6]]
+// CHECK-A32: ret void
+int64x1x3_t test_vld1_s64_x3(int64_t const *a) {
+ return vld1_s64_x3(a);
+}
+
+// CHECK-LABEL: @test_vld1_s64_x4(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int64x1x4_t, align 8
+// CHECK-A32: %struct.int64x1x4_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.int64x1x4_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
+// CHECK: [[VLD1XN:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v1i64.p0i64(i64* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }*
+// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } [[VLD1XN]], { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x1x4_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.int64x1x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.int64x1x4_t, %struct.int64x1x4_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.int64x1x4_t [[TMP6]]
+// CHECK-A32: ret void
+int64x1x4_t test_vld1_s64_x4(int64_t const *a) {
+ return vld1_s64_x4(a);
+}
+
+// CHECK-LABEL: @test_vld1_s8_x2(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int8x8x2_t, align 8
+// CHECK-A32: %struct.int8x8x2_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.int8x8x2_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[__RET]] to i8*
+// CHECK: [[VLD1XN:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v8i8.p0i8(i8* %a)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8> }*
+// CHECK: store { <8 x i8>, <8 x i8> } [[VLD1XN]], { <8 x i8>, <8 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x8x2_t* [[RETVAL]] to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], {{i64|i32}} 16, i1 false)
+// CHECK-A64: [[TMP4:%.*]] = load %struct.int8x8x2_t, %struct.int8x8x2_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.int8x8x2_t [[TMP4]]
+// CHECK-A32: ret void
+int8x8x2_t test_vld1_s8_x2(int8_t const *a) {
+ return vld1_s8_x2(a);
+}
+
+// CHECK-LABEL: @test_vld1_s8_x3(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int8x8x3_t, align 8
+// CHECK-A32: %struct.int8x8x3_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.int8x8x3_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x3_t* [[__RET]] to i8*
+// CHECK: [[VLD1XN:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v8i8.p0i8(i8* %a)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8> }*
+// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD1XN]], { <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x8x3_t* [[RETVAL]] to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], {{i64|i32}} 24, i1 false)
+// CHECK-A64: [[TMP4:%.*]] = load %struct.int8x8x3_t, %struct.int8x8x3_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.int8x8x3_t [[TMP4]]
+// CHECK-A32: ret void
+int8x8x3_t test_vld1_s8_x3(int8_t const *a) {
+ return vld1_s8_x3(a);
+}
+
+// CHECK-LABEL: @test_vld1_s8_x4(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int8x8x4_t, align 8
+// CHECK-A32: %struct.int8x8x4_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.int8x8x4_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x4_t* [[__RET]] to i8*
+// CHECK: [[VLD1XN:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v8i8.p0i8(i8* %a)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }*
+// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[VLD1XN]], { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x8x4_t* [[RETVAL]] to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], {{i64|i32}} 32, i1 false)
+// CHECK-A64: [[TMP4:%.*]] = load %struct.int8x8x4_t, %struct.int8x8x4_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.int8x8x4_t [[TMP4]]
+// CHECK-A32: ret void
+int8x8x4_t test_vld1_s8_x4(int8_t const *a) {
+ return vld1_s8_x4(a);
+}
+
+// CHECK-LABEL: @test_vld1_u16_x2(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint16x4x2_t, align 8
+// CHECK-A32: %struct.uint16x4x2_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.uint16x4x2_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK: [[VLD1XN:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v4i16.p0i16(i16* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16> }*
+// CHECK: store { <4 x i16>, <4 x i16> } [[VLD1XN]], { <4 x i16>, <4 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x4x2_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 16, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.uint16x4x2_t [[TMP6]]
+// CHECK-A32: ret void
+uint16x4x2_t test_vld1_u16_x2(uint16_t const *a) {
+ return vld1_u16_x2(a);
+}
+
+// CHECK-LABEL: @test_vld1_u16_x3(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint16x4x3_t, align 8
+// CHECK-A32: %struct.uint16x4x3_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.uint16x4x3_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK: [[VLD1XN:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v4i16.p0i16(i16* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16> }*
+// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD1XN]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x4x3_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x4x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 24, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.uint16x4x3_t, %struct.uint16x4x3_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.uint16x4x3_t [[TMP6]]
+// CHECK-A32: ret void
+uint16x4x3_t test_vld1_u16_x3(uint16_t const *a) {
+ return vld1_u16_x3(a);
+}
+
+// CHECK-LABEL: @test_vld1_u16_x4(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint16x4x4_t, align 8
+// CHECK-A32: %struct.uint16x4x4_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.uint16x4x4_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK: [[VLD1XN:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v4i16.p0i16(i16* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }*
+// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD1XN]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x4x4_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x4x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.uint16x4x4_t, %struct.uint16x4x4_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.uint16x4x4_t [[TMP6]]
+// CHECK-A32: ret void
+uint16x4x4_t test_vld1_u16_x4(uint16_t const *a) {
+ return vld1_u16_x4(a);
+}
+
+// CHECK-LABEL: @test_vld1_u32_x2(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint32x2x2_t, align 8
+// CHECK-A32: %struct.uint32x2x2_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.uint32x2x2_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
+// CHECK: [[VLD1XN:%.*]] = call { <2 x i32>, <2 x i32> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v2i32.p0i32(i32* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32> }*
+// CHECK: store { <2 x i32>, <2 x i32> } [[VLD1XN]], { <2 x i32>, <2 x i32> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x2x2_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 16, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.uint32x2x2_t [[TMP6]]
+// CHECK-A32: ret void
+uint32x2x2_t test_vld1_u32_x2(uint32_t const *a) {
+ return vld1_u32_x2(a);
+}
+
+// CHECK-LABEL: @test_vld1_u32_x3(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint32x2x3_t, align 8
+// CHECK-A32: %struct.uint32x2x3_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.uint32x2x3_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
+// CHECK: [[VLD1XN:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v2i32.p0i32(i32* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32>, <2 x i32> }*
+// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32> } [[VLD1XN]], { <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x2x3_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x2x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 24, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.uint32x2x3_t, %struct.uint32x2x3_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.uint32x2x3_t [[TMP6]]
+// CHECK-A32: ret void
+uint32x2x3_t test_vld1_u32_x3(uint32_t const *a) {
+ return vld1_u32_x3(a);
+}
+
+// CHECK-LABEL: @test_vld1_u32_x4(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint32x2x4_t, align 8
+// CHECK-A32: %struct.uint32x2x4_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.uint32x2x4_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
+// CHECK: [[VLD1XN:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v2i32.p0i32(i32* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }*
+// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[VLD1XN]], { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x2x4_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x2x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.uint32x2x4_t, %struct.uint32x2x4_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.uint32x2x4_t [[TMP6]]
+// CHECK-A32: ret void
+uint32x2x4_t test_vld1_u32_x4(uint32_t const *a) {
+ return vld1_u32_x4(a);
+}
+
+// CHECK-LABEL: @test_vld1_u64_x2(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint64x1x2_t, align 8
+// CHECK-A32: %struct.uint64x1x2_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.uint64x1x2_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
+// CHECK: [[VLD1XN:%.*]] = call { <1 x i64>, <1 x i64> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v1i64.p0i64(i64* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64> }*
+// CHECK: store { <1 x i64>, <1 x i64> } [[VLD1XN]], { <1 x i64>, <1 x i64> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x1x2_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.uint64x1x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 16, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.uint64x1x2_t, %struct.uint64x1x2_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.uint64x1x2_t [[TMP6]]
+// CHECK-A32: ret void
+uint64x1x2_t test_vld1_u64_x2(uint64_t const *a) {
+ return vld1_u64_x2(a);
+}
+
+// CHECK-LABEL: @test_vld1_u64_x3(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint64x1x3_t, align 8
+// CHECK-A32: %struct.uint64x1x3_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.uint64x1x3_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
+// CHECK: [[VLD1XN:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v1i64.p0i64(i64* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64>, <1 x i64> }*
+// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64> } [[VLD1XN]], { <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x1x3_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.uint64x1x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 24, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.uint64x1x3_t, %struct.uint64x1x3_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.uint64x1x3_t [[TMP6]]
+// CHECK-A32: ret void
+uint64x1x3_t test_vld1_u64_x3(uint64_t const *a) {
+ return vld1_u64_x3(a);
+}
+
+// CHECK-LABEL: @test_vld1_u64_x4(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint64x1x4_t, align 8
+// CHECK-A32: %struct.uint64x1x4_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.uint64x1x4_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
+// CHECK: [[VLD1XN:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v1i64.p0i64(i64* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }*
+// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } [[VLD1XN]], { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x1x4_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.uint64x1x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.uint64x1x4_t, %struct.uint64x1x4_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.uint64x1x4_t [[TMP6]]
+// CHECK-A32: ret void
+uint64x1x4_t test_vld1_u64_x4(uint64_t const *a) {
+ return vld1_u64_x4(a);
+}
+
+// CHECK-LABEL: @test_vld1_u8_x2(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint8x8x2_t, align 8
+// CHECK-A32: %struct.uint8x8x2_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.uint8x8x2_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET]] to i8*
+// CHECK: [[VLD1XN:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v8i8.p0i8(i8* %a)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8> }*
+// CHECK: store { <8 x i8>, <8 x i8> } [[VLD1XN]], { <8 x i8>, <8 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x8x2_t* [[RETVAL]] to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], {{i64|i32}} 16, i1 false)
+// CHECK-A64: [[TMP4:%.*]] = load %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.uint8x8x2_t [[TMP4]]
+// CHECK-A32: ret void
+uint8x8x2_t test_vld1_u8_x2(uint8_t const *a) {
+ return vld1_u8_x2(a);
+}
+
+// CHECK-LABEL: @test_vld1_u8_x3(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint8x8x3_t, align 8
+// CHECK-A32: %struct.uint8x8x3_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.uint8x8x3_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x3_t* [[__RET]] to i8*
+// CHECK: [[VLD1XN:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v8i8.p0i8(i8* %a)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8> }*
+// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD1XN]], { <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x8x3_t* [[RETVAL]] to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], {{i64|i32}} 24, i1 false)
+// CHECK-A64: [[TMP4:%.*]] = load %struct.uint8x8x3_t, %struct.uint8x8x3_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.uint8x8x3_t [[TMP4]]
+// CHECK-A32: ret void
+uint8x8x3_t test_vld1_u8_x3(uint8_t const *a) {
+ return vld1_u8_x3(a);
+}
+
+// CHECK-LABEL: @test_vld1_u8_x4(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint8x8x4_t, align 8
+// CHECK-A32: %struct.uint8x8x4_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.uint8x8x4_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x4_t* [[__RET]] to i8*
+// CHECK: [[VLD1XN:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v8i8.p0i8(i8* %a)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }*
+// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[VLD1XN]], { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x8x4_t* [[RETVAL]] to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], {{i64|i32}} 32, i1 false)
+// CHECK-A64: [[TMP4:%.*]] = load %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[RETVAL]], align 8
+// CHECK-A64: ret %struct.uint8x8x4_t [[TMP4]]
+// CHECK-A32: ret void
+uint8x8x4_t test_vld1_u8_x4(uint8_t const *a) {
+ return vld1_u8_x4(a);
+}
+
+// CHECK-LABEL: @test_vld1q_f16_x2(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.float16x8x2_t, align 16
+// CHECK-A32: %struct.float16x8x2_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x2_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to [[HALF]]*
+// CHECK: [[VLD1XN:%.*]] = call { <8 x [[HALF]]>, <8 x [[HALF]]> } @llvm.{{aarch64.neon.ld1x2.v8f16.p0f16|arm.neon.vld1x2.v8i16.p0i16}}([[HALF]]* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x [[HALF]]>, <8 x [[HALF]]> }*
+// CHECK: store { <8 x [[HALF]]>, <8 x [[HALF]]> } [[VLD1XN]], { <8 x [[HALF]]>, <8 x [[HALF]]> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x8x2_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.float16x8x2_t, %struct.float16x8x2_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.float16x8x2_t [[TMP6]]
+// CHECK-A32: ret void
+float16x8x2_t test_vld1q_f16_x2(float16_t const *a) {
+ return vld1q_f16_x2(a);
+}
+
+// CHECK-LABEL: @test_vld1q_f16_x3(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.float16x8x3_t, align 16
+// CHECK-A32: %struct.float16x8x3_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x3_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to [[HALF]]*
+// CHECK: [[VLD1XN:%.*]] = call { <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]> } @llvm.{{aarch64.neon.ld1x3.v8f16.p0f16|arm.neon.vld1x3.v8i16.p0i16}}([[HALF]]* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]> }*
+// CHECK: store { <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]> } [[VLD1XN]], { <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x8x3_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 48, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.float16x8x3_t, %struct.float16x8x3_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.float16x8x3_t [[TMP6]]
+// CHECK-A32: ret void
+float16x8x3_t test_vld1q_f16_x3(float16_t const *a) {
+ return vld1q_f16_x3(a);
+}
+
+// CHECK-LABEL: @test_vld1q_f16_x4(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.float16x8x4_t, align 16
+// CHECK-A32: %struct.float16x8x4_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x4_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to [[HALF]]*
+// CHECK: [[VLD1XN:%.*]] = call { <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]> } @llvm.{{aarch64.neon.ld1x4.v8f16.p0f16|arm.neon.vld1x4.v8i16.p0i16}}([[HALF]]* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]> }*
+// CHECK: store { <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]> } [[VLD1XN]], { <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x8x4_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 64, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.float16x8x4_t, %struct.float16x8x4_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.float16x8x4_t [[TMP6]]
+// CHECK-A32: ret void
+float16x8x4_t test_vld1q_f16_x4(float16_t const *a) {
+ return vld1q_f16_x4(a);
+}
+
+// CHECK-LABEL: @test_vld1q_f32_x2(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.float32x4x2_t, align 16
+// CHECK-A32: %struct.float32x4x2_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.float32x4x2_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast float* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float*
+// CHECK: [[VLD1XN:%.*]] = call { <4 x float>, <4 x float> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v4f32.p0f32(float* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x float>, <4 x float> }*
+// CHECK: store { <4 x float>, <4 x float> } [[VLD1XN]], { <4 x float>, <4 x float> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x4x2_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x4x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.float32x4x2_t, %struct.float32x4x2_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.float32x4x2_t [[TMP6]]
+// CHECK-A32: ret void
+float32x4x2_t test_vld1q_f32_x2(float32_t const *a) {
+ return vld1q_f32_x2(a);
+}
+
+// CHECK-LABEL: @test_vld1q_f32_x3(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.float32x4x3_t, align 16
+// CHECK-A32: %struct.float32x4x3_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.float32x4x3_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast float* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float*
+// CHECK: [[VLD1XN:%.*]] = call { <4 x float>, <4 x float>, <4 x float> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v4f32.p0f32(float* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x float>, <4 x float>, <4 x float> }*
+// CHECK: store { <4 x float>, <4 x float>, <4 x float> } [[VLD1XN]], { <4 x float>, <4 x float>, <4 x float> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x4x3_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x4x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 48, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.float32x4x3_t, %struct.float32x4x3_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.float32x4x3_t [[TMP6]]
+// CHECK-A32: ret void
+float32x4x3_t test_vld1q_f32_x3(float32_t const *a) {
+ return vld1q_f32_x3(a);
+}
+
+// CHECK-LABEL: @test_vld1q_f32_x4(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.float32x4x4_t, align 16
+// CHECK-A32: %struct.float32x4x4_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.float32x4x4_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast float* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float*
+// CHECK: [[VLD1XN:%.*]] = call { <4 x float>, <4 x float>, <4 x float>, <4 x float> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v4f32.p0f32(float* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x float>, <4 x float>, <4 x float>, <4 x float> }*
+// CHECK: store { <4 x float>, <4 x float>, <4 x float>, <4 x float> } [[VLD1XN]], { <4 x float>, <4 x float>, <4 x float>, <4 x float> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x4x4_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x4x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 64, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.float32x4x4_t, %struct.float32x4x4_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.float32x4x4_t [[TMP6]]
+// CHECK-A32: ret void
+float32x4x4_t test_vld1q_f32_x4(float32_t const *a) {
+ return vld1q_f32_x4(a);
+}
+
+// CHECK-LABEL: @test_vld1q_p16_x2(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.poly16x8x2_t, align 16
+// CHECK-A32: %struct.poly16x8x2_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x2_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK: [[VLD1XN:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v8i16.p0i16(i16* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16> }*
+// CHECK: store { <8 x i16>, <8 x i16> } [[VLD1XN]], { <8 x i16>, <8 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x8x2_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.poly16x8x2_t [[TMP6]]
+// CHECK-A32: ret void
+poly16x8x2_t test_vld1q_p16_x2(poly16_t const *a) {
+ return vld1q_p16_x2(a);
+}
+
+// CHECK-LABEL: @test_vld1q_p16_x3(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.poly16x8x3_t, align 16
+// CHECK-A32: %struct.poly16x8x3_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x3_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK: [[VLD1XN:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v8i16.p0i16(i16* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16> }*
+// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD1XN]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x8x3_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x8x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 48, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.poly16x8x3_t [[TMP6]]
+// CHECK-A32: ret void
+poly16x8x3_t test_vld1q_p16_x3(poly16_t const *a) {
+ return vld1q_p16_x3(a);
+}
+
+// CHECK-LABEL: @test_vld1q_p16_x4(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.poly16x8x4_t, align 16
+// CHECK-A32: %struct.poly16x8x4_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x4_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK: [[VLD1XN:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v8i16.p0i16(i16* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }*
+// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } [[VLD1XN]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x8x4_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x8x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 64, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.poly16x8x4_t [[TMP6]]
+// CHECK-A32: ret void
+poly16x8x4_t test_vld1q_p16_x4(poly16_t const *a) {
+ return vld1q_p16_x4(a);
+}
+
+// CHECK-LABEL: @test_vld1q_p8_x2(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.poly8x16x2_t, align 16
+// CHECK-A32: %struct.poly8x16x2_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.poly8x16x2_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET]] to i8*
+// CHECK: [[VLD1XN:%.*]] = call { <16 x i8>, <16 x i8> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v16i8.p0i8(i8* %a)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8> }*
+// CHECK: store { <16 x i8>, <16 x i8> } [[VLD1XN]], { <16 x i8>, <16 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x16x2_t* [[RETVAL]] to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP2]], i8* align {{16|8}} [[TMP3]], {{i64|i32}} 32, i1 false)
+// CHECK-A64: [[TMP4:%.*]] = load %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.poly8x16x2_t [[TMP4]]
+// CHECK-A32: ret void
+poly8x16x2_t test_vld1q_p8_x2(poly8_t const *a) {
+ return vld1q_p8_x2(a);
+}
+
+// CHECK-LABEL: @test_vld1q_p8_x3(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.poly8x16x3_t, align 16
+// CHECK-A32: %struct.poly8x16x3_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.poly8x16x3_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x3_t* [[__RET]] to i8*
+// CHECK: [[VLD1XN:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v16i8.p0i8(i8* %a)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8> }*
+// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8> } [[VLD1XN]], { <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x16x3_t* [[RETVAL]] to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP2]], i8* align {{16|8}} [[TMP3]], {{i64|i32}} 48, i1 false)
+// CHECK-A64: [[TMP4:%.*]] = load %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.poly8x16x3_t [[TMP4]]
+// CHECK-A32: ret void
+poly8x16x3_t test_vld1q_p8_x3(poly8_t const *a) {
+ return vld1q_p8_x3(a);
+}
+
+// CHECK-LABEL: @test_vld1q_p8_x4(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.poly8x16x4_t, align 16
+// CHECK-A32: %struct.poly8x16x4_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.poly8x16x4_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x4_t* [[__RET]] to i8*
+// CHECK: [[VLD1XN:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v16i8.p0i8(i8* %a)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }*
+// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } [[VLD1XN]], { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x16x4_t* [[RETVAL]] to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP2]], i8* align {{16|8}} [[TMP3]], {{i64|i32}} 64, i1 false)
+// CHECK-A64: [[TMP4:%.*]] = load %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.poly8x16x4_t [[TMP4]]
+// CHECK-A32: ret void
+poly8x16x4_t test_vld1q_p8_x4(poly8_t const *a) {
+ return vld1q_p8_x4(a);
+}
+
+// CHECK-LABEL: @test_vld1q_s16_x2(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int16x8x2_t, align 16
+// CHECK-A32: %struct.int16x8x2_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.int16x8x2_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK: [[VLD1XN:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v8i16.p0i16(i16* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16> }*
+// CHECK: store { <8 x i16>, <8 x i16> } [[VLD1XN]], { <8 x i16>, <8 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x8x2_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x8x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.int16x8x2_t, %struct.int16x8x2_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.int16x8x2_t [[TMP6]]
+// CHECK-A32: ret void
+int16x8x2_t test_vld1q_s16_x2(int16_t const *a) {
+ return vld1q_s16_x2(a);
+}
+
+// CHECK-LABEL: @test_vld1q_s16_x3(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int16x8x3_t, align 16
+// CHECK-A32: %struct.int16x8x3_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.int16x8x3_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK: [[VLD1XN:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v8i16.p0i16(i16* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16> }*
+// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD1XN]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x8x3_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x8x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 48, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.int16x8x3_t, %struct.int16x8x3_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.int16x8x3_t [[TMP6]]
+// CHECK-A32: ret void
+int16x8x3_t test_vld1q_s16_x3(int16_t const *a) {
+ return vld1q_s16_x3(a);
+}
+
+// CHECK-LABEL: @test_vld1q_s16_x4(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int16x8x4_t, align 16
+// CHECK-A32: %struct.int16x8x4_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.int16x8x4_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK: [[VLD1XN:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v8i16.p0i16(i16* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }*
+// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } [[VLD1XN]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x8x4_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x8x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 64, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.int16x8x4_t, %struct.int16x8x4_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.int16x8x4_t [[TMP6]]
+// CHECK-A32: ret void
+int16x8x4_t test_vld1q_s16_x4(int16_t const *a) {
+ return vld1q_s16_x4(a);
+}
+
+// CHECK-LABEL: @test_vld1q_s32_x2(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int32x4x2_t, align 16
+// CHECK-A32: %struct.int32x4x2_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.int32x4x2_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
+// CHECK: [[VLD1XN:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v4i32.p0i32(i32* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32> }*
+// CHECK: store { <4 x i32>, <4 x i32> } [[VLD1XN]], { <4 x i32>, <4 x i32> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x4x2_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x4x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.int32x4x2_t, %struct.int32x4x2_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.int32x4x2_t [[TMP6]]
+// CHECK-A32: ret void
+int32x4x2_t test_vld1q_s32_x2(int32_t const *a) {
+ return vld1q_s32_x2(a);
+}
+
+// CHECK-LABEL: @test_vld1q_s32_x3(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int32x4x3_t, align 16
+// CHECK-A32: %struct.int32x4x3_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.int32x4x3_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
+// CHECK: [[VLD1XN:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v4i32.p0i32(i32* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32>, <4 x i32> }*
+// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32> } [[VLD1XN]], { <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x4x3_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x4x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 48, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.int32x4x3_t, %struct.int32x4x3_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.int32x4x3_t [[TMP6]]
+// CHECK-A32: ret void
+int32x4x3_t test_vld1q_s32_x3(int32_t const *a) {
+ return vld1q_s32_x3(a);
+}
+
+// CHECK-LABEL: @test_vld1q_s32_x4(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int32x4x4_t, align 16
+// CHECK-A32: %struct.int32x4x4_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.int32x4x4_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
+// CHECK: [[VLD1XN:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v4i32.p0i32(i32* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> }*
+// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLD1XN]], { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x4x4_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x4x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 64, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.int32x4x4_t, %struct.int32x4x4_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.int32x4x4_t [[TMP6]]
+// CHECK-A32: ret void
+int32x4x4_t test_vld1q_s32_x4(int32_t const *a) {
+ return vld1q_s32_x4(a);
+}
+
+// CHECK-LABEL: @test_vld1q_s64_x2(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int64x2x2_t, align 16
+// CHECK-A32: %struct.int64x2x2_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.int64x2x2_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x2x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
+// CHECK: [[VLD1XN:%.*]] = call { <2 x i64>, <2 x i64> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v2i64.p0i64(i64* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i64>, <2 x i64> }*
+// CHECK: store { <2 x i64>, <2 x i64> } [[VLD1XN]], { <2 x i64>, <2 x i64> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x2x2_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.int64x2x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.int64x2x2_t, %struct.int64x2x2_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.int64x2x2_t [[TMP6]]
+// CHECK-A32: ret void
+int64x2x2_t test_vld1q_s64_x2(int64_t const *a) {
+ return vld1q_s64_x2(a);
+}
+
+// CHECK-LABEL: @test_vld1q_s64_x3(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int64x2x3_t, align 16
+// CHECK-A32: %struct.int64x2x3_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.int64x2x3_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x2x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
+// CHECK: [[VLD1XN:%.*]] = call { <2 x i64>, <2 x i64>, <2 x i64> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v2i64.p0i64(i64* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i64>, <2 x i64>, <2 x i64> }*
+// CHECK: store { <2 x i64>, <2 x i64>, <2 x i64> } [[VLD1XN]], { <2 x i64>, <2 x i64>, <2 x i64> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x2x3_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.int64x2x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 48, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.int64x2x3_t, %struct.int64x2x3_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.int64x2x3_t [[TMP6]]
+// CHECK-A32: ret void
+int64x2x3_t test_vld1q_s64_x3(int64_t const *a) {
+ return vld1q_s64_x3(a);
+}
+
+// CHECK-LABEL: @test_vld1q_s64_x4(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int64x2x4_t, align 16
+// CHECK-A32: %struct.int64x2x4_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.int64x2x4_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x2x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
+// CHECK: [[VLD1XN:%.*]] = call { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v2i64.p0i64(i64* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> }*
+// CHECK: store { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } [[VLD1XN]], { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x2x4_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.int64x2x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 64, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.int64x2x4_t, %struct.int64x2x4_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.int64x2x4_t [[TMP6]]
+// CHECK-A32: ret void
+int64x2x4_t test_vld1q_s64_x4(int64_t const *a) {
+ return vld1q_s64_x4(a);
+}
+
+// CHECK-LABEL: @test_vld1q_s8_x2(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int8x16x2_t, align 16
+// CHECK-A32: %struct.int8x16x2_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.int8x16x2_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[__RET]] to i8*
+// CHECK: [[VLD1XN:%.*]] = call { <16 x i8>, <16 x i8> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v16i8.p0i8(i8* %a)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8> }*
+// CHECK: store { <16 x i8>, <16 x i8> } [[VLD1XN]], { <16 x i8>, <16 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x16x2_t* [[RETVAL]] to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP2]], i8* align {{16|8}} [[TMP3]], {{i64|i32}} 32, i1 false)
+// CHECK-A64: [[TMP4:%.*]] = load %struct.int8x16x2_t, %struct.int8x16x2_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.int8x16x2_t [[TMP4]]
+// CHECK-A32: ret void
+int8x16x2_t test_vld1q_s8_x2(int8_t const *a) {
+ return vld1q_s8_x2(a);
+}
+
+// CHECK-LABEL: @test_vld1q_s8_x3(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int8x16x3_t, align 16
+// CHECK-A32: %struct.int8x16x3_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.int8x16x3_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x3_t* [[__RET]] to i8*
+// CHECK: [[VLD1XN:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v16i8.p0i8(i8* %a)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8> }*
+// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8> } [[VLD1XN]], { <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x16x3_t* [[RETVAL]] to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP2]], i8* align {{16|8}} [[TMP3]], {{i64|i32}} 48, i1 false)
+// CHECK-A64: [[TMP4:%.*]] = load %struct.int8x16x3_t, %struct.int8x16x3_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.int8x16x3_t [[TMP4]]
+// CHECK-A32: ret void
+int8x16x3_t test_vld1q_s8_x3(int8_t const *a) {
+ return vld1q_s8_x3(a);
+}
+
+// CHECK-LABEL: @test_vld1q_s8_x4(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int8x16x4_t, align 16
+// CHECK-A32: %struct.int8x16x4_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.int8x16x4_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x4_t* [[__RET]] to i8*
+// CHECK: [[VLD1XN:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v16i8.p0i8(i8* %a)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }*
+// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } [[VLD1XN]], { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x16x4_t* [[RETVAL]] to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP2]], i8* align {{16|8}} [[TMP3]], {{i64|i32}} 64, i1 false)
+// CHECK-A64: [[TMP4:%.*]] = load %struct.int8x16x4_t, %struct.int8x16x4_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.int8x16x4_t [[TMP4]]
+// CHECK-A32: ret void
+int8x16x4_t test_vld1q_s8_x4(int8_t const *a) {
+ return vld1q_s8_x4(a);
+}
+
+// CHECK-LABEL: @test_vld1q_u16_x2(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint16x8x2_t, align 16
+// CHECK-A32: %struct.uint16x8x2_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x2_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK: [[VLD1XN:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v8i16.p0i16(i16* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16> }*
+// CHECK: store { <8 x i16>, <8 x i16> } [[VLD1XN]], { <8 x i16>, <8 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x8x2_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.uint16x8x2_t [[TMP6]]
+// CHECK-A32: ret void
+uint16x8x2_t test_vld1q_u16_x2(uint16_t const *a) {
+ return vld1q_u16_x2(a);
+}
+
+// CHECK-LABEL: @test_vld1q_u16_x3(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint16x8x3_t, align 16
+// CHECK-A32: %struct.uint16x8x3_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x3_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK: [[VLD1XN:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v8i16.p0i16(i16* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16> }*
+// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD1XN]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x8x3_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x8x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 48, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.uint16x8x3_t [[TMP6]]
+// CHECK-A32: ret void
+uint16x8x3_t test_vld1q_u16_x3(uint16_t const *a) {
+ return vld1q_u16_x3(a);
+}
+
+// CHECK-LABEL: @test_vld1q_u16_x4(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint16x8x4_t, align 16
+// CHECK-A32: %struct.uint16x8x4_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x4_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK: [[VLD1XN:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v8i16.p0i16(i16* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }*
+// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } [[VLD1XN]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x8x4_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x8x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 64, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.uint16x8x4_t [[TMP6]]
+// CHECK-A32: ret void
+uint16x8x4_t test_vld1q_u16_x4(uint16_t const *a) {
+ return vld1q_u16_x4(a);
+}
+
+// CHECK-LABEL: @test_vld1q_u32_x2(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint32x4x2_t, align 16
+// CHECK-A32: %struct.uint32x4x2_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x2_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
+// CHECK: [[VLD1XN:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v4i32.p0i32(i32* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32> }*
+// CHECK: store { <4 x i32>, <4 x i32> } [[VLD1XN]], { <4 x i32>, <4 x i32> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x4x2_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.uint32x4x2_t [[TMP6]]
+// CHECK-A32: ret void
+uint32x4x2_t test_vld1q_u32_x2(uint32_t const *a) {
+ return vld1q_u32_x2(a);
+}
+
+// CHECK-LABEL: @test_vld1q_u32_x3(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint32x4x3_t, align 16
+// CHECK-A32: %struct.uint32x4x3_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x3_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
+// CHECK: [[VLD1XN:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v4i32.p0i32(i32* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32>, <4 x i32> }*
+// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32> } [[VLD1XN]], { <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x4x3_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x4x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 48, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.uint32x4x3_t [[TMP6]]
+// CHECK-A32: ret void
+uint32x4x3_t test_vld1q_u32_x3(uint32_t const *a) {
+ return vld1q_u32_x3(a);
+}
+
+// CHECK-LABEL: @test_vld1q_u32_x4(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint32x4x4_t, align 16
+// CHECK-A32: %struct.uint32x4x4_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x4_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
+// CHECK: [[VLD1XN:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v4i32.p0i32(i32* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> }*
+// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLD1XN]], { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x4x4_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x4x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 64, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.uint32x4x4_t [[TMP6]]
+// CHECK-A32: ret void
+uint32x4x4_t test_vld1q_u32_x4(uint32_t const *a) {
+ return vld1q_u32_x4(a);
+}
+
+// CHECK-LABEL: @test_vld1q_u64_x2(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint64x2x2_t, align 16
+// CHECK-A32: %struct.uint64x2x2_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.uint64x2x2_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x2x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
+// CHECK: [[VLD1XN:%.*]] = call { <2 x i64>, <2 x i64> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v2i64.p0i64(i64* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i64>, <2 x i64> }*
+// CHECK: store { <2 x i64>, <2 x i64> } [[VLD1XN]], { <2 x i64>, <2 x i64> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x2x2_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.uint64x2x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.uint64x2x2_t, %struct.uint64x2x2_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.uint64x2x2_t [[TMP6]]
+// CHECK-A32: ret void
+uint64x2x2_t test_vld1q_u64_x2(uint64_t const *a) {
+ return vld1q_u64_x2(a);
+}
+
+// CHECK-LABEL: @test_vld1q_u64_x3(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint64x2x3_t, align 16
+// CHECK-A32: %struct.uint64x2x3_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.uint64x2x3_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x2x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
+// CHECK: [[VLD1XN:%.*]] = call { <2 x i64>, <2 x i64>, <2 x i64> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v2i64.p0i64(i64* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i64>, <2 x i64>, <2 x i64> }*
+// CHECK: store { <2 x i64>, <2 x i64>, <2 x i64> } [[VLD1XN]], { <2 x i64>, <2 x i64>, <2 x i64> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x2x3_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.uint64x2x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 48, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.uint64x2x3_t, %struct.uint64x2x3_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.uint64x2x3_t [[TMP6]]
+// CHECK-A32: ret void
+uint64x2x3_t test_vld1q_u64_x3(uint64_t const *a) {
+ return vld1q_u64_x3(a);
+}
+
+// CHECK-LABEL: @test_vld1q_u64_x4(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint64x2x4_t, align 16
+// CHECK-A32: %struct.uint64x2x4_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.uint64x2x4_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x2x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
+// CHECK: [[VLD1XN:%.*]] = call { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v2i64.p0i64(i64* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> }*
+// CHECK: store { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } [[VLD1XN]], { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x2x4_t* [[RETVAL]] to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.uint64x2x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 64, i1 false)
+// CHECK-A64: [[TMP6:%.*]] = load %struct.uint64x2x4_t, %struct.uint64x2x4_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.uint64x2x4_t [[TMP6]]
+// CHECK-A32: ret void
+uint64x2x4_t test_vld1q_u64_x4(uint64_t const *a) {
+ return vld1q_u64_x4(a);
+}
+
+// CHECK-LABEL: @test_vld1q_u8_x2(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint8x16x2_t, align 16
+// CHECK-A32: %struct.uint8x16x2_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.uint8x16x2_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET]] to i8*
+// CHECK: [[VLD1XN:%.*]] = call { <16 x i8>, <16 x i8> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v16i8.p0i8(i8* %a)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8> }*
+// CHECK: store { <16 x i8>, <16 x i8> } [[VLD1XN]], { <16 x i8>, <16 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x16x2_t* [[RETVAL]] to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP2]], i8* align {{16|8}} [[TMP3]], {{i64|i32}} 32, i1 false)
+// CHECK-A64: [[TMP4:%.*]] = load %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.uint8x16x2_t [[TMP4]]
+// CHECK-A32: ret void
+uint8x16x2_t test_vld1q_u8_x2(uint8_t const *a) {
+ return vld1q_u8_x2(a);
+}
+
+// CHECK-LABEL: @test_vld1q_u8_x3(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint8x16x3_t, align 16
+// CHECK-A32: %struct.uint8x16x3_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.uint8x16x3_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x3_t* [[__RET]] to i8*
+// CHECK: [[VLD1XN:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v16i8.p0i8(i8* %a)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8> }*
+// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8> } [[VLD1XN]], { <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x16x3_t* [[RETVAL]] to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP2]], i8* align {{16|8}} [[TMP3]], {{i64|i32}} 48, i1 false)
+// CHECK-A64: [[TMP4:%.*]] = load %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.uint8x16x3_t [[TMP4]]
+// CHECK-A32: ret void
+uint8x16x3_t test_vld1q_u8_x3(uint8_t const *a) {
+ return vld1q_u8_x3(a);
+}
+
+// CHECK-LABEL: @test_vld1q_u8_x4(
+// CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint8x16x4_t, align 16
+// CHECK-A32: %struct.uint8x16x4_t* noalias sret [[RETVAL:%.*]],
+// CHECK: [[__RET:%.*]] = alloca %struct.uint8x16x4_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x4_t* [[__RET]] to i8*
+// CHECK: [[VLD1XN:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v16i8.p0i8(i8* %a)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }*
+// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } [[VLD1XN]], { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x16x4_t* [[RETVAL]] to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP2]], i8* align {{16|8}} [[TMP3]], {{i64|i32}} 64, i1 false)
+// CHECK-A64: [[TMP4:%.*]] = load %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[RETVAL]], align 16
+// CHECK-A64: ret %struct.uint8x16x4_t [[TMP4]]
+// CHECK-A32: ret void
+uint8x16x4_t test_vld1q_u8_x4(uint8_t const *a) {
+ return vld1q_u8_x4(a);
+}
+
+// CHECK-LABEL: @test_vld2_dup_f16(
+// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x2_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast half* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half*
+// CHECK-A64: [[VLD2:%.*]] = call { <4 x half>, <4 x half> } @llvm.aarch64.neon.ld2r.v4f16.p0f16(half* [[TMP2]])
+// CHECK-A32: [[VLD2:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.arm.neon.vld2dup.v4i16.p0i8(i8* [[TMP1]], i32 2)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x [[HALF]]>, <4 x [[HALF]]> }*
+// CHECK: store { <4 x [[HALF]]>, <4 x [[HALF]]> } [[VLD2]], { <4 x [[HALF]]>, <4 x [[HALF]]> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x4x2_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 16, i1 false)
+// CHECK: ret void
+void test_vld2_dup_f16(float16x4x2_t *dest, const float16_t *src) {
+ *dest = vld2_dup_f16(src);
+}
+
+// CHECK-LABEL: @test_vld2_dup_f32(
+// CHECK: [[__RET:%.*]] = alloca %struct.float32x2x2_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast float* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float*
+// CHECK-A64: [[VLD2:%.*]] = call { <2 x float>, <2 x float> } @llvm.aarch64.neon.ld2r.v2f32.p0f32(float* [[TMP2]])
+// CHECK-A32: [[VLD2:%.*]] = call { <2 x float>, <2 x float> } @llvm.arm.neon.vld2dup.v2f32.p0i8(i8* [[TMP1]], i32 4)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x float>, <2 x float> }*
+// CHECK: store { <2 x float>, <2 x float> } [[VLD2]], { <2 x float>, <2 x float> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x2x2_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x2x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 16, i1 false)
+// CHECK: ret void
+void test_vld2_dup_f32(float32x2x2_t *dest, const float32_t *src) {
+ *dest = vld2_dup_f32(src);
+}
+
+// CHECK-LABEL: @test_vld2_dup_p16(
+// CHECK: [[__RET:%.*]] = alloca %struct.poly16x4x2_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK-A64: [[VLD2:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld2r.v4i16.p0i16(i16* [[TMP2]])
+// CHECK-A32: [[VLD2:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.arm.neon.vld2dup.v4i16.p0i8(i8* [[TMP1]], i32 2)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16> }*
+// CHECK: store { <4 x i16>, <4 x i16> } [[VLD2]], { <4 x i16>, <4 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x4x2_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 16, i1 false)
+// CHECK: ret void
+void test_vld2_dup_p16(poly16x4x2_t *dest, const poly16_t *src) {
+ *dest = vld2_dup_p16(src);
+}
+
+// CHECK-LABEL: @test_vld2_dup_p8(
+// CHECK: [[__RET:%.*]] = alloca %struct.poly8x8x2_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET]] to i8*
+// CHECK-A64: [[VLD2:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld2r.v8i8.p0i8(i8* %src)
+// CHECK-A32: [[VLD2:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.arm.neon.vld2dup.v8i8.p0i8(i8* %src, i32 1)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8> }*
+// CHECK: store { <8 x i8>, <8 x i8> } [[VLD2]], { <8 x i8>, <8 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x8x2_t* %dest to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], {{i64|i32}} 16, i1 false)
+// CHECK: ret void
+void test_vld2_dup_p8(poly8x8x2_t *dest, poly8_t *src) {
+ *dest = vld2_dup_p8(src);
+}
+
+// CHECK-LABEL: @test_vld2_dup_s16(
+// CHECK: [[__RET:%.*]] = alloca %struct.int16x4x2_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK-A64: [[VLD2:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld2r.v4i16.p0i16(i16* [[TMP2]])
+// CHECK-A32: [[VLD2:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.arm.neon.vld2dup.v4i16.p0i8(i8* [[TMP1]], i32 2)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16> }*
+// CHECK: store { <4 x i16>, <4 x i16> } [[VLD2]], { <4 x i16>, <4 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x4x2_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x4x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 16, i1 false)
+// CHECK: ret void
+void test_vld2_dup_s16(int16x4x2_t *dest, const int16_t *src) {
+ *dest = vld2_dup_s16(src);
+}
+
+// CHECK-LABEL: @test_vld2_dup_s32(
+// CHECK: [[__RET:%.*]] = alloca %struct.int32x2x2_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i32* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
+// CHECK-A64: [[VLD2:%.*]] = call { <2 x i32>, <2 x i32> } @llvm.aarch64.neon.ld2r.v2i32.p0i32(i32* [[TMP2]])
+// CHECK-A32: [[VLD2:%.*]] = call { <2 x i32>, <2 x i32> } @llvm.arm.neon.vld2dup.v2i32.p0i8(i8* [[TMP1]], i32 4)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32> }*
+// CHECK: store { <2 x i32>, <2 x i32> } [[VLD2]], { <2 x i32>, <2 x i32> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x2x2_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x2x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 16, i1 false)
+// CHECK: ret void
+void test_vld2_dup_s32(int32x2x2_t *dest, const int32_t *src) {
+ *dest = vld2_dup_s32(src);
+}
+
+// CHECK-LABEL: @test_vld2_dup_s8(
+// CHECK: [[__RET:%.*]] = alloca %struct.int8x8x2_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[__RET]] to i8*
+// CHECK-A64: [[VLD2:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld2r.v8i8.p0i8(i8* %src)
+// CHECK-A32: [[VLD2:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.arm.neon.vld2dup.v8i8.p0i8(i8* %src, i32 1)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8> }*
+// CHECK: store { <8 x i8>, <8 x i8> } [[VLD2]], { <8 x i8>, <8 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x8x2_t* %dest to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], {{i64|i32}} 16, i1 false)
+// CHECK: ret void
+void test_vld2_dup_s8(int8x8x2_t *dest, int8_t *src) {
+ *dest = vld2_dup_s8(src);
+}
+
+// CHECK-LABEL: @test_vld2_dup_u16(
+// CHECK: [[__RET:%.*]] = alloca %struct.uint16x4x2_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK-A64: [[VLD2:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld2r.v4i16.p0i16(i16* [[TMP2]])
+// CHECK-A32: [[VLD2:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.arm.neon.vld2dup.v4i16.p0i8(i8* [[TMP1]], i32 2)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16> }*
+// CHECK: store { <4 x i16>, <4 x i16> } [[VLD2]], { <4 x i16>, <4 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x4x2_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 16, i1 false)
+// CHECK: ret void
+void test_vld2_dup_u16(uint16x4x2_t *dest, const uint16_t *src) {
+ *dest = vld2_dup_u16(src);
+}
+
+// CHECK-LABEL: @test_vld2_dup_u32(
+// CHECK: entry:
+// CHECK: [[__RET:%.*]] = alloca %struct.uint32x2x2_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i32* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
+// CHECK-A64: [[VLD2:%.*]] = call { <2 x i32>, <2 x i32> } @llvm.aarch64.neon.ld2r.v2i32.p0i32(i32* [[TMP2]])
+// CHECK-A32: [[VLD2:%.*]] = call { <2 x i32>, <2 x i32> } @llvm.arm.neon.vld2dup.v2i32.p0i8(i8* [[TMP1]], i32 4)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32> }*
+// CHECK: store { <2 x i32>, <2 x i32> } [[VLD2]], { <2 x i32>, <2 x i32> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x2x2_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 16, i1 false)
+// CHECK: ret void
+void test_vld2_dup_u32(uint32x2x2_t *dest, const uint32_t *src) {
+ *dest = vld2_dup_u32(src);
+}
+
+// CHECK-LABEL: @test_vld2_dup_s64(
+// CHECK: [[__RET:%.*]] = alloca %struct.int64x1x2_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i64* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
+// CHECK-A64: [[VLD2:%.*]] = call { <1 x i64>, <1 x i64> } @llvm.aarch64.neon.ld2r.v1i64.p0i64(i64* [[TMP2]])
+// CHECK-A32: [[VLD2:%.*]] = call { <1 x i64>, <1 x i64> } @llvm.arm.neon.vld2dup.v1i64.p0i8(i8* [[TMP1]], i32 8)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64> }*
+// CHECK: store { <1 x i64>, <1 x i64> } [[VLD2]], { <1 x i64>, <1 x i64> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x1x2_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.int64x1x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 16, i1 false)
+// CHECK: ret void
+void test_vld2_dup_s64(int64x1x2_t *dest, const int64_t *src) {
+ *dest = vld2_dup_s64(src);
+}
+
+// CHECK-LABEL: @test_vld2_dup_u64(
+// CHECK: [[__RET:%.*]] = alloca %struct.uint64x1x2_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i64* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
+// CHECK-A64: [[VLD2:%.*]] = call { <1 x i64>, <1 x i64> } @llvm.aarch64.neon.ld2r.v1i64.p0i64(i64* [[TMP2]])
+// CHECK-A32: [[VLD2:%.*]] = call { <1 x i64>, <1 x i64> } @llvm.arm.neon.vld2dup.v1i64.p0i8(i8* [[TMP1]], i32 8)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64> }*
+// CHECK: store { <1 x i64>, <1 x i64> } [[VLD2]], { <1 x i64>, <1 x i64> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x1x2_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.uint64x1x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 16, i1 false)
+// CHECK: ret void
+void test_vld2_dup_u64(uint64x1x2_t *dest, const uint64_t *src) {
+ *dest = vld2_dup_u64(src);
+}
+
+// CHECK-LABEL: @test_vld2_dup_u8(
+// CHECK: [[__RET:%.*]] = alloca %struct.uint8x8x2_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET]] to i8*
+// CHECK-A64: [[VLD2:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld2r.v8i8.p0i8(i8* %src)
+// CHECK-A32: [[VLD2:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.arm.neon.vld2dup.v8i8.p0i8(i8* %src, i32 1)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8> }*
+// CHECK: store { <8 x i8>, <8 x i8> } [[VLD2]], { <8 x i8>, <8 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x8x2_t* %dest to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], {{i64|i32}} 16, i1 false)
+// CHECK: ret void
+void test_vld2_dup_u8(uint8x8x2_t *dest, const uint8_t *src) {
+ *dest = vld2_dup_u8(src);
+}
+
+// CHECK-LABEL: @test_vld3_dup_f16(
+// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x3_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast half* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half*
+// CHECK-A64: [[VLD3:%.*]] = call { <4 x half>, <4 x half>, <4 x half> } @llvm.aarch64.neon.ld3r.v4f16.p0f16(half* [[TMP2]])
+// CHECK-A32: [[VLD3:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld3dup.v4i16.p0i8(i8* [[TMP1]], i32 2)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]> }*
+// CHECK: store { <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]> } [[VLD3]], { <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x4x3_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 24, i1 false)
+// CHECK: ret void
+void test_vld3_dup_f16(float16x4x3_t *dest, float16_t *src) {
+ *dest = vld3_dup_f16(src);
+}
+
+// CHECK-LABEL: @test_vld3_dup_f32(
+// CHECK: [[__RET:%.*]] = alloca %struct.float32x2x3_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast float* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float*
+// CHECK-A64: [[VLD3:%.*]] = call { <2 x float>, <2 x float>, <2 x float> } @llvm.aarch64.neon.ld3r.v2f32.p0f32(float* [[TMP2]])
+// CHECK-A32: [[VLD3:%.*]] = call { <2 x float>, <2 x float>, <2 x float> } @llvm.arm.neon.vld3dup.v2f32.p0i8(i8* [[TMP1]], i32 4)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x float>, <2 x float>, <2 x float> }*
+// CHECK: store { <2 x float>, <2 x float>, <2 x float> } [[VLD3]], { <2 x float>, <2 x float>, <2 x float> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x2x3_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x2x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 24, i1 false)
+// CHECK: ret void
+void test_vld3_dup_f32(float32x2x3_t *dest, const float32_t *src) {
+ *dest = vld3_dup_f32(src);
+}
+
+// CHECK-LABEL: @test_vld3_dup_p16(
+// CHECK: [[__RET:%.*]] = alloca %struct.poly16x4x3_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK-A64: [[VLD3:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld3r.v4i16.p0i16(i16* [[TMP2]])
+// CHECK-A32: [[VLD3:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld3dup.v4i16.p0i8(i8* [[TMP1]], i32 2)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16> }*
+// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD3]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x4x3_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x4x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 24, i1 false)
+// CHECK: ret void
+void test_vld3_dup_p16(poly16x4x3_t *dest, const poly16_t *src) {
+ *dest = vld3_dup_p16(src);
+}
+
+// CHECK-LABEL: @test_vld3_dup_p8(
+// CHECK: [[__RET:%.*]] = alloca %struct.poly8x8x3_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x3_t* [[__RET]] to i8*
+// CHECK-A64: [[VLD3:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld3r.v8i8.p0i8(i8* %src)
+// CHECK-A32: [[VLD3:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.arm.neon.vld3dup.v8i8.p0i8(i8* %src, i32 1)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8> }*
+// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD3]], { <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x8x3_t* %dest to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], {{i64|i32}} 24, i1 false)
+// CHECK: ret void
+void test_vld3_dup_p8(poly8x8x3_t *dest, const poly8_t *src) {
+ *dest = vld3_dup_p8(src);
+}
+
+// CHECK-LABEL: @test_vld3_dup_s16(
+// CHECK: [[__RET:%.*]] = alloca %struct.int16x4x3_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK-A64: [[VLD3:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld3r.v4i16.p0i16(i16* [[TMP2]])
+// CHECK-A32: [[VLD3:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld3dup.v4i16.p0i8(i8* [[TMP1]], i32 2)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16> }*
+// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD3]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x4x3_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x4x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 24, i1 false)
+// CHECK: ret void
+void test_vld3_dup_s16(int16x4x3_t *dest, const int16_t *src) {
+ *dest = vld3_dup_s16(src);
+}
+
+// CHECK-LABEL: @test_vld3_dup_s32(
+// CHECK: [[__RET:%.*]] = alloca %struct.int32x2x3_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i32* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
+// CHECK-A64: [[VLD3:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32> } @llvm.aarch64.neon.ld3r.v2i32.p0i32(i32* [[TMP2]])
+// CHECK-A32: [[VLD3:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32> } @llvm.arm.neon.vld3dup.v2i32.p0i8(i8* [[TMP1]], i32 4)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32>, <2 x i32> }*
+// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32> } [[VLD3]], { <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x2x3_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x2x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 24, i1 false)
+// CHECK: ret void
+void test_vld3_dup_s32(int32x2x3_t *dest, const int32_t *src) {
+ *dest = vld3_dup_s32(src);
+}
+
+// CHECK-LABEL: @test_vld3_dup_s8(
+// CHECK: [[__RET:%.*]] = alloca %struct.int8x8x3_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x3_t* [[__RET]] to i8*
+// CHECK-A64: [[VLD3:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld3r.v8i8.p0i8(i8* %src)
+// CHECK-A32: [[VLD3:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.arm.neon.vld3dup.v8i8.p0i8(i8* %src, i32 1)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8> }*
+// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD3]], { <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x8x3_t* %dest to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], {{i64|i32}} 24, i1 false)
+// CHECK: ret void
+void test_vld3_dup_s8(int8x8x3_t *dest, const int8_t *src) {
+ *dest = vld3_dup_s8(src);
+}
+
+// CHECK-LABEL: @test_vld3_dup_u16(
+// CHECK: [[__RET:%.*]] = alloca %struct.uint16x4x3_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK-A64: [[VLD3:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld3r.v4i16.p0i16(i16* [[TMP2]])
+// CHECK-A32: [[VLD3:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld3dup.v4i16.p0i8(i8* [[TMP1]], i32 2)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16> }*
+// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD3]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x4x3_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x4x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 24, i1 false)
+// CHECK: ret void
+void test_vld3_dup_u16(uint16x4x3_t *dest, const uint16_t *src) {
+ *dest = vld3_dup_u16(src);
+}
+
+// CHECK-LABEL: @test_vld3_dup_u32(
+// CHECK: [[__RET:%.*]] = alloca %struct.uint32x2x3_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i32* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
+// CHECK-A64: [[VLD3:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32> } @llvm.aarch64.neon.ld3r.v2i32.p0i32(i32* [[TMP2]])
+// CHECK-A32: [[VLD3:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32> } @llvm.arm.neon.vld3dup.v2i32.p0i8(i8* [[TMP1]], i32 4)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32>, <2 x i32> }*
+// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32> } [[VLD3]], { <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x2x3_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x2x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 24, i1 false)
+// CHECK: ret void
+void test_vld3_dup_u32(uint32x2x3_t *dest, const uint32_t *src) {
+ *dest = vld3_dup_u32(src);
+}
+
+// CHECK-LABEL: @test_vld3_dup_u8(
+// CHECK: [[__RET:%.*]] = alloca %struct.uint8x8x3_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x3_t* [[__RET]] to i8*
+// CHECK-A64: [[VLD3:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld3r.v8i8.p0i8(i8* %src)
+// CHECK-A32: [[VLD3:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.arm.neon.vld3dup.v8i8.p0i8(i8* %src, i32 1)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8> }*
+// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD3]], { <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x8x3_t* %dest to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], {{i64|i32}} 24, i1 false)
+// CHECK: ret void
+void test_vld3_dup_u8(uint8x8x3_t *dest, const uint8_t *src) {
+ *dest = vld3_dup_u8(src);
+}
+
+// CHECK-LABEL: @test_vld3_dup_s64(
+// CHECK: [[__RET:%.*]] = alloca %struct.int64x1x3_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i64* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
+// CHECK-A64: [[VLD3:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64> } @llvm.aarch64.neon.ld3r.v1i64.p0i64(i64* [[TMP2]])
+// CHECK-A32: [[VLD3:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64> } @llvm.arm.neon.vld3dup.v1i64.p0i8(i8* [[TMP1]], i32 8)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64>, <1 x i64> }*
+// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64> } [[VLD3]], { <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x1x3_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.int64x1x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 24, i1 false)
+// CHECK: ret void
+void test_vld3_dup_s64(int64x1x3_t *dest, const int64_t *src) {
+ *dest = vld3_dup_s64(src);
+}
+
+// CHECK-LABEL: @test_vld3_dup_u64(
+// CHECK: [[__RET:%.*]] = alloca %struct.uint64x1x3_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i64* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
+// CHECK-A64: [[VLD3:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64> } @llvm.aarch64.neon.ld3r.v1i64.p0i64(i64* [[TMP2]])
+// CHECK-A32: [[VLD3:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64> } @llvm.arm.neon.vld3dup.v1i64.p0i8(i8* [[TMP1]], i32 8)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64>, <1 x i64> }*
+// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64> } [[VLD3]], { <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x1x3_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.uint64x1x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 24, i1 false)
+// CHECK: ret void
+void test_vld3_dup_u64(uint64x1x3_t *dest, const uint64_t *src) {
+ *dest = vld3_dup_u64(src);
+}
+
+// CHECK-LABEL: @test_vld4_dup_f16(
+// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x4_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast half* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half*
+// CHECK-A64: [[VLD4:%.*]] = call { <4 x half>, <4 x half>, <4 x half>, <4 x half> } @llvm.aarch64.neon.ld4r.v4f16.p0f16(half* [[TMP2]])
+// CHECK-A32: [[VLD4:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld4dup.v4i16.p0i8(i8* [[TMP1]], i32 2)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]> }*
+// CHECK: store { <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]> } [[VLD4]], { <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x4x4_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK: ret void
+void test_vld4_dup_f16(float16x4x4_t *dest, const float16_t *src) {
+ *dest = vld4_dup_f16(src);
+}
+
+// CHECK-LABEL: @test_vld4_dup_f32(
+// CHECK: [[__RET:%.*]] = alloca %struct.float32x2x4_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast float* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float*
+// CHECK-A64: [[VLD4:%.*]] = call { <2 x float>, <2 x float>, <2 x float>, <2 x float> } @llvm.aarch64.neon.ld4r.v2f32.p0f32(float* [[TMP2]])
+// CHECK-A32: [[VLD4:%.*]] = call { <2 x float>, <2 x float>, <2 x float>, <2 x float> } @llvm.arm.neon.vld4dup.v2f32.p0i8(i8* [[TMP1]], i32 4)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x float>, <2 x float>, <2 x float>, <2 x float> }*
+// CHECK: store { <2 x float>, <2 x float>, <2 x float>, <2 x float> } [[VLD4]], { <2 x float>, <2 x float>, <2 x float>, <2 x float> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x2x4_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x2x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK: ret void
+void test_vld4_dup_f32(float32x2x4_t *dest, const float32_t *src) {
+ *dest = vld4_dup_f32(src);
+}
+
+// CHECK-LABEL: @test_vld4_dup_p16(
+// CHECK: [[__RET:%.*]] = alloca %struct.poly16x4x4_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK-A64: [[VLD4:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld4r.v4i16.p0i16(i16* [[TMP2]])
+// CHECK-A32: [[VLD4:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld4dup.v4i16.p0i8(i8* [[TMP1]], i32 2)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }*
+// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD4]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x4x4_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x4x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK: ret void
+void test_vld4_dup_p16(poly16x4x4_t *dest, const poly16_t *src) {
+ *dest = vld4_dup_p16(src);
+}
+
+// CHECK-LABEL: @test_vld4_dup_p8(
+// CHECK: [[__RET:%.*]] = alloca %struct.poly8x8x4_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x4_t* [[__RET]] to i8*
+// CHECK-A64: [[VLD4:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld4r.v8i8.p0i8(i8* %src)
+// CHECK-A32: [[VLD4:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.arm.neon.vld4dup.v8i8.p0i8(i8* %src, i32 1)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }*
+// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[VLD4]], { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x8x4_t* %dest to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], {{i64|i32}} 32, i1 false)
+// CHECK: ret void
+void test_vld4_dup_p8(poly8x8x4_t *dest, const poly8_t *src) {
+ *dest = vld4_dup_p8(src);
+}
+
+// CHECK-LABEL: @test_vld4_dup_s16(
+// CHECK: [[__RET:%.*]] = alloca %struct.int16x4x4_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK-A64: [[VLD4:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld4r.v4i16.p0i16(i16* [[TMP2]])
+// CHECK-A32: [[VLD4:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld4dup.v4i16.p0i8(i8* [[TMP1]], i32 2)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }*
+// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD4]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x4x4_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x4x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK: ret void
+void test_vld4_dup_s16(int16x4x4_t *dest, const int16_t *src) {
+ *dest = vld4_dup_s16(src);
+}
+
+// CHECK-LABEL: @test_vld4_dup_s32(
+// CHECK: [[__RET:%.*]] = alloca %struct.int32x2x4_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i32* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
+// CHECK-A64: [[VLD4:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } @llvm.aarch64.neon.ld4r.v2i32.p0i32(i32* [[TMP2]])
+// CHECK-A32: [[VLD4:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } @llvm.arm.neon.vld4dup.v2i32.p0i8(i8* [[TMP1]], i32 4)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }*
+// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[VLD4]], { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x2x4_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x2x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK: ret void
+void test_vld4_dup_s32(int32x2x4_t *dest, const int32_t *src) {
+ *dest = vld4_dup_s32(src);
+}
+
+// CHECK-LABEL: @test_vld4_dup_s8(
+// CHECK: [[__RET:%.*]] = alloca %struct.int8x8x4_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x4_t* [[__RET]] to i8*
+// CHECK-A64: [[VLD4:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld4r.v8i8.p0i8(i8* %src)
+// CHECK-A32: [[VLD4:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.arm.neon.vld4dup.v8i8.p0i8(i8* %src, i32 1)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }*
+// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[VLD4]], { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x8x4_t* %dest to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], {{i64|i32}} 32, i1 false)
+// CHECK: ret void
+void test_vld4_dup_s8(int8x8x4_t *dest, const int8_t *src) {
+ *dest = vld4_dup_s8(src);
+}
+
+// CHECK-LABEL: @test_vld4_dup_u16(
+// CHECK: [[__RET:%.*]] = alloca %struct.uint16x4x4_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK-A64: [[VLD4:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld4r.v4i16.p0i16(i16* [[TMP2]])
+// CHECK-A32: [[VLD4:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld4dup.v4i16.p0i8(i8* [[TMP1]], i32 2)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }*
+// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD4]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x4x4_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x4x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK: ret void
+void test_vld4_dup_u16(uint16x4x4_t *dest, const uint16_t *src) {
+ *dest = vld4_dup_u16(src);
+}
+
+// CHECK-LABEL: @test_vld4_dup_u32(
+// CHECK: [[__RET:%.*]] = alloca %struct.uint32x2x4_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i32* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
+// CHECK-A64: [[VLD4:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } @llvm.aarch64.neon.ld4r.v2i32.p0i32(i32* [[TMP2]])
+// CHECK-A32: [[VLD4:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } @llvm.arm.neon.vld4dup.v2i32.p0i8(i8* [[TMP1]], i32 4)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }*
+// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[VLD4]], { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x2x4_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x2x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK: ret void
+void test_vld4_dup_u32(uint32x2x4_t *dest, const uint32_t *src) {
+ *dest = vld4_dup_u32(src);
+}
+
+// CHECK-LABEL: @test_vld4_dup_u8(
+// CHECK: [[__RET:%.*]] = alloca %struct.uint8x8x4_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x4_t* [[__RET]] to i8*
+// CHECK-A64: [[VLD4:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld4r.v8i8.p0i8(i8* %src)
+// CHECK-A32: [[VLD4:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.arm.neon.vld4dup.v8i8.p0i8(i8* %src, i32 1)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }*
+// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[VLD4]], { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x8x4_t* %dest to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], {{i64|i32}} 32, i1 false)
+// CHECK: ret void
+void test_vld4_dup_u8(uint8x8x4_t *dest, const uint8_t *src) {
+ *dest = vld4_dup_u8(src);
+}
+
+// CHECK-LABEL: @test_vld4_dup_s64(
+// CHECK: [[__RET:%.*]] = alloca %struct.int64x1x4_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i64* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
+// CHECK-A64: [[VLD4:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } @llvm.aarch64.neon.ld4r.v1i64.p0i64(i64* [[TMP2]])
+// CHECK-A32: [[VLD4:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } @llvm.arm.neon.vld4dup.v1i64.p0i8(i8* [[TMP1]], i32 8)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }*
+// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } [[VLD4]], { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x1x4_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.int64x1x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK: ret void
+void test_vld4_dup_s64(int64x1x4_t *dest, const int64_t *src) {
+ *dest = vld4_dup_s64(src);
+}
+
+// CHECK-LABEL: @test_vld4_dup_u64(
+// CHECK: [[__RET:%.*]] = alloca %struct.uint64x1x4_t, align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i64* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64*
+// CHECK-A64: [[VLD4:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } @llvm.aarch64.neon.ld4r.v1i64.p0i64(i64* [[TMP2]])
+// CHECK-A32: [[VLD4:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } @llvm.arm.neon.vld4dup.v1i64.p0i8(i8* [[TMP1]], i32 8)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }*
+// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } [[VLD4]], { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x1x4_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.uint64x1x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK: ret void
+void test_vld4_dup_u64(uint64x1x4_t *dest, const uint64_t *src) {
+ *dest = vld4_dup_u64(src);
+}
+
+// CHECK-LABEL: @test_vld2q_dup_f16(
+// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x2_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast half* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half*
+// CHECK-A64: [[VLD2:%.*]] = call { <8 x half>, <8 x half> } @llvm.aarch64.neon.ld2r.v8f16.p0f16(half* [[TMP2]])
+// CHECK-A32: [[VLD2:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.arm.neon.vld2dup.v8i16.p0i8(i8* [[TMP1]], i32 2)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x [[HALF]]>, <8 x [[HALF]]> }*
+// CHECK: store { <8 x [[HALF]]>, <8 x [[HALF]]> } [[VLD2]], { <8 x [[HALF]]>, <8 x [[HALF]]> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x8x2_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK: ret void
+void test_vld2q_dup_f16(float16x8x2_t *dest, const float16_t *src) {
+ *dest = vld2q_dup_f16(src);
+}
+
+// CHECK-LABEL: @test_vld2q_dup_f32(
+// CHECK: [[__RET:%.*]] = alloca %struct.float32x4x2_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast float* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float*
+// CHECK-A64: [[VLD2:%.*]] = call { <4 x float>, <4 x float> } @llvm.aarch64.neon.ld2r.v4f32.p0f32(float* [[TMP2]])
+// CHECK-A32: [[VLD2:%.*]] = call { <4 x float>, <4 x float> } @llvm.arm.neon.vld2dup.v4f32.p0i8(i8* [[TMP1]], i32 4)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x float>, <4 x float> }*
+// CHECK: store { <4 x float>, <4 x float> } [[VLD2]], { <4 x float>, <4 x float> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x4x2_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x4x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK: ret void
+void test_vld2q_dup_f32(float32x4x2_t *dest, const float32_t *src) {
+ *dest = vld2q_dup_f32(src);
+}
+
+// CHECK-LABEL: @test_vld2q_dup_p16(
+// CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x2_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK-A64: [[VLD2:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld2r.v8i16.p0i16(i16* [[TMP2]])
+// CHECK-A32: [[VLD2:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.arm.neon.vld2dup.v8i16.p0i8(i8* [[TMP1]], i32 2)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16> }*
+// CHECK: store { <8 x i16>, <8 x i16> } [[VLD2]], { <8 x i16>, <8 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x8x2_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK: ret void
+void test_vld2q_dup_p16(poly16x8x2_t *dest, const poly16_t *src) {
+ *dest = vld2q_dup_p16(src);
+}
+
+// CHECK-LABEL: @test_vld2q_dup_p8(
+// CHECK: [[__RET:%.*]] = alloca %struct.poly8x16x2_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET]] to i8*
+// CHECK-A64: [[VLD2:%.*]] = call { <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld2r.v16i8.p0i8(i8* %src)
+// CHECK-A32: [[VLD2:%.*]] = call { <16 x i8>, <16 x i8> } @llvm.arm.neon.vld2dup.v16i8.p0i8(i8* %src, i32 1)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8> }*
+// CHECK: store { <16 x i8>, <16 x i8> } [[VLD2]], { <16 x i8>, <16 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x16x2_t* %dest to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP2]], i8* align {{16|8}} [[TMP3]], {{i64|i32}} 32, i1 false)
+// CHECK: ret void
+void test_vld2q_dup_p8(poly8x16x2_t *dest, const poly8_t *src) {
+ *dest = vld2q_dup_p8(src);
+}
+
+// CHECK-LABEL: @test_vld2q_dup_s16(
+// CHECK: [[__RET:%.*]] = alloca %struct.int16x8x2_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK-A64: [[VLD2:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld2r.v8i16.p0i16(i16* [[TMP2]])
+// CHECK-A32: [[VLD2:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.arm.neon.vld2dup.v8i16.p0i8(i8* [[TMP1]], i32 2)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16> }*
+// CHECK: store { <8 x i16>, <8 x i16> } [[VLD2]], { <8 x i16>, <8 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x8x2_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x8x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK: ret void
+void test_vld2q_dup_s16(int16x8x2_t *dest, const int16_t *src) {
+ *dest = vld2q_dup_s16(src);
+}
+
+// CHECK-LABEL: @test_vld2q_dup_s32(
+// CHECK: [[__RET:%.*]] = alloca %struct.int32x4x2_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i32* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
+// CHECK-A64: [[VLD2:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2r.v4i32.p0i32(i32* [[TMP2]])
+// CHECK-A32: [[VLD2:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.arm.neon.vld2dup.v4i32.p0i8(i8* [[TMP1]], i32 4)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32> }*
+// CHECK: store { <4 x i32>, <4 x i32> } [[VLD2]], { <4 x i32>, <4 x i32> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x4x2_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x4x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK: ret void
+void test_vld2q_dup_s32(int32x4x2_t *dest, const int32_t *src) {
+ *dest = vld2q_dup_s32(src);
+}
+
+// CHECK-LABEL: @test_vld2q_dup_s8(
+// CHECK: [[__RET:%.*]] = alloca %struct.int8x16x2_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[__RET]] to i8*
+// CHECK-A64: [[VLD2:%.*]] = call { <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld2r.v16i8.p0i8(i8* %src)
+// CHECK-A32: [[VLD2:%.*]] = call { <16 x i8>, <16 x i8> } @llvm.arm.neon.vld2dup.v16i8.p0i8(i8* %src, i32 1)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8> }*
+// CHECK: store { <16 x i8>, <16 x i8> } [[VLD2]], { <16 x i8>, <16 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x16x2_t* %dest to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP2]], i8* align {{16|8}} [[TMP3]], {{i64|i32}} 32, i1 false)
+// CHECK: ret void
+void test_vld2q_dup_s8(int8x16x2_t *dest, const int8_t *src) {
+ *dest = vld2q_dup_s8(src);
+}
+
+// CHECK-LABEL: @test_vld2q_dup_u16(
+// CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x2_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK-A64: [[VLD2:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld2r.v8i16.p0i16(i16* [[TMP2]])
+// CHECK-A32: [[VLD2:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.arm.neon.vld2dup.v8i16.p0i8(i8* [[TMP1]], i32 2)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16> }*
+// CHECK: store { <8 x i16>, <8 x i16> } [[VLD2]], { <8 x i16>, <8 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x8x2_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK: ret void
+void test_vld2q_dup_u16(uint16x8x2_t *dest, const uint16_t *src) {
+ *dest = vld2q_dup_u16(src);
+}
+
+// CHECK-LABEL: @test_vld2q_dup_u32(
+// CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x2_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i32* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
+// CHECK-A64: [[VLD2:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2r.v4i32.p0i32(i32* [[TMP2]])
+// CHECK-A32: [[VLD2:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.arm.neon.vld2dup.v4i32.p0i8(i8* [[TMP1]], i32 4)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32> }*
+// CHECK: store { <4 x i32>, <4 x i32> } [[VLD2]], { <4 x i32>, <4 x i32> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x4x2_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 32, i1 false)
+// CHECK: ret void
+void test_vld2q_dup_u32(uint32x4x2_t *dest, const uint32_t *src) {
+ *dest = vld2q_dup_u32(src);
+}
+
+// CHECK-LABEL: @test_vld2q_dup_u8(
+// CHECK: [[__RET:%.*]] = alloca %struct.uint8x16x2_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET]] to i8*
+// CHECK-A64: [[VLD2:%.*]] = call { <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld2r.v16i8.p0i8(i8* %src)
+// CHECK-A32: [[VLD2:%.*]] = call { <16 x i8>, <16 x i8> } @llvm.arm.neon.vld2dup.v16i8.p0i8(i8* %src, i32 1)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8> }*
+// CHECK: store { <16 x i8>, <16 x i8> } [[VLD2]], { <16 x i8>, <16 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x16x2_t* %dest to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP2]], i8* align {{16|8}} [[TMP3]], {{i64|i32}} 32, i1 false)
+// CHECK: ret void
+void test_vld2q_dup_u8(uint8x16x2_t *dest, const uint8_t *src) {
+ *dest = vld2q_dup_u8(src);
+}
+
+// CHECK-LABEL: @test_vld3q_dup_f16(
+// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x3_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast half* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half*
+// CHECK-A64: [[VLD3:%.*]] = call { <8 x half>, <8 x half>, <8 x half> } @llvm.aarch64.neon.ld3r.v8f16.p0f16(half* [[TMP2]])
+// CHECK-A32: [[VLD3:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld3dup.v8i16.p0i8(i8* [[TMP1]], i32 2)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]> }*
+// CHECK: store { <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]> } [[VLD3]], { <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x8x3_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 48, i1 false)
+// CHECK: ret void
+void test_vld3q_dup_f16(float16x8x3_t *dest, const float16_t *src) {
+ *dest = vld3q_dup_f16(src);
+}
+
+// CHECK-LABEL: @test_vld3q_dup_f32(
+// CHECK: [[__RET:%.*]] = alloca %struct.float32x4x3_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast float* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float*
+// CHECK-A64: [[VLD3:%.*]] = call { <4 x float>, <4 x float>, <4 x float> } @llvm.aarch64.neon.ld3r.v4f32.p0f32(float* [[TMP2]])
+// CHECK-A32: [[VLD3:%.*]] = call { <4 x float>, <4 x float>, <4 x float> } @llvm.arm.neon.vld3dup.v4f32.p0i8(i8* [[TMP1]], i32 4)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x float>, <4 x float>, <4 x float> }*
+// CHECK: store { <4 x float>, <4 x float>, <4 x float> } [[VLD3]], { <4 x float>, <4 x float>, <4 x float> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x4x3_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x4x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 48, i1 false)
+// CHECK: ret void
+void test_vld3q_dup_f32(float32x4x3_t *dest, const float32_t *src) {
+ *dest = vld3q_dup_f32(src);
+}
+
+// CHECK-LABEL: @test_vld3q_dup_p16(
+// CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x3_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK-A64: [[VLD3:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld3r.v8i16.p0i16(i16* [[TMP2]])
+// CHECK-A32: [[VLD3:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld3dup.v8i16.p0i8(i8* [[TMP1]], i32 2)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16> }*
+// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD3]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x8x3_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x8x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 48, i1 false)
+// CHECK: ret void
+void test_vld3q_dup_p16(poly16x8x3_t *dest, const poly16_t *src) {
+ *dest = vld3q_dup_p16(src);
+}
+
+// CHECK-LABEL: @test_vld3q_dup_p8(
+// CHECK: [[__RET:%.*]] = alloca %struct.poly8x16x3_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x3_t* [[__RET]] to i8*
+// CHECK-A64: [[VLD3:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld3r.v16i8.p0i8(i8* %src)
+// CHECK-A32: [[VLD3:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8> } @llvm.arm.neon.vld3dup.v16i8.p0i8(i8* %src, i32 1)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8> }*
+// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8> } [[VLD3]], { <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x16x3_t* %dest to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP2]], i8* align {{16|8}} [[TMP3]], {{i64|i32}} 48, i1 false)
+// CHECK: ret void
+void test_vld3q_dup_p8(poly8x16x3_t *dest, const poly8_t *src) {
+ *dest = vld3q_dup_p8(src);
+}
+
+// CHECK-LABEL: @test_vld3q_dup_s16(
+// CHECK: [[__RET:%.*]] = alloca %struct.int16x8x3_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK-A64: [[VLD3:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld3r.v8i16.p0i16(i16* [[TMP2]])
+// CHECK-A32: [[VLD3:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld3dup.v8i16.p0i8(i8* [[TMP1]], i32 2)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16> }*
+// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD3]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x8x3_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x8x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 48, i1 false)
+// CHECK: ret void
+void test_vld3q_dup_s16(int16x8x3_t *dest, const int16_t *src) {
+ *dest = vld3q_dup_s16(src);
+}
+
+// CHECK-LABEL: @test_vld3q_dup_s32(
+// CHECK: [[__RET:%.*]] = alloca %struct.int32x4x3_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i32* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
+// CHECK-A64: [[VLD3:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld3r.v4i32.p0i32(i32* [[TMP2]])
+// CHECK-A32: [[VLD3:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.arm.neon.vld3dup.v4i32.p0i8(i8* [[TMP1]], i32 4)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32>, <4 x i32> }*
+// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32> } [[VLD3]], { <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x4x3_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x4x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 48, i1 false)
+// CHECK: ret void
+void test_vld3q_dup_s32(int32x4x3_t *dest, const int32_t *src) {
+ *dest = vld3q_dup_s32(src);
+}
+
+// CHECK-LABEL: @test_vld3q_dup_s8(
+// CHECK: [[__RET:%.*]] = alloca %struct.int8x16x3_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x3_t* [[__RET]] to i8*
+// CHECK-A64: [[VLD3:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld3r.v16i8.p0i8(i8* %src)
+// CHECK-A32: [[VLD3:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8> } @llvm.arm.neon.vld3dup.v16i8.p0i8(i8* %src, i32 1)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8> }*
+// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8> } [[VLD3]], { <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x16x3_t* %dest to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP2]], i8* align {{16|8}} [[TMP3]], {{i64|i32}} 48, i1 false)
+// CHECK: ret void
+void test_vld3q_dup_s8(int8x16x3_t *dest, const int8_t *src) {
+ *dest = vld3q_dup_s8(src);
+}
+
+// CHECK-LABEL: @test_vld3q_dup_u16(
+// CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x3_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK-A64: [[VLD3:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld3r.v8i16.p0i16(i16* [[TMP2]])
+// CHECK-A32: [[VLD3:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld3dup.v8i16.p0i8(i8* [[TMP1]], i32 2)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16> }*
+// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD3]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x8x3_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x8x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 48, i1 false)
+// CHECK: ret void
+void test_vld3q_dup_u16(uint16x8x3_t *dest, const uint16_t *src) {
+ *dest = vld3q_dup_u16(src);
+}
+
+// CHECK-LABEL: @test_vld3q_dup_u32(
+// CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x3_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x3_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i32* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
+// CHECK-A64: [[VLD3:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld3r.v4i32.p0i32(i32* [[TMP2]])
+// CHECK-A32: [[VLD3:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.arm.neon.vld3dup.v4i32.p0i8(i8* [[TMP1]], i32 4)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32>, <4 x i32> }*
+// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32> } [[VLD3]], { <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x4x3_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x4x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 48, i1 false)
+// CHECK: ret void
+void test_vld3q_dup_u32(uint32x4x3_t *dest, const uint32_t *src) {
+ *dest = vld3q_dup_u32(src);
+}
+
+// CHECK-LABEL: @test_vld3q_dup_u8(
+// CHECK: [[__RET:%.*]] = alloca %struct.uint8x16x3_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x3_t* [[__RET]] to i8*
+// CHECK-A64: [[VLD3:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld3r.v16i8.p0i8(i8* %src)
+// CHECK-A32: [[VLD3:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8> } @llvm.arm.neon.vld3dup.v16i8.p0i8(i8* %src, i32 1)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8> }*
+// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8> } [[VLD3]], { <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x16x3_t* %dest to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x3_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP2]], i8* align {{16|8}} [[TMP3]], {{i64|i32}} 48, i1 false)
+// CHECK: ret void
+void test_vld3q_dup_u8(uint8x16x3_t *dest, const uint8_t *src) {
+ *dest = vld3q_dup_u8(src);
+}
+
+// CHECK-LABEL: @test_vld4q_dup_f16(
+// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x4_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast half* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half*
+// CHECK-A64: [[VLD4:%.*]] = call { <8 x half>, <8 x half>, <8 x half>, <8 x half> } @llvm.aarch64.neon.ld4r.v8f16.p0f16(half* [[TMP2]])
+// CHECK-A32: [[VLD4:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld4dup.v8i16.p0i8(i8* [[TMP1]], i32 2)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]> }*
+// CHECK: store { <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]> } [[VLD4]], { <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x8x4_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 64, i1 false)
+// CHECK: ret void
+void test_vld4q_dup_f16(float16x8x4_t *dest, const float16_t *src) {
+ *dest = vld4q_dup_f16(src);
+}
+
+// CHECK-LABEL: @test_vld4q_dup_f32(
+// CHECK: [[__RET:%.*]] = alloca %struct.float32x4x4_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast float* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float*
+// CHECK-A64: [[VLD4:%.*]] = call { <4 x float>, <4 x float>, <4 x float>, <4 x float> } @llvm.aarch64.neon.ld4r.v4f32.p0f32(float* [[TMP2]])
+// CHECK-A32: [[VLD4:%.*]] = call { <4 x float>, <4 x float>, <4 x float>, <4 x float> } @llvm.arm.neon.vld4dup.v4f32.p0i8(i8* [[TMP1]], i32 4)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x float>, <4 x float>, <4 x float>, <4 x float> }*
+// CHECK: store { <4 x float>, <4 x float>, <4 x float>, <4 x float> } [[VLD4]], { <4 x float>, <4 x float>, <4 x float>, <4 x float> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x4x4_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x4x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 64, i1 false)
+// CHECK: ret void
+void test_vld4q_dup_f32(float32x4x4_t *dest, const float32_t *src) {
+ *dest = vld4q_dup_f32(src);
+}
+
+// CHECK-LABEL: @test_vld4q_dup_p16(
+// CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x4_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK-A64: [[VLD4:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld4r.v8i16.p0i16(i16* [[TMP2]])
+// CHECK-A32: [[VLD4:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld4dup.v8i16.p0i8(i8* [[TMP1]], i32 2)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }*
+// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } [[VLD4]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x8x4_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x8x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 64, i1 false)
+// CHECK: ret void
+void test_vld4q_dup_p16(poly16x8x4_t *dest, const poly16_t *src) {
+ *dest = vld4q_dup_p16(src);
+}
+
+// CHECK-LABEL: @test_vld4q_dup_p8(
+// CHECK: [[__RET:%.*]] = alloca %struct.poly8x16x4_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x4_t* [[__RET]] to i8*
+// CHECK-A64: [[VLD4:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld4r.v16i8.p0i8(i8* %src)
+// CHECK-A32: [[VLD4:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.arm.neon.vld4dup.v16i8.p0i8(i8* %src, i32 1)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }*
+// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } [[VLD4]], { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x16x4_t* %dest to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP2]], i8* align {{16|8}} [[TMP3]], {{i64|i32}} 64, i1 false)
+// CHECK: ret void
+void test_vld4q_dup_p8(poly8x16x4_t *dest, const poly8_t *src) {
+ *dest = vld4q_dup_p8(src);
+}
+
+// CHECK-LABEL: @test_vld4q_dup_s16(
+// CHECK: [[__RET:%.*]] = alloca %struct.int16x8x4_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK-A64: [[VLD4:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld4r.v8i16.p0i16(i16* [[TMP2]])
+// CHECK-A32: [[VLD4:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld4dup.v8i16.p0i8(i8* [[TMP1]], i32 2)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }*
+// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } [[VLD4]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x8x4_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x8x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 64, i1 false)
+// CHECK: ret void
+void test_vld4q_dup_s16(int16x8x4_t *dest, const int16_t *src) {
+ *dest = vld4q_dup_s16(src);
+}
+
+// CHECK-LABEL: @test_vld4q_dup_s32(
+// CHECK: [[__RET:%.*]] = alloca %struct.int32x4x4_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i32* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
+// CHECK-A64: [[VLD4:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld4r.v4i32.p0i32(i32* [[TMP2]])
+// CHECK-A32: [[VLD4:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } @llvm.arm.neon.vld4dup.v4i32.p0i8(i8* [[TMP1]], i32 4)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> }*
+// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLD4]], { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x4x4_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x4x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 64, i1 false)
+// CHECK: ret void
+void test_vld4q_dup_s32(int32x4x4_t *dest, const int32_t *src) {
+ *dest = vld4q_dup_s32(src);
+}
+
+// CHECK-LABEL: @test_vld4q_dup_s8(
+// CHECK: [[__RET:%.*]] = alloca %struct.int8x16x4_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x4_t* [[__RET]] to i8*
+// CHECK-A64: [[VLD4:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld4r.v16i8.p0i8(i8* %src)
+// CHECK-A32: [[VLD4:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.arm.neon.vld4dup.v16i8.p0i8(i8* %src, i32 1)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }*
+// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } [[VLD4]], { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x16x4_t* %dest to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP2]], i8* align {{16|8}} [[TMP3]], {{i64|i32}} 64, i1 false)
+// CHECK: ret void
+void test_vld4q_dup_s8(int8x16x4_t *dest, const int8_t *src) {
+ *dest = vld4q_dup_s8(src);
+}
+
+// CHECK-LABEL: @test_vld4q_dup_u16(
+// CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x4_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
+// CHECK-A64: [[VLD4:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld4r.v8i16.p0i16(i16* [[TMP2]])
+// CHECK-A32: [[VLD4:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld4dup.v8i16.p0i8(i8* [[TMP1]], i32 2)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }*
+// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } [[VLD4]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x8x4_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x8x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 64, i1 false)
+// CHECK: ret void
+void test_vld4q_dup_u16(uint16x8x4_t *dest, const uint16_t *src) {
+ *dest = vld4q_dup_u16(src);
+}
+
+// CHECK-LABEL: @test_vld4q_dup_u32(
+// CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x4_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x4_t* [[__RET]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast i32* %src to i8*
+// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
+// CHECK-A64: [[VLD4:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld4r.v4i32.p0i32(i32* [[TMP2]])
+// CHECK-A32: [[VLD4:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } @llvm.arm.neon.vld4dup.v4i32.p0i8(i8* [[TMP1]], i32 4)
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> }*
+// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLD4]], { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP3]]
+// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x4x4_t* %dest to i8*
+// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x4x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 64, i1 false)
+// CHECK: ret void
+void test_vld4q_dup_u32(uint32x4x4_t *dest, const uint32_t *src) {
+ *dest = vld4q_dup_u32(src);
+}
+
+// CHECK-LABEL: @test_vld4q_dup_u8(
+// CHECK: [[__RET:%.*]] = alloca %struct.uint8x16x4_t, align {{16|8}}
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x4_t* [[__RET]] to i8*
+// CHECK-A64: [[VLD4:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld4r.v16i8.p0i8(i8* %src)
+// CHECK-A32: [[VLD4:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.arm.neon.vld4dup.v16i8.p0i8(i8* %src, i32 1)
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }*
+// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } [[VLD4]], { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]]
+// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x16x4_t* %dest to i8*
+// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x4_t* [[__RET]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP2]], i8* align {{16|8}} [[TMP3]], {{i64|i32}} 64, i1 false)
+// CHECK: ret void
+void test_vld4q_dup_u8(uint8x16x4_t *dest, const uint8_t *src) {
+ *dest = vld4q_dup_u8(src);
+}
diff --git a/test/CodeGen/arm-neon-vst.c b/test/CodeGen/arm-neon-vst.c
new file mode 100644
index 000000000000..404c4d9c295c
--- /dev/null
+++ b/test/CodeGen/arm-neon-vst.c
@@ -0,0 +1,2312 @@
+// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon \
+// RUN: -S -disable-O0-optnone -emit-llvm -o - %s | opt -S -mem2reg | \
+// RUN: FileCheck -check-prefixes=CHECK,CHECK-A64 %s
+// RUN: %clang_cc1 -triple armv8-none-linux-gnueabi -target-feature +neon \
+// RUN: -S -disable-O0-optnone -emit-llvm -o - %s | opt -S -mem2reg | \
+// RUN: FileCheck -check-prefixes=CHECK,CHECK-A32 %s
+
+#include <arm_neon.h>
+
+// CHECK-LABEL: @test_vst1_f16_x2(
+// CHECK: [[B:%.*]] = alloca %struct.float16x4x2_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.float16x4x2_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x4x2_t, %struct.float16x4x2_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [2 x <4 x half>] [[B]].coerce, [2 x <4 x half>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <4 x half>]* %coerce.dive to [2 x i64]*
+// CHECK-A32: store [2 x i64] %b.coerce, [2 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x2_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x4x2_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 16, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x4x2_t, %struct.float16x4x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x half>], [2 x <4 x half>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX]], align 8
+// CHECK: [[TMP4:%.*]] = bitcast <4 x half> [[TMP3]] to <8 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float16x4x2_t, %struct.float16x4x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x half>], [2 x <4 x half>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX2]], align 8
+// CHECK: [[TMP6:%.*]] = bitcast <4 x half> [[TMP5]] to <8 x i8>
+// CHECK-DAG: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x [[HALF:(half|i16)]]>
+// CHECK-DAG: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x [[HALF]]>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to [[HALF]]*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v4f16.p0f16(<4 x half> [[TMP7]], <4 x half> [[TMP8]], half* [[TMP9]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i16.v4i16(i16* [[TMP9]], <4 x i16> [[TMP7]], <4 x i16> [[TMP8]])
+// CHECK: ret void
+void test_vst1_f16_x2(float16_t *a, float16x4x2_t b) {
+ vst1_f16_x2(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_f16_x3(
+// CHECK: [[B:%.*]] = alloca %struct.float16x4x3_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.float16x4x3_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x4x3_t, %struct.float16x4x3_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [3 x <4 x half>] [[B]].coerce, [3 x <4 x half>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <4 x half>]* %coerce.dive to [3 x i64]*
+// CHECK-A32: store [3 x i64] %b.coerce, [3 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x3_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x4x3_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 24, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x4x3_t, %struct.float16x4x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x half>], [3 x <4 x half>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX]], align 8
+// CHECK: [[TMP4:%.*]] = bitcast <4 x half> [[TMP3]] to <8 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float16x4x3_t, %struct.float16x4x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x half>], [3 x <4 x half>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX2]], align 8
+// CHECK: [[TMP6:%.*]] = bitcast <4 x half> [[TMP5]] to <8 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float16x4x3_t, %struct.float16x4x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x half>], [3 x <4 x half>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX4]], align 8
+// CHECK: [[TMP8:%.*]] = bitcast <4 x half> [[TMP7]] to <8 x i8>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x [[HALF]]>
+// CHECK-DAG: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x [[HALF]]>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x [[HALF]]>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to [[HALF]]*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v4f16.p0f16(<4 x half> [[TMP9]], <4 x half> [[TMP10]], <4 x half> [[TMP11]], half* [[TMP12]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i16.v4i16(i16* [[TMP12]], <4 x i16> [[TMP9]], <4 x i16> [[TMP10]], <4 x i16> [[TMP11]])
+// CHECK: ret void
+void test_vst1_f16_x3(float16_t *a, float16x4x3_t b) {
+ vst1_f16_x3(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_f16_x4(
+// CHECK: [[B:%.*]] = alloca %struct.float16x4x4_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.float16x4x4_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x4x4_t, %struct.float16x4x4_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [4 x <4 x half>] [[B]].coerce, [4 x <4 x half>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <4 x half>]* %coerce.dive to [4 x i64]*
+// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x4_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x4x4_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 32, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x4x4_t, %struct.float16x4x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x half>], [4 x <4 x half>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX]], align 8
+// CHECK: [[TMP4:%.*]] = bitcast <4 x half> [[TMP3]] to <8 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float16x4x4_t, %struct.float16x4x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x half>], [4 x <4 x half>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX2]], align 8
+// CHECK: [[TMP6:%.*]] = bitcast <4 x half> [[TMP5]] to <8 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float16x4x4_t, %struct.float16x4x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x half>], [4 x <4 x half>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX4]], align 8
+// CHECK: [[TMP8:%.*]] = bitcast <4 x half> [[TMP7]] to <8 x i8>
+// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.float16x4x4_t, %struct.float16x4x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x half>], [4 x <4 x half>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3
+// CHECK: [[TMP9:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX6]], align 8
+// CHECK: [[TMP10:%.*]] = bitcast <4 x half> [[TMP9]] to <8 x i8>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x [[HALF]]>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x [[HALF]]>
+// CHECK-DAG: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x [[HALF]]>
+// CHECK-DAG: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x [[HALF]]>
+// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to [[HALF]]*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v4f16.p0f16(<4 x half> [[TMP11]], <4 x half> [[TMP12]], <4 x half> [[TMP13]], <4 x half> [[TMP14]], half* [[TMP15]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i16.v4i16(i16* [[TMP15]], <4 x i16> [[TMP11]], <4 x i16> [[TMP12]], <4 x i16> [[TMP13]], <4 x i16> [[TMP14]])
+// CHECK: ret void
+void test_vst1_f16_x4(float16_t *a, float16x4x4_t b) {
+ vst1_f16_x4(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_f32_x2(
+// CHECK: [[B:%.*]] = alloca %struct.float32x2x2_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.float32x2x2_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x2x2_t, %struct.float32x2x2_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [2 x <2 x float>] [[B]].coerce, [2 x <2 x float>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <2 x float>]* %coerce.dive to [2 x i64]*
+// CHECK-A32: store [2 x i64] %b.coerce, [2 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x2x2_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 16, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x2x2_t, %struct.float32x2x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x float>], [2 x <2 x float>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX]], align 8
+// CHECK: [[TMP4:%.*]] = bitcast <2 x float> [[TMP3]] to <8 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float32x2x2_t, %struct.float32x2x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <2 x float>], [2 x <2 x float>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX2]], align 8
+// CHECK: [[TMP6:%.*]] = bitcast <2 x float> [[TMP5]] to <8 x i8>
+// CHECK-DAG: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x float>
+// CHECK-DAG: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x float>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to float*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v2f32.p0f32(<2 x float> [[TMP7]], <2 x float> [[TMP8]], float* [[TMP9]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0f32.v2f32(float* [[TMP9]], <2 x float> [[TMP7]], <2 x float> [[TMP8]])
+// CHECK: ret void
+void test_vst1_f32_x2(float32_t *a, float32x2x2_t b) {
+ vst1_f32_x2(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_f32_x3(
+// CHECK: [[B:%.*]] = alloca %struct.float32x2x3_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.float32x2x3_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x2x3_t, %struct.float32x2x3_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [3 x <2 x float>] [[B]].coerce, [3 x <2 x float>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <2 x float>]* %coerce.dive to [3 x i64]*
+// CHECK-A32: store [3 x i64] %b.coerce, [3 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x3_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x2x3_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 24, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x2x3_t, %struct.float32x2x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x float>], [3 x <2 x float>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX]], align 8
+// CHECK: [[TMP4:%.*]] = bitcast <2 x float> [[TMP3]] to <8 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float32x2x3_t, %struct.float32x2x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <2 x float>], [3 x <2 x float>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX2]], align 8
+// CHECK: [[TMP6:%.*]] = bitcast <2 x float> [[TMP5]] to <8 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float32x2x3_t, %struct.float32x2x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <2 x float>], [3 x <2 x float>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX4]], align 8
+// CHECK: [[TMP8:%.*]] = bitcast <2 x float> [[TMP7]] to <8 x i8>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x float>
+// CHECK-DAG: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x float>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <2 x float>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to float*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v2f32.p0f32(<2 x float> [[TMP9]], <2 x float> [[TMP10]], <2 x float> [[TMP11]], float* [[TMP12]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0f32.v2f32(float* [[TMP12]], <2 x float> [[TMP9]], <2 x float> [[TMP10]], <2 x float> [[TMP11]])
+// CHECK: ret void
+void test_vst1_f32_x3(float32_t *a, float32x2x3_t b) {
+ vst1_f32_x3(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_f32_x4(
+// CHECK: [[B:%.*]] = alloca %struct.float32x2x4_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.float32x2x4_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x2x4_t, %struct.float32x2x4_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [4 x <2 x float>] [[B]].coerce, [4 x <2 x float>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <2 x float>]* %coerce.dive to [4 x i64]*
+// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x4_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x2x4_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 32, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x2x4_t, %struct.float32x2x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x float>], [4 x <2 x float>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX]], align 8
+// CHECK: [[TMP4:%.*]] = bitcast <2 x float> [[TMP3]] to <8 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float32x2x4_t, %struct.float32x2x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <2 x float>], [4 x <2 x float>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX2]], align 8
+// CHECK: [[TMP6:%.*]] = bitcast <2 x float> [[TMP5]] to <8 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float32x2x4_t, %struct.float32x2x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <2 x float>], [4 x <2 x float>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX4]], align 8
+// CHECK: [[TMP8:%.*]] = bitcast <2 x float> [[TMP7]] to <8 x i8>
+// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.float32x2x4_t, %struct.float32x2x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <2 x float>], [4 x <2 x float>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3
+// CHECK: [[TMP9:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX6]], align 8
+// CHECK: [[TMP10:%.*]] = bitcast <2 x float> [[TMP9]] to <8 x i8>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x float>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x float>
+// CHECK-DAG: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <2 x float>
+// CHECK-DAG: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <2 x float>
+// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to float*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v2f32.p0f32(<2 x float> [[TMP11]], <2 x float> [[TMP12]], <2 x float> [[TMP13]], <2 x float> [[TMP14]], float* [[TMP15]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0f32.v2f32(float* [[TMP15]], <2 x float> [[TMP11]], <2 x float> [[TMP12]], <2 x float> [[TMP13]], <2 x float> [[TMP14]])
+// CHECK: ret void
+void test_vst1_f32_x4(float32_t *a, float32x2x4_t b) {
+ vst1_f32_x4(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_p16_x2(
+// CHECK: [[B:%.*]] = alloca %struct.poly16x4x2_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.poly16x4x2_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [2 x <4 x i16>] [[B]].coerce, [2 x <4 x i16>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <4 x i16>]* %coerce.dive to [2 x i64]*
+// CHECK-A32: store [2 x i64] %b.coerce, [2 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x4x2_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 16, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8
+// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8
+// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8>
+// CHECK-DAG: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16>
+// CHECK-DAG: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i16*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v4i16.p0i16(<4 x i16> [[TMP7]], <4 x i16> [[TMP8]], i16* [[TMP9]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i16.v4i16(i16* [[TMP9]], <4 x i16> [[TMP7]], <4 x i16> [[TMP8]])
+// CHECK: ret void
+void test_vst1_p16_x2(poly16_t *a, poly16x4x2_t b) {
+ vst1_p16_x2(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_p16_x3(
+// CHECK: [[B:%.*]] = alloca %struct.poly16x4x3_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.poly16x4x3_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x4x3_t, %struct.poly16x4x3_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [3 x <4 x i16>] [[B]].coerce, [3 x <4 x i16>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <4 x i16>]* %coerce.dive to [3 x i64]*
+// CHECK-A32: store [3 x i64] %b.coerce, [3 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x3_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x4x3_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 24, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x4x3_t, %struct.poly16x4x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8
+// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly16x4x3_t, %struct.poly16x4x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8
+// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly16x4x3_t, %struct.poly16x4x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX4]], align 8
+// CHECK: [[TMP8:%.*]] = bitcast <4 x i16> [[TMP7]] to <8 x i8>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16>
+// CHECK-DAG: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i16*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v4i16.p0i16(<4 x i16> [[TMP9]], <4 x i16> [[TMP10]], <4 x i16> [[TMP11]], i16* [[TMP12]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i16.v4i16(i16* [[TMP12]], <4 x i16> [[TMP9]], <4 x i16> [[TMP10]], <4 x i16> [[TMP11]])
+// CHECK: ret void
+void test_vst1_p16_x3(poly16_t *a, poly16x4x3_t b) {
+ vst1_p16_x3(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_p16_x4(
+// CHECK: [[B:%.*]] = alloca %struct.poly16x4x4_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.poly16x4x4_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x4x4_t, %struct.poly16x4x4_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [4 x <4 x i16>] [[B]].coerce, [4 x <4 x i16>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <4 x i16>]* %coerce.dive to [4 x i64]*
+// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x4_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x4x4_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 32, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x4x4_t, %struct.poly16x4x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8
+// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly16x4x4_t, %struct.poly16x4x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8
+// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly16x4x4_t, %struct.poly16x4x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX4]], align 8
+// CHECK: [[TMP8:%.*]] = bitcast <4 x i16> [[TMP7]] to <8 x i8>
+// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.poly16x4x4_t, %struct.poly16x4x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3
+// CHECK: [[TMP9:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX6]], align 8
+// CHECK: [[TMP10:%.*]] = bitcast <4 x i16> [[TMP9]] to <8 x i8>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
+// CHECK-DAG: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16>
+// CHECK-DAG: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x i16>
+// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i16*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v4i16.p0i16(<4 x i16> [[TMP11]], <4 x i16> [[TMP12]], <4 x i16> [[TMP13]], <4 x i16> [[TMP14]], i16* [[TMP15]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i16.v4i16(i16* [[TMP15]], <4 x i16> [[TMP11]], <4 x i16> [[TMP12]], <4 x i16> [[TMP13]], <4 x i16> [[TMP14]])
+// CHECK: ret void
+void test_vst1_p16_x4(poly16_t *a, poly16x4x4_t b) {
+ vst1_p16_x4(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_p8_x2(
+// CHECK: [[B:%.*]] = alloca %struct.poly8x8x2_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.poly8x8x2_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [2 x <8 x i8>] [[B]].coerce, [2 x <8 x i8>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <8 x i8>]* %coerce.dive to [2 x i64]*
+// CHECK-A32: store [2 x i64] %b.coerce, [2 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x8x2_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 16, i1 false)
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8
+// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], i8* %a)
+// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i8.v8i8(i8* %a, <8 x i8> [[TMP2]], <8 x i8> [[TMP3]])
+// CHECK: ret void
+void test_vst1_p8_x2(poly8_t *a, poly8x8x2_t b) {
+ vst1_p8_x2(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_p8_x3(
+// CHECK: [[B:%.*]] = alloca %struct.poly8x8x3_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.poly8x8x3_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x8x3_t, %struct.poly8x8x3_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [3 x <8 x i8>] [[B]].coerce, [3 x <8 x i8>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <8 x i8>]* %coerce.dive to [3 x i64]*
+// CHECK-A32: store [3 x i64] %b.coerce, [3 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x3_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x8x3_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 24, i1 false)
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x8x3_t, %struct.poly8x8x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly8x8x3_t, %struct.poly8x8x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly8x8x3_t, %struct.poly8x8x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP4:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX4]], align 8
+// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], i8* %a)
+// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i8.v8i8(i8* %a, <8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]])
+// CHECK: ret void
+void test_vst1_p8_x3(poly8_t *a, poly8x8x3_t b) {
+ vst1_p8_x3(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_p8_x4(
+// CHECK: [[B:%.*]] = alloca %struct.poly8x8x4_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.poly8x8x4_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [4 x <8 x i8>] [[B]].coerce, [4 x <8 x i8>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <8 x i8>]* %coerce.dive to [4 x i64]*
+// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x4_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x8x4_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 32, i1 false)
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP4:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX4]], align 8
+// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3
+// CHECK: [[TMP5:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX6]], align 8
+// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], <8 x i8> [[TMP5]], i8* %a)
+// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i8.v8i8(i8* %a, <8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], <8 x i8> [[TMP5]])
+// CHECK: ret void
+void test_vst1_p8_x4(poly8_t *a, poly8x8x4_t b) {
+ vst1_p8_x4(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_s16_x2(
+// CHECK: [[B:%.*]] = alloca %struct.int16x4x2_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.int16x4x2_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x4x2_t, %struct.int16x4x2_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [2 x <4 x i16>] [[B]].coerce, [2 x <4 x i16>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <4 x i16>]* %coerce.dive to [2 x i64]*
+// CHECK-A32: store [2 x i64] %b.coerce, [2 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x4x2_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 16, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x4x2_t, %struct.int16x4x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8
+// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int16x4x2_t, %struct.int16x4x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8
+// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8>
+// CHECK-DAG: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16>
+// CHECK-DAG: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i16*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v4i16.p0i16(<4 x i16> [[TMP7]], <4 x i16> [[TMP8]], i16* [[TMP9]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i16.v4i16(i16* [[TMP9]], <4 x i16> [[TMP7]], <4 x i16> [[TMP8]])
+// CHECK: ret void
+void test_vst1_s16_x2(int16_t *a, int16x4x2_t b) {
+ vst1_s16_x2(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_s16_x3(
+// CHECK: [[B:%.*]] = alloca %struct.int16x4x3_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.int16x4x3_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x4x3_t, %struct.int16x4x3_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [3 x <4 x i16>] [[B]].coerce, [3 x <4 x i16>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <4 x i16>]* %coerce.dive to [3 x i64]*
+// CHECK-A32: store [3 x i64] %b.coerce, [3 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x3_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x4x3_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 24, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x4x3_t, %struct.int16x4x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8
+// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int16x4x3_t, %struct.int16x4x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8
+// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int16x4x3_t, %struct.int16x4x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX4]], align 8
+// CHECK: [[TMP8:%.*]] = bitcast <4 x i16> [[TMP7]] to <8 x i8>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16>
+// CHECK-DAG: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i16*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v4i16.p0i16(<4 x i16> [[TMP9]], <4 x i16> [[TMP10]], <4 x i16> [[TMP11]], i16* [[TMP12]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i16.v4i16(i16* [[TMP12]], <4 x i16> [[TMP9]], <4 x i16> [[TMP10]], <4 x i16> [[TMP11]])
+// CHECK: ret void
+void test_vst1_s16_x3(int16_t *a, int16x4x3_t b) {
+ vst1_s16_x3(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_s16_x4(
+// CHECK: [[B:%.*]] = alloca %struct.int16x4x4_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.int16x4x4_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x4x4_t, %struct.int16x4x4_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [4 x <4 x i16>] [[B]].coerce, [4 x <4 x i16>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <4 x i16>]* %coerce.dive to [4 x i64]*
+// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x4_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x4x4_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 32, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x4x4_t, %struct.int16x4x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8
+// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int16x4x4_t, %struct.int16x4x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8
+// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int16x4x4_t, %struct.int16x4x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX4]], align 8
+// CHECK: [[TMP8:%.*]] = bitcast <4 x i16> [[TMP7]] to <8 x i8>
+// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int16x4x4_t, %struct.int16x4x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3
+// CHECK: [[TMP9:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX6]], align 8
+// CHECK: [[TMP10:%.*]] = bitcast <4 x i16> [[TMP9]] to <8 x i8>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
+// CHECK-DAG: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16>
+// CHECK-DAG: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x i16>
+// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i16*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v4i16.p0i16(<4 x i16> [[TMP11]], <4 x i16> [[TMP12]], <4 x i16> [[TMP13]], <4 x i16> [[TMP14]], i16* [[TMP15]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i16.v4i16(i16* [[TMP15]], <4 x i16> [[TMP11]], <4 x i16> [[TMP12]], <4 x i16> [[TMP13]], <4 x i16> [[TMP14]])
+// CHECK: ret void
+void test_vst1_s16_x4(int16_t *a, int16x4x4_t b) {
+ vst1_s16_x4(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_s32_x2(
+// CHECK: [[B:%.*]] = alloca %struct.int32x2x2_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.int32x2x2_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x2x2_t, %struct.int32x2x2_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [2 x <2 x i32>] [[B]].coerce, [2 x <2 x i32>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <2 x i32>]* %coerce.dive to [2 x i64]*
+// CHECK-A32: store [2 x i64] %b.coerce, [2 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x2x2_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 16, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x2x2_t, %struct.int32x2x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x i32>], [2 x <2 x i32>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX]], align 8
+// CHECK: [[TMP4:%.*]] = bitcast <2 x i32> [[TMP3]] to <8 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int32x2x2_t, %struct.int32x2x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <2 x i32>], [2 x <2 x i32>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX2]], align 8
+// CHECK: [[TMP6:%.*]] = bitcast <2 x i32> [[TMP5]] to <8 x i8>
+// CHECK-DAG: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x i32>
+// CHECK-DAG: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x i32>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i32*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v2i32.p0i32(<2 x i32> [[TMP7]], <2 x i32> [[TMP8]], i32* [[TMP9]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i32.v2i32(i32* [[TMP9]], <2 x i32> [[TMP7]], <2 x i32> [[TMP8]])
+// CHECK: ret void
+void test_vst1_s32_x2(int32_t *a, int32x2x2_t b) {
+ vst1_s32_x2(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_s32_x3(
+// CHECK: [[B:%.*]] = alloca %struct.int32x2x3_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.int32x2x3_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x2x3_t, %struct.int32x2x3_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [3 x <2 x i32>] [[B]].coerce, [3 x <2 x i32>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <2 x i32>]* %coerce.dive to [3 x i64]*
+// CHECK-A32: store [3 x i64] %b.coerce, [3 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x3_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x2x3_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 24, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x2x3_t, %struct.int32x2x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x i32>], [3 x <2 x i32>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX]], align 8
+// CHECK: [[TMP4:%.*]] = bitcast <2 x i32> [[TMP3]] to <8 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int32x2x3_t, %struct.int32x2x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <2 x i32>], [3 x <2 x i32>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX2]], align 8
+// CHECK: [[TMP6:%.*]] = bitcast <2 x i32> [[TMP5]] to <8 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int32x2x3_t, %struct.int32x2x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <2 x i32>], [3 x <2 x i32>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX4]], align 8
+// CHECK: [[TMP8:%.*]] = bitcast <2 x i32> [[TMP7]] to <8 x i8>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x i32>
+// CHECK-DAG: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x i32>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <2 x i32>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i32*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v2i32.p0i32(<2 x i32> [[TMP9]], <2 x i32> [[TMP10]], <2 x i32> [[TMP11]], i32* [[TMP12]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i32.v2i32(i32* [[TMP12]], <2 x i32> [[TMP9]], <2 x i32> [[TMP10]], <2 x i32> [[TMP11]])
+// CHECK: ret void
+void test_vst1_s32_x3(int32_t *a, int32x2x3_t b) {
+ vst1_s32_x3(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_s32_x4(
+// CHECK: [[B:%.*]] = alloca %struct.int32x2x4_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.int32x2x4_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x2x4_t, %struct.int32x2x4_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [4 x <2 x i32>] [[B]].coerce, [4 x <2 x i32>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <2 x i32>]* %coerce.dive to [4 x i64]*
+// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x4_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x2x4_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 32, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x2x4_t, %struct.int32x2x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX]], align 8
+// CHECK: [[TMP4:%.*]] = bitcast <2 x i32> [[TMP3]] to <8 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int32x2x4_t, %struct.int32x2x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX2]], align 8
+// CHECK: [[TMP6:%.*]] = bitcast <2 x i32> [[TMP5]] to <8 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int32x2x4_t, %struct.int32x2x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX4]], align 8
+// CHECK: [[TMP8:%.*]] = bitcast <2 x i32> [[TMP7]] to <8 x i8>
+// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int32x2x4_t, %struct.int32x2x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3
+// CHECK: [[TMP9:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX6]], align 8
+// CHECK: [[TMP10:%.*]] = bitcast <2 x i32> [[TMP9]] to <8 x i8>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x i32>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x i32>
+// CHECK-DAG: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <2 x i32>
+// CHECK-DAG: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <2 x i32>
+// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i32*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v2i32.p0i32(<2 x i32> [[TMP11]], <2 x i32> [[TMP12]], <2 x i32> [[TMP13]], <2 x i32> [[TMP14]], i32* [[TMP15]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i32.v2i32(i32* [[TMP15]], <2 x i32> [[TMP11]], <2 x i32> [[TMP12]], <2 x i32> [[TMP13]], <2 x i32> [[TMP14]])
+// CHECK: ret void
+void test_vst1_s32_x4(int32_t *a, int32x2x4_t b) {
+ vst1_s32_x4(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_s64_x2(
+// CHECK: [[B:%.*]] = alloca %struct.int64x1x2_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.int64x1x2_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int64x1x2_t, %struct.int64x1x2_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [2 x <1 x i64>] [[B]].coerce, [2 x <1 x i64>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <1 x i64>]* %coerce.dive to [2 x i64]*
+// CHECK-A32: store [2 x i64] %b.coerce, [2 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x2_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x1x2_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 16, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x1x2_t, %struct.int64x1x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <1 x i64>], [2 x <1 x i64>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX]], align 8
+// CHECK: [[TMP4:%.*]] = bitcast <1 x i64> [[TMP3]] to <8 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int64x1x2_t, %struct.int64x1x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <1 x i64>], [2 x <1 x i64>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX2]], align 8
+// CHECK: [[TMP6:%.*]] = bitcast <1 x i64> [[TMP5]] to <8 x i8>
+// CHECK-DAG: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <1 x i64>
+// CHECK-DAG: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <1 x i64>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i64*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v1i64.p0i64(<1 x i64> [[TMP7]], <1 x i64> [[TMP8]], i64* [[TMP9]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i64.v1i64(i64* [[TMP9]], <1 x i64> [[TMP7]], <1 x i64> [[TMP8]])
+// CHECK: ret void
+void test_vst1_s64_x2(int64_t *a, int64x1x2_t b) {
+ vst1_s64_x2(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_s64_x3(
+// CHECK: [[B:%.*]] = alloca %struct.int64x1x3_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.int64x1x3_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int64x1x3_t, %struct.int64x1x3_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [3 x <1 x i64>] [[B]].coerce, [3 x <1 x i64>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <1 x i64>]* %coerce.dive to [3 x i64]*
+// CHECK-A32: store [3 x i64] %b.coerce, [3 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x3_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x1x3_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 24, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x1x3_t, %struct.int64x1x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX]], align 8
+// CHECK: [[TMP4:%.*]] = bitcast <1 x i64> [[TMP3]] to <8 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int64x1x3_t, %struct.int64x1x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX2]], align 8
+// CHECK: [[TMP6:%.*]] = bitcast <1 x i64> [[TMP5]] to <8 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int64x1x3_t, %struct.int64x1x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX4]], align 8
+// CHECK: [[TMP8:%.*]] = bitcast <1 x i64> [[TMP7]] to <8 x i8>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <1 x i64>
+// CHECK-DAG: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <1 x i64>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <1 x i64>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i64*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v1i64.p0i64(<1 x i64> [[TMP9]], <1 x i64> [[TMP10]], <1 x i64> [[TMP11]], i64* [[TMP12]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i64.v1i64(i64* [[TMP12]], <1 x i64> [[TMP9]], <1 x i64> [[TMP10]], <1 x i64> [[TMP11]])
+// CHECK: ret void
+void test_vst1_s64_x3(int64_t *a, int64x1x3_t b) {
+ vst1_s64_x3(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_s64_x4(
+// CHECK: [[B:%.*]] = alloca %struct.int64x1x4_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.int64x1x4_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int64x1x4_t, %struct.int64x1x4_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [4 x <1 x i64>] [[B]].coerce, [4 x <1 x i64>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <1 x i64>]* %coerce.dive to [4 x i64]*
+// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x4_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x1x4_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 32, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x1x4_t, %struct.int64x1x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX]], align 8
+// CHECK: [[TMP4:%.*]] = bitcast <1 x i64> [[TMP3]] to <8 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int64x1x4_t, %struct.int64x1x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX2]], align 8
+// CHECK: [[TMP6:%.*]] = bitcast <1 x i64> [[TMP5]] to <8 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int64x1x4_t, %struct.int64x1x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX4]], align 8
+// CHECK: [[TMP8:%.*]] = bitcast <1 x i64> [[TMP7]] to <8 x i8>
+// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int64x1x4_t, %struct.int64x1x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3
+// CHECK: [[TMP9:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX6]], align 8
+// CHECK: [[TMP10:%.*]] = bitcast <1 x i64> [[TMP9]] to <8 x i8>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <1 x i64>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <1 x i64>
+// CHECK-DAG: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <1 x i64>
+// CHECK-DAG: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <1 x i64>
+// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i64*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v1i64.p0i64(<1 x i64> [[TMP11]], <1 x i64> [[TMP12]], <1 x i64> [[TMP13]], <1 x i64> [[TMP14]], i64* [[TMP15]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i64.v1i64(i64* [[TMP15]], <1 x i64> [[TMP11]], <1 x i64> [[TMP12]], <1 x i64> [[TMP13]], <1 x i64> [[TMP14]])
+// CHECK: ret void
+void test_vst1_s64_x4(int64_t *a, int64x1x4_t b) {
+ vst1_s64_x4(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_s8_x2(
+// CHECK: [[B:%.*]] = alloca %struct.int8x8x2_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.int8x8x2_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x8x2_t, %struct.int8x8x2_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [2 x <8 x i8>] [[B]].coerce, [2 x <8 x i8>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <8 x i8>]* %coerce.dive to [2 x i64]*
+// CHECK-A32: store [2 x i64] %b.coerce, [2 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x8x2_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 16, i1 false)
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x8x2_t, %struct.int8x8x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int8x8x2_t, %struct.int8x8x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8
+// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], i8* %a)
+// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i8.v8i8(i8* %a, <8 x i8> [[TMP2]], <8 x i8> [[TMP3]])
+// CHECK: ret void
+void test_vst1_s8_x2(int8_t *a, int8x8x2_t b) {
+ vst1_s8_x2(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_s8_x3(
+// CHECK: [[B:%.*]] = alloca %struct.int8x8x3_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.int8x8x3_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x8x3_t, %struct.int8x8x3_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [3 x <8 x i8>] [[B]].coerce, [3 x <8 x i8>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <8 x i8>]* %coerce.dive to [3 x i64]*
+// CHECK-A32: store [3 x i64] %b.coerce, [3 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x3_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x8x3_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 24, i1 false)
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x8x3_t, %struct.int8x8x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int8x8x3_t, %struct.int8x8x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int8x8x3_t, %struct.int8x8x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP4:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX4]], align 8
+// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], i8* %a)
+// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i8.v8i8(i8* %a, <8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]])
+// CHECK: ret void
+void test_vst1_s8_x3(int8_t *a, int8x8x3_t b) {
+ vst1_s8_x3(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_s8_x4(
+// CHECK: [[B:%.*]] = alloca %struct.int8x8x4_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.int8x8x4_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x8x4_t, %struct.int8x8x4_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [4 x <8 x i8>] [[B]].coerce, [4 x <8 x i8>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <8 x i8>]* %coerce.dive to [4 x i64]*
+// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x4_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x8x4_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 32, i1 false)
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x8x4_t, %struct.int8x8x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int8x8x4_t, %struct.int8x8x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int8x8x4_t, %struct.int8x8x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP4:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX4]], align 8
+// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int8x8x4_t, %struct.int8x8x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3
+// CHECK: [[TMP5:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX6]], align 8
+// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], <8 x i8> [[TMP5]], i8* %a)
+// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i8.v8i8(i8* %a, <8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], <8 x i8> [[TMP5]])
+// CHECK: ret void
+void test_vst1_s8_x4(int8_t *a, int8x8x4_t b) {
+ vst1_s8_x4(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_u16_x2(
+// CHECK: [[B:%.*]] = alloca %struct.uint16x4x2_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.uint16x4x2_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [2 x <4 x i16>] [[B]].coerce, [2 x <4 x i16>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <4 x i16>]* %coerce.dive to [2 x i64]*
+// CHECK-A32: store [2 x i64] %b.coerce, [2 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x4x2_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 16, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8
+// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8
+// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8>
+// CHECK-DAG: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16>
+// CHECK-DAG: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i16*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v4i16.p0i16(<4 x i16> [[TMP7]], <4 x i16> [[TMP8]], i16* [[TMP9]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i16.v4i16(i16* [[TMP9]], <4 x i16> [[TMP7]], <4 x i16> [[TMP8]])
+// CHECK: ret void
+void test_vst1_u16_x2(uint16_t *a, uint16x4x2_t b) {
+ vst1_u16_x2(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_u16_x3(
+// CHECK: [[B:%.*]] = alloca %struct.uint16x4x3_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.uint16x4x3_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x4x3_t, %struct.uint16x4x3_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [3 x <4 x i16>] [[B]].coerce, [3 x <4 x i16>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <4 x i16>]* %coerce.dive to [3 x i64]*
+// CHECK-A32: store [3 x i64] %b.coerce, [3 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x3_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x4x3_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 24, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x4x3_t, %struct.uint16x4x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8
+// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint16x4x3_t, %struct.uint16x4x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8
+// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint16x4x3_t, %struct.uint16x4x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX4]], align 8
+// CHECK: [[TMP8:%.*]] = bitcast <4 x i16> [[TMP7]] to <8 x i8>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16>
+// CHECK-DAG: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i16*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v4i16.p0i16(<4 x i16> [[TMP9]], <4 x i16> [[TMP10]], <4 x i16> [[TMP11]], i16* [[TMP12]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i16.v4i16(i16* [[TMP12]], <4 x i16> [[TMP9]], <4 x i16> [[TMP10]], <4 x i16> [[TMP11]])
+// CHECK: ret void
+void test_vst1_u16_x3(uint16_t *a, uint16x4x3_t b) {
+ vst1_u16_x3(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_u16_x4(
+// CHECK: [[B:%.*]] = alloca %struct.uint16x4x4_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.uint16x4x4_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x4x4_t, %struct.uint16x4x4_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [4 x <4 x i16>] [[B]].coerce, [4 x <4 x i16>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <4 x i16>]* %coerce.dive to [4 x i64]*
+// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x4_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x4x4_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 32, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x4x4_t, %struct.uint16x4x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8
+// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint16x4x4_t, %struct.uint16x4x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8
+// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint16x4x4_t, %struct.uint16x4x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX4]], align 8
+// CHECK: [[TMP8:%.*]] = bitcast <4 x i16> [[TMP7]] to <8 x i8>
+// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint16x4x4_t, %struct.uint16x4x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3
+// CHECK: [[TMP9:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX6]], align 8
+// CHECK: [[TMP10:%.*]] = bitcast <4 x i16> [[TMP9]] to <8 x i8>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
+// CHECK-DAG: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16>
+// CHECK-DAG: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x i16>
+// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i16*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v4i16.p0i16(<4 x i16> [[TMP11]], <4 x i16> [[TMP12]], <4 x i16> [[TMP13]], <4 x i16> [[TMP14]], i16* [[TMP15]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i16.v4i16(i16* [[TMP15]], <4 x i16> [[TMP11]], <4 x i16> [[TMP12]], <4 x i16> [[TMP13]], <4 x i16> [[TMP14]])
+// CHECK: ret void
+void test_vst1_u16_x4(uint16_t *a, uint16x4x4_t b) {
+ vst1_u16_x4(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_u32_x2(
+// CHECK: [[B:%.*]] = alloca %struct.uint32x2x2_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.uint32x2x2_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [2 x <2 x i32>] [[B]].coerce, [2 x <2 x i32>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <2 x i32>]* %coerce.dive to [2 x i64]*
+// CHECK-A32: store [2 x i64] %b.coerce, [2 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x2x2_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 16, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x i32>], [2 x <2 x i32>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX]], align 8
+// CHECK: [[TMP4:%.*]] = bitcast <2 x i32> [[TMP3]] to <8 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <2 x i32>], [2 x <2 x i32>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX2]], align 8
+// CHECK: [[TMP6:%.*]] = bitcast <2 x i32> [[TMP5]] to <8 x i8>
+// CHECK-DAG: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x i32>
+// CHECK-DAG: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x i32>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i32*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v2i32.p0i32(<2 x i32> [[TMP7]], <2 x i32> [[TMP8]], i32* [[TMP9]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i32.v2i32(i32* [[TMP9]], <2 x i32> [[TMP7]], <2 x i32> [[TMP8]])
+// CHECK: ret void
+void test_vst1_u32_x2(uint32_t *a, uint32x2x2_t b) {
+ vst1_u32_x2(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_u32_x3(
+// CHECK: [[B:%.*]] = alloca %struct.uint32x2x3_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.uint32x2x3_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x2x3_t, %struct.uint32x2x3_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [3 x <2 x i32>] [[B]].coerce, [3 x <2 x i32>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <2 x i32>]* %coerce.dive to [3 x i64]*
+// CHECK-A32: store [3 x i64] %b.coerce, [3 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x3_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x2x3_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 24, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x2x3_t, %struct.uint32x2x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x i32>], [3 x <2 x i32>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX]], align 8
+// CHECK: [[TMP4:%.*]] = bitcast <2 x i32> [[TMP3]] to <8 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint32x2x3_t, %struct.uint32x2x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <2 x i32>], [3 x <2 x i32>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX2]], align 8
+// CHECK: [[TMP6:%.*]] = bitcast <2 x i32> [[TMP5]] to <8 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint32x2x3_t, %struct.uint32x2x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <2 x i32>], [3 x <2 x i32>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX4]], align 8
+// CHECK: [[TMP8:%.*]] = bitcast <2 x i32> [[TMP7]] to <8 x i8>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x i32>
+// CHECK-DAG: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x i32>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <2 x i32>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i32*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v2i32.p0i32(<2 x i32> [[TMP9]], <2 x i32> [[TMP10]], <2 x i32> [[TMP11]], i32* [[TMP12]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i32.v2i32(i32* [[TMP12]], <2 x i32> [[TMP9]], <2 x i32> [[TMP10]], <2 x i32> [[TMP11]])
+// CHECK: ret void
+void test_vst1_u32_x3(uint32_t *a, uint32x2x3_t b) {
+ vst1_u32_x3(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_u32_x4(
+// CHECK: [[B:%.*]] = alloca %struct.uint32x2x4_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.uint32x2x4_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x2x4_t, %struct.uint32x2x4_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [4 x <2 x i32>] [[B]].coerce, [4 x <2 x i32>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <2 x i32>]* %coerce.dive to [4 x i64]*
+// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x4_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x2x4_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 32, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x2x4_t, %struct.uint32x2x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX]], align 8
+// CHECK: [[TMP4:%.*]] = bitcast <2 x i32> [[TMP3]] to <8 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint32x2x4_t, %struct.uint32x2x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX2]], align 8
+// CHECK: [[TMP6:%.*]] = bitcast <2 x i32> [[TMP5]] to <8 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint32x2x4_t, %struct.uint32x2x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX4]], align 8
+// CHECK: [[TMP8:%.*]] = bitcast <2 x i32> [[TMP7]] to <8 x i8>
+// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint32x2x4_t, %struct.uint32x2x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3
+// CHECK: [[TMP9:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX6]], align 8
+// CHECK: [[TMP10:%.*]] = bitcast <2 x i32> [[TMP9]] to <8 x i8>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x i32>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x i32>
+// CHECK-DAG: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <2 x i32>
+// CHECK-DAG: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <2 x i32>
+// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i32*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v2i32.p0i32(<2 x i32> [[TMP11]], <2 x i32> [[TMP12]], <2 x i32> [[TMP13]], <2 x i32> [[TMP14]], i32* [[TMP15]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i32.v2i32(i32* [[TMP15]], <2 x i32> [[TMP11]], <2 x i32> [[TMP12]], <2 x i32> [[TMP13]], <2 x i32> [[TMP14]])
+// CHECK: ret void
+void test_vst1_u32_x4(uint32_t *a, uint32x2x4_t b) {
+ vst1_u32_x4(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_u64_x2(
+// CHECK: [[B:%.*]] = alloca %struct.uint64x1x2_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.uint64x1x2_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint64x1x2_t, %struct.uint64x1x2_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [2 x <1 x i64>] [[B]].coerce, [2 x <1 x i64>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <1 x i64>]* %coerce.dive to [2 x i64]*
+// CHECK-A32: store [2 x i64] %b.coerce, [2 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x2_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x1x2_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 16, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x1x2_t, %struct.uint64x1x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <1 x i64>], [2 x <1 x i64>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX]], align 8
+// CHECK: [[TMP4:%.*]] = bitcast <1 x i64> [[TMP3]] to <8 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint64x1x2_t, %struct.uint64x1x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <1 x i64>], [2 x <1 x i64>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX2]], align 8
+// CHECK: [[TMP6:%.*]] = bitcast <1 x i64> [[TMP5]] to <8 x i8>
+// CHECK-DAG: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <1 x i64>
+// CHECK-DAG: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <1 x i64>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i64*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v1i64.p0i64(<1 x i64> [[TMP7]], <1 x i64> [[TMP8]], i64* [[TMP9]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i64.v1i64(i64* [[TMP9]], <1 x i64> [[TMP7]], <1 x i64> [[TMP8]])
+// CHECK: ret void
+void test_vst1_u64_x2(uint64_t *a, uint64x1x2_t b) {
+ vst1_u64_x2(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_u64_x3(
+// CHECK: [[B:%.*]] = alloca %struct.uint64x1x3_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.uint64x1x3_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint64x1x3_t, %struct.uint64x1x3_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [3 x <1 x i64>] [[B]].coerce, [3 x <1 x i64>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <1 x i64>]* %coerce.dive to [3 x i64]*
+// CHECK-A32: store [3 x i64] %b.coerce, [3 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x3_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x1x3_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 24, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x1x3_t, %struct.uint64x1x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX]], align 8
+// CHECK: [[TMP4:%.*]] = bitcast <1 x i64> [[TMP3]] to <8 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint64x1x3_t, %struct.uint64x1x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX2]], align 8
+// CHECK: [[TMP6:%.*]] = bitcast <1 x i64> [[TMP5]] to <8 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint64x1x3_t, %struct.uint64x1x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX4]], align 8
+// CHECK: [[TMP8:%.*]] = bitcast <1 x i64> [[TMP7]] to <8 x i8>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <1 x i64>
+// CHECK-DAG: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <1 x i64>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <1 x i64>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i64*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v1i64.p0i64(<1 x i64> [[TMP9]], <1 x i64> [[TMP10]], <1 x i64> [[TMP11]], i64* [[TMP12]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i64.v1i64(i64* [[TMP12]], <1 x i64> [[TMP9]], <1 x i64> [[TMP10]], <1 x i64> [[TMP11]])
+// CHECK: ret void
+void test_vst1_u64_x3(uint64_t *a, uint64x1x3_t b) {
+ vst1_u64_x3(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_u64_x4(
+// CHECK: [[B:%.*]] = alloca %struct.uint64x1x4_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.uint64x1x4_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint64x1x4_t, %struct.uint64x1x4_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [4 x <1 x i64>] [[B]].coerce, [4 x <1 x i64>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <1 x i64>]* %coerce.dive to [4 x i64]*
+// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x4_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x1x4_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 32, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x1x4_t, %struct.uint64x1x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX]], align 8
+// CHECK: [[TMP4:%.*]] = bitcast <1 x i64> [[TMP3]] to <8 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint64x1x4_t, %struct.uint64x1x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX2]], align 8
+// CHECK: [[TMP6:%.*]] = bitcast <1 x i64> [[TMP5]] to <8 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint64x1x4_t, %struct.uint64x1x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX4]], align 8
+// CHECK: [[TMP8:%.*]] = bitcast <1 x i64> [[TMP7]] to <8 x i8>
+// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint64x1x4_t, %struct.uint64x1x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3
+// CHECK: [[TMP9:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX6]], align 8
+// CHECK: [[TMP10:%.*]] = bitcast <1 x i64> [[TMP9]] to <8 x i8>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <1 x i64>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <1 x i64>
+// CHECK-DAG: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <1 x i64>
+// CHECK-DAG: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <1 x i64>
+// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i64*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v1i64.p0i64(<1 x i64> [[TMP11]], <1 x i64> [[TMP12]], <1 x i64> [[TMP13]], <1 x i64> [[TMP14]], i64* [[TMP15]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i64.v1i64(i64* [[TMP15]], <1 x i64> [[TMP11]], <1 x i64> [[TMP12]], <1 x i64> [[TMP13]], <1 x i64> [[TMP14]])
+// CHECK: ret void
+void test_vst1_u64_x4(uint64_t *a, uint64x1x4_t b) {
+ vst1_u64_x4(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_u8_x2(
+// CHECK: [[B:%.*]] = alloca %struct.uint8x8x2_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.uint8x8x2_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [2 x <8 x i8>] [[B]].coerce, [2 x <8 x i8>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <8 x i8>]* %coerce.dive to [2 x i64]*
+// CHECK-A32: store [2 x i64] %b.coerce, [2 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x8x2_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 16, i1 false)
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8
+// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], i8* %a)
+// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i8.v8i8(i8* %a, <8 x i8> [[TMP2]], <8 x i8> [[TMP3]])
+// CHECK: ret void
+void test_vst1_u8_x2(uint8_t *a, uint8x8x2_t b) {
+ vst1_u8_x2(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_u8_x3(
+// CHECK: [[B:%.*]] = alloca %struct.uint8x8x3_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.uint8x8x3_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x8x3_t, %struct.uint8x8x3_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [3 x <8 x i8>] [[B]].coerce, [3 x <8 x i8>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <8 x i8>]* %coerce.dive to [3 x i64]*
+// CHECK-A32: store [3 x i64] %b.coerce, [3 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x3_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x8x3_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 24, i1 false)
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x8x3_t, %struct.uint8x8x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint8x8x3_t, %struct.uint8x8x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint8x8x3_t, %struct.uint8x8x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP4:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX4]], align 8
+// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], i8* %a)
+// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i8.v8i8(i8* %a, <8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]])
+// CHECK: ret void
+void test_vst1_u8_x3(uint8_t *a, uint8x8x3_t b) {
+ vst1_u8_x3(a, b);
+}
+
+// CHECK-LABEL: @test_vst1_u8_x4(
+// CHECK: [[B:%.*]] = alloca %struct.uint8x8x4_t, align 8
+// CHECK: [[__S1:%.*]] = alloca %struct.uint8x8x4_t, align 8
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [4 x <8 x i8>] [[B]].coerce, [4 x <8 x i8>]* [[COERCE_DIVE]], align 8
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <8 x i8>]* %coerce.dive to [4 x i64]*
+// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x4_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x8x4_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 32, i1 false)
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP4:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX4]], align 8
+// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3
+// CHECK: [[TMP5:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX6]], align 8
+// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], <8 x i8> [[TMP5]], i8* %a)
+// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i8.v8i8(i8* %a, <8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], <8 x i8> [[TMP5]])
+// CHECK: ret void
+void test_vst1_u8_x4(uint8_t *a, uint8x8x4_t b) {
+ vst1_u8_x4(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_f16_x2(
+// CHECK: [[B:%.*]] = alloca %struct.float16x8x2_t, align [[QALIGN:(16|8)]]
+// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x2_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x8x2_t, %struct.float16x8x2_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [2 x <8 x half>] [[B]].coerce, [2 x <8 x half>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <8 x half>]* %coerce.dive to [4 x i64]*
+// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x2_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x2_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 32, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x2_t, %struct.float16x8x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x half>], [2 x <8 x half>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[TMP4:%.*]] = bitcast <8 x half> [[TMP3]] to <16 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float16x8x2_t, %struct.float16x8x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x half>], [2 x <8 x half>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK: [[TMP6:%.*]] = bitcast <8 x half> [[TMP5]] to <16 x i8>
+// CHECK-DAG: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x [[HALF]]>
+// CHECK-DAG: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x [[HALF]]>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to [[HALF]]*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v8f16.p0f16(<8 x half> [[TMP7]], <8 x half> [[TMP8]], half* [[TMP9]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i16.v8i16(i16* [[TMP9]], <8 x i16> [[TMP7]], <8 x i16> [[TMP8]])
+// CHECK: ret void
+void test_vst1q_f16_x2(float16_t *a, float16x8x2_t b) {
+ vst1q_f16_x2(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_f16_x3(
+// CHECK: [[B:%.*]] = alloca %struct.float16x8x3_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x3_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [3 x <8 x half>] [[B]].coerce, [3 x <8 x half>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <8 x half>]* %coerce.dive to [6 x i64]*
+// CHECK-A32: store [6 x i64] %b.coerce, [6 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x3_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x3_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 48, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x half>], [3 x <8 x half>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[TMP4:%.*]] = bitcast <8 x half> [[TMP3]] to <16 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x half>], [3 x <8 x half>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK: [[TMP6:%.*]] = bitcast <8 x half> [[TMP5]] to <16 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x half>], [3 x <8 x half>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX4]], align [[QALIGN]]
+// CHECK: [[TMP8:%.*]] = bitcast <8 x half> [[TMP7]] to <16 x i8>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x [[HALF]]>
+// CHECK-DAG: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x [[HALF]]>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x [[HALF]]>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to [[HALF]]*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v8f16.p0f16(<8 x half> [[TMP9]], <8 x half> [[TMP10]], <8 x half> [[TMP11]], half* [[TMP12]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i16.v8i16(i16* [[TMP12]], <8 x i16> [[TMP9]], <8 x i16> [[TMP10]], <8 x i16> [[TMP11]])
+// CHECK: ret void
+void test_vst1q_f16_x3(float16_t *a, float16x8x3_t b) {
+ vst1q_f16_x3(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_f16_x4(
+// CHECK: [[B:%.*]] = alloca %struct.float16x8x4_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x4_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [4 x <8 x half>] [[B]].coerce, [4 x <8 x half>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <8 x half>]* %coerce.dive to [8 x i64]*
+// CHECK-A32: store [8 x i64] %b.coerce, [8 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x4_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x4_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 64, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[TMP4:%.*]] = bitcast <8 x half> [[TMP3]] to <16 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK: [[TMP6:%.*]] = bitcast <8 x half> [[TMP5]] to <16 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX4]], align [[QALIGN]]
+// CHECK: [[TMP8:%.*]] = bitcast <8 x half> [[TMP7]] to <16 x i8>
+// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3
+// CHECK: [[TMP9:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX6]], align [[QALIGN]]
+// CHECK: [[TMP10:%.*]] = bitcast <8 x half> [[TMP9]] to <16 x i8>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x [[HALF]]>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x [[HALF]]>
+// CHECK-DAG: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x [[HALF]]>
+// CHECK-DAG: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x [[HALF]]>
+// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to [[HALF]]*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v8f16.p0f16(<8 x half> [[TMP11]], <8 x half> [[TMP12]], <8 x half> [[TMP13]], <8 x half> [[TMP14]], half* [[TMP15]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i16.v8i16(i16* [[TMP15]], <8 x i16> [[TMP11]], <8 x i16> [[TMP12]], <8 x i16> [[TMP13]], <8 x i16> [[TMP14]])
+// CHECK: ret void
+void test_vst1q_f16_x4(float16_t *a, float16x8x4_t b) {
+ vst1q_f16_x4(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_f32_x2(
+// CHECK: [[B:%.*]] = alloca %struct.float32x4x2_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x2_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [2 x <4 x float>] [[B]].coerce, [2 x <4 x float>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <4 x float>]* %coerce.dive to [4 x i64]*
+// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x2_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 32, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x float>], [2 x <4 x float>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[TMP4:%.*]] = bitcast <4 x float> [[TMP3]] to <16 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x float>], [2 x <4 x float>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK: [[TMP6:%.*]] = bitcast <4 x float> [[TMP5]] to <16 x i8>
+// CHECK-DAG: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x float>
+// CHECK-DAG: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x float>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to float*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v4f32.p0f32(<4 x float> [[TMP7]], <4 x float> [[TMP8]], float* [[TMP9]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0f32.v4f32(float* [[TMP9]], <4 x float> [[TMP7]], <4 x float> [[TMP8]])
+// CHECK: ret void
+void test_vst1q_f32_x2(float32_t *a, float32x4x2_t b) {
+ vst1q_f32_x2(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_f32_x3(
+// CHECK: [[B:%.*]] = alloca %struct.float32x4x3_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x3_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [3 x <4 x float>] [[B]].coerce, [3 x <4 x float>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <4 x float>]* %coerce.dive to [6 x i64]*
+// CHECK-A32: store [6 x i64] %b.coerce, [6 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x3_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x3_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 48, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x float>], [3 x <4 x float>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[TMP4:%.*]] = bitcast <4 x float> [[TMP3]] to <16 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x float>], [3 x <4 x float>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK: [[TMP6:%.*]] = bitcast <4 x float> [[TMP5]] to <16 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x float>], [3 x <4 x float>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX4]], align [[QALIGN]]
+// CHECK: [[TMP8:%.*]] = bitcast <4 x float> [[TMP7]] to <16 x i8>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x float>
+// CHECK-DAG: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x float>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x float>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to float*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v4f32.p0f32(<4 x float> [[TMP9]], <4 x float> [[TMP10]], <4 x float> [[TMP11]], float* [[TMP12]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0f32.v4f32(float* [[TMP12]], <4 x float> [[TMP9]], <4 x float> [[TMP10]], <4 x float> [[TMP11]])
+// CHECK: ret void
+void test_vst1q_f32_x3(float32_t *a, float32x4x3_t b) {
+ vst1q_f32_x3(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_f32_x4(
+// CHECK: [[B:%.*]] = alloca %struct.float32x4x4_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x4_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [4 x <4 x float>] [[B]].coerce, [4 x <4 x float>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <4 x float>]* %coerce.dive to [8 x i64]*
+// CHECK-A32: store [8 x i64] %b.coerce, [8 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x4_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x4_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 64, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x float>], [4 x <4 x float>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[TMP4:%.*]] = bitcast <4 x float> [[TMP3]] to <16 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x float>], [4 x <4 x float>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK: [[TMP6:%.*]] = bitcast <4 x float> [[TMP5]] to <16 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x float>], [4 x <4 x float>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX4]], align [[QALIGN]]
+// CHECK: [[TMP8:%.*]] = bitcast <4 x float> [[TMP7]] to <16 x i8>
+// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x float>], [4 x <4 x float>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3
+// CHECK: [[TMP9:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX6]], align [[QALIGN]]
+// CHECK: [[TMP10:%.*]] = bitcast <4 x float> [[TMP9]] to <16 x i8>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x float>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x float>
+// CHECK-DAG: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x float>
+// CHECK-DAG: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <4 x float>
+// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to float*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v4f32.p0f32(<4 x float> [[TMP11]], <4 x float> [[TMP12]], <4 x float> [[TMP13]], <4 x float> [[TMP14]], float* [[TMP15]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0f32.v4f32(float* [[TMP15]], <4 x float> [[TMP11]], <4 x float> [[TMP12]], <4 x float> [[TMP13]], <4 x float> [[TMP14]])
+// CHECK: ret void
+void test_vst1q_f32_x4(float32_t *a, float32x4x4_t b) {
+ vst1q_f32_x4(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_p16_x2(
+// CHECK: [[B:%.*]] = alloca %struct.poly16x8x2_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x2_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [2 x <8 x i16>] [[B]].coerce, [2 x <8 x i16>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <8 x i16>]* %coerce.dive to [4 x i64]*
+// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x2_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 32, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8>
+// CHECK-DAG: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16>
+// CHECK-DAG: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i16*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v8i16.p0i16(<8 x i16> [[TMP7]], <8 x i16> [[TMP8]], i16* [[TMP9]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i16.v8i16(i16* [[TMP9]], <8 x i16> [[TMP7]], <8 x i16> [[TMP8]])
+// CHECK: ret void
+void test_vst1q_p16_x2(poly16_t *a, poly16x8x2_t b) {
+ vst1q_p16_x2(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_p16_x3(
+// CHECK: [[B:%.*]] = alloca %struct.poly16x8x3_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x3_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [3 x <8 x i16>] [[B]].coerce, [3 x <8 x i16>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <8 x i16>]* %coerce.dive to [6 x i64]*
+// CHECK-A32: store [6 x i64] %b.coerce, [6 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x3_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x3_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 48, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align [[QALIGN]]
+// CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16>
+// CHECK-DAG: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i16*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v8i16.p0i16(<8 x i16> [[TMP9]], <8 x i16> [[TMP10]], <8 x i16> [[TMP11]], i16* [[TMP12]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i16.v8i16(i16* [[TMP12]], <8 x i16> [[TMP9]], <8 x i16> [[TMP10]], <8 x i16> [[TMP11]])
+// CHECK: ret void
+void test_vst1q_p16_x3(poly16_t *a, poly16x8x3_t b) {
+ vst1q_p16_x3(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_p16_x4(
+// CHECK: [[B:%.*]] = alloca %struct.poly16x8x4_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x4_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [4 x <8 x i16>] [[B]].coerce, [4 x <8 x i16>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <8 x i16>]* %coerce.dive to [8 x i64]*
+// CHECK-A32: store [8 x i64] %b.coerce, [8 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x4_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x4_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 64, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align [[QALIGN]]
+// CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8>
+// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3
+// CHECK: [[TMP9:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX6]], align [[QALIGN]]
+// CHECK: [[TMP10:%.*]] = bitcast <8 x i16> [[TMP9]] to <16 x i8>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
+// CHECK-DAG: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16>
+// CHECK-DAG: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x i16>
+// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i16*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v8i16.p0i16(<8 x i16> [[TMP11]], <8 x i16> [[TMP12]], <8 x i16> [[TMP13]], <8 x i16> [[TMP14]], i16* [[TMP15]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i16.v8i16(i16* [[TMP15]], <8 x i16> [[TMP11]], <8 x i16> [[TMP12]], <8 x i16> [[TMP13]], <8 x i16> [[TMP14]])
+// CHECK: ret void
+void test_vst1q_p16_x4(poly16_t *a, poly16x8x4_t b) {
+ vst1q_p16_x4(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_p8_x2(
+// CHECK: [[B:%.*]] = alloca %struct.poly8x16x2_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.poly8x16x2_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [2 x <16 x i8>] [[B]].coerce, [2 x <16 x i8>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <16 x i8>]* %coerce.dive to [4 x i64]*
+// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x16x2_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 32, i1 false)
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], i8* %a)
+// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i8.v16i8(i8* %a, <16 x i8> [[TMP2]], <16 x i8> [[TMP3]])
+// CHECK: ret void
+void test_vst1q_p8_x2(poly8_t *a, poly8x16x2_t b) {
+ vst1q_p8_x2(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_p8_x3(
+// CHECK: [[B:%.*]] = alloca %struct.poly8x16x3_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.poly8x16x3_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [3 x <16 x i8>] [[B]].coerce, [3 x <16 x i8>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <16 x i8>]* %coerce.dive to [6 x i64]*
+// CHECK-A32: store [6 x i64] %b.coerce, [6 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x3_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x16x3_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 48, i1 false)
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align [[QALIGN]]
+// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], i8* %a)
+// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i8.v16i8(i8* %a, <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]])
+// CHECK: ret void
+void test_vst1q_p8_x3(poly8_t *a, poly8x16x3_t b) {
+ vst1q_p8_x3(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_p8_x4(
+// CHECK: [[B:%.*]] = alloca %struct.poly8x16x4_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.poly8x16x4_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [4 x <16 x i8>] [[B]].coerce, [4 x <16 x i8>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <16 x i8>]* %coerce.dive to [8 x i64]*
+// CHECK-A32: store [8 x i64] %b.coerce, [8 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x4_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x16x4_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 64, i1 false)
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align [[QALIGN]]
+// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3
+// CHECK: [[TMP5:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX6]], align [[QALIGN]]
+// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> [[TMP5]], i8* %a)
+// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i8.v16i8(i8* %a, <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> [[TMP5]])
+// CHECK: ret void
+void test_vst1q_p8_x4(poly8_t *a, poly8x16x4_t b) {
+ vst1q_p8_x4(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_s16_x2(
+// CHECK: [[B:%.*]] = alloca %struct.int16x8x2_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x2_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [2 x <8 x i16>] [[B]].coerce, [2 x <8 x i16>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <8 x i16>]* %coerce.dive to [4 x i64]*
+// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x2_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 32, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8>
+// CHECK-DAG: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16>
+// CHECK-DAG: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i16*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v8i16.p0i16(<8 x i16> [[TMP7]], <8 x i16> [[TMP8]], i16* [[TMP9]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i16.v8i16(i16* [[TMP9]], <8 x i16> [[TMP7]], <8 x i16> [[TMP8]])
+// CHECK: ret void
+void test_vst1q_s16_x2(int16_t *a, int16x8x2_t b) {
+ vst1q_s16_x2(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_s16_x3(
+// CHECK: [[B:%.*]] = alloca %struct.int16x8x3_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x3_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [3 x <8 x i16>] [[B]].coerce, [3 x <8 x i16>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <8 x i16>]* %coerce.dive to [6 x i64]*
+// CHECK-A32: store [6 x i64] %b.coerce, [6 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x3_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x3_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 48, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align [[QALIGN]]
+// CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16>
+// CHECK-DAG: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i16*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v8i16.p0i16(<8 x i16> [[TMP9]], <8 x i16> [[TMP10]], <8 x i16> [[TMP11]], i16* [[TMP12]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i16.v8i16(i16* [[TMP12]], <8 x i16> [[TMP9]], <8 x i16> [[TMP10]], <8 x i16> [[TMP11]])
+// CHECK: ret void
+void test_vst1q_s16_x3(int16_t *a, int16x8x3_t b) {
+ vst1q_s16_x3(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_s16_x4(
+// CHECK: [[B:%.*]] = alloca %struct.int16x8x4_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x4_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [4 x <8 x i16>] [[B]].coerce, [4 x <8 x i16>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <8 x i16>]* %coerce.dive to [8 x i64]*
+// CHECK-A32: store [8 x i64] %b.coerce, [8 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x4_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x4_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 64, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align [[QALIGN]]
+// CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8>
+// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3
+// CHECK: [[TMP9:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX6]], align [[QALIGN]]
+// CHECK: [[TMP10:%.*]] = bitcast <8 x i16> [[TMP9]] to <16 x i8>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
+// CHECK-DAG: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16>
+// CHECK-DAG: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x i16>
+// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i16*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v8i16.p0i16(<8 x i16> [[TMP11]], <8 x i16> [[TMP12]], <8 x i16> [[TMP13]], <8 x i16> [[TMP14]], i16* [[TMP15]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i16.v8i16(i16* [[TMP15]], <8 x i16> [[TMP11]], <8 x i16> [[TMP12]], <8 x i16> [[TMP13]], <8 x i16> [[TMP14]])
+// CHECK: ret void
+void test_vst1q_s16_x4(int16_t *a, int16x8x4_t b) {
+ vst1q_s16_x4(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_s32_x2(
+// CHECK: [[B:%.*]] = alloca %struct.int32x4x2_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x2_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [2 x <4 x i32>] [[B]].coerce, [2 x <4 x i32>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <4 x i32>]* %coerce.dive to [4 x i64]*
+// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x2_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 32, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP3]] to <16 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK: [[TMP6:%.*]] = bitcast <4 x i32> [[TMP5]] to <16 x i8>
+// CHECK-DAG: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x i32>
+// CHECK-DAG: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i32*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v4i32.p0i32(<4 x i32> [[TMP7]], <4 x i32> [[TMP8]], i32* [[TMP9]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i32.v4i32(i32* [[TMP9]], <4 x i32> [[TMP7]], <4 x i32> [[TMP8]])
+// CHECK: ret void
+void test_vst1q_s32_x2(int32_t *a, int32x4x2_t b) {
+ vst1q_s32_x2(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_s32_x3(
+// CHECK: [[B:%.*]] = alloca %struct.int32x4x3_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x3_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [3 x <4 x i32>] [[B]].coerce, [3 x <4 x i32>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <4 x i32>]* %coerce.dive to [6 x i64]*
+// CHECK-A32: store [6 x i64] %b.coerce, [6 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x3_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x3_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 48, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP3]] to <16 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK: [[TMP6:%.*]] = bitcast <4 x i32> [[TMP5]] to <16 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align [[QALIGN]]
+// CHECK: [[TMP8:%.*]] = bitcast <4 x i32> [[TMP7]] to <16 x i8>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x i32>
+// CHECK-DAG: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x i32>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i32*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v4i32.p0i32(<4 x i32> [[TMP9]], <4 x i32> [[TMP10]], <4 x i32> [[TMP11]], i32* [[TMP12]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i32.v4i32(i32* [[TMP12]], <4 x i32> [[TMP9]], <4 x i32> [[TMP10]], <4 x i32> [[TMP11]])
+// CHECK: ret void
+void test_vst1q_s32_x3(int32_t *a, int32x4x3_t b) {
+ vst1q_s32_x3(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_s32_x4(
+// CHECK: [[B:%.*]] = alloca %struct.int32x4x4_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x4_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [4 x <4 x i32>] [[B]].coerce, [4 x <4 x i32>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <4 x i32>]* %coerce.dive to [8 x i64]*
+// CHECK-A32: store [8 x i64] %b.coerce, [8 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x4_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x4_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 64, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP3]] to <16 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK: [[TMP6:%.*]] = bitcast <4 x i32> [[TMP5]] to <16 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align [[QALIGN]]
+// CHECK: [[TMP8:%.*]] = bitcast <4 x i32> [[TMP7]] to <16 x i8>
+// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3
+// CHECK: [[TMP9:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX6]], align [[QALIGN]]
+// CHECK: [[TMP10:%.*]] = bitcast <4 x i32> [[TMP9]] to <16 x i8>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x i32>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32>
+// CHECK-DAG: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x i32>
+// CHECK-DAG: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <4 x i32>
+// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i32*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v4i32.p0i32(<4 x i32> [[TMP11]], <4 x i32> [[TMP12]], <4 x i32> [[TMP13]], <4 x i32> [[TMP14]], i32* [[TMP15]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i32.v4i32(i32* [[TMP15]], <4 x i32> [[TMP11]], <4 x i32> [[TMP12]], <4 x i32> [[TMP13]], <4 x i32> [[TMP14]])
+// CHECK: ret void
+void test_vst1q_s32_x4(int32_t *a, int32x4x4_t b) {
+ vst1q_s32_x4(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_s64_x2(
+// CHECK: [[B:%.*]] = alloca %struct.int64x2x2_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.int64x2x2_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int64x2x2_t, %struct.int64x2x2_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [2 x <2 x i64>] [[B]].coerce, [2 x <2 x i64>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <2 x i64>]* %coerce.dive to [4 x i64]*
+// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x2x2_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x2x2_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 32, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x2x2_t, %struct.int64x2x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x i64>], [2 x <2 x i64>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[TMP4:%.*]] = bitcast <2 x i64> [[TMP3]] to <16 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int64x2x2_t, %struct.int64x2x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <2 x i64>], [2 x <2 x i64>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK: [[TMP6:%.*]] = bitcast <2 x i64> [[TMP5]] to <16 x i8>
+// CHECK-DAG: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <2 x i64>
+// CHECK-DAG: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <2 x i64>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i64*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v2i64.p0i64(<2 x i64> [[TMP7]], <2 x i64> [[TMP8]], i64* [[TMP9]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i64.v2i64(i64* [[TMP9]], <2 x i64> [[TMP7]], <2 x i64> [[TMP8]])
+// CHECK: ret void
+void test_vst1q_s64_x2(int64_t *a, int64x2x2_t b) {
+ vst1q_s64_x2(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_s64_x3(
+// CHECK: [[B:%.*]] = alloca %struct.int64x2x3_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.int64x2x3_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int64x2x3_t, %struct.int64x2x3_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [3 x <2 x i64>] [[B]].coerce, [3 x <2 x i64>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <2 x i64>]* %coerce.dive to [6 x i64]*
+// CHECK-A32: store [6 x i64] %b.coerce, [6 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x2x3_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x2x3_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 48, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x2x3_t, %struct.int64x2x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x i64>], [3 x <2 x i64>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[TMP4:%.*]] = bitcast <2 x i64> [[TMP3]] to <16 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int64x2x3_t, %struct.int64x2x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <2 x i64>], [3 x <2 x i64>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK: [[TMP6:%.*]] = bitcast <2 x i64> [[TMP5]] to <16 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int64x2x3_t, %struct.int64x2x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <2 x i64>], [3 x <2 x i64>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX4]], align [[QALIGN]]
+// CHECK: [[TMP8:%.*]] = bitcast <2 x i64> [[TMP7]] to <16 x i8>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <2 x i64>
+// CHECK-DAG: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <2 x i64>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <2 x i64>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i64*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v2i64.p0i64(<2 x i64> [[TMP9]], <2 x i64> [[TMP10]], <2 x i64> [[TMP11]], i64* [[TMP12]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i64.v2i64(i64* [[TMP12]], <2 x i64> [[TMP9]], <2 x i64> [[TMP10]], <2 x i64> [[TMP11]])
+// CHECK: ret void
+void test_vst1q_s64_x3(int64_t *a, int64x2x3_t b) {
+ vst1q_s64_x3(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_s64_x4(
+// CHECK: [[B:%.*]] = alloca %struct.int64x2x4_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.int64x2x4_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int64x2x4_t, %struct.int64x2x4_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [4 x <2 x i64>] [[B]].coerce, [4 x <2 x i64>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <2 x i64>]* %coerce.dive to [8 x i64]*
+// CHECK-A32: store [8 x i64] %b.coerce, [8 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x2x4_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x2x4_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 64, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x2x4_t, %struct.int64x2x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[TMP4:%.*]] = bitcast <2 x i64> [[TMP3]] to <16 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int64x2x4_t, %struct.int64x2x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK: [[TMP6:%.*]] = bitcast <2 x i64> [[TMP5]] to <16 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int64x2x4_t, %struct.int64x2x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX4]], align [[QALIGN]]
+// CHECK: [[TMP8:%.*]] = bitcast <2 x i64> [[TMP7]] to <16 x i8>
+// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int64x2x4_t, %struct.int64x2x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3
+// CHECK: [[TMP9:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX6]], align [[QALIGN]]
+// CHECK: [[TMP10:%.*]] = bitcast <2 x i64> [[TMP9]] to <16 x i8>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <2 x i64>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <2 x i64>
+// CHECK-DAG: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <2 x i64>
+// CHECK-DAG: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <2 x i64>
+// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i64*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v2i64.p0i64(<2 x i64> [[TMP11]], <2 x i64> [[TMP12]], <2 x i64> [[TMP13]], <2 x i64> [[TMP14]], i64* [[TMP15]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i64.v2i64(i64* [[TMP15]], <2 x i64> [[TMP11]], <2 x i64> [[TMP12]], <2 x i64> [[TMP13]], <2 x i64> [[TMP14]])
+// CHECK: ret void
+void test_vst1q_s64_x4(int64_t *a, int64x2x4_t b) {
+ vst1q_s64_x4(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_s8_x2(
+// CHECK: [[B:%.*]] = alloca %struct.int8x16x2_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.int8x16x2_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x16x2_t, %struct.int8x16x2_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [2 x <16 x i8>] [[B]].coerce, [2 x <16 x i8>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <16 x i8>]* %coerce.dive to [4 x i64]*
+// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x16x2_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 32, i1 false)
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x16x2_t, %struct.int8x16x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int8x16x2_t, %struct.int8x16x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], i8* %a)
+// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i8.v16i8(i8* %a, <16 x i8> [[TMP2]], <16 x i8> [[TMP3]])
+// CHECK: ret void
+void test_vst1q_s8_x2(int8_t *a, int8x16x2_t b) {
+ vst1q_s8_x2(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_s8_x3(
+// CHECK: [[B:%.*]] = alloca %struct.int8x16x3_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.int8x16x3_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x16x3_t, %struct.int8x16x3_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [3 x <16 x i8>] [[B]].coerce, [3 x <16 x i8>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <16 x i8>]* %coerce.dive to [6 x i64]*
+// CHECK-A32: store [6 x i64] %b.coerce, [6 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x3_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x16x3_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 48, i1 false)
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x16x3_t, %struct.int8x16x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int8x16x3_t, %struct.int8x16x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int8x16x3_t, %struct.int8x16x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align [[QALIGN]]
+// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], i8* %a)
+// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i8.v16i8(i8* %a, <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]])
+// CHECK: ret void
+void test_vst1q_s8_x3(int8_t *a, int8x16x3_t b) {
+ vst1q_s8_x3(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_s8_x4(
+// CHECK: [[B:%.*]] = alloca %struct.int8x16x4_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.int8x16x4_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [4 x <16 x i8>] [[B]].coerce, [4 x <16 x i8>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <16 x i8>]* %coerce.dive to [8 x i64]*
+// CHECK-A32: store [8 x i64] %b.coerce, [8 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x4_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x16x4_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 64, i1 false)
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align [[QALIGN]]
+// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3
+// CHECK: [[TMP5:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX6]], align [[QALIGN]]
+// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> [[TMP5]], i8* %a)
+// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i8.v16i8(i8* %a, <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> [[TMP5]])
+// CHECK: ret void
+void test_vst1q_s8_x4(int8_t *a, int8x16x4_t b) {
+ vst1q_s8_x4(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_u16_x2(
+// CHECK: [[B:%.*]] = alloca %struct.uint16x8x2_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x2_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [2 x <8 x i16>] [[B]].coerce, [2 x <8 x i16>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <8 x i16>]* %coerce.dive to [4 x i64]*
+// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x2_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 32, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8>
+// CHECK-DAG: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16>
+// CHECK-DAG: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i16*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v8i16.p0i16(<8 x i16> [[TMP7]], <8 x i16> [[TMP8]], i16* [[TMP9]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i16.v8i16(i16* [[TMP9]], <8 x i16> [[TMP7]], <8 x i16> [[TMP8]])
+// CHECK: ret void
+void test_vst1q_u16_x2(uint16_t *a, uint16x8x2_t b) {
+ vst1q_u16_x2(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_u16_x3(
+// CHECK: [[B:%.*]] = alloca %struct.uint16x8x3_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x3_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [3 x <8 x i16>] [[B]].coerce, [3 x <8 x i16>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <8 x i16>]* %coerce.dive to [6 x i64]*
+// CHECK-A32: store [6 x i64] %b.coerce, [6 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x3_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x3_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 48, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align [[QALIGN]]
+// CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16>
+// CHECK-DAG: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i16*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v8i16.p0i16(<8 x i16> [[TMP9]], <8 x i16> [[TMP10]], <8 x i16> [[TMP11]], i16* [[TMP12]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i16.v8i16(i16* [[TMP12]], <8 x i16> [[TMP9]], <8 x i16> [[TMP10]], <8 x i16> [[TMP11]])
+// CHECK: ret void
+void test_vst1q_u16_x3(uint16_t *a, uint16x8x3_t b) {
+ vst1q_u16_x3(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_u16_x4(
+// CHECK: [[B:%.*]] = alloca %struct.uint16x8x4_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x4_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [4 x <8 x i16>] [[B]].coerce, [4 x <8 x i16>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <8 x i16>]* %coerce.dive to [8 x i64]*
+// CHECK-A32: store [8 x i64] %b.coerce, [8 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x4_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x4_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 64, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align [[QALIGN]]
+// CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8>
+// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3
+// CHECK: [[TMP9:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX6]], align [[QALIGN]]
+// CHECK: [[TMP10:%.*]] = bitcast <8 x i16> [[TMP9]] to <16 x i8>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
+// CHECK-DAG: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16>
+// CHECK-DAG: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x i16>
+// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i16*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v8i16.p0i16(<8 x i16> [[TMP11]], <8 x i16> [[TMP12]], <8 x i16> [[TMP13]], <8 x i16> [[TMP14]], i16* [[TMP15]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i16.v8i16(i16* [[TMP15]], <8 x i16> [[TMP11]], <8 x i16> [[TMP12]], <8 x i16> [[TMP13]], <8 x i16> [[TMP14]])
+// CHECK: ret void
+void test_vst1q_u16_x4(uint16_t *a, uint16x8x4_t b) {
+ vst1q_u16_x4(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_u32_x2(
+// CHECK: [[B:%.*]] = alloca %struct.uint32x4x2_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x2_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [2 x <4 x i32>] [[B]].coerce, [2 x <4 x i32>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <4 x i32>]* %coerce.dive to [4 x i64]*
+// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x2_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 32, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP3]] to <16 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK: [[TMP6:%.*]] = bitcast <4 x i32> [[TMP5]] to <16 x i8>
+// CHECK-DAG: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x i32>
+// CHECK-DAG: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i32*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v4i32.p0i32(<4 x i32> [[TMP7]], <4 x i32> [[TMP8]], i32* [[TMP9]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i32.v4i32(i32* [[TMP9]], <4 x i32> [[TMP7]], <4 x i32> [[TMP8]])
+// CHECK: ret void
+void test_vst1q_u32_x2(uint32_t *a, uint32x4x2_t b) {
+ vst1q_u32_x2(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_u32_x3(
+// CHECK: [[B:%.*]] = alloca %struct.uint32x4x3_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x3_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [3 x <4 x i32>] [[B]].coerce, [3 x <4 x i32>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <4 x i32>]* %coerce.dive to [6 x i64]*
+// CHECK-A32: store [6 x i64] %b.coerce, [6 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x3_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x3_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 48, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP3]] to <16 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK: [[TMP6:%.*]] = bitcast <4 x i32> [[TMP5]] to <16 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align [[QALIGN]]
+// CHECK: [[TMP8:%.*]] = bitcast <4 x i32> [[TMP7]] to <16 x i8>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x i32>
+// CHECK-DAG: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x i32>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i32*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v4i32.p0i32(<4 x i32> [[TMP9]], <4 x i32> [[TMP10]], <4 x i32> [[TMP11]], i32* [[TMP12]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i32.v4i32(i32* [[TMP12]], <4 x i32> [[TMP9]], <4 x i32> [[TMP10]], <4 x i32> [[TMP11]])
+// CHECK: ret void
+void test_vst1q_u32_x3(uint32_t *a, uint32x4x3_t b) {
+ vst1q_u32_x3(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_u32_x4(
+// CHECK: [[B:%.*]] = alloca %struct.uint32x4x4_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x4_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [4 x <4 x i32>] [[B]].coerce, [4 x <4 x i32>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <4 x i32>]* %coerce.dive to [8 x i64]*
+// CHECK-A32: store [8 x i64] %b.coerce, [8 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x4_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x4_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 64, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP3]] to <16 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK: [[TMP6:%.*]] = bitcast <4 x i32> [[TMP5]] to <16 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align [[QALIGN]]
+// CHECK: [[TMP8:%.*]] = bitcast <4 x i32> [[TMP7]] to <16 x i8>
+// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3
+// CHECK: [[TMP9:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX6]], align [[QALIGN]]
+// CHECK: [[TMP10:%.*]] = bitcast <4 x i32> [[TMP9]] to <16 x i8>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x i32>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32>
+// CHECK-DAG: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x i32>
+// CHECK-DAG: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <4 x i32>
+// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i32*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v4i32.p0i32(<4 x i32> [[TMP11]], <4 x i32> [[TMP12]], <4 x i32> [[TMP13]], <4 x i32> [[TMP14]], i32* [[TMP15]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i32.v4i32(i32* [[TMP15]], <4 x i32> [[TMP11]], <4 x i32> [[TMP12]], <4 x i32> [[TMP13]], <4 x i32> [[TMP14]])
+// CHECK: ret void
+void test_vst1q_u32_x4(uint32_t *a, uint32x4x4_t b) {
+ vst1q_u32_x4(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_u64_x2(
+// CHECK: [[B:%.*]] = alloca %struct.uint64x2x2_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.uint64x2x2_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint64x2x2_t, %struct.uint64x2x2_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [2 x <2 x i64>] [[B]].coerce, [2 x <2 x i64>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <2 x i64>]* %coerce.dive to [4 x i64]*
+// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x2x2_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x2x2_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 32, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x2x2_t, %struct.uint64x2x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x i64>], [2 x <2 x i64>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[TMP4:%.*]] = bitcast <2 x i64> [[TMP3]] to <16 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint64x2x2_t, %struct.uint64x2x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <2 x i64>], [2 x <2 x i64>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK: [[TMP6:%.*]] = bitcast <2 x i64> [[TMP5]] to <16 x i8>
+// CHECK-DAG: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <2 x i64>
+// CHECK-DAG: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <2 x i64>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i64*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v2i64.p0i64(<2 x i64> [[TMP7]], <2 x i64> [[TMP8]], i64* [[TMP9]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i64.v2i64(i64* [[TMP9]], <2 x i64> [[TMP7]], <2 x i64> [[TMP8]])
+// CHECK: ret void
+void test_vst1q_u64_x2(uint64_t *a, uint64x2x2_t b) {
+ vst1q_u64_x2(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_u64_x3(
+// CHECK: [[B:%.*]] = alloca %struct.uint64x2x3_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.uint64x2x3_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint64x2x3_t, %struct.uint64x2x3_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [3 x <2 x i64>] [[B]].coerce, [3 x <2 x i64>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <2 x i64>]* %coerce.dive to [6 x i64]*
+// CHECK-A32: store [6 x i64] %b.coerce, [6 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x2x3_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x2x3_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 48, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x2x3_t, %struct.uint64x2x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x i64>], [3 x <2 x i64>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[TMP4:%.*]] = bitcast <2 x i64> [[TMP3]] to <16 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint64x2x3_t, %struct.uint64x2x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <2 x i64>], [3 x <2 x i64>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK: [[TMP6:%.*]] = bitcast <2 x i64> [[TMP5]] to <16 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint64x2x3_t, %struct.uint64x2x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <2 x i64>], [3 x <2 x i64>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX4]], align [[QALIGN]]
+// CHECK: [[TMP8:%.*]] = bitcast <2 x i64> [[TMP7]] to <16 x i8>
+// CHECK-DAG: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <2 x i64>
+// CHECK-DAG: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <2 x i64>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <2 x i64>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i64*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v2i64.p0i64(<2 x i64> [[TMP9]], <2 x i64> [[TMP10]], <2 x i64> [[TMP11]], i64* [[TMP12]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i64.v2i64(i64* [[TMP12]], <2 x i64> [[TMP9]], <2 x i64> [[TMP10]], <2 x i64> [[TMP11]])
+// CHECK: ret void
+void test_vst1q_u64_x3(uint64_t *a, uint64x2x3_t b) {
+ vst1q_u64_x3(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_u64_x4(
+// CHECK: [[B:%.*]] = alloca %struct.uint64x2x4_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.uint64x2x4_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint64x2x4_t, %struct.uint64x2x4_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [4 x <2 x i64>] [[B]].coerce, [4 x <2 x i64>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <2 x i64>]* %coerce.dive to [8 x i64]*
+// CHECK-A32: store [8 x i64] %b.coerce, [8 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x2x4_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x2x4_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 64, i1 false)
+// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8*
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x2x4_t, %struct.uint64x2x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP3:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[TMP4:%.*]] = bitcast <2 x i64> [[TMP3]] to <16 x i8>
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint64x2x4_t, %struct.uint64x2x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP5:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK: [[TMP6:%.*]] = bitcast <2 x i64> [[TMP5]] to <16 x i8>
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint64x2x4_t, %struct.uint64x2x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP7:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX4]], align [[QALIGN]]
+// CHECK: [[TMP8:%.*]] = bitcast <2 x i64> [[TMP7]] to <16 x i8>
+// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint64x2x4_t, %struct.uint64x2x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3
+// CHECK: [[TMP9:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX6]], align [[QALIGN]]
+// CHECK: [[TMP10:%.*]] = bitcast <2 x i64> [[TMP9]] to <16 x i8>
+// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <2 x i64>
+// CHECK-DAG: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <2 x i64>
+// CHECK-DAG: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <2 x i64>
+// CHECK-DAG: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <2 x i64>
+// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i64*
+// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v2i64.p0i64(<2 x i64> [[TMP11]], <2 x i64> [[TMP12]], <2 x i64> [[TMP13]], <2 x i64> [[TMP14]], i64* [[TMP15]])
+// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i64.v2i64(i64* [[TMP15]], <2 x i64> [[TMP11]], <2 x i64> [[TMP12]], <2 x i64> [[TMP13]], <2 x i64> [[TMP14]])
+// CHECK: ret void
+void test_vst1q_u64_x4(uint64_t *a, uint64x2x4_t b) {
+ vst1q_u64_x4(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_u8_x2(
+// CHECK: [[B:%.*]] = alloca %struct.uint8x16x2_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.uint8x16x2_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [2 x <16 x i8>] [[B]].coerce, [2 x <16 x i8>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <16 x i8>]* %coerce.dive to [4 x i64]*
+// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x16x2_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 32, i1 false)
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], i8* %a)
+// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i8.v16i8(i8* %a, <16 x i8> [[TMP2]], <16 x i8> [[TMP3]])
+// CHECK: ret void
+void test_vst1q_u8_x2(uint8_t *a, uint8x16x2_t b) {
+ vst1q_u8_x2(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_u8_x3(
+// CHECK: [[B:%.*]] = alloca %struct.uint8x16x3_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.uint8x16x3_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [3 x <16 x i8>] [[B]].coerce, [3 x <16 x i8>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <16 x i8>]* %coerce.dive to [6 x i64]*
+// CHECK-A32: store [6 x i64] %b.coerce, [6 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x3_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x16x3_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 48, i1 false)
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align [[QALIGN]]
+// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], i8* %a)
+// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i8.v16i8(i8* %a, <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]])
+// CHECK: ret void
+void test_vst1q_u8_x3(uint8_t *a, uint8x16x3_t b) {
+ vst1q_u8_x3(a, b);
+}
+
+// CHECK-LABEL: @test_vst1q_u8_x4(
+// CHECK: [[B:%.*]] = alloca %struct.uint8x16x4_t, align [[QALIGN]]
+// CHECK: [[__S1:%.*]] = alloca %struct.uint8x16x4_t, align [[QALIGN]]
+// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[B]], i32 0, i32 0
+// CHECK-A64: store [4 x <16 x i8>] [[B]].coerce, [4 x <16 x i8>]* [[COERCE_DIVE]], align 16
+// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <16 x i8>]* %coerce.dive to [8 x i64]*
+// CHECK-A32: store [8 x i64] %b.coerce, [8 x i64]* [[COERCE_DIVE_TMP]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x4_t* [[__S1]] to i8*
+// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x16x4_t* [[B]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 64, i1 false)
+// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0
+// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align [[QALIGN]]
+// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1
+// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align [[QALIGN]]
+// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2
+// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align [[QALIGN]]
+// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[__S1]], i32 0, i32 0
+// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3
+// CHECK: [[TMP5:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX6]], align [[QALIGN]]
+// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> [[TMP5]], i8* %a)
+// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i8.v16i8(i8* %a, <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> [[TMP5]])
+// CHECK: ret void
+void test_vst1q_u8_x4(uint8_t *a, uint8x16x4_t b) {
+ vst1q_u8_x4(a, b);
+}
diff --git a/test/CodeGen/arm-no-movt.c b/test/CodeGen/arm-no-movt.c
index f61f2248643e..bee1752b059c 100644
--- a/test/CodeGen/arm-no-movt.c
+++ b/test/CodeGen/arm-no-movt.c
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -triple thumbv7-apple-ios5 -target-feature +no-movt -emit-llvm -o - %s | FileCheck -check-prefix=NO-MOVT %s
// RUN: %clang_cc1 -triple thumbv7-apple-ios5 -emit-llvm -o - %s | FileCheck -check-prefix=MOVT %s
-// NO-MOVT: attributes #0 = { {{.*}} "target-features"="+no-movt,+thumb-mode"
-// MOVT-NOT: attributes #0 = { {{.*}} "target-features"="+no-movt,+thumb-mode"
+// NO-MOVT: attributes #0 = { {{.*}} "target-features"="+armv7-a,+no-movt,+thumb-mode"
+// MOVT-NOT: attributes #0 = { {{.*}} "target-features"="+armv7-a,+no-movt,+thumb-mode"
int foo1(int a) { return a; }
diff --git a/test/CodeGen/arm-swiftcall.c b/test/CodeGen/arm-swiftcall.c
index f5c33845e2f4..53109a3f681e 100644
--- a/test/CodeGen/arm-swiftcall.c
+++ b/test/CodeGen/arm-swiftcall.c
@@ -103,9 +103,7 @@ typedef struct {
TEST(struct_1);
// CHECK-LABEL: define {{.*}} @return_struct_1()
// CHECK: [[RET:%.*]] = alloca [[REC:%.*]], align 4
-// CHECK: [[VAR:%.*]] = alloca [[REC]], align 4
// CHECK: @llvm.memset
-// CHECK: @llvm.memcpy
// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[RET]] to [[AGG:{ i32, i16, \[2 x i8\], float, float }]]*
// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
// CHECK: [[FIRST:%.*]] = load i32, i32* [[T0]], align 4
@@ -170,8 +168,6 @@ typedef struct {
TEST(struct_2);
// CHECK-LABEL: define {{.*}} @return_struct_2()
// CHECK: [[RET:%.*]] = alloca [[REC:%.*]], align 4
-// CHECK: [[VAR:%.*]] = alloca [[REC]], align 4
-// CHECK: @llvm.memcpy
// CHECK: @llvm.memcpy
// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[RET]] to [[AGG:{ i32, i32, float, float }]]*
// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
@@ -240,9 +236,7 @@ typedef struct {
TEST(struct_misaligned_1)
// CHECK-LABEL: define {{.*}} @return_struct_misaligned_1()
// CHECK: [[RET:%.*]] = alloca [[REC:%.*]], align
-// CHECK: [[VAR:%.*]] = alloca [[REC]], align
// CHECK: @llvm.memset
-// CHECK: @llvm.memcpy
// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[RET]] to [[AGG:{ i32, i8 }]]*
// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
// CHECK: [[FIRST:%.*]] = load i32, i32* [[T0]], align
@@ -282,8 +276,6 @@ typedef union {
TEST(union_het_fp)
// CHECK-LABEL: define {{.*}} @return_union_het_fp()
// CHECK: [[RET:%.*]] = alloca [[REC:%.*]], align {{(4|8)}}
-// CHECK: [[VAR:%.*]] = alloca [[REC]], align {{(4|8)}}
-// CHECK: @llvm.memcpy
// CHECK: @llvm.memcpy
// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[RET]] to [[AGG:{ i32, i32 }]]*
// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
@@ -414,7 +406,6 @@ TEST(int4)
TEST(int8)
// CHECK-LABEL: define {{.*}} @return_int8()
// CHECK: [[RET:%.*]] = alloca [[REC:<8 x i32>]], align 32
-// CHECK: [[VAR:%.*]] = alloca [[REC]], align
// CHECK: store
// CHECK: load
// CHECK: store
@@ -458,7 +449,6 @@ TEST(int8)
TEST(int5)
// CHECK-LABEL: define {{.*}} @return_int5()
// CHECK: [[RET:%.*]] = alloca [[REC:<5 x i32>]], align 32
-// CHECK: [[VAR:%.*]] = alloca [[REC]], align
// CHECK: store
// CHECK: load
// CHECK: store
diff --git a/test/CodeGen/arm-target-features.c b/test/CodeGen/arm-target-features.c
index e5591a28ad1a..6bc56be4f4ca 100644
--- a/test/CodeGen/arm-target-features.c
+++ b/test/CodeGen/arm-target-features.c
@@ -1,22 +1,23 @@
// REQUIRES: arm-registered-target
// RUN: %clang_cc1 -triple thumbv7-linux-gnueabihf -target-cpu cortex-a8 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP3
-// CHECK-VFP3: "target-features"="+dsp,+neon,+thumb-mode
+// CHECK-VFP3: "target-features"="+armv7-a,+dsp,+neon,+thumb-mode,+vfp3"
// RUN: %clang_cc1 -triple thumbv7-linux-gnueabihf -target-cpu cortex-a5 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP4
-// CHECK-VFP4: "target-features"="+dsp,+neon,+thumb-mode,+vfp4"
+// CHECK-VFP4: "target-features"="+armv7-a,+dsp,+neon,+thumb-mode,+vfp4"
// RUN: %clang_cc1 -triple thumbv7-linux-gnueabihf -target-cpu cortex-a7 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP4-DIV
// RUN: %clang_cc1 -triple thumbv7-linux-gnueabi -target-cpu cortex-a12 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP4-DIV
-// RUN: %clang_cc1 -triple thumbv7s-linux-gnueabi -target-cpu swift -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP4-DIV
+// RUN: %clang_cc1 -triple thumbv7s-linux-gnueabi -target-cpu swift -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP4-DIV-2
// RUN: %clang_cc1 -triple thumbv7-linux-gnueabihf -target-cpu krait -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP4-DIV
-// CHECK-VFP4-DIV: "target-features"="+dsp,+hwdiv,+hwdiv-arm,+neon,+thumb-mode,+vfp4"
+// CHECK-VFP4-DIV: "target-features"="+armv7-a,+dsp,+hwdiv,+hwdiv-arm,+neon,+thumb-mode,+vfp4"
+// CHECK-VFP4-DIV-2: "target-features"="+armv7s,+dsp,+hwdiv,+hwdiv-arm,+neon,+thumb-mode,+vfp4"
// RUN: %clang_cc1 -triple armv7-linux-gnueabihf -target-cpu cortex-a15 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP4-DIV-ARM
// RUN: %clang_cc1 -triple armv7-linux-gnueabihf -target-cpu cortex-a17 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP4-DIV-ARM
-// CHECK-VFP4-DIV-ARM: "target-features"="+dsp,+hwdiv,+hwdiv-arm,+neon,+vfp4,-thumb-mode"
+// CHECK-VFP4-DIV-ARM: "target-features"="+armv7-a,+dsp,+hwdiv,+hwdiv-arm,+neon,+vfp4,-thumb-mode"
// RUN: %clang_cc1 -triple thumbv7s-apple-ios7.0 -target-cpu cyclone -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8
// RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu cortex-a32 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8
@@ -27,37 +28,82 @@
// RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu exynos-m1 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8
// RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu exynos-m2 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8
// RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu exynos-m3 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8
-// CHECK-BASIC-V8: "target-features"="+crc,+crypto,+dsp,+fp-armv8,+hwdiv,+hwdiv-arm,+neon,+thumb-mode"
+// RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu exynos-m4 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8
+// CHECK-BASIC-V8: "target-features"="+armv8-a,+crc,+crypto,+dsp,+fp-armv8,+hwdiv,+hwdiv-arm,+neon,+thumb-mode"
// RUN: %clang_cc1 -triple armv8-linux-gnueabi -target-cpu cortex-a53 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8-ARM
-// CHECK-BASIC-V8-ARM: "target-features"="+crc,+crypto,+dsp,+fp-armv8,+hwdiv,+hwdiv-arm,+neon,-thumb-mode"
+// CHECK-BASIC-V8-ARM: "target-features"="+armv8-a,+crc,+crypto,+dsp,+fp-armv8,+hwdiv,+hwdiv-arm,+neon,-thumb-mode"
// RUN: %clang_cc1 -triple thumbv7-linux-gnueabi -target-cpu cortex-r5 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP3-D16-DIV
-// CHECK-VFP3-D16-DIV: "target-features"="+d16,+dsp,+hwdiv,+hwdiv-arm,+thumb-mode,+vfp3"
+// CHECK-VFP3-D16-DIV: "target-features"="+armv7-r,+d16,+dsp,+hwdiv,+hwdiv-arm,+thumb-mode,+vfp3"
// RUN: %clang_cc1 -triple armv7-linux-gnueabi -target-cpu cortex-r4f -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP3-D16-THUMB-DIV
-// CHECK-VFP3-D16-THUMB-DIV: "target-features"="+d16,+dsp,+hwdiv,+vfp3,-thumb-mode"
+// CHECK-VFP3-D16-THUMB-DIV: "target-features"="+armv7-r,+d16,+dsp,+hwdiv,+vfp3,-thumb-mode"
// RUN: %clang_cc1 -triple thumbv7-linux-gnueabi -target-cpu cortex-r7 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP3-D16-FP16-DIV
// RUN: %clang_cc1 -triple thumbv7-linux-gnueabi -target-cpu cortex-r8 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP3-D16-FP16-DIV
-// CHECK-VFP3-D16-FP16-DIV: "target-features"="+d16,+dsp,+fp16,+hwdiv,+hwdiv-arm,+thumb-mode,+vfp3"
+// CHECK-VFP3-D16-FP16-DIV: "target-features"="+armv7-r,+d16,+dsp,+fp16,+hwdiv,+hwdiv-arm,+thumb-mode,+vfp3"
// RUN: %clang_cc1 -triple thumbv7-linux-gnueabi -target-cpu cortex-m4 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP4-D16-SP-THUMB-DIV
-// CHECK-VFP4-D16-SP-THUMB-DIV: "target-features"="+d16,+dsp,+fp-only-sp,+hwdiv,+thumb-mode,+vfp4"
+// CHECK-VFP4-D16-SP-THUMB-DIV: "target-features"="+armv7e-m,+d16,+dsp,+fp-only-sp,+hwdiv,+thumb-mode,+vfp4"
// RUN: %clang_cc1 -triple thumbv7-linux-gnueabi -target-cpu cortex-m7 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP5-D16-THUMB-DIV
-// CHECK-VFP5-D16-THUMB-DIV: "target-features"="+d16,+dsp,+fp-armv8,+hwdiv,+thumb-mode"
+// CHECK-VFP5-D16-THUMB-DIV: "target-features"="+armv7e-m,+d16,+dsp,+fp-armv8,+hwdiv,+thumb-mode"
// RUN: %clang_cc1 -triple armv7-linux-gnueabi -target-cpu cortex-r4 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-THUMB-DIV
-// CHECK-THUMB-DIV: "target-features"="+dsp,+hwdiv,-thumb-mode"
+// CHECK-THUMB-DIV: "target-features"="+armv7-r,+dsp,+hwdiv,-thumb-mode"
// RUN: %clang_cc1 -triple thumbv7-linux-gnueabi -target-cpu cortex-m3 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-THUMB-DIV-M3
-// CHECK-THUMB-DIV-M3: "target-features"="+hwdiv,+thumb-mode"
+// CHECK-THUMB-DIV-M3: "target-features"="+armv7-m,+hwdiv,+thumb-mode"
+// (The following test with no arch specified shouldn't happen; the driver
+// rewrites triples. Just make sure it does something sane.)
+// RUN: %clang_cc1 -triple arm-linux-gnueabi -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-ARM-NOARCH-LINUX
+// CHECK-ARM-NOARCH-LINUX: "target-features"="-thumb-mode"
+
+// RUN: %clang_cc1 -triple armv4-linux-gnueabi -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-ARMV4-LINUX
+// CHECK-ARMV4-LINUX: "target-features"="+armv4,-thumb-mode"
+
+// RUN: %clang_cc1 -triple armv4t-linux-gnueabi -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-ARMV4T-LINUX
+// CHECK-ARMV4T-LINUX: "target-features"="+armv4t,-thumb-mode"
+
+// RUN: %clang_cc1 -triple armv5t-linux-gnueabi -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-ARMV5T-LINUX
+// CHECK-ARMV5T-LINUX: "target-features"="+armv5t,-thumb-mode"
+
+// RUN: %clang_cc1 -triple armv6-linux-gnueabi -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-ARMV6-LINUX
+// CHECK-ARMV6-LINUX: "target-features"="+armv6,-thumb-mode"
+
+// RUN: %clang_cc1 -triple armv6k-linux-gnueabi -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-ARMV6K-LINUX
+// CHECK-ARMV6K-LINUX: "target-features"="+armv6k,-thumb-mode"
+
+// RUN: %clang_cc1 -triple arm-linux-gnueabi -target-cpu mpcorenovfp -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-ARMV6K-MPCORE-LINUX
+// CHECK-ARMV6K-MPCORE-LINUX: "target-features"="+armv6k,+dsp,-thumb-mode"
+
+// RUN: %clang_cc1 -triple armv6t2-linux-gnueabi -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-ARMV6T2-LINUX
+// CHECK-ARMV6T2-LINUX: "target-features"="+armv6t2,-thumb-mode"
+
+// RUN: %clang_cc1 -triple thumbv6m-linux-gnueabi -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-ARMV6M-LINUX
+// RUN: %clang_cc1 -triple thumb-linux-gnueabi -target-cpu cortex-m0 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-ARMV6M-LINUX
+// CHECK-ARMV6M-LINUX: "target-features"="+armv6-m,+thumb-mode"
+
+// RUN: %clang_cc1 -triple thumbv7m-linux-gnueabi -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-ARMV7M-LINUX
+// CHECK-ARMV7M-LINUX: "target-features"="+armv7-m,+thumb-mode"
+
+// RUN: %clang_cc1 -triple thumb-linux-gnueabi -target-cpu cortex-m3 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-ARMV7M-M3-LINUX
+// CHECK-ARMV7M-M3-LINUX: "target-features"="+armv7-m,+hwdiv,+thumb-mode"
+
+// RUN: %clang_cc1 -triple thumbv8m.base-linux-gnueabi -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-ARMV8M-LINUX
+// CHECK-ARMV8M-LINUX: "target-features"="+armv8-m.base,+thumb-mode"
+
+// RUN: %clang_cc1 -triple thumb-linux-gnueabi -target-cpu cortex-m23 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-ARMV8M-M23-LINUX
+// CHECK-ARMV8M-M23-LINUX: "target-features"="+armv8-m.base,+hwdiv,+thumb-mode"
+
+// RUN: %clang_cc1 -triple thumb-linux-gnueabi -target-cpu cortex-m33 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-ARMV8M-MAIN-LINUX
+// CHECK-ARMV8M-MAIN-LINUX: "target-features"="+armv8-m.main,+d16,+dsp,+fp-armv8,+fp-only-sp,+hwdiv,+thumb-mode"
void foo() {}
diff --git a/test/CodeGen/arm-thumb-mode-target-feature.c b/test/CodeGen/arm-thumb-mode-target-feature.c
index 5c41d0b16fda..2b86529dc634 100644
--- a/test/CodeGen/arm-thumb-mode-target-feature.c
+++ b/test/CodeGen/arm-thumb-mode-target-feature.c
@@ -17,8 +17,8 @@ void t3() {}
// THUMB: void @t1() [[ThumbAttr:#[0-7]]]
// THUMB: void @t2() [[NoThumbAttr:#[0-7]]]
// THUMB: void @t3() [[ThumbAttr:#[0-7]]]
-// THUMB: attributes [[ThumbAttr]] = { {{.*}} "target-features"="+thumb-mode"
-// THUMB: attributes [[NoThumbAttr]] = { {{.*}} "target-features"="-thumb-mode"
+// THUMB: attributes [[ThumbAttr]] = { {{.*}} "target-features"="+armv7-a,+thumb-mode"
+// THUMB: attributes [[NoThumbAttr]] = { {{.*}} "target-features"="+armv7-a,-thumb-mode"
//
// THUMB-CLANG: void @t1() [[ThumbAttr:#[0-7]]]
// THUMB-CLANG: void @t2() [[NoThumbAttr:#[0-7]]]
@@ -29,5 +29,5 @@ void t3() {}
// ARM: void @t1() [[NoThumbAtr:#[0-7]]]
// ARM: void @t2() [[NoThumbAttr:#[0-7]]]
// ARM: void @t3() [[ThumbAttr:#[0-7]]]
-// ARM: attributes [[NoThumbAttr]] = { {{.*}} "target-features"="-thumb-mode"
-// ARM: attributes [[ThumbAttr]] = { {{.*}} "target-features"="+thumb-mode"
+// ARM: attributes [[NoThumbAttr]] = { {{.*}} "target-features"="+armv7-a,-thumb-mode"
+// ARM: attributes [[ThumbAttr]] = { {{.*}} "target-features"="+armv7-a,+thumb-mode"
diff --git a/test/CodeGen/arm-v8.2a-neon-intrinsics.c b/test/CodeGen/arm-v8.2a-neon-intrinsics.c
new file mode 100644
index 000000000000..58d911d3ff70
--- /dev/null
+++ b/test/CodeGen/arm-v8.2a-neon-intrinsics.c
@@ -0,0 +1,989 @@
+// RUN: %clang_cc1 -triple armv8.2a-linux-gnu -target-abi apcs-gnu -target-feature +neon -target-feature +fullfp16 \
+// RUN: -fallow-half-arguments-and-returns -S -disable-O0-optnone -emit-llvm -o - %s \
+// RUN: | opt -S -mem2reg \
+// RUN: | FileCheck %s
+
+// REQUIRES: arm-registered-target
+
+#include <arm_neon.h>
+
+// CHECK-LABEL: test_vabs_f16
+// CHECK: [[ABS:%.*]] = call <4 x half> @llvm.fabs.v4f16(<4 x half> %a)
+// CHECK: ret <4 x half> [[ABS]]
+float16x4_t test_vabs_f16(float16x4_t a) {
+ return vabs_f16(a);
+}
+
+// CHECK-LABEL: test_vabsq_f16
+// CHECK: [[ABS:%.*]] = call <8 x half> @llvm.fabs.v8f16(<8 x half> %a)
+// CHECK: ret <8 x half> [[ABS]]
+float16x8_t test_vabsq_f16(float16x8_t a) {
+ return vabsq_f16(a);
+}
+
+// CHECK-LABEL: test_vceqz_f16
+// CHECK: [[TMP1:%.*]] = fcmp oeq <4 x half> %a, zeroinitializer
+// CHECK: [[TMP2:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i16>
+// CHECK: ret <4 x i16> [[TMP2]]
+uint16x4_t test_vceqz_f16(float16x4_t a) {
+ return vceqz_f16(a);
+}
+
+// CHECK-LABEL: test_vceqzq_f16
+// CHECK: [[TMP1:%.*]] = fcmp oeq <8 x half> %a, zeroinitializer
+// CHECK: [[TMP2:%.*]] = sext <8 x i1> [[TMP1:%.*]] to <8 x i16>
+// CHECK: ret <8 x i16> [[TMP2]]
+uint16x8_t test_vceqzq_f16(float16x8_t a) {
+ return vceqzq_f16(a);
+}
+
+// CHECK-LABEL: test_vcgez_f16
+// CHECK: [[TMP1:%.*]] = fcmp oge <4 x half> %a, zeroinitializer
+// CHECK: [[TMP2:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i16>
+// CHECK: ret <4 x i16> [[TMP2]]
+uint16x4_t test_vcgez_f16(float16x4_t a) {
+ return vcgez_f16(a);
+}
+
+// CHECK-LABEL: test_vcgezq_f16
+// CHECK: [[TMP1:%.*]] = fcmp oge <8 x half> %a, zeroinitializer
+// CHECK: [[TMP2:%.*]] = sext <8 x i1> [[TMP1:%.*]] to <8 x i16>
+// CHECK: ret <8 x i16> [[TMP2]]
+uint16x8_t test_vcgezq_f16(float16x8_t a) {
+ return vcgezq_f16(a);
+}
+
+// CHECK-LABEL: test_vcgtz_f16
+// CHECK: [[TMP1:%.*]] = fcmp ogt <4 x half> %a, zeroinitializer
+// CHECK: [[TMP2:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i16>
+// CHECK: ret <4 x i16> [[TMP2]]
+uint16x4_t test_vcgtz_f16(float16x4_t a) {
+ return vcgtz_f16(a);
+}
+
+// CHECK-LABEL: test_vcgtzq_f16
+// CHECK: [[TMP1:%.*]] = fcmp ogt <8 x half> %a, zeroinitializer
+// CHECK: [[TMP2:%.*]] = sext <8 x i1> [[TMP1:%.*]] to <8 x i16>
+// CHECK: ret <8 x i16> [[TMP2]]
+uint16x8_t test_vcgtzq_f16(float16x8_t a) {
+ return vcgtzq_f16(a);
+}
+
+// CHECK-LABEL: test_vclez_f16
+// CHECK: [[TMP1:%.*]] = fcmp ole <4 x half> %a, zeroinitializer
+// CHECK: [[TMP2:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i16>
+// CHECK: ret <4 x i16> [[TMP2]]
+uint16x4_t test_vclez_f16(float16x4_t a) {
+ return vclez_f16(a);
+}
+
+// CHECK-LABEL: test_vclezq_f16
+// CHECK: [[TMP1:%.*]] = fcmp ole <8 x half> %a, zeroinitializer
+// CHECK: [[TMP2:%.*]] = sext <8 x i1> [[TMP1:%.*]] to <8 x i16>
+// CHECK: ret <8 x i16> [[TMP2]]
+uint16x8_t test_vclezq_f16(float16x8_t a) {
+ return vclezq_f16(a);
+}
+
+// CHECK-LABEL: test_vcltz_f16
+// CHECK: [[TMP1:%.*]] = fcmp olt <4 x half> %a, zeroinitializer
+// CHECK: [[TMP2:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i16>
+// CHECK: ret <4 x i16> [[TMP2]]
+uint16x4_t test_vcltz_f16(float16x4_t a) {
+ return vcltz_f16(a);
+}
+
+// CHECK-LABEL: test_vcltzq_f16
+// CHECK: [[TMP1:%.*]] = fcmp olt <8 x half> %a, zeroinitializer
+// CHECK: [[TMP2:%.*]] = sext <8 x i1> [[TMP1:%.*]] to <8 x i16>
+// CHECK: ret <8 x i16> [[TMP2]]
+uint16x8_t test_vcltzq_f16(float16x8_t a) {
+ return vcltzq_f16(a);
+}
+
+// CHECK-LABEL: test_vcvt_f16_s16
+// CHECK: [[VCVT:%.*]] = sitofp <4 x i16> %a to <4 x half>
+// CHECK: ret <4 x half> [[VCVT]]
+float16x4_t test_vcvt_f16_s16 (int16x4_t a) {
+ return vcvt_f16_s16(a);
+}
+
+// CHECK-LABEL: test_vcvtq_f16_s16
+// CHECK: [[VCVT:%.*]] = sitofp <8 x i16> %a to <8 x half>
+// CHECK: ret <8 x half> [[VCVT]]
+float16x8_t test_vcvtq_f16_s16 (int16x8_t a) {
+ return vcvtq_f16_s16(a);
+}
+
+// CHECK-LABEL: test_vcvt_f16_u16
+// CHECK: [[VCVT:%.*]] = uitofp <4 x i16> %a to <4 x half>
+// CHECK: ret <4 x half> [[VCVT]]
+float16x4_t test_vcvt_f16_u16 (uint16x4_t a) {
+ return vcvt_f16_u16(a);
+}
+
+// CHECK-LABEL: test_vcvtq_f16_u16
+// CHECK: [[VCVT:%.*]] = uitofp <8 x i16> %a to <8 x half>
+// CHECK: ret <8 x half> [[VCVT]]
+float16x8_t test_vcvtq_f16_u16 (uint16x8_t a) {
+ return vcvtq_f16_u16(a);
+}
+
+// CHECK-LABEL: test_vcvt_s16_f16
+// CHECK: [[VCVT:%.*]] = fptosi <4 x half> %a to <4 x i16>
+// CHECK: ret <4 x i16> [[VCVT]]
+int16x4_t test_vcvt_s16_f16 (float16x4_t a) {
+ return vcvt_s16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtq_s16_f16
+// CHECK: [[VCVT:%.*]] = fptosi <8 x half> %a to <8 x i16>
+// CHECK: ret <8 x i16> [[VCVT]]
+int16x8_t test_vcvtq_s16_f16 (float16x8_t a) {
+ return vcvtq_s16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvt_u16_f16
+// CHECK: [[VCVT:%.*]] = fptoui <4 x half> %a to <4 x i16>
+// CHECK: ret <4 x i16> [[VCVT]]
+int16x4_t test_vcvt_u16_f16 (float16x4_t a) {
+ return vcvt_u16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtq_u16_f16
+// CHECK: [[VCVT:%.*]] = fptoui <8 x half> %a to <8 x i16>
+// CHECK: ret <8 x i16> [[VCVT]]
+int16x8_t test_vcvtq_u16_f16 (float16x8_t a) {
+ return vcvtq_u16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvta_s16_f16
+// CHECK: [[VCVT:%.*]] = call <4 x i16> @llvm.arm.neon.vcvtas.v4i16.v4f16(<4 x half> %a)
+// CHECK: ret <4 x i16> [[VCVT]]
+int16x4_t test_vcvta_s16_f16 (float16x4_t a) {
+ return vcvta_s16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvta_u16_f16
+// CHECK: [[VCVT:%.*]] = call <4 x i16> @llvm.arm.neon.vcvtau.v4i16.v4f16(<4 x half> %a)
+// CHECK: ret <4 x i16> [[VCVT]]
+int16x4_t test_vcvta_u16_f16 (float16x4_t a) {
+ return vcvta_u16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtaq_s16_f16
+// CHECK: [[VCVT:%.*]] = call <8 x i16> @llvm.arm.neon.vcvtas.v8i16.v8f16(<8 x half> %a)
+// CHECK: ret <8 x i16> [[VCVT]]
+int16x8_t test_vcvtaq_s16_f16 (float16x8_t a) {
+ return vcvtaq_s16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtm_s16_f16
+// CHECK: [[VCVT:%.*]] = call <4 x i16> @llvm.arm.neon.vcvtms.v4i16.v4f16(<4 x half> %a)
+// CHECK: ret <4 x i16> [[VCVT]]
+int16x4_t test_vcvtm_s16_f16 (float16x4_t a) {
+ return vcvtm_s16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtmq_s16_f16
+// CHECK: [[VCVT:%.*]] = call <8 x i16> @llvm.arm.neon.vcvtms.v8i16.v8f16(<8 x half> %a)
+// CHECK: ret <8 x i16> [[VCVT]]
+int16x8_t test_vcvtmq_s16_f16 (float16x8_t a) {
+ return vcvtmq_s16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtm_u16_f16
+// CHECK: [[VCVT:%.*]] = call <4 x i16> @llvm.arm.neon.vcvtmu.v4i16.v4f16(<4 x half> %a)
+// CHECK: ret <4 x i16> [[VCVT]]
+uint16x4_t test_vcvtm_u16_f16 (float16x4_t a) {
+ return vcvtm_u16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtmq_u16_f16
+// CHECK: [[VCVT:%.*]] = call <8 x i16> @llvm.arm.neon.vcvtmu.v8i16.v8f16(<8 x half> %a)
+// CHECK: ret <8 x i16> [[VCVT]]
+uint16x8_t test_vcvtmq_u16_f16 (float16x8_t a) {
+ return vcvtmq_u16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtn_s16_f16
+// CHECK: [[VCVT:%.*]] = call <4 x i16> @llvm.arm.neon.vcvtns.v4i16.v4f16(<4 x half> %a)
+// CHECK: ret <4 x i16> [[VCVT]]
+int16x4_t test_vcvtn_s16_f16 (float16x4_t a) {
+ return vcvtn_s16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtnq_s16_f16
+// CHECK: [[VCVT:%.*]] = call <8 x i16> @llvm.arm.neon.vcvtns.v8i16.v8f16(<8 x half> %a)
+// CHECK: ret <8 x i16> [[VCVT]]
+int16x8_t test_vcvtnq_s16_f16 (float16x8_t a) {
+ return vcvtnq_s16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtn_u16_f16
+// CHECK: [[VCVT:%.*]] = call <4 x i16> @llvm.arm.neon.vcvtnu.v4i16.v4f16(<4 x half> %a)
+// CHECK: ret <4 x i16> [[VCVT]]
+uint16x4_t test_vcvtn_u16_f16 (float16x4_t a) {
+ return vcvtn_u16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtnq_u16_f16
+// CHECK: [[VCVT:%.*]] = call <8 x i16> @llvm.arm.neon.vcvtnu.v8i16.v8f16(<8 x half> %a)
+// CHECK: ret <8 x i16> [[VCVT]]
+uint16x8_t test_vcvtnq_u16_f16 (float16x8_t a) {
+ return vcvtnq_u16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtp_s16_f16
+// CHECK: [[VCVT:%.*]] = call <4 x i16> @llvm.arm.neon.vcvtps.v4i16.v4f16(<4 x half> %a)
+// CHECK: ret <4 x i16> [[VCVT]]
+int16x4_t test_vcvtp_s16_f16 (float16x4_t a) {
+ return vcvtp_s16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtpq_s16_f16
+// CHECK: [[VCVT:%.*]] = call <8 x i16> @llvm.arm.neon.vcvtps.v8i16.v8f16(<8 x half> %a)
+// CHECK: ret <8 x i16> [[VCVT]]
+int16x8_t test_vcvtpq_s16_f16 (float16x8_t a) {
+ return vcvtpq_s16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtp_u16_f16
+// CHECK: [[VCVT:%.*]] = call <4 x i16> @llvm.arm.neon.vcvtpu.v4i16.v4f16(<4 x half> %a)
+// CHECK: ret <4 x i16> [[VCVT]]
+uint16x4_t test_vcvtp_u16_f16 (float16x4_t a) {
+ return vcvtp_u16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtpq_u16_f16
+// CHECK: [[VCVT:%.*]] = call <8 x i16> @llvm.arm.neon.vcvtpu.v8i16.v8f16(<8 x half> %a)
+// CHECK: ret <8 x i16> [[VCVT]]
+uint16x8_t test_vcvtpq_u16_f16 (float16x8_t a) {
+ return vcvtpq_u16_f16(a);
+}
+
+// FIXME: Fix the zero constant when fp16 non-storage-only type becomes available.
+// CHECK-LABEL: test_vneg_f16
+// CHECK: [[NEG:%.*]] = fsub <4 x half> <half 0xH8000, half 0xH8000, half 0xH8000, half 0xH8000>, %a
+// CHECK: ret <4 x half> [[NEG]]
+float16x4_t test_vneg_f16(float16x4_t a) {
+ return vneg_f16(a);
+}
+
+// CHECK-LABEL: test_vnegq_f16
+// CHECK: [[NEG:%.*]] = fsub <8 x half> <half 0xH8000, half 0xH8000, half 0xH8000, half 0xH8000, half 0xH8000, half 0xH8000, half 0xH8000, half 0xH8000>, %a
+// CHECK: ret <8 x half> [[NEG]]
+float16x8_t test_vnegq_f16(float16x8_t a) {
+ return vnegq_f16(a);
+}
+
+// CHECK-LABEL: test_vrecpe_f16
+// CHECK: [[RCP:%.*]] = call <4 x half> @llvm.arm.neon.vrecpe.v4f16(<4 x half> %a)
+// CHECK: ret <4 x half> [[RCP]]
+float16x4_t test_vrecpe_f16(float16x4_t a) {
+ return vrecpe_f16(a);
+}
+
+// CHECK-LABEL: test_vrecpeq_f16
+// CHECK: [[RCP:%.*]] = call <8 x half> @llvm.arm.neon.vrecpe.v8f16(<8 x half> %a)
+// CHECK: ret <8 x half> [[RCP]]
+float16x8_t test_vrecpeq_f16(float16x8_t a) {
+ return vrecpeq_f16(a);
+}
+
+// CHECK-LABEL: test_vrnd_f16
+// CHECK: [[RND:%.*]] = call <4 x half> @llvm.arm.neon.vrintz.v4f16(<4 x half> %a)
+// CHECK: ret <4 x half> [[RND]]
+float16x4_t test_vrnd_f16(float16x4_t a) {
+ return vrnd_f16(a);
+}
+
+// CHECK-LABEL: test_vrndq_f16
+// CHECK: [[RND:%.*]] = call <8 x half> @llvm.arm.neon.vrintz.v8f16(<8 x half> %a)
+// CHECK: ret <8 x half> [[RND]]
+float16x8_t test_vrndq_f16(float16x8_t a) {
+ return vrndq_f16(a);
+}
+
+// CHECK-LABEL: test_vrnda_f16
+// CHECK: [[RND:%.*]] = call <4 x half> @llvm.arm.neon.vrinta.v4f16(<4 x half> %a)
+// CHECK: ret <4 x half> [[RND]]
+float16x4_t test_vrnda_f16(float16x4_t a) {
+ return vrnda_f16(a);
+}
+
+// CHECK-LABEL: test_vrndaq_f16
+// CHECK: [[RND:%.*]] = call <8 x half> @llvm.arm.neon.vrinta.v8f16(<8 x half> %a)
+// CHECK: ret <8 x half> [[RND]]
+float16x8_t test_vrndaq_f16(float16x8_t a) {
+ return vrndaq_f16(a);
+}
+
+// CHECK-LABEL: test_vrndm_f16
+// CHECK: [[RND:%.*]] = call <4 x half> @llvm.arm.neon.vrintm.v4f16(<4 x half> %a)
+// CHECK: ret <4 x half> [[RND]]
+float16x4_t test_vrndm_f16(float16x4_t a) {
+ return vrndm_f16(a);
+}
+
+// CHECK-LABEL: test_vrndmq_f16
+// CHECK: [[RND:%.*]] = call <8 x half> @llvm.arm.neon.vrintm.v8f16(<8 x half> %a)
+// CHECK: ret <8 x half> [[RND]]
+float16x8_t test_vrndmq_f16(float16x8_t a) {
+ return vrndmq_f16(a);
+}
+
+// CHECK-LABEL: test_vrndn_f16
+// CHECK: [[RND:%.*]] = call <4 x half> @llvm.arm.neon.vrintn.v4f16(<4 x half> %a)
+// CHECK: ret <4 x half> [[RND]]
+float16x4_t test_vrndn_f16(float16x4_t a) {
+ return vrndn_f16(a);
+}
+
+// CHECK-LABEL: test_vrndnq_f16
+// CHECK: [[RND:%.*]] = call <8 x half> @llvm.arm.neon.vrintn.v8f16(<8 x half> %a)
+// CHECK: ret <8 x half> [[RND]]
+float16x8_t test_vrndnq_f16(float16x8_t a) {
+ return vrndnq_f16(a);
+}
+
+// CHECK-LABEL: test_vrndp_f16
+// CHECK: [[RND:%.*]] = call <4 x half> @llvm.arm.neon.vrintp.v4f16(<4 x half> %a)
+// CHECK: ret <4 x half> [[RND]]
+float16x4_t test_vrndp_f16(float16x4_t a) {
+ return vrndp_f16(a);
+}
+
+// CHECK-LABEL: test_vrndpq_f16
+// CHECK: [[RND:%.*]] = call <8 x half> @llvm.arm.neon.vrintp.v8f16(<8 x half> %a)
+// CHECK: ret <8 x half> [[RND]]
+float16x8_t test_vrndpq_f16(float16x8_t a) {
+ return vrndpq_f16(a);
+}
+
+// CHECK-LABEL: test_vrndx_f16
+// CHECK: [[RND:%.*]] = call <4 x half> @llvm.arm.neon.vrintx.v4f16(<4 x half> %a)
+// CHECK: ret <4 x half> [[RND]]
+float16x4_t test_vrndx_f16(float16x4_t a) {
+ return vrndx_f16(a);
+}
+
+// CHECK-LABEL: test_vrndxq_f16
+// CHECK: [[RND:%.*]] = call <8 x half> @llvm.arm.neon.vrintx.v8f16(<8 x half> %a)
+// CHECK: ret <8 x half> [[RND]]
+float16x8_t test_vrndxq_f16(float16x8_t a) {
+ return vrndxq_f16(a);
+}
+
+// CHECK-LABEL: test_vrsqrte_f16
+// CHECK: [[RND:%.*]] = call <4 x half> @llvm.arm.neon.vrsqrte.v4f16(<4 x half> %a)
+// CHECK: ret <4 x half> [[RND]]
+float16x4_t test_vrsqrte_f16(float16x4_t a) {
+ return vrsqrte_f16(a);
+}
+
+// CHECK-LABEL: test_vrsqrteq_f16
+// CHECK: [[RND:%.*]] = call <8 x half> @llvm.arm.neon.vrsqrte.v8f16(<8 x half> %a)
+// CHECK: ret <8 x half> [[RND]]
+float16x8_t test_vrsqrteq_f16(float16x8_t a) {
+ return vrsqrteq_f16(a);
+}
+
+// CHECK-LABEL: test_vadd_f16
+// CHECK: [[ADD:%.*]] = fadd <4 x half> %a, %b
+// CHECK: ret <4 x half> [[ADD]]
+float16x4_t test_vadd_f16(float16x4_t a, float16x4_t b) {
+ return vadd_f16(a, b);
+}
+
+// CHECK-LABEL: test_vaddq_f16
+// CHECK: [[ADD:%.*]] = fadd <8 x half> %a, %b
+// CHECK: ret <8 x half> [[ADD]]
+float16x8_t test_vaddq_f16(float16x8_t a, float16x8_t b) {
+ return vaddq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vabd_f16
+// CHECK: [[ABD:%.*]] = call <4 x half> @llvm.arm.neon.vabds.v4f16(<4 x half> %a, <4 x half> %b)
+// CHECK: ret <4 x half> [[ABD]]
+float16x4_t test_vabd_f16(float16x4_t a, float16x4_t b) {
+ return vabd_f16(a, b);
+}
+
+// CHECK-LABEL: test_vabdq_f16
+// CHECK: [[ABD:%.*]] = call <8 x half> @llvm.arm.neon.vabds.v8f16(<8 x half> %a, <8 x half> %b)
+// CHECK: ret <8 x half> [[ABD]]
+float16x8_t test_vabdq_f16(float16x8_t a, float16x8_t b) {
+ return vabdq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcage_f16
+// CHECK: [[ABS:%.*]] = call <4 x i16> @llvm.arm.neon.vacge.v4i16.v4f16(<4 x half> %a, <4 x half> %b)
+// CHECK: ret <4 x i16> [[ABS]]
+uint16x4_t test_vcage_f16(float16x4_t a, float16x4_t b) {
+ return vcage_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcageq_f16
+// CHECK: [[ABS:%.*]] = call <8 x i16> @llvm.arm.neon.vacge.v8i16.v8f16(<8 x half> %a, <8 x half> %b)
+// CHECK: ret <8 x i16> [[ABS]]
+uint16x8_t test_vcageq_f16(float16x8_t a, float16x8_t b) {
+ return vcageq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcagt_f16
+// CHECK: [[ABS:%.*]] = call <4 x i16> @llvm.arm.neon.vacgt.v4i16.v4f16(<4 x half> %a, <4 x half> %b)
+// CHECK: ret <4 x i16> [[ABS]]
+uint16x4_t test_vcagt_f16(float16x4_t a, float16x4_t b) {
+ return vcagt_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcagtq_f16
+// CHECK: [[ABS:%.*]] = call <8 x i16> @llvm.arm.neon.vacgt.v8i16.v8f16(<8 x half> %a, <8 x half> %b)
+// CHECK: ret <8 x i16> [[ABS]]
+uint16x8_t test_vcagtq_f16(float16x8_t a, float16x8_t b) {
+ return vcagtq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcale_f16
+// CHECK: [[ABS:%.*]] = call <4 x i16> @llvm.arm.neon.vacge.v4i16.v4f16(<4 x half> %b, <4 x half> %a)
+// CHECK: ret <4 x i16> [[ABS]]
+uint16x4_t test_vcale_f16(float16x4_t a, float16x4_t b) {
+ return vcale_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcaleq_f16
+// CHECK: [[ABS:%.*]] = call <8 x i16> @llvm.arm.neon.vacge.v8i16.v8f16(<8 x half> %b, <8 x half> %a)
+// CHECK: ret <8 x i16> [[ABS]]
+uint16x8_t test_vcaleq_f16(float16x8_t a, float16x8_t b) {
+ return vcaleq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcalt_f16
+// CHECK: [[ABS:%.*]] = call <4 x i16> @llvm.arm.neon.vacgt.v4i16.v4f16(<4 x half> %b, <4 x half> %a)
+// CHECK: ret <4 x i16> [[ABS]]
+uint16x4_t test_vcalt_f16(float16x4_t a, float16x4_t b) {
+ return vcalt_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcaltq_f16
+// CHECK: [[ABS:%.*]] = call <8 x i16> @llvm.arm.neon.vacgt.v8i16.v8f16(<8 x half> %b, <8 x half> %a)
+// CHECK: ret <8 x i16> [[ABS]]
+uint16x8_t test_vcaltq_f16(float16x8_t a, float16x8_t b) {
+ return vcaltq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vceq_f16
+// CHECK: [[TMP1:%.*]] = fcmp oeq <4 x half> %a, %b
+// CHECK: [[TMP2:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i16>
+// CHECK: ret <4 x i16> [[TMP2]]
+uint16x4_t test_vceq_f16(float16x4_t a, float16x4_t b) {
+ return vceq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vceqq_f16
+// CHECK: [[TMP1:%.*]] = fcmp oeq <8 x half> %a, %b
+// CHECK: [[TMP2:%.*]] = sext <8 x i1> [[TMP1:%.*]] to <8 x i16>
+// CHECK: ret <8 x i16> [[TMP2]]
+uint16x8_t test_vceqq_f16(float16x8_t a, float16x8_t b) {
+ return vceqq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcge_f16
+// CHECK: [[TMP1:%.*]] = fcmp oge <4 x half> %a, %b
+// CHECK: [[TMP2:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i16>
+// CHECK: ret <4 x i16> [[TMP2]]
+uint16x4_t test_vcge_f16(float16x4_t a, float16x4_t b) {
+ return vcge_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcgeq_f16
+// CHECK: [[TMP1:%.*]] = fcmp oge <8 x half> %a, %b
+// CHECK: [[TMP2:%.*]] = sext <8 x i1> [[TMP1:%.*]] to <8 x i16>
+// CHECK: ret <8 x i16> [[TMP2]]
+uint16x8_t test_vcgeq_f16(float16x8_t a, float16x8_t b) {
+ return vcgeq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcgt_f16
+// CHECK: [[TMP1:%.*]] = fcmp ogt <4 x half> %a, %b
+// CHECK: [[TMP2:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i16>
+// CHECK: ret <4 x i16> [[TMP2]]
+uint16x4_t test_vcgt_f16(float16x4_t a, float16x4_t b) {
+ return vcgt_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcgtq_f16
+// CHECK: [[TMP1:%.*]] = fcmp ogt <8 x half> %a, %b
+// CHECK: [[TMP2:%.*]] = sext <8 x i1> [[TMP1:%.*]] to <8 x i16>
+// CHECK: ret <8 x i16> [[TMP2]]
+uint16x8_t test_vcgtq_f16(float16x8_t a, float16x8_t b) {
+ return vcgtq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcle_f16
+// CHECK: [[TMP1:%.*]] = fcmp ole <4 x half> %a, %b
+// CHECK: [[TMP2:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i16>
+// CHECK: ret <4 x i16> [[TMP2]]
+uint16x4_t test_vcle_f16(float16x4_t a, float16x4_t b) {
+ return vcle_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcleq_f16
+// CHECK: [[TMP1:%.*]] = fcmp ole <8 x half> %a, %b
+// CHECK: [[TMP2:%.*]] = sext <8 x i1> [[TMP1:%.*]] to <8 x i16>
+// CHECK: ret <8 x i16> [[TMP2]]
+uint16x8_t test_vcleq_f16(float16x8_t a, float16x8_t b) {
+ return vcleq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vclt_f16
+// CHECK: [[TMP1:%.*]] = fcmp olt <4 x half> %a, %b
+// CHECK: [[TMP2:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i16>
+// CHECK: ret <4 x i16> [[TMP2]]
+uint16x4_t test_vclt_f16(float16x4_t a, float16x4_t b) {
+ return vclt_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcltq_f16
+// CHECK: [[TMP1:%.*]] = fcmp olt <8 x half> %a, %b
+// CHECK: [[TMP2:%.*]] = sext <8 x i1> [[TMP1:%.*]] to <8 x i16>
+// CHECK: ret <8 x i16> [[TMP2]]
+uint16x8_t test_vcltq_f16(float16x8_t a, float16x8_t b) {
+ return vcltq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcvt_n_f16_s16
+// CHECK: [[CVT:%.*]] = call <4 x half> @llvm.arm.neon.vcvtfxs2fp.v4f16.v4i16(<4 x i16> %vcvt_n, i32 2)
+// CHECK: ret <4 x half> [[CVT]]
+float16x4_t test_vcvt_n_f16_s16(int16x4_t a) {
+ return vcvt_n_f16_s16(a, 2);
+}
+
+// CHECK-LABEL: test_vcvtq_n_f16_s16
+// CHECK: [[CVT:%.*]] = call <8 x half> @llvm.arm.neon.vcvtfxs2fp.v8f16.v8i16(<8 x i16> %vcvt_n, i32 2)
+// CHECK: ret <8 x half> [[CVT]]
+float16x8_t test_vcvtq_n_f16_s16(int16x8_t a) {
+ return vcvtq_n_f16_s16(a, 2);
+}
+
+// CHECK-LABEL: test_vcvt_n_f16_u16
+// CHECK: [[CVT:%.*]] = call <4 x half> @llvm.arm.neon.vcvtfxu2fp.v4f16.v4i16(<4 x i16> %vcvt_n, i32 2)
+// CHECK: ret <4 x half> [[CVT]]
+float16x4_t test_vcvt_n_f16_u16(uint16x4_t a) {
+ return vcvt_n_f16_u16(a, 2);
+}
+
+// CHECK-LABEL: test_vcvtq_n_f16_u16
+// CHECK: [[CVT:%.*]] = call <8 x half> @llvm.arm.neon.vcvtfxu2fp.v8f16.v8i16(<8 x i16> %vcvt_n, i32 2)
+// CHECK: ret <8 x half> [[CVT]]
+float16x8_t test_vcvtq_n_f16_u16(uint16x8_t a) {
+ return vcvtq_n_f16_u16(a, 2);
+}
+
+// CHECK-LABEL: test_vcvt_n_s16_f16
+// CHECK: [[CVT:%.*]] = call <4 x i16> @llvm.arm.neon.vcvtfp2fxs.v4i16.v4f16(<4 x half> %vcvt_n, i32 2)
+// CHECK: ret <4 x i16> [[CVT]]
+int16x4_t test_vcvt_n_s16_f16(float16x4_t a) {
+ return vcvt_n_s16_f16(a, 2);
+}
+
+// CHECK-LABEL: test_vcvtq_n_s16_f16
+// CHECK: [[CVT:%.*]] = call <8 x i16> @llvm.arm.neon.vcvtfp2fxs.v8i16.v8f16(<8 x half> %vcvt_n, i32 2)
+// CHECK: ret <8 x i16> [[CVT]]
+int16x8_t test_vcvtq_n_s16_f16(float16x8_t a) {
+ return vcvtq_n_s16_f16(a, 2);
+}
+
+// CHECK-LABEL: test_vcvt_n_u16_f16
+// CHECK: [[CVT:%.*]] = call <4 x i16> @llvm.arm.neon.vcvtfp2fxu.v4i16.v4f16(<4 x half> %vcvt_n, i32 2)
+// CHECK: ret <4 x i16> [[CVT]]
+uint16x4_t test_vcvt_n_u16_f16(float16x4_t a) {
+ return vcvt_n_u16_f16(a, 2);
+}
+
+// CHECK-LABEL: test_vcvtq_n_u16_f16
+// CHECK: [[CVT:%.*]] = call <8 x i16> @llvm.arm.neon.vcvtfp2fxu.v8i16.v8f16(<8 x half> %vcvt_n, i32 2)
+// CHECK: ret <8 x i16> [[CVT]]
+uint16x8_t test_vcvtq_n_u16_f16(float16x8_t a) {
+ return vcvtq_n_u16_f16(a, 2);
+}
+
+// CHECK-LABEL: test_vmax_f16
+// CHECK: [[MAX:%.*]] = call <4 x half> @llvm.arm.neon.vmaxs.v4f16(<4 x half> %a, <4 x half> %b)
+// CHECK: ret <4 x half> [[MAX]]
+float16x4_t test_vmax_f16(float16x4_t a, float16x4_t b) {
+ return vmax_f16(a, b);
+}
+
+// CHECK-LABEL: test_vmaxq_f16
+// CHECK: [[MAX:%.*]] = call <8 x half> @llvm.arm.neon.vmaxs.v8f16(<8 x half> %a, <8 x half> %b)
+// CHECK: ret <8 x half> [[MAX]]
+float16x8_t test_vmaxq_f16(float16x8_t a, float16x8_t b) {
+ return vmaxq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vmaxnm_f16
+// CHECK: [[MAX:%.*]] = call <4 x half> @llvm.arm.neon.vmaxnm.v4f16(<4 x half> %a, <4 x half> %b)
+// CHECK: ret <4 x half> [[MAX]]
+float16x4_t test_vmaxnm_f16(float16x4_t a, float16x4_t b) {
+ return vmaxnm_f16(a, b);
+}
+
+// CHECK-LABEL: test_vmaxnmq_f16
+// CHECK: [[MAX:%.*]] = call <8 x half> @llvm.arm.neon.vmaxnm.v8f16(<8 x half> %a, <8 x half> %b)
+// CHECK: ret <8 x half> [[MAX]]
+float16x8_t test_vmaxnmq_f16(float16x8_t a, float16x8_t b) {
+ return vmaxnmq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vmin_f16
+// CHECK: [[MIN:%.*]] = call <4 x half> @llvm.arm.neon.vmins.v4f16(<4 x half> %a, <4 x half> %b)
+// CHECK: ret <4 x half> [[MIN]]
+float16x4_t test_vmin_f16(float16x4_t a, float16x4_t b) {
+ return vmin_f16(a, b);
+}
+
+// CHECK-LABEL: test_vminq_f16
+// CHECK: [[MIN:%.*]] = call <8 x half> @llvm.arm.neon.vmins.v8f16(<8 x half> %a, <8 x half> %b)
+// CHECK: ret <8 x half> [[MIN]]
+float16x8_t test_vminq_f16(float16x8_t a, float16x8_t b) {
+ return vminq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vminnm_f16
+// CHECK: [[MIN:%.*]] = call <4 x half> @llvm.arm.neon.vminnm.v4f16(<4 x half> %a, <4 x half> %b)
+// CHECK: ret <4 x half> [[MIN]]
+float16x4_t test_vminnm_f16(float16x4_t a, float16x4_t b) {
+ return vminnm_f16(a, b);
+}
+
+// CHECK-LABEL: test_vminnmq_f16
+// CHECK: [[MIN:%.*]] = call <8 x half> @llvm.arm.neon.vminnm.v8f16(<8 x half> %a, <8 x half> %b)
+// CHECK: ret <8 x half> [[MIN]]
+float16x8_t test_vminnmq_f16(float16x8_t a, float16x8_t b) {
+ return vminnmq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vmul_f16
+// CHECK: [[MUL:%.*]] = fmul <4 x half> %a, %b
+// CHECK: ret <4 x half> [[MUL]]
+float16x4_t test_vmul_f16(float16x4_t a, float16x4_t b) {
+ return vmul_f16(a, b);
+}
+
+// CHECK-LABEL: test_vmulq_f16
+// CHECK: [[MUL:%.*]] = fmul <8 x half> %a, %b
+// CHECK: ret <8 x half> [[MUL]]
+float16x8_t test_vmulq_f16(float16x8_t a, float16x8_t b) {
+ return vmulq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vpadd_f16
+// CHECK: [[ADD:%.*]] = call <4 x half> @llvm.arm.neon.vpadd.v4f16(<4 x half> %a, <4 x half> %b)
+// CHECK: ret <4 x half> [[ADD]]
+float16x4_t test_vpadd_f16(float16x4_t a, float16x4_t b) {
+ return vpadd_f16(a, b);
+}
+
+// CHECK-LABEL: test_vpmax_f16
+// CHECK: [[MAX:%.*]] = call <4 x half> @llvm.arm.neon.vpmaxs.v4f16(<4 x half> %a, <4 x half> %b)
+// CHECK: ret <4 x half> [[MAX]]
+float16x4_t test_vpmax_f16(float16x4_t a, float16x4_t b) {
+ return vpmax_f16(a, b);
+}
+
+// CHECK-LABEL: test_vpmin_f16
+// CHECK: [[MIN:%.*]] = call <4 x half> @llvm.arm.neon.vpmins.v4f16(<4 x half> %a, <4 x half> %b)
+// CHECK: ret <4 x half> [[MIN]]
+float16x4_t test_vpmin_f16(float16x4_t a, float16x4_t b) {
+ return vpmin_f16(a, b);
+}
+
+// CHECK-LABEL: test_vrecps_f16
+// CHECK: [[MIN:%.*]] = call <4 x half> @llvm.arm.neon.vrecps.v4f16(<4 x half> %a, <4 x half> %b)
+// CHECK: ret <4 x half> [[MIN]]
+float16x4_t test_vrecps_f16(float16x4_t a, float16x4_t b) {
+ return vrecps_f16(a, b);
+}
+
+// CHECK-LABEL: test_vrecpsq_f16
+// CHECK: [[MIN:%.*]] = call <8 x half> @llvm.arm.neon.vrecps.v8f16(<8 x half> %a, <8 x half> %b)
+// CHECK: ret <8 x half> [[MIN]]
+float16x8_t test_vrecpsq_f16(float16x8_t a, float16x8_t b) {
+ return vrecpsq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vrsqrts_f16
+// CHECK: [[MIN:%.*]] = call <4 x half> @llvm.arm.neon.vrsqrts.v4f16(<4 x half> %a, <4 x half> %b)
+// CHECK: ret <4 x half> [[MIN]]
+float16x4_t test_vrsqrts_f16(float16x4_t a, float16x4_t b) {
+ return vrsqrts_f16(a, b);
+}
+
+// CHECK-LABEL: test_vrsqrtsq_f16
+// CHECK: [[MIN:%.*]] = call <8 x half> @llvm.arm.neon.vrsqrts.v8f16(<8 x half> %a, <8 x half> %b)
+// CHECK: ret <8 x half> [[MIN]]
+float16x8_t test_vrsqrtsq_f16(float16x8_t a, float16x8_t b) {
+ return vrsqrtsq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vsub_f16
+// CHECK: [[ADD:%.*]] = fsub <4 x half> %a, %b
+// CHECK: ret <4 x half> [[ADD]]
+float16x4_t test_vsub_f16(float16x4_t a, float16x4_t b) {
+ return vsub_f16(a, b);
+}
+
+// CHECK-LABEL: test_vsubq_f16
+// CHECK: [[ADD:%.*]] = fsub <8 x half> %a, %b
+// CHECK: ret <8 x half> [[ADD]]
+float16x8_t test_vsubq_f16(float16x8_t a, float16x8_t b) {
+ return vsubq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vfma_f16
+// CHECK: [[ADD:%.*]] = call <4 x half> @llvm.fma.v4f16(<4 x half> %b, <4 x half> %c, <4 x half> %a)
+// CHECK: ret <4 x half> [[ADD]]
+float16x4_t test_vfma_f16(float16x4_t a, float16x4_t b, float16x4_t c) {
+ return vfma_f16(a, b, c);
+}
+
+// CHECK-LABEL: test_vfmaq_f16
+// CHECK: [[ADD:%.*]] = call <8 x half> @llvm.fma.v8f16(<8 x half> %b, <8 x half> %c, <8 x half> %a)
+// CHECK: ret <8 x half> [[ADD]]
+float16x8_t test_vfmaq_f16(float16x8_t a, float16x8_t b, float16x8_t c) {
+ return vfmaq_f16(a, b, c);
+}
+
+// CHECK-LABEL: test_vfms_f16
+// CHECK: [[SUB:%.*]] = fsub <4 x half> <half 0xH8000, half 0xH8000, half 0xH8000, half 0xH8000>, %b
+// CHECK: [[ADD:%.*]] = call <4 x half> @llvm.fma.v4f16(<4 x half> [[SUB]], <4 x half> %c, <4 x half> %a)
+// CHECK: ret <4 x half> [[ADD]]
+float16x4_t test_vfms_f16(float16x4_t a, float16x4_t b, float16x4_t c) {
+ return vfms_f16(a, b, c);
+}
+
+// CHECK-LABEL: test_vfmsq_f16
+// CHECK: [[SUB:%.*]] = fsub <8 x half> <half 0xH8000, half 0xH8000, half 0xH8000, half 0xH8000, half 0xH8000, half 0xH8000, half 0xH8000, half 0xH8000>, %b
+// CHECK: [[ADD:%.*]] = call <8 x half> @llvm.fma.v8f16(<8 x half> [[SUB]], <8 x half> %c, <8 x half> %a)
+// CHECK: ret <8 x half> [[ADD]]
+float16x8_t test_vfmsq_f16(float16x8_t a, float16x8_t b, float16x8_t c) {
+ return vfmsq_f16(a, b, c);
+}
+
+// CHECK-LABEL: test_vmul_lane_f16
+// CHECK: [[TMP0:%.*]] = shufflevector <4 x half> %b, <4 x half> %b, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
+// CHECK: [[MUL:%.*]] = fmul <4 x half> %a, [[TMP0]]
+// CHECK: ret <4 x half> [[MUL]]
+float16x4_t test_vmul_lane_f16(float16x4_t a, float16x4_t b) {
+ return vmul_lane_f16(a, b, 3);
+}
+
+// CHECK-LABEL: test_vmulq_lane_f16
+// CHECK: [[TMP0:%.*]] = shufflevector <4 x half> %b, <4 x half> %b, <8 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>
+// CHECK: [[MUL:%.*]] = fmul <8 x half> %a, [[TMP0]]
+// CHECK: ret <8 x half> [[MUL]]
+float16x8_t test_vmulq_lane_f16(float16x8_t a, float16x4_t b) {
+ return vmulq_lane_f16(a, b, 7);
+}
+
+// CHECK-LABEL: test_vmul_n_f16
+// CHECK: [[TMP0:%.*]] = insertelement <4 x half> undef, half [[b:%.*]], i32 0
+// CHECK: [[TMP1:%.*]] = insertelement <4 x half> [[TMP0]], half [[b]], i32 1
+// CHECK: [[TMP2:%.*]] = insertelement <4 x half> [[TMP1]], half [[b]], i32 2
+// CHECK: [[TMP3:%.*]] = insertelement <4 x half> [[TMP2]], half [[b]], i32 3
+// CHECK: [[MUL:%.*]] = fmul <4 x half> %a, [[TMP3]]
+// CHECK: ret <4 x half> [[MUL]]
+float16x4_t test_vmul_n_f16(float16x4_t a, float16_t b) {
+ return vmul_n_f16(a, b);
+}
+
+// CHECK-LABEL: test_vmulq_n_f16
+// CHECK: [[TMP0:%.*]] = insertelement <8 x half> undef, half [[b:%.*]], i32 0
+// CHECK: [[TMP1:%.*]] = insertelement <8 x half> [[TMP0]], half [[b]], i32 1
+// CHECK: [[TMP2:%.*]] = insertelement <8 x half> [[TMP1]], half [[b]], i32 2
+// CHECK: [[TMP3:%.*]] = insertelement <8 x half> [[TMP2]], half [[b]], i32 3
+// CHECK: [[TMP4:%.*]] = insertelement <8 x half> [[TMP3]], half [[b]], i32 4
+// CHECK: [[TMP5:%.*]] = insertelement <8 x half> [[TMP4]], half [[b]], i32 5
+// CHECK: [[TMP6:%.*]] = insertelement <8 x half> [[TMP5]], half [[b]], i32 6
+// CHECK: [[TMP7:%.*]] = insertelement <8 x half> [[TMP6]], half [[b]], i32 7
+// CHECK: [[MUL:%.*]] = fmul <8 x half> %a, [[TMP7]]
+// CHECK: ret <8 x half> [[MUL]]
+float16x8_t test_vmulq_n_f16(float16x8_t a, float16_t b) {
+ return vmulq_n_f16(a, b);
+}
+
+// CHECK-LABEL: test_vbsl_f16
+// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
+// CHECK: [[TMP1:%.*]] = bitcast <4 x half> %b to <8 x i8>
+// CHECK: [[TMP2:%.*]] = bitcast <4 x half> %c to <8 x i8>
+// CHECK: [[VBSL:%.*]] = call <8 x i8> @llvm.arm.neon.vbsl.v8i8(<8 x i8> [[TMP0]], <8 x i8> [[TMP1]], <8 x i8> [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[VBSL]] to <4 x half>
+// CHECK: ret <4 x half> [[TMP3]]
+float16x4_t test_vbsl_f16(uint16x4_t a, float16x4_t b, float16x4_t c) {
+ return vbsl_f16(a, b, c);
+}
+
+// CHECK-LABEL: test_vbslq_f16
+// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
+// CHECK: [[TMP1:%.*]] = bitcast <8 x half> %b to <16 x i8>
+// CHECK: [[TMP2:%.*]] = bitcast <8 x half> %c to <16 x i8>
+// CHECK: [[VBSL:%.*]] = call <16 x i8> @llvm.arm.neon.vbsl.v16i8(<16 x i8> [[TMP0]], <16 x i8> [[TMP1]], <16 x i8> [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[VBSL]] to <8 x half>
+// CHECK: ret <8 x half> [[TMP3]]
+float16x8_t test_vbslq_f16(uint16x8_t a, float16x8_t b, float16x8_t c) {
+ return vbslq_f16(a, b, c);
+}
+
+// CHECK-LABEL: test_vzip_f16
+// CHECK: [[VZIP0:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 0, i32 4, i32 1, i32 5>
+// CHECK: store <4 x half> [[VZIP0]], <4 x half>* [[addr1:%.*]]
+// CHECK: [[VZIP1:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
+// CHECK: store <4 x half> [[VZIP1]], <4 x half>* [[addr2:%.*]]
+float16x4x2_t test_vzip_f16(float16x4_t a, float16x4_t b) {
+ return vzip_f16(a, b);
+}
+
+// CHECK-LABEL: test_vzipq_f16
+// CHECK: [[VZIP0:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
+// CHECK: store <8 x half> [[VZIP0]], <8 x half>* [[addr1:%.*]]
+// CHECK: [[VZIP1:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
+// CHECK: store <8 x half> [[VZIP1]], <8 x half>* [[addr2:%.*]]
+float16x8x2_t test_vzipq_f16(float16x8_t a, float16x8_t b) {
+ return vzipq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vuzp_f16
+// CHECK: [[VUZP0:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
+// CHECK: store <4 x half> [[VUZP0]], <4 x half>* [[addr1:%.*]]
+// CHECK: [[VUZP1:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
+// CHECK: store <4 x half> [[VUZP1]], <4 x half>* [[addr1:%.*]]
+float16x4x2_t test_vuzp_f16(float16x4_t a, float16x4_t b) {
+ return vuzp_f16(a, b);
+}
+
+// CHECK-LABEL: test_vuzpq_f16
+// CHECK: [[VUZP0:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
+// CHECK: store <8 x half> [[VUZP0]], <8 x half>* [[addr1:%.*]]
+// CHECK: [[VUZP1:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
+// CHECK: store <8 x half> [[VUZP1]], <8 x half>* [[addr2:%.*]]
+float16x8x2_t test_vuzpq_f16(float16x8_t a, float16x8_t b) {
+ return vuzpq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vtrn_f16
+// CHECK: [[VTRN0:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 0, i32 4, i32 2, i32 6>
+// CHECK: store <4 x half> [[VTRN0]], <4 x half>* [[addr1:%.*]]
+// CHECK: [[VTRN1:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
+// CHECK: store <4 x half> [[VTRN1]], <4 x half>* [[addr2:%.*]]
+float16x4x2_t test_vtrn_f16(float16x4_t a, float16x4_t b) {
+ return vtrn_f16(a, b);
+}
+
+// CHECK-LABEL: test_vtrnq_f16
+// CHECK: [[VTRN0:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14>
+// CHECK: store <8 x half> [[VTRN0]], <8 x half>* [[addr1:%.*]]
+// CHECK: [[VTRN1:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
+// CHECK: store <8 x half> [[VTRN1]], <8 x half>* [[addr2:%.*]]
+float16x8x2_t test_vtrnq_f16(float16x8_t a, float16x8_t b) {
+ return vtrnq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vmov_n_f16
+// CHECK: [[TMP0:%.*]] = insertelement <4 x half> undef, half [[ARG:%.*]], i32 0
+// CHECK: [[TMP1:%.*]] = insertelement <4 x half> [[TMP0]], half [[ARG]], i32 1
+// CHECK: [[TMP2:%.*]] = insertelement <4 x half> [[TMP1]], half [[ARG]], i32 2
+// CHECK: [[TMP3:%.*]] = insertelement <4 x half> [[TMP2]], half [[ARG]], i32 3
+// CHECK: ret <4 x half> [[TMP3]]
+float16x4_t test_vmov_n_f16(float16_t a) {
+ return vmov_n_f16(a);
+}
+
+// CHECK-LABEL: test_vmovq_n_f16
+// CHECK: [[TMP0:%.*]] = insertelement <8 x half> undef, half [[ARG:%.*]], i32 0
+// CHECK: [[TMP1:%.*]] = insertelement <8 x half> [[TMP0]], half [[ARG]], i32 1
+// CHECK: [[TMP2:%.*]] = insertelement <8 x half> [[TMP1]], half [[ARG]], i32 2
+// CHECK: [[TMP3:%.*]] = insertelement <8 x half> [[TMP2]], half [[ARG]], i32 3
+// CHECK: [[TMP4:%.*]] = insertelement <8 x half> [[TMP3]], half [[ARG]], i32 4
+// CHECK: [[TMP5:%.*]] = insertelement <8 x half> [[TMP4]], half [[ARG]], i32 5
+// CHECK: [[TMP6:%.*]] = insertelement <8 x half> [[TMP5]], half [[ARG]], i32 6
+// CHECK: [[TMP7:%.*]] = insertelement <8 x half> [[TMP6]], half [[ARG]], i32 7
+// CHECK: ret <8 x half> [[TMP7]]
+float16x8_t test_vmovq_n_f16(float16_t a) {
+ return vmovq_n_f16(a);
+}
+
+// CHECK-LABEL: test_vdup_n_f16
+// CHECK: [[TMP0:%.*]] = insertelement <4 x half> undef, half [[ARG:%.*]], i32 0
+// CHECK: [[TMP1:%.*]] = insertelement <4 x half> [[TMP0]], half [[ARG]], i32 1
+// CHECK: [[TMP2:%.*]] = insertelement <4 x half> [[TMP1]], half [[ARG]], i32 2
+// CHECK: [[TMP3:%.*]] = insertelement <4 x half> [[TMP2]], half [[ARG]], i32 3
+// CHECK: ret <4 x half> [[TMP3]]
+float16x4_t test_vdup_n_f16(float16_t a) {
+ return vdup_n_f16(a);
+}
+
+// CHECK-LABEL: test_vdupq_n_f16
+// CHECK: [[TMP0:%.*]] = insertelement <8 x half> undef, half [[ARG:%.*]], i32 0
+// CHECK: [[TMP1:%.*]] = insertelement <8 x half> [[TMP0]], half [[ARG]], i32 1
+// CHECK: [[TMP2:%.*]] = insertelement <8 x half> [[TMP1]], half [[ARG]], i32 2
+// CHECK: [[TMP3:%.*]] = insertelement <8 x half> [[TMP2]], half [[ARG]], i32 3
+// CHECK: [[TMP4:%.*]] = insertelement <8 x half> [[TMP3]], half [[ARG]], i32 4
+// CHECK: [[TMP5:%.*]] = insertelement <8 x half> [[TMP4]], half [[ARG]], i32 5
+// CHECK: [[TMP6:%.*]] = insertelement <8 x half> [[TMP5]], half [[ARG]], i32 6
+// CHECK: [[TMP7:%.*]] = insertelement <8 x half> [[TMP6]], half [[ARG]], i32 7
+// CHECK: ret <8 x half> [[TMP7]]
+float16x8_t test_vdupq_n_f16(float16_t a) {
+ return vdupq_n_f16(a);
+}
+
+// CHECK-LABEL: test_vdup_lane_f16
+// CHECK: [[SHFL:%.*]] = shufflevector <4 x half> %a, <4 x half> %a, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
+// CHECK: ret <4 x half> [[SHFL]]
+float16x4_t test_vdup_lane_f16(float16x4_t a) {
+ return vdup_lane_f16(a, 3);
+}
+
+// CHECK-LABEL: test_vdupq_lane_f16
+// CHECK: [[SHFL:%.*]] = shufflevector <4 x half> %a, <4 x half> %a, <8 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>
+// CHECK: ret <8 x half> [[SHFL]]
+float16x8_t test_vdupq_lane_f16(float16x4_t a) {
+ return vdupq_lane_f16(a, 7);
+}
+
+// CHECK-LABEL: @test_vext_f16(
+// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <8 x i8>
+// CHECK: [[TMP1:%.*]] = bitcast <4 x half> %b to <8 x i8>
+// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x half>
+// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x half>
+// CHECK: [[VEXT:%.*]] = shufflevector <4 x half> [[TMP2]], <4 x half> [[TMP3]], <4 x i32> <i32 2, i32 3, i32 4, i32 5>
+// CHECK: ret <4 x half> [[VEXT]]
+float16x4_t test_vext_f16(float16x4_t a, float16x4_t b) {
+ return vext_f16(a, b, 2);
+}
+
+// CHECK-LABEL: @test_vextq_f16(
+// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %a to <16 x i8>
+// CHECK: [[TMP1:%.*]] = bitcast <8 x half> %b to <16 x i8>
+// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x half>
+// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x half>
+// CHECK: [[VEXT:%.*]] = shufflevector <8 x half> [[TMP2]], <8 x half> [[TMP3]], <8 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12>
+// CHECK: ret <8 x half> [[VEXT]]
+float16x8_t test_vextq_f16(float16x8_t a, float16x8_t b) {
+ return vextq_f16(a, b, 5);
+}
+
+// CHECK-LABEL: @test_vrev64_f16(
+// CHECK: [[SHFL:%.*]] = shufflevector <4 x half> %a, <4 x half> %a, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+// CHECK: ret <4 x half> [[SHFL]]
+float16x4_t test_vrev64_f16(float16x4_t a) {
+ return vrev64_f16(a);
+}
+
+// CHECK-LABEL: @test_vrev64q_f16(
+// CHECK: [[SHFL:%.*]] = shufflevector <8 x half> %a, <8 x half> %a, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
+// CHECK: ret <8 x half> [[SHFL]]
+float16x8_t test_vrev64q_f16(float16x8_t a) {
+ return vrev64q_f16(a);
+}
diff --git a/test/CodeGen/arm64-be-bitfield.c b/test/CodeGen/arm64-be-bitfield.c
index 081eab81e905..cee59b87099f 100644
--- a/test/CodeGen/arm64-be-bitfield.c
+++ b/test/CodeGen/arm64-be-bitfield.c
@@ -7,6 +7,6 @@ signed callee_b0f(struct bt3 bp11) {
// IR: callee_b0f(i64 [[ARG:%.*]])
// IR: store i64 [[ARG]], i64* [[PTR:%.*]], align 8
// IR: [[BITCAST:%.*]] = bitcast i64* [[PTR]] to i8*
-// IR: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* [[BITCAST]], i64 4
+// IR: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* align 8 [[BITCAST]], i64 4
return bp11.b2;
}
diff --git a/test/CodeGen/arm64-microsoft-arguments.cpp b/test/CodeGen/arm64-microsoft-arguments.cpp
new file mode 100644
index 000000000000..3ef468880ad7
--- /dev/null
+++ b/test/CodeGen/arm64-microsoft-arguments.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -triple aarch64-windows -ffreestanding -emit-llvm -O0 \
+// RUN: -x c++ -o - %s | FileCheck %s
+
+struct pod { int a, b, c, d, e; };
+
+struct non_pod {
+ int a;
+ non_pod() {}
+};
+
+struct pod s;
+struct non_pod t;
+
+struct pod bar() { return s; }
+struct non_pod foo() { return t; }
+// CHECK: define {{.*}} void @{{.*}}bar{{.*}}(%struct.pod* noalias sret %agg.result)
+// CHECK: define {{.*}} void @{{.*}}foo{{.*}}(%struct.non_pod* noalias %agg.result)
+
+
+// Check instance methods.
+struct pod2 { int x; };
+struct Baz { pod2 baz(); };
+
+int qux() { return Baz().baz().x; }
+// CHECK: declare {{.*}} void @{{.*}}baz@Baz{{.*}}(%struct.Baz*, %struct.pod2*)
diff --git a/test/CodeGen/arm64-microsoft-intrinsics.c b/test/CodeGen/arm64-microsoft-intrinsics.c
index ff802e7f9b85..2dbf1f9ea0f4 100644
--- a/test/CodeGen/arm64-microsoft-intrinsics.c
+++ b/test/CodeGen/arm64-microsoft-intrinsics.c
@@ -24,3 +24,38 @@ void check__isb(void) {
// CHECK-MSVC: @llvm.aarch64.isb(i32 0)
// CHECK-LINUX: error: implicit declaration of function '__isb'
+
+void check__yield(void) {
+ __yield();
+}
+
+// CHECK-MSVC: @llvm.aarch64.hint(i32 1)
+// CHECK-LINUX: error: implicit declaration of function '__yield'
+
+void check__wfe(void) {
+ __wfe();
+}
+
+// CHECK-MSVC: @llvm.aarch64.hint(i32 2)
+// CHECK-LINUX: error: implicit declaration of function '__wfe'
+
+void check__wfi(void) {
+ __wfi();
+}
+
+// CHECK-MSVC: @llvm.aarch64.hint(i32 3)
+// CHECK-LINUX: error: implicit declaration of function '__wfi'
+
+void check__sev(void) {
+ __sev();
+}
+
+// CHECK-MSVC: @llvm.aarch64.hint(i32 4)
+// CHECK-LINUX: error: implicit declaration of function '__sev'
+
+void check__sevl(void) {
+ __sevl();
+}
+
+// CHECK-MSVC: @llvm.aarch64.hint(i32 5)
+// CHECK-LINUX: error: implicit declaration of function '__sevl'
diff --git a/test/CodeGen/arm64-vrnd.c b/test/CodeGen/arm64-vrnd.c
index 2c1bb8f46a10..7729c094a20c 100644
--- a/test/CodeGen/arm64-vrnd.c
+++ b/test/CodeGen/arm64-vrnd.c
@@ -2,50 +2,21 @@
#include <arm_neon.h>
-int32x2_t rnd1(float32x2_t a) { return vrnd_f32(a); }
-// CHECK: call <2 x float> @llvm.trunc.v2f32(<2 x float>
-int32x4_t rnd3(float32x4_t a) { return vrndq_f32(a); }
-// CHECK: call <4 x float> @llvm.trunc.v4f32(<4 x float>
int64x2_t rnd5(float64x2_t a) { return vrndq_f64(a); }
// CHECK: call <2 x double> @llvm.trunc.v2f64(<2 x double>
-
-int32x2_t rnd7(float32x2_t a) { return vrndn_f32(a); }
-// CHECK: call <2 x float> @llvm.aarch64.neon.frintn.v2f32(<2 x float>
-int32x4_t rnd8(float32x4_t a) { return vrndnq_f32(a); }
-// CHECK: call <4 x float> @llvm.aarch64.neon.frintn.v4f32(<4 x float>
int64x2_t rnd9(float64x2_t a) { return vrndnq_f64(a); }
// CHECK: call <2 x double> @llvm.aarch64.neon.frintn.v2f64(<2 x double>
-int64x2_t rnd10(float64x2_t a) { return vrndnq_f64(a); }
-// CHECK: call <2 x double> @llvm.aarch64.neon.frintn.v2f64(<2 x double>
-int32x2_t rnd11(float32x2_t a) { return vrndm_f32(a); }
-// CHECK: call <2 x float> @llvm.floor.v2f32(<2 x float>
-int32x4_t rnd12(float32x4_t a) { return vrndmq_f32(a); }
-// CHECK: call <4 x float> @llvm.floor.v4f32(<4 x float>
int64x2_t rnd13(float64x2_t a) { return vrndmq_f64(a); }
// CHECK: call <2 x double> @llvm.floor.v2f64(<2 x double>
-int64x2_t rnd14(float64x2_t a) { return vrndmq_f64(a); }
-// CHECK: call <2 x double> @llvm.floor.v2f64(<2 x double>
-int32x2_t rnd15(float32x2_t a) { return vrndp_f32(a); }
-// CHECK: call <2 x float> @llvm.ceil.v2f32(<2 x float>
-int32x4_t rnd16(float32x4_t a) { return vrndpq_f32(a); }
-// CHECK: call <4 x float> @llvm.ceil.v4f32(<4 x float>
int64x2_t rnd18(float64x2_t a) { return vrndpq_f64(a); }
// CHECK: call <2 x double> @llvm.ceil.v2f64(<2 x double>
-int32x2_t rnd19(float32x2_t a) { return vrnda_f32(a); }
-// CHECK: call <2 x float> @llvm.round.v2f32(<2 x float>
-int32x4_t rnd20(float32x4_t a) { return vrndaq_f32(a); }
-// CHECK: call <4 x float> @llvm.round.v4f32(<4 x float>
int64x2_t rnd22(float64x2_t a) { return vrndaq_f64(a); }
// CHECK: call <2 x double> @llvm.round.v2f64(<2 x double>
-int32x2_t rnd23(float32x2_t a) { return vrndx_f32(a); }
-// CHECK: call <2 x float> @llvm.rint.v2f32(<2 x float>
-int32x4_t rnd24(float32x4_t a) { return vrndxq_f32(a); }
-// CHECK: call <4 x float> @llvm.rint.v4f32(<4 x float>
int64x2_t rnd25(float64x2_t a) { return vrndxq_f64(a); }
// CHECK: call <2 x double> @llvm.rint.v2f64(<2 x double>
diff --git a/test/CodeGen/arm64_vdup.c b/test/CodeGen/arm64_vdup.c
index 8419828b38d2..67eb8553638a 100644
--- a/test/CodeGen/arm64_vdup.c
+++ b/test/CodeGen/arm64_vdup.c
@@ -30,7 +30,7 @@ float16x8_t test_vdupq_n_f16(float16_t *a1) {
// CHECK-LABEL: test_vdupq_n_f16
return vdupq_n_f16(*a1);
// match that an element is inserted into parts 0-7. The backend better
- // turn that into a single dup intruction
+ // turn that into a single dup instruction
// CHECK: insertelement {{.*, i32 0 *$}}
// CHECK: insertelement {{.*, i32 1 *$}}
// CHECK: insertelement {{.*, i32 2 *$}}
diff --git a/test/CodeGen/arm_neon_intrinsics.c b/test/CodeGen/arm_neon_intrinsics.c
index 62888dd73339..f6305062e8fd 100644
--- a/test/CodeGen/arm_neon_intrinsics.c
+++ b/test/CodeGen/arm_neon_intrinsics.c
@@ -4732,111 +4732,6 @@ poly16x4x2_t test_vld2_p16(poly16_t const * a) {
return vld2_p16(a);
}
-// CHECK-LABEL: @test_vld2_dup_u8(
-// CHECK: [[__RET:%.*]] = alloca %struct.uint8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET]] to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <8 x i8>, <8 x i8>
-uint8x8x2_t test_vld2_dup_u8(uint8_t const * a) {
- return vld2_dup_u8(a);
-}
-
-// CHECK-LABEL: @test_vld2_dup_u16(
-// CHECK: [[__RET:%.*]] = alloca %struct.uint16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <4 x i16>, <4 x i16>
-uint16x4x2_t test_vld2_dup_u16(uint16_t const * a) {
- return vld2_dup_u16(a);
-}
-
-// CHECK-LABEL: @test_vld2_dup_u32(
-// CHECK: [[__RET:%.*]] = alloca %struct.uint32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <2 x i32>, <2 x i32>
-uint32x2x2_t test_vld2_dup_u32(uint32_t const * a) {
- return vld2_dup_u32(a);
-}
-
-// CHECK-LABEL: @test_vld2_dup_u64(
-// CHECK: [[__RET:%.*]] = alloca %struct.uint64x1x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <1 x i64>, <1 x i64>
-uint64x1x2_t test_vld2_dup_u64(uint64_t const * a) {
- return vld2_dup_u64(a);
-}
-
-// CHECK-LABEL: @test_vld2_dup_s8(
-// CHECK: [[__RET:%.*]] = alloca %struct.int8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[__RET]] to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <8 x i8>, <8 x i8>
-int8x8x2_t test_vld2_dup_s8(int8_t const * a) {
- return vld2_dup_s8(a);
-}
-
-// CHECK-LABEL: @test_vld2_dup_s16(
-// CHECK: [[__RET:%.*]] = alloca %struct.int16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <4 x i16>, <4 x i16>
-int16x4x2_t test_vld2_dup_s16(int16_t const * a) {
- return vld2_dup_s16(a);
-}
-
-// CHECK-LABEL: @test_vld2_dup_s32(
-// CHECK: [[__RET:%.*]] = alloca %struct.int32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <2 x i32>, <2 x i32>
-int32x2x2_t test_vld2_dup_s32(int32_t const * a) {
- return vld2_dup_s32(a);
-}
-
-// CHECK-LABEL: @test_vld2_dup_s64(
-// CHECK: [[__RET:%.*]] = alloca %struct.int64x1x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <1 x i64>, <1 x i64>
-int64x1x2_t test_vld2_dup_s64(int64_t const * a) {
- return vld2_dup_s64(a);
-}
-
-// CHECK-LABEL: @test_vld2_dup_f16(
-// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <4 x i16>, <4 x i16>
-float16x4x2_t test_vld2_dup_f16(float16_t const * a) {
- return vld2_dup_f16(a);
-}
-
-// CHECK-LABEL: @test_vld2_dup_f32(
-// CHECK: [[__RET:%.*]] = alloca %struct.float32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast float* %a to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <2 x float>, <2 x float>
-float32x2x2_t test_vld2_dup_f32(float32_t const * a) {
- return vld2_dup_f32(a);
-}
-
-// CHECK-LABEL: @test_vld2_dup_p8(
-// CHECK: [[__RET:%.*]] = alloca %struct.poly8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET]] to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <8 x i8>, <8 x i8>
-poly8x8x2_t test_vld2_dup_p8(poly8_t const * a) {
- return vld2_dup_p8(a);
-}
-
-// CHECK-LABEL: @test_vld2_dup_p16(
-// CHECK: [[__RET:%.*]] = alloca %struct.poly16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <4 x i16>, <4 x i16>
-poly16x4x2_t test_vld2_dup_p16(poly16_t const * a) {
- return vld2_dup_p16(a);
-}
-
// CHECK-LABEL: @test_vld2q_lane_u16(
// CHECK: [[B:%.*]] = alloca %struct.uint16x8x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x2_t, align 16
@@ -4846,7 +4741,7 @@ poly16x4x2_t test_vld2_dup_p16(poly16_t const * a) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint16x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[__S1]], i32 0, i32 0
@@ -4873,7 +4768,7 @@ uint16x8x2_t test_vld2q_lane_u16(uint16_t const * a, uint16x8x2_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint32x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[__S1]], i32 0, i32 0
@@ -4900,7 +4795,7 @@ uint32x4x2_t test_vld2q_lane_u32(uint32_t const * a, uint32x4x2_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int16x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.int16x8x2_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[__S1]], i32 0, i32 0
@@ -4927,7 +4822,7 @@ int16x8x2_t test_vld2q_lane_s16(int16_t const * a, int16x8x2_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int32x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.int32x4x2_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[__S1]], i32 0, i32 0
@@ -4954,7 +4849,7 @@ int32x4x2_t test_vld2q_lane_s32(int32_t const * a, int32x4x2_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float16x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.float16x8x2_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x2_t, %struct.float16x8x2_t* [[__S1]], i32 0, i32 0
@@ -4981,7 +4876,7 @@ float16x8x2_t test_vld2q_lane_f16(float16_t const * a, float16x8x2_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float32x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.float32x4x2_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[__S1]], i32 0, i32 0
@@ -5008,7 +4903,7 @@ float32x4x2_t test_vld2q_lane_f32(float32_t const * a, float32x4x2_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly16x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[__S1]], i32 0, i32 0
@@ -5035,7 +4930,7 @@ poly16x8x2_t test_vld2q_lane_p16(poly16_t const * a, poly16x8x2_t b) {
// CHECK: store [2 x i64] [[B]].coerce, [2 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 16, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET]] to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL]], i32 0, i32 0
@@ -5057,7 +4952,7 @@ uint8x8x2_t test_vld2_lane_u8(uint8_t const * a, uint8x8x2_t b) {
// CHECK: store [2 x i64] [[B]].coerce, [2 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint16x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 16, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[__S1]], i32 0, i32 0
@@ -5084,7 +4979,7 @@ uint16x4x2_t test_vld2_lane_u16(uint16_t const * a, uint16x4x2_t b) {
// CHECK: store [2 x i64] [[B]].coerce, [2 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x2x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint32x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 16, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[__S1]], i32 0, i32 0
@@ -5111,7 +5006,7 @@ uint32x2x2_t test_vld2_lane_u32(uint32_t const * a, uint32x2x2_t b) {
// CHECK: store [2 x i64] [[B]].coerce, [2 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 16, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x2_t* [[__RET]] to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x8x2_t, %struct.int8x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL]], i32 0, i32 0
@@ -5133,7 +5028,7 @@ int8x8x2_t test_vld2_lane_s8(int8_t const * a, int8x8x2_t b) {
// CHECK: store [2 x i64] [[B]].coerce, [2 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int16x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 16, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.int16x4x2_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x4x2_t, %struct.int16x4x2_t* [[__S1]], i32 0, i32 0
@@ -5160,7 +5055,7 @@ int16x4x2_t test_vld2_lane_s16(int16_t const * a, int16x4x2_t b) {
// CHECK: store [2 x i64] [[B]].coerce, [2 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x2x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int32x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 16, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.int32x2x2_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x2x2_t, %struct.int32x2x2_t* [[__S1]], i32 0, i32 0
@@ -5187,7 +5082,7 @@ int32x2x2_t test_vld2_lane_s32(int32_t const * a, int32x2x2_t b) {
// CHECK: store [2 x i64] [[B]].coerce, [2 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float16x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 16, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.float16x4x2_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x4x2_t, %struct.float16x4x2_t* [[__S1]], i32 0, i32 0
@@ -5214,7 +5109,7 @@ float16x4x2_t test_vld2_lane_f16(float16_t const * a, float16x4x2_t b) {
// CHECK: store [2 x i64] [[B]].coerce, [2 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x2x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float32x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 16, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.float32x2x2_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x2x2_t, %struct.float32x2x2_t* [[__S1]], i32 0, i32 0
@@ -5241,7 +5136,7 @@ float32x2x2_t test_vld2_lane_f32(float32_t const * a, float32x2x2_t b) {
// CHECK: store [2 x i64] [[B]].coerce, [2 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 16, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET]] to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL]], i32 0, i32 0
@@ -5263,7 +5158,7 @@ poly8x8x2_t test_vld2_lane_p8(poly8_t const * a, poly8x8x2_t b) {
// CHECK: store [2 x i64] [[B]].coerce, [2 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly16x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 16, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[__S1]], i32 0, i32 0
@@ -5473,111 +5368,6 @@ poly16x4x3_t test_vld3_p16(poly16_t const * a) {
return vld3_p16(a);
}
-// CHECK-LABEL: @test_vld3_dup_u8(
-// CHECK: [[__RET:%.*]] = alloca %struct.uint8x8x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x3_t* [[__RET]] to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>
-uint8x8x3_t test_vld3_dup_u8(uint8_t const * a) {
- return vld3_dup_u8(a);
-}
-
-// CHECK-LABEL: @test_vld3_dup_u16(
-// CHECK: [[__RET:%.*]] = alloca %struct.uint16x4x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>
-uint16x4x3_t test_vld3_dup_u16(uint16_t const * a) {
- return vld3_dup_u16(a);
-}
-
-// CHECK-LABEL: @test_vld3_dup_u32(
-// CHECK: [[__RET:%.*]] = alloca %struct.uint32x2x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>
-uint32x2x3_t test_vld3_dup_u32(uint32_t const * a) {
- return vld3_dup_u32(a);
-}
-
-// CHECK-LABEL: @test_vld3_dup_u64(
-// CHECK: [[__RET:%.*]] = alloca %struct.uint64x1x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64>
-uint64x1x3_t test_vld3_dup_u64(uint64_t const * a) {
- return vld3_dup_u64(a);
-}
-
-// CHECK-LABEL: @test_vld3_dup_s8(
-// CHECK: [[__RET:%.*]] = alloca %struct.int8x8x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x3_t* [[__RET]] to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>
-int8x8x3_t test_vld3_dup_s8(int8_t const * a) {
- return vld3_dup_s8(a);
-}
-
-// CHECK-LABEL: @test_vld3_dup_s16(
-// CHECK: [[__RET:%.*]] = alloca %struct.int16x4x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>
-int16x4x3_t test_vld3_dup_s16(int16_t const * a) {
- return vld3_dup_s16(a);
-}
-
-// CHECK-LABEL: @test_vld3_dup_s32(
-// CHECK: [[__RET:%.*]] = alloca %struct.int32x2x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>
-int32x2x3_t test_vld3_dup_s32(int32_t const * a) {
- return vld3_dup_s32(a);
-}
-
-// CHECK-LABEL: @test_vld3_dup_s64(
-// CHECK: [[__RET:%.*]] = alloca %struct.int64x1x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64>
-int64x1x3_t test_vld3_dup_s64(int64_t const * a) {
- return vld3_dup_s64(a);
-}
-
-// CHECK-LABEL: @test_vld3_dup_f16(
-// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>
-float16x4x3_t test_vld3_dup_f16(float16_t const * a) {
- return vld3_dup_f16(a);
-}
-
-// CHECK-LABEL: @test_vld3_dup_f32(
-// CHECK: [[__RET:%.*]] = alloca %struct.float32x2x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast float* %a to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <2 x float>, <2 x float>, <2 x float>
-float32x2x3_t test_vld3_dup_f32(float32_t const * a) {
- return vld3_dup_f32(a);
-}
-
-// CHECK-LABEL: @test_vld3_dup_p8(
-// CHECK: [[__RET:%.*]] = alloca %struct.poly8x8x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x3_t* [[__RET]] to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>
-poly8x8x3_t test_vld3_dup_p8(poly8_t const * a) {
- return vld3_dup_p8(a);
-}
-
-// CHECK-LABEL: @test_vld3_dup_p16(
-// CHECK: [[__RET:%.*]] = alloca %struct.poly16x4x3_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x3_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>
-poly16x4x3_t test_vld3_dup_p16(poly16_t const * a) {
- return vld3_dup_p16(a);
-}
-
// CHECK-LABEL: @test_vld3q_lane_u16(
// CHECK: [[B:%.*]] = alloca %struct.uint16x8x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x3_t, align 16
@@ -5587,7 +5377,7 @@ poly16x4x3_t test_vld3_dup_p16(poly16_t const * a) {
// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint16x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 48, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.uint16x8x3_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[__S1]], i32 0, i32 0
@@ -5619,7 +5409,7 @@ uint16x8x3_t test_vld3q_lane_u16(uint16_t const * a, uint16x8x3_t b) {
// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint32x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 48, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.uint32x4x3_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[__S1]], i32 0, i32 0
@@ -5651,7 +5441,7 @@ uint32x4x3_t test_vld3q_lane_u32(uint32_t const * a, uint32x4x3_t b) {
// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int16x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 48, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.int16x8x3_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[__S1]], i32 0, i32 0
@@ -5683,7 +5473,7 @@ int16x8x3_t test_vld3q_lane_s16(int16_t const * a, int16x8x3_t b) {
// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int32x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 48, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.int32x4x3_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[__S1]], i32 0, i32 0
@@ -5715,7 +5505,7 @@ int32x4x3_t test_vld3q_lane_s32(int32_t const * a, int32x4x3_t b) {
// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float16x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 48, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.float16x8x3_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[__S1]], i32 0, i32 0
@@ -5747,7 +5537,7 @@ float16x8x3_t test_vld3q_lane_f16(float16_t const * a, float16x8x3_t b) {
// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float32x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 48, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.float32x4x3_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[__S1]], i32 0, i32 0
@@ -5779,7 +5569,7 @@ float32x4x3_t test_vld3q_lane_f32(float32_t const * a, float32x4x3_t b) {
// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly16x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 48, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.poly16x8x3_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[__S1]], i32 0, i32 0
@@ -5811,7 +5601,7 @@ poly16x8x3_t test_vld3q_lane_p16(poly16_t const * a, poly16x8x3_t b) {
// CHECK: store [3 x i64] [[B]].coerce, [3 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 24, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x3_t* [[__RET]] to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x8x3_t, %struct.uint8x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL]], i32 0, i32 0
@@ -5836,7 +5626,7 @@ uint8x8x3_t test_vld3_lane_u8(uint8_t const * a, uint8x8x3_t b) {
// CHECK: store [3 x i64] [[B]].coerce, [3 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint16x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 24, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.uint16x4x3_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x4x3_t, %struct.uint16x4x3_t* [[__S1]], i32 0, i32 0
@@ -5868,7 +5658,7 @@ uint16x4x3_t test_vld3_lane_u16(uint16_t const * a, uint16x4x3_t b) {
// CHECK: store [3 x i64] [[B]].coerce, [3 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x2x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint32x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 24, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.uint32x2x3_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x2x3_t, %struct.uint32x2x3_t* [[__S1]], i32 0, i32 0
@@ -5900,7 +5690,7 @@ uint32x2x3_t test_vld3_lane_u32(uint32_t const * a, uint32x2x3_t b) {
// CHECK: store [3 x i64] [[B]].coerce, [3 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 24, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x3_t* [[__RET]] to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x8x3_t, %struct.int8x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL]], i32 0, i32 0
@@ -5925,7 +5715,7 @@ int8x8x3_t test_vld3_lane_s8(int8_t const * a, int8x8x3_t b) {
// CHECK: store [3 x i64] [[B]].coerce, [3 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int16x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 24, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.int16x4x3_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x4x3_t, %struct.int16x4x3_t* [[__S1]], i32 0, i32 0
@@ -5957,7 +5747,7 @@ int16x4x3_t test_vld3_lane_s16(int16_t const * a, int16x4x3_t b) {
// CHECK: store [3 x i64] [[B]].coerce, [3 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x2x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int32x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 24, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.int32x2x3_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x2x3_t, %struct.int32x2x3_t* [[__S1]], i32 0, i32 0
@@ -5989,7 +5779,7 @@ int32x2x3_t test_vld3_lane_s32(int32_t const * a, int32x2x3_t b) {
// CHECK: store [3 x i64] [[B]].coerce, [3 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float16x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 24, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.float16x4x3_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x4x3_t, %struct.float16x4x3_t* [[__S1]], i32 0, i32 0
@@ -6021,7 +5811,7 @@ float16x4x3_t test_vld3_lane_f16(float16_t const * a, float16x4x3_t b) {
// CHECK: store [3 x i64] [[B]].coerce, [3 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x2x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float32x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 24, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.float32x2x3_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x2x3_t, %struct.float32x2x3_t* [[__S1]], i32 0, i32 0
@@ -6053,7 +5843,7 @@ float32x2x3_t test_vld3_lane_f32(float32_t const * a, float32x2x3_t b) {
// CHECK: store [3 x i64] [[B]].coerce, [3 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 24, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x3_t* [[__RET]] to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x8x3_t, %struct.poly8x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL]], i32 0, i32 0
@@ -6078,7 +5868,7 @@ poly8x8x3_t test_vld3_lane_p8(poly8_t const * a, poly8x8x3_t b) {
// CHECK: store [3 x i64] [[B]].coerce, [3 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly16x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 24, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.poly16x4x3_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x4x3_t, %struct.poly16x4x3_t* [[__S1]], i32 0, i32 0
@@ -6293,111 +6083,6 @@ poly16x4x4_t test_vld4_p16(poly16_t const * a) {
return vld4_p16(a);
}
-// CHECK-LABEL: @test_vld4_dup_u8(
-// CHECK: [[__RET:%.*]] = alloca %struct.uint8x8x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x4_t* [[__RET]] to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>
-uint8x8x4_t test_vld4_dup_u8(uint8_t const * a) {
- return vld4_dup_u8(a);
-}
-
-// CHECK-LABEL: @test_vld4_dup_u16(
-// CHECK: [[__RET:%.*]] = alloca %struct.uint16x4x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16>
-uint16x4x4_t test_vld4_dup_u16(uint16_t const * a) {
- return vld4_dup_u16(a);
-}
-
-// CHECK-LABEL: @test_vld4_dup_u32(
-// CHECK: [[__RET:%.*]] = alloca %struct.uint32x2x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32>
-uint32x2x4_t test_vld4_dup_u32(uint32_t const * a) {
- return vld4_dup_u32(a);
-}
-
-// CHECK-LABEL: @test_vld4_dup_u64(
-// CHECK: [[__RET:%.*]] = alloca %struct.uint64x1x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64>
-uint64x1x4_t test_vld4_dup_u64(uint64_t const * a) {
- return vld4_dup_u64(a);
-}
-
-// CHECK-LABEL: @test_vld4_dup_s8(
-// CHECK: [[__RET:%.*]] = alloca %struct.int8x8x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x4_t* [[__RET]] to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>
-int8x8x4_t test_vld4_dup_s8(int8_t const * a) {
- return vld4_dup_s8(a);
-}
-
-// CHECK-LABEL: @test_vld4_dup_s16(
-// CHECK: [[__RET:%.*]] = alloca %struct.int16x4x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16>
-int16x4x4_t test_vld4_dup_s16(int16_t const * a) {
- return vld4_dup_s16(a);
-}
-
-// CHECK-LABEL: @test_vld4_dup_s32(
-// CHECK: [[__RET:%.*]] = alloca %struct.int32x2x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32>
-int32x2x4_t test_vld4_dup_s32(int32_t const * a) {
- return vld4_dup_s32(a);
-}
-
-// CHECK-LABEL: @test_vld4_dup_s64(
-// CHECK: [[__RET:%.*]] = alloca %struct.int64x1x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64>
-int64x1x4_t test_vld4_dup_s64(int64_t const * a) {
- return vld4_dup_s64(a);
-}
-
-// CHECK-LABEL: @test_vld4_dup_f16(
-// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16>
-float16x4x4_t test_vld4_dup_f16(float16_t const * a) {
- return vld4_dup_f16(a);
-}
-
-// CHECK-LABEL: @test_vld4_dup_f32(
-// CHECK: [[__RET:%.*]] = alloca %struct.float32x2x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast float* %a to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <2 x float>, <2 x float>, <2 x float>, <2 x float>
-float32x2x4_t test_vld4_dup_f32(float32_t const * a) {
- return vld4_dup_f32(a);
-}
-
-// CHECK-LABEL: @test_vld4_dup_p8(
-// CHECK: [[__RET:%.*]] = alloca %struct.poly8x8x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x4_t* [[__RET]] to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>
-poly8x8x4_t test_vld4_dup_p8(poly8_t const * a) {
- return vld4_dup_p8(a);
-}
-
-// CHECK-LABEL: @test_vld4_dup_p16(
-// CHECK: [[__RET:%.*]] = alloca %struct.poly16x4x4_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x4_t* [[__RET]] to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8*
-// CHECK: [[VLD_DUP:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16>
-poly16x4x4_t test_vld4_dup_p16(poly16_t const * a) {
- return vld4_dup_p16(a);
-}
-
// CHECK-LABEL: @test_vld4q_lane_u16(
// CHECK: [[B:%.*]] = alloca %struct.uint16x8x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x4_t, align 16
@@ -6407,7 +6092,7 @@ poly16x4x4_t test_vld4_dup_p16(poly16_t const * a) {
// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint16x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 64, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.uint16x8x4_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0
@@ -6444,7 +6129,7 @@ uint16x8x4_t test_vld4q_lane_u16(uint16_t const * a, uint16x8x4_t b) {
// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint32x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 64, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.uint32x4x4_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0
@@ -6481,7 +6166,7 @@ uint32x4x4_t test_vld4q_lane_u32(uint32_t const * a, uint32x4x4_t b) {
// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int16x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 64, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.int16x8x4_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0
@@ -6518,7 +6203,7 @@ int16x8x4_t test_vld4q_lane_s16(int16_t const * a, int16x8x4_t b) {
// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int32x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 64, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.int32x4x4_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0
@@ -6555,7 +6240,7 @@ int32x4x4_t test_vld4q_lane_s32(int32_t const * a, int32x4x4_t b) {
// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float16x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 64, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.float16x8x4_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0
@@ -6592,7 +6277,7 @@ float16x8x4_t test_vld4q_lane_f16(float16_t const * a, float16x8x4_t b) {
// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float32x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 64, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.float32x4x4_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0
@@ -6629,7 +6314,7 @@ float32x4x4_t test_vld4q_lane_f32(float32_t const * a, float32x4x4_t b) {
// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly16x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 64, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.poly16x8x4_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0
@@ -6666,7 +6351,7 @@ poly16x8x4_t test_vld4q_lane_p16(poly16_t const * a, poly16x8x4_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x4_t* [[__RET]] to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL]], i32 0, i32 0
@@ -6694,7 +6379,7 @@ uint8x8x4_t test_vld4_lane_u8(uint8_t const * a, uint8x8x4_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint16x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.uint16x4x4_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x4x4_t, %struct.uint16x4x4_t* [[__S1]], i32 0, i32 0
@@ -6731,7 +6416,7 @@ uint16x4x4_t test_vld4_lane_u16(uint16_t const * a, uint16x4x4_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x2x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint32x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.uint32x2x4_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x2x4_t, %struct.uint32x2x4_t* [[__S1]], i32 0, i32 0
@@ -6768,7 +6453,7 @@ uint32x2x4_t test_vld4_lane_u32(uint32_t const * a, uint32x2x4_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x4_t* [[__RET]] to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x8x4_t, %struct.int8x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL]], i32 0, i32 0
@@ -6796,7 +6481,7 @@ int8x8x4_t test_vld4_lane_s8(int8_t const * a, int8x8x4_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int16x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.int16x4x4_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x4x4_t, %struct.int16x4x4_t* [[__S1]], i32 0, i32 0
@@ -6833,7 +6518,7 @@ int16x4x4_t test_vld4_lane_s16(int16_t const * a, int16x4x4_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x2x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int32x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.int32x2x4_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x2x4_t, %struct.int32x2x4_t* [[__S1]], i32 0, i32 0
@@ -6870,7 +6555,7 @@ int32x2x4_t test_vld4_lane_s32(int32_t const * a, int32x2x4_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float16x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.float16x4x4_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x4x4_t, %struct.float16x4x4_t* [[__S1]], i32 0, i32 0
@@ -6907,7 +6592,7 @@ float16x4x4_t test_vld4_lane_f16(float16_t const * a, float16x4x4_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x2x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float32x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.float32x2x4_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x2x4_t, %struct.float32x2x4_t* [[__S1]], i32 0, i32 0
@@ -6944,7 +6629,7 @@ float32x2x4_t test_vld4_lane_f32(float32_t const * a, float32x2x4_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x4_t* [[__RET]] to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL]], i32 0, i32 0
@@ -6972,7 +6657,7 @@ poly8x8x4_t test_vld4_lane_p8(poly8_t const * a, poly8x8x4_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly16x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast %struct.poly16x4x4_t* [[__RET]] to i8*
// CHECK: [[TMP4:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x4x4_t, %struct.poly16x4x4_t* [[__S1]], i32 0, i32 0
@@ -16199,7 +15884,7 @@ void test_vst1_lane_p16(poly16_t * a, poly16x4_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x16x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x16x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 32, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL]], i32 0, i32 0
// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
@@ -16220,7 +15905,7 @@ void test_vst2q_u8(uint8_t * a, uint8x16x2_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint16x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL]], i32 0, i32 0
@@ -16246,7 +15931,7 @@ void test_vst2q_u16(uint16_t * a, uint16x8x2_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint32x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL]], i32 0, i32 0
@@ -16272,7 +15957,7 @@ void test_vst2q_u32(uint32_t * a, uint32x4x2_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x16x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x16x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 32, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x16x2_t, %struct.int8x16x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL]], i32 0, i32 0
// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
@@ -16293,7 +15978,7 @@ void test_vst2q_s8(int8_t * a, int8x16x2_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int16x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL]], i32 0, i32 0
@@ -16319,7 +16004,7 @@ void test_vst2q_s16(int16_t * a, int16x8x2_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int32x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL]], i32 0, i32 0
@@ -16345,7 +16030,7 @@ void test_vst2q_s32(int32_t * a, int32x4x2_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float16x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x2_t, %struct.float16x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x half>], [2 x <8 x half>]* [[VAL]], i32 0, i32 0
@@ -16371,7 +16056,7 @@ void test_vst2q_f16(float16_t * a, float16x8x2_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float32x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x float>], [2 x <4 x float>]* [[VAL]], i32 0, i32 0
@@ -16397,7 +16082,7 @@ void test_vst2q_f32(float32_t * a, float32x4x2_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x16x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x16x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 32, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL]], i32 0, i32 0
// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
@@ -16418,7 +16103,7 @@ void test_vst2q_p8(poly8_t * a, poly8x16x2_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly16x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL]], i32 0, i32 0
@@ -16444,7 +16129,7 @@ void test_vst2q_p16(poly16_t * a, poly16x8x2_t b) {
// CHECK: store [2 x i64] [[B]].coerce, [2 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 16, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL]], i32 0, i32 0
// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -16465,7 +16150,7 @@ void test_vst2_u8(uint8_t * a, uint8x8x2_t b) {
// CHECK: store [2 x i64] [[B]].coerce, [2 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint16x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 16, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL]], i32 0, i32 0
@@ -16491,7 +16176,7 @@ void test_vst2_u16(uint16_t * a, uint16x4x2_t b) {
// CHECK: store [2 x i64] [[B]].coerce, [2 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x2x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint32x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 16, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x i32>], [2 x <2 x i32>]* [[VAL]], i32 0, i32 0
@@ -16517,7 +16202,7 @@ void test_vst2_u32(uint32_t * a, uint32x2x2_t b) {
// CHECK: store [2 x i64] [[B]].coerce, [2 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x1x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint64x1x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 16, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x1x2_t, %struct.uint64x1x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <1 x i64>], [2 x <1 x i64>]* [[VAL]], i32 0, i32 0
@@ -16543,7 +16228,7 @@ void test_vst2_u64(uint64_t * a, uint64x1x2_t b) {
// CHECK: store [2 x i64] [[B]].coerce, [2 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 16, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x8x2_t, %struct.int8x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL]], i32 0, i32 0
// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -16564,7 +16249,7 @@ void test_vst2_s8(int8_t * a, int8x8x2_t b) {
// CHECK: store [2 x i64] [[B]].coerce, [2 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int16x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 16, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x4x2_t, %struct.int16x4x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL]], i32 0, i32 0
@@ -16590,7 +16275,7 @@ void test_vst2_s16(int16_t * a, int16x4x2_t b) {
// CHECK: store [2 x i64] [[B]].coerce, [2 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x2x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int32x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 16, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x2x2_t, %struct.int32x2x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x i32>], [2 x <2 x i32>]* [[VAL]], i32 0, i32 0
@@ -16616,7 +16301,7 @@ void test_vst2_s32(int32_t * a, int32x2x2_t b) {
// CHECK: store [2 x i64] [[B]].coerce, [2 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x1x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int64x1x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 16, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x1x2_t, %struct.int64x1x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <1 x i64>], [2 x <1 x i64>]* [[VAL]], i32 0, i32 0
@@ -16642,7 +16327,7 @@ void test_vst2_s64(int64_t * a, int64x1x2_t b) {
// CHECK: store [2 x i64] [[B]].coerce, [2 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float16x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 16, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x4x2_t, %struct.float16x4x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x half>], [2 x <4 x half>]* [[VAL]], i32 0, i32 0
@@ -16668,7 +16353,7 @@ void test_vst2_f16(float16_t * a, float16x4x2_t b) {
// CHECK: store [2 x i64] [[B]].coerce, [2 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x2x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float32x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 16, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x2x2_t, %struct.float32x2x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x float>], [2 x <2 x float>]* [[VAL]], i32 0, i32 0
@@ -16694,7 +16379,7 @@ void test_vst2_f32(float32_t * a, float32x2x2_t b) {
// CHECK: store [2 x i64] [[B]].coerce, [2 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 16, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL]], i32 0, i32 0
// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -16715,7 +16400,7 @@ void test_vst2_p8(poly8_t * a, poly8x8x2_t b) {
// CHECK: store [2 x i64] [[B]].coerce, [2 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly16x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 16, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL]], i32 0, i32 0
@@ -16741,7 +16426,7 @@ void test_vst2_p16(poly16_t * a, poly16x4x2_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint16x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL]], i32 0, i32 0
@@ -16767,7 +16452,7 @@ void test_vst2q_lane_u16(uint16_t * a, uint16x8x2_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint32x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL]], i32 0, i32 0
@@ -16793,7 +16478,7 @@ void test_vst2q_lane_u32(uint32_t * a, uint32x4x2_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int16x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL]], i32 0, i32 0
@@ -16819,7 +16504,7 @@ void test_vst2q_lane_s16(int16_t * a, int16x8x2_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int32x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL]], i32 0, i32 0
@@ -16845,7 +16530,7 @@ void test_vst2q_lane_s32(int32_t * a, int32x4x2_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float16x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x2_t, %struct.float16x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x half>], [2 x <8 x half>]* [[VAL]], i32 0, i32 0
@@ -16871,7 +16556,7 @@ void test_vst2q_lane_f16(float16_t * a, float16x8x2_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float32x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x float>], [2 x <4 x float>]* [[VAL]], i32 0, i32 0
@@ -16897,7 +16582,7 @@ void test_vst2q_lane_f32(float32_t * a, float32x4x2_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly16x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL]], i32 0, i32 0
@@ -16923,7 +16608,7 @@ void test_vst2q_lane_p16(poly16_t * a, poly16x8x2_t b) {
// CHECK: store [2 x i64] [[B]].coerce, [2 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 16, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL]], i32 0, i32 0
// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -16944,7 +16629,7 @@ void test_vst2_lane_u8(uint8_t * a, uint8x8x2_t b) {
// CHECK: store [2 x i64] [[B]].coerce, [2 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint16x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 16, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL]], i32 0, i32 0
@@ -16970,7 +16655,7 @@ void test_vst2_lane_u16(uint16_t * a, uint16x4x2_t b) {
// CHECK: store [2 x i64] [[B]].coerce, [2 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x2x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint32x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 16, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x i32>], [2 x <2 x i32>]* [[VAL]], i32 0, i32 0
@@ -16996,7 +16681,7 @@ void test_vst2_lane_u32(uint32_t * a, uint32x2x2_t b) {
// CHECK: store [2 x i64] [[B]].coerce, [2 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 16, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x8x2_t, %struct.int8x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL]], i32 0, i32 0
// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -17017,7 +16702,7 @@ void test_vst2_lane_s8(int8_t * a, int8x8x2_t b) {
// CHECK: store [2 x i64] [[B]].coerce, [2 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int16x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 16, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x4x2_t, %struct.int16x4x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL]], i32 0, i32 0
@@ -17043,7 +16728,7 @@ void test_vst2_lane_s16(int16_t * a, int16x4x2_t b) {
// CHECK: store [2 x i64] [[B]].coerce, [2 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x2x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int32x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 16, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x2x2_t, %struct.int32x2x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x i32>], [2 x <2 x i32>]* [[VAL]], i32 0, i32 0
@@ -17069,7 +16754,7 @@ void test_vst2_lane_s32(int32_t * a, int32x2x2_t b) {
// CHECK: store [2 x i64] [[B]].coerce, [2 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float16x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 16, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x4x2_t, %struct.float16x4x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x half>], [2 x <4 x half>]* [[VAL]], i32 0, i32 0
@@ -17095,7 +16780,7 @@ void test_vst2_lane_f16(float16_t * a, float16x4x2_t b) {
// CHECK: store [2 x i64] [[B]].coerce, [2 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x2x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float32x2x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 16, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x2x2_t, %struct.float32x2x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x float>], [2 x <2 x float>]* [[VAL]], i32 0, i32 0
@@ -17121,7 +16806,7 @@ void test_vst2_lane_f32(float32_t * a, float32x2x2_t b) {
// CHECK: store [2 x i64] [[B]].coerce, [2 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x8x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x8x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 16, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL]], i32 0, i32 0
// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -17142,7 +16827,7 @@ void test_vst2_lane_p8(poly8_t * a, poly8x8x2_t b) {
// CHECK: store [2 x i64] [[B]].coerce, [2 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x4x2_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly16x4x2_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 16, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL]], i32 0, i32 0
@@ -17168,7 +16853,7 @@ void test_vst2_lane_p16(poly16_t * a, poly16x4x2_t b) {
// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x16x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x16x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 48, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL]], i32 0, i32 0
// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
@@ -17192,7 +16877,7 @@ void test_vst3q_u8(uint8_t * a, uint8x16x3_t b) {
// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint16x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 48, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL]], i32 0, i32 0
@@ -17223,7 +16908,7 @@ void test_vst3q_u16(uint16_t * a, uint16x8x3_t b) {
// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint32x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 48, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL]], i32 0, i32 0
@@ -17254,7 +16939,7 @@ void test_vst3q_u32(uint32_t * a, uint32x4x3_t b) {
// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x16x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x16x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 48, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x16x3_t, %struct.int8x16x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL]], i32 0, i32 0
// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
@@ -17278,7 +16963,7 @@ void test_vst3q_s8(int8_t * a, int8x16x3_t b) {
// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int16x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 48, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL]], i32 0, i32 0
@@ -17309,7 +16994,7 @@ void test_vst3q_s16(int16_t * a, int16x8x3_t b) {
// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int32x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 48, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL]], i32 0, i32 0
@@ -17340,7 +17025,7 @@ void test_vst3q_s32(int32_t * a, int32x4x3_t b) {
// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float16x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 48, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x half>], [3 x <8 x half>]* [[VAL]], i32 0, i32 0
@@ -17371,7 +17056,7 @@ void test_vst3q_f16(float16_t * a, float16x8x3_t b) {
// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float32x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 48, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x float>], [3 x <4 x float>]* [[VAL]], i32 0, i32 0
@@ -17402,7 +17087,7 @@ void test_vst3q_f32(float32_t * a, float32x4x3_t b) {
// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x16x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x16x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 48, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL]], i32 0, i32 0
// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
@@ -17426,7 +17111,7 @@ void test_vst3q_p8(poly8_t * a, poly8x16x3_t b) {
// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly16x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 48, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL]], i32 0, i32 0
@@ -17457,7 +17142,7 @@ void test_vst3q_p16(poly16_t * a, poly16x8x3_t b) {
// CHECK: store [3 x i64] [[B]].coerce, [3 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 24, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x8x3_t, %struct.uint8x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL]], i32 0, i32 0
// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -17481,7 +17166,7 @@ void test_vst3_u8(uint8_t * a, uint8x8x3_t b) {
// CHECK: store [3 x i64] [[B]].coerce, [3 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint16x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 24, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x4x3_t, %struct.uint16x4x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL]], i32 0, i32 0
@@ -17512,7 +17197,7 @@ void test_vst3_u16(uint16_t * a, uint16x4x3_t b) {
// CHECK: store [3 x i64] [[B]].coerce, [3 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x2x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint32x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 24, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x2x3_t, %struct.uint32x2x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x i32>], [3 x <2 x i32>]* [[VAL]], i32 0, i32 0
@@ -17543,7 +17228,7 @@ void test_vst3_u32(uint32_t * a, uint32x2x3_t b) {
// CHECK: store [3 x i64] [[B]].coerce, [3 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x1x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint64x1x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 24, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x1x3_t, %struct.uint64x1x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL]], i32 0, i32 0
@@ -17574,7 +17259,7 @@ void test_vst3_u64(uint64_t * a, uint64x1x3_t b) {
// CHECK: store [3 x i64] [[B]].coerce, [3 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 24, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x8x3_t, %struct.int8x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL]], i32 0, i32 0
// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -17598,7 +17283,7 @@ void test_vst3_s8(int8_t * a, int8x8x3_t b) {
// CHECK: store [3 x i64] [[B]].coerce, [3 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int16x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 24, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x4x3_t, %struct.int16x4x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL]], i32 0, i32 0
@@ -17629,7 +17314,7 @@ void test_vst3_s16(int16_t * a, int16x4x3_t b) {
// CHECK: store [3 x i64] [[B]].coerce, [3 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x2x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int32x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 24, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x2x3_t, %struct.int32x2x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x i32>], [3 x <2 x i32>]* [[VAL]], i32 0, i32 0
@@ -17660,7 +17345,7 @@ void test_vst3_s32(int32_t * a, int32x2x3_t b) {
// CHECK: store [3 x i64] [[B]].coerce, [3 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x1x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int64x1x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 24, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x1x3_t, %struct.int64x1x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL]], i32 0, i32 0
@@ -17691,7 +17376,7 @@ void test_vst3_s64(int64_t * a, int64x1x3_t b) {
// CHECK: store [3 x i64] [[B]].coerce, [3 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float16x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 24, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x4x3_t, %struct.float16x4x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x half>], [3 x <4 x half>]* [[VAL]], i32 0, i32 0
@@ -17722,7 +17407,7 @@ void test_vst3_f16(float16_t * a, float16x4x3_t b) {
// CHECK: store [3 x i64] [[B]].coerce, [3 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x2x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float32x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 24, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x2x3_t, %struct.float32x2x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x float>], [3 x <2 x float>]* [[VAL]], i32 0, i32 0
@@ -17753,7 +17438,7 @@ void test_vst3_f32(float32_t * a, float32x2x3_t b) {
// CHECK: store [3 x i64] [[B]].coerce, [3 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 24, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x8x3_t, %struct.poly8x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL]], i32 0, i32 0
// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -17777,7 +17462,7 @@ void test_vst3_p8(poly8_t * a, poly8x8x3_t b) {
// CHECK: store [3 x i64] [[B]].coerce, [3 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly16x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 24, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x4x3_t, %struct.poly16x4x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL]], i32 0, i32 0
@@ -17808,7 +17493,7 @@ void test_vst3_p16(poly16_t * a, poly16x4x3_t b) {
// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint16x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 48, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL]], i32 0, i32 0
@@ -17839,7 +17524,7 @@ void test_vst3q_lane_u16(uint16_t * a, uint16x8x3_t b) {
// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint32x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 48, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL]], i32 0, i32 0
@@ -17870,7 +17555,7 @@ void test_vst3q_lane_u32(uint32_t * a, uint32x4x3_t b) {
// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int16x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 48, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL]], i32 0, i32 0
@@ -17901,7 +17586,7 @@ void test_vst3q_lane_s16(int16_t * a, int16x8x3_t b) {
// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int32x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 48, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL]], i32 0, i32 0
@@ -17932,7 +17617,7 @@ void test_vst3q_lane_s32(int32_t * a, int32x4x3_t b) {
// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float16x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 48, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x half>], [3 x <8 x half>]* [[VAL]], i32 0, i32 0
@@ -17963,7 +17648,7 @@ void test_vst3q_lane_f16(float16_t * a, float16x8x3_t b) {
// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float32x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 48, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x float>], [3 x <4 x float>]* [[VAL]], i32 0, i32 0
@@ -17994,7 +17679,7 @@ void test_vst3q_lane_f32(float32_t * a, float32x4x3_t b) {
// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly16x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 48, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL]], i32 0, i32 0
@@ -18025,7 +17710,7 @@ void test_vst3q_lane_p16(poly16_t * a, poly16x8x3_t b) {
// CHECK: store [3 x i64] [[B]].coerce, [3 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 24, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x8x3_t, %struct.uint8x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL]], i32 0, i32 0
// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -18049,7 +17734,7 @@ void test_vst3_lane_u8(uint8_t * a, uint8x8x3_t b) {
// CHECK: store [3 x i64] [[B]].coerce, [3 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint16x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 24, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x4x3_t, %struct.uint16x4x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL]], i32 0, i32 0
@@ -18080,7 +17765,7 @@ void test_vst3_lane_u16(uint16_t * a, uint16x4x3_t b) {
// CHECK: store [3 x i64] [[B]].coerce, [3 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x2x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint32x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 24, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x2x3_t, %struct.uint32x2x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x i32>], [3 x <2 x i32>]* [[VAL]], i32 0, i32 0
@@ -18111,7 +17796,7 @@ void test_vst3_lane_u32(uint32_t * a, uint32x2x3_t b) {
// CHECK: store [3 x i64] [[B]].coerce, [3 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 24, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x8x3_t, %struct.int8x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL]], i32 0, i32 0
// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -18135,7 +17820,7 @@ void test_vst3_lane_s8(int8_t * a, int8x8x3_t b) {
// CHECK: store [3 x i64] [[B]].coerce, [3 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int16x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 24, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x4x3_t, %struct.int16x4x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL]], i32 0, i32 0
@@ -18166,7 +17851,7 @@ void test_vst3_lane_s16(int16_t * a, int16x4x3_t b) {
// CHECK: store [3 x i64] [[B]].coerce, [3 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x2x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int32x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 24, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x2x3_t, %struct.int32x2x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x i32>], [3 x <2 x i32>]* [[VAL]], i32 0, i32 0
@@ -18197,7 +17882,7 @@ void test_vst3_lane_s32(int32_t * a, int32x2x3_t b) {
// CHECK: store [3 x i64] [[B]].coerce, [3 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float16x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 24, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x4x3_t, %struct.float16x4x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x half>], [3 x <4 x half>]* [[VAL]], i32 0, i32 0
@@ -18228,7 +17913,7 @@ void test_vst3_lane_f16(float16_t * a, float16x4x3_t b) {
// CHECK: store [3 x i64] [[B]].coerce, [3 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x2x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float32x2x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 24, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x2x3_t, %struct.float32x2x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x float>], [3 x <2 x float>]* [[VAL]], i32 0, i32 0
@@ -18259,7 +17944,7 @@ void test_vst3_lane_f32(float32_t * a, float32x2x3_t b) {
// CHECK: store [3 x i64] [[B]].coerce, [3 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x8x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x8x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 24, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x8x3_t, %struct.poly8x8x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL]], i32 0, i32 0
// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -18283,7 +17968,7 @@ void test_vst3_lane_p8(poly8_t * a, poly8x8x3_t b) {
// CHECK: store [3 x i64] [[B]].coerce, [3 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x4x3_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly16x4x3_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 24, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 24, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x4x3_t, %struct.poly16x4x3_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL]], i32 0, i32 0
@@ -18314,7 +17999,7 @@ void test_vst3_lane_p16(poly16_t * a, poly16x4x3_t b) {
// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x16x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x16x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 64, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL]], i32 0, i32 0
// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
@@ -18341,7 +18026,7 @@ void test_vst4q_u8(uint8_t * a, uint8x16x4_t b) {
// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint16x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 64, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL]], i32 0, i32 0
@@ -18377,7 +18062,7 @@ void test_vst4q_u16(uint16_t * a, uint16x8x4_t b) {
// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint32x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 64, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL]], i32 0, i32 0
@@ -18413,7 +18098,7 @@ void test_vst4q_u32(uint32_t * a, uint32x4x4_t b) {
// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x16x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x16x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 64, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL]], i32 0, i32 0
// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
@@ -18440,7 +18125,7 @@ void test_vst4q_s8(int8_t * a, int8x16x4_t b) {
// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int16x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 64, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL]], i32 0, i32 0
@@ -18476,7 +18161,7 @@ void test_vst4q_s16(int16_t * a, int16x8x4_t b) {
// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int32x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 64, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL]], i32 0, i32 0
@@ -18512,7 +18197,7 @@ void test_vst4q_s32(int32_t * a, int32x4x4_t b) {
// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float16x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 64, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL]], i32 0, i32 0
@@ -18548,7 +18233,7 @@ void test_vst4q_f16(float16_t * a, float16x8x4_t b) {
// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float32x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 64, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x float>], [4 x <4 x float>]* [[VAL]], i32 0, i32 0
@@ -18584,7 +18269,7 @@ void test_vst4q_f32(float32_t * a, float32x4x4_t b) {
// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x16x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x16x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 64, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL]], i32 0, i32 0
// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16
@@ -18611,7 +18296,7 @@ void test_vst4q_p8(poly8_t * a, poly8x16x4_t b) {
// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly16x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 64, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL]], i32 0, i32 0
@@ -18647,7 +18332,7 @@ void test_vst4q_p16(poly16_t * a, poly16x8x4_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 32, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL]], i32 0, i32 0
// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -18674,7 +18359,7 @@ void test_vst4_u8(uint8_t * a, uint8x8x4_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint16x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x4x4_t, %struct.uint16x4x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL]], i32 0, i32 0
@@ -18710,7 +18395,7 @@ void test_vst4_u16(uint16_t * a, uint16x4x4_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x2x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint32x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x2x4_t, %struct.uint32x2x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL]], i32 0, i32 0
@@ -18746,7 +18431,7 @@ void test_vst4_u32(uint32_t * a, uint32x2x4_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x1x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint64x1x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x1x4_t, %struct.uint64x1x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL]], i32 0, i32 0
@@ -18782,7 +18467,7 @@ void test_vst4_u64(uint64_t * a, uint64x1x4_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 32, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x8x4_t, %struct.int8x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL]], i32 0, i32 0
// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -18809,7 +18494,7 @@ void test_vst4_s8(int8_t * a, int8x8x4_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int16x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x4x4_t, %struct.int16x4x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL]], i32 0, i32 0
@@ -18845,7 +18530,7 @@ void test_vst4_s16(int16_t * a, int16x4x4_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x2x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int32x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x2x4_t, %struct.int32x2x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL]], i32 0, i32 0
@@ -18881,7 +18566,7 @@ void test_vst4_s32(int32_t * a, int32x2x4_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x1x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int64x1x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x1x4_t, %struct.int64x1x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL]], i32 0, i32 0
@@ -18917,7 +18602,7 @@ void test_vst4_s64(int64_t * a, int64x1x4_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float16x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x4x4_t, %struct.float16x4x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x half>], [4 x <4 x half>]* [[VAL]], i32 0, i32 0
@@ -18953,7 +18638,7 @@ void test_vst4_f16(float16_t * a, float16x4x4_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x2x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float32x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x2x4_t, %struct.float32x2x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x float>], [4 x <2 x float>]* [[VAL]], i32 0, i32 0
@@ -18989,7 +18674,7 @@ void test_vst4_f32(float32_t * a, float32x2x4_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 32, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL]], i32 0, i32 0
// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -19016,7 +18701,7 @@ void test_vst4_p8(poly8_t * a, poly8x8x4_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly16x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x4x4_t, %struct.poly16x4x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL]], i32 0, i32 0
@@ -19052,7 +18737,7 @@ void test_vst4_p16(poly16_t * a, poly16x4x4_t b) {
// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint16x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 64, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL]], i32 0, i32 0
@@ -19088,7 +18773,7 @@ void test_vst4q_lane_u16(uint16_t * a, uint16x8x4_t b) {
// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint32x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 64, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL]], i32 0, i32 0
@@ -19124,7 +18809,7 @@ void test_vst4q_lane_u32(uint32_t * a, uint32x4x4_t b) {
// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int16x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 64, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL]], i32 0, i32 0
@@ -19160,7 +18845,7 @@ void test_vst4q_lane_s16(int16_t * a, int16x8x4_t b) {
// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int32x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 64, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL]], i32 0, i32 0
@@ -19196,7 +18881,7 @@ void test_vst4q_lane_s32(int32_t * a, int32x4x4_t b) {
// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float16x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 64, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL]], i32 0, i32 0
@@ -19232,7 +18917,7 @@ void test_vst4q_lane_f16(float16_t * a, float16x8x4_t b) {
// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float32x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 64, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x float>], [4 x <4 x float>]* [[VAL]], i32 0, i32 0
@@ -19268,7 +18953,7 @@ void test_vst4q_lane_f32(float32_t * a, float32x4x4_t b) {
// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly16x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 [[TMP1]], i8* align 16 [[TMP2]], i32 64, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL]], i32 0, i32 0
@@ -19304,7 +18989,7 @@ void test_vst4q_lane_p16(poly16_t * a, poly16x8x4_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 32, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL]], i32 0, i32 0
// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -19331,7 +19016,7 @@ void test_vst4_lane_u8(uint8_t * a, uint8x8x4_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint16x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x4x4_t, %struct.uint16x4x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL]], i32 0, i32 0
@@ -19367,7 +19052,7 @@ void test_vst4_lane_u16(uint16_t * a, uint16x4x4_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x2x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.uint32x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x2x4_t, %struct.uint32x2x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL]], i32 0, i32 0
@@ -19403,7 +19088,7 @@ void test_vst4_lane_u32(uint32_t * a, uint32x2x4_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 32, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x8x4_t, %struct.int8x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL]], i32 0, i32 0
// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -19430,7 +19115,7 @@ void test_vst4_lane_s8(int8_t * a, int8x8x4_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int16x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x4x4_t, %struct.int16x4x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL]], i32 0, i32 0
@@ -19466,7 +19151,7 @@ void test_vst4_lane_s16(int16_t * a, int16x4x4_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x2x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.int32x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x2x4_t, %struct.int32x2x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL]], i32 0, i32 0
@@ -19502,7 +19187,7 @@ void test_vst4_lane_s32(int32_t * a, int32x2x4_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float16x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast half* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x4x4_t, %struct.float16x4x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x half>], [4 x <4 x half>]* [[VAL]], i32 0, i32 0
@@ -19538,7 +19223,7 @@ void test_vst4_lane_f16(float16_t * a, float16x4x4_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x2x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.float32x2x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast float* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x2x4_t, %struct.float32x2x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x float>], [4 x <2 x float>]* [[VAL]], i32 0, i32 0
@@ -19574,7 +19259,7 @@ void test_vst4_lane_f32(float32_t * a, float32x2x4_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x8x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x8x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 32, i1 false)
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL]], i32 0, i32 0
// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8
@@ -19601,7 +19286,7 @@ void test_vst4_lane_p8(poly8_t * a, poly8x8x4_t b) {
// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8
// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x4x4_t* [[__S1]] to i8*
// CHECK: [[TMP2:%.*]] = bitcast %struct.poly16x4x4_t* [[B]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP1]], i8* align 8 [[TMP2]], i32 32, i1 false)
// CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x4x4_t, %struct.poly16x4x4_t* [[__S1]], i32 0, i32 0
// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL]], i32 0, i32 0
@@ -20463,331 +20148,259 @@ poly8x8_t test_vtbx4_p8(poly8x8_t a, poly8x8x4_t b, uint8x8_t c) {
return vtbx4_p8(a, b, c);
}
-// CHECK-LABEL: @test_vtrn_s8(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrn_s8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14>
-// CHECK: store <8 x i8> [[VTRN_I]], <8 x i8>* [[TMP1]], !noalias !3
+// CHECK: store <8 x i8> [[VTRN_I]], <8 x i8>* [[TMP1]], !alias.scope !3
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
-// CHECK: store <8 x i8> [[VTRN1_I]], <8 x i8>* [[TMP2]], !noalias !3
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 16, i32 8, i1 false)
+// CHECK: store <8 x i8> [[VTRN1_I]], <8 x i8>* [[TMP2]], !alias.scope !3
// CHECK: ret void
int8x8x2_t test_vtrn_s8(int8x8_t a, int8x8_t b) {
return vtrn_s8(a, b);
}
-// CHECK-LABEL: @test_vtrn_s16(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrn_s16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 0, i32 4, i32 2, i32 6>
-// CHECK: store <4 x i16> [[VTRN_I]], <4 x i16>* [[TMP3]], !noalias !6
+// CHECK: store <4 x i16> [[VTRN_I]], <4 x i16>* [[TMP3]], !alias.scope !6
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
-// CHECK: store <4 x i16> [[VTRN1_I]], <4 x i16>* [[TMP4]], !noalias !6
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 16, i32 8, i1 false)
+// CHECK: store <4 x i16> [[VTRN1_I]], <4 x i16>* [[TMP4]], !alias.scope !6
// CHECK: ret void
int16x4x2_t test_vtrn_s16(int16x4_t a, int16x4_t b) {
return vtrn_s16(a, b);
}
-// CHECK-LABEL: @test_vtrn_s32(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrn_s32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x i32>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 0, i32 2>
-// CHECK: store <2 x i32> [[VTRN_I]], <2 x i32>* [[TMP3]], !noalias !9
+// CHECK: store <2 x i32> [[VTRN_I]], <2 x i32>* [[TMP3]], !alias.scope !9
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x i32> [[VTRN1_I]], <2 x i32>* [[TMP4]], !noalias !9
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 16, i32 8, i1 false)
+// CHECK: store <2 x i32> [[VTRN1_I]], <2 x i32>* [[TMP4]], !alias.scope !9
// CHECK: ret void
int32x2x2_t test_vtrn_s32(int32x2_t a, int32x2_t b) {
return vtrn_s32(a, b);
}
-// CHECK-LABEL: @test_vtrn_u8(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrn_u8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14>
-// CHECK: store <8 x i8> [[VTRN_I]], <8 x i8>* [[TMP1]], !noalias !12
+// CHECK: store <8 x i8> [[VTRN_I]], <8 x i8>* [[TMP1]], !alias.scope !12
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
-// CHECK: store <8 x i8> [[VTRN1_I]], <8 x i8>* [[TMP2]], !noalias !12
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 16, i32 8, i1 false)
+// CHECK: store <8 x i8> [[VTRN1_I]], <8 x i8>* [[TMP2]], !alias.scope !12
// CHECK: ret void
uint8x8x2_t test_vtrn_u8(uint8x8_t a, uint8x8_t b) {
return vtrn_u8(a, b);
}
-// CHECK-LABEL: @test_vtrn_u16(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrn_u16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 0, i32 4, i32 2, i32 6>
-// CHECK: store <4 x i16> [[VTRN_I]], <4 x i16>* [[TMP3]], !noalias !15
+// CHECK: store <4 x i16> [[VTRN_I]], <4 x i16>* [[TMP3]], !alias.scope !15
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
-// CHECK: store <4 x i16> [[VTRN1_I]], <4 x i16>* [[TMP4]], !noalias !15
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 16, i32 8, i1 false)
+// CHECK: store <4 x i16> [[VTRN1_I]], <4 x i16>* [[TMP4]], !alias.scope !15
// CHECK: ret void
uint16x4x2_t test_vtrn_u16(uint16x4_t a, uint16x4_t b) {
return vtrn_u16(a, b);
}
-// CHECK-LABEL: @test_vtrn_u32(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrn_u32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x i32>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 0, i32 2>
-// CHECK: store <2 x i32> [[VTRN_I]], <2 x i32>* [[TMP3]], !noalias !18
+// CHECK: store <2 x i32> [[VTRN_I]], <2 x i32>* [[TMP3]], !alias.scope !18
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x i32> [[VTRN1_I]], <2 x i32>* [[TMP4]], !noalias !18
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 16, i32 8, i1 false)
+// CHECK: store <2 x i32> [[VTRN1_I]], <2 x i32>* [[TMP4]], !alias.scope !18
// CHECK: ret void
uint32x2x2_t test_vtrn_u32(uint32x2_t a, uint32x2_t b) {
return vtrn_u32(a, b);
}
-// CHECK-LABEL: @test_vtrn_f32(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.float32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrn_f32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x float> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x float>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <2 x float> %a, <2 x float> %b, <2 x i32> <i32 0, i32 2>
-// CHECK: store <2 x float> [[VTRN_I]], <2 x float>* [[TMP3]], !noalias !21
+// CHECK: store <2 x float> [[VTRN_I]], <2 x float>* [[TMP3]], !alias.scope !21
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x float>, <2 x float>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <2 x float> %a, <2 x float> %b, <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x float> [[VTRN1_I]], <2 x float>* [[TMP4]], !noalias !21
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.float32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 16, i32 8, i1 false)
+// CHECK: store <2 x float> [[VTRN1_I]], <2 x float>* [[TMP4]], !alias.scope !21
// CHECK: ret void
float32x2x2_t test_vtrn_f32(float32x2_t a, float32x2_t b) {
return vtrn_f32(a, b);
}
-// CHECK-LABEL: @test_vtrn_p8(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrn_p8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14>
-// CHECK: store <8 x i8> [[VTRN_I]], <8 x i8>* [[TMP1]], !noalias !24
+// CHECK: store <8 x i8> [[VTRN_I]], <8 x i8>* [[TMP1]], !alias.scope !24
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
-// CHECK: store <8 x i8> [[VTRN1_I]], <8 x i8>* [[TMP2]], !noalias !24
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 16, i32 8, i1 false)
+// CHECK: store <8 x i8> [[VTRN1_I]], <8 x i8>* [[TMP2]], !alias.scope !24
// CHECK: ret void
poly8x8x2_t test_vtrn_p8(poly8x8_t a, poly8x8_t b) {
return vtrn_p8(a, b);
}
-// CHECK-LABEL: @test_vtrn_p16(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrn_p16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 0, i32 4, i32 2, i32 6>
-// CHECK: store <4 x i16> [[VTRN_I]], <4 x i16>* [[TMP3]], !noalias !27
+// CHECK: store <4 x i16> [[VTRN_I]], <4 x i16>* [[TMP3]], !alias.scope !27
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
-// CHECK: store <4 x i16> [[VTRN1_I]], <4 x i16>* [[TMP4]], !noalias !27
-// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 16, i32 8, i1 false)
+// CHECK: store <4 x i16> [[VTRN1_I]], <4 x i16>* [[TMP4]], !alias.scope !27
// CHECK: ret void
poly16x4x2_t test_vtrn_p16(poly16x4_t a, poly16x4_t b) {
return vtrn_p16(a, b);
}
-// CHECK-LABEL: @test_vtrnq_s8(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrnq_s8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <16 x i8>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 0, i32 16, i32 2, i32 18, i32 4, i32 20, i32 6, i32 22, i32 8, i32 24, i32 10, i32 26, i32 12, i32 28, i32 14, i32 30>
-// CHECK: store <16 x i8> [[VTRN_I]], <16 x i8>* [[TMP1]], !noalias !30
+// CHECK: store <16 x i8> [[VTRN_I]], <16 x i8>* [[TMP1]], !alias.scope !30
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 1, i32 17, i32 3, i32 19, i32 5, i32 21, i32 7, i32 23, i32 9, i32 25, i32 11, i32 27, i32 13, i32 29, i32 15, i32 31>
-// CHECK: store <16 x i8> [[VTRN1_I]], <16 x i8>* [[TMP2]], !noalias !30
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int8x16x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 16, i1 false)
+// CHECK: store <16 x i8> [[VTRN1_I]], <16 x i8>* [[TMP2]], !alias.scope !30
// CHECK: ret void
int8x16x2_t test_vtrnq_s8(int8x16_t a, int8x16_t b) {
return vtrnq_s8(a, b);
}
-// CHECK-LABEL: @test_vtrnq_s16(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrnq_s16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14>
-// CHECK: store <8 x i16> [[VTRN_I]], <8 x i16>* [[TMP3]], !noalias !33
+// CHECK: store <8 x i16> [[VTRN_I]], <8 x i16>* [[TMP3]], !alias.scope !33
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
-// CHECK: store <8 x i16> [[VTRN1_I]], <8 x i16>* [[TMP4]], !noalias !33
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x8x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false)
+// CHECK: store <8 x i16> [[VTRN1_I]], <8 x i16>* [[TMP4]], !alias.scope !33
// CHECK: ret void
int16x8x2_t test_vtrnq_s16(int16x8_t a, int16x8_t b) {
return vtrnq_s16(a, b);
}
-// CHECK-LABEL: @test_vtrnq_s32(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int32x4x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrnq_s32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i32>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 0, i32 4, i32 2, i32 6>
-// CHECK: store <4 x i32> [[VTRN_I]], <4 x i32>* [[TMP3]], !noalias !36
+// CHECK: store <4 x i32> [[VTRN_I]], <4 x i32>* [[TMP3]], !alias.scope !36
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
-// CHECK: store <4 x i32> [[VTRN1_I]], <4 x i32>* [[TMP4]], !noalias !36
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x4x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false)
+// CHECK: store <4 x i32> [[VTRN1_I]], <4 x i32>* [[TMP4]], !alias.scope !36
// CHECK: ret void
int32x4x2_t test_vtrnq_s32(int32x4_t a, int32x4_t b) {
return vtrnq_s32(a, b);
}
-// CHECK-LABEL: @test_vtrnq_u8(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrnq_u8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <16 x i8>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 0, i32 16, i32 2, i32 18, i32 4, i32 20, i32 6, i32 22, i32 8, i32 24, i32 10, i32 26, i32 12, i32 28, i32 14, i32 30>
-// CHECK: store <16 x i8> [[VTRN_I]], <16 x i8>* [[TMP1]], !noalias !39
+// CHECK: store <16 x i8> [[VTRN_I]], <16 x i8>* [[TMP1]], !alias.scope !39
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 1, i32 17, i32 3, i32 19, i32 5, i32 21, i32 7, i32 23, i32 9, i32 25, i32 11, i32 27, i32 13, i32 29, i32 15, i32 31>
-// CHECK: store <16 x i8> [[VTRN1_I]], <16 x i8>* [[TMP2]], !noalias !39
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 16, i1 false)
+// CHECK: store <16 x i8> [[VTRN1_I]], <16 x i8>* [[TMP2]], !alias.scope !39
// CHECK: ret void
uint8x16x2_t test_vtrnq_u8(uint8x16_t a, uint8x16_t b) {
return vtrnq_u8(a, b);
}
-// CHECK-LABEL: @test_vtrnq_u16(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrnq_u16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14>
-// CHECK: store <8 x i16> [[VTRN_I]], <8 x i16>* [[TMP3]], !noalias !42
+// CHECK: store <8 x i16> [[VTRN_I]], <8 x i16>* [[TMP3]], !alias.scope !42
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
-// CHECK: store <8 x i16> [[VTRN1_I]], <8 x i16>* [[TMP4]], !noalias !42
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x8x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false)
+// CHECK: store <8 x i16> [[VTRN1_I]], <8 x i16>* [[TMP4]], !alias.scope !42
// CHECK: ret void
uint16x8x2_t test_vtrnq_u16(uint16x8_t a, uint16x8_t b) {
return vtrnq_u16(a, b);
}
-// CHECK-LABEL: @test_vtrnq_u32(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint32x4x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrnq_u32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i32>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 0, i32 4, i32 2, i32 6>
-// CHECK: store <4 x i32> [[VTRN_I]], <4 x i32>* [[TMP3]], !noalias !45
+// CHECK: store <4 x i32> [[VTRN_I]], <4 x i32>* [[TMP3]], !alias.scope !45
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
-// CHECK: store <4 x i32> [[VTRN1_I]], <4 x i32>* [[TMP4]], !noalias !45
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x4x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false)
+// CHECK: store <4 x i32> [[VTRN1_I]], <4 x i32>* [[TMP4]], !alias.scope !45
// CHECK: ret void
uint32x4x2_t test_vtrnq_u32(uint32x4_t a, uint32x4_t b) {
return vtrnq_u32(a, b);
}
-// CHECK-LABEL: @test_vtrnq_f32(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.float32x4x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrnq_f32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x float> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x float>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 0, i32 4, i32 2, i32 6>
-// CHECK: store <4 x float> [[VTRN_I]], <4 x float>* [[TMP3]], !noalias !48
+// CHECK: store <4 x float> [[VTRN_I]], <4 x float>* [[TMP3]], !alias.scope !48
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x float>, <4 x float>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
-// CHECK: store <4 x float> [[VTRN1_I]], <4 x float>* [[TMP4]], !noalias !48
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x4x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.float32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false)
+// CHECK: store <4 x float> [[VTRN1_I]], <4 x float>* [[TMP4]], !alias.scope !48
// CHECK: ret void
float32x4x2_t test_vtrnq_f32(float32x4_t a, float32x4_t b) {
return vtrnq_f32(a, b);
}
-// CHECK-LABEL: @test_vtrnq_p8(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrnq_p8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <16 x i8>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 0, i32 16, i32 2, i32 18, i32 4, i32 20, i32 6, i32 22, i32 8, i32 24, i32 10, i32 26, i32 12, i32 28, i32 14, i32 30>
-// CHECK: store <16 x i8> [[VTRN_I]], <16 x i8>* [[TMP1]], !noalias !51
+// CHECK: store <16 x i8> [[VTRN_I]], <16 x i8>* [[TMP1]], !alias.scope !51
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 1, i32 17, i32 3, i32 19, i32 5, i32 21, i32 7, i32 23, i32 9, i32 25, i32 11, i32 27, i32 13, i32 29, i32 15, i32 31>
-// CHECK: store <16 x i8> [[VTRN1_I]], <16 x i8>* [[TMP2]], !noalias !51
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 16, i1 false)
+// CHECK: store <16 x i8> [[VTRN1_I]], <16 x i8>* [[TMP2]], !alias.scope !51
// CHECK: ret void
poly8x16x2_t test_vtrnq_p8(poly8x16_t a, poly8x16_t b) {
return vtrnq_p8(a, b);
}
-// CHECK-LABEL: @test_vtrnq_p16(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrnq_p16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14>
-// CHECK: store <8 x i16> [[VTRN_I]], <8 x i16>* [[TMP3]], !noalias !54
+// CHECK: store <8 x i16> [[VTRN_I]], <8 x i16>* [[TMP3]], !alias.scope !54
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
-// CHECK: store <8 x i16> [[VTRN1_I]], <8 x i16>* [[TMP4]], !noalias !54
-// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x8x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false)
+// CHECK: store <8 x i16> [[VTRN1_I]], <8 x i16>* [[TMP4]], !alias.scope !54
// CHECK: ret void
poly16x8x2_t test_vtrnq_p16(poly16x8_t a, poly16x8_t b) {
return vtrnq_p16(a, b);
@@ -20957,661 +20570,517 @@ uint16x8_t test_vtstq_p16(poly16x8_t a, poly16x8_t b) {
return vtstq_p16(a, b);
}
-// CHECK-LABEL: @test_vuzp_s8(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzp_s8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
-// CHECK: store <8 x i8> [[VUZP_I]], <8 x i8>* [[TMP1]], !noalias !57
+// CHECK: store <8 x i8> [[VUZP_I]], <8 x i8>* [[TMP1]], !alias.scope !57
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
-// CHECK: store <8 x i8> [[VUZP1_I]], <8 x i8>* [[TMP2]], !noalias !57
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 16, i32 8, i1 false)
+// CHECK: store <8 x i8> [[VUZP1_I]], <8 x i8>* [[TMP2]], !alias.scope !57
// CHECK: ret void
int8x8x2_t test_vuzp_s8(int8x8_t a, int8x8_t b) {
return vuzp_s8(a, b);
}
-// CHECK-LABEL: @test_vuzp_s16(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzp_s16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
-// CHECK: store <4 x i16> [[VUZP_I]], <4 x i16>* [[TMP3]], !noalias !60
+// CHECK: store <4 x i16> [[VUZP_I]], <4 x i16>* [[TMP3]], !alias.scope !60
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
-// CHECK: store <4 x i16> [[VUZP1_I]], <4 x i16>* [[TMP4]], !noalias !60
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 16, i32 8, i1 false)
+// CHECK: store <4 x i16> [[VUZP1_I]], <4 x i16>* [[TMP4]], !alias.scope !60
// CHECK: ret void
int16x4x2_t test_vuzp_s16(int16x4_t a, int16x4_t b) {
return vuzp_s16(a, b);
}
-// CHECK-LABEL: @test_vuzp_s32(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzp_s32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x i32>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 0, i32 2>
-// CHECK: store <2 x i32> [[VUZP_I]], <2 x i32>* [[TMP3]], !noalias !63
+// CHECK: store <2 x i32> [[VUZP_I]], <2 x i32>* [[TMP3]], !alias.scope !63
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x i32> [[VUZP1_I]], <2 x i32>* [[TMP4]], !noalias !63
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 16, i32 8, i1 false)
+// CHECK: store <2 x i32> [[VUZP1_I]], <2 x i32>* [[TMP4]], !alias.scope !63
// CHECK: ret void
int32x2x2_t test_vuzp_s32(int32x2_t a, int32x2_t b) {
return vuzp_s32(a, b);
}
-// CHECK-LABEL: @test_vuzp_u8(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzp_u8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
-// CHECK: store <8 x i8> [[VUZP_I]], <8 x i8>* [[TMP1]], !noalias !66
+// CHECK: store <8 x i8> [[VUZP_I]], <8 x i8>* [[TMP1]], !alias.scope !66
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
-// CHECK: store <8 x i8> [[VUZP1_I]], <8 x i8>* [[TMP2]], !noalias !66
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 16, i32 8, i1 false)
+// CHECK: store <8 x i8> [[VUZP1_I]], <8 x i8>* [[TMP2]], !alias.scope !66
// CHECK: ret void
uint8x8x2_t test_vuzp_u8(uint8x8_t a, uint8x8_t b) {
return vuzp_u8(a, b);
}
-// CHECK-LABEL: @test_vuzp_u16(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzp_u16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
-// CHECK: store <4 x i16> [[VUZP_I]], <4 x i16>* [[TMP3]], !noalias !69
+// CHECK: store <4 x i16> [[VUZP_I]], <4 x i16>* [[TMP3]], !alias.scope !69
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
-// CHECK: store <4 x i16> [[VUZP1_I]], <4 x i16>* [[TMP4]], !noalias !69
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 16, i32 8, i1 false)
+// CHECK: store <4 x i16> [[VUZP1_I]], <4 x i16>* [[TMP4]], !alias.scope !69
// CHECK: ret void
uint16x4x2_t test_vuzp_u16(uint16x4_t a, uint16x4_t b) {
return vuzp_u16(a, b);
}
-// CHECK-LABEL: @test_vuzp_u32(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzp_u32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x i32>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 0, i32 2>
-// CHECK: store <2 x i32> [[VUZP_I]], <2 x i32>* [[TMP3]], !noalias !72
+// CHECK: store <2 x i32> [[VUZP_I]], <2 x i32>* [[TMP3]], !alias.scope !72
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x i32> [[VUZP1_I]], <2 x i32>* [[TMP4]], !noalias !72
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 16, i32 8, i1 false)
+// CHECK: store <2 x i32> [[VUZP1_I]], <2 x i32>* [[TMP4]], !alias.scope !72
// CHECK: ret void
uint32x2x2_t test_vuzp_u32(uint32x2_t a, uint32x2_t b) {
return vuzp_u32(a, b);
}
-// CHECK-LABEL: @test_vuzp_f32(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.float32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzp_f32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x float> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x float>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <2 x float> %a, <2 x float> %b, <2 x i32> <i32 0, i32 2>
-// CHECK: store <2 x float> [[VUZP_I]], <2 x float>* [[TMP3]], !noalias !75
+// CHECK: store <2 x float> [[VUZP_I]], <2 x float>* [[TMP3]], !alias.scope !75
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x float>, <2 x float>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <2 x float> %a, <2 x float> %b, <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x float> [[VUZP1_I]], <2 x float>* [[TMP4]], !noalias !75
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.float32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 16, i32 8, i1 false)
+// CHECK: store <2 x float> [[VUZP1_I]], <2 x float>* [[TMP4]], !alias.scope !75
// CHECK: ret void
float32x2x2_t test_vuzp_f32(float32x2_t a, float32x2_t b) {
return vuzp_f32(a, b);
}
-// CHECK-LABEL: @test_vuzp_p8(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzp_p8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
-// CHECK: store <8 x i8> [[VUZP_I]], <8 x i8>* [[TMP1]], !noalias !78
+// CHECK: store <8 x i8> [[VUZP_I]], <8 x i8>* [[TMP1]], !alias.scope !78
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
-// CHECK: store <8 x i8> [[VUZP1_I]], <8 x i8>* [[TMP2]], !noalias !78
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 16, i32 8, i1 false)
+// CHECK: store <8 x i8> [[VUZP1_I]], <8 x i8>* [[TMP2]], !alias.scope !78
// CHECK: ret void
poly8x8x2_t test_vuzp_p8(poly8x8_t a, poly8x8_t b) {
return vuzp_p8(a, b);
}
-// CHECK-LABEL: @test_vuzp_p16(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzp_p16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
-// CHECK: store <4 x i16> [[VUZP_I]], <4 x i16>* [[TMP3]], !noalias !81
+// CHECK: store <4 x i16> [[VUZP_I]], <4 x i16>* [[TMP3]], !alias.scope !81
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
-// CHECK: store <4 x i16> [[VUZP1_I]], <4 x i16>* [[TMP4]], !noalias !81
-// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 16, i32 8, i1 false)
+// CHECK: store <4 x i16> [[VUZP1_I]], <4 x i16>* [[TMP4]], !alias.scope !81
// CHECK: ret void
poly16x4x2_t test_vuzp_p16(poly16x4_t a, poly16x4_t b) {
return vuzp_p16(a, b);
}
-// CHECK-LABEL: @test_vuzpq_s8(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzpq_s8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <16 x i8>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14, i32 16, i32 18, i32 20, i32 22, i32 24, i32 26, i32 28, i32 30>
-// CHECK: store <16 x i8> [[VUZP_I]], <16 x i8>* [[TMP1]], !noalias !84
+// CHECK: store <16 x i8> [[VUZP_I]], <16 x i8>* [[TMP1]], !alias.scope !84
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15, i32 17, i32 19, i32 21, i32 23, i32 25, i32 27, i32 29, i32 31>
-// CHECK: store <16 x i8> [[VUZP1_I]], <16 x i8>* [[TMP2]], !noalias !84
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int8x16x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 16, i1 false)
+// CHECK: store <16 x i8> [[VUZP1_I]], <16 x i8>* [[TMP2]], !alias.scope !84
// CHECK: ret void
int8x16x2_t test_vuzpq_s8(int8x16_t a, int8x16_t b) {
return vuzpq_s8(a, b);
}
-// CHECK-LABEL: @test_vuzpq_s16(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzpq_s16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
-// CHECK: store <8 x i16> [[VUZP_I]], <8 x i16>* [[TMP3]], !noalias !87
+// CHECK: store <8 x i16> [[VUZP_I]], <8 x i16>* [[TMP3]], !alias.scope !87
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
-// CHECK: store <8 x i16> [[VUZP1_I]], <8 x i16>* [[TMP4]], !noalias !87
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x8x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false)
+// CHECK: store <8 x i16> [[VUZP1_I]], <8 x i16>* [[TMP4]], !alias.scope !87
// CHECK: ret void
int16x8x2_t test_vuzpq_s16(int16x8_t a, int16x8_t b) {
return vuzpq_s16(a, b);
}
-// CHECK-LABEL: @test_vuzpq_s32(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int32x4x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzpq_s32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i32>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
-// CHECK: store <4 x i32> [[VUZP_I]], <4 x i32>* [[TMP3]], !noalias !90
+// CHECK: store <4 x i32> [[VUZP_I]], <4 x i32>* [[TMP3]], !alias.scope !90
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
-// CHECK: store <4 x i32> [[VUZP1_I]], <4 x i32>* [[TMP4]], !noalias !90
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x4x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false)
+// CHECK: store <4 x i32> [[VUZP1_I]], <4 x i32>* [[TMP4]], !alias.scope !90
// CHECK: ret void
int32x4x2_t test_vuzpq_s32(int32x4_t a, int32x4_t b) {
return vuzpq_s32(a, b);
}
-// CHECK-LABEL: @test_vuzpq_u8(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzpq_u8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <16 x i8>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14, i32 16, i32 18, i32 20, i32 22, i32 24, i32 26, i32 28, i32 30>
-// CHECK: store <16 x i8> [[VUZP_I]], <16 x i8>* [[TMP1]], !noalias !93
+// CHECK: store <16 x i8> [[VUZP_I]], <16 x i8>* [[TMP1]], !alias.scope !93
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15, i32 17, i32 19, i32 21, i32 23, i32 25, i32 27, i32 29, i32 31>
-// CHECK: store <16 x i8> [[VUZP1_I]], <16 x i8>* [[TMP2]], !noalias !93
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 16, i1 false)
+// CHECK: store <16 x i8> [[VUZP1_I]], <16 x i8>* [[TMP2]], !alias.scope !93
// CHECK: ret void
uint8x16x2_t test_vuzpq_u8(uint8x16_t a, uint8x16_t b) {
return vuzpq_u8(a, b);
}
-// CHECK-LABEL: @test_vuzpq_u16(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzpq_u16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
-// CHECK: store <8 x i16> [[VUZP_I]], <8 x i16>* [[TMP3]], !noalias !96
+// CHECK: store <8 x i16> [[VUZP_I]], <8 x i16>* [[TMP3]], !alias.scope !96
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
-// CHECK: store <8 x i16> [[VUZP1_I]], <8 x i16>* [[TMP4]], !noalias !96
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x8x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false)
+// CHECK: store <8 x i16> [[VUZP1_I]], <8 x i16>* [[TMP4]], !alias.scope !96
// CHECK: ret void
uint16x8x2_t test_vuzpq_u16(uint16x8_t a, uint16x8_t b) {
return vuzpq_u16(a, b);
}
-// CHECK-LABEL: @test_vuzpq_u32(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint32x4x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzpq_u32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i32>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
-// CHECK: store <4 x i32> [[VUZP_I]], <4 x i32>* [[TMP3]], !noalias !99
+// CHECK: store <4 x i32> [[VUZP_I]], <4 x i32>* [[TMP3]], !alias.scope !99
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
-// CHECK: store <4 x i32> [[VUZP1_I]], <4 x i32>* [[TMP4]], !noalias !99
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x4x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false)
+// CHECK: store <4 x i32> [[VUZP1_I]], <4 x i32>* [[TMP4]], !alias.scope !99
// CHECK: ret void
uint32x4x2_t test_vuzpq_u32(uint32x4_t a, uint32x4_t b) {
return vuzpq_u32(a, b);
}
-// CHECK-LABEL: @test_vuzpq_f32(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.float32x4x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzpq_f32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x float> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x float>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
-// CHECK: store <4 x float> [[VUZP_I]], <4 x float>* [[TMP3]], !noalias !102
+// CHECK: store <4 x float> [[VUZP_I]], <4 x float>* [[TMP3]], !alias.scope !102
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x float>, <4 x float>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
-// CHECK: store <4 x float> [[VUZP1_I]], <4 x float>* [[TMP4]], !noalias !102
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x4x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.float32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false)
+// CHECK: store <4 x float> [[VUZP1_I]], <4 x float>* [[TMP4]], !alias.scope !102
// CHECK: ret void
float32x4x2_t test_vuzpq_f32(float32x4_t a, float32x4_t b) {
return vuzpq_f32(a, b);
}
-// CHECK-LABEL: @test_vuzpq_p8(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzpq_p8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <16 x i8>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14, i32 16, i32 18, i32 20, i32 22, i32 24, i32 26, i32 28, i32 30>
-// CHECK: store <16 x i8> [[VUZP_I]], <16 x i8>* [[TMP1]], !noalias !105
+// CHECK: store <16 x i8> [[VUZP_I]], <16 x i8>* [[TMP1]], !alias.scope !105
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15, i32 17, i32 19, i32 21, i32 23, i32 25, i32 27, i32 29, i32 31>
-// CHECK: store <16 x i8> [[VUZP1_I]], <16 x i8>* [[TMP2]], !noalias !105
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 16, i1 false)
+// CHECK: store <16 x i8> [[VUZP1_I]], <16 x i8>* [[TMP2]], !alias.scope !105
// CHECK: ret void
poly8x16x2_t test_vuzpq_p8(poly8x16_t a, poly8x16_t b) {
return vuzpq_p8(a, b);
}
-// CHECK-LABEL: @test_vuzpq_p16(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzpq_p16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
-// CHECK: store <8 x i16> [[VUZP_I]], <8 x i16>* [[TMP3]], !noalias !108
+// CHECK: store <8 x i16> [[VUZP_I]], <8 x i16>* [[TMP3]], !alias.scope !108
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
-// CHECK: store <8 x i16> [[VUZP1_I]], <8 x i16>* [[TMP4]], !noalias !108
-// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x8x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false)
+// CHECK: store <8 x i16> [[VUZP1_I]], <8 x i16>* [[TMP4]], !alias.scope !108
// CHECK: ret void
poly16x8x2_t test_vuzpq_p16(poly16x8_t a, poly16x8_t b) {
return vuzpq_p16(a, b);
}
-// CHECK-LABEL: @test_vzip_s8(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzip_s8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
-// CHECK: store <8 x i8> [[VZIP_I]], <8 x i8>* [[TMP1]], !noalias !111
+// CHECK: store <8 x i8> [[VZIP_I]], <8 x i8>* [[TMP1]], !alias.scope !111
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
-// CHECK: store <8 x i8> [[VZIP1_I]], <8 x i8>* [[TMP2]], !noalias !111
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 16, i32 8, i1 false)
+// CHECK: store <8 x i8> [[VZIP1_I]], <8 x i8>* [[TMP2]], !alias.scope !111
// CHECK: ret void
int8x8x2_t test_vzip_s8(int8x8_t a, int8x8_t b) {
return vzip_s8(a, b);
}
-// CHECK-LABEL: @test_vzip_s16(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzip_s16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 0, i32 4, i32 1, i32 5>
-// CHECK: store <4 x i16> [[VZIP_I]], <4 x i16>* [[TMP3]], !noalias !114
+// CHECK: store <4 x i16> [[VZIP_I]], <4 x i16>* [[TMP3]], !alias.scope !114
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
-// CHECK: store <4 x i16> [[VZIP1_I]], <4 x i16>* [[TMP4]], !noalias !114
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 16, i32 8, i1 false)
+// CHECK: store <4 x i16> [[VZIP1_I]], <4 x i16>* [[TMP4]], !alias.scope !114
// CHECK: ret void
int16x4x2_t test_vzip_s16(int16x4_t a, int16x4_t b) {
return vzip_s16(a, b);
}
-// CHECK-LABEL: @test_vzip_s32(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzip_s32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x i32>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 0, i32 2>
-// CHECK: store <2 x i32> [[VZIP_I]], <2 x i32>* [[TMP3]], !noalias !117
+// CHECK: store <2 x i32> [[VZIP_I]], <2 x i32>* [[TMP3]], !alias.scope !117
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x i32> [[VZIP1_I]], <2 x i32>* [[TMP4]], !noalias !117
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 16, i32 8, i1 false)
+// CHECK: store <2 x i32> [[VZIP1_I]], <2 x i32>* [[TMP4]], !alias.scope !117
// CHECK: ret void
int32x2x2_t test_vzip_s32(int32x2_t a, int32x2_t b) {
return vzip_s32(a, b);
}
-// CHECK-LABEL: @test_vzip_u8(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzip_u8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
-// CHECK: store <8 x i8> [[VZIP_I]], <8 x i8>* [[TMP1]], !noalias !120
+// CHECK: store <8 x i8> [[VZIP_I]], <8 x i8>* [[TMP1]], !alias.scope !120
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
-// CHECK: store <8 x i8> [[VZIP1_I]], <8 x i8>* [[TMP2]], !noalias !120
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 16, i32 8, i1 false)
+// CHECK: store <8 x i8> [[VZIP1_I]], <8 x i8>* [[TMP2]], !alias.scope !120
// CHECK: ret void
uint8x8x2_t test_vzip_u8(uint8x8_t a, uint8x8_t b) {
return vzip_u8(a, b);
}
-// CHECK-LABEL: @test_vzip_u16(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzip_u16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 0, i32 4, i32 1, i32 5>
-// CHECK: store <4 x i16> [[VZIP_I]], <4 x i16>* [[TMP3]], !noalias !123
+// CHECK: store <4 x i16> [[VZIP_I]], <4 x i16>* [[TMP3]], !alias.scope !123
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
-// CHECK: store <4 x i16> [[VZIP1_I]], <4 x i16>* [[TMP4]], !noalias !123
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 16, i32 8, i1 false)
+// CHECK: store <4 x i16> [[VZIP1_I]], <4 x i16>* [[TMP4]], !alias.scope !123
// CHECK: ret void
uint16x4x2_t test_vzip_u16(uint16x4_t a, uint16x4_t b) {
return vzip_u16(a, b);
}
-// CHECK-LABEL: @test_vzip_u32(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzip_u32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x i32>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 0, i32 2>
-// CHECK: store <2 x i32> [[VZIP_I]], <2 x i32>* [[TMP3]], !noalias !126
+// CHECK: store <2 x i32> [[VZIP_I]], <2 x i32>* [[TMP3]], !alias.scope !126
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x i32> [[VZIP1_I]], <2 x i32>* [[TMP4]], !noalias !126
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 16, i32 8, i1 false)
+// CHECK: store <2 x i32> [[VZIP1_I]], <2 x i32>* [[TMP4]], !alias.scope !126
// CHECK: ret void
uint32x2x2_t test_vzip_u32(uint32x2_t a, uint32x2_t b) {
return vzip_u32(a, b);
}
-// CHECK-LABEL: @test_vzip_f32(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.float32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzip_f32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x float> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x float>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <2 x float> %a, <2 x float> %b, <2 x i32> <i32 0, i32 2>
-// CHECK: store <2 x float> [[VZIP_I]], <2 x float>* [[TMP3]], !noalias !129
+// CHECK: store <2 x float> [[VZIP_I]], <2 x float>* [[TMP3]], !alias.scope !129
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x float>, <2 x float>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <2 x float> %a, <2 x float> %b, <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x float> [[VZIP1_I]], <2 x float>* [[TMP4]], !noalias !129
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.float32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 16, i32 8, i1 false)
+// CHECK: store <2 x float> [[VZIP1_I]], <2 x float>* [[TMP4]], !alias.scope !129
// CHECK: ret void
float32x2x2_t test_vzip_f32(float32x2_t a, float32x2_t b) {
return vzip_f32(a, b);
}
-// CHECK-LABEL: @test_vzip_p8(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzip_p8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
-// CHECK: store <8 x i8> [[VZIP_I]], <8 x i8>* [[TMP1]], !noalias !132
+// CHECK: store <8 x i8> [[VZIP_I]], <8 x i8>* [[TMP1]], !alias.scope !132
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
-// CHECK: store <8 x i8> [[VZIP1_I]], <8 x i8>* [[TMP2]], !noalias !132
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 16, i32 8, i1 false)
+// CHECK: store <8 x i8> [[VZIP1_I]], <8 x i8>* [[TMP2]], !alias.scope !132
// CHECK: ret void
poly8x8x2_t test_vzip_p8(poly8x8_t a, poly8x8_t b) {
return vzip_p8(a, b);
}
-// CHECK-LABEL: @test_vzip_p16(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzip_p16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 0, i32 4, i32 1, i32 5>
-// CHECK: store <4 x i16> [[VZIP_I]], <4 x i16>* [[TMP3]], !noalias !135
+// CHECK: store <4 x i16> [[VZIP_I]], <4 x i16>* [[TMP3]], !alias.scope !135
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
-// CHECK: store <4 x i16> [[VZIP1_I]], <4 x i16>* [[TMP4]], !noalias !135
-// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 16, i32 8, i1 false)
+// CHECK: store <4 x i16> [[VZIP1_I]], <4 x i16>* [[TMP4]], !alias.scope !135
// CHECK: ret void
poly16x4x2_t test_vzip_p16(poly16x4_t a, poly16x4_t b) {
return vzip_p16(a, b);
}
-// CHECK-LABEL: @test_vzipq_s8(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzipq_s8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <16 x i8>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 0, i32 16, i32 1, i32 17, i32 2, i32 18, i32 3, i32 19, i32 4, i32 20, i32 5, i32 21, i32 6, i32 22, i32 7, i32 23>
-// CHECK: store <16 x i8> [[VZIP_I]], <16 x i8>* [[TMP1]], !noalias !138
+// CHECK: store <16 x i8> [[VZIP_I]], <16 x i8>* [[TMP1]], !alias.scope !138
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 8, i32 24, i32 9, i32 25, i32 10, i32 26, i32 11, i32 27, i32 12, i32 28, i32 13, i32 29, i32 14, i32 30, i32 15, i32 31>
-// CHECK: store <16 x i8> [[VZIP1_I]], <16 x i8>* [[TMP2]], !noalias !138
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int8x16x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 16, i1 false)
+// CHECK: store <16 x i8> [[VZIP1_I]], <16 x i8>* [[TMP2]], !alias.scope !138
// CHECK: ret void
int8x16x2_t test_vzipq_s8(int8x16_t a, int8x16_t b) {
return vzipq_s8(a, b);
}
-// CHECK-LABEL: @test_vzipq_s16(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzipq_s16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
-// CHECK: store <8 x i16> [[VZIP_I]], <8 x i16>* [[TMP3]], !noalias !141
+// CHECK: store <8 x i16> [[VZIP_I]], <8 x i16>* [[TMP3]], !alias.scope !141
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
-// CHECK: store <8 x i16> [[VZIP1_I]], <8 x i16>* [[TMP4]], !noalias !141
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x8x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false)
+// CHECK: store <8 x i16> [[VZIP1_I]], <8 x i16>* [[TMP4]], !alias.scope !141
// CHECK: ret void
int16x8x2_t test_vzipq_s16(int16x8_t a, int16x8_t b) {
return vzipq_s16(a, b);
}
-// CHECK-LABEL: @test_vzipq_s32(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int32x4x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzipq_s32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i32>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 0, i32 4, i32 1, i32 5>
-// CHECK: store <4 x i32> [[VZIP_I]], <4 x i32>* [[TMP3]], !noalias !144
+// CHECK: store <4 x i32> [[VZIP_I]], <4 x i32>* [[TMP3]], !alias.scope !144
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
-// CHECK: store <4 x i32> [[VZIP1_I]], <4 x i32>* [[TMP4]], !noalias !144
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x4x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false)
+// CHECK: store <4 x i32> [[VZIP1_I]], <4 x i32>* [[TMP4]], !alias.scope !144
// CHECK: ret void
int32x4x2_t test_vzipq_s32(int32x4_t a, int32x4_t b) {
return vzipq_s32(a, b);
}
-// CHECK-LABEL: @test_vzipq_u8(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzipq_u8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <16 x i8>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 0, i32 16, i32 1, i32 17, i32 2, i32 18, i32 3, i32 19, i32 4, i32 20, i32 5, i32 21, i32 6, i32 22, i32 7, i32 23>
-// CHECK: store <16 x i8> [[VZIP_I]], <16 x i8>* [[TMP1]], !noalias !147
+// CHECK: store <16 x i8> [[VZIP_I]], <16 x i8>* [[TMP1]], !alias.scope !147
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 8, i32 24, i32 9, i32 25, i32 10, i32 26, i32 11, i32 27, i32 12, i32 28, i32 13, i32 29, i32 14, i32 30, i32 15, i32 31>
-// CHECK: store <16 x i8> [[VZIP1_I]], <16 x i8>* [[TMP2]], !noalias !147
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 16, i1 false)
+// CHECK: store <16 x i8> [[VZIP1_I]], <16 x i8>* [[TMP2]], !alias.scope !147
// CHECK: ret void
uint8x16x2_t test_vzipq_u8(uint8x16_t a, uint8x16_t b) {
return vzipq_u8(a, b);
}
-// CHECK-LABEL: @test_vzipq_u16(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzipq_u16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
-// CHECK: store <8 x i16> [[VZIP_I]], <8 x i16>* [[TMP3]], !noalias !150
+// CHECK: store <8 x i16> [[VZIP_I]], <8 x i16>* [[TMP3]], !alias.scope !150
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
-// CHECK: store <8 x i16> [[VZIP1_I]], <8 x i16>* [[TMP4]], !noalias !150
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x8x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false)
+// CHECK: store <8 x i16> [[VZIP1_I]], <8 x i16>* [[TMP4]], !alias.scope !150
// CHECK: ret void
uint16x8x2_t test_vzipq_u16(uint16x8_t a, uint16x8_t b) {
return vzipq_u16(a, b);
}
-// CHECK-LABEL: @test_vzipq_u32(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint32x4x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzipq_u32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i32>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 0, i32 4, i32 1, i32 5>
-// CHECK: store <4 x i32> [[VZIP_I]], <4 x i32>* [[TMP3]], !noalias !153
+// CHECK: store <4 x i32> [[VZIP_I]], <4 x i32>* [[TMP3]], !alias.scope !153
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
-// CHECK: store <4 x i32> [[VZIP1_I]], <4 x i32>* [[TMP4]], !noalias !153
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x4x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false)
+// CHECK: store <4 x i32> [[VZIP1_I]], <4 x i32>* [[TMP4]], !alias.scope !153
// CHECK: ret void
uint32x4x2_t test_vzipq_u32(uint32x4_t a, uint32x4_t b) {
return vzipq_u32(a, b);
}
-// CHECK-LABEL: @test_vzipq_f32(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.float32x4x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzipq_f32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x float> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x float>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 0, i32 4, i32 1, i32 5>
-// CHECK: store <4 x float> [[VZIP_I]], <4 x float>* [[TMP3]], !noalias !156
+// CHECK: store <4 x float> [[VZIP_I]], <4 x float>* [[TMP3]], !alias.scope !156
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x float>, <4 x float>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
-// CHECK: store <4 x float> [[VZIP1_I]], <4 x float>* [[TMP4]], !noalias !156
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x4x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.float32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false)
+// CHECK: store <4 x float> [[VZIP1_I]], <4 x float>* [[TMP4]], !alias.scope !156
// CHECK: ret void
float32x4x2_t test_vzipq_f32(float32x4_t a, float32x4_t b) {
return vzipq_f32(a, b);
}
-// CHECK-LABEL: @test_vzipq_p8(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzipq_p8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <16 x i8>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 0, i32 16, i32 1, i32 17, i32 2, i32 18, i32 3, i32 19, i32 4, i32 20, i32 5, i32 21, i32 6, i32 22, i32 7, i32 23>
-// CHECK: store <16 x i8> [[VZIP_I]], <16 x i8>* [[TMP1]], !noalias !159
+// CHECK: store <16 x i8> [[VZIP_I]], <16 x i8>* [[TMP1]], !alias.scope !159
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 8, i32 24, i32 9, i32 25, i32 10, i32 26, i32 11, i32 27, i32 12, i32 28, i32 13, i32 29, i32 14, i32 30, i32 15, i32 31>
-// CHECK: store <16 x i8> [[VZIP1_I]], <16 x i8>* [[TMP2]], !noalias !159
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 16, i1 false)
+// CHECK: store <16 x i8> [[VZIP1_I]], <16 x i8>* [[TMP2]], !alias.scope !159
// CHECK: ret void
poly8x16x2_t test_vzipq_p8(poly8x16_t a, poly8x16_t b) {
return vzipq_p8(a, b);
}
-// CHECK-LABEL: @test_vzipq_p16(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzipq_p16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
-// CHECK: store <8 x i16> [[VZIP_I]], <8 x i16>* [[TMP3]], !noalias !162
+// CHECK: store <8 x i16> [[VZIP_I]], <8 x i16>* [[TMP3]], !alias.scope !162
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
-// CHECK: store <8 x i16> [[VZIP1_I]], <8 x i16>* [[TMP4]], !noalias !162
-// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x8x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false)
+// CHECK: store <8 x i16> [[VZIP1_I]], <8 x i16>* [[TMP4]], !alias.scope !162
// CHECK: ret void
poly16x8x2_t test_vzipq_p16(poly16x8_t a, poly16x8_t b) {
return vzipq_p16(a, b);
diff --git a/test/CodeGen/array-init.c b/test/CodeGen/array-init.c
new file mode 100644
index 000000000000..62e87edc2974
--- /dev/null
+++ b/test/CodeGen/array-init.c
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 %s -O0 -triple x86_64-unknown-linux-gnu -emit-llvm -o - | FileCheck -check-prefix=CHECK-NO-MERGE-CONSTANTS %s
+// RUN: %clang_cc1 %s -O0 -triple x86_64-unknown-linux-gnu -fmerge-all-constants -emit-llvm -o - | FileCheck -check-prefix=CHECK-MERGE-CONSTANTS %s
+
+// CHECK-NO-MERGE-CONSTANTS: @{{.*}}.a1 = private unnamed_addr constant [5 x i32] [i32 0, i32 1, i32 2, i32 0, i32 0]
+
+// CHECK-MERGE-CONSTANTS: @{{.*}}.a1 = internal constant [5 x i32] [i32 0, i32 1, i32 2, i32 0, i32 0]
+// CHECK-MERGE-CONSTANTS: @{{.*}}.a2 = internal constant [5 x i32] zeroinitializer
+// CHECK-MERGE-CONSTANTS: @{{.*}}.a3 = internal constant [5 x i32] zeroinitializer
+
+void testConstArrayInits(void)
+{
+ const int a1[5] = {0,1,2};
+ const int a2[5] = {0,0,0};
+ const int a3[5] = {0};
+}
diff --git a/test/CodeGen/artificial.c b/test/CodeGen/artificial.c
new file mode 100644
index 000000000000..5db6a6719454
--- /dev/null
+++ b/test/CodeGen/artificial.c
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -triple=x86_64-unknown-linux-gnu -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s
+
+extern void foo();
+// CHECK: !DISubprogram(name: "foo"
+// CHECK-SAME: flags: DIFlagArtificial
+inline void __attribute__((artificial)) foo() {}
+
+void baz() {
+ foo();
+}
diff --git a/test/CodeGen/asm-parser-info.S b/test/CodeGen/asm-parser-info.S
new file mode 100644
index 000000000000..62145c0a74d9
--- /dev/null
+++ b/test/CodeGen/asm-parser-info.S
@@ -0,0 +1,12 @@
+// REQUIRES: x86-registered-target
+// RUN: %clang --target=x86_64-unknown-linux-gnu -c %s -o /dev/null
+
+// Check that cc1as can use assembler info in object generation.
+.data
+
+foo:
+.if . - foo == 0
+ .byte 0xaa
+.else
+ .byte 0x00
+.endif
diff --git a/test/CodeGen/atomic-arm64.c b/test/CodeGen/atomic-arm64.c
index 5cae3d134984..0e79846085cf 100644
--- a/test/CodeGen/atomic-arm64.c
+++ b/test/CodeGen/atomic-arm64.c
@@ -65,7 +65,7 @@ void test3(pointer_pair_t pair) {
// CHECK: [[TEMP:%.*]] = alloca [[QUAD_T:%.*]], align 8
// CHECK-NEXT: [[T0:%.*]] = bitcast [[QUAD_T]]* [[TEMP]] to i8*
// CHECK-NEXT: [[T1:%.*]] = bitcast [[QUAD_T]]* {{%.*}} to i8*
-// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T0]], i8* [[T1]], i64 32, i32 8, i1 false)
+// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[T0]], i8* align 8 [[T1]], i64 32, i1 false)
// CHECK-NEXT: [[T0:%.*]] = bitcast [[QUAD_T]]* [[TEMP]] to i256*
// CHECK-NEXT: [[T1:%.*]] = bitcast i256* [[T0]] to i8*
// CHECK-NEXT: call void @__atomic_store(i64 32, i8* bitcast ([[QUAD_T]]* @a_pointer_quad to i8*), i8* [[T1]], i32 5)
diff --git a/test/CodeGen/atomic-ops.c b/test/CodeGen/atomic-ops.c
index 1ebb2baa1ac6..500939f6fd75 100644
--- a/test/CodeGen/atomic-ops.c
+++ b/test/CodeGen/atomic-ops.c
@@ -183,11 +183,23 @@ struct S {
double x;
};
+void implicit_store(_Atomic(struct S) *a, struct S s) {
+ // CHECK-LABEL: @implicit_store(
+ // CHECK: store atomic i64 %{{.*}}, i64* %{{.*}} seq_cst, align 8
+ *a = s;
+}
+
+struct S implicit_load(_Atomic(struct S) *a) {
+ // CHECK-LABEL: @implicit_load(
+ // CHECK: load atomic i64, i64* %{{.*}} seq_cst, align 8
+ return *a;
+}
+
struct S fd1(struct S *a) {
// CHECK-LABEL: @fd1
// CHECK: [[RETVAL:%.*]] = alloca %struct.S, align 4
- // CHECK: [[RET:%.*]] = alloca %struct.S, align 4
- // CHECK: [[CAST:%.*]] = bitcast %struct.S* [[RET]] to i64*
+ // CHECK: bitcast %struct.S* {{.*}} to i64*
+ // CHECK: [[CAST:%.*]] = bitcast %struct.S* [[RETVAL]] to i64*
// CHECK: [[CALL:%.*]] = call i64 @__atomic_load_8(
// CHECK: store i64 [[CALL]], i64* [[CAST]], align 4
struct S ret;
diff --git a/test/CodeGen/atomics-sema-alignment.c b/test/CodeGen/atomics-sema-alignment.c
new file mode 100644
index 000000000000..364743dd53f0
--- /dev/null
+++ b/test/CodeGen/atomics-sema-alignment.c
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -triple aarch64-linux-gnu %s -emit-llvm -o /dev/null -verify
+
+typedef struct {
+ int a, b;
+} IntPair;
+
+typedef struct {
+ long long a;
+} LongStruct;
+
+typedef int __attribute__((aligned(1))) unaligned_int;
+
+void func(IntPair *p) {
+ IntPair res;
+ __atomic_load(p, &res, 0); // expected-warning {{misaligned or large atomic operation may incur significant performance penalty}}
+ __atomic_store(p, &res, 0); // expected-warning {{misaligned or large atomic operation may incur significant performance penalty}}
+ __atomic_fetch_add((unaligned_int *)p, 1, 2); // expected-warning {{misaligned or large atomic operation may incur significant performance penalty}}
+ __atomic_fetch_sub((unaligned_int *)p, 1, 3); // expected-warning {{misaligned or large atomic operation may incur significant performance penalty}}
+}
+
+void func1(LongStruct *p) {
+ LongStruct res;
+ __atomic_load(p, &res, 0);
+ __atomic_store(p, &res, 0);
+ __atomic_fetch_add((int *)p, 1, 2);
+ __atomic_fetch_sub((int *)p, 1, 3);
+}
diff --git a/test/CodeGen/attr-cpuspecific.c b/test/CodeGen/attr-cpuspecific.c
new file mode 100644
index 000000000000..1b98b5dc9678
--- /dev/null
+++ b/test/CodeGen/attr-cpuspecific.c
@@ -0,0 +1,101 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s
+
+
+// Each called version should have an IFunc.
+// CHECK: @SingleVersion.ifunc = ifunc void (), void ()* ()* @SingleVersion.resolver
+// CHECK: @TwoVersions.ifunc = ifunc void (), void ()* ()* @TwoVersions.resolver
+// CHECK: @TwoVersionsSameAttr.ifunc = ifunc void (), void ()* ()* @TwoVersionsSameAttr.resolver
+// CHECK: @ThreeVersionsSameAttr.ifunc = ifunc void (), void ()* ()* @ThreeVersionsSameAttr.resolver
+
+__attribute__((cpu_specific(ivybridge)))
+void SingleVersion(void){}
+// CHECK: define void @SingleVersion.S() #[[S:[0-9]+]]
+
+__attribute__((cpu_specific(ivybridge)))
+void NotCalled(void){}
+// CHECK: define void @NotCalled.S() #[[S]]
+
+// Done before any of the implementations.
+__attribute__((cpu_dispatch(ivybridge, knl)))
+void TwoVersions(void);
+// CHECK: define void ()* @TwoVersions.resolver()
+// CHECK: call void @__cpu_indicator_init
+// CHECK: ret void ()* @TwoVersions.Z
+// CHECK: ret void ()* @TwoVersions.S
+// CHECK: call void @llvm.trap
+// CHECK: unreachable
+
+__attribute__((cpu_specific(ivybridge)))
+void TwoVersions(void){}
+// CHECK: define void @TwoVersions.S() #[[S]]
+
+__attribute__((cpu_specific(knl)))
+void TwoVersions(void){}
+// CHECK: define void @TwoVersions.Z() #[[K:[0-9]+]]
+
+__attribute__((cpu_specific(ivybridge, knl)))
+void TwoVersionsSameAttr(void){}
+// CHECK: define void @TwoVersionsSameAttr.S() #[[S]]
+// CHECK: define void @TwoVersionsSameAttr.Z() #[[K]]
+
+__attribute__((cpu_specific(atom, ivybridge, knl)))
+void ThreeVersionsSameAttr(void){}
+// CHECK: define void @ThreeVersionsSameAttr.O() #[[O:[0-9]+]]
+// CHECK: define void @ThreeVersionsSameAttr.S() #[[S]]
+// CHECK: define void @ThreeVersionsSameAttr.Z() #[[K]]
+
+void usages() {
+ SingleVersion();
+ // CHECK: @SingleVersion.ifunc()
+ TwoVersions();
+ // CHECK: @TwoVersions.ifunc()
+ TwoVersionsSameAttr();
+ // CHECK: @TwoVersionsSameAttr.ifunc()
+ ThreeVersionsSameAttr();
+ // CHECK: @ThreeVersionsSameAttr.ifunc()
+}
+
+// has an extra config to emit!
+__attribute__((cpu_dispatch(ivybridge, knl, atom)))
+void TwoVersionsSameAttr(void);
+// CHECK: define void ()* @TwoVersionsSameAttr.resolver()
+// CHECK: ret void ()* @TwoVersionsSameAttr.Z
+// CHECK: ret void ()* @TwoVersionsSameAttr.S
+// CHECK: ret void ()* @TwoVersionsSameAttr.O
+// CHECK: call void @llvm.trap
+// CHECK: unreachable
+
+__attribute__((cpu_dispatch(atom, ivybridge, knl)))
+void ThreeVersionsSameAttr(void){}
+// CHECK: define void ()* @ThreeVersionsSameAttr.resolver()
+// CHECK: call void @__cpu_indicator_init
+// CHECK: ret void ()* @ThreeVersionsSameAttr.Z
+// CHECK: ret void ()* @ThreeVersionsSameAttr.S
+// CHECK: ret void ()* @ThreeVersionsSameAttr.O
+// CHECK: call void @llvm.trap
+// CHECK: unreachable
+
+// No Cpu Specific options.
+__attribute__((cpu_dispatch(atom, ivybridge, knl)))
+void NoSpecifics(void);
+// CHECK: define void ()* @NoSpecifics.resolver()
+// CHECK: call void @__cpu_indicator_init
+// CHECK: ret void ()* @NoSpecifics.Z
+// CHECK: ret void ()* @NoSpecifics.S
+// CHECK: ret void ()* @NoSpecifics.O
+// CHECK: call void @llvm.trap
+// CHECK: unreachable
+
+__attribute__((cpu_dispatch(atom, generic, ivybridge, knl)))
+void HasGeneric(void);
+// CHECK: define void ()* @HasGeneric.resolver()
+// CHECK: call void @__cpu_indicator_init
+// CHECK: ret void ()* @HasGeneric.Z
+// CHECK: ret void ()* @HasGeneric.S
+// CHECK: ret void ()* @HasGeneric.O
+// CHECK: ret void ()* @HasGeneric.A
+// CHECK-NOT: call void @llvm.trap
+
+// CHECK: attributes #[[S]] = {{.*}}"target-features"="+avx,+cmov,+f16c,+mmx,+popcnt,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave"
+// CHECK: attributes #[[K]] = {{.*}}"target-features"="+adx,+avx,+avx2,+avx512cd,+avx512er,+avx512f,+avx512pf,+bmi,+cmov,+f16c,+fma,+lzcnt,+mmx,+movbe,+popcnt,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave"
+// CHECK: attributes #[[O]] = {{.*}}"target-features"="+cmov,+mmx,+movbe,+sse,+sse2,+sse3,+ssse3,+x87"
diff --git a/test/CodeGen/attr-target-mv-func-ptrs.c b/test/CodeGen/attr-target-mv-func-ptrs.c
new file mode 100644
index 000000000000..5df9a927cf8d
--- /dev/null
+++ b/test/CodeGen/attr-target-mv-func-ptrs.c
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s
+int __attribute__((target("sse4.2"))) foo(int i) { return 0; }
+int __attribute__((target("arch=sandybridge"))) foo(int);
+int __attribute__((target("arch=ivybridge"))) foo(int i) {return 1;}
+int __attribute__((target("default"))) foo(int i) { return 2; }
+
+typedef int (*FuncPtr)(int);
+void func(FuncPtr);
+
+int bar() {
+ func(foo);
+ FuncPtr Free = &foo;
+ FuncPtr Free2 = foo;
+
+ return 0;
+ return Free(1) + Free(2);
+}
+
+// CHECK: @foo.ifunc = ifunc i32 (i32), i32 (i32)* ()* @foo.resolver
+// CHECK: define i32 @foo.sse4.2(
+// CHECK: ret i32 0
+// CHECK: define i32 @foo.arch_ivybridge(
+// CHECK: ret i32 1
+// CHECK: define i32 @foo(
+// CHECK: ret i32 2
+
+// CHECK: define i32 @bar()
+// CHECK: call void @func(i32 (i32)* @foo.ifunc)
+// CHECK: store i32 (i32)* @foo.ifunc
+// CHECK: store i32 (i32)* @foo.ifunc
+
+// CHECK: declare i32 @foo.arch_sandybridge(
diff --git a/test/CodeGen/attr-target-mv-va-args.c b/test/CodeGen/attr-target-mv-va-args.c
new file mode 100644
index 000000000000..b33f841dba5e
--- /dev/null
+++ b/test/CodeGen/attr-target-mv-va-args.c
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s
+int __attribute__((target("sse4.2"))) foo(int i, ...) { return 0; }
+int __attribute__((target("arch=sandybridge"))) foo(int i, ...);
+int __attribute__((target("arch=ivybridge"))) foo(int i, ...) {return 1;}
+int __attribute__((target("default"))) foo(int i, ...) { return 2; }
+
+int bar() {
+ return foo(1, 'a', 1.1) + foo(2, 2.2, "asdf");
+}
+
+// CHECK: @foo.ifunc = ifunc i32 (i32, ...), i32 (i32, ...)* ()* @foo.resolver
+// CHECK: define i32 @foo.sse4.2(i32 %i, ...)
+// CHECK: ret i32 0
+// CHECK: define i32 @foo.arch_ivybridge(i32 %i, ...)
+// CHECK: ret i32 1
+// CHECK: define i32 @foo(i32 %i, ...)
+// CHECK: ret i32 2
+// CHECK: define i32 @bar()
+// CHECK: call i32 (i32, ...) @foo.ifunc(i32 1, i32 97, double
+// CHECK: call i32 (i32, ...) @foo.ifunc(i32 2, double 2.2{{[0-9Ee+]+}}, i8* getelementptr inbounds
+// CHECK: define i32 (i32, ...)* @foo.resolver() comdat
+// CHECK: ret i32 (i32, ...)* @foo.arch_sandybridge
+// CHECK: ret i32 (i32, ...)* @foo.arch_ivybridge
+// CHECK: ret i32 (i32, ...)* @foo.sse4.2
+// CHECK: ret i32 (i32, ...)* @foo
+// CHECK: declare i32 @foo.arch_sandybridge(i32, ...)
diff --git a/test/CodeGen/attr-target-mv.c b/test/CodeGen/attr-target-mv.c
new file mode 100644
index 000000000000..0085a154ced1
--- /dev/null
+++ b/test/CodeGen/attr-target-mv.c
@@ -0,0 +1,91 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s
+int __attribute__((target("sse4.2"))) foo(void) { return 0; }
+int __attribute__((target("arch=sandybridge"))) foo(void);
+int __attribute__((target("arch=ivybridge"))) foo(void) {return 1;}
+int __attribute__((target("default"))) foo(void) { return 2; }
+
+int bar() {
+ return foo();
+}
+
+inline int __attribute__((target("sse4.2"))) foo_inline(void) { return 0; }
+inline int __attribute__((target("arch=sandybridge"))) foo_inline(void);
+inline int __attribute__((target("arch=ivybridge"))) foo_inline(void) {return 1;}
+inline int __attribute__((target("default"))) foo_inline(void) { return 2; }
+
+int bar2() {
+ return foo_inline();
+}
+
+inline __attribute__((target("default"))) void foo_decls(void);
+inline __attribute__((target("sse4.2"))) void foo_decls(void);
+void bar3() {
+ foo_decls();
+}
+inline __attribute__((target("default"))) void foo_decls(void) {}
+inline __attribute__((target("sse4.2"))) void foo_decls(void) {}
+
+inline __attribute__((target("default"))) void foo_multi(void) {}
+inline __attribute__((target("avx,sse4.2"))) void foo_multi(void) {}
+inline __attribute__((target("sse4.2,fma4"))) void foo_multi(void) {}
+inline __attribute__((target("arch=ivybridge,fma4,sse4.2"))) void foo_multi(void) {}
+void bar4() {
+ foo_multi();
+}
+
+// CHECK: @foo.ifunc = ifunc i32 (), i32 ()* ()* @foo.resolver
+// CHECK: @foo_inline.ifunc = ifunc i32 (), i32 ()* ()* @foo_inline.resolver
+// CHECK: @foo_decls.ifunc = ifunc void (), void ()* ()* @foo_decls.resolver
+
+// CHECK: define i32 @foo.sse4.2()
+// CHECK: ret i32 0
+// CHECK: define i32 @foo.arch_ivybridge()
+// CHECK: ret i32 1
+// CHECK: define i32 @foo()
+// CHECK: ret i32 2
+// CHECK: define i32 @bar()
+// CHECK: call i32 @foo.ifunc()
+
+// CHECK: define i32 ()* @foo.resolver() comdat
+// CHECK: call void @__cpu_indicator_init()
+// CHECK: ret i32 ()* @foo.arch_sandybridge
+// CHECK: ret i32 ()* @foo.arch_ivybridge
+// CHECK: ret i32 ()* @foo.sse4.2
+// CHECK: ret i32 ()* @foo
+
+// CHECK: define i32 @bar2()
+// CHECK: call i32 @foo_inline.ifunc()
+
+// CHECK: define i32 ()* @foo_inline.resolver() comdat
+// CHECK: call void @__cpu_indicator_init()
+// CHECK: ret i32 ()* @foo_inline.arch_sandybridge
+// CHECK: ret i32 ()* @foo_inline.arch_ivybridge
+// CHECK: ret i32 ()* @foo_inline.sse4.2
+// CHECK: ret i32 ()* @foo_inline
+
+// CHECK: define void @bar3()
+// CHECK: call void @foo_decls.ifunc()
+
+// CHECK: define void ()* @foo_decls.resolver() comdat
+// CHECK: ret void ()* @foo_decls.sse4.2
+// CHECK: ret void ()* @foo_decls
+
+// CHECK: declare i32 @foo.arch_sandybridge()
+
+// CHECK: define available_externally i32 @foo_inline.sse4.2()
+// CHECK: ret i32 0
+
+// CHECK: declare i32 @foo_inline.arch_sandybridge()
+//
+// CHECK: define available_externally i32 @foo_inline.arch_ivybridge()
+// CHECK: ret i32 1
+// CHECK: define available_externally i32 @foo_inline()
+// CHECK: ret i32 2
+
+// CHECK: define available_externally void @foo_decls()
+// CHECK: define available_externally void @foo_decls.sse4.2()
+
+// CHECK: define available_externally void @foo_multi.avx_sse4.2()
+// CHECK: define available_externally void @foo_multi.fma4_sse4.2()
+// CHECK: define available_externally void @foo_multi.arch_ivybridge_fma4_sse4.2()
+
diff --git a/test/CodeGen/attr-target-x86.c b/test/CodeGen/attr-target-x86.c
index 9e46de74916b..ca544e4eaefb 100644
--- a/test/CodeGen/attr-target-x86.c
+++ b/test/CodeGen/attr-target-x86.c
@@ -21,6 +21,17 @@ int __attribute__((target("no-mmx"))) qq(int a) { return 40; }
int __attribute__((target("arch=lakemont,mmx"))) lake(int a) { return 4; }
+int use_before_def(void);
+int useage(void){
+ return use_before_def();
+}
+
+// Adding the attribute to a definition does update it in IR.
+int __attribute__((target("arch=lakemont,mmx"))) use_before_def(void) {
+ return 5;
+}
+
+
// Check that we emit the additional subtarget and cpu features for foo and not for baz or bar.
// CHECK: baz{{.*}} #0
// CHECK: foo{{.*}} #1
@@ -36,11 +47,12 @@ int __attribute__((target("arch=lakemont,mmx"))) lake(int a) { return 4; }
// CHECK: qax{{.*}} #5
// CHECK: qq{{.*}} #6
// CHECK: lake{{.*}} #7
+// CHECK: use_before_def{{.*}} #7
// CHECK: #0 = {{.*}}"target-cpu"="i686" "target-features"="+x87"
-// CHECK: #1 = {{.*}}"target-cpu"="ivybridge" "target-features"="+aes,+avx,+cx16,+f16c,+fsgsbase,+fxsr,+mmx,+pclmul,+popcnt,+rdrnd,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave,+xsaveopt"
+// CHECK: #1 = {{.*}}"target-cpu"="ivybridge" "target-features"="+aes,+avx,+cx16,+f16c,+fsgsbase,+fxsr,+mmx,+pclmul,+popcnt,+rdrnd,+sahf,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave,+xsaveopt"
// CHECK: #2 = {{.*}}"target-cpu"="i686" "target-features"="+x87,-aes,-avx,-avx2,-avx512bitalg,-avx512bw,-avx512cd,-avx512dq,-avx512er,-avx512f,-avx512ifma,-avx512pf,-avx512vbmi,-avx512vbmi2,-avx512vl,-avx512vnni,-avx512vpopcntdq,-f16c,-fma,-fma4,-gfni,-pclmul,-sha,-sse2,-sse3,-sse4.1,-sse4.2,-sse4a,-ssse3,-vaes,-vpclmulqdq,-xop,-xsave,-xsaveopt"
// CHECK: #3 = {{.*}}"target-cpu"="i686" "target-features"="+mmx,+popcnt,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87"
// CHECK: #4 = {{.*}}"target-cpu"="i686" "target-features"="+x87,-avx,-avx2,-avx512bitalg,-avx512bw,-avx512cd,-avx512dq,-avx512er,-avx512f,-avx512ifma,-avx512pf,-avx512vbmi,-avx512vbmi2,-avx512vl,-avx512vnni,-avx512vpopcntdq,-f16c,-fma,-fma4,-sse4.1,-sse4.2,-vaes,-vpclmulqdq,-xop,-xsave,-xsaveopt"
-// CHECK: #5 = {{.*}}"target-cpu"="ivybridge" "target-features"="+avx,+cx16,+f16c,+fsgsbase,+fxsr,+mmx,+pclmul,+popcnt,+rdrnd,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave,+xsaveopt,-aes,-vaes"
+// CHECK: #5 = {{.*}}"target-cpu"="ivybridge" "target-features"="+avx,+cx16,+f16c,+fsgsbase,+fxsr,+mmx,+pclmul,+popcnt,+rdrnd,+sahf,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave,+xsaveopt,-aes,-vaes"
// CHECK: #6 = {{.*}}"target-cpu"="i686" "target-features"="+x87,-3dnow,-3dnowa,-mmx"
// CHECK: #7 = {{.*}}"target-cpu"="lakemont" "target-features"="+mmx"
diff --git a/test/CodeGen/attr-x86-interrupt.c b/test/CodeGen/attr-x86-interrupt.c
index 0aca1f5b9c9c..700a57524dca 100644
--- a/test/CodeGen/attr-x86-interrupt.c
+++ b/test/CodeGen/attr-x86-interrupt.c
@@ -23,12 +23,12 @@ __attribute__((interrupt)) void foo8(int *a) {}
// X86_LINUX: "disable-tail-calls"="true"
// X86_LINUX-NOT: "disable-tail-calls"="false"
// X86_64_WIN: @llvm.used = appending global [2 x i8*] [i8* bitcast (void (i32*, i64)* @foo7 to i8*), i8* bitcast (void (i32*)* @foo8 to i8*)], section "llvm.metadata"
-// X86_64_WIN: define x86_intrcc void @foo7(i32* %{{.+}}, i64 %{{.+}})
-// X86_64_WIN: define x86_intrcc void @foo8(i32* %{{.+}})
+// X86_64_WIN: define dso_local x86_intrcc void @foo7(i32* %{{.+}}, i64 %{{.+}})
+// X86_64_WIN: define dso_local x86_intrcc void @foo8(i32* %{{.+}})
// X86_64_Win: "disable-tail-calls"="true"
// X86_64_Win-NOT: "disable-tail-calls"="false"
// X86_WIN: @llvm.used = appending global [2 x i8*] [i8* bitcast (void (i32*, i32)* @foo7 to i8*), i8* bitcast (void (i32*)* @foo8 to i8*)], section "llvm.metadata"
-// X86_WIN: define x86_intrcc void @foo7(i32* %{{.+}}, i32 %{{.+}})
-// X86_WIN: define x86_intrcc void @foo8(i32* %{{.+}})
+// X86_WIN: define dso_local x86_intrcc void @foo7(i32* %{{.+}}, i32 %{{.+}})
+// X86_WIN: define dso_local x86_intrcc void @foo8(i32* %{{.+}})
// X86_Win: "disable-tail-calls"="true"
// X86_Win-NOT: "disable-tail-calls"="false"
diff --git a/test/CodeGen/attributes.c b/test/CodeGen/attributes.c
index 34833a246920..4be38b6367dc 100644
--- a/test/CodeGen/attributes.c
+++ b/test/CodeGen/attributes.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm -triple i386-linux-gnu -o %t %s
+// RUN: %clang_cc1 -emit-llvm -fcf-protection=branch -triple i386-linux-gnu -o %t %s
// RUN: FileCheck --input-file=%t %s
// CHECK: @t5 = weak global i32 2
@@ -97,8 +97,20 @@ void __attribute__((section(".bar"))) t22(void) {}
// CHECK: define void @t22() [[NUW]] section ".bar"
+// CHECK: define void @t23() [[NOCF_CHECK_FUNC:#[0-9]+]]
+void __attribute__((nocf_check)) t23(void) {}
+
+// CHECK: call void %{{[a-z0-9]+}}() [[NOCF_CHECK_CALL:#[0-9]+]]
+typedef void (*f_t)(void);
+void t24(f_t f1) {
+ __attribute__((nocf_check)) f_t p = f1;
+ (*p)();
+}
+
// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
// CHECK: attributes [[NR]] = { noinline noreturn nounwind{{.*}} }
// CHECK: attributes [[COLDDEF]] = { cold {{.*}}}
// CHECK: attributes [[COLDDECL]] = { cold {{.*}}}
+// CHECK: attributes [[NOCF_CHECK_FUNC]] = { nocf_check {{.*}}}
// CHECK: attributes [[COLDSITE]] = { cold {{.*}}}
+// CHECK: attributes [[NOCF_CHECK_CALL]] = { nocf_check }
diff --git a/test/CodeGen/avx-builtins.c b/test/CodeGen/avx-builtins.c
index 4e77ad166ce0..3e7709b1b7e9 100644
--- a/test/CodeGen/avx-builtins.c
+++ b/test/CodeGen/avx-builtins.c
@@ -2,7 +2,7 @@
// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx -fno-signed-char -emit-llvm -o - -Wall -Werror | FileCheck %s
-#include <x86intrin.h>
+#include <immintrin.h>
// NOTE: This should match the tests in llvm/test/CodeGen/X86/sse-intrinsics-fast-isel.ll
@@ -59,7 +59,7 @@ __m256 test_mm256_andnot_ps(__m256 A, __m256 B) {
__m256d test_mm256_blend_pd(__m256d A, __m256d B) {
// CHECK-LABEL: test_mm256_blend_pd
// CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x i32> <i32 4, i32 1, i32 6, i32 3>
- return _mm256_blend_pd(A, B, 0x35);
+ return _mm256_blend_pd(A, B, 0x05);
}
__m256 test_mm256_blend_ps(__m256 A, __m256 B) {
@@ -212,28 +212,772 @@ __m256 test_mm_ceil_ps(__m256 x) {
return _mm256_ceil_ps(x);
}
-__m128d test_mm_cmp_pd(__m128d A, __m128d B) {
- // CHECK-LABEL: test_mm_cmp_pd
- // CHECK: call <2 x double> @llvm.x86.sse2.cmp.pd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 13)
- return _mm_cmp_pd(A, B, _CMP_GE_OS);
+__m256d test_mm256_cmp_pd_eq_oq(__m256d a, __m256d b) {
+ // CHECK-LABEL: @test_mm256_cmp_pd_eq_oq
+ // CHECK: fcmp oeq <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd(a, b, _CMP_EQ_OQ);
}
-__m256d test_mm256_cmp_pd(__m256d A, __m256d B) {
- // CHECK-LABEL: test_mm256_cmp_pd
- // CHECK: call <4 x double> @llvm.x86.avx.cmp.pd.256(<4 x double> %{{.*}}, <4 x double> %{{.*}}, i8 13)
- return _mm256_cmp_pd(A, B, _CMP_GE_OS);
+__m256d test_mm256_cmp_pd_lt_os(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_lt_os
+ // CHECK: fcmp olt <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd(a, b, _CMP_LT_OS);
}
-__m128 test_mm_cmp_ps(__m128 A, __m128 B) {
- // CHECK-LABEL: test_mm_cmp_ps
- // CHECK: call <4 x float> @llvm.x86.sse.cmp.ps(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 13)
- return _mm_cmp_ps(A, B, _CMP_GE_OS);
+__m256d test_mm256_cmp_pd_le_os(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_le_os
+ // CHECK: fcmp ole <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd(a, b, _CMP_LE_OS);
}
-__m256 test_mm256_cmp_ps(__m256d A, __m256d B) {
- // CHECK-LABEL: test_mm256_cmp_ps
- // CHECK: call <8 x float> @llvm.x86.avx.cmp.ps.256(<8 x float> %{{.*}}, <8 x float> %{{.*}}, i8 13)
- return _mm256_cmp_ps(A, B, _CMP_GE_OS);
+__m256d test_mm256_cmp_pd_unord_q(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_unord_q
+ // CHECK: fcmp uno <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd(a, b, _CMP_UNORD_Q);
+}
+
+__m256d test_mm256_cmp_pd_neq_uq(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_neq_uq
+ // CHECK: fcmp une <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd(a, b, _CMP_NEQ_UQ);
+}
+
+__m256d test_mm256_cmp_pd_nlt_us(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_nlt_us
+ // CHECK: fcmp uge <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd(a, b, _CMP_NLT_US);
+}
+
+__m256d test_mm256_cmp_pd_nle_us(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_nle_us
+ // CHECK: fcmp ugt <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd(a, b, _CMP_NLE_US);
+}
+
+__m256d test_mm256_cmp_pd_ord_q(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_ord_q
+ // CHECK: fcmp ord <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd(a, b, _CMP_ORD_Q);
+}
+
+__m256d test_mm256_cmp_pd_eq_uq(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_eq_uq
+ // CHECK: fcmp ueq <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd(a, b, _CMP_EQ_UQ);
+}
+
+__m256d test_mm256_cmp_pd_nge_us(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_nge_us
+ // CHECK: fcmp ult <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd(a, b, _CMP_NGE_US);
+}
+
+__m256d test_mm256_cmp_pd_ngt_us(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_ngt_us
+ // CHECK: fcmp ule <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd(a, b, _CMP_NGT_US);
+}
+
+__m256d test_mm256_cmp_pd_false_oq(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_false_oq
+ // CHECK: fcmp false <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd(a, b, _CMP_FALSE_OQ);
+}
+
+__m256d test_mm256_cmp_pd_neq_oq(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_neq_oq
+ // CHECK: fcmp one <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd(a, b, _CMP_NEQ_OQ);
+}
+
+__m256d test_mm256_cmp_pd_ge_os(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_ge_os
+ // CHECK: fcmp oge <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd(a, b, _CMP_GE_OS);
+}
+
+__m256d test_mm256_cmp_pd_gt_os(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_gt_os
+ // CHECK: fcmp ogt <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd(a, b, _CMP_GT_OS);
+}
+
+__m256d test_mm256_cmp_pd_true_uq(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_true_uq
+ // CHECK: fcmp true <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd(a, b, _CMP_TRUE_UQ);
+}
+
+__m256d test_mm256_cmp_pd_eq_os(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_eq_os
+ // CHECK: fcmp oeq <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd(a, b, _CMP_EQ_OS);
+}
+
+__m256d test_mm256_cmp_pd_lt_oq(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_lt_oq
+ // CHECK: fcmp olt <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd(a, b, _CMP_LT_OQ);
+}
+
+__m256d test_mm256_cmp_pd_le_oq(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_le_oq
+ // CHECK: fcmp ole <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd(a, b, _CMP_LE_OQ);
+}
+
+__m256d test_mm256_cmp_pd_unord_s(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_unord_s
+ // CHECK: fcmp uno <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd(a, b, _CMP_UNORD_S);
+}
+
+__m256d test_mm256_cmp_pd_neq_us(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_neq_us
+ // CHECK: fcmp une <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd(a, b, _CMP_NEQ_US);
+}
+
+__m256d test_mm256_cmp_pd_nlt_uq(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_nlt_uq
+ // CHECK: fcmp uge <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd(a, b, _CMP_NLT_UQ);
+}
+
+__m256d test_mm256_cmp_pd_nle_uq(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_nle_uq
+ // CHECK: fcmp ugt <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd(a, b, _CMP_NLE_UQ);
+}
+
+__m256d test_mm256_cmp_pd_ord_s(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_ord_s
+ // CHECK: fcmp ord <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd(a, b, _CMP_ORD_S);
+}
+
+__m256d test_mm256_cmp_pd_eq_us(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_eq_us
+ // CHECK: fcmp ueq <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd(a, b, _CMP_EQ_US);
+}
+
+__m256d test_mm256_cmp_pd_nge_uq(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_nge_uq
+ // CHECK: fcmp ult <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd(a, b, _CMP_NGE_UQ);
+}
+
+__m256d test_mm256_cmp_pd_ngt_uq(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_ngt_uq
+ // CHECK: fcmp ule <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd(a, b, _CMP_NGT_UQ);
+}
+
+__m256d test_mm256_cmp_pd_false_os(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_false_os
+ // CHECK: fcmp false <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd(a, b, _CMP_FALSE_OS);
+}
+
+__m256d test_mm256_cmp_pd_neq_os(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_neq_os
+ // CHECK: fcmp one <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd(a, b, _CMP_NEQ_OS);
+}
+
+__m256d test_mm256_cmp_pd_ge_oq(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_ge_oq
+ // CHECK: fcmp oge <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd(a, b, _CMP_GE_OQ);
+}
+
+__m256d test_mm256_cmp_pd_gt_oq(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_gt_oq
+ // CHECK: fcmp ogt <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd(a, b, _CMP_GT_OQ);
+}
+
+__m256d test_mm256_cmp_pd_true_us(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_true_us
+ // CHECK: fcmp true <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd(a, b, _CMP_TRUE_US);
+}
+
+__m256 test_mm256_cmp_ps_eq_oq(__m256 a, __m256 b) {
+ // CHECK-LABEL: @test_mm256_cmp_ps_eq_oq
+ // CHECK: fcmp oeq <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps(a, b, _CMP_EQ_OQ);
+}
+
+__m256 test_mm256_cmp_ps_lt_os(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_lt_os
+ // CHECK: fcmp olt <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps(a, b, _CMP_LT_OS);
+}
+
+__m256 test_mm256_cmp_ps_le_os(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_le_os
+ // CHECK: fcmp ole <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps(a, b, _CMP_LE_OS);
+}
+
+__m256 test_mm256_cmp_ps_unord_q(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_unord_q
+ // CHECK: fcmp uno <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps(a, b, _CMP_UNORD_Q);
+}
+
+__m256 test_mm256_cmp_ps_neq_uq(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_neq_uq
+ // CHECK: fcmp une <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps(a, b, _CMP_NEQ_UQ);
+}
+
+__m256 test_mm256_cmp_ps_nlt_us(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_nlt_us
+ // CHECK: fcmp uge <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps(a, b, _CMP_NLT_US);
+}
+
+__m256 test_mm256_cmp_ps_nle_us(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_nle_us
+ // CHECK: fcmp ugt <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps(a, b, _CMP_NLE_US);
+}
+
+__m256 test_mm256_cmp_ps_ord_q(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_ord_q
+ // CHECK: fcmp ord <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps(a, b, _CMP_ORD_Q);
+}
+
+__m256 test_mm256_cmp_ps_eq_uq(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_eq_uq
+ // CHECK: fcmp ueq <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps(a, b, _CMP_EQ_UQ);
+}
+
+__m256 test_mm256_cmp_ps_nge_us(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_nge_us
+ // CHECK: fcmp ult <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps(a, b, _CMP_NGE_US);
+}
+
+__m256 test_mm256_cmp_ps_ngt_us(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_ngt_us
+ // CHECK: fcmp ule <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps(a, b, _CMP_NGT_US);
+}
+
+__m256 test_mm256_cmp_ps_false_oq(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_false_oq
+ // CHECK: fcmp false <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps(a, b, _CMP_FALSE_OQ);
+}
+
+__m256 test_mm256_cmp_ps_neq_oq(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_neq_oq
+ // CHECK: fcmp one <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps(a, b, _CMP_NEQ_OQ);
+}
+
+__m256 test_mm256_cmp_ps_ge_os(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_ge_os
+ // CHECK: fcmp oge <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps(a, b, _CMP_GE_OS);
+}
+
+__m256 test_mm256_cmp_ps_gt_os(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_gt_os
+ // CHECK: fcmp ogt <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps(a, b, _CMP_GT_OS);
+}
+
+__m256 test_mm256_cmp_ps_true_uq(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_true_uq
+ // CHECK: fcmp true <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps(a, b, _CMP_TRUE_UQ);
+}
+
+__m256 test_mm256_cmp_ps_eq_os(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_eq_os
+ // CHECK: fcmp oeq <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps(a, b, _CMP_EQ_OS);
+}
+
+__m256 test_mm256_cmp_ps_lt_oq(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_lt_oq
+ // CHECK: fcmp olt <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps(a, b, _CMP_LT_OQ);
+}
+
+__m256 test_mm256_cmp_ps_le_oq(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_le_oq
+ // CHECK: fcmp ole <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps(a, b, _CMP_LE_OQ);
+}
+
+__m256 test_mm256_cmp_ps_unord_s(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_unord_s
+ // CHECK: fcmp uno <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps(a, b, _CMP_UNORD_S);
+}
+
+__m256 test_mm256_cmp_ps_neq_us(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_neq_us
+ // CHECK: fcmp une <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps(a, b, _CMP_NEQ_US);
+}
+
+__m256 test_mm256_cmp_ps_nlt_uq(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_nlt_uq
+ // CHECK: fcmp uge <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps(a, b, _CMP_NLT_UQ);
+}
+
+__m256 test_mm256_cmp_ps_nle_uq(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_nle_uq
+ // CHECK: fcmp ugt <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps(a, b, _CMP_NLE_UQ);
+}
+
+__m256 test_mm256_cmp_ps_ord_s(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_ord_s
+ // CHECK: fcmp ord <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps(a, b, _CMP_ORD_S);
+}
+
+__m256 test_mm256_cmp_ps_eq_us(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_eq_us
+ // CHECK: fcmp ueq <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps(a, b, _CMP_EQ_US);
+}
+
+__m256 test_mm256_cmp_ps_nge_uq(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_nge_uq
+ // CHECK: fcmp ult <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps(a, b, _CMP_NGE_UQ);
+}
+
+__m256 test_mm256_cmp_ps_ngt_uq(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_ngt_uq
+ // CHECK: fcmp ule <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps(a, b, _CMP_NGT_UQ);
+}
+
+__m256 test_mm256_cmp_ps_false_os(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_false_os
+ // CHECK: fcmp false <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps(a, b, _CMP_FALSE_OS);
+}
+
+__m256 test_mm256_cmp_ps_neq_os(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_neq_os
+ // CHECK: fcmp one <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps(a, b, _CMP_NEQ_OS);
+}
+
+__m256 test_mm256_cmp_ps_ge_oq(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_ge_oq
+ // CHECK: fcmp oge <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps(a, b, _CMP_GE_OQ);
+}
+
+__m256 test_mm256_cmp_ps_gt_oq(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_gt_oq
+ // CHECK: fcmp ogt <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps(a, b, _CMP_GT_OQ);
+}
+
+__m256 test_mm256_cmp_ps_true_us(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_true_us
+ // CHECK: fcmp true <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps(a, b, _CMP_TRUE_US);
+}
+
+__m128d test_mm_cmp_pd_eq_oq(__m128d a, __m128d b) {
+ // CHECK-LABEL: @test_mm_cmp_pd_eq_oq
+ // CHECK: fcmp oeq <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd(a, b, _CMP_EQ_OQ);
+}
+
+__m128d test_mm_cmp_pd_lt_os(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_lt_os
+ // CHECK: fcmp olt <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd(a, b, _CMP_LT_OS);
+}
+
+__m128d test_mm_cmp_pd_le_os(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_le_os
+ // CHECK: fcmp ole <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd(a, b, _CMP_LE_OS);
+}
+
+__m128d test_mm_cmp_pd_unord_q(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_unord_q
+ // CHECK: fcmp uno <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd(a, b, _CMP_UNORD_Q);
+}
+
+__m128d test_mm_cmp_pd_neq_uq(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_neq_uq
+ // CHECK: fcmp une <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd(a, b, _CMP_NEQ_UQ);
+}
+
+__m128d test_mm_cmp_pd_nlt_us(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_nlt_us
+ // CHECK: fcmp uge <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd(a, b, _CMP_NLT_US);
+}
+
+__m128d test_mm_cmp_pd_nle_us(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_nle_us
+ // CHECK: fcmp ugt <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd(a, b, _CMP_NLE_US);
+}
+
+__m128d test_mm_cmp_pd_ord_q(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_ord_q
+ // CHECK: fcmp ord <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd(a, b, _CMP_ORD_Q);
+}
+
+__m128d test_mm_cmp_pd_eq_uq(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_eq_uq
+ // CHECK: fcmp ueq <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd(a, b, _CMP_EQ_UQ);
+}
+
+__m128d test_mm_cmp_pd_nge_us(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_nge_us
+ // CHECK: fcmp ult <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd(a, b, _CMP_NGE_US);
+}
+
+__m128d test_mm_cmp_pd_ngt_us(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_ngt_us
+ // CHECK: fcmp ule <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd(a, b, _CMP_NGT_US);
+}
+
+__m128d test_mm_cmp_pd_false_oq(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_false_oq
+ // CHECK: fcmp false <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd(a, b, _CMP_FALSE_OQ);
+}
+
+__m128d test_mm_cmp_pd_neq_oq(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_neq_oq
+ // CHECK: fcmp one <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd(a, b, _CMP_NEQ_OQ);
+}
+
+__m128d test_mm_cmp_pd_ge_os(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_ge_os
+ // CHECK: fcmp oge <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd(a, b, _CMP_GE_OS);
+}
+
+__m128d test_mm_cmp_pd_gt_os(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_gt_os
+ // CHECK: fcmp ogt <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd(a, b, _CMP_GT_OS);
+}
+
+__m128d test_mm_cmp_pd_true_uq(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_true_uq
+ // CHECK: fcmp true <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd(a, b, _CMP_TRUE_UQ);
+}
+
+__m128d test_mm_cmp_pd_eq_os(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_eq_os
+ // CHECK: fcmp oeq <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd(a, b, _CMP_EQ_OS);
+}
+
+__m128d test_mm_cmp_pd_lt_oq(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_lt_oq
+ // CHECK: fcmp olt <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd(a, b, _CMP_LT_OQ);
+}
+
+__m128d test_mm_cmp_pd_le_oq(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_le_oq
+ // CHECK: fcmp ole <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd(a, b, _CMP_LE_OQ);
+}
+
+__m128d test_mm_cmp_pd_unord_s(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_unord_s
+ // CHECK: fcmp uno <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd(a, b, _CMP_UNORD_S);
+}
+
+__m128d test_mm_cmp_pd_neq_us(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_neq_us
+ // CHECK: fcmp une <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd(a, b, _CMP_NEQ_US);
+}
+
+__m128d test_mm_cmp_pd_nlt_uq(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_nlt_uq
+ // CHECK: fcmp uge <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd(a, b, _CMP_NLT_UQ);
+}
+
+__m128d test_mm_cmp_pd_nle_uq(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_nle_uq
+ // CHECK: fcmp ugt <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd(a, b, _CMP_NLE_UQ);
+}
+
+__m128d test_mm_cmp_pd_ord_s(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_ord_s
+ // CHECK: fcmp ord <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd(a, b, _CMP_ORD_S);
+}
+
+__m128d test_mm_cmp_pd_eq_us(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_eq_us
+ // CHECK: fcmp ueq <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd(a, b, _CMP_EQ_US);
+}
+
+__m128d test_mm_cmp_pd_nge_uq(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_nge_uq
+ // CHECK: fcmp ult <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd(a, b, _CMP_NGE_UQ);
+}
+
+__m128d test_mm_cmp_pd_ngt_uq(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_ngt_uq
+ // CHECK: fcmp ule <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd(a, b, _CMP_NGT_UQ);
+}
+
+__m128d test_mm_cmp_pd_false_os(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_false_os
+ // CHECK: fcmp false <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd(a, b, _CMP_FALSE_OS);
+}
+
+__m128d test_mm_cmp_pd_neq_os(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_neq_os
+ // CHECK: fcmp one <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd(a, b, _CMP_NEQ_OS);
+}
+
+__m128d test_mm_cmp_pd_ge_oq(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_ge_oq
+ // CHECK: fcmp oge <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd(a, b, _CMP_GE_OQ);
+}
+
+__m128d test_mm_cmp_pd_gt_oq(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_gt_oq
+ // CHECK: fcmp ogt <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd(a, b, _CMP_GT_OQ);
+}
+
+__m128d test_mm_cmp_pd_true_us(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_true_us
+ // CHECK: fcmp true <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd(a, b, _CMP_TRUE_US);
+}
+
+__m128 test_mm_cmp_ps_eq_oq(__m128 a, __m128 b) {
+ // CHECK-LABEL: @test_mm_cmp_ps_eq_oq
+ // CHECK: fcmp oeq <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps(a, b, _CMP_EQ_OQ);
+}
+
+__m128 test_mm_cmp_ps_lt_os(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_lt_os
+ // CHECK: fcmp olt <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps(a, b, _CMP_LT_OS);
+}
+
+__m128 test_mm_cmp_ps_le_os(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_le_os
+ // CHECK: fcmp ole <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps(a, b, _CMP_LE_OS);
+}
+
+__m128 test_mm_cmp_ps_unord_q(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_unord_q
+ // CHECK: fcmp uno <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps(a, b, _CMP_UNORD_Q);
+}
+
+__m128 test_mm_cmp_ps_neq_uq(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_neq_uq
+ // CHECK: fcmp une <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps(a, b, _CMP_NEQ_UQ);
+}
+
+__m128 test_mm_cmp_ps_nlt_us(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_nlt_us
+ // CHECK: fcmp uge <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps(a, b, _CMP_NLT_US);
+}
+
+__m128 test_mm_cmp_ps_nle_us(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_nle_us
+ // CHECK: fcmp ugt <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps(a, b, _CMP_NLE_US);
+}
+
+__m128 test_mm_cmp_ps_ord_q(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_ord_q
+ // CHECK: fcmp ord <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps(a, b, _CMP_ORD_Q);
+}
+
+__m128 test_mm_cmp_ps_eq_uq(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_eq_uq
+ // CHECK: fcmp ueq <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps(a, b, _CMP_EQ_UQ);
+}
+
+__m128 test_mm_cmp_ps_nge_us(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_nge_us
+ // CHECK: fcmp ult <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps(a, b, _CMP_NGE_US);
+}
+
+__m128 test_mm_cmp_ps_ngt_us(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_ngt_us
+ // CHECK: fcmp ule <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps(a, b, _CMP_NGT_US);
+}
+
+__m128 test_mm_cmp_ps_false_oq(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_false_oq
+ // CHECK: fcmp false <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps(a, b, _CMP_FALSE_OQ);
+}
+
+__m128 test_mm_cmp_ps_neq_oq(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_neq_oq
+ // CHECK: fcmp one <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps(a, b, _CMP_NEQ_OQ);
+}
+
+__m128 test_mm_cmp_ps_ge_os(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_ge_os
+ // CHECK: fcmp oge <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps(a, b, _CMP_GE_OS);
+}
+
+__m128 test_mm_cmp_ps_gt_os(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_gt_os
+ // CHECK: fcmp ogt <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps(a, b, _CMP_GT_OS);
+}
+
+__m128 test_mm_cmp_ps_true_uq(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_true_uq
+ // CHECK: fcmp true <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps(a, b, _CMP_TRUE_UQ);
+}
+
+__m128 test_mm_cmp_ps_eq_os(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_eq_os
+ // CHECK: fcmp oeq <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps(a, b, _CMP_EQ_OS);
+}
+
+__m128 test_mm_cmp_ps_lt_oq(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_lt_oq
+ // CHECK: fcmp olt <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps(a, b, _CMP_LT_OQ);
+}
+
+__m128 test_mm_cmp_ps_le_oq(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_le_oq
+ // CHECK: fcmp ole <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps(a, b, _CMP_LE_OQ);
+}
+
+__m128 test_mm_cmp_ps_unord_s(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_unord_s
+ // CHECK: fcmp uno <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps(a, b, _CMP_UNORD_S);
+}
+
+__m128 test_mm_cmp_ps_neq_us(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_neq_us
+ // CHECK: fcmp une <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps(a, b, _CMP_NEQ_US);
+}
+
+__m128 test_mm_cmp_ps_nlt_uq(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_nlt_uq
+ // CHECK: fcmp uge <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps(a, b, _CMP_NLT_UQ);
+}
+
+__m128 test_mm_cmp_ps_nle_uq(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_nle_uq
+ // CHECK: fcmp ugt <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps(a, b, _CMP_NLE_UQ);
+}
+
+__m128 test_mm_cmp_ps_ord_s(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_ord_s
+ // CHECK: fcmp ord <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps(a, b, _CMP_ORD_S);
+}
+
+__m128 test_mm_cmp_ps_eq_us(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_eq_us
+ // CHECK: fcmp ueq <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps(a, b, _CMP_EQ_US);
+}
+
+__m128 test_mm_cmp_ps_nge_uq(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_nge_uq
+ // CHECK: fcmp ult <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps(a, b, _CMP_NGE_UQ);
+}
+
+__m128 test_mm_cmp_ps_ngt_uq(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_ngt_uq
+ // CHECK: fcmp ule <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps(a, b, _CMP_NGT_UQ);
+}
+
+__m128 test_mm_cmp_ps_false_os(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_false_os
+ // CHECK: fcmp false <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps(a, b, _CMP_FALSE_OS);
+}
+
+__m128 test_mm_cmp_ps_neq_os(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_neq_os
+ // CHECK: fcmp one <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps(a, b, _CMP_NEQ_OS);
+}
+
+__m128 test_mm_cmp_ps_ge_oq(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_ge_oq
+ // CHECK: fcmp oge <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps(a, b, _CMP_GE_OQ);
+}
+
+__m128 test_mm_cmp_ps_gt_oq(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_gt_oq
+ // CHECK: fcmp ogt <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps(a, b, _CMP_GT_OQ);
+}
+
+__m128 test_mm_cmp_ps_true_us(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_true_us
+ // CHECK: fcmp true <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps(a, b, _CMP_TRUE_US);
}
__m128d test_mm_cmp_sd(__m128d A, __m128d B) {
@@ -256,7 +1000,7 @@ __m256d test_mm256_cvtepi32_pd(__m128i A) {
__m256 test_mm256_cvtepi32_ps(__m256i A) {
// CHECK-LABEL: test_mm256_cvtepi32_ps
- // CHECK: call <8 x float> @llvm.x86.avx.cvtdq2.ps.256(<8 x i32> %{{.*}})
+ // CHECK: sitofp <8 x i32> %{{.*}} to <8 x float>
return _mm256_cvtepi32_ps(A);
}
@@ -316,49 +1060,45 @@ __m256 test_mm256_dp_ps(__m256 A, __m256 B) {
int test_mm256_extract_epi8(__m256i A) {
// CHECK-LABEL: test_mm256_extract_epi8
- // CHECK: and i32 %{{.*}}, 31
- // CHECK: extractelement <32 x i8> %{{.*}}, i32 %{{.*}}
+ // CHECK: extractelement <32 x i8> %{{.*}}, {{i32|i64}} 31
// CHECK: zext i8 %{{.*}} to i32
- return _mm256_extract_epi8(A, 32);
+ return _mm256_extract_epi8(A, 31);
}
int test_mm256_extract_epi16(__m256i A) {
// CHECK-LABEL: test_mm256_extract_epi16
- // CHECK: and i32 %{{.*}}, 15
- // CHECK: extractelement <16 x i16> %{{.*}}, i32 %{{.*}}
+ // CHECK: extractelement <16 x i16> %{{.*}}, {{i32|i64}} 15
// CHECK: zext i16 %{{.*}} to i32
- return _mm256_extract_epi16(A, 16);
+ return _mm256_extract_epi16(A, 15);
}
int test_mm256_extract_epi32(__m256i A) {
// CHECK-LABEL: test_mm256_extract_epi32
- // CHECK: and i32 %{{.*}}, 7
- // CHECK: extractelement <8 x i32> %{{.*}}, i32 %{{.*}}
- return _mm256_extract_epi32(A, 8);
+ // CHECK: extractelement <8 x i32> %{{.*}}, {{i32|i64}} 7
+ return _mm256_extract_epi32(A, 7);
}
long long test_mm256_extract_epi64(__m256i A) {
// CHECK-LABEL: test_mm256_extract_epi64
- // CHECK: and i32 %{{.*}}, 3
- // CHECK: extractelement <4 x i64> %{{.*}}, i32 %{{.*}}
- return _mm256_extract_epi64(A, 5);
+ // CHECK: extractelement <4 x i64> %{{.*}}, {{i32|i64}} 3
+ return _mm256_extract_epi64(A, 3);
}
__m128d test_mm256_extractf128_pd(__m256d A) {
// CHECK-LABEL: test_mm256_extractf128_pd
- // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> zeroinitializer, <2 x i32> <i32 2, i32 3>
+ // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <2 x i32> <i32 2, i32 3>
return _mm256_extractf128_pd(A, 1);
}
__m128 test_mm256_extractf128_ps(__m256 A) {
// CHECK-LABEL: test_mm256_extractf128_ps
- // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> zeroinitializer, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
return _mm256_extractf128_ps(A, 1);
}
__m128i test_mm256_extractf128_si256(__m256i A) {
// CHECK-LABEL: test_mm256_extractf128_si256
- // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> zeroinitializer, <2 x i32> <i32 2, i32 3>
+ // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
return _mm256_extractf128_si256(A, 1);
}
@@ -400,50 +1140,46 @@ __m256 test_mm256_hsub_ps(__m256 A, __m256 B) {
__m256i test_mm256_insert_epi8(__m256i x, char b) {
// CHECK-LABEL: test_mm256_insert_epi8
- // CHECK: and i32 %{{.*}}, 31
- // CHECK: insertelement <32 x i8> %{{.*}}, i8 %{{.*}}, i32 %{{.*}}
- return _mm256_insert_epi8(x, b, 17);
+ // CHECK: insertelement <32 x i8> %{{.*}}, i8 %{{.*}}, {{i32|i64}} 14
+ return _mm256_insert_epi8(x, b, 14);
}
__m256i test_mm256_insert_epi16(__m256i x, int b) {
// CHECK-LABEL: test_mm256_insert_epi16
- // CHECK: and i32 %{{.*}}, 15
- // CHECK: insertelement <16 x i16> %{{.*}}, i16 %{{.*}}, i32 %{{.*}}
+ // CHECK: insertelement <16 x i16> %{{.*}}, i16 %{{.*}}, {{i32|i64}} 4
return _mm256_insert_epi16(x, b, 4);
}
__m256i test_mm256_insert_epi32(__m256i x, int b) {
// CHECK-LABEL: test_mm256_insert_epi32
- // CHECK: and i32 %{{.*}}, 7
- // CHECK: insertelement <8 x i32> %{{.*}}, i32 %{{.*}}, i32 %{{.*}}
+ // CHECK: insertelement <8 x i32> %{{.*}}, i32 %{{.*}}, {{i32|i64}} 5
return _mm256_insert_epi32(x, b, 5);
}
__m256i test_mm256_insert_epi64(__m256i x, long long b) {
// CHECK-LABEL: test_mm256_insert_epi64
- // CHECK: and i32 %{{.*}}, 3
- // CHECK: insertelement <4 x i64> %{{.*}}, i64 %{{.*}}, i32 %{{.*}}
+ // CHECK: insertelement <4 x i64> %{{.*}}, i64 %{{.*}}, {{i32|i64}} 2
return _mm256_insert_epi64(x, b, 2);
}
__m256d test_mm256_insertf128_pd(__m256d A, __m128d B) {
// CHECK-LABEL: test_mm256_insertf128_pd
- // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
+ // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
// CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x i32> <i32 4, i32 5, i32 2, i32 3>
return _mm256_insertf128_pd(A, B, 0);
}
__m256 test_mm256_insertf128_ps(__m256 A, __m128 B) {
// CHECK-LABEL: test_mm256_insertf128_ps
- // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
// CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 10, i32 11>
return _mm256_insertf128_ps(A, B, 1);
}
__m256i test_mm256_insertf128_si256(__m256i A, __m128i B) {
// CHECK-LABEL: test_mm256_insertf128_si256
- // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
- // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i32> <i32 4, i32 5, i32 2, i32 3>
+ // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7>
return _mm256_insertf128_si256(A, B, 0);
}
@@ -494,7 +1230,7 @@ __m256 test_mm256_loadu2_m128(float* A, float* B) {
// CHECK: load <4 x float>, <4 x float>* %{{.*}}, align 1{{$}}
// CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef>
// CHECK: load <4 x float>, <4 x float>* %{{.*}}, align 1{{$}}
- // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
// CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 10, i32 11>
return _mm256_loadu2_m128(A, B);
}
@@ -504,7 +1240,7 @@ __m256d test_mm256_loadu2_m128d(double* A, double* B) {
// CHECK: load <2 x double>, <2 x double>* %{{.*}}, align 1{{$}}
// CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
// CHECK: load <2 x double>, <2 x double>* %{{.*}}, align 1{{$}}
- // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
+ // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
// CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
return _mm256_loadu2_m128d(A, B);
}
@@ -514,8 +1250,8 @@ __m256i test_mm256_loadu2_m128i(__m128i* A, __m128i* B) {
// CHECK: load <2 x i64>, <2 x i64>* %{{.*}}, align 1{{$}}
// CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
// CHECK: load <2 x i64>, <2 x i64>* %{{.*}}, align 1{{$}}
- // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
- // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+ // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 10, i32 11>
return _mm256_loadu2_m128i(A, B);
}
@@ -647,32 +1383,32 @@ __m256 test_mm256_or_ps(__m256 A, __m256 B) {
__m128d test_mm_permute_pd(__m128d A) {
// CHECK-LABEL: test_mm_permute_pd
- // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> zeroinitializer, <2 x i32> <i32 1, i32 0>
+ // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> undef, <2 x i32> <i32 1, i32 0>
return _mm_permute_pd(A, 1);
}
__m256d test_mm256_permute_pd(__m256d A) {
// CHECK-LABEL: test_mm256_permute_pd
- // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> zeroinitializer, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
+ // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
return _mm256_permute_pd(A, 5);
}
__m128 test_mm_permute_ps(__m128 A) {
// CHECK-LABEL: test_mm_permute_ps
- // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> zeroinitializer, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+ // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> undef, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
return _mm_permute_ps(A, 0x1b);
}
// Test case for PR12401
__m128 test2_mm_permute_ps(__m128 a) {
// CHECK-LABEL: test2_mm_permute_ps
- // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> zeroinitializer, <4 x i32> <i32 2, i32 1, i32 2, i32 3>
+ // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> undef, <4 x i32> <i32 2, i32 1, i32 2, i32 3>
return _mm_permute_ps(a, 0xe6);
}
__m256 test_mm256_permute_ps(__m256 A) {
// CHECK-LABEL: test_mm256_permute_ps
- // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> zeroinitializer, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
+ // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> undef, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
return _mm256_permute_ps(A, 0x1b);
}
@@ -834,13 +1570,13 @@ __m256 test_mm256_set_m128(__m128 A, __m128 B) {
__m256d test_mm256_set_m128d(__m128d A, __m128d B) {
// CHECK-LABEL: test_mm256_set_m128d
- // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
return _mm256_set_m128d(A, B);
}
__m256i test_mm256_set_m128i(__m128i A, __m128i B) {
// CHECK-LABEL: test_mm256_set_m128i
- // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
return _mm256_set_m128i(A, B);
}
@@ -1060,13 +1796,13 @@ __m256 test_mm256_setr_m128(__m128 A, __m128 B) {
__m256d test_mm256_setr_m128d(__m128d A, __m128d B) {
// CHECK-LABEL: test_mm256_setr_m128d
- // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
return _mm256_setr_m128d(A, B);
}
__m256i test_mm256_setr_m128i(__m128i A, __m128i B) {
// CHECK-LABEL: test_mm256_setr_m128i
- // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
return _mm256_setr_m128i(A, B);
}
@@ -1124,13 +1860,13 @@ __m256 test_mm256_shuffle_ps(__m256 A, __m256 B) {
__m256d test_mm256_sqrt_pd(__m256d A) {
// CHECK-LABEL: test_mm256_sqrt_pd
- // CHECK: call <4 x double> @llvm.x86.avx.sqrt.pd.256(<4 x double> %{{.*}})
+ // CHECK: call <4 x double> @llvm.sqrt.v4f64(<4 x double> %{{.*}})
return _mm256_sqrt_pd(A);
}
__m256 test_mm256_sqrt_ps(__m256 A) {
// CHECK-LABEL: test_mm256_sqrt_ps
- // CHECK: call <8 x float> @llvm.x86.avx.sqrt.ps.256(<8 x float> %{{.*}})
+ // CHECK: call <8 x float> @llvm.sqrt.v8f32(<8 x float> %{{.*}})
return _mm256_sqrt_ps(A);
}
@@ -1177,7 +1913,7 @@ void test_mm256_storeu2_m128(float* A, float* B, __m256 C) {
// CHECK-LABEL: test_mm256_storeu2_m128
// CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
// CHECK: store <4 x float> %{{.*}}, <4 x float>* %{{.*}}, align 1{{$}}
- // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> zeroinitializer, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: store <4 x float> %{{.*}}, <4 x float>* %{{.*}}, align 1{{$}}
_mm256_storeu2_m128(A, B, C);
}
@@ -1186,7 +1922,7 @@ void test_mm256_storeu2_m128d(double* A, double* B, __m256d C) {
// CHECK-LABEL: test_mm256_storeu2_m128d
// CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> %{{.*}}, <2 x i32> <i32 0, i32 1>
// CHECK: store <2 x double> %{{.*}}, <2 x double>* %{{.*}}, align 1{{$}}
- // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> zeroinitializer, <2 x i32> <i32 2, i32 3>
+ // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <2 x i32> <i32 2, i32 3>
// CHECK: store <2 x double> %{{.*}}, <2 x double>* %{{.*}}, align 1{{$}}
_mm256_storeu2_m128d(A, B, C);
}
@@ -1195,7 +1931,7 @@ void test_mm256_storeu2_m128i(__m128i* A, __m128i* B, __m256i C) {
// CHECK-LABEL: test_mm256_storeu2_m128i
// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <2 x i32> <i32 0, i32 1>
// CHECK: store <2 x i64> %{{.*}}, <2 x i64>* %{{.*}}, align 1{{$}}
- // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> zeroinitializer, <2 x i32> <i32 2, i32 3>
+ // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: store <2 x i64> %{{.*}}, <2 x i64>* %{{.*}}, align 1{{$}}
_mm256_storeu2_m128i(A, B, C);
}
@@ -1254,7 +1990,7 @@ int test_mm256_testc_ps(__m256 A, __m256 B) {
return _mm256_testc_ps(A, B);
}
-int test_mm256_testc_si256(__m256 A, __m256 B) {
+int test_mm256_testc_si256(__m256i A, __m256i B) {
// CHECK-LABEL: test_mm256_testc_si256
// CHECK: call i32 @llvm.x86.avx.ptestc.256(<4 x i64> %{{.*}}, <4 x i64> %{{.*}})
return _mm256_testc_si256(A, B);
@@ -1284,7 +2020,7 @@ int test_mm256_testnzc_ps(__m256 A, __m256 B) {
return _mm256_testnzc_ps(A, B);
}
-int test_mm256_testnzc_si256(__m256 A, __m256 B) {
+int test_mm256_testnzc_si256(__m256i A, __m256i B) {
// CHECK-LABEL: test_mm256_testnzc_si256
// CHECK: call i32 @llvm.x86.avx.ptestnzc.256(<4 x i64> %{{.*}}, <4 x i64> %{{.*}})
return _mm256_testnzc_si256(A, B);
@@ -1314,7 +2050,7 @@ int test_mm256_testz_ps(__m256 A, __m256 B) {
return _mm256_testz_ps(A, B);
}
-int test_mm256_testz_si256(__m256 A, __m256 B) {
+int test_mm256_testz_si256(__m256i A, __m256i B) {
// CHECK-LABEL: test_mm256_testz_si256
// CHECK: call i32 @llvm.x86.avx.ptestz.256(<4 x i64> %{{.*}}, <4 x i64> %{{.*}})
return _mm256_testz_si256(A, B);
@@ -1409,69 +2145,21 @@ __m256i test_mm256_zextsi128_si256(__m128i A) {
double test_mm256_cvtsd_f64(__m256d __a)
{
- // CHECK-LABEL: @test_mm256_cvtsd_f64
- // CHECK: extractelement <4 x double> %{{.*}}, i32 0
- return _mm256_cvtsd_f64(__a);
+ // CHECK-LABEL: @test_mm256_cvtsd_f64
+ // CHECK: extractelement <4 x double> %{{.*}}, i32 0
+ return _mm256_cvtsd_f64(__a);
}
int test_mm256_cvtsi256_si32(__m256i __a)
{
- // CHECK-LABEL: @test_mm256_cvtsi256_si32
- // CHECK: extractelement <8 x i32> %{{.*}}, i32 0
- return _mm256_cvtsi256_si32(__a);
+ // CHECK-LABEL: @test_mm256_cvtsi256_si32
+ // CHECK: extractelement <8 x i32> %{{.*}}, i32 0
+ return _mm256_cvtsi256_si32(__a);
}
float test_mm256_cvtss_f32(__m256 __a)
{
- // CHECK-LABEL: @test_mm256_cvtss_f32
- // CHECK: extractelement <8 x float> %{{.*}}, i32 0
- return _mm256_cvtss_f32(__a);
-}
-
-__m256 test_mm256_cmp_ps_true(__m256 a, __m256 b) {
- // CHECK-LABEL: @test_mm256_cmp_ps_true
- // CHECK: store <8 x float> <float 0xFFFFFFFFE0000000,
- return _mm256_cmp_ps(a, b, _CMP_TRUE_UQ);
-}
-
-__m256 test_mm256_cmp_pd_true(__m256 a, __m256 b) {
- // CHECK-LABEL: @test_mm256_cmp_pd_true
- // CHECK: store <4 x double> <double 0xFFFFFFFFFFFFFFFF,
- return _mm256_cmp_pd(a, b, _CMP_TRUE_UQ);
-}
-
-__m256 test_mm256_cmp_ps_false(__m256 a, __m256 b) {
- // CHECK-LABEL: @test_mm256_cmp_ps_false
- // CHECK: store <8 x float> zeroinitializer, <8 x float>* %tmp, align 32
- return _mm256_cmp_ps(a, b, _CMP_FALSE_OQ);
-}
-
-__m256 test_mm256_cmp_pd_false(__m256 a, __m256 b) {
- // CHECK-LABEL: @test_mm256_cmp_pd_false
- // CHECK: store <4 x double> zeroinitializer, <4 x double>* %tmp, align 32
- return _mm256_cmp_pd(a, b, _CMP_FALSE_OQ);
-}
-
-__m256 test_mm256_cmp_ps_strue(__m256 a, __m256 b) {
- // CHECK-LABEL: @test_mm256_cmp_ps_strue
- // CHECK: store <8 x float> <float 0xFFFFFFFFE0000000,
- return _mm256_cmp_ps(a, b, _CMP_TRUE_US);
-}
-
-__m256 test_mm256_cmp_pd_strue(__m256 a, __m256 b) {
- // CHECK-LABEL: @test_mm256_cmp_pd_strue
- // CHECK: store <4 x double> <double 0xFFFFFFFFFFFFFFFF,
- return _mm256_cmp_pd(a, b, _CMP_TRUE_US);
-}
-
-__m256 test_mm256_cmp_ps_sfalse(__m256 a, __m256 b) {
- // CHECK-LABEL: @test_mm256_cmp_ps_sfalse
- // CHECK: store <8 x float> zeroinitializer, <8 x float>* %tmp, align 32
- return _mm256_cmp_ps(a, b, _CMP_FALSE_OS);
-}
-
-__m256 test_mm256_cmp_pd_sfalse(__m256 a, __m256 b) {
- // CHECK-LABEL: @test_mm256_cmp_pd_sfalse
- // CHECK: store <4 x double> zeroinitializer, <4 x double>* %tmp, align 32
- return _mm256_cmp_pd(a, b, _CMP_FALSE_OS);
+ // CHECK-LABEL: @test_mm256_cvtss_f32
+ // CHECK: extractelement <8 x float> %{{.*}}, i32 0
+ return _mm256_cvtss_f32(__a);
}
diff --git a/test/CodeGen/avx-cmp-builtins.c b/test/CodeGen/avx-cmp-builtins.c
index 7d619426653d..38d3ae24cdf1 100644
--- a/test/CodeGen/avx-cmp-builtins.c
+++ b/test/CodeGen/avx-cmp-builtins.c
@@ -8,30 +8,6 @@
// Test LLVM IR codegen of cmpXY instructions
//
-__m128d test_cmp_pd(__m128d a, __m128d b) {
- // Expects that the third argument in LLVM IR is immediate expression
- // CHECK: @llvm.x86.sse2.cmp.pd({{.*}}, i8 13)
- return _mm_cmp_pd(a, b, _CMP_GE_OS);
-}
-
-__m128d test_cmp_ps(__m128 a, __m128 b) {
- // Expects that the third argument in LLVM IR is immediate expression
- // CHECK: @llvm.x86.sse.cmp.ps({{.*}}, i8 13)
- return _mm_cmp_ps(a, b, _CMP_GE_OS);
-}
-
-__m256d test_cmp_pd256(__m256d a, __m256d b) {
- // Expects that the third argument in LLVM IR is immediate expression
- // CHECK: @llvm.x86.avx.cmp.pd.256({{.*}}, i8 13)
- return _mm256_cmp_pd(a, b, _CMP_GE_OS);
-}
-
-__m256d test_cmp_ps256(__m256 a, __m256 b) {
- // Expects that the third argument in LLVM IR is immediate expression
- // CHECK: @llvm.x86.avx.cmp.ps.256({{.*}}, i8 13)
- return _mm256_cmp_ps(a, b, _CMP_GE_OS);
-}
-
__m128d test_cmp_sd(__m128d a, __m128d b) {
// Expects that the third argument in LLVM IR is immediate expression
// CHECK: @llvm.x86.sse2.cmp.sd({{.*}}, i8 13)
diff --git a/test/CodeGen/avx-shuffle-builtins.c b/test/CodeGen/avx-shuffle-builtins.c
index b5bac89bd1ec..fef2879abd55 100644
--- a/test/CodeGen/avx-shuffle-builtins.c
+++ b/test/CodeGen/avx-shuffle-builtins.c
@@ -103,7 +103,7 @@ __m256d test_mm256_insertf128_pd_0(__m256d a, __m128d b) {
__m256i test_mm256_insertf128_si256_0(__m256i a, __m128i b) {
// CHECK-LABEL: @test_mm256_insertf128_si256_0
- // CHECK: shufflevector{{.*}}<i32 4, i32 5, i32 2, i32 3>
+ // CHECK: shufflevector{{.*}}<i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7>
return _mm256_insertf128_si256(a, b, 0);
}
@@ -121,7 +121,7 @@ __m256d test_mm256_insertf128_pd_1(__m256d a, __m128d b) {
__m256i test_mm256_insertf128_si256_1(__m256i a, __m128i b) {
// CHECK-LABEL: @test_mm256_insertf128_si256_1
- // CHECK: shufflevector{{.*}}<i32 0, i32 1, i32 4, i32 5>
+ // CHECK: shufflevector{{.*}}<i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 10, i32 11>
return _mm256_insertf128_si256(a, b, 1);
}
@@ -141,7 +141,7 @@ __m128d test_mm256_extractf128_pd_0(__m256d a) {
__m128i test_mm256_extractf128_si256_0(__m256i a) {
// CHECK-LABEL: @test_mm256_extractf128_si256_0
- // CHECK: shufflevector{{.*}}<i32 0, i32 1>
+ // CHECK: shufflevector{{.*}}<i32 0, i32 1, i32 2, i32 3>
return _mm256_extractf128_si256(a, 0);
}
@@ -159,7 +159,7 @@ __m128d test_mm256_extractf128_pd_1(__m256d a) {
__m128i test_mm256_extractf128_si256_1(__m256i a) {
// CHECK-LABEL: @test_mm256_extractf128_si256_1
- // CHECK: shufflevector{{.*}}<i32 2, i32 3>
+ // CHECK: shufflevector{{.*}}<i32 4, i32 5, i32 6, i32 7>
return _mm256_extractf128_si256(a, 1);
}
@@ -171,13 +171,13 @@ __m256 test_mm256_set_m128(__m128 hi, __m128 lo) {
__m256d test_mm256_set_m128d(__m128d hi, __m128d lo) {
// CHECK-LABEL: @test_mm256_set_m128d
- // CHECK: shufflevector{{.*}}<i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ // CHECK: shufflevector{{.*}}<i32 0, i32 1, i32 2, i32 3>
return _mm256_set_m128d(hi, lo);
}
__m256i test_mm256_set_m128i(__m128i hi, __m128i lo) {
// CHECK-LABEL: @test_mm256_set_m128i
- // CHECK: shufflevector{{.*}}<i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ // CHECK: shufflevector{{.*}}<i32 0, i32 1, i32 2, i32 3>
return _mm256_set_m128i(hi, lo);
}
@@ -189,12 +189,12 @@ __m256 test_mm256_setr_m128(__m128 hi, __m128 lo) {
__m256d test_mm256_setr_m128d(__m128d hi, __m128d lo) {
// CHECK-LABEL: @test_mm256_setr_m128d
- // CHECK: shufflevector{{.*}}<i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ // CHECK: shufflevector{{.*}}<i32 0, i32 1, i32 2, i32 3>
return _mm256_setr_m128d(lo, hi);
}
__m256i test_mm256_setr_m128i(__m128i hi, __m128i lo) {
// CHECK-LABEL: @test_mm256_setr_m128i
- // CHECK: shufflevector{{.*}}<i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ // CHECK: shufflevector{{.*}}<i32 0, i32 1, i32 2, i32 3>
return _mm256_setr_m128i(lo, hi);
}
diff --git a/test/CodeGen/avx2-builtins.c b/test/CodeGen/avx2-builtins.c
index f79f60e6db78..b0f4b5e6b55b 100644
--- a/test/CodeGen/avx2-builtins.c
+++ b/test/CodeGen/avx2-builtins.c
@@ -2,7 +2,7 @@
// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx2 -fno-signed-char -emit-llvm -o - -Wall -Werror | FileCheck %s
-#include <x86intrin.h>
+#include <immintrin.h>
// NOTE: This should match the tests in llvm/test/CodeGen/X86/avx2-intrinsics-fast-isel.ll
@@ -141,7 +141,7 @@ __m128i test_mm_blend_epi32(__m128i a, __m128i b) {
// CHECK-LABEL: test_mm_blend_epi32
// CHECK-NOT: @llvm.x86.avx2.pblendd.128
// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 4, i32 1, i32 6, i32 3>
- return _mm_blend_epi32(a, b, 0x35);
+ return _mm_blend_epi32(a, b, 0x05);
}
__m256i test_mm256_blend_epi32(__m256i a, __m256i b) {
@@ -248,13 +248,13 @@ __m256i test_mm256_broadcastw_epi16(__m128i a) {
__m256i test_mm256_bslli_epi128(__m256i a) {
// CHECK-LABEL: test_mm256_bslli_epi128
- // CHECK: shufflevector <32 x i8> %{{.*}}, <32 x i8> %{{.*}}, <32 x i32> <i32 13, i32 14, i32 15, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 29, i32 30, i32 31, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60>
+ // CHECK: shufflevector <32 x i8> zeroinitializer, <32 x i8> %{{.*}}, <32 x i32> <i32 13, i32 14, i32 15, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 29, i32 30, i32 31, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60>
return _mm256_bslli_epi128(a, 3);
}
__m256i test_mm256_bsrli_epi128(__m256i a) {
// CHECK-LABEL: test_mm256_bsrli_epi128
- // CHECK: shufflevector <32 x i8> %{{.*}}, <32 x i8> %{{.*}}, <32 x i32> <i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 32, i32 33, i32 34, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 48, i32 49, i32 50>
+ // CHECK: shufflevector <32 x i8> %{{.*}}, <32 x i8> zeroinitializer, <32 x i32> <i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 32, i32 33, i32 34, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 48, i32 49, i32 50>
return _mm256_bsrli_epi128(a, 3);
}
@@ -386,21 +386,21 @@ __m256i test_mm256_cvtepu32_epi64(__m128i a) {
__m128i test0_mm256_extracti128_si256_0(__m256i a) {
// CHECK-LABEL: test0_mm256_extracti128_si256
- // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> zeroinitializer, <2 x i32> <i32 0, i32 1>
+ // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 0, i32 1>
return _mm256_extracti128_si256(a, 0);
}
__m128i test1_mm256_extracti128_si256_1(__m256i a) {
// CHECK-LABEL: test1_mm256_extracti128_si256
- // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> zeroinitializer, <2 x i32> <i32 2, i32 3>
+ // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 2, i32 3>
return _mm256_extracti128_si256(a, 1);
}
// Immediate should be truncated to one bit.
__m128i test2_mm256_extracti128_si256(__m256i a) {
// CHECK-LABEL: test2_mm256_extracti128_si256
- // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> zeroinitializer, <2 x i32> <i32 0, i32 1>
- return _mm256_extracti128_si256(a, 2);
+ // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 0, i32 1>
+ return _mm256_extracti128_si256(a, 0);
}
__m256i test_mm256_hadd_epi16(__m256i a, __m256i b) {
@@ -612,9 +612,7 @@ __m128d test_mm_mask_i64gather_pd(__m128d a, double const *b, __m128i c, __m128d
__m256d test_mm256_i64gather_pd(double const *b, __m256i c) {
// CHECK-LABEL: test_mm256_i64gather_pd
- // CHECK: [[CMP:%.*]] = fcmp oeq <4 x double>
- // CHECK-NEXT: [[SEXT:%.*]] = sext <4 x i1> [[CMP]] to <4 x i64>
- // CHECK-NEXT: [[BC:%.*]] = bitcast <4 x i64> [[SEXT]] to <4 x double>
+ // CHECK: fcmp oeq <4 x double> %{{.*}}, %{{.*}}
// CHECK: call <4 x double> @llvm.x86.avx2.gather.q.pd.256(<4 x double> zeroinitializer, i8* %{{.*}}, <4 x i64> %{{.*}}, <4 x double> %{{.*}}, i8 2)
return _mm256_i64gather_pd(b, c, 2);
}
@@ -657,14 +655,14 @@ __m128 test_mm256_mask_i64gather_ps(__m128 a, float const *b, __m256i c, __m128
__m256i test0_mm256_inserti128_si256(__m256i a, __m128i b) {
// CHECK-LABEL: test0_mm256_inserti128_si256
- // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
+ // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i32> <i32 4, i32 5, i32 2, i32 3>
return _mm256_inserti128_si256(a, b, 0);
}
__m256i test1_mm256_inserti128_si256(__m256i a, __m128i b) {
// CHECK-LABEL: test1_mm256_inserti128_si256
- // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
+ // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
return _mm256_inserti128_si256(a, b, 1);
}
@@ -672,9 +670,9 @@ __m256i test1_mm256_inserti128_si256(__m256i a, __m128i b) {
// Immediate should be truncated to one bit.
__m256i test2_mm256_inserti128_si256(__m256i a, __m128i b) {
// CHECK-LABEL: test2_mm256_inserti128_si256
- // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
+ // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i32> <i32 4, i32 5, i32 2, i32 3>
- return _mm256_inserti128_si256(a, b, 2);
+ return _mm256_inserti128_si256(a, b, 0);
}
__m256i test_mm256_madd_epi16(__m256i a, __m256i b) {
@@ -835,13 +833,19 @@ __m256i test_mm256_mpsadbw_epu8(__m256i x, __m256i y) {
__m256i test_mm256_mul_epi32(__m256i a, __m256i b) {
// CHECK-LABEL: test_mm256_mul_epi32
- // CHECK: call <4 x i64> @llvm.x86.avx2.pmul.dq(<8 x i32> %{{.*}}, <8 x i32> %{{.*}})
+ // CHECK: shl <4 x i64> %{{.*}}, <i64 32, i64 32, i64 32, i64 32>
+ // CHECK: ashr <4 x i64> %{{.*}}, <i64 32, i64 32, i64 32, i64 32>
+ // CHECK: shl <4 x i64> %{{.*}}, <i64 32, i64 32, i64 32, i64 32>
+ // CHECK: ashr <4 x i64> %{{.*}}, <i64 32, i64 32, i64 32, i64 32>
+ // CHECK: mul <4 x i64> %{{.*}}, %{{.*}}
return _mm256_mul_epi32(a, b);
}
__m256i test_mm256_mul_epu32(__m256i a, __m256i b) {
// CHECK-LABEL: test_mm256_mul_epu32
- // CHECK: call <4 x i64> @llvm.x86.avx2.pmulu.dq(<8 x i32> %{{.*}}, <8 x i32> %{{.*}})
+ // CHECK: and <4 x i64> %{{.*}}, <i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295>
+ // CHECK: and <4 x i64> %{{.*}}, <i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295>
+ // CHECK: mul <4 x i64> %{{.*}}, %{{.*}}
return _mm256_mul_epu32(a, b);
}
@@ -913,13 +917,13 @@ __m256i test_mm256_permute2x128_si256(__m256i a, __m256i b) {
__m256i test_mm256_permute4x64_epi64(__m256i a) {
// CHECK-LABEL: test_mm256_permute4x64_epi64
- // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> zeroinitializer, <4 x i32> <i32 3, i32 0, i32 2, i32 0>
+ // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <4 x i32> <i32 3, i32 0, i32 2, i32 0>
return _mm256_permute4x64_epi64(a, 35);
}
__m256d test_mm256_permute4x64_pd(__m256d a) {
// CHECK-LABEL: test_mm256_permute4x64_pd
- // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 1, i32 0>
+ // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <4 x i32> <i32 1, i32 2, i32 1, i32 0>
return _mm256_permute4x64_pd(a, 25);
}
@@ -949,19 +953,19 @@ __m256i test_mm256_shuffle_epi8(__m256i a, __m256i b) {
__m256i test_mm256_shuffle_epi32(__m256i a) {
// CHECK-LABEL: test_mm256_shuffle_epi32
- // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> <i32 3, i32 3, i32 0, i32 0, i32 7, i32 7, i32 4, i32 4>
+ // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> undef, <8 x i32> <i32 3, i32 3, i32 0, i32 0, i32 7, i32 7, i32 4, i32 4>
return _mm256_shuffle_epi32(a, 15);
}
__m256i test_mm256_shufflehi_epi16(__m256i a) {
// CHECK-LABEL: test_mm256_shufflehi_epi16
- // CHECK: shufflevector <16 x i16> %{{.*}}, <16 x i16> %{{.*}}, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 7, i32 6, i32 6, i32 5, i32 8, i32 9, i32 10, i32 11, i32 15, i32 14, i32 14, i32 13>
+ // CHECK: shufflevector <16 x i16> %{{.*}}, <16 x i16> undef, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 7, i32 6, i32 6, i32 5, i32 8, i32 9, i32 10, i32 11, i32 15, i32 14, i32 14, i32 13>
return _mm256_shufflehi_epi16(a, 107);
}
__m256i test_mm256_shufflelo_epi16(__m256i a) {
// CHECK-LABEL: test_mm256_shufflelo_epi16
- // CHECK: shufflevector <16 x i16> %{{.*}}, <16 x i16> %{{.*}}, <16 x i32> <i32 3, i32 0, i32 1, i32 1, i32 4, i32 5, i32 6, i32 7, i32 11, i32 8, i32 9, i32 9, i32 12, i32 13, i32 14, i32 15>
+ // CHECK: shufflevector <16 x i16> %{{.*}}, <16 x i16> undef, <16 x i32> <i32 3, i32 0, i32 1, i32 1, i32 4, i32 5, i32 6, i32 7, i32 11, i32 8, i32 9, i32 9, i32 12, i32 13, i32 14, i32 15>
return _mm256_shufflelo_epi16(a, 83);
}
@@ -1003,7 +1007,7 @@ __m256i test_mm256_slli_epi64(__m256i a) {
__m256i test_mm256_slli_si256(__m256i a) {
// CHECK-LABEL: test_mm256_slli_si256
- // CHECK: shufflevector <32 x i8> %{{.*}}, <32 x i8> %{{.*}}, <32 x i32> <i32 13, i32 14, i32 15, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 29, i32 30, i32 31, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60>
+ // CHECK: shufflevector <32 x i8> zeroinitializer, <32 x i8> %{{.*}}, <32 x i32> <i32 13, i32 14, i32 15, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 29, i32 30, i32 31, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60>
return _mm256_slli_si256(a, 3);
}
@@ -1105,7 +1109,7 @@ __m256i test_mm256_srli_epi64(__m256i a) {
__m256i test_mm256_srli_si256(__m256i a) {
// CHECK-LABEL: test_mm256_srli_si256
- // CHECK: shufflevector <32 x i8> %{{.*}}, <32 x i8> %{{.*}}, <32 x i32> <i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 32, i32 33, i32 34, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 48, i32 49, i32 50>
+ // CHECK: shufflevector <32 x i8> %{{.*}}, <32 x i8> zeroinitializer, <32 x i32> <i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 32, i32 33, i32 34, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 48, i32 49, i32 50>
return _mm256_srli_si256(a, 3);
}
diff --git a/test/CodeGen/avx512-reduceIntrin.c b/test/CodeGen/avx512-reduceIntrin.c
index d24cd0e5634d..8157095fc644 100644
--- a/test/CodeGen/avx512-reduceIntrin.c
+++ b/test/CodeGen/avx512-reduceIntrin.c
@@ -1,410 +1,404 @@
-// RUN: %clang_cc1 -ffreestanding %s -O2 -triple=x86_64-apple-darwin -target-cpu skylake-avx512 -emit-llvm -o - -Wall -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -O0 -triple=x86_64-apple-darwin -target-cpu skylake-avx512 -emit-llvm -o - -Wall -Werror | FileCheck %s
#include <immintrin.h>
long long test_mm512_reduce_add_epi64(__m512i __W){
- // CHECK: %shuffle.i = shufflevector <8 x i64> %__W, <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
- // CHECK: %shuffle1.i = shufflevector <8 x i64> %__W, <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
- // CHECK: %add.i = add <4 x i64> %shuffle.i, %shuffle1.i
- // CHECK: %shuffle2.i = shufflevector <4 x i64> %add.i, <4 x i64> undef, <2 x i32> <i32 0, i32 1>
- // CHECK: %shuffle3.i = shufflevector <4 x i64> %add.i, <4 x i64> undef, <2 x i32> <i32 2, i32 3>
- // CHECK: %add4.i = add <2 x i64> %shuffle2.i, %shuffle3.i
- // CHECK: %shuffle6.i = shufflevector <2 x i64> %add4.i, <2 x i64> undef, <2 x i32> <i32 1, i32 undef>
- // CHECK: %add7.i = add <2 x i64> %shuffle6.i, %add4.i
- // CHECK: %vecext.i = extractelement <2 x i64> %add7.i, i32 0
- // CHECK: ret i64 %vecext.i
+// CHECK-LABEL: @test_mm512_reduce_add_epi64(
+// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK: add <4 x i64> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 0, i32 1>
+// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 2, i32 3>
+// CHECK: add <2 x i64> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i32> <i32 1, i32 0>
+// CHECK: add <2 x i64> %{{.*}}, %{{.*}}
+// CHECK: extractelement <2 x i64> %{{.*}}, i32 0
return _mm512_reduce_add_epi64(__W);
}
long long test_mm512_reduce_mul_epi64(__m512i __W){
- // CHECK: %shuffle.i = shufflevector <8 x i64> %__W, <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
- // CHECK: %shuffle1.i = shufflevector <8 x i64> %__W, <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
- // CHECK: %mul.i = mul <4 x i64> %shuffle.i, %shuffle1.i
- // CHECK: %shuffle2.i = shufflevector <4 x i64> %mul.i, <4 x i64> undef, <2 x i32> <i32 0, i32 1>
- // CHECK: %shuffle3.i = shufflevector <4 x i64> %mul.i, <4 x i64> undef, <2 x i32> <i32 2, i32 3>
- // CHECK: %mul4.i = mul <2 x i64> %shuffle2.i, %shuffle3.i
- // CHECK: %shuffle6.i = shufflevector <2 x i64> %mul4.i, <2 x i64> undef, <2 x i32> <i32 1, i32 undef>
- // CHECK: %mul7.i = mul <2 x i64> %shuffle6.i, %mul4.i
- // CHECK: %vecext.i = extractelement <2 x i64> %mul7.i, i32 0
- // CHECK: ret i64 %vecext.i
+// CHECK-LABEL: @test_mm512_reduce_mul_epi64(
+// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK: mul <4 x i64> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 0, i32 1>
+// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 2, i32 3>
+// CHECK: mul <2 x i64> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i32> <i32 1, i32 0>
+// CHECK: mul <2 x i64> %{{.*}}, %{{.*}}
+// CHECK: extractelement <2 x i64> %{{.*}}, i32 0
return _mm512_reduce_mul_epi64(__W);
}
long long test_mm512_reduce_or_epi64(__m512i __W){
- // CHECK: %shuffle.i = shufflevector <8 x i64> %__W, <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
- // CHECK: %shuffle1.i = shufflevector <8 x i64> %__W, <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
- // CHECK: %or.i = or <4 x i64> %shuffle.i, %shuffle1.i
- // CHECK: %shuffle2.i = shufflevector <4 x i64> %or.i, <4 x i64> undef, <2 x i32> <i32 0, i32 1>
- // CHECK: %shuffle3.i = shufflevector <4 x i64> %or.i, <4 x i64> undef, <2 x i32> <i32 2, i32 3>
- // CHECK: %or4.i = or <2 x i64> %shuffle2.i, %shuffle3.i
- // CHECK: %shuffle6.i = shufflevector <2 x i64> %or4.i, <2 x i64> undef, <2 x i32> <i32 1, i32 undef>
- // CHECK: %or7.i = or <2 x i64> %shuffle6.i, %or4.i
- // CHECK: %vecext.i = extractelement <2 x i64> %or7.i, i32 0
- // CHECK: ret i64 %vecext.i
+// CHECK-LABEL: @test_mm512_reduce_or_epi64(
+// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK: or <4 x i64> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 0, i32 1>
+// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 2, i32 3>
+// CHECK: or <2 x i64> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i32> <i32 1, i32 0>
+// CHECK: or <2 x i64> %{{.*}}, %{{.*}}
+// CHECK: extractelement <2 x i64> %{{.*}}, i32 0
return _mm512_reduce_or_epi64(__W);
}
long long test_mm512_reduce_and_epi64(__m512i __W){
- // CHECK: %shuffle.i = shufflevector <8 x i64> %__W, <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
- // CHECK: %shuffle1.i = shufflevector <8 x i64> %__W, <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
- // CHECK: %and.i = and <4 x i64> %shuffle.i, %shuffle1.i
- // CHECK: %shuffle2.i = shufflevector <4 x i64> %and.i, <4 x i64> undef, <2 x i32> <i32 0, i32 1>
- // CHECK: %shuffle3.i = shufflevector <4 x i64> %and.i, <4 x i64> undef, <2 x i32> <i32 2, i32 3>
- // CHECK: %and4.i = and <2 x i64> %shuffle2.i, %shuffle3.i
- // CHECK: %shuffle6.i = shufflevector <2 x i64> %and4.i, <2 x i64> undef, <2 x i32> <i32 1, i32 undef>
- // CHECK: %and7.i = and <2 x i64> %shuffle6.i, %and4.i
- // CHECK: %vecext.i = extractelement <2 x i64> %and7.i, i32 0
- // CHECK: ret i64 %vecext.i
+// CHECK-LABEL: @test_mm512_reduce_and_epi64(
+// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK: and <4 x i64> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 0, i32 1>
+// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 2, i32 3>
+// CHECK: and <2 x i64> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i32> <i32 1, i32 0>
+// CHECK: and <2 x i64> %{{.*}}, %{{.*}}
+// CHECK: extractelement <2 x i64> %{{.*}}, i32 0
return _mm512_reduce_and_epi64(__W);
}
long long test_mm512_mask_reduce_add_epi64(__mmask8 __M, __m512i __W){
- // CHECK: {{.*}} = bitcast i8 %__M to <8 x i1>
- // CHECK: {{.*}} = select <8 x i1> {{.*}}, <8 x i64> %__W, <8 x i64> zeroinitializer
- // CHECK: %shuffle.i = shufflevector <8 x i64> {{.*}}, <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
- // CHECK: %shuffle1.i = shufflevector <8 x i64> {{.*}}, <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
- // CHECK: %add.i = add <4 x i64> %shuffle.i, %shuffle1.i
- // CHECK: %shuffle2.i = shufflevector <4 x i64> %add.i, <4 x i64> undef, <2 x i32> <i32 0, i32 1>
- // CHECK: %shuffle3.i = shufflevector <4 x i64> %add.i, <4 x i64> undef, <2 x i32> <i32 2, i32 3>
- // CHECK: %add4.i = add <2 x i64> %shuffle2.i, %shuffle3.i
- // CHECK: %shuffle6.i = shufflevector <2 x i64> %add4.i, <2 x i64> undef, <2 x i32> <i32 1, i32 undef>
- // CHECK: %add7.i = add <2 x i64> %shuffle6.i, %add4.i
- // CHECK: %vecext.i = extractelement <2 x i64> %add7.i, i32 0
- // CHECK: ret i64 %vecext.i
+// CHECK-LABEL: @test_mm512_mask_reduce_add_epi64(
+// CHECK: bitcast i8 %{{.*}} to <8 x i1>
+// CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
+// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK: add <4 x i64> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 0, i32 1>
+// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 2, i32 3>
+// CHECK: add <2 x i64> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i32> <i32 1, i32 0>
+// CHECK: add <2 x i64> %{{.*}}, %{{.*}}
+// CHECK: extractelement <2 x i64> %{{.*}}, i32 0
return _mm512_mask_reduce_add_epi64(__M, __W);
}
long long test_mm512_mask_reduce_mul_epi64(__mmask8 __M, __m512i __W){
- // CHECK: {{.*}} = bitcast i8 %__M to <8 x i1>
- // CHECK: {{.*}} = select <8 x i1> {{.*}}, <8 x i64> %__W, <8 x i64> <i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1>
- // CHECK: %shuffle.i = shufflevector <8 x i64> {{.*}}, <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
- // CHECK: %shuffle1.i = shufflevector <8 x i64> {{.*}}, <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
- // CHECK: %mul.i = mul <4 x i64> %shuffle.i, %shuffle1.i
- // CHECK: %shuffle2.i = shufflevector <4 x i64> %mul.i, <4 x i64> undef, <2 x i32> <i32 0, i32 1>
- // CHECK: %shuffle3.i = shufflevector <4 x i64> %mul.i, <4 x i64> undef, <2 x i32> <i32 2, i32 3>
- // CHECK: %mul4.i = mul <2 x i64> %shuffle2.i, %shuffle3.i
- // CHECK: %shuffle6.i = shufflevector <2 x i64> %mul4.i, <2 x i64> undef, <2 x i32> <i32 1, i32 undef>
- // CHECK: %mul7.i = mul <2 x i64> %shuffle6.i, %mul4.i
- // CHECK: %vecext.i = extractelement <2 x i64> %mul7.i, i32 0
- // CHECK: ret i64 %vecext.i
+// CHECK-LABEL: @test_mm512_mask_reduce_mul_epi64(
+// CHECK: bitcast i8 %{{.*}} to <8 x i1>
+// CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
+// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK: mul <4 x i64> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 0, i32 1>
+// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 2, i32 3>
+// CHECK: mul <2 x i64> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i32> <i32 1, i32 0>
+// CHECK: mul <2 x i64> %{{.*}}, %{{.*}}
+// CHECK: extractelement <2 x i64> %{{.*}}, i32 0
return _mm512_mask_reduce_mul_epi64(__M, __W);
}
long long test_mm512_mask_reduce_and_epi64(__mmask8 __M, __m512i __W){
- // CHECK: {{.*}} = bitcast i8 %__M to <8 x i1>
- // CHECK: {{.*}} = select <8 x i1> {{.*}}, <8 x i64> %__W, <8 x i64> <i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1>
- // CHECK: %shuffle.i = shufflevector <8 x i64> {{.*}}, <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
- // CHECK: %shuffle1.i = shufflevector <8 x i64> {{.*}}, <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
- // CHECK: %and.i = and <4 x i64> %shuffle.i, %shuffle1.i
- // CHECK: %shuffle2.i = shufflevector <4 x i64> %and.i, <4 x i64> undef, <2 x i32> <i32 0, i32 1>
- // CHECK: %shuffle3.i = shufflevector <4 x i64> %and.i, <4 x i64> undef, <2 x i32> <i32 2, i32 3>
- // CHECK: %and4.i = and <2 x i64> %shuffle2.i, %shuffle3.i
- // CHECK: %shuffle6.i = shufflevector <2 x i64> %and4.i, <2 x i64> undef, <2 x i32> <i32 1, i32 undef>
- // CHECK: %and7.i = and <2 x i64> %shuffle6.i, %and4.i
- // CHECK: %vecext.i = extractelement <2 x i64> %and7.i, i32 0
+// CHECK-LABEL: @test_mm512_mask_reduce_and_epi64(
+// CHECK: bitcast i8 %{{.*}} to <8 x i1>
+// CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
+// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK: and <4 x i64> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 0, i32 1>
+// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 2, i32 3>
+// CHECK: and <2 x i64> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i32> <i32 1, i32 0>
+// CHECK: and <2 x i64> %{{.*}}, %{{.*}}
+// CHECK: extractelement <2 x i64> %{{.*}}, i32 0
return _mm512_mask_reduce_and_epi64(__M, __W);
}
long long test_mm512_mask_reduce_or_epi64(__mmask8 __M, __m512i __W){
- // CHECK: {{.*}} = bitcast i8 %__M to <8 x i1>
- // CHECK: {{.*}} = select <8 x i1> {{.*}}, <8 x i64> %__W, <8 x i64> zeroinitializer
- // CHECK: %shuffle.i = shufflevector <8 x i64> {{.*}}, <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
- // CHECK: %shuffle1.i = shufflevector <8 x i64> {{.*}}, <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
- // CHECK: %or.i = or <4 x i64> %shuffle.i, %shuffle1.i
- // CHECK: %shuffle2.i = shufflevector <4 x i64> %or.i, <4 x i64> undef, <2 x i32> <i32 0, i32 1>
- // CHECK: %shuffle3.i = shufflevector <4 x i64> %or.i, <4 x i64> undef, <2 x i32> <i32 2, i32 3>
- // CHECK: %or4.i = or <2 x i64> %shuffle2.i, %shuffle3.i
- // CHECK: %shuffle6.i = shufflevector <2 x i64> %or4.i, <2 x i64> undef, <2 x i32> <i32 1, i32 undef>
- // CHECK: %or7.i = or <2 x i64> %shuffle6.i, %or4.i
- // CHECK: %vecext.i = extractelement <2 x i64> %or7.i, i32 0
- // CHECK: ret i64 %vecext.i
+// CHECK-LABEL: @test_mm512_mask_reduce_or_epi64(
+// CHECK: bitcast i8 %{{.*}} to <8 x i1>
+// CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
+// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK: or <4 x i64> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 0, i32 1>
+// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 2, i32 3>
+// CHECK: or <2 x i64> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i32> <i32 1, i32 0>
+// CHECK: or <2 x i64> %{{.*}}, %{{.*}}
+// CHECK: extractelement <2 x i64> %{{.*}}, i32 0
return _mm512_mask_reduce_or_epi64(__M, __W);
}
int test_mm512_reduce_add_epi32(__m512i __W){
- // CHECK: {{.*}} = bitcast <8 x i64> %__W to <16 x i32>
- // CHECK: %shuffle.i = shufflevector <16 x i32> {{.*}}, <16 x i32> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
- // CHECK: %shuffle1.i = shufflevector <16 x i32> {{.*}}, <16 x i32> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
- // CHECK: %add.i = add <8 x i32> %shuffle.i, %shuffle1.i
- // CHECK: %shuffle2.i = shufflevector <8 x i32> %add.i, <8 x i32> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
- // CHECK: %shuffle3.i = shufflevector <8 x i32> %add.i, <8 x i32> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
- // CHECK: %add4.i = add <4 x i32> %shuffle2.i, %shuffle3.i
- // CHECK: %shuffle6.i = shufflevector <4 x i32> %add4.i, <4 x i32> undef, <4 x i32> <i32 2, i32 3, i32 undef, i32 undef>
- // CHECK: %add7.i = add <4 x i32> %shuffle6.i, %add4.i
- // CHECK: %shuffle9.i = shufflevector <4 x i32> %add7.i, <4 x i32> undef, <4 x i32> <i32 1, i32 undef, i32 undef, i32 undef>
- // CHECK: %add10.i = add <4 x i32> %shuffle9.i, %add7.i
- // CHECK: {{.*}} = bitcast <4 x i32> %add10.i to <2 x i64>
- // CHECK: %vecext.i = extractelement <2 x i64> {{.*}}, i32 0
- // CHECK: %conv.i = trunc i64 %vecext.i to i32
- // CHECK: ret i32 %conv.i
+// CHECK-LABEL: @test_mm512_reduce_add_epi32(
+// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK: add <8 x i32> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 0, i32 1>
+// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 2, i32 3>
+// CHECK: add <4 x i32> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 2, i32 3, i32 0, i32 1>
+// CHECK: add <4 x i32> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
+// CHECK: add <4 x i32> %{{.*}}, %{{.*}}
+// CHECK: extractelement <4 x i32> %{{.*}}, i32 0
return _mm512_reduce_add_epi32(__W);
}
int test_mm512_reduce_mul_epi32(__m512i __W){
- // CHECK: {{.*}} = bitcast <8 x i64> %__W to <16 x i32>
- // CHECK: %shuffle.i = shufflevector <16 x i32> {{.*}}, <16 x i32> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
- // CHECK: %shuffle1.i = shufflevector <16 x i32> {{.*}}, <16 x i32> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
- // CHECK: %mul.i = mul <8 x i32> %shuffle.i, %shuffle1.i
- // CHECK: %shuffle2.i = shufflevector <8 x i32> %mul.i, <8 x i32> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
- // CHECK: %shuffle3.i = shufflevector <8 x i32> %mul.i, <8 x i32> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
- // CHECK: %mul4.i = mul <4 x i32> %shuffle2.i, %shuffle3.i
- // CHECK: %shuffle6.i = shufflevector <4 x i32> %mul4.i, <4 x i32> undef, <4 x i32> <i32 2, i32 3, i32 undef, i32 undef>
- // CHECK: %mul7.i = mul <4 x i32> %shuffle6.i, %mul4.i
- // CHECK: %shuffle9.i = shufflevector <4 x i32> %mul7.i, <4 x i32> undef, <4 x i32> <i32 1, i32 undef, i32 undef, i32 undef>
- // CHECK: %mul10.i = mul <4 x i32> %shuffle9.i, %mul7.i
- // CHECK: {{.*}} = bitcast <4 x i32> %mul10.i to <2 x i64>
- // CHECK: %vecext.i = extractelement <2 x i64> {{.*}}, i32 0
- // CHECK: %conv.i = trunc i64 %vecext.i to i32
- // CHECK: ret i32 %conv.i
+// CHECK-LABEL: @test_mm512_reduce_mul_epi32(
+// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK: mul <8 x i32> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 0, i32 1>
+// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 2, i32 3>
+// CHECK: mul <4 x i32> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 2, i32 3, i32 0, i32 1>
+// CHECK: mul <4 x i32> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
+// CHECK: mul <4 x i32> %{{.*}}, %{{.*}}
+// CHECK: extractelement <4 x i32> %{{.*}}, i32 0
return _mm512_reduce_mul_epi32(__W);
}
int test_mm512_reduce_or_epi32(__m512i __W){
- // CHECK: {{.*}} = bitcast <8 x i64> %__W to <16 x i32>
- // CHECK: %shuffle.i = shufflevector <16 x i32> {{.*}}, <16 x i32> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
- // CHECK: %shuffle1.i = shufflevector <16 x i32> {{.*}}, <16 x i32> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
- // CHECK: %or.i = or <8 x i32> %shuffle.i, %shuffle1.i
- // CHECK: %shuffle2.i = shufflevector <8 x i32> %or.i, <8 x i32> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
- // CHECK: %shuffle3.i = shufflevector <8 x i32> %or.i, <8 x i32> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
- // CHECK: %or4.i = or <4 x i32> %shuffle2.i, %shuffle3.i
- // CHECK: %shuffle6.i = shufflevector <4 x i32> %or4.i, <4 x i32> undef, <4 x i32> <i32 2, i32 3, i32 undef, i32 undef>
- // CHECK: %or7.i = or <4 x i32> %shuffle6.i, %or4.i
- // CHECK: %shuffle9.i = shufflevector <4 x i32> %or7.i, <4 x i32> undef, <4 x i32> <i32 1, i32 undef, i32 undef, i32 undef>
- // CHECK: %or10.i = or <4 x i32> %shuffle9.i, %or7.i
- // CHECK: {{.*}} = bitcast <4 x i32> %or10.i to <2 x i64>
- // CHECK: %vecext.i = extractelement <2 x i64> {{.*}}, i32 0
- // CHECK: %conv.i = trunc i64 %vecext.i to i32
- // CHECK: ret i32 %conv.i
+// CHECK-LABEL: @test_mm512_reduce_or_epi32(
+// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK: or <8 x i32> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 0, i32 1>
+// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 2, i32 3>
+// CHECK: or <4 x i32> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 2, i32 3, i32 0, i32 1>
+// CHECK: or <4 x i32> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
+// CHECK: or <4 x i32> %{{.*}}, %{{.*}}
+// CHECK: extractelement <4 x i32> %{{.*}}, i32 0
return _mm512_reduce_or_epi32(__W);
}
int test_mm512_reduce_and_epi32(__m512i __W){
- // CHECK: {{.*}} = bitcast <8 x i64> %__W to <16 x i32>
- // CHECK: %shuffle.i = shufflevector <16 x i32> {{.*}}, <16 x i32> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
- // CHECK: %shuffle1.i = shufflevector <16 x i32> {{.*}}, <16 x i32> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
- // CHECK: %and.i = and <8 x i32> %shuffle.i, %shuffle1.i
- // CHECK: %shuffle2.i = shufflevector <8 x i32> %and.i, <8 x i32> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
- // CHECK: %shuffle3.i = shufflevector <8 x i32> %and.i, <8 x i32> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
- // CHECK: %and4.i = and <4 x i32> %shuffle2.i, %shuffle3.i
- // CHECK: %shuffle6.i = shufflevector <4 x i32> %and4.i, <4 x i32> undef, <4 x i32> <i32 2, i32 3, i32 undef, i32 undef>
- // CHECK: %and7.i = and <4 x i32> %shuffle6.i, %and4.i
- // CHECK: %shuffle9.i = shufflevector <4 x i32> %and7.i, <4 x i32> undef, <4 x i32> <i32 1, i32 undef, i32 undef, i32 undef>
- // CHECK: %and10.i = and <4 x i32> %shuffle9.i, %and7.i
- // CHECK: {{.*}} = bitcast <4 x i32> %and10.i to <2 x i64>
- // CHECK: %vecext.i = extractelement <2 x i64> {{.*}}, i32 0
- // CHECK: %conv.i = trunc i64 %vecext.i to i32
- // CHECK: ret i32 %conv.i
+// CHECK-LABEL: @test_mm512_reduce_and_epi32(
+// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK: and <8 x i32> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 0, i32 1>
+// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 2, i32 3>
+// CHECK: and <4 x i32> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 2, i32 3, i32 0, i32 1>
+// CHECK: and <4 x i32> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
+// CHECK: and <4 x i32> %{{.*}}, %{{.*}}
+// CHECK: extractelement <4 x i32> %{{.*}}, i32 0
return _mm512_reduce_and_epi32(__W);
}
int test_mm512_mask_reduce_add_epi32(__mmask16 __M, __m512i __W){
- // CHECK: {{.*}} = bitcast <8 x i64> %__W to <16 x i32>
- // CHECK: {{.*}} = bitcast i16 %__M to <16 x i1>
- // CHECK: {{.*}} = select <16 x i1> {{.*}}, <16 x i32> {{.*}}, <16 x i32> zeroinitializer
- // CHECK: %shuffle.i = shufflevector <16 x i32> {{.*}}, <16 x i32> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
- // CHECK: %shuffle1.i = shufflevector <16 x i32> {{.*}}, <16 x i32> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
- // CHECK: %add.i = add <8 x i32> %shuffle.i, %shuffle1.i
- // CHECK: %shuffle2.i = shufflevector <8 x i32> %add.i, <8 x i32> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
- // CHECK: %shuffle3.i = shufflevector <8 x i32> %add.i, <8 x i32> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
- // CHECK: %add4.i = add <4 x i32> %shuffle2.i, %shuffle3.i
- // CHECK: %shuffle6.i = shufflevector <4 x i32> %add4.i, <4 x i32> undef, <4 x i32> <i32 2, i32 3, i32 undef, i32 undef>
- // CHECK: %add7.i = add <4 x i32> %shuffle6.i, %add4.i
- // CHECK: %shuffle9.i = shufflevector <4 x i32> %add7.i, <4 x i32> undef, <4 x i32> <i32 1, i32 undef, i32 undef, i32 undef>
- // CHECK: %add10.i = add <4 x i32> %shuffle9.i, %add7.i
- // CHECK: {{.*}} = bitcast <4 x i32> %add10.i to <2 x i64>
- // CHECK: %vecext.i = extractelement <2 x i64> {{.*}}, i32 0
- // CHECK: %conv.i = trunc i64 %vecext.i to i32
- // CHECK: ret i32 %conv.i
+// CHECK-LABEL: @test_mm512_mask_reduce_add_epi32(
+// CHECK: bitcast i16 %{{.*}} to <16 x i1>
+// CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
+// CHECK: bitcast <16 x i32> %{{.*}} to <8 x i64>
+// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK: add <8 x i32> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 0, i32 1>
+// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 2, i32 3>
+// CHECK: add <4 x i32> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 2, i32 3, i32 0, i32 1>
+// CHECK: add <4 x i32> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
+// CHECK: add <4 x i32> %{{.*}}, %{{.*}}
+// CHECK: extractelement <4 x i32> %{{.*}}, i32 0
return _mm512_mask_reduce_add_epi32(__M, __W);
}
int test_mm512_mask_reduce_mul_epi32(__mmask16 __M, __m512i __W){
- // CHECK: {{.*}} = bitcast <8 x i64> %__W to <16 x i32>
- // CHECK: {{.*}} = bitcast i16 %__M to <16 x i1>
- // CHECK: {{.*}} = select <16 x i1> {{.*}}, <16 x i32> {{.*}}, <16 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
- // CHECK: %shuffle.i = shufflevector <16 x i32> {{.*}}, <16 x i32> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
- // CHECK: %shuffle1.i = shufflevector <16 x i32> {{.*}}, <16 x i32> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
- // CHECK: %mul.i = mul <8 x i32> %shuffle.i, %shuffle1.i
- // CHECK: %shuffle2.i = shufflevector <8 x i32> %mul.i, <8 x i32> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
- // CHECK: %shuffle3.i = shufflevector <8 x i32> %mul.i, <8 x i32> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
- // CHECK: %mul4.i = mul <4 x i32> %shuffle2.i, %shuffle3.i
- // CHECK: %shuffle6.i = shufflevector <4 x i32> %mul4.i, <4 x i32> undef, <4 x i32> <i32 2, i32 3, i32 undef, i32 undef>
- // CHECK: %mul7.i = mul <4 x i32> %shuffle6.i, %mul4.i
- // CHECK: %shuffle9.i = shufflevector <4 x i32> %mul7.i, <4 x i32> undef, <4 x i32> <i32 1, i32 undef, i32 undef, i32 undef>
- // CHECK: %mul10.i = mul <4 x i32> %shuffle9.i, %mul7.i
- // CHECK: {{.*}} = bitcast <4 x i32> %mul10.i to <2 x i64>
- // CHECK: %vecext.i = extractelement <2 x i64> {{.*}}, i32 0
- // CHECK: %conv.i = trunc i64 %vecext.i to i32
- // CHECK: ret i32 %conv.i
+// CHECK-LABEL: @test_mm512_mask_reduce_mul_epi32(
+// CHECK: bitcast i16 %{{.*}} to <16 x i1>
+// CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
+// CHECK: bitcast <16 x i32> %{{.*}} to <8 x i64>
+// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK: mul <8 x i32> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 0, i32 1>
+// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 2, i32 3>
+// CHECK: mul <4 x i32> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 2, i32 3, i32 0, i32 1>
+// CHECK: mul <4 x i32> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
+// CHECK: mul <4 x i32> %{{.*}}, %{{.*}}
+// CHECK: extractelement <4 x i32> %{{.*}}, i32 0
return _mm512_mask_reduce_mul_epi32(__M, __W);
}
int test_mm512_mask_reduce_and_epi32(__mmask16 __M, __m512i __W){
- // CHECK: {{.*}} = bitcast <8 x i64> %__W to <16 x i32>
- // CHECK: {{.*}} = bitcast i16 %__M to <16 x i1>
- // CHECK: {{.*}} = select <16 x i1> {{.*}}, <16 x i32> {{.*}}, <16 x i32> <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>
- // CHECK: %shuffle.i = shufflevector <16 x i32> {{.*}}, <16 x i32> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
- // CHECK: %shuffle1.i = shufflevector <16 x i32> {{.*}}, <16 x i32> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
- // CHECK: %and.i = and <8 x i32> %shuffle.i, %shuffle1.i
- // CHECK: %shuffle2.i = shufflevector <8 x i32> %and.i, <8 x i32> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
- // CHECK: %shuffle3.i = shufflevector <8 x i32> %and.i, <8 x i32> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
- // CHECK: %and4.i = and <4 x i32> %shuffle2.i, %shuffle3.i
- // CHECK: %shuffle6.i = shufflevector <4 x i32> %and4.i, <4 x i32> undef, <4 x i32> <i32 2, i32 3, i32 undef, i32 undef>
- // CHECK: %and7.i = and <4 x i32> %shuffle6.i, %and4.i
- // CHECK: %shuffle9.i = shufflevector <4 x i32> %and7.i, <4 x i32> undef, <4 x i32> <i32 1, i32 undef, i32 undef, i32 undef>
- // CHECK: %and10.i = and <4 x i32> %shuffle9.i, %and7.i
- // CHECK: {{.*}} = bitcast <4 x i32> %and10.i to <2 x i64>
- // CHECK: %vecext.i = extractelement <2 x i64> {{.*}}, i32 0
- // CHECK: %conv.i = trunc i64 %vecext.i to i32
- // CHECK: ret i32 %conv.i
+// CHECK-LABEL: @test_mm512_mask_reduce_and_epi32(
+// CHECK: bitcast i16 %{{.*}} to <16 x i1>
+// CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
+// CHECK: bitcast <16 x i32> %{{.*}} to <8 x i64>
+// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK: and <8 x i32> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 0, i32 1>
+// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 2, i32 3>
+// CHECK: and <4 x i32> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 2, i32 3, i32 0, i32 1>
+// CHECK: and <4 x i32> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
+// CHECK: and <4 x i32> %{{.*}}, %{{.*}}
+// CHECK: extractelement <4 x i32> %{{.*}}, i32 0
return _mm512_mask_reduce_and_epi32(__M, __W);
}
int test_mm512_mask_reduce_or_epi32(__mmask16 __M, __m512i __W){
- // CHECK: {{.*}} = bitcast <8 x i64> %__W to <16 x i32>
- // CHECK: {{.*}} = bitcast i16 %__M to <16 x i1>
- // CHECK: {{.*}} = select <16 x i1> {{.*}}, <16 x i32> {{.*}}, <16 x i32> zeroinitializer
- // CHECK: %shuffle.i = shufflevector <16 x i32> {{.*}}, <16 x i32> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
- // CHECK: %shuffle1.i = shufflevector <16 x i32> {{.*}}, <16 x i32> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
- // CHECK: %or.i = or <8 x i32> %shuffle.i, %shuffle1.i
- // CHECK: %shuffle2.i = shufflevector <8 x i32> %or.i, <8 x i32> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
- // CHECK: %shuffle3.i = shufflevector <8 x i32> %or.i, <8 x i32> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
- // CHECK: %or4.i = or <4 x i32> %shuffle2.i, %shuffle3.i
- // CHECK: %shuffle6.i = shufflevector <4 x i32> %or4.i, <4 x i32> undef, <4 x i32> <i32 2, i32 3, i32 undef, i32 undef>
- // CHECK: %or7.i = or <4 x i32> %shuffle6.i, %or4.i
- // CHECK: %shuffle9.i = shufflevector <4 x i32> %or7.i, <4 x i32> undef, <4 x i32> <i32 1, i32 undef, i32 undef, i32 undef>
- // CHECK: %or10.i = or <4 x i32> %shuffle9.i, %or7.i
- // CHECK: {{.*}} = bitcast <4 x i32> %or10.i to <2 x i64>
- // CHECK: %vecext.i = extractelement <2 x i64> {{.*}}, i32 0
- // CHECK: %conv.i = trunc i64 %vecext.i to i32
- // CHECK: ret i32 %conv.i
+// CHECK-LABEL: @test_mm512_mask_reduce_or_epi32(
+// CHECK: bitcast i16 %{{.*}} to <16 x i1>
+// CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
+// CHECK: bitcast <16 x i32> %{{.*}} to <8 x i64>
+// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK: or <8 x i32> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 0, i32 1>
+// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 2, i32 3>
+// CHECK: or <4 x i32> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 2, i32 3, i32 0, i32 1>
+// CHECK: or <4 x i32> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
+// CHECK: or <4 x i32> %{{.*}}, %{{.*}}
+// CHECK: extractelement <4 x i32> %{{.*}}, i32 0
return _mm512_mask_reduce_or_epi32(__M, __W);
}
double test_mm512_reduce_add_pd(__m512d __W){
- // CHECK: %shuffle.i = shufflevector <8 x double> %__W, <8 x double> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
- // CHECK: %shuffle1.i = shufflevector <8 x double> %__W, <8 x double> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
- // CHECK: %add.i = fadd <4 x double> %shuffle.i, %shuffle1.i
- // CHECK: %shuffle2.i = shufflevector <4 x double> %add.i, <4 x double> undef, <2 x i32> <i32 0, i32 1>
- // CHECK: %shuffle3.i = shufflevector <4 x double> %add.i, <4 x double> undef, <2 x i32> <i32 2, i32 3>
- // CHECK: %add4.i = fadd <2 x double> %shuffle2.i, %shuffle3.i
- // CHECK: %shuffle6.i = shufflevector <2 x double> %add4.i, <2 x double> undef, <2 x i32> <i32 1, i32 undef>
- // CHECK: %add7.i = fadd <2 x double> %add4.i, %shuffle6.i
- // CHECK: %vecext.i = extractelement <2 x double> %add7.i, i32 0
- // CHECK: ret double %vecext.i
+// CHECK-LABEL: @test_mm512_reduce_add_pd(
+// CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK: fadd <4 x double> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <2 x i32> <i32 0, i32 1>
+// CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <2 x i32> <i32 2, i32 3>
+// CHECK: fadd <2 x double> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x i32> <i32 1, i32 0>
+// CHECK: fadd <2 x double> %{{.*}}, %{{.*}}
+// CHECK: extractelement <2 x double> %{{.*}}, i32 0
return _mm512_reduce_add_pd(__W);
}
double test_mm512_reduce_mul_pd(__m512d __W){
- // CHECK: %shuffle.i = shufflevector <8 x double> %__W, <8 x double> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
- // CHECK: %shuffle1.i = shufflevector <8 x double> %__W, <8 x double> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
- // CHECK: %mul.i = fmul <4 x double> %shuffle.i, %shuffle1.i
- // CHECK: %shuffle2.i = shufflevector <4 x double> %mul.i, <4 x double> undef, <2 x i32> <i32 0, i32 1>
- // CHECK: %shuffle3.i = shufflevector <4 x double> %mul.i, <4 x double> undef, <2 x i32> <i32 2, i32 3>
- // CHECK: %mul4.i = fmul <2 x double> %shuffle2.i, %shuffle3.i
- // CHECK: %shuffle6.i = shufflevector <2 x double> %mul4.i, <2 x double> undef, <2 x i32> <i32 1, i32 undef>
- // CHECK: %mul7.i = fmul <2 x double> %mul4.i, %shuffle6.i
- // CHECK: %vecext.i = extractelement <2 x double> %mul7.i, i32 0
- // CHECK: ret double %vecext.i
+// CHECK-LABEL: @test_mm512_reduce_mul_pd(
+// CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK: fmul <4 x double> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <2 x i32> <i32 0, i32 1>
+// CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <2 x i32> <i32 2, i32 3>
+// CHECK: fmul <2 x double> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x i32> <i32 1, i32 0>
+// CHECK: fmul <2 x double> %{{.*}}, %{{.*}}
+// CHECK: extractelement <2 x double> %{{.*}}, i32 0
return _mm512_reduce_mul_pd(__W);
}
float test_mm512_reduce_add_ps(__m512 __W){
- // CHECK: %shuffle.i = shufflevector <16 x float> %__W, <16 x float> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
- // CHECK: %shuffle1.i = shufflevector <16 x float> %__W, <16 x float> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
- // CHECK: %add.i = fadd <8 x float> %shuffle.i, %shuffle1.i
- // CHECK: %shuffle2.i = shufflevector <8 x float> %add.i, <8 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
- // CHECK: %shuffle3.i = shufflevector <8 x float> %add.i, <8 x float> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
- // CHECK: %add4.i = fadd <4 x float> %shuffle2.i, %shuffle3.i
- // CHECK: %shuffle6.i = shufflevector <4 x float> %add4.i, <4 x float> undef, <4 x i32> <i32 2, i32 3, i32 undef, i32 undef>
- // CHECK: %add7.i = fadd <4 x float> %add4.i, %shuffle6.i
- // CHECK: %shuffle9.i = shufflevector <4 x float> %add7.i, <4 x float> undef, <4 x i32> <i32 1, i32 undef, i32 undef, i32 undef>
- // CHECK: %add10.i = fadd <4 x float> %add7.i, %shuffle9.i
- // CHECK: %vecext.i = extractelement <4 x float> %add10.i, i32 0
- // CHECK: ret float %vecext.i
+// CHECK-LABEL: @test_mm512_reduce_add_ps(
+// CHECK: bitcast <16 x float> %{{.*}} to <8 x double>
+// CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: bitcast <4 x double> %{{.*}} to <8 x float>
+// CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK: bitcast <4 x double> %{{.*}} to <8 x float>
+// CHECK: fadd <8 x float> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK: fadd <4 x float> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x i32> <i32 2, i32 3, i32 0, i32 1>
+// CHECK: fadd <4 x float> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
+// CHECK: fadd <4 x float> %{{.*}}, %{{.*}}
+// CHECK: extractelement <4 x float> %{{.*}}, i32 0
return _mm512_reduce_add_ps(__W);
}
float test_mm512_reduce_mul_ps(__m512 __W){
- // CHECK: %shuffle.i = shufflevector <16 x float> %__W, <16 x float> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
- // CHECK: %shuffle1.i = shufflevector <16 x float> %__W, <16 x float> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
- // CHECK: %mul.i = fmul <8 x float> %shuffle.i, %shuffle1.i
- // CHECK: %shuffle2.i = shufflevector <8 x float> %mul.i, <8 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
- // CHECK: %shuffle3.i = shufflevector <8 x float> %mul.i, <8 x float> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
- // CHECK: %mul4.i = fmul <4 x float> %shuffle2.i, %shuffle3.i
- // CHECK: %shuffle6.i = shufflevector <4 x float> %mul4.i, <4 x float> undef, <4 x i32> <i32 2, i32 3, i32 undef, i32 undef>
- // CHECK: %mul7.i = fmul <4 x float> %mul4.i, %shuffle6.i
- // CHECK: %shuffle9.i = shufflevector <4 x float> %mul7.i, <4 x float> undef, <4 x i32> <i32 1, i32 undef, i32 undef, i32 undef>
- // CHECK: %mul10.i = fmul <4 x float> %mul7.i, %shuffle9.i
- // CHECK: %vecext.i = extractelement <4 x float> %mul10.i, i32 0
- // CHECK: ret float %vecext.i
+// CHECK-LABEL: @test_mm512_reduce_mul_ps(
+// CHECK: bitcast <16 x float> %{{.*}} to <8 x double>
+// CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: bitcast <4 x double> %{{.*}} to <8 x float>
+// CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK: bitcast <4 x double> %{{.*}} to <8 x float>
+// CHECK: fmul <8 x float> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK: fmul <4 x float> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x i32> <i32 2, i32 3, i32 0, i32 1>
+// CHECK: fmul <4 x float> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
+// CHECK: fmul <4 x float> %{{.*}}, %{{.*}}
+// CHECK: extractelement <4 x float> %{{.*}}, i32 0
return _mm512_reduce_mul_ps(__W);
}
double test_mm512_mask_reduce_add_pd(__mmask8 __M, __m512d __W){
- // CHECK: {{.*}} = bitcast i8 %__M to <8 x i1>
- // CHECK: {{.*}} = select <8 x i1> {{.*}}, <8 x double> %__W, <8 x double> zeroinitializer
- // CHECK: %shuffle.i = shufflevector <8 x double> {{.*}}, <8 x double> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
- // CHECK: %shuffle1.i = shufflevector <8 x double> {{.*}}, <8 x double> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
- // CHECK: %add.i = fadd <4 x double> %shuffle.i, %shuffle1.i
- // CHECK: %shuffle2.i = shufflevector <4 x double> %add.i, <4 x double> undef, <2 x i32> <i32 0, i32 1>
- // CHECK: %shuffle3.i = shufflevector <4 x double> %add.i, <4 x double> undef, <2 x i32> <i32 2, i32 3>
- // CHECK: %add4.i = fadd <2 x double> %shuffle2.i, %shuffle3.i
- // CHECK: %shuffle6.i = shufflevector <2 x double> %add4.i, <2 x double> undef, <2 x i32> <i32 1, i32 undef>
- // CHECK: %add7.i = fadd <2 x double> %add4.i, %shuffle6.i
- // CHECK: %vecext.i = extractelement <2 x double> %add7.i, i32 0
- // CHECK: ret double %vecext.i
+// CHECK-LABEL: @test_mm512_mask_reduce_add_pd(
+// CHECK: bitcast i8 %{{.*}} to <8 x i1>
+// CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
+// CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK: fadd <4 x double> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <2 x i32> <i32 0, i32 1>
+// CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <2 x i32> <i32 2, i32 3>
+// CHECK: fadd <2 x double> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x i32> <i32 1, i32 0>
+// CHECK: fadd <2 x double> %{{.*}}, %{{.*}}
+// CHECK: extractelement <2 x double> %{{.*}}, i32 0
return _mm512_mask_reduce_add_pd(__M, __W);
}
double test_mm512_mask_reduce_mul_pd(__mmask8 __M, __m512d __W){
- // CHECK: {{.*}} = bitcast i8 %__M to <8 x i1>
- // CHECK: {{.*}} = select <8 x i1> {{.*}}, <8 x double> %__W, <8 x double> <double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00>
- // CHECK: %shuffle.i = shufflevector <8 x double> {{.*}}, <8 x double> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
- // CHECK: %shuffle1.i = shufflevector <8 x double> {{.*}}, <8 x double> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
- // CHECK: %mul.i = fmul <4 x double> %shuffle.i, %shuffle1.i
- // CHECK: %shuffle2.i = shufflevector <4 x double> %mul.i, <4 x double> undef, <2 x i32> <i32 0, i32 1>
- // CHECK: %shuffle3.i = shufflevector <4 x double> %mul.i, <4 x double> undef, <2 x i32> <i32 2, i32 3>
- // CHECK: %mul4.i = fmul <2 x double> %shuffle2.i, %shuffle3.i
- // CHECK: %shuffle6.i = shufflevector <2 x double> %mul4.i, <2 x double> undef, <2 x i32> <i32 1, i32 undef>
- // CHECK: %mul7.i = fmul <2 x double> %mul4.i, %shuffle6.i
- // CHECK: %vecext.i = extractelement <2 x double> %mul7.i, i32 0
- // CHECK: ret double %vecext.i
+// CHECK-LABEL: @test_mm512_mask_reduce_mul_pd(
+// CHECK: bitcast i8 %{{.*}} to <8 x i1>
+// CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
+// CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK: fmul <4 x double> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <2 x i32> <i32 0, i32 1>
+// CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <2 x i32> <i32 2, i32 3>
+// CHECK: fmul <2 x double> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x i32> <i32 1, i32 0>
+// CHECK: fmul <2 x double> %{{.*}}, %{{.*}}
+// CHECK: extractelement <2 x double> %{{.*}}, i32 0
return _mm512_mask_reduce_mul_pd(__M, __W);
}
float test_mm512_mask_reduce_add_ps(__mmask16 __M, __m512 __W){
- // CHECK: {{.*}} = bitcast i16 %__M to <16 x i1>
- // CHECK: {{.*}} = select <16 x i1> {{.*}}, <16 x float> %__W, <16 x float> zeroinitializer
- // CHECK: %shuffle.i = shufflevector <16 x float> {{.*}}, <16 x float> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
- // CHECK: %shuffle1.i = shufflevector <16 x float> {{.*}}, <16 x float> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
- // CHECK: %add.i = fadd <8 x float> %shuffle.i, %shuffle1.i
- // CHECK: %shuffle2.i = shufflevector <8 x float> %add.i, <8 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
- // CHECK: %shuffle3.i = shufflevector <8 x float> %add.i, <8 x float> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
- // CHECK: %add4.i = fadd <4 x float> %shuffle2.i, %shuffle3.i
- // CHECK: %shuffle6.i = shufflevector <4 x float> %add4.i, <4 x float> undef, <4 x i32> <i32 2, i32 3, i32 undef, i32 undef>
- // CHECK: %add7.i = fadd <4 x float> %add4.i, %shuffle6.i
- // CHECK: %shuffle9.i = shufflevector <4 x float> %add7.i, <4 x float> undef, <4 x i32> <i32 1, i32 undef, i32 undef, i32 undef>
- // CHECK: %add10.i = fadd <4 x float> %add7.i, %shuffle9.i
- // CHECK: %vecext.i = extractelement <4 x float> %add10.i, i32 0
- // CHECK: ret float %vecext.i
+// CHECK-LABEL: @test_mm512_mask_reduce_add_ps(
+// CHECK-NEXT: entry:
+// CHECK: bitcast i16 %{{.*}} to <16 x i1>
+// CHECK: select <16 x i1> %{{.*}}, <16 x float> {{.*}}, <16 x float> {{.*}}
+// CHECK: bitcast <16 x float> %{{.*}} to <8 x double>
+// CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: bitcast <4 x double> %{{.*}} to <8 x float>
+// CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK: bitcast <4 x double> %{{.*}} to <8 x float>
+// CHECK: fadd <8 x float> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK: fadd <4 x float> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x i32> <i32 2, i32 3, i32 0, i32 1>
+// CHECK: fadd <4 x float> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
+// CHECK: fadd <4 x float> %{{.*}}, %{{.*}}
+// CHECK: extractelement <4 x float> %{{.*}}, i32 0
return _mm512_mask_reduce_add_ps(__M, __W);
}
float test_mm512_mask_reduce_mul_ps(__mmask16 __M, __m512 __W){
- // CHECK: {{.*}} = bitcast i16 %__M to <16 x i1>
- // CHECK: {{.*}} = select <16 x i1> {{.*}}, <16 x float> %__W, <16 x float> <float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00>
- // CHECK: %shuffle.i = shufflevector <16 x float> {{.*}}, <16 x float> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
- // CHECK: %shuffle1.i = shufflevector <16 x float> {{.*}}, <16 x float> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
- // CHECK: %mul.i = fmul <8 x float> %shuffle.i, %shuffle1.i
- // CHECK: %shuffle2.i = shufflevector <8 x float> %mul.i, <8 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
- // CHECK: %shuffle3.i = shufflevector <8 x float> %mul.i, <8 x float> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
- // CHECK: %mul4.i = fmul <4 x float> %shuffle2.i, %shuffle3.i
- // CHECK: %shuffle6.i = shufflevector <4 x float> %mul4.i, <4 x float> undef, <4 x i32> <i32 2, i32 3, i32 undef, i32 undef>
- // CHECK: %mul7.i = fmul <4 x float> %mul4.i, %shuffle6.i
- // CHECK: %shuffle9.i = shufflevector <4 x float> %mul7.i, <4 x float> undef, <4 x i32> <i32 1, i32 undef, i32 undef, i32 undef>
- // CHECK: %mul10.i = fmul <4 x float> %mul7.i, %shuffle9.i
- // CHECK: %vecext.i = extractelement <4 x float> %mul10.i, i32 0
- // CHECK: ret float %vecext.i
+// CHECK-LABEL: @test_mm512_mask_reduce_mul_ps(
+// CHECK: bitcast i16 %{{.*}} to <16 x i1>
+// CHECK: select <16 x i1> %{{.*}}, <16 x float> {{.*}}, <16 x float> %{{.*}}
+// CHECK: bitcast <16 x float> %{{.*}} to <8 x double>
+// CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: bitcast <4 x double> %{{.*}} to <8 x float>
+// CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK: bitcast <4 x double> %{{.*}} to <8 x float>
+// CHECK: fmul <8 x float> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK: fmul <4 x float> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x i32> <i32 2, i32 3, i32 0, i32 1>
+// CHECK: fmul <4 x float> %{{.*}}, %{{.*}}
+// CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
+// CHECK: fmul <4 x float> %{{.*}}, %{{.*}}
+// CHECK: extractelement <4 x float> %{{.*}}, i32 0
return _mm512_mask_reduce_mul_ps(__M, __W);
}
diff --git a/test/CodeGen/avx512-reduceMinMaxIntrin.c b/test/CodeGen/avx512-reduceMinMaxIntrin.c
index 2081cef75460..fde7c0a273cd 100644
--- a/test/CodeGen/avx512-reduceMinMaxIntrin.c
+++ b/test/CodeGen/avx512-reduceMinMaxIntrin.c
@@ -3,2608 +3,2526 @@
#include <immintrin.h>
// CHECK-LABEL: define i64 @test_mm512_reduce_max_epi64(<8 x i64> %__W) #0 {
-// CHECK: [[_COMPOUNDLITERAL_I_I11_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I8_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I9_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64
-// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64
-// CHECK: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64
-// CHECK: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> [[TMP2]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP3]], <8 x i64> [[TMP4]], <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__A_ADDR_I_I]], align 64
-// CHECK: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__B_ADDR_I_I]], align 64
-// CHECK: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64
-// CHECK: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP7:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP8:%.*]] = icmp sgt <8 x i64> [[TMP5]], [[TMP6]]
-// CHECK: [[TMP9:%.*]] = select <8 x i1> [[TMP8]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]]
-// CHECK: store <8 x i64> [[TMP9]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <8 x i64> [[TMP10]], <8 x i64> [[TMP11]], <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP12]], <8 x i64> [[TMP13]], <8 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x i64> [[SHUFFLE2_I]], <8 x i64>* [[__A_ADDR_I12_I]], align 64
-// CHECK: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__B_ADDR_I13_I]], align 64
-// CHECK: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I12_I]], align 64
-// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I13_I]], align 64
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I11_I]], align 64
-// CHECK: [[TMP16:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I11_I]], align 64
-// CHECK: [[TMP17:%.*]] = icmp sgt <8 x i64> [[TMP14]], [[TMP15]]
-// CHECK: [[TMP18:%.*]] = select <8 x i1> [[TMP17]], <8 x i64> [[TMP14]], <8 x i64> [[TMP15]]
-// CHECK: store <8 x i64> [[TMP18]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP19]], <8 x i64> [[TMP20]], <8 x i32> <i32 0, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x i64> [[TMP21]], <8 x i64> [[TMP22]], <8 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x i64> [[SHUFFLE5_I]], <8 x i64>* [[__A_ADDR_I9_I]], align 64
-// CHECK: store <8 x i64> [[SHUFFLE6_I]], <8 x i64>* [[__B_ADDR_I10_I]], align 64
-// CHECK: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I9_I]], align 64
-// CHECK: [[TMP24:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I10_I]], align 64
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I8_I]], align 64
-// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I8_I]], align 64
-// CHECK: [[TMP26:%.*]] = icmp sgt <8 x i64> [[TMP23]], [[TMP24]]
-// CHECK: [[TMP27:%.*]] = select <8 x i1> [[TMP26]], <8 x i64> [[TMP23]], <8 x i64> [[TMP24]]
-// CHECK: store <8 x i64> [[TMP27]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP28]], i32 0
-// CHECK: ret i64 [[VECEXT_I]]
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[__A_ADDR_I7_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__B_ADDR_I8_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__A_ADDR_I5_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__B_ADDR_I6_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T4_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T5_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T6_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64
+// CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> [[TMP2]], <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3>
+// CHECK-NEXT: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__T1_I]], align 64
+// CHECK-NEXT: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[__T1_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP3]], <8 x i64>* [[__A_ADDR_I_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[__B_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP7:%.*]] = icmp sgt <8 x i64> [[TMP5]], [[TMP6]]
+// CHECK-NEXT: [[TMP8:%.*]] = select <8 x i1> [[TMP7]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]]
+// CHECK-NEXT: store <8 x i64> [[TMP8]], <8 x i64>* [[__T2_I]], align 64
+// CHECK-NEXT: [[TMP9:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64
+// CHECK-NEXT: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64
+// CHECK-NEXT: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP9]], <8 x i64> [[TMP10]], <8 x i32> <i32 2, i32 3, i32 0, i32 1, i32 6, i32 7, i32 4, i32 5>
+// CHECK-NEXT: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__T3_I]], align 64
+// CHECK-NEXT: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64
+// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__T3_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP11]], <8 x i64>* [[__A_ADDR_I7_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP12]], <8 x i64>* [[__B_ADDR_I8_I]], align 64
+// CHECK-NEXT: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I7_I]], align 64
+// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I8_I]], align 64
+// CHECK-NEXT: [[TMP15:%.*]] = icmp sgt <8 x i64> [[TMP13]], [[TMP14]]
+// CHECK-NEXT: [[TMP16:%.*]] = select <8 x i1> [[TMP15]], <8 x i64> [[TMP13]], <8 x i64> [[TMP14]]
+// CHECK-NEXT: store <8 x i64> [[TMP16]], <8 x i64>* [[__T4_I]], align 64
+// CHECK-NEXT: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64
+// CHECK-NEXT: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64
+// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6>
+// CHECK-NEXT: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__T5_I]], align 64
+// CHECK-NEXT: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64
+// CHECK-NEXT: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__T5_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP19]], <8 x i64>* [[__A_ADDR_I5_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP20]], <8 x i64>* [[__B_ADDR_I6_I]], align 64
+// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I5_I]], align 64
+// CHECK-NEXT: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I6_I]], align 64
+// CHECK-NEXT: [[TMP23:%.*]] = icmp sgt <8 x i64> [[TMP21]], [[TMP22]]
+// CHECK-NEXT: [[TMP24:%.*]] = select <8 x i1> [[TMP23]], <8 x i64> [[TMP21]], <8 x i64> [[TMP22]]
+// CHECK-NEXT: store <8 x i64> [[TMP24]], <8 x i64>* [[__T6_I]], align 64
+// CHECK-NEXT: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__T6_I]], align 64
+// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP25]], i32 0
+// CHECK-NEXT: ret i64 [[VECEXT_I]]
long long test_mm512_reduce_max_epi64(__m512i __W){
return _mm512_reduce_max_epi64(__W);
}
// CHECK-LABEL: define i64 @test_mm512_reduce_max_epu64(<8 x i64> %__W) #0 {
-// CHECK: [[_COMPOUNDLITERAL_I_I11_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I8_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I9_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64
-// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64
-// CHECK: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64
-// CHECK: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> [[TMP2]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP3]], <8 x i64> [[TMP4]], <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__A_ADDR_I_I]], align 64
-// CHECK: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__B_ADDR_I_I]], align 64
-// CHECK: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64
-// CHECK: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP7:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP8:%.*]] = icmp ugt <8 x i64> [[TMP5]], [[TMP6]]
-// CHECK: [[TMP9:%.*]] = select <8 x i1> [[TMP8]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]]
-// CHECK: store <8 x i64> [[TMP9]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <8 x i64> [[TMP10]], <8 x i64> [[TMP11]], <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP12]], <8 x i64> [[TMP13]], <8 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x i64> [[SHUFFLE2_I]], <8 x i64>* [[__A_ADDR_I12_I]], align 64
-// CHECK: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__B_ADDR_I13_I]], align 64
-// CHECK: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I12_I]], align 64
-// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I13_I]], align 64
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I11_I]], align 64
-// CHECK: [[TMP16:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I11_I]], align 64
-// CHECK: [[TMP17:%.*]] = icmp ugt <8 x i64> [[TMP14]], [[TMP15]]
-// CHECK: [[TMP18:%.*]] = select <8 x i1> [[TMP17]], <8 x i64> [[TMP14]], <8 x i64> [[TMP15]]
-// CHECK: store <8 x i64> [[TMP18]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP19]], <8 x i64> [[TMP20]], <8 x i32> <i32 0, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x i64> [[TMP21]], <8 x i64> [[TMP22]], <8 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x i64> [[SHUFFLE5_I]], <8 x i64>* [[__A_ADDR_I9_I]], align 64
-// CHECK: store <8 x i64> [[SHUFFLE6_I]], <8 x i64>* [[__B_ADDR_I10_I]], align 64
-// CHECK: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I9_I]], align 64
-// CHECK: [[TMP24:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I10_I]], align 64
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I8_I]], align 64
-// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I8_I]], align 64
-// CHECK: [[TMP26:%.*]] = icmp ugt <8 x i64> [[TMP23]], [[TMP24]]
-// CHECK: [[TMP27:%.*]] = select <8 x i1> [[TMP26]], <8 x i64> [[TMP23]], <8 x i64> [[TMP24]]
-// CHECK: store <8 x i64> [[TMP27]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP28]], i32 0
-// CHECK: ret i64 [[VECEXT_I]]
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[__A_ADDR_I7_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__B_ADDR_I8_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__A_ADDR_I5_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__B_ADDR_I6_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T4_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T5_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T6_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64
+// CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> [[TMP2]], <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3>
+// CHECK-NEXT: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__T1_I]], align 64
+// CHECK-NEXT: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[__T1_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP3]], <8 x i64>* [[__A_ADDR_I_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[__B_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP7:%.*]] = icmp ugt <8 x i64> [[TMP5]], [[TMP6]]
+// CHECK-NEXT: [[TMP8:%.*]] = select <8 x i1> [[TMP7]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]]
+// CHECK-NEXT: store <8 x i64> [[TMP8]], <8 x i64>* [[__T2_I]], align 64
+// CHECK-NEXT: [[TMP9:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64
+// CHECK-NEXT: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64
+// CHECK-NEXT: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP9]], <8 x i64> [[TMP10]], <8 x i32> <i32 2, i32 3, i32 0, i32 1, i32 6, i32 7, i32 4, i32 5>
+// CHECK-NEXT: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__T3_I]], align 64
+// CHECK-NEXT: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64
+// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__T3_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP11]], <8 x i64>* [[__A_ADDR_I7_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP12]], <8 x i64>* [[__B_ADDR_I8_I]], align 64
+// CHECK-NEXT: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I7_I]], align 64
+// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I8_I]], align 64
+// CHECK-NEXT: [[TMP15:%.*]] = icmp ugt <8 x i64> [[TMP13]], [[TMP14]]
+// CHECK-NEXT: [[TMP16:%.*]] = select <8 x i1> [[TMP15]], <8 x i64> [[TMP13]], <8 x i64> [[TMP14]]
+// CHECK-NEXT: store <8 x i64> [[TMP16]], <8 x i64>* [[__T4_I]], align 64
+// CHECK-NEXT: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64
+// CHECK-NEXT: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64
+// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6>
+// CHECK-NEXT: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__T5_I]], align 64
+// CHECK-NEXT: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64
+// CHECK-NEXT: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__T5_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP19]], <8 x i64>* [[__A_ADDR_I5_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP20]], <8 x i64>* [[__B_ADDR_I6_I]], align 64
+// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I5_I]], align 64
+// CHECK-NEXT: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I6_I]], align 64
+// CHECK-NEXT: [[TMP23:%.*]] = icmp ugt <8 x i64> [[TMP21]], [[TMP22]]
+// CHECK-NEXT: [[TMP24:%.*]] = select <8 x i1> [[TMP23]], <8 x i64> [[TMP21]], <8 x i64> [[TMP22]]
+// CHECK-NEXT: store <8 x i64> [[TMP24]], <8 x i64>* [[__T6_I]], align 64
+// CHECK-NEXT: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__T6_I]], align 64
+// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP25]], i32 0
+// CHECK-NEXT: ret i64 [[VECEXT_I]]
unsigned long long test_mm512_reduce_max_epu64(__m512i __W){
return _mm512_reduce_max_epu64(__W);
}
// CHECK-LABEL: define double @test_mm512_reduce_max_pd(<8 x double> %__W) #0 {
-// CHECK: [[_COMPOUNDLITERAL_I_I11_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I8_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__A_ADDR_I9_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__B_ADDR_I10_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__W_ADDR:%.*]] = alloca <8 x double>, align 64
-// CHECK: store <8 x double> %__W, <8 x double>* [[__W_ADDR]], align 64
-// CHECK: [[TMP0:%.*]] = load <8 x double>, <8 x double>* [[__W_ADDR]], align 64
-// CHECK: store <8 x double> [[TMP0]], <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP1:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP2:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x double> [[TMP1]], <8 x double> [[TMP2]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP3:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP4:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x double> [[TMP3]], <8 x double> [[TMP4]], <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x double> [[SHUFFLE_I]], <8 x double>* [[__A_ADDR_I_I]], align 64
-// CHECK: store <8 x double> [[SHUFFLE1_I]], <8 x double>* [[__B_ADDR_I_I]], align 64
-// CHECK: [[TMP5:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I_I]], align 64
-// CHECK: [[TMP6:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I_I]], align 64
-// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP7:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP8:%.*]] = call <8 x double> @llvm.x86.avx512.mask.max.pd.512(<8 x double> [[TMP5]], <8 x double> [[TMP6]], <8 x double> [[TMP7]], i8 -1, i32 4) #2
-// CHECK: store <8 x double> [[TMP8]], <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP9:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP10:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <8 x double> [[TMP9]], <8 x double> [[TMP10]], <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP11:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP12:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x double> [[TMP11]], <8 x double> [[TMP12]], <8 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x double> [[SHUFFLE2_I]], <8 x double>* [[__A_ADDR_I12_I]], align 64
-// CHECK: store <8 x double> [[SHUFFLE3_I]], <8 x double>* [[__B_ADDR_I13_I]], align 64
-// CHECK: [[TMP13:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I12_I]], align 64
-// CHECK: [[TMP14:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I13_I]], align 64
-// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I11_I]], align 64
-// CHECK: [[TMP15:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I11_I]], align 64
-// CHECK: [[TMP16:%.*]] = call <8 x double> @llvm.x86.avx512.mask.max.pd.512(<8 x double> [[TMP13]], <8 x double> [[TMP14]], <8 x double> [[TMP15]], i8 -1, i32 4) #2
-// CHECK: store <8 x double> [[TMP16]], <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP17:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP18:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <8 x double> [[TMP17]], <8 x double> [[TMP18]], <8 x i32> <i32 0, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP19:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP20:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x double> [[TMP19]], <8 x double> [[TMP20]], <8 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x double> [[SHUFFLE5_I]], <8 x double>* [[__A_ADDR_I9_I]], align 64
-// CHECK: store <8 x double> [[SHUFFLE6_I]], <8 x double>* [[__B_ADDR_I10_I]], align 64
-// CHECK: [[TMP21:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I9_I]], align 64
-// CHECK: [[TMP22:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I10_I]], align 64
-// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I8_I]], align 64
-// CHECK: [[TMP23:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I8_I]], align 64
-// CHECK: [[TMP24:%.*]] = call <8 x double> @llvm.x86.avx512.mask.max.pd.512(<8 x double> [[TMP21]], <8 x double> [[TMP22]], <8 x double> [[TMP23]], i8 -1, i32 4) #2
-// CHECK: store <8 x double> [[TMP24]], <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP25:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x double> [[TMP25]], i32 0
-// CHECK: ret double [[VECEXT_I]]
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[__A_ADDR_I10_I:%.*]] = alloca <4 x double>, align 32
+// CHECK-NEXT: [[__B_ADDR_I11_I:%.*]] = alloca <4 x double>, align 32
+// CHECK-NEXT: [[__A_ADDR_I8_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__B_ADDR_I9_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x double>, align 64
+// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x double>, align 32
+// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x double>, align 32
+// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x double>, align 32
+// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x double>, align 64
+// CHECK-NEXT: store <8 x double> [[__W:%.*]], <8 x double>* [[__W_ADDR]], align 64
+// CHECK-NEXT: [[TMP0:%.*]] = load <8 x double>, <8 x double>* [[__W_ADDR]], align 64
+// CHECK-NEXT: store <8 x double> [[TMP0]], <8 x double>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP1:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[EXTRACT_I:%.*]] = shufflevector <8 x double> [[TMP1]], <8 x double> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK-NEXT: store <4 x double> [[EXTRACT_I]], <4 x double>* [[__T1_I]], align 32
+// CHECK-NEXT: [[TMP2:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[EXTRACT2_I:%.*]] = shufflevector <8 x double> [[TMP2]], <8 x double> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK-NEXT: store <4 x double> [[EXTRACT2_I]], <4 x double>* [[__T2_I]], align 32
+// CHECK-NEXT: [[TMP3:%.*]] = load <4 x double>, <4 x double>* [[__T1_I]], align 32
+// CHECK-NEXT: [[TMP4:%.*]] = load <4 x double>, <4 x double>* [[__T2_I]], align 32
+// CHECK-NEXT: store <4 x double> [[TMP3]], <4 x double>* [[__A_ADDR_I10_I]], align 32
+// CHECK-NEXT: store <4 x double> [[TMP4]], <4 x double>* [[__B_ADDR_I11_I]], align 32
+// CHECK-NEXT: [[TMP5:%.*]] = load <4 x double>, <4 x double>* [[__A_ADDR_I10_I]], align 32
+// CHECK-NEXT: [[TMP6:%.*]] = load <4 x double>, <4 x double>* [[__B_ADDR_I11_I]], align 32
+// CHECK-NEXT: [[TMP7:%.*]] = call <4 x double> @llvm.x86.avx.max.pd.256(<4 x double> [[TMP5]], <4 x double> [[TMP6]]) #2
+// CHECK-NEXT: store <4 x double> [[TMP7]], <4 x double>* [[__T3_I]], align 32
+// CHECK-NEXT: [[TMP8:%.*]] = load <4 x double>, <4 x double>* [[__T3_I]], align 32
+// CHECK-NEXT: [[EXTRACT4_I:%.*]] = shufflevector <4 x double> [[TMP8]], <4 x double> undef, <2 x i32> <i32 0, i32 1>
+// CHECK-NEXT: store <2 x double> [[EXTRACT4_I]], <2 x double>* [[__T4_I]], align 16
+// CHECK-NEXT: [[TMP9:%.*]] = load <4 x double>, <4 x double>* [[__T3_I]], align 32
+// CHECK-NEXT: [[EXTRACT5_I:%.*]] = shufflevector <4 x double> [[TMP9]], <4 x double> undef, <2 x i32> <i32 2, i32 3>
+// CHECK-NEXT: store <2 x double> [[EXTRACT5_I]], <2 x double>* [[__T5_I]], align 16
+// CHECK-NEXT: [[TMP10:%.*]] = load <2 x double>, <2 x double>* [[__T4_I]], align 16
+// CHECK-NEXT: [[TMP11:%.*]] = load <2 x double>, <2 x double>* [[__T5_I]], align 16
+// CHECK-NEXT: store <2 x double> [[TMP10]], <2 x double>* [[__A_ADDR_I8_I]], align 16
+// CHECK-NEXT: store <2 x double> [[TMP11]], <2 x double>* [[__B_ADDR_I9_I]], align 16
+// CHECK-NEXT: [[TMP12:%.*]] = load <2 x double>, <2 x double>* [[__A_ADDR_I8_I]], align 16
+// CHECK-NEXT: [[TMP13:%.*]] = load <2 x double>, <2 x double>* [[__B_ADDR_I9_I]], align 16
+// CHECK-NEXT: [[TMP14:%.*]] = call <2 x double> @llvm.x86.sse2.max.pd(<2 x double> [[TMP12]], <2 x double> [[TMP13]]) #2
+// CHECK-NEXT: store <2 x double> [[TMP14]], <2 x double>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP15:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP16:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <2 x double> [[TMP15]], <2 x double> [[TMP16]], <2 x i32> <i32 1, i32 0>
+// CHECK-NEXT: store <2 x double> [[SHUFFLE_I]], <2 x double>* [[__T7_I]], align 16
+// CHECK-NEXT: [[TMP17:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP18:%.*]] = load <2 x double>, <2 x double>* [[__T7_I]], align 16
+// CHECK-NEXT: store <2 x double> [[TMP17]], <2 x double>* [[__A_ADDR_I_I]], align 16
+// CHECK-NEXT: store <2 x double> [[TMP18]], <2 x double>* [[__B_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP19:%.*]] = load <2 x double>, <2 x double>* [[__A_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP20:%.*]] = load <2 x double>, <2 x double>* [[__B_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP21:%.*]] = call <2 x double> @llvm.x86.sse2.max.pd(<2 x double> [[TMP19]], <2 x double> [[TMP20]]) #2
+// CHECK-NEXT: store <2 x double> [[TMP21]], <2 x double>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP22:%.*]] = load <2 x double>, <2 x double>* [[__T8_I]], align 16
+// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <2 x double> [[TMP22]], i32 0
+// CHECK-NEXT: ret double [[VECEXT_I]]
double test_mm512_reduce_max_pd(__m512d __W){
return _mm512_reduce_max_pd(__W);
}
// CHECK-LABEL: define i64 @test_mm512_reduce_min_epi64(<8 x i64> %__W) #0 {
-// CHECK: [[_COMPOUNDLITERAL_I_I11_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I8_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I9_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64
-// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64
-// CHECK: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64
-// CHECK: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> [[TMP2]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP3]], <8 x i64> [[TMP4]], <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__A_ADDR_I_I]], align 64
-// CHECK: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__B_ADDR_I_I]], align 64
-// CHECK: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64
-// CHECK: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP7:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP8:%.*]] = icmp sgt <8 x i64> [[TMP5]], [[TMP6]]
-// CHECK: [[TMP9:%.*]] = select <8 x i1> [[TMP8]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]]
-// CHECK: store <8 x i64> [[TMP9]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <8 x i64> [[TMP10]], <8 x i64> [[TMP11]], <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP12]], <8 x i64> [[TMP13]], <8 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x i64> [[SHUFFLE2_I]], <8 x i64>* [[__A_ADDR_I12_I]], align 64
-// CHECK: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__B_ADDR_I13_I]], align 64
-// CHECK: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I12_I]], align 64
-// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I13_I]], align 64
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I11_I]], align 64
-// CHECK: [[TMP16:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I11_I]], align 64
-// CHECK: [[TMP17:%.*]] = icmp sgt <8 x i64> [[TMP14]], [[TMP15]]
-// CHECK: [[TMP18:%.*]] = select <8 x i1> [[TMP17]], <8 x i64> [[TMP14]], <8 x i64> [[TMP15]]
-// CHECK: store <8 x i64> [[TMP18]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP19]], <8 x i64> [[TMP20]], <8 x i32> <i32 0, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x i64> [[TMP21]], <8 x i64> [[TMP22]], <8 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x i64> [[SHUFFLE5_I]], <8 x i64>* [[__A_ADDR_I9_I]], align 64
-// CHECK: store <8 x i64> [[SHUFFLE6_I]], <8 x i64>* [[__B_ADDR_I10_I]], align 64
-// CHECK: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I9_I]], align 64
-// CHECK: [[TMP24:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I10_I]], align 64
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I8_I]], align 64
-// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I8_I]], align 64
-// CHECK: [[TMP26:%.*]] = icmp sgt <8 x i64> [[TMP23]], [[TMP24]]
-// CHECK: [[TMP27:%.*]] = select <8 x i1> [[TMP26]], <8 x i64> [[TMP23]], <8 x i64> [[TMP24]]
-// CHECK: store <8 x i64> [[TMP27]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP28]], i32 0
-// CHECK: ret i64 [[VECEXT_I]]
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[__A_ADDR_I7_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__B_ADDR_I8_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__A_ADDR_I5_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__B_ADDR_I6_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T4_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T5_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T6_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64
+// CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> [[TMP2]], <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3>
+// CHECK-NEXT: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__T1_I]], align 64
+// CHECK-NEXT: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[__T1_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP3]], <8 x i64>* [[__A_ADDR_I_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[__B_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP7:%.*]] = icmp slt <8 x i64> [[TMP5]], [[TMP6]]
+// CHECK-NEXT: [[TMP8:%.*]] = select <8 x i1> [[TMP7]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]]
+// CHECK-NEXT: store <8 x i64> [[TMP8]], <8 x i64>* [[__T2_I]], align 64
+// CHECK-NEXT: [[TMP9:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64
+// CHECK-NEXT: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64
+// CHECK-NEXT: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP9]], <8 x i64> [[TMP10]], <8 x i32> <i32 2, i32 3, i32 0, i32 1, i32 6, i32 7, i32 4, i32 5>
+// CHECK-NEXT: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__T3_I]], align 64
+// CHECK-NEXT: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64
+// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__T3_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP11]], <8 x i64>* [[__A_ADDR_I7_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP12]], <8 x i64>* [[__B_ADDR_I8_I]], align 64
+// CHECK-NEXT: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I7_I]], align 64
+// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I8_I]], align 64
+// CHECK-NEXT: [[TMP15:%.*]] = icmp slt <8 x i64> [[TMP13]], [[TMP14]]
+// CHECK-NEXT: [[TMP16:%.*]] = select <8 x i1> [[TMP15]], <8 x i64> [[TMP13]], <8 x i64> [[TMP14]]
+// CHECK-NEXT: store <8 x i64> [[TMP16]], <8 x i64>* [[__T4_I]], align 64
+// CHECK-NEXT: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64
+// CHECK-NEXT: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64
+// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6>
+// CHECK-NEXT: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__T5_I]], align 64
+// CHECK-NEXT: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64
+// CHECK-NEXT: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__T5_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP19]], <8 x i64>* [[__A_ADDR_I5_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP20]], <8 x i64>* [[__B_ADDR_I6_I]], align 64
+// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I5_I]], align 64
+// CHECK-NEXT: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I6_I]], align 64
+// CHECK-NEXT: [[TMP23:%.*]] = icmp slt <8 x i64> [[TMP21]], [[TMP22]]
+// CHECK-NEXT: [[TMP24:%.*]] = select <8 x i1> [[TMP23]], <8 x i64> [[TMP21]], <8 x i64> [[TMP22]]
+// CHECK-NEXT: store <8 x i64> [[TMP24]], <8 x i64>* [[__T6_I]], align 64
+// CHECK-NEXT: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__T6_I]], align 64
+// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP25]], i32 0
+// CHECK-NEXT: ret i64 [[VECEXT_I]]
long long test_mm512_reduce_min_epi64(__m512i __W){
- return _mm512_reduce_max_epi64(__W);
+ return _mm512_reduce_min_epi64(__W);
}
// CHECK-LABEL: define i64 @test_mm512_reduce_min_epu64(<8 x i64> %__W) #0 {
-// CHECK: [[_COMPOUNDLITERAL_I_I11_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I8_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I9_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64
-// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64
-// CHECK: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64
-// CHECK: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> [[TMP2]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP3]], <8 x i64> [[TMP4]], <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__A_ADDR_I_I]], align 64
-// CHECK: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__B_ADDR_I_I]], align 64
-// CHECK: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64
-// CHECK: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP7:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP8:%.*]] = icmp ugt <8 x i64> [[TMP5]], [[TMP6]]
-// CHECK: [[TMP9:%.*]] = select <8 x i1> [[TMP8]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]]
-// CHECK: store <8 x i64> [[TMP9]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <8 x i64> [[TMP10]], <8 x i64> [[TMP11]], <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP12]], <8 x i64> [[TMP13]], <8 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x i64> [[SHUFFLE2_I]], <8 x i64>* [[__A_ADDR_I12_I]], align 64
-// CHECK: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__B_ADDR_I13_I]], align 64
-// CHECK: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I12_I]], align 64
-// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I13_I]], align 64
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I11_I]], align 64
-// CHECK: [[TMP16:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I11_I]], align 64
-// CHECK: [[TMP17:%.*]] = icmp ugt <8 x i64> [[TMP14]], [[TMP15]]
-// CHECK: [[TMP18:%.*]] = select <8 x i1> [[TMP17]], <8 x i64> [[TMP14]], <8 x i64> [[TMP15]]
-// CHECK: store <8 x i64> [[TMP18]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP19]], <8 x i64> [[TMP20]], <8 x i32> <i32 0, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x i64> [[TMP21]], <8 x i64> [[TMP22]], <8 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x i64> [[SHUFFLE5_I]], <8 x i64>* [[__A_ADDR_I9_I]], align 64
-// CHECK: store <8 x i64> [[SHUFFLE6_I]], <8 x i64>* [[__B_ADDR_I10_I]], align 64
-// CHECK: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I9_I]], align 64
-// CHECK: [[TMP24:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I10_I]], align 64
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I8_I]], align 64
-// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I8_I]], align 64
-// CHECK: [[TMP26:%.*]] = icmp ugt <8 x i64> [[TMP23]], [[TMP24]]
-// CHECK: [[TMP27:%.*]] = select <8 x i1> [[TMP26]], <8 x i64> [[TMP23]], <8 x i64> [[TMP24]]
-// CHECK: store <8 x i64> [[TMP27]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP28]], i32 0
-// CHECK: ret i64 [[VECEXT_I]]
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[__A_ADDR_I7_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__B_ADDR_I8_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__A_ADDR_I5_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__B_ADDR_I6_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T4_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T5_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T6_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64
+// CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> [[TMP2]], <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3>
+// CHECK-NEXT: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__T1_I]], align 64
+// CHECK-NEXT: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[__T1_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP3]], <8 x i64>* [[__A_ADDR_I_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[__B_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP7:%.*]] = icmp ult <8 x i64> [[TMP5]], [[TMP6]]
+// CHECK-NEXT: [[TMP8:%.*]] = select <8 x i1> [[TMP7]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]]
+// CHECK-NEXT: store <8 x i64> [[TMP8]], <8 x i64>* [[__T2_I]], align 64
+// CHECK-NEXT: [[TMP9:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64
+// CHECK-NEXT: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64
+// CHECK-NEXT: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP9]], <8 x i64> [[TMP10]], <8 x i32> <i32 2, i32 3, i32 0, i32 1, i32 6, i32 7, i32 4, i32 5>
+// CHECK-NEXT: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__T3_I]], align 64
+// CHECK-NEXT: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64
+// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__T3_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP11]], <8 x i64>* [[__A_ADDR_I7_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP12]], <8 x i64>* [[__B_ADDR_I8_I]], align 64
+// CHECK-NEXT: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I7_I]], align 64
+// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I8_I]], align 64
+// CHECK-NEXT: [[TMP15:%.*]] = icmp ult <8 x i64> [[TMP13]], [[TMP14]]
+// CHECK-NEXT: [[TMP16:%.*]] = select <8 x i1> [[TMP15]], <8 x i64> [[TMP13]], <8 x i64> [[TMP14]]
+// CHECK-NEXT: store <8 x i64> [[TMP16]], <8 x i64>* [[__T4_I]], align 64
+// CHECK-NEXT: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64
+// CHECK-NEXT: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64
+// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6>
+// CHECK-NEXT: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__T5_I]], align 64
+// CHECK-NEXT: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64
+// CHECK-NEXT: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__T5_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP19]], <8 x i64>* [[__A_ADDR_I5_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP20]], <8 x i64>* [[__B_ADDR_I6_I]], align 64
+// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I5_I]], align 64
+// CHECK-NEXT: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I6_I]], align 64
+// CHECK-NEXT: [[TMP23:%.*]] = icmp ult <8 x i64> [[TMP21]], [[TMP22]]
+// CHECK-NEXT: [[TMP24:%.*]] = select <8 x i1> [[TMP23]], <8 x i64> [[TMP21]], <8 x i64> [[TMP22]]
+// CHECK-NEXT: store <8 x i64> [[TMP24]], <8 x i64>* [[__T6_I]], align 64
+// CHECK-NEXT: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__T6_I]], align 64
+// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP25]], i32 0
+// CHECK-NEXT: ret i64 [[VECEXT_I]]
unsigned long long test_mm512_reduce_min_epu64(__m512i __W){
- return _mm512_reduce_max_epu64(__W);
+ return _mm512_reduce_min_epu64(__W);
}
// CHECK-LABEL: define double @test_mm512_reduce_min_pd(<8 x double> %__W) #0 {
-// CHECK: [[_COMPOUNDLITERAL_I_I11_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I8_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__A_ADDR_I9_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__B_ADDR_I10_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__W_ADDR:%.*]] = alloca <8 x double>, align 64
-// CHECK: store <8 x double> %__W, <8 x double>* [[__W_ADDR]], align 64
-// CHECK: [[TMP0:%.*]] = load <8 x double>, <8 x double>* [[__W_ADDR]], align 64
-// CHECK: store <8 x double> [[TMP0]], <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP1:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP2:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x double> [[TMP1]], <8 x double> [[TMP2]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP3:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP4:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x double> [[TMP3]], <8 x double> [[TMP4]], <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x double> [[SHUFFLE_I]], <8 x double>* [[__A_ADDR_I_I]], align 64
-// CHECK: store <8 x double> [[SHUFFLE1_I]], <8 x double>* [[__B_ADDR_I_I]], align 64
-// CHECK: [[TMP5:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I_I]], align 64
-// CHECK: [[TMP6:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I_I]], align 64
-// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP7:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP8:%.*]] = call <8 x double> @llvm.x86.avx512.mask.min.pd.512(<8 x double> [[TMP5]], <8 x double> [[TMP6]], <8 x double> [[TMP7]], i8 -1, i32 4) #2
-// CHECK: store <8 x double> [[TMP8]], <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP9:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP10:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <8 x double> [[TMP9]], <8 x double> [[TMP10]], <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP11:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP12:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x double> [[TMP11]], <8 x double> [[TMP12]], <8 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x double> [[SHUFFLE2_I]], <8 x double>* [[__A_ADDR_I12_I]], align 64
-// CHECK: store <8 x double> [[SHUFFLE3_I]], <8 x double>* [[__B_ADDR_I13_I]], align 64
-// CHECK: [[TMP13:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I12_I]], align 64
-// CHECK: [[TMP14:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I13_I]], align 64
-// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I11_I]], align 64
-// CHECK: [[TMP15:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I11_I]], align 64
-// CHECK: [[TMP16:%.*]] = call <8 x double> @llvm.x86.avx512.mask.min.pd.512(<8 x double> [[TMP13]], <8 x double> [[TMP14]], <8 x double> [[TMP15]], i8 -1, i32 4) #2
-// CHECK: store <8 x double> [[TMP16]], <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP17:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP18:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <8 x double> [[TMP17]], <8 x double> [[TMP18]], <8 x i32> <i32 0, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP19:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP20:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x double> [[TMP19]], <8 x double> [[TMP20]], <8 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x double> [[SHUFFLE5_I]], <8 x double>* [[__A_ADDR_I9_I]], align 64
-// CHECK: store <8 x double> [[SHUFFLE6_I]], <8 x double>* [[__B_ADDR_I10_I]], align 64
-// CHECK: [[TMP21:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I9_I]], align 64
-// CHECK: [[TMP22:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I10_I]], align 64
-// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I8_I]], align 64
-// CHECK: [[TMP23:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I8_I]], align 64
-// CHECK: [[TMP24:%.*]] = call <8 x double> @llvm.x86.avx512.mask.min.pd.512(<8 x double> [[TMP21]], <8 x double> [[TMP22]], <8 x double> [[TMP23]], i8 -1, i32 4) #2
-// CHECK: store <8 x double> [[TMP24]], <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP25:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x double> [[TMP25]], i32 0
-// CHECK: ret double [[VECEXT_I]]
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[__A_ADDR_I10_I:%.*]] = alloca <4 x double>, align 32
+// CHECK-NEXT: [[__B_ADDR_I11_I:%.*]] = alloca <4 x double>, align 32
+// CHECK-NEXT: [[__A_ADDR_I8_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__B_ADDR_I9_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x double>, align 64
+// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x double>, align 32
+// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x double>, align 32
+// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x double>, align 32
+// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x double>, align 64
+// CHECK-NEXT: store <8 x double> [[__W:%.*]], <8 x double>* [[__W_ADDR]], align 64
+// CHECK-NEXT: [[TMP0:%.*]] = load <8 x double>, <8 x double>* [[__W_ADDR]], align 64
+// CHECK-NEXT: store <8 x double> [[TMP0]], <8 x double>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP1:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[EXTRACT_I:%.*]] = shufflevector <8 x double> [[TMP1]], <8 x double> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK-NEXT: store <4 x double> [[EXTRACT_I]], <4 x double>* [[__T1_I]], align 32
+// CHECK-NEXT: [[TMP2:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[EXTRACT2_I:%.*]] = shufflevector <8 x double> [[TMP2]], <8 x double> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK-NEXT: store <4 x double> [[EXTRACT2_I]], <4 x double>* [[__T2_I]], align 32
+// CHECK-NEXT: [[TMP3:%.*]] = load <4 x double>, <4 x double>* [[__T1_I]], align 32
+// CHECK-NEXT: [[TMP4:%.*]] = load <4 x double>, <4 x double>* [[__T2_I]], align 32
+// CHECK-NEXT: store <4 x double> [[TMP3]], <4 x double>* [[__A_ADDR_I10_I]], align 32
+// CHECK-NEXT: store <4 x double> [[TMP4]], <4 x double>* [[__B_ADDR_I11_I]], align 32
+// CHECK-NEXT: [[TMP5:%.*]] = load <4 x double>, <4 x double>* [[__A_ADDR_I10_I]], align 32
+// CHECK-NEXT: [[TMP6:%.*]] = load <4 x double>, <4 x double>* [[__B_ADDR_I11_I]], align 32
+// CHECK-NEXT: [[TMP7:%.*]] = call <4 x double> @llvm.x86.avx.min.pd.256(<4 x double> [[TMP5]], <4 x double> [[TMP6]]) #2
+// CHECK-NEXT: store <4 x double> [[TMP7]], <4 x double>* [[__T3_I]], align 32
+// CHECK-NEXT: [[TMP8:%.*]] = load <4 x double>, <4 x double>* [[__T3_I]], align 32
+// CHECK-NEXT: [[EXTRACT4_I:%.*]] = shufflevector <4 x double> [[TMP8]], <4 x double> undef, <2 x i32> <i32 0, i32 1>
+// CHECK-NEXT: store <2 x double> [[EXTRACT4_I]], <2 x double>* [[__T4_I]], align 16
+// CHECK-NEXT: [[TMP9:%.*]] = load <4 x double>, <4 x double>* [[__T3_I]], align 32
+// CHECK-NEXT: [[EXTRACT5_I:%.*]] = shufflevector <4 x double> [[TMP9]], <4 x double> undef, <2 x i32> <i32 2, i32 3>
+// CHECK-NEXT: store <2 x double> [[EXTRACT5_I]], <2 x double>* [[__T5_I]], align 16
+// CHECK-NEXT: [[TMP10:%.*]] = load <2 x double>, <2 x double>* [[__T4_I]], align 16
+// CHECK-NEXT: [[TMP11:%.*]] = load <2 x double>, <2 x double>* [[__T5_I]], align 16
+// CHECK-NEXT: store <2 x double> [[TMP10]], <2 x double>* [[__A_ADDR_I8_I]], align 16
+// CHECK-NEXT: store <2 x double> [[TMP11]], <2 x double>* [[__B_ADDR_I9_I]], align 16
+// CHECK-NEXT: [[TMP12:%.*]] = load <2 x double>, <2 x double>* [[__A_ADDR_I8_I]], align 16
+// CHECK-NEXT: [[TMP13:%.*]] = load <2 x double>, <2 x double>* [[__B_ADDR_I9_I]], align 16
+// CHECK-NEXT: [[TMP14:%.*]] = call <2 x double> @llvm.x86.sse2.min.pd(<2 x double> [[TMP12]], <2 x double> [[TMP13]]) #2
+// CHECK-NEXT: store <2 x double> [[TMP14]], <2 x double>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP15:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP16:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <2 x double> [[TMP15]], <2 x double> [[TMP16]], <2 x i32> <i32 1, i32 0>
+// CHECK-NEXT: store <2 x double> [[SHUFFLE_I]], <2 x double>* [[__T7_I]], align 16
+// CHECK-NEXT: [[TMP17:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP18:%.*]] = load <2 x double>, <2 x double>* [[__T7_I]], align 16
+// CHECK-NEXT: store <2 x double> [[TMP17]], <2 x double>* [[__A_ADDR_I_I]], align 16
+// CHECK-NEXT: store <2 x double> [[TMP18]], <2 x double>* [[__B_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP19:%.*]] = load <2 x double>, <2 x double>* [[__A_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP20:%.*]] = load <2 x double>, <2 x double>* [[__B_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP21:%.*]] = call <2 x double> @llvm.x86.sse2.min.pd(<2 x double> [[TMP19]], <2 x double> [[TMP20]]) #2
+// CHECK-NEXT: store <2 x double> [[TMP21]], <2 x double>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP22:%.*]] = load <2 x double>, <2 x double>* [[__T8_I]], align 16
+// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <2 x double> [[TMP22]], i32 0
+// CHECK-NEXT: ret double [[VECEXT_I]]
double test_mm512_reduce_min_pd(__m512d __W){
return _mm512_reduce_min_pd(__W);
}
// CHECK-LABEL: define i64 @test_mm512_mask_reduce_max_epi64(i8 zeroext %__M, <8 x i64> %__W) #0 {
-// CHECK: [[_COMPOUNDLITERAL_I_I12_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I9_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I11_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__D_ADDR_I_I:%.*]] = alloca i64, align 8
-// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__M_ADDR_I:%.*]] = alloca i8, align 1
-// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__M_ADDR:%.*]] = alloca i8, align 1
-// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64
-// CHECK: store i8 %__M, i8* [[__M_ADDR]], align 1
-// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64
-// CHECK: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1
-// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64
-// CHECK: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1
-// CHECK: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP2:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1
-// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: store i64 -9223372036854775808, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[TMP4:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[VECINIT_I_I:%.*]] = insertelement <8 x i64> undef, i64 [[TMP4]], i32 0
-// CHECK: [[TMP5:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <8 x i64> [[VECINIT_I_I]], i64 [[TMP5]], i32 1
-// CHECK: [[TMP6:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <8 x i64> [[VECINIT1_I_I]], i64 [[TMP6]], i32 2
-// CHECK: [[TMP7:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <8 x i64> [[VECINIT2_I_I]], i64 [[TMP7]], i32 3
-// CHECK: [[TMP8:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <8 x i64> [[VECINIT3_I_I]], i64 [[TMP8]], i32 4
-// CHECK: [[TMP9:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <8 x i64> [[VECINIT4_I_I]], i64 [[TMP9]], i32 5
-// CHECK: [[TMP10:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <8 x i64> [[VECINIT5_I_I]], i64 [[TMP10]], i32 6
-// CHECK: [[TMP11:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <8 x i64> [[VECINIT6_I_I]], i64 [[TMP11]], i32 7
-// CHECK: store <8 x i64> [[VECINIT7_I_I]], <8 x i64>* [[_COMPOUNDLITERAL_I_I]], align 64
-// CHECK: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I]], align 64
-// CHECK: [[TMP13:%.*]] = bitcast i8 [[TMP2]] to <8 x i1>
-// CHECK: [[TMP14:%.*]] = select <8 x i1> [[TMP13]], <8 x i64> [[TMP3]], <8 x i64> [[TMP12]]
-// CHECK: store <8 x i64> [[TMP14]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP16:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP15]], <8 x i64> [[TMP16]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__A_ADDR_I13_I]], align 64
-// CHECK: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__B_ADDR_I14_I]], align 64
-// CHECK: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I13_I]], align 64
-// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I14_I]], align 64
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I12_I]], align 64
-// CHECK: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I12_I]], align 64
-// CHECK: [[TMP22:%.*]] = icmp sgt <8 x i64> [[TMP19]], [[TMP20]]
-// CHECK: [[TMP23:%.*]] = select <8 x i1> [[TMP22]], <8 x i64> [[TMP19]], <8 x i64> [[TMP20]]
-// CHECK: store <8 x i64> [[TMP23]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP24:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP24]], <8 x i64> [[TMP25]], <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <8 x i64> [[TMP26]], <8 x i64> [[TMP27]], <8 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__A_ADDR_I10_I]], align 64
-// CHECK: store <8 x i64> [[SHUFFLE4_I]], <8 x i64>* [[__B_ADDR_I11_I]], align 64
-// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I10_I]], align 64
-// CHECK: [[TMP29:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I11_I]], align 64
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I9_I]], align 64
-// CHECK: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I9_I]], align 64
-// CHECK: [[TMP31:%.*]] = icmp sgt <8 x i64> [[TMP28]], [[TMP29]]
-// CHECK: [[TMP32:%.*]] = select <8 x i1> [[TMP31]], <8 x i64> [[TMP28]], <8 x i64> [[TMP29]]
-// CHECK: store <8 x i64> [[TMP32]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP34:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x i64> [[TMP33]], <8 x i64> [[TMP34]], <8 x i32> <i32 0, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP35:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <8 x i64> [[TMP35]], <8 x i64> [[TMP36]], <8 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x i64> [[SHUFFLE6_I]], <8 x i64>* [[__A_ADDR_I_I]], align 64
-// CHECK: store <8 x i64> [[SHUFFLE7_I]], <8 x i64>* [[__B_ADDR_I_I]], align 64
-// CHECK: [[TMP37:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64
-// CHECK: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP39:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP40:%.*]] = icmp sgt <8 x i64> [[TMP37]], [[TMP38]]
-// CHECK: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i64> [[TMP37]], <8 x i64> [[TMP38]]
-// CHECK: store <8 x i64> [[TMP41]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP42:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP42]], i32 0
-// CHECK: ret i64 [[VECEXT_I]]
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i8, align 1
+// CHECK-NEXT: [[__A_ADDR_I11_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__A_ADDR_I9_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__B_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__A_ADDR_I7_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__B_ADDR_I8_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__D_ADDR_I_I:%.*]] = alloca i64, align 8
+// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i8, align 1
+// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T4_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T5_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T6_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i8, align 1
+// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: store i8 [[__M:%.*]], i8* [[__M_ADDR]], align 1
+// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64
+// CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1
+// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64
+// CHECK-NEXT: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1
+// CHECK-NEXT: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: store i64 -9223372036854775808, i64* [[__D_ADDR_I_I]], align 8
+// CHECK-NEXT: [[TMP2:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <8 x i64> undef, i64 [[TMP2]], i32 0
+// CHECK-NEXT: [[TMP3:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <8 x i64> [[VECINIT_I_I]], i64 [[TMP3]], i32 1
+// CHECK-NEXT: [[TMP4:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <8 x i64> [[VECINIT1_I_I]], i64 [[TMP4]], i32 2
+// CHECK-NEXT: [[TMP5:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <8 x i64> [[VECINIT2_I_I]], i64 [[TMP5]], i32 3
+// CHECK-NEXT: [[TMP6:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <8 x i64> [[VECINIT3_I_I]], i64 [[TMP6]], i32 4
+// CHECK-NEXT: [[TMP7:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <8 x i64> [[VECINIT4_I_I]], i64 [[TMP7]], i32 5
+// CHECK-NEXT: [[TMP8:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <8 x i64> [[VECINIT5_I_I]], i64 [[TMP8]], i32 6
+// CHECK-NEXT: [[TMP9:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <8 x i64> [[VECINIT6_I_I]], i64 [[TMP9]], i32 7
+// CHECK-NEXT: store <8 x i64> [[VECINIT7_I_I]], <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I]], align 64
+// CHECK-NEXT: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I]], align 64
+// CHECK-NEXT: [[TMP11:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1
+// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP10]], <8 x i64>* [[__W_ADDR_I_I]], align 64
+// CHECK-NEXT: store i8 [[TMP11]], i8* [[__U_ADDR_I_I]], align 1
+// CHECK-NEXT: store <8 x i64> [[TMP12]], <8 x i64>* [[__A_ADDR_I11_I]], align 64
+// CHECK-NEXT: [[TMP13:%.*]] = load i8, i8* [[__U_ADDR_I_I]], align 1
+// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I11_I]], align 64
+// CHECK-NEXT: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP16:%.*]] = bitcast i8 [[TMP13]] to <8 x i1>
+// CHECK-NEXT: [[TMP17:%.*]] = select <8 x i1> [[TMP16]], <8 x i64> [[TMP14]], <8 x i64> [[TMP15]]
+// CHECK-NEXT: store <8 x i64> [[TMP17]], <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP18]], <8 x i64> [[TMP19]], <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3>
+// CHECK-NEXT: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__T1_I]], align 64
+// CHECK-NEXT: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__T1_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP20]], <8 x i64>* [[__A_ADDR_I9_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP21]], <8 x i64>* [[__B_ADDR_I10_I]], align 64
+// CHECK-NEXT: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I9_I]], align 64
+// CHECK-NEXT: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I10_I]], align 64
+// CHECK-NEXT: [[TMP24:%.*]] = icmp sgt <8 x i64> [[TMP22]], [[TMP23]]
+// CHECK-NEXT: [[TMP25:%.*]] = select <8 x i1> [[TMP24]], <8 x i64> [[TMP22]], <8 x i64> [[TMP23]]
+// CHECK-NEXT: store <8 x i64> [[TMP25]], <8 x i64>* [[__T2_I]], align 64
+// CHECK-NEXT: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64
+// CHECK-NEXT: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64
+// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP26]], <8 x i64> [[TMP27]], <8 x i32> <i32 2, i32 3, i32 0, i32 1, i32 6, i32 7, i32 4, i32 5>
+// CHECK-NEXT: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__T3_I]], align 64
+// CHECK-NEXT: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64
+// CHECK-NEXT: [[TMP29:%.*]] = load <8 x i64>, <8 x i64>* [[__T3_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP28]], <8 x i64>* [[__A_ADDR_I7_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP29]], <8 x i64>* [[__B_ADDR_I8_I]], align 64
+// CHECK-NEXT: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I7_I]], align 64
+// CHECK-NEXT: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I8_I]], align 64
+// CHECK-NEXT: [[TMP32:%.*]] = icmp sgt <8 x i64> [[TMP30]], [[TMP31]]
+// CHECK-NEXT: [[TMP33:%.*]] = select <8 x i1> [[TMP32]], <8 x i64> [[TMP30]], <8 x i64> [[TMP31]]
+// CHECK-NEXT: store <8 x i64> [[TMP33]], <8 x i64>* [[__T4_I]], align 64
+// CHECK-NEXT: [[TMP34:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64
+// CHECK-NEXT: [[TMP35:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64
+// CHECK-NEXT: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP34]], <8 x i64> [[TMP35]], <8 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6>
+// CHECK-NEXT: store <8 x i64> [[SHUFFLE5_I]], <8 x i64>* [[__T5_I]], align 64
+// CHECK-NEXT: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64
+// CHECK-NEXT: [[TMP37:%.*]] = load <8 x i64>, <8 x i64>* [[__T5_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP36]], <8 x i64>* [[__A_ADDR_I_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP37]], <8 x i64>* [[__B_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP39:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP40:%.*]] = icmp sgt <8 x i64> [[TMP38]], [[TMP39]]
+// CHECK-NEXT: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i64> [[TMP38]], <8 x i64> [[TMP39]]
+// CHECK-NEXT: store <8 x i64> [[TMP41]], <8 x i64>* [[__T6_I]], align 64
+// CHECK-NEXT: [[TMP42:%.*]] = load <8 x i64>, <8 x i64>* [[__T6_I]], align 64
+// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP42]], i32 0
+// CHECK-NEXT: ret i64 [[VECEXT_I]]
long long test_mm512_mask_reduce_max_epi64(__mmask8 __M, __m512i __W){
return _mm512_mask_reduce_max_epi64(__M, __W);
}
// CHECK-LABEL: define i64 @test_mm512_mask_reduce_max_epu64(i8 zeroext %__M, <8 x i64> %__W) #0 {
-// CHECK: [[_COMPOUNDLITERAL_I_I12_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I9_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I11_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__D_ADDR_I_I:%.*]] = alloca i64, align 8
-// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__M_ADDR_I:%.*]] = alloca i8, align 1
-// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__M_ADDR:%.*]] = alloca i8, align 1
-// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64
-// CHECK: store i8 %__M, i8* [[__M_ADDR]], align 1
-// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64
-// CHECK: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1
-// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64
-// CHECK: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1
-// CHECK: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP2:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1
-// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: store i64 0, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[TMP4:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[VECINIT_I_I:%.*]] = insertelement <8 x i64> undef, i64 [[TMP4]], i32 0
-// CHECK: [[TMP5:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <8 x i64> [[VECINIT_I_I]], i64 [[TMP5]], i32 1
-// CHECK: [[TMP6:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <8 x i64> [[VECINIT1_I_I]], i64 [[TMP6]], i32 2
-// CHECK: [[TMP7:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <8 x i64> [[VECINIT2_I_I]], i64 [[TMP7]], i32 3
-// CHECK: [[TMP8:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <8 x i64> [[VECINIT3_I_I]], i64 [[TMP8]], i32 4
-// CHECK: [[TMP9:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <8 x i64> [[VECINIT4_I_I]], i64 [[TMP9]], i32 5
-// CHECK: [[TMP10:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <8 x i64> [[VECINIT5_I_I]], i64 [[TMP10]], i32 6
-// CHECK: [[TMP11:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <8 x i64> [[VECINIT6_I_I]], i64 [[TMP11]], i32 7
-// CHECK: store <8 x i64> [[VECINIT7_I_I]], <8 x i64>* [[_COMPOUNDLITERAL_I_I]], align 64
-// CHECK: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I]], align 64
-// CHECK: [[TMP13:%.*]] = bitcast i8 [[TMP2]] to <8 x i1>
-// CHECK: [[TMP14:%.*]] = select <8 x i1> [[TMP13]], <8 x i64> [[TMP3]], <8 x i64> [[TMP12]]
-// CHECK: store <8 x i64> [[TMP14]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP16:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP15]], <8 x i64> [[TMP16]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__A_ADDR_I13_I]], align 64
-// CHECK: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__B_ADDR_I14_I]], align 64
-// CHECK: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I13_I]], align 64
-// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I14_I]], align 64
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I12_I]], align 64
-// CHECK: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I12_I]], align 64
-// CHECK: [[TMP22:%.*]] = icmp ugt <8 x i64> [[TMP19]], [[TMP20]]
-// CHECK: [[TMP23:%.*]] = select <8 x i1> [[TMP22]], <8 x i64> [[TMP19]], <8 x i64> [[TMP20]]
-// CHECK: store <8 x i64> [[TMP23]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP24:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP24]], <8 x i64> [[TMP25]], <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <8 x i64> [[TMP26]], <8 x i64> [[TMP27]], <8 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__A_ADDR_I10_I]], align 64
-// CHECK: store <8 x i64> [[SHUFFLE4_I]], <8 x i64>* [[__B_ADDR_I11_I]], align 64
-// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I10_I]], align 64
-// CHECK: [[TMP29:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I11_I]], align 64
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I9_I]], align 64
-// CHECK: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I9_I]], align 64
-// CHECK: [[TMP31:%.*]] = icmp ugt <8 x i64> [[TMP28]], [[TMP29]]
-// CHECK: [[TMP32:%.*]] = select <8 x i1> [[TMP31]], <8 x i64> [[TMP28]], <8 x i64> [[TMP29]]
-// CHECK: store <8 x i64> [[TMP32]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP34:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x i64> [[TMP33]], <8 x i64> [[TMP34]], <8 x i32> <i32 0, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP35:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <8 x i64> [[TMP35]], <8 x i64> [[TMP36]], <8 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x i64> [[SHUFFLE6_I]], <8 x i64>* [[__A_ADDR_I_I]], align 64
-// CHECK: store <8 x i64> [[SHUFFLE7_I]], <8 x i64>* [[__B_ADDR_I_I]], align 64
-// CHECK: [[TMP37:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64
-// CHECK: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP39:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP40:%.*]] = icmp ugt <8 x i64> [[TMP37]], [[TMP38]]
-// CHECK: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i64> [[TMP37]], <8 x i64> [[TMP38]]
-// CHECK: store <8 x i64> [[TMP41]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP42:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP42]], i32 0
-// CHECK: ret i64 [[VECEXT_I]]
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[__A_ADDR_I9_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__B_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__A_ADDR_I7_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__B_ADDR_I8_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__A_ADDR_I6_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i8, align 1
+// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i8, align 1
+// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T4_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T5_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T6_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i8, align 1
+// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: store i8 [[__M:%.*]], i8* [[__M_ADDR]], align 1
+// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64
+// CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1
+// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64
+// CHECK-NEXT: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1
+// CHECK-NEXT: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP2:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1
+// CHECK-NEXT: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: store i8 [[TMP2]], i8* [[__U_ADDR_I_I]], align 1
+// CHECK-NEXT: store <8 x i64> [[TMP3]], <8 x i64>* [[__A_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP4:%.*]] = load i8, i8* [[__U_ADDR_I_I]], align 1
+// CHECK-NEXT: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64
+// CHECK-NEXT: store <8 x i64> zeroinitializer, <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I_I]], align 64
+// CHECK-NEXT: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I_I]], align 64
+// CHECK-NEXT: [[TMP7:%.*]] = bitcast i8 [[TMP4]] to <8 x i1>
+// CHECK-NEXT: [[TMP8:%.*]] = select <8 x i1> [[TMP7]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]]
+// CHECK-NEXT: store <8 x i64> [[TMP8]], <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP9:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP9]], <8 x i64> [[TMP10]], <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3>
+// CHECK-NEXT: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__T1_I]], align 64
+// CHECK-NEXT: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__T1_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP11]], <8 x i64>* [[__A_ADDR_I9_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP12]], <8 x i64>* [[__B_ADDR_I10_I]], align 64
+// CHECK-NEXT: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I9_I]], align 64
+// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I10_I]], align 64
+// CHECK-NEXT: [[TMP15:%.*]] = icmp ugt <8 x i64> [[TMP13]], [[TMP14]]
+// CHECK-NEXT: [[TMP16:%.*]] = select <8 x i1> [[TMP15]], <8 x i64> [[TMP13]], <8 x i64> [[TMP14]]
+// CHECK-NEXT: store <8 x i64> [[TMP16]], <8 x i64>* [[__T2_I]], align 64
+// CHECK-NEXT: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64
+// CHECK-NEXT: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64
+// CHECK-NEXT: [[SHUFFLE2_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> <i32 2, i32 3, i32 0, i32 1, i32 6, i32 7, i32 4, i32 5>
+// CHECK-NEXT: store <8 x i64> [[SHUFFLE2_I]], <8 x i64>* [[__T3_I]], align 64
+// CHECK-NEXT: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64
+// CHECK-NEXT: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__T3_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP19]], <8 x i64>* [[__A_ADDR_I7_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP20]], <8 x i64>* [[__B_ADDR_I8_I]], align 64
+// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I7_I]], align 64
+// CHECK-NEXT: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I8_I]], align 64
+// CHECK-NEXT: [[TMP23:%.*]] = icmp ugt <8 x i64> [[TMP21]], [[TMP22]]
+// CHECK-NEXT: [[TMP24:%.*]] = select <8 x i1> [[TMP23]], <8 x i64> [[TMP21]], <8 x i64> [[TMP22]]
+// CHECK-NEXT: store <8 x i64> [[TMP24]], <8 x i64>* [[__T4_I]], align 64
+// CHECK-NEXT: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64
+// CHECK-NEXT: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64
+// CHECK-NEXT: [[SHUFFLE4_I:%.*]] = shufflevector <8 x i64> [[TMP25]], <8 x i64> [[TMP26]], <8 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6>
+// CHECK-NEXT: store <8 x i64> [[SHUFFLE4_I]], <8 x i64>* [[__T5_I]], align 64
+// CHECK-NEXT: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64
+// CHECK-NEXT: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__T5_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP27]], <8 x i64>* [[__A_ADDR_I6_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP28]], <8 x i64>* [[__B_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP29:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I6_I]], align 64
+// CHECK-NEXT: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP31:%.*]] = icmp ugt <8 x i64> [[TMP29]], [[TMP30]]
+// CHECK-NEXT: [[TMP32:%.*]] = select <8 x i1> [[TMP31]], <8 x i64> [[TMP29]], <8 x i64> [[TMP30]]
+// CHECK-NEXT: store <8 x i64> [[TMP32]], <8 x i64>* [[__T6_I]], align 64
+// CHECK-NEXT: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__T6_I]], align 64
+// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP33]], i32 0
+// CHECK-NEXT: ret i64 [[VECEXT_I]]
unsigned long test_mm512_mask_reduce_max_epu64(__mmask8 __M, __m512i __W){
return _mm512_mask_reduce_max_epu64(__M, __W);
}
-// CHECK-LABEL: define i64 @test_mm512_mask_reduce_max_pd(i8 zeroext %__M, <8 x double> %__W) #0 {
-// CHECK: [[_COMPOUNDLITERAL_I_I12_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I9_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__A_ADDR_I10_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__B_ADDR_I11_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__W_ADDR_I_I:%.*]] = alloca double, align 8
-// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__M_ADDR_I:%.*]] = alloca i8, align 1
-// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__M_ADDR:%.*]] = alloca i8, align 1
-// CHECK: [[__W_ADDR:%.*]] = alloca <8 x double>, align 64
-// CHECK: store i8 %__M, i8* [[__M_ADDR]], align 1
-// CHECK: store <8 x double> %__W, <8 x double>* [[__W_ADDR]], align 64
-// CHECK: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1
-// CHECK: [[TMP1:%.*]] = load <8 x double>, <8 x double>* [[__W_ADDR]], align 64
-// CHECK: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1
-// CHECK: store <8 x double> [[TMP1]], <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP2:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1
-// CHECK: [[TMP3:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: store double 0x7FF0000000000000, double* [[__W_ADDR_I_I]], align 8
-// CHECK: [[TMP4:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8
-// CHECK: [[VECINIT_I_I:%.*]] = insertelement <8 x double> undef, double [[TMP4]], i32 0
-// CHECK: [[TMP5:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8
-// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <8 x double> [[VECINIT_I_I]], double [[TMP5]], i32 1
-// CHECK: [[TMP6:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8
-// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <8 x double> [[VECINIT1_I_I]], double [[TMP6]], i32 2
-// CHECK: [[TMP7:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8
-// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <8 x double> [[VECINIT2_I_I]], double [[TMP7]], i32 3
-// CHECK: [[TMP8:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8
-// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <8 x double> [[VECINIT3_I_I]], double [[TMP8]], i32 4
-// CHECK: [[TMP9:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8
-// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <8 x double> [[VECINIT4_I_I]], double [[TMP9]], i32 5
-// CHECK: [[TMP10:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8
-// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <8 x double> [[VECINIT5_I_I]], double [[TMP10]], i32 6
-// CHECK: [[TMP11:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8
-// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <8 x double> [[VECINIT6_I_I]], double [[TMP11]], i32 7
-// CHECK: store <8 x double> [[VECINIT7_I_I]], <8 x double>* [[_COMPOUNDLITERAL_I_I]], align 64
-// CHECK: [[TMP12:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I]], align 64
-// CHECK: [[SUB_I:%.*]] = fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, [[TMP12]]
-// CHECK: [[TMP13:%.*]] = bitcast i8 [[TMP2]] to <8 x i1>
-// CHECK: [[TMP14:%.*]] = select <8 x i1> [[TMP13]], <8 x double> [[TMP3]], <8 x double> [[SUB_I]]
-// CHECK: store <8 x double> [[TMP14]], <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP15:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP16:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x double> [[TMP15]], <8 x double> [[TMP16]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP17:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP18:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x double> [[TMP17]], <8 x double> [[TMP18]], <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x double> [[SHUFFLE_I]], <8 x double>* [[__A_ADDR_I13_I]], align 64
-// CHECK: store <8 x double> [[SHUFFLE1_I]], <8 x double>* [[__B_ADDR_I14_I]], align 64
-// CHECK: [[TMP19:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I13_I]], align 64
-// CHECK: [[TMP20:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I14_I]], align 64
-// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I12_I]], align 64
-// CHECK: [[TMP21:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I12_I]], align 64
-// CHECK: [[TMP22:%.*]] = call <8 x double> @llvm.x86.avx512.mask.max.pd.512(<8 x double> [[TMP19]], <8 x double> [[TMP20]], <8 x double> [[TMP21]], i8 -1, i32 4) #2
-// CHECK: store <8 x double> [[TMP22]], <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP23:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP24:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x double> [[TMP23]], <8 x double> [[TMP24]], <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP25:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP26:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <8 x double> [[TMP25]], <8 x double> [[TMP26]], <8 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x double> [[SHUFFLE3_I]], <8 x double>* [[__A_ADDR_I10_I]], align 64
-// CHECK: store <8 x double> [[SHUFFLE4_I]], <8 x double>* [[__B_ADDR_I11_I]], align 64
-// CHECK: [[TMP27:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I10_I]], align 64
-// CHECK: [[TMP28:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I11_I]], align 64
-// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I9_I]], align 64
-// CHECK: [[TMP29:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I9_I]], align 64
-// CHECK: [[TMP30:%.*]] = call <8 x double> @llvm.x86.avx512.mask.max.pd.512(<8 x double> [[TMP27]], <8 x double> [[TMP28]], <8 x double> [[TMP29]], i8 -1, i32 4) #2
-// CHECK: store <8 x double> [[TMP30]], <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP31:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP32:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x double> [[TMP31]], <8 x double> [[TMP32]], <8 x i32> <i32 0, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP33:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP34:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <8 x double> [[TMP33]], <8 x double> [[TMP34]], <8 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x double> [[SHUFFLE6_I]], <8 x double>* [[__A_ADDR_I_I]], align 64
-// CHECK: store <8 x double> [[SHUFFLE7_I]], <8 x double>* [[__B_ADDR_I_I]], align 64
-// CHECK: [[TMP35:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I_I]], align 64
-// CHECK: [[TMP36:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I_I]], align 64
-// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP37:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP38:%.*]] = call <8 x double> @llvm.x86.avx512.mask.max.pd.512(<8 x double> [[TMP35]], <8 x double> [[TMP36]], <8 x double> [[TMP37]], i8 -1, i32 4) #2
-// CHECK: store <8 x double> [[TMP38]], <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP39:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x double> [[TMP39]], i32 0
-// CHECK: [[CONV:%.*]] = fptosi double [[VECEXT_I]] to i64
-// CHECK: ret i64 [[CONV]]
-long long test_mm512_mask_reduce_max_pd(__mmask8 __M, __m512d __W){
+// CHECK-LABEL: define double @test_mm512_mask_reduce_max_pd(i8 zeroext %__M, <8 x double> %__W) #0 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[__W2_ADDR_I_I:%.*]] = alloca <8 x double>, align 64
+// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i8, align 1
+// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x double>, align 64
+// CHECK-NEXT: [[__A_ADDR_I12_I:%.*]] = alloca <4 x double>, align 32
+// CHECK-NEXT: [[__B_ADDR_I13_I:%.*]] = alloca <4 x double>, align 32
+// CHECK-NEXT: [[__A_ADDR_I10_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__B_ADDR_I11_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__A2_ADDR_I_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca double, align 8
+// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <8 x double>, align 64
+// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i8, align 1
+// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x double>, align 64
+// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x double>, align 32
+// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x double>, align 32
+// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x double>, align 32
+// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i8, align 1
+// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x double>, align 64
+// CHECK-NEXT: store i8 [[__M:%.*]], i8* [[__M_ADDR]], align 1
+// CHECK-NEXT: store <8 x double> [[__W:%.*]], <8 x double>* [[__W_ADDR]], align 64
+// CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1
+// CHECK-NEXT: [[TMP1:%.*]] = load <8 x double>, <8 x double>* [[__W_ADDR]], align 64
+// CHECK-NEXT: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1
+// CHECK-NEXT: store <8 x double> [[TMP1]], <8 x double>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: store double 0xFFF0000000000000, double* [[__W_ADDR_I_I]], align 8
+// CHECK-NEXT: [[TMP2:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <8 x double> undef, double [[TMP2]], i32 0
+// CHECK-NEXT: [[TMP3:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <8 x double> [[VECINIT_I_I]], double [[TMP3]], i32 1
+// CHECK-NEXT: [[TMP4:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <8 x double> [[VECINIT1_I_I]], double [[TMP4]], i32 2
+// CHECK-NEXT: [[TMP5:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <8 x double> [[VECINIT2_I_I]], double [[TMP5]], i32 3
+// CHECK-NEXT: [[TMP6:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <8 x double> [[VECINIT3_I_I]], double [[TMP6]], i32 4
+// CHECK-NEXT: [[TMP7:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <8 x double> [[VECINIT4_I_I]], double [[TMP7]], i32 5
+// CHECK-NEXT: [[TMP8:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <8 x double> [[VECINIT5_I_I]], double [[TMP8]], i32 6
+// CHECK-NEXT: [[TMP9:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <8 x double> [[VECINIT6_I_I]], double [[TMP9]], i32 7
+// CHECK-NEXT: store <8 x double> [[VECINIT7_I_I]], <8 x double>* [[DOTCOMPOUNDLITERAL_I_I]], align 64
+// CHECK-NEXT: [[TMP10:%.*]] = load <8 x double>, <8 x double>* [[DOTCOMPOUNDLITERAL_I_I]], align 64
+// CHECK-NEXT: [[TMP11:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1
+// CHECK-NEXT: [[TMP12:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: store <8 x double> [[TMP10]], <8 x double>* [[__W2_ADDR_I_I]], align 64
+// CHECK-NEXT: store i8 [[TMP11]], i8* [[__U_ADDR_I_I]], align 1
+// CHECK-NEXT: store <8 x double> [[TMP12]], <8 x double>* [[__A_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP13:%.*]] = load i8, i8* [[__U_ADDR_I_I]], align 1
+// CHECK-NEXT: [[TMP14:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP15:%.*]] = load <8 x double>, <8 x double>* [[__W2_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP16:%.*]] = bitcast i8 [[TMP13]] to <8 x i1>
+// CHECK-NEXT: [[TMP17:%.*]] = select <8 x i1> [[TMP16]], <8 x double> [[TMP14]], <8 x double> [[TMP15]]
+// CHECK-NEXT: store <8 x double> [[TMP17]], <8 x double>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP18:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[EXTRACT_I:%.*]] = shufflevector <8 x double> [[TMP18]], <8 x double> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK-NEXT: store <4 x double> [[EXTRACT_I]], <4 x double>* [[__T1_I]], align 32
+// CHECK-NEXT: [[TMP19:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[EXTRACT4_I:%.*]] = shufflevector <8 x double> [[TMP19]], <8 x double> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK-NEXT: store <4 x double> [[EXTRACT4_I]], <4 x double>* [[__T2_I]], align 32
+// CHECK-NEXT: [[TMP20:%.*]] = load <4 x double>, <4 x double>* [[__T1_I]], align 32
+// CHECK-NEXT: [[TMP21:%.*]] = load <4 x double>, <4 x double>* [[__T2_I]], align 32
+// CHECK-NEXT: store <4 x double> [[TMP20]], <4 x double>* [[__A_ADDR_I12_I]], align 32
+// CHECK-NEXT: store <4 x double> [[TMP21]], <4 x double>* [[__B_ADDR_I13_I]], align 32
+// CHECK-NEXT: [[TMP22:%.*]] = load <4 x double>, <4 x double>* [[__A_ADDR_I12_I]], align 32
+// CHECK-NEXT: [[TMP23:%.*]] = load <4 x double>, <4 x double>* [[__B_ADDR_I13_I]], align 32
+// CHECK-NEXT: [[TMP24:%.*]] = call <4 x double> @llvm.x86.avx.max.pd.256(<4 x double> [[TMP22]], <4 x double> [[TMP23]]) #2
+// CHECK-NEXT: store <4 x double> [[TMP24]], <4 x double>* [[__T3_I]], align 32
+// CHECK-NEXT: [[TMP25:%.*]] = load <4 x double>, <4 x double>* [[__T3_I]], align 32
+// CHECK-NEXT: [[EXTRACT6_I:%.*]] = shufflevector <4 x double> [[TMP25]], <4 x double> undef, <2 x i32> <i32 0, i32 1>
+// CHECK-NEXT: store <2 x double> [[EXTRACT6_I]], <2 x double>* [[__T4_I]], align 16
+// CHECK-NEXT: [[TMP26:%.*]] = load <4 x double>, <4 x double>* [[__T3_I]], align 32
+// CHECK-NEXT: [[EXTRACT7_I:%.*]] = shufflevector <4 x double> [[TMP26]], <4 x double> undef, <2 x i32> <i32 2, i32 3>
+// CHECK-NEXT: store <2 x double> [[EXTRACT7_I]], <2 x double>* [[__T5_I]], align 16
+// CHECK-NEXT: [[TMP27:%.*]] = load <2 x double>, <2 x double>* [[__T4_I]], align 16
+// CHECK-NEXT: [[TMP28:%.*]] = load <2 x double>, <2 x double>* [[__T5_I]], align 16
+// CHECK-NEXT: store <2 x double> [[TMP27]], <2 x double>* [[__A_ADDR_I10_I]], align 16
+// CHECK-NEXT: store <2 x double> [[TMP28]], <2 x double>* [[__B_ADDR_I11_I]], align 16
+// CHECK-NEXT: [[TMP29:%.*]] = load <2 x double>, <2 x double>* [[__A_ADDR_I10_I]], align 16
+// CHECK-NEXT: [[TMP30:%.*]] = load <2 x double>, <2 x double>* [[__B_ADDR_I11_I]], align 16
+// CHECK-NEXT: [[TMP31:%.*]] = call <2 x double> @llvm.x86.sse2.max.pd(<2 x double> [[TMP29]], <2 x double> [[TMP30]]) #2
+// CHECK-NEXT: store <2 x double> [[TMP31]], <2 x double>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP32:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP33:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <2 x double> [[TMP32]], <2 x double> [[TMP33]], <2 x i32> <i32 1, i32 0>
+// CHECK-NEXT: store <2 x double> [[SHUFFLE_I]], <2 x double>* [[__T7_I]], align 16
+// CHECK-NEXT: [[TMP34:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP35:%.*]] = load <2 x double>, <2 x double>* [[__T7_I]], align 16
+// CHECK-NEXT: store <2 x double> [[TMP34]], <2 x double>* [[__A2_ADDR_I_I]], align 16
+// CHECK-NEXT: store <2 x double> [[TMP35]], <2 x double>* [[__B_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP36:%.*]] = load <2 x double>, <2 x double>* [[__A2_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP37:%.*]] = load <2 x double>, <2 x double>* [[__B_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP38:%.*]] = call <2 x double> @llvm.x86.sse2.max.pd(<2 x double> [[TMP36]], <2 x double> [[TMP37]]) #2
+// CHECK-NEXT: store <2 x double> [[TMP38]], <2 x double>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP39:%.*]] = load <2 x double>, <2 x double>* [[__T8_I]], align 16
+// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <2 x double> [[TMP39]], i32 0
+// CHECK-NEXT: ret double [[VECEXT_I]]
+double test_mm512_mask_reduce_max_pd(__mmask8 __M, __m512d __W){
return _mm512_mask_reduce_max_pd(__M, __W);
}
// CHECK-LABEL: define i64 @test_mm512_mask_reduce_min_epi64(i8 zeroext %__M, <8 x i64> %__W) #0 {
-// CHECK: [[_COMPOUNDLITERAL_I_I12_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I9_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I11_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__D_ADDR_I_I:%.*]] = alloca i64, align 8
-// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__M_ADDR_I:%.*]] = alloca i8, align 1
-// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__M_ADDR:%.*]] = alloca i8, align 1
-// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64
-// CHECK: store i8 %__M, i8* [[__M_ADDR]], align 1
-// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64
-// CHECK: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1
-// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64
-// CHECK: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1
-// CHECK: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP2:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1
-// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: store i64 9223372036854775807, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[TMP4:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[VECINIT_I_I:%.*]] = insertelement <8 x i64> undef, i64 [[TMP4]], i32 0
-// CHECK: [[TMP5:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <8 x i64> [[VECINIT_I_I]], i64 [[TMP5]], i32 1
-// CHECK: [[TMP6:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <8 x i64> [[VECINIT1_I_I]], i64 [[TMP6]], i32 2
-// CHECK: [[TMP7:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <8 x i64> [[VECINIT2_I_I]], i64 [[TMP7]], i32 3
-// CHECK: [[TMP8:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <8 x i64> [[VECINIT3_I_I]], i64 [[TMP8]], i32 4
-// CHECK: [[TMP9:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <8 x i64> [[VECINIT4_I_I]], i64 [[TMP9]], i32 5
-// CHECK: [[TMP10:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <8 x i64> [[VECINIT5_I_I]], i64 [[TMP10]], i32 6
-// CHECK: [[TMP11:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <8 x i64> [[VECINIT6_I_I]], i64 [[TMP11]], i32 7
-// CHECK: store <8 x i64> [[VECINIT7_I_I]], <8 x i64>* [[_COMPOUNDLITERAL_I_I]], align 64
-// CHECK: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I]], align 64
-// CHECK: [[TMP13:%.*]] = bitcast i8 [[TMP2]] to <8 x i1>
-// CHECK: [[TMP14:%.*]] = select <8 x i1> [[TMP13]], <8 x i64> [[TMP3]], <8 x i64> [[TMP12]]
-// CHECK: store <8 x i64> [[TMP14]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP16:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP15]], <8 x i64> [[TMP16]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__A_ADDR_I13_I]], align 64
-// CHECK: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__B_ADDR_I14_I]], align 64
-// CHECK: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I13_I]], align 64
-// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I14_I]], align 64
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I12_I]], align 64
-// CHECK: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I12_I]], align 64
-// CHECK: [[TMP22:%.*]] = icmp slt <8 x i64> [[TMP19]], [[TMP20]]
-// CHECK: [[TMP23:%.*]] = select <8 x i1> [[TMP22]], <8 x i64> [[TMP19]], <8 x i64> [[TMP20]]
-// CHECK: store <8 x i64> [[TMP23]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP24:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP24]], <8 x i64> [[TMP25]], <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <8 x i64> [[TMP26]], <8 x i64> [[TMP27]], <8 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__A_ADDR_I10_I]], align 64
-// CHECK: store <8 x i64> [[SHUFFLE4_I]], <8 x i64>* [[__B_ADDR_I11_I]], align 64
-// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I10_I]], align 64
-// CHECK: [[TMP29:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I11_I]], align 64
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I9_I]], align 64
-// CHECK: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I9_I]], align 64
-// CHECK: [[TMP31:%.*]] = icmp slt <8 x i64> [[TMP28]], [[TMP29]]
-// CHECK: [[TMP32:%.*]] = select <8 x i1> [[TMP31]], <8 x i64> [[TMP28]], <8 x i64> [[TMP29]]
-// CHECK: store <8 x i64> [[TMP32]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP34:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x i64> [[TMP33]], <8 x i64> [[TMP34]], <8 x i32> <i32 0, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP35:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <8 x i64> [[TMP35]], <8 x i64> [[TMP36]], <8 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x i64> [[SHUFFLE6_I]], <8 x i64>* [[__A_ADDR_I_I]], align 64
-// CHECK: store <8 x i64> [[SHUFFLE7_I]], <8 x i64>* [[__B_ADDR_I_I]], align 64
-// CHECK: [[TMP37:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64
-// CHECK: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP39:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP40:%.*]] = icmp slt <8 x i64> [[TMP37]], [[TMP38]]
-// CHECK: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i64> [[TMP37]], <8 x i64> [[TMP38]]
-// CHECK: store <8 x i64> [[TMP41]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP42:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP42]], i32 0
-// CHECK: ret i64 [[VECEXT_I]]
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i8, align 1
+// CHECK-NEXT: [[__A_ADDR_I11_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__A_ADDR_I9_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__B_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__A_ADDR_I7_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__B_ADDR_I8_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__D_ADDR_I_I:%.*]] = alloca i64, align 8
+// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i8, align 1
+// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T4_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T5_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T6_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i8, align 1
+// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: store i8 [[__M:%.*]], i8* [[__M_ADDR]], align 1
+// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64
+// CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1
+// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64
+// CHECK-NEXT: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1
+// CHECK-NEXT: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: store i64 9223372036854775807, i64* [[__D_ADDR_I_I]], align 8
+// CHECK-NEXT: [[TMP2:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <8 x i64> undef, i64 [[TMP2]], i32 0
+// CHECK-NEXT: [[TMP3:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <8 x i64> [[VECINIT_I_I]], i64 [[TMP3]], i32 1
+// CHECK-NEXT: [[TMP4:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <8 x i64> [[VECINIT1_I_I]], i64 [[TMP4]], i32 2
+// CHECK-NEXT: [[TMP5:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <8 x i64> [[VECINIT2_I_I]], i64 [[TMP5]], i32 3
+// CHECK-NEXT: [[TMP6:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <8 x i64> [[VECINIT3_I_I]], i64 [[TMP6]], i32 4
+// CHECK-NEXT: [[TMP7:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <8 x i64> [[VECINIT4_I_I]], i64 [[TMP7]], i32 5
+// CHECK-NEXT: [[TMP8:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <8 x i64> [[VECINIT5_I_I]], i64 [[TMP8]], i32 6
+// CHECK-NEXT: [[TMP9:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <8 x i64> [[VECINIT6_I_I]], i64 [[TMP9]], i32 7
+// CHECK-NEXT: store <8 x i64> [[VECINIT7_I_I]], <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I]], align 64
+// CHECK-NEXT: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I]], align 64
+// CHECK-NEXT: [[TMP11:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1
+// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP10]], <8 x i64>* [[__W_ADDR_I_I]], align 64
+// CHECK-NEXT: store i8 [[TMP11]], i8* [[__U_ADDR_I_I]], align 1
+// CHECK-NEXT: store <8 x i64> [[TMP12]], <8 x i64>* [[__A_ADDR_I11_I]], align 64
+// CHECK-NEXT: [[TMP13:%.*]] = load i8, i8* [[__U_ADDR_I_I]], align 1
+// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I11_I]], align 64
+// CHECK-NEXT: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP16:%.*]] = bitcast i8 [[TMP13]] to <8 x i1>
+// CHECK-NEXT: [[TMP17:%.*]] = select <8 x i1> [[TMP16]], <8 x i64> [[TMP14]], <8 x i64> [[TMP15]]
+// CHECK-NEXT: store <8 x i64> [[TMP17]], <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP18]], <8 x i64> [[TMP19]], <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3>
+// CHECK-NEXT: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__T1_I]], align 64
+// CHECK-NEXT: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__T1_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP20]], <8 x i64>* [[__A_ADDR_I9_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP21]], <8 x i64>* [[__B_ADDR_I10_I]], align 64
+// CHECK-NEXT: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I9_I]], align 64
+// CHECK-NEXT: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I10_I]], align 64
+// CHECK-NEXT: [[TMP24:%.*]] = icmp slt <8 x i64> [[TMP22]], [[TMP23]]
+// CHECK-NEXT: [[TMP25:%.*]] = select <8 x i1> [[TMP24]], <8 x i64> [[TMP22]], <8 x i64> [[TMP23]]
+// CHECK-NEXT: store <8 x i64> [[TMP25]], <8 x i64>* [[__T2_I]], align 64
+// CHECK-NEXT: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64
+// CHECK-NEXT: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64
+// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP26]], <8 x i64> [[TMP27]], <8 x i32> <i32 2, i32 3, i32 0, i32 1, i32 6, i32 7, i32 4, i32 5>
+// CHECK-NEXT: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__T3_I]], align 64
+// CHECK-NEXT: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64
+// CHECK-NEXT: [[TMP29:%.*]] = load <8 x i64>, <8 x i64>* [[__T3_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP28]], <8 x i64>* [[__A_ADDR_I7_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP29]], <8 x i64>* [[__B_ADDR_I8_I]], align 64
+// CHECK-NEXT: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I7_I]], align 64
+// CHECK-NEXT: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I8_I]], align 64
+// CHECK-NEXT: [[TMP32:%.*]] = icmp slt <8 x i64> [[TMP30]], [[TMP31]]
+// CHECK-NEXT: [[TMP33:%.*]] = select <8 x i1> [[TMP32]], <8 x i64> [[TMP30]], <8 x i64> [[TMP31]]
+// CHECK-NEXT: store <8 x i64> [[TMP33]], <8 x i64>* [[__T4_I]], align 64
+// CHECK-NEXT: [[TMP34:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64
+// CHECK-NEXT: [[TMP35:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64
+// CHECK-NEXT: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP34]], <8 x i64> [[TMP35]], <8 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6>
+// CHECK-NEXT: store <8 x i64> [[SHUFFLE5_I]], <8 x i64>* [[__T5_I]], align 64
+// CHECK-NEXT: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64
+// CHECK-NEXT: [[TMP37:%.*]] = load <8 x i64>, <8 x i64>* [[__T5_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP36]], <8 x i64>* [[__A_ADDR_I_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP37]], <8 x i64>* [[__B_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP39:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP40:%.*]] = icmp slt <8 x i64> [[TMP38]], [[TMP39]]
+// CHECK-NEXT: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i64> [[TMP38]], <8 x i64> [[TMP39]]
+// CHECK-NEXT: store <8 x i64> [[TMP41]], <8 x i64>* [[__T6_I]], align 64
+// CHECK-NEXT: [[TMP42:%.*]] = load <8 x i64>, <8 x i64>* [[__T6_I]], align 64
+// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP42]], i32 0
+// CHECK-NEXT: ret i64 [[VECEXT_I]]
long long test_mm512_mask_reduce_min_epi64(__mmask8 __M, __m512i __W){
return _mm512_mask_reduce_min_epi64(__M, __W);
}
// CHECK-LABEL: define i64 @test_mm512_mask_reduce_min_epu64(i8 zeroext %__M, <8 x i64> %__W) #0 {
-// CHECK: [[_COMPOUNDLITERAL_I_I12_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I9_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I11_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__D_ADDR_I_I:%.*]] = alloca i64, align 8
-// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__M_ADDR_I:%.*]] = alloca i8, align 1
-// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__M_ADDR:%.*]] = alloca i8, align 1
-// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64
-// CHECK: store i8 %__M, i8* [[__M_ADDR]], align 1
-// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64
-// CHECK: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1
-// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64
-// CHECK: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1
-// CHECK: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP2:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1
-// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: store i64 0, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[TMP4:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[VECINIT_I_I:%.*]] = insertelement <8 x i64> undef, i64 [[TMP4]], i32 0
-// CHECK: [[TMP5:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <8 x i64> [[VECINIT_I_I]], i64 [[TMP5]], i32 1
-// CHECK: [[TMP6:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <8 x i64> [[VECINIT1_I_I]], i64 [[TMP6]], i32 2
-// CHECK: [[TMP7:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <8 x i64> [[VECINIT2_I_I]], i64 [[TMP7]], i32 3
-// CHECK: [[TMP8:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <8 x i64> [[VECINIT3_I_I]], i64 [[TMP8]], i32 4
-// CHECK: [[TMP9:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <8 x i64> [[VECINIT4_I_I]], i64 [[TMP9]], i32 5
-// CHECK: [[TMP10:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <8 x i64> [[VECINIT5_I_I]], i64 [[TMP10]], i32 6
-// CHECK: [[TMP11:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
-// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <8 x i64> [[VECINIT6_I_I]], i64 [[TMP11]], i32 7
-// CHECK: store <8 x i64> [[VECINIT7_I_I]], <8 x i64>* [[_COMPOUNDLITERAL_I_I]], align 64
-// CHECK: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I]], align 64
-// CHECK: [[TMP13:%.*]] = bitcast i8 [[TMP2]] to <8 x i1>
-// CHECK: [[TMP14:%.*]] = select <8 x i1> [[TMP13]], <8 x i64> [[TMP3]], <8 x i64> [[TMP12]]
-// CHECK: store <8 x i64> [[TMP14]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP16:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP15]], <8 x i64> [[TMP16]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__A_ADDR_I13_I]], align 64
-// CHECK: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__B_ADDR_I14_I]], align 64
-// CHECK: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I13_I]], align 64
-// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I14_I]], align 64
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I12_I]], align 64
-// CHECK: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I12_I]], align 64
-// CHECK: [[TMP22:%.*]] = icmp ugt <8 x i64> [[TMP19]], [[TMP20]]
-// CHECK: [[TMP23:%.*]] = select <8 x i1> [[TMP22]], <8 x i64> [[TMP19]], <8 x i64> [[TMP20]]
-// CHECK: store <8 x i64> [[TMP23]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP24:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP24]], <8 x i64> [[TMP25]], <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <8 x i64> [[TMP26]], <8 x i64> [[TMP27]], <8 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__A_ADDR_I10_I]], align 64
-// CHECK: store <8 x i64> [[SHUFFLE4_I]], <8 x i64>* [[__B_ADDR_I11_I]], align 64
-// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I10_I]], align 64
-// CHECK: [[TMP29:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I11_I]], align 64
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I9_I]], align 64
-// CHECK: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I9_I]], align 64
-// CHECK: [[TMP31:%.*]] = icmp ugt <8 x i64> [[TMP28]], [[TMP29]]
-// CHECK: [[TMP32:%.*]] = select <8 x i1> [[TMP31]], <8 x i64> [[TMP28]], <8 x i64> [[TMP29]]
-// CHECK: store <8 x i64> [[TMP32]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP34:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x i64> [[TMP33]], <8 x i64> [[TMP34]], <8 x i32> <i32 0, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP35:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <8 x i64> [[TMP35]], <8 x i64> [[TMP36]], <8 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x i64> [[SHUFFLE6_I]], <8 x i64>* [[__A_ADDR_I_I]], align 64
-// CHECK: store <8 x i64> [[SHUFFLE7_I]], <8 x i64>* [[__B_ADDR_I_I]], align 64
-// CHECK: [[TMP37:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64
-// CHECK: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP39:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP40:%.*]] = icmp ugt <8 x i64> [[TMP37]], [[TMP38]]
-// CHECK: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i64> [[TMP37]], <8 x i64> [[TMP38]]
-// CHECK: store <8 x i64> [[TMP41]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP42:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP42]], i32 0
-// CHECK: ret i64 [[VECEXT_I]]
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i8, align 1
+// CHECK-NEXT: [[__A_ADDR_I11_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__A_ADDR_I9_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__B_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__A_ADDR_I7_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__B_ADDR_I8_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__D_ADDR_I_I:%.*]] = alloca i64, align 8
+// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i8, align 1
+// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T4_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T5_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T6_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i8, align 1
+// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: store i8 [[__M:%.*]], i8* [[__M_ADDR]], align 1
+// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64
+// CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1
+// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64
+// CHECK-NEXT: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1
+// CHECK-NEXT: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: store i64 -1, i64* [[__D_ADDR_I_I]], align 8
+// CHECK-NEXT: [[TMP2:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <8 x i64> undef, i64 [[TMP2]], i32 0
+// CHECK-NEXT: [[TMP3:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <8 x i64> [[VECINIT_I_I]], i64 [[TMP3]], i32 1
+// CHECK-NEXT: [[TMP4:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <8 x i64> [[VECINIT1_I_I]], i64 [[TMP4]], i32 2
+// CHECK-NEXT: [[TMP5:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <8 x i64> [[VECINIT2_I_I]], i64 [[TMP5]], i32 3
+// CHECK-NEXT: [[TMP6:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <8 x i64> [[VECINIT3_I_I]], i64 [[TMP6]], i32 4
+// CHECK-NEXT: [[TMP7:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <8 x i64> [[VECINIT4_I_I]], i64 [[TMP7]], i32 5
+// CHECK-NEXT: [[TMP8:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <8 x i64> [[VECINIT5_I_I]], i64 [[TMP8]], i32 6
+// CHECK-NEXT: [[TMP9:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <8 x i64> [[VECINIT6_I_I]], i64 [[TMP9]], i32 7
+// CHECK-NEXT: store <8 x i64> [[VECINIT7_I_I]], <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I]], align 64
+// CHECK-NEXT: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I]], align 64
+// CHECK-NEXT: [[TMP11:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1
+// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP10]], <8 x i64>* [[__W_ADDR_I_I]], align 64
+// CHECK-NEXT: store i8 [[TMP11]], i8* [[__U_ADDR_I_I]], align 1
+// CHECK-NEXT: store <8 x i64> [[TMP12]], <8 x i64>* [[__A_ADDR_I11_I]], align 64
+// CHECK-NEXT: [[TMP13:%.*]] = load i8, i8* [[__U_ADDR_I_I]], align 1
+// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I11_I]], align 64
+// CHECK-NEXT: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP16:%.*]] = bitcast i8 [[TMP13]] to <8 x i1>
+// CHECK-NEXT: [[TMP17:%.*]] = select <8 x i1> [[TMP16]], <8 x i64> [[TMP14]], <8 x i64> [[TMP15]]
+// CHECK-NEXT: store <8 x i64> [[TMP17]], <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP18]], <8 x i64> [[TMP19]], <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3>
+// CHECK-NEXT: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__T1_I]], align 64
+// CHECK-NEXT: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__T1_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP20]], <8 x i64>* [[__A_ADDR_I9_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP21]], <8 x i64>* [[__B_ADDR_I10_I]], align 64
+// CHECK-NEXT: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I9_I]], align 64
+// CHECK-NEXT: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I10_I]], align 64
+// CHECK-NEXT: [[TMP24:%.*]] = icmp ult <8 x i64> [[TMP22]], [[TMP23]]
+// CHECK-NEXT: [[TMP25:%.*]] = select <8 x i1> [[TMP24]], <8 x i64> [[TMP22]], <8 x i64> [[TMP23]]
+// CHECK-NEXT: store <8 x i64> [[TMP25]], <8 x i64>* [[__T2_I]], align 64
+// CHECK-NEXT: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64
+// CHECK-NEXT: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64
+// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP26]], <8 x i64> [[TMP27]], <8 x i32> <i32 2, i32 3, i32 0, i32 1, i32 6, i32 7, i32 4, i32 5>
+// CHECK-NEXT: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__T3_I]], align 64
+// CHECK-NEXT: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64
+// CHECK-NEXT: [[TMP29:%.*]] = load <8 x i64>, <8 x i64>* [[__T3_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP28]], <8 x i64>* [[__A_ADDR_I7_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP29]], <8 x i64>* [[__B_ADDR_I8_I]], align 64
+// CHECK-NEXT: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I7_I]], align 64
+// CHECK-NEXT: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I8_I]], align 64
+// CHECK-NEXT: [[TMP32:%.*]] = icmp ult <8 x i64> [[TMP30]], [[TMP31]]
+// CHECK-NEXT: [[TMP33:%.*]] = select <8 x i1> [[TMP32]], <8 x i64> [[TMP30]], <8 x i64> [[TMP31]]
+// CHECK-NEXT: store <8 x i64> [[TMP33]], <8 x i64>* [[__T4_I]], align 64
+// CHECK-NEXT: [[TMP34:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64
+// CHECK-NEXT: [[TMP35:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64
+// CHECK-NEXT: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP34]], <8 x i64> [[TMP35]], <8 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6>
+// CHECK-NEXT: store <8 x i64> [[SHUFFLE5_I]], <8 x i64>* [[__T5_I]], align 64
+// CHECK-NEXT: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64
+// CHECK-NEXT: [[TMP37:%.*]] = load <8 x i64>, <8 x i64>* [[__T5_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP36]], <8 x i64>* [[__A_ADDR_I_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP37]], <8 x i64>* [[__B_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP39:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP40:%.*]] = icmp ult <8 x i64> [[TMP38]], [[TMP39]]
+// CHECK-NEXT: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i64> [[TMP38]], <8 x i64> [[TMP39]]
+// CHECK-NEXT: store <8 x i64> [[TMP41]], <8 x i64>* [[__T6_I]], align 64
+// CHECK-NEXT: [[TMP42:%.*]] = load <8 x i64>, <8 x i64>* [[__T6_I]], align 64
+// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP42]], i32 0
+// CHECK-NEXT: ret i64 [[VECEXT_I]]
long long test_mm512_mask_reduce_min_epu64(__mmask8 __M, __m512i __W){
- return _mm512_mask_reduce_max_epu64(__M, __W);
+ return _mm512_mask_reduce_min_epu64(__M, __W);
}
// CHECK-LABEL: define double @test_mm512_mask_reduce_min_pd(i8 zeroext %__M, <8 x double> %__W) #0 {
-// CHECK: [[_COMPOUNDLITERAL_I_I12_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I9_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__A_ADDR_I10_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__B_ADDR_I11_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__W_ADDR_I_I:%.*]] = alloca double, align 8
-// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__M_ADDR_I:%.*]] = alloca i8, align 1
-// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x double>, align 64
-// CHECK: [[__M_ADDR:%.*]] = alloca i8, align 1
-// CHECK: [[__W_ADDR:%.*]] = alloca <8 x double>, align 64
-// CHECK: store i8 %__M, i8* [[__M_ADDR]], align 1
-// CHECK: store <8 x double> %__W, <8 x double>* [[__W_ADDR]], align 64
-// CHECK: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1
-// CHECK: [[TMP1:%.*]] = load <8 x double>, <8 x double>* [[__W_ADDR]], align 64
-// CHECK: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1
-// CHECK: store <8 x double> [[TMP1]], <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP2:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1
-// CHECK: [[TMP3:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: store double 0x7FF0000000000000, double* [[__W_ADDR_I_I]], align 8
-// CHECK: [[TMP4:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8
-// CHECK: [[VECINIT_I_I:%.*]] = insertelement <8 x double> undef, double [[TMP4]], i32 0
-// CHECK: [[TMP5:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8
-// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <8 x double> [[VECINIT_I_I]], double [[TMP5]], i32 1
-// CHECK: [[TMP6:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8
-// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <8 x double> [[VECINIT1_I_I]], double [[TMP6]], i32 2
-// CHECK: [[TMP7:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8
-// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <8 x double> [[VECINIT2_I_I]], double [[TMP7]], i32 3
-// CHECK: [[TMP8:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8
-// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <8 x double> [[VECINIT3_I_I]], double [[TMP8]], i32 4
-// CHECK: [[TMP9:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8
-// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <8 x double> [[VECINIT4_I_I]], double [[TMP9]], i32 5
-// CHECK: [[TMP10:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8
-// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <8 x double> [[VECINIT5_I_I]], double [[TMP10]], i32 6
-// CHECK: [[TMP11:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8
-// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <8 x double> [[VECINIT6_I_I]], double [[TMP11]], i32 7
-// CHECK: store <8 x double> [[VECINIT7_I_I]], <8 x double>* [[_COMPOUNDLITERAL_I_I]], align 64
-// CHECK: [[TMP12:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I]], align 64
-// CHECK: [[TMP13:%.*]] = bitcast i8 [[TMP2]] to <8 x i1>
-// CHECK: [[TMP14:%.*]] = select <8 x i1> [[TMP13]], <8 x double> [[TMP3]], <8 x double> [[TMP12]]
-// CHECK: store <8 x double> [[TMP14]], <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP15:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP16:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x double> [[TMP15]], <8 x double> [[TMP16]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP17:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP18:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x double> [[TMP17]], <8 x double> [[TMP18]], <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x double> [[SHUFFLE_I]], <8 x double>* [[__A_ADDR_I13_I]], align 64
-// CHECK: store <8 x double> [[SHUFFLE1_I]], <8 x double>* [[__B_ADDR_I14_I]], align 64
-// CHECK: [[TMP19:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I13_I]], align 64
-// CHECK: [[TMP20:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I14_I]], align 64
-// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I12_I]], align 64
-// CHECK: [[TMP21:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I12_I]], align 64
-// CHECK: [[TMP22:%.*]] = call <8 x double> @llvm.x86.avx512.mask.min.pd.512(<8 x double> [[TMP19]], <8 x double> [[TMP20]], <8 x double> [[TMP21]], i8 -1, i32 4) #2
-// CHECK: store <8 x double> [[TMP22]], <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP23:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP24:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x double> [[TMP23]], <8 x double> [[TMP24]], <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP25:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP26:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <8 x double> [[TMP25]], <8 x double> [[TMP26]], <8 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x double> [[SHUFFLE3_I]], <8 x double>* [[__A_ADDR_I10_I]], align 64
-// CHECK: store <8 x double> [[SHUFFLE4_I]], <8 x double>* [[__B_ADDR_I11_I]], align 64
-// CHECK: [[TMP27:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I10_I]], align 64
-// CHECK: [[TMP28:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I11_I]], align 64
-// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I9_I]], align 64
-// CHECK: [[TMP29:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I9_I]], align 64
-// CHECK: [[TMP30:%.*]] = call <8 x double> @llvm.x86.avx512.mask.min.pd.512(<8 x double> [[TMP27]], <8 x double> [[TMP28]], <8 x double> [[TMP29]], i8 -1, i32 4) #2
-// CHECK: store <8 x double> [[TMP30]], <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP31:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP32:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x double> [[TMP31]], <8 x double> [[TMP32]], <8 x i32> <i32 0, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP33:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP34:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <8 x double> [[TMP33]], <8 x double> [[TMP34]], <8 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <8 x double> [[SHUFFLE6_I]], <8 x double>* [[__A_ADDR_I_I]], align 64
-// CHECK: store <8 x double> [[SHUFFLE7_I]], <8 x double>* [[__B_ADDR_I_I]], align 64
-// CHECK: [[TMP35:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I_I]], align 64
-// CHECK: [[TMP36:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I_I]], align 64
-// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP37:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP38:%.*]] = call <8 x double> @llvm.x86.avx512.mask.min.pd.512(<8 x double> [[TMP35]], <8 x double> [[TMP36]], <8 x double> [[TMP37]], i8 -1, i32 4) #2
-// CHECK: store <8 x double> [[TMP38]], <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP39:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
-// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x double> [[TMP39]], i32 0
-// CHECK: ret double [[VECEXT_I]]
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[__W2_ADDR_I_I:%.*]] = alloca <8 x double>, align 64
+// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i8, align 1
+// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x double>, align 64
+// CHECK-NEXT: [[__A_ADDR_I12_I:%.*]] = alloca <4 x double>, align 32
+// CHECK-NEXT: [[__B_ADDR_I13_I:%.*]] = alloca <4 x double>, align 32
+// CHECK-NEXT: [[__A_ADDR_I10_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__B_ADDR_I11_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__A2_ADDR_I_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca double, align 8
+// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <8 x double>, align 64
+// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i8, align 1
+// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x double>, align 64
+// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x double>, align 32
+// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x double>, align 32
+// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x double>, align 32
+// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i8, align 1
+// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x double>, align 64
+// CHECK-NEXT: store i8 [[__M:%.*]], i8* [[__M_ADDR]], align 1
+// CHECK-NEXT: store <8 x double> [[__W:%.*]], <8 x double>* [[__W_ADDR]], align 64
+// CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1
+// CHECK-NEXT: [[TMP1:%.*]] = load <8 x double>, <8 x double>* [[__W_ADDR]], align 64
+// CHECK-NEXT: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1
+// CHECK-NEXT: store <8 x double> [[TMP1]], <8 x double>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: store double 0x7FF0000000000000, double* [[__W_ADDR_I_I]], align 8
+// CHECK-NEXT: [[TMP2:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <8 x double> undef, double [[TMP2]], i32 0
+// CHECK-NEXT: [[TMP3:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <8 x double> [[VECINIT_I_I]], double [[TMP3]], i32 1
+// CHECK-NEXT: [[TMP4:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <8 x double> [[VECINIT1_I_I]], double [[TMP4]], i32 2
+// CHECK-NEXT: [[TMP5:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <8 x double> [[VECINIT2_I_I]], double [[TMP5]], i32 3
+// CHECK-NEXT: [[TMP6:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <8 x double> [[VECINIT3_I_I]], double [[TMP6]], i32 4
+// CHECK-NEXT: [[TMP7:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <8 x double> [[VECINIT4_I_I]], double [[TMP7]], i32 5
+// CHECK-NEXT: [[TMP8:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <8 x double> [[VECINIT5_I_I]], double [[TMP8]], i32 6
+// CHECK-NEXT: [[TMP9:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8
+// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <8 x double> [[VECINIT6_I_I]], double [[TMP9]], i32 7
+// CHECK-NEXT: store <8 x double> [[VECINIT7_I_I]], <8 x double>* [[DOTCOMPOUNDLITERAL_I_I]], align 64
+// CHECK-NEXT: [[TMP10:%.*]] = load <8 x double>, <8 x double>* [[DOTCOMPOUNDLITERAL_I_I]], align 64
+// CHECK-NEXT: [[TMP11:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1
+// CHECK-NEXT: [[TMP12:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: store <8 x double> [[TMP10]], <8 x double>* [[__W2_ADDR_I_I]], align 64
+// CHECK-NEXT: store i8 [[TMP11]], i8* [[__U_ADDR_I_I]], align 1
+// CHECK-NEXT: store <8 x double> [[TMP12]], <8 x double>* [[__A_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP13:%.*]] = load i8, i8* [[__U_ADDR_I_I]], align 1
+// CHECK-NEXT: [[TMP14:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP15:%.*]] = load <8 x double>, <8 x double>* [[__W2_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP16:%.*]] = bitcast i8 [[TMP13]] to <8 x i1>
+// CHECK-NEXT: [[TMP17:%.*]] = select <8 x i1> [[TMP16]], <8 x double> [[TMP14]], <8 x double> [[TMP15]]
+// CHECK-NEXT: store <8 x double> [[TMP17]], <8 x double>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP18:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[EXTRACT_I:%.*]] = shufflevector <8 x double> [[TMP18]], <8 x double> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK-NEXT: store <4 x double> [[EXTRACT_I]], <4 x double>* [[__T1_I]], align 32
+// CHECK-NEXT: [[TMP19:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[EXTRACT4_I:%.*]] = shufflevector <8 x double> [[TMP19]], <8 x double> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK-NEXT: store <4 x double> [[EXTRACT4_I]], <4 x double>* [[__T2_I]], align 32
+// CHECK-NEXT: [[TMP20:%.*]] = load <4 x double>, <4 x double>* [[__T1_I]], align 32
+// CHECK-NEXT: [[TMP21:%.*]] = load <4 x double>, <4 x double>* [[__T2_I]], align 32
+// CHECK-NEXT: store <4 x double> [[TMP20]], <4 x double>* [[__A_ADDR_I12_I]], align 32
+// CHECK-NEXT: store <4 x double> [[TMP21]], <4 x double>* [[__B_ADDR_I13_I]], align 32
+// CHECK-NEXT: [[TMP22:%.*]] = load <4 x double>, <4 x double>* [[__A_ADDR_I12_I]], align 32
+// CHECK-NEXT: [[TMP23:%.*]] = load <4 x double>, <4 x double>* [[__B_ADDR_I13_I]], align 32
+// CHECK-NEXT: [[TMP24:%.*]] = call <4 x double> @llvm.x86.avx.min.pd.256(<4 x double> [[TMP22]], <4 x double> [[TMP23]]) #2
+// CHECK-NEXT: store <4 x double> [[TMP24]], <4 x double>* [[__T3_I]], align 32
+// CHECK-NEXT: [[TMP25:%.*]] = load <4 x double>, <4 x double>* [[__T3_I]], align 32
+// CHECK-NEXT: [[EXTRACT6_I:%.*]] = shufflevector <4 x double> [[TMP25]], <4 x double> undef, <2 x i32> <i32 0, i32 1>
+// CHECK-NEXT: store <2 x double> [[EXTRACT6_I]], <2 x double>* [[__T4_I]], align 16
+// CHECK-NEXT: [[TMP26:%.*]] = load <4 x double>, <4 x double>* [[__T3_I]], align 32
+// CHECK-NEXT: [[EXTRACT7_I:%.*]] = shufflevector <4 x double> [[TMP26]], <4 x double> undef, <2 x i32> <i32 2, i32 3>
+// CHECK-NEXT: store <2 x double> [[EXTRACT7_I]], <2 x double>* [[__T5_I]], align 16
+// CHECK-NEXT: [[TMP27:%.*]] = load <2 x double>, <2 x double>* [[__T4_I]], align 16
+// CHECK-NEXT: [[TMP28:%.*]] = load <2 x double>, <2 x double>* [[__T5_I]], align 16
+// CHECK-NEXT: store <2 x double> [[TMP27]], <2 x double>* [[__A_ADDR_I10_I]], align 16
+// CHECK-NEXT: store <2 x double> [[TMP28]], <2 x double>* [[__B_ADDR_I11_I]], align 16
+// CHECK-NEXT: [[TMP29:%.*]] = load <2 x double>, <2 x double>* [[__A_ADDR_I10_I]], align 16
+// CHECK-NEXT: [[TMP30:%.*]] = load <2 x double>, <2 x double>* [[__B_ADDR_I11_I]], align 16
+// CHECK-NEXT: [[TMP31:%.*]] = call <2 x double> @llvm.x86.sse2.min.pd(<2 x double> [[TMP29]], <2 x double> [[TMP30]]) #2
+// CHECK-NEXT: store <2 x double> [[TMP31]], <2 x double>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP32:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP33:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <2 x double> [[TMP32]], <2 x double> [[TMP33]], <2 x i32> <i32 1, i32 0>
+// CHECK-NEXT: store <2 x double> [[SHUFFLE_I]], <2 x double>* [[__T7_I]], align 16
+// CHECK-NEXT: [[TMP34:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP35:%.*]] = load <2 x double>, <2 x double>* [[__T7_I]], align 16
+// CHECK-NEXT: store <2 x double> [[TMP34]], <2 x double>* [[__A2_ADDR_I_I]], align 16
+// CHECK-NEXT: store <2 x double> [[TMP35]], <2 x double>* [[__B_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP36:%.*]] = load <2 x double>, <2 x double>* [[__A2_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP37:%.*]] = load <2 x double>, <2 x double>* [[__B_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP38:%.*]] = call <2 x double> @llvm.x86.sse2.min.pd(<2 x double> [[TMP36]], <2 x double> [[TMP37]]) #2
+// CHECK-NEXT: store <2 x double> [[TMP38]], <2 x double>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP39:%.*]] = load <2 x double>, <2 x double>* [[__T8_I]], align 16
+// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <2 x double> [[TMP39]], i32 0
+// CHECK-NEXT: ret double [[VECEXT_I]]
double test_mm512_mask_reduce_min_pd(__mmask8 __M, __m512d __W){
return _mm512_mask_reduce_min_pd(__M, __W);
}
// CHECK-LABEL: define i32 @test_mm512_reduce_max_epi32(<8 x i64> %__W) #0 {
-// CHECK: [[_COMPOUNDLITERAL_I_I17_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I18_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I19_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I14_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I15_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I16_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I11_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[A_ADDR_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64
-// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64
-// CHECK: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64
-// CHECK: store <8 x i64> [[TMP0]], <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i64> [[TMP1]] to <16 x i32>
-// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i64> [[TMP3]] to <16 x i32>
-// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i32> [[TMP2]], <16 x i32> [[TMP4]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i32> [[SHUFFLE_I]] to <8 x i64>
-// CHECK: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP7:%.*]] = bitcast <8 x i64> [[TMP6]] to <16 x i32>
-// CHECK: [[TMP8:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP9:%.*]] = bitcast <8 x i64> [[TMP8]] to <16 x i32>
-// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x i32> [[TMP7]], <16 x i32> [[TMP9]], <16 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP10:%.*]] = bitcast <16 x i32> [[SHUFFLE1_I]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP5]], <8 x i64>* [[__A_ADDR_I_I]], align 64
-// CHECK: store <8 x i64> [[TMP10]], <8 x i64>* [[__B_ADDR_I_I]], align 64
-// CHECK: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64
-// CHECK: [[TMP12:%.*]] = bitcast <8 x i64> [[TMP11]] to <16 x i32>
-// CHECK: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64
-// CHECK: [[TMP14:%.*]] = bitcast <8 x i64> [[TMP13]] to <16 x i32>
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP16:%.*]] = bitcast <8 x i64> [[TMP15]] to <16 x i32>
-// CHECK: [[TMP17:%.*]] = icmp sgt <16 x i32> [[TMP12]], [[TMP14]]
-// CHECK: [[TMP18:%.*]] = select <16 x i1> [[TMP17]], <16 x i32> [[TMP12]], <16 x i32> [[TMP14]]
-// CHECK: [[TMP19:%.*]] = bitcast <16 x i32> [[TMP18]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP19]], <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP21:%.*]] = bitcast <8 x i64> [[TMP20]] to <16 x i32>
-// CHECK: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP23:%.*]] = bitcast <8 x i64> [[TMP22]] to <16 x i32>
-// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <16 x i32> [[TMP21]], <16 x i32> [[TMP23]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP24:%.*]] = bitcast <16 x i32> [[SHUFFLE2_I]] to <8 x i64>
-// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP26:%.*]] = bitcast <8 x i64> [[TMP25]] to <16 x i32>
-// CHECK: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP28:%.*]] = bitcast <8 x i64> [[TMP27]] to <16 x i32>
-// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x i32> [[TMP26]], <16 x i32> [[TMP28]], <16 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP29:%.*]] = bitcast <16 x i32> [[SHUFFLE3_I]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP24]], <8 x i64>* [[__A_ADDR_I18_I]], align 64
-// CHECK: store <8 x i64> [[TMP29]], <8 x i64>* [[__B_ADDR_I19_I]], align 64
-// CHECK: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I18_I]], align 64
-// CHECK: [[TMP31:%.*]] = bitcast <8 x i64> [[TMP30]] to <16 x i32>
-// CHECK: [[TMP32:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I19_I]], align 64
-// CHECK: [[TMP33:%.*]] = bitcast <8 x i64> [[TMP32]] to <16 x i32>
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I17_I]], align 64
-// CHECK: [[TMP34:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I17_I]], align 64
-// CHECK: [[TMP35:%.*]] = bitcast <8 x i64> [[TMP34]] to <16 x i32>
-// CHECK: [[TMP36:%.*]] = icmp sgt <16 x i32> [[TMP31]], [[TMP33]]
-// CHECK: [[TMP37:%.*]] = select <16 x i1> [[TMP36]], <16 x i32> [[TMP31]], <16 x i32> [[TMP33]]
-// CHECK: [[TMP38:%.*]] = bitcast <16 x i32> [[TMP37]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP38]], <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP39:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP40:%.*]] = bitcast <8 x i64> [[TMP39]] to <16 x i32>
-// CHECK: [[TMP41:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP42:%.*]] = bitcast <8 x i64> [[TMP41]] to <16 x i32>
-// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <16 x i32> [[TMP40]], <16 x i32> [[TMP42]], <16 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP43:%.*]] = bitcast <16 x i32> [[SHUFFLE5_I]] to <8 x i64>
-// CHECK: [[TMP44:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP45:%.*]] = bitcast <8 x i64> [[TMP44]] to <16 x i32>
-// CHECK: [[TMP46:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP47:%.*]] = bitcast <8 x i64> [[TMP46]] to <16 x i32>
-// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x i32> [[TMP45]], <16 x i32> [[TMP47]], <16 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP48:%.*]] = bitcast <16 x i32> [[SHUFFLE6_I]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP43]], <8 x i64>* [[__A_ADDR_I15_I]], align 64
-// CHECK: store <8 x i64> [[TMP48]], <8 x i64>* [[__B_ADDR_I16_I]], align 64
-// CHECK: [[TMP49:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I15_I]], align 64
-// CHECK: [[TMP50:%.*]] = bitcast <8 x i64> [[TMP49]] to <16 x i32>
-// CHECK: [[TMP51:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I16_I]], align 64
-// CHECK: [[TMP52:%.*]] = bitcast <8 x i64> [[TMP51]] to <16 x i32>
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I14_I]], align 64
-// CHECK: [[TMP53:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I14_I]], align 64
-// CHECK: [[TMP54:%.*]] = bitcast <8 x i64> [[TMP53]] to <16 x i32>
-// CHECK: [[TMP55:%.*]] = icmp sgt <16 x i32> [[TMP50]], [[TMP52]]
-// CHECK: [[TMP56:%.*]] = select <16 x i1> [[TMP55]], <16 x i32> [[TMP50]], <16 x i32> [[TMP52]]
-// CHECK: [[TMP57:%.*]] = bitcast <16 x i32> [[TMP56]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP57]], <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP58:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP59:%.*]] = bitcast <8 x i64> [[TMP58]] to <16 x i32>
-// CHECK: [[TMP60:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP61:%.*]] = bitcast <8 x i64> [[TMP60]] to <16 x i32>
-// CHECK: [[SHUFFLE8_I:%.*]] = shufflevector <16 x i32> [[TMP59]], <16 x i32> [[TMP61]], <16 x i32> <i32 0, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP62:%.*]] = bitcast <16 x i32> [[SHUFFLE8_I]] to <8 x i64>
-// CHECK: [[TMP63:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP64:%.*]] = bitcast <8 x i64> [[TMP63]] to <16 x i32>
-// CHECK: [[TMP65:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP66:%.*]] = bitcast <8 x i64> [[TMP65]] to <16 x i32>
-// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x i32> [[TMP64]], <16 x i32> [[TMP66]], <16 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP67:%.*]] = bitcast <16 x i32> [[SHUFFLE9_I]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP62]], <8 x i64>* [[__A_ADDR_I12_I]], align 64
-// CHECK: store <8 x i64> [[TMP67]], <8 x i64>* [[__B_ADDR_I13_I]], align 64
-// CHECK: [[TMP68:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I12_I]], align 64
-// CHECK: [[TMP69:%.*]] = bitcast <8 x i64> [[TMP68]] to <16 x i32>
-// CHECK: [[TMP70:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I13_I]], align 64
-// CHECK: [[TMP71:%.*]] = bitcast <8 x i64> [[TMP70]] to <16 x i32>
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I11_I]], align 64
-// CHECK: [[TMP72:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I11_I]], align 64
-// CHECK: [[TMP73:%.*]] = bitcast <8 x i64> [[TMP72]] to <16 x i32>
-// CHECK: [[TMP74:%.*]] = icmp sgt <16 x i32> [[TMP69]], [[TMP71]]
-// CHECK: [[TMP75:%.*]] = select <16 x i1> [[TMP74]], <16 x i32> [[TMP69]], <16 x i32> [[TMP71]]
-// CHECK: [[TMP76:%.*]] = bitcast <16 x i32> [[TMP75]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP76]], <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP77:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP77]], i32 0
-// CHECK: [[CONV_I:%.*]] = trunc i64 [[VECEXT_I]] to i32
-// CHECK: ret i32 [[CONV_I]]
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__V1_ADDR_I12_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V2_ADDR_I13_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V1_ADDR_I10_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V2_ADDR_I11_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V1_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V2_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T9_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x i32>, align 16
+// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64
+// CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[EXTRACT_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK-NEXT: store <4 x i64> [[EXTRACT_I]], <4 x i64>* [[__T1_I]], align 32
+// CHECK-NEXT: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[EXTRACT2_I:%.*]] = shufflevector <8 x i64> [[TMP2]], <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK-NEXT: store <4 x i64> [[EXTRACT2_I]], <4 x i64>* [[__T2_I]], align 32
+// CHECK-NEXT: [[TMP3:%.*]] = load <4 x i64>, <4 x i64>* [[__T1_I]], align 32
+// CHECK-NEXT: [[TMP4:%.*]] = load <4 x i64>, <4 x i64>* [[__T2_I]], align 32
+// CHECK-NEXT: store <4 x i64> [[TMP3]], <4 x i64>* [[__A_ADDR_I_I]], align 32
+// CHECK-NEXT: store <4 x i64> [[TMP4]], <4 x i64>* [[__B_ADDR_I_I]], align 32
+// CHECK-NEXT: [[TMP5:%.*]] = load <4 x i64>, <4 x i64>* [[__A_ADDR_I_I]], align 32
+// CHECK-NEXT: [[TMP6:%.*]] = bitcast <4 x i64> [[TMP5]] to <8 x i32>
+// CHECK-NEXT: [[TMP7:%.*]] = load <4 x i64>, <4 x i64>* [[__B_ADDR_I_I]], align 32
+// CHECK-NEXT: [[TMP8:%.*]] = bitcast <4 x i64> [[TMP7]] to <8 x i32>
+// CHECK-NEXT: [[TMP9:%.*]] = icmp sgt <8 x i32> [[TMP6]], [[TMP8]]
+// CHECK-NEXT: [[TMP10:%.*]] = select <8 x i1> [[TMP9]], <8 x i32> [[TMP6]], <8 x i32> [[TMP8]]
+// CHECK-NEXT: [[TMP11:%.*]] = bitcast <8 x i32> [[TMP10]] to <4 x i64>
+// CHECK-NEXT: store <4 x i64> [[TMP11]], <4 x i64>* [[__T3_I]], align 32
+// CHECK-NEXT: [[TMP12:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32
+// CHECK-NEXT: [[EXTRACT4_I:%.*]] = shufflevector <4 x i64> [[TMP12]], <4 x i64> undef, <2 x i32> <i32 0, i32 1>
+// CHECK-NEXT: store <2 x i64> [[EXTRACT4_I]], <2 x i64>* [[__T4_I]], align 16
+// CHECK-NEXT: [[TMP13:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32
+// CHECK-NEXT: [[EXTRACT5_I:%.*]] = shufflevector <4 x i64> [[TMP13]], <4 x i64> undef, <2 x i32> <i32 2, i32 3>
+// CHECK-NEXT: store <2 x i64> [[EXTRACT5_I]], <2 x i64>* [[__T5_I]], align 16
+// CHECK-NEXT: [[TMP14:%.*]] = load <2 x i64>, <2 x i64>* [[__T4_I]], align 16
+// CHECK-NEXT: [[TMP15:%.*]] = load <2 x i64>, <2 x i64>* [[__T5_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP14]], <2 x i64>* [[__V1_ADDR_I12_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP15]], <2 x i64>* [[__V2_ADDR_I13_I]], align 16
+// CHECK-NEXT: [[TMP16:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I12_I]], align 16
+// CHECK-NEXT: [[TMP17:%.*]] = bitcast <2 x i64> [[TMP16]] to <4 x i32>
+// CHECK-NEXT: [[TMP18:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I13_I]], align 16
+// CHECK-NEXT: [[TMP19:%.*]] = bitcast <2 x i64> [[TMP18]] to <4 x i32>
+// CHECK-NEXT: [[TMP20:%.*]] = icmp sgt <4 x i32> [[TMP17]], [[TMP19]]
+// CHECK-NEXT: [[TMP21:%.*]] = select <4 x i1> [[TMP20]], <4 x i32> [[TMP17]], <4 x i32> [[TMP19]]
+// CHECK-NEXT: [[TMP22:%.*]] = bitcast <4 x i32> [[TMP21]] to <2 x i64>
+// CHECK-NEXT: store <2 x i64> [[TMP22]], <2 x i64>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP23:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP24:%.*]] = bitcast <2 x i64> [[TMP23]] to <4 x i32>
+// CHECK-NEXT: [[TMP25:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP26:%.*]] = bitcast <2 x i64> [[TMP25]] to <4 x i32>
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> [[TMP24]], <4 x i32> [[TMP26]], <4 x i32> <i32 2, i32 3, i32 0, i32 1>
+// CHECK-NEXT: [[TMP27:%.*]] = bitcast <4 x i32> [[SHUFFLE_I]] to <2 x i64>
+// CHECK-NEXT: store <2 x i64> [[TMP27]], <2 x i64>* [[__T7_I]], align 16
+// CHECK-NEXT: [[TMP28:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP29:%.*]] = load <2 x i64>, <2 x i64>* [[__T7_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP28]], <2 x i64>* [[__V1_ADDR_I10_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP29]], <2 x i64>* [[__V2_ADDR_I11_I]], align 16
+// CHECK-NEXT: [[TMP30:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I10_I]], align 16
+// CHECK-NEXT: [[TMP31:%.*]] = bitcast <2 x i64> [[TMP30]] to <4 x i32>
+// CHECK-NEXT: [[TMP32:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I11_I]], align 16
+// CHECK-NEXT: [[TMP33:%.*]] = bitcast <2 x i64> [[TMP32]] to <4 x i32>
+// CHECK-NEXT: [[TMP34:%.*]] = icmp sgt <4 x i32> [[TMP31]], [[TMP33]]
+// CHECK-NEXT: [[TMP35:%.*]] = select <4 x i1> [[TMP34]], <4 x i32> [[TMP31]], <4 x i32> [[TMP33]]
+// CHECK-NEXT: [[TMP36:%.*]] = bitcast <4 x i32> [[TMP35]] to <2 x i64>
+// CHECK-NEXT: store <2 x i64> [[TMP36]], <2 x i64>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP37:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP38:%.*]] = bitcast <2 x i64> [[TMP37]] to <4 x i32>
+// CHECK-NEXT: [[TMP39:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP40:%.*]] = bitcast <2 x i64> [[TMP39]] to <4 x i32>
+// CHECK-NEXT: [[SHUFFLE8_I:%.*]] = shufflevector <4 x i32> [[TMP38]], <4 x i32> [[TMP40]], <4 x i32> <i32 1, i32 0, i32 3, i32 2>
+// CHECK-NEXT: [[TMP41:%.*]] = bitcast <4 x i32> [[SHUFFLE8_I]] to <2 x i64>
+// CHECK-NEXT: store <2 x i64> [[TMP41]], <2 x i64>* [[__T9_I]], align 16
+// CHECK-NEXT: [[TMP42:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP43:%.*]] = load <2 x i64>, <2 x i64>* [[__T9_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP42]], <2 x i64>* [[__V1_ADDR_I_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP43]], <2 x i64>* [[__V2_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP44:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP45:%.*]] = bitcast <2 x i64> [[TMP44]] to <4 x i32>
+// CHECK-NEXT: [[TMP46:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP47:%.*]] = bitcast <2 x i64> [[TMP46]] to <4 x i32>
+// CHECK-NEXT: [[TMP48:%.*]] = icmp sgt <4 x i32> [[TMP45]], [[TMP47]]
+// CHECK-NEXT: [[TMP49:%.*]] = select <4 x i1> [[TMP48]], <4 x i32> [[TMP45]], <4 x i32> [[TMP47]]
+// CHECK-NEXT: [[TMP50:%.*]] = bitcast <4 x i32> [[TMP49]] to <2 x i64>
+// CHECK-NEXT: store <4 x i32> [[TMP49]], <4 x i32>* [[__T10_I]], align 16
+// CHECK-NEXT: [[TMP51:%.*]] = load <4 x i32>, <4 x i32>* [[__T10_I]], align 16
+// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x i32> [[TMP51]], i32 0
+// CHECK-NEXT: ret i32 [[VECEXT_I]]
int test_mm512_reduce_max_epi32(__m512i __W){
return _mm512_reduce_max_epi32(__W);
}
// CHECK-LABEL: define i32 @test_mm512_reduce_max_epu32(<8 x i64> %__W) #0 {
-// CHECK: [[_COMPOUNDLITERAL_I_I17_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I18_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I19_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I14_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I15_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I16_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I11_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[A_ADDR_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64
-// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64
-// CHECK: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64
-// CHECK: store <8 x i64> [[TMP0]], <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i64> [[TMP1]] to <16 x i32>
-// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i64> [[TMP3]] to <16 x i32>
-// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i32> [[TMP2]], <16 x i32> [[TMP4]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i32> [[SHUFFLE_I]] to <8 x i64>
-// CHECK: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP7:%.*]] = bitcast <8 x i64> [[TMP6]] to <16 x i32>
-// CHECK: [[TMP8:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP9:%.*]] = bitcast <8 x i64> [[TMP8]] to <16 x i32>
-// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x i32> [[TMP7]], <16 x i32> [[TMP9]], <16 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP10:%.*]] = bitcast <16 x i32> [[SHUFFLE1_I]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP5]], <8 x i64>* [[__A_ADDR_I_I]], align 64
-// CHECK: store <8 x i64> [[TMP10]], <8 x i64>* [[__B_ADDR_I_I]], align 64
-// CHECK: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64
-// CHECK: [[TMP12:%.*]] = bitcast <8 x i64> [[TMP11]] to <16 x i32>
-// CHECK: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64
-// CHECK: [[TMP14:%.*]] = bitcast <8 x i64> [[TMP13]] to <16 x i32>
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP16:%.*]] = bitcast <8 x i64> [[TMP15]] to <16 x i32>
-// CHECK: [[TMP17:%.*]] = icmp ugt <16 x i32> [[TMP12]], [[TMP14]]
-// CHECK: [[TMP18:%.*]] = select <16 x i1> [[TMP17]], <16 x i32> [[TMP12]], <16 x i32> [[TMP14]]
-// CHECK: [[TMP19:%.*]] = bitcast <16 x i32> [[TMP18]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP19]], <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP21:%.*]] = bitcast <8 x i64> [[TMP20]] to <16 x i32>
-// CHECK: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP23:%.*]] = bitcast <8 x i64> [[TMP22]] to <16 x i32>
-// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <16 x i32> [[TMP21]], <16 x i32> [[TMP23]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP24:%.*]] = bitcast <16 x i32> [[SHUFFLE2_I]] to <8 x i64>
-// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP26:%.*]] = bitcast <8 x i64> [[TMP25]] to <16 x i32>
-// CHECK: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP28:%.*]] = bitcast <8 x i64> [[TMP27]] to <16 x i32>
-// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x i32> [[TMP26]], <16 x i32> [[TMP28]], <16 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP29:%.*]] = bitcast <16 x i32> [[SHUFFLE3_I]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP24]], <8 x i64>* [[__A_ADDR_I18_I]], align 64
-// CHECK: store <8 x i64> [[TMP29]], <8 x i64>* [[__B_ADDR_I19_I]], align 64
-// CHECK: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I18_I]], align 64
-// CHECK: [[TMP31:%.*]] = bitcast <8 x i64> [[TMP30]] to <16 x i32>
-// CHECK: [[TMP32:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I19_I]], align 64
-// CHECK: [[TMP33:%.*]] = bitcast <8 x i64> [[TMP32]] to <16 x i32>
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I17_I]], align 64
-// CHECK: [[TMP34:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I17_I]], align 64
-// CHECK: [[TMP35:%.*]] = bitcast <8 x i64> [[TMP34]] to <16 x i32>
-// CHECK: [[TMP36:%.*]] = icmp ugt <16 x i32> [[TMP31]], [[TMP33]]
-// CHECK: [[TMP37:%.*]] = select <16 x i1> [[TMP36]], <16 x i32> [[TMP31]], <16 x i32> [[TMP33]]
-// CHECK: [[TMP38:%.*]] = bitcast <16 x i32> [[TMP37]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP38]], <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP39:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP40:%.*]] = bitcast <8 x i64> [[TMP39]] to <16 x i32>
-// CHECK: [[TMP41:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP42:%.*]] = bitcast <8 x i64> [[TMP41]] to <16 x i32>
-// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <16 x i32> [[TMP40]], <16 x i32> [[TMP42]], <16 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP43:%.*]] = bitcast <16 x i32> [[SHUFFLE5_I]] to <8 x i64>
-// CHECK: [[TMP44:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP45:%.*]] = bitcast <8 x i64> [[TMP44]] to <16 x i32>
-// CHECK: [[TMP46:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP47:%.*]] = bitcast <8 x i64> [[TMP46]] to <16 x i32>
-// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x i32> [[TMP45]], <16 x i32> [[TMP47]], <16 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP48:%.*]] = bitcast <16 x i32> [[SHUFFLE6_I]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP43]], <8 x i64>* [[__A_ADDR_I15_I]], align 64
-// CHECK: store <8 x i64> [[TMP48]], <8 x i64>* [[__B_ADDR_I16_I]], align 64
-// CHECK: [[TMP49:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I15_I]], align 64
-// CHECK: [[TMP50:%.*]] = bitcast <8 x i64> [[TMP49]] to <16 x i32>
-// CHECK: [[TMP51:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I16_I]], align 64
-// CHECK: [[TMP52:%.*]] = bitcast <8 x i64> [[TMP51]] to <16 x i32>
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I14_I]], align 64
-// CHECK: [[TMP53:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I14_I]], align 64
-// CHECK: [[TMP54:%.*]] = bitcast <8 x i64> [[TMP53]] to <16 x i32>
-// CHECK: [[TMP55:%.*]] = icmp ugt <16 x i32> [[TMP50]], [[TMP52]]
-// CHECK: [[TMP56:%.*]] = select <16 x i1> [[TMP55]], <16 x i32> [[TMP50]], <16 x i32> [[TMP52]]
-// CHECK: [[TMP57:%.*]] = bitcast <16 x i32> [[TMP56]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP57]], <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP58:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP59:%.*]] = bitcast <8 x i64> [[TMP58]] to <16 x i32>
-// CHECK: [[TMP60:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP61:%.*]] = bitcast <8 x i64> [[TMP60]] to <16 x i32>
-// CHECK: [[SHUFFLE8_I:%.*]] = shufflevector <16 x i32> [[TMP59]], <16 x i32> [[TMP61]], <16 x i32> <i32 0, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP62:%.*]] = bitcast <16 x i32> [[SHUFFLE8_I]] to <8 x i64>
-// CHECK: [[TMP63:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP64:%.*]] = bitcast <8 x i64> [[TMP63]] to <16 x i32>
-// CHECK: [[TMP65:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP66:%.*]] = bitcast <8 x i64> [[TMP65]] to <16 x i32>
-// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x i32> [[TMP64]], <16 x i32> [[TMP66]], <16 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP67:%.*]] = bitcast <16 x i32> [[SHUFFLE9_I]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP62]], <8 x i64>* [[__A_ADDR_I12_I]], align 64
-// CHECK: store <8 x i64> [[TMP67]], <8 x i64>* [[__B_ADDR_I13_I]], align 64
-// CHECK: [[TMP68:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I12_I]], align 64
-// CHECK: [[TMP69:%.*]] = bitcast <8 x i64> [[TMP68]] to <16 x i32>
-// CHECK: [[TMP70:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I13_I]], align 64
-// CHECK: [[TMP71:%.*]] = bitcast <8 x i64> [[TMP70]] to <16 x i32>
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I11_I]], align 64
-// CHECK: [[TMP72:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I11_I]], align 64
-// CHECK: [[TMP73:%.*]] = bitcast <8 x i64> [[TMP72]] to <16 x i32>
-// CHECK: [[TMP74:%.*]] = icmp ugt <16 x i32> [[TMP69]], [[TMP71]]
-// CHECK: [[TMP75:%.*]] = select <16 x i1> [[TMP74]], <16 x i32> [[TMP69]], <16 x i32> [[TMP71]]
-// CHECK: [[TMP76:%.*]] = bitcast <16 x i32> [[TMP75]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP76]], <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP77:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP77]], i32 0
-// CHECK: [[CONV_I:%.*]] = trunc i64 [[VECEXT_I]] to i32
-// CHECK: ret i32 [[CONV_I]]
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__V1_ADDR_I12_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V2_ADDR_I13_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V1_ADDR_I10_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V2_ADDR_I11_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V1_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V2_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T9_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x i32>, align 16
+// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64
+// CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[EXTRACT_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK-NEXT: store <4 x i64> [[EXTRACT_I]], <4 x i64>* [[__T1_I]], align 32
+// CHECK-NEXT: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[EXTRACT2_I:%.*]] = shufflevector <8 x i64> [[TMP2]], <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK-NEXT: store <4 x i64> [[EXTRACT2_I]], <4 x i64>* [[__T2_I]], align 32
+// CHECK-NEXT: [[TMP3:%.*]] = load <4 x i64>, <4 x i64>* [[__T1_I]], align 32
+// CHECK-NEXT: [[TMP4:%.*]] = load <4 x i64>, <4 x i64>* [[__T2_I]], align 32
+// CHECK-NEXT: store <4 x i64> [[TMP3]], <4 x i64>* [[__A_ADDR_I_I]], align 32
+// CHECK-NEXT: store <4 x i64> [[TMP4]], <4 x i64>* [[__B_ADDR_I_I]], align 32
+// CHECK-NEXT: [[TMP5:%.*]] = load <4 x i64>, <4 x i64>* [[__A_ADDR_I_I]], align 32
+// CHECK-NEXT: [[TMP6:%.*]] = bitcast <4 x i64> [[TMP5]] to <8 x i32>
+// CHECK-NEXT: [[TMP7:%.*]] = load <4 x i64>, <4 x i64>* [[__B_ADDR_I_I]], align 32
+// CHECK-NEXT: [[TMP8:%.*]] = bitcast <4 x i64> [[TMP7]] to <8 x i32>
+// CHECK-NEXT: [[TMP9:%.*]] = icmp ugt <8 x i32> [[TMP6]], [[TMP8]]
+// CHECK-NEXT: [[TMP10:%.*]] = select <8 x i1> [[TMP9]], <8 x i32> [[TMP6]], <8 x i32> [[TMP8]]
+// CHECK-NEXT: [[TMP11:%.*]] = bitcast <8 x i32> [[TMP10]] to <4 x i64>
+// CHECK-NEXT: store <4 x i64> [[TMP11]], <4 x i64>* [[__T3_I]], align 32
+// CHECK-NEXT: [[TMP12:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32
+// CHECK-NEXT: [[EXTRACT4_I:%.*]] = shufflevector <4 x i64> [[TMP12]], <4 x i64> undef, <2 x i32> <i32 0, i32 1>
+// CHECK-NEXT: store <2 x i64> [[EXTRACT4_I]], <2 x i64>* [[__T4_I]], align 16
+// CHECK-NEXT: [[TMP13:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32
+// CHECK-NEXT: [[EXTRACT5_I:%.*]] = shufflevector <4 x i64> [[TMP13]], <4 x i64> undef, <2 x i32> <i32 2, i32 3>
+// CHECK-NEXT: store <2 x i64> [[EXTRACT5_I]], <2 x i64>* [[__T5_I]], align 16
+// CHECK-NEXT: [[TMP14:%.*]] = load <2 x i64>, <2 x i64>* [[__T4_I]], align 16
+// CHECK-NEXT: [[TMP15:%.*]] = load <2 x i64>, <2 x i64>* [[__T5_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP14]], <2 x i64>* [[__V1_ADDR_I12_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP15]], <2 x i64>* [[__V2_ADDR_I13_I]], align 16
+// CHECK-NEXT: [[TMP16:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I12_I]], align 16
+// CHECK-NEXT: [[TMP17:%.*]] = bitcast <2 x i64> [[TMP16]] to <4 x i32>
+// CHECK-NEXT: [[TMP18:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I13_I]], align 16
+// CHECK-NEXT: [[TMP19:%.*]] = bitcast <2 x i64> [[TMP18]] to <4 x i32>
+// CHECK-NEXT: [[TMP20:%.*]] = icmp ugt <4 x i32> [[TMP17]], [[TMP19]]
+// CHECK-NEXT: [[TMP21:%.*]] = select <4 x i1> [[TMP20]], <4 x i32> [[TMP17]], <4 x i32> [[TMP19]]
+// CHECK-NEXT: [[TMP22:%.*]] = bitcast <4 x i32> [[TMP21]] to <2 x i64>
+// CHECK-NEXT: store <2 x i64> [[TMP22]], <2 x i64>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP23:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP24:%.*]] = bitcast <2 x i64> [[TMP23]] to <4 x i32>
+// CHECK-NEXT: [[TMP25:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP26:%.*]] = bitcast <2 x i64> [[TMP25]] to <4 x i32>
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> [[TMP24]], <4 x i32> [[TMP26]], <4 x i32> <i32 2, i32 3, i32 0, i32 1>
+// CHECK-NEXT: [[TMP27:%.*]] = bitcast <4 x i32> [[SHUFFLE_I]] to <2 x i64>
+// CHECK-NEXT: store <2 x i64> [[TMP27]], <2 x i64>* [[__T7_I]], align 16
+// CHECK-NEXT: [[TMP28:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP29:%.*]] = load <2 x i64>, <2 x i64>* [[__T7_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP28]], <2 x i64>* [[__V1_ADDR_I10_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP29]], <2 x i64>* [[__V2_ADDR_I11_I]], align 16
+// CHECK-NEXT: [[TMP30:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I10_I]], align 16
+// CHECK-NEXT: [[TMP31:%.*]] = bitcast <2 x i64> [[TMP30]] to <4 x i32>
+// CHECK-NEXT: [[TMP32:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I11_I]], align 16
+// CHECK-NEXT: [[TMP33:%.*]] = bitcast <2 x i64> [[TMP32]] to <4 x i32>
+// CHECK-NEXT: [[TMP34:%.*]] = icmp ugt <4 x i32> [[TMP31]], [[TMP33]]
+// CHECK-NEXT: [[TMP35:%.*]] = select <4 x i1> [[TMP34]], <4 x i32> [[TMP31]], <4 x i32> [[TMP33]]
+// CHECK-NEXT: [[TMP36:%.*]] = bitcast <4 x i32> [[TMP35]] to <2 x i64>
+// CHECK-NEXT: store <2 x i64> [[TMP36]], <2 x i64>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP37:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP38:%.*]] = bitcast <2 x i64> [[TMP37]] to <4 x i32>
+// CHECK-NEXT: [[TMP39:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP40:%.*]] = bitcast <2 x i64> [[TMP39]] to <4 x i32>
+// CHECK-NEXT: [[SHUFFLE8_I:%.*]] = shufflevector <4 x i32> [[TMP38]], <4 x i32> [[TMP40]], <4 x i32> <i32 1, i32 0, i32 3, i32 2>
+// CHECK-NEXT: [[TMP41:%.*]] = bitcast <4 x i32> [[SHUFFLE8_I]] to <2 x i64>
+// CHECK-NEXT: store <2 x i64> [[TMP41]], <2 x i64>* [[__T9_I]], align 16
+// CHECK-NEXT: [[TMP42:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP43:%.*]] = load <2 x i64>, <2 x i64>* [[__T9_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP42]], <2 x i64>* [[__V1_ADDR_I_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP43]], <2 x i64>* [[__V2_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP44:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP45:%.*]] = bitcast <2 x i64> [[TMP44]] to <4 x i32>
+// CHECK-NEXT: [[TMP46:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP47:%.*]] = bitcast <2 x i64> [[TMP46]] to <4 x i32>
+// CHECK-NEXT: [[TMP48:%.*]] = icmp ugt <4 x i32> [[TMP45]], [[TMP47]]
+// CHECK-NEXT: [[TMP49:%.*]] = select <4 x i1> [[TMP48]], <4 x i32> [[TMP45]], <4 x i32> [[TMP47]]
+// CHECK-NEXT: [[TMP50:%.*]] = bitcast <4 x i32> [[TMP49]] to <2 x i64>
+// CHECK-NEXT: store <4 x i32> [[TMP49]], <4 x i32>* [[__T10_I]], align 16
+// CHECK-NEXT: [[TMP51:%.*]] = load <4 x i32>, <4 x i32>* [[__T10_I]], align 16
+// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x i32> [[TMP51]], i32 0
+// CHECK-NEXT: ret i32 [[VECEXT_I]]
unsigned int test_mm512_reduce_max_epu32(__m512i __W){
return _mm512_reduce_max_epu32(__W);
}
// CHECK-LABEL: define float @test_mm512_reduce_max_ps(<16 x float> %__W) #0 {
-// CHECK: [[_COMPOUNDLITERAL_I_I17_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__A_ADDR_I18_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__B_ADDR_I19_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I14_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__A_ADDR_I15_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__B_ADDR_I16_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I11_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[A_ADDR_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__W_ADDR:%.*]] = alloca <16 x float>, align 64
-// CHECK: store <16 x float> %__W, <16 x float>* [[__W_ADDR]], align 64
-// CHECK: [[TMP0:%.*]] = load <16 x float>, <16 x float>* [[__W_ADDR]], align 64
-// CHECK: store <16 x float> [[TMP0]], <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP1:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP2:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x float> [[TMP1]], <16 x float> [[TMP2]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP3:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP4:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x float> [[TMP3]], <16 x float> [[TMP4]], <16 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <16 x float> [[SHUFFLE_I]], <16 x float>* [[__A_ADDR_I_I]], align 64
-// CHECK: store <16 x float> [[SHUFFLE1_I]], <16 x float>* [[__B_ADDR_I_I]], align 64
-// CHECK: [[TMP5:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I_I]], align 64
-// CHECK: [[TMP6:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I_I]], align 64
-// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP7:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP8:%.*]] = call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> [[TMP5]], <16 x float> [[TMP6]], <16 x float> [[TMP7]], i16 -1, i32 4) #2
-// CHECK: store <16 x float> [[TMP8]], <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP9:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP10:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <16 x float> [[TMP9]], <16 x float> [[TMP10]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP11:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP12:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x float> [[TMP11]], <16 x float> [[TMP12]], <16 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <16 x float> [[SHUFFLE2_I]], <16 x float>* [[__A_ADDR_I18_I]], align 64
-// CHECK: store <16 x float> [[SHUFFLE3_I]], <16 x float>* [[__B_ADDR_I19_I]], align 64
-// CHECK: [[TMP13:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I18_I]], align 64
-// CHECK: [[TMP14:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I19_I]], align 64
-// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I17_I]], align 64
-// CHECK: [[TMP15:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I17_I]], align 64
-// CHECK: [[TMP16:%.*]] = call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> [[TMP13]], <16 x float> [[TMP14]], <16 x float> [[TMP15]], i16 -1, i32 4) #2
-// CHECK: store <16 x float> [[TMP16]], <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP17:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP18:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <16 x float> [[TMP17]], <16 x float> [[TMP18]], <16 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP19:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP20:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x float> [[TMP19]], <16 x float> [[TMP20]], <16 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <16 x float> [[SHUFFLE5_I]], <16 x float>* [[__A_ADDR_I15_I]], align 64
-// CHECK: store <16 x float> [[SHUFFLE6_I]], <16 x float>* [[__B_ADDR_I16_I]], align 64
-// CHECK: [[TMP21:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I15_I]], align 64
-// CHECK: [[TMP22:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I16_I]], align 64
-// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I14_I]], align 64
-// CHECK: [[TMP23:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I14_I]], align 64
-// CHECK: [[TMP24:%.*]] = call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> [[TMP21]], <16 x float> [[TMP22]], <16 x float> [[TMP23]], i16 -1, i32 4) #2
-// CHECK: store <16 x float> [[TMP24]], <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP25:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP26:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[SHUFFLE8_I:%.*]] = shufflevector <16 x float> [[TMP25]], <16 x float> [[TMP26]], <16 x i32> <i32 0, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP27:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP28:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x float> [[TMP27]], <16 x float> [[TMP28]], <16 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <16 x float> [[SHUFFLE8_I]], <16 x float>* [[__A_ADDR_I12_I]], align 64
-// CHECK: store <16 x float> [[SHUFFLE9_I]], <16 x float>* [[__B_ADDR_I13_I]], align 64
-// CHECK: [[TMP29:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I12_I]], align 64
-// CHECK: [[TMP30:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I13_I]], align 64
-// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I11_I]], align 64
-// CHECK: [[TMP31:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I11_I]], align 64
-// CHECK: [[TMP32:%.*]] = call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> [[TMP29]], <16 x float> [[TMP30]], <16 x float> [[TMP31]], i16 -1, i32 4) #2
-// CHECK: store <16 x float> [[TMP32]], <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP33:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[VECEXT_I:%.*]] = extractelement <16 x float> [[TMP33]], i32 0
-// CHECK: ret float [[VECEXT_I]]
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[__A_ADDR_I14_I:%.*]] = alloca <8 x float>, align 32
+// CHECK-NEXT: [[__B_ADDR_I15_I:%.*]] = alloca <8 x float>, align 32
+// CHECK-NEXT: [[__A_ADDR_I12_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__B_ADDR_I13_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__A_ADDR_I10_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__B_ADDR_I11_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <16 x float>, align 64
+// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x float>, align 32
+// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x float>, align 32
+// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x float>, align 32
+// CHECK-NEXT: [[__T4_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__T5_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__T6_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__T7_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__T8_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__T9_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <16 x float>, align 64
+// CHECK-NEXT: store <16 x float> [[__W:%.*]], <16 x float>* [[__W_ADDR]], align 64
+// CHECK-NEXT: [[TMP0:%.*]] = load <16 x float>, <16 x float>* [[__W_ADDR]], align 64
+// CHECK-NEXT: store <16 x float> [[TMP0]], <16 x float>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP1:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x float> [[TMP1]] to <8 x double>
+// CHECK-NEXT: [[EXTRACT_I:%.*]] = shufflevector <8 x double> [[TMP2]], <8 x double> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK-NEXT: [[TMP3:%.*]] = bitcast <4 x double> [[EXTRACT_I]] to <8 x float>
+// CHECK-NEXT: store <8 x float> [[TMP3]], <8 x float>* [[__T1_I]], align 32
+// CHECK-NEXT: [[TMP4:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP5:%.*]] = bitcast <16 x float> [[TMP4]] to <8 x double>
+// CHECK-NEXT: [[EXTRACT2_I:%.*]] = shufflevector <8 x double> [[TMP5]], <8 x double> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK-NEXT: [[TMP6:%.*]] = bitcast <4 x double> [[EXTRACT2_I]] to <8 x float>
+// CHECK-NEXT: store <8 x float> [[TMP6]], <8 x float>* [[__T2_I]], align 32
+// CHECK-NEXT: [[TMP7:%.*]] = load <8 x float>, <8 x float>* [[__T1_I]], align 32
+// CHECK-NEXT: [[TMP8:%.*]] = load <8 x float>, <8 x float>* [[__T2_I]], align 32
+// CHECK-NEXT: store <8 x float> [[TMP7]], <8 x float>* [[__A_ADDR_I14_I]], align 32
+// CHECK-NEXT: store <8 x float> [[TMP8]], <8 x float>* [[__B_ADDR_I15_I]], align 32
+// CHECK-NEXT: [[TMP9:%.*]] = load <8 x float>, <8 x float>* [[__A_ADDR_I14_I]], align 32
+// CHECK-NEXT: [[TMP10:%.*]] = load <8 x float>, <8 x float>* [[__B_ADDR_I15_I]], align 32
+// CHECK-NEXT: [[TMP11:%.*]] = call <8 x float> @llvm.x86.avx.max.ps.256(<8 x float> [[TMP9]], <8 x float> [[TMP10]]) #2
+// CHECK-NEXT: store <8 x float> [[TMP11]], <8 x float>* [[__T3_I]], align 32
+// CHECK-NEXT: [[TMP12:%.*]] = load <8 x float>, <8 x float>* [[__T3_I]], align 32
+// CHECK-NEXT: [[EXTRACT4_I:%.*]] = shufflevector <8 x float> [[TMP12]], <8 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK-NEXT: store <4 x float> [[EXTRACT4_I]], <4 x float>* [[__T4_I]], align 16
+// CHECK-NEXT: [[TMP13:%.*]] = load <8 x float>, <8 x float>* [[__T3_I]], align 32
+// CHECK-NEXT: [[EXTRACT5_I:%.*]] = shufflevector <8 x float> [[TMP13]], <8 x float> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK-NEXT: store <4 x float> [[EXTRACT5_I]], <4 x float>* [[__T5_I]], align 16
+// CHECK-NEXT: [[TMP14:%.*]] = load <4 x float>, <4 x float>* [[__T4_I]], align 16
+// CHECK-NEXT: [[TMP15:%.*]] = load <4 x float>, <4 x float>* [[__T5_I]], align 16
+// CHECK-NEXT: store <4 x float> [[TMP14]], <4 x float>* [[__A_ADDR_I12_I]], align 16
+// CHECK-NEXT: store <4 x float> [[TMP15]], <4 x float>* [[__B_ADDR_I13_I]], align 16
+// CHECK-NEXT: [[TMP16:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I12_I]], align 16
+// CHECK-NEXT: [[TMP17:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I13_I]], align 16
+// CHECK-NEXT: [[TMP18:%.*]] = call <4 x float> @llvm.x86.sse.max.ps(<4 x float> [[TMP16]], <4 x float> [[TMP17]]) #2
+// CHECK-NEXT: store <4 x float> [[TMP18]], <4 x float>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP19:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP20:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x float> [[TMP19]], <4 x float> [[TMP20]], <4 x i32> <i32 2, i32 3, i32 0, i32 1>
+// CHECK-NEXT: store <4 x float> [[SHUFFLE_I]], <4 x float>* [[__T7_I]], align 16
+// CHECK-NEXT: [[TMP21:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP22:%.*]] = load <4 x float>, <4 x float>* [[__T7_I]], align 16
+// CHECK-NEXT: store <4 x float> [[TMP21]], <4 x float>* [[__A_ADDR_I10_I]], align 16
+// CHECK-NEXT: store <4 x float> [[TMP22]], <4 x float>* [[__B_ADDR_I11_I]], align 16
+// CHECK-NEXT: [[TMP23:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I10_I]], align 16
+// CHECK-NEXT: [[TMP24:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I11_I]], align 16
+// CHECK-NEXT: [[TMP25:%.*]] = call <4 x float> @llvm.x86.sse.max.ps(<4 x float> [[TMP23]], <4 x float> [[TMP24]]) #2
+// CHECK-NEXT: store <4 x float> [[TMP25]], <4 x float>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP26:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP27:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16
+// CHECK-NEXT: [[SHUFFLE8_I:%.*]] = shufflevector <4 x float> [[TMP26]], <4 x float> [[TMP27]], <4 x i32> <i32 1, i32 0, i32 3, i32 2>
+// CHECK-NEXT: store <4 x float> [[SHUFFLE8_I]], <4 x float>* [[__T9_I]], align 16
+// CHECK-NEXT: [[TMP28:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP29:%.*]] = load <4 x float>, <4 x float>* [[__T9_I]], align 16
+// CHECK-NEXT: store <4 x float> [[TMP28]], <4 x float>* [[__A_ADDR_I_I]], align 16
+// CHECK-NEXT: store <4 x float> [[TMP29]], <4 x float>* [[__B_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP30:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP31:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP32:%.*]] = call <4 x float> @llvm.x86.sse.max.ps(<4 x float> [[TMP30]], <4 x float> [[TMP31]]) #2
+// CHECK-NEXT: store <4 x float> [[TMP32]], <4 x float>* [[__T10_I]], align 16
+// CHECK-NEXT: [[TMP33:%.*]] = load <4 x float>, <4 x float>* [[__T10_I]], align 16
+// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x float> [[TMP33]], i32 0
+// CHECK-NEXT: ret float [[VECEXT_I]]
float test_mm512_reduce_max_ps(__m512 __W){
return _mm512_reduce_max_ps(__W);
}
// CHECK-LABEL: define i32 @test_mm512_reduce_min_epi32(<8 x i64> %__W) #0 {
-// CHECK: [[_COMPOUNDLITERAL_I_I17_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I18_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I19_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I14_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I15_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I16_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I11_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[A_ADDR_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64
-// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64
-// CHECK: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64
-// CHECK: store <8 x i64> [[TMP0]], <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i64> [[TMP1]] to <16 x i32>
-// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i64> [[TMP3]] to <16 x i32>
-// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i32> [[TMP2]], <16 x i32> [[TMP4]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i32> [[SHUFFLE_I]] to <8 x i64>
-// CHECK: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP7:%.*]] = bitcast <8 x i64> [[TMP6]] to <16 x i32>
-// CHECK: [[TMP8:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP9:%.*]] = bitcast <8 x i64> [[TMP8]] to <16 x i32>
-// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x i32> [[TMP7]], <16 x i32> [[TMP9]], <16 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP10:%.*]] = bitcast <16 x i32> [[SHUFFLE1_I]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP5]], <8 x i64>* [[__A_ADDR_I_I]], align 64
-// CHECK: store <8 x i64> [[TMP10]], <8 x i64>* [[__B_ADDR_I_I]], align 64
-// CHECK: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64
-// CHECK: [[TMP12:%.*]] = bitcast <8 x i64> [[TMP11]] to <16 x i32>
-// CHECK: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64
-// CHECK: [[TMP14:%.*]] = bitcast <8 x i64> [[TMP13]] to <16 x i32>
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP16:%.*]] = bitcast <8 x i64> [[TMP15]] to <16 x i32>
-// CHECK: [[TMP17:%.*]] = icmp slt <16 x i32> [[TMP12]], [[TMP14]]
-// CHECK: [[TMP18:%.*]] = select <16 x i1> [[TMP17]], <16 x i32> [[TMP12]], <16 x i32> [[TMP14]]
-// CHECK: [[TMP19:%.*]] = bitcast <16 x i32> [[TMP18]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP19]], <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP21:%.*]] = bitcast <8 x i64> [[TMP20]] to <16 x i32>
-// CHECK: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP23:%.*]] = bitcast <8 x i64> [[TMP22]] to <16 x i32>
-// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <16 x i32> [[TMP21]], <16 x i32> [[TMP23]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP24:%.*]] = bitcast <16 x i32> [[SHUFFLE2_I]] to <8 x i64>
-// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP26:%.*]] = bitcast <8 x i64> [[TMP25]] to <16 x i32>
-// CHECK: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP28:%.*]] = bitcast <8 x i64> [[TMP27]] to <16 x i32>
-// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x i32> [[TMP26]], <16 x i32> [[TMP28]], <16 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP29:%.*]] = bitcast <16 x i32> [[SHUFFLE3_I]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP24]], <8 x i64>* [[__A_ADDR_I18_I]], align 64
-// CHECK: store <8 x i64> [[TMP29]], <8 x i64>* [[__B_ADDR_I19_I]], align 64
-// CHECK: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I18_I]], align 64
-// CHECK: [[TMP31:%.*]] = bitcast <8 x i64> [[TMP30]] to <16 x i32>
-// CHECK: [[TMP32:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I19_I]], align 64
-// CHECK: [[TMP33:%.*]] = bitcast <8 x i64> [[TMP32]] to <16 x i32>
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I17_I]], align 64
-// CHECK: [[TMP34:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I17_I]], align 64
-// CHECK: [[TMP35:%.*]] = bitcast <8 x i64> [[TMP34]] to <16 x i32>
-// CHECK: [[TMP36:%.*]] = icmp slt <16 x i32> [[TMP31]], [[TMP33]]
-// CHECK: [[TMP37:%.*]] = select <16 x i1> [[TMP36]], <16 x i32> [[TMP31]], <16 x i32> [[TMP33]]
-// CHECK: [[TMP38:%.*]] = bitcast <16 x i32> [[TMP37]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP38]], <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP39:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP40:%.*]] = bitcast <8 x i64> [[TMP39]] to <16 x i32>
-// CHECK: [[TMP41:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP42:%.*]] = bitcast <8 x i64> [[TMP41]] to <16 x i32>
-// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <16 x i32> [[TMP40]], <16 x i32> [[TMP42]], <16 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP43:%.*]] = bitcast <16 x i32> [[SHUFFLE5_I]] to <8 x i64>
-// CHECK: [[TMP44:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP45:%.*]] = bitcast <8 x i64> [[TMP44]] to <16 x i32>
-// CHECK: [[TMP46:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP47:%.*]] = bitcast <8 x i64> [[TMP46]] to <16 x i32>
-// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x i32> [[TMP45]], <16 x i32> [[TMP47]], <16 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP48:%.*]] = bitcast <16 x i32> [[SHUFFLE6_I]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP43]], <8 x i64>* [[__A_ADDR_I15_I]], align 64
-// CHECK: store <8 x i64> [[TMP48]], <8 x i64>* [[__B_ADDR_I16_I]], align 64
-// CHECK: [[TMP49:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I15_I]], align 64
-// CHECK: [[TMP50:%.*]] = bitcast <8 x i64> [[TMP49]] to <16 x i32>
-// CHECK: [[TMP51:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I16_I]], align 64
-// CHECK: [[TMP52:%.*]] = bitcast <8 x i64> [[TMP51]] to <16 x i32>
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I14_I]], align 64
-// CHECK: [[TMP53:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I14_I]], align 64
-// CHECK: [[TMP54:%.*]] = bitcast <8 x i64> [[TMP53]] to <16 x i32>
-// CHECK: [[TMP55:%.*]] = icmp slt <16 x i32> [[TMP50]], [[TMP52]]
-// CHECK: [[TMP56:%.*]] = select <16 x i1> [[TMP55]], <16 x i32> [[TMP50]], <16 x i32> [[TMP52]]
-// CHECK: [[TMP57:%.*]] = bitcast <16 x i32> [[TMP56]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP57]], <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP58:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP59:%.*]] = bitcast <8 x i64> [[TMP58]] to <16 x i32>
-// CHECK: [[TMP60:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP61:%.*]] = bitcast <8 x i64> [[TMP60]] to <16 x i32>
-// CHECK: [[SHUFFLE8_I:%.*]] = shufflevector <16 x i32> [[TMP59]], <16 x i32> [[TMP61]], <16 x i32> <i32 0, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP62:%.*]] = bitcast <16 x i32> [[SHUFFLE8_I]] to <8 x i64>
-// CHECK: [[TMP63:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP64:%.*]] = bitcast <8 x i64> [[TMP63]] to <16 x i32>
-// CHECK: [[TMP65:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP66:%.*]] = bitcast <8 x i64> [[TMP65]] to <16 x i32>
-// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x i32> [[TMP64]], <16 x i32> [[TMP66]], <16 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP67:%.*]] = bitcast <16 x i32> [[SHUFFLE9_I]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP62]], <8 x i64>* [[__A_ADDR_I12_I]], align 64
-// CHECK: store <8 x i64> [[TMP67]], <8 x i64>* [[__B_ADDR_I13_I]], align 64
-// CHECK: [[TMP68:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I12_I]], align 64
-// CHECK: [[TMP69:%.*]] = bitcast <8 x i64> [[TMP68]] to <16 x i32>
-// CHECK: [[TMP70:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I13_I]], align 64
-// CHECK: [[TMP71:%.*]] = bitcast <8 x i64> [[TMP70]] to <16 x i32>
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I11_I]], align 64
-// CHECK: [[TMP72:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I11_I]], align 64
-// CHECK: [[TMP73:%.*]] = bitcast <8 x i64> [[TMP72]] to <16 x i32>
-// CHECK: [[TMP74:%.*]] = icmp slt <16 x i32> [[TMP69]], [[TMP71]]
-// CHECK: [[TMP75:%.*]] = select <16 x i1> [[TMP74]], <16 x i32> [[TMP69]], <16 x i32> [[TMP71]]
-// CHECK: [[TMP76:%.*]] = bitcast <16 x i32> [[TMP75]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP76]], <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP77:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP77]], i32 0
-// CHECK: [[CONV_I:%.*]] = trunc i64 [[VECEXT_I]] to i32
-// CHECK: ret i32 [[CONV_I]]
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__V1_ADDR_I12_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V2_ADDR_I13_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V1_ADDR_I10_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V2_ADDR_I11_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V1_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V2_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T9_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x i32>, align 16
+// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64
+// CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[EXTRACT_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK-NEXT: store <4 x i64> [[EXTRACT_I]], <4 x i64>* [[__T1_I]], align 32
+// CHECK-NEXT: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[EXTRACT2_I:%.*]] = shufflevector <8 x i64> [[TMP2]], <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK-NEXT: store <4 x i64> [[EXTRACT2_I]], <4 x i64>* [[__T2_I]], align 32
+// CHECK-NEXT: [[TMP3:%.*]] = load <4 x i64>, <4 x i64>* [[__T1_I]], align 32
+// CHECK-NEXT: [[TMP4:%.*]] = load <4 x i64>, <4 x i64>* [[__T2_I]], align 32
+// CHECK-NEXT: store <4 x i64> [[TMP3]], <4 x i64>* [[__A_ADDR_I_I]], align 32
+// CHECK-NEXT: store <4 x i64> [[TMP4]], <4 x i64>* [[__B_ADDR_I_I]], align 32
+// CHECK-NEXT: [[TMP5:%.*]] = load <4 x i64>, <4 x i64>* [[__A_ADDR_I_I]], align 32
+// CHECK-NEXT: [[TMP6:%.*]] = bitcast <4 x i64> [[TMP5]] to <8 x i32>
+// CHECK-NEXT: [[TMP7:%.*]] = load <4 x i64>, <4 x i64>* [[__B_ADDR_I_I]], align 32
+// CHECK-NEXT: [[TMP8:%.*]] = bitcast <4 x i64> [[TMP7]] to <8 x i32>
+// CHECK-NEXT: [[TMP9:%.*]] = icmp slt <8 x i32> [[TMP6]], [[TMP8]]
+// CHECK-NEXT: [[TMP10:%.*]] = select <8 x i1> [[TMP9]], <8 x i32> [[TMP6]], <8 x i32> [[TMP8]]
+// CHECK-NEXT: [[TMP11:%.*]] = bitcast <8 x i32> [[TMP10]] to <4 x i64>
+// CHECK-NEXT: store <4 x i64> [[TMP11]], <4 x i64>* [[__T3_I]], align 32
+// CHECK-NEXT: [[TMP12:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32
+// CHECK-NEXT: [[EXTRACT4_I:%.*]] = shufflevector <4 x i64> [[TMP12]], <4 x i64> undef, <2 x i32> <i32 0, i32 1>
+// CHECK-NEXT: store <2 x i64> [[EXTRACT4_I]], <2 x i64>* [[__T4_I]], align 16
+// CHECK-NEXT: [[TMP13:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32
+// CHECK-NEXT: [[EXTRACT5_I:%.*]] = shufflevector <4 x i64> [[TMP13]], <4 x i64> undef, <2 x i32> <i32 2, i32 3>
+// CHECK-NEXT: store <2 x i64> [[EXTRACT5_I]], <2 x i64>* [[__T5_I]], align 16
+// CHECK-NEXT: [[TMP14:%.*]] = load <2 x i64>, <2 x i64>* [[__T4_I]], align 16
+// CHECK-NEXT: [[TMP15:%.*]] = load <2 x i64>, <2 x i64>* [[__T5_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP14]], <2 x i64>* [[__V1_ADDR_I12_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP15]], <2 x i64>* [[__V2_ADDR_I13_I]], align 16
+// CHECK-NEXT: [[TMP16:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I12_I]], align 16
+// CHECK-NEXT: [[TMP17:%.*]] = bitcast <2 x i64> [[TMP16]] to <4 x i32>
+// CHECK-NEXT: [[TMP18:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I13_I]], align 16
+// CHECK-NEXT: [[TMP19:%.*]] = bitcast <2 x i64> [[TMP18]] to <4 x i32>
+// CHECK-NEXT: [[TMP20:%.*]] = icmp slt <4 x i32> [[TMP17]], [[TMP19]]
+// CHECK-NEXT: [[TMP21:%.*]] = select <4 x i1> [[TMP20]], <4 x i32> [[TMP17]], <4 x i32> [[TMP19]]
+// CHECK-NEXT: [[TMP22:%.*]] = bitcast <4 x i32> [[TMP21]] to <2 x i64>
+// CHECK-NEXT: store <2 x i64> [[TMP22]], <2 x i64>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP23:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP24:%.*]] = bitcast <2 x i64> [[TMP23]] to <4 x i32>
+// CHECK-NEXT: [[TMP25:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP26:%.*]] = bitcast <2 x i64> [[TMP25]] to <4 x i32>
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> [[TMP24]], <4 x i32> [[TMP26]], <4 x i32> <i32 2, i32 3, i32 0, i32 1>
+// CHECK-NEXT: [[TMP27:%.*]] = bitcast <4 x i32> [[SHUFFLE_I]] to <2 x i64>
+// CHECK-NEXT: store <2 x i64> [[TMP27]], <2 x i64>* [[__T7_I]], align 16
+// CHECK-NEXT: [[TMP28:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP29:%.*]] = load <2 x i64>, <2 x i64>* [[__T7_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP28]], <2 x i64>* [[__V1_ADDR_I10_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP29]], <2 x i64>* [[__V2_ADDR_I11_I]], align 16
+// CHECK-NEXT: [[TMP30:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I10_I]], align 16
+// CHECK-NEXT: [[TMP31:%.*]] = bitcast <2 x i64> [[TMP30]] to <4 x i32>
+// CHECK-NEXT: [[TMP32:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I11_I]], align 16
+// CHECK-NEXT: [[TMP33:%.*]] = bitcast <2 x i64> [[TMP32]] to <4 x i32>
+// CHECK-NEXT: [[TMP34:%.*]] = icmp slt <4 x i32> [[TMP31]], [[TMP33]]
+// CHECK-NEXT: [[TMP35:%.*]] = select <4 x i1> [[TMP34]], <4 x i32> [[TMP31]], <4 x i32> [[TMP33]]
+// CHECK-NEXT: [[TMP36:%.*]] = bitcast <4 x i32> [[TMP35]] to <2 x i64>
+// CHECK-NEXT: store <2 x i64> [[TMP36]], <2 x i64>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP37:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP38:%.*]] = bitcast <2 x i64> [[TMP37]] to <4 x i32>
+// CHECK-NEXT: [[TMP39:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP40:%.*]] = bitcast <2 x i64> [[TMP39]] to <4 x i32>
+// CHECK-NEXT: [[SHUFFLE8_I:%.*]] = shufflevector <4 x i32> [[TMP38]], <4 x i32> [[TMP40]], <4 x i32> <i32 1, i32 0, i32 3, i32 2>
+// CHECK-NEXT: [[TMP41:%.*]] = bitcast <4 x i32> [[SHUFFLE8_I]] to <2 x i64>
+// CHECK-NEXT: store <2 x i64> [[TMP41]], <2 x i64>* [[__T9_I]], align 16
+// CHECK-NEXT: [[TMP42:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP43:%.*]] = load <2 x i64>, <2 x i64>* [[__T9_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP42]], <2 x i64>* [[__V1_ADDR_I_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP43]], <2 x i64>* [[__V2_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP44:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP45:%.*]] = bitcast <2 x i64> [[TMP44]] to <4 x i32>
+// CHECK-NEXT: [[TMP46:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP47:%.*]] = bitcast <2 x i64> [[TMP46]] to <4 x i32>
+// CHECK-NEXT: [[TMP48:%.*]] = icmp slt <4 x i32> [[TMP45]], [[TMP47]]
+// CHECK-NEXT: [[TMP49:%.*]] = select <4 x i1> [[TMP48]], <4 x i32> [[TMP45]], <4 x i32> [[TMP47]]
+// CHECK-NEXT: [[TMP50:%.*]] = bitcast <4 x i32> [[TMP49]] to <2 x i64>
+// CHECK-NEXT: store <4 x i32> [[TMP49]], <4 x i32>* [[__T10_I]], align 16
+// CHECK-NEXT: [[TMP51:%.*]] = load <4 x i32>, <4 x i32>* [[__T10_I]], align 16
+// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x i32> [[TMP51]], i32 0
+// CHECK-NEXT: ret i32 [[VECEXT_I]]
int test_mm512_reduce_min_epi32(__m512i __W){
return _mm512_reduce_min_epi32(__W);
}
// CHECK-LABEL: define i32 @test_mm512_reduce_min_epu32(<8 x i64> %__W) #0 {
-// CHECK: [[_COMPOUNDLITERAL_I_I17_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I18_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I19_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I14_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I15_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I16_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I11_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[A_ADDR_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64
-// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64
-// CHECK: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64
-// CHECK: store <8 x i64> [[TMP0]], <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i64> [[TMP1]] to <16 x i32>
-// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i64> [[TMP3]] to <16 x i32>
-// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i32> [[TMP2]], <16 x i32> [[TMP4]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i32> [[SHUFFLE_I]] to <8 x i64>
-// CHECK: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP7:%.*]] = bitcast <8 x i64> [[TMP6]] to <16 x i32>
-// CHECK: [[TMP8:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP9:%.*]] = bitcast <8 x i64> [[TMP8]] to <16 x i32>
-// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x i32> [[TMP7]], <16 x i32> [[TMP9]], <16 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP10:%.*]] = bitcast <16 x i32> [[SHUFFLE1_I]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP5]], <8 x i64>* [[__A_ADDR_I_I]], align 64
-// CHECK: store <8 x i64> [[TMP10]], <8 x i64>* [[__B_ADDR_I_I]], align 64
-// CHECK: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64
-// CHECK: [[TMP12:%.*]] = bitcast <8 x i64> [[TMP11]] to <16 x i32>
-// CHECK: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64
-// CHECK: [[TMP14:%.*]] = bitcast <8 x i64> [[TMP13]] to <16 x i32>
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP16:%.*]] = bitcast <8 x i64> [[TMP15]] to <16 x i32>
-// CHECK: [[TMP17:%.*]] = icmp ult <16 x i32> [[TMP12]], [[TMP14]]
-// CHECK: [[TMP18:%.*]] = select <16 x i1> [[TMP17]], <16 x i32> [[TMP12]], <16 x i32> [[TMP14]]
-// CHECK: [[TMP19:%.*]] = bitcast <16 x i32> [[TMP18]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP19]], <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP21:%.*]] = bitcast <8 x i64> [[TMP20]] to <16 x i32>
-// CHECK: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP23:%.*]] = bitcast <8 x i64> [[TMP22]] to <16 x i32>
-// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <16 x i32> [[TMP21]], <16 x i32> [[TMP23]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP24:%.*]] = bitcast <16 x i32> [[SHUFFLE2_I]] to <8 x i64>
-// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP26:%.*]] = bitcast <8 x i64> [[TMP25]] to <16 x i32>
-// CHECK: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP28:%.*]] = bitcast <8 x i64> [[TMP27]] to <16 x i32>
-// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x i32> [[TMP26]], <16 x i32> [[TMP28]], <16 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP29:%.*]] = bitcast <16 x i32> [[SHUFFLE3_I]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP24]], <8 x i64>* [[__A_ADDR_I18_I]], align 64
-// CHECK: store <8 x i64> [[TMP29]], <8 x i64>* [[__B_ADDR_I19_I]], align 64
-// CHECK: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I18_I]], align 64
-// CHECK: [[TMP31:%.*]] = bitcast <8 x i64> [[TMP30]] to <16 x i32>
-// CHECK: [[TMP32:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I19_I]], align 64
-// CHECK: [[TMP33:%.*]] = bitcast <8 x i64> [[TMP32]] to <16 x i32>
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I17_I]], align 64
-// CHECK: [[TMP34:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I17_I]], align 64
-// CHECK: [[TMP35:%.*]] = bitcast <8 x i64> [[TMP34]] to <16 x i32>
-// CHECK: [[TMP36:%.*]] = icmp ult <16 x i32> [[TMP31]], [[TMP33]]
-// CHECK: [[TMP37:%.*]] = select <16 x i1> [[TMP36]], <16 x i32> [[TMP31]], <16 x i32> [[TMP33]]
-// CHECK: [[TMP38:%.*]] = bitcast <16 x i32> [[TMP37]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP38]], <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP39:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP40:%.*]] = bitcast <8 x i64> [[TMP39]] to <16 x i32>
-// CHECK: [[TMP41:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP42:%.*]] = bitcast <8 x i64> [[TMP41]] to <16 x i32>
-// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <16 x i32> [[TMP40]], <16 x i32> [[TMP42]], <16 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP43:%.*]] = bitcast <16 x i32> [[SHUFFLE5_I]] to <8 x i64>
-// CHECK: [[TMP44:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP45:%.*]] = bitcast <8 x i64> [[TMP44]] to <16 x i32>
-// CHECK: [[TMP46:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP47:%.*]] = bitcast <8 x i64> [[TMP46]] to <16 x i32>
-// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x i32> [[TMP45]], <16 x i32> [[TMP47]], <16 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP48:%.*]] = bitcast <16 x i32> [[SHUFFLE6_I]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP43]], <8 x i64>* [[__A_ADDR_I15_I]], align 64
-// CHECK: store <8 x i64> [[TMP48]], <8 x i64>* [[__B_ADDR_I16_I]], align 64
-// CHECK: [[TMP49:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I15_I]], align 64
-// CHECK: [[TMP50:%.*]] = bitcast <8 x i64> [[TMP49]] to <16 x i32>
-// CHECK: [[TMP51:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I16_I]], align 64
-// CHECK: [[TMP52:%.*]] = bitcast <8 x i64> [[TMP51]] to <16 x i32>
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I14_I]], align 64
-// CHECK: [[TMP53:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I14_I]], align 64
-// CHECK: [[TMP54:%.*]] = bitcast <8 x i64> [[TMP53]] to <16 x i32>
-// CHECK: [[TMP55:%.*]] = icmp ult <16 x i32> [[TMP50]], [[TMP52]]
-// CHECK: [[TMP56:%.*]] = select <16 x i1> [[TMP55]], <16 x i32> [[TMP50]], <16 x i32> [[TMP52]]
-// CHECK: [[TMP57:%.*]] = bitcast <16 x i32> [[TMP56]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP57]], <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP58:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP59:%.*]] = bitcast <8 x i64> [[TMP58]] to <16 x i32>
-// CHECK: [[TMP60:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP61:%.*]] = bitcast <8 x i64> [[TMP60]] to <16 x i32>
-// CHECK: [[SHUFFLE8_I:%.*]] = shufflevector <16 x i32> [[TMP59]], <16 x i32> [[TMP61]], <16 x i32> <i32 0, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP62:%.*]] = bitcast <16 x i32> [[SHUFFLE8_I]] to <8 x i64>
-// CHECK: [[TMP63:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP64:%.*]] = bitcast <8 x i64> [[TMP63]] to <16 x i32>
-// CHECK: [[TMP65:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP66:%.*]] = bitcast <8 x i64> [[TMP65]] to <16 x i32>
-// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x i32> [[TMP64]], <16 x i32> [[TMP66]], <16 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP67:%.*]] = bitcast <16 x i32> [[SHUFFLE9_I]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP62]], <8 x i64>* [[__A_ADDR_I12_I]], align 64
-// CHECK: store <8 x i64> [[TMP67]], <8 x i64>* [[__B_ADDR_I13_I]], align 64
-// CHECK: [[TMP68:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I12_I]], align 64
-// CHECK: [[TMP69:%.*]] = bitcast <8 x i64> [[TMP68]] to <16 x i32>
-// CHECK: [[TMP70:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I13_I]], align 64
-// CHECK: [[TMP71:%.*]] = bitcast <8 x i64> [[TMP70]] to <16 x i32>
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I11_I]], align 64
-// CHECK: [[TMP72:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I11_I]], align 64
-// CHECK: [[TMP73:%.*]] = bitcast <8 x i64> [[TMP72]] to <16 x i32>
-// CHECK: [[TMP74:%.*]] = icmp ult <16 x i32> [[TMP69]], [[TMP71]]
-// CHECK: [[TMP75:%.*]] = select <16 x i1> [[TMP74]], <16 x i32> [[TMP69]], <16 x i32> [[TMP71]]
-// CHECK: [[TMP76:%.*]] = bitcast <16 x i32> [[TMP75]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP76]], <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP77:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64
-// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP77]], i32 0
-// CHECK: [[CONV_I:%.*]] = trunc i64 [[VECEXT_I]] to i32
-// CHECK: ret i32 [[CONV_I]]
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__V1_ADDR_I12_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V2_ADDR_I13_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V1_ADDR_I10_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V2_ADDR_I11_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V1_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V2_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T9_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x i32>, align 16
+// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64
+// CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[EXTRACT_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK-NEXT: store <4 x i64> [[EXTRACT_I]], <4 x i64>* [[__T1_I]], align 32
+// CHECK-NEXT: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[EXTRACT2_I:%.*]] = shufflevector <8 x i64> [[TMP2]], <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK-NEXT: store <4 x i64> [[EXTRACT2_I]], <4 x i64>* [[__T2_I]], align 32
+// CHECK-NEXT: [[TMP3:%.*]] = load <4 x i64>, <4 x i64>* [[__T1_I]], align 32
+// CHECK-NEXT: [[TMP4:%.*]] = load <4 x i64>, <4 x i64>* [[__T2_I]], align 32
+// CHECK-NEXT: store <4 x i64> [[TMP3]], <4 x i64>* [[__A_ADDR_I_I]], align 32
+// CHECK-NEXT: store <4 x i64> [[TMP4]], <4 x i64>* [[__B_ADDR_I_I]], align 32
+// CHECK-NEXT: [[TMP5:%.*]] = load <4 x i64>, <4 x i64>* [[__A_ADDR_I_I]], align 32
+// CHECK-NEXT: [[TMP6:%.*]] = bitcast <4 x i64> [[TMP5]] to <8 x i32>
+// CHECK-NEXT: [[TMP7:%.*]] = load <4 x i64>, <4 x i64>* [[__B_ADDR_I_I]], align 32
+// CHECK-NEXT: [[TMP8:%.*]] = bitcast <4 x i64> [[TMP7]] to <8 x i32>
+// CHECK-NEXT: [[TMP9:%.*]] = icmp ult <8 x i32> [[TMP6]], [[TMP8]]
+// CHECK-NEXT: [[TMP10:%.*]] = select <8 x i1> [[TMP9]], <8 x i32> [[TMP6]], <8 x i32> [[TMP8]]
+// CHECK-NEXT: [[TMP11:%.*]] = bitcast <8 x i32> [[TMP10]] to <4 x i64>
+// CHECK-NEXT: store <4 x i64> [[TMP11]], <4 x i64>* [[__T3_I]], align 32
+// CHECK-NEXT: [[TMP12:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32
+// CHECK-NEXT: [[EXTRACT4_I:%.*]] = shufflevector <4 x i64> [[TMP12]], <4 x i64> undef, <2 x i32> <i32 0, i32 1>
+// CHECK-NEXT: store <2 x i64> [[EXTRACT4_I]], <2 x i64>* [[__T4_I]], align 16
+// CHECK-NEXT: [[TMP13:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32
+// CHECK-NEXT: [[EXTRACT5_I:%.*]] = shufflevector <4 x i64> [[TMP13]], <4 x i64> undef, <2 x i32> <i32 2, i32 3>
+// CHECK-NEXT: store <2 x i64> [[EXTRACT5_I]], <2 x i64>* [[__T5_I]], align 16
+// CHECK-NEXT: [[TMP14:%.*]] = load <2 x i64>, <2 x i64>* [[__T4_I]], align 16
+// CHECK-NEXT: [[TMP15:%.*]] = load <2 x i64>, <2 x i64>* [[__T5_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP14]], <2 x i64>* [[__V1_ADDR_I12_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP15]], <2 x i64>* [[__V2_ADDR_I13_I]], align 16
+// CHECK-NEXT: [[TMP16:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I12_I]], align 16
+// CHECK-NEXT: [[TMP17:%.*]] = bitcast <2 x i64> [[TMP16]] to <4 x i32>
+// CHECK-NEXT: [[TMP18:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I13_I]], align 16
+// CHECK-NEXT: [[TMP19:%.*]] = bitcast <2 x i64> [[TMP18]] to <4 x i32>
+// CHECK-NEXT: [[TMP20:%.*]] = icmp ult <4 x i32> [[TMP17]], [[TMP19]]
+// CHECK-NEXT: [[TMP21:%.*]] = select <4 x i1> [[TMP20]], <4 x i32> [[TMP17]], <4 x i32> [[TMP19]]
+// CHECK-NEXT: [[TMP22:%.*]] = bitcast <4 x i32> [[TMP21]] to <2 x i64>
+// CHECK-NEXT: store <2 x i64> [[TMP22]], <2 x i64>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP23:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP24:%.*]] = bitcast <2 x i64> [[TMP23]] to <4 x i32>
+// CHECK-NEXT: [[TMP25:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP26:%.*]] = bitcast <2 x i64> [[TMP25]] to <4 x i32>
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> [[TMP24]], <4 x i32> [[TMP26]], <4 x i32> <i32 2, i32 3, i32 0, i32 1>
+// CHECK-NEXT: [[TMP27:%.*]] = bitcast <4 x i32> [[SHUFFLE_I]] to <2 x i64>
+// CHECK-NEXT: store <2 x i64> [[TMP27]], <2 x i64>* [[__T7_I]], align 16
+// CHECK-NEXT: [[TMP28:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP29:%.*]] = load <2 x i64>, <2 x i64>* [[__T7_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP28]], <2 x i64>* [[__V1_ADDR_I10_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP29]], <2 x i64>* [[__V2_ADDR_I11_I]], align 16
+// CHECK-NEXT: [[TMP30:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I10_I]], align 16
+// CHECK-NEXT: [[TMP31:%.*]] = bitcast <2 x i64> [[TMP30]] to <4 x i32>
+// CHECK-NEXT: [[TMP32:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I11_I]], align 16
+// CHECK-NEXT: [[TMP33:%.*]] = bitcast <2 x i64> [[TMP32]] to <4 x i32>
+// CHECK-NEXT: [[TMP34:%.*]] = icmp ult <4 x i32> [[TMP31]], [[TMP33]]
+// CHECK-NEXT: [[TMP35:%.*]] = select <4 x i1> [[TMP34]], <4 x i32> [[TMP31]], <4 x i32> [[TMP33]]
+// CHECK-NEXT: [[TMP36:%.*]] = bitcast <4 x i32> [[TMP35]] to <2 x i64>
+// CHECK-NEXT: store <2 x i64> [[TMP36]], <2 x i64>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP37:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP38:%.*]] = bitcast <2 x i64> [[TMP37]] to <4 x i32>
+// CHECK-NEXT: [[TMP39:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP40:%.*]] = bitcast <2 x i64> [[TMP39]] to <4 x i32>
+// CHECK-NEXT: [[SHUFFLE8_I:%.*]] = shufflevector <4 x i32> [[TMP38]], <4 x i32> [[TMP40]], <4 x i32> <i32 1, i32 0, i32 3, i32 2>
+// CHECK-NEXT: [[TMP41:%.*]] = bitcast <4 x i32> [[SHUFFLE8_I]] to <2 x i64>
+// CHECK-NEXT: store <2 x i64> [[TMP41]], <2 x i64>* [[__T9_I]], align 16
+// CHECK-NEXT: [[TMP42:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP43:%.*]] = load <2 x i64>, <2 x i64>* [[__T9_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP42]], <2 x i64>* [[__V1_ADDR_I_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP43]], <2 x i64>* [[__V2_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP44:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP45:%.*]] = bitcast <2 x i64> [[TMP44]] to <4 x i32>
+// CHECK-NEXT: [[TMP46:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP47:%.*]] = bitcast <2 x i64> [[TMP46]] to <4 x i32>
+// CHECK-NEXT: [[TMP48:%.*]] = icmp ult <4 x i32> [[TMP45]], [[TMP47]]
+// CHECK-NEXT: [[TMP49:%.*]] = select <4 x i1> [[TMP48]], <4 x i32> [[TMP45]], <4 x i32> [[TMP47]]
+// CHECK-NEXT: [[TMP50:%.*]] = bitcast <4 x i32> [[TMP49]] to <2 x i64>
+// CHECK-NEXT: store <4 x i32> [[TMP49]], <4 x i32>* [[__T10_I]], align 16
+// CHECK-NEXT: [[TMP51:%.*]] = load <4 x i32>, <4 x i32>* [[__T10_I]], align 16
+// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x i32> [[TMP51]], i32 0
+// CHECK-NEXT: ret i32 [[VECEXT_I]]
unsigned int test_mm512_reduce_min_epu32(__m512i __W){
return _mm512_reduce_min_epu32(__W);
}
// CHECK-LABEL: define float @test_mm512_reduce_min_ps(<16 x float> %__W) #0 {
-// CHECK: [[_COMPOUNDLITERAL_I_I17_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__A_ADDR_I18_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__B_ADDR_I19_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I14_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__A_ADDR_I15_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__B_ADDR_I16_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I11_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[A_ADDR_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__W_ADDR:%.*]] = alloca <16 x float>, align 64
-// CHECK: store <16 x float> %__W, <16 x float>* [[__W_ADDR]], align 64
-// CHECK: [[TMP0:%.*]] = load <16 x float>, <16 x float>* [[__W_ADDR]], align 64
-// CHECK: store <16 x float> [[TMP0]], <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP1:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP2:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x float> [[TMP1]], <16 x float> [[TMP2]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP3:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP4:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x float> [[TMP3]], <16 x float> [[TMP4]], <16 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <16 x float> [[SHUFFLE_I]], <16 x float>* [[__A_ADDR_I_I]], align 64
-// CHECK: store <16 x float> [[SHUFFLE1_I]], <16 x float>* [[__B_ADDR_I_I]], align 64
-// CHECK: [[TMP5:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I_I]], align 64
-// CHECK: [[TMP6:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I_I]], align 64
-// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP7:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP8:%.*]] = call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> [[TMP5]], <16 x float> [[TMP6]], <16 x float> [[TMP7]], i16 -1, i32 4) #2
-// CHECK: store <16 x float> [[TMP8]], <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP9:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP10:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <16 x float> [[TMP9]], <16 x float> [[TMP10]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP11:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP12:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x float> [[TMP11]], <16 x float> [[TMP12]], <16 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <16 x float> [[SHUFFLE2_I]], <16 x float>* [[__A_ADDR_I18_I]], align 64
-// CHECK: store <16 x float> [[SHUFFLE3_I]], <16 x float>* [[__B_ADDR_I19_I]], align 64
-// CHECK: [[TMP13:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I18_I]], align 64
-// CHECK: [[TMP14:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I19_I]], align 64
-// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I17_I]], align 64
-// CHECK: [[TMP15:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I17_I]], align 64
-// CHECK: [[TMP16:%.*]] = call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> [[TMP13]], <16 x float> [[TMP14]], <16 x float> [[TMP15]], i16 -1, i32 4) #2
-// CHECK: store <16 x float> [[TMP16]], <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP17:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP18:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <16 x float> [[TMP17]], <16 x float> [[TMP18]], <16 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP19:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP20:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x float> [[TMP19]], <16 x float> [[TMP20]], <16 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <16 x float> [[SHUFFLE5_I]], <16 x float>* [[__A_ADDR_I15_I]], align 64
-// CHECK: store <16 x float> [[SHUFFLE6_I]], <16 x float>* [[__B_ADDR_I16_I]], align 64
-// CHECK: [[TMP21:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I15_I]], align 64
-// CHECK: [[TMP22:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I16_I]], align 64
-// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I14_I]], align 64
-// CHECK: [[TMP23:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I14_I]], align 64
-// CHECK: [[TMP24:%.*]] = call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> [[TMP21]], <16 x float> [[TMP22]], <16 x float> [[TMP23]], i16 -1, i32 4) #2
-// CHECK: store <16 x float> [[TMP24]], <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP25:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP26:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[SHUFFLE8_I:%.*]] = shufflevector <16 x float> [[TMP25]], <16 x float> [[TMP26]], <16 x i32> <i32 0, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP27:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP28:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x float> [[TMP27]], <16 x float> [[TMP28]], <16 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <16 x float> [[SHUFFLE8_I]], <16 x float>* [[__A_ADDR_I12_I]], align 64
-// CHECK: store <16 x float> [[SHUFFLE9_I]], <16 x float>* [[__B_ADDR_I13_I]], align 64
-// CHECK: [[TMP29:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I12_I]], align 64
-// CHECK: [[TMP30:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I13_I]], align 64
-// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I11_I]], align 64
-// CHECK: [[TMP31:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I11_I]], align 64
-// CHECK: [[TMP32:%.*]] = call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> [[TMP29]], <16 x float> [[TMP30]], <16 x float> [[TMP31]], i16 -1, i32 4) #2
-// CHECK: store <16 x float> [[TMP32]], <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[TMP33:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64
-// CHECK: [[VECEXT_I:%.*]] = extractelement <16 x float> [[TMP33]], i32 0
-// CHECK: ret float [[VECEXT_I]]
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[__A_ADDR_I14_I:%.*]] = alloca <8 x float>, align 32
+// CHECK-NEXT: [[__B_ADDR_I15_I:%.*]] = alloca <8 x float>, align 32
+// CHECK-NEXT: [[__A_ADDR_I12_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__B_ADDR_I13_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__A_ADDR_I10_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__B_ADDR_I11_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <16 x float>, align 64
+// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x float>, align 32
+// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x float>, align 32
+// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x float>, align 32
+// CHECK-NEXT: [[__T4_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__T5_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__T6_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__T7_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__T8_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__T9_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <16 x float>, align 64
+// CHECK-NEXT: store <16 x float> [[__W:%.*]], <16 x float>* [[__W_ADDR]], align 64
+// CHECK-NEXT: [[TMP0:%.*]] = load <16 x float>, <16 x float>* [[__W_ADDR]], align 64
+// CHECK-NEXT: store <16 x float> [[TMP0]], <16 x float>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP1:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x float> [[TMP1]] to <8 x double>
+// CHECK-NEXT: [[EXTRACT_I:%.*]] = shufflevector <8 x double> [[TMP2]], <8 x double> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK-NEXT: [[TMP3:%.*]] = bitcast <4 x double> [[EXTRACT_I]] to <8 x float>
+// CHECK-NEXT: store <8 x float> [[TMP3]], <8 x float>* [[__T1_I]], align 32
+// CHECK-NEXT: [[TMP4:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP5:%.*]] = bitcast <16 x float> [[TMP4]] to <8 x double>
+// CHECK-NEXT: [[EXTRACT2_I:%.*]] = shufflevector <8 x double> [[TMP5]], <8 x double> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK-NEXT: [[TMP6:%.*]] = bitcast <4 x double> [[EXTRACT2_I]] to <8 x float>
+// CHECK-NEXT: store <8 x float> [[TMP6]], <8 x float>* [[__T2_I]], align 32
+// CHECK-NEXT: [[TMP7:%.*]] = load <8 x float>, <8 x float>* [[__T1_I]], align 32
+// CHECK-NEXT: [[TMP8:%.*]] = load <8 x float>, <8 x float>* [[__T2_I]], align 32
+// CHECK-NEXT: store <8 x float> [[TMP7]], <8 x float>* [[__A_ADDR_I14_I]], align 32
+// CHECK-NEXT: store <8 x float> [[TMP8]], <8 x float>* [[__B_ADDR_I15_I]], align 32
+// CHECK-NEXT: [[TMP9:%.*]] = load <8 x float>, <8 x float>* [[__A_ADDR_I14_I]], align 32
+// CHECK-NEXT: [[TMP10:%.*]] = load <8 x float>, <8 x float>* [[__B_ADDR_I15_I]], align 32
+// CHECK-NEXT: [[TMP11:%.*]] = call <8 x float> @llvm.x86.avx.min.ps.256(<8 x float> [[TMP9]], <8 x float> [[TMP10]]) #2
+// CHECK-NEXT: store <8 x float> [[TMP11]], <8 x float>* [[__T3_I]], align 32
+// CHECK-NEXT: [[TMP12:%.*]] = load <8 x float>, <8 x float>* [[__T3_I]], align 32
+// CHECK-NEXT: [[EXTRACT4_I:%.*]] = shufflevector <8 x float> [[TMP12]], <8 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK-NEXT: store <4 x float> [[EXTRACT4_I]], <4 x float>* [[__T4_I]], align 16
+// CHECK-NEXT: [[TMP13:%.*]] = load <8 x float>, <8 x float>* [[__T3_I]], align 32
+// CHECK-NEXT: [[EXTRACT5_I:%.*]] = shufflevector <8 x float> [[TMP13]], <8 x float> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK-NEXT: store <4 x float> [[EXTRACT5_I]], <4 x float>* [[__T5_I]], align 16
+// CHECK-NEXT: [[TMP14:%.*]] = load <4 x float>, <4 x float>* [[__T4_I]], align 16
+// CHECK-NEXT: [[TMP15:%.*]] = load <4 x float>, <4 x float>* [[__T5_I]], align 16
+// CHECK-NEXT: store <4 x float> [[TMP14]], <4 x float>* [[__A_ADDR_I12_I]], align 16
+// CHECK-NEXT: store <4 x float> [[TMP15]], <4 x float>* [[__B_ADDR_I13_I]], align 16
+// CHECK-NEXT: [[TMP16:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I12_I]], align 16
+// CHECK-NEXT: [[TMP17:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I13_I]], align 16
+// CHECK-NEXT: [[TMP18:%.*]] = call <4 x float> @llvm.x86.sse.min.ps(<4 x float> [[TMP16]], <4 x float> [[TMP17]]) #2
+// CHECK-NEXT: store <4 x float> [[TMP18]], <4 x float>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP19:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP20:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x float> [[TMP19]], <4 x float> [[TMP20]], <4 x i32> <i32 2, i32 3, i32 0, i32 1>
+// CHECK-NEXT: store <4 x float> [[SHUFFLE_I]], <4 x float>* [[__T7_I]], align 16
+// CHECK-NEXT: [[TMP21:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP22:%.*]] = load <4 x float>, <4 x float>* [[__T7_I]], align 16
+// CHECK-NEXT: store <4 x float> [[TMP21]], <4 x float>* [[__A_ADDR_I10_I]], align 16
+// CHECK-NEXT: store <4 x float> [[TMP22]], <4 x float>* [[__B_ADDR_I11_I]], align 16
+// CHECK-NEXT: [[TMP23:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I10_I]], align 16
+// CHECK-NEXT: [[TMP24:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I11_I]], align 16
+// CHECK-NEXT: [[TMP25:%.*]] = call <4 x float> @llvm.x86.sse.min.ps(<4 x float> [[TMP23]], <4 x float> [[TMP24]]) #2
+// CHECK-NEXT: store <4 x float> [[TMP25]], <4 x float>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP26:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP27:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16
+// CHECK-NEXT: [[SHUFFLE8_I:%.*]] = shufflevector <4 x float> [[TMP26]], <4 x float> [[TMP27]], <4 x i32> <i32 1, i32 0, i32 3, i32 2>
+// CHECK-NEXT: store <4 x float> [[SHUFFLE8_I]], <4 x float>* [[__T9_I]], align 16
+// CHECK-NEXT: [[TMP28:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP29:%.*]] = load <4 x float>, <4 x float>* [[__T9_I]], align 16
+// CHECK-NEXT: store <4 x float> [[TMP28]], <4 x float>* [[__A_ADDR_I_I]], align 16
+// CHECK-NEXT: store <4 x float> [[TMP29]], <4 x float>* [[__B_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP30:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP31:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP32:%.*]] = call <4 x float> @llvm.x86.sse.min.ps(<4 x float> [[TMP30]], <4 x float> [[TMP31]]) #2
+// CHECK-NEXT: store <4 x float> [[TMP32]], <4 x float>* [[__T10_I]], align 16
+// CHECK-NEXT: [[TMP33:%.*]] = load <4 x float>, <4 x float>* [[__T10_I]], align 16
+// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x float> [[TMP33]], i32 0
+// CHECK-NEXT: ret float [[VECEXT_I]]
float test_mm512_reduce_min_ps(__m512 __W){
return _mm512_reduce_min_ps(__W);
}
// CHECK-LABEL: define i32 @test_mm512_mask_reduce_max_epi32(i16 zeroext %__M, <8 x i64> %__W) #0 {
-// CHECK: [[_COMPOUNDLITERAL_I_I18_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I19_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I20_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I15_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I16_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I17_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I12_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__S_ADDR_I_I:%.*]] = alloca i32, align 4
-// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <16 x i32>, align 64
-// CHECK: [[__M_ADDR_I:%.*]] = alloca i16, align 2
-// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__M_ADDR:%.*]] = alloca i16, align 2
-// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64
-// CHECK: store i16 %__M, i16* [[__M_ADDR]], align 2
-// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64
-// CHECK: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2
-// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64
-// CHECK: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2
-// CHECK: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP2:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2
-// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i64> [[TMP3]] to <16 x i32>
-// CHECK: store i32 -2147483648, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[TMP5:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT_I_I:%.*]] = insertelement <16 x i32> undef, i32 [[TMP5]], i32 0
-// CHECK: [[TMP6:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <16 x i32> [[VECINIT_I_I]], i32 [[TMP6]], i32 1
-// CHECK: [[TMP7:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <16 x i32> [[VECINIT1_I_I]], i32 [[TMP7]], i32 2
-// CHECK: [[TMP8:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <16 x i32> [[VECINIT2_I_I]], i32 [[TMP8]], i32 3
-// CHECK: [[TMP9:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <16 x i32> [[VECINIT3_I_I]], i32 [[TMP9]], i32 4
-// CHECK: [[TMP10:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <16 x i32> [[VECINIT4_I_I]], i32 [[TMP10]], i32 5
-// CHECK: [[TMP11:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <16 x i32> [[VECINIT5_I_I]], i32 [[TMP11]], i32 6
-// CHECK: [[TMP12:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <16 x i32> [[VECINIT6_I_I]], i32 [[TMP12]], i32 7
-// CHECK: [[TMP13:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT8_I_I:%.*]] = insertelement <16 x i32> [[VECINIT7_I_I]], i32 [[TMP13]], i32 8
-// CHECK: [[TMP14:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT9_I_I:%.*]] = insertelement <16 x i32> [[VECINIT8_I_I]], i32 [[TMP14]], i32 9
-// CHECK: [[TMP15:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT10_I_I:%.*]] = insertelement <16 x i32> [[VECINIT9_I_I]], i32 [[TMP15]], i32 10
-// CHECK: [[TMP16:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT11_I_I:%.*]] = insertelement <16 x i32> [[VECINIT10_I_I]], i32 [[TMP16]], i32 11
-// CHECK: [[TMP17:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT12_I_I:%.*]] = insertelement <16 x i32> [[VECINIT11_I_I]], i32 [[TMP17]], i32 12
-// CHECK: [[TMP18:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT13_I_I:%.*]] = insertelement <16 x i32> [[VECINIT12_I_I]], i32 [[TMP18]], i32 13
-// CHECK: [[TMP19:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT14_I_I:%.*]] = insertelement <16 x i32> [[VECINIT13_I_I]], i32 [[TMP19]], i32 14
-// CHECK: [[TMP20:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT15_I_I:%.*]] = insertelement <16 x i32> [[VECINIT14_I_I]], i32 [[TMP20]], i32 15
-// CHECK: store <16 x i32> [[VECINIT15_I_I]], <16 x i32>* [[_COMPOUNDLITERAL_I_I]], align 64
-// CHECK: [[TMP21:%.*]] = load <16 x i32>, <16 x i32>* [[_COMPOUNDLITERAL_I_I]], align 64
-// CHECK: [[TMP22:%.*]] = bitcast <16 x i32> [[TMP21]] to <8 x i64>
-// CHECK: [[TMP23:%.*]] = bitcast i16 [[TMP2]] to <16 x i1>
-// CHECK: [[TMP24:%.*]] = select <16 x i1> [[TMP23]], <16 x i32> [[TMP4]], <16 x i32> [[TMP21]]
-// CHECK: [[TMP25:%.*]] = bitcast <16 x i32> [[TMP24]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP25]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP27:%.*]] = bitcast <8 x i64> [[TMP26]] to <16 x i32>
-// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP29:%.*]] = bitcast <8 x i64> [[TMP28]] to <16 x i32>
-// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i32> [[TMP27]], <16 x i32> [[TMP29]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP30:%.*]] = bitcast <16 x i32> [[SHUFFLE_I]] to <8 x i64>
-// CHECK: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP32:%.*]] = bitcast <8 x i64> [[TMP31]] to <16 x i32>
-// CHECK: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP34:%.*]] = bitcast <8 x i64> [[TMP33]] to <16 x i32>
-// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x i32> [[TMP32]], <16 x i32> [[TMP34]], <16 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP35:%.*]] = bitcast <16 x i32> [[SHUFFLE1_I]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP30]], <8 x i64>* [[__A_ADDR_I19_I]], align 64
-// CHECK: store <8 x i64> [[TMP35]], <8 x i64>* [[__B_ADDR_I20_I]], align 64
-// CHECK: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I19_I]], align 64
-// CHECK: [[TMP37:%.*]] = bitcast <8 x i64> [[TMP36]] to <16 x i32>
-// CHECK: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I20_I]], align 64
-// CHECK: [[TMP39:%.*]] = bitcast <8 x i64> [[TMP38]] to <16 x i32>
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I18_I]], align 64
-// CHECK: [[TMP40:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I18_I]], align 64
-// CHECK: [[TMP41:%.*]] = bitcast <8 x i64> [[TMP40]] to <16 x i32>
-// CHECK: [[TMP42:%.*]] = icmp sgt <16 x i32> [[TMP37]], [[TMP39]]
-// CHECK: [[TMP43:%.*]] = select <16 x i1> [[TMP42]], <16 x i32> [[TMP37]], <16 x i32> [[TMP39]]
-// CHECK: [[TMP44:%.*]] = bitcast <16 x i32> [[TMP43]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP44]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP45:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP46:%.*]] = bitcast <8 x i64> [[TMP45]] to <16 x i32>
-// CHECK: [[TMP47:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP48:%.*]] = bitcast <8 x i64> [[TMP47]] to <16 x i32>
-// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x i32> [[TMP46]], <16 x i32> [[TMP48]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP49:%.*]] = bitcast <16 x i32> [[SHUFFLE3_I]] to <8 x i64>
-// CHECK: [[TMP50:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP51:%.*]] = bitcast <8 x i64> [[TMP50]] to <16 x i32>
-// CHECK: [[TMP52:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP53:%.*]] = bitcast <8 x i64> [[TMP52]] to <16 x i32>
-// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <16 x i32> [[TMP51]], <16 x i32> [[TMP53]], <16 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP54:%.*]] = bitcast <16 x i32> [[SHUFFLE4_I]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP49]], <8 x i64>* [[__A_ADDR_I16_I]], align 64
-// CHECK: store <8 x i64> [[TMP54]], <8 x i64>* [[__B_ADDR_I17_I]], align 64
-// CHECK: [[TMP55:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I16_I]], align 64
-// CHECK: [[TMP56:%.*]] = bitcast <8 x i64> [[TMP55]] to <16 x i32>
-// CHECK: [[TMP57:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I17_I]], align 64
-// CHECK: [[TMP58:%.*]] = bitcast <8 x i64> [[TMP57]] to <16 x i32>
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I15_I]], align 64
-// CHECK: [[TMP59:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I15_I]], align 64
-// CHECK: [[TMP60:%.*]] = bitcast <8 x i64> [[TMP59]] to <16 x i32>
-// CHECK: [[TMP61:%.*]] = icmp sgt <16 x i32> [[TMP56]], [[TMP58]]
-// CHECK: [[TMP62:%.*]] = select <16 x i1> [[TMP61]], <16 x i32> [[TMP56]], <16 x i32> [[TMP58]]
-// CHECK: [[TMP63:%.*]] = bitcast <16 x i32> [[TMP62]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP63]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP64:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP65:%.*]] = bitcast <8 x i64> [[TMP64]] to <16 x i32>
-// CHECK: [[TMP66:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP67:%.*]] = bitcast <8 x i64> [[TMP66]] to <16 x i32>
-// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x i32> [[TMP65]], <16 x i32> [[TMP67]], <16 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP68:%.*]] = bitcast <16 x i32> [[SHUFFLE6_I]] to <8 x i64>
-// CHECK: [[TMP69:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP70:%.*]] = bitcast <8 x i64> [[TMP69]] to <16 x i32>
-// CHECK: [[TMP71:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP72:%.*]] = bitcast <8 x i64> [[TMP71]] to <16 x i32>
-// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <16 x i32> [[TMP70]], <16 x i32> [[TMP72]], <16 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP73:%.*]] = bitcast <16 x i32> [[SHUFFLE7_I]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP68]], <8 x i64>* [[__A_ADDR_I13_I]], align 64
-// CHECK: store <8 x i64> [[TMP73]], <8 x i64>* [[__B_ADDR_I14_I]], align 64
-// CHECK: [[TMP74:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I13_I]], align 64
-// CHECK: [[TMP75:%.*]] = bitcast <8 x i64> [[TMP74]] to <16 x i32>
-// CHECK: [[TMP76:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I14_I]], align 64
-// CHECK: [[TMP77:%.*]] = bitcast <8 x i64> [[TMP76]] to <16 x i32>
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I12_I]], align 64
-// CHECK: [[TMP78:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I12_I]], align 64
-// CHECK: [[TMP79:%.*]] = bitcast <8 x i64> [[TMP78]] to <16 x i32>
-// CHECK: [[TMP80:%.*]] = icmp sgt <16 x i32> [[TMP75]], [[TMP77]]
-// CHECK: [[TMP81:%.*]] = select <16 x i1> [[TMP80]], <16 x i32> [[TMP75]], <16 x i32> [[TMP77]]
-// CHECK: [[TMP82:%.*]] = bitcast <16 x i32> [[TMP81]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP82]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP83:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP84:%.*]] = bitcast <8 x i64> [[TMP83]] to <16 x i32>
-// CHECK: [[TMP85:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP86:%.*]] = bitcast <8 x i64> [[TMP85]] to <16 x i32>
-// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x i32> [[TMP84]], <16 x i32> [[TMP86]], <16 x i32> <i32 0, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP87:%.*]] = bitcast <16 x i32> [[SHUFFLE9_I]] to <8 x i64>
-// CHECK: [[TMP88:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP89:%.*]] = bitcast <8 x i64> [[TMP88]] to <16 x i32>
-// CHECK: [[TMP90:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP91:%.*]] = bitcast <8 x i64> [[TMP90]] to <16 x i32>
-// CHECK: [[SHUFFLE10_I:%.*]] = shufflevector <16 x i32> [[TMP89]], <16 x i32> [[TMP91]], <16 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP92:%.*]] = bitcast <16 x i32> [[SHUFFLE10_I]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP87]], <8 x i64>* [[__A_ADDR_I_I]], align 64
-// CHECK: store <8 x i64> [[TMP92]], <8 x i64>* [[__B_ADDR_I_I]], align 64
-// CHECK: [[TMP93:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64
-// CHECK: [[TMP94:%.*]] = bitcast <8 x i64> [[TMP93]] to <16 x i32>
-// CHECK: [[TMP95:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64
-// CHECK: [[TMP96:%.*]] = bitcast <8 x i64> [[TMP95]] to <16 x i32>
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP97:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP98:%.*]] = bitcast <8 x i64> [[TMP97]] to <16 x i32>
-// CHECK: [[TMP99:%.*]] = icmp sgt <16 x i32> [[TMP94]], [[TMP96]]
-// CHECK: [[TMP100:%.*]] = select <16 x i1> [[TMP99]], <16 x i32> [[TMP94]], <16 x i32> [[TMP96]]
-// CHECK: [[TMP101:%.*]] = bitcast <16 x i32> [[TMP100]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP101]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP102:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP102]], i32 0
-// CHECK: [[CONV_I:%.*]] = trunc i64 [[VECEXT_I]] to i32
-// CHECK: ret i32 [[CONV_I]]
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i16, align 2
+// CHECK-NEXT: [[__A2_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__V1_ADDR_I14_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V2_ADDR_I15_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V1_ADDR_I12_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V2_ADDR_I13_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V1_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V2_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__S_ADDR_I_I:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <16 x i32>, align 64
+// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i16, align 2
+// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T9_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x i32>, align 16
+// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i16, align 2
+// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: store i16 [[__M:%.*]], i16* [[__M_ADDR]], align 2
+// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64
+// CHECK-NEXT: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2
+// CHECK-NEXT: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: store i32 -2147483648, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <16 x i32> undef, i32 [[TMP2]], i32 0
+// CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <16 x i32> [[VECINIT_I_I]], i32 [[TMP3]], i32 1
+// CHECK-NEXT: [[TMP4:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <16 x i32> [[VECINIT1_I_I]], i32 [[TMP4]], i32 2
+// CHECK-NEXT: [[TMP5:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <16 x i32> [[VECINIT2_I_I]], i32 [[TMP5]], i32 3
+// CHECK-NEXT: [[TMP6:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <16 x i32> [[VECINIT3_I_I]], i32 [[TMP6]], i32 4
+// CHECK-NEXT: [[TMP7:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <16 x i32> [[VECINIT4_I_I]], i32 [[TMP7]], i32 5
+// CHECK-NEXT: [[TMP8:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <16 x i32> [[VECINIT5_I_I]], i32 [[TMP8]], i32 6
+// CHECK-NEXT: [[TMP9:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <16 x i32> [[VECINIT6_I_I]], i32 [[TMP9]], i32 7
+// CHECK-NEXT: [[TMP10:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT8_I_I:%.*]] = insertelement <16 x i32> [[VECINIT7_I_I]], i32 [[TMP10]], i32 8
+// CHECK-NEXT: [[TMP11:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT9_I_I:%.*]] = insertelement <16 x i32> [[VECINIT8_I_I]], i32 [[TMP11]], i32 9
+// CHECK-NEXT: [[TMP12:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT10_I_I:%.*]] = insertelement <16 x i32> [[VECINIT9_I_I]], i32 [[TMP12]], i32 10
+// CHECK-NEXT: [[TMP13:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT11_I_I:%.*]] = insertelement <16 x i32> [[VECINIT10_I_I]], i32 [[TMP13]], i32 11
+// CHECK-NEXT: [[TMP14:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT12_I_I:%.*]] = insertelement <16 x i32> [[VECINIT11_I_I]], i32 [[TMP14]], i32 12
+// CHECK-NEXT: [[TMP15:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT13_I_I:%.*]] = insertelement <16 x i32> [[VECINIT12_I_I]], i32 [[TMP15]], i32 13
+// CHECK-NEXT: [[TMP16:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT14_I_I:%.*]] = insertelement <16 x i32> [[VECINIT13_I_I]], i32 [[TMP16]], i32 14
+// CHECK-NEXT: [[TMP17:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT15_I_I:%.*]] = insertelement <16 x i32> [[VECINIT14_I_I]], i32 [[TMP17]], i32 15
+// CHECK-NEXT: store <16 x i32> [[VECINIT15_I_I]], <16 x i32>* [[DOTCOMPOUNDLITERAL_I_I]], align 64
+// CHECK-NEXT: [[TMP18:%.*]] = load <16 x i32>, <16 x i32>* [[DOTCOMPOUNDLITERAL_I_I]], align 64
+// CHECK-NEXT: [[TMP19:%.*]] = bitcast <16 x i32> [[TMP18]] to <8 x i64>
+// CHECK-NEXT: [[TMP20:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2
+// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP19]], <8 x i64>* [[__W_ADDR_I_I]], align 64
+// CHECK-NEXT: store i16 [[TMP20]], i16* [[__U_ADDR_I_I]], align 2
+// CHECK-NEXT: store <8 x i64> [[TMP21]], <8 x i64>* [[__A2_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP22:%.*]] = load i16, i16* [[__U_ADDR_I_I]], align 2
+// CHECK-NEXT: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__A2_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP24:%.*]] = bitcast <8 x i64> [[TMP23]] to <16 x i32>
+// CHECK-NEXT: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP26:%.*]] = bitcast <8 x i64> [[TMP25]] to <16 x i32>
+// CHECK-NEXT: [[TMP27:%.*]] = bitcast i16 [[TMP22]] to <16 x i1>
+// CHECK-NEXT: [[TMP28:%.*]] = select <16 x i1> [[TMP27]], <16 x i32> [[TMP24]], <16 x i32> [[TMP26]]
+// CHECK-NEXT: [[TMP29:%.*]] = bitcast <16 x i32> [[TMP28]] to <8 x i64>
+// CHECK-NEXT: store <8 x i64> [[TMP29]], <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[EXTRACT_I:%.*]] = shufflevector <8 x i64> [[TMP30]], <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK-NEXT: store <4 x i64> [[EXTRACT_I]], <4 x i64>* [[__T1_I]], align 32
+// CHECK-NEXT: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[EXTRACT4_I:%.*]] = shufflevector <8 x i64> [[TMP31]], <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK-NEXT: store <4 x i64> [[EXTRACT4_I]], <4 x i64>* [[__T2_I]], align 32
+// CHECK-NEXT: [[TMP32:%.*]] = load <4 x i64>, <4 x i64>* [[__T1_I]], align 32
+// CHECK-NEXT: [[TMP33:%.*]] = load <4 x i64>, <4 x i64>* [[__T2_I]], align 32
+// CHECK-NEXT: store <4 x i64> [[TMP32]], <4 x i64>* [[__A_ADDR_I_I]], align 32
+// CHECK-NEXT: store <4 x i64> [[TMP33]], <4 x i64>* [[__B_ADDR_I_I]], align 32
+// CHECK-NEXT: [[TMP34:%.*]] = load <4 x i64>, <4 x i64>* [[__A_ADDR_I_I]], align 32
+// CHECK-NEXT: [[TMP35:%.*]] = bitcast <4 x i64> [[TMP34]] to <8 x i32>
+// CHECK-NEXT: [[TMP36:%.*]] = load <4 x i64>, <4 x i64>* [[__B_ADDR_I_I]], align 32
+// CHECK-NEXT: [[TMP37:%.*]] = bitcast <4 x i64> [[TMP36]] to <8 x i32>
+// CHECK-NEXT: [[TMP38:%.*]] = icmp sgt <8 x i32> [[TMP35]], [[TMP37]]
+// CHECK-NEXT: [[TMP39:%.*]] = select <8 x i1> [[TMP38]], <8 x i32> [[TMP35]], <8 x i32> [[TMP37]]
+// CHECK-NEXT: [[TMP40:%.*]] = bitcast <8 x i32> [[TMP39]] to <4 x i64>
+// CHECK-NEXT: store <4 x i64> [[TMP40]], <4 x i64>* [[__T3_I]], align 32
+// CHECK-NEXT: [[TMP41:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32
+// CHECK-NEXT: [[EXTRACT6_I:%.*]] = shufflevector <4 x i64> [[TMP41]], <4 x i64> undef, <2 x i32> <i32 0, i32 1>
+// CHECK-NEXT: store <2 x i64> [[EXTRACT6_I]], <2 x i64>* [[__T4_I]], align 16
+// CHECK-NEXT: [[TMP42:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32
+// CHECK-NEXT: [[EXTRACT7_I:%.*]] = shufflevector <4 x i64> [[TMP42]], <4 x i64> undef, <2 x i32> <i32 2, i32 3>
+// CHECK-NEXT: store <2 x i64> [[EXTRACT7_I]], <2 x i64>* [[__T5_I]], align 16
+// CHECK-NEXT: [[TMP43:%.*]] = load <2 x i64>, <2 x i64>* [[__T4_I]], align 16
+// CHECK-NEXT: [[TMP44:%.*]] = load <2 x i64>, <2 x i64>* [[__T5_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP43]], <2 x i64>* [[__V1_ADDR_I14_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP44]], <2 x i64>* [[__V2_ADDR_I15_I]], align 16
+// CHECK-NEXT: [[TMP45:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I14_I]], align 16
+// CHECK-NEXT: [[TMP46:%.*]] = bitcast <2 x i64> [[TMP45]] to <4 x i32>
+// CHECK-NEXT: [[TMP47:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I15_I]], align 16
+// CHECK-NEXT: [[TMP48:%.*]] = bitcast <2 x i64> [[TMP47]] to <4 x i32>
+// CHECK-NEXT: [[TMP49:%.*]] = icmp sgt <4 x i32> [[TMP46]], [[TMP48]]
+// CHECK-NEXT: [[TMP50:%.*]] = select <4 x i1> [[TMP49]], <4 x i32> [[TMP46]], <4 x i32> [[TMP48]]
+// CHECK-NEXT: [[TMP51:%.*]] = bitcast <4 x i32> [[TMP50]] to <2 x i64>
+// CHECK-NEXT: store <2 x i64> [[TMP51]], <2 x i64>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP52:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP53:%.*]] = bitcast <2 x i64> [[TMP52]] to <4 x i32>
+// CHECK-NEXT: [[TMP54:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP55:%.*]] = bitcast <2 x i64> [[TMP54]] to <4 x i32>
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> [[TMP53]], <4 x i32> [[TMP55]], <4 x i32> <i32 2, i32 3, i32 0, i32 1>
+// CHECK-NEXT: [[TMP56:%.*]] = bitcast <4 x i32> [[SHUFFLE_I]] to <2 x i64>
+// CHECK-NEXT: store <2 x i64> [[TMP56]], <2 x i64>* [[__T7_I]], align 16
+// CHECK-NEXT: [[TMP57:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP58:%.*]] = load <2 x i64>, <2 x i64>* [[__T7_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP57]], <2 x i64>* [[__V1_ADDR_I12_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP58]], <2 x i64>* [[__V2_ADDR_I13_I]], align 16
+// CHECK-NEXT: [[TMP59:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I12_I]], align 16
+// CHECK-NEXT: [[TMP60:%.*]] = bitcast <2 x i64> [[TMP59]] to <4 x i32>
+// CHECK-NEXT: [[TMP61:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I13_I]], align 16
+// CHECK-NEXT: [[TMP62:%.*]] = bitcast <2 x i64> [[TMP61]] to <4 x i32>
+// CHECK-NEXT: [[TMP63:%.*]] = icmp sgt <4 x i32> [[TMP60]], [[TMP62]]
+// CHECK-NEXT: [[TMP64:%.*]] = select <4 x i1> [[TMP63]], <4 x i32> [[TMP60]], <4 x i32> [[TMP62]]
+// CHECK-NEXT: [[TMP65:%.*]] = bitcast <4 x i32> [[TMP64]] to <2 x i64>
+// CHECK-NEXT: store <2 x i64> [[TMP65]], <2 x i64>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP66:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP67:%.*]] = bitcast <2 x i64> [[TMP66]] to <4 x i32>
+// CHECK-NEXT: [[TMP68:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP69:%.*]] = bitcast <2 x i64> [[TMP68]] to <4 x i32>
+// CHECK-NEXT: [[SHUFFLE10_I:%.*]] = shufflevector <4 x i32> [[TMP67]], <4 x i32> [[TMP69]], <4 x i32> <i32 1, i32 0, i32 3, i32 2>
+// CHECK-NEXT: [[TMP70:%.*]] = bitcast <4 x i32> [[SHUFFLE10_I]] to <2 x i64>
+// CHECK-NEXT: store <2 x i64> [[TMP70]], <2 x i64>* [[__T9_I]], align 16
+// CHECK-NEXT: [[TMP71:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP72:%.*]] = load <2 x i64>, <2 x i64>* [[__T9_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP71]], <2 x i64>* [[__V1_ADDR_I_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP72]], <2 x i64>* [[__V2_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP73:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP74:%.*]] = bitcast <2 x i64> [[TMP73]] to <4 x i32>
+// CHECK-NEXT: [[TMP75:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP76:%.*]] = bitcast <2 x i64> [[TMP75]] to <4 x i32>
+// CHECK-NEXT: [[TMP77:%.*]] = icmp sgt <4 x i32> [[TMP74]], [[TMP76]]
+// CHECK-NEXT: [[TMP78:%.*]] = select <4 x i1> [[TMP77]], <4 x i32> [[TMP74]], <4 x i32> [[TMP76]]
+// CHECK-NEXT: [[TMP79:%.*]] = bitcast <4 x i32> [[TMP78]] to <2 x i64>
+// CHECK-NEXT: store <4 x i32> [[TMP78]], <4 x i32>* [[__T10_I]], align 16
+// CHECK-NEXT: [[TMP80:%.*]] = load <4 x i32>, <4 x i32>* [[__T10_I]], align 16
+// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x i32> [[TMP80]], i32 0
+// CHECK-NEXT: ret i32 [[VECEXT_I]]
int test_mm512_mask_reduce_max_epi32(__mmask16 __M, __m512i __W){
return _mm512_mask_reduce_max_epi32(__M, __W);
}
// CHECK-LABEL: define i32 @test_mm512_mask_reduce_max_epu32(i16 zeroext %__M, <8 x i64> %__W) #0 {
-// CHECK: [[_COMPOUNDLITERAL_I_I18_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I19_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I20_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I15_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I16_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I17_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I12_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__S_ADDR_I_I:%.*]] = alloca i32, align 4
-// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <16 x i32>, align 64
-// CHECK: [[__M_ADDR_I:%.*]] = alloca i16, align 2
-// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__M_ADDR:%.*]] = alloca i16, align 2
-// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64
-// CHECK: store i16 %__M, i16* [[__M_ADDR]], align 2
-// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64
-// CHECK: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2
-// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64
-// CHECK: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2
-// CHECK: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP2:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2
-// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i64> [[TMP3]] to <16 x i32>
-// CHECK: store i32 0, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[TMP5:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT_I_I:%.*]] = insertelement <16 x i32> undef, i32 [[TMP5]], i32 0
-// CHECK: [[TMP6:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <16 x i32> [[VECINIT_I_I]], i32 [[TMP6]], i32 1
-// CHECK: [[TMP7:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <16 x i32> [[VECINIT1_I_I]], i32 [[TMP7]], i32 2
-// CHECK: [[TMP8:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <16 x i32> [[VECINIT2_I_I]], i32 [[TMP8]], i32 3
-// CHECK: [[TMP9:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <16 x i32> [[VECINIT3_I_I]], i32 [[TMP9]], i32 4
-// CHECK: [[TMP10:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <16 x i32> [[VECINIT4_I_I]], i32 [[TMP10]], i32 5
-// CHECK: [[TMP11:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <16 x i32> [[VECINIT5_I_I]], i32 [[TMP11]], i32 6
-// CHECK: [[TMP12:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <16 x i32> [[VECINIT6_I_I]], i32 [[TMP12]], i32 7
-// CHECK: [[TMP13:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT8_I_I:%.*]] = insertelement <16 x i32> [[VECINIT7_I_I]], i32 [[TMP13]], i32 8
-// CHECK: [[TMP14:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT9_I_I:%.*]] = insertelement <16 x i32> [[VECINIT8_I_I]], i32 [[TMP14]], i32 9
-// CHECK: [[TMP15:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT10_I_I:%.*]] = insertelement <16 x i32> [[VECINIT9_I_I]], i32 [[TMP15]], i32 10
-// CHECK: [[TMP16:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT11_I_I:%.*]] = insertelement <16 x i32> [[VECINIT10_I_I]], i32 [[TMP16]], i32 11
-// CHECK: [[TMP17:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT12_I_I:%.*]] = insertelement <16 x i32> [[VECINIT11_I_I]], i32 [[TMP17]], i32 12
-// CHECK: [[TMP18:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT13_I_I:%.*]] = insertelement <16 x i32> [[VECINIT12_I_I]], i32 [[TMP18]], i32 13
-// CHECK: [[TMP19:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT14_I_I:%.*]] = insertelement <16 x i32> [[VECINIT13_I_I]], i32 [[TMP19]], i32 14
-// CHECK: [[TMP20:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT15_I_I:%.*]] = insertelement <16 x i32> [[VECINIT14_I_I]], i32 [[TMP20]], i32 15
-// CHECK: store <16 x i32> [[VECINIT15_I_I]], <16 x i32>* [[_COMPOUNDLITERAL_I_I]], align 64
-// CHECK: [[TMP21:%.*]] = load <16 x i32>, <16 x i32>* [[_COMPOUNDLITERAL_I_I]], align 64
-// CHECK: [[TMP22:%.*]] = bitcast <16 x i32> [[TMP21]] to <8 x i64>
-// CHECK: [[TMP23:%.*]] = bitcast i16 [[TMP2]] to <16 x i1>
-// CHECK: [[TMP24:%.*]] = select <16 x i1> [[TMP23]], <16 x i32> [[TMP4]], <16 x i32> [[TMP21]]
-// CHECK: [[TMP25:%.*]] = bitcast <16 x i32> [[TMP24]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP25]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP27:%.*]] = bitcast <8 x i64> [[TMP26]] to <16 x i32>
-// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP29:%.*]] = bitcast <8 x i64> [[TMP28]] to <16 x i32>
-// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i32> [[TMP27]], <16 x i32> [[TMP29]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP30:%.*]] = bitcast <16 x i32> [[SHUFFLE_I]] to <8 x i64>
-// CHECK: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP32:%.*]] = bitcast <8 x i64> [[TMP31]] to <16 x i32>
-// CHECK: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP34:%.*]] = bitcast <8 x i64> [[TMP33]] to <16 x i32>
-// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x i32> [[TMP32]], <16 x i32> [[TMP34]], <16 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP35:%.*]] = bitcast <16 x i32> [[SHUFFLE1_I]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP30]], <8 x i64>* [[__A_ADDR_I19_I]], align 64
-// CHECK: store <8 x i64> [[TMP35]], <8 x i64>* [[__B_ADDR_I20_I]], align 64
-// CHECK: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I19_I]], align 64
-// CHECK: [[TMP37:%.*]] = bitcast <8 x i64> [[TMP36]] to <16 x i32>
-// CHECK: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I20_I]], align 64
-// CHECK: [[TMP39:%.*]] = bitcast <8 x i64> [[TMP38]] to <16 x i32>
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I18_I]], align 64
-// CHECK: [[TMP40:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I18_I]], align 64
-// CHECK: [[TMP41:%.*]] = bitcast <8 x i64> [[TMP40]] to <16 x i32>
-// CHECK: [[TMP42:%.*]] = icmp ugt <16 x i32> [[TMP37]], [[TMP39]]
-// CHECK: [[TMP43:%.*]] = select <16 x i1> [[TMP42]], <16 x i32> [[TMP37]], <16 x i32> [[TMP39]]
-// CHECK: [[TMP44:%.*]] = bitcast <16 x i32> [[TMP43]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP44]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP45:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP46:%.*]] = bitcast <8 x i64> [[TMP45]] to <16 x i32>
-// CHECK: [[TMP47:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP48:%.*]] = bitcast <8 x i64> [[TMP47]] to <16 x i32>
-// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x i32> [[TMP46]], <16 x i32> [[TMP48]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP49:%.*]] = bitcast <16 x i32> [[SHUFFLE3_I]] to <8 x i64>
-// CHECK: [[TMP50:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP51:%.*]] = bitcast <8 x i64> [[TMP50]] to <16 x i32>
-// CHECK: [[TMP52:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP53:%.*]] = bitcast <8 x i64> [[TMP52]] to <16 x i32>
-// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <16 x i32> [[TMP51]], <16 x i32> [[TMP53]], <16 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP54:%.*]] = bitcast <16 x i32> [[SHUFFLE4_I]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP49]], <8 x i64>* [[__A_ADDR_I16_I]], align 64
-// CHECK: store <8 x i64> [[TMP54]], <8 x i64>* [[__B_ADDR_I17_I]], align 64
-// CHECK: [[TMP55:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I16_I]], align 64
-// CHECK: [[TMP56:%.*]] = bitcast <8 x i64> [[TMP55]] to <16 x i32>
-// CHECK: [[TMP57:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I17_I]], align 64
-// CHECK: [[TMP58:%.*]] = bitcast <8 x i64> [[TMP57]] to <16 x i32>
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I15_I]], align 64
-// CHECK: [[TMP59:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I15_I]], align 64
-// CHECK: [[TMP60:%.*]] = bitcast <8 x i64> [[TMP59]] to <16 x i32>
-// CHECK: [[TMP61:%.*]] = icmp ugt <16 x i32> [[TMP56]], [[TMP58]]
-// CHECK: [[TMP62:%.*]] = select <16 x i1> [[TMP61]], <16 x i32> [[TMP56]], <16 x i32> [[TMP58]]
-// CHECK: [[TMP63:%.*]] = bitcast <16 x i32> [[TMP62]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP63]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP64:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP65:%.*]] = bitcast <8 x i64> [[TMP64]] to <16 x i32>
-// CHECK: [[TMP66:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP67:%.*]] = bitcast <8 x i64> [[TMP66]] to <16 x i32>
-// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x i32> [[TMP65]], <16 x i32> [[TMP67]], <16 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP68:%.*]] = bitcast <16 x i32> [[SHUFFLE6_I]] to <8 x i64>
-// CHECK: [[TMP69:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP70:%.*]] = bitcast <8 x i64> [[TMP69]] to <16 x i32>
-// CHECK: [[TMP71:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP72:%.*]] = bitcast <8 x i64> [[TMP71]] to <16 x i32>
-// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <16 x i32> [[TMP70]], <16 x i32> [[TMP72]], <16 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP73:%.*]] = bitcast <16 x i32> [[SHUFFLE7_I]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP68]], <8 x i64>* [[__A_ADDR_I13_I]], align 64
-// CHECK: store <8 x i64> [[TMP73]], <8 x i64>* [[__B_ADDR_I14_I]], align 64
-// CHECK: [[TMP74:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I13_I]], align 64
-// CHECK: [[TMP75:%.*]] = bitcast <8 x i64> [[TMP74]] to <16 x i32>
-// CHECK: [[TMP76:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I14_I]], align 64
-// CHECK: [[TMP77:%.*]] = bitcast <8 x i64> [[TMP76]] to <16 x i32>
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I12_I]], align 64
-// CHECK: [[TMP78:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I12_I]], align 64
-// CHECK: [[TMP79:%.*]] = bitcast <8 x i64> [[TMP78]] to <16 x i32>
-// CHECK: [[TMP80:%.*]] = icmp ugt <16 x i32> [[TMP75]], [[TMP77]]
-// CHECK: [[TMP81:%.*]] = select <16 x i1> [[TMP80]], <16 x i32> [[TMP75]], <16 x i32> [[TMP77]]
-// CHECK: [[TMP82:%.*]] = bitcast <16 x i32> [[TMP81]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP82]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP83:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP84:%.*]] = bitcast <8 x i64> [[TMP83]] to <16 x i32>
-// CHECK: [[TMP85:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP86:%.*]] = bitcast <8 x i64> [[TMP85]] to <16 x i32>
-// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x i32> [[TMP84]], <16 x i32> [[TMP86]], <16 x i32> <i32 0, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP87:%.*]] = bitcast <16 x i32> [[SHUFFLE9_I]] to <8 x i64>
-// CHECK: [[TMP88:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP89:%.*]] = bitcast <8 x i64> [[TMP88]] to <16 x i32>
-// CHECK: [[TMP90:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP91:%.*]] = bitcast <8 x i64> [[TMP90]] to <16 x i32>
-// CHECK: [[SHUFFLE10_I:%.*]] = shufflevector <16 x i32> [[TMP89]], <16 x i32> [[TMP91]], <16 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP92:%.*]] = bitcast <16 x i32> [[SHUFFLE10_I]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP87]], <8 x i64>* [[__A_ADDR_I_I]], align 64
-// CHECK: store <8 x i64> [[TMP92]], <8 x i64>* [[__B_ADDR_I_I]], align 64
-// CHECK: [[TMP93:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64
-// CHECK: [[TMP94:%.*]] = bitcast <8 x i64> [[TMP93]] to <16 x i32>
-// CHECK: [[TMP95:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64
-// CHECK: [[TMP96:%.*]] = bitcast <8 x i64> [[TMP95]] to <16 x i32>
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP97:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP98:%.*]] = bitcast <8 x i64> [[TMP97]] to <16 x i32>
-// CHECK: [[TMP99:%.*]] = icmp ugt <16 x i32> [[TMP94]], [[TMP96]]
-// CHECK: [[TMP100:%.*]] = select <16 x i1> [[TMP99]], <16 x i32> [[TMP94]], <16 x i32> [[TMP96]]
-// CHECK: [[TMP101:%.*]] = bitcast <16 x i32> [[TMP100]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP101]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP102:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP102]], i32 0
-// CHECK: [[CONV_I:%.*]] = trunc i64 [[VECEXT_I]] to i32
-// CHECK: ret i32 [[CONV_I]]
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[__A2_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__V1_ADDR_I13_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V2_ADDR_I14_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V1_ADDR_I11_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V2_ADDR_I12_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V1_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V2_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i16, align 2
+// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i16, align 2
+// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T9_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x i32>, align 16
+// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i16, align 2
+// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: store i16 [[__M:%.*]], i16* [[__M_ADDR]], align 2
+// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64
+// CHECK-NEXT: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2
+// CHECK-NEXT: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP2:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2
+// CHECK-NEXT: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: store i16 [[TMP2]], i16* [[__U_ADDR_I_I]], align 2
+// CHECK-NEXT: store <8 x i64> [[TMP3]], <8 x i64>* [[__A_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP4:%.*]] = load i16, i16* [[__U_ADDR_I_I]], align 2
+// CHECK-NEXT: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP6:%.*]] = bitcast <8 x i64> [[TMP5]] to <16 x i32>
+// CHECK-NEXT: store <8 x i64> zeroinitializer, <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I_I]], align 64
+// CHECK-NEXT: [[TMP7:%.*]] = load <8 x i64>, <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I_I]], align 64
+// CHECK-NEXT: [[TMP8:%.*]] = bitcast <8 x i64> [[TMP7]] to <16 x i32>
+// CHECK-NEXT: [[TMP9:%.*]] = bitcast i16 [[TMP4]] to <16 x i1>
+// CHECK-NEXT: [[TMP10:%.*]] = select <16 x i1> [[TMP9]], <16 x i32> [[TMP6]], <16 x i32> [[TMP8]]
+// CHECK-NEXT: [[TMP11:%.*]] = bitcast <16 x i32> [[TMP10]] to <8 x i64>
+// CHECK-NEXT: store <8 x i64> [[TMP11]], <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[EXTRACT_I:%.*]] = shufflevector <8 x i64> [[TMP12]], <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK-NEXT: store <4 x i64> [[EXTRACT_I]], <4 x i64>* [[__T1_I]], align 32
+// CHECK-NEXT: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[EXTRACT3_I:%.*]] = shufflevector <8 x i64> [[TMP13]], <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK-NEXT: store <4 x i64> [[EXTRACT3_I]], <4 x i64>* [[__T2_I]], align 32
+// CHECK-NEXT: [[TMP14:%.*]] = load <4 x i64>, <4 x i64>* [[__T1_I]], align 32
+// CHECK-NEXT: [[TMP15:%.*]] = load <4 x i64>, <4 x i64>* [[__T2_I]], align 32
+// CHECK-NEXT: store <4 x i64> [[TMP14]], <4 x i64>* [[__A2_ADDR_I_I]], align 32
+// CHECK-NEXT: store <4 x i64> [[TMP15]], <4 x i64>* [[__B_ADDR_I_I]], align 32
+// CHECK-NEXT: [[TMP16:%.*]] = load <4 x i64>, <4 x i64>* [[__A2_ADDR_I_I]], align 32
+// CHECK-NEXT: [[TMP17:%.*]] = bitcast <4 x i64> [[TMP16]] to <8 x i32>
+// CHECK-NEXT: [[TMP18:%.*]] = load <4 x i64>, <4 x i64>* [[__B_ADDR_I_I]], align 32
+// CHECK-NEXT: [[TMP19:%.*]] = bitcast <4 x i64> [[TMP18]] to <8 x i32>
+// CHECK-NEXT: [[TMP20:%.*]] = icmp ugt <8 x i32> [[TMP17]], [[TMP19]]
+// CHECK-NEXT: [[TMP21:%.*]] = select <8 x i1> [[TMP20]], <8 x i32> [[TMP17]], <8 x i32> [[TMP19]]
+// CHECK-NEXT: [[TMP22:%.*]] = bitcast <8 x i32> [[TMP21]] to <4 x i64>
+// CHECK-NEXT: store <4 x i64> [[TMP22]], <4 x i64>* [[__T3_I]], align 32
+// CHECK-NEXT: [[TMP23:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32
+// CHECK-NEXT: [[EXTRACT5_I:%.*]] = shufflevector <4 x i64> [[TMP23]], <4 x i64> undef, <2 x i32> <i32 0, i32 1>
+// CHECK-NEXT: store <2 x i64> [[EXTRACT5_I]], <2 x i64>* [[__T4_I]], align 16
+// CHECK-NEXT: [[TMP24:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32
+// CHECK-NEXT: [[EXTRACT6_I:%.*]] = shufflevector <4 x i64> [[TMP24]], <4 x i64> undef, <2 x i32> <i32 2, i32 3>
+// CHECK-NEXT: store <2 x i64> [[EXTRACT6_I]], <2 x i64>* [[__T5_I]], align 16
+// CHECK-NEXT: [[TMP25:%.*]] = load <2 x i64>, <2 x i64>* [[__T4_I]], align 16
+// CHECK-NEXT: [[TMP26:%.*]] = load <2 x i64>, <2 x i64>* [[__T5_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP25]], <2 x i64>* [[__V1_ADDR_I13_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP26]], <2 x i64>* [[__V2_ADDR_I14_I]], align 16
+// CHECK-NEXT: [[TMP27:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I13_I]], align 16
+// CHECK-NEXT: [[TMP28:%.*]] = bitcast <2 x i64> [[TMP27]] to <4 x i32>
+// CHECK-NEXT: [[TMP29:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I14_I]], align 16
+// CHECK-NEXT: [[TMP30:%.*]] = bitcast <2 x i64> [[TMP29]] to <4 x i32>
+// CHECK-NEXT: [[TMP31:%.*]] = icmp ugt <4 x i32> [[TMP28]], [[TMP30]]
+// CHECK-NEXT: [[TMP32:%.*]] = select <4 x i1> [[TMP31]], <4 x i32> [[TMP28]], <4 x i32> [[TMP30]]
+// CHECK-NEXT: [[TMP33:%.*]] = bitcast <4 x i32> [[TMP32]] to <2 x i64>
+// CHECK-NEXT: store <2 x i64> [[TMP33]], <2 x i64>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP34:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP35:%.*]] = bitcast <2 x i64> [[TMP34]] to <4 x i32>
+// CHECK-NEXT: [[TMP36:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP37:%.*]] = bitcast <2 x i64> [[TMP36]] to <4 x i32>
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> [[TMP35]], <4 x i32> [[TMP37]], <4 x i32> <i32 2, i32 3, i32 0, i32 1>
+// CHECK-NEXT: [[TMP38:%.*]] = bitcast <4 x i32> [[SHUFFLE_I]] to <2 x i64>
+// CHECK-NEXT: store <2 x i64> [[TMP38]], <2 x i64>* [[__T7_I]], align 16
+// CHECK-NEXT: [[TMP39:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP40:%.*]] = load <2 x i64>, <2 x i64>* [[__T7_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP39]], <2 x i64>* [[__V1_ADDR_I11_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP40]], <2 x i64>* [[__V2_ADDR_I12_I]], align 16
+// CHECK-NEXT: [[TMP41:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I11_I]], align 16
+// CHECK-NEXT: [[TMP42:%.*]] = bitcast <2 x i64> [[TMP41]] to <4 x i32>
+// CHECK-NEXT: [[TMP43:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I12_I]], align 16
+// CHECK-NEXT: [[TMP44:%.*]] = bitcast <2 x i64> [[TMP43]] to <4 x i32>
+// CHECK-NEXT: [[TMP45:%.*]] = icmp ugt <4 x i32> [[TMP42]], [[TMP44]]
+// CHECK-NEXT: [[TMP46:%.*]] = select <4 x i1> [[TMP45]], <4 x i32> [[TMP42]], <4 x i32> [[TMP44]]
+// CHECK-NEXT: [[TMP47:%.*]] = bitcast <4 x i32> [[TMP46]] to <2 x i64>
+// CHECK-NEXT: store <2 x i64> [[TMP47]], <2 x i64>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP48:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP49:%.*]] = bitcast <2 x i64> [[TMP48]] to <4 x i32>
+// CHECK-NEXT: [[TMP50:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP51:%.*]] = bitcast <2 x i64> [[TMP50]] to <4 x i32>
+// CHECK-NEXT: [[SHUFFLE9_I:%.*]] = shufflevector <4 x i32> [[TMP49]], <4 x i32> [[TMP51]], <4 x i32> <i32 1, i32 0, i32 3, i32 2>
+// CHECK-NEXT: [[TMP52:%.*]] = bitcast <4 x i32> [[SHUFFLE9_I]] to <2 x i64>
+// CHECK-NEXT: store <2 x i64> [[TMP52]], <2 x i64>* [[__T9_I]], align 16
+// CHECK-NEXT: [[TMP53:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP54:%.*]] = load <2 x i64>, <2 x i64>* [[__T9_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP53]], <2 x i64>* [[__V1_ADDR_I_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP54]], <2 x i64>* [[__V2_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP55:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP56:%.*]] = bitcast <2 x i64> [[TMP55]] to <4 x i32>
+// CHECK-NEXT: [[TMP57:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP58:%.*]] = bitcast <2 x i64> [[TMP57]] to <4 x i32>
+// CHECK-NEXT: [[TMP59:%.*]] = icmp ugt <4 x i32> [[TMP56]], [[TMP58]]
+// CHECK-NEXT: [[TMP60:%.*]] = select <4 x i1> [[TMP59]], <4 x i32> [[TMP56]], <4 x i32> [[TMP58]]
+// CHECK-NEXT: [[TMP61:%.*]] = bitcast <4 x i32> [[TMP60]] to <2 x i64>
+// CHECK-NEXT: store <4 x i32> [[TMP60]], <4 x i32>* [[__T10_I]], align 16
+// CHECK-NEXT: [[TMP62:%.*]] = load <4 x i32>, <4 x i32>* [[__T10_I]], align 16
+// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x i32> [[TMP62]], i32 0
+// CHECK-NEXT: ret i32 [[VECEXT_I]]
unsigned int test_mm512_mask_reduce_max_epu32(__mmask16 __M, __m512i __W){
return _mm512_mask_reduce_max_epu32(__M, __W);
}
// CHECK-LABEL: define float @test_mm512_mask_reduce_max_ps(i16 zeroext %__M, <16 x float> %__W) #0 {
-// CHECK: [[_COMPOUNDLITERAL_I_I18_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__A_ADDR_I19_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__B_ADDR_I20_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I15_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__A_ADDR_I16_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__B_ADDR_I17_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I12_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__W_ADDR_I_I:%.*]] = alloca float, align 4
-// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__M_ADDR_I:%.*]] = alloca i16, align 2
-// CHECK: [[__V_ADDR_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__M_ADDR:%.*]] = alloca i16, align 2
-// CHECK: [[__W_ADDR:%.*]] = alloca <16 x float>, align 64
-// CHECK: store i16 %__M, i16* [[__M_ADDR]], align 2
-// CHECK: store <16 x float> %__W, <16 x float>* [[__W_ADDR]], align 64
-// CHECK: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2
-// CHECK: [[TMP1:%.*]] = load <16 x float>, <16 x float>* [[__W_ADDR]], align 64
-// CHECK: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2
-// CHECK: store <16 x float> [[TMP1]], <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP2:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2
-// CHECK: [[TMP3:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: store float 0x7FF0000000000000, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[TMP4:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[VECINIT_I_I:%.*]] = insertelement <16 x float> undef, float [[TMP4]], i32 0
-// CHECK: [[TMP5:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <16 x float> [[VECINIT_I_I]], float [[TMP5]], i32 1
-// CHECK: [[TMP6:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <16 x float> [[VECINIT1_I_I]], float [[TMP6]], i32 2
-// CHECK: [[TMP7:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <16 x float> [[VECINIT2_I_I]], float [[TMP7]], i32 3
-// CHECK: [[TMP8:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <16 x float> [[VECINIT3_I_I]], float [[TMP8]], i32 4
-// CHECK: [[TMP9:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <16 x float> [[VECINIT4_I_I]], float [[TMP9]], i32 5
-// CHECK: [[TMP10:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <16 x float> [[VECINIT5_I_I]], float [[TMP10]], i32 6
-// CHECK: [[TMP11:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <16 x float> [[VECINIT6_I_I]], float [[TMP11]], i32 7
-// CHECK: [[TMP12:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[VECINIT8_I_I:%.*]] = insertelement <16 x float> [[VECINIT7_I_I]], float [[TMP12]], i32 8
-// CHECK: [[TMP13:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[VECINIT9_I_I:%.*]] = insertelement <16 x float> [[VECINIT8_I_I]], float [[TMP13]], i32 9
-// CHECK: [[TMP14:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[VECINIT10_I_I:%.*]] = insertelement <16 x float> [[VECINIT9_I_I]], float [[TMP14]], i32 10
-// CHECK: [[TMP15:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[VECINIT11_I_I:%.*]] = insertelement <16 x float> [[VECINIT10_I_I]], float [[TMP15]], i32 11
-// CHECK: [[TMP16:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[VECINIT12_I_I:%.*]] = insertelement <16 x float> [[VECINIT11_I_I]], float [[TMP16]], i32 12
-// CHECK: [[TMP17:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[VECINIT13_I_I:%.*]] = insertelement <16 x float> [[VECINIT12_I_I]], float [[TMP17]], i32 13
-// CHECK: [[TMP18:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[VECINIT14_I_I:%.*]] = insertelement <16 x float> [[VECINIT13_I_I]], float [[TMP18]], i32 14
-// CHECK: [[TMP19:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[VECINIT15_I_I:%.*]] = insertelement <16 x float> [[VECINIT14_I_I]], float [[TMP19]], i32 15
-// CHECK: store <16 x float> [[VECINIT15_I_I]], <16 x float>* [[_COMPOUNDLITERAL_I_I]], align 64
-// CHECK: [[TMP20:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I]], align 64
-// CHECK: [[SUB_I:%.*]] = fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, [[TMP20]]
-// CHECK: [[TMP21:%.*]] = bitcast i16 [[TMP2]] to <16 x i1>
-// CHECK: [[TMP22:%.*]] = select <16 x i1> [[TMP21]], <16 x float> [[TMP3]], <16 x float> [[SUB_I]]
-// CHECK: store <16 x float> [[TMP22]], <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP23:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP24:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x float> [[TMP23]], <16 x float> [[TMP24]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP25:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP26:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x float> [[TMP25]], <16 x float> [[TMP26]], <16 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <16 x float> [[SHUFFLE_I]], <16 x float>* [[__A_ADDR_I19_I]], align 64
-// CHECK: store <16 x float> [[SHUFFLE1_I]], <16 x float>* [[__B_ADDR_I20_I]], align 64
-// CHECK: [[TMP27:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I19_I]], align 64
-// CHECK: [[TMP28:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I20_I]], align 64
-// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I18_I]], align 64
-// CHECK: [[TMP29:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I18_I]], align 64
-// CHECK: [[TMP30:%.*]] = call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> [[TMP27]], <16 x float> [[TMP28]], <16 x float> [[TMP29]], i16 -1, i32 4) #2
-// CHECK: store <16 x float> [[TMP30]], <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP31:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP32:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x float> [[TMP31]], <16 x float> [[TMP32]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP33:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP34:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <16 x float> [[TMP33]], <16 x float> [[TMP34]], <16 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <16 x float> [[SHUFFLE3_I]], <16 x float>* [[__A_ADDR_I16_I]], align 64
-// CHECK: store <16 x float> [[SHUFFLE4_I]], <16 x float>* [[__B_ADDR_I17_I]], align 64
-// CHECK: [[TMP35:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I16_I]], align 64
-// CHECK: [[TMP36:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I17_I]], align 64
-// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I15_I]], align 64
-// CHECK: [[TMP37:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I15_I]], align 64
-// CHECK: [[TMP38:%.*]] = call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> [[TMP35]], <16 x float> [[TMP36]], <16 x float> [[TMP37]], i16 -1, i32 4) #2
-// CHECK: store <16 x float> [[TMP38]], <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP39:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP40:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x float> [[TMP39]], <16 x float> [[TMP40]], <16 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP41:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP42:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <16 x float> [[TMP41]], <16 x float> [[TMP42]], <16 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <16 x float> [[SHUFFLE6_I]], <16 x float>* [[__A_ADDR_I13_I]], align 64
-// CHECK: store <16 x float> [[SHUFFLE7_I]], <16 x float>* [[__B_ADDR_I14_I]], align 64
-// CHECK: [[TMP43:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I13_I]], align 64
-// CHECK: [[TMP44:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I14_I]], align 64
-// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I12_I]], align 64
-// CHECK: [[TMP45:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I12_I]], align 64
-// CHECK: [[TMP46:%.*]] = call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> [[TMP43]], <16 x float> [[TMP44]], <16 x float> [[TMP45]], i16 -1, i32 4) #2
-// CHECK: store <16 x float> [[TMP46]], <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP47:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP48:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x float> [[TMP47]], <16 x float> [[TMP48]], <16 x i32> <i32 0, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP49:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP50:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE10_I:%.*]] = shufflevector <16 x float> [[TMP49]], <16 x float> [[TMP50]], <16 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <16 x float> [[SHUFFLE9_I]], <16 x float>* [[__A_ADDR_I_I]], align 64
-// CHECK: store <16 x float> [[SHUFFLE10_I]], <16 x float>* [[__B_ADDR_I_I]], align 64
-// CHECK: [[TMP51:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I_I]], align 64
-// CHECK: [[TMP52:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I_I]], align 64
-// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP53:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP54:%.*]] = call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> [[TMP51]], <16 x float> [[TMP52]], <16 x float> [[TMP53]], i16 -1, i32 4) #2
-// CHECK: store <16 x float> [[TMP54]], <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP55:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[VECEXT_I:%.*]] = extractelement <16 x float> [[TMP55]], i32 0
-// CHECK: ret float [[VECEXT_I]]
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[__W2_ADDR_I_I:%.*]] = alloca <16 x float>, align 64
+// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i16, align 2
+// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <16 x float>, align 64
+// CHECK-NEXT: [[__A_ADDR_I16_I:%.*]] = alloca <8 x float>, align 32
+// CHECK-NEXT: [[__B_ADDR_I17_I:%.*]] = alloca <8 x float>, align 32
+// CHECK-NEXT: [[__A_ADDR_I14_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__B_ADDR_I15_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__A_ADDR_I12_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__B_ADDR_I13_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__A2_ADDR_I_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca float, align 4
+// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <16 x float>, align 64
+// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i16, align 2
+// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <16 x float>, align 64
+// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x float>, align 32
+// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x float>, align 32
+// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x float>, align 32
+// CHECK-NEXT: [[__T4_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__T5_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__T6_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__T7_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__T8_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__T9_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i16, align 2
+// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <16 x float>, align 64
+// CHECK-NEXT: store i16 [[__M:%.*]], i16* [[__M_ADDR]], align 2
+// CHECK-NEXT: store <16 x float> [[__W:%.*]], <16 x float>* [[__W_ADDR]], align 64
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load <16 x float>, <16 x float>* [[__W_ADDR]], align 64
+// CHECK-NEXT: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2
+// CHECK-NEXT: store <16 x float> [[TMP1]], <16 x float>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: store float 0xFFF0000000000000, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <16 x float> undef, float [[TMP2]], i32 0
+// CHECK-NEXT: [[TMP3:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <16 x float> [[VECINIT_I_I]], float [[TMP3]], i32 1
+// CHECK-NEXT: [[TMP4:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <16 x float> [[VECINIT1_I_I]], float [[TMP4]], i32 2
+// CHECK-NEXT: [[TMP5:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <16 x float> [[VECINIT2_I_I]], float [[TMP5]], i32 3
+// CHECK-NEXT: [[TMP6:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <16 x float> [[VECINIT3_I_I]], float [[TMP6]], i32 4
+// CHECK-NEXT: [[TMP7:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <16 x float> [[VECINIT4_I_I]], float [[TMP7]], i32 5
+// CHECK-NEXT: [[TMP8:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <16 x float> [[VECINIT5_I_I]], float [[TMP8]], i32 6
+// CHECK-NEXT: [[TMP9:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <16 x float> [[VECINIT6_I_I]], float [[TMP9]], i32 7
+// CHECK-NEXT: [[TMP10:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT8_I_I:%.*]] = insertelement <16 x float> [[VECINIT7_I_I]], float [[TMP10]], i32 8
+// CHECK-NEXT: [[TMP11:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT9_I_I:%.*]] = insertelement <16 x float> [[VECINIT8_I_I]], float [[TMP11]], i32 9
+// CHECK-NEXT: [[TMP12:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT10_I_I:%.*]] = insertelement <16 x float> [[VECINIT9_I_I]], float [[TMP12]], i32 10
+// CHECK-NEXT: [[TMP13:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT11_I_I:%.*]] = insertelement <16 x float> [[VECINIT10_I_I]], float [[TMP13]], i32 11
+// CHECK-NEXT: [[TMP14:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT12_I_I:%.*]] = insertelement <16 x float> [[VECINIT11_I_I]], float [[TMP14]], i32 12
+// CHECK-NEXT: [[TMP15:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT13_I_I:%.*]] = insertelement <16 x float> [[VECINIT12_I_I]], float [[TMP15]], i32 13
+// CHECK-NEXT: [[TMP16:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT14_I_I:%.*]] = insertelement <16 x float> [[VECINIT13_I_I]], float [[TMP16]], i32 14
+// CHECK-NEXT: [[TMP17:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT15_I_I:%.*]] = insertelement <16 x float> [[VECINIT14_I_I]], float [[TMP17]], i32 15
+// CHECK-NEXT: store <16 x float> [[VECINIT15_I_I]], <16 x float>* [[DOTCOMPOUNDLITERAL_I_I]], align 64
+// CHECK-NEXT: [[TMP18:%.*]] = load <16 x float>, <16 x float>* [[DOTCOMPOUNDLITERAL_I_I]], align 64
+// CHECK-NEXT: [[TMP19:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2
+// CHECK-NEXT: [[TMP20:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: store <16 x float> [[TMP18]], <16 x float>* [[__W2_ADDR_I_I]], align 64
+// CHECK-NEXT: store i16 [[TMP19]], i16* [[__U_ADDR_I_I]], align 2
+// CHECK-NEXT: store <16 x float> [[TMP20]], <16 x float>* [[__A_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP21:%.*]] = load i16, i16* [[__U_ADDR_I_I]], align 2
+// CHECK-NEXT: [[TMP22:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP23:%.*]] = load <16 x float>, <16 x float>* [[__W2_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP24:%.*]] = bitcast i16 [[TMP21]] to <16 x i1>
+// CHECK-NEXT: [[TMP25:%.*]] = select <16 x i1> [[TMP24]], <16 x float> [[TMP22]], <16 x float> [[TMP23]]
+// CHECK-NEXT: store <16 x float> [[TMP25]], <16 x float>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP26:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP27:%.*]] = bitcast <16 x float> [[TMP26]] to <8 x double>
+// CHECK-NEXT: [[EXTRACT_I:%.*]] = shufflevector <8 x double> [[TMP27]], <8 x double> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK-NEXT: [[TMP28:%.*]] = bitcast <4 x double> [[EXTRACT_I]] to <8 x float>
+// CHECK-NEXT: store <8 x float> [[TMP28]], <8 x float>* [[__T1_I]], align 32
+// CHECK-NEXT: [[TMP29:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP30:%.*]] = bitcast <16 x float> [[TMP29]] to <8 x double>
+// CHECK-NEXT: [[EXTRACT4_I:%.*]] = shufflevector <8 x double> [[TMP30]], <8 x double> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK-NEXT: [[TMP31:%.*]] = bitcast <4 x double> [[EXTRACT4_I]] to <8 x float>
+// CHECK-NEXT: store <8 x float> [[TMP31]], <8 x float>* [[__T2_I]], align 32
+// CHECK-NEXT: [[TMP32:%.*]] = load <8 x float>, <8 x float>* [[__T1_I]], align 32
+// CHECK-NEXT: [[TMP33:%.*]] = load <8 x float>, <8 x float>* [[__T2_I]], align 32
+// CHECK-NEXT: store <8 x float> [[TMP32]], <8 x float>* [[__A_ADDR_I16_I]], align 32
+// CHECK-NEXT: store <8 x float> [[TMP33]], <8 x float>* [[__B_ADDR_I17_I]], align 32
+// CHECK-NEXT: [[TMP34:%.*]] = load <8 x float>, <8 x float>* [[__A_ADDR_I16_I]], align 32
+// CHECK-NEXT: [[TMP35:%.*]] = load <8 x float>, <8 x float>* [[__B_ADDR_I17_I]], align 32
+// CHECK-NEXT: [[TMP36:%.*]] = call <8 x float> @llvm.x86.avx.max.ps.256(<8 x float> [[TMP34]], <8 x float> [[TMP35]]) #2
+// CHECK-NEXT: store <8 x float> [[TMP36]], <8 x float>* [[__T3_I]], align 32
+// CHECK-NEXT: [[TMP37:%.*]] = load <8 x float>, <8 x float>* [[__T3_I]], align 32
+// CHECK-NEXT: [[EXTRACT6_I:%.*]] = shufflevector <8 x float> [[TMP37]], <8 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK-NEXT: store <4 x float> [[EXTRACT6_I]], <4 x float>* [[__T4_I]], align 16
+// CHECK-NEXT: [[TMP38:%.*]] = load <8 x float>, <8 x float>* [[__T3_I]], align 32
+// CHECK-NEXT: [[EXTRACT7_I:%.*]] = shufflevector <8 x float> [[TMP38]], <8 x float> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK-NEXT: store <4 x float> [[EXTRACT7_I]], <4 x float>* [[__T5_I]], align 16
+// CHECK-NEXT: [[TMP39:%.*]] = load <4 x float>, <4 x float>* [[__T4_I]], align 16
+// CHECK-NEXT: [[TMP40:%.*]] = load <4 x float>, <4 x float>* [[__T5_I]], align 16
+// CHECK-NEXT: store <4 x float> [[TMP39]], <4 x float>* [[__A_ADDR_I14_I]], align 16
+// CHECK-NEXT: store <4 x float> [[TMP40]], <4 x float>* [[__B_ADDR_I15_I]], align 16
+// CHECK-NEXT: [[TMP41:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I14_I]], align 16
+// CHECK-NEXT: [[TMP42:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I15_I]], align 16
+// CHECK-NEXT: [[TMP43:%.*]] = call <4 x float> @llvm.x86.sse.max.ps(<4 x float> [[TMP41]], <4 x float> [[TMP42]]) #2
+// CHECK-NEXT: store <4 x float> [[TMP43]], <4 x float>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP44:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP45:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x float> [[TMP44]], <4 x float> [[TMP45]], <4 x i32> <i32 2, i32 3, i32 0, i32 1>
+// CHECK-NEXT: store <4 x float> [[SHUFFLE_I]], <4 x float>* [[__T7_I]], align 16
+// CHECK-NEXT: [[TMP46:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP47:%.*]] = load <4 x float>, <4 x float>* [[__T7_I]], align 16
+// CHECK-NEXT: store <4 x float> [[TMP46]], <4 x float>* [[__A_ADDR_I12_I]], align 16
+// CHECK-NEXT: store <4 x float> [[TMP47]], <4 x float>* [[__B_ADDR_I13_I]], align 16
+// CHECK-NEXT: [[TMP48:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I12_I]], align 16
+// CHECK-NEXT: [[TMP49:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I13_I]], align 16
+// CHECK-NEXT: [[TMP50:%.*]] = call <4 x float> @llvm.x86.sse.max.ps(<4 x float> [[TMP48]], <4 x float> [[TMP49]]) #2
+// CHECK-NEXT: store <4 x float> [[TMP50]], <4 x float>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP51:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP52:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16
+// CHECK-NEXT: [[SHUFFLE10_I:%.*]] = shufflevector <4 x float> [[TMP51]], <4 x float> [[TMP52]], <4 x i32> <i32 1, i32 0, i32 3, i32 2>
+// CHECK-NEXT: store <4 x float> [[SHUFFLE10_I]], <4 x float>* [[__T9_I]], align 16
+// CHECK-NEXT: [[TMP53:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP54:%.*]] = load <4 x float>, <4 x float>* [[__T9_I]], align 16
+// CHECK-NEXT: store <4 x float> [[TMP53]], <4 x float>* [[__A2_ADDR_I_I]], align 16
+// CHECK-NEXT: store <4 x float> [[TMP54]], <4 x float>* [[__B_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP55:%.*]] = load <4 x float>, <4 x float>* [[__A2_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP56:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP57:%.*]] = call <4 x float> @llvm.x86.sse.max.ps(<4 x float> [[TMP55]], <4 x float> [[TMP56]]) #2
+// CHECK-NEXT: store <4 x float> [[TMP57]], <4 x float>* [[__T10_I]], align 16
+// CHECK-NEXT: [[TMP58:%.*]] = load <4 x float>, <4 x float>* [[__T10_I]], align 16
+// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x float> [[TMP58]], i32 0
+// CHECK-NEXT: ret float [[VECEXT_I]]
float test_mm512_mask_reduce_max_ps(__mmask16 __M, __m512 __W){
return _mm512_mask_reduce_max_ps(__M, __W);
}
// CHECK-LABEL: define i32 @test_mm512_mask_reduce_min_epi32(i16 zeroext %__M, <8 x i64> %__W) #0 {
-// CHECK: [[_COMPOUNDLITERAL_I_I18_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I19_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I20_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I15_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I16_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I17_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I12_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__S_ADDR_I_I:%.*]] = alloca i32, align 4
-// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <16 x i32>, align 64
-// CHECK: [[__M_ADDR_I:%.*]] = alloca i16, align 2
-// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__M_ADDR:%.*]] = alloca i16, align 2
-// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64
-// CHECK: store i16 %__M, i16* [[__M_ADDR]], align 2
-// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64
-// CHECK: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2
-// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64
-// CHECK: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2
-// CHECK: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP2:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2
-// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i64> [[TMP3]] to <16 x i32>
-// CHECK: store i32 2147483647, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[TMP5:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT_I_I:%.*]] = insertelement <16 x i32> undef, i32 [[TMP5]], i32 0
-// CHECK: [[TMP6:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <16 x i32> [[VECINIT_I_I]], i32 [[TMP6]], i32 1
-// CHECK: [[TMP7:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <16 x i32> [[VECINIT1_I_I]], i32 [[TMP7]], i32 2
-// CHECK: [[TMP8:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <16 x i32> [[VECINIT2_I_I]], i32 [[TMP8]], i32 3
-// CHECK: [[TMP9:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <16 x i32> [[VECINIT3_I_I]], i32 [[TMP9]], i32 4
-// CHECK: [[TMP10:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <16 x i32> [[VECINIT4_I_I]], i32 [[TMP10]], i32 5
-// CHECK: [[TMP11:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <16 x i32> [[VECINIT5_I_I]], i32 [[TMP11]], i32 6
-// CHECK: [[TMP12:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <16 x i32> [[VECINIT6_I_I]], i32 [[TMP12]], i32 7
-// CHECK: [[TMP13:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT8_I_I:%.*]] = insertelement <16 x i32> [[VECINIT7_I_I]], i32 [[TMP13]], i32 8
-// CHECK: [[TMP14:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT9_I_I:%.*]] = insertelement <16 x i32> [[VECINIT8_I_I]], i32 [[TMP14]], i32 9
-// CHECK: [[TMP15:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT10_I_I:%.*]] = insertelement <16 x i32> [[VECINIT9_I_I]], i32 [[TMP15]], i32 10
-// CHECK: [[TMP16:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT11_I_I:%.*]] = insertelement <16 x i32> [[VECINIT10_I_I]], i32 [[TMP16]], i32 11
-// CHECK: [[TMP17:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT12_I_I:%.*]] = insertelement <16 x i32> [[VECINIT11_I_I]], i32 [[TMP17]], i32 12
-// CHECK: [[TMP18:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT13_I_I:%.*]] = insertelement <16 x i32> [[VECINIT12_I_I]], i32 [[TMP18]], i32 13
-// CHECK: [[TMP19:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT14_I_I:%.*]] = insertelement <16 x i32> [[VECINIT13_I_I]], i32 [[TMP19]], i32 14
-// CHECK: [[TMP20:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT15_I_I:%.*]] = insertelement <16 x i32> [[VECINIT14_I_I]], i32 [[TMP20]], i32 15
-// CHECK: store <16 x i32> [[VECINIT15_I_I]], <16 x i32>* [[_COMPOUNDLITERAL_I_I]], align 64
-// CHECK: [[TMP21:%.*]] = load <16 x i32>, <16 x i32>* [[_COMPOUNDLITERAL_I_I]], align 64
-// CHECK: [[TMP22:%.*]] = bitcast <16 x i32> [[TMP21]] to <8 x i64>
-// CHECK: [[TMP23:%.*]] = bitcast i16 [[TMP2]] to <16 x i1>
-// CHECK: [[TMP24:%.*]] = select <16 x i1> [[TMP23]], <16 x i32> [[TMP4]], <16 x i32> [[TMP21]]
-// CHECK: [[TMP25:%.*]] = bitcast <16 x i32> [[TMP24]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP25]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP27:%.*]] = bitcast <8 x i64> [[TMP26]] to <16 x i32>
-// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP29:%.*]] = bitcast <8 x i64> [[TMP28]] to <16 x i32>
-// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i32> [[TMP27]], <16 x i32> [[TMP29]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP30:%.*]] = bitcast <16 x i32> [[SHUFFLE_I]] to <8 x i64>
-// CHECK: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP32:%.*]] = bitcast <8 x i64> [[TMP31]] to <16 x i32>
-// CHECK: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP34:%.*]] = bitcast <8 x i64> [[TMP33]] to <16 x i32>
-// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x i32> [[TMP32]], <16 x i32> [[TMP34]], <16 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP35:%.*]] = bitcast <16 x i32> [[SHUFFLE1_I]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP30]], <8 x i64>* [[__A_ADDR_I19_I]], align 64
-// CHECK: store <8 x i64> [[TMP35]], <8 x i64>* [[__B_ADDR_I20_I]], align 64
-// CHECK: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I19_I]], align 64
-// CHECK: [[TMP37:%.*]] = bitcast <8 x i64> [[TMP36]] to <16 x i32>
-// CHECK: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I20_I]], align 64
-// CHECK: [[TMP39:%.*]] = bitcast <8 x i64> [[TMP38]] to <16 x i32>
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I18_I]], align 64
-// CHECK: [[TMP40:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I18_I]], align 64
-// CHECK: [[TMP41:%.*]] = bitcast <8 x i64> [[TMP40]] to <16 x i32>
-// CHECK: [[TMP42:%.*]] = icmp slt <16 x i32> [[TMP37]], [[TMP39]]
-// CHECK: [[TMP43:%.*]] = select <16 x i1> [[TMP42]], <16 x i32> [[TMP37]], <16 x i32> [[TMP39]]
-// CHECK: [[TMP44:%.*]] = bitcast <16 x i32> [[TMP43]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP44]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP45:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP46:%.*]] = bitcast <8 x i64> [[TMP45]] to <16 x i32>
-// CHECK: [[TMP47:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP48:%.*]] = bitcast <8 x i64> [[TMP47]] to <16 x i32>
-// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x i32> [[TMP46]], <16 x i32> [[TMP48]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP49:%.*]] = bitcast <16 x i32> [[SHUFFLE3_I]] to <8 x i64>
-// CHECK: [[TMP50:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP51:%.*]] = bitcast <8 x i64> [[TMP50]] to <16 x i32>
-// CHECK: [[TMP52:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP53:%.*]] = bitcast <8 x i64> [[TMP52]] to <16 x i32>
-// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <16 x i32> [[TMP51]], <16 x i32> [[TMP53]], <16 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP54:%.*]] = bitcast <16 x i32> [[SHUFFLE4_I]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP49]], <8 x i64>* [[__A_ADDR_I16_I]], align 64
-// CHECK: store <8 x i64> [[TMP54]], <8 x i64>* [[__B_ADDR_I17_I]], align 64
-// CHECK: [[TMP55:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I16_I]], align 64
-// CHECK: [[TMP56:%.*]] = bitcast <8 x i64> [[TMP55]] to <16 x i32>
-// CHECK: [[TMP57:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I17_I]], align 64
-// CHECK: [[TMP58:%.*]] = bitcast <8 x i64> [[TMP57]] to <16 x i32>
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I15_I]], align 64
-// CHECK: [[TMP59:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I15_I]], align 64
-// CHECK: [[TMP60:%.*]] = bitcast <8 x i64> [[TMP59]] to <16 x i32>
-// CHECK: [[TMP61:%.*]] = icmp slt <16 x i32> [[TMP56]], [[TMP58]]
-// CHECK: [[TMP62:%.*]] = select <16 x i1> [[TMP61]], <16 x i32> [[TMP56]], <16 x i32> [[TMP58]]
-// CHECK: [[TMP63:%.*]] = bitcast <16 x i32> [[TMP62]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP63]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP64:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP65:%.*]] = bitcast <8 x i64> [[TMP64]] to <16 x i32>
-// CHECK: [[TMP66:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP67:%.*]] = bitcast <8 x i64> [[TMP66]] to <16 x i32>
-// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x i32> [[TMP65]], <16 x i32> [[TMP67]], <16 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP68:%.*]] = bitcast <16 x i32> [[SHUFFLE6_I]] to <8 x i64>
-// CHECK: [[TMP69:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP70:%.*]] = bitcast <8 x i64> [[TMP69]] to <16 x i32>
-// CHECK: [[TMP71:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP72:%.*]] = bitcast <8 x i64> [[TMP71]] to <16 x i32>
-// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <16 x i32> [[TMP70]], <16 x i32> [[TMP72]], <16 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP73:%.*]] = bitcast <16 x i32> [[SHUFFLE7_I]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP68]], <8 x i64>* [[__A_ADDR_I13_I]], align 64
-// CHECK: store <8 x i64> [[TMP73]], <8 x i64>* [[__B_ADDR_I14_I]], align 64
-// CHECK: [[TMP74:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I13_I]], align 64
-// CHECK: [[TMP75:%.*]] = bitcast <8 x i64> [[TMP74]] to <16 x i32>
-// CHECK: [[TMP76:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I14_I]], align 64
-// CHECK: [[TMP77:%.*]] = bitcast <8 x i64> [[TMP76]] to <16 x i32>
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I12_I]], align 64
-// CHECK: [[TMP78:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I12_I]], align 64
-// CHECK: [[TMP79:%.*]] = bitcast <8 x i64> [[TMP78]] to <16 x i32>
-// CHECK: [[TMP80:%.*]] = icmp slt <16 x i32> [[TMP75]], [[TMP77]]
-// CHECK: [[TMP81:%.*]] = select <16 x i1> [[TMP80]], <16 x i32> [[TMP75]], <16 x i32> [[TMP77]]
-// CHECK: [[TMP82:%.*]] = bitcast <16 x i32> [[TMP81]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP82]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP83:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP84:%.*]] = bitcast <8 x i64> [[TMP83]] to <16 x i32>
-// CHECK: [[TMP85:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP86:%.*]] = bitcast <8 x i64> [[TMP85]] to <16 x i32>
-// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x i32> [[TMP84]], <16 x i32> [[TMP86]], <16 x i32> <i32 0, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP87:%.*]] = bitcast <16 x i32> [[SHUFFLE9_I]] to <8 x i64>
-// CHECK: [[TMP88:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP89:%.*]] = bitcast <8 x i64> [[TMP88]] to <16 x i32>
-// CHECK: [[TMP90:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP91:%.*]] = bitcast <8 x i64> [[TMP90]] to <16 x i32>
-// CHECK: [[SHUFFLE10_I:%.*]] = shufflevector <16 x i32> [[TMP89]], <16 x i32> [[TMP91]], <16 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP92:%.*]] = bitcast <16 x i32> [[SHUFFLE10_I]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP87]], <8 x i64>* [[__A_ADDR_I_I]], align 64
-// CHECK: store <8 x i64> [[TMP92]], <8 x i64>* [[__B_ADDR_I_I]], align 64
-// CHECK: [[TMP93:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64
-// CHECK: [[TMP94:%.*]] = bitcast <8 x i64> [[TMP93]] to <16 x i32>
-// CHECK: [[TMP95:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64
-// CHECK: [[TMP96:%.*]] = bitcast <8 x i64> [[TMP95]] to <16 x i32>
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP97:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP98:%.*]] = bitcast <8 x i64> [[TMP97]] to <16 x i32>
-// CHECK: [[TMP99:%.*]] = icmp slt <16 x i32> [[TMP94]], [[TMP96]]
-// CHECK: [[TMP100:%.*]] = select <16 x i1> [[TMP99]], <16 x i32> [[TMP94]], <16 x i32> [[TMP96]]
-// CHECK: [[TMP101:%.*]] = bitcast <16 x i32> [[TMP100]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP101]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP102:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP102]], i32 0
-// CHECK: [[CONV_I:%.*]] = trunc i64 [[VECEXT_I]] to i32
-// CHECK: ret i32 [[CONV_I]]
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i16, align 2
+// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__A2_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__V1_ADDR_I14_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V2_ADDR_I15_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V1_ADDR_I12_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V2_ADDR_I13_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V1_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V2_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__S_ADDR_I_I:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <16 x i32>, align 64
+// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i16, align 2
+// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T9_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x i32>, align 16
+// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i16, align 2
+// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: store i16 [[__M:%.*]], i16* [[__M_ADDR]], align 2
+// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64
+// CHECK-NEXT: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2
+// CHECK-NEXT: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: store i32 2147483647, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <16 x i32> undef, i32 [[TMP2]], i32 0
+// CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <16 x i32> [[VECINIT_I_I]], i32 [[TMP3]], i32 1
+// CHECK-NEXT: [[TMP4:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <16 x i32> [[VECINIT1_I_I]], i32 [[TMP4]], i32 2
+// CHECK-NEXT: [[TMP5:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <16 x i32> [[VECINIT2_I_I]], i32 [[TMP5]], i32 3
+// CHECK-NEXT: [[TMP6:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <16 x i32> [[VECINIT3_I_I]], i32 [[TMP6]], i32 4
+// CHECK-NEXT: [[TMP7:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <16 x i32> [[VECINIT4_I_I]], i32 [[TMP7]], i32 5
+// CHECK-NEXT: [[TMP8:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <16 x i32> [[VECINIT5_I_I]], i32 [[TMP8]], i32 6
+// CHECK-NEXT: [[TMP9:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <16 x i32> [[VECINIT6_I_I]], i32 [[TMP9]], i32 7
+// CHECK-NEXT: [[TMP10:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT8_I_I:%.*]] = insertelement <16 x i32> [[VECINIT7_I_I]], i32 [[TMP10]], i32 8
+// CHECK-NEXT: [[TMP11:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT9_I_I:%.*]] = insertelement <16 x i32> [[VECINIT8_I_I]], i32 [[TMP11]], i32 9
+// CHECK-NEXT: [[TMP12:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT10_I_I:%.*]] = insertelement <16 x i32> [[VECINIT9_I_I]], i32 [[TMP12]], i32 10
+// CHECK-NEXT: [[TMP13:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT11_I_I:%.*]] = insertelement <16 x i32> [[VECINIT10_I_I]], i32 [[TMP13]], i32 11
+// CHECK-NEXT: [[TMP14:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT12_I_I:%.*]] = insertelement <16 x i32> [[VECINIT11_I_I]], i32 [[TMP14]], i32 12
+// CHECK-NEXT: [[TMP15:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT13_I_I:%.*]] = insertelement <16 x i32> [[VECINIT12_I_I]], i32 [[TMP15]], i32 13
+// CHECK-NEXT: [[TMP16:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT14_I_I:%.*]] = insertelement <16 x i32> [[VECINIT13_I_I]], i32 [[TMP16]], i32 14
+// CHECK-NEXT: [[TMP17:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT15_I_I:%.*]] = insertelement <16 x i32> [[VECINIT14_I_I]], i32 [[TMP17]], i32 15
+// CHECK-NEXT: store <16 x i32> [[VECINIT15_I_I]], <16 x i32>* [[DOTCOMPOUNDLITERAL_I_I]], align 64
+// CHECK-NEXT: [[TMP18:%.*]] = load <16 x i32>, <16 x i32>* [[DOTCOMPOUNDLITERAL_I_I]], align 64
+// CHECK-NEXT: [[TMP19:%.*]] = bitcast <16 x i32> [[TMP18]] to <8 x i64>
+// CHECK-NEXT: [[TMP20:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2
+// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP19]], <8 x i64>* [[__W_ADDR_I_I]], align 64
+// CHECK-NEXT: store i16 [[TMP20]], i16* [[__U_ADDR_I_I]], align 2
+// CHECK-NEXT: store <8 x i64> [[TMP21]], <8 x i64>* [[__A_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP22:%.*]] = load i16, i16* [[__U_ADDR_I_I]], align 2
+// CHECK-NEXT: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP24:%.*]] = bitcast <8 x i64> [[TMP23]] to <16 x i32>
+// CHECK-NEXT: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP26:%.*]] = bitcast <8 x i64> [[TMP25]] to <16 x i32>
+// CHECK-NEXT: [[TMP27:%.*]] = bitcast i16 [[TMP22]] to <16 x i1>
+// CHECK-NEXT: [[TMP28:%.*]] = select <16 x i1> [[TMP27]], <16 x i32> [[TMP24]], <16 x i32> [[TMP26]]
+// CHECK-NEXT: [[TMP29:%.*]] = bitcast <16 x i32> [[TMP28]] to <8 x i64>
+// CHECK-NEXT: store <8 x i64> [[TMP29]], <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[EXTRACT_I:%.*]] = shufflevector <8 x i64> [[TMP30]], <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK-NEXT: store <4 x i64> [[EXTRACT_I]], <4 x i64>* [[__T1_I]], align 32
+// CHECK-NEXT: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[EXTRACT4_I:%.*]] = shufflevector <8 x i64> [[TMP31]], <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK-NEXT: store <4 x i64> [[EXTRACT4_I]], <4 x i64>* [[__T2_I]], align 32
+// CHECK-NEXT: [[TMP32:%.*]] = load <4 x i64>, <4 x i64>* [[__T1_I]], align 32
+// CHECK-NEXT: [[TMP33:%.*]] = load <4 x i64>, <4 x i64>* [[__T2_I]], align 32
+// CHECK-NEXT: store <4 x i64> [[TMP32]], <4 x i64>* [[__A2_ADDR_I_I]], align 32
+// CHECK-NEXT: store <4 x i64> [[TMP33]], <4 x i64>* [[__B_ADDR_I_I]], align 32
+// CHECK-NEXT: [[TMP34:%.*]] = load <4 x i64>, <4 x i64>* [[__A2_ADDR_I_I]], align 32
+// CHECK-NEXT: [[TMP35:%.*]] = bitcast <4 x i64> [[TMP34]] to <8 x i32>
+// CHECK-NEXT: [[TMP36:%.*]] = load <4 x i64>, <4 x i64>* [[__B_ADDR_I_I]], align 32
+// CHECK-NEXT: [[TMP37:%.*]] = bitcast <4 x i64> [[TMP36]] to <8 x i32>
+// CHECK-NEXT: [[TMP38:%.*]] = icmp slt <8 x i32> [[TMP35]], [[TMP37]]
+// CHECK-NEXT: [[TMP39:%.*]] = select <8 x i1> [[TMP38]], <8 x i32> [[TMP35]], <8 x i32> [[TMP37]]
+// CHECK-NEXT: [[TMP40:%.*]] = bitcast <8 x i32> [[TMP39]] to <4 x i64>
+// CHECK-NEXT: store <4 x i64> [[TMP40]], <4 x i64>* [[__T3_I]], align 32
+// CHECK-NEXT: [[TMP41:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32
+// CHECK-NEXT: [[EXTRACT6_I:%.*]] = shufflevector <4 x i64> [[TMP41]], <4 x i64> undef, <2 x i32> <i32 0, i32 1>
+// CHECK-NEXT: store <2 x i64> [[EXTRACT6_I]], <2 x i64>* [[__T4_I]], align 16
+// CHECK-NEXT: [[TMP42:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32
+// CHECK-NEXT: [[EXTRACT7_I:%.*]] = shufflevector <4 x i64> [[TMP42]], <4 x i64> undef, <2 x i32> <i32 2, i32 3>
+// CHECK-NEXT: store <2 x i64> [[EXTRACT7_I]], <2 x i64>* [[__T5_I]], align 16
+// CHECK-NEXT: [[TMP43:%.*]] = load <2 x i64>, <2 x i64>* [[__T4_I]], align 16
+// CHECK-NEXT: [[TMP44:%.*]] = load <2 x i64>, <2 x i64>* [[__T5_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP43]], <2 x i64>* [[__V1_ADDR_I14_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP44]], <2 x i64>* [[__V2_ADDR_I15_I]], align 16
+// CHECK-NEXT: [[TMP45:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I14_I]], align 16
+// CHECK-NEXT: [[TMP46:%.*]] = bitcast <2 x i64> [[TMP45]] to <4 x i32>
+// CHECK-NEXT: [[TMP47:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I15_I]], align 16
+// CHECK-NEXT: [[TMP48:%.*]] = bitcast <2 x i64> [[TMP47]] to <4 x i32>
+// CHECK-NEXT: [[TMP49:%.*]] = icmp slt <4 x i32> [[TMP46]], [[TMP48]]
+// CHECK-NEXT: [[TMP50:%.*]] = select <4 x i1> [[TMP49]], <4 x i32> [[TMP46]], <4 x i32> [[TMP48]]
+// CHECK-NEXT: [[TMP51:%.*]] = bitcast <4 x i32> [[TMP50]] to <2 x i64>
+// CHECK-NEXT: store <2 x i64> [[TMP51]], <2 x i64>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP52:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP53:%.*]] = bitcast <2 x i64> [[TMP52]] to <4 x i32>
+// CHECK-NEXT: [[TMP54:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP55:%.*]] = bitcast <2 x i64> [[TMP54]] to <4 x i32>
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> [[TMP53]], <4 x i32> [[TMP55]], <4 x i32> <i32 2, i32 3, i32 0, i32 1>
+// CHECK-NEXT: [[TMP56:%.*]] = bitcast <4 x i32> [[SHUFFLE_I]] to <2 x i64>
+// CHECK-NEXT: store <2 x i64> [[TMP56]], <2 x i64>* [[__T7_I]], align 16
+// CHECK-NEXT: [[TMP57:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP58:%.*]] = load <2 x i64>, <2 x i64>* [[__T7_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP57]], <2 x i64>* [[__V1_ADDR_I12_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP58]], <2 x i64>* [[__V2_ADDR_I13_I]], align 16
+// CHECK-NEXT: [[TMP59:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I12_I]], align 16
+// CHECK-NEXT: [[TMP60:%.*]] = bitcast <2 x i64> [[TMP59]] to <4 x i32>
+// CHECK-NEXT: [[TMP61:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I13_I]], align 16
+// CHECK-NEXT: [[TMP62:%.*]] = bitcast <2 x i64> [[TMP61]] to <4 x i32>
+// CHECK-NEXT: [[TMP63:%.*]] = icmp slt <4 x i32> [[TMP60]], [[TMP62]]
+// CHECK-NEXT: [[TMP64:%.*]] = select <4 x i1> [[TMP63]], <4 x i32> [[TMP60]], <4 x i32> [[TMP62]]
+// CHECK-NEXT: [[TMP65:%.*]] = bitcast <4 x i32> [[TMP64]] to <2 x i64>
+// CHECK-NEXT: store <2 x i64> [[TMP65]], <2 x i64>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP66:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP67:%.*]] = bitcast <2 x i64> [[TMP66]] to <4 x i32>
+// CHECK-NEXT: [[TMP68:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP69:%.*]] = bitcast <2 x i64> [[TMP68]] to <4 x i32>
+// CHECK-NEXT: [[SHUFFLE10_I:%.*]] = shufflevector <4 x i32> [[TMP67]], <4 x i32> [[TMP69]], <4 x i32> <i32 1, i32 0, i32 3, i32 2>
+// CHECK-NEXT: [[TMP70:%.*]] = bitcast <4 x i32> [[SHUFFLE10_I]] to <2 x i64>
+// CHECK-NEXT: store <2 x i64> [[TMP70]], <2 x i64>* [[__T9_I]], align 16
+// CHECK-NEXT: [[TMP71:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP72:%.*]] = load <2 x i64>, <2 x i64>* [[__T9_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP71]], <2 x i64>* [[__V1_ADDR_I_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP72]], <2 x i64>* [[__V2_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP73:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP74:%.*]] = bitcast <2 x i64> [[TMP73]] to <4 x i32>
+// CHECK-NEXT: [[TMP75:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP76:%.*]] = bitcast <2 x i64> [[TMP75]] to <4 x i32>
+// CHECK-NEXT: [[TMP77:%.*]] = icmp slt <4 x i32> [[TMP74]], [[TMP76]]
+// CHECK-NEXT: [[TMP78:%.*]] = select <4 x i1> [[TMP77]], <4 x i32> [[TMP74]], <4 x i32> [[TMP76]]
+// CHECK-NEXT: [[TMP79:%.*]] = bitcast <4 x i32> [[TMP78]] to <2 x i64>
+// CHECK-NEXT: store <4 x i32> [[TMP78]], <4 x i32>* [[__T10_I]], align 16
+// CHECK-NEXT: [[TMP80:%.*]] = load <4 x i32>, <4 x i32>* [[__T10_I]], align 16
+// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x i32> [[TMP80]], i32 0
+// CHECK-NEXT: ret i32 [[VECEXT_I]]
int test_mm512_mask_reduce_min_epi32(__mmask16 __M, __m512i __W){
return _mm512_mask_reduce_min_epi32(__M, __W);
}
// CHECK-LABEL: define i32 @test_mm512_mask_reduce_min_epu32(i16 zeroext %__M, <8 x i64> %__W) #0 {
-// CHECK: [[_COMPOUNDLITERAL_I_I18_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I19_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I20_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I15_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I16_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I17_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I12_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__S_ADDR_I_I:%.*]] = alloca i32, align 4
-// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <16 x i32>, align 64
-// CHECK: [[__M_ADDR_I:%.*]] = alloca i16, align 2
-// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64
-// CHECK: [[__M_ADDR:%.*]] = alloca i16, align 2
-// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64
-// CHECK: store i16 %__M, i16* [[__M_ADDR]], align 2
-// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64
-// CHECK: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2
-// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64
-// CHECK: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2
-// CHECK: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP2:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2
-// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i64> [[TMP3]] to <16 x i32>
-// CHECK: store i32 -1, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[TMP5:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT_I_I:%.*]] = insertelement <16 x i32> undef, i32 [[TMP5]], i32 0
-// CHECK: [[TMP6:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <16 x i32> [[VECINIT_I_I]], i32 [[TMP6]], i32 1
-// CHECK: [[TMP7:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <16 x i32> [[VECINIT1_I_I]], i32 [[TMP7]], i32 2
-// CHECK: [[TMP8:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <16 x i32> [[VECINIT2_I_I]], i32 [[TMP8]], i32 3
-// CHECK: [[TMP9:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <16 x i32> [[VECINIT3_I_I]], i32 [[TMP9]], i32 4
-// CHECK: [[TMP10:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <16 x i32> [[VECINIT4_I_I]], i32 [[TMP10]], i32 5
-// CHECK: [[TMP11:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <16 x i32> [[VECINIT5_I_I]], i32 [[TMP11]], i32 6
-// CHECK: [[TMP12:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <16 x i32> [[VECINIT6_I_I]], i32 [[TMP12]], i32 7
-// CHECK: [[TMP13:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT8_I_I:%.*]] = insertelement <16 x i32> [[VECINIT7_I_I]], i32 [[TMP13]], i32 8
-// CHECK: [[TMP14:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT9_I_I:%.*]] = insertelement <16 x i32> [[VECINIT8_I_I]], i32 [[TMP14]], i32 9
-// CHECK: [[TMP15:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT10_I_I:%.*]] = insertelement <16 x i32> [[VECINIT9_I_I]], i32 [[TMP15]], i32 10
-// CHECK: [[TMP16:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT11_I_I:%.*]] = insertelement <16 x i32> [[VECINIT10_I_I]], i32 [[TMP16]], i32 11
-// CHECK: [[TMP17:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT12_I_I:%.*]] = insertelement <16 x i32> [[VECINIT11_I_I]], i32 [[TMP17]], i32 12
-// CHECK: [[TMP18:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT13_I_I:%.*]] = insertelement <16 x i32> [[VECINIT12_I_I]], i32 [[TMP18]], i32 13
-// CHECK: [[TMP19:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT14_I_I:%.*]] = insertelement <16 x i32> [[VECINIT13_I_I]], i32 [[TMP19]], i32 14
-// CHECK: [[TMP20:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
-// CHECK: [[VECINIT15_I_I:%.*]] = insertelement <16 x i32> [[VECINIT14_I_I]], i32 [[TMP20]], i32 15
-// CHECK: store <16 x i32> [[VECINIT15_I_I]], <16 x i32>* [[_COMPOUNDLITERAL_I_I]], align 64
-// CHECK: [[TMP21:%.*]] = load <16 x i32>, <16 x i32>* [[_COMPOUNDLITERAL_I_I]], align 64
-// CHECK: [[TMP22:%.*]] = bitcast <16 x i32> [[TMP21]] to <8 x i64>
-// CHECK: [[TMP23:%.*]] = bitcast i16 [[TMP2]] to <16 x i1>
-// CHECK: [[TMP24:%.*]] = select <16 x i1> [[TMP23]], <16 x i32> [[TMP4]], <16 x i32> [[TMP21]]
-// CHECK: [[TMP25:%.*]] = bitcast <16 x i32> [[TMP24]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP25]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP27:%.*]] = bitcast <8 x i64> [[TMP26]] to <16 x i32>
-// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP29:%.*]] = bitcast <8 x i64> [[TMP28]] to <16 x i32>
-// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i32> [[TMP27]], <16 x i32> [[TMP29]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP30:%.*]] = bitcast <16 x i32> [[SHUFFLE_I]] to <8 x i64>
-// CHECK: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP32:%.*]] = bitcast <8 x i64> [[TMP31]] to <16 x i32>
-// CHECK: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP34:%.*]] = bitcast <8 x i64> [[TMP33]] to <16 x i32>
-// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x i32> [[TMP32]], <16 x i32> [[TMP34]], <16 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP35:%.*]] = bitcast <16 x i32> [[SHUFFLE1_I]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP30]], <8 x i64>* [[__A_ADDR_I19_I]], align 64
-// CHECK: store <8 x i64> [[TMP35]], <8 x i64>* [[__B_ADDR_I20_I]], align 64
-// CHECK: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I19_I]], align 64
-// CHECK: [[TMP37:%.*]] = bitcast <8 x i64> [[TMP36]] to <16 x i32>
-// CHECK: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I20_I]], align 64
-// CHECK: [[TMP39:%.*]] = bitcast <8 x i64> [[TMP38]] to <16 x i32>
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I18_I]], align 64
-// CHECK: [[TMP40:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I18_I]], align 64
-// CHECK: [[TMP41:%.*]] = bitcast <8 x i64> [[TMP40]] to <16 x i32>
-// CHECK: [[TMP42:%.*]] = icmp ult <16 x i32> [[TMP37]], [[TMP39]]
-// CHECK: [[TMP43:%.*]] = select <16 x i1> [[TMP42]], <16 x i32> [[TMP37]], <16 x i32> [[TMP39]]
-// CHECK: [[TMP44:%.*]] = bitcast <16 x i32> [[TMP43]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP44]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP45:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP46:%.*]] = bitcast <8 x i64> [[TMP45]] to <16 x i32>
-// CHECK: [[TMP47:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP48:%.*]] = bitcast <8 x i64> [[TMP47]] to <16 x i32>
-// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x i32> [[TMP46]], <16 x i32> [[TMP48]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP49:%.*]] = bitcast <16 x i32> [[SHUFFLE3_I]] to <8 x i64>
-// CHECK: [[TMP50:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP51:%.*]] = bitcast <8 x i64> [[TMP50]] to <16 x i32>
-// CHECK: [[TMP52:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP53:%.*]] = bitcast <8 x i64> [[TMP52]] to <16 x i32>
-// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <16 x i32> [[TMP51]], <16 x i32> [[TMP53]], <16 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP54:%.*]] = bitcast <16 x i32> [[SHUFFLE4_I]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP49]], <8 x i64>* [[__A_ADDR_I16_I]], align 64
-// CHECK: store <8 x i64> [[TMP54]], <8 x i64>* [[__B_ADDR_I17_I]], align 64
-// CHECK: [[TMP55:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I16_I]], align 64
-// CHECK: [[TMP56:%.*]] = bitcast <8 x i64> [[TMP55]] to <16 x i32>
-// CHECK: [[TMP57:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I17_I]], align 64
-// CHECK: [[TMP58:%.*]] = bitcast <8 x i64> [[TMP57]] to <16 x i32>
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I15_I]], align 64
-// CHECK: [[TMP59:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I15_I]], align 64
-// CHECK: [[TMP60:%.*]] = bitcast <8 x i64> [[TMP59]] to <16 x i32>
-// CHECK: [[TMP61:%.*]] = icmp ult <16 x i32> [[TMP56]], [[TMP58]]
-// CHECK: [[TMP62:%.*]] = select <16 x i1> [[TMP61]], <16 x i32> [[TMP56]], <16 x i32> [[TMP58]]
-// CHECK: [[TMP63:%.*]] = bitcast <16 x i32> [[TMP62]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP63]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP64:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP65:%.*]] = bitcast <8 x i64> [[TMP64]] to <16 x i32>
-// CHECK: [[TMP66:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP67:%.*]] = bitcast <8 x i64> [[TMP66]] to <16 x i32>
-// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x i32> [[TMP65]], <16 x i32> [[TMP67]], <16 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP68:%.*]] = bitcast <16 x i32> [[SHUFFLE6_I]] to <8 x i64>
-// CHECK: [[TMP69:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP70:%.*]] = bitcast <8 x i64> [[TMP69]] to <16 x i32>
-// CHECK: [[TMP71:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP72:%.*]] = bitcast <8 x i64> [[TMP71]] to <16 x i32>
-// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <16 x i32> [[TMP70]], <16 x i32> [[TMP72]], <16 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP73:%.*]] = bitcast <16 x i32> [[SHUFFLE7_I]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP68]], <8 x i64>* [[__A_ADDR_I13_I]], align 64
-// CHECK: store <8 x i64> [[TMP73]], <8 x i64>* [[__B_ADDR_I14_I]], align 64
-// CHECK: [[TMP74:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I13_I]], align 64
-// CHECK: [[TMP75:%.*]] = bitcast <8 x i64> [[TMP74]] to <16 x i32>
-// CHECK: [[TMP76:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I14_I]], align 64
-// CHECK: [[TMP77:%.*]] = bitcast <8 x i64> [[TMP76]] to <16 x i32>
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I12_I]], align 64
-// CHECK: [[TMP78:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I12_I]], align 64
-// CHECK: [[TMP79:%.*]] = bitcast <8 x i64> [[TMP78]] to <16 x i32>
-// CHECK: [[TMP80:%.*]] = icmp ult <16 x i32> [[TMP75]], [[TMP77]]
-// CHECK: [[TMP81:%.*]] = select <16 x i1> [[TMP80]], <16 x i32> [[TMP75]], <16 x i32> [[TMP77]]
-// CHECK: [[TMP82:%.*]] = bitcast <16 x i32> [[TMP81]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP82]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP83:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP84:%.*]] = bitcast <8 x i64> [[TMP83]] to <16 x i32>
-// CHECK: [[TMP85:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP86:%.*]] = bitcast <8 x i64> [[TMP85]] to <16 x i32>
-// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x i32> [[TMP84]], <16 x i32> [[TMP86]], <16 x i32> <i32 0, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP87:%.*]] = bitcast <16 x i32> [[SHUFFLE9_I]] to <8 x i64>
-// CHECK: [[TMP88:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP89:%.*]] = bitcast <8 x i64> [[TMP88]] to <16 x i32>
-// CHECK: [[TMP90:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP91:%.*]] = bitcast <8 x i64> [[TMP90]] to <16 x i32>
-// CHECK: [[SHUFFLE10_I:%.*]] = shufflevector <16 x i32> [[TMP89]], <16 x i32> [[TMP91]], <16 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP92:%.*]] = bitcast <16 x i32> [[SHUFFLE10_I]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP87]], <8 x i64>* [[__A_ADDR_I_I]], align 64
-// CHECK: store <8 x i64> [[TMP92]], <8 x i64>* [[__B_ADDR_I_I]], align 64
-// CHECK: [[TMP93:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64
-// CHECK: [[TMP94:%.*]] = bitcast <8 x i64> [[TMP93]] to <16 x i32>
-// CHECK: [[TMP95:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64
-// CHECK: [[TMP96:%.*]] = bitcast <8 x i64> [[TMP95]] to <16 x i32>
-// CHECK: store <8 x i64> zeroinitializer, <8 x i64>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP97:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP98:%.*]] = bitcast <8 x i64> [[TMP97]] to <16 x i32>
-// CHECK: [[TMP99:%.*]] = icmp ult <16 x i32> [[TMP94]], [[TMP96]]
-// CHECK: [[TMP100:%.*]] = select <16 x i1> [[TMP99]], <16 x i32> [[TMP94]], <16 x i32> [[TMP96]]
-// CHECK: [[TMP101:%.*]] = bitcast <16 x i32> [[TMP100]] to <8 x i64>
-// CHECK: store <8 x i64> [[TMP101]], <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP102:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
-// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP102]], i32 0
-// CHECK: [[CONV_I:%.*]] = trunc i64 [[VECEXT_I]] to i32
-// CHECK: ret i32 [[CONV_I]]
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i16, align 2
+// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__A2_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__V1_ADDR_I14_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V2_ADDR_I15_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V1_ADDR_I12_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V2_ADDR_I13_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V1_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__V2_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__S_ADDR_I_I:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <16 x i32>, align 64
+// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i16, align 2
+// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x i64>, align 32
+// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T9_I:%.*]] = alloca <2 x i64>, align 16
+// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x i32>, align 16
+// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i16, align 2
+// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64
+// CHECK-NEXT: store i16 [[__M:%.*]], i16* [[__M_ADDR]], align 2
+// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64
+// CHECK-NEXT: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2
+// CHECK-NEXT: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: store i32 -1, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <16 x i32> undef, i32 [[TMP2]], i32 0
+// CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <16 x i32> [[VECINIT_I_I]], i32 [[TMP3]], i32 1
+// CHECK-NEXT: [[TMP4:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <16 x i32> [[VECINIT1_I_I]], i32 [[TMP4]], i32 2
+// CHECK-NEXT: [[TMP5:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <16 x i32> [[VECINIT2_I_I]], i32 [[TMP5]], i32 3
+// CHECK-NEXT: [[TMP6:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <16 x i32> [[VECINIT3_I_I]], i32 [[TMP6]], i32 4
+// CHECK-NEXT: [[TMP7:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <16 x i32> [[VECINIT4_I_I]], i32 [[TMP7]], i32 5
+// CHECK-NEXT: [[TMP8:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <16 x i32> [[VECINIT5_I_I]], i32 [[TMP8]], i32 6
+// CHECK-NEXT: [[TMP9:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <16 x i32> [[VECINIT6_I_I]], i32 [[TMP9]], i32 7
+// CHECK-NEXT: [[TMP10:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT8_I_I:%.*]] = insertelement <16 x i32> [[VECINIT7_I_I]], i32 [[TMP10]], i32 8
+// CHECK-NEXT: [[TMP11:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT9_I_I:%.*]] = insertelement <16 x i32> [[VECINIT8_I_I]], i32 [[TMP11]], i32 9
+// CHECK-NEXT: [[TMP12:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT10_I_I:%.*]] = insertelement <16 x i32> [[VECINIT9_I_I]], i32 [[TMP12]], i32 10
+// CHECK-NEXT: [[TMP13:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT11_I_I:%.*]] = insertelement <16 x i32> [[VECINIT10_I_I]], i32 [[TMP13]], i32 11
+// CHECK-NEXT: [[TMP14:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT12_I_I:%.*]] = insertelement <16 x i32> [[VECINIT11_I_I]], i32 [[TMP14]], i32 12
+// CHECK-NEXT: [[TMP15:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT13_I_I:%.*]] = insertelement <16 x i32> [[VECINIT12_I_I]], i32 [[TMP15]], i32 13
+// CHECK-NEXT: [[TMP16:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT14_I_I:%.*]] = insertelement <16 x i32> [[VECINIT13_I_I]], i32 [[TMP16]], i32 14
+// CHECK-NEXT: [[TMP17:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT15_I_I:%.*]] = insertelement <16 x i32> [[VECINIT14_I_I]], i32 [[TMP17]], i32 15
+// CHECK-NEXT: store <16 x i32> [[VECINIT15_I_I]], <16 x i32>* [[DOTCOMPOUNDLITERAL_I_I]], align 64
+// CHECK-NEXT: [[TMP18:%.*]] = load <16 x i32>, <16 x i32>* [[DOTCOMPOUNDLITERAL_I_I]], align 64
+// CHECK-NEXT: [[TMP19:%.*]] = bitcast <16 x i32> [[TMP18]] to <8 x i64>
+// CHECK-NEXT: [[TMP20:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2
+// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: store <8 x i64> [[TMP19]], <8 x i64>* [[__W_ADDR_I_I]], align 64
+// CHECK-NEXT: store i16 [[TMP20]], i16* [[__U_ADDR_I_I]], align 2
+// CHECK-NEXT: store <8 x i64> [[TMP21]], <8 x i64>* [[__A_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP22:%.*]] = load i16, i16* [[__U_ADDR_I_I]], align 2
+// CHECK-NEXT: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP24:%.*]] = bitcast <8 x i64> [[TMP23]] to <16 x i32>
+// CHECK-NEXT: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP26:%.*]] = bitcast <8 x i64> [[TMP25]] to <16 x i32>
+// CHECK-NEXT: [[TMP27:%.*]] = bitcast i16 [[TMP22]] to <16 x i1>
+// CHECK-NEXT: [[TMP28:%.*]] = select <16 x i1> [[TMP27]], <16 x i32> [[TMP24]], <16 x i32> [[TMP26]]
+// CHECK-NEXT: [[TMP29:%.*]] = bitcast <16 x i32> [[TMP28]] to <8 x i64>
+// CHECK-NEXT: store <8 x i64> [[TMP29]], <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[EXTRACT_I:%.*]] = shufflevector <8 x i64> [[TMP30]], <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK-NEXT: store <4 x i64> [[EXTRACT_I]], <4 x i64>* [[__T1_I]], align 32
+// CHECK-NEXT: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[EXTRACT4_I:%.*]] = shufflevector <8 x i64> [[TMP31]], <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK-NEXT: store <4 x i64> [[EXTRACT4_I]], <4 x i64>* [[__T2_I]], align 32
+// CHECK-NEXT: [[TMP32:%.*]] = load <4 x i64>, <4 x i64>* [[__T1_I]], align 32
+// CHECK-NEXT: [[TMP33:%.*]] = load <4 x i64>, <4 x i64>* [[__T2_I]], align 32
+// CHECK-NEXT: store <4 x i64> [[TMP32]], <4 x i64>* [[__A2_ADDR_I_I]], align 32
+// CHECK-NEXT: store <4 x i64> [[TMP33]], <4 x i64>* [[__B_ADDR_I_I]], align 32
+// CHECK-NEXT: [[TMP34:%.*]] = load <4 x i64>, <4 x i64>* [[__A2_ADDR_I_I]], align 32
+// CHECK-NEXT: [[TMP35:%.*]] = bitcast <4 x i64> [[TMP34]] to <8 x i32>
+// CHECK-NEXT: [[TMP36:%.*]] = load <4 x i64>, <4 x i64>* [[__B_ADDR_I_I]], align 32
+// CHECK-NEXT: [[TMP37:%.*]] = bitcast <4 x i64> [[TMP36]] to <8 x i32>
+// CHECK-NEXT: [[TMP38:%.*]] = icmp ult <8 x i32> [[TMP35]], [[TMP37]]
+// CHECK-NEXT: [[TMP39:%.*]] = select <8 x i1> [[TMP38]], <8 x i32> [[TMP35]], <8 x i32> [[TMP37]]
+// CHECK-NEXT: [[TMP40:%.*]] = bitcast <8 x i32> [[TMP39]] to <4 x i64>
+// CHECK-NEXT: store <4 x i64> [[TMP40]], <4 x i64>* [[__T3_I]], align 32
+// CHECK-NEXT: [[TMP41:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32
+// CHECK-NEXT: [[EXTRACT6_I:%.*]] = shufflevector <4 x i64> [[TMP41]], <4 x i64> undef, <2 x i32> <i32 0, i32 1>
+// CHECK-NEXT: store <2 x i64> [[EXTRACT6_I]], <2 x i64>* [[__T4_I]], align 16
+// CHECK-NEXT: [[TMP42:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32
+// CHECK-NEXT: [[EXTRACT7_I:%.*]] = shufflevector <4 x i64> [[TMP42]], <4 x i64> undef, <2 x i32> <i32 2, i32 3>
+// CHECK-NEXT: store <2 x i64> [[EXTRACT7_I]], <2 x i64>* [[__T5_I]], align 16
+// CHECK-NEXT: [[TMP43:%.*]] = load <2 x i64>, <2 x i64>* [[__T4_I]], align 16
+// CHECK-NEXT: [[TMP44:%.*]] = load <2 x i64>, <2 x i64>* [[__T5_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP43]], <2 x i64>* [[__V1_ADDR_I14_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP44]], <2 x i64>* [[__V2_ADDR_I15_I]], align 16
+// CHECK-NEXT: [[TMP45:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I14_I]], align 16
+// CHECK-NEXT: [[TMP46:%.*]] = bitcast <2 x i64> [[TMP45]] to <4 x i32>
+// CHECK-NEXT: [[TMP47:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I15_I]], align 16
+// CHECK-NEXT: [[TMP48:%.*]] = bitcast <2 x i64> [[TMP47]] to <4 x i32>
+// CHECK-NEXT: [[TMP49:%.*]] = icmp ult <4 x i32> [[TMP46]], [[TMP48]]
+// CHECK-NEXT: [[TMP50:%.*]] = select <4 x i1> [[TMP49]], <4 x i32> [[TMP46]], <4 x i32> [[TMP48]]
+// CHECK-NEXT: [[TMP51:%.*]] = bitcast <4 x i32> [[TMP50]] to <2 x i64>
+// CHECK-NEXT: store <2 x i64> [[TMP51]], <2 x i64>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP52:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP53:%.*]] = bitcast <2 x i64> [[TMP52]] to <4 x i32>
+// CHECK-NEXT: [[TMP54:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP55:%.*]] = bitcast <2 x i64> [[TMP54]] to <4 x i32>
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> [[TMP53]], <4 x i32> [[TMP55]], <4 x i32> <i32 2, i32 3, i32 0, i32 1>
+// CHECK-NEXT: [[TMP56:%.*]] = bitcast <4 x i32> [[SHUFFLE_I]] to <2 x i64>
+// CHECK-NEXT: store <2 x i64> [[TMP56]], <2 x i64>* [[__T7_I]], align 16
+// CHECK-NEXT: [[TMP57:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP58:%.*]] = load <2 x i64>, <2 x i64>* [[__T7_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP57]], <2 x i64>* [[__V1_ADDR_I12_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP58]], <2 x i64>* [[__V2_ADDR_I13_I]], align 16
+// CHECK-NEXT: [[TMP59:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I12_I]], align 16
+// CHECK-NEXT: [[TMP60:%.*]] = bitcast <2 x i64> [[TMP59]] to <4 x i32>
+// CHECK-NEXT: [[TMP61:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I13_I]], align 16
+// CHECK-NEXT: [[TMP62:%.*]] = bitcast <2 x i64> [[TMP61]] to <4 x i32>
+// CHECK-NEXT: [[TMP63:%.*]] = icmp ult <4 x i32> [[TMP60]], [[TMP62]]
+// CHECK-NEXT: [[TMP64:%.*]] = select <4 x i1> [[TMP63]], <4 x i32> [[TMP60]], <4 x i32> [[TMP62]]
+// CHECK-NEXT: [[TMP65:%.*]] = bitcast <4 x i32> [[TMP64]] to <2 x i64>
+// CHECK-NEXT: store <2 x i64> [[TMP65]], <2 x i64>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP66:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP67:%.*]] = bitcast <2 x i64> [[TMP66]] to <4 x i32>
+// CHECK-NEXT: [[TMP68:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP69:%.*]] = bitcast <2 x i64> [[TMP68]] to <4 x i32>
+// CHECK-NEXT: [[SHUFFLE10_I:%.*]] = shufflevector <4 x i32> [[TMP67]], <4 x i32> [[TMP69]], <4 x i32> <i32 1, i32 0, i32 3, i32 2>
+// CHECK-NEXT: [[TMP70:%.*]] = bitcast <4 x i32> [[SHUFFLE10_I]] to <2 x i64>
+// CHECK-NEXT: store <2 x i64> [[TMP70]], <2 x i64>* [[__T9_I]], align 16
+// CHECK-NEXT: [[TMP71:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP72:%.*]] = load <2 x i64>, <2 x i64>* [[__T9_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP71]], <2 x i64>* [[__V1_ADDR_I_I]], align 16
+// CHECK-NEXT: store <2 x i64> [[TMP72]], <2 x i64>* [[__V2_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP73:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP74:%.*]] = bitcast <2 x i64> [[TMP73]] to <4 x i32>
+// CHECK-NEXT: [[TMP75:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP76:%.*]] = bitcast <2 x i64> [[TMP75]] to <4 x i32>
+// CHECK-NEXT: [[TMP77:%.*]] = icmp ult <4 x i32> [[TMP74]], [[TMP76]]
+// CHECK-NEXT: [[TMP78:%.*]] = select <4 x i1> [[TMP77]], <4 x i32> [[TMP74]], <4 x i32> [[TMP76]]
+// CHECK-NEXT: [[TMP79:%.*]] = bitcast <4 x i32> [[TMP78]] to <2 x i64>
+// CHECK-NEXT: store <4 x i32> [[TMP78]], <4 x i32>* [[__T10_I]], align 16
+// CHECK-NEXT: [[TMP80:%.*]] = load <4 x i32>, <4 x i32>* [[__T10_I]], align 16
+// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x i32> [[TMP80]], i32 0
+// CHECK-NEXT: ret i32 [[VECEXT_I]]
unsigned int test_mm512_mask_reduce_min_epu32(__mmask16 __M, __m512i __W){
return _mm512_mask_reduce_min_epu32(__M, __W);
}
// CHECK-LABEL: define float @test_mm512_mask_reduce_min_ps(i16 zeroext %__M, <16 x float> %__W) #0 {
-// CHECK: [[_COMPOUNDLITERAL_I_I18_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__A_ADDR_I19_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__B_ADDR_I20_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I15_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__A_ADDR_I16_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__B_ADDR_I17_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I12_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__W_ADDR_I_I:%.*]] = alloca float, align 4
-// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__M_ADDR_I:%.*]] = alloca i16, align 2
-// CHECK: [[__V_ADDR_I:%.*]] = alloca <16 x float>, align 64
-// CHECK: [[__M_ADDR:%.*]] = alloca i16, align 2
-// CHECK: [[__W_ADDR:%.*]] = alloca <16 x float>, align 64
-// CHECK: store i16 %__M, i16* [[__M_ADDR]], align 2
-// CHECK: store <16 x float> %__W, <16 x float>* [[__W_ADDR]], align 64
-// CHECK: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2
-// CHECK: [[TMP1:%.*]] = load <16 x float>, <16 x float>* [[__W_ADDR]], align 64
-// CHECK: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2
-// CHECK: store <16 x float> [[TMP1]], <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP2:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2
-// CHECK: [[TMP3:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: store float 0x7FF0000000000000, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[TMP4:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[VECINIT_I_I:%.*]] = insertelement <16 x float> undef, float [[TMP4]], i32 0
-// CHECK: [[TMP5:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <16 x float> [[VECINIT_I_I]], float [[TMP5]], i32 1
-// CHECK: [[TMP6:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <16 x float> [[VECINIT1_I_I]], float [[TMP6]], i32 2
-// CHECK: [[TMP7:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <16 x float> [[VECINIT2_I_I]], float [[TMP7]], i32 3
-// CHECK: [[TMP8:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <16 x float> [[VECINIT3_I_I]], float [[TMP8]], i32 4
-// CHECK: [[TMP9:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <16 x float> [[VECINIT4_I_I]], float [[TMP9]], i32 5
-// CHECK: [[TMP10:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <16 x float> [[VECINIT5_I_I]], float [[TMP10]], i32 6
-// CHECK: [[TMP11:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <16 x float> [[VECINIT6_I_I]], float [[TMP11]], i32 7
-// CHECK: [[TMP12:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[VECINIT8_I_I:%.*]] = insertelement <16 x float> [[VECINIT7_I_I]], float [[TMP12]], i32 8
-// CHECK: [[TMP13:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[VECINIT9_I_I:%.*]] = insertelement <16 x float> [[VECINIT8_I_I]], float [[TMP13]], i32 9
-// CHECK: [[TMP14:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[VECINIT10_I_I:%.*]] = insertelement <16 x float> [[VECINIT9_I_I]], float [[TMP14]], i32 10
-// CHECK: [[TMP15:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[VECINIT11_I_I:%.*]] = insertelement <16 x float> [[VECINIT10_I_I]], float [[TMP15]], i32 11
-// CHECK: [[TMP16:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[VECINIT12_I_I:%.*]] = insertelement <16 x float> [[VECINIT11_I_I]], float [[TMP16]], i32 12
-// CHECK: [[TMP17:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[VECINIT13_I_I:%.*]] = insertelement <16 x float> [[VECINIT12_I_I]], float [[TMP17]], i32 13
-// CHECK: [[TMP18:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[VECINIT14_I_I:%.*]] = insertelement <16 x float> [[VECINIT13_I_I]], float [[TMP18]], i32 14
-// CHECK: [[TMP19:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
-// CHECK: [[VECINIT15_I_I:%.*]] = insertelement <16 x float> [[VECINIT14_I_I]], float [[TMP19]], i32 15
-// CHECK: store <16 x float> [[VECINIT15_I_I]], <16 x float>* [[_COMPOUNDLITERAL_I_I]], align 64
-// CHECK: [[TMP20:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I]], align 64
-// CHECK: [[TMP21:%.*]] = bitcast i16 [[TMP2]] to <16 x i1>
-// CHECK: [[TMP22:%.*]] = select <16 x i1> [[TMP21]], <16 x float> [[TMP3]], <16 x float> [[TMP20]]
-// CHECK: store <16 x float> [[TMP22]], <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP23:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP24:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x float> [[TMP23]], <16 x float> [[TMP24]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP25:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP26:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x float> [[TMP25]], <16 x float> [[TMP26]], <16 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <16 x float> [[SHUFFLE_I]], <16 x float>* [[__A_ADDR_I19_I]], align 64
-// CHECK: store <16 x float> [[SHUFFLE1_I]], <16 x float>* [[__B_ADDR_I20_I]], align 64
-// CHECK: [[TMP27:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I19_I]], align 64
-// CHECK: [[TMP28:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I20_I]], align 64
-// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I18_I]], align 64
-// CHECK: [[TMP29:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I18_I]], align 64
-// CHECK: [[TMP30:%.*]] = call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> [[TMP27]], <16 x float> [[TMP28]], <16 x float> [[TMP29]], i16 -1, i32 4) #2
-// CHECK: store <16 x float> [[TMP30]], <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP31:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP32:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x float> [[TMP31]], <16 x float> [[TMP32]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP33:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP34:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <16 x float> [[TMP33]], <16 x float> [[TMP34]], <16 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <16 x float> [[SHUFFLE3_I]], <16 x float>* [[__A_ADDR_I16_I]], align 64
-// CHECK: store <16 x float> [[SHUFFLE4_I]], <16 x float>* [[__B_ADDR_I17_I]], align 64
-// CHECK: [[TMP35:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I16_I]], align 64
-// CHECK: [[TMP36:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I17_I]], align 64
-// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I15_I]], align 64
-// CHECK: [[TMP37:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I15_I]], align 64
-// CHECK: [[TMP38:%.*]] = call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> [[TMP35]], <16 x float> [[TMP36]], <16 x float> [[TMP37]], i16 -1, i32 4) #2
-// CHECK: store <16 x float> [[TMP38]], <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP39:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP40:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x float> [[TMP39]], <16 x float> [[TMP40]], <16 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP41:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP42:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <16 x float> [[TMP41]], <16 x float> [[TMP42]], <16 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <16 x float> [[SHUFFLE6_I]], <16 x float>* [[__A_ADDR_I13_I]], align 64
-// CHECK: store <16 x float> [[SHUFFLE7_I]], <16 x float>* [[__B_ADDR_I14_I]], align 64
-// CHECK: [[TMP43:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I13_I]], align 64
-// CHECK: [[TMP44:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I14_I]], align 64
-// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I12_I]], align 64
-// CHECK: [[TMP45:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I12_I]], align 64
-// CHECK: [[TMP46:%.*]] = call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> [[TMP43]], <16 x float> [[TMP44]], <16 x float> [[TMP45]], i16 -1, i32 4) #2
-// CHECK: store <16 x float> [[TMP46]], <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP47:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP48:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x float> [[TMP47]], <16 x float> [[TMP48]], <16 x i32> <i32 0, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: [[TMP49:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP50:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[SHUFFLE10_I:%.*]] = shufflevector <16 x float> [[TMP49]], <16 x float> [[TMP50]], <16 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
-// CHECK: store <16 x float> [[SHUFFLE9_I]], <16 x float>* [[__A_ADDR_I_I]], align 64
-// CHECK: store <16 x float> [[SHUFFLE10_I]], <16 x float>* [[__B_ADDR_I_I]], align 64
-// CHECK: [[TMP51:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I_I]], align 64
-// CHECK: [[TMP52:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I_I]], align 64
-// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP53:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I_I]], align 64
-// CHECK: [[TMP54:%.*]] = call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> [[TMP51]], <16 x float> [[TMP52]], <16 x float> [[TMP53]], i16 -1, i32 4) #2
-// CHECK: store <16 x float> [[TMP54]], <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[TMP55:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
-// CHECK: [[VECEXT_I:%.*]] = extractelement <16 x float> [[TMP55]], i32 0
-// CHECK: ret float [[VECEXT_I]]
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[__W2_ADDR_I_I:%.*]] = alloca <16 x float>, align 64
+// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i16, align 2
+// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <16 x float>, align 64
+// CHECK-NEXT: [[__A_ADDR_I16_I:%.*]] = alloca <8 x float>, align 32
+// CHECK-NEXT: [[__B_ADDR_I17_I:%.*]] = alloca <8 x float>, align 32
+// CHECK-NEXT: [[__A_ADDR_I14_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__B_ADDR_I15_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__A_ADDR_I12_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__B_ADDR_I13_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__A2_ADDR_I_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca float, align 4
+// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <16 x float>, align 64
+// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i16, align 2
+// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <16 x float>, align 64
+// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x float>, align 32
+// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x float>, align 32
+// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x float>, align 32
+// CHECK-NEXT: [[__T4_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__T5_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__T6_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__T7_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__T8_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__T9_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i16, align 2
+// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <16 x float>, align 64
+// CHECK-NEXT: store i16 [[__M:%.*]], i16* [[__M_ADDR]], align 2
+// CHECK-NEXT: store <16 x float> [[__W:%.*]], <16 x float>* [[__W_ADDR]], align 64
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load <16 x float>, <16 x float>* [[__W_ADDR]], align 64
+// CHECK-NEXT: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2
+// CHECK-NEXT: store <16 x float> [[TMP1]], <16 x float>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: store float 0x7FF0000000000000, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <16 x float> undef, float [[TMP2]], i32 0
+// CHECK-NEXT: [[TMP3:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <16 x float> [[VECINIT_I_I]], float [[TMP3]], i32 1
+// CHECK-NEXT: [[TMP4:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <16 x float> [[VECINIT1_I_I]], float [[TMP4]], i32 2
+// CHECK-NEXT: [[TMP5:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <16 x float> [[VECINIT2_I_I]], float [[TMP5]], i32 3
+// CHECK-NEXT: [[TMP6:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <16 x float> [[VECINIT3_I_I]], float [[TMP6]], i32 4
+// CHECK-NEXT: [[TMP7:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <16 x float> [[VECINIT4_I_I]], float [[TMP7]], i32 5
+// CHECK-NEXT: [[TMP8:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <16 x float> [[VECINIT5_I_I]], float [[TMP8]], i32 6
+// CHECK-NEXT: [[TMP9:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <16 x float> [[VECINIT6_I_I]], float [[TMP9]], i32 7
+// CHECK-NEXT: [[TMP10:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT8_I_I:%.*]] = insertelement <16 x float> [[VECINIT7_I_I]], float [[TMP10]], i32 8
+// CHECK-NEXT: [[TMP11:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT9_I_I:%.*]] = insertelement <16 x float> [[VECINIT8_I_I]], float [[TMP11]], i32 9
+// CHECK-NEXT: [[TMP12:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT10_I_I:%.*]] = insertelement <16 x float> [[VECINIT9_I_I]], float [[TMP12]], i32 10
+// CHECK-NEXT: [[TMP13:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT11_I_I:%.*]] = insertelement <16 x float> [[VECINIT10_I_I]], float [[TMP13]], i32 11
+// CHECK-NEXT: [[TMP14:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT12_I_I:%.*]] = insertelement <16 x float> [[VECINIT11_I_I]], float [[TMP14]], i32 12
+// CHECK-NEXT: [[TMP15:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT13_I_I:%.*]] = insertelement <16 x float> [[VECINIT12_I_I]], float [[TMP15]], i32 13
+// CHECK-NEXT: [[TMP16:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT14_I_I:%.*]] = insertelement <16 x float> [[VECINIT13_I_I]], float [[TMP16]], i32 14
+// CHECK-NEXT: [[TMP17:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4
+// CHECK-NEXT: [[VECINIT15_I_I:%.*]] = insertelement <16 x float> [[VECINIT14_I_I]], float [[TMP17]], i32 15
+// CHECK-NEXT: store <16 x float> [[VECINIT15_I_I]], <16 x float>* [[DOTCOMPOUNDLITERAL_I_I]], align 64
+// CHECK-NEXT: [[TMP18:%.*]] = load <16 x float>, <16 x float>* [[DOTCOMPOUNDLITERAL_I_I]], align 64
+// CHECK-NEXT: [[TMP19:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2
+// CHECK-NEXT: [[TMP20:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: store <16 x float> [[TMP18]], <16 x float>* [[__W2_ADDR_I_I]], align 64
+// CHECK-NEXT: store i16 [[TMP19]], i16* [[__U_ADDR_I_I]], align 2
+// CHECK-NEXT: store <16 x float> [[TMP20]], <16 x float>* [[__A_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP21:%.*]] = load i16, i16* [[__U_ADDR_I_I]], align 2
+// CHECK-NEXT: [[TMP22:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP23:%.*]] = load <16 x float>, <16 x float>* [[__W2_ADDR_I_I]], align 64
+// CHECK-NEXT: [[TMP24:%.*]] = bitcast i16 [[TMP21]] to <16 x i1>
+// CHECK-NEXT: [[TMP25:%.*]] = select <16 x i1> [[TMP24]], <16 x float> [[TMP22]], <16 x float> [[TMP23]]
+// CHECK-NEXT: store <16 x float> [[TMP25]], <16 x float>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP26:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP27:%.*]] = bitcast <16 x float> [[TMP26]] to <8 x double>
+// CHECK-NEXT: [[EXTRACT_I:%.*]] = shufflevector <8 x double> [[TMP27]], <8 x double> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK-NEXT: [[TMP28:%.*]] = bitcast <4 x double> [[EXTRACT_I]] to <8 x float>
+// CHECK-NEXT: store <8 x float> [[TMP28]], <8 x float>* [[__T1_I]], align 32
+// CHECK-NEXT: [[TMP29:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64
+// CHECK-NEXT: [[TMP30:%.*]] = bitcast <16 x float> [[TMP29]] to <8 x double>
+// CHECK-NEXT: [[EXTRACT4_I:%.*]] = shufflevector <8 x double> [[TMP30]], <8 x double> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK-NEXT: [[TMP31:%.*]] = bitcast <4 x double> [[EXTRACT4_I]] to <8 x float>
+// CHECK-NEXT: store <8 x float> [[TMP31]], <8 x float>* [[__T2_I]], align 32
+// CHECK-NEXT: [[TMP32:%.*]] = load <8 x float>, <8 x float>* [[__T1_I]], align 32
+// CHECK-NEXT: [[TMP33:%.*]] = load <8 x float>, <8 x float>* [[__T2_I]], align 32
+// CHECK-NEXT: store <8 x float> [[TMP32]], <8 x float>* [[__A_ADDR_I16_I]], align 32
+// CHECK-NEXT: store <8 x float> [[TMP33]], <8 x float>* [[__B_ADDR_I17_I]], align 32
+// CHECK-NEXT: [[TMP34:%.*]] = load <8 x float>, <8 x float>* [[__A_ADDR_I16_I]], align 32
+// CHECK-NEXT: [[TMP35:%.*]] = load <8 x float>, <8 x float>* [[__B_ADDR_I17_I]], align 32
+// CHECK-NEXT: [[TMP36:%.*]] = call <8 x float> @llvm.x86.avx.min.ps.256(<8 x float> [[TMP34]], <8 x float> [[TMP35]]) #2
+// CHECK-NEXT: store <8 x float> [[TMP36]], <8 x float>* [[__T3_I]], align 32
+// CHECK-NEXT: [[TMP37:%.*]] = load <8 x float>, <8 x float>* [[__T3_I]], align 32
+// CHECK-NEXT: [[EXTRACT6_I:%.*]] = shufflevector <8 x float> [[TMP37]], <8 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK-NEXT: store <4 x float> [[EXTRACT6_I]], <4 x float>* [[__T4_I]], align 16
+// CHECK-NEXT: [[TMP38:%.*]] = load <8 x float>, <8 x float>* [[__T3_I]], align 32
+// CHECK-NEXT: [[EXTRACT7_I:%.*]] = shufflevector <8 x float> [[TMP38]], <8 x float> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// CHECK-NEXT: store <4 x float> [[EXTRACT7_I]], <4 x float>* [[__T5_I]], align 16
+// CHECK-NEXT: [[TMP39:%.*]] = load <4 x float>, <4 x float>* [[__T4_I]], align 16
+// CHECK-NEXT: [[TMP40:%.*]] = load <4 x float>, <4 x float>* [[__T5_I]], align 16
+// CHECK-NEXT: store <4 x float> [[TMP39]], <4 x float>* [[__A_ADDR_I14_I]], align 16
+// CHECK-NEXT: store <4 x float> [[TMP40]], <4 x float>* [[__B_ADDR_I15_I]], align 16
+// CHECK-NEXT: [[TMP41:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I14_I]], align 16
+// CHECK-NEXT: [[TMP42:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I15_I]], align 16
+// CHECK-NEXT: [[TMP43:%.*]] = call <4 x float> @llvm.x86.sse.min.ps(<4 x float> [[TMP41]], <4 x float> [[TMP42]]) #2
+// CHECK-NEXT: store <4 x float> [[TMP43]], <4 x float>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP44:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP45:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16
+// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x float> [[TMP44]], <4 x float> [[TMP45]], <4 x i32> <i32 2, i32 3, i32 0, i32 1>
+// CHECK-NEXT: store <4 x float> [[SHUFFLE_I]], <4 x float>* [[__T7_I]], align 16
+// CHECK-NEXT: [[TMP46:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16
+// CHECK-NEXT: [[TMP47:%.*]] = load <4 x float>, <4 x float>* [[__T7_I]], align 16
+// CHECK-NEXT: store <4 x float> [[TMP46]], <4 x float>* [[__A_ADDR_I12_I]], align 16
+// CHECK-NEXT: store <4 x float> [[TMP47]], <4 x float>* [[__B_ADDR_I13_I]], align 16
+// CHECK-NEXT: [[TMP48:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I12_I]], align 16
+// CHECK-NEXT: [[TMP49:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I13_I]], align 16
+// CHECK-NEXT: [[TMP50:%.*]] = call <4 x float> @llvm.x86.sse.min.ps(<4 x float> [[TMP48]], <4 x float> [[TMP49]]) #2
+// CHECK-NEXT: store <4 x float> [[TMP50]], <4 x float>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP51:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP52:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16
+// CHECK-NEXT: [[SHUFFLE10_I:%.*]] = shufflevector <4 x float> [[TMP51]], <4 x float> [[TMP52]], <4 x i32> <i32 1, i32 0, i32 3, i32 2>
+// CHECK-NEXT: store <4 x float> [[SHUFFLE10_I]], <4 x float>* [[__T9_I]], align 16
+// CHECK-NEXT: [[TMP53:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16
+// CHECK-NEXT: [[TMP54:%.*]] = load <4 x float>, <4 x float>* [[__T9_I]], align 16
+// CHECK-NEXT: store <4 x float> [[TMP53]], <4 x float>* [[__A2_ADDR_I_I]], align 16
+// CHECK-NEXT: store <4 x float> [[TMP54]], <4 x float>* [[__B_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP55:%.*]] = load <4 x float>, <4 x float>* [[__A2_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP56:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I_I]], align 16
+// CHECK-NEXT: [[TMP57:%.*]] = call <4 x float> @llvm.x86.sse.min.ps(<4 x float> [[TMP55]], <4 x float> [[TMP56]]) #2
+// CHECK-NEXT: store <4 x float> [[TMP57]], <4 x float>* [[__T10_I]], align 16
+// CHECK-NEXT: [[TMP58:%.*]] = load <4 x float>, <4 x float>* [[__T10_I]], align 16
+// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x float> [[TMP58]], i32 0
+// CHECK-NEXT: ret float [[VECEXT_I]]
float test_mm512_mask_reduce_min_ps(__mmask16 __M, __m512 __W){
return _mm512_mask_reduce_min_ps(__M, __W);
}
diff --git a/test/CodeGen/avx512bw-builtins.c b/test/CodeGen/avx512bw-builtins.c
index 3160a6667c00..7d2e1fadf4ce 100644
--- a/test/CodeGen/avx512bw-builtins.c
+++ b/test/CodeGen/avx512bw-builtins.c
@@ -684,7 +684,7 @@ __m512i test_mm512_maskz_avg_epu8(__mmask64 __U, __m512i __A, __m512i __B) {
// CHECK: add <64 x i16> %{{.*}}, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>
// CHECK: lshr <64 x i16> %{{.*}}, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>
// CHECK: trunc <64 x i16> %{{.*}} to <64 x i8>
- // CHECK: store <64 x i8> zeroinitializer
+ // CHECK: store <8 x i64> zeroinitializer
// CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}}
return _mm512_maskz_avg_epu8(__U,__A,__B);
}
@@ -720,7 +720,7 @@ __m512i test_mm512_maskz_avg_epu16(__mmask32 __U, __m512i __A, __m512i __B) {
// CHECK: add <32 x i32> %{{.*}}, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
// CHECK: lshr <32 x i32> %{{.*}}, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
// CHECK: trunc <32 x i32> %{{.*}} to <32 x i16>
- // CHECK: store <32 x i16> zeroinitializer
+ // CHECK: store <8 x i64> zeroinitializer
// CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_maskz_avg_epu16(__U,__A,__B);
}
@@ -963,99 +963,112 @@ __m512i test_mm512_maskz_subs_epu16(__mmask32 __U, __m512i __A, __m512i __B) {
}
__m512i test_mm512_mask2_permutex2var_epi16(__m512i __A, __m512i __I, __mmask32 __U, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask2_permutex2var_epi16
- // CHECK: @llvm.x86.avx512.mask.vpermi2var.hi.512
+ // CHECK: @llvm.x86.avx512.vpermi2var.hi.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_mask2_permutex2var_epi16(__A,__I,__U,__B);
}
__m512i test_mm512_permutex2var_epi16(__m512i __A, __m512i __I, __m512i __B) {
// CHECK-LABEL: @test_mm512_permutex2var_epi16
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.hi.512
+ // CHECK: @llvm.x86.avx512.vpermi2var.hi.512
return _mm512_permutex2var_epi16(__A,__I,__B);
}
__m512i test_mm512_mask_permutex2var_epi16(__m512i __A, __mmask32 __U, __m512i __I, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_permutex2var_epi16
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.hi.512
+ // CHECK: @llvm.x86.avx512.vpermi2var.hi.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_mask_permutex2var_epi16(__A,__U,__I,__B);
}
__m512i test_mm512_maskz_permutex2var_epi16(__mmask32 __U, __m512i __A, __m512i __I, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_permutex2var_epi16
- // CHECK: @llvm.x86.avx512.maskz.vpermt2var.hi.512
+ // CHECK: @llvm.x86.avx512.vpermi2var.hi.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_maskz_permutex2var_epi16(__U,__A,__I,__B);
}
__m512i test_mm512_mulhrs_epi16(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mulhrs_epi16
- // CHECK: @llvm.x86.avx512.mask.pmul.hr.sw.512
+ // CHECK: @llvm.x86.avx512.pmul.hr.sw.512
return _mm512_mulhrs_epi16(__A,__B);
}
__m512i test_mm512_mask_mulhrs_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_mulhrs_epi16
- // CHECK: @llvm.x86.avx512.mask.pmul.hr.sw.512
+ // CHECK: @llvm.x86.avx512.pmul.hr.sw.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_mask_mulhrs_epi16(__W,__U,__A,__B);
}
__m512i test_mm512_maskz_mulhrs_epi16(__mmask32 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_mulhrs_epi16
- // CHECK: @llvm.x86.avx512.mask.pmul.hr.sw.512
+ // CHECK: @llvm.x86.avx512.pmul.hr.sw.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_maskz_mulhrs_epi16(__U,__A,__B);
}
__m512i test_mm512_mulhi_epi16(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mulhi_epi16
- // CHECK: @llvm.x86.avx512.mask.pmulh.w.512
+ // CHECK: @llvm.x86.avx512.pmulh.w.512
return _mm512_mulhi_epi16(__A,__B);
}
__m512i test_mm512_mask_mulhi_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_mulhi_epi16
- // CHECK: @llvm.x86.avx512.mask.pmulh.w.512
+ // CHECK: @llvm.x86.avx512.pmulh.w.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_mask_mulhi_epi16(__W,__U,__A,__B);
}
__m512i test_mm512_maskz_mulhi_epi16(__mmask32 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_mulhi_epi16
- // CHECK: @llvm.x86.avx512.mask.pmulh.w.512
+ // CHECK: @llvm.x86.avx512.pmulh.w.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_maskz_mulhi_epi16(__U,__A,__B);
}
__m512i test_mm512_mulhi_epu16(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mulhi_epu16
- // CHECK: @llvm.x86.avx512.mask.pmulhu.w.512
+ // CHECK: @llvm.x86.avx512.pmulhu.w.512
return _mm512_mulhi_epu16(__A,__B);
}
__m512i test_mm512_mask_mulhi_epu16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_mulhi_epu16
- // CHECK: @llvm.x86.avx512.mask.pmulhu.w.512
+ // CHECK: @llvm.x86.avx512.pmulhu.w.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_mask_mulhi_epu16(__W,__U,__A,__B);
}
__m512i test_mm512_maskz_mulhi_epu16(__mmask32 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_mulhi_epu16
- // CHECK: @llvm.x86.avx512.mask.pmulhu.w.512
+ // CHECK: @llvm.x86.avx512.pmulhu.w.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_maskz_mulhi_epu16(__U,__A,__B);
}
__m512i test_mm512_maddubs_epi16(__m512i __X, __m512i __Y) {
// CHECK-LABEL: @test_mm512_maddubs_epi16
- // CHECK: @llvm.x86.avx512.mask.pmaddubs.w.512
+ // CHECK: @llvm.x86.avx512.pmaddubs.w.512
return _mm512_maddubs_epi16(__X,__Y);
}
__m512i test_mm512_mask_maddubs_epi16(__m512i __W, __mmask32 __U, __m512i __X, __m512i __Y) {
// CHECK-LABEL: @test_mm512_mask_maddubs_epi16
- // CHECK: @llvm.x86.avx512.mask.pmaddubs.w.512
+ // CHECK: @llvm.x86.avx512.pmaddubs.w.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_mask_maddubs_epi16(__W,__U,__X,__Y);
}
__m512i test_mm512_maskz_maddubs_epi16(__mmask32 __U, __m512i __X, __m512i __Y) {
// CHECK-LABEL: @test_mm512_maskz_maddubs_epi16
- // CHECK: @llvm.x86.avx512.mask.pmaddubs.w.512
+ // CHECK: @llvm.x86.avx512.pmaddubs.w.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_maskz_maddubs_epi16(__U,__X,__Y);
}
__m512i test_mm512_madd_epi16(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_madd_epi16
- // CHECK: @llvm.x86.avx512.mask.pmaddw.d.512
+ // CHECK: @llvm.x86.avx512.pmaddw.d.512
return _mm512_madd_epi16(__A,__B);
}
__m512i test_mm512_mask_madd_epi16(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_madd_epi16
- // CHECK: @llvm.x86.avx512.mask.pmaddw.d.512
+ // CHECK: @llvm.x86.avx512.pmaddw.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_madd_epi16(__W,__U,__A,__B);
}
__m512i test_mm512_maskz_madd_epi16(__mmask16 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_madd_epi16
- // CHECK: @llvm.x86.avx512.mask.pmaddw.d.512
+ // CHECK: @llvm.x86.avx512.pmaddw.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_madd_epi16(__U,__A,__B);
}
@@ -1097,19 +1110,21 @@ __m256i test_mm512_maskz_cvtusepi16_epi8(__mmask32 __M, __m512i __A) {
__m256i test_mm512_cvtepi16_epi8(__m512i __A) {
// CHECK-LABEL: @test_mm512_cvtepi16_epi8
- // CHECK: @llvm.x86.avx512.mask.pmov.wb.512
+ // CHECK: trunc <32 x i16> %{{.*}} to <32 x i8>
return _mm512_cvtepi16_epi8(__A);
}
__m256i test_mm512_mask_cvtepi16_epi8(__m256i __O, __mmask32 __M, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_cvtepi16_epi8
- // CHECK: @llvm.x86.avx512.mask.pmov.wb.512
+ // CHECK: trunc <32 x i16> %{{.*}} to <32 x i8>
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm512_mask_cvtepi16_epi8(__O, __M, __A);
}
__m256i test_mm512_maskz_cvtepi16_epi8(__mmask32 __M, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_cvtepi16_epi8
- // CHECK: @llvm.x86.avx512.mask.pmov.wb.512
+ // CHECK: trunc <32 x i16> %{{.*}} to <32 x i8>
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm512_maskz_cvtepi16_epi8(__M, __A);
}
@@ -1235,40 +1250,40 @@ __m512i test_mm512_maskz_cvtepu8_epi16(__mmask32 __U, __m256i __A) {
__m512i test_mm512_shufflehi_epi16(__m512i __A) {
// CHECK-LABEL: @test_mm512_shufflehi_epi16
- // CHECK: shufflevector <32 x i16> %{{.*}}, <32 x i16> %{{.*}}, <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 5, i32 5, i32 4, i32 4, i32 8, i32 9, i32 10, i32 11, i32 13, i32 13, i32 12, i32 12, i32 16, i32 17, i32 18, i32 19, i32 21, i32 21, i32 20, i32 20, i32 24, i32 25, i32 26, i32 27, i32 29, i32 29, i32 28, i32 28>
+ // CHECK: shufflevector <32 x i16> %{{.*}}, <32 x i16> undef, <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 5, i32 5, i32 4, i32 4, i32 8, i32 9, i32 10, i32 11, i32 13, i32 13, i32 12, i32 12, i32 16, i32 17, i32 18, i32 19, i32 21, i32 21, i32 20, i32 20, i32 24, i32 25, i32 26, i32 27, i32 29, i32 29, i32 28, i32 28>
return _mm512_shufflehi_epi16(__A, 5);
}
__m512i test_mm512_mask_shufflehi_epi16(__m512i __W, __mmask32 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_shufflehi_epi16
- // CHECK: shufflevector <32 x i16> %{{.*}}, <32 x i16> %{{.*}}, <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 5, i32 5, i32 4, i32 4, i32 8, i32 9, i32 10, i32 11, i32 13, i32 13, i32 12, i32 12, i32 16, i32 17, i32 18, i32 19, i32 21, i32 21, i32 20, i32 20, i32 24, i32 25, i32 26, i32 27, i32 29, i32 29, i32 28, i32 28>
+ // CHECK: shufflevector <32 x i16> %{{.*}}, <32 x i16> undef, <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 5, i32 5, i32 4, i32 4, i32 8, i32 9, i32 10, i32 11, i32 13, i32 13, i32 12, i32 12, i32 16, i32 17, i32 18, i32 19, i32 21, i32 21, i32 20, i32 20, i32 24, i32 25, i32 26, i32 27, i32 29, i32 29, i32 28, i32 28>
// CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_mask_shufflehi_epi16(__W, __U, __A, 5);
}
__m512i test_mm512_maskz_shufflehi_epi16(__mmask32 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_shufflehi_epi16
- // CHECK: shufflevector <32 x i16> %{{.*}}, <32 x i16> %{{.*}}, <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 5, i32 5, i32 4, i32 4, i32 8, i32 9, i32 10, i32 11, i32 13, i32 13, i32 12, i32 12, i32 16, i32 17, i32 18, i32 19, i32 21, i32 21, i32 20, i32 20, i32 24, i32 25, i32 26, i32 27, i32 29, i32 29, i32 28, i32 28>
+ // CHECK: shufflevector <32 x i16> %{{.*}}, <32 x i16> undef, <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 5, i32 5, i32 4, i32 4, i32 8, i32 9, i32 10, i32 11, i32 13, i32 13, i32 12, i32 12, i32 16, i32 17, i32 18, i32 19, i32 21, i32 21, i32 20, i32 20, i32 24, i32 25, i32 26, i32 27, i32 29, i32 29, i32 28, i32 28>
// CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_maskz_shufflehi_epi16(__U, __A, 5);
}
__m512i test_mm512_shufflelo_epi16(__m512i __A) {
// CHECK-LABEL: @test_mm512_shufflelo_epi16
- // CHECK: shufflevector <32 x i16> %{{.*}}, <32 x i16> %{{.*}}, <32 x i32> <i32 1, i32 1, i32 0, i32 0, i32 4, i32 5, i32 6, i32 7, i32 9, i32 9, i32 8, i32 8, i32 12, i32 13, i32 14, i32 15, i32 17, i32 17, i32 16, i32 16, i32 20, i32 21, i32 22, i32 23, i32 25, i32 25, i32 24, i32 24, i32 28, i32 29, i32 30, i32 31>
+ // CHECK: shufflevector <32 x i16> %{{.*}}, <32 x i16> undef, <32 x i32> <i32 1, i32 1, i32 0, i32 0, i32 4, i32 5, i32 6, i32 7, i32 9, i32 9, i32 8, i32 8, i32 12, i32 13, i32 14, i32 15, i32 17, i32 17, i32 16, i32 16, i32 20, i32 21, i32 22, i32 23, i32 25, i32 25, i32 24, i32 24, i32 28, i32 29, i32 30, i32 31>
return _mm512_shufflelo_epi16(__A, 5);
}
__m512i test_mm512_mask_shufflelo_epi16(__m512i __W, __mmask32 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_shufflelo_epi16
- // CHECK: shufflevector <32 x i16> %{{.*}}, <32 x i16> %{{.*}}, <32 x i32> <i32 1, i32 1, i32 0, i32 0, i32 4, i32 5, i32 6, i32 7, i32 9, i32 9, i32 8, i32 8, i32 12, i32 13, i32 14, i32 15, i32 17, i32 17, i32 16, i32 16, i32 20, i32 21, i32 22, i32 23, i32 25, i32 25, i32 24, i32 24, i32 28, i32 29, i32 30, i32 31>
+ // CHECK: shufflevector <32 x i16> %{{.*}}, <32 x i16> undef, <32 x i32> <i32 1, i32 1, i32 0, i32 0, i32 4, i32 5, i32 6, i32 7, i32 9, i32 9, i32 8, i32 8, i32 12, i32 13, i32 14, i32 15, i32 17, i32 17, i32 16, i32 16, i32 20, i32 21, i32 22, i32 23, i32 25, i32 25, i32 24, i32 24, i32 28, i32 29, i32 30, i32 31>
// CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_mask_shufflelo_epi16(__W, __U, __A, 5);
}
__m512i test_mm512_maskz_shufflelo_epi16(__mmask32 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_shufflelo_epi16
- // CHECK: shufflevector <32 x i16> %{{.*}}, <32 x i16> %{{.*}}, <32 x i32> <i32 1, i32 1, i32 0, i32 0, i32 4, i32 5, i32 6, i32 7, i32 9, i32 9, i32 8, i32 8, i32 12, i32 13, i32 14, i32 15, i32 17, i32 17, i32 16, i32 16, i32 20, i32 21, i32 22, i32 23, i32 25, i32 25, i32 24, i32 24, i32 28, i32 29, i32 30, i32 31>
+ // CHECK: shufflevector <32 x i16> %{{.*}}, <32 x i16> undef, <32 x i32> <i32 1, i32 1, i32 0, i32 0, i32 4, i32 5, i32 6, i32 7, i32 9, i32 9, i32 8, i32 8, i32 12, i32 13, i32 14, i32 15, i32 17, i32 17, i32 16, i32 16, i32 20, i32 21, i32 22, i32 23, i32 25, i32 25, i32 24, i32 24, i32 28, i32 29, i32 30, i32 31>
// CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_maskz_shufflelo_epi16(__U, __A, 5);
}
@@ -1335,7 +1350,7 @@ __m512i test_mm512_maskz_slli_epi16(__mmask32 __U, __m512i __A) {
__m512i test_mm512_bslli_epi128(__m512i __A) {
// CHECK-LABEL: @test_mm512_bslli_epi128
- // CHECK: shufflevector <64 x i8> %{{.*}}, <64 x i8> %{{.*}}, <64 x i32> <i32 11, i32 12, i32 13, i32 14, i32 15, i32 64, i32 65, i32 66, i32 67, i32 68, i32 69, i32 70, i32 71, i32 72, i32 73, i32 74, i32 27, i32 28, i32 29, i32 30, i32 31, i32 80, i32 81, i32 82, i32 83, i32 84, i32 85, i32 86, i32 87, i32 88, i32 89, i32 90, i32 43, i32 44, i32 45, i32 46, i32 47, i32 96, i32 97, i32 98, i32 99, i32 100, i32 101, i32 102, i32 103, i32 104, i32 105, i32 106, i32 59, i32 60, i32 61, i32 62, i32 63, i32 112, i32 113, i32 114, i32 115, i32 116, i32 117, i32 118, i32 119, i32 120, i32 121, i32 122>
+ // CHECK: shufflevector <64 x i8> zeroinitializer, <64 x i8> %{{.*}}, <64 x i32> <i32 11, i32 12, i32 13, i32 14, i32 15, i32 64, i32 65, i32 66, i32 67, i32 68, i32 69, i32 70, i32 71, i32 72, i32 73, i32 74, i32 27, i32 28, i32 29, i32 30, i32 31, i32 80, i32 81, i32 82, i32 83, i32 84, i32 85, i32 86, i32 87, i32 88, i32 89, i32 90, i32 43, i32 44, i32 45, i32 46, i32 47, i32 96, i32 97, i32 98, i32 99, i32 100, i32 101, i32 102, i32 103, i32 104, i32 105, i32 106, i32 59, i32 60, i32 61, i32 62, i32 63, i32 112, i32 113, i32 114, i32 115, i32 116, i32 117, i32 118, i32 119, i32 120, i32 121, i32 122>
return _mm512_bslli_epi128(__A, 5);
}
@@ -1461,7 +1476,7 @@ __m512i test_mm512_maskz_srli_epi16(__mmask32 __U, __m512i __A) {
__m512i test_mm512_bsrli_epi128(__m512i __A) {
// CHECK-LABEL: @test_mm512_bsrli_epi128
- // CHECK: shufflevector <64 x i8> %{{.*}}, <64 x i8> %{{.*}}, <64 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 64, i32 65, i32 66, i32 67, i32 68, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 80, i32 81, i32 82, i32 83, i32 84, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 96, i32 97, i32 98, i32 99, i32 100, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63, i32 112, i32 113, i32 114, i32 115, i32 116>
+ // CHECK: shufflevector <64 x i8> %{{.*}}, <64 x i8> zeroinitializer, <64 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 64, i32 65, i32 66, i32 67, i32 68, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 80, i32 81, i32 82, i32 83, i32 84, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 96, i32 97, i32 98, i32 99, i32 100, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63, i32 112, i32 113, i32 114, i32 115, i32 116>
return _mm512_bsrli_epi128(__A, 5);
}
__m512i test_mm512_mask_mov_epi16(__m512i __W, __mmask32 __U, __m512i __A) {
@@ -1628,23 +1643,22 @@ __m512i test_mm512_maskz_set1_epi8(__mmask64 __M, char __A) {
__mmask64 test_mm512_kunpackd(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __m512i __E, __m512i __F) {
// CHECK-LABEL: @test_mm512_kunpackd
- // CHECK: bitcast <64 x i1> %{{.*}} to i64
- // CHECK: bitcast <64 x i1> %{{.*}} to i64
- // CHECK: and i64 %{{.*}}, 4294967295
- // CHECK: shl i64 %{{.*}}, 32
- // CHECK: or i64 %{{.*}}, %{{.*}}
- // CHECK: bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[LHS:%.*]] = bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[LHS2:%.*]] = shufflevector <64 x i1> [[LHS]], <64 x i1> [[LHS]], <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
+ // CHECK: [[RHS2:%.*]] = shufflevector <64 x i1> [[RHS]], <64 x i1> [[RHS]], <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
+ // CHECK: [[CONCAT:%.*]] = shufflevector <32 x i1> [[RHS2]], <32 x i1> [[LHS2]], <64 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63>
+ // CHECK: bitcast <64 x i1> [[CONCAT]] to i64
return _mm512_mask_cmpneq_epu8_mask(_mm512_kunpackd(_mm512_cmpneq_epu8_mask(__B, __A),_mm512_cmpneq_epu8_mask(__C, __D)), __E, __F);
}
__mmask32 test_mm512_kunpackw(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __m512i __E, __m512i __F) {
// CHECK-LABEL: @test_mm512_kunpackw
- // CHECK: bitcast <32 x i1> %{{.*}} to i32
- // CHECK: bitcast <32 x i1> %{{.*}} to i32
- // CHECK: and i32 %{{.*}}, 65535
- // CHECK: shl i32 %{{.*}}, 16
- // CHECK: or i32 %{{.*}}, %{{.*}}
- // CHECK: bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[LHS:%.*]] = bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[LHS2:%.*]] = shufflevector <32 x i1> [[LHS]], <32 x i1> [[LHS]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+ // CHECK: [[RHS2:%.*]] = shufflevector <32 x i1> [[RHS]], <32 x i1> [[RHS]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+ // CHECK: [[CONCAT:%.*]] = shufflevector <16 x i1> [[RHS2]], <16 x i1> [[LHS2]], <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
return _mm512_mask_cmpneq_epu16_mask(_mm512_kunpackw(_mm512_cmpneq_epu16_mask(__B, __A),_mm512_cmpneq_epu16_mask(__C, __D)), __E, __F);
}
@@ -1743,7 +1757,8 @@ __mmask32 test_mm512_mask_testn_epi16_mask(__mmask32 __U, __m512i __A, __m512i _
__mmask64 test_mm512_movepi8_mask(__m512i __A) {
// CHECK-LABEL: @test_mm512_movepi8_mask
- // CHECK: @llvm.x86.avx512.cvtb2mask.512
+ // CHECK: [[CMP:%.*]] = icmp slt <64 x i8> %{{.*}}, zeroinitializer
+ // CHECK: bitcast <64 x i1> [[CMP]] to i64
return _mm512_movepi8_mask(__A);
}
@@ -1763,40 +1778,40 @@ __m512i test_mm512_movm_epi16(__mmask32 __A) {
__m512i test_mm512_broadcastb_epi8(__m128i __A) {
// CHECK-LABEL: @test_mm512_broadcastb_epi8
- // CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> zeroinitializer, <64 x i32> zeroinitializer
+ // CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <64 x i32> zeroinitializer
return _mm512_broadcastb_epi8(__A);
}
__m512i test_mm512_mask_broadcastb_epi8(__m512i __O, __mmask64 __M, __m128i __A) {
// CHECK-LABEL: @test_mm512_mask_broadcastb_epi8
- // CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> zeroinitializer, <64 x i32> zeroinitializer
+ // CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <64 x i32> zeroinitializer
// CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}}
return _mm512_mask_broadcastb_epi8(__O, __M, __A);
}
__m512i test_mm512_maskz_broadcastb_epi8(__mmask64 __M, __m128i __A) {
// CHECK-LABEL: @test_mm512_maskz_broadcastb_epi8
- // CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> zeroinitializer, <64 x i32> zeroinitializer
+ // CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <64 x i32> zeroinitializer
// CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}}
return _mm512_maskz_broadcastb_epi8(__M, __A);
}
__m512i test_mm512_broadcastw_epi16(__m128i __A) {
// CHECK-LABEL: @test_mm512_broadcastw_epi16
- // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> zeroinitializer, <32 x i32> zeroinitializer
+ // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <32 x i32> zeroinitializer
return _mm512_broadcastw_epi16(__A);
}
__m512i test_mm512_mask_broadcastw_epi16(__m512i __O, __mmask32 __M, __m128i __A) {
// CHECK-LABEL: @test_mm512_mask_broadcastw_epi16
- // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> zeroinitializer, <32 x i32> zeroinitializer
+ // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <32 x i32> zeroinitializer
// CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_mask_broadcastw_epi16(__O, __M, __A);
}
__m512i test_mm512_maskz_broadcastw_epi16(__mmask32 __M, __m128i __A) {
// CHECK-LABEL: @test_mm512_maskz_broadcastw_epi16
- // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> zeroinitializer, <32 x i32> zeroinitializer
+ // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <32 x i32> zeroinitializer
// CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_maskz_broadcastw_epi16(__M, __A);
}
@@ -1878,19 +1893,21 @@ __m512i test_mm512_maskz_set1_epi16(__mmask32 __M, short __A) {
}
__m512i test_mm512_permutexvar_epi16(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_permutexvar_epi16
- // CHECK: @llvm.x86.avx512.mask.permvar.hi.512
+ // CHECK: @llvm.x86.avx512.permvar.hi.512
return _mm512_permutexvar_epi16(__A, __B);
}
__m512i test_mm512_maskz_permutexvar_epi16(__mmask32 __M, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_permutexvar_epi16
- // CHECK: @llvm.x86.avx512.mask.permvar.hi.512
+ // CHECK: @llvm.x86.avx512.permvar.hi.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_maskz_permutexvar_epi16(__M, __A, __B);
}
__m512i test_mm512_mask_permutexvar_epi16(__m512i __W, __mmask32 __M, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_permutexvar_epi16
- // CHECK: @llvm.x86.avx512.mask.permvar.hi.512
+ // CHECK: @llvm.x86.avx512.permvar.hi.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_mask_permutexvar_epi16(__W, __M, __A, __B);
}
__m512i test_mm512_alignr_epi8(__m512i __A,__m512i __B){
@@ -1917,19 +1934,21 @@ __m512i test_mm512_maskz_alignr_epi8(__mmask64 __U, __m512i __A,__m512i __B){
__m512i test_mm512_mm_dbsad_epu8(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mm_dbsad_epu8
- // CHECK: @llvm.x86.avx512.mask.dbpsadbw.512
+ // CHECK: @llvm.x86.avx512.dbpsadbw.512
return _mm512_dbsad_epu8(__A, __B, 170);
}
__m512i test_mm512_mm_mask_dbsad_epu8(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mm_mask_dbsad_epu8
- // CHECK: @llvm.x86.avx512.mask.dbpsadbw.512
+ // CHECK: @llvm.x86.avx512.dbpsadbw.512
+ //CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_mask_dbsad_epu8(__W, __U, __A, __B, 170);
}
__m512i test_mm512_mm_maskz_dbsad_epu8(__mmask32 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mm_maskz_dbsad_epu8
- // CHECK: @llvm.x86.avx512.mask.dbpsadbw.512
+ // CHECK: @llvm.x86.avx512.dbpsadbw.512
+ //CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_maskz_dbsad_epu8(__U, __A, __B, 170);
}
@@ -1941,7 +1960,8 @@ __m512i test_mm512_sad_epu8(__m512i __A, __m512i __B) {
__mmask32 test_mm512_movepi16_mask(__m512i __A) {
// CHECK-LABEL: @test_mm512_movepi16_mask
- // CHECK: @llvm.x86.avx512.cvtw2mask.512
+ // CHECK: [[CMP:%.*]] = icmp slt <32 x i16> %{{.*}}, zeroinitializer
+ // CHECK: bitcast <32 x i1> [[CMP]] to i32
return _mm512_movepi16_mask(__A);
}
diff --git a/test/CodeGen/avx512dq-builtins.c b/test/CodeGen/avx512dq-builtins.c
index 1b21ca3c4302..6ac3aff0aa3c 100644
--- a/test/CodeGen/avx512dq-builtins.c
+++ b/test/CodeGen/avx512dq-builtins.c
@@ -6,7 +6,7 @@
__m512i test_mm512_mullo_epi64 (__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mullo_epi64
// CHECK: mul <8 x i64>
- return (__m512i) ((__v8di) __A * (__v8di) __B);
+ return (__m512i) _mm512_mullo_epi64(__A, __B);
}
__m512i test_mm512_mask_mullo_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) {
@@ -347,19 +347,21 @@ __m512i test_mm512_maskz_cvt_roundps_epu64(__mmask8 __U, __m256 __A) {
__m512d test_mm512_cvtepi64_pd(__m512i __A) {
// CHECK-LABEL: @test_mm512_cvtepi64_pd
- // CHECK: @llvm.x86.avx512.mask.cvtqq2pd.512
+ // CHECK: sitofp <8 x i64> %{{.*}} to <8 x double>
return _mm512_cvtepi64_pd(__A);
}
__m512d test_mm512_mask_cvtepi64_pd(__m512d __W, __mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_cvtepi64_pd
- // CHECK: @llvm.x86.avx512.mask.cvtqq2pd.512
+ // CHECK: sitofp <8 x i64> %{{.*}} to <8 x double>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_cvtepi64_pd(__W, __U, __A);
}
__m512d test_mm512_maskz_cvtepi64_pd(__mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_cvtepi64_pd
- // CHECK: @llvm.x86.avx512.mask.cvtqq2pd.512
+ // CHECK: sitofp <8 x i64> %{{.*}} to <8 x double>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_maskz_cvtepi64_pd(__U, __A);
}
@@ -563,19 +565,21 @@ __m512i test_mm512_maskz_cvtt_roundps_epu64(__mmask8 __U, __m256 __A) {
__m512d test_mm512_cvtepu64_pd(__m512i __A) {
// CHECK-LABEL: @test_mm512_cvtepu64_pd
- // CHECK: @llvm.x86.avx512.mask.cvtuqq2pd.512
+ // CHECK: uitofp <8 x i64> %{{.*}} to <8 x double>
return _mm512_cvtepu64_pd(__A);
}
__m512d test_mm512_mask_cvtepu64_pd(__m512d __W, __mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_cvtepu64_pd
- // CHECK: @llvm.x86.avx512.mask.cvtuqq2pd.512
+ // CHECK: uitofp <8 x i64> %{{.*}} to <8 x double>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_cvtepu64_pd(__W, __U, __A);
}
__m512d test_mm512_maskz_cvtepu64_pd(__mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_cvtepu64_pd
- // CHECK: @llvm.x86.avx512.mask.cvtuqq2pd.512
+ // CHECK: uitofp <8 x i64> %{{.*}} to <8 x double>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_maskz_cvtepu64_pd(__U, __A);
}
@@ -687,13 +691,13 @@ __m128d test_mm512_maskz_range_round_sd(__mmask8 __U, __m128d __A, __m128d __B)
return _mm_maskz_range_round_sd(__U, __A, __B, 4, 8);
}
-__m128d test_mm512_range_round_ss(__m128d __A, __m128d __B) {
+__m128 test_mm512_range_round_ss(__m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm512_range_round_ss
// CHECK: @llvm.x86.avx512.mask.range.ss
return _mm_range_round_ss(__A, __B, 4, 8);
}
-__m128d test_mm512_mask_range_round_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
+__m128 test_mm512_mask_range_round_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm512_mask_range_round_ss
// CHECK: @llvm.x86.avx512.mask.range.ss
return _mm_mask_range_round_ss(__W, __U, __A, __B, 4, 8);
@@ -723,13 +727,13 @@ __m128d test_mm_maskz_range_sd(__mmask8 __U, __m128d __A, __m128d __B) {
return _mm_maskz_range_sd(__U, __A, __B, 4);
}
-__m128d test_mm_range_ss(__m128d __A, __m128d __B) {
+__m128 test_mm_range_ss(__m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_range_ss
// CHECK: @llvm.x86.avx512.mask.range.ss
return _mm_range_ss(__A, __B, 4);
}
-__m128d test_mm_mask_range_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
+__m128 test_mm_mask_range_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_mask_range_ss
// CHECK: @llvm.x86.avx512.mask.range.ss
return _mm_mask_range_ss(__W, __U, __A, __B, 4);
@@ -923,7 +927,8 @@ __m128d test_mm_maskz_reduce_round_sd(__mmask8 __U, __m128d __A, __m128d __B) {
__mmask16 test_mm512_movepi32_mask(__m512i __A) {
// CHECK-LABEL: @test_mm512_movepi32_mask
- // CHECK: @llvm.x86.avx512.cvtd2mask.512
+ // CHECK: [[CMP:%.*]] = icmp slt <16 x i32> %{{.*}}, zeroinitializer
+ // CHECK: bitcast <16 x i1> [[CMP]] to i16
return _mm512_movepi32_mask(__A);
}
@@ -943,26 +948,27 @@ __m512i test_mm512_movm_epi64(__mmask8 __A) {
__mmask8 test_mm512_movepi64_mask(__m512i __A) {
// CHECK-LABEL: @test_mm512_movepi64_mask
- // CHECK: @llvm.x86.avx512.cvtq2mask.512
+ // CHECK: [[CMP:%.*]] = icmp slt <8 x i64> %{{.*}}, zeroinitializer
+ // CHECK: bitcast <8 x i1> [[CMP]] to i8
return _mm512_movepi64_mask(__A);
}
__m512 test_mm512_broadcast_f32x2(__m128 __A) {
// CHECK-LABEL: @test_mm512_broadcast_f32x2
- // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> zeroinitializer, <16 x i32> <i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1>
+ // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <16 x i32> <i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1>
return _mm512_broadcast_f32x2(__A);
}
__m512 test_mm512_mask_broadcast_f32x2(__m512 __O, __mmask16 __M, __m128 __A) {
// CHECK-LABEL: @test_mm512_mask_broadcast_f32x2
- // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> zeroinitializer, <16 x i32> <i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1>
+ // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <16 x i32> <i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1>
// CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_broadcast_f32x2(__O, __M, __A);
}
__m512 test_mm512_maskz_broadcast_f32x2(__mmask16 __M, __m128 __A) {
// CHECK-LABEL: @test_mm512_maskz_broadcast_f32x2
- // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> zeroinitializer, <16 x i32> <i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1>
+ // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <16 x i32> <i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1>
// CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_maskz_broadcast_f32x2(__M, __A);
}
@@ -1009,20 +1015,20 @@ __m512d test_mm512_maskz_broadcast_f64x2(__mmask8 __M, double const* __A) {
__m512i test_mm512_broadcast_i32x2(__m128i __A) {
// CHECK-LABEL: @test_mm512_broadcast_i32x2
- // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> zeroinitializer, <16 x i32> <i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1>
+ // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <16 x i32> <i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1>
return _mm512_broadcast_i32x2(__A);
}
__m512i test_mm512_mask_broadcast_i32x2(__m512i __O, __mmask16 __M, __m128i __A) {
// CHECK-LABEL: @test_mm512_mask_broadcast_i32x2
- // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> zeroinitializer, <16 x i32> <i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1>
+ // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <16 x i32> <i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1>
// CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_broadcast_i32x2(__O, __M, __A);
}
__m512i test_mm512_maskz_broadcast_i32x2(__mmask16 __M, __m128i __A) {
// CHECK-LABEL: @test_mm512_maskz_broadcast_i32x2
- // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> zeroinitializer, <16 x i32> <i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1>
+ // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <16 x i32> <i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1>
// CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_broadcast_i32x2(__M, __A);
}
@@ -1069,80 +1075,80 @@ __m512i test_mm512_maskz_broadcast_i64x2(__mmask8 __M, __m128i const* __A) {
__m256 test_mm512_extractf32x8_ps(__m512 __A) {
// CHECK-LABEL: @test_mm512_extractf32x8_ps
- // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> zeroinitializer, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+ // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
return _mm512_extractf32x8_ps(__A, 1);
}
__m256 test_mm512_mask_extractf32x8_ps(__m256 __W, __mmask8 __U, __m512 __A) {
// CHECK-LABEL: @test_mm512_mask_extractf32x8_ps
- // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> zeroinitializer, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+ // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm512_mask_extractf32x8_ps(__W, __U, __A, 1);
}
__m256 test_mm512_maskz_extractf32x8_ps(__mmask8 __U, __m512 __A) {
// CHECK-LABEL: @test_mm512_maskz_extractf32x8_ps
- // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> zeroinitializer, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+ // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm512_maskz_extractf32x8_ps(__U, __A, 1);
}
__m128d test_mm512_extractf64x2_pd(__m512d __A) {
// CHECK-LABEL: @test_mm512_extractf64x2_pd
- // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> zeroinitializer, <2 x i32> <i32 6, i32 7>
+ // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <2 x i32> <i32 6, i32 7>
return _mm512_extractf64x2_pd(__A, 3);
}
__m128d test_mm512_mask_extractf64x2_pd(__m128d __W, __mmask8 __U, __m512d __A) {
// CHECK-LABEL: @test_mm512_mask_extractf64x2_pd
- // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> zeroinitializer, <2 x i32> <i32 6, i32 7>
+ // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <2 x i32> <i32 6, i32 7>
// CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm512_mask_extractf64x2_pd(__W, __U, __A, 3);
}
__m128d test_mm512_maskz_extractf64x2_pd(__mmask8 __U, __m512d __A) {
// CHECK-LABEL: @test_mm512_maskz_extractf64x2_pd
- // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> zeroinitializer, <2 x i32> <i32 6, i32 7>
+ // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <2 x i32> <i32 6, i32 7>
// CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm512_maskz_extractf64x2_pd(__U, __A, 3);
}
__m256i test_mm512_extracti32x8_epi32(__m512i __A) {
// CHECK-LABEL: @test_mm512_extracti32x8_epi32
- // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+ // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
return _mm512_extracti32x8_epi32(__A, 1);
}
__m256i test_mm512_mask_extracti32x8_epi32(__m256i __W, __mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_extracti32x8_epi32
- // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+ // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm512_mask_extracti32x8_epi32(__W, __U, __A, 1);
}
__m256i test_mm512_maskz_extracti32x8_epi32(__mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_extracti32x8_epi32
- // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+ // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm512_maskz_extracti32x8_epi32(__U, __A, 1);
}
__m128i test_mm512_extracti64x2_epi64(__m512i __A) {
// CHECK-LABEL: @test_mm512_extracti64x2_epi64
- // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> zeroinitializer, <2 x i32> <i32 6, i32 7>
+ // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <2 x i32> <i32 6, i32 7>
return _mm512_extracti64x2_epi64(__A, 3);
}
__m128i test_mm512_mask_extracti64x2_epi64(__m128i __W, __mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_extracti64x2_epi64
- // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> zeroinitializer, <2 x i32> <i32 6, i32 7>
+ // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <2 x i32> <i32 6, i32 7>
// CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm512_mask_extracti64x2_epi64(__W, __U, __A, 3);
}
__m128i test_mm512_maskz_extracti64x2_epi64(__mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_extracti64x2_epi64
- // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> zeroinitializer, <2 x i32> <i32 6, i32 7>
+ // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <2 x i32> <i32 6, i32 7>
// CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm512_maskz_extracti64x2_epi64(__U, __A, 3);
}
@@ -1228,35 +1234,35 @@ __m512i test_mm512_maskz_inserti64x2(__mmask8 __U, __m512i __A, __m128i __B) {
}
__mmask8 test_mm512_mask_fpclass_pd_mask(__mmask8 __U, __m512d __A) {
// CHECK-LABEL: @test_mm512_mask_fpclass_pd_mask
- // CHECK: @llvm.x86.avx512.mask.fpclass.pd.512
+ // CHECK: @llvm.x86.avx512.fpclass.pd.512
return _mm512_mask_fpclass_pd_mask(__U, __A, 4);
}
__mmask8 test_mm512_fpclass_pd_mask(__m512d __A) {
// CHECK-LABEL: @test_mm512_fpclass_pd_mask
- // CHECK: @llvm.x86.avx512.mask.fpclass.pd.512
+ // CHECK: @llvm.x86.avx512.fpclass.pd.512
return _mm512_fpclass_pd_mask(__A, 4);
}
__mmask16 test_mm512_mask_fpclass_ps_mask(__mmask16 __U, __m512 __A) {
// CHECK-LABEL: @test_mm512_mask_fpclass_ps_mask
- // CHECK: @llvm.x86.avx512.mask.fpclass.ps.512
+ // CHECK: @llvm.x86.avx512.fpclass.ps.512
return _mm512_mask_fpclass_ps_mask(__U, __A, 4);
}
__mmask16 test_mm512_fpclass_ps_mask(__m512 __A) {
// CHECK-LABEL: @test_mm512_fpclass_ps_mask
- // CHECK: @llvm.x86.avx512.mask.fpclass.ps.512
+ // CHECK: @llvm.x86.avx512.fpclass.ps.512
return _mm512_fpclass_ps_mask(__A, 4);
}
-__mmask8 test_mm_fpclass_sd_mask(__m128 __A) {
+__mmask8 test_mm_fpclass_sd_mask(__m128d __A) {
// CHECK-LABEL: @test_mm_fpclass_sd_mask
// CHECK: @llvm.x86.avx512.mask.fpclass.sd
return _mm_fpclass_sd_mask (__A, 2);
}
-__mmask8 test_mm_mask_fpclass_sd_mask(__mmask8 __U, __m128 __A) {
+__mmask8 test_mm_mask_fpclass_sd_mask(__mmask8 __U, __m128d __A) {
// CHECK-LABEL: @test_mm_mask_fpclass_sd_mask
// CHECK: @llvm.x86.avx512.mask.fpclass.sd
return _mm_mask_fpclass_sd_mask (__U, __A, 2);
diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c
index ce831d690ee7..17cbc62d6149 100644
--- a/test/CodeGen/avx512f-builtins.c
+++ b/test/CodeGen/avx512f-builtins.c
@@ -5,85 +5,101 @@
__m512d test_mm512_sqrt_pd(__m512d a)
{
// CHECK-LABEL: @test_mm512_sqrt_pd
- // CHECK: @llvm.x86.avx512.mask.sqrt.pd.512
+ // CHECK: call <8 x double> @llvm.sqrt.v8f64(<8 x double> %{{.*}})
return _mm512_sqrt_pd(a);
}
__m512d test_mm512_mask_sqrt_pd (__m512d __W, __mmask8 __U, __m512d __A)
{
// CHECK-LABEL: @test_mm512_mask_sqrt_pd
- // CHECK: @llvm.x86.avx512.mask.sqrt.pd.512
+ // CHECK: call <8 x double> @llvm.sqrt.v8f64(<8 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_sqrt_pd (__W,__U,__A);
}
__m512d test_mm512_maskz_sqrt_pd (__mmask8 __U, __m512d __A)
{
// CHECK-LABEL: @test_mm512_maskz_sqrt_pd
- // CHECK: @llvm.x86.avx512.mask.sqrt.pd.512
+ // CHECK: call <8 x double> @llvm.sqrt.v8f64(<8 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> {{.*}}
return _mm512_maskz_sqrt_pd (__U,__A);
}
__m512d test_mm512_mask_sqrt_round_pd(__m512d __W,__mmask8 __U,__m512d __A)
{
// CHECK-LABEL: @test_mm512_mask_sqrt_round_pd
- // CHECK: @llvm.x86.avx512.mask.sqrt.pd.512
- return _mm512_mask_sqrt_round_pd(__W,__U,__A,_MM_FROUND_CUR_DIRECTION);
+ // CHECK: call <8 x double> @llvm.x86.avx512.sqrt.pd.512(<8 x double> %{{.*}}, i32 8)
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
+ return _mm512_mask_sqrt_round_pd(__W,__U,__A,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_maskz_sqrt_round_pd(__mmask8 __U,__m512d __A)
{
// CHECK-LABEL: @test_mm512_maskz_sqrt_round_pd
- // CHECK: @llvm.x86.avx512.mask.sqrt.pd.512
- return _mm512_maskz_sqrt_round_pd(__U,__A,_MM_FROUND_CUR_DIRECTION);
+ // CHECK: call <8 x double> @llvm.x86.avx512.sqrt.pd.512(<8 x double> %{{.*}}, i32 8)
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> {{.*}}
+ return _mm512_maskz_sqrt_round_pd(__U,__A,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_sqrt_round_pd(__m512d __A)
{
// CHECK-LABEL: @test_mm512_sqrt_round_pd
- // CHECK: @llvm.x86.avx512.mask.sqrt.pd.512
- return _mm512_sqrt_round_pd(__A,_MM_FROUND_CUR_DIRECTION);
+ // CHECK: call <8 x double> @llvm.x86.avx512.sqrt.pd.512(<8 x double> %{{.*}}, i32 8)
+ return _mm512_sqrt_round_pd(__A,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_sqrt_ps(__m512 a)
{
// CHECK-LABEL: @test_mm512_sqrt_ps
- // CHECK: @llvm.x86.avx512.mask.sqrt.ps.512
+ // CHECK: call <16 x float> @llvm.sqrt.v16f32(<16 x float> %{{.*}})
return _mm512_sqrt_ps(a);
}
__m512 test_mm512_mask_sqrt_ps(__m512 __W, __mmask16 __U, __m512 __A)
{
// CHECK-LABEL: @test_mm512_mask_sqrt_ps
- // CHECK: @llvm.x86.avx512.mask.sqrt.ps.512
+ // CHECK: call <16 x float> @llvm.sqrt.v16f32(<16 x float> %{{.*}})
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_sqrt_ps( __W, __U, __A);
}
__m512 test_mm512_maskz_sqrt_ps( __mmask16 __U, __m512 __A)
{
// CHECK-LABEL: @test_mm512_maskz_sqrt_ps
- // CHECK: @llvm.x86.avx512.mask.sqrt.ps.512
+ // CHECK: call <16 x float> @llvm.sqrt.v16f32(<16 x float> %{{.*}})
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> {{.*}}
return _mm512_maskz_sqrt_ps(__U ,__A);
}
__m512 test_mm512_mask_sqrt_round_ps(__m512 __W,__mmask16 __U,__m512 __A)
{
// CHECK-LABEL: @test_mm512_mask_sqrt_round_ps
- // CHECK: @llvm.x86.avx512.mask.sqrt.ps.512
- return _mm512_mask_sqrt_round_ps(__W,__U,__A,_MM_FROUND_CUR_DIRECTION);
+ // CHECK: call <16 x float> @llvm.x86.avx512.sqrt.ps.512(<16 x float> %{{.*}}, i32 8)
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
+ return _mm512_mask_sqrt_round_ps(__W,__U,__A,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_maskz_sqrt_round_ps(__mmask16 __U,__m512 __A)
{
// CHECK-LABEL: @test_mm512_maskz_sqrt_round_ps
- // CHECK: @llvm.x86.avx512.mask.sqrt.ps.512
- return _mm512_maskz_sqrt_round_ps(__U,__A,_MM_FROUND_CUR_DIRECTION);
+ // CHECK: call <16 x float> @llvm.x86.avx512.sqrt.ps.512(<16 x float> %{{.*}}, i32 8)
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> {{.*}}
+ return _mm512_maskz_sqrt_round_ps(__U,__A,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_sqrt_round_ps(__m512 __A)
{
// CHECK-LABEL: @test_mm512_sqrt_round_ps
- // CHECK: @llvm.x86.avx512.mask.sqrt.ps.512
- return _mm512_sqrt_round_ps(__A,_MM_FROUND_CUR_DIRECTION);
+ // CHECK: call <16 x float> @llvm.x86.avx512.sqrt.ps.512(<16 x float> %{{.*}}, i32 8)
+ return _mm512_sqrt_round_ps(__A,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_rsqrt14_pd(__m512d a)
@@ -159,7 +175,7 @@ __m512d test_mm512_mul_pd(__m512d a, __m512d b)
void test_mm512_storeu_si512 (void *__P, __m512i __A)
{
// CHECK-LABEL: @test_mm512_storeu_si512
- // CHECK: store <16 x i32> %{{.*}}, <16 x i32>* %{{.*}}, align 1{{$}}
+ // CHECK: store <8 x i64> %{{.*}}, <8 x i64>* %{{.*}}, align 1{{$}}
// CHECK-NEXT: ret void
_mm512_storeu_si512 ( __P,__A);
}
@@ -253,7 +269,7 @@ void test_mm512_mask_storeu_epi64(void *__P, __mmask8 __U, __m512i __A) {
__m512i test_mm512_loadu_si512 (void *__P)
{
// CHECK-LABEL: @test_mm512_loadu_si512
- // CHECK: load <16 x i32>, <16 x i32>* %{{.*}}, align 1{{$}}
+ // CHECK: load <8 x i64>, <8 x i64>* %{{.*}}, align 1{{$}}
return _mm512_loadu_si512 ( __P);
}
@@ -439,483 +455,745 @@ __m512i test_mm512_maskz_alignr_epi64( __mmask8 u, __m512i a, __m512i b)
__m512d test_mm512_fmadd_round_pd(__m512d __A, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_fmadd_round_pd
- // CHECK: @llvm.x86.avx512.mask.vfmadd.pd.512
+ // CHECK: @llvm.x86.avx512.vfmadd.pd.512
return _mm512_fmadd_round_pd(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_mask_fmadd_round_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_mask_fmadd_round_pd
- // CHECK: @llvm.x86.avx512.mask.vfmadd.pd.512
+ // CHECK: @llvm.x86.avx512.vfmadd.pd.512
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_fmadd_round_pd(__A, __U, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_mask3_fmadd_round_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm512_mask3_fmadd_round_pd
- // CHECK: @llvm.x86.avx512.mask3.vfmadd.pd.512
+ // CHECK: @llvm.x86.avx512.vfmadd.pd.512
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask3_fmadd_round_pd(__A, __B, __C, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_maskz_fmadd_round_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_maskz_fmadd_round_pd
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.pd.512
+ // CHECK: @llvm.x86.avx512.vfmadd.pd.512
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> zeroinitializer
return _mm512_maskz_fmadd_round_pd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_fmsub_round_pd(__m512d __A, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_fmsub_round_pd
- // CHECK: @llvm.x86.avx512.mask.vfmadd.pd.512
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>
+ // CHECK: @llvm.x86.avx512.vfmadd.pd.512
return _mm512_fmsub_round_pd(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_mask_fmsub_round_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_mask_fmsub_round_pd
- // CHECK: @llvm.x86.avx512.mask.vfmadd.pd.512
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>
+ // CHECK: @llvm.x86.avx512.vfmadd.pd.512
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_fmsub_round_pd(__A, __U, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_maskz_fmsub_round_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_maskz_fmsub_round_pd
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.pd.512
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>
+ // CHECK: @llvm.x86.avx512.vfmadd.pd.512
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> zeroinitializer
return _mm512_maskz_fmsub_round_pd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_fnmadd_round_pd(__m512d __A, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_fnmadd_round_pd
- // CHECK: @llvm.x86.avx512.mask.vfmadd.pd.512
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>
+ // CHECK: @llvm.x86.avx512.vfmadd.pd.512
return _mm512_fnmadd_round_pd(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_mask3_fnmadd_round_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm512_mask3_fnmadd_round_pd
- // CHECK: @llvm.x86.avx512.mask3.vfmadd.pd.512
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>
+ // CHECK: @llvm.x86.avx512.vfmadd.pd.512
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask3_fnmadd_round_pd(__A, __B, __C, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_maskz_fnmadd_round_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_maskz_fnmadd_round_pd
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.pd.512
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>
+ // CHECK: @llvm.x86.avx512.vfmadd.pd.512
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> zeroinitializer
return _mm512_maskz_fnmadd_round_pd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_fnmsub_round_pd(__m512d __A, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_fnmsub_round_pd
- // CHECK: @llvm.x86.avx512.mask.vfmadd.pd.512
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>
+ // CHECK: @llvm.x86.avx512.vfmadd.pd.512
return _mm512_fnmsub_round_pd(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_maskz_fnmsub_round_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_maskz_fnmsub_round_pd
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.pd.512
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>
+ // CHECK: @llvm.x86.avx512.vfmadd.pd.512
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> zeroinitializer
return _mm512_maskz_fnmsub_round_pd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_fmadd_pd(__m512d __A, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_fmadd_pd
- // CHECK: @llvm.x86.avx512.mask.vfmadd.pd.512
+ // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}})
return _mm512_fmadd_pd(__A, __B, __C);
}
__m512d test_mm512_mask_fmadd_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_mask_fmadd_pd
- // CHECK: @llvm.x86.avx512.mask.vfmadd.pd.512
+ // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_fmadd_pd(__A, __U, __B, __C);
}
__m512d test_mm512_mask3_fmadd_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm512_mask3_fmadd_pd
- // CHECK: @llvm.x86.avx512.mask3.vfmadd.pd.512
+ // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask3_fmadd_pd(__A, __B, __C, __U);
}
__m512d test_mm512_maskz_fmadd_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_maskz_fmadd_pd
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.pd.512
+ // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> zeroinitializer
return _mm512_maskz_fmadd_pd(__U, __A, __B, __C);
}
__m512d test_mm512_fmsub_pd(__m512d __A, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_fmsub_pd
- // CHECK: @llvm.x86.avx512.mask.vfmadd.pd.512
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}})
return _mm512_fmsub_pd(__A, __B, __C);
}
__m512d test_mm512_mask_fmsub_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_mask_fmsub_pd
- // CHECK: @llvm.x86.avx512.mask.vfmadd.pd.512
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_fmsub_pd(__A, __U, __B, __C);
}
__m512d test_mm512_maskz_fmsub_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_maskz_fmsub_pd
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.pd.512
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> zeroinitializer
return _mm512_maskz_fmsub_pd(__U, __A, __B, __C);
}
__m512d test_mm512_fnmadd_pd(__m512d __A, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_fnmadd_pd
- // CHECK: @llvm.x86.avx512.mask.vfmadd.pd.512
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}})
return _mm512_fnmadd_pd(__A, __B, __C);
}
__m512d test_mm512_mask3_fnmadd_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm512_mask3_fnmadd_pd
- // CHECK: @llvm.x86.avx512.mask3.vfmadd.pd.512
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask3_fnmadd_pd(__A, __B, __C, __U);
}
__m512d test_mm512_maskz_fnmadd_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_maskz_fnmadd_pd
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.pd.512
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> zeroinitializer
return _mm512_maskz_fnmadd_pd(__U, __A, __B, __C);
}
__m512d test_mm512_fnmsub_pd(__m512d __A, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_fnmsub_pd
- // CHECK: @llvm.x86.avx512.mask.vfmadd.pd.512
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}})
return _mm512_fnmsub_pd(__A, __B, __C);
}
__m512d test_mm512_maskz_fnmsub_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_maskz_fnmsub_pd
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.pd.512
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> zeroinitializer
return _mm512_maskz_fnmsub_pd(__U, __A, __B, __C);
}
__m512 test_mm512_fmadd_round_ps(__m512 __A, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_fmadd_round_ps
- // CHECK: @llvm.x86.avx512.mask.vfmadd.ps.512
+ // CHECK: @llvm.x86.avx512.vfmadd.ps.512
return _mm512_fmadd_round_ps(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_mask_fmadd_round_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_mask_fmadd_round_ps
- // CHECK: @llvm.x86.avx512.mask.vfmadd.ps.512
+ // CHECK: @llvm.x86.avx512.vfmadd.ps.512
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_fmadd_round_ps(__A, __U, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_mask3_fmadd_round_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) {
// CHECK-LABEL: @test_mm512_mask3_fmadd_round_ps
- // CHECK: @llvm.x86.avx512.mask3.vfmadd.ps.512
+ // CHECK: @llvm.x86.avx512.vfmadd.ps.512
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask3_fmadd_round_ps(__A, __B, __C, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_maskz_fmadd_round_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_maskz_fmadd_round_ps
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.ps.512
+ // CHECK: @llvm.x86.avx512.vfmadd.ps.512
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> zeroinitializer
return _mm512_maskz_fmadd_round_ps(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_fmsub_round_ps(__m512 __A, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_fmsub_round_ps
- // CHECK: @llvm.x86.avx512.mask.vfmadd.ps.512
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: @llvm.x86.avx512.vfmadd.ps.512
return _mm512_fmsub_round_ps(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_mask_fmsub_round_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_mask_fmsub_round_ps
- // CHECK: @llvm.x86.avx512.mask.vfmadd.ps.512
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: @llvm.x86.avx512.vfmadd.ps.512
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_fmsub_round_ps(__A, __U, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_maskz_fmsub_round_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_maskz_fmsub_round_ps
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.ps.512
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: @llvm.x86.avx512.vfmadd.ps.512
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> zeroinitializer
return _mm512_maskz_fmsub_round_ps(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_fnmadd_round_ps(__m512 __A, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_fnmadd_round_ps
- // CHECK: @llvm.x86.avx512.mask.vfmadd.ps.512
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: @llvm.x86.avx512.vfmadd.ps.512
return _mm512_fnmadd_round_ps(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_mask3_fnmadd_round_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) {
// CHECK-LABEL: @test_mm512_mask3_fnmadd_round_ps
- // CHECK: @llvm.x86.avx512.mask3.vfmadd.ps.512
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: @llvm.x86.avx512.vfmadd.ps.512
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask3_fnmadd_round_ps(__A, __B, __C, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_maskz_fnmadd_round_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_maskz_fnmadd_round_ps
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.ps.512
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: @llvm.x86.avx512.vfmadd.ps.512
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> zeroinitializer
return _mm512_maskz_fnmadd_round_ps(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_fnmsub_round_ps(__m512 __A, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_fnmsub_round_ps
- // CHECK: @llvm.x86.avx512.mask.vfmadd.ps.512
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: @llvm.x86.avx512.vfmadd.ps.512
return _mm512_fnmsub_round_ps(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_maskz_fnmsub_round_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_maskz_fnmsub_round_ps
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.ps.512
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: @llvm.x86.avx512.vfmadd.ps.512
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> zeroinitializer
return _mm512_maskz_fnmsub_round_ps(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_fmadd_ps(__m512 __A, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_fmadd_ps
- // CHECK: @llvm.x86.avx512.mask.vfmadd.ps.512
+ // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}})
return _mm512_fmadd_ps(__A, __B, __C);
}
__m512 test_mm512_mask_fmadd_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_mask_fmadd_ps
- // CHECK: @llvm.x86.avx512.mask.vfmadd.ps.512
+ // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}})
return _mm512_mask_fmadd_ps(__A, __U, __B, __C);
}
__m512 test_mm512_mask3_fmadd_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) {
// CHECK-LABEL: @test_mm512_mask3_fmadd_ps
- // CHECK: @llvm.x86.avx512.mask3.vfmadd.ps.512
+ // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}})
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask3_fmadd_ps(__A, __B, __C, __U);
}
__m512 test_mm512_maskz_fmadd_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_maskz_fmadd_ps
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.ps.512
+ // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}})
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> zeroinitializer
return _mm512_maskz_fmadd_ps(__U, __A, __B, __C);
}
__m512 test_mm512_fmsub_ps(__m512 __A, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_fmsub_ps
- // CHECK: @llvm.x86.avx512.mask.vfmadd.ps.512
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}})
return _mm512_fmsub_ps(__A, __B, __C);
}
__m512 test_mm512_mask_fmsub_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_mask_fmsub_ps
- // CHECK: @llvm.x86.avx512.mask.vfmadd.ps.512
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}})
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_fmsub_ps(__A, __U, __B, __C);
}
__m512 test_mm512_maskz_fmsub_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_maskz_fmsub_ps
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.ps.512
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}})
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> zeroinitializer
return _mm512_maskz_fmsub_ps(__U, __A, __B, __C);
}
__m512 test_mm512_fnmadd_ps(__m512 __A, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_fnmadd_ps
- // CHECK: @llvm.x86.avx512.mask.vfmadd.ps.512
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}})
return _mm512_fnmadd_ps(__A, __B, __C);
}
__m512 test_mm512_mask3_fnmadd_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) {
// CHECK-LABEL: @test_mm512_mask3_fnmadd_ps
- // CHECK: @llvm.x86.avx512.mask3.vfmadd.ps.512
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}})
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask3_fnmadd_ps(__A, __B, __C, __U);
}
__m512 test_mm512_maskz_fnmadd_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_maskz_fnmadd_ps
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.ps.512
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}})
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> zeroinitializer
return _mm512_maskz_fnmadd_ps(__U, __A, __B, __C);
}
__m512 test_mm512_fnmsub_ps(__m512 __A, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_fnmsub_ps
- // CHECK: @llvm.x86.avx512.mask.vfmadd.ps.512
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}})
return _mm512_fnmsub_ps(__A, __B, __C);
}
__m512 test_mm512_maskz_fnmsub_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_maskz_fnmsub_ps
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.ps.512
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}})
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> zeroinitializer
return _mm512_maskz_fnmsub_ps(__U, __A, __B, __C);
}
__m512d test_mm512_fmaddsub_round_pd(__m512d __A, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_fmaddsub_round_pd
- // CHECK: @llvm.x86.avx512.mask.vfmaddsub.pd.512
+ // CHECK: @llvm.x86.avx512.vfmaddsub.pd.512
return _mm512_fmaddsub_round_pd(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_mask_fmaddsub_round_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_mask_fmaddsub_round_pd
- // CHECK: @llvm.x86.avx512.mask.vfmaddsub.pd.512
+ // CHECK: @llvm.x86.avx512.vfmaddsub.pd.512
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_fmaddsub_round_pd(__A, __U, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_mask3_fmaddsub_round_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm512_mask3_fmaddsub_round_pd
- // CHECK: @llvm.x86.avx512.mask3.vfmaddsub.pd.512
+ // CHECK: @llvm.x86.avx512.vfmaddsub.pd.512
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask3_fmaddsub_round_pd(__A, __B, __C, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_maskz_fmaddsub_round_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_maskz_fmaddsub_round_pd
- // CHECK: @llvm.x86.avx512.maskz.vfmaddsub.pd.512
+ // CHECK: @llvm.x86.avx512.vfmaddsub.pd.512
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> zeroinitializer
return _mm512_maskz_fmaddsub_round_pd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_fmsubadd_round_pd(__m512d __A, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_fmsubadd_round_pd
- // CHECK: @llvm.x86.avx512.mask.vfmaddsub.pd.512
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: @llvm.x86.avx512.vfmaddsub.pd.512
return _mm512_fmsubadd_round_pd(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_mask_fmsubadd_round_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_mask_fmsubadd_round_pd
- // CHECK: @llvm.x86.avx512.mask.vfmaddsub.pd.512
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: @llvm.x86.avx512.vfmaddsub.pd.512
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_fmsubadd_round_pd(__A, __U, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_maskz_fmsubadd_round_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_maskz_fmsubadd_round_pd
- // CHECK: @llvm.x86.avx512.maskz.vfmaddsub.pd.512
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: @llvm.x86.avx512.vfmaddsub.pd.512
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> zeroinitializer
return _mm512_maskz_fmsubadd_round_pd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_fmaddsub_pd(__m512d __A, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_fmaddsub_pd
- // CHECK: @llvm.x86.avx512.mask.vfmaddsub.pd.512
+ // CHECK: [[ADD:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}})
+ // CHECK: [[NEG:%.+]] = fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: [[SUB:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> [[NEG]]
+ // CHECK: shufflevector <8 x double> [[SUB]], <8 x double> [[ADD]], <8 x i32> <i32 0, i32 9, i32 2, i32 11, i32 4, i32 13, i32 6, i32 15>
return _mm512_fmaddsub_pd(__A, __B, __C);
}
__m512d test_mm512_mask_fmaddsub_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_mask_fmaddsub_pd
- // CHECK: @llvm.x86.avx512.mask.vfmaddsub.pd.512
+ // CHECK: [[ADD:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}})
+ // CHECK: [[NEG:%.+]] = fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: [[SUB:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> [[NEG]]
+ // CHECK: shufflevector <8 x double> [[SUB]], <8 x double> [[ADD]], <8 x i32> <i32 0, i32 9, i32 2, i32 11, i32 4, i32 13, i32 6, i32 15>
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_fmaddsub_pd(__A, __U, __B, __C);
}
__m512d test_mm512_mask3_fmaddsub_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm512_mask3_fmaddsub_pd
- // CHECK: @llvm.x86.avx512.mask3.vfmaddsub.pd.512
+ // CHECK: [[ADD:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}})
+ // CHECK: [[NEG:%.+]] = fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: [[SUB:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> [[NEG]]
+ // CHECK: shufflevector <8 x double> [[SUB]], <8 x double> [[ADD]], <8 x i32> <i32 0, i32 9, i32 2, i32 11, i32 4, i32 13, i32 6, i32 15>
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask3_fmaddsub_pd(__A, __B, __C, __U);
}
__m512d test_mm512_maskz_fmaddsub_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_maskz_fmaddsub_pd
- // CHECK: @llvm.x86.avx512.maskz.vfmaddsub.pd.512
+ // CHECK: [[ADD:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}})
+ // CHECK: [[NEG:%.+]] = fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: [[SUB:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> [[NEG]]
+ // CHECK: shufflevector <8 x double> [[SUB]], <8 x double> [[ADD]], <8 x i32> <i32 0, i32 9, i32 2, i32 11, i32 4, i32 13, i32 6, i32 15>
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> zeroinitializer
return _mm512_maskz_fmaddsub_pd(__U, __A, __B, __C);
}
__m512d test_mm512_fmsubadd_pd(__m512d __A, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_fmsubadd_pd
- // CHECK: @llvm.x86.avx512.mask.vfmaddsub.pd.512
+ // CHECK: [[NEG:%.+]] = fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: [[SUB:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> [[NEG]]
+ // CHECK: [[ADD:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}})
+ // CHECK: shufflevector <8 x double> [[ADD]], <8 x double> [[SUB]], <8 x i32> <i32 0, i32 9, i32 2, i32 11, i32 4, i32 13, i32 6, i32 15>
return _mm512_fmsubadd_pd(__A, __B, __C);
}
__m512d test_mm512_mask_fmsubadd_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_mask_fmsubadd_pd
- // CHECK: @llvm.x86.avx512.mask.vfmaddsub.pd.512
+ // CHECK: [[NEG:%.+]] = fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: [[SUB:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> [[NEG]]
+ // CHECK: [[ADD:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}})
+ // CHECK: shufflevector <8 x double> [[ADD]], <8 x double> [[SUB]], <8 x i32> <i32 0, i32 9, i32 2, i32 11, i32 4, i32 13, i32 6, i32 15>
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_fmsubadd_pd(__A, __U, __B, __C);
}
__m512d test_mm512_maskz_fmsubadd_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_maskz_fmsubadd_pd
- // CHECK: @llvm.x86.avx512.maskz.vfmaddsub.pd.512
+ // CHECK: [[NEG:%.+]] = fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: [[SUB:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> [[NEG]]
+ // CHECK: [[ADD:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}})
+ // CHECK: shufflevector <8 x double> [[ADD]], <8 x double> [[SUB]], <8 x i32> <i32 0, i32 9, i32 2, i32 11, i32 4, i32 13, i32 6, i32 15>
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> zeroinitializer
return _mm512_maskz_fmsubadd_pd(__U, __A, __B, __C);
}
__m512 test_mm512_fmaddsub_round_ps(__m512 __A, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_fmaddsub_round_ps
- // CHECK: @llvm.x86.avx512.mask.vfmaddsub.ps.512
+ // CHECK: @llvm.x86.avx512.vfmaddsub.ps.512
return _mm512_fmaddsub_round_ps(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_mask_fmaddsub_round_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_mask_fmaddsub_round_ps
- // CHECK: @llvm.x86.avx512.mask.vfmaddsub.ps.512
+ // CHECK: @llvm.x86.avx512.vfmaddsub.ps.512
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_fmaddsub_round_ps(__A, __U, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_mask3_fmaddsub_round_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) {
// CHECK-LABEL: @test_mm512_mask3_fmaddsub_round_ps
- // CHECK: @llvm.x86.avx512.mask3.vfmaddsub.ps.512
+ // CHECK: @llvm.x86.avx512.vfmaddsub.ps.512
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask3_fmaddsub_round_ps(__A, __B, __C, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_maskz_fmaddsub_round_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_maskz_fmaddsub_round_ps
- // CHECK: @llvm.x86.avx512.maskz.vfmaddsub.ps.512
+ // CHECK: @llvm.x86.avx512.vfmaddsub.ps.512
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> zeroinitializer
return _mm512_maskz_fmaddsub_round_ps(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_fmsubadd_round_ps(__m512 __A, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_fmsubadd_round_ps
- // CHECK: @llvm.x86.avx512.mask.vfmaddsub.ps.512
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: @llvm.x86.avx512.vfmaddsub.ps.512
return _mm512_fmsubadd_round_ps(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_mask_fmsubadd_round_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_mask_fmsubadd_round_ps
- // CHECK: @llvm.x86.avx512.mask.vfmaddsub.ps.512
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: @llvm.x86.avx512.vfmaddsub.ps.512
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_fmsubadd_round_ps(__A, __U, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_maskz_fmsubadd_round_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_maskz_fmsubadd_round_ps
- // CHECK: @llvm.x86.avx512.maskz.vfmaddsub.ps.512
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: @llvm.x86.avx512.vfmaddsub.ps.512
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> zeroinitializer
return _mm512_maskz_fmsubadd_round_ps(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_fmaddsub_ps(__m512 __A, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_fmaddsub_ps
- // CHECK: @llvm.x86.avx512.mask.vfmaddsub.ps.512
+ // CHECK: [[ADD:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}})
+ // CHECK: [[NEG:%.+]] = fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[SUB:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> [[NEG]]
+ // CHECK: shufflevector <16 x float> [[SUB]], <16 x float> [[ADD]], <16 x i32> <i32 0, i32 17, i32 2, i32 19, i32 4, i32 21, i32 6, i32 23, i32 8, i32 25, i32 10, i32 27, i32 12, i32 29, i32 14, i32 31>
return _mm512_fmaddsub_ps(__A, __B, __C);
}
__m512 test_mm512_mask_fmaddsub_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_mask_fmaddsub_ps
- // CHECK: @llvm.x86.avx512.mask.vfmaddsub.ps.512
+ // CHECK: [[ADD:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}})
+ // CHECK: [[NEG:%.+]] = fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[SUB:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> [[NEG]]
+ // CHECK: shufflevector <16 x float> [[SUB]], <16 x float> [[ADD]], <16 x i32> <i32 0, i32 17, i32 2, i32 19, i32 4, i32 21, i32 6, i32 23, i32 8, i32 25, i32 10, i32 27, i32 12, i32 29, i32 14, i32 31>
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_fmaddsub_ps(__A, __U, __B, __C);
}
__m512 test_mm512_mask3_fmaddsub_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) {
// CHECK-LABEL: @test_mm512_mask3_fmaddsub_ps
- // CHECK: @llvm.x86.avx512.mask3.vfmaddsub.ps.512
+ // CHECK: [[ADD:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}})
+ // CHECK: [[NEG:%.+]] = fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[SUB:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> [[NEG]]
+ // CHECK: shufflevector <16 x float> [[SUB]], <16 x float> [[ADD]], <16 x i32> <i32 0, i32 17, i32 2, i32 19, i32 4, i32 21, i32 6, i32 23, i32 8, i32 25, i32 10, i32 27, i32 12, i32 29, i32 14, i32 31>
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask3_fmaddsub_ps(__A, __B, __C, __U);
}
__m512 test_mm512_maskz_fmaddsub_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_maskz_fmaddsub_ps
- // CHECK: @llvm.x86.avx512.maskz.vfmaddsub.ps.512
+ // CHECK: [[ADD:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}})
+ // CHECK: [[NEG:%.+]] = fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[SUB:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> [[NEG]]
+ // CHECK: shufflevector <16 x float> [[SUB]], <16 x float> [[ADD]], <16 x i32> <i32 0, i32 17, i32 2, i32 19, i32 4, i32 21, i32 6, i32 23, i32 8, i32 25, i32 10, i32 27, i32 12, i32 29, i32 14, i32 31>
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> zeroinitializer
return _mm512_maskz_fmaddsub_ps(__U, __A, __B, __C);
}
__m512 test_mm512_fmsubadd_ps(__m512 __A, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_fmsubadd_ps
- // CHECK: @llvm.x86.avx512.mask.vfmaddsub.ps.512
+ // CHECK: [[NEG:%.+]] = fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[SUB:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> [[NEG]]
+ // CHECK: [[ADD:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}})
+ // CHECK: shufflevector <16 x float> [[ADD]], <16 x float> [[SUB]], <16 x i32> <i32 0, i32 17, i32 2, i32 19, i32 4, i32 21, i32 6, i32 23, i32 8, i32 25, i32 10, i32 27, i32 12, i32 29, i32 14, i32 31>
return _mm512_fmsubadd_ps(__A, __B, __C);
}
__m512 test_mm512_mask_fmsubadd_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_mask_fmsubadd_ps
- // CHECK: @llvm.x86.avx512.mask.vfmaddsub.ps.512
+ // CHECK: [[NEG:%.+]] = fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[SUB:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> [[NEG]]
+ // CHECK: [[ADD:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}})
+ // CHECK: shufflevector <16 x float> [[ADD]], <16 x float> [[SUB]], <16 x i32> <i32 0, i32 17, i32 2, i32 19, i32 4, i32 21, i32 6, i32 23, i32 8, i32 25, i32 10, i32 27, i32 12, i32 29, i32 14, i32 31>
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_fmsubadd_ps(__A, __U, __B, __C);
}
__m512 test_mm512_maskz_fmsubadd_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_maskz_fmsubadd_ps
- // CHECK: @llvm.x86.avx512.maskz.vfmaddsub.ps.512
+ // CHECK: [[NEG:%.+]] = fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[SUB:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> [[NEG]]
+ // CHECK: [[ADD:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}})
+ // CHECK: shufflevector <16 x float> [[ADD]], <16 x float> [[SUB]], <16 x i32> <i32 0, i32 17, i32 2, i32 19, i32 4, i32 21, i32 6, i32 23, i32 8, i32 25, i32 10, i32 27, i32 12, i32 29, i32 14, i32 31>
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> zeroinitializer
return _mm512_maskz_fmsubadd_ps(__U, __A, __B, __C);
}
__m512d test_mm512_mask3_fmsub_round_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm512_mask3_fmsub_round_pd
- // CHECK: @llvm.x86.avx512.mask3.vfmsub.pd.512
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>
+ // CHECK: @llvm.x86.avx512.vfmadd.pd.512
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask3_fmsub_round_pd(__A, __B, __C, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_mask3_fmsub_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm512_mask3_fmsub_pd
- // CHECK: @llvm.x86.avx512.mask3.vfmsub.pd.512
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask3_fmsub_pd(__A, __B, __C, __U);
}
__m512 test_mm512_mask3_fmsub_round_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) {
// CHECK-LABEL: @test_mm512_mask3_fmsub_round_ps
- // CHECK: @llvm.x86.avx512.mask3.vfmsub.ps.512
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: @llvm.x86.avx512.vfmadd.ps.512
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask3_fmsub_round_ps(__A, __B, __C, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_mask3_fmsub_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) {
// CHECK-LABEL: @test_mm512_mask3_fmsub_ps
- // CHECK: @llvm.x86.avx512.mask3.vfmsub.ps.512
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}})
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask3_fmsub_ps(__A, __B, __C, __U);
}
__m512d test_mm512_mask3_fmsubadd_round_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm512_mask3_fmsubadd_round_pd
- // CHECK: @llvm.x86.avx512.mask3.vfmsubadd.pd.512
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: @llvm.x86.avx512.vfmaddsub.pd.512
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask3_fmsubadd_round_pd(__A, __B, __C, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_mask3_fmsubadd_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm512_mask3_fmsubadd_pd
- // CHECK: @llvm.x86.avx512.mask3.vfmsubadd.pd.512
+ // CHECK: [[NEG:%.+]] = fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: [[SUB:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> [[NEG]]
+ // CHECK: [[ADD:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}})
+ // CHECK: shufflevector <8 x double> [[ADD]], <8 x double> [[SUB]], <8 x i32> <i32 0, i32 9, i32 2, i32 11, i32 4, i32 13, i32 6, i32 15>
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask3_fmsubadd_pd(__A, __B, __C, __U);
}
__m512 test_mm512_mask3_fmsubadd_round_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) {
// CHECK-LABEL: @test_mm512_mask3_fmsubadd_round_ps
- // CHECK: @llvm.x86.avx512.mask3.vfmsubadd.ps.512
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: @llvm.x86.avx512.vfmaddsub.ps.512
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask3_fmsubadd_round_ps(__A, __B, __C, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_mask3_fmsubadd_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) {
// CHECK-LABEL: @test_mm512_mask3_fmsubadd_ps
- // CHECK: @llvm.x86.avx512.mask3.vfmsubadd.ps.512
+ // CHECK: [[NEG:%.+]] = fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[SUB:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> [[NEG]]
+ // CHECK: [[ADD:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}})
+ // CHECK: shufflevector <16 x float> [[ADD]], <16 x float> [[SUB]], <16 x i32> <i32 0, i32 17, i32 2, i32 19, i32 4, i32 21, i32 6, i32 23, i32 8, i32 25, i32 10, i32 27, i32 12, i32 29, i32 14, i32 31>
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask3_fmsubadd_ps(__A, __B, __C, __U);
}
__m512d test_mm512_mask_fnmadd_round_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_mask_fnmadd_round_pd
- // CHECK: @llvm.x86.avx512.mask.vfnmadd.pd.512
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>
+ // CHECK: @llvm.x86.avx512.vfmadd.pd.512
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_fnmadd_round_pd(__A, __U, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_mask_fnmadd_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_mask_fnmadd_pd
- // CHECK: @llvm.x86.avx512.mask.vfnmadd.pd.512
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_fnmadd_pd(__A, __U, __B, __C);
}
__m512 test_mm512_mask_fnmadd_round_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_mask_fnmadd_round_ps
- // CHECK: @llvm.x86.avx512.mask.vfnmadd.ps.512
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: @llvm.x86.avx512.vfmadd.ps.512
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_fnmadd_round_ps(__A, __U, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_mask_fnmadd_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_mask_fnmadd_ps
- // CHECK: @llvm.x86.avx512.mask.vfnmadd.ps.512
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}})
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_fnmadd_ps(__A, __U, __B, __C);
}
__m512d test_mm512_mask_fnmsub_round_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_mask_fnmsub_round_pd
- // CHECK: @llvm.x86.avx512.mask.vfnmsub.pd.512
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>
+ // CHECK: @llvm.x86.avx512.vfmadd.pd.512
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_fnmsub_round_pd(__A, __U, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_mask3_fnmsub_round_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm512_mask3_fnmsub_round_pd
- // CHECK: @llvm.x86.avx512.mask3.vfnmsub.pd.512
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>
+ // CHECK: @llvm.x86.avx512.vfmadd.pd.512
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask3_fnmsub_round_pd(__A, __B, __C, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_mask_fnmsub_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) {
// CHECK-LABEL: @test_mm512_mask_fnmsub_pd
- // CHECK: @llvm.x86.avx512.mask.vfnmsub.pd.512
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_fnmsub_pd(__A, __U, __B, __C);
}
__m512d test_mm512_mask3_fnmsub_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm512_mask3_fnmsub_pd
- // CHECK: @llvm.x86.avx512.mask3.vfnmsub.pd.512
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: fsub <8 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask3_fnmsub_pd(__A, __B, __C, __U);
}
__m512 test_mm512_mask_fnmsub_round_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_mask_fnmsub_round_ps
- // CHECK: @llvm.x86.avx512.mask.vfnmsub.ps.512
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: @llvm.x86.avx512.vfmadd.ps.512
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_fnmsub_round_ps(__A, __U, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_mask3_fnmsub_round_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) {
// CHECK-LABEL: @test_mm512_mask3_fnmsub_round_ps
- // CHECK: @llvm.x86.avx512.mask3.vfnmsub.ps.512
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: @llvm.x86.avx512.vfmadd.ps.512
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask3_fnmsub_round_ps(__A, __B, __C, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_mask_fnmsub_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) {
// CHECK-LABEL: @test_mm512_mask_fnmsub_ps
- // CHECK: @llvm.x86.avx512.mask.vfnmsub.ps.512
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}})
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_fnmsub_ps(__A, __U, __B, __C);
}
__m512 test_mm512_mask3_fnmsub_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) {
// CHECK-LABEL: @test_mm512_mask3_fnmsub_ps
- // CHECK: @llvm.x86.avx512.mask3.vfnmsub.ps.512
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: fsub <16 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}})
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask3_fnmsub_ps(__A, __B, __C, __U);
}
@@ -1001,261 +1279,1094 @@ __m512 test_mm512_unpacklo_ps(__m512 a, __m512 b)
__mmask16 test_mm512_cmp_round_ps_mask(__m512 a, __m512 b) {
// CHECK-LABEL: @test_mm512_cmp_round_ps_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
+ // CHECK: fcmp oeq <16 x float> %{{.*}}, %{{.*}}
return _mm512_cmp_round_ps_mask(a, b, 0, _MM_FROUND_CUR_DIRECTION);
}
__mmask16 test_mm512_mask_cmp_round_ps_mask(__mmask16 m, __m512 a, __m512 b) {
// CHECK-LABEL: @test_mm512_mask_cmp_round_ps_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
+ // CHECK: [[CMP:%.*]] = fcmp oeq <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
return _mm512_mask_cmp_round_ps_mask(m, a, b, 0, _MM_FROUND_CUR_DIRECTION);
}
-__mmask16 test_mm512_cmp_ps_mask(__m512 a, __m512 b) {
- // CHECK-LABEL: @test_mm512_cmp_ps_mask
- // CHECKn: @llvm.x86.avx512.mask.cmp.ps.512
- return _mm512_cmp_ps_mask(a, b, 0);
+__mmask16 test_mm512_cmp_ps_mask_eq_oq(__m512 a, __m512 b) {
+ // CHECK-LABEL: @test_mm512_cmp_ps_mask_eq_oq
+ // CHECK: fcmp oeq <16 x float> %{{.*}}, %{{.*}}
+ return _mm512_cmp_ps_mask(a, b, _CMP_EQ_OQ);
+}
+
+__mmask16 test_mm512_cmp_ps_mask_lt_os(__m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_cmp_ps_mask_lt_os
+ // CHECK: fcmp olt <16 x float> %{{.*}}, %{{.*}}
+ return _mm512_cmp_ps_mask(a, b, _CMP_LT_OS);
+}
+
+__mmask16 test_mm512_cmp_ps_mask_le_os(__m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_cmp_ps_mask_le_os
+ // CHECK: fcmp ole <16 x float> %{{.*}}, %{{.*}}
+ return _mm512_cmp_ps_mask(a, b, _CMP_LE_OS);
+}
+
+__mmask16 test_mm512_cmp_ps_mask_unord_q(__m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_cmp_ps_mask_unord_q
+ // CHECK: fcmp uno <16 x float> %{{.*}}, %{{.*}}
+ return _mm512_cmp_ps_mask(a, b, _CMP_UNORD_Q);
+}
+
+__mmask16 test_mm512_cmp_ps_mask_neq_uq(__m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_cmp_ps_mask_neq_uq
+ // CHECK: fcmp une <16 x float> %{{.*}}, %{{.*}}
+ return _mm512_cmp_ps_mask(a, b, _CMP_NEQ_UQ);
+}
+
+__mmask16 test_mm512_cmp_ps_mask_nlt_us(__m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_cmp_ps_mask_nlt_us
+ // CHECK: fcmp uge <16 x float> %{{.*}}, %{{.*}}
+ return _mm512_cmp_ps_mask(a, b, _CMP_NLT_US);
+}
+
+__mmask16 test_mm512_cmp_ps_mask_nle_us(__m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_cmp_ps_mask_nle_us
+ // CHECK: fcmp ugt <16 x float> %{{.*}}, %{{.*}}
+ return _mm512_cmp_ps_mask(a, b, _CMP_NLE_US);
+}
+
+__mmask16 test_mm512_cmp_ps_mask_ord_q(__m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_cmp_ps_mask_ord_q
+ // CHECK: fcmp ord <16 x float> %{{.*}}, %{{.*}}
+ return _mm512_cmp_ps_mask(a, b, _CMP_ORD_Q);
+}
+
+__mmask16 test_mm512_cmp_ps_mask_eq_uq(__m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_cmp_ps_mask_eq_uq
+ // CHECK: fcmp ueq <16 x float> %{{.*}}, %{{.*}}
+ return _mm512_cmp_ps_mask(a, b, _CMP_EQ_UQ);
+}
+
+__mmask16 test_mm512_cmp_ps_mask_nge_us(__m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_cmp_ps_mask_nge_us
+ // CHECK: fcmp ult <16 x float> %{{.*}}, %{{.*}}
+ return _mm512_cmp_ps_mask(a, b, _CMP_NGE_US);
+}
+
+__mmask16 test_mm512_cmp_ps_mask_ngt_us(__m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_cmp_ps_mask_ngt_us
+ // CHECK: fcmp ule <16 x float> %{{.*}}, %{{.*}}
+ return _mm512_cmp_ps_mask(a, b, _CMP_NGT_US);
+}
+
+__mmask16 test_mm512_cmp_ps_mask_false_oq(__m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_cmp_ps_mask_false_oq
+ // CHECK: fcmp false <16 x float> %{{.*}}, %{{.*}}
+ return _mm512_cmp_ps_mask(a, b, _CMP_FALSE_OQ);
+}
+
+__mmask16 test_mm512_cmp_ps_mask_neq_oq(__m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_cmp_ps_mask_neq_oq
+ // CHECK: fcmp one <16 x float> %{{.*}}, %{{.*}}
+ return _mm512_cmp_ps_mask(a, b, _CMP_NEQ_OQ);
+}
+
+__mmask16 test_mm512_cmp_ps_mask_ge_os(__m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_cmp_ps_mask_ge_os
+ // CHECK: fcmp oge <16 x float> %{{.*}}, %{{.*}}
+ return _mm512_cmp_ps_mask(a, b, _CMP_GE_OS);
+}
+
+__mmask16 test_mm512_cmp_ps_mask_gt_os(__m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_cmp_ps_mask_gt_os
+ // CHECK: fcmp ogt <16 x float> %{{.*}}, %{{.*}}
+ return _mm512_cmp_ps_mask(a, b, _CMP_GT_OS);
+}
+
+__mmask16 test_mm512_cmp_ps_mask_true_uq(__m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_cmp_ps_mask_true_uq
+ // CHECK: fcmp true <16 x float> %{{.*}}, %{{.*}}
+ return _mm512_cmp_ps_mask(a, b, _CMP_TRUE_UQ);
+}
+
+__mmask16 test_mm512_cmp_ps_mask_eq_os(__m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_cmp_ps_mask_eq_os
+ // CHECK: fcmp oeq <16 x float> %{{.*}}, %{{.*}}
+ return _mm512_cmp_ps_mask(a, b, _CMP_EQ_OS);
+}
+
+__mmask16 test_mm512_cmp_ps_mask_lt_oq(__m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_cmp_ps_mask_lt_oq
+ // CHECK: fcmp olt <16 x float> %{{.*}}, %{{.*}}
+ return _mm512_cmp_ps_mask(a, b, _CMP_LT_OQ);
+}
+
+__mmask16 test_mm512_cmp_ps_mask_le_oq(__m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_cmp_ps_mask_le_oq
+ // CHECK: fcmp ole <16 x float> %{{.*}}, %{{.*}}
+ return _mm512_cmp_ps_mask(a, b, _CMP_LE_OQ);
}
-__mmask16 test_mm512_mask_cmp_ps_mask(__mmask16 m, __m512 a, __m512 b) {
- // CHECK-LABEL: @test_mm512_mask_cmp_ps_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
- return _mm512_mask_cmp_ps_mask(m, a, b, 0);
+__mmask16 test_mm512_cmp_ps_mask_unord_s(__m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_cmp_ps_mask_unord_s
+ // CHECK: fcmp uno <16 x float> %{{.*}}, %{{.*}}
+ return _mm512_cmp_ps_mask(a, b, _CMP_UNORD_S);
+}
+
+__mmask16 test_mm512_cmp_ps_mask_neq_us(__m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_cmp_ps_mask_neq_us
+ // CHECK: fcmp une <16 x float> %{{.*}}, %{{.*}}
+ return _mm512_cmp_ps_mask(a, b, _CMP_NEQ_US);
+}
+
+__mmask16 test_mm512_cmp_ps_mask_nlt_uq(__m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_cmp_ps_mask_nlt_uq
+ // CHECK: fcmp uge <16 x float> %{{.*}}, %{{.*}}
+ return _mm512_cmp_ps_mask(a, b, _CMP_NLT_UQ);
+}
+
+__mmask16 test_mm512_cmp_ps_mask_nle_uq(__m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_cmp_ps_mask_nle_uq
+ // CHECK: fcmp ugt <16 x float> %{{.*}}, %{{.*}}
+ return _mm512_cmp_ps_mask(a, b, _CMP_NLE_UQ);
+}
+
+__mmask16 test_mm512_cmp_ps_mask_ord_s(__m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_cmp_ps_mask_ord_s
+ // CHECK: fcmp ord <16 x float> %{{.*}}, %{{.*}}
+ return _mm512_cmp_ps_mask(a, b, _CMP_ORD_S);
+}
+
+__mmask16 test_mm512_cmp_ps_mask_eq_us(__m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_cmp_ps_mask_eq_us
+ // CHECK: fcmp ueq <16 x float> %{{.*}}, %{{.*}}
+ return _mm512_cmp_ps_mask(a, b, _CMP_EQ_US);
+}
+
+__mmask16 test_mm512_cmp_ps_mask_nge_uq(__m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_cmp_ps_mask_nge_uq
+ // CHECK: fcmp ult <16 x float> %{{.*}}, %{{.*}}
+ return _mm512_cmp_ps_mask(a, b, _CMP_NGE_UQ);
+}
+
+__mmask16 test_mm512_cmp_ps_mask_ngt_uq(__m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_cmp_ps_mask_ngt_uq
+ // CHECK: fcmp ule <16 x float> %{{.*}}, %{{.*}}
+ return _mm512_cmp_ps_mask(a, b, _CMP_NGT_UQ);
+}
+
+__mmask16 test_mm512_cmp_ps_mask_false_os(__m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_cmp_ps_mask_false_os
+ // CHECK: fcmp false <16 x float> %{{.*}}, %{{.*}}
+ return _mm512_cmp_ps_mask(a, b, _CMP_FALSE_OS);
+}
+
+__mmask16 test_mm512_cmp_ps_mask_neq_os(__m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_cmp_ps_mask_neq_os
+ // CHECK: fcmp one <16 x float> %{{.*}}, %{{.*}}
+ return _mm512_cmp_ps_mask(a, b, _CMP_NEQ_OS);
+}
+
+__mmask16 test_mm512_cmp_ps_mask_ge_oq(__m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_cmp_ps_mask_ge_oq
+ // CHECK: fcmp oge <16 x float> %{{.*}}, %{{.*}}
+ return _mm512_cmp_ps_mask(a, b, _CMP_GE_OQ);
+}
+
+__mmask16 test_mm512_cmp_ps_mask_gt_oq(__m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_cmp_ps_mask_gt_oq
+ // CHECK: fcmp ogt <16 x float> %{{.*}}, %{{.*}}
+ return _mm512_cmp_ps_mask(a, b, _CMP_GT_OQ);
+}
+
+__mmask16 test_mm512_cmp_ps_mask_true_us(__m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_cmp_ps_mask_true_us
+ // CHECK: fcmp true <16 x float> %{{.*}}, %{{.*}}
+ return _mm512_cmp_ps_mask(a, b, _CMP_TRUE_US);
+}
+
+__mmask16 test_mm512_mask_cmp_ps_mask_eq_oq(__mmask16 m, __m512 a, __m512 b) {
+ // CHECK-LABEL: @test_mm512_mask_cmp_ps_mask_eq_oq
+ // CHECK: [[CMP:%.*]] = fcmp oeq <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_EQ_OQ);
+}
+
+__mmask16 test_mm512_mask_cmp_ps_mask_lt_os(__mmask16 m, __m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_lt_os
+ // CHECK: [[CMP:%.*]] = fcmp olt <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_LT_OS);
+}
+
+__mmask16 test_mm512_mask_cmp_ps_mask_le_os(__mmask16 m, __m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_le_os
+ // CHECK: [[CMP:%.*]] = fcmp ole <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_LE_OS);
+}
+
+__mmask16 test_mm512_mask_cmp_ps_mask_unord_q(__mmask16 m, __m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_unord_q
+ // CHECK: [[CMP:%.*]] = fcmp uno <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_UNORD_Q);
+}
+
+__mmask16 test_mm512_mask_cmp_ps_mask_neq_uq(__mmask16 m, __m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_neq_uq
+ // CHECK: [[CMP:%.*]] = fcmp une <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_NEQ_UQ);
+}
+
+__mmask16 test_mm512_mask_cmp_ps_mask_nlt_us(__mmask16 m, __m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_nlt_us
+ // CHECK: [[CMP:%.*]] = fcmp uge <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_NLT_US);
+}
+
+__mmask16 test_mm512_mask_cmp_ps_mask_nle_us(__mmask16 m, __m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_nle_us
+ // CHECK: [[CMP:%.*]] = fcmp ugt <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_NLE_US);
+}
+
+__mmask16 test_mm512_mask_cmp_ps_mask_ord_q(__mmask16 m, __m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_ord_q
+ // CHECK: [[CMP:%.*]] = fcmp ord <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_ORD_Q);
+}
+
+__mmask16 test_mm512_mask_cmp_ps_mask_eq_uq(__mmask16 m, __m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_eq_uq
+ // CHECK: [[CMP:%.*]] = fcmp ueq <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_EQ_UQ);
+}
+
+__mmask16 test_mm512_mask_cmp_ps_mask_nge_us(__mmask16 m, __m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_nge_us
+ // CHECK: [[CMP:%.*]] = fcmp ult <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_NGE_US);
+}
+
+__mmask16 test_mm512_mask_cmp_ps_mask_ngt_us(__mmask16 m, __m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_ngt_us
+ // CHECK: [[CMP:%.*]] = fcmp ule <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_NGT_US);
+}
+
+__mmask16 test_mm512_mask_cmp_ps_mask_false_oq(__mmask16 m, __m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_false_oq
+ // CHECK: [[CMP:%.*]] = fcmp false <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_FALSE_OQ);
+}
+
+__mmask16 test_mm512_mask_cmp_ps_mask_neq_oq(__mmask16 m, __m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_neq_oq
+ // CHECK: [[CMP:%.*]] = fcmp one <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_NEQ_OQ);
+}
+
+__mmask16 test_mm512_mask_cmp_ps_mask_ge_os(__mmask16 m, __m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_ge_os
+ // CHECK: [[CMP:%.*]] = fcmp oge <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_GE_OS);
+}
+
+__mmask16 test_mm512_mask_cmp_ps_mask_gt_os(__mmask16 m, __m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_gt_os
+ // CHECK: [[CMP:%.*]] = fcmp ogt <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_GT_OS);
+}
+
+__mmask16 test_mm512_mask_cmp_ps_mask_true_uq(__mmask16 m, __m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_true_uq
+ // CHECK: [[CMP:%.*]] = fcmp true <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_TRUE_UQ);
+}
+
+__mmask16 test_mm512_mask_cmp_ps_mask_eq_os(__mmask16 m, __m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_eq_os
+ // CHECK: [[CMP:%.*]] = fcmp oeq <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_EQ_OS);
+}
+
+__mmask16 test_mm512_mask_cmp_ps_mask_lt_oq(__mmask16 m, __m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_lt_oq
+ // CHECK: [[CMP:%.*]] = fcmp olt <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_LT_OQ);
+}
+
+__mmask16 test_mm512_mask_cmp_ps_mask_le_oq(__mmask16 m, __m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_le_oq
+ // CHECK: [[CMP:%.*]] = fcmp ole <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_LE_OQ);
+}
+
+__mmask16 test_mm512_mask_cmp_ps_mask_unord_s(__mmask16 m, __m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_unord_s
+ // CHECK: [[CMP:%.*]] = fcmp uno <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_UNORD_S);
+}
+
+__mmask16 test_mm512_mask_cmp_ps_mask_neq_us(__mmask16 m, __m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_neq_us
+ // CHECK: [[CMP:%.*]] = fcmp une <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_NEQ_US);
+}
+
+__mmask16 test_mm512_mask_cmp_ps_mask_nlt_uq(__mmask16 m, __m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_nlt_uq
+ // CHECK: [[CMP:%.*]] = fcmp uge <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_NLT_UQ);
+}
+
+__mmask16 test_mm512_mask_cmp_ps_mask_nle_uq(__mmask16 m, __m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_nle_uq
+ // CHECK: [[CMP:%.*]] = fcmp ugt <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_NLE_UQ);
+}
+
+__mmask16 test_mm512_mask_cmp_ps_mask_ord_s(__mmask16 m, __m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_ord_s
+ // CHECK: [[CMP:%.*]] = fcmp ord <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_ORD_S);
+}
+
+__mmask16 test_mm512_mask_cmp_ps_mask_eq_us(__mmask16 m, __m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_eq_us
+ // CHECK: [[CMP:%.*]] = fcmp ueq <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_EQ_US);
+}
+
+__mmask16 test_mm512_mask_cmp_ps_mask_nge_uq(__mmask16 m, __m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_nge_uq
+ // CHECK: [[CMP:%.*]] = fcmp ult <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_NGE_UQ);
+}
+
+__mmask16 test_mm512_mask_cmp_ps_mask_ngt_uq(__mmask16 m, __m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_ngt_uq
+ // CHECK: [[CMP:%.*]] = fcmp ule <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_NGT_UQ);
+}
+
+__mmask16 test_mm512_mask_cmp_ps_mask_false_os(__mmask16 m, __m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_false_os
+ // CHECK: [[CMP:%.*]] = fcmp false <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_FALSE_OS);
+}
+
+__mmask16 test_mm512_mask_cmp_ps_mask_neq_os(__mmask16 m, __m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_neq_os
+ // CHECK: [[CMP:%.*]] = fcmp one <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_NEQ_OS);
+}
+
+__mmask16 test_mm512_mask_cmp_ps_mask_ge_oq(__mmask16 m, __m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_ge_oq
+ // CHECK: [[CMP:%.*]] = fcmp oge <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_GE_OQ);
+}
+
+__mmask16 test_mm512_mask_cmp_ps_mask_gt_oq(__mmask16 m, __m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_gt_oq
+ // CHECK: [[CMP:%.*]] = fcmp ogt <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_GT_OQ);
+}
+
+__mmask16 test_mm512_mask_cmp_ps_mask_true_us(__mmask16 m, __m512 a, __m512 b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_true_us
+ // CHECK: [[CMP:%.*]] = fcmp true <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_TRUE_US);
}
__mmask8 test_mm512_cmp_round_pd_mask(__m512d a, __m512d b) {
// CHECK-LABEL: @test_mm512_cmp_round_pd_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.pd.512
+ // CHECK: [[CMP:%.*]] = fcmp oeq <8 x double> %{{.*}}, %{{.*}}
return _mm512_cmp_round_pd_mask(a, b, 0, _MM_FROUND_CUR_DIRECTION);
}
__mmask8 test_mm512_mask_cmp_round_pd_mask(__mmask8 m, __m512d a, __m512d b) {
// CHECK-LABEL: @test_mm512_mask_cmp_round_pd_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.pd.512
+ // CHECK: [[CMP:%.*]] = fcmp oeq <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
return _mm512_mask_cmp_round_pd_mask(m, a, b, 0, _MM_FROUND_CUR_DIRECTION);
}
-__mmask8 test_mm512_cmp_pd_mask(__m512d a, __m512d b) {
- // CHECK-LABEL: @test_mm512_cmp_pd_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.pd.512
- return _mm512_cmp_pd_mask(a, b, 0);
+__mmask8 test_mm512_cmp_pd_mask_eq_oq(__m512d a, __m512d b) {
+ // CHECK-LABEL: @test_mm512_cmp_pd_mask_eq_oq
+ // CHECK: fcmp oeq <8 x double> %{{.*}}, %{{.*}}
+ return _mm512_cmp_pd_mask(a, b, _CMP_EQ_OQ);
+}
+
+__mmask8 test_mm512_cmp_pd_mask_lt_os(__m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_cmp_pd_mask_lt_os
+ // CHECK: fcmp olt <8 x double> %{{.*}}, %{{.*}}
+ return _mm512_cmp_pd_mask(a, b, _CMP_LT_OS);
+}
+
+__mmask8 test_mm512_cmp_pd_mask_le_os(__m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_cmp_pd_mask_le_os
+ // CHECK: fcmp ole <8 x double> %{{.*}}, %{{.*}}
+ return _mm512_cmp_pd_mask(a, b, _CMP_LE_OS);
+}
+
+__mmask8 test_mm512_cmp_pd_mask_unord_q(__m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_cmp_pd_mask_unord_q
+ // CHECK: fcmp uno <8 x double> %{{.*}}, %{{.*}}
+ return _mm512_cmp_pd_mask(a, b, _CMP_UNORD_Q);
+}
+
+__mmask8 test_mm512_cmp_pd_mask_neq_uq(__m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_cmp_pd_mask_neq_uq
+ // CHECK: fcmp une <8 x double> %{{.*}}, %{{.*}}
+ return _mm512_cmp_pd_mask(a, b, _CMP_NEQ_UQ);
+}
+
+__mmask8 test_mm512_cmp_pd_mask_nlt_us(__m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_cmp_pd_mask_nlt_us
+ // CHECK: fcmp uge <8 x double> %{{.*}}, %{{.*}}
+ return _mm512_cmp_pd_mask(a, b, _CMP_NLT_US);
+}
+
+__mmask8 test_mm512_cmp_pd_mask_nle_us(__m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_cmp_pd_mask_nle_us
+ // CHECK: fcmp ugt <8 x double> %{{.*}}, %{{.*}}
+ return _mm512_cmp_pd_mask(a, b, _CMP_NLE_US);
+}
+
+__mmask8 test_mm512_cmp_pd_mask_ord_q(__m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_cmp_pd_mask_ord_q
+ // CHECK: fcmp ord <8 x double> %{{.*}}, %{{.*}}
+ return _mm512_cmp_pd_mask(a, b, _CMP_ORD_Q);
+}
+
+__mmask8 test_mm512_cmp_pd_mask_eq_uq(__m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_cmp_pd_mask_eq_uq
+ // CHECK: fcmp ueq <8 x double> %{{.*}}, %{{.*}}
+ return _mm512_cmp_pd_mask(a, b, _CMP_EQ_UQ);
+}
+
+__mmask8 test_mm512_cmp_pd_mask_nge_us(__m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_cmp_pd_mask_nge_us
+ // CHECK: fcmp ult <8 x double> %{{.*}}, %{{.*}}
+ return _mm512_cmp_pd_mask(a, b, _CMP_NGE_US);
+}
+
+__mmask8 test_mm512_cmp_pd_mask_ngt_us(__m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_cmp_pd_mask_ngt_us
+ // CHECK: fcmp ule <8 x double> %{{.*}}, %{{.*}}
+ return _mm512_cmp_pd_mask(a, b, _CMP_NGT_US);
+}
+
+__mmask8 test_mm512_cmp_pd_mask_false_oq(__m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_cmp_pd_mask_false_oq
+ // CHECK: fcmp false <8 x double> %{{.*}}, %{{.*}}
+ return _mm512_cmp_pd_mask(a, b, _CMP_FALSE_OQ);
+}
+
+__mmask8 test_mm512_cmp_pd_mask_neq_oq(__m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_cmp_pd_mask_neq_oq
+ // CHECK: fcmp one <8 x double> %{{.*}}, %{{.*}}
+ return _mm512_cmp_pd_mask(a, b, _CMP_NEQ_OQ);
+}
+
+__mmask8 test_mm512_cmp_pd_mask_ge_os(__m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_cmp_pd_mask_ge_os
+ // CHECK: fcmp oge <8 x double> %{{.*}}, %{{.*}}
+ return _mm512_cmp_pd_mask(a, b, _CMP_GE_OS);
+}
+
+__mmask8 test_mm512_cmp_pd_mask_gt_os(__m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_cmp_pd_mask_gt_os
+ // CHECK: fcmp ogt <8 x double> %{{.*}}, %{{.*}}
+ return _mm512_cmp_pd_mask(a, b, _CMP_GT_OS);
+}
+
+__mmask8 test_mm512_cmp_pd_mask_true_uq(__m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_cmp_pd_mask_true_uq
+ // CHECK: fcmp true <8 x double> %{{.*}}, %{{.*}}
+ return _mm512_cmp_pd_mask(a, b, _CMP_TRUE_UQ);
+}
+
+__mmask8 test_mm512_cmp_pd_mask_eq_os(__m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_cmp_pd_mask_eq_os
+ // CHECK: fcmp oeq <8 x double> %{{.*}}, %{{.*}}
+ return _mm512_cmp_pd_mask(a, b, _CMP_EQ_OS);
+}
+
+__mmask8 test_mm512_cmp_pd_mask_lt_oq(__m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_cmp_pd_mask_lt_oq
+ // CHECK: fcmp olt <8 x double> %{{.*}}, %{{.*}}
+ return _mm512_cmp_pd_mask(a, b, _CMP_LT_OQ);
+}
+
+__mmask8 test_mm512_cmp_pd_mask_le_oq(__m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_cmp_pd_mask_le_oq
+ // CHECK: fcmp ole <8 x double> %{{.*}}, %{{.*}}
+ return _mm512_cmp_pd_mask(a, b, _CMP_LE_OQ);
+}
+
+__mmask8 test_mm512_cmp_pd_mask_unord_s(__m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_cmp_pd_mask_unord_s
+ // CHECK: fcmp uno <8 x double> %{{.*}}, %{{.*}}
+ return _mm512_cmp_pd_mask(a, b, _CMP_UNORD_S);
+}
+
+__mmask8 test_mm512_cmp_pd_mask_neq_us(__m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_cmp_pd_mask_neq_us
+ // CHECK: fcmp une <8 x double> %{{.*}}, %{{.*}}
+ return _mm512_cmp_pd_mask(a, b, _CMP_NEQ_US);
+}
+
+__mmask8 test_mm512_cmp_pd_mask_nlt_uq(__m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_cmp_pd_mask_nlt_uq
+ // CHECK: fcmp uge <8 x double> %{{.*}}, %{{.*}}
+ return _mm512_cmp_pd_mask(a, b, _CMP_NLT_UQ);
+}
+
+__mmask8 test_mm512_cmp_pd_mask_nle_uq(__m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_cmp_pd_mask_nle_uq
+ // CHECK: fcmp ugt <8 x double> %{{.*}}, %{{.*}}
+ return _mm512_cmp_pd_mask(a, b, _CMP_NLE_UQ);
+}
+
+__mmask8 test_mm512_cmp_pd_mask_ord_s(__m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_cmp_pd_mask_ord_s
+ // CHECK: fcmp ord <8 x double> %{{.*}}, %{{.*}}
+ return _mm512_cmp_pd_mask(a, b, _CMP_ORD_S);
+}
+
+__mmask8 test_mm512_cmp_pd_mask_eq_us(__m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_cmp_pd_mask_eq_us
+ // CHECK: fcmp ueq <8 x double> %{{.*}}, %{{.*}}
+ return _mm512_cmp_pd_mask(a, b, _CMP_EQ_US);
+}
+
+__mmask8 test_mm512_cmp_pd_mask_nge_uq(__m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_cmp_pd_mask_nge_uq
+ // CHECK: fcmp ult <8 x double> %{{.*}}, %{{.*}}
+ return _mm512_cmp_pd_mask(a, b, _CMP_NGE_UQ);
+}
+
+__mmask8 test_mm512_cmp_pd_mask_ngt_uq(__m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_cmp_pd_mask_ngt_uq
+ // CHECK: fcmp ule <8 x double> %{{.*}}, %{{.*}}
+ return _mm512_cmp_pd_mask(a, b, _CMP_NGT_UQ);
+}
+
+__mmask8 test_mm512_cmp_pd_mask_false_os(__m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_cmp_pd_mask_false_os
+ // CHECK: fcmp false <8 x double> %{{.*}}, %{{.*}}
+ return _mm512_cmp_pd_mask(a, b, _CMP_FALSE_OS);
+}
+
+__mmask8 test_mm512_cmp_pd_mask_neq_os(__m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_cmp_pd_mask_neq_os
+ // CHECK: fcmp one <8 x double> %{{.*}}, %{{.*}}
+ return _mm512_cmp_pd_mask(a, b, _CMP_NEQ_OS);
+}
+
+__mmask8 test_mm512_cmp_pd_mask_ge_oq(__m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_cmp_pd_mask_ge_oq
+ // CHECK: fcmp oge <8 x double> %{{.*}}, %{{.*}}
+ return _mm512_cmp_pd_mask(a, b, _CMP_GE_OQ);
+}
+
+__mmask8 test_mm512_cmp_pd_mask_gt_oq(__m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_cmp_pd_mask_gt_oq
+ // CHECK: fcmp ogt <8 x double> %{{.*}}, %{{.*}}
+ return _mm512_cmp_pd_mask(a, b, _CMP_GT_OQ);
+}
+
+__mmask8 test_mm512_cmp_pd_mask_true_us(__m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_cmp_pd_mask_true_us
+ // CHECK: fcmp true <8 x double> %{{.*}}, %{{.*}}
+ return _mm512_cmp_pd_mask(a, b, _CMP_TRUE_US);
+}
+
+__mmask8 test_mm512_mask_cmp_pd_mask_eq_oq(__mmask8 m, __m512d a, __m512d b) {
+ // CHECK-LABEL: @test_mm512_mask_cmp_pd_mask_eq_oq
+ // CHECK: [[CMP:%.*]] = fcmp oeq <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_EQ_OQ);
+}
+
+__mmask8 test_mm512_mask_cmp_pd_mask_lt_os(__mmask8 m, __m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_lt_os
+ // CHECK: [[CMP:%.*]] = fcmp olt <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_LT_OS);
+}
+
+__mmask8 test_mm512_mask_cmp_pd_mask_le_os(__mmask8 m, __m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_le_os
+ // CHECK: [[CMP:%.*]] = fcmp ole <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_LE_OS);
+}
+
+__mmask8 test_mm512_mask_cmp_pd_mask_unord_q(__mmask8 m, __m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_unord_q
+ // CHECK: [[CMP:%.*]] = fcmp uno <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_UNORD_Q);
+}
+
+__mmask8 test_mm512_mask_cmp_pd_mask_neq_uq(__mmask8 m, __m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_neq_uq
+ // CHECK: [[CMP:%.*]] = fcmp une <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_NEQ_UQ);
+}
+
+__mmask8 test_mm512_mask_cmp_pd_mask_nlt_us(__mmask8 m, __m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_nlt_us
+ // CHECK: [[CMP:%.*]] = fcmp uge <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_NLT_US);
+}
+
+__mmask8 test_mm512_mask_cmp_pd_mask_nle_us(__mmask8 m, __m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_nle_us
+ // CHECK: [[CMP:%.*]] = fcmp ugt <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_NLE_US);
+}
+
+__mmask8 test_mm512_mask_cmp_pd_mask_ord_q(__mmask8 m, __m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_ord_q
+ // CHECK: [[CMP:%.*]] = fcmp ord <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_ORD_Q);
+}
+
+__mmask8 test_mm512_mask_cmp_pd_mask_eq_uq(__mmask8 m, __m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_eq_uq
+ // CHECK: [[CMP:%.*]] = fcmp ueq <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_EQ_UQ);
+}
+
+__mmask8 test_mm512_mask_cmp_pd_mask_nge_us(__mmask8 m, __m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_nge_us
+ // CHECK: [[CMP:%.*]] = fcmp ult <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_NGE_US);
+}
+
+__mmask8 test_mm512_mask_cmp_pd_mask_ngt_us(__mmask8 m, __m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_ngt_us
+ // CHECK: [[CMP:%.*]] = fcmp ule <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_NGT_US);
+}
+
+__mmask8 test_mm512_mask_cmp_pd_mask_false_oq(__mmask8 m, __m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_false_oq
+ // CHECK: [[CMP:%.*]] = fcmp false <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_FALSE_OQ);
+}
+
+__mmask8 test_mm512_mask_cmp_pd_mask_neq_oq(__mmask8 m, __m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_neq_oq
+ // CHECK: [[CMP:%.*]] = fcmp one <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_NEQ_OQ);
+}
+
+__mmask8 test_mm512_mask_cmp_pd_mask_ge_os(__mmask8 m, __m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_ge_os
+ // CHECK: [[CMP:%.*]] = fcmp oge <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_GE_OS);
+}
+
+__mmask8 test_mm512_mask_cmp_pd_mask_gt_os(__mmask8 m, __m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_gt_os
+ // CHECK: [[CMP:%.*]] = fcmp ogt <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_GT_OS);
+}
+
+__mmask8 test_mm512_mask_cmp_pd_mask_true_uq(__mmask8 m, __m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_true_uq
+ // CHECK: [[CMP:%.*]] = fcmp true <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_TRUE_UQ);
+}
+
+__mmask8 test_mm512_mask_cmp_pd_mask_eq_os(__mmask8 m, __m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_eq_os
+ // CHECK: [[CMP:%.*]] = fcmp oeq <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_EQ_OS);
+}
+
+__mmask8 test_mm512_mask_cmp_pd_mask_lt_oq(__mmask8 m, __m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_lt_oq
+ // CHECK: [[CMP:%.*]] = fcmp olt <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_LT_OQ);
+}
+
+__mmask8 test_mm512_mask_cmp_pd_mask_le_oq(__mmask8 m, __m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_le_oq
+ // CHECK: [[CMP:%.*]] = fcmp ole <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_LE_OQ);
+}
+
+__mmask8 test_mm512_mask_cmp_pd_mask_unord_s(__mmask8 m, __m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_unord_s
+ // CHECK: [[CMP:%.*]] = fcmp uno <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_UNORD_S);
+}
+
+__mmask8 test_mm512_mask_cmp_pd_mask_neq_us(__mmask8 m, __m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_neq_us
+ // CHECK: [[CMP:%.*]] = fcmp une <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_NEQ_US);
+}
+
+__mmask8 test_mm512_mask_cmp_pd_mask_nlt_uq(__mmask8 m, __m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_nlt_uq
+ // CHECK: [[CMP:%.*]] = fcmp uge <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_NLT_UQ);
+}
+
+__mmask8 test_mm512_mask_cmp_pd_mask_nle_uq(__mmask8 m, __m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_nle_uq
+ // CHECK: [[CMP:%.*]] = fcmp ugt <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_NLE_UQ);
+}
+
+__mmask8 test_mm512_mask_cmp_pd_mask_ord_s(__mmask8 m, __m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_ord_s
+ // CHECK: [[CMP:%.*]] = fcmp ord <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_ORD_S);
+}
+
+__mmask8 test_mm512_mask_cmp_pd_mask_eq_us(__mmask8 m, __m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_eq_us
+ // CHECK: [[CMP:%.*]] = fcmp ueq <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_EQ_US);
+}
+
+__mmask8 test_mm512_mask_cmp_pd_mask_nge_uq(__mmask8 m, __m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_nge_uq
+ // CHECK: [[CMP:%.*]] = fcmp ult <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_NGE_UQ);
+}
+
+__mmask8 test_mm512_mask_cmp_pd_mask_ngt_uq(__mmask8 m, __m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_ngt_uq
+ // CHECK: [[CMP:%.*]] = fcmp ule <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_NGT_UQ);
+}
+
+__mmask8 test_mm512_mask_cmp_pd_mask_false_os(__mmask8 m, __m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_false_os
+ // CHECK: [[CMP:%.*]] = fcmp false <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_FALSE_OS);
+}
+
+__mmask8 test_mm512_mask_cmp_pd_mask_neq_os(__mmask8 m, __m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_neq_os
+ // CHECK: [[CMP:%.*]] = fcmp one <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_NEQ_OS);
+}
+
+__mmask8 test_mm512_mask_cmp_pd_mask_ge_oq(__mmask8 m, __m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_ge_oq
+ // CHECK: [[CMP:%.*]] = fcmp oge <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_GE_OQ);
+}
+
+__mmask8 test_mm512_mask_cmp_pd_mask_gt_oq(__mmask8 m, __m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_gt_oq
+ // CHECK: [[CMP:%.*]] = fcmp ogt <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_GT_OQ);
+}
+
+__mmask8 test_mm512_mask_cmp_pd_mask_true_us(__mmask8 m, __m512d a, __m512d b) {
+ // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_true_us
+ // CHECK: [[CMP:%.*]] = fcmp true <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_TRUE_US);
}
__mmask8 test_mm512_mask_cmp_pd_mask(__mmask8 m, __m512d a, __m512d b) {
// CHECK-LABEL: @test_mm512_mask_cmp_pd_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.pd.512
+ // CHECK: [[CMP:%.*]] = fcmp oeq <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
return _mm512_mask_cmp_pd_mask(m, a, b, 0);
}
__mmask8 test_mm512_cmpeq_pd_mask(__m512d a, __m512d b) {
// CHECK-LABEL: @test_mm512_cmpeq_pd_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.pd.512
+ // CHECK: fcmp oeq <8 x double> %{{.*}}, %{{.*}}
return _mm512_cmpeq_pd_mask(a, b);
}
-__mmask8 test_mm512_cmpeq_ps_mask(__m512 a, __m512 b) {
+__mmask16 test_mm512_cmpeq_ps_mask(__m512 a, __m512 b) {
// CHECK-LABEL: @test_mm512_cmpeq_ps_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
+ // CHECK: fcmp oeq <16 x float> %{{.*}}, %{{.*}}
return _mm512_cmpeq_ps_mask(a, b);
}
__mmask8 test_mm512_mask_cmpeq_pd_mask(__mmask8 k, __m512d a, __m512d b) {
// CHECK-LABEL: @test_mm512_mask_cmpeq_pd_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.pd.512
+ // CHECK: [[CMP:%.*]] = fcmp oeq <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
return _mm512_mask_cmpeq_pd_mask(k, a, b);
}
-__mmask8 test_mm512_mask_cmpeq_ps_mask(__mmask8 k, __m512 a, __m512 b) {
+__mmask16 test_mm512_mask_cmpeq_ps_mask(__mmask16 k, __m512 a, __m512 b) {
// CHECK-LABEL: @test_mm512_mask_cmpeq_ps_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
+ // CHECK: [[CMP:%.*]] = fcmp oeq <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
return _mm512_mask_cmpeq_ps_mask(k, a, b);
}
__mmask8 test_mm512_cmple_pd_mask(__m512d a, __m512d b) {
// CHECK-LABEL: @test_mm512_cmple_pd_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.pd.512
- return _mm512_cmpeq_pd_mask(a, b);
+ // CHECK: fcmp ole <8 x double> %{{.*}}, %{{.*}}
+ return _mm512_cmple_pd_mask(a, b);
}
-__mmask8 test_mm512_cmple_ps_mask(__m512 a, __m512 b) {
+__mmask16 test_mm512_cmple_ps_mask(__m512 a, __m512 b) {
// CHECK-LABEL: @test_mm512_cmple_ps_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
- return _mm512_cmpeq_ps_mask(a, b);
+ // CHECK: fcmp ole <16 x float> %{{.*}}, %{{.*}}
+ return _mm512_cmple_ps_mask(a, b);
}
__mmask8 test_mm512_mask_cmple_pd_mask(__mmask8 k, __m512d a, __m512d b) {
// CHECK-LABEL: @test_mm512_mask_cmple_pd_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.pd.512
+ // CHECK: [[CMP:%.*]] = fcmp ole <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
return _mm512_mask_cmple_pd_mask(k, a, b);
}
-__mmask8 test_mm512_mask_cmple_ps_mask(__mmask8 k, __m512 a, __m512 b) {
+__mmask16 test_mm512_mask_cmple_ps_mask(__mmask16 k, __m512 a, __m512 b) {
// CHECK-LABEL: @test_mm512_mask_cmple_ps_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
+ // CHECK: [[CMP:%.*]] = fcmp ole <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
return _mm512_mask_cmple_ps_mask(k, a, b);
}
__mmask8 test_mm512_cmplt_pd_mask(__m512d a, __m512d b) {
// CHECK-LABEL: @test_mm512_cmplt_pd_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.pd.512
+ // CHECK: fcmp olt <8 x double> %{{.*}}, %{{.*}}
return _mm512_cmplt_pd_mask(a, b);
}
-__mmask8 test_mm512_cmplt_ps_mask(__m512 a, __m512 b) {
+__mmask16 test_mm512_cmplt_ps_mask(__m512 a, __m512 b) {
// CHECK-LABEL: @test_mm512_cmplt_ps_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
+ // CHECK: fcmp olt <16 x float> %{{.*}}, %{{.*}}
return _mm512_cmplt_ps_mask(a, b);
}
__mmask8 test_mm512_mask_cmplt_pd_mask(__mmask8 k, __m512d a, __m512d b) {
// CHECK-LABEL: @test_mm512_mask_cmplt_pd_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.pd.512
+ // CHECK: [[CMP:%.*]] = fcmp olt <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
return _mm512_mask_cmplt_pd_mask(k, a, b);
}
-__mmask8 test_mm512_mask_cmplt_ps_mask(__mmask8 k, __m512 a, __m512 b) {
+__mmask16 test_mm512_mask_cmplt_ps_mask(__mmask16 k, __m512 a, __m512 b) {
// CHECK-LABEL: @test_mm512_mask_cmplt_ps_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
+ // CHECK: [[CMP:%.*]] = fcmp olt <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
return _mm512_mask_cmplt_ps_mask(k, a, b);
}
__mmask8 test_mm512_cmpneq_pd_mask(__m512d a, __m512d b) {
// CHECK-LABEL: @test_mm512_cmpneq_pd_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.pd.512
+ // CHECK: fcmp une <8 x double> %{{.*}}, %{{.*}}
return _mm512_cmpneq_pd_mask(a, b);
}
-__mmask8 test_mm512_cmpneq_ps_mask(__m512 a, __m512 b) {
+__mmask16 test_mm512_cmpneq_ps_mask(__m512 a, __m512 b) {
// CHECK-LABEL: @test_mm512_cmpneq_ps_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
+ // CHECK: fcmp une <16 x float> %{{.*}}, %{{.*}}
return _mm512_cmpneq_ps_mask(a, b);
}
__mmask8 test_mm512_mask_cmpneq_pd_mask(__mmask8 k, __m512d a, __m512d b) {
// CHECK-LABEL: @test_mm512_mask_cmpneq_pd_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.pd.512
+ // CHECK: [[CMP:%.*]] = fcmp une <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
return _mm512_mask_cmpneq_pd_mask(k, a, b);
}
-__mmask8 test_mm512_mask_cmpneq_ps_mask(__mmask8 k, __m512 a, __m512 b) {
+__mmask16 test_mm512_mask_cmpneq_ps_mask(__mmask16 k, __m512 a, __m512 b) {
// CHECK-LABEL: @test_mm512_mask_cmpneq_ps_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
+ // CHECK: [[CMP:%.*]] = fcmp une <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
return _mm512_mask_cmpneq_ps_mask(k, a, b);
}
__mmask8 test_mm512_cmpnle_pd_mask(__m512d a, __m512d b) {
// CHECK-LABEL: @test_mm512_cmpnle_pd_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.pd.512
+ // CHECK: fcmp ugt <8 x double> %{{.*}}, %{{.*}}
return _mm512_cmpnle_pd_mask(a, b);
}
-__mmask8 test_mm512_cmpnle_ps_mask(__m512 a, __m512 b) {
+__mmask16 test_mm512_cmpnle_ps_mask(__m512 a, __m512 b) {
// CHECK-LABEL: @test_mm512_cmpnle_ps_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
+ // CHECK: fcmp ugt <16 x float> %{{.*}}, %{{.*}}
return _mm512_cmpnle_ps_mask(a, b);
}
__mmask8 test_mm512_mask_cmpnle_pd_mask(__mmask8 k, __m512d a, __m512d b) {
// CHECK-LABEL: @test_mm512_mask_cmpnle_pd_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.pd.512
+ // CHECK: [[CMP:%.*]] = fcmp ugt <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
return _mm512_mask_cmpnle_pd_mask(k, a, b);
}
-__mmask8 test_mm512_mask_cmpnle_ps_mask(__mmask8 k, __m512 a, __m512 b) {
+__mmask16 test_mm512_mask_cmpnle_ps_mask(__mmask16 k, __m512 a, __m512 b) {
// CHECK-LABEL: @test_mm512_mask_cmpnle_ps_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
+ // CHECK: [[CMP:%.*]] = fcmp ugt <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
return _mm512_mask_cmpnle_ps_mask(k, a, b);
}
__mmask8 test_mm512_cmpnlt_pd_mask(__m512d a, __m512d b) {
// CHECK-LABEL: @test_mm512_cmpnlt_pd_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.pd.512
+ // CHECK: fcmp uge <8 x double> %{{.*}}, %{{.*}}
return _mm512_cmpnlt_pd_mask(a, b);
}
-__mmask8 test_mm512_cmpnlt_ps_mask(__m512 a, __m512 b) {
+__mmask16 test_mm512_cmpnlt_ps_mask(__m512 a, __m512 b) {
// CHECK-LABEL: @test_mm512_cmpnlt_ps_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
+ // CHECK: fcmp uge <16 x float> %{{.*}}, %{{.*}}
return _mm512_cmpnlt_ps_mask(a, b);
}
__mmask8 test_mm512_mask_cmpnlt_pd_mask(__mmask8 k, __m512d a, __m512d b) {
// CHECK-LABEL: @test_mm512_mask_cmpnlt_pd_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.pd.512
+ // CHECK: [[CMP:%.*]] = fcmp uge <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
return _mm512_mask_cmpnlt_pd_mask(k, a, b);
}
-__mmask8 test_mm512_mask_cmpnlt_ps_mask(__mmask8 k, __m512 a, __m512 b) {
+__mmask16 test_mm512_mask_cmpnlt_ps_mask(__mmask16 k, __m512 a, __m512 b) {
// CHECK-LABEL: @test_mm512_mask_cmpnlt_ps_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
+ // CHECK: [[CMP:%.*]] = fcmp uge <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
return _mm512_mask_cmpnlt_ps_mask(k, a, b);
}
__mmask8 test_mm512_cmpord_pd_mask(__m512d a, __m512d b) {
// CHECK-LABEL: @test_mm512_cmpord_pd_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.pd.512
+ // CHECK: fcmp ord <8 x double> %{{.*}}, %{{.*}}
return _mm512_cmpord_pd_mask(a, b);
}
-__mmask8 test_mm512_cmpord_ps_mask(__m512 a, __m512 b) {
+__mmask16 test_mm512_cmpord_ps_mask(__m512 a, __m512 b) {
// CHECK-LABEL: @test_mm512_cmpord_ps_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
+ // CHECK: fcmp ord <16 x float> %{{.*}}, %{{.*}}
return _mm512_cmpord_ps_mask(a, b);
}
__mmask8 test_mm512_mask_cmpord_pd_mask(__mmask8 k, __m512d a, __m512d b) {
// CHECK-LABEL: @test_mm512_mask_cmpord_pd_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.pd.512
+ // CHECK: [[CMP:%.*]] = fcmp ord <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
return _mm512_mask_cmpord_pd_mask(k, a, b);
}
-__mmask8 test_mm512_mask_cmpord_ps_mask(__mmask8 k, __m512 a, __m512 b) {
+__mmask16 test_mm512_mask_cmpord_ps_mask(__mmask16 k, __m512 a, __m512 b) {
// CHECK-LABEL: @test_mm512_mask_cmpord_ps_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
+ // CHECK: [[CMP:%.*]] = fcmp ord <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
return _mm512_mask_cmpord_ps_mask(k, a, b);
}
__mmask8 test_mm512_cmpunord_pd_mask(__m512d a, __m512d b) {
// CHECK-LABEL: @test_mm512_cmpunord_pd_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.pd.512
+ // CHECK: fcmp uno <8 x double> %{{.*}}, %{{.*}}
return _mm512_cmpunord_pd_mask(a, b);
}
-__mmask8 test_mm512_cmpunord_ps_mask(__m512 a, __m512 b) {
+__mmask16 test_mm512_cmpunord_ps_mask(__m512 a, __m512 b) {
// CHECK-LABEL: @test_mm512_cmpunord_ps_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
+ // CHECK: fcmp uno <16 x float> %{{.*}}, %{{.*}}
return _mm512_cmpunord_ps_mask(a, b);
}
__mmask8 test_mm512_mask_cmpunord_pd_mask(__mmask8 k, __m512d a, __m512d b) {
// CHECK-LABEL: @test_mm512_mask_cmpunord_pd_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.pd.512
+ // CHECK: [[CMP:%.*]] = fcmp uno <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
return _mm512_mask_cmpunord_pd_mask(k, a, b);
}
-__mmask8 test_mm512_mask_cmpunord_ps_mask(__mmask8 k, __m512 a, __m512 b) {
+__mmask16 test_mm512_mask_cmpunord_ps_mask(__mmask16 k, __m512 a, __m512 b) {
// CHECK-LABEL: @test_mm512_mask_cmpunord_ps_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
+ // CHECK: [[CMP:%.*]] = fcmp uno <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <16 x i1> [[CMP]], {{.*}}
return _mm512_mask_cmpunord_ps_mask(k, a, b);
}
__m256d test_mm512_extractf64x4_pd(__m512d a)
{
// CHECK-LABEL: @test_mm512_extractf64x4_pd
- // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> zeroinitializer, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
return _mm512_extractf64x4_pd(a, 1);
}
__m256d test_mm512_mask_extractf64x4_pd(__m256d __W,__mmask8 __U,__m512d __A){
// CHECK-LABEL:@test_mm512_mask_extractf64x4_pd
- // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> zeroinitializer, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm512_mask_extractf64x4_pd( __W, __U, __A, 1);
}
__m256d test_mm512_maskz_extractf64x4_pd(__mmask8 __U,__m512d __A){
// CHECK-LABEL:@test_mm512_maskz_extractf64x4_pd
- // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> zeroinitializer, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm512_maskz_extractf64x4_pd( __U, __A, 1);
}
@@ -1263,20 +2374,20 @@ __m256d test_mm512_maskz_extractf64x4_pd(__mmask8 __U,__m512d __A){
__m128 test_mm512_extractf32x4_ps(__m512 a)
{
// CHECK-LABEL: @test_mm512_extractf32x4_ps
- // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> zeroinitializer, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
return _mm512_extractf32x4_ps(a, 1);
}
-__m128 test_mm512_mask_extractf32x4_ps(__m128 __W, __mmask8 __U,__m512d __A){
+__m128 test_mm512_mask_extractf32x4_ps(__m128 __W, __mmask8 __U,__m512 __A){
// CHECK-LABEL:@test_mm512_mask_extractf32x4_ps
- // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> zeroinitializer, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm512_mask_extractf32x4_ps( __W, __U, __A, 1);
}
-__m128 test_mm512_maskz_extractf32x4_ps( __mmask8 __U,__m512d __A){
+__m128 test_mm512_maskz_extractf32x4_ps( __mmask8 __U,__m512 __A){
// CHECK-LABEL:@test_mm512_maskz_extractf32x4_ps
- // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> zeroinitializer, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm512_maskz_extractf32x4_ps( __U, __A, 1);
}
@@ -1870,42 +2981,58 @@ __m512i test_mm512_add_epi64(__m512i __A, __m512i __B) {
__m512i test_mm512_mul_epi32(__m512i __A, __m512i __B) {
//CHECK-LABEL: @test_mm512_mul_epi32
- //CHECK: @llvm.x86.avx512.pmul.dq.512
+ //CHECK: shl <8 x i64> %{{.*}}, <i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32>
+ //CHECK: ashr <8 x i64> %{{.*}}, <i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32>
+ //CHECK: shl <8 x i64> %{{.*}}, <i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32>
+ //CHECK: ashr <8 x i64> %{{.*}}, <i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32>
+ //CHECK: mul <8 x i64> %{{.*}}, %{{.*}}
return _mm512_mul_epi32(__A,__B);
}
-__m512i test_mm512_maskz_mul_epi32 (__mmask16 __k,__m512i __A, __m512i __B) {
+__m512i test_mm512_maskz_mul_epi32 (__mmask8 __k,__m512i __A, __m512i __B) {
//CHECK-LABEL: @test_mm512_maskz_mul_epi32
- //CHECK: @llvm.x86.avx512.pmul.dq.512
+ //CHECK: shl <8 x i64> %{{.*}}, <i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32>
+ //CHECK: ashr <8 x i64> %{{.*}}, <i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32>
+ //CHECK: shl <8 x i64> %{{.*}}, <i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32>
+ //CHECK: ashr <8 x i64> %{{.*}}, <i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32>
+ //CHECK: mul <8 x i64> %{{.*}}, %{{.*}}
//CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_mul_epi32(__k,__A,__B);
}
-__m512i test_mm512_mask_mul_epi32 (__mmask16 __k,__m512i __A, __m512i __B,
- __m512i __src) {
+__m512i test_mm512_mask_mul_epi32 (__mmask8 __k,__m512i __A, __m512i __B, __m512i __src) {
//CHECK-LABEL: @test_mm512_mask_mul_epi32
- //CHECK: @llvm.x86.avx512.pmul.dq.512
+ //CHECK: shl <8 x i64> %{{.*}}, <i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32>
+ //CHECK: ashr <8 x i64> %{{.*}}, <i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32>
+ //CHECK: shl <8 x i64> %{{.*}}, <i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32>
+ //CHECK: ashr <8 x i64> %{{.*}}, <i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32>
+ //CHECK: mul <8 x i64> %{{.*}}, %{{.*}}
//CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_mul_epi32(__src,__k,__A,__B);
}
__m512i test_mm512_mul_epu32 (__m512i __A, __m512i __B) {
//CHECK-LABEL: @test_mm512_mul_epu32
- //CHECK: @llvm.x86.avx512.pmulu.dq.512
+ //CHECK: and <8 x i64> %{{.*}}, <i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295>
+ //CHECK: and <8 x i64> %{{.*}}, <i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295>
+ //CHECK: mul <8 x i64> %{{.*}}, %{{.*}}
return _mm512_mul_epu32(__A,__B);
}
-__m512i test_mm512_maskz_mul_epu32 (__mmask16 __k,__m512i __A, __m512i __B) {
+__m512i test_mm512_maskz_mul_epu32 (__mmask8 __k,__m512i __A, __m512i __B) {
//CHECK-LABEL: @test_mm512_maskz_mul_epu32
- //CHECK: @llvm.x86.avx512.pmulu.dq.512
+ //CHECK: and <8 x i64> %{{.*}}, <i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295>
+ //CHECK: and <8 x i64> %{{.*}}, <i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295>
+ //CHECK: mul <8 x i64> %{{.*}}, %{{.*}}
//CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_mul_epu32(__k,__A,__B);
}
-__m512i test_mm512_mask_mul_epu32 (__mmask16 __k,__m512i __A, __m512i __B,
- __m512i __src) {
+__m512i test_mm512_mask_mul_epu32 (__mmask8 __k,__m512i __A, __m512i __B, __m512i __src) {
//CHECK-LABEL: @test_mm512_mask_mul_epu32
- //CHECK: @llvm.x86.avx512.pmulu.dq.512
+ //CHECK: and <8 x i64> %{{.*}}, <i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295>
+ //CHECK: and <8 x i64> %{{.*}}, <i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295>
+ //CHECK: mul <8 x i64> %{{.*}}, %{{.*}}
//CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_mul_epu32(__src,__k,__A,__B);
}
@@ -1930,19 +3057,34 @@ __m512i test_mm512_mullo_epi32(__m512i __A, __m512i __B) {
return _mm512_mullo_epi32(__A,__B);
}
+__m512i test_mm512_mullox_epi64 (__m512i __A, __m512i __B) {
+ // CHECK-LABEL: @test_mm512_mullox_epi64
+ // CHECK: mul <8 x i64>
+ return (__m512i) _mm512_mullox_epi64(__A, __B);
+}
+
+__m512i test_mm512_mask_mullox_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) {
+ // CHECK-LABEL: @test_mm512_mask_mullox_epi64
+ // CHECK: mul <8 x i64> %{{.*}}, %{{.*}}
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
+ return (__m512i) _mm512_mask_mullox_epi64(__W, __U, __A, __B);
+}
+
__m512d test_mm512_add_round_pd(__m512d __A, __m512d __B) {
// CHECK-LABEL: @test_mm512_add_round_pd
- // CHECK: @llvm.x86.avx512.mask.add.pd.512
+ // CHECK: @llvm.x86.avx512.add.pd.512
return _mm512_add_round_pd(__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_mask_add_round_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
// CHECK-LABEL: @test_mm512_mask_add_round_pd
- // CHECK: @llvm.x86.avx512.mask.add.pd.512
+ // CHECK: @llvm.x86.avx512.add.pd.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_add_round_pd(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_maskz_add_round_pd(__mmask8 __U, __m512d __A, __m512d __B) {
// CHECK-LABEL: @test_mm512_maskz_add_round_pd
- // CHECK: @llvm.x86.avx512.mask.add.pd.512
+ // CHECK: @llvm.x86.avx512.add.pd.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_maskz_add_round_pd(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_mask_add_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
@@ -1959,17 +3101,19 @@ __m512d test_mm512_maskz_add_pd(__mmask8 __U, __m512d __A, __m512d __B) {
}
__m512 test_mm512_add_round_ps(__m512 __A, __m512 __B) {
// CHECK-LABEL: @test_mm512_add_round_ps
- // CHECK: @llvm.x86.avx512.mask.add.ps.512
+ // CHECK: @llvm.x86.avx512.add.ps.512
return _mm512_add_round_ps(__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_mask_add_round_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
// CHECK-LABEL: @test_mm512_mask_add_round_ps
- // CHECK: @llvm.x86.avx512.mask.add.ps.512
+ // CHECK: @llvm.x86.avx512.add.ps.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_add_round_ps(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_maskz_add_round_ps(__mmask16 __U, __m512 __A, __m512 __B) {
// CHECK-LABEL: @test_mm512_maskz_add_round_ps
- // CHECK: @llvm.x86.avx512.mask.add.ps.512
+ // CHECK: @llvm.x86.avx512.add.ps.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_maskz_add_round_ps(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_mask_add_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
@@ -2001,12 +3145,32 @@ __m128 test_mm_maskz_add_round_ss(__mmask8 __U, __m128 __A, __m128 __B) {
}
__m128 test_mm_mask_add_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_mask_add_ss
- // CHECK: @llvm.x86.avx512.mask.add.ss.round
+ // CHECK-NOT: @llvm.x86.avx512.mask.add.ss.round
+ // CHECK: extractelement <4 x float> %{{.*}}, i32 0
+ // CHECK: extractelement <4 x float> %{{.*}}, i32 0
+ // CHECK: fadd float %{{.*}}, %{{.*}}
+ // CHECK: insertelement <4 x float> %{{.*}}, i32 0
+ // CHECK: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: select i1 %{{.*}}, float %{{.*}}, float %{{.*}}
+ // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0
return _mm_mask_add_ss(__W,__U,__A,__B);
}
__m128 test_mm_maskz_add_ss(__mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_maskz_add_ss
- // CHECK: @llvm.x86.avx512.mask.add.ss.round
+ // CHECK-NOT: @llvm.x86.avx512.mask.add.ss.round
+ // CHECK: extractelement <4 x float> %{{.*}}, i32 0
+ // CHECK: extractelement <4 x float> %{{.*}}, i32 0
+ // CHECK: fadd float %{{.*}}, %{{.*}}
+ // CHECK: insertelement <4 x float> %{{.*}}, i32 0
+ // CHECK: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: select i1 %{{.*}}, float %{{.*}}, float %{{.*}}
+ // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0
return _mm_maskz_add_ss(__U,__A,__B);
}
__m128d test_mm_add_round_sd(__m128d __A, __m128d __B) {
@@ -2026,27 +3190,49 @@ __m128d test_mm_maskz_add_round_sd(__mmask8 __U, __m128d __A, __m128d __B) {
}
__m128d test_mm_mask_add_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_mask_add_sd
- // CHECK: @llvm.x86.avx512.mask.add.sd.round
+ // CHECK-NOT: @llvm.x86.avx512.mask.add.sd.round
+ // CHECK: extractelement <2 x double> %{{.*}}, i32 0
+ // CHECK: extractelement <2 x double> %{{.*}}, i32 0
+ // CHECK: fadd double %{{.*}}, %{{.*}}
+ // CHECK: insertelement <2 x double> {{.*}}, i32 0
+ // CHECK: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: select i1 %{{.*}}, double %{{.*}}, double %{{.*}}
+ // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0
return _mm_mask_add_sd(__W,__U,__A,__B);
}
__m128d test_mm_maskz_add_sd(__mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_maskz_add_sd
- // CHECK: @llvm.x86.avx512.mask.add.sd.round
+ // CHECK-NOT: @llvm.x86.avx512.mask.add.sd.round
+ // CHECK: extractelement <2 x double> %{{.*}}, i32 0
+ // CHECK: extractelement <2 x double> %{{.*}}, i32 0
+ // CHECK: fadd double %{{.*}}, %{{.*}}
+ // CHECK: insertelement <2 x double> {{.*}}, i32 0
+ // CHECK: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: select i1 %{{.*}}, double %{{.*}}, double %{{.*}}
+ // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0
return _mm_maskz_add_sd(__U,__A,__B);
}
__m512d test_mm512_sub_round_pd(__m512d __A, __m512d __B) {
// CHECK-LABEL: @test_mm512_sub_round_pd
- // CHECK: @llvm.x86.avx512.mask.sub.pd.512
+ // CHECK: @llvm.x86.avx512.sub.pd.512
return _mm512_sub_round_pd(__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_mask_sub_round_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
// CHECK-LABEL: @test_mm512_mask_sub_round_pd
- // CHECK: @llvm.x86.avx512.mask.sub.pd.512
+ // CHECK: @llvm.x86.avx512.sub.pd.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_sub_round_pd(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_maskz_sub_round_pd(__mmask8 __U, __m512d __A, __m512d __B) {
// CHECK-LABEL: @test_mm512_maskz_sub_round_pd
- // CHECK: @llvm.x86.avx512.mask.sub.pd.512
+ // CHECK: @llvm.x86.avx512.sub.pd.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_maskz_sub_round_pd(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_mask_sub_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
@@ -2063,17 +3249,19 @@ __m512d test_mm512_maskz_sub_pd(__mmask8 __U, __m512d __A, __m512d __B) {
}
__m512 test_mm512_sub_round_ps(__m512 __A, __m512 __B) {
// CHECK-LABEL: @test_mm512_sub_round_ps
- // CHECK: @llvm.x86.avx512.mask.sub.ps.512
+ // CHECK: @llvm.x86.avx512.sub.ps.512
return _mm512_sub_round_ps(__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_mask_sub_round_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
// CHECK-LABEL: @test_mm512_mask_sub_round_ps
- // CHECK: @llvm.x86.avx512.mask.sub.ps.512
+ // CHECK: @llvm.x86.avx512.sub.ps.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_sub_round_ps(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_maskz_sub_round_ps(__mmask16 __U, __m512 __A, __m512 __B) {
// CHECK-LABEL: @test_mm512_maskz_sub_round_ps
- // CHECK: @llvm.x86.avx512.mask.sub.ps.512
+ // CHECK: @llvm.x86.avx512.sub.ps.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_maskz_sub_round_ps(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_mask_sub_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
@@ -2105,12 +3293,32 @@ __m128 test_mm_maskz_sub_round_ss(__mmask8 __U, __m128 __A, __m128 __B) {
}
__m128 test_mm_mask_sub_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_mask_sub_ss
- // CHECK: @llvm.x86.avx512.mask.sub.ss.round
+ // CHECK-NOT: @llvm.x86.avx512.mask.sub.ss.round
+ // CHECK: extractelement <4 x float> %{{.*}}, i32 0
+ // CHECK: extractelement <4 x float> %{{.*}}, i32 0
+ // CHECK: fsub float %{{.*}}, %{{.*}}
+ // CHECK: insertelement <4 x float> {{.*}}, i32 0
+ // CHECK: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: select i1 %{{.*}}, float %{{.*}}, float %{{.*}}
+ // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0
return _mm_mask_sub_ss(__W,__U,__A,__B);
}
__m128 test_mm_maskz_sub_ss(__mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_maskz_sub_ss
- // CHECK: @llvm.x86.avx512.mask.sub.ss.round
+ // CHECK-NOT: @llvm.x86.avx512.mask.sub.ss.round
+ // CHECK: extractelement <4 x float> %{{.*}}, i32 0
+ // CHECK: extractelement <4 x float> %{{.*}}, i32 0
+ // CHECK: fsub float %{{.*}}, %{{.*}}
+ // CHECK: insertelement <4 x float> {{.*}}, i32 0
+ // CHECK: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: select i1 %{{.*}}, float %{{.*}}, float %{{.*}}
+ // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0
return _mm_maskz_sub_ss(__U,__A,__B);
}
__m128d test_mm_sub_round_sd(__m128d __A, __m128d __B) {
@@ -2130,27 +3338,49 @@ __m128d test_mm_maskz_sub_round_sd(__mmask8 __U, __m128d __A, __m128d __B) {
}
__m128d test_mm_mask_sub_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_mask_sub_sd
- // CHECK: @llvm.x86.avx512.mask.sub.sd.round
+ // CHECK-NOT: @llvm.x86.avx512.mask.sub.sd.round
+ // CHECK: extractelement <2 x double> %{{.*}}, i32 0
+ // CHECK: extractelement <2 x double> %{{.*}}, i32 0
+ // CHECK: fsub double %{{.*}}, %{{.*}}
+ // CHECK: insertelement <2 x double> {{.*}}, i32 0
+ // CHECK: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: select i1 %{{.*}}, double %{{.*}}, double %{{.*}}
+ // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0
return _mm_mask_sub_sd(__W,__U,__A,__B);
}
__m128d test_mm_maskz_sub_sd(__mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_maskz_sub_sd
- // CHECK: @llvm.x86.avx512.mask.sub.sd.round
+ // CHECK-NOT: @llvm.x86.avx512.mask.sub.sd.round
+ // CHECK: extractelement <2 x double> %{{.*}}, i32 0
+ // CHECK: extractelement <2 x double> %{{.*}}, i32 0
+ // CHECK: fsub double %{{.*}}, %{{.*}}
+ // CHECK: insertelement <2 x double> {{.*}}, i32 0
+ // CHECK: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: select i1 %{{.*}}, double %{{.*}}, double %{{.*}}
+ // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0
return _mm_maskz_sub_sd(__U,__A,__B);
}
__m512d test_mm512_mul_round_pd(__m512d __A, __m512d __B) {
// CHECK-LABEL: @test_mm512_mul_round_pd
- // CHECK: @llvm.x86.avx512.mask.mul.pd.512
+ // CHECK: @llvm.x86.avx512.mul.pd.512
return _mm512_mul_round_pd(__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_mask_mul_round_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
// CHECK-LABEL: @test_mm512_mask_mul_round_pd
- // CHECK: @llvm.x86.avx512.mask.mul.pd.512
+ // CHECK: @llvm.x86.avx512.mul.pd.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_mul_round_pd(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_maskz_mul_round_pd(__mmask8 __U, __m512d __A, __m512d __B) {
// CHECK-LABEL: @test_mm512_maskz_mul_round_pd
- // CHECK: @llvm.x86.avx512.mask.mul.pd.512
+ // CHECK: @llvm.x86.avx512.mul.pd.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_maskz_mul_round_pd(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_mask_mul_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
@@ -2167,17 +3397,19 @@ __m512d test_mm512_maskz_mul_pd(__mmask8 __U, __m512d __A, __m512d __B) {
}
__m512 test_mm512_mul_round_ps(__m512 __A, __m512 __B) {
// CHECK-LABEL: @test_mm512_mul_round_ps
- // CHECK: @llvm.x86.avx512.mask.mul.ps.512
+ // CHECK: @llvm.x86.avx512.mul.ps.512
return _mm512_mul_round_ps(__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_mask_mul_round_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
// CHECK-LABEL: @test_mm512_mask_mul_round_ps
- // CHECK: @llvm.x86.avx512.mask.mul.ps.512
+ // CHECK: @llvm.x86.avx512.mul.ps.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_mul_round_ps(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_maskz_mul_round_ps(__mmask16 __U, __m512 __A, __m512 __B) {
// CHECK-LABEL: @test_mm512_maskz_mul_round_ps
- // CHECK: @llvm.x86.avx512.mask.mul.ps.512
+ // CHECK: @llvm.x86.avx512.mul.ps.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_maskz_mul_round_ps(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_mask_mul_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
@@ -2209,12 +3441,32 @@ __m128 test_mm_maskz_mul_round_ss(__mmask8 __U, __m128 __A, __m128 __B) {
}
__m128 test_mm_mask_mul_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_mask_mul_ss
- // CHECK: @llvm.x86.avx512.mask.mul.ss.round
+ // CHECK-NOT: @llvm.x86.avx512.mask.mul.ss.round
+ // CHECK: extractelement <4 x float> %{{.*}}, i32 0
+ // CHECK: extractelement <4 x float> %{{.*}}, i32 0
+ // CHECK: fmul float %{{.*}}, %{{.*}}
+ // CHECK: insertelement <4 x float> {{.*}}, i32 0
+ // CHECK: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: select i1 %{{.*}}, float %{{.*}}, float %{{.*}}
+ // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0
return _mm_mask_mul_ss(__W,__U,__A,__B);
}
__m128 test_mm_maskz_mul_ss(__mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_maskz_mul_ss
- // CHECK: @llvm.x86.avx512.mask.mul.ss.round
+ // CHECK-NOT: @llvm.x86.avx512.mask.mul.ss.round
+ // CHECK: extractelement <4 x float> %{{.*}}, i32 0
+ // CHECK: extractelement <4 x float> %{{.*}}, i32 0
+ // CHECK: fmul float %{{.*}}, %{{.*}}
+ // CHECK: insertelement <4 x float> {{.*}}, i32 0
+ // CHECK: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: select i1 %{{.*}}, float %{{.*}}, float %{{.*}}
+ // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0
return _mm_maskz_mul_ss(__U,__A,__B);
}
__m128d test_mm_mul_round_sd(__m128d __A, __m128d __B) {
@@ -2234,36 +3486,58 @@ __m128d test_mm_maskz_mul_round_sd(__mmask8 __U, __m128d __A, __m128d __B) {
}
__m128d test_mm_mask_mul_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_mask_mul_sd
- // CHECK: @llvm.x86.avx512.mask.mul.sd.round
+ // CHECK-NOT: @llvm.x86.avx512.mask.mul.sd.round
+ // CHECK: extractelement <2 x double> %{{.*}}, i32 0
+ // CHECK: extractelement <2 x double> %{{.*}}, i32 0
+ // CHECK: fmul double %{{.*}}, %{{.*}}
+ // CHECK: insertelement <2 x double> {{.*}}, i32 0
+ // CHECK: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: select i1 %{{.*}}, double %{{.*}}, double %{{.*}}
+ // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0
return _mm_mask_mul_sd(__W,__U,__A,__B);
}
__m128d test_mm_maskz_mul_sd(__mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_maskz_mul_sd
- // CHECK: @llvm.x86.avx512.mask.mul.sd.round
+ // CHECK-NOT: @llvm.x86.avx512.mask.mul.sd.round
+ // CHECK: extractelement <2 x double> %{{.*}}, i32 0
+ // CHECK: extractelement <2 x double> %{{.*}}, i32 0
+ // CHECK: fmul double %{{.*}}, %{{.*}}
+ // CHECK: insertelement <2 x double> {{.*}}, i32 0
+ // CHECK: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: select i1 %{{.*}}, double %{{.*}}, double %{{.*}}
+ // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0
return _mm_maskz_mul_sd(__U,__A,__B);
}
__m512d test_mm512_div_round_pd(__m512d __A, __m512d __B) {
// CHECK-LABEL: @test_mm512_div_round_pd
- // CHECK: @llvm.x86.avx512.mask.div.pd.512
+ // CHECK: @llvm.x86.avx512.div.pd.512
return _mm512_div_round_pd(__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_mask_div_round_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
// CHECK-LABEL: @test_mm512_mask_div_round_pd
- // CHECK: @llvm.x86.avx512.mask.div.pd.512
+ // CHECK: @llvm.x86.avx512.div.pd.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_div_round_pd(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_maskz_div_round_pd(__mmask8 __U, __m512d __A, __m512d __B) {
// CHECK-LABEL: @test_mm512_maskz_div_round_pd
- // CHECK: @llvm.x86.avx512.mask.div.pd.512
+ // CHECK: @llvm.x86.avx512.div.pd.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_maskz_div_round_pd(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_div_pd(__m512d __a, __m512d __b) {
- // CHECK-LABLE: @test_mm512_div_pd
+ // CHECK-LABEL: @test_mm512_div_pd
// CHECK: fdiv <8 x double>
return _mm512_div_pd(__a,__b);
}
__m512d test_mm512_mask_div_pd(__m512d __w, __mmask8 __u, __m512d __a, __m512d __b) {
- // CHECK-LABLE: @test_mm512_mask_div_pd
+ // CHECK-LABEL: @test_mm512_mask_div_pd
// CHECK: fdiv <8 x double> %{{.*}}, %{{.*}}
// CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_div_pd(__w,__u,__a,__b);
@@ -2276,17 +3550,19 @@ __m512d test_mm512_maskz_div_pd(__mmask8 __U, __m512d __A, __m512d __B) {
}
__m512 test_mm512_div_round_ps(__m512 __A, __m512 __B) {
// CHECK-LABEL: @test_mm512_div_round_ps
- // CHECK: @llvm.x86.avx512.mask.div.ps.512
+ // CHECK: @llvm.x86.avx512.div.ps.512
return _mm512_div_round_ps(__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_mask_div_round_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
// CHECK-LABEL: @test_mm512_mask_div_round_ps
- // CHECK: @llvm.x86.avx512.mask.div.ps.512
+ // CHECK: @llvm.x86.avx512.div.ps.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_div_round_ps(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_maskz_div_round_ps(__mmask16 __U, __m512 __A, __m512 __B) {
// CHECK-LABEL: @test_mm512_maskz_div_round_ps
- // CHECK: @llvm.x86.avx512.mask.div.ps.512
+ // CHECK: @llvm.x86.avx512.div.ps.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_maskz_div_round_ps(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_div_ps(__m512 __A, __m512 __B) {
@@ -2323,12 +3599,30 @@ __m128 test_mm_maskz_div_round_ss(__mmask8 __U, __m128 __A, __m128 __B) {
}
__m128 test_mm_mask_div_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_mask_div_ss
- // CHECK: @llvm.x86.avx512.mask.div.ss.round
+ // CHECK: extractelement <4 x float> %{{.*}}, i32 0
+ // CHECK: extractelement <4 x float> %{{.*}}, i32 0
+ // CHECK: fdiv float %{{.*}}, %{{.*}}
+ // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i32 0
+ // CHECK: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: select i1 %{{.*}}, float %{{.*}}, float %{{.*}}
+ // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0
return _mm_mask_div_ss(__W,__U,__A,__B);
}
__m128 test_mm_maskz_div_ss(__mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_maskz_div_ss
- // CHECK: @llvm.x86.avx512.mask.div.ss.round
+ // CHECK: extractelement <4 x float> %{{.*}}, i32 0
+ // CHECK: extractelement <4 x float> %{{.*}}, i32 0
+ // CHECK: fdiv float %{{.*}}, %{{.*}}
+ // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i32 0
+ // CHECK: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: select i1 %{{.*}}, float %{{.*}}, float %{{.*}}
+ // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0
return _mm_maskz_div_ss(__U,__A,__B);
}
__m128d test_mm_div_round_sd(__m128d __A, __m128d __B) {
@@ -2348,12 +3642,30 @@ __m128d test_mm_maskz_div_round_sd(__mmask8 __U, __m128d __A, __m128d __B) {
}
__m128d test_mm_mask_div_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_mask_div_sd
- // CHECK: @llvm.x86.avx512.mask.div.sd.round
+ // CHECK: extractelement <2 x double> %{{.*}}, i32 0
+ // CHECK: extractelement <2 x double> %{{.*}}, i32 0
+ // CHECK: fdiv double %{{.*}}, %{{.*}}
+ // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 0
+ // CHECK: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: select i1 %{{.*}}, double %{{.*}}, double %{{.*}}
+ // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0
return _mm_mask_div_sd(__W,__U,__A,__B);
}
__m128d test_mm_maskz_div_sd(__mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_maskz_div_sd
- // CHECK: @llvm.x86.avx512.mask.div.sd.round
+ // CHECK: extractelement <2 x double> %{{.*}}, i32 0
+ // CHECK: extractelement <2 x double> %{{.*}}, i32 0
+ // CHECK: fdiv double %{{.*}}, %{{.*}}
+ // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 0
+ // CHECK: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: select i1 %{{.*}}, double %{{.*}}, double %{{.*}}
+ // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0
return _mm_maskz_div_sd(__U,__A,__B);
}
__m128 test_mm_max_round_ss(__m128 __A, __m128 __B) {
@@ -2684,146 +3996,162 @@ __m512i test_mm512_maskz_cvtepu16_epi64(__mmask8 __U, __m128i __A) {
__m512i test_mm512_rol_epi32(__m512i __A) {
// CHECK-LABEL: @test_mm512_rol_epi32
- // CHECK: @llvm.x86.avx512.mask.prol.d.512
+ // CHECK: @llvm.x86.avx512.prol.d.512
return _mm512_rol_epi32(__A, 5);
}
__m512i test_mm512_mask_rol_epi32(__m512i __W, __mmask16 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_rol_epi32
- // CHECK: @llvm.x86.avx512.mask.prol.d.512
+ // CHECK: @llvm.x86.avx512.prol.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_rol_epi32(__W, __U, __A, 5);
}
__m512i test_mm512_maskz_rol_epi32(__mmask16 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_rol_epi32
- // CHECK: @llvm.x86.avx512.mask.prol.d.512
+ // CHECK: @llvm.x86.avx512.prol.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_rol_epi32(__U, __A, 5);
}
__m512i test_mm512_rol_epi64(__m512i __A) {
// CHECK-LABEL: @test_mm512_rol_epi64
- // CHECK: @llvm.x86.avx512.mask.prol.q.512
+ // CHECK: @llvm.x86.avx512.prol.q.512
return _mm512_rol_epi64(__A, 5);
}
__m512i test_mm512_mask_rol_epi64(__m512i __W, __mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_rol_epi64
- // CHECK: @llvm.x86.avx512.mask.prol.q.512
+ // CHECK: @llvm.x86.avx512.prol.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_rol_epi64(__W, __U, __A, 5);
}
__m512i test_mm512_maskz_rol_epi64(__mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_rol_epi64
- // CHECK: @llvm.x86.avx512.mask.prol.q.512
+ // CHECK: @llvm.x86.avx512.prol.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_rol_epi64(__U, __A, 5);
}
__m512i test_mm512_rolv_epi32(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_rolv_epi32
- // CHECK: @llvm.x86.avx512.mask.prolv.d.512
+ // CHECK: @llvm.x86.avx512.prolv.d.512
return _mm512_rolv_epi32(__A, __B);
}
__m512i test_mm512_mask_rolv_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_rolv_epi32
- // CHECK: @llvm.x86.avx512.mask.prolv.d.512
+ // CHECK: @llvm.x86.avx512.prolv.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_rolv_epi32(__W, __U, __A, __B);
}
__m512i test_mm512_maskz_rolv_epi32(__mmask16 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_rolv_epi32
- // CHECK: @llvm.x86.avx512.mask.prolv.d.512
+ // CHECK: @llvm.x86.avx512.prolv.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_rolv_epi32(__U, __A, __B);
}
__m512i test_mm512_rolv_epi64(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_rolv_epi64
- // CHECK: @llvm.x86.avx512.mask.prolv.q.512
+ // CHECK: @llvm.x86.avx512.prolv.q.512
return _mm512_rolv_epi64(__A, __B);
}
__m512i test_mm512_mask_rolv_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_rolv_epi64
- // CHECK: @llvm.x86.avx512.mask.prolv.q.512
+ // CHECK: @llvm.x86.avx512.prolv.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_rolv_epi64(__W, __U, __A, __B);
}
__m512i test_mm512_maskz_rolv_epi64(__mmask8 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_rolv_epi64
- // CHECK: @llvm.x86.avx512.mask.prolv.q.512
+ // CHECK: @llvm.x86.avx512.prolv.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_rolv_epi64(__U, __A, __B);
}
__m512i test_mm512_ror_epi32(__m512i __A) {
// CHECK-LABEL: @test_mm512_ror_epi32
- // CHECK: @llvm.x86.avx512.mask.pror.d.512
+ // CHECK: @llvm.x86.avx512.pror.d.512
return _mm512_ror_epi32(__A, 5);
}
__m512i test_mm512_mask_ror_epi32(__m512i __W, __mmask16 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_ror_epi32
- // CHECK: @llvm.x86.avx512.mask.pror.d.512
+ // CHECK: @llvm.x86.avx512.pror.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_ror_epi32(__W, __U, __A, 5);
}
__m512i test_mm512_maskz_ror_epi32(__mmask16 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_ror_epi32
- // CHECK: @llvm.x86.avx512.mask.pror.d.512
+ // CHECK: @llvm.x86.avx512.pror.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_ror_epi32(__U, __A, 5);
}
__m512i test_mm512_ror_epi64(__m512i __A) {
// CHECK-LABEL: @test_mm512_ror_epi64
- // CHECK: @llvm.x86.avx512.mask.pror.q.512
+ // CHECK: @llvm.x86.avx512.pror.q.512
return _mm512_ror_epi64(__A, 5);
}
__m512i test_mm512_mask_ror_epi64(__m512i __W, __mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_ror_epi64
- // CHECK: @llvm.x86.avx512.mask.pror.q.512
+ // CHECK: @llvm.x86.avx512.pror.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_ror_epi64(__W, __U, __A, 5);
}
__m512i test_mm512_maskz_ror_epi64(__mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_ror_epi64
- // CHECK: @llvm.x86.avx512.mask.pror.q.512
+ // CHECK: @llvm.x86.avx512.pror.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_ror_epi64(__U, __A, 5);
}
__m512i test_mm512_rorv_epi32(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_rorv_epi32
- // CHECK: @llvm.x86.avx512.mask.prorv.d.512
+ // CHECK: @llvm.x86.avx512.prorv.d.512
return _mm512_rorv_epi32(__A, __B);
}
__m512i test_mm512_mask_rorv_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_rorv_epi32
- // CHECK: @llvm.x86.avx512.mask.prorv.d.512
+ // CHECK: @llvm.x86.avx512.prorv.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_rorv_epi32(__W, __U, __A, __B);
}
__m512i test_mm512_maskz_rorv_epi32(__mmask16 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_rorv_epi32
- // CHECK: @llvm.x86.avx512.mask.prorv.d.512
+ // CHECK: @llvm.x86.avx512.prorv.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_rorv_epi32(__U, __A, __B);
}
__m512i test_mm512_rorv_epi64(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_rorv_epi64
- // CHECK: @llvm.x86.avx512.mask.prorv.q.512
+ // CHECK: @llvm.x86.avx512.prorv.q.512
return _mm512_rorv_epi64(__A, __B);
}
__m512i test_mm512_mask_rorv_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_rorv_epi64
- // CHECK: @llvm.x86.avx512.mask.prorv.q.512
+ // CHECK: @llvm.x86.avx512.prorv.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_rorv_epi64(__W, __U, __A, __B);
}
__m512i test_mm512_maskz_rorv_epi64(__mmask8 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_rorv_epi64
- // CHECK: @llvm.x86.avx512.mask.prorv.q.512
+ // CHECK: @llvm.x86.avx512.prorv.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_rorv_epi64(__U, __A, __B);
}
@@ -3211,7 +4539,8 @@ unsigned long long test_mm_cvt_roundsd_si64(__m128d __A) {
#endif
__m512i test_mm512_mask2_permutex2var_epi32(__m512i __A, __m512i __I, __mmask16 __U, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask2_permutex2var_epi32
- // CHECK: @llvm.x86.avx512.mask.vpermi2var.d.512
+ // CHECK: @llvm.x86.avx512.vpermi2var.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask2_permutex2var_epi32(__A, __I, __U, __B);
}
__m512i test_mm512_unpackhi_epi32(__m512i __A, __m512i __B) {
@@ -3235,7 +4564,8 @@ long long test_mm_cvt_roundsd_i64(__m128d __A) {
#endif
__m512d test_mm512_mask2_permutex2var_pd(__m512d __A, __m512i __I, __mmask8 __U, __m512d __B) {
// CHECK-LABEL: @test_mm512_mask2_permutex2var_pd
- // CHECK: @llvm.x86.avx512.mask.vpermi2var.pd.512
+ // CHECK: @llvm.x86.avx512.vpermi2var.pd.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask2_permutex2var_pd(__A, __I, __U, __B);
}
__m512i test_mm512_mask_unpackhi_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) {
@@ -3337,7 +4667,7 @@ int test_mm_cvt_roundss_i32(__m128 __A) {
}
#ifdef __x86_64__
-int test_mm_cvt_roundss_si64(__m128 __A) {
+long long test_mm_cvt_roundss_si64(__m128 __A) {
// CHECK-LABEL: @test_mm_cvt_roundss_si64
// CHECK: @llvm.x86.avx512.vcvtss2si64
return _mm_cvt_roundss_si64(__A, _MM_FROUND_CUR_DIRECTION);
@@ -3703,52 +5033,54 @@ __m256i test_mm512_maskz_cvt_roundpd_epu32(__mmask8 U, __m512d A)
__m512 test_mm512_mask2_permutex2var_ps(__m512 __A, __m512i __I, __mmask16 __U, __m512 __B) {
// CHECK-LABEL: @test_mm512_mask2_permutex2var_ps
- // CHECK: @llvm.x86.avx512.mask.vpermi2var.ps.512
+ // CHECK: @llvm.x86.avx512.vpermi2var.ps.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask2_permutex2var_ps(__A, __I, __U, __B);
}
__m512i test_mm512_mask2_permutex2var_epi64(__m512i __A, __m512i __I, __mmask8 __U, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask2_permutex2var_epi64
- // CHECK: @llvm.x86.avx512.mask.vpermi2var.q.512
+ // CHECK: @llvm.x86.avx512.vpermi2var.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask2_permutex2var_epi64(__A, __I, __U, __B);
}
__m512d test_mm512_permute_pd(__m512d __X) {
// CHECK-LABEL: @test_mm512_permute_pd
- // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> zeroinitializer, <8 x i32> <i32 0, i32 1, i32 2, i32 2, i32 4, i32 4, i32 6, i32 6>
+ // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 2, i32 4, i32 4, i32 6, i32 6>
return _mm512_permute_pd(__X, 2);
}
__m512d test_mm512_mask_permute_pd(__m512d __W, __mmask8 __U, __m512d __X) {
// CHECK-LABEL: @test_mm512_mask_permute_pd
- // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> zeroinitializer, <8 x i32> <i32 0, i32 1, i32 2, i32 2, i32 4, i32 4, i32 6, i32 6>
+ // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 2, i32 4, i32 4, i32 6, i32 6>
// CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_permute_pd(__W, __U, __X, 2);
}
__m512d test_mm512_maskz_permute_pd(__mmask8 __U, __m512d __X) {
// CHECK-LABEL: @test_mm512_maskz_permute_pd
- // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> zeroinitializer, <8 x i32> <i32 0, i32 1, i32 2, i32 2, i32 4, i32 4, i32 6, i32 6>
+ // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 2, i32 4, i32 4, i32 6, i32 6>
// CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_maskz_permute_pd(__U, __X, 2);
}
__m512 test_mm512_permute_ps(__m512 __X) {
// CHECK-LABEL: @test_mm512_permute_ps
- // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> zeroinitializer, <16 x i32> <i32 2, i32 0, i32 0, i32 0, i32 6, i32 4, i32 4, i32 4, i32 10, i32 8, i32 8, i32 8, i32 14, i32 12, i32 12, i32 12>
+ // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> undef, <16 x i32> <i32 2, i32 0, i32 0, i32 0, i32 6, i32 4, i32 4, i32 4, i32 10, i32 8, i32 8, i32 8, i32 14, i32 12, i32 12, i32 12>
return _mm512_permute_ps(__X, 2);
}
__m512 test_mm512_mask_permute_ps(__m512 __W, __mmask16 __U, __m512 __X) {
// CHECK-LABEL: @test_mm512_mask_permute_ps
- // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> zeroinitializer, <16 x i32> <i32 2, i32 0, i32 0, i32 0, i32 6, i32 4, i32 4, i32 4, i32 10, i32 8, i32 8, i32 8, i32 14, i32 12, i32 12, i32 12>
+ // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> undef, <16 x i32> <i32 2, i32 0, i32 0, i32 0, i32 6, i32 4, i32 4, i32 4, i32 10, i32 8, i32 8, i32 8, i32 14, i32 12, i32 12, i32 12>
// CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_permute_ps(__W, __U, __X, 2);
}
__m512 test_mm512_maskz_permute_ps(__mmask16 __U, __m512 __X) {
// CHECK-LABEL: @test_mm512_maskz_permute_ps
- // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> zeroinitializer, <16 x i32> <i32 2, i32 0, i32 0, i32 0, i32 6, i32 4, i32 4, i32 4, i32 10, i32 8, i32 8, i32 8, i32 14, i32 12, i32 12, i32 12>
+ // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> undef, <16 x i32> <i32 2, i32 0, i32 0, i32 0, i32 6, i32 4, i32 4, i32 4, i32 10, i32 8, i32 8, i32 8, i32 14, i32 12, i32 12, i32 12>
// CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_maskz_permute_ps(__U, __X, 2);
}
@@ -3793,68 +5125,88 @@ __m512 test_mm512_maskz_permutevar_ps(__mmask16 __U, __m512 __A, __m512i __C) {
return _mm512_maskz_permutevar_ps(__U, __A, __C);
}
+__m512i test_mm512_permutex2var_epi32(__m512i __A, __m512i __I, __m512i __B) {
+ // CHECK-LABEL: @test_mm512_permutex2var_epi32
+ // CHECK: @llvm.x86.avx512.vpermi2var.d.512
+ return _mm512_permutex2var_epi32(__A, __I, __B);
+}
+
__m512i test_mm512_maskz_permutex2var_epi32(__mmask16 __U, __m512i __A, __m512i __I, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_permutex2var_epi32
- // CHECK: @llvm.x86.avx512.maskz.vpermt2var.d.512
+ // CHECK: @llvm.x86.avx512.vpermi2var.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_permutex2var_epi32(__U, __A, __I, __B);
}
__m512i test_mm512_mask_permutex2var_epi32 (__m512i __A, __mmask16 __U, __m512i __I, __m512i __B)
{
// CHECK-LABEL: @test_mm512_mask_permutex2var_epi32
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.d.512
+ // CHECK: @llvm.x86.avx512.vpermi2var.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_permutex2var_epi32 (__A,__U,__I,__B);
}
__m512d test_mm512_permutex2var_pd (__m512d __A, __m512i __I, __m512d __B)
{
// CHECK-LABEL: @test_mm512_permutex2var_pd
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.pd.512
+ // CHECK: @llvm.x86.avx512.vpermi2var.pd.512
return _mm512_permutex2var_pd (__A, __I,__B);
}
__m512d test_mm512_mask_permutex2var_pd (__m512d __A, __mmask8 __U, __m512i __I, __m512d __B)
{
// CHECK-LABEL: @test_mm512_mask_permutex2var_pd
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.pd.512
+ // CHECK: @llvm.x86.avx512.vpermi2var.pd.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_permutex2var_pd (__A,__U,__I,__B);
}
__m512d test_mm512_maskz_permutex2var_pd(__mmask8 __U, __m512d __A, __m512i __I, __m512d __B) {
// CHECK-LABEL: @test_mm512_maskz_permutex2var_pd
- // CHECK: @llvm.x86.avx512.maskz.vpermt2var.pd.512
+ // CHECK: @llvm.x86.avx512.vpermi2var.pd.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_maskz_permutex2var_pd(__U, __A, __I, __B);
}
__m512 test_mm512_permutex2var_ps (__m512 __A, __m512i __I, __m512 __B)
{
// CHECK-LABEL: @test_mm512_permutex2var_ps
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.ps.512
+ // CHECK: @llvm.x86.avx512.vpermi2var.ps.512
return _mm512_permutex2var_ps (__A, __I, __B);
}
__m512 test_mm512_mask_permutex2var_ps (__m512 __A, __mmask16 __U, __m512i __I, __m512 __B)
{
// CHECK-LABEL: @test_mm512_mask_permutex2var_ps
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.ps.512
+ // CHECK: @llvm.x86.avx512.vpermi2var.ps.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_permutex2var_ps (__A,__U,__I,__B);
}
__m512 test_mm512_maskz_permutex2var_ps(__mmask16 __U, __m512 __A, __m512i __I, __m512 __B) {
// CHECK-LABEL: @test_mm512_maskz_permutex2var_ps
- // CHECK: @llvm.x86.avx512.maskz.vpermt2var.ps.512
+ // CHECK: @llvm.x86.avx512.vpermi2var.ps.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_maskz_permutex2var_ps(__U, __A, __I, __B);
}
+__m512i test_mm512_permutex2var_epi64 (__m512i __A, __m512i __I, __m512i __B){
+ // CHECK-LABEL: @test_mm512_permutex2var_epi64
+ // CHECK: @llvm.x86.avx512.vpermi2var.q.512
+ return _mm512_permutex2var_epi64(__A, __I, __B);
+}
+
__m512i test_mm512_mask_permutex2var_epi64 (__m512i __A, __mmask8 __U, __m512i __I, __m512i __B){
// CHECK-LABEL: @test_mm512_mask_permutex2var_epi64
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.q.512
+ // CHECK: @llvm.x86.avx512.vpermi2var.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_permutex2var_epi64(__A, __U, __I, __B);
}
__m512i test_mm512_maskz_permutex2var_epi64(__mmask8 __U, __m512i __A, __m512i __I, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_permutex2var_epi64
- // CHECK: @llvm.x86.avx512.maskz.vpermt2var.q.512
+ // CHECK: @llvm.x86.avx512.vpermi2var.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_permutex2var_epi64(__U, __A, __I, __B);
}
__mmask16 test_mm512_testn_epi32_mask(__m512i __A, __m512i __B) {
@@ -4015,19 +5367,19 @@ __m128 test_mm_roundscale_ss(__m128 __A, __m128 __B) {
return _mm_roundscale_ss(__A, __B, 3);
}
-__m128 test_mm_mask_roundscale_ss(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){
+__m128 test_mm_mask_roundscale_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){
// CHECK-LABEL: @test_mm_mask_roundscale_ss
// CHECK: @llvm.x86.avx512.mask.rndscale.ss
return _mm_mask_roundscale_ss(__W,__U,__A,__B,3);
}
-__m128 test_mm_maskz_roundscale_round_ss( __mmask8 __U, __m128d __A, __m128d __B){
+__m128 test_mm_maskz_roundscale_round_ss( __mmask8 __U, __m128 __A, __m128 __B){
// CHECK-LABEL: @test_mm_maskz_roundscale_round_ss
// CHECK: @llvm.x86.avx512.mask.rndscale.ss
return _mm_maskz_roundscale_round_ss(__U,__A,__B,3,_MM_FROUND_CUR_DIRECTION);
}
-__m128 test_mm_maskz_roundscale_ss(__mmask8 __U, __m128d __A, __m128d __B){
+__m128 test_mm_maskz_roundscale_ss(__mmask8 __U, __m128 __A, __m128 __B){
// CHECK-LABEL: @test_mm_maskz_roundscale_ss
// CHECK: @llvm.x86.avx512.mask.rndscale.ss
return _mm_maskz_roundscale_ss(__U,__A,__B,3);
@@ -4107,8 +5459,8 @@ __m512 test_mm512_maskz_scalef_ps(__mmask16 __U, __m512 __A, __m512 __B) {
__m128d test_mm_scalef_round_sd(__m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_scalef_round_sd
- // CHECK: @llvm.x86.avx512.mask.scalef
- return _mm_scalef_round_sd(__A, __B, _MM_FROUND_CUR_DIRECTION);
+ // CHECK: @llvm.x86.avx512.mask.scalef.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %2, i8 -1, i32 8)
+ return _mm_scalef_round_sd(__A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128d test_mm_scalef_sd(__m128d __A, __m128d __B) {
@@ -4125,8 +5477,8 @@ __m128d test_mm_mask_scalef_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d _
__m128d test_mm_mask_scalef_round_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){
// CHECK-LABEL: @test_mm_mask_scalef_round_sd
- // CHECK: @llvm.x86.avx512.mask.scalef.sd
- return _mm_mask_scalef_round_sd(__W, __U, __A, __B, _MM_FROUND_CUR_DIRECTION);
+ // CHECK: @llvm.x86.avx512.mask.scalef.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 %{{.*}}, i32 8)
+ return _mm_mask_scalef_round_sd(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128d test_mm_maskz_scalef_sd(__mmask8 __U, __m128d __A, __m128d __B){
@@ -4137,14 +5489,14 @@ __m128d test_mm_maskz_scalef_sd(__mmask8 __U, __m128d __A, __m128d __B){
__m128d test_mm_maskz_scalef_round_sd(__mmask8 __U, __m128d __A, __m128d __B){
// CHECK-LABEL: @test_mm_maskz_scalef_round_sd
- // CHECK: @llvm.x86.avx512.mask.scalef.sd
- return _mm_maskz_scalef_round_sd(__U, __A, __B, _MM_FROUND_CUR_DIRECTION);
+ // CHECK: @llvm.x86.avx512.mask.scalef.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 %{{.*}}, i32 8)
+ return _mm_maskz_scalef_round_sd(__U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128 test_mm_scalef_round_ss(__m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_scalef_round_ss
- // CHECK: @llvm.x86.avx512.mask.scalef.ss
- return _mm_scalef_round_ss(__A, __B, _MM_FROUND_CUR_DIRECTION);
+ // CHECK: @llvm.x86.avx512.mask.scalef.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 -1, i32 8)
+ return _mm_scalef_round_ss(__A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128 test_mm_scalef_ss(__m128 __A, __m128 __B) {
@@ -4161,8 +5513,8 @@ __m128 test_mm_mask_scalef_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){
__m128 test_mm_mask_scalef_round_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){
// CHECK-LABEL: @test_mm_mask_scalef_round_ss
- // CHECK: @llvm.x86.avx512.mask.scalef.ss
- return _mm_mask_scalef_round_ss(__W, __U, __A, __B, _MM_FROUND_CUR_DIRECTION);
+ // CHECK: @llvm.x86.avx512.mask.scalef.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 %{{.*}}, i32 8)
+ return _mm_mask_scalef_round_ss(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128 test_mm_maskz_scalef_ss(__mmask8 __U, __m128 __A, __m128 __B){
@@ -4173,8 +5525,8 @@ __m128 test_mm_maskz_scalef_ss(__mmask8 __U, __m128 __A, __m128 __B){
__m128 test_mm_maskz_scalef_round_ss(__mmask8 __U, __m128 __A, __m128 __B){
// CHECK-LABEL: @test_mm_maskz_scalef_round_ss
- // CHECK: @llvm.x86.avx512.mask.scalef.ss
- return _mm_maskz_scalef_round_ss(__U, __A, __B, _MM_FROUND_CUR_DIRECTION);
+ // CHECK: @llvm.x86.avx512.mask.scalef.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 %{{.*}}, i32 8)
+ return _mm_maskz_scalef_round_ss(__U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512i test_mm512_srai_epi32(__m512i __A) {
@@ -4459,37 +5811,41 @@ __m512i test_mm512_maskz_srlv_epi64(__mmask8 __U, __m512i __X, __m512i __Y) {
__m512i test_mm512_ternarylogic_epi32(__m512i __A, __m512i __B, __m512i __C) {
// CHECK-LABEL: @test_mm512_ternarylogic_epi32
- // CHECK: @llvm.x86.avx512.mask.pternlog.d.512
+ // CHECK: @llvm.x86.avx512.pternlog.d.512
return _mm512_ternarylogic_epi32(__A, __B, __C, 4);
}
__m512i test_mm512_mask_ternarylogic_epi32(__m512i __A, __mmask16 __U, __m512i __B, __m512i __C) {
// CHECK-LABEL: @test_mm512_mask_ternarylogic_epi32
- // CHECK: @llvm.x86.avx512.mask.pternlog.d.512
+ // CHECK: @llvm.x86.avx512.pternlog.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_ternarylogic_epi32(__A, __U, __B, __C, 4);
}
__m512i test_mm512_maskz_ternarylogic_epi32(__mmask16 __U, __m512i __A, __m512i __B, __m512i __C) {
// CHECK-LABEL: @test_mm512_maskz_ternarylogic_epi32
- // CHECK: @llvm.x86.avx512.maskz.pternlog.d.512
+ // CHECK: @llvm.x86.avx512.pternlog.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> zeroinitializer
return _mm512_maskz_ternarylogic_epi32(__U, __A, __B, __C, 4);
}
__m512i test_mm512_ternarylogic_epi64(__m512i __A, __m512i __B, __m512i __C) {
// CHECK-LABEL: @test_mm512_ternarylogic_epi64
- // CHECK: @llvm.x86.avx512.mask.pternlog.q.512
+ // CHECK: @llvm.x86.avx512.pternlog.q.512
return _mm512_ternarylogic_epi64(__A, __B, __C, 4);
}
__m512i test_mm512_mask_ternarylogic_epi64(__m512i __A, __mmask8 __U, __m512i __B, __m512i __C) {
// CHECK-LABEL: @test_mm512_mask_ternarylogic_epi64
- // CHECK: @llvm.x86.avx512.mask.pternlog.q.512
+ // CHECK: @llvm.x86.avx512.pternlog.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_ternarylogic_epi64(__A, __U, __B, __C, 4);
}
__m512i test_mm512_maskz_ternarylogic_epi64(__mmask8 __U, __m512i __A, __m512i __B, __m512i __C) {
// CHECK-LABEL: @test_mm512_maskz_ternarylogic_epi64
- // CHECK: @llvm.x86.avx512.maskz.pternlog.q.512
+ // CHECK: @llvm.x86.avx512.pternlog.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> zeroinitializer
return _mm512_maskz_ternarylogic_epi64(__U, __A, __B, __C, 4);
}
@@ -4535,20 +5891,20 @@ __m512d test_mm512_maskz_shuffle_f64x2(__mmask8 __U, __m512d __A, __m512d __B) {
__m512i test_mm512_shuffle_i32x4(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_shuffle_i32x4
- // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 8, i32 9>
+ // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 16, i32 17, i32 18, i32 19, i32 16, i32 17, i32 18, i32 19>
return _mm512_shuffle_i32x4(__A, __B, 4);
}
__m512i test_mm512_mask_shuffle_i32x4(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_shuffle_i32x4
- // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 8, i32 9>
+ // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 16, i32 17, i32 18, i32 19, i32 16, i32 17, i32 18, i32 19>
// CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_shuffle_i32x4(__W, __U, __A, __B, 4);
}
__m512i test_mm512_maskz_shuffle_i32x4(__mmask16 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_shuffle_i32x4
- // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 8, i32 9>
+ // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 16, i32 17, i32 18, i32 19, i32 16, i32 17, i32 18, i32 19>
// CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_shuffle_i32x4(__U, __A, __B, 4);
}
@@ -4615,54 +5971,86 @@ __m512 test_mm512_maskz_shuffle_ps(__mmask16 __U, __m512 __M, __m512 __V) {
__m128d test_mm_sqrt_round_sd(__m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_sqrt_round_sd
- // CHECK: @llvm.x86.avx512.mask.sqrt.sd
- return _mm_sqrt_round_sd(__A, __B, 4);
+ // CHECK: call <2 x double> @llvm.x86.avx512.mask.sqrt.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 -1, i32 8)
+ return _mm_sqrt_round_sd(__A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128d test_mm_mask_sqrt_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){
- // CHECK: @llvm.x86.avx512.mask.sqrt.sd
- return _mm_mask_sqrt_sd(__W,__U,__A,__B);
+ // CHECK-LABEL: @test_mm_mask_sqrt_sd
+ // CHECK: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: call double @llvm.sqrt.f64(double %{{.*}})
+ // CHECK-NEXT: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: select i1 {{.*}}, double {{.*}}, double {{.*}}
+ // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double {{.*}}, i64 0
+ return _mm_mask_sqrt_sd(__W,__U,__A,__B);
}
__m128d test_mm_mask_sqrt_round_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){
- // CHECK: @llvm.x86.avx512.mask.sqrt.sd
- return _mm_mask_sqrt_round_sd(__W,__U,__A,__B,_MM_FROUND_CUR_DIRECTION);
+ // CHECK-LABEL: @test_mm_mask_sqrt_round_sd
+ // CHECK: call <2 x double> @llvm.x86.avx512.mask.sqrt.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 %{{.*}}, i32 8)
+ return _mm_mask_sqrt_round_sd(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128d test_mm_maskz_sqrt_sd(__mmask8 __U, __m128d __A, __m128d __B){
- // CHECK: @llvm.x86.avx512.mask.sqrt.sd
- return _mm_maskz_sqrt_sd(__U,__A,__B);
+ // CHECK-LABEL: @test_mm_maskz_sqrt_sd
+ // CHECK: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: call double @llvm.sqrt.f64(double %{{.*}})
+ // CHECK-NEXT: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: select i1 {{.*}}, double {{.*}}, double {{.*}}
+ // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double {{.*}}, i64 0
+ return _mm_maskz_sqrt_sd(__U,__A,__B);
}
__m128d test_mm_maskz_sqrt_round_sd(__mmask8 __U, __m128d __A, __m128d __B){
- // CHECK: @llvm.x86.avx512.mask.sqrt.sd
- return _mm_maskz_sqrt_round_sd(__U,__A,__B,_MM_FROUND_CUR_DIRECTION);
+ // CHECK-LABEL: @test_mm_maskz_sqrt_round_sd
+ // CHECK: call <2 x double> @llvm.x86.avx512.mask.sqrt.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 %{{.*}}, i32 8)
+ return _mm_maskz_sqrt_round_sd(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128 test_mm_sqrt_round_ss(__m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_sqrt_round_ss
- // CHECK: @llvm.x86.avx512.mask.sqrt.ss
- return _mm_sqrt_round_ss(__A, __B, 4);
+ // CHECK: call <4 x float> @llvm.x86.avx512.mask.sqrt.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 -1, i32 8)
+ return _mm_sqrt_round_ss(__A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128 test_mm_mask_sqrt_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){
- // CHECK: @llvm.x86.avx512.mask.sqrt.ss
- return _mm_mask_sqrt_ss(__W,__U,__A,__B);
+ // CHECK-LABEL: @test_mm_mask_sqrt_ss
+ // CHECK: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: call float @llvm.sqrt.f32(float %{{.*}})
+ // CHECK-NEXT: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: select i1 {{.*}}, float {{.*}}, float {{.*}}
+ // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float {{.*}}, i64 0
+ return _mm_mask_sqrt_ss(__W,__U,__A,__B);
}
__m128 test_mm_mask_sqrt_round_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){
- // CHECK: @llvm.x86.avx512.mask.sqrt.ss
- return _mm_mask_sqrt_round_ss(__W,__U,__A,__B,_MM_FROUND_CUR_DIRECTION);
+ // CHECK-LABEL: @test_mm_mask_sqrt_round_ss
+ // CHECK: call <4 x float> @llvm.x86.avx512.mask.sqrt.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 {{.*}}, i32 8)
+ return _mm_mask_sqrt_round_ss(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128 test_mm_maskz_sqrt_ss(__mmask8 __U, __m128 __A, __m128 __B){
- // CHECK: @llvm.x86.avx512.mask.sqrt.ss
- return _mm_maskz_sqrt_ss(__U,__A,__B);
+ // CHECK-LABEL: @test_mm_maskz_sqrt_ss
+ // CHECK: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: call float @llvm.sqrt.f32(float %{{.*}})
+ // CHECK-NEXT: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: select i1 {{.*}}, float {{.*}}, float {{.*}}
+ // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float {{.*}}, i64 0
+ return _mm_maskz_sqrt_ss(__U,__A,__B);
}
__m128 test_mm_maskz_sqrt_round_ss(__mmask8 __U, __m128 __A, __m128 __B){
- // CHECK: @llvm.x86.avx512.mask.sqrt.ss
- return _mm_maskz_sqrt_round_ss(__U,__A,__B,_MM_FROUND_CUR_DIRECTION);
+ // CHECK-LABEL: @test_mm_maskz_sqrt_round_ss
+ // CHECK: call <4 x float> @llvm.x86.avx512.mask.sqrt.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 {{.*}}, i32 8)
+ return _mm_maskz_sqrt_round_ss(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512 test_mm512_broadcast_f32x4(float const* __A) {
@@ -4685,24 +6073,24 @@ __m512 test_mm512_maskz_broadcast_f32x4(__mmask16 __M, float const* __A) {
return _mm512_maskz_broadcast_f32x4(__M, _mm_loadu_ps(__A));
}
-__m512d test_mm512_broadcast_f64x4(float const* __A) {
+__m512d test_mm512_broadcast_f64x4(double const* __A) {
// CHECK-LABEL: @test_mm512_broadcast_f64x4
// CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 0, i32 1, i32 2, i32 3>
- return _mm512_broadcast_f64x4(_mm256_loadu_ps(__A));
+ return _mm512_broadcast_f64x4(_mm256_loadu_pd(__A));
}
-__m512d test_mm512_mask_broadcast_f64x4(__m512d __O, __mmask8 __M, float const* __A) {
+__m512d test_mm512_mask_broadcast_f64x4(__m512d __O, __mmask8 __M, double const* __A) {
// CHECK-LABEL: @test_mm512_mask_broadcast_f64x4
// CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 0, i32 1, i32 2, i32 3>
// CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
- return _mm512_mask_broadcast_f64x4(__O, __M, _mm256_loadu_ps(__A));
+ return _mm512_mask_broadcast_f64x4(__O, __M, _mm256_loadu_pd(__A));
}
-__m512d test_mm512_maskz_broadcast_f64x4(__mmask8 __M, float const* __A) {
+__m512d test_mm512_maskz_broadcast_f64x4(__mmask8 __M, double const* __A) {
// CHECK-LABEL: @test_mm512_maskz_broadcast_f64x4
// CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 0, i32 1, i32 2, i32 3>
// CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
- return _mm512_maskz_broadcast_f64x4(__M, _mm256_loadu_ps(__A));
+ return _mm512_maskz_broadcast_f64x4(__M, _mm256_loadu_pd(__A));
}
__m512i test_mm512_broadcast_i32x4(__m128i const* __A) {
@@ -4747,80 +6135,80 @@ __m512i test_mm512_maskz_broadcast_i64x4(__mmask8 __M, __m256i const* __A) {
__m512d test_mm512_broadcastsd_pd(__m128d __A) {
// CHECK-LABEL: @test_mm512_broadcastsd_pd
- // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> zeroinitializer, <8 x i32> zeroinitializer
+ // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> %{{.*}}, <8 x i32> zeroinitializer
return _mm512_broadcastsd_pd(__A);
}
__m512d test_mm512_mask_broadcastsd_pd(__m512d __O, __mmask8 __M, __m128d __A) {
// CHECK-LABEL: @test_mm512_mask_broadcastsd_pd
- // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> zeroinitializer, <8 x i32> zeroinitializer
+ // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> %{{.*}}, <8 x i32> zeroinitializer
// CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_broadcastsd_pd(__O, __M, __A);
}
__m512d test_mm512_maskz_broadcastsd_pd(__mmask8 __M, __m128d __A) {
// CHECK-LABEL: @test_mm512_maskz_broadcastsd_pd
- // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> zeroinitializer, <8 x i32> zeroinitializer
+ // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> %{{.*}}, <8 x i32> zeroinitializer
// CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_maskz_broadcastsd_pd(__M, __A);
}
__m512 test_mm512_broadcastss_ps(__m128 __A) {
// CHECK-LABEL: @test_mm512_broadcastss_ps
- // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> zeroinitializer, <16 x i32> zeroinitializer
+ // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <16 x i32> zeroinitializer
return _mm512_broadcastss_ps(__A);
}
__m512 test_mm512_mask_broadcastss_ps(__m512 __O, __mmask16 __M, __m128 __A) {
// CHECK-LABEL: @test_mm512_mask_broadcastss_ps
- // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> zeroinitializer, <16 x i32> zeroinitializer
+ // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <16 x i32> zeroinitializer
// CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_broadcastss_ps(__O, __M, __A);
}
__m512 test_mm512_maskz_broadcastss_ps(__mmask16 __M, __m128 __A) {
// CHECK-LABEL: @test_mm512_maskz_broadcastss_ps
- // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> zeroinitializer, <16 x i32> zeroinitializer
+ // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <16 x i32> zeroinitializer
// CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_maskz_broadcastss_ps(__M, __A);
}
__m512i test_mm512_broadcastd_epi32(__m128i __A) {
// CHECK-LABEL: @test_mm512_broadcastd_epi32
- // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> zeroinitializer, <16 x i32> zeroinitializer
+ // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <16 x i32> zeroinitializer
return _mm512_broadcastd_epi32(__A);
}
__m512i test_mm512_mask_broadcastd_epi32(__m512i __O, __mmask16 __M, __m128i __A) {
// CHECK-LABEL: @test_mm512_mask_broadcastd_epi32
- // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> zeroinitializer, <16 x i32> zeroinitializer
+ // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <16 x i32> zeroinitializer
// CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_broadcastd_epi32(__O, __M, __A);
}
__m512i test_mm512_maskz_broadcastd_epi32(__mmask16 __M, __m128i __A) {
// CHECK-LABEL: @test_mm512_maskz_broadcastd_epi32
- // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> zeroinitializer, <16 x i32> zeroinitializer
+ // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <16 x i32> zeroinitializer
// CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_broadcastd_epi32(__M, __A);
}
__m512i test_mm512_broadcastq_epi64(__m128i __A) {
// CHECK-LABEL: @test_mm512_broadcastq_epi64
- // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> zeroinitializer, <8 x i32> zeroinitializer
+ // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <8 x i32> zeroinitializer
return _mm512_broadcastq_epi64(__A);
}
__m512i test_mm512_mask_broadcastq_epi64(__m512i __O, __mmask8 __M, __m128i __A) {
// CHECK-LABEL: @test_mm512_mask_broadcastq_epi64
- // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> zeroinitializer, <8 x i32> zeroinitializer
+ // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <8 x i32> zeroinitializer
// CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_broadcastq_epi64(__O, __M, __A);
}
__m512i test_mm512_maskz_broadcastq_epi64(__mmask8 __M, __m128i __A) {
// CHECK-LABEL: @test_mm512_maskz_broadcastq_epi64
- // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> zeroinitializer, <8 x i32> zeroinitializer
+ // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <8 x i32> zeroinitializer
// CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_broadcastq_epi64(__M, __A);
}
@@ -5067,7 +6455,7 @@ void test_mm512_mask_cvtusepi64_storeu_epi16(void *__P, __mmask8 __M, __m512i __
__m128i test_mm512_cvtepi32_epi8(__m512i __A) {
// CHECK-LABEL: @test_mm512_cvtepi32_epi8
- // CHECK: @llvm.x86.avx512.mask.pmov.db.512
+ // CHECK: trunc <16 x i32> %{{.*}} to <16 x i8>
return _mm512_cvtepi32_epi8(__A);
}
@@ -5091,7 +6479,7 @@ void test_mm512_mask_cvtepi32_storeu_epi8(void * __P, __mmask16 __M, __m512i __A
__m256i test_mm512_cvtepi32_epi16(__m512i __A) {
// CHECK-LABEL: @test_mm512_cvtepi32_epi16
- // CHECK: @llvm.x86.avx512.mask.pmov.dw.512
+ // CHECK: trunc <16 x i32> %{{.*}} to <16 x i16>
return _mm512_cvtepi32_epi16(__A);
}
@@ -5139,19 +6527,21 @@ void test_mm512_mask_cvtepi64_storeu_epi8(void * __P, __mmask8 __M, __m512i __A)
__m256i test_mm512_cvtepi64_epi32(__m512i __A) {
// CHECK-LABEL: @test_mm512_cvtepi64_epi32
- // CHECK: @llvm.x86.avx512.mask.pmov.qd.512
+ // CHECK: trunc <8 x i64> %{{.*}} to <8 x i32>
return _mm512_cvtepi64_epi32(__A);
}
__m256i test_mm512_mask_cvtepi64_epi32(__m256i __O, __mmask8 __M, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_cvtepi64_epi32
- // CHECK: @llvm.x86.avx512.mask.pmov.qd.512
+ // CHECK: trunc <8 x i64> %{{.*}} to <8 x i32>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm512_mask_cvtepi64_epi32(__O, __M, __A);
}
__m256i test_mm512_maskz_cvtepi64_epi32(__mmask8 __M, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_cvtepi64_epi32
- // CHECK: @llvm.x86.avx512.mask.pmov.qd.512
+ // CHECK: trunc <8 x i64> %{{.*}} to <8 x i32>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm512_maskz_cvtepi64_epi32(__M, __A);
}
@@ -5163,7 +6553,7 @@ void test_mm512_mask_cvtepi64_storeu_epi32(void* __P, __mmask8 __M, __m512i __A)
__m128i test_mm512_cvtepi64_epi16(__m512i __A) {
// CHECK-LABEL: @test_mm512_cvtepi64_epi16
- // CHECK: @llvm.x86.avx512.mask.pmov.qw.512
+ // CHECK: trunc <8 x i64> %{{.*}} to <8 x i16>
return _mm512_cvtepi64_epi16(__A);
}
@@ -5187,40 +6577,40 @@ void test_mm512_mask_cvtepi64_storeu_epi16(void *__P, __mmask8 __M, __m512i __A)
__m128i test_mm512_extracti32x4_epi32(__m512i __A) {
// CHECK-LABEL: @test_mm512_extracti32x4_epi32
- // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <4 x i32> <i32 12, i32 13, i32 14, i32 15>
+ // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> undef, <4 x i32> <i32 12, i32 13, i32 14, i32 15>
return _mm512_extracti32x4_epi32(__A, 3);
}
__m128i test_mm512_mask_extracti32x4_epi32(__m128i __W, __mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_extracti32x4_epi32
- // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <4 x i32> <i32 12, i32 13, i32 14, i32 15>
+ // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> undef, <4 x i32> <i32 12, i32 13, i32 14, i32 15>
// CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm512_mask_extracti32x4_epi32(__W, __U, __A, 3);
}
__m128i test_mm512_maskz_extracti32x4_epi32(__mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_extracti32x4_epi32
- // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <4 x i32> <i32 12, i32 13, i32 14, i32 15>
+ // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> undef, <4 x i32> <i32 12, i32 13, i32 14, i32 15>
// CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm512_maskz_extracti32x4_epi32(__U, __A, 3);
}
__m256i test_mm512_extracti64x4_epi64(__m512i __A) {
// CHECK-LABEL: @test_mm512_extracti64x4_epi64
- // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> zeroinitializer, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
return _mm512_extracti64x4_epi64(__A, 1);
}
__m256i test_mm512_mask_extracti64x4_epi64(__m256i __W, __mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_extracti64x4_epi64
- // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> zeroinitializer, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm512_mask_extracti64x4_epi64(__W, __U, __A, 1);
}
__m256i test_mm512_maskz_extracti64x4_epi64(__mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_extracti64x4_epi64
- // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> zeroinitializer, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm512_maskz_extracti64x4_epi64(__U, __A, 1);
}
@@ -5815,401 +7205,889 @@ __m128 test_mm_maskz_getmant_round_ss(__mmask8 __U, __m128 __A, __m128 __B){
__m128 test_mm_mask_fmadd_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){
// CHECK-LABEL: @test_mm_mask_fmadd_ss
- // CHECK: @llvm.x86.avx512.mask.vfmadd.ss
+ // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.fma.f32(float [[A]], float [[B]], float [[C]])
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float [[A]]
+ // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[SEL]], i64 0
return _mm_mask_fmadd_ss(__W, __U, __A, __B);
}
+__m128 test_mm_fmadd_round_ss(__m128 __A, __m128 __B, __m128 __C){
+ // CHECK-LABEL: @test_mm_fmadd_round_ss
+ // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.x86.avx512.vfmadd.f32(float [[A]], float [[B]], float [[C]], i32 8)
+ // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[FMA]], i64 0
+ return _mm_fmadd_round_ss(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
+}
+
__m128 test_mm_mask_fmadd_round_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){
// CHECK-LABEL: @test_mm_mask_fmadd_round_ss
- // CHECK: @llvm.x86.avx512.mask.vfmadd.ss
- return _mm_mask_fmadd_round_ss(__W, __U, __A, __B, _MM_FROUND_CUR_DIRECTION);
+ // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.x86.avx512.vfmadd.f32(float [[A]], float [[B]], float [[C]], i32 8)
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float [[A]]
+ // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[SEL]], i64 0
+ return _mm_mask_fmadd_round_ss(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128 test_mm_maskz_fmadd_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){
// CHECK-LABEL: @test_mm_maskz_fmadd_ss
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.ss
+ // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.fma.f32(float [[A]], float [[B]], float [[C]])
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float 0.000000e+00
+ // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[SEL]], i64 0
return _mm_maskz_fmadd_ss(__U, __A, __B, __C);
}
__m128 test_mm_maskz_fmadd_round_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){
// CHECK-LABEL: @test_mm_maskz_fmadd_round_ss
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.ss
- return _mm_maskz_fmadd_round_ss(__U, __A, __B, __C, _MM_FROUND_CUR_DIRECTION);
+ // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.x86.avx512.vfmadd.f32(float [[A]], float [[B]], float [[C]], i32 8)
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float 0.000000e+00
+ // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[SEL]], i64 0
+ return _mm_maskz_fmadd_round_ss(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128 test_mm_mask3_fmadd_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){
// CHECK-LABEL: @test_mm_mask3_fmadd_ss
- // CHECK: @llvm.x86.avx512.mask3.vfmadd.ss
+ // CHECK: [[A:%.+]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[ORIGC:%.+]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.fma.f32(float [[A]], float [[B]], float [[C]])
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float [[C]]
+ // CHECK-NEXT: insertelement <4 x float> [[ORIGC]], float [[SEL]], i64 0
return _mm_mask3_fmadd_ss(__W, __X, __Y, __U);
}
__m128 test_mm_mask3_fmadd_round_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){
// CHECK-LABEL: @test_mm_mask3_fmadd_round_ss
- // CHECK: @llvm.x86.avx512.mask3.vfmadd.ss
- return _mm_mask3_fmadd_round_ss(__W, __X, __Y, __U, _MM_FROUND_CUR_DIRECTION);
+ // CHECK: [[A:%.+]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[ORIGC:%.+]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.x86.avx512.vfmadd.f32(float [[A]], float [[B]], float [[C]], i32 8)
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float [[C]]
+ // CHECK-NEXT: insertelement <4 x float> [[ORIGC]], float [[SEL]], i64 0
+ return _mm_mask3_fmadd_round_ss(__W, __X, __Y, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128 test_mm_mask_fmsub_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){
// CHECK-LABEL: @test_mm_mask_fmsub_ss
- // CHECK: @llvm.x86.avx512.mask.vfmadd.ss
+ // CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[NEG]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.fma.f32(float [[A]], float [[B]], float [[C]])
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float [[A]]
+ // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[SEL]], i64 0
return _mm_mask_fmsub_ss(__W, __U, __A, __B);
}
+__m128 test_mm_fmsub_round_ss(__m128 __A, __m128 __B, __m128 __C){
+ // CHECK-LABEL: @test_mm_fmsub_round_ss
+ // CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[NEG]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.x86.avx512.vfmadd.f32(float [[A]], float [[B]], float [[C]], i32 8)
+ // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[FMA]], i64 0
+ return _mm_fmsub_round_ss(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
+}
+
__m128 test_mm_mask_fmsub_round_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){
// CHECK-LABEL: @test_mm_mask_fmsub_round_ss
- // CHECK: @llvm.x86.avx512.mask.vfmadd.ss
- return _mm_mask_fmsub_round_ss(__W, __U, __A, __B, _MM_FROUND_CUR_DIRECTION);
+ // CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[NEG]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.x86.avx512.vfmadd.f32(float [[A]], float [[B]], float [[C]], i32 8)
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float [[A]]
+ // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[SEL]], i64 0
+ return _mm_mask_fmsub_round_ss(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128 test_mm_maskz_fmsub_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){
// CHECK-LABEL: @test_mm_maskz_fmsub_ss
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.ss
+ // CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[NEG]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.fma.f32(float [[A]], float [[B]], float [[C]])
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float 0.000000e+00
+ // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[SEL]], i64 0
return _mm_maskz_fmsub_ss(__U, __A, __B, __C);
}
__m128 test_mm_maskz_fmsub_round_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){
// CHECK-LABEL: @test_mm_maskz_fmsub_round_ss
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.ss
- return _mm_maskz_fmsub_round_ss(__U, __A, __B, __C, _MM_FROUND_CUR_DIRECTION);
+ // CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[NEG]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.x86.avx512.vfmadd.f32(float [[A]], float [[B]], float [[C]], i32 8)
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float 0.000000e+00
+ // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[SEL]], i64 0
+ return _mm_maskz_fmsub_round_ss(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128 test_mm_mask3_fmsub_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){
// CHECK-LABEL: @test_mm_mask3_fmsub_ss
- // CHECK: @llvm.x86.avx512.mask3.vfmsub.ss
+ // CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, [[ORIGC:%.+]]
+ // CHECK: [[A:%.+]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[NEG]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.fma.f32(float [[A]], float [[B]], float [[C]])
+ // CHECK-NEXT: [[C2:%.+]] = extractelement <4 x float> [[ORIGC]], i64 0
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float [[C2]]
+ // CHECK-NEXT: insertelement <4 x float> [[ORIGC]], float [[SEL]], i64 0
return _mm_mask3_fmsub_ss(__W, __X, __Y, __U);
}
__m128 test_mm_mask3_fmsub_round_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){
// CHECK-LABEL: @test_mm_mask3_fmsub_round_ss
- // CHECK: @llvm.x86.avx512.mask3.vfmsub.ss
- return _mm_mask3_fmsub_round_ss(__W, __X, __Y, __U, _MM_FROUND_CUR_DIRECTION);
+ // CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, [[ORIGC:%.+]]
+ // CHECK: [[A:%.+]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[NEG]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.x86.avx512.vfmadd.f32(float [[A]], float [[B]], float [[C]], i32 8)
+ // CHECK-NEXT: [[C2:%.+]] = extractelement <4 x float> [[ORIGC]], i64 0
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float [[C2]]
+ // CHECK-NEXT: insertelement <4 x float> [[ORIGC]], float [[SEL]], i64 0
+ return _mm_mask3_fmsub_round_ss(__W, __X, __Y, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128 test_mm_mask_fnmadd_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){
// CHECK-LABEL: @test_mm_mask_fnmadd_ss
- // CHECK: @llvm.x86.avx512.mask.vfmadd.ss
+ // CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> [[NEG]], i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.fma.f32(float [[A]], float [[B]], float [[C]])
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float [[A]]
+ // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[SEL]], i64 0
return _mm_mask_fnmadd_ss(__W, __U, __A, __B);
}
+__m128 test_mm_fnmadd_round_ss(__m128 __A, __m128 __B, __m128 __C){
+ // CHECK-LABEL: @test_mm_fnmadd_round_ss
+ // CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> [[NEG]], i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.x86.avx512.vfmadd.f32(float [[A]], float [[B]], float [[C]], i32 8)
+ // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[FMA]], i64 0
+ return _mm_fnmadd_round_ss(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
+}
+
__m128 test_mm_mask_fnmadd_round_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){
// CHECK-LABEL: @test_mm_mask_fnmadd_round_ss
- // CHECK: @llvm.x86.avx512.mask.vfmadd.ss
- return _mm_mask_fnmadd_round_ss(__W, __U, __A, __B, _MM_FROUND_CUR_DIRECTION);
+ // CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> [[NEG]], i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.x86.avx512.vfmadd.f32(float [[A]], float [[B]], float [[C]], i32 8)
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float [[A]]
+ // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[SEL]], i64 0
+ return _mm_mask_fnmadd_round_ss(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128 test_mm_maskz_fnmadd_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){
// CHECK-LABEL: @test_mm_maskz_fnmadd_ss
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.ss
+ // CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> [[NEG]], i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.fma.f32(float [[A]], float [[B]], float [[C]])
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float 0.000000e+00
+ // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[SEL]], i64 0
return _mm_maskz_fnmadd_ss(__U, __A, __B, __C);
}
__m128 test_mm_maskz_fnmadd_round_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){
// CHECK-LABEL: @test_mm_maskz_fnmadd_round_ss
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.ss
- return _mm_maskz_fnmadd_round_ss(__U, __A, __B, __C, _MM_FROUND_CUR_DIRECTION);
+ // CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> [[NEG]], i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.x86.avx512.vfmadd.f32(float [[A]], float [[B]], float [[C]], i32 8)
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float 0.000000e+00
+ // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[SEL]], i64 0
+ return _mm_maskz_fnmadd_round_ss(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128 test_mm_mask3_fnmadd_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){
// CHECK-LABEL: @test_mm_mask3_fnmadd_ss
- // CHECK: @llvm.x86.avx512.mask3.vfmadd.ss
+ // CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> [[NEG]], i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[ORIGC:%.+]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.fma.f32(float [[A]], float [[B]], float [[C]])
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float [[C]]
+ // CHECK-NEXT: insertelement <4 x float> [[ORIGC]], float [[SEL]], i64 0
return _mm_mask3_fnmadd_ss(__W, __X, __Y, __U);
}
__m128 test_mm_mask3_fnmadd_round_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){
// CHECK-LABEL: @test_mm_mask3_fnmadd_round_ss
- // CHECK: @llvm.x86.avx512.mask3.vfmadd.ss
- return _mm_mask3_fnmadd_round_ss(__W, __X, __Y, __U, _MM_FROUND_CUR_DIRECTION);
+ // CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> [[NEG]], i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[ORIGC:%.+]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.x86.avx512.vfmadd.f32(float [[A]], float [[B]], float [[C]], i32 8)
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float [[C]]
+ // CHECK-NEXT: insertelement <4 x float> [[ORIGC]], float [[SEL]], i64 0
+ return _mm_mask3_fnmadd_round_ss(__W, __X, __Y, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128 test_mm_mask_fnmsub_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){
// CHECK-LABEL: @test_mm_mask_fnmsub_ss
- // CHECK: @llvm.x86.avx512.mask.vfmadd.ss
+ // CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[NEG2:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> [[NEG]], i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[NEG2]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.fma.f32(float [[A]], float [[B]], float [[C]])
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float [[A]]
+ // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[SEL]], i64 0
return _mm_mask_fnmsub_ss(__W, __U, __A, __B);
}
+__m128 test_mm_fnmsub_round_ss(__m128 __A, __m128 __B, __m128 __C){
+ // CHECK-LABEL: @test_mm_fnmsub_round_ss
+ // CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[NEG2:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> [[NEG]], i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[NEG2]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.x86.avx512.vfmadd.f32(float [[A]], float [[B]], float [[C]], i32 8)
+ // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[FMA]], i64 0
+ return _mm_fnmsub_round_ss(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
+}
+
__m128 test_mm_mask_fnmsub_round_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){
// CHECK-LABEL: @test_mm_mask_fnmsub_round_ss
- // CHECK: @llvm.x86.avx512.mask.vfmadd.ss
- return _mm_mask_fnmsub_round_ss(__W, __U, __A, __B, _MM_FROUND_CUR_DIRECTION);
+ // CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[NEG2:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> [[NEG]], i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[NEG2]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.x86.avx512.vfmadd.f32(float [[A]], float [[B]], float [[C]], i32 8)
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float [[A]]
+ // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[SEL]], i64 0
+ return _mm_mask_fnmsub_round_ss(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128 test_mm_maskz_fnmsub_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){
// CHECK-LABEL: @test_mm_maskz_fnmsub_ss
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.ss
+ // CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[NEG2:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> [[NEG]], i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[NEG2]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.fma.f32(float [[A]], float [[B]], float [[C]])
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float 0.000000e+00
+ // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[SEL]], i64 0
return _mm_maskz_fnmsub_ss(__U, __A, __B, __C);
}
__m128 test_mm_maskz_fnmsub_round_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){
// CHECK-LABEL: @test_mm_maskz_fnmsub_round_ss
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.ss
- return _mm_maskz_fnmsub_round_ss(__U, __A, __B, __C, _MM_FROUND_CUR_DIRECTION);
+ // CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[NEG2:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> [[NEG]], i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[NEG2]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.x86.avx512.vfmadd.f32(float [[A]], float [[B]], float [[C]], i32 8)
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float 0.000000e+00
+ // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[SEL]], i64 0
+ return _mm_maskz_fnmsub_round_ss(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128 test_mm_mask3_fnmsub_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){
// CHECK-LABEL: @test_mm_mask3_fnmsub_ss
- // CHECK: @llvm.x86.avx512.mask3.vfnmsub.ss
+ // CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[NEG2:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, [[ORIGC:%.+]]
+ // CHECK: [[A:%.+]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> [[NEG]], i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[NEG2]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.fma.f32(float [[A]], float [[B]], float [[C]])
+ // CHECK-NEXT: [[C2:%.+]] = extractelement <4 x float> [[ORIGC]], i64 0
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float [[C2]]
+ // CHECK-NEXT: insertelement <4 x float> [[ORIGC]], float [[SEL]], i64 0
return _mm_mask3_fnmsub_ss(__W, __X, __Y, __U);
}
__m128 test_mm_mask3_fnmsub_round_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){
// CHECK-LABEL: @test_mm_mask3_fnmsub_round_ss
- // CHECK: @llvm.x86.avx512.mask3.vfnmsub.ss
- return _mm_mask3_fnmsub_round_ss(__W, __X, __Y, __U, _MM_FROUND_CUR_DIRECTION);
+ // CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[NEG2:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, [[ORIGC:%.+]]
+ // CHECK: [[A:%.+]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> [[NEG]], i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[NEG2]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.x86.avx512.vfmadd.f32(float [[A]], float [[B]], float [[C]], i32 8)
+ // CHECK-NEXT: [[C2:%.+]] = extractelement <4 x float> [[ORIGC]], i64 0
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float [[C2]]
+ // CHECK-NEXT: insertelement <4 x float> [[ORIGC]], float [[SEL]], i64 0
+ return _mm_mask3_fnmsub_round_ss(__W, __X, __Y, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128d test_mm_mask_fmadd_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){
// CHECK-LABEL: @test_mm_mask_fmadd_sd
- // CHECK: @llvm.x86.avx512.mask.vfmadd.sd
+ // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.fma.f64(double [[A]], double [[B]], double [[C]])
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double [[A]]
+ // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[SEL]], i64 0
return _mm_mask_fmadd_sd(__W, __U, __A, __B);
}
+__m128d test_mm_fmadd_round_sd(__m128d __A, __m128d __B, __m128d __C){
+ // CHECK-LABEL: @test_mm_fmadd_round_sd
+ // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.x86.avx512.vfmadd.f64(double [[A]], double [[B]], double [[C]], i32 8)
+ // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[FMA]], i64 0
+ return _mm_fmadd_round_sd(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
+}
+
__m128d test_mm_mask_fmadd_round_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){
// CHECK-LABEL: @test_mm_mask_fmadd_round_sd
- // CHECK: @llvm.x86.avx512.mask.vfmadd.sd
- return _mm_mask_fmadd_round_sd(__W, __U, __A, __B, _MM_FROUND_CUR_DIRECTION);
+ // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.x86.avx512.vfmadd.f64(double [[A]], double [[B]], double [[C]], i32 8)
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double [[A]]
+ // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[SEL]], i64 0
+ return _mm_mask_fmadd_round_sd(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128d test_mm_maskz_fmadd_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C){
// CHECK-LABEL: @test_mm_maskz_fmadd_sd
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.sd
+ // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.fma.f64(double [[A]], double [[B]], double [[C]])
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double 0.000000e+00
+ // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[SEL]], i64 0
return _mm_maskz_fmadd_sd(__U, __A, __B, __C);
}
__m128d test_mm_maskz_fmadd_round_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C){
// CHECK-LABEL: @test_mm_maskz_fmadd_round_sd
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.sd
- return _mm_maskz_fmadd_round_sd(__U, __A, __B, __C, _MM_FROUND_CUR_DIRECTION);
+ // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.x86.avx512.vfmadd.f64(double [[A]], double [[B]], double [[C]], i32 8)
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double 0.000000e+00
+ // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[SEL]], i64 0
+ return _mm_maskz_fmadd_round_sd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128d test_mm_mask3_fmadd_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U){
// CHECK-LABEL: @test_mm_mask3_fmadd_sd
- // CHECK: @llvm.x86.avx512.mask3.vfmadd.sd
+ // CHECK: [[A:%.+]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[ORIGC:%.+]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.fma.f64(double [[A]], double [[B]], double [[C]])
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double [[C]]
+ // CHECK-NEXT: insertelement <2 x double> [[ORIGC]], double [[SEL]], i64 0
return _mm_mask3_fmadd_sd(__W, __X, __Y, __U);
}
__m128d test_mm_mask3_fmadd_round_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U){
// CHECK-LABEL: @test_mm_mask3_fmadd_round_sd
- // CHECK: @llvm.x86.avx512.mask3.vfmadd.sd
- return _mm_mask3_fmadd_round_sd(__W, __X, __Y, __U, _MM_FROUND_CUR_DIRECTION);
+ // CHECK: [[A:%.+]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[ORIGC:%.+]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.x86.avx512.vfmadd.f64(double [[A]], double [[B]], double [[C]], i32 8)
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double [[C]]
+ // CHECK-NEXT: insertelement <2 x double> [[ORIGC]], double [[SEL]], i64 0
+ return _mm_mask3_fmadd_round_sd(__W, __X, __Y, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128d test_mm_mask_fmsub_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){
// CHECK-LABEL: @test_mm_mask_fmsub_sd
- // CHECK: @llvm.x86.avx512.mask.vfmadd.sd
+ // CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[NEG]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.fma.f64(double [[A]], double [[B]], double [[C]])
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double [[A]]
+ // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[SEL]], i64 0
return _mm_mask_fmsub_sd(__W, __U, __A, __B);
}
+__m128d test_mm_fmsub_round_sd(__m128d __A, __m128d __B, __m128d __C){
+ // CHECK-LABEL: @test_mm_fmsub_round_sd
+ // CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[NEG]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.x86.avx512.vfmadd.f64(double [[A]], double [[B]], double [[C]], i32 8)
+ // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[FMA]], i64 0
+ return _mm_fmsub_round_sd(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
+}
+
__m128d test_mm_mask_fmsub_round_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){
// CHECK-LABEL: @test_mm_mask_fmsub_round_sd
- // CHECK: @llvm.x86.avx512.mask.vfmadd.sd
- return _mm_mask_fmsub_round_sd(__W, __U, __A, __B, _MM_FROUND_CUR_DIRECTION);
+ // CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[NEG]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.x86.avx512.vfmadd.f64(double [[A]], double [[B]], double [[C]], i32 8)
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double [[A]]
+ // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[SEL]], i64 0
+ return _mm_mask_fmsub_round_sd(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128d test_mm_maskz_fmsub_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C){
// CHECK-LABEL: @test_mm_maskz_fmsub_sd
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.sd
+ // CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[NEG]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.fma.f64(double [[A]], double [[B]], double [[C]])
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double 0.000000e+00
+ // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[SEL]], i64 0
return _mm_maskz_fmsub_sd(__U, __A, __B, __C);
}
__m128d test_mm_maskz_fmsub_round_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C){
// CHECK-LABEL: @test_mm_maskz_fmsub_round_sd
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.sd
- return _mm_maskz_fmsub_round_sd(__U, __A, __B, __C, _MM_FROUND_CUR_DIRECTION);
+ // CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[NEG]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.x86.avx512.vfmadd.f64(double [[A]], double [[B]], double [[C]], i32 8)
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double 0.000000e+00
+ // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[SEL]], i64 0
+ return _mm_maskz_fmsub_round_sd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128d test_mm_mask3_fmsub_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U){
// CHECK-LABEL: @test_mm_mask3_fmsub_sd
- // CHECK: @llvm.x86.avx512.mask3.vfmsub.sd
+ // CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, [[ORIGC:%.+]]
+ // CHECK: [[A:%.+]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[NEG]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.fma.f64(double [[A]], double [[B]], double [[C]])
+ // CHECK-NEXT: [[C2:%.+]] = extractelement <2 x double> [[ORIGC]], i64 0
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double [[C2]]
+ // CHECK-NEXT: insertelement <2 x double> [[ORIGC]], double [[SEL]], i64 0
return _mm_mask3_fmsub_sd(__W, __X, __Y, __U);
}
__m128d test_mm_mask3_fmsub_round_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U){
// CHECK-LABEL: @test_mm_mask3_fmsub_round_sd
- // CHECK: @llvm.x86.avx512.mask3.vfmsub.sd
- return _mm_mask3_fmsub_round_sd(__W, __X, __Y, __U, _MM_FROUND_CUR_DIRECTION);
+ // CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, [[ORIGC:%.+]]
+ // CHECK: [[A:%.+]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[NEG]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.x86.avx512.vfmadd.f64(double [[A]], double [[B]], double [[C]], i32 8)
+ // CHECK-NEXT: [[C2:%.+]] = extractelement <2 x double> [[ORIGC]], i64 0
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double [[C2]]
+ // CHECK-NEXT: insertelement <2 x double> [[ORIGC]], double [[SEL]], i64 0
+ return _mm_mask3_fmsub_round_sd(__W, __X, __Y, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128d test_mm_mask_fnmadd_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){
// CHECK-LABEL: @test_mm_mask_fnmadd_sd
- // CHECK: @llvm.x86.avx512.mask.vfmadd.sd
+ // CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> [[NEG]], i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.fma.f64(double [[A]], double [[B]], double [[C]])
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double [[A]]
+ // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[SEL]], i64 0
return _mm_mask_fnmadd_sd(__W, __U, __A, __B);
}
+__m128d test_mm_fnmadd_round_sd(__m128d __A, __m128d __B, __m128d __C){
+ // CHECK-LABEL: @test_mm_fnmadd_round_sd
+ // CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> [[NEG]], i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.x86.avx512.vfmadd.f64(double [[A]], double [[B]], double [[C]], i32 8)
+ // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[FMA]], i64 0
+ return _mm_fnmadd_round_sd(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
+}
+
__m128d test_mm_mask_fnmadd_round_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){
// CHECK-LABEL: @test_mm_mask_fnmadd_round_sd
- // CHECK: @llvm.x86.avx512.mask.vfmadd.sd
- return _mm_mask_fnmadd_round_sd(__W, __U, __A, __B, _MM_FROUND_CUR_DIRECTION);
+ // CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> [[NEG]], i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.x86.avx512.vfmadd.f64(double [[A]], double [[B]], double [[C]], i32 8)
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double [[A]]
+ // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[SEL]], i64 0
+ return _mm_mask_fnmadd_round_sd(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128d test_mm_maskz_fnmadd_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C){
// CHECK-LABEL: @test_mm_maskz_fnmadd_sd
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.sd
+ // CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> [[NEG]], i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.fma.f64(double [[A]], double [[B]], double [[C]])
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double 0.000000e+00
+ // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[SEL]], i64 0
return _mm_maskz_fnmadd_sd(__U, __A, __B, __C);
}
__m128d test_mm_maskz_fnmadd_round_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C){
// CHECK-LABEL: @test_mm_maskz_fnmadd_round_sd
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.sd
- return _mm_maskz_fnmadd_round_sd(__U, __A, __B, __C, _MM_FROUND_CUR_DIRECTION);
+ // CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.+]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> [[NEG]], i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.x86.avx512.vfmadd.f64(double [[A]], double [[B]], double [[C]], i32 8)
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double 0.000000e+00
+ // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[SEL]], i64 0
+ return _mm_maskz_fnmadd_round_sd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128d test_mm_mask3_fnmadd_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U){
// CHECK-LABEL: @test_mm_mask3_fnmadd_sd
- // CHECK: @llvm.x86.avx512.mask3.vfmadd.sd
+ // CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> [[NEG]], i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[ORIGC:%.+]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.fma.f64(double [[A]], double [[B]], double [[C]])
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double [[C]]
+ // CHECK-NEXT: insertelement <2 x double> [[ORIGC]], double [[SEL]], i64 0
return _mm_mask3_fnmadd_sd(__W, __X, __Y, __U);
}
__m128d test_mm_mask3_fnmadd_round_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U){
// CHECK-LABEL: @test_mm_mask3_fnmadd_round_sd
- // CHECK: @llvm.x86.avx512.mask3.vfmadd.sd
- return _mm_mask3_fnmadd_round_sd(__W, __X, __Y, __U, _MM_FROUND_CUR_DIRECTION);
+ // CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> [[NEG]], i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[ORIGC:%.+]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.x86.avx512.vfmadd.f64(double [[A]], double [[B]], double [[C]], i32 8)
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double [[C]]
+ // CHECK-NEXT: insertelement <2 x double> [[ORIGC]], double [[SEL]], i64 0
+ return _mm_mask3_fnmadd_round_sd(__W, __X, __Y, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128d test_mm_mask_fnmsub_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){
// CHECK-LABEL: @test_mm_mask_fnmsub_sd
- // CHECK: @llvm.x86.avx512.mask.vfmadd.sd
+ // CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: [[NEG2:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> [[NEG]], i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[NEG2]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.fma.f64(double [[A]], double [[B]], double [[C]])
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double [[A]]
+ // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[SEL]], i64 0
return _mm_mask_fnmsub_sd(__W, __U, __A, __B);
}
+__m128d test_mm_fnmsub_round_sd(__m128d __A, __m128d __B, __m128d __C){
+ // CHECK-LABEL: @test_mm_fnmsub_round_sd
+ // CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: [[NEG2:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> [[NEG]], i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[NEG2]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.x86.avx512.vfmadd.f64(double [[A]], double [[B]], double [[C]], i32 8)
+ // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[FMA]], i64 0
+ return _mm_fnmsub_round_sd(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
+}
+
__m128d test_mm_mask_fnmsub_round_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){
// CHECK-LABEL: @test_mm_mask_fnmsub_round_sd
- // CHECK: @llvm.x86.avx512.mask.vfmadd.sd
- return _mm_mask_fnmsub_round_sd(__W, __U, __A, __B, _MM_FROUND_CUR_DIRECTION);
+ // CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: [[NEG2:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> [[NEG]], i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[NEG2]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.x86.avx512.vfmadd.f64(double [[A]], double [[B]], double [[C]], i32 8)
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double [[A]]
+ // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[SEL]], i64 0
+ return _mm_mask_fnmsub_round_sd(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128d test_mm_maskz_fnmsub_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C){
// CHECK-LABEL: @test_mm_maskz_fnmsub_sd
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.sd
+ // CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: [[NEG2:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> [[NEG]], i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[NEG2]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.fma.f64(double [[A]], double [[B]], double [[C]])
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double 0.000000e+00
+ // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[SEL]], i64 0
return _mm_maskz_fnmsub_sd(__U, __A, __B, __C);
}
__m128d test_mm_maskz_fnmsub_round_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C){
// CHECK-LABEL: @test_mm_maskz_fnmsub_round_sd
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.sd
- return _mm_maskz_fnmsub_round_sd(__U, __A, __B, __C, _MM_FROUND_CUR_DIRECTION);
+ // CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: [[NEG2:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.]], i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> [[NEG]], i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[NEG2]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.x86.avx512.vfmadd.f64(double [[A]], double [[B]], double [[C]], i32 8)
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double 0.000000e+00
+ // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[SEL]], i64 0
+ return _mm_maskz_fnmsub_round_sd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128d test_mm_mask3_fnmsub_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U){
// CHECK-LABEL: @test_mm_mask3_fnmsub_sd
- // CHECK: @llvm.x86.avx512.mask3.vfnmsub.sd
+ // CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: [[NEG2:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, [[ORIGC:%.+]]
+ // CHECK: [[A:%.+]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> [[NEG]], i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[NEG2]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.fma.f64(double [[A]], double [[B]], double [[C]])
+ // CHECK-NEXT: [[C2:%.+]] = extractelement <2 x double> [[ORIGC]], i64 0
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double [[C2]]
+ // CHECK-NEXT: insertelement <2 x double> [[ORIGC]], double [[SEL]], i64 0
return _mm_mask3_fnmsub_sd(__W, __X, __Y, __U);
}
__m128d test_mm_mask3_fnmsub_round_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U){
// CHECK-LABEL: @test_mm_mask3_fnmsub_round_sd
- // CHECK: @llvm.x86.avx512.mask3.vfnmsub.sd
- return _mm_mask3_fnmsub_round_sd(__W, __X, __Y, __U, _MM_FROUND_CUR_DIRECTION);
+ // CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: [[NEG2:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, [[ORIGC:%.+]]
+ // CHECK: [[A:%.+]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> [[NEG]], i64 0
+ // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[NEG2]], i64 0
+ // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.x86.avx512.vfmadd.f64(double [[A]], double [[B]], double [[C]], i32 8)
+ // CHECK-NEXT: [[C2:%.+]] = extractelement <2 x double> [[ORIGC]], i64 0
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double [[C2]]
+ // CHECK-NEXT: insertelement <2 x double> [[ORIGC]], double [[SEL]], i64 0
+ return _mm_mask3_fnmsub_round_sd(__W, __X, __Y, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_permutex_pd(__m512d __X) {
// CHECK-LABEL: @test_mm512_permutex_pd
- // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> zeroinitializer, <8 x i32> <i32 0, i32 0, i32 0, i32 0, i32 4, i32 4, i32 4, i32 4>
+ // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <8 x i32> <i32 0, i32 0, i32 0, i32 0, i32 4, i32 4, i32 4, i32 4>
return _mm512_permutex_pd(__X, 0);
}
__m512d test_mm512_mask_permutex_pd(__m512d __W, __mmask8 __U, __m512d __X) {
// CHECK-LABEL: @test_mm512_mask_permutex_pd
- // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> zeroinitializer, <8 x i32> <i32 0, i32 0, i32 0, i32 0, i32 4, i32 4, i32 4, i32 4>
+ // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <8 x i32> <i32 0, i32 0, i32 0, i32 0, i32 4, i32 4, i32 4, i32 4>
// CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_permutex_pd(__W, __U, __X, 0);
}
__m512d test_mm512_maskz_permutex_pd(__mmask8 __U, __m512d __X) {
// CHECK-LABEL: @test_mm512_maskz_permutex_pd
- // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> zeroinitializer, <8 x i32> <i32 0, i32 0, i32 0, i32 0, i32 4, i32 4, i32 4, i32 4>
+ // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <8 x i32> <i32 0, i32 0, i32 0, i32 0, i32 4, i32 4, i32 4, i32 4>
// CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_maskz_permutex_pd(__U, __X, 0);
}
__m512i test_mm512_permutex_epi64(__m512i __X) {
// CHECK-LABEL: @test_mm512_permutex_epi64
- // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> zeroinitializer, <8 x i32> <i32 0, i32 0, i32 0, i32 0, i32 4, i32 4, i32 4, i32 4>
+ // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <8 x i32> <i32 0, i32 0, i32 0, i32 0, i32 4, i32 4, i32 4, i32 4>
return _mm512_permutex_epi64(__X, 0);
}
__m512i test_mm512_mask_permutex_epi64(__m512i __W, __mmask8 __M, __m512i __X) {
// CHECK-LABEL: @test_mm512_mask_permutex_epi64
- // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> zeroinitializer, <8 x i32> <i32 0, i32 0, i32 0, i32 0, i32 4, i32 4, i32 4, i32 4>
+ // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <8 x i32> <i32 0, i32 0, i32 0, i32 0, i32 4, i32 4, i32 4, i32 4>
// CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_permutex_epi64(__W, __M, __X, 0);
}
__m512i test_mm512_maskz_permutex_epi64(__mmask8 __M, __m512i __X) {
// CHECK-LABEL: @test_mm512_maskz_permutex_epi64
- // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> zeroinitializer, <8 x i32> <i32 0, i32 0, i32 0, i32 0, i32 4, i32 4, i32 4, i32 4>
+ // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <8 x i32> <i32 0, i32 0, i32 0, i32 0, i32 4, i32 4, i32 4, i32 4>
// CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_permutex_epi64(__M, __X, 0);
}
__m512d test_mm512_permutexvar_pd(__m512i __X, __m512d __Y) {
// CHECK-LABEL: @test_mm512_permutexvar_pd
- // CHECK: @llvm.x86.avx512.mask.permvar.df.512
+ // CHECK: @llvm.x86.avx512.permvar.df.512
return _mm512_permutexvar_pd(__X, __Y);
}
__m512d test_mm512_mask_permutexvar_pd(__m512d __W, __mmask8 __U, __m512i __X, __m512d __Y) {
// CHECK-LABEL: @test_mm512_mask_permutexvar_pd
- // CHECK: @llvm.x86.avx512.mask.permvar.df.512
+ // CHECK: @llvm.x86.avx512.permvar.df.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_permutexvar_pd(__W, __U, __X, __Y);
}
__m512d test_mm512_maskz_permutexvar_pd(__mmask8 __U, __m512i __X, __m512d __Y) {
// CHECK-LABEL: @test_mm512_maskz_permutexvar_pd
- // CHECK: @llvm.x86.avx512.mask.permvar.df.512
+ // CHECK: @llvm.x86.avx512.permvar.df.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_maskz_permutexvar_pd(__U, __X, __Y);
}
__m512i test_mm512_maskz_permutexvar_epi64(__mmask8 __M, __m512i __X, __m512i __Y) {
// CHECK-LABEL: @test_mm512_maskz_permutexvar_epi64
- // CHECK: @llvm.x86.avx512.mask.permvar.di.512
+ // CHECK: @llvm.x86.avx512.permvar.di.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_permutexvar_epi64(__M, __X, __Y);
}
__m512i test_mm512_permutexvar_epi64(__m512i __X, __m512i __Y) {
// CHECK-LABEL: @test_mm512_permutexvar_epi64
- // CHECK: @llvm.x86.avx512.mask.permvar.di.512
+ // CHECK: @llvm.x86.avx512.permvar.di.512
return _mm512_permutexvar_epi64(__X, __Y);
}
__m512i test_mm512_mask_permutexvar_epi64(__m512i __W, __mmask8 __M, __m512i __X, __m512i __Y) {
// CHECK-LABEL: @test_mm512_mask_permutexvar_epi64
- // CHECK: @llvm.x86.avx512.mask.permvar.di.512
+ // CHECK: @llvm.x86.avx512.permvar.di.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_permutexvar_epi64(__W, __M, __X, __Y);
}
__m512 test_mm512_permutexvar_ps(__m512i __X, __m512 __Y) {
// CHECK-LABEL: @test_mm512_permutexvar_ps
- // CHECK: @llvm.x86.avx512.mask.permvar.sf.512
+ // CHECK: @llvm.x86.avx512.permvar.sf.512
return _mm512_permutexvar_ps(__X, __Y);
}
__m512 test_mm512_mask_permutexvar_ps(__m512 __W, __mmask16 __U, __m512i __X, __m512 __Y) {
// CHECK-LABEL: @test_mm512_mask_permutexvar_ps
- // CHECK: @llvm.x86.avx512.mask.permvar.sf.512
+ // CHECK: @llvm.x86.avx512.permvar.sf.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_permutexvar_ps(__W, __U, __X, __Y);
}
__m512 test_mm512_maskz_permutexvar_ps(__mmask16 __U, __m512i __X, __m512 __Y) {
// CHECK-LABEL: @test_mm512_maskz_permutexvar_ps
- // CHECK: @llvm.x86.avx512.mask.permvar.sf.512
+ // CHECK: @llvm.x86.avx512.permvar.sf.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_maskz_permutexvar_ps(__U, __X, __Y);
}
__m512i test_mm512_maskz_permutexvar_epi32(__mmask16 __M, __m512i __X, __m512i __Y) {
// CHECK-LABEL: @test_mm512_maskz_permutexvar_epi32
- // CHECK: @llvm.x86.avx512.mask.permvar.si.512
+ // CHECK: @llvm.x86.avx512.permvar.si.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_permutexvar_epi32(__M, __X, __Y);
}
__m512i test_mm512_permutexvar_epi32(__m512i __X, __m512i __Y) {
// CHECK-LABEL: @test_mm512_permutexvar_epi32
- // CHECK: @llvm.x86.avx512.mask.permvar.si.512
+ // CHECK: @llvm.x86.avx512.permvar.si.512
return _mm512_permutexvar_epi32(__X, __Y);
}
__m512i test_mm512_mask_permutexvar_epi32(__m512i __W, __mmask16 __M, __m512i __X, __m512i __Y) {
// CHECK-LABEL: @test_mm512_mask_permutexvar_epi32
- // CHECK: @llvm.x86.avx512.mask.permvar.si.512
+ // CHECK: @llvm.x86.avx512.permvar.si.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_permutexvar_epi32(__W, __M, __X, __Y);
}
@@ -6247,26 +8125,38 @@ __mmask16 test_mm512_kor(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __m
__E, __F);
}
-int test_mm512_kortestc(__mmask16 __A, __mmask16 __B) {
+int test_mm512_kortestc(__m512i __A, __m512i __B, __m512i __C, __m512i __D) {
// CHECK-LABEL: @test_mm512_kortestc
- // CHECK: @llvm.x86.avx512.kortestc.w
- return _mm512_kortestc(__A, __B);
+ // CHECK: [[LHS:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[OR:%.*]] = or <16 x i1> [[LHS]], [[RHS]]
+ // CHECK: [[CAST:%.*]] = bitcast <16 x i1> [[OR]] to i16
+ // CHECK: [[CMP:%.*]] = icmp eq i16 [[CAST]], -1
+ // CHECK: zext i1 [[CMP]] to i32
+ return _mm512_kortestc(_mm512_cmpneq_epu32_mask(__A, __B),
+ _mm512_cmpneq_epu32_mask(__C, __D));
}
-int test_mm512_kortestz(__mmask16 __A, __mmask16 __B) {
+int test_mm512_kortestz(__m512i __A, __m512i __B, __m512i __C, __m512i __D) {
// CHECK-LABEL: @test_mm512_kortestz
- // CHECK: @llvm.x86.avx512.kortestz.w
- return _mm512_kortestz(__A, __B);
+ // CHECK: [[LHS:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[OR:%.*]] = or <16 x i1> [[LHS]], [[RHS]]
+ // CHECK: [[CAST:%.*]] = bitcast <16 x i1> [[OR]] to i16
+ // CHECK: [[CMP:%.*]] = icmp eq i16 [[CAST]], 0
+ // CHECK: zext i1 [[CMP]] to i32
+ return _mm512_kortestz(_mm512_cmpneq_epu32_mask(__A, __B),
+ _mm512_cmpneq_epu32_mask(__C, __D));
}
__mmask16 test_mm512_kunpackb(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __m512i __E, __m512i __F) {
// CHECK-LABEL: @test_mm512_kunpackb
- // CHECK: bitcast <16 x i1> %{{.*}} to i16
- // CHECK: bitcast <16 x i1> %{{.*}} to i16
- // CHECK: and i32 %{{.*}}, 255
- // CHECK: shl i32 %{{.*}}, 8
- // CHECK: or i32 %{{.*}}, %{{.*}}
- // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[LHS:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[LHS2:%.*]] = shufflevector <16 x i1> [[LHS]], <16 x i1> [[LHS]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ // CHECK: [[RHS2:%.*]] = shufflevector <16 x i1> [[RHS]], <16 x i1> [[RHS]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ // CHECK: [[CONCAT:%.*]] = shufflevector <8 x i1> [[RHS2]], <8 x i1> [[LHS2]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+ // CHECK: bitcast <16 x i1> [[CONCAT]] to i16
return _mm512_mask_cmpneq_epu32_mask(_mm512_kunpackb(_mm512_cmpneq_epu32_mask(__A, __B),
_mm512_cmpneq_epu32_mask(__C, __D)),
__E, __F);
@@ -6463,20 +8353,20 @@ __m512 test_mm512_maskz_moveldup_ps(__mmask16 __U, __m512 __A) {
__m512i test_mm512_shuffle_epi32(__m512i __A) {
// CHECK-LABEL: @test_mm512_shuffle_epi32
- // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> <i32 1, i32 0, i32 0, i32 0, i32 5, i32 4, i32 4, i32 4, i32 9, i32 8, i32 8, i32 8, i32 13, i32 12, i32 12, i32 12>
+ // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> undef, <16 x i32> <i32 1, i32 0, i32 0, i32 0, i32 5, i32 4, i32 4, i32 4, i32 9, i32 8, i32 8, i32 8, i32 13, i32 12, i32 12, i32 12>
return _mm512_shuffle_epi32(__A, 1);
}
__m512i test_mm512_mask_shuffle_epi32(__m512i __W, __mmask16 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_shuffle_epi32
- // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> <i32 1, i32 0, i32 0, i32 0, i32 5, i32 4, i32 4, i32 4, i32 9, i32 8, i32 8, i32 8, i32 13, i32 12, i32 12, i32 12>
+ // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> undef, <16 x i32> <i32 1, i32 0, i32 0, i32 0, i32 5, i32 4, i32 4, i32 4, i32 9, i32 8, i32 8, i32 8, i32 13, i32 12, i32 12, i32 12>
// CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_shuffle_epi32(__W, __U, __A, 1);
}
__m512i test_mm512_maskz_shuffle_epi32(__mmask16 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_shuffle_epi32
- // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> <i32 1, i32 0, i32 0, i32 0, i32 5, i32 4, i32 4, i32 4, i32 9, i32 8, i32 8, i32 8, i32 13, i32 12, i32 12, i32 12>
+ // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> undef, <16 x i32> <i32 1, i32 0, i32 0, i32 0, i32 5, i32 4, i32 4, i32 4, i32 9, i32 8, i32 8, i32 8, i32 13, i32 12, i32 12, i32 12>
// CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_shuffle_epi32(__U, __A, 1);
}
@@ -6506,40 +8396,52 @@ __m512i test_mm512_maskz_expand_epi64(__mmask8 __U, __m512i __A) {
}
__m512i test_mm512_mask_expandloadu_epi64(__m512i __W, __mmask8 __U, void const *__P) {
// CHECK-LABEL: @test_mm512_mask_expandloadu_epi64
- // CHECK: @llvm.x86.avx512.mask.expand.load.q.512
+ // CHECK: @llvm.masked.expandload.v8i64(i64* %{{.*}}, <8 x i1> %{{.*}}, <8 x i64> %{{.*}})
return _mm512_mask_expandloadu_epi64(__W, __U, __P);
}
__m512i test_mm512_maskz_expandloadu_epi64(__mmask8 __U, void const *__P) {
// CHECK-LABEL: @test_mm512_maskz_expandloadu_epi64
- // CHECK: @llvm.x86.avx512.mask.expand.load.q.512
+ // CHECK: @llvm.masked.expandload.v8i64(i64* %{{.*}}, <8 x i1> %{{.*}}, <8 x i64> %{{.*}})
return _mm512_maskz_expandloadu_epi64(__U, __P);
}
__m512d test_mm512_mask_expandloadu_pd(__m512d __W, __mmask8 __U, void const *__P) {
// CHECK-LABEL: @test_mm512_mask_expandloadu_pd
- // CHECK: @llvm.x86.avx512.mask.expand.load.pd.512
+ // CHECK: @llvm.masked.expandload.v8f64(double* %{{.*}}, <8 x i1> %{{.*}}, <8 x double> %{{.*}})
return _mm512_mask_expandloadu_pd(__W, __U, __P);
}
__m512d test_mm512_maskz_expandloadu_pd(__mmask8 __U, void const *__P) {
// CHECK-LABEL: @test_mm512_maskz_expandloadu_pd
- // CHECK: @llvm.x86.avx512.mask.expand.load.pd.512
+ // CHECK: @llvm.masked.expandload.v8f64(double* %{{.*}}, <8 x i1> %{{.*}}, <8 x double> %{{.*}})
return _mm512_maskz_expandloadu_pd(__U, __P);
}
__m512i test_mm512_mask_expandloadu_epi32(__m512i __W, __mmask16 __U, void const *__P) {
// CHECK-LABEL: @test_mm512_mask_expandloadu_epi32
- // CHECK: @llvm.x86.avx512.mask.expand.load.d.512
+ // CHECK: @llvm.masked.expandload.v16i32(i32* %{{.*}}, <16 x i1> %{{.*}}, <16 x i32> %{{.*}})
return _mm512_mask_expandloadu_epi32(__W, __U, __P);
}
__m512i test_mm512_maskz_expandloadu_epi32(__mmask16 __U, void const *__P) {
// CHECK-LABEL: @test_mm512_maskz_expandloadu_epi32
- // CHECK: @llvm.x86.avx512.mask.expand.load.d.512
+ // CHECK: @llvm.masked.expandload.v16i32(i32* %{{.*}}, <16 x i1> %{{.*}}, <16 x i32> %{{.*}})
return _mm512_maskz_expandloadu_epi32(__U, __P);
}
+__m512 test_mm512_mask_expandloadu_ps(__m512 __W, __mmask16 __U, void const *__P) {
+ // CHECK-LABEL: @test_mm512_mask_expandloadu_ps
+ // CHECK: @llvm.masked.expandload.v16f32(float* %{{.*}}, <16 x i1> %{{.*}}, <16 x float> %{{.*}})
+ return _mm512_mask_expandloadu_ps(__W, __U, __P);
+}
+
+__m512 test_mm512_maskz_expandloadu_ps(__mmask16 __U, void const *__P) {
+ // CHECK-LABEL: @test_mm512_maskz_expandloadu_ps
+ // CHECK: @llvm.masked.expandload.v16f32(float* %{{.*}}, <16 x i1> %{{.*}}, <16 x float> %{{.*}})
+ return _mm512_maskz_expandloadu_ps(__U, __P);
+}
+
__m512 test_mm512_mask_expand_ps(__m512 __W, __mmask16 __U, __m512 __A) {
// CHECK-LABEL: @test_mm512_mask_expand_ps
// CHECK: @llvm.x86.avx512.mask.expand.ps.512
@@ -6583,33 +8485,36 @@ __m512d test_mm512_maskz_cvt_roundps_pd(__mmask8 __U, __m256 __A) {
__m512d test_mm512_cvtps_pd(__m256 __A) {
// CHECK-LABEL: @test_mm512_cvtps_pd
- // CHECK: @llvm.x86.avx512.mask.cvtps2pd.512
+ // CHECK: fpext <8 x float> %{{.*}} to <8 x double>
return _mm512_cvtps_pd(__A);
}
__m512d test_mm512_cvtpslo_pd(__m512 __A) {
// CHECK-LABEL: @test_mm512_cvtpslo_pd
// CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
- // CHECK: @llvm.x86.avx512.mask.cvtps2pd.512
+ // CHECK: fpext <8 x float> %{{.*}} to <8 x double>
return _mm512_cvtpslo_pd(__A);
}
__m512d test_mm512_mask_cvtps_pd(__m512d __W, __mmask8 __U, __m256 __A) {
// CHECK-LABEL: @test_mm512_mask_cvtps_pd
- // CHECK: @llvm.x86.avx512.mask.cvtps2pd.512
+ // CHECK: fpext <8 x float> %{{.*}} to <8 x double>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_cvtps_pd(__W, __U, __A);
}
__m512d test_mm512_mask_cvtpslo_pd(__m512d __W, __mmask8 __U, __m512 __A) {
// CHECK-LABEL: @test_mm512_mask_cvtpslo_pd
// CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
- // CHECK: @llvm.x86.avx512.mask.cvtps2pd.512
+ // CHECK: fpext <8 x float> %{{.*}} to <8 x double>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_cvtpslo_pd(__W, __U, __A);
}
__m512d test_mm512_maskz_cvtps_pd(__mmask8 __U, __m256 __A) {
// CHECK-LABEL: @test_mm512_maskz_cvtps_pd
- // CHECK: @llvm.x86.avx512.mask.cvtps2pd.512
+ // CHECK: fpext <8 x float> %{{.*}} to <8 x double>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_maskz_cvtps_pd(__U, __A);
}
__m512d test_mm512_mask_mov_pd(__m512d __W, __mmask8 __U, __m512d __A) {
@@ -6638,25 +8543,25 @@ __m512 test_mm512_maskz_mov_ps(__mmask16 __U, __m512 __A) {
void test_mm512_mask_compressstoreu_pd(void *__P, __mmask8 __U, __m512d __A) {
// CHECK-LABEL: @test_mm512_mask_compressstoreu_pd
- // CHECK: @llvm.x86.avx512.mask.compress.store.pd.512
+ // CHECK: @llvm.masked.compressstore.v8f64(<8 x double> %{{.*}}, double* %{{.*}}, <8 x i1> %{{.*}})
return _mm512_mask_compressstoreu_pd(__P, __U, __A);
}
void test_mm512_mask_compressstoreu_epi64(void *__P, __mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_compressstoreu_epi64
- // CHECK: @llvm.x86.avx512.mask.compress.store.q.512
+ // CHECK: @llvm.masked.compressstore.v8i64(<8 x i64> %{{.*}}, i64* %{{.*}}, <8 x i1> %{{.*}})
return _mm512_mask_compressstoreu_epi64(__P, __U, __A);
}
void test_mm512_mask_compressstoreu_ps(void *__P, __mmask16 __U, __m512 __A) {
// CHECK-LABEL: @test_mm512_mask_compressstoreu_ps
- // CHECK: @llvm.x86.avx512.mask.compress.store.ps.512
+ // CHECK: @llvm.masked.compressstore.v16f32(<16 x float> %{{.*}}, float* %{{.*}}, <16 x i1> %{{.*}})
return _mm512_mask_compressstoreu_ps(__P, __U, __A);
}
void test_mm512_mask_compressstoreu_epi32(void *__P, __mmask16 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_compressstoreu_epi32
- // CHECK: @llvm.x86.avx512.mask.compress.store.d.512
+ // CHECK: @llvm.masked.compressstore.v16i32(<16 x i32> %{{.*}}, i32* %{{.*}}, <16 x i1> %{{.*}})
return _mm512_mask_compressstoreu_epi32(__P, __U, __A);
}
@@ -6729,7 +8634,7 @@ __m512d test_mm512_castpd128_pd512(__m128d __A) {
return _mm512_castpd128_pd512(__A);
}
-__m512d test_mm512_set1_epi8(char d)
+__m512i test_mm512_set1_epi8(char d)
{
// CHECK-LABEL: @test_mm512_set1_epi8
// CHECK: insertelement <64 x i8> {{.*}}, i32 0
@@ -6744,7 +8649,7 @@ __m512d test_mm512_set1_epi8(char d)
return _mm512_set1_epi8(d);
}
-__m512d test_mm512_set1_epi16(short d)
+__m512i test_mm512_set1_epi16(short d)
{
// CHECK-LABEL: @test_mm512_set1_epi16
// CHECK: insertelement <32 x i16> {{.*}}, i32 0
@@ -6801,14 +8706,14 @@ __m512i test_mm512_setr4_epi32(int e0, int e1, int e2, int e3)
return _mm512_setr4_epi64(e0, e1, e2, e3);
}
-__m512i test_mm512_setr4_pd(double e0, double e1, double e2, double e3)
+__m512d test_mm512_setr4_pd(double e0, double e1, double e2, double e3)
{
// CHECK-LABEL: @test_mm512_setr4_pd
// CHECK: insertelement <8 x double> {{.*}}, i32 7
return _mm512_setr4_pd(e0,e1,e2,e3);
}
- __m512i test_mm512_setr4_ps(float e0, float e1, float e2, float e3)
+ __m512 test_mm512_setr4_ps(float e0, float e1, float e2, float e3)
{
// CHECK-LABEL: @test_mm512_setr4_ps
// CHECK: insertelement <16 x float> {{.*}}, i32 15
@@ -6960,7 +8865,8 @@ __m128d test_mm_maskz_cvt_roundss_sd( __mmask8 __U, __m128d __A, __m128 __B) {
__m128d test_mm_cvtu32_sd(__m128d __A, unsigned __B) {
// CHECK-LABEL: @test_mm_cvtu32_sd
- // CHECK: @llvm.x86.avx512.cvtusi2sd
+ // CHECK: uitofp i32 %{{.*}} to double
+ // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 0
return _mm_cvtu32_sd(__A, __B);
}
@@ -6973,7 +8879,8 @@ __m128d test_mm_cvt_roundu64_sd(__m128d __A, unsigned long long __B) {
__m128d test_mm_cvtu64_sd(__m128d __A, unsigned long long __B) {
// CHECK-LABEL: @test_mm_cvtu64_sd
- // CHECK: @llvm.x86.avx512.cvtusi642sd
+ // CHECK: uitofp i64 %{{.*}} to double
+ // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 0
return _mm_cvtu64_sd(__A, __B);
}
#endif
@@ -6986,7 +8893,8 @@ __m128 test_mm_cvt_roundu32_ss(__m128 __A, unsigned __B) {
__m128 test_mm_cvtu32_ss(__m128 __A, unsigned __B) {
// CHECK-LABEL: @test_mm_cvtu32_ss
- // CHECK: @llvm.x86.avx512.cvtusi2ss
+ // CHECK: uitofp i32 %{{.*}} to float
+ // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i32 0
return _mm_cvtu32_ss(__A, __B);
}
@@ -6999,7 +8907,8 @@ __m128 test_mm_cvt_roundu64_ss(__m128 __A, unsigned long long __B) {
__m128 test_mm_cvtu64_ss(__m128 __A, unsigned long long __B) {
// CHECK-LABEL: @test_mm_cvtu64_ss
- // CHECK: @llvm.x86.avx512.cvtusi642ss
+ // CHECK: uitofp i64 %{{.*}} to float
+ // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i32 0
return _mm_cvtu64_ss(__A, __B);
}
#endif
@@ -7021,21 +8930,23 @@ __m512i test_mm512_maskz_cvttps_epu32 (__mmask16 __U, __m512 __A)
__m512 test_mm512_cvtepu32_ps (__m512i __A)
{
// CHECK-LABEL: @test_mm512_cvtepu32_ps
- // CHECK: @llvm.x86.avx512.mask.cvtudq2ps.512
+ // CHECK: uitofp <16 x i32> %{{.*}} to <16 x float>
return _mm512_cvtepu32_ps (__A);
}
__m512 test_mm512_mask_cvtepu32_ps (__m512 __W, __mmask16 __U, __m512i __A)
{
// CHECK-LABEL: @test_mm512_mask_cvtepu32_ps
- // CHECK: @llvm.x86.avx512.mask.cvtudq2ps.512
+ // CHECK: uitofp <16 x i32> %{{.*}} to <16 x float>
+ // CHECK: select <16 x i1> {{.*}}, <16 x float> {{.*}}, <16 x float> {{.*}}
return _mm512_mask_cvtepu32_ps (__W,__U,__A);
}
__m512 test_mm512_maskz_cvtepu32_ps (__mmask16 __U, __m512i __A)
{
// CHECK-LABEL: @test_mm512_maskz_cvtepu32_ps
- // CHECK: @llvm.x86.avx512.mask.cvtudq2ps.512
+ // CHECK: uitofp <16 x i32> %{{.*}} to <16 x float>
+ // CHECK: select <16 x i1> {{.*}}, <16 x float> {{.*}}, <16 x float> {{.*}}
return _mm512_maskz_cvtepu32_ps (__U,__A);
}
@@ -7082,21 +8993,23 @@ __m512d test_mm512_mask_cvtepi32lo_pd (__m512d __W, __mmask8 __U, __m512i __A)
__m512 test_mm512_cvtepi32_ps (__m512i __A)
{
// CHECK-LABEL: @test_mm512_cvtepi32_ps
- // CHECK: @llvm.x86.avx512.mask.cvtdq2ps.512
+ // CHECK: sitofp <16 x i32> %{{.*}} to <16 x float>
return _mm512_cvtepi32_ps (__A);
}
__m512 test_mm512_mask_cvtepi32_ps (__m512 __W, __mmask16 __U, __m512i __A)
{
// CHECK-LABEL: @test_mm512_mask_cvtepi32_ps
- // CHECK: @llvm.x86.avx512.mask.cvtdq2ps.512
+ // CHECK: sitofp <16 x i32> %{{.*}} to <16 x float>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_cvtepi32_ps (__W,__U,__A);
}
__m512 test_mm512_maskz_cvtepi32_ps (__mmask16 __U, __m512i __A)
{
// CHECK-LABEL: @test_mm512_maskz_cvtepi32_ps
- // CHECK: @llvm.x86.avx512.mask.cvtdq2ps.512
+ // CHECK: sitofp <16 x i32> %{{.*}} to <16 x float>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_maskz_cvtepi32_ps (__U,__A);
}
@@ -7332,140 +9245,155 @@ float test_mm512_cvtss_f32(__m512 A) {
__m512d test_mm512_mask_max_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B)
{
// CHECK-LABEL: @test_mm512_mask_max_pd
- // CHECK: @llvm.x86.avx512.mask.max.pd.512
+ // CHECK: @llvm.x86.avx512.max.pd.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_max_pd (__W,__U,__A,__B);
}
__m512d test_mm512_maskz_max_pd (__mmask8 __U, __m512d __A, __m512d __B)
{
// CHECK-LABEL: @test_mm512_maskz_max_pd
- // CHECK: @llvm.x86.avx512.mask.max.pd.512
+ // CHECK: @llvm.x86.avx512.max.pd.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_maskz_max_pd (__U,__A,__B);
}
__m512 test_mm512_mask_max_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B)
{
// CHECK-LABEL: @test_mm512_mask_max_ps
- // CHECK: @llvm.x86.avx512.mask.max.ps.512
+ // CHECK: @llvm.x86.avx512.max.ps.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_max_ps (__W,__U,__A,__B);
}
__m512d test_mm512_mask_max_round_pd(__m512d __W,__mmask8 __U,__m512d __A,__m512d __B)
{
// CHECK-LABEL: @test_mm512_mask_max_round_pd
- // CHECK: @llvm.x86.avx512.mask.max.pd.512
+ // CHECK: @llvm.x86.avx512.max.pd.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_max_round_pd(__W,__U,__A,__B,_MM_FROUND_CUR_DIRECTION);
}
__m512d test_mm512_maskz_max_round_pd(__mmask8 __U,__m512d __A,__m512d __B)
{
// CHECK-LABEL: @test_mm512_maskz_max_round_pd
- // CHECK: @llvm.x86.avx512.mask.max.pd.512
+ // CHECK: @llvm.x86.avx512.max.pd.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_maskz_max_round_pd(__U,__A,__B,_MM_FROUND_CUR_DIRECTION);
}
__m512d test_mm512_max_round_pd(__m512d __A,__m512d __B)
{
// CHECK-LABEL: @test_mm512_max_round_pd
- // CHECK: @llvm.x86.avx512.mask.max.pd.512
+ // CHECK: @llvm.x86.avx512.max.pd.512
return _mm512_max_round_pd(__A,__B,_MM_FROUND_CUR_DIRECTION);
}
__m512 test_mm512_maskz_max_ps (__mmask16 __U, __m512 __A, __m512 __B)
{
// CHECK-LABEL: @test_mm512_maskz_max_ps
- // CHECK: @llvm.x86.avx512.mask.max.ps.512
+ // CHECK: @llvm.x86.avx512.max.ps.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_maskz_max_ps (__U,__A,__B);
}
__m512 test_mm512_mask_max_round_ps(__m512 __W,__mmask16 __U,__m512 __A,__m512 __B)
{
// CHECK-LABEL: @test_mm512_mask_max_round_ps
- // CHECK: @llvm.x86.avx512.mask.max.ps.512
+ // CHECK: @llvm.x86.avx512.max.ps.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_max_round_ps(__W,__U,__A,__B,_MM_FROUND_CUR_DIRECTION);
}
__m512 test_mm512_maskz_max_round_ps(__mmask16 __U,__m512 __A,__m512 __B)
{
// CHECK-LABEL: @test_mm512_maskz_max_round_ps
- // CHECK: @llvm.x86.avx512.mask.max.ps.512
+ // CHECK: @llvm.x86.avx512.max.ps.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_maskz_max_round_ps(__U,__A,__B,_MM_FROUND_CUR_DIRECTION);
}
__m512 test_mm512_max_round_ps(__m512 __A,__m512 __B)
{
// CHECK-LABEL: @test_mm512_max_round_ps
- // CHECK: @llvm.x86.avx512.mask.max.ps.512
+ // CHECK: @llvm.x86.avx512.max.ps.512
return _mm512_max_round_ps(__A,__B,_MM_FROUND_CUR_DIRECTION);
}
__m512d test_mm512_mask_min_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B)
{
// CHECK-LABEL: @test_mm512_mask_min_pd
- // CHECK: @llvm.x86.avx512.mask.min.pd.512
+ // CHECK: @llvm.x86.avx512.min.pd.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_min_pd (__W,__U,__A,__B);
}
__m512d test_mm512_maskz_min_pd (__mmask8 __U, __m512d __A, __m512d __B)
{
// CHECK-LABEL: @test_mm512_maskz_min_pd
- // CHECK: @llvm.x86.avx512.mask.min.pd.512
+ // CHECK: @llvm.x86.avx512.min.pd.512
return _mm512_maskz_min_pd (__U,__A,__B);
}
__m512d test_mm512_mask_min_round_pd(__m512d __W,__mmask8 __U,__m512d __A,__m512d __B)
{
// CHECK-LABEL: @test_mm512_mask_min_round_pd
- // CHECK: @llvm.x86.avx512.mask.min.pd.512
+ // CHECK: @llvm.x86.avx512.min.pd.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_min_round_pd(__W,__U,__A,__B,_MM_FROUND_CUR_DIRECTION);
}
__m512d test_mm512_maskz_min_round_pd(__mmask8 __U,__m512d __A,__m512d __B)
{
// CHECK-LABEL: @test_mm512_maskz_min_round_pd
- // CHECK: @llvm.x86.avx512.mask.min.pd.512
+ // CHECK: @llvm.x86.avx512.min.pd.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_maskz_min_round_pd(__U,__A,__B,_MM_FROUND_CUR_DIRECTION);
}
__m512d test_mm512_min_round_pd( __m512d __A,__m512d __B)
{
// CHECK-LABEL: @test_mm512_min_round_pd
- // CHECK: @llvm.x86.avx512.mask.min.pd.512
+ // CHECK: @llvm.x86.avx512.min.pd.512
return _mm512_min_round_pd(__A,__B,_MM_FROUND_CUR_DIRECTION);
}
__m512 test_mm512_mask_min_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B)
{
// CHECK-LABEL: @test_mm512_mask_min_ps
- // CHECK: @llvm.x86.avx512.mask.min.ps.512
+ // CHECK: @llvm.x86.avx512.min.ps.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_min_ps (__W,__U,__A,__B);
}
__m512 test_mm512_maskz_min_ps (__mmask16 __U, __m512 __A, __m512 __B)
{
// CHECK-LABEL: @test_mm512_maskz_min_ps
- // CHECK: @llvm.x86.avx512.mask.min.ps.512
+ // CHECK: @llvm.x86.avx512.min.ps.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_maskz_min_ps (__U,__A,__B);
}
__m512 test_mm512_mask_min_round_ps(__m512 __W,__mmask16 __U,__m512 __A,__m512 __B)
{
// CHECK-LABEL: @test_mm512_mask_min_round_ps
- // CHECK: @llvm.x86.avx512.mask.min.ps.512
+ // CHECK: @llvm.x86.avx512.min.ps.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_min_round_ps(__W,__U,__A,__B,_MM_FROUND_CUR_DIRECTION);
}
__m512 test_mm512_maskz_min_round_ps(__mmask16 __U,__m512 __A,__m512 __B)
{
// CHECK-LABEL: @test_mm512_maskz_min_round_ps
- // CHECK: @llvm.x86.avx512.mask.min.ps.512
+ // CHECK: @llvm.x86.avx512.min.ps.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_maskz_min_round_ps(__U,__A,__B,_MM_FROUND_CUR_DIRECTION);
}
__m512 test_mm512_min_round_ps(__m512 __A,__m512 __B)
{
// CHECK-LABEL: @test_mm512_min_round_ps
- // CHECK: @llvm.x86.avx512.mask.min.ps.512
+ // CHECK: @llvm.x86.avx512.min.ps.512
return _mm512_min_round_ps(__A,__B,_MM_FROUND_CUR_DIRECTION);
}
@@ -8017,7 +9945,6 @@ __m512i test_mm512_setr_epi32 (int __A, int __B, int __C, int __D,
__I, __J, __K, __L,__M, __N, __O, __P);
}
-#ifdef __x86_64__
__m512i test_mm512_mask_set1_epi64 (__m512i __O, __mmask8 __M, long long __A)
{
// CHECK-LABEL: @test_mm512_mask_set1_epi64
@@ -8047,7 +9974,6 @@ __m512i test_mm512_maskz_set1_epi64 (__mmask8 __M, long long __A)
// CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_set1_epi64 (__M, __A);
}
-#endif
__m512i test_mm512_set_epi64 (long long __A, long long __B, long long __C,
@@ -8373,80 +10299,98 @@ int test_mm512_mask2int(__mmask16 __a)
__m128 test_mm_mask_move_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B)
{
// CHECK-LABEL: @test_mm_mask_move_ss
- // CHECK: extractelement <4 x float> %{{.*}}, i32 0
- // CHECK: extractelement <4 x float> %{{.*}}, i32 0
- // CHECK: phi float [ %{{.*}}, %{{.*}} ], [ %{{.*}}, %{{.*}} ]
- // CHECK: insertelement <4 x float> %{{.*}}, float %cond.i, i32 0
+ // CHECK: [[EXT:%.*]] = extractelement <4 x float> %{{.*}}, i32 0
+ // CHECK: insertelement <4 x float> %{{.*}}, float [[EXT]], i32 0
+ // CHECK: [[A:%.*]] = extractelement <4 x float> [[VEC:%.*]], i64 0
+ // CHECK-NEXT: [[B:%.*]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.*]] = select i1 %{{.*}}, float [[A]], float [[B]]
+ // CHECK-NEXT: insertelement <4 x float> [[VEC]], float [[SEL]], i64 0
return _mm_mask_move_ss ( __W, __U, __A, __B);
}
__m128 test_mm_maskz_move_ss (__mmask8 __U, __m128 __A, __m128 __B)
{
// CHECK-LABEL: @test_mm_maskz_move_ss
- // CHECK: extractelement <4 x float> %{{.*}}, i32 0
- // CHECK: phi float [ %{{.*}}, %{{.*}} ], [ 0.000000e+00, %{{.*}} ]
- // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i32 0
+ // CHECK: [[EXT:%.*]] = extractelement <4 x float> %{{.*}}, i32 0
+ // CHECK: insertelement <4 x float> %{{.*}}, float [[EXT]], i32 0
+ // CHECK: [[A:%.*]] = extractelement <4 x float> [[VEC:%.*]], i64 0
+ // CHECK-NEXT: [[B:%.*]] = extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.*]] = select i1 %{{.*}}, float [[A]], float [[B]]
+ // CHECK-NEXT: insertelement <4 x float> [[VEC]], float [[SEL]], i64 0
return _mm_maskz_move_ss (__U, __A, __B);
}
__m128d test_mm_mask_move_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B)
{
// CHECK-LABEL: @test_mm_mask_move_sd
- // CHECK: extractelement <2 x double> %{{.*}}, i32 0
- // CHECK: extractelement <2 x double> %{{.*}}, i32 0
- // CHECK: phi double [ %{{.*}}, %{{.*}} ], [ %{{.*}}, %{{.*}} ]
- // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 0
+ // CHECK: [[EXT:%.*]] = extractelement <2 x double> %{{.*}}, i32 0
+ // CHECK: insertelement <2 x double> %{{.*}}, double [[EXT]], i32 0
+ // CHECK: [[A:%.*]] = extractelement <2 x double> [[VEC:%.*]], i64 0
+ // CHECK-NEXT: [[B:%.*]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.*]] = select i1 %{{.*}}, double [[A]], double [[B]]
+ // CHECK-NEXT: insertelement <2 x double> [[VEC]], double [[SEL]], i64 0
return _mm_mask_move_sd ( __W, __U, __A, __B);
}
__m128d test_mm_maskz_move_sd (__mmask8 __U, __m128d __A, __m128d __B)
{
// CHECK-LABEL: @test_mm_maskz_move_sd
- // CHECK: extractelement <2 x double> %{{.*}}, i32 0
- // CHECK: phi double [ %{{.*}}, %{{.*}} ], [ 0.000000e+00, %{{.*}} ]
- // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 0
+ // CHECK: [[EXT:%.*]] = extractelement <2 x double> %{{.*}}, i32 0
+ // CHECK: insertelement <2 x double> %{{.*}}, double [[EXT]], i32 0
+ // CHECK: [[A:%.*]] = extractelement <2 x double> [[VEC:%.*]], i64 0
+ // CHECK-NEXT: [[B:%.*]] = extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0
+ // CHECK-NEXT: [[SEL:%.*]] = select i1 %13, double [[A]], double [[B]]
+ // CHECK-NEXT: insertelement <2 x double> [[VEC]], double [[SEL]], i64 0
return _mm_maskz_move_sd (__U, __A, __B);
}
void test_mm_mask_store_ss(float * __P, __mmask8 __U, __m128 __A)
{
// CHECK-LABEL: @test_mm_mask_store_ss
- // CHECK: call void @llvm.masked.store.v16f32.p0v16f32(
+ // CHECK: call void @llvm.masked.store.v4f32.p0v4f32(
_mm_mask_store_ss(__P, __U, __A);
}
void test_mm_mask_store_sd(double * __P, __mmask8 __U, __m128d __A)
{
// CHECK-LABEL: @test_mm_mask_store_sd
- // CHECK: call void @llvm.masked.store.v8f64.p0v8f64(
+ // CHECK: call void @llvm.masked.store.v2f64.p0v2f64(
_mm_mask_store_sd(__P, __U, __A);
}
__m128 test_mm_mask_load_ss(__m128 __A, __mmask8 __U, const float* __W)
{
// CHECK-LABEL: @test_mm_mask_load_ss
- // CHECK: call <16 x float> @llvm.masked.load.v16f32.p0v16f32(
+ // CHECK: call <4 x float> @llvm.masked.load.v4f32.p0v4f32(
return _mm_mask_load_ss(__A, __U, __W);
}
__m128 test_mm_maskz_load_ss (__mmask8 __U, const float * __W)
{
// CHECK-LABEL: @test_mm_maskz_load_ss
- // CHECK: call <16 x float> @llvm.masked.load.v16f32.p0v16f32(
+ // CHECK: call <4 x float> @llvm.masked.load.v4f32.p0v4f32(
return _mm_maskz_load_ss (__U, __W);
}
__m128d test_mm_mask_load_sd (__m128d __A, __mmask8 __U, const double * __W)
{
// CHECK-LABEL: @test_mm_mask_load_sd
- // CHECK: call <8 x double> @llvm.masked.load.v8f64.p0v8f64(
+ // CHECK: call <2 x double> @llvm.masked.load.v2f64.p0v2f64(
return _mm_mask_load_sd (__A, __U, __W);
}
__m128d test_mm_maskz_load_sd (__mmask8 __U, const double * __W)
{
// CHECK-LABEL: @test_mm_maskz_load_sd
- // CHECK: call <8 x double> @llvm.masked.load.v8f64.p0v8f64(
+ // CHECK: call <2 x double> @llvm.masked.load.v2f64.p0v2f64(
return _mm_maskz_load_sd (__U, __W);
}
diff --git a/test/CodeGen/avx512ifma-builtins.c b/test/CodeGen/avx512ifma-builtins.c
index 311d6989bf0d..383cf5350428 100644
--- a/test/CodeGen/avx512ifma-builtins.c
+++ b/test/CodeGen/avx512ifma-builtins.c
@@ -5,36 +5,40 @@
__m512i test_mm512_madd52hi_epu64(__m512i __X, __m512i __Y, __m512i __Z) {
// CHECK-LABEL: @test_mm512_madd52hi_epu64
- // CHECK: @llvm.x86.avx512.mask.vpmadd52h.uq.512
+ // CHECK: @llvm.x86.avx512.vpmadd52h.uq.512
return _mm512_madd52hi_epu64(__X, __Y, __Z);
}
__m512i test_mm512_mask_madd52hi_epu64(__m512i __W, __mmask8 __M, __m512i __X, __m512i __Y) {
// CHECK-LABEL: @test_mm512_mask_madd52hi_epu64
- // CHECK: @llvm.x86.avx512.mask.vpmadd52h.uq.512
+ // CHECK: @llvm.x86.avx512.vpmadd52h.uq.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_madd52hi_epu64(__W, __M, __X, __Y);
}
__m512i test_mm512_maskz_madd52hi_epu64(__mmask8 __M, __m512i __X, __m512i __Y, __m512i __Z) {
// CHECK-LABEL: @test_mm512_maskz_madd52hi_epu64
- // CHECK: @llvm.x86.avx512.maskz.vpmadd52h.uq.512
+ // CHECK: @llvm.x86.avx512.vpmadd52h.uq.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_madd52hi_epu64(__M, __X, __Y, __Z);
}
__m512i test_mm512_madd52lo_epu64(__m512i __X, __m512i __Y, __m512i __Z) {
// CHECK-LABEL: @test_mm512_madd52lo_epu64
- // CHECK: @llvm.x86.avx512.mask.vpmadd52l.uq.512
+ // CHECK: @llvm.x86.avx512.vpmadd52l.uq.512
return _mm512_madd52lo_epu64(__X, __Y, __Z);
}
__m512i test_mm512_mask_madd52lo_epu64(__m512i __W, __mmask8 __M, __m512i __X, __m512i __Y) {
// CHECK-LABEL: @test_mm512_mask_madd52lo_epu64
- // CHECK: @llvm.x86.avx512.mask.vpmadd52l.uq.512
+ // CHECK: @llvm.x86.avx512.vpmadd52l.uq.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_madd52lo_epu64(__W, __M, __X, __Y);
}
__m512i test_mm512_maskz_madd52lo_epu64(__mmask8 __M, __m512i __X, __m512i __Y, __m512i __Z) {
// CHECK-LABEL: @test_mm512_maskz_madd52lo_epu64
- // CHECK: @llvm.x86.avx512.mask.vpmadd52l.uq.512
+ // CHECK: @llvm.x86.avx512.vpmadd52l.uq.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_madd52lo_epu64(__M, __X, __Y, __Z);
}
diff --git a/test/CodeGen/avx512ifmavl-builtins.c b/test/CodeGen/avx512ifmavl-builtins.c
index 4aeec336ad94..2fe9938eab76 100644
--- a/test/CodeGen/avx512ifmavl-builtins.c
+++ b/test/CodeGen/avx512ifmavl-builtins.c
@@ -4,72 +4,80 @@
__m128i test_mm_madd52hi_epu64(__m128i __X, __m128i __Y, __m128i __Z) {
// CHECK-LABEL: @test_mm_madd52hi_epu64
- // CHECK: @llvm.x86.avx512.mask.vpmadd52h.uq.128
+ // CHECK: @llvm.x86.avx512.vpmadd52h.uq.128
return _mm_madd52hi_epu64(__X, __Y, __Z);
}
__m128i test_mm_mask_madd52hi_epu64(__m128i __W, __mmask8 __M, __m128i __X, __m128i __Y) {
// CHECK-LABEL: @test_mm_mask_madd52hi_epu64
- // CHECK: @llvm.x86.avx512.mask.vpmadd52h.uq.128
+ // CHECK: @llvm.x86.avx512.vpmadd52h.uq.128
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_madd52hi_epu64(__W, __M, __X, __Y);
}
__m128i test_mm_maskz_madd52hi_epu64(__mmask8 __M, __m128i __X, __m128i __Y, __m128i __Z) {
// CHECK-LABEL: @test_mm_maskz_madd52hi_epu64
- // CHECK: @llvm.x86.avx512.maskz.vpmadd52h.uq.128
+ // CHECK: @llvm.x86.avx512.vpmadd52h.uq.128
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_madd52hi_epu64(__M, __X, __Y, __Z);
}
__m256i test_mm256_madd52hi_epu64(__m256i __X, __m256i __Y, __m256i __Z) {
// CHECK-LABEL: @test_mm256_madd52hi_epu64
- // CHECK: @llvm.x86.avx512.mask.vpmadd52h.uq.256
+ // CHECK: @llvm.x86.avx512.vpmadd52h.uq.256
return _mm256_madd52hi_epu64(__X, __Y, __Z);
}
__m256i test_mm256_mask_madd52hi_epu64(__m256i __W, __mmask8 __M, __m256i __X, __m256i __Y) {
// CHECK-LABEL: @test_mm256_mask_madd52hi_epu64
- // CHECK: @llvm.x86.avx512.mask.vpmadd52h.uq.256
+ // CHECK: @llvm.x86.avx512.vpmadd52h.uq.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_madd52hi_epu64(__W, __M, __X, __Y);
}
__m256i test_mm256_maskz_madd52hi_epu64(__mmask8 __M, __m256i __X, __m256i __Y, __m256i __Z) {
// CHECK-LABEL: @test_mm256_maskz_madd52hi_epu64
- // CHECK: @llvm.x86.avx512.maskz.vpmadd52h.uq.256
+ // CHECK: @llvm.x86.avx512.vpmadd52h.uq.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_madd52hi_epu64(__M, __X, __Y, __Z);
}
__m128i test_mm_madd52lo_epu64(__m128i __X, __m128i __Y, __m128i __Z) {
// CHECK-LABEL: @test_mm_madd52lo_epu64
- // CHECK: @llvm.x86.avx512.mask.vpmadd52l.uq.128
+ // CHECK: @llvm.x86.avx512.vpmadd52l.uq.128
return _mm_madd52lo_epu64(__X, __Y, __Z);
}
__m128i test_mm_mask_madd52lo_epu64(__m128i __W, __mmask8 __M, __m128i __X, __m128i __Y) {
// CHECK-LABEL: @test_mm_mask_madd52lo_epu64
- // CHECK: @llvm.x86.avx512.mask.vpmadd52l.uq.128
+ // CHECK: @llvm.x86.avx512.vpmadd52l.uq.128
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_madd52lo_epu64(__W, __M, __X, __Y);
}
__m128i test_mm_maskz_madd52lo_epu64(__mmask8 __M, __m128i __X, __m128i __Y, __m128i __Z) {
// CHECK-LABEL: @test_mm_maskz_madd52lo_epu64
- // CHECK: @llvm.x86.avx512.maskz.vpmadd52l.uq.128
+ // CHECK: @llvm.x86.avx512.vpmadd52l.uq.128
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_madd52lo_epu64(__M, __X, __Y, __Z);
}
__m256i test_mm256_madd52lo_epu64(__m256i __X, __m256i __Y, __m256i __Z) {
// CHECK-LABEL: @test_mm256_madd52lo_epu64
- // CHECK: @llvm.x86.avx512.mask.vpmadd52l.uq.256
+ // CHECK: @llvm.x86.avx512.vpmadd52l.uq.256
return _mm256_madd52lo_epu64(__X, __Y, __Z);
}
__m256i test_mm256_mask_madd52lo_epu64(__m256i __W, __mmask8 __M, __m256i __X, __m256i __Y) {
// CHECK-LABEL: @test_mm256_mask_madd52lo_epu64
- // CHECK: @llvm.x86.avx512.mask.vpmadd52l.uq.256
+ // CHECK: @llvm.x86.avx512.vpmadd52l.uq.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_madd52lo_epu64(__W, __M, __X, __Y);
}
__m256i test_mm256_maskz_madd52lo_epu64(__mmask8 __M, __m256i __X, __m256i __Y, __m256i __Z) {
// CHECK-LABEL: @test_mm256_maskz_madd52lo_epu64
- // CHECK: @llvm.x86.avx512.mask.vpmadd52l.uq.256
+ // CHECK: @llvm.x86.avx512.vpmadd52l.uq.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_madd52lo_epu64(__M, __X, __Y, __Z);
}
diff --git a/test/CodeGen/avx512vbmi-builtins.c b/test/CodeGen/avx512vbmi-builtins.c
index 0816bce3a6de..0347916af09f 100644
--- a/test/CodeGen/avx512vbmi-builtins.c
+++ b/test/CodeGen/avx512vbmi-builtins.c
@@ -5,43 +5,48 @@
__m512i test_mm512_mask2_permutex2var_epi8(__m512i __A, __m512i __I, __mmask64 __U, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask2_permutex2var_epi8
- // CHECK: @llvm.x86.avx512.mask.vpermi2var.qi.512
+ // CHECK: @llvm.x86.avx512.vpermi2var.qi.512
+ // CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}}
return _mm512_mask2_permutex2var_epi8(__A, __I, __U, __B);
}
__m512i test_mm512_permutex2var_epi8(__m512i __A, __m512i __I, __m512i __B) {
// CHECK-LABEL: @test_mm512_permutex2var_epi8
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.qi.512
+ // CHECK: @llvm.x86.avx512.vpermi2var.qi.512
return _mm512_permutex2var_epi8(__A, __I, __B);
}
__m512i test_mm512_mask_permutex2var_epi8(__m512i __A, __mmask64 __U, __m512i __I, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_permutex2var_epi8
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.qi.512
+ // CHECK: @llvm.x86.avx512.vpermi2var.qi.512
+ // CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}}
return _mm512_mask_permutex2var_epi8(__A, __U, __I, __B);
}
__m512i test_mm512_maskz_permutex2var_epi8(__mmask64 __U, __m512i __A, __m512i __I, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_permutex2var_epi8
- // CHECK: @llvm.x86.avx512.maskz.vpermt2var.qi.512
+ // CHECK: @llvm.x86.avx512.vpermi2var.qi.512
+ // CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}}
return _mm512_maskz_permutex2var_epi8(__U, __A, __I, __B);
}
__m512i test_mm512_permutexvar_epi8(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_permutexvar_epi8
- // CHECK: @llvm.x86.avx512.mask.permvar.qi.512
+ // CHECK: @llvm.x86.avx512.permvar.qi.512
return _mm512_permutexvar_epi8(__A, __B);
}
__m512i test_mm512_maskz_permutexvar_epi8(__mmask64 __M, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_permutexvar_epi8
- // CHECK: @llvm.x86.avx512.mask.permvar.qi.512
+ // CHECK: @llvm.x86.avx512.permvar.qi.512
+ // CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}}
return _mm512_maskz_permutexvar_epi8(__M, __A, __B);
}
__m512i test_mm512_mask_permutexvar_epi8(__m512i __W, __mmask64 __M, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_permutexvar_epi8
- // CHECK: @llvm.x86.avx512.mask.permvar.qi.512
+ // CHECK: @llvm.x86.avx512.permvar.qi.512
+ // CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}}
return _mm512_mask_permutexvar_epi8(__W, __M, __A, __B);
}
diff --git a/test/CodeGen/avx512vbmi2-builtins.c b/test/CodeGen/avx512vbmi2-builtins.c
index 4da21e39d4e3..db4abdba457f 100644
--- a/test/CodeGen/avx512vbmi2-builtins.c
+++ b/test/CodeGen/avx512vbmi2-builtins.c
@@ -28,13 +28,13 @@ __m512i test_mm512_maskz_compress_epi8(__mmask64 __U, __m512i __D) {
void test_mm512_mask_compressstoreu_epi16(void *__P, __mmask32 __U, __m512i __D) {
// CHECK-LABEL: @test_mm512_mask_compressstoreu_epi16
- // CHECK: @llvm.x86.avx512.mask.compress.store.w.512
+ // CHECK: @llvm.masked.compressstore.v32i16(<32 x i16> %{{.*}}, i16* %{{.*}}, <32 x i1> %{{.*}})
_mm512_mask_compressstoreu_epi16(__P, __U, __D);
}
void test_mm512_mask_compressstoreu_epi8(void *__P, __mmask64 __U, __m512i __D) {
// CHECK-LABEL: @test_mm512_mask_compressstoreu_epi8
- // CHECK: @llvm.x86.avx512.mask.compress.store.b.512
+ // CHECK: @llvm.masked.compressstore.v64i8(<64 x i8> %{{.*}}, i8* %{{.*}}, <64 x i1> %{{.*}})
_mm512_mask_compressstoreu_epi8(__P, __U, __D);
}
@@ -64,133 +64,145 @@ __m512i test_mm512_maskz_expand_epi8(__mmask64 __U, __m512i __D) {
__m512i test_mm512_mask_expandloadu_epi16(__m512i __S, __mmask32 __U, void const* __P) {
// CHECK-LABEL: @test_mm512_mask_expandloadu_epi16
- // CHECK: @llvm.x86.avx512.mask.expand.load.w.512
+ // CHECK: @llvm.masked.expandload.v32i16(i16* %{{.*}}, <32 x i1> %{{.*}}, <32 x i16> %{{.*}})
return _mm512_mask_expandloadu_epi16(__S, __U, __P);
}
__m512i test_mm512_maskz_expandloadu_epi16(__mmask32 __U, void const* __P) {
// CHECK-LABEL: @test_mm512_maskz_expandloadu_epi16
- // CHECK: @llvm.x86.avx512.mask.expand.load.w.512
+ // CHECK: @llvm.masked.expandload.v32i16(i16* %{{.*}}, <32 x i1> %{{.*}}, <32 x i16> %{{.*}})
return _mm512_maskz_expandloadu_epi16(__U, __P);
}
__m512i test_mm512_mask_expandloadu_epi8(__m512i __S, __mmask64 __U, void const* __P) {
// CHECK-LABEL: @test_mm512_mask_expandloadu_epi8
- // CHECK: @llvm.x86.avx512.mask.expand.load.b.512
+ // CHECK: @llvm.masked.expandload.v64i8(i8* %{{.*}}, <64 x i1> %{{.*}}, <64 x i8> %{{.*}})
return _mm512_mask_expandloadu_epi8(__S, __U, __P);
}
__m512i test_mm512_maskz_expandloadu_epi8(__mmask64 __U, void const* __P) {
// CHECK-LABEL: @test_mm512_maskz_expandloadu_epi8
- // CHECK: @llvm.x86.avx512.mask.expand.load.b.512
+ // CHECK: @llvm.masked.expandload.v64i8(i8* %{{.*}}, <64 x i1> %{{.*}}, <64 x i8> %{{.*}})
return _mm512_maskz_expandloadu_epi8(__U, __P);
}
__m512i test_mm512_mask_shldi_epi64(__m512i __S, __mmask8 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_shldi_epi64
- // CHECK: @llvm.x86.avx512.mask.vpshld.q.512
+ // CHECK: @llvm.x86.avx512.vpshld.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_shldi_epi64(__S, __U, __A, __B, 127);
}
__m512i test_mm512_maskz_shldi_epi64(__mmask8 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_shldi_epi64
- // CHECK: @llvm.x86.avx512.mask.vpshld.q.512
+ // CHECK: @llvm.x86.avx512.vpshld.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_shldi_epi64(__U, __A, __B, 63);
}
__m512i test_mm512_shldi_epi64(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_shldi_epi64
- // CHECK: @llvm.x86.avx512.mask.vpshld.q.512
+ // CHECK: @llvm.x86.avx512.vpshld.q.512
return _mm512_shldi_epi64(__A, __B, 31);
}
__m512i test_mm512_mask_shldi_epi32(__m512i __S, __mmask16 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_shldi_epi32
- // CHECK: @llvm.x86.avx512.mask.vpshld.d.512
+ // CHECK: @llvm.x86.avx512.vpshld.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_shldi_epi32(__S, __U, __A, __B, 127);
}
__m512i test_mm512_maskz_shldi_epi32(__mmask16 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_shldi_epi32
- // CHECK: @llvm.x86.avx512.mask.vpshld.d.512
+ // CHECK: @llvm.x86.avx512.vpshld.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_shldi_epi32(__U, __A, __B, 63);
}
__m512i test_mm512_shldi_epi32(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_shldi_epi32
- // CHECK: @llvm.x86.avx512.mask.vpshld.d.512
+ // CHECK: @llvm.x86.avx512.vpshld.d.512
return _mm512_shldi_epi32(__A, __B, 31);
}
__m512i test_mm512_mask_shldi_epi16(__m512i __S, __mmask32 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_shldi_epi16
- // CHECK: @llvm.x86.avx512.mask.vpshld.w.512
+ // CHECK: @llvm.x86.avx512.vpshld.w.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_mask_shldi_epi16(__S, __U, __A, __B, 127);
}
__m512i test_mm512_maskz_shldi_epi16(__mmask32 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_shldi_epi16
- // CHECK: @llvm.x86.avx512.mask.vpshld.w.512
+ // CHECK: @llvm.x86.avx512.vpshld.w.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_maskz_shldi_epi16(__U, __A, __B, 63);
}
__m512i test_mm512_shldi_epi16(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_shldi_epi16
- // CHECK: @llvm.x86.avx512.mask.vpshld.w.512
+ // CHECK: @llvm.x86.avx512.vpshld.w.512
return _mm512_shldi_epi16(__A, __B, 31);
}
__m512i test_mm512_mask_shrdi_epi64(__m512i __S, __mmask8 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_shrdi_epi64
- // CHECK: @llvm.x86.avx512.mask.vpshrd.q.512
+ // CHECK: @llvm.x86.avx512.vpshrd.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_shrdi_epi64(__S, __U, __A, __B, 127);
}
__m512i test_mm512_maskz_shrdi_epi64(__mmask8 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_shrdi_epi64
- // CHECK: @llvm.x86.avx512.mask.vpshrd.q.512
+ // CHECK: @llvm.x86.avx512.vpshrd.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_shrdi_epi64(__U, __A, __B, 63);
}
__m512i test_mm512_shrdi_epi64(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_shrdi_epi64
- // CHECK: @llvm.x86.avx512.mask.vpshrd.q.512
+ // CHECK: @llvm.x86.avx512.vpshrd.q.512
return _mm512_shrdi_epi64(__A, __B, 31);
}
__m512i test_mm512_mask_shrdi_epi32(__m512i __S, __mmask16 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_shrdi_epi32
- // CHECK: @llvm.x86.avx512.mask.vpshrd.d.512
+ // CHECK: @llvm.x86.avx512.vpshrd.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_shrdi_epi32(__S, __U, __A, __B, 127);
}
__m512i test_mm512_maskz_shrdi_epi32(__mmask16 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_shrdi_epi32
- // CHECK: @llvm.x86.avx512.mask.vpshrd.d.512
+ // CHECK: @llvm.x86.avx512.vpshrd.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_shrdi_epi32(__U, __A, __B, 63);
}
__m512i test_mm512_shrdi_epi32(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_shrdi_epi32
- // CHECK: @llvm.x86.avx512.mask.vpshrd.d.512
+ // CHECK: @llvm.x86.avx512.vpshrd.d.512
return _mm512_shrdi_epi32(__A, __B, 31);
}
__m512i test_mm512_mask_shrdi_epi16(__m512i __S, __mmask32 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_shrdi_epi16
- // CHECK: @llvm.x86.avx512.mask.vpshrd.w.512
+ // CHECK: @llvm.x86.avx512.vpshrd.w.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_mask_shrdi_epi16(__S, __U, __A, __B, 127);
}
__m512i test_mm512_maskz_shrdi_epi16(__mmask32 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_shrdi_epi16
- // CHECK: @llvm.x86.avx512.mask.vpshrd.w.512
+ // CHECK: @llvm.x86.avx512.vpshrd.w.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_maskz_shrdi_epi16(__U, __A, __B, 63);
}
__m512i test_mm512_shrdi_epi16(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_shrdi_epi16
- // CHECK: @llvm.x86.avx512.mask.vpshrd.w.512
+ // CHECK: @llvm.x86.avx512.vpshrd.w.512
return _mm512_shrdi_epi16(__A, __B, 31);
}
diff --git a/test/CodeGen/avx512vbmivl-builtin.c b/test/CodeGen/avx512vbmivl-builtin.c
index b114720758aa..da8986f2e7d8 100644
--- a/test/CodeGen/avx512vbmivl-builtin.c
+++ b/test/CodeGen/avx512vbmivl-builtin.c
@@ -5,85 +5,95 @@
__m128i test_mm_permutexvar_epi8(__m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_permutexvar_epi8
- // CHECK: @llvm.x86.avx512.mask.permvar.qi.128
+ // CHECK: @llvm.x86.avx512.permvar.qi.128
return _mm_permutexvar_epi8(__A, __B);
}
__m128i test_mm_maskz_permutexvar_epi8(__mmask16 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_permutexvar_epi8
- // CHECK: @llvm.x86.avx512.mask.permvar.qi.128
+ // CHECK: @llvm.x86.avx512.permvar.qi.128
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_maskz_permutexvar_epi8(__M, __A, __B);
}
__m128i test_mm_mask_permutexvar_epi8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_permutexvar_epi8
- // CHECK: @llvm.x86.avx512.mask.permvar.qi.128
+ // CHECK: @llvm.x86.avx512.permvar.qi.128
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_mask_permutexvar_epi8(__W, __M, __A, __B);
}
__m256i test_mm256_permutexvar_epi8(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_permutexvar_epi8
- // CHECK: @llvm.x86.avx512.mask.permvar.qi.256
+ // CHECK: @llvm.x86.avx512.permvar.qi.256
return _mm256_permutexvar_epi8(__A, __B);
}
__m256i test_mm256_maskz_permutexvar_epi8(__mmask32 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_permutexvar_epi8
- // CHECK: @llvm.x86.avx512.mask.permvar.qi.256
+ // CHECK: @llvm.x86.avx512.permvar.qi.256
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_maskz_permutexvar_epi8(__M, __A, __B);
}
__m256i test_mm256_mask_permutexvar_epi8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_permutexvar_epi8
- // CHECK: @llvm.x86.avx512.mask.permvar.qi.256
+ // CHECK: @llvm.x86.avx512.permvar.qi.256
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_mask_permutexvar_epi8(__W, __M, __A, __B);
}
__m128i test_mm_mask2_permutex2var_epi8(__m128i __A, __m128i __I, __mmask16 __U, __m128i __B) {
// CHECK-LABEL: @test_mm_mask2_permutex2var_epi8
- // CHECK: @llvm.x86.avx512.mask.vpermi2var.qi.128
+ // CHECK: @llvm.x86.avx512.vpermi2var.qi.128
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_mask2_permutex2var_epi8(__A, __I, __U, __B);
}
__m256i test_mm256_mask2_permutex2var_epi8(__m256i __A, __m256i __I, __mmask32 __U, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask2_permutex2var_epi8
- // CHECK: @llvm.x86.avx512.mask.vpermi2var.qi.256
+ // CHECK: @llvm.x86.avx512.vpermi2var.qi.256
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_mask2_permutex2var_epi8(__A, __I, __U, __B);
}
__m128i test_mm_permutex2var_epi8(__m128i __A, __m128i __I, __m128i __B) {
// CHECK-LABEL: @test_mm_permutex2var_epi8
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.qi.128
+ // CHECK: @llvm.x86.avx512.vpermi2var.qi.128
return _mm_permutex2var_epi8(__A, __I, __B);
}
__m128i test_mm_mask_permutex2var_epi8(__m128i __A, __mmask16 __U, __m128i __I, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_permutex2var_epi8
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.qi.128
+ // CHECK: @llvm.x86.avx512.vpermi2var.qi.128
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_mask_permutex2var_epi8(__A, __U, __I, __B);
}
__m128i test_mm_maskz_permutex2var_epi8(__mmask16 __U, __m128i __A, __m128i __I, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_permutex2var_epi8
- // CHECK: @llvm.x86.avx512.maskz.vpermt2var.qi.128
+ // CHECK: @llvm.x86.avx512.vpermi2var.qi.128
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_maskz_permutex2var_epi8(__U, __A, __I, __B);
}
__m256i test_mm256_permutex2var_epi8(__m256i __A, __m256i __I, __m256i __B) {
// CHECK-LABEL: @test_mm256_permutex2var_epi8
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.qi.256
+ // CHECK: @llvm.x86.avx512.vpermi2var.qi.256
return _mm256_permutex2var_epi8(__A, __I, __B);
}
__m256i test_mm256_mask_permutex2var_epi8(__m256i __A, __mmask32 __U, __m256i __I, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_permutex2var_epi8
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.qi.256
+ // CHECK: @llvm.x86.avx512.vpermi2var.qi.256
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_mask_permutex2var_epi8(__A, __U, __I, __B);
}
__m256i test_mm256_maskz_permutex2var_epi8(__mmask32 __U, __m256i __A, __m256i __I, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_permutex2var_epi8
- // CHECK: @llvm.x86.avx512.maskz.vpermt2var.qi.256
+ // CHECK: @llvm.x86.avx512.vpermi2var.qi.256
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_maskz_permutex2var_epi8(__U, __A, __I, __B);
}
diff --git a/test/CodeGen/avx512vl-builtins.c b/test/CodeGen/avx512vl-builtins.c
index b4fc86da704b..7e4e64381c1d 100644
--- a/test/CodeGen/avx512vl-builtins.c
+++ b/test/CodeGen/avx512vl-builtins.c
@@ -727,14 +727,22 @@ __m128i test_mm_maskz_sub_epi64 (__mmask8 __U, __m128i __A, __m128i __B) {
__m256i test_mm256_mask_mul_epi32 (__m256i __W, __mmask8 __M, __m256i __X,
__m256i __Y) {
//CHECK-LABEL: @test_mm256_mask_mul_epi32
- //CHECK: @llvm.x86.avx2.pmul.dq
+ //CHECK: shl <4 x i64> %{{.*}}, <i64 32, i64 32, i64 32, i64 32>
+ //CHECK: ashr <4 x i64> %{{.*}}, <i64 32, i64 32, i64 32, i64 32>
+ //CHECK: shl <4 x i64> %{{.*}}, <i64 32, i64 32, i64 32, i64 32>
+ //CHECK: ashr <4 x i64> %{{.*}}, <i64 32, i64 32, i64 32, i64 32>
+ //CHECK: mul <4 x i64> %{{.*}}, %{{.*}}
//CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_mul_epi32(__W, __M, __X, __Y);
}
__m256i test_mm256_maskz_mul_epi32 (__mmask8 __M, __m256i __X, __m256i __Y) {
//CHECK-LABEL: @test_mm256_maskz_mul_epi32
- //CHECK: @llvm.x86.avx2.pmul.dq
+ //CHECK: shl <4 x i64> %{{.*}}, <i64 32, i64 32, i64 32, i64 32>
+ //CHECK: ashr <4 x i64> %{{.*}}, <i64 32, i64 32, i64 32, i64 32>
+ //CHECK: shl <4 x i64> %{{.*}}, <i64 32, i64 32, i64 32, i64 32>
+ //CHECK: ashr <4 x i64> %{{.*}}, <i64 32, i64 32, i64 32, i64 32>
+ //CHECK: mul <4 x i64> %{{.*}}, %{{.*}}
//CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_mul_epi32(__M, __X, __Y);
}
@@ -743,14 +751,22 @@ __m256i test_mm256_maskz_mul_epi32 (__mmask8 __M, __m256i __X, __m256i __Y) {
__m128i test_mm_mask_mul_epi32 (__m128i __W, __mmask8 __M, __m128i __X,
__m128i __Y) {
//CHECK-LABEL: @test_mm_mask_mul_epi32
- //CHECK: @llvm.x86.sse41.pmuldq
+ //CHECK: shl <2 x i64> %{{.*}}, <i64 32, i64 32>
+ //CHECK: ashr <2 x i64> %{{.*}}, <i64 32, i64 32>
+ //CHECK: shl <2 x i64> %{{.*}}, <i64 32, i64 32>
+ //CHECK: ashr <2 x i64> %{{.*}}, <i64 32, i64 32>
+ //CHECK: mul <2 x i64> %{{.*}}, %{{.*}}
//CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_mul_epi32(__W, __M, __X, __Y);
}
__m128i test_mm_maskz_mul_epi32 (__mmask8 __M, __m128i __X, __m128i __Y) {
//CHECK-LABEL: @test_mm_maskz_mul_epi32
- //CHECK: @llvm.x86.sse41.pmuldq
+ //CHECK: shl <2 x i64> %{{.*}}, <i64 32, i64 32>
+ //CHECK: ashr <2 x i64> %{{.*}}, <i64 32, i64 32>
+ //CHECK: shl <2 x i64> %{{.*}}, <i64 32, i64 32>
+ //CHECK: ashr <2 x i64> %{{.*}}, <i64 32, i64 32>
+ //CHECK: mul <2 x i64> %{{.*}}, %{{.*}}
//CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_mul_epi32(__M, __X, __Y);
}
@@ -758,14 +774,18 @@ __m128i test_mm_maskz_mul_epi32 (__mmask8 __M, __m128i __X, __m128i __Y) {
__m256i test_mm256_mask_mul_epu32 (__m256i __W, __mmask8 __M, __m256i __X,
__m256i __Y) {
//CHECK-LABEL: @test_mm256_mask_mul_epu32
- //CHECK: @llvm.x86.avx2.pmulu.dq
+ //CHECK: and <4 x i64> %{{.*}}, <i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295>
+ //CHECK: and <4 x i64> %{{.*}}, <i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295>
+ //CHECK: mul <4 x i64> %{{.*}}, %{{.*}}
//CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_mul_epu32(__W, __M, __X, __Y);
}
__m256i test_mm256_maskz_mul_epu32 (__mmask8 __M, __m256i __X, __m256i __Y) {
//CHECK-LABEL: @test_mm256_maskz_mul_epu32
- //CHECK: @llvm.x86.avx2.pmulu.dq
+ //CHECK: and <4 x i64> %{{.*}}, <i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295>
+ //CHECK: and <4 x i64> %{{.*}}, <i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295>
+ //CHECK: mul <4 x i64> %{{.*}}, %{{.*}}
//CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_mul_epu32(__M, __X, __Y);
}
@@ -773,14 +793,18 @@ __m256i test_mm256_maskz_mul_epu32 (__mmask8 __M, __m256i __X, __m256i __Y) {
__m128i test_mm_mask_mul_epu32 (__m128i __W, __mmask8 __M, __m128i __X,
__m128i __Y) {
//CHECK-LABEL: @test_mm_mask_mul_epu32
- //CHECK: @llvm.x86.sse2.pmulu.dq
+ //CHECK: and <2 x i64> %{{.*}}, <i64 4294967295, i64 4294967295>
+ //CHECK: and <2 x i64> %{{.*}}, <i64 4294967295, i64 4294967295>
+ //CHECK: mul <2 x i64> %{{.*}}, %{{.*}}
//CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_mul_epu32(__W, __M, __X, __Y);
}
__m128i test_mm_maskz_mul_epu32 (__mmask8 __M, __m128i __X, __m128i __Y) {
//CHECK-LABEL: @test_mm_maskz_mul_epu32
- //CHECK: @llvm.x86.sse2.pmulu.dq
+ //CHECK: and <2 x i64> %{{.*}}, <i64 4294967295, i64 4294967295>
+ //CHECK: and <2 x i64> %{{.*}}, <i64 4294967295, i64 4294967295>
+ //CHECK: mul <2 x i64> %{{.*}}, %{{.*}}
//CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_mul_epu32(__M, __X, __Y);
}
@@ -1047,483 +1071,2417 @@ __m128i test_mm_maskz_xor_epi64 (__mmask8 __U, __m128i __A, __m128i __B) {
return _mm_maskz_xor_epi64( __U, __A, __B);
}
-__mmask8 test_mm256_cmp_ps_mask(__m256 __A, __m256 __B) {
- // CHECK-LABEL: @test_mm256_cmp_ps_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.ps.256
- return (__mmask8)_mm256_cmp_ps_mask(__A, __B, 0);
+__mmask8 test_mm256_cmp_ps_mask_eq_oq(__m256 a, __m256 b) {
+ // CHECK-LABEL: @test_mm256_cmp_ps_mask_eq_oq
+ // CHECK: fcmp oeq <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps_mask(a, b, _CMP_EQ_OQ);
}
-__mmask8 test_mm256_mask_cmp_ps_mask(__mmask8 m, __m256 __A, __m256 __B) {
- // CHECK-LABEL: @test_mm256_mask_cmp_ps_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.ps.256
- return _mm256_mask_cmp_ps_mask(m, __A, __B, 0);
+__mmask8 test_mm256_cmp_ps_mask_lt_os(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_mask_lt_os
+ // CHECK: fcmp olt <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps_mask(a, b, _CMP_LT_OS);
}
-__mmask8 test_mm_cmp_ps_mask(__m128 __A, __m128 __B) {
- // CHECK-LABEL: @test_mm_cmp_ps_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.ps.128
- return (__mmask8)_mm_cmp_ps_mask(__A, __B, 0);
+__mmask8 test_mm256_cmp_ps_mask_le_os(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_mask_le_os
+ // CHECK: fcmp ole <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps_mask(a, b, _CMP_LE_OS);
}
-__mmask8 test_mm_mask_cmp_ps_mask(__mmask8 m, __m128 __A, __m128 __B) {
- // CHECK-LABEL: @test_mm_mask_cmp_ps_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.ps.128
- return _mm_mask_cmp_ps_mask(m, __A, __B, 0);
+__mmask8 test_mm256_cmp_ps_mask_unord_q(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_mask_unord_q
+ // CHECK: fcmp uno <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps_mask(a, b, _CMP_UNORD_Q);
}
-__mmask8 test_mm256_cmp_pd_mask(__m256d __A, __m256d __B) {
- // CHECK-LABEL: @test_mm256_cmp_pd_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.pd.256
- return (__mmask8)_mm256_cmp_pd_mask(__A, __B, 0);
+__mmask8 test_mm256_cmp_ps_mask_neq_uq(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_mask_neq_uq
+ // CHECK: fcmp une <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps_mask(a, b, _CMP_NEQ_UQ);
}
-__mmask8 test_mm256_mask_cmp_pd_mask(__mmask8 m, __m256d __A, __m256d __B) {
- // CHECK-LABEL: @test_mm256_mask_cmp_pd_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.pd.256
- return _mm256_mask_cmp_pd_mask(m, __A, __B, 0);
+__mmask8 test_mm256_cmp_ps_mask_nlt_us(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_mask_nlt_us
+ // CHECK: fcmp uge <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps_mask(a, b, _CMP_NLT_US);
}
-__mmask8 test_mm_cmp_pd_mask(__m128d __A, __m128d __B) {
- // CHECK-LABEL: @test_mm_cmp_pd_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.pd.128
- return (__mmask8)_mm_cmp_pd_mask(__A, __B, 0);
+__mmask8 test_mm256_cmp_ps_mask_nle_us(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_mask_nle_us
+ // CHECK: fcmp ugt <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps_mask(a, b, _CMP_NLE_US);
}
-__mmask8 test_mm_mask_cmp_pd_mask(__mmask8 m, __m128d __A, __m128d __B) {
- // CHECK-LABEL: @test_mm_mask_cmp_pd_mask
- // CHECK: @llvm.x86.avx512.mask.cmp.pd.128
- return _mm_mask_cmp_pd_mask(m, __A, __B, 0);
+__mmask8 test_mm256_cmp_ps_mask_ord_q(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_mask_ord_q
+ // CHECK: fcmp ord <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps_mask(a, b, _CMP_ORD_Q);
+}
+
+__mmask8 test_mm256_cmp_ps_mask_eq_uq(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_mask_eq_uq
+ // CHECK: fcmp ueq <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps_mask(a, b, _CMP_EQ_UQ);
+}
+
+__mmask8 test_mm256_cmp_ps_mask_nge_us(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_mask_nge_us
+ // CHECK: fcmp ult <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps_mask(a, b, _CMP_NGE_US);
+}
+
+__mmask8 test_mm256_cmp_ps_mask_ngt_us(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_mask_ngt_us
+ // CHECK: fcmp ule <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps_mask(a, b, _CMP_NGT_US);
+}
+
+__mmask8 test_mm256_cmp_ps_mask_false_oq(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_mask_false_oq
+ // CHECK: fcmp false <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps_mask(a, b, _CMP_FALSE_OQ);
+}
+
+__mmask8 test_mm256_cmp_ps_mask_neq_oq(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_mask_neq_oq
+ // CHECK: fcmp one <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps_mask(a, b, _CMP_NEQ_OQ);
+}
+
+__mmask8 test_mm256_cmp_ps_mask_ge_os(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_mask_ge_os
+ // CHECK: fcmp oge <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps_mask(a, b, _CMP_GE_OS);
+}
+
+__mmask8 test_mm256_cmp_ps_mask_gt_os(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_mask_gt_os
+ // CHECK: fcmp ogt <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps_mask(a, b, _CMP_GT_OS);
+}
+
+__mmask8 test_mm256_cmp_ps_mask_true_uq(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_mask_true_uq
+ // CHECK: fcmp true <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps_mask(a, b, _CMP_TRUE_UQ);
+}
+
+__mmask8 test_mm256_cmp_ps_mask_eq_os(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_mask_eq_os
+ // CHECK: fcmp oeq <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps_mask(a, b, _CMP_EQ_OS);
+}
+
+__mmask8 test_mm256_cmp_ps_mask_lt_oq(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_mask_lt_oq
+ // CHECK: fcmp olt <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps_mask(a, b, _CMP_LT_OQ);
+}
+
+__mmask8 test_mm256_cmp_ps_mask_le_oq(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_mask_le_oq
+ // CHECK: fcmp ole <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps_mask(a, b, _CMP_LE_OQ);
+}
+
+__mmask8 test_mm256_cmp_ps_mask_unord_s(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_mask_unord_s
+ // CHECK: fcmp uno <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps_mask(a, b, _CMP_UNORD_S);
+}
+
+__mmask8 test_mm256_cmp_ps_mask_neq_us(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_mask_neq_us
+ // CHECK: fcmp une <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps_mask(a, b, _CMP_NEQ_US);
+}
+
+__mmask8 test_mm256_cmp_ps_mask_nlt_uq(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_mask_nlt_uq
+ // CHECK: fcmp uge <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps_mask(a, b, _CMP_NLT_UQ);
+}
+
+__mmask8 test_mm256_cmp_ps_mask_nle_uq(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_mask_nle_uq
+ // CHECK: fcmp ugt <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps_mask(a, b, _CMP_NLE_UQ);
+}
+
+__mmask8 test_mm256_cmp_ps_mask_ord_s(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_mask_ord_s
+ // CHECK: fcmp ord <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps_mask(a, b, _CMP_ORD_S);
+}
+
+__mmask8 test_mm256_cmp_ps_mask_eq_us(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_mask_eq_us
+ // CHECK: fcmp ueq <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps_mask(a, b, _CMP_EQ_US);
+}
+
+__mmask8 test_mm256_cmp_ps_mask_nge_uq(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_mask_nge_uq
+ // CHECK: fcmp ult <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps_mask(a, b, _CMP_NGE_UQ);
+}
+
+__mmask8 test_mm256_cmp_ps_mask_ngt_uq(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_mask_ngt_uq
+ // CHECK: fcmp ule <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps_mask(a, b, _CMP_NGT_UQ);
+}
+
+__mmask8 test_mm256_cmp_ps_mask_false_os(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_mask_false_os
+ // CHECK: fcmp false <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps_mask(a, b, _CMP_FALSE_OS);
+}
+
+__mmask8 test_mm256_cmp_ps_mask_neq_os(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_mask_neq_os
+ // CHECK: fcmp one <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps_mask(a, b, _CMP_NEQ_OS);
+}
+
+__mmask8 test_mm256_cmp_ps_mask_ge_oq(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_mask_ge_oq
+ // CHECK: fcmp oge <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps_mask(a, b, _CMP_GE_OQ);
+}
+
+__mmask8 test_mm256_cmp_ps_mask_gt_oq(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_mask_gt_oq
+ // CHECK: fcmp ogt <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps_mask(a, b, _CMP_GT_OQ);
+}
+
+__mmask8 test_mm256_cmp_ps_mask_true_us(__m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_cmp_ps_mask_true_us
+ // CHECK: fcmp true <8 x float> %{{.*}}, %{{.*}}
+ return _mm256_cmp_ps_mask(a, b, _CMP_TRUE_US);
+}
+
+__mmask8 test_mm256_mask_cmp_ps_mask_eq_oq(__mmask8 m, __m256 a, __m256 b) {
+ // CHECK-LABEL: @test_mm256_mask_cmp_ps_mask_eq_oq
+ // CHECK: [[CMP:%.*]] = fcmp oeq <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_EQ_OQ);
+}
+
+__mmask8 test_mm256_mask_cmp_ps_mask_lt_os(__mmask8 m, __m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_lt_os
+ // CHECK: [[CMP:%.*]] = fcmp olt <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_LT_OS);
+}
+
+__mmask8 test_mm256_mask_cmp_ps_mask_le_os(__mmask8 m, __m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_le_os
+ // CHECK: [[CMP:%.*]] = fcmp ole <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_LE_OS);
+}
+
+__mmask8 test_mm256_mask_cmp_ps_mask_unord_q(__mmask8 m, __m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_unord_q
+ // CHECK: [[CMP:%.*]] = fcmp uno <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_UNORD_Q);
+}
+
+__mmask8 test_mm256_mask_cmp_ps_mask_neq_uq(__mmask8 m, __m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_neq_uq
+ // CHECK: [[CMP:%.*]] = fcmp une <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_NEQ_UQ);
+}
+
+__mmask8 test_mm256_mask_cmp_ps_mask_nlt_us(__mmask8 m, __m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_nlt_us
+ // CHECK: [[CMP:%.*]] = fcmp uge <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_NLT_US);
+}
+
+__mmask8 test_mm256_mask_cmp_ps_mask_nle_us(__mmask8 m, __m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_nle_us
+ // CHECK: [[CMP:%.*]] = fcmp ugt <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_NLE_US);
+}
+
+__mmask8 test_mm256_mask_cmp_ps_mask_ord_q(__mmask8 m, __m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_ord_q
+ // CHECK: [[CMP:%.*]] = fcmp ord <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_ORD_Q);
+}
+
+__mmask8 test_mm256_mask_cmp_ps_mask_eq_uq(__mmask8 m, __m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_eq_uq
+ // CHECK: [[CMP:%.*]] = fcmp ueq <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_EQ_UQ);
+}
+
+__mmask8 test_mm256_mask_cmp_ps_mask_nge_us(__mmask8 m, __m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_nge_us
+ // CHECK: [[CMP:%.*]] = fcmp ult <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_NGE_US);
+}
+
+__mmask8 test_mm256_mask_cmp_ps_mask_ngt_us(__mmask8 m, __m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_ngt_us
+ // CHECK: [[CMP:%.*]] = fcmp ule <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_NGT_US);
+}
+
+__mmask8 test_mm256_mask_cmp_ps_mask_false_oq(__mmask8 m, __m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_false_oq
+ // CHECK: [[CMP:%.*]] = fcmp false <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_FALSE_OQ);
+}
+
+__mmask8 test_mm256_mask_cmp_ps_mask_neq_oq(__mmask8 m, __m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_neq_oq
+ // CHECK: [[CMP:%.*]] = fcmp one <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_NEQ_OQ);
+}
+
+__mmask8 test_mm256_mask_cmp_ps_mask_ge_os(__mmask8 m, __m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_ge_os
+ // CHECK: [[CMP:%.*]] = fcmp oge <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_GE_OS);
+}
+
+__mmask8 test_mm256_mask_cmp_ps_mask_gt_os(__mmask8 m, __m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_gt_os
+ // CHECK: [[CMP:%.*]] = fcmp ogt <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_GT_OS);
+}
+
+__mmask8 test_mm256_mask_cmp_ps_mask_true_uq(__mmask8 m, __m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_true_uq
+ // CHECK: [[CMP:%.*]] = fcmp true <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_TRUE_UQ);
+}
+
+__mmask8 test_mm256_mask_cmp_ps_mask_eq_os(__mmask8 m, __m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_eq_os
+ // CHECK: [[CMP:%.*]] = fcmp oeq <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_EQ_OS);
+}
+
+__mmask8 test_mm256_mask_cmp_ps_mask_lt_oq(__mmask8 m, __m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_lt_oq
+ // CHECK: [[CMP:%.*]] = fcmp olt <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_LT_OQ);
+}
+
+__mmask8 test_mm256_mask_cmp_ps_mask_le_oq(__mmask8 m, __m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_le_oq
+ // CHECK: [[CMP:%.*]] = fcmp ole <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_LE_OQ);
+}
+
+__mmask8 test_mm256_mask_cmp_ps_mask_unord_s(__mmask8 m, __m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_unord_s
+ // CHECK: [[CMP:%.*]] = fcmp uno <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_UNORD_S);
+}
+
+__mmask8 test_mm256_mask_cmp_ps_mask_neq_us(__mmask8 m, __m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_neq_us
+ // CHECK: [[CMP:%.*]] = fcmp une <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_NEQ_US);
+}
+
+__mmask8 test_mm256_mask_cmp_ps_mask_nlt_uq(__mmask8 m, __m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_nlt_uq
+ // CHECK: [[CMP:%.*]] = fcmp uge <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_NLT_UQ);
+}
+
+__mmask8 test_mm256_mask_cmp_ps_mask_nle_uq(__mmask8 m, __m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_nle_uq
+ // CHECK: [[CMP:%.*]] = fcmp ugt <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_NLE_UQ);
+}
+
+__mmask8 test_mm256_mask_cmp_ps_mask_ord_s(__mmask8 m, __m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_ord_s
+ // CHECK: [[CMP:%.*]] = fcmp ord <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_ORD_S);
+}
+
+__mmask8 test_mm256_mask_cmp_ps_mask_eq_us(__mmask8 m, __m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_eq_us
+ // CHECK: [[CMP:%.*]] = fcmp ueq <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_EQ_US);
+}
+
+__mmask8 test_mm256_mask_cmp_ps_mask_nge_uq(__mmask8 m, __m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_nge_uq
+ // CHECK: [[CMP:%.*]] = fcmp ult <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_NGE_UQ);
+}
+
+__mmask8 test_mm256_mask_cmp_ps_mask_ngt_uq(__mmask8 m, __m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_ngt_uq
+ // CHECK: [[CMP:%.*]] = fcmp ule <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_NGT_UQ);
+}
+
+__mmask8 test_mm256_mask_cmp_ps_mask_false_os(__mmask8 m, __m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_false_os
+ // CHECK: [[CMP:%.*]] = fcmp false <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_FALSE_OS);
+}
+
+__mmask8 test_mm256_mask_cmp_ps_mask_neq_os(__mmask8 m, __m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_neq_os
+ // CHECK: [[CMP:%.*]] = fcmp one <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_NEQ_OS);
+}
+
+__mmask8 test_mm256_mask_cmp_ps_mask_ge_oq(__mmask8 m, __m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_ge_oq
+ // CHECK: [[CMP:%.*]] = fcmp oge <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_GE_OQ);
+}
+
+__mmask8 test_mm256_mask_cmp_ps_mask_gt_oq(__mmask8 m, __m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_gt_oq
+ // CHECK: [[CMP:%.*]] = fcmp ogt <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_GT_OQ);
+}
+
+__mmask8 test_mm256_mask_cmp_ps_mask_true_us(__mmask8 m, __m256 a, __m256 b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_true_us
+ // CHECK: [[CMP:%.*]] = fcmp true <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <8 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_TRUE_US);
+}
+
+__mmask8 test_mm256_cmp_pd_mask_eq_oq(__m256d a, __m256d b) {
+ // CHECK-LABEL: @test_mm256_cmp_pd_mask_eq_oq
+ // CHECK: fcmp oeq <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd_mask(a, b, _CMP_EQ_OQ);
+}
+
+__mmask8 test_mm256_cmp_pd_mask_lt_os(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_mask_lt_os
+ // CHECK: fcmp olt <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd_mask(a, b, _CMP_LT_OS);
+}
+
+__mmask8 test_mm256_cmp_pd_mask_le_os(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_mask_le_os
+ // CHECK: fcmp ole <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd_mask(a, b, _CMP_LE_OS);
+}
+
+__mmask8 test_mm256_cmp_pd_mask_unord_q(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_mask_unord_q
+ // CHECK: fcmp uno <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd_mask(a, b, _CMP_UNORD_Q);
+}
+
+__mmask8 test_mm256_cmp_pd_mask_neq_uq(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_mask_neq_uq
+ // CHECK: fcmp une <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd_mask(a, b, _CMP_NEQ_UQ);
+}
+
+__mmask8 test_mm256_cmp_pd_mask_nlt_us(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_mask_nlt_us
+ // CHECK: fcmp uge <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd_mask(a, b, _CMP_NLT_US);
+}
+
+__mmask8 test_mm256_cmp_pd_mask_nle_us(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_mask_nle_us
+ // CHECK: fcmp ugt <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd_mask(a, b, _CMP_NLE_US);
+}
+
+__mmask8 test_mm256_cmp_pd_mask_ord_q(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_mask_ord_q
+ // CHECK: fcmp ord <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd_mask(a, b, _CMP_ORD_Q);
+}
+
+__mmask8 test_mm256_cmp_pd_mask_eq_uq(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_mask_eq_uq
+ // CHECK: fcmp ueq <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd_mask(a, b, _CMP_EQ_UQ);
+}
+
+__mmask8 test_mm256_cmp_pd_mask_nge_us(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_mask_nge_us
+ // CHECK: fcmp ult <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd_mask(a, b, _CMP_NGE_US);
+}
+
+__mmask8 test_mm256_cmp_pd_mask_ngt_us(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_mask_ngt_us
+ // CHECK: fcmp ule <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd_mask(a, b, _CMP_NGT_US);
+}
+
+__mmask8 test_mm256_cmp_pd_mask_false_oq(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_mask_false_oq
+ // CHECK: fcmp false <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd_mask(a, b, _CMP_FALSE_OQ);
+}
+
+__mmask8 test_mm256_cmp_pd_mask_neq_oq(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_mask_neq_oq
+ // CHECK: fcmp one <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd_mask(a, b, _CMP_NEQ_OQ);
+}
+
+__mmask8 test_mm256_cmp_pd_mask_ge_os(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_mask_ge_os
+ // CHECK: fcmp oge <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd_mask(a, b, _CMP_GE_OS);
+}
+
+__mmask8 test_mm256_cmp_pd_mask_gt_os(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_mask_gt_os
+ // CHECK: fcmp ogt <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd_mask(a, b, _CMP_GT_OS);
+}
+
+__mmask8 test_mm256_cmp_pd_mask_true_uq(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_mask_true_uq
+ // CHECK: fcmp true <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd_mask(a, b, _CMP_TRUE_UQ);
+}
+
+__mmask8 test_mm256_cmp_pd_mask_eq_os(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_mask_eq_os
+ // CHECK: fcmp oeq <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd_mask(a, b, _CMP_EQ_OS);
+}
+
+__mmask8 test_mm256_cmp_pd_mask_lt_oq(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_mask_lt_oq
+ // CHECK: fcmp olt <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd_mask(a, b, _CMP_LT_OQ);
+}
+
+__mmask8 test_mm256_cmp_pd_mask_le_oq(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_mask_le_oq
+ // CHECK: fcmp ole <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd_mask(a, b, _CMP_LE_OQ);
+}
+
+__mmask8 test_mm256_cmp_pd_mask_unord_s(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_mask_unord_s
+ // CHECK: fcmp uno <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd_mask(a, b, _CMP_UNORD_S);
+}
+
+__mmask8 test_mm256_cmp_pd_mask_neq_us(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_mask_neq_us
+ // CHECK: fcmp une <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd_mask(a, b, _CMP_NEQ_US);
+}
+
+__mmask8 test_mm256_cmp_pd_mask_nlt_uq(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_mask_nlt_uq
+ // CHECK: fcmp uge <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd_mask(a, b, _CMP_NLT_UQ);
+}
+
+__mmask8 test_mm256_cmp_pd_mask_nle_uq(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_mask_nle_uq
+ // CHECK: fcmp ugt <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd_mask(a, b, _CMP_NLE_UQ);
+}
+
+__mmask8 test_mm256_cmp_pd_mask_ord_s(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_mask_ord_s
+ // CHECK: fcmp ord <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd_mask(a, b, _CMP_ORD_S);
+}
+
+__mmask8 test_mm256_cmp_pd_mask_eq_us(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_mask_eq_us
+ // CHECK: fcmp ueq <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd_mask(a, b, _CMP_EQ_US);
+}
+
+__mmask8 test_mm256_cmp_pd_mask_nge_uq(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_mask_nge_uq
+ // CHECK: fcmp ult <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd_mask(a, b, _CMP_NGE_UQ);
+}
+
+__mmask8 test_mm256_cmp_pd_mask_ngt_uq(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_mask_ngt_uq
+ // CHECK: fcmp ule <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd_mask(a, b, _CMP_NGT_UQ);
+}
+
+__mmask8 test_mm256_cmp_pd_mask_false_os(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_mask_false_os
+ // CHECK: fcmp false <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd_mask(a, b, _CMP_FALSE_OS);
+}
+
+__mmask8 test_mm256_cmp_pd_mask_neq_os(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_mask_neq_os
+ // CHECK: fcmp one <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd_mask(a, b, _CMP_NEQ_OS);
+}
+
+__mmask8 test_mm256_cmp_pd_mask_ge_oq(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_mask_ge_oq
+ // CHECK: fcmp oge <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd_mask(a, b, _CMP_GE_OQ);
+}
+
+__mmask8 test_mm256_cmp_pd_mask_gt_oq(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_mask_gt_oq
+ // CHECK: fcmp ogt <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd_mask(a, b, _CMP_GT_OQ);
+}
+
+__mmask8 test_mm256_cmp_pd_mask_true_us(__m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_cmp_pd_mask_true_us
+ // CHECK: fcmp true <4 x double> %{{.*}}, %{{.*}}
+ return _mm256_cmp_pd_mask(a, b, _CMP_TRUE_US);
+}
+
+__mmask8 test_mm256_mask_cmp_pd_mask_eq_oq(__mmask8 m, __m256d a, __m256d b) {
+ // CHECK-LABEL: @test_mm256_mask_cmp_pd_mask_eq_oq
+ // CHECK: [[CMP:%.*]] = fcmp oeq <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_EQ_OQ);
+}
+
+__mmask8 test_mm256_mask_cmp_pd_mask_lt_os(__mmask8 m, __m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_lt_os
+ // CHECK: [[CMP:%.*]] = fcmp olt <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_LT_OS);
+}
+
+__mmask8 test_mm256_mask_cmp_pd_mask_le_os(__mmask8 m, __m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_le_os
+ // CHECK: [[CMP:%.*]] = fcmp ole <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_LE_OS);
+}
+
+__mmask8 test_mm256_mask_cmp_pd_mask_unord_q(__mmask8 m, __m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_unord_q
+ // CHECK: [[CMP:%.*]] = fcmp uno <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_UNORD_Q);
+}
+
+__mmask8 test_mm256_mask_cmp_pd_mask_neq_uq(__mmask8 m, __m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_neq_uq
+ // CHECK: [[CMP:%.*]] = fcmp une <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_NEQ_UQ);
+}
+
+__mmask8 test_mm256_mask_cmp_pd_mask_nlt_us(__mmask8 m, __m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_nlt_us
+ // CHECK: [[CMP:%.*]] = fcmp uge <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_NLT_US);
+}
+
+__mmask8 test_mm256_mask_cmp_pd_mask_nle_us(__mmask8 m, __m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_nle_us
+ // CHECK: [[CMP:%.*]] = fcmp ugt <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_NLE_US);
+}
+
+__mmask8 test_mm256_mask_cmp_pd_mask_ord_q(__mmask8 m, __m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_ord_q
+ // CHECK: [[CMP:%.*]] = fcmp ord <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_ORD_Q);
+}
+
+__mmask8 test_mm256_mask_cmp_pd_mask_eq_uq(__mmask8 m, __m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_eq_uq
+ // CHECK: [[CMP:%.*]] = fcmp ueq <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_EQ_UQ);
+}
+
+__mmask8 test_mm256_mask_cmp_pd_mask_nge_us(__mmask8 m, __m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_nge_us
+ // CHECK: [[CMP:%.*]] = fcmp ult <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_NGE_US);
+}
+
+__mmask8 test_mm256_mask_cmp_pd_mask_ngt_us(__mmask8 m, __m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_ngt_us
+ // CHECK: [[CMP:%.*]] = fcmp ule <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_NGT_US);
+}
+
+__mmask8 test_mm256_mask_cmp_pd_mask_false_oq(__mmask8 m, __m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_false_oq
+ // CHECK: [[CMP:%.*]] = fcmp false <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_FALSE_OQ);
+}
+
+__mmask8 test_mm256_mask_cmp_pd_mask_neq_oq(__mmask8 m, __m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_neq_oq
+ // CHECK: [[CMP:%.*]] = fcmp one <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_NEQ_OQ);
+}
+
+__mmask8 test_mm256_mask_cmp_pd_mask_ge_os(__mmask8 m, __m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_ge_os
+ // CHECK: [[CMP:%.*]] = fcmp oge <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_GE_OS);
+}
+
+__mmask8 test_mm256_mask_cmp_pd_mask_gt_os(__mmask8 m, __m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_gt_os
+ // CHECK: [[CMP:%.*]] = fcmp ogt <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_GT_OS);
+}
+
+__mmask8 test_mm256_mask_cmp_pd_mask_true_uq(__mmask8 m, __m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_true_uq
+ // CHECK: [[CMP:%.*]] = fcmp true <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_TRUE_UQ);
+}
+
+__mmask8 test_mm256_mask_cmp_pd_mask_eq_os(__mmask8 m, __m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_eq_os
+ // CHECK: [[CMP:%.*]] = fcmp oeq <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_EQ_OS);
+}
+
+__mmask8 test_mm256_mask_cmp_pd_mask_lt_oq(__mmask8 m, __m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_lt_oq
+ // CHECK: [[CMP:%.*]] = fcmp olt <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_LT_OQ);
+}
+
+__mmask8 test_mm256_mask_cmp_pd_mask_le_oq(__mmask8 m, __m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_le_oq
+ // CHECK: [[CMP:%.*]] = fcmp ole <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_LE_OQ);
+}
+
+__mmask8 test_mm256_mask_cmp_pd_mask_unord_s(__mmask8 m, __m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_unord_s
+ // CHECK: [[CMP:%.*]] = fcmp uno <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_UNORD_S);
+}
+
+__mmask8 test_mm256_mask_cmp_pd_mask_neq_us(__mmask8 m, __m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_neq_us
+ // CHECK: [[CMP:%.*]] = fcmp une <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_NEQ_US);
+}
+
+__mmask8 test_mm256_mask_cmp_pd_mask_nlt_uq(__mmask8 m, __m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_nlt_uq
+ // CHECK: [[CMP:%.*]] = fcmp uge <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_NLT_UQ);
+}
+
+__mmask8 test_mm256_mask_cmp_pd_mask_nle_uq(__mmask8 m, __m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_nle_uq
+ // CHECK: [[CMP:%.*]] = fcmp ugt <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_NLE_UQ);
+}
+
+__mmask8 test_mm256_mask_cmp_pd_mask_ord_s(__mmask8 m, __m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_ord_s
+ // CHECK: [[CMP:%.*]] = fcmp ord <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_ORD_S);
+}
+
+__mmask8 test_mm256_mask_cmp_pd_mask_eq_us(__mmask8 m, __m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_eq_us
+ // CHECK: [[CMP:%.*]] = fcmp ueq <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_EQ_US);
+}
+
+__mmask8 test_mm256_mask_cmp_pd_mask_nge_uq(__mmask8 m, __m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_nge_uq
+ // CHECK: [[CMP:%.*]] = fcmp ult <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_NGE_UQ);
+}
+
+__mmask8 test_mm256_mask_cmp_pd_mask_ngt_uq(__mmask8 m, __m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_ngt_uq
+ // CHECK: [[CMP:%.*]] = fcmp ule <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_NGT_UQ);
+}
+
+__mmask8 test_mm256_mask_cmp_pd_mask_false_os(__mmask8 m, __m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_false_os
+ // CHECK: [[CMP:%.*]] = fcmp false <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_FALSE_OS);
+}
+
+__mmask8 test_mm256_mask_cmp_pd_mask_neq_os(__mmask8 m, __m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_neq_os
+ // CHECK: [[CMP:%.*]] = fcmp one <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_NEQ_OS);
+}
+
+__mmask8 test_mm256_mask_cmp_pd_mask_ge_oq(__mmask8 m, __m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_ge_oq
+ // CHECK: [[CMP:%.*]] = fcmp oge <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_GE_OQ);
+}
+
+__mmask8 test_mm256_mask_cmp_pd_mask_gt_oq(__mmask8 m, __m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_gt_oq
+ // CHECK: [[CMP:%.*]] = fcmp ogt <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_GT_OQ);
+}
+
+__mmask8 test_mm256_mask_cmp_pd_mask_true_us(__mmask8 m, __m256d a, __m256d b) {
+ // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_true_us
+ // CHECK: [[CMP:%.*]] = fcmp true <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_TRUE_US);
+}
+
+__mmask8 test_mm_cmp_ps_mask_eq_oq(__m128 a, __m128 b) {
+ // CHECK-LABEL: @test_mm_cmp_ps_mask_eq_oq
+ // CHECK: fcmp oeq <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps_mask(a, b, _CMP_EQ_OQ);
+}
+
+__mmask8 test_mm_cmp_ps_mask_lt_os(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_mask_lt_os
+ // CHECK: fcmp olt <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps_mask(a, b, _CMP_LT_OS);
+}
+
+__mmask8 test_mm_cmp_ps_mask_le_os(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_mask_le_os
+ // CHECK: fcmp ole <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps_mask(a, b, _CMP_LE_OS);
+}
+
+__mmask8 test_mm_cmp_ps_mask_unord_q(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_mask_unord_q
+ // CHECK: fcmp uno <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps_mask(a, b, _CMP_UNORD_Q);
+}
+
+__mmask8 test_mm_cmp_ps_mask_neq_uq(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_mask_neq_uq
+ // CHECK: fcmp une <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps_mask(a, b, _CMP_NEQ_UQ);
+}
+
+__mmask8 test_mm_cmp_ps_mask_nlt_us(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_mask_nlt_us
+ // CHECK: fcmp uge <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps_mask(a, b, _CMP_NLT_US);
+}
+
+__mmask8 test_mm_cmp_ps_mask_nle_us(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_mask_nle_us
+ // CHECK: fcmp ugt <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps_mask(a, b, _CMP_NLE_US);
+}
+
+__mmask8 test_mm_cmp_ps_mask_ord_q(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_mask_ord_q
+ // CHECK: fcmp ord <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps_mask(a, b, _CMP_ORD_Q);
+}
+
+__mmask8 test_mm_cmp_ps_mask_eq_uq(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_mask_eq_uq
+ // CHECK: fcmp ueq <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps_mask(a, b, _CMP_EQ_UQ);
+}
+
+__mmask8 test_mm_cmp_ps_mask_nge_us(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_mask_nge_us
+ // CHECK: fcmp ult <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps_mask(a, b, _CMP_NGE_US);
+}
+
+__mmask8 test_mm_cmp_ps_mask_ngt_us(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_mask_ngt_us
+ // CHECK: fcmp ule <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps_mask(a, b, _CMP_NGT_US);
+}
+
+__mmask8 test_mm_cmp_ps_mask_false_oq(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_mask_false_oq
+ // CHECK: fcmp false <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps_mask(a, b, _CMP_FALSE_OQ);
+}
+
+__mmask8 test_mm_cmp_ps_mask_neq_oq(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_mask_neq_oq
+ // CHECK: fcmp one <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps_mask(a, b, _CMP_NEQ_OQ);
+}
+
+__mmask8 test_mm_cmp_ps_mask_ge_os(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_mask_ge_os
+ // CHECK: fcmp oge <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps_mask(a, b, _CMP_GE_OS);
+}
+
+__mmask8 test_mm_cmp_ps_mask_gt_os(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_mask_gt_os
+ // CHECK: fcmp ogt <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps_mask(a, b, _CMP_GT_OS);
+}
+
+__mmask8 test_mm_cmp_ps_mask_true_uq(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_mask_true_uq
+ // CHECK: fcmp true <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps_mask(a, b, _CMP_TRUE_UQ);
+}
+
+__mmask8 test_mm_cmp_ps_mask_eq_os(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_mask_eq_os
+ // CHECK: fcmp oeq <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps_mask(a, b, _CMP_EQ_OS);
+}
+
+__mmask8 test_mm_cmp_ps_mask_lt_oq(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_mask_lt_oq
+ // CHECK: fcmp olt <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps_mask(a, b, _CMP_LT_OQ);
+}
+
+__mmask8 test_mm_cmp_ps_mask_le_oq(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_mask_le_oq
+ // CHECK: fcmp ole <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps_mask(a, b, _CMP_LE_OQ);
+}
+
+__mmask8 test_mm_cmp_ps_mask_unord_s(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_mask_unord_s
+ // CHECK: fcmp uno <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps_mask(a, b, _CMP_UNORD_S);
+}
+
+__mmask8 test_mm_cmp_ps_mask_neq_us(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_mask_neq_us
+ // CHECK: fcmp une <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps_mask(a, b, _CMP_NEQ_US);
+}
+
+__mmask8 test_mm_cmp_ps_mask_nlt_uq(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_mask_nlt_uq
+ // CHECK: fcmp uge <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps_mask(a, b, _CMP_NLT_UQ);
+}
+
+__mmask8 test_mm_cmp_ps_mask_nle_uq(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_mask_nle_uq
+ // CHECK: fcmp ugt <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps_mask(a, b, _CMP_NLE_UQ);
+}
+
+__mmask8 test_mm_cmp_ps_mask_ord_s(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_mask_ord_s
+ // CHECK: fcmp ord <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps_mask(a, b, _CMP_ORD_S);
+}
+
+__mmask8 test_mm_cmp_ps_mask_eq_us(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_mask_eq_us
+ // CHECK: fcmp ueq <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps_mask(a, b, _CMP_EQ_US);
+}
+
+__mmask8 test_mm_cmp_ps_mask_nge_uq(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_mask_nge_uq
+ // CHECK: fcmp ult <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps_mask(a, b, _CMP_NGE_UQ);
+}
+
+__mmask8 test_mm_cmp_ps_mask_ngt_uq(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_mask_ngt_uq
+ // CHECK: fcmp ule <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps_mask(a, b, _CMP_NGT_UQ);
+}
+
+__mmask8 test_mm_cmp_ps_mask_false_os(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_mask_false_os
+ // CHECK: fcmp false <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps_mask(a, b, _CMP_FALSE_OS);
+}
+
+__mmask8 test_mm_cmp_ps_mask_neq_os(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_mask_neq_os
+ // CHECK: fcmp one <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps_mask(a, b, _CMP_NEQ_OS);
+}
+
+__mmask8 test_mm_cmp_ps_mask_ge_oq(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_mask_ge_oq
+ // CHECK: fcmp oge <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps_mask(a, b, _CMP_GE_OQ);
+}
+
+__mmask8 test_mm_cmp_ps_mask_gt_oq(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_mask_gt_oq
+ // CHECK: fcmp ogt <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps_mask(a, b, _CMP_GT_OQ);
+}
+
+__mmask8 test_mm_cmp_ps_mask_true_us(__m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_cmp_ps_mask_true_us
+ // CHECK: fcmp true <4 x float> %{{.*}}, %{{.*}}
+ return _mm_cmp_ps_mask(a, b, _CMP_TRUE_US);
+}
+
+__mmask8 test_mm_mask_cmp_ps_mask_eq_oq(__mmask8 m, __m128 a, __m128 b) {
+ // CHECK-LABEL: @test_mm_mask_cmp_ps_mask_eq_oq
+ // CHECK: [[CMP:%.*]] = fcmp oeq <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_ps_mask(m, a, b, _CMP_EQ_OQ);
+}
+
+__mmask8 test_mm_mask_cmp_ps_mask_lt_os(__mmask8 m, __m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_mask_cmp_ps_mask_lt_os
+ // CHECK: [[CMP:%.*]] = fcmp olt <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_ps_mask(m, a, b, _CMP_LT_OS);
+}
+
+__mmask8 test_mm_mask_cmp_ps_mask_le_os(__mmask8 m, __m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_mask_cmp_ps_mask_le_os
+ // CHECK: [[CMP:%.*]] = fcmp ole <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_ps_mask(m, a, b, _CMP_LE_OS);
+}
+
+__mmask8 test_mm_mask_cmp_ps_mask_unord_q(__mmask8 m, __m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_mask_cmp_ps_mask_unord_q
+ // CHECK: [[CMP:%.*]] = fcmp uno <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_ps_mask(m, a, b, _CMP_UNORD_Q);
+}
+
+__mmask8 test_mm_mask_cmp_ps_mask_neq_uq(__mmask8 m, __m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_mask_cmp_ps_mask_neq_uq
+ // CHECK: [[CMP:%.*]] = fcmp une <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_ps_mask(m, a, b, _CMP_NEQ_UQ);
+}
+
+__mmask8 test_mm_mask_cmp_ps_mask_nlt_us(__mmask8 m, __m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_mask_cmp_ps_mask_nlt_us
+ // CHECK: [[CMP:%.*]] = fcmp uge <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_ps_mask(m, a, b, _CMP_NLT_US);
+}
+
+__mmask8 test_mm_mask_cmp_ps_mask_nle_us(__mmask8 m, __m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_mask_cmp_ps_mask_nle_us
+ // CHECK: [[CMP:%.*]] = fcmp ugt <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_ps_mask(m, a, b, _CMP_NLE_US);
+}
+
+__mmask8 test_mm_mask_cmp_ps_mask_ord_q(__mmask8 m, __m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_mask_cmp_ps_mask_ord_q
+ // CHECK: [[CMP:%.*]] = fcmp ord <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_ps_mask(m, a, b, _CMP_ORD_Q);
+}
+
+__mmask8 test_mm_mask_cmp_ps_mask_eq_uq(__mmask8 m, __m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_mask_cmp_ps_mask_eq_uq
+ // CHECK: [[CMP:%.*]] = fcmp ueq <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_ps_mask(m, a, b, _CMP_EQ_UQ);
+}
+
+__mmask8 test_mm_mask_cmp_ps_mask_nge_us(__mmask8 m, __m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_mask_cmp_ps_mask_nge_us
+ // CHECK: [[CMP:%.*]] = fcmp ult <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_ps_mask(m, a, b, _CMP_NGE_US);
+}
+
+__mmask8 test_mm_mask_cmp_ps_mask_ngt_us(__mmask8 m, __m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_mask_cmp_ps_mask_ngt_us
+ // CHECK: [[CMP:%.*]] = fcmp ule <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_ps_mask(m, a, b, _CMP_NGT_US);
+}
+
+__mmask8 test_mm_mask_cmp_ps_mask_false_oq(__mmask8 m, __m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_mask_cmp_ps_mask_false_oq
+ // CHECK: [[CMP:%.*]] = fcmp false <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_ps_mask(m, a, b, _CMP_FALSE_OQ);
+}
+
+__mmask8 test_mm_mask_cmp_ps_mask_neq_oq(__mmask8 m, __m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_mask_cmp_ps_mask_neq_oq
+ // CHECK: [[CMP:%.*]] = fcmp one <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_ps_mask(m, a, b, _CMP_NEQ_OQ);
+}
+
+__mmask8 test_mm_mask_cmp_ps_mask_ge_os(__mmask8 m, __m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_mask_cmp_ps_mask_ge_os
+ // CHECK: [[CMP:%.*]] = fcmp oge <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_ps_mask(m, a, b, _CMP_GE_OS);
+}
+
+__mmask8 test_mm_mask_cmp_ps_mask_gt_os(__mmask8 m, __m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_mask_cmp_ps_mask_gt_os
+ // CHECK: [[CMP:%.*]] = fcmp ogt <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_ps_mask(m, a, b, _CMP_GT_OS);
+}
+
+__mmask8 test_mm_mask_cmp_ps_mask_true_uq(__mmask8 m, __m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_mask_cmp_ps_mask_true_uq
+ // CHECK: [[CMP:%.*]] = fcmp true <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_ps_mask(m, a, b, _CMP_TRUE_UQ);
+}
+
+__mmask8 test_mm_mask_cmp_ps_mask_eq_os(__mmask8 m, __m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_mask_cmp_ps_mask_eq_os
+ // CHECK: [[CMP:%.*]] = fcmp oeq <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_ps_mask(m, a, b, _CMP_EQ_OS);
+}
+
+__mmask8 test_mm_mask_cmp_ps_mask_lt_oq(__mmask8 m, __m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_mask_cmp_ps_mask_lt_oq
+ // CHECK: [[CMP:%.*]] = fcmp olt <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_ps_mask(m, a, b, _CMP_LT_OQ);
+}
+
+__mmask8 test_mm_mask_cmp_ps_mask_le_oq(__mmask8 m, __m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_mask_cmp_ps_mask_le_oq
+ // CHECK: [[CMP:%.*]] = fcmp ole <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_ps_mask(m, a, b, _CMP_LE_OQ);
+}
+
+__mmask8 test_mm_mask_cmp_ps_mask_unord_s(__mmask8 m, __m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_mask_cmp_ps_mask_unord_s
+ // CHECK: [[CMP:%.*]] = fcmp uno <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_ps_mask(m, a, b, _CMP_UNORD_S);
+}
+
+__mmask8 test_mm_mask_cmp_ps_mask_neq_us(__mmask8 m, __m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_mask_cmp_ps_mask_neq_us
+ // CHECK: [[CMP:%.*]] = fcmp une <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_ps_mask(m, a, b, _CMP_NEQ_US);
+}
+
+__mmask8 test_mm_mask_cmp_ps_mask_nlt_uq(__mmask8 m, __m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_mask_cmp_ps_mask_nlt_uq
+ // CHECK: [[CMP:%.*]] = fcmp uge <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_ps_mask(m, a, b, _CMP_NLT_UQ);
+}
+
+__mmask8 test_mm_mask_cmp_ps_mask_nle_uq(__mmask8 m, __m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_mask_cmp_ps_mask_nle_uq
+ // CHECK: [[CMP:%.*]] = fcmp ugt <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_ps_mask(m, a, b, _CMP_NLE_UQ);
+}
+
+__mmask8 test_mm_mask_cmp_ps_mask_ord_s(__mmask8 m, __m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_mask_cmp_ps_mask_ord_s
+ // CHECK: [[CMP:%.*]] = fcmp ord <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_ps_mask(m, a, b, _CMP_ORD_S);
+}
+
+__mmask8 test_mm_mask_cmp_ps_mask_eq_us(__mmask8 m, __m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_mask_cmp_ps_mask_eq_us
+ // CHECK: [[CMP:%.*]] = fcmp ueq <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_ps_mask(m, a, b, _CMP_EQ_US);
+}
+
+__mmask8 test_mm_mask_cmp_ps_mask_nge_uq(__mmask8 m, __m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_mask_cmp_ps_mask_nge_uq
+ // CHECK: [[CMP:%.*]] = fcmp ult <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_ps_mask(m, a, b, _CMP_NGE_UQ);
+}
+
+__mmask8 test_mm_mask_cmp_ps_mask_ngt_uq(__mmask8 m, __m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_mask_cmp_ps_mask_ngt_uq
+ // CHECK: [[CMP:%.*]] = fcmp ule <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_ps_mask(m, a, b, _CMP_NGT_UQ);
+}
+
+__mmask8 test_mm_mask_cmp_ps_mask_false_os(__mmask8 m, __m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_mask_cmp_ps_mask_false_os
+ // CHECK: [[CMP:%.*]] = fcmp false <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_ps_mask(m, a, b, _CMP_FALSE_OS);
+}
+
+__mmask8 test_mm_mask_cmp_ps_mask_neq_os(__mmask8 m, __m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_mask_cmp_ps_mask_neq_os
+ // CHECK: [[CMP:%.*]] = fcmp one <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_ps_mask(m, a, b, _CMP_NEQ_OS);
+}
+
+__mmask8 test_mm_mask_cmp_ps_mask_ge_oq(__mmask8 m, __m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_mask_cmp_ps_mask_ge_oq
+ // CHECK: [[CMP:%.*]] = fcmp oge <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_ps_mask(m, a, b, _CMP_GE_OQ);
+}
+
+__mmask8 test_mm_mask_cmp_ps_mask_gt_oq(__mmask8 m, __m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_mask_cmp_ps_mask_gt_oq
+ // CHECK: [[CMP:%.*]] = fcmp ogt <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_ps_mask(m, a, b, _CMP_GT_OQ);
+}
+
+__mmask8 test_mm_mask_cmp_ps_mask_true_us(__mmask8 m, __m128 a, __m128 b) {
+ // CHECK-LABEL: test_mm_mask_cmp_ps_mask_true_us
+ // CHECK: [[CMP:%.*]] = fcmp true <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: and <4 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_ps_mask(m, a, b, _CMP_TRUE_US);
+}
+
+__mmask8 test_mm_cmp_pd_mask_eq_oq(__m128d a, __m128d b) {
+ // CHECK-LABEL: @test_mm_cmp_pd_mask_eq_oq
+ // CHECK: fcmp oeq <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd_mask(a, b, _CMP_EQ_OQ);
+}
+
+__mmask8 test_mm_cmp_pd_mask_lt_os(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_mask_lt_os
+ // CHECK: fcmp olt <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd_mask(a, b, _CMP_LT_OS);
+}
+
+__mmask8 test_mm_cmp_pd_mask_le_os(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_mask_le_os
+ // CHECK: fcmp ole <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd_mask(a, b, _CMP_LE_OS);
+}
+
+__mmask8 test_mm_cmp_pd_mask_unord_q(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_mask_unord_q
+ // CHECK: fcmp uno <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd_mask(a, b, _CMP_UNORD_Q);
+}
+
+__mmask8 test_mm_cmp_pd_mask_neq_uq(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_mask_neq_uq
+ // CHECK: fcmp une <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd_mask(a, b, _CMP_NEQ_UQ);
+}
+
+__mmask8 test_mm_cmp_pd_mask_nlt_us(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_mask_nlt_us
+ // CHECK: fcmp uge <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd_mask(a, b, _CMP_NLT_US);
+}
+
+__mmask8 test_mm_cmp_pd_mask_nle_us(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_mask_nle_us
+ // CHECK: fcmp ugt <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd_mask(a, b, _CMP_NLE_US);
+}
+
+__mmask8 test_mm_cmp_pd_mask_ord_q(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_mask_ord_q
+ // CHECK: fcmp ord <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd_mask(a, b, _CMP_ORD_Q);
+}
+
+__mmask8 test_mm_cmp_pd_mask_eq_uq(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_mask_eq_uq
+ // CHECK: fcmp ueq <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd_mask(a, b, _CMP_EQ_UQ);
+}
+
+__mmask8 test_mm_cmp_pd_mask_nge_us(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_mask_nge_us
+ // CHECK: fcmp ult <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd_mask(a, b, _CMP_NGE_US);
+}
+
+__mmask8 test_mm_cmp_pd_mask_ngt_us(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_mask_ngt_us
+ // CHECK: fcmp ule <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd_mask(a, b, _CMP_NGT_US);
+}
+
+__mmask8 test_mm_cmp_pd_mask_false_oq(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_mask_false_oq
+ // CHECK: fcmp false <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd_mask(a, b, _CMP_FALSE_OQ);
+}
+
+__mmask8 test_mm_cmp_pd_mask_neq_oq(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_mask_neq_oq
+ // CHECK: fcmp one <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd_mask(a, b, _CMP_NEQ_OQ);
+}
+
+__mmask8 test_mm_cmp_pd_mask_ge_os(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_mask_ge_os
+ // CHECK: fcmp oge <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd_mask(a, b, _CMP_GE_OS);
+}
+
+__mmask8 test_mm_cmp_pd_mask_gt_os(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_mask_gt_os
+ // CHECK: fcmp ogt <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd_mask(a, b, _CMP_GT_OS);
+}
+
+__mmask8 test_mm_cmp_pd_mask_true_uq(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_mask_true_uq
+ // CHECK: fcmp true <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd_mask(a, b, _CMP_TRUE_UQ);
+}
+
+__mmask8 test_mm_cmp_pd_mask_eq_os(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_mask_eq_os
+ // CHECK: fcmp oeq <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd_mask(a, b, _CMP_EQ_OS);
+}
+
+__mmask8 test_mm_cmp_pd_mask_lt_oq(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_mask_lt_oq
+ // CHECK: fcmp olt <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd_mask(a, b, _CMP_LT_OQ);
+}
+
+__mmask8 test_mm_cmp_pd_mask_le_oq(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_mask_le_oq
+ // CHECK: fcmp ole <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd_mask(a, b, _CMP_LE_OQ);
+}
+
+__mmask8 test_mm_cmp_pd_mask_unord_s(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_mask_unord_s
+ // CHECK: fcmp uno <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd_mask(a, b, _CMP_UNORD_S);
+}
+
+__mmask8 test_mm_cmp_pd_mask_neq_us(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_mask_neq_us
+ // CHECK: fcmp une <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd_mask(a, b, _CMP_NEQ_US);
+}
+
+__mmask8 test_mm_cmp_pd_mask_nlt_uq(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_mask_nlt_uq
+ // CHECK: fcmp uge <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd_mask(a, b, _CMP_NLT_UQ);
+}
+
+__mmask8 test_mm_cmp_pd_mask_nle_uq(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_mask_nle_uq
+ // CHECK: fcmp ugt <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd_mask(a, b, _CMP_NLE_UQ);
+}
+
+__mmask8 test_mm_cmp_pd_mask_ord_s(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_mask_ord_s
+ // CHECK: fcmp ord <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd_mask(a, b, _CMP_ORD_S);
+}
+
+__mmask8 test_mm_cmp_pd_mask_eq_us(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_mask_eq_us
+ // CHECK: fcmp ueq <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd_mask(a, b, _CMP_EQ_US);
+}
+
+__mmask8 test_mm_cmp_pd_mask_nge_uq(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_mask_nge_uq
+ // CHECK: fcmp ult <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd_mask(a, b, _CMP_NGE_UQ);
+}
+
+__mmask8 test_mm_cmp_pd_mask_ngt_uq(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_mask_ngt_uq
+ // CHECK: fcmp ule <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd_mask(a, b, _CMP_NGT_UQ);
+}
+
+__mmask8 test_mm_cmp_pd_mask_false_os(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_mask_false_os
+ // CHECK: fcmp false <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd_mask(a, b, _CMP_FALSE_OS);
+}
+
+__mmask8 test_mm_cmp_pd_mask_neq_os(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_mask_neq_os
+ // CHECK: fcmp one <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd_mask(a, b, _CMP_NEQ_OS);
+}
+
+__mmask8 test_mm_cmp_pd_mask_ge_oq(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_mask_ge_oq
+ // CHECK: fcmp oge <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd_mask(a, b, _CMP_GE_OQ);
+}
+
+__mmask8 test_mm_cmp_pd_mask_gt_oq(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_mask_gt_oq
+ // CHECK: fcmp ogt <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd_mask(a, b, _CMP_GT_OQ);
+}
+
+__mmask8 test_mm_cmp_pd_mask_true_us(__m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_cmp_pd_mask_true_us
+ // CHECK: fcmp true <2 x double> %{{.*}}, %{{.*}}
+ return _mm_cmp_pd_mask(a, b, _CMP_TRUE_US);
+}
+
+__mmask8 test_mm_mask_cmp_pd_mask_eq_oq(__mmask8 m, __m128d a, __m128d b) {
+ // CHECK-LABEL: @test_mm_mask_cmp_pd_mask_eq_oq
+ // CHECK: [[CMP:%.*]] = fcmp oeq <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <2 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_pd_mask(m, a, b, _CMP_EQ_OQ);
+}
+
+__mmask8 test_mm_mask_cmp_pd_mask_lt_os(__mmask8 m, __m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_mask_cmp_pd_mask_lt_os
+ // CHECK: [[CMP:%.*]] = fcmp olt <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <2 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_pd_mask(m, a, b, _CMP_LT_OS);
+}
+
+__mmask8 test_mm_mask_cmp_pd_mask_le_os(__mmask8 m, __m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_mask_cmp_pd_mask_le_os
+ // CHECK: [[CMP:%.*]] = fcmp ole <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <2 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_pd_mask(m, a, b, _CMP_LE_OS);
+}
+
+__mmask8 test_mm_mask_cmp_pd_mask_unord_q(__mmask8 m, __m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_mask_cmp_pd_mask_unord_q
+ // CHECK: [[CMP:%.*]] = fcmp uno <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <2 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_pd_mask(m, a, b, _CMP_UNORD_Q);
+}
+
+__mmask8 test_mm_mask_cmp_pd_mask_neq_uq(__mmask8 m, __m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_mask_cmp_pd_mask_neq_uq
+ // CHECK: [[CMP:%.*]] = fcmp une <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <2 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_pd_mask(m, a, b, _CMP_NEQ_UQ);
+}
+
+__mmask8 test_mm_mask_cmp_pd_mask_nlt_us(__mmask8 m, __m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_mask_cmp_pd_mask_nlt_us
+ // CHECK: [[CMP:%.*]] = fcmp uge <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <2 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_pd_mask(m, a, b, _CMP_NLT_US);
+}
+
+__mmask8 test_mm_mask_cmp_pd_mask_nle_us(__mmask8 m, __m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_mask_cmp_pd_mask_nle_us
+ // CHECK: [[CMP:%.*]] = fcmp ugt <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <2 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_pd_mask(m, a, b, _CMP_NLE_US);
+}
+
+__mmask8 test_mm_mask_cmp_pd_mask_ord_q(__mmask8 m, __m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_mask_cmp_pd_mask_ord_q
+ // CHECK: [[CMP:%.*]] = fcmp ord <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <2 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_pd_mask(m, a, b, _CMP_ORD_Q);
+}
+
+__mmask8 test_mm_mask_cmp_pd_mask_eq_uq(__mmask8 m, __m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_mask_cmp_pd_mask_eq_uq
+ // CHECK: [[CMP:%.*]] = fcmp ueq <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <2 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_pd_mask(m, a, b, _CMP_EQ_UQ);
+}
+
+__mmask8 test_mm_mask_cmp_pd_mask_nge_us(__mmask8 m, __m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_mask_cmp_pd_mask_nge_us
+ // CHECK: [[CMP:%.*]] = fcmp ult <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <2 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_pd_mask(m, a, b, _CMP_NGE_US);
+}
+
+__mmask8 test_mm_mask_cmp_pd_mask_ngt_us(__mmask8 m, __m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_mask_cmp_pd_mask_ngt_us
+ // CHECK: [[CMP:%.*]] = fcmp ule <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <2 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_pd_mask(m, a, b, _CMP_NGT_US);
+}
+
+__mmask8 test_mm_mask_cmp_pd_mask_false_oq(__mmask8 m, __m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_mask_cmp_pd_mask_false_oq
+ // CHECK: [[CMP:%.*]] = fcmp false <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <2 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_pd_mask(m, a, b, _CMP_FALSE_OQ);
+}
+
+__mmask8 test_mm_mask_cmp_pd_mask_neq_oq(__mmask8 m, __m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_mask_cmp_pd_mask_neq_oq
+ // CHECK: [[CMP:%.*]] = fcmp one <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <2 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_pd_mask(m, a, b, _CMP_NEQ_OQ);
+}
+
+__mmask8 test_mm_mask_cmp_pd_mask_ge_os(__mmask8 m, __m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_mask_cmp_pd_mask_ge_os
+ // CHECK: [[CMP:%.*]] = fcmp oge <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <2 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_pd_mask(m, a, b, _CMP_GE_OS);
+}
+
+__mmask8 test_mm_mask_cmp_pd_mask_gt_os(__mmask8 m, __m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_mask_cmp_pd_mask_gt_os
+ // CHECK: [[CMP:%.*]] = fcmp ogt <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <2 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_pd_mask(m, a, b, _CMP_GT_OS);
+}
+
+__mmask8 test_mm_mask_cmp_pd_mask_true_uq(__mmask8 m, __m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_mask_cmp_pd_mask_true_uq
+ // CHECK: [[CMP:%.*]] = fcmp true <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <2 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_pd_mask(m, a, b, _CMP_TRUE_UQ);
+}
+
+__mmask8 test_mm_mask_cmp_pd_mask_eq_os(__mmask8 m, __m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_mask_cmp_pd_mask_eq_os
+ // CHECK: [[CMP:%.*]] = fcmp oeq <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <2 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_pd_mask(m, a, b, _CMP_EQ_OS);
+}
+
+__mmask8 test_mm_mask_cmp_pd_mask_lt_oq(__mmask8 m, __m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_mask_cmp_pd_mask_lt_oq
+ // CHECK: [[CMP:%.*]] = fcmp olt <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <2 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_pd_mask(m, a, b, _CMP_LT_OQ);
+}
+
+__mmask8 test_mm_mask_cmp_pd_mask_le_oq(__mmask8 m, __m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_mask_cmp_pd_mask_le_oq
+ // CHECK: [[CMP:%.*]] = fcmp ole <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <2 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_pd_mask(m, a, b, _CMP_LE_OQ);
+}
+
+__mmask8 test_mm_mask_cmp_pd_mask_unord_s(__mmask8 m, __m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_mask_cmp_pd_mask_unord_s
+ // CHECK: [[CMP:%.*]] = fcmp uno <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <2 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_pd_mask(m, a, b, _CMP_UNORD_S);
+}
+
+__mmask8 test_mm_mask_cmp_pd_mask_neq_us(__mmask8 m, __m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_mask_cmp_pd_mask_neq_us
+ // CHECK: [[CMP:%.*]] = fcmp une <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <2 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_pd_mask(m, a, b, _CMP_NEQ_US);
+}
+
+__mmask8 test_mm_mask_cmp_pd_mask_nlt_uq(__mmask8 m, __m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_mask_cmp_pd_mask_nlt_uq
+ // CHECK: [[CMP:%.*]] = fcmp uge <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <2 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_pd_mask(m, a, b, _CMP_NLT_UQ);
+}
+
+__mmask8 test_mm_mask_cmp_pd_mask_nle_uq(__mmask8 m, __m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_mask_cmp_pd_mask_nle_uq
+ // CHECK: [[CMP:%.*]] = fcmp ugt <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <2 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_pd_mask(m, a, b, _CMP_NLE_UQ);
+}
+
+__mmask8 test_mm_mask_cmp_pd_mask_ord_s(__mmask8 m, __m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_mask_cmp_pd_mask_ord_s
+ // CHECK: [[CMP:%.*]] = fcmp ord <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <2 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_pd_mask(m, a, b, _CMP_ORD_S);
+}
+
+__mmask8 test_mm_mask_cmp_pd_mask_eq_us(__mmask8 m, __m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_mask_cmp_pd_mask_eq_us
+ // CHECK: [[CMP:%.*]] = fcmp ueq <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <2 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_pd_mask(m, a, b, _CMP_EQ_US);
+}
+
+__mmask8 test_mm_mask_cmp_pd_mask_nge_uq(__mmask8 m, __m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_mask_cmp_pd_mask_nge_uq
+ // CHECK: [[CMP:%.*]] = fcmp ult <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <2 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_pd_mask(m, a, b, _CMP_NGE_UQ);
+}
+
+__mmask8 test_mm_mask_cmp_pd_mask_ngt_uq(__mmask8 m, __m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_mask_cmp_pd_mask_ngt_uq
+ // CHECK: [[CMP:%.*]] = fcmp ule <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <2 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_pd_mask(m, a, b, _CMP_NGT_UQ);
+}
+
+__mmask8 test_mm_mask_cmp_pd_mask_false_os(__mmask8 m, __m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_mask_cmp_pd_mask_false_os
+ // CHECK: [[CMP:%.*]] = fcmp false <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <2 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_pd_mask(m, a, b, _CMP_FALSE_OS);
+}
+
+__mmask8 test_mm_mask_cmp_pd_mask_neq_os(__mmask8 m, __m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_mask_cmp_pd_mask_neq_os
+ // CHECK: [[CMP:%.*]] = fcmp one <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <2 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_pd_mask(m, a, b, _CMP_NEQ_OS);
+}
+
+__mmask8 test_mm_mask_cmp_pd_mask_ge_oq(__mmask8 m, __m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_mask_cmp_pd_mask_ge_oq
+ // CHECK: [[CMP:%.*]] = fcmp oge <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <2 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_pd_mask(m, a, b, _CMP_GE_OQ);
+}
+
+__mmask8 test_mm_mask_cmp_pd_mask_gt_oq(__mmask8 m, __m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_mask_cmp_pd_mask_gt_oq
+ // CHECK: [[CMP:%.*]] = fcmp ogt <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <2 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_pd_mask(m, a, b, _CMP_GT_OQ);
+}
+
+__mmask8 test_mm_mask_cmp_pd_mask_true_us(__mmask8 m, __m128d a, __m128d b) {
+ // CHECK-LABEL: test_mm_mask_cmp_pd_mask_true_us
+ // CHECK: [[CMP:%.*]] = fcmp true <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: and <2 x i1> [[CMP]], {{.*}}
+ return _mm_mask_cmp_pd_mask(m, a, b, _CMP_TRUE_US);
}
__m128d test_mm_mask_fmadd_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C) {
// CHECK-LABEL: @test_mm_mask_fmadd_pd
- // CHECK: @llvm.x86.avx512.mask.vfmadd.pd.128
+ // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <2 x i32> <i32 0, i32 1>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_mask_fmadd_pd(__A, __U, __B, __C);
}
__m128d test_mm_mask_fmsub_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C) {
// CHECK-LABEL: @test_mm_mask_fmsub_pd
- // CHECK: @llvm.x86.avx512.mask.vfmadd.pd.128
+ // CHECK: fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <2 x i32> <i32 0, i32 1>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_mask_fmsub_pd(__A, __U, __B, __C);
}
__m128d test_mm_mask3_fmadd_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm_mask3_fmadd_pd
- // CHECK: @llvm.x86.avx512.mask3.vfmadd.pd.128
+ // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <2 x i32> <i32 0, i32 1>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_mask3_fmadd_pd(__A, __B, __C, __U);
}
__m128d test_mm_mask3_fnmadd_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm_mask3_fnmadd_pd
- // CHECK: @llvm.x86.avx512.mask3.vfmadd.pd.128
+ // CHECK: fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <2 x i32> <i32 0, i32 1>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_mask3_fnmadd_pd(__A, __B, __C, __U);
}
__m128d test_mm_maskz_fmadd_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) {
// CHECK-LABEL: @test_mm_maskz_fmadd_pd
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.pd.128
+ // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <2 x i32> <i32 0, i32 1>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_maskz_fmadd_pd(__U, __A, __B, __C);
}
__m128d test_mm_maskz_fmsub_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) {
// CHECK-LABEL: @test_mm_maskz_fmsub_pd
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.pd.128
+ // CHECK: fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <2 x i32> <i32 0, i32 1>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_maskz_fmsub_pd(__U, __A, __B, __C);
}
__m128d test_mm_maskz_fnmadd_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) {
// CHECK-LABEL: @test_mm_maskz_fnmadd_pd
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.pd.128
+ // CHECK: fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <2 x i32> <i32 0, i32 1>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_maskz_fnmadd_pd(__U, __A, __B, __C);
}
__m128d test_mm_maskz_fnmsub_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) {
// CHECK-LABEL: @test_mm_maskz_fnmsub_pd
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.pd.128
+ // CHECK: fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <2 x i32> <i32 0, i32 1>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_maskz_fnmsub_pd(__U, __A, __B, __C);
}
__m256d test_mm256_mask_fmadd_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C) {
// CHECK-LABEL: @test_mm256_mask_fmadd_pd
- // CHECK: @llvm.x86.avx512.mask.vfmadd.pd.256
+ // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_mask_fmadd_pd(__A, __U, __B, __C);
}
__m256d test_mm256_mask_fmsub_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C) {
// CHECK-LABEL: @test_mm256_mask_fmsub_pd
- // CHECK: @llvm.x86.avx512.mask.vfmadd.pd.256
+ // CHECK: fsub <4 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_mask_fmsub_pd(__A, __U, __B, __C);
}
__m256d test_mm256_mask3_fmadd_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm256_mask3_fmadd_pd
- // CHECK: @llvm.x86.avx512.mask3.vfmadd.pd.256
+ // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_mask3_fmadd_pd(__A, __B, __C, __U);
}
__m256d test_mm256_mask3_fnmadd_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm256_mask3_fnmadd_pd
- // CHECK: @llvm.x86.avx512.mask3.vfmadd.pd.256
+ // CHECK: fsub <4 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_mask3_fnmadd_pd(__A, __B, __C, __U);
}
__m256d test_mm256_maskz_fmadd_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C) {
// CHECK-LABEL: @test_mm256_maskz_fmadd_pd
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.pd.256
+ // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_maskz_fmadd_pd(__U, __A, __B, __C);
}
__m256d test_mm256_maskz_fmsub_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C) {
// CHECK-LABEL: @test_mm256_maskz_fmsub_pd
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.pd.256
+ // CHECK: fsub <4 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_maskz_fmsub_pd(__U, __A, __B, __C);
}
__m256d test_mm256_maskz_fnmadd_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C) {
// CHECK-LABEL: @test_mm256_maskz_fnmadd_pd
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.pd.256
+ // CHECK: fsub <4 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_maskz_fnmadd_pd(__U, __A, __B, __C);
}
__m256d test_mm256_maskz_fnmsub_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C) {
// CHECK-LABEL: @test_mm256_maskz_fnmsub_pd
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.pd.256
+ // CHECK: fsub <4 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: fsub <4 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_maskz_fnmsub_pd(__U, __A, __B, __C);
}
__m128 test_mm_mask_fmadd_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C) {
// CHECK-LABEL: @test_mm_mask_fmadd_ps
- // CHECK: @llvm.x86.avx512.mask.vfmadd.ps.128
+ // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_mask_fmadd_ps(__A, __U, __B, __C);
}
__m128 test_mm_mask_fmsub_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C) {
// CHECK-LABEL: @test_mm_mask_fmsub_ps
- // CHECK: @llvm.x86.avx512.mask.vfmadd.ps.128
+ // CHECK: fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_mask_fmsub_ps(__A, __U, __B, __C);
}
__m128 test_mm_mask3_fmadd_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm_mask3_fmadd_ps
- // CHECK: @llvm.x86.avx512.mask3.vfmadd.ps.128
+ // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_mask3_fmadd_ps(__A, __B, __C, __U);
}
__m128 test_mm_mask3_fnmadd_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm_mask3_fnmadd_ps
- // CHECK: @llvm.x86.avx512.mask3.vfmadd.ps.128
+ // CHECK: fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_mask3_fnmadd_ps(__A, __B, __C, __U);
}
__m128 test_mm_maskz_fmadd_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) {
// CHECK-LABEL: @test_mm_maskz_fmadd_ps
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.ps.128
+ // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_maskz_fmadd_ps(__U, __A, __B, __C);
}
__m128 test_mm_maskz_fmsub_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) {
// CHECK-LABEL: @test_mm_maskz_fmsub_ps
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.ps.128
+ // CHECK: fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_maskz_fmsub_ps(__U, __A, __B, __C);
}
__m128 test_mm_maskz_fnmadd_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) {
// CHECK-LABEL: @test_mm_maskz_fnmadd_ps
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.ps.128
+ // CHECK: fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_maskz_fnmadd_ps(__U, __A, __B, __C);
}
__m128 test_mm_maskz_fnmsub_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) {
// CHECK-LABEL: @test_mm_maskz_fnmsub_ps
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.ps.128
+ // CHECK: fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_maskz_fnmsub_ps(__U, __A, __B, __C);
}
__m256 test_mm256_mask_fmadd_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __C) {
// CHECK-LABEL: @test_mm256_mask_fmadd_ps
- // CHECK: @llvm.x86.avx512.mask.vfmadd.ps.256
+ // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_mask_fmadd_ps(__A, __U, __B, __C);
}
__m256 test_mm256_mask_fmsub_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __C) {
// CHECK-LABEL: @test_mm256_mask_fmsub_ps
- // CHECK: @llvm.x86.avx512.mask.vfmadd.ps.256
+ // CHECK: fsub <8 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_mask_fmsub_ps(__A, __U, __B, __C);
}
__m256 test_mm256_mask3_fmadd_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm256_mask3_fmadd_ps
- // CHECK: @llvm.x86.avx512.mask3.vfmadd.ps.256
+ // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_mask3_fmadd_ps(__A, __B, __C, __U);
}
__m256 test_mm256_mask3_fnmadd_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm256_mask3_fnmadd_ps
- // CHECK: @llvm.x86.avx512.mask3.vfmadd.ps.256
+ // CHECK: fsub <8 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_mask3_fnmadd_ps(__A, __B, __C, __U);
}
__m256 test_mm256_maskz_fmadd_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C) {
// CHECK-LABEL: @test_mm256_maskz_fmadd_ps
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.ps.256
+ // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_maskz_fmadd_ps(__U, __A, __B, __C);
}
__m256 test_mm256_maskz_fmsub_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C) {
// CHECK-LABEL: @test_mm256_maskz_fmsub_ps
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.ps.256
+ // CHECK: fsub <8 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_maskz_fmsub_ps(__U, __A, __B, __C);
}
__m256 test_mm256_maskz_fnmadd_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C) {
// CHECK-LABEL: @test_mm256_maskz_fnmadd_ps
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.ps.256
+ // CHECK: fsub <8 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_maskz_fnmadd_ps(__U, __A, __B, __C);
}
__m256 test_mm256_maskz_fnmsub_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C) {
// CHECK-LABEL: @test_mm256_maskz_fnmsub_ps
- // CHECK: @llvm.x86.avx512.maskz.vfmadd.ps.256
+ // CHECK: fsub <8 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: fsub <8 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_maskz_fnmsub_ps(__U, __A, __B, __C);
}
__m128d test_mm_mask_fmaddsub_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C) {
// CHECK-LABEL: @test_mm_mask_fmaddsub_pd
- // CHECK: @llvm.x86.avx512.mask.vfmaddsub.pd.128
+ // CHECK: [[ADD:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.+}}
+ // CHECK: [[SUB:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]]
+ // CHECK: shufflevector <2 x double> [[SUB]], <2 x double> [[ADD]], <2 x i32> <i32 0, i32 3>
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <2 x i32> <i32 0, i32 1>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_mask_fmaddsub_pd(__A, __U, __B, __C);
}
__m128d test_mm_mask_fmsubadd_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C) {
// CHECK-LABEL: @test_mm_mask_fmsubadd_pd
- // CHECK: @llvm.x86.avx512.mask.vfmaddsub.pd.128
+ // CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.+}}
+ // CHECK: [[SUB:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]]
+ // CHECK: [[ADD:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK: shufflevector <2 x double> [[ADD]], <2 x double> [[SUB]], <2 x i32> <i32 0, i32 3>
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <2 x i32> <i32 0, i32 1>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_mask_fmsubadd_pd(__A, __U, __B, __C);
}
__m128d test_mm_mask3_fmaddsub_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm_mask3_fmaddsub_pd
- // CHECK: @llvm.x86.avx512.mask3.vfmaddsub.pd.128
+ // CHECK: [[ADD:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.+}}
+ // CHECK: [[SUB:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]]
+ // CHECK: shufflevector <2 x double> [[SUB]], <2 x double> [[ADD]], <2 x i32> <i32 0, i32 3>
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <2 x i32> <i32 0, i32 1>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_mask3_fmaddsub_pd(__A, __B, __C, __U);
}
__m128d test_mm_maskz_fmaddsub_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) {
// CHECK-LABEL: @test_mm_maskz_fmaddsub_pd
- // CHECK: @llvm.x86.avx512.maskz.vfmaddsub.pd.128
+ // CHECK: [[ADD:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.+}}
+ // CHECK: [[SUB:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]]
+ // CHECK: shufflevector <2 x double> [[SUB]], <2 x double> [[ADD]], <2 x i32> <i32 0, i32 3>
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <2 x i32> <i32 0, i32 1>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_maskz_fmaddsub_pd(__U, __A, __B, __C);
}
__m128d test_mm_maskz_fmsubadd_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) {
// CHECK-LABEL: @test_mm_maskz_fmsubadd_pd
- // CHECK: @llvm.x86.avx512.maskz.vfmaddsub.pd.128
+ // CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.+}}
+ // CHECK: [[SUB:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]]
+ // CHECK: [[ADD:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK: shufflevector <2 x double> [[ADD]], <2 x double> [[SUB]], <2 x i32> <i32 0, i32 3>
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <2 x i32> <i32 0, i32 1>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_maskz_fmsubadd_pd(__U, __A, __B, __C);
}
__m256d test_mm256_mask_fmaddsub_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C) {
// CHECK-LABEL: @test_mm256_mask_fmaddsub_pd
- // CHECK: @llvm.x86.avx512.mask.vfmaddsub.pd.256
+ // CHECK: [[ADD:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
+ // CHECK: [[NEG:%.+]] = fsub <4 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.+}}
+ // CHECK: [[SUB:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
+ // CHECK: shufflevector <4 x double> [[SUB]], <4 x double> [[ADD]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_mask_fmaddsub_pd(__A, __U, __B, __C);
}
__m256d test_mm256_mask_fmsubadd_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C) {
// CHECK-LABEL: @test_mm256_mask_fmsubadd_pd
- // CHECK: @llvm.x86.avx512.mask.vfmaddsub.pd.256
+ // CHECK: [[NEG:%.+]] = fsub <4 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.+}}
+ // CHECK: [[SUB:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> [[NEG]]
+ // CHECK: [[ADD:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
+ // CHECK: shufflevector <4 x double> [[ADD]], <4 x double> [[SUB]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_mask_fmsubadd_pd(__A, __U, __B, __C);
}
__m256d test_mm256_mask3_fmaddsub_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm256_mask3_fmaddsub_pd
- // CHECK: @llvm.x86.avx512.mask3.vfmaddsub.pd.256
+ // CHECK: [[ADD:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
+ // CHECK: [[NEG:%.+]] = fsub <4 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.+}}
+ // CHECK: [[SUB:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
+ // CHECK: shufflevector <4 x double> [[SUB]], <4 x double> [[ADD]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_mask3_fmaddsub_pd(__A, __B, __C, __U);
}
__m256d test_mm256_maskz_fmaddsub_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C) {
// CHECK-LABEL: @test_mm256_maskz_fmaddsub_pd
- // CHECK: @llvm.x86.avx512.maskz.vfmaddsub.pd.256
+ // CHECK: [[ADD:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
+ // CHECK: [[NEG:%.+]] = fsub <4 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.+}}
+ // CHECK: [[SUB:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
+ // CHECK: shufflevector <4 x double> [[SUB]], <4 x double> [[ADD]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_maskz_fmaddsub_pd(__U, __A, __B, __C);
}
__m256d test_mm256_maskz_fmsubadd_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C) {
// CHECK-LABEL: @test_mm256_maskz_fmsubadd_pd
- // CHECK: @llvm.x86.avx512.maskz.vfmaddsub.pd.256
+ // CHECK: [[NEG:%.+]] = fsub <4 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.+}}
+ // CHECK: [[SUB:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> [[NEG]]
+ // CHECK: [[ADD:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
+ // CHECK: shufflevector <4 x double> [[ADD]], <4 x double> [[SUB]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_maskz_fmsubadd_pd(__U, __A, __B, __C);
}
__m128 test_mm_mask_fmaddsub_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C) {
// CHECK-LABEL: @test_mm_mask_fmaddsub_ps
- // CHECK: @llvm.x86.avx512.mask.vfmaddsub.ps.128
+ // CHECK: [[ADD:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.+}}
+ // CHECK: [[SUB:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]]
+ // CHECK: shufflevector <4 x float> [[SUB]], <4 x float> [[ADD]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_mask_fmaddsub_ps(__A, __U, __B, __C);
}
__m128 test_mm_mask_fmsubadd_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C) {
// CHECK-LABEL: @test_mm_mask_fmsubadd_ps
- // CHECK: @llvm.x86.avx512.mask.vfmaddsub.ps.128
+ // CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.+}}
+ // CHECK: [[SUB:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]]
+ // CHECK: [[ADD:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK: shufflevector <4 x float> [[ADD]], <4 x float> [[SUB]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_mask_fmsubadd_ps(__A, __U, __B, __C);
}
__m128 test_mm_mask3_fmaddsub_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm_mask3_fmaddsub_ps
- // CHECK: @llvm.x86.avx512.mask3.vfmaddsub.ps.128
+ // CHECK: [[ADD:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.+}}
+ // CHECK: [[SUB:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]]
+ // CHECK: shufflevector <4 x float> [[SUB]], <4 x float> [[ADD]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_mask3_fmaddsub_ps(__A, __B, __C, __U);
}
__m128 test_mm_maskz_fmaddsub_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) {
// CHECK-LABEL: @test_mm_maskz_fmaddsub_ps
- // CHECK: @llvm.x86.avx512.maskz.vfmaddsub.ps.128
+ // CHECK: [[ADD:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.+}}
+ // CHECK: [[SUB:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]]
+ // CHECK: shufflevector <4 x float> [[SUB]], <4 x float> [[ADD]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_maskz_fmaddsub_ps(__U, __A, __B, __C);
}
__m128 test_mm_maskz_fmsubadd_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) {
// CHECK-LABEL: @test_mm_maskz_fmsubadd_ps
- // CHECK: @llvm.x86.avx512.maskz.vfmaddsub.ps.128
+ // CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.+}}
+ // CHECK: [[SUB:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]]
+ // CHECK: [[ADD:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK: shufflevector <4 x float> [[ADD]], <4 x float> [[SUB]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_maskz_fmsubadd_ps(__U, __A, __B, __C);
}
__m256 test_mm256_mask_fmaddsub_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __C) {
// CHECK-LABEL: @test_mm256_mask_fmaddsub_ps
- // CHECK: @llvm.x86.avx512.mask.vfmaddsub.ps.256
+ // CHECK: [[ADD:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}})
+ // CHECK: [[NEG:%.+]] = fsub <8 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[SUB:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]]
+ // CHECK: shufflevector <8 x float> [[SUB]], <8 x float> [[ADD]], <8 x i32> <i32 0, i32 9, i32 2, i32 11, i32 4, i32 13, i32 6, i32 15>
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_mask_fmaddsub_ps(__A, __U, __B, __C);
}
__m256 test_mm256_mask_fmsubadd_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __C) {
// CHECK-LABEL: @test_mm256_mask_fmsubadd_ps
- // CHECK: @llvm.x86.avx512.mask.vfmaddsub.ps.256
+ // CHECK: [[NEG:%.+]] = fsub <8 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[SUB:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]]
+ // CHECK: [[ADD:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}})
+ // CHECK: shufflevector <8 x float> [[ADD]], <8 x float> [[SUB]], <8 x i32> <i32 0, i32 9, i32 2, i32 11, i32 4, i32 13, i32 6, i32 15>
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_mask_fmsubadd_ps(__A, __U, __B, __C);
}
__m256 test_mm256_mask3_fmaddsub_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm256_mask3_fmaddsub_ps
- // CHECK: @llvm.x86.avx512.mask3.vfmaddsub.ps.256
+ // CHECK: [[ADD:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}})
+ // CHECK: [[NEG:%.+]] = fsub <8 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[SUB:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]]
+ // CHECK: shufflevector <8 x float> [[SUB]], <8 x float> [[ADD]], <8 x i32> <i32 0, i32 9, i32 2, i32 11, i32 4, i32 13, i32 6, i32 15>
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_mask3_fmaddsub_ps(__A, __B, __C, __U);
}
__m256 test_mm256_maskz_fmaddsub_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C) {
// CHECK-LABEL: @test_mm256_maskz_fmaddsub_ps
- // CHECK: @llvm.x86.avx512.maskz.vfmaddsub.ps.256
+ // CHECK: [[ADD:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}})
+ // CHECK: [[NEG:%.+]] = fsub <8 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[SUB:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]]
+ // CHECK: shufflevector <8 x float> [[SUB]], <8 x float> [[ADD]], <8 x i32> <i32 0, i32 9, i32 2, i32 11, i32 4, i32 13, i32 6, i32 15>
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_maskz_fmaddsub_ps(__U, __A, __B, __C);
}
__m256 test_mm256_maskz_fmsubadd_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C) {
// CHECK-LABEL: @test_mm256_maskz_fmsubadd_ps
- // CHECK: @llvm.x86.avx512.maskz.vfmaddsub.ps.256
+ // CHECK: [[NEG:%.+]] = fsub <8 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[SUB:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]]
+ // CHECK: [[ADD:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}})
+ // CHECK: shufflevector <8 x float> [[ADD]], <8 x float> [[SUB]], <8 x i32> <i32 0, i32 9, i32 2, i32 11, i32 4, i32 13, i32 6, i32 15>
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_maskz_fmsubadd_ps(__U, __A, __B, __C);
}
__m128d test_mm_mask3_fmsub_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm_mask3_fmsub_pd
- // CHECK: @llvm.x86.avx512.mask3.vfmsub.pd.128
+ // CHECK: fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <2 x i32> <i32 0, i32 1>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_mask3_fmsub_pd(__A, __B, __C, __U);
}
__m256d test_mm256_mask3_fmsub_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm256_mask3_fmsub_pd
- // CHECK: @llvm.x86.avx512.mask3.vfmsub.pd.256
+ // CHECK: fsub <4 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_mask3_fmsub_pd(__A, __B, __C, __U);
}
__m128 test_mm_mask3_fmsub_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm_mask3_fmsub_ps
- // CHECK: @llvm.x86.avx512.mask3.vfmsub.ps.128
+ // CHECK: fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_mask3_fmsub_ps(__A, __B, __C, __U);
}
__m256 test_mm256_mask3_fmsub_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm256_mask3_fmsub_ps
- // CHECK: @llvm.x86.avx512.mask3.vfmsub.ps.256
+ // CHECK: fsub <8 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_mask3_fmsub_ps(__A, __B, __C, __U);
}
__m128d test_mm_mask3_fmsubadd_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm_mask3_fmsubadd_pd
- // CHECK: @llvm.x86.avx512.mask3.vfmsubadd.pd.128
+ // CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.+}}
+ // CHECK: [[SUB:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]]
+ // CHECK: [[ADD:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK: shufflevector <2 x double> [[ADD]], <2 x double> [[SUB]], <2 x i32> <i32 0, i32 3>
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <2 x i32> <i32 0, i32 1>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_mask3_fmsubadd_pd(__A, __B, __C, __U);
}
__m256d test_mm256_mask3_fmsubadd_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm256_mask3_fmsubadd_pd
- // CHECK: @llvm.x86.avx512.mask3.vfmsubadd.pd.256
+ // CHECK: [[NEG:%.+]] = fsub <4 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.+}}
+ // CHECK: [[SUB:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> [[NEG]]
+ // CHECK: [[ADD:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
+ // CHECK: shufflevector <4 x double> [[ADD]], <4 x double> [[SUB]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_mask3_fmsubadd_pd(__A, __B, __C, __U);
}
__m128 test_mm_mask3_fmsubadd_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm_mask3_fmsubadd_ps
- // CHECK: @llvm.x86.avx512.mask3.vfmsubadd.ps.128
+ // CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.+}}
+ // CHECK: [[SUB:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]]
+ // CHECK: [[ADD:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK: shufflevector <4 x float> [[ADD]], <4 x float> [[SUB]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_mask3_fmsubadd_ps(__A, __B, __C, __U);
}
__m256 test_mm256_mask3_fmsubadd_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm256_mask3_fmsubadd_ps
- // CHECK: @llvm.x86.avx512.mask3.vfmsubadd.ps.256
+ // CHECK: [[NEG:%.+]] = fsub <8 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[SUB:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]]
+ // CHECK: [[ADD:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}})
+ // CHECK: shufflevector <8 x float> [[ADD]], <8 x float> [[SUB]], <8 x i32> <i32 0, i32 9, i32 2, i32 11, i32 4, i32 13, i32 6, i32 15>
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_mask3_fmsubadd_ps(__A, __B, __C, __U);
}
__m128d test_mm_mask_fnmadd_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C) {
// CHECK-LABEL: @test_mm_mask_fnmadd_pd
- // CHECK: @llvm.x86.avx512.mask.vfnmadd.pd.128
+ // CHECK: fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <2 x i32> <i32 0, i32 1>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_mask_fnmadd_pd(__A, __U, __B, __C);
}
__m256d test_mm256_mask_fnmadd_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C) {
// CHECK-LABEL: @test_mm256_mask_fnmadd_pd
- // CHECK: @llvm.x86.avx512.mask.vfnmadd.pd.256
+ // CHECK: fsub <4 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_mask_fnmadd_pd(__A, __U, __B, __C);
}
__m128 test_mm_mask_fnmadd_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C) {
// CHECK-LABEL: @test_mm_mask_fnmadd_ps
- // CHECK: @llvm.x86.avx512.mask.vfnmadd.ps.128
+ // CHECK: fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_mask_fnmadd_ps(__A, __U, __B, __C);
}
__m256 test_mm256_mask_fnmadd_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __C) {
// CHECK-LABEL: @test_mm256_mask_fnmadd_ps
- // CHECK: @llvm.x86.avx512.mask.vfnmadd.ps.256
+ // CHECK: fsub <8 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_mask_fnmadd_ps(__A, __U, __B, __C);
}
__m128d test_mm_mask_fnmsub_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C) {
// CHECK-LABEL: @test_mm_mask_fnmsub_pd
- // CHECK: @llvm.x86.avx512.mask.vfnmsub.pd.128
+ // CHECK: fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <2 x i32> <i32 0, i32 1>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_mask_fnmsub_pd(__A, __U, __B, __C);
}
__m128d test_mm_mask3_fnmsub_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm_mask3_fnmsub_pd
- // CHECK: @llvm.x86.avx512.mask3.vfnmsub.pd.128
+ // CHECK: fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <2 x i32> <i32 0, i32 1>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_mask3_fnmsub_pd(__A, __B, __C, __U);
}
__m256d test_mm256_mask_fnmsub_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C) {
// CHECK-LABEL: @test_mm256_mask_fnmsub_pd
- // CHECK: @llvm.x86.avx512.mask.vfnmsub.pd.256
+ // CHECK: fsub <4 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: fsub <4 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_mask_fnmsub_pd(__A, __U, __B, __C);
}
__m256d test_mm256_mask3_fnmsub_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm256_mask3_fnmsub_pd
- // CHECK: @llvm.x86.avx512.mask3.vfnmsub.pd.256
+ // CHECK: fsub <4 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: fsub <4 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.*}}
+ // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_mask3_fnmsub_pd(__A, __B, __C, __U);
}
__m128 test_mm_mask_fnmsub_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C) {
// CHECK-LABEL: @test_mm_mask_fnmsub_ps
- // CHECK: @llvm.x86.avx512.mask.vfnmsub.ps.128
+ // CHECK: fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_mask_fnmsub_ps(__A, __U, __B, __C);
}
__m128 test_mm_mask3_fnmsub_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm_mask3_fnmsub_ps
- // CHECK: @llvm.x86.avx512.mask3.vfnmsub.ps.128
+ // CHECK: fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_mask3_fnmsub_ps(__A, __B, __C, __U);
}
__m256 test_mm256_mask_fnmsub_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __C) {
// CHECK-LABEL: @test_mm256_mask_fnmsub_ps
- // CHECK: @llvm.x86.avx512.mask.vfnmsub.ps.256
+ // CHECK: fsub <8 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: fsub <8 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_mask_fnmsub_ps(__A, __U, __B, __C);
}
__m256 test_mm256_mask3_fnmsub_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U) {
// CHECK-LABEL: @test_mm256_mask3_fnmsub_ps
- // CHECK: @llvm.x86.avx512.mask3.vfnmsub.ps.256
+ // CHECK: fsub <8 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: fsub <8 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}})
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_mask3_fnmsub_ps(__A, __B, __C, __U);
}
@@ -1557,7 +3515,7 @@ __m128 test_mm_mask_add_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
// CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_mask_add_ps(__W,__U,__A,__B);
}
-__m128 test_mm_maskz_add_ps(__mmask16 __U, __m128 __A, __m128 __B) {
+__m128 test_mm_maskz_add_ps(__mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_maskz_add_ps
// CHECK: fadd <4 x float> %{{.*}}, %{{.*}}
// CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
@@ -1697,42 +3655,42 @@ __m256i test_mm256_maskz_compress_epi32(__mmask8 __U, __m256i __A) {
}
void test_mm_mask_compressstoreu_pd(void *__P, __mmask8 __U, __m128d __A) {
// CHECK-LABEL: @test_mm_mask_compressstoreu_pd
- // CHECK: @llvm.x86.avx512.mask.compress.store.pd.128
+ // CHECK: @llvm.masked.compressstore.v2f64(<2 x double> %{{.*}}, double* %{{.*}}, <2 x i1> %{{.*}})
return _mm_mask_compressstoreu_pd(__P,__U,__A);
}
void test_mm256_mask_compressstoreu_pd(void *__P, __mmask8 __U, __m256d __A) {
// CHECK-LABEL: @test_mm256_mask_compressstoreu_pd
- // CHECK: @llvm.x86.avx512.mask.compress.store.pd.256
+ // CHECK: @llvm.masked.compressstore.v4f64(<4 x double> %{{.*}}, double* %{{.*}}, <4 x i1> %{{.*}})
return _mm256_mask_compressstoreu_pd(__P,__U,__A);
}
void test_mm_mask_compressstoreu_epi64(void *__P, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_compressstoreu_epi64
- // CHECK: @llvm.x86.avx512.mask.compress.store.q.128
+ // CHECK: @llvm.masked.compressstore.v2i64(<2 x i64> %{{.*}}, i64* %{{.*}}, <2 x i1> %{{.*}})
return _mm_mask_compressstoreu_epi64(__P,__U,__A);
}
void test_mm256_mask_compressstoreu_epi64(void *__P, __mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_compressstoreu_epi64
- // CHECK: @llvm.x86.avx512.mask.compress.store.q.256
+ // CHECK: @llvm.masked.compressstore.v4i64(<4 x i64> %{{.*}}, i64* %{{.*}}, <4 x i1> %{{.*}})
return _mm256_mask_compressstoreu_epi64(__P,__U,__A);
}
void test_mm_mask_compressstoreu_ps(void *__P, __mmask8 __U, __m128 __A) {
// CHECK-LABEL: @test_mm_mask_compressstoreu_ps
- // CHECK: @llvm.x86.avx512.mask.compress.store.ps.128
+ // CHECK: @llvm.masked.compressstore.v4f32(<4 x float> %{{.*}}, float* %{{.*}}, <4 x i1> %{{.*}})
return _mm_mask_compressstoreu_ps(__P,__U,__A);
}
void test_mm256_mask_compressstoreu_ps(void *__P, __mmask8 __U, __m256 __A) {
// CHECK-LABEL: @test_mm256_mask_compressstoreu_ps
- // CHECK: @llvm.x86.avx512.mask.compress.store.ps.256
+ // CHECK: @llvm.masked.compressstore.v8f32(<8 x float> %{{.*}}, float* %{{.*}}, <8 x i1> %{{.*}})
return _mm256_mask_compressstoreu_ps(__P,__U,__A);
}
void test_mm_mask_compressstoreu_epi32(void *__P, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_compressstoreu_epi32
- // CHECK: @llvm.x86.avx512.mask.compress.store.d.128
+ // CHECK: @llvm.masked.compressstore.v4i32(<4 x i32> %{{.*}}, i32* %{{.*}}, <4 x i1> %{{.*}})
return _mm_mask_compressstoreu_epi32(__P,__U,__A);
}
void test_mm256_mask_compressstoreu_epi32(void *__P, __mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_compressstoreu_epi32
- // CHECK: @llvm.x86.avx512.mask.compress.store.d.256
+ // CHECK: @llvm.masked.compressstore.v8i32(<8 x i32> %{{.*}}, i32* %{{.*}}, <8 x i1> %{{.*}})
return _mm256_mask_compressstoreu_epi32(__P,__U,__A);
}
__m128d test_mm_mask_cvtepi32_pd(__m128d __W, __mmask8 __U, __m128i __A) {
@@ -1763,22 +3721,26 @@ __m256d test_mm256_maskz_cvtepi32_pd(__mmask8 __U, __m128i __A) {
}
__m128 test_mm_mask_cvtepi32_ps(__m128 __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_cvtepi32_ps
- // CHECK: @llvm.x86.avx512.mask.cvtdq2ps.128
+ // CHECK: sitofp <4 x i32> %{{.*}} to <4 x float>
+ // CHECK: select <4 x i1> {{.*}}, <4 x float> {{.*}}, <4 x float> {{.*}}
return _mm_mask_cvtepi32_ps(__W,__U,__A);
}
-__m128 test_mm_maskz_cvtepi32_ps(__mmask16 __U, __m128i __A) {
+__m128 test_mm_maskz_cvtepi32_ps(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_cvtepi32_ps
- // CHECK: @llvm.x86.avx512.mask.cvtdq2ps.128
+ // CHECK: sitofp <4 x i32> %{{.*}} to <4 x float>
+ // CHECK: select <4 x i1> {{.*}}, <4 x float> {{.*}}, <4 x float> {{.*}}
return _mm_maskz_cvtepi32_ps(__U,__A);
}
__m256 test_mm256_mask_cvtepi32_ps(__m256 __W, __mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_cvtepi32_ps
- // CHECK: @llvm.x86.avx512.mask.cvtdq2ps.256
+ // CHECK: sitofp <8 x i32> %{{.*}} to <8 x float>
+ // CHECK: select <8 x i1> {{.*}}, <8 x float> {{.*}}, <8 x float> {{.*}}
return _mm256_mask_cvtepi32_ps(__W,__U,__A);
}
-__m256 test_mm256_maskz_cvtepi32_ps(__mmask16 __U, __m256i __A) {
+__m256 test_mm256_maskz_cvtepi32_ps(__mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_cvtepi32_ps
- // CHECK: @llvm.x86.avx512.mask.cvtdq2ps.256
+ // CHECK: sitofp <8 x i32> %{{.*}} to <8 x float>
+ // CHECK: select <8 x i1> {{.*}}, <8 x float> {{.*}}, <8 x float> {{.*}}
return _mm256_maskz_cvtepi32_ps(__U,__A);
}
__m128i test_mm_mask_cvtpd_epi32(__m128i __W, __mmask8 __U, __m128d __A) {
@@ -1793,12 +3755,14 @@ __m128i test_mm_maskz_cvtpd_epi32(__mmask8 __U, __m128d __A) {
}
__m128i test_mm256_mask_cvtpd_epi32(__m128i __W, __mmask8 __U, __m256d __A) {
// CHECK-LABEL: @test_mm256_mask_cvtpd_epi32
- // CHECK: @llvm.x86.avx512.mask.cvtpd2dq.256
+ // CHECK: @llvm.x86.avx.cvt.pd2dq.256
+ // CHECK: select <4 x i1> {{.*}}, <4 x i32> {{.*}}, <4 x i32> {{.*}}
return _mm256_mask_cvtpd_epi32(__W,__U,__A);
}
__m128i test_mm256_maskz_cvtpd_epi32(__mmask8 __U, __m256d __A) {
// CHECK-LABEL: @test_mm256_maskz_cvtpd_epi32
- // CHECK: @llvm.x86.avx512.mask.cvtpd2dq.256
+ // CHECK: @llvm.x86.avx.cvt.pd2dq.256
+ // CHECK: select <4 x i1> {{.*}}, <4 x i32> {{.*}}, <4 x i32> {{.*}}
return _mm256_maskz_cvtpd_epi32(__U,__A);
}
__m128 test_mm_mask_cvtpd_ps(__m128 __W, __mmask8 __U, __m128d __A) {
@@ -1813,12 +3777,14 @@ __m128 test_mm_maskz_cvtpd_ps(__mmask8 __U, __m128d __A) {
}
__m128 test_mm256_mask_cvtpd_ps(__m128 __W, __mmask8 __U, __m256d __A) {
// CHECK-LABEL: @test_mm256_mask_cvtpd_ps
- // CHECK: @llvm.x86.avx512.mask.cvtpd2ps.256
+ // CHECK: @llvm.x86.avx.cvt.pd2.ps.256
+ // CHECK: select <4 x i1> {{.*}}, <4 x float> {{.*}}, <4 x float> {{.*}}
return _mm256_mask_cvtpd_ps(__W,__U,__A);
}
__m128 test_mm256_maskz_cvtpd_ps(__mmask8 __U, __m256d __A) {
// CHECK-LABEL: @test_mm256_maskz_cvtpd_ps
- // CHECK: @llvm.x86.avx512.mask.cvtpd2ps.256
+ // CHECK: @llvm.x86.avx.cvt.pd2.ps.256
+ // CHECK: select <4 x i1> {{.*}}, <4 x float> {{.*}}, <4 x float> {{.*}}
return _mm256_maskz_cvtpd_ps(__U,__A);
}
__m128i test_mm_cvtpd_epu32(__m128d __A) {
@@ -1853,42 +3819,50 @@ __m128i test_mm256_maskz_cvtpd_epu32(__mmask8 __U, __m256d __A) {
}
__m128i test_mm_mask_cvtps_epi32(__m128i __W, __mmask8 __U, __m128 __A) {
// CHECK-LABEL: @test_mm_mask_cvtps_epi32
- // CHECK: @llvm.x86.avx512.mask.cvtps2dq.128
+ // CHECK: @llvm.x86.sse2.cvtps2dq
+ // CHECK: select <4 x i1> {{.*}}, <4 x i32> {{.*}}, <4 x i32> {{.*}}
return _mm_mask_cvtps_epi32(__W,__U,__A);
}
__m128i test_mm_maskz_cvtps_epi32(__mmask8 __U, __m128 __A) {
// CHECK-LABEL: @test_mm_maskz_cvtps_epi32
- // CHECK: @llvm.x86.avx512.mask.cvtps2dq.128
+ // CHECK: @llvm.x86.sse2.cvtps2dq
+ // CHECK: select <4 x i1> {{.*}}, <4 x i32> {{.*}}, <4 x i32> {{.*}}
return _mm_maskz_cvtps_epi32(__U,__A);
}
__m256i test_mm256_mask_cvtps_epi32(__m256i __W, __mmask8 __U, __m256 __A) {
// CHECK-LABEL: @test_mm256_mask_cvtps_epi32
- // CHECK: @llvm.x86.avx512.mask.cvtps2dq.256
+ // CHECK: @llvm.x86.avx.cvt.ps2dq.256
+ // CHECK: select <8 x i1> {{.*}}, <8 x i32> {{.*}}, <8 x i32> {{.*}}
return _mm256_mask_cvtps_epi32(__W,__U,__A);
}
__m256i test_mm256_maskz_cvtps_epi32(__mmask8 __U, __m256 __A) {
// CHECK-LABEL: @test_mm256_maskz_cvtps_epi32
- // CHECK: @llvm.x86.avx512.mask.cvtps2dq.256
+ // CHECK: @llvm.x86.avx.cvt.ps2dq.256
+ // CHECK: select <8 x i1> {{.*}}, <8 x i32> {{.*}}, <8 x i32> {{.*}}
return _mm256_maskz_cvtps_epi32(__U,__A);
}
__m128d test_mm_mask_cvtps_pd(__m128d __W, __mmask8 __U, __m128 __A) {
// CHECK-LABEL: @test_mm_mask_cvtps_pd
- // CHECK: @llvm.x86.avx512.mask.cvtps2pd.128
+ // CHECK: fpext <2 x float> %{{.*}} to <2 x double>
+ // CHECK: select <2 x i1> {{.*}}, <2 x double> {{.*}}, <2 x double> {{.*}}
return _mm_mask_cvtps_pd(__W,__U,__A);
}
__m128d test_mm_maskz_cvtps_pd(__mmask8 __U, __m128 __A) {
// CHECK-LABEL: @test_mm_maskz_cvtps_pd
- // CHECK: @llvm.x86.avx512.mask.cvtps2pd.128
+ // CHECK: fpext <2 x float> %{{.*}} to <2 x double>
+ // CHECK: select <2 x i1> {{.*}}, <2 x double> {{.*}}, <2 x double> {{.*}}
return _mm_maskz_cvtps_pd(__U,__A);
}
__m256d test_mm256_mask_cvtps_pd(__m256d __W, __mmask8 __U, __m128 __A) {
// CHECK-LABEL: @test_mm256_mask_cvtps_pd
- // CHECK: @llvm.x86.avx512.mask.cvtps2pd.256
+ // CHECK: fpext <4 x float> %{{.*}} to <4 x double>
+ // CHECK: select <4 x i1> {{.*}}, <4 x double> {{.*}}, <4 x double> {{.*}}
return _mm256_mask_cvtps_pd(__W,__U,__A);
}
__m256d test_mm256_maskz_cvtps_pd(__mmask8 __U, __m128 __A) {
// CHECK-LABEL: @test_mm256_maskz_cvtps_pd
- // CHECK: @llvm.x86.avx512.mask.cvtps2pd.256
+ // CHECK: fpext <4 x float> %{{.*}} to <4 x double>
+ // CHECK: select <4 x i1> {{.*}}, <4 x double> {{.*}}, <4 x double> {{.*}}
return _mm256_maskz_cvtps_pd(__U,__A);
}
__m128i test_mm_cvtps_epu32(__m128 __A) {
@@ -1933,12 +3907,14 @@ __m128i test_mm_maskz_cvttpd_epi32(__mmask8 __U, __m128d __A) {
}
__m128i test_mm256_mask_cvttpd_epi32(__m128i __W, __mmask8 __U, __m256d __A) {
// CHECK-LABEL: @test_mm256_mask_cvttpd_epi32
- // CHECK: @llvm.x86.avx512.mask.cvttpd2dq.256
+ // CHECK: @llvm.x86.avx.cvtt.pd2dq.256
+ // CHECK: select <4 x i1> {{.*}}, <4 x i32> {{.*}}, <4 x i32> {{.*}}
return _mm256_mask_cvttpd_epi32(__W,__U,__A);
}
__m128i test_mm256_maskz_cvttpd_epi32(__mmask8 __U, __m256d __A) {
// CHECK-LABEL: @test_mm256_maskz_cvttpd_epi32
- // CHECK: @llvm.x86.avx512.mask.cvttpd2dq.256
+ // CHECK: @llvm.x86.avx.cvtt.pd2dq.256
+ // CHECK: select <4 x i1> {{.*}}, <4 x i32> {{.*}}, <4 x i32> {{.*}}
return _mm256_maskz_cvttpd_epi32(__U,__A);
}
__m128i test_mm_cvttpd_epu32(__m128d __A) {
@@ -1973,22 +3949,26 @@ __m128i test_mm256_maskz_cvttpd_epu32(__mmask8 __U, __m256d __A) {
}
__m128i test_mm_mask_cvttps_epi32(__m128i __W, __mmask8 __U, __m128 __A) {
// CHECK-LABEL: @test_mm_mask_cvttps_epi32
- // CHECK: @llvm.x86.avx512.mask.cvttps2dq.128
+ // CHECK: @llvm.x86.sse2.cvttps2dq
+ // CHECK: select <4 x i1> {{.*}}, <4 x i32> {{.*}}, <4 x i32> {{.*}}
return _mm_mask_cvttps_epi32(__W,__U,__A);
}
__m128i test_mm_maskz_cvttps_epi32(__mmask8 __U, __m128 __A) {
// CHECK-LABEL: @test_mm_maskz_cvttps_epi32
- // CHECK: @llvm.x86.avx512.mask.cvttps2dq.128
+ // CHECK: @llvm.x86.sse2.cvttps2dq
+ // CHECK: select <4 x i1> {{.*}}, <4 x i32> {{.*}}, <4 x i32> {{.*}}
return _mm_maskz_cvttps_epi32(__U,__A);
}
__m256i test_mm256_mask_cvttps_epi32(__m256i __W, __mmask8 __U, __m256 __A) {
// CHECK-LABEL: @test_mm256_mask_cvttps_epi32
- // CHECK: @llvm.x86.avx512.mask.cvttps2dq.256
+ // CHECK: @llvm.x86.avx.cvtt.ps2dq.256
+ // CHECK: select <8 x i1> {{.*}}, <8 x i32> {{.*}}, <8 x i32> {{.*}}
return _mm256_mask_cvttps_epi32(__W,__U,__A);
}
__m256i test_mm256_maskz_cvttps_epi32(__mmask8 __U, __m256 __A) {
// CHECK-LABEL: @test_mm256_maskz_cvttps_epi32
- // CHECK: @llvm.x86.avx512.mask.cvttps2dq.256
+ // CHECK: @llvm.x86.avx.cvtt.ps2dq.256
+ // CHECK: select <8 x i1> {{.*}}, <8 x i32> {{.*}}, <8 x i32> {{.*}}
return _mm256_maskz_cvttps_epi32(__U,__A);
}
__m128i test_mm_cvttps_epu32(__m128 __A) {
@@ -2060,32 +4040,36 @@ __m256d test_mm256_maskz_cvtepu32_pd(__mmask8 __U, __m128i __A) {
}
__m128 test_mm_cvtepu32_ps(__m128i __A) {
// CHECK-LABEL: @test_mm_cvtepu32_ps
- // CHECK: @llvm.x86.avx512.mask.cvtudq2ps.128
+ // CHECK: uitofp <4 x i32> %{{.*}} to <4 x float>
return _mm_cvtepu32_ps(__A);
}
__m128 test_mm_mask_cvtepu32_ps(__m128 __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_cvtepu32_ps
- // CHECK: @llvm.x86.avx512.mask.cvtudq2ps.128
+ // CHECK: uitofp <4 x i32> %{{.*}} to <4 x float>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_mask_cvtepu32_ps(__W,__U,__A);
}
__m128 test_mm_maskz_cvtepu32_ps(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_cvtepu32_ps
- // CHECK: @llvm.x86.avx512.mask.cvtudq2ps.128
+ // CHECK: uitofp <4 x i32> %{{.*}} to <4 x float>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_maskz_cvtepu32_ps(__U,__A);
}
__m256 test_mm256_cvtepu32_ps(__m256i __A) {
// CHECK-LABEL: @test_mm256_cvtepu32_ps
- // CHECK: @llvm.x86.avx512.mask.cvtudq2ps.256
+ // CHECK: uitofp <8 x i32> %{{.*}} to <8 x float>
return _mm256_cvtepu32_ps(__A);
}
__m256 test_mm256_mask_cvtepu32_ps(__m256 __W, __mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_cvtepu32_ps
- // CHECK: @llvm.x86.avx512.mask.cvtudq2ps.256
+ // CHECK: uitofp <8 x i32> %{{.*}} to <8 x float>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_mask_cvtepu32_ps(__W,__U,__A);
}
__m256 test_mm256_maskz_cvtepu32_ps(__mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_cvtepu32_ps
- // CHECK: @llvm.x86.avx512.mask.cvtudq2ps.256
+ // CHECK: uitofp <8 x i32> %{{.*}} to <8 x float>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_maskz_cvtepu32_ps(__U,__A);
}
__m128d test_mm_mask_div_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
@@ -2118,7 +4102,7 @@ __m128 test_mm_mask_div_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
// CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_mask_div_ps(__W,__U,__A,__B);
}
-__m128 test_mm_maskz_div_ps(__mmask16 __U, __m128 __A, __m128 __B) {
+__m128 test_mm_maskz_div_ps(__mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_maskz_div_ps
// CHECK: fdiv <4 x float> %{{.*}}, %{{.*}}
// CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
@@ -2178,82 +4162,82 @@ __m256i test_mm256_maskz_expand_epi64(__mmask8 __U, __m256i __A) {
}
__m128d test_mm_mask_expandloadu_pd(__m128d __W, __mmask8 __U, void const *__P) {
// CHECK-LABEL: @test_mm_mask_expandloadu_pd
- // CHECK: @llvm.x86.avx512.mask.expand.load.pd.128
+ // CHECK: @llvm.masked.expandload.v2f64(double* %{{.*}}, <2 x i1> %{{.*}}, <2 x double> %{{.*}})
return _mm_mask_expandloadu_pd(__W,__U,__P);
}
__m128d test_mm_maskz_expandloadu_pd(__mmask8 __U, void const *__P) {
// CHECK-LABEL: @test_mm_maskz_expandloadu_pd
- // CHECK: @llvm.x86.avx512.mask.expand.load.pd.128
+ // CHECK: @llvm.masked.expandload.v2f64(double* %{{.*}}, <2 x i1> %{{.*}}, <2 x double> %{{.*}})
return _mm_maskz_expandloadu_pd(__U,__P);
}
__m256d test_mm256_mask_expandloadu_pd(__m256d __W, __mmask8 __U, void const *__P) {
// CHECK-LABEL: @test_mm256_mask_expandloadu_pd
- // CHECK: @llvm.x86.avx512.mask.expand.load.pd.256
+ // CHECK: @llvm.masked.expandload.v4f64(double* %{{.*}}, <4 x i1> %{{.*}}, <4 x double> %{{.*}})
return _mm256_mask_expandloadu_pd(__W,__U,__P);
}
__m256d test_mm256_maskz_expandloadu_pd(__mmask8 __U, void const *__P) {
// CHECK-LABEL: @test_mm256_maskz_expandloadu_pd
- // CHECK: @llvm.x86.avx512.mask.expand.load.pd.256
+ // CHECK: @llvm.masked.expandload.v4f64(double* %{{.*}}, <4 x i1> %{{.*}}, <4 x double> %{{.*}})
return _mm256_maskz_expandloadu_pd(__U,__P);
}
__m128i test_mm_mask_expandloadu_epi64(__m128i __W, __mmask8 __U, void const *__P) {
// CHECK-LABEL: @test_mm_mask_expandloadu_epi64
- // CHECK: @llvm.x86.avx512.mask.expand.load.q.128
+ // CHECK: @llvm.masked.expandload.v2i64(i64* %{{.*}}, <2 x i1> %{{.*}}, <2 x i64> %{{.*}})
return _mm_mask_expandloadu_epi64(__W,__U,__P);
}
__m128i test_mm_maskz_expandloadu_epi64(__mmask8 __U, void const *__P) {
// CHECK-LABEL: @test_mm_maskz_expandloadu_epi64
- // CHECK: @llvm.x86.avx512.mask.expand.load.q.128
+ // CHECK: @llvm.masked.expandload.v2i64(i64* %{{.*}}, <2 x i1> %{{.*}}, <2 x i64> %{{.*}})
return _mm_maskz_expandloadu_epi64(__U,__P);
}
__m256i test_mm256_mask_expandloadu_epi64(__m256i __W, __mmask8 __U, void const *__P) {
// CHECK-LABEL: @test_mm256_mask_expandloadu_epi64
- // CHECK: @llvm.x86.avx512.mask.expand.load.q.256
+ // CHECK: @llvm.masked.expandload.v4i64(i64* %{{.*}}, <4 x i1> %{{.*}}, <4 x i64> %{{.*}})
return _mm256_mask_expandloadu_epi64(__W,__U,__P);
}
__m256i test_mm256_maskz_expandloadu_epi64(__mmask8 __U, void const *__P) {
// CHECK-LABEL: @test_mm256_maskz_expandloadu_epi64
- // CHECK: @llvm.x86.avx512.mask.expand.load.q.256
+ // CHECK: @llvm.masked.expandload.v4i64(i64* %{{.*}}, <4 x i1> %{{.*}}, <4 x i64> %{{.*}})
return _mm256_maskz_expandloadu_epi64(__U,__P);
}
__m128 test_mm_mask_expandloadu_ps(__m128 __W, __mmask8 __U, void const *__P) {
// CHECK-LABEL: @test_mm_mask_expandloadu_ps
- // CHECK: @llvm.x86.avx512.mask.expand.load.ps.128
+ // CHECK: @llvm.masked.expandload.v4f32(float* %{{.*}}, <4 x i1> %{{.*}}, <4 x float> %{{.*}})
return _mm_mask_expandloadu_ps(__W,__U,__P);
}
__m128 test_mm_maskz_expandloadu_ps(__mmask8 __U, void const *__P) {
// CHECK-LABEL: @test_mm_maskz_expandloadu_ps
- // CHECK: @llvm.x86.avx512.mask.expand.load.ps.128
+ // CHECK: @llvm.masked.expandload.v4f32(float* %{{.*}}, <4 x i1> %{{.*}}, <4 x float> %{{.*}})
return _mm_maskz_expandloadu_ps(__U,__P);
}
__m256 test_mm256_mask_expandloadu_ps(__m256 __W, __mmask8 __U, void const *__P) {
// CHECK-LABEL: @test_mm256_mask_expandloadu_ps
- // CHECK: @llvm.x86.avx512.mask.expand.load.ps.256
+ // CHECK: @llvm.masked.expandload.v8f32(float* %{{.*}}, <8 x i1> %{{.*}}, <8 x float> %{{.*}})
return _mm256_mask_expandloadu_ps(__W,__U,__P);
}
__m256 test_mm256_maskz_expandloadu_ps(__mmask8 __U, void const *__P) {
// CHECK-LABEL: @test_mm256_maskz_expandloadu_ps
- // CHECK: @llvm.x86.avx512.mask.expand.load.ps.256
+ // CHECK: @llvm.masked.expandload.v8f32(float* %{{.*}}, <8 x i1> %{{.*}}, <8 x float> %{{.*}})
return _mm256_maskz_expandloadu_ps(__U,__P);
}
__m128i test_mm_mask_expandloadu_epi32(__m128i __W, __mmask8 __U, void const *__P) {
// CHECK-LABEL: @test_mm_mask_expandloadu_epi32
- // CHECK: @llvm.x86.avx512.mask.expand.load.d.128
+ // CHECK: @llvm.masked.expandload.v4i32(i32* %{{.*}}, <4 x i1> %{{.*}}, <4 x i32> %{{.*}})
return _mm_mask_expandloadu_epi32(__W,__U,__P);
}
__m128i test_mm_maskz_expandloadu_epi32(__mmask8 __U, void const *__P) {
// CHECK-LABEL: @test_mm_maskz_expandloadu_epi32
- // CHECK: @llvm.x86.avx512.mask.expand.load.d.128
+ // CHECK: @llvm.masked.expandload.v4i32(i32* %{{.*}}, <4 x i1> %{{.*}}, <4 x i32> %{{.*}})
return _mm_maskz_expandloadu_epi32(__U,__P);
}
__m256i test_mm256_mask_expandloadu_epi32(__m256i __W, __mmask8 __U, void const *__P) {
// CHECK-LABEL: @test_mm256_mask_expandloadu_epi32
- // CHECK: @llvm.x86.avx512.mask.expand.load.d.256
+ // CHECK: @llvm.masked.expandload.v8i32(i32* %{{.*}}, <8 x i1> %{{.*}}, <8 x i32> %{{.*}})
return _mm256_mask_expandloadu_epi32(__W,__U,__P);
}
__m256i test_mm256_maskz_expandloadu_epi32(__mmask8 __U, void const *__P) {
// CHECK-LABEL: @test_mm256_maskz_expandloadu_epi32
- // CHECK: @llvm.x86.avx512.mask.expand.load.d.256
+ // CHECK: @llvm.masked.expandload.v8i32(i32* %{{.*}}, <8 x i1> %{{.*}}, <8 x i32> %{{.*}})
return _mm256_maskz_expandloadu_epi32(__U,__P);
}
__m128 test_mm_mask_expand_ps(__m128 __W, __mmask8 __U, __m128 __A) {
@@ -3134,49 +5118,49 @@ void test_mm256_mask_i32scatter_epi32(int *__addr, __mmask8 __mask, __m256i __i
}
__m128d test_mm_mask_sqrt_pd(__m128d __W, __mmask8 __U, __m128d __A) {
// CHECK-LABEL: @test_mm_mask_sqrt_pd
- // CHECK: @llvm.x86.sse2.sqrt.pd
+ // CHECK: @llvm.sqrt.v2f64
// CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_mask_sqrt_pd(__W,__U,__A);
}
__m128d test_mm_maskz_sqrt_pd(__mmask8 __U, __m128d __A) {
// CHECK-LABEL: @test_mm_maskz_sqrt_pd
- // CHECK: @llvm.x86.sse2.sqrt.pd
+ // CHECK: @llvm.sqrt.v2f64
// CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_maskz_sqrt_pd(__U,__A);
}
__m256d test_mm256_mask_sqrt_pd(__m256d __W, __mmask8 __U, __m256d __A) {
// CHECK-LABEL: @test_mm256_mask_sqrt_pd
- // CHECK: @llvm.x86.avx.sqrt.pd.256
+ // CHECK: @llvm.sqrt.v4f64
// CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_mask_sqrt_pd(__W,__U,__A);
}
__m256d test_mm256_maskz_sqrt_pd(__mmask8 __U, __m256d __A) {
// CHECK-LABEL: @test_mm256_maskz_sqrt_pd
- // CHECK: @llvm.x86.avx.sqrt.pd.256
+ // CHECK: @llvm.sqrt.v4f64
// CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_maskz_sqrt_pd(__U,__A);
}
__m128 test_mm_mask_sqrt_ps(__m128 __W, __mmask8 __U, __m128 __A) {
// CHECK-LABEL: @test_mm_mask_sqrt_ps
- // CHECK: @llvm.x86.sse.sqrt.ps
+ // CHECK: @llvm.sqrt.v4f32
// CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_mask_sqrt_ps(__W,__U,__A);
}
__m128 test_mm_maskz_sqrt_ps(__mmask8 __U, __m128 __A) {
// CHECK-LABEL: @test_mm_maskz_sqrt_ps
- // CHECK: @llvm.x86.sse.sqrt.ps
+ // CHECK: @llvm.sqrt.v4f32
// CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_maskz_sqrt_ps(__U,__A);
}
__m256 test_mm256_mask_sqrt_ps(__m256 __W, __mmask8 __U, __m256 __A) {
// CHECK-LABEL: @test_mm256_mask_sqrt_ps
- // CHECK: @llvm.x86.avx.sqrt.ps.256
+ // CHECK: @llvm.sqrt.v8f32
// CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_mask_sqrt_ps(__W,__U,__A);
}
__m256 test_mm256_maskz_sqrt_ps(__mmask8 __U, __m256 __A) {
// CHECK-LABEL: @test_mm256_maskz_sqrt_ps
- // CHECK: @llvm.x86.avx.sqrt.ps.256
+ // CHECK: @llvm.sqrt.v8f32
// CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_maskz_sqrt_ps(__U,__A);
}
@@ -3230,162 +5214,186 @@ __m256 test_mm256_maskz_sub_ps(__mmask8 __U, __m256 __A, __m256 __B) {
}
__m128i test_mm_mask2_permutex2var_epi32(__m128i __A, __m128i __I, __mmask8 __U, __m128i __B) {
// CHECK-LABEL: @test_mm_mask2_permutex2var_epi32
- // CHECK: @llvm.x86.avx512.mask.vpermi2var.d.128
+ // CHECK: @llvm.x86.avx512.vpermi2var.d.128
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask2_permutex2var_epi32(__A,__I,__U,__B);
}
__m256i test_mm256_mask2_permutex2var_epi32(__m256i __A, __m256i __I, __mmask8 __U, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask2_permutex2var_epi32
- // CHECK: @llvm.x86.avx512.mask.vpermi2var.d.256
+ // CHECK: @llvm.x86.avx512.vpermi2var.d.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask2_permutex2var_epi32(__A,__I,__U,__B);
}
__m128d test_mm_mask2_permutex2var_pd(__m128d __A, __m128i __I, __mmask8 __U, __m128d __B) {
// CHECK-LABEL: @test_mm_mask2_permutex2var_pd
- // CHECK: @llvm.x86.avx512.mask.vpermi2var.pd.128
+ // CHECK: @llvm.x86.avx512.vpermi2var.pd.128
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_mask2_permutex2var_pd(__A,__I,__U,__B);
}
__m256d test_mm256_mask2_permutex2var_pd(__m256d __A, __m256i __I, __mmask8 __U, __m256d __B) {
// CHECK-LABEL: @test_mm256_mask2_permutex2var_pd
- // CHECK: @llvm.x86.avx512.mask.vpermi2var.pd.256
+ // CHECK: @llvm.x86.avx512.vpermi2var.pd.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_mask2_permutex2var_pd(__A,__I,__U,__B);
}
__m128 test_mm_mask2_permutex2var_ps(__m128 __A, __m128i __I, __mmask8 __U, __m128 __B) {
// CHECK-LABEL: @test_mm_mask2_permutex2var_ps
- // CHECK: @llvm.x86.avx512.mask.vpermi2var.ps.128
+ // CHECK: @llvm.x86.avx512.vpermi2var.ps.128
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_mask2_permutex2var_ps(__A,__I,__U,__B);
}
__m256 test_mm256_mask2_permutex2var_ps(__m256 __A, __m256i __I, __mmask8 __U, __m256 __B) {
// CHECK-LABEL: @test_mm256_mask2_permutex2var_ps
- // CHECK: @llvm.x86.avx512.mask.vpermi2var.ps.256
+ // CHECK: @llvm.x86.avx512.vpermi2var.ps.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_mask2_permutex2var_ps(__A,__I,__U,__B);
}
__m128i test_mm_mask2_permutex2var_epi64(__m128i __A, __m128i __I, __mmask8 __U, __m128i __B) {
// CHECK-LABEL: @test_mm_mask2_permutex2var_epi64
- // CHECK: @llvm.x86.avx512.mask.vpermi2var.q.128
+ // CHECK: @llvm.x86.avx512.vpermi2var.q.128
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask2_permutex2var_epi64(__A,__I,__U,__B);
}
__m256i test_mm256_mask2_permutex2var_epi64(__m256i __A, __m256i __I, __mmask8 __U, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask2_permutex2var_epi64
- // CHECK: @llvm.x86.avx512.mask.vpermi2var.q.256
+ // CHECK: @llvm.x86.avx512.vpermi2var.q.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask2_permutex2var_epi64(__A,__I,__U,__B);
}
__m128i test_mm_permutex2var_epi32(__m128i __A, __m128i __I, __m128i __B) {
// CHECK-LABEL: @test_mm_permutex2var_epi32
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.d.128
+ // CHECK: @llvm.x86.avx512.vpermi2var.d.128
return _mm_permutex2var_epi32(__A,__I,__B);
}
__m128i test_mm_mask_permutex2var_epi32(__m128i __A, __mmask8 __U, __m128i __I, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_permutex2var_epi32
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.d.128
+ // CHECK: @llvm.x86.avx512.vpermi2var.d.128
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_permutex2var_epi32(__A,__U,__I,__B);
}
__m128i test_mm_maskz_permutex2var_epi32(__mmask8 __U, __m128i __A, __m128i __I, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_permutex2var_epi32
- // CHECK: @llvm.x86.avx512.maskz.vpermt2var.d.128
+ // CHECK: @llvm.x86.avx512.vpermi2var.d.128
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_permutex2var_epi32(__U,__A,__I,__B);
}
__m256i test_mm256_permutex2var_epi32(__m256i __A, __m256i __I, __m256i __B) {
// CHECK-LABEL: @test_mm256_permutex2var_epi32
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.d.256
+ // CHECK: @llvm.x86.avx512.vpermi2var.d.256
return _mm256_permutex2var_epi32(__A,__I,__B);
}
__m256i test_mm256_mask_permutex2var_epi32(__m256i __A, __mmask8 __U, __m256i __I, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_permutex2var_epi32
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.d.256
+ // CHECK: @llvm.x86.avx512.vpermi2var.d.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_permutex2var_epi32(__A,__U,__I,__B);
}
__m256i test_mm256_maskz_permutex2var_epi32(__mmask8 __U, __m256i __A, __m256i __I, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_permutex2var_epi32
- // CHECK: @llvm.x86.avx512.maskz.vpermt2var.d.256
+ // CHECK: @llvm.x86.avx512.vpermi2var.d.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_permutex2var_epi32(__U,__A,__I,__B);
}
__m128d test_mm_permutex2var_pd(__m128d __A, __m128i __I, __m128d __B) {
// CHECK-LABEL: @test_mm_permutex2var_pd
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.pd.128
+ // CHECK: @llvm.x86.avx512.vpermi2var.pd.128
return _mm_permutex2var_pd(__A,__I,__B);
}
__m128d test_mm_mask_permutex2var_pd(__m128d __A, __mmask8 __U, __m128i __I, __m128d __B) {
// CHECK-LABEL: @test_mm_mask_permutex2var_pd
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.pd.128
+ // CHECK: @llvm.x86.avx512.vpermi2var.pd.128
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_mask_permutex2var_pd(__A,__U,__I,__B);
}
__m128d test_mm_maskz_permutex2var_pd(__mmask8 __U, __m128d __A, __m128i __I, __m128d __B) {
// CHECK-LABEL: @test_mm_maskz_permutex2var_pd
- // CHECK: @llvm.x86.avx512.maskz.vpermt2var.pd.128
+ // CHECK: @llvm.x86.avx512.vpermi2var.pd.128
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_maskz_permutex2var_pd(__U,__A,__I,__B);
}
__m256d test_mm256_permutex2var_pd(__m256d __A, __m256i __I, __m256d __B) {
// CHECK-LABEL: @test_mm256_permutex2var_pd
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.pd.256
+ // CHECK: @llvm.x86.avx512.vpermi2var.pd.256
return _mm256_permutex2var_pd(__A,__I,__B);
}
__m256d test_mm256_mask_permutex2var_pd(__m256d __A, __mmask8 __U, __m256i __I, __m256d __B) {
// CHECK-LABEL: @test_mm256_mask_permutex2var_pd
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.pd.256
+ // CHECK: @llvm.x86.avx512.vpermi2var.pd.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_mask_permutex2var_pd(__A,__U,__I,__B);
}
__m256d test_mm256_maskz_permutex2var_pd(__mmask8 __U, __m256d __A, __m256i __I, __m256d __B) {
// CHECK-LABEL: @test_mm256_maskz_permutex2var_pd
- // CHECK: @llvm.x86.avx512.maskz.vpermt2var.pd.256
+ // CHECK: @llvm.x86.avx512.vpermi2var.pd.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_maskz_permutex2var_pd(__U,__A,__I,__B);
}
__m128 test_mm_permutex2var_ps(__m128 __A, __m128i __I, __m128 __B) {
// CHECK-LABEL: @test_mm_permutex2var_ps
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.ps.128
+ // CHECK: @llvm.x86.avx512.vpermi2var.ps.128
return _mm_permutex2var_ps(__A,__I,__B);
}
__m128 test_mm_mask_permutex2var_ps(__m128 __A, __mmask8 __U, __m128i __I, __m128 __B) {
// CHECK-LABEL: @test_mm_mask_permutex2var_ps
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.ps.128
+ // CHECK: @llvm.x86.avx512.vpermi2var.ps.128
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_mask_permutex2var_ps(__A,__U,__I,__B);
}
__m128 test_mm_maskz_permutex2var_ps(__mmask8 __U, __m128 __A, __m128i __I, __m128 __B) {
// CHECK-LABEL: @test_mm_maskz_permutex2var_ps
- // CHECK: @llvm.x86.avx512.maskz.vpermt2var.ps.128
+ // CHECK: @llvm.x86.avx512.vpermi2var.ps.128
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_maskz_permutex2var_ps(__U,__A,__I,__B);
}
__m256 test_mm256_permutex2var_ps(__m256 __A, __m256i __I, __m256 __B) {
// CHECK-LABEL: @test_mm256_permutex2var_ps
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.ps.256
+ // CHECK: @llvm.x86.avx512.vpermi2var.ps.256
return _mm256_permutex2var_ps(__A,__I,__B);
}
__m256 test_mm256_mask_permutex2var_ps(__m256 __A, __mmask8 __U, __m256i __I, __m256 __B) {
// CHECK-LABEL: @test_mm256_mask_permutex2var_ps
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.ps.256
+ // CHECK: @llvm.x86.avx512.vpermi2var.ps.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_mask_permutex2var_ps(__A,__U,__I,__B);
}
__m256 test_mm256_maskz_permutex2var_ps(__mmask8 __U, __m256 __A, __m256i __I, __m256 __B) {
// CHECK-LABEL: @test_mm256_maskz_permutex2var_ps
- // CHECK: @llvm.x86.avx512.maskz.vpermt2var.ps.256
+ // CHECK: @llvm.x86.avx512.vpermi2var.ps.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_maskz_permutex2var_ps(__U,__A,__I,__B);
}
__m128i test_mm_permutex2var_epi64(__m128i __A, __m128i __I, __m128i __B) {
// CHECK-LABEL: @test_mm_permutex2var_epi64
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.q.128
+ // CHECK: @llvm.x86.avx512.vpermi2var.q.128
return _mm_permutex2var_epi64(__A,__I,__B);
}
__m128i test_mm_mask_permutex2var_epi64(__m128i __A, __mmask8 __U, __m128i __I, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_permutex2var_epi64
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.q.128
+ // CHECK: @llvm.x86.avx512.vpermi2var.q.128
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_permutex2var_epi64(__A,__U,__I,__B);
}
__m128i test_mm_maskz_permutex2var_epi64(__mmask8 __U, __m128i __A, __m128i __I, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_permutex2var_epi64
- // CHECK: @llvm.x86.avx512.maskz.vpermt2var.q.128
+ // CHECK: @llvm.x86.avx512.vpermi2var.q.128
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_permutex2var_epi64(__U,__A,__I,__B);
}
__m256i test_mm256_permutex2var_epi64(__m256i __A, __m256i __I, __m256i __B) {
// CHECK-LABEL: @test_mm256_permutex2var_epi64
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.q.256
+ // CHECK: @llvm.x86.avx512.vpermi2var.q.256
return _mm256_permutex2var_epi64(__A,__I,__B);
}
__m256i test_mm256_mask_permutex2var_epi64(__m256i __A, __mmask8 __U, __m256i __I, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_permutex2var_epi64
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.q.256
+ // CHECK: @llvm.x86.avx512.vpermi2var.q.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_permutex2var_epi64(__A,__U,__I,__B);
}
__m256i test_mm256_maskz_permutex2var_epi64(__mmask8 __U, __m256i __A, __m256i __I, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_permutex2var_epi64
- // CHECK: @llvm.x86.avx512.maskz.vpermt2var.q.256
+ // CHECK: @llvm.x86.avx512.vpermi2var.q.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_permutex2var_epi64(__U,__A,__I,__B);
}
@@ -3671,290 +5679,322 @@ __m256i test_mm256_maskz_cvtepu16_epi64(__mmask8 __U, __m128i __A) {
__m128i test_mm_rol_epi32(__m128i __A) {
// CHECK-LABEL: @test_mm_rol_epi32
- // CHECK: @llvm.x86.avx512.mask.prol.d.128
+ // CHECK: @llvm.x86.avx512.prol.d.128
return _mm_rol_epi32(__A, 5);
}
__m128i test_mm_mask_rol_epi32(__m128i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_rol_epi32
- // CHECK: @llvm.x86.avx512.mask.prol.d.128
+ // CHECK: @llvm.x86.avx512.prol.d.128
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_rol_epi32(__W, __U, __A, 5);
}
__m128i test_mm_maskz_rol_epi32(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_rol_epi32
- // CHECK: @llvm.x86.avx512.mask.prol.d.128
+ // CHECK: @llvm.x86.avx512.prol.d.128
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_rol_epi32(__U, __A, 5);
}
__m256i test_mm256_rol_epi32(__m256i __A) {
// CHECK-LABEL: @test_mm256_rol_epi32
- // CHECK: @llvm.x86.avx512.mask.prol.d.256
+ // CHECK: @llvm.x86.avx512.prol.d.256
return _mm256_rol_epi32(__A, 5);
}
__m256i test_mm256_mask_rol_epi32(__m256i __W, __mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_rol_epi32
- // CHECK: @llvm.x86.avx512.mask.prol.d.256
+ // CHECK: @llvm.x86.avx512.prol.d.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_rol_epi32(__W, __U, __A, 5);
}
__m256i test_mm256_maskz_rol_epi32(__mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_rol_epi32
- // CHECK: @llvm.x86.avx512.mask.prol.d.256
+ // CHECK: @llvm.x86.avx512.prol.d.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_rol_epi32(__U, __A, 5);
}
__m128i test_mm_rol_epi64(__m128i __A) {
// CHECK-LABEL: @test_mm_rol_epi64
- // CHECK: @llvm.x86.avx512.mask.prol.q.128
+ // CHECK: @llvm.x86.avx512.prol.q.128
return _mm_rol_epi64(__A, 5);
}
__m128i test_mm_mask_rol_epi64(__m128i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_rol_epi64
- // CHECK: @llvm.x86.avx512.mask.prol.q.128
+ // CHECK: @llvm.x86.avx512.prol.q.128
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_rol_epi64(__W, __U, __A, 5);
}
__m128i test_mm_maskz_rol_epi64(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_rol_epi64
- // CHECK: @llvm.x86.avx512.mask.prol.q.128
+ // CHECK: @llvm.x86.avx512.prol.q.128
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_rol_epi64(__U, __A, 5);
}
__m256i test_mm256_rol_epi64(__m256i __A) {
// CHECK-LABEL: @test_mm256_rol_epi64
- // CHECK: @llvm.x86.avx512.mask.prol.q.256
+ // CHECK: @llvm.x86.avx512.prol.q.256
return _mm256_rol_epi64(__A, 5);
}
__m256i test_mm256_mask_rol_epi64(__m256i __W, __mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_rol_epi64
- // CHECK: @llvm.x86.avx512.mask.prol.q.256
+ // CHECK: @llvm.x86.avx512.prol.q.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_rol_epi64(__W, __U, __A, 5);
}
__m256i test_mm256_maskz_rol_epi64(__mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_rol_epi64
- // CHECK: @llvm.x86.avx512.mask.prol.q.256
+ // CHECK: @llvm.x86.avx512.prol.q.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_rol_epi64(__U, __A, 5);
}
__m128i test_mm_rolv_epi32(__m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_rolv_epi32
- // CHECK: @llvm.x86.avx512.mask.prolv.d.128
+ // CHECK: @llvm.x86.avx512.prolv.d.128
return _mm_rolv_epi32(__A, __B);
}
__m128i test_mm_mask_rolv_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_rolv_epi32
- // CHECK: @llvm.x86.avx512.mask.prolv.d.128
+ // CHECK: @llvm.x86.avx512.prolv.d.128
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_rolv_epi32(__W, __U, __A, __B);
}
__m128i test_mm_maskz_rolv_epi32(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_rolv_epi32
- // CHECK: @llvm.x86.avx512.mask.prolv.d.128
+ // CHECK: @llvm.x86.avx512.prolv.d.128
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_rolv_epi32(__U, __A, __B);
}
__m256i test_mm256_rolv_epi32(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_rolv_epi32
- // CHECK: @llvm.x86.avx512.mask.prolv.d.256
+ // CHECK: @llvm.x86.avx512.prolv.d.256
return _mm256_rolv_epi32(__A, __B);
}
__m256i test_mm256_mask_rolv_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_rolv_epi32
- // CHECK: @llvm.x86.avx512.mask.prolv.d.256
+ // CHECK: @llvm.x86.avx512.prolv.d.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_rolv_epi32(__W, __U, __A, __B);
}
__m256i test_mm256_maskz_rolv_epi32(__mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_rolv_epi32
- // CHECK: @llvm.x86.avx512.mask.prolv.d.256
+ // CHECK: @llvm.x86.avx512.prolv.d.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_rolv_epi32(__U, __A, __B);
}
__m128i test_mm_rolv_epi64(__m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_rolv_epi64
- // CHECK: @llvm.x86.avx512.mask.prolv.q.128
+ // CHECK: @llvm.x86.avx512.prolv.q.128
return _mm_rolv_epi64(__A, __B);
}
__m128i test_mm_mask_rolv_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_rolv_epi64
- // CHECK: @llvm.x86.avx512.mask.prolv.q.128
+ // CHECK: @llvm.x86.avx512.prolv.q.128
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_rolv_epi64(__W, __U, __A, __B);
}
__m128i test_mm_maskz_rolv_epi64(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_rolv_epi64
- // CHECK: @llvm.x86.avx512.mask.prolv.q.128
+ // CHECK: @llvm.x86.avx512.prolv.q.128
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_rolv_epi64(__U, __A, __B);
}
__m256i test_mm256_rolv_epi64(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_rolv_epi64
- // CHECK: @llvm.x86.avx512.mask.prolv.q.256
+ // CHECK: @llvm.x86.avx512.prolv.q.256
return _mm256_rolv_epi64(__A, __B);
}
__m256i test_mm256_mask_rolv_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_rolv_epi64
- // CHECK: @llvm.x86.avx512.mask.prolv.q.256
+ // CHECK: @llvm.x86.avx512.prolv.q.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_rolv_epi64(__W, __U, __A, __B);
}
__m256i test_mm256_maskz_rolv_epi64(__mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_rolv_epi64
- // CHECK: @llvm.x86.avx512.mask.prolv.q.256
+ // CHECK: @llvm.x86.avx512.prolv.q.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_rolv_epi64(__U, __A, __B);
}
__m128i test_mm_ror_epi32(__m128i __A) {
// CHECK-LABEL: @test_mm_ror_epi32
- // CHECK: @llvm.x86.avx512.mask.pror.d.128
+ // CHECK: @llvm.x86.avx512.pror.d.128
return _mm_ror_epi32(__A, 5);
}
__m128i test_mm_mask_ror_epi32(__m128i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_ror_epi32
- // CHECK: @llvm.x86.avx512.mask.pror.d.128
+ // CHECK: @llvm.x86.avx512.pror.d.128
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_ror_epi32(__W, __U, __A, 5);
}
__m128i test_mm_maskz_ror_epi32(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_ror_epi32
- // CHECK: @llvm.x86.avx512.mask.pror.d.128
+ // CHECK: @llvm.x86.avx512.pror.d.128
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_ror_epi32(__U, __A, 5);
}
__m256i test_mm256_ror_epi32(__m256i __A) {
// CHECK-LABEL: @test_mm256_ror_epi32
- // CHECK: @llvm.x86.avx512.mask.pror.d.256
+ // CHECK: @llvm.x86.avx512.pror.d.256
return _mm256_ror_epi32(__A, 5);
}
__m256i test_mm256_mask_ror_epi32(__m256i __W, __mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_ror_epi32
- // CHECK: @llvm.x86.avx512.mask.pror.d.256
+ // CHECK: @llvm.x86.avx512.pror.d.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_ror_epi32(__W, __U, __A, 5);
}
__m256i test_mm256_maskz_ror_epi32(__mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_ror_epi32
- // CHECK: @llvm.x86.avx512.mask.pror.d.256
+ // CHECK: @llvm.x86.avx512.pror.d.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_ror_epi32(__U, __A, 5);
}
__m128i test_mm_ror_epi64(__m128i __A) {
// CHECK-LABEL: @test_mm_ror_epi64
- // CHECK: @llvm.x86.avx512.mask.pror.q.128
+ // CHECK: @llvm.x86.avx512.pror.q.128
return _mm_ror_epi64(__A, 5);
}
__m128i test_mm_mask_ror_epi64(__m128i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_ror_epi64
- // CHECK: @llvm.x86.avx512.mask.pror.q.128
+ // CHECK: @llvm.x86.avx512.pror.q.128
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_ror_epi64(__W, __U, __A, 5);
}
__m128i test_mm_maskz_ror_epi64(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_ror_epi64
- // CHECK: @llvm.x86.avx512.mask.pror.q.128
+ // CHECK: @llvm.x86.avx512.pror.q.128
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_ror_epi64(__U, __A, 5);
}
__m256i test_mm256_ror_epi64(__m256i __A) {
// CHECK-LABEL: @test_mm256_ror_epi64
- // CHECK: @llvm.x86.avx512.mask.pror.q.256
+ // CHECK: @llvm.x86.avx512.pror.q.256
return _mm256_ror_epi64(__A, 5);
}
__m256i test_mm256_mask_ror_epi64(__m256i __W, __mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_ror_epi64
- // CHECK: @llvm.x86.avx512.mask.pror.q.256
+ // CHECK: @llvm.x86.avx512.pror.q.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_ror_epi64(__W, __U, __A,5);
}
__m256i test_mm256_maskz_ror_epi64(__mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_ror_epi64
- // CHECK: @llvm.x86.avx512.mask.pror.q.256
+ // CHECK: @llvm.x86.avx512.pror.q.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_ror_epi64(__U, __A, 5);
}
__m128i test_mm_rorv_epi32(__m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_rorv_epi32
- // CHECK: @llvm.x86.avx512.mask.prorv.d.128
+ // CHECK: @llvm.x86.avx512.prorv.d.128
return _mm_rorv_epi32(__A, __B);
}
__m128i test_mm_mask_rorv_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_rorv_epi32
- // CHECK: @llvm.x86.avx512.mask.prorv.d.128
+ // CHECK: @llvm.x86.avx512.prorv.d.128
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_rorv_epi32(__W, __U, __A, __B);
}
__m128i test_mm_maskz_rorv_epi32(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_rorv_epi32
- // CHECK: @llvm.x86.avx512.mask.prorv.d.128
+ // CHECK: @llvm.x86.avx512.prorv.d.128
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_rorv_epi32(__U, __A, __B);
}
__m256i test_mm256_rorv_epi32(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_rorv_epi32
- // CHECK: @llvm.x86.avx512.mask.prorv.d.256
+ // CHECK: @llvm.x86.avx512.prorv.d.256
return _mm256_rorv_epi32(__A, __B);
}
__m256i test_mm256_mask_rorv_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_rorv_epi32
- // CHECK: @llvm.x86.avx512.mask.prorv.d.256
+ // CHECK: @llvm.x86.avx512.prorv.d.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_rorv_epi32(__W, __U, __A, __B);
}
__m256i test_mm256_maskz_rorv_epi32(__mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_rorv_epi32
- // CHECK: @llvm.x86.avx512.mask.prorv.d.256
+ // CHECK: @llvm.x86.avx512.prorv.d.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_rorv_epi32(__U, __A, __B);
}
__m128i test_mm_rorv_epi64(__m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_rorv_epi64
- // CHECK: @llvm.x86.avx512.mask.prorv.q.128
+ // CHECK: @llvm.x86.avx512.prorv.q.128
return _mm_rorv_epi64(__A, __B);
}
__m128i test_mm_mask_rorv_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_rorv_epi64
- // CHECK: @llvm.x86.avx512.mask.prorv.q.128
+ // CHECK: @llvm.x86.avx512.prorv.q.128
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_rorv_epi64(__W, __U, __A, __B);
}
__m128i test_mm_maskz_rorv_epi64(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_rorv_epi64
- // CHECK: @llvm.x86.avx512.mask.prorv.q.128
+ // CHECK: @llvm.x86.avx512.prorv.q.128
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_rorv_epi64(__U, __A, __B);
}
__m256i test_mm256_rorv_epi64(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_rorv_epi64
- // CHECK: @llvm.x86.avx512.mask.prorv.q.256
+ // CHECK: @llvm.x86.avx512.prorv.q.256
return _mm256_rorv_epi64(__A, __B);
}
__m256i test_mm256_mask_rorv_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_rorv_epi64
- // CHECK: @llvm.x86.avx512.mask.prorv.q.256
+ // CHECK: @llvm.x86.avx512.prorv.q.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_rorv_epi64(__W, __U, __A, __B);
}
__m256i test_mm256_maskz_rorv_epi64(__mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_rorv_epi64
- // CHECK: @llvm.x86.avx512.mask.prorv.q.256
+ // CHECK: @llvm.x86.avx512.prorv.q.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_rorv_epi64(__U, __A, __B);
}
@@ -4560,7 +6600,6 @@ __m256i test_mm256_maskz_set1_epi32(__mmask8 __M) {
return _mm256_maskz_set1_epi32(__M, 5);
}
-#ifdef __x86_64__
__m128i test_mm_mask_set1_epi64(__m128i __O, __mmask8 __M, long long __A) {
// CHECK-LABEL: @test_mm_mask_set1_epi64
// CHECK: insertelement <2 x i64> undef, i64 %{{.*}}, i32 0
@@ -4600,7 +6639,6 @@ __m256i test_mm256_maskz_set1_epi64(__mmask8 __M, long long __A) {
// CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_set1_epi64(__M, __A);
}
-#endif
__m128d test_mm_fixupimm_pd(__m128d __A, __m128d __B, __m128i __C) {
// CHECK-LABEL: @test_mm_fixupimm_pd
@@ -5076,56 +7114,56 @@ __m256 test_mm256_maskz_rcp14_ps(__mmask8 __U, __m256 __A) {
__m128d test_mm_mask_permute_pd(__m128d __W, __mmask8 __U, __m128d __X) {
// CHECK-LABEL: @test_mm_mask_permute_pd
- // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> zeroinitializer, <2 x i32> <i32 1, i32 0>
+ // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> undef, <2 x i32> <i32 1, i32 0>
// CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_mask_permute_pd(__W, __U, __X, 1);
}
__m128d test_mm_maskz_permute_pd(__mmask8 __U, __m128d __X) {
// CHECK-LABEL: @test_mm_maskz_permute_pd
- // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> zeroinitializer, <2 x i32> <i32 1, i32 0>
+ // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> undef, <2 x i32> <i32 1, i32 0>
// CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_maskz_permute_pd(__U, __X, 1);
}
__m256d test_mm256_mask_permute_pd(__m256d __W, __mmask8 __U, __m256d __X) {
// CHECK-LABEL: @test_mm256_mask_permute_pd
- // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> zeroinitializer, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
+ // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
// CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_mask_permute_pd(__W, __U, __X, 5);
}
__m256d test_mm256_maskz_permute_pd(__mmask8 __U, __m256d __X) {
// CHECK-LABEL: @test_mm256_maskz_permute_pd
- // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> zeroinitializer, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
+ // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
// CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_maskz_permute_pd(__U, __X, 5);
}
__m128 test_mm_mask_permute_ps(__m128 __W, __mmask8 __U, __m128 __X) {
// CHECK-LABEL: @test_mm_mask_permute_ps
- // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> zeroinitializer, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+ // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> undef, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
// CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_mask_permute_ps(__W, __U, __X, 0x1b);
}
__m128 test_mm_maskz_permute_ps(__mmask8 __U, __m128 __X) {
// CHECK-LABEL: @test_mm_maskz_permute_ps
- // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> zeroinitializer, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+ // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> undef, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
// CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_maskz_permute_ps(__U, __X, 0x1b);
}
__m256 test_mm256_mask_permute_ps(__m256 __W, __mmask8 __U, __m256 __X) {
// CHECK-LABEL: @test_mm256_mask_permute_ps
- // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> zeroinitializer, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
+ // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> undef, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
// CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_mask_permute_ps(__W, __U, __X, 0x1b);
}
__m256 test_mm256_maskz_permute_ps(__mmask8 __U, __m256 __X) {
// CHECK-LABEL: @test_mm256_maskz_permute_ps
- // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> zeroinitializer, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
+ // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> undef, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
// CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_maskz_permute_ps(__U, __X, 0x1b);
}
@@ -5556,73 +7594,81 @@ __m256i test_mm256_maskz_srai_epi64(__mmask8 __U, __m256i __A) {
__m128i test_mm_ternarylogic_epi32(__m128i __A, __m128i __B, __m128i __C) {
// CHECK-LABEL: @test_mm_ternarylogic_epi32
- // CHECK: @llvm.x86.avx512.mask.pternlog.d.128
+ // CHECK: @llvm.x86.avx512.pternlog.d.128
return _mm_ternarylogic_epi32(__A, __B, __C, 4);
}
__m128i test_mm_mask_ternarylogic_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) {
// CHECK-LABEL: @test_mm_mask_ternarylogic_epi32
- // CHECK: @llvm.x86.avx512.mask.pternlog.d.128
+ // CHECK: @llvm.x86.avx512.pternlog.d.128
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_ternarylogic_epi32(__A, __U, __B, __C, 4);
}
__m128i test_mm_maskz_ternarylogic_epi32(__mmask8 __U, __m128i __A, __m128i __B, __m128i __C) {
// CHECK-LABEL: @test_mm_maskz_ternarylogic_epi32
- // CHECK: @llvm.x86.avx512.maskz.pternlog.d.128
+ // CHECK: @llvm.x86.avx512.pternlog.d.128
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> zeroinitializer
return _mm_maskz_ternarylogic_epi32(__U, __A, __B, __C, 4);
}
__m256i test_mm256_ternarylogic_epi32(__m256i __A, __m256i __B, __m256i __C) {
// CHECK-LABEL: @test_mm256_ternarylogic_epi32
- // CHECK: @llvm.x86.avx512.mask.pternlog.d.256
+ // CHECK: @llvm.x86.avx512.pternlog.d.256
return _mm256_ternarylogic_epi32(__A, __B, __C, 4);
}
__m256i test_mm256_mask_ternarylogic_epi32(__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) {
// CHECK-LABEL: @test_mm256_mask_ternarylogic_epi32
- // CHECK: @llvm.x86.avx512.mask.pternlog.d.256
+ // CHECK: @llvm.x86.avx512.pternlog.d.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_ternarylogic_epi32(__A, __U, __B, __C, 4);
}
__m256i test_mm256_maskz_ternarylogic_epi32(__mmask8 __U, __m256i __A, __m256i __B, __m256i __C) {
// CHECK-LABEL: @test_mm256_maskz_ternarylogic_epi32
- // CHECK: @llvm.x86.avx512.maskz.pternlog.d.256
+ // CHECK: @llvm.x86.avx512.pternlog.d.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> zeroinitializer
return _mm256_maskz_ternarylogic_epi32(__U, __A, __B, __C, 4);
}
__m128i test_mm_ternarylogic_epi64(__m128i __A, __m128i __B, __m128i __C) {
// CHECK-LABEL: @test_mm_ternarylogic_epi64
- // CHECK: @llvm.x86.avx512.mask.pternlog.q.128
+ // CHECK: @llvm.x86.avx512.pternlog.q.128
return _mm_ternarylogic_epi64(__A, __B, __C, 4);
}
__m128i test_mm_mask_ternarylogic_epi64(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) {
// CHECK-LABEL: @test_mm_mask_ternarylogic_epi64
- // CHECK: @llvm.x86.avx512.mask.pternlog.q.128
+ // CHECK: @llvm.x86.avx512.pternlog.q.128
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_ternarylogic_epi64(__A, __U, __B, __C, 4);
}
__m128i test_mm_maskz_ternarylogic_epi64(__mmask8 __U, __m128i __A, __m128i __B, __m128i __C) {
// CHECK-LABEL: @test_mm_maskz_ternarylogic_epi64
- // CHECK: @llvm.x86.avx512.maskz.pternlog.q.128
+ // CHECK: @llvm.x86.avx512.pternlog.q.128
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> zeroinitializer
return _mm_maskz_ternarylogic_epi64(__U, __A, __B, __C, 4);
}
__m256i test_mm256_ternarylogic_epi64(__m256i __A, __m256i __B, __m256i __C) {
// CHECK-LABEL: @test_mm256_ternarylogic_epi64
- // CHECK: @llvm.x86.avx512.mask.pternlog.q.256
+ // CHECK: @llvm.x86.avx512.pternlog.q.256
return _mm256_ternarylogic_epi64(__A, __B, __C, 4);
}
__m256i test_mm256_mask_ternarylogic_epi64(__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) {
// CHECK-LABEL: @test_mm256_mask_ternarylogic_epi64
- // CHECK: @llvm.x86.avx512.mask.pternlog.q.256
+ // CHECK: @llvm.x86.avx512.pternlog.q.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_ternarylogic_epi64(__A, __U, __B, __C, 4);
}
__m256i test_mm256_maskz_ternarylogic_epi64(__mmask8 __U, __m256i __A, __m256i __B, __m256i __C) {
// CHECK-LABEL: @test_mm256_maskz_ternarylogic_epi64
- // CHECK: @llvm.x86.avx512.maskz.pternlog.q.256
+ // CHECK: @llvm.x86.avx512.pternlog.q.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> zeroinitializer
return _mm256_maskz_ternarylogic_epi64(__U, __A, __B, __C, 4);
}
__m256 test_mm256_shuffle_f32x4(__m256 __A, __m256 __B) {
@@ -5669,20 +7715,20 @@ __m256d test_mm256_maskz_shuffle_f64x2(__mmask8 __U, __m256d __A, __m256d __B) {
__m256i test_mm256_shuffle_i32x4(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_shuffle_i32x4
- // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i32> <i32 2, i32 3, i32 6, i32 7>
+ // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 12, i32 13, i32 14, i32 15>
return _mm256_shuffle_i32x4(__A, __B, 3);
}
__m256i test_mm256_mask_shuffle_i32x4(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_shuffle_i32x4
- // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i32> <i32 2, i32 3, i32 6, i32 7>
+ // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 12, i32 13, i32 14, i32 15>
// CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_shuffle_i32x4(__W, __U, __A, __B, 3);
}
__m256i test_mm256_maskz_shuffle_i32x4(__mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_shuffle_i32x4
- // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i32> <i32 2, i32 3, i32 6, i32 7>
+ // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 12, i32 13, i32 14, i32 15>
// CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_shuffle_i32x4(__U, __A, __B, 3);
}
@@ -6457,7 +8503,8 @@ void test_mm256_mask_cvtusepi64_storeu_epi16(void * __P, __mmask8 __M, __m256i _
__m128i test_mm_cvtepi32_epi8(__m128i __A) {
// CHECK-LABEL: @test_mm_cvtepi32_epi8
- // CHECK: @llvm.x86.avx512.mask.pmov.db.128
+ // CHECK: trunc <4 x i32> %{{.*}} to <4 x i8>
+ // CHECK: shufflevector <4 x i8> %{{.*}}, <4 x i8> %{{.*}}, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>
return _mm_cvtepi32_epi8(__A);
}
@@ -6481,7 +8528,8 @@ void test_mm_mask_cvtepi32_storeu_epi8(void * __P, __mmask8 __M, __m128i __A) {
__m128i test_mm256_cvtepi32_epi8(__m256i __A) {
// CHECK-LABEL: @test_mm256_cvtepi32_epi8
- // CHECK: @llvm.x86.avx512.mask.pmov.db.256
+ // CHECK: trunc <8 x i32> %{{.*}} to <8 x i8>
+ // CHECK: shufflevector <8 x i8> %{{.*}}, <8 x i8> %{{.*}}, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
return _mm256_cvtepi32_epi8(__A);
}
@@ -6505,7 +8553,8 @@ void test_mm256_mask_cvtepi32_storeu_epi8(void * __P, __mmask8 __M, __m256i __A)
__m128i test_mm_cvtepi32_epi16(__m128i __A) {
// CHECK-LABEL: @test_mm_cvtepi32_epi16
- // CHECK: @llvm.x86.avx512.mask.pmov.dw.128
+ // CHECK: trunc <4 x i32> %{{.*}} to <4 x i16>
+ // CHECK: shufflevector <4 x i16> %{{.*}}, <4 x i16> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
return _mm_cvtepi32_epi16(__A);
}
@@ -6529,7 +8578,7 @@ void test_mm_mask_cvtepi32_storeu_epi16(void * __P, __mmask8 __M, __m128i __A) {
__m128i test_mm256_cvtepi32_epi16(__m256i __A) {
// CHECK-LABEL: @test_mm256_cvtepi32_epi16
- // CHECK: @llvm.x86.avx512.mask.pmov.dw.256
+ // CHECK: trunc <8 x i32> %{{.*}} to <8 x i16>
return _mm256_cvtepi32_epi16(__A);
}
@@ -6553,7 +8602,8 @@ void test_mm256_mask_cvtepi32_storeu_epi16(void * __P, __mmask8 __M, __m256i __
__m128i test_mm_cvtepi64_epi8(__m128i __A) {
// CHECK-LABEL: @test_mm_cvtepi64_epi8
- // CHECK: @llvm.x86.avx512.mask.pmov.qb.128
+ // CHECK: trunc <2 x i64> %{{.*}} to <2 x i8>
+ // CHECK: shufflevector <2 x i8> %{{.*}}, <2 x i8> %{{.*}}, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
return _mm_cvtepi64_epi8(__A);
}
@@ -6577,7 +8627,8 @@ void test_mm_mask_cvtepi64_storeu_epi8(void * __P, __mmask8 __M, __m128i __A) {
__m128i test_mm256_cvtepi64_epi8(__m256i __A) {
// CHECK-LABEL: @test_mm256_cvtepi64_epi8
- // CHECK: @llvm.x86.avx512.mask.pmov.qb.256
+ // CHECK: trunc <4 x i64> %{{.*}} to <4 x i8>
+ // CHECK: shufflevector <4 x i8> %{{.*}}, <4 x i8> %{{.*}}, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>
return _mm256_cvtepi64_epi8(__A);
}
@@ -6601,7 +8652,8 @@ void test_mm256_mask_cvtepi64_storeu_epi8(void * __P, __mmask8 __M, __m256i __A)
__m128i test_mm_cvtepi64_epi32(__m128i __A) {
// CHECK-LABEL: @test_mm_cvtepi64_epi32
- // CHECK: @llvm.x86.avx512.mask.pmov.qd.128
+ // CHECK: trunc <2 x i64> %{{.*}} to <2 x i32>
+ // CHECK: shufflevector <2 x i32> %{{.*}}, <2 x i32> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
return _mm_cvtepi64_epi32(__A);
}
@@ -6625,19 +8677,21 @@ void test_mm_mask_cvtepi64_storeu_epi32(void * __P, __mmask8 __M, __m128i __A) {
__m128i test_mm256_cvtepi64_epi32(__m256i __A) {
// CHECK-LABEL: @test_mm256_cvtepi64_epi32
- // CHECK: @llvm.x86.avx512.mask.pmov.qd.256
+ // CHECK: trunc <4 x i64> %{{.*}} to <4 x i32>
return _mm256_cvtepi64_epi32(__A);
}
__m128i test_mm256_mask_cvtepi64_epi32(__m128i __O, __mmask8 __M, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_cvtepi64_epi32
- // CHECK: @llvm.x86.avx512.mask.pmov.qd.256
+ // CHECK: trunc <4 x i64> %{{.*}} to <4 x i32>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm256_mask_cvtepi64_epi32(__O, __M, __A);
}
__m128i test_mm256_maskz_cvtepi64_epi32(__mmask8 __M, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_cvtepi64_epi32
- // CHECK: @llvm.x86.avx512.mask.pmov.qd.256
+ // CHECK: trunc <4 x i64> %{{.*}} to <4 x i32>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm256_maskz_cvtepi64_epi32(__M, __A);
}
@@ -6649,7 +8703,8 @@ void test_mm256_mask_cvtepi64_storeu_epi32(void * __P, __mmask8 __M, __m256i __A
__m128i test_mm_cvtepi64_epi16(__m128i __A) {
// CHECK-LABEL: @test_mm_cvtepi64_epi16
- // CHECK: @llvm.x86.avx512.mask.pmov.qw.128
+ // CHECK: trunc <2 x i64> %{{.*}} to <2 x i16>
+ // CHECK: shufflevector <2 x i16> %{{.*}}, <2 x i16> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 3, i32 3, i32 3, i32 3>
return _mm_cvtepi64_epi16(__A);
}
@@ -6673,7 +8728,8 @@ void test_mm_mask_cvtepi64_storeu_epi16(void * __P, __mmask8 __M, __m128i __A) {
__m128i test_mm256_cvtepi64_epi16(__m256i __A) {
// CHECK-LABEL: @test_mm256_cvtepi64_epi16
- // CHECK: @llvm.x86.avx512.mask.pmov.qw.256
+ // CHECK: trunc <4 x i64> %{{.*}} to <4 x i16>
+ // CHECK: shufflevector <4 x i16> %{{.*}}, <4 x i16> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
return _mm256_cvtepi64_epi16(__A);
}
@@ -6697,40 +8753,40 @@ void test_mm256_mask_cvtepi64_storeu_epi16(void * __P, __mmask8 __M, __m256i __A
__m128 test_mm256_extractf32x4_ps(__m256 __A) {
// CHECK-LABEL: @test_mm256_extractf32x4_ps
- // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> zeroinitializer, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
return _mm256_extractf32x4_ps(__A, 1);
}
__m128 test_mm256_mask_extractf32x4_ps(__m128 __W, __mmask8 __U, __m256 __A) {
// CHECK-LABEL: @test_mm256_mask_extractf32x4_ps
- // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> zeroinitializer, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm256_mask_extractf32x4_ps(__W, __U, __A, 1);
}
__m128 test_mm256_maskz_extractf32x4_ps(__mmask8 __U, __m256 __A) {
// CHECK-LABEL: @test_mm256_maskz_extractf32x4_ps
- // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> zeroinitializer, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm256_maskz_extractf32x4_ps(__U, __A, 1);
}
__m128i test_mm256_extracti32x4_epi32(__m256i __A) {
// CHECK-LABEL: @test_mm256_extracti32x4_epi32
- // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
return _mm256_extracti32x4_epi32(__A, 1);
}
__m128i test_mm256_mask_extracti32x4_epi32(__m128i __W, __mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_extracti32x4_epi32
- // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm256_mask_extracti32x4_epi32(__W, __U, __A, 1);
}
__m128i test_mm256_maskz_extracti32x4_epi32(__mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_extracti32x4_epi32
- // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm256_maskz_extracti32x4_epi32(__U, __A, 1);
}
@@ -6945,107 +9001,114 @@ __m256i test_mm256_mask_i32gather_epi32(__m256i __v1_old, __mmask8 __mask, __m25
__m256d test_mm256_permutex_pd(__m256d __X) {
// CHECK-LABEL: @test_mm256_permutex_pd
- // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> zeroinitializer, <4 x i32> <i32 3, i32 0, i32 0, i32 0>
+ // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <4 x i32> <i32 3, i32 0, i32 0, i32 0>
return _mm256_permutex_pd(__X, 3);
}
__m256d test_mm256_mask_permutex_pd(__m256d __W, __mmask8 __U, __m256d __X) {
// CHECK-LABEL: @test_mm256_mask_permutex_pd
- // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> zeroinitializer, <4 x i32> <i32 1, i32 0, i32 0, i32 0>
+ // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <4 x i32> <i32 1, i32 0, i32 0, i32 0>
// CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_mask_permutex_pd(__W, __U, __X, 1);
}
__m256d test_mm256_maskz_permutex_pd(__mmask8 __U, __m256d __X) {
// CHECK-LABEL: @test_mm256_maskz_permutex_pd
- // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> zeroinitializer, <4 x i32> <i32 1, i32 0, i32 0, i32 0>
+ // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <4 x i32> <i32 1, i32 0, i32 0, i32 0>
// CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_maskz_permutex_pd(__U, __X, 1);
}
__m256i test_mm256_permutex_epi64(__m256i __X) {
// CHECK-LABEL: @test_mm256_permutex_epi64
- // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> zeroinitializer, <4 x i32> <i32 3, i32 0, i32 0, i32 0>
+ // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <4 x i32> <i32 3, i32 0, i32 0, i32 0>
return _mm256_permutex_epi64(__X, 3);
}
__m256i test_mm256_mask_permutex_epi64(__m256i __W, __mmask8 __M, __m256i __X) {
// CHECK-LABEL: @test_mm256_mask_permutex_epi64
- // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> zeroinitializer, <4 x i32> <i32 3, i32 0, i32 0, i32 0>
+ // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <4 x i32> <i32 3, i32 0, i32 0, i32 0>
// CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_permutex_epi64(__W, __M, __X, 3);
}
__m256i test_mm256_maskz_permutex_epi64(__mmask8 __M, __m256i __X) {
// CHECK-LABEL: @test_mm256_maskz_permutex_epi64
- // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> zeroinitializer, <4 x i32> <i32 3, i32 0, i32 0, i32 0>
+ // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <4 x i32> <i32 3, i32 0, i32 0, i32 0>
// CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_permutex_epi64(__M, __X, 3);
}
__m256d test_mm256_permutexvar_pd(__m256i __X, __m256d __Y) {
// CHECK-LABEL: @test_mm256_permutexvar_pd
- // CHECK: @llvm.x86.avx512.mask.permvar.df.256
+ // CHECK: @llvm.x86.avx512.permvar.df.256
return _mm256_permutexvar_pd(__X, __Y);
}
__m256d test_mm256_mask_permutexvar_pd(__m256d __W, __mmask8 __U, __m256i __X, __m256d __Y) {
// CHECK-LABEL: @test_mm256_mask_permutexvar_pd
- // CHECK: @llvm.x86.avx512.mask.permvar.df.256
+ // CHECK: @llvm.x86.avx512.permvar.df.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_mask_permutexvar_pd(__W, __U, __X, __Y);
}
__m256d test_mm256_maskz_permutexvar_pd(__mmask8 __U, __m256i __X, __m256d __Y) {
// CHECK-LABEL: @test_mm256_maskz_permutexvar_pd
- // CHECK: @llvm.x86.avx512.mask.permvar.df.256
+ // CHECK: @llvm.x86.avx512.permvar.df.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_maskz_permutexvar_pd(__U, __X, __Y);
}
__m256i test_mm256_maskz_permutexvar_epi64(__mmask8 __M, __m256i __X, __m256i __Y) {
// CHECK-LABEL: @test_mm256_maskz_permutexvar_epi64
- // CHECK: @llvm.x86.avx512.mask.permvar.di.256
+ // CHECK: @llvm.x86.avx512.permvar.di.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_permutexvar_epi64(__M, __X, __Y);
}
__m256i test_mm256_mask_permutexvar_epi64(__m256i __W, __mmask8 __M, __m256i __X, __m256i __Y) {
// CHECK-LABEL: @test_mm256_mask_permutexvar_epi64
- // CHECK: @llvm.x86.avx512.mask.permvar.di.256
+ // CHECK: @llvm.x86.avx512.permvar.di.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_permutexvar_epi64(__W, __M, __X, __Y);
}
__m256 test_mm256_mask_permutexvar_ps(__m256 __W, __mmask8 __U, __m256i __X, __m256 __Y) {
// CHECK-LABEL: @test_mm256_mask_permutexvar_ps
- // CHECK: @llvm.x86.avx512.mask.permvar.sf.256
+ // CHECK: @llvm.x86.avx2.permps
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_mask_permutexvar_ps(__W, __U, __X, __Y);
}
__m256 test_mm256_maskz_permutexvar_ps(__mmask8 __U, __m256i __X, __m256 __Y) {
// CHECK-LABEL: @test_mm256_maskz_permutexvar_ps
- // CHECK: @llvm.x86.avx512.mask.permvar.sf.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_maskz_permutexvar_ps(__U, __X, __Y);
}
__m256 test_mm256_permutexvar_ps(__m256i __X, __m256 __Y) {
// CHECK-LABEL: @test_mm256_permutexvar_ps
- // CHECK: @llvm.x86.avx512.mask.permvar.sf.256
+ // CHECK: @llvm.x86.avx2.permps
return _mm256_permutexvar_ps( __X, __Y);
}
__m256i test_mm256_maskz_permutexvar_epi32(__mmask8 __M, __m256i __X, __m256i __Y) {
// CHECK-LABEL: @test_mm256_maskz_permutexvar_epi32
- // CHECK: @llvm.x86.avx512.mask.permvar.si.256
+ // CHECK: @llvm.x86.avx2.permd
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_permutexvar_epi32(__M, __X, __Y);
}
__m256i test_mm256_permutexvar_epi32(__m256i __X, __m256i __Y) {
// CHECK-LABEL: @test_mm256_permutexvar_epi32
- // CHECK: @llvm.x86.avx512.mask.permvar.si.256
+ // CHECK: @llvm.x86.avx2.permd
return _mm256_permutexvar_epi32(__X, __Y);
}
__m256i test_mm256_mask_permutexvar_epi32(__m256i __W, __mmask8 __M, __m256i __X, __m256i __Y) {
// CHECK-LABEL: @test_mm256_mask_permutexvar_epi32
- // CHECK: @llvm.x86.avx512.mask.permvar.si.256
+ // CHECK: @llvm.x86.avx2.permd
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_permutexvar_epi32(__W, __M, __X, __Y);
}
@@ -7187,28 +9250,28 @@ __m256 test_mm256_maskz_moveldup_ps(__mmask8 __U, __m256 __A) {
__m128i test_mm_mask_shuffle_epi32(__m128i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_shuffle_epi32
- // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 1, i32 0, i32 0, i32 0>
+ // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> undef, <4 x i32> <i32 1, i32 0, i32 0, i32 0>
// CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_shuffle_epi32(__W, __U, __A, 1);
}
__m128i test_mm_maskz_shuffle_epi32(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_shuffle_epi32
- // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 2, i32 0, i32 0, i32 0>
+ // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> undef, <4 x i32> <i32 2, i32 0, i32 0, i32 0>
// CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_shuffle_epi32(__U, __A, 2);
}
__m256i test_mm256_mask_shuffle_epi32(__m256i __W, __mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_shuffle_epi32
- // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> <i32 2, i32 0, i32 0, i32 0, i32 6, i32 4, i32 4, i32 4>
+ // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> undef, <8 x i32> <i32 2, i32 0, i32 0, i32 0, i32 6, i32 4, i32 4, i32 4>
// CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_shuffle_epi32(__W, __U, __A, 2);
}
__m256i test_mm256_maskz_shuffle_epi32(__mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_shuffle_epi32
- // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> <i32 2, i32 0, i32 0, i32 0, i32 6, i32 4, i32 4, i32 4>
+ // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> undef, <8 x i32> <i32 2, i32 0, i32 0, i32 0, i32 6, i32 4, i32 4, i32 4>
// CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_shuffle_epi32(__U, __A, 2);
}
diff --git a/test/CodeGen/avx512vlbitalg-builtins.c b/test/CodeGen/avx512vlbitalg-builtins.c
index 9b2a1a469b2a..3dd5b68fd463 100644
--- a/test/CodeGen/avx512vlbitalg-builtins.c
+++ b/test/CodeGen/avx512vlbitalg-builtins.c
@@ -21,23 +21,23 @@ __m256i test_mm256_maskz_popcnt_epi16(__mmask16 __U, __m256i __B) {
return _mm256_maskz_popcnt_epi16(__U, __B);
}
-__m128i test_mm128_popcnt_epi16(__m128i __A) {
- // CHECK-LABEL: @test_mm128_popcnt_epi16
+__m128i test_mm_popcnt_epi16(__m128i __A) {
+ // CHECK-LABEL: @test_mm_popcnt_epi16
// CHECK: @llvm.ctpop.v8i16
- return _mm128_popcnt_epi16(__A);
+ return _mm_popcnt_epi16(__A);
}
-__m128i test_mm128_mask_popcnt_epi16(__m128i __A, __mmask8 __U, __m128i __B) {
- // CHECK-LABEL: @test_mm128_mask_popcnt_epi16
+__m128i test_mm_mask_popcnt_epi16(__m128i __A, __mmask8 __U, __m128i __B) {
+ // CHECK-LABEL: @test_mm_mask_popcnt_epi16
// CHECK: @llvm.ctpop.v8i16
// CHECK: select <8 x i1> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}, <8 x i16> {{.*}}
- return _mm128_mask_popcnt_epi16(__A, __U, __B);
+ return _mm_mask_popcnt_epi16(__A, __U, __B);
}
-__m128i test_mm128_maskz_popcnt_epi16(__mmask8 __U, __m128i __B) {
- // CHECK-LABEL: @test_mm128_maskz_popcnt_epi16
+__m128i test_mm_maskz_popcnt_epi16(__mmask8 __U, __m128i __B) {
+ // CHECK-LABEL: @test_mm_maskz_popcnt_epi16
// CHECK: @llvm.ctpop.v8i16
// CHECK: select <8 x i1> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}, <8 x i16> {{.*}}
- return _mm128_maskz_popcnt_epi16(__U, __B);
+ return _mm_maskz_popcnt_epi16(__U, __B);
}
__m256i test_mm256_popcnt_epi8(__m256i __A) {
@@ -59,46 +59,46 @@ __m256i test_mm256_maskz_popcnt_epi8(__mmask32 __U, __m256i __B) {
return _mm256_maskz_popcnt_epi8(__U, __B);
}
-__m128i test_mm128_popcnt_epi8(__m128i __A) {
- // CHECK-LABEL: @test_mm128_popcnt_epi8
+__m128i test_mm_popcnt_epi8(__m128i __A) {
+ // CHECK-LABEL: @test_mm_popcnt_epi8
// CHECK: @llvm.ctpop.v16i8
- return _mm128_popcnt_epi8(__A);
+ return _mm_popcnt_epi8(__A);
}
-__m128i test_mm128_mask_popcnt_epi8(__m128i __A, __mmask16 __U, __m128i __B) {
- // CHECK-LABEL: @test_mm128_mask_popcnt_epi8
+__m128i test_mm_mask_popcnt_epi8(__m128i __A, __mmask16 __U, __m128i __B) {
+ // CHECK-LABEL: @test_mm_mask_popcnt_epi8
// CHECK: @llvm.ctpop.v16i8
// CHECK: select <16 x i1> %{{[0-9]+}}, <16 x i8> %{{[0-9]+}}, <16 x i8> {{.*}}
- return _mm128_mask_popcnt_epi8(__A, __U, __B);
+ return _mm_mask_popcnt_epi8(__A, __U, __B);
}
-__m128i test_mm128_maskz_popcnt_epi8(__mmask16 __U, __m128i __B) {
- // CHECK-LABEL: @test_mm128_maskz_popcnt_epi8
+__m128i test_mm_maskz_popcnt_epi8(__mmask16 __U, __m128i __B) {
+ // CHECK-LABEL: @test_mm_maskz_popcnt_epi8
// CHECK: @llvm.ctpop.v16i8
// CHECK: select <16 x i1> %{{[0-9]+}}, <16 x i8> %{{[0-9]+}}, <16 x i8> {{.*}}
- return _mm128_maskz_popcnt_epi8(__U, __B);
+ return _mm_maskz_popcnt_epi8(__U, __B);
}
-__mmask32 test_mm256_mask_bitshuffle_epi32_mask(__mmask32 __U, __m256i __A, __m256i __B) {
- // CHECK-LABEL: @test_mm256_mask_bitshuffle_epi32_mask
+__mmask32 test_mm256_mask_bitshuffle_epi64_mask(__mmask32 __U, __m256i __A, __m256i __B) {
+ // CHECK-LABEL: @test_mm256_mask_bitshuffle_epi64_mask
// CHECK: @llvm.x86.avx512.mask.vpshufbitqmb.256
- return _mm256_mask_bitshuffle_epi32_mask(__U, __A, __B);
+ return _mm256_mask_bitshuffle_epi64_mask(__U, __A, __B);
}
-__mmask32 test_mm256_bitshuffle_epi32_mask(__m256i __A, __m256i __B) {
- // CHECK-LABEL: @test_mm256_bitshuffle_epi32_mask
+__mmask32 test_mm256_bitshuffle_epi64_mask(__m256i __A, __m256i __B) {
+ // CHECK-LABEL: @test_mm256_bitshuffle_epi64_mask
// CHECK: @llvm.x86.avx512.mask.vpshufbitqmb.256
- return _mm256_bitshuffle_epi32_mask(__A, __B);
+ return _mm256_bitshuffle_epi64_mask(__A, __B);
}
-__mmask16 test_mm128_mask_bitshuffle_epi16_mask(__mmask16 __U, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_mask_bitshuffle_epi16_mask
+__mmask16 test_mm_mask_bitshuffle_epi64_mask(__mmask16 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_mask_bitshuffle_epi64_mask
// CHECK: @llvm.x86.avx512.mask.vpshufbitqmb.128
- return _mm128_mask_bitshuffle_epi16_mask(__U, __A, __B);
+ return _mm_mask_bitshuffle_epi64_mask(__U, __A, __B);
}
-__mmask16 test_mm128_bitshuffle_epi16_mask(__m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_bitshuffle_epi16_mask
+__mmask16 test_mm_bitshuffle_epi64_mask(__m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_bitshuffle_epi64_mask
// CHECK: @llvm.x86.avx512.mask.vpshufbitqmb.128
- return _mm128_bitshuffle_epi16_mask(__A, __B);
+ return _mm_bitshuffle_epi64_mask(__A, __B);
}
diff --git a/test/CodeGen/avx512vlbw-builtins.c b/test/CodeGen/avx512vlbw-builtins.c
index 23fbd4026aaa..c28c3fbd7f81 100644
--- a/test/CodeGen/avx512vlbw-builtins.c
+++ b/test/CodeGen/avx512vlbw-builtins.c
@@ -974,7 +974,7 @@ __m128i test_mm_maskz_packs_epi32(__mmask8 __M, __m128i __A, __m128i __B) {
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_maskz_packs_epi32(__M,__A,__B);
}
-__m128i test_mm_mask_packs_epi32(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) {
+__m128i test_mm_mask_packs_epi32(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_packs_epi32
// CHECK: @llvm.x86.sse2.packssdw
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
@@ -986,7 +986,7 @@ __m256i test_mm256_maskz_packs_epi32(__mmask16 __M, __m256i __A, __m256i __B) {
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_packs_epi32(__M,__A,__B);
}
-__m256i test_mm256_mask_packs_epi32(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) {
+__m256i test_mm256_mask_packs_epi32(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_packs_epi32
// CHECK: @llvm.x86.avx2.packssdw
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
@@ -998,7 +998,7 @@ __m128i test_mm_maskz_packs_epi16(__mmask16 __M, __m128i __A, __m128i __B) {
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_maskz_packs_epi16(__M,__A,__B);
}
-__m128i test_mm_mask_packs_epi16(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) {
+__m128i test_mm_mask_packs_epi16(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_packs_epi16
// CHECK: @llvm.x86.sse2.packsswb
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
@@ -1010,14 +1010,14 @@ __m256i test_mm256_maskz_packs_epi16(__mmask32 __M, __m256i __A, __m256i __B) {
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_maskz_packs_epi16(__M,__A,__B);
}
-__m256i test_mm256_mask_packs_epi16(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) {
+__m256i test_mm256_mask_packs_epi16(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_packs_epi16
// CHECK: @llvm.x86.avx2.packsswb
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_mask_packs_epi16(__W,__M,__A,__B);
}
-__m128i test_mm_mask_packus_epi32(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) {
+__m128i test_mm_mask_packus_epi32(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_packus_epi32
// CHECK: @llvm.x86.sse41.packusdw
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
@@ -1038,7 +1038,7 @@ __m256i test_mm256_maskz_packus_epi32(__mmask16 __M, __m256i __A, __m256i __B) {
return _mm256_maskz_packus_epi32(__M,__A,__B);
}
-__m256i test_mm256_mask_packus_epi32(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) {
+__m256i test_mm256_mask_packus_epi32(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_packus_epi32
// CHECK: @llvm.x86.avx2.packusdw
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
@@ -1052,7 +1052,7 @@ __m128i test_mm_maskz_packus_epi16(__mmask16 __M, __m128i __A, __m128i __B) {
return _mm_maskz_packus_epi16(__M,__A,__B);
}
-__m128i test_mm_mask_packus_epi16(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) {
+__m128i test_mm_mask_packus_epi16(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_packus_epi16
// CHECK: @llvm.x86.sse2.packuswb
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
@@ -1066,14 +1066,14 @@ __m256i test_mm256_maskz_packus_epi16(__mmask32 __M, __m256i __A, __m256i __B) {
return _mm256_maskz_packus_epi16(__M,__A,__B);
}
-__m256i test_mm256_mask_packus_epi16(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) {
+__m256i test_mm256_mask_packus_epi16(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_packus_epi16
// CHECK: @llvm.x86.avx2.packuswb
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_mask_packus_epi16(__W,__M,__A,__B);
}
-__m128i test_mm_mask_adds_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) {
+__m128i test_mm_mask_adds_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_adds_epi8
// CHECK: @llvm.x86.sse2.padds.b
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
@@ -1085,7 +1085,7 @@ __m128i test_mm_maskz_adds_epi8(__mmask16 __U, __m128i __A, __m128i __B) {
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_maskz_adds_epi8(__U,__A,__B);
}
-__m256i test_mm256_mask_adds_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) {
+__m256i test_mm256_mask_adds_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_adds_epi8
// CHECK: @llvm.x86.avx2.padds.b
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
@@ -1097,7 +1097,7 @@ __m256i test_mm256_maskz_adds_epi8(__mmask32 __U, __m256i __A, __m256i __B) {
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_maskz_adds_epi8(__U,__A,__B);
}
-__m128i test_mm_mask_adds_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
+__m128i test_mm_mask_adds_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_adds_epi16
// CHECK: @llvm.x86.sse2.padds.w
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
@@ -1109,7 +1109,7 @@ __m128i test_mm_maskz_adds_epi16(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_maskz_adds_epi16(__U,__A,__B);
}
-__m256i test_mm256_mask_adds_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
+__m256i test_mm256_mask_adds_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_adds_epi16
// CHECK: @llvm.x86.avx2.padds.w
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
@@ -1121,7 +1121,7 @@ __m256i test_mm256_maskz_adds_epi16(__mmask16 __U, __m256i __A, __m256i __B) {
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_adds_epi16(__U,__A,__B);
}
-__m128i test_mm_mask_adds_epu8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) {
+__m128i test_mm_mask_adds_epu8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_adds_epu8
// CHECK: @llvm.x86.sse2.paddus.b
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
@@ -1133,7 +1133,7 @@ __m128i test_mm_maskz_adds_epu8(__mmask16 __U, __m128i __A, __m128i __B) {
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_maskz_adds_epu8(__U,__A,__B);
}
-__m256i test_mm256_mask_adds_epu8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) {
+__m256i test_mm256_mask_adds_epu8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_adds_epu8
// CHECK: @llvm.x86.avx2.paddus.b
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
@@ -1145,7 +1145,7 @@ __m256i test_mm256_maskz_adds_epu8(__mmask32 __U, __m256i __A, __m256i __B) {
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_maskz_adds_epu8(__U,__A,__B);
}
-__m128i test_mm_mask_adds_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
+__m128i test_mm_mask_adds_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_adds_epu16
// CHECK: @llvm.x86.sse2.paddus.w
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
@@ -1157,7 +1157,7 @@ __m128i test_mm_maskz_adds_epu16(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_maskz_adds_epu16(__U,__A,__B);
}
-__m256i test_mm256_mask_adds_epu16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
+__m256i test_mm256_mask_adds_epu16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_adds_epu16
// CHECK: @llvm.x86.avx2.paddus.w
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
@@ -1169,7 +1169,7 @@ __m256i test_mm256_maskz_adds_epu16(__mmask16 __U, __m256i __A, __m256i __B) {
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_adds_epu16(__U,__A,__B);
}
-__m128i test_mm_mask_avg_epu8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) {
+__m128i test_mm_mask_avg_epu8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_avg_epu8
// CHECK-NOT: @llvm.x86.sse2.pavg.b
// CHECK: zext <16 x i8> %{{.*}} to <16 x i16>
@@ -1194,7 +1194,7 @@ __m128i test_mm_maskz_avg_epu8(__mmask16 __U, __m128i __A, __m128i __B) {
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_maskz_avg_epu8(__U,__A,__B);
}
-__m256i test_mm256_mask_avg_epu8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) {
+__m256i test_mm256_mask_avg_epu8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_avg_epu8
// CHECK-NOT: @llvm.x86.avx2.pavg.b
// CHECK: zext <32 x i8> %{{.*}} to <32 x i16>
@@ -1219,7 +1219,7 @@ __m256i test_mm256_maskz_avg_epu8(__mmask32 __U, __m256i __A, __m256i __B) {
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_maskz_avg_epu8(__U,__A,__B);
}
-__m128i test_mm_mask_avg_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
+__m128i test_mm_mask_avg_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_avg_epu16
// CHECK-NOT: @llvm.x86.sse2.pavg.w
// CHECK: zext <8 x i16> %{{.*}} to <8 x i32>
@@ -1244,7 +1244,7 @@ __m128i test_mm_maskz_avg_epu16(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_maskz_avg_epu16(__U,__A,__B);
}
-__m256i test_mm256_mask_avg_epu16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
+__m256i test_mm256_mask_avg_epu16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_avg_epu16
// CHECK-NOT: @llvm.x86.avx2.pavg.w
// CHECK: zext <16 x i16> %{{.*}} to <16 x i32>
@@ -1276,7 +1276,7 @@ __m128i test_mm_maskz_max_epi8(__mmask16 __M, __m128i __A, __m128i __B) {
// CHECK: select <16 x i1> {{.*}}, <16 x i8> [[RES]], <16 x i8> {{.*}}
return _mm_maskz_max_epi8(__M,__A,__B);
}
-__m128i test_mm_mask_max_epi8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) {
+__m128i test_mm_mask_max_epi8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_max_epi8
// CHECK: [[CMP:%.*]] = icmp sgt <16 x i8> [[X:%.*]], [[Y:%.*]]
// CHECK-NEXT: [[RES:%.*]] = select <16 x i1> [[CMP]], <16 x i8> [[X]], <16 x i8> [[Y]]
@@ -1290,7 +1290,7 @@ __m256i test_mm256_maskz_max_epi8(__mmask32 __M, __m256i __A, __m256i __B) {
// CHECK: select <32 x i1> {{.*}}, <32 x i8> [[RES]], <32 x i8> {{.*}}
return _mm256_maskz_max_epi8(__M,__A,__B);
}
-__m256i test_mm256_mask_max_epi8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) {
+__m256i test_mm256_mask_max_epi8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_max_epi8
// CHECK: [[CMP:%.*]] = icmp sgt <32 x i8> [[X:%.*]], [[Y:%.*]]
// CHECK-NEXT: [[RES:%.*]] = select <32 x i1> [[CMP]], <32 x i8> [[X]], <32 x i8> [[Y]]
@@ -1304,7 +1304,7 @@ __m128i test_mm_maskz_max_epi16(__mmask8 __M, __m128i __A, __m128i __B) {
// CHECK: select <8 x i1> {{.*}}, <8 x i16> [[RES]], <8 x i16> {{.*}}
return _mm_maskz_max_epi16(__M,__A,__B);
}
-__m128i test_mm_mask_max_epi16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) {
+__m128i test_mm_mask_max_epi16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_max_epi16
// CHECK: [[CMP:%.*]] = icmp sgt <8 x i16> [[X:%.*]], [[Y:%.*]]
// CHECK-NEXT: [[RES:%.*]] = select <8 x i1> [[CMP]], <8 x i16> [[X]], <8 x i16> [[Y]]
@@ -1318,7 +1318,7 @@ __m256i test_mm256_maskz_max_epi16(__mmask16 __M, __m256i __A, __m256i __B) {
// CHECK: select <16 x i1> {{.*}}, <16 x i16> [[RES]], <16 x i16> {{.*}}
return _mm256_maskz_max_epi16(__M,__A,__B);
}
-__m256i test_mm256_mask_max_epi16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) {
+__m256i test_mm256_mask_max_epi16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_max_epi16
// CHECK: [[CMP:%.*]] = icmp sgt <16 x i16> [[X:%.*]], [[Y:%.*]]
// CHECK-NEXT: [[RES:%.*]] = select <16 x i1> [[CMP]], <16 x i16> [[X]], <16 x i16> [[Y]]
@@ -1332,7 +1332,7 @@ __m128i test_mm_maskz_max_epu8(__mmask16 __M, __m128i __A, __m128i __B) {
// CHECK: select <16 x i1> {{.*}}, <16 x i8> [[RES]], <16 x i8> {{.*}}
return _mm_maskz_max_epu8(__M,__A,__B);
}
-__m128i test_mm_mask_max_epu8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) {
+__m128i test_mm_mask_max_epu8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_max_epu8
// CHECK: [[CMP:%.*]] = icmp ugt <16 x i8> [[X:%.*]], [[Y:%.*]]
// CHECK-NEXT: [[RES:%.*]] = select <16 x i1> [[CMP]], <16 x i8> [[X]], <16 x i8> [[Y]]
@@ -1346,7 +1346,7 @@ __m256i test_mm256_maskz_max_epu8(__mmask32 __M, __m256i __A, __m256i __B) {
// CHECK: select <32 x i1> {{.*}}, <32 x i8> [[RES]], <32 x i8> {{.*}}
return _mm256_maskz_max_epu8(__M,__A,__B);
}
-__m256i test_mm256_mask_max_epu8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) {
+__m256i test_mm256_mask_max_epu8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_max_epu8
// CHECK: [[CMP:%.*]] = icmp ugt <32 x i8> [[X:%.*]], [[Y:%.*]]
// CHECK-NEXT: [[RES:%.*]] = select <32 x i1> [[CMP]], <32 x i8> [[X]], <32 x i8> [[Y]]
@@ -1360,7 +1360,7 @@ __m128i test_mm_maskz_max_epu16(__mmask8 __M, __m128i __A, __m128i __B) {
// CHECK: select <8 x i1> {{.*}}, <8 x i16> [[RES]], <8 x i16> {{.*}}
return _mm_maskz_max_epu16(__M,__A,__B);
}
-__m128i test_mm_mask_max_epu16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) {
+__m128i test_mm_mask_max_epu16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_max_epu16
// CHECK: [[CMP:%.*]] = icmp ugt <8 x i16> [[X:%.*]], [[Y:%.*]]
// CHECK-NEXT: [[RES:%.*]] = select <8 x i1> [[CMP]], <8 x i16> [[X]], <8 x i16> [[Y]]
@@ -1374,7 +1374,7 @@ __m256i test_mm256_maskz_max_epu16(__mmask16 __M, __m256i __A, __m256i __B) {
// CHECK: select <16 x i1> {{.*}}, <16 x i16> [[RES]], <16 x i16> {{.*}}
return _mm256_maskz_max_epu16(__M,__A,__B);
}
-__m256i test_mm256_mask_max_epu16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) {
+__m256i test_mm256_mask_max_epu16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_max_epu16
// CHECK: [[CMP:%.*]] = icmp ugt <16 x i16> [[X:%.*]], [[Y:%.*]]
// CHECK-NEXT: [[RES:%.*]] = select <16 x i1> [[CMP]], <16 x i16> [[X]], <16 x i16> [[Y]]
@@ -1388,7 +1388,7 @@ __m128i test_mm_maskz_min_epi8(__mmask16 __M, __m128i __A, __m128i __B) {
// CHECK: select <16 x i1> {{.*}}, <16 x i8> [[RES]], <16 x i8> {{.*}}
return _mm_maskz_min_epi8(__M,__A,__B);
}
-__m128i test_mm_mask_min_epi8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) {
+__m128i test_mm_mask_min_epi8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_min_epi8
// CHECK: [[CMP:%.*]] = icmp slt <16 x i8> [[X:%.*]], [[Y:%.*]]
// CHECK-NEXT: [[RES:%.*]] = select <16 x i1> [[CMP]], <16 x i8> [[X]], <16 x i8> [[Y]]
@@ -1402,7 +1402,7 @@ __m256i test_mm256_maskz_min_epi8(__mmask32 __M, __m256i __A, __m256i __B) {
// CHECK: select <32 x i1> {{.*}}, <32 x i8> [[RES]], <32 x i8> {{.*}}
return _mm256_maskz_min_epi8(__M,__A,__B);
}
-__m256i test_mm256_mask_min_epi8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) {
+__m256i test_mm256_mask_min_epi8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_min_epi8
// CHECK: [[CMP:%.*]] = icmp slt <32 x i8> [[X:%.*]], [[Y:%.*]]
// CHECK-NEXT: [[RES:%.*]] = select <32 x i1> [[CMP]], <32 x i8> [[X]], <32 x i8> [[Y]]
@@ -1416,7 +1416,7 @@ __m128i test_mm_maskz_min_epi16(__mmask8 __M, __m128i __A, __m128i __B) {
// CHECK: select <8 x i1> {{.*}}, <8 x i16> [[RES]], <8 x i16> {{.*}}
return _mm_maskz_min_epi16(__M,__A,__B);
}
-__m128i test_mm_mask_min_epi16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) {
+__m128i test_mm_mask_min_epi16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_min_epi16
// CHECK: [[CMP:%.*]] = icmp slt <8 x i16> [[X:%.*]], [[Y:%.*]]
// CHECK-NEXT: [[RES:%.*]] = select <8 x i1> [[CMP]], <8 x i16> [[X]], <8 x i16> [[Y]]
@@ -1430,7 +1430,7 @@ __m256i test_mm256_maskz_min_epi16(__mmask16 __M, __m256i __A, __m256i __B) {
// CHECK: select <16 x i1> {{.*}}, <16 x i16> [[RES]], <16 x i16> {{.*}}
return _mm256_maskz_min_epi16(__M,__A,__B);
}
-__m256i test_mm256_mask_min_epi16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) {
+__m256i test_mm256_mask_min_epi16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_min_epi16
// CHECK: [[CMP:%.*]] = icmp slt <16 x i16> [[X:%.*]], [[Y:%.*]]
// CHECK-NEXT: [[RES:%.*]] = select <16 x i1> [[CMP]], <16 x i16> [[X]], <16 x i16> [[Y]]
@@ -1444,7 +1444,7 @@ __m128i test_mm_maskz_min_epu8(__mmask16 __M, __m128i __A, __m128i __B) {
// CHECK: select <16 x i1> {{.*}}, <16 x i8> [[RES]], <16 x i8> {{.*}}
return _mm_maskz_min_epu8(__M,__A,__B);
}
-__m128i test_mm_mask_min_epu8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) {
+__m128i test_mm_mask_min_epu8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_min_epu8
// CHECK: [[CMP:%.*]] = icmp ult <16 x i8> [[X:%.*]], [[Y:%.*]]
// CHECK-NEXT: [[RES:%.*]] = select <16 x i1> [[CMP]], <16 x i8> [[X]], <16 x i8> [[Y]]
@@ -1458,7 +1458,7 @@ __m256i test_mm256_maskz_min_epu8(__mmask32 __M, __m256i __A, __m256i __B) {
// CHECK: select <32 x i1> {{.*}}, <32 x i8> [[RES]], <32 x i8> {{.*}}
return _mm256_maskz_min_epu8(__M,__A,__B);
}
-__m256i test_mm256_mask_min_epu8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) {
+__m256i test_mm256_mask_min_epu8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_min_epu8
// CHECK: [[CMP:%.*]] = icmp ult <32 x i8> [[X:%.*]], [[Y:%.*]]
// CHECK-NEXT: [[RES:%.*]] = select <32 x i1> [[CMP]], <32 x i8> [[X]], <32 x i8> [[Y]]
@@ -1472,7 +1472,7 @@ __m128i test_mm_maskz_min_epu16(__mmask8 __M, __m128i __A, __m128i __B) {
// CHECK: select <8 x i1> {{.*}}, <8 x i16> [[RES]], <8 x i16> {{.*}}
return _mm_maskz_min_epu16(__M,__A,__B);
}
-__m128i test_mm_mask_min_epu16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) {
+__m128i test_mm_mask_min_epu16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_min_epu16
// CHECK: [[CMP:%.*]] = icmp ult <8 x i16> [[X:%.*]], [[Y:%.*]]
// CHECK-NEXT: [[RES:%.*]] = select <8 x i1> [[CMP]], <8 x i16> [[X]], <8 x i16> [[Y]]
@@ -1486,14 +1486,14 @@ __m256i test_mm256_maskz_min_epu16(__mmask16 __M, __m256i __A, __m256i __B) {
// CHECK: select <16 x i1> {{.*}}, <16 x i16> [[RES]], <16 x i16> {{.*}}
return _mm256_maskz_min_epu16(__M,__A,__B);
}
-__m256i test_mm256_mask_min_epu16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) {
+__m256i test_mm256_mask_min_epu16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_min_epu16
// CHECK: [[CMP:%.*]] = icmp ult <16 x i16> [[X:%.*]], [[Y:%.*]]
// CHECK-NEXT: [[RES:%.*]] = select <16 x i1> [[CMP]], <16 x i16> [[X]], <16 x i16> [[Y]]
// CHECK: select <16 x i1> {{.*}}, <16 x i16> [[RES]], <16 x i16> {{.*}}
return _mm256_mask_min_epu16(__W,__M,__A,__B);
}
-__m128i test_mm_mask_shuffle_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) {
+__m128i test_mm_mask_shuffle_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_shuffle_epi8
// CHECK: @llvm.x86.ssse3.pshuf.b
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
@@ -1505,7 +1505,7 @@ __m128i test_mm_maskz_shuffle_epi8(__mmask16 __U, __m128i __A, __m128i __B) {
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_maskz_shuffle_epi8(__U,__A,__B);
}
-__m256i test_mm256_mask_shuffle_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) {
+__m256i test_mm256_mask_shuffle_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_shuffle_epi8
// CHECK: @llvm.x86.avx2.pshuf.b
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
@@ -1517,7 +1517,7 @@ __m256i test_mm256_maskz_shuffle_epi8(__mmask32 __U, __m256i __A, __m256i __B) {
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_maskz_shuffle_epi8(__U,__A,__B);
}
-__m128i test_mm_mask_subs_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) {
+__m128i test_mm_mask_subs_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_subs_epi8
// CHECK: @llvm.x86.sse2.psubs.b
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
@@ -1529,7 +1529,7 @@ __m128i test_mm_maskz_subs_epi8(__mmask16 __U, __m128i __A, __m128i __B) {
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_maskz_subs_epi8(__U,__A,__B);
}
-__m256i test_mm256_mask_subs_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) {
+__m256i test_mm256_mask_subs_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_subs_epi8
// CHECK: @llvm.x86.avx2.psubs.b
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
@@ -1541,7 +1541,7 @@ __m256i test_mm256_maskz_subs_epi8(__mmask32 __U, __m256i __A, __m256i __B) {
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_maskz_subs_epi8(__U,__A,__B);
}
-__m128i test_mm_mask_subs_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
+__m128i test_mm_mask_subs_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_subs_epi16
// CHECK: @llvm.x86.sse2.psubs.w
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
@@ -1553,7 +1553,7 @@ __m128i test_mm_maskz_subs_epi16(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_maskz_subs_epi16(__U,__A,__B);
}
-__m256i test_mm256_mask_subs_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
+__m256i test_mm256_mask_subs_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_subs_epi16
// CHECK: @llvm.x86.avx2.psubs.w
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
@@ -1565,7 +1565,7 @@ __m256i test_mm256_maskz_subs_epi16(__mmask16 __U, __m256i __A, __m256i __B) {
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_subs_epi16(__U,__A,__B);
}
-__m128i test_mm_mask_subs_epu8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) {
+__m128i test_mm_mask_subs_epu8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_subs_epu8
// CHECK: @llvm.x86.sse2.psubus.b
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
@@ -1577,7 +1577,7 @@ __m128i test_mm_maskz_subs_epu8(__mmask16 __U, __m128i __A, __m128i __B) {
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_maskz_subs_epu8(__U,__A,__B);
}
-__m256i test_mm256_mask_subs_epu8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) {
+__m256i test_mm256_mask_subs_epu8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_subs_epu8
// CHECK: @llvm.x86.avx2.psubus.b
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
@@ -1589,7 +1589,7 @@ __m256i test_mm256_maskz_subs_epu8(__mmask32 __U, __m256i __A, __m256i __B) {
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_maskz_subs_epu8(__U,__A,__B);
}
-__m128i test_mm_mask_subs_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
+__m128i test_mm_mask_subs_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_subs_epu16
// CHECK: @llvm.x86.sse2.psubus.w
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
@@ -1601,7 +1601,7 @@ __m128i test_mm_maskz_subs_epu16(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_maskz_subs_epu16(__U,__A,__B);
}
-__m256i test_mm256_mask_subs_epu16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
+__m256i test_mm256_mask_subs_epu16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_subs_epu16
// CHECK: @llvm.x86.avx2.psubus.w
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
@@ -1615,45 +1615,51 @@ __m256i test_mm256_maskz_subs_epu16(__mmask16 __U, __m256i __A, __m256i __B) {
}
-__m128i test_mm_mask2_permutex2var_epi16(__m128i __A, __m128i __I, __mmask8 __U, __m128i __B) {
+__m128i test_mm_mask2_permutex2var_epi16(__m128i __A, __m128i __I, __mmask8 __U, __m128i __B) {
// CHECK-LABEL: @test_mm_mask2_permutex2var_epi16
- // CHECK: @llvm.x86.avx512.mask.vpermi2var.hi.128
+ // CHECK: @llvm.x86.avx512.vpermi2var.hi.128
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_mask2_permutex2var_epi16(__A,__I,__U,__B);
}
-__m256i test_mm256_mask2_permutex2var_epi16(__m256i __A, __m256i __I, __mmask16 __U, __m256i __B) {
+__m256i test_mm256_mask2_permutex2var_epi16(__m256i __A, __m256i __I, __mmask16 __U, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask2_permutex2var_epi16
- // CHECK: @llvm.x86.avx512.mask.vpermi2var.hi.256
+ // CHECK: @llvm.x86.avx512.vpermi2var.hi.256
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask2_permutex2var_epi16(__A,__I,__U,__B);
}
__m128i test_mm_permutex2var_epi16(__m128i __A, __m128i __I, __m128i __B) {
// CHECK-LABEL: @test_mm_permutex2var_epi16
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.hi.128
+ // CHECK: @llvm.x86.avx512.vpermi2var.hi.128
return _mm_permutex2var_epi16(__A,__I,__B);
}
-__m128i test_mm_mask_permutex2var_epi16(__m128i __A, __mmask8 __U, __m128i __I, __m128i __B) {
+__m128i test_mm_mask_permutex2var_epi16(__m128i __A, __mmask8 __U, __m128i __I, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_permutex2var_epi16
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.hi.128
+ // CHECK: @llvm.x86.avx512.vpermi2var.hi.128
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_mask_permutex2var_epi16(__A,__U,__I,__B);
}
-__m128i test_mm_maskz_permutex2var_epi16(__mmask8 __U, __m128i __A, __m128i __I, __m128i __B) {
+__m128i test_mm_maskz_permutex2var_epi16(__mmask8 __U, __m128i __A, __m128i __I, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_permutex2var_epi16
- // CHECK: @llvm.x86.avx512.maskz.vpermt2var.hi.128
+ // CHECK: @llvm.x86.avx512.vpermi2var.hi.128
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_maskz_permutex2var_epi16(__U,__A,__I,__B);
}
__m256i test_mm256_permutex2var_epi16(__m256i __A, __m256i __I, __m256i __B) {
// CHECK-LABEL: @test_mm256_permutex2var_epi16
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.hi.256
+ // CHECK: @llvm.x86.avx512.vpermi2var.hi.256
return _mm256_permutex2var_epi16(__A,__I,__B);
}
-__m256i test_mm256_mask_permutex2var_epi16(__m256i __A, __mmask16 __U, __m256i __I, __m256i __B) {
+__m256i test_mm256_mask_permutex2var_epi16(__m256i __A, __mmask16 __U, __m256i __I, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_permutex2var_epi16
- // CHECK: @llvm.x86.avx512.mask.vpermt2var.hi.256
+ // CHECK: @llvm.x86.avx512.vpermi2var.hi.256
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_permutex2var_epi16(__A,__U,__I,__B);
}
-__m256i test_mm256_maskz_permutex2var_epi16(__mmask16 __U, __m256i __A, __m256i __I, __m256i __B) {
+__m256i test_mm256_maskz_permutex2var_epi16(__mmask16 __U, __m256i __A, __m256i __I, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_permutex2var_epi16
- // CHECK: @llvm.x86.avx512.maskz.vpermt2var.hi.256
+ // CHECK: @llvm.x86.avx512.vpermi2var.hi.256
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_permutex2var_epi16(__U,__A,__I,__B);
}
__m128i test_mm_mask_maddubs_epi16(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y) {
@@ -1786,7 +1792,8 @@ __m128i test_mm256_maskz_cvtusepi16_epi8(__mmask16 __M, __m256i __A) {
__m128i test_mm_cvtepi16_epi8(__m128i __A) {
// CHECK-LABEL: @test_mm_cvtepi16_epi8
- // CHECK: @llvm.x86.avx512.mask.pmov.wb.128
+ // CHECK: trunc <8 x i16> %{{.*}} to <8 x i8>
+ // CHECK: shufflevector <8 x i8> %{{.*}}, <8 x i8> %{{.*}}, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
return _mm_cvtepi16_epi8(__A);
}
@@ -1804,19 +1811,21 @@ __m128i test_mm_maskz_cvtepi16_epi8(__mmask8 __M, __m128i __A) {
__m128i test_mm256_cvtepi16_epi8(__m256i __A) {
// CHECK-LABEL: @test_mm256_cvtepi16_epi8
- // CHECK: @llvm.x86.avx512.mask.pmov.wb.256
+ // CHECK: trunc <16 x i16> %{{.*}} to <16 x i8>
return _mm256_cvtepi16_epi8(__A);
}
__m128i test_mm256_mask_cvtepi16_epi8(__m128i __O, __mmask16 __M, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_cvtepi16_epi8
- // CHECK: @llvm.x86.avx512.mask.pmov.wb.256
+ // CHECK: trunc <16 x i16> %{{.*}} to <16 x i8>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm256_mask_cvtepi16_epi8(__O, __M, __A);
}
__m128i test_mm256_maskz_cvtepi16_epi8(__mmask16 __M, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_cvtepi16_epi8
- // CHECK: @llvm.x86.avx512.mask.pmov.wb.256
+ // CHECK: trunc <16 x i16> %{{.*}} to <16 x i8>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm256_maskz_cvtepi16_epi8(__M, __A);
}
@@ -2016,7 +2025,7 @@ __m256i test_mm256_maskz_unpacklo_epi16(__mmask16 __U, __m256i __A, __m256i __B)
return _mm256_maskz_unpacklo_epi16(__U, __A, __B);
}
-__m128i test_mm_mask_cvtepi8_epi16(__m128i __W, __mmask32 __U, __m128i __A) {
+__m128i test_mm_mask_cvtepi8_epi16(__m128i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_cvtepi8_epi16
// CHECK: sext <8 x i8> %{{.*}} to <8 x i16>
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
@@ -2030,7 +2039,7 @@ __m128i test_mm_maskz_cvtepi8_epi16(__mmask8 __U, __m128i __A) {
return _mm_maskz_cvtepi8_epi16(__U, __A);
}
-__m256i test_mm256_mask_cvtepi8_epi16(__m256i __W, __mmask32 __U, __m128i __A) {
+__m256i test_mm256_mask_cvtepi8_epi16(__m256i __W, __mmask16 __U, __m128i __A) {
// CHECK-LABEL: @test_mm256_mask_cvtepi8_epi16
// CHECK: sext <16 x i8> %{{.*}} to <16 x i16>
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
@@ -2044,7 +2053,7 @@ __m256i test_mm256_maskz_cvtepi8_epi16(__mmask16 __U, __m128i __A) {
return _mm256_maskz_cvtepi8_epi16(__U, __A);
}
-__m128i test_mm_mask_cvtepu8_epi16(__m128i __W, __mmask32 __U, __m128i __A) {
+__m128i test_mm_mask_cvtepu8_epi16(__m128i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_cvtepu8_epi16
// CHECK: zext <8 x i8> %{{.*}} to <8 x i16>
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
@@ -2058,7 +2067,7 @@ __m128i test_mm_maskz_cvtepu8_epi16(__mmask8 __U, __m128i __A) {
return _mm_maskz_cvtepu8_epi16(__U, __A);
}
-__m256i test_mm256_mask_cvtepu8_epi16(__m256i __W, __mmask32 __U, __m128i __A) {
+__m256i test_mm256_mask_cvtepu8_epi16(__m256i __W, __mmask16 __U, __m128i __A) {
// CHECK-LABEL: @test_mm256_mask_cvtepu8_epi16
// CHECK: zext <16 x i8> %{{.*}} to <16 x i16>
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
@@ -2601,13 +2610,15 @@ __mmask16 test_mm256_mask_testn_epi16_mask(__mmask16 __U, __m256i __A, __m256i _
__mmask16 test_mm_movepi8_mask(__m128i __A) {
// CHECK-LABEL: @test_mm_movepi8_mask
- // CHECK: @llvm.x86.avx512.cvtb2mask.128
+ // CHECK: [[CMP:%.*]] = icmp slt <16 x i8> %{{.*}}, zeroinitializer
+ // CHECK: bitcast <16 x i1> [[CMP]] to i16
return _mm_movepi8_mask(__A);
}
__mmask32 test_mm256_movepi8_mask(__m256i __A) {
// CHECK-LABEL: @test_mm256_movepi8_mask
- // CHECK: @llvm.x86.avx512.cvtb2mask.256
+ // CHECK: [[CMP:%.*]] = icmp slt <32 x i8> %{{.*}}, zeroinitializer
+ // CHECK: bitcast <32 x i1> [[CMP]] to i32
return _mm256_movepi8_mask(__A);
}
@@ -2887,37 +2898,41 @@ __m128i test_mm_maskz_set1_epi16(__mmask8 __M, short __A) {
}
__m128i test_mm_permutexvar_epi16(__m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_permutexvar_epi16
- // CHECK: @llvm.x86.avx512.mask.permvar.hi.128
+ // CHECK: @llvm.x86.avx512.permvar.hi.128
return _mm_permutexvar_epi16(__A, __B);
}
__m128i test_mm_maskz_permutexvar_epi16(__mmask8 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_permutexvar_epi16
- // CHECK: @llvm.x86.avx512.mask.permvar.hi.128
+ // CHECK: @llvm.x86.avx512.permvar.hi.128
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_maskz_permutexvar_epi16(__M, __A, __B);
}
__m128i test_mm_mask_permutexvar_epi16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_permutexvar_epi16
- // CHECK: @llvm.x86.avx512.mask.permvar.hi.128
+ // CHECK: @llvm.x86.avx512.permvar.hi.128
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_mask_permutexvar_epi16(__W, __M, __A, __B);
}
__m256i test_mm256_permutexvar_epi16(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_permutexvar_epi16
- // CHECK: @llvm.x86.avx512.mask.permvar.hi.256
+ // CHECK: @llvm.x86.avx512.permvar.hi.256
return _mm256_permutexvar_epi16(__A, __B);
}
__m256i test_mm256_maskz_permutexvar_epi16(__mmask16 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_permutexvar_epi16
- // CHECK: @llvm.x86.avx512.mask.permvar.hi.256
+ // CHECK: @llvm.x86.avx512.permvar.hi.256
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_permutexvar_epi16(__M, __A, __B);
}
__m256i test_mm256_mask_permutexvar_epi16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_permutexvar_epi16
- // CHECK: @llvm.x86.avx512.mask.permvar.hi.256
+ // CHECK: @llvm.x86.avx512.permvar.hi.256
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_permutexvar_epi16(__W, __M, __A, __B);
}
__m128i test_mm_mask_alignr_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) {
@@ -2950,103 +2965,109 @@ __m256i test_mm256_maskz_alignr_epi8(__mmask32 __U, __m256i __A, __m256i __B) {
__m128i test_mm_dbsad_epu8(__m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_dbsad_epu8
- // CHECK: @llvm.x86.avx512.mask.dbpsadbw.128
+ // CHECK: @llvm.x86.avx512.dbpsadbw.128
return _mm_dbsad_epu8(__A, __B, 170);
}
__m128i test_mm_mask_dbsad_epu8(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_dbsad_epu8
- // CHECK: @llvm.x86.avx512.mask.dbpsadbw.128
+ // CHECK: @llvm.x86.avx512.dbpsadbw.128
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_mask_dbsad_epu8(__W, __U, __A, __B, 170);
}
__m128i test_mm_maskz_dbsad_epu8(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_dbsad_epu8
- // CHECK: @llvm.x86.avx512.mask.dbpsadbw.128
+ // CHECK: @llvm.x86.avx512.dbpsadbw.128
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_maskz_dbsad_epu8(__U, __A, __B, 170);
}
__m256i test_mm256_dbsad_epu8(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_dbsad_epu8
- // CHECK: @llvm.x86.avx512.mask.dbpsadbw.256
+ // CHECK: @llvm.x86.avx512.dbpsadbw.256
return _mm256_dbsad_epu8(__A, __B, 170);
}
__m256i test_mm256_mask_dbsad_epu8(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_dbsad_epu8
- // CHECK: @llvm.x86.avx512.mask.dbpsadbw.256
+ // CHECK: @llvm.x86.avx512.dbpsadbw.256
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_dbsad_epu8(__W, __U, __A, __B, 170);
}
__m256i test_mm256_maskz_dbsad_epu8(__mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_dbsad_epu8
- // CHECK: @llvm.x86.avx512.mask.dbpsadbw.256
+ // CHECK: @llvm.x86.avx512.dbpsadbw.256
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_dbsad_epu8(__U, __A, __B, 170);
}
__mmask8 test_mm_movepi16_mask(__m128i __A) {
// CHECK-LABEL: @test_mm_movepi16_mask
- // CHECK: @llvm.x86.avx512.cvtw2mask.128
+ // CHECK: [[CMP:%.*]] = icmp slt <8 x i16> %{{.*}}, zeroinitializer
+ // CHECK: bitcast <8 x i1> [[CMP]] to i8
return _mm_movepi16_mask(__A);
}
__mmask16 test_mm256_movepi16_mask(__m256i __A) {
// CHECK-LABEL: @test_mm256_movepi16_mask
- // CHECK: @llvm.x86.avx512.cvtw2mask.256
+ // CHECK: [[CMP:%.*]] = icmp slt <16 x i16> %{{.*}}, zeroinitializer
+ // CHECK: bitcast <16 x i1> [[CMP]] to i16
return _mm256_movepi16_mask(__A);
}
-__m128i test_mm_mask_shufflehi_epi16(__m128i __W, __mmask32 __U, __m128i __A) {
+__m128i test_mm_mask_shufflehi_epi16(__m128i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_shufflehi_epi16
- // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 5, i32 5, i32 4, i32 4>
+ // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 5, i32 5, i32 4, i32 4>
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_mask_shufflehi_epi16(__W, __U, __A, 5);
}
-__m128i test_mm_maskz_shufflehi_epi16(__mmask32 __U, __m128i __A) {
+__m128i test_mm_maskz_shufflehi_epi16(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_shufflehi_epi16
- // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 5, i32 5, i32 4, i32 4>
+ // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 5, i32 5, i32 4, i32 4>
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_maskz_shufflehi_epi16(__U, __A, 5);
}
-__m128i test_mm_mask_shufflelo_epi16(__m128i __W, __mmask32 __U, __m128i __A) {
+__m128i test_mm_mask_shufflelo_epi16(__m128i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_shufflelo_epi16
- // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i32> <i32 1, i32 1, i32 0, i32 0, i32 4, i32 5, i32 6, i32 7>
+ // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> undef, <8 x i32> <i32 1, i32 1, i32 0, i32 0, i32 4, i32 5, i32 6, i32 7>
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_mask_shufflelo_epi16(__W, __U, __A, 5);
}
-__m128i test_mm_maskz_shufflelo_epi16(__mmask32 __U, __m128i __A) {
+__m128i test_mm_maskz_shufflelo_epi16(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_shufflelo_epi16
- // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i32> <i32 1, i32 1, i32 0, i32 0, i32 4, i32 5, i32 6, i32 7>
+ // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> undef, <8 x i32> <i32 1, i32 1, i32 0, i32 0, i32 4, i32 5, i32 6, i32 7>
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_maskz_shufflelo_epi16(__U, __A, 5);
}
-__m256i test_mm256_mask_shufflehi_epi16(__m256i __W, __mmask32 __U, __m256i __A) {
+__m256i test_mm256_mask_shufflehi_epi16(__m256i __W, __mmask16 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_shufflehi_epi16
- // CHECK: shufflevector <16 x i16> %{{.*}}, <16 x i16> %{{.*}}, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 5, i32 5, i32 4, i32 4, i32 8, i32 9, i32 10, i32 11, i32 13, i32 13, i32 12, i32 12>
+ // CHECK: shufflevector <16 x i16> %{{.*}}, <16 x i16> undef, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 5, i32 5, i32 4, i32 4, i32 8, i32 9, i32 10, i32 11, i32 13, i32 13, i32 12, i32 12>
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_shufflehi_epi16(__W, __U, __A, 5);
}
-__m256i test_mm256_maskz_shufflehi_epi16(__mmask32 __U, __m256i __A) {
+__m256i test_mm256_maskz_shufflehi_epi16(__mmask16 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_shufflehi_epi16
- // CHECK: shufflevector <16 x i16> %{{.*}}, <16 x i16> %{{.*}}, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 5, i32 5, i32 4, i32 4, i32 8, i32 9, i32 10, i32 11, i32 13, i32 13, i32 12, i32 12>
+ // CHECK: shufflevector <16 x i16> %{{.*}}, <16 x i16> undef, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 5, i32 5, i32 4, i32 4, i32 8, i32 9, i32 10, i32 11, i32 13, i32 13, i32 12, i32 12>
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_shufflehi_epi16(__U, __A, 5);
}
-__m256i test_mm256_mask_shufflelo_epi16(__m256i __W, __mmask32 __U, __m256i __A) {
+__m256i test_mm256_mask_shufflelo_epi16(__m256i __W, __mmask16 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_shufflelo_epi16
- // CHECK: shufflevector <16 x i16> %{{.*}}, <16 x i16> %{{.*}}, <16 x i32> <i32 1, i32 1, i32 0, i32 0, i32 4, i32 5, i32 6, i32 7, i32 9, i32 9, i32 8, i32 8, i32 12, i32 13, i32 14, i32 15>
+ // CHECK: shufflevector <16 x i16> %{{.*}}, <16 x i16> undef, <16 x i32> <i32 1, i32 1, i32 0, i32 0, i32 4, i32 5, i32 6, i32 7, i32 9, i32 9, i32 8, i32 8, i32 12, i32 13, i32 14, i32 15>
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_shufflelo_epi16(__W, __U, __A, 5);
}
-__m256i test_mm256_maskz_shufflelo_epi16(__mmask32 __U, __m256i __A) {
+__m256i test_mm256_maskz_shufflelo_epi16(__mmask16 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_shufflelo_epi16
- // CHECK: shufflevector <16 x i16> %{{.*}}, <16 x i16> %{{.*}}, <16 x i32> <i32 1, i32 1, i32 0, i32 0, i32 4, i32 5, i32 6, i32 7, i32 9, i32 9, i32 8, i32 8, i32 12, i32 13, i32 14, i32 15>
+ // CHECK: shufflevector <16 x i16> %{{.*}}, <16 x i16> undef, <16 x i32> <i32 1, i32 1, i32 0, i32 0, i32 4, i32 5, i32 6, i32 7, i32 9, i32 9, i32 8, i32 8, i32 12, i32 13, i32 14, i32 15>
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_shufflelo_epi16(__U, __A, 5);
}
diff --git a/test/CodeGen/avx512vldq-builtins.c b/test/CodeGen/avx512vldq-builtins.c
index 3ca4b2135ea7..b21b665eb9be 100644
--- a/test/CodeGen/avx512vldq-builtins.c
+++ b/test/CodeGen/avx512vldq-builtins.c
@@ -421,37 +421,41 @@ __m256i test_mm256_maskz_cvtps_epu64(__mmask8 __U, __m128 __A) {
__m128d test_mm_cvtepi64_pd(__m128i __A) {
// CHECK-LABEL: @test_mm_cvtepi64_pd
- // CHECK: @llvm.x86.avx512.mask.cvtqq2pd.128
+ // CHECK: sitofp <2 x i64> %{{.*}} to <2 x double>
return _mm_cvtepi64_pd(__A);
}
__m128d test_mm_mask_cvtepi64_pd(__m128d __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_cvtepi64_pd
- // CHECK: @llvm.x86.avx512.mask.cvtqq2pd.128
+ // CHECK: sitofp <2 x i64> %{{.*}} to <2 x double>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_mask_cvtepi64_pd(__W, __U, __A);
}
__m128d test_mm_maskz_cvtepi64_pd(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_cvtepi64_pd
- // CHECK: @llvm.x86.avx512.mask.cvtqq2pd.128
+ // CHECK: sitofp <2 x i64> %{{.*}} to <2 x double>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_maskz_cvtepi64_pd(__U, __A);
}
__m256d test_mm256_cvtepi64_pd(__m256i __A) {
// CHECK-LABEL: @test_mm256_cvtepi64_pd
- // CHECK: @llvm.x86.avx512.mask.cvtqq2pd.256
+ // CHECK: sitofp <4 x i64> %{{.*}} to <4 x double>
return _mm256_cvtepi64_pd(__A);
}
__m256d test_mm256_mask_cvtepi64_pd(__m256d __W, __mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_cvtepi64_pd
- // CHECK: @llvm.x86.avx512.mask.cvtqq2pd.256
+ // CHECK: sitofp <4 x i64> %{{.*}} to <4 x double>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_mask_cvtepi64_pd(__W, __U, __A);
}
__m256d test_mm256_maskz_cvtepi64_pd(__mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_cvtepi64_pd
- // CHECK: @llvm.x86.avx512.mask.cvtqq2pd.256
+ // CHECK: sitofp <4 x i64> %{{.*}} to <4 x double>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_maskz_cvtepi64_pd(__U, __A);
}
@@ -637,37 +641,41 @@ __m256i test_mm256_maskz_cvttps_epu64(__mmask8 __U, __m128 __A) {
__m128d test_mm_cvtepu64_pd(__m128i __A) {
// CHECK-LABEL: @test_mm_cvtepu64_pd
- // CHECK: @llvm.x86.avx512.mask.cvtuqq2pd.128
+ // CHECK: uitofp <2 x i64> %{{.*}} to <2 x double>
return _mm_cvtepu64_pd(__A);
}
__m128d test_mm_mask_cvtepu64_pd(__m128d __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_cvtepu64_pd
- // CHECK: @llvm.x86.avx512.mask.cvtuqq2pd.128
+ // CHECK: uitofp <2 x i64> %{{.*}} to <2 x double>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_mask_cvtepu64_pd(__W, __U, __A);
}
__m128d test_mm_maskz_cvtepu64_pd(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_cvtepu64_pd
- // CHECK: @llvm.x86.avx512.mask.cvtuqq2pd.128
+ // CHECK: uitofp <2 x i64> %{{.*}} to <2 x double>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_maskz_cvtepu64_pd(__U, __A);
}
__m256d test_mm256_cvtepu64_pd(__m256i __A) {
// CHECK-LABEL: @test_mm256_cvtepu64_pd
- // CHECK: @llvm.x86.avx512.mask.cvtuqq2pd.256
+ // CHECK: uitofp <4 x i64> %{{.*}} to <4 x double>
return _mm256_cvtepu64_pd(__A);
}
__m256d test_mm256_mask_cvtepu64_pd(__m256d __W, __mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_cvtepu64_pd
- // CHECK: @llvm.x86.avx512.mask.cvtuqq2pd.256
+ // CHECK: uitofp <4 x i64> %{{.*}} to <4 x double>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_mask_cvtepu64_pd(__W, __U, __A);
}
__m256d test_mm256_maskz_cvtepu64_pd(__mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_cvtepu64_pd
- // CHECK: @llvm.x86.avx512.mask.cvtuqq2pd.256
+ // CHECK: uitofp <4 x i64> %{{.*}} to <4 x double>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_maskz_cvtepu64_pd(__U, __A);
}
@@ -853,13 +861,16 @@ __m256 test_mm256_maskz_reduce_ps(__mmask8 __U, __m256 __A) {
__mmask8 test_mm_movepi32_mask(__m128i __A) {
// CHECK-LABEL: @test_mm_movepi32_mask
- // CHECK: @llvm.x86.avx512.cvtd2mask.128
+ // CHECK: [[CMP:%.*]] = icmp slt <4 x i32> %{{.*}}, zeroinitializer
+ // CHECK: [[SHUF:%.*]] = shufflevector <4 x i1> [[CMP]], <4 x i1> zeroinitializer, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ // CHECK: bitcast <8 x i1> [[SHUF]] to i8
return _mm_movepi32_mask(__A);
}
__mmask8 test_mm256_movepi32_mask(__m256i __A) {
// CHECK-LABEL: @test_mm256_movepi32_mask
- // CHECK: @llvm.x86.avx512.cvtd2mask.256
+ // CHECK: [[CMP:%.*]] = icmp slt <8 x i32> %{{.*}}, zeroinitializer
+ // CHECK: bitcast <8 x i1> [[CMP]] to i8
return _mm256_movepi32_mask(__A);
}
@@ -896,33 +907,37 @@ __m256i test_mm256_movm_epi64(__mmask8 __A) {
__mmask8 test_mm_movepi64_mask(__m128i __A) {
// CHECK-LABEL: @test_mm_movepi64_mask
- // CHECK: @llvm.x86.avx512.cvtq2mask.128
+ // CHECK: [[CMP:%.*]] = icmp slt <2 x i64> %{{.*}}, zeroinitializer
+ // CHECK: [[SHUF:%.*]] = shufflevector <2 x i1> [[CMP]], <2 x i1> zeroinitializer, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 2, i32 3, i32 2, i32 3>
+ // CHECK: bitcast <8 x i1> [[SHUF]] to i8
return _mm_movepi64_mask(__A);
}
__mmask8 test_mm256_movepi64_mask(__m256i __A) {
// CHECK-LABEL: @test_mm256_movepi64_mask
- // CHECK: @llvm.x86.avx512.cvtq2mask.256
+ // CHECK: [[CMP:%.*]] = icmp slt <4 x i64> %{{.*}}, zeroinitializer
+ // CHECK: [[SHUF:%.*]] = shufflevector <4 x i1> [[CMP]], <4 x i1> zeroinitializer, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ // CHECK: bitcast <8 x i1> [[SHUF]] to i8
return _mm256_movepi64_mask(__A);
}
__m256 test_mm256_broadcast_f32x2(__m128 __A) {
// CHECK-LABEL: @test_mm256_broadcast_f32x2
- // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> zeroinitializer, <8 x i32> <i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1>
+ // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1>
return _mm256_broadcast_f32x2(__A);
}
__m256 test_mm256_mask_broadcast_f32x2(__m256 __O, __mmask8 __M, __m128 __A) {
// CHECK-LABEL: @test_mm256_mask_broadcast_f32x2
- // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> zeroinitializer, <8 x i32> <i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1>
+ // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1>
// CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_mask_broadcast_f32x2(__O, __M, __A);
}
__m256 test_mm256_maskz_broadcast_f32x2(__mmask8 __M, __m128 __A) {
// CHECK-LABEL: @test_mm256_maskz_broadcast_f32x2
- // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> zeroinitializer, <8 x i32> <i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1>
+ // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1>
// CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_maskz_broadcast_f32x2(__M, __A);
}
@@ -949,40 +964,40 @@ __m256d test_mm256_maskz_broadcast_f64x2(__mmask8 __M, double const* __A) {
__m128i test_mm_broadcast_i32x2(__m128i __A) {
// CHECK-LABEL: @test_mm_broadcast_i32x2
- // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 0, i32 1>
+ // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 0, i32 1>
return _mm_broadcast_i32x2(__A);
}
__m128i test_mm_mask_broadcast_i32x2(__m128i __O, __mmask8 __M, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_broadcast_i32x2
- // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 0, i32 1>
+ // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 0, i32 1>
// CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_broadcast_i32x2(__O, __M, __A);
}
__m128i test_mm_maskz_broadcast_i32x2(__mmask8 __M, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_broadcast_i32x2
- // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 0, i32 1>
+ // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 0, i32 1>
// CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_broadcast_i32x2(__M, __A);
}
__m256i test_mm256_broadcast_i32x2(__m128i __A) {
// CHECK-LABEL: @test_mm256_broadcast_i32x2
- // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> zeroinitializer, <8 x i32> <i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1>
+ // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1>
return _mm256_broadcast_i32x2(__A);
}
__m256i test_mm256_mask_broadcast_i32x2(__m256i __O, __mmask8 __M, __m128i __A) {
// CHECK-LABEL: @test_mm256_mask_broadcast_i32x2
- // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> zeroinitializer, <8 x i32> <i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1>
+ // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1>
// CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_broadcast_i32x2(__O, __M, __A);
}
__m256i test_mm256_maskz_broadcast_i32x2(__mmask8 __M, __m128i __A) {
// CHECK-LABEL: @test_mm256_maskz_broadcast_i32x2
- // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> zeroinitializer, <8 x i32> <i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1>
+ // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1>
// CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_broadcast_i32x2(__M, __A);
}
@@ -1009,40 +1024,40 @@ __m256i test_mm256_maskz_broadcast_i64x2(__mmask8 __M, __m128i const* __A) {
__m128d test_mm256_extractf64x2_pd(__m256d __A) {
// CHECK-LABEL: @test_mm256_extractf64x2_pd
- // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> zeroinitializer, <2 x i32> <i32 2, i32 3>
+ // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <2 x i32> <i32 2, i32 3>
return _mm256_extractf64x2_pd(__A, 1);
}
__m128d test_mm256_mask_extractf64x2_pd(__m128d __W, __mmask8 __U, __m256d __A) {
// CHECK-LABEL: @test_mm256_mask_extractf64x2_pd
- // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> zeroinitializer, <2 x i32> <i32 2, i32 3>
+ // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <2 x i32> <i32 2, i32 3>
// CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm256_mask_extractf64x2_pd(__W, __U, __A, 1);
}
__m128d test_mm256_maskz_extractf64x2_pd(__mmask8 __U, __m256d __A) {
// CHECK-LABEL: @test_mm256_maskz_extractf64x2_pd
- // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> zeroinitializer, <2 x i32> <i32 2, i32 3>
+ // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <2 x i32> <i32 2, i32 3>
// CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm256_maskz_extractf64x2_pd(__U, __A, 1);
}
__m128i test_mm256_extracti64x2_epi64(__m256i __A) {
// CHECK-LABEL: @test_mm256_extracti64x2_epi64
- // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> zeroinitializer, <2 x i32> <i32 2, i32 3>
+ // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 2, i32 3>
return _mm256_extracti64x2_epi64(__A, 1);
}
__m128i test_mm256_mask_extracti64x2_epi64(__m128i __W, __mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_extracti64x2_epi64
- // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> zeroinitializer, <2 x i32> <i32 2, i32 3>
+ // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 2, i32 3>
// CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm256_mask_extracti64x2_epi64(__W, __U, __A, 1);
}
__m128i test_mm256_maskz_extracti64x2_epi64(__mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_extracti64x2_epi64
- // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> zeroinitializer, <2 x i32> <i32 2, i32 3>
+ // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> <i32 2, i32 3>
// CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm256_maskz_extracti64x2_epi64(__U, __A, 1);
}
@@ -1089,48 +1104,48 @@ __m256i test_mm256_maskz_inserti64x2(__mmask8 __U, __m256i __A, __m128i __B) {
__mmask8 test_mm_mask_fpclass_pd_mask(__mmask8 __U, __m128d __A) {
// CHECK-LABEL: @test_mm_mask_fpclass_pd_mask
- // CHECK: @llvm.x86.avx512.mask.fpclass.pd.128
+ // CHECK: @llvm.x86.avx512.fpclass.pd.128
return _mm_mask_fpclass_pd_mask(__U, __A, 2);
}
__mmask8 test_mm_fpclass_pd_mask(__m128d __A) {
// CHECK-LABEL: @test_mm_fpclass_pd_mask
- // CHECK: @llvm.x86.avx512.mask.fpclass.pd.128
+ // CHECK: @llvm.x86.avx512.fpclass.pd.128
return _mm_fpclass_pd_mask(__A, 2);
}
__mmask8 test_mm256_mask_fpclass_pd_mask(__mmask8 __U, __m256d __A) {
// CHECK-LABEL: @test_mm256_mask_fpclass_pd_mask
- // CHECK: @llvm.x86.avx512.mask.fpclass.pd.256
+ // CHECK: @llvm.x86.avx512.fpclass.pd.256
return _mm256_mask_fpclass_pd_mask(__U, __A, 2);
}
__mmask8 test_mm256_fpclass_pd_mask(__m256d __A) {
// CHECK-LABEL: @test_mm256_fpclass_pd_mask
- // CHECK: @llvm.x86.avx512.mask.fpclass.pd.256
+ // CHECK: @llvm.x86.avx512.fpclass.pd.256
return _mm256_fpclass_pd_mask(__A, 2);
}
__mmask8 test_mm_mask_fpclass_ps_mask(__mmask8 __U, __m128 __A) {
// CHECK-LABEL: @test_mm_mask_fpclass_ps_mask
- // CHECK: @llvm.x86.avx512.mask.fpclass.ps.128
+ // CHECK: @llvm.x86.avx512.fpclass.ps.128
return _mm_mask_fpclass_ps_mask(__U, __A, 2);
}
__mmask8 test_mm_fpclass_ps_mask(__m128 __A) {
// CHECK-LABEL: @test_mm_fpclass_ps_mask
- // CHECK: @llvm.x86.avx512.mask.fpclass.ps.128
+ // CHECK: @llvm.x86.avx512.fpclass.ps.128
return _mm_fpclass_ps_mask(__A, 2);
}
__mmask8 test_mm256_mask_fpclass_ps_mask(__mmask8 __U, __m256 __A) {
// CHECK-LABEL: @test_mm256_mask_fpclass_ps_mask
- // CHECK: @llvm.x86.avx512.mask.fpclass.ps.256
+ // CHECK: @llvm.x86.avx512.fpclass.ps.256
return _mm256_mask_fpclass_ps_mask(__U, __A, 2);
}
__mmask8 test_mm256_fpclass_ps_mask(__m256 __A) {
// CHECK-LABEL: @test_mm256_fpclass_ps_mask
- // CHECK: @llvm.x86.avx512.mask.fpclass.ps.256
+ // CHECK: @llvm.x86.avx512.fpclass.ps.256
return _mm256_fpclass_ps_mask(__A, 2);
}
diff --git a/test/CodeGen/avx512vlvbmi2-builtins.c b/test/CodeGen/avx512vlvbmi2-builtins.c
index 6edc66d30eee..aceb97616d2b 100644
--- a/test/CodeGen/avx512vlvbmi2-builtins.c
+++ b/test/CodeGen/avx512vlvbmi2-builtins.c
@@ -2,88 +2,88 @@
#include <immintrin.h>
-__m128i test_mm128_mask_compress_epi16(__m128i __S, __mmask8 __U, __m128i __D) {
- // CHECK-LABEL: @test_mm128_mask_compress_epi16
+__m128i test_mm_mask_compress_epi16(__m128i __S, __mmask8 __U, __m128i __D) {
+ // CHECK-LABEL: @test_mm_mask_compress_epi16
// CHECK: @llvm.x86.avx512.mask.compress.w.128
- return _mm128_mask_compress_epi16(__S, __U, __D);
+ return _mm_mask_compress_epi16(__S, __U, __D);
}
-__m128i test_mm128_maskz_compress_epi16(__mmask8 __U, __m128i __D) {
- // CHECK-LABEL: @test_mm128_maskz_compress_epi16
+__m128i test_mm_maskz_compress_epi16(__mmask8 __U, __m128i __D) {
+ // CHECK-LABEL: @test_mm_maskz_compress_epi16
// CHECK: @llvm.x86.avx512.mask.compress.w.128
- return _mm128_maskz_compress_epi16(__U, __D);
+ return _mm_maskz_compress_epi16(__U, __D);
}
-__m128i test_mm128_mask_compress_epi8(__m128i __S, __mmask16 __U, __m128i __D) {
- // CHECK-LABEL: @test_mm128_mask_compress_epi8
+__m128i test_mm_mask_compress_epi8(__m128i __S, __mmask16 __U, __m128i __D) {
+ // CHECK-LABEL: @test_mm_mask_compress_epi8
// CHECK: @llvm.x86.avx512.mask.compress.b.128
- return _mm128_mask_compress_epi8(__S, __U, __D);
+ return _mm_mask_compress_epi8(__S, __U, __D);
}
-__m128i test_mm128_maskz_compress_epi8(__mmask16 __U, __m128i __D) {
- // CHECK-LABEL: @test_mm128_maskz_compress_epi8
+__m128i test_mm_maskz_compress_epi8(__mmask16 __U, __m128i __D) {
+ // CHECK-LABEL: @test_mm_maskz_compress_epi8
// CHECK: @llvm.x86.avx512.mask.compress.b.128
- return _mm128_maskz_compress_epi8(__U, __D);
+ return _mm_maskz_compress_epi8(__U, __D);
}
-void test_mm128_mask_compressstoreu_epi16(void *__P, __mmask8 __U, __m128i __D) {
- // CHECK-LABEL: @test_mm128_mask_compressstoreu_epi16
- // CHECK: @llvm.x86.avx512.mask.compress.store.w.128
- _mm128_mask_compressstoreu_epi16(__P, __U, __D);
+void test_mm_mask_compressstoreu_epi16(void *__P, __mmask8 __U, __m128i __D) {
+ // CHECK-LABEL: @test_mm_mask_compressstoreu_epi16
+ // CHECK: @llvm.masked.compressstore.v8i16(<8 x i16> %{{.*}}, i16* %{{.*}}, <8 x i1> %{{.*}})
+ _mm_mask_compressstoreu_epi16(__P, __U, __D);
}
-void test_mm128_mask_compressstoreu_epi8(void *__P, __mmask16 __U, __m128i __D) {
- // CHECK-LABEL: @test_mm128_mask_compressstoreu_epi8
- // CHECK: @llvm.x86.avx512.mask.compress.store.b.128
- _mm128_mask_compressstoreu_epi8(__P, __U, __D);
+void test_mm_mask_compressstoreu_epi8(void *__P, __mmask16 __U, __m128i __D) {
+ // CHECK-LABEL: @test_mm_mask_compressstoreu_epi8
+ // CHECK: @llvm.masked.compressstore.v16i8(<16 x i8> %{{.*}}, i8* %{{.*}}, <16 x i1> %{{.*}})
+ _mm_mask_compressstoreu_epi8(__P, __U, __D);
}
-__m128i test_mm128_mask_expand_epi16(__m128i __S, __mmask8 __U, __m128i __D) {
- // CHECK-LABEL: @test_mm128_mask_expand_epi16
+__m128i test_mm_mask_expand_epi16(__m128i __S, __mmask8 __U, __m128i __D) {
+ // CHECK-LABEL: @test_mm_mask_expand_epi16
// CHECK: @llvm.x86.avx512.mask.expand.w.128
- return _mm128_mask_expand_epi16(__S, __U, __D);
+ return _mm_mask_expand_epi16(__S, __U, __D);
}
-__m128i test_mm128_maskz_expand_epi16(__mmask8 __U, __m128i __D) {
- // CHECK-LABEL: @test_mm128_maskz_expand_epi16
+__m128i test_mm_maskz_expand_epi16(__mmask8 __U, __m128i __D) {
+ // CHECK-LABEL: @test_mm_maskz_expand_epi16
// CHECK: @llvm.x86.avx512.mask.expand.w.128
- return _mm128_maskz_expand_epi16(__U, __D);
+ return _mm_maskz_expand_epi16(__U, __D);
}
-__m128i test_mm128_mask_expand_epi8(__m128i __S, __mmask16 __U, __m128i __D) {
- // CHECK-LABEL: @test_mm128_mask_expand_epi8
+__m128i test_mm_mask_expand_epi8(__m128i __S, __mmask16 __U, __m128i __D) {
+ // CHECK-LABEL: @test_mm_mask_expand_epi8
// CHECK: @llvm.x86.avx512.mask.expand.b.128
- return _mm128_mask_expand_epi8(__S, __U, __D);
+ return _mm_mask_expand_epi8(__S, __U, __D);
}
-__m128i test_mm128_maskz_expand_epi8(__mmask16 __U, __m128i __D) {
- // CHECK-LABEL: @test_mm128_maskz_expand_epi8
+__m128i test_mm_maskz_expand_epi8(__mmask16 __U, __m128i __D) {
+ // CHECK-LABEL: @test_mm_maskz_expand_epi8
// CHECK: @llvm.x86.avx512.mask.expand.b.128
- return _mm128_maskz_expand_epi8(__U, __D);
+ return _mm_maskz_expand_epi8(__U, __D);
}
-__m128i test_mm128_mask_expandloadu_epi16(__m128i __S, __mmask8 __U, void const* __P) {
- // CHECK-LABEL: @test_mm128_mask_expandloadu_epi16
- // CHECK: @llvm.x86.avx512.mask.expand.load.w.128
- return _mm128_mask_expandloadu_epi16(__S, __U, __P);
+__m128i test_mm_mask_expandloadu_epi16(__m128i __S, __mmask8 __U, void const* __P) {
+ // CHECK-LABEL: @test_mm_mask_expandloadu_epi16
+ // CHECK: @llvm.masked.expandload.v8i16(i16* %{{.*}}, <8 x i1> %{{.*}}, <8 x i16> %{{.*}})
+ return _mm_mask_expandloadu_epi16(__S, __U, __P);
}
-__m128i test_mm128_maskz_expandloadu_epi16(__mmask8 __U, void const* __P) {
- // CHECK-LABEL: @test_mm128_maskz_expandloadu_epi16
- // CHECK: @llvm.x86.avx512.mask.expand.load.w.128
- return _mm128_maskz_expandloadu_epi16(__U, __P);
+__m128i test_mm_maskz_expandloadu_epi16(__mmask8 __U, void const* __P) {
+ // CHECK-LABEL: @test_mm_maskz_expandloadu_epi16
+ // CHECK: @llvm.masked.expandload.v8i16(i16* %{{.*}}, <8 x i1> %{{.*}}, <8 x i16> %{{.*}})
+ return _mm_maskz_expandloadu_epi16(__U, __P);
}
-__m128i test_mm128_mask_expandloadu_epi8(__m128i __S, __mmask16 __U, void const* __P) {
- // CHECK-LABEL: @test_mm128_mask_expandloadu_epi8
- // CHECK: @llvm.x86.avx512.mask.expand.load.b.128
- return _mm128_mask_expandloadu_epi8(__S, __U, __P);
+__m128i test_mm_mask_expandloadu_epi8(__m128i __S, __mmask16 __U, void const* __P) {
+ // CHECK-LABEL: @test_mm_mask_expandloadu_epi8
+ // CHECK: @llvm.masked.expandload.v16i8(i8* %{{.*}}, <16 x i1> %{{.*}}, <16 x i8> %{{.*}})
+ return _mm_mask_expandloadu_epi8(__S, __U, __P);
}
-__m128i test_mm128_maskz_expandloadu_epi8(__mmask16 __U, void const* __P) {
- // CHECK-LABEL: @test_mm128_maskz_expandloadu_epi8
- // CHECK: @llvm.x86.avx512.mask.expand.load.b.128
- return _mm128_maskz_expandloadu_epi8(__U, __P);
+__m128i test_mm_maskz_expandloadu_epi8(__mmask16 __U, void const* __P) {
+ // CHECK-LABEL: @test_mm_maskz_expandloadu_epi8
+ // CHECK: @llvm.masked.expandload.v16i8(i8* %{{.*}}, <16 x i1> %{{.*}}, <16 x i8> %{{.*}})
+ return _mm_maskz_expandloadu_epi8(__U, __P);
}
__m256i test_mm256_mask_compress_epi16(__m256i __S, __mmask16 __U, __m256i __D) {
@@ -112,13 +112,13 @@ __m256i test_mm256_maskz_compress_epi8(__mmask32 __U, __m256i __D) {
void test_mm256_mask_compressstoreu_epi16(void *__P, __mmask16 __U, __m256i __D) {
// CHECK-LABEL: @test_mm256_mask_compressstoreu_epi16
- // CHECK: @llvm.x86.avx512.mask.compress.store.w.256
+ // CHECK: @llvm.masked.compressstore.v16i16(<16 x i16> %{{.*}}, i16* %{{.*}}, <16 x i1> %{{.*}})
_mm256_mask_compressstoreu_epi16(__P, __U, __D);
}
void test_mm256_mask_compressstoreu_epi8(void *__P, __mmask32 __U, __m256i __D) {
// CHECK-LABEL: @test_mm256_mask_compressstoreu_epi8
- // CHECK: @llvm.x86.avx512.mask.compress.store.b.256
+ // CHECK: @llvm.masked.compressstore.v32i8(<32 x i8> %{{.*}}, i8* %{{.*}}, <32 x i1> %{{.*}})
_mm256_mask_compressstoreu_epi8(__P, __U, __D);
}
@@ -148,242 +148,266 @@ __m256i test_mm256_maskz_expand_epi8(__mmask32 __U, __m256i __D) {
__m256i test_mm256_mask_expandloadu_epi16(__m256i __S, __mmask16 __U, void const* __P) {
// CHECK-LABEL: @test_mm256_mask_expandloadu_epi16
- // CHECK: @llvm.x86.avx512.mask.expand.load.w.256
+ // CHECK: @llvm.masked.expandload.v16i16(i16* %{{.*}}, <16 x i1> %{{.*}}, <16 x i16> %{{.*}})
return _mm256_mask_expandloadu_epi16(__S, __U, __P);
}
__m256i test_mm256_maskz_expandloadu_epi16(__mmask16 __U, void const* __P) {
// CHECK-LABEL: @test_mm256_maskz_expandloadu_epi16
- // CHECK: @llvm.x86.avx512.mask.expand.load.w.256
+ // CHECK: @llvm.masked.expandload.v16i16(i16* %{{.*}}, <16 x i1> %{{.*}}, <16 x i16> %{{.*}})
return _mm256_maskz_expandloadu_epi16(__U, __P);
}
__m256i test_mm256_mask_expandloadu_epi8(__m256i __S, __mmask32 __U, void const* __P) {
// CHECK-LABEL: @test_mm256_mask_expandloadu_epi8
- // CHECK: @llvm.x86.avx512.mask.expand.load.b.256
+ // CHECK: @llvm.masked.expandload.v32i8(i8* %{{.*}}, <32 x i1> %{{.*}}, <32 x i8> %{{.*}})
return _mm256_mask_expandloadu_epi8(__S, __U, __P);
}
__m256i test_mm256_maskz_expandloadu_epi8(__mmask32 __U, void const* __P) {
// CHECK-LABEL: @test_mm256_maskz_expandloadu_epi8
- // CHECK: @llvm.x86.avx512.mask.expand.load.b.256
+ // CHECK: @llvm.masked.expandload.v32i8(i8* %{{.*}}, <32 x i1> %{{.*}}, <32 x i8> %{{.*}})
return _mm256_maskz_expandloadu_epi8(__U, __P);
}
__m256i test_mm256_mask_shldi_epi64(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_shldi_epi64
- // CHECK: @llvm.x86.avx512.mask.vpshld.q.256
+ // CHECK: @llvm.x86.avx512.vpshld.q.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_shldi_epi64(__S, __U, __A, __B, 127);
}
__m256i test_mm256_maskz_shldi_epi64(__mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_shldi_epi64
- // CHECK: @llvm.x86.avx512.mask.vpshld.q.256
+ // CHECK: @llvm.x86.avx512.vpshld.q.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_shldi_epi64(__U, __A, __B, 63);
}
__m256i test_mm256_shldi_epi64(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_shldi_epi64
- // CHECK: @llvm.x86.avx512.mask.vpshld.q.256
+ // CHECK: @llvm.x86.avx512.vpshld.q.256
return _mm256_shldi_epi64(__A, __B, 31);
}
-__m128i test_mm128_mask_shldi_epi64(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_mask_shldi_epi64
- // CHECK: @llvm.x86.avx512.mask.vpshld.q.128
- return _mm128_mask_shldi_epi64(__S, __U, __A, __B, 127);
+__m128i test_mm_mask_shldi_epi64(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_mask_shldi_epi64
+ // CHECK: @llvm.x86.avx512.vpshld.q.128
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
+ return _mm_mask_shldi_epi64(__S, __U, __A, __B, 127);
}
-__m128i test_mm128_maskz_shldi_epi64(__mmask8 __U, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_maskz_shldi_epi64
- // CHECK: @llvm.x86.avx512.mask.vpshld.q.128
- return _mm128_maskz_shldi_epi64(__U, __A, __B, 63);
+__m128i test_mm_maskz_shldi_epi64(__mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_maskz_shldi_epi64
+ // CHECK: @llvm.x86.avx512.vpshld.q.128
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
+ return _mm_maskz_shldi_epi64(__U, __A, __B, 63);
}
-__m128i test_mm128_shldi_epi64(__m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_shldi_epi64
- // CHECK: @llvm.x86.avx512.mask.vpshld.q.128
- return _mm128_shldi_epi64(__A, __B, 31);
+__m128i test_mm_shldi_epi64(__m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_shldi_epi64
+ // CHECK: @llvm.x86.avx512.vpshld.q.128
+ return _mm_shldi_epi64(__A, __B, 31);
}
__m256i test_mm256_mask_shldi_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_shldi_epi32
- // CHECK: @llvm.x86.avx512.mask.vpshld.d.256
+ // CHECK: @llvm.x86.avx512.vpshld.d.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_shldi_epi32(__S, __U, __A, __B, 127);
}
__m256i test_mm256_maskz_shldi_epi32(__mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_shldi_epi32
- // CHECK: @llvm.x86.avx512.mask.vpshld.d.256
+ // CHECK: @llvm.x86.avx512.vpshld.d.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_shldi_epi32(__U, __A, __B, 63);
}
__m256i test_mm256_shldi_epi32(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_shldi_epi32
- // CHECK: @llvm.x86.avx512.mask.vpshld.d.256
+ // CHECK: @llvm.x86.avx512.vpshld.d.256
return _mm256_shldi_epi32(__A, __B, 31);
}
-__m128i test_mm128_mask_shldi_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_mask_shldi_epi32
- // CHECK: @llvm.x86.avx512.mask.vpshld.d.128
- return _mm128_mask_shldi_epi32(__S, __U, __A, __B, 127);
+__m128i test_mm_mask_shldi_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_mask_shldi_epi32
+ // CHECK: @llvm.x86.avx512.vpshld.d.128
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
+ return _mm_mask_shldi_epi32(__S, __U, __A, __B, 127);
}
-__m128i test_mm128_maskz_shldi_epi32(__mmask8 __U, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_maskz_shldi_epi32
- // CHECK: @llvm.x86.avx512.mask.vpshld.d.128
- return _mm128_maskz_shldi_epi32(__U, __A, __B, 63);
+__m128i test_mm_maskz_shldi_epi32(__mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_maskz_shldi_epi32
+ // CHECK: @llvm.x86.avx512.vpshld.d.128
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
+ return _mm_maskz_shldi_epi32(__U, __A, __B, 63);
}
-__m128i test_mm128_shldi_epi32(__m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_shldi_epi32
- // CHECK: @llvm.x86.avx512.mask.vpshld.d.128
- return _mm128_shldi_epi32(__A, __B, 31);
+__m128i test_mm_shldi_epi32(__m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_shldi_epi32
+ // CHECK: @llvm.x86.avx512.vpshld.d.128
+ return _mm_shldi_epi32(__A, __B, 31);
}
__m256i test_mm256_mask_shldi_epi16(__m256i __S, __mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_shldi_epi16
- // CHECK: @llvm.x86.avx512.mask.vpshld.w.256
+ // CHECK: @llvm.x86.avx512.vpshld.w.256
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_shldi_epi16(__S, __U, __A, __B, 127);
}
__m256i test_mm256_maskz_shldi_epi16(__mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_shldi_epi16
- // CHECK: @llvm.x86.avx512.mask.vpshld.w.256
+ // CHECK: @llvm.x86.avx512.vpshld.w.256
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_shldi_epi16(__U, __A, __B, 63);
}
__m256i test_mm256_shldi_epi16(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_shldi_epi16
- // CHECK: @llvm.x86.avx512.mask.vpshld.w.256
+ // CHECK: @llvm.x86.avx512.vpshld.w.256
return _mm256_shldi_epi16(__A, __B, 31);
}
-__m128i test_mm128_mask_shldi_epi16(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_mask_shldi_epi16
- // CHECK: @llvm.x86.avx512.mask.vpshld.w.128
- return _mm128_mask_shldi_epi16(__S, __U, __A, __B, 127);
+__m128i test_mm_mask_shldi_epi16(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_mask_shldi_epi16
+ // CHECK: @llvm.x86.avx512.vpshld.w.128
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
+ return _mm_mask_shldi_epi16(__S, __U, __A, __B, 127);
}
-__m128i test_mm128_maskz_shldi_epi16(__mmask8 __U, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_maskz_shldi_epi16
- // CHECK: @llvm.x86.avx512.mask.vpshld.w.128
- return _mm128_maskz_shldi_epi16(__U, __A, __B, 63);
+__m128i test_mm_maskz_shldi_epi16(__mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_maskz_shldi_epi16
+ // CHECK: @llvm.x86.avx512.vpshld.w.128
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
+ return _mm_maskz_shldi_epi16(__U, __A, __B, 63);
}
-__m128i test_mm128_shldi_epi16(__m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_shldi_epi16
- // CHECK: @llvm.x86.avx512.mask.vpshld.w.128
- return _mm128_shldi_epi16(__A, __B, 31);
+__m128i test_mm_shldi_epi16(__m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_shldi_epi16
+ // CHECK: @llvm.x86.avx512.vpshld.w.128
+ return _mm_shldi_epi16(__A, __B, 31);
}
__m256i test_mm256_mask_shrdi_epi64(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_shrdi_epi64
- // CHECK: @llvm.x86.avx512.mask.vpshrd.q.256
+ // CHECK: @llvm.x86.avx512.vpshrd.q.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_shrdi_epi64(__S, __U, __A, __B, 127);
}
__m256i test_mm256_maskz_shrdi_epi64(__mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_shrdi_epi64
- // CHECK: @llvm.x86.avx512.mask.vpshrd.q.256
+ // CHECK: @llvm.x86.avx512.vpshrd.q.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_shrdi_epi64(__U, __A, __B, 63);
}
__m256i test_mm256_shrdi_epi64(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_shrdi_epi64
- // CHECK: @llvm.x86.avx512.mask.vpshrd.q.256
+ // CHECK: @llvm.x86.avx512.vpshrd.q.256
return _mm256_shrdi_epi64(__A, __B, 31);
}
-__m128i test_mm128_mask_shrdi_epi64(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_mask_shrdi_epi64
- // CHECK: @llvm.x86.avx512.mask.vpshrd.q.128
- return _mm128_mask_shrdi_epi64(__S, __U, __A, __B, 127);
+__m128i test_mm_mask_shrdi_epi64(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_mask_shrdi_epi64
+ // CHECK: @llvm.x86.avx512.vpshrd.q.128
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
+ return _mm_mask_shrdi_epi64(__S, __U, __A, __B, 127);
}
-__m128i test_mm128_maskz_shrdi_epi64(__mmask8 __U, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_maskz_shrdi_epi64
- // CHECK: @llvm.x86.avx512.mask.vpshrd.q.128
- return _mm128_maskz_shrdi_epi64(__U, __A, __B, 63);
+__m128i test_mm_maskz_shrdi_epi64(__mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_maskz_shrdi_epi64
+ // CHECK: @llvm.x86.avx512.vpshrd.q.128
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
+ return _mm_maskz_shrdi_epi64(__U, __A, __B, 63);
}
-__m128i test_mm128_shrdi_epi64(__m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_shrdi_epi64
- // CHECK: @llvm.x86.avx512.mask.vpshrd.q.128
- return _mm128_shrdi_epi64(__A, __B, 31);
+__m128i test_mm_shrdi_epi64(__m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_shrdi_epi64
+ // CHECK: @llvm.x86.avx512.vpshrd.q.128
+ return _mm_shrdi_epi64(__A, __B, 31);
}
__m256i test_mm256_mask_shrdi_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_shrdi_epi32
- // CHECK: @llvm.x86.avx512.mask.vpshrd.d.256
+ // CHECK: @llvm.x86.avx512.vpshrd.d.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_shrdi_epi32(__S, __U, __A, __B, 127);
}
__m256i test_mm256_maskz_shrdi_epi32(__mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_shrdi_epi32
- // CHECK: @llvm.x86.avx512.mask.vpshrd.d.256
+ // CHECK: @llvm.x86.avx512.vpshrd.d.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_shrdi_epi32(__U, __A, __B, 63);
}
__m256i test_mm256_shrdi_epi32(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_shrdi_epi32
- // CHECK: @llvm.x86.avx512.mask.vpshrd.d.256
+ // CHECK: @llvm.x86.avx512.vpshrd.d.256
return _mm256_shrdi_epi32(__A, __B, 31);
}
-__m128i test_mm128_mask_shrdi_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_mask_shrdi_epi32
- // CHECK: @llvm.x86.avx512.mask.vpshrd.d.128
- return _mm128_mask_shrdi_epi32(__S, __U, __A, __B, 127);
+__m128i test_mm_mask_shrdi_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_mask_shrdi_epi32
+ // CHECK: @llvm.x86.avx512.vpshrd.d.128
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
+ return _mm_mask_shrdi_epi32(__S, __U, __A, __B, 127);
}
-__m128i test_mm128_maskz_shrdi_epi32(__mmask8 __U, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_maskz_shrdi_epi32
- // CHECK: @llvm.x86.avx512.mask.vpshrd.d.128
- return _mm128_maskz_shrdi_epi32(__U, __A, __B, 63);
+__m128i test_mm_maskz_shrdi_epi32(__mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_maskz_shrdi_epi32
+ // CHECK: @llvm.x86.avx512.vpshrd.d.128
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
+ return _mm_maskz_shrdi_epi32(__U, __A, __B, 63);
}
-__m128i test_mm128_shrdi_epi32(__m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_shrdi_epi32
- // CHECK: @llvm.x86.avx512.mask.vpshrd.d.128
- return _mm128_shrdi_epi32(__A, __B, 31);
+__m128i test_mm_shrdi_epi32(__m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_shrdi_epi32
+ // CHECK: @llvm.x86.avx512.vpshrd.d.128
+ return _mm_shrdi_epi32(__A, __B, 31);
}
__m256i test_mm256_mask_shrdi_epi16(__m256i __S, __mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_shrdi_epi16
- // CHECK: @llvm.x86.avx512.mask.vpshrd.w.256
+ // CHECK: @llvm.x86.avx512.vpshrd.w.256
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_shrdi_epi16(__S, __U, __A, __B, 127);
}
__m256i test_mm256_maskz_shrdi_epi16(__mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_shrdi_epi16
- // CHECK: @llvm.x86.avx512.mask.vpshrd.w.256
+ // CHECK: @llvm.x86.avx512.vpshrd.w.256
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_shrdi_epi16(__U, __A, __B, 63);
}
__m256i test_mm256_shrdi_epi16(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_shrdi_epi16
- // CHECK: @llvm.x86.avx512.mask.vpshrd.w.256
+ // CHECK: @llvm.x86.avx512.vpshrd.w.256
return _mm256_shrdi_epi16(__A, __B, 31);
}
-__m128i test_mm128_mask_shrdi_epi16(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_mask_shrdi_epi16
- // CHECK: @llvm.x86.avx512.mask.vpshrd.w.128
- return _mm128_mask_shrdi_epi16(__S, __U, __A, __B, 127);
+__m128i test_mm_mask_shrdi_epi16(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_mask_shrdi_epi16
+ // CHECK: @llvm.x86.avx512.vpshrd.w.128
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
+ return _mm_mask_shrdi_epi16(__S, __U, __A, __B, 127);
}
-__m128i test_mm128_maskz_shrdi_epi16(__mmask8 __U, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_maskz_shrdi_epi16
- // CHECK: @llvm.x86.avx512.mask.vpshrd.w.128
- return _mm128_maskz_shrdi_epi16(__U, __A, __B, 63);
+__m128i test_mm_maskz_shrdi_epi16(__mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_maskz_shrdi_epi16
+ // CHECK: @llvm.x86.avx512.vpshrd.w.128
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
+ return _mm_maskz_shrdi_epi16(__U, __A, __B, 63);
}
-__m128i test_mm128_shrdi_epi16(__m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_shrdi_epi16
- // CHECK: @llvm.x86.avx512.mask.vpshrd.w.128
- return _mm128_shrdi_epi16(__A, __B, 31);
+__m128i test_mm_shrdi_epi16(__m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_shrdi_epi16
+ // CHECK: @llvm.x86.avx512.vpshrd.w.128
+ return _mm_shrdi_epi16(__A, __B, 31);
}
__m256i test_mm256_mask_shldv_epi64(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) {
@@ -404,22 +428,22 @@ __m256i test_mm256_shldv_epi64(__m256i __S, __m256i __A, __m256i __B) {
return _mm256_shldv_epi64(__S, __A, __B);
}
-__m128i test_mm128_mask_shldv_epi64(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_mask_shldv_epi64
+__m128i test_mm_mask_shldv_epi64(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_mask_shldv_epi64
// CHECK: @llvm.x86.avx512.mask.vpshldv.q.128
- return _mm128_mask_shldv_epi64(__S, __U, __A, __B);
+ return _mm_mask_shldv_epi64(__S, __U, __A, __B);
}
-__m128i test_mm128_maskz_shldv_epi64(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_maskz_shldv_epi64
+__m128i test_mm_maskz_shldv_epi64(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_maskz_shldv_epi64
// CHECK: @llvm.x86.avx512.maskz.vpshldv.q.128
- return _mm128_maskz_shldv_epi64(__U, __S, __A, __B);
+ return _mm_maskz_shldv_epi64(__U, __S, __A, __B);
}
-__m128i test_mm128_shldv_epi64(__m128i __S, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_shldv_epi64
+__m128i test_mm_shldv_epi64(__m128i __S, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_shldv_epi64
// CHECK: @llvm.x86.avx512.mask.vpshldv.q.128
- return _mm128_shldv_epi64(__S, __A, __B);
+ return _mm_shldv_epi64(__S, __A, __B);
}
__m256i test_mm256_mask_shldv_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) {
@@ -440,22 +464,22 @@ __m256i test_mm256_shldv_epi32(__m256i __S, __m256i __A, __m256i __B) {
return _mm256_shldv_epi32(__S, __A, __B);
}
-__m128i test_mm128_mask_shldv_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_mask_shldv_epi32
+__m128i test_mm_mask_shldv_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_mask_shldv_epi32
// CHECK: @llvm.x86.avx512.mask.vpshldv.d.128
- return _mm128_mask_shldv_epi32(__S, __U, __A, __B);
+ return _mm_mask_shldv_epi32(__S, __U, __A, __B);
}
-__m128i test_mm128_maskz_shldv_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_maskz_shldv_epi32
+__m128i test_mm_maskz_shldv_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_maskz_shldv_epi32
// CHECK: @llvm.x86.avx512.maskz.vpshldv.d.128
- return _mm128_maskz_shldv_epi32(__U, __S, __A, __B);
+ return _mm_maskz_shldv_epi32(__U, __S, __A, __B);
}
-__m128i test_mm128_shldv_epi32(__m128i __S, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_shldv_epi32
+__m128i test_mm_shldv_epi32(__m128i __S, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_shldv_epi32
// CHECK: @llvm.x86.avx512.mask.vpshldv.d.128
- return _mm128_shldv_epi32(__S, __A, __B);
+ return _mm_shldv_epi32(__S, __A, __B);
}
__m256i test_mm256_mask_shldv_epi16(__m256i __S, __mmask16 __U, __m256i __A, __m256i __B) {
@@ -476,22 +500,22 @@ __m256i test_mm256_shldv_epi16(__m256i __S, __m256i __A, __m256i __B) {
return _mm256_shldv_epi16(__S, __A, __B);
}
-__m128i test_mm128_mask_shldv_epi16(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_mask_shldv_epi16
+__m128i test_mm_mask_shldv_epi16(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_mask_shldv_epi16
// CHECK: @llvm.x86.avx512.mask.vpshldv.w.128
- return _mm128_mask_shldv_epi16(__S, __U, __A, __B);
+ return _mm_mask_shldv_epi16(__S, __U, __A, __B);
}
-__m128i test_mm128_maskz_shldv_epi16(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_maskz_shldv_epi16
+__m128i test_mm_maskz_shldv_epi16(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_maskz_shldv_epi16
// CHECK: @llvm.x86.avx512.maskz.vpshldv.w.128
- return _mm128_maskz_shldv_epi16(__U, __S, __A, __B);
+ return _mm_maskz_shldv_epi16(__U, __S, __A, __B);
}
-__m128i test_mm128_shldv_epi16(__m128i __S, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_shldv_epi16
+__m128i test_mm_shldv_epi16(__m128i __S, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_shldv_epi16
// CHECK: @llvm.x86.avx512.mask.vpshldv.w.128
- return _mm128_shldv_epi16(__S, __A, __B);
+ return _mm_shldv_epi16(__S, __A, __B);
}
__m256i test_mm256_mask_shrdv_epi64(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) {
@@ -512,22 +536,22 @@ __m256i test_mm256_shrdv_epi64(__m256i __S, __m256i __A, __m256i __B) {
return _mm256_shrdv_epi64(__S, __A, __B);
}
-__m128i test_mm128_mask_shrdv_epi64(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_mask_shrdv_epi64
+__m128i test_mm_mask_shrdv_epi64(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_mask_shrdv_epi64
// CHECK: @llvm.x86.avx512.mask.vpshrdv.q.128
- return _mm128_mask_shrdv_epi64(__S, __U, __A, __B);
+ return _mm_mask_shrdv_epi64(__S, __U, __A, __B);
}
-__m128i test_mm128_maskz_shrdv_epi64(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_maskz_shrdv_epi64
+__m128i test_mm_maskz_shrdv_epi64(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_maskz_shrdv_epi64
// CHECK: @llvm.x86.avx512.maskz.vpshrdv.q.128
- return _mm128_maskz_shrdv_epi64(__U, __S, __A, __B);
+ return _mm_maskz_shrdv_epi64(__U, __S, __A, __B);
}
-__m128i test_mm128_shrdv_epi64(__m128i __S, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_shrdv_epi64
+__m128i test_mm_shrdv_epi64(__m128i __S, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_shrdv_epi64
// CHECK: @llvm.x86.avx512.mask.vpshrdv.q.128
- return _mm128_shrdv_epi64(__S, __A, __B);
+ return _mm_shrdv_epi64(__S, __A, __B);
}
__m256i test_mm256_mask_shrdv_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) {
@@ -548,22 +572,22 @@ __m256i test_mm256_shrdv_epi32(__m256i __S, __m256i __A, __m256i __B) {
return _mm256_shrdv_epi32(__S, __A, __B);
}
-__m128i test_mm128_mask_shrdv_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_mask_shrdv_epi32
+__m128i test_mm_mask_shrdv_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_mask_shrdv_epi32
// CHECK: @llvm.x86.avx512.mask.vpshrdv.d.128
- return _mm128_mask_shrdv_epi32(__S, __U, __A, __B);
+ return _mm_mask_shrdv_epi32(__S, __U, __A, __B);
}
-__m128i test_mm128_maskz_shrdv_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_maskz_shrdv_epi32
+__m128i test_mm_maskz_shrdv_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_maskz_shrdv_epi32
// CHECK: @llvm.x86.avx512.maskz.vpshrdv.d.128
- return _mm128_maskz_shrdv_epi32(__U, __S, __A, __B);
+ return _mm_maskz_shrdv_epi32(__U, __S, __A, __B);
}
-__m128i test_mm128_shrdv_epi32(__m128i __S, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_shrdv_epi32
+__m128i test_mm_shrdv_epi32(__m128i __S, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_shrdv_epi32
// CHECK: @llvm.x86.avx512.mask.vpshrdv.d.128
- return _mm128_shrdv_epi32(__S, __A, __B);
+ return _mm_shrdv_epi32(__S, __A, __B);
}
__m256i test_mm256_mask_shrdv_epi16(__m256i __S, __mmask16 __U, __m256i __A, __m256i __B) {
@@ -584,21 +608,21 @@ __m256i test_mm256_shrdv_epi16(__m256i __S, __m256i __A, __m256i __B) {
return _mm256_shrdv_epi16(__S, __A, __B);
}
-__m128i test_mm128_mask_shrdv_epi16(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_mask_shrdv_epi16
+__m128i test_mm_mask_shrdv_epi16(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_mask_shrdv_epi16
// CHECK: @llvm.x86.avx512.mask.vpshrdv.w.128
- return _mm128_mask_shrdv_epi16(__S, __U, __A, __B);
+ return _mm_mask_shrdv_epi16(__S, __U, __A, __B);
}
-__m128i test_mm128_maskz_shrdv_epi16(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_maskz_shrdv_epi16
+__m128i test_mm_maskz_shrdv_epi16(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_maskz_shrdv_epi16
// CHECK: @llvm.x86.avx512.maskz.vpshrdv.w.128
- return _mm128_maskz_shrdv_epi16(__U, __S, __A, __B);
+ return _mm_maskz_shrdv_epi16(__U, __S, __A, __B);
}
-__m128i test_mm128_shrdv_epi16(__m128i __S, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_shrdv_epi16
+__m128i test_mm_shrdv_epi16(__m128i __S, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_shrdv_epi16
// CHECK: @llvm.x86.avx512.mask.vpshrdv.w.128
- return _mm128_shrdv_epi16(__S, __A, __B);
+ return _mm_shrdv_epi16(__S, __A, __B);
}
diff --git a/test/CodeGen/avx512vlvnni-builtins.c b/test/CodeGen/avx512vlvnni-builtins.c
index 861b915fdb29..b742019cb6ee 100644
--- a/test/CodeGen/avx512vlvnni-builtins.c
+++ b/test/CodeGen/avx512vlvnni-builtins.c
@@ -4,145 +4,161 @@
__m256i test_mm256_mask_dpbusd_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_dpbusd_epi32
- // CHECK: @llvm.x86.avx512.mask.vpdpbusd.256
+ // CHECK: @llvm.x86.avx512.vpdpbusd.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_dpbusd_epi32(__S, __U, __A, __B);
}
__m256i test_mm256_maskz_dpbusd_epi32(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_dpbusd_epi32
- // CHECK: @llvm.x86.avx512.maskz.vpdpbusd.256
+ // CHECK: @llvm.x86.avx512.vpdpbusd.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_dpbusd_epi32(__U, __S, __A, __B);
}
__m256i test_mm256_dpbusd_epi32(__m256i __S, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_dpbusd_epi32
- // CHECK: @llvm.x86.avx512.mask.vpdpbusd.256
+ // CHECK: @llvm.x86.avx512.vpdpbusd.256
return _mm256_dpbusd_epi32(__S, __A, __B);
}
__m256i test_mm256_mask_dpbusds_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_dpbusds_epi32
- // CHECK: @llvm.x86.avx512.mask.vpdpbusds.256
+ // CHECK: @llvm.x86.avx512.vpdpbusds.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_dpbusds_epi32(__S, __U, __A, __B);
}
__m256i test_mm256_maskz_dpbusds_epi32(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_dpbusds_epi32
- // CHECK: @llvm.x86.avx512.maskz.vpdpbusds.256
+ // CHECK: @llvm.x86.avx512.vpdpbusds.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_dpbusds_epi32(__U, __S, __A, __B);
}
__m256i test_mm256_dpbusds_epi32(__m256i __S, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_dpbusds_epi32
- // CHECK: @llvm.x86.avx512.mask.vpdpbusds.256
+ // CHECK: @llvm.x86.avx512.vpdpbusds.256
return _mm256_dpbusds_epi32(__S, __A, __B);
}
__m256i test_mm256_mask_dpwssd_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_dpwssd_epi32
- // CHECK: @llvm.x86.avx512.mask.vpdpwssd.256
+ // CHECK: @llvm.x86.avx512.vpdpwssd.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_dpwssd_epi32(__S, __U, __A, __B);
}
__m256i test_mm256_maskz_dpwssd_epi32(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_dpwssd_epi32
- // CHECK: @llvm.x86.avx512.maskz.vpdpwssd.256
+ // CHECK: @llvm.x86.avx512.vpdpwssd.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_dpwssd_epi32(__U, __S, __A, __B);
}
__m256i test_mm256_dpwssd_epi32(__m256i __S, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_dpwssd_epi32
- // CHECK: @llvm.x86.avx512.mask.vpdpwssd.256
+ // CHECK: @llvm.x86.avx512.vpdpwssd.256
return _mm256_dpwssd_epi32(__S, __A, __B);
}
__m256i test_mm256_mask_dpwssds_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_dpwssds_epi32
- // CHECK: @llvm.x86.avx512.mask.vpdpwssds.256
+ // CHECK: @llvm.x86.avx512.vpdpwssds.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_dpwssds_epi32(__S, __U, __A, __B);
}
__m256i test_mm256_maskz_dpwssds_epi32(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_dpwssds_epi32
- // CHECK: @llvm.x86.avx512.maskz.vpdpwssds.256
+ // CHECK: @llvm.x86.avx512.vpdpwssds.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_dpwssds_epi32(__U, __S, __A, __B);
}
__m256i test_mm256_dpwssds_epi32(__m256i __S, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_dpwssds_epi32
- // CHECK: @llvm.x86.avx512.mask.vpdpwssds.256
+ // CHECK: @llvm.x86.avx512.vpdpwssds.256
return _mm256_dpwssds_epi32(__S, __A, __B);
}
-__m128i test_mm128_mask_dpbusd_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_mask_dpbusd_epi32
- // CHECK: @llvm.x86.avx512.mask.vpdpbusd.128
- return _mm128_mask_dpbusd_epi32(__S, __U, __A, __B);
+__m128i test_mm_mask_dpbusd_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_mask_dpbusd_epi32
+ // CHECK: @llvm.x86.avx512.vpdpbusd.128
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
+ return _mm_mask_dpbusd_epi32(__S, __U, __A, __B);
}
-__m128i test_mm128_maskz_dpbusd_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_maskz_dpbusd_epi32
- // CHECK: @llvm.x86.avx512.maskz.vpdpbusd.128
- return _mm128_maskz_dpbusd_epi32(__U, __S, __A, __B);
+__m128i test_mm_maskz_dpbusd_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_maskz_dpbusd_epi32
+ // CHECK: @llvm.x86.avx512.vpdpbusd.128
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
+ return _mm_maskz_dpbusd_epi32(__U, __S, __A, __B);
}
-__m128i test_mm128_dpbusd_epi32(__m128i __S, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_dpbusd_epi32
- // CHECK: @llvm.x86.avx512.mask.vpdpbusd.128
- return _mm128_dpbusd_epi32(__S, __A, __B);
+__m128i test_mm_dpbusd_epi32(__m128i __S, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_dpbusd_epi32
+ // CHECK: @llvm.x86.avx512.vpdpbusd.128
+ return _mm_dpbusd_epi32(__S, __A, __B);
}
-__m128i test_mm128_mask_dpbusds_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_mask_dpbusds_epi32
- // CHECK: @llvm.x86.avx512.mask.vpdpbusds.128
- return _mm128_mask_dpbusds_epi32(__S, __U, __A, __B);
+__m128i test_mm_mask_dpbusds_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_mask_dpbusds_epi32
+ // CHECK: @llvm.x86.avx512.vpdpbusds.128
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
+ return _mm_mask_dpbusds_epi32(__S, __U, __A, __B);
}
-__m128i test_mm128_maskz_dpbusds_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_maskz_dpbusds_epi32
- // CHECK: @llvm.x86.avx512.maskz.vpdpbusds.128
- return _mm128_maskz_dpbusds_epi32(__U, __S, __A, __B);
+__m128i test_mm_maskz_dpbusds_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_maskz_dpbusds_epi32
+ // CHECK: @llvm.x86.avx512.vpdpbusds.128
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
+ return _mm_maskz_dpbusds_epi32(__U, __S, __A, __B);
}
-__m128i test_mm128_dpbusds_epi32(__m128i __S, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_dpbusds_epi32
- // CHECK: @llvm.x86.avx512.mask.vpdpbusds.128
- return _mm128_dpbusds_epi32(__S, __A, __B);
+__m128i test_mm_dpbusds_epi32(__m128i __S, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_dpbusds_epi32
+ // CHECK: @llvm.x86.avx512.vpdpbusds.128
+ return _mm_dpbusds_epi32(__S, __A, __B);
}
-__m128i test_mm128_mask_dpwssd_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_mask_dpwssd_epi32
- // CHECK: @llvm.x86.avx512.mask.vpdpwssd.128
- return _mm128_mask_dpwssd_epi32(__S, __U, __A, __B);
+__m128i test_mm_mask_dpwssd_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_mask_dpwssd_epi32
+ // CHECK: @llvm.x86.avx512.vpdpwssd.128
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
+ return _mm_mask_dpwssd_epi32(__S, __U, __A, __B);
}
-__m128i test_mm128_maskz_dpwssd_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_maskz_dpwssd_epi32
- // CHECK: @llvm.x86.avx512.maskz.vpdpwssd.128
- return _mm128_maskz_dpwssd_epi32(__U, __S, __A, __B);
+__m128i test_mm_maskz_dpwssd_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_maskz_dpwssd_epi32
+ // CHECK: @llvm.x86.avx512.vpdpwssd.128
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
+ return _mm_maskz_dpwssd_epi32(__U, __S, __A, __B);
}
-__m128i test_mm128_dpwssd_epi32(__m128i __S, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_dpwssd_epi32
- // CHECK: @llvm.x86.avx512.mask.vpdpwssd.128
- return _mm128_dpwssd_epi32(__S, __A, __B);
+__m128i test_mm_dpwssd_epi32(__m128i __S, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_dpwssd_epi32
+ // CHECK: @llvm.x86.avx512.vpdpwssd.128
+ return _mm_dpwssd_epi32(__S, __A, __B);
}
-__m128i test_mm128_mask_dpwssds_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_mask_dpwssds_epi32
- // CHECK: @llvm.x86.avx512.mask.vpdpwssds.128
- return _mm128_mask_dpwssds_epi32(__S, __U, __A, __B);
+__m128i test_mm_mask_dpwssds_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_mask_dpwssds_epi32
+ // CHECK: @llvm.x86.avx512.vpdpwssds.128
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
+ return _mm_mask_dpwssds_epi32(__S, __U, __A, __B);
}
-__m128i test_mm128_maskz_dpwssds_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_maskz_dpwssds_epi32
- // CHECK: @llvm.x86.avx512.maskz.vpdpwssds.128
- return _mm128_maskz_dpwssds_epi32(__U, __S, __A, __B);
+__m128i test_mm_maskz_dpwssds_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_maskz_dpwssds_epi32
+ // CHECK: @llvm.x86.avx512.vpdpwssds.128
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
+ return _mm_maskz_dpwssds_epi32(__U, __S, __A, __B);
}
-__m128i test_mm128_dpwssds_epi32(__m128i __S, __m128i __A, __m128i __B) {
- // CHECK-LABEL: @test_mm128_dpwssds_epi32
- // CHECK: @llvm.x86.avx512.mask.vpdpwssds.128
- return _mm128_dpwssds_epi32(__S, __A, __B);
+__m128i test_mm_dpwssds_epi32(__m128i __S, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_dpwssds_epi32
+ // CHECK: @llvm.x86.avx512.vpdpwssds.128
+ return _mm_dpwssds_epi32(__S, __A, __B);
}
diff --git a/test/CodeGen/avx512vnni-builtins.c b/test/CodeGen/avx512vnni-builtins.c
index d79046aa0499..f03c8eaa8261 100644
--- a/test/CodeGen/avx512vnni-builtins.c
+++ b/test/CodeGen/avx512vnni-builtins.c
@@ -4,73 +4,81 @@
__m512i test_mm512_mask_dpbusd_epi32(__m512i __S, __mmask16 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_dpbusd_epi32
- // CHECK: @llvm.x86.avx512.mask.vpdpbusd.512
+ // CHECK: @llvm.x86.avx512.vpdpbusd.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_dpbusd_epi32(__S, __U, __A, __B);
}
__m512i test_mm512_maskz_dpbusd_epi32(__mmask16 __U, __m512i __S, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_dpbusd_epi32
- // CHECK: @llvm.x86.avx512.maskz.vpdpbusd.512
+ // CHECK: @llvm.x86.avx512.vpdpbusd.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_dpbusd_epi32(__U, __S, __A, __B);
}
__m512i test_mm512_dpbusd_epi32(__m512i __S, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_dpbusd_epi32
- // CHECK: @llvm.x86.avx512.mask.vpdpbusd.512
+ // CHECK: @llvm.x86.avx512.vpdpbusd.512
return _mm512_dpbusd_epi32(__S, __A, __B);
}
__m512i test_mm512_mask_dpbusds_epi32(__m512i __S, __mmask16 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_dpbusds_epi32
- // CHECK: @llvm.x86.avx512.mask.vpdpbusds.512
+ // CHECK: @llvm.x86.avx512.vpdpbusds.51
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_dpbusds_epi32(__S, __U, __A, __B);
}
__m512i test_mm512_maskz_dpbusds_epi32(__mmask16 __U, __m512i __S, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_dpbusds_epi32
- // CHECK: @llvm.x86.avx512.maskz.vpdpbusds.512
+ // CHECK: @llvm.x86.avx512.vpdpbusds.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_dpbusds_epi32(__U, __S, __A, __B);
}
__m512i test_mm512_dpbusds_epi32(__m512i __S, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_dpbusds_epi32
- // CHECK: @llvm.x86.avx512.mask.vpdpbusds.512
+ // CHECK: @llvm.x86.avx512.vpdpbusds.512
return _mm512_dpbusds_epi32(__S, __A, __B);
}
__m512i test_mm512_mask_dpwssd_epi32(__m512i __S, __mmask16 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_dpwssd_epi32
- // CHECK: @llvm.x86.avx512.mask.vpdpwssd.512
+ // CHECK: @llvm.x86.avx512.vpdpwssd.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_dpwssd_epi32(__S, __U, __A, __B);
}
__m512i test_mm512_maskz_dpwssd_epi32(__mmask16 __U, __m512i __S, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_dpwssd_epi32
- // CHECK: @llvm.x86.avx512.maskz.vpdpwssd.512
+ // CHECK: @llvm.x86.avx512.vpdpwssd.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_dpwssd_epi32(__U, __S, __A, __B);
}
__m512i test_mm512_dpwssd_epi32(__m512i __S, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_dpwssd_epi32
- // CHECK: @llvm.x86.avx512.mask.vpdpwssd.512
+ // CHECK: @llvm.x86.avx512.vpdpwssd.512
return _mm512_dpwssd_epi32(__S, __A, __B);
}
__m512i test_mm512_mask_dpwssds_epi32(__m512i __S, __mmask16 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_dpwssds_epi32
- // CHECK: @llvm.x86.avx512.mask.vpdpwssds.512
+ // CHECK: @llvm.x86.avx512.vpdpwssds.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_dpwssds_epi32(__S, __U, __A, __B);
}
__m512i test_mm512_maskz_dpwssds_epi32(__mmask16 __U, __m512i __S, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_dpwssds_epi32
- // CHECK: @llvm.x86.avx512.maskz.vpdpwssds.512
+ // CHECK: @llvm.x86.avx512.vpdpwssds.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_dpwssds_epi32(__U, __S, __A, __B);
}
__m512i test_mm512_dpwssds_epi32(__m512i __S, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_dpwssds_epi32
- // CHECK: @llvm.x86.avx512.mask.vpdpwssds.512
+ // CHECK: @llvm.x86.avx512.vpdpwssds.512
return _mm512_dpwssds_epi32(__S, __A, __B);
}
diff --git a/test/CodeGen/backend-unsupported-error.ll b/test/CodeGen/backend-unsupported-error.ll
index 1a15bfc74dfb..75a5992f2353 100644
--- a/test/CodeGen/backend-unsupported-error.ll
+++ b/test/CodeGen/backend-unsupported-error.ll
@@ -3,7 +3,7 @@
; This is to check that backend errors for unsupported features are formatted correctly
-; CHECK: error: test.c:2:20: in function bar i32 (): unsupported call to function foo.2
+; CHECK: error: test.c:2:20: in function bar i32 (): unsupported call to function foo
target triple = "r600-unknown-unknown"
@@ -21,7 +21,7 @@ entry:
ret i32 %call, !dbg !15
}
-attributes #0 = { nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #0 = { nounwind noinline "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!9, !10}
@@ -30,11 +30,11 @@ attributes #0 = { nounwind uwtable "disable-tail-calls"="false" "less-precise-fp
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.0", isOptimized: false, runtimeVersion: 0, emissionKind: 1, enums: !2)
!1 = !DIFile(filename: "test.c", directory: "")
!2 = !{}
-!4 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 2, type: !5, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: false, unit: !0, variables: !2)
+!4 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 2, type: !5, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: false, unit: !0, retainedNodes: !2)
!5 = !DISubroutineType(types: !6)
!6 = !{!7}
!7 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
-!8 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 3, type: !5, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)
+!8 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 3, type: !5, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2)
!9 = !{i32 2, !"Dwarf Version", i32 4}
!10 = !{i32 2, !"Debug Info Version", i32 3}
!11 = !{!"clang version 3.9.0"}
diff --git a/test/CodeGen/bitscan-builtins.c b/test/CodeGen/bitscan-builtins.c
index 5fd3f13fbc73..25dfa4046205 100644
--- a/test/CodeGen/bitscan-builtins.c
+++ b/test/CodeGen/bitscan-builtins.c
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -ffreestanding -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s
// PR33722
-// RUN: %clang_cc1 -ffreestanding -triple x86_64-unknown-unknown -D_MSC_VER -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding -triple x86_64-unknown-unknown -fms-extensions -fms-compatibility-version=19.00 -emit-llvm -o - %s | FileCheck %s
#include <immintrin.h>
diff --git a/test/CodeGen/bittest-intrin.c b/test/CodeGen/bittest-intrin.c
new file mode 100644
index 000000000000..f89a8267b0c7
--- /dev/null
+++ b/test/CodeGen/bittest-intrin.c
@@ -0,0 +1,135 @@
+// RUN: %clang_cc1 -fms-extensions -triple x86_64-windows-msvc %s -emit-llvm -o - | FileCheck %s --check-prefix=X64
+// RUN: %clang_cc1 -fms-extensions -triple thumbv7-windows-msvc %s -emit-llvm -o - | FileCheck %s --check-prefix=ARM
+// RUN: %clang_cc1 -fms-extensions -triple aarch64-windows-msvc %s -emit-llvm -o - | FileCheck %s --check-prefix=ARM
+
+volatile unsigned char sink = 0;
+void test32(long *base, long idx) {
+ sink = _bittest(base, idx);
+ sink = _bittestandcomplement(base, idx);
+ sink = _bittestandreset(base, idx);
+ sink = _bittestandset(base, idx);
+ sink = _interlockedbittestandreset(base, idx);
+ sink = _interlockedbittestandset(base, idx);
+ sink = _interlockedbittestandset(base, idx);
+}
+
+void test64(__int64 *base, __int64 idx) {
+ sink = _bittest64(base, idx);
+ sink = _bittestandcomplement64(base, idx);
+ sink = _bittestandreset64(base, idx);
+ sink = _bittestandset64(base, idx);
+ sink = _interlockedbittestandreset64(base, idx);
+ sink = _interlockedbittestandset64(base, idx);
+}
+
+#if defined(_M_ARM) || defined(_M_ARM64)
+void test_arm(long *base, long idx) {
+ sink = _interlockedbittestandreset_acq(base, idx);
+ sink = _interlockedbittestandreset_rel(base, idx);
+ sink = _interlockedbittestandreset_nf(base, idx);
+ sink = _interlockedbittestandset_acq(base, idx);
+ sink = _interlockedbittestandset_rel(base, idx);
+ sink = _interlockedbittestandset_nf(base, idx);
+}
+#endif
+
+// X64-LABEL: define dso_local void @test32(i32* %base, i32 %idx)
+// X64: call i8 asm sideeffect "btl $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i32* %{{.*}}, i32 {{.*}})
+// X64: call i8 asm sideeffect "btcl $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i32* %{{.*}}, i32 {{.*}})
+// X64: call i8 asm sideeffect "btrl $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i32* %{{.*}}, i32 {{.*}})
+// X64: call i8 asm sideeffect "btsl $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i32* %{{.*}}, i32 {{.*}})
+// X64: call i8 asm sideeffect "lock btrl $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i32* %{{.*}}, i32 {{.*}})
+// X64: call i8 asm sideeffect "lock btsl $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i32* %{{.*}}, i32 {{.*}})
+
+// X64-LABEL: define dso_local void @test64(i64* %base, i64 %idx)
+// X64: call i8 asm sideeffect "btq $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i64* %{{.*}}, i64 {{.*}})
+// X64: call i8 asm sideeffect "btcq $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i64* %{{.*}}, i64 {{.*}})
+// X64: call i8 asm sideeffect "btrq $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i64* %{{.*}}, i64 {{.*}})
+// X64: call i8 asm sideeffect "btsq $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i64* %{{.*}}, i64 {{.*}})
+// X64: call i8 asm sideeffect "lock btrq $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i64* %{{.*}}, i64 {{.*}})
+// X64: call i8 asm sideeffect "lock btsq $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i64* %{{.*}}, i64 {{.*}})
+
+// ARM-LABEL: define dso_local {{.*}}void @test32(i32* %base, i32 %idx)
+// ARM: %[[IDXHI:[^ ]*]] = ashr i32 %{{.*}}, 3
+// ARM: %[[BASE:[^ ]*]] = bitcast i32* %{{.*}} to i8*
+// ARM: %[[BYTEADDR:[^ ]*]] = getelementptr inbounds i8, i8* %[[BASE]], i32 %[[IDXHI]]
+// ARM: %[[IDX8:[^ ]*]] = trunc i32 %{{.*}} to i8
+// ARM: %[[IDXLO:[^ ]*]] = and i8 %[[IDX8]], 7
+// ARM: %[[BYTE:[^ ]*]] = load i8, i8* %[[BYTEADDR]], align 1
+// ARM: %[[BYTESHR:[^ ]*]] = lshr i8 %[[BYTE]], %[[IDXLO]]
+// ARM: %[[RES:[^ ]*]] = and i8 %[[BYTESHR]], 1
+// ARM: store volatile i8 %[[RES]], i8* @sink, align 1
+
+// ARM: %[[IDXHI:[^ ]*]] = ashr i32 %{{.*}}, 3
+// ARM: %[[BASE:[^ ]*]] = bitcast i32* %{{.*}} to i8*
+// ARM: %[[BYTEADDR:[^ ]*]] = getelementptr inbounds i8, i8* %[[BASE]], i32 %[[IDXHI]]
+// ARM: %[[IDX8:[^ ]*]] = trunc i32 %{{.*}} to i8
+// ARM: %[[IDXLO:[^ ]*]] = and i8 %[[IDX8]], 7
+// ARM: %[[MASK:[^ ]*]] = shl i8 1, %[[IDXLO]]
+// ARM: %[[BYTE:[^ ]*]] = load i8, i8* %[[BYTEADDR]], align 1
+// ARM: %[[NEWBYTE:[^ ]*]] = xor i8 %[[BYTE]], %[[MASK]]
+// ARM store i8 %[[NEWBYTE]], i8* %[[BYTEADDR]], align 1
+// ARM: %[[BYTESHR:[^ ]*]] = lshr i8 %[[BYTE]], %[[IDXLO]]
+// ARM: %[[RES:[^ ]*]] = and i8 %[[BYTESHR]], 1
+// ARM: store volatile i8 %[[RES]], i8* @sink, align 1
+
+// ARM: %[[IDXHI:[^ ]*]] = ashr i32 %{{.*}}, 3
+// ARM: %[[BASE:[^ ]*]] = bitcast i32* %{{.*}} to i8*
+// ARM: %[[BYTEADDR:[^ ]*]] = getelementptr inbounds i8, i8* %[[BASE]], i32 %[[IDXHI]]
+// ARM: %[[IDX8:[^ ]*]] = trunc i32 %{{.*}} to i8
+// ARM: %[[IDXLO:[^ ]*]] = and i8 %[[IDX8]], 7
+// ARM: %[[MASK:[^ ]*]] = shl i8 1, %[[IDXLO]]
+// ARM: %[[BYTE:[^ ]*]] = load i8, i8* %[[BYTEADDR]], align 1
+// ARM: %[[NOTMASK:[^ ]*]] = xor i8 %[[MASK]], -1
+// ARM: %[[NEWBYTE:[^ ]*]] = and i8 %[[BYTE]], %[[NOTMASK]]
+// ARM store i8 %[[NEWBYTE]], i8* %[[BYTEADDR]], align 1
+// ARM: %[[BYTESHR:[^ ]*]] = lshr i8 %[[BYTE]], %[[IDXLO]]
+// ARM: %[[RES:[^ ]*]] = and i8 %[[BYTESHR]], 1
+// ARM: store volatile i8 %[[RES]], i8* @sink, align 1
+
+// ARM: %[[IDXHI:[^ ]*]] = ashr i32 %{{.*}}, 3
+// ARM: %[[BASE:[^ ]*]] = bitcast i32* %{{.*}} to i8*
+// ARM: %[[BYTEADDR:[^ ]*]] = getelementptr inbounds i8, i8* %[[BASE]], i32 %[[IDXHI]]
+// ARM: %[[IDX8:[^ ]*]] = trunc i32 %{{.*}} to i8
+// ARM: %[[IDXLO:[^ ]*]] = and i8 %[[IDX8]], 7
+// ARM: %[[MASK:[^ ]*]] = shl i8 1, %[[IDXLO]]
+// ARM: %[[BYTE:[^ ]*]] = load i8, i8* %[[BYTEADDR]], align 1
+// ARM: %[[NEWBYTE:[^ ]*]] = or i8 %[[BYTE]], %[[MASK]]
+// ARM store i8 %[[NEWBYTE]], i8* %[[BYTEADDR]], align 1
+// ARM: %[[BYTESHR:[^ ]*]] = lshr i8 %[[BYTE]], %[[IDXLO]]
+// ARM: %[[RES:[^ ]*]] = and i8 %[[BYTESHR]], 1
+// ARM: store volatile i8 %[[RES]], i8* @sink, align 1
+
+// ARM: %[[IDXHI:[^ ]*]] = ashr i32 %{{.*}}, 3
+// ARM: %[[BASE:[^ ]*]] = bitcast i32* %{{.*}} to i8*
+// ARM: %[[BYTEADDR:[^ ]*]] = getelementptr inbounds i8, i8* %[[BASE]], i32 %[[IDXHI]]
+// ARM: %[[IDX8:[^ ]*]] = trunc i32 %{{.*}} to i8
+// ARM: %[[IDXLO:[^ ]*]] = and i8 %[[IDX8]], 7
+// ARM: %[[MASK:[^ ]*]] = shl i8 1, %[[IDXLO]]
+// ARM: %[[NOTMASK:[^ ]*]] = xor i8 %[[MASK]], -1
+// ARM: %[[BYTE:[^ ]*]] = atomicrmw and i8* %[[BYTEADDR]], i8 %[[NOTMASK]] seq_cst
+// ARM: %[[BYTESHR:[^ ]*]] = lshr i8 %[[BYTE]], %[[IDXLO]]
+// ARM: %[[RES:[^ ]*]] = and i8 %[[BYTESHR]], 1
+// ARM: store volatile i8 %[[RES]], i8* @sink, align 1
+
+// ARM: %[[IDXHI:[^ ]*]] = ashr i32 %{{.*}}, 3
+// ARM: %[[BASE:[^ ]*]] = bitcast i32* %{{.*}} to i8*
+// ARM: %[[BYTEADDR:[^ ]*]] = getelementptr inbounds i8, i8* %[[BASE]], i32 %[[IDXHI]]
+// ARM: %[[IDX8:[^ ]*]] = trunc i32 %{{.*}} to i8
+// ARM: %[[IDXLO:[^ ]*]] = and i8 %[[IDX8]], 7
+// ARM: %[[MASK:[^ ]*]] = shl i8 1, %[[IDXLO]]
+// ARM: %[[BYTE:[^ ]*]] = atomicrmw or i8* %[[BYTEADDR]], i8 %[[MASK]] seq_cst
+// ARM: %[[BYTESHR:[^ ]*]] = lshr i8 %[[BYTE]], %[[IDXLO]]
+// ARM: %[[RES:[^ ]*]] = and i8 %[[BYTESHR]], 1
+// ARM: store volatile i8 %[[RES]], i8* @sink, align 1
+
+
+// Just look for the atomicrmw instructions.
+
+// ARM-LABEL: define dso_local {{.*}}void @test_arm(i32* %base, i32 %idx)
+// ARM: atomicrmw and i8* %{{.*}}, i8 {{.*}} acquire
+// ARM: atomicrmw and i8* %{{.*}}, i8 {{.*}} release
+// ARM: atomicrmw and i8* %{{.*}}, i8 {{.*}} monotonic
+// ARM: atomicrmw or i8* %{{.*}}, i8 {{.*}} acquire
+// ARM: atomicrmw or i8* %{{.*}}, i8 {{.*}} release
+// ARM: atomicrmw or i8* %{{.*}}, i8 {{.*}} monotonic
diff --git a/test/CodeGen/block-byref-aggr.c b/test/CodeGen/block-byref-aggr.c
index 7d146a2d4777..962f100638f0 100644
--- a/test/CodeGen/block-byref-aggr.c
+++ b/test/CodeGen/block-byref-aggr.c
@@ -24,7 +24,7 @@ void test0() {
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[BYREF]], [[BYREF]]* [[T0]], i32 0, i32 4
// CHECK-NEXT: [[T2:%.*]] = bitcast [[AGG]]* [[T1]] to i8*
// CHECK-NEXT: [[T3:%.*]] = bitcast [[AGG]]* [[TEMP]] to i8*
-// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T2]], i8* [[T3]], i64 4, i32 4, i1 false)
+// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[T2]], i8* align 4 [[T3]], i64 4, i1 false)
// Verify that there's nothing else significant in the function.
// CHECK-NEXT: [[T0:%.*]] = bitcast [[BYREF]]* [[A]] to i8*
// CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8)
@@ -50,14 +50,14 @@ void test1() {
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[B_BYREF]], [[B_BYREF]]* [[T0]], i32 0, i32 4
// CHECK-NEXT: [[T2:%.*]] = bitcast [[AGG]]* [[T1]] to i8*
// CHECK-NEXT: [[T3:%.*]] = bitcast [[AGG]]* [[TEMP]] to i8*
-// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T2]], i8* [[T3]], i64 4, i32 4, i1 false)
+// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[T2]], i8* align 4 [[T3]], i64 4, i1 false)
// Then for 'a':
// CHECK-NEXT: [[A_FORWARDING:%.*]] = getelementptr inbounds [[A_BYREF]], [[A_BYREF]]* [[A]], i32 0, i32 1
// CHECK-NEXT: [[T0:%.*]] = load [[A_BYREF]]*, [[A_BYREF]]** [[A_FORWARDING]]
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[A_BYREF]], [[A_BYREF]]* [[T0]], i32 0, i32 4
// CHECK-NEXT: [[T2:%.*]] = bitcast [[AGG]]* [[T1]] to i8*
// CHECK-NEXT: [[T3:%.*]] = bitcast [[AGG]]* [[TEMP]] to i8*
-// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T2]], i8* [[T3]], i64 4, i32 4, i1 false)
+// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[T2]], i8* align 4 [[T3]], i64 4, i1 false)
// Verify that there's nothing else significant in the function.
// CHECK-NEXT: [[T0:%.*]] = bitcast [[B_BYREF]]* [[B]] to i8*
// CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8)
diff --git a/test/CodeGen/blocks-windows.c b/test/CodeGen/blocks-windows.c
index ced00ef015fc..2dd97ffdd2f3 100644
--- a/test/CodeGen/blocks-windows.c
+++ b/test/CodeGen/blocks-windows.c
@@ -67,8 +67,8 @@ int (*g(void))(void) {
return _Block_copy(^{ ++i; return i; });
}
-// CHECK-BLOCKS-IN-BLOCKS-DECL: @_NSConcreteStackBlock = external dllexport global i8*
-// CHECK-BLOCKS-IN-BLOCKS-DEFN: @_NSConcreteStackBlock = common dllexport global [5 x i32]
+// CHECK-BLOCKS-IN-BLOCKS-DECL: @_NSConcreteStackBlock = external dso_local dllexport global i8*
+// CHECK-BLOCKS-IN-BLOCKS-DEFN: @_NSConcreteStackBlock = common dso_local dllexport global [5 x i32]
// CHECK-BLOCKS-NOT-IN-BLOCKS: @_NSConcreteStackBlock = external dllimport global i8*
// CHECK-BLOCKS-NOT-IN-BLOCKS-EXTERN: @_NSConcreteStackBlock = external dllimport global i8*
// CHECK-BLOCKS-NOT-IN-BLOCKS-EXTERN-DLLIMPORT: @_NSConcreteStackBlock = external dllimport global i8*
diff --git a/test/CodeGen/bmi-builtins.c b/test/CodeGen/bmi-builtins.c
index f78e3fdd4a17..91271f0b3599 100644
--- a/test/CodeGen/bmi-builtins.c
+++ b/test/CodeGen/bmi-builtins.c
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +bmi -emit-llvm -o - -Wall -Werror | FileCheck %s
-#include <x86intrin.h>
+#include <immintrin.h>
// NOTE: This should match the tests in llvm/test/CodeGen/X86/bmi-intrinsics-fast-isel.ll
diff --git a/test/CodeGen/bmi2-builtins.c b/test/CodeGen/bmi2-builtins.c
index 3a5d5e756ddb..9cce92474c85 100644
--- a/test/CodeGen/bmi2-builtins.c
+++ b/test/CodeGen/bmi2-builtins.c
@@ -2,7 +2,7 @@
// RUN: %clang_cc1 -ffreestanding %s -triple=i386-apple-darwin -target-feature +bmi2 -emit-llvm -o - | FileCheck %s --check-prefix=B32
-#include <x86intrin.h>
+#include <immintrin.h>
unsigned int test_bzhi_u32(unsigned int __X, unsigned int __Y) {
// CHECK: @llvm.x86.bmi.bzhi.32
diff --git a/test/CodeGen/builtin-abs.c b/test/CodeGen/builtin-abs.c
new file mode 100644
index 000000000000..791395368a8c
--- /dev/null
+++ b/test/CodeGen/builtin-abs.c
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck %s
+
+int absi(int x) {
+// CHECK-LABEL: @absi(
+// CHECK: [[NEG:%.*]] = sub nsw i32 0, [[X:%.*]]
+// CHECK: [[CMP:%.*]] = icmp slt i32 [[X]], 0
+// CHECK: [[SEL:%.*]] = select i1 [[CMP]], i32 [[NEG]], i32 [[X]]
+//
+ return __builtin_abs(x);
+}
+
+long absl(long x) {
+// CHECK-LABEL: @absl(
+// CHECK: [[NEG:%.*]] = sub nsw i64 0, [[X:%.*]]
+// CHECK: [[CMP:%.*]] = icmp slt i64 [[X]], 0
+// CHECK: [[SEL:%.*]] = select i1 [[CMP]], i64 [[NEG]], i64 [[X]]
+//
+ return __builtin_labs(x);
+}
+
+long long absll(long long x) {
+// CHECK-LABEL: @absll(
+// CHECK: [[NEG:%.*]] = sub nsw i64 0, [[X:%.*]]
+// CHECK: [[CMP:%.*]] = icmp slt i64 [[X]], 0
+// CHECK: [[SEL:%.*]] = select i1 [[CMP]], i64 [[NEG]], i64 [[X]]
+//
+ return __builtin_llabs(x);
+}
+
diff --git a/test/CodeGen/builtin-clflushopt.c b/test/CodeGen/builtin-clflushopt.c
index f82ac4638f40..4bf6f7efcc1f 100644
--- a/test/CodeGen/builtin-clflushopt.c
+++ b/test/CodeGen/builtin-clflushopt.c
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 %s -ffreestanding -triple=x86_64-apple-darwin -target-feature +clflushopt -emit-llvm -o - -Wall -Werror | FileCheck %s
-#include <x86intrin.h>
+#include <immintrin.h>
void test_mm_clflushopt(char * __m) {
//CHECK-LABEL: @test_mm_clflushopt
diff --git a/test/CodeGen/builtin-clwb.c b/test/CodeGen/builtin-clwb.c
index 96d00a6a7ca1..11c37c17694c 100644
--- a/test/CodeGen/builtin-clwb.c
+++ b/test/CodeGen/builtin-clwb.c
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 %s -ffreestanding -triple=x86_64-apple-darwin -target-feature +clwb -emit-llvm -o - -Wall -Werror | FileCheck %s
-#include <x86intrin.h>
+#include <immintrin.h>
void test_mm_clwb(const void *__m) {
//CHECK-LABEL: @test_mm_clwb
diff --git a/test/CodeGen/builtin-memfns.c b/test/CodeGen/builtin-memfns.c
index 4a06160ccbc6..d93a5aadae27 100644
--- a/test/CodeGen/builtin-memfns.c
+++ b/test/CodeGen/builtin-memfns.c
@@ -54,14 +54,14 @@ int test6(char *X) {
int test7(int *p) {
struct snd_pcm_hw_params_t* hwparams; // incomplete type.
- // CHECK: call void @llvm.memset{{.*}}256, i32 4, i1 false)
+ // CHECK: call void @llvm.memset{{.*}} align 4 {{.*}}256, i1 false)
__builtin_memset(p, 0, 256); // Should be alignment = 4
- // CHECK: call void @llvm.memset{{.*}}256, i32 1, i1 false)
+ // CHECK: call void @llvm.memset{{.*}} align 1 {{.*}}256, i1 false)
__builtin_memset((char*)p, 0, 256); // Should be alignment = 1
__builtin_memset(hwparams, 0, 256); // No crash alignment = 1
- // CHECK: call void @llvm.memset{{.*}}256, i32 1, i1 false)
+ // CHECK: call void @llvm.memset{{.*}} align 1{{.*}}256, i1 false)
}
// <rdar://problem/11314941>
@@ -73,13 +73,13 @@ struct PS {
struct PS ps;
void test8(int *arg) {
// CHECK: @test8
- // CHECK: call void @llvm.memcpy{{.*}} 16, i32 1, i1 false)
+ // CHECK: call void @llvm.memcpy{{.*}} align 4 {{.*}} align 1 {{.*}} 16, i1 false)
__builtin_memcpy(arg, ps.modes, sizeof(struct PS));
}
__attribute((aligned(16))) int x[4], y[4];
void test9() {
// CHECK: @test9
- // CHECK: call void @llvm.memcpy{{.*}} 16, i32 16, i1 false)
+ // CHECK: call void @llvm.memcpy{{.*}} align 16 {{.*}} align 16 {{.*}} 16, i1 false)
__builtin_memcpy(x, y, sizeof(y));
}
diff --git a/test/CodeGen/builtin-movdir.c b/test/CodeGen/builtin-movdir.c
new file mode 100644
index 000000000000..958690469a80
--- /dev/null
+++ b/test/CodeGen/builtin-movdir.c
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -ffreestanding -Wall -pedantic -triple x86_64-unknown-unknown -target-feature +movdiri -target-feature +movdir64b %s -emit-llvm -o - | FileCheck %s --check-prefix=X86_64 --check-prefix=CHECK
+// RUN: %clang_cc1 -ffreestanding -Wall -pedantic -triple i386-unknown-unknown -target-feature +movdiri -target-feature +movdir64b %s -emit-llvm -o - | FileCheck %s --check-prefix=X86 --check-prefix=CHECK
+
+#include <immintrin.h>
+#include <stdint.h>
+
+void test_directstore32(void *dst, uint32_t value) {
+ // CHECK-LABEL: test_directstore32
+ // CHECK: call void @llvm.x86.directstore32
+ _directstoreu_u32(dst, value);
+}
+
+#ifdef __x86_64__
+
+void test_directstore64(void *dst, uint64_t value) {
+ // X86_64-LABEL: test_directstore64
+ // X86_64: call void @llvm.x86.directstore64
+ _directstoreu_u64(dst, value);
+}
+
+#endif
+
+void test_dir64b(void *dst, const void *src) {
+ // CHECK-LABEL: test_dir64b
+ // CHECK: [[PTRINT1:%.+]] = ptrtoint
+ // X86: [[MASKEDPTR1:%.+]] = and i32 [[PTRINT1]], 63
+ // X86: [[MASKCOND1:%.+]] = icmp eq i32 [[MASKEDPTR1]], 0
+ // X86_64: [[MASKEDPTR1:%.+]] = and i64 [[PTRINT1]], 63
+ // X86_64: [[MASKCOND1:%.+]] = icmp eq i64 [[MASKEDPTR1]], 0
+ // CHECK: call void @llvm.x86.movdir64b
+ _movdir64b(dst, src);
+}
+
+// CHECK: declare void @llvm.x86.directstore32(i8*, i32)
+// X86_64: declare void @llvm.x86.directstore64(i8*, i64)
+// CHECK: declare void @llvm.x86.movdir64b(i8*, i8*)
diff --git a/test/CodeGen/builtin-wbinvd.c b/test/CodeGen/builtin-wbinvd.c
new file mode 100644
index 000000000000..fe5ad58ca2f3
--- /dev/null
+++ b/test/CodeGen/builtin-wbinvd.c
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 %s -ffreestanding -triple=x86_64-unknown-unknown -emit-llvm -o - -Wall -Werror | FileCheck %s
+// RUN: %clang_cc1 %s -ffreestanding -triple=i386-unknown-unknown -emit-llvm -o - -Wall -Werror | FileCheck %s
+
+#include <x86intrin.h>
+
+void test_wbinvd(void) {
+ //CHECK-LABEL: @test_wbinvd
+ //CHECK: call void @llvm.x86.wbinvd()
+ _wbinvd();
+}
diff --git a/test/CodeGen/builtin-wbnoinvd.c b/test/CodeGen/builtin-wbnoinvd.c
new file mode 100644
index 000000000000..5bea5acf5b09
--- /dev/null
+++ b/test/CodeGen/builtin-wbnoinvd.c
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 %s -ffreestanding -triple=x86_64-unknown-unknown -target-feature +wbnoinvd -emit-llvm -o - -Wall -Werror | FileCheck %s
+
+#include <immintrin.h>
+
+void test_wbnoinvd(void) {
+ //CHECK-LABEL: @test_wbnoinvd
+ //CHECK: call void @llvm.x86.wbnoinvd()
+ _wbnoinvd();
+}
diff --git a/test/CodeGen/builtins-arm.c b/test/CodeGen/builtins-arm.c
index e04349f1a38a..020f2b4dc528 100644
--- a/test/CodeGen/builtins-arm.c
+++ b/test/CodeGen/builtins-arm.c
@@ -8,69 +8,85 @@ void *f0()
}
void f1(char *a, char *b) {
+ // CHECK: call {{.*}} @__clear_cache
__clear_cache(a,b);
}
-// CHECK: call {{.*}} @__clear_cache
+float test_vcvtrf0(float f) {
+ // CHECK: call float @llvm.arm.vcvtr.f32(float %f)
+ return __builtin_arm_vcvtr_f(f, 0);
+}
+
+float test_vcvtrf1(float f) {
+ // CHECK: call float @llvm.arm.vcvtru.f32(float %f)
+ return __builtin_arm_vcvtr_f(f, 1);
+}
+
+double test_vcvtrd0(double d) {
+ // CHECK: call float @llvm.arm.vcvtr.f64(double %d)
+ return __builtin_arm_vcvtr_d(d, 0);
+}
+
+double test_vcvtrd1(double d) {
+ // call float @llvm.arm.vcvtru.f64(double %d)
+ return __builtin_arm_vcvtr_d(d, 1);
+}
void test_eh_return_data_regno()
{
+ // CHECK: store volatile i32 0
+ // CHECK: store volatile i32 1
volatile int res;
- res = __builtin_eh_return_data_regno(0); // CHECK: store volatile i32 0
- res = __builtin_eh_return_data_regno(1); // CHECK: store volatile i32 1
+ res = __builtin_eh_return_data_regno(0);
+ res = __builtin_eh_return_data_regno(1);
}
void nop() {
+ // CHECK: call {{.*}} @llvm.arm.hint(i32 0)
__builtin_arm_nop();
}
-// CHECK: call {{.*}} @llvm.arm.hint(i32 0)
-
void yield() {
+ // CHECK: call {{.*}} @llvm.arm.hint(i32 1)
__builtin_arm_yield();
}
-// CHECK: call {{.*}} @llvm.arm.hint(i32 1)
-
void wfe() {
+ // CHECK: call {{.*}} @llvm.arm.hint(i32 2)
__builtin_arm_wfe();
}
-// CHECK: call {{.*}} @llvm.arm.hint(i32 2)
-
void wfi() {
+ // CHECK: call {{.*}} @llvm.arm.hint(i32 3)
__builtin_arm_wfi();
}
-// CHECK: call {{.*}} @llvm.arm.hint(i32 3)
-
void sev() {
+ // CHECK: call {{.*}} @llvm.arm.hint(i32 4)
__builtin_arm_sev();
}
-// CHECK: call {{.*}} @llvm.arm.hint(i32 4)
-
void sevl() {
+ // CHECK: call {{.*}} @llvm.arm.hint(i32 5)
__builtin_arm_sevl();
}
-// CHECK: call {{.*}} @llvm.arm.hint(i32 5)
-
void dbg() {
+ // CHECK: call {{.*}} @llvm.arm.dbg(i32 0)
__builtin_arm_dbg(0);
}
-// CHECK: call {{.*}} @llvm.arm.dbg(i32 0)
-
void test_barrier() {
- __builtin_arm_dmb(1); //CHECK: call {{.*}} @llvm.arm.dmb(i32 1)
- __builtin_arm_dsb(2); //CHECK: call {{.*}} @llvm.arm.dsb(i32 2)
- __builtin_arm_isb(3); //CHECK: call {{.*}} @llvm.arm.isb(i32 3)
+ //CHECK: call {{.*}} @llvm.arm.dmb(i32 1)
+ //CHECK: call {{.*}} @llvm.arm.dsb(i32 2)
+ //CHECK: call {{.*}} @llvm.arm.isb(i32 3)
+ __builtin_arm_dmb(1);
+ __builtin_arm_dsb(2);
+ __builtin_arm_isb(3);
}
-// CHECK: call {{.*}} @llvm.bitreverse.i32(i32 %a)
-
unsigned rbit(unsigned a) {
+ // CHECK: call {{.*}} @llvm.bitreverse.i32(i32 %a)
return __builtin_arm_rbit(a);
}
diff --git a/test/CodeGen/builtins-hexagon-circ.c b/test/CodeGen/builtins-hexagon-circ.c
new file mode 100644
index 000000000000..dc8f5a693fe3
--- /dev/null
+++ b/test/CodeGen/builtins-hexagon-circ.c
@@ -0,0 +1,156 @@
+// REQUIRES: hexagon-registered-target
+// RUN: %clang_cc1 -triple hexagon-unknown-elf -emit-llvm %s -o - | FileCheck %s
+
+// CHECK-LABEL: test1
+// CHECK: @llvm.hexagon.L2.loadrub.pci
+unsigned char test1(int mod, void *start) {
+ unsigned char *base = start;
+ return __builtin_HEXAGON_L2_loadrub_pci(&base, 4, mod, start);
+}
+
+// CHECK-LABEL: test2
+// CHECK: @llvm.hexagon.L2.loadrb.pci
+unsigned char test2(int mod, void *start) {
+ char *base = start;
+ return __builtin_HEXAGON_L2_loadrb_pci(&base, 4, mod, start);
+}
+
+// CHECK-LABEL: test3
+// CHECK: @llvm.hexagon.L2.loadruh.pci
+unsigned short test3(int mod, void *start) {
+ unsigned short *base = start;
+ return __builtin_HEXAGON_L2_loadruh_pci(&base, 4, mod, start);
+}
+
+// CHECK-LABEL: test4
+// CHECK: @llvm.hexagon.L2.loadrh.pci
+short test4(int mod, void *start) {
+ short *base = start;
+ return __builtin_HEXAGON_L2_loadrh_pci(&base, 4, mod, start);
+}
+
+// CHECK-LABEL: test5
+// CHECK: @llvm.hexagon.L2.loadri.pci
+int test5(int mod, void *start) {
+ int *base = start;
+ return __builtin_HEXAGON_L2_loadri_pci(&base, 4, mod, start);
+}
+
+// CHECK-LABEL: test6
+// CHECK: @llvm.hexagon.L2.loadrd.pci
+long long test6(int mod, void *start) {
+ long long *base = start;
+ return __builtin_HEXAGON_L2_loadrd_pci(&base, 8, mod, start);
+}
+
+// CHECK-LABEL: test7
+// CHECK: @llvm.hexagon.L2.loadrub.pcr
+unsigned char test7(int mod, void *start) {
+ unsigned char *base = start;
+ return __builtin_HEXAGON_L2_loadrub_pcr(&base, mod, start);
+}
+
+// CHECK-LABEL: test8
+// CHECK: @llvm.hexagon.L2.loadrb.pcr
+unsigned char test8(int mod, void *start) {
+ char *base = start;
+ return __builtin_HEXAGON_L2_loadrb_pcr(&base, mod, start);
+}
+
+// CHECK-LABEL: test9
+// CHECK: @llvm.hexagon.L2.loadruh.pcr
+unsigned short test9(int mod, void *start) {
+ unsigned short *base = start;
+ return __builtin_HEXAGON_L2_loadruh_pcr(&base, mod, start);
+}
+
+// CHECK-LABEL: test10
+// CHECK: @llvm.hexagon.L2.loadrh.pcr
+short test10(int mod, void *start) {
+ short *base = start;
+ return __builtin_HEXAGON_L2_loadrh_pcr(&base, mod, start);
+}
+
+// CHECK-LABEL: test11
+// CHECK: @llvm.hexagon.L2.loadri.pcr
+int test11(int mod, void *start) {
+ int *base = start;
+ return __builtin_HEXAGON_L2_loadri_pcr(&base, mod, start);
+}
+
+// CHECK-LABEL: test12
+// CHECK: @llvm.hexagon.L2.loadrd.pcr
+long long test12(int mod, void *start) {
+ long long *base = start;
+ return __builtin_HEXAGON_L2_loadrd_pcr(&base, mod, start);
+}
+
+// CHECK-LABEL: test13
+// CHECK: @llvm.hexagon.S2.storerb.pci
+void test13(int mod, void *start, char v) {
+ void *base = start;
+ __builtin_HEXAGON_S2_storerb_pci(&base, 4, mod, v, start);
+}
+
+// CHECK-LABEL: test14
+// CHECK: @llvm.hexagon.S2.storerh.pci
+void test14(int mod, void *start, short v) {
+ void *base = start;
+ __builtin_HEXAGON_S2_storerh_pci(&base, 4, mod, v, start);
+}
+
+// CHECK-LABEL: test15
+// CHECK: @llvm.hexagon.S2.storerf.pci
+void test15(int mod, void *start, short v) {
+ void *base = start;
+ __builtin_HEXAGON_S2_storerf_pci(&base, 4, mod, v, start);
+}
+
+// CHECK-LABEL: test16
+// CHECK: @llvm.hexagon.S2.storeri.pci
+void test16(int mod, void *start, int v) {
+ void *base = start;
+ __builtin_HEXAGON_S2_storeri_pci(&base, 4, mod, v, start);
+}
+
+// CHECK-LABEL: test17
+// CHECK: @llvm.hexagon.S2.storerd.pci
+void test17(int mod, void *start, long long v) {
+ void *base = start;
+ __builtin_HEXAGON_S2_storerd_pci(&base, 8, mod, v, start);
+}
+
+// CHECK-LABEL: test18
+// CHECK: @llvm.hexagon.S2.storerb.pcr
+void test18(int mod, void *start, char v) {
+ void *base = start;
+ __builtin_HEXAGON_S2_storerb_pcr(&base, mod, v, start);
+}
+
+// CHECK-LABEL: test19
+// CHECK: @llvm.hexagon.S2.storerh.pcr
+void test19(int mod, void *start, short v) {
+ void *base = start;
+ __builtin_HEXAGON_S2_storerh_pcr(&base, mod, v, start);
+}
+
+// CHECK-LABEL: test20
+// CHECK: @llvm.hexagon.S2.storerf.pcr
+void test20(int mod, void *start, short v) {
+ void *base = start;
+ __builtin_HEXAGON_S2_storerf_pcr(&base, mod, v, start);
+}
+
+// CHECK-LABEL: test21
+// CHECK: @llvm.hexagon.S2.storeri.pcr
+void test21(int mod, void *start, int v) {
+ void *base = start;
+ __builtin_HEXAGON_S2_storeri_pcr(&base, mod, v, start);
+}
+
+// CHECK-LABEL: test22
+// CHECK: @llvm.hexagon.S2.storerd.pcr
+void test22(int mod, void *start, long long v) {
+ void *base = start;
+ __builtin_HEXAGON_S2_storerd_pcr(&base, mod, v, start);
+}
diff --git a/test/CodeGen/builtins-hexagon.c b/test/CodeGen/builtins-hexagon.c
index 22835a23f292..b4c0642ef3c1 100644
--- a/test/CodeGen/builtins-hexagon.c
+++ b/test/CodeGen/builtins-hexagon.c
@@ -1,5 +1,5 @@
// REQUIRES: hexagon-registered-target
-// RUN: %clang_cc1 -triple hexagon-unknown-elf -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple hexagon-unknown-elf -target-cpu hexagonv65 -target-feature +hvxv65 -emit-llvm %s -o - | FileCheck %s
void test() {
int v64 __attribute__((__vector_size__(64)));
@@ -1722,1594 +1722,6 @@ void test() {
__builtin_HEXAGON_S6_vtrunehb_ppp(0, 0);
// CHECK: @llvm.hexagon.S6.vtrunohb.ppp
__builtin_HEXAGON_S6_vtrunohb_ppp(0, 0);
- // CHECK: @llvm.hexagon.V6.extractw
- __builtin_HEXAGON_V6_extractw(v64, 0);
- // CHECK: @llvm.hexagon.V6.extractw.128B
- __builtin_HEXAGON_V6_extractw_128B(v128, 0);
- // CHECK: @llvm.hexagon.V6.hi
- __builtin_HEXAGON_V6_hi(v128);
- // CHECK: @llvm.hexagon.V6.hi.128B
- __builtin_HEXAGON_V6_hi_128B(v256);
- // CHECK: @llvm.hexagon.V6.lo
- __builtin_HEXAGON_V6_lo(v128);
- // CHECK: @llvm.hexagon.V6.lo.128B
- __builtin_HEXAGON_V6_lo_128B(v256);
- // CHECK: @llvm.hexagon.V6.lvsplatb
- __builtin_HEXAGON_V6_lvsplatb(0);
- // CHECK: @llvm.hexagon.V6.lvsplatb.128B
- __builtin_HEXAGON_V6_lvsplatb_128B(0);
- // CHECK: @llvm.hexagon.V6.lvsplath
- __builtin_HEXAGON_V6_lvsplath(0);
- // CHECK: @llvm.hexagon.V6.lvsplath.128B
- __builtin_HEXAGON_V6_lvsplath_128B(0);
- // CHECK: @llvm.hexagon.V6.lvsplatw
- __builtin_HEXAGON_V6_lvsplatw(0);
- // CHECK: @llvm.hexagon.V6.lvsplatw.128B
- __builtin_HEXAGON_V6_lvsplatw_128B(0);
- // CHECK: @llvm.hexagon.V6.pred.and
- __builtin_HEXAGON_V6_pred_and(v64, v64);
- // CHECK: @llvm.hexagon.V6.pred.and.128B
- __builtin_HEXAGON_V6_pred_and_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.pred.and.n
- __builtin_HEXAGON_V6_pred_and_n(v64, v64);
- // CHECK: @llvm.hexagon.V6.pred.and.n.128B
- __builtin_HEXAGON_V6_pred_and_n_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.pred.not
- __builtin_HEXAGON_V6_pred_not(v64);
- // CHECK: @llvm.hexagon.V6.pred.not.128B
- __builtin_HEXAGON_V6_pred_not_128B(v128);
- // CHECK: @llvm.hexagon.V6.pred.or
- __builtin_HEXAGON_V6_pred_or(v64, v64);
- // CHECK: @llvm.hexagon.V6.pred.or.128B
- __builtin_HEXAGON_V6_pred_or_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.pred.or.n
- __builtin_HEXAGON_V6_pred_or_n(v64, v64);
- // CHECK: @llvm.hexagon.V6.pred.or.n.128B
- __builtin_HEXAGON_V6_pred_or_n_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.pred.scalar2
- __builtin_HEXAGON_V6_pred_scalar2(0);
- // CHECK: @llvm.hexagon.V6.pred.scalar2.128B
- __builtin_HEXAGON_V6_pred_scalar2_128B(0);
- // CHECK: @llvm.hexagon.V6.pred.scalar2v2
- __builtin_HEXAGON_V6_pred_scalar2v2(0);
- // CHECK: @llvm.hexagon.V6.pred.scalar2v2.128B
- __builtin_HEXAGON_V6_pred_scalar2v2_128B(0);
- // CHECK: @llvm.hexagon.V6.pred.xor
- __builtin_HEXAGON_V6_pred_xor(v64, v64);
- // CHECK: @llvm.hexagon.V6.pred.xor.128B
- __builtin_HEXAGON_V6_pred_xor_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.shuffeqh
- __builtin_HEXAGON_V6_shuffeqh(v64, v64);
- // CHECK: @llvm.hexagon.V6.shuffeqh.128B
- __builtin_HEXAGON_V6_shuffeqh_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.shuffeqw
- __builtin_HEXAGON_V6_shuffeqw(v64, v64);
- // CHECK: @llvm.hexagon.V6.shuffeqw.128B
- __builtin_HEXAGON_V6_shuffeqw_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vS32b.nqpred.ai
- __builtin_HEXAGON_V6_vS32b_nqpred_ai(v64, 0, v64);
- // CHECK: @llvm.hexagon.V6.vS32b.nqpred.ai.128B
- __builtin_HEXAGON_V6_vS32b_nqpred_ai_128B(v128, 0, v128);
- // CHECK: @llvm.hexagon.V6.vS32b.nt.nqpred.ai
- __builtin_HEXAGON_V6_vS32b_nt_nqpred_ai(v64, 0, v64);
- // CHECK: @llvm.hexagon.V6.vS32b.nt.nqpred.ai.128B
- __builtin_HEXAGON_V6_vS32b_nt_nqpred_ai_128B(v128, 0, v128);
- // CHECK: @llvm.hexagon.V6.vS32b.nt.qpred.ai
- __builtin_HEXAGON_V6_vS32b_nt_qpred_ai(v64, 0, v64);
- // CHECK: @llvm.hexagon.V6.vS32b.nt.qpred.ai.128B
- __builtin_HEXAGON_V6_vS32b_nt_qpred_ai_128B(v128, 0, v128);
- // CHECK: @llvm.hexagon.V6.vS32b.qpred.ai
- __builtin_HEXAGON_V6_vS32b_qpred_ai(v64, 0, v64);
- // CHECK: @llvm.hexagon.V6.vS32b.qpred.ai.128B
- __builtin_HEXAGON_V6_vS32b_qpred_ai_128B(v128, 0, v128);
- // CHECK: @llvm.hexagon.V6.vabsb
- __builtin_HEXAGON_V6_vabsb(v64);
- // CHECK: @llvm.hexagon.V6.vabsb.128B
- __builtin_HEXAGON_V6_vabsb_128B(v128);
- // CHECK: @llvm.hexagon.V6.vabsb.sat
- __builtin_HEXAGON_V6_vabsb_sat(v64);
- // CHECK: @llvm.hexagon.V6.vabsb.sat.128B
- __builtin_HEXAGON_V6_vabsb_sat_128B(v128);
- // CHECK: @llvm.hexagon.V6.vabsdiffh
- __builtin_HEXAGON_V6_vabsdiffh(v64, v64);
- // CHECK: @llvm.hexagon.V6.vabsdiffh.128B
- __builtin_HEXAGON_V6_vabsdiffh_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vabsdiffub
- __builtin_HEXAGON_V6_vabsdiffub(v64, v64);
- // CHECK: @llvm.hexagon.V6.vabsdiffub.128B
- __builtin_HEXAGON_V6_vabsdiffub_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vabsdiffuh
- __builtin_HEXAGON_V6_vabsdiffuh(v64, v64);
- // CHECK: @llvm.hexagon.V6.vabsdiffuh.128B
- __builtin_HEXAGON_V6_vabsdiffuh_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vabsdiffw
- __builtin_HEXAGON_V6_vabsdiffw(v64, v64);
- // CHECK: @llvm.hexagon.V6.vabsdiffw.128B
- __builtin_HEXAGON_V6_vabsdiffw_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vabsh
- __builtin_HEXAGON_V6_vabsh(v64);
- // CHECK: @llvm.hexagon.V6.vabsh.128B
- __builtin_HEXAGON_V6_vabsh_128B(v128);
- // CHECK: @llvm.hexagon.V6.vabsh.sat
- __builtin_HEXAGON_V6_vabsh_sat(v64);
- // CHECK: @llvm.hexagon.V6.vabsh.sat.128B
- __builtin_HEXAGON_V6_vabsh_sat_128B(v128);
- // CHECK: @llvm.hexagon.V6.vabsw
- __builtin_HEXAGON_V6_vabsw(v64);
- // CHECK: @llvm.hexagon.V6.vabsw.128B
- __builtin_HEXAGON_V6_vabsw_128B(v128);
- // CHECK: @llvm.hexagon.V6.vabsw.sat
- __builtin_HEXAGON_V6_vabsw_sat(v64);
- // CHECK: @llvm.hexagon.V6.vabsw.sat.128B
- __builtin_HEXAGON_V6_vabsw_sat_128B(v128);
- // CHECK: @llvm.hexagon.V6.vaddb
- __builtin_HEXAGON_V6_vaddb(v64, v64);
- // CHECK: @llvm.hexagon.V6.vaddb.128B
- __builtin_HEXAGON_V6_vaddb_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vaddb.dv
- __builtin_HEXAGON_V6_vaddb_dv(v128, v128);
- // CHECK: @llvm.hexagon.V6.vaddb.dv.128B
- __builtin_HEXAGON_V6_vaddb_dv_128B(v256, v256);
- // CHECK: @llvm.hexagon.V6.vaddbnq
- __builtin_HEXAGON_V6_vaddbnq(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vaddbnq.128B
- __builtin_HEXAGON_V6_vaddbnq_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vaddbq
- __builtin_HEXAGON_V6_vaddbq(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vaddbq.128B
- __builtin_HEXAGON_V6_vaddbq_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vaddbsat
- __builtin_HEXAGON_V6_vaddbsat(v64, v64);
- // CHECK: @llvm.hexagon.V6.vaddbsat.128B
- __builtin_HEXAGON_V6_vaddbsat_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vaddbsat.dv
- __builtin_HEXAGON_V6_vaddbsat_dv(v128, v128);
- // CHECK: @llvm.hexagon.V6.vaddbsat.dv.128B
- __builtin_HEXAGON_V6_vaddbsat_dv_128B(v256, v256);
- // CHECK: @llvm.hexagon.V6.vaddcarry
- __builtin_HEXAGON_V6_vaddcarry(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vaddcarry.128B
- __builtin_HEXAGON_V6_vaddcarry_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vaddclbh
- __builtin_HEXAGON_V6_vaddclbh(v64, v64);
- // CHECK: @llvm.hexagon.V6.vaddclbh.128B
- __builtin_HEXAGON_V6_vaddclbh_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vaddclbw
- __builtin_HEXAGON_V6_vaddclbw(v64, v64);
- // CHECK: @llvm.hexagon.V6.vaddclbw.128B
- __builtin_HEXAGON_V6_vaddclbw_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vaddh
- __builtin_HEXAGON_V6_vaddh(v64, v64);
- // CHECK: @llvm.hexagon.V6.vaddh.128B
- __builtin_HEXAGON_V6_vaddh_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vaddh.dv
- __builtin_HEXAGON_V6_vaddh_dv(v128, v128);
- // CHECK: @llvm.hexagon.V6.vaddh.dv.128B
- __builtin_HEXAGON_V6_vaddh_dv_128B(v256, v256);
- // CHECK: @llvm.hexagon.V6.vaddhnq
- __builtin_HEXAGON_V6_vaddhnq(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vaddhnq.128B
- __builtin_HEXAGON_V6_vaddhnq_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vaddhq
- __builtin_HEXAGON_V6_vaddhq(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vaddhq.128B
- __builtin_HEXAGON_V6_vaddhq_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vaddhsat
- __builtin_HEXAGON_V6_vaddhsat(v64, v64);
- // CHECK: @llvm.hexagon.V6.vaddhsat.128B
- __builtin_HEXAGON_V6_vaddhsat_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vaddhsat.dv
- __builtin_HEXAGON_V6_vaddhsat_dv(v128, v128);
- // CHECK: @llvm.hexagon.V6.vaddhsat.dv.128B
- __builtin_HEXAGON_V6_vaddhsat_dv_128B(v256, v256);
- // CHECK: @llvm.hexagon.V6.vaddhw
- __builtin_HEXAGON_V6_vaddhw(v64, v64);
- // CHECK: @llvm.hexagon.V6.vaddhw.128B
- __builtin_HEXAGON_V6_vaddhw_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vaddhw.acc
- __builtin_HEXAGON_V6_vaddhw_acc(v128, v64, v64);
- // CHECK: @llvm.hexagon.V6.vaddhw.acc.128B
- __builtin_HEXAGON_V6_vaddhw_acc_128B(v256, v128, v128);
- // CHECK: @llvm.hexagon.V6.vaddubh
- __builtin_HEXAGON_V6_vaddubh(v64, v64);
- // CHECK: @llvm.hexagon.V6.vaddubh.128B
- __builtin_HEXAGON_V6_vaddubh_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vaddubh.acc
- __builtin_HEXAGON_V6_vaddubh_acc(v128, v64, v64);
- // CHECK: @llvm.hexagon.V6.vaddubh.acc.128B
- __builtin_HEXAGON_V6_vaddubh_acc_128B(v256, v128, v128);
- // CHECK: @llvm.hexagon.V6.vaddubsat
- __builtin_HEXAGON_V6_vaddubsat(v64, v64);
- // CHECK: @llvm.hexagon.V6.vaddubsat.128B
- __builtin_HEXAGON_V6_vaddubsat_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vaddubsat.dv
- __builtin_HEXAGON_V6_vaddubsat_dv(v128, v128);
- // CHECK: @llvm.hexagon.V6.vaddubsat.dv.128B
- __builtin_HEXAGON_V6_vaddubsat_dv_128B(v256, v256);
- // CHECK: @llvm.hexagon.V6.vaddububb.sat
- __builtin_HEXAGON_V6_vaddububb_sat(v64, v64);
- // CHECK: @llvm.hexagon.V6.vaddububb.sat.128B
- __builtin_HEXAGON_V6_vaddububb_sat_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vadduhsat
- __builtin_HEXAGON_V6_vadduhsat(v64, v64);
- // CHECK: @llvm.hexagon.V6.vadduhsat.128B
- __builtin_HEXAGON_V6_vadduhsat_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vadduhsat.dv
- __builtin_HEXAGON_V6_vadduhsat_dv(v128, v128);
- // CHECK: @llvm.hexagon.V6.vadduhsat.dv.128B
- __builtin_HEXAGON_V6_vadduhsat_dv_128B(v256, v256);
- // CHECK: @llvm.hexagon.V6.vadduhw
- __builtin_HEXAGON_V6_vadduhw(v64, v64);
- // CHECK: @llvm.hexagon.V6.vadduhw.128B
- __builtin_HEXAGON_V6_vadduhw_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vadduhw.acc
- __builtin_HEXAGON_V6_vadduhw_acc(v128, v64, v64);
- // CHECK: @llvm.hexagon.V6.vadduhw.acc.128B
- __builtin_HEXAGON_V6_vadduhw_acc_128B(v256, v128, v128);
- // CHECK: @llvm.hexagon.V6.vadduwsat
- __builtin_HEXAGON_V6_vadduwsat(v64, v64);
- // CHECK: @llvm.hexagon.V6.vadduwsat.128B
- __builtin_HEXAGON_V6_vadduwsat_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vadduwsat.dv
- __builtin_HEXAGON_V6_vadduwsat_dv(v128, v128);
- // CHECK: @llvm.hexagon.V6.vadduwsat.dv.128B
- __builtin_HEXAGON_V6_vadduwsat_dv_128B(v256, v256);
- // CHECK: @llvm.hexagon.V6.vaddw
- __builtin_HEXAGON_V6_vaddw(v64, v64);
- // CHECK: @llvm.hexagon.V6.vaddw.128B
- __builtin_HEXAGON_V6_vaddw_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vaddw.dv
- __builtin_HEXAGON_V6_vaddw_dv(v128, v128);
- // CHECK: @llvm.hexagon.V6.vaddw.dv.128B
- __builtin_HEXAGON_V6_vaddw_dv_128B(v256, v256);
- // CHECK: @llvm.hexagon.V6.vaddwnq
- __builtin_HEXAGON_V6_vaddwnq(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vaddwnq.128B
- __builtin_HEXAGON_V6_vaddwnq_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vaddwq
- __builtin_HEXAGON_V6_vaddwq(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vaddwq.128B
- __builtin_HEXAGON_V6_vaddwq_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vaddwsat
- __builtin_HEXAGON_V6_vaddwsat(v64, v64);
- // CHECK: @llvm.hexagon.V6.vaddwsat.128B
- __builtin_HEXAGON_V6_vaddwsat_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vaddwsat.dv
- __builtin_HEXAGON_V6_vaddwsat_dv(v128, v128);
- // CHECK: @llvm.hexagon.V6.vaddwsat.dv.128B
- __builtin_HEXAGON_V6_vaddwsat_dv_128B(v256, v256);
- // CHECK: @llvm.hexagon.V6.valignb
- __builtin_HEXAGON_V6_valignb(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.valignb.128B
- __builtin_HEXAGON_V6_valignb_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.valignbi
- __builtin_HEXAGON_V6_valignbi(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.valignbi.128B
- __builtin_HEXAGON_V6_valignbi_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vand
- __builtin_HEXAGON_V6_vand(v64, v64);
- // CHECK: @llvm.hexagon.V6.vand.128B
- __builtin_HEXAGON_V6_vand_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vandnqrt
- __builtin_HEXAGON_V6_vandnqrt(v64, 0);
- // CHECK: @llvm.hexagon.V6.vandnqrt.128B
- __builtin_HEXAGON_V6_vandnqrt_128B(v128, 0);
- // CHECK: @llvm.hexagon.V6.vandnqrt.acc
- __builtin_HEXAGON_V6_vandnqrt_acc(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vandnqrt.acc.128B
- __builtin_HEXAGON_V6_vandnqrt_acc_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vandqrt
- __builtin_HEXAGON_V6_vandqrt(v64, 0);
- // CHECK: @llvm.hexagon.V6.vandqrt.128B
- __builtin_HEXAGON_V6_vandqrt_128B(v128, 0);
- // CHECK: @llvm.hexagon.V6.vandqrt.acc
- __builtin_HEXAGON_V6_vandqrt_acc(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vandqrt.acc.128B
- __builtin_HEXAGON_V6_vandqrt_acc_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vandvnqv
- __builtin_HEXAGON_V6_vandvnqv(v64, v64);
- // CHECK: @llvm.hexagon.V6.vandvnqv.128B
- __builtin_HEXAGON_V6_vandvnqv_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vandvqv
- __builtin_HEXAGON_V6_vandvqv(v64, v64);
- // CHECK: @llvm.hexagon.V6.vandvqv.128B
- __builtin_HEXAGON_V6_vandvqv_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vandvrt
- __builtin_HEXAGON_V6_vandvrt(v64, 0);
- // CHECK: @llvm.hexagon.V6.vandvrt.128B
- __builtin_HEXAGON_V6_vandvrt_128B(v128, 0);
- // CHECK: @llvm.hexagon.V6.vandvrt.acc
- __builtin_HEXAGON_V6_vandvrt_acc(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vandvrt.acc.128B
- __builtin_HEXAGON_V6_vandvrt_acc_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vaslh
- __builtin_HEXAGON_V6_vaslh(v64, 0);
- // CHECK: @llvm.hexagon.V6.vaslh.128B
- __builtin_HEXAGON_V6_vaslh_128B(v128, 0);
- // CHECK: @llvm.hexagon.V6.vaslh.acc
- __builtin_HEXAGON_V6_vaslh_acc(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vaslh.acc.128B
- __builtin_HEXAGON_V6_vaslh_acc_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vaslhv
- __builtin_HEXAGON_V6_vaslhv(v64, v64);
- // CHECK: @llvm.hexagon.V6.vaslhv.128B
- __builtin_HEXAGON_V6_vaslhv_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vaslw
- __builtin_HEXAGON_V6_vaslw(v64, 0);
- // CHECK: @llvm.hexagon.V6.vaslw.128B
- __builtin_HEXAGON_V6_vaslw_128B(v128, 0);
- // CHECK: @llvm.hexagon.V6.vaslw.acc
- __builtin_HEXAGON_V6_vaslw_acc(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vaslw.acc.128B
- __builtin_HEXAGON_V6_vaslw_acc_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vaslwv
- __builtin_HEXAGON_V6_vaslwv(v64, v64);
- // CHECK: @llvm.hexagon.V6.vaslwv.128B
- __builtin_HEXAGON_V6_vaslwv_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vasrh
- __builtin_HEXAGON_V6_vasrh(v64, 0);
- // CHECK: @llvm.hexagon.V6.vasrh.128B
- __builtin_HEXAGON_V6_vasrh_128B(v128, 0);
- // CHECK: @llvm.hexagon.V6.vasrh.acc
- __builtin_HEXAGON_V6_vasrh_acc(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vasrh.acc.128B
- __builtin_HEXAGON_V6_vasrh_acc_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vasrhbrndsat
- __builtin_HEXAGON_V6_vasrhbrndsat(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vasrhbrndsat.128B
- __builtin_HEXAGON_V6_vasrhbrndsat_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vasrhbsat
- __builtin_HEXAGON_V6_vasrhbsat(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vasrhbsat.128B
- __builtin_HEXAGON_V6_vasrhbsat_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vasrhubrndsat
- __builtin_HEXAGON_V6_vasrhubrndsat(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vasrhubrndsat.128B
- __builtin_HEXAGON_V6_vasrhubrndsat_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vasrhubsat
- __builtin_HEXAGON_V6_vasrhubsat(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vasrhubsat.128B
- __builtin_HEXAGON_V6_vasrhubsat_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vasrhv
- __builtin_HEXAGON_V6_vasrhv(v64, v64);
- // CHECK: @llvm.hexagon.V6.vasrhv.128B
- __builtin_HEXAGON_V6_vasrhv_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vasruhubrndsat
- __builtin_HEXAGON_V6_vasruhubrndsat(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vasruhubrndsat.128B
- __builtin_HEXAGON_V6_vasruhubrndsat_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vasruhubsat
- __builtin_HEXAGON_V6_vasruhubsat(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vasruhubsat.128B
- __builtin_HEXAGON_V6_vasruhubsat_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vasruwuhrndsat
- __builtin_HEXAGON_V6_vasruwuhrndsat(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vasruwuhrndsat.128B
- __builtin_HEXAGON_V6_vasruwuhrndsat_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vasruwuhsat
- __builtin_HEXAGON_V6_vasruwuhsat(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vasruwuhsat.128B
- __builtin_HEXAGON_V6_vasruwuhsat_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vasrw
- __builtin_HEXAGON_V6_vasrw(v64, 0);
- // CHECK: @llvm.hexagon.V6.vasrw.128B
- __builtin_HEXAGON_V6_vasrw_128B(v128, 0);
- // CHECK: @llvm.hexagon.V6.vasrw.acc
- __builtin_HEXAGON_V6_vasrw_acc(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vasrw.acc.128B
- __builtin_HEXAGON_V6_vasrw_acc_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vasrwh
- __builtin_HEXAGON_V6_vasrwh(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vasrwh.128B
- __builtin_HEXAGON_V6_vasrwh_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vasrwhrndsat
- __builtin_HEXAGON_V6_vasrwhrndsat(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vasrwhrndsat.128B
- __builtin_HEXAGON_V6_vasrwhrndsat_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vasrwhsat
- __builtin_HEXAGON_V6_vasrwhsat(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vasrwhsat.128B
- __builtin_HEXAGON_V6_vasrwhsat_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vasrwuhrndsat
- __builtin_HEXAGON_V6_vasrwuhrndsat(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vasrwuhrndsat.128B
- __builtin_HEXAGON_V6_vasrwuhrndsat_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vasrwuhsat
- __builtin_HEXAGON_V6_vasrwuhsat(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vasrwuhsat.128B
- __builtin_HEXAGON_V6_vasrwuhsat_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vasrwv
- __builtin_HEXAGON_V6_vasrwv(v64, v64);
- // CHECK: @llvm.hexagon.V6.vasrwv.128B
- __builtin_HEXAGON_V6_vasrwv_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vassign
- __builtin_HEXAGON_V6_vassign(v64);
- // CHECK: @llvm.hexagon.V6.vassign.128B
- __builtin_HEXAGON_V6_vassign_128B(v128);
- // CHECK: @llvm.hexagon.V6.vassignp
- __builtin_HEXAGON_V6_vassignp(v128);
- // CHECK: @llvm.hexagon.V6.vassignp.128B
- __builtin_HEXAGON_V6_vassignp_128B(v256);
- // CHECK: @llvm.hexagon.V6.vavgb
- __builtin_HEXAGON_V6_vavgb(v64, v64);
- // CHECK: @llvm.hexagon.V6.vavgb.128B
- __builtin_HEXAGON_V6_vavgb_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vavgbrnd
- __builtin_HEXAGON_V6_vavgbrnd(v64, v64);
- // CHECK: @llvm.hexagon.V6.vavgbrnd.128B
- __builtin_HEXAGON_V6_vavgbrnd_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vavgh
- __builtin_HEXAGON_V6_vavgh(v64, v64);
- // CHECK: @llvm.hexagon.V6.vavgh.128B
- __builtin_HEXAGON_V6_vavgh_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vavghrnd
- __builtin_HEXAGON_V6_vavghrnd(v64, v64);
- // CHECK: @llvm.hexagon.V6.vavghrnd.128B
- __builtin_HEXAGON_V6_vavghrnd_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vavgub
- __builtin_HEXAGON_V6_vavgub(v64, v64);
- // CHECK: @llvm.hexagon.V6.vavgub.128B
- __builtin_HEXAGON_V6_vavgub_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vavgubrnd
- __builtin_HEXAGON_V6_vavgubrnd(v64, v64);
- // CHECK: @llvm.hexagon.V6.vavgubrnd.128B
- __builtin_HEXAGON_V6_vavgubrnd_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vavguh
- __builtin_HEXAGON_V6_vavguh(v64, v64);
- // CHECK: @llvm.hexagon.V6.vavguh.128B
- __builtin_HEXAGON_V6_vavguh_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vavguhrnd
- __builtin_HEXAGON_V6_vavguhrnd(v64, v64);
- // CHECK: @llvm.hexagon.V6.vavguhrnd.128B
- __builtin_HEXAGON_V6_vavguhrnd_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vavguw
- __builtin_HEXAGON_V6_vavguw(v64, v64);
- // CHECK: @llvm.hexagon.V6.vavguw.128B
- __builtin_HEXAGON_V6_vavguw_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vavguwrnd
- __builtin_HEXAGON_V6_vavguwrnd(v64, v64);
- // CHECK: @llvm.hexagon.V6.vavguwrnd.128B
- __builtin_HEXAGON_V6_vavguwrnd_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vavgw
- __builtin_HEXAGON_V6_vavgw(v64, v64);
- // CHECK: @llvm.hexagon.V6.vavgw.128B
- __builtin_HEXAGON_V6_vavgw_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vavgwrnd
- __builtin_HEXAGON_V6_vavgwrnd(v64, v64);
- // CHECK: @llvm.hexagon.V6.vavgwrnd.128B
- __builtin_HEXAGON_V6_vavgwrnd_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vcl0h
- __builtin_HEXAGON_V6_vcl0h(v64);
- // CHECK: @llvm.hexagon.V6.vcl0h.128B
- __builtin_HEXAGON_V6_vcl0h_128B(v128);
- // CHECK: @llvm.hexagon.V6.vcl0w
- __builtin_HEXAGON_V6_vcl0w(v64);
- // CHECK: @llvm.hexagon.V6.vcl0w.128B
- __builtin_HEXAGON_V6_vcl0w_128B(v128);
- // CHECK: @llvm.hexagon.V6.vcombine
- __builtin_HEXAGON_V6_vcombine(v64, v64);
- // CHECK: @llvm.hexagon.V6.vcombine.128B
- __builtin_HEXAGON_V6_vcombine_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vd0
- __builtin_HEXAGON_V6_vd0();
- // CHECK: @llvm.hexagon.V6.vd0.128B
- __builtin_HEXAGON_V6_vd0_128B();
- // CHECK: @llvm.hexagon.V6.vdd0
- __builtin_HEXAGON_V6_vdd0();
- // CHECK: @llvm.hexagon.V6.vdd0.128B
- __builtin_HEXAGON_V6_vdd0_128B();
- // CHECK: @llvm.hexagon.V6.vdealb
- __builtin_HEXAGON_V6_vdealb(v64);
- // CHECK: @llvm.hexagon.V6.vdealb.128B
- __builtin_HEXAGON_V6_vdealb_128B(v128);
- // CHECK: @llvm.hexagon.V6.vdealb4w
- __builtin_HEXAGON_V6_vdealb4w(v64, v64);
- // CHECK: @llvm.hexagon.V6.vdealb4w.128B
- __builtin_HEXAGON_V6_vdealb4w_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vdealh
- __builtin_HEXAGON_V6_vdealh(v64);
- // CHECK: @llvm.hexagon.V6.vdealh.128B
- __builtin_HEXAGON_V6_vdealh_128B(v128);
- // CHECK: @llvm.hexagon.V6.vdealvdd
- __builtin_HEXAGON_V6_vdealvdd(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vdealvdd.128B
- __builtin_HEXAGON_V6_vdealvdd_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vdelta
- __builtin_HEXAGON_V6_vdelta(v64, v64);
- // CHECK: @llvm.hexagon.V6.vdelta.128B
- __builtin_HEXAGON_V6_vdelta_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vdmpybus
- __builtin_HEXAGON_V6_vdmpybus(v64, 0);
- // CHECK: @llvm.hexagon.V6.vdmpybus.128B
- __builtin_HEXAGON_V6_vdmpybus_128B(v128, 0);
- // CHECK: @llvm.hexagon.V6.vdmpybus.acc
- __builtin_HEXAGON_V6_vdmpybus_acc(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vdmpybus.acc.128B
- __builtin_HEXAGON_V6_vdmpybus_acc_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vdmpybus.dv
- __builtin_HEXAGON_V6_vdmpybus_dv(v128, 0);
- // CHECK: @llvm.hexagon.V6.vdmpybus.dv.128B
- __builtin_HEXAGON_V6_vdmpybus_dv_128B(v256, 0);
- // CHECK: @llvm.hexagon.V6.vdmpybus.dv.acc
- __builtin_HEXAGON_V6_vdmpybus_dv_acc(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vdmpybus.dv.acc.128B
- __builtin_HEXAGON_V6_vdmpybus_dv_acc_128B(v256, v256, 0);
- // CHECK: @llvm.hexagon.V6.vdmpyhb
- __builtin_HEXAGON_V6_vdmpyhb(v64, 0);
- // CHECK: @llvm.hexagon.V6.vdmpyhb.128B
- __builtin_HEXAGON_V6_vdmpyhb_128B(v128, 0);
- // CHECK: @llvm.hexagon.V6.vdmpyhb.acc
- __builtin_HEXAGON_V6_vdmpyhb_acc(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vdmpyhb.acc.128B
- __builtin_HEXAGON_V6_vdmpyhb_acc_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vdmpyhb.dv
- __builtin_HEXAGON_V6_vdmpyhb_dv(v128, 0);
- // CHECK: @llvm.hexagon.V6.vdmpyhb.dv.128B
- __builtin_HEXAGON_V6_vdmpyhb_dv_128B(v256, 0);
- // CHECK: @llvm.hexagon.V6.vdmpyhb.dv.acc
- __builtin_HEXAGON_V6_vdmpyhb_dv_acc(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vdmpyhb.dv.acc.128B
- __builtin_HEXAGON_V6_vdmpyhb_dv_acc_128B(v256, v256, 0);
- // CHECK: @llvm.hexagon.V6.vdmpyhisat
- __builtin_HEXAGON_V6_vdmpyhisat(v128, 0);
- // CHECK: @llvm.hexagon.V6.vdmpyhisat.128B
- __builtin_HEXAGON_V6_vdmpyhisat_128B(v256, 0);
- // CHECK: @llvm.hexagon.V6.vdmpyhisat.acc
- __builtin_HEXAGON_V6_vdmpyhisat_acc(v64, v128, 0);
- // CHECK: @llvm.hexagon.V6.vdmpyhisat.acc.128B
- __builtin_HEXAGON_V6_vdmpyhisat_acc_128B(v128, v256, 0);
- // CHECK: @llvm.hexagon.V6.vdmpyhsat
- __builtin_HEXAGON_V6_vdmpyhsat(v64, 0);
- // CHECK: @llvm.hexagon.V6.vdmpyhsat.128B
- __builtin_HEXAGON_V6_vdmpyhsat_128B(v128, 0);
- // CHECK: @llvm.hexagon.V6.vdmpyhsat.acc
- __builtin_HEXAGON_V6_vdmpyhsat_acc(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vdmpyhsat.acc.128B
- __builtin_HEXAGON_V6_vdmpyhsat_acc_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vdmpyhsuisat
- __builtin_HEXAGON_V6_vdmpyhsuisat(v128, 0);
- // CHECK: @llvm.hexagon.V6.vdmpyhsuisat.128B
- __builtin_HEXAGON_V6_vdmpyhsuisat_128B(v256, 0);
- // CHECK: @llvm.hexagon.V6.vdmpyhsuisat.acc
- __builtin_HEXAGON_V6_vdmpyhsuisat_acc(v64, v128, 0);
- // CHECK: @llvm.hexagon.V6.vdmpyhsuisat.acc.128B
- __builtin_HEXAGON_V6_vdmpyhsuisat_acc_128B(v128, v256, 0);
- // CHECK: @llvm.hexagon.V6.vdmpyhsusat
- __builtin_HEXAGON_V6_vdmpyhsusat(v64, 0);
- // CHECK: @llvm.hexagon.V6.vdmpyhsusat.128B
- __builtin_HEXAGON_V6_vdmpyhsusat_128B(v128, 0);
- // CHECK: @llvm.hexagon.V6.vdmpyhsusat.acc
- __builtin_HEXAGON_V6_vdmpyhsusat_acc(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vdmpyhsusat.acc.128B
- __builtin_HEXAGON_V6_vdmpyhsusat_acc_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vdmpyhvsat
- __builtin_HEXAGON_V6_vdmpyhvsat(v64, v64);
- // CHECK: @llvm.hexagon.V6.vdmpyhvsat.128B
- __builtin_HEXAGON_V6_vdmpyhvsat_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vdmpyhvsat.acc
- __builtin_HEXAGON_V6_vdmpyhvsat_acc(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vdmpyhvsat.acc.128B
- __builtin_HEXAGON_V6_vdmpyhvsat_acc_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vdsaduh
- __builtin_HEXAGON_V6_vdsaduh(v128, 0);
- // CHECK: @llvm.hexagon.V6.vdsaduh.128B
- __builtin_HEXAGON_V6_vdsaduh_128B(v256, 0);
- // CHECK: @llvm.hexagon.V6.vdsaduh.acc
- __builtin_HEXAGON_V6_vdsaduh_acc(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vdsaduh.acc.128B
- __builtin_HEXAGON_V6_vdsaduh_acc_128B(v256, v256, 0);
- // CHECK: @llvm.hexagon.V6.veqb
- __builtin_HEXAGON_V6_veqb(v64, v64);
- // CHECK: @llvm.hexagon.V6.veqb.128B
- __builtin_HEXAGON_V6_veqb_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.veqb.and
- __builtin_HEXAGON_V6_veqb_and(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.veqb.and.128B
- __builtin_HEXAGON_V6_veqb_and_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.veqb.or
- __builtin_HEXAGON_V6_veqb_or(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.veqb.or.128B
- __builtin_HEXAGON_V6_veqb_or_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.veqb.xor
- __builtin_HEXAGON_V6_veqb_xor(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.veqb.xor.128B
- __builtin_HEXAGON_V6_veqb_xor_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.veqh
- __builtin_HEXAGON_V6_veqh(v64, v64);
- // CHECK: @llvm.hexagon.V6.veqh.128B
- __builtin_HEXAGON_V6_veqh_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.veqh.and
- __builtin_HEXAGON_V6_veqh_and(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.veqh.and.128B
- __builtin_HEXAGON_V6_veqh_and_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.veqh.or
- __builtin_HEXAGON_V6_veqh_or(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.veqh.or.128B
- __builtin_HEXAGON_V6_veqh_or_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.veqh.xor
- __builtin_HEXAGON_V6_veqh_xor(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.veqh.xor.128B
- __builtin_HEXAGON_V6_veqh_xor_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.veqw
- __builtin_HEXAGON_V6_veqw(v64, v64);
- // CHECK: @llvm.hexagon.V6.veqw.128B
- __builtin_HEXAGON_V6_veqw_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.veqw.and
- __builtin_HEXAGON_V6_veqw_and(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.veqw.and.128B
- __builtin_HEXAGON_V6_veqw_and_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.veqw.or
- __builtin_HEXAGON_V6_veqw_or(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.veqw.or.128B
- __builtin_HEXAGON_V6_veqw_or_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.veqw.xor
- __builtin_HEXAGON_V6_veqw_xor(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.veqw.xor.128B
- __builtin_HEXAGON_V6_veqw_xor_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vgathermh
- __builtin_HEXAGON_V6_vgathermh(0, 0, 0, v64);
- // CHECK: @llvm.hexagon.V6.vgathermh.128B
- __builtin_HEXAGON_V6_vgathermh_128B(0, 0, 0, v128);
- // CHECK: @llvm.hexagon.V6.vgathermhq
- __builtin_HEXAGON_V6_vgathermhq(0, v64, 0, 0, v64);
- // CHECK: @llvm.hexagon.V6.vgathermhq.128B
- __builtin_HEXAGON_V6_vgathermhq_128B(0, v128, 0, 0, v128);
- // CHECK: @llvm.hexagon.V6.vgathermhw
- __builtin_HEXAGON_V6_vgathermhw(0, 0, 0, v128);
- // CHECK: @llvm.hexagon.V6.vgathermhw.128B
- __builtin_HEXAGON_V6_vgathermhw_128B(0, 0, 0, v256);
- // CHECK: @llvm.hexagon.V6.vgathermhwq
- __builtin_HEXAGON_V6_vgathermhwq(0, v64, 0, 0, v128);
- // CHECK: @llvm.hexagon.V6.vgathermhwq.128B
- __builtin_HEXAGON_V6_vgathermhwq_128B(0, v128, 0, 0, v256);
- // CHECK: @llvm.hexagon.V6.vgathermw
- __builtin_HEXAGON_V6_vgathermw(0, 0, 0, v64);
- // CHECK: @llvm.hexagon.V6.vgathermw.128B
- __builtin_HEXAGON_V6_vgathermw_128B(0, 0, 0, v128);
- // CHECK: @llvm.hexagon.V6.vgathermwq
- __builtin_HEXAGON_V6_vgathermwq(0, v64, 0, 0, v64);
- // CHECK: @llvm.hexagon.V6.vgathermwq.128B
- __builtin_HEXAGON_V6_vgathermwq_128B(0, v128, 0, 0, v128);
- // CHECK: @llvm.hexagon.V6.vgtb
- __builtin_HEXAGON_V6_vgtb(v64, v64);
- // CHECK: @llvm.hexagon.V6.vgtb.128B
- __builtin_HEXAGON_V6_vgtb_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vgtb.and
- __builtin_HEXAGON_V6_vgtb_and(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vgtb.and.128B
- __builtin_HEXAGON_V6_vgtb_and_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vgtb.or
- __builtin_HEXAGON_V6_vgtb_or(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vgtb.or.128B
- __builtin_HEXAGON_V6_vgtb_or_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vgtb.xor
- __builtin_HEXAGON_V6_vgtb_xor(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vgtb.xor.128B
- __builtin_HEXAGON_V6_vgtb_xor_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vgth
- __builtin_HEXAGON_V6_vgth(v64, v64);
- // CHECK: @llvm.hexagon.V6.vgth.128B
- __builtin_HEXAGON_V6_vgth_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vgth.and
- __builtin_HEXAGON_V6_vgth_and(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vgth.and.128B
- __builtin_HEXAGON_V6_vgth_and_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vgth.or
- __builtin_HEXAGON_V6_vgth_or(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vgth.or.128B
- __builtin_HEXAGON_V6_vgth_or_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vgth.xor
- __builtin_HEXAGON_V6_vgth_xor(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vgth.xor.128B
- __builtin_HEXAGON_V6_vgth_xor_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vgtub
- __builtin_HEXAGON_V6_vgtub(v64, v64);
- // CHECK: @llvm.hexagon.V6.vgtub.128B
- __builtin_HEXAGON_V6_vgtub_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vgtub.and
- __builtin_HEXAGON_V6_vgtub_and(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vgtub.and.128B
- __builtin_HEXAGON_V6_vgtub_and_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vgtub.or
- __builtin_HEXAGON_V6_vgtub_or(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vgtub.or.128B
- __builtin_HEXAGON_V6_vgtub_or_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vgtub.xor
- __builtin_HEXAGON_V6_vgtub_xor(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vgtub.xor.128B
- __builtin_HEXAGON_V6_vgtub_xor_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vgtuh
- __builtin_HEXAGON_V6_vgtuh(v64, v64);
- // CHECK: @llvm.hexagon.V6.vgtuh.128B
- __builtin_HEXAGON_V6_vgtuh_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vgtuh.and
- __builtin_HEXAGON_V6_vgtuh_and(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vgtuh.and.128B
- __builtin_HEXAGON_V6_vgtuh_and_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vgtuh.or
- __builtin_HEXAGON_V6_vgtuh_or(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vgtuh.or.128B
- __builtin_HEXAGON_V6_vgtuh_or_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vgtuh.xor
- __builtin_HEXAGON_V6_vgtuh_xor(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vgtuh.xor.128B
- __builtin_HEXAGON_V6_vgtuh_xor_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vgtuw
- __builtin_HEXAGON_V6_vgtuw(v64, v64);
- // CHECK: @llvm.hexagon.V6.vgtuw.128B
- __builtin_HEXAGON_V6_vgtuw_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vgtuw.and
- __builtin_HEXAGON_V6_vgtuw_and(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vgtuw.and.128B
- __builtin_HEXAGON_V6_vgtuw_and_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vgtuw.or
- __builtin_HEXAGON_V6_vgtuw_or(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vgtuw.or.128B
- __builtin_HEXAGON_V6_vgtuw_or_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vgtuw.xor
- __builtin_HEXAGON_V6_vgtuw_xor(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vgtuw.xor.128B
- __builtin_HEXAGON_V6_vgtuw_xor_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vgtw
- __builtin_HEXAGON_V6_vgtw(v64, v64);
- // CHECK: @llvm.hexagon.V6.vgtw.128B
- __builtin_HEXAGON_V6_vgtw_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vgtw.and
- __builtin_HEXAGON_V6_vgtw_and(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vgtw.and.128B
- __builtin_HEXAGON_V6_vgtw_and_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vgtw.or
- __builtin_HEXAGON_V6_vgtw_or(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vgtw.or.128B
- __builtin_HEXAGON_V6_vgtw_or_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vgtw.xor
- __builtin_HEXAGON_V6_vgtw_xor(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vgtw.xor.128B
- __builtin_HEXAGON_V6_vgtw_xor_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vinsertwr
- __builtin_HEXAGON_V6_vinsertwr(v64, 0);
- // CHECK: @llvm.hexagon.V6.vinsertwr.128B
- __builtin_HEXAGON_V6_vinsertwr_128B(v128, 0);
- // CHECK: @llvm.hexagon.V6.vlalignb
- __builtin_HEXAGON_V6_vlalignb(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vlalignb.128B
- __builtin_HEXAGON_V6_vlalignb_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vlalignbi
- __builtin_HEXAGON_V6_vlalignbi(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vlalignbi.128B
- __builtin_HEXAGON_V6_vlalignbi_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vlsrb
- __builtin_HEXAGON_V6_vlsrb(v64, 0);
- // CHECK: @llvm.hexagon.V6.vlsrb.128B
- __builtin_HEXAGON_V6_vlsrb_128B(v128, 0);
- // CHECK: @llvm.hexagon.V6.vlsrh
- __builtin_HEXAGON_V6_vlsrh(v64, 0);
- // CHECK: @llvm.hexagon.V6.vlsrh.128B
- __builtin_HEXAGON_V6_vlsrh_128B(v128, 0);
- // CHECK: @llvm.hexagon.V6.vlsrhv
- __builtin_HEXAGON_V6_vlsrhv(v64, v64);
- // CHECK: @llvm.hexagon.V6.vlsrhv.128B
- __builtin_HEXAGON_V6_vlsrhv_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vlsrw
- __builtin_HEXAGON_V6_vlsrw(v64, 0);
- // CHECK: @llvm.hexagon.V6.vlsrw.128B
- __builtin_HEXAGON_V6_vlsrw_128B(v128, 0);
- // CHECK: @llvm.hexagon.V6.vlsrwv
- __builtin_HEXAGON_V6_vlsrwv(v64, v64);
- // CHECK: @llvm.hexagon.V6.vlsrwv.128B
- __builtin_HEXAGON_V6_vlsrwv_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vlut4
- __builtin_HEXAGON_V6_vlut4(v64, 0);
- // CHECK: @llvm.hexagon.V6.vlut4.128B
- __builtin_HEXAGON_V6_vlut4_128B(v128, 0);
- // CHECK: @llvm.hexagon.V6.vlutvvb
- __builtin_HEXAGON_V6_vlutvvb(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vlutvvb.128B
- __builtin_HEXAGON_V6_vlutvvb_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vlutvvb.nm
- __builtin_HEXAGON_V6_vlutvvb_nm(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vlutvvb.nm.128B
- __builtin_HEXAGON_V6_vlutvvb_nm_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vlutvvb.oracc
- __builtin_HEXAGON_V6_vlutvvb_oracc(v64, v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vlutvvb.oracc.128B
- __builtin_HEXAGON_V6_vlutvvb_oracc_128B(v128, v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vlutvvb.oracci
- __builtin_HEXAGON_V6_vlutvvb_oracci(v64, v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vlutvvb.oracci.128B
- __builtin_HEXAGON_V6_vlutvvb_oracci_128B(v128, v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vlutvvbi
- __builtin_HEXAGON_V6_vlutvvbi(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vlutvvbi.128B
- __builtin_HEXAGON_V6_vlutvvbi_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vlutvwh
- __builtin_HEXAGON_V6_vlutvwh(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vlutvwh.128B
- __builtin_HEXAGON_V6_vlutvwh_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vlutvwh.nm
- __builtin_HEXAGON_V6_vlutvwh_nm(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vlutvwh.nm.128B
- __builtin_HEXAGON_V6_vlutvwh_nm_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vlutvwh.oracc
- __builtin_HEXAGON_V6_vlutvwh_oracc(v128, v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vlutvwh.oracc.128B
- __builtin_HEXAGON_V6_vlutvwh_oracc_128B(v256, v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vlutvwh.oracci
- __builtin_HEXAGON_V6_vlutvwh_oracci(v128, v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vlutvwh.oracci.128B
- __builtin_HEXAGON_V6_vlutvwh_oracci_128B(v256, v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vlutvwhi
- __builtin_HEXAGON_V6_vlutvwhi(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vlutvwhi.128B
- __builtin_HEXAGON_V6_vlutvwhi_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vmaskedstorenq
- __builtin_HEXAGON_V6_vmaskedstorenq(v64, 0, v64);
- // CHECK: @llvm.hexagon.V6.vmaskedstorenq.128B
- __builtin_HEXAGON_V6_vmaskedstorenq_128B(v128, 0, v128);
- // CHECK: @llvm.hexagon.V6.vmaskedstorentnq
- __builtin_HEXAGON_V6_vmaskedstorentnq(v64, 0, v64);
- // CHECK: @llvm.hexagon.V6.vmaskedstorentnq.128B
- __builtin_HEXAGON_V6_vmaskedstorentnq_128B(v128, 0, v128);
- // CHECK: @llvm.hexagon.V6.vmaskedstorentq
- __builtin_HEXAGON_V6_vmaskedstorentq(v64, 0, v64);
- // CHECK: @llvm.hexagon.V6.vmaskedstorentq.128B
- __builtin_HEXAGON_V6_vmaskedstorentq_128B(v128, 0, v128);
- // CHECK: @llvm.hexagon.V6.vmaskedstoreq
- __builtin_HEXAGON_V6_vmaskedstoreq(v64, 0, v64);
- // CHECK: @llvm.hexagon.V6.vmaskedstoreq.128B
- __builtin_HEXAGON_V6_vmaskedstoreq_128B(v128, 0, v128);
- // CHECK: @llvm.hexagon.V6.vmaxb
- __builtin_HEXAGON_V6_vmaxb(v64, v64);
- // CHECK: @llvm.hexagon.V6.vmaxb.128B
- __builtin_HEXAGON_V6_vmaxb_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vmaxh
- __builtin_HEXAGON_V6_vmaxh(v64, v64);
- // CHECK: @llvm.hexagon.V6.vmaxh.128B
- __builtin_HEXAGON_V6_vmaxh_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vmaxub
- __builtin_HEXAGON_V6_vmaxub(v64, v64);
- // CHECK: @llvm.hexagon.V6.vmaxub.128B
- __builtin_HEXAGON_V6_vmaxub_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vmaxuh
- __builtin_HEXAGON_V6_vmaxuh(v64, v64);
- // CHECK: @llvm.hexagon.V6.vmaxuh.128B
- __builtin_HEXAGON_V6_vmaxuh_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vmaxw
- __builtin_HEXAGON_V6_vmaxw(v64, v64);
- // CHECK: @llvm.hexagon.V6.vmaxw.128B
- __builtin_HEXAGON_V6_vmaxw_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vminb
- __builtin_HEXAGON_V6_vminb(v64, v64);
- // CHECK: @llvm.hexagon.V6.vminb.128B
- __builtin_HEXAGON_V6_vminb_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vminh
- __builtin_HEXAGON_V6_vminh(v64, v64);
- // CHECK: @llvm.hexagon.V6.vminh.128B
- __builtin_HEXAGON_V6_vminh_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vminub
- __builtin_HEXAGON_V6_vminub(v64, v64);
- // CHECK: @llvm.hexagon.V6.vminub.128B
- __builtin_HEXAGON_V6_vminub_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vminuh
- __builtin_HEXAGON_V6_vminuh(v64, v64);
- // CHECK: @llvm.hexagon.V6.vminuh.128B
- __builtin_HEXAGON_V6_vminuh_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vminw
- __builtin_HEXAGON_V6_vminw(v64, v64);
- // CHECK: @llvm.hexagon.V6.vminw.128B
- __builtin_HEXAGON_V6_vminw_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vmpabus
- __builtin_HEXAGON_V6_vmpabus(v128, 0);
- // CHECK: @llvm.hexagon.V6.vmpabus.128B
- __builtin_HEXAGON_V6_vmpabus_128B(v256, 0);
- // CHECK: @llvm.hexagon.V6.vmpabus.acc
- __builtin_HEXAGON_V6_vmpabus_acc(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vmpabus.acc.128B
- __builtin_HEXAGON_V6_vmpabus_acc_128B(v256, v256, 0);
- // CHECK: @llvm.hexagon.V6.vmpabusv
- __builtin_HEXAGON_V6_vmpabusv(v128, v128);
- // CHECK: @llvm.hexagon.V6.vmpabusv.128B
- __builtin_HEXAGON_V6_vmpabusv_128B(v256, v256);
- // CHECK: @llvm.hexagon.V6.vmpabuu
- __builtin_HEXAGON_V6_vmpabuu(v128, 0);
- // CHECK: @llvm.hexagon.V6.vmpabuu.128B
- __builtin_HEXAGON_V6_vmpabuu_128B(v256, 0);
- // CHECK: @llvm.hexagon.V6.vmpabuu.acc
- __builtin_HEXAGON_V6_vmpabuu_acc(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vmpabuu.acc.128B
- __builtin_HEXAGON_V6_vmpabuu_acc_128B(v256, v256, 0);
- // CHECK: @llvm.hexagon.V6.vmpabuuv
- __builtin_HEXAGON_V6_vmpabuuv(v128, v128);
- // CHECK: @llvm.hexagon.V6.vmpabuuv.128B
- __builtin_HEXAGON_V6_vmpabuuv_128B(v256, v256);
- // CHECK: @llvm.hexagon.V6.vmpahb
- __builtin_HEXAGON_V6_vmpahb(v128, 0);
- // CHECK: @llvm.hexagon.V6.vmpahb.128B
- __builtin_HEXAGON_V6_vmpahb_128B(v256, 0);
- // CHECK: @llvm.hexagon.V6.vmpahb.acc
- __builtin_HEXAGON_V6_vmpahb_acc(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vmpahb.acc.128B
- __builtin_HEXAGON_V6_vmpahb_acc_128B(v256, v256, 0);
- // CHECK: @llvm.hexagon.V6.vmpahhsat
- __builtin_HEXAGON_V6_vmpahhsat(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vmpahhsat.128B
- __builtin_HEXAGON_V6_vmpahhsat_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vmpauhb
- __builtin_HEXAGON_V6_vmpauhb(v128, 0);
- // CHECK: @llvm.hexagon.V6.vmpauhb.128B
- __builtin_HEXAGON_V6_vmpauhb_128B(v256, 0);
- // CHECK: @llvm.hexagon.V6.vmpauhb.acc
- __builtin_HEXAGON_V6_vmpauhb_acc(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vmpauhb.acc.128B
- __builtin_HEXAGON_V6_vmpauhb_acc_128B(v256, v256, 0);
- // CHECK: @llvm.hexagon.V6.vmpauhuhsat
- __builtin_HEXAGON_V6_vmpauhuhsat(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vmpauhuhsat.128B
- __builtin_HEXAGON_V6_vmpauhuhsat_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vmpsuhuhsat
- __builtin_HEXAGON_V6_vmpsuhuhsat(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vmpsuhuhsat.128B
- __builtin_HEXAGON_V6_vmpsuhuhsat_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vmpybus
- __builtin_HEXAGON_V6_vmpybus(v64, 0);
- // CHECK: @llvm.hexagon.V6.vmpybus.128B
- __builtin_HEXAGON_V6_vmpybus_128B(v128, 0);
- // CHECK: @llvm.hexagon.V6.vmpybus.acc
- __builtin_HEXAGON_V6_vmpybus_acc(v128, v64, 0);
- // CHECK: @llvm.hexagon.V6.vmpybus.acc.128B
- __builtin_HEXAGON_V6_vmpybus_acc_128B(v256, v128, 0);
- // CHECK: @llvm.hexagon.V6.vmpybusv
- __builtin_HEXAGON_V6_vmpybusv(v64, v64);
- // CHECK: @llvm.hexagon.V6.vmpybusv.128B
- __builtin_HEXAGON_V6_vmpybusv_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vmpybusv.acc
- __builtin_HEXAGON_V6_vmpybusv_acc(v128, v64, v64);
- // CHECK: @llvm.hexagon.V6.vmpybusv.acc.128B
- __builtin_HEXAGON_V6_vmpybusv_acc_128B(v256, v128, v128);
- // CHECK: @llvm.hexagon.V6.vmpybv
- __builtin_HEXAGON_V6_vmpybv(v64, v64);
- // CHECK: @llvm.hexagon.V6.vmpybv.128B
- __builtin_HEXAGON_V6_vmpybv_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vmpybv.acc
- __builtin_HEXAGON_V6_vmpybv_acc(v128, v64, v64);
- // CHECK: @llvm.hexagon.V6.vmpybv.acc.128B
- __builtin_HEXAGON_V6_vmpybv_acc_128B(v256, v128, v128);
- // CHECK: @llvm.hexagon.V6.vmpyewuh
- __builtin_HEXAGON_V6_vmpyewuh(v64, v64);
- // CHECK: @llvm.hexagon.V6.vmpyewuh.128B
- __builtin_HEXAGON_V6_vmpyewuh_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vmpyewuh.64
- __builtin_HEXAGON_V6_vmpyewuh_64(v64, v64);
- // CHECK: @llvm.hexagon.V6.vmpyewuh.64.128B
- __builtin_HEXAGON_V6_vmpyewuh_64_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vmpyh
- __builtin_HEXAGON_V6_vmpyh(v64, 0);
- // CHECK: @llvm.hexagon.V6.vmpyh.128B
- __builtin_HEXAGON_V6_vmpyh_128B(v128, 0);
- // CHECK: @llvm.hexagon.V6.vmpyh.acc
- __builtin_HEXAGON_V6_vmpyh_acc(v128, v64, 0);
- // CHECK: @llvm.hexagon.V6.vmpyh.acc.128B
- __builtin_HEXAGON_V6_vmpyh_acc_128B(v256, v128, 0);
- // CHECK: @llvm.hexagon.V6.vmpyhsat.acc
- __builtin_HEXAGON_V6_vmpyhsat_acc(v128, v64, 0);
- // CHECK: @llvm.hexagon.V6.vmpyhsat.acc.128B
- __builtin_HEXAGON_V6_vmpyhsat_acc_128B(v256, v128, 0);
- // CHECK: @llvm.hexagon.V6.vmpyhsrs
- __builtin_HEXAGON_V6_vmpyhsrs(v64, 0);
- // CHECK: @llvm.hexagon.V6.vmpyhsrs.128B
- __builtin_HEXAGON_V6_vmpyhsrs_128B(v128, 0);
- // CHECK: @llvm.hexagon.V6.vmpyhss
- __builtin_HEXAGON_V6_vmpyhss(v64, 0);
- // CHECK: @llvm.hexagon.V6.vmpyhss.128B
- __builtin_HEXAGON_V6_vmpyhss_128B(v128, 0);
- // CHECK: @llvm.hexagon.V6.vmpyhus
- __builtin_HEXAGON_V6_vmpyhus(v64, v64);
- // CHECK: @llvm.hexagon.V6.vmpyhus.128B
- __builtin_HEXAGON_V6_vmpyhus_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vmpyhus.acc
- __builtin_HEXAGON_V6_vmpyhus_acc(v128, v64, v64);
- // CHECK: @llvm.hexagon.V6.vmpyhus.acc.128B
- __builtin_HEXAGON_V6_vmpyhus_acc_128B(v256, v128, v128);
- // CHECK: @llvm.hexagon.V6.vmpyhv
- __builtin_HEXAGON_V6_vmpyhv(v64, v64);
- // CHECK: @llvm.hexagon.V6.vmpyhv.128B
- __builtin_HEXAGON_V6_vmpyhv_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vmpyhv.acc
- __builtin_HEXAGON_V6_vmpyhv_acc(v128, v64, v64);
- // CHECK: @llvm.hexagon.V6.vmpyhv.acc.128B
- __builtin_HEXAGON_V6_vmpyhv_acc_128B(v256, v128, v128);
- // CHECK: @llvm.hexagon.V6.vmpyhvsrs
- __builtin_HEXAGON_V6_vmpyhvsrs(v64, v64);
- // CHECK: @llvm.hexagon.V6.vmpyhvsrs.128B
- __builtin_HEXAGON_V6_vmpyhvsrs_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vmpyieoh
- __builtin_HEXAGON_V6_vmpyieoh(v64, v64);
- // CHECK: @llvm.hexagon.V6.vmpyieoh.128B
- __builtin_HEXAGON_V6_vmpyieoh_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vmpyiewh.acc
- __builtin_HEXAGON_V6_vmpyiewh_acc(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vmpyiewh.acc.128B
- __builtin_HEXAGON_V6_vmpyiewh_acc_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vmpyiewuh
- __builtin_HEXAGON_V6_vmpyiewuh(v64, v64);
- // CHECK: @llvm.hexagon.V6.vmpyiewuh.128B
- __builtin_HEXAGON_V6_vmpyiewuh_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vmpyiewuh.acc
- __builtin_HEXAGON_V6_vmpyiewuh_acc(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vmpyiewuh.acc.128B
- __builtin_HEXAGON_V6_vmpyiewuh_acc_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vmpyih
- __builtin_HEXAGON_V6_vmpyih(v64, v64);
- // CHECK: @llvm.hexagon.V6.vmpyih.128B
- __builtin_HEXAGON_V6_vmpyih_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vmpyih.acc
- __builtin_HEXAGON_V6_vmpyih_acc(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vmpyih.acc.128B
- __builtin_HEXAGON_V6_vmpyih_acc_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vmpyihb
- __builtin_HEXAGON_V6_vmpyihb(v64, 0);
- // CHECK: @llvm.hexagon.V6.vmpyihb.128B
- __builtin_HEXAGON_V6_vmpyihb_128B(v128, 0);
- // CHECK: @llvm.hexagon.V6.vmpyihb.acc
- __builtin_HEXAGON_V6_vmpyihb_acc(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vmpyihb.acc.128B
- __builtin_HEXAGON_V6_vmpyihb_acc_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vmpyiowh
- __builtin_HEXAGON_V6_vmpyiowh(v64, v64);
- // CHECK: @llvm.hexagon.V6.vmpyiowh.128B
- __builtin_HEXAGON_V6_vmpyiowh_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vmpyiwb
- __builtin_HEXAGON_V6_vmpyiwb(v64, 0);
- // CHECK: @llvm.hexagon.V6.vmpyiwb.128B
- __builtin_HEXAGON_V6_vmpyiwb_128B(v128, 0);
- // CHECK: @llvm.hexagon.V6.vmpyiwb.acc
- __builtin_HEXAGON_V6_vmpyiwb_acc(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vmpyiwb.acc.128B
- __builtin_HEXAGON_V6_vmpyiwb_acc_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vmpyiwh
- __builtin_HEXAGON_V6_vmpyiwh(v64, 0);
- // CHECK: @llvm.hexagon.V6.vmpyiwh.128B
- __builtin_HEXAGON_V6_vmpyiwh_128B(v128, 0);
- // CHECK: @llvm.hexagon.V6.vmpyiwh.acc
- __builtin_HEXAGON_V6_vmpyiwh_acc(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vmpyiwh.acc.128B
- __builtin_HEXAGON_V6_vmpyiwh_acc_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vmpyiwub
- __builtin_HEXAGON_V6_vmpyiwub(v64, 0);
- // CHECK: @llvm.hexagon.V6.vmpyiwub.128B
- __builtin_HEXAGON_V6_vmpyiwub_128B(v128, 0);
- // CHECK: @llvm.hexagon.V6.vmpyiwub.acc
- __builtin_HEXAGON_V6_vmpyiwub_acc(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vmpyiwub.acc.128B
- __builtin_HEXAGON_V6_vmpyiwub_acc_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vmpyowh
- __builtin_HEXAGON_V6_vmpyowh(v64, v64);
- // CHECK: @llvm.hexagon.V6.vmpyowh.128B
- __builtin_HEXAGON_V6_vmpyowh_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vmpyowh.64.acc
- __builtin_HEXAGON_V6_vmpyowh_64_acc(v128, v64, v64);
- // CHECK: @llvm.hexagon.V6.vmpyowh.64.acc.128B
- __builtin_HEXAGON_V6_vmpyowh_64_acc_128B(v256, v128, v128);
- // CHECK: @llvm.hexagon.V6.vmpyowh.rnd
- __builtin_HEXAGON_V6_vmpyowh_rnd(v64, v64);
- // CHECK: @llvm.hexagon.V6.vmpyowh.rnd.128B
- __builtin_HEXAGON_V6_vmpyowh_rnd_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vmpyowh.rnd.sacc
- __builtin_HEXAGON_V6_vmpyowh_rnd_sacc(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vmpyowh.rnd.sacc.128B
- __builtin_HEXAGON_V6_vmpyowh_rnd_sacc_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vmpyowh.sacc
- __builtin_HEXAGON_V6_vmpyowh_sacc(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vmpyowh.sacc.128B
- __builtin_HEXAGON_V6_vmpyowh_sacc_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vmpyub
- __builtin_HEXAGON_V6_vmpyub(v64, 0);
- // CHECK: @llvm.hexagon.V6.vmpyub.128B
- __builtin_HEXAGON_V6_vmpyub_128B(v128, 0);
- // CHECK: @llvm.hexagon.V6.vmpyub.acc
- __builtin_HEXAGON_V6_vmpyub_acc(v128, v64, 0);
- // CHECK: @llvm.hexagon.V6.vmpyub.acc.128B
- __builtin_HEXAGON_V6_vmpyub_acc_128B(v256, v128, 0);
- // CHECK: @llvm.hexagon.V6.vmpyubv
- __builtin_HEXAGON_V6_vmpyubv(v64, v64);
- // CHECK: @llvm.hexagon.V6.vmpyubv.128B
- __builtin_HEXAGON_V6_vmpyubv_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vmpyubv.acc
- __builtin_HEXAGON_V6_vmpyubv_acc(v128, v64, v64);
- // CHECK: @llvm.hexagon.V6.vmpyubv.acc.128B
- __builtin_HEXAGON_V6_vmpyubv_acc_128B(v256, v128, v128);
- // CHECK: @llvm.hexagon.V6.vmpyuh
- __builtin_HEXAGON_V6_vmpyuh(v64, 0);
- // CHECK: @llvm.hexagon.V6.vmpyuh.128B
- __builtin_HEXAGON_V6_vmpyuh_128B(v128, 0);
- // CHECK: @llvm.hexagon.V6.vmpyuh.acc
- __builtin_HEXAGON_V6_vmpyuh_acc(v128, v64, 0);
- // CHECK: @llvm.hexagon.V6.vmpyuh.acc.128B
- __builtin_HEXAGON_V6_vmpyuh_acc_128B(v256, v128, 0);
- // CHECK: @llvm.hexagon.V6.vmpyuhe
- __builtin_HEXAGON_V6_vmpyuhe(v64, 0);
- // CHECK: @llvm.hexagon.V6.vmpyuhe.128B
- __builtin_HEXAGON_V6_vmpyuhe_128B(v128, 0);
- // CHECK: @llvm.hexagon.V6.vmpyuhe.acc
- __builtin_HEXAGON_V6_vmpyuhe_acc(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vmpyuhe.acc.128B
- __builtin_HEXAGON_V6_vmpyuhe_acc_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vmpyuhv
- __builtin_HEXAGON_V6_vmpyuhv(v64, v64);
- // CHECK: @llvm.hexagon.V6.vmpyuhv.128B
- __builtin_HEXAGON_V6_vmpyuhv_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vmpyuhv.acc
- __builtin_HEXAGON_V6_vmpyuhv_acc(v128, v64, v64);
- // CHECK: @llvm.hexagon.V6.vmpyuhv.acc.128B
- __builtin_HEXAGON_V6_vmpyuhv_acc_128B(v256, v128, v128);
- // CHECK: @llvm.hexagon.V6.vmux
- __builtin_HEXAGON_V6_vmux(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vmux.128B
- __builtin_HEXAGON_V6_vmux_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vnavgb
- __builtin_HEXAGON_V6_vnavgb(v64, v64);
- // CHECK: @llvm.hexagon.V6.vnavgb.128B
- __builtin_HEXAGON_V6_vnavgb_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vnavgh
- __builtin_HEXAGON_V6_vnavgh(v64, v64);
- // CHECK: @llvm.hexagon.V6.vnavgh.128B
- __builtin_HEXAGON_V6_vnavgh_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vnavgub
- __builtin_HEXAGON_V6_vnavgub(v64, v64);
- // CHECK: @llvm.hexagon.V6.vnavgub.128B
- __builtin_HEXAGON_V6_vnavgub_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vnavgw
- __builtin_HEXAGON_V6_vnavgw(v64, v64);
- // CHECK: @llvm.hexagon.V6.vnavgw.128B
- __builtin_HEXAGON_V6_vnavgw_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vnormamth
- __builtin_HEXAGON_V6_vnormamth(v64);
- // CHECK: @llvm.hexagon.V6.vnormamth.128B
- __builtin_HEXAGON_V6_vnormamth_128B(v128);
- // CHECK: @llvm.hexagon.V6.vnormamtw
- __builtin_HEXAGON_V6_vnormamtw(v64);
- // CHECK: @llvm.hexagon.V6.vnormamtw.128B
- __builtin_HEXAGON_V6_vnormamtw_128B(v128);
- // CHECK: @llvm.hexagon.V6.vnot
- __builtin_HEXAGON_V6_vnot(v64);
- // CHECK: @llvm.hexagon.V6.vnot.128B
- __builtin_HEXAGON_V6_vnot_128B(v128);
- // CHECK: @llvm.hexagon.V6.vor
- __builtin_HEXAGON_V6_vor(v64, v64);
- // CHECK: @llvm.hexagon.V6.vor.128B
- __builtin_HEXAGON_V6_vor_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vpackeb
- __builtin_HEXAGON_V6_vpackeb(v64, v64);
- // CHECK: @llvm.hexagon.V6.vpackeb.128B
- __builtin_HEXAGON_V6_vpackeb_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vpackeh
- __builtin_HEXAGON_V6_vpackeh(v64, v64);
- // CHECK: @llvm.hexagon.V6.vpackeh.128B
- __builtin_HEXAGON_V6_vpackeh_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vpackhb.sat
- __builtin_HEXAGON_V6_vpackhb_sat(v64, v64);
- // CHECK: @llvm.hexagon.V6.vpackhb.sat.128B
- __builtin_HEXAGON_V6_vpackhb_sat_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vpackhub.sat
- __builtin_HEXAGON_V6_vpackhub_sat(v64, v64);
- // CHECK: @llvm.hexagon.V6.vpackhub.sat.128B
- __builtin_HEXAGON_V6_vpackhub_sat_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vpackob
- __builtin_HEXAGON_V6_vpackob(v64, v64);
- // CHECK: @llvm.hexagon.V6.vpackob.128B
- __builtin_HEXAGON_V6_vpackob_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vpackoh
- __builtin_HEXAGON_V6_vpackoh(v64, v64);
- // CHECK: @llvm.hexagon.V6.vpackoh.128B
- __builtin_HEXAGON_V6_vpackoh_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vpackwh.sat
- __builtin_HEXAGON_V6_vpackwh_sat(v64, v64);
- // CHECK: @llvm.hexagon.V6.vpackwh.sat.128B
- __builtin_HEXAGON_V6_vpackwh_sat_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vpackwuh.sat
- __builtin_HEXAGON_V6_vpackwuh_sat(v64, v64);
- // CHECK: @llvm.hexagon.V6.vpackwuh.sat.128B
- __builtin_HEXAGON_V6_vpackwuh_sat_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vpopcounth
- __builtin_HEXAGON_V6_vpopcounth(v64);
- // CHECK: @llvm.hexagon.V6.vpopcounth.128B
- __builtin_HEXAGON_V6_vpopcounth_128B(v128);
- // CHECK: @llvm.hexagon.V6.vprefixqb
- __builtin_HEXAGON_V6_vprefixqb(v64);
- // CHECK: @llvm.hexagon.V6.vprefixqb.128B
- __builtin_HEXAGON_V6_vprefixqb_128B(v128);
- // CHECK: @llvm.hexagon.V6.vprefixqh
- __builtin_HEXAGON_V6_vprefixqh(v64);
- // CHECK: @llvm.hexagon.V6.vprefixqh.128B
- __builtin_HEXAGON_V6_vprefixqh_128B(v128);
- // CHECK: @llvm.hexagon.V6.vprefixqw
- __builtin_HEXAGON_V6_vprefixqw(v64);
- // CHECK: @llvm.hexagon.V6.vprefixqw.128B
- __builtin_HEXAGON_V6_vprefixqw_128B(v128);
- // CHECK: @llvm.hexagon.V6.vrdelta
- __builtin_HEXAGON_V6_vrdelta(v64, v64);
- // CHECK: @llvm.hexagon.V6.vrdelta.128B
- __builtin_HEXAGON_V6_vrdelta_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vrmpybub.rtt
- __builtin_HEXAGON_V6_vrmpybub_rtt(v64, 0);
- // CHECK: @llvm.hexagon.V6.vrmpybub.rtt.128B
- __builtin_HEXAGON_V6_vrmpybub_rtt_128B(v128, 0);
- // CHECK: @llvm.hexagon.V6.vrmpybub.rtt.acc
- __builtin_HEXAGON_V6_vrmpybub_rtt_acc(v128, v64, 0);
- // CHECK: @llvm.hexagon.V6.vrmpybub.rtt.acc.128B
- __builtin_HEXAGON_V6_vrmpybub_rtt_acc_128B(v256, v128, 0);
- // CHECK: @llvm.hexagon.V6.vrmpybus
- __builtin_HEXAGON_V6_vrmpybus(v64, 0);
- // CHECK: @llvm.hexagon.V6.vrmpybus.128B
- __builtin_HEXAGON_V6_vrmpybus_128B(v128, 0);
- // CHECK: @llvm.hexagon.V6.vrmpybus.acc
- __builtin_HEXAGON_V6_vrmpybus_acc(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vrmpybus.acc.128B
- __builtin_HEXAGON_V6_vrmpybus_acc_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vrmpybusi
- __builtin_HEXAGON_V6_vrmpybusi(v128, 0, 0);
- // CHECK: @llvm.hexagon.V6.vrmpybusi.128B
- __builtin_HEXAGON_V6_vrmpybusi_128B(v256, 0, 0);
- // CHECK: @llvm.hexagon.V6.vrmpybusi.acc
- __builtin_HEXAGON_V6_vrmpybusi_acc(v128, v128, 0, 0);
- // CHECK: @llvm.hexagon.V6.vrmpybusi.acc.128B
- __builtin_HEXAGON_V6_vrmpybusi_acc_128B(v256, v256, 0, 0);
- // CHECK: @llvm.hexagon.V6.vrmpybusv
- __builtin_HEXAGON_V6_vrmpybusv(v64, v64);
- // CHECK: @llvm.hexagon.V6.vrmpybusv.128B
- __builtin_HEXAGON_V6_vrmpybusv_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vrmpybusv.acc
- __builtin_HEXAGON_V6_vrmpybusv_acc(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vrmpybusv.acc.128B
- __builtin_HEXAGON_V6_vrmpybusv_acc_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vrmpybv
- __builtin_HEXAGON_V6_vrmpybv(v64, v64);
- // CHECK: @llvm.hexagon.V6.vrmpybv.128B
- __builtin_HEXAGON_V6_vrmpybv_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vrmpybv.acc
- __builtin_HEXAGON_V6_vrmpybv_acc(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vrmpybv.acc.128B
- __builtin_HEXAGON_V6_vrmpybv_acc_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vrmpyub
- __builtin_HEXAGON_V6_vrmpyub(v64, 0);
- // CHECK: @llvm.hexagon.V6.vrmpyub.128B
- __builtin_HEXAGON_V6_vrmpyub_128B(v128, 0);
- // CHECK: @llvm.hexagon.V6.vrmpyub.acc
- __builtin_HEXAGON_V6_vrmpyub_acc(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vrmpyub.acc.128B
- __builtin_HEXAGON_V6_vrmpyub_acc_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vrmpyub.rtt
- __builtin_HEXAGON_V6_vrmpyub_rtt(v64, 0);
- // CHECK: @llvm.hexagon.V6.vrmpyub.rtt.128B
- __builtin_HEXAGON_V6_vrmpyub_rtt_128B(v128, 0);
- // CHECK: @llvm.hexagon.V6.vrmpyub.rtt.acc
- __builtin_HEXAGON_V6_vrmpyub_rtt_acc(v128, v64, 0);
- // CHECK: @llvm.hexagon.V6.vrmpyub.rtt.acc.128B
- __builtin_HEXAGON_V6_vrmpyub_rtt_acc_128B(v256, v128, 0);
- // CHECK: @llvm.hexagon.V6.vrmpyubi
- __builtin_HEXAGON_V6_vrmpyubi(v128, 0, 0);
- // CHECK: @llvm.hexagon.V6.vrmpyubi.128B
- __builtin_HEXAGON_V6_vrmpyubi_128B(v256, 0, 0);
- // CHECK: @llvm.hexagon.V6.vrmpyubi.acc
- __builtin_HEXAGON_V6_vrmpyubi_acc(v128, v128, 0, 0);
- // CHECK: @llvm.hexagon.V6.vrmpyubi.acc.128B
- __builtin_HEXAGON_V6_vrmpyubi_acc_128B(v256, v256, 0, 0);
- // CHECK: @llvm.hexagon.V6.vrmpyubv
- __builtin_HEXAGON_V6_vrmpyubv(v64, v64);
- // CHECK: @llvm.hexagon.V6.vrmpyubv.128B
- __builtin_HEXAGON_V6_vrmpyubv_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vrmpyubv.acc
- __builtin_HEXAGON_V6_vrmpyubv_acc(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vrmpyubv.acc.128B
- __builtin_HEXAGON_V6_vrmpyubv_acc_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vror
- __builtin_HEXAGON_V6_vror(v64, 0);
- // CHECK: @llvm.hexagon.V6.vror.128B
- __builtin_HEXAGON_V6_vror_128B(v128, 0);
- // CHECK: @llvm.hexagon.V6.vroundhb
- __builtin_HEXAGON_V6_vroundhb(v64, v64);
- // CHECK: @llvm.hexagon.V6.vroundhb.128B
- __builtin_HEXAGON_V6_vroundhb_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vroundhub
- __builtin_HEXAGON_V6_vroundhub(v64, v64);
- // CHECK: @llvm.hexagon.V6.vroundhub.128B
- __builtin_HEXAGON_V6_vroundhub_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vrounduhub
- __builtin_HEXAGON_V6_vrounduhub(v64, v64);
- // CHECK: @llvm.hexagon.V6.vrounduhub.128B
- __builtin_HEXAGON_V6_vrounduhub_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vrounduwuh
- __builtin_HEXAGON_V6_vrounduwuh(v64, v64);
- // CHECK: @llvm.hexagon.V6.vrounduwuh.128B
- __builtin_HEXAGON_V6_vrounduwuh_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vroundwh
- __builtin_HEXAGON_V6_vroundwh(v64, v64);
- // CHECK: @llvm.hexagon.V6.vroundwh.128B
- __builtin_HEXAGON_V6_vroundwh_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vroundwuh
- __builtin_HEXAGON_V6_vroundwuh(v64, v64);
- // CHECK: @llvm.hexagon.V6.vroundwuh.128B
- __builtin_HEXAGON_V6_vroundwuh_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vrsadubi
- __builtin_HEXAGON_V6_vrsadubi(v128, 0, 0);
- // CHECK: @llvm.hexagon.V6.vrsadubi.128B
- __builtin_HEXAGON_V6_vrsadubi_128B(v256, 0, 0);
- // CHECK: @llvm.hexagon.V6.vrsadubi.acc
- __builtin_HEXAGON_V6_vrsadubi_acc(v128, v128, 0, 0);
- // CHECK: @llvm.hexagon.V6.vrsadubi.acc.128B
- __builtin_HEXAGON_V6_vrsadubi_acc_128B(v256, v256, 0, 0);
- // CHECK: @llvm.hexagon.V6.vsathub
- __builtin_HEXAGON_V6_vsathub(v64, v64);
- // CHECK: @llvm.hexagon.V6.vsathub.128B
- __builtin_HEXAGON_V6_vsathub_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vsatuwuh
- __builtin_HEXAGON_V6_vsatuwuh(v64, v64);
- // CHECK: @llvm.hexagon.V6.vsatuwuh.128B
- __builtin_HEXAGON_V6_vsatuwuh_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vsatwh
- __builtin_HEXAGON_V6_vsatwh(v64, v64);
- // CHECK: @llvm.hexagon.V6.vsatwh.128B
- __builtin_HEXAGON_V6_vsatwh_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vsb
- __builtin_HEXAGON_V6_vsb(v64);
- // CHECK: @llvm.hexagon.V6.vsb.128B
- __builtin_HEXAGON_V6_vsb_128B(v128);
- // CHECK: @llvm.hexagon.V6.vscattermh
- __builtin_HEXAGON_V6_vscattermh(0, 0, v64, v64);
- // CHECK: @llvm.hexagon.V6.vscattermh.128B
- __builtin_HEXAGON_V6_vscattermh_128B(0, 0, v128, v128);
- // CHECK: @llvm.hexagon.V6.vscattermh.add
- __builtin_HEXAGON_V6_vscattermh_add(0, 0, v64, v64);
- // CHECK: @llvm.hexagon.V6.vscattermh.add.128B
- __builtin_HEXAGON_V6_vscattermh_add_128B(0, 0, v128, v128);
- // CHECK: @llvm.hexagon.V6.vscattermhq
- __builtin_HEXAGON_V6_vscattermhq(v64, 0, 0, v64, v64);
- // CHECK: @llvm.hexagon.V6.vscattermhq.128B
- __builtin_HEXAGON_V6_vscattermhq_128B(v128, 0, 0, v128, v128);
- // CHECK: @llvm.hexagon.V6.vscattermhw
- __builtin_HEXAGON_V6_vscattermhw(0, 0, v128, v64);
- // CHECK: @llvm.hexagon.V6.vscattermhw.128B
- __builtin_HEXAGON_V6_vscattermhw_128B(0, 0, v256, v128);
- // CHECK: @llvm.hexagon.V6.vscattermhw.add
- __builtin_HEXAGON_V6_vscattermhw_add(0, 0, v128, v64);
- // CHECK: @llvm.hexagon.V6.vscattermhw.add.128B
- __builtin_HEXAGON_V6_vscattermhw_add_128B(0, 0, v256, v128);
- // CHECK: @llvm.hexagon.V6.vscattermhwq
- __builtin_HEXAGON_V6_vscattermhwq(v64, 0, 0, v128, v64);
- // CHECK: @llvm.hexagon.V6.vscattermhwq.128B
- __builtin_HEXAGON_V6_vscattermhwq_128B(v128, 0, 0, v256, v128);
- // CHECK: @llvm.hexagon.V6.vscattermw
- __builtin_HEXAGON_V6_vscattermw(0, 0, v64, v64);
- // CHECK: @llvm.hexagon.V6.vscattermw.128B
- __builtin_HEXAGON_V6_vscattermw_128B(0, 0, v128, v128);
- // CHECK: @llvm.hexagon.V6.vscattermw.add
- __builtin_HEXAGON_V6_vscattermw_add(0, 0, v64, v64);
- // CHECK: @llvm.hexagon.V6.vscattermw.add.128B
- __builtin_HEXAGON_V6_vscattermw_add_128B(0, 0, v128, v128);
- // CHECK: @llvm.hexagon.V6.vscattermwq
- __builtin_HEXAGON_V6_vscattermwq(v64, 0, 0, v64, v64);
- // CHECK: @llvm.hexagon.V6.vscattermwq.128B
- __builtin_HEXAGON_V6_vscattermwq_128B(v128, 0, 0, v128, v128);
- // CHECK: @llvm.hexagon.V6.vsh
- __builtin_HEXAGON_V6_vsh(v64);
- // CHECK: @llvm.hexagon.V6.vsh.128B
- __builtin_HEXAGON_V6_vsh_128B(v128);
- // CHECK: @llvm.hexagon.V6.vshufeh
- __builtin_HEXAGON_V6_vshufeh(v64, v64);
- // CHECK: @llvm.hexagon.V6.vshufeh.128B
- __builtin_HEXAGON_V6_vshufeh_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vshuffb
- __builtin_HEXAGON_V6_vshuffb(v64);
- // CHECK: @llvm.hexagon.V6.vshuffb.128B
- __builtin_HEXAGON_V6_vshuffb_128B(v128);
- // CHECK: @llvm.hexagon.V6.vshuffeb
- __builtin_HEXAGON_V6_vshuffeb(v64, v64);
- // CHECK: @llvm.hexagon.V6.vshuffeb.128B
- __builtin_HEXAGON_V6_vshuffeb_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vshuffh
- __builtin_HEXAGON_V6_vshuffh(v64);
- // CHECK: @llvm.hexagon.V6.vshuffh.128B
- __builtin_HEXAGON_V6_vshuffh_128B(v128);
- // CHECK: @llvm.hexagon.V6.vshuffob
- __builtin_HEXAGON_V6_vshuffob(v64, v64);
- // CHECK: @llvm.hexagon.V6.vshuffob.128B
- __builtin_HEXAGON_V6_vshuffob_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vshuffvdd
- __builtin_HEXAGON_V6_vshuffvdd(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vshuffvdd.128B
- __builtin_HEXAGON_V6_vshuffvdd_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vshufoeb
- __builtin_HEXAGON_V6_vshufoeb(v64, v64);
- // CHECK: @llvm.hexagon.V6.vshufoeb.128B
- __builtin_HEXAGON_V6_vshufoeb_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vshufoeh
- __builtin_HEXAGON_V6_vshufoeh(v64, v64);
- // CHECK: @llvm.hexagon.V6.vshufoeh.128B
- __builtin_HEXAGON_V6_vshufoeh_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vshufoh
- __builtin_HEXAGON_V6_vshufoh(v64, v64);
- // CHECK: @llvm.hexagon.V6.vshufoh.128B
- __builtin_HEXAGON_V6_vshufoh_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vsubb
- __builtin_HEXAGON_V6_vsubb(v64, v64);
- // CHECK: @llvm.hexagon.V6.vsubb.128B
- __builtin_HEXAGON_V6_vsubb_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vsubb.dv
- __builtin_HEXAGON_V6_vsubb_dv(v128, v128);
- // CHECK: @llvm.hexagon.V6.vsubb.dv.128B
- __builtin_HEXAGON_V6_vsubb_dv_128B(v256, v256);
- // CHECK: @llvm.hexagon.V6.vsubbnq
- __builtin_HEXAGON_V6_vsubbnq(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vsubbnq.128B
- __builtin_HEXAGON_V6_vsubbnq_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vsubbq
- __builtin_HEXAGON_V6_vsubbq(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vsubbq.128B
- __builtin_HEXAGON_V6_vsubbq_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vsubbsat
- __builtin_HEXAGON_V6_vsubbsat(v64, v64);
- // CHECK: @llvm.hexagon.V6.vsubbsat.128B
- __builtin_HEXAGON_V6_vsubbsat_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vsubbsat.dv
- __builtin_HEXAGON_V6_vsubbsat_dv(v128, v128);
- // CHECK: @llvm.hexagon.V6.vsubbsat.dv.128B
- __builtin_HEXAGON_V6_vsubbsat_dv_128B(v256, v256);
- // CHECK: @llvm.hexagon.V6.vsubcarry
- __builtin_HEXAGON_V6_vsubcarry(v64, v64, 0);
- // CHECK: @llvm.hexagon.V6.vsubcarry.128B
- __builtin_HEXAGON_V6_vsubcarry_128B(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vsubh
- __builtin_HEXAGON_V6_vsubh(v64, v64);
- // CHECK: @llvm.hexagon.V6.vsubh.128B
- __builtin_HEXAGON_V6_vsubh_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vsubh.dv
- __builtin_HEXAGON_V6_vsubh_dv(v128, v128);
- // CHECK: @llvm.hexagon.V6.vsubh.dv.128B
- __builtin_HEXAGON_V6_vsubh_dv_128B(v256, v256);
- // CHECK: @llvm.hexagon.V6.vsubhnq
- __builtin_HEXAGON_V6_vsubhnq(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vsubhnq.128B
- __builtin_HEXAGON_V6_vsubhnq_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vsubhq
- __builtin_HEXAGON_V6_vsubhq(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vsubhq.128B
- __builtin_HEXAGON_V6_vsubhq_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vsubhsat
- __builtin_HEXAGON_V6_vsubhsat(v64, v64);
- // CHECK: @llvm.hexagon.V6.vsubhsat.128B
- __builtin_HEXAGON_V6_vsubhsat_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vsubhsat.dv
- __builtin_HEXAGON_V6_vsubhsat_dv(v128, v128);
- // CHECK: @llvm.hexagon.V6.vsubhsat.dv.128B
- __builtin_HEXAGON_V6_vsubhsat_dv_128B(v256, v256);
- // CHECK: @llvm.hexagon.V6.vsubhw
- __builtin_HEXAGON_V6_vsubhw(v64, v64);
- // CHECK: @llvm.hexagon.V6.vsubhw.128B
- __builtin_HEXAGON_V6_vsubhw_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vsububh
- __builtin_HEXAGON_V6_vsububh(v64, v64);
- // CHECK: @llvm.hexagon.V6.vsububh.128B
- __builtin_HEXAGON_V6_vsububh_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vsububsat
- __builtin_HEXAGON_V6_vsububsat(v64, v64);
- // CHECK: @llvm.hexagon.V6.vsububsat.128B
- __builtin_HEXAGON_V6_vsububsat_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vsububsat.dv
- __builtin_HEXAGON_V6_vsububsat_dv(v128, v128);
- // CHECK: @llvm.hexagon.V6.vsububsat.dv.128B
- __builtin_HEXAGON_V6_vsububsat_dv_128B(v256, v256);
- // CHECK: @llvm.hexagon.V6.vsubububb.sat
- __builtin_HEXAGON_V6_vsubububb_sat(v64, v64);
- // CHECK: @llvm.hexagon.V6.vsubububb.sat.128B
- __builtin_HEXAGON_V6_vsubububb_sat_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vsubuhsat
- __builtin_HEXAGON_V6_vsubuhsat(v64, v64);
- // CHECK: @llvm.hexagon.V6.vsubuhsat.128B
- __builtin_HEXAGON_V6_vsubuhsat_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vsubuhsat.dv
- __builtin_HEXAGON_V6_vsubuhsat_dv(v128, v128);
- // CHECK: @llvm.hexagon.V6.vsubuhsat.dv.128B
- __builtin_HEXAGON_V6_vsubuhsat_dv_128B(v256, v256);
- // CHECK: @llvm.hexagon.V6.vsubuhw
- __builtin_HEXAGON_V6_vsubuhw(v64, v64);
- // CHECK: @llvm.hexagon.V6.vsubuhw.128B
- __builtin_HEXAGON_V6_vsubuhw_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vsubuwsat
- __builtin_HEXAGON_V6_vsubuwsat(v64, v64);
- // CHECK: @llvm.hexagon.V6.vsubuwsat.128B
- __builtin_HEXAGON_V6_vsubuwsat_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vsubuwsat.dv
- __builtin_HEXAGON_V6_vsubuwsat_dv(v128, v128);
- // CHECK: @llvm.hexagon.V6.vsubuwsat.dv.128B
- __builtin_HEXAGON_V6_vsubuwsat_dv_128B(v256, v256);
- // CHECK: @llvm.hexagon.V6.vsubw
- __builtin_HEXAGON_V6_vsubw(v64, v64);
- // CHECK: @llvm.hexagon.V6.vsubw.128B
- __builtin_HEXAGON_V6_vsubw_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vsubw.dv
- __builtin_HEXAGON_V6_vsubw_dv(v128, v128);
- // CHECK: @llvm.hexagon.V6.vsubw.dv.128B
- __builtin_HEXAGON_V6_vsubw_dv_128B(v256, v256);
- // CHECK: @llvm.hexagon.V6.vsubwnq
- __builtin_HEXAGON_V6_vsubwnq(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vsubwnq.128B
- __builtin_HEXAGON_V6_vsubwnq_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vsubwq
- __builtin_HEXAGON_V6_vsubwq(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vsubwq.128B
- __builtin_HEXAGON_V6_vsubwq_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vsubwsat
- __builtin_HEXAGON_V6_vsubwsat(v64, v64);
- // CHECK: @llvm.hexagon.V6.vsubwsat.128B
- __builtin_HEXAGON_V6_vsubwsat_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vsubwsat.dv
- __builtin_HEXAGON_V6_vsubwsat_dv(v128, v128);
- // CHECK: @llvm.hexagon.V6.vsubwsat.dv.128B
- __builtin_HEXAGON_V6_vsubwsat_dv_128B(v256, v256);
- // CHECK: @llvm.hexagon.V6.vswap
- __builtin_HEXAGON_V6_vswap(v64, v64, v64);
- // CHECK: @llvm.hexagon.V6.vswap.128B
- __builtin_HEXAGON_V6_vswap_128B(v128, v128, v128);
- // CHECK: @llvm.hexagon.V6.vtmpyb
- __builtin_HEXAGON_V6_vtmpyb(v128, 0);
- // CHECK: @llvm.hexagon.V6.vtmpyb.128B
- __builtin_HEXAGON_V6_vtmpyb_128B(v256, 0);
- // CHECK: @llvm.hexagon.V6.vtmpyb.acc
- __builtin_HEXAGON_V6_vtmpyb_acc(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vtmpyb.acc.128B
- __builtin_HEXAGON_V6_vtmpyb_acc_128B(v256, v256, 0);
- // CHECK: @llvm.hexagon.V6.vtmpybus
- __builtin_HEXAGON_V6_vtmpybus(v128, 0);
- // CHECK: @llvm.hexagon.V6.vtmpybus.128B
- __builtin_HEXAGON_V6_vtmpybus_128B(v256, 0);
- // CHECK: @llvm.hexagon.V6.vtmpybus.acc
- __builtin_HEXAGON_V6_vtmpybus_acc(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vtmpybus.acc.128B
- __builtin_HEXAGON_V6_vtmpybus_acc_128B(v256, v256, 0);
- // CHECK: @llvm.hexagon.V6.vtmpyhb
- __builtin_HEXAGON_V6_vtmpyhb(v128, 0);
- // CHECK: @llvm.hexagon.V6.vtmpyhb.128B
- __builtin_HEXAGON_V6_vtmpyhb_128B(v256, 0);
- // CHECK: @llvm.hexagon.V6.vtmpyhb.acc
- __builtin_HEXAGON_V6_vtmpyhb_acc(v128, v128, 0);
- // CHECK: @llvm.hexagon.V6.vtmpyhb.acc.128B
- __builtin_HEXAGON_V6_vtmpyhb_acc_128B(v256, v256, 0);
- // CHECK: @llvm.hexagon.V6.vunpackb
- __builtin_HEXAGON_V6_vunpackb(v64);
- // CHECK: @llvm.hexagon.V6.vunpackb.128B
- __builtin_HEXAGON_V6_vunpackb_128B(v128);
- // CHECK: @llvm.hexagon.V6.vunpackh
- __builtin_HEXAGON_V6_vunpackh(v64);
- // CHECK: @llvm.hexagon.V6.vunpackh.128B
- __builtin_HEXAGON_V6_vunpackh_128B(v128);
- // CHECK: @llvm.hexagon.V6.vunpackob
- __builtin_HEXAGON_V6_vunpackob(v128, v64);
- // CHECK: @llvm.hexagon.V6.vunpackob.128B
- __builtin_HEXAGON_V6_vunpackob_128B(v256, v128);
- // CHECK: @llvm.hexagon.V6.vunpackoh
- __builtin_HEXAGON_V6_vunpackoh(v128, v64);
- // CHECK: @llvm.hexagon.V6.vunpackoh.128B
- __builtin_HEXAGON_V6_vunpackoh_128B(v256, v128);
- // CHECK: @llvm.hexagon.V6.vunpackub
- __builtin_HEXAGON_V6_vunpackub(v64);
- // CHECK: @llvm.hexagon.V6.vunpackub.128B
- __builtin_HEXAGON_V6_vunpackub_128B(v128);
- // CHECK: @llvm.hexagon.V6.vunpackuh
- __builtin_HEXAGON_V6_vunpackuh(v64);
- // CHECK: @llvm.hexagon.V6.vunpackuh.128B
- __builtin_HEXAGON_V6_vunpackuh_128B(v128);
- // CHECK: @llvm.hexagon.V6.vxor
- __builtin_HEXAGON_V6_vxor(v64, v64);
- // CHECK: @llvm.hexagon.V6.vxor.128B
- __builtin_HEXAGON_V6_vxor_128B(v128, v128);
- // CHECK: @llvm.hexagon.V6.vzb
- __builtin_HEXAGON_V6_vzb(v64);
- // CHECK: @llvm.hexagon.V6.vzb.128B
- __builtin_HEXAGON_V6_vzb_128B(v128);
- // CHECK: @llvm.hexagon.V6.vzh
- __builtin_HEXAGON_V6_vzh(v64);
- // CHECK: @llvm.hexagon.V6.vzh.128B
- __builtin_HEXAGON_V6_vzh_128B(v128);
// CHECK: @llvm.hexagon.Y2.dccleana
__builtin_HEXAGON_Y2_dccleana(0);
// CHECK: @llvm.hexagon.Y2.dccleaninva
@@ -3322,28 +1734,30 @@ void test() {
__builtin_HEXAGON_Y4_l2fetch(0, 0);
// CHECK: @llvm.hexagon.Y5.l2fetch
__builtin_HEXAGON_Y5_l2fetch(0, 0);
- // CHECK: @llvm.hexagon.brev.ldb
+
+ // CHECK: @llvm.hexagon.L2.loadrb.pbr
__builtin_brev_ldb(0, 0, 0);
- // CHECK: @llvm.hexagon.brev.ldd
+ // CHECK: @llvm.hexagon.L2.loadrd.pbr
__builtin_brev_ldd(0, 0, 0);
- // CHECK: @llvm.hexagon.brev.ldh
+ // CHECK: @llvm.hexagon.L2.loadrh.pbr
__builtin_brev_ldh(0, 0, 0);
- // CHECK: @llvm.hexagon.brev.ldub
+ // CHECK: @llvm.hexagon.L2.loadrub.pbr
__builtin_brev_ldub(0, 0, 0);
- // CHECK: @llvm.hexagon.brev.lduh
+ // CHECK: @llvm.hexagon.L2.loadruh.pbr
__builtin_brev_lduh(0, 0, 0);
- // CHECK: @llvm.hexagon.brev.ldw
+ // CHECK: @llvm.hexagon.L2.loadri.pbr
__builtin_brev_ldw(0, 0, 0);
- // CHECK: @llvm.hexagon.brev.stb
+ // CHECK: @llvm.hexagon.S2.storerb.pbr
__builtin_brev_stb(0, 0, 0);
- // CHECK: @llvm.hexagon.brev.std
- __builtin_brev_std(0, 0, 0);
- // CHECK: @llvm.hexagon.brev.sth
+ // CHECK: @llvm.hexagon.S2.storerd.pbr
+ __builtin_brev_std(0, 0LL, 0);
+ // CHECK: @llvm.hexagon.S2.storerh.pbr
__builtin_brev_sth(0, 0, 0);
- // CHECK: @llvm.hexagon.brev.sthhi
+ // CHECK: @llvm.hexagon.S2.storerf.pbr
__builtin_brev_sthhi(0, 0, 0);
- // CHECK: @llvm.hexagon.brev.stw
+ // CHECK: @llvm.hexagon.S2.storeri.pbr
__builtin_brev_stw(0, 0, 0);
+
// CHECK: @llvm.hexagon.circ.ldb
__builtin_circ_ldb(0, 0, 0, 0);
// CHECK: @llvm.hexagon.circ.ldd
diff --git a/test/CodeGen/builtins-hvx128.c b/test/CodeGen/builtins-hvx128.c
new file mode 100644
index 000000000000..07d0e050ddc0
--- /dev/null
+++ b/test/CodeGen/builtins-hvx128.c
@@ -0,0 +1,802 @@
+// REQUIRES: hexagon-registered-target
+// RUN: %clang_cc1 -triple hexagon-unknown-elf -target-cpu hexagonv65 -target-feature +hvxv65 -target-feature +hvx-length128b -emit-llvm %s -o - | FileCheck %s
+
+void test() {
+ int v128 __attribute__((__vector_size__(128)));
+ int v256 __attribute__((__vector_size__(256)));
+
+ // CHECK: @llvm.hexagon.V6.extractw.128B
+ __builtin_HEXAGON_V6_extractw_128B(v128, 0);
+ // CHECK: @llvm.hexagon.V6.hi.128B
+ __builtin_HEXAGON_V6_hi_128B(v256);
+ // CHECK: @llvm.hexagon.V6.lo.128B
+ __builtin_HEXAGON_V6_lo_128B(v256);
+ // CHECK: @llvm.hexagon.V6.lvsplatb.128B
+ __builtin_HEXAGON_V6_lvsplatb_128B(0);
+ // CHECK: @llvm.hexagon.V6.lvsplath.128B
+ __builtin_HEXAGON_V6_lvsplath_128B(0);
+ // CHECK: @llvm.hexagon.V6.lvsplatw.128B
+ __builtin_HEXAGON_V6_lvsplatw_128B(0);
+ // CHECK: @llvm.hexagon.V6.pred.and.128B
+ __builtin_HEXAGON_V6_pred_and_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.pred.and.n.128B
+ __builtin_HEXAGON_V6_pred_and_n_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.pred.not.128B
+ __builtin_HEXAGON_V6_pred_not_128B(v128);
+ // CHECK: @llvm.hexagon.V6.pred.or.128B
+ __builtin_HEXAGON_V6_pred_or_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.pred.or.n.128B
+ __builtin_HEXAGON_V6_pred_or_n_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.pred.scalar2.128B
+ __builtin_HEXAGON_V6_pred_scalar2_128B(0);
+ // CHECK: @llvm.hexagon.V6.pred.scalar2v2.128B
+ __builtin_HEXAGON_V6_pred_scalar2v2_128B(0);
+ // CHECK: @llvm.hexagon.V6.pred.xor.128B
+ __builtin_HEXAGON_V6_pred_xor_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.shuffeqh.128B
+ __builtin_HEXAGON_V6_shuffeqh_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.shuffeqw.128B
+ __builtin_HEXAGON_V6_shuffeqw_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vS32b.nqpred.ai.128B
+ __builtin_HEXAGON_V6_vS32b_nqpred_ai_128B(v128, 0, v128);
+ // CHECK: @llvm.hexagon.V6.vS32b.nt.nqpred.ai.128B
+ __builtin_HEXAGON_V6_vS32b_nt_nqpred_ai_128B(v128, 0, v128);
+ // CHECK: @llvm.hexagon.V6.vS32b.nt.qpred.ai.128B
+ __builtin_HEXAGON_V6_vS32b_nt_qpred_ai_128B(v128, 0, v128);
+ // CHECK: @llvm.hexagon.V6.vS32b.qpred.ai.128B
+ __builtin_HEXAGON_V6_vS32b_qpred_ai_128B(v128, 0, v128);
+ // CHECK: @llvm.hexagon.V6.vabsb.128B
+ __builtin_HEXAGON_V6_vabsb_128B(v128);
+ // CHECK: @llvm.hexagon.V6.vabsb.sat.128B
+ __builtin_HEXAGON_V6_vabsb_sat_128B(v128);
+ // CHECK: @llvm.hexagon.V6.vabsdiffh.128B
+ __builtin_HEXAGON_V6_vabsdiffh_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vabsdiffub.128B
+ __builtin_HEXAGON_V6_vabsdiffub_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vabsdiffuh.128B
+ __builtin_HEXAGON_V6_vabsdiffuh_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vabsdiffw.128B
+ __builtin_HEXAGON_V6_vabsdiffw_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vabsh.128B
+ __builtin_HEXAGON_V6_vabsh_128B(v128);
+ // CHECK: @llvm.hexagon.V6.vabsh.sat.128B
+ __builtin_HEXAGON_V6_vabsh_sat_128B(v128);
+ // CHECK: @llvm.hexagon.V6.vabsw.128B
+ __builtin_HEXAGON_V6_vabsw_128B(v128);
+ // CHECK: @llvm.hexagon.V6.vabsw.sat.128B
+ __builtin_HEXAGON_V6_vabsw_sat_128B(v128);
+ // CHECK: @llvm.hexagon.V6.vaddb.128B
+ __builtin_HEXAGON_V6_vaddb_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vaddb.dv.128B
+ __builtin_HEXAGON_V6_vaddb_dv_128B(v256, v256);
+ // CHECK: @llvm.hexagon.V6.vaddbnq.128B
+ __builtin_HEXAGON_V6_vaddbnq_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vaddbq.128B
+ __builtin_HEXAGON_V6_vaddbq_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vaddbsat.128B
+ __builtin_HEXAGON_V6_vaddbsat_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vaddbsat.dv.128B
+ __builtin_HEXAGON_V6_vaddbsat_dv_128B(v256, v256);
+ // CHECK: @llvm.hexagon.V6.vaddcarry.128B
+ __builtin_HEXAGON_V6_vaddcarry_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vaddclbh.128B
+ __builtin_HEXAGON_V6_vaddclbh_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vaddclbw.128B
+ __builtin_HEXAGON_V6_vaddclbw_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vaddh.128B
+ __builtin_HEXAGON_V6_vaddh_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vaddh.dv.128B
+ __builtin_HEXAGON_V6_vaddh_dv_128B(v256, v256);
+ // CHECK: @llvm.hexagon.V6.vaddhnq.128B
+ __builtin_HEXAGON_V6_vaddhnq_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vaddhq.128B
+ __builtin_HEXAGON_V6_vaddhq_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vaddhsat.128B
+ __builtin_HEXAGON_V6_vaddhsat_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vaddhsat.dv.128B
+ __builtin_HEXAGON_V6_vaddhsat_dv_128B(v256, v256);
+ // CHECK: @llvm.hexagon.V6.vaddhw.128B
+ __builtin_HEXAGON_V6_vaddhw_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vaddhw.acc.128B
+ __builtin_HEXAGON_V6_vaddhw_acc_128B(v256, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vaddubh.128B
+ __builtin_HEXAGON_V6_vaddubh_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vaddubh.acc.128B
+ __builtin_HEXAGON_V6_vaddubh_acc_128B(v256, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vaddubsat.128B
+ __builtin_HEXAGON_V6_vaddubsat_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vaddubsat.dv.128B
+ __builtin_HEXAGON_V6_vaddubsat_dv_128B(v256, v256);
+ // CHECK: @llvm.hexagon.V6.vaddububb.sat.128B
+ __builtin_HEXAGON_V6_vaddububb_sat_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vadduhsat.128B
+ __builtin_HEXAGON_V6_vadduhsat_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vadduhsat.dv.128B
+ __builtin_HEXAGON_V6_vadduhsat_dv_128B(v256, v256);
+ // CHECK: @llvm.hexagon.V6.vadduhw.128B
+ __builtin_HEXAGON_V6_vadduhw_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vadduhw.acc.128B
+ __builtin_HEXAGON_V6_vadduhw_acc_128B(v256, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vadduwsat.128B
+ __builtin_HEXAGON_V6_vadduwsat_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vadduwsat.dv.128B
+ __builtin_HEXAGON_V6_vadduwsat_dv_128B(v256, v256);
+ // CHECK: @llvm.hexagon.V6.vaddw.128B
+ __builtin_HEXAGON_V6_vaddw_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vaddw.dv.128B
+ __builtin_HEXAGON_V6_vaddw_dv_128B(v256, v256);
+ // CHECK: @llvm.hexagon.V6.vaddwnq.128B
+ __builtin_HEXAGON_V6_vaddwnq_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vaddwq.128B
+ __builtin_HEXAGON_V6_vaddwq_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vaddwsat.128B
+ __builtin_HEXAGON_V6_vaddwsat_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vaddwsat.dv.128B
+ __builtin_HEXAGON_V6_vaddwsat_dv_128B(v256, v256);
+ // CHECK: @llvm.hexagon.V6.valignb.128B
+ __builtin_HEXAGON_V6_valignb_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.valignbi.128B
+ __builtin_HEXAGON_V6_valignbi_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vand.128B
+ __builtin_HEXAGON_V6_vand_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vandnqrt.128B
+ __builtin_HEXAGON_V6_vandnqrt_128B(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vandnqrt.acc.128B
+ __builtin_HEXAGON_V6_vandnqrt_acc_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vandqrt.128B
+ __builtin_HEXAGON_V6_vandqrt_128B(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vandqrt.acc.128B
+ __builtin_HEXAGON_V6_vandqrt_acc_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vandvnqv.128B
+ __builtin_HEXAGON_V6_vandvnqv_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vandvqv.128B
+ __builtin_HEXAGON_V6_vandvqv_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vandvrt.128B
+ __builtin_HEXAGON_V6_vandvrt_128B(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vandvrt.acc.128B
+ __builtin_HEXAGON_V6_vandvrt_acc_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vaslh.128B
+ __builtin_HEXAGON_V6_vaslh_128B(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vaslh.acc.128B
+ __builtin_HEXAGON_V6_vaslh_acc_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vaslhv.128B
+ __builtin_HEXAGON_V6_vaslhv_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vaslw.128B
+ __builtin_HEXAGON_V6_vaslw_128B(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vaslw.acc.128B
+ __builtin_HEXAGON_V6_vaslw_acc_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vaslwv.128B
+ __builtin_HEXAGON_V6_vaslwv_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vasrh.128B
+ __builtin_HEXAGON_V6_vasrh_128B(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vasrh.acc.128B
+ __builtin_HEXAGON_V6_vasrh_acc_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vasrhbrndsat.128B
+ __builtin_HEXAGON_V6_vasrhbrndsat_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vasrhbsat.128B
+ __builtin_HEXAGON_V6_vasrhbsat_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vasrhubrndsat.128B
+ __builtin_HEXAGON_V6_vasrhubrndsat_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vasrhubsat.128B
+ __builtin_HEXAGON_V6_vasrhubsat_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vasrhv.128B
+ __builtin_HEXAGON_V6_vasrhv_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vasruhubrndsat.128B
+ __builtin_HEXAGON_V6_vasruhubrndsat_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vasruhubsat.128B
+ __builtin_HEXAGON_V6_vasruhubsat_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vasruwuhrndsat.128B
+ __builtin_HEXAGON_V6_vasruwuhrndsat_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vasruwuhsat.128B
+ __builtin_HEXAGON_V6_vasruwuhsat_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vasrw.128B
+ __builtin_HEXAGON_V6_vasrw_128B(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vasrw.acc.128B
+ __builtin_HEXAGON_V6_vasrw_acc_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vasrwh.128B
+ __builtin_HEXAGON_V6_vasrwh_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vasrwhrndsat.128B
+ __builtin_HEXAGON_V6_vasrwhrndsat_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vasrwhsat.128B
+ __builtin_HEXAGON_V6_vasrwhsat_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vasrwuhrndsat.128B
+ __builtin_HEXAGON_V6_vasrwuhrndsat_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vasrwuhsat.128B
+ __builtin_HEXAGON_V6_vasrwuhsat_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vasrwv.128B
+ __builtin_HEXAGON_V6_vasrwv_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vassign.128B
+ __builtin_HEXAGON_V6_vassign_128B(v128);
+ // CHECK: @llvm.hexagon.V6.vassignp.128B
+ __builtin_HEXAGON_V6_vassignp_128B(v256);
+ // CHECK: @llvm.hexagon.V6.vavgb.128B
+ __builtin_HEXAGON_V6_vavgb_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vavgbrnd.128B
+ __builtin_HEXAGON_V6_vavgbrnd_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vavgh.128B
+ __builtin_HEXAGON_V6_vavgh_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vavghrnd.128B
+ __builtin_HEXAGON_V6_vavghrnd_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vavgub.128B
+ __builtin_HEXAGON_V6_vavgub_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vavgubrnd.128B
+ __builtin_HEXAGON_V6_vavgubrnd_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vavguh.128B
+ __builtin_HEXAGON_V6_vavguh_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vavguhrnd.128B
+ __builtin_HEXAGON_V6_vavguhrnd_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vavguw.128B
+ __builtin_HEXAGON_V6_vavguw_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vavguwrnd.128B
+ __builtin_HEXAGON_V6_vavguwrnd_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vavgw.128B
+ __builtin_HEXAGON_V6_vavgw_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vavgwrnd.128B
+ __builtin_HEXAGON_V6_vavgwrnd_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vcl0h.128B
+ __builtin_HEXAGON_V6_vcl0h_128B(v128);
+ // CHECK: @llvm.hexagon.V6.vcl0w.128B
+ __builtin_HEXAGON_V6_vcl0w_128B(v128);
+ // CHECK: @llvm.hexagon.V6.vcombine.128B
+ __builtin_HEXAGON_V6_vcombine_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vd0.128B
+ __builtin_HEXAGON_V6_vd0_128B();
+ // CHECK: @llvm.hexagon.V6.vdd0.128B
+ __builtin_HEXAGON_V6_vdd0_128B();
+ // CHECK: @llvm.hexagon.V6.vdealb.128B
+ __builtin_HEXAGON_V6_vdealb_128B(v128);
+ // CHECK: @llvm.hexagon.V6.vdealb4w.128B
+ __builtin_HEXAGON_V6_vdealb4w_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vdealh.128B
+ __builtin_HEXAGON_V6_vdealh_128B(v128);
+ // CHECK: @llvm.hexagon.V6.vdealvdd.128B
+ __builtin_HEXAGON_V6_vdealvdd_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vdelta.128B
+ __builtin_HEXAGON_V6_vdelta_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vdmpybus.128B
+ __builtin_HEXAGON_V6_vdmpybus_128B(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vdmpybus.acc.128B
+ __builtin_HEXAGON_V6_vdmpybus_acc_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vdmpybus.dv.128B
+ __builtin_HEXAGON_V6_vdmpybus_dv_128B(v256, 0);
+ // CHECK: @llvm.hexagon.V6.vdmpybus.dv.acc.128B
+ __builtin_HEXAGON_V6_vdmpybus_dv_acc_128B(v256, v256, 0);
+ // CHECK: @llvm.hexagon.V6.vdmpyhb.128B
+ __builtin_HEXAGON_V6_vdmpyhb_128B(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vdmpyhb.acc.128B
+ __builtin_HEXAGON_V6_vdmpyhb_acc_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vdmpyhb.dv.128B
+ __builtin_HEXAGON_V6_vdmpyhb_dv_128B(v256, 0);
+ // CHECK: @llvm.hexagon.V6.vdmpyhb.dv.acc.128B
+ __builtin_HEXAGON_V6_vdmpyhb_dv_acc_128B(v256, v256, 0);
+ // CHECK: @llvm.hexagon.V6.vdmpyhisat.128B
+ __builtin_HEXAGON_V6_vdmpyhisat_128B(v256, 0);
+ // CHECK: @llvm.hexagon.V6.vdmpyhisat.acc.128B
+ __builtin_HEXAGON_V6_vdmpyhisat_acc_128B(v128, v256, 0);
+ // CHECK: @llvm.hexagon.V6.vdmpyhsat.128B
+ __builtin_HEXAGON_V6_vdmpyhsat_128B(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vdmpyhsat.acc.128B
+ __builtin_HEXAGON_V6_vdmpyhsat_acc_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vdmpyhsuisat.128B
+ __builtin_HEXAGON_V6_vdmpyhsuisat_128B(v256, 0);
+ // CHECK: @llvm.hexagon.V6.vdmpyhsuisat.acc.128B
+ __builtin_HEXAGON_V6_vdmpyhsuisat_acc_128B(v128, v256, 0);
+ // CHECK: @llvm.hexagon.V6.vdmpyhsusat.128B
+ __builtin_HEXAGON_V6_vdmpyhsusat_128B(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vdmpyhsusat.acc.128B
+ __builtin_HEXAGON_V6_vdmpyhsusat_acc_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vdmpyhvsat.128B
+ __builtin_HEXAGON_V6_vdmpyhvsat_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vdmpyhvsat.acc.128B
+ __builtin_HEXAGON_V6_vdmpyhvsat_acc_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vdsaduh.128B
+ __builtin_HEXAGON_V6_vdsaduh_128B(v256, 0);
+ // CHECK: @llvm.hexagon.V6.vdsaduh.acc.128B
+ __builtin_HEXAGON_V6_vdsaduh_acc_128B(v256, v256, 0);
+ // CHECK: @llvm.hexagon.V6.veqb.128B
+ __builtin_HEXAGON_V6_veqb_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.veqb.and.128B
+ __builtin_HEXAGON_V6_veqb_and_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.veqb.or.128B
+ __builtin_HEXAGON_V6_veqb_or_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.veqb.xor.128B
+ __builtin_HEXAGON_V6_veqb_xor_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.veqh.128B
+ __builtin_HEXAGON_V6_veqh_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.veqh.and.128B
+ __builtin_HEXAGON_V6_veqh_and_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.veqh.or.128B
+ __builtin_HEXAGON_V6_veqh_or_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.veqh.xor.128B
+ __builtin_HEXAGON_V6_veqh_xor_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.veqw.128B
+ __builtin_HEXAGON_V6_veqw_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.veqw.and.128B
+ __builtin_HEXAGON_V6_veqw_and_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.veqw.or.128B
+ __builtin_HEXAGON_V6_veqw_or_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.veqw.xor.128B
+ __builtin_HEXAGON_V6_veqw_xor_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vgathermh.128B
+ __builtin_HEXAGON_V6_vgathermh_128B(0, 0, 0, v128);
+ // CHECK: @llvm.hexagon.V6.vgathermhq.128B
+ __builtin_HEXAGON_V6_vgathermhq_128B(0, v128, 0, 0, v128);
+ // CHECK: @llvm.hexagon.V6.vgathermhw.128B
+ __builtin_HEXAGON_V6_vgathermhw_128B(0, 0, 0, v256);
+ // CHECK: @llvm.hexagon.V6.vgathermhwq.128B
+ __builtin_HEXAGON_V6_vgathermhwq_128B(0, v128, 0, 0, v256);
+ // CHECK: @llvm.hexagon.V6.vgathermw.128B
+ __builtin_HEXAGON_V6_vgathermw_128B(0, 0, 0, v128);
+ // CHECK: @llvm.hexagon.V6.vgathermwq.128B
+ __builtin_HEXAGON_V6_vgathermwq_128B(0, v128, 0, 0, v128);
+ // CHECK: @llvm.hexagon.V6.vgtb.128B
+ __builtin_HEXAGON_V6_vgtb_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vgtb.and.128B
+ __builtin_HEXAGON_V6_vgtb_and_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vgtb.or.128B
+ __builtin_HEXAGON_V6_vgtb_or_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vgtb.xor.128B
+ __builtin_HEXAGON_V6_vgtb_xor_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vgth.128B
+ __builtin_HEXAGON_V6_vgth_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vgth.and.128B
+ __builtin_HEXAGON_V6_vgth_and_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vgth.or.128B
+ __builtin_HEXAGON_V6_vgth_or_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vgth.xor.128B
+ __builtin_HEXAGON_V6_vgth_xor_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vgtub.128B
+ __builtin_HEXAGON_V6_vgtub_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vgtub.and.128B
+ __builtin_HEXAGON_V6_vgtub_and_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vgtub.or.128B
+ __builtin_HEXAGON_V6_vgtub_or_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vgtub.xor.128B
+ __builtin_HEXAGON_V6_vgtub_xor_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vgtuh.128B
+ __builtin_HEXAGON_V6_vgtuh_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vgtuh.and.128B
+ __builtin_HEXAGON_V6_vgtuh_and_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vgtuh.or.128B
+ __builtin_HEXAGON_V6_vgtuh_or_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vgtuh.xor.128B
+ __builtin_HEXAGON_V6_vgtuh_xor_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vgtuw.128B
+ __builtin_HEXAGON_V6_vgtuw_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vgtuw.and.128B
+ __builtin_HEXAGON_V6_vgtuw_and_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vgtuw.or.128B
+ __builtin_HEXAGON_V6_vgtuw_or_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vgtuw.xor.128B
+ __builtin_HEXAGON_V6_vgtuw_xor_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vgtw.128B
+ __builtin_HEXAGON_V6_vgtw_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vgtw.and.128B
+ __builtin_HEXAGON_V6_vgtw_and_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vgtw.or.128B
+ __builtin_HEXAGON_V6_vgtw_or_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vgtw.xor.128B
+ __builtin_HEXAGON_V6_vgtw_xor_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vinsertwr.128B
+ __builtin_HEXAGON_V6_vinsertwr_128B(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vlalignb.128B
+ __builtin_HEXAGON_V6_vlalignb_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vlalignbi.128B
+ __builtin_HEXAGON_V6_vlalignbi_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vlsrb.128B
+ __builtin_HEXAGON_V6_vlsrb_128B(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vlsrh.128B
+ __builtin_HEXAGON_V6_vlsrh_128B(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vlsrhv.128B
+ __builtin_HEXAGON_V6_vlsrhv_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vlsrw.128B
+ __builtin_HEXAGON_V6_vlsrw_128B(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vlsrwv.128B
+ __builtin_HEXAGON_V6_vlsrwv_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vlut4.128B
+ __builtin_HEXAGON_V6_vlut4_128B(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vlutvvb.128B
+ __builtin_HEXAGON_V6_vlutvvb_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vlutvvb.nm.128B
+ __builtin_HEXAGON_V6_vlutvvb_nm_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vlutvvb.oracc.128B
+ __builtin_HEXAGON_V6_vlutvvb_oracc_128B(v128, v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vlutvvb.oracci.128B
+ __builtin_HEXAGON_V6_vlutvvb_oracci_128B(v128, v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vlutvvbi.128B
+ __builtin_HEXAGON_V6_vlutvvbi_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vlutvwh.128B
+ __builtin_HEXAGON_V6_vlutvwh_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vlutvwh.nm.128B
+ __builtin_HEXAGON_V6_vlutvwh_nm_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vlutvwh.oracc.128B
+ __builtin_HEXAGON_V6_vlutvwh_oracc_128B(v256, v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vlutvwh.oracci.128B
+ __builtin_HEXAGON_V6_vlutvwh_oracci_128B(v256, v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vlutvwhi.128B
+ __builtin_HEXAGON_V6_vlutvwhi_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vmaskedstorenq.128B
+ __builtin_HEXAGON_V6_vmaskedstorenq_128B(v128, 0, v128);
+ // CHECK: @llvm.hexagon.V6.vmaskedstorentnq.128B
+ __builtin_HEXAGON_V6_vmaskedstorentnq_128B(v128, 0, v128);
+ // CHECK: @llvm.hexagon.V6.vmaskedstorentq.128B
+ __builtin_HEXAGON_V6_vmaskedstorentq_128B(v128, 0, v128);
+ // CHECK: @llvm.hexagon.V6.vmaskedstoreq.128B
+ __builtin_HEXAGON_V6_vmaskedstoreq_128B(v128, 0, v128);
+ // CHECK: @llvm.hexagon.V6.vmaxb.128B
+ __builtin_HEXAGON_V6_vmaxb_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmaxh.128B
+ __builtin_HEXAGON_V6_vmaxh_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmaxub.128B
+ __builtin_HEXAGON_V6_vmaxub_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmaxuh.128B
+ __builtin_HEXAGON_V6_vmaxuh_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmaxw.128B
+ __builtin_HEXAGON_V6_vmaxw_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vminb.128B
+ __builtin_HEXAGON_V6_vminb_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vminh.128B
+ __builtin_HEXAGON_V6_vminh_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vminub.128B
+ __builtin_HEXAGON_V6_vminub_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vminuh.128B
+ __builtin_HEXAGON_V6_vminuh_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vminw.128B
+ __builtin_HEXAGON_V6_vminw_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmpabus.128B
+ __builtin_HEXAGON_V6_vmpabus_128B(v256, 0);
+ // CHECK: @llvm.hexagon.V6.vmpabus.acc.128B
+ __builtin_HEXAGON_V6_vmpabus_acc_128B(v256, v256, 0);
+ // CHECK: @llvm.hexagon.V6.vmpabusv.128B
+ __builtin_HEXAGON_V6_vmpabusv_128B(v256, v256);
+ // CHECK: @llvm.hexagon.V6.vmpabuu.128B
+ __builtin_HEXAGON_V6_vmpabuu_128B(v256, 0);
+ // CHECK: @llvm.hexagon.V6.vmpabuu.acc.128B
+ __builtin_HEXAGON_V6_vmpabuu_acc_128B(v256, v256, 0);
+ // CHECK: @llvm.hexagon.V6.vmpabuuv.128B
+ __builtin_HEXAGON_V6_vmpabuuv_128B(v256, v256);
+ // CHECK: @llvm.hexagon.V6.vmpahb.128B
+ __builtin_HEXAGON_V6_vmpahb_128B(v256, 0);
+ // CHECK: @llvm.hexagon.V6.vmpahb.acc.128B
+ __builtin_HEXAGON_V6_vmpahb_acc_128B(v256, v256, 0);
+ // CHECK: @llvm.hexagon.V6.vmpahhsat.128B
+ __builtin_HEXAGON_V6_vmpahhsat_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vmpauhb.128B
+ __builtin_HEXAGON_V6_vmpauhb_128B(v256, 0);
+ // CHECK: @llvm.hexagon.V6.vmpauhb.acc.128B
+ __builtin_HEXAGON_V6_vmpauhb_acc_128B(v256, v256, 0);
+ // CHECK: @llvm.hexagon.V6.vmpauhuhsat.128B
+ __builtin_HEXAGON_V6_vmpauhuhsat_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vmpsuhuhsat.128B
+ __builtin_HEXAGON_V6_vmpsuhuhsat_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vmpybus.128B
+ __builtin_HEXAGON_V6_vmpybus_128B(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vmpybus.acc.128B
+ __builtin_HEXAGON_V6_vmpybus_acc_128B(v256, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vmpybusv.128B
+ __builtin_HEXAGON_V6_vmpybusv_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmpybusv.acc.128B
+ __builtin_HEXAGON_V6_vmpybusv_acc_128B(v256, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmpybv.128B
+ __builtin_HEXAGON_V6_vmpybv_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmpybv.acc.128B
+ __builtin_HEXAGON_V6_vmpybv_acc_128B(v256, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmpyewuh.128B
+ __builtin_HEXAGON_V6_vmpyewuh_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmpyewuh.64.128B
+ __builtin_HEXAGON_V6_vmpyewuh_64_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmpyh.128B
+ __builtin_HEXAGON_V6_vmpyh_128B(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyh.acc.128B
+ __builtin_HEXAGON_V6_vmpyh_acc_128B(v256, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyhsat.acc.128B
+ __builtin_HEXAGON_V6_vmpyhsat_acc_128B(v256, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyhsrs.128B
+ __builtin_HEXAGON_V6_vmpyhsrs_128B(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyhss.128B
+ __builtin_HEXAGON_V6_vmpyhss_128B(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyhus.128B
+ __builtin_HEXAGON_V6_vmpyhus_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmpyhus.acc.128B
+ __builtin_HEXAGON_V6_vmpyhus_acc_128B(v256, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmpyhv.128B
+ __builtin_HEXAGON_V6_vmpyhv_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmpyhv.acc.128B
+ __builtin_HEXAGON_V6_vmpyhv_acc_128B(v256, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmpyhvsrs.128B
+ __builtin_HEXAGON_V6_vmpyhvsrs_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmpyieoh.128B
+ __builtin_HEXAGON_V6_vmpyieoh_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmpyiewh.acc.128B
+ __builtin_HEXAGON_V6_vmpyiewh_acc_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmpyiewuh.128B
+ __builtin_HEXAGON_V6_vmpyiewuh_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmpyiewuh.acc.128B
+ __builtin_HEXAGON_V6_vmpyiewuh_acc_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmpyih.128B
+ __builtin_HEXAGON_V6_vmpyih_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmpyih.acc.128B
+ __builtin_HEXAGON_V6_vmpyih_acc_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmpyihb.128B
+ __builtin_HEXAGON_V6_vmpyihb_128B(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyihb.acc.128B
+ __builtin_HEXAGON_V6_vmpyihb_acc_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyiowh.128B
+ __builtin_HEXAGON_V6_vmpyiowh_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmpyiwb.128B
+ __builtin_HEXAGON_V6_vmpyiwb_128B(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyiwb.acc.128B
+ __builtin_HEXAGON_V6_vmpyiwb_acc_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyiwh.128B
+ __builtin_HEXAGON_V6_vmpyiwh_128B(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyiwh.acc.128B
+ __builtin_HEXAGON_V6_vmpyiwh_acc_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyiwub.128B
+ __builtin_HEXAGON_V6_vmpyiwub_128B(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyiwub.acc.128B
+ __builtin_HEXAGON_V6_vmpyiwub_acc_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyowh.128B
+ __builtin_HEXAGON_V6_vmpyowh_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmpyowh.64.acc.128B
+ __builtin_HEXAGON_V6_vmpyowh_64_acc_128B(v256, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmpyowh.rnd.128B
+ __builtin_HEXAGON_V6_vmpyowh_rnd_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmpyowh.rnd.sacc.128B
+ __builtin_HEXAGON_V6_vmpyowh_rnd_sacc_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmpyowh.sacc.128B
+ __builtin_HEXAGON_V6_vmpyowh_sacc_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmpyub.128B
+ __builtin_HEXAGON_V6_vmpyub_128B(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyub.acc.128B
+ __builtin_HEXAGON_V6_vmpyub_acc_128B(v256, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyubv.128B
+ __builtin_HEXAGON_V6_vmpyubv_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmpyubv.acc.128B
+ __builtin_HEXAGON_V6_vmpyubv_acc_128B(v256, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmpyuh.128B
+ __builtin_HEXAGON_V6_vmpyuh_128B(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyuh.acc.128B
+ __builtin_HEXAGON_V6_vmpyuh_acc_128B(v256, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyuhe.128B
+ __builtin_HEXAGON_V6_vmpyuhe_128B(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyuhe.acc.128B
+ __builtin_HEXAGON_V6_vmpyuhe_acc_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyuhv.128B
+ __builtin_HEXAGON_V6_vmpyuhv_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmpyuhv.acc.128B
+ __builtin_HEXAGON_V6_vmpyuhv_acc_128B(v256, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmux.128B
+ __builtin_HEXAGON_V6_vmux_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vnavgb.128B
+ __builtin_HEXAGON_V6_vnavgb_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vnavgh.128B
+ __builtin_HEXAGON_V6_vnavgh_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vnavgub.128B
+ __builtin_HEXAGON_V6_vnavgub_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vnavgw.128B
+ __builtin_HEXAGON_V6_vnavgw_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vnormamth.128B
+ __builtin_HEXAGON_V6_vnormamth_128B(v128);
+ // CHECK: @llvm.hexagon.V6.vnormamtw.128B
+ __builtin_HEXAGON_V6_vnormamtw_128B(v128);
+ // CHECK: @llvm.hexagon.V6.vnot.128B
+ __builtin_HEXAGON_V6_vnot_128B(v128);
+ // CHECK: @llvm.hexagon.V6.vor.128B
+ __builtin_HEXAGON_V6_vor_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vpackeb.128B
+ __builtin_HEXAGON_V6_vpackeb_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vpackeh.128B
+ __builtin_HEXAGON_V6_vpackeh_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vpackhb.sat.128B
+ __builtin_HEXAGON_V6_vpackhb_sat_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vpackhub.sat.128B
+ __builtin_HEXAGON_V6_vpackhub_sat_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vpackob.128B
+ __builtin_HEXAGON_V6_vpackob_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vpackoh.128B
+ __builtin_HEXAGON_V6_vpackoh_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vpackwh.sat.128B
+ __builtin_HEXAGON_V6_vpackwh_sat_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vpackwuh.sat.128B
+ __builtin_HEXAGON_V6_vpackwuh_sat_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vpopcounth.128B
+ __builtin_HEXAGON_V6_vpopcounth_128B(v128);
+ // CHECK: @llvm.hexagon.V6.vprefixqb.128B
+ __builtin_HEXAGON_V6_vprefixqb_128B(v128);
+ // CHECK: @llvm.hexagon.V6.vprefixqh.128B
+ __builtin_HEXAGON_V6_vprefixqh_128B(v128);
+ // CHECK: @llvm.hexagon.V6.vprefixqw.128B
+ __builtin_HEXAGON_V6_vprefixqw_128B(v128);
+ // CHECK: @llvm.hexagon.V6.vrdelta.128B
+ __builtin_HEXAGON_V6_vrdelta_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vrmpybub.rtt.128B
+ __builtin_HEXAGON_V6_vrmpybub_rtt_128B(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vrmpybub.rtt.acc.128B
+ __builtin_HEXAGON_V6_vrmpybub_rtt_acc_128B(v256, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vrmpybus.128B
+ __builtin_HEXAGON_V6_vrmpybus_128B(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vrmpybus.acc.128B
+ __builtin_HEXAGON_V6_vrmpybus_acc_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vrmpybusi.128B
+ __builtin_HEXAGON_V6_vrmpybusi_128B(v256, 0, 0);
+ // CHECK: @llvm.hexagon.V6.vrmpybusi.acc.128B
+ __builtin_HEXAGON_V6_vrmpybusi_acc_128B(v256, v256, 0, 0);
+ // CHECK: @llvm.hexagon.V6.vrmpybusv.128B
+ __builtin_HEXAGON_V6_vrmpybusv_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vrmpybusv.acc.128B
+ __builtin_HEXAGON_V6_vrmpybusv_acc_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vrmpybv.128B
+ __builtin_HEXAGON_V6_vrmpybv_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vrmpybv.acc.128B
+ __builtin_HEXAGON_V6_vrmpybv_acc_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vrmpyub.128B
+ __builtin_HEXAGON_V6_vrmpyub_128B(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vrmpyub.acc.128B
+ __builtin_HEXAGON_V6_vrmpyub_acc_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vrmpyub.rtt.128B
+ __builtin_HEXAGON_V6_vrmpyub_rtt_128B(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vrmpyub.rtt.acc.128B
+ __builtin_HEXAGON_V6_vrmpyub_rtt_acc_128B(v256, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vrmpyubi.128B
+ __builtin_HEXAGON_V6_vrmpyubi_128B(v256, 0, 0);
+ // CHECK: @llvm.hexagon.V6.vrmpyubi.acc.128B
+ __builtin_HEXAGON_V6_vrmpyubi_acc_128B(v256, v256, 0, 0);
+ // CHECK: @llvm.hexagon.V6.vrmpyubv.128B
+ __builtin_HEXAGON_V6_vrmpyubv_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vrmpyubv.acc.128B
+ __builtin_HEXAGON_V6_vrmpyubv_acc_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vror.128B
+ __builtin_HEXAGON_V6_vror_128B(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vroundhb.128B
+ __builtin_HEXAGON_V6_vroundhb_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vroundhub.128B
+ __builtin_HEXAGON_V6_vroundhub_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vrounduhub.128B
+ __builtin_HEXAGON_V6_vrounduhub_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vrounduwuh.128B
+ __builtin_HEXAGON_V6_vrounduwuh_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vroundwh.128B
+ __builtin_HEXAGON_V6_vroundwh_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vroundwuh.128B
+ __builtin_HEXAGON_V6_vroundwuh_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vrsadubi.128B
+ __builtin_HEXAGON_V6_vrsadubi_128B(v256, 0, 0);
+ // CHECK: @llvm.hexagon.V6.vrsadubi.acc.128B
+ __builtin_HEXAGON_V6_vrsadubi_acc_128B(v256, v256, 0, 0);
+ // CHECK: @llvm.hexagon.V6.vsathub.128B
+ __builtin_HEXAGON_V6_vsathub_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vsatuwuh.128B
+ __builtin_HEXAGON_V6_vsatuwuh_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vsatwh.128B
+ __builtin_HEXAGON_V6_vsatwh_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vsb.128B
+ __builtin_HEXAGON_V6_vsb_128B(v128);
+ // CHECK: @llvm.hexagon.V6.vscattermh.128B
+ __builtin_HEXAGON_V6_vscattermh_128B(0, 0, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vscattermh.add.128B
+ __builtin_HEXAGON_V6_vscattermh_add_128B(0, 0, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vscattermhq.128B
+ __builtin_HEXAGON_V6_vscattermhq_128B(v128, 0, 0, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vscattermhw.128B
+ __builtin_HEXAGON_V6_vscattermhw_128B(0, 0, v256, v128);
+ // CHECK: @llvm.hexagon.V6.vscattermhw.add.128B
+ __builtin_HEXAGON_V6_vscattermhw_add_128B(0, 0, v256, v128);
+ // CHECK: @llvm.hexagon.V6.vscattermhwq.128B
+ __builtin_HEXAGON_V6_vscattermhwq_128B(v128, 0, 0, v256, v128);
+ // CHECK: @llvm.hexagon.V6.vscattermw.128B
+ __builtin_HEXAGON_V6_vscattermw_128B(0, 0, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vscattermw.add.128B
+ __builtin_HEXAGON_V6_vscattermw_add_128B(0, 0, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vscattermwq.128B
+ __builtin_HEXAGON_V6_vscattermwq_128B(v128, 0, 0, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vsh.128B
+ __builtin_HEXAGON_V6_vsh_128B(v128);
+ // CHECK: @llvm.hexagon.V6.vshufeh.128B
+ __builtin_HEXAGON_V6_vshufeh_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vshuffb.128B
+ __builtin_HEXAGON_V6_vshuffb_128B(v128);
+ // CHECK: @llvm.hexagon.V6.vshuffeb.128B
+ __builtin_HEXAGON_V6_vshuffeb_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vshuffh.128B
+ __builtin_HEXAGON_V6_vshuffh_128B(v128);
+ // CHECK: @llvm.hexagon.V6.vshuffob.128B
+ __builtin_HEXAGON_V6_vshuffob_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vshuffvdd.128B
+ __builtin_HEXAGON_V6_vshuffvdd_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vshufoeb.128B
+ __builtin_HEXAGON_V6_vshufoeb_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vshufoeh.128B
+ __builtin_HEXAGON_V6_vshufoeh_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vshufoh.128B
+ __builtin_HEXAGON_V6_vshufoh_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vsubb.128B
+ __builtin_HEXAGON_V6_vsubb_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vsubb.dv.128B
+ __builtin_HEXAGON_V6_vsubb_dv_128B(v256, v256);
+ // CHECK: @llvm.hexagon.V6.vsubbnq.128B
+ __builtin_HEXAGON_V6_vsubbnq_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vsubbq.128B
+ __builtin_HEXAGON_V6_vsubbq_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vsubbsat.128B
+ __builtin_HEXAGON_V6_vsubbsat_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vsubbsat.dv.128B
+ __builtin_HEXAGON_V6_vsubbsat_dv_128B(v256, v256);
+ // CHECK: @llvm.hexagon.V6.vsubcarry.128B
+ __builtin_HEXAGON_V6_vsubcarry_128B(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vsubh.128B
+ __builtin_HEXAGON_V6_vsubh_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vsubh.dv.128B
+ __builtin_HEXAGON_V6_vsubh_dv_128B(v256, v256);
+ // CHECK: @llvm.hexagon.V6.vsubhnq.128B
+ __builtin_HEXAGON_V6_vsubhnq_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vsubhq.128B
+ __builtin_HEXAGON_V6_vsubhq_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vsubhsat.128B
+ __builtin_HEXAGON_V6_vsubhsat_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vsubhsat.dv.128B
+ __builtin_HEXAGON_V6_vsubhsat_dv_128B(v256, v256);
+ // CHECK: @llvm.hexagon.V6.vsubhw.128B
+ __builtin_HEXAGON_V6_vsubhw_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vsububh.128B
+ __builtin_HEXAGON_V6_vsububh_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vsububsat.128B
+ __builtin_HEXAGON_V6_vsububsat_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vsububsat.dv.128B
+ __builtin_HEXAGON_V6_vsububsat_dv_128B(v256, v256);
+ // CHECK: @llvm.hexagon.V6.vsubububb.sat.128B
+ __builtin_HEXAGON_V6_vsubububb_sat_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vsubuhsat.128B
+ __builtin_HEXAGON_V6_vsubuhsat_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vsubuhsat.dv.128B
+ __builtin_HEXAGON_V6_vsubuhsat_dv_128B(v256, v256);
+ // CHECK: @llvm.hexagon.V6.vsubuhw.128B
+ __builtin_HEXAGON_V6_vsubuhw_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vsubuwsat.128B
+ __builtin_HEXAGON_V6_vsubuwsat_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vsubuwsat.dv.128B
+ __builtin_HEXAGON_V6_vsubuwsat_dv_128B(v256, v256);
+ // CHECK: @llvm.hexagon.V6.vsubw.128B
+ __builtin_HEXAGON_V6_vsubw_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vsubw.dv.128B
+ __builtin_HEXAGON_V6_vsubw_dv_128B(v256, v256);
+ // CHECK: @llvm.hexagon.V6.vsubwnq.128B
+ __builtin_HEXAGON_V6_vsubwnq_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vsubwq.128B
+ __builtin_HEXAGON_V6_vsubwq_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vsubwsat.128B
+ __builtin_HEXAGON_V6_vsubwsat_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vsubwsat.dv.128B
+ __builtin_HEXAGON_V6_vsubwsat_dv_128B(v256, v256);
+ // CHECK: @llvm.hexagon.V6.vswap.128B
+ __builtin_HEXAGON_V6_vswap_128B(v128, v128, v128);
+ // CHECK: @llvm.hexagon.V6.vtmpyb.128B
+ __builtin_HEXAGON_V6_vtmpyb_128B(v256, 0);
+ // CHECK: @llvm.hexagon.V6.vtmpyb.acc.128B
+ __builtin_HEXAGON_V6_vtmpyb_acc_128B(v256, v256, 0);
+ // CHECK: @llvm.hexagon.V6.vtmpybus.128B
+ __builtin_HEXAGON_V6_vtmpybus_128B(v256, 0);
+ // CHECK: @llvm.hexagon.V6.vtmpybus.acc.128B
+ __builtin_HEXAGON_V6_vtmpybus_acc_128B(v256, v256, 0);
+ // CHECK: @llvm.hexagon.V6.vtmpyhb.128B
+ __builtin_HEXAGON_V6_vtmpyhb_128B(v256, 0);
+ // CHECK: @llvm.hexagon.V6.vtmpyhb.acc.128B
+ __builtin_HEXAGON_V6_vtmpyhb_acc_128B(v256, v256, 0);
+ // CHECK: @llvm.hexagon.V6.vunpackb.128B
+ __builtin_HEXAGON_V6_vunpackb_128B(v128);
+ // CHECK: @llvm.hexagon.V6.vunpackh.128B
+ __builtin_HEXAGON_V6_vunpackh_128B(v128);
+ // CHECK: @llvm.hexagon.V6.vunpackob.128B
+ __builtin_HEXAGON_V6_vunpackob_128B(v256, v128);
+ // CHECK: @llvm.hexagon.V6.vunpackoh.128B
+ __builtin_HEXAGON_V6_vunpackoh_128B(v256, v128);
+ // CHECK: @llvm.hexagon.V6.vunpackub.128B
+ __builtin_HEXAGON_V6_vunpackub_128B(v128);
+ // CHECK: @llvm.hexagon.V6.vunpackuh.128B
+ __builtin_HEXAGON_V6_vunpackuh_128B(v128);
+ // CHECK: @llvm.hexagon.V6.vxor.128B
+ __builtin_HEXAGON_V6_vxor_128B(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vzb.128B
+ __builtin_HEXAGON_V6_vzb_128B(v128);
+ // CHECK: @llvm.hexagon.V6.vzh.128B
+ __builtin_HEXAGON_V6_vzh_128B(v128);
+}
diff --git a/test/CodeGen/builtins-hvx64.c b/test/CodeGen/builtins-hvx64.c
new file mode 100644
index 000000000000..5a53296e7276
--- /dev/null
+++ b/test/CodeGen/builtins-hvx64.c
@@ -0,0 +1,802 @@
+// REQUIRES: hexagon-registered-target
+// RUN: %clang_cc1 -triple hexagon-unknown-elf -target-cpu hexagonv65 -target-feature +hvxv65 -target-feature +hvx-length64b -emit-llvm %s -o - | FileCheck %s
+
+void test() {
+ int v64 __attribute__((__vector_size__(64)));
+ int v128 __attribute__((__vector_size__(128)));
+
+ // CHECK: @llvm.hexagon.V6.extractw
+ __builtin_HEXAGON_V6_extractw(v64, 0);
+ // CHECK: @llvm.hexagon.V6.hi
+ __builtin_HEXAGON_V6_hi(v128);
+ // CHECK: @llvm.hexagon.V6.lo
+ __builtin_HEXAGON_V6_lo(v128);
+ // CHECK: @llvm.hexagon.V6.lvsplatb
+ __builtin_HEXAGON_V6_lvsplatb(0);
+ // CHECK: @llvm.hexagon.V6.lvsplath
+ __builtin_HEXAGON_V6_lvsplath(0);
+ // CHECK: @llvm.hexagon.V6.lvsplatw
+ __builtin_HEXAGON_V6_lvsplatw(0);
+ // CHECK: @llvm.hexagon.V6.pred.and
+ __builtin_HEXAGON_V6_pred_and(v64, v64);
+ // CHECK: @llvm.hexagon.V6.pred.and.n
+ __builtin_HEXAGON_V6_pred_and_n(v64, v64);
+ // CHECK: @llvm.hexagon.V6.pred.not
+ __builtin_HEXAGON_V6_pred_not(v64);
+ // CHECK: @llvm.hexagon.V6.pred.or
+ __builtin_HEXAGON_V6_pred_or(v64, v64);
+ // CHECK: @llvm.hexagon.V6.pred.or.n
+ __builtin_HEXAGON_V6_pred_or_n(v64, v64);
+ // CHECK: @llvm.hexagon.V6.pred.scalar2
+ __builtin_HEXAGON_V6_pred_scalar2(0);
+ // CHECK: @llvm.hexagon.V6.pred.scalar2v2
+ __builtin_HEXAGON_V6_pred_scalar2v2(0);
+ // CHECK: @llvm.hexagon.V6.pred.xor
+ __builtin_HEXAGON_V6_pred_xor(v64, v64);
+ // CHECK: @llvm.hexagon.V6.shuffeqh
+ __builtin_HEXAGON_V6_shuffeqh(v64, v64);
+ // CHECK: @llvm.hexagon.V6.shuffeqw
+ __builtin_HEXAGON_V6_shuffeqw(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vS32b.nqpred.ai
+ __builtin_HEXAGON_V6_vS32b_nqpred_ai(v64, 0, v64);
+ // CHECK: @llvm.hexagon.V6.vS32b.nt.nqpred.ai
+ __builtin_HEXAGON_V6_vS32b_nt_nqpred_ai(v64, 0, v64);
+ // CHECK: @llvm.hexagon.V6.vS32b.nt.qpred.ai
+ __builtin_HEXAGON_V6_vS32b_nt_qpred_ai(v64, 0, v64);
+ // CHECK: @llvm.hexagon.V6.vS32b.qpred.ai
+ __builtin_HEXAGON_V6_vS32b_qpred_ai(v64, 0, v64);
+ // CHECK: @llvm.hexagon.V6.vabsb
+ __builtin_HEXAGON_V6_vabsb(v64);
+ // CHECK: @llvm.hexagon.V6.vabsb.sat
+ __builtin_HEXAGON_V6_vabsb_sat(v64);
+ // CHECK: @llvm.hexagon.V6.vabsdiffh
+ __builtin_HEXAGON_V6_vabsdiffh(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vabsdiffub
+ __builtin_HEXAGON_V6_vabsdiffub(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vabsdiffuh
+ __builtin_HEXAGON_V6_vabsdiffuh(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vabsdiffw
+ __builtin_HEXAGON_V6_vabsdiffw(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vabsh
+ __builtin_HEXAGON_V6_vabsh(v64);
+ // CHECK: @llvm.hexagon.V6.vabsh.sat
+ __builtin_HEXAGON_V6_vabsh_sat(v64);
+ // CHECK: @llvm.hexagon.V6.vabsw
+ __builtin_HEXAGON_V6_vabsw(v64);
+ // CHECK: @llvm.hexagon.V6.vabsw.sat
+ __builtin_HEXAGON_V6_vabsw_sat(v64);
+ // CHECK: @llvm.hexagon.V6.vaddb
+ __builtin_HEXAGON_V6_vaddb(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vaddb.dv
+ __builtin_HEXAGON_V6_vaddb_dv(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vaddbnq
+ __builtin_HEXAGON_V6_vaddbnq(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vaddbq
+ __builtin_HEXAGON_V6_vaddbq(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vaddbsat
+ __builtin_HEXAGON_V6_vaddbsat(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vaddbsat.dv
+ __builtin_HEXAGON_V6_vaddbsat_dv(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vaddcarry
+ __builtin_HEXAGON_V6_vaddcarry(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vaddclbh
+ __builtin_HEXAGON_V6_vaddclbh(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vaddclbw
+ __builtin_HEXAGON_V6_vaddclbw(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vaddh
+ __builtin_HEXAGON_V6_vaddh(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vaddh.dv
+ __builtin_HEXAGON_V6_vaddh_dv(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vaddhnq
+ __builtin_HEXAGON_V6_vaddhnq(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vaddhq
+ __builtin_HEXAGON_V6_vaddhq(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vaddhsat
+ __builtin_HEXAGON_V6_vaddhsat(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vaddhsat.dv
+ __builtin_HEXAGON_V6_vaddhsat_dv(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vaddhw
+ __builtin_HEXAGON_V6_vaddhw(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vaddhw.acc
+ __builtin_HEXAGON_V6_vaddhw_acc(v128, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vaddubh
+ __builtin_HEXAGON_V6_vaddubh(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vaddubh.acc
+ __builtin_HEXAGON_V6_vaddubh_acc(v128, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vaddubsat
+ __builtin_HEXAGON_V6_vaddubsat(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vaddubsat.dv
+ __builtin_HEXAGON_V6_vaddubsat_dv(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vaddububb.sat
+ __builtin_HEXAGON_V6_vaddububb_sat(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vadduhsat
+ __builtin_HEXAGON_V6_vadduhsat(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vadduhsat.dv
+ __builtin_HEXAGON_V6_vadduhsat_dv(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vadduhw
+ __builtin_HEXAGON_V6_vadduhw(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vadduhw.acc
+ __builtin_HEXAGON_V6_vadduhw_acc(v128, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vadduwsat
+ __builtin_HEXAGON_V6_vadduwsat(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vadduwsat.dv
+ __builtin_HEXAGON_V6_vadduwsat_dv(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vaddw
+ __builtin_HEXAGON_V6_vaddw(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vaddw.dv
+ __builtin_HEXAGON_V6_vaddw_dv(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vaddwnq
+ __builtin_HEXAGON_V6_vaddwnq(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vaddwq
+ __builtin_HEXAGON_V6_vaddwq(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vaddwsat
+ __builtin_HEXAGON_V6_vaddwsat(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vaddwsat.dv
+ __builtin_HEXAGON_V6_vaddwsat_dv(v128, v128);
+ // CHECK: @llvm.hexagon.V6.valignb
+ __builtin_HEXAGON_V6_valignb(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.valignbi
+ __builtin_HEXAGON_V6_valignbi(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vand
+ __builtin_HEXAGON_V6_vand(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vandnqrt
+ __builtin_HEXAGON_V6_vandnqrt(v64, 0);
+ // CHECK: @llvm.hexagon.V6.vandnqrt.acc
+ __builtin_HEXAGON_V6_vandnqrt_acc(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vandqrt
+ __builtin_HEXAGON_V6_vandqrt(v64, 0);
+ // CHECK: @llvm.hexagon.V6.vandqrt.acc
+ __builtin_HEXAGON_V6_vandqrt_acc(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vandvnqv
+ __builtin_HEXAGON_V6_vandvnqv(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vandvqv
+ __builtin_HEXAGON_V6_vandvqv(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vandvrt
+ __builtin_HEXAGON_V6_vandvrt(v64, 0);
+ // CHECK: @llvm.hexagon.V6.vandvrt.acc
+ __builtin_HEXAGON_V6_vandvrt_acc(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vaslh
+ __builtin_HEXAGON_V6_vaslh(v64, 0);
+ // CHECK: @llvm.hexagon.V6.vaslh.acc
+ __builtin_HEXAGON_V6_vaslh_acc(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vaslhv
+ __builtin_HEXAGON_V6_vaslhv(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vaslw
+ __builtin_HEXAGON_V6_vaslw(v64, 0);
+ // CHECK: @llvm.hexagon.V6.vaslw.acc
+ __builtin_HEXAGON_V6_vaslw_acc(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vaslwv
+ __builtin_HEXAGON_V6_vaslwv(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vasrh
+ __builtin_HEXAGON_V6_vasrh(v64, 0);
+ // CHECK: @llvm.hexagon.V6.vasrh.acc
+ __builtin_HEXAGON_V6_vasrh_acc(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vasrhbrndsat
+ __builtin_HEXAGON_V6_vasrhbrndsat(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vasrhbsat
+ __builtin_HEXAGON_V6_vasrhbsat(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vasrhubrndsat
+ __builtin_HEXAGON_V6_vasrhubrndsat(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vasrhubsat
+ __builtin_HEXAGON_V6_vasrhubsat(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vasrhv
+ __builtin_HEXAGON_V6_vasrhv(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vasruhubrndsat
+ __builtin_HEXAGON_V6_vasruhubrndsat(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vasruhubsat
+ __builtin_HEXAGON_V6_vasruhubsat(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vasruwuhrndsat
+ __builtin_HEXAGON_V6_vasruwuhrndsat(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vasruwuhsat
+ __builtin_HEXAGON_V6_vasruwuhsat(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vasrw
+ __builtin_HEXAGON_V6_vasrw(v64, 0);
+ // CHECK: @llvm.hexagon.V6.vasrw.acc
+ __builtin_HEXAGON_V6_vasrw_acc(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vasrwh
+ __builtin_HEXAGON_V6_vasrwh(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vasrwhrndsat
+ __builtin_HEXAGON_V6_vasrwhrndsat(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vasrwhsat
+ __builtin_HEXAGON_V6_vasrwhsat(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vasrwuhrndsat
+ __builtin_HEXAGON_V6_vasrwuhrndsat(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vasrwuhsat
+ __builtin_HEXAGON_V6_vasrwuhsat(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vasrwv
+ __builtin_HEXAGON_V6_vasrwv(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vassign
+ __builtin_HEXAGON_V6_vassign(v64);
+ // CHECK: @llvm.hexagon.V6.vassignp
+ __builtin_HEXAGON_V6_vassignp(v128);
+ // CHECK: @llvm.hexagon.V6.vavgb
+ __builtin_HEXAGON_V6_vavgb(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vavgbrnd
+ __builtin_HEXAGON_V6_vavgbrnd(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vavgh
+ __builtin_HEXAGON_V6_vavgh(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vavghrnd
+ __builtin_HEXAGON_V6_vavghrnd(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vavgub
+ __builtin_HEXAGON_V6_vavgub(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vavgubrnd
+ __builtin_HEXAGON_V6_vavgubrnd(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vavguh
+ __builtin_HEXAGON_V6_vavguh(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vavguhrnd
+ __builtin_HEXAGON_V6_vavguhrnd(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vavguw
+ __builtin_HEXAGON_V6_vavguw(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vavguwrnd
+ __builtin_HEXAGON_V6_vavguwrnd(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vavgw
+ __builtin_HEXAGON_V6_vavgw(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vavgwrnd
+ __builtin_HEXAGON_V6_vavgwrnd(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vcl0h
+ __builtin_HEXAGON_V6_vcl0h(v64);
+ // CHECK: @llvm.hexagon.V6.vcl0w
+ __builtin_HEXAGON_V6_vcl0w(v64);
+ // CHECK: @llvm.hexagon.V6.vcombine
+ __builtin_HEXAGON_V6_vcombine(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vd0
+ __builtin_HEXAGON_V6_vd0();
+ // CHECK: @llvm.hexagon.V6.vdd0
+ __builtin_HEXAGON_V6_vdd0();
+ // CHECK: @llvm.hexagon.V6.vdealb
+ __builtin_HEXAGON_V6_vdealb(v64);
+ // CHECK: @llvm.hexagon.V6.vdealb4w
+ __builtin_HEXAGON_V6_vdealb4w(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vdealh
+ __builtin_HEXAGON_V6_vdealh(v64);
+ // CHECK: @llvm.hexagon.V6.vdealvdd
+ __builtin_HEXAGON_V6_vdealvdd(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vdelta
+ __builtin_HEXAGON_V6_vdelta(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vdmpybus
+ __builtin_HEXAGON_V6_vdmpybus(v64, 0);
+ // CHECK: @llvm.hexagon.V6.vdmpybus.acc
+ __builtin_HEXAGON_V6_vdmpybus_acc(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vdmpybus.dv
+ __builtin_HEXAGON_V6_vdmpybus_dv(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vdmpybus.dv.acc
+ __builtin_HEXAGON_V6_vdmpybus_dv_acc(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vdmpyhb
+ __builtin_HEXAGON_V6_vdmpyhb(v64, 0);
+ // CHECK: @llvm.hexagon.V6.vdmpyhb.acc
+ __builtin_HEXAGON_V6_vdmpyhb_acc(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vdmpyhb.dv
+ __builtin_HEXAGON_V6_vdmpyhb_dv(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vdmpyhb.dv.acc
+ __builtin_HEXAGON_V6_vdmpyhb_dv_acc(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vdmpyhisat
+ __builtin_HEXAGON_V6_vdmpyhisat(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vdmpyhisat.acc
+ __builtin_HEXAGON_V6_vdmpyhisat_acc(v64, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vdmpyhsat
+ __builtin_HEXAGON_V6_vdmpyhsat(v64, 0);
+ // CHECK: @llvm.hexagon.V6.vdmpyhsat.acc
+ __builtin_HEXAGON_V6_vdmpyhsat_acc(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vdmpyhsuisat
+ __builtin_HEXAGON_V6_vdmpyhsuisat(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vdmpyhsuisat.acc
+ __builtin_HEXAGON_V6_vdmpyhsuisat_acc(v64, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vdmpyhsusat
+ __builtin_HEXAGON_V6_vdmpyhsusat(v64, 0);
+ // CHECK: @llvm.hexagon.V6.vdmpyhsusat.acc
+ __builtin_HEXAGON_V6_vdmpyhsusat_acc(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vdmpyhvsat
+ __builtin_HEXAGON_V6_vdmpyhvsat(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vdmpyhvsat.acc
+ __builtin_HEXAGON_V6_vdmpyhvsat_acc(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vdsaduh
+ __builtin_HEXAGON_V6_vdsaduh(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vdsaduh.acc
+ __builtin_HEXAGON_V6_vdsaduh_acc(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.veqb
+ __builtin_HEXAGON_V6_veqb(v64, v64);
+ // CHECK: @llvm.hexagon.V6.veqb.and
+ __builtin_HEXAGON_V6_veqb_and(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.veqb.or
+ __builtin_HEXAGON_V6_veqb_or(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.veqb.xor
+ __builtin_HEXAGON_V6_veqb_xor(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.veqh
+ __builtin_HEXAGON_V6_veqh(v64, v64);
+ // CHECK: @llvm.hexagon.V6.veqh.and
+ __builtin_HEXAGON_V6_veqh_and(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.veqh.or
+ __builtin_HEXAGON_V6_veqh_or(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.veqh.xor
+ __builtin_HEXAGON_V6_veqh_xor(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.veqw
+ __builtin_HEXAGON_V6_veqw(v64, v64);
+ // CHECK: @llvm.hexagon.V6.veqw.and
+ __builtin_HEXAGON_V6_veqw_and(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.veqw.or
+ __builtin_HEXAGON_V6_veqw_or(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.veqw.xor
+ __builtin_HEXAGON_V6_veqw_xor(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vgathermh
+ __builtin_HEXAGON_V6_vgathermh(0, 0, 0, v64);
+ // CHECK: @llvm.hexagon.V6.vgathermhq
+ __builtin_HEXAGON_V6_vgathermhq(0, v64, 0, 0, v64);
+ // CHECK: @llvm.hexagon.V6.vgathermhw
+ __builtin_HEXAGON_V6_vgathermhw(0, 0, 0, v128);
+ // CHECK: @llvm.hexagon.V6.vgathermhwq
+ __builtin_HEXAGON_V6_vgathermhwq(0, v64, 0, 0, v128);
+ // CHECK: @llvm.hexagon.V6.vgathermw
+ __builtin_HEXAGON_V6_vgathermw(0, 0, 0, v64);
+ // CHECK: @llvm.hexagon.V6.vgathermwq
+ __builtin_HEXAGON_V6_vgathermwq(0, v64, 0, 0, v64);
+ // CHECK: @llvm.hexagon.V6.vgtb
+ __builtin_HEXAGON_V6_vgtb(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vgtb.and
+ __builtin_HEXAGON_V6_vgtb_and(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vgtb.or
+ __builtin_HEXAGON_V6_vgtb_or(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vgtb.xor
+ __builtin_HEXAGON_V6_vgtb_xor(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vgth
+ __builtin_HEXAGON_V6_vgth(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vgth.and
+ __builtin_HEXAGON_V6_vgth_and(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vgth.or
+ __builtin_HEXAGON_V6_vgth_or(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vgth.xor
+ __builtin_HEXAGON_V6_vgth_xor(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vgtub
+ __builtin_HEXAGON_V6_vgtub(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vgtub.and
+ __builtin_HEXAGON_V6_vgtub_and(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vgtub.or
+ __builtin_HEXAGON_V6_vgtub_or(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vgtub.xor
+ __builtin_HEXAGON_V6_vgtub_xor(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vgtuh
+ __builtin_HEXAGON_V6_vgtuh(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vgtuh.and
+ __builtin_HEXAGON_V6_vgtuh_and(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vgtuh.or
+ __builtin_HEXAGON_V6_vgtuh_or(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vgtuh.xor
+ __builtin_HEXAGON_V6_vgtuh_xor(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vgtuw
+ __builtin_HEXAGON_V6_vgtuw(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vgtuw.and
+ __builtin_HEXAGON_V6_vgtuw_and(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vgtuw.or
+ __builtin_HEXAGON_V6_vgtuw_or(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vgtuw.xor
+ __builtin_HEXAGON_V6_vgtuw_xor(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vgtw
+ __builtin_HEXAGON_V6_vgtw(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vgtw.and
+ __builtin_HEXAGON_V6_vgtw_and(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vgtw.or
+ __builtin_HEXAGON_V6_vgtw_or(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vgtw.xor
+ __builtin_HEXAGON_V6_vgtw_xor(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vinsertwr
+ __builtin_HEXAGON_V6_vinsertwr(v64, 0);
+ // CHECK: @llvm.hexagon.V6.vlalignb
+ __builtin_HEXAGON_V6_vlalignb(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vlalignbi
+ __builtin_HEXAGON_V6_vlalignbi(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vlsrb
+ __builtin_HEXAGON_V6_vlsrb(v64, 0);
+ // CHECK: @llvm.hexagon.V6.vlsrh
+ __builtin_HEXAGON_V6_vlsrh(v64, 0);
+ // CHECK: @llvm.hexagon.V6.vlsrhv
+ __builtin_HEXAGON_V6_vlsrhv(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vlsrw
+ __builtin_HEXAGON_V6_vlsrw(v64, 0);
+ // CHECK: @llvm.hexagon.V6.vlsrwv
+ __builtin_HEXAGON_V6_vlsrwv(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vlut4
+ __builtin_HEXAGON_V6_vlut4(v64, 0);
+ // CHECK: @llvm.hexagon.V6.vlutvvb
+ __builtin_HEXAGON_V6_vlutvvb(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vlutvvb.nm
+ __builtin_HEXAGON_V6_vlutvvb_nm(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vlutvvb.oracc
+ __builtin_HEXAGON_V6_vlutvvb_oracc(v64, v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vlutvvb.oracci
+ __builtin_HEXAGON_V6_vlutvvb_oracci(v64, v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vlutvvbi
+ __builtin_HEXAGON_V6_vlutvvbi(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vlutvwh
+ __builtin_HEXAGON_V6_vlutvwh(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vlutvwh.nm
+ __builtin_HEXAGON_V6_vlutvwh_nm(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vlutvwh.oracc
+ __builtin_HEXAGON_V6_vlutvwh_oracc(v128, v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vlutvwh.oracci
+ __builtin_HEXAGON_V6_vlutvwh_oracci(v128, v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vlutvwhi
+ __builtin_HEXAGON_V6_vlutvwhi(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vmaskedstorenq
+ __builtin_HEXAGON_V6_vmaskedstorenq(v64, 0, v64);
+ // CHECK: @llvm.hexagon.V6.vmaskedstorentnq
+ __builtin_HEXAGON_V6_vmaskedstorentnq(v64, 0, v64);
+ // CHECK: @llvm.hexagon.V6.vmaskedstorentq
+ __builtin_HEXAGON_V6_vmaskedstorentq(v64, 0, v64);
+ // CHECK: @llvm.hexagon.V6.vmaskedstoreq
+ __builtin_HEXAGON_V6_vmaskedstoreq(v64, 0, v64);
+ // CHECK: @llvm.hexagon.V6.vmaxb
+ __builtin_HEXAGON_V6_vmaxb(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vmaxh
+ __builtin_HEXAGON_V6_vmaxh(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vmaxub
+ __builtin_HEXAGON_V6_vmaxub(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vmaxuh
+ __builtin_HEXAGON_V6_vmaxuh(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vmaxw
+ __builtin_HEXAGON_V6_vmaxw(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vminb
+ __builtin_HEXAGON_V6_vminb(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vminh
+ __builtin_HEXAGON_V6_vminh(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vminub
+ __builtin_HEXAGON_V6_vminub(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vminuh
+ __builtin_HEXAGON_V6_vminuh(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vminw
+ __builtin_HEXAGON_V6_vminw(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vmpabus
+ __builtin_HEXAGON_V6_vmpabus(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vmpabus.acc
+ __builtin_HEXAGON_V6_vmpabus_acc(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vmpabusv
+ __builtin_HEXAGON_V6_vmpabusv(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmpabuu
+ __builtin_HEXAGON_V6_vmpabuu(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vmpabuu.acc
+ __builtin_HEXAGON_V6_vmpabuu_acc(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vmpabuuv
+ __builtin_HEXAGON_V6_vmpabuuv(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vmpahb
+ __builtin_HEXAGON_V6_vmpahb(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vmpahb.acc
+ __builtin_HEXAGON_V6_vmpahb_acc(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vmpahhsat
+ __builtin_HEXAGON_V6_vmpahhsat(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vmpauhb
+ __builtin_HEXAGON_V6_vmpauhb(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vmpauhb.acc
+ __builtin_HEXAGON_V6_vmpauhb_acc(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vmpauhuhsat
+ __builtin_HEXAGON_V6_vmpauhuhsat(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vmpsuhuhsat
+ __builtin_HEXAGON_V6_vmpsuhuhsat(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vmpybus
+ __builtin_HEXAGON_V6_vmpybus(v64, 0);
+ // CHECK: @llvm.hexagon.V6.vmpybus.acc
+ __builtin_HEXAGON_V6_vmpybus_acc(v128, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vmpybusv
+ __builtin_HEXAGON_V6_vmpybusv(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vmpybusv.acc
+ __builtin_HEXAGON_V6_vmpybusv_acc(v128, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vmpybv
+ __builtin_HEXAGON_V6_vmpybv(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vmpybv.acc
+ __builtin_HEXAGON_V6_vmpybv_acc(v128, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vmpyewuh
+ __builtin_HEXAGON_V6_vmpyewuh(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vmpyewuh.64
+ __builtin_HEXAGON_V6_vmpyewuh_64(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vmpyh
+ __builtin_HEXAGON_V6_vmpyh(v64, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyh.acc
+ __builtin_HEXAGON_V6_vmpyh_acc(v128, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyhsat.acc
+ __builtin_HEXAGON_V6_vmpyhsat_acc(v128, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyhsrs
+ __builtin_HEXAGON_V6_vmpyhsrs(v64, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyhss
+ __builtin_HEXAGON_V6_vmpyhss(v64, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyhus
+ __builtin_HEXAGON_V6_vmpyhus(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vmpyhus.acc
+ __builtin_HEXAGON_V6_vmpyhus_acc(v128, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vmpyhv
+ __builtin_HEXAGON_V6_vmpyhv(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vmpyhv.acc
+ __builtin_HEXAGON_V6_vmpyhv_acc(v128, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vmpyhvsrs
+ __builtin_HEXAGON_V6_vmpyhvsrs(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vmpyieoh
+ __builtin_HEXAGON_V6_vmpyieoh(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vmpyiewh.acc
+ __builtin_HEXAGON_V6_vmpyiewh_acc(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vmpyiewuh
+ __builtin_HEXAGON_V6_vmpyiewuh(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vmpyiewuh.acc
+ __builtin_HEXAGON_V6_vmpyiewuh_acc(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vmpyih
+ __builtin_HEXAGON_V6_vmpyih(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vmpyih.acc
+ __builtin_HEXAGON_V6_vmpyih_acc(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vmpyihb
+ __builtin_HEXAGON_V6_vmpyihb(v64, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyihb.acc
+ __builtin_HEXAGON_V6_vmpyihb_acc(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyiowh
+ __builtin_HEXAGON_V6_vmpyiowh(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vmpyiwb
+ __builtin_HEXAGON_V6_vmpyiwb(v64, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyiwb.acc
+ __builtin_HEXAGON_V6_vmpyiwb_acc(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyiwh
+ __builtin_HEXAGON_V6_vmpyiwh(v64, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyiwh.acc
+ __builtin_HEXAGON_V6_vmpyiwh_acc(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyiwub
+ __builtin_HEXAGON_V6_vmpyiwub(v64, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyiwub.acc
+ __builtin_HEXAGON_V6_vmpyiwub_acc(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyowh
+ __builtin_HEXAGON_V6_vmpyowh(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vmpyowh.64.acc
+ __builtin_HEXAGON_V6_vmpyowh_64_acc(v128, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vmpyowh.rnd
+ __builtin_HEXAGON_V6_vmpyowh_rnd(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vmpyowh.rnd.sacc
+ __builtin_HEXAGON_V6_vmpyowh_rnd_sacc(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vmpyowh.sacc
+ __builtin_HEXAGON_V6_vmpyowh_sacc(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vmpyub
+ __builtin_HEXAGON_V6_vmpyub(v64, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyub.acc
+ __builtin_HEXAGON_V6_vmpyub_acc(v128, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyubv
+ __builtin_HEXAGON_V6_vmpyubv(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vmpyubv.acc
+ __builtin_HEXAGON_V6_vmpyubv_acc(v128, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vmpyuh
+ __builtin_HEXAGON_V6_vmpyuh(v64, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyuh.acc
+ __builtin_HEXAGON_V6_vmpyuh_acc(v128, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyuhe
+ __builtin_HEXAGON_V6_vmpyuhe(v64, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyuhe.acc
+ __builtin_HEXAGON_V6_vmpyuhe_acc(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vmpyuhv
+ __builtin_HEXAGON_V6_vmpyuhv(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vmpyuhv.acc
+ __builtin_HEXAGON_V6_vmpyuhv_acc(v128, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vmux
+ __builtin_HEXAGON_V6_vmux(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vnavgb
+ __builtin_HEXAGON_V6_vnavgb(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vnavgh
+ __builtin_HEXAGON_V6_vnavgh(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vnavgub
+ __builtin_HEXAGON_V6_vnavgub(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vnavgw
+ __builtin_HEXAGON_V6_vnavgw(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vnormamth
+ __builtin_HEXAGON_V6_vnormamth(v64);
+ // CHECK: @llvm.hexagon.V6.vnormamtw
+ __builtin_HEXAGON_V6_vnormamtw(v64);
+ // CHECK: @llvm.hexagon.V6.vnot
+ __builtin_HEXAGON_V6_vnot(v64);
+ // CHECK: @llvm.hexagon.V6.vor
+ __builtin_HEXAGON_V6_vor(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vpackeb
+ __builtin_HEXAGON_V6_vpackeb(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vpackeh
+ __builtin_HEXAGON_V6_vpackeh(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vpackhb.sat
+ __builtin_HEXAGON_V6_vpackhb_sat(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vpackhub.sat
+ __builtin_HEXAGON_V6_vpackhub_sat(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vpackob
+ __builtin_HEXAGON_V6_vpackob(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vpackoh
+ __builtin_HEXAGON_V6_vpackoh(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vpackwh.sat
+ __builtin_HEXAGON_V6_vpackwh_sat(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vpackwuh.sat
+ __builtin_HEXAGON_V6_vpackwuh_sat(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vpopcounth
+ __builtin_HEXAGON_V6_vpopcounth(v64);
+ // CHECK: @llvm.hexagon.V6.vprefixqb
+ __builtin_HEXAGON_V6_vprefixqb(v64);
+ // CHECK: @llvm.hexagon.V6.vprefixqh
+ __builtin_HEXAGON_V6_vprefixqh(v64);
+ // CHECK: @llvm.hexagon.V6.vprefixqw
+ __builtin_HEXAGON_V6_vprefixqw(v64);
+ // CHECK: @llvm.hexagon.V6.vrdelta
+ __builtin_HEXAGON_V6_vrdelta(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vrmpybub.rtt
+ __builtin_HEXAGON_V6_vrmpybub_rtt(v64, 0);
+ // CHECK: @llvm.hexagon.V6.vrmpybub.rtt.acc
+ __builtin_HEXAGON_V6_vrmpybub_rtt_acc(v128, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vrmpybus
+ __builtin_HEXAGON_V6_vrmpybus(v64, 0);
+ // CHECK: @llvm.hexagon.V6.vrmpybus.acc
+ __builtin_HEXAGON_V6_vrmpybus_acc(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vrmpybusi
+ __builtin_HEXAGON_V6_vrmpybusi(v128, 0, 0);
+ // CHECK: @llvm.hexagon.V6.vrmpybusi.acc
+ __builtin_HEXAGON_V6_vrmpybusi_acc(v128, v128, 0, 0);
+ // CHECK: @llvm.hexagon.V6.vrmpybusv
+ __builtin_HEXAGON_V6_vrmpybusv(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vrmpybusv.acc
+ __builtin_HEXAGON_V6_vrmpybusv_acc(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vrmpybv
+ __builtin_HEXAGON_V6_vrmpybv(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vrmpybv.acc
+ __builtin_HEXAGON_V6_vrmpybv_acc(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vrmpyub
+ __builtin_HEXAGON_V6_vrmpyub(v64, 0);
+ // CHECK: @llvm.hexagon.V6.vrmpyub.acc
+ __builtin_HEXAGON_V6_vrmpyub_acc(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vrmpyub.rtt
+ __builtin_HEXAGON_V6_vrmpyub_rtt(v64, 0);
+ // CHECK: @llvm.hexagon.V6.vrmpyub.rtt.acc
+ __builtin_HEXAGON_V6_vrmpyub_rtt_acc(v128, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vrmpyubi
+ __builtin_HEXAGON_V6_vrmpyubi(v128, 0, 0);
+ // CHECK: @llvm.hexagon.V6.vrmpyubi.acc
+ __builtin_HEXAGON_V6_vrmpyubi_acc(v128, v128, 0, 0);
+ // CHECK: @llvm.hexagon.V6.vrmpyubv
+ __builtin_HEXAGON_V6_vrmpyubv(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vrmpyubv.acc
+ __builtin_HEXAGON_V6_vrmpyubv_acc(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vror
+ __builtin_HEXAGON_V6_vror(v64, 0);
+ // CHECK: @llvm.hexagon.V6.vroundhb
+ __builtin_HEXAGON_V6_vroundhb(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vroundhub
+ __builtin_HEXAGON_V6_vroundhub(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vrounduhub
+ __builtin_HEXAGON_V6_vrounduhub(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vrounduwuh
+ __builtin_HEXAGON_V6_vrounduwuh(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vroundwh
+ __builtin_HEXAGON_V6_vroundwh(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vroundwuh
+ __builtin_HEXAGON_V6_vroundwuh(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vrsadubi
+ __builtin_HEXAGON_V6_vrsadubi(v128, 0, 0);
+ // CHECK: @llvm.hexagon.V6.vrsadubi.acc
+ __builtin_HEXAGON_V6_vrsadubi_acc(v128, v128, 0, 0);
+ // CHECK: @llvm.hexagon.V6.vsathub
+ __builtin_HEXAGON_V6_vsathub(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vsatuwuh
+ __builtin_HEXAGON_V6_vsatuwuh(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vsatwh
+ __builtin_HEXAGON_V6_vsatwh(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vsb
+ __builtin_HEXAGON_V6_vsb(v64);
+ // CHECK: @llvm.hexagon.V6.vscattermh
+ __builtin_HEXAGON_V6_vscattermh(0, 0, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vscattermh.add
+ __builtin_HEXAGON_V6_vscattermh_add(0, 0, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vscattermhq
+ __builtin_HEXAGON_V6_vscattermhq(v64, 0, 0, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vscattermhw
+ __builtin_HEXAGON_V6_vscattermhw(0, 0, v128, v64);
+ // CHECK: @llvm.hexagon.V6.vscattermhw.add
+ __builtin_HEXAGON_V6_vscattermhw_add(0, 0, v128, v64);
+ // CHECK: @llvm.hexagon.V6.vscattermhwq
+ __builtin_HEXAGON_V6_vscattermhwq(v64, 0, 0, v128, v64);
+ // CHECK: @llvm.hexagon.V6.vscattermw
+ __builtin_HEXAGON_V6_vscattermw(0, 0, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vscattermw.add
+ __builtin_HEXAGON_V6_vscattermw_add(0, 0, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vscattermwq
+ __builtin_HEXAGON_V6_vscattermwq(v64, 0, 0, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vsh
+ __builtin_HEXAGON_V6_vsh(v64);
+ // CHECK: @llvm.hexagon.V6.vshufeh
+ __builtin_HEXAGON_V6_vshufeh(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vshuffb
+ __builtin_HEXAGON_V6_vshuffb(v64);
+ // CHECK: @llvm.hexagon.V6.vshuffeb
+ __builtin_HEXAGON_V6_vshuffeb(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vshuffh
+ __builtin_HEXAGON_V6_vshuffh(v64);
+ // CHECK: @llvm.hexagon.V6.vshuffob
+ __builtin_HEXAGON_V6_vshuffob(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vshuffvdd
+ __builtin_HEXAGON_V6_vshuffvdd(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vshufoeb
+ __builtin_HEXAGON_V6_vshufoeb(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vshufoeh
+ __builtin_HEXAGON_V6_vshufoeh(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vshufoh
+ __builtin_HEXAGON_V6_vshufoh(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vsubb
+ __builtin_HEXAGON_V6_vsubb(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vsubb.dv
+ __builtin_HEXAGON_V6_vsubb_dv(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vsubbnq
+ __builtin_HEXAGON_V6_vsubbnq(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vsubbq
+ __builtin_HEXAGON_V6_vsubbq(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vsubbsat
+ __builtin_HEXAGON_V6_vsubbsat(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vsubbsat.dv
+ __builtin_HEXAGON_V6_vsubbsat_dv(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vsubcarry
+ __builtin_HEXAGON_V6_vsubcarry(v64, v64, 0);
+ // CHECK: @llvm.hexagon.V6.vsubh
+ __builtin_HEXAGON_V6_vsubh(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vsubh.dv
+ __builtin_HEXAGON_V6_vsubh_dv(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vsubhnq
+ __builtin_HEXAGON_V6_vsubhnq(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vsubhq
+ __builtin_HEXAGON_V6_vsubhq(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vsubhsat
+ __builtin_HEXAGON_V6_vsubhsat(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vsubhsat.dv
+ __builtin_HEXAGON_V6_vsubhsat_dv(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vsubhw
+ __builtin_HEXAGON_V6_vsubhw(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vsububh
+ __builtin_HEXAGON_V6_vsububh(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vsububsat
+ __builtin_HEXAGON_V6_vsububsat(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vsububsat.dv
+ __builtin_HEXAGON_V6_vsububsat_dv(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vsubububb.sat
+ __builtin_HEXAGON_V6_vsubububb_sat(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vsubuhsat
+ __builtin_HEXAGON_V6_vsubuhsat(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vsubuhsat.dv
+ __builtin_HEXAGON_V6_vsubuhsat_dv(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vsubuhw
+ __builtin_HEXAGON_V6_vsubuhw(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vsubuwsat
+ __builtin_HEXAGON_V6_vsubuwsat(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vsubuwsat.dv
+ __builtin_HEXAGON_V6_vsubuwsat_dv(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vsubw
+ __builtin_HEXAGON_V6_vsubw(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vsubw.dv
+ __builtin_HEXAGON_V6_vsubw_dv(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vsubwnq
+ __builtin_HEXAGON_V6_vsubwnq(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vsubwq
+ __builtin_HEXAGON_V6_vsubwq(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vsubwsat
+ __builtin_HEXAGON_V6_vsubwsat(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vsubwsat.dv
+ __builtin_HEXAGON_V6_vsubwsat_dv(v128, v128);
+ // CHECK: @llvm.hexagon.V6.vswap
+ __builtin_HEXAGON_V6_vswap(v64, v64, v64);
+ // CHECK: @llvm.hexagon.V6.vtmpyb
+ __builtin_HEXAGON_V6_vtmpyb(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vtmpyb.acc
+ __builtin_HEXAGON_V6_vtmpyb_acc(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vtmpybus
+ __builtin_HEXAGON_V6_vtmpybus(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vtmpybus.acc
+ __builtin_HEXAGON_V6_vtmpybus_acc(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vtmpyhb
+ __builtin_HEXAGON_V6_vtmpyhb(v128, 0);
+ // CHECK: @llvm.hexagon.V6.vtmpyhb.acc
+ __builtin_HEXAGON_V6_vtmpyhb_acc(v128, v128, 0);
+ // CHECK: @llvm.hexagon.V6.vunpackb
+ __builtin_HEXAGON_V6_vunpackb(v64);
+ // CHECK: @llvm.hexagon.V6.vunpackh
+ __builtin_HEXAGON_V6_vunpackh(v64);
+ // CHECK: @llvm.hexagon.V6.vunpackob
+ __builtin_HEXAGON_V6_vunpackob(v128, v64);
+ // CHECK: @llvm.hexagon.V6.vunpackoh
+ __builtin_HEXAGON_V6_vunpackoh(v128, v64);
+ // CHECK: @llvm.hexagon.V6.vunpackub
+ __builtin_HEXAGON_V6_vunpackub(v64);
+ // CHECK: @llvm.hexagon.V6.vunpackuh
+ __builtin_HEXAGON_V6_vunpackuh(v64);
+ // CHECK: @llvm.hexagon.V6.vxor
+ __builtin_HEXAGON_V6_vxor(v64, v64);
+ // CHECK: @llvm.hexagon.V6.vzb
+ __builtin_HEXAGON_V6_vzb(v64);
+ // CHECK: @llvm.hexagon.V6.vzh
+ __builtin_HEXAGON_V6_vzh(v64);
+}
diff --git a/test/CodeGen/builtins-mips-args.c b/test/CodeGen/builtins-mips-args.c
index fd3e31443ecf..cdb42af4a53d 100644
--- a/test/CodeGen/builtins-mips-args.c
+++ b/test/CodeGen/builtins-mips-args.c
@@ -7,10 +7,10 @@ void foo() {
int a = 3;
__builtin_mips_wrdsp(2052, a); // expected-error{{argument to '__builtin_mips_wrdsp' must be a constant integer}}
__builtin_mips_rddsp(a); // expected-error{{argument to '__builtin_mips_rddsp' must be a constant integer}}
- __builtin_mips_wrdsp(2052, -1); // expected-error{{argument should be a value from 0 to 63}}
- __builtin_mips_rddsp(-1); // expected-error{{argument should be a value from 0 to 63}}
- __builtin_mips_wrdsp(2052, 64); // expected-error{{argument should be a value from 0 to 63}}
- __builtin_mips_rddsp(64); // expected-error{{argument should be a value from 0 to 63}}
+ __builtin_mips_wrdsp(2052, -1); // expected-error-re{{argument value {{.*}} is outside the valid range}}
+ __builtin_mips_rddsp(-1); // expected-error-re{{argument value {{.*}} is outside the valid range}}
+ __builtin_mips_wrdsp(2052, 64); // expected-error-re{{argument value {{.*}} is outside the valid range}}
+ __builtin_mips_rddsp(64); // expected-error-re{{argument value {{.*}} is outside the valid range}}
// MIPS DSP Rev 2
@@ -20,18 +20,18 @@ void foo() {
__builtin_mips_precr_sra_r_ph_w(1, 2, a); // expected-error{{argument to '__builtin_mips_precr_sra_r_ph_w' must be a constant integer}}
__builtin_mips_prepend(1, 2, a); // expected-error{{argument to '__builtin_mips_prepend' must be a constant integer}}
- __builtin_mips_append(1, 2, -1); // expected-error{{argument should be a value from 0 to 31}}
- __builtin_mips_append(1, 2, 32); // expected-error{{argument should be a value from 0 to 31}}
+ __builtin_mips_append(1, 2, -1); // expected-error-re{{argument value {{.*}} is outside the valid range}}
+ __builtin_mips_append(1, 2, 32); // expected-error-re{{argument value {{.*}} is outside the valid range}}
- __builtin_mips_balign(1, 2, -1); // expected-error{{argument should be a value from 0 to 3}}
- __builtin_mips_balign(1, 2, 4); // expected-error{{argument should be a value from 0 to 3}}
+ __builtin_mips_balign(1, 2, -1); // expected-error-re{{argument value {{.*}} is outside the valid range}}
+ __builtin_mips_balign(1, 2, 4); // expected-error-re{{argument value {{.*}} is outside the valid range}}
- __builtin_mips_precr_sra_ph_w(1, 2, -1); // expected-error{{argument should be a value from 0 to 31}}
- __builtin_mips_precr_sra_ph_w(1, 2, 32); // expected-error{{argument should be a value from 0 to 31}}
+ __builtin_mips_precr_sra_ph_w(1, 2, -1); // expected-error-re{{argument value {{.*}} is outside the valid range}}
+ __builtin_mips_precr_sra_ph_w(1, 2, 32); // expected-error-re{{argument value {{.*}} is outside the valid range}}
- __builtin_mips_precr_sra_r_ph_w(1, 2, -1); // expected-error{{argument should be a value from 0 to 31}}
- __builtin_mips_precr_sra_r_ph_w(1, 2, 32); // expected-error{{argument should be a value from 0 to 31}}
+ __builtin_mips_precr_sra_r_ph_w(1, 2, -1); // expected-error-re{{argument value {{.*}} is outside the valid range}}
+ __builtin_mips_precr_sra_r_ph_w(1, 2, 32); // expected-error-re{{argument value {{.*}} is outside the valid range}}
- __builtin_mips_prepend(1, 2, -1); // expected-error{{argument should be a value from 0 to 31}}
- __builtin_mips_prepend(1, 2, -1); // expected-error{{argument should be a value from 0 to 31}}
+ __builtin_mips_prepend(1, 2, -1); // expected-error-re{{argument value {{.*}} is outside the valid range}}
+ __builtin_mips_prepend(1, 2, -1); // expected-error-re{{argument value {{.*}} is outside the valid range}}
}
diff --git a/test/CodeGen/builtins-ms.c b/test/CodeGen/builtins-ms.c
index a33b57de8ddf..915cc17e002c 100644
--- a/test/CodeGen/builtins-ms.c
+++ b/test/CodeGen/builtins-ms.c
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 %s -emit-llvm -o - -fms-extensions -triple i686-pc-win32 | FileCheck %s
-// CHECK-LABEL: define void @test_alloca(
+// CHECK-LABEL: define dso_local void @test_alloca(
void capture(void *);
void test_alloca(int n) {
capture(_alloca(n));
@@ -8,7 +8,7 @@ void test_alloca(int n) {
// CHECK: call void @capture(i8* %[[arg]])
}
-// CHECK-LABEL: define void @test_alloca_with_align(
+// CHECK-LABEL: define dso_local void @test_alloca_with_align(
void test_alloca_with_align(int n) {
capture(__builtin_alloca_with_align(n, 64));
// CHECK: %[[arg:.*]] = alloca i8, i32 %{{.*}}, align 8
diff --git a/test/CodeGen/builtins-nvptx-ptx50.cu b/test/CodeGen/builtins-nvptx-ptx50.cu
index e85be442eb47..72e1aecb4870 100644
--- a/test/CodeGen/builtins-nvptx-ptx50.cu
+++ b/test/CodeGen/builtins-nvptx-ptx50.cu
@@ -18,6 +18,6 @@
// CHECK-LABEL: test_fn
__device__ void test_fn(double d, double* double_ptr) {
// CHECK: call double @llvm.nvvm.atomic.load.add.f64.p0f64
- // expected-error@+1 {{'__nvvm_atom_add_gen_d' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_add_gen_d' needs target feature sm_60}}
__nvvm_atom_add_gen_d(double_ptr, d);
}
diff --git a/test/CodeGen/builtins-nvptx-sm_70.cu b/test/CodeGen/builtins-nvptx-sm_70.cu
index 09e5b6ba7a7d..66fa1b5d6386 100644
--- a/test/CodeGen/builtins-nvptx-sm_70.cu
+++ b/test/CodeGen/builtins-nvptx-sm_70.cu
@@ -1,9 +1,16 @@
// RUN: %clang_cc1 -triple nvptx64-unknown-unknown -target-cpu sm_70 \
// RUN: -fcuda-is-device -target-feature +ptx60 \
// RUN: -S -emit-llvm -o - -x cuda %s \
-// RUN: | FileCheck -check-prefix=CHECK %s
+// RUN: | FileCheck -check-prefix=CHECK_M16 %s
+// RUN: %clang_cc1 -triple nvptx64-unknown-unknown -target-cpu sm_70 \
+// RUN: -fcuda-is-device -target-feature +ptx61 -DPTX61 \
+// RUN: -S -emit-llvm -o - -x cuda %s \
+// RUN: | FileCheck -check-prefixes=CHECK_M16,CHECK_M32_M8 %s
// RUN: %clang_cc1 -triple nvptx-unknown-unknown -target-cpu sm_60 \
-// RUN: -fcuda-is-device -S -o /dev/null -x cuda -verify %s
+// RUN: -DPTX61 -fcuda-is-device -S -o /dev/null -x cuda -verify=pre-sm_70 %s
+// RUN: %clang_cc1 -triple nvptx-unknown-unknown \
+// RUN: -target-cpu sm_70 -target-feature +ptx60 \
+// RUN: -DPTX61 -fcuda-is-device -S -o /dev/null -x cuda -verify=pre-ptx61 %s
#if !defined(CUDA_VERSION)
#define __device__ __attribute__((device))
@@ -18,149 +25,443 @@ typedef unsigned long long uint64_t;
// that encounters an error, so -verify will not be able to find errors in
// subsequent functions.
-// CHECK-LABEL: nvvm_wmma
-__device__ void nvvm_wmma(int *src, int *dst,
- float *fsrc, float *fdst,
- int ldm) {
- // CHECK: call {{.*}} @llvm.nvvm.wmma.load.a.sync.row.m16n16k16.stride.f16
- // expected-error@+1 {{'__hmma_m16n16k16_ld_a' needs target feature ptx60}}
+// CHECK-LABEL: nvvm_wmma_m16n16k16
+__device__ void nvvm_wmma_m16n16k16(int *src, int *dst,
+ float *fsrc, float *fdst,
+ int ldm) {
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.load.a.row.stride.f16
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_ld_a' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_ld_a(dst, src, ldm, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.load.a.sync.col.m16n16k16.stride.f16
- // expected-error@+1 {{'__hmma_m16n16k16_ld_a' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.load.a.col.stride.f16
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_ld_a' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_ld_a(dst, src+1, ldm, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.load.b.sync.row.m16n16k16.stride.f16
- // expected-error@+1 {{'__hmma_m16n16k16_ld_b' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.load.b.row.stride.f16
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_ld_b' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_ld_b(dst, src, ldm, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.load.b.sync.col.m16n16k16.stride.f16
- // expected-error@+1 {{'__hmma_m16n16k16_ld_b' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.load.b.col.stride.f16
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_ld_b' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_ld_b(dst, src+2, ldm, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.load.c.sync.row.m16n16k16.stride.f16
- // expected-error@+1 {{'__hmma_m16n16k16_ld_c_f16' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.load.c.row.stride.f16
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_ld_c_f16' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_ld_c_f16(dst, src, ldm, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.load.c.sync.col.m16n16k16.stride.f16
- // expected-error@+1 {{'__hmma_m16n16k16_ld_c_f16' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.load.c.col.stride.f16
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_ld_c_f16' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_ld_c_f16(dst, src, ldm, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.load.c.sync.row.m16n16k16.stride.f32
- // expected-error@+1 {{'__hmma_m16n16k16_ld_c_f32' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.load.c.row.stride.f32
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_ld_c_f32' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_ld_c_f32(fdst, fsrc, ldm, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.load.c.sync.col.m16n16k16.stride.f32
- // expected-error@+1 {{'__hmma_m16n16k16_ld_c_f32' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.load.c.col.stride.f32
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_ld_c_f32' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_ld_c_f32(fdst, fsrc, ldm, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.store.d.sync.row.m16n16k16.stride.f16
- // expected-error@+1 {{'__hmma_m16n16k16_st_c_f16' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.store.d.row.stride.f16
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_st_c_f16' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_st_c_f16(dst, src, ldm, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.store.d.sync.col.m16n16k16.stride.f16
- // expected-error@+1 {{'__hmma_m16n16k16_st_c_f16' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.store.d.col.stride.f16
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_st_c_f16' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_st_c_f16(dst, src, ldm, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.store.d.sync.row.m16n16k16.stride.f32
- // expected-error@+1 {{'__hmma_m16n16k16_st_c_f32' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.store.d.row.stride.f32
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_st_c_f32' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_st_c_f32(fdst, fsrc, ldm, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.store.d.sync.col.m16n16k16.stride.f32
- // expected-error@+1 {{'__hmma_m16n16k16_st_c_f32' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.store.d.col.stride.f32
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_st_c_f32' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_st_c_f32(fdst, fsrc, ldm, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.row.m16n16k16.f16.f16
- // expected-error@+1 {{'__hmma_m16n16k16_mma_f16f16' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.row.row.f16.f16
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_mma_f16f16' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_mma_f16f16(dst, src, src, src, 0, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.row.m16n16k16.f16.f16.satfinite
- // expected-error@+1 {{'__hmma_m16n16k16_mma_f16f16' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.row.row.f16.f16.satfinite
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_mma_f16f16' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_mma_f16f16(dst, src, src, src, 0, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.col.m16n16k16.f16.f16
- // expected-error@+1 {{'__hmma_m16n16k16_mma_f16f16' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.row.col.f16.f16
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_mma_f16f16' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_mma_f16f16(dst, src, src, src, 1, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.col.m16n16k16.f16.f16.satfinite
- // expected-error@+1 {{'__hmma_m16n16k16_mma_f16f16' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.row.col.f16.f16.satfinite
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_mma_f16f16' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_mma_f16f16(dst, src, src, src, 1, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.row.m16n16k16.f16.f16
- // expected-error@+1 {{'__hmma_m16n16k16_mma_f16f16' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.col.row.f16.f16
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_mma_f16f16' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_mma_f16f16(dst, src, src, src, 2, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.row.m16n16k16.f16.f16.satfinite
- // expected-error@+1 {{'__hmma_m16n16k16_mma_f16f16' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.col.row.f16.f16.satfinite
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_mma_f16f16' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_mma_f16f16(dst, src, src, src, 2, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.col.m16n16k16.f16.f16
- // expected-error@+1 {{'__hmma_m16n16k16_mma_f16f16' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.col.col.f16.f16
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_mma_f16f16' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_mma_f16f16(dst, src, src, src, 3, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.col.m16n16k16.f16.f16.satfinite
- // expected-error@+1 {{'__hmma_m16n16k16_mma_f16f16' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.col.col.f16.f16.satfinite
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_mma_f16f16' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_mma_f16f16(dst, src, src, src, 3, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.row.m16n16k16.f16.f32
- // expected-error@+1 {{'__hmma_m16n16k16_mma_f16f32' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.row.row.f16.f32
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_mma_f16f32' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_mma_f16f32(dst, src, src, fsrc, 0, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.row.m16n16k16.f16.f32.satfinite
- // expected-error@+1 {{'__hmma_m16n16k16_mma_f16f32' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.row.row.f16.f32.satfinite
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_mma_f16f32' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_mma_f16f32(dst, src, src, fsrc, 0, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.col.m16n16k16.f16.f32
- // expected-error@+1 {{'__hmma_m16n16k16_mma_f16f32' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.row.col.f16.f32
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_mma_f16f32' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_mma_f16f32(dst, src, src, fsrc, 1, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.col.m16n16k16.f16.f32.satfinite
- // expected-error@+1 {{'__hmma_m16n16k16_mma_f16f32' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.row.col.f16.f32.satfinite
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_mma_f16f32' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_mma_f16f32(dst, src, src, fsrc, 1, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.row.m16n16k16.f16.f32
- // expected-error@+1 {{'__hmma_m16n16k16_mma_f16f32' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.col.row.f16.f32
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_mma_f16f32' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_mma_f16f32(dst, src, src, fsrc, 2, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.row.m16n16k16.f16.f32.satfinite
- // expected-error@+1 {{'__hmma_m16n16k16_mma_f16f32' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.col.row.f16.f32.satfinite
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_mma_f16f32' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_mma_f16f32(dst, src, src, fsrc, 2, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.col.m16n16k16.f16.f32
- // expected-error@+1 {{'__hmma_m16n16k16_mma_f16f32' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.col.col.f16.f32
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_mma_f16f32' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_mma_f16f32(dst, src, src, fsrc, 3, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.col.m16n16k16.f16.f32.satfinite
- // expected-error@+1 {{'__hmma_m16n16k16_mma_f16f32' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.col.col.f16.f32.satfinite
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_mma_f16f32' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_mma_f16f32(dst, src, src, fsrc, 3, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.row.m16n16k16.f32.f16
- // expected-error@+1 {{'__hmma_m16n16k16_mma_f32f16' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.row.row.f32.f16
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_mma_f32f16' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_mma_f32f16(fdst, src, src, src, 0, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.row.m16n16k16.f32.f16.satfinite
- // expected-error@+1 {{'__hmma_m16n16k16_mma_f32f16' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.row.row.f32.f16.satfinite
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_mma_f32f16' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_mma_f32f16(fdst, src, src, src, 0, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.col.m16n16k16.f32.f16
- // expected-error@+1 {{'__hmma_m16n16k16_mma_f32f16' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.row.col.f32.f16
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_mma_f32f16' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_mma_f32f16(fdst, src, src, src, 1, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.col.m16n16k16.f32.f16.satfinite
- // expected-error@+1 {{'__hmma_m16n16k16_mma_f32f16' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.row.col.f32.f16.satfinite
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_mma_f32f16' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_mma_f32f16(fdst, src, src, src, 1, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.row.m16n16k16.f32.f16
- // expected-error@+1 {{'__hmma_m16n16k16_mma_f32f16' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.col.row.f32.f16
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_mma_f32f16' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_mma_f32f16(fdst, src, src, src, 2, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.row.m16n16k16.f32.f16.satfinite
- // expected-error@+1 {{'__hmma_m16n16k16_mma_f32f16' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.col.row.f32.f16.satfinite
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_mma_f32f16' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_mma_f32f16(fdst, src, src, src, 2, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.col.m16n16k16.f32.f16
- // expected-error@+1 {{'__hmma_m16n16k16_mma_f32f16' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.col.col.f32.f16
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_mma_f32f16' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_mma_f32f16(fdst, src, src, src, 3, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.col.m16n16k16.f32.f16.satfinite
- // expected-error@+1 {{'__hmma_m16n16k16_mma_f32f16' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.col.col.f32.f16.satfinite
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_mma_f32f16' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_mma_f32f16(fdst, src, src, src, 3, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.row.m16n16k16.f32.f32
- // expected-error@+1 {{'__hmma_m16n16k16_mma_f32f32' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.row.row.f32.f32
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_mma_f32f32' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_mma_f32f32(fdst, src, src, fsrc, 0, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.row.m16n16k16.f32.f32.satfinite
- // expected-error@+1 {{'__hmma_m16n16k16_mma_f32f32' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.row.row.f32.f32.satfinite
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_mma_f32f32' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_mma_f32f32(fdst, src, src, fsrc, 0, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.col.m16n16k16.f32.f32
- // expected-error@+1 {{'__hmma_m16n16k16_mma_f32f32' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.row.col.f32.f32
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_mma_f32f32' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_mma_f32f32(fdst, src, src, fsrc, 1, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.col.m16n16k16.f32.f32.satfinite
- // expected-error@+1 {{'__hmma_m16n16k16_mma_f32f32' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.row.col.f32.f32.satfinite
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_mma_f32f32' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_mma_f32f32(fdst, src, src, fsrc, 1, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.row.m16n16k16.f32.f32
- // expected-error@+1 {{'__hmma_m16n16k16_mma_f32f32' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.col.row.f32.f32
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_mma_f32f32' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_mma_f32f32(fdst, src, src, fsrc, 2, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.row.m16n16k16.f32.f32.satfinite
- // expected-error@+1 {{'__hmma_m16n16k16_mma_f32f32' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.col.row.f32.f32.satfinite
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_mma_f32f32' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_mma_f32f32(fdst, src, src, fsrc, 2, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.col.m16n16k16.f32.f32
- // expected-error@+1 {{'__hmma_m16n16k16_mma_f32f32' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.col.col.f32.f32
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_mma_f32f32' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_mma_f32f32(fdst, src, src, fsrc, 3, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.col.m16n16k16.f32.f32.satfinite
- // expected-error@+1 {{'__hmma_m16n16k16_mma_f32f32' needs target feature ptx60}}
+ // CHECK_M16: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.col.col.f32.f32.satfinite
+ // pre-sm_70-error-re@+1 {{'__hmma_m16n16k16_mma_f32f32' needs target feature sm_70{{.*}},ptx60{{.*}}}}
__hmma_m16n16k16_mma_f32f32(fdst, src, src, fsrc, 3, 1);
}
+
+#ifdef PTX61
+// CHECK-LABEL: nvvm_wmma_m32n8k16
+__device__ void nvvm_wmma_m32n8k16(int *src, int *dst,
+ float *fsrc, float *fdst,
+ int ldm) {
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.load.a.row.stride.f16
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_ld_a' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_ld_a(dst, src, ldm, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.load.a.col.stride.f16
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_ld_a' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_ld_a(dst, src+1, ldm, 1);
+
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.load.b.row.stride.f16
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_ld_b' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_ld_b(dst, src, ldm, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.load.b.col.stride.f16
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_ld_b' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_ld_b(dst, src+2, ldm, 1);
+
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.load.c.row.stride.f16
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_ld_c_f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_ld_c_f16(dst, src, ldm, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.load.c.col.stride.f16
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_ld_c_f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_ld_c_f16(dst, src, ldm, 1);
+
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.load.c.row.stride.f32
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_ld_c_f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_ld_c_f32(fdst, fsrc, ldm, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.load.c.col.stride.f32
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_ld_c_f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_ld_c_f32(fdst, fsrc, ldm, 1);
+
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.store.d.row.stride.f16
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_st_c_f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_st_c_f16(dst, src, ldm, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.store.d.col.stride.f16
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_st_c_f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_st_c_f16(dst, src, ldm, 1);
+
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.store.d.row.stride.f32
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_st_c_f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_st_c_f32(fdst, fsrc, ldm, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.store.d.col.stride.f32
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_st_c_f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_st_c_f32(fdst, fsrc, ldm, 1);
+
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.mma.row.row.f16.f16
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_mma_f16f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_mma_f16f16(dst, src, src, src, 0, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.mma.row.row.f16.f16.satfinite
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_mma_f16f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_mma_f16f16(dst, src, src, src, 0, 1);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.mma.row.col.f16.f16
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_mma_f16f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_mma_f16f16(dst, src, src, src, 1, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.mma.row.col.f16.f16.satfinite
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_mma_f16f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_mma_f16f16(dst, src, src, src, 1, 1);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.mma.col.row.f16.f16
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_mma_f16f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_mma_f16f16(dst, src, src, src, 2, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.mma.col.row.f16.f16.satfinite
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_mma_f16f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_mma_f16f16(dst, src, src, src, 2, 1);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.mma.col.col.f16.f16
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_mma_f16f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_mma_f16f16(dst, src, src, src, 3, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.mma.col.col.f16.f16.satfinite
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_mma_f16f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_mma_f16f16(dst, src, src, src, 3, 1);
+
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.mma.row.row.f16.f32
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_mma_f16f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_mma_f16f32(dst, src, src, fsrc, 0, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.mma.row.row.f16.f32.satfinite
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_mma_f16f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_mma_f16f32(dst, src, src, fsrc, 0, 1);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.mma.row.col.f16.f32
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_mma_f16f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_mma_f16f32(dst, src, src, fsrc, 1, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.mma.row.col.f16.f32.satfinite
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_mma_f16f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_mma_f16f32(dst, src, src, fsrc, 1, 1);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.mma.col.row.f16.f32
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_mma_f16f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_mma_f16f32(dst, src, src, fsrc, 2, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.mma.col.row.f16.f32.satfinite
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_mma_f16f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_mma_f16f32(dst, src, src, fsrc, 2, 1);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.mma.col.col.f16.f32
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_mma_f16f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_mma_f16f32(dst, src, src, fsrc, 3, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.mma.col.col.f16.f32.satfinite
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_mma_f16f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_mma_f16f32(dst, src, src, fsrc, 3, 1);
+
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.mma.row.row.f32.f16
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_mma_f32f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_mma_f32f16(fdst, src, src, src, 0, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.mma.row.row.f32.f16.satfinite
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_mma_f32f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_mma_f32f16(fdst, src, src, src, 0, 1);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.mma.row.col.f32.f16
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_mma_f32f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_mma_f32f16(fdst, src, src, src, 1, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.mma.row.col.f32.f16.satfinite
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_mma_f32f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_mma_f32f16(fdst, src, src, src, 1, 1);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.mma.col.row.f32.f16
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_mma_f32f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_mma_f32f16(fdst, src, src, src, 2, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.mma.col.row.f32.f16.satfinite
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_mma_f32f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_mma_f32f16(fdst, src, src, src, 2, 1);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.mma.col.col.f32.f16
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_mma_f32f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_mma_f32f16(fdst, src, src, src, 3, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.mma.col.col.f32.f16.satfinite
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_mma_f32f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_mma_f32f16(fdst, src, src, src, 3, 1);
+
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.mma.row.row.f32.f32
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_mma_f32f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_mma_f32f32(fdst, src, src, fsrc, 0, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.mma.row.row.f32.f32.satfinite
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_mma_f32f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_mma_f32f32(fdst, src, src, fsrc, 0, 1);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.mma.row.col.f32.f32
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_mma_f32f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_mma_f32f32(fdst, src, src, fsrc, 1, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.mma.row.col.f32.f32.satfinite
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_mma_f32f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_mma_f32f32(fdst, src, src, fsrc, 1, 1);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.mma.col.row.f32.f32
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_mma_f32f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_mma_f32f32(fdst, src, src, fsrc, 2, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.mma.col.row.f32.f32.satfinite
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_mma_f32f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_mma_f32f32(fdst, src, src, fsrc, 2, 1);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.mma.col.col.f32.f32
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_mma_f32f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_mma_f32f32(fdst, src, src, fsrc, 3, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m32n8k16.mma.col.col.f32.f32.satfinite
+ // pre-ptx61-error-re@+1 {{'__hmma_m32n8k16_mma_f32f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m32n8k16_mma_f32f32(fdst, src, src, fsrc, 3, 1);
+
+
+ // m8n32k16 variants.
+
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.load.a.row.stride.f16
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_ld_a' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_ld_a(dst, src, ldm, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.load.a.col.stride.f16
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_ld_a' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_ld_a(dst, src+1, ldm, 1);
+
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.load.b.row.stride.f16
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_ld_b' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_ld_b(dst, src, ldm, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.load.b.col.stride.f16
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_ld_b' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_ld_b(dst, src+2, ldm, 1);
+
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.load.c.row.stride.f16
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_ld_c_f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_ld_c_f16(dst, src, ldm, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.load.c.col.stride.f16
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_ld_c_f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_ld_c_f16(dst, src, ldm, 1);
+
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.load.c.row.stride.f32
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_ld_c_f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_ld_c_f32(fdst, fsrc, ldm, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.load.c.col.stride.f32
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_ld_c_f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_ld_c_f32(fdst, fsrc, ldm, 1);
+
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.store.d.row.stride.f16
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_st_c_f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_st_c_f16(dst, src, ldm, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.store.d.col.stride.f16
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_st_c_f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_st_c_f16(dst, src, ldm, 1);
+
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.store.d.row.stride.f32
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_st_c_f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_st_c_f32(fdst, fsrc, ldm, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.store.d.col.stride.f32
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_st_c_f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_st_c_f32(fdst, fsrc, ldm, 1);
+
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.mma.row.row.f16.f16
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_mma_f16f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_mma_f16f16(dst, src, src, src, 0, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.mma.row.row.f16.f16.satfinite
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_mma_f16f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_mma_f16f16(dst, src, src, src, 0, 1);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.mma.row.col.f16.f16
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_mma_f16f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_mma_f16f16(dst, src, src, src, 1, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.mma.row.col.f16.f16.satfinite
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_mma_f16f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_mma_f16f16(dst, src, src, src, 1, 1);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.mma.col.row.f16.f16
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_mma_f16f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_mma_f16f16(dst, src, src, src, 2, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.mma.col.row.f16.f16.satfinite
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_mma_f16f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_mma_f16f16(dst, src, src, src, 2, 1);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.mma.col.col.f16.f16
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_mma_f16f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_mma_f16f16(dst, src, src, src, 3, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.mma.col.col.f16.f16.satfinite
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_mma_f16f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_mma_f16f16(dst, src, src, src, 3, 1);
+
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.mma.row.row.f16.f32
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_mma_f16f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_mma_f16f32(dst, src, src, fsrc, 0, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.mma.row.row.f16.f32.satfinite
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_mma_f16f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_mma_f16f32(dst, src, src, fsrc, 0, 1);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.mma.row.col.f16.f32
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_mma_f16f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_mma_f16f32(dst, src, src, fsrc, 1, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.mma.row.col.f16.f32.satfinite
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_mma_f16f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_mma_f16f32(dst, src, src, fsrc, 1, 1);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.mma.col.row.f16.f32
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_mma_f16f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_mma_f16f32(dst, src, src, fsrc, 2, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.mma.col.row.f16.f32.satfinite
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_mma_f16f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_mma_f16f32(dst, src, src, fsrc, 2, 1);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.mma.col.col.f16.f32
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_mma_f16f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_mma_f16f32(dst, src, src, fsrc, 3, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.mma.col.col.f16.f32.satfinite
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_mma_f16f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_mma_f16f32(dst, src, src, fsrc, 3, 1);
+
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.mma.row.row.f32.f16
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_mma_f32f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_mma_f32f16(fdst, src, src, src, 0, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.mma.row.row.f32.f16.satfinite
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_mma_f32f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_mma_f32f16(fdst, src, src, src, 0, 1);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.mma.row.col.f32.f16
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_mma_f32f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_mma_f32f16(fdst, src, src, src, 1, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.mma.row.col.f32.f16.satfinite
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_mma_f32f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_mma_f32f16(fdst, src, src, src, 1, 1);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.mma.col.row.f32.f16
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_mma_f32f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_mma_f32f16(fdst, src, src, src, 2, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.mma.col.row.f32.f16.satfinite
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_mma_f32f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_mma_f32f16(fdst, src, src, src, 2, 1);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.mma.col.col.f32.f16
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_mma_f32f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_mma_f32f16(fdst, src, src, src, 3, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.mma.col.col.f32.f16.satfinite
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_mma_f32f16' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_mma_f32f16(fdst, src, src, src, 3, 1);
+
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.mma.row.row.f32.f32
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_mma_f32f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_mma_f32f32(fdst, src, src, fsrc, 0, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.mma.row.row.f32.f32.satfinite
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_mma_f32f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_mma_f32f32(fdst, src, src, fsrc, 0, 1);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.mma.row.col.f32.f32
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_mma_f32f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_mma_f32f32(fdst, src, src, fsrc, 1, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.mma.row.col.f32.f32.satfinite
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_mma_f32f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_mma_f32f32(fdst, src, src, fsrc, 1, 1);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.mma.col.row.f32.f32
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_mma_f32f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_mma_f32f32(fdst, src, src, fsrc, 2, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.mma.col.row.f32.f32.satfinite
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_mma_f32f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_mma_f32f32(fdst, src, src, fsrc, 2, 1);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.mma.col.col.f32.f32
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_mma_f32f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_mma_f32f32(fdst, src, src, fsrc, 3, 0);
+ // CHECK_M32_M8: call {{.*}} @llvm.nvvm.wmma.m8n32k16.mma.col.col.f32.f32.satfinite
+ // pre-ptx61-error-re@+1 {{'__hmma_m8n32k16_mma_f32f32' needs target feature sm_70{{.*}},ptx61{{.*}}}}
+ __hmma_m8n32k16_mma_f32f32(fdst, src, src, fsrc, 3, 1);
+}
+#endif
diff --git a/test/CodeGen/builtins-nvptx.c b/test/CodeGen/builtins-nvptx.c
index 89a982377ad4..16f41bac3432 100644
--- a/test/CodeGen/builtins-nvptx.c
+++ b/test/CodeGen/builtins-nvptx.c
@@ -5,6 +5,9 @@
// RUN: %clang_cc1 -triple nvptx64-unknown-unknown -target-cpu sm_60 \
// RUN: -fcuda-is-device -S -emit-llvm -o - -x cuda %s \
// RUN: | FileCheck -check-prefix=CHECK -check-prefix=LP64 %s
+// RUN: %clang_cc1 -triple nvptx64-unknown-unknown -target-cpu sm_61 \
+// RUN: -fcuda-is-device -S -emit-llvm -o - -x cuda %s \
+// RUN: | FileCheck -check-prefix=CHECK -check-prefix=LP64 %s
// RUN: %clang_cc1 -triple nvptx-unknown-unknown -target-cpu sm_53 \
// RUN: -DERROR_CHECK -fcuda-is-device -S -o /dev/null -x cuda -verify %s
@@ -292,245 +295,245 @@ __device__ void nvvm_atom(float *fp, float f, double *dfp, double df, int *ip,
#if ERROR_CHECK || __CUDA_ARCH__ >= 600
// CHECK: call i32 @llvm.nvvm.atomic.add.gen.i.cta.i32.p0i32
- // expected-error@+1 {{'__nvvm_atom_cta_add_gen_i' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_add_gen_i' needs target feature sm_60}}
__nvvm_atom_cta_add_gen_i(ip, i);
// LP32: call i32 @llvm.nvvm.atomic.add.gen.i.cta.i32.p0i32
// LP64: call i64 @llvm.nvvm.atomic.add.gen.i.cta.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_cta_add_gen_l' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_add_gen_l' needs target feature sm_60}}
__nvvm_atom_cta_add_gen_l(&dl, l);
// CHECK: call i64 @llvm.nvvm.atomic.add.gen.i.cta.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_cta_add_gen_ll' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_add_gen_ll' needs target feature sm_60}}
__nvvm_atom_cta_add_gen_ll(&sll, ll);
// CHECK: call i32 @llvm.nvvm.atomic.add.gen.i.sys.i32.p0i32
- // expected-error@+1 {{'__nvvm_atom_sys_add_gen_i' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_add_gen_i' needs target feature sm_60}}
__nvvm_atom_sys_add_gen_i(ip, i);
// LP32: call i32 @llvm.nvvm.atomic.add.gen.i.sys.i32.p0i32
// LP64: call i64 @llvm.nvvm.atomic.add.gen.i.sys.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_sys_add_gen_l' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_add_gen_l' needs target feature sm_60}}
__nvvm_atom_sys_add_gen_l(&dl, l);
// CHECK: call i64 @llvm.nvvm.atomic.add.gen.i.sys.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_sys_add_gen_ll' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_add_gen_ll' needs target feature sm_60}}
__nvvm_atom_sys_add_gen_ll(&sll, ll);
// CHECK: call float @llvm.nvvm.atomic.add.gen.f.cta.f32.p0f32
- // expected-error@+1 {{'__nvvm_atom_cta_add_gen_f' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_add_gen_f' needs target feature sm_60}}
__nvvm_atom_cta_add_gen_f(fp, f);
// CHECK: call double @llvm.nvvm.atomic.add.gen.f.cta.f64.p0f64
- // expected-error@+1 {{'__nvvm_atom_cta_add_gen_d' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_add_gen_d' needs target feature sm_60}}
__nvvm_atom_cta_add_gen_d(dfp, df);
// CHECK: call float @llvm.nvvm.atomic.add.gen.f.sys.f32.p0f32
- // expected-error@+1 {{'__nvvm_atom_sys_add_gen_f' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_add_gen_f' needs target feature sm_60}}
__nvvm_atom_sys_add_gen_f(fp, f);
// CHECK: call double @llvm.nvvm.atomic.add.gen.f.sys.f64.p0f64
- // expected-error@+1 {{'__nvvm_atom_sys_add_gen_d' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_add_gen_d' needs target feature sm_60}}
__nvvm_atom_sys_add_gen_d(dfp, df);
// CHECK: call i32 @llvm.nvvm.atomic.exch.gen.i.cta.i32.p0i32
- // expected-error@+1 {{'__nvvm_atom_cta_xchg_gen_i' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_xchg_gen_i' needs target feature sm_60}}
__nvvm_atom_cta_xchg_gen_i(ip, i);
// LP32: call i32 @llvm.nvvm.atomic.exch.gen.i.cta.i32.p0i32
// LP64: call i64 @llvm.nvvm.atomic.exch.gen.i.cta.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_cta_xchg_gen_l' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_xchg_gen_l' needs target feature sm_60}}
__nvvm_atom_cta_xchg_gen_l(&dl, l);
// CHECK: call i64 @llvm.nvvm.atomic.exch.gen.i.cta.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_cta_xchg_gen_ll' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_xchg_gen_ll' needs target feature sm_60}}
__nvvm_atom_cta_xchg_gen_ll(&sll, ll);
// CHECK: call i32 @llvm.nvvm.atomic.exch.gen.i.sys.i32.p0i32
- // expected-error@+1 {{'__nvvm_atom_sys_xchg_gen_i' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_xchg_gen_i' needs target feature sm_60}}
__nvvm_atom_sys_xchg_gen_i(ip, i);
// LP32: call i32 @llvm.nvvm.atomic.exch.gen.i.sys.i32.p0i32
// LP64: call i64 @llvm.nvvm.atomic.exch.gen.i.sys.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_sys_xchg_gen_l' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_xchg_gen_l' needs target feature sm_60}}
__nvvm_atom_sys_xchg_gen_l(&dl, l);
// CHECK: call i64 @llvm.nvvm.atomic.exch.gen.i.sys.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_sys_xchg_gen_ll' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_xchg_gen_ll' needs target feature sm_60}}
__nvvm_atom_sys_xchg_gen_ll(&sll, ll);
// CHECK: call i32 @llvm.nvvm.atomic.max.gen.i.cta.i32.p0i32
- // expected-error@+1 {{'__nvvm_atom_cta_max_gen_i' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_max_gen_i' needs target feature sm_60}}
__nvvm_atom_cta_max_gen_i(ip, i);
// CHECK: call i32 @llvm.nvvm.atomic.max.gen.i.cta.i32.p0i32
- // expected-error@+1 {{'__nvvm_atom_cta_max_gen_ui' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_max_gen_ui' needs target feature sm_60}}
__nvvm_atom_cta_max_gen_ui((unsigned int *)ip, i);
// LP32: call i32 @llvm.nvvm.atomic.max.gen.i.cta.i32.p0i32
// LP64: call i64 @llvm.nvvm.atomic.max.gen.i.cta.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_cta_max_gen_l' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_max_gen_l' needs target feature sm_60}}
__nvvm_atom_cta_max_gen_l(&dl, l);
// LP32: call i32 @llvm.nvvm.atomic.max.gen.i.cta.i32.p0i32
// LP64: call i64 @llvm.nvvm.atomic.max.gen.i.cta.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_cta_max_gen_ul' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_max_gen_ul' needs target feature sm_60}}
__nvvm_atom_cta_max_gen_ul((unsigned long *)lp, l);
// CHECK: call i64 @llvm.nvvm.atomic.max.gen.i.cta.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_cta_max_gen_ll' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_max_gen_ll' needs target feature sm_60}}
__nvvm_atom_cta_max_gen_ll(&sll, ll);
// CHECK: call i64 @llvm.nvvm.atomic.max.gen.i.cta.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_cta_max_gen_ull' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_max_gen_ull' needs target feature sm_60}}
__nvvm_atom_cta_max_gen_ull((unsigned long long *)llp, ll);
// CHECK: call i32 @llvm.nvvm.atomic.max.gen.i.sys.i32.p0i32
- // expected-error@+1 {{'__nvvm_atom_sys_max_gen_i' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_max_gen_i' needs target feature sm_60}}
__nvvm_atom_sys_max_gen_i(ip, i);
// CHECK: call i32 @llvm.nvvm.atomic.max.gen.i.sys.i32.p0i32
- // expected-error@+1 {{'__nvvm_atom_sys_max_gen_ui' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_max_gen_ui' needs target feature sm_60}}
__nvvm_atom_sys_max_gen_ui((unsigned int *)ip, i);
// LP32: call i32 @llvm.nvvm.atomic.max.gen.i.sys.i32.p0i32
// LP64: call i64 @llvm.nvvm.atomic.max.gen.i.sys.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_sys_max_gen_l' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_max_gen_l' needs target feature sm_60}}
__nvvm_atom_sys_max_gen_l(&dl, l);
// LP32: call i32 @llvm.nvvm.atomic.max.gen.i.sys.i32.p0i32
// LP64: call i64 @llvm.nvvm.atomic.max.gen.i.sys.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_sys_max_gen_ul' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_max_gen_ul' needs target feature sm_60}}
__nvvm_atom_sys_max_gen_ul((unsigned long *)lp, l);
// CHECK: call i64 @llvm.nvvm.atomic.max.gen.i.sys.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_sys_max_gen_ll' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_max_gen_ll' needs target feature sm_60}}
__nvvm_atom_sys_max_gen_ll(&sll, ll);
// CHECK: call i64 @llvm.nvvm.atomic.max.gen.i.sys.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_sys_max_gen_ull' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_max_gen_ull' needs target feature sm_60}}
__nvvm_atom_sys_max_gen_ull((unsigned long long *)llp, ll);
// CHECK: call i32 @llvm.nvvm.atomic.min.gen.i.cta.i32.p0i32
- // expected-error@+1 {{'__nvvm_atom_cta_min_gen_i' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_min_gen_i' needs target feature sm_60}}
__nvvm_atom_cta_min_gen_i(ip, i);
// CHECK: call i32 @llvm.nvvm.atomic.min.gen.i.cta.i32.p0i32
- // expected-error@+1 {{'__nvvm_atom_cta_min_gen_ui' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_min_gen_ui' needs target feature sm_60}}
__nvvm_atom_cta_min_gen_ui((unsigned int *)ip, i);
// LP32: call i32 @llvm.nvvm.atomic.min.gen.i.cta.i32.p0i32
// LP64: call i64 @llvm.nvvm.atomic.min.gen.i.cta.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_cta_min_gen_l' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_min_gen_l' needs target feature sm_60}}
__nvvm_atom_cta_min_gen_l(&dl, l);
// LP32: call i32 @llvm.nvvm.atomic.min.gen.i.cta.i32.p0i32
// LP64: call i64 @llvm.nvvm.atomic.min.gen.i.cta.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_cta_min_gen_ul' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_min_gen_ul' needs target feature sm_60}}
__nvvm_atom_cta_min_gen_ul((unsigned long *)lp, l);
// CHECK: call i64 @llvm.nvvm.atomic.min.gen.i.cta.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_cta_min_gen_ll' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_min_gen_ll' needs target feature sm_60}}
__nvvm_atom_cta_min_gen_ll(&sll, ll);
// CHECK: call i64 @llvm.nvvm.atomic.min.gen.i.cta.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_cta_min_gen_ull' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_min_gen_ull' needs target feature sm_60}}
__nvvm_atom_cta_min_gen_ull((unsigned long long *)llp, ll);
// CHECK: call i32 @llvm.nvvm.atomic.min.gen.i.sys.i32.p0i32
- // expected-error@+1 {{'__nvvm_atom_sys_min_gen_i' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_min_gen_i' needs target feature sm_60}}
__nvvm_atom_sys_min_gen_i(ip, i);
// CHECK: call i32 @llvm.nvvm.atomic.min.gen.i.sys.i32.p0i32
- // expected-error@+1 {{'__nvvm_atom_sys_min_gen_ui' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_min_gen_ui' needs target feature sm_60}}
__nvvm_atom_sys_min_gen_ui((unsigned int *)ip, i);
// LP32: call i32 @llvm.nvvm.atomic.min.gen.i.sys.i32.p0i32
// LP64: call i64 @llvm.nvvm.atomic.min.gen.i.sys.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_sys_min_gen_l' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_min_gen_l' needs target feature sm_60}}
__nvvm_atom_sys_min_gen_l(&dl, l);
// LP32: call i32 @llvm.nvvm.atomic.min.gen.i.sys.i32.p0i32
// LP64: call i64 @llvm.nvvm.atomic.min.gen.i.sys.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_sys_min_gen_ul' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_min_gen_ul' needs target feature sm_60}}
__nvvm_atom_sys_min_gen_ul((unsigned long *)lp, l);
// CHECK: call i64 @llvm.nvvm.atomic.min.gen.i.sys.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_sys_min_gen_ll' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_min_gen_ll' needs target feature sm_60}}
__nvvm_atom_sys_min_gen_ll(&sll, ll);
// CHECK: call i64 @llvm.nvvm.atomic.min.gen.i.sys.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_sys_min_gen_ull' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_min_gen_ull' needs target feature sm_60}}
__nvvm_atom_sys_min_gen_ull((unsigned long long *)llp, ll);
// CHECK: call i32 @llvm.nvvm.atomic.inc.gen.i.cta.i32.p0i32
- // expected-error@+1 {{'__nvvm_atom_cta_inc_gen_ui' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_inc_gen_ui' needs target feature sm_60}}
__nvvm_atom_cta_inc_gen_ui((unsigned int *)ip, i);
// CHECK: call i32 @llvm.nvvm.atomic.inc.gen.i.sys.i32.p0i32
- // expected-error@+1 {{'__nvvm_atom_sys_inc_gen_ui' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_inc_gen_ui' needs target feature sm_60}}
__nvvm_atom_sys_inc_gen_ui((unsigned int *)ip, i);
// CHECK: call i32 @llvm.nvvm.atomic.dec.gen.i.cta.i32.p0i32
- // expected-error@+1 {{'__nvvm_atom_cta_dec_gen_ui' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_dec_gen_ui' needs target feature sm_60}}
__nvvm_atom_cta_dec_gen_ui((unsigned int *)ip, i);
// CHECK: call i32 @llvm.nvvm.atomic.dec.gen.i.sys.i32.p0i32
- // expected-error@+1 {{'__nvvm_atom_sys_dec_gen_ui' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_dec_gen_ui' needs target feature sm_60}}
__nvvm_atom_sys_dec_gen_ui((unsigned int *)ip, i);
// CHECK: call i32 @llvm.nvvm.atomic.and.gen.i.cta.i32.p0i32
- // expected-error@+1 {{'__nvvm_atom_cta_and_gen_i' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_and_gen_i' needs target feature sm_60}}
__nvvm_atom_cta_and_gen_i(ip, i);
// LP32: call i32 @llvm.nvvm.atomic.and.gen.i.cta.i32.p0i32
// LP64: call i64 @llvm.nvvm.atomic.and.gen.i.cta.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_cta_and_gen_l' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_and_gen_l' needs target feature sm_60}}
__nvvm_atom_cta_and_gen_l(&dl, l);
// CHECK: call i64 @llvm.nvvm.atomic.and.gen.i.cta.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_cta_and_gen_ll' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_and_gen_ll' needs target feature sm_60}}
__nvvm_atom_cta_and_gen_ll(&sll, ll);
// CHECK: call i32 @llvm.nvvm.atomic.and.gen.i.sys.i32.p0i32
- // expected-error@+1 {{'__nvvm_atom_sys_and_gen_i' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_and_gen_i' needs target feature sm_60}}
__nvvm_atom_sys_and_gen_i(ip, i);
// LP32: call i32 @llvm.nvvm.atomic.and.gen.i.sys.i32.p0i32
// LP64: call i64 @llvm.nvvm.atomic.and.gen.i.sys.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_sys_and_gen_l' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_and_gen_l' needs target feature sm_60}}
__nvvm_atom_sys_and_gen_l(&dl, l);
// CHECK: call i64 @llvm.nvvm.atomic.and.gen.i.sys.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_sys_and_gen_ll' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_and_gen_ll' needs target feature sm_60}}
__nvvm_atom_sys_and_gen_ll(&sll, ll);
// CHECK: call i32 @llvm.nvvm.atomic.or.gen.i.cta.i32.p0i32
- // expected-error@+1 {{'__nvvm_atom_cta_or_gen_i' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_or_gen_i' needs target feature sm_60}}
__nvvm_atom_cta_or_gen_i(ip, i);
// LP32: call i32 @llvm.nvvm.atomic.or.gen.i.cta.i32.p0i32
// LP64: call i64 @llvm.nvvm.atomic.or.gen.i.cta.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_cta_or_gen_l' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_or_gen_l' needs target feature sm_60}}
__nvvm_atom_cta_or_gen_l(&dl, l);
// CHECK: call i64 @llvm.nvvm.atomic.or.gen.i.cta.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_cta_or_gen_ll' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_or_gen_ll' needs target feature sm_60}}
__nvvm_atom_cta_or_gen_ll(&sll, ll);
// CHECK: call i32 @llvm.nvvm.atomic.or.gen.i.sys.i32.p0i32
- // expected-error@+1 {{'__nvvm_atom_sys_or_gen_i' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_or_gen_i' needs target feature sm_60}}
__nvvm_atom_sys_or_gen_i(ip, i);
// LP32: call i32 @llvm.nvvm.atomic.or.gen.i.sys.i32.p0i32
// LP64: call i64 @llvm.nvvm.atomic.or.gen.i.sys.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_sys_or_gen_l' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_or_gen_l' needs target feature sm_60}}
__nvvm_atom_sys_or_gen_l(&dl, l);
// CHECK: call i64 @llvm.nvvm.atomic.or.gen.i.sys.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_sys_or_gen_ll' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_or_gen_ll' needs target feature sm_60}}
__nvvm_atom_sys_or_gen_ll(&sll, ll);
// CHECK: call i32 @llvm.nvvm.atomic.xor.gen.i.cta.i32.p0i32
- // expected-error@+1 {{'__nvvm_atom_cta_xor_gen_i' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_xor_gen_i' needs target feature sm_60}}
__nvvm_atom_cta_xor_gen_i(ip, i);
// LP32: call i32 @llvm.nvvm.atomic.xor.gen.i.cta.i32.p0i32
// LP64: call i64 @llvm.nvvm.atomic.xor.gen.i.cta.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_cta_xor_gen_l' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_xor_gen_l' needs target feature sm_60}}
__nvvm_atom_cta_xor_gen_l(&dl, l);
// CHECK: call i64 @llvm.nvvm.atomic.xor.gen.i.cta.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_cta_xor_gen_ll' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_xor_gen_ll' needs target feature sm_60}}
__nvvm_atom_cta_xor_gen_ll(&sll, ll);
// CHECK: call i32 @llvm.nvvm.atomic.xor.gen.i.sys.i32.p0i32
- // expected-error@+1 {{'__nvvm_atom_sys_xor_gen_i' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_xor_gen_i' needs target feature sm_60}}
__nvvm_atom_sys_xor_gen_i(ip, i);
// LP32: call i32 @llvm.nvvm.atomic.xor.gen.i.sys.i32.p0i32
// LP64: call i64 @llvm.nvvm.atomic.xor.gen.i.sys.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_sys_xor_gen_l' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_xor_gen_l' needs target feature sm_60}}
__nvvm_atom_sys_xor_gen_l(&dl, l);
// CHECK: call i64 @llvm.nvvm.atomic.xor.gen.i.sys.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_sys_xor_gen_ll' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_xor_gen_ll' needs target feature sm_60}}
__nvvm_atom_sys_xor_gen_ll(&sll, ll);
// CHECK: call i32 @llvm.nvvm.atomic.cas.gen.i.cta.i32.p0i32
- // expected-error@+1 {{'__nvvm_atom_cta_cas_gen_i' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_cas_gen_i' needs target feature sm_60}}
__nvvm_atom_cta_cas_gen_i(ip, i, 0);
// LP32: call i32 @llvm.nvvm.atomic.cas.gen.i.cta.i32.p0i32
// LP64: call i64 @llvm.nvvm.atomic.cas.gen.i.cta.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_cta_cas_gen_l' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_cas_gen_l' needs target feature sm_60}}
__nvvm_atom_cta_cas_gen_l(&dl, l, 0);
// CHECK: call i64 @llvm.nvvm.atomic.cas.gen.i.cta.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_cta_cas_gen_ll' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_cta_cas_gen_ll' needs target feature sm_60}}
__nvvm_atom_cta_cas_gen_ll(&sll, ll, 0);
// CHECK: call i32 @llvm.nvvm.atomic.cas.gen.i.sys.i32.p0i32
- // expected-error@+1 {{'__nvvm_atom_sys_cas_gen_i' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_cas_gen_i' needs target feature sm_60}}
__nvvm_atom_sys_cas_gen_i(ip, i, 0);
// LP32: call i32 @llvm.nvvm.atomic.cas.gen.i.sys.i32.p0i32
// LP64: call i64 @llvm.nvvm.atomic.cas.gen.i.sys.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_sys_cas_gen_l' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_cas_gen_l' needs target feature sm_60}}
__nvvm_atom_sys_cas_gen_l(&dl, l, 0);
// CHECK: call i64 @llvm.nvvm.atomic.cas.gen.i.sys.i64.p0i64
- // expected-error@+1 {{'__nvvm_atom_sys_cas_gen_ll' needs target feature satom}}
+ // expected-error@+1 {{'__nvvm_atom_sys_cas_gen_ll' needs target feature sm_60}}
__nvvm_atom_sys_cas_gen_ll(&sll, ll, 0);
#endif
diff --git a/test/CodeGen/builtins-overflow.c b/test/CodeGen/builtins-overflow.c
index 7a30cfbd46ee..57f90eb66a5f 100644
--- a/test/CodeGen/builtins-overflow.c
+++ b/test/CodeGen/builtins-overflow.c
@@ -14,7 +14,7 @@ extern long long LongLongErrorCode;
void overflowed(void);
unsigned test_add_overflow_uint_uint_uint(unsigned x, unsigned y) {
- // CHECK-LABEL: define i32 @test_add_overflow_uint_uint_uint
+ // CHECK-LABEL: define {{(dso_local )?}}i32 @test_add_overflow_uint_uint_uint
// CHECK-NOT: ext
// CHECK: [[S:%.+]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
// CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
@@ -28,7 +28,7 @@ unsigned test_add_overflow_uint_uint_uint(unsigned x, unsigned y) {
}
int test_add_overflow_int_int_int(int x, int y) {
- // CHECK-LABEL: define i32 @test_add_overflow_int_int_int
+ // CHECK-LABEL: define {{(dso_local )?}}i32 @test_add_overflow_int_int_int
// CHECK-NOT: ext
// CHECK: [[S:%.+]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
// CHECK-DAG: [[C:%.+]] = extractvalue { i32, i1 } [[S]], 1
@@ -42,7 +42,7 @@ int test_add_overflow_int_int_int(int x, int y) {
}
unsigned test_sub_overflow_uint_uint_uint(unsigned x, unsigned y) {
- // CHECK-LABEL: define i32 @test_sub_overflow_uint_uint_uint
+ // CHECK-LABEL: define {{(dso_local )?}}i32 @test_sub_overflow_uint_uint_uint
// CHECK-NOT: ext
// CHECK: [[S:%.+]] = call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
// CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
@@ -56,7 +56,7 @@ unsigned test_sub_overflow_uint_uint_uint(unsigned x, unsigned y) {
}
int test_sub_overflow_int_int_int(int x, int y) {
- // CHECK-LABEL: define i32 @test_sub_overflow_int_int_int
+ // CHECK-LABEL: define {{(dso_local )?}}i32 @test_sub_overflow_int_int_int
// CHECK-NOT: ext
// CHECK: [[S:%.+]] = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
// CHECK-DAG: [[C:%.+]] = extractvalue { i32, i1 } [[S]], 1
@@ -70,7 +70,7 @@ int test_sub_overflow_int_int_int(int x, int y) {
}
unsigned test_mul_overflow_uint_uint_uint(unsigned x, unsigned y) {
- // CHECK-LABEL: define i32 @test_mul_overflow_uint_uint_uint
+ // CHECK-LABEL: define {{(dso_local )?}}i32 @test_mul_overflow_uint_uint_uint
// CHECK-NOT: ext
// CHECK: [[S:%.+]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
// CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
@@ -84,7 +84,7 @@ unsigned test_mul_overflow_uint_uint_uint(unsigned x, unsigned y) {
}
int test_mul_overflow_int_int_int(int x, int y) {
- // CHECK-LABEL: define i32 @test_mul_overflow_int_int_int
+ // CHECK-LABEL: define {{(dso_local )?}}i32 @test_mul_overflow_int_int_int
// CHECK-NOT: ext
// CHECK: [[S:%.+]] = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
// CHECK-DAG: [[C:%.+]] = extractvalue { i32, i1 } [[S]], 1
@@ -98,7 +98,7 @@ int test_mul_overflow_int_int_int(int x, int y) {
}
int test_add_overflow_uint_int_int(unsigned x, int y) {
- // CHECK-LABEL: define i32 @test_add_overflow_uint_int_int
+ // CHECK-LABEL: define {{(dso_local )?}}i32 @test_add_overflow_uint_int_int
// CHECK: [[XE:%.+]] = zext i32 %{{.+}} to i33
// CHECK: [[YE:%.+]] = sext i32 %{{.+}} to i33
// CHECK: [[S:%.+]] = call { i33, i1 } @llvm.sadd.with.overflow.i33(i33 [[XE]], i33 [[YE]])
@@ -136,7 +136,7 @@ _Bool test_add_overflow_uint_uint_bool(unsigned x, unsigned y) {
}
unsigned test_add_overflow_bool_bool_uint(_Bool x, _Bool y) {
- // CHECK-LABEL: define i32 @test_add_overflow_bool_bool_uint
+ // CHECK-LABEL: define {{(dso_local )?}}i32 @test_add_overflow_bool_bool_uint
// CHECK: [[XE:%.+]] = zext i1 %{{.+}} to i32
// CHECK: [[YE:%.+]] = zext i1 %{{.+}} to i32
// CHECK: [[S:%.+]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[XE]], i32 [[YE]])
@@ -165,7 +165,7 @@ _Bool test_add_overflow_bool_bool_bool(_Bool x, _Bool y) {
}
int test_add_overflow_volatile(int x, int y) {
- // CHECK-LABEL: define i32 @test_add_overflow_volatile
+ // CHECK-LABEL: define {{(dso_local )?}}i32 @test_add_overflow_volatile
// CHECK: [[S:%.+]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
// CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
// CHECK-DAG: [[C:%.+]] = extractvalue { i32, i1 } [[S]], 1
@@ -373,7 +373,9 @@ int test_mixed_sign_mull_overflow_unsigned(int x, unsigned y) {
// CHECK-NEXT: [[NotNull:%.*]] = icmp ne i32 [[UnsignedResult]], 0
// CHECK-NEXT: [[Underflow:%.*]] = and i1 [[IsNeg]], [[NotNull]]
// CHECK-NEXT: [[OFlow:%.*]] = or i1 [[UnsignedOFlow]], [[Underflow]]
-// CHECK-NEXT: store i32 [[UnsignedResult]], i32* %{{.*}}, align 4
+// CHECK-NEXT: [[NegatedResult:%.*]] = sub i32 0, [[UnsignedResult]]
+// CHECK-NEXT: [[Result:%.*]] = select i1 [[IsNeg]], i32 [[NegatedResult]], i32 [[UnsignedResult]]
+// CHECK-NEXT: store i32 [[Result]], i32* %{{.*}}, align 4
// CHECK: br i1 [[OFlow]]
unsigned result;
@@ -432,7 +434,9 @@ long long test_mixed_sign_mulll_overflow_trunc_unsigned(long long x, unsigned lo
// CHECK-NEXT: [[OVERFLOW_PRE_TRUNC:%.*]] = or i1 {{.*}}, [[UNDERFLOW]]
// CHECK-NEXT: [[TRUNC_OVERFLOW:%.*]] = icmp ugt i64 [[UNSIGNED_RESULT]], 4294967295
// CHECK-NEXT: [[OVERFLOW:%.*]] = or i1 [[OVERFLOW_PRE_TRUNC]], [[TRUNC_OVERFLOW]]
-// CHECK-NEXT: trunc i64 [[UNSIGNED_RESULT]] to i32
+// CHECK-NEXT: [[NEGATED:%.*]] = sub i64 0, [[UNSIGNED_RESULT]]
+// CHECK-NEXT: [[RESULT:%.*]] = select i1 {{.*}}, i64 [[NEGATED]], i64 [[UNSIGNED_RESULT]]
+// CHECK-NEXT: trunc i64 [[RESULT]] to i32
// CHECK-NEXT: store
unsigned result;
if (__builtin_mul_overflow(y, x, &result))
diff --git a/test/CodeGen/builtins-ppc-p9-f128.c b/test/CodeGen/builtins-ppc-p9-f128.c
new file mode 100644
index 000000000000..c43915ad2489
--- /dev/null
+++ b/test/CodeGen/builtins-ppc-p9-f128.c
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu -emit-llvm \
+// RUN: -target-cpu pwr9 -target-feature +float128 -o - %s | FileCheck %s
+
+__float128 A;
+__float128 B;
+__float128 C;
+
+
+__float128 testSqrtOdd() {
+ return __builtin_sqrtf128_round_to_odd(A);
+// CHECK: @llvm.ppc.sqrtf128.round.to.odd(fp128
+// CHECK-NEXT: ret fp128
+}
+
+__float128 testFMAOdd() {
+ return __builtin_fmaf128_round_to_odd(A, B, C);
+// CHECK: @llvm.ppc.fmaf128.round.to.odd(fp128 %{{.+}}, fp128 %{{.+}}, fp128
+// CHECK-NEXT: ret fp128
+}
+
+__float128 testAddOdd() {
+ return __builtin_addf128_round_to_odd(A, B);
+// CHECK: @llvm.ppc.addf128.round.to.odd(fp128 %{{.+}}, fp128
+// CHECK-NEXT: ret fp128
+}
+
+__float128 testSubOdd() {
+ return __builtin_subf128_round_to_odd(A, B);
+// CHECK: @llvm.ppc.subf128.round.to.odd(fp128 %{{.+}}, fp128
+// CHECK-NEXT: ret fp128
+}
+
+__float128 testMulOdd() {
+ return __builtin_mulf128_round_to_odd(A, B);
+// CHECK: @llvm.ppc.mulf128.round.to.odd(fp128 %{{.+}}, fp128
+// CHECK-NEXT: ret fp128
+}
+
+__float128 testDivOdd() {
+ return __builtin_divf128_round_to_odd(A, B);
+// CHECK: @llvm.ppc.divf128.round.to.odd(fp128 %{{.+}}, fp128
+// CHECK-NEXT: ret fp128
+}
+
+double testTruncOdd() {
+ return __builtin_truncf128_round_to_odd(A);
+// CHECK: @llvm.ppc.truncf128.round.to.odd(fp128
+// CHECK-NEXT: ret double
+}
+
diff --git a/test/CodeGen/builtins-ppc-p9vector.c b/test/CodeGen/builtins-ppc-p9vector.c
index f92df86561ad..bfbb81585471 100644
--- a/test/CodeGen/builtins-ppc-p9vector.c
+++ b/test/CodeGen/builtins-ppc-p9vector.c
@@ -983,7 +983,7 @@ vector bool int test86(void) {
}
vector bool long long test87(void) {
// CHECK-BE: @llvm.ppc.vsx.xvtstdcdp(<2 x double> {{.+}}, i32 127)
-// CHECK-BE_NEXT: ret <2 x i64
+// CHECK-BE-NEXT: ret <2 x i64>
// CHECK: @llvm.ppc.vsx.xvtstdcdp(<2 x double> {{.+}}, i32 127)
// CHECK-NEXT: ret <2 x i64>
return vec_test_data_class(vda, __VEC_CLASS_FP_NOT_NORMAL);
diff --git a/test/CodeGen/builtins-ppc-vsx.c b/test/CodeGen/builtins-ppc-vsx.c
index 6dda19d5d9f3..848d24d4fb10 100644
--- a/test/CodeGen/builtins-ppc-vsx.c
+++ b/test/CodeGen/builtins-ppc-vsx.c
@@ -1694,43 +1694,43 @@ vec_xst_be(vd, sll, ad);
res_vd = vec_xxpermdi(vd, vd, 0);
// CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 0, i32 2>
-// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 3, i32 1>
+// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 0, i32 2>
res_vf = vec_xxpermdi(vf, vf, 1);
// CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 0, i32 3>
-// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 2, i32 1>
+// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 0, i32 3>
res_vsll = vec_xxpermdi(vsll, vsll, 2);
// CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 1, i32 2>
-// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 3, i32 0>
+// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 1, i32 2>
res_vull = vec_xxpermdi(vull, vull, 3);
// CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 1, i32 3>
-// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 2, i32 0>
+// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 1, i32 3>
res_vsi = vec_xxpermdi(vsi, vsi, 0);
// CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 0, i32 2>
-// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 3, i32 1>
+// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 0, i32 2>
res_vui = vec_xxpermdi(vui, vui, 1);
// CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 0, i32 3>
-// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 2, i32 1>
+// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 0, i32 3>
res_vss = vec_xxpermdi(vss, vss, 2);
// CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 1, i32 2>
-// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 3, i32 0>
+// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 1, i32 2>
res_vus = vec_xxpermdi(vus, vus, 3);
// CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 1, i32 3>
-// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 2, i32 0>
+// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 1, i32 3>
res_vsc = vec_xxpermdi(vsc, vsc, 0);
// CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 0, i32 2>
-// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 3, i32 1>
+// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 0, i32 2>
res_vuc = vec_xxpermdi(vuc, vuc, 1);
// CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 0, i32 3>
-// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 2, i32 1>
+// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 0, i32 3>
res_vd = vec_xxsldwi(vd, vd, 0);
// CHECK: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
@@ -1786,7 +1786,7 @@ vector int xxpermdi_should_not_assert(vector int a, vector int b) {
// CHECK-LE: bitcast <4 x i32> %{{[0-9]+}} to <2 x i64>
// CHECK-LE-NEXT: bitcast <4 x i32> %{{[0-9]+}} to <2 x i64>
-// CHECK-LE-NEXT: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 3, i32 1>
+// CHECK-LE-NEXT: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 0, i32 2>
// CHECK-LE-NEXT: bitcast <2 x i64> %{{[0-9]+}} to <4 x i32>
}
diff --git a/test/CodeGen/builtins-systemz-vector-error.c b/test/CodeGen/builtins-systemz-vector-error.c
index 6f4ecc2acad3..f0db90108279 100644
--- a/test/CodeGen/builtins-systemz-vector-error.c
+++ b/test/CodeGen/builtins-systemz-vector-error.c
@@ -27,148 +27,148 @@ const void * volatile cptr;
int cc;
void test_core(void) {
- __builtin_s390_lcbb(cptr, -1); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_lcbb(cptr, 16); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_lcbb(cptr, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_lcbb(cptr, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_lcbb(cptr, len); // expected-error {{must be a constant integer}}
- __builtin_s390_vlbb(cptr, -1); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vlbb(cptr, 16); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vlbb(cptr, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vlbb(cptr, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vlbb(cptr, len); // expected-error {{must be a constant integer}}
- __builtin_s390_vpdi(vul, vul, -1); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vpdi(vul, vul, 16); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vpdi(vul, vul, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vpdi(vul, vul, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vpdi(vul, vul, len); // expected-error {{must be a constant integer}}
}
void test_integer(void) {
- __builtin_s390_verimb(vuc, vuc, vuc, -1); // expected-error {{argument should be a value from 0 to 255}}
- __builtin_s390_verimb(vuc, vuc, vuc, 256); // expected-error {{argument should be a value from 0 to 255}}
+ __builtin_s390_verimb(vuc, vuc, vuc, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_verimb(vuc, vuc, vuc, 256); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_verimb(vuc, vuc, vuc, len); // expected-error {{must be a constant integer}}
- __builtin_s390_verimh(vus, vus, vus, -1); // expected-error {{argument should be a value from 0 to 255}}
- __builtin_s390_verimh(vus, vus, vus, 256); // expected-error {{argument should be a value from 0 to 255}}
+ __builtin_s390_verimh(vus, vus, vus, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_verimh(vus, vus, vus, 256); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_verimh(vus, vus, vus, len); // expected-error {{must be a constant integer}}
- __builtin_s390_verimf(vui, vui, vui, -1); // expected-error {{argument should be a value from 0 to 255}}
- __builtin_s390_verimf(vui, vui, vui, 256); // expected-error {{argument should be a value from 0 to 255}}
+ __builtin_s390_verimf(vui, vui, vui, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_verimf(vui, vui, vui, 256); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_verimf(vui, vui, vui, len); // expected-error {{must be a constant integer}}
- __builtin_s390_verimg(vul, vul, vul, -1); // expected-error {{argument should be a value from 0 to 255}}
- __builtin_s390_verimg(vul, vul, vul, 256); // expected-error {{argument should be a value from 0 to 255}}
+ __builtin_s390_verimg(vul, vul, vul, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_verimg(vul, vul, vul, 256); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_verimg(vul, vul, vul, len); // expected-error {{must be a constant integer}}
- __builtin_s390_vsldb(vuc, vuc, -1); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vsldb(vuc, vuc, 16); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vsldb(vuc, vuc, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vsldb(vuc, vuc, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vsldb(vuc, vuc, len); // expected-error {{must be a constant integer}}
}
void test_string(void) {
- __builtin_s390_vfaeb(vuc, vuc, -1); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vfaeb(vuc, vuc, 16); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vfaeb(vuc, vuc, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vfaeb(vuc, vuc, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vfaeb(vuc, vuc, len); // expected-error {{must be a constant integer}}
- __builtin_s390_vfaeh(vus, vus, -1); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vfaeh(vus, vus, 16); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vfaeh(vus, vus, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vfaeh(vus, vus, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vfaeh(vus, vus, len); // expected-error {{must be a constant integer}}
- __builtin_s390_vfaef(vui, vui, -1); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vfaef(vui, vui, 16); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vfaef(vui, vui, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vfaef(vui, vui, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vfaef(vui, vui, len); // expected-error {{must be a constant integer}}
- __builtin_s390_vfaezb(vuc, vuc, -1); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vfaezb(vuc, vuc, 16); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vfaezb(vuc, vuc, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vfaezb(vuc, vuc, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vfaezb(vuc, vuc, len); // expected-error {{must be a constant integer}}
- __builtin_s390_vfaezh(vus, vus, -1); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vfaezh(vus, vus, 16); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vfaezh(vus, vus, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vfaezh(vus, vus, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vfaezh(vus, vus, len); // expected-error {{must be a constant integer}}
- __builtin_s390_vfaezf(vui, vui, -1); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vfaezf(vui, vui, 16); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vfaezf(vui, vui, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vfaezf(vui, vui, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vfaezf(vui, vui, len); // expected-error {{must be a constant integer}}
- __builtin_s390_vstrcb(vuc, vuc, vuc, -1); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vstrcb(vuc, vuc, vuc, 16); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vstrcb(vuc, vuc, vuc, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vstrcb(vuc, vuc, vuc, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vstrcb(vuc, vuc, vuc, len); // expected-error {{must be a constant integer}}
- __builtin_s390_vstrch(vus, vus, vus, -1); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vstrch(vus, vus, vus, 16); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vstrch(vus, vus, vus, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vstrch(vus, vus, vus, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vstrch(vus, vus, vus, len); // expected-error {{must be a constant integer}}
- __builtin_s390_vstrcf(vui, vui, vui, -1); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vstrcf(vui, vui, vui, 16); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vstrcf(vui, vui, vui, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vstrcf(vui, vui, vui, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vstrcf(vui, vui, vui, len); // expected-error {{must be a constant integer}}
- __builtin_s390_vstrczb(vuc, vuc, vuc, -1); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vstrczb(vuc, vuc, vuc, 16); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vstrczb(vuc, vuc, vuc, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vstrczb(vuc, vuc, vuc, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vstrczb(vuc, vuc, vuc, len); // expected-error {{must be a constant integer}}
- __builtin_s390_vstrczh(vus, vus, vus, -1); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vstrczh(vus, vus, vus, 16); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vstrczh(vus, vus, vus, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vstrczh(vus, vus, vus, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vstrczh(vus, vus, vus, len); // expected-error {{must be a constant integer}}
- __builtin_s390_vstrczf(vui, vui, vui, -1); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vstrczf(vui, vui, vui, 16); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vstrczf(vui, vui, vui, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vstrczf(vui, vui, vui, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vstrczf(vui, vui, vui, len); // expected-error {{must be a constant integer}}
- __builtin_s390_vfaebs(vuc, vuc, -1, &cc); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vfaebs(vuc, vuc, 16, &cc); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vfaebs(vuc, vuc, -1, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vfaebs(vuc, vuc, 16, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vfaebs(vuc, vuc, len, &cc); // expected-error {{must be a constant integer}}
- __builtin_s390_vfaehs(vus, vus, -1, &cc); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vfaehs(vus, vus, 16, &cc); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vfaehs(vus, vus, -1, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vfaehs(vus, vus, 16, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vfaehs(vus, vus, len, &cc); // expected-error {{must be a constant integer}}
- __builtin_s390_vfaefs(vui, vui, -1, &cc); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vfaefs(vui, vui, 16, &cc); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vfaefs(vui, vui, -1, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vfaefs(vui, vui, 16, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vfaefs(vui, vui, len, &cc); // expected-error {{must be a constant integer}}
- __builtin_s390_vfaezbs(vuc, vuc, -1, &cc); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vfaezbs(vuc, vuc, 16, &cc); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vfaezbs(vuc, vuc, -1, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vfaezbs(vuc, vuc, 16, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vfaezbs(vuc, vuc, len, &cc); // expected-error {{must be a constant integer}}
- __builtin_s390_vfaezhs(vus, vus, -1, &cc); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vfaezhs(vus, vus, 16, &cc); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vfaezhs(vus, vus, -1, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vfaezhs(vus, vus, 16, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vfaezhs(vus, vus, len, &cc); // expected-error {{must be a constant integer}}
- __builtin_s390_vfaezfs(vui, vui, -1, &cc); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vfaezfs(vui, vui, 16, &cc); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vfaezfs(vui, vui, -1, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vfaezfs(vui, vui, 16, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vfaezfs(vui, vui, len, &cc); // expected-error {{must be a constant integer}}
- __builtin_s390_vstrcbs(vuc, vuc, vuc, -1, &cc); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vstrcbs(vuc, vuc, vuc, 16, &cc); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vstrcbs(vuc, vuc, vuc, -1, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vstrcbs(vuc, vuc, vuc, 16, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vstrcbs(vuc, vuc, vuc, len, &cc); // expected-error {{must be a constant integer}}
- __builtin_s390_vstrchs(vus, vus, vus, -1, &cc); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vstrchs(vus, vus, vus, 16, &cc); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vstrchs(vus, vus, vus, -1, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vstrchs(vus, vus, vus, 16, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vstrchs(vus, vus, vus, len, &cc); // expected-error {{must be a constant integer}}
- __builtin_s390_vstrcfs(vui, vui, vui, -1, &cc); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vstrcfs(vui, vui, vui, 16, &cc); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vstrcfs(vui, vui, vui, -1, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vstrcfs(vui, vui, vui, 16, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vstrcfs(vui, vui, vui, len, &cc); // expected-error {{must be a constant integer}}
- __builtin_s390_vstrczbs(vuc, vuc, vuc, -1, &cc); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vstrczbs(vuc, vuc, vuc, 16, &cc); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vstrczbs(vuc, vuc, vuc, -1, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vstrczbs(vuc, vuc, vuc, 16, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vstrczbs(vuc, vuc, vuc, len, &cc); // expected-error {{must be a constant integer}}
- __builtin_s390_vstrczhs(vus, vus, vus, -1, &cc); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vstrczhs(vus, vus, vus, 16, &cc); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vstrczhs(vus, vus, vus, -1, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vstrczhs(vus, vus, vus, 16, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vstrczhs(vus, vus, vus, len, &cc); // expected-error {{must be a constant integer}}
- __builtin_s390_vstrczfs(vui, vui, vui, -1, &cc); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vstrczfs(vui, vui, vui, 16, &cc); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vstrczfs(vui, vui, vui, -1, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vstrczfs(vui, vui, vui, 16, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vstrczfs(vui, vui, vui, len, &cc); // expected-error {{must be a constant integer}}
}
void test_float(void) {
- __builtin_s390_vftcidb(vd, -1, &cc); // expected-error {{argument should be a value from 0 to 4095}}
- __builtin_s390_vftcidb(vd, 4096, &cc); // expected-error {{argument should be a value from 0 to 4095}}
+ __builtin_s390_vftcidb(vd, -1, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vftcidb(vd, 4096, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vftcidb(vd, len, &cc); // expected-error {{must be a constant integer}}
- __builtin_s390_vfidb(vd, -1, 0); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vfidb(vd, 16, 0); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vfidb(vd, -1, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vfidb(vd, 16, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vfidb(vd, len, 0); // expected-error {{must be a constant integer}}
- __builtin_s390_vfidb(vd, 0, -1); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vfidb(vd, 0, 16); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vfidb(vd, 0, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vfidb(vd, 0, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vfidb(vd, 0, len); // expected-error {{must be a constant integer}}
}
diff --git a/test/CodeGen/builtins-systemz-vector2-error.c b/test/CodeGen/builtins-systemz-vector2-error.c
index ceebaf8cc72f..cd27ac79e15d 100644
--- a/test/CodeGen/builtins-systemz-vector2-error.c
+++ b/test/CodeGen/builtins-systemz-vector2-error.c
@@ -28,34 +28,34 @@ volatile unsigned int len;
int cc;
void test_integer(void) {
- __builtin_s390_vmslg(vul, vul, vuc, -1); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vmslg(vul, vul, vuc, 16); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vmslg(vul, vul, vuc, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vmslg(vul, vul, vuc, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vmslg(vul, vul, vuc, len); // expected-error {{must be a constant integer}}
}
void test_float(void) {
- __builtin_s390_vfmaxdb(vd, vd, -1); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vfmaxdb(vd, vd, 16); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vfmaxdb(vd, vd, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vfmaxdb(vd, vd, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vfmaxdb(vd, vd, len); // expected-error {{must be a constant integer}}
- __builtin_s390_vfmindb(vd, vd, -1); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vfmindb(vd, vd, 16); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vfmindb(vd, vd, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vfmindb(vd, vd, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vfmindb(vd, vd, len); // expected-error {{must be a constant integer}}
- __builtin_s390_vftcisb(vf, -1, &cc); // expected-error {{argument should be a value from 0 to 4095}}
- __builtin_s390_vftcisb(vf, 4096, &cc); // expected-error {{argument should be a value from 0 to 4095}}
+ __builtin_s390_vftcisb(vf, -1, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vftcisb(vf, 4096, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vftcisb(vf, len, &cc); // expected-error {{must be a constant integer}}
- __builtin_s390_vfisb(vf, -1, 0); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vfisb(vf, 16, 0); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vfisb(vf, -1, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vfisb(vf, 16, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vfisb(vf, len, 0); // expected-error {{must be a constant integer}}
- __builtin_s390_vfisb(vf, 0, -1); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vfisb(vf, 0, 16); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vfisb(vf, 0, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vfisb(vf, 0, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vfisb(vf, 0, len); // expected-error {{must be a constant integer}}
- __builtin_s390_vfmaxsb(vf, vf, -1); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vfmaxsb(vf, vf, 16); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vfmaxsb(vf, vf, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vfmaxsb(vf, vf, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vfmaxsb(vf, vf, len); // expected-error {{must be a constant integer}}
- __builtin_s390_vfminsb(vf, vf, -1); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_s390_vfminsb(vf, vf, 16); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_s390_vfminsb(vf, vf, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_s390_vfminsb(vf, vf, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
__builtin_s390_vfminsb(vf, vf, len); // expected-error {{must be a constant integer}}
}
diff --git a/test/CodeGen/builtins-systemz-zvector-error.c b/test/CodeGen/builtins-systemz-zvector-error.c
index 8d5aaabfbac3..cb60ea495ece 100644
--- a/test/CodeGen/builtins-systemz-zvector-error.c
+++ b/test/CodeGen/builtins-systemz-zvector-error.c
@@ -560,6 +560,6 @@ void test_float(void) {
// expected-note@vecintrin.h:* 1 {{must be a constant integer from 0 to 31}}
vbl = vec_fp_test_data_class(vd, idx, &cc); // expected-error {{must be a constant integer}}
- vbl = vec_fp_test_data_class(vd, -1, &cc); // expected-error {{should be a value from 0 to 4095}}
- vbl = vec_fp_test_data_class(vd, 4096, &cc); // expected-error {{should be a value from 0 to 4095}}
+ vbl = vec_fp_test_data_class(vd, -1, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vbl = vec_fp_test_data_class(vd, 4096, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}}
}
diff --git a/test/CodeGen/builtins-systemz-zvector2-error.c b/test/CodeGen/builtins-systemz-zvector2-error.c
index 823d6374dc0e..3b890b9d09af 100644
--- a/test/CodeGen/builtins-systemz-zvector2-error.c
+++ b/test/CodeGen/builtins-systemz-zvector2-error.c
@@ -127,8 +127,8 @@ void test_integer(void) {
// expected-note@vecintrin.h:* 1 {{must be a constant integer from 0 to 15}}
vuc = vec_msum_u128(vul, vul, vuc, idx); // expected-error {{must be a constant integer}}
- vuc = vec_msum_u128(vul, vul, vuc, -1); // expected-error {{should be a value from 0 to 15}}
- vuc = vec_msum_u128(vul, vul, vuc, 16); // expected-error {{should be a value from 0 to 15}}
+ vuc = vec_msum_u128(vul, vul, vuc, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vuc = vec_msum_u128(vul, vul, vuc, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
}
void test_float(void) {
diff --git a/test/CodeGen/builtins-wasm.c b/test/CodeGen/builtins-wasm.c
index e0f72d2e5034..1b647b56d1a2 100644
--- a/test/CodeGen/builtins-wasm.c
+++ b/test/CodeGen/builtins-wasm.c
@@ -3,25 +3,49 @@
// RUN: %clang_cc1 -triple wasm64-unknown-unknown -O3 -emit-llvm -o - %s \
// RUN: | FileCheck %s -check-prefix=WEBASSEMBLY64
-__SIZE_TYPE__ f1(void) {
+__SIZE_TYPE__ f0(void) {
+ return __builtin_wasm_memory_size(0);
+// WEBASSEMBLY32: call {{i.*}} @llvm.wasm.memory.size.i32(i32 0)
+// WEBASSEMBLY64: call {{i.*}} @llvm.wasm.memory.size.i64(i32 0)
+}
+
+__SIZE_TYPE__ f1(__SIZE_TYPE__ delta) {
+ return __builtin_wasm_memory_grow(0, delta);
+// WEBASSEMBLY32: call i32 @llvm.wasm.memory.grow.i32(i32 0, i32 %{{.*}})
+// WEBASSEMBLY64: call i64 @llvm.wasm.memory.grow.i64(i32 0, i64 %{{.*}})
+}
+
+__SIZE_TYPE__ f2(void) {
+ return __builtin_wasm_mem_size(0);
+// WEBASSEMBLY32: call {{i.*}} @llvm.wasm.mem.size.i32(i32 0)
+// WEBASSEMBLY64: call {{i.*}} @llvm.wasm.mem.size.i64(i32 0)
+}
+
+__SIZE_TYPE__ f3(__SIZE_TYPE__ delta) {
+ return __builtin_wasm_mem_grow(0, delta);
+// WEBASSEMBLY32: call i32 @llvm.wasm.mem.grow.i32(i32 0, i32 %{{.*}})
+// WEBASSEMBLY64: call i64 @llvm.wasm.mem.grow.i64(i32 0, i64 %{{.*}})
+}
+
+__SIZE_TYPE__ f4(void) {
return __builtin_wasm_current_memory();
// WEBASSEMBLY32: call {{i.*}} @llvm.wasm.current.memory.i32()
// WEBASSEMBLY64: call {{i.*}} @llvm.wasm.current.memory.i64()
}
-__SIZE_TYPE__ f2(__SIZE_TYPE__ delta) {
+__SIZE_TYPE__ f5(__SIZE_TYPE__ delta) {
return __builtin_wasm_grow_memory(delta);
// WEBASSEMBLY32: call i32 @llvm.wasm.grow.memory.i32(i32 %{{.*}})
// WEBASSEMBLY64: call i64 @llvm.wasm.grow.memory.i64(i64 %{{.*}})
}
-void f3(unsigned int tag, void *obj) {
+void f6(unsigned int tag, void *obj) {
return __builtin_wasm_throw(tag, obj);
// WEBASSEMBLY32: call void @llvm.wasm.throw(i32 %{{.*}}, i8* %{{.*}})
// WEBASSEMBLY64: call void @llvm.wasm.throw(i32 %{{.*}}, i8* %{{.*}})
}
-void f4() {
+void f7(void) {
return __builtin_wasm_rethrow();
// WEBASSEMBLY32: call void @llvm.wasm.rethrow()
// WEBASSEMBLY64: call void @llvm.wasm.rethrow()
diff --git a/test/CodeGen/builtins-x86.c b/test/CodeGen/builtins-x86.c
index fc3cc448cf3c..fd99dd2be31f 100644
--- a/test/CodeGen/builtins-x86.c
+++ b/test/CodeGen/builtins-x86.c
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -DUSE_64 -triple x86_64-unknown-unknown -target-feature +fxsr -target-feature +avx -target-feature +xsaveopt -target-feature +xsaves -target-feature +xsavec -target-feature +mwaitx -target-feature +clzero -target-feature +ibt -target-feature +shstk -emit-llvm -o %t %s
-// RUN: %clang_cc1 -DUSE_ALL -triple x86_64-unknown-unknown -target-feature +fxsr -target-feature +avx -target-feature +xsaveopt -target-feature +xsaves -target-feature +xsavec -target-feature +mwaitx -target-feature +ibt -target-feature +shstk -target-feature +clzero -fsyntax-only -o %t %s
+// RUN: %clang_cc1 -DUSE_64 -triple x86_64-unknown-unknown -target-feature +fxsr -target-feature +avx -target-feature +xsaveopt -target-feature +xsaves -target-feature +xsavec -target-feature +mwaitx -target-feature +clzero -target-feature +shstk -target-feature +wbnoinvd -target-feature +cldemote -emit-llvm -o %t %s
+// RUN: %clang_cc1 -DUSE_ALL -triple x86_64-unknown-unknown -target-feature +fxsr -target-feature +avx -target-feature +xsaveopt -target-feature +xsaves -target-feature +xsavec -target-feature +mwaitx -target-feature +shstk -target-feature +clzero -target-feature +wbnoinvd -target-feature +cldemote -fsyntax-only -o %t %s
#ifdef USE_ALL
#define USE_3DNOW
@@ -295,6 +295,7 @@ void f0() {
(void) __builtin_ia32_monitorx(tmp_vp, tmp_Ui, tmp_Ui);
(void) __builtin_ia32_mwaitx(tmp_Ui, tmp_Ui, tmp_Ui);
(void) __builtin_ia32_clzero(tmp_vp);
+ (void) __builtin_ia32_cldemote(tmp_vp);
tmp_V4f = __builtin_ia32_cvtpi2ps(tmp_V4f, tmp_V2i);
tmp_V2i = __builtin_ia32_cvtps2pi(tmp_V4f);
@@ -305,6 +306,7 @@ void f0() {
tmp_i = __rdtsc();
tmp_i = __builtin_ia32_rdtscp(&tmp_Ui);
tmp_LLi = __builtin_ia32_rdpmc(tmp_i);
+ __builtin_ia32_wbnoinvd();
#ifdef USE_64
tmp_LLi = __builtin_ia32_cvtss2si64(tmp_V4f);
tmp_LLi = __builtin_ia32_cvttss2si64(tmp_V4f);
@@ -336,7 +338,6 @@ void f0() {
tmp_V2LLi = __builtin_ia32_psadbw128(tmp_V16c, tmp_V16c);
tmp_V2d = __builtin_ia32_sqrtpd(tmp_V2d);
tmp_V2d = __builtin_ia32_sqrtsd(tmp_V2d);
- tmp_V4f = __builtin_ia32_cvtdq2ps(tmp_V4i);
tmp_V2LLi = __builtin_ia32_cvtpd2dq(tmp_V2d);
tmp_V2i = __builtin_ia32_cvtpd2pi(tmp_V2d);
tmp_V4f = __builtin_ia32_cvtpd2ps(tmp_V2d);
@@ -432,7 +433,6 @@ void f0() {
tmp_V8f = __builtin_ia32_dpps256(tmp_V8f, tmp_V8f, 0x7);
tmp_V4d = __builtin_ia32_cmppd256(tmp_V4d, tmp_V4d, 0);
tmp_V8f = __builtin_ia32_cmpps256(tmp_V8f, tmp_V8f, 0);
- tmp_V8f = __builtin_ia32_cvtdq2ps256(tmp_V8i);
tmp_V4f = __builtin_ia32_cvtpd2ps256(tmp_V4d);
tmp_V8i = __builtin_ia32_cvtps2dq256(tmp_V8f);
tmp_V4i = __builtin_ia32_cvttpd2dq256(tmp_V4d);
@@ -466,8 +466,6 @@ void f0() {
tmp_i = __builtin_ia32_movmskps256(tmp_V8f);
__builtin_ia32_vzeroall();
__builtin_ia32_vzeroupper();
- tmp_V4d = __builtin_ia32_vbroadcastf128_pd256(tmp_V2dCp);
- tmp_V8f = __builtin_ia32_vbroadcastf128_ps256(tmp_V4fCp);
tmp_V32c = __builtin_ia32_lddqu256(tmp_cCp);
tmp_V2d = __builtin_ia32_maskloadpd(tmp_V2dCp, tmp_V2LLi);
tmp_V4f = __builtin_ia32_maskloadps(tmp_V4fCp, tmp_V4i);
diff --git a/test/CodeGen/builtins.c b/test/CodeGen/builtins.c
index 4f84db00cbd7..77b479e4c112 100644
--- a/test/CodeGen/builtins.c
+++ b/test/CodeGen/builtins.c
@@ -422,6 +422,28 @@ void test_builtin_os_log(void *buf, int i, const char *data) {
// CHECK: %[[V6:.*]] = ptrtoint i8* %[[V5]] to i64
// CHECK: call void @__os_log_helper_1_3_4_4_0_8_34_4_17_8_49(i8* %[[V1]], i32 %[[V2]], i64 %[[V4]], i32 16, i64 %[[V6]])
__builtin_os_log_format(buf, "%d %{public}s %{private}.16P", i, data, data);
+
+ // privacy annotations aren't recognized when they are preceded or followed
+ // by non-whitespace characters.
+
+ // CHECK: call void @__os_log_helper_1_2_1_8_32(
+ __builtin_os_log_format(buf, "%{xyz public}s", data);
+
+ // CHECK: call void @__os_log_helper_1_2_1_8_32(
+ __builtin_os_log_format(buf, "%{ public xyz}s", data);
+
+ // CHECK: call void @__os_log_helper_1_2_1_8_32(
+ __builtin_os_log_format(buf, "%{ public1}s", data);
+
+ // Privacy annotations do not have to be in the first comma-delimited string.
+
+ // CHECK: call void @__os_log_helper_1_2_1_8_34(
+ __builtin_os_log_format(buf, "%{ xyz, public }s", "abc");
+
+ // The last privacy annotation in the string wins.
+
+ // CHECK: call void @__os_log_helper_1_3_1_8_33(
+ __builtin_os_log_format(buf, "%{ private, public, private, public}s", "abc");
}
// CHECK-LABEL: define linkonce_odr hidden void @__os_log_helper_1_3_4_4_0_8_34_4_17_8_49
diff --git a/test/CodeGen/c-strings.c b/test/CodeGen/c-strings.c
index 4e14d988a5dc..a94cd8920e06 100644
--- a/test/CodeGen/c-strings.c
+++ b/test/CodeGen/c-strings.c
@@ -4,16 +4,16 @@
// Should be 3 hello strings, two global (of different sizes), the rest are
// shared.
-// CHECK: @align = global i8 [[ALIGN:[0-9]+]]
+// CHECK: @align = {{(dso_local )?}}global i8 [[ALIGN:[0-9]+]]
// ITANIUM: @.str = private unnamed_addr constant [6 x i8] c"hello\00"
-// MSABI: @"\01??_C@_05CJBACGMB@hello?$AA@" = linkonce_odr unnamed_addr constant [6 x i8] c"hello\00", comdat, align 1
+// MSABI: @"??_C@_05CJBACGMB@hello?$AA@" = linkonce_odr dso_local unnamed_addr constant [6 x i8] c"hello\00", comdat, align 1
// ITANIUM: @f1.x = internal global i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str, i32 0, i32 0)
-// MSABI: @f1.x = internal global i8* getelementptr inbounds ([6 x i8], [6 x i8]* @"\01??_C@_05CJBACGMB@hello?$AA@", i32 0, i32 0)
+// MSABI: @f1.x = internal global i8* getelementptr inbounds ([6 x i8], [6 x i8]* @"??_C@_05CJBACGMB@hello?$AA@", i32 0, i32 0)
// CHECK: @f2.x = internal global [6 x i8] c"hello\00", align [[ALIGN]]
// CHECK: @f3.x = internal global [8 x i8] c"hello\00\00\00", align [[ALIGN]]
// ITANIUM: @f4.x = internal global %struct.s { i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str, i32 0, i32 0) }
-// MSABI: @f4.x = internal global %struct.s { i8* getelementptr inbounds ([6 x i8], [6 x i8]* @"\01??_C@_05CJBACGMB@hello?$AA@", i32 0, i32 0) }
-// CHECK: @x = global [3 x i8] c"ola", align [[ALIGN]]
+// MSABI: @f4.x = internal global %struct.s { i8* getelementptr inbounds ([6 x i8], [6 x i8]* @"??_C@_05CJBACGMB@hello?$AA@", i32 0, i32 0) }
+// CHECK: @x = {{(dso_local )?}}global [3 x i8] c"ola", align [[ALIGN]]
// XFAIL: hexagon
// Hexagon aligns arrays of size 8+ bytes to a 64-bit boundary, which
@@ -32,7 +32,7 @@ void bar(const char *);
void f0() {
bar("hello");
// ITANIUM: call {{.*}}void @bar({{.*}} @.str
- // MSABI: call {{.*}}void @bar({{.*}} @"\01??_C@_05CJBACGMB@hello?$AA@"
+ // MSABI: call {{.*}}void @bar({{.*}} @"??_C@_05CJBACGMB@hello?$AA@"
}
// CHECK-LABEL: define {{.*}}void @f1()
diff --git a/test/CodeGen/c11atomics-ios.c b/test/CodeGen/c11atomics-ios.c
index fb731dfd7a1f..f48e10e4aa43 100644
--- a/test/CodeGen/c11atomics-ios.c
+++ b/test/CodeGen/c11atomics-ios.c
@@ -132,7 +132,7 @@ void testStruct(_Atomic(S) *fp) {
// CHECK-NEXT: [[T0:%.*]] = load [[S]]*, [[S]]** [[FP]]
// CHECK-NEXT: [[T1:%.*]] = bitcast [[S]]* [[TMP0]] to i8*
// CHECK-NEXT: [[T2:%.*]] = bitcast [[S]]* [[F]] to i8*
-// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[T1]], i8* [[T2]], i32 8, i32 2, i1 false)
+// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[T1]], i8* align 2 [[T2]], i32 8, i1 false)
// CHECK-NEXT: [[T3:%.*]] = bitcast [[S]]* [[TMP0]] to i64*
// CHECK-NEXT: [[T4:%.*]] = load i64, i64* [[T3]], align 8
// CHECK-NEXT: [[T5:%.*]] = bitcast [[S]]* [[T0]] to i64*
@@ -154,7 +154,7 @@ void testPromotedStruct(_Atomic(PS) *fp) {
// CHECK-NEXT: [[P:%.*]] = load [[APS]]*, [[APS]]** [[FP]]
// CHECK-NEXT: [[T0:%.*]] = bitcast [[APS]]* [[P]] to i8*
-// CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 8, i32 8, i1 false)
+// CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 8 [[T0]], i8 0, i64 8, i1 false)
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[APS]], [[APS]]* [[P]], i32 0, i32 0
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[PS]], [[PS]]* [[T0]], i32 0, i32 0
// CHECK-NEXT: store i16 1, i16* [[T1]], align 8
@@ -165,7 +165,7 @@ void testPromotedStruct(_Atomic(PS) *fp) {
__c11_atomic_init(fp, (PS){1,2,3});
// CHECK-NEXT: [[T0:%.*]] = bitcast [[APS]]* [[X]] to i8*
-// CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* [[T0]], i8 0, i32 8, i32 8, i1 false)
+// CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* align 8 [[T0]], i8 0, i32 8, i1 false)
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[APS]], [[APS]]* [[X]], i32 0, i32 0
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[PS]], [[PS]]* [[T0]], i32 0, i32 0
// CHECK-NEXT: store i16 1, i16* [[T1]], align 8
@@ -183,16 +183,16 @@ void testPromotedStruct(_Atomic(PS) *fp) {
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[APS]], [[APS]]* [[TMP0]], i32 0, i32 0
// CHECK-NEXT: [[T1:%.*]] = bitcast [[PS]]* [[F]] to i8*
// CHECK-NEXT: [[T2:%.*]] = bitcast [[PS]]* [[T0]] to i8*
-// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[T1]], i8* [[T2]], i32 6, i32 2, i1 false)
+// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 2 [[T1]], i8* align 8 [[T2]], i32 6, i1 false)
PS f = *fp;
// CHECK-NEXT: [[T0:%.*]] = load [[APS]]*, [[APS]]** [[FP]]
// CHECK-NEXT: [[T1:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[TMP1]] to i8*
-// CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* [[T1]], i8 0, i32 8, i32 8, i1 false)
+// CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* align 8 [[T1]], i8 0, i32 8, i1 false)
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[APS]], [[APS]]* [[TMP1]], i32 0, i32 0
// CHECK-NEXT: [[T2:%.*]] = bitcast [[PS]]* [[T1]] to i8*
// CHECK-NEXT: [[T3:%.*]] = bitcast [[PS]]* [[F]] to i8*
-// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[T2]], i8* [[T3]], i32 6, i32 2, i1 false)
+// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[T2]], i8* align 2 [[T3]], i32 6, i1 false)
// CHECK-NEXT: [[T4:%.*]] = bitcast [[APS]]* [[TMP1]] to i64*
// CHECK-NEXT: [[T5:%.*]] = load i64, i64* [[T4]], align 8
// CHECK-NEXT: [[T6:%.*]] = bitcast [[APS]]* [[T0]] to i64*
@@ -215,7 +215,7 @@ PS test_promoted_load(_Atomic(PS) *addr) {
// CHECK: [[ATOMIC_RES_STRUCT:%.*]] = bitcast i64* [[ATOMIC_RES64]] to %struct.PS*
// CHECK: [[AGG_RESULT8:%.*]] = bitcast %struct.PS* %agg.result to i8*
// CHECK: [[ATOMIC_RES8:%.*]] = bitcast %struct.PS* [[ATOMIC_RES_STRUCT]] to i8*
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[AGG_RESULT8]], i8* [[ATOMIC_RES8]], i32 6, i32 2, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 2 [[AGG_RESULT8]], i8* align 8 [[ATOMIC_RES8]], i32 6, i1 false)
return __c11_atomic_load(addr, 5);
}
@@ -232,11 +232,11 @@ void test_promoted_store(_Atomic(PS) *addr, PS *val) {
// CHECK: [[VAL:%.*]] = load %struct.PS*, %struct.PS** [[VAL_ARG]], align 4
// CHECK: [[NONATOMIC_TMP8:%.*]] = bitcast %struct.PS* [[NONATOMIC_TMP]] to i8*
// CHECK: [[VAL8:%.*]] = bitcast %struct.PS* [[VAL]] to i8*
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[NONATOMIC_TMP8]], i8* [[VAL8]], i32 6, i32 2, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 2 [[NONATOMIC_TMP8]], i8* align 2 [[VAL8]], i32 6, i1 false)
// CHECK: [[ADDR64:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ADDR]] to i64*
// CHECK: [[ATOMIC_VAL8:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ATOMIC_VAL]] to i8*
// CHECK: [[NONATOMIC_TMP8:%.*]] = bitcast %struct.PS* [[NONATOMIC_TMP]] to i8*
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[ATOMIC_VAL8]], i8* [[NONATOMIC_TMP8]], i64 6, i32 2, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[ATOMIC_VAL8]], i8* align 2 [[NONATOMIC_TMP8]], i64 6, i1 false)
// CHECK: [[ATOMIC_VAL64:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ATOMIC_VAL]] to i64*
// CHECK: [[VAL64:%.*]] = load i64, i64* [[ATOMIC_VAL64]], align 8
// CHECK: store atomic i64 [[VAL64]], i64* [[ADDR64]] seq_cst, align 8
@@ -257,11 +257,11 @@ PS test_promoted_exchange(_Atomic(PS) *addr, PS *val) {
// CHECK: [[VAL:%.*]] = load %struct.PS*, %struct.PS** [[VAL_ARG]], align 4
// CHECK: [[NONATOMIC_TMP8:%.*]] = bitcast %struct.PS* [[NONATOMIC_TMP]] to i8*
// CHECK: [[VAL8:%.*]] = bitcast %struct.PS* [[VAL]] to i8*
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[NONATOMIC_TMP8]], i8* [[VAL8]], i32 6, i32 2, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 2 [[NONATOMIC_TMP8]], i8* align 2 [[VAL8]], i32 6, i1 false)
// CHECK: [[ADDR64:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ADDR]] to i64*
// CHECK: [[ATOMIC_VAL8:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ATOMIC_VAL]] to i8*
// CHECK: [[NONATOMIC_TMP8:%.*]] = bitcast %struct.PS* [[NONATOMIC_TMP]] to i8*
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[ATOMIC_VAL8]], i8* [[NONATOMIC_TMP8]], i64 6, i32 2, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[ATOMIC_VAL8]], i8* align 2 [[NONATOMIC_TMP8]], i64 6, i1 false)
// CHECK: [[ATOMIC_VAL64:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ATOMIC_VAL]] to i64*
// CHECK: [[ATOMIC_RES64:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ATOMIC_RES]] to i64*
// CHECK: [[VAL64:%.*]] = load i64, i64* [[ATOMIC_VAL64]], align 8
@@ -270,7 +270,7 @@ PS test_promoted_exchange(_Atomic(PS) *addr, PS *val) {
// CHECK: [[ATOMIC_RES_STRUCT:%.*]] = bitcast i64* [[ATOMIC_RES64]] to %struct.PS*
// CHECK: [[AGG_RESULT8:%.*]] = bitcast %struct.PS* %agg.result to i8*
// CHECK: [[ATOMIC_RES8:%.*]] = bitcast %struct.PS* [[ATOMIC_RES_STRUCT]] to i8*
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[AGG_RESULT8]], i8* [[ATOMIC_RES8]], i32 6, i32 2, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 2 [[AGG_RESULT8]], i8* align 8 [[ATOMIC_RES8]], i32 6, i1 false)
return __c11_atomic_exchange(addr, *val, 5);
}
@@ -291,15 +291,15 @@ _Bool test_promoted_cmpxchg(_Atomic(PS) *addr, PS *desired, PS *new) {
// CHECK: [[NEW:%.*]] = load %struct.PS*, %struct.PS** [[NEW_ARG]], align 4
// CHECK: [[NONATOMIC_TMP8:%.*]] = bitcast %struct.PS* [[NONATOMIC_TMP]] to i8*
// CHECK: [[NEW8:%.*]] = bitcast %struct.PS* [[NEW]] to i8*
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[NONATOMIC_TMP8]], i8* [[NEW8]], i32 6, i32 2, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 2 [[NONATOMIC_TMP8]], i8* align 2 [[NEW8]], i32 6, i1 false)
// CHECK: [[ADDR64:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ADDR]] to i64*
// CHECK: [[ATOMIC_DESIRED8:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ATOMIC_DESIRED:%.*]] to i8*
// CHECK: [[DESIRED8:%.*]] = bitcast %struct.PS* [[DESIRED]] to i8*
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[ATOMIC_DESIRED8]], i8* [[DESIRED8]], i64 6, i32 2, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[ATOMIC_DESIRED8]], i8* align 2 [[DESIRED8]], i64 6, i1 false)
// CHECK: [[ATOMIC_DESIRED64:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ATOMIC_DESIRED:%.*]] to i64*
// CHECK: [[ATOMIC_NEW8:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ATOMIC_NEW]] to i8*
// CHECK: [[NONATOMIC_TMP8:%.*]] = bitcast %struct.PS* [[NONATOMIC_TMP]] to i8*
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[ATOMIC_NEW8]], i8* [[NONATOMIC_TMP8]], i64 6, i32 2, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[ATOMIC_NEW8]], i8* align 2 [[NONATOMIC_TMP8]], i64 6, i1 false)
// CHECK: [[ATOMIC_NEW64:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ATOMIC_NEW]] to i64*
// CHECK: [[ATOMIC_DESIRED_VAL64:%.*]] = load i64, i64* [[ATOMIC_DESIRED64]], align 8
// CHECK: [[ATOMIC_NEW_VAL64:%.*]] = load i64, i64* [[ATOMIC_NEW64]], align 8
@@ -319,3 +319,19 @@ _Bool test_promoted_cmpxchg(_Atomic(PS) *addr, PS *desired, PS *new) {
return __c11_atomic_compare_exchange_strong(addr, desired, *new, 5, 5);
}
+
+struct Empty {};
+
+struct Empty testEmptyStructLoad(_Atomic(struct Empty)* empty) {
+ // CHECK-LABEL: @testEmptyStructLoad(
+ // CHECK-NOT: @__atomic_load
+ // CHECK: load atomic i8, i8* %{{.*}} seq_cst, align 1
+ return *empty;
+}
+
+void testEmptyStructStore(_Atomic(struct Empty)* empty, struct Empty value) {
+ // CHECK-LABEL: @testEmptyStructStore(
+ // CHECK-NOT: @__atomic_store
+ // CHECK: store atomic i8 %{{.*}}, i8* %{{.*}} seq_cst, align 1
+ *empty = value;
+}
diff --git a/test/CodeGen/c11atomics.c b/test/CodeGen/c11atomics.c
index ccb642174c94..cf251738be55 100644
--- a/test/CodeGen/c11atomics.c
+++ b/test/CodeGen/c11atomics.c
@@ -282,7 +282,7 @@ void testStruct(_Atomic(S) *fp) {
// CHECK-NEXT: [[T0:%.*]] = load [[S]]*, [[S]]** [[FP]]
// CHECK-NEXT: [[T1:%.*]] = bitcast [[S]]* [[TMP0]] to i8*
// CHECK-NEXT: [[T2:%.*]] = bitcast [[S]]* [[F]] to i8*
-// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[T1]], i8* [[T2]], i32 8, i32 2, i1 false)
+// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[T1]], i8* align 2 [[T2]], i32 8, i1 false)
// CHECK-NEXT: [[T3:%.*]] = bitcast [[S]]* [[T0]] to i8*
// CHECK-NEXT: [[T4:%.*]] = bitcast [[S]]* [[TMP0]] to i8*
// CHECK-NEXT: call arm_aapcscc void @__atomic_store(i32 8, i8* [[T3]], i8* [[T4]], i32 5)
@@ -307,7 +307,7 @@ void testPromotedStruct(_Atomic(PS) *fp) {
// CHECK-NEXT: [[P:%.*]] = load [[APS]]*, [[APS]]** [[FP]]
// CHECK-NEXT: [[T0:%.*]] = bitcast [[APS]]* [[P]] to i8*
-// CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 8, i32 8, i1 false)
+// CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 8 [[T0]], i8 0, i64 8, i1 false)
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[APS]], [[APS]]* [[P]], i32 0, i32 0
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[PS]], [[PS]]* [[T0]], i32 0, i32 0
// CHECK-NEXT: store i16 1, i16* [[T1]], align 8
@@ -318,7 +318,7 @@ void testPromotedStruct(_Atomic(PS) *fp) {
__c11_atomic_init(fp, (PS){1,2,3});
// CHECK-NEXT: [[T0:%.*]] = bitcast [[APS]]* [[X]] to i8*
-// CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* [[T0]], i8 0, i32 8, i32 8, i1 false)
+// CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* align 8 [[T0]], i8 0, i32 8, i1 false)
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[APS]], [[APS]]* [[X]], i32 0, i32 0
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[PS]], [[PS]]* [[T0]], i32 0, i32 0
// CHECK-NEXT: store i16 1, i16* [[T1]], align 8
@@ -335,16 +335,16 @@ void testPromotedStruct(_Atomic(PS) *fp) {
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[APS]], [[APS]]* [[TMP0]], i32 0, i32 0
// CHECK-NEXT: [[T1:%.*]] = bitcast [[PS]]* [[F]] to i8*
// CHECK-NEXT: [[T2:%.*]] = bitcast [[PS]]* [[T0]] to i8*
-// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[T1]], i8* [[T2]], i32 6, i32 2, i1 false)
+// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 2 [[T1]], i8* align 8 [[T2]], i32 6, i1 false)
PS f = *fp;
// CHECK-NEXT: [[T0:%.*]] = load [[APS]]*, [[APS]]** [[FP]]
// CHECK-NEXT: [[T1:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[TMP1]] to i8*
-// CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* [[T1]], i8 0, i32 8, i32 8, i1 false)
+// CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* align 8 [[T1]], i8 0, i32 8, i1 false)
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[APS]], [[APS]]* [[TMP1]], i32 0, i32 0
// CHECK-NEXT: [[T2:%.*]] = bitcast [[PS]]* [[T1]] to i8*
// CHECK-NEXT: [[T3:%.*]] = bitcast [[PS]]* [[F]] to i8*
-// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[T2]], i8* [[T3]], i32 6, i32 2, i1 false)
+// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[T2]], i8* align 2 [[T3]], i32 6, i1 false)
// CHECK-NEXT: [[T4:%.*]] = bitcast [[APS]]* [[T0]] to i8*
// CHECK-NEXT: [[T5:%.*]] = bitcast [[APS]]* [[TMP1]] to i8*
// CHECK-NEXT: call arm_aapcscc void @__atomic_store(i32 8, i8* [[T4]], i8* [[T5]], i32 5)
@@ -357,7 +357,7 @@ void testPromotedStruct(_Atomic(PS) *fp) {
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[APS]], [[APS]]* [[TMP3]], i32 0, i32 0
// CHECK-NEXT: [[T1:%.*]] = bitcast %struct.PS* [[TMP2]] to i8*
// CHECK-NEXT: [[T2:%.*]] = bitcast %struct.PS* [[T0]] to i8*
-// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[T1]], i8* [[T2]], i32 6, i32 2, i1 false)
+// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 2 [[T1]], i8* align 8 [[T2]], i32 6, i1 false)
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds %struct.PS, %struct.PS* [[TMP2]], i32 0, i32 0
// CHECK-NEXT: [[T1:%.*]] = load i16, i16* [[T0]], align 2
// CHECK-NEXT: [[T2:%.*]] = sext i16 [[T1]] to i32
@@ -381,7 +381,7 @@ PS test_promoted_load(_Atomic(PS) *addr) {
// CHECK: [[ATOMIC_RES_STRUCT:%.*]] = bitcast i64* [[ATOMIC_RES64]] to %struct.PS*
// CHECK: [[AGG_RESULT8:%.*]] = bitcast %struct.PS* %agg.result to i8*
// CHECK: [[ATOMIC_RES8:%.*]] = bitcast %struct.PS* [[ATOMIC_RES_STRUCT]] to i8*
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[AGG_RESULT8]], i8* [[ATOMIC_RES8]], i32 6, i32 2, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 2 [[AGG_RESULT8]], i8* align 8 [[ATOMIC_RES8]], i32 6, i1 false)
return __c11_atomic_load(addr, 5);
}
@@ -398,11 +398,11 @@ void test_promoted_store(_Atomic(PS) *addr, PS *val) {
// CHECK: [[VAL:%.*]] = load %struct.PS*, %struct.PS** [[VAL_ARG]], align 4
// CHECK: [[NONATOMIC_TMP8:%.*]] = bitcast %struct.PS* [[NONATOMIC_TMP]] to i8*
// CHECK: [[VAL8:%.*]] = bitcast %struct.PS* [[VAL]] to i8*
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[NONATOMIC_TMP8]], i8* [[VAL8]], i32 6, i32 2, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 2 [[NONATOMIC_TMP8]], i8* align 2 [[VAL8]], i32 6, i1 false)
// CHECK: [[ADDR64:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ADDR]] to i64*
// CHECK: [[ATOMIC_VAL8:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ATOMIC_VAL]] to i8*
// CHECK: [[NONATOMIC_TMP8:%.*]] = bitcast %struct.PS* [[NONATOMIC_TMP]] to i8*
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[ATOMIC_VAL8]], i8* [[NONATOMIC_TMP8]], i64 6, i32 2, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[ATOMIC_VAL8]], i8* align 2 [[NONATOMIC_TMP8]], i64 6, i1 false)
// CHECK: [[ATOMIC_VAL64:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ATOMIC_VAL]] to i64*
// CHECK: [[ADDR8:%.*]] = bitcast i64* [[ADDR64]] to i8*
// CHECK: [[VAL64:%.*]] = load i64, i64* [[ATOMIC_VAL64]], align 2
@@ -423,11 +423,11 @@ PS test_promoted_exchange(_Atomic(PS) *addr, PS *val) {
// CHECK: [[VAL:%.*]] = load %struct.PS*, %struct.PS** [[VAL_ARG]], align 4
// CHECK: [[NONATOMIC_TMP8:%.*]] = bitcast %struct.PS* [[NONATOMIC_TMP]] to i8*
// CHECK: [[VAL8:%.*]] = bitcast %struct.PS* [[VAL]] to i8*
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[NONATOMIC_TMP8]], i8* [[VAL8]], i32 6, i32 2, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 2 [[NONATOMIC_TMP8]], i8* align 2 [[VAL8]], i32 6, i1 false)
// CHECK: [[ADDR64:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ADDR]] to i64*
// CHECK: [[ATOMIC_VAL8:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ATOMIC_VAL]] to i8*
// CHECK: [[NONATOMIC_TMP8:%.*]] = bitcast %struct.PS* [[NONATOMIC_TMP]] to i8*
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[ATOMIC_VAL8]], i8* [[NONATOMIC_TMP8]], i64 6, i32 2, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[ATOMIC_VAL8]], i8* align 2 [[NONATOMIC_TMP8]], i64 6, i1 false)
// CHECK: [[ATOMIC_VAL64:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ATOMIC_VAL]] to i64*
// CHECK: [[ATOMIC_RES64:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ATOMIC_RES]] to i64*
// CHECK: [[ADDR8:%.*]] = bitcast i64* [[ADDR64]] to i8*
@@ -437,7 +437,7 @@ PS test_promoted_exchange(_Atomic(PS) *addr, PS *val) {
// CHECK: [[ATOMIC_RES_STRUCT:%.*]] = bitcast i64* [[ATOMIC_RES64]] to %struct.PS*
// CHECK: [[AGG_RESULT8:%.*]] = bitcast %struct.PS* %agg.result to i8*
// CHECK: [[ATOMIC_RES8:%.*]] = bitcast %struct.PS* [[ATOMIC_RES_STRUCT]] to i8*
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[AGG_RESULT8]], i8* [[ATOMIC_RES8]], i32 6, i32 2, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 2 [[AGG_RESULT8]], i8* align 8 [[ATOMIC_RES8]], i32 6, i1 false)
return __c11_atomic_exchange(addr, *val, 5);
}
@@ -457,15 +457,15 @@ _Bool test_promoted_cmpxchg(_Atomic(PS) *addr, PS *desired, PS *new) {
// CHECK: [[NEW:%.*]] = load %struct.PS*, %struct.PS** [[NEW_ARG]], align 4
// CHECK: [[NONATOMIC_TMP8:%.*]] = bitcast %struct.PS* [[NONATOMIC_TMP]] to i8*
// CHECK: [[NEW8:%.*]] = bitcast %struct.PS* [[NEW]] to i8*
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[NONATOMIC_TMP8]], i8* [[NEW8]], i32 6, i32 2, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 2 [[NONATOMIC_TMP8]], i8* align 2 [[NEW8]], i32 6, i1 false)
// CHECK: [[ADDR64:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ADDR]] to i64*
// CHECK: [[ATOMIC_DESIRED8:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ATOMIC_DESIRED]] to i8*
// CHECK: [[DESIRED8:%.*]] = bitcast %struct.PS* [[DESIRED]]to i8*
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[ATOMIC_DESIRED8]], i8* [[DESIRED8]], i64 6, i32 2, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[ATOMIC_DESIRED8]], i8* align 2 [[DESIRED8]], i64 6, i1 false)
// CHECK: [[ATOMIC_DESIRED64:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ATOMIC_DESIRED]] to i64*
// CHECK: [[ATOMIC_NEW8:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ATOMIC_NEW]] to i8*
// CHECK: [[NONATOMIC_TMP8:%.*]] = bitcast %struct.PS* [[NONATOMIC_TMP]] to i8*
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[ATOMIC_NEW8]], i8* [[NONATOMIC_TMP8]], i64 6, i32 2, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[ATOMIC_NEW8]], i8* align 2 [[NONATOMIC_TMP8]], i64 6, i1 false)
// CHECK: [[ATOMIC_NEW64:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ATOMIC_NEW]] to i64*
// CHECK: [[ADDR8:%.*]] = bitcast i64* [[ADDR64]] to i8*
// CHECK: [[ATOMIC_DESIRED8:%.*]] = bitcast i64* [[ATOMIC_DESIRED64]] to i8*
@@ -474,3 +474,17 @@ _Bool test_promoted_cmpxchg(_Atomic(PS) *addr, PS *desired, PS *new) {
// CHECK: ret i1 [[RES]]
return __c11_atomic_compare_exchange_strong(addr, desired, *new, 5, 5);
}
+
+struct Empty {};
+
+struct Empty test_empty_struct_load(_Atomic(struct Empty)* empty) {
+ // CHECK-LABEL: @test_empty_struct_load(
+ // CHECK: call arm_aapcscc zeroext i8 @__atomic_load_1(i8* %{{.*}}, i32 5)
+ return __c11_atomic_load(empty, 5);
+}
+
+void test_empty_struct_store(_Atomic(struct Empty)* empty, struct Empty value) {
+ // CHECK-LABEL: @test_empty_struct_store(
+ // CHECK: call arm_aapcscc void @__atomic_store_1(i8* %{{.*}}, i8 zeroext %{{.*}}, i32 5)
+ __c11_atomic_store(empty, value, 5);
+}
diff --git a/test/CodeGen/cetintrin.c b/test/CodeGen/cetintrin.c
index 085462a6626d..f70d1c80e1cf 100644
--- a/test/CodeGen/cetintrin.c
+++ b/test/CodeGen/cetintrin.c
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -ffreestanding %s -triple=i386-apple-darwin -target-feature +shstk -emit-llvm -o - -Wall -Werror | FileCheck %s
-// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +shstk -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=X86_64
+// RUN: %clang_cc1 -ffreestanding %s -triple=i386-unknown-unknown -target-feature +shstk -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=I386 --check-prefix=CHECK
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-unknown-unknown -target-feature +shstk -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=X86_64 --check-prefix=CHECK
#include <immintrin.h>
@@ -15,6 +15,20 @@ void test_incsspq(int a) {
// X86_64: call void @llvm.x86.incsspq(i64 %{{[a-z0-9.]+}})
_incsspq(a);
}
+
+void test_inc_ssp(unsigned int a) {
+ // X86_64-LABEL: @test_inc_ssp
+ // X86_64: call void @llvm.x86.incsspq(i64 %{{[a-z0-9.]+}})
+ _inc_ssp(a);
+}
+#else
+
+void test_inc_ssp(unsigned int a) {
+ // I386-LABEL: @test_inc_ssp
+ // I386: call void @llvm.x86.incsspd(i32 %{{[0-9]+}})
+ _inc_ssp(a);
+}
+
#endif
unsigned int test_rdsspd(unsigned int a) {
@@ -29,6 +43,21 @@ unsigned long long test_rdsspq(unsigned long long a) {
// X86_64: call i64 @llvm.x86.rdsspq(i64 %{{[a-z0-9.]+}})
return _rdsspq(a);
}
+
+unsigned long long test_get_ssp(void) {
+ // X86_64-LABEL: @test_get_ssp
+ // X86_64: call i64 @llvm.x86.rdsspq(i64 0)
+ return _get_ssp();
+}
+
+#else
+
+unsigned int test_get_ssp(void) {
+ // I386-LABEL: @test_get_ssp
+ // I386: call i32 @llvm.x86.rdsspd(i32 0)
+ return _get_ssp();
+}
+
#endif
void test_saveprevssp() {
diff --git a/test/CodeGen/cfi-check-fail2.c b/test/CodeGen/cfi-check-fail2.c
index 5340871c2ebe..9c4d0ac2ea36 100644
--- a/test/CodeGen/cfi-check-fail2.c
+++ b/test/CodeGen/cfi-check-fail2.c
@@ -3,6 +3,12 @@
// RUN: -fsanitize=cfi-vcall \
// RUN: -emit-llvm -o - %s | FileCheck %s
+// Check that blacklist does not affect generated code.
+// RUN: echo "src:*" > %t-all.blacklist
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -O0 -fsanitize-cfi-cross-dso \
+// RUN: -fsanitize=cfi-vcall -fsanitize-blacklist=%t-all.blacklist \
+// RUN: -emit-llvm -o - %s | FileCheck %s
+
void caller(void (*f)()) {
f();
}
diff --git a/test/CodeGen/cfi-icall-cross-dso.c b/test/CodeGen/cfi-icall-cross-dso.c
index 43ab0e73b14a..1df20aa1c8a3 100644
--- a/test/CodeGen/cfi-icall-cross-dso.c
+++ b/test/CodeGen/cfi-icall-cross-dso.c
@@ -39,6 +39,11 @@
// MS-DIAG: call void @__cfi_slowpath_diag(i64 4195979634929632483, i8* %{{.*}}, {{.*}}@[[DATA]]{{.*}}) {{.*}}, !nosanitize
// MS-TRAP: call void @__cfi_slowpath(i64 4195979634929632483, i8* %{{.*}}) {{.*}}, !nosanitize
+// ITANIUM-DIAG: declare void @__cfi_slowpath_diag(
+// ITANIUM-TRAP: declare void @__cfi_slowpath(
+// MS-DIAG: declare dso_local void @__cfi_slowpath_diag(
+// MS-TRAP: declare dso_local void @__cfi_slowpath(
+
void caller(void (*f)()) {
f();
}
@@ -49,7 +54,7 @@ void caller(void (*f)()) {
// CHECK: define internal void @g({{.*}} !type [[TVOID:![0-9]+]] !type [[TVOID_GENERALIZED:![0-9]+]] !type [[TVOID_ID:![0-9]+]]
static void g(void) {}
-// CHECK: declare void @h({{[^!]*$}}
+// CHECK: declare {{(dso_local )?}}void @h({{[^!]*$}}
void h(void);
typedef void (*Fn)(void);
@@ -60,12 +65,15 @@ Fn h1() {
return &h;
}
-// CHECK: define void @bar({{.*}} !type [[TNOPROTO:![0-9]+]] !type [[TNOPROTO_GENERALIZED:![0-9]+]] !type [[TNOPROTO_ID:![0-9]+]]
+// CHECK: define {{(dso_local )?}}void @bar({{.*}} !type [[TNOPROTO:![0-9]+]] !type [[TNOPROTO_GENERALIZED:![0-9]+]] !type [[TNOPROTO_ID:![0-9]+]]
// ITANIUM: define available_externally void @foo({{[^!]*$}}
-// MS: define linkonce_odr void @foo({{.*}} !type [[TNOPROTO]] !type [[TNOPROTO_GENERALIZED:![0-9]+]] !type [[TNOPROTO_ID]]
+// MS: define linkonce_odr dso_local void @foo({{.*}} !type [[TNOPROTO]] !type [[TNOPROTO_GENERALIZED:![0-9]+]] !type [[TNOPROTO_ID]]
inline void foo() {}
void bar() { foo(); }
+// ITANIUM: define weak void @__cfi_check
+// MS: define weak dso_local void @__cfi_check
+
// CHECK: !{i32 4, !"Cross-DSO CFI", i32 1}
// Check that the type entries are correct.
diff --git a/test/CodeGen/cfi-icall.c b/test/CodeGen/cfi-icall.c
index 5f346b66e81e..83fc8f89fbcf 100644
--- a/test/CodeGen/cfi-icall.c
+++ b/test/CodeGen/cfi-icall.c
@@ -3,20 +3,20 @@
// Tests that we assign appropriate identifiers to unprototyped functions.
-// CHECK: define void @f({{.*}} !type [[TVOID:![0-9]+]] !type [[TVOID_GENERALIZED:![0-9]+]]
+// CHECK: define {{(dso_local )?}}void @f({{.*}} !type [[TVOID:![0-9]+]] !type [[TVOID_GENERALIZED:![0-9]+]]
void f() {
}
void xf();
-// CHECK: define void @g({{.*}} !type [[TINT:![0-9]+]] !type [[TINT_GENERALIZED:![0-9]+]]
+// CHECK: define {{(dso_local )?}}void @g({{.*}} !type [[TINT:![0-9]+]] !type [[TINT_GENERALIZED:![0-9]+]]
void g(int b) {
void (*fp)() = b ? f : xf;
// ITANIUM: call i1 @llvm.type.test(i8* {{.*}}, metadata !"_ZTSFvE")
fp();
}
-// CHECK: declare !type [[TVOID]] !type [[TVOID_GENERALIZED]] void @xf({{.*}}
+// CHECK: declare !type [[TVOID]] !type [[TVOID_GENERALIZED]] {{(dso_local )?}}void @xf({{.*}}
// ITANIUM-DAG: [[TVOID]] = !{i64 0, !"_ZTSFvE"}
// ITANIUM-DAG: [[TVOID_GENERALIZED]] = !{i64 0, !"_ZTSFvE.generalized"}
diff --git a/test/CodeGen/cfstring-windows.c b/test/CodeGen/cfstring-windows.c
index e54c86089078..fe7511eae141 100644
--- a/test/CodeGen/cfstring-windows.c
+++ b/test/CodeGen/cfstring-windows.c
@@ -31,8 +31,8 @@ __declspec(dllimport) long __CFConstantStringClassReference[];
typedef struct __CFString *CFStringRef;
const CFStringRef string = (CFStringRef)__builtin___CFStringMakeConstantString("string");
-// CHECK-CF-IN-CF-DECL: @__CFConstantStringClassReference = external dllexport global [0 x i32]
-// CHECK-CF-IN-CF-DEFN: @__CFConstantStringClassReference = common dllexport global [32 x i32]
+// CHECK-CF-IN-CF-DECL: @__CFConstantStringClassReference = external dso_local dllexport global [0 x i32]
+// CHECK-CF-IN-CF-DEFN: @__CFConstantStringClassReference = common dso_local dllexport global [32 x i32]
// CHECK-CF: @__CFConstantStringClassReference = external dllimport global [0 x i32]
// CHECK-CF-EXTERN: @__CFConstantStringClassReference = external dllimport global [0 x i32]
// CHECK-CF-EXTERN-DLLIMPORT: @__CFConstantStringClassReference = external dllimport global [0 x i32]
diff --git a/test/CodeGen/clang-sections-attribute.c b/test/CodeGen/clang-sections-attribute.c
new file mode 100644
index 000000000000..7223d7d97a7a
--- /dev/null
+++ b/test/CodeGen/clang-sections-attribute.c
@@ -0,0 +1,76 @@
+// RUN: %clang_cc1 -emit-llvm -triple arm-none-eabi -o - %s | FileCheck %s
+
+// Test interaction between __attribute__((section())) and '#pragma clang
+// section' directives. The attribute should always have higher priority than
+// the pragma.
+
+// Text tests.
+#pragma clang section text=".ext_fun_pragma"
+void ext_fun(void) __attribute__((section(".ext_fun_attr")));
+void ext_fun(void) {}
+#pragma clang section text=""
+
+void ext_fun2(void) __attribute__((section(".ext_fun2_attr")));
+#pragma clang section text=".ext_fun2_pragma"
+void ext_fun2(void) {}
+#pragma clang section text=""
+
+#pragma clang section text=".int_fun_pragma"
+static void int_fun(void) __attribute__((section(".int_fun_attr"), used));
+static void int_fun(void) {}
+#pragma clang section text=""
+
+static void int_fun2(void) __attribute__((section(".int_fun2_attr"), used));
+#pragma clang section text=".int_fun2_pragma"
+static void int_fun2(void) {}
+#pragma clang section text=""
+
+// Rodata tests.
+#pragma clang section rodata=".ext_const_pragma"
+__attribute__((section(".ext_const_attr")))
+const int ext_const = 1;
+#pragma clang section rodata=""
+
+#pragma clang section rodata=".int_const_pragma"
+__attribute__((section(".int_const_attr"), used))
+static const int int_const = 1;
+#pragma clang section rodata=""
+
+// Data tests.
+#pragma clang section data=".ext_var_pragma"
+__attribute__((section(".ext_var_attr")))
+int ext_var = 1;
+#pragma clang section data=""
+
+#pragma clang section data=".int_var_pragma"
+__attribute__((section(".int_var_attr"), used))
+static int int_var = 1;
+#pragma clang section data=""
+
+// Bss tests.
+#pragma clang section bss=".ext_zvar_pragma"
+__attribute__((section(".ext_zvar_attr")))
+int ext_zvar;
+#pragma clang section bss=""
+
+#pragma clang section bss=".int_zvar_pragma"
+__attribute__((section(".int_zvar_attr"), used))
+static int int_zvar;
+#pragma clang section bss=""
+
+// CHECK: @ext_const = constant i32 1, section ".ext_const_attr", align 4{{$}}
+// CHECK: @int_const = internal constant i32 1, section ".int_const_attr", align 4{{$}}
+// CHECK: @ext_var = global i32 1, section ".ext_var_attr", align 4{{$}}
+// CHECK: @int_var = internal global i32 1, section ".int_var_attr", align 4{{$}}
+// CHECK: @ext_zvar = global i32 0, section ".ext_zvar_attr", align 4{{$}}
+// CHECK: @int_zvar = internal global i32 0, section ".int_zvar_attr", align 4{{$}}
+// CHECK: define void @ext_fun() #0 section ".ext_fun_attr"
+// CHECK: define void @ext_fun2() #0 section ".ext_fun2_attr"
+// CHECK: define internal void @int_fun() #0 section ".int_fun_attr"
+// CHECK: define internal void @int_fun2() #0 section ".int_fun2_attr"
+//
+// Function attributes should not include implicit-section-name.
+// CHECK-NOT: attributes #0 = {{.*}}implicit-section-name
+//
+// No other attribute group should be present in the file.
+// CHECK-NOT: attributes #1
diff --git a/test/CodeGen/cldemote.c b/test/CodeGen/cldemote.c
new file mode 100644
index 000000000000..8c7bdf539333
--- /dev/null
+++ b/test/CodeGen/cldemote.c
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 %s -ffreestanding -triple=x86_64-unknown-unknown -target-feature +cldemote -emit-llvm -o - -Wall -Werror | FileCheck %s
+// RUN: %clang_cc1 %s -ffreestanding -triple=i386-unknown-unknown -target-feature +cldemote -emit-llvm -o - -Wall -Werror | FileCheck %s
+
+#include <immintrin.h>
+
+void test_cldemote(const void *p) {
+ //CHECK-LABEL: @test_cldemote
+ //CHECK: call void @llvm.x86.cldemote(i8* %{{.*}})
+ _cldemote(p);
+}
diff --git a/test/CodeGen/code-coverage.c b/test/CodeGen/code-coverage.c
index 80307f49ef34..310d58544e41 100644
--- a/test/CodeGen/code-coverage.c
+++ b/test/CodeGen/code-coverage.c
@@ -2,7 +2,16 @@
// RUN: %clang_cc1 -emit-llvm -disable-red-zone -femit-coverage-data -coverage-no-function-names-in-data %s -o - | FileCheck %s --check-prefix WITHOUTNAMES
// RUN: %clang_cc1 -emit-llvm -disable-red-zone -femit-coverage-data -coverage-notes-file=aaa.gcno -coverage-data-file=bbb.gcda -dwarf-column-info -debug-info-kind=limited -dwarf-version=4 %s -o - | FileCheck %s --check-prefix GCOV_FILE_INFO
-// <rdar://problem/12843084>
+// RUN: %clang_cc1 -emit-llvm-bc -o /dev/null -fexperimental-new-pass-manager -fdebug-pass-manager -femit-coverage-data %s 2>&1 | FileCheck --check-prefix=NEWPM %s
+// RUN: %clang_cc1 -emit-llvm-bc -o /dev/null -fexperimental-new-pass-manager -fdebug-pass-manager -femit-coverage-data -O3 %s 2>&1 | FileCheck --check-prefix=NEWPM-O3 %s
+
+// NEWPM-NOT: Running pass
+// NEWPM: Running pass: GCOVProfilerPass
+
+// NEWPM-O3-NOT: Running pass
+// NEWPM-O3: Running pass: ForceFunctionAttrsPass
+// NEWPM-O3: Running pass: GCOVProfilerPass
+
int test1(int a) {
switch (a % 2) {
@@ -14,17 +23,25 @@ int test1(int a) {
return a;
}
+int test2(int b) {
+ return b * 2;
+}
+
+// Inside function emission data structure, check that
+// -coverage-no-function-names-in-data uses null as the function name.
+// CHECK: @__llvm_internal_gcov_emit_function_args.0 = internal unnamed_addr constant
+// CHECK-SAME: { i32 {{[0-9]+}}, i8* getelementptr inbounds ({{[^,]*}}, {{[^,]*}}* @
+// CHECK-SAME: { i32 {{[0-9]+}}, i8* getelementptr inbounds ({{[^,]*}}, {{[^,]*}}* @
+// WITHOUTNAMES: @__llvm_internal_gcov_emit_function_args.0 = internal unnamed_addr constant
+// WITHOUTNAMES-NOT: getelementptr inbounds ({{.*}}@
+// WITHOUTNAMES-SAME: zeroinitializer,
+// WITHOUTNAMES-NOT: getelementptr inbounds ({{.*}}@
+// WITHOUTNAMES-SAME: { i32 {{[0-9]+}}, i8* null,
+
// Check that the noredzone flag is set on the generated functions.
// CHECK: void @__llvm_gcov_indirect_counter_increment(i32* %{{.*}}, i64** %{{.*}}) unnamed_addr [[NRZ:#[0-9]+]]
-
-// Inside llvm_gcov_writeout, check that -coverage-no-function-names-in-data
-// passes null as the function name.
// CHECK: void @__llvm_gcov_writeout() unnamed_addr [[NRZ]]
-// CHECK: call void @llvm_gcda_emit_function({{.*}}, i8* getelementptr {{.*}}, {{.*}})
-// WITHOUTNAMES: void @__llvm_gcov_writeout() unnamed_addr
-// WITHOUTNAMES: call void @llvm_gcda_emit_function({{.*}}, i8* null, {{.*}})
-
// CHECK: void @__llvm_gcov_flush() unnamed_addr [[NRZ]]
// CHECK: void @__llvm_gcov_init() unnamed_addr [[NRZ]]
diff --git a/test/CodeGen/compound-literal.c b/test/CodeGen/compound-literal.c
index 6507341ce2c1..38675a7dda22 100644
--- a/test/CodeGen/compound-literal.c
+++ b/test/CodeGen/compound-literal.c
@@ -33,7 +33,7 @@ void f() {
// CHECK-NEXT: store i32 [[TMP]], i32* [[CY]]
// CHECK-NEXT: [[SI8:%[a-zA-Z0-9.]+]] = bitcast [[STRUCT]]* [[S]] to i8*
// CHECK-NEXT: [[COMPOUNDLITI8:%[a-zA-Z0-9.]+]] = bitcast [[STRUCT]]* [[COMPOUNDLIT]] to i8*
- // CHECK-NEXT: call void @llvm.memcpy{{.*}}(i8* [[SI8]], i8* [[COMPOUNDLITI8]]
+ // CHECK-NEXT: call void @llvm.memcpy{{.*}}(i8* align {{[0-9]+}} [[SI8]], i8* align {{[0-9]+}} [[COMPOUNDLITI8]]
s = (S){s.y,s.x};
// CHECK-NEXT: ret void
}
@@ -67,7 +67,7 @@ struct G g(int x, int y, int z) {
// CHECK-NEXT: [[T0:%.*]] = bitcast i48* [[COERCE_TEMP]] to i8*
// CHECK-NEXT: [[T1:%.*]] = bitcast [[G]]* [[RESULT]] to i8*
- // CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T0]], i8* [[T1]], i64 6
+ // CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align {{[0-9]+}} [[T0]], i8* align {{[0-9]+}} [[T1]], i64 6
// CHECK-NEXT: [[T0:%.*]] = load i48, i48* [[COERCE_TEMP]]
// CHECK-NEXT: ret i48 [[T0]]
}
diff --git a/test/CodeGen/constructor-attribute.c b/test/CodeGen/constructor-attribute.c
index a1f0e604d401..562e57b8b122 100644
--- a/test/CodeGen/constructor-attribute.c
+++ b/test/CodeGen/constructor-attribute.c
@@ -1,8 +1,39 @@
-// RUN: %clang_cc1 -emit-llvm -o %t %s
-// RUN: grep -e "global_ctors.*@A" %t
-// RUN: grep -e "global_dtors.*@B" %t
-// RUN: grep -e "global_ctors.*@C" %t
-// RUN: grep -e "global_dtors.*@D" %t
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=WITHOUTATEXIT %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -fregister-global-dtors-with-atexit -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=CXAATEXIT --check-prefix=WITHATEXIT %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -fno-use-cxa-atexit -fregister-global-dtors-with-atexit -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=ATEXIT --check-prefix=WITHATEXIT %s
+
+// WITHOUTATEXIT: global_ctors{{.*}}@A{{.*}}@C
+// WITHOUTATEXIT: @llvm.global_dtors = appending global [5 x { i32, void ()*, i8* }]{{.*}}@B{{.*}}@E{{.*}}@F{{.*}}@G{{.*}}@D
+// WITHATEXIT: @llvm.global_ctors = appending global [5 x { i32, void ()*, i8* }]{{.*}}i32 65535, void ()* @A,{{.*}}i32 65535, void ()* @C,{{.*}}i32 123, void ()* @__GLOBAL_init_123,{{.*}}i32 789, void ()* @[[GLOBAL_INIT_789:__GLOBAL_init_789.[0-9]+]],{{.*}}i32 65535, void ()* @__GLOBAL_init_65535,
+// WITHATEXIT-NOT: global_dtors
+
+// CHECK: define void @A()
+// CHECK: define void @B()
+// CHECK: define internal void @E()
+// CHECK: define internal void @F()
+// CHECK: define internal void @G()
+// CHECK: define i32 @__GLOBAL_init_789(i32 %{{.*}})
+// CHECK: define internal void @C()
+// CHECK: define internal void @D()
+// CHECK: define i32 @main()
+// CHECK: define internal i32 @foo()
+// WITHOUTATEXIT-NOT: define
+
+// WITHATEXIT: define internal void @__GLOBAL_init_123(){{.*}}section "__TEXT,__StaticInit,regular,pure_instructions"
+// CXAATEXIT: call i32 @__cxa_atexit(void (i8*)* bitcast (void ()* @E to void (i8*)*), i8* null, i8* @__dso_handle)
+// CXAATEXIT: call i32 @__cxa_atexit(void (i8*)* bitcast (void ()* @G to void (i8*)*), i8* null, i8* @__dso_handle)
+// ATEXIT: call i32 @atexit(void ()* @E)
+// ATEXIT: call i32 @atexit(void ()* @G)
+
+// WITHATEXIT: define internal void @[[GLOBAL_INIT_789]](){{.*}}section "__TEXT,__StaticInit,regular,pure_instructions"
+// CXAATEXIT: call i32 @__cxa_atexit(void (i8*)* bitcast (void ()* @F to void (i8*)*), i8* null, i8* @__dso_handle)
+// ATEXIT: call i32 @atexit(void ()* @F)
+
+// WITHATEXIT: define internal void @__GLOBAL_init_65535(){{.*}}section "__TEXT,__StaticInit,regular,pure_instructions"
+// CXAATEXIT: call i32 @__cxa_atexit(void (i8*)* bitcast (void ()* @B to void (i8*)*), i8* null, i8* @__dso_handle)
+// CXAATEXIT: call i32 @__cxa_atexit(void (i8*)* bitcast (void ()* @D to void (i8*)*), i8* null, i8* @__dso_handle)
+// ATEXIT: call i32 @atexit(void ()* @B)
+// ATEXIT: call i32 @atexit(void ()* @D)
int printf(const char *, ...);
@@ -21,6 +52,21 @@ static void C() __attribute__((constructor));
static void D() __attribute__((destructor));
+static __attribute__((destructor(123))) void E() {
+}
+
+static __attribute__((destructor(789))) void F() {
+}
+
+static __attribute__((destructor(123))) void G() {
+}
+
+// Test that this function doesn't collide with the synthesized constructor
+// function for destructors with priority 789.
+int __GLOBAL_init_789(int a) {
+ return a * a;
+}
+
static int foo() {
return 10;
}
diff --git a/test/CodeGen/debug-info-block-out-return.c b/test/CodeGen/debug-info-block-out-return.c
index 428a50c77a06..931ea64d1383 100644
--- a/test/CodeGen/debug-info-block-out-return.c
+++ b/test/CodeGen/debug-info-block-out-return.c
@@ -14,7 +14,7 @@
// CHECK: !DILocalVariable(name: ".block_descriptor", arg: 1,{{.*}}line: 2,
// CHECK: !DILocalVariable(name: "param", arg: 2,{{.*}}line: 2,
-// Line directive so we don't have to worry about how many lines preceed the
+// Line directive so we don't have to worry about how many lines precede the
// test code (as the line number is mangled in with the argument number as shown
// above)
#line 1
diff --git a/test/CodeGen/debug-info-cc.c b/test/CodeGen/debug-info-cc.c
new file mode 100644
index 000000000000..fe158550a627
--- /dev/null
+++ b/test/CodeGen/debug-info-cc.c
@@ -0,0 +1,120 @@
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -o - -emit-llvm -debug-info-kind=limited %s | FileCheck %s --check-prefix=LINUX
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -o - -emit-llvm -debug-info-kind=limited %s | FileCheck %s --check-prefix=WINDOWS
+// RUN: %clang_cc1 -triple i386-pc-linux-gnu -o - -emit-llvm -debug-info-kind=limited %s | FileCheck %s --check-prefix=LINUX32
+// RUN: %clang_cc1 -triple armv7--linux-gnueabihf -o - -emit-llvm -debug-info-kind=limited %s | FileCheck %s --check-prefix=ARM
+
+// enum CallingConv {
+// CC_C, // __attribute__((cdecl))
+// CC_X86StdCall, // __attribute__((stdcall))
+// CC_X86FastCall, // __attribute__((fastcall))
+// CC_X86ThisCall, // __attribute__((thiscall))
+// CC_X86VectorCall, // __attribute__((vectorcall))
+// CC_X86Pascal, // __attribute__((pascal))
+// CC_Win64, // __attribute__((ms_abi))
+// CC_X86_64SysV, // __attribute__((sysv_abi))
+// CC_X86RegCall, // __attribute__((regcall))
+// CC_AAPCS, // __attribute__((pcs("aapcs")))
+// CC_AAPCS_VFP, // __attribute__((pcs("aapcs-vfp")))
+// CC_IntelOclBicc, // __attribute__((intel_ocl_bicc))
+// CC_SpirFunction, // default for OpenCL functions on SPIR target
+// CC_OpenCLKernel, // inferred for OpenCL kernels
+// CC_Swift, // __attribute__((swiftcall))
+// CC_PreserveMost, // __attribute__((preserve_most))
+// CC_PreserveAll, // __attribute__((preserve_all))
+// };
+
+#ifdef __x86_64__
+
+#ifdef __linux__
+// LINUX: !DISubprogram({{.*}}"add_msabi", {{.*}}type: ![[FTY:[0-9]+]]
+// LINUX: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_LLVM_Win64,
+__attribute__((ms_abi)) int add_msabi(int a, int b) {
+ return a+b;
+}
+
+// LINUX: !DISubprogram({{.*}}"add_regcall", {{.*}}type: ![[FTY:[0-9]+]]
+// LINUX: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_LLVM_X86RegCall,
+__attribute__((regcall)) int add_regcall(int a, int b) {
+ return a+b;
+}
+
+// LINUX: !DISubprogram({{.*}}"add_preserve_most", {{.*}}type: ![[FTY:[0-9]+]]
+// LINUX: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_LLVM_PreserveMost,
+__attribute__((preserve_most)) int add_preserve_most(int a, int b) {
+ return a+b;
+}
+
+// LINUX: !DISubprogram({{.*}}"add_preserve_all", {{.*}}type: ![[FTY:[0-9]+]]
+// LINUX: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_LLVM_PreserveAll,
+__attribute__((preserve_all)) int add_preserve_all(int a, int b) {
+ return a+b;
+}
+
+// LINUX: !DISubprogram({{.*}}"add_swiftcall", {{.*}}type: ![[FTY:[0-9]+]]
+// LINUX: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_LLVM_Swift,
+__attribute__((swiftcall)) int add_swiftcall(int a, int b) {
+ return a+b;
+}
+
+// LINUX: !DISubprogram({{.*}}"add_inteloclbicc", {{.*}}type: ![[FTY:[0-9]+]]
+// LINUX: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_LLVM_IntelOclBicc,
+__attribute__((intel_ocl_bicc)) int add_inteloclbicc(int a, int b) {
+ return a+b;
+}
+#endif
+
+#ifdef _WIN64
+// WINDOWS: !DISubprogram({{.*}}"add_sysvabi", {{.*}}type: ![[FTY:[0-9]+]]
+// WINDOWS: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_LLVM_X86_64SysV,
+__attribute__((sysv_abi)) int add_sysvabi(int a, int b) {
+ return a+b;
+}
+#endif
+
+#endif
+
+#ifdef __i386__
+// LINUX32: !DISubprogram({{.*}}"add_stdcall", {{.*}}type: ![[FTY:[0-9]+]]
+// LINUX32: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_BORLAND_stdcall,
+__attribute__((stdcall)) int add_stdcall(int a, int b) {
+ return a+b;
+}
+
+// LINUX32: !DISubprogram({{.*}}"add_fastcall", {{.*}}type: ![[FTY:[0-9]+]]
+// LINUX32: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_BORLAND_msfastcall,
+__attribute__((fastcall)) int add_fastcall(int a, int b) {
+ return a+b;
+}
+
+// LINUX32: !DISubprogram({{.*}}"add_thiscall", {{.*}}type: ![[FTY:[0-9]+]]
+// LINUX32: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_BORLAND_thiscall,
+__attribute__((thiscall)) int add_thiscall(int a, int b) {
+ return a+b;
+}
+
+// LINUX32: !DISubprogram({{.*}}"add_vectorcall", {{.*}}type: ![[FTY:[0-9]+]]
+// LINUX32: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_LLVM_vectorcall,
+__attribute__((vectorcall)) int add_vectorcall(int a, int b) {
+ return a+b;
+}
+
+// LINUX32: !DISubprogram({{.*}}"add_pascal", {{.*}}type: ![[FTY:[0-9]+]]
+// LINUX32: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_BORLAND_pascal,
+__attribute__((pascal)) int add_pascal(int a, int b) {
+ return a+b;
+}
+#endif
+
+#ifdef __arm__
+// ARM: !DISubprogram({{.*}}"add_aapcs", {{.*}}type: ![[FTY:[0-9]+]]
+// ARM: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_LLVM_AAPCS,
+__attribute__((pcs("aapcs"))) int add_aapcs(int a, int b) {
+ return a+b;
+}
+
+// ARM: !DISubprogram({{.*}}"add_aapcs_vfp", {{.*}}type: ![[FTY:[0-9]+]]
+// ARM: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_LLVM_AAPCS_VFP,
+__attribute__((pcs("aapcs-vfp"))) int add_aapcs_vfp(int a, int b) {
+ return a+b;
+}
+#endif
diff --git a/test/CodeGen/debug-info-codeview-unnamed.c b/test/CodeGen/debug-info-codeview-unnamed.c
new file mode 100644
index 000000000000..bd2a7543e56b
--- /dev/null
+++ b/test/CodeGen/debug-info-codeview-unnamed.c
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -debug-info-kind=limited -S -emit-llvm -o - %s | FileCheck --check-prefix LINUX %s
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -debug-info-kind=limited -gcodeview -S -emit-llvm -o - %s | FileCheck --check-prefix MSVC %s
+
+int main(int argc, char* argv[], char* arge[]) {
+
+ // In both DWARF and CodeView, an unnamed C structure type will generate a
+ // DICompositeType without a name or identifier attribute;
+ //
+ struct { int bar; } one = {42};
+ //
+ // LINUX: !{{[0-9]+}} = !DILocalVariable(name: "one"
+ // LINUX-SAME: type: [[TYPE_OF_ONE:![0-9]+]]
+ // LINUX-SAME: )
+ // LINUX: [[TYPE_OF_ONE]] = distinct !DICompositeType(
+ // LINUX-SAME: tag: DW_TAG_structure_type
+ // LINUX-NOT: name:
+ // LINUX-NOT: identifier:
+ // LINUX-SAME: )
+ //
+ // MSVC: !{{[0-9]+}} = !DILocalVariable(name: "one"
+ // MSVC-SAME: type: [[TYPE_OF_ONE:![0-9]+]]
+ // MSVC-SAME: )
+ // MSVC: [[TYPE_OF_ONE]] = distinct !DICompositeType
+ // MSVC-SAME: tag: DW_TAG_structure_type
+ // MSVC-NOT: name:
+ // MSVC-NOT: identifier:
+ // MSVC-SAME: )
+
+ return 0;
+}
diff --git a/test/CodeGen/debug-info-embed-source.c b/test/CodeGen/debug-info-embed-source.c
new file mode 100644
index 000000000000..3b607b61f7d7
--- /dev/null
+++ b/test/CodeGen/debug-info-embed-source.c
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -debug-info-kind=limited -emit-llvm %p/Inputs/debug-info-embed-source.c -o - | FileCheck %s --check-prefix=NOEMBED
+// RUN: %clang_cc1 -gembed-source -debug-info-kind=limited -emit-llvm %p/Inputs/debug-info-embed-source.c -o - | FileCheck %s --check-prefix=EMBED
+
+// NOEMBED-NOT: !DIFile({{.*}}source:
+// EMBED: !DIFile({{.*}}source: "void foo() { }\0A"
diff --git a/test/CodeGen/debug-info-enum.cpp b/test/CodeGen/debug-info-enum.cpp
new file mode 100644
index 000000000000..1237f28b9a55
--- /dev/null
+++ b/test/CodeGen/debug-info-enum.cpp
@@ -0,0 +1,100 @@
+// Test enumeration representation in debuig info metadata:
+// * test value representation for each possible underlying integer type
+// * test the integer type is as expected
+// * test the DW_AT_enum_class attribute is present (resp. absent) as expected.
+
+// RUN: %clang -target x86_64-linux -g -S -emit-llvm -o - %s | FileCheck %s
+
+
+enum class E0 : signed char {
+ A0 = -128,
+ B0 = 127,
+} x0;
+// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "E0"
+// CHECK-SAME: baseType: ![[SCHAR:[0-9]+]]
+// CHECK-SAME: DIFlagFixedEnum
+// CHECK-SAME: elements: ![[ELTS0:[0-9]+]]
+// CHECK: ![[SCHAR]] = !DIBasicType(name: "signed char", size: 8, encoding: DW_ATE_signed_char)
+// CHECK: ![[ELTS0]] = !{![[A0:[0-9]+]], ![[B0:[0-9]+]]}
+// CHECK: ![[A0]] = !DIEnumerator(name: "A0", value: -128)
+// CHECK: ![[B0]] = !DIEnumerator(name: "B0", value: 127)
+
+enum class E1 : unsigned char { A1 = 255 } x1;
+// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "E1"
+// CHECK-SAME: baseType: ![[UCHAR:[0-9]+]]
+// CHECK-SAME: DIFlagFixedEnum
+// CHECK-SAME: elements: ![[ELTS1:[0-9]+]]
+// CHECK: ![[UCHAR]] = !DIBasicType(name: "unsigned char", size: 8, encoding: DW_ATE_unsigned_char)
+// CHECK: ![[ELTS1]] = !{![[A1:[0-9]+]]}
+// CHECK: ![[A1]] = !DIEnumerator(name: "A1", value: 255, isUnsigned: true)
+
+enum class E2 : signed short {
+ A2 = -32768,
+ B2 = 32767,
+} x2;
+// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "E2"
+// CHECK-SAME: baseType: ![[SHORT:[0-9]+]]
+// CHECK-SAME: DIFlagFixedEnum
+// CHECK-SAME: elements: ![[ELTS2:[0-9]+]]
+// CHECK: ![[SHORT]] = !DIBasicType(name: "short", size: 16, encoding: DW_ATE_signed)
+// CHECK: ![[ELTS2]] = !{![[A2:[0-9]+]], ![[B2:[0-9]+]]}
+// CHECK: ![[A2]] = !DIEnumerator(name: "A2", value: -32768)
+// CHECK: ![[B2]] = !DIEnumerator(name: "B2", value: 32767)
+
+enum class E3 : unsigned short { A3 = 65535 } x3;
+// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "E3"
+// CHECK-SAME: baseType: ![[USHORT:[0-9]+]]
+// CHECK-SAME: DIFlagFixedEnum
+// CHECK-SAME: elements: ![[ELTS3:[0-9]+]]
+// CHECK: ![[USHORT]] = !DIBasicType(name: "unsigned short", size: 16, encoding: DW_ATE_unsigned)
+// CHECK: ![[ELTS3]] = !{![[A3:[0-9]+]]}
+// CHECK: ![[A3]] = !DIEnumerator(name: "A3", value: 65535, isUnsigned: true)
+
+enum class E4 : signed int { A4 = -2147483648, B4 = 2147483647 } x4;
+// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "E4"
+// CHECK-SAME: baseType: ![[INT:[0-9]+]]
+// CHECK-SAME: DIFlagFixedEnum
+// CHECK-SAME: elements: ![[ELTS4:[0-9]+]]
+// CHECK: ![[INT]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+// CHECK: ![[ELTS4]] = !{![[A4:[0-9]+]], ![[B4:[0-9]+]]}
+// CHECK: ![[A4]] = !DIEnumerator(name: "A4", value: -2147483648)
+// CHECK: ![[B4]] = !DIEnumerator(name: "B4", value: 2147483647)
+
+enum class E5 : unsigned int { A5 = 4294967295 } x5;
+// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "E5"
+// CHECK-SAME: baseType: ![[UINT:[0-9]+]]
+// CHECK-SAME: DIFlagFixedEnum
+// CHECK-SAME: elements: ![[ELTS5:[0-9]+]]
+// CHECK: ![[UINT]] = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned)
+// CHECK: ![[ELTS5]] = !{![[A5:[0-9]+]]}
+// CHECK: ![[A5]] = !DIEnumerator(name: "A5", value: 4294967295, isUnsigned: true)
+
+enum class E6 : signed long long {
+ A6 = -9223372036854775807LL - 1,
+ B6 = 9223372036854775807LL
+} x6;
+// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "E6"
+// CHECK-SAME: baseType: ![[LONG:[0-9]+]]
+// CHECK-SAME: DIFlagFixedEnum
+// CHECK-SAME: elements: ![[ELTS6:[0-9]+]]
+// CHECK: ![[LONG]] = !DIBasicType(name: "long long int", size: 64, encoding: DW_ATE_signed)
+// CHECK: ![[ELTS6]] = !{![[A6:[0-9]+]], ![[B6:[0-9]+]]}
+// CHECK: ![[A6]] = !DIEnumerator(name: "A6", value: -9223372036854775808)
+// CHECK: ![[B6]] = !DIEnumerator(name: "B6", value: 9223372036854775807)
+
+enum class E7 : unsigned long long { A7 = 18446744073709551615ULL } x7;
+// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "E7"
+// CHECK-SAME: baseType: ![[ULONG:[0-9]+]]
+// CHECK-SAME: DIFlagFixedEnum
+// CHECK-SAME: elements: ![[ELTS7:[0-9]+]]
+// CHECK: ![[ULONG]] = !DIBasicType(name: "long long unsigned int", size: 64, encoding: DW_ATE_unsigned)
+// CHECK: ![[ELTS7]] = !{![[A7:[0-9]+]]}
+// CHECK: ![[A7]] = !DIEnumerator(name: "A7", value: 18446744073709551615, isUnsigned: true)
+
+// Also test the FixedEnum flag is not present for old-style enumerations.
+enum E8 { A8 = -128, B8 = 127 } x8;
+// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "E8"
+// CHECK-SAME: baseType: ![[INT]]
+// CHECK-NOT: DIFlagFixedEnum
+// CHECK: !DIEnumerator(name: "A8", value: -128)
+
diff --git a/test/CodeGen/debug-info-file-checksum.c b/test/CodeGen/debug-info-file-checksum.c
index 2750800d41ea..d644aac0614f 100644
--- a/test/CodeGen/debug-info-file-checksum.c
+++ b/test/CodeGen/debug-info-file-checksum.c
@@ -1,4 +1,5 @@
// RUN: %clang -emit-llvm -S -g -gcodeview -x c %S/Inputs/debug-info-file-checksum.c -o - | FileCheck %s
+// RUN: %clang -emit-llvm -S -gdwarf-5 -x c %S/Inputs/debug-info-file-checksum.c -o - | FileCheck %s
// Check that "checksum" is created correctly for the compiled file.
diff --git a/test/CodeGen/debug-info-inline-for.c b/test/CodeGen/debug-info-inline-for.c
new file mode 100644
index 000000000000..55066b28a1ff
--- /dev/null
+++ b/test/CodeGen/debug-info-inline-for.c
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -debug-info-kind=limited -emit-llvm -o - %s | FileCheck %s
+// Check that clang emits Debug location in the phi instruction
+
+int func(int n) {
+ int a;
+ for(a = 10; a>0 && n++; a--);
+ return n;
+}
+
+// CHECK: land.end:
+// CHECK-NEXT: {{.*}} = phi i1 {{.*}} !dbg ![[DbgLoc:[0-9]+]]
+
+// CHECK: ![[DbgLoc]] = !DILocation(line: 0
diff --git a/test/CodeGen/debug-info-vla.c b/test/CodeGen/debug-info-vla.c
index 7928ca761397..8bd6a6d0acbe 100644
--- a/test/CodeGen/debug-info-vla.c
+++ b/test/CodeGen/debug-info-vla.c
@@ -2,9 +2,11 @@
void testVLAwithSize(int s)
{
-// CHECK: dbg.declare
-// CHECK: dbg.declare({{.*}}, metadata ![[VAR:.*]], metadata !DIExpression())
-// CHECK: ![[VAR]] = !DILocalVariable(name: "vla",{{.*}} line: [[@LINE+1]]
+// CHECK-DAG: dbg.declare({{.*}} %__vla_expr, metadata ![[VLAEXPR:[0-9]+]]
+// CHECK-DAG: dbg.declare({{.*}} %vla, metadata ![[VAR:[0-9]+]]
+// CHECK-DAG: ![[VLAEXPR]] = !DILocalVariable(name: "__vla_expr", {{.*}} flags: DIFlagArtificial
+// CHECK-DAG: ![[VAR]] = !DILocalVariable(name: "vla",{{.*}} line: [[@LINE+2]]
+// CHECK-DAG: !DISubrange(count: ![[VLAEXPR]])
int vla[s];
int i;
for (i = 0; i < s; i++) {
diff --git a/test/CodeGen/decl.c b/test/CodeGen/decl.c
index 2065e3364bcd..d62629c7fb5c 100644
--- a/test/CodeGen/decl.c
+++ b/test/CodeGen/decl.c
@@ -1,13 +1,13 @@
-// RUN: %clang_cc1 -w -emit-llvm < %s | FileCheck %s
+// RUN: %clang_cc1 -w -fmerge-all-constants -emit-llvm < %s | FileCheck %s
// CHECK: @test1.x = internal constant [12 x i32] [i32 1
// CHECK: @test2.x = private unnamed_addr constant [13 x i32] [i32 1,
-// CHECK: @test5w = global { i32, [4 x i8] } { i32 2, [4 x i8] undef }
-// CHECK: @test5y = global { double } { double 7.300000e+0{{[0]*}}1 }
+// CHECK: @test5w = {{(dso_local )?}}global { i32, [4 x i8] } { i32 2, [4 x i8] undef }
+// CHECK: @test5y = {{(dso_local )?}}global { double } { double 7.300000e+0{{[0]*}}1 }
// CHECK: @test6.x = private unnamed_addr constant %struct.SelectDest { i8 1, i8 2, i32 3, i32 0 }
-// CHECK: @test7 = global [2 x %struct.test7s] [%struct.test7s { i32 1, i32 2 }, %struct.test7s { i32 4, i32 0 }]
+// CHECK: @test7 = {{(dso_local )?}}global [2 x %struct.test7s] [%struct.test7s { i32 1, i32 2 }, %struct.test7s { i32 4, i32 0 }]
void test1() {
// This should codegen as a "@test1.x" global.
diff --git a/test/CodeGen/default-address-space.c b/test/CodeGen/default-address-space.c
index b7f40585b267..5450609e06bb 100644
--- a/test/CodeGen/default-address-space.c
+++ b/test/CodeGen/default-address-space.c
@@ -1,39 +1,27 @@
-// RUN: %clang_cc1 -triple amdgcn -emit-llvm < %s | FileCheck -check-prefixes=PIZ,COM %s
// RUN: %clang_cc1 -triple amdgcn---amdgiz -emit-llvm < %s | FileCheck -check-prefixes=CHECK,COM %s
-// PIZ-DAG: @foo = common addrspace(1) global i32 0
// CHECK-DAG: @foo = common addrspace(1) global i32 0
int foo;
-// PIZ-DAG: @ban = common addrspace(1) global [10 x i32] zeroinitializer
// CHECK-DAG: @ban = common addrspace(1) global [10 x i32] zeroinitializer
int ban[10];
-// PIZ-DAG: @A = common addrspace(1) global i32 addrspace(4)* null
-// PIZ-DAG: @B = common addrspace(1) global i32 addrspace(4)* null
// CHECK-DAG: @A = common addrspace(1) global i32* null
// CHECK-DAG: @B = common addrspace(1) global i32* null
int *A;
int *B;
// COM-LABEL: define i32 @test1()
-// PIZ: load i32, i32 addrspace(4)* addrspacecast{{[^@]+}} @foo
// CHECK: load i32, i32* addrspacecast{{[^@]+}} @foo
int test1() { return foo; }
// COM-LABEL: define i32 @test2(i32 %i)
// COM: %[[addr:.*]] = getelementptr
-// PIZ: load i32, i32 addrspace(4)* %[[addr]]
-// PIZ-NEXT: ret i32
// CHECK: load i32, i32* %[[addr]]
// CHECK-NEXT: ret i32
int test2(int i) { return ban[i]; }
// COM-LABEL: define void @test3()
-// PIZ: load i32 addrspace(4)*, i32 addrspace(4)* addrspace(4)* addrspacecast{{[^@]+}} @B
-// PIZ: load i32, i32 addrspace(4)*
-// PIZ: load i32 addrspace(4)*, i32 addrspace(4)* addrspace(4)* addrspacecast{{[^@]+}} @A
-// PIZ: store i32 {{.*}}, i32 addrspace(4)*
// CHECK: load i32*, i32** addrspacecast{{.*}} @B
// CHECK: load i32, i32*
// CHECK: load i32*, i32** addrspacecast{{.*}} @A
@@ -42,13 +30,6 @@ void test3() {
*A = *B;
}
-// PIZ-LABEL: define void @test4(i32 addrspace(4)* %a)
-// PIZ: %[[alloca:.*]] = alloca i32 addrspace(4)*
-// PIZ: %[[a_addr:.*]] = addrspacecast{{.*}} %[[alloca]] to i32 addrspace(4)* addrspace(4)*
-// PIZ: store i32 addrspace(4)* %a, i32 addrspace(4)* addrspace(4)* %[[a_addr]]
-// PIZ: %[[r0:.*]] = load i32 addrspace(4)*, i32 addrspace(4)* addrspace(4)* %[[a_addr]]
-// PIZ: %[[arrayidx:.*]] = getelementptr inbounds i32, i32 addrspace(4)* %[[r0]]
-// PIZ: store i32 0, i32 addrspace(4)* %[[arrayidx]]
// CHECK-LABEL: define void @test4(i32* %a)
// CHECK: %[[alloca:.*]] = alloca i32*, align 8, addrspace(5)
// CHECK: %[[a_addr:.*]] = addrspacecast{{.*}} %[[alloca]] to i32**
diff --git a/test/CodeGen/delete-null-pointer-checks.c b/test/CodeGen/delete-null-pointer-checks.c
new file mode 100644
index 000000000000..a3c1460f0a06
--- /dev/null
+++ b/test/CodeGen/delete-null-pointer-checks.c
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-unknown-linux-gnu -O2 -o - %s | FileCheck -check-prefix=NULL-POINTER-INVALID %s
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-unknown-linux-gnu -O2 -o - %s -fno-delete-null-pointer-checks | FileCheck -check-prefix=NULL-POINTER-VALID %s
+
+// Test that clang does not remove the null pointer check with
+// -fno-delete-null-pointer-checks.
+int null_check(int *P) {
+// NULL-POINTER-VALID: %[[TOBOOL:.*]] = icmp eq i32* %P, null
+// NULL-POINTER-INVALID-NOT: icmp eq
+// NULL-POINTER-VALID: %[[SEL:.*]] = select i1 %[[TOBOOL:.*]], i32* null, i32*
+// NULL-POINTER-INVALID-NOT: select i1
+// NULL-POINTER-VALID: load i32, i32* %[[SEL:.*]]
+ int *Q = P;
+ if (P) {
+ Q = P + 2;
+ }
+ return *Q;
+}
+
+// NULL-POINTER-INVALID-NOT: attributes #0 = {{.*}} "null-pointer-is-valid"="true"
+// NULL-POINTER-VALID: attributes #0 = {{.*}} "null-pointer-is-valid"="true"
diff --git a/test/CodeGen/dllexport.c b/test/CodeGen/dllexport.c
index 17c2ce9e2755..f27012ec2355 100644
--- a/test/CodeGen/dllexport.c
+++ b/test/CodeGen/dllexport.c
@@ -14,24 +14,24 @@
__declspec(dllexport) extern int ExternGlobalDecl;
// dllexport implies a definition.
-// CHECK-DAG: @GlobalDef = common dllexport global i32 0, align 4
+// CHECK-DAG: @GlobalDef = common dso_local dllexport global i32 0, align 4
__declspec(dllexport) int GlobalDef;
// Export definition.
-// CHECK-DAG: @GlobalInit = dllexport global i32 1, align 4
+// CHECK-DAG: @GlobalInit = dso_local dllexport global i32 1, align 4
__declspec(dllexport) int GlobalInit = 1;
// Declare, then export definition.
-// CHECK-DAG: @GlobalDeclInit = dllexport global i32 1, align 4
+// CHECK-DAG: @GlobalDeclInit = dso_local dllexport global i32 1, align 4
__declspec(dllexport) extern int GlobalDeclInit;
int GlobalDeclInit = 1;
// Redeclarations
-// CHECK-DAG: @GlobalRedecl1 = common dllexport global i32 0, align 4
+// CHECK-DAG: @GlobalRedecl1 = common dso_local dllexport global i32 0, align 4
__declspec(dllexport) extern int GlobalRedecl1;
__declspec(dllexport) int GlobalRedecl1;
-// CHECK-DAG: @GlobalRedecl2 = common dllexport global i32 0, align 4
+// CHECK-DAG: @GlobalRedecl2 = common dso_local dllexport global i32 0, align 4
__declspec(dllexport) extern int GlobalRedecl2;
int GlobalRedecl2;
@@ -44,22 +44,22 @@ __declspec(dllexport) extern int GlobalRedecl2;
// Declarations are not exported.
// Export function definition.
-// CHECK-DAG: define dllexport void @def()
+// CHECK-DAG: define dso_local dllexport void @def()
__declspec(dllexport) void def(void) {}
// Export inline function.
-// CHECK-DAG: define weak_odr dllexport void @inlineFunc()
-// CHECK-DAG: define weak_odr dllexport void @externInlineFunc()
+// CHECK-DAG: define weak_odr dso_local dllexport void @inlineFunc()
+// CHECK-DAG: define weak_odr dso_local dllexport void @externInlineFunc()
__declspec(dllexport) inline void inlineFunc(void) {}
__declspec(dllexport) inline void externInlineFunc(void) {}
extern void externInlineFunc(void);
// Redeclarations
-// CHECK-DAG: define dllexport void @redecl1()
+// CHECK-DAG: define dso_local dllexport void @redecl1()
__declspec(dllexport) void redecl1(void);
__declspec(dllexport) void redecl1(void) {}
-// CHECK-DAG: define dllexport void @redecl2()
+// CHECK-DAG: define dso_local dllexport void @redecl2()
__declspec(dllexport) void redecl2(void);
void redecl2(void) {}
@@ -70,46 +70,46 @@ __declspec(dllexport) void redecl2(void);
//===----------------------------------------------------------------------===//
// dllexport takes precedence over the dllimport if both are specified.
-// CHECK-DAG: @PrecedenceGlobal1A = common dllexport global i32 0, align 4
-// CHECK-DAG: @PrecedenceGlobal1B = common dllexport global i32 0, align 4
+// CHECK-DAG: @PrecedenceGlobal1A = common dso_local dllexport global i32 0, align 4
+// CHECK-DAG: @PrecedenceGlobal1B = common dso_local dllexport global i32 0, align 4
__attribute__((dllimport, dllexport)) int PrecedenceGlobal1A;
__declspec(dllimport) __declspec(dllexport) int PrecedenceGlobal1B;
-// CHECK-DAG: @PrecedenceGlobal2A = common dllexport global i32 0, align 4
-// CHECK-DAG: @PrecedenceGlobal2B = common dllexport global i32 0, align 4
+// CHECK-DAG: @PrecedenceGlobal2A = common dso_local dllexport global i32 0, align 4
+// CHECK-DAG: @PrecedenceGlobal2B = common dso_local dllexport global i32 0, align 4
__attribute__((dllexport, dllimport)) int PrecedenceGlobal2A;
__declspec(dllexport) __declspec(dllimport) int PrecedenceGlobal2B;
-// CHECK-DAG: @PrecedenceGlobalRedecl1 = dllexport global i32 0, align 4
+// CHECK-DAG: @PrecedenceGlobalRedecl1 = dso_local dllexport global i32 0, align 4
__declspec(dllexport) extern int PrecedenceGlobalRedecl1;
__declspec(dllimport) int PrecedenceGlobalRedecl1 = 0;
-// CHECK-DAG: @PrecedenceGlobalRedecl2 = common dllexport global i32 0, align 4
+// CHECK-DAG: @PrecedenceGlobalRedecl2 = common dso_local dllexport global i32 0, align 4
__declspec(dllimport) extern int PrecedenceGlobalRedecl2;
__declspec(dllexport) int PrecedenceGlobalRedecl2;
-// CHECK-DAG: @PrecedenceGlobalMixed1 = dllexport global i32 1, align 4
+// CHECK-DAG: @PrecedenceGlobalMixed1 = dso_local dllexport global i32 1, align 4
__attribute__((dllexport)) extern int PrecedenceGlobalMixed1;
__declspec(dllimport) int PrecedenceGlobalMixed1 = 1;
-// CHECK-DAG: @PrecedenceGlobalMixed2 = common dllexport global i32 0, align 4
+// CHECK-DAG: @PrecedenceGlobalMixed2 = common dso_local dllexport global i32 0, align 4
__attribute__((dllimport)) extern int PrecedenceGlobalMixed2;
__declspec(dllexport) int PrecedenceGlobalMixed2;
-// CHECK-DAG: define dllexport void @precedence1A()
-// CHECK-DAG: define dllexport void @precedence1B()
+// CHECK-DAG: define dso_local dllexport void @precedence1A()
+// CHECK-DAG: define dso_local dllexport void @precedence1B()
void __attribute__((dllimport, dllexport)) precedence1A(void) {}
void __declspec(dllimport) __declspec(dllexport) precedence1B(void) {}
-// CHECK-DAG: define dllexport void @precedence2A()
-// CHECK-DAG: define dllexport void @precedence2B()
+// CHECK-DAG: define dso_local dllexport void @precedence2A()
+// CHECK-DAG: define dso_local dllexport void @precedence2B()
void __attribute__((dllexport, dllimport)) precedence2A(void) {}
void __declspec(dllexport) __declspec(dllimport) precedence2B(void) {}
-// CHECK-DAG: define dllexport void @precedenceRedecl1()
+// CHECK-DAG: define dso_local dllexport void @precedenceRedecl1()
void __declspec(dllimport) precedenceRedecl1(void);
void __declspec(dllexport) precedenceRedecl1(void) {}
-// CHECK-DAG: define dllexport void @precedenceRedecl2()
+// CHECK-DAG: define dso_local dllexport void @precedenceRedecl2()
void __declspec(dllexport) precedenceRedecl2(void);
void __declspec(dllimport) precedenceRedecl2(void) {}
diff --git a/test/CodeGen/dllimport.c b/test/CodeGen/dllimport.c
index f70048ebd1fb..61d695705261 100644
--- a/test/CodeGen/dllimport.c
+++ b/test/CodeGen/dllimport.c
@@ -39,14 +39,14 @@ USEVAR(GlobalRedecl2)
// NB: MSVC issues a warning and makes GlobalRedecl3 dllexport. We follow GCC
// and drop the dllimport with a warning.
-// CHECK: @GlobalRedecl3 = external global i32
+// CHECK: @GlobalRedecl3 = external dso_local global i32
__declspec(dllimport) extern int GlobalRedecl3;
extern int GlobalRedecl3; // dllimport ignored
USEVAR(GlobalRedecl3)
// Make sure this works even if the decl has been used before it's defined (PR20792).
-// MS: @GlobalRedecl4 = common dllexport global i32
-// GNU: @GlobalRedecl4 = common global i32
+// MS: @GlobalRedecl4 = common dso_local dllexport global i32
+// GNU: @GlobalRedecl4 = common dso_local global i32
__declspec(dllimport) extern int GlobalRedecl4;
USEVAR(GlobalRedecl4)
int GlobalRedecl4; // dllimport ignored
@@ -76,22 +76,22 @@ int functionScope() {
__declspec(dllimport) void decl(void);
// Initialize use_decl with the address of the thunk.
-// CHECK-DAG: @use_decl = global void ()* @decl
+// CHECK-DAG: @use_decl = dso_local global void ()* @decl
void (*use_decl)(void) = &decl;
// Import inline function.
// MS-DAG: declare dllimport void @inlineFunc()
// MO1-DAG: define available_externally dllimport void @inlineFunc()
-// GNU-DAG: declare void @inlineFunc()
-// GO1-DAG: define available_externally void @inlineFunc()
+// GNU-DAG: declare dso_local void @inlineFunc()
+// GO1-DAG: define available_externally dso_local void @inlineFunc()
__declspec(dllimport) inline void inlineFunc(void) {}
USE(inlineFunc)
// inline attributes
// MS-DAG: declare dllimport void @noinline()
// MO1-DAG: define available_externally dllimport void @noinline()
-// GNU-DAG: declare void @noinline()
-// GO1-DAG: define available_externally void @noinline()
+// GNU-DAG: declare dso_local void @noinline()
+// GO1-DAG: define available_externally dso_local void @noinline()
// CHECK-NOT: @alwaysInline()
// O1-NOT: @alwaysInline()
__declspec(dllimport) __attribute__((noinline)) inline void noinline(void) {}
@@ -107,20 +107,20 @@ USE(redecl1)
// NB: MSVC issues a warning and makes redecl2/redecl3 dllexport. We follow GCC
// and drop the dllimport with a warning.
-// CHECK-DAG: declare void @redecl2()
+// CHECK-DAG: declare dso_local void @redecl2()
__declspec(dllimport) void redecl2(void);
void redecl2(void);
USE(redecl2)
-// MS: define dllexport void @redecl3()
-// GNU: define void @redecl3()
+// MS: define dso_local dllexport void @redecl3()
+// GNU: define dso_local void @redecl3()
__declspec(dllimport) void redecl3(void);
void redecl3(void) {} // dllimport ignored
USE(redecl3)
// Make sure this works even if the decl is used before it's defined (PR20792).
-// MS: define dllexport void @redecl4()
-// GNU: define void @redecl4()
+// MS: define dso_local dllexport void @redecl4()
+// GNU: define dso_local void @redecl4()
__declspec(dllimport) void redecl4(void);
USE(redecl4)
void redecl4(void) {} // dllimport ignored
diff --git a/test/CodeGen/dso-local-executable.c b/test/CodeGen/dso-local-executable.c
new file mode 100644
index 000000000000..6e434a67effb
--- /dev/null
+++ b/test/CodeGen/dso-local-executable.c
@@ -0,0 +1,112 @@
+// RUN: %clang_cc1 -triple x86_64-pc-win32 -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix=COFF %s
+// COFF-DAG: @bar = external dso_local global i32
+// COFF-DAG: @weak_bar = extern_weak dso_local global i32
+// COFF-DAG: declare dso_local void @foo()
+// COFF-DAG: @baz = dso_local global i32 42
+// COFF-DAG: define dso_local i32* @zed()
+// COFF-DAG: @thread_var = external dso_local thread_local global i32
+// COFF-DAG: @local_thread_var = dso_local thread_local global i32 42
+// COFF-DAG: @import_var = external dllimport global i32
+// COFF-DAG: declare dllimport void @import_func()
+
+// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm -mrelocation-model static %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix=STATIC %s
+// STATIC-DAG: @bar = external dso_local global i32
+// STATIC-DAG: @weak_bar = extern_weak dso_local global i32
+// STATIC-DAG: declare dso_local void @foo()
+// STATIC-DAG: @baz = dso_local global i32 42
+// STATIC-DAG: define dso_local i32* @zed()
+// STATIC-DAG: @thread_var = external thread_local global i32
+// STATIC-DAG: @local_thread_var = dso_local thread_local global i32 42
+// STATIC-DAG: @import_var = external dso_local global i32
+// STATIC-DAG: declare dso_local void @import_func()
+
+// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm -pic-is-pie -mpie-copy-relocations %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix=PIE-COPY %s
+// PIE-COPY-DAG: @bar = external dso_local global i32
+// PIE-COPY-DAG: @weak_bar = extern_weak global i32
+// PIE-COPY-DAG: declare void @foo()
+// PIE-COPY-DAG: @baz = dso_local global i32 42
+// PIE-COPY-DAG: define dso_local i32* @zed()
+// PIE-COPY-DAG: @thread_var = external thread_local global i32
+// PIE-COPY-DAG: @local_thread_var = dso_local thread_local global i32 42
+// PIE-COPY-DAG: @import_var = external dso_local global i32
+// PIE-COPY-DAG: declare void @import_func()
+
+// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm -pic-is-pie %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix=PIE %s
+// PIE-DAG: @bar = external global i32
+// PIE-DAG: @weak_bar = extern_weak global i32
+// PIE-DAG: declare void @foo()
+// PIE-DAG: @baz = dso_local global i32 42
+// PIE-DAG: define dso_local i32* @zed()
+// PIE-DAG: @thread_var = external thread_local global i32
+// PIE-DAG: @local_thread_var = dso_local thread_local global i32 42
+// PIE-DAG: @import_var = external global i32
+// PIE-DAG: declare void @import_func()
+
+// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm -mrelocation-model static -fno-plt %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix=NOPLT %s
+// NOPLT-DAG: @bar = external dso_local global i32
+// NOPLT-DAG: @weak_bar = extern_weak dso_local global i32
+// NOPLT-DAG: declare void @foo()
+// NOPLT-DAG: @baz = dso_local global i32 42
+// NOPLT-DAG: define dso_local i32* @zed()
+// NOPLT-DAG: @thread_var = external thread_local global i32
+// NOPLT-DAG: @local_thread_var = dso_local thread_local global i32 42
+// NOPLT-DAG: @import_var = external dso_local global i32
+// NOPLT-DAG: declare void @import_func()
+
+// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm -fno-plt -pic-is-pie -mpie-copy-relocations %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix=PIE-COPY-NOPLT %s
+// PIE-COPY-NOPLT-DAG: @bar = external dso_local global i32
+// PIE-COPY-NOPLT-DAG: @weak_bar = extern_weak global i32
+// PIE-COPY-NOPLT-DAG: declare void @foo()
+// PIE-COPY-NOPLT-DAG: @baz = dso_local global i32 42
+// PIE-COPY-NOPLT-DAG: define dso_local i32* @zed()
+// PIE-COPY-NOPLT-DAG: @thread_var = external thread_local global i32
+// PIE-COPY-NOPLT-DAG: @local_thread_var = dso_local thread_local global i32 42
+// PIE-COPY-NOPLT-DAG: @import_var = external dso_local global i32
+// PIE-COPY-NOPLT-DAG: declare void @import_func()
+
+// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm -pic-is-pie -fno-plt %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix=PIE-NO-PLT %s
+// RUN: %clang_cc1 -triple powerpc64le-pc-linux -emit-llvm -mrelocation-model static %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix=PIE-NO-PLT %s
+// PIE-NO-PLT-DAG: @bar = external global i32
+// PIE-NO-PLT-DAG: @weak_bar = extern_weak global i32
+// PIE-NO-PLT-DAG: declare void @foo()
+// PIE-NO-PLT-DAG: @baz = dso_local global i32 42
+// PIE-NO-PLT-DAG: define dso_local i32* @zed()
+// PIE-NO-PLT-DAG: @thread_var = external thread_local global i32
+// PIE-NO-PLT-DAG: @local_thread_var = dso_local thread_local global i32 42
+// PIE-NO-PLT-DAG: @import_var = external global i32
+// PIE-NO-PLT-DAG: declare void @import_func()
+
+// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix=SHARED %s
+// SHARED-DAG: @bar = external global i32
+// SHARED-DAG: @weak_bar = extern_weak global i32
+// SHARED-DAG: declare void @foo()
+// SHARED-DAG: @baz = global i32 42
+// SHARED-DAG: define i32* @zed()
+// SHARED-DAG: @thread_var = external thread_local global i32
+// SHARED-DAG: @local_thread_var = thread_local global i32 42
+// PIE-NO-PLT-DAG: @import_var = external global i32
+// PIE-NO-PLT-DAG: declare void @import_func()
+
+__attribute__((dllimport)) extern int import_var;
+__attribute__((dllimport)) void import_func(void);
+
+int *use_import() {
+ import_func();
+ return &import_var;
+}
+
+extern int bar;
+__attribute__((weak)) extern int weak_bar;
+void foo(void);
+
+int baz = 42;
+int *zed() {
+ foo();
+ return baz ? &weak_bar : &bar;
+}
+
+extern __thread int thread_var;
+__thread int local_thread_var = 42;
+int *get_thread_var(int a) {
+ return a ? &thread_var : &local_thread_var;
+}
diff --git a/test/CodeGen/dump-struct-builtin.c b/test/CodeGen/dump-struct-builtin.c
new file mode 100644
index 000000000000..cd8540960205
--- /dev/null
+++ b/test/CodeGen/dump-struct-builtin.c
@@ -0,0 +1,555 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck %s
+
+#include "Inputs/stdio.h"
+#include <stdint.h>
+
+// CHECK: @unit1.a = private unnamed_addr constant %struct.U1A { i16 12 }, align 2
+// CHECK-NEXT: [[STRUCT_STR_U1:@[0-9]+]] = private unnamed_addr constant [14 x i8] c"struct U1A {\0A\00"
+// CHECK-NEXT: [[FIELD_U1:@[0-9]+]] = private unnamed_addr constant [11 x i8] c"short a : \00"
+// CHECK-NEXT: [[FORMAT_U1:@[0-9]+]] = private unnamed_addr constant [5 x i8] c"%hd\0A\00"
+// CHECK-NEXT: [[END_STRUCT_U1:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
+
+// CHECK: @unit2.a = private unnamed_addr constant %struct.U2A { i16 12 }, align 2
+// CHECK-NEXT: [[STRUCT_STR_U2:@[0-9]+]] = private unnamed_addr constant [14 x i8] c"struct U2A {\0A\00"
+// CHECK-NEXT: [[FIELD_U2:@[0-9]+]] = private unnamed_addr constant [20 x i8] c"unsigned short a : \00"
+// CHECK-NEXT: [[FORMAT_U2:@[0-9]+]] = private unnamed_addr constant [5 x i8] c"%hu\0A\00"
+// CHECK-NEXT: [[END_STRUCT_U2:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
+
+// CHECK: @unit3.a = private unnamed_addr constant %struct.U3A { i32 12 }, align 4
+// CHECK-NEXT: [[STRUCT_STR_U3:@[0-9]+]] = private unnamed_addr constant [14 x i8] c"struct U3A {\0A\00"
+// CHECK-NEXT: [[FIELD_U3:@[0-9]+]] = private unnamed_addr constant [9 x i8] c"int a : \00"
+// CHECK-NEXT: [[FORMAT_U3:@[0-9]+]] = private unnamed_addr constant [4 x i8] c"%d\0A\00"
+// CHECK-NEXT: [[END_STRUCT_U3:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
+
+// CHECK: @unit4.a = private unnamed_addr constant %struct.U4A { i32 12 }, align 4
+// CHECK-NEXT: [[STRUCT_STR_U4:@[0-9]+]] = private unnamed_addr constant [14 x i8] c"struct U4A {\0A\00"
+// CHECK-NEXT: [[FIELD_U4:@[0-9]+]] = private unnamed_addr constant [18 x i8] c"unsigned int a : \00"
+// CHECK-NEXT: [[FORMAT_U4:@[0-9]+]] = private unnamed_addr constant [4 x i8] c"%u\0A\00"
+// CHECK-NEXT: [[END_STRUCT_U4:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
+
+// CHECK: @unit5.a = private unnamed_addr constant %struct.U5A { i64 12 }, align 8
+// CHECK-NEXT: [[STRUCT_STR_U5:@[0-9]+]] = private unnamed_addr constant [14 x i8] c"struct U5A {\0A\00"
+// CHECK-NEXT: [[FIELD_U5:@[0-9]+]] = private unnamed_addr constant [10 x i8] c"long a : \00"
+// CHECK-NEXT: [[FORMAT_U5:@[0-9]+]] = private unnamed_addr constant [5 x i8] c"%ld\0A\00"
+// CHECK-NEXT: [[END_STRUCT_U5:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
+
+// CHECK: @unit6.a = private unnamed_addr constant %struct.U6A { i64 12 }, align 8
+// CHECK-NEXT: [[STRUCT_STR_U6:@[0-9]+]] = private unnamed_addr constant [14 x i8] c"struct U6A {\0A\00"
+// CHECK-NEXT: [[FIELD_U6:@[0-9]+]] = private unnamed_addr constant [19 x i8] c"unsigned long a : \00"
+// CHECK-NEXT: [[FORMAT_U6:@[0-9]+]] = private unnamed_addr constant [5 x i8] c"%lu\0A\00"
+// CHECK-NEXT: [[END_STRUCT_U6:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
+
+// CHECK: @unit7.a = private unnamed_addr constant %struct.U7A { i64 12 }, align 8
+// CHECK-NEXT: [[STRUCT_STR_U7:@[0-9]+]] = private unnamed_addr constant [14 x i8] c"struct U7A {\0A\00"
+// CHECK-NEXT: [[FIELD_U7:@[0-9]+]] = private unnamed_addr constant [15 x i8] c"long long a : \00"
+// CHECK-NEXT: [[FORMAT_U7:@[0-9]+]] = private unnamed_addr constant [6 x i8] c"%lld\0A\00"
+// CHECK-NEXT: [[END_STRUCT_U7:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
+
+// CHECK: @unit8.a = private unnamed_addr constant %struct.U8A { i64 12 }, align 8
+// CHECK-NEXT: [[STRUCT_STR_U8:@[0-9]+]] = private unnamed_addr constant [14 x i8] c"struct U8A {\0A\00"
+// CHECK-NEXT: [[FIELD_U8:@[0-9]+]] = private unnamed_addr constant [24 x i8] c"unsigned long long a : \00"
+// CHECK-NEXT: [[FORMAT_U8:@[0-9]+]] = private unnamed_addr constant [6 x i8] c"%llu\0A\00"
+// CHECK-NEXT: [[END_STRUCT_U8:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
+
+// CHECK: @unit9.a = private unnamed_addr constant %struct.U9A { i8 97 }, align 1
+// CHECK-NEXT: [[STRUCT_STR_U9:@[0-9]+]] = private unnamed_addr constant [14 x i8] c"struct U9A {\0A\00"
+// CHECK-NEXT: [[FIELD_U9:@[0-9]+]] = private unnamed_addr constant [10 x i8] c"char a : \00"
+// CHECK-NEXT: [[FORMAT_U9:@[0-9]+]] = private unnamed_addr constant [4 x i8] c"%c\0A\00"
+// CHECK-NEXT: [[END_STRUCT_U9:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
+
+// CHECK: @.str = private unnamed_addr constant [4 x i8] c"LSE\00", align 1
+
+// CHECK: @unit10.a = private unnamed_addr constant %struct.U10A { i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0) }, align 8
+// CHECK-NEXT: [[STRUCT_STR_U10:@[0-9]+]] = private unnamed_addr constant [15 x i8] c"struct U10A {\0A\00"
+// CHECK-NEXT: [[FIELD_U10:@[0-9]+]] = private unnamed_addr constant [12 x i8] c"char * a : \00"
+// CHECK-NEXT: [[FORMAT_U10:@[0-9]+]] = private unnamed_addr constant [4 x i8] c"%s\0A\00"
+// CHECK-NEXT: [[END_STRUCT_U10:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
+
+// CHECK: @unit11.a = private unnamed_addr constant %struct.U11A { i8* inttoptr (i64 305419896 to i8*) }, align 8
+// CHECK-NEXT: [[STRUCT_STR_U11:@[0-9]+]] = private unnamed_addr constant [15 x i8] c"struct U11A {\0A\00"
+// CHECK-NEXT: [[FIELD_U11:@[0-9]+]] = private unnamed_addr constant [12 x i8] c"void * a : \00"
+// CHECK-NEXT: [[FORMAT_U11:@[0-9]+]] = private unnamed_addr constant [4 x i8] c"%p\0A\00"
+// CHECK-NEXT: [[END_STRUCT_U11:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
+
+// CHECK: @unit12.a = private unnamed_addr constant %struct.U12A { i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0) }, align 8
+// CHECK-NEXT: [[STRUCT_STR_U12:@[0-9]+]] = private unnamed_addr constant [15 x i8] c"struct U12A {\0A\00"
+// CHECK-NEXT: [[FIELD_U12:@[0-9]+]] = private unnamed_addr constant [18 x i8] c"const char * a : \00"
+// CHECK-NEXT: [[FORMAT_U12:@[0-9]+]] = private unnamed_addr constant [4 x i8] c"%s\0A\00"
+// CHECK-NEXT: [[END_STRUCT_U12:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
+
+// CHECK: @unit13.a = private unnamed_addr constant %struct.U13A { i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0) }, align 8
+// CHECK-NEXT: [[STRUCT_STR_U13:@[0-9]+]] = private unnamed_addr constant [15 x i8] c"struct U13A {\0A\00"
+// CHECK-NEXT: [[FIELD_U13:@[0-9]+]] = private unnamed_addr constant [20 x i8] c"const charstar a : \00"
+// CHECK-NEXT: [[FORMAT_U13:@[0-9]+]] = private unnamed_addr constant [4 x i8] c"%s\0A\00"
+// CHECK-NEXT: [[END_STRUCT_U13:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
+
+// CHECK: @unit14.a = private unnamed_addr constant %struct.U14A { double 0x3FF1F9ACFFA7EB6C }, align 8
+// CHECK-NEXT: [[STRUCT_STR_U14:@[0-9]+]] = private unnamed_addr constant [15 x i8] c"struct U14A {\0A\00"
+// CHECK-NEXT: [[FIELD_U14:@[0-9]+]] = private unnamed_addr constant [12 x i8] c"double a : \00"
+// CHECK-NEXT: [[FORMAT_U14:@[0-9]+]] = private unnamed_addr constant [4 x i8] c"%f\0A\00"
+// CHECK-NEXT: [[END_STRUCT_U14:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
+
+// CHECK: @unit15.a = private unnamed_addr constant %struct.U15A { [3 x i32] [i32 1, i32 2, i32 3] }, align 4
+// CHECK-NEXT: [[STRUCT_STR_U15:@[0-9]+]] = private unnamed_addr constant [15 x i8] c"struct U15A {\0A\00"
+// CHECK-NEXT: [[FIELD_U15:@[0-9]+]] = private unnamed_addr constant [13 x i8] c"int [3] a : \00"
+// CHECK-NEXT: [[FORMAT_U15:@[0-9]+]] = private unnamed_addr constant [4 x i8] c"%p\0A\00"
+// CHECK-NEXT: [[END_STRUCT_U15:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
+
+// CHECK: @unit16.a = private unnamed_addr constant %struct.U16A { i8 12 }, align 1
+// CHECK-NEXT: [[STRUCT_STR_U16:@[0-9]+]] = private unnamed_addr constant [15 x i8] c"struct U16A {\0A\00"
+// CHECK-NEXT: [[FIELD_U16:@[0-9]+]] = private unnamed_addr constant [13 x i8] c"uint8_t a : \00"
+// CHECK-NEXT: [[FORMAT_U16:@[0-9]+]] = private unnamed_addr constant [6 x i8] c"%hhu\0A\00"
+// CHECK-NEXT: [[END_STRUCT_U16:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
+
+// CHECK: @unit17.a = private unnamed_addr constant %struct.U17A { i8 12 }, align 1
+// CHECK-NEXT: [[STRUCT_STR_U17:@[0-9]+]] = private unnamed_addr constant [15 x i8] c"struct U17A {\0A\00"
+// CHECK-NEXT: [[FIELD_U17:@[0-9]+]] = private unnamed_addr constant [12 x i8] c"int8_t a : \00"
+// CHECK-NEXT: [[FORMAT_U17:@[0-9]+]] = private unnamed_addr constant [6 x i8] c"%hhd\0A\00"
+// CHECK-NEXT: [[END_STRUCT_U17:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
+
+// CHECK: @unit18.a = private unnamed_addr constant %struct.U18A { x86_fp80 0xK3FFF8FCD67FD3F5B6000 }, align 16
+// CHECK-NEXT: [[STRUCT_STR_U18:@[0-9]+]] = private unnamed_addr constant [15 x i8] c"struct U18A {\0A\00"
+// CHECK-NEXT: [[FIELD_U18:@[0-9]+]] = private unnamed_addr constant [17 x i8] c"long double a : \00"
+// CHECK-NEXT: [[FORMAT_U18:@[0-9]+]] = private unnamed_addr constant [5 x i8] c"%Lf\0A\00"
+// CHECK-NEXT: [[END_STRUCT_U18:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
+
+int printf(const char *fmt, ...) {
+ return 0;
+}
+
+void unit1() {
+ struct U1A {
+ short a;
+ };
+
+ struct U1A a = {
+ .a = 12,
+ };
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([14 x i8], [14 x i8]* [[STRUCT_STR_U1]], i32 0, i32 0))
+ // CHECK: [[RES1:%[0-9]+]] = getelementptr inbounds %struct.U1A, %struct.U1A* %a, i32 0, i32 0
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* [[FIELD_U1]], i32 0, i32 0))
+ // CHECK: [[LOAD1:%[0-9]+]] = load i16, i16* [[RES1]],
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* [[FORMAT_U1]], i32 0, i32 0), i16 [[LOAD1]])
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* [[END_STRUCT_U1]], i32 0, i32 0))
+ __builtin_dump_struct(&a, &printf);
+}
+
+void unit2() {
+ struct U2A {
+ unsigned short a;
+ };
+
+ struct U2A a = {
+ .a = 12,
+ };
+
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([14 x i8], [14 x i8]* [[STRUCT_STR_U2]], i32 0, i32 0))
+ // CHECK: [[RES1:%[0-9]+]] = getelementptr inbounds %struct.U2A, %struct.U2A* %a, i32 0, i32 0
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([20 x i8], [20 x i8]* [[FIELD_U2]], i32 0, i32 0))
+ // CHECK: [[LOAD1:%[0-9]+]] = load i16, i16* [[RES1]],
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* [[FORMAT_U2]], i32 0, i32 0), i16 [[LOAD1]])
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* [[END_STRUCT_U2]], i32 0, i32 0))
+ __builtin_dump_struct(&a, &printf);
+}
+
+void unit3() {
+ struct U3A {
+ int a;
+ };
+
+ struct U3A a = {
+ .a = 12,
+ };
+
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([14 x i8], [14 x i8]* [[STRUCT_STR_U3]], i32 0, i32 0))
+ // CHECK: [[RES1:%[0-9]+]] = getelementptr inbounds %struct.U3A, %struct.U3A* %a, i32 0, i32 0
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* [[FIELD_U3]], i32 0, i32 0))
+ // CHECK: [[LOAD1:%[0-9]+]] = load i32, i32* [[RES1]],
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* [[FORMAT_U3]], i32 0, i32 0), i32 [[LOAD1]])
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* [[END_STRUCT_U3]], i32 0, i32 0)
+ __builtin_dump_struct(&a, &printf);
+}
+
+void unit4() {
+ struct U4A {
+ unsigned int a;
+ };
+
+ struct U4A a = {
+ .a = 12,
+ };
+
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([14 x i8], [14 x i8]* [[STRUCT_STR_U4]], i32 0, i32 0))
+ // CHECK: [[RES1:%[0-9]+]] = getelementptr inbounds %struct.U4A, %struct.U4A* %a, i32 0, i32 0
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([18 x i8], [18 x i8]* [[FIELD_U4]], i32 0, i32 0))
+ // CHECK: [[LOAD1:%[0-9]+]] = load i32, i32* [[RES1]],
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* [[FORMAT_U4]], i32 0, i32 0), i32 [[LOAD1]])
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* [[END_STRUCT_U4]], i32 0, i32 0)
+ __builtin_dump_struct(&a, &printf);
+}
+
+void unit5() {
+ struct U5A {
+ long a;
+ };
+
+ struct U5A a = {
+ .a = 12,
+ };
+
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([14 x i8], [14 x i8]* [[STRUCT_STR_U5]], i32 0, i32 0))
+ // CHECK: [[RES1:%[0-9]+]] = getelementptr inbounds %struct.U5A, %struct.U5A* %a, i32 0, i32 0
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* [[FIELD_U5]], i32 0, i32 0))
+ // CHECK: [[LOAD1:%[0-9]+]] = load i64, i64* [[RES1]],
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* [[FORMAT_U5]], i32 0, i32 0), i64 [[LOAD1]])
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* [[END_STRUCT_U5]], i32 0, i32 0)
+ __builtin_dump_struct(&a, &printf);
+}
+
+void unit6() {
+ struct U6A {
+ unsigned long a;
+ };
+
+ struct U6A a = {
+ .a = 12,
+ };
+
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([14 x i8], [14 x i8]* [[STRUCT_STR_U6]], i32 0, i32 0))
+ // CHECK: [[RES1:%[0-9]+]] = getelementptr inbounds %struct.U6A, %struct.U6A* %a, i32 0, i32 0
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([19 x i8], [19 x i8]* [[FIELD_U6]], i32 0, i32 0))
+ // CHECK: [[LOAD1:%[0-9]+]] = load i64, i64* [[RES1]],
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* [[FORMAT_U6]], i32 0, i32 0), i64 [[LOAD1]])
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* [[END_STRUCT_U6]], i32 0, i32 0)
+ __builtin_dump_struct(&a, &printf);
+}
+
+void unit7() {
+ struct U7A {
+ long long a;
+ };
+
+ struct U7A a = {
+ .a = 12,
+ };
+
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([14 x i8], [14 x i8]* [[STRUCT_STR_U7]], i32 0, i32 0))
+ // CHECK: [[RES1:%[0-9]+]] = getelementptr inbounds %struct.U7A, %struct.U7A* %a, i32 0, i32 0
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* [[FIELD_U7]], i32 0, i32 0))
+ // CHECK: [[LOAD1:%[0-9]+]] = load i64, i64* [[RES1]],
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([6 x i8], [6 x i8]* [[FORMAT_U7]], i32 0, i32 0), i64 [[LOAD1]])
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* [[END_STRUCT_U7]], i32 0, i32 0)
+ __builtin_dump_struct(&a, &printf);
+}
+
+void unit8() {
+ struct U8A {
+ unsigned long long a;
+ };
+
+ struct U8A a = {
+ .a = 12,
+ };
+
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([14 x i8], [14 x i8]* [[STRUCT_STR_U8]], i32 0, i32 0))
+ // CHECK: [[RES1:%[0-9]+]] = getelementptr inbounds %struct.U8A, %struct.U8A* %a, i32 0, i32 0
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([24 x i8], [24 x i8]* [[FIELD_U8]], i32 0, i32 0))
+ // CHECK: [[LOAD1:%[0-9]+]] = load i64, i64* [[RES1]],
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([6 x i8], [6 x i8]* [[FORMAT_U8]], i32 0, i32 0), i64 [[LOAD1]])
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* [[END_STRUCT_U8]], i32 0, i32 0)
+ __builtin_dump_struct(&a, &printf);
+}
+
+void unit9() {
+ struct U9A {
+ char a;
+ };
+
+ struct U9A a = {
+ .a = 'a',
+ };
+
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([14 x i8], [14 x i8]* [[STRUCT_STR_U9]], i32 0, i32 0))
+ // CHECK: [[RES1:%[0-9]+]] = getelementptr inbounds %struct.U9A, %struct.U9A* %a, i32 0, i32 0
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* [[FIELD_U9]], i32 0, i32 0))
+ // CHECK: [[LOAD1:%[0-9]+]] = load i8, i8* [[RES1]],
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* [[FORMAT_U9]], i32 0, i32 0), i8 [[LOAD1]])
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* [[END_STRUCT_U9]], i32 0, i32 0)
+ __builtin_dump_struct(&a, &printf);
+}
+
+void unit10() {
+ struct U10A {
+ char *a;
+ };
+
+ struct U10A a = {
+ .a = "LSE",
+ };
+
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* [[STRUCT_STR_U10]], i32 0, i32 0))
+ // CHECK: [[RES1:%[0-9]+]] = getelementptr inbounds %struct.U10A, %struct.U10A* %a, i32 0, i32 0
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* [[FIELD_U10]], i32 0, i32 0))
+ // CHECK: [[LOAD1:%[0-9]+]] = load i8*, i8** [[RES1]],
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* [[FORMAT_U10]], i32 0, i32 0), i8* [[LOAD1]])
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* [[END_STRUCT_U10]], i32 0, i32 0)
+ __builtin_dump_struct(&a, &printf);
+}
+
+void unit11() {
+ struct U11A {
+ void *a;
+ };
+
+ struct U11A a = {
+ .a = (void *)0x12345678,
+ };
+
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* [[STRUCT_STR_U11]], i32 0, i32 0))
+ // CHECK: [[RES1:%[0-9]+]] = getelementptr inbounds %struct.U11A, %struct.U11A* %a, i32 0, i32 0
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* [[FIELD_U11]], i32 0, i32 0))
+ // CHECK: [[LOAD1:%[0-9]+]] = load i8*, i8** [[RES1]],
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* [[FORMAT_U11]], i32 0, i32 0), i8* [[LOAD1]])
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* [[END_STRUCT_U11]], i32 0, i32 0)
+ __builtin_dump_struct(&a, &printf);
+}
+
+void unit12() {
+ struct U12A {
+ const char *a;
+ };
+
+ struct U12A a = {
+ .a = "LSE",
+ };
+
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* [[STRUCT_STR_U12]], i32 0, i32 0))
+ // CHECK: [[RES1:%[0-9]+]] = getelementptr inbounds %struct.U12A, %struct.U12A* %a, i32 0, i32 0
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([18 x i8], [18 x i8]* [[FIELD_U12]], i32 0, i32 0))
+ // CHECK: [[LOAD1:%[0-9]+]] = load i8*, i8** [[RES1]],
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* [[FORMAT_U12]], i32 0, i32 0), i8* [[LOAD1]])
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* [[END_STRUCT_U12]], i32 0, i32 0)
+ __builtin_dump_struct(&a, &printf);
+}
+
+void unit13() {
+ typedef char *charstar;
+ struct U13A {
+ const charstar a;
+ };
+
+ struct U13A a = {
+ .a = "LSE",
+ };
+
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* [[STRUCT_STR_U13]], i32 0, i32 0))
+ // CHECK: [[RES1:%[0-9]+]] = getelementptr inbounds %struct.U13A, %struct.U13A* %a, i32 0, i32 0
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([20 x i8], [20 x i8]* [[FIELD_U13]], i32 0, i32 0))
+ // CHECK: [[LOAD1:%[0-9]+]] = load i8*, i8** [[RES1]],
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* [[FORMAT_U13]], i32 0, i32 0), i8* [[LOAD1]])
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* [[END_STRUCT_U13]], i32 0, i32 0)
+ __builtin_dump_struct(&a, &printf);
+}
+
+void unit14() {
+ struct U14A {
+ double a;
+ };
+
+ struct U14A a = {
+ .a = 1.123456,
+ };
+
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* [[STRUCT_STR_U14]], i32 0, i32 0))
+ // CHECK: [[RES1:%[0-9]+]] = getelementptr inbounds %struct.U14A, %struct.U14A* %a, i32 0, i32 0
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* [[FIELD_U14]], i32 0, i32 0))
+ // CHECK: [[LOAD1:%[0-9]+]] = load double, double* [[RES1]],
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* [[FORMAT_U14]], i32 0, i32 0), double [[LOAD1]])
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* [[END_STRUCT_U14]], i32 0, i32 0)
+ __builtin_dump_struct(&a, &printf);
+}
+
+void unit15() {
+ struct U15A {
+ int a[3];
+ };
+
+ struct U15A a = {
+ .a = {1, 2, 3},
+ };
+
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* [[STRUCT_STR_U15]], i32 0, i32 0))
+ // CHECK: [[RES1:%[0-9]+]] = getelementptr inbounds %struct.U15A, %struct.U15A* %a, i32 0, i32 0
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* [[FIELD_U15]], i32 0, i32 0))
+ // CHECK: [[LOAD1:%[0-9]+]] = load [3 x i32], [3 x i32]* [[RES1]],
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* [[FORMAT_U15]], i32 0, i32 0), [3 x i32] [[LOAD1]])
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* [[END_STRUCT_U15]], i32 0, i32 0)
+ __builtin_dump_struct(&a, &printf);
+}
+
+void unit16() {
+ struct U16A {
+ uint8_t a;
+ };
+
+ struct U16A a = {
+ .a = 12,
+ };
+
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* [[STRUCT_STR_U16]], i32 0, i32 0))
+ // CHECK: [[RES1:%[0-9]+]] = getelementptr inbounds %struct.U16A, %struct.U16A* %a, i32 0, i32 0
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* [[FIELD_U16]], i32 0, i32 0))
+ // CHECK: [[LOAD1:%[0-9]+]] = load i8, i8* [[RES1]],
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([6 x i8], [6 x i8]* [[FORMAT_U16]], i32 0, i32 0), i8 [[LOAD1]])
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* [[END_STRUCT_U16]], i32 0, i32 0)
+ __builtin_dump_struct(&a, &printf);
+}
+
+void unit17() {
+ struct U17A {
+ int8_t a;
+ };
+
+ struct U17A a = {
+ .a = 12,
+ };
+
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* [[STRUCT_STR_U17]], i32 0, i32 0))
+ // CHECK: [[RES1:%[0-9]+]] = getelementptr inbounds %struct.U17A, %struct.U17A* %a, i32 0, i32 0
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* [[FIELD_U17]], i32 0, i32 0))
+ // CHECK: [[LOAD1:%[0-9]+]] = load i8, i8* [[RES1]],
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([6 x i8], [6 x i8]* [[FORMAT_U17]], i32 0, i32 0), i8 [[LOAD1]])
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* [[END_STRUCT_U17]], i32 0, i32 0)
+ __builtin_dump_struct(&a, &printf);
+}
+
+void unit18() {
+ struct U18A {
+ long double a;
+ };
+
+ struct U18A a = {
+ .a = 1.123456,
+ };
+
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* [[STRUCT_STR_U18]], i32 0, i32 0))
+ // CHECK: [[RES1:%[0-9]+]] = getelementptr inbounds %struct.U18A, %struct.U18A* %a, i32 0, i32 0
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([17 x i8], [17 x i8]* [[FIELD_U18]], i32 0, i32 0))
+ // CHECK: [[LOAD1:%[0-9]+]] = load x86_fp80, x86_fp80* [[RES1]],
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* [[FORMAT_U18]], i32 0, i32 0), x86_fp80 [[LOAD1]])
+ // CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* [[END_STRUCT_U18]], i32 0, i32 0)
+ __builtin_dump_struct(&a, &printf);
+}
+
+void test1() {
+ struct T1A {
+ int a;
+ char *b;
+ };
+
+ struct T1A a = {
+ .a = 12,
+ .b = "LSE",
+ };
+
+ // CHECK: call i32 (i8*, ...) @printf(
+ // CHECK: [[RES1:%[0-9]+]] = getelementptr inbounds %struct.T1A, %struct.T1A* %a, i32 0, i32 0
+ // CHECK: call i32 (i8*, ...) @printf(
+ // CHECK: [[LOAD1:%[0-9]+]] = load i32, i32* [[RES1]],
+ // CHECK: call i32 (i8*, ...) @printf({{.*}}, i32 [[LOAD1]])
+ // CHECK: [[RES2:%[0-9]+]] = getelementptr inbounds %struct.T1A, %struct.T1A* %a, i32 0, i32 1
+ // CHECK: call i32 (i8*, ...) @printf(
+ // CHECK: [[LOAD2:%[0-9]+]] = load i8*, i8** [[RES2]],
+ // CHECK: call i32 (i8*, ...) @printf({{.*}}, i8* [[LOAD2]])
+ // CHECK: call i32 (i8*, ...) @printf(
+ __builtin_dump_struct(&a, &printf);
+}
+
+void test2() {
+ struct T2A {
+ int a;
+ };
+
+ struct T2B {
+ int b;
+ struct T2A a;
+ };
+
+ struct T2B b = {
+ .b = 24,
+ .a = {
+ .a = 12,
+ }
+ };
+
+ // CHECK: call i32 (i8*, ...) @printf(
+ // CHECK: [[RES1:%[0-9]+]] = getelementptr inbounds %struct.T2B, %struct.T2B* %b, i32 0, i32 0
+ // CHECK: call i32 (i8*, ...) @printf(
+ // CHECK: [[LOAD1:%[0-9]+]] = load i32, i32* [[RES1]],
+ // CHECK: call i32 (i8*, ...) @printf({{.*}}, i32 [[LOAD1]])
+ // CHECK: [[NESTED_STRUCT:%[0-9]+]] = getelementptr inbounds %struct.T2B, %struct.T2B* %b, i32 0, i32 1
+ // CHECK: call i32 (i8*, ...) @printf(
+ // CHECK: [[RES2:%[0-9]+]] = getelementptr inbounds %struct.T2A, %struct.T2A* [[NESTED_STRUCT]], i32 0, i32 0
+ // CHECK: call i32 (i8*, ...) @printf(
+ // CHECK: [[LOAD2:%[0-9]+]] = load i32, i32* [[RES2]],
+ // CHECK: call i32 (i8*, ...) @printf({{.*}}, i32 [[LOAD2]])
+ // CHECK: call i32 (i8*, ...) @printf(
+ __builtin_dump_struct(&b, &printf);
+}
+
+void test3() {
+ struct T3A {
+ union {
+ int a;
+ char b[4];
+ };
+ };
+
+ struct T3A a = {
+ .a = 42,
+ };
+
+ // CHECK: call i32 (i8*, ...) @printf(
+ // CHECK: [[RES1:%[0-9]+]] = getelementptr inbounds %struct.T3A, %struct.T3A* %a, i32 0, i32 0
+ // CHECK: call i32 (i8*, ...) @printf(
+ // CHECK: [[BC1:%[0-9]+]] = bitcast %union.anon* [[RES1]] to i32*
+ // CHECK: [[LOAD1:%[0-9]+]] = load i32, i32* [[BC1]],
+ // CHECK: call i32 (i8*, ...) @printf({{.*}}, i32 [[LOAD1]])
+ // CHECK: [[BC2:%[0-9]+]] = bitcast %union.anon* [[RES1]] to [4 x i8]*
+ // CHECK: [[LOAD2:%[0-9]+]] = load [4 x i8], [4 x i8]* [[BC2]],
+ // CHECK: call i32 (i8*, ...) @printf({{.*}}, [4 x i8] [[LOAD2]])
+ // CHECK: call i32 (i8*, ...) @printf(
+ __builtin_dump_struct(&a, &printf);
+}
+
+void test4() {
+ struct T4A {
+ union {
+ struct {
+ void *a;
+ };
+ struct {
+ unsigned long b;
+ };
+ };
+ };
+
+ struct T4A a = {
+ .a = (void *)0x12345678,
+ };
+
+ // CHECK: call i32 (i8*, ...) @printf(
+ // CHECK: [[RES1:%[0-9]+]] = getelementptr inbounds %struct.T4A, %struct.T4A* %a, i32 0, i32 0
+ // CHECK: call i32 (i8*, ...) @printf(
+ // CHECK: [[BC1:%[0-9]+]] = bitcast %union.anon.0* [[RES1]] to %struct.anon*
+ // CHECK: [[RES2:%[0-9]+]] = getelementptr inbounds %struct.anon, %struct.anon* [[BC1]], i32 0, i32 0
+ // CHECK: [[LOAD1:%[0-9]+]] = load i8*, i8** [[RES2]],
+ // CHECK: call i32 (i8*, ...) @printf({{.*}}, i8* [[LOAD1]])
+
+ // CHECK: [[BC2:%[0-9]+]] = bitcast %union.anon.0* [[RES1]] to %struct.anon.1*
+ // CHECK: [[RES3:%[0-9]+]] = getelementptr inbounds %struct.anon.1, %struct.anon.1* [[BC2]], i32 0, i32 0
+ // CHECK: [[LOAD2:%[0-9]+]] = load i64, i64* [[RES3]],
+ // CHECK: call i32 (i8*, ...) @printf({{.*}}, i64 [[LOAD2]])
+ // CHECK: call i32 (i8*, ...) @printf(
+ __builtin_dump_struct(&a, &printf);
+}
diff --git a/test/CodeGen/elf-linker-options.c b/test/CodeGen/elf-linker-options.c
new file mode 100644
index 000000000000..cf2d1b92b998
--- /dev/null
+++ b/test/CodeGen/elf-linker-options.c
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -triple i686---elf -emit-llvm %s -o - | FileCheck %s
+
+#pragma comment(lib, "alpha")
+
+// CHECK: !llvm.linker.options = !{[[NODE:![0-9]+]]}
+// CHECK: [[NODE]] = !{!"lib", !"alpha"}
+
diff --git a/test/CodeGen/emit-summary-index.c b/test/CodeGen/emit-summary-index.c
new file mode 100644
index 000000000000..612641020689
--- /dev/null
+++ b/test/CodeGen/emit-summary-index.c
@@ -0,0 +1,17 @@
+// ; Check that the -flto=thin option emits a ThinLTO summary
+// RUN: %clang_cc1 -flto=thin -emit-llvm-bc < %s | llvm-bcanalyzer -dump | FileCheck %s
+// CHECK: <GLOBALVAL_SUMMARY_BLOCK
+//
+// ; Check that we do not emit a summary for regular LTO on Apple platforms
+// RUN: %clang_cc1 -flto -triple x86_64-apple-darwin -emit-llvm-bc < %s | llvm-bcanalyzer -dump | FileCheck --check-prefix=LTO %s
+// LTO-NOT: GLOBALVAL_SUMMARY_BLOCK
+//
+// ; Check that we emit a summary for regular LTO by default elsewhere
+// RUN: %clang_cc1 -flto -triple x86_64-pc-linux-gnu -emit-llvm-bc < %s | llvm-bcanalyzer -dump | FileCheck --check-prefix=LTOINDEX %s
+// LTOINDEX: <FULL_LTO_GLOBALVAL_SUMMARY_BLOCK
+//
+// ; Simulate -save-temps and check that it works (!"ThinLTO" module flag not added multiple times)
+// RUN: %clang_cc1 -flto -triple x86_64-pc-linux-gnu -emit-llvm-bc -disable-llvm-passes < %s -o %t.bc
+// RUN: %clang_cc1 -flto -triple x86_64-pc-linux-gnu -emit-llvm-bc -x ir < %t.bc | llvm-bcanalyzer -dump | FileCheck --check-prefix=LTOINDEX %s
+
+int main() {}
diff --git a/test/CodeGen/exceptions-seh-finally.c b/test/CodeGen/exceptions-seh-finally.c
index 0f2123ba32bb..d863eb1bb47e 100644
--- a/test/CodeGen/exceptions-seh-finally.c
+++ b/test/CodeGen/exceptions-seh-finally.c
@@ -13,22 +13,22 @@ void basic_finally(void) {
}
}
-// CHECK-LABEL: define void @basic_finally()
+// CHECK-LABEL: define dso_local void @basic_finally()
// CHECK: invoke void @might_crash()
// CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
//
// CHECK: [[invoke_cont]]
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK: call void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
+// CHECK: call void @"?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
// CHECK-NEXT: ret void
//
// CHECK: [[lpad]]
// CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK: call void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
+// CHECK: call void @"?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
// CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
-// CHECK: define internal void @"\01?fin$0@0@basic_finally@@"({{.*}})
+// CHECK: define internal void @"?fin$0@0@basic_finally@@"({{.*}})
// CHECK-SAME: [[finally_attrs:#[0-9]+]]
// CHECK: call void @cleanup()
@@ -53,16 +53,16 @@ l:
}
}
-// CHECK-LABEL: define void @label_in_finally()
+// CHECK-LABEL: define dso_local void @label_in_finally()
// CHECK: invoke void @might_crash()
// CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
//
// CHECK: [[invoke_cont]]
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK: call void @"\01?fin$0@0@label_in_finally@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
+// CHECK: call void @"?fin$0@0@label_in_finally@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
// CHECK: ret void
-// CHECK: define internal void @"\01?fin$0@0@label_in_finally@@"({{.*}})
+// CHECK: define internal void @"?fin$0@0@label_in_finally@@"({{.*}})
// CHECK-SAME: [[finally_attrs]]
// CHECK: br label %[[l:[^ ]*]]
//
@@ -81,22 +81,22 @@ void use_abnormal_termination(void) {
}
}
-// CHECK-LABEL: define void @use_abnormal_termination()
+// CHECK-LABEL: define dso_local void @use_abnormal_termination()
// CHECK: invoke void @might_crash()
// CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
//
// CHECK: [[invoke_cont]]
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
+// CHECK: call void @"?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
// CHECK: ret void
//
// CHECK: [[lpad]]
// CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
+// CHECK: call void @"?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
// CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
-// CHECK: define internal void @"\01?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} %[[abnormal:abnormal_termination]], i8* %frame_pointer)
+// CHECK: define internal void @"?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} %[[abnormal:abnormal_termination]], i8* %frame_pointer)
// CHECK-SAME: [[finally_attrs]]
// CHECK: %[[abnormal_zext:[^ ]*]] = zext i8 %[[abnormal]] to i32
// CHECK: store i32 %[[abnormal_zext]], i32* @crashed
@@ -110,11 +110,11 @@ void noreturn_noop_finally() {
}
}
-// CHECK-LABEL: define void @noreturn_noop_finally()
-// CHECK: call void @"\01?fin$0@0@noreturn_noop_finally@@"({{.*}})
+// CHECK-LABEL: define dso_local void @noreturn_noop_finally()
+// CHECK: call void @"?fin$0@0@noreturn_noop_finally@@"({{.*}})
// CHECK: ret void
-// CHECK: define internal void @"\01?fin$0@0@noreturn_noop_finally@@"({{.*}})
+// CHECK: define internal void @"?fin$0@0@noreturn_noop_finally@@"({{.*}})
// CHECK-SAME: [[finally_attrs]]
// CHECK: call void @abort()
// CHECK: unreachable
@@ -127,20 +127,20 @@ void noreturn_finally() {
}
}
-// CHECK-LABEL: define void @noreturn_finally()
+// CHECK-LABEL: define dso_local void @noreturn_finally()
// CHECK: invoke void @might_crash()
// CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
//
// CHECK: [[cont]]
-// CHECK: call void @"\01?fin$0@0@noreturn_finally@@"({{.*}})
+// CHECK: call void @"?fin$0@0@noreturn_finally@@"({{.*}})
// CHECK: ret void
//
// CHECK: [[lpad]]
// CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
-// CHECK: call void @"\01?fin$0@0@noreturn_finally@@"({{.*}})
+// CHECK: call void @"?fin$0@0@noreturn_finally@@"({{.*}})
// CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
-// CHECK: define internal void @"\01?fin$0@0@noreturn_finally@@"({{.*}})
+// CHECK: define internal void @"?fin$0@0@noreturn_finally@@"({{.*}})
// CHECK-SAME: [[finally_attrs]]
// CHECK: call void @abort()
// CHECK: unreachable
@@ -151,11 +151,11 @@ int finally_with_return() {
} __finally {
}
}
-// CHECK-LABEL: define i32 @finally_with_return()
-// CHECK: call void @"\01?fin$0@0@finally_with_return@@"({{.*}})
+// CHECK-LABEL: define dso_local i32 @finally_with_return()
+// CHECK: call void @"?fin$0@0@finally_with_return@@"({{.*}})
// CHECK-NEXT: ret i32 42
-// CHECK: define internal void @"\01?fin$0@0@finally_with_return@@"({{.*}})
+// CHECK: define internal void @"?fin$0@0@finally_with_return@@"({{.*}})
// CHECK-SAME: [[finally_attrs]]
// CHECK-NOT: br i1
// CHECK-NOT: br label
@@ -173,24 +173,24 @@ int nested___finally___finally() {
return 0;
}
-// CHECK-LABEL: define i32 @nested___finally___finally
-// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally@@"({{.*}})
+// CHECK-LABEL: define dso_local i32 @nested___finally___finally
+// CHECK: invoke void @"?fin$1@0@nested___finally___finally@@"({{.*}})
// CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
//
// CHECK: [[outercont]]
-// CHECK: call void @"\01?fin$0@0@nested___finally___finally@@"({{.*}})
+// CHECK: call void @"?fin$0@0@nested___finally___finally@@"({{.*}})
// CHECK-NEXT: ret i32 0
//
// CHECK: [[lpad]]
// CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
-// CHECK: call void @"\01?fin$0@0@nested___finally___finally@@"({{.*}})
+// CHECK: call void @"?fin$0@0@nested___finally___finally@@"({{.*}})
// CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
-// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally@@"({{.*}})
+// CHECK-LABEL: define internal void @"?fin$0@0@nested___finally___finally@@"({{.*}})
// CHECK-SAME: [[finally_attrs]]
// CHECK: ret void
-// CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally@@"({{.*}})
+// CHECK-LABEL: define internal void @"?fin$1@0@nested___finally___finally@@"({{.*}})
// CHECK-SAME: [[finally_attrs]]
// CHECK: unreachable
@@ -208,21 +208,21 @@ int nested___finally___finally_with_eh_edge() {
}
return 912;
}
-// CHECK-LABEL: define i32 @nested___finally___finally_with_eh_edge
+// CHECK-LABEL: define dso_local i32 @nested___finally___finally_with_eh_edge
// CHECK: invoke void @might_crash()
// CHECK-NEXT: to label %[[invokecont:[^ ]*]] unwind label %[[lpad1:[^ ]*]]
//
// [[invokecont]]
-// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
+// CHECK: invoke void @"?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
// CHECK-NEXT: to label %[[outercont:[^ ]*]] unwind label %[[lpad2:[^ ]*]]
//
// CHECK: [[outercont]]
-// CHECK: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
+// CHECK: call void @"?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
// CHECK-NEXT: ret i32 912
//
// CHECK: [[lpad1]]
// CHECK-NEXT: %[[innerpad:[^ ]*]] = cleanuppad
-// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
+// CHECK: invoke void @"?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
// CHECK-NEXT: label %[[innercleanupretbb:[^ ]*]] unwind label %[[lpad2:[^ ]*]]
//
// CHECK: [[innercleanupretbb]]
@@ -230,14 +230,14 @@ int nested___finally___finally_with_eh_edge() {
//
// CHECK: [[lpad2]]
// CHECK-NEXT: %[[outerpad:[^ ]*]] = cleanuppad
-// CHECK: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
+// CHECK: call void @"?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
// CHECK-NEXT: cleanupret from %[[outerpad]] unwind to caller
-// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
+// CHECK-LABEL: define internal void @"?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
// CHECK-SAME: [[finally_attrs]]
// CHECK: ret void
-// CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
+// CHECK-LABEL: define internal void @"?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
// CHECK-SAME: [[finally_attrs]]
// CHECK: unreachable
@@ -252,22 +252,34 @@ void finally_within_finally() {
}
}
-// CHECK-LABEL: define void @finally_within_finally(
+// CHECK-LABEL: define dso_local void @finally_within_finally(
// CHECK: invoke void @might_crash(
-// CHECK: call void @"\01?fin$0@0@finally_within_finally@@"(
-// CHECK: call void @"\01?fin$0@0@finally_within_finally@@"({{.*}}) [ "funclet"(
+// CHECK: call void @"?fin$0@0@finally_within_finally@@"(
+// CHECK: call void @"?fin$0@0@finally_within_finally@@"({{.*}}) [ "funclet"(
-// CHECK-LABEL: define internal void @"\01?fin$0@0@finally_within_finally@@"({{[^)]*}})
+// CHECK-LABEL: define internal void @"?fin$0@0@finally_within_finally@@"({{[^)]*}})
// CHECK-SAME: [[finally_attrs]]
// CHECK: invoke void @might_crash(
-// CHECK: call void @"\01?fin$1@0@finally_within_finally@@"(
-// CHECK: call void @"\01?fin$1@0@finally_within_finally@@"({{.*}}) [ "funclet"(
+// CHECK: call void @"?fin$1@0@finally_within_finally@@"(
+// CHECK: call void @"?fin$1@0@finally_within_finally@@"({{.*}}) [ "funclet"(
-// CHECK-LABEL: define internal void @"\01?fin$1@0@finally_within_finally@@"({{[^)]*}})
+// CHECK-LABEL: define internal void @"?fin$1@0@finally_within_finally@@"({{[^)]*}})
// CHECK-SAME: [[finally_attrs]]
+void cleanup_with_func(const char *);
+void finally_with_func() {
+ __try {
+ might_crash();
+ } __finally {
+ cleanup_with_func(__func__);
+ }
+}
+
+// CHECK-LABEL: define internal void @"?fin$0@0@finally_with_func@@"({{[^)]*}})
+// CHECK: call void @cleanup_with_func(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @"??_C@_0BC@COAGBPGM@finally_with_func?$AA@", i32 0, i32 0))
+
// Look for the absence of noinline. Enum attributes come first, so check that
// a string attribute is the first to verify that no enum attributes are
// present.
diff --git a/test/CodeGen/exceptions-seh-leave.c b/test/CodeGen/exceptions-seh-leave.c
index 087fadbcd7ab..e977e32e9fa4 100644
--- a/test/CodeGen/exceptions-seh-leave.c
+++ b/test/CodeGen/exceptions-seh-leave.c
@@ -17,7 +17,7 @@ int __leave_with___except_simple() {
}
return 1;
}
-// CHECK-LABEL: define i32 @__leave_with___except_simple()
+// CHECK-LABEL: define dso_local i32 @__leave_with___except_simple()
// CHECK: store i32 15, i32* %myres
// CHECK-NEXT: br label %[[tryleave:[^ ]*]]
// CHECK-NOT: store i32 23
@@ -37,7 +37,7 @@ int __leave_with___except() {
}
return 1;
}
-// CHECK-LABEL: define i32 @__leave_with___except()
+// CHECK-LABEL: define dso_local i32 @__leave_with___except()
// CHECK: invoke void @g()
// CHECK-NEXT: to label %[[cont:.*]] unwind label %{{.*}}
// For __excepts, instead of an explicit __try.__leave label, we could use
@@ -69,13 +69,13 @@ int __leave_with___finally_simple() {
}
return 1;
}
-// CHECK-LABEL: define i32 @__leave_with___finally_simple()
+// CHECK-LABEL: define dso_local i32 @__leave_with___finally_simple()
// CHECK: store i32 15, i32* %myres
// CHECK-NEXT: br label %[[tryleave:[^ ]*]]
// CHECK-NOT: store i32 23
// CHECK: [[tryleave]]
// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK-NEXT: call void @"\01?fin$0@0@__leave_with___finally_simple@@"(i8 0, i8* %[[fp]])
+// CHECK-NEXT: call void @"?fin$0@0@__leave_with___finally_simple@@"(i8 0, i8* %[[fp]])
// __finally block doesn't return, __finally.cont doesn't exist.
int __leave_with___finally_noreturn() {
@@ -89,13 +89,13 @@ int __leave_with___finally_noreturn() {
}
return 1;
}
-// CHECK-LABEL: define i32 @__leave_with___finally_noreturn()
+// CHECK-LABEL: define dso_local i32 @__leave_with___finally_noreturn()
// CHECK: store i32 15, i32* %myres
// CHECK-NEXT: br label %[[tryleave:[^ ]*]]
// CHECK-NOT: store i32 23
// CHECK: [[tryleave]]
// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK-NEXT: call void @"\01?fin$0@0@__leave_with___finally_noreturn@@"(i8 0, i8* %[[fp]])
+// CHECK-NEXT: call void @"?fin$0@0@__leave_with___finally_noreturn@@"(i8 0, i8* %[[fp]])
// The "normal" case.
int __leave_with___finally() {
@@ -109,7 +109,7 @@ int __leave_with___finally() {
}
return 1;
}
-// CHECK-LABEL: define i32 @__leave_with___finally()
+// CHECK-LABEL: define dso_local i32 @__leave_with___finally()
// CHECK: invoke void @g()
// CHECK-NEXT: to label %[[cont:.*]] unwind label %{{.*}}
// For __finally, there needs to be an explicit __try.__leave, because
@@ -119,7 +119,7 @@ int __leave_with___finally() {
// CHECK-NOT: store i32 23
// CHECK: [[tryleave]]
// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK-NEXT: call void @"\01?fin$0@0@__leave_with___finally@@"(i8 0, i8* %[[fp]])
+// CHECK-NEXT: call void @"?fin$0@0@__leave_with___finally@@"(i8 0, i8* %[[fp]])
//////////////////////////////////////////////////////////////////////////////
@@ -142,14 +142,14 @@ int nested___except___finally() {
}
return 1;
}
-// CHECK-LABEL: define i32 @nested___except___finally()
+// CHECK-LABEL: define dso_local i32 @nested___except___finally()
// CHECK-LABEL: invoke void @g()
// CHECK-NEXT: to label %[[g1_cont1:.*]] unwind label %[[g1_lpad:.*]]
// CHECK: [[g1_cont1]]
// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK-NEXT: invoke void @"\01?fin$0@0@nested___except___finally@@"(i8 0, i8* %[[fp]])
+// CHECK-NEXT: invoke void @"?fin$0@0@nested___except___finally@@"(i8 0, i8* %[[fp]])
// CHECK-NEXT: to label %[[fin_cont:.*]] unwind label %[[g2_lpad:.*]]
// CHECK: [[fin_cont]]
@@ -159,7 +159,7 @@ int nested___except___finally() {
// CHECK: [[g1_lpad]]
// CHECK-NEXT: cleanuppad
// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK-NEXT: invoke void @"\01?fin$0@0@nested___except___finally@@"(i8 1, i8* %[[fp]])
+// CHECK-NEXT: invoke void @"?fin$0@0@nested___except___finally@@"(i8 1, i8* %[[fp]])
// CHECK-NEXT: to label %[[g1_resume:.*]] unwind label %[[g2_lpad]]
// CHECK: cleanupret {{.*}} unwind label %[[g2_lpad]]
@@ -171,7 +171,7 @@ int nested___except___finally() {
// CHECK: [[trycont]]
// CHECK-NEXT: ret i32 1
-// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___except___finally@@"(i8 %abnormal_termination, i8* %frame_pointer)
+// CHECK-LABEL: define internal void @"?fin$0@0@nested___except___finally@@"(i8 %abnormal_termination, i8* %frame_pointer)
// CHECK: call void @g()
// CHECK: unreachable
@@ -194,7 +194,7 @@ int nested___except___except() {
return 1;
}
// The order of basic blocks in the below doesn't matter.
-// CHECK-LABEL: define i32 @nested___except___except()
+// CHECK-LABEL: define dso_local i32 @nested___except___except()
// CHECK-LABEL: invoke void @g()
// CHECK-NEXT: to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]]
@@ -247,7 +247,7 @@ int nested___finally___except() {
return 1;
}
// The order of basic blocks in the below doesn't matter.
-// CHECK-LABEL: define i32 @nested___finally___except()
+// CHECK-LABEL: define dso_local i32 @nested___finally___except()
// CHECK-LABEL: invoke void @g()
// CHECK-NEXT: to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]]
@@ -271,16 +271,16 @@ int nested___finally___except() {
// CHECK: [[tryleave]]
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___except@@"(i8 0, i8* %[[fp]])
+// CHECK-NEXT: call void @"?fin$0@0@nested___finally___except@@"(i8 0, i8* %[[fp]])
// CHECK-NEXT: ret i32 1
// CHECK: [[g2_lpad]]
// CHECK: cleanuppad
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___except@@"(i8 1, i8* %[[fp]])
+// CHECK-NEXT: call void @"?fin$0@0@nested___finally___except@@"(i8 1, i8* %[[fp]])
// CHECK: cleanupret {{.*}} unwind to caller
-// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___except@@"(i8 %abnormal_termination, i8* %frame_pointer)
+// CHECK-LABEL: define internal void @"?fin$0@0@nested___finally___except@@"(i8 %abnormal_termination, i8* %frame_pointer)
// CHECK: ret void
int nested___finally___finally() {
@@ -302,7 +302,7 @@ int nested___finally___finally() {
return 1;
}
// The order of basic blocks in the below doesn't matter.
-// CHECK-LABEL: define i32 @nested___finally___finally()
+// CHECK-LABEL: define dso_local i32 @nested___finally___finally()
// CHECK: invoke void @g()
// CHECK-NEXT: to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]]
@@ -310,19 +310,19 @@ int nested___finally___finally() {
// CHECK: [[g1_cont]]
// CHECK: store i32 16, i32* %[[myres:[^ ]*]],
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK-NEXT: invoke void @"\01?fin$1@0@nested___finally___finally@@"(i8 0, i8* %[[fp]])
+// CHECK-NEXT: invoke void @"?fin$1@0@nested___finally___finally@@"(i8 0, i8* %[[fp]])
// CHECK-NEXT: to label %[[finally_cont:.*]] unwind label %[[g2_lpad:.*]]
// CHECK: [[finally_cont]]
// CHECK: store i32 51, i32* %[[myres]]
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i8 0, i8* %[[fp]])
+// CHECK-NEXT: call void @"?fin$0@0@nested___finally___finally@@"(i8 0, i8* %[[fp]])
// CHECK-NEXT: ret i32 1
// CHECK: [[g1_lpad]]
// CHECK-NEXT: %[[padtoken:[^ ]*]] = cleanuppad within none []
// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK-NEXT: invoke void @"\01?fin$1@0@nested___finally___finally@@"(i8 1, i8* %[[fp]])
+// CHECK-NEXT: invoke void @"?fin$1@0@nested___finally___finally@@"(i8 1, i8* %[[fp]])
// CHECK-NEXT: to label %[[finally_cont2:.*]] unwind label %[[g2_lpad]]
// CHECK: [[finally_cont2]]
// CHECK: cleanupret from %[[padtoken]] unwind label %[[g2_lpad]]
@@ -330,12 +330,12 @@ int nested___finally___finally() {
// CHECK: [[g2_lpad]]
// CHECK-NEXT: %[[padtoken:[^ ]*]] = cleanuppad within none []
// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i8 1, i8* %[[fp]])
+// CHECK-NEXT: call void @"?fin$0@0@nested___finally___finally@@"(i8 1, i8* %[[fp]])
// CHECK: cleanupret from %[[padtoken]] unwind to caller
-// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally@@"(i8 %abnormal_termination, i8* %frame_pointer)
+// CHECK-LABEL: define internal void @"?fin$0@0@nested___finally___finally@@"(i8 %abnormal_termination, i8* %frame_pointer)
// CHECK: ret void
-// CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally@@"(i8 %abnormal_termination, i8* %frame_pointer)
+// CHECK-LABEL: define internal void @"?fin$1@0@nested___finally___finally@@"(i8 %abnormal_termination, i8* %frame_pointer)
// CHECK: call void @g()
// CHECK: unreachable
diff --git a/test/CodeGen/exceptions-seh.c b/test/CodeGen/exceptions-seh.c
index a0a1dbccd158..b38c7a2490c0 100644
--- a/test/CodeGen/exceptions-seh.c
+++ b/test/CodeGen/exceptions-seh.c
@@ -10,7 +10,7 @@
void try_body(int numerator, int denominator, int *myres) {
*myres = numerator / denominator;
}
-// CHECK-LABEL: define void @try_body(i32 %numerator, i32 %denominator, i32* %myres)
+// CHECK-LABEL: define dso_local void @try_body(i32 %numerator, i32 %denominator, i32* %myres)
// CHECK: sdiv i32
// CHECK: store i32 %{{.*}}, i32*
// CHECK: ret void
@@ -27,7 +27,7 @@ int safe_div(int numerator, int denominator, int *res) {
return success;
}
-// CHECK-LABEL: define i32 @safe_div(i32 %numerator, i32 %denominator, i32* %res)
+// CHECK-LABEL: define dso_local i32 @safe_div(i32 %numerator, i32 %denominator, i32* %res)
// X64-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
// X86-SAME: personality i8* bitcast (i32 (...)* @_except_handler3 to i8*)
// CHECK: invoke void @try_body(i32 %{{.*}}, i32 %{{.*}}, i32* %{{.*}}) #[[NOINLINE:[0-9]+]]
@@ -35,7 +35,7 @@ int safe_div(int numerator, int denominator, int *res) {
//
// CHECK: [[catchpad]]
// X64: %[[padtoken:[^ ]*]] = catchpad within %{{[^ ]*}} [i8* null]
-// X86: %[[padtoken:[^ ]*]] = catchpad within %{{[^ ]*}} [i8* bitcast (i32 ()* @"\01?filt$0@0@safe_div@@" to i8*)]
+// X86: %[[padtoken:[^ ]*]] = catchpad within %{{[^ ]*}} [i8* bitcast (i32 ()* @"?filt$0@0@safe_div@@" to i8*)]
// CHECK-NEXT: catchret from %[[padtoken]] to label %[[except:[^ ]*]]
//
// CHECK: [[except]]
@@ -46,7 +46,7 @@ int safe_div(int numerator, int denominator, int *res) {
// 32-bit SEH needs this filter to save the exception code.
//
-// X86-LABEL: define internal i32 @"\01?filt$0@0@safe_div@@"()
+// X86-LABEL: define internal i32 @"?filt$0@0@safe_div@@"()
// X86: %[[ebp:[^ ]*]] = call i8* @llvm.frameaddress(i32 1)
// X86: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 (i32, i32, i32*)* @safe_div to i8*), i8* %[[ebp]])
// X86: call i8* @llvm.localrecover(i8* bitcast (i32 (i32, i32, i32*)* @safe_div to i8*), i8* %[[fp]], i32 0)
@@ -57,9 +57,9 @@ int safe_div(int numerator, int denominator, int *res) {
// X86: ret i32 1
// Mingw uses msvcrt, so it can also use _except_handler3.
-// X86-GNU-LABEL: define i32 @safe_div(i32 %numerator, i32 %denominator, i32* %res)
+// X86-GNU-LABEL: define dso_local i32 @safe_div(i32 %numerator, i32 %denominator, i32* %res)
// X86-GNU-SAME: personality i8* bitcast (i32 (...)* @_except_handler3 to i8*)
-// X64-GNU-LABEL: define i32 @safe_div(i32 %numerator, i32 %denominator, i32* %res)
+// X64-GNU-LABEL: define dso_local i32 @safe_div(i32 %numerator, i32 %denominator, i32* %res)
// X64-GNU-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
void j(void);
@@ -74,7 +74,7 @@ int filter_expr_capture(void) {
return r;
}
-// CHECK-LABEL: define i32 @filter_expr_capture()
+// CHECK-LABEL: define dso_local i32 @filter_expr_capture()
// X64-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
// X86-SAME: personality i8* bitcast (i32 (...)* @_except_handler3 to i8*)
// X64: call void (...) @llvm.localescape(i32* %[[r:[^ ,]*]])
@@ -82,17 +82,17 @@ int filter_expr_capture(void) {
// CHECK: store i32 42, i32* %[[r]]
// CHECK: invoke void @j() #[[NOINLINE]]
//
-// CHECK: catchpad within %{{[^ ]*}} [i8* bitcast (i32 ({{.*}})* @"\01?filt$0@0@filter_expr_capture@@" to i8*)]
+// CHECK: catchpad within %{{[^ ]*}} [i8* bitcast (i32 ({{.*}})* @"?filt$0@0@filter_expr_capture@@" to i8*)]
// CHECK: store i32 13, i32* %[[r]]
//
// CHECK: %[[rv:[^ ]*]] = load i32, i32* %[[r]]
// CHECK: ret i32 %[[rv]]
-// X64-LABEL: define internal i32 @"\01?filt$0@0@filter_expr_capture@@"(i8* %exception_pointers, i8* %frame_pointer)
+// X64-LABEL: define internal i32 @"?filt$0@0@filter_expr_capture@@"(i8* %exception_pointers, i8* %frame_pointer)
// X64: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %frame_pointer)
// X64: call i8* @llvm.localrecover(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %[[fp]], i32 0)
//
-// X86-LABEL: define internal i32 @"\01?filt$0@0@filter_expr_capture@@"()
+// X86-LABEL: define internal i32 @"?filt$0@0@filter_expr_capture@@"()
// X86: %[[ebp:[^ ]*]] = call i8* @llvm.frameaddress(i32 1)
// X86: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %[[ebp]])
// X86: call i8* @llvm.localrecover(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %[[fp]], i32 0)
@@ -114,7 +114,7 @@ int nested_try(void) {
}
return r;
}
-// CHECK-LABEL: define i32 @nested_try()
+// CHECK-LABEL: define dso_local i32 @nested_try()
// X64-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
// X86-SAME: personality i8* bitcast (i32 (...)* @_except_handler3 to i8*)
// CHECK: store i32 42, i32* %[[r:[^ ,]*]]
@@ -128,7 +128,7 @@ int nested_try(void) {
// CHECK: %[[cs_outer:[^ ]*]] = catchswitch within none [label %[[cpad_outer:[^ ]*]]] unwind to caller
//
// CHECK: [[cpad_outer]]
-// CHECK: catchpad within %{{[^ ]*}} [i8* bitcast (i32 ({{.*}})* @"\01?filt$0@0@nested_try@@" to i8*)]
+// CHECK: catchpad within %{{[^ ]*}} [i8* bitcast (i32 ({{.*}})* @"?filt$0@0@nested_try@@" to i8*)]
// CHECK-NEXT: catchret {{.*}} to label %[[except_outer:[^ ]*]]
//
// CHECK: [[except_outer]]
@@ -140,7 +140,7 @@ int nested_try(void) {
// CHECK: ret i32 %[[r_load]]
//
// CHECK: [[cpad_inner]]
-// CHECK: catchpad within %[[cs_inner]] [i8* bitcast (i32 ({{.*}})* @"\01?filt$1@0@nested_try@@" to i8*)]
+// CHECK: catchpad within %[[cs_inner]] [i8* bitcast (i32 ({{.*}})* @"?filt$1@0@nested_try@@" to i8*)]
// CHECK-NEXT: catchret {{.*}} to label %[[except_inner:[^ ]*]]
//
// CHECK: [[except_inner]]
@@ -154,13 +154,13 @@ int nested_try(void) {
// CHECK: store i32 0, i32* %[[r]]
// CHECK: br label %[[inner_try_cont]]
//
-// CHECK-LABEL: define internal i32 @"\01?filt$0@0@nested_try@@"({{.*}})
+// CHECK-LABEL: define internal i32 @"?filt$0@0@nested_try@@"({{.*}})
// X86: call i8* @llvm.x86.seh.recoverfp({{.*}})
// CHECK: load i32*, i32**
// CHECK: load i32, i32*
// CHECK: icmp eq i32 %{{.*}}, 456
//
-// CHECK-LABEL: define internal i32 @"\01?filt$1@0@nested_try@@"({{.*}})
+// CHECK-LABEL: define internal i32 @"?filt$1@0@nested_try@@"({{.*}})
// X86: call i8* @llvm.x86.seh.recoverfp({{.*}})
// CHECK: load i32*, i32**
// CHECK: load i32, i32*
@@ -174,7 +174,7 @@ int basic_finally(int g) {
}
return g;
}
-// CHECK-LABEL: define i32 @basic_finally(i32 %g)
+// CHECK-LABEL: define dso_local i32 @basic_finally(i32 %g)
// X64-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
// X86-SAME: personality i8* bitcast (i32 (...)* @_except_handler3 to i8*)
// CHECK: %[[g_addr:[^ ]*]] = alloca i32, align 4
@@ -186,17 +186,17 @@ int basic_finally(int g) {
//
// CHECK: [[cont]]
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK: call void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
+// CHECK: call void @"?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
// CHECK: load i32, i32* %[[g_addr]], align 4
// CHECK: ret i32
//
// CHECK: [[cleanuppad]]
// CHECK: %[[padtoken:[^ ]*]] = cleanuppad within none []
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK: call void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
+// CHECK: call void @"?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
// CHECK: cleanupret from %[[padtoken]] unwind to caller
-// CHECK: define internal void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} %abnormal_termination, i8* %frame_pointer)
+// CHECK: define internal void @"?fin$0@0@basic_finally@@"({{i8( zeroext)?}} %abnormal_termination, i8* %frame_pointer)
// CHECK: call i8* @llvm.localrecover(i8* bitcast (i32 (i32)* @basic_finally to i8*), i8* %frame_pointer, i32 0)
// CHECK: load i32, i32* %{{.*}}, align 4
// CHECK: add nsw i32 %{{.*}}, 1
@@ -211,7 +211,7 @@ int except_return(void) {
return 42;
}
}
-// CHECK-LABEL: define i32 @except_return()
+// CHECK-LABEL: define dso_local i32 @except_return()
// CHECK: %[[tmp:[^ ]*]] = invoke i32 @returns_int()
// CHECK: to label %[[cont:[^ ]*]] unwind label %[[catchpad:[^ ]*]]
//
@@ -240,7 +240,7 @@ void finally_capture_twice(int x) {
}
}
//
-// CHECK-LABEL: define void @finally_capture_twice(
+// CHECK-LABEL: define dso_local void @finally_capture_twice(
// CHECK: [[X:%.*]] = alloca i32, align 4
// CHECK: call void (...) @llvm.localescape(i32* [[X]])
// CHECK-NEXT: store i32 {{.*}}, i32* [[X]], align 4
@@ -267,7 +267,7 @@ int exception_code_in_except(void) {
}
}
-// CHECK-LABEL: define i32 @exception_code_in_except()
+// CHECK-LABEL: define dso_local i32 @exception_code_in_except()
// CHECK: %[[ret_slot:[^ ]*]] = alloca i32
// CHECK: %[[code_slot:[^ ]*]] = alloca i32
// CHECK: invoke void @try_body(i32 0, i32 0, i32* null)
diff --git a/test/CodeGen/ext-vector.c b/test/CodeGen/ext-vector.c
index beb58827ea13..faa6ede6a24d 100644
--- a/test/CodeGen/ext-vector.c
+++ b/test/CodeGen/ext-vector.c
@@ -5,10 +5,10 @@ typedef __attribute__(( ext_vector_type(2) )) float float2;
typedef __attribute__(( ext_vector_type(4) )) int int4;
typedef __attribute__(( ext_vector_type(4) )) unsigned int uint4;
-// CHECK: @foo = global <4 x float> <float 1.000000e+00, float 2.000000e+00, float 3.000000e+00, float 4.000000e+00>
+// CHECK: @foo = {{(dso_local )?}}global <4 x float> <float 1.000000e+00, float 2.000000e+00, float 3.000000e+00, float 4.000000e+00>
float4 foo = (float4){ 1.0, 2.0, 3.0, 4.0 };
-// CHECK: @bar = constant <4 x float> <float 1.000000e+00, float 2.000000e+00, float 3.000000e+00, float 0x7FF0000000000000>
+// CHECK: @bar = {{(dso_local )?}}constant <4 x float> <float 1.000000e+00, float 2.000000e+00, float 3.000000e+00, float 0x7FF0000000000000>
const float4 bar = (float4){ 1.0, 2.0, 3.0, __builtin_inff() };
// CHECK: @test1
diff --git a/test/CodeGen/f16c-builtins.c b/test/CodeGen/f16c-builtins.c
index e4933e9f9bf3..ce14187cdad3 100644
--- a/test/CodeGen/f16c-builtins.c
+++ b/test/CodeGen/f16c-builtins.c
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +f16c -emit-llvm -o - -Wall -Werror | FileCheck %s
-#include <x86intrin.h>
+#include <immintrin.h>
float test_cvtsh_ss(unsigned short a) {
// CHECK-LABEL: test_cvtsh_ss
diff --git a/test/CodeGen/fentry.c b/test/CodeGen/fentry.c
index b9133184e4d4..43586c45633d 100644
--- a/test/CodeGen/fentry.c
+++ b/test/CodeGen/fentry.c
@@ -7,5 +7,12 @@ int foo(void) {
return 0;
}
-//CHECK: attributes #{{[0-9]+}} = { {{.*}}"fentry-call"="true"{{.*}} }
-//NOPG-NOT: attributes #{{[0-9]+}} = { {{.*}}"fentry-call"{{.*}} }
+int __attribute__((no_instrument_function)) no_instrument(void) {
+ return foo();
+}
+
+//CHECK: attributes #0 = { {{.*}}"fentry-call"="true"{{.*}} }
+//CHECK: attributes #1 = { {{.*}} }
+//CHECK-NOT: attributes #1 = { {{.*}}"fentry-call"="true"{{.*}} }
+//NOPG-NOT: attributes #0 = { {{.*}}"fentry-call"{{.*}} }
+//NOPG-NOT: attributes #1 = { {{.*}}"fentry-call"{{.*}} }
diff --git a/test/CodeGen/fixup-depth-overflow.c b/test/CodeGen/fixup-depth-overflow.c
index af452d05b643..1ae2a41b1c26 100644
--- a/test/CodeGen/fixup-depth-overflow.c
+++ b/test/CodeGen/fixup-depth-overflow.c
@@ -22,5 +22,5 @@ L1:
return;
}
-// CHECK-LABEL: define void @f
+// CHECK-LABEL: define {{(dso_local )?}}void @f
// CHECK-NOT: cleanup
diff --git a/test/CodeGen/flip-dllimport.c b/test/CodeGen/flip-dllimport.c
new file mode 100644
index 000000000000..d20479d8f6e8
--- /dev/null
+++ b/test/CodeGen/flip-dllimport.c
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-extensions -emit-llvm -o - %s | FileCheck %s
+
+__declspec(dllimport) void f();
+void g() { f(); } // use it
+
+// CHECK: define dso_local dllexport void @f
+void f() { }
diff --git a/test/CodeGen/fma-builtins.c b/test/CodeGen/fma-builtins.c
index 6f792a78d84c..ff047f3d8374 100644
--- a/test/CodeGen/fma-builtins.c
+++ b/test/CodeGen/fma-builtins.c
@@ -5,81 +5,105 @@
__m128 test_mm_fmadd_ps(__m128 a, __m128 b, __m128 c) {
// CHECK-LABEL: test_mm_fmadd_ps
- // CHECK: @llvm.x86.fma.vfmadd.ps
+ // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
return _mm_fmadd_ps(a, b, c);
}
__m128d test_mm_fmadd_pd(__m128d a, __m128d b, __m128d c) {
// CHECK-LABEL: test_mm_fmadd_pd
- // CHECK: @llvm.x86.fma.vfmadd.pd
+ // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
return _mm_fmadd_pd(a, b, c);
}
__m128 test_mm_fmadd_ss(__m128 a, __m128 b, __m128 c) {
// CHECK-LABEL: test_mm_fmadd_ss
- // CHECK: @llvm.x86.fma.vfmadd.ss
+ // CHECK: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK: call float @llvm.fma.f32(float %{{.*}}, float %{{.*}}, float %{{.*}})
+ // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0
return _mm_fmadd_ss(a, b, c);
}
__m128d test_mm_fmadd_sd(__m128d a, __m128d b, __m128d c) {
// CHECK-LABEL: test_mm_fmadd_sd
- // CHECK: @llvm.x86.fma.vfmadd.sd
+ // CHECK: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK: call double @llvm.fma.f64(double %{{.*}}, double %{{.*}}, double %{{.*}})
+ // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0
return _mm_fmadd_sd(a, b, c);
}
__m128 test_mm_fmsub_ps(__m128 a, __m128 b, __m128 c) {
// CHECK-LABEL: test_mm_fmsub_ps
// CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma.vfmadd.ps(<4 x float> %{{.+}}, <4 x float> %{{.+}}, <4 x float> [[NEG]])
+ // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
return _mm_fmsub_ps(a, b, c);
}
__m128d test_mm_fmsub_pd(__m128d a, __m128d b, __m128d c) {
// CHECK-LABEL: test_mm_fmsub_pd
// CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma.vfmadd.pd(<2 x double> %{{.+}}, <2 x double> %{{.+}}, <2 x double> [[NEG]])
+ // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
return _mm_fmsub_pd(a, b, c);
}
__m128 test_mm_fmsub_ss(__m128 a, __m128 b, __m128 c) {
// CHECK-LABEL: test_mm_fmsub_ss
// CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma.vfmadd.ss(<4 x float> %{{.+}}, <4 x float> %{{.+}}, <4 x float> [[NEG]])
+ // CHECK: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK: call float @llvm.fma.f32(float %{{.*}}, float %{{.*}}, float %{{.*}})
+ // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0
return _mm_fmsub_ss(a, b, c);
}
__m128d test_mm_fmsub_sd(__m128d a, __m128d b, __m128d c) {
// CHECK-LABEL: test_mm_fmsub_sd
// CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma.vfmadd.sd(<2 x double> %{{.+}}, <2 x double> %{{.+}}, <2 x double> [[NEG]])
+ // CHECK: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK: call double @llvm.fma.f64(double %{{.*}}, double %{{.*}}, double %{{.*}})
+ // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0
return _mm_fmsub_sd(a, b, c);
}
__m128 test_mm_fnmadd_ps(__m128 a, __m128 b, __m128 c) {
// CHECK-LABEL: test_mm_fnmadd_ps
// CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma.vfmadd.ps(<4 x float> [[NEG]], <4 x float> %{{.+}}, <4 x float> %{{.+}})
+ // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
return _mm_fnmadd_ps(a, b, c);
}
__m128d test_mm_fnmadd_pd(__m128d a, __m128d b, __m128d c) {
// CHECK-LABEL: test_mm_fnmadd_pd
// CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma.vfmadd.pd(<2 x double> [[NEG]], <2 x double> %{{.+}}, <2 x double> %{{.+}})
+ // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
return _mm_fnmadd_pd(a, b, c);
}
__m128 test_mm_fnmadd_ss(__m128 a, __m128 b, __m128 c) {
// CHECK-LABEL: test_mm_fnmadd_ss
// CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma.vfmadd.ss(<4 x float> %{{.+}}, <4 x float> [[NEG]], <4 x float> %{{.+}})
+ // CHECK: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK: call float @llvm.fma.f32(float %{{.*}}, float %{{.*}}, float %{{.*}})
+ // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0
return _mm_fnmadd_ss(a, b, c);
}
__m128d test_mm_fnmadd_sd(__m128d a, __m128d b, __m128d c) {
// CHECK-LABEL: test_mm_fnmadd_sd
// CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma.vfmadd.sd(<2 x double> %{{.+}}, <2 x double> [[NEG]], <2 x double> %{{.+}})
+ // CHECK: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK: call double @llvm.fma.f64(double %{{.*}}, double %{{.*}}, double %{{.*}})
+ // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0
return _mm_fnmadd_sd(a, b, c);
}
@@ -87,7 +111,7 @@ __m128 test_mm_fnmsub_ps(__m128 a, __m128 b, __m128 c) {
// CHECK-LABEL: test_mm_fnmsub_ps
// CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.+}}
// CHECK: [[NEG2:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma.vfmadd.ps(<4 x float> [[NEG]], <4 x float> %{{.+}}, <4 x float> [[NEG2]])
+ // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
return _mm_fnmsub_ps(a, b, c);
}
@@ -95,7 +119,7 @@ __m128d test_mm_fnmsub_pd(__m128d a, __m128d b, __m128d c) {
// CHECK-LABEL: test_mm_fnmsub_pd
// CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.+}}
// CHECK: [[NEG2:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma.vfmadd.pd(<2 x double> [[NEG]], <2 x double> %{{.+}}, <2 x double> [[NEG2]])
+ // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
return _mm_fnmsub_pd(a, b, c);
}
@@ -103,7 +127,11 @@ __m128 test_mm_fnmsub_ss(__m128 a, __m128 b, __m128 c) {
// CHECK-LABEL: test_mm_fnmsub_ss
// CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.+}}
// CHECK: [[NEG2:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma.vfmadd.ss(<4 x float> %{{.+}}, <4 x float> [[NEG]], <4 x float> [[NEG2]])
+ // CHECK: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK: call float @llvm.fma.f32(float %{{.*}}, float %{{.*}}, float %{{.*}})
+ // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0
return _mm_fnmsub_ss(a, b, c);
}
@@ -111,73 +139,87 @@ __m128d test_mm_fnmsub_sd(__m128d a, __m128d b, __m128d c) {
// CHECK-LABEL: test_mm_fnmsub_sd
// CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.+}}
// CHECK: [[NEG2:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma.vfmadd.sd(<2 x double> %{{.+}}, <2 x double> [[NEG]], <2 x double> [[NEG2]])
+ // CHECK: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK: call double @llvm.fma.f64(double %{{.*}}, double %{{.*}}, double %{{.*}})
+ // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0
return _mm_fnmsub_sd(a, b, c);
}
__m128 test_mm_fmaddsub_ps(__m128 a, __m128 b, __m128 c) {
// CHECK-LABEL: test_mm_fmaddsub_ps
- // CHECK: @llvm.x86.fma.vfmaddsub.ps
+ // CHECK: [[ADD:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.+}}
+ // CHECK: [[SUB:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]]
+ // CHECK: shufflevector <4 x float> [[SUB]], <4 x float> [[ADD]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
return _mm_fmaddsub_ps(a, b, c);
}
__m128d test_mm_fmaddsub_pd(__m128d a, __m128d b, __m128d c) {
// CHECK-LABEL: test_mm_fmaddsub_pd
- // CHECK: @llvm.x86.fma.vfmaddsub.pd
+ // CHECK: [[ADD:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.+}}
+ // CHECK: [[SUB:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]]
+ // CHECK: shufflevector <2 x double> [[SUB]], <2 x double> [[ADD]], <2 x i32> <i32 0, i32 3>
return _mm_fmaddsub_pd(a, b, c);
}
__m128 test_mm_fmsubadd_ps(__m128 a, __m128 b, __m128 c) {
// CHECK-LABEL: test_mm_fmsubadd_ps
// CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma.vfmaddsub.ps(<4 x float> %{{.+}}, <4 x float> %{{.+}}, <4 x float> [[NEG]])
+ // CHECK: [[SUB:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]]
+ // CHECK: [[ADD:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK: shufflevector <4 x float> [[ADD]], <4 x float> [[SUB]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
return _mm_fmsubadd_ps(a, b, c);
}
__m128d test_mm_fmsubadd_pd(__m128d a, __m128d b, __m128d c) {
// CHECK-LABEL: test_mm_fmsubadd_pd
// CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma.vfmaddsub.pd(<2 x double> %{{.+}}, <2 x double> %{{.+}}, <2 x double> [[NEG]])
+ // CHECK: [[SUB:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]]
+ // CHECK: [[ADD:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK: shufflevector <2 x double> [[ADD]], <2 x double> [[SUB]], <2 x i32> <i32 0, i32 3>
return _mm_fmsubadd_pd(a, b, c);
}
__m256 test_mm256_fmadd_ps(__m256 a, __m256 b, __m256 c) {
// CHECK-LABEL: test_mm256_fmadd_ps
- // CHECK: @llvm.x86.fma.vfmadd.ps.256
+ // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}})
return _mm256_fmadd_ps(a, b, c);
}
__m256d test_mm256_fmadd_pd(__m256d a, __m256d b, __m256d c) {
// CHECK-LABEL: test_mm256_fmadd_pd
- // CHECK: @llvm.x86.fma.vfmadd.pd.256
+ // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
return _mm256_fmadd_pd(a, b, c);
}
__m256 test_mm256_fmsub_ps(__m256 a, __m256 b, __m256 c) {
// CHECK-LABEL: test_mm256_fmsub_ps
// CHECK: [[NEG:%.+]] = fsub <8 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
- // CHECK: @llvm.x86.fma.vfmadd.ps.256(<8 x float> %{{.+}}, <8 x float> %{{.+}}, <8 x float> [[NEG]])
+ // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}})
return _mm256_fmsub_ps(a, b, c);
}
__m256d test_mm256_fmsub_pd(__m256d a, __m256d b, __m256d c) {
// CHECK-LABEL: test_mm256_fmsub_pd
// CHECK: [[NEG:%.+]] = fsub <4 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma.vfmadd.pd.256(<4 x double> %{{.+}}, <4 x double> %{{.+}}, <4 x double> [[NEG]])
+ // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
return _mm256_fmsub_pd(a, b, c);
}
__m256 test_mm256_fnmadd_ps(__m256 a, __m256 b, __m256 c) {
// CHECK-LABEL: test_mm256_fnmadd_ps
// CHECK: [[NEG:%.+]] = fsub <8 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
- // CHECK: @llvm.x86.fma.vfmadd.ps.256(<8 x float> [[NEG]], <8 x float> %{{.+}}, <8 x float> %{{.+}})
+ // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}})
return _mm256_fnmadd_ps(a, b, c);
}
__m256d test_mm256_fnmadd_pd(__m256d a, __m256d b, __m256d c) {
// CHECK-LABEL: test_mm256_fnmadd_pd
// CHECK: [[NEG:%.+]] = fsub <4 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma.vfmadd.pd.256(<4 x double> [[NEG]], <4 x double> %{{.+}}, <4 x double> %{{.+}})
+ // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
return _mm256_fnmadd_pd(a, b, c);
}
@@ -185,7 +227,7 @@ __m256 test_mm256_fnmsub_ps(__m256 a, __m256 b, __m256 c) {
// CHECK-LABEL: test_mm256_fnmsub_ps
// CHECK: [[NEG:%.+]] = fsub <8 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
// CHECK: [[NEG2:%.+]] = fsub <8 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
- // CHECK: @llvm.x86.fma.vfmadd.ps.256(<8 x float> [[NEG]], <8 x float> %{{.+}}, <8 x float> [[NEG2]])
+ // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}})
return _mm256_fnmsub_ps(a, b, c);
}
@@ -193,32 +235,42 @@ __m256d test_mm256_fnmsub_pd(__m256d a, __m256d b, __m256d c) {
// CHECK-LABEL: test_mm256_fnmsub_pd
// CHECK: [[NEG:%.+]] = fsub <4 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.+}}
// CHECK: [[NEG2:%.+]] = fsub <4 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma.vfmadd.pd.256(<4 x double> [[NEG]], <4 x double> %{{.+}}, <4 x double> [[NEG2]])
+ // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
return _mm256_fnmsub_pd(a, b, c);
}
__m256 test_mm256_fmaddsub_ps(__m256 a, __m256 b, __m256 c) {
// CHECK-LABEL: test_mm256_fmaddsub_ps
- // CHECK: @llvm.x86.fma.vfmaddsub.ps.256
+ // CHECK: [[ADD:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}})
+ // CHECK: [[NEG:%.+]] = fsub <8 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[SUB:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]]
+ // CHECK: shufflevector <8 x float> [[SUB]], <8 x float> [[ADD]], <8 x i32> <i32 0, i32 9, i32 2, i32 11, i32 4, i32 13, i32 6, i32 15>
return _mm256_fmaddsub_ps(a, b, c);
}
__m256d test_mm256_fmaddsub_pd(__m256d a, __m256d b, __m256d c) {
// CHECK-LABEL: test_mm256_fmaddsub_pd
- // CHECK: @llvm.x86.fma.vfmaddsub.pd.256
+ // CHECK: [[ADD:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
+ // CHECK: [[NEG:%.+]] = fsub <4 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.+}}
+ // CHECK: [[SUB:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
+ // CHECK: shufflevector <4 x double> [[SUB]], <4 x double> [[ADD]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
return _mm256_fmaddsub_pd(a, b, c);
}
__m256 test_mm256_fmsubadd_ps(__m256 a, __m256 b, __m256 c) {
// CHECK-LABEL: test_mm256_fmsubadd_ps
// CHECK: [[NEG:%.+]] = fsub <8 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
- // CHECK: @llvm.x86.fma.vfmaddsub.ps.256(<8 x float> %{{.*}}, <8 x float> %{{.+}}, <8 x float> [[NEG]])
+ // CHECK: [[SUB:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]]
+ // CHECK: [[ADD:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}})
+ // CHECK: shufflevector <8 x float> [[ADD]], <8 x float> [[SUB]], <8 x i32> <i32 0, i32 9, i32 2, i32 11, i32 4, i32 13, i32 6, i32 15>
return _mm256_fmsubadd_ps(a, b, c);
}
__m256d test_mm256_fmsubadd_pd(__m256d a, __m256d b, __m256d c) {
// CHECK-LABEL: test_mm256_fmsubadd_pd
// CHECK: [[NEG:%.+]] = fsub <4 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma.vfmaddsub.pd.256(<4 x double> %{{.+}}, <4 x double> %{{.+}}, <4 x double> [[NEG]])
+ // CHECK: [[SUB:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> [[NEG]]
+ // CHECK: [[ADD:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
+ // CHECK: shufflevector <4 x double> [[ADD]], <4 x double> [[SUB]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
return _mm256_fmsubadd_pd(a, b, c);
}
diff --git a/test/CodeGen/fma4-builtins.c b/test/CodeGen/fma4-builtins.c
index c848d4a751da..8078a6ed69b2 100644
--- a/test/CodeGen/fma4-builtins.c
+++ b/test/CodeGen/fma4-builtins.c
@@ -5,81 +5,105 @@
__m128 test_mm_macc_ps(__m128 a, __m128 b, __m128 c) {
// CHECK-LABEL: test_mm_macc_ps
- // CHECK: @llvm.x86.fma.vfmadd.ps
+ // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
return _mm_macc_ps(a, b, c);
}
__m128d test_mm_macc_pd(__m128d a, __m128d b, __m128d c) {
// CHECK-LABEL: test_mm_macc_pd
- // CHECK: @llvm.x86.fma.vfmadd.pd
+ // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
return _mm_macc_pd(a, b, c);
}
__m128 test_mm_macc_ss(__m128 a, __m128 b, __m128 c) {
// CHECK-LABEL: test_mm_macc_ss
- // CHECK: @llvm.x86.fma4.vfmadd.ss
+ // CHECK: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK: call float @llvm.fma.f32(float %{{.*}}, float %{{.*}}, float %{{.*}})
+ // CHECK: insertelement <4 x float> zeroinitializer, float %{{.*}}, i64 0
return _mm_macc_ss(a, b, c);
}
__m128d test_mm_macc_sd(__m128d a, __m128d b, __m128d c) {
// CHECK-LABEL: test_mm_macc_sd
- // CHECK: @llvm.x86.fma4.vfmadd.sd
+ // CHECK: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK: call double @llvm.fma.f64(double %{{.*}}, double %{{.*}}, double %{{.*}})
+ // CHECK: insertelement <2 x double> zeroinitializer, double %{{.*}}, i64 0
return _mm_macc_sd(a, b, c);
}
__m128 test_mm_msub_ps(__m128 a, __m128 b, __m128 c) {
// CHECK-LABEL: test_mm_msub_ps
// CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma.vfmadd.ps(<4 x float> %{{.+}}, <4 x float> %{{.+}}, <4 x float> [[NEG]])
+ // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
return _mm_msub_ps(a, b, c);
}
__m128d test_mm_msub_pd(__m128d a, __m128d b, __m128d c) {
// CHECK-LABEL: test_mm_msub_pd
// CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma.vfmadd.pd(<2 x double> %{{.+}}, <2 x double> %{{.+}}, <2 x double> [[NEG]])
+ // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
return _mm_msub_pd(a, b, c);
}
__m128 test_mm_msub_ss(__m128 a, __m128 b, __m128 c) {
// CHECK-LABEL: test_mm_msub_ss
// CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma4.vfmadd.ss(<4 x float> %{{.+}}, <4 x float> %{{.+}}, <4 x float> [[NEG]])
+ // CHECK: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK: [[C:%.+]] = extractelement <4 x float> [[NEG]], i64 0
+ // CHECK: call float @llvm.fma.f32(float %{{.*}}, float %{{.*}}, float [[C]])
+ // CHECK: insertelement <4 x float> zeroinitializer, float %{{.*}}, i64 0
return _mm_msub_ss(a, b, c);
}
__m128d test_mm_msub_sd(__m128d a, __m128d b, __m128d c) {
// CHECK-LABEL: test_mm_msub_sd
// CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma4.vfmadd.sd(<2 x double> %{{.+}}, <2 x double> %{{.+}}, <2 x double> [[NEG]])
+ // CHECK: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK: [[C:%.+]] = extractelement <2 x double> [[NEG]], i64 0
+ // CHECK: call double @llvm.fma.f64(double %{{.*}}, double %{{.*}}, double [[C]])
+ // CHECK: insertelement <2 x double> zeroinitializer, double %{{.*}}, i64 0
return _mm_msub_sd(a, b, c);
}
__m128 test_mm_nmacc_ps(__m128 a, __m128 b, __m128 c) {
// CHECK-LABEL: test_mm_nmacc_ps
// CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma.vfmadd.ps(<4 x float> [[NEG]], <4 x float> %{{.+}}, <4 x float> %{{.+}})
+ // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
return _mm_nmacc_ps(a, b, c);
}
__m128d test_mm_nmacc_pd(__m128d a, __m128d b, __m128d c) {
// CHECK-LABEL: test_mm_nmacc_pd
// CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma.vfmadd.pd(<2 x double> [[NEG]], <2 x double> %{{.+}}, <2 x double> %{{.+}})
+ // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
return _mm_nmacc_pd(a, b, c);
}
__m128 test_mm_nmacc_ss(__m128 a, __m128 b, __m128 c) {
// CHECK-LABEL: test_mm_nmacc_ss
// CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma4.vfmadd.ss(<4 x float> [[NEG]], <4 x float> %{{.+}}, <4 x float> %{{.+}})
+ // CHECK: [[A:%.+]] = extractelement <4 x float> [[NEG]], i64 0
+ // CHECK: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK: call float @llvm.fma.f32(float [[A]], float %{{.*}}, float %{{.*}})
+ // CHECK: insertelement <4 x float> zeroinitializer, float %{{.*}}, i64 0
return _mm_nmacc_ss(a, b, c);
}
__m128d test_mm_nmacc_sd(__m128d a, __m128d b, __m128d c) {
// CHECK-LABEL: test_mm_nmacc_sd
// CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma4.vfmadd.sd(<2 x double> [[NEG]], <2 x double> %{{.+}}, <2 x double> %{{.+}})
+ // CHECK: [[A:%.+]] = extractelement <2 x double> [[NEG]], i64 0
+ // CHECK: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK: call double @llvm.fma.f64(double [[A]], double %{{.*}}, double %{{.*}})
+ // CHECK: insertelement <2 x double> zeroinitializer, double %{{.*}}, i64 0
return _mm_nmacc_sd(a, b, c);
}
@@ -87,7 +111,7 @@ __m128 test_mm_nmsub_ps(__m128 a, __m128 b, __m128 c) {
// CHECK-LABEL: test_mm_nmsub_ps
// CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.+}}
// CHECK: [[NEG2:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma.vfmadd.ps(<4 x float> [[NEG]], <4 x float> %{{.+}}, <4 x float> [[NEG2]])
+ // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
return _mm_nmsub_ps(a, b, c);
}
@@ -95,7 +119,7 @@ __m128d test_mm_nmsub_pd(__m128d a, __m128d b, __m128d c) {
// CHECK-LABEL: test_mm_nmsub_pd
// CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.+}}
// CHECK: [[NEG2:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma.vfmadd.pd(<2 x double> [[NEG]], <2 x double> %{{.+}}, <2 x double> [[NEG2]])
+ // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
return _mm_nmsub_pd(a, b, c);
}
@@ -103,7 +127,11 @@ __m128 test_mm_nmsub_ss(__m128 a, __m128 b, __m128 c) {
// CHECK-LABEL: test_mm_nmsub_ss
// CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.+}}
// CHECK: [[NEG2:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma4.vfmadd.ss(<4 x float> [[NEG]], <4 x float> %{{.+}}, <4 x float> [[NEG2]])
+ // CHECK: [[A:%.+]] = extractelement <4 x float> [[NEG]], i64 0
+ // CHECK: extractelement <4 x float> %{{.*}}, i64 0
+ // CHECK: [[C:%.+]] = extractelement <4 x float> [[NEG2]], i64 0
+ // CHECK: call float @llvm.fma.f32(float [[A]], float %{{.*}}, float [[C]])
+ // CHECK: insertelement <4 x float> zeroinitializer, float %{{.*}}, i64 0
return _mm_nmsub_ss(a, b, c);
}
@@ -111,73 +139,87 @@ __m128d test_mm_nmsub_sd(__m128d a, __m128d b, __m128d c) {
// CHECK-LABEL: test_mm_nmsub_sd
// CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.+}}
// CHECK: [[NEG2:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma4.vfmadd.sd(<2 x double> [[NEG]], <2 x double> %{{.+}}, <2 x double> [[NEG2]])
+ // CHECK: [[A:%.+]] = extractelement <2 x double> [[NEG]], i64 0
+ // CHECK: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK: [[C:%.+]] = extractelement <2 x double> [[NEG2]], i64 0
+ // CHECK: call double @llvm.fma.f64(double [[A]], double %{{.*}}, double [[C]])
+ // CHECK: insertelement <2 x double> zeroinitializer, double %{{.*}}, i64 0
return _mm_nmsub_sd(a, b, c);
}
__m128 test_mm_maddsub_ps(__m128 a, __m128 b, __m128 c) {
// CHECK-LABEL: test_mm_maddsub_ps
- // CHECK: @llvm.x86.fma.vfmaddsub.ps
+ // CHECK: [[ADD:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.+}}
+ // CHECK: [[SUB:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]]
+ // CHECK: shufflevector <4 x float> [[SUB]], <4 x float> [[ADD]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
return _mm_maddsub_ps(a, b, c);
}
__m128d test_mm_maddsub_pd(__m128d a, __m128d b, __m128d c) {
// CHECK-LABEL: test_mm_maddsub_pd
- // CHECK: @llvm.x86.fma.vfmaddsub.pd
+ // CHECK: [[ADD:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.+}}
+ // CHECK: [[SUB:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]]
+ // CHECK: shufflevector <2 x double> [[SUB]], <2 x double> [[ADD]], <2 x i32> <i32 0, i32 3>
return _mm_maddsub_pd(a, b, c);
}
__m128 test_mm_msubadd_ps(__m128 a, __m128 b, __m128 c) {
// CHECK-LABEL: test_mm_msubadd_ps
// CHECK: [[NEG:%.+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma.vfmaddsub.ps(<4 x float> %{{.+}}, <4 x float> %{{.+}}, <4 x float> [[NEG]])
+ // CHECK: [[SUB:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]]
+ // CHECK: [[ADD:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK: shufflevector <4 x float> [[ADD]], <4 x float> [[SUB]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
return _mm_msubadd_ps(a, b, c);
}
__m128d test_mm_msubadd_pd(__m128d a, __m128d b, __m128d c) {
// CHECK-LABEL: test_mm_msubadd_pd
// CHECK: [[NEG:%.+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma.vfmaddsub.pd(<2 x double> %{{.+}}, <2 x double> %{{.+}}, <2 x double> [[NEG]])
+ // CHECK: [[SUB:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]]
+ // CHECK: [[ADD:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK: shufflevector <2 x double> [[ADD]], <2 x double> [[SUB]], <2 x i32> <i32 0, i32 3>
return _mm_msubadd_pd(a, b, c);
}
__m256 test_mm256_macc_ps(__m256 a, __m256 b, __m256 c) {
// CHECK-LABEL: test_mm256_macc_ps
- // CHECK: @llvm.x86.fma.vfmadd.ps.256
+ // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}})
return _mm256_macc_ps(a, b, c);
}
__m256d test_mm256_macc_pd(__m256d a, __m256d b, __m256d c) {
// CHECK-LABEL: test_mm256_macc_pd
- // CHECK: @llvm.x86.fma.vfmadd.pd.256
+ // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
return _mm256_macc_pd(a, b, c);
}
__m256 test_mm256_msub_ps(__m256 a, __m256 b, __m256 c) {
// CHECK-LABEL: test_mm256_msub_ps
// CHECK: [[NEG:%.+]] = fsub <8 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
- // CHECK: @llvm.x86.fma.vfmadd.ps.256(<8 x float> %{{.+}}, <8 x float> %{{.+}}, <8 x float> [[NEG]])
+ // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}})
return _mm256_msub_ps(a, b, c);
}
__m256d test_mm256_msub_pd(__m256d a, __m256d b, __m256d c) {
// CHECK-LABEL: test_mm256_msub_pd
// CHECK: [[NEG:%.+]] = fsub <4 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma.vfmadd.pd.256(<4 x double> %{{.+}}, <4 x double> %{{.+}}, <4 x double> [[NEG]])
+ // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
return _mm256_msub_pd(a, b, c);
}
__m256 test_mm256_nmacc_ps(__m256 a, __m256 b, __m256 c) {
// CHECK-LABEL: test_mm256_nmacc_ps
// CHECK: [[NEG:%.+]] = fsub <8 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
- // CHECK: @llvm.x86.fma.vfmadd.ps.256(<8 x float> [[NEG]], <8 x float> %{{.+}}, <8 x float> %{{.+}})
+ // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}})
return _mm256_nmacc_ps(a, b, c);
}
__m256d test_mm256_nmacc_pd(__m256d a, __m256d b, __m256d c) {
// CHECK-LABEL: test_mm256_nmacc_pd
// CHECK: [[NEG:%.+]] = fsub <4 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma.vfmadd.pd.256(<4 x double> [[NEG]], <4 x double> %{{.+}}, <4 x double> %{{.+}})
+ // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
return _mm256_nmacc_pd(a, b, c);
}
@@ -185,7 +227,7 @@ __m256 test_mm256_nmsub_ps(__m256 a, __m256 b, __m256 c) {
// CHECK-LABEL: test_mm256_nmsub_ps
// CHECK: [[NEG:%.+]] = fsub <8 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
// CHECK: [[NEG2:%.+]] = fsub <8 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
- // CHECK: @llvm.x86.fma.vfmadd.ps.256(<8 x float> [[NEG]], <8 x float> %{{.+}}, <8 x float> [[NEG2]])
+ // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}})
return _mm256_nmsub_ps(a, b, c);
}
@@ -193,32 +235,42 @@ __m256d test_mm256_nmsub_pd(__m256d a, __m256d b, __m256d c) {
// CHECK-LABEL: test_mm256_nmsub_pd
// CHECK: [[NEG:%.+]] = fsub <4 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.+}}
// CHECK: [[NEG2:%.+]] = fsub <4 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma.vfmadd.pd.256(<4 x double> [[NEG]], <4 x double> %{{.+}}, <4 x double> [[NEG2]])
+ // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
return _mm256_nmsub_pd(a, b, c);
}
__m256 test_mm256_maddsub_ps(__m256 a, __m256 b, __m256 c) {
// CHECK-LABEL: test_mm256_maddsub_ps
- // CHECK: @llvm.x86.fma.vfmaddsub.ps.256
+ // CHECK: [[ADD:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}})
+ // CHECK: [[NEG:%.+]] = fsub <8 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
+ // CHECK: [[SUB:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]]
+ // CHECK: shufflevector <8 x float> [[SUB]], <8 x float> [[ADD]], <8 x i32> <i32 0, i32 9, i32 2, i32 11, i32 4, i32 13, i32 6, i32 15>
return _mm256_maddsub_ps(a, b, c);
}
__m256d test_mm256_maddsub_pd(__m256d a, __m256d b, __m256d c) {
// CHECK-LABEL: test_mm256_maddsub_pd
- // CHECK: @llvm.x86.fma.vfmaddsub.pd.256
+ // CHECK: [[ADD:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
+ // CHECK: [[NEG:%.+]] = fsub <4 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.+}}
+ // CHECK: [[SUB:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
+ // CHECK: shufflevector <4 x double> [[SUB]], <4 x double> [[ADD]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
return _mm256_maddsub_pd(a, b, c);
}
__m256 test_mm256_msubadd_ps(__m256 a, __m256 b, __m256 c) {
// CHECK-LABEL: test_mm256_msubadd_ps
// CHECK: [[NEG:%.+]] = fsub <8 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
- // CHECK: @llvm.x86.fma.vfmaddsub.ps.256(<8 x float> %{{.*}}, <8 x float> %{{.+}}, <8 x float> [[NEG]])
+ // CHECK: [[SUB:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]]
+ // CHECK: [[ADD:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}})
+ // CHECK: shufflevector <8 x float> [[ADD]], <8 x float> [[SUB]], <8 x i32> <i32 0, i32 9, i32 2, i32 11, i32 4, i32 13, i32 6, i32 15>
return _mm256_msubadd_ps(a, b, c);
}
__m256d test_mm256_msubadd_pd(__m256d a, __m256d b, __m256d c) {
// CHECK-LABEL: test_mm256_msubadd_pd
// CHECK: [[NEG:%.+]] = fsub <4 x double> <double -0.000000e+00, double -0.000000e+00, double -0.000000e+00, double -0.000000e+00>, %{{.+}}
- // CHECK: @llvm.x86.fma.vfmaddsub.pd.256(<4 x double> %{{.+}}, <4 x double> %{{.+}}, <4 x double> [[NEG]])
+ // CHECK: [[SUB:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> [[NEG]]
+ // CHECK: [[ADD:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}})
+ // CHECK: shufflevector <4 x double> [[ADD]], <4 x double> [[SUB]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
return _mm256_msubadd_pd(a, b, c);
}
diff --git a/test/CodeGen/fsgsbase-builtins.c b/test/CodeGen/fsgsbase-builtins.c
index 25f4b311a596..587ad84e3f51 100644
--- a/test/CodeGen/fsgsbase-builtins.c
+++ b/test/CodeGen/fsgsbase-builtins.c
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +fsgsbase -emit-llvm -o - | FileCheck %s
-#include <x86intrin.h>
+#include <immintrin.h>
unsigned int test_readfsbase_u32()
{
diff --git a/test/CodeGen/function-alignment.c b/test/CodeGen/function-alignment.c
new file mode 100644
index 000000000000..8564ceb02354
--- /dev/null
+++ b/test/CodeGen/function-alignment.c
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NONE
+// RUN: %clang_cc1 -emit-llvm -function-alignment 4 %s -o - | FileCheck %s -check-prefix CHECK-16
+// RUN: %clang_cc1 -emit-llvm -function-alignment 5 %s -o - | FileCheck %s -check-prefix CHECK-32
+
+void f(void) {}
+void __attribute__((__aligned__(64))) g(void) {}
+
+// CHECK-NONE-NOT: define {{(dso_local )?}}void @f() #0 align
+// CHECK-NONE: define {{(dso_local )?}}void @g() #0 align 64
+
+// CHECK-16: define {{(dso_local )?}}void @f() #0 align 16
+// CHECK-16: define {{(dso_local )?}}void @g() #0 align 64
+
+// CHECK-32: define {{(dso_local )?}}void @f() #0 align 32
+// CHECK-32: define {{(dso_local )?}}void @g() #0 align 64
+
diff --git a/test/CodeGen/function-attributes.c b/test/CodeGen/function-attributes.c
index e14397440100..9174b8785d9e 100644
--- a/test/CodeGen/function-attributes.c
+++ b/test/CodeGen/function-attributes.c
@@ -71,7 +71,7 @@ void f15(void) {
// PR5254
// CHECK-LABEL: define void @f16
-// CHECK: [[ALIGN:#[0-9]+]]
+// CHECK: [[SR:#[0-9]+]]
// CHECK: {
void __attribute__((force_align_arg_pointer)) f16(void) {
}
@@ -112,7 +112,7 @@ void f20(void) {
// CHECK: attributes [[NUW]] = { nounwind optsize{{.*}} }
// CHECK: attributes [[AI]] = { alwaysinline nounwind optsize{{.*}} }
// CHECK: attributes [[NUW_OS_RN]] = { nounwind optsize readnone{{.*}} }
-// CHECK: attributes [[ALIGN]] = { nounwind optsize alignstack=16{{.*}} }
+// CHECK: attributes [[SR]] = { nounwind optsize{{.*}} "stackrealign"{{.*}} }
// CHECK: attributes [[RT]] = { nounwind optsize returns_twice{{.*}} }
// CHECK: attributes [[NR]] = { noreturn optsize }
// CHECK: attributes [[NUW_RN]] = { nounwind optsize readnone }
diff --git a/test/CodeGen/function-min-vector-width.c b/test/CodeGen/function-min-vector-width.c
new file mode 100644
index 000000000000..fb22a4fce6d9
--- /dev/null
+++ b/test/CodeGen/function-min-vector-width.c
@@ -0,0 +1,7 @@
+// This test verifies that we produce min-legal-vector-width attributes
+
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s
+
+void __attribute((__min_vector_width__(128))) foo() {}
+
+// CHECK: "min-legal-vector-width"="128"
diff --git a/test/CodeGen/gfni-builtins.c b/test/CodeGen/gfni-builtins.c
index 95cfd4fcd5c7..0d10d7aeacd6 100644
--- a/test/CodeGen/gfni-builtins.c
+++ b/test/CodeGen/gfni-builtins.c
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +gfni -emit-llvm -o - | FileCheck %s --check-prefix SSE
-// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -DAVX -target-feature +gfni -target-feature +avx -emit-llvm -o - | FileCheck %s --check-prefixes SSE,AVX
-// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -DAVX512 -target-feature +gfni -target-feature +avx512bw -target-feature +avx512vl -emit-llvm -o - | FileCheck %s --check-prefixes SSE,AVX,AVX512
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +gfni -target-feature +avx -emit-llvm -o - | FileCheck %s --check-prefixes SSE,AVX
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +gfni -target-feature +avx512bw -target-feature +avx512vl -emit-llvm -o - | FileCheck %s --check-prefixes SSE,AVX,AVX512
#include <immintrin.h>
@@ -22,7 +22,7 @@ __m128i test_mm_gf2p8mul_epi8(__m128i A, __m128i B) {
return _mm_gf2p8mul_epi8(A, B);
}
-#if defined(AVX) || defined(AVX512)
+#ifdef __AVX__
__m256i test_mm256_gf2p8affineinv_epi64_epi8(__m256i A, __m256i B) {
// AVX-LABEL: @test_mm256_gf2p8affineinv_epi64_epi8
// AVX: @llvm.x86.vgf2p8affineinvqb.256
@@ -40,9 +40,9 @@ __m256i test_mm256_gf2p8mul_epi8(__m256i A, __m256i B) {
// AVX: @llvm.x86.vgf2p8mulb.256
return _mm256_gf2p8mul_epi8(A, B);
}
-#endif // AVX
+#endif // __AVX__
-#ifdef AVX512
+#ifdef __AVX512BW__
__m512i test_mm512_gf2p8affineinv_epi64_epi8(__m512i A, __m512i B) {
// AVX512-LABEL: @test_mm512_gf2p8affineinv_epi64_epi8
// AVX512: @llvm.x86.vgf2p8affineinvqb.512
@@ -179,4 +179,4 @@ __m128i test_mm_mask_gf2p8mul_epi8(__m128i S, __mmask16 U, __m128i A, __m128i B)
// AVX512: select <16 x i1> %{{[0-9]+}}, <16 x i8> %{{[0-9]+}}, <16 x i8> {{.*}}
return _mm_mask_gf2p8mul_epi8(S, U, A, B);
}
-#endif // AVX512
+#endif // __AVX512BW__
diff --git a/test/CodeGen/hexagon-brev-ld-ptr-incdec.c b/test/CodeGen/hexagon-brev-ld-ptr-incdec.c
new file mode 100644
index 000000000000..67c6c347e94d
--- /dev/null
+++ b/test/CodeGen/hexagon-brev-ld-ptr-incdec.c
@@ -0,0 +1,52 @@
+// REQUIRES: hexagon-registered-target
+// RUN: %clang_cc1 -emit-llvm -O2 -o - -triple hexagon-unknown-elf %s | FileCheck %s
+
+// The return value should return the value in A[1].
+// Check that the HexagonBuiltinExpr doesn't evaluate &(*ptr++) twice. If so,
+// the return value will be the value in A[2]
+// CHECK: @brev_ptr_inc
+// CHECK-DAG: llvm.hexagon.L2.loadri.pbr
+// CHECK-DAG: getelementptr{{.*}}i32 1
+// CHECK-NOT: getelementptr{{.*}}i32 2
+// CHECK-NOT: getelementptr{{.*}}i32 1
+int brev_ptr_inc(int A[], int B[]) {
+ int *p0 = &B[0];
+ int *p1 = &A[0];
+ __builtin_brev_ldw(p0, &*p1++, 8);
+ return (*p1);
+}
+
+// The return value should return the value in A[0].
+// CHECK: @brev_ptr_dec
+// CHECK: llvm.hexagon.L2.loadri.pbr
+// CHECK: [[RET:%[0-9]+]] = load{{.*}}%A
+// CHECK: ret{{.*}}[[RET]]
+int brev_ptr_dec(int A[], int B[]) {
+ int *p0 = &B[0];
+ int *p1 = &A[1];
+ __builtin_brev_ldw(p0, &*p1--, 8);
+ return (*p1);
+}
+
+// The store in bitcode needs to be of width correspondng to 16-bit.
+// CHECK: @brev_ptr_half
+// CHECK: llvm.hexagon.L2.loadrh.pbr
+// CHECK: store{{.*}}i16{{.*}}i16*
+short int brev_ptr_half(short int A[], short int B[]) {
+ short int *p0 = &B[0];
+ short int *p1 = &A[0];
+ __builtin_brev_ldh(p0, &*p1++, 8);
+ return (*p1);
+}
+
+// The store in bitcode needs to be of width correspondng to 8-bit.
+// CHECK: @brev_ptr_byte
+// CHECK: llvm.hexagon.L2.loadrub.pbr
+// CHECK: store{{.*}}i8{{.*}}i8*
+unsigned char brev_ptr_byte(unsigned char A[], unsigned char B[]) {
+ unsigned char *p0 = &B[0];
+ unsigned char *p1 = &A[0];
+ __builtin_brev_ldub(p0, &*p1++, 8);
+ return (*p1);
+}
+
diff --git a/test/CodeGen/hexagon-brev-store-elm.c b/test/CodeGen/hexagon-brev-store-elm.c
new file mode 100644
index 000000000000..f593419e63e6
--- /dev/null
+++ b/test/CodeGen/hexagon-brev-store-elm.c
@@ -0,0 +1,46 @@
+// REQUIRES: hexagon-registered-target
+// RUN: %clang_cc1 -emit-llvm -O2 -o - -triple hexagon-unknown-elf %s | FileCheck %s
+// This unit test validates that the store to "dst" variable needs to be eliminated.
+
+// CHECK: @brev_store_elimination_test1
+// CHECK: llvm.hexagon.L2.loadri.pbr
+// CHECK-NOT: store
+
+int *brev_store_elimination_test1(int *ptr, int mod) {
+ int dst = 100;
+ return __builtin_brev_ldw(ptr, &dst, mod);
+}
+
+// CHECK: @brev_store_elimination_test2
+// CHECK: llvm.hexagon.L2.loadri.pbr
+// CHECK-NOT: store
+extern int add(int a);
+int brev_store_elimination_test2(int *ptr, int mod) {
+ int dst = 100;
+ __builtin_brev_ldw(ptr, &dst, mod);
+ return add(dst);
+}
+
+// CHECK: @brev_store_elimination_test3
+// CHECK: llvm.hexagon.L2.loadri.pbr
+// CHECK-NOT: store
+int brev_store_elimination_test3(int *ptr, int mod, int inc) {
+ int dst = 100;
+ for (int i = 0; i < inc; ++i) {
+ __builtin_brev_ldw(ptr, &dst, mod);
+ dst = add(dst);
+ }
+ return dst;
+}
+
+// brev_store_elimination_test4 validates the fact that we are not deleting the
+// stores if the value is passed by reference later.
+// CHECK: @brev_store_elimination_test4
+// CHECK: llvm.hexagon.L2.loadri.pbr
+// CHECK: store
+extern int sub(int *a);
+int brev_store_elimination_test4(int *ptr, int mod) {
+ int dst = 100;
+ __builtin_brev_ldw(ptr, &dst, mod);
+ return sub(&dst);
+}
diff --git a/test/CodeGen/hexagon-check-builtins.c b/test/CodeGen/hexagon-check-builtins.c
new file mode 100644
index 000000000000..a9294362f6ba
--- /dev/null
+++ b/test/CodeGen/hexagon-check-builtins.c
@@ -0,0 +1,30 @@
+// REQUIRES: hexagon-registered-target
+// RUN: %clang_cc1 -fsyntax-only -triple hexagon-unknown-elf -verify %s
+
+int foo(int x) {
+ // expected-error-re@+2 {{argument value {{.*}} is outside the valid range}}
+ // expected-error-re@+1 {{argument value {{.*}} is outside the valid range}}
+ return __builtin_HEXAGON_S4_extract(x, 33, -1) +
+ // expected-error-re@+1 {{argument value {{.*}} is outside the valid range}}
+ __builtin_HEXAGON_S4_extract(x, 3, 91) +
+ // expected-error-re@+2 {{argument value {{.*}} is outside the valid range}}
+ // expected-error-re@+1 {{argument value {{.*}} is outside the valid range}}
+ __builtin_HEXAGON_S4_extract(x, -1, 35) +
+ __builtin_HEXAGON_S4_extract(x, 0, 31) +
+ __builtin_HEXAGON_S4_extract(x, 31, 0);
+}
+
+int bar(void *p, void *q, int x) {
+ // expected-error@+1 {{argument should be a multiple of 4}}
+ return __builtin_HEXAGON_L2_loadri_pci(p, -1, x, q) +
+ // expected-error-re@+2 {{argument value {{.*}} is outside the valid range}}
+ // expected-error@+1 {{argument should be a multiple of 4}}
+ __builtin_HEXAGON_L2_loadri_pci(p, -99, x, q) +
+ // expected-error-re@+1 {{argument value {{.*}} is outside the valid range}}
+ __builtin_HEXAGON_L2_loadri_pci(p, -132, x, q) +
+ __builtin_HEXAGON_L2_loadri_pci(p, 28, x, q) +
+ // expected-error-re@+2 {{argument value {{.*}} is outside the valid range}}
+ // expected-error@+1 {{argument should be a multiple of 4}}
+ __builtin_HEXAGON_L2_loadri_pci(p, 29, x, q);
+}
+
diff --git a/test/CodeGen/init.c b/test/CodeGen/init.c
index 5d086723cc0e..71aba39b1244 100644
--- a/test/CodeGen/init.c
+++ b/test/CodeGen/init.c
@@ -8,8 +8,9 @@ unsigned v2[2][3] = {[0 ... 1][0 ... 1] = 2222, 3333};
// CHECK-DAG: %struct.M = type { [2 x %struct.I] }
// CHECK-DAG: %struct.I = type { [3 x i32] }
-// CHECK: [1 x %struct.M] [%struct.M { [2 x %struct.I] [%struct.I { [3 x i32] [i32 4, i32 4, i32 0] }, %struct.I { [3 x i32] [i32 4, i32 4, i32 5] }] }],
-// CHECK: [2 x [3 x i32]] {{[[][[]}}3 x i32] [i32 2222, i32 2222, i32 0], [3 x i32] [i32 2222, i32 2222, i32 3333]],
+// CHECK-DAG: [1 x %struct.M] [%struct.M { [2 x %struct.I] [%struct.I { [3 x i32] [i32 4, i32 4, i32 0] }, %struct.I { [3 x i32] [i32 4, i32 4, i32 5] }] }],
+// CHECK-DAG: [2 x [3 x i32]] {{[[][[]}}3 x i32] [i32 2222, i32 2222, i32 0], [3 x i32] [i32 2222, i32 2222, i32 3333]],
+// CHECK-DAG: [[INIT14:.*]] = private global [16 x i32] [i32 0, i32 0, i32 0, i32 0, i32 0, i32 17, i32 17, i32 17, i32 17, i32 17, i32 17, i32 17, i32 0, i32 0, i32 0, i32 0], align 4
void f1() {
// Scalars in braces.
@@ -33,8 +34,8 @@ void f3() {
}
// Constants
-// CHECK: @g3 = constant i32 10
-// CHECK: @f4.g4 = internal constant i32 12
+// CHECK-DAG: @g3 = constant i32 10
+// CHECK-DAG: @f4.g4 = internal constant i32 12
const int g3 = 10;
int f4() {
static const int g4 = 12;
@@ -61,7 +62,7 @@ void f6() {
-// CHECK: @test7 = global{{.*}}{ i32 0, [4 x i8] c"bar\00" }
+// CHECK-DAG: @test7 = global{{.*}}{ i32 0, [4 x i8] c"bar\00" }
// PR8217
struct a7 {
int b;
@@ -71,29 +72,54 @@ struct a7 {
struct a7 test7 = { .b = 0, .v = "bar" };
+// CHECK-DAG: @huge_array = global {{.*}} <{ i32 1, i32 0, i32 2, i32 0, i32 3, [999999995 x i32] zeroinitializer }>
+int huge_array[1000000000] = {1, 0, 2, 0, 3, 0, 0, 0};
+
+// CHECK-DAG: @huge_struct = global {{.*}} { i32 1, <{ i32, [999999999 x i32] }> <{ i32 2, [999999999 x i32] zeroinitializer }> }
+struct Huge {
+ int a;
+ int arr[1000 * 1000 * 1000];
+} huge_struct = {1, {2, 0, 0, 0}};
+
+// CHECK-DAG: @large_array_with_zeroes = constant <{ [21 x i8], [979 x i8] }> <{ [21 x i8] c"abc\01\02\03xyzzy\00\00\00\00\00\00\00\00\00q", [979 x i8] zeroinitializer }>
+const char large_array_with_zeroes[1000] = {
+ 'a', 'b', 'c', 1, 2, 3, 'x', 'y', 'z', 'z', 'y', [20] = 'q'
+};
+
+char global;
+
+// CHECK-DAG: @large_array_with_zeroes_2 = global <{ [10 x i8*], [90 x i8*] }> <{ [10 x i8*] [i8* null, i8* null, i8* null, i8* null, i8* null, i8* null, i8* null, i8* null, i8* null, i8* @global], [90 x i8*] zeroinitializer }>
+const void *large_array_with_zeroes_2[100] = {
+ [9] = &global
+};
+// CHECK-DAG: @large_array_with_zeroes_3 = global <{ [10 x i8*], [990 x i8*] }> <{ [10 x i8*] [i8* null, i8* null, i8* null, i8* null, i8* null, i8* null, i8* null, i8* null, i8* null, i8* @global], [990 x i8*] zeroinitializer }>
+const void *large_array_with_zeroes_3[1000] = {
+ [9] = &global
+};
+
// PR279 comment #3
char test8(int X) {
char str[100000] = "abc"; // tail should be memset.
return str[X];
-// CHECK: @test8(
-// CHECK: call void @llvm.memset
-// CHECK: store i8 97
-// CHECK: store i8 98
-// CHECK: store i8 99
-// CHECK-NOT: getelementptr
-// CHECK: load
+ // CHECK-LABEL: @test8(
+ // CHECK: call void @llvm.memset
+ // CHECK: store i8 97, i8* %{{[0-9]*}}, align 1
+ // CHECK: store i8 98, i8* %{{[0-9]*}}, align 1
+ // CHECK: store i8 99, i8* %{{[0-9]*}}, align 1
+ // CHECK-NOT: getelementptr
+ // CHECK: load
}
void bar(void*);
// PR279
-int test9(int X) {
+void test9(int X) {
int Arr[100] = { X }; // Should use memset
bar(Arr);
-// CHECK: @test9
-// CHECK: call void @llvm.memset
-// CHECK-NOT: store i32 0
-// CHECK: call void @bar
+ // CHECK-LABEL: @test9(
+ // CHECK: call void @llvm.memset
+ // CHECK-NOT: store i32 0
+ // CHECK: call void @bar
}
struct a {
@@ -104,16 +130,82 @@ struct b {
struct a a,b,c,d,e,f,g;
};
-int test10(int X) {
+void test10(int X) {
struct b S = { .a.a = X, .d.e = X, .f.e = 0, .f.f = 0, .f.p = 0 };
bar(&S);
- // CHECK: @test10
+ // CHECK-LABEL: @test10(
// CHECK: call void @llvm.memset
// CHECK-NOT: store i32 0
// CHECK: call void @bar
}
+void nonzeroMemseti8() {
+ char arr[33] = { 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, };
+ // CHECK-LABEL: @nonzeroMemseti8(
+ // CHECK-NOT: store
+ // CHECK-NOT: memcpy
+ // CHECK: call void @llvm.memset.p0i8.i32(i8* {{.*}}, i8 42, i32 33, i1 false)
+}
+
+void nonzeroMemseti16() {
+ unsigned short arr[17] = { 0x4242, 0x4242, 0x4242, 0x4242, 0x4242, 0x4242, 0x4242, 0x4242, 0x4242, 0x4242, 0x4242, 0x4242, 0x4242, 0x4242, 0x4242, 0x4242, 0x4242, };
+ // CHECK-LABEL: @nonzeroMemseti16(
+ // CHECK-NOT: store
+ // CHECK-NOT: memcpy
+ // CHECK: call void @llvm.memset.p0i8.i32(i8* {{.*}}, i8 66, i32 34, i1 false)
+}
+
+void nonzeroMemseti32() {
+ unsigned arr[9] = { 0xF0F0F0F0, 0xF0F0F0F0, 0xF0F0F0F0, 0xF0F0F0F0, 0xF0F0F0F0, 0xF0F0F0F0, 0xF0F0F0F0, 0xF0F0F0F0, 0xF0F0F0F0, };
+ // CHECK-LABEL: @nonzeroMemseti32(
+ // CHECK-NOT: store
+ // CHECK-NOT: memcpy
+ // CHECK: call void @llvm.memset.p0i8.i32(i8* {{.*}}, i8 -16, i32 36, i1 false)
+}
+
+void nonzeroMemseti64() {
+ unsigned long long arr[7] = { 0xAAAAAAAAAAAAAAAA, 0xAAAAAAAAAAAAAAAA, 0xAAAAAAAAAAAAAAAA, 0xAAAAAAAAAAAAAAAA, 0xAAAAAAAAAAAAAAAA, 0xAAAAAAAAAAAAAAAA, 0xAAAAAAAAAAAAAAAA, };
+ // CHECK-LABEL: @nonzeroMemseti64(
+ // CHECK-NOT: store
+ // CHECK-NOT: memcpy
+ // CHECK: call void @llvm.memset.p0i8.i32(i8* {{.*}}, i8 -86, i32 56, i1 false)
+}
+
+void nonzeroMemsetf32() {
+ float arr[9] = { 0x1.cacacap+75, 0x1.cacacap+75, 0x1.cacacap+75, 0x1.cacacap+75, 0x1.cacacap+75, 0x1.cacacap+75, 0x1.cacacap+75, 0x1.cacacap+75, 0x1.cacacap+75, };
+ // CHECK-LABEL: @nonzeroMemsetf32(
+ // CHECK-NOT: store
+ // CHECK-NOT: memcpy
+ // CHECK: call void @llvm.memset.p0i8.i32(i8* {{.*}}, i8 101, i32 36, i1 false)
+}
+
+void nonzeroMemsetf64() {
+ double arr[7] = { 0x1.4444444444444p+69, 0x1.4444444444444p+69, 0x1.4444444444444p+69, 0x1.4444444444444p+69, 0x1.4444444444444p+69, 0x1.4444444444444p+69, 0x1.4444444444444p+69, };
+ // CHECK-LABEL: @nonzeroMemsetf64(
+ // CHECK-NOT: store
+ // CHECK-NOT: memcpy
+ // CHECK: call void @llvm.memset.p0i8.i32(i8* {{.*}}, i8 68, i32 56, i1 false)
+}
+
+void nonzeroPaddedUnionMemset() {
+ union U { char c; int i; };
+ union U arr[9] = { 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, };
+ // CHECK-LABEL: @nonzeroPaddedUnionMemset(
+ // CHECK-NOT: store
+ // CHECK-NOT: memcpy
+ // CHECK: call void @llvm.memset.p0i8.i32(i8* {{.*}}, i8 -16, i32 36, i1 false)
+}
+
+void nonzeroNestedMemset() {
+ union U { char c; int i; };
+ struct S { union U u; short i; };
+ struct S arr[5] = { { {0xF0}, 0xF0F0 }, { {0xF0}, 0xF0F0 }, { {0xF0}, 0xF0F0 }, { {0xF0}, 0xF0F0 }, { {0xF0}, 0xF0F0 }, };
+ // CHECK-LABEL: @nonzeroNestedMemset(
+ // CHECK-NOT: store
+ // CHECK-NOT: memcpy
+ // CHECK: call void @llvm.memset.p0i8.i32(i8* {{.*}}, i8 -16, i32 40, i1 false)
+}
// PR9257
struct test11S {
@@ -121,11 +213,11 @@ struct test11S {
};
void test11(struct test11S *P) {
*P = (struct test11S) { .A = { [0 ... 3] = 4 } };
- // CHECK: @test11
- // CHECK: store i32 4
- // CHECK: store i32 4
- // CHECK: store i32 4
- // CHECK: store i32 4
+ // CHECK-LABEL: @test11(
+ // CHECK: store i32 4, i32* %{{.*}}, align 4
+ // CHECK: store i32 4, i32* %{{.*}}, align 4
+ // CHECK: store i32 4, i32* %{{.*}}, align 4
+ // CHECK: store i32 4, i32* %{{.*}}, align 4
// CHECK: ret void
}
@@ -140,14 +232,26 @@ struct test12 {
void test13(int x) {
struct X { int a; int b : 10; int c; };
struct X y = {.c = x};
- // CHECK: @test13
+ // CHECK-LABEL: @test13(
// CHECK: and i16 {{.*}}, -1024
}
-// CHECK-LABEL: @PR20473
+// CHECK-LABEL: @PR20473(
void PR20473() {
// CHECK: memcpy{{.*}}getelementptr inbounds ([2 x i8], [2 x i8]* @
bar((char[2]) {""});
// CHECK: memcpy{{.*}}getelementptr inbounds ([3 x i8], [3 x i8]* @
bar((char[3]) {""});
}
+
+// Test that we initialize large member arrays by copying from a global and not
+// with a series of stores.
+struct S14 { int a[16]; };
+
+void test14(struct S14 *s14) {
+ // CHECK-LABEL: @test14(
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 {{.*}}, i8* align 4 {{.*}} [[INIT14]] {{.*}}, i32 64, i1 false)
+ // CHECK-NOT: store
+ // CHECK: ret void
+ *s14 = (struct S14) { { [5 ... 11] = 17 } };
+}
diff --git a/test/CodeGen/inline.c b/test/CodeGen/inline.c
index e17b251df000..ea6e9d76494b 100644
--- a/test/CodeGen/inline.c
+++ b/test/CodeGen/inline.c
@@ -61,13 +61,13 @@
// RUN: %clang_cc1 %s -triple i386-pc-win32 -O1 -disable-llvm-passes -emit-llvm -o - -std=c99 | FileCheck %s --check-prefix=CHECK4
// RUN: %clang_cc1 %s -triple i386-pc-win32 -fexperimental-new-pass-manager -O1 -disable-llvm-passes -emit-llvm -o - -std=c99 | FileCheck %s --check-prefix=CHECK4
// CHECK4-NOT: define weak_odr void @_Exit(
-// CHECK4-LABEL: define weak_odr i32 @ei()
-// CHECK4-LABEL: define i32 @bar()
+// CHECK4-LABEL: define weak_odr dso_local i32 @ei()
+// CHECK4-LABEL: define dso_local i32 @bar()
// CHECK4-NOT: unreferenced1
-// CHECK4-LABEL: define weak_odr void @unreferenced2()
-// CHECK4-LABEL: define void @gnu_inline()
-// CHECK4-LABEL: define linkonce_odr i32 @foo()
-// CHECK4-LABEL: define available_externally void @gnu_ei_inline()
+// CHECK4-LABEL: define weak_odr dso_local void @unreferenced2()
+// CHECK4-LABEL: define dso_local void @gnu_inline()
+// CHECK4-LABEL: define linkonce_odr dso_local i32 @foo()
+// CHECK4-LABEL: define available_externally dso_local void @gnu_ei_inline()
__attribute__((noreturn)) void __cdecl _exit(int _Code);
__inline void __cdecl _Exit(int status) { _exit(status); }
diff --git a/test/CodeGen/invpcid.c b/test/CodeGen/invpcid.c
new file mode 100644
index 000000000000..f472cd995371
--- /dev/null
+++ b/test/CodeGen/invpcid.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 %s -ffreestanding -triple=x86_64-unknown-unknown -target-feature +invpcid -emit-llvm -o - -Wall -Werror -pedantic | FileCheck %s
+// RUN: %clang_cc1 %s -ffreestanding -triple=i386-unknown-unknown -target-feature +invpcid -emit-llvm -o - -Wall -Werror -pedantic | FileCheck %s
+
+#include <immintrin.h>
+
+#include <stdint.h>
+
+void test_invpcid(uint32_t type, void *descriptor) {
+ //CHECK-LABEL: @test_invpcid
+ //CHECK: call void @llvm.x86.invpcid(i32 %{{.*}}, i8* %{{.*}})
+ _invpcid(type, descriptor);
+}
diff --git a/test/CodeGen/kr-func-promote.c b/test/CodeGen/kr-func-promote.c
index 8e55dc91edf4..122e6435d0b5 100644
--- a/test/CodeGen/kr-func-promote.c
+++ b/test/CodeGen/kr-func-promote.c
@@ -1,6 +1,12 @@
// RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm -o - | FileCheck %s
-// CHECK: i32 @a(i32)
+// CHECK: i32 @a(i32
int a();
int a(x) short x; {return x;}
+// CHECK: void @b(double
+// CHECK: %[[ADDR:.*]] = alloca float, align 4
+// CHECK: %[[TRUNC:.*]] = fptrunc double %0 to float
+// CHECK: store float %[[TRUNC]], float* %[[ADDR]], align 4
+void b();
+void b(f) float f; {}
diff --git a/test/CodeGen/le32-vaarg.c b/test/CodeGen/le32-vaarg.c
index c02af27691f2..7e1dd8a27ae6 100644
--- a/test/CodeGen/le32-vaarg.c
+++ b/test/CodeGen/le32-vaarg.c
@@ -23,7 +23,7 @@ void get_struct(va_list *args) {
// CHECK: [[RESULT:%[a-z_0-9]+]] = va_arg {{.*}}, %struct.Foo{{$}}
// CHECK: store %struct.Foo [[RESULT]], %struct.Foo* [[LOC:%[a-z_0-9]+]]
// CHECK: [[LOC2:%[a-z_0-9]+]] = bitcast {{.*}} [[LOC]] to i8*
-// CHECK: call void @llvm.memcpy{{.*}}@dest{{.*}}, i8* [[LOC2]]
+// CHECK: call void @llvm.memcpy{{.*}}@dest{{.*}}, i8* align {{[0-9]+}} [[LOC2]]
void skip_struct(va_list *args) {
va_arg(*args, struct Foo);
diff --git a/test/CodeGen/libcalls-fno-builtin.c b/test/CodeGen/libcalls-fno-builtin.c
index bc6a4302b01c..6fac6ee3390b 100644
--- a/test/CodeGen/libcalls-fno-builtin.c
+++ b/test/CodeGen/libcalls-fno-builtin.c
@@ -1,14 +1,19 @@
-// RUN: %clang_cc1 -S -O3 -fno-builtin -o - %s | FileCheck %s
-// RUN: %clang_cc1 -S -O3 -fno-builtin-ceil -fno-builtin-copysign -fno-builtin-cos \
+// RUN: %clang_cc1 -S -emit-llvm -fno-builtin -o - %s | FileCheck %s
+// RUN: %clang_cc1 -S -emit-llvm -fno-builtin-ceil -fno-builtin-copysign -fno-builtin-cos \
// RUN: -fno-builtin-fabs -fno-builtin-floor -fno-builtin-strcat -fno-builtin-strncat \
// RUN: -fno-builtin-strchr -fno-builtin-strrchr -fno-builtin-strcmp -fno-builtin-strncmp \
// RUN: -fno-builtin-strcpy -fno-builtin-stpcpy -fno-builtin-strncpy -fno-builtin-strlen \
// RUN: -fno-builtin-strpbrk -fno-builtin-strspn -fno-builtin-strtod -fno-builtin-strtof \
// RUN: -fno-builtin-strtold -fno-builtin-strtol -fno-builtin-strtoll -fno-builtin-strtoul \
-// RUN: -fno-builtin-strtoull -o - %s | FileCheck %s
+// RUN: -fno-builtin-strtoull -fno-builtin-fread -fno-builtin-fwrite -fno-builtin-fopen \
+// RUN: -o - %s | FileCheck %s
+// RUN: %clang_cc1 -S -O3 -fno-builtin -o - %s | FileCheck --check-prefix=ASM %s
+// RUN: %clang_cc1 -S -O3 -fno-builtin-ceil -o - %s | FileCheck --check-prefix=ASM-INDIV %s
+
// rdar://10551066
typedef __SIZE_TYPE__ size_t;
+typedef struct FILE FILE;
double ceil(double x);
double copysign(double,double);
@@ -34,99 +39,125 @@ long int strtol(const char *nptr, char **endptr, int base);
long long int strtoll(const char *nptr, char **endptr, int base);
unsigned long int strtoul(const char *nptr, char **endptr, int base);
unsigned long long int strtoull(const char *nptr, char **endptr, int base);
+size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
+size_t fwrite(const void *ptr, size_t size, size_t nmemb,
+ FILE *stream);
+FILE *fopen(const char *path, const char *mode);
double t1(double x) { return ceil(x); }
-// CHECK: t1
-// CHECK: ceil
+// CHECK-LABEL: t1
+// CHECK: call{{.*}}@ceil{{.*}} [[ATTR:#[0-9]+]]
+
+// ASM: t1
+// ASM: ceil
+
+// ASM-INDIV: t1
+// ASM-INDIV: ceil
double t2(double x, double y) { return copysign(x,y); }
-// CHECK: t2
-// CHECK: copysign
+// CHECK-LABEL: t2
+// CHECK: call{{.*}}@copysign{{.*}} [[ATTR]]
double t3(double x) { return cos(x); }
-// CHECK: t3
-// CHECK: cos
+// CHECK-LABEL: t3
+// CHECK: call{{.*}}@cos{{.*}} [[ATTR]]
double t4(double x) { return fabs(x); }
-// CHECK: t4
-// CHECK: fabs
+// CHECK-LABEL: t4
+// CHECK: call{{.*}}@fabs{{.*}} [[ATTR]]
double t5(double x) { return floor(x); }
-// CHECK: t5
-// CHECK: floor
+// CHECK-LABEL: t5
+// CHECK: call{{.*}}@floor{{.*}} [[ATTR]]
char *t6(char *x) { return strcat(x, ""); }
-// CHECK: t6
-// CHECK: strcat
+// CHECK-LABEL: t6
+// CHECK: call{{.*}}@strcat{{.*}} [[ATTR]]
char *t7(char *x) { return strncat(x, "", 1); }
-// CHECK: t7
-// CHECK: strncat
+// CHECK-LABEL: t7
+// CHECK: call{{.*}}@strncat{{.*}} [[ATTR]]
char *t8(void) { return strchr("hello, world", 'w'); }
-// CHECK: t8
-// CHECK: strchr
+// CHECK-LABEL: t8
+// CHECK: call{{.*}}@strchr{{.*}} [[ATTR]]
char *t9(void) { return strrchr("hello, world", 'w'); }
-// CHECK: t9
-// CHECK: strrchr
+// CHECK-LABEL: t9
+// CHECK: call{{.*}}@strrchr{{.*}} [[ATTR]]
int t10(void) { return strcmp("foo", "bar"); }
-// CHECK: t10
-// CHECK: strcmp
+// CHECK-LABEL: t10
+// CHECK: call{{.*}}@strcmp{{.*}} [[ATTR]]
int t11(void) { return strncmp("foo", "bar", 3); }
-// CHECK: t11
-// CHECK: strncmp
+// CHECK-LABEL: t11
+// CHECK: call{{.*}}@strncmp{{.*}} [[ATTR]]
char *t12(char *x) { return strcpy(x, "foo"); }
-// CHECK: t12
-// CHECK: strcpy
+// CHECK-LABEL: t12
+// CHECK: call{{.*}}@strcpy{{.*}} [[ATTR]]
char *t13(char *x) { return stpcpy(x, "foo"); }
-// CHECK: t13
-// CHECK: stpcpy
+// CHECK-LABEL: t13
+// CHECK: call{{.*}}@stpcpy{{.*}} [[ATTR]]
char *t14(char *x) { return strncpy(x, "foo", 3); }
-// CHECK: t14
-// CHECK: strncpy
+// CHECK-LABEL: t14
+// CHECK: call{{.*}}@strncpy{{.*}} [[ATTR]]
size_t t15(void) { return strlen("foo"); }
-// CHECK: t15
-// CHECK: strlen
+// CHECK-LABEL: t15
+// CHECK: call{{.*}}@strlen{{.*}} [[ATTR]]
char *t16(char *x) { return strpbrk(x, ""); }
-// CHECK: t16
-// CHECK: strpbrk
+// CHECK-LABEL: t16
+// CHECK: call{{.*}}@strpbrk{{.*}} [[ATTR]]
size_t t17(char *x) { return strspn(x, ""); }
-// CHECK: t17
-// CHECK: strspn
+// CHECK-LABEL: t17
+// CHECK: call{{.*}}@strspn{{.*}} [[ATTR]]
double t18(char **x) { return strtod("123.4", x); }
-// CHECK: t18
-// CHECK: strtod
+// CHECK-LABEL: t18
+// CHECK: call{{.*}}@strtod{{.*}} [[ATTR]]
float t19(char **x) { return strtof("123.4", x); }
-// CHECK: t19
-// CHECK: strtof
+// CHECK-LABEL: t19
+// CHECK: call{{.*}}@strtof{{.*}} [[ATTR]]
long double t20(char **x) { return strtold("123.4", x); }
-// CHECK: t20
-// CHECK: strtold
+// CHECK-LABEL: t20
+// CHECK: call{{.*}}@strtold{{.*}} [[ATTR]]
long int t21(char **x) { return strtol("1234", x, 10); }
-// CHECK: t21
-// CHECK: strtol
+// CHECK-LABEL: t21
+// CHECK: call{{.*}}@strtol{{.*}} [[ATTR]]
long int t22(char **x) { return strtoll("1234", x, 10); }
-// CHECK: t22
-// CHECK: strtoll
+// CHECK-LABEL: t22
+// CHECK: call{{.*}}@strtoll{{.*}} [[ATTR]]
long int t23(char **x) { return strtoul("1234", x, 10); }
-// CHECK: t23
-// CHECK: strtoul
+// CHECK-LABEL: t23
+// CHECK: call{{.*}}@strtoul{{.*}} [[ATTR]]
long int t24(char **x) { return strtoull("1234", x, 10); }
-// CHECK: t24
-// CHECK: strtoull
+// CHECK-LABEL: t24
+// CHECK: call{{.*}}@strtoull{{.*}} [[ATTR]]
+
+void t25(FILE *fp, int *buf) {
+ size_t x = fwrite(buf, sizeof(int), 10, fp);
+ size_t y = fread(buf, sizeof(int), 10, fp);
+}
+// CHECK-LABEL: t25
+// CHECK: call{{.*}}@fwrite{{.*}} [[ATTR]]
+// CHECK: call{{.*}}@fread{{.*}} [[ATTR]]
+
+FILE *t26(const char *path, const char *mode) {
+ return fopen(path, mode);
+}
+// CHECK-LABEL: t26
+// CHECK: call{{.*}}@fopen{{.*}} [[ATTR]]
+
+// CHECK: [[ATTR]] = { nobuiltin }
diff --git a/test/CodeGen/lto-newpm-pipeline.c b/test/CodeGen/lto-newpm-pipeline.c
index 10112da6d508..137c46c964cc 100644
--- a/test/CodeGen/lto-newpm-pipeline.c
+++ b/test/CodeGen/lto-newpm-pipeline.c
@@ -27,6 +27,7 @@
// CHECK-FULL-O0: Starting llvm::Module pass manager run.
// CHECK-FULL-O0: Running pass: AlwaysInlinerPass
+// CHECK-FULL-O0-NEXT: Running pass: NameAnonGlobalPass
// CHECK-FULL-O0-NEXT: Running pass: BitcodeWriterPass
// CHECK-FULL-O0: Finished llvm::Module pass manager run.
diff --git a/test/CodeGen/lzcnt-builtins.c b/test/CodeGen/lzcnt-builtins.c
index cc5d458c7630..b1414a3b56f2 100644
--- a/test/CodeGen/lzcnt-builtins.c
+++ b/test/CodeGen/lzcnt-builtins.c
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +lzcnt -emit-llvm -o - | FileCheck %s
-#include <x86intrin.h>
+#include <immintrin.h>
unsigned short test__lzcnt16(unsigned short __X)
{
diff --git a/test/CodeGen/mangle-ms-string-literals.c b/test/CodeGen/mangle-ms-string-literals.c
new file mode 100644
index 000000000000..41dd78c1fa72
--- /dev/null
+++ b/test/CodeGen/mangle-ms-string-literals.c
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -x c -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -x c -emit-llvm %s -o - -triple=x86_64-pc-win32 | FileCheck %s
+
+void crbug857442(int x) {
+ // Make sure to handle truncated or padded literals. The truncation is only valid in C.
+ struct {int x; char s[2]; } truncatedAscii = {x, "hello"};
+ // CHECK: "??_C@_01CONKJJHI@he@"
+ struct {int x; char s[16]; } paddedAscii = {x, "hello"};
+ // CHECK: "??_C@_0BA@EAAINDNC@hello?$AA?$AA?$AA?$AA?$AA?$AA?$AA?$AA?$AA?$AA?$AA@"
+}
diff --git a/test/CodeGen/mangle-ms.c b/test/CodeGen/mangle-ms.c
index 042c72e6d794..13d23c6e6902 100644
--- a/test/CodeGen/mangle-ms.c
+++ b/test/CodeGen/mangle-ms.c
@@ -1,13 +1,13 @@
// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-win32 | FileCheck %s
-// CHECK: define void @"\01?f@@$$J0YAXP6AX@Z@Z"
+// CHECK: define dso_local void @"?f@@$$J0YAXP6AX@Z@Z"
__attribute__((overloadable)) void f(void (*x)()) {}
-// CHECK: define void @f
+// CHECK: define dso_local void @f
void f(void (*x)(int)) {}
-// CHECK: define void @g
+// CHECK: define dso_local void @g
void g(void (*x)(int)) {}
-// CHECK: define void @"\01?g@@$$J0YAXP6AX@Z@Z"
+// CHECK: define dso_local void @"?g@@$$J0YAXP6AX@Z@Z"
__attribute__((overloadable)) void g(void (*x)()) {}
diff --git a/test/CodeGen/mangle-windows-rtd.c b/test/CodeGen/mangle-windows-rtd.c
index fc6f309eaf58..a22cba2e7ef9 100644
--- a/test/CodeGen/mangle-windows-rtd.c
+++ b/test/CodeGen/mangle-windows-rtd.c
@@ -1,10 +1,10 @@
// RUN: %clang_cc1 -emit-llvm -mrtd %s -o - -triple=i386-mingw32 | FileCheck %s
void f1(void) {}
-// CHECK: define x86_stdcallcc void @"\01_f1@0"
+// CHECK: define dso_local x86_stdcallcc void @"\01_f1@0"
void __stdcall f2(void) {}
-// CHECK: define x86_stdcallcc void @"\01_f2@0"
+// CHECK: define dso_local x86_stdcallcc void @"\01_f2@0"
void __fastcall f3(void) {}
-// CHECK: define x86_fastcallcc void @"\01@f3@0"
+// CHECK: define dso_local x86_fastcallcc void @"\01@f3@0"
diff --git a/test/CodeGen/mangle-windows.c b/test/CodeGen/mangle-windows.c
index db39425da827..6dd14d95e00f 100644
--- a/test/CodeGen/mangle-windows.c
+++ b/test/CodeGen/mangle-windows.c
@@ -11,73 +11,73 @@
// ELF64: target datalayout = "e-m:e-{{.*}}"
void __stdcall f1(void) {}
-// CHECK: define x86_stdcallcc void @"\01_f1@0"
-// X64: define void @f1(
+// CHECK: define dso_local x86_stdcallcc void @"\01_f1@0"
+// X64: define dso_local void @f1(
// ELF32: define x86_stdcallcc void @"\01_f1@0"
// ELF64: define void @f1(
void __fastcall f2(void) {}
-// CHECK: define x86_fastcallcc void @"\01@f2@0"
-// X64: define void @f2(
+// CHECK: define dso_local x86_fastcallcc void @"\01@f2@0"
+// X64: define dso_local void @f2(
// ELF32: define x86_fastcallcc void @"\01@f2@0"
// ELF64: define void @f2(
void __stdcall f3() {}
-// CHECK: define x86_stdcallcc void @"\01_f3@0"
-// X64: define void @f3(
+// CHECK: define dso_local x86_stdcallcc void @"\01_f3@0"
+// X64: define dso_local void @f3(
void __fastcall f4(char a) {}
-// CHECK: define x86_fastcallcc void @"\01@f4@4"
-// X64: define void @f4(
+// CHECK: define dso_local x86_fastcallcc void @"\01@f4@4"
+// X64: define dso_local void @f4(
void __fastcall f5(short a) {}
-// CHECK: define x86_fastcallcc void @"\01@f5@4"
-// X64: define void @f5(
+// CHECK: define dso_local x86_fastcallcc void @"\01@f5@4"
+// X64: define dso_local void @f5(
void __fastcall f6(int a) {}
-// CHECK: define x86_fastcallcc void @"\01@f6@4"
-// X64: define void @f6(
+// CHECK: define dso_local x86_fastcallcc void @"\01@f6@4"
+// X64: define dso_local void @f6(
void __fastcall f7(long a) {}
-// CHECK: define x86_fastcallcc void @"\01@f7@4"
-// X64: define void @f7(
+// CHECK: define dso_local x86_fastcallcc void @"\01@f7@4"
+// X64: define dso_local void @f7(
void __fastcall f8(long long a) {}
-// CHECK: define x86_fastcallcc void @"\01@f8@8"
-// X64: define void @f8(
+// CHECK: define dso_local x86_fastcallcc void @"\01@f8@8"
+// X64: define dso_local void @f8(
void __fastcall f9(long long a, char b, char c, short d) {}
-// CHECK: define x86_fastcallcc void @"\01@f9@20"(i64 %a, i8 signext %b, i8 signext %c, i16 signext %d)
-// X64: define void @f9(
+// CHECK: define dso_local x86_fastcallcc void @"\01@f9@20"(i64 %a, i8 signext %b, i8 signext %c, i16 signext %d)
+// X64: define dso_local void @f9(
void f12(void) {}
-// CHECK: define void @f12(
-// X64: define void @f12(
+// CHECK: define dso_local void @f12(
+// X64: define dso_local void @f12(
void __vectorcall v1(void) {}
-// CHECK: define x86_vectorcallcc void @"\01v1@@0"(
-// X64: define x86_vectorcallcc void @"\01v1@@0"(
+// CHECK: define dso_local x86_vectorcallcc void @"\01v1@@0"(
+// X64: define dso_local x86_vectorcallcc void @"\01v1@@0"(
// ELF32: define x86_vectorcallcc void @"\01v1@@0"(
// ELF64: define x86_vectorcallcc void @"\01v1@@0"(
void __vectorcall v2(char a) {}
-// CHECK: define x86_vectorcallcc void @"\01v2@@4"(
-// X64: define x86_vectorcallcc void @"\01v2@@8"(
+// CHECK: define dso_local x86_vectorcallcc void @"\01v2@@4"(
+// X64: define dso_local x86_vectorcallcc void @"\01v2@@8"(
// ELF32: define x86_vectorcallcc void @"\01v2@@4"(
// ELF64: define x86_vectorcallcc void @"\01v2@@8"(
void __vectorcall v3(short a) {}
-// CHECK: define x86_vectorcallcc void @"\01v3@@4"(
-// X64: define x86_vectorcallcc void @"\01v3@@8"(
+// CHECK: define dso_local x86_vectorcallcc void @"\01v3@@4"(
+// X64: define dso_local x86_vectorcallcc void @"\01v3@@8"(
void __vectorcall v4(int a) {}
-// CHECK: define x86_vectorcallcc void @"\01v4@@4"(
-// X64: define x86_vectorcallcc void @"\01v4@@8"(
+// CHECK: define dso_local x86_vectorcallcc void @"\01v4@@4"(
+// X64: define dso_local x86_vectorcallcc void @"\01v4@@8"(
void __vectorcall v5(long long a) {}
-// CHECK: define x86_vectorcallcc void @"\01v5@@8"(
-// X64: define x86_vectorcallcc void @"\01v5@@8"(
+// CHECK: define dso_local x86_vectorcallcc void @"\01v5@@8"(
+// X64: define dso_local x86_vectorcallcc void @"\01v5@@8"(
void __vectorcall v6(char a, char b) {}
-// CHECK: define x86_vectorcallcc void @"\01v6@@8"(
-// X64: define x86_vectorcallcc void @"\01v6@@16"(
+// CHECK: define dso_local x86_vectorcallcc void @"\01v6@@8"(
+// X64: define dso_local x86_vectorcallcc void @"\01v6@@16"(
diff --git a/test/CodeGen/math-builtins.c b/test/CodeGen/math-builtins.c
index 799d91b4ec00..82f049bdd12e 100644
--- a/test/CodeGen/math-builtins.c
+++ b/test/CodeGen/math-builtins.c
@@ -1,6 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -w -S -o - -emit-llvm %s | FileCheck %s -check-prefix=NO__ERRNO
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -w -S -o - -emit-llvm -fmath-errno %s | FileCheck %s -check-prefix=HAS_ERRNO
// RUN: %clang_cc1 -triple x86_64-unknown-unknown-gnu -w -S -o - -emit-llvm -fmath-errno %s | FileCheck %s --check-prefix=HAS_ERRNO_GNU
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown-android -w -S -o - -emit-llvm -fmath-errno %s | FileCheck %s --check-prefix=HAS_ERRNO_ANDROID
// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -w -S -o - -emit-llvm -fmath-errno %s | FileCheck %s --check-prefix=HAS_ERRNO_WIN
// Test attributes and codegen of math builtins.
@@ -24,23 +25,27 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) {
// HAS_ERRNO: declare float @atan2f(float, float) [[NOT_READNONE]]
// HAS_ERRNO: declare x86_fp80 @atan2l(x86_fp80, x86_fp80) [[NOT_READNONE]]
- __builtin_copysign(f,f); __builtin_copysignf(f,f);__builtin_copysignl(f,f);
+ __builtin_copysign(f,f); __builtin_copysignf(f,f); __builtin_copysignl(f,f); __builtin_copysignf128(f,f);
// NO__ERRNO: declare double @llvm.copysign.f64(double, double) [[READNONE_INTRINSIC:#[0-9]+]]
// NO__ERRNO: declare float @llvm.copysign.f32(float, float) [[READNONE_INTRINSIC]]
// NO__ERRNO: declare x86_fp80 @llvm.copysign.f80(x86_fp80, x86_fp80) [[READNONE_INTRINSIC]]
+// NO__ERRNO: declare fp128 @llvm.copysign.f128(fp128, fp128) [[READNONE_INTRINSIC]]
// HAS_ERRNO: declare double @llvm.copysign.f64(double, double) [[READNONE_INTRINSIC:#[0-9]+]]
// HAS_ERRNO: declare float @llvm.copysign.f32(float, float) [[READNONE_INTRINSIC]]
// HAS_ERRNO: declare x86_fp80 @llvm.copysign.f80(x86_fp80, x86_fp80) [[READNONE_INTRINSIC]]
+// HAS_ERRNO: declare fp128 @llvm.copysign.f128(fp128, fp128) [[READNONE_INTRINSIC]]
- __builtin_fabs(f); __builtin_fabsf(f); __builtin_fabsl(f);
+ __builtin_fabs(f); __builtin_fabsf(f); __builtin_fabsl(f); __builtin_fabsf128(f);
// NO__ERRNO: declare double @llvm.fabs.f64(double) [[READNONE_INTRINSIC]]
// NO__ERRNO: declare float @llvm.fabs.f32(float) [[READNONE_INTRINSIC]]
// NO__ERRNO: declare x86_fp80 @llvm.fabs.f80(x86_fp80) [[READNONE_INTRINSIC]]
+// NO__ERRNO: declare fp128 @llvm.fabs.f128(fp128) [[READNONE_INTRINSIC]]
// HAS_ERRNO: declare double @llvm.fabs.f64(double) [[READNONE_INTRINSIC]]
// HAS_ERRNO: declare float @llvm.fabs.f32(float) [[READNONE_INTRINSIC]]
// HAS_ERRNO: declare x86_fp80 @llvm.fabs.f80(x86_fp80) [[READNONE_INTRINSIC]]
+// HAS_ERRNO: declare fp128 @llvm.fabs.f128(fp128) [[READNONE_INTRINSIC]]
__builtin_frexp(f,i); __builtin_frexpf(f,i); __builtin_frexpl(f,i);
@@ -51,14 +56,14 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) {
// HAS_ERRNO: declare float @frexpf(float, i32*) [[NOT_READNONE]]
// HAS_ERRNO: declare x86_fp80 @frexpl(x86_fp80, i32*) [[NOT_READNONE]]
- __builtin_huge_val(); __builtin_huge_valf(); __builtin_huge_vall();
+ __builtin_huge_val(); __builtin_huge_valf(); __builtin_huge_vall(); __builtin_huge_valf128();
// NO__ERRNO-NOT: .huge
// NO__ERRNO-NOT: @huge
// HAS_ERRNO-NOT: .huge
// HAS_ERRNO-NOT: @huge
- __builtin_inf(); __builtin_inff(); __builtin_infl();
+ __builtin_inf(); __builtin_inff(); __builtin_infl(); __builtin_inff128();
// NO__ERRNO-NOT: .inf
// NO__ERRNO-NOT: @inf
@@ -83,23 +88,27 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) {
// HAS_ERRNO: declare float @modff(float, float*) [[NOT_READNONE]]
// HAS_ERRNO: declare x86_fp80 @modfl(x86_fp80, x86_fp80*) [[NOT_READNONE]]
- __builtin_nan(c); __builtin_nanf(c); __builtin_nanl(c);
+ __builtin_nan(c); __builtin_nanf(c); __builtin_nanl(c); __builtin_nanf128(c);
-// NO__ERRNO: declare double @nan(i8*) [[READNONE]]
-// NO__ERRNO: declare float @nanf(i8*) [[READNONE]]
-// NO__ERRNO: declare x86_fp80 @nanl(i8*) [[READNONE]]
-// HAS_ERRNO: declare double @nan(i8*) [[READNONE:#[0-9]+]]
-// HAS_ERRNO: declare float @nanf(i8*) [[READNONE]]
-// HAS_ERRNO: declare x86_fp80 @nanl(i8*) [[READNONE]]
+// NO__ERRNO: declare double @nan(i8*) [[PURE:#[0-9]+]]
+// NO__ERRNO: declare float @nanf(i8*) [[PURE]]
+// NO__ERRNO: declare x86_fp80 @nanl(i8*) [[PURE]]
+// NO__ERRNO: declare fp128 @nanf128(i8*) [[PURE]]
+// HAS_ERRNO: declare double @nan(i8*) [[PURE:#[0-9]+]]
+// HAS_ERRNO: declare float @nanf(i8*) [[PURE]]
+// HAS_ERRNO: declare x86_fp80 @nanl(i8*) [[PURE]]
+// HAS_ERRNO: declare fp128 @nanf128(i8*) [[PURE]]
- __builtin_nans(c); __builtin_nansf(c); __builtin_nansl(c);
+ __builtin_nans(c); __builtin_nansf(c); __builtin_nansl(c); __builtin_nansf128(c);
-// NO__ERRNO: declare double @nans(i8*) [[READNONE]]
-// NO__ERRNO: declare float @nansf(i8*) [[READNONE]]
-// NO__ERRNO: declare x86_fp80 @nansl(i8*) [[READNONE]]
-// HAS_ERRNO: declare double @nans(i8*) [[READNONE]]
-// HAS_ERRNO: declare float @nansf(i8*) [[READNONE]]
-// HAS_ERRNO: declare x86_fp80 @nansl(i8*) [[READNONE]]
+// NO__ERRNO: declare double @nans(i8*) [[PURE]]
+// NO__ERRNO: declare float @nansf(i8*) [[PURE]]
+// NO__ERRNO: declare x86_fp80 @nansl(i8*) [[PURE]]
+// NO__ERRNO: declare fp128 @nansf128(i8*) [[PURE]]
+// HAS_ERRNO: declare double @nans(i8*) [[PURE]]
+// HAS_ERRNO: declare float @nansf(i8*) [[PURE]]
+// HAS_ERRNO: declare x86_fp80 @nansl(i8*) [[PURE]]
+// HAS_ERRNO: declare fp128 @nansf128(i8*) [[PURE]]
__builtin_pow(f,f); __builtin_powf(f,f); __builtin_powl(f,f);
@@ -179,7 +188,7 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) {
// NO__ERRNO: declare double @cbrt(double) [[READNONE]]
// NO__ERRNO: declare float @cbrtf(float) [[READNONE]]
// NO__ERRNO: declare x86_fp80 @cbrtl(x86_fp80) [[READNONE]]
-// HAS_ERRNO: declare double @cbrt(double) [[READNONE]]
+// HAS_ERRNO: declare double @cbrt(double) [[READNONE:#[0-9]+]]
// HAS_ERRNO: declare float @cbrtf(float) [[READNONE]]
// HAS_ERRNO: declare x86_fp80 @cbrtl(x86_fp80) [[READNONE]]
@@ -288,6 +297,10 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) {
// HAS_ERRNO_GNU: declare float @llvm.fma.f32(float, float, float) [[READNONE_INTRINSIC]]
// HAS_ERRNO_GNU: declare x86_fp80 @llvm.fma.f80(x86_fp80, x86_fp80, x86_fp80) [[READNONE_INTRINSIC]]
+// HAS_ERRNO_ANDROID: declare double @llvm.fma.f64(double, double, double) [[READNONE_INTRINSIC:#[0-9]+]]
+// HAS_ERRNO_ANDROID: declare float @llvm.fma.f32(float, float, float) [[READNONE_INTRINSIC]]
+// HAS_ERRNO_ANDROID: declare x86_fp80 @llvm.fma.f80(x86_fp80, x86_fp80, x86_fp80) [[READNONE_INTRINSIC]]
+
// HAS_ERRNO_WIN: declare double @llvm.fma.f64(double, double, double) [[READNONE_INTRINSIC:#[0-9]+]]
// HAS_ERRNO_WIN: declare float @llvm.fma.f32(float, float, float) [[READNONE_INTRINSIC]]
// Long double is just double on win, so no f80 use/declaration.
@@ -568,11 +581,14 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) {
// NO__ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} }
// NO__ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} }
// NO__ERRNO: attributes [[NOT_READNONE]] = { nounwind "correctly{{.*}} }
+// NO__ERRNO: attributes [[PURE]] = { {{.*}}readonly{{.*}} }
// HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind "correctly{{.*}} }
// HAS_ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} }
+// HAS_ERRNO: attributes [[PURE]] = { {{.*}}readonly{{.*}} }
// HAS_ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} }
// HAS_ERRNO_GNU: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} }
+// HAS_ERRNO_ANDROID: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} }
// HAS_ERRNO_WIN: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} }
diff --git a/test/CodeGen/may-alias.c b/test/CodeGen/may-alias.c
index 41eda8587068..cba62af4bb92 100644
--- a/test/CodeGen/may-alias.c
+++ b/test/CodeGen/may-alias.c
@@ -1,18 +1,24 @@
-// RUN: %clang_cc1 -Werror -triple i386-unknown-unknown -emit-llvm -O1 -no-struct-path-tbaa -disable-llvm-passes -o - %s | FileCheck %s
-// RUN: %clang_cc1 -Werror -triple i386-unknown-unknown -emit-llvm -O1 -disable-llvm-passes -o - %s | FileCheck %s -check-prefix=PATH
+// RUN: %clang_cc1 -Werror -triple i386-unknown-unknown -emit-llvm -O1 \
+// RUN: -no-struct-path-tbaa -disable-llvm-passes -o - %s | \
+// RUN: FileCheck -allow-deprecated-dag-overlap %s -check-prefixes=CHECK,SCALAR
+// RUN: %clang_cc1 -Werror -triple i386-unknown-unknown -emit-llvm -O1 \
+// RUN: -disable-llvm-passes -o - %s | \
+// RUN: FileCheck -allow-deprecated-dag-overlap %s -check-prefixes=CHECK,OLD-PATH
+// RUN: %clang_cc1 -Werror -triple i386-unknown-unknown -emit-llvm -O1 \
+// RUN: -new-struct-path-tbaa -disable-llvm-passes -o - %s | \
+// RUN: FileCheck -allow-deprecated-dag-overlap %s -check-prefixes=CHECK,NEW-PATH
// Types with the may_alias attribute should be considered equivalent
// to char for aliasing.
typedef int __attribute__((may_alias)) aliasing_int;
-void test0(aliasing_int *ai, int *i)
-{
-// CHECK: store i32 0, i32* %{{.*}}, !tbaa [[TAG_CHAR:!.*]]
-// PATH: store i32 0, i32* %{{.*}}, !tbaa [[TAG_CHAR:!.*]]
+void test0(aliasing_int *ai, int *i) {
+// CHECK-LABEL: test0
+// CHECK: store i32 0, {{.*}}, !tbaa [[TAG_alias_int:!.*]]
*ai = 0;
-// CHECK: store i32 1, i32* %{{.*}}, !tbaa [[TAG_INT:!.*]]
-// PATH: store i32 1, i32* %{{.*}}, !tbaa [[TAG_INT:!.*]]
+
+// CHECK: store i32 1, {{.*}}, !tbaa [[TAG_int:!.*]]
*i = 1;
}
@@ -20,23 +26,36 @@ void test0(aliasing_int *ai, int *i)
struct Test1 { int x; };
struct Test1MA { int x; } __attribute__((may_alias));
void test1(struct Test1MA *p1, struct Test1 *p2) {
- // CHECK: store i32 2, i32* {{%.*}}, !tbaa [[TAG_CHAR]]
- // PATH: store i32 2, i32* {{%.*}}, !tbaa [[TAG_CHAR]]
+// CHECK-LABEL: test1
+// CHECK: store i32 2, {{.*}}, !tbaa [[TAG_alias_test1_x:!.*]]
p1->x = 2;
- // CHECK: store i32 3, i32* {{%.*}}, !tbaa [[TAG_INT]]
- // PATH: store i32 3, i32* {{%.*}}, !tbaa [[TAG_test1_x:!.*]]
+
+// CHECK: store i32 3, {{.*}}, !tbaa [[TAG_test1_x:!.*]]
p2->x = 3;
}
-// CHECK: !"any pointer", [[TYPE_CHAR:!.*]],
-// CHECK: [[TYPE_CHAR]] = !{!"omnipotent char", [[TAG_CXX_TBAA:!.*]],
-// CHECK: [[TAG_CXX_TBAA]] = !{!"Simple C/C++ TBAA"}
-// CHECK: [[TAG_CHAR]] = !{[[TYPE_CHAR]], [[TYPE_CHAR]], i64 0}
-// CHECK: [[TAG_INT]] = !{[[TYPE_INT:!.*]], [[TYPE_INT]], i64 0}
-// CHECK: [[TYPE_INT]] = !{!"int", [[TYPE_CHAR]]
-
-// PATH: [[TYPE_CHAR:!.*]] = !{!"omnipotent char", !{{.*}}
-// PATH: [[TAG_CHAR]] = !{[[TYPE_CHAR]], [[TYPE_CHAR]], i64 0}
-// PATH: [[TAG_INT]] = !{[[TYPE_INT:!.*]], [[TYPE_INT]], i64 0}
-// PATH: [[TYPE_INT]] = !{!"int", [[TYPE_CHAR]]
-// PATH: [[TAG_test1_x]] = !{[[TYPE_test1:!.*]], [[TYPE_INT]], i64 0}
-// PATH: [[TYPE_test1]] = !{!"Test1", [[TYPE_INT]], i64 0}
+
+// SCALAR-DAG: [[ROOT:!.*]] = !{!"Simple C/C++ TBAA"}
+// SCALAR-DAG: [[TYPE_char:!.*]] = !{!"omnipotent char", [[ROOT]], i64 0}
+// SCALAR-DAG: [[TAG_alias_int]] = !{[[TYPE_char]], [[TYPE_char]], i64 0}
+// SCALAR-DAG: [[TAG_alias_test1_x]] = !{[[TYPE_char]], [[TYPE_char]], i64 0}
+// SCALAR-DAG: [[TYPE_int:!.*]] = !{!"int", [[TYPE_char]], i64 0}
+// SCALAR-DAG: [[TAG_int]] = !{[[TYPE_int]], [[TYPE_int]], i64 0}
+// SCALAR-DAG: [[TAG_test1_x]] = !{[[TYPE_int]], [[TYPE_int]], i64 0}
+
+// OLD-PATH-DAG: [[ROOT:!.*]] = !{!"Simple C/C++ TBAA"}
+// OLD-PATH-DAG: [[TYPE_char:!.*]] = !{!"omnipotent char", [[ROOT]], i64 0}
+// OLD-PATH-DAG: [[TAG_alias_int]] = !{[[TYPE_char]], [[TYPE_char]], i64 0}
+// OLD-PATH-DAG: [[TAG_alias_test1_x]] = !{[[TYPE_char]], [[TYPE_char]], i64 0}
+// OLD-PATH-DAG: [[TYPE_int:!.*]] = !{!"int", [[TYPE_char]], i64 0}
+// OLD-PATH-DAG: [[TAG_int]] = !{[[TYPE_int]], [[TYPE_int]], i64 0}
+// OLD-PATH-DAG: [[TYPE_test1:!.*]] = !{!"Test1", [[TYPE_int]], i64 0}
+// OLD-PATH-DAG: [[TAG_test1_x]] = !{[[TYPE_test1]], [[TYPE_int]], i64 0}
+
+// NEW-PATH-DAG: [[ROOT:!.*]] = !{!"Simple C/C++ TBAA"}
+// NEW-PATH-DAG: [[TYPE_char:!.*]] = !{[[ROOT]], i64 1, !"omnipotent char"}
+// NEW-PATH-DAG: [[TAG_alias_int]] = !{[[TYPE_char]], [[TYPE_char]], i64 0, i64 0}
+// NEW-PATH-DAG: [[TAG_alias_test1_x]] = !{[[TYPE_char]], [[TYPE_char]], i64 0, i64 0}
+// NEW-PATH-DAG: [[TYPE_int:!.*]] = !{[[TYPE_char]], i64 4, !"int"}
+// NEW-PATH-DAG: [[TAG_int]] = !{[[TYPE_int]], [[TYPE_int]], i64 0, i64 4}
+// NEW-PATH-DAG: [[TYPE_test1:!.*]] = !{[[TYPE_char]], i64 4, !"Test1", [[TYPE_int]], i64 0, i64 4}
+// NEW-PATH-DAG: [[TAG_test1_x]] = !{[[TYPE_test1]], [[TYPE_int]], i64 0, i64 4}
diff --git a/test/CodeGen/mbackchain-2.c b/test/CodeGen/mbackchain-2.c
index e76afaf7687a..bea46d248263 100644
--- a/test/CodeGen/mbackchain-2.c
+++ b/test/CodeGen/mbackchain-2.c
@@ -1,6 +1,6 @@
// RUN: %clang -mbackchain --target=s390x-linux -S -emit-llvm -o - %s | FileCheck %s
-// CHECK: define void @foo() [[NUW:#[0-9]+]]
+// CHECK: define dso_local void @foo() [[NUW:#[0-9]+]]
void foo(void) {
}
diff --git a/test/CodeGen/mbackchain-3.c b/test/CodeGen/mbackchain-3.c
index b115861f5e02..5ff0e1676100 100644
--- a/test/CodeGen/mbackchain-3.c
+++ b/test/CodeGen/mbackchain-3.c
@@ -1,6 +1,6 @@
// RUN: %clang -mno-backchain --target=s390x-linux -S -emit-llvm -o - %s | FileCheck %s
-// CHECK: define void @foo() [[NUW:#[0-9]+]]
+// CHECK: define dso_local void @foo() [[NUW:#[0-9]+]]
void foo(void) {
}
diff --git a/test/CodeGen/mcount.c b/test/CodeGen/mcount.c
index 98a2a6b39092..c67cf03c0016 100644
--- a/test/CodeGen/mcount.c
+++ b/test/CodeGen/mcount.c
@@ -3,20 +3,20 @@
// RUN: %clang_cc1 -pg -triple powerpc-unknown-gnu-linux -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
// RUN: %clang_cc1 -pg -triple powerpc64-unknown-gnu-linux -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
// RUN: %clang_cc1 -pg -triple powerpc64le-unknown-gnu-linux -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
-// RUN: %clang_cc1 -pg -triple i386-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
-// RUN: %clang_cc1 -pg -triple x86_64-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
-// RUN: %clang_cc1 -pg -triple arm-netbsd-eabi -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
-// RUN: %clang_cc1 -pg -triple aarch64-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
-// RUN: %clang_cc1 -pg -triple mips-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
+// RUN: %clang_cc1 -pg -triple i386-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-DOUBLE-PREFIXED,NO-MCOUNT1 %s
+// RUN: %clang_cc1 -pg -triple x86_64-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-DOUBLE-PREFIXED,NO-MCOUNT1 %s
+// RUN: %clang_cc1 -pg -triple arm-netbsd-eabi -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-DOUBLE-PREFIXED,NO-MCOUNT1 %s
+// RUN: %clang_cc1 -pg -triple aarch64-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-DOUBLE-PREFIXED,NO-MCOUNT1 %s
+// RUN: %clang_cc1 -pg -triple mips-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-DOUBLE-PREFIXED,NO-MCOUNT1 %s
// RUN: %clang_cc1 -pg -triple mips-unknown-gnu-linux -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
// RUN: %clang_cc1 -pg -triple mipsel-unknown-gnu-linux -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
// RUN: %clang_cc1 -pg -triple mips64-unknown-gnu-linux -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
// RUN: %clang_cc1 -pg -triple mips64el-unknown-gnu-linux -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
-// RUN: %clang_cc1 -pg -triple powerpc-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
-// RUN: %clang_cc1 -pg -triple powerpc64-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
-// RUN: %clang_cc1 -pg -triple powerpc64le-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
-// RUN: %clang_cc1 -pg -triple sparc-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
-// RUN: %clang_cc1 -pg -triple sparc64-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
+// RUN: %clang_cc1 -pg -triple powerpc-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-DOUBLE-PREFIXED,NO-MCOUNT1 %s
+// RUN: %clang_cc1 -pg -triple powerpc64-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-DOUBLE-PREFIXED,NO-MCOUNT1 %s
+// RUN: %clang_cc1 -pg -triple powerpc64le-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-DOUBLE-PREFIXED,NO-MCOUNT1 %s
+// RUN: %clang_cc1 -pg -triple sparc-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-DOUBLE-PREFIXED,NO-MCOUNT1 %s
+// RUN: %clang_cc1 -pg -triple sparc64-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-DOUBLE-PREFIXED,NO-MCOUNT1 %s
// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s -check-prefix=NO-MCOUNT
int bar(void) {
@@ -39,5 +39,7 @@ int main(void) {
// CHECK: attributes #1 = { {{.*}} }
// CHECK-PREFIXED: attributes #0 = { {{.*}}"instrument-function-entry-inlined"="_mcount"{{.*}} }
// CHECK-PREFIXED: attributes #1 = { {{.*}} }
+// CHECK-DOUBLE-PREFIXED: attributes #0 = { {{.*}}"instrument-function-entry-inlined"="__mcount"{{.*}} }
+// CHECK-DOUBLE-PREFIXED: attributes #1 = { {{.*}} }
// NO-MCOUNT-NOT: attributes #{{[0-9]}} = { {{.*}}"instrument-function-entry-inlined"={{.*}} }
// NO-MCOUNT1-NOT: attributes #1 = { {{.*}}"instrument-function-entry-inlined"={{.*}} }
diff --git a/test/CodeGen/microsoft-call-conv-x64.c b/test/CodeGen/microsoft-call-conv-x64.c
index 6475dfa2936d..5be748f94c5a 100644
--- a/test/CodeGen/microsoft-call-conv-x64.c
+++ b/test/CodeGen/microsoft-call-conv-x64.c
@@ -3,12 +3,12 @@
void __fastcall f1(void);
void __stdcall f2(void);
void __fastcall f4(void) {
-// CHECK-LABEL: define void @f4()
+// CHECK-LABEL: define dso_local void @f4()
f1();
// CHECK: call void @f1()
}
void __stdcall f5(void) {
-// CHECK-LABEL: define void @f5()
+// CHECK-LABEL: define dso_local void @f5()
f2();
// CHECK: call void @f2()
}
diff --git a/test/CodeGen/mingw-long-double.c b/test/CodeGen/mingw-long-double.c
index 1c7c31f88be3..6026c24b367d 100644
--- a/test/CodeGen/mingw-long-double.c
+++ b/test/CodeGen/mingw-long-double.c
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -o - %s \
// RUN: | FileCheck %s --check-prefix=GNU32
+// RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -o - %s -mms-bitfields \
+// RUN: | FileCheck %s --check-prefix=GNU32
// RUN: %clang_cc1 -triple x86_64-windows-gnu -emit-llvm -o - %s \
// RUN: | FileCheck %s --check-prefix=GNU64
// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -o - %s \
@@ -10,32 +12,36 @@ struct {
long double ldb;
} agggregate_LD = {};
// GNU32: %struct.anon = type { i8, x86_fp80 }
-// GNU32: @agggregate_LD = global %struct.anon zeroinitializer, align 4
+// GNU32: @agggregate_LD = dso_local global %struct.anon zeroinitializer, align 4
// GNU64: %struct.anon = type { i8, x86_fp80 }
-// GNU64: @agggregate_LD = global %struct.anon zeroinitializer, align 16
+// GNU64: @agggregate_LD = dso_local global %struct.anon zeroinitializer, align 16
// MSC64: %struct.anon = type { i8, double }
-// MSC64: @agggregate_LD = global %struct.anon zeroinitializer, align 8
+// MSC64: @agggregate_LD = dso_local global %struct.anon zeroinitializer, align 8
long double dataLD = 1.0L;
-// GNU32: @dataLD = global x86_fp80 0xK3FFF8000000000000000, align 4
-// GNU64: @dataLD = global x86_fp80 0xK3FFF8000000000000000, align 16
-// MSC64: @dataLD = global double 1.000000e+00, align 8
+// GNU32: @dataLD = dso_local global x86_fp80 0xK3FFF8000000000000000, align 4
+// GNU64: @dataLD = dso_local global x86_fp80 0xK3FFF8000000000000000, align 16
+// MSC64: @dataLD = dso_local global double 1.000000e+00, align 8
long double _Complex dataLDC = {1.0L, 1.0L};
-// GNU32: @dataLDC = global { x86_fp80, x86_fp80 } { x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK3FFF8000000000000000 }, align 4
-// GNU64: @dataLDC = global { x86_fp80, x86_fp80 } { x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK3FFF8000000000000000 }, align 16
-// MSC64: @dataLDC = global { double, double } { double 1.000000e+00, double 1.000000e+00 }, align 8
+// GNU32: @dataLDC = dso_local global { x86_fp80, x86_fp80 } { x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK3FFF8000000000000000 }, align 4
+// GNU64: @dataLDC = dso_local global { x86_fp80, x86_fp80 } { x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK3FFF8000000000000000 }, align 16
+// MSC64: @dataLDC = dso_local global { double, double } { double 1.000000e+00, double 1.000000e+00 }, align 8
long double TestLD(long double x) {
return x * x;
}
-// GNU32: define x86_fp80 @TestLD(x86_fp80 %x)
-// GNU64: define void @TestLD(x86_fp80* noalias sret %agg.result, x86_fp80*)
-// MSC64: define double @TestLD(double %x)
+// GNU32: define dso_local x86_fp80 @TestLD(x86_fp80 %x)
+// GNU64: define dso_local void @TestLD(x86_fp80* noalias sret %agg.result, x86_fp80*)
+// MSC64: define dso_local double @TestLD(double %x)
long double _Complex TestLDC(long double _Complex x) {
return x * x;
}
-// GNU32: define void @TestLDC({ x86_fp80, x86_fp80 }* noalias sret %agg.result, { x86_fp80, x86_fp80 }* byval align 4 %x)
-// GNU64: define void @TestLDC({ x86_fp80, x86_fp80 }* noalias sret %agg.result, { x86_fp80, x86_fp80 }* %x)
-// MSC64: define void @TestLDC({ double, double }* noalias sret %agg.result, { double, double }* %x)
+// GNU32: define dso_local void @TestLDC({ x86_fp80, x86_fp80 }* noalias sret %agg.result, { x86_fp80, x86_fp80 }* byval align 4 %x)
+// GNU64: define dso_local void @TestLDC({ x86_fp80, x86_fp80 }* noalias sret %agg.result, { x86_fp80, x86_fp80 }* %x)
+// MSC64: define dso_local void @TestLDC({ double, double }* noalias sret %agg.result, { double, double }* %x)
+
+// GNU32: declare dso_local void @__mulxc3
+// GNU64: declare dso_local void @__mulxc3
+// MSC64: declare dso_local void @__muldc3
diff --git a/test/CodeGen/mips-vector-return.c b/test/CodeGen/mips-vector-return.c
index 8af4998cdf7c..dd3c400c0197 100644
--- a/test/CodeGen/mips-vector-return.c
+++ b/test/CodeGen/mips-vector-return.c
@@ -8,13 +8,13 @@ typedef float v4sf __attribute__ ((__vector_size__ (16)));
typedef double v4df __attribute__ ((__vector_size__ (32)));
typedef int v4i32 __attribute__ ((__vector_size__ (16)));
-// O32-LABEL: define void @test_v4sf(<4 x float>* noalias nocapture sret
+// O32-LABEL: define dso_local void @test_v4sf(<4 x float>* noalias nocapture sret
// N64: define inreg { i64, i64 } @test_v4sf
v4sf test_v4sf(float a) {
return (v4sf){0.0f, a, 0.0f, 0.0f};
}
-// O32-LABEL: define void @test_v4df(<4 x double>* noalias nocapture sret
+// O32-LABEL: define dso_local void @test_v4df(<4 x double>* noalias nocapture sret
// N64-LABEL: define void @test_v4df(<4 x double>* noalias nocapture sret
v4df test_v4df(double a) {
return (v4df){0.0, a, 0.0, 0.0};
@@ -23,7 +23,7 @@ v4df test_v4df(double a) {
// O32 returns integer vectors whose size is equal to or smaller than 16-bytes
// in integer registers.
//
-// O32: define inreg { i32, i32, i32, i32 } @test_v4i32
+// O32: define dso_local inreg { i32, i32, i32, i32 } @test_v4i32
// N64: define inreg { i64, i64 } @test_v4i32
v4i32 test_v4i32(int a) {
return (v4i32){0, a, 0, 0};
diff --git a/test/CodeGen/mms-bitfields.c b/test/CodeGen/mms-bitfields.c
index 1617e8ac40d9..d4604fbaa44e 100644
--- a/test/CodeGen/mms-bitfields.c
+++ b/test/CodeGen/mms-bitfields.c
@@ -20,3 +20,46 @@ struct s3 {
} s3;
// CHECK: %struct.s3 = type { i32, [4 x i8], %struct.s1 }
+
+// PR32482:
+
+#pragma pack (push,1)
+
+typedef unsigned int UINT32;
+
+struct Inner {
+ UINT32 A : 1;
+ UINT32 B : 1;
+ UINT32 C : 1;
+ UINT32 D : 30;
+} Inner;
+
+#pragma pack (pop)
+
+// CHECK: %struct.Inner = type { i32, i32 }
+
+// CHECK: %struct.A = type { i32, i32, i32 }
+
+#pragma pack(push, 1)
+
+union HEADER {
+ struct A {
+ int : 3; // Bits 2:0
+ int a : 9; // Bits 11:3
+ int : 12; // Bits 23:12
+ int b : 17; // Bits 40:24
+ int : 7; // Bits 47:41
+ int c : 4; // Bits 51:48
+ int : 4; // Bits 55:52
+ int d : 3; // Bits 58:56
+ int : 5; // Bits 63:59
+ } Bits;
+} HEADER;
+
+#pragma pack(pop)
+
+struct Inner variable = { 1,0,1, 21 };
+union HEADER hdr = {{1,2,3,4}};
+
+// CHECK: @variable = global { i8, [3 x i8], i8, i8, i8, i8 } { i8 5, [3 x i8] undef, i8 21, i8 0, i8 0, i8 0 }, align 1
+// CHECK: @hdr = global { { i8, i8, [2 x i8], i8, i8, i8, i8, i8, [3 x i8] } } { { i8, i8, [2 x i8], i8, i8, i8, i8, i8, [3 x i8] } { i8 8, i8 0, [2 x i8] undef, i8 2, i8 0, i8 0, i8 3, i8 4, [3 x i8] undef } }, align 1
diff --git a/test/CodeGen/mmx-builtins.c b/test/CodeGen/mmx-builtins.c
index cd725e22b83c..ab01c7bd5a52 100644
--- a/test/CodeGen/mmx-builtins.c
+++ b/test/CodeGen/mmx-builtins.c
@@ -2,7 +2,7 @@
// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +ssse3 -fno-signed-char -emit-llvm -o - -Wall -Werror | FileCheck %s
-#include <x86intrin.h>
+#include <immintrin.h>
__m64 test_mm_abs_pi8(__m64 a) {
// CHECK-LABEL: test_mm_abs_pi8
diff --git a/test/CodeGen/ms-align-tentative.c b/test/CodeGen/ms-align-tentative.c
index eb68e69f586b..ae9b4b10241c 100644
--- a/test/CodeGen/ms-align-tentative.c
+++ b/test/CodeGen/ms-align-tentative.c
@@ -1,25 +1,25 @@
// RUN: %clang_cc1 -triple i386-pc-win32 -emit-llvm -fms-compatibility -o - < %s | FileCheck %s
char __declspec(align(8192)) x;
-// CHECK-DAG: @x = global i8 0, align 8192
+// CHECK-DAG: @x = dso_local global i8 0, align 8192
typedef char __declspec(align(8192)) T;
T y;
-// CHECK-DAG: @y = global i8 0, align 8192
+// CHECK-DAG: @y = dso_local global i8 0, align 8192
T __declspec(align(8192)) z;
-// CHECK-DAG: @z = global i8 0, align 8192
+// CHECK-DAG: @z = dso_local global i8 0, align 8192
int __declspec(align(16)) redef;
int __declspec(align(32)) redef = 8;
-// CHECK-DAG: @redef = global i32 8, align 32
+// CHECK-DAG: @redef = dso_local global i32 8, align 32
struct __declspec(align(64)) S {
char fd;
} s;
-// CHECK-DAG: @s = global %struct.S zeroinitializer, align 64
+// CHECK-DAG: @s = dso_local global %struct.S zeroinitializer, align 64
struct Wrap {
struct S x;
} w;
-// CHECK-DAG: @w = global %struct.Wrap zeroinitializer, align 64
+// CHECK-DAG: @w = dso_local global %struct.Wrap zeroinitializer, align 64
diff --git a/test/CodeGen/ms-annotation.c b/test/CodeGen/ms-annotation.c
index 6f4a20c7b154..8ad48366bfda 100644
--- a/test/CodeGen/ms-annotation.c
+++ b/test/CodeGen/ms-annotation.c
@@ -11,7 +11,7 @@ void test1(void) {
__annotation(L"unicode: \u0ca0_\u0ca0");
}
-// CHECK-LABEL: define void @test1()
+// CHECK-LABEL: define dso_local void @test1()
// CHECK: call void @llvm.codeview.annotation(metadata ![[A1:[0-9]+]])
// CHECK: call void @llvm.codeview.annotation(metadata ![[A2:[0-9]+]])
// CHECK: call void @llvm.codeview.annotation(metadata ![[A3:[0-9]+]])
diff --git a/test/CodeGen/ms-barriers-intrinsics.c b/test/CodeGen/ms-barriers-intrinsics.c
index c7da50cd0d83..7f87c9017046 100644
--- a/test/CodeGen/ms-barriers-intrinsics.c
+++ b/test/CodeGen/ms-barriers-intrinsics.c
@@ -12,26 +12,26 @@ typedef __SIZE_TYPE__ size_t;
#include <intrin.h>
void test_ReadWriteBarrier() { _ReadWriteBarrier(); }
-// CHECK-LABEL: define void @test_ReadWriteBarrier
+// CHECK-LABEL: define dso_local void @test_ReadWriteBarrier
// CHECK: fence syncscope("singlethread") seq_cst
// CHECK: ret void
// CHECK: }
void test_ReadBarrier() { _ReadBarrier(); }
-// CHECK-LABEL: define void @test_ReadBarrier
+// CHECK-LABEL: define dso_local void @test_ReadBarrier
// CHECK: fence syncscope("singlethread") seq_cst
// CHECK: ret void
// CHECK: }
void test_WriteBarrier() { _WriteBarrier(); }
-// CHECK-LABEL: define void @test_WriteBarrier
+// CHECK-LABEL: define dso_local void @test_WriteBarrier
// CHECK: fence syncscope("singlethread") seq_cst
// CHECK: ret void
// CHECK: }
#if defined(__x86_64__)
void test__faststorefence() { __faststorefence(); }
-// CHECK-X64-LABEL: define void @test__faststorefence
+// CHECK-X64-LABEL: define dso_local void @test__faststorefence
// CHECK-X64: fence seq_cst
// CHECK-X64: ret void
// CHECK-X64: }
diff --git a/test/CodeGen/ms-declspecs.c b/test/CodeGen/ms-declspecs.c
index 05810bb4b71c..68d964003ec8 100644
--- a/test/CodeGen/ms-declspecs.c
+++ b/test/CodeGen/ms-declspecs.c
@@ -2,14 +2,14 @@
__declspec(selectany) int x1 = 1;
const __declspec(selectany) int x2 = 2;
-// CHECK: @x1 = weak_odr global i32 1, comdat, align 4
-// CHECK: @x2 = weak_odr constant i32 2, comdat, align 4
+// CHECK: @x1 = weak_odr dso_local global i32 1, comdat, align 4
+// CHECK: @x2 = weak_odr dso_local constant i32 2, comdat, align 4
// selectany turns extern variable declarations into definitions.
__declspec(selectany) int x3;
extern __declspec(selectany) int x4;
-// CHECK: @x3 = weak_odr global i32 0, comdat, align 4
-// CHECK: @x4 = weak_odr global i32 0, comdat, align 4
+// CHECK: @x3 = weak_odr dso_local global i32 0, comdat, align 4
+// CHECK: @x4 = weak_odr dso_local global i32 0, comdat, align 4
struct __declspec(align(16)) S {
char x;
@@ -19,14 +19,14 @@ union { struct S s; } u;
// CHECK: @u = {{.*}}zeroinitializer, align 16
-// CHECK: define void @t3() [[NAKED:#[0-9]+]] {
+// CHECK: define dso_local void @t3() [[NAKED:#[0-9]+]] {
__declspec(naked) void t3() {}
-// CHECK: define void @t22() [[NUW:#[0-9]+]]
+// CHECK: define dso_local void @t22() [[NUW:#[0-9]+]]
void __declspec(nothrow) t22();
void t22() {}
-// CHECK: define void @t2() [[NI:#[0-9]+]] {
+// CHECK: define dso_local void @t2() [[NI:#[0-9]+]] {
__declspec(noinline) void t2() {}
// CHECK: call void @f20_t() [[NR:#[0-9]+]]
diff --git a/test/CodeGen/ms-declspecs.cpp b/test/CodeGen/ms-declspecs.cpp
index decf5d6fcb22..99e39f9c9ea7 100644
--- a/test/CodeGen/ms-declspecs.cpp
+++ b/test/CodeGen/ms-declspecs.cpp
@@ -8,8 +8,8 @@ extern "C" {
__declspec(selectany) int x4;
}
__declspec(selectany) int x5;
-// CHECK: @"\01?x1@@3HA" = weak_odr global i32 0, comdat, align 4
-// CHECK: @x2 = weak_odr global i32 0, comdat, align 4
-// CHECK: @"\01?x3@@3HA" = weak_odr global i32 0, comdat, align 4
-// CHECK: @x4 = weak_odr global i32 0, comdat, align 4
-// CHECK: @"\01?x5@@3HA" = weak_odr global i32 0, comdat, align 4
+// CHECK: @"?x1@@3HA" = weak_odr dso_local global i32 0, comdat, align 4
+// CHECK: @x2 = weak_odr dso_local global i32 0, comdat, align 4
+// CHECK: @"?x3@@3HA" = weak_odr dso_local global i32 0, comdat, align 4
+// CHECK: @x4 = weak_odr dso_local global i32 0, comdat, align 4
+// CHECK: @"?x5@@3HA" = weak_odr dso_local global i32 0, comdat, align 4
diff --git a/test/CodeGen/ms-inline-asm-align.c b/test/CodeGen/ms-inline-asm-align.c
index de896b8e60d6..4786b2fe6e6c 100644
--- a/test/CodeGen/ms-inline-asm-align.c
+++ b/test/CodeGen/ms-inline-asm-align.c
@@ -21,7 +21,7 @@ void align_test() {
// DARWIN-SAME: .align 8
// DARWIN-SAME: "~{dirflag},~{fpsr},~{flags}"()
-// WINDOWS-LABEL: define void @align_test()
+// WINDOWS-LABEL: define dso_local void @align_test()
// WINDOWS: call void asm sideeffect inteldialect
// WINDOWS-SAME: .align 8
// WINDOWS-SAME: .align 16
diff --git a/test/CodeGen/ms-inline-asm-avx512.c b/test/CodeGen/ms-inline-asm-avx512.c
index 6189e50d2116..76c0a57250b3 100644
--- a/test/CodeGen/ms-inline-asm-avx512.c
+++ b/test/CodeGen/ms-inline-asm-avx512.c
@@ -21,7 +21,7 @@ void t2() {
}
void ignore_fe_size() {
- // CHECK-LABEL: define void @ignore_fe_size()
+ // CHECK-LABEL: define dso_local void @ignore_fe_size()
char c;
// CHECK: vaddps xmm1, xmm2, $1{1to4}
__asm vaddps xmm1, xmm2, [c]{1to4}
diff --git a/test/CodeGen/ms-inline-asm.c b/test/CodeGen/ms-inline-asm.c
index 5c3e3ff2a843..edcbaa8aa455 100644
--- a/test/CodeGen/ms-inline-asm.c
+++ b/test/CodeGen/ms-inline-asm.c
@@ -754,6 +754,13 @@ void mxcsr() {
// CHECK-LABEL: define void @mxcsr
// CHECK: call void asm sideeffect inteldialect "fxrstor $0", "=*m,~{dirflag},~{fpsr},~{flags}"
+// Make sure we can find the register for the dirflag for popfd
+void dirflag() {
+ __asm popfd
+}
+// CHECK-LABEL: define void @dirflag
+// CHECK: call void asm sideeffect inteldialect "popfd", "~{dirflag},~{flags},~{esp},~{dirflag},~{fpsr},~{flags}"
+
typedef union _LARGE_INTEGER {
struct {
unsigned int LowPart;
diff --git a/test/CodeGen/ms-intrinsics-other.c b/test/CodeGen/ms-intrinsics-other.c
index d23bc7301801..65d767058462 100644
--- a/test/CodeGen/ms-intrinsics-other.c
+++ b/test/CodeGen/ms-intrinsics-other.c
@@ -148,14 +148,3 @@ LONG test_InterlockedDecrement(LONG volatile *Addend) {
// CHECK: [[RESULT:%[0-9]+]] = add i32 [[TMP]], -1
// CHECK: ret i32 [[RESULT]]
// CHECK: }
-
-unsigned char test_interlockedbittestandset(volatile LONG *ptr, LONG bit) {
- return _interlockedbittestandset(ptr, bit);
-}
-// CHECK-LABEL: define{{.*}} i8 @test_interlockedbittestandset
-// CHECK: [[MASKBIT:%[0-9]+]] = shl i32 1, %bit
-// CHECK: [[OLD:%[0-9]+]] = atomicrmw or i32* %ptr, i32 [[MASKBIT]] seq_cst
-// CHECK: [[SHIFT:%[0-9]+]] = lshr i32 [[OLD]], %bit
-// CHECK: [[TRUNC:%[0-9]+]] = trunc i32 [[SHIFT]] to i8
-// CHECK: [[AND:%[0-9]+]] = and i8 [[TRUNC]], 1
-// CHECK: ret i8 [[AND]]
diff --git a/test/CodeGen/ms-intrinsics-rotations.c b/test/CodeGen/ms-intrinsics-rotations.c
index 9533e6c3c6a2..735de6e41e68 100644
--- a/test/CodeGen/ms-intrinsics-rotations.c
+++ b/test/CodeGen/ms-intrinsics-rotations.c
@@ -30,13 +30,12 @@ unsigned char test_rotl8(unsigned char value, unsigned char shift) {
return _rotl8(value, shift);
}
// CHECK: i8 @test_rotl8
-// CHECK: [[SHIFT:%[0-9]+]] = and i8 %{{[0-9]+}}, 7
-// CHECK: [[NEGSHIFT:%[0-9]+]] = sub i8 8, [[SHIFT]]
-// CHECK: [[HIGH:%[0-9]+]] = shl i8 [[VALUE:%[0-9]+]], [[SHIFT]]
-// CHECK: [[LOW:%[0-9]+]] = lshr i8 [[VALUE]], [[NEGSHIFT]]
-// CHECK: [[ROTATED:%[0-9]+]] = or i8 [[HIGH]], [[LOW]]
-// CHECK: [[ISZERO:%[0-9]+]] = icmp eq i8 [[SHIFT]], 0
-// CHECK: [[RESULT:%[0-9]+]] = select i1 [[ISZERO]], i8 [[VALUE]], i8 [[ROTATED]]
+// CHECK: [[LSHIFT:%[0-9]+]] = and i8 [[SHIFT:%[0-9]+]], 7
+// CHECK: [[HIGH:%[0-9]+]] = shl i8 [[VALUE:%[0-9]+]], [[LSHIFT]]
+// CHECK: [[NEGATE:%[0-9]+]] = sub i8 0, [[SHIFT]]
+// CHECK: [[RSHIFT:%[0-9]+]] = and i8 [[NEGATE]], 7
+// CHECK: [[LOW:%[0-9]+]] = lshr i8 [[VALUE]], [[RSHIFT]]
+// CHECK: [[RESULT:%[0-9]+]] = or i8 [[HIGH]], [[LOW]]
// CHECK: ret i8 [[RESULT]]
// CHECK }
@@ -44,13 +43,12 @@ unsigned short test_rotl16(unsigned short value, unsigned char shift) {
return _rotl16(value, shift);
}
// CHECK: i16 @test_rotl16
-// CHECK: [[SHIFT:%[0-9]+]] = and i16 %{{[0-9]+}}, 15
-// CHECK: [[NEGSHIFT:%[0-9]+]] = sub i16 16, [[SHIFT]]
-// CHECK: [[HIGH:%[0-9]+]] = shl i16 [[VALUE:%[0-9]+]], [[SHIFT]]
-// CHECK: [[LOW:%[0-9]+]] = lshr i16 [[VALUE]], [[NEGSHIFT]]
-// CHECK: [[ROTATED:%[0-9]+]] = or i16 [[HIGH]], [[LOW]]
-// CHECK: [[ISZERO:%[0-9]+]] = icmp eq i16 [[SHIFT]], 0
-// CHECK: [[RESULT:%[0-9]+]] = select i1 [[ISZERO]], i16 [[VALUE]], i16 [[ROTATED]]
+// CHECK: [[LSHIFT:%[0-9]+]] = and i16 [[SHIFT:%[0-9]+]], 15
+// CHECK: [[HIGH:%[0-9]+]] = shl i16 [[VALUE:%[0-9]+]], [[LSHIFT]]
+// CHECK: [[NEGATE:%[0-9]+]] = sub i16 0, [[SHIFT]]
+// CHECK: [[RSHIFT:%[0-9]+]] = and i16 [[NEGATE]], 15
+// CHECK: [[LOW:%[0-9]+]] = lshr i16 [[VALUE]], [[RSHIFT]]
+// CHECK: [[RESULT:%[0-9]+]] = or i16 [[HIGH]], [[LOW]]
// CHECK: ret i16 [[RESULT]]
// CHECK }
@@ -58,13 +56,12 @@ unsigned int test_rotl(unsigned int value, int shift) {
return _rotl(value, shift);
}
// CHECK: i32 @test_rotl
-// CHECK: [[SHIFT:%[0-9]+]] = and i32 %{{[0-9]+}}, 31
-// CHECK: [[NEGSHIFT:%[0-9]+]] = sub i32 32, [[SHIFT]]
-// CHECK: [[HIGH:%[0-9]+]] = shl i32 [[VALUE:%[0-9]+]], [[SHIFT]]
-// CHECK: [[LOW:%[0-9]+]] = lshr i32 [[VALUE]], [[NEGSHIFT]]
-// CHECK: [[ROTATED:%[0-9]+]] = or i32 [[HIGH]], [[LOW]]
-// CHECK: [[ISZERO:%[0-9]+]] = icmp eq i32 [[SHIFT]], 0
-// CHECK: [[RESULT:%[0-9]+]] = select i1 [[ISZERO]], i32 [[VALUE]], i32 [[ROTATED]]
+// CHECK: [[LSHIFT:%[0-9]+]] = and i32 [[SHIFT:%[0-9]+]], 31
+// CHECK: [[HIGH:%[0-9]+]] = shl i32 [[VALUE:%[0-9]+]], [[LSHIFT]]
+// CHECK: [[NEGATE:%[0-9]+]] = sub i32 0, [[SHIFT]]
+// CHECK: [[RSHIFT:%[0-9]+]] = and i32 [[NEGATE]], 31
+// CHECK: [[LOW:%[0-9]+]] = lshr i32 [[VALUE]], [[RSHIFT]]
+// CHECK: [[RESULT:%[0-9]+]] = or i32 [[HIGH]], [[LOW]]
// CHECK: ret i32 [[RESULT]]
// CHECK }
@@ -72,13 +69,12 @@ unsigned LONG test_lrotl(unsigned LONG value, int shift) {
return _lrotl(value, shift);
}
// CHECK-32BIT-LONG: i32 @test_lrotl
-// CHECK-32BIT-LONG: [[SHIFT:%[0-9]+]] = and i32 %{{[0-9]+}}, 31
-// CHECK-32BIT-LONG: [[NEGSHIFT:%[0-9]+]] = sub i32 32, [[SHIFT]]
-// CHECK-32BIT-LONG: [[HIGH:%[0-9]+]] = shl i32 [[VALUE:%[0-9]+]], [[SHIFT]]
-// CHECK-32BIT-LONG: [[LOW:%[0-9]+]] = lshr i32 [[VALUE]], [[NEGSHIFT]]
-// CHECK-32BIT-LONG: [[ROTATED:%[0-9]+]] = or i32 [[HIGH]], [[LOW]]
-// CHECK-32BIT-LONG: [[ISZERO:%[0-9]+]] = icmp eq i32 [[SHIFT]], 0
-// CHECK-32BIT-LONG: [[RESULT:%[0-9]+]] = select i1 [[ISZERO]], i32 [[VALUE]], i32 [[ROTATED]]
+// CHECK-32BIT-LONG: [[LSHIFT:%[0-9]+]] = and i32 [[SHIFT:%[0-9]+]], 31
+// CHECK-32BIT-LONG: [[HIGH:%[0-9]+]] = shl i32 [[VALUE:%[0-9]+]], [[LSHIFT]]
+// CHECK-32BIT-LONG: [[NEGATE:%[0-9]+]] = sub i32 0, [[SHIFT]]
+// CHECK-32BIT-LONG: [[RSHIFT:%[0-9]+]] = and i32 [[NEGATE]], 31
+// CHECK-32BIT-LONG: [[LOW:%[0-9]+]] = lshr i32 [[VALUE]], [[RSHIFT]]
+// CHECK-32BIT-LONG: [[RESULT:%[0-9]+]] = or i32 [[HIGH]], [[LOW]]
// CHECK-32BIT-LONG: ret i32 [[RESULT]]
// CHECK-32BIT-LONG }
@@ -86,13 +82,12 @@ unsigned __int64 test_rotl64(unsigned __int64 value, int shift) {
return _rotl64(value, shift);
}
// CHECK: i64 @test_rotl64
-// CHECK: [[SHIFT:%[0-9]+]] = and i64 %{{[0-9]+}}, 63
-// CHECK: [[NEGSHIFT:%[0-9]+]] = sub i64 64, [[SHIFT]]
-// CHECK: [[HIGH:%[0-9]+]] = shl i64 [[VALUE:%[0-9]+]], [[SHIFT]]
-// CHECK: [[LOW:%[0-9]+]] = lshr i64 [[VALUE]], [[NEGSHIFT]]
-// CHECK: [[ROTATED:%[0-9]+]] = or i64 [[HIGH]], [[LOW]]
-// CHECK: [[ISZERO:%[0-9]+]] = icmp eq i64 [[SHIFT]], 0
-// CHECK: [[RESULT:%[0-9]+]] = select i1 [[ISZERO]], i64 [[VALUE]], i64 [[ROTATED]]
+// CHECK: [[LSHIFT:%[0-9]+]] = and i64 [[SHIFT:%[0-9]+]], 63
+// CHECK: [[HIGH:%[0-9]+]] = shl i64 [[VALUE:%[0-9]+]], [[LSHIFT]]
+// CHECK: [[NEGATE:%[0-9]+]] = sub i64 0, [[SHIFT]]
+// CHECK: [[RSHIFT:%[0-9]+]] = and i64 [[NEGATE]], 63
+// CHECK: [[LOW:%[0-9]+]] = lshr i64 [[VALUE]], [[RSHIFT]]
+// CHECK: [[RESULT:%[0-9]+]] = or i64 [[HIGH]], [[LOW]]
// CHECK: ret i64 [[RESULT]]
// CHECK }
@@ -102,41 +97,36 @@ unsigned char test_rotr8(unsigned char value, unsigned char shift) {
return _rotr8(value, shift);
}
// CHECK: i8 @test_rotr8
-// CHECK: [[SHIFT:%[0-9]+]] = and i8 %{{[0-9]+}}, 7
-// CHECK: [[NEGSHIFT:%[0-9]+]] = sub i8 8, [[SHIFT]]
-// CHECK: [[LOW:%[0-9]+]] = lshr i8 [[VALUE:%[0-9]+]], [[SHIFT]]
-// CHECK: [[HIGH:%[0-9]+]] = shl i8 [[VALUE]], [[NEGSHIFT]]
-// CHECK: [[ROTATED:%[0-9]+]] = or i8 [[HIGH]], [[LOW]]
-// CHECK: [[ISZERO:%[0-9]+]] = icmp eq i8 [[SHIFT]], 0
-// CHECK: [[RESULT:%[0-9]+]] = select i1 [[ISZERO]], i8 [[VALUE]], i8 [[ROTATED]]
-// CHECK: ret i8 [[RESULT]]
+// CHECK: [[RSHIFT:%[0-9]+]] = and i8 [[SHIFT:%[0-9]+]], 7
+// CHECK: [[LOW:%[0-9]+]] = lshr i8 [[VALUE:%[0-9]+]], [[RSHIFT]]
+// CHECK: [[NEGATE:%[0-9]+]] = sub i8 0, [[SHIFT]]
+// CHECK: [[LSHIFT:%[0-9]+]] = and i8 [[NEGATE]], 7
+// CHECK: [[HIGH:%[0-9]+]] = shl i8 [[VALUE]], [[LSHIFT]]
+// CHECK: [[RESULT:%[0-9]+]] = or i8 [[HIGH]], [[LOW]]
// CHECK }
unsigned short test_rotr16(unsigned short value, unsigned char shift) {
return _rotr16(value, shift);
}
// CHECK: i16 @test_rotr16
-// CHECK: [[SHIFT:%[0-9]+]] = and i16 %{{[0-9]+}}, 15
-// CHECK: [[NEGSHIFT:%[0-9]+]] = sub i16 16, [[SHIFT]]
-// CHECK: [[LOW:%[0-9]+]] = lshr i16 [[VALUE:%[0-9]+]], [[SHIFT]]
-// CHECK: [[HIGH:%[0-9]+]] = shl i16 [[VALUE]], [[NEGSHIFT]]
-// CHECK: [[ROTATED:%[0-9]+]] = or i16 [[HIGH]], [[LOW]]
-// CHECK: [[ISZERO:%[0-9]+]] = icmp eq i16 [[SHIFT]], 0
-// CHECK: [[RESULT:%[0-9]+]] = select i1 [[ISZERO]], i16 [[VALUE]], i16 [[ROTATED]]
-// CHECK: ret i16 [[RESULT]]
+// CHECK: [[RSHIFT:%[0-9]+]] = and i16 [[SHIFT:%[0-9]+]], 15
+// CHECK: [[LOW:%[0-9]+]] = lshr i16 [[VALUE:%[0-9]+]], [[RSHIFT]]
+// CHECK: [[NEGATE:%[0-9]+]] = sub i16 0, [[SHIFT]]
+// CHECK: [[LSHIFT:%[0-9]+]] = and i16 [[NEGATE]], 15
+// CHECK: [[HIGH:%[0-9]+]] = shl i16 [[VALUE]], [[LSHIFT]]
+// CHECK: [[RESULT:%[0-9]+]] = or i16 [[HIGH]], [[LOW]]
// CHECK }
unsigned int test_rotr(unsigned int value, int shift) {
return _rotr(value, shift);
}
// CHECK: i32 @test_rotr
-// CHECK: [[SHIFT:%[0-9]+]] = and i32 %{{[0-9]+}}, 31
-// CHECK: [[NEGSHIFT:%[0-9]+]] = sub i32 32, [[SHIFT]]
-// CHECK: [[LOW:%[0-9]+]] = lshr i32 [[VALUE:%[0-9]+]], [[SHIFT]]
-// CHECK: [[HIGH:%[0-9]+]] = shl i32 [[VALUE]], [[NEGSHIFT]]
-// CHECK: [[ROTATED:%[0-9]+]] = or i32 [[HIGH]], [[LOW]]
-// CHECK: [[ISZERO:%[0-9]+]] = icmp eq i32 [[SHIFT]], 0
-// CHECK: [[RESULT:%[0-9]+]] = select i1 [[ISZERO]], i32 [[VALUE]], i32 [[ROTATED]]
+// CHECK: [[RSHIFT:%[0-9]+]] = and i32 [[SHIFT:%[0-9]+]], 31
+// CHECK: [[LOW:%[0-9]+]] = lshr i32 [[VALUE:%[0-9]+]], [[RSHIFT]]
+// CHECK: [[NEGATE:%[0-9]+]] = sub i32 0, [[SHIFT]]
+// CHECK: [[LSHIFT:%[0-9]+]] = and i32 [[NEGATE]], 31
+// CHECK: [[HIGH:%[0-9]+]] = shl i32 [[VALUE]], [[LSHIFT]]
+// CHECK: [[RESULT:%[0-9]+]] = or i32 [[HIGH]], [[LOW]]
// CHECK: ret i32 [[RESULT]]
// CHECK }
@@ -144,13 +134,12 @@ unsigned LONG test_lrotr(unsigned LONG value, int shift) {
return _lrotr(value, shift);
}
// CHECK-32BIT-LONG: i32 @test_lrotr
-// CHECK-32BIT-LONG: [[SHIFT:%[0-9]+]] = and i32 %{{[0-9]+}}, 31
-// CHECK-32BIT-LONG: [[NEGSHIFT:%[0-9]+]] = sub i32 32, [[SHIFT]]
-// CHECK-32BIT-LONG: [[LOW:%[0-9]+]] = lshr i32 [[VALUE:%[0-9]+]], [[SHIFT]]
-// CHECK-32BIT-LONG: [[HIGH:%[0-9]+]] = shl i32 [[VALUE]], [[NEGSHIFT]]
-// CHECK-32BIT-LONG: [[ROTATED:%[0-9]+]] = or i32 [[HIGH]], [[LOW]]
-// CHECK-32BIT-LONG: [[ISZERO:%[0-9]+]] = icmp eq i32 [[SHIFT]], 0
-// CHECK-32BIT-LONG: [[RESULT:%[0-9]+]] = select i1 [[ISZERO]], i32 [[VALUE]], i32 [[ROTATED]]
+// CHECK-32BIT-LONG: [[RSHIFT:%[0-9]+]] = and i32 [[SHIFT:%[0-9]+]], 31
+// CHECK-32BIT-LONG: [[LOW:%[0-9]+]] = lshr i32 [[VALUE:%[0-9]+]], [[RSHIFT]]
+// CHECK-32BIT-LONG: [[NEGATE:%[0-9]+]] = sub i32 0, [[SHIFT]]
+// CHECK-32BIT-LONG: [[LSHIFT:%[0-9]+]] = and i32 [[NEGATE]], 31
+// CHECK-32BIT-LONG: [[HIGH:%[0-9]+]] = shl i32 [[VALUE]], [[LSHIFT]]
+// CHECK-32BIT-LONG: [[RESULT:%[0-9]+]] = or i32 [[HIGH]], [[LOW]]
// CHECK-32BIT-LONG: ret i32 [[RESULT]]
// CHECK-32BIT-LONG }
@@ -158,12 +147,11 @@ unsigned __int64 test_rotr64(unsigned __int64 value, int shift) {
return _rotr64(value, shift);
}
// CHECK: i64 @test_rotr64
-// CHECK: [[SHIFT:%[0-9]+]] = and i64 %{{[0-9]+}}, 63
-// CHECK: [[NEGSHIFT:%[0-9]+]] = sub i64 64, [[SHIFT]]
-// CHECK: [[LOW:%[0-9]+]] = lshr i64 [[VALUE:%[0-9]+]], [[SHIFT]]
-// CHECK: [[HIGH:%[0-9]+]] = shl i64 [[VALUE]], [[NEGSHIFT]]
-// CHECK: [[ROTATED:%[0-9]+]] = or i64 [[HIGH]], [[LOW]]
-// CHECK: [[ISZERO:%[0-9]+]] = icmp eq i64 [[SHIFT]], 0
-// CHECK: [[RESULT:%[0-9]+]] = select i1 [[ISZERO]], i64 [[VALUE]], i64 [[ROTATED]]
+// CHECK: [[RSHIFT:%[0-9]+]] = and i64 [[SHIFT:%[0-9]+]], 63
+// CHECK: [[LOW:%[0-9]+]] = lshr i64 [[VALUE:%[0-9]+]], [[RSHIFT]]
+// CHECK: [[NEGATE:%[0-9]+]] = sub i64 0, [[SHIFT]]
+// CHECK: [[LSHIFT:%[0-9]+]] = and i64 [[NEGATE]], 63
+// CHECK: [[HIGH:%[0-9]+]] = shl i64 [[VALUE]], [[LSHIFT]]
+// CHECK: [[RESULT:%[0-9]+]] = or i64 [[HIGH]], [[LOW]]
// CHECK: ret i64 [[RESULT]]
// CHECK }
diff --git a/test/CodeGen/ms-intrinsics.c b/test/CodeGen/ms-intrinsics.c
index 38cda9785029..a8c234123a93 100644
--- a/test/CodeGen/ms-intrinsics.c
+++ b/test/CodeGen/ms-intrinsics.c
@@ -7,6 +7,9 @@
// RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \
// RUN: -triple x86_64--windows -Oz -emit-llvm -target-feature +cx16 %s -o - \
// RUN: | FileCheck %s --check-prefixes CHECK,CHECK-X64,CHECK-ARM-X64,CHECK-INTEL
+// RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \
+// RUN: -triple aarch64-windows -Oz -emit-llvm %s -o - \
+// RUN: | FileCheck %s --check-prefix CHECK-ARM-X64
// intrin.h needs size_t, but -ffreestanding prevents us from getting it from
// stddef.h. Work around it with this typedef.
@@ -20,15 +23,98 @@ void test__stosb(unsigned char *Dest, unsigned char Data, size_t Count) {
}
// CHECK-I386: define{{.*}}void @test__stosb
-// CHECK-I386: tail call void @llvm.memset.p0i8.i32(i8* %Dest, i8 %Data, i32 %Count, i32 1, i1 true)
+// CHECK-I386: tail call void @llvm.memset.p0i8.i32(i8* align 1 %Dest, i8 %Data, i32 %Count, i1 true)
// CHECK-I386: ret void
// CHECK-I386: }
// CHECK-X64: define{{.*}}void @test__stosb
-// CHECK-X64: tail call void @llvm.memset.p0i8.i64(i8* %Dest, i8 %Data, i64 %Count, i32 1, i1 true)
+// CHECK-X64: tail call void @llvm.memset.p0i8.i64(i8* align 1 %Dest, i8 %Data, i64 %Count, i1 true)
+// CHECK-X64: ret void
+// CHECK-X64: }
+
+void test__movsb(unsigned char *Dest, unsigned char *Src, size_t Count) {
+ return __movsb(Dest, Src, Count);
+}
+// CHECK-I386-LABEL: define{{.*}} void @test__movsb
+// CHECK-I386: call { i8*, i8*, i32 } asm sideeffect "rep movsb", "={di},={si},={cx},0,1,2,~{memory},~{dirflag},~{fpsr},~{flags}"(i8* %Dest, i8* %Src, i32 %Count)
+// CHECK-I386: ret void
+// CHECK-I386: }
+
+// CHECK-X64-LABEL: define{{.*}} void @test__movsb
+// CHECK-X64: call { i8*, i8*, i64 } asm sideeffect "rep movsb", "={di},={si},={cx},0,1,2,~{memory},~{dirflag},~{fpsr},~{flags}"(i8* %Dest, i8* %Src, i64 %Count)
+// CHECK-X64: ret void
+// CHECK-X64: }
+
+void test__stosw(unsigned short *Dest, unsigned short Data, size_t Count) {
+ return __stosw(Dest, Data, Count);
+}
+// CHECK-I386-LABEL: define{{.*}} void @test__stosw
+// CHECK-I386: call { i16*, i32 } asm sideeffect "rep stosw", "={di},={cx},{ax},0,1,~{memory},~{dirflag},~{fpsr},~{flags}"(i16 %Data, i16* %Dest, i32 %Count)
+// CHECK-I386: ret void
+// CHECK-I386: }
+
+// CHECK-X64-LABEL: define{{.*}} void @test__stosw
+// CHECK-X64: call { i16*, i64 } asm sideeffect "rep stosw", "={di},={cx},{ax},0,1,~{memory},~{dirflag},~{fpsr},~{flags}"(i16 %Data, i16* %Dest, i64 %Count)
+// CHECK-X64: ret void
+// CHECK-X64: }
+
+void test__movsw(unsigned short *Dest, unsigned short *Src, size_t Count) {
+ return __movsw(Dest, Src, Count);
+}
+// CHECK-I386-LABEL: define{{.*}} void @test__movsw
+// CHECK-I386: call { i16*, i16*, i32 } asm sideeffect "rep movsw", "={di},={si},={cx},0,1,2,~{memory},~{dirflag},~{fpsr},~{flags}"(i16* %Dest, i16* %Src, i32 %Count)
+// CHECK-I386: ret void
+// CHECK-I386: }
+
+// CHECK-X64-LABEL: define{{.*}} void @test__movsw
+// CHECK-X64: call { i16*, i16*, i64 } asm sideeffect "rep movsw", "={di},={si},={cx},0,1,2,~{memory},~{dirflag},~{fpsr},~{flags}"(i16* %Dest, i16* %Src, i64 %Count)
+// CHECK-X64: ret void
+// CHECK-X64: }
+
+void test__stosd(unsigned long *Dest, unsigned long Data, size_t Count) {
+ return __stosd(Dest, Data, Count);
+}
+// CHECK-I386-LABEL: define{{.*}} void @test__stosd
+// CHECK-I386: call { i32*, i32 } asm sideeffect "rep stosl", "={di},={cx},{ax},0,1,~{memory},~{dirflag},~{fpsr},~{flags}"(i32 %Data, i32* %Dest, i32 %Count)
+// CHECK-I386: ret void
+// CHECK-I386: }
+
+// CHECK-X64-LABEL: define{{.*}} void @test__stosd
+// CHECK-X64: call { i32*, i64 } asm sideeffect "rep stosl", "={di},={cx},{ax},0,1,~{memory},~{dirflag},~{fpsr},~{flags}"(i32 %Data, i32* %Dest, i64 %Count)
+// CHECK-X64: ret void
+// CHECK-X64: }
+
+void test__movsd(unsigned long *Dest, unsigned long *Src, size_t Count) {
+ return __movsd(Dest, Src, Count);
+}
+// CHECK-I386-LABEL: define{{.*}} void @test__movsd
+// CHECK-I386: call { i32*, i32*, i32 } asm sideeffect "rep movsl", "={di},={si},={cx},0,1,2,~{memory},~{dirflag},~{fpsr},~{flags}"(i32* %Dest, i32* %Src, i32 %Count)
+// CHECK-I386: ret void
+// CHECK-I386: }
+
+// CHECK-X64-LABEL: define{{.*}} void @test__movsd
+// CHECK-X64: call { i32*, i32*, i64 } asm sideeffect "rep movsl", "={di},={si},={cx},0,1,2,~{memory},~{dirflag},~{fpsr},~{flags}"(i32* %Dest, i32* %Src, i64 %Count)
+// CHECK-X64: ret void
+// CHECK-X64: }
+
+#ifdef __x86_64__
+void test__stosq(unsigned __int64 *Dest, unsigned __int64 Data, size_t Count) {
+ return __stosq(Dest, Data, Count);
+}
+// CHECK-X64-LABEL: define{{.*}} void @test__stosq
+// CHECK-X64: call { i64*, i64 } asm sideeffect "rep stosq", "={di},={cx},{ax},0,1,~{memory},~{dirflag},~{fpsr},~{flags}"(i64 %Data, i64* %Dest, i64 %Count)
// CHECK-X64: ret void
// CHECK-X64: }
+void test__movsq(unsigned __int64 *Dest, unsigned __int64 *Src, size_t Count) {
+ return __movsq(Dest, Src, Count);
+}
+// CHECK-X64-LABEL: define{{.*}} void @test__movsq
+// CHECK-X64: call { i64*, i64*, i64 } asm sideeffect "rep movsq", "={di},={si},={cx},0,1,2,~{memory},~{dirflag},~{fpsr},~{flags}"(i64* %Dest, i64* %Src, i64 %Count)
+// CHECK-X64: ret void
+// CHECK-X64: }
+#endif
+
void test__ud2(void) {
__ud2();
}
@@ -55,7 +141,7 @@ void *test_ReturnAddress() {
void *test_AddressOfReturnAddress() {
return _AddressOfReturnAddress();
}
-// CHECK-INTEL-LABEL: define i8* @test_AddressOfReturnAddress()
+// CHECK-INTEL-LABEL: define dso_local i8* @test_AddressOfReturnAddress()
// CHECK-INTEL: = tail call i8* @llvm.addressofreturnaddress()
// CHECK-INTEL: ret i8*
#endif
@@ -89,7 +175,7 @@ unsigned char test_BitScanReverse(unsigned long *Index, unsigned long Mask) {
// CHECK: store i32 [[INDEX]], i32* %Index, align 4
// CHECK: br label %[[END_LABEL]]
-#if defined(__x86_64__) || defined(__arm__)
+#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
unsigned char test_BitScanForward64(unsigned long *Index, unsigned __int64 Mask) {
return _BitScanForward64(Index, Mask);
}
@@ -386,7 +472,7 @@ long test_InterlockedDecrement(long volatile *Addend) {
// CHECK: ret i32 [[RESULT]]
// CHECK: }
-#if defined(__x86_64__) || defined(__arm__)
+#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
__int64 test_InterlockedExchange64(__int64 volatile *value, __int64 mask) {
return _InterlockedExchange64(value, mask);
}
@@ -455,17 +541,56 @@ __int64 test_InterlockedDecrement64(__int64 volatile *Addend) {
#endif
-unsigned char test_interlockedbittestandset(volatile long *ptr, long bit) {
- return _interlockedbittestandset(ptr, bit);
+#if defined(__i386__) || defined(__x86_64__)
+long test_InterlockedExchange_HLEAcquire(long volatile *Target, long Value) {
+// CHECK-INTEL: define{{.*}} i32 @test_InterlockedExchange_HLEAcquire(i32*{{[a-z_ ]*}}%Target, i32{{[a-z_ ]*}}%Value)
+// CHECK-INTEL: call i32 asm sideeffect ".byte 0xf2 ; lock ; xchg $0, $1", "=r,=*m,0,*m,~{memory},~{dirflag},~{fpsr},~{flags}"(i32* %Target, i32 %Value, i32* %Target)
+ return _InterlockedExchange_HLEAcquire(Target, Value);
+}
+long test_InterlockedExchange_HLERelease(long volatile *Target, long Value) {
+// CHECK-INTEL: define{{.*}} i32 @test_InterlockedExchange_HLERelease(i32*{{[a-z_ ]*}}%Target, i32{{[a-z_ ]*}}%Value)
+// CHECK-INTEL: call i32 asm sideeffect ".byte 0xf3 ; lock ; xchg $0, $1", "=r,=*m,0,*m,~{memory},~{dirflag},~{fpsr},~{flags}"(i32* %Target, i32 %Value, i32* %Target)
+ return _InterlockedExchange_HLERelease(Target, Value);
+}
+long test_InterlockedCompareExchange_HLEAcquire(long volatile *Destination,
+ long Exchange, long Comparand) {
+// CHECK-INTEL: define{{.*}} i32 @test_InterlockedCompareExchange_HLEAcquire(i32*{{[a-z_ ]*}}%Destination, i32{{[a-z_ ]*}}%Exchange, i32{{[a-z_ ]*}}%Comparand)
+// CHECK-INTEL: call i32 asm sideeffect ".byte 0xf2 ; lock ; cmpxchg $2, $1", "={ax},=*m,r,0,*m,~{memory},~{dirflag},~{fpsr},~{flags}"(i32* %Destination, i32 %Exchange, i32 %Comparand, i32* %Destination)
+ return _InterlockedCompareExchange_HLEAcquire(Destination, Exchange, Comparand);
+}
+long test_InterlockedCompareExchange_HLERelease(long volatile *Destination,
+ long Exchange, long Comparand) {
+// CHECK-INTEL: define{{.*}} i32 @test_InterlockedCompareExchange_HLERelease(i32*{{[a-z_ ]*}}%Destination, i32{{[a-z_ ]*}}%Exchange, i32{{[a-z_ ]*}}%Comparand)
+// CHECK-INTEL: call i32 asm sideeffect ".byte 0xf3 ; lock ; cmpxchg $2, $1", "={ax},=*m,r,0,*m,~{memory},~{dirflag},~{fpsr},~{flags}"(i32* %Destination, i32 %Exchange, i32 %Comparand, i32* %Destination)
+ return _InterlockedCompareExchange_HLERelease(Destination, Exchange, Comparand);
}
-// CHECK-LABEL: define{{.*}} i8 @test_interlockedbittestandset
-// CHECK: [[MASKBIT:%[0-9]+]] = shl i32 1, %bit
-// CHECK: [[OLD:%[0-9]+]] = atomicrmw or i32* %ptr, i32 [[MASKBIT]] seq_cst
-// CHECK: [[SHIFT:%[0-9]+]] = lshr i32 [[OLD]], %bit
-// CHECK: [[TRUNC:%[0-9]+]] = trunc i32 [[SHIFT]] to i8
-// CHECK: [[AND:%[0-9]+]] = and i8 [[TRUNC]], 1
-// CHECK: ret i8 [[AND]]
+#endif
+#if defined(__x86_64__)
+__int64 test_InterlockedExchange64_HLEAcquire(__int64 volatile *Target, __int64 Value) {
+// CHECK-X64: define{{.*}} i64 @test_InterlockedExchange64_HLEAcquire(i64*{{[a-z_ ]*}}%Target, i64{{[a-z_ ]*}}%Value)
+// CHECK-X64: call i64 asm sideeffect ".byte 0xf2 ; lock ; xchg $0, $1", "=r,=*m,0,*m,~{memory},~{dirflag},~{fpsr},~{flags}"(i64* %Target, i64 %Value, i64* %Target)
+ return _InterlockedExchange64_HLEAcquire(Target, Value);
+}
+__int64 test_InterlockedExchange64_HLERelease(__int64 volatile *Target, __int64 Value) {
+// CHECK-X64: define{{.*}} i64 @test_InterlockedExchange64_HLERelease(i64*{{[a-z_ ]*}}%Target, i64{{[a-z_ ]*}}%Value)
+// CHECK-X64: call i64 asm sideeffect ".byte 0xf3 ; lock ; xchg $0, $1", "=r,=*m,0,*m,~{memory},~{dirflag},~{fpsr},~{flags}"(i64* %Target, i64 %Value, i64* %Target)
+ return _InterlockedExchange64_HLERelease(Target, Value);
+}
+__int64 test_InterlockedCompareExchange64_HLEAcquire(__int64 volatile *Destination,
+ __int64 Exchange, __int64 Comparand) {
+// CHECK-X64: define{{.*}} i64 @test_InterlockedCompareExchange64_HLEAcquire(i64*{{[a-z_ ]*}}%Destination, i64{{[a-z_ ]*}}%Exchange, i64{{[a-z_ ]*}}%Comparand)
+// CHECK-X64: call i64 asm sideeffect ".byte 0xf2 ; lock ; cmpxchg $2, $1", "={ax},=*m,r,0,*m,~{memory},~{dirflag},~{fpsr},~{flags}"(i64* %Destination, i64 %Exchange, i64 %Comparand, i64* %Destination)
+ return _InterlockedCompareExchange64_HLEAcquire(Destination, Exchange, Comparand);
+}
+__int64 test_InterlockedCompareExchange64_HLERelease(__int64 volatile *Destination,
+ __int64 Exchange, __int64 Comparand) {
+// CHECK-X64: define{{.*}} i64 @test_InterlockedCompareExchange64_HLERelease(i64*{{[a-z_ ]*}}%Destination, i64{{[a-z_ ]*}}%Exchange, i64{{[a-z_ ]*}}%Comparand)
+// CHECK-X64: call i64 asm sideeffect ".byte 0xf3 ; lock ; cmpxchg $2, $1", "={ax},=*m,r,0,*m,~{memory},~{dirflag},~{fpsr},~{flags}"(i64* %Destination, i64 %Exchange, i64 %Comparand, i64* %Destination)
+ return _InterlockedCompareExchange64_HLERelease(Destination, Exchange, Comparand);
+}
+#endif
+#if !defined(__aarch64__)
void test__fastfail() {
__fastfail(42);
}
@@ -476,4 +601,4 @@ void test__fastfail() {
// Attributes come last.
// CHECK: attributes #[[NORETURN]] = { noreturn{{.*}} }
-
+#endif
diff --git a/test/CodeGen/ms-setjmp.c b/test/CodeGen/ms-setjmp.c
index 675c8dda27de..d92f4d00ff5c 100644
--- a/test/CodeGen/ms-setjmp.c
+++ b/test/CodeGen/ms-setjmp.c
@@ -1,7 +1,9 @@
// RUN: %clang_cc1 -fms-extensions -DDECLARE_SETJMP -triple i686-windows-msvc -emit-llvm %s -o - | FileCheck --check-prefix=I386 %s
// RUN: %clang_cc1 -fms-extensions -DDECLARE_SETJMP -triple x86_64-windows-msvc -emit-llvm %s -o - | FileCheck --check-prefix=X64 %s
+// RUN: %clang_cc1 -fms-extensions -DDECLARE_SETJMP -triple aarch64-windows-msvc -emit-llvm %s -o - | FileCheck --check-prefix=AARCH64 %s
// RUN: %clang_cc1 -fms-extensions -triple i686-windows-msvc -emit-llvm %s -o - | FileCheck --check-prefix=I386 %s
// RUN: %clang_cc1 -fms-extensions -triple x86_64-windows-msvc -emit-llvm %s -o - | FileCheck --check-prefix=X64 %s
+// RUN: %clang_cc1 -fms-extensions -triple aarch64-windows-msvc -emit-llvm %s -o - | FileCheck --check-prefix=AARCH64 %s
typedef char jmp_buf[1];
#ifdef DECLARE_SETJMP
@@ -13,20 +15,30 @@ jmp_buf jb;
int test_setjmp() {
return _setjmp(jb);
- // I386-LABEL: define i32 @test_setjmp
+ // I386-LABEL: define dso_local i32 @test_setjmp
// I386: %[[call:.*]] = call i32 (i8*, i32, ...) @_setjmp3(i8* getelementptr inbounds ([1 x i8], [1 x i8]* @jb, i32 0, i32 0), i32 0)
// I386-NEXT: ret i32 %[[call]]
- // X64-LABEL: define i32 @test_setjmp
+ // X64-LABEL: define dso_local i32 @test_setjmp
// X64: %[[addr:.*]] = call i8* @llvm.frameaddress(i32 0)
// X64: %[[call:.*]] = call i32 @_setjmp(i8* getelementptr inbounds ([1 x i8], [1 x i8]* @jb, i32 0, i32 0), i8* %[[addr]])
// X64-NEXT: ret i32 %[[call]]
+
+ // AARCH64-LABEL: define dso_local i32 @test_setjmp
+ // AARCH64: %[[addr:.*]] = call i8* @llvm.frameaddress(i32 0)
+ // AARCH64: %[[call:.*]] = call i32 @_setjmpex(i8* getelementptr inbounds ([1 x i8], [1 x i8]* @jb, i32 0, i32 0), i8* %[[addr]])
+ // AARCH64-NEXT: ret i32 %[[call]]
}
int test_setjmpex() {
return _setjmpex(jb);
- // X64-LABEL: define i32 @test_setjmpex
+ // X64-LABEL: define dso_local i32 @test_setjmpex
// X64: %[[addr:.*]] = call i8* @llvm.frameaddress(i32 0)
// X64: %[[call:.*]] = call i32 @_setjmpex(i8* getelementptr inbounds ([1 x i8], [1 x i8]* @jb, i32 0, i32 0), i8* %[[addr]])
// X64-NEXT: ret i32 %[[call]]
+
+ // AARCH64-LABEL: define dso_local i32 @test_setjmpex
+ // AARCH64: %[[addr:.*]] = call i8* @llvm.frameaddress(i32 0)
+ // AARCH64: %[[call:.*]] = call i32 @_setjmpex(i8* getelementptr inbounds ([1 x i8], [1 x i8]* @jb, i32 0, i32 0), i8* %[[addr]])
+ // AARCH64-NEXT: ret i32 %[[call]]
}
diff --git a/test/CodeGen/ms-volatile-aarch64.c b/test/CodeGen/ms-volatile-aarch64.c
new file mode 100644
index 000000000000..2a139f5139fa
--- /dev/null
+++ b/test/CodeGen/ms-volatile-aarch64.c
@@ -0,0 +1,13 @@
+// REQUIRES: aarch64-registered-target
+// RUN: %clang_cc1 -triple aarch64-win32 -emit-llvm -fms-extensions -fms-volatile -o - < %s | FileCheck %s
+
+void test1(int volatile *p, int v) {
+ __iso_volatile_store32(p, v);
+ // CHECK-LABEL: @test1
+ // CHECK: store volatile {{.*}}, {{.*}}
+}
+int test2(const int volatile *p) {
+ return __iso_volatile_load32(p);
+ // CHECK-LABEL: @test2
+ // CHECK: load volatile {{.*}}
+}
diff --git a/test/CodeGen/ms-x86-intrinsics.c b/test/CodeGen/ms-x86-intrinsics.c
index 51520d1f658b..450a134131be 100644
--- a/test/CodeGen/ms-x86-intrinsics.c
+++ b/test/CodeGen/ms-x86-intrinsics.c
@@ -9,7 +9,7 @@
char test__readfsbyte(unsigned long Offset) {
return __readfsbyte(Offset);
}
-// CHECK-I386-LABEL: define signext i8 @test__readfsbyte(i32 %Offset)
+// CHECK-I386-LABEL: define dso_local signext i8 @test__readfsbyte(i32 %Offset)
// CHECK-I386: [[PTR:%[0-9]+]] = inttoptr i32 %Offset to i8 addrspace(257)*
// CHECK-I386: [[VALUE:%[0-9]+]] = load volatile i8, i8 addrspace(257)* [[PTR]], align 1
// CHECK-I386: ret i8 [[VALUE:%[0-9]+]]
@@ -17,7 +17,7 @@ char test__readfsbyte(unsigned long Offset) {
short test__readfsword(unsigned long Offset) {
return __readfsword(Offset);
}
-// CHECK-I386-LABEL: define signext i16 @test__readfsword(i32 %Offset)
+// CHECK-I386-LABEL: define dso_local signext i16 @test__readfsword(i32 %Offset)
// CHECK-I386: [[PTR:%[0-9]+]] = inttoptr i32 %Offset to i16 addrspace(257)*
// CHECK-I386: [[VALUE:%[0-9]+]] = load volatile i16, i16 addrspace(257)* [[PTR]], align 2
// CHECK-I386: ret i16 [[VALUE:%[0-9]+]]
@@ -25,7 +25,7 @@ short test__readfsword(unsigned long Offset) {
long test__readfsdword(unsigned long Offset) {
return __readfsdword(Offset);
}
-// CHECK-I386-LABEL: define i32 @test__readfsdword(i32 %Offset)
+// CHECK-I386-LABEL: define dso_local i32 @test__readfsdword(i32 %Offset)
// CHECK-I386: [[PTR:%[0-9]+]] = inttoptr i32 %Offset to i32 addrspace(257)*
// CHECK-I386: [[VALUE:%[0-9]+]] = load volatile i32, i32 addrspace(257)* [[PTR]], align 4
// CHECK-I386: ret i32 [[VALUE:%[0-9]+]]
@@ -33,7 +33,7 @@ long test__readfsdword(unsigned long Offset) {
long long test__readfsqword(unsigned long Offset) {
return __readfsqword(Offset);
}
-// CHECK-I386-LABEL: define i64 @test__readfsqword(i32 %Offset)
+// CHECK-I386-LABEL: define dso_local i64 @test__readfsqword(i32 %Offset)
// CHECK-I386: [[PTR:%[0-9]+]] = inttoptr i32 %Offset to i64 addrspace(257)*
// CHECK-I386: [[VALUE:%[0-9]+]] = load volatile i64, i64 addrspace(257)* [[PTR]], align 8
// CHECK-I386: ret i64 [[VALUE:%[0-9]+]]
@@ -42,7 +42,7 @@ long long test__readfsqword(unsigned long Offset) {
__int64 test__emul(int a, int b) {
return __emul(a, b);
}
-// CHECK-LABEL: define i64 @test__emul(i32 %a, i32 %b)
+// CHECK-LABEL: define dso_local i64 @test__emul(i32 %a, i32 %b)
// CHECK: [[X:%[0-9]+]] = sext i32 %a to i64
// CHECK: [[Y:%[0-9]+]] = sext i32 %b to i64
// CHECK: [[RES:%[0-9]+]] = mul nsw i64 [[Y]], [[X]]
@@ -51,7 +51,7 @@ __int64 test__emul(int a, int b) {
unsigned __int64 test__emulu(unsigned int a, unsigned int b) {
return __emulu(a, b);
}
-// CHECK-LABEL: define i64 @test__emulu(i32 %a, i32 %b)
+// CHECK-LABEL: define dso_local i64 @test__emulu(i32 %a, i32 %b)
// CHECK: [[X:%[0-9]+]] = zext i32 %a to i64
// CHECK: [[Y:%[0-9]+]] = zext i32 %b to i64
// CHECK: [[RES:%[0-9]+]] = mul nuw i64 [[Y]], [[X]]
@@ -62,7 +62,7 @@ unsigned __int64 test__emulu(unsigned int a, unsigned int b) {
char test__readgsbyte(unsigned long Offset) {
return __readgsbyte(Offset);
}
-// CHECK-X64-LABEL: define i8 @test__readgsbyte(i32 %Offset)
+// CHECK-X64-LABEL: define dso_local i8 @test__readgsbyte(i32 %Offset)
// CHECK-X64: [[ZEXT:%[0-9]+]] = zext i32 %Offset to i64
// CHECK-X64: [[PTR:%[0-9]+]] = inttoptr i64 [[ZEXT]] to i8 addrspace(256)*
// CHECK-X64: [[VALUE:%[0-9]+]] = load volatile i8, i8 addrspace(256)* [[PTR]], align 1
@@ -71,7 +71,7 @@ char test__readgsbyte(unsigned long Offset) {
short test__readgsword(unsigned long Offset) {
return __readgsword(Offset);
}
-// CHECK-X64-LABEL: define i16 @test__readgsword(i32 %Offset)
+// CHECK-X64-LABEL: define dso_local i16 @test__readgsword(i32 %Offset)
// CHECK-X64: [[ZEXT:%[0-9]+]] = zext i32 %Offset to i64
// CHECK-X64: [[PTR:%[0-9]+]] = inttoptr i64 [[ZEXT]] to i16 addrspace(256)*
// CHECK-X64: [[VALUE:%[0-9]+]] = load volatile i16, i16 addrspace(256)* [[PTR]], align 2
@@ -80,7 +80,7 @@ short test__readgsword(unsigned long Offset) {
long test__readgsdword(unsigned long Offset) {
return __readgsdword(Offset);
}
-// CHECK-X64-LABEL: define i32 @test__readgsdword(i32 %Offset)
+// CHECK-X64-LABEL: define dso_local i32 @test__readgsdword(i32 %Offset)
// CHECK-X64: [[ZEXT:%[0-9]+]] = zext i32 %Offset to i64
// CHECK-X64: [[PTR:%[0-9]+]] = inttoptr i64 [[ZEXT]] to i32 addrspace(256)*
// CHECK-X64: [[VALUE:%[0-9]+]] = load volatile i32, i32 addrspace(256)* [[PTR]], align 4
@@ -89,7 +89,7 @@ long test__readgsdword(unsigned long Offset) {
long long test__readgsqword(unsigned long Offset) {
return __readgsqword(Offset);
}
-// CHECK-X64-LABEL: define i64 @test__readgsqword(i32 %Offset)
+// CHECK-X64-LABEL: define dso_local i64 @test__readgsqword(i32 %Offset)
// CHECK-X64: [[ZEXT:%[0-9]+]] = zext i32 %Offset to i64
// CHECK-X64: [[PTR:%[0-9]+]] = inttoptr i64 [[ZEXT]] to i64 addrspace(256)*
// CHECK-X64: [[VALUE:%[0-9]+]] = load volatile i64, i64 addrspace(256)* [[PTR]], align 8
@@ -98,13 +98,13 @@ long long test__readgsqword(unsigned long Offset) {
__int64 test__mulh(__int64 a, __int64 b) {
return __mulh(a, b);
}
-// CHECK-X64-LABEL: define i64 @test__mulh(i64 %a, i64 %b)
+// CHECK-X64-LABEL: define dso_local i64 @test__mulh(i64 %a, i64 %b)
// CHECK-X64: = mul nsw i128 %
unsigned __int64 test__umulh(unsigned __int64 a, unsigned __int64 b) {
return __umulh(a, b);
}
-// CHECK-X64-LABEL: define i64 @test__umulh(i64 %a, i64 %b)
+// CHECK-X64-LABEL: define dso_local i64 @test__umulh(i64 %a, i64 %b)
// CHECK-X64: = mul nuw i128 %
__int64 test_mul128(__int64 Multiplier,
@@ -112,7 +112,7 @@ __int64 test_mul128(__int64 Multiplier,
__int64 *HighProduct) {
return _mul128(Multiplier, Multiplicand, HighProduct);
}
-// CHECK-X64-LABEL: define i64 @test_mul128(i64 %Multiplier, i64 %Multiplicand, i64*{{[a-z_ ]*}}%HighProduct)
+// CHECK-X64-LABEL: define dso_local i64 @test_mul128(i64 %Multiplier, i64 %Multiplicand, i64*{{[a-z_ ]*}}%HighProduct)
// CHECK-X64: = sext i64 %Multiplier to i128
// CHECK-X64: = sext i64 %Multiplicand to i128
// CHECK-X64: = mul nsw i128 %
@@ -124,7 +124,7 @@ unsigned __int64 test_umul128(unsigned __int64 Multiplier,
unsigned __int64 *HighProduct) {
return _umul128(Multiplier, Multiplicand, HighProduct);
}
-// CHECK-X64-LABEL: define i64 @test_umul128(i64 %Multiplier, i64 %Multiplicand, i64*{{[a-z_ ]*}}%HighProduct)
+// CHECK-X64-LABEL: define dso_local i64 @test_umul128(i64 %Multiplier, i64 %Multiplicand, i64*{{[a-z_ ]*}}%HighProduct)
// CHECK-X64: = zext i64 %Multiplier to i128
// CHECK-X64: = zext i64 %Multiplicand to i128
// CHECK-X64: = mul nuw i128 %
diff --git a/test/CodeGen/ms_abi.c b/test/CodeGen/ms_abi.c
index 407087e40916..75e1caf922df 100644
--- a/test/CodeGen/ms_abi.c
+++ b/test/CodeGen/ms_abi.c
@@ -13,7 +13,7 @@ void __attribute__((ms_abi)) f1(void);
void __attribute__((sysv_abi)) f2(void);
void f3(void) {
// FREEBSD-LABEL: define void @f3()
- // WIN64-LABEL: define void @f3()
+ // WIN64-LABEL: define dso_local void @f3()
f1();
// FREEBSD: call win64cc void @f1()
// WIN64: call void @f1()
@@ -23,13 +23,13 @@ void f3(void) {
}
// FREEBSD: declare win64cc void @f1()
// FREEBSD: declare void @f2()
-// WIN64: declare void @f1()
-// WIN64: declare x86_64_sysvcc void @f2()
+// WIN64: declare dso_local void @f1()
+// WIN64: declare dso_local x86_64_sysvcc void @f2()
// Win64 ABI varargs
void __attribute__((ms_abi)) f4(int a, ...) {
// FREEBSD-LABEL: define win64cc void @f4
- // WIN64-LABEL: define void @f4
+ // WIN64-LABEL: define dso_local void @f4
__builtin_ms_va_list ap;
__builtin_ms_va_start(ap, a);
// FREEBSD: %[[AP:.*]] = alloca i8*
@@ -79,7 +79,7 @@ void __attribute__((ms_abi)) f4(int a, ...) {
// Let's verify that normal va_lists work right on Win64, too.
void f5(int a, ...) {
- // WIN64-LABEL: define void @f5
+ // WIN64-LABEL: define dso_local void @f5
__builtin_va_list ap;
__builtin_va_start(ap, a);
// WIN64: %[[AP:.*]] = alloca i8*
@@ -110,7 +110,7 @@ void f5(int a, ...) {
void __attribute__((sysv_abi)) f6(__builtin_ms_va_list ap) {
// FREEBSD-LABEL: define void @f6
// FREEBSD: store i8* %ap, i8** %[[AP:.*]]
- // WIN64-LABEL: define x86_64_sysvcc void @f6
+ // WIN64-LABEL: define dso_local x86_64_sysvcc void @f6
// WIN64: store i8* %ap, i8** %[[AP:.*]]
int b = __builtin_va_arg(ap, int);
// FREEBSD: %[[AP_CUR:.*]] = load i8*, i8** %[[AP]]
@@ -146,3 +146,16 @@ void __attribute__((sysv_abi)) f6(__builtin_ms_va_list ap) {
// WIN64: %[[AP_VAL:.*]] = load i8*, i8** %[[AP]]
// WIN64-NEXT: store i8* %[[AP_VAL]], i8** %[[AP2:.*]]
}
+
+// This test checks if structs are passed according to Win64 calling convention
+// when it's enforced by __attribute((ms_abi)).
+struct i128 {
+ unsigned long long a;
+ unsigned long long b;
+};
+
+__attribute__((ms_abi)) struct i128 f7(struct i128 a) {
+ // WIN64: define dso_local void @f7(%struct.i128* noalias sret %agg.result, %struct.i128* %a)
+ // FREEBSD: define win64cc void @f7(%struct.i128* noalias sret %agg.result, %struct.i128* %a)
+ return a;
+}
diff --git a/test/CodeGen/ms_abi_aarch64.c b/test/CodeGen/ms_abi_aarch64.c
index 4aa93f00859a..5b6cd6a208b6 100644
--- a/test/CodeGen/ms_abi_aarch64.c
+++ b/test/CodeGen/ms_abi_aarch64.c
@@ -5,7 +5,7 @@ void __attribute__((ms_abi)) f1(void);
void f2(void);
void f3(void) {
// LINUX-LABEL: define void @f3()
- // WIN64-LABEL: define void @f3()
+ // WIN64-LABEL: define dso_local void @f3()
f1();
// LINUX: call win64cc void @f1()
// WIN64: call void @f1()
@@ -15,13 +15,13 @@ void f3(void) {
}
// LINUX: declare win64cc void @f1()
// LINUX: declare void @f2()
-// WIN64: declare void @f1()
-// WIN64: declare void @f2()
+// WIN64: declare dso_local void @f1()
+// WIN64: declare dso_local void @f2()
// Win64 ABI varargs
void __attribute__((ms_abi)) f4(int a, ...) {
// LINUX-LABEL: define win64cc void @f4
- // WIN64-LABEL: define void @f4
+ // WIN64-LABEL: define dso_local void @f4
__builtin_ms_va_list ap;
__builtin_ms_va_start(ap, a);
// LINUX: %[[AP:.*]] = alloca i8*
@@ -50,7 +50,7 @@ void __attribute__((ms_abi)) f4(int a, ...) {
// Let's verify that normal va_lists work right on Win64, too.
void f5(int a, ...) {
- // WIN64-LABEL: define void @f5
+ // WIN64-LABEL: define dso_local void @f5
__builtin_va_list ap;
__builtin_va_start(ap, a);
// WIN64: %[[AP:.*]] = alloca i8*
diff --git a/test/CodeGen/ms_struct-long-double.c b/test/CodeGen/ms_struct-long-double.c
new file mode 100644
index 000000000000..9b3ea7947a03
--- /dev/null
+++ b/test/CodeGen/ms_struct-long-double.c
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -emit-llvm-only -triple i686-windows-gnu -fdump-record-layouts %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm-only -triple i686-linux -fdump-record-layouts -Wno-incompatible-ms-struct %s | FileCheck %s
+// RUN: not %clang_cc1 -emit-llvm-only -triple i686-linux -fdump-record-layouts %s 2>&1 | FileCheck %s -check-prefix=ERROR
+
+struct ldb_struct {
+ char c;
+ long double ldb;
+} __attribute__((__ms_struct__));
+
+struct ldb_struct a;
+
+// CHECK: 0 | struct ldb_struct
+// CHECK-NEXT: 0 | char c
+// CHECK-NEXT: 4 | long double ldb
+// CHECK-NEXT: | [sizeof=16, align=4]
+
+// ERROR: error: ms_struct may not produce Microsoft-compatible layouts with fundamental data types with sizes that aren't a power of two
diff --git a/test/CodeGen/ms_this.cpp b/test/CodeGen/ms_this.cpp
index 8647a5bc8b8b..f0da36f447ec 100644
--- a/test/CodeGen/ms_this.cpp
+++ b/test/CodeGen/ms_this.cpp
@@ -13,7 +13,7 @@ public:
void runc();
};
-// CHECK: define void @"\01?runc@t2@@
+// CHECK: define dso_local void @"?runc@t2@@
void t2::runc() {
double num = 0;
__asm {
@@ -26,7 +26,7 @@ void t2::runc() {
};
}
-// CHECK: define void @"\01?runc@t1@@
+// CHECK: define dso_local void @"?runc@t1@@
void t1::runc() {
double num = 0;
__asm {
@@ -41,7 +41,7 @@ void t1::runc() {
struct s {
int a;
- // CHECK: define linkonce_odr void @"\01?func@s@@
+ // CHECK: define linkonce_odr dso_local void @"?func@s@@
void func() {
__asm mov rax, [this]
// CHECK: [[THIS_ADDR_S:%.+]] = alloca %struct.s*
diff --git a/test/CodeGen/no-bitfield-type-align.c b/test/CodeGen/no-bitfield-type-align.c
new file mode 100644
index 000000000000..830cd585c6ba
--- /dev/null
+++ b/test/CodeGen/no-bitfield-type-align.c
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -fno-bitfield-type-align -emit-llvm -o - %s | FileCheck %s
+
+// CHECK: %[[STRUCT_S:.*]] = type { i32 }
+
+struct S {
+ unsigned short: 0;
+ unsigned short f1:15;
+ unsigned short: 0;
+ unsigned short f2:15;
+};
+
+// CHECK: define void @test_zero_width_bitfield(%[[STRUCT_S]]* %[[A:.*]])
+// CHECK: %[[BF_LOAD:.*]] = load i32, i32* %[[V1:.*]], align 1
+// CHECK: %[[BF_CLEAR:.*]] = and i32 %[[BF_LOAD]], 32767
+// CHECK: %[[BF_CAST:.*]] = trunc i32 %[[BF_CLEAR]] to i16
+// CHECK: %[[CONV:.*]] = zext i16 %[[BF_CAST]] to i32
+// CHECK: %[[ADD:.*]] = add nsw i32 %[[CONV]], 1
+// CHECK: %[[CONV1:.*]] = trunc i32 %[[ADD]] to i16
+// CHECK: %[[V2:.*]] = zext i16 %[[CONV1]] to i32
+// CHECK: %[[BF_LOAD2:.*]] = load i32, i32* %[[V1]], align 1
+// CHECK: %[[BF_VALUE:.*]] = and i32 %[[V2]], 32767
+// CHECK: %[[BF_CLEAR3:.*]] = and i32 %[[BF_LOAD2]], -32768
+// CHECK: %[[BF_SET:.*]] = or i32 %[[BF_CLEAR3]], %[[BF_VALUE]]
+// CHECK: store i32 %[[BF_SET]], i32* %[[V1]], align 1
+
+// CHECK: %[[BF_LOAD4:.*]] = load i32, i32* %[[V4:.*]], align 1
+// CHECK: %[[BF_LSHR:.*]] = lshr i32 %[[BF_LOAD4]], 15
+// CHECK: %[[BF_CLEAR5:.*]] = and i32 %[[BF_LSHR]], 32767
+// CHECK: %[[BF_CAST6:.*]] = trunc i32 %[[BF_CLEAR5]] to i16
+// CHECK: %[[CONV7:.*]] = zext i16 %[[BF_CAST6]] to i32
+// CHECK: %[[ADD8:.*]] = add nsw i32 %[[CONV7]], 2
+// CHECK: %[[CONV9:.*]] = trunc i32 %[[ADD8]] to i16
+// CHECK: %[[V5:.*]] = zext i16 %[[CONV9]] to i32
+// CHECK: %[[BF_LOAD10:.*]] = load i32, i32* %[[V4]], align 1
+// CHECK: %[[BF_VALUE11:.*]] = and i32 %[[V5]], 32767
+// CHECK: %[[BF_SHL:.*]] = shl i32 %[[BF_VALUE11]], 15
+// CHECK: %[[BF_CLEAR12:.*]] = and i32 %[[BF_LOAD10]], -1073709057
+// CHECK: %[[BF_SET13:.*]] = or i32 %[[BF_CLEAR12]], %[[BF_SHL]]
+// CHECK: store i32 %[[BF_SET13]], i32* %[[V4]], align 1
+
+void test_zero_width_bitfield(struct S *a) {
+ a->f1 += 1;
+ a->f2 += 2;
+}
diff --git a/test/CodeGen/no-common.c b/test/CodeGen/no-common.c
index 8d2c4d7d74c8..f3a6a334e6f5 100644
--- a/test/CodeGen/no-common.c
+++ b/test/CodeGen/no-common.c
@@ -1,15 +1,15 @@
// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-DEFAULT
// RUN: %clang_cc1 %s -fno-common -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-NOCOMMON
-// CHECK-DEFAULT: @x = common global
-// CHECK-NOCOMMON: @x = global
+// CHECK-DEFAULT: @x = common {{(dso_local )?}}global
+// CHECK-NOCOMMON: @x = {{(dso_local )?}}global
int x;
-// CHECK-DEFAULT: @ABC = global
-// CHECK-NOCOMMON: @ABC = global
+// CHECK-DEFAULT: @ABC = {{(dso_local )?}}global
+// CHECK-NOCOMMON: @ABC = {{(dso_local )?}}global
typedef void* (*fn_t)(long a, long b, char *f, int c);
fn_t ABC __attribute__ ((nocommon));
-// CHECK-DEFAULT: @y = common global
-// CHECK-NOCOMMON: @y = common global
+// CHECK-DEFAULT: @y = common {{(dso_local )?}}global
+// CHECK-NOCOMMON: @y = common {{(dso_local )?}}global
int y __attribute__((common));
diff --git a/test/CodeGen/no-ident-version.c b/test/CodeGen/no-ident-version.c
new file mode 100644
index 000000000000..3765a605a988
--- /dev/null
+++ b/test/CodeGen/no-ident-version.c
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -o - %s \
+// RUN: | FileCheck --check-prefix=CHECK-NONE %s
+// RUN: %clang_cc1 -Qn -emit-llvm -debug-info-kind=limited -o - %s \
+// RUN: | FileCheck --check-prefix=CHECK-QN %s
+// RUN: %clang_cc1 -fno-ident -emit-llvm -debug-info-kind=limited -o - %s \
+// RUN: | FileCheck --check-prefix=CHECK-QN %s
+// RUN: %clang_cc1 -Qy -emit-llvm -debug-info-kind=limited -o - %s \
+// RUN: | FileCheck --check-prefix=CHECK-QY %s
+// RUN: %clang_cc1 -fident -emit-llvm -debug-info-kind=limited -o - %s \
+// RUN: | FileCheck --check-prefix=CHECK-QY %s
+
+// CHECK-NONE: @main
+// CHECK-NONE: llvm.ident
+// CHECK-NONE: producer:
+
+// CHECK-QN: @main
+// CHECK-QN-NOT: llvm.ident
+// CHECK-QN-NOT: producer:
+
+// CHECK-QY: @main
+// CHECK-QY: llvm.ident
+// CHECK-QY: producer:
+int main(void) {}
diff --git a/test/CodeGen/no-junk-ftrunc.c b/test/CodeGen/no-junk-ftrunc.c
new file mode 100644
index 000000000000..a645d9688669
--- /dev/null
+++ b/test/CodeGen/no-junk-ftrunc.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -S -fno-strict-float-cast-overflow %s -emit-llvm -o - | FileCheck %s --check-prefix=NOSTRICT
+// NOSTRICT-LABEL: main
+// NOSTRICT: attributes #0 = {{.*}}"strict-float-cast-overflow"="false"{{.*}}
+
+// The workaround attribute is not applied by default.
+
+// RUN: %clang_cc1 -S %s -fstrict-float-cast-overflow -emit-llvm -o - | FileCheck %s --check-prefix=STRICT
+// STRICT-LABEL: main
+// STRICT-NOT: strict-float-cast-overflow
+
+// RUN: %clang_cc1 -S %s -emit-llvm -o - | FileCheck %s --check-prefix=DEFAULT
+// DEFAULT-LABEL: main
+// DEFAULT-NOT: strict-float-cast-overflow
+
+int main() {
+ return 0;
+}
+
diff --git a/test/CodeGen/no-opt-volatile-memcpy.c b/test/CodeGen/no-opt-volatile-memcpy.c
index bf98df39af16..2781475b6302 100644
--- a/test/CodeGen/no-opt-volatile-memcpy.c
+++ b/test/CodeGen/no-opt-volatile-memcpy.c
@@ -18,10 +18,10 @@ void foo (void) {
// CHECK: %[[LS:.*]] = alloca %struct.s, align 4
// CHECK-NEXT: %[[ZERO:.*]] = bitcast %struct.s* %[[LS]] to i8*
// CHECK-NEXT: %[[ONE:.*]] = bitcast %struct.s* %[[LS]] to i8*
-// CHECK-NEXT: call void @llvm.memcpy.{{.*}}(i8* %[[ZERO]], i8* %[[ONE]], i64 132, i32 4, i1 true)
-// CHECK-NEXT: call void @llvm.memcpy.{{.*}}(i8* getelementptr inbounds (%struct.s, %struct.s* @gs, i32 0, i32 0, i32 0), i8* getelementptr inbounds (%struct.s, %struct.s* @gs, i32 0, i32 0, i32 0), i64 132, i32 4, i1 true)
+// CHECK-NEXT: call void @llvm.memcpy.{{.*}}(i8* align 4 %[[ZERO]], i8* align 4 %[[ONE]], i64 132, i1 true)
+// CHECK-NEXT: call void @llvm.memcpy.{{.*}}(i8* align 4 getelementptr inbounds (%struct.s, %struct.s* @gs, i32 0, i32 0, i32 0), i8* align 4 getelementptr inbounds (%struct.s, %struct.s* @gs, i32 0, i32 0, i32 0), i64 132, i1 true)
// CHECK-NEXT: %[[TWO:.*]] = bitcast %struct.s* %[[LS]] to i8*
-// CHECK-NEXT: call void @llvm.memcpy.{{.*}}(i8* %[[TWO]], i8* getelementptr inbounds (%struct.s, %struct.s* @gs, i32 0, i32 0, i32 0), i64 132, i32 4, i1 true)
+// CHECK-NEXT: call void @llvm.memcpy.{{.*}}(i8* align 4 %[[TWO]], i8* align 4 getelementptr inbounds (%struct.s, %struct.s* @gs, i32 0, i32 0, i32 0), i64 132, i1 true)
struct s1 {
@@ -35,6 +35,6 @@ void fee (void) {
s.y = gs;
}
// CHECK-LABEL: define void @fee()
-// CHECK: call void @llvm.memcpy.{{.*}}(i8* getelementptr inbounds (%struct.s1, %struct.s1* @s, i32 0, i32 0, i32 0, i32 0), i8* getelementptr inbounds (%struct.s1, %struct.s1* @s, i32 0, i32 0, i32 0, i32 0), i64 132, i32 4, i1 true)
-// CHECK-NEXT: call void @llvm.memcpy.{{.*}}(i8* getelementptr inbounds (%struct.s1, %struct.s1* @s, i32 0, i32 0, i32 0, i32 0), i8* getelementptr inbounds (%struct.s, %struct.s* @gs, i32 0, i32 0, i32 0), i64 132, i32 4, i1 true)
+// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 4 getelementptr inbounds (%struct.s1, %struct.s1* @s, i32 0, i32 0, i32 0, i32 0), i8* align 4 getelementptr inbounds (%struct.s1, %struct.s1* @s, i32 0, i32 0, i32 0, i32 0), i64 132, i1 true)
+// CHECK-NEXT: call void @llvm.memcpy.{{.*}}(i8* align 4 getelementptr inbounds (%struct.s1, %struct.s1* @s, i32 0, i32 0, i32 0, i32 0), i8* align 4 getelementptr inbounds (%struct.s, %struct.s* @gs, i32 0, i32 0, i32 0), i64 132, i1 true)
diff --git a/test/CodeGen/no-prototype.c b/test/CodeGen/no-prototype.c
new file mode 100644
index 000000000000..6030357b70f7
--- /dev/null
+++ b/test/CodeGen/no-prototype.c
@@ -0,0 +1,20 @@
+// REQUIRES: webassembly-registered-target
+// RUN: %clang_cc1 -triple wasm32 -emit-llvm %s -o - | FileCheck %s
+
+int foo();
+
+int bar(int a) {
+ return foo();
+}
+
+int baz() {
+ return foo();
+}
+
+// CHECK: define i32 @bar(i32 %a) [[BAR_ATTR:#[0-9]+]] {
+// CHECK: declare i32 @foo(...) [[FOO_ATTR:#[0-9]+]]
+// CHECK: define i32 @baz() [[BAZ_ATTR:#[0-9]+]] {
+
+// CHECK: attributes [[FOO_ATTR]] = { {{.*}}"no-prototype"{{.*}} }
+// CHECK-NOT: attributes [[BAR_ATTR]] = { {{.*}}"no-prototype"{{.*}} }
+// CHECK-NOT: attributes [[BAZ_ATTR]] = { {{.*}}"no-prototype"{{.*}} }
diff --git a/test/CodeGen/nonnull.c b/test/CodeGen/nonnull.c
index 7c33e6329fdd..30162441cf4c 100644
--- a/test/CodeGen/nonnull.c
+++ b/test/CodeGen/nonnull.c
@@ -1,32 +1,39 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm < %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm < %s | FileCheck -check-prefix=NULL-INVALID %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -fno-delete-null-pointer-checks < %s | FileCheck -check-prefix=NULL-VALID %s
-// CHECK: define void @foo(i32* nonnull %x)
+// NULL-INVALID: define void @foo(i32* nonnull %x)
+// NULL-VALID: define void @foo(i32* %x)
void foo(int * __attribute__((nonnull)) x) {
*x = 0;
}
-// CHECK: define void @bar(i32* nonnull %x)
+// NULL-INVALID: define void @bar(i32* nonnull %x)
+// NULL-VALID: define void @bar(i32* %x)
void bar(int * x) __attribute__((nonnull(1))) {
*x = 0;
}
-// CHECK: define void @bar2(i32* %x, i32* nonnull %y)
+// NULL-INVALID: define void @bar2(i32* %x, i32* nonnull %y)
+// NULL-VALID: define void @bar2(i32* %x, i32* %y)
void bar2(int * x, int * y) __attribute__((nonnull(2))) {
*x = 0;
}
static int a;
-// CHECK: define nonnull i32* @bar3()
+// NULL-INVALID: define nonnull i32* @bar3()
+// NULL-VALID: define i32* @bar3()
int * bar3() __attribute__((returns_nonnull)) {
return &a;
}
-// CHECK: define i32 @bar4(i32 %n, i32* nonnull %p)
+// NULL-INVALID: define i32 @bar4(i32 %n, i32* nonnull %p)
+// NULL-VALID: define i32 @bar4(i32 %n, i32* %p)
int bar4(int n, int *p) __attribute__((nonnull)) {
return n + *p;
}
-// CHECK: define i32 @bar5(i32 %n, i32* nonnull %p)
+// NULL-INVALID: define i32 @bar5(i32 %n, i32* nonnull %p)
+// NULL-VALID: define i32 @bar5(i32 %n, i32* %p)
int bar5(int n, int *p) __attribute__((nonnull(1, 2))) {
return n + *p;
}
@@ -37,15 +44,18 @@ typedef union {
double d;
} TransparentUnion __attribute__((transparent_union));
-// CHECK: define i32 @bar6(i64 %
+// NULL-INVALID: define i32 @bar6(i64 %
+// NULL-VALID: define i32 @bar6(i64 %
int bar6(TransparentUnion tu) __attribute__((nonnull(1))) {
return *tu.p;
}
-// CHECK: define void @bar7(i32* nonnull %a, i32* nonnull %b)
+// NULL-INVALID: define void @bar7(i32* nonnull %a, i32* nonnull %b)
+// NULL-VALID: define void @bar7(i32* %a, i32* %b)
void bar7(int *a, int *b) __attribute__((nonnull(1)))
__attribute__((nonnull(2))) {}
-// CHECK: define void @bar8(i32* nonnull %a, i32* nonnull %b)
+// NULL-INVALID: define void @bar8(i32* nonnull %a, i32* nonnull %b)
+// NULL-VALID: define void @bar8(i32* %a, i32* %b)
void bar8(int *a, int *b) __attribute__((nonnull))
__attribute__((nonnull(1))) {}
diff --git a/test/CodeGen/noplt.c b/test/CodeGen/noplt.c
index f467199efab2..20e2e07b0fd4 100644
--- a/test/CodeGen/noplt.c
+++ b/test/CodeGen/noplt.c
@@ -1,7 +1,8 @@
-// RUN: %clang_cc1 -emit-llvm -fno-plt %s -o - | FileCheck %s -check-prefix=CHECK-NOPLT
+// RUN: %clang_cc1 -emit-llvm -fno-plt %s -o - | FileCheck %s -check-prefix=CHECK-NOPLT -check-prefix=CHECK-NOPLT-METADATA
// CHECK-NOPLT: Function Attrs: nonlazybind
// CHECK-NOPLT-NEXT: declare {{.*}}i32 @foo
+// CHECK-NOPLT-METADATA: !"RtLibUseGOT"
int foo();
int bar() {
diff --git a/test/CodeGen/opt-record-MIR.c b/test/CodeGen/opt-record-MIR.c
index 00b91ffdf3cb..37239281e9e9 100644
--- a/test/CodeGen/opt-record-MIR.c
+++ b/test/CodeGen/opt-record-MIR.c
@@ -21,8 +21,9 @@ void foo(float *p, int i) {
// YAML: --- !Missed
// YAML: Pass: regalloc
// YAML: Name: LoopSpillReload
-// YAML: DebugLoc: { File: {{.*}},
-// YAML: Line: 10, Column: 11 }
+// YAML: DebugLoc: { File: {{[^,]+}},
+// YAML: Line: 10,
+// YAML: Column: 11 }
// YAML: Function: foo
// YAML: Args:
// YAML: - NumSpills: '{{.}}'
diff --git a/test/CodeGen/overloadable.c b/test/CodeGen/overloadable.c
index 1feb12f5b579..f4fd0b36308b 100644
--- a/test/CodeGen/overloadable.c
+++ b/test/CodeGen/overloadable.c
@@ -41,7 +41,7 @@ void addrof_single(int *a) __attribute__((overloadable, enable_if(0, "")));
void addrof_single(char *a) __attribute__((overloadable, enable_if(0, "")));
void addrof_single(char *a) __attribute__((overloadable));
-// CHECK-LABEL: define void @foo
+// CHECK-LABEL: define {{(dso_local )?}}void @foo
void foo() {
// CHECK: store void (i8*)* @_Z11addrof_manyPc
void (*p1)(char *) = &addrof_many;
@@ -64,7 +64,7 @@ void foo() {
void ovl_bar(char *) __attribute__((overloadable));
void ovl_bar(int) __attribute__((overloadable));
-// CHECK-LABEL: define void @bar
+// CHECK-LABEL: define {{(dso_local )?}}void @bar
void bar() {
char charbuf[1];
unsigned char ucharbuf[1];
@@ -79,7 +79,7 @@ void ovl_baz(int *, int) __attribute__((overloadable));
void ovl_baz(unsigned int *, unsigned int) __attribute__((overloadable));
void ovl_baz2(int, int *) __attribute__((overloadable));
void ovl_baz2(unsigned int, unsigned int *) __attribute__((overloadable));
-// CHECK-LABEL: define void @baz
+// CHECK-LABEL: define {{(dso_local )?}}void @baz
void baz() {
unsigned int j;
// Initial rules for incompatible pointer conversions made this overload
diff --git a/test/CodeGen/packed-nest-unpacked.c b/test/CodeGen/packed-nest-unpacked.c
index e2bbd41a9daf..4124a8ade86a 100644
--- a/test/CodeGen/packed-nest-unpacked.c
+++ b/test/CodeGen/packed-nest-unpacked.c
@@ -9,26 +9,26 @@ struct X foo(void);
// <rdar://problem/10463337>
struct X test1() {
// CHECK: @test1
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* bitcast (%struct.X* getelementptr inbounds (%struct.Y, %struct.Y* @g, i32 0, i32 1) to i8*), i64 24, i32 1, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* align 1 bitcast (%struct.X* getelementptr inbounds (%struct.Y, %struct.Y* @g, i32 0, i32 1) to i8*), i64 24, i1 false)
return g.y;
}
struct X test2() {
// CHECK: @test2
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* bitcast (%struct.X* getelementptr inbounds (%struct.Y, %struct.Y* @g, i32 0, i32 1) to i8*), i64 24, i32 1, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* align 1 bitcast (%struct.X* getelementptr inbounds (%struct.Y, %struct.Y* @g, i32 0, i32 1) to i8*), i64 24, i1 false)
struct X a = g.y;
return a;
}
void test3(struct X a) {
// CHECK: @test3
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* bitcast (%struct.X* getelementptr inbounds (%struct.Y, %struct.Y* @g, i32 0, i32 1) to i8*), i8* {{.*}}, i64 24, i32 1, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 bitcast (%struct.X* getelementptr inbounds (%struct.Y, %struct.Y* @g, i32 0, i32 1) to i8*), i8* {{.*}}, i64 24, i1 false)
g.y = a;
}
// <rdar://problem/10530444>
void test4() {
// CHECK: @test4
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* bitcast (%struct.X* getelementptr inbounds (%struct.Y, %struct.Y* @g, i32 0, i32 1) to i8*), i64 24, i32 1, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* align 1 bitcast (%struct.X* getelementptr inbounds (%struct.Y, %struct.Y* @g, i32 0, i32 1) to i8*), i64 24, i1 false)
f(g.y);
}
@@ -42,7 +42,7 @@ int test5() {
// <rdar://problem/11220251>
void test6() {
// CHECK: @test6
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* bitcast (%struct.X* getelementptr inbounds (%struct.Y, %struct.Y* @g, i32 0, i32 1) to i8*), i8* %{{.*}}, i64 24, i32 1, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 bitcast (%struct.X* getelementptr inbounds (%struct.Y, %struct.Y* @g, i32 0, i32 1) to i8*), i8* align 4 %{{.*}}, i64 24, i1 false)
g.y = foo();
}
diff --git a/test/CodeGen/packed-structure.c b/test/CodeGen/packed-structure.c
index 7d1183dc5ca6..91cacb400536 100644
--- a/test/CodeGen/packed-structure.c
+++ b/test/CodeGen/packed-structure.c
@@ -29,7 +29,7 @@ int s0_load_x(struct s0 *a) { return a->x; }
// CHECK-FUNCTIONS: ret i32 [[s0_load_y]]
int s0_load_y(struct s0 *a) { return a->y; }
// CHECK-FUNCTIONS-LABEL: define void @s0_copy
-// CHECK-FUNCTIONS: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 8, i32 4, i1 false)
+// CHECK-FUNCTIONS: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 {{.*}}, i8* align 4 {{.*}}, i64 8, i1 false)
void s0_copy(struct s0 *a, struct s0 *b) { *b = *a; }
//
@@ -55,7 +55,7 @@ int s1_load_x(struct s1 *a) { return a->x; }
// CHECK-FUNCTIONS: ret i32 [[s1_load_y]]
int s1_load_y(struct s1 *a) { return a->y; }
// CHECK-FUNCTIONS-LABEL: define void @s1_copy
-// CHECK-FUNCTIONS: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 8, i32 1, i1 false)
+// CHECK-FUNCTIONS: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 8, i1 false)
void s1_copy(struct s1 *a, struct s1 *b) { *b = *a; }
//
@@ -83,7 +83,7 @@ int s2_load_x(struct s2 *a) { return a->x; }
// CHECK-FUNCTIONS: ret i32 [[s2_load_y]]
int s2_load_y(struct s2 *a) { return a->y; }
// CHECK-FUNCTIONS-LABEL: define void @s2_copy
-// CHECK-FUNCTIONS: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 8, i32 2, i1 false)
+// CHECK-FUNCTIONS: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 2 {{.*}}, i8* align 2 {{.*}}, i64 8, i1 false)
void s2_copy(struct s2 *a, struct s2 *b) { *b = *a; }
struct __attribute__((packed, aligned)) s3 {
diff --git a/test/CodeGen/partial-reinitialization2.c b/test/CodeGen/partial-reinitialization2.c
index c4f6567b36ce..9c3ce99b98dc 100644
--- a/test/CodeGen/partial-reinitialization2.c
+++ b/test/CodeGen/partial-reinitialization2.c
@@ -15,7 +15,7 @@ union ULP3 { struct LP3 l3; };
// CHECK-LABEL: test1
void test1(void)
{
- // CHECK: call void @llvm.memcpy{{.*}}%struct.P1, %struct.P1* @g1{{.*}}i64 6, i32 {{[0-9]}}, i1 false)
+ // CHECK: call void @llvm.memcpy{{.*}}%struct.P1, %struct.P1* @g1{{.*}}i64 6, i1 false)
// CHECK: store i8 120, i8* %
struct LP1 l = { .p1 = g1, .p1.x[2] = 'x' };
@@ -24,7 +24,7 @@ void test1(void)
// CHECK-LABEL: test2
void test2(void)
{
- // CHECK: call void @llvm.memcpy{{.*}}%struct.P1, %struct.P1* @g1{{.*}}i64 6, i32 {{[0-9]}}, i1 false)
+ // CHECK: call void @llvm.memcpy{{.*}}%struct.P1, %struct.P1* @g1{{.*}}i64 6, i1 false)
// CHECK: store i8 114, i8* %
struct LP1 l = { .p1 = g1, .p1.x[1] = 'r' };
@@ -33,7 +33,7 @@ void test2(void)
// CHECK-LABEL: test3
void test3(void)
{
- // CHECK: call void @llvm.memcpy{{.*}}%struct.P2* @g2{{.*}}i64 12, i32 {{[0-9]}}, i1 false)
+ // CHECK: call void @llvm.memcpy{{.*}}%struct.P2* @g2{{.*}}i64 12, i1 false)
// CHECK: store i32 10, i32* %
struct LP2 l = { .p2 = g2, .p2.b = 10 };
@@ -66,7 +66,7 @@ void test4(void)
// CHECK: [[CALL:%[a-z0-9]+]] = call {{.*}}@get123()
// CHECK: store{{.*}}[[CALL]], {{.*}}[[TMP0:%[a-z0-9]+]]
// CHECK: [[TMP1:%[a-z0-9]+]] = bitcast {{.*}}[[TMP0]]
- // CHECK: call void @llvm.memcpy{{.*}}[[TMP1]], i64 12, i32 {{[0-9]}}, i1 false)
+ // CHECK: call void @llvm.memcpy{{.*}}[[TMP1]], i64 12, i1 false)
// CHECK: store i32 100, i32* %
struct LUP2 { union UP2 up; } var = { get123(), .up.p2.a = 100 };
@@ -76,12 +76,12 @@ void test4(void)
void test5(void)
{
// .l3 = g3
- // CHECK: call void @llvm.memcpy{{.*}}%struct.LP3, %struct.LP3* @g3{{.*}}i64 12, i32 {{[0-9]}}, i1 false)
+ // CHECK: call void @llvm.memcpy{{.*}}%struct.LP3, %struct.LP3* @g3{{.*}}i64 12, i1 false)
// .l3.p1 = { [0] = g1 } implicitly sets [1] to zero
- // CHECK: call void @llvm.memcpy{{.*}}%struct.P1, %struct.P1* @g1{{.*}}i64 6, i32 {{[0-9]}}, i1 false)
+ // CHECK: call void @llvm.memcpy{{.*}}%struct.P1, %struct.P1* @g1{{.*}}i64 6, i1 false)
// CHECK: getelementptr{{.*}}%struct.P1, %struct.P1*{{.*}}i64 1
- // CHECK: call void @llvm.memset{{.*}}i8 0, i64 6, i32 {{[0-9]}}, i1 false)
+ // CHECK: call void @llvm.memset{{.*}}i8 0, i64 6, i1 false)
// .l3.p1[1].x[1] = 'x'
// CHECK: store i8 120, i8* %
@@ -98,7 +98,7 @@ void test6(void)
// CHECK: [[CALL:%[a-z0-9]+]] = call {{.*}}@get235()
// CHECK: store{{.*}}[[CALL]], {{.*}}[[TMP0:%[a-z0-9]+]]
// CHECK: [[TMP1:%[a-z0-9]+]] = bitcast {{.*}}[[TMP0]]
- // CHECK: call void @llvm.memcpy{{.*}}[[TMP1]], i64 12, i32 {{[0-9]}}, i1 false)
+ // CHECK: call void @llvm.memcpy{{.*}}[[TMP1]], i64 12, i1 false)
// CHECK: store i32 10, i32* %
diff --git a/test/CodeGen/pch-dllexport.cpp b/test/CodeGen/pch-dllexport.cpp
new file mode 100644
index 000000000000..9c6623be4362
--- /dev/null
+++ b/test/CodeGen/pch-dllexport.cpp
@@ -0,0 +1,84 @@
+// Build PCH without object file, then use it.
+// RUN: %clang_cc1 -triple i686-pc-win32 -fms-extensions -emit-pch -o %t %s
+// RUN: %clang_cc1 -triple i686-pc-win32 -fms-extensions -emit-obj -emit-llvm -include-pch %t -o - %s | FileCheck -check-prefix=PCH %s
+
+// Build PCH with object file, then use it.
+// RUN: %clang_cc1 -triple i686-pc-win32 -fms-extensions -emit-pch -building-pch-with-obj -o %t %s
+// RUN: %clang_cc1 -triple i686-pc-win32 -fms-extensions -emit-obj -emit-llvm -include-pch %t -building-pch-with-obj -o - %s | FileCheck -check-prefix=OBJ %s
+// RUN: %clang_cc1 -triple i686-pc-win32 -fms-extensions -emit-obj -emit-llvm -include-pch %t -o - %s | FileCheck -check-prefix=PCHWITHOBJ %s
+
+// Check for vars separately to avoid having to reorder the check statements.
+// RUN: %clang_cc1 -triple i686-pc-win32 -fms-extensions -emit-obj -emit-llvm -include-pch %t -o - %s | FileCheck -check-prefix=PCHWITHOBJVARS %s
+
+#ifndef IN_HEADER
+#define IN_HEADER
+
+inline void __declspec(dllexport) foo() {}
+// OBJ: define weak_odr dso_local dllexport void @"?foo@@YAXXZ"
+// PCH: define weak_odr dso_local dllexport void @"?foo@@YAXXZ"
+// PCHWITHOBJ-NOT: define {{.*}}foo
+
+
+// This function is referenced, so gets emitted as usual.
+inline void __declspec(dllexport) baz() {}
+// OBJ: define weak_odr dso_local dllexport void @"?baz@@YAXXZ"
+// PCH: define weak_odr dso_local dllexport void @"?baz@@YAXXZ"
+// PCHWITHOBJ: define weak_odr dso_local dllexport void @"?baz@@YAXXZ"
+
+
+struct __declspec(dllexport) S {
+ void bar() {}
+// OBJ: define weak_odr dso_local dllexport x86_thiscallcc void @"?bar@S@@QAEXXZ"
+// PCH: define weak_odr dso_local dllexport x86_thiscallcc void @"?bar@S@@QAEXXZ"
+// PCHWITHOBJ-NOT: define {{.*}}bar
+};
+
+// This isn't dllexported, attribute((used)) or referenced, so not emitted.
+inline void quux() {}
+// OBJ-NOT: define {{.*}}quux
+// PCH-NOT: define {{.*}}quux
+// PCHWITHOBJ-NOT: define {{.*}}quux
+
+// Referenced non-dllexport function.
+inline void referencedNonExported() {}
+// OBJ: define {{.*}}referencedNonExported
+// PCH: define {{.*}}referencedNonExported
+// PCHWITHOBJ: define {{.*}}referencedNonExported
+
+template <typename T> void __declspec(dllexport) implicitInstantiation(T) {}
+
+template <typename T> inline void __declspec(dllexport) explicitSpecialization(T) {}
+
+template <typename T> void __declspec(dllexport) explicitInstantiationDef(T) {}
+
+template <typename T> void __declspec(dllexport) explicitInstantiationDefAfterDecl(T) {}
+extern template void explicitInstantiationDefAfterDecl<int>(int);
+
+template <typename T> T __declspec(dllexport) variableTemplate;
+extern template int variableTemplate<int>;
+
+#else
+
+void use() {
+ baz();
+ referencedNonExported();
+}
+
+// Templates can be tricky. None of the definitions below come from the PCH.
+
+void useTemplate() { implicitInstantiation(42); }
+// PCHWITHOBJ: define weak_odr dso_local dllexport void @"??$implicitInstantiation@H@@YAXH@Z"
+
+template<> inline void __declspec(dllexport) explicitSpecialization<int>(int) {}
+// PCHWITHOBJ: define weak_odr dso_local dllexport void @"??$explicitSpecialization@H@@YAXH@Z"
+
+template void __declspec(dllexport) explicitInstantiationDef<int>(int);
+// PCHWITHOBJ: define weak_odr dso_local dllexport void @"??$explicitInstantiationDef@H@@YAXH@Z"
+
+template void __declspec(dllexport) explicitInstantiationDefAfterDecl<int>(int);
+// PCHWITHOBJ: define weak_odr dso_local dllexport void @"??$explicitInstantiationDefAfterDecl@H@@YAXH@Z"(i32)
+
+template int __declspec(dllexport) variableTemplate<int>;
+// PCHWITHOBJVARS: @"??$variableTemplate@H@@3HA" = weak_odr dso_local dllexport global
+
+#endif
diff --git a/test/CodeGen/personality.c b/test/CodeGen/personality.c
new file mode 100644
index 000000000000..1c533ce786c0
--- /dev/null
+++ b/test/CodeGen/personality.c
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fblocks -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNU
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fdwarf-exceptions -fblocks -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-DWARF
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fseh-exceptions -fblocks -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-SEH
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fsjlj-exceptions -fblocks -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-SJLJ
+
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fblocks -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -D __SEH_EXCEPTIONS__ -fms-extensions -fexceptions -fblocks -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-SEH-X86
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -D __SEH_EXCEPTIONS__ -fms-extensions -fexceptions -fblocks -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-SEH-X64
+
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fblocks -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNU
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fdwarf-exceptions -fblocks -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-DWARF
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fseh-exceptions -fblocks -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-SEH
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fsjlj-exceptions -fblocks -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-SJLJ
+
+
+extern void g(void (^)(void));
+extern void i(void);
+
+// CHECK-GNU: personality i8* bitcast (i32 (...)* @__gcc_personality_v0 to i8*)
+// CHECK-DWARF: personality i8* bitcast (i32 (...)* @__gcc_personality_v0 to i8*)
+// CHECK-SEH: personality i8* bitcast (i32 (...)* @__gcc_personality_seh0 to i8*)
+// CHECK-SJLJ: personality i8* bitcast (i32 (...)* @__gcc_personality_sj0 to i8*)
+
+// CHECK-WIN: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
+// CHECK-MINGW-SEH: personality i8* bitcast (i32 (...)* @__gcc_personality_seh0 to i8*)
+
+void f(void) {
+ __block int i;
+ g(^ { });
+}
+
+#if defined(__SEH_EXCEPTIONS__)
+// CHECK-WIN-SEH-X86: personality i8* bitcast (i32 (...)* @_except_handler3 to i8*)
+// CHECK-WIN-SEH-X64: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
+
+void h(void) {
+ __try {
+ i();
+ } __finally {
+ }
+}
+#endif
+
diff --git a/test/CodeGen/pgo-sample-thinlto-summary.c b/test/CodeGen/pgo-sample-thinlto-summary.c
index 7045db08f22e..eae35a040e5f 100644
--- a/test/CodeGen/pgo-sample-thinlto-summary.c
+++ b/test/CodeGen/pgo-sample-thinlto-summary.c
@@ -13,8 +13,8 @@ void foo(int n) {
g += baz(i);
}
-// SAMPLEPGO-LABEL: define void @bar
-// THINLTO-LABEL: define void @bar
+// SAMPLEPGO-LABEL: define {{(dso_local )?}}void @bar
+// THINLTO-LABEL: define {{(dso_local )?}}void @bar
// SAMPLEPGO-NOT: call{{.*}}foo
// THINLTO: call{{.*}}foo
void bar(int n) {
@@ -23,8 +23,8 @@ void bar(int n) {
}
// Checks if loop unroll is invoked by normal compile, but not thinlto compile.
-// SAMPLEPGO-LABEL: define void @unroll
-// THINLTO-LABEL: define void @unroll
+// SAMPLEPGO-LABEL: define {{(dso_local )?}}void @unroll
+// THINLTO-LABEL: define {{(dso_local )?}}void @unroll
// SAMPLEPGO: call{{.*}}baz
// SAMPLEPGO: call{{.*}}baz
// THINLTO: call{{.*}}baz
@@ -35,8 +35,8 @@ void unroll() {
}
// Checks that icp is not invoked for ThinLTO, but invoked for normal samplepgo.
-// SAMPLEPGO-LABEL: define void @icp
-// THINLTO-LABEL: define void @icp
+// SAMPLEPGO-LABEL: define {{(dso_local )?}}void @icp
+// THINLTO-LABEL: define {{(dso_local )?}}void @icp
// SAMPLEPGO: if.true.direct_targ
// FIXME: the following condition needs to be reversed once
// LTOPreLinkDefaultPipeline is customized.
diff --git a/test/CodeGen/popcnt-builtins.c b/test/CodeGen/popcnt-builtins.c
index 656a20f98605..1fdb43339a80 100644
--- a/test/CodeGen/popcnt-builtins.c
+++ b/test/CodeGen/popcnt-builtins.c
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +popcnt -emit-llvm -o - | FileCheck %s
-#include <x86intrin.h>
+#include <immintrin.h>
unsigned int test_mm_popcnt_u32(unsigned int __X) {
//CHECK: call i32 @llvm.ctpop.i32
diff --git a/test/CodeGen/ppc-varargs-struct.c b/test/CodeGen/ppc-varargs-struct.c
index d7936a126960..c201074e1fd9 100644
--- a/test/CodeGen/ppc-varargs-struct.c
+++ b/test/CodeGen/ppc-varargs-struct.c
@@ -54,7 +54,7 @@ void testva (int n, ...)
// CHECK-PPC-NEXT: [[AGGR:%[a-z0-9]+]] = load %struct.x*, %struct.x** [[VAARG_ADDR]]
// CHECK-PPC-NEXT: [[DEST:%[0-9]+]] = bitcast %struct.x* %t to i8*
// CHECK-PPC-NEXT: [[SRC:%.+]] = bitcast %struct.x* [[AGGR]] to i8*
-// CHECK-PPC-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[DEST]], i8* [[SRC]], i32 16, i32 8, i1 false)
+// CHECK-PPC-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[DEST]], i8* align 8 [[SRC]], i32 16, i1 false)
int v = va_arg (ap, int);
diff --git a/test/CodeGen/ppc64-align-struct.c b/test/CodeGen/ppc64-align-struct.c
index 5894a6aeb379..5e2dc8b2eb8a 100644
--- a/test/CodeGen/ppc64-align-struct.c
+++ b/test/CodeGen/ppc64-align-struct.c
@@ -48,15 +48,14 @@ void test7 (int x, struct test7 y)
{
}
-// CHECK-LABEL: define void @test1va(%struct.test1* noalias sret %agg.result, i32 signext %x, ...)
-// CHECK: %y = alloca %struct.test1, align 4
+// CHECK: define void @test1va(%struct.test1* noalias sret %[[AGG_RESULT:.*]], i32 signext %x, ...)
// CHECK: %[[CUR:[^ ]+]] = load i8*, i8** %ap
// CHECK: %[[NEXT:[^ ]+]] = getelementptr inbounds i8, i8* %[[CUR]], i64 8
// CHECK: store i8* %[[NEXT]], i8** %ap
// CHECK: [[T0:%.*]] = bitcast i8* %[[CUR]] to %struct.test1*
-// CHECK: [[DEST:%.*]] = bitcast %struct.test1* %y to i8*
+// CHECK: [[DEST:%.*]] = bitcast %struct.test1* %[[AGG_RESULT]] to i8*
// CHECK: [[SRC:%.*]] = bitcast %struct.test1* [[T0]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[DEST]], i8* [[SRC]], i64 8, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[DEST]], i8* align 8 [[SRC]], i64 8, i1 false)
struct test1 test1va (int x, ...)
{
struct test1 y;
@@ -67,8 +66,7 @@ struct test1 test1va (int x, ...)
return y;
}
-// CHECK-LABEL: define void @test2va(%struct.test2* noalias sret %agg.result, i32 signext %x, ...)
-// CHECK: %y = alloca %struct.test2, align 16
+// CHECK: define void @test2va(%struct.test2* noalias sret %[[AGG_RESULT:.*]], i32 signext %x, ...)
// CHECK: %[[CUR:[^ ]+]] = load i8*, i8** %ap
// CHECK: %[[TMP0:[^ ]+]] = ptrtoint i8* %[[CUR]] to i64
// CHECK: %[[TMP1:[^ ]+]] = add i64 %[[TMP0]], 15
@@ -77,9 +75,9 @@ struct test1 test1va (int x, ...)
// CHECK: %[[NEXT:[^ ]+]] = getelementptr inbounds i8, i8* %[[ALIGN]], i64 16
// CHECK: store i8* %[[NEXT]], i8** %ap
// CHECK: [[T0:%.*]] = bitcast i8* %[[ALIGN]] to %struct.test2*
-// CHECK: [[DEST:%.*]] = bitcast %struct.test2* %y to i8*
+// CHECK: [[DEST:%.*]] = bitcast %struct.test2* %[[AGG_RESULT]] to i8*
// CHECK: [[SRC:%.*]] = bitcast %struct.test2* [[T0]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[DEST]], i8* [[SRC]], i64 16, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[DEST]], i8* align 16 [[SRC]], i64 16, i1 false)
struct test2 test2va (int x, ...)
{
struct test2 y;
@@ -90,8 +88,7 @@ struct test2 test2va (int x, ...)
return y;
}
-// CHECK-LABEL: define void @test3va(%struct.test3* noalias sret %agg.result, i32 signext %x, ...)
-// CHECK: %y = alloca %struct.test3, align 32
+// CHECK: define void @test3va(%struct.test3* noalias sret %[[AGG_RESULT:.*]], i32 signext %x, ...)
// CHECK: %[[CUR:[^ ]+]] = load i8*, i8** %ap
// CHECK: %[[TMP0:[^ ]+]] = ptrtoint i8* %[[CUR]] to i64
// CHECK: %[[TMP1:[^ ]+]] = add i64 %[[TMP0]], 15
@@ -100,9 +97,9 @@ struct test2 test2va (int x, ...)
// CHECK: %[[NEXT:[^ ]+]] = getelementptr inbounds i8, i8* %[[ALIGN]], i64 32
// CHECK: store i8* %[[NEXT]], i8** %ap
// CHECK: [[T0:%.*]] = bitcast i8* %[[ALIGN]] to %struct.test3*
-// CHECK: [[DEST:%.*]] = bitcast %struct.test3* %y to i8*
+// CHECK: [[DEST:%.*]] = bitcast %struct.test3* %[[AGG_RESULT]] to i8*
// CHECK: [[SRC:%.*]] = bitcast %struct.test3* [[T0]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[DEST]], i8* [[SRC]], i64 32, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 32 [[DEST]], i8* align 16 [[SRC]], i64 32, i1 false)
struct test3 test3va (int x, ...)
{
struct test3 y;
@@ -113,15 +110,14 @@ struct test3 test3va (int x, ...)
return y;
}
-// CHECK-LABEL: define void @test4va(%struct.test4* noalias sret %agg.result, i32 signext %x, ...)
-// CHECK: %y = alloca %struct.test4, align 4
+// CHECK: define void @test4va(%struct.test4* noalias sret %[[AGG_RESULT:.*]], i32 signext %x, ...)
// CHECK: %[[CUR:[^ ]+]] = load i8*, i8** %ap
// CHECK: %[[NEXT:[^ ]+]] = getelementptr inbounds i8, i8* %[[CUR]], i64 16
// CHECK: store i8* %[[NEXT]], i8** %ap
// CHECK: [[T0:%.*]] = bitcast i8* %[[CUR]] to %struct.test4*
-// CHECK: [[DEST:%.*]] = bitcast %struct.test4* %y to i8*
+// CHECK: [[DEST:%.*]] = bitcast %struct.test4* %[[AGG_RESULT]] to i8*
// CHECK: [[SRC:%.*]] = bitcast %struct.test4* [[T0]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[DEST]], i8* [[SRC]], i64 12, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[DEST]], i8* align 8 [[SRC]], i64 12, i1 false)
struct test4 test4va (int x, ...)
{
struct test4 y;
@@ -132,15 +128,14 @@ struct test4 test4va (int x, ...)
return y;
}
-// CHECK-LABEL: define void @testva_longdouble(%struct.test_longdouble* noalias sret %agg.result, i32 signext %x, ...)
-// CHECK: %y = alloca %struct.test_longdouble, align 16
+// CHECK: define void @testva_longdouble(%struct.test_longdouble* noalias sret %[[AGG_RESULT:.*]], i32 signext %x, ...)
// CHECK: %[[CUR:[^ ]+]] = load i8*, i8** %ap
// CHECK: %[[NEXT:[^ ]+]] = getelementptr inbounds i8, i8* %[[CUR]], i64 16
// CHECK: store i8* %[[NEXT]], i8** %ap
// CHECK: [[T0:%.*]] = bitcast i8* %[[CUR]] to %struct.test_longdouble*
-// CHECK: [[DEST:%.*]] = bitcast %struct.test_longdouble* %y to i8*
+// CHECK: [[DEST:%.*]] = bitcast %struct.test_longdouble* %[[AGG_RESULT]] to i8*
// CHECK: [[SRC:%.*]] = bitcast %struct.test_longdouble* [[T0]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[DEST]], i8* [[SRC]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[DEST]], i8* align 8 [[SRC]], i64 16, i1 false)
struct test_longdouble { long double x; };
struct test_longdouble testva_longdouble (int x, ...)
{
@@ -152,8 +147,7 @@ struct test_longdouble testva_longdouble (int x, ...)
return y;
}
-// CHECK-LABEL: define void @testva_vector(%struct.test_vector* noalias sret %agg.result, i32 signext %x, ...)
-// CHECK: %y = alloca %struct.test_vector, align 16
+// CHECK: define void @testva_vector(%struct.test_vector* noalias sret %[[AGG_RESULT:.*]], i32 signext %x, ...)
// CHECK: %[[CUR:[^ ]+]] = load i8*, i8** %ap
// CHECK: %[[TMP0:[^ ]+]] = ptrtoint i8* %[[CUR]] to i64
// CHECK: %[[TMP1:[^ ]+]] = add i64 %[[TMP0]], 15
@@ -162,9 +156,9 @@ struct test_longdouble testva_longdouble (int x, ...)
// CHECK: %[[NEXT:[^ ]+]] = getelementptr inbounds i8, i8* %[[ALIGN]], i64 16
// CHECK: store i8* %[[NEXT]], i8** %ap
// CHECK: [[T0:%.*]] = bitcast i8* %[[ALIGN]] to %struct.test_vector*
-// CHECK: [[DEST:%.*]] = bitcast %struct.test_vector* %y to i8*
+// CHECK: [[DEST:%.*]] = bitcast %struct.test_vector* %[[AGG_RESULT]] to i8*
// CHECK: [[SRC:%.*]] = bitcast %struct.test_vector* [[T0]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[DEST]], i8* [[SRC]], i64 16, i32 16, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[DEST]], i8* align 16 [[SRC]], i64 16, i1 false)
struct test_vector { vector int x; };
struct test_vector testva_vector (int x, ...)
{
diff --git a/test/CodeGen/ppc64-soft-float.c b/test/CodeGen/ppc64-soft-float.c
index 95b18292319d..84ac2d55b636 100644
--- a/test/CodeGen/ppc64-soft-float.c
+++ b/test/CodeGen/ppc64-soft-float.c
@@ -92,7 +92,7 @@ void call_f2(void) { global_f2 = func_f2(global_f2); }
// CHECK-BE: %[[TMP0:[^ ]+]] = alloca %struct.f3, align 4
// CHECK: %[[TMP1:[^ ]+]] = alloca [2 x i64]
// CHECK: %[[TMP2:[^ ]+]] = bitcast [2 x i64]* %[[TMP1]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %[[TMP2]], i8* bitcast (%struct.f3* @global_f3 to i8*), i64 12, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %[[TMP2]], i8* align 4 bitcast (%struct.f3* @global_f3 to i8*), i64 12, i1 false)
// CHECK: %[[TMP3:[^ ]+]] = load [2 x i64], [2 x i64]* %[[TMP1]]
// CHECK-LE: call { i64, i64 } @func_f3([2 x i64] %[[TMP3]])
// CHECK-BE: call void @func_f3(%struct.f3* sret %[[TMP0]], [2 x i64] %[[TMP3]])
@@ -111,7 +111,7 @@ void call_f4(void) { global_f4 = func_f4(global_f4); }
// CHECK: %[[TMP0:[^ ]+]] = alloca %struct.f5, align 4
// CHECK: %[[TMP1:[^ ]+]] = alloca [3 x i64]
// CHECK: %[[TMP2:[^ ]+]] = bitcast [3 x i64]* %[[TMP1]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %[[TMP2]], i8* bitcast (%struct.f5* @global_f5 to i8*), i64 20, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %[[TMP2]], i8* align 4 bitcast (%struct.f5* @global_f5 to i8*), i64 20, i1 false)
// CHECK: %[[TMP3:[^ ]+]] = load [3 x i64], [3 x i64]* %[[TMP1]]
// CHECK: call void @func_f5(%struct.f5* sret %[[TMP0]], [3 x i64] %[[TMP3]])
struct f5 global_f5;
@@ -128,7 +128,7 @@ void call_f6(void) { global_f6 = func_f6(global_f6); }
// CHECK: %[[TMP0:[^ ]+]] = alloca %struct.f7, align 4
// CHECK: %[[TMP1:[^ ]+]] = alloca [4 x i64], align 8
// CHECK: %[[TMP2:[^ ]+]] = bitcast [4 x i64]* %[[TMP1]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %[[TMP2]], i8* bitcast (%struct.f7* @global_f7 to i8*), i64 28, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %[[TMP2]], i8* align 4 bitcast (%struct.f7* @global_f7 to i8*), i64 28, i1 false)
// CHECK: %[[TMP3:[^ ]+]] = load [4 x i64], [4 x i64]* %[[TMP1]], align 8
// CHECK: call void @func_f7(%struct.f7* sret %[[TMP0]], [4 x i64] %[[TMP3]])
struct f7 global_f7;
@@ -144,7 +144,7 @@ void call_f8(void) { global_f8 = func_f8(global_f8); }
// CHECK-LABEL: @call_f9
// CHECK: %[[TMP1:[^ ]+]] = alloca [5 x i64]
// CHECK: %[[TMP2:[^ ]+]] = bitcast [5 x i64]* %[[TMP1]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %[[TMP2]], i8* bitcast (%struct.f9* @global_f9 to i8*), i64 36, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %[[TMP2]], i8* align 4 bitcast (%struct.f9* @global_f9 to i8*), i64 36, i1 false)
// CHECK: %[[TMP3:[^ ]+]] = load [5 x i64], [5 x i64]* %[[TMP1]]
// CHECK: call void @func_f9(%struct.f9* sret %{{[^ ]+}}, [5 x i64] %[[TMP3]])
struct f9 global_f9;
@@ -162,7 +162,7 @@ void call_fab(void) { global_fab = func_fab(global_fab); }
// CHECK-BE: %[[TMPX:[^ ]+]] = alloca %struct.fabc, align 4
// CHECK: %[[TMP0:[^ ]+]] = alloca [2 x i64], align 8
// CHECK: %[[TMP2:[^ ]+]] = bitcast [2 x i64]* %[[TMP0]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %[[TMP2]], i8* bitcast (%struct.fabc* @global_fabc to i8*), i64 12, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %[[TMP2]], i8* align 4 bitcast (%struct.fabc* @global_fabc to i8*), i64 12, i1 false)
// CHECK: %[[TMP3:[^ ]+]] = load [2 x i64], [2 x i64]* %[[TMP0]], align 8
// CHECK-LE: %call = call { i64, i64 } @func_fabc([2 x i64] %[[TMP3]])
// CHECK-BE: call void @func_fabc(%struct.fabc* sret %[[TMPX]], [2 x i64] %[[TMP3]])
diff --git a/test/CodeGen/ppc64le-aggregates.c b/test/CodeGen/ppc64le-aggregates.c
index f78f26a59285..a7780beec5f6 100644
--- a/test/CodeGen/ppc64le-aggregates.c
+++ b/test/CodeGen/ppc64le-aggregates.c
@@ -104,7 +104,7 @@ void call_f8(void) { global_f8 = func_f8(global_f8); }
// CHECK-LABEL: @call_f9
// CHECK: %[[TMP1:[^ ]+]] = alloca [5 x i64]
// CHECK: %[[TMP2:[^ ]+]] = bitcast [5 x i64]* %[[TMP1]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %[[TMP2]], i8* bitcast (%struct.f9* @global_f9 to i8*), i64 36, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %[[TMP2]], i8* align 4 bitcast (%struct.f9* @global_f9 to i8*), i64 36, i1 false)
// CHECK: %[[TMP3:[^ ]+]] = load [5 x i64], [5 x i64]* %[[TMP1]]
// CHECK: call void @func_f9(%struct.f9* sret %{{[^ ]+}}, [5 x i64] %[[TMP3]])
struct f9 global_f9;
diff --git a/test/CodeGen/ppc64le-f128Aggregates.c b/test/CodeGen/ppc64le-f128Aggregates.c
new file mode 100644
index 000000000000..a51b6d5e709c
--- /dev/null
+++ b/test/CodeGen/ppc64le-f128Aggregates.c
@@ -0,0 +1,124 @@
+// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu -emit-llvm \
+// RUN: -target-cpu pwr9 -target-feature +float128 -o - %s | FileCheck %s
+
+// Test homogeneous fp128 aggregate passing and returning.
+
+struct fp1 { __float128 f[1]; };
+struct fp2 { __float128 f[2]; };
+struct fp3 { __float128 f[3]; };
+struct fp4 { __float128 f[4]; };
+struct fp5 { __float128 f[5]; };
+struct fp6 { __float128 f[6]; };
+struct fp7 { __float128 f[7]; };
+struct fp8 { __float128 f[8]; };
+struct fp9 { __float128 f[9]; };
+
+struct fpab { __float128 a; __float128 b; };
+struct fpabc { __float128 a; __float128 b; __float128 c; };
+
+struct fp2a2b { __float128 a[2]; __float128 b[2]; };
+
+// CHECK: define [1 x fp128] @func_f1(fp128 inreg %x.coerce)
+struct fp1 func_f1(struct fp1 x) { return x; }
+
+// CHECK: define [2 x fp128] @func_f2([2 x fp128] %x.coerce)
+struct fp2 func_f2(struct fp2 x) { return x; }
+
+// CHECK: define [3 x fp128] @func_f3([3 x fp128] %x.coerce)
+struct fp3 func_f3(struct fp3 x) { return x; }
+
+// CHECK: define [4 x fp128] @func_f4([4 x fp128] %x.coerce)
+struct fp4 func_f4(struct fp4 x) { return x; }
+
+// CHECK: define [5 x fp128] @func_f5([5 x fp128] %x.coerce)
+struct fp5 func_f5(struct fp5 x) { return x; }
+
+// CHECK: define [6 x fp128] @func_f6([6 x fp128] %x.coerce)
+struct fp6 func_f6(struct fp6 x) { return x; }
+
+// CHECK: define [7 x fp128] @func_f7([7 x fp128] %x.coerce)
+struct fp7 func_f7(struct fp7 x) { return x; }
+
+// CHECK: define [8 x fp128] @func_f8([8 x fp128] %x.coerce)
+struct fp8 func_f8(struct fp8 x) { return x; }
+
+// CHECK: define void @func_f9(%struct.fp9* noalias sret %agg.result, %struct.fp9* byval align 16 %x)
+struct fp9 func_f9(struct fp9 x) { return x; }
+
+// CHECK: define [2 x fp128] @func_fab([2 x fp128] %x.coerce)
+struct fpab func_fab(struct fpab x) { return x; }
+
+// CHECK: define [3 x fp128] @func_fabc([3 x fp128] %x.coerce)
+struct fpabc func_fabc(struct fpabc x) { return x; }
+
+// CHECK: define [4 x fp128] @func_f2a2b([4 x fp128] %x.coerce)
+struct fp2a2b func_f2a2b(struct fp2a2b x) { return x; }
+
+// CHECK-LABEL: @call_fp1
+// CHECK: %[[TMP:[^ ]+]] = load fp128, fp128* getelementptr inbounds (%struct.fp1, %struct.fp1* @global_f1, i32 0, i32 0, i32 0), align 16
+// CHECK: call [1 x fp128] @func_f1(fp128 inreg %[[TMP]])
+struct fp1 global_f1;
+void call_fp1(void) { global_f1 = func_f1(global_f1); }
+
+// CHECK-LABEL: @call_fp2
+// CHECK: %[[TMP:[^ ]+]] = load [2 x fp128], [2 x fp128]* getelementptr inbounds (%struct.fp2, %struct.fp2* @global_f2, i32 0, i32 0), align 16
+// CHECK: call [2 x fp128] @func_f2([2 x fp128] %[[TMP]])
+struct fp2 global_f2;
+void call_fp2(void) { global_f2 = func_f2(global_f2); }
+
+// CHECK-LABEL: @call_fp3
+// CHECK: %[[TMP:[^ ]+]] = load [3 x fp128], [3 x fp128]* getelementptr inbounds (%struct.fp3, %struct.fp3* @global_f3, i32 0, i32 0), align 16
+// CHECK: call [3 x fp128] @func_f3([3 x fp128] %[[TMP]])
+struct fp3 global_f3;
+void call_fp3(void) { global_f3 = func_f3(global_f3); }
+
+// CHECK-LABEL: @call_fp4
+// CHECK: %[[TMP:[^ ]+]] = load [4 x fp128], [4 x fp128]* getelementptr inbounds (%struct.fp4, %struct.fp4* @global_f4, i32 0, i32 0), align 16
+// CHECK: call [4 x fp128] @func_f4([4 x fp128] %[[TMP]])
+struct fp4 global_f4;
+void call_fp4(void) { global_f4 = func_f4(global_f4); }
+
+// CHECK-LABEL: @call_fp5
+// CHECK: %[[TMP:[^ ]+]] = load [5 x fp128], [5 x fp128]* getelementptr inbounds (%struct.fp5, %struct.fp5* @global_f5, i32 0, i32 0), align 16
+// CHECK: call [5 x fp128] @func_f5([5 x fp128] %[[TMP]])
+struct fp5 global_f5;
+void call_fp5(void) { global_f5 = func_f5(global_f5); }
+
+// CHECK-LABEL: @call_fp6
+// CHECK: %[[TMP:[^ ]+]] = load [6 x fp128], [6 x fp128]* getelementptr inbounds (%struct.fp6, %struct.fp6* @global_f6, i32 0, i32 0), align 16
+// CHECK: call [6 x fp128] @func_f6([6 x fp128] %[[TMP]])
+struct fp6 global_f6;
+void call_fp6(void) { global_f6 = func_f6(global_f6); }
+
+// CHECK-LABEL: @call_fp7
+// CHECK: %[[TMP:[^ ]+]] = load [7 x fp128], [7 x fp128]* getelementptr inbounds (%struct.fp7, %struct.fp7* @global_f7, i32 0, i32 0), align 16
+// CHECK: call [7 x fp128] @func_f7([7 x fp128] %[[TMP]])
+struct fp7 global_f7;
+void call_fp7(void) { global_f7 = func_f7(global_f7); }
+
+// CHECK-LABEL: @call_fp8
+// CHECK: %[[TMP:[^ ]+]] = load [8 x fp128], [8 x fp128]* getelementptr inbounds (%struct.fp8, %struct.fp8* @global_f8, i32 0, i32 0), align 16
+// CHECK: call [8 x fp128] @func_f8([8 x fp128] %[[TMP]])
+struct fp8 global_f8;
+void call_fp8(void) { global_f8 = func_f8(global_f8); }
+
+// CHECK-LABEL: @call_fp9
+// CHECK: %[[TMP1:[^ ]+]] = alloca %struct.fp9, align 16
+// CHECK: call void @func_f9(%struct.fp9* sret %[[TMP2:[^ ]+]], %struct.fp9* byval align 16 @global_f9
+// CHECK: %[[TMP3:[^ ]+]] = bitcast %struct.fp9* %[[TMP2]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 bitcast (%struct.fp9* @global_f9 to i8*), i8* align 16 %[[TMP3]], i64 144, i1 false
+// CHECK: ret void
+struct fp9 global_f9;
+void call_fp9(void) { global_f9 = func_f9(global_f9); }
+
+// CHECK-LABEL: @call_fpab
+// CHECK: %[[TMP:[^ ]+]] = load [2 x fp128], [2 x fp128]* bitcast (%struct.fpab* @global_fab to [2 x fp128]*)
+// CHECK: call [2 x fp128] @func_fab([2 x fp128] %[[TMP]])
+struct fpab global_fab;
+void call_fpab(void) { global_fab = func_fab(global_fab); }
+
+// CHECK-LABEL: @call_fpabc
+// CHECK: %[[TMP:[^ ]+]] = load [3 x fp128], [3 x fp128]* bitcast (%struct.fpabc* @global_fabc to [3 x fp128]*)
+// CHECK: call [3 x fp128] @func_fabc([3 x fp128] %[[TMP]])
+struct fpabc global_fabc;
+void call_fpabc(void) { global_fabc = func_fabc(global_fabc); }
diff --git a/test/CodeGen/pr19841.cpp b/test/CodeGen/pr19841.cpp
index 8fef68384fc1..282b2e6d000b 100644
--- a/test/CodeGen/pr19841.cpp
+++ b/test/CodeGen/pr19841.cpp
@@ -12,7 +12,7 @@ class A {
unsigned char _highlightColorTableVGA[];
static const unsigned char b[];
};
-// CHECK: [[Common_A_b:@[^ ]+]] = constant [1 x i8] zeroinitializer
+// CHECK: [[Common_A_b:@[^ ]+]] = {{(dso_local )?}}constant [1 x i8] zeroinitializer
class B {
public:
Common::RenderMode _configRenderMode;
diff --git a/test/CodeGen/pr3518.c b/test/CodeGen/pr3518.c
index 5ce6a6570564..f0c06d9be6dc 100644
--- a/test/CodeGen/pr3518.c
+++ b/test/CodeGen/pr3518.c
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
// PR 3518
-// Some of the objects were coming out as unintialized (external) before 3518
+// Some of the objects were coming out as uninitialized (external) before 3518
// was fixed. Internal names are different between llvm-gcc and clang so they
// are not tested.
diff --git a/test/CodeGen/pr4349.c b/test/CodeGen/pr4349.c
index e39dc2c517f4..9ec6f2fac78a 100644
--- a/test/CodeGen/pr4349.c
+++ b/test/CodeGen/pr4349.c
@@ -16,22 +16,22 @@ struct svar
{
void *ptr;
};
-// CHECK: @svars1 = global [1 x %struct.svar] [%struct.svar { i8* bitcast (%struct.cpu* @cpu to i8*) }]
+// CHECK: @svars1 = {{(dso_local )?}}global [1 x %struct.svar] [%struct.svar { i8* bitcast (%struct.cpu* @cpu to i8*) }]
struct svar svars1[] =
{
{ &((cpu.pc).w[0]) }
};
-// CHECK: @svars2 = global [1 x %struct.svar] [%struct.svar { i8* getelementptr (i8, i8* bitcast (%struct.cpu* @cpu to i8*), i64 1) }]
+// CHECK: @svars2 = {{(dso_local )?}}global [1 x %struct.svar] [%struct.svar { i8* getelementptr (i8, i8* bitcast (%struct.cpu* @cpu to i8*), i64 1) }]
struct svar svars2[] =
{
{ &((cpu.pc).b[0][1]) }
};
-// CHECK: @svars3 = global [1 x %struct.svar] [%struct.svar { i8* getelementptr (i8, i8* bitcast (%struct.cpu* @cpu to i8*), i64 2) }]
+// CHECK: @svars3 = {{(dso_local )?}}global [1 x %struct.svar] [%struct.svar { i8* getelementptr (i8, i8* bitcast (%struct.cpu* @cpu to i8*), i64 2) }]
struct svar svars3[] =
{
{ &((cpu.pc).w[1]) }
};
-// CHECK: @svars4 = global [1 x %struct.svar] [%struct.svar { i8* getelementptr (i8, i8* bitcast (%struct.cpu* @cpu to i8*), i64 3) }]
+// CHECK: @svars4 = {{(dso_local )?}}global [1 x %struct.svar] [%struct.svar { i8* getelementptr (i8, i8* bitcast (%struct.cpu* @cpu to i8*), i64 3) }]
struct svar svars4[] =
{
{ &((cpu.pc).b[1][1]) }
diff --git a/test/CodeGen/pragma-comment.c b/test/CodeGen/pragma-comment.c
index fae9b8fb9ed8..1896e5c0fb98 100644
--- a/test/CodeGen/pragma-comment.c
+++ b/test/CodeGen/pragma-comment.c
@@ -23,10 +23,9 @@
// CHECK: ![[bar]] = !{!" /bar=2"}
// CHECK: ![[foo]] = !{!" /foo=\22foo bar\22"}
-// LINUX: !{!"-lmsvcrt.lib"}
-// LINUX: !{!"-lkernel32"}
-// LINUX: !{!"-lUSER32.LIB"}
-// LINUX: !{!" /bar=2"}
+// LINUX: !{!"lib", !"msvcrt.lib"}
+// LINUX: !{!"lib", !"kernel32"}
+// LINUX: !{!"lib", !"USER32.LIB"}
// PS4: !{!"\01msvcrt.lib"}
// PS4: !{!"\01kernel32"}
diff --git a/test/CodeGen/pragma-do-while.cpp b/test/CodeGen/pragma-do-while.cpp
new file mode 100644
index 000000000000..ecab7fc029e2
--- /dev/null
+++ b/test/CodeGen/pragma-do-while.cpp
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s
+
+// We expect to get a loop structure like this:
+// do.body: ; preds = %do.cond, ...
+// ...
+// br label %do.cond
+// do.cond: ; preds = %do.body
+// ...
+// br i1 %cmp, label %do.body, label %do.end
+// do.end: ; preds = %do.cond
+// ...
+//
+// Verify that the loop metadata only is put on the backedge.
+//
+// CHECK-NOT: llvm.loop
+// CHECK-LABEL: do.cond:
+// CHECK: br {{.*}}, label %do.body, label %do.end, !llvm.loop ![[LMD1:[0-9]+]]
+// CHECK-LABEL: do.end:
+// CHECK-NOT: llvm.loop
+// CHECK: ![[LMD1]] = distinct !{![[LMD1]], ![[LMD2:[0-9]+]]}
+// CHECK: ![[LMD2]] = !{!"llvm.loop.unroll.count", i32 4}
+
+int test(int a[], int n) {
+ int i = 0;
+ int sum = 0;
+
+#pragma unroll 4
+ do
+ {
+ a[i] = a[i] + 1;
+ sum = sum + a[i];
+ i++;
+ } while (i < n);
+
+ return sum;
+}
diff --git a/test/CodeGen/preserve-call-conv.c b/test/CodeGen/preserve-call-conv.c
index b67e29f392a4..7a84fa282314 100644
--- a/test/CodeGen/preserve-call-conv.c
+++ b/test/CodeGen/preserve-call-conv.c
@@ -3,18 +3,19 @@
// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -triple aarch64-unknown-windows-msvc -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple thumbv7-unknown-windows-msvc -emit-llvm %s -o - | FileCheck %s
// Check that the preserve_most calling convention attribute at the source level
// is lowered to the corresponding calling convention attrribute at the LLVM IR
// level.
void foo() __attribute__((preserve_most)) {
- // CHECK-LABEL: define preserve_mostcc void @foo()
+ // CHECK-LABEL: define {{(dso_local )?}}preserve_mostcc void @foo()
}
// Check that the preserve_most calling convention attribute at the source level
// is lowered to the corresponding calling convention attrribute at the LLVM IR
// level.
void boo() __attribute__((preserve_all)) {
- // CHECK-LABEL: define preserve_allcc void @boo()
+ // CHECK-LABEL: define {{(dso_local )?}}preserve_allcc void @boo()
}
diff --git a/test/CodeGen/ptwrite.c b/test/CodeGen/ptwrite.c
new file mode 100644
index 000000000000..a34ed741b5ff
--- /dev/null
+++ b/test/CodeGen/ptwrite.c
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 %s -ffreestanding -triple=x86_64-unknown-unknown -target-feature +ptwrite -emit-llvm -o - -Wall -Werror -pedantic | FileCheck %s --check-prefix=X86 --check-prefix=X86_64
+// RUN: %clang_cc1 %s -ffreestanding -triple=i386-unknown-unknown -target-feature +ptwrite -emit-llvm -o - -Wall -Werror -pedantic | FileCheck %s --check-prefix=X86
+
+#include <immintrin.h>
+
+#include <stdint.h>
+
+void test_ptwrite32(uint32_t value) {
+ //X86-LABEL: @test_ptwrite32
+ //X86: call void @llvm.x86.ptwrite32(i32 %{{.*}})
+ _ptwrite32(value);
+}
+
+#ifdef __x86_64__
+
+void test_ptwrite64(uint64_t value) {
+ //X86_64-LABEL: @test_ptwrite64
+ //X86_64: call void @llvm.x86.ptwrite64(i64 %{{.*}})
+ _ptwrite64(value);
+}
+
+#endif /* __x86_64__ */
diff --git a/test/CodeGen/rdpid-builtins.c b/test/CodeGen/rdpid-builtins.c
new file mode 100644
index 000000000000..0816bd07ad1d
--- /dev/null
+++ b/test/CodeGen/rdpid-builtins.c
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -ffreestanding -triple x86_64-unknown-unknown -target-feature +rdpid -emit-llvm -o - %s | FileCheck %s
+
+
+#include <immintrin.h>
+
+unsigned int test_rdpid_u32(void) {
+// CHECK-LABEL: @test_rdpid_u32
+// CHECK: call i32 @llvm.x86.rdpid
+ return _rdpid_u32();
+}
diff --git a/test/CodeGen/rdrand-builtins.c b/test/CodeGen/rdrand-builtins.c
index 936502b77483..44a38a048e96 100644
--- a/test/CodeGen/rdrand-builtins.c
+++ b/test/CodeGen/rdrand-builtins.c
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -ffreestanding -triple x86_64-unknown-unknown -target-feature +rdrnd -target-feature +rdseed -emit-llvm -o - %s | FileCheck %s
-#include <x86intrin.h>
+#include <immintrin.h>
int rdrand16(unsigned short *p) {
return _rdrand16_step(p);
diff --git a/test/CodeGen/regcall.c b/test/CodeGen/regcall.c
index 350a82d33963..b7389904844a 100644
--- a/test/CodeGen/regcall.c
+++ b/test/CodeGen/regcall.c
@@ -6,34 +6,34 @@
#include <xmmintrin.h>
void __regcall v1(int a, int b) {}
-// Win32: define x86_regcallcc void @__regcall3__v1(i32 inreg %a, i32 inreg %b)
-// Win64: define x86_regcallcc void @__regcall3__v1(i32 %a, i32 %b)
+// Win32: define dso_local x86_regcallcc void @__regcall3__v1(i32 inreg %a, i32 inreg %b)
+// Win64: define dso_local x86_regcallcc void @__regcall3__v1(i32 %a, i32 %b)
// Lin32: define x86_regcallcc void @__regcall3__v1(i32 inreg %a, i32 inreg %b)
// Lin64: define x86_regcallcc void @__regcall3__v1(i32 %a, i32 %b)
void __attribute__((regcall)) v1b(int a, int b) {}
-// Win32: define x86_regcallcc void @__regcall3__v1b(i32 inreg %a, i32 inreg %b)
-// Win64: define x86_regcallcc void @__regcall3__v1b(i32 %a, i32 %b)
+// Win32: define dso_local x86_regcallcc void @__regcall3__v1b(i32 inreg %a, i32 inreg %b)
+// Win64: define dso_local x86_regcallcc void @__regcall3__v1b(i32 %a, i32 %b)
// Lin32: define x86_regcallcc void @__regcall3__v1b(i32 inreg %a, i32 inreg %b)
// Lin64: define x86_regcallcc void @__regcall3__v1b(i32 %a, i32 %b)
void __regcall v2(char a, char b) {}
-// Win32: define x86_regcallcc void @__regcall3__v2(i8 inreg signext %a, i8 inreg signext %b)
-// Win64: define x86_regcallcc void @__regcall3__v2(i8 %a, i8 %b)
+// Win32: define dso_local x86_regcallcc void @__regcall3__v2(i8 inreg signext %a, i8 inreg signext %b)
+// Win64: define dso_local x86_regcallcc void @__regcall3__v2(i8 %a, i8 %b)
// Lin32: define x86_regcallcc void @__regcall3__v2(i8 inreg signext %a, i8 inreg signext %b)
// Lin64: define x86_regcallcc void @__regcall3__v2(i8 signext %a, i8 signext %b)
struct Small { int x; };
void __regcall v3(int a, struct Small b, int c) {}
-// Win32: define x86_regcallcc void @__regcall3__v3(i32 inreg %a, i32 %b.0, i32 inreg %c)
-// Win64: define x86_regcallcc void @__regcall3__v3(i32 %a, i32 %b.coerce, i32 %c)
+// Win32: define dso_local x86_regcallcc void @__regcall3__v3(i32 inreg %a, i32 %b.0, i32 inreg %c)
+// Win64: define dso_local x86_regcallcc void @__regcall3__v3(i32 %a, i32 %b.coerce, i32 %c)
// Lin32: define x86_regcallcc void @__regcall3__v3(i32 inreg %a, i32 inreg, i32 %b.0, i32 inreg %c)
// Lin64: define x86_regcallcc void @__regcall3__v3(i32 %a, i32 %b.coerce, i32 %c)
struct Large { int a[5]; };
void __regcall v4(int a, struct Large b, int c) {}
-// Win32: define x86_regcallcc void @__regcall3__v4(i32 inreg %a, %struct.Large* byval align 4 %b, i32 inreg %c)
-// Win64: define x86_regcallcc void @__regcall3__v4(i32 %a, %struct.Large* %b, i32 %c)
+// Win32: define dso_local x86_regcallcc void @__regcall3__v4(i32 inreg %a, %struct.Large* byval align 4 %b, i32 inreg %c)
+// Win64: define dso_local x86_regcallcc void @__regcall3__v4(i32 %a, %struct.Large* %b, i32 %c)
// Lin32: define x86_regcallcc void @__regcall3__v4(i32 inreg %a, %struct.Large* byval align 4 %b, i32 %c)
// Lin64: define x86_regcallcc void @__regcall3__v4(i32 %a, [5 x i32] %b.coerce, i32 %c)
@@ -42,8 +42,8 @@ struct HFA4 { double w, x, y, z; };
struct HFA5 { double v, w, x, y, z; };
void __regcall hfa1(int a, struct HFA4 b, int c) {}
-// Win32: define x86_regcallcc void @__regcall3__hfa1(i32 inreg %a, double %b.0, double %b.1, double %b.2, double %b.3, i32 inreg %c)
-// Win64: define x86_regcallcc void @__regcall3__hfa1(i32 %a, double %b.0, double %b.1, double %b.2, double %b.3, i32 %c)
+// Win32: define dso_local x86_regcallcc void @__regcall3__hfa1(i32 inreg %a, double %b.0, double %b.1, double %b.2, double %b.3, i32 inreg %c)
+// Win64: define dso_local x86_regcallcc void @__regcall3__hfa1(i32 %a, double %b.0, double %b.1, double %b.2, double %b.3, i32 %c)
// Lin32: define x86_regcallcc void @__regcall3__hfa1(i32 inreg %a, double %b.0, double %b.1, double %b.2, double %b.3, i32 inreg %c)
// Lin64: define x86_regcallcc void @__regcall3__hfa1(i32 %a, double %b.coerce0, double %b.coerce1, double %b.coerce2, double %b.coerce3, i32 %c)
@@ -51,16 +51,16 @@ void __regcall hfa1(int a, struct HFA4 b, int c) {}
// indirectly. Additional vector arguments can consume the rest of the SSE
// registers.
void __regcall hfa2(struct HFA4 a, struct HFA4 b, double c) {}
-// Win32: define x86_regcallcc void @__regcall3__hfa2(double %a.0, double %a.1, double %a.2, double %a.3, double %b.0, double %b.1, double %b.2, double %b.3, double* inreg)
-// Win64: define x86_regcallcc void @__regcall3__hfa2(double %a.0, double %a.1, double %a.2, double %a.3, double %b.0, double %b.1, double %b.2, double %b.3, double %c)
+// Win32: define dso_local x86_regcallcc void @__regcall3__hfa2(double %a.0, double %a.1, double %a.2, double %a.3, double %b.0, double %b.1, double %b.2, double %b.3, double* inreg)
+// Win64: define dso_local x86_regcallcc void @__regcall3__hfa2(double %a.0, double %a.1, double %a.2, double %a.3, double %b.0, double %b.1, double %b.2, double %b.3, double %c)
// Lin32: define x86_regcallcc void @__regcall3__hfa2(double %a.0, double %a.1, double %a.2, double %a.3, double %b.0, double %b.1, double %b.2, double %b.3, double* inreg)
// Lin64: define x86_regcallcc void @__regcall3__hfa2(double %a.coerce0, double %a.coerce1, double %a.coerce2, double %a.coerce3, double %b.coerce0, double %b.coerce1, double %b.coerce2, double %b.coerce3, double %c)
// Ensure that we pass builtin types directly while counting them against the
// SSE register usage.
void __regcall hfa3(double a, double b, double c, double d, double e, struct HFA2 f) {}
-// Win32: define x86_regcallcc void @__regcall3__hfa3(double %a, double %b, double %c, double %d, double %e, double %f.0, double %f.1)
-// Win64: define x86_regcallcc void @__regcall3__hfa3(double %a, double %b, double %c, double %d, double %e, double %f.0, double %f.1)
+// Win32: define dso_local x86_regcallcc void @__regcall3__hfa3(double %a, double %b, double %c, double %d, double %e, double %f.0, double %f.1)
+// Win64: define dso_local x86_regcallcc void @__regcall3__hfa3(double %a, double %b, double %c, double %d, double %e, double %f.0, double %f.1)
// Lin32: define x86_regcallcc void @__regcall3__hfa3(double %a, double %b, double %c, double %d, double %e, double %f.0, double %f.1)
// Lin64: define x86_regcallcc void @__regcall3__hfa3(double %a, double %b, double %c, double %d, double %e, double %f.coerce0, double %f.coerce1)
@@ -68,16 +68,16 @@ void __regcall hfa3(double a, double b, double c, double d, double e, struct HFA
// Because they are not classified as homogeneous, they don't get special
// handling to ensure alignment.
void __regcall hfa4(struct HFA5 a) {}
-// Win32: define x86_regcallcc void @__regcall3__hfa4(%struct.HFA5* byval align 4)
-// Win64: define x86_regcallcc void @__regcall3__hfa4(%struct.HFA5* %a)
+// Win32: define dso_local x86_regcallcc void @__regcall3__hfa4(%struct.HFA5* byval align 4)
+// Win64: define dso_local x86_regcallcc void @__regcall3__hfa4(%struct.HFA5* %a)
// Lin32: define x86_regcallcc void @__regcall3__hfa4(%struct.HFA5* byval align 4 %a)
// Lin64: define x86_regcallcc void @__regcall3__hfa4(double %a.coerce0, double %a.coerce1, double %a.coerce2, double %a.coerce3, double %a.coerce4)
// Return HFAs of 4 or fewer elements in registers.
static struct HFA2 g_hfa2;
struct HFA2 __regcall hfa5(void) { return g_hfa2; }
-// Win32: define x86_regcallcc %struct.HFA2 @__regcall3__hfa5()
-// Win64: define x86_regcallcc %struct.HFA2 @__regcall3__hfa5()
+// Win32: define dso_local x86_regcallcc %struct.HFA2 @__regcall3__hfa5()
+// Win64: define dso_local x86_regcallcc %struct.HFA2 @__regcall3__hfa5()
// Lin32: define x86_regcallcc %struct.HFA2 @__regcall3__hfa5()
// Lin64: define x86_regcallcc %struct.HFA2 @__regcall3__hfa5()
@@ -86,20 +86,20 @@ struct HVA2 { v4f32 x, y; };
struct HVA4 { v4f32 w, x, y, z; };
void __regcall hva1(int a, struct HVA4 b, int c) {}
-// Win32: define x86_regcallcc void @__regcall3__hva1(i32 inreg %a, <4 x float> %b.0, <4 x float> %b.1, <4 x float> %b.2, <4 x float> %b.3, i32 inreg %c)
-// Win64: define x86_regcallcc void @__regcall3__hva1(i32 %a, <4 x float> %b.0, <4 x float> %b.1, <4 x float> %b.2, <4 x float> %b.3, i32 %c)
+// Win32: define dso_local x86_regcallcc void @__regcall3__hva1(i32 inreg %a, <4 x float> %b.0, <4 x float> %b.1, <4 x float> %b.2, <4 x float> %b.3, i32 inreg %c)
+// Win64: define dso_local x86_regcallcc void @__regcall3__hva1(i32 %a, <4 x float> %b.0, <4 x float> %b.1, <4 x float> %b.2, <4 x float> %b.3, i32 %c)
// Lin32: define x86_regcallcc void @__regcall3__hva1(i32 inreg %a, <4 x float> %b.0, <4 x float> %b.1, <4 x float> %b.2, <4 x float> %b.3, i32 inreg %c)
// Lin64: define x86_regcallcc void @__regcall3__hva1(i32 %a, <4 x float> %b.coerce0, <4 x float> %b.coerce1, <4 x float> %b.coerce2, <4 x float> %b.coerce3, i32 %c)
void __regcall hva2(struct HVA4 a, struct HVA4 b, v4f32 c) {}
-// Win32: define x86_regcallcc void @__regcall3__hva2(<4 x float> %a.0, <4 x float> %a.1, <4 x float> %a.2, <4 x float> %a.3, <4 x float> %b.0, <4 x float> %b.1, <4 x float> %b.2, <4 x float> %b.3, <4 x float>* inreg)
-// Win64: define x86_regcallcc void @__regcall3__hva2(<4 x float> %a.0, <4 x float> %a.1, <4 x float> %a.2, <4 x float> %a.3, <4 x float> %b.0, <4 x float> %b.1, <4 x float> %b.2, <4 x float> %b.3, <4 x float> %c)
+// Win32: define dso_local x86_regcallcc void @__regcall3__hva2(<4 x float> %a.0, <4 x float> %a.1, <4 x float> %a.2, <4 x float> %a.3, <4 x float> %b.0, <4 x float> %b.1, <4 x float> %b.2, <4 x float> %b.3, <4 x float>* inreg)
+// Win64: define dso_local x86_regcallcc void @__regcall3__hva2(<4 x float> %a.0, <4 x float> %a.1, <4 x float> %a.2, <4 x float> %a.3, <4 x float> %b.0, <4 x float> %b.1, <4 x float> %b.2, <4 x float> %b.3, <4 x float> %c)
// Lin32: define x86_regcallcc void @__regcall3__hva2(<4 x float> %a.0, <4 x float> %a.1, <4 x float> %a.2, <4 x float> %a.3, <4 x float> %b.0, <4 x float> %b.1, <4 x float> %b.2, <4 x float> %b.3, <4 x float>* inreg)
// Lin64: define x86_regcallcc void @__regcall3__hva2(<4 x float> %a.coerce0, <4 x float> %a.coerce1, <4 x float> %a.coerce2, <4 x float> %a.coerce3, <4 x float> %b.coerce0, <4 x float> %b.coerce1, <4 x float> %b.coerce2, <4 x float> %b.coerce3, <4 x float> %c)
void __regcall hva3(v4f32 a, v4f32 b, v4f32 c, v4f32 d, v4f32 e, struct HVA2 f) {}
-// Win32: define x86_regcallcc void @__regcall3__hva3(<4 x float> %a, <4 x float> %b, <4 x float> %c, <4 x float> %d, <4 x float> %e, <4 x float> %f.0, <4 x float> %f.1)
-// Win64: define x86_regcallcc void @__regcall3__hva3(<4 x float> %a, <4 x float> %b, <4 x float> %c, <4 x float> %d, <4 x float> %e, <4 x float> %f.0, <4 x float> %f.1)
+// Win32: define dso_local x86_regcallcc void @__regcall3__hva3(<4 x float> %a, <4 x float> %b, <4 x float> %c, <4 x float> %d, <4 x float> %e, <4 x float> %f.0, <4 x float> %f.1)
+// Win64: define dso_local x86_regcallcc void @__regcall3__hva3(<4 x float> %a, <4 x float> %b, <4 x float> %c, <4 x float> %d, <4 x float> %e, <4 x float> %f.0, <4 x float> %f.1)
// Lin32: define x86_regcallcc void @__regcall3__hva3(<4 x float> %a, <4 x float> %b, <4 x float> %c, <4 x float> %d, <4 x float> %e, <4 x float> %f.0, <4 x float> %f.1)
// Lin64: define x86_regcallcc void @__regcall3__hva3(<4 x float> %a, <4 x float> %b, <4 x float> %c, <4 x float> %d, <4 x float> %e, <4 x float> %f.coerce0, <4 x float> %f.coerce1)
@@ -107,14 +107,14 @@ typedef float __attribute__((ext_vector_type(3))) v3f32;
struct OddSizeHVA { v3f32 x, y; };
void __regcall odd_size_hva(struct OddSizeHVA a) {}
-// Win32: define x86_regcallcc void @__regcall3__odd_size_hva(<3 x float> %a.0, <3 x float> %a.1)
-// Win64: define x86_regcallcc void @__regcall3__odd_size_hva(<3 x float> %a.0, <3 x float> %a.1)
+// Win32: define dso_local x86_regcallcc void @__regcall3__odd_size_hva(<3 x float> %a.0, <3 x float> %a.1)
+// Win64: define dso_local x86_regcallcc void @__regcall3__odd_size_hva(<3 x float> %a.0, <3 x float> %a.1)
// Lin32: define x86_regcallcc void @__regcall3__odd_size_hva(<3 x float> %a.0, <3 x float> %a.1)
// Lin64: define x86_regcallcc void @__regcall3__odd_size_hva(<3 x float> %a.coerce0, <3 x float> %a.coerce1)
struct HFA6 { __m128 f[4]; };
struct HFA6 __regcall ret_reg_reused(struct HFA6 a, struct HFA6 b, struct HFA6 c, struct HFA6 d){ struct HFA6 h; return h;}
-// Win32: define x86_regcallcc %struct.HFA6 @__regcall3__ret_reg_reused(<4 x float> %a.0, <4 x float> %a.1, <4 x float> %a.2, <4 x float> %a.3, <4 x float> %b.0, <4 x float> %b.1, <4 x float> %b.2, <4 x float> %b.3, %struct.HFA6* inreg %c, %struct.HFA6* inreg %d)
-// Win64: define x86_regcallcc %struct.HFA6 @__regcall3__ret_reg_reused(<4 x float> %a.0, <4 x float> %a.1, <4 x float> %a.2, <4 x float> %a.3, <4 x float> %b.0, <4 x float> %b.1, <4 x float> %b.2, <4 x float> %b.3, <4 x float> %c.0, <4 x float> %c.1, <4 x float> %c.2, <4 x float> %c.3, <4 x float> %d.0, <4 x float> %d.1, <4 x float> %d.2, <4 x float> %d.3)
+// Win32: define dso_local x86_regcallcc %struct.HFA6 @__regcall3__ret_reg_reused(<4 x float> %a.0, <4 x float> %a.1, <4 x float> %a.2, <4 x float> %a.3, <4 x float> %b.0, <4 x float> %b.1, <4 x float> %b.2, <4 x float> %b.3, %struct.HFA6* inreg %c, %struct.HFA6* inreg %d)
+// Win64: define dso_local x86_regcallcc %struct.HFA6 @__regcall3__ret_reg_reused(<4 x float> %a.0, <4 x float> %a.1, <4 x float> %a.2, <4 x float> %a.3, <4 x float> %b.0, <4 x float> %b.1, <4 x float> %b.2, <4 x float> %b.3, <4 x float> %c.0, <4 x float> %c.1, <4 x float> %c.2, <4 x float> %c.3, <4 x float> %d.0, <4 x float> %d.1, <4 x float> %d.2, <4 x float> %d.3)
// Lin32: define x86_regcallcc %struct.HFA6 @__regcall3__ret_reg_reused(<4 x float> %a.0, <4 x float> %a.1, <4 x float> %a.2, <4 x float> %a.3, <4 x float> %b.0, <4 x float> %b.1, <4 x float> %b.2, <4 x float> %b.3, %struct.HFA6* inreg %c, %struct.HFA6* inreg %d)
// Lin64: define x86_regcallcc %struct.HFA6 @__regcall3__ret_reg_reused([4 x <4 x float>] %a.coerce, [4 x <4 x float>] %b.coerce, [4 x <4 x float>] %c.coerce, [4 x <4 x float>] %d.coerce)
diff --git a/test/CodeGen/riscv32-abi.c b/test/CodeGen/riscv32-abi.c
new file mode 100644
index 000000000000..04eceb3a8182
--- /dev/null
+++ b/test/CodeGen/riscv32-abi.c
@@ -0,0 +1,430 @@
+// RUN: %clang_cc1 -triple riscv32 -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple riscv32 -emit-llvm -fforce-enable-int128 %s -o - \
+// RUN: | FileCheck %s -check-prefixes=CHECK,CHECK-FORCEINT128
+
+#include <stddef.h>
+#include <stdint.h>
+
+// CHECK-LABEL: define void @f_void()
+void f_void(void) {}
+
+// Scalar arguments and return values smaller than the word size are extended
+// according to the sign of their type, up to 32 bits
+
+// CHECK-LABEL: define zeroext i1 @f_scalar_0(i1 zeroext %x)
+_Bool f_scalar_0(_Bool x) { return x; }
+
+// CHECK-LABEL: define signext i8 @f_scalar_1(i8 signext %x)
+int8_t f_scalar_1(int8_t x) { return x; }
+
+// CHECK-LABEL: define zeroext i8 @f_scalar_2(i8 zeroext %x)
+uint8_t f_scalar_2(uint8_t x) { return x; }
+
+// CHECK-LABEL: define i32 @f_scalar_3(i32 %x)
+int32_t f_scalar_3(int32_t x) { return x; }
+
+// CHECK-LABEL: define i64 @f_scalar_4(i64 %x)
+int64_t f_scalar_4(int64_t x) { return x; }
+
+#ifdef __SIZEOF_INT128__
+// CHECK-FORCEINT128-LABEL: define i128 @f_scalar_5(i128 %x)
+__int128_t f_scalar_5(__int128_t x) { return x; }
+#endif
+
+// CHECK-LABEL: define float @f_fp_scalar_1(float %x)
+float f_fp_scalar_1(float x) { return x; }
+
+// CHECK-LABEL: define double @f_fp_scalar_2(double %x)
+double f_fp_scalar_2(double x) { return x; }
+
+// Scalars larger than 2*xlen are passed/returned indirect. However, the
+// RISC-V LLVM backend can handle this fine, so the function doesn't need to
+// be modified.
+
+// CHECK-LABEL: define fp128 @f_fp_scalar_3(fp128 %x)
+long double f_fp_scalar_3(long double x) { return x; }
+
+// Empty structs or unions are ignored.
+
+struct empty_s {};
+
+// CHECK-LABEL: define void @f_agg_empty_struct()
+struct empty_s f_agg_empty_struct(struct empty_s x) {
+ return x;
+}
+
+union empty_u {};
+
+// CHECK-LABEL: define void @f_agg_empty_union()
+union empty_u f_agg_empty_union(union empty_u x) {
+ return x;
+}
+
+// Aggregates <= 2*xlen may be passed in registers, so will be coerced to
+// integer arguments. The rules for return are the same.
+
+struct tiny {
+ uint8_t a, b, c, d;
+};
+
+// CHECK-LABEL: define void @f_agg_tiny(i32 %x.coerce)
+void f_agg_tiny(struct tiny x) {
+ x.a += x.b;
+ x.c += x.d;
+}
+
+// CHECK-LABEL: define i32 @f_agg_tiny_ret()
+struct tiny f_agg_tiny_ret() {
+ return (struct tiny){1, 2, 3, 4};
+}
+
+typedef uint8_t v4i8 __attribute__((vector_size(4)));
+typedef int32_t v1i32 __attribute__((vector_size(4)));
+
+// CHECK-LABEL: define void @f_vec_tiny_v4i8(i32 %x.coerce)
+void f_vec_tiny_v4i8(v4i8 x) {
+ x[0] = x[1];
+ x[2] = x[3];
+}
+
+// CHECK-LABEL: define i32 @f_vec_tiny_v4i8_ret()
+v4i8 f_vec_tiny_v4i8_ret() {
+ return (v4i8){1, 2, 3, 4};
+}
+
+// CHECK-LABEL: define void @f_vec_tiny_v1i32(i32 %x.coerce)
+void f_vec_tiny_v1i32(v1i32 x) {
+ x[0] = 114;
+}
+
+// CHECK-LABEL: define i32 @f_vec_tiny_v1i32_ret()
+v1i32 f_vec_tiny_v1i32_ret() {
+ return (v1i32){1};
+}
+
+struct small {
+ int32_t a, *b;
+};
+
+// CHECK-LABEL: define void @f_agg_small([2 x i32] %x.coerce)
+void f_agg_small(struct small x) {
+ x.a += *x.b;
+ x.b = &x.a;
+}
+
+// CHECK-LABEL: define [2 x i32] @f_agg_small_ret()
+struct small f_agg_small_ret() {
+ return (struct small){1, 0};
+}
+
+typedef uint8_t v8i8 __attribute__((vector_size(8)));
+typedef int64_t v1i64 __attribute__((vector_size(8)));
+
+// CHECK-LABEL: define void @f_vec_small_v8i8(i64 %x.coerce)
+void f_vec_small_v8i8(v8i8 x) {
+ x[0] = x[7];
+}
+
+// CHECK-LABEL: define i64 @f_vec_small_v8i8_ret()
+v8i8 f_vec_small_v8i8_ret() {
+ return (v8i8){1, 2, 3, 4, 5, 6, 7, 8};
+}
+
+// CHECK-LABEL: define void @f_vec_small_v1i64(i64 %x.coerce)
+void f_vec_small_v1i64(v1i64 x) {
+ x[0] = 114;
+}
+
+// CHECK-LABEL: define i64 @f_vec_small_v1i64_ret()
+v1i64 f_vec_small_v1i64_ret() {
+ return (v1i64){1};
+}
+
+// Aggregates of 2*xlen size and 2*xlen alignment should be coerced to a
+// single 2*xlen-sized argument, to ensure that alignment can be maintained if
+// passed on the stack.
+
+struct small_aligned {
+ int64_t a;
+};
+
+// CHECK-LABEL: define void @f_agg_small_aligned(i64 %x.coerce)
+void f_agg_small_aligned(struct small_aligned x) {
+ x.a += x.a;
+}
+
+// CHECK-LABEL: define i64 @f_agg_small_aligned_ret(i64 %x.coerce)
+struct small_aligned f_agg_small_aligned_ret(struct small_aligned x) {
+ return (struct small_aligned){10};
+}
+
+// Aggregates greater > 2*xlen will be passed and returned indirectly
+struct large {
+ int32_t a, b, c, d;
+};
+
+// CHECK-LABEL: define void @f_agg_large(%struct.large* %x)
+void f_agg_large(struct large x) {
+ x.a = x.b + x.c + x.d;
+}
+
+// The address where the struct should be written to will be the first
+// argument
+// CHECK-LABEL: define void @f_agg_large_ret(%struct.large* noalias sret %agg.result, i32 %i, i8 signext %j)
+struct large f_agg_large_ret(int32_t i, int8_t j) {
+ return (struct large){1, 2, 3, 4};
+}
+
+typedef unsigned char v16i8 __attribute__((vector_size(16)));
+
+// CHECK-LABEL: define void @f_vec_large_v16i8(<16 x i8>*)
+void f_vec_large_v16i8(v16i8 x) {
+ x[0] = x[7];
+}
+
+// CHECK-LABEL: define void @f_vec_large_v16i8_ret(<16 x i8>* noalias sret %agg.result)
+v16i8 f_vec_large_v16i8_ret() {
+ return (v16i8){1, 2, 3, 4, 5, 6, 7, 8};
+}
+
+// Scalars passed on the stack should have signext/zeroext attributes (they
+// are anyext).
+
+// CHECK-LABEL: define i32 @f_scalar_stack_1(i32 %a.coerce, [2 x i32] %b.coerce, i64 %c.coerce, %struct.large* %d, i8 zeroext %e, i8 signext %f, i8 %g, i8 %h)
+int f_scalar_stack_1(struct tiny a, struct small b, struct small_aligned c,
+ struct large d, uint8_t e, int8_t f, uint8_t g, int8_t h) {
+ return g + h;
+}
+
+// CHECK-LABEL: define i32 @f_scalar_stack_2(i32 %a, i64 %b, float %c, double %d, fp128 %e, i8 zeroext %f, i8 %g, i8 %h)
+int f_scalar_stack_2(int32_t a, int64_t b, float c, double d, long double e,
+ uint8_t f, int8_t g, uint8_t h) {
+ return g + h;
+}
+
+// Ensure that scalars passed on the stack are still determined correctly in
+// the presence of large return values that consume a register due to the need
+// to pass a pointer.
+
+// CHECK-LABEL: define void @f_scalar_stack_3(%struct.large* noalias sret %agg.result, i32 %a, i64 %b, double %c, fp128 %d, i8 zeroext %e, i8 %f, i8 %g)
+struct large f_scalar_stack_3(int32_t a, int64_t b, double c, long double d,
+ uint8_t e, int8_t f, uint8_t g) {
+ return (struct large){a, e, f, g};
+}
+
+// CHECK-LABEL: define fp128 @f_scalar_stack_4(i32 %a, i64 %b, double %c, fp128 %d, i8 zeroext %e, i8 %f, i8 %g)
+long double f_scalar_stack_4(int32_t a, int64_t b, double c, long double d,
+ uint8_t e, int8_t f, uint8_t g) {
+ return d;
+}
+
+// Aggregates and >=XLen scalars passed on the stack should be lowered just as
+// they would be if passed via registers.
+
+// CHECK-LABEL: define void @f_scalar_stack_5(double %a, i64 %b, double %c, i64 %d, i32 %e, i64 %f, float %g, double %h, fp128 %i)
+void f_scalar_stack_5(double a, int64_t b, double c, int64_t d, int e,
+ int64_t f, float g, double h, long double i) {}
+
+// CHECK-LABEL: define void @f_agg_stack(double %a, i64 %b, double %c, i64 %d, i32 %e.coerce, [2 x i32] %f.coerce, i64 %g.coerce, %struct.large* %h)
+void f_agg_stack(double a, int64_t b, double c, int64_t d, struct tiny e,
+ struct small f, struct small_aligned g, struct large h) {}
+
+// Ensure that ABI lowering happens as expected for vararg calls. For RV32
+// with the base integer calling convention there will be no observable
+// differences in the lowered IR for a call with varargs vs without.
+
+int f_va_callee(int, ...);
+
+// CHECK-LABEL: define void @f_va_caller()
+// CHECK: call i32 (i32, ...) @f_va_callee(i32 1, i32 2, i64 3, double 4.000000e+00, double 5.000000e+00, i32 {{%.*}}, [2 x i32] {{%.*}}, i64 {{%.*}}, %struct.large* {{%.*}})
+void f_va_caller() {
+ f_va_callee(1, 2, 3LL, 4.0f, 5.0, (struct tiny){6, 7, 8, 9},
+ (struct small){10, NULL}, (struct small_aligned){11},
+ (struct large){12, 13, 14, 15});
+}
+
+// CHECK-LABEL: define i32 @f_va_1(i8* %fmt, ...) {{.*}} {
+// CHECK: [[FMT_ADDR:%.*]] = alloca i8*, align 4
+// CHECK: [[VA:%.*]] = alloca i8*, align 4
+// CHECK: [[V:%.*]] = alloca i32, align 4
+// CHECK: store i8* %fmt, i8** [[FMT_ADDR]], align 4
+// CHECK: [[VA1:%.*]] = bitcast i8** [[VA]] to i8*
+// CHECK: call void @llvm.va_start(i8* [[VA1]])
+// CHECK: [[ARGP_CUR:%.*]] = load i8*, i8** [[VA]], align 4
+// CHECK: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[ARGP_CUR]], i32 4
+// CHECK: store i8* [[ARGP_NEXT]], i8** [[VA]], align 4
+// CHECK: [[TMP0:%.*]] = bitcast i8* [[ARGP_CUR]] to i32*
+// CHECK: [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 4
+// CHECK: store i32 [[TMP1]], i32* [[V]], align 4
+// CHECK: [[VA2:%.*]] = bitcast i8** [[VA]] to i8*
+// CHECK: call void @llvm.va_end(i8* [[VA2]])
+// CHECK: [[TMP2:%.*]] = load i32, i32* [[V]], align 4
+// CHECK: ret i32 [[TMP2]]
+// CHECK: }
+int f_va_1(char *fmt, ...) {
+ __builtin_va_list va;
+
+ __builtin_va_start(va, fmt);
+ int v = __builtin_va_arg(va, int);
+ __builtin_va_end(va);
+
+ return v;
+}
+
+// An "aligned" register pair (where the first register is even-numbered) is
+// used to pass varargs with 2x xlen alignment and 2x xlen size. Ensure the
+// correct offsets are used.
+
+// CHECK-LABEL: @f_va_2(
+// CHECK: [[FMT_ADDR:%.*]] = alloca i8*, align 4
+// CHECK-NEXT: [[VA:%.*]] = alloca i8*, align 4
+// CHECK-NEXT: [[V:%.*]] = alloca double, align 8
+// CHECK-NEXT: store i8* [[FMT:%.*]], i8** [[FMT_ADDR]], align 4
+// CHECK-NEXT: [[VA1:%.*]] = bitcast i8** [[VA]] to i8*
+// CHECK-NEXT: call void @llvm.va_start(i8* [[VA1]])
+// CHECK-NEXT: [[ARGP_CUR:%.*]] = load i8*, i8** [[VA]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = ptrtoint i8* [[ARGP_CUR]] to i32
+// CHECK-NEXT: [[TMP1:%.*]] = add i32 [[TMP0]], 7
+// CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], -8
+// CHECK-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = inttoptr i32 [[TMP2]] to i8*
+// CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[ARGP_CUR_ALIGNED]], i32 8
+// CHECK-NEXT: store i8* [[ARGP_NEXT]], i8** [[VA]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = bitcast i8* [[ARGP_CUR_ALIGNED]] to double*
+// CHECK-NEXT: [[TMP4:%.*]] = load double, double* [[TMP3]], align 8
+// CHECK-NEXT: store double [[TMP4]], double* [[V]], align 8
+// CHECK-NEXT: [[VA2:%.*]] = bitcast i8** [[VA]] to i8*
+// CHECK-NEXT: call void @llvm.va_end(i8* [[VA2]])
+// CHECK-NEXT: [[TMP5:%.*]] = load double, double* [[V]], align 8
+// CHECK-NEXT: ret double [[TMP5]]
+double f_va_2(char *fmt, ...) {
+ __builtin_va_list va;
+
+ __builtin_va_start(va, fmt);
+ double v = __builtin_va_arg(va, double);
+ __builtin_va_end(va);
+
+ return v;
+}
+
+// Two "aligned" register pairs.
+
+// CHECK-LABEL: @f_va_3(
+// CHECK: [[FMT_ADDR:%.*]] = alloca i8*, align 4
+// CHECK-NEXT: [[VA:%.*]] = alloca i8*, align 4
+// CHECK-NEXT: [[V:%.*]] = alloca double, align 8
+// CHECK-NEXT: [[W:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[X:%.*]] = alloca double, align 8
+// CHECK-NEXT: store i8* [[FMT:%.*]], i8** [[FMT_ADDR]], align 4
+// CHECK-NEXT: [[VA1:%.*]] = bitcast i8** [[VA]] to i8*
+// CHECK-NEXT: call void @llvm.va_start(i8* [[VA1]])
+// CHECK-NEXT: [[ARGP_CUR:%.*]] = load i8*, i8** [[VA]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = ptrtoint i8* [[ARGP_CUR]] to i32
+// CHECK-NEXT: [[TMP1:%.*]] = add i32 [[TMP0]], 7
+// CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], -8
+// CHECK-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = inttoptr i32 [[TMP2]] to i8*
+// CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[ARGP_CUR_ALIGNED]], i32 8
+// CHECK-NEXT: store i8* [[ARGP_NEXT]], i8** [[VA]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = bitcast i8* [[ARGP_CUR_ALIGNED]] to double*
+// CHECK-NEXT: [[TMP4:%.*]] = load double, double* [[TMP3]], align 8
+// CHECK-NEXT: store double [[TMP4]], double* [[V]], align 8
+// CHECK-NEXT: [[ARGP_CUR2:%.*]] = load i8*, i8** [[VA]], align 4
+// CHECK-NEXT: [[ARGP_NEXT3:%.*]] = getelementptr inbounds i8, i8* [[ARGP_CUR2]], i32 4
+// CHECK-NEXT: store i8* [[ARGP_NEXT3]], i8** [[VA]], align 4
+// CHECK-NEXT: [[TMP5:%.*]] = bitcast i8* [[ARGP_CUR2]] to i32*
+// CHECK-NEXT: [[TMP6:%.*]] = load i32, i32* [[TMP5]], align 4
+// CHECK-NEXT: store i32 [[TMP6]], i32* [[W]], align 4
+// CHECK-NEXT: [[ARGP_CUR4:%.*]] = load i8*, i8** [[VA]], align 4
+// CHECK-NEXT: [[TMP7:%.*]] = ptrtoint i8* [[ARGP_CUR4]] to i32
+// CHECK-NEXT: [[TMP8:%.*]] = add i32 [[TMP7]], 7
+// CHECK-NEXT: [[TMP9:%.*]] = and i32 [[TMP8]], -8
+// CHECK-NEXT: [[ARGP_CUR4_ALIGNED:%.*]] = inttoptr i32 [[TMP9]] to i8*
+// CHECK-NEXT: [[ARGP_NEXT5:%.*]] = getelementptr inbounds i8, i8* [[ARGP_CUR4_ALIGNED]], i32 8
+// CHECK-NEXT: store i8* [[ARGP_NEXT5]], i8** [[VA]], align 4
+// CHECK-NEXT: [[TMP10:%.*]] = bitcast i8* [[ARGP_CUR4_ALIGNED]] to double*
+// CHECK-NEXT: [[TMP11:%.*]] = load double, double* [[TMP10]], align 8
+// CHECK-NEXT: store double [[TMP11]], double* [[X]], align 8
+// CHECK-NEXT: [[VA6:%.*]] = bitcast i8** [[VA]] to i8*
+// CHECK-NEXT: call void @llvm.va_end(i8* [[VA6]])
+// CHECK-NEXT: [[TMP12:%.*]] = load double, double* [[V]], align 8
+// CHECK-NEXT: [[TMP13:%.*]] = load double, double* [[X]], align 8
+// CHECK-NEXT: [[ADD:%.*]] = fadd double [[TMP12]], [[TMP13]]
+// CHECK-NEXT: ret double [[ADD]]
+double f_va_3(char *fmt, ...) {
+ __builtin_va_list va;
+
+ __builtin_va_start(va, fmt);
+ double v = __builtin_va_arg(va, double);
+ int w = __builtin_va_arg(va, int);
+ double x = __builtin_va_arg(va, double);
+ __builtin_va_end(va);
+
+ return v + x;
+}
+
+// CHECK-LABEL: define i32 @f_va_4(i8* %fmt, ...) {{.*}} {
+// CHECK: [[FMT_ADDR:%.*]] = alloca i8*, align 4
+// CHECK-NEXT: [[VA:%.*]] = alloca i8*, align 4
+// CHECK-NEXT: [[V:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[LD:%.*]] = alloca fp128, align 16
+// CHECK-NEXT: [[TS:%.*]] = alloca [[STRUCT_TINY:%.*]], align 1
+// CHECK-NEXT: [[SS:%.*]] = alloca [[STRUCT_SMALL:%.*]], align 4
+// CHECK-NEXT: [[LS:%.*]] = alloca [[STRUCT_LARGE:%.*]], align 4
+// CHECK-NEXT: [[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i8* [[FMT:%.*]], i8** [[FMT_ADDR]], align 4
+// CHECK-NEXT: [[VA1:%.*]] = bitcast i8** [[VA]] to i8*
+// CHECK-NEXT: call void @llvm.va_start(i8* [[VA1]])
+// CHECK-NEXT: [[ARGP_CUR:%.*]] = load i8*, i8** [[VA]], align 4
+// CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[ARGP_CUR]], i32 4
+// CHECK-NEXT: store i8* [[ARGP_NEXT]], i8** [[VA]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = bitcast i8* [[ARGP_CUR]] to i32*
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 4
+// CHECK-NEXT: store i32 [[TMP1]], i32* [[V]], align 4
+// CHECK-NEXT: [[ARGP_CUR2:%.*]] = load i8*, i8** [[VA]], align 4
+// CHECK-NEXT: [[ARGP_NEXT3:%.*]] = getelementptr inbounds i8, i8* [[ARGP_CUR2]], i32 4
+// CHECK-NEXT: store i8* [[ARGP_NEXT3]], i8** [[VA]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[ARGP_CUR2]] to fp128**
+// CHECK-NEXT: [[TMP3:%.*]] = load fp128*, fp128** [[TMP2]], align 4
+// CHECK-NEXT: [[TMP4:%.*]] = load fp128, fp128* [[TMP3]], align 16
+// CHECK-NEXT: store fp128 [[TMP4]], fp128* [[LD]], align 16
+// CHECK-NEXT: [[ARGP_CUR4:%.*]] = load i8*, i8** [[VA]], align 4
+// CHECK-NEXT: [[ARGP_NEXT5:%.*]] = getelementptr inbounds i8, i8* [[ARGP_CUR4]], i32 4
+// CHECK-NEXT: store i8* [[ARGP_NEXT5]], i8** [[VA]], align 4
+// CHECK-NEXT: [[TMP5:%.*]] = bitcast i8* [[ARGP_CUR4]] to %struct.tiny*
+// CHECK-NEXT: [[TMP6:%.*]] = bitcast %struct.tiny* [[TS]] to i8*
+// CHECK-NEXT: [[TMP7:%.*]] = bitcast %struct.tiny* [[TMP5]] to i8*
+// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 [[TMP6]], i8* align 4 [[TMP7]], i32 4, i1 false)
+// CHECK-NEXT: [[ARGP_CUR6:%.*]] = load i8*, i8** [[VA]], align 4
+// CHECK-NEXT: [[ARGP_NEXT7:%.*]] = getelementptr inbounds i8, i8* [[ARGP_CUR6]], i32 8
+// CHECK-NEXT: store i8* [[ARGP_NEXT7]], i8** [[VA]], align 4
+// CHECK-NEXT: [[TMP8:%.*]] = bitcast i8* [[ARGP_CUR6]] to %struct.small*
+// CHECK-NEXT: [[TMP9:%.*]] = bitcast %struct.small* [[SS]] to i8*
+// CHECK-NEXT: [[TMP10:%.*]] = bitcast %struct.small* [[TMP8]] to i8*
+// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 [[TMP9]], i8* align 4 [[TMP10]], i32 8, i1 false)
+// CHECK-NEXT: [[ARGP_CUR8:%.*]] = load i8*, i8** [[VA]], align 4
+// CHECK-NEXT: [[ARGP_NEXT9:%.*]] = getelementptr inbounds i8, i8* [[ARGP_CUR8]], i32 4
+// CHECK-NEXT: store i8* [[ARGP_NEXT9]], i8** [[VA]], align 4
+// CHECK-NEXT: [[TMP11:%.*]] = bitcast i8* [[ARGP_CUR8]] to %struct.large**
+// CHECK-NEXT: [[TMP12:%.*]] = load %struct.large*, %struct.large** [[TMP11]], align 4
+// CHECK-NEXT: [[TMP13:%.*]] = bitcast %struct.large* [[LS]] to i8*
+// CHECK-NEXT: [[TMP14:%.*]] = bitcast %struct.large* [[TMP12]] to i8*
+// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 [[TMP13]], i8* align 4 [[TMP14]], i32 16, i1 false)
+// CHECK-NEXT: [[VA10:%.*]] = bitcast i8** [[VA]] to i8*
+// CHECK-NEXT: call void @llvm.va_end(i8* [[VA10]])
+int f_va_4(char *fmt, ...) {
+ __builtin_va_list va;
+
+ __builtin_va_start(va, fmt);
+ int v = __builtin_va_arg(va, int);
+ long double ld = __builtin_va_arg(va, long double);
+ struct tiny ts = __builtin_va_arg(va, struct tiny);
+ struct small ss = __builtin_va_arg(va, struct small);
+ struct large ls = __builtin_va_arg(va, struct large);
+ __builtin_va_end(va);
+
+ int ret = (int)((long double)v + ld);
+ ret = ret + ts.a + ts.b + ts.c + ts.d;
+ ret = ret + ss.a + (int)ss.b;
+ ret = ret + ls.a + ls.b + ls.c + ls.d;
+
+ return ret;
+}
diff --git a/test/CodeGen/riscv64-abi.c b/test/CodeGen/riscv64-abi.c
new file mode 100644
index 000000000000..7a0f065fb4cf
--- /dev/null
+++ b/test/CodeGen/riscv64-abi.c
@@ -0,0 +1,422 @@
+// RUN: %clang_cc1 -triple riscv64 -emit-llvm %s -o - | FileCheck %s
+
+#include <stddef.h>
+#include <stdint.h>
+
+// CHECK-LABEL: define void @f_void()
+void f_void(void) {}
+
+// Scalar arguments and return values smaller than the word size are extended
+// according to the sign of their type, up to 32 bits
+
+// CHECK-LABEL: define zeroext i1 @f_scalar_0(i1 zeroext %x)
+_Bool f_scalar_0(_Bool x) { return x; }
+
+// CHECK-LABEL: define signext i8 @f_scalar_1(i8 signext %x)
+int8_t f_scalar_1(int8_t x) { return x; }
+
+// CHECK-LABEL: define zeroext i8 @f_scalar_2(i8 zeroext %x)
+uint8_t f_scalar_2(uint8_t x) { return x; }
+
+// CHECK-LABEL: define signext i32 @f_scalar_3(i32 signext %x)
+uint32_t f_scalar_3(int32_t x) { return x; }
+
+// CHECK-LABEL: define i64 @f_scalar_4(i64 %x)
+int64_t f_scalar_4(int64_t x) { return x; }
+
+// CHECK-LABEL: define float @f_fp_scalar_1(float %x)
+float f_fp_scalar_1(float x) { return x; }
+
+// CHECK-LABEL: define double @f_fp_scalar_2(double %x)
+double f_fp_scalar_2(double x) { return x; }
+
+// CHECK-LABEL: define fp128 @f_fp_scalar_3(fp128 %x)
+long double f_fp_scalar_3(long double x) { return x; }
+
+// Empty structs or unions are ignored.
+
+struct empty_s {};
+
+// CHECK-LABEL: define void @f_agg_empty_struct()
+struct empty_s f_agg_empty_struct(struct empty_s x) {
+ return x;
+}
+
+union empty_u {};
+
+// CHECK-LABEL: define void @f_agg_empty_union()
+union empty_u f_agg_empty_union(union empty_u x) {
+ return x;
+}
+
+// Aggregates <= 2*xlen may be passed in registers, so will be coerced to
+// integer arguments. The rules for return are the same.
+
+struct tiny {
+ uint16_t a, b, c, d;
+};
+
+// CHECK-LABEL: define void @f_agg_tiny(i64 %x.coerce)
+void f_agg_tiny(struct tiny x) {
+ x.a += x.b;
+ x.c += x.d;
+}
+
+// CHECK-LABEL: define i64 @f_agg_tiny_ret()
+struct tiny f_agg_tiny_ret() {
+ return (struct tiny){1, 2, 3, 4};
+}
+
+typedef uint16_t v4i16 __attribute__((vector_size(8)));
+typedef int64_t v1i64 __attribute__((vector_size(8)));
+
+// CHECK-LABEL: define void @f_vec_tiny_v4i16(i64 %x.coerce)
+void f_vec_tiny_v4i16(v4i16 x) {
+ x[0] = x[1];
+ x[2] = x[3];
+}
+
+// CHECK-LABEL: define i64 @f_vec_tiny_v4i16_ret()
+v4i16 f_vec_tiny_v4i16_ret() {
+ return (v4i16){1, 2, 3, 4};
+}
+
+// CHECK-LABEL: define void @f_vec_tiny_v1i64(i64 %x.coerce)
+void f_vec_tiny_v1i64(v1i64 x) {
+ x[0] = 114;
+}
+
+// CHECK-LABEL: define i64 @f_vec_tiny_v1i64_ret()
+v1i64 f_vec_tiny_v1i64_ret() {
+ return (v1i64){1};
+}
+
+struct small {
+ int64_t a, *b;
+};
+
+// CHECK-LABEL: define void @f_agg_small([2 x i64] %x.coerce)
+void f_agg_small(struct small x) {
+ x.a += *x.b;
+ x.b = &x.a;
+}
+
+// CHECK-LABEL: define [2 x i64] @f_agg_small_ret()
+struct small f_agg_small_ret() {
+ return (struct small){1, 0};
+}
+
+typedef uint16_t v8i16 __attribute__((vector_size(16)));
+typedef __int128_t v1i128 __attribute__((vector_size(16)));
+
+// CHECK-LABEL: define void @f_vec_small_v8i16(i128 %x.coerce)
+void f_vec_small_v8i16(v8i16 x) {
+ x[0] = x[7];
+}
+
+// CHECK-LABEL: define i128 @f_vec_small_v8i16_ret()
+v8i16 f_vec_small_v8i16_ret() {
+ return (v8i16){1, 2, 3, 4, 5, 6, 7, 8};
+}
+
+// CHECK-LABEL: define void @f_vec_small_v1i128(i128 %x.coerce)
+void f_vec_small_v1i128(v1i128 x) {
+ x[0] = 114;
+}
+
+// CHECK-LABEL: define i128 @f_vec_small_v1i128_ret()
+v1i128 f_vec_small_v1i128_ret() {
+ return (v1i128){1};
+}
+
+// Aggregates of 2*xlen size and 2*xlen alignment should be coerced to a
+// single 2*xlen-sized argument, to ensure that alignment can be maintained if
+// passed on the stack.
+
+struct small_aligned {
+ __int128_t a;
+};
+
+// CHECK-LABEL: define void @f_agg_small_aligned(i128 %x.coerce)
+void f_agg_small_aligned(struct small_aligned x) {
+ x.a += x.a;
+}
+
+// CHECK-LABEL: define i128 @f_agg_small_aligned_ret(i128 %x.coerce)
+struct small_aligned f_agg_small_aligned_ret(struct small_aligned x) {
+ return (struct small_aligned){10};
+}
+
+// Aggregates greater > 2*xlen will be passed and returned indirectly
+struct large {
+ int64_t a, b, c, d;
+};
+
+// CHECK-LABEL: define void @f_agg_large(%struct.large* %x)
+void f_agg_large(struct large x) {
+ x.a = x.b + x.c + x.d;
+}
+
+// The address where the struct should be written to will be the first
+// argument
+// CHECK-LABEL: define void @f_agg_large_ret(%struct.large* noalias sret %agg.result, i32 signext %i, i8 signext %j)
+struct large f_agg_large_ret(int32_t i, int8_t j) {
+ return (struct large){1, 2, 3, 4};
+}
+
+typedef unsigned char v32i8 __attribute__((vector_size(32)));
+
+// CHECK-LABEL: define void @f_vec_large_v32i8(<32 x i8>*)
+void f_vec_large_v32i8(v32i8 x) {
+ x[0] = x[7];
+}
+
+// CHECK-LABEL: define void @f_vec_large_v32i8_ret(<32 x i8>* noalias sret %agg.result)
+v32i8 f_vec_large_v32i8_ret() {
+ return (v32i8){1, 2, 3, 4, 5, 6, 7, 8};
+}
+
+// Scalars passed on the stack should have signext/zeroext attributes (they
+// are anyext).
+
+// CHECK-LABEL: define signext i32 @f_scalar_stack_1(i64 %a.coerce, [2 x i64] %b.coerce, i128 %c.coerce, %struct.large* %d, i8 zeroext %e, i8 signext %f, i8 %g, i8 %h)
+int f_scalar_stack_1(struct tiny a, struct small b, struct small_aligned c,
+ struct large d, uint8_t e, int8_t f, uint8_t g, int8_t h) {
+ return g + h;
+}
+
+// CHECK-LABEL: define signext i32 @f_scalar_stack_2(i32 signext %a, i128 %b, float %c, fp128 %d, <32 x i8>*, i8 zeroext %f, i8 %g, i8 %h)
+int f_scalar_stack_2(int32_t a, __int128_t b, float c, long double d, v32i8 e,
+ uint8_t f, int8_t g, uint8_t h) {
+ return g + h;
+}
+
+// Ensure that scalars passed on the stack are still determined correctly in
+// the presence of large return values that consume a register due to the need
+// to pass a pointer.
+
+// CHECK-LABEL: define void @f_scalar_stack_3(%struct.large* noalias sret %agg.result, i32 signext %a, i128 %b, fp128 %c, <32 x i8>*, i8 zeroext %e, i8 %f, i8 %g)
+struct large f_scalar_stack_3(uint32_t a, __int128_t b, long double c, v32i8 d,
+ uint8_t e, int8_t f, uint8_t g) {
+ return (struct large){a, e, f, g};
+}
+
+// Ensure that ABI lowering happens as expected for vararg calls.
+// Specifically, ensure that signext is emitted for varargs that will be
+// passed in registers but not on the stack. Ensure this takes into account
+// the use of "aligned" register pairs for varargs with 2*xlen alignment.
+
+int f_va_callee(int, ...);
+
+// CHECK-LABEL: define void @f_va_caller()
+void f_va_caller() {
+ // CHECK: call signext i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i64 3, double 4.000000e+00, double 5.000000e+00, i64 {{%.*}}, [2 x i64] {{%.*}}, i128 {{%.*}}, %struct.large* {{%.*}})
+ f_va_callee(1, 2, 3LL, 4.0f, 5.0, (struct tiny){6, 7, 8, 9},
+ (struct small){10, NULL}, (struct small_aligned){11},
+ (struct large){12, 13, 14, 15});
+ // CHECK: call signext i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, fp128 0xL00000000000000004001400000000000, i32 signext 6, i32 signext 7, i32 8, i32 9)
+ f_va_callee(1, 2, 3, 4, 5.0L, 6, 7, 8, 9);
+ // CHECK: call signext i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, i128 {{%.*}}, i32 signext 6, i32 signext 7, i32 8, i32 9)
+ f_va_callee(1, 2, 3, 4, (struct small_aligned){5}, 6, 7, 8, 9);
+ // CHECK: call signext i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, [2 x i64] {{%.*}}, i32 signext 6, i32 signext 7, i32 8, i32 9)
+ f_va_callee(1, 2, 3, 4, (struct small){5, NULL}, 6, 7, 8, 9);
+ // CHECK: call signext i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, i32 signext 5, fp128 0xL00000000000000004001800000000000, i32 7, i32 8, i32 9)
+ f_va_callee(1, 2, 3, 4, 5, 6.0L, 7, 8, 9);
+ // CHECK: call signext i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, i32 signext 5, i128 {{%.*}}, i32 7, i32 8, i32 9)
+ f_va_callee(1, 2, 3, 4, 5, (struct small_aligned){6}, 7, 8, 9);
+ // CHECK: call signext i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, i32 signext 5, [2 x i64] {{%.*}}, i32 signext 7, i32 8, i32 9)
+ f_va_callee(1, 2, 3, 4, 5, (struct small){6, NULL}, 7, 8, 9);
+ // CHECK: call signext i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, i32 signext 5, i32 signext 6, fp128 0xL00000000000000004001C00000000000, i32 8, i32 9)
+ f_va_callee(1, 2, 3, 4, 5, 6, 7.0L, 8, 9);
+ // CHECK: call signext i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, i32 signext 5, i32 signext 6, i128 {{%.*}}, i32 8, i32 9)
+ f_va_callee(1, 2, 3, 4, 5, 6, (struct small_aligned){7}, 8, 9);
+ // CHECK: call signext i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, i32 signext 5, i32 signext 6, [2 x i64] {{.*}}, i32 8, i32 9)
+ f_va_callee(1, 2, 3, 4, 5, 6, (struct small){7, NULL}, 8, 9);
+}
+
+// CHECK-LABEL: define signext i32 @f_va_1(i8* %fmt, ...) {{.*}} {
+// CHECK: [[FMT_ADDR:%.*]] = alloca i8*, align 8
+// CHECK: [[VA:%.*]] = alloca i8*, align 8
+// CHECK: [[V:%.*]] = alloca i32, align 4
+// CHECK: store i8* %fmt, i8** [[FMT_ADDR]], align 8
+// CHECK: [[VA1:%.*]] = bitcast i8** [[VA]] to i8*
+// CHECK: call void @llvm.va_start(i8* [[VA1]])
+// CHECK: [[ARGP_CUR:%.*]] = load i8*, i8** [[VA]], align 8
+// CHECK: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[ARGP_CUR]], i64 8
+// CHECK: store i8* [[ARGP_NEXT]], i8** [[VA]], align 8
+// CHECK: [[TMP0:%.*]] = bitcast i8* [[ARGP_CUR]] to i32*
+// CHECK: [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 8
+// CHECK: store i32 [[TMP1]], i32* [[V]], align 4
+// CHECK: [[VA2:%.*]] = bitcast i8** [[VA]] to i8*
+// CHECK: call void @llvm.va_end(i8* [[VA2]])
+// CHECK: [[TMP2:%.*]] = load i32, i32* [[V]], align 4
+// CHECK: ret i32 [[TMP2]]
+// CHECK: }
+int f_va_1(char *fmt, ...) {
+ __builtin_va_list va;
+
+ __builtin_va_start(va, fmt);
+ int v = __builtin_va_arg(va, int);
+ __builtin_va_end(va);
+
+ return v;
+}
+
+// An "aligned" register pair (where the first register is even-numbered) is
+// used to pass varargs with 2x xlen alignment and 2x xlen size. Ensure the
+// correct offsets are used.
+
+// CHECK-LABEL: @f_va_2(
+// CHECK: [[FMT_ADDR:%.*]] = alloca i8*, align 8
+// CHECK-NEXT: [[VA:%.*]] = alloca i8*, align 8
+// CHECK-NEXT: [[V:%.*]] = alloca fp128, align 16
+// CHECK-NEXT: store i8* [[FMT:%.*]], i8** [[FMT_ADDR]], align 8
+// CHECK-NEXT: [[VA1:%.*]] = bitcast i8** [[VA]] to i8*
+// CHECK-NEXT: call void @llvm.va_start(i8* [[VA1]])
+// CHECK-NEXT: [[ARGP_CUR:%.*]] = load i8*, i8** [[VA]], align 8
+// CHECK-NEXT: [[TMP0:%.*]] = ptrtoint i8* [[ARGP_CUR]] to i64
+// CHECK-NEXT: [[TMP1:%.*]] = add i64 [[TMP0]], 15
+// CHECK-NEXT: [[TMP2:%.*]] = and i64 [[TMP1]], -16
+// CHECK-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = inttoptr i64 [[TMP2]] to i8*
+// CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[ARGP_CUR_ALIGNED]], i64 16
+// CHECK-NEXT: store i8* [[ARGP_NEXT]], i8** [[VA]], align 8
+// CHECK-NEXT: [[TMP3:%.*]] = bitcast i8* [[ARGP_CUR_ALIGNED]] to fp128*
+// CHECK-NEXT: [[TMP4:%.*]] = load fp128, fp128* [[TMP3]], align 16
+// CHECK-NEXT: store fp128 [[TMP4]], fp128* [[V]], align 16
+// CHECK-NEXT: [[VA2:%.*]] = bitcast i8** [[VA]] to i8*
+// CHECK-NEXT: call void @llvm.va_end(i8* [[VA2]])
+// CHECK-NEXT: [[TMP5:%.*]] = load fp128, fp128* [[V]], align 16
+// CHECK-NEXT: ret fp128 [[TMP5]]
+long double f_va_2(char *fmt, ...) {
+ __builtin_va_list va;
+
+ __builtin_va_start(va, fmt);
+ long double v = __builtin_va_arg(va, long double);
+ __builtin_va_end(va);
+
+ return v;
+}
+
+// Two "aligned" register pairs.
+
+// CHECK-LABEL: @f_va_3(
+// CHECK: [[FMT_ADDR:%.*]] = alloca i8*, align 8
+// CHECK-NEXT: [[VA:%.*]] = alloca i8*, align 8
+// CHECK-NEXT: [[V:%.*]] = alloca fp128, align 16
+// CHECK-NEXT: [[W:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[X:%.*]] = alloca fp128, align 16
+// CHECK-NEXT: store i8* [[FMT:%.*]], i8** [[FMT_ADDR]], align 8
+// CHECK-NEXT: [[VA1:%.*]] = bitcast i8** [[VA]] to i8*
+// CHECK-NEXT: call void @llvm.va_start(i8* [[VA1]])
+// CHECK-NEXT: [[ARGP_CUR:%.*]] = load i8*, i8** [[VA]], align 8
+// CHECK-NEXT: [[TMP0:%.*]] = ptrtoint i8* [[ARGP_CUR]] to i64
+// CHECK-NEXT: [[TMP1:%.*]] = add i64 [[TMP0]], 15
+// CHECK-NEXT: [[TMP2:%.*]] = and i64 [[TMP1]], -16
+// CHECK-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = inttoptr i64 [[TMP2]] to i8*
+// CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[ARGP_CUR_ALIGNED]], i64 16
+// CHECK-NEXT: store i8* [[ARGP_NEXT]], i8** [[VA]], align 8
+// CHECK-NEXT: [[TMP3:%.*]] = bitcast i8* [[ARGP_CUR_ALIGNED]] to fp128*
+// CHECK-NEXT: [[TMP4:%.*]] = load fp128, fp128* [[TMP3]], align 16
+// CHECK-NEXT: store fp128 [[TMP4]], fp128* [[V]], align 16
+// CHECK-NEXT: [[ARGP_CUR2:%.*]] = load i8*, i8** [[VA]], align 8
+// CHECK-NEXT: [[ARGP_NEXT3:%.*]] = getelementptr inbounds i8, i8* [[ARGP_CUR2]], i64 8
+// CHECK-NEXT: store i8* [[ARGP_NEXT3]], i8** [[VA]], align 8
+// CHECK-NEXT: [[TMP5:%.*]] = bitcast i8* [[ARGP_CUR2]] to i32*
+// CHECK-NEXT: [[TMP6:%.*]] = load i32, i32* [[TMP5]], align 8
+// CHECK-NEXT: store i32 [[TMP6]], i32* [[W]], align 4
+// CHECK-NEXT: [[ARGP_CUR4:%.*]] = load i8*, i8** [[VA]], align 8
+// CHECK-NEXT: [[TMP7:%.*]] = ptrtoint i8* [[ARGP_CUR4]] to i64
+// CHECK-NEXT: [[TMP8:%.*]] = add i64 [[TMP7]], 15
+// CHECK-NEXT: [[TMP9:%.*]] = and i64 [[TMP8]], -16
+// CHECK-NEXT: [[ARGP_CUR4_ALIGNED:%.*]] = inttoptr i64 [[TMP9]] to i8*
+// CHECK-NEXT: [[ARGP_NEXT5:%.*]] = getelementptr inbounds i8, i8* [[ARGP_CUR4_ALIGNED]], i64 16
+// CHECK-NEXT: store i8* [[ARGP_NEXT5]], i8** [[VA]], align 8
+// CHECK-NEXT: [[TMP10:%.*]] = bitcast i8* [[ARGP_CUR4_ALIGNED]] to fp128*
+// CHECK-NEXT: [[TMP11:%.*]] = load fp128, fp128* [[TMP10]], align 16
+// CHECK-NEXT: store fp128 [[TMP11]], fp128* [[X]], align 16
+// CHECK-NEXT: [[VA6:%.*]] = bitcast i8** [[VA]] to i8*
+// CHECK-NEXT: call void @llvm.va_end(i8* [[VA6]])
+// CHECK-NEXT: [[TMP12:%.*]] = load fp128, fp128* [[V]], align 16
+// CHECK-NEXT: [[TMP13:%.*]] = load fp128, fp128* [[X]], align 16
+// CHECK-NEXT: [[ADD:%.*]] = fadd fp128 [[TMP12]], [[TMP13]]
+// CHECK-NEXT: ret fp128 [[ADD]]
+long double f_va_3(char *fmt, ...) {
+ __builtin_va_list va;
+
+ __builtin_va_start(va, fmt);
+ long double v = __builtin_va_arg(va, long double);
+ int w = __builtin_va_arg(va, int);
+ long double x = __builtin_va_arg(va, long double);
+ __builtin_va_end(va);
+
+ return v + x;
+}
+
+// CHECK-LABEL: @f_va_4(
+// CHECK: [[FMT_ADDR:%.*]] = alloca i8*, align 8
+// CHECK-NEXT: [[VA:%.*]] = alloca i8*, align 8
+// CHECK-NEXT: [[V:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[TS:%.*]] = alloca [[STRUCT_TINY:%.*]], align 2
+// CHECK-NEXT: [[SS:%.*]] = alloca [[STRUCT_SMALL:%.*]], align 8
+// CHECK-NEXT: [[LS:%.*]] = alloca [[STRUCT_LARGE:%.*]], align 8
+// CHECK-NEXT: [[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i8* [[FMT:%.*]], i8** [[FMT_ADDR]], align 8
+// CHECK-NEXT: [[VA1:%.*]] = bitcast i8** [[VA]] to i8*
+// CHECK-NEXT: call void @llvm.va_start(i8* [[VA1]])
+// CHECK-NEXT: [[ARGP_CUR:%.*]] = load i8*, i8** [[VA]], align 8
+// CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[ARGP_CUR]], i64 8
+// CHECK-NEXT: store i8* [[ARGP_NEXT]], i8** [[VA]], align 8
+// CHECK-NEXT: [[TMP0:%.*]] = bitcast i8* [[ARGP_CUR]] to i32*
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 8
+// CHECK-NEXT: store i32 [[TMP1]], i32* [[V]], align 4
+// CHECK-NEXT: [[ARGP_CUR2:%.*]] = load i8*, i8** [[VA]], align 8
+// CHECK-NEXT: [[ARGP_NEXT3:%.*]] = getelementptr inbounds i8, i8* [[ARGP_CUR2]], i64 8
+// CHECK-NEXT: store i8* [[ARGP_NEXT3]], i8** [[VA]], align 8
+// CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[ARGP_CUR2]] to %struct.tiny*
+// CHECK-NEXT: [[TMP3:%.*]] = bitcast %struct.tiny* [[TS]] to i8*
+// CHECK-NEXT: [[TMP4:%.*]] = bitcast %struct.tiny* [[TMP2]] to i8*
+// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 2 [[TMP3]], i8* align 8 [[TMP4]], i64 8, i1 false)
+// CHECK-NEXT: [[ARGP_CUR4:%.*]] = load i8*, i8** [[VA]], align 8
+// CHECK-NEXT: [[ARGP_NEXT5:%.*]] = getelementptr inbounds i8, i8* [[ARGP_CUR4]], i64 16
+// CHECK-NEXT: store i8* [[ARGP_NEXT5]], i8** [[VA]], align 8
+// CHECK-NEXT: [[TMP5:%.*]] = bitcast i8* [[ARGP_CUR4]] to %struct.small*
+// CHECK-NEXT: [[TMP6:%.*]] = bitcast %struct.small* [[SS]] to i8*
+// CHECK-NEXT: [[TMP7:%.*]] = bitcast %struct.small* [[TMP5]] to i8*
+// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP6]], i8* align 8 [[TMP7]], i64 16, i1 false)
+// CHECK-NEXT: [[ARGP_CUR6:%.*]] = load i8*, i8** [[VA]], align 8
+// CHECK-NEXT: [[ARGP_NEXT7:%.*]] = getelementptr inbounds i8, i8* [[ARGP_CUR6]], i64 8
+// CHECK-NEXT: store i8* [[ARGP_NEXT7]], i8** [[VA]], align 8
+// CHECK-NEXT: [[TMP8:%.*]] = bitcast i8* [[ARGP_CUR6]] to %struct.large**
+// CHECK-NEXT: [[TMP9:%.*]] = load %struct.large*, %struct.large** [[TMP8]], align 8
+// CHECK-NEXT: [[TMP10:%.*]] = bitcast %struct.large* [[LS]] to i8*
+// CHECK-NEXT: [[TMP11:%.*]] = bitcast %struct.large* [[TMP9]] to i8*
+// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP10]], i8* align 8 [[TMP11]], i64 32, i1 false)
+// CHECK-NEXT: [[VA8:%.*]] = bitcast i8** [[VA]] to i8*
+// CHECK-NEXT: call void @llvm.va_end(i8* [[VA8]])
+// CHECK-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_TINY]], %struct.tiny* [[TS]], i32 0, i32 0
+// CHECK-NEXT: [[TMP12:%.*]] = load i16, i16* [[A]], align 2
+// CHECK-NEXT: [[CONV:%.*]] = zext i16 [[TMP12]] to i64
+// CHECK-NEXT: [[A9:%.*]] = getelementptr inbounds [[STRUCT_SMALL]], %struct.small* [[SS]], i32 0, i32 0
+// CHECK-NEXT: [[TMP13:%.*]] = load i64, i64* [[A9]], align 8
+// CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[CONV]], [[TMP13]]
+// CHECK-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_LARGE]], %struct.large* [[LS]], i32 0, i32 2
+// CHECK-NEXT: [[TMP14:%.*]] = load i64, i64* [[C]], align 8
+// CHECK-NEXT: [[ADD10:%.*]] = add nsw i64 [[ADD]], [[TMP14]]
+// CHECK-NEXT: [[CONV11:%.*]] = trunc i64 [[ADD10]] to i32
+// CHECK-NEXT: store i32 [[CONV11]], i32* [[RET]], align 4
+// CHECK-NEXT: [[TMP15:%.*]] = load i32, i32* [[RET]], align 4
+// CHECK-NEXT: ret i32 [[TMP15]]
+int f_va_4(char *fmt, ...) {
+ __builtin_va_list va;
+
+ __builtin_va_start(va, fmt);
+ int v = __builtin_va_arg(va, int);
+ struct tiny ts = __builtin_va_arg(va, struct tiny);
+ struct small ss = __builtin_va_arg(va, struct small);
+ struct large ls = __builtin_va_arg(va, struct large);
+ __builtin_va_end(va);
+
+ int ret = ts.a + ss.a + ls.c;
+
+ return ret;
+}
diff --git a/test/CodeGen/shadowcallstack-attr.c b/test/CodeGen/shadowcallstack-attr.c
new file mode 100644
index 000000000000..45e710d87562
--- /dev/null
+++ b/test/CodeGen/shadowcallstack-attr.c
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple x86_64-linux-unknown -emit-llvm -o - %s -fsanitize=shadow-call-stack | FileCheck -check-prefix=UNBLACKLISTED %s
+
+// RUN: %clang_cc1 -D ATTR -triple x86_64-linux-unknown -emit-llvm -o - %s -fsanitize=shadow-call-stack | FileCheck -check-prefix=BLACKLISTED %s
+
+// RUN: echo -e "[shadow-call-stack]\nfun:foo" > %t
+// RUN: %clang_cc1 -fsanitize-blacklist=%t -triple x86_64-linux-unknown -emit-llvm -o - %s -fsanitize=shadow-call-stack | FileCheck -check-prefix=BLACKLISTED %s
+
+#ifdef ATTR
+__attribute__((no_sanitize("shadow-call-stack")))
+#endif
+int foo(int *a) { return *a; }
+
+// CHECK: define i32 @foo(i32* %a)
+
+// BLACKLISTED-NOT: attributes {{.*}}shadowcallstack{{.*}}
+// UNBLACKLISTED: attributes {{.*}}shadowcallstack{{.*}}
diff --git a/test/CodeGen/sparc-vaarg.c b/test/CodeGen/sparc-vaarg.c
index 3e4dd7c2c3f2..920b9a18b065 100644
--- a/test/CodeGen/sparc-vaarg.c
+++ b/test/CodeGen/sparc-vaarg.c
@@ -19,7 +19,7 @@ struct Foo dest;
// CHECK-LABEL: define void @get_struct
// CHECK: [[RESULT:%[a-z_0-9]+]] = va_arg {{.*}}, %struct.Foo*{{$}}
// CHECK: [[RESULT2:%[a-z_0-9]+]] = bitcast {{.*}} [[RESULT]] to i8*
-// CHECK: call void @llvm.memcpy{{.*}}@dest{{.*}}, i8* [[RESULT2]]
+// CHECK: call void @llvm.memcpy{{.*}}@dest{{.*}}, i8* align {{[0-9]+}} [[RESULT2]]
void get_struct(va_list *args) {
dest = va_arg(*args, struct Foo);
}
diff --git a/test/CodeGen/sparcv8-inline-asm.c b/test/CodeGen/sparcv8-inline-asm.c
index 711a2a0afbb0..8befe4556c84 100644
--- a/test/CodeGen/sparcv8-inline-asm.c
+++ b/test/CodeGen/sparcv8-inline-asm.c
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -triple sparc-unknown-unknown -emit-llvm %s -o - | FileCheck %s
// CHECK: define float @fabsf(float %a)
-// CHECK: %{{.*}} = call float asm sideeffect "fabss $1, $0;", "=e,f"(float %{{.*}}) #1
+// CHECK: %{{.*}} = call float asm sideeffect "fabss $1, $0;", "=e,f"(float %{{.*}})
float fabsf(float a) {
float res;
__asm __volatile__("fabss %1, %0;"
@@ -9,3 +9,34 @@ float fabsf(float a) {
: /* reg in */ "f"(a));
return res;
}
+
+void test_gcc_registers(void) {
+ register unsigned int regO6 asm("o6") = 0;
+ register unsigned int regSP asm("sp") = 1;
+ register unsigned int reg14 asm("r14") = 2;
+ register unsigned int regI6 asm("i6") = 3;
+ register unsigned int regFP asm("fp") = 4;
+ register unsigned int reg30 asm("r30") = 5;
+
+ register float fF20 asm("f20") = 8.0;
+ register double dF20 asm("f20") = 11.0;
+ register long double qF20 asm("f20") = 14.0;
+
+ // Test remapping register names in register ... asm("rN") statments.
+
+ // CHECK: call void asm sideeffect "add $0,$1,$2", "{r14},{r14},{r14}"
+ asm volatile("add %0,%1,%2" : : "r" (regO6), "r" (regSP), "r" (reg14));
+
+ // CHECK: call void asm sideeffect "add $0,$1,$2", "{r30},{r30},{r30}"
+ asm volatile("add %0,%1,%2" : : "r" (regI6), "r" (regFP), "r" (reg30));
+
+ // CHECK: call void asm sideeffect "fadds $0,$1,$2", "{f20},{f20},{f20}"
+ asm volatile("fadds %0,%1,%2" : : "f" (fF20), "f" (fF20), "f"(fF20));
+
+ // CHECK: call void asm sideeffect "faddd $0,$1,$2", "{f20},{f20},{f20}"
+ asm volatile("faddd %0,%1,%2" : : "f" (dF20), "f" (dF20), "f"(dF20));
+
+ // CHECK: call void asm sideeffect "faddq $0,$1,$2", "{f20},{f20},{f20}"
+ asm volatile("faddq %0,%1,%2" : : "f" (qF20), "f" (qF20), "f"(qF20));
+
+}
diff --git a/test/CodeGen/sparcv9-inline-asm.c b/test/CodeGen/sparcv9-inline-asm.c
new file mode 100644
index 000000000000..3a7ef0ea86e7
--- /dev/null
+++ b/test/CodeGen/sparcv9-inline-asm.c
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -triple sparcv9-unknown-unknown -emit-llvm %s -o - | FileCheck %s
+
+void test_gcc_registers(void) {
+ register unsigned int regO6 asm("o6") = 0;
+ register unsigned int regSP asm("sp") = 1;
+ register unsigned int reg14 asm("r14") = 2;
+ register unsigned int regI6 asm("i6") = 3;
+ register unsigned int regFP asm("fp") = 4;
+ register unsigned int reg30 asm("r30") = 5;
+
+ register float fF20 asm("f20") = 8.0;
+ register double dF40 asm("f40") = 11.0;
+ register long double qF40 asm("f40") = 14.0;
+
+ // Test remapping register names in register ... asm("rN") statments.
+
+ // CHECK: call void asm sideeffect "add $0,$1,$2", "{r14},{r14},{r14}"
+ asm volatile("add %0,%1,%2" : : "r" (regO6), "r" (regSP), "r" (reg14));
+
+ // CHECK: call void asm sideeffect "add $0,$1,$2", "{r30},{r30},{r30}"
+ asm volatile("add %0,%1,%2" : : "r" (regI6), "r" (regFP), "r" (reg30));
+
+ // CHECK: call void asm sideeffect "fadds $0,$1,$2", "{f20},{f20},{f20}"
+ asm volatile("fadds %0,%1,%2" : : "f" (fF20), "f" (fF20), "f"(fF20));
+
+ // CHECK: call void asm sideeffect "faddd $0,$1,$2", "{f40},{f40},{f40}"
+ asm volatile("faddd %0,%1,%2" : : "f" (dF40), "f" (dF40), "f"(dF40));
+
+ // CHECK: call void asm sideeffect "faddq $0,$1,$2", "{f40},{f40},{f40}"
+ asm volatile("faddq %0,%1,%2" : : "f" (qF40), "f" (qF40), "f"(qF40));
+
+}
diff --git a/test/CodeGen/spir-half-type.cpp b/test/CodeGen/spir-half-type.cpp
new file mode 100644
index 000000000000..b60931fea6ed
--- /dev/null
+++ b/test/CodeGen/spir-half-type.cpp
@@ -0,0 +1,146 @@
+// RUN: %clang_cc1 -O0 -triple spir -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -O0 -triple spir64 -emit-llvm %s -o - | FileCheck %s
+
+// This file tests that using the _Float16 type with the spir target will not
+// use the llvm intrinsics but instead will use the half arithmetic
+// instructions directly.
+
+// Previously attempting to use a constant _Float16 with a comparison
+// instruction when the target is spir or spir64 lead to an assert being hit.
+bool fcmp_const() {
+ _Float16 a = 0.0f16;
+ const _Float16 b = 1.0f16;
+
+ // CHECK-NOT: llvm.convert.to.fp16
+ // CHECK-NOT: llvm.convert.from.fp16
+
+ // CHECK: [[REG1:%.*]] = load half, half* %a, align 2
+ // CHECK-NEXT: fcmp olt half [[REG1]], 0xH3C00
+
+ // CHECK: [[REG2:%.*]] = load half, half* %a, align 2
+ // CHECK-NEXT: fcmp olt half [[REG2]], 0xH4000
+
+ // CHECK: [[REG3:%.*]] = load half, half* %a, align 2
+ // CHECK-NEXT: fcmp ogt half [[REG3]], 0xH3C00
+
+ // CHECK: [[REG4:%.*]] = load half, half* %a, align 2
+ // CHECK-NEXT: fcmp ogt half [[REG4]], 0xH4200
+
+ // CHECK: [[REG5:%.*]] = load half, half* %a, align 2
+ // CHECK-NEXT: fcmp oeq half [[REG5]], 0xH3C00
+
+ // CHECK: [[REG7:%.*]] = load half, half* %a, align 2
+ // CHECK-NEXT: fcmp oeq half [[REG7]], 0xH4400
+
+ // CHECK: [[REG8:%.*]] = load half, half* %a, align 2
+ // CHECK-NEXT: fcmp une half [[REG8]], 0xH3C00
+
+ // CHECK: [[REG9:%.*]] = load half, half* %a, align 2
+ // CHECK-NEXT: fcmp une half [[REG9]], 0xH4500
+
+ // CHECK: [[REG10:%.*]] = load half, half* %a, align 2
+ // CHECK-NEXT: fcmp ole half [[REG10]], 0xH3C00
+
+ // CHECK: [[REG11:%.*]] = load half, half* %a, align 2
+ // CHECK-NEXT: fcmp ole half [[REG11]], 0xH4600
+
+ // CHECK: [[REG12:%.*]] = load half, half* %a, align 2
+ // CHECK-NEXT: fcmp oge half [[REG12]], 0xH3C00
+
+ // CHECK: [[REG13:%.*]] = load half, half* %a, align 2
+ // CHECK-NEXT: fcmp oge half [[REG13]], 0xH4700
+ return a < b || a < 2.0f16 || a > b || a > 3.0f16 || a == b || a == 4.0f16 ||
+ a != b || a != 5.0f16 || a <= b || a <= 6.0f16 || a >= b ||
+ a >= 7.0f16;
+}
+
+bool fcmp() {
+ _Float16 a = 0.0f16;
+ _Float16 b = 1.0f16;
+
+ // CHECK-NOT: llvm.convert.to.fp16
+ // CHECK-NOT: llvm.convert.from.fp16
+ // CHECK: [[REG1:%.*]] = load half, half* %a, align 2
+ // CHECK-NEXT: [[REG2:%.*]] = load half, half* %b, align 2
+ // CHECK-NEXT: fcmp olt half [[REG1]], [[REG2]]
+
+ // CHECK: [[REG3:%.*]] = load half, half* %a, align 2
+ // CHECK-NEXT: [[REG4:%.*]] = load half, half* %b, align 2
+ // CHECK-NEXT: fcmp ogt half [[REG3]], [[REG4]]
+
+ // CHECK: [[REG5:%.*]] = load half, half* %a, align 2
+ // CHECK-NEXT: [[REG6:%.*]] = load half, half* %b, align 2
+ // CHECK-NEXT: fcmp oeq half [[REG5]], [[REG6]]
+
+ // CHECK: [[REG7:%.*]] = load half, half* %a, align 2
+ // CHECK-NEXT: [[REG8:%.*]] = load half, half* %b, align 2
+ // CHECK-NEXT: fcmp une half [[REG7]], [[REG8]]
+
+ // CHECK: [[REG7:%.*]] = load half, half* %a, align 2
+ // CHECK-NEXT: [[REG8:%.*]] = load half, half* %b, align 2
+ // CHECK-NEXT: fcmp ole half [[REG7]], [[REG8]]
+
+ // CHECK: [[REG7:%.*]] = load half, half* %a, align 2
+ // CHECK-NEXT: [[REG8:%.*]] = load half, half* %b, align 2
+ // CHECK-NEXT: fcmp oge half [[REG7]], [[REG8]]
+ return a < b || a > b || a == b || a != b || a <= b || a >= b;
+}
+
+_Float16 fadd() {
+ _Float16 a = 1.0f16;
+ const _Float16 b = 2.0f16;
+
+ // CHECK-NOT: llvm.convert.to.fp16
+ // CHECK-NOT: llvm.convert.from.fp16
+
+ // CHECK: [[REG1:%.*]] = load half, half* %a, align 2
+ // CHECK-NEXT: [[REG2:%.*]] = fadd half [[REG1]], 0xH4000
+ // CHECK-NEXT: [[REG3:%.*]] = fadd half [[REG2]], 0xH4200
+ // CHECK-NEXT: ret half [[REG3]]
+ return a + b + 3.0f16;
+}
+
+_Float16 fsub() {
+ _Float16 a = 1.0f16;
+ const _Float16 b = 2.0f16;
+
+ // CHECK-NOT: llvm.convert.to.fp16
+ // CHECK-NOT: llvm.convert.from.fp16
+
+ // CHECK: [[REG1:%.*]] = load half, half* %a, align 2
+ // CHECK-NEXT: [[REG2:%.*]] = fsub half [[REG1]], 0xH4000
+ // CHECK-NEXT: [[REG3:%.*]] = fsub half [[REG2]], 0xH4200
+ // CHECK-NEXT: ret half [[REG3]]
+ return a - b - 3.0f16;
+}
+
+// CHECK: define spir_func half @_Z4fmulDF16_(half %arg)
+_Float16 fmul(_Float16 arg) {
+ _Float16 a = 1.0f16;
+ const _Float16 b = 2.0f16;
+
+ // CHECK-NOT: llvm.convert.to.fp16
+ // CHECK-NOT: llvm.convert.from.fp16
+
+ // CHECK: [[REG1:%.*]] = load half, half* %a, align 2
+ // CHECK-NEXT: [[REG2:%.*]] = load half, half* %arg.addr, align 2
+ // CHECK-NEXT: [[REG3:%.*]] = fmul half [[REG1]], [[REG2]]
+ // CHECK-NEXT: [[REG4:%.*]] = fmul half [[REG3]], 0xH4000
+ // CHECK-NEXT: [[REG5:%.*]] = fmul half [[REG4]], 0xH4200
+ // CHECK-NEXT: ret half [[REG5]]
+ return a * arg * b * 3.0f16;
+}
+
+_Float16 fdiv() {
+ _Float16 a = 1.0f16;
+ const _Float16 b = 2.0f16;
+
+ // CHECK-NOT: llvm.convert.to.fp16
+ // CHECK-NOT: llvm.convert.from.fp16
+
+ // CHECK: [[REG1:%.*]] = load half, half* %a, align 2
+ // CHECK-NEXT: [[REG2:%.*]] = fdiv half [[REG1]], 0xH4000
+ // CHECK-NEXT: [[REG3:%.*]] = fdiv half [[REG2]], 0xH4200
+ // CHECK-NEXT: ret half [[REG3]]
+ return a / b / 3.0f16;
+}
diff --git a/test/CodeGen/split-debug-filename.c b/test/CodeGen/split-debug-filename.c
index 9ca7b0f3287a..99f89a741450 100644
--- a/test/CodeGen/split-debug-filename.c
+++ b/test/CodeGen/split-debug-filename.c
@@ -1,5 +1,9 @@
+// REQUIRES: x86-registered-target
// RUN: %clang_cc1 -debug-info-kind=limited -split-dwarf-file foo.dwo -S -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -debug-info-kind=limited -enable-split-dwarf -split-dwarf-file foo.dwo -S -emit-llvm -o - %s | FileCheck --check-prefix=VANILLA %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -debug-info-kind=limited -enable-split-dwarf -split-dwarf-file %t.dwo -emit-obj -o - %s | llvm-objdump -section-headers - | FileCheck --check-prefix=O %s
+// RUN: llvm-objdump -section-headers %t.dwo | FileCheck --check-prefix=DWO %s
+
int main (void) {
return 0;
}
@@ -10,3 +14,6 @@ int main (void) {
// Testing to ensure that the dwo name is not output into the compile unit if
// it's for vanilla split-dwarf rather than split-dwarf for implicit modules.
// VANILLA-NOT: splitDebugFilename
+
+// O-NOT: .dwo
+// DWO: .dwo
diff --git a/test/CodeGen/split-stacks.c b/test/CodeGen/split-stacks.c
index bf4cf0f026aa..d9ff1f955d2e 100644
--- a/test/CodeGen/split-stacks.c
+++ b/test/CodeGen/split-stacks.c
@@ -14,13 +14,13 @@ int main() {
return foo();
}
-// CHECK-SEGSTK: define i32 @foo() [[SS:#[0-9]+]] {
-// CHECK-SEGSTK: define i32 @nosplit() [[NSS:#[0-9]+]] {
-// CHECK-SEGSTK: define i32 @main() [[SS]] {
+// CHECK-SEGSTK: define dso_local i32 @foo() [[SS:#[0-9]+]] {
+// CHECK-SEGSTK: define dso_local i32 @nosplit() [[NSS:#[0-9]+]] {
+// CHECK-SEGSTK: define dso_local i32 @main() [[SS]] {
// CHECK-SEGSTK-NOT: [[NSS]] = { {{.*}} "split-stack" {{.*}} }
// CHECK-SEGSTK: [[SS]] = { {{.*}} "split-stack" {{.*}} }
// CHECK-SEGSTK-NOT: [[NSS]] = { {{.*}} "split-stack" {{.*}} }
-// CHECK-NOSEGSTK: define i32 @foo() #0 {
-// CHECK-NOSEGSTK: define i32 @main() #0 {
+// CHECK-NOSEGSTK: define dso_local i32 @foo() #0 {
+// CHECK-NOSEGSTK: define dso_local i32 @main() #0 {
// CHECK-NOSEGSTK-NOT: #0 = { {{.*}} "split-stack" {{.*}} }
diff --git a/test/CodeGen/sse-builtins.c b/test/CodeGen/sse-builtins.c
index 28b4f2cae1f0..e9801487be0d 100644
--- a/test/CodeGen/sse-builtins.c
+++ b/test/CodeGen/sse-builtins.c
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +sse -emit-llvm -o - -Wall -Werror | FileCheck %s
-#include <x86intrin.h>
+#include <immintrin.h>
// NOTE: This should match the tests in llvm/test/CodeGen/X86/sse-intrinsics-fast-isel.ll
@@ -450,7 +450,8 @@ __m128 test_mm_min_ss(__m128 A, __m128 B) {
__m128 test_mm_move_ss(__m128 A, __m128 B) {
// CHECK-LABEL: test_mm_move_ss
- // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x i32> <i32 4, i32 1, i32 2, i32 3>
+ // CHECK: extractelement <4 x float> %{{.*}}, i32 0
+ // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i32 0
return _mm_move_ss(A, B);
}
@@ -508,14 +509,6 @@ __m128 test_mm_rcp_ps(__m128 x) {
__m128 test_mm_rcp_ss(__m128 x) {
// CHECK-LABEL: test_mm_rcp_ss
// CHECK: call <4 x float> @llvm.x86.sse.rcp.ss(<4 x float> {{.*}})
- // CHECK: extractelement <4 x float> {{.*}}, i32 0
- // CHECK: insertelement <4 x float> undef, float {{.*}}, i32 0
- // CHECK: extractelement <4 x float> {{.*}}, i32 1
- // CHECK: insertelement <4 x float> {{.*}}, float {{.*}}, i32 1
- // CHECK: extractelement <4 x float> {{.*}}, i32 2
- // CHECK: insertelement <4 x float> {{.*}}, float {{.*}}, i32 2
- // CHECK: extractelement <4 x float> {{.*}}, i32 3
- // CHECK: insertelement <4 x float> {{.*}}, float {{.*}}, i32 3
return _mm_rcp_ss(x);
}
@@ -528,14 +521,6 @@ __m128 test_mm_rsqrt_ps(__m128 x) {
__m128 test_mm_rsqrt_ss(__m128 x) {
// CHECK-LABEL: test_mm_rsqrt_ss
// CHECK: call <4 x float> @llvm.x86.sse.rsqrt.ss(<4 x float> {{.*}})
- // CHECK: extractelement <4 x float> {{.*}}, i32 0
- // CHECK: insertelement <4 x float> undef, float {{.*}}, i32 0
- // CHECK: extractelement <4 x float> {{.*}}, i32 1
- // CHECK: insertelement <4 x float> {{.*}}, float {{.*}}, i32 1
- // CHECK: extractelement <4 x float> {{.*}}, i32 2
- // CHECK: insertelement <4 x float> {{.*}}, float {{.*}}, i32 2
- // CHECK: extractelement <4 x float> {{.*}}, i32 3
- // CHECK: insertelement <4 x float> {{.*}}, float {{.*}}, i32 3
return _mm_rsqrt_ss(x);
}
@@ -655,21 +640,15 @@ __m128 test_mm_shuffle_ps(__m128 A, __m128 B) {
__m128 test_mm_sqrt_ps(__m128 x) {
// CHECK-LABEL: test_mm_sqrt_ps
- // CHECK: call <4 x float> @llvm.x86.sse.sqrt.ps(<4 x float> {{.*}})
+ // CHECK: call <4 x float> @llvm.sqrt.v4f32(<4 x float> {{.*}})
return _mm_sqrt_ps(x);
}
__m128 test_sqrt_ss(__m128 x) {
// CHECK: define {{.*}} @test_sqrt_ss
- // CHECK: call <4 x float> @llvm.x86.sse.sqrt.ss
- // CHECK: extractelement <4 x float> {{.*}}, i32 0
- // CHECK: insertelement <4 x float> undef, float {{.*}}, i32 0
- // CHECK: extractelement <4 x float> {{.*}}, i32 1
- // CHECK: insertelement <4 x float> {{.*}}, float {{.*}}, i32 1
- // CHECK: extractelement <4 x float> {{.*}}, i32 2
- // CHECK: insertelement <4 x float> {{.*}}, float {{.*}}, i32 2
- // CHECK: extractelement <4 x float> {{.*}}, i32 3
- // CHECK: insertelement <4 x float> {{.*}}, float {{.*}}, i32 3
+ // CHECK: extractelement <4 x float> {{.*}}, i64 0
+ // CHECK: call float @llvm.sqrt.f32(float {{.*}})
+ // CHECK: insertelement <4 x float> {{.*}}, float {{.*}}, i64 0
return _mm_sqrt_ss(x);
}
diff --git a/test/CodeGen/sse2-builtins.c b/test/CodeGen/sse2-builtins.c
index c2279cb88109..fe7f7ccf83ee 100644
--- a/test/CodeGen/sse2-builtins.c
+++ b/test/CodeGen/sse2-builtins.c
@@ -2,7 +2,7 @@
// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +sse2 -fno-signed-char -emit-llvm -o - -Wall -Werror | FileCheck %s
-#include <x86intrin.h>
+#include <immintrin.h>
// NOTE: This should match the tests in llvm/test/CodeGen/X86/sse2-intrinsics-fast-isel.ll
@@ -121,13 +121,13 @@ __m128i test_mm_avg_epu16(__m128i A, __m128i B) {
__m128i test_mm_bslli_si128(__m128i A) {
// CHECK-LABEL: test_mm_bslli_si128
- // CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i32> <i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26>
+ // CHECK: shufflevector <16 x i8> zeroinitializer, <16 x i8> %{{.*}}, <16 x i32> <i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26>
return _mm_bslli_si128(A, 5);
}
__m128i test_mm_bsrli_si128(__m128i A) {
// CHECK-LABEL: test_mm_bsrli_si128
- // CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20>
+ // CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> zeroinitializer, <16 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20>
return _mm_bsrli_si128(A, 5);
}
@@ -468,7 +468,7 @@ __m128d test_mm_cvtepi32_pd(__m128i A) {
__m128 test_mm_cvtepi32_ps(__m128i A) {
// CHECK-LABEL: test_mm_cvtepi32_ps
- // CHECK: call <4 x float> @llvm.x86.sse2.cvtdq2ps(<4 x i32> %{{.*}})
+ // CHECK: sitofp <4 x i32> %{{.*}} to <4 x float>
return _mm_cvtepi32_ps(A);
}
@@ -613,17 +613,15 @@ __m128d test_mm_div_sd(__m128d A, __m128d B) {
// Lowering to pextrw requires optimization.
int test_mm_extract_epi16(__m128i A) {
// CHECK-LABEL: test_mm_extract_epi16
- // CHECK: [[x:%.*]] = and i32 %{{.*}}, 7
- // CHECK: extractelement <8 x i16> %{{.*}}, i32 [[x]]
+ // CHECK: extractelement <8 x i16> %{{.*}}, {{i32|i64}} 1
// CHECK: zext i16 %{{.*}} to i32
- return _mm_extract_epi16(A, 9);
+ return _mm_extract_epi16(A, 1);
}
__m128i test_mm_insert_epi16(__m128i A, int B) {
// CHECK-LABEL: test_mm_insert_epi16
- // CHECK: [[x:%.*]] = and i32 %{{.*}}, 7
- // CHECK: insertelement <8 x i16> %{{.*}}, i32 [[x]]
- return _mm_insert_epi16(A, B, 8);
+ // CHECK: insertelement <8 x i16> %{{.*}}, {{i32|i64}} 0
+ return _mm_insert_epi16(A, B, 0);
}
void test_mm_lfence() {
@@ -796,9 +794,7 @@ __m128i test_mm_move_epi64(__m128i A) {
__m128d test_mm_move_sd(__m128d A, __m128d B) {
// CHECK-LABEL: test_mm_move_sd
// CHECK: extractelement <2 x double> %{{.*}}, i32 0
- // CHECK: insertelement <2 x double> undef, double %{{.*}}, i32 0
- // CHECK: extractelement <2 x double> %{{.*}}, i32 1
- // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 1
+ // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 0
return _mm_move_sd(A, B);
}
@@ -816,7 +812,9 @@ int test_mm_movemask_pd(__m128d A) {
__m128i test_mm_mul_epu32(__m128i A, __m128i B) {
// CHECK-LABEL: test_mm_mul_epu32
- // CHECK: call <2 x i64> @llvm.x86.sse2.pmulu.dq(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK: and <2 x i64> %{{.*}}, <i64 4294967295, i64 4294967295>
+ // CHECK: and <2 x i64> %{{.*}}, <i64 4294967295, i64 4294967295>
+ // CHECK: mul <2 x i64> %{{.*}}, %{{.*}}
return _mm_mul_epu32(A, B);
}
@@ -1116,7 +1114,7 @@ __m128i test_mm_setzero_si128() {
__m128i test_mm_shuffle_epi32(__m128i A) {
// CHECK-LABEL: test_mm_shuffle_epi32
- // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> zeroinitializer
+ // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> undef, <4 x i32> zeroinitializer
return _mm_shuffle_epi32(A, 0);
}
@@ -1128,13 +1126,13 @@ __m128d test_mm_shuffle_pd(__m128d A, __m128d B) {
__m128i test_mm_shufflehi_epi16(__m128i A) {
// CHECK-LABEL: test_mm_shufflehi_epi16
- // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 4, i32 4, i32 4>
+ // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 4, i32 4, i32 4>
return _mm_shufflehi_epi16(A, 0);
}
__m128i test_mm_shufflelo_epi16(__m128i A) {
// CHECK-LABEL: test_mm_shufflelo_epi16
- // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i32> <i32 0, i32 0, i32 0, i32 0, i32 4, i32 5, i32 6, i32 7>
+ // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> undef, <8 x i32> <i32 0, i32 0, i32 0, i32 0, i32 4, i32 5, i32 6, i32 7>
return _mm_shufflelo_epi16(A, 0);
}
@@ -1176,29 +1174,27 @@ __m128i test_mm_slli_epi64(__m128i A) {
__m128i test_mm_slli_si128(__m128i A) {
// CHECK-LABEL: test_mm_slli_si128
- // CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i32> <i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26>
+ // CHECK: shufflevector <16 x i8> zeroinitializer, <16 x i8> %{{.*}}, <16 x i32> <i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26>
return _mm_slli_si128(A, 5);
}
__m128i test_mm_slli_si128_2(__m128i A) {
// CHECK-LABEL: test_mm_slli_si128_2
- // CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+ // CHECK: ret <2 x i64> zeroinitializer
return _mm_slli_si128(A, 17);
}
__m128d test_mm_sqrt_pd(__m128d A) {
// CHECK-LABEL: test_mm_sqrt_pd
- // CHECK: call <2 x double> @llvm.x86.sse2.sqrt.pd(<2 x double> %{{.*}})
+ // CHECK: call <2 x double> @llvm.sqrt.v2f64(<2 x double> %{{.*}})
return _mm_sqrt_pd(A);
}
__m128d test_mm_sqrt_sd(__m128d A, __m128d B) {
// CHECK-LABEL: test_mm_sqrt_sd
- // CHECK: call <2 x double> @llvm.x86.sse2.sqrt.sd(<2 x double> %{{.*}})
- // CHECK: extractelement <2 x double> %{{.*}}, i32 0
- // CHECK: insertelement <2 x double> undef, double %{{.*}}, i32 0
- // CHECK: extractelement <2 x double> %{{.*}}, i32 1
- // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 1
+ // CHECK: extractelement <2 x double> %{{.*}}, i64 0
+ // CHECK: call double @llvm.sqrt.f64(double {{.*}})
+ // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0
return _mm_sqrt_sd(A, B);
}
@@ -1264,13 +1260,13 @@ __m128i test_mm_srli_epi64(__m128i A) {
__m128i test_mm_srli_si128(__m128i A) {
// CHECK-LABEL: test_mm_srli_si128
- // CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20>
+ // CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> zeroinitializer, <16 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20>
return _mm_srli_si128(A, 5);
}
__m128i test_mm_srli_si128_2(__m128i A) {
// CHECK-LABEL: test_mm_srli_si128_2
- // CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i32> <i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
+ // ret <2 x i64> zeroinitializer
return _mm_srli_si128(A, 17);
}
diff --git a/test/CodeGen/sse3-builtins.c b/test/CodeGen/sse3-builtins.c
index 46a7bbbb91e2..cf3e9526c377 100644
--- a/test/CodeGen/sse3-builtins.c
+++ b/test/CodeGen/sse3-builtins.c
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +sse3 -emit-llvm -o - -Wall -Werror | FileCheck %s
-#include <x86intrin.h>
+#include <immintrin.h>
// NOTE: This should match the tests in llvm/test/CodeGen/X86/sse3-intrinsics-fast-isel.ll
diff --git a/test/CodeGen/sse41-builtins.c b/test/CodeGen/sse41-builtins.c
index b48b73ec18d9..2d9da07330dc 100644
--- a/test/CodeGen/sse41-builtins.c
+++ b/test/CodeGen/sse41-builtins.c
@@ -2,7 +2,7 @@
// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +sse4.1 -fno-signed-char -emit-llvm -o - -Wall -Werror | FileCheck %s
-#include <x86intrin.h>
+#include <immintrin.h>
// NOTE: This should match the tests in llvm/test/CodeGen/X86/sse41-intrinsics-fast-isel.ll
@@ -171,26 +171,26 @@ __m128 test_mm_dp_ps(__m128 x, __m128 y) {
int test_mm_extract_epi8(__m128i x) {
// CHECK-LABEL: test_mm_extract_epi8
- // CHECK: extractelement <16 x i8> %{{.*}}, i32 1
+ // CHECK: extractelement <16 x i8> %{{.*}}, {{i32|i64}} 1
// CHECK: zext i8 %{{.*}} to i32
return _mm_extract_epi8(x, 1);
}
int test_mm_extract_epi32(__m128i x) {
// CHECK-LABEL: test_mm_extract_epi32
- // CHECK: extractelement <4 x i32> %{{.*}}, i32 1
+ // CHECK: extractelement <4 x i32> %{{.*}}, {{i32|i64}} 1
return _mm_extract_epi32(x, 1);
}
long long test_mm_extract_epi64(__m128i x) {
// CHECK-LABEL: test_mm_extract_epi64
- // CHECK: extractelement <2 x i64> %{{.*}}, i32 1
+ // CHECK: extractelement <2 x i64> %{{.*}}, {{i32|i64}} 1
return _mm_extract_epi64(x, 1);
}
int test_mm_extract_ps(__m128 x) {
// CHECK-LABEL: test_mm_extract_ps
- // CHECK: extractelement <4 x float> %{{.*}}, i32 1
+ // CHECK: extractelement <4 x float> %{{.*}}, {{i32|i64}} 1
return _mm_extract_ps(x, 1);
}
@@ -220,20 +220,20 @@ __m128 test_mm_floor_ss(__m128 x, __m128 y) {
__m128i test_mm_insert_epi8(__m128i x, char b) {
// CHECK-LABEL: test_mm_insert_epi8
- // CHECK: insertelement <16 x i8> %{{.*}}, i8 %{{.*}}, i32 0
- return _mm_insert_epi8(x, b, 16);
+ // CHECK: insertelement <16 x i8> %{{.*}}, i8 %{{.*}}, {{i32|i64}} 1
+ return _mm_insert_epi8(x, b, 1);
}
__m128i test_mm_insert_epi32(__m128i x, int b) {
// CHECK-LABEL: test_mm_insert_epi32
- // CHECK: insertelement <4 x i32> %{{.*}}, i32 %{{.*}}, i32 0
- return _mm_insert_epi32(x, b, 4);
+ // CHECK: insertelement <4 x i32> %{{.*}}, i32 %{{.*}}, {{i32|i64}} 1
+ return _mm_insert_epi32(x, b, 1);
}
__m128i test_mm_insert_epi64(__m128i x, long long b) {
// CHECK-LABEL: test_mm_insert_epi64
- // CHECK: insertelement <2 x i64> %{{.*}}, i64 %{{.*}}, i32 0
- return _mm_insert_epi64(x, b, 2);
+ // CHECK: insertelement <2 x i64> %{{.*}}, i64 %{{.*}}, {{i32|i64}} 1
+ return _mm_insert_epi64(x, b, 1);
}
__m128 test_mm_insert_ps(__m128 x, __m128 y) {
@@ -312,7 +312,11 @@ __m128i test_mm_mpsadbw_epu8(__m128i x, __m128i y) {
__m128i test_mm_mul_epi32(__m128i x, __m128i y) {
// CHECK-LABEL: test_mm_mul_epi32
- // CHECK: call <2 x i64> @llvm.x86.sse41.pmuldq(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK: shl <2 x i64> %{{.*}}, <i64 32, i64 32>
+ // CHECK: ashr <2 x i64> %{{.*}}, <i64 32, i64 32>
+ // CHECK: shl <2 x i64> %{{.*}}, <i64 32, i64 32>
+ // CHECK: ashr <2 x i64> %{{.*}}, <i64 32, i64 32>
+ // CHECK: mul <2 x i64> %{{.*}}, %{{.*}}
return _mm_mul_epi32(x, y);
}
diff --git a/test/CodeGen/sse42-builtins.c b/test/CodeGen/sse42-builtins.c
index 523db1a3416e..d94d12452df7 100644
--- a/test/CodeGen/sse42-builtins.c
+++ b/test/CodeGen/sse42-builtins.c
@@ -2,7 +2,7 @@
// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +sse4.2 -fno-signed-char -emit-llvm -o - -Wall -Werror | FileCheck %s
-#include <x86intrin.h>
+#include <immintrin.h>
// NOTE: This should match the tests in llvm/test/CodeGen/X86/sse42-intrinsics-fast-isel.ll
diff --git a/test/CodeGen/ssse3-builtins.c b/test/CodeGen/ssse3-builtins.c
index 4fd22aa79b46..4e6d401772be 100644
--- a/test/CodeGen/ssse3-builtins.c
+++ b/test/CodeGen/ssse3-builtins.c
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +ssse3 -emit-llvm -o - -Wall -Werror | FileCheck %s
-#include <x86intrin.h>
+#include <immintrin.h>
// NOTE: This should match the tests in llvm/test/CodeGen/X86/ssse3-intrinsics-fast-isel.ll
diff --git a/test/CodeGen/stack-arg-probe.c b/test/CodeGen/stack-arg-probe.c
new file mode 100644
index 000000000000..d806db61c369
--- /dev/null
+++ b/test/CodeGen/stack-arg-probe.c
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 %s -triple=i686-windows-msvc -emit-llvm -o - -mno-stack-arg-probe | FileCheck %s -check-prefix=NO-STACKPROBE
+// RUN: %clang_cc1 %s -triple=i686-windows-msvc -emit-llvm -o - | FileCheck %s -check-prefix=STACKPROBE
+
+// NO-STACKPROBE: attributes #{{[0-9]+}} = {{{.*}} "no-stack-arg-probe"
+// STACKPROBE-NOT: attributes #{{[0-9]+}} = {{{.*}} "no-stack-arg-probe"
+
+void test1() {
+}
diff --git a/test/CodeGen/stack-protector.c b/test/CodeGen/stack-protector.c
index 7a45a2f4acf6..5037a3e0d6fe 100644
--- a/test/CodeGen/stack-protector.c
+++ b/test/CodeGen/stack-protector.c
@@ -22,6 +22,14 @@ void test1(const char *msg) {
printf("%s\n", a);
}
+// DEF: define {{.*}}void @test2(i8* %msg) #[[B:.*]] {
+__attribute__((no_stack_protector))
+void test2(const char *msg) {
+ char a[strlen(msg) + 1];
+ strcpy(a, msg);
+ printf("%s\n", a);
+}
+
// NOSSP-NOT: attributes #[[A]] = {{.*}} ssp
// SSP: attributes #[[A]] = {{.*}} ssp{{ }}
// SSPSTRONG: attributes #[[A]] = {{.*}} sspstrong
@@ -33,3 +41,15 @@ void test1(const char *msg) {
// SAFESTACK-SSP: attributes #[[A]] = {{.*}} safestack ssp{{ }}
// SAFESTACK-SSPSTRONG: attributes #[[A]] = {{.*}} safestack sspstrong
// SAFESTACK-SSPREQ: attributes #[[A]] = {{.*}} safestack sspreq
+
+// NOSSP-NOT: attributes #[[B]] = {{.*}} ssp
+// SSP-NOT: attributes #[[B]] = {{.*}} ssp{{ }}
+// SSPSTRONG-NOT: attributes #[[B]] = {{.*}} sspstrong
+// SSPREQ-NOT: attributes #[[B]] = {{.*}} sspreq
+
+// SAFESTACK-SSP: attributes #[[B]] = {{.*}} safestack
+// SAFESTACK-SSP-NOT: attributes #[[B]] = {{.*}} safestack ssp{{ }}
+// SAFESTACK-SSPSTRONG: attributes #[[B]] = {{.*}} safestack
+// SAFESTACK-SSPSTRONG-NOT: attributes #[[B]] = {{.*}} safestack sspstrong
+// SAFESTACK-SSPREQ: attributes #[[B]] = {{.*}} safestack
+// SAFESTACK-SSPREQ-NOT: attributes #[[B]] = {{.*}} safestack sspreq
diff --git a/test/CodeGen/stack-size-section.c b/test/CodeGen/stack-size-section.c
new file mode 100644
index 000000000000..504a42de1341
--- /dev/null
+++ b/test/CodeGen/stack-size-section.c
@@ -0,0 +1,9 @@
+// REQUIRES: x86-registered-target
+
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -S -o - | FileCheck %s --check-prefix=CHECK-ABSENT
+// CHECK-ABSENT-NOT: section .stack_sizes
+
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fstack-size-section %s -S -o - | FileCheck %s --check-prefix=CHECK-PRESENT
+// CHECK-PRESENT: section .stack_sizes
+
+int foo() { return 42; }
diff --git a/test/CodeGen/string-literal-short-wstring.c b/test/CodeGen/string-literal-short-wstring.c
index fb1fe0cad0a8..8894b8823e91 100644
--- a/test/CodeGen/string-literal-short-wstring.c
+++ b/test/CodeGen/string-literal-short-wstring.c
@@ -12,12 +12,12 @@ int main() {
char b[10] = "\u1120\u0220\U00102030";
// ITANIUM: private unnamed_addr constant [3 x i16] [i16 65, i16 66, i16 0]
- // MSABI: linkonce_odr unnamed_addr constant [3 x i16] [i16 65, i16 66, i16 0]
+ // MSABI: linkonce_odr dso_local unnamed_addr constant [3 x i16] [i16 65, i16 66, i16 0]
const wchar_t *foo = L"AB";
// This should convert to utf16.
// ITANIUM: private unnamed_addr constant [5 x i16] [i16 4384, i16 544, i16 -9272, i16 -9168, i16 0]
- // MSABI: linkonce_odr unnamed_addr constant [5 x i16] [i16 4384, i16 544, i16 -9272, i16 -9168, i16 0]
+ // MSABI: linkonce_odr dso_local unnamed_addr constant [5 x i16] [i16 4384, i16 544, i16 -9272, i16 -9168, i16 0]
const wchar_t *bar = L"\u1120\u0220\U00102030";
diff --git a/test/CodeGen/target-data.c b/test/CodeGen/target-data.c
index 3869afec7858..2b990910920c 100644
--- a/test/CodeGen/target-data.c
+++ b/test/CodeGen/target-data.c
@@ -124,20 +124,20 @@
// RUN: %clang_cc1 -triple r600-unknown -o - -emit-llvm %s | \
// RUN: FileCheck %s -check-prefix=R600
-// R600: target datalayout = "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"
+// R600: target datalayout = "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-S32-A5"
// RUN: %clang_cc1 -triple r600-unknown -target-cpu cayman -o - -emit-llvm %s \
// RUN: | FileCheck %s -check-prefix=R600D
-// R600D: target datalayout = "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"
+// R600D: target datalayout = "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-S32-A5"
// RUN: %clang_cc1 -triple amdgcn-unknown -target-cpu hawaii -o - -emit-llvm %s \
// RUN: | FileCheck %s -check-prefix=R600SI
-// R600SI: target datalayout = "e-p:32:32-p1:64:64-p2:64:64-p3:32:32-p4:64:64-p5:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64"
+// R600SI: target datalayout = "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-S32-A5"
// Test default -target-cpu
// RUN: %clang_cc1 -triple amdgcn-unknown -o - -emit-llvm %s \
// RUN: | FileCheck %s -check-prefix=R600SIDefault
-// R600SIDefault: target datalayout = "e-p:32:32-p1:64:64-p2:64:64-p3:32:32-p4:64:64-p5:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64"
+// R600SIDefault: target datalayout = "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-S32-A5"
// RUN: %clang_cc1 -triple arm64-unknown -o - -emit-llvm %s | \
// RUN: FileCheck %s -check-prefix=AARCH64
diff --git a/test/CodeGen/target-features-error-2.c b/test/CodeGen/target-features-error-2.c
index 683d9ab99ef6..60586fb57f1c 100644
--- a/test/CodeGen/target-features-error-2.c
+++ b/test/CodeGen/target-features-error-2.c
@@ -1,38 +1,46 @@
-// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -S -verify -o - -D NEED_SSE42
// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -S -verify -o - -D NEED_AVX_1
// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -S -verify -o - -D NEED_AVX_2
-// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -S -verify -o - -D NEED_AVX_3
-// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -S -verify -o - -D NEED_AVX_4
+// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -S -verify -o - -D NEED_AVX512f
+// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -target-feature +movdir64b -S -verify -o - -D NEED_MOVDIRI
+// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -target-feature +avx512vnni -target-feature +movdiri -S -verify -o - -D NEED_CLWB
#define __MM_MALLOC_H
#include <x86intrin.h>
-#if NEED_SSE42
+#if NEED_AVX_1
int baz(__m256i a) {
- return _mm256_extract_epi32(a, 3); // expected-error {{always_inline function '_mm256_extract_epi32' requires target feature 'sse4.2', but would be inlined into function 'baz' that is compiled without support for 'sse4.2'}}
+ return _mm256_extract_epi32(a, 3); // expected-error {{'__builtin_ia32_vec_ext_v8si' needs target feature avx}}
}
#endif
-#if NEED_AVX_1
+#if NEED_AVX_2
__m128 need_avx(__m128 a, __m128 b) {
return _mm_cmp_ps(a, b, 0); // expected-error {{'__builtin_ia32_cmpps' needs target feature avx}}
}
#endif
-#if NEED_AVX_2
-__m128 need_avx(__m128 a, __m128 b) {
- return _mm_cmp_ss(a, b, 0); // expected-error {{'__builtin_ia32_cmpss' needs target feature avx}}
+#if NEED_AVX512f
+unsigned short need_avx512f(unsigned short a, unsigned short b) {
+ return __builtin_ia32_korhi(a, b); // expected-error {{'__builtin_ia32_korhi' needs target feature avx512f}}
}
#endif
-#if NEED_AVX_3
-__m128d need_avx(__m128d a, __m128d b) {
- return _mm_cmp_pd(a, b, 0); // expected-error {{'__builtin_ia32_cmppd' needs target feature avx}}
+#if NEED_MOVDIRI
+void need_movdiri(unsigned int *a, unsigned int b) {
+ __builtin_ia32_directstore_u32(a, b); // expected-error {{'__builtin_ia32_directstore_u32' needs target feature movdiri}}
}
#endif
-#if NEED_AVX_4
-__m128d need_avx(__m128d a, __m128d b) {
- return _mm_cmp_sd(a, b, 0); // expected-error {{'__builtin_ia32_cmpsd' needs target feature avx}}
+#if NEED_CLWB
+static __inline__ void
+ __attribute__((__always_inline__, __nodebug__, __target__("avx512vnni,clwb,movdiri,movdir64b")))
+ func(unsigned int *a, unsigned int b)
+{
+ __builtin_ia32_directstore_u32(a, b);
+}
+
+void need_clwb(unsigned int *a, unsigned int b) {
+ func(a, b); // expected-error {{always_inline function 'func' requires target feature 'clwb', but would be inlined into function 'need_clwb' that is compiled without support for 'clwb'}}
+
}
#endif
diff --git a/test/CodeGen/target-features-error.c b/test/CodeGen/target-features-error.c
index 518f6e6189ed..a55163a95d43 100644
--- a/test/CodeGen/target-features-error.c
+++ b/test/CodeGen/target-features-error.c
@@ -3,6 +3,5 @@ int __attribute__((target("avx"), always_inline)) foo(int a) {
return a + 4;
}
int bar() {
- return foo(4); // expected-error {{always_inline function 'foo' requires target feature 'sse4.2', but would be inlined into function 'bar' that is compiled without support for 'sse4.2'}}
+ return foo(4); // expected-error {{always_inline function 'foo' requires target feature 'avx', but would be inlined into function 'bar' that is compiled without support for 'avx'}}
}
-
diff --git a/test/CodeGen/tbaa-base.cpp b/test/CodeGen/tbaa-base.cpp
new file mode 100644
index 000000000000..bcd4732df8f8
--- /dev/null
+++ b/test/CodeGen/tbaa-base.cpp
@@ -0,0 +1,58 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -O1 %s -emit-llvm -o - | FileCheck %s -check-prefixes=CHECK,OLD-PATH
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -O1 %s -emit-llvm -new-struct-path-tbaa -o - | FileCheck %s -check-prefixes=CHECK,NEW-PATH
+//
+// Test generating of TBAA metadata for accesses to members of base classes.
+
+struct A {
+ int x, y, z;
+};
+
+struct B : A {
+ int i;
+};
+
+struct C {
+ int i;
+ B b;
+ int j;
+};
+
+int f1(B *b) {
+// CHECK-LABEL: _Z2f1P1B
+// CHECK: load i32, {{.*}}, !tbaa [[TAG_A_y:!.*]]
+ return b->y;
+}
+
+int f2(C *c) {
+// CHECK-LABEL: _Z2f2P1C
+// CHECK: load i32, {{.*}}, !tbaa [[TAG_A_y]]
+ return (&(c->b))->y;
+}
+
+struct D : virtual A
+{};
+
+struct E {
+ D d;
+};
+
+int f3(D *d) {
+// CHECK-LABEL: _Z2f3P1D
+// CHECK: load i32, {{.*}}, !tbaa [[TAG_A_y]]
+ return d->y;
+}
+
+int f4(E *e) {
+// CHECK-LABEL: _Z2f4P1E
+// CHECK: load i32, {{.*}}, !tbaa [[TAG_A_y]]
+ return (&(e->d))->y;
+}
+
+// OLD-PATH-DAG: [[TYPE_char:!.*]] = !{!"omnipotent char", {{.*}}, i64 0}
+// OLD-PATH-DAG: [[TYPE_int:!.*]] = !{!"int", [[TYPE_char]], i64 0}
+// OLD-PATH-DAG: [[TYPE_A:!.*]] = !{!"_ZTS1A", [[TYPE_int]], i64 0, [[TYPE_int]], i64 4, [[TYPE_int]], i64 8}
+// OLD-PATH-DAG: [[TAG_A_y]] = !{[[TYPE_A]], [[TYPE_int]], i64 4}
+// NEW-PATH-DAG: [[TYPE_char:!.*]] = !{{{.*}}, i64 1, !"omnipotent char"}
+// NEW-PATH-DAG: [[TYPE_int:!.*]] = !{[[TYPE_char]], i64 4, !"int"}
+// NEW-PATH-DAG: [[TYPE_A:!.*]] = !{[[TYPE_char]], i64 12, !"_ZTS1A", [[TYPE_int]], i64 0, i64 4, [[TYPE_int]], i64 4, i64 4, [[TYPE_int]], i64 8, i64 4}
+// NEW-PATH-DAG: [[TAG_A_y]] = !{[[TYPE_A]], [[TYPE_int]], i64 4, i64 4}
diff --git a/test/CodeGen/tbaa-cast.cpp b/test/CodeGen/tbaa-cast.cpp
index 2b9e31086664..fee2f30bccc1 100644
--- a/test/CodeGen/tbaa-cast.cpp
+++ b/test/CodeGen/tbaa-cast.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-linux -O1 -disable-llvm-passes %s \
-// RUN: -emit-llvm -o - | FileCheck %s
+// RUN: -emit-llvm -o - | FileCheck %s -check-prefixes=CHECK,OLD-PATH
+// RUN: %clang_cc1 -triple x86_64-linux -O1 -disable-llvm-passes %s \
+// RUN: -emit-llvm -new-struct-path-tbaa -o - | FileCheck %s -check-prefixes=CHECK,NEW-PATH
//
// Check that we generate correct TBAA information for lvalues constructed
// with use of casts.
@@ -18,6 +20,9 @@ void foo(S *p) {
((V*)p->bytes)->n = 5;
}
-// CHECK-DAG: [[TAG_V_n]] = !{[[TYPE_V:!.*]], [[TYPE_int:!.*]], i64 0}
-// CHECK-DAG: [[TYPE_V]] = !{!"_ZTS1V", !{{.*}}, i64 0}
-// CHECK-DAG: [[TYPE_int]] = !{!"int", !{{.*}}, i64 0}
+// OLD-PATH-DAG: [[TAG_V_n]] = !{[[TYPE_V:!.*]], [[TYPE_int:!.*]], i64 0}
+// OLD-PATH-DAG: [[TYPE_V]] = !{!"_ZTS1V", !{{.*}}, i64 0}
+// OLD-PATH-DAG: [[TYPE_int]] = !{!"int", !{{.*}}, i64 0}
+// NEW-PATH-DAG: [[TAG_V_n]] = !{[[TYPE_V:!.*]], [[TYPE_int:!.*]], i64 0, i64 4}
+// NEW-PATH-DAG: [[TYPE_V]] = !{[[TYPE_char:!.*]], i64 4, !"_ZTS1V", [[TYPE_int]], i64 0, i64 4}
+// NEW-PATH-DAG: [[TYPE_int]] = !{[[TYPE_char]], i64 4, !"int"}
diff --git a/test/CodeGen/tbaa-class.cpp b/test/CodeGen/tbaa-class.cpp
index 9b614a19e8b0..b7d2a865451a 100644
--- a/test/CodeGen/tbaa-class.cpp
+++ b/test/CodeGen/tbaa-class.cpp
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin -O1 -no-struct-path-tbaa -disable-llvm-passes %s -emit-llvm -o - | FileCheck %s
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -O1 -disable-llvm-passes %s -emit-llvm -o - | FileCheck %s -check-prefix=PATH
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -O1 -disable-llvm-passes %s -emit-llvm -o - | FileCheck %s -check-prefixes=PATH,OLD-PATH
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -O1 -disable-llvm-passes %s -emit-llvm -new-struct-path-tbaa -o - | FileCheck %s -check-prefixes=PATH,NEW-PATH
// Test TBAA metadata generated by front-end.
typedef unsigned char uint8_t;
@@ -205,24 +206,46 @@ uint32_t g12(StructC *C, StructD *D, uint64_t count) {
// CHECK: [[TAG_i16]] = !{[[TYPE_i16:!.*]], [[TYPE_i16]], i64 0}
// CHECK: [[TYPE_i16]] = !{!"short", [[TYPE_char]],
-// PATH: [[TYPE_CHAR:!.*]] = !{!"omnipotent char", !
-// PATH: [[TAG_i32]] = !{[[TYPE_INT:!.*]], [[TYPE_INT]], i64 0}
-// PATH: [[TYPE_INT]] = !{!"int", [[TYPE_CHAR]]
-// PATH: [[TAG_A_f32]] = !{[[TYPE_A:!.*]], [[TYPE_INT]], i64 4}
-// PATH: [[TYPE_A]] = !{!"_ZTS7StructA", [[TYPE_SHORT:!.*]], i64 0, [[TYPE_INT]], i64 4, [[TYPE_SHORT]], i64 8, [[TYPE_INT]], i64 12}
-// PATH: [[TYPE_SHORT:!.*]] = !{!"short", [[TYPE_CHAR]]
-// PATH: [[TAG_A_f16]] = !{[[TYPE_A]], [[TYPE_SHORT]], i64 0}
-// PATH: [[TAG_B_a_f32]] = !{[[TYPE_B:!.*]], [[TYPE_INT]], i64 8}
-// PATH: [[TYPE_B]] = !{!"_ZTS7StructB", [[TYPE_SHORT]], i64 0, [[TYPE_A]], i64 4, [[TYPE_INT]], i64 20}
-// PATH: [[TAG_B_a_f16]] = !{[[TYPE_B]], [[TYPE_SHORT]], i64 4}
-// PATH: [[TAG_B_f32]] = !{[[TYPE_B]], [[TYPE_INT]], i64 20}
-// PATH: [[TAG_B_a_f32_2]] = !{[[TYPE_B]], [[TYPE_INT]], i64 16}
-// PATH: [[TAG_S_f32]] = !{[[TYPE_S:!.*]], [[TYPE_INT]], i64 4}
-// PATH: [[TYPE_S]] = !{!"_ZTS7StructS", [[TYPE_SHORT]], i64 0, [[TYPE_INT]], i64 4}
-// PATH: [[TAG_S_f16]] = !{[[TYPE_S]], [[TYPE_SHORT]], i64 0}
-// PATH: [[TAG_S2_f32_2]] = !{[[TYPE_S2:!.*]], [[TYPE_INT]], i64 12}
-// PATH: [[TYPE_S2]] = !{!"_ZTS8StructS2", [[TYPE_SHORT]], i64 8, [[TYPE_INT]], i64 12}
-// PATH: [[TAG_C_b_a_f32]] = !{[[TYPE_C:!.*]], [[TYPE_INT]], i64 12}
-// PATH: [[TYPE_C]] = !{!"_ZTS7StructC", [[TYPE_SHORT]], i64 0, [[TYPE_B]], i64 4, [[TYPE_INT]], i64 28}
-// PATH: [[TAG_D_b_a_f32]] = !{[[TYPE_D:!.*]], [[TYPE_INT]], i64 12}
-// PATH: [[TYPE_D]] = !{!"_ZTS7StructD", [[TYPE_SHORT]], i64 0, [[TYPE_B]], i64 4, [[TYPE_INT]], i64 28, [[TYPE_CHAR]], i64 32}
+// OLD-PATH: [[TYPE_CHAR:!.*]] = !{!"omnipotent char", !
+// OLD-PATH: [[TAG_i32]] = !{[[TYPE_INT:!.*]], [[TYPE_INT]], i64 0}
+// OLD-PATH: [[TYPE_INT]] = !{!"int", [[TYPE_CHAR]]
+// OLD-PATH: [[TAG_A_f32]] = !{[[TYPE_A:!.*]], [[TYPE_INT]], i64 4}
+// OLD-PATH: [[TYPE_A]] = !{!"_ZTS7StructA", [[TYPE_SHORT:!.*]], i64 0, [[TYPE_INT]], i64 4, [[TYPE_SHORT]], i64 8, [[TYPE_INT]], i64 12}
+// OLD-PATH: [[TYPE_SHORT:!.*]] = !{!"short", [[TYPE_CHAR]]
+// OLD-PATH: [[TAG_A_f16]] = !{[[TYPE_A]], [[TYPE_SHORT]], i64 0}
+// OLD-PATH: [[TAG_B_a_f32]] = !{[[TYPE_B:!.*]], [[TYPE_INT]], i64 8}
+// OLD-PATH: [[TYPE_B]] = !{!"_ZTS7StructB", [[TYPE_SHORT]], i64 0, [[TYPE_A]], i64 4, [[TYPE_INT]], i64 20}
+// OLD-PATH: [[TAG_B_a_f16]] = !{[[TYPE_B]], [[TYPE_SHORT]], i64 4}
+// OLD-PATH: [[TAG_B_f32]] = !{[[TYPE_B]], [[TYPE_INT]], i64 20}
+// OLD-PATH: [[TAG_B_a_f32_2]] = !{[[TYPE_B]], [[TYPE_INT]], i64 16}
+// OLD-PATH: [[TAG_S_f32]] = !{[[TYPE_S:!.*]], [[TYPE_INT]], i64 4}
+// OLD-PATH: [[TYPE_S]] = !{!"_ZTS7StructS", [[TYPE_SHORT]], i64 0, [[TYPE_INT]], i64 4}
+// OLD-PATH: [[TAG_S_f16]] = !{[[TYPE_S]], [[TYPE_SHORT]], i64 0}
+// OLD-PATH: [[TAG_S2_f32_2]] = !{[[TYPE_S2:!.*]], [[TYPE_INT]], i64 12}
+// OLD-PATH: [[TYPE_S2]] = !{!"_ZTS8StructS2", [[TYPE_SHORT]], i64 8, [[TYPE_INT]], i64 12}
+// OLD-PATH: [[TAG_C_b_a_f32]] = !{[[TYPE_C:!.*]], [[TYPE_INT]], i64 12}
+// OLD-PATH: [[TYPE_C]] = !{!"_ZTS7StructC", [[TYPE_SHORT]], i64 0, [[TYPE_B]], i64 4, [[TYPE_INT]], i64 28}
+// OLD-PATH: [[TAG_D_b_a_f32]] = !{[[TYPE_D:!.*]], [[TYPE_INT]], i64 12}
+// OLD-PATH: [[TYPE_D]] = !{!"_ZTS7StructD", [[TYPE_SHORT]], i64 0, [[TYPE_B]], i64 4, [[TYPE_INT]], i64 28, [[TYPE_CHAR]], i64 32}
+
+// NEW-PATH: [[TYPE_CHAR:!.*]] = !{!{{.*}}, i64 1, !"omnipotent char"}
+// NEW-PATH: [[TAG_i32]] = !{[[TYPE_INT:!.*]], [[TYPE_INT]], i64 0, i64 4}
+// NEW-PATH: [[TYPE_INT]] = !{[[TYPE_CHAR]], i64 4, !"int"}
+// NEW-PATH: [[TAG_A_f32]] = !{[[TYPE_A:!.*]], [[TYPE_INT]], i64 4, i64 4}
+// NEW-PATH: [[TYPE_A]] = !{[[TYPE_CHAR]], i64 16, !"_ZTS7StructA", [[TYPE_SHORT:!.*]], i64 0, i64 2, [[TYPE_INT]], i64 4, i64 4, [[TYPE_SHORT]], i64 8, i64 2, [[TYPE_INT]], i64 12, i64 4}
+// NEW-PATH: [[TYPE_SHORT:!.*]] = !{[[TYPE_CHAR]], i64 2, !"short"}
+// NEW-PATH: [[TAG_A_f16]] = !{[[TYPE_A]], [[TYPE_SHORT]], i64 0, i64 2}
+// NEW-PATH: [[TAG_B_a_f32]] = !{[[TYPE_B:!.*]], [[TYPE_INT]], i64 8, i64 4}
+// NEW-PATH: [[TYPE_B]] = !{[[TYPE_CHAR]], i64 24, !"_ZTS7StructB", [[TYPE_SHORT]], i64 0, i64 2, [[TYPE_A]], i64 4, i64 16, [[TYPE_INT]], i64 20, i64 4}
+// NEW-PATH: [[TAG_B_a_f16]] = !{[[TYPE_B]], [[TYPE_SHORT]], i64 4, i64 2}
+// NEW-PATH: [[TAG_B_f32]] = !{[[TYPE_B]], [[TYPE_INT]], i64 20, i64 4}
+// NEW-PATH: [[TAG_B_a_f32_2]] = !{[[TYPE_B]], [[TYPE_INT]], i64 16, i64 4}
+// NEW-PATH: [[TAG_S_f32]] = !{[[TYPE_S:!.*]], [[TYPE_INT]], i64 4, i64 4}
+// NEW-PATH: [[TYPE_S]] = !{[[TYPE_CHAR]], i64 8, !"_ZTS7StructS", [[TYPE_SHORT]], i64 0, i64 2, [[TYPE_INT]], i64 4, i64 4}
+// NEW-PATH: [[TAG_S_f16]] = !{[[TYPE_S]], [[TYPE_SHORT]], i64 0, i64 2}
+// NEW-PATH: [[TAG_S2_f32_2]] = !{[[TYPE_S2:!.*]], [[TYPE_INT]], i64 12, i64 4}
+// NEW-PATH: [[TYPE_S2]] = !{[[TYPE_CHAR]], i64 16, !"_ZTS8StructS2", [[TYPE_SHORT]], i64 8, i64 2, [[TYPE_INT]], i64 12, i64 4}
+// NEW-PATH: [[TAG_C_b_a_f32]] = !{[[TYPE_C:!.*]], [[TYPE_INT]], i64 12, i64 4}
+// NEW-PATH: [[TYPE_C]] = !{[[TYPE_CHAR]], i64 32, !"_ZTS7StructC", [[TYPE_SHORT]], i64 0, i64 2, [[TYPE_B]], i64 4, i64 24, [[TYPE_INT]], i64 28, i64 4}
+// NEW-PATH: [[TAG_D_b_a_f32]] = !{[[TYPE_D:!.*]], [[TYPE_INT]], i64 12, i64 4}
+// NEW-PATH: [[TYPE_D]] = !{[[TYPE_CHAR]], i64 36, !"_ZTS7StructD", [[TYPE_SHORT]], i64 0, i64 2, [[TYPE_B]], i64 4, i64 24, [[TYPE_INT]], i64 28, i64 4, [[TYPE_CHAR]], i64 32, i64 1}
diff --git a/test/CodeGen/tbaa-for-vptr.cpp b/test/CodeGen/tbaa-for-vptr.cpp
index 6136874cbfcb..1139749f0fad 100644
--- a/test/CodeGen/tbaa-for-vptr.cpp
+++ b/test/CodeGen/tbaa-for-vptr.cpp
@@ -1,6 +1,10 @@
-// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - -fsanitize=thread %s | FileCheck %s
-// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - -O1 %s | FileCheck %s
-// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - -O1 -relaxed-aliasing -fsanitize=thread %s | FileCheck %s
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - -fsanitize=thread %s | FileCheck %s --check-prefixes=CHECK,OLD-PATH
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - -O1 %s | FileCheck %s --check-prefixes=CHECK,OLD-PATH
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - -O1 -relaxed-aliasing -fsanitize=thread %s | FileCheck %s --check-prefixes=CHECK,OLD-PATH
+//
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -new-struct-path-tbaa -o - -fsanitize=thread %s | FileCheck %s --check-prefixes=CHECK,NEW-PATH
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -new-struct-path-tbaa -o - -O1 %s | FileCheck %s --check-prefixes=CHECK,NEW-PATH
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -new-struct-path-tbaa -o - -O1 -relaxed-aliasing -fsanitize=thread %s | FileCheck %s --check-prefixes=CHECK,NEW-PATH
//
// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s --check-prefix=NOTBAA
// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - -O2 -relaxed-aliasing %s | FileCheck %s --check-prefix=NOTBAA
@@ -30,6 +34,8 @@ void CallFoo(A *a, int (A::*fp)() const) {
// CHECK-LABEL: @_ZN1AC2Ev
// CHECK: store i32 (...)** {{.*}}, !tbaa ![[NUM]]
//
-// CHECK: [[NUM]] = !{[[TYPE:!.*]], [[TYPE]], i64 0}
-// CHECK: [[TYPE]] = !{!"vtable pointer", !{{.*}}
+// OLD-PATH: [[NUM]] = !{[[TYPE:!.*]], [[TYPE]], i64 0}
+// OLD-PATH: [[TYPE]] = !{!"vtable pointer", !{{.*}}
+// NEW-PATH: [[NUM]] = !{[[TYPE:!.*]], [[TYPE]], i64 0, i64 [[POINTER_SIZE:.*]]}
+// NEW-PATH: [[TYPE]] = !{!{{.*}}, i64 [[POINTER_SIZE]], !"vtable pointer"}
// NOTBAA-NOT: = !{!"Simple C++ TBAA"}
diff --git a/test/CodeGen/tbaa-ms-abi.cpp b/test/CodeGen/tbaa-ms-abi.cpp
index 51100b18c3d4..c7f258b50224 100644
--- a/test/CodeGen/tbaa-ms-abi.cpp
+++ b/test/CodeGen/tbaa-ms-abi.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -triple i686-pc-win32 -disable-llvm-passes -emit-llvm -o - -O1 %s | FileCheck %s
+// RUN: %clang_cc1 -triple i686-pc-win32 -disable-llvm-passes -emit-llvm -o - -O1 %s | FileCheck %s -check-prefixes=CHECK,OLD-PATH
+// RUN: %clang_cc1 -triple i686-pc-win32 -disable-llvm-passes -emit-llvm -new-struct-path-tbaa -o - -O1 %s | FileCheck %s -check-prefixes=CHECK,NEW-PATH
//
// Test that TBAA works in the Microsoft C++ ABI. We used to error out while
// attempting to mangle RTTI.
@@ -16,7 +17,11 @@ StructB::StructB() {
// CHECK: store i32 42, i32* {{.*}}, !tbaa [[TAG_A_i32:!.*]]
}
-// CHECK: [[TYPE_INT:!.*]] = !{!"int", [[TYPE_CHAR:!.*]], i64 0}
-// CHECK: [[TYPE_CHAR]] = !{!"omnipotent char", !
-// CHECK: [[TAG_A_i32]] = !{[[TYPE_A:!.*]], [[TYPE_INT]], i64 0}
-// CHECK: [[TYPE_A]] = !{!"?AUStructA@@", [[TYPE_INT]], i64 0}
+// OLD-PATH: [[TYPE_INT:!.*]] = !{!"int", [[TYPE_CHAR:!.*]], i64 0}
+// OLD-PATH: [[TYPE_CHAR]] = !{!"omnipotent char", !
+// OLD-PATH: [[TAG_A_i32]] = !{[[TYPE_A:!.*]], [[TYPE_INT]], i64 0}
+// OLD-PATH: [[TYPE_A]] = !{!"?AUStructA@@", [[TYPE_INT]], i64 0}
+// NEW-PATH: [[TYPE_INT:!.*]] = !{[[TYPE_CHAR:!.*]], i64 4, !"int"}
+// NEW-PATH: [[TYPE_CHAR]] = !{{{.*}}, i64 1, !"omnipotent char"}
+// NEW-PATH: [[TAG_A_i32]] = !{[[TYPE_A:!.*]], [[TYPE_INT]], i64 0, i64 4}
+// NEW-PATH: [[TYPE_A]] = !{[[TYPE_CHAR]], i64 4, !"?AUStructA@@", [[TYPE_INT]], i64 0, i64 4}
diff --git a/test/CodeGen/tbaa-reference.cpp b/test/CodeGen/tbaa-reference.cpp
index ecdbfbee7f14..113796aa045a 100644
--- a/test/CodeGen/tbaa-reference.cpp
+++ b/test/CodeGen/tbaa-reference.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -triple x86_64-linux -O1 -disable-llvm-passes %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-linux -O1 -disable-llvm-passes %s -emit-llvm -o - | FileCheck %s -check-prefixes=CHECK,OLD-PATH
+// RUN: %clang_cc1 -triple x86_64-linux -O1 -disable-llvm-passes %s -emit-llvm -new-struct-path-tbaa -o - | FileCheck %s -check-prefixes=CHECK,NEW-PATH
//
// Check that we generate correct TBAA information for reference accesses.
@@ -29,9 +30,16 @@ S &B::get() {
return s;
}
-// CHECK-DAG: [[TAG_pointer]] = !{[[TYPE_pointer:!.*]], [[TYPE_pointer]], i64 0}
-// CHECK-DAG: [[TAG_B_s]] = !{[[TYPE_B:!.*]], [[TYPE_pointer]], i64 0}
+// OLD-PATH-DAG: [[TAG_pointer]] = !{[[TYPE_pointer:!.*]], [[TYPE_pointer]], i64 0}
+// OLD-PATH-DAG: [[TAG_B_s]] = !{[[TYPE_B:!.*]], [[TYPE_pointer]], i64 0}
//
-// CHECK-DAG: [[TYPE_B]] = !{!"_ZTS1B", [[TYPE_pointer]], i64 0}
-// CHECK-DAG: [[TYPE_pointer]] = !{!"any pointer", [[TYPE_char:!.*]], i64 0}
-// CHECK-DAG: [[TYPE_char]] = !{!"omnipotent char", {{!.*}}, i64 0}
+// OLD-PATH-DAG: [[TYPE_B]] = !{!"_ZTS1B", [[TYPE_pointer]], i64 0}
+// OLD-PATH-DAG: [[TYPE_pointer]] = !{!"any pointer", [[TYPE_char:!.*]], i64 0}
+// OLD-PATH-DAG: [[TYPE_char]] = !{!"omnipotent char", {{!.*}}, i64 0}
+
+// NEW-PATH-DAG: [[TAG_pointer]] = !{[[TYPE_pointer:!.*]], [[TYPE_pointer]], i64 0, i64 8}
+// NEW-PATH-DAG: [[TAG_B_s]] = !{[[TYPE_B:!.*]], [[TYPE_pointer]], i64 0, i64 8}
+//
+// NEW-PATH-DAG: [[TYPE_B]] = !{[[TYPE_char:!.*]], i64 8, !"_ZTS1B", [[TYPE_pointer]], i64 0, i64 8}
+// NEW-PATH-DAG: [[TYPE_pointer]] = !{[[TYPE_char:!.*]], i64 8, !"any pointer"}
+// NEW-PATH-DAG: [[TYPE_char]] = !{{{!.*}}, i64 1, !"omnipotent char"}
diff --git a/test/CodeGen/tbaa-struct.cpp b/test/CodeGen/tbaa-struct.cpp
index 2623c42c9a3f..9e5429b2e360 100644
--- a/test/CodeGen/tbaa-struct.cpp
+++ b/test/CodeGen/tbaa-struct.cpp
@@ -1,6 +1,11 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - -O1 %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - -O1 %s | \
+// RUN: FileCheck -check-prefixes=CHECK,CHECK-OLD %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -new-struct-path-tbaa \
+// RUN: -emit-llvm -o - -O1 %s | \
+// RUN: FileCheck -check-prefixes=CHECK,CHECK-NEW %s
//
-// Check that we generate !tbaa.struct metadata for struct copies.
+// Check that we generate TBAA metadata for struct copies correctly.
+
struct A {
short s;
int i;
@@ -8,68 +13,117 @@ struct A {
int j;
};
-void copy(struct A *a, struct A *b) {
- *a = *b;
-}
+typedef A __attribute__((may_alias)) AA;
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.*}}, i8* %{{.*}}, i64 16, i32 4, i1 false), !tbaa.struct [[TS:!.*]]
+void copy(A *a1, A *a2) {
+// CHECK-LABEL: _Z4copyP1AS0_
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %{{.*}}, i8* align 4 %{{.*}}, i64 16, i1 false)
+// CHECK-OLD-SAME: !tbaa.struct [[TS:!.*]]
+// CHECK-NEW-SAME: !tbaa [[TAG_A:![0-9]*]]
+ *a1 = *a2;
+}
struct B {
- char c1;
- struct A a;
- int ii;
+ char c;
+ A a;
+ int i;
};
-void copy2(struct B *a, struct B *b) {
- *a = *b;
+void copy2(B *b1, B *b2) {
+// CHECK-LABEL: _Z5copy2P1BS0_
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %{{.*}}, i8* align 4 %{{.*}}, i64 24, i1 false)
+// CHECK-OLD-SAME: !tbaa.struct [[TS2:!.*]]
+// CHECK-NEW-SAME: !tbaa [[TAG_B:![0-9]*]]
+ *b1 = *b2;
}
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.*}}, i8* %{{.*}}, i64 24, i32 4, i1 false), !tbaa.struct [[TS2:!.*]]
+struct S {
+ _Complex char cc;
+ _Complex int ci;
+};
-typedef _Complex int T2;
-typedef _Complex char T5;
-typedef _Complex int T7;
-typedef struct T4 { T5 field0; T7 field1; } T4;
-typedef union T1 { T2 field0; T4 field1; } T1;
+union U {
+ _Complex int ci;
+ S s;
+};
-void copy3 (T1 *a, T1 *b) {
- *a = *b;
+void copy3(U *u1, U *u2) {
+// CHECK-LABEL: _Z5copy3P1US0_
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %{{.*}}, i8* align 4 %{{.*}}, i64 12, i1 false)
+// CHECK-OLD-SAME: !tbaa.struct [[TS3:!.*]]
+// CHECK-NEW-SAME: !tbaa [[TAG_U:![0-9]*]]
+ *u1 = *u2;
}
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.*}}, i8* %{{.*}}, i64 12, i32 4, i1 false), !tbaa.struct [[TS3:!.*]]
-
// Make sure that zero-length bitfield works.
-#define ATTR __attribute__ ((ms_struct))
-struct five {
+struct C {
char a;
- int :0; /* ignored; prior field is not a bitfield. */
+ int : 0; // Shall not be ignored; see r185018.
char b;
char c;
-} ATTR;
-void copy4(struct five *a, struct five *b) {
- *a = *b;
+} __attribute__((ms_struct));
+
+void copy4(C *c1, C *c2) {
+// CHECK-LABEL: _Z5copy4P1CS0_
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 3, i1 false)
+// CHECK-OLD-SAME: !tbaa.struct [[TS4:!.*]]
+// CHECK-NEW-SAME: !tbaa [[TAG_C:![0-9]*]]
+ *c1 = *c2;
}
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.*}}, i8* %{{.*}}, i64 3, i32 1, i1 false), !tbaa.struct [[TS4:!.*]]
-struct six {
+struct D {
char a;
- int :0;
+ int : 0;
char b;
char c;
};
-void copy5(struct six *a, struct six *b) {
- *a = *b;
+
+void copy5(D *d1, D *d2) {
+// CHECK-LABEL: _Z5copy5P1DS0_
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 6, i1 false)
+// CHECK-OLD-SAME: !tbaa.struct [[TS5:!.*]]
+// CHECK-NEW-SAME: !tbaa [[TAG_D:![0-9]*]]
+ *d1 = *d2;
+}
+
+void copy6(AA *a1, A *a2) {
+// CHECK-LABEL: _Z5copy6P1AS0_
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %{{.*}}, i8* align 4 %{{.*}}, i64 16, i1 false)
+// CHECK-OLD-SAME: !tbaa.struct [[TS]]
+// CHECK-NEW-SAME: !tbaa [[TAG_char:![0-9]*]]
+ *a1 = *a2;
}
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.*}}, i8* %{{.*}}, i64 6, i32 1, i1 false), !tbaa.struct [[TS5:!.*]]
-// CHECK: [[TS]] = !{i64 0, i64 2, !{{.*}}, i64 4, i64 4, !{{.*}}, i64 8, i64 1, !{{.*}}, i64 12, i64 4, !{{.*}}}
-// CHECK: [[CHAR:!.*]] = !{!"omnipotent char", !{{.*}}}
-// CHECK: [[TAG_INT:!.*]] = !{[[INT:!.*]], [[INT]], i64 0}
-// CHECK: [[INT]] = !{!"int", [[CHAR]]
-// CHECK: [[TAG_CHAR:!.*]] = !{[[CHAR]], [[CHAR]], i64 0}
+void copy7(A *a1, AA *a2) {
+// CHECK-LABEL: _Z5copy7P1AS0_
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %{{.*}}, i8* align 4 %{{.*}}, i64 16, i1 false)
+// CHECK-OLD-SAME: !tbaa.struct [[TS]]
+// CHECK-NEW-SAME: !tbaa [[TAG_char]]
+ *a1 = *a2;
+}
+
+// CHECK-OLD: [[TS]] = !{i64 0, i64 2, !{{.*}}, i64 4, i64 4, !{{.*}}, i64 8, i64 1, !{{.*}}, i64 12, i64 4, !{{.*}}}
+// CHECK-OLD: [[CHAR:!.*]] = !{!"omnipotent char", !{{.*}}}
+// CHECK-OLD: [[TAG_INT:!.*]] = !{[[INT:!.*]], [[INT]], i64 0}
+// CHECK-OLD: [[INT]] = !{!"int", [[CHAR]]
+// CHECK-OLD: [[TAG_CHAR:!.*]] = !{[[CHAR]], [[CHAR]], i64 0}
// (offset, size) = (0,1) char; (4,2) short; (8,4) int; (12,1) char; (16,4) int; (20,4) int
-// CHECK: [[TS2]] = !{i64 0, i64 1, !{{.*}}, i64 4, i64 2, !{{.*}}, i64 8, i64 4, !{{.*}}, i64 12, i64 1, !{{.*}}, i64 16, i64 4, {{.*}}, i64 20, i64 4, {{.*}}}
+// CHECK-OLD: [[TS2]] = !{i64 0, i64 1, !{{.*}}, i64 4, i64 2, !{{.*}}, i64 8, i64 4, !{{.*}}, i64 12, i64 1, !{{.*}}, i64 16, i64 4, {{.*}}, i64 20, i64 4, {{.*}}}
// (offset, size) = (0,8) char; (0,2) char; (4,8) char
-// CHECK: [[TS3]] = !{i64 0, i64 8, !{{.*}}, i64 0, i64 2, !{{.*}}, i64 4, i64 8, !{{.*}}}
-// CHECK: [[TS4]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 1, i64 4, [[TAG_INT]], i64 1, i64 1, [[TAG_CHAR]], i64 2, i64 1, [[TAG_CHAR]]}
-// CHECK: [[TS5]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 4, i64 4, [[TAG_INT]], i64 4, i64 1, [[TAG_CHAR]], i64 5, i64 1, [[TAG_CHAR]]}
+// CHECK-OLD: [[TS3]] = !{i64 0, i64 8, !{{.*}}, i64 0, i64 2, !{{.*}}, i64 4, i64 8, !{{.*}}}
+// CHECK-OLD: [[TS4]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 1, i64 4, [[TAG_INT]], i64 1, i64 1, [[TAG_CHAR]], i64 2, i64 1, [[TAG_CHAR]]}
+// CHECK-OLD: [[TS5]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 4, i64 4, [[TAG_INT]], i64 4, i64 1, [[TAG_CHAR]], i64 5, i64 1, [[TAG_CHAR]]}
+
+// CHECK-NEW-DAG: [[TYPE_char:!.*]] = !{{{.*}}, i64 1, !"omnipotent char"}
+// CHECK-NEW-DAG: [[TAG_char]] = !{[[TYPE_char]], [[TYPE_char]], i64 0, i64 0}
+// CHECK-NEW-DAG: [[TYPE_short:!.*]] = !{[[TYPE_char]], i64 2, !"short"}
+// CHECK-NEW-DAG: [[TYPE_int:!.*]] = !{[[TYPE_char]], i64 4, !"int"}
+// CHECK-NEW-DAG: [[TYPE_A:!.*]] = !{[[TYPE_char]], i64 16, !"_ZTS1A", [[TYPE_short]], i64 0, i64 2, [[TYPE_int]], i64 4, i64 4, [[TYPE_char]], i64 8, i64 1, [[TYPE_int]], i64 12, i64 4}
+// CHECK-NEW-DAG: [[TAG_A]] = !{[[TYPE_A]], [[TYPE_A]], i64 0, i64 16}
+// CHECK-NEW-DAG: [[TYPE_B:!.*]] = !{[[TYPE_char]], i64 24, !"_ZTS1B", [[TYPE_char]], i64 0, i64 1, [[TYPE_A]], i64 4, i64 16, [[TYPE_int]], i64 20, i64 4}
+// CHECK-NEW-DAG: [[TAG_B]] = !{[[TYPE_B]], [[TYPE_B]], i64 0, i64 24}
+// CHECK-NEW-DAG: [[TAG_U]] = !{[[TYPE_char]], [[TYPE_char]], i64 0, i64 12}
+// CHECK-NEW-DAG: [[TYPE_C:!.*]] = !{[[TYPE_char]], i64 3, !"_ZTS1C", [[TYPE_char]], i64 0, i64 1, [[TYPE_int]], i64 1, i64 4, [[TYPE_char]], i64 1, i64 1, [[TYPE_char]], i64 2, i64 1}
+// CHECK-NEW-DAG: [[TAG_C]] = !{[[TYPE_C]], [[TYPE_C]], i64 0, i64 3}
+// CHECK-NEW-DAG: [[TYPE_D:!.*]] = !{[[TYPE_char]], i64 6, !"_ZTS1D", [[TYPE_char]], i64 0, i64 1, [[TYPE_int]], i64 4, i64 4, [[TYPE_char]], i64 4, i64 1, [[TYPE_char]], i64 5, i64 1}
+// CHECK-NEW-DAG: [[TAG_D]] = !{[[TYPE_D]], [[TYPE_D]], i64 0, i64 6}
diff --git a/test/CodeGen/tentative-decls.c b/test/CodeGen/tentative-decls.c
index d88c346d7c52..321778720587 100644
--- a/test/CodeGen/tentative-decls.c
+++ b/test/CodeGen/tentative-decls.c
@@ -1,16 +1,16 @@
-// RUN: %clang_cc1 -emit-llvm -o %t %s
+// RUN: %clang_cc1 -emit-llvm -w -o - %s | FileCheck %s
-// RUN: grep '@r = common global \[1 x .*\] zeroinitializer' %t
+// CHECK-DAG: @r = common {{(dso_local )?}}global [1 x {{.*}}] zeroinitializer
int r[];
int (*a)[] = &r;
struct s0;
struct s0 x;
-// RUN: grep '@x = common global .struct.s0 zeroinitializer' %t
+// CHECK-DAG: @x = common {{(dso_local )?}}global %struct.s0 zeroinitializer
struct s0 y;
-// RUN: grep '@y = common global .struct.s0 zeroinitializer' %t
+// CHECK-DAG: @y = common {{(dso_local )?}}global %struct.s0 zeroinitializer
struct s0 *f0() {
return &y;
}
@@ -19,19 +19,19 @@ struct s0 {
int x;
};
-// RUN: grep '@b = common global \[1 x .*\] zeroinitializer' %t
+// CHECK-DAG: @b = common {{(dso_local )?}}global [1 x {{.*}}] zeroinitializer
int b[];
int *f1() {
return b;
}
// Check that the most recent tentative definition wins.
-// RUN: grep '@c = common global \[4 x .*\] zeroinitializer' %t
+// CHECK-DAG: @c = common {{(dso_local )?}}global [4 x {{.*}}] zeroinitializer
int c[];
int c[4];
// Check that we emit static tentative definitions
-// RUN: grep '@c5 = internal global \[1 x .*\] zeroinitializer' %t
+// CHECK-DAG: @c5 = internal global [1 x {{.*}}] zeroinitializer
static int c5[];
static int func() { return c5[0]; }
int callfunc() { return func(); }
diff --git a/test/CodeGen/thinlto-backend-option.ll b/test/CodeGen/thinlto-backend-option.ll
index 4fcdd079df84..b25b584a2fe1 100644
--- a/test/CodeGen/thinlto-backend-option.ll
+++ b/test/CodeGen/thinlto-backend-option.ll
@@ -1,4 +1,4 @@
-; Test to ensure -backend-options work when invoking the ThinLTO backend path.
+; Test to ensure -mllvm work when invoking the ThinLTO backend path.
; This test uses a non-existent backend option to test that backend options are
; being parsed. While it's more important that the existing options are parsed
@@ -8,8 +8,8 @@
; RUN: %clang -flto=thin -c -o %t.o %s
; RUN: llvm-lto -thinlto -o %t %t.o
-; RUN: not %clang_cc1 -x ir %t.o -fthinlto-index=%t.thinlto.bc -backend-option -nonexistent -emit-obj -o /dev/null 2>&1 | FileCheck %s -check-prefix=UNKNOWN
-; UNKNOWN: clang: Unknown command line argument '-nonexistent'
+; RUN: not %clang_cc1 -x ir %t.o -fthinlto-index=%t.thinlto.bc -mllvm -nonexistent -emit-obj -o /dev/null 2>&1 | FileCheck %s -check-prefix=UNKNOWN
+; UNKNOWN: clang (LLVM option parsing): Unknown command line argument '-nonexistent'
; RUN: not %clang_cc1 -flto=thinfoo 2>&1 | FileCheck %s -check-prefix=INVALID
; INVALID: error: invalid value 'thinfoo' in '-flto=thinfoo'
diff --git a/test/CodeGen/thinlto-diagnostic-handler-remarks-with-hotness.ll b/test/CodeGen/thinlto-diagnostic-handler-remarks-with-hotness.ll
new file mode 100644
index 000000000000..09a2ec890ff9
--- /dev/null
+++ b/test/CodeGen/thinlto-diagnostic-handler-remarks-with-hotness.ll
@@ -0,0 +1,49 @@
+; Test to ensure -fdiagnostics-show-hotness and -fsave-optimization-record
+; work when invoking the ThinLTO backend path.
+; REQUIRES: x86-registered-target
+
+; RUN: opt -module-summary -o %t.o %s
+; RUN: llvm-lto -thinlto -o %t %t.o
+
+; First try YAML pass remarks file
+; RUN: rm -f %t2.opt.yaml
+; RUN: %clang -target x86_64-scei-ps4 -O2 -x ir %t.o -fthinlto-index=%t.thinlto.bc -fsave-optimization-record -fdiagnostics-show-hotness -o %t2.o -c
+; RUN: cat %t2.opt.yaml | FileCheck %s -check-prefix=YAML
+
+; YAML: --- !Passed
+; YAML-NEXT: Pass: inline
+; YAML-NEXT: Name: Inlined
+; YAML-NEXT: Function: main
+; YAML-NEXT: Hotness: 300
+; YAML-NEXT: Args:
+; YAML-NEXT: - Callee: tinkywinky
+; YAML-NEXT: - String: ' inlined into '
+; YAML-NEXT: - Caller: main
+; YAML-NEXT: - String: ' with cost='
+; YAML-NEXT: - Cost: '0'
+; YAML-NEXT: - String: ' (threshold='
+; YAML-NEXT: - Threshold: '337'
+; YAML-NEXT: - String: ')'
+; YAML-NEXT: ...
+
+; Next try with pass remarks to stderr
+; RUN: %clang -target x86_64-scei-ps4 -O2 -x ir %t.o -fthinlto-index=%t.thinlto.bc -mllvm -pass-remarks=inline -fdiagnostics-show-hotness -o %t2.o -c 2>&1 | FileCheck %s
+
+; CHECK: tinkywinky inlined into main with cost=0 (threshold=337) (hotness: 300)
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-scei-ps4"
+
+declare i32 @patatino()
+
+define i32 @tinkywinky() {
+ %a = call i32 @patatino()
+ ret i32 %a
+}
+
+define i32 @main() !prof !0 {
+ %i = call i32 @tinkywinky()
+ ret i32 %i
+}
+
+!0 = !{!"function_entry_count", i64 300}
diff --git a/test/CodeGen/thinlto-distributed-backend-skip.ll b/test/CodeGen/thinlto-distributed-backend-skip.ll
new file mode 100644
index 000000000000..d9fa47d23dfc
--- /dev/null
+++ b/test/CodeGen/thinlto-distributed-backend-skip.ll
@@ -0,0 +1,21 @@
+; REQUIRES: x86-registered-target
+
+; Check that ThinLTO backend respects "SkipModuleByDistributedBackend"
+; flag which can be set by indexing.
+
+; RUN: opt -thinlto-bc -o %t.o %s
+
+; RUN: %clang_cc1 -triple x86_64-grtev4-linux-gnu \
+; RUN: -fthinlto-index=%S/Inputs/thinlto-distributed-backend-skip.bc \
+; RUN: -emit-llvm -o - -x ir %t.o | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-grtev4-linux-gnu"
+
+; CHECK: "empty"
+; CHECK: target triple =
+; CHECK-NOT: @main
+define i32 @main() {
+entry:
+ ret i32 0
+}
diff --git a/test/CodeGen/thinlto-distributed-cfi-devirt.ll b/test/CodeGen/thinlto-distributed-cfi-devirt.ll
new file mode 100644
index 000000000000..ab33a59b6982
--- /dev/null
+++ b/test/CodeGen/thinlto-distributed-cfi-devirt.ll
@@ -0,0 +1,109 @@
+; REQUIRES: x86-registered-target
+
+; Backend test for distribute ThinLTO with CFI.
+; It additionally enables -fwhole-program-vtables to get more information in
+; TYPE_IDs of GLOBALVAL_SUMMARY_BLOCK.
+
+; RUN: opt -thinlto-bc -o %t.o %s
+
+; RUN: llvm-lto2 run -thinlto-distributed-indexes %t.o \
+; RUN: -o %t2.index \
+; RUN: -r=%t.o,test,px \
+; RUN: -r=%t.o,_ZN1A1nEi,p \
+; RUN: -r=%t.o,_ZN1B1fEi,p \
+; RUN: -r=%t.o,_ZN1C1fEi,p \
+; RUN: -r=%t.o,_ZTV1B, \
+; RUN: -r=%t.o,_ZTV1C, \
+; RUN: -r=%t.o,_ZN1A1nEi, \
+; RUN: -r=%t.o,_ZN1B1fEi, \
+; RUN: -r=%t.o,_ZN1C1fEi, \
+; RUN: -r=%t.o,_ZTV1B,px \
+; RUN: -r=%t.o,_ZTV1C,px
+
+; Ensure that typeids are in the index.
+; RUN: llvm-bcanalyzer -dump %t.o.thinlto.bc | FileCheck %s
+; CHECK-LABEL: <GLOBALVAL_SUMMARY_BLOCK
+; CHECK: <TYPE_ID op0=0 op1=6 op2=4 op3=7 op4=0 op5=0 op6=0 op7=0 op8=0 op9=2 op10=6 op11=0 op12=0 op13=8 op14=1 op15=6 op16=9 op17=0/>
+; CHECK-LABEL: </GLOBALVAL_SUMMARY_BLOCK
+; CHECK-LABEL: <STRTAB_BLOCK
+; CHECK: blob data = '_ZTS1A_ZN1A1nEi'
+; CHECK-LABEL: </STRTAB_BLOCK
+
+; RUN: llvm-dis %t.o.thinlto.bc -o - | FileCheck %s --check-prefix=CHECK-DIS
+; Round trip it through llvm-as
+; RUN: llvm-dis %t.o.thinlto.bc -o - | llvm-as -o - | llvm-dis -o - | FileCheck %s --check-prefix=CHECK-DIS
+; CHECK-DIS: ^0 = module: (path: "{{.*}}thinlto-distributed-cfi-devirt.ll.tmp.o", hash: ({{.*}}, {{.*}}, {{.*}}, {{.*}}, {{.*}}))
+; CHECK-DIS: ^1 = gv: (guid: 8346051122425466633, summaries: (function: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 1, dsoLocal: 0), insts: 18, typeIdInfo: (typeTests: (^2), typeCheckedLoadVCalls: (vFuncId: (^2, offset: 8), vFuncId: (^2, offset: 0))))))
+; CHECK-DIS: ^2 = typeid: (name: "_ZTS1A", summary: (typeTestRes: (kind: allOnes, sizeM1BitWidth: 7), wpdResolutions: ((offset: 0, wpdRes: (kind: branchFunnel)), (offset: 8, wpdRes: (kind: singleImpl, singleImplName: "_ZN1A1nEi"))))) ; guid = 7004155349499253778
+
+; RUN: %clang_cc1 -triple x86_64-grtev4-linux-gnu \
+; RUN: -emit-obj -fthinlto-index=%t.o.thinlto.bc \
+; RUN: -emit-llvm -o - -x ir %t.o | FileCheck %s --check-prefixes=CHECK-IR
+
+; Check that backend does not fail generating native code.
+; RUN: %clang_cc1 -triple x86_64-grtev4-linux-gnu \
+; RUN: -emit-obj -fthinlto-index=%t.o.thinlto.bc \
+; RUN: -o %t.native.o -x ir %t.o
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-grtev4-linux-gnu"
+
+%struct.A = type { i32 (...)** }
+%struct.B = type { %struct.A }
+%struct.C = type { %struct.A }
+
+@_ZTV1B = constant { [4 x i8*] } { [4 x i8*] [i8* null, i8* undef, i8* bitcast (i32 (%struct.B*, i32)* @_ZN1B1fEi to i8*), i8* bitcast (i32 (%struct.A*, i32)* @_ZN1A1nEi to i8*)] }, !type !0, !type !1
+@_ZTV1C = constant { [4 x i8*] } { [4 x i8*] [i8* null, i8* undef, i8* bitcast (i32 (%struct.C*, i32)* @_ZN1C1fEi to i8*), i8* bitcast (i32 (%struct.A*, i32)* @_ZN1A1nEi to i8*)] }, !type !0, !type !2
+
+; CHECK-IR-LABEL: define i32 @test
+define i32 @test(%struct.A* %obj, i32 %a) {
+entry:
+ %0 = bitcast %struct.A* %obj to i8**
+ %vtable5 = load i8*, i8** %0
+
+ %1 = tail call { i8*, i1 } @llvm.type.checked.load(i8* %vtable5, i32 8, metadata !"_ZTS1A")
+ %2 = extractvalue { i8*, i1 } %1, 1
+ br i1 %2, label %cont, label %trap
+
+trap:
+ tail call void @llvm.trap()
+ unreachable
+
+cont:
+ %3 = extractvalue { i8*, i1 } %1, 0
+ %4 = bitcast i8* %3 to i32 (%struct.A*, i32)*
+
+ ; Check that the call was devirtualized.
+ ; CHECK-IR: %call = tail call i32 @_ZN1A1nEi
+ %call = tail call i32 %4(%struct.A* nonnull %obj, i32 %a)
+ %vtable16 = load i8*, i8** %0
+ %5 = tail call { i8*, i1 } @llvm.type.checked.load(i8* %vtable16, i32 0, metadata !"_ZTS1A")
+ %6 = extractvalue { i8*, i1 } %5, 1
+ br i1 %6, label %cont2, label %trap
+
+cont2:
+ %7 = extractvalue { i8*, i1 } %5, 0
+ %8 = bitcast i8* %7 to i32 (%struct.A*, i32)*
+
+ ; Check that traps are conditional. Invalid TYPE_ID can cause
+ ; unconditional traps.
+ ; CHECK-IR: br i1 {{.*}}, label %trap
+
+ ; We still have to call it as virtual.
+ ; CHECK-IR: %call3 = tail call i32 %8
+ %call3 = tail call i32 %8(%struct.A* nonnull %obj, i32 %call)
+ ret i32 %call3
+}
+; CHECK-IR-LABEL: ret i32
+; CHECK-IR-LABEL: }
+
+declare { i8*, i1 } @llvm.type.checked.load(i8*, i32, metadata)
+declare void @llvm.trap()
+
+declare i32 @_ZN1B1fEi(%struct.B* %this, i32 %a)
+declare i32 @_ZN1A1nEi(%struct.A* %this, i32 %a)
+declare i32 @_ZN1C1fEi(%struct.C* %this, i32 %a)
+
+!0 = !{i64 16, !"_ZTS1A"}
+!1 = !{i64 16, !"_ZTS1B"}
+!2 = !{i64 16, !"_ZTS1C"}
diff --git a/test/CodeGen/thinlto-distributed-cfi.ll b/test/CodeGen/thinlto-distributed-cfi.ll
new file mode 100644
index 000000000000..055b5971eb23
--- /dev/null
+++ b/test/CodeGen/thinlto-distributed-cfi.ll
@@ -0,0 +1,74 @@
+; REQUIRES: x86-registered-target
+
+; Backend test for distribute ThinLTO with CFI.
+
+; RUN: opt -thinlto-bc -o %t.o %s
+
+; RUN: llvm-lto2 run -thinlto-distributed-indexes %t.o \
+; RUN: -o %t2.index \
+; RUN: -r=%t.o,test,px \
+; RUN: -r=%t.o,_ZTV1B, \
+; RUN: -r=%t.o,_ZN1B1fEi, \
+; RUN: -r=%t.o,_ZTV1B,px
+
+; Check that typeids are in the index.
+; RUN: llvm-bcanalyzer -dump %t.o.thinlto.bc | FileCheck %s
+; CHECK-LABEL: <GLOBALVAL_SUMMARY_BLOCK
+; CHECK: <TYPE_ID op0=0 op1=6 op2=3 op3=0 op4=0 op5=0 op6=0 op7=0/>
+; CHECK-LABEL: </GLOBALVAL_SUMMARY_BLOCK
+; CHECK-LABEL: <STRTAB_BLOCK
+; CHECK: blob data = '_ZTS1A'
+; CHECK-LABEL: </STRTAB_BLOCK
+
+; RUN: llvm-dis %t.o.thinlto.bc -o - | FileCheck %s --check-prefix=CHECK-DIS
+; Round trip it through llvm-as
+; RUN: llvm-dis %t.o.thinlto.bc -o - | llvm-as -o - | llvm-dis -o - | FileCheck %s --check-prefix=CHECK-DIS
+; CHECK-DIS: ^0 = module: (path: "{{.*}}thinlto-distributed-cfi.ll.tmp.o", hash: ({{.*}}, {{.*}}, {{.*}}, {{.*}}, {{.*}}))
+; CHECK-DIS: ^1 = gv: (guid: 8346051122425466633, summaries: (function: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 1, dsoLocal: 0), insts: 7, typeIdInfo: (typeTests: (^2)))))
+; CHECK-DIS: ^2 = typeid: (name: "_ZTS1A", summary: (typeTestRes: (kind: single, sizeM1BitWidth: 0))) ; guid = 7004155349499253778
+
+; RUN: %clang_cc1 -triple x86_64-grtev4-linux-gnu \
+; RUN: -emit-obj -fthinlto-index=%t.o.thinlto.bc \
+; RUN: -emit-llvm -o - -x ir %t.o | FileCheck %s --check-prefixes=CHECK-IR
+
+; Ensure that backend does not fail generating native code.
+; RUN: %clang_cc1 -triple x86_64-grtev4-linux-gnu \
+; RUN: -emit-obj -fthinlto-index=%t.o.thinlto.bc \
+; RUN: -o %t.native.o -x ir %t.o
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-grtev4-linux-gnu"
+
+%struct.B = type { %struct.A }
+%struct.A = type { i32 (...)** }
+
+@_ZTV1B = constant { [3 x i8*] } { [3 x i8*] [i8* undef, i8* undef, i8* undef] }, !type !0
+
+; CHECK-IR-LABEL: define void @test
+define void @test(i8* %b) {
+entry:
+ ; Ensure that traps are conditional. Invalid TYPE_ID can cause
+ ; unconditional traps.
+ ; CHECK-IR: br i1 {{.*}}, label %trap
+ %0 = bitcast i8* %b to i8**
+ %vtable2 = load i8*, i8** %0
+ %1 = tail call i1 @llvm.type.test(i8* %vtable2, metadata !"_ZTS1A")
+ br i1 %1, label %cont, label %trap
+
+trap:
+ tail call void @llvm.trap()
+ unreachable
+
+cont:
+ ; CHECK-IR-LABEL: ret void
+ ret void
+}
+; CHECK-IR-LABEL: }
+
+declare i1 @llvm.type.test(i8*, metadata)
+declare void @llvm.trap()
+
+declare i32 @_ZN1B1fEi(%struct.B* %this, i32 %a)
+
+!0 = !{i64 16, !"_ZTS1A"}
+!1 = !{i64 16, !"_ZTS1B"}
diff --git a/test/CodeGen/thinlto-distributed.ll b/test/CodeGen/thinlto-distributed.ll
new file mode 100644
index 000000000000..ae21d7b3e9a3
--- /dev/null
+++ b/test/CodeGen/thinlto-distributed.ll
@@ -0,0 +1,21 @@
+; REQUIRES: x86-registered-target
+
+; Trivial test for distributes ThinLTO
+
+; RUN: opt -thinlto-bc -o %t.o %s
+
+; RUN: llvm-lto2 run -thinlto-distributed-indexes %t.o \
+; RUN: -o %t2.index \
+; RUN: -r=%t.o,main,px
+
+; RUN: %clang_cc1 -triple x86_64-grtev4-linux-gnu \
+; RUN: -emit-obj -fthinlto-index=%t.o.thinlto.bc \
+; RUN: -o %t.native.o -x ir %t.o
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-grtev4-linux-gnu"
+
+define i32 @main() {
+entry:
+ ret i32 0
+}
diff --git a/test/CodeGen/thinlto-split-dwarf.c b/test/CodeGen/thinlto-split-dwarf.c
new file mode 100644
index 000000000000..2a0d82b34c07
--- /dev/null
+++ b/test/CodeGen/thinlto-split-dwarf.c
@@ -0,0 +1,21 @@
+// REQUIRES: x86-registered-target
+
+// RUN: %clang_cc1 -debug-info-kind=limited -triple x86_64-unknown-linux-gnu \
+// RUN: -flto=thin -emit-llvm-bc \
+// RUN: -o %t.o %s
+
+// RUN: llvm-lto2 run -thinlto-distributed-indexes %t.o \
+// RUN: -o %t2.index \
+// RUN: -r=%t.o,main,px
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu \
+// RUN: -emit-obj -fthinlto-index=%t.o.thinlto.bc \
+// RUN: -o %t.native.o -split-dwarf-file %t.native.dwo -x ir %t.o
+
+// RUN: llvm-readobj -sections %t.native.o | FileCheck --check-prefix=O %s
+// RUN: llvm-readobj -sections %t.native.dwo | FileCheck --check-prefix=DWO %s
+
+// O-NOT: .dwo
+// DWO: .dwo
+
+int main() {}
diff --git a/test/CodeGen/thinlto_backend.ll b/test/CodeGen/thinlto_backend.ll
index 86f30c0374fc..5ba846457dfd 100644
--- a/test/CodeGen/thinlto_backend.ll
+++ b/test/CodeGen/thinlto_backend.ll
@@ -1,4 +1,5 @@
-; REQUIRES: x86-registered-target
+; shell required since the windows bot does not like the "(cd ..."
+; REQUIRES: x86-registered-target, shell
; RUN: opt -module-summary -o %t1.o %s
; RUN: opt -module-summary -o %t2.o %S/Inputs/thinlto_backend.ll
@@ -20,8 +21,22 @@
; CHECK-OBJ-IGNORE-EMPTY: T f1
; CHECK-OBJ-IGNORE-EMPTY: U f2
-; Ensure f2 was imported
-; RUN: %clang -target x86_64-unknown-linux-gnu -O2 -o %t3.o -x ir %t1.o -c -fthinlto-index=%t.thinlto.bc
+; Ensure we don't fail with index and non-ThinLTO object file, and output must
+; be empty file.
+; RUN: opt -o %t5.o %s
+; RUN: %clang -target x86_64-unknown-linux-gnu -O2 -o %t4.o -x ir %t5.o -c -fthinlto-index=%t.thinlto.bc
+; RUN: llvm-nm %t4.o | count 0
+
+; Ensure f2 was imported. Check for all 3 flavors of -save-temps[=cwd|obj].
+; RUN: %clang -target x86_64-unknown-linux-gnu -O2 -o %t3.o -x ir %t1.o -c -fthinlto-index=%t.thinlto.bc -save-temps=obj
+; RUN: llvm-dis %t1.s.3.import.bc -o - | FileCheck --check-prefix=CHECK-IMPORT %s
+; RUN: mkdir -p %T/dir1
+; RUN: (cd %T/dir1 && %clang -target x86_64-unknown-linux-gnu -O2 -o %t3.o -x ir %t1.o -c -fthinlto-index=%t.thinlto.bc -save-temps=cwd)
+; RUN: llvm-dis %T/dir1/*1.s.3.import.bc -o - | FileCheck --check-prefix=CHECK-IMPORT %s
+; RUN: mkdir -p %T/dir2
+; RUN: (cd %T/dir2 && %clang -target x86_64-unknown-linux-gnu -O2 -o %t3.o -x ir %t1.o -c -fthinlto-index=%t.thinlto.bc -save-temps)
+; RUN: llvm-dis %T/dir2/*1.s.3.import.bc -o - | FileCheck --check-prefix=CHECK-IMPORT %s
+; CHECK-IMPORT: define available_externally void @f2()
; RUN: llvm-nm %t3.o | FileCheck --check-prefix=CHECK-OBJ %s
; CHECK-OBJ: T f1
; CHECK-OBJ-NOT: U f2
diff --git a/test/CodeGen/transparent-union-redecl.c b/test/CodeGen/transparent-union-redecl.c
new file mode 100644
index 000000000000..31192089827d
--- /dev/null
+++ b/test/CodeGen/transparent-union-redecl.c
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -Werror -triple i386-linux -emit-llvm -o - %s | FileCheck %s
+
+// Test that different order of declarations is acceptable and that
+// implementing different redeclarations is acceptable.
+// rdar://problem/34949329
+
+typedef union {
+ int i;
+ float f;
+} TU __attribute__((transparent_union));
+
+// CHECK-LABEL: define void @f0(i32 %tu.coerce)
+// CHECK: %tu = alloca %union.TU, align 4
+// CHECK: %coerce.dive = getelementptr inbounds %union.TU, %union.TU* %tu, i32 0, i32 0
+// CHECK: store i32 %tu.coerce, i32* %coerce.dive, align 4
+void f0(TU tu) {}
+void f0(int i);
+
+// CHECK-LABEL: define void @f1(i32 %tu.coerce)
+// CHECK: %tu = alloca %union.TU, align 4
+// CHECK: %coerce.dive = getelementptr inbounds %union.TU, %union.TU* %tu, i32 0, i32 0
+// CHECK: store i32 %tu.coerce, i32* %coerce.dive, align 4
+void f1(int i);
+void f1(TU tu) {}
+
+// CHECK-LABEL: define void @f2(i32 %i)
+// CHECK: %i.addr = alloca i32, align 4
+// CHECK: store i32 %i, i32* %i.addr, align 4
+void f2(TU tu);
+void f2(int i) {}
+
+// CHECK-LABEL: define void @f3(i32 %i)
+// CHECK: %i.addr = alloca i32, align 4
+// CHECK: store i32 %i, i32* %i.addr, align 4
+void f3(int i) {}
+void f3(TU tu);
+
+// Also test functions with parameters specified K&R style.
+// CHECK-LABEL: define void @knrStyle(i32 %tu.coerce)
+// CHECK: %tu = alloca %union.TU, align 4
+// CHECK: %coerce.dive = getelementptr inbounds %union.TU, %union.TU* %tu, i32 0, i32 0
+// CHECK: store i32 %tu.coerce, i32* %coerce.dive, align 4
+void knrStyle(int i);
+void knrStyle(tu) TU tu; {}
diff --git a/test/CodeGen/vaes-builtins.c b/test/CodeGen/vaes-builtins.c
index df160aa16ee3..1dd5784814d3 100644
--- a/test/CodeGen/vaes-builtins.c
+++ b/test/CodeGen/vaes-builtins.c
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +vaes -emit-llvm -o - | FileCheck %s --check-prefix AVX
-// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -DAVX512 -target-feature +vaes -target-feature +avx512f -emit-llvm -o - | FileCheck %s --check-prefixes AVX,AVX512
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +vaes -target-feature +avx512f -emit-llvm -o - | FileCheck %s --check-prefixes AVX,AVX512
#include <immintrin.h>
@@ -27,7 +27,7 @@ __m256i test_mm256_aesdeclast_epi128(__m256i __A, __m256i __B) {
return _mm256_aesdeclast_epi128(__A, __B);
}
-#ifdef AVX512
+#ifdef __AVX512F__
__m512i test_mm512_aesenc_epi128(__m512i __A, __m512i __B) {
// AVX512-LABEL: @test_mm512_aesenc_epi128
// AVX512: @llvm.x86.aesni.aesenc.512
diff --git a/test/CodeGen/variadic-null-win64.c b/test/CodeGen/variadic-null-win64.c
index 23c85b835756..a52fb896ddab 100644
--- a/test/CodeGen/variadic-null-win64.c
+++ b/test/CodeGen/variadic-null-win64.c
@@ -15,7 +15,7 @@ void f(const char *f) {
v(f, 1, 2, 3, NULL);
kr(f, 1, 2, 3, 0);
}
-// WINDOWS: define void @f(i8* %f)
+// WINDOWS: define dso_local void @f(i8* %f)
// WINDOWS: call void (i8*, ...) @v(i8* {{.*}}, i32 1, i32 2, i32 3, i64 0)
// WINDOWS: call void bitcast (void (...)* @kr to void (i8*, i32, i32, i32, i32)*)(i8* {{.*}}, i32 1, i32 2, i32 3, i32 0)
// LINUX: define void @f(i8* %f)
diff --git a/test/CodeGen/vector-scalar.c b/test/CodeGen/vector-scalar.c
new file mode 100644
index 000000000000..0c973cd41ee4
--- /dev/null
+++ b/test/CodeGen/vector-scalar.c
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s
+
+// PR27085
+
+typedef unsigned char uchar4 __attribute__ ((vector_size (4)));
+
+// CHECK: @add2
+// CHECK: add <4 x i8> {{.*}}, <i8 2, i8 2, i8 2, i8 2>
+uchar4 add2(uchar4 v)
+{
+ return v + 2;
+}
+
+// CHECK: @sub2
+// CHECK: sub <4 x i8> {{.*}}, <i8 2, i8 2, i8 2, i8 2>
+uchar4 sub2(uchar4 v)
+{
+ return v - 2;
+}
+
+// CHECK: @mul2
+// CHECK: mul <4 x i8> {{.*}}, <i8 2, i8 2, i8 2, i8 2>
+uchar4 mul2(uchar4 v)
+{
+ return v * 2;
+}
+
+// CHECK: @div2
+// CHECK: udiv <4 x i8> {{.*}}, <i8 2, i8 2, i8 2, i8 2>
+uchar4 div2(uchar4 v)
+{
+ return v / 2;
+}
+
+typedef __attribute__(( ext_vector_type(4) )) unsigned char uchar4_ext;
+
+// CHECK: @div3_ext
+// CHECK: udiv <4 x i8> %{{.*}}, <i8 3, i8 3, i8 3, i8 3>
+uchar4_ext div3_ext(uchar4_ext v)
+{
+ return v / 3;
+}
diff --git a/test/CodeGen/vector.c b/test/CodeGen/vector.c
index ebaea841aa85..c79cd84f7e2e 100644
--- a/test/CodeGen/vector.c
+++ b/test/CodeGen/vector.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -ffreestanding -triple i386-apple-darwin9 -O1 -target-cpu core2 -debug-info-kind=limited -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding -triple i386-apple-darwin9 -O1 -target-cpu corei7 -debug-info-kind=limited -emit-llvm %s -o - | FileCheck %s
typedef short __v4hi __attribute__ ((__vector_size__ (8)));
void test1() {
@@ -45,13 +45,13 @@ int test4(int argc, char *argv[]) {
unsigned long test_epi8(__m128i x) { return _mm_extract_epi8(x, 4); }
// CHECK: @test_epi8
-// CHECK: extractelement <16 x i8> {{.*}}, i32 4
+// CHECK: extractelement <16 x i8> {{.*}}, {{i32|i64}} 4
// CHECK: zext i8 {{.*}} to i32
unsigned long test_epi16(__m128i x) { return _mm_extract_epi16(x, 3); }
// CHECK: @test_epi16
-// CHECK: extractelement <8 x i16> {{.*}}, i32 3
+// CHECK: extractelement <8 x i16> {{.*}}, {{i32|i64}} 3
// CHECK: zext i16 {{.*}} to i32
void extractinttypes() {
diff --git a/test/CodeGen/vectorcall.c b/test/CodeGen/vectorcall.c
index fa244fb908e0..564b41e1f54d 100644
--- a/test/CodeGen/vectorcall.c
+++ b/test/CodeGen/vectorcall.c
@@ -2,56 +2,56 @@
// RUN: %clang_cc1 -emit-llvm %s -o - -ffreestanding -triple=x86_64-pc-win32 | FileCheck %s --check-prefix=X64
void __vectorcall v1(int a, int b) {}
-// X32: define x86_vectorcallcc void @"\01v1@@8"(i32 inreg %a, i32 inreg %b)
-// X64: define x86_vectorcallcc void @"\01v1@@16"(i32 %a, i32 %b)
+// X32: define dso_local x86_vectorcallcc void @"\01v1@@8"(i32 inreg %a, i32 inreg %b)
+// X64: define dso_local x86_vectorcallcc void @"\01v1@@16"(i32 %a, i32 %b)
void __vectorcall v2(char a, char b) {}
-// X32: define x86_vectorcallcc void @"\01v2@@8"(i8 inreg signext %a, i8 inreg signext %b)
-// X64: define x86_vectorcallcc void @"\01v2@@16"(i8 %a, i8 %b)
+// X32: define dso_local x86_vectorcallcc void @"\01v2@@8"(i8 inreg signext %a, i8 inreg signext %b)
+// X64: define dso_local x86_vectorcallcc void @"\01v2@@16"(i8 %a, i8 %b)
struct Small { int x; };
void __vectorcall v3(int a, struct Small b, int c) {}
-// X32: define x86_vectorcallcc void @"\01v3@@12"(i32 inreg %a, i32 %b.0, i32 inreg %c)
-// X64: define x86_vectorcallcc void @"\01v3@@24"(i32 %a, i32 %b.coerce, i32 %c)
+// X32: define dso_local x86_vectorcallcc void @"\01v3@@12"(i32 inreg %a, i32 %b.0, i32 inreg %c)
+// X64: define dso_local x86_vectorcallcc void @"\01v3@@24"(i32 %a, i32 %b.coerce, i32 %c)
struct Large { int a[5]; };
void __vectorcall v4(int a, struct Large b, int c) {}
-// X32: define x86_vectorcallcc void @"\01v4@@28"(i32 inreg %a, %struct.Large* byval align 4 %b, i32 inreg %c)
-// X64: define x86_vectorcallcc void @"\01v4@@40"(i32 %a, %struct.Large* %b, i32 %c)
+// X32: define dso_local x86_vectorcallcc void @"\01v4@@28"(i32 inreg %a, %struct.Large* byval align 4 %b, i32 inreg %c)
+// X64: define dso_local x86_vectorcallcc void @"\01v4@@40"(i32 %a, %struct.Large* %b, i32 %c)
struct HFA2 { double x, y; };
struct HFA4 { double w, x, y, z; };
struct HFA5 { double v, w, x, y, z; };
void __vectorcall hfa1(int a, struct HFA4 b, int c) {}
-// X32: define x86_vectorcallcc void @"\01hfa1@@40"(i32 inreg %a, %struct.HFA4 inreg %b.coerce, i32 inreg %c)
-// X64: define x86_vectorcallcc void @"\01hfa1@@48"(i32 %a, %struct.HFA4 inreg %b.coerce, i32 %c)
+// X32: define dso_local x86_vectorcallcc void @"\01hfa1@@40"(i32 inreg %a, %struct.HFA4 inreg %b.coerce, i32 inreg %c)
+// X64: define dso_local x86_vectorcallcc void @"\01hfa1@@48"(i32 %a, %struct.HFA4 inreg %b.coerce, i32 %c)
// HFAs that would require more than six total SSE registers are passed
// indirectly. Additional vector arguments can consume the rest of the SSE
// registers.
void __vectorcall hfa2(struct HFA4 a, struct HFA4 b, double c) {}
-// X32: define x86_vectorcallcc void @"\01hfa2@@72"(%struct.HFA4 inreg %a.coerce, %struct.HFA4* inreg %b, double %c)
-// X64: define x86_vectorcallcc void @"\01hfa2@@72"(%struct.HFA4 inreg %a.coerce, %struct.HFA4* %b, double %c)
+// X32: define dso_local x86_vectorcallcc void @"\01hfa2@@72"(%struct.HFA4 inreg %a.coerce, %struct.HFA4* inreg %b, double %c)
+// X64: define dso_local x86_vectorcallcc void @"\01hfa2@@72"(%struct.HFA4 inreg %a.coerce, %struct.HFA4* %b, double %c)
// Ensure that we pass builtin types directly while counting them against the
// SSE register usage.
void __vectorcall hfa3(double a, double b, double c, double d, double e, struct HFA2 f) {}
-// X32: define x86_vectorcallcc void @"\01hfa3@@56"(double %a, double %b, double %c, double %d, double %e, %struct.HFA2* inreg %f)
-// X64: define x86_vectorcallcc void @"\01hfa3@@56"(double %a, double %b, double %c, double %d, double %e, %struct.HFA2* %f)
+// X32: define dso_local x86_vectorcallcc void @"\01hfa3@@56"(double %a, double %b, double %c, double %d, double %e, %struct.HFA2* inreg %f)
+// X64: define dso_local x86_vectorcallcc void @"\01hfa3@@56"(double %a, double %b, double %c, double %d, double %e, %struct.HFA2* %f)
// Aggregates with more than four elements are not HFAs and are passed byval.
// Because they are not classified as homogeneous, they don't get special
// handling to ensure alignment.
void __vectorcall hfa4(struct HFA5 a) {}
-// X32: define x86_vectorcallcc void @"\01hfa4@@40"(%struct.HFA5* byval align 4)
-// X64: define x86_vectorcallcc void @"\01hfa4@@40"(%struct.HFA5* %a)
+// X32: define dso_local x86_vectorcallcc void @"\01hfa4@@40"(%struct.HFA5* byval align 4)
+// X64: define dso_local x86_vectorcallcc void @"\01hfa4@@40"(%struct.HFA5* %a)
// Return HFAs of 4 or fewer elements in registers.
static struct HFA2 g_hfa2;
struct HFA2 __vectorcall hfa5(void) { return g_hfa2; }
-// X32: define x86_vectorcallcc %struct.HFA2 @"\01hfa5@@0"()
-// X64: define x86_vectorcallcc %struct.HFA2 @"\01hfa5@@0"()
+// X32: define dso_local x86_vectorcallcc %struct.HFA2 @"\01hfa5@@0"()
+// X64: define dso_local x86_vectorcallcc %struct.HFA2 @"\01hfa5@@0"()
typedef float __attribute__((vector_size(16))) v4f32;
struct HVA2 { v4f32 x, y; };
@@ -60,52 +60,52 @@ struct HVA4 { v4f32 w, x, y, z; };
struct HVA5 { v4f32 w, x, y, z, p; };
v4f32 __vectorcall hva1(int a, struct HVA4 b, int c) {return b.w;}
-// X32: define x86_vectorcallcc <4 x float> @"\01hva1@@72"(i32 inreg %a, %struct.HVA4 inreg %b.coerce, i32 inreg %c)
-// X64: define x86_vectorcallcc <4 x float> @"\01hva1@@80"(i32 %a, %struct.HVA4 inreg %b.coerce, i32 %c)
+// X32: define dso_local x86_vectorcallcc <4 x float> @"\01hva1@@72"(i32 inreg %a, %struct.HVA4 inreg %b.coerce, i32 inreg %c)
+// X64: define dso_local x86_vectorcallcc <4 x float> @"\01hva1@@80"(i32 %a, %struct.HVA4 inreg %b.coerce, i32 %c)
v4f32 __vectorcall hva2(struct HVA4 a, struct HVA4 b, v4f32 c) {return c;}
-// X32: define x86_vectorcallcc <4 x float> @"\01hva2@@144"(%struct.HVA4 inreg %a.coerce, %struct.HVA4* inreg %b, <4 x float> %c)
-// X64: define x86_vectorcallcc <4 x float> @"\01hva2@@144"(%struct.HVA4 inreg %a.coerce, %struct.HVA4* %b, <4 x float> %c)
+// X32: define dso_local x86_vectorcallcc <4 x float> @"\01hva2@@144"(%struct.HVA4 inreg %a.coerce, %struct.HVA4* inreg %b, <4 x float> %c)
+// X64: define dso_local x86_vectorcallcc <4 x float> @"\01hva2@@144"(%struct.HVA4 inreg %a.coerce, %struct.HVA4* %b, <4 x float> %c)
v4f32 __vectorcall hva3(v4f32 a, v4f32 b, v4f32 c, v4f32 d, v4f32 e, struct HVA2 f) {return f.x;}
-// X32: define x86_vectorcallcc <4 x float> @"\01hva3@@112"(<4 x float> %a, <4 x float> %b, <4 x float> %c, <4 x float> %d, <4 x float> %e, %struct.HVA2* inreg %f)
-// X64: define x86_vectorcallcc <4 x float> @"\01hva3@@112"(<4 x float> %a, <4 x float> %b, <4 x float> %c, <4 x float> %d, <4 x float> %e, %struct.HVA2* %f)
+// X32: define dso_local x86_vectorcallcc <4 x float> @"\01hva3@@112"(<4 x float> %a, <4 x float> %b, <4 x float> %c, <4 x float> %d, <4 x float> %e, %struct.HVA2* inreg %f)
+// X64: define dso_local x86_vectorcallcc <4 x float> @"\01hva3@@112"(<4 x float> %a, <4 x float> %b, <4 x float> %c, <4 x float> %d, <4 x float> %e, %struct.HVA2* %f)
// vector types have higher priority then HVA structures, So vector types are allocated first
// and HVAs are allocated if enough registers are available
v4f32 __vectorcall hva4(struct HVA4 a, struct HVA2 b, v4f32 c) {return b.y;}
-// X32: define x86_vectorcallcc <4 x float> @"\01hva4@@112"(%struct.HVA4 inreg %a.coerce, %struct.HVA2* inreg %b, <4 x float> %c)
-// X64: define x86_vectorcallcc <4 x float> @"\01hva4@@112"(%struct.HVA4 inreg %a.coerce, %struct.HVA2* %b, <4 x float> %c)
+// X32: define dso_local x86_vectorcallcc <4 x float> @"\01hva4@@112"(%struct.HVA4 inreg %a.coerce, %struct.HVA2* inreg %b, <4 x float> %c)
+// X64: define dso_local x86_vectorcallcc <4 x float> @"\01hva4@@112"(%struct.HVA4 inreg %a.coerce, %struct.HVA2* %b, <4 x float> %c)
v4f32 __vectorcall hva5(struct HVA3 a, struct HVA3 b, v4f32 c, struct HVA2 d) {return d.y;}
-// X32: define x86_vectorcallcc <4 x float> @"\01hva5@@144"(%struct.HVA3 inreg %a.coerce, %struct.HVA3* inreg %b, <4 x float> %c, %struct.HVA2 inreg %d.coerce)
-// X64: define x86_vectorcallcc <4 x float> @"\01hva5@@144"(%struct.HVA3 inreg %a.coerce, %struct.HVA3* %b, <4 x float> %c, %struct.HVA2 inreg %d.coerce)
+// X32: define dso_local x86_vectorcallcc <4 x float> @"\01hva5@@144"(%struct.HVA3 inreg %a.coerce, %struct.HVA3* inreg %b, <4 x float> %c, %struct.HVA2 inreg %d.coerce)
+// X64: define dso_local x86_vectorcallcc <4 x float> @"\01hva5@@144"(%struct.HVA3 inreg %a.coerce, %struct.HVA3* %b, <4 x float> %c, %struct.HVA2 inreg %d.coerce)
struct HVA4 __vectorcall hva6(struct HVA4 a, struct HVA4 b) { return b;}
-// X32: define x86_vectorcallcc %struct.HVA4 @"\01hva6@@128"(%struct.HVA4 inreg %a.coerce, %struct.HVA4* inreg %b)
-// X64: define x86_vectorcallcc %struct.HVA4 @"\01hva6@@128"(%struct.HVA4 inreg %a.coerce, %struct.HVA4* %b)
+// X32: define dso_local x86_vectorcallcc %struct.HVA4 @"\01hva6@@128"(%struct.HVA4 inreg %a.coerce, %struct.HVA4* inreg %b)
+// X64: define dso_local x86_vectorcallcc %struct.HVA4 @"\01hva6@@128"(%struct.HVA4 inreg %a.coerce, %struct.HVA4* %b)
struct HVA5 __vectorcall hva7() {struct HVA5 a = {}; return a;}
-// X32: define x86_vectorcallcc void @"\01hva7@@0"(%struct.HVA5* inreg noalias sret %agg.result)
-// X64: define x86_vectorcallcc void @"\01hva7@@0"(%struct.HVA5* noalias sret %agg.result)
+// X32: define dso_local x86_vectorcallcc void @"\01hva7@@0"(%struct.HVA5* inreg noalias sret %agg.result)
+// X64: define dso_local x86_vectorcallcc void @"\01hva7@@0"(%struct.HVA5* noalias sret %agg.result)
v4f32 __vectorcall hva8(v4f32 a, v4f32 b, v4f32 c, v4f32 d, int e, v4f32 f) {return f;}
-// X32: define x86_vectorcallcc <4 x float> @"\01hva8@@84"(<4 x float> %a, <4 x float> %b, <4 x float> %c, <4 x float> %d, i32 inreg %e, <4 x float> %f)
-// X64: define x86_vectorcallcc <4 x float> @"\01hva8@@88"(<4 x float> %a, <4 x float> %b, <4 x float> %c, <4 x float> %d, i32 %e, <4 x float> %f)
+// X32: define dso_local x86_vectorcallcc <4 x float> @"\01hva8@@84"(<4 x float> %a, <4 x float> %b, <4 x float> %c, <4 x float> %d, i32 inreg %e, <4 x float> %f)
+// X64: define dso_local x86_vectorcallcc <4 x float> @"\01hva8@@88"(<4 x float> %a, <4 x float> %b, <4 x float> %c, <4 x float> %d, i32 %e, <4 x float> %f)
typedef float __attribute__((ext_vector_type(3))) v3f32;
struct OddSizeHVA { v3f32 x, y; };
void __vectorcall odd_size_hva(struct OddSizeHVA a) {}
-// X32: define x86_vectorcallcc void @"\01odd_size_hva@@32"(%struct.OddSizeHVA inreg %a.coerce)
-// X64: define x86_vectorcallcc void @"\01odd_size_hva@@32"(%struct.OddSizeHVA inreg %a.coerce)
+// X32: define dso_local x86_vectorcallcc void @"\01odd_size_hva@@32"(%struct.OddSizeHVA inreg %a.coerce)
+// X64: define dso_local x86_vectorcallcc void @"\01odd_size_hva@@32"(%struct.OddSizeHVA inreg %a.coerce)
// The Vectorcall ABI only allows passing the first 6 items in registers in x64, so this shouldn't
// consider 'p7' as a register. Instead p5 gets put into the register on the second pass.
// x86 should pass p2, p6 and p7 in registers, then p1 in the second pass.
struct HFA2 __vectorcall AddParticles(struct HFA2 p1, float p2, struct HFA4 p3, int p4, struct HFA2 p5, float p6, float p7, int p8){ return p1;}
-// X32: define x86_vectorcallcc %struct.HFA2 @"\01AddParticles@@84"(%struct.HFA2 inreg %p1.coerce, float %p2, %struct.HFA4* inreg %p3, i32 inreg %p4, %struct.HFA2* %p5, float %p6, float %p7, i32 %p8)
-// X64: define x86_vectorcallcc %struct.HFA2 @"\01AddParticles@@104"(%struct.HFA2 inreg %p1.coerce, float %p2, %struct.HFA4* %p3, i32 %p4, %struct.HFA2 inreg %p5.coerce, float %p6, float %p7, i32 %p8)
+// X32: define dso_local x86_vectorcallcc %struct.HFA2 @"\01AddParticles@@84"(%struct.HFA2 inreg %p1.coerce, float %p2, %struct.HFA4* inreg %p3, i32 inreg %p4, %struct.HFA2* %p5, float %p6, float %p7, i32 %p8)
+// X64: define dso_local x86_vectorcallcc %struct.HFA2 @"\01AddParticles@@104"(%struct.HFA2 inreg %p1.coerce, float %p2, %struct.HFA4* %p3, i32 %p4, %struct.HFA2 inreg %p5.coerce, float %p6, float %p7, i32 %p8)
// Vectorcall in both architectures allows passing of an HVA as long as there is room,
// even if it is not one of the first 6 arguments. First pass puts p4 into a
@@ -113,6 +113,6 @@ struct HFA2 __vectorcall AddParticles(struct HFA2 p1, float p2, struct HFA4 p3,
// in a register, does NOT put p7 in a register (since theres no room), then puts
// p8 in a register.
void __vectorcall HVAAnywhere(struct HFA2 p1, int p2, int p3, float p4, int p5, int p6, struct HFA4 p7, struct HFA2 p8, float p9){}
-// X32: define x86_vectorcallcc void @"\01HVAAnywhere@@88"(%struct.HFA2 inreg %p1.coerce, i32 inreg %p2, i32 inreg %p3, float %p4, i32 %p5, i32 %p6, %struct.HFA4* %p7, %struct.HFA2 inreg %p8.coerce, float %p9)
-// X64: define x86_vectorcallcc void @"\01HVAAnywhere@@112"(%struct.HFA2 inreg %p1.coerce, i32 %p2, i32 %p3, float %p4, i32 %p5, i32 %p6, %struct.HFA4* %p7, %struct.HFA2 inreg %p8.coerce, float %p9)
+// X32: define dso_local x86_vectorcallcc void @"\01HVAAnywhere@@88"(%struct.HFA2 inreg %p1.coerce, i32 inreg %p2, i32 inreg %p3, float %p4, i32 %p5, i32 %p6, %struct.HFA4* %p7, %struct.HFA2 inreg %p8.coerce, float %p9)
+// X64: define dso_local x86_vectorcallcc void @"\01HVAAnywhere@@112"(%struct.HFA2 inreg %p1.coerce, i32 %p2, i32 %p3, float %p4, i32 %p5, i32 %p6, %struct.HFA4* %p7, %struct.HFA2 inreg %p8.coerce, float %p9)
diff --git a/test/CodeGen/vla.c b/test/CodeGen/vla.c
index 0f2e2cdc669d..37243cd17290 100644
--- a/test/CodeGen/vla.c
+++ b/test/CodeGen/vla.c
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm -o - | FileCheck %s -check-prefixes=CHECK,NULL-INVALID
+// RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm -fno-delete-null-pointer-checks -o - | FileCheck %s -check-prefixes=CHECK,NULL-VALID
int b(char* x);
@@ -202,5 +203,6 @@ void test8(int a[static 3]) { }
// CHECK: define void @test8(i32* dereferenceable(12) %a)
void test9(int n, int a[static n]) { }
-// CHECK: define void @test9(i32 %n, i32* nonnull %a)
+// NULL-INVALID: define void @test9(i32 %n, i32* nonnull %a)
+// NULL-VALID: define void @test9(i32 %n, i32* %a)
diff --git a/test/CodeGen/vld_dup.c b/test/CodeGen/vld_dup.c
deleted file mode 100644
index d910c82966ea..000000000000
--- a/test/CodeGen/vld_dup.c
+++ /dev/null
@@ -1,50 +0,0 @@
-// REQUIRES: arm-registered-target
-// RUN: %clang_cc1 -triple armv7a-linux-gnueabi \
-// RUN: -target-cpu cortex-a8 \
-// RUN: -emit-llvm -o - %s | FileCheck %s
-#include <arm_neon.h>
-int main(){
- int32_t v0[3];
- int32x2x3_t v1;
- int32_t v2[4];
- int32x2x4_t v3;
- int64x1x3_t v4;
- int64x1x4_t v5;
- int64_t v6[3];
- int64_t v7[4];
-
- v1 = vld3_dup_s32(v0);
-// CHECK: [[T168:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32> } @llvm.arm.neon.vld3lane.v2i32.p0i8(i8* {{.*}}, <2 x i32> undef, <2 x i32> undef, <2 x i32> undef, i32 {{[0-9]+}}, i32 {{[0-9]+}})
-// CHECK-NEXT: [[T169:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32> } [[T168]], 0
-// CHECK-NEXT: [[T170:%.*]] = shufflevector <2 x i32> [[T169]], <2 x i32> [[T169]], <2 x i32> zeroinitializer
-// CHECK-NEXT: [[T171:%.*]] = insertvalue { <2 x i32>, <2 x i32>, <2 x i32> } [[T168]], <2 x i32> [[T170]], 0
-// CHECK-NEXT: [[T172:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32> } [[T171]], 1
-// CHECK-NEXT: [[T173:%.*]] = shufflevector <2 x i32> [[T172]], <2 x i32> [[T172]], <2 x i32> zeroinitializer
-// CHECK-NEXT: [[T174:%.*]] = insertvalue { <2 x i32>, <2 x i32>, <2 x i32> } [[T171]], <2 x i32> [[T173]], 1
-// CHECK-NEXT: [[T175:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32> } [[T174]], 2
-// CHECK-NEXT: [[T176:%.*]] = shufflevector <2 x i32> [[T175]], <2 x i32> [[T175]], <2 x i32> zeroinitializer
-// CHECK-NEXT: [[T177:%.*]] = insertvalue { <2 x i32>, <2 x i32>, <2 x i32> } [[T174]], <2 x i32> [[T176]], 2
-
- v3 = vld4_dup_s32(v2);
-// CHECK: [[T178:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } @llvm.arm.neon.vld4lane.v2i32.p0i8(i8* {{.*}}, <2 x i32> undef, <2 x i32> undef, <2 x i32> undef, <2 x i32> undef, i32 {{[0-9]+}}, i32 {{[0-9]+}})
-// CHECK-NEXT: [[T179:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[T178]], 0
-// CHECK-NEXT: [[T180:%.*]] = shufflevector <2 x i32> [[T179]], <2 x i32> [[T179]], <2 x i32> zeroinitializer
-// CHECK-NEXT: [[T181:%.*]] = insertvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[T178]], <2 x i32> [[T180]], 0
-// CHECK-NEXT: [[T182:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[T181]], 1
-// CHECK-NEXT: [[T183:%.*]] = shufflevector <2 x i32> [[T182]], <2 x i32> [[T182]], <2 x i32> zeroinitializer
-// CHECK-NEXT: [[T184:%.*]] = insertvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[T181]], <2 x i32> [[T183]], 1
-// CHECK-NEXT: [[T185:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[T184]], 2
-// CHECK-NEXT: [[T186:%.*]] = shufflevector <2 x i32> [[T185]], <2 x i32> [[T185]], <2 x i32> zeroinitializer
-// CHECK-NEXT: [[T187:%.*]] = insertvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[T184]], <2 x i32> [[T186]], 2
-// CHECK-NEXT: [[T188:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[T187]], 3
-// CHECK-NEXT: [[T189:%.*]] = shufflevector <2 x i32> [[T188]], <2 x i32> [[T188]], <2 x i32> zeroinitializer
-// CHECK-NEXT: [[T190:%.*]] = insertvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[T187]], <2 x i32> [[T189]], 3
-
- v4 = vld3_dup_s64(v6);
-// CHECK: {{%.*}} = call { <1 x i64>, <1 x i64>, <1 x i64> } @llvm.arm.neon.vld3.v1i64.p0i8(i8* {{.*}}, i32 {{[0-9]+}})
-
- v5 = vld4_dup_s64(v7);
-// CHECK: {{%.*}} = call { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } @llvm.arm.neon.vld4.v1i64.p0i8(i8* {{.*}}, i32 {{[0-9]+}})
-
- return 0;
-}
diff --git a/test/CodeGen/volatile-1.c b/test/CodeGen/volatile-1.c
index f63274b37f61..c62a8fd4cd3d 100644
--- a/test/CodeGen/volatile-1.c
+++ b/test/CodeGen/volatile-1.c
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -Wno-return-type -Wno-unused-value -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -Wno-return-type -Wno-unused-value -emit-llvm %s -w -o - | FileCheck %s
-// CHECK: @i = common global [[INT:i[0-9]+]] 0
+// CHECK: @i = common {{(dso_local )?}}global [[INT:i[0-9]+]] 0
volatile int i, j, k;
volatile int ar[5];
volatile char c;
-// CHECK: @ci = common global [[CINT:.*]] zeroinitializer
+// CHECK: @ci = common {{(dso_local )?}}global [[CINT:.*]] zeroinitializer
volatile _Complex int ci;
volatile struct S {
#ifdef __cplusplus
diff --git a/test/CodeGen/volatile.c b/test/CodeGen/volatile.c
index 52915f6f4d5b..0f58bb62a248 100644
--- a/test/CodeGen/volatile.c
+++ b/test/CodeGen/volatile.c
@@ -199,7 +199,7 @@ int main() {
// CHECK: store volatile i32 {{.*}}, i32* @vtS
(void)vF2;
// From vF2 to a temporary
-// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* {{.*}} @vF2 {{.*}}, i1 true)
+// CHECK: call void @llvm.memcpy.{{.*}}(i8* align {{[0-9]+}} %{{.*}}, i8* {{.*}} @vF2 {{.*}}, i1 true)
vF2 = vF2;
// vF2 to itself
// CHECK: call void @llvm.memcpy.{{.*}}(i8* {{.*@vF2.*}}, i8* {{.*@vF2.*}}, i1 true)
@@ -209,6 +209,6 @@ int main() {
// CHECK: call void @llvm.memcpy.{{.*}}(i8* {{.*@vF2.*}}, i8* {{.*@vF2.*}}, i1 true)
vF2 = (vF2, vF2);
// vF2 to a temporary, then vF2 to itself
-// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* {{.*@vF2.*}}, i1 true)
+// CHECK: call void @llvm.memcpy.{{.*}}(i8* align {{[0-9]+}} %{{.*}}, i8* {{.*@vF2.*}}, i1 true)
// CHECK: call void @llvm.memcpy.{{.*}}(i8* {{.*@vF2.*}}, i8* {{.*@vF2.*}}, i1 true)
}
diff --git a/test/CodeGen/vpclmulqdq-builtins.c b/test/CodeGen/vpclmulqdq-builtins.c
index 8c610e2d851c..15eef399bcdf 100644
--- a/test/CodeGen/vpclmulqdq-builtins.c
+++ b/test/CodeGen/vpclmulqdq-builtins.c
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +vpclmulqdq -emit-llvm -o - | FileCheck %s --check-prefix AVX
-// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -DAVX512 -target-feature +vpclmulqdq -target-feature +avx512f -emit-llvm -o - | FileCheck %s --check-prefixes AVX,AVX512
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +vpclmulqdq -target-feature +avx512f -emit-llvm -o - | FileCheck %s --check-prefixes AVX,AVX512
#include <immintrin.h>
@@ -8,7 +8,7 @@ __m256i test_mm256_clmulepi64_epi128(__m256i A, __m256i B) {
return _mm256_clmulepi64_epi128(A, B, 0);
}
-#ifdef AVX512
+#ifdef __AVX512F__
__m512i test_mm512_clmulepi64_epi128(__m512i A, __m512i B) {
// AVX512: @llvm.x86.pclmulqdq.512
return _mm512_clmulepi64_epi128(A, B, 0);
diff --git a/test/CodeGen/waitpkg.c b/test/CodeGen/waitpkg.c
new file mode 100644
index 000000000000..250e74fdd9fc
--- /dev/null
+++ b/test/CodeGen/waitpkg.c
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 %s -ffreestanding -triple x86_64-unknown-unknown -emit-llvm -target-feature +waitpkg -Wall -pedantic -o - | FileCheck %s
+// RUN: %clang_cc1 %s -ffreestanding -triple i386-unknown-unknown -emit-llvm -target-feature +waitpkg -Wall -pedantic -o - | FileCheck %s
+
+#include <immintrin.h>
+
+#include <stddef.h>
+#include <stdint.h>
+
+void test_umonitor(void *address) {
+ //CHECK-LABEL: @test_umonitor
+ //CHECK: call void @llvm.x86.umonitor(i8* %{{.*}})
+ return _umonitor(address);
+}
+
+uint8_t test_umwait(uint32_t control, uint64_t counter) {
+ //CHECK-LABEL: @test_umwait
+ //CHECK: call i8 @llvm.x86.umwait(i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}})
+ return _umwait(control, counter);
+}
+
+uint8_t test_tpause(uint32_t control, uint64_t counter) {
+ //CHECK-LABEL: @test_tpause
+ //CHECK: call i8 @llvm.x86.tpause(i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}})
+ return _tpause(control, counter);
+}
diff --git a/test/CodeGen/wasm-arguments.c b/test/CodeGen/wasm-arguments.c
index 723632b62f6b..9283dd5d15f9 100644
--- a/test/CodeGen/wasm-arguments.c
+++ b/test/CodeGen/wasm-arguments.c
@@ -24,7 +24,7 @@ typedef struct {
// Single-element structs should be returned as the one element.
// WEBASSEMBLY32: define i32 @f2()
// WEBASSEMBLY64: define i32 @f2()
-s2 f2() {
+s2 f2(void) {
s2 foo;
return foo;
}
@@ -36,7 +36,7 @@ typedef struct {
// Structs should be returned sret and not simplified by the frontend.
// WEBASSEMBLY32: define void @f3(%struct.s3* noalias sret %agg.result)
// WEBASSEMBLY64: define void @f3(%struct.s3* noalias sret %agg.result)
-s3 f3() {
+s3 f3(void) {
s3 foo;
return foo;
}
diff --git a/test/CodeGen/wasm-varargs.c b/test/CodeGen/wasm-varargs.c
index b8e488ec1440..acbd590cc25c 100644
--- a/test/CodeGen/wasm-varargs.c
+++ b/test/CodeGen/wasm-varargs.c
@@ -80,10 +80,9 @@ struct S test_struct(char *fmt, ...) {
return v;
}
-// CHECK: define void @test_struct([[STRUCT_S:%[^,=]+]]*{{.*}} noalias sret %agg.result, i8*{{.*}} %fmt, ...) {{.*}} {
+// CHECK: define void @test_struct([[STRUCT_S:%[^,=]+]]*{{.*}} noalias sret [[AGG_RESULT:%.*]], i8*{{.*}} %fmt, ...) {{.*}} {
// CHECK: [[FMT_ADDR:%[^,=]+]] = alloca i8*, align 4
// CHECK: [[VA:%[^,=]+]] = alloca i8*, align 4
-// CHECK: [[V:%[^,=]+]] = alloca [[STRUCT_S]], align 4
// CHECK: store i8* %fmt, i8** [[FMT_ADDR]], align 4
// CHECK: [[VA1:%[^,=]+]] = bitcast i8** [[VA]] to i8*
// CHECK: call void @llvm.va_start(i8* [[VA1]])
@@ -91,13 +90,10 @@ struct S test_struct(char *fmt, ...) {
// CHECK: [[ARGP_NEXT:%[^,=]+]] = getelementptr inbounds i8, i8* [[ARGP_CUR]], i32 12
// CHECK: store i8* [[ARGP_NEXT]], i8** [[VA]], align 4
// CHECK: [[R3:%[^,=]+]] = bitcast i8* [[ARGP_CUR]] to [[STRUCT_S]]*
-// CHECK: [[R4:%[^,=]+]] = bitcast [[STRUCT_S]]* [[V]] to i8*
+// CHECK: [[R4:%[^,=]+]] = bitcast [[STRUCT_S]]* [[AGG_RESULT]] to i8*
// CHECK: [[R5:%[^,=]+]] = bitcast [[STRUCT_S]]* [[R3]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[R4]], i8* [[R5]], i32 12, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 [[R4]], i8* align 4 [[R5]], i32 12, i1 false)
// CHECK: [[VA2:%[^,=]+]] = bitcast i8** [[VA]] to i8*
// CHECK: call void @llvm.va_end(i8* [[VA2]])
-// CHECK: [[R6:%[^,=]+]] = bitcast [[STRUCT_S]]* %agg.result to i8*
-// CHECK: [[R7:%[^,=]+]] = bitcast [[STRUCT_S]]* [[V]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[R6]], i8* [[R7]], i32 12, i32 4, i1 false)
// CHECK: ret void
// CHECK: }
diff --git a/test/CodeGen/wchar-const.c b/test/CodeGen/wchar-const.c
index b461d605f6a9..91b14ecc1024 100644
--- a/test/CodeGen/wchar-const.c
+++ b/test/CodeGen/wchar-const.c
@@ -15,7 +15,7 @@ typedef __WCHAR_TYPE__ wchar_t;
// CHECK-DAR: private unnamed_addr constant [18 x i32] [i32 84,
-// CHECK-WIN: linkonce_odr unnamed_addr constant [18 x i16] [i16 84,
+// CHECK-WIN: linkonce_odr dso_local unnamed_addr constant [18 x i16] [i16 84,
extern void foo(const wchar_t* p);
int main (int argc, const char * argv[])
{
diff --git a/test/CodeGen/windows-itanium.c b/test/CodeGen/windows-itanium.c
index 7f0e7b135d2b..5bcd6dc710c1 100644
--- a/test/CodeGen/windows-itanium.c
+++ b/test/CodeGen/windows-itanium.c
@@ -8,8 +8,8 @@ int function() {
return 32;
}
-// CHECK-C: define i32 @function() {{.*}} {
-// CHECK-CXX: define i32 @_Z8functionv() {{.*}} {
+// CHECK-C: define dso_local i32 @function() {{.*}} {
+// CHECK-CXX: define dso_local i32 @_Z8functionv() {{.*}} {
// CHECK: ret i32 32
// CHECK: }
diff --git a/test/CodeGen/windows-on-arm-dllimport-dllexport.c b/test/CodeGen/windows-on-arm-dllimport-dllexport.c
index 4b2e29e430c6..a2ebbf195f79 100644
--- a/test/CodeGen/windows-on-arm-dllimport-dllexport.c
+++ b/test/CodeGen/windows-on-arm-dllimport-dllexport.c
@@ -17,9 +17,9 @@ void call_imported_function() {
}
// CHECK: @import_int = external dllimport global i32
-// CHECK: @export_int = common dllexport global i32 0, align 4
+// CHECK: @export_int = common dso_local dllexport global i32 0, align 4
-// CHECK: define dllexport arm_aapcs_vfpcc void @export_implemented_function()
+// CHECK: define dso_local dllexport arm_aapcs_vfpcc void @export_implemented_function()
// CHECK: declare dllimport arm_aapcs_vfpcc void @import_function(i32)
diff --git a/test/CodeGen/windows-struct-abi.c b/test/CodeGen/windows-struct-abi.c
index 1631f61db90c..5ffc4fad6473 100644
--- a/test/CodeGen/windows-struct-abi.c
+++ b/test/CodeGen/windows-struct-abi.c
@@ -6,11 +6,11 @@ struct f1 {
struct f1 return_f1(void) { while (1); }
-// CHECK: define i32 @return_f1()
+// CHECK: define dso_local i32 @return_f1()
void receive_f1(struct f1 a0) { }
-// CHECK: define void @receive_f1(float %a0.0)
+// CHECK: define dso_local void @receive_f1(float %a0.0)
struct f2 {
float f;
@@ -19,11 +19,11 @@ struct f2 {
struct f2 return_f2(void) { while (1); }
-// CHECK: define i64 @return_f2()
+// CHECK: define dso_local i64 @return_f2()
void receive_f2(struct f2 a0) { }
-// CHECK: define void @receive_f2(float %a0.0, float %a0.1)
+// CHECK: define dso_local void @receive_f2(float %a0.0, float %a0.1)
struct f4 {
float f;
@@ -34,9 +34,9 @@ struct f4 {
struct f4 return_f4(void) { while (1); }
-// CHECK: define void @return_f4(%struct.f4* noalias sret %agg.result)
+// CHECK: define dso_local void @return_f4(%struct.f4* noalias sret %agg.result)
void receive_f4(struct f4 a0) { }
-// CHECK: define void @receive_f4(float %a0.0, float %a0.1, float %a0.2, float %a0.3)
+// CHECK: define dso_local void @receive_f4(float %a0.0, float %a0.1, float %a0.2, float %a0.3)
diff --git a/test/CodeGen/windows-swiftcall.c b/test/CodeGen/windows-swiftcall.c
index f76b2fd3a40f..d8fdec47aa24 100644
--- a/test/CodeGen/windows-swiftcall.c
+++ b/test/CodeGen/windows-swiftcall.c
@@ -40,7 +40,7 @@ void test_context_error_1() {
float *error;
context_error_1(&x, &error);
}
-// CHECK-LABEL: define void @test_context_error_1()
+// CHECK-LABEL: define dso_local void @test_context_error_1()
// CHECK: [[X:%.*]] = alloca i32, align 4
// CHECK: [[ERROR:%.*]] = alloca float*, align 8
// CHECK: [[TEMP:%.*]] = alloca swifterror float*, align 8
@@ -97,11 +97,9 @@ typedef struct {
float f1;
} struct_1;
TEST(struct_1);
-// CHECK-LABEL: define swiftcc { i64, i64 } @return_struct_1() {{.*}}{
+// CHECK-LABEL: define dso_local swiftcc { i64, i64 } @return_struct_1() {{.*}}{
// CHECK: [[RET:%.*]] = alloca [[STRUCT1:%.*]], align 4
-// CHECK: [[VAR:%.*]] = alloca [[STRUCT1]], align 4
// CHECK: call void @llvm.memset
-// CHECK: call void @llvm.memcpy
// CHECK: [[CAST:%.*]] = bitcast [[STRUCT1]]* %retval to { i64, i64 }*
// CHECK: [[GEP0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
// CHECK: [[T0:%.*]] = load i64, i64* [[GEP0]], align 4
@@ -111,7 +109,7 @@ TEST(struct_1);
// CHECK: [[R1:%.*]] = insertvalue { i64, i64 } [[R0]], i64 [[T1]], 1
// CHECK: ret { i64, i64 } [[R1]]
// CHECK: }
-// CHECK-LABEL: define swiftcc void @take_struct_1(i64, i64) {{.*}}{
+// CHECK-LABEL: define dso_local swiftcc void @take_struct_1(i64, i64) {{.*}}{
// CHECK: [[V:%.*]] = alloca [[STRUCT1:%.*]], align 4
// CHECK: [[CAST:%.*]] = bitcast [[STRUCT1]]* [[V]] to { i64, i64 }*
// CHECK: [[GEP0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
@@ -120,7 +118,7 @@ TEST(struct_1);
// CHECK: store i64 %1, i64* [[GEP1]], align 4
// CHECK: ret void
// CHECK: }
-// CHECK-LABEL: define void @test_struct_1() {{.*}}{
+// CHECK-LABEL: define dso_local void @test_struct_1() {{.*}}{
// CHECK: [[AGG:%.*]] = alloca [[STRUCT1:%.*]], align 4
// CHECK: [[RET:%.*]] = call swiftcc { i64, i64 } @return_struct_1()
// CHECK: [[CAST:%.*]] = bitcast [[STRUCT1]]* [[AGG]] to { i64, i64 }*
@@ -147,14 +145,10 @@ typedef struct {
float f1;
} struct_2;
TEST(struct_2);
-// CHECK-LABEL: define swiftcc { i64, i64 } @return_struct_2() {{.*}}{
+// CHECK-LABEL: define dso_local swiftcc { i64, i64 } @return_struct_2() {{.*}}{
// CHECK: [[RET:%.*]] = alloca [[STRUCT2_TYPE]], align 4
-// CHECK: [[VAR:%.*]] = alloca [[STRUCT2_TYPE]], align 4
-// CHECK: [[CASTVAR:%.*]] = bitcast {{.*}} [[VAR]]
+// CHECK: [[CASTVAR:%.*]] = bitcast {{.*}} [[RET]]
// CHECK: call void @llvm.memcpy{{.*}}({{.*}}[[CASTVAR]], {{.*}}[[STRUCT2_RESULT]]
-// CHECK: [[CASTRET:%.*]] = bitcast {{.*}} [[RET]]
-// CHECK: [[CASTVAR:%.*]] = bitcast {{.*}} [[VAR]]
-// CHECK: call void @llvm.memcpy{{.*}}({{.*}}[[CASTRET]], {{.*}}[[CASTVAR]]
// CHECK: [[CAST:%.*]] = bitcast [[STRUCT2_TYPE]]* [[RET]] to { i64, i64 }*
// CHECK: [[GEP0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
// CHECK: [[T0:%.*]] = load i64, i64* [[GEP0]], align 4
@@ -164,7 +158,7 @@ TEST(struct_2);
// CHECK: [[R1:%.*]] = insertvalue { i64, i64 } [[R0]], i64 [[T1]], 1
// CHECK: ret { i64, i64 } [[R1]]
// CHECK: }
-// CHECK-LABEL: define swiftcc void @take_struct_2(i64, i64) {{.*}}{
+// CHECK-LABEL: define dso_local swiftcc void @take_struct_2(i64, i64) {{.*}}{
// CHECK: [[V:%.*]] = alloca [[STRUCT:%.*]], align 4
// CHECK: [[CAST:%.*]] = bitcast [[STRUCT]]* [[V]] to { i64, i64 }*
// CHECK: [[GEP0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
@@ -173,7 +167,7 @@ TEST(struct_2);
// CHECK: store i64 %1, i64* [[GEP1]], align 4
// CHECK: ret void
// CHECK: }
-// CHECK-LABEL: define void @test_struct_2() {{.*}} {
+// CHECK-LABEL: define dso_local void @test_struct_2() {{.*}} {
// CHECK: [[TMP:%.*]] = alloca [[STRUCT2_TYPE]], align 4
// CHECK: [[CALL:%.*]] = call swiftcc { i64, i64 } @return_struct_2()
// CHECK: [[CAST_TMP:%.*]] = bitcast [[STRUCT2_TYPE]]* [[TMP]] to { i64, i64 }*
@@ -203,27 +197,23 @@ typedef struct {
__attribute__((packed)) float f;
} struct_misaligned_1;
TEST(struct_misaligned_1)
-// CHECK-LABEL: define swiftcc i64 @return_struct_misaligned_1()
+// CHECK-LABEL: define dso_local swiftcc i64 @return_struct_misaligned_1()
// CHECK: [[RET:%.*]] = alloca [[STRUCT:%.*]], align 1
-// CHECK: [[RES:%.*]] = alloca [[STRUCT]], align 1
-// CHECK: [[CAST:%.*]] = bitcast [[STRUCT]]* [[RES]] to i8*
-// CHECK: call void @llvm.memset{{.*}}(i8* [[CAST]], i8 0, i64 5
-// CHECK: [[CASTRET:%.*]] = bitcast [[STRUCT]]* [[RET]] to i8*
-// CHECK: [[CASTRES:%.*]] = bitcast [[STRUCT]]* [[RES]] to i8*
-// CHECK: call void @llvm.memcpy{{.*}}(i8* [[CASTRET]], i8* [[CASTRES]], i64 5
+// CHECK: [[CAST:%.*]] = bitcast [[STRUCT]]* [[RET]] to i8*
+// CHECK: call void @llvm.memset{{.*}}(i8* align 1 [[CAST]], i8 0, i64 5
// CHECK: [[CAST:%.*]] = bitcast [[STRUCT]]* [[RET]] to { i64 }*
// CHECK: [[GEP:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[CAST]], i32 0, i32 0
// CHECK: [[R0:%.*]] = load i64, i64* [[GEP]], align 1
// CHECK: ret i64 [[R0]]
// CHECK:}
-// CHECK-LABEL: define swiftcc void @take_struct_misaligned_1(i64) {{.*}}{
+// CHECK-LABEL: define dso_local swiftcc void @take_struct_misaligned_1(i64) {{.*}}{
// CHECK: [[V:%.*]] = alloca [[STRUCT:%.*]], align 1
// CHECK: [[CAST:%.*]] = bitcast [[STRUCT]]* [[V]] to { i64 }*
// CHECK: [[GEP:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[CAST]], i32 0, i32 0
// CHECK: store i64 %0, i64* [[GEP]], align 1
// CHECK: ret void
// CHECK: }
-// CHECK: define void @test_struct_misaligned_1() {{.*}}{
+// CHECK: define dso_local void @test_struct_misaligned_1() {{.*}}{
// CHECK: [[AGG:%.*]] = alloca [[STRUCT:%.*]], align 1
// CHECK: [[CALL:%.*]] = call swiftcc i64 @return_struct_misaligned_1()
// CHECK: [[T0:%.*]] = bitcast [[STRUCT]]* [[AGG]] to { i64 }*
@@ -256,26 +246,22 @@ typedef union {
double d;
} union_het_fp;
TEST(union_het_fp)
-// CHECK-LABEL: define swiftcc i64 @return_union_het_fp()
+// CHECK-LABEL: define dso_local swiftcc i64 @return_union_het_fp()
// CHECK: [[RET:%.*]] = alloca [[UNION:%.*]], align 8
-// CHECK: [[RES:%.*]] = alloca [[UNION]], align 8
-// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[RES]] to i8*
-// CHECK: call void @llvm.memcpy{{.*}}(i8* [[CAST]]
-// CHECK: [[CASTRET:%.*]] = bitcast [[UNION]]* [[RET]] to i8*
-// CHECK: [[CASTRES:%.*]] = bitcast [[UNION]]* [[RES]] to i8*
-// CHECK: call void @llvm.memcpy{{.*}}(i8* [[CASTRET]], i8* [[CASTRES]]
+// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[RET]] to i8*
+// CHECK: call void @llvm.memcpy{{.*}}(i8* align {{[0-9]+}} [[CAST]]
// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[RET]] to { i64 }*
// CHECK: [[GEP:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[CAST]], i32 0, i32 0
// CHECK: [[R0:%.*]] = load i64, i64* [[GEP]], align 8
// CHECK: ret i64 [[R0]]
-// CHECK-LABEL: define swiftcc void @take_union_het_fp(i64) {{.*}}{
+// CHECK-LABEL: define dso_local swiftcc void @take_union_het_fp(i64) {{.*}}{
// CHECK: [[V:%.*]] = alloca [[UNION:%.*]], align 8
// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[V]] to { i64 }*
// CHECK: [[GEP:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[CAST]], i32 0, i32 0
// CHECK: store i64 %0, i64* [[GEP]], align 8
// CHECK: ret void
// CHECK: }
-// CHECK-LABEL: define void @test_union_het_fp() {{.*}}{
+// CHECK-LABEL: define dso_local void @test_union_het_fp() {{.*}}{
// CHECK: [[AGG:%.*]] = alloca [[UNION:%.*]], align 8
// CHECK: [[CALL:%.*]] = call swiftcc i64 @return_union_het_fp()
// CHECK: [[T0:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64 }*
@@ -294,7 +280,7 @@ typedef union {
float f2;
} union_hom_fp;
TEST(union_hom_fp)
-// CHECK-LABEL: define void @test_union_hom_fp()
+// CHECK-LABEL: define dso_local void @test_union_hom_fp()
// CHECK: [[TMP:%.*]] = alloca [[REC:%.*]], align 4
// CHECK: [[CALL:%.*]] = call [[SWIFTCC]] float @return_union_hom_fp()
// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP]] to [[AGG:{ float }]]*
@@ -311,7 +297,7 @@ typedef union {
float4 fv2;
} union_hom_fp_partial;
TEST(union_hom_fp_partial)
-// CHECK: define void @test_union_hom_fp_partial()
+// CHECK: define dso_local void @test_union_hom_fp_partial()
// CHECK: [[AGG:%.*]] = alloca [[UNION:%.*]], align 16
// CHECK: [[CALL:%.*]] = call swiftcc { i64, i64 } @return_union_hom_fp_partial()
// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, i64 }*
@@ -335,7 +321,7 @@ typedef union {
float4 fv2;
} union_het_fpv_partial;
TEST(union_het_fpv_partial)
-// CHECK-LABEL: define void @test_union_het_fpv_partial()
+// CHECK-LABEL: define dso_local void @test_union_het_fpv_partial()
// CHECK: [[AGG:%.*]] = alloca [[UNION:%.*]], align 16
// CHECK: [[CALL:%.*]] = call swiftcc { i64, i64 } @return_union_het_fpv_partial()
// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, i64 }*
@@ -385,7 +371,7 @@ TEST(int8)
// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
// CHECK: store <4 x i32> %1, <4 x i32>* [[T0]], align
// CHECK: ret void
-// CHECK-LABEL: define void @test_int8()
+// CHECK-LABEL: define dso_local void @test_int8()
// CHECK: [[TMP1:%.*]] = alloca [[REC]], align
// CHECK: [[TMP2:%.*]] = alloca [[REC]], align
// CHECK: [[CALL:%.*]] = call [[SWIFTCC]] [[UAGG]] @return_int8()
@@ -429,7 +415,7 @@ TEST(int5)
// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
// CHECK: store i32 %1, i32* [[T0]], align
// CHECK: ret void
-// CHECK-LABEL: define void @test_int5()
+// CHECK-LABEL: define dso_local void @test_int5()
// CHECK: [[TMP1:%.*]] = alloca [[REC]], align
// CHECK: [[TMP2:%.*]] = alloca [[REC]], align
// CHECK: [[CALL:%.*]] = call [[SWIFTCC]] [[UAGG]] @return_int5()
@@ -455,4 +441,4 @@ typedef struct {
int3 v __attribute__((packed));
} misaligned_int3;
TEST(misaligned_int3)
-// CHECK-LABEL: define swiftcc void @take_misaligned_int3(i64, i64)
+// CHECK-LABEL: define dso_local swiftcc void @take_misaligned_int3(i64, i64)
diff --git a/test/CodeGen/wmemcmp.c b/test/CodeGen/wmemcmp.c
new file mode 100644
index 000000000000..ad0886192bcf
--- /dev/null
+++ b/test/CodeGen/wmemcmp.c
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 %s -triple x86_64-pc-win32 -emit-llvm -o - | FileCheck %s
+
+typedef __SIZE_TYPE__ size_t;
+typedef __WCHAR_TYPE__ wchar_t;
+
+int wmemcmp_test(const wchar_t *s1, const wchar_t *s2, size_t n) {
+ // CHECK: [[S1:%.*]] = load
+ // CHECK: [[S2:%.*]] = load
+ // CHECK: [[N:%.*]] = load
+ // CHECK: [[N0:%.*]] = icmp eq i64 [[N]], 0
+ // CHECK: br i1 [[N0]], label %[[EXIT:.*]], label %[[GT:.*]]
+
+ // CHECK: [[GT]]:
+ // CHECK: [[S1P:%.*]] = phi i16* [ [[S1]], %[[ENTRY:.*]] ], [ [[S1N:.*]], %[[NEXT:.*]] ]
+ // CHECK: [[S2P:%.*]] = phi i16* [ [[S2]], %[[ENTRY]] ], [ [[S2N:.*]], %[[NEXT]] ]
+ // CHECK: [[NP:%.*]] = phi i64 [ [[N]], %[[ENTRY]] ], [ [[NN:.*]], %[[NEXT]] ]
+ // CHECK: [[S1L:%.*]] = load i16, i16* [[S1P]], align 2
+ // CHECK: [[S2L:%.*]] = load i16, i16* [[S2P]], align 2
+ // CHECK: [[CMPGT:%.*]] = icmp ugt i16 [[S1L]], [[S2L]]
+ // CHECK: br i1 [[CMPGT]], label %[[EXIT]], label %[[LT:.*]]
+
+ // CHECK: [[LT]]:
+ // CHECK: [[CMPLT:%.*]] = icmp ult i16 [[S1L]], [[S2L]]
+ // CHECK: br i1 [[CMPLT]], label %[[EXIT]], label %[[NEXT:.*]]
+
+ // CHECK: [[NEXT]]:
+ // CHECK: [[S1N]] = getelementptr inbounds i16, i16* [[S1P]], i32 1
+ // CHECK: [[S2N]] = getelementptr inbounds i16, i16* [[S2P]], i32 1
+ // CHECK: [[NN]] = sub i64 [[NP]], 1
+ // CHECK: [[NN0:%.*]] = icmp eq i64 [[NN]], 0
+ // CHECK: br i1 [[NN0]], label %[[EXIT]], label %[[GT]]
+ //
+ // CHECK: [[EXIT]]:
+ // CHECK: [[RV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ 1, %[[GT]] ], [ -1, %[[LT]] ], [ 0, %[[NEXT]] ]
+ // CHECK: ret i32 [[RV]]
+ return __builtin_wmemcmp(s1, s2, n);
+}
diff --git a/test/CodeGen/x86-atomic-long_double.c b/test/CodeGen/x86-atomic-long_double.c
index 9857c67592f2..130ff45c0346 100644
--- a/test/CodeGen/x86-atomic-long_double.c
+++ b/test/CodeGen/x86-atomic-long_double.c
@@ -15,12 +15,12 @@ long double testinc(_Atomic long double *addr) {
// CHECK: [[OLD_VALUE:%.+]] = phi x86_fp80 [ [[LD_VALUE]], %{{.+}} ], [ [[LD_VALUE:%.+]], %[[ATOMIC_OP]] ]
// CHECK: [[INC_VALUE:%.+]] = fadd x86_fp80 [[OLD_VALUE]],
// CHECK: [[OLD_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR:%.+]] to i8*
- // CHECK: call void @llvm.memset.p0i8.i64(i8* [[OLD_VALUE_VOID_ADDR]], i8 0, i64 16, i32 16, i1 false)
+ // CHECK: call void @llvm.memset.p0i8.i64(i8* align 16 [[OLD_VALUE_VOID_ADDR]], i8 0, i64 16, i1 false)
// CHECK: store x86_fp80 [[OLD_VALUE]], x86_fp80* [[OLD_VALUE_ADDR]], align 16
// CHECK: [[OLD_INT_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR]] to i128*
// CHECK: [[OLD_INT:%.+]] = load i128, i128* [[OLD_INT_ADDR]], align 16
// CHECK: [[NEW_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[NEW_VALUE_ADDR:%.+]] to i8*
- // CHECK: call void @llvm.memset.p0i8.i64(i8* [[NEW_VALUE_VOID_ADDR]], i8 0, i64 16, i32 16, i1 false)
+ // CHECK: call void @llvm.memset.p0i8.i64(i8* align 16 [[NEW_VALUE_VOID_ADDR]], i8 0, i64 16, i1 false)
// CHECK: store x86_fp80 [[INC_VALUE]], x86_fp80* [[NEW_VALUE_ADDR]], align 16
// CHECK: [[NEW_INT_ADDR:%.+]] = bitcast x86_fp80* [[NEW_VALUE_ADDR]] to i128*
// CHECK: [[NEW_INT:%.+]] = load i128, i128* [[NEW_INT_ADDR]], align 16
@@ -46,10 +46,10 @@ long double testinc(_Atomic long double *addr) {
// CHECK32: [[OLD_VALUE:%.+]] = phi x86_fp80 [ [[LD_VALUE]], %{{.+}} ], [ [[LD_VALUE:%.+]], %[[ATOMIC_OP]] ]
// CHECK32: [[INC_VALUE:%.+]] = fadd x86_fp80 [[OLD_VALUE]],
// CHECK32: [[OLD_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR:%.+]] to i8*
- // CHECK32: call void @llvm.memset.p0i8.i64(i8* [[OLD_VALUE_VOID_ADDR]], i8 0, i64 12, i32 4, i1 false)
+ // CHECK32: call void @llvm.memset.p0i8.i64(i8* align 4 [[OLD_VALUE_VOID_ADDR]], i8 0, i64 12, i1 false)
// CHECK32: store x86_fp80 [[OLD_VALUE]], x86_fp80* [[OLD_VALUE_ADDR]], align 4
// CHECK32: [[DESIRED_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[DESIRED_VALUE_ADDR:%.+]] to i8*
- // CHECK32: call void @llvm.memset.p0i8.i64(i8* [[DESIRED_VALUE_VOID_ADDR]], i8 0, i64 12, i32 4, i1 false)
+ // CHECK32: call void @llvm.memset.p0i8.i64(i8* align 4 [[DESIRED_VALUE_VOID_ADDR]], i8 0, i64 12, i1 false)
// CHECK32: store x86_fp80 [[INC_VALUE]], x86_fp80* [[DESIRED_VALUE_ADDR]], align 4
// CHECK32: [[OBJ:%.+]] = bitcast x86_fp80* [[ADDR]] to i8*
// CHECK32: [[EXPECTED:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR]] to i8*
@@ -77,12 +77,12 @@ long double testdec(_Atomic long double *addr) {
// CHECK: [[OLD_VALUE:%.+]] = phi x86_fp80 [ [[ORIG_LD_VALUE]], %{{.+}} ], [ [[LD_VALUE:%.+]], %[[ATOMIC_OP]] ]
// CHECK: [[DEC_VALUE:%.+]] = fadd x86_fp80 [[OLD_VALUE]],
// CHECK: [[OLD_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR:%.+]] to i8*
- // CHECK: call void @llvm.memset.p0i8.i64(i8* [[OLD_VALUE_VOID_ADDR]], i8 0, i64 16, i32 16, i1 false)
+ // CHECK: call void @llvm.memset.p0i8.i64(i8* align 16 [[OLD_VALUE_VOID_ADDR]], i8 0, i64 16, i1 false)
// CHECK: store x86_fp80 [[OLD_VALUE]], x86_fp80* [[OLD_VALUE_ADDR]], align 16
// CHECK: [[OLD_INT_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR]] to i128*
// CHECK: [[OLD_INT:%.+]] = load i128, i128* [[OLD_INT_ADDR]], align 16
// CHECK: [[NEW_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[NEW_VALUE_ADDR:%.+]] to i8*
- // CHECK: call void @llvm.memset.p0i8.i64(i8* [[NEW_VALUE_VOID_ADDR]], i8 0, i64 16, i32 16, i1 false)
+ // CHECK: call void @llvm.memset.p0i8.i64(i8* align 16 [[NEW_VALUE_VOID_ADDR]], i8 0, i64 16, i1 false)
// CHECK: store x86_fp80 [[DEC_VALUE]], x86_fp80* [[NEW_VALUE_ADDR]], align 16
// CHECK: [[NEW_INT_ADDR:%.+]] = bitcast x86_fp80* [[NEW_VALUE_ADDR]] to i128*
// CHECK: [[NEW_INT:%.+]] = load i128, i128* [[NEW_INT_ADDR]], align 16
@@ -108,10 +108,10 @@ long double testdec(_Atomic long double *addr) {
// CHECK32: [[OLD_VALUE:%.+]] = phi x86_fp80 [ [[ORIG_LD_VALUE]], %{{.+}} ], [ [[LD_VALUE:%.+]], %[[ATOMIC_OP]] ]
// CHECK32: [[DEC_VALUE:%.+]] = fadd x86_fp80 [[OLD_VALUE]],
// CHECK32: [[OLD_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR:%.+]] to i8*
- // CHECK32: call void @llvm.memset.p0i8.i64(i8* [[OLD_VALUE_VOID_ADDR]], i8 0, i64 12, i32 4, i1 false)
+ // CHECK32: call void @llvm.memset.p0i8.i64(i8* align 4 [[OLD_VALUE_VOID_ADDR]], i8 0, i64 12, i1 false)
// CHECK32: store x86_fp80 [[OLD_VALUE]], x86_fp80* [[OLD_VALUE_ADDR]], align 4
// CHECK32: [[DESIRED_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[DESIRED_VALUE_ADDR:%.+]] to i8*
- // CHECK32: call void @llvm.memset.p0i8.i64(i8* [[DESIRED_VALUE_VOID_ADDR]], i8 0, i64 12, i32 4, i1 false)
+ // CHECK32: call void @llvm.memset.p0i8.i64(i8* align 4 [[DESIRED_VALUE_VOID_ADDR]], i8 0, i64 12, i1 false)
// CHECK32: store x86_fp80 [[DEC_VALUE]], x86_fp80* [[DESIRED_VALUE_ADDR]], align 4
// CHECK32: [[OBJ:%.+]] = bitcast x86_fp80* [[ADDR]] to i8*
// CHECK32: [[EXPECTED:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR]] to i8*
@@ -140,12 +140,12 @@ long double testcompassign(_Atomic long double *addr) {
// CHECK: [[OLD_VALUE:%.+]] = phi x86_fp80 [ [[LD_VALUE]], %{{.+}} ], [ [[LD_VALUE:%.+]], %[[ATOMIC_OP]] ]
// CHECK: [[SUB_VALUE:%.+]] = fsub x86_fp80 [[OLD_VALUE]],
// CHECK: [[OLD_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR:%.+]] to i8*
- // CHECK: call void @llvm.memset.p0i8.i64(i8* [[OLD_VALUE_VOID_ADDR]], i8 0, i64 16, i32 16, i1 false)
+ // CHECK: call void @llvm.memset.p0i8.i64(i8* align 16 [[OLD_VALUE_VOID_ADDR]], i8 0, i64 16, i1 false)
// CHECK: store x86_fp80 [[OLD_VALUE]], x86_fp80* [[OLD_VALUE_ADDR]], align 16
// CHECK: [[OLD_INT_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR]] to i128*
// CHECK: [[OLD_INT:%.+]] = load i128, i128* [[OLD_INT_ADDR]], align 16
// CHECK: [[NEW_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[NEW_VALUE_ADDR:%.+]] to i8*
- // CHECK: call void @llvm.memset.p0i8.i64(i8* [[NEW_VALUE_VOID_ADDR]], i8 0, i64 16, i32 16, i1 false)
+ // CHECK: call void @llvm.memset.p0i8.i64(i8* align 16 [[NEW_VALUE_VOID_ADDR]], i8 0, i64 16, i1 false)
// CHECK: store x86_fp80 [[SUB_VALUE]], x86_fp80* [[NEW_VALUE_ADDR]], align 16
// CHECK: [[NEW_INT_ADDR:%.+]] = bitcast x86_fp80* [[NEW_VALUE_ADDR]] to i128*
// CHECK: [[NEW_INT:%.+]] = load i128, i128* [[NEW_INT_ADDR]], align 16
@@ -177,10 +177,10 @@ long double testcompassign(_Atomic long double *addr) {
// CHECK32: [[OLD_VALUE:%.+]] = phi x86_fp80 [ [[LD_VALUE]], %{{.+}} ], [ [[LD_VALUE:%.+]], %[[ATOMIC_OP]] ]
// CHECK32: [[INC_VALUE:%.+]] = fsub x86_fp80 [[OLD_VALUE]],
// CHECK32: [[OLD_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR:%.+]] to i8*
- // CHECK32: call void @llvm.memset.p0i8.i64(i8* [[OLD_VALUE_VOID_ADDR]], i8 0, i64 12, i32 4, i1 false)
+ // CHECK32: call void @llvm.memset.p0i8.i64(i8* align 4 [[OLD_VALUE_VOID_ADDR]], i8 0, i64 12, i1 false)
// CHECK32: store x86_fp80 [[OLD_VALUE]], x86_fp80* [[OLD_VALUE_ADDR]], align 4
// CHECK32: [[DESIRED_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[DESIRED_VALUE_ADDR:%.+]] to i8*
- // CHECK32: call void @llvm.memset.p0i8.i64(i8* [[DESIRED_VALUE_VOID_ADDR]], i8 0, i64 12, i32 4, i1 false)
+ // CHECK32: call void @llvm.memset.p0i8.i64(i8* align 4 [[DESIRED_VALUE_VOID_ADDR]], i8 0, i64 12, i1 false)
// CHECK32: store x86_fp80 [[INC_VALUE]], x86_fp80* [[DESIRED_VALUE_ADDR]], align 4
// CHECK32: [[OBJ:%.+]] = bitcast x86_fp80* [[ADDR]] to i8*
// CHECK32: [[EXPECTED:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR]] to i8*
@@ -203,7 +203,7 @@ long double testassign(_Atomic long double *addr) {
// CHECK: store x86_fp80* %{{.+}}, x86_fp80** [[ADDR_ADDR:%.+]], align 8
// CHECK: [[ADDR:%.+]] = load x86_fp80*, x86_fp80** [[ADDR_ADDR]], align 8
// CHECK: [[STORE_TEMP_VOID_PTR:%.+]] = bitcast x86_fp80* [[STORE_TEMP_PTR:%.+]] to i8*
- // CHECK: call void @llvm.memset.p0i8.i64(i8* [[STORE_TEMP_VOID_PTR]], i8 0, i64 16, i32 16, i1 false)
+ // CHECK: call void @llvm.memset.p0i8.i64(i8* align 16 [[STORE_TEMP_VOID_PTR]], i8 0, i64 16, i1 false)
// CHECK: store x86_fp80 {{.+}}, x86_fp80* [[STORE_TEMP_PTR]], align 16
// CHECK: [[STORE_TEMP_INT_PTR:%.+]] = bitcast x86_fp80* [[STORE_TEMP_PTR]] to i128*
// CHECK: [[STORE_TEMP_INT:%.+]] = load i128, i128* [[STORE_TEMP_INT_PTR]], align 16
@@ -213,7 +213,7 @@ long double testassign(_Atomic long double *addr) {
// CHECK32: store x86_fp80* %{{.+}}, x86_fp80** [[ADDR_ADDR:%.+]], align 4
// CHECK32: [[ADDR:%.+]] = load x86_fp80*, x86_fp80** [[ADDR_ADDR]], align 4
// CHECK32: [[STORE_TEMP_VOID_PTR:%.+]] = bitcast x86_fp80* [[STORE_TEMP_PTR:%.+]] to i8*
- // CHECK32: call void @llvm.memset.p0i8.i64(i8* [[STORE_TEMP_VOID_PTR]], i8 0, i64 12, i32 4, i1 false)
+ // CHECK32: call void @llvm.memset.p0i8.i64(i8* align 4 [[STORE_TEMP_VOID_PTR]], i8 0, i64 12, i1 false)
// CHECK32: store x86_fp80 {{.+}}, x86_fp80* [[STORE_TEMP_PTR]], align 4
// CHECK32: [[ADDR_VOID:%.+]] = bitcast x86_fp80* [[ADDR]] to i8*
// CHECK32: [[STORE_TEMP_VOID_PTR:%.+]] = bitcast x86_fp80* [[STORE_TEMP_PTR]] to i8*
@@ -250,12 +250,12 @@ long double test_volatile_inc(volatile _Atomic long double *addr) {
// CHECK: [[OLD_VALUE:%.+]] = phi x86_fp80 [ [[LD_VALUE]], %{{.+}} ], [ [[LD_VALUE:%.+]], %[[ATOMIC_OP]] ]
// CHECK: [[INC_VALUE:%.+]] = fadd x86_fp80 [[OLD_VALUE]],
// CHECK: [[OLD_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR:%.+]] to i8*
- // CHECK: call void @llvm.memset.p0i8.i64(i8* [[OLD_VALUE_VOID_ADDR]], i8 0, i64 16, i32 16, i1 false)
+ // CHECK: call void @llvm.memset.p0i8.i64(i8* align 16 [[OLD_VALUE_VOID_ADDR]], i8 0, i64 16, i1 false)
// CHECK: store x86_fp80 [[OLD_VALUE]], x86_fp80* [[OLD_VALUE_ADDR]], align 16
// CHECK: [[OLD_INT_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR]] to i128*
// CHECK: [[OLD_INT:%.+]] = load i128, i128* [[OLD_INT_ADDR]], align 16
// CHECK: [[NEW_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[NEW_VALUE_ADDR:%.+]] to i8*
- // CHECK: call void @llvm.memset.p0i8.i64(i8* [[NEW_VALUE_VOID_ADDR]], i8 0, i64 16, i32 16, i1 false)
+ // CHECK: call void @llvm.memset.p0i8.i64(i8* align 16 [[NEW_VALUE_VOID_ADDR]], i8 0, i64 16, i1 false)
// CHECK: store x86_fp80 [[INC_VALUE]], x86_fp80* [[NEW_VALUE_ADDR]], align 16
// CHECK: [[NEW_INT_ADDR:%.+]] = bitcast x86_fp80* [[NEW_VALUE_ADDR]] to i128*
// CHECK: [[NEW_INT:%.+]] = load i128, i128* [[NEW_INT_ADDR]], align 16
@@ -281,10 +281,10 @@ long double test_volatile_inc(volatile _Atomic long double *addr) {
// CHECK32: [[OLD_VALUE:%.+]] = phi x86_fp80 [ [[LD_VALUE]], %{{.+}} ], [ [[LD_VALUE:%.+]], %[[ATOMIC_OP]] ]
// CHECK32: [[INC_VALUE:%.+]] = fadd x86_fp80 [[OLD_VALUE]],
// CHECK32: [[OLD_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR:%.+]] to i8*
- // CHECK32: call void @llvm.memset.p0i8.i64(i8* [[OLD_VALUE_VOID_ADDR]], i8 0, i64 12, i32 4, i1 false)
+ // CHECK32: call void @llvm.memset.p0i8.i64(i8* align 4 [[OLD_VALUE_VOID_ADDR]], i8 0, i64 12, i1 false)
// CHECK32: store x86_fp80 [[OLD_VALUE]], x86_fp80* [[OLD_VALUE_ADDR]], align 4
// CHECK32: [[DESIRED_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[DESIRED_VALUE_ADDR:%.+]] to i8*
- // CHECK32: call void @llvm.memset.p0i8.i64(i8* [[DESIRED_VALUE_VOID_ADDR]], i8 0, i64 12, i32 4, i1 false)
+ // CHECK32: call void @llvm.memset.p0i8.i64(i8* align 4 [[DESIRED_VALUE_VOID_ADDR]], i8 0, i64 12, i1 false)
// CHECK32: store x86_fp80 [[INC_VALUE]], x86_fp80* [[DESIRED_VALUE_ADDR]], align 4
// CHECK32: [[OBJ:%.+]] = bitcast x86_fp80* [[ADDR]] to i8*
// CHECK32: [[EXPECTED:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR]] to i8*
@@ -311,12 +311,12 @@ long double test_volatile_dec(volatile _Atomic long double *addr) {
// CHECK: [[OLD_VALUE:%.+]] = phi x86_fp80 [ [[ORIG_LD_VALUE]], %{{.+}} ], [ [[LD_VALUE:%.+]], %[[ATOMIC_OP]] ]
// CHECK: [[DEC_VALUE:%.+]] = fadd x86_fp80 [[OLD_VALUE]],
// CHECK: [[OLD_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR:%.+]] to i8*
- // CHECK: call void @llvm.memset.p0i8.i64(i8* [[OLD_VALUE_VOID_ADDR]], i8 0, i64 16, i32 16, i1 false)
+ // CHECK: call void @llvm.memset.p0i8.i64(i8* align 16 [[OLD_VALUE_VOID_ADDR]], i8 0, i64 16, i1 false)
// CHECK: store x86_fp80 [[OLD_VALUE]], x86_fp80* [[OLD_VALUE_ADDR]], align 16
// CHECK: [[OLD_INT_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR]] to i128*
// CHECK: [[OLD_INT:%.+]] = load i128, i128* [[OLD_INT_ADDR]], align 16
// CHECK: [[NEW_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[NEW_VALUE_ADDR:%.+]] to i8*
- // CHECK: call void @llvm.memset.p0i8.i64(i8* [[NEW_VALUE_VOID_ADDR]], i8 0, i64 16, i32 16, i1 false)
+ // CHECK: call void @llvm.memset.p0i8.i64(i8* align 16 [[NEW_VALUE_VOID_ADDR]], i8 0, i64 16, i1 false)
// CHECK: store x86_fp80 [[DEC_VALUE]], x86_fp80* [[NEW_VALUE_ADDR]], align 16
// CHECK: [[NEW_INT_ADDR:%.+]] = bitcast x86_fp80* [[NEW_VALUE_ADDR]] to i128*
// CHECK: [[NEW_INT:%.+]] = load i128, i128* [[NEW_INT_ADDR]], align 16
@@ -342,10 +342,10 @@ long double test_volatile_dec(volatile _Atomic long double *addr) {
// CHECK32: [[OLD_VALUE:%.+]] = phi x86_fp80 [ [[ORIG_LD_VALUE]], %{{.+}} ], [ [[LD_VALUE:%.+]], %[[ATOMIC_OP]] ]
// CHECK32: [[DEC_VALUE:%.+]] = fadd x86_fp80 [[OLD_VALUE]],
// CHECK32: [[OLD_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR:%.+]] to i8*
- // CHECK32: call void @llvm.memset.p0i8.i64(i8* [[OLD_VALUE_VOID_ADDR]], i8 0, i64 12, i32 4, i1 false)
+ // CHECK32: call void @llvm.memset.p0i8.i64(i8* align 4 [[OLD_VALUE_VOID_ADDR]], i8 0, i64 12, i1 false)
// CHECK32: store x86_fp80 [[OLD_VALUE]], x86_fp80* [[OLD_VALUE_ADDR]], align 4
// CHECK32: [[DESIRED_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[DESIRED_VALUE_ADDR:%.+]] to i8*
- // CHECK32: call void @llvm.memset.p0i8.i64(i8* [[DESIRED_VALUE_VOID_ADDR]], i8 0, i64 12, i32 4, i1 false)
+ // CHECK32: call void @llvm.memset.p0i8.i64(i8* align 4 [[DESIRED_VALUE_VOID_ADDR]], i8 0, i64 12, i1 false)
// CHECK32: store x86_fp80 [[DEC_VALUE]], x86_fp80* [[DESIRED_VALUE_ADDR]], align 4
// CHECK32: [[OBJ:%.+]] = bitcast x86_fp80* [[ADDR]] to i8*
// CHECK32: [[EXPECTED:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR]] to i8*
@@ -373,12 +373,12 @@ long double test_volatile_compassign(volatile _Atomic long double *addr) {
// CHECK: [[OLD_VALUE:%.+]] = phi x86_fp80 [ [[LD_VALUE]], %{{.+}} ], [ [[LD_VALUE:%.+]], %[[ATOMIC_OP]] ]
// CHECK: [[SUB_VALUE:%.+]] = fsub x86_fp80 [[OLD_VALUE]],
// CHECK: [[OLD_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR:%.+]] to i8*
- // CHECK: call void @llvm.memset.p0i8.i64(i8* [[OLD_VALUE_VOID_ADDR]], i8 0, i64 16, i32 16, i1 false)
+ // CHECK: call void @llvm.memset.p0i8.i64(i8* align 16 [[OLD_VALUE_VOID_ADDR]], i8 0, i64 16, i1 false)
// CHECK: store x86_fp80 [[OLD_VALUE]], x86_fp80* [[OLD_VALUE_ADDR]], align 16
// CHECK: [[OLD_INT_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR]] to i128*
// CHECK: [[OLD_INT:%.+]] = load i128, i128* [[OLD_INT_ADDR]], align 16
// CHECK: [[NEW_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[NEW_VALUE_ADDR:%.+]] to i8*
- // CHECK: call void @llvm.memset.p0i8.i64(i8* [[NEW_VALUE_VOID_ADDR]], i8 0, i64 16, i32 16, i1 false)
+ // CHECK: call void @llvm.memset.p0i8.i64(i8* align 16 [[NEW_VALUE_VOID_ADDR]], i8 0, i64 16, i1 false)
// CHECK: store x86_fp80 [[SUB_VALUE]], x86_fp80* [[NEW_VALUE_ADDR]], align 16
// CHECK: [[NEW_INT_ADDR:%.+]] = bitcast x86_fp80* [[NEW_VALUE_ADDR]] to i128*
// CHECK: [[NEW_INT:%.+]] = load i128, i128* [[NEW_INT_ADDR]], align 16
@@ -409,10 +409,10 @@ long double test_volatile_compassign(volatile _Atomic long double *addr) {
// CHECK32: [[OLD_VALUE:%.+]] = phi x86_fp80 [ [[LD_VALUE]], %{{.+}} ], [ [[LD_VALUE:%.+]], %[[ATOMIC_OP]] ]
// CHECK32: [[INC_VALUE:%.+]] = fsub x86_fp80 [[OLD_VALUE]],
// CHECK32: [[OLD_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR:%.+]] to i8*
- // CHECK32: call void @llvm.memset.p0i8.i64(i8* [[OLD_VALUE_VOID_ADDR]], i8 0, i64 12, i32 4, i1 false)
+ // CHECK32: call void @llvm.memset.p0i8.i64(i8* align 4 [[OLD_VALUE_VOID_ADDR]], i8 0, i64 12, i1 false)
// CHECK32: store x86_fp80 [[OLD_VALUE]], x86_fp80* [[OLD_VALUE_ADDR]], align 4
// CHECK32: [[DESIRED_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[DESIRED_VALUE_ADDR:%.+]] to i8*
- // CHECK32: call void @llvm.memset.p0i8.i64(i8* [[DESIRED_VALUE_VOID_ADDR]], i8 0, i64 12, i32 4, i1 false)
+ // CHECK32: call void @llvm.memset.p0i8.i64(i8* align 4 [[DESIRED_VALUE_VOID_ADDR]], i8 0, i64 12, i1 false)
// CHECK32: store x86_fp80 [[INC_VALUE]], x86_fp80* [[DESIRED_VALUE_ADDR]], align 4
// CHECK32: [[OBJ:%.+]] = bitcast x86_fp80* [[ADDR]] to i8*
// CHECK32: [[EXPECTED:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR]] to i8*
@@ -435,7 +435,7 @@ long double test_volatile_assign(volatile _Atomic long double *addr) {
// CHECK: store x86_fp80* %{{.+}}, x86_fp80** [[ADDR_ADDR:%.+]], align 8
// CHECK: [[ADDR:%.+]] = load x86_fp80*, x86_fp80** [[ADDR_ADDR]], align 8
// CHECK: [[STORE_TEMP_VOID_PTR:%.+]] = bitcast x86_fp80* [[STORE_TEMP_PTR:%.+]] to i8*
- // CHECK: call void @llvm.memset.p0i8.i64(i8* [[STORE_TEMP_VOID_PTR]], i8 0, i64 16, i32 16, i1 false)
+ // CHECK: call void @llvm.memset.p0i8.i64(i8* align 16 [[STORE_TEMP_VOID_PTR]], i8 0, i64 16, i1 false)
// CHECK: store x86_fp80 {{.+}}, x86_fp80* [[STORE_TEMP_PTR]], align 16
// CHECK: [[STORE_TEMP_INT_PTR:%.+]] = bitcast x86_fp80* [[STORE_TEMP_PTR]] to i128*
// CHECK: [[STORE_TEMP_INT:%.+]] = load i128, i128* [[STORE_TEMP_INT_PTR]], align 16
@@ -445,7 +445,7 @@ long double test_volatile_assign(volatile _Atomic long double *addr) {
// CHECK32: store x86_fp80* %{{.+}}, x86_fp80** [[ADDR_ADDR:%.+]], align 4
// CHECK32: [[ADDR:%.+]] = load x86_fp80*, x86_fp80** [[ADDR_ADDR]], align 4
// CHECK32: [[STORE_TEMP_VOID_PTR:%.+]] = bitcast x86_fp80* [[STORE_TEMP_PTR:%.+]] to i8*
- // CHECK32: call void @llvm.memset.p0i8.i64(i8* [[STORE_TEMP_VOID_PTR]], i8 0, i64 12, i32 4, i1 false)
+ // CHECK32: call void @llvm.memset.p0i8.i64(i8* align 4 [[STORE_TEMP_VOID_PTR]], i8 0, i64 12, i1 false)
// CHECK32: store x86_fp80 {{.+}}, x86_fp80* [[STORE_TEMP_PTR]], align 4
// CHECK32: [[ADDR_VOID:%.+]] = bitcast x86_fp80* [[ADDR]] to i8*
// CHECK32: [[STORE_TEMP_VOID_PTR:%.+]] = bitcast x86_fp80* [[STORE_TEMP_PTR]] to i8*
diff --git a/test/CodeGen/x86-builtins-vector-width.c b/test/CodeGen/x86-builtins-vector-width.c
new file mode 100644
index 000000000000..62f5929e4fda
--- /dev/null
+++ b/test/CodeGen/x86-builtins-vector-width.c
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -triple i686-linux-gnu -target-cpu i686 -emit-llvm %s -o - | FileCheck %s
+
+typedef signed long long V2LLi __attribute__((vector_size(16)));
+typedef signed long long V4LLi __attribute__((vector_size(32)));
+
+// Make sure builtin forces a min-legal-width attribute
+void foo(void) {
+ V2LLi tmp_V2LLi;
+
+ tmp_V2LLi = __builtin_ia32_undef128();
+}
+
+// Make sure explicit attribute larger than builtin wins.
+void goo(void) __attribute__((__min_vector_width__(256))) {
+ V2LLi tmp_V2LLi;
+
+ tmp_V2LLi = __builtin_ia32_undef128();
+}
+
+// Make sure builtin larger than explicit attribute wins.
+void hoo(void) __attribute__((__min_vector_width__(128))) {
+ V4LLi tmp_V4LLi;
+
+ tmp_V4LLi = __builtin_ia32_undef256();
+}
+
+// CHECK: foo{{.*}} #0
+// CHECK: goo{{.*}} #1
+// CHECK: hoo{{.*}} #1
+
+// CHECK: #0 = {{.*}}"min-legal-vector-width"="128"
+// CHECK: #1 = {{.*}}"min-legal-vector-width"="256"
diff --git a/test/CodeGen/x86-cf-protection.c b/test/CodeGen/x86-cf-protection.c
new file mode 100644
index 000000000000..7197dacc4ba0
--- /dev/null
+++ b/test/CodeGen/x86-cf-protection.c
@@ -0,0 +1,8 @@
+// RUN: %clang -target i386-unknown-unknown -x c -E -dM -o - -fcf-protection=return %s | FileCheck %s --check-prefix=RETURN
+// RUN: %clang -target i386-unknown-unknown -x c -E -dM -o - -fcf-protection=branch %s | FileCheck %s --check-prefix=BRANCH
+// RUN: %clang -target i386-unknown-unknown -x c -E -dM -o - -fcf-protection=full %s | FileCheck %s --check-prefix=FULL
+
+// RETURN: #define __CET__ 2
+// BRANCH: #define __CET__ 1
+// FULL: #define __CET__ 3
+void foo() {}
diff --git a/test/CodeGen/x86-nontemporal.c b/test/CodeGen/x86-nontemporal.c
index 5e9e42c9f204..cb72f41950a8 100644
--- a/test/CodeGen/x86-nontemporal.c
+++ b/test/CodeGen/x86-nontemporal.c
@@ -4,7 +4,7 @@
// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +sse4.1 -target-feature +avx -target-feature +avx2 -target-feature +avx512f -emit-llvm -o - -Wall -Werror -fmax-type-align=16 | FileCheck %s --check-prefix=CHECK
// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +sse4.1 -target-feature +avx -target-feature +avx2 -target-feature +avx512f -fno-signed-char -emit-llvm -o - -Wall -Werror -fmax-type-align=16 | FileCheck %s --check-prefix=CHECK
-#include <x86intrin.h>
+#include <immintrin.h>
// (PR33830) Tests ensure the correct alignment of non-temporal load/stores on darwin targets where fmax-type-align is set to 16.
diff --git a/test/CodeGen/x86_32-arguments-realign.c b/test/CodeGen/x86_32-arguments-realign.c
index 768e1cc4690f..b99523b7eee6 100644
--- a/test/CodeGen/x86_32-arguments-realign.c
+++ b/test/CodeGen/x86_32-arguments-realign.c
@@ -2,7 +2,7 @@
// RUN: FileCheck < %t %s
// CHECK-LABEL: define void @f0(%struct.s0* byval align 4)
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %{{.*}}, i8* %{{.*}}, i32 16, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 %{{.*}}, i8* align 4 %{{.*}}, i32 16, i1 false)
// CHECK: }
struct s0 { long double a; };
void f0(struct s0 a0) {
diff --git a/test/CodeGen/x86_32-arguments-win32.c b/test/CodeGen/x86_32-arguments-win32.c
index 7b27fc746477..65e25f32c250 100644
--- a/test/CodeGen/x86_32-arguments-win32.c
+++ b/test/CodeGen/x86_32-arguments-win32.c
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -w -triple i386-pc-win32 -emit-llvm -o - %s | FileCheck %s
-// CHECK-LABEL: define i64 @f1_1()
-// CHECK-LABEL: define void @f1_2(i32 %a0.0, i32 %a0.1)
+// CHECK-LABEL: define dso_local i64 @f1_1()
+// CHECK-LABEL: define dso_local void @f1_2(i32 %a0.0, i32 %a0.1)
struct s1 {
int a;
int b;
@@ -9,37 +9,37 @@ struct s1 {
struct s1 f1_1(void) { while (1) {} }
void f1_2(struct s1 a0) {}
-// CHECK-LABEL: define i32 @f2_1()
+// CHECK-LABEL: define dso_local i32 @f2_1()
struct s2 {
short a;
short b;
};
struct s2 f2_1(void) { while (1) {} }
-// CHECK-LABEL: define i16 @f3_1()
+// CHECK-LABEL: define dso_local i16 @f3_1()
struct s3 {
char a;
char b;
};
struct s3 f3_1(void) { while (1) {} }
-// CHECK-LABEL: define i8 @f4_1()
+// CHECK-LABEL: define dso_local i8 @f4_1()
struct s4 {
char a:4;
char b:4;
};
struct s4 f4_1(void) { while (1) {} }
-// CHECK-LABEL: define i64 @f5_1()
-// CHECK-LABEL: define void @f5_2(double %a0.0)
+// CHECK-LABEL: define dso_local i64 @f5_1()
+// CHECK-LABEL: define dso_local void @f5_2(double %a0.0)
struct s5 {
double a;
};
struct s5 f5_1(void) { while (1) {} }
void f5_2(struct s5 a0) {}
-// CHECK-LABEL: define i32 @f6_1()
-// CHECK-LABEL: define void @f6_2(float %a0.0)
+// CHECK-LABEL: define dso_local i32 @f6_1()
+// CHECK-LABEL: define dso_local void @f6_2(float %a0.0)
struct s6 {
float a;
};
diff --git a/test/CodeGen/x86_32-fpcc-struct-return.c b/test/CodeGen/x86_32-fpcc-struct-return.c
index 9f61599fc695..2cfd4378c347 100644
--- a/test/CodeGen/x86_32-fpcc-struct-return.c
+++ b/test/CodeGen/x86_32-fpcc-struct-return.c
@@ -17,15 +17,15 @@ typedef struct { } ZeroSized;
// CHECK: ret void
Big returnBig(Big x) { return x; }
-// CHECK-PCC-LABEL: define void @returnSmall
+// CHECK-PCC-LABEL: define {{(dso_local )?}}void @returnSmall
// CHECK-PCC: ret void
-// CHECK-REG-LABEL: define i32 @returnSmall
+// CHECK-REG-LABEL: define {{(dso_local )?}}i32 @returnSmall
// CHECK-REG: ret i32
Small returnSmall(Small x) { return x; }
-// CHECK-PCC-LABEL: define void @returnShort
+// CHECK-PCC-LABEL: define {{(dso_local )?}}void @returnShort
// CHECK-PCC: ret void
-// CHECK-REG-LABEL: define i16 @returnShort
+// CHECK-REG-LABEL: define {{(dso_local )?}}i16 @returnShort
// CHECK-REG: ret i16
Short returnShort(Short x) { return x; }
diff --git a/test/CodeGen/x86_64-arguments-win32.c b/test/CodeGen/x86_64-arguments-win32.c
index 7731eadd01ea..b43107c65ef6 100644
--- a/test/CodeGen/x86_64-arguments-win32.c
+++ b/test/CodeGen/x86_64-arguments-win32.c
@@ -3,29 +3,29 @@
// To be ABI compatible with code generated by MSVC, there shouldn't be any
// sign/zero extensions on types smaller than 64bit.
-// CHECK-LABEL: define void @f1(i8 %a)
+// CHECK-LABEL: define dso_local void @f1(i8 %a)
void f1(char a) {}
-// CHECK-LABEL: define void @f2(i8 %a)
+// CHECK-LABEL: define dso_local void @f2(i8 %a)
void f2(unsigned char a) {}
-// CHECK-LABEL: define void @f3(i16 %a)
+// CHECK-LABEL: define dso_local void @f3(i16 %a)
void f3(short a) {}
-// CHECK-LABEL: define void @f4(i16 %a)
+// CHECK-LABEL: define dso_local void @f4(i16 %a)
void f4(unsigned short a) {}
// For ABI compatibility with ICC, _Complex should be passed/returned
// as if it were a struct with two elements.
-// CHECK-LABEL: define void @f5(i64 %a.coerce)
+// CHECK-LABEL: define dso_local void @f5(i64 %a.coerce)
void f5(_Complex float a) {}
-// CHECK-LABEL: define void @f6({ double, double }* %a)
+// CHECK-LABEL: define dso_local void @f6({ double, double }* %a)
void f6(_Complex double a) {}
-// CHECK-LABEL: define i64 @f7()
+// CHECK-LABEL: define dso_local i64 @f7()
_Complex float f7() { return 1.0; }
-// CHECK-LABEL: define void @f8({ double, double }* noalias sret %agg.result)
+// CHECK-LABEL: define dso_local void @f8({ double, double }* noalias sret %agg.result)
_Complex double f8() { return 1.0; }
diff --git a/test/CodeGen/x86_64-arguments.c b/test/CodeGen/x86_64-arguments.c
index d24ea4dbab3d..548980b32ae4 100644
--- a/test/CodeGen/x86_64-arguments.c
+++ b/test/CodeGen/x86_64-arguments.c
@@ -434,7 +434,7 @@ void test51(struct test51_s *s, __builtin_va_list argList) {
// CHECK-NEXT: [[CASTED_VALUE_ADDR:%.*]] = bitcast i8* [[VALUE_ADDR]] to [[STRUCT_TEST51]]
// CHECK-NEXT: [[CASTED_TMP_ADDR:%.*]] = bitcast [[STRUCT_TEST51]]* [[TMP_ADDR]] to i8*
// CHECK-NEXT: [[RECASTED_VALUE_ADDR:%.*]] = bitcast [[STRUCT_TEST51]]* [[CASTED_VALUE_ADDR]] to i8*
-// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[CASTED_TMP_ADDR]], i8* [[RECASTED_VALUE_ADDR]], i64 16, i32 8, i1 false)
+// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[CASTED_TMP_ADDR]], i8* align 8 [[RECASTED_VALUE_ADDR]], i64 16, i1 false)
// CHECK-NEXT: add i32 {{.*}}, 16
// CHECK-NEXT: store i32 {{.*}}, i32* {{.*}}
// CHECK-NEXT: br label
diff --git a/test/CodeGen/x86_64-floatvectors.c b/test/CodeGen/x86_64-floatvectors.c
new file mode 100644
index 000000000000..389a06a6d6e4
--- /dev/null
+++ b/test/CodeGen/x86_64-floatvectors.c
@@ -0,0 +1,131 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | \
+// RUN: FileCheck %s
+
+// This test validates that the inreg branch generation for __builtin_va_arg
+// does not exceed the alloca size of the type, which can cause the SROA pass to
+// eliminate the assignment.
+
+typedef struct { float x, y, z; } vec3f;
+
+double Vec3FTest(__builtin_va_list ap) {
+ vec3f vec = __builtin_va_arg(ap, vec3f);
+ return vec.x + vec.y + vec.z;
+}
+// CHECK: define double @Vec3FTest
+// CHECK: vaarg.in_reg:
+// CHECK: [[Vec3FLoad1:%.*]] = load <2 x float>, <2 x float>*
+// CHECK: [[Vec3FGEP1:%.*]] = getelementptr inbounds { <2 x float>, float }, { <2 x float>, float }* {{%.*}}, i32 0, i32 0
+// CHECK: store <2 x float> [[Vec3FLoad1]], <2 x float>* [[Vec3FGEP1]]
+// CHECK: [[Vec3FLoad2:%.*]] = load float, float*
+// CHECK: [[Vec3FGEP2:%.*]] = getelementptr inbounds { <2 x float>, float }, { <2 x float>, float }* {{%.*}}, i32 0, i32 1
+// CHECK: store float [[Vec3FLoad2]], float* [[Vec3FGEP2]]
+// CHECK: vaarg.in_mem:
+
+
+typedef struct { float x, y, z, q; } vec4f;
+
+double Vec4FTest(__builtin_va_list ap) {
+ vec4f vec = __builtin_va_arg(ap, vec4f);
+ return vec.x + vec.y + vec.z + vec.q;
+}
+// CHECK: define double @Vec4FTest
+// CHECK: vaarg.in_reg:
+// CHECK: [[Vec4FLoad1:%.*]] = load <2 x float>, <2 x float>*
+// CHECK: [[Vec4FGEP1:%.*]] = getelementptr inbounds { <2 x float>, <2 x float> }, { <2 x float>, <2 x float> }* {{%.*}}, i32 0, i32 0
+// CHECK: store <2 x float> [[Vec4FLoad1]], <2 x float>* [[Vec4FGEP1]]
+// CHECK: [[Vec4FLoad2:%.*]] = load <2 x float>, <2 x float>*
+// CHECK: [[Vec4FGEP2:%.*]] = getelementptr inbounds { <2 x float>, <2 x float> }, { <2 x float>, <2 x float> }* {{%.*}}, i32 0, i32 1
+// CHECK: store <2 x float> [[Vec4FLoad2]], <2 x float>* [[Vec4FGEP2]]
+// CHECK: vaarg.in_mem:
+
+typedef struct { double x, y; } vec2d;
+
+double Vec2DTest(__builtin_va_list ap) {
+ vec2d vec = __builtin_va_arg(ap, vec2d);
+ return vec.x + vec.y;
+}
+// CHECK: define double @Vec2DTest
+// CHECK: vaarg.in_reg:
+// CHECK: [[Vec2DLoad1:%.*]] = load double, double*
+// CHECK: [[Vec2DGEP1:%.*]] = getelementptr inbounds { double, double }, { double, double }* {{%.*}}, i32 0, i32 0
+// CHECK: store double [[Vec2DLoad1]], double* [[Vec2DGEP1]]
+// CHECK: [[Vec2DLoad2:%.*]] = load double, double*
+// CHECK: [[Vec2DGEP2:%.*]] = getelementptr inbounds { double, double }, { double, double }* {{%.*}}, i32 0, i32 1
+// CHECK: store double [[Vec2DLoad2]], double* [[Vec2DGEP2]]
+// CHECK: vaarg.in_mem:
+
+typedef struct {
+ float x, y;
+ double z;
+} vec2f1d;
+
+double Vec2F1DTest(__builtin_va_list ap) {
+ vec2f1d vec = __builtin_va_arg(ap, vec2f1d);
+ return vec.x + vec.y + vec.z;
+}
+// CHECK: define double @Vec2F1DTest
+// CHECK: vaarg.in_reg:
+// CHECK: [[Vec2F1DLoad1:%.*]] = load <2 x float>, <2 x float>*
+// CHECK: [[Vec2F1DGEP1:%.*]] = getelementptr inbounds { <2 x float>, double }, { <2 x float>, double }* {{%.*}}, i32 0, i32 0
+// CHECK: store <2 x float> [[Vec2F1DLoad1]], <2 x float>* [[Vec2F1DGEP1]]
+// CHECK: [[Vec2F1DLoad2:%.*]] = load double, double*
+// CHECK: [[Vec2F1DGEP2:%.*]] = getelementptr inbounds { <2 x float>, double }, { <2 x float>, double }* {{%.*}}, i32 0, i32 1
+// CHECK: store double [[Vec2F1DLoad2]], double* [[Vec2F1DGEP2]]
+// CHECK: vaarg.in_mem:
+
+typedef struct {
+ double x;
+ float y, z;
+} vec1d2f;
+
+double Vec1D2FTest(__builtin_va_list ap) {
+ vec1d2f vec = __builtin_va_arg(ap, vec1d2f);
+ return vec.x + vec.y + vec.z;
+}
+// CHECK: define double @Vec1D2FTest
+// CHECK: vaarg.in_reg:
+// CHECK: [[Vec1D2FLoad1:%.*]] = load double, double*
+// CHECK: [[Vec1D2FGEP1:%.*]] = getelementptr inbounds { double, <2 x float> }, { double, <2 x float> }* {{%.*}}, i32 0, i32 0
+// CHECK: store double [[Vec1D2FLoad1]], double* [[Vec1D2FGEP1]]
+// CHECK: [[Vec1D2FLoad2:%.*]] = load <2 x float>, <2 x float>*
+// CHECK: [[Vec1D2FGEP2:%.*]] = getelementptr inbounds { double, <2 x float> }, { double, <2 x float> }* {{%.*}}, i32 0, i32 1
+// CHECK: store <2 x float> [[Vec1D2FLoad2]], <2 x float>* [[Vec1D2FGEP2]]
+// CHECK: vaarg.in_mem:
+
+typedef struct {
+ float x;
+ double z;
+} vec1f1d;
+
+double Vec1F1DTest(__builtin_va_list ap) {
+ vec1f1d vec = __builtin_va_arg(ap, vec1f1d);
+ return vec.x + vec.z;
+}
+// CHECK: define double @Vec1F1DTest
+// CHECK: vaarg.in_reg:
+// CHECK: [[Vec1F1DLoad1:%.*]] = load float, float*
+// CHECK: [[Vec1F1DGEP1:%.*]] = getelementptr inbounds { float, double }, { float, double }* {{%.*}}, i32 0, i32 0
+// CHECK: store float [[Vec1F1DLoad1]], float* [[Vec1F1DGEP1]]
+// CHECK: [[Vec1F1DLoad2:%.*]] = load double, double*
+// CHECK: [[Vec1F1DGEP2:%.*]] = getelementptr inbounds { float, double }, { float, double }* {{%.*}}, i32 0, i32 1
+// CHECK: store double [[Vec1F1DLoad2]], double* [[Vec1F1DGEP2]]
+// CHECK: vaarg.in_mem:
+
+typedef struct {
+ double x;
+ float z;
+} vec1d1f;
+
+double Vec1D1FTest(__builtin_va_list ap) {
+ vec1d1f vec = __builtin_va_arg(ap, vec1d1f);
+ return vec.x + vec.z;
+}
+// CHECK: define double @Vec1D1FTest
+// CHECK: vaarg.in_reg:
+// CHECK: [[Vec1D1FLoad1:%.*]] = load double, double*
+// CHECK: [[Vec1D1FGEP1:%.*]] = getelementptr inbounds { double, float }, { double, float }* {{%.*}}, i32 0, i32 0
+// CHECK: store double [[Vec1D1FLoad1]], double* [[Vec1D1FGEP1]]
+// CHECK: [[Vec1D1FLoad2:%.*]] = load float, float*
+// CHECK: [[Vec1D1FGEP2:%.*]] = getelementptr inbounds { double, float }, { double, float }* {{%.*}}, i32 0, i32 1
+// CHECK: store float [[Vec1D1FLoad2]], float* [[Vec1D1FGEP2]]
+// CHECK: vaarg.in_mem:
diff --git a/test/CodeGen/xcore-abi.c b/test/CodeGen/xcore-abi.c
index 2bac78d92edd..90306ce31a53 100644
--- a/test/CodeGen/xcore-abi.c
+++ b/test/CodeGen/xcore-abi.c
@@ -80,7 +80,7 @@ void testva (int n, ...) {
// CHECK: store i8* [[IN]], i8** [[AP]]
// CHECK: [[V1:%[a-z0-9]+]] = bitcast %struct.x* [[V:%[a-z0-9]+]] to i8*
// CHECK: [[P1:%[a-z0-9]+]] = bitcast %struct.x* [[P]] to i8*
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[V1]], i8* [[P1]], i32 20, i32 4, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 [[V1]], i8* align 4 [[P1]], i32 20, i1 false)
// CHECK: [[V2:%[a-z0-9]+]] = bitcast %struct.x* [[V]] to i8*
// CHECK: call void @f(i8* [[V2]])
@@ -93,7 +93,7 @@ void testva (int n, ...) {
// CHECK: store i8* [[IN]], i8** [[AP]]
// CHECK: [[V1:%[a-z0-9]+]] = bitcast [4 x i32]* [[V0:%[a-z0-9]+]] to i8*
// CHECK: [[P1:%[a-z0-9]+]] = bitcast [4 x i32]* [[P]] to i8*
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[V1]], i8* [[P1]], i32 16, i32 4, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 [[V1]], i8* align 4 [[P1]], i32 16, i1 false)
// CHECK: [[V2:%[a-z0-9]+]] = getelementptr inbounds [4 x i32], [4 x i32]* [[V0]], i32 0, i32 0
// CHECK: store i32* [[V2]], i32** [[V:%[a-z0-9]+]], align 4
// CHECK: [[V3:%[a-z0-9]+]] = load i32*, i32** [[V]], align 4
diff --git a/test/CodeGen/xray-always-emit-typedevent.cpp b/test/CodeGen/xray-always-emit-typedevent.cpp
new file mode 100644
index 000000000000..50593dd20322
--- /dev/null
+++ b/test/CodeGen/xray-always-emit-typedevent.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -fxray-instrument -fxray-always-emit-typedevents -x c++ \
+// RUN: -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s \
+// RUN: | FileCheck %s
+
+// CHECK-LABEL: @_Z15neverInstrumentv
+[[clang::xray_never_instrument]] void neverInstrument() {
+ static constexpr char kPhase[] = "never";
+ __xray_typedevent(1, kPhase, 5);
+ // CHECK: call void @llvm.xray.typedevent(i16 {{.*}}, i8*{{.*}}, i32 5)
+}
diff --git a/test/CodeGen/xray-always-instrument.cpp b/test/CodeGen/xray-always-instrument.cpp
index 60d859569958..fb6690577f58 100644
--- a/test/CodeGen/xray-always-instrument.cpp
+++ b/test/CodeGen/xray-always-instrument.cpp
@@ -1,6 +1,14 @@
// RUN: echo "fun:*foo*" > %t.always-instrument
// RUN: echo "src:*xray-always-instrument.cpp" >> %t.always-instrument
-// RUN: %clang_cc1 -fxray-instrument -x c++ -std=c++11 -fxray-always-instrument=%t.always-instrument -emit-llvm -o - %s -triple x86_64-unknown-linux-gnu | FileCheck %s
+// RUN: echo "[always]" > %t.xray-attrlist
+// RUN: echo "fun:*foo*" >> %t.xray-attrlist
+// RUN: echo "src:*xray-always-instrument.cpp" >> %t.xray-attrlist
+// RUN: %clang_cc1 -fxray-instrument -x c++ -std=c++11 \
+// RUN: -fxray-always-instrument=%t.always-instrument -emit-llvm -o - %s \
+// RUN: -triple x86_64-unknown-linux-gnu | FileCheck %s
+// RUN: %clang_cc1 -fxray-instrument -x c++ -std=c++11 \
+// RUN: -fxray-attr-list=%t.xray-attrlist -emit-llvm -o - %s \
+// RUN: -triple x86_64-unknown-linux-gnu | FileCheck %s
void foo() {}
diff --git a/test/CodeGen/xray-attr-list.cpp b/test/CodeGen/xray-attr-list.cpp
new file mode 100644
index 000000000000..f2e48773e41a
--- /dev/null
+++ b/test/CodeGen/xray-attr-list.cpp
@@ -0,0 +1,19 @@
+// RUN: echo "[always]" > %t.xray-attrlist
+// RUN: echo "fun:*always*" >> %t.xray-attrlist
+// RUN: echo "[never]" >> %t.xray-attrlist
+// RUN: echo "fun:*never*" >> %t.xray-attrlist
+// RUN: %clang_cc1 -fxray-instrument -x c++ -std=c++11 \
+// RUN: -fxray-attr-list=%t.xray-attrlist -emit-llvm -o - %s \
+// RUN: -triple x86_64-unknown-linux-gnu | FileCheck %s
+
+void always() {}
+void never() {}
+[[clang::xray_never_instrument]] void alwaysNever() {}
+[[clang::xray_always_instrument]] void neverAlways() {}
+
+// CHECK: define void @_Z6alwaysv() #[[ALWAYSATTR:[0-9]+]] {
+// CHECK: define void @_Z5neverv() #[[NEVERATTR:[0-9]+]] {
+// CHECK: define void @_Z11alwaysNeverv() #[[NEVERATTR]] {
+// CHECK: define void @_Z11neverAlwaysv() #[[ALWAYSATTR]] {
+// CHECK: attributes #[[ALWAYSATTR]] = {{.*}} "function-instrument"="xray-always" {{.*}}
+// CHECK: attributes #[[NEVERATTR]] = {{.*}} "function-instrument"="xray-never" {{.*}}
diff --git a/test/CodeGen/xray-imbue-arg1.cpp b/test/CodeGen/xray-imbue-arg1.cpp
index eb272b97eafb..083099ce582d 100644
--- a/test/CodeGen/xray-imbue-arg1.cpp
+++ b/test/CodeGen/xray-imbue-arg1.cpp
@@ -1,5 +1,12 @@
// RUN: echo "fun:*arg1*=arg1" >> %t.always-instrument
-// RUN: %clang_cc1 -fxray-instrument -x c++ -std=c++11 -fxray-always-instrument=%t.always-instrument -emit-llvm -o - %s -triple x86_64-unknown-linux-gnu | FileCheck %s
+// RUN: echo "[always]" > %t.xray-attrlist
+// RUN: echo "fun:*arg1*=arg1" >> %t.xray-attrlist
+// RUN: %clang_cc1 -fxray-instrument -x c++ -std=c++11 \
+// RUN: -fxray-always-instrument=%t.always-instrument -emit-llvm -o - %s \
+// RUN: -triple x86_64-unknown-linux-gnu | FileCheck %s
+// RUN: %clang_cc1 -fxray-instrument -x c++ -std=c++11 \
+// RUN: -fxray-attr-list=%t.xray-attrlist -emit-llvm -o - %s \
+// RUN: -triple x86_64-unknown-linux-gnu | FileCheck %s
void foo() {}
diff --git a/test/CodeGen/xray-instrumentation-bundles.cpp b/test/CodeGen/xray-instrumentation-bundles.cpp
new file mode 100644
index 000000000000..79286c2c8aed
--- /dev/null
+++ b/test/CodeGen/xray-instrumentation-bundles.cpp
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -fxray-instrument -fxray-instrumentation-bundle=none -x c++ \
+// RUN: -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s \
+// RUN: | FileCheck --check-prefixes CHECK,NOFUNCTION,NOCUSTOM,NOTYPED %s
+// RUN: %clang_cc1 -fxray-instrument -fxray-instrumentation-bundle=function -x c++ \
+// RUN: -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s \
+// RUN: | FileCheck --check-prefixes CHECK,FUNCTION,NOCUSTOM,NOTYPED %s
+// RUN: %clang_cc1 -fxray-instrument \
+// RUN: -fxray-instrumentation-bundle=custom -x c++ \
+// RUN: -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s \
+// RUN: | FileCheck --check-prefixes CHECK,NOFUNCTION,CUSTOM,NOTYPED %s
+// RUN: %clang_cc1 -fxray-instrument \
+// RUN: -fxray-instrumentation-bundle=typed -x c++ \
+// RUN: -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s \
+// RUN: | FileCheck --check-prefixes CHECK,NOFUNCTION,NOCUSTOM,TYPED %s
+// RUN: %clang_cc1 -fxray-instrument \
+// RUN: -fxray-instrumentation-bundle=custom,typed -x c++ \
+// RUN: -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s \
+// RUN: | FileCheck --check-prefixes CHECK,NOFUNCTION,CUSTOM,TYPED %s
+// RUN: %clang_cc1 -fxray-instrument \
+// RUN: -fxray-instrumentation-bundle=function,custom -x c++ \
+// RUN: -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s \
+// RUN: | FileCheck --check-prefixes CHECK,FUNCTION,CUSTOM,NOTYPED %s
+// RUN: %clang_cc1 -fxray-instrument \
+// RUN: -fxray-instrumentation-bundle=function,typed -x c++ \
+// RUN: -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s \
+// RUN: | FileCheck --check-prefixes CHECK,FUNCTION,NOCUSTOM,TYPED %s
+// RUN: %clang_cc1 -fxray-instrument \
+// RUN: -fxray-instrumentation-bundle=function,custom,typed -x c++ \
+// RUN: -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s \
+// RUN: | FileCheck --check-prefixes CHECK,FUNCTION,CUSTOM,TYPED %s
+// RUN: %clang_cc1 -fxray-instrument \
+// RUN: -fxray-instrumentation-bundle=function \
+// RUN: -fxray-instrumentation-bundle=custom \
+// RUN: -fxray-instrumentation-bundle=typed -x c++ \
+// RUN: -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s \
+// RUN: | FileCheck --check-prefixes CHECK,FUNCTION,CUSTOM,TYPED %s
+
+// CHECK: define void @_Z16alwaysInstrumentv() #[[ALWAYSATTR:[0-9]+]] {
+[[clang::xray_always_instrument]] void alwaysInstrument() {
+ static constexpr char kPhase[] = "always";
+ __xray_customevent(kPhase, 6);
+ __xray_typedevent(1, kPhase, 6);
+ // CUSTOM: call void @llvm.xray.customevent(i8*{{.*}}, i32 6)
+ // NOCUSTOM-NOT: call void @llvm.xray.customevent(i8*{{.*}}, i32 6)
+ // TYPED: call void @llvm.xray.typedevent(i16 {{.*}}, i8*{{.*}}, i32 6)
+ // NOTYPED-NOT: call void @llvm.xray.typedevent(i16 {{.*}}, i8*{{.*}}, i32 6)
+}
+
+// FUNCTION: attributes #[[ALWAYSATTR]] = {{.*}} "function-instrument"="xray-always" {{.*}}
+// NOFUNCTION-NOT: attributes #[[ALWAYSATTR]] = {{.*}} "function-instrument"="xray-always" {{.*}}
diff --git a/test/CodeGen/xray-never-instrument.cpp b/test/CodeGen/xray-never-instrument.cpp
new file mode 100644
index 000000000000..4b20edc6ad60
--- /dev/null
+++ b/test/CodeGen/xray-never-instrument.cpp
@@ -0,0 +1,24 @@
+// RUN: echo "fun:*foo*" > %t.never-instrument
+// RUN: echo "src:*xray-never-instrument.cpp" >> %t.never-instrument
+// RUN: echo "[never]" > %t.xray-attrlist
+// RUN: echo "fun:*foo*" >> %t.xray-attrlist
+// RUN: echo "src:*xray-never-instrument.cpp" >> %t.xray-attrlist
+// RUN: %clang_cc1 -fxray-instrument -x c++ -std=c++11 \
+// RUN: -fxray-never-instrument=%t.never-instrument -emit-llvm -o - %s \
+// RUN: -triple x86_64-unknown-linux-gnu | FileCheck %s
+// RUN: %clang_cc1 -fxray-instrument -x c++ -std=c++11 \
+// RUN: -fxray-attr-list=%t.xray-attrlist -emit-llvm -o - %s \
+// RUN: -triple x86_64-unknown-linux-gnu | FileCheck %s
+
+void foo() {}
+
+[[clang::xray_always_instrument]] void bar() {}
+
+void baz() {}
+
+// CHECK: define void @_Z3foov() #[[NEVERATTR:[0-9]+]] {
+// CHECK: define void @_Z3barv() #[[ALWAYSATTR:[0-9]+]] {
+// CHECK: define void @_Z3bazv() #[[NEVERATTR:[0-9]+]] {
+// CHECK: attributes #[[NEVERATTR]] = {{.*}} "function-instrument"="xray-never" {{.*}}
+// CHECK: attributes #[[ALWAYSATTR]] = {{.*}} "function-instrument"="xray-always" {{.*}}
+
diff --git a/test/CodeGen/xray-typedevent.cpp b/test/CodeGen/xray-typedevent.cpp
new file mode 100644
index 000000000000..e804b09dc2c4
--- /dev/null
+++ b/test/CodeGen/xray-typedevent.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -fxray-instrument -x c++ -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s
+
+// CHECK-LABEL: @_Z16alwaysInstrumentv
+[[clang::xray_always_instrument]] void alwaysInstrument() {
+ // Event types would normally come from calling __xray_register_event_type
+ // from compiler-rt
+ auto EventType = 1;
+ static constexpr char kPhase[] = "instrument";
+ __xray_typedevent(EventType, kPhase, 10);
+ // CHECK: call void @llvm.xray.typedevent(i16 {{.*}}, i8*{{.*}}, i32 10)
+}
+
+// CHECK-LABEL: @_Z15neverInstrumentv
+[[clang::xray_never_instrument]] void neverInstrument() {
+ auto EventType = 2;
+ static constexpr char kPhase[] = "never";
+ __xray_typedevent(EventType, kPhase, 5);
+ // CHECK-NOT: call void @llvm.xray.typedevent(i16 {{.*}}, i8*{{.*}}, i32 5)
+}
+
+// CHECK-LABEL: @_Z21conditionalInstrumenti
+[[clang::xray_always_instrument]] void conditionalInstrument(int v) {
+ auto TrueEventType = 3;
+ auto UntrueEventType = 4;
+ static constexpr char kTrue[] = "true";
+ static constexpr char kUntrue[] = "untrue";
+ if (v % 2)
+ __xray_typedevent(TrueEventType, kTrue, 4);
+ else
+ __xray_typedevent(UntrueEventType, kUntrue, 6);
+
+ // CHECK: call void @llvm.xray.typedevent(i16 {{.*}}, i8*{{.*}}, i32 4)
+ // CHECK: call void @llvm.xray.typedevent(i16 {{.*}}, i8*{{.*}}, i32 6)
+}
diff --git a/test/CodeGenCUDA/Inputs/cuda.h b/test/CodeGenCUDA/Inputs/cuda.h
index 9b9f43a1aaa9..3adbdc5b6d18 100644
--- a/test/CodeGenCUDA/Inputs/cuda.h
+++ b/test/CodeGenCUDA/Inputs/cuda.h
@@ -16,7 +16,12 @@ struct dim3 {
typedef struct cudaStream *cudaStream_t;
+#ifdef __HIP__
+int hipConfigureCall(dim3 gridSize, dim3 blockSize, size_t sharedSize = 0,
+ cudaStream_t stream = 0);
+#else
int cudaConfigureCall(dim3 gridSize, dim3 blockSize, size_t sharedSize = 0,
cudaStream_t stream = 0);
+#endif
extern "C" __device__ int printf(const char*, ...);
diff --git a/test/CodeGenCUDA/address-spaces.cu b/test/CodeGenCUDA/address-spaces.cu
index 449529bb24b4..58b0a4370762 100644
--- a/test/CodeGenCUDA/address-spaces.cu
+++ b/test/CodeGenCUDA/address-spaces.cu
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -emit-llvm %s -o - -fcuda-is-device -triple nvptx-unknown-unknown | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -fcuda-is-device -triple amdgcn | FileCheck %s
// Verifies Clang emits correct address spaces and addrspacecast instructions
// for CUDA code.
@@ -19,11 +20,11 @@ struct MyStruct {
int data2;
};
-// CHECK: @_ZZ5func0vE1a = internal addrspace(3) global %struct.MyStruct zeroinitializer
-// CHECK: @_ZZ5func1vE1a = internal addrspace(3) global float 0.000000e+00
-// CHECK: @_ZZ5func2vE1a = internal addrspace(3) global [256 x float] zeroinitializer
-// CHECK: @_ZZ5func3vE1a = internal addrspace(3) global float 0.000000e+00
-// CHECK: @_ZZ5func4vE1a = internal addrspace(3) global float 0.000000e+00
+// CHECK: @_ZZ5func0vE1a = internal addrspace(3) global %struct.MyStruct undef
+// CHECK: @_ZZ5func1vE1a = internal addrspace(3) global float undef
+// CHECK: @_ZZ5func2vE1a = internal addrspace(3) global [256 x float] undef
+// CHECK: @_ZZ5func3vE1a = internal addrspace(3) global float undef
+// CHECK: @_ZZ5func4vE1a = internal addrspace(3) global float undef
// CHECK: @b = addrspace(3) global float undef
__device__ void foo() {
@@ -48,7 +49,7 @@ __device__ void func0() {
ap->data2 = 2;
}
// CHECK: define void @_Z5func0v()
-// CHECK: store %struct.MyStruct* addrspacecast (%struct.MyStruct addrspace(3)* @_ZZ5func0vE1a to %struct.MyStruct*), %struct.MyStruct** %ap
+// CHECK: store %struct.MyStruct* addrspacecast (%struct.MyStruct addrspace(3)* @_ZZ5func0vE1a to %struct.MyStruct*), %struct.MyStruct** %{{.*}}
__device__ void callee(float *ap) {
*ap = 1.0f;
@@ -67,7 +68,7 @@ __device__ void func2() {
*ap = 1.0f;
}
// CHECK: define void @_Z5func2v()
-// CHECK: store float* getelementptr inbounds ([256 x float], [256 x float]* addrspacecast ([256 x float] addrspace(3)* @_ZZ5func2vE1a to [256 x float]*), i32 0, i32 128), float** %ap
+// CHECK: store float* getelementptr inbounds ([256 x float], [256 x float]* addrspacecast ([256 x float] addrspace(3)* @_ZZ5func2vE1a to [256 x float]*), i{{32|64}} 0, i{{32|64}} 128), float** %{{.*}}
__device__ void func3() {
__shared__ float a;
@@ -75,7 +76,7 @@ __device__ void func3() {
*ap = 1.0f;
}
// CHECK: define void @_Z5func3v()
-// CHECK: store float* addrspacecast (float addrspace(3)* @_ZZ5func3vE1a to float*), float** %ap
+// CHECK: store float* addrspacecast (float addrspace(3)* @_ZZ5func3vE1a to float*), float** %{{.*}}
__device__ void func4() {
__shared__ float a;
@@ -83,7 +84,7 @@ __device__ void func4() {
*ap = 1.0f;
}
// CHECK: define void @_Z5func4v()
-// CHECK: store float* addrspacecast (float addrspace(3)* @_ZZ5func4vE1a to float*), float** %ap
+// CHECK: store float* addrspacecast (float addrspace(3)* @_ZZ5func4vE1a to float*), float** %{{.*}}
__shared__ float b;
diff --git a/test/CodeGenCUDA/alias.cu b/test/CodeGenCUDA/alias.cu
index 6efff6b92aa8..56e595ed3639 100644
--- a/test/CodeGenCUDA/alias.cu
+++ b/test/CodeGenCUDA/alias.cu
@@ -1,8 +1,11 @@
// REQUIRES: x86-registered-target
// REQUIRES: nvptx-registered-target
+// REQUIRES: amdgpu-registered-target
// RUN: %clang_cc1 -fcuda-is-device -triple nvptx-nvidia-cuda -emit-llvm \
// RUN: -o - %s | FileCheck %s
+// RUN: %clang_cc1 -fcuda-is-device -triple amdgcn -emit-llvm \
+// RUN: -o - %s | FileCheck %s
#include "Inputs/cuda.h"
diff --git a/test/CodeGenCUDA/amdgpu-kernel-attrs.cu b/test/CodeGenCUDA/amdgpu-kernel-attrs.cu
new file mode 100644
index 000000000000..70eb9091d8d4
--- /dev/null
+++ b/test/CodeGenCUDA/amdgpu-kernel-attrs.cu
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa \
+// RUN: -fcuda-is-device -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple nvptx \
+// RUN: -fcuda-is-device -emit-llvm -o - %s | FileCheck %s \
+// RUN: -check-prefix=NAMD
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm \
+// RUN: -verify -o - %s | FileCheck -check-prefix=NAMD %s
+
+#include "Inputs/cuda.h"
+
+__attribute__((amdgpu_flat_work_group_size(32, 64))) // expected-no-diagnostics
+__global__ void flat_work_group_size_32_64() {
+// CHECK: define amdgpu_kernel void @_Z26flat_work_group_size_32_64v() [[FLAT_WORK_GROUP_SIZE_32_64:#[0-9]+]]
+}
+__attribute__((amdgpu_waves_per_eu(2))) // expected-no-diagnostics
+__global__ void waves_per_eu_2() {
+// CHECK: define amdgpu_kernel void @_Z14waves_per_eu_2v() [[WAVES_PER_EU_2:#[0-9]+]]
+}
+__attribute__((amdgpu_num_sgpr(32))) // expected-no-diagnostics
+__global__ void num_sgpr_32() {
+// CHECK: define amdgpu_kernel void @_Z11num_sgpr_32v() [[NUM_SGPR_32:#[0-9]+]]
+}
+__attribute__((amdgpu_num_vgpr(64))) // expected-no-diagnostics
+__global__ void num_vgpr_64() {
+// CHECK: define amdgpu_kernel void @_Z11num_vgpr_64v() [[NUM_VGPR_64:#[0-9]+]]
+}
+
+// Make sure this is silently accepted on other targets.
+// NAMD-NOT: "amdgpu-flat-work-group-size"
+// NAMD-NOT: "amdgpu-waves-per-eu"
+// NAMD-NOT: "amdgpu-num-vgpr"
+// NAMD-NOT: "amdgpu-num-sgpr"
+
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64"
+// CHECK-DAG: attributes [[WAVES_PER_EU_2]] = { convergent noinline nounwind optnone "amdgpu-waves-per-eu"="2"
+// CHECK-DAG: attributes [[NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-num-sgpr"="32"
+// CHECK-DAG: attributes [[NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-num-vgpr"="64"
diff --git a/test/CodeGenCUDA/convergent.cu b/test/CodeGenCUDA/convergent.cu
index 62818f9e5af4..dd410cc644ac 100644
--- a/test/CodeGenCUDA/convergent.cu
+++ b/test/CodeGenCUDA/convergent.cu
@@ -2,11 +2,11 @@
// REQUIRES: nvptx-registered-target
// RUN: %clang_cc1 -fcuda-is-device -triple nvptx-nvidia-cuda -emit-llvm \
-// RUN: -disable-llvm-passes -o - %s | FileCheck -check-prefix DEVICE %s
+// RUN: -disable-llvm-passes -o - %s | FileCheck -allow-deprecated-dag-overlap -check-prefix DEVICE %s
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm \
// RUN: -disable-llvm-passes -o - %s | \
-// RUN: FileCheck -check-prefix HOST %s
+// RUN: FileCheck -allow-deprecated-dag-overlap -check-prefix HOST %s
#include "Inputs/cuda.h"
diff --git a/test/CodeGenCUDA/device-stub.cu b/test/CodeGenCUDA/device-stub.cu
index 3376803c5020..716381b7a826 100644
--- a/test/CodeGenCUDA/device-stub.cu
+++ b/test/CodeGenCUDA/device-stub.cu
@@ -1,33 +1,52 @@
// RUN: echo "GPU binary would be here" > %t
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -fcuda-include-gpubinary %t -o - | FileCheck %s
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -fcuda-include-gpubinary %t -o - -DNOGLOBALS \
-// RUN: | FileCheck %s -check-prefix=NOGLOBALS
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s -check-prefix=NOGPUBIN
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s \
+// RUN: -fcuda-include-gpubinary %t -o - \
+// RUN: | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=ALL,NORDC,CUDA,CUDANORDC
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s \
+// RUN: -fcuda-include-gpubinary %t -o - -DNOGLOBALS \
+// RUN: | FileCheck -allow-deprecated-dag-overlap %s -check-prefixes=NOGLOBALS,CUDANOGLOBALS
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s \
+// RUN: -fcuda-rdc -fcuda-include-gpubinary %t -o - \
+// RUN: | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=ALL,RDC,CUDA,CUDARDC
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - \
+// RUN: | FileCheck -allow-deprecated-dag-overlap %s -check-prefix=NOGPUBIN
+
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s \
+// RUN: -fcuda-include-gpubinary %t -o - -x hip\
+// RUN: | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=ALL,NORDC,HIP
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s \
+// RUN: -fcuda-include-gpubinary %t -o - -DNOGLOBALS -x hip \
+// RUN: | FileCheck -allow-deprecated-dag-overlap %s -check-prefixes=NOGLOBALS,HIPNOGLOBALS
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s \
+// RUN: -fcuda-rdc -fcuda-include-gpubinary %t -o - -x hip \
+// RUN: | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=ALL,NORDC,HIP
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - -x hip\
+// RUN: | FileCheck -allow-deprecated-dag-overlap %s -check-prefix=NOGPUBIN
#include "Inputs/cuda.h"
#ifndef NOGLOBALS
-// CHECK-DAG: @device_var = internal global i32
+// ALL-DAG: @device_var = internal global i32
__device__ int device_var;
-// CHECK-DAG: @constant_var = internal global i32
+// ALL-DAG: @constant_var = internal global i32
__constant__ int constant_var;
-// CHECK-DAG: @shared_var = internal global i32
+// ALL-DAG: @shared_var = internal global i32
__shared__ int shared_var;
// Make sure host globals don't get internalized...
-// CHECK-DAG: @host_var = global i32
+// ALL-DAG: @host_var = global i32
int host_var;
// ... and that extern vars remain external.
-// CHECK-DAG: @ext_host_var = external global i32
+// ALL-DAG: @ext_host_var = external global i32
extern int ext_host_var;
// Shadows for external device-side variables are *definitions* of
// those variables.
-// CHECK-DAG: @ext_device_var = internal global i32
+// ALL-DAG: @ext_device_var = internal global i32
extern __device__ int ext_device_var;
-// CHECK-DAG: @ext_device_var = internal global i32
+// ALL-DAG: @ext_device_var = internal global i32
extern __constant__ int ext_constant_var;
void use_pointers() {
@@ -43,72 +62,110 @@ void use_pointers() {
// Make sure that all parts of GPU code init/cleanup are there:
// * constant unnamed string with the kernel name
-// CHECK: private unnamed_addr constant{{.*}}kernelfunc{{.*}}\00"
+// ALL: private unnamed_addr constant{{.*}}kernelfunc{{.*}}\00"
// * constant unnamed string with GPU binary
-// CHECK: private unnamed_addr constant{{.*GPU binary would be here.*}}\00"
-// CHECK-SAME: section ".nv_fatbin", align 8
+// HIP: @[[FATBIN:__hip_fatbin]] = external constant i8, section ".hip_fatbin"
+// CUDA: @[[FATBIN:.*]] = private constant{{.*GPU binary would be here.*}}\00",
+// CUDANORDC-SAME: section ".nv_fatbin", align 8
+// CUDARDC-SAME: section "__nv_relfatbin", align 8
// * constant struct that wraps GPU binary
-// CHECK: @__cuda_fatbin_wrapper = internal constant { i32, i32, i8*, i8* }
-// CHECK-SAME: { i32 1180844977, i32 1, {{.*}}, i8* null }
-// CHECK-SAME: section ".nvFatBinSegment"
+// ALL: @__[[PREFIX:cuda|hip]]_fatbin_wrapper = internal constant
+// ALL-SAME: { i32, i32, i8*, i8* }
+// CUDA-SAME: { i32 1180844977, i32 1,
+// HIP-SAME: { i32 1212764230, i32 1,
+// CUDA-SAME: i8* getelementptr inbounds ({{.*}}@[[FATBIN]], i64 0, i64 0),
+// HIP-SAME: i8* @[[FATBIN]],
+// ALL-SAME: i8* null }
+// CUDA-SAME: section ".nvFatBinSegment"
+// HIP-SAME: section ".hipFatBinSegment"
// * variable to save GPU binary handle after initialization
-// CHECK: @__cuda_gpubin_handle = internal global i8** null
-// * Make sure our constructor/destructor was added to global ctor/dtor list.
-// CHECK: @llvm.global_ctors = appending global {{.*}}@__cuda_module_ctor
-// CHECK: @llvm.global_dtors = appending global {{.*}}@__cuda_module_dtor
+// CUDANORDC: @__[[PREFIX]]_gpubin_handle = internal global i8** null
+// HIP: @__[[PREFIX]]_gpubin_handle = linkonce global i8** null
+// * constant unnamed string with NVModuleID
+// RDC: [[MODULE_ID_GLOBAL:@.*]] = private constant
+// CUDARDC-SAME: c"[[MODULE_ID:.+]]\00", section "__nv_module_id", align 32
+// * Make sure our constructor was added to global ctor list.
+// ALL: @llvm.global_ctors = appending global {{.*}}@__[[PREFIX]]_module_ctor
+// * Alias to global symbol containing the NVModuleID.
+// RDC: @__fatbinwrap[[MODULE_ID]] = alias { i32, i32, i8*, i8* }
+// RDC-SAME: { i32, i32, i8*, i8* }* @__[[PREFIX]]_fatbin_wrapper
// Test that we build the correct number of calls to cudaSetupArgument followed
// by a call to cudaLaunch.
-// CHECK: define{{.*}}kernelfunc
-// CHECK: call{{.*}}cudaSetupArgument
-// CHECK: call{{.*}}cudaSetupArgument
-// CHECK: call{{.*}}cudaSetupArgument
-// CHECK: call{{.*}}cudaLaunch
+// ALL: define{{.*}}kernelfunc
+// ALL: call{{.*}}[[PREFIX]]SetupArgument
+// ALL: call{{.*}}[[PREFIX]]SetupArgument
+// ALL: call{{.*}}[[PREFIX]]SetupArgument
+// ALL: call{{.*}}[[PREFIX]]Launch
__global__ void kernelfunc(int i, int j, int k) {}
// Test that we've built correct kernel launch sequence.
-// CHECK: define{{.*}}hostfunc
-// CHECK: call{{.*}}cudaConfigureCall
-// CHECK: call{{.*}}kernelfunc
+// ALL: define{{.*}}hostfunc
+// ALL: call{{.*}}[[PREFIX]]ConfigureCall
+// ALL: call{{.*}}kernelfunc
void hostfunc(void) { kernelfunc<<<1, 1>>>(1, 1, 1); }
#endif
// Test that we've built a function to register kernels and global vars.
-// CHECK: define internal void @__cuda_register_globals
-// CHECK: call{{.*}}cudaRegisterFunction(i8** %0, {{.*}}kernelfunc
-// CHECK-DAG: call{{.*}}cudaRegisterVar(i8** %0, {{.*}}device_var{{.*}}i32 0, i32 4, i32 0, i32 0
-// CHECK-DAG: call{{.*}}cudaRegisterVar(i8** %0, {{.*}}constant_var{{.*}}i32 0, i32 4, i32 1, i32 0
-// CHECK-DAG: call{{.*}}cudaRegisterVar(i8** %0, {{.*}}ext_device_var{{.*}}i32 1, i32 4, i32 0, i32 0
-// CHECK-DAG: call{{.*}}cudaRegisterVar(i8** %0, {{.*}}ext_constant_var{{.*}}i32 1, i32 4, i32 1, i32 0
-// CHECK: ret void
-
-// Test that we've built contructor..
-// CHECK: define internal void @__cuda_module_ctor
-// .. that calls __cudaRegisterFatBinary(&__cuda_fatbin_wrapper)
-// CHECK: call{{.*}}cudaRegisterFatBinary{{.*}}__cuda_fatbin_wrapper
-// .. stores return value in __cuda_gpubin_handle
-// CHECK-NEXT: store{{.*}}__cuda_gpubin_handle
-// .. and then calls __cuda_register_globals
-// CHECK-NEXT: call void @__cuda_register_globals
+// ALL: define internal void @__[[PREFIX]]_register_globals
+// ALL: call{{.*}}[[PREFIX]]RegisterFunction(i8** %0, {{.*}}kernelfunc
+// ALL-DAG: call{{.*}}[[PREFIX]]RegisterVar(i8** %0, {{.*}}device_var{{.*}}i32 0, i32 4, i32 0, i32 0
+// ALL-DAG: call{{.*}}[[PREFIX]]RegisterVar(i8** %0, {{.*}}constant_var{{.*}}i32 0, i32 4, i32 1, i32 0
+// ALL-DAG: call{{.*}}[[PREFIX]]RegisterVar(i8** %0, {{.*}}ext_device_var{{.*}}i32 1, i32 4, i32 0, i32 0
+// ALL-DAG: call{{.*}}[[PREFIX]]RegisterVar(i8** %0, {{.*}}ext_constant_var{{.*}}i32 1, i32 4, i32 1, i32 0
+// ALL: ret void
+
+// Test that we've built a constructor.
+// ALL: define internal void @__[[PREFIX]]_module_ctor
+
+// In separate mode it calls __[[PREFIX]]RegisterFatBinary(&__[[PREFIX]]_fatbin_wrapper)
+// HIP only register fat binary once.
+// HIP: load i8**, i8*** @__hip_gpubin_handle
+// HIP-NEXT: icmp eq i8** {{.*}}, null
+// HIP-NEXT: br i1 {{.*}}, label %if, label %exit
+// HIP: if:
+// NORDC: call{{.*}}[[PREFIX]]RegisterFatBinary{{.*}}__[[PREFIX]]_fatbin_wrapper
+// .. stores return value in __[[PREFIX]]_gpubin_handle
+// NORDC-NEXT: store{{.*}}__[[PREFIX]]_gpubin_handle
+// .. and then calls __[[PREFIX]]_register_globals
+// HIP-NEXT: br label %exit
+// HIP: exit:
+// HIP-NEXT: load i8**, i8*** @__hip_gpubin_handle
+// NORDC-NEXT: call void @__[[PREFIX]]_register_globals
+// * In separate mode we also register a destructor.
+// NORDC-NEXT: call i32 @atexit(void (i8*)* @__[[PREFIX]]_module_dtor)
+
+// With relocatable device code we call __[[PREFIX]]RegisterLinkedBinary%NVModuleID%
+// RDC: call{{.*}}__[[PREFIX]]RegisterLinkedBinary[[MODULE_ID]](
+// RDC-SAME: __[[PREFIX]]_register_globals, {{.*}}__[[PREFIX]]_fatbin_wrapper
+// RDC-SAME: [[MODULE_ID_GLOBAL]]
// Test that we've created destructor.
-// CHECK: define internal void @__cuda_module_dtor
-// CHECK: load{{.*}}__cuda_gpubin_handle
-// CHECK-NEXT: call void @__cudaUnregisterFatBinary
-
-// There should be no __cuda_register_globals if we have no
+// NORDC: define internal void @__[[PREFIX]]_module_dtor
+// NORDC: load{{.*}}__[[PREFIX]]_gpubin_handle
+// CUDANORDC-NEXT: call void @__[[PREFIX]]UnregisterFatBinary
+// HIP-NEXT: icmp ne i8** {{.*}}, null
+// HIP-NEXT: br i1 {{.*}}, label %if, label %exit
+// HIP: if:
+// HIP-NEXT: call void @__[[PREFIX]]UnregisterFatBinary
+// HIP-NEXT: store i8** null, i8*** @__hip_gpubin_handle
+// HIP-NEXT: br label %exit
+// HIP: exit:
+
+// There should be no __[[PREFIX]]_register_globals if we have no
// device-side globals, but we still need to register GPU binary.
// Skip GPU binary string first.
-// NOGLOBALS: @0 = private unnamed_addr constant{{.*}}
-// NOGLOBALS-NOT: define internal void @__cuda_register_globals
-// NOGLOBALS: define internal void @__cuda_module_ctor
-// NOGLOBALS: call{{.*}}cudaRegisterFatBinary{{.*}}__cuda_fatbin_wrapper
-// NOGLOBALS-NOT: call void @__cuda_register_globals
-// NOGLOBALS: define internal void @__cuda_module_dtor
-// NOGLOBALS: call void @__cudaUnregisterFatBinary
+// CUDANOGLOBALS: @{{.*}} = private constant{{.*}}
+// HIPNOGLOBALS: @{{.*}} = external constant{{.*}}
+// NOGLOBALS-NOT: define internal void @__{{.*}}_register_globals
+// NOGLOBALS: define internal void @__[[PREFIX:cuda|hip]]_module_ctor
+// NOGLOBALS: call{{.*}}[[PREFIX]]RegisterFatBinary{{.*}}__[[PREFIX]]_fatbin_wrapper
+// NOGLOBALS-NOT: call void @__[[PREFIX]]_register_globals
+// NOGLOBALS: define internal void @__[[PREFIX]]_module_dtor
+// NOGLOBALS: call void @__[[PREFIX]]UnregisterFatBinary
// There should be no constructors/destructors if we have no GPU binary.
-// NOGPUBIN-NOT: define internal void @__cuda_register_globals
-// NOGPUBIN-NOT: define internal void @__cuda_module_ctor
-// NOGPUBIN-NOT: define internal void @__cuda_module_dtor
+// NOGPUBIN-NOT: define internal void @__[[PREFIX]]_register_globals
+// NOGPUBIN-NOT: define internal void @__[[PREFIX]]_module_ctor
+// NOGPUBIN-NOT: define internal void @__[[PREFIX]]_module_dtor
diff --git a/test/CodeGenCUDA/device-var-init.cu b/test/CodeGenCUDA/device-var-init.cu
index 0f4c64813406..9f788b764fbc 100644
--- a/test/CodeGenCUDA/device-var-init.cu
+++ b/test/CodeGenCUDA/device-var-init.cu
@@ -1,10 +1,14 @@
// REQUIRES: nvptx-registered-target
+// REQUIRES: amdgpu-registered-target
// Make sure we don't allow dynamic initialization for device
// variables, but accept empty constructors allowed by CUDA.
// RUN: %clang_cc1 -triple nvptx64-nvidia-cuda -fcuda-is-device -std=c++11 \
-// RUN: -fno-threadsafe-statics -emit-llvm -o - %s | FileCheck %s
+// RUN: -fno-threadsafe-statics -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK,NVPTX %s
+
+// RUN: %clang_cc1 -triple amdgcn -fcuda-is-device -std=c++11 \
+// RUN: -fno-threadsafe-statics -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK,AMDGCN %s
#ifdef __clang__
#include "Inputs/cuda.h"
@@ -105,50 +109,102 @@ __shared__ EC_I_EC s_ec_i_ec;
__constant__ EC_I_EC c_ec_i_ec;
// CHECK: @c_ec_i_ec = addrspace(4) externally_initialized global %struct.EC_I_EC zeroinitializer,
+// CHECK: @_ZZ2dfvE4s_ec = internal addrspace(3) global %struct.EC undef
+// CHECK: @_ZZ2dfvE5s_etc = internal addrspace(3) global %struct.ETC undef
+
// We should not emit global initializers for device-side variables.
// CHECK-NOT: @__cxx_global_var_init
// Make sure that initialization restrictions do not apply to local
// variables.
__device__ void df() {
+ // NVPTX: %[[ec:.*]] = alloca %struct.EC
+ // NVPTX: %[[ed:.*]] = alloca %struct.ED
+ // NVPTX: %[[ecd:.*]] = alloca %struct.ECD
+ // NVPTX: %[[etc:.*]] = alloca %struct.ETC
+ // NVPTX: %[[uc:.*]] = alloca %struct.UC
+ // NVPTX: %[[ud:.*]] = alloca %struct.UD
+ // NVPTX: %[[eci:.*]] = alloca %struct.ECI
+ // NVPTX: %[[nec:.*]] = alloca %struct.NEC
+ // NVPTX: %[[ned:.*]] = alloca %struct.NED
+ // NVPTX: %[[ncv:.*]] = alloca %struct.NCV
+ // NVPTX: %[[vd:.*]] = alloca %struct.VD
+ // NVPTX: %[[ncf:.*]] = alloca %struct.NCF
+ // NVPTX: %[[ncfs:.*]] = alloca %struct.NCFS
+ // NVPTX: %[[utc:.*]] = alloca %struct.UTC
+ // NVPTX: %[[netc:.*]] = alloca %struct.NETC
+ // NVPTX: %[[ec_i_ec:.*]] = alloca %struct.EC_I_EC
+ // NVPTX: %[[ec_i_ec1:.*]] = alloca %struct.EC_I_EC1
+ // NVPTX: %[[t_v_t:.*]] = alloca %struct.T_V_T
+ // NVPTX: %[[t_b_nec:.*]] = alloca %struct.T_B_NEC
+ // NVPTX: %[[t_f_nec:.*]] = alloca %struct.T_F_NEC
+ // NVPTX: %[[t_fa_nec:.*]] = alloca %struct.T_FA_NEC
+ // NVPTX: %[[t_b_ned:.*]] = alloca %struct.T_B_NED
+ // NVPTX: %[[t_f_ned:.*]] = alloca %struct.T_F_NED
+ // NVPTX: %[[t_fa_ned:.*]] = alloca %struct.T_FA_NED
+ // AMDGCN: %[[ec:.*]] = addrspacecast %struct.EC addrspace(5)* %ec to %struct.EC*
+ // AMDGCN: %[[ed:.*]] = addrspacecast %struct.ED addrspace(5)* %ed to %struct.ED*
+ // AMDGCN: %[[ecd:.*]] = addrspacecast %struct.ECD addrspace(5)* %ecd to %struct.ECD*
+ // AMDGCN: %[[etc:.*]] = addrspacecast %struct.ETC addrspace(5)* %etc to %struct.ETC*
+ // AMDGCN: %[[uc:.*]] = addrspacecast %struct.UC addrspace(5)* %uc to %struct.UC*
+ // AMDGCN: %[[ud:.*]] = addrspacecast %struct.UD addrspace(5)* %ud to %struct.UD*
+ // AMDGCN: %[[eci:.*]] = addrspacecast %struct.ECI addrspace(5)* %eci to %struct.ECI*
+ // AMDGCN: %[[nec:.*]] = addrspacecast %struct.NEC addrspace(5)* %nec to %struct.NEC*
+ // AMDGCN: %[[ned:.*]] = addrspacecast %struct.NED addrspace(5)* %ned to %struct.NED*
+ // AMDGCN: %[[ncv:.*]] = addrspacecast %struct.NCV addrspace(5)* %ncv to %struct.NCV*
+ // AMDGCN: %[[vd:.*]] = addrspacecast %struct.VD addrspace(5)* %vd to %struct.VD*
+ // AMDGCN: %[[ncf:.*]] = addrspacecast %struct.NCF addrspace(5)* %ncf to %struct.NCF*
+ // AMDGCN: %[[ncfs:.*]] = addrspacecast %struct.NCFS addrspace(5)* %ncfs to %struct.NCFS*
+ // AMDGCN: %[[utc:.*]] = addrspacecast %struct.UTC addrspace(5)* %utc to %struct.UTC*
+ // AMDGCN: %[[netc:.*]] = addrspacecast %struct.NETC addrspace(5)* %netc to %struct.NETC*
+ // AMDGCN: %[[ec_i_ec:.*]] = addrspacecast %struct.EC_I_EC addrspace(5)* %ec_i_ec to %struct.EC_I_EC*
+ // AMDGCN: %[[ec_i_ec1:.*]] = addrspacecast %struct.EC_I_EC1 addrspace(5)* %ec_i_ec1 to %struct.EC_I_EC1*
+ // AMDGCN: %[[t_v_t:.*]] = addrspacecast %struct.T_V_T addrspace(5)* %t_v_t to %struct.T_V_T*
+ // AMDGCN: %[[t_b_nec:.*]] = addrspacecast %struct.T_B_NEC addrspace(5)* %t_b_nec to %struct.T_B_NEC*
+ // AMDGCN: %[[t_f_nec:.*]] = addrspacecast %struct.T_F_NEC addrspace(5)* %t_f_nec to %struct.T_F_NEC*
+ // AMDGCN: %[[t_fa_nec:.*]] = addrspacecast %struct.T_FA_NEC addrspace(5)* %t_fa_nec to %struct.T_FA_NEC*
+ // AMDGCN: %[[t_b_ned:.*]] = addrspacecast %struct.T_B_NED addrspace(5)* %t_b_ned to %struct.T_B_NED*
+ // AMDGCN: %[[t_f_ned:.*]] = addrspacecast %struct.T_F_NED addrspace(5)* %t_f_ned to %struct.T_F_NED*
+ // AMDGCN: %[[t_fa_ned:.*]] = addrspacecast %struct.T_FA_NED addrspace(5)* %t_fa_ned to %struct.T_FA_NED*
+
T t;
// CHECK-NOT: call
EC ec;
- // CHECK: call void @_ZN2ECC1Ev(%struct.EC* %ec)
+ // CHECK: call void @_ZN2ECC1Ev(%struct.EC* %[[ec]])
ED ed;
// CHECK-NOT: call
ECD ecd;
- // CHECK: call void @_ZN3ECDC1Ev(%struct.ECD* %ecd)
+ // CHECK: call void @_ZN3ECDC1Ev(%struct.ECD* %[[ecd]])
ETC etc;
- // CHECK: call void @_ZN3ETCC1IJEEEDpT_(%struct.ETC* %etc)
+ // CHECK: call void @_ZN3ETCC1IJEEEDpT_(%struct.ETC* %[[etc]])
UC uc;
// undefined constructor -- not allowed
- // CHECK: call void @_ZN2UCC1Ev(%struct.UC* %uc)
+ // CHECK: call void @_ZN2UCC1Ev(%struct.UC* %[[uc]])
UD ud;
// undefined destructor -- not allowed
// CHECK-NOT: call
ECI eci;
// empty constructor w/ initializer list -- not allowed
- // CHECK: call void @_ZN3ECIC1Ev(%struct.ECI* %eci)
+ // CHECK: call void @_ZN3ECIC1Ev(%struct.ECI* %[[eci]])
NEC nec;
// non-empty constructor -- not allowed
- // CHECK: call void @_ZN3NECC1Ev(%struct.NEC* %nec)
+ // CHECK: call void @_ZN3NECC1Ev(%struct.NEC* %[[nec]])
// non-empty destructor -- not allowed
NED ned;
// no-constructor, virtual method -- not allowed
- // CHECK: call void @_ZN3NCVC1Ev(%struct.NCV* %ncv)
+ // CHECK: call void @_ZN3NCVC1Ev(%struct.NCV* %[[ncv]])
NCV ncv;
// CHECK-NOT: call
VD vd;
- // CHECK: call void @_ZN2VDC1Ev(%struct.VD* %vd)
+ // CHECK: call void @_ZN2VDC1Ev(%struct.VD* %[[vd]])
NCF ncf;
- // CHECK: call void @_ZN3NCFC1Ev(%struct.NCF* %ncf)
+ // CHECK: call void @_ZN3NCFC1Ev(%struct.NCF* %[[ncf]])
NCFS ncfs;
- // CHECK: call void @_ZN4NCFSC1Ev(%struct.NCFS* %ncfs)
+ // CHECK: call void @_ZN4NCFSC1Ev(%struct.NCFS* %[[ncfs]])
UTC utc;
- // CHECK: call void @_ZN3UTCC1IJEEEDpT_(%struct.UTC* %utc)
+ // CHECK: call void @_ZN3UTCC1IJEEEDpT_(%struct.UTC* %[[utc]])
NETC netc;
- // CHECK: call void @_ZN4NETCC1IJEEEDpT_(%struct.NETC* %netc)
+ // CHECK: call void @_ZN4NETCC1IJEEEDpT_(%struct.NETC* %[[netc]])
T_B_T t_b_t;
// CHECK-NOT: call
T_F_T t_f_t;
@@ -156,17 +212,17 @@ __device__ void df() {
T_FA_T t_fa_t;
// CHECK-NOT: call
EC_I_EC ec_i_ec;
- // CHECK: call void @_ZN7EC_I_ECC1Ev(%struct.EC_I_EC* %ec_i_ec)
+ // CHECK: call void @_ZN7EC_I_ECC1Ev(%struct.EC_I_EC* %[[ec_i_ec]])
EC_I_EC1 ec_i_ec1;
- // CHECK: call void @_ZN8EC_I_EC1C1Ev(%struct.EC_I_EC1* %ec_i_ec1)
+ // CHECK: call void @_ZN8EC_I_EC1C1Ev(%struct.EC_I_EC1* %[[ec_i_ec1]])
T_V_T t_v_t;
- // CHECK: call void @_ZN5T_V_TC1Ev(%struct.T_V_T* %t_v_t)
+ // CHECK: call void @_ZN5T_V_TC1Ev(%struct.T_V_T* %[[t_v_t]])
T_B_NEC t_b_nec;
- // CHECK: call void @_ZN7T_B_NECC1Ev(%struct.T_B_NEC* %t_b_nec)
+ // CHECK: call void @_ZN7T_B_NECC1Ev(%struct.T_B_NEC* %[[t_b_nec]])
T_F_NEC t_f_nec;
- // CHECK: call void @_ZN7T_F_NECC1Ev(%struct.T_F_NEC* %t_f_nec)
+ // CHECK: call void @_ZN7T_F_NECC1Ev(%struct.T_F_NEC* %[[t_f_nec]])
T_FA_NEC t_fa_nec;
- // CHECK: call void @_ZN8T_FA_NECC1Ev(%struct.T_FA_NEC* %t_fa_nec)
+ // CHECK: call void @_ZN8T_FA_NECC1Ev(%struct.T_FA_NEC* %[[t_fa_nec]])
T_B_NED t_b_ned;
// CHECK-NOT: call
T_F_NED t_f_ned;
@@ -182,14 +238,14 @@ __device__ void df() {
df(); // CHECK: call void @_Z2dfv()
// Verify that we only call non-empty destructors
- // CHECK-NEXT: call void @_ZN8T_FA_NEDD1Ev(%struct.T_FA_NED* %t_fa_ned)
- // CHECK-NEXT: call void @_ZN7T_F_NEDD1Ev(%struct.T_F_NED* %t_f_ned)
- // CHECK-NEXT: call void @_ZN7T_B_NEDD1Ev(%struct.T_B_NED* %t_b_ned)
- // CHECK-NEXT: call void @_ZN2VDD1Ev(%struct.VD* %vd)
- // CHECK-NEXT: call void @_ZN3NEDD1Ev(%struct.NED* %ned)
- // CHECK-NEXT: call void @_ZN2UDD1Ev(%struct.UD* %ud)
- // CHECK-NEXT: call void @_ZN3ECDD1Ev(%struct.ECD* %ecd)
- // CHECK-NEXT: call void @_ZN2EDD1Ev(%struct.ED* %ed)
+ // CHECK-NEXT: call void @_ZN8T_FA_NEDD1Ev(%struct.T_FA_NED* %[[t_fa_ned]])
+ // CHECK-NEXT: call void @_ZN7T_F_NEDD1Ev(%struct.T_F_NED* %[[t_f_ned]])
+ // CHECK-NEXT: call void @_ZN7T_B_NEDD1Ev(%struct.T_B_NED* %[[t_b_ned]])
+ // CHECK-NEXT: call void @_ZN2VDD1Ev(%struct.VD* %[[vd]])
+ // CHECK-NEXT: call void @_ZN3NEDD1Ev(%struct.NED* %[[ned]])
+ // CHECK-NEXT: call void @_ZN2UDD1Ev(%struct.UD* %[[ud]])
+ // CHECK-NEXT: call void @_ZN3ECDD1Ev(%struct.ECD* %[[ecd]])
+ // CHECK-NEXT: call void @_ZN2EDD1Ev(%struct.ED* %[[ed]])
// CHECK-NEXT: ret void
}
diff --git a/test/CodeGenCUDA/device-vtable.cu b/test/CodeGenCUDA/device-vtable.cu
index 9730e404caa4..a7307dcdaf9b 100644
--- a/test/CodeGenCUDA/device-vtable.cu
+++ b/test/CodeGenCUDA/device-vtable.cu
@@ -19,7 +19,9 @@ struct H {
//CHECK-HOST: @_ZTV1H =
//CHECK-HOST-SAME: @_ZN1H6methodEv
//CHECK-DEVICE-NOT: @_ZTV1H =
-
+//CHECK-DEVICE-NOT: @_ZTVN10__cxxabiv117__class_type_infoE
+//CHECK-DEVICE-NOT: @_ZTS1H
+//CHECK-DEVICE-NOT: @_ZTI1H
struct D {
__device__ virtual void method();
};
@@ -27,7 +29,9 @@ struct D {
//CHECK-DEVICE: @_ZTV1D
//CHECK-DEVICE-SAME: @_ZN1D6methodEv
//CHECK-HOST-NOT: @_ZTV1D
-
+//CHECK-DEVICE-NOT: @_ZTVN10__cxxabiv117__class_type_infoE
+//CHECK-DEVICE-NOT: @_ZTS1D
+//CHECK-DEVICE-NOT: @_ZTI1D
// This is the case with mixed host and device virtual methods. It's
// impossible to emit a valid vtable in that case because only host or
// only device methods would be available during host or device
@@ -45,6 +49,9 @@ struct HD {
// CHECK-HOST-NOT: @_ZN2HD8d_methodEv
// CHECK-HOST-SAME: null
// CHECK-BOTH-SAME: ]
+// CHECK-DEVICE-NOT: @_ZTVN10__cxxabiv117__class_type_infoE
+// CHECK-DEVICE-NOT: @_ZTS2HD
+// CHECK-DEVICE-NOT: @_ZTI2HD
void H::method() {}
//CHECK-HOST: define void @_ZN1H6methodEv
diff --git a/test/CodeGenCUDA/filter-decl.cu b/test/CodeGenCUDA/filter-decl.cu
index bc744a07a330..0f4691f7c8aa 100644
--- a/test/CodeGenCUDA/filter-decl.cu
+++ b/test/CodeGenCUDA/filter-decl.cu
@@ -10,18 +10,18 @@
__asm__("file scope asm is host only");
// CHECK-HOST: constantdata = internal global
-// CHECK-DEVICE: constantdata = externally_initialized global
+// CHECK-DEVICE: constantdata = {{(dso_local )?}}externally_initialized global
__constant__ char constantdata[256];
// CHECK-HOST: devicedata = internal global
-// CHECK-DEVICE: devicedata = externally_initialized global
+// CHECK-DEVICE: devicedata = {{(dso_local )?}}externally_initialized global
__device__ char devicedata[256];
// CHECK-HOST: shareddata = internal global
-// CHECK-DEVICE: shareddata = global
+// CHECK-DEVICE: shareddata = {{(dso_local )?}}global
__shared__ char shareddata[256];
-// CHECK-HOST: hostdata = global
+// CHECK-HOST: hostdata = {{(dso_local )?}}global
// CHECK-DEVICE-NOT: hostdata = global
char hostdata[256];
diff --git a/test/CodeGenCUDA/flush-denormals.cu b/test/CodeGenCUDA/flush-denormals.cu
index 94285f1f33ce..13f2e3b2871e 100644
--- a/test/CodeGenCUDA/flush-denormals.cu
+++ b/test/CodeGenCUDA/flush-denormals.cu
@@ -5,6 +5,13 @@
// RUN: -triple nvptx-nvidia-cuda -emit-llvm -o - %s | \
// RUN: FileCheck %s -check-prefix CHECK -check-prefix FTZ
+// RUN: %clang_cc1 -fcuda-is-device -x hip \
+// RUN: -triple amdgcn-amd-amdhsa -target-cpu gfx900 -emit-llvm -o - %s | \
+// RUN: FileCheck %s -check-prefix CHECK -check-prefix AMDNOFTZ
+// RUN: %clang_cc1 -fcuda-is-device -x hip -fcuda-flush-denormals-to-zero \
+// RUN: -triple amdgcn-amd-amdhsa -target-cpu gfx900 -emit-llvm -o - %s | \
+// RUN: FileCheck %s -check-prefix CHECK -check-prefix AMDFTZ
+
#include "Inputs/cuda.h"
// Checks that device function calls get emitted with the "ntpvx-f32ftz"
@@ -12,11 +19,19 @@
// -fcuda-flush-denormals-to-zero. Further, check that we reflect the presence
// or absence of -fcuda-flush-denormals-to-zero in a module flag.
+// AMDGCN targets always have +fp64-fp16-denormals.
+// AMDGCN targets without fast FMAF (e.g. gfx803) always have +fp32-denormals.
+// For AMDGCN target with fast FMAF (e.g. gfx900), it has +fp32-denormals
+// by default and -fp32-denormals when there is option
+// -fcuda-flush-denormals-to-zero.
+
// CHECK-LABEL: define void @foo() #0
extern "C" __device__ void foo() {}
// FTZ: attributes #0 = {{.*}} "nvptx-f32ftz"="true"
// NOFTZ-NOT: attributes #0 = {{.*}} "nvptx-f32ftz"
+// AMDNOFTZ: attributes #0 = {{.*}}+fp32-denormals{{.*}}+fp64-fp16-denormals
+// AMDFTZ: attributes #0 = {{.*}}+fp64-fp16-denormals{{.*}}-fp32-denormals
// FTZ:!llvm.module.flags = !{{{.*}}[[MODFLAG:![0-9]+]]}
// FTZ:[[MODFLAG]] = !{i32 4, !"nvvm-reflect-ftz", i32 1}
diff --git a/test/CodeGenCUDA/kernel-amdgcn.cu b/test/CodeGenCUDA/kernel-amdgcn.cu
new file mode 100644
index 000000000000..ffa6c9549f07
--- /dev/null
+++ b/test/CodeGenCUDA/kernel-amdgcn.cu
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 -triple amdgcn -fcuda-is-device -emit-llvm %s -o - | FileCheck %s
+#include "Inputs/cuda.h"
+
+// CHECK: define amdgpu_kernel void @_ZN1A6kernelEv
+class A {
+public:
+ static __global__ void kernel(){}
+};
+
+// CHECK: define void @_Z10non_kernelv
+__device__ void non_kernel(){}
+
+// CHECK: define amdgpu_kernel void @_Z6kerneli
+__global__ void kernel(int x) {
+ non_kernel();
+}
+
+// CHECK: define amdgpu_kernel void @_Z11EmptyKernelIvEvv
+template <typename T>
+__global__ void EmptyKernel(void) {}
+
+struct Dummy {
+ /// Type definition of the EmptyKernel kernel entry point
+ typedef void (*EmptyKernelPtr)();
+ EmptyKernelPtr Empty() { return EmptyKernel<void>; }
+};
+
+// CHECK: define amdgpu_kernel void @_Z15template_kernelI1AEvT_
+template<class T>
+__global__ void template_kernel(T x) {}
+
+void launch(void *f);
+
+int main() {
+ Dummy D;
+ launch((void*)A::kernel);
+ launch((void*)kernel);
+ launch((void*)template_kernel<A>);
+ launch((void*)D.Empty());
+ return 0;
+}
diff --git a/test/CodeGenCUDA/kernel-args.cu b/test/CodeGenCUDA/kernel-args.cu
new file mode 100644
index 000000000000..d0986629f8d4
--- /dev/null
+++ b/test/CodeGenCUDA/kernel-args.cu
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -fcuda-is-device \
+// RUN: -emit-llvm %s -o - | FileCheck -check-prefix=AMDGCN %s
+// RUN: %clang_cc1 -triple nvptx64-nvidia-cuda- -fcuda-is-device \
+// RUN: -emit-llvm %s -o - | FileCheck -check-prefix=NVPTX %s
+#include "Inputs/cuda.h"
+
+struct A {
+ int a[32];
+};
+
+// AMDGCN: define amdgpu_kernel void @_Z6kernel1A(%struct.A %x.coerce)
+// NVPTX: define void @_Z6kernel1A(%struct.A* byval align 4 %x)
+__global__ void kernel(A x) {
+}
+
+class Kernel {
+public:
+ // AMDGCN: define amdgpu_kernel void @_ZN6Kernel12memberKernelE1A(%struct.A %x.coerce)
+ // NVPTX: define void @_ZN6Kernel12memberKernelE1A(%struct.A* byval align 4 %x)
+ static __global__ void memberKernel(A x){}
+ template<typename T> static __global__ void templateMemberKernel(T x) {}
+};
+
+
+template <typename T>
+__global__ void templateKernel(T x) {}
+
+void launch(void*);
+
+void test() {
+ Kernel K;
+ // AMDGCN: define amdgpu_kernel void @_Z14templateKernelI1AEvT_(%struct.A %x.coerce)
+ // NVPTX: define void @_Z14templateKernelI1AEvT_(%struct.A* byval align 4 %x)
+ launch((void*)templateKernel<A>);
+
+ // AMDGCN: define amdgpu_kernel void @_ZN6Kernel20templateMemberKernelI1AEEvT_(%struct.A %x.coerce)
+ // NVPTX: define void @_ZN6Kernel20templateMemberKernelI1AEEvT_(%struct.A* byval align 4 %x)
+ launch((void*)Kernel::templateMemberKernel<A>);
+}
diff --git a/test/CodeGenCUDA/kernel-call.cu b/test/CodeGenCUDA/kernel-call.cu
index 9b849db908f8..43d08dfaf89b 100644
--- a/test/CodeGenCUDA/kernel-call.cu
+++ b/test/CodeGenCUDA/kernel-call.cu
@@ -1,11 +1,20 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s --check-prefixes=CUDA,CHECK
+// RUN: %clang_cc1 -x hip -emit-llvm %s -o - | FileCheck %s --check-prefixes=HIP,CHECK
+
#include "Inputs/cuda.h"
+// CHECK-LABEL: define{{.*}}g1
+// HIP: call{{.*}}hipSetupArgument
+// HIP: call{{.*}}hipLaunchByPtr
+// CUDA: call{{.*}}cudaSetupArgument
+// CUDA: call{{.*}}cudaLaunch
__global__ void g1(int x) {}
+// CHECK-LABEL: define{{.*}}main
int main(void) {
- // CHECK: call{{.*}}cudaConfigureCall
+ // HIP: call{{.*}}hipConfigureCall
+ // CUDA: call{{.*}}cudaConfigureCall
// CHECK: icmp
// CHECK: br
// CHECK: call{{.*}}g1
diff --git a/test/CodeGenCUDA/library-builtin.cu b/test/CodeGenCUDA/library-builtin.cu
new file mode 100644
index 000000000000..4804c75cde38
--- /dev/null
+++ b/test/CodeGenCUDA/library-builtin.cu
@@ -0,0 +1,22 @@
+// REQUIRES: x86-registered-target
+// REQUIRES: nvptx-registered-target
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | \
+// RUN: FileCheck --check-prefixes=HOST,BOTH %s
+// RUN: %clang_cc1 -fcuda-is-device -triple nvptx64-nvidia-cuda \
+// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefixes=DEVICE,BOTH
+
+// BOTH-LABEL: define float @logf(float
+
+// logf() should be calling itself recursively as we don't have any standard
+// library on device side.
+// DEVICE: call float @logf(float
+extern "C" __attribute__((device)) float logf(float __x) { return logf(__x); }
+
+// NOTE: this case is to illustrate the expected differences in behavior between
+// the host and device. In general we do not mess with host-side standard
+// library.
+//
+// Host is assumed to have standard library, so logf() calls LLVM intrinsic.
+// HOST: call float @llvm.log.f32(float
+extern "C" float logf(float __x) { return logf(__x); }
diff --git a/test/CodeGenCUDA/link-device-bitcode.cu b/test/CodeGenCUDA/link-device-bitcode.cu
index 869fcb1bc938..b307838ae82d 100644
--- a/test/CodeGenCUDA/link-device-bitcode.cu
+++ b/test/CodeGenCUDA/link-device-bitcode.cu
@@ -31,7 +31,7 @@
// Make sure NVVMReflect pass is enabled in NVPTX back-end.
// RUN: %clang_cc1 -triple nvptx-unknown-cuda -fcuda-is-device \
// RUN: -mlink-cuda-bitcode %t.bc -S -o /dev/null %s \
-// RUN: -backend-option -debug-pass=Structure 2>&1 \
+// RUN: -mllvm -debug-pass=Structure 2>&1 \
// RUN: | FileCheck %s -check-prefix CHECK-REFLECT
#include "Inputs/cuda.h"
diff --git a/test/CodeGenCUDA/propagate-metadata.cu b/test/CodeGenCUDA/propagate-metadata.cu
index f8db765099ef..1616cb933748 100644
--- a/test/CodeGenCUDA/propagate-metadata.cu
+++ b/test/CodeGenCUDA/propagate-metadata.cu
@@ -29,7 +29,7 @@
// RUN: -fcuda-is-device -menable-unsafe-fp-math -triple nvptx-unknown-unknown \
// RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=FAST
-// Wrap everything in extern "C" so we don't ahve to worry about name mangling
+// Wrap everything in extern "C" so we don't have to worry about name mangling
// in the IR.
extern "C" {
#ifdef LIB
diff --git a/test/CodeGenCXX/Inputs/override-bit-field-layout.layout b/test/CodeGenCXX/Inputs/override-bit-field-layout.layout
new file mode 100644
index 000000000000..8e67dce65026
--- /dev/null
+++ b/test/CodeGenCXX/Inputs/override-bit-field-layout.layout
@@ -0,0 +1,16 @@
+
+*** Dumping AST Record Layout
+Type: struct S1
+
+Layout: <ASTRecordLayout
+ Size:16
+ Alignment:16
+ FieldOffsets: [0, 11]>
+
+*** Dumping AST Record Layout
+Type: struct S2
+
+Layout: <ASTRecordLayout
+ Size:128
+ Alignment:64
+ FieldOffsets: [64]>
diff --git a/test/CodeGenCXX/Inputs/std-compare.h b/test/CodeGenCXX/Inputs/std-compare.h
new file mode 100644
index 000000000000..a6ab605bb527
--- /dev/null
+++ b/test/CodeGenCXX/Inputs/std-compare.h
@@ -0,0 +1,437 @@
+#ifndef STD_COMPARE_H
+#define STD_COMPARE_H
+
+namespace std {
+inline namespace __1 {
+
+// exposition only
+enum class _EqResult : unsigned char {
+ __zero = 0,
+ __equal = __zero,
+ __equiv = __equal,
+ __nonequal = 1,
+ __nonequiv = __nonequal
+};
+
+enum class _OrdResult : signed char {
+ __less = -1,
+ __greater = 1
+};
+
+enum class _NCmpResult : signed char {
+ __unordered = -127
+};
+
+struct _CmpUnspecifiedType;
+using _CmpUnspecifiedParam = void (_CmpUnspecifiedType::*)();
+
+class weak_equality {
+ constexpr explicit weak_equality(_EqResult __val) noexcept : __value_(__val) {}
+
+public:
+ static const weak_equality equivalent;
+ static const weak_equality nonequivalent;
+
+ friend constexpr bool operator==(weak_equality __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator==(_CmpUnspecifiedParam, weak_equality __v) noexcept;
+ friend constexpr bool operator!=(weak_equality __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator!=(_CmpUnspecifiedParam, weak_equality __v) noexcept;
+ friend constexpr weak_equality operator<=>(weak_equality __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr weak_equality operator<=>(_CmpUnspecifiedParam, weak_equality __v) noexcept;
+
+ // test helper
+ constexpr bool test_eq(weak_equality const &other) const noexcept {
+ return __value_ == other.__value_;
+ }
+
+private:
+ _EqResult __value_;
+};
+
+inline constexpr weak_equality weak_equality::equivalent(_EqResult::__equiv);
+inline constexpr weak_equality weak_equality::nonequivalent(_EqResult::__nonequiv);
+inline constexpr bool operator==(weak_equality __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ == _EqResult::__zero;
+}
+inline constexpr bool operator==(_CmpUnspecifiedParam, weak_equality __v) noexcept {
+ return __v.__value_ == _EqResult::__zero;
+}
+inline constexpr bool operator!=(weak_equality __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ != _EqResult::__zero;
+}
+inline constexpr bool operator!=(_CmpUnspecifiedParam, weak_equality __v) noexcept {
+ return __v.__value_ != _EqResult::__zero;
+}
+
+inline constexpr weak_equality operator<=>(weak_equality __v, _CmpUnspecifiedParam) noexcept {
+ return __v;
+}
+inline constexpr weak_equality operator<=>(_CmpUnspecifiedParam, weak_equality __v) noexcept {
+ return __v;
+}
+
+class strong_equality {
+ explicit constexpr strong_equality(_EqResult __val) noexcept : __value_(__val) {}
+
+public:
+ static const strong_equality equal;
+ static const strong_equality nonequal;
+ static const strong_equality equivalent;
+ static const strong_equality nonequivalent;
+
+ // conversion
+ constexpr operator weak_equality() const noexcept {
+ return __value_ == _EqResult::__zero ? weak_equality::equivalent
+ : weak_equality::nonequivalent;
+ }
+
+ // comparisons
+ friend constexpr bool operator==(strong_equality __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator!=(strong_equality __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator==(_CmpUnspecifiedParam, strong_equality __v) noexcept;
+ friend constexpr bool operator!=(_CmpUnspecifiedParam, strong_equality __v) noexcept;
+
+ friend constexpr strong_equality operator<=>(strong_equality __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr strong_equality operator<=>(_CmpUnspecifiedParam, strong_equality __v) noexcept;
+
+ // test helper
+ constexpr bool test_eq(strong_equality const &other) const noexcept {
+ return __value_ == other.__value_;
+ }
+
+private:
+ _EqResult __value_;
+};
+
+inline constexpr strong_equality strong_equality::equal(_EqResult::__equal);
+inline constexpr strong_equality strong_equality::nonequal(_EqResult::__nonequal);
+inline constexpr strong_equality strong_equality::equivalent(_EqResult::__equiv);
+inline constexpr strong_equality strong_equality::nonequivalent(_EqResult::__nonequiv);
+constexpr bool operator==(strong_equality __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ == _EqResult::__zero;
+}
+constexpr bool operator==(_CmpUnspecifiedParam, strong_equality __v) noexcept {
+ return __v.__value_ == _EqResult::__zero;
+}
+constexpr bool operator!=(strong_equality __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ != _EqResult::__zero;
+}
+constexpr bool operator!=(_CmpUnspecifiedParam, strong_equality __v) noexcept {
+ return __v.__value_ != _EqResult::__zero;
+}
+
+constexpr strong_equality operator<=>(strong_equality __v, _CmpUnspecifiedParam) noexcept {
+ return __v;
+}
+constexpr strong_equality operator<=>(_CmpUnspecifiedParam, strong_equality __v) noexcept {
+ return __v;
+}
+
+class partial_ordering {
+ using _ValueT = signed char;
+ explicit constexpr partial_ordering(_EqResult __v) noexcept
+ : __value_(_ValueT(__v)) {}
+ explicit constexpr partial_ordering(_OrdResult __v) noexcept
+ : __value_(_ValueT(__v)) {}
+ explicit constexpr partial_ordering(_NCmpResult __v) noexcept
+ : __value_(_ValueT(__v)) {}
+
+ constexpr bool __is_ordered() const noexcept {
+ return __value_ != _ValueT(_NCmpResult::__unordered);
+ }
+
+public:
+ // valid values
+ static const partial_ordering less;
+ static const partial_ordering equivalent;
+ static const partial_ordering greater;
+ static const partial_ordering unordered;
+
+ // conversion
+ constexpr operator weak_equality() const noexcept {
+ return __value_ == 0 ? weak_equality::equivalent : weak_equality::nonequivalent;
+ }
+
+ // comparisons
+ friend constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator!=(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator<(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator>(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator==(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
+ friend constexpr bool operator!=(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
+ friend constexpr bool operator<(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
+ friend constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
+ friend constexpr bool operator>(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
+ friend constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
+
+ friend constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
+
+ // test helper
+ constexpr bool test_eq(partial_ordering const &other) const noexcept {
+ return __value_ == other.__value_;
+ }
+
+private:
+ _ValueT __value_;
+};
+
+inline constexpr partial_ordering partial_ordering::less(_OrdResult::__less);
+inline constexpr partial_ordering partial_ordering::equivalent(_EqResult::__equiv);
+inline constexpr partial_ordering partial_ordering::greater(_OrdResult::__greater);
+inline constexpr partial_ordering partial_ordering::unordered(_NCmpResult ::__unordered);
+constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__is_ordered() && __v.__value_ == 0;
+}
+constexpr bool operator<(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__is_ordered() && __v.__value_ < 0;
+}
+constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__is_ordered() && __v.__value_ <= 0;
+}
+constexpr bool operator>(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__is_ordered() && __v.__value_ > 0;
+}
+constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__is_ordered() && __v.__value_ >= 0;
+}
+constexpr bool operator==(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
+ return __v.__is_ordered() && 0 == __v.__value_;
+}
+constexpr bool operator<(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
+ return __v.__is_ordered() && 0 < __v.__value_;
+}
+constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
+ return __v.__is_ordered() && 0 <= __v.__value_;
+}
+constexpr bool operator>(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
+ return __v.__is_ordered() && 0 > __v.__value_;
+}
+constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
+ return __v.__is_ordered() && 0 >= __v.__value_;
+}
+constexpr bool operator!=(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return !__v.__is_ordered() || __v.__value_ != 0;
+}
+constexpr bool operator!=(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
+ return !__v.__is_ordered() || __v.__value_ != 0;
+}
+
+constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v;
+}
+constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
+ return __v < 0 ? partial_ordering::greater : (__v > 0 ? partial_ordering::less : __v);
+}
+
+class weak_ordering {
+ using _ValueT = signed char;
+ explicit constexpr weak_ordering(_EqResult __v) noexcept : __value_(_ValueT(__v)) {}
+ explicit constexpr weak_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {}
+
+public:
+ static const weak_ordering less;
+ static const weak_ordering equivalent;
+ static const weak_ordering greater;
+
+ // conversions
+ constexpr operator weak_equality() const noexcept {
+ return __value_ == 0 ? weak_equality::equivalent
+ : weak_equality::nonequivalent;
+ }
+ constexpr operator partial_ordering() const noexcept {
+ return __value_ == 0 ? partial_ordering::equivalent
+ : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater);
+ }
+
+ // comparisons
+ friend constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator!=(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator<(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator>(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator==(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
+ friend constexpr bool operator!=(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
+ friend constexpr bool operator<(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
+ friend constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
+ friend constexpr bool operator>(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
+ friend constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
+
+ friend constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
+
+ // test helper
+ constexpr bool test_eq(weak_ordering const &other) const noexcept {
+ return __value_ == other.__value_;
+ }
+
+private:
+ _ValueT __value_;
+};
+
+inline constexpr weak_ordering weak_ordering::less(_OrdResult::__less);
+inline constexpr weak_ordering weak_ordering::equivalent(_EqResult::__equiv);
+inline constexpr weak_ordering weak_ordering::greater(_OrdResult::__greater);
+constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ == 0;
+}
+constexpr bool operator!=(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ != 0;
+}
+constexpr bool operator<(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ < 0;
+}
+constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ <= 0;
+}
+constexpr bool operator>(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ > 0;
+}
+constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ >= 0;
+}
+constexpr bool operator==(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
+ return 0 == __v.__value_;
+}
+constexpr bool operator!=(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
+ return 0 != __v.__value_;
+}
+constexpr bool operator<(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
+ return 0 < __v.__value_;
+}
+constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
+ return 0 <= __v.__value_;
+}
+constexpr bool operator>(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
+ return 0 > __v.__value_;
+}
+constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
+ return 0 >= __v.__value_;
+}
+
+constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v;
+}
+constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
+ return __v < 0 ? weak_ordering::greater : (__v > 0 ? weak_ordering::less : __v);
+}
+
+class strong_ordering {
+ using _ValueT = signed char;
+ explicit constexpr strong_ordering(_EqResult __v) noexcept : __value_(static_cast<signed char>(__v)) {}
+ explicit constexpr strong_ordering(_OrdResult __v) noexcept : __value_(static_cast<signed char>(__v)) {}
+
+public:
+ static const strong_ordering less;
+ static const strong_ordering equal;
+ static const strong_ordering equivalent;
+ static const strong_ordering greater;
+
+ // conversions
+ constexpr operator weak_equality() const noexcept {
+ return __value_ == 0 ? weak_equality::equivalent
+ : weak_equality::nonequivalent;
+ }
+ constexpr operator strong_equality() const noexcept {
+ return __value_ == 0 ? strong_equality::equal
+ : strong_equality::nonequal;
+ }
+ constexpr operator partial_ordering() const noexcept {
+ return __value_ == 0 ? partial_ordering::equivalent
+ : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater);
+ }
+ constexpr operator weak_ordering() const noexcept {
+ return __value_ == 0 ? weak_ordering::equivalent
+ : (__value_ < 0 ? weak_ordering::less : weak_ordering::greater);
+ }
+
+ // comparisons
+ friend constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator!=(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator<(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator>(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator==(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
+ friend constexpr bool operator!=(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
+ friend constexpr bool operator<(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
+ friend constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
+ friend constexpr bool operator>(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
+ friend constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
+
+ friend constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
+
+ // test helper
+ constexpr bool test_eq(strong_ordering const &other) const noexcept {
+ return __value_ == other.__value_;
+ }
+
+private:
+ _ValueT __value_;
+};
+
+inline constexpr strong_ordering strong_ordering::less(_OrdResult::__less);
+inline constexpr strong_ordering strong_ordering::equal(_EqResult::__equal);
+inline constexpr strong_ordering strong_ordering::equivalent(_EqResult::__equiv);
+inline constexpr strong_ordering strong_ordering::greater(_OrdResult::__greater);
+
+constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ == 0;
+}
+constexpr bool operator!=(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ != 0;
+}
+constexpr bool operator<(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ < 0;
+}
+constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ <= 0;
+}
+constexpr bool operator>(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ > 0;
+}
+constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ >= 0;
+}
+constexpr bool operator==(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
+ return 0 == __v.__value_;
+}
+constexpr bool operator!=(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
+ return 0 != __v.__value_;
+}
+constexpr bool operator<(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
+ return 0 < __v.__value_;
+}
+constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
+ return 0 <= __v.__value_;
+}
+constexpr bool operator>(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
+ return 0 > __v.__value_;
+}
+constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
+ return 0 >= __v.__value_;
+}
+
+constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v;
+}
+constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
+ return __v < 0 ? strong_ordering::greater : (__v > 0 ? strong_ordering::less : __v);
+}
+
+// named comparison functions
+constexpr bool is_eq(weak_equality __cmp) noexcept { return __cmp == 0; }
+constexpr bool is_neq(weak_equality __cmp) noexcept { return __cmp != 0; }
+constexpr bool is_lt(partial_ordering __cmp) noexcept { return __cmp < 0; }
+constexpr bool is_lteq(partial_ordering __cmp) noexcept { return __cmp <= 0; }
+constexpr bool is_gt(partial_ordering __cmp) noexcept { return __cmp > 0; }
+constexpr bool is_gteq(partial_ordering __cmp) noexcept { return __cmp >= 0; }
+
+} // namespace __1
+} // end namespace std
+
+#endif // STD_COMPARE_H
diff --git a/test/CodeGenCXX/PR19955.cpp b/test/CodeGenCXX/PR19955.cpp
index 100108437752..5175b74aae7f 100644
--- a/test/CodeGenCXX/PR19955.cpp
+++ b/test/CodeGenCXX/PR19955.cpp
@@ -6,22 +6,22 @@ extern void __declspec(dllimport) fun();
extern int *varp;
int *varp = &var;
-// CHECK-DAG: @"\01?varp@@3PAHA" = global i32* null
-// X64-DAG: @"\01?varp@@3PEAHEA" = global i32* null
+// CHECK-DAG: @"?varp@@3PAHA" = dso_local global i32* null
+// X64-DAG: @"?varp@@3PEAHEA" = dso_local global i32* null
extern void (*funp)();
void (*funp)() = &fun;
-// CHECK-DAG: @"\01?funp@@3P6AXXZA" = global void ()* null
-// X64-DAG: @"\01?funp@@3P6AXXZEA" = global void ()* null
+// CHECK-DAG: @"?funp@@3P6AXXZA" = dso_local global void ()* null
+// X64-DAG: @"?funp@@3P6AXXZEA" = dso_local global void ()* null
-// CHECK-LABEL: @"\01??__Evarp@@YAXXZ"
-// CHECK-DAG: store i32* @"\01?var@@3HA", i32** @"\01?varp@@3PAHA"
+// CHECK-LABEL: @"??__Evarp@@YAXXZ"
+// CHECK-DAG: store i32* @"?var@@3HA", i32** @"?varp@@3PAHA"
-// X64-LABEL: @"\01??__Evarp@@YAXXZ"
-// X64-DAG: store i32* @"\01?var@@3HA", i32** @"\01?varp@@3PEAHEA"
+// X64-LABEL: @"??__Evarp@@YAXXZ"
+// X64-DAG: store i32* @"?var@@3HA", i32** @"?varp@@3PEAHEA"
-// CHECK-LABEL: @"\01??__Efunp@@YAXXZ"()
-// CHECK-DAG: store void ()* @"\01?fun@@YAXXZ", void ()** @"\01?funp@@3P6AXXZA"
+// CHECK-LABEL: @"??__Efunp@@YAXXZ"()
+// CHECK-DAG: store void ()* @"?fun@@YAXXZ", void ()** @"?funp@@3P6AXXZA"
-// X64-LABEL: @"\01??__Efunp@@YAXXZ"()
-// X64-DAG: store void ()* @"\01?fun@@YAXXZ", void ()** @"\01?funp@@3P6AXXZEA"
+// X64-LABEL: @"??__Efunp@@YAXXZ"()
+// X64-DAG: store void ()* @"?fun@@YAXXZ", void ()** @"?funp@@3P6AXXZEA"
diff --git a/test/CodeGenCXX/PR26569.cpp b/test/CodeGenCXX/PR26569.cpp
index 859b6e26f0c4..379b50c9276c 100644
--- a/test/CodeGenCXX/PR26569.cpp
+++ b/test/CodeGenCXX/PR26569.cpp
@@ -9,12 +9,12 @@ class B : virtual A {};
extern template class __declspec(dllimport) B<int>;
class __declspec(dllexport) C : B<int> {};
-// CHECK-DAG: @[[VTABLE_C:.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4C@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"\01?m_fn1@A@@EAEXXZ" to i8*)] }
-// CHECK-DAG: @[[VTABLE_B:.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4?$B@H@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"\01?m_fn1@A@@EAEXXZ" to i8*)] }, comdat($"\01??_S?$B@H@@6B@")
-// CHECK-DAG: @[[VTABLE_A:.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4A@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"\01?m_fn1@A@@EAEXXZ" to i8*)] }, comdat($"\01??_SA@@6B@")
+// CHECK-DAG: @[[VTABLE_C:.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"??_R4C@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"?m_fn1@A@@EAEXXZ" to i8*)] }
+// CHECK-DAG: @[[VTABLE_B:.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"??_R4?$B@H@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"?m_fn1@A@@EAEXXZ" to i8*)] }, comdat($"??_S?$B@H@@6B@")
+// CHECK-DAG: @[[VTABLE_A:.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"??_R4A@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"?m_fn1@A@@EAEXXZ" to i8*)] }, comdat($"??_SA@@6B@")
-// CHECK-DAG: @"\01??_7C@@6B@" = dllexport unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* @[[VTABLE_C]], i32 0, i32 0, i32 1)
-// CHECK-DAG: @"\01??_S?$B@H@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* @[[VTABLE_B]], i32 0, i32 0, i32 1)
-// CHECK-DAG: @"\01??_SA@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* @[[VTABLE_A]], i32 0, i32 0, i32 1)
+// CHECK-DAG: @"??_7C@@6B@" = dllexport unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* @[[VTABLE_C]], i32 0, i32 0, i32 1)
+// CHECK-DAG: @"??_S?$B@H@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* @[[VTABLE_B]], i32 0, i32 0, i32 1)
+// CHECK-DAG: @"??_SA@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* @[[VTABLE_A]], i32 0, i32 0, i32 1)
-// CHECK-DAG: @"\01??_8?$B@H@@7B@" = available_externally dllimport unnamed_addr constant [2 x i32] [i32 0, i32 4]
+// CHECK-DAG: @"??_8?$B@H@@7B@" = available_externally dllimport unnamed_addr constant [2 x i32] [i32 0, i32 4]
diff --git a/test/CodeGenCXX/PR28220.cpp b/test/CodeGenCXX/PR28220.cpp
index 6262c87de206..5863b6dced85 100644
--- a/test/CodeGenCXX/PR28220.cpp
+++ b/test/CodeGenCXX/PR28220.cpp
@@ -14,6 +14,6 @@ template <typename T>
S<T> U<T>::u;
template S<int> U<int>::u;
-// CHECK-NOT: define internal void @"\01??__Eu@?$U@H@@2U?$S@H@@A@YAXXZ"(
+// CHECK-NOT: define internal void @"??__Eu@?$U@H@@2U?$S@H@@A@YAXXZ"(
S<int> &i = U<int>::u;
diff --git a/test/CodeGenCXX/PR37481.cpp b/test/CodeGenCXX/PR37481.cpp
new file mode 100644
index 000000000000..fba2ffdc8488
--- /dev/null
+++ b/test/CodeGenCXX/PR37481.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -o /dev/null -emit-llvm -std=c++17 -triple x86_64-pc-windows-msvc %s
+
+struct Foo {
+ virtual void f();
+ virtual void g();
+};
+
+void Foo::f() {}
+void Foo::g() {}
+
+template <void (Foo::*)()>
+void h() {}
+
+void x() {
+ h<&Foo::f>();
+ h<&Foo::g>();
+}
diff --git a/test/CodeGenCXX/abstract-class-ctors-dtors.cpp b/test/CodeGenCXX/abstract-class-ctors-dtors.cpp
index f36922413d83..f1d207649a4a 100644
--- a/test/CodeGenCXX/abstract-class-ctors-dtors.cpp
+++ b/test/CodeGenCXX/abstract-class-ctors-dtors.cpp
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
-// Check that we dont emit the complete constructor/destructor for this class.
+// Check that we don't emit the complete constructor/destructor for this class.
struct A {
virtual void f() = 0;
A();
diff --git a/test/CodeGenCXX/address-space-cast.cpp b/test/CodeGenCXX/address-space-cast.cpp
new file mode 100644
index 000000000000..334a1a63e627
--- /dev/null
+++ b/test/CodeGenCXX/address-space-cast.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 %s -triple=amdgcn-amd-amdhsa -emit-llvm -o - | FileCheck %s
+
+#define __private__ __attribute__((address_space(5)))
+
+void func_pchar(__private__ char *x);
+
+void test_cast(char *gen_ptr) {
+ // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)*
+ // CHECK-NEXT: store i8 addrspace(5)* %[[cast]]
+ __private__ char *priv_ptr = (__private__ char *)gen_ptr;
+
+ // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)*
+ // CHECK-NEXT: call void @_Z10func_pcharPU3AS5c(i8 addrspace(5)* %[[cast]])
+ func_pchar((__private__ char *)gen_ptr);
+}
diff --git a/test/CodeGenCXX/address-space-ref.cpp b/test/CodeGenCXX/address-space-ref.cpp
index de6bddca66a7..5f0a42950328 100644
--- a/test/CodeGenCXX/address-space-ref.cpp
+++ b/test/CodeGenCXX/address-space-ref.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s -check-prefixes=CHECK,NULL-INVALID
+// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-apple-darwin10 -fno-delete-null-pointer-checks -emit-llvm -o - | FileCheck %s -check-prefixes=CHECK,NULL-VALID
// For a reference to a complete type, output the dereferenceable attribute (in
// any address space).
@@ -29,6 +30,7 @@ bc & bar2(bc &x, bc & y) {
return x;
}
-// CHECK: define nonnull %class.bc* @_Z4bar2R2bcS0_(%class.bc* nonnull %x, %class.bc* nonnull %y)
+// NULL-INVALID: define nonnull %class.bc* @_Z4bar2R2bcS0_(%class.bc* nonnull %x, %class.bc* nonnull %y)
+// NULL-VALID: define %class.bc* @_Z4bar2R2bcS0_(%class.bc* %x, %class.bc* %y)
diff --git a/test/CodeGenCXX/alignment.cpp b/test/CodeGenCXX/alignment.cpp
index 4c44badd21cd..37509fcb4dd5 100644
--- a/test/CodeGenCXX/alignment.cpp
+++ b/test/CodeGenCXX/alignment.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-apple-darwin10 | FileCheck %s
+// RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-apple-darwin10 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NOCOMPAT
+// RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-apple-darwin10 -fclang-abi-compat=6.0 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-V6COMPAT
+// RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-scei-ps4 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-V6COMPAT
extern int int_source();
extern void int_sink(int x);
@@ -54,11 +56,13 @@ namespace test0 {
// CHECK: [[B_P:%.*]] = bitcast i8* [[T1]] to [[B]]*
// CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8*
// CHECK: [[TRUNC:%.*]] = trunc i32 [[CALL]] to i8
- // CHECK: [[OLD_VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2
+ // CHECK-V6COMPAT: [[OLD_VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2
+ // CHECK-NOCOMPAT: [[OLD_VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 4
// CHECK: [[T0:%.*]] = and i8 [[TRUNC]], 3
// CHECK: [[T1:%.*]] = and i8 [[OLD_VALUE]], -4
// CHECK: [[T2:%.*]] = or i8 [[T1]], [[T0]]
- // CHECK: store i8 [[T2]], i8* [[FIELD_P]], align 2
+ // CHECK-V6COMPAT: store i8 [[T2]], i8* [[FIELD_P]], align 2
+ // CHECK-NOCOMPAT: store i8 [[T2]], i8* [[FIELD_P]], align 4
c.onebit = int_source();
// CHECK: [[C_P:%.*]] = load [[C]]*, [[C]]**
@@ -66,7 +70,8 @@ namespace test0 {
// CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 8
// CHECK: [[B_P:%.*]] = bitcast i8* [[T1]] to [[B]]*
// CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8*
- // CHECK: [[VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2
+ // CHECK-V6COMPAT: [[VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2
+ // CHECK-NOCOMPAT: [[VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 4
// CHECK: [[T0:%.*]] = shl i8 [[VALUE]], 6
// CHECK: [[T1:%.*]] = ashr i8 [[T0]], 6
// CHECK: [[T2:%.*]] = sext i8 [[T1]] to i32
@@ -83,11 +88,13 @@ namespace test0 {
// CHECK: [[B_P:%.*]] = bitcast i8* [[T1]] to [[B]]*
// CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8*
// CHECK: [[TRUNC:%.*]] = trunc i32 [[CALL]] to i8
- // CHECK: [[OLD_VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2
+ // CHECK-V6COMPAT: [[OLD_VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2
+ // CHECK-NOCOMPAT: [[OLD_VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 4
// CHECK: [[T0:%.*]] = and i8 [[TRUNC]], 3
// CHECK: [[T1:%.*]] = and i8 [[OLD_VALUE]], -4
// CHECK: [[T2:%.*]] = or i8 [[T1]], [[T0]]
- // CHECK: store i8 [[T2]], i8* [[FIELD_P]], align 2
+ // CHECK-V6COMPAT: store i8 [[T2]], i8* [[FIELD_P]], align 2
+ // CHECK-NOCOMPAT: store i8 [[T2]], i8* [[FIELD_P]], align 4
c->onebit = int_source();
// CHECK: [[C_P:%.*]] = load [[C:%.*]]*, [[C]]**
@@ -95,7 +102,8 @@ namespace test0 {
// CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 8
// CHECK: [[B_P:%.*]] = bitcast i8* [[T1]] to [[B:%.*]]*
// CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8*
- // CHECK: [[VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2
+ // CHECK-V6COMPAT: [[VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2
+ // CHECK-NOCOMPAT: [[VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 4
// CHECK: [[T0:%.*]] = shl i8 [[VALUE]], 6
// CHECK: [[T1:%.*]] = ashr i8 [[T0]], 6
// CHECK: [[T2:%.*]] = sext i8 [[T1]] to i32
@@ -107,7 +115,8 @@ namespace test0 {
// in an alignment-2 variable.
// CHECK-LABEL: @_ZN5test01dEv
void d() {
- // CHECK: [[C_P:%.*]] = alloca [[C:%.*]], align 2
+ // CHECK-V6COMPAT: [[C_P:%.*]] = alloca [[C:%.*]], align 2
+ // CHECK-NOCOMPAT: [[C_P:%.*]] = alloca [[C:%.*]], align 4
C c;
// CHECK: [[CALL:%.*]] = call i32 @_Z10int_sourcev()
@@ -116,18 +125,21 @@ namespace test0 {
// CHECK: [[B_P:%.*]] = bitcast i8* [[T1]] to [[B]]*
// CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8*
// CHECK: [[TRUNC:%.*]] = trunc i32 [[CALL]] to i8
- // CHECK: [[OLD_VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2
+ // CHECK-V6COMPAT: [[OLD_VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2
+ // CHECK-NOCOMPAT: [[OLD_VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 4
// CHECK: [[T0:%.*]] = and i8 [[TRUNC]], 3
// CHECK: [[T1:%.*]] = and i8 [[OLD_VALUE]], -4
// CHECK: [[T2:%.*]] = or i8 [[T1]], [[T0]]
- // CHECK: store i8 [[T2]], i8* [[FIELD_P]], align 2
+ // CHECK-V6COMPAT: store i8 [[T2]], i8* [[FIELD_P]], align 2
+ // CHECK-NOCOMPAT: store i8 [[T2]], i8* [[FIELD_P]], align 4
c.onebit = int_source();
// CHECK: [[T0:%.*]] = bitcast [[C]]* [[C_P]] to i8*
// CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 8
// CHECK: [[B_P:%.*]] = bitcast i8* [[T1]] to [[B:%.*]]*
// CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8*
- // CHECK: [[VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2
+ // CHECK-V6COMPAT: [[VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2
+ // CHECK-NOCOMPAT: [[VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 4
// CHECK: [[T0:%.*]] = shl i8 [[VALUE]], 6
// CHECK: [[T1:%.*]] = ashr i8 [[T0]], 6
// CHECK: [[T2:%.*]] = sext i8 [[T1]] to i32
@@ -204,7 +216,7 @@ namespace test1 {
// CHECK: [[ARRAY_P:%.*]] = getelementptr inbounds [[A]], [[A]]* [[A_P]], i32 0, i32 0
// CHECK: [[T0:%.*]] = bitcast [[ARRAY]]* [[RESULT]] to i8*
// CHECK: [[T1:%.*]] = bitcast [[ARRAY]]* [[ARRAY_P]] to i8*
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T0]], i8* [[T1]], i64 16, i32 16, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 64 [[T0]], i8* align 16 [[T1]], i64 16, i1 false)
AlignedArray result = a.aArray;
}
@@ -223,7 +235,7 @@ namespace test1 {
// CHECK: [[ARRAY_P:%.*]] = getelementptr inbounds [[A]], [[A]]* [[A_P]], i32 0, i32 0
// CHECK: [[T0:%.*]] = bitcast [[ARRAY]]* [[RESULT]] to i8*
// CHECK: [[T1:%.*]] = bitcast [[ARRAY]]* [[ARRAY_P]] to i8*
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T0]], i8* [[T1]], i64 16, i32 16, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 64 [[T0]], i8* align 16 [[T1]], i64 16, i1 false)
AlignedArray result = b.aArray;
}
@@ -234,7 +246,7 @@ namespace test1 {
// CHECK: [[ARRAY_P:%.*]] = getelementptr inbounds [[B]], [[B]]* [[B_P]], i32 0, i32 2
// CHECK: [[T0:%.*]] = bitcast [[ARRAY]]* [[RESULT]] to i8*
// CHECK: [[T1:%.*]] = bitcast [[ARRAY]]* [[ARRAY_P]] to i8*
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T0]], i8* [[T1]], i64 16, i32 8, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 64 [[T0]], i8* align 8 [[T1]], i64 16, i1 false)
AlignedArray result = b.bArray;
}
@@ -245,7 +257,7 @@ namespace test1 {
// CHECK: [[ARRAY_P:%.*]] = getelementptr inbounds [[B]], [[B]]* [[B_P]], i32 0, i32 2
// CHECK: [[T0:%.*]] = bitcast [[ARRAY]]* [[RESULT]] to i8*
// CHECK: [[T1:%.*]] = bitcast [[ARRAY]]* [[ARRAY_P]] to i8*
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T0]], i8* [[T1]], i64 16, i32 8, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 64 [[T0]], i8* align 8 [[T1]], i64 16, i1 false)
AlignedArray result = b->bArray;
}
@@ -256,7 +268,7 @@ namespace test1 {
// CHECK: [[ARRAY_P:%.*]] = getelementptr inbounds [[B]], [[B]]* [[B_P]], i32 0, i32 2
// CHECK: [[T0:%.*]] = bitcast [[ARRAY]]* [[RESULT]] to i8*
// CHECK: [[T1:%.*]] = bitcast [[ARRAY]]* [[ARRAY_P]] to i8*
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T0]], i8* [[T1]], i64 16, i32 16, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 64 [[T0]], i8* align 16 [[T1]], i64 16, i1 false)
B b;
AlignedArray result = b.bArray;
}
@@ -277,7 +289,7 @@ namespace test1 {
// CHECK: [[ARRAY_P:%.*]] = getelementptr inbounds [[A]], [[A]]* [[A_P]], i32 0, i32 0
// CHECK: [[T0:%.*]] = bitcast [[ARRAY]]* [[RESULT]] to i8*
// CHECK: [[T1:%.*]] = bitcast [[ARRAY]]* [[ARRAY_P]] to i8*
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T0]], i8* [[T1]], i64 16, i32 16, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 64 [[T0]], i8* align 16 [[T1]], i64 16, i1 false)
D d;
AlignedArray result = d.aArray;
}
@@ -292,7 +304,7 @@ namespace test1 {
// CHECK: [[ARRAY_P:%.*]] = getelementptr inbounds [[B]], [[B]]* [[B_P]], i32 0, i32 2
// CHECK: [[T0:%.*]] = bitcast [[ARRAY]]* [[RESULT]] to i8*
// CHECK: [[T1:%.*]] = bitcast [[ARRAY]]* [[ARRAY_P]] to i8*
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T0]], i8* [[T1]], i64 16, i32 8, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 64 [[T0]], i8* align 8 [[T1]], i64 16, i1 false)
D d;
AlignedArray result = d.bArray;
}
diff --git a/test/CodeGenCXX/alloc-size.cpp b/test/CodeGenCXX/alloc-size.cpp
index e93e231b70e8..e68e52c86bf2 100644
--- a/test/CodeGenCXX/alloc-size.cpp
+++ b/test/CodeGenCXX/alloc-size.cpp
@@ -69,4 +69,38 @@ int testIt() {
__builtin_object_size(dependent_calloc<7, 8>(), 0) +
__builtin_object_size(dependent_calloc2<int, 9>(), 0);
}
+} // namespace templated_alloc_size
+
+// Be sure that an ExprWithCleanups doesn't deter us.
+namespace alloc_size_with_cleanups {
+struct Foo {
+ ~Foo();
+};
+
+void *my_malloc(const Foo &, int N) __attribute__((alloc_size(2)));
+
+// CHECK-LABEL: define i32 @_ZN24alloc_size_with_cleanups6testItEv
+int testIt() {
+ int *const p = (int *)my_malloc(Foo{}, 3);
+ // CHECK: ret i32 3
+ return __builtin_object_size(p, 0);
+}
+} // namespace alloc_size_with_cleanups
+
+class C {
+public:
+ void *my_malloc(int N) __attribute__((alloc_size(2)));
+ void *my_calloc(int N, int M) __attribute__((alloc_size(2, 3)));
+};
+
+// CHECK-LABEL: define i32 @_Z16callMemberMallocv
+int callMemberMalloc() {
+ // CHECK: ret i32 16
+ return __builtin_object_size(C().my_malloc(16), 0);
+}
+
+// CHECK-LABEL: define i32 @_Z16callMemberCallocv
+int callMemberCalloc() {
+ // CHECK: ret i32 32
+ return __builtin_object_size(C().my_calloc(16, 2), 0);
}
diff --git a/test/CodeGenCXX/amdgcn-func-arg.cpp b/test/CodeGenCXX/amdgcn-func-arg.cpp
new file mode 100644
index 000000000000..9ac143a52005
--- /dev/null
+++ b/test/CodeGenCXX/amdgcn-func-arg.cpp
@@ -0,0 +1,94 @@
+// RUN: %clang_cc1 -O0 -triple amdgcn -emit-llvm %s -o - | FileCheck %s
+
+class A {
+public:
+ int x;
+ A():x(0) {}
+ ~A() {}
+};
+
+class B {
+int x[100];
+};
+
+A g_a;
+B g_b;
+
+void func_with_ref_arg(A &a);
+void func_with_ref_arg(B &b);
+
+// CHECK-LABEL: define void @_Z22func_with_indirect_arg1A(%class.A addrspace(5)* %a)
+// CHECK: %p = alloca %class.A*, align 8, addrspace(5)
+// CHECK: %[[r1:.+]] = addrspacecast %class.A* addrspace(5)* %p to %class.A**
+// CHECK: %[[r0:.+]] = addrspacecast %class.A addrspace(5)* %a to %class.A*
+// CHECK: store %class.A* %[[r0]], %class.A** %[[r1]], align 8
+void func_with_indirect_arg(A a) {
+ A *p = &a;
+}
+
+// CHECK-LABEL: define void @_Z22test_indirect_arg_autov()
+// CHECK: %a = alloca %class.A, align 4, addrspace(5)
+// CHECK: %[[r0:.+]] = addrspacecast %class.A addrspace(5)* %a to %class.A*
+// CHECK: %agg.tmp = alloca %class.A, align 4, addrspace(5)
+// CHECK: %[[r1:.+]] = addrspacecast %class.A addrspace(5)* %agg.tmp to %class.A*
+// CHECK: call void @_ZN1AC1Ev(%class.A* %[[r0]])
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64
+// CHECK: %[[r4:.+]] = addrspacecast %class.A* %[[r1]] to %class.A addrspace(5)*
+// CHECK: call void @_Z22func_with_indirect_arg1A(%class.A addrspace(5)* %[[r4]])
+// CHECK: call void @_ZN1AD1Ev(%class.A* %[[r1]])
+// CHECK: call void @_Z17func_with_ref_argR1A(%class.A* dereferenceable(4) %[[r0]])
+// CHECK: call void @_ZN1AD1Ev(%class.A* %[[r0]])
+void test_indirect_arg_auto() {
+ A a;
+ func_with_indirect_arg(a);
+ func_with_ref_arg(a);
+}
+
+// CHECK: define void @_Z24test_indirect_arg_globalv()
+// CHECK: %agg.tmp = alloca %class.A, align 4, addrspace(5)
+// CHECK: %[[r0:.+]] = addrspacecast %class.A addrspace(5)* %agg.tmp to %class.A*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64
+// CHECK: %[[r2:.+]] = addrspacecast %class.A* %[[r0]] to %class.A addrspace(5)*
+// CHECK: call void @_Z22func_with_indirect_arg1A(%class.A addrspace(5)* %[[r2]])
+// CHECK: call void @_ZN1AD1Ev(%class.A* %[[r0]])
+// CHECK: call void @_Z17func_with_ref_argR1A(%class.A* dereferenceable(4) addrspacecast (%class.A addrspace(1)* @g_a to %class.A*))
+void test_indirect_arg_global() {
+ func_with_indirect_arg(g_a);
+ func_with_ref_arg(g_a);
+}
+
+// CHECK-LABEL: define void @_Z19func_with_byval_arg1B(%class.B addrspace(5)* byval align 4 %b)
+// CHECK: %p = alloca %class.B*, align 8, addrspace(5)
+// CHECK: %[[r1:.+]] = addrspacecast %class.B* addrspace(5)* %p to %class.B**
+// CHECK: %[[r0:.+]] = addrspacecast %class.B addrspace(5)* %b to %class.B*
+// CHECK: store %class.B* %[[r0]], %class.B** %[[r1]], align 8
+void func_with_byval_arg(B b) {
+ B *p = &b;
+}
+
+// CHECK-LABEL: define void @_Z19test_byval_arg_autov()
+// CHECK: %b = alloca %class.B, align 4, addrspace(5)
+// CHECK: %[[r0:.+]] = addrspacecast %class.B addrspace(5)* %b to %class.B*
+// CHECK: %agg.tmp = alloca %class.B, align 4, addrspace(5)
+// CHECK: %[[r1:.+]] = addrspacecast %class.B addrspace(5)* %agg.tmp to %class.B*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64
+// CHECK: %[[r4:.+]] = addrspacecast %class.B* %[[r1]] to %class.B addrspace(5)*
+// CHECK: call void @_Z19func_with_byval_arg1B(%class.B addrspace(5)* byval align 4 %[[r4]])
+// CHECK: call void @_Z17func_with_ref_argR1B(%class.B* dereferenceable(400) %[[r0]])
+void test_byval_arg_auto() {
+ B b;
+ func_with_byval_arg(b);
+ func_with_ref_arg(b);
+}
+
+// CHECK-LABEL: define void @_Z21test_byval_arg_globalv()
+// CHECK: %agg.tmp = alloca %class.B, align 4, addrspace(5)
+// CHECK: %[[r0:.+]] = addrspacecast %class.B addrspace(5)* %agg.tmp to %class.B*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64
+// CHECK: %[[r2:.+]] = addrspacecast %class.B* %[[r0]] to %class.B addrspace(5)*
+// CHECK: call void @_Z19func_with_byval_arg1B(%class.B addrspace(5)* byval align 4 %[[r2]])
+// CHECK: call void @_Z17func_with_ref_argR1B(%class.B* dereferenceable(400) addrspacecast (%class.B addrspace(1)* @g_b to %class.B*))
+void test_byval_arg_global() {
+ func_with_byval_arg(g_b);
+ func_with_ref_arg(g_b);
+}
diff --git a/test/CodeGenCXX/amdgcn-string-literal.cpp b/test/CodeGenCXX/amdgcn-string-literal.cpp
new file mode 100644
index 000000000000..7fd05351c863
--- /dev/null
+++ b/test/CodeGenCXX/amdgcn-string-literal.cpp
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -emit-llvm %s -o - | FileCheck %s
+
+// CHECK: @.str = private unnamed_addr addrspace(4) constant [6 x i8] c"g_str\00", align 1
+// CHECK: @g_str = addrspace(1) global i8* addrspacecast (i8 addrspace(4)* getelementptr inbounds ([6 x i8], [6 x i8] addrspace(4)* @.str, i32 0, i32 0) to i8*), align 8
+// CHECK: @g_array = addrspace(1) global [8 x i8] c"g_array\00", align 1
+// CHECK: @.str.1 = private unnamed_addr addrspace(4) constant [6 x i8] c"l_str\00", align 1
+// CHECK: @_ZZ1fvE7l_array = private unnamed_addr addrspace(4) constant [8 x i8] c"l_array\00", align 1
+
+const char* g_str = "g_str";
+char g_array[] = "g_array";
+
+void g(const char* p);
+
+// CHECK-LABEL: define void @_Z1fv()
+void f() {
+ const char* l_str = "l_str";
+
+ // CHECK: call void @llvm.memcpy.p0i8.p4i8.i64
+ char l_array[] = "l_array";
+
+ g(g_str);
+ g(g_array);
+ g(l_str);
+ g(l_array);
+
+ const char* p = g_str;
+ g(p);
+}
diff --git a/test/CodeGenCXX/amdgcn_declspec_get.cpp b/test/CodeGenCXX/amdgcn_declspec_get.cpp
new file mode 100644
index 000000000000..93f7a36af141
--- /dev/null
+++ b/test/CodeGenCXX/amdgcn_declspec_get.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -emit-llvm -O3 -fdeclspec \
+// RUN: -disable-llvm-passes -o - %s | FileCheck %s
+
+int get_x();
+
+struct A {
+ __declspec(property(get = _get_x)) int x;
+ static int _get_x(void) {
+ return get_x();
+ };
+};
+
+extern const A a;
+
+// CHECK-LABEL: define void @_Z4testv()
+// CHECK: %i = alloca i32, align 4, addrspace(5)
+// CHECK: %[[ii:.*]] = addrspacecast i32 addrspace(5)* %i to i32*
+// CHECK: %[[cast:.*]] = bitcast i32 addrspace(5)* %i to i8 addrspace(5)*
+// CHECK: call void @llvm.lifetime.start.p5i8(i64 4, i8 addrspace(5)* %[[cast]])
+// CHECK: %call = call i32 @_ZN1A6_get_xEv()
+// CHECK: store i32 %call, i32* %[[ii]]
+// CHECK: %[[cast2:.*]] = bitcast i32 addrspace(5)* %i to i8 addrspace(5)*
+// CHECK: call void @llvm.lifetime.end.p5i8(i64 4, i8 addrspace(5)* %[[cast2]])
+void test()
+{
+ int i = a.x;
+}
diff --git a/test/CodeGenCXX/apple-kext-guard-variable.cpp b/test/CodeGenCXX/apple-kext-guard-variable.cpp
index 76875a0b69ae..ea4c1483ce70 100644
--- a/test/CodeGenCXX/apple-kext-guard-variable.cpp
+++ b/test/CodeGenCXX/apple-kext-guard-variable.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang -target x86_64-apple-darwin10 -S -o %t.s -mkernel -Xclang -verify %s
+// RUN: %clang -target x86_64-apple-darwin10 -S -o %t.s -Wno-stdlibcxx-not-found -mkernel -Xclang -verify %s
// rdar://problem/9143356
diff --git a/test/CodeGenCXX/arm-swiftcall.cpp b/test/CodeGenCXX/arm-swiftcall.cpp
index 5c932c77b1da..36a5afad4c62 100644
--- a/test/CodeGenCXX/arm-swiftcall.cpp
+++ b/test/CodeGenCXX/arm-swiftcall.cpp
@@ -113,3 +113,13 @@ TEST(struct_indirect_1)
// Should not be byval.
// CHECK-LABEL: define {{.*}} void @take_struct_indirect_1({{.*}}*{{( %.*)?}})
+
+// Do a simple standalone test here of a function definition to ensure that
+// we don't have problems due to failure to eagerly synthesize a copy
+// constructor declaration.
+class struct_trivial {
+ int x;
+};
+// CHECK-LABEL define void @test_struct_trivial(i32{{( %.*)?}})
+extern "C" SWIFTCALL
+void test_struct_trivial(struct_trivial triv) {}
diff --git a/test/CodeGenCXX/array-default-argument.cpp b/test/CodeGenCXX/array-default-argument.cpp
index a07e3908392a..23bc9fdbb703 100644
--- a/test/CodeGenCXX/array-default-argument.cpp
+++ b/test/CodeGenCXX/array-default-argument.cpp
@@ -12,7 +12,7 @@ struct B {
};
void f();
-// CHECK-LABEL: define void @_Z1gv()
+// CHECK-LABEL: define {{(dso_local )?}}void @_Z1gv()
void g() {
// CHECK: br label %[[LOOP:.*]]
diff --git a/test/CodeGenCXX/assign-construct-memcpy.cpp b/test/CodeGenCXX/assign-construct-memcpy.cpp
index 3d4205132409..5e52b1625b61 100644
--- a/test/CodeGenCXX/assign-construct-memcpy.cpp
+++ b/test/CodeGenCXX/assign-construct-memcpy.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin12 -emit-llvm -o - -std=c++11 %s -DPOD | FileCheck %s -check-prefix=CHECK-POD
+/// RUN: %clang_cc1 -triple x86_64-apple-darwin12 -emit-llvm -o - -std=c++11 %s -DPOD | FileCheck %s -check-prefix=CHECK-POD
// RUN: %clang_cc1 -triple x86_64-apple-darwin12 -emit-llvm -o - -std=c++11 %s | FileCheck %s -check-prefix=CHECK-NONPOD
// Declare the reserved placement operators.
@@ -23,47 +23,47 @@ struct foo {
foo *test1(void *f, const foo &x) {
return new (f) foo(x);
// CHECK-POD: test1
-// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8
+// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 8 {{.*}} align 8 {{.*}}i64 24
// CHECK-NONPOD: test1
-// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8
+// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 8 {{.*}} align 8 {{.*}}i64 24
}
foo *test2(const foo &x) {
return new foo(x);
// CHECK-POD: test2
-// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8
+// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 16 {{.*}} align 8 {{.*}}i64 24
// CHECK-NONPOD: test2
-// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8
+// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 16 {{.*}} align 8 {{.*}}i64 24
}
foo test3(const foo &x) {
foo f = x;
return f;
// CHECK-POD: test3
-// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8
+// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 8 {{.*}} align 8 {{.*}}i64 24
// CHECK-NONPOD: test3
-// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8
+// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 8 {{.*}} align 8 {{.*}}i64 24
}
foo *test4(foo &&x) {
return new foo(x);
// CHECK-POD: test4
-// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8
+// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 16 {{.*}} align 8 {{.*}}i64 24
// CHECK-NONPOD: test4
-// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8
+// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 16 {{.*}} align 8 {{.*}}i64 24
}
void test5(foo &f, const foo &x) {
f = x;
// CHECK-POD: test5
-// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8
+// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 8 {{.*}} align 8 {{.*}}i64 24
// CHECK-NONPOD: test5
-// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 17, i32 8
+// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 8 {{.*}} align 8 {{.*}}i64 17
}
extern foo globtest;
@@ -71,10 +71,10 @@ extern foo globtest;
void test6(foo &&x) {
globtest = move(x);
// CHECK-POD: test6
-// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8
+// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 8 {{.*}} align 8 {{.*}}i64 24
// CHECK-NONPOD: test6
-// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 17, i32 8
+// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 8 {{.*}} align 8 {{.*}}i64 17
}
void byval(foo f);
@@ -82,8 +82,8 @@ void byval(foo f);
void test7(const foo &x) {
byval(x);
// CHECK-POD: test7
-// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8
+// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 8 {{.*}} align 8 {{.*}}i64 24
// CHECK-NONPOD: test7
-// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8
+// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 8 {{.*}} align 8 {{.*}}i64 24
}
diff --git a/test/CodeGenCXX/atomic-dllexport.cpp b/test/CodeGenCXX/atomic-dllexport.cpp
index ae1422243160..20c500555c2e 100644
--- a/test/CodeGenCXX/atomic-dllexport.cpp
+++ b/test/CodeGenCXX/atomic-dllexport.cpp
@@ -3,7 +3,7 @@
struct __declspec(dllexport) SomeStruct {
// Copy assignment operator should be produced, and exported:
- // M32: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.SomeStruct* @"\01??4SomeStruct@@QAEAAU0@ABU0@@Z"
- // M64: define weak_odr dllexport dereferenceable({{[0-9]+}}) %struct.SomeStruct* @"\01??4SomeStruct@@QEAAAEAU0@AEBU0@@Z"
+ // M32: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.SomeStruct* @"??4SomeStruct@@QAEAAU0@ABU0@@Z"
+ // M64: define weak_odr dso_local dllexport dereferenceable({{[0-9]+}}) %struct.SomeStruct* @"??4SomeStruct@@QEAAAEAU0@AEBU0@@Z"
_Atomic(int) mData;
};
diff --git a/test/CodeGenCXX/atomic-inline.cpp b/test/CodeGenCXX/atomic-inline.cpp
index fe727589d2e2..327f85d5667f 100644
--- a/test/CodeGenCXX/atomic-inline.cpp
+++ b/test/CodeGenCXX/atomic-inline.cpp
@@ -1,6 +1,52 @@
// RUN: %clang_cc1 %s -std=c++11 -emit-llvm -o - -triple=x86_64-linux-gnu | FileCheck %s
// RUN: %clang_cc1 %s -std=c++11 -emit-llvm -o - -triple=x86_64-linux-gnu -target-cpu core2 | FileCheck %s --check-prefix=CORE2
-// Check the atomic code generation for cpu targets w/wo cx16 support.
+// RUN: %clang_cc1 %s -std=c++11 -emit-llvm -o - -triple=i386-linux-gnu -target-cpu i386 | FileCheck %s --check-prefix=I386
+// RUN: %clang_cc1 %s -std=c++11 -emit-llvm -o - -triple=i386-linux-gnu -target-cpu i486 | FileCheck %s --check-prefix=I486
+// Check the atomic code generation for cpu targets w/wo cx, cx8 and cx16 support.
+
+struct alignas(4) AM4 {
+ short f1, f2;
+};
+AM4 m4;
+AM4 load4() {
+ AM4 am;
+ // CHECK-LABEL: @_Z5load4v
+ // CHECK: load atomic i32, {{.*}} monotonic
+ // CORE2-LABEL: @_Z5load4v
+ // CORE2: load atomic i32, {{.*}} monotonic
+ // I386-LABEL: @_Z5load4v
+ // I386: call i32 @__atomic_load_4
+ // I486-LABEL: @_Z5load4v
+ // I486: load atomic i32, {{.*}} monotonic
+ __atomic_load(&m4, &am, 0);
+ return am;
+}
+
+AM4 s4;
+void store4() {
+ // CHECK-LABEL: @_Z6store4v
+ // CHECK: store atomic i32 {{.*}} monotonic
+ // CORE2-LABEL: @_Z6store4v
+ // CORE2: store atomic i32 {{.*}} monotonic
+ // I386-LABEL: @_Z6store4v
+ // I386: call void @__atomic_store_4
+ // I486-LABEL: @_Z6store4v
+ // I486: store atomic i32 {{.*}} monotonic
+ __atomic_store(&m4, &s4, 0);
+}
+
+bool cmpxchg4() {
+ AM4 am;
+ // CHECK-LABEL: @_Z8cmpxchg4v
+ // CHECK: cmpxchg i32* {{.*}} monotonic
+ // CORE2-LABEL: @_Z8cmpxchg4v
+ // CORE2: cmpxchg i32* {{.*}} monotonic
+ // I386-LABEL: @_Z8cmpxchg4v
+ // I386: call zeroext i1 @__atomic_compare_exchange_4
+ // I486-LABEL: @_Z8cmpxchg4v
+ // I486: cmpxchg i32* {{.*}} monotonic
+ return __atomic_compare_exchange(&m4, &s4, &am, 0, 0, 0);
+}
struct alignas(8) AM8 {
int f1, f2;
@@ -12,6 +58,10 @@ AM8 load8() {
// CHECK: load atomic i64, {{.*}} monotonic
// CORE2-LABEL: @_Z5load8v
// CORE2: load atomic i64, {{.*}} monotonic
+ // I386-LABEL: @_Z5load8v
+ // I386: call i64 @__atomic_load_8
+ // I486-LABEL: @_Z5load8v
+ // I486: call i64 @__atomic_load_8
__atomic_load(&m8, &am, 0);
return am;
}
@@ -22,6 +72,10 @@ void store8() {
// CHECK: store atomic i64 {{.*}} monotonic
// CORE2-LABEL: @_Z6store8v
// CORE2: store atomic i64 {{.*}} monotonic
+ // I386-LABEL: @_Z6store8v
+ // I386: call void @__atomic_store_8
+ // I486-LABEL: @_Z6store8v
+ // I486: call void @__atomic_store_8
__atomic_store(&m8, &s8, 0);
}
@@ -31,6 +85,10 @@ bool cmpxchg8() {
// CHECK: cmpxchg i64* {{.*}} monotonic
// CORE2-LABEL: @_Z8cmpxchg8v
// CORE2: cmpxchg i64* {{.*}} monotonic
+ // I386-LABEL: @_Z8cmpxchg8v
+ // I386: call zeroext i1 @__atomic_compare_exchange_8
+ // I486-LABEL: @_Z8cmpxchg8v
+ // I486: call zeroext i1 @__atomic_compare_exchange_8
return __atomic_compare_exchange(&m8, &s8, &am, 0, 0, 0);
}
@@ -66,4 +124,3 @@ bool cmpxchg16() {
// CORE2: cmpxchg i128* {{.*}} monotonic
return __atomic_compare_exchange(&m16, &s16, &am, 0, 0, 0);
}
-
diff --git a/test/CodeGenCXX/attr-target-mv-diff-ns.cpp b/test/CodeGenCXX/attr-target-mv-diff-ns.cpp
new file mode 100644
index 000000000000..4dc2b67b4644
--- /dev/null
+++ b/test/CodeGenCXX/attr-target-mv-diff-ns.cpp
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s
+// Test ensures that this properly differentiates between types in different
+// namespaces.
+int __attribute__((target("sse4.2"))) foo(int) { return 0; }
+int __attribute__((target("arch=sandybridge"))) foo(int);
+int __attribute__((target("arch=ivybridge"))) foo(int) {return 1;}
+int __attribute__((target("default"))) foo(int) { return 2; }
+
+namespace ns {
+int __attribute__((target("sse4.2"))) foo(int) { return 0; }
+int __attribute__((target("arch=sandybridge"))) foo(int);
+int __attribute__((target("arch=ivybridge"))) foo(int) {return 1;}
+int __attribute__((target("default"))) foo(int) { return 2; }
+}
+
+int bar() {
+ return foo(1) + ns::foo(2);
+}
+
+// CHECK: @_Z3fooi.ifunc = ifunc i32 (i32), i32 (i32)* ()* @_Z3fooi.resolver
+// CHECK: @_ZN2ns3fooEi.ifunc = ifunc i32 (i32), i32 (i32)* ()* @_ZN2ns3fooEi.resolver
+
+// CHECK: define i32 @_Z3fooi.sse4.2(i32)
+// CHECK: ret i32 0
+// CHECK: define i32 @_Z3fooi.arch_ivybridge(i32)
+// CHECK: ret i32 1
+// CHECK: define i32 @_Z3fooi(i32)
+// CHECK: ret i32 2
+
+// CHECK: define i32 @_ZN2ns3fooEi.sse4.2(i32)
+// CHECK: ret i32 0
+// CHECK: define i32 @_ZN2ns3fooEi.arch_ivybridge(i32)
+// CHECK: ret i32 1
+// CHECK: define i32 @_ZN2ns3fooEi(i32)
+// CHECK: ret i32 2
+
+// CHECK: define i32 @_Z3barv()
+// CHECK: call i32 @_Z3fooi.ifunc(i32 1)
+// CHECK: call i32 @_ZN2ns3fooEi.ifunc(i32 2)
+
+// CHECK: define i32 (i32)* @_Z3fooi.resolver() comdat
+// CHECK: ret i32 (i32)* @_Z3fooi.arch_sandybridge
+// CHECK: ret i32 (i32)* @_Z3fooi.arch_ivybridge
+// CHECK: ret i32 (i32)* @_Z3fooi.sse4.2
+// CHECK: ret i32 (i32)* @_Z3fooi
+//
+// CHECK: define i32 (i32)* @_ZN2ns3fooEi.resolver() comdat
+// CHECK: ret i32 (i32)* @_ZN2ns3fooEi.arch_sandybridge
+// CHECK: ret i32 (i32)* @_ZN2ns3fooEi.arch_ivybridge
+// CHECK: ret i32 (i32)* @_ZN2ns3fooEi.sse4.2
+// CHECK: ret i32 (i32)* @_ZN2ns3fooEi
+
+// CHECK: declare i32 @_Z3fooi.arch_sandybridge(i32)
+// CHECK: declare i32 @_ZN2ns3fooEi.arch_sandybridge(i32)
diff --git a/test/CodeGenCXX/attr-target-mv-func-ptrs.cpp b/test/CodeGenCXX/attr-target-mv-func-ptrs.cpp
new file mode 100644
index 000000000000..290d6b5c6489
--- /dev/null
+++ b/test/CodeGenCXX/attr-target-mv-func-ptrs.cpp
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s
+void temp();
+void temp(int);
+using FP = void(*)(int);
+void b() {
+ FP f = temp;
+}
+
+int __attribute__((target("sse4.2"))) foo(int) { return 0; }
+int __attribute__((target("arch=sandybridge"))) foo(int);
+int __attribute__((target("arch=ivybridge"))) foo(int) {return 1;}
+int __attribute__((target("default"))) foo(int) { return 2; }
+
+struct S {
+int __attribute__((target("sse4.2"))) foo(int) { return 0; }
+int __attribute__((target("arch=sandybridge"))) foo(int);
+int __attribute__((target("arch=ivybridge"))) foo(int) {return 1;}
+int __attribute__((target("default"))) foo(int) { return 2; }
+};
+
+using FuncPtr = int (*)(int);
+using MemFuncPtr = int (S::*)(int);
+
+void f(FuncPtr, MemFuncPtr);
+
+int bar() {
+ FuncPtr Free = &foo;
+ MemFuncPtr Member = &S::foo;
+ S s;
+ f(foo, &S::foo);
+ return Free(1) + (s.*Member)(2);
+}
+
+
+// CHECK: @_Z3fooi.ifunc
+// CHECK: @_ZN1S3fooEi.ifunc
+
+// CHECK: define i32 @_Z3barv()
+// Store to Free of ifunc
+// CHECK: store i32 (i32)* @_Z3fooi.ifunc
+// Store to Member of ifunc
+// CHECK: store { i64, i64 } { i64 ptrtoint (i32 (%struct.S*, i32)* @_ZN1S3fooEi.ifunc to i64), i64 0 }, { i64, i64 }* [[MEMBER:%[a-z]+]]
+
+// Call to 'f' with the ifunc
+// CHECK: call void @_Z1fPFiiEM1SFiiE(i32 (i32)* @_Z3fooi.ifunc
diff --git a/test/CodeGenCXX/attr-target-mv-member-funcs.cpp b/test/CodeGenCXX/attr-target-mv-member-funcs.cpp
new file mode 100644
index 000000000000..2e5db3b705e4
--- /dev/null
+++ b/test/CodeGenCXX/attr-target-mv-member-funcs.cpp
@@ -0,0 +1,137 @@
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s
+
+struct S {
+ int __attribute__((target("sse4.2"))) foo(int) { return 0; }
+ int __attribute__((target("arch=sandybridge"))) foo(int);
+ int __attribute__((target("arch=ivybridge"))) foo(int) { return 1; }
+ int __attribute__((target("default"))) foo(int) { return 2; }
+
+ S &__attribute__((target("arch=ivybridge"))) operator=(const S &) {
+ return *this;
+ }
+ S &__attribute__((target("default"))) operator=(const S &) {
+ return *this;
+ }
+};
+
+struct ConvertTo {
+ __attribute__((target("arch=ivybridge"))) operator S() const {
+ return S{};
+ }
+ __attribute__((target("default"))) operator S() const {
+ return S{};
+ }
+};
+
+int bar() {
+ S s;
+ S s2;
+ s2 = s;
+
+ ConvertTo C;
+ s2 = static_cast<S>(C);
+
+ return s.foo(0);
+}
+
+struct S2 {
+ int __attribute__((target("sse4.2"))) foo(int);
+ int __attribute__((target("arch=sandybridge"))) foo(int);
+ int __attribute__((target("arch=ivybridge"))) foo(int);
+ int __attribute__((target("default"))) foo(int);
+};
+
+int bar2() {
+ S2 s;
+ return s.foo(0);
+}
+
+int __attribute__((target("sse4.2"))) S2::foo(int) { return 0; }
+int __attribute__((target("arch=ivybridge"))) S2::foo(int) { return 1; }
+int __attribute__((target("default"))) S2::foo(int) { return 2; }
+
+template<typename T>
+struct templ {
+ int __attribute__((target("sse4.2"))) foo(int) { return 0; }
+ int __attribute__((target("arch=sandybridge"))) foo(int);
+ int __attribute__((target("arch=ivybridge"))) foo(int) { return 1; }
+ int __attribute__((target("default"))) foo(int) { return 2; }
+};
+
+int templ_use() {
+ templ<int> a;
+ templ<double> b;
+ return a.foo(1) + b.foo(2);
+}
+
+// CHECK: @_ZN1SaSERKS_.ifunc = ifunc %struct.S* (%struct.S*, %struct.S*), %struct.S* (%struct.S*, %struct.S*)* ()* @_ZN1SaSERKS_.resolver
+// CHECK: @_ZNK9ConvertTocv1SEv.ifunc = ifunc void (%struct.ConvertTo*), void (%struct.ConvertTo*)* ()* @_ZNK9ConvertTocv1SEv.resolver
+// CHECK: @_ZN1S3fooEi.ifunc = ifunc i32 (%struct.S*, i32), i32 (%struct.S*, i32)* ()* @_ZN1S3fooEi.resolver
+// CHECK: @_ZN2S23fooEi.ifunc = ifunc i32 (%struct.S2*, i32), i32 (%struct.S2*, i32)* ()* @_ZN2S23fooEi.resolver
+// Templates:
+// CHECK: @_ZN5templIiE3fooEi.ifunc = ifunc i32 (%struct.templ*, i32), i32 (%struct.templ*, i32)* ()* @_ZN5templIiE3fooEi.resolver
+// CHECK: @_ZN5templIdE3fooEi.ifunc = ifunc i32 (%struct.templ.0*, i32), i32 (%struct.templ.0*, i32)* ()* @_ZN5templIdE3fooEi.resolver
+
+// CHECK: define i32 @_Z3barv()
+// CHECK: %s = alloca %struct.S, align 1
+// CHECK: %s2 = alloca %struct.S, align 1
+// CHECK: %C = alloca %struct.ConvertTo, align 1
+// CHECK: call dereferenceable(1) %struct.S* @_ZN1SaSERKS_.ifunc(%struct.S* %s2
+// CHECK: call void @_ZNK9ConvertTocv1SEv.ifunc(%struct.ConvertTo* %C)
+// CHECK: call dereferenceable(1) %struct.S* @_ZN1SaSERKS_.ifunc(%struct.S* %s2
+// CHECK: call i32 @_ZN1S3fooEi.ifunc(%struct.S* %s, i32 0)
+
+// CHECK: define %struct.S* (%struct.S*, %struct.S*)* @_ZN1SaSERKS_.resolver() comdat
+// CHECK: ret %struct.S* (%struct.S*, %struct.S*)* @_ZN1SaSERKS_.arch_ivybridge
+// CHECK: ret %struct.S* (%struct.S*, %struct.S*)* @_ZN1SaSERKS_
+
+// CHECK: define void (%struct.ConvertTo*)* @_ZNK9ConvertTocv1SEv.resolver() comdat
+// CHECK: ret void (%struct.ConvertTo*)* @_ZNK9ConvertTocv1SEv.arch_ivybridge
+// CHECK: ret void (%struct.ConvertTo*)* @_ZNK9ConvertTocv1SEv
+
+// CHECK: define i32 (%struct.S*, i32)* @_ZN1S3fooEi.resolver() comdat
+// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_sandybridge
+// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_ivybridge
+// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.sse4.2
+// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi
+
+// CHECK: define i32 @_Z4bar2v()
+// CHECK:call i32 @_ZN2S23fooEi.ifunc
+// define i32 (%struct.S2*, i32)* @_ZN2S23fooEi.resolver() comdat
+// CHECK: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi.arch_sandybridge
+// CHECK: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi.arch_ivybridge
+// CHECK: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi.sse4.2
+// CHECK: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi
+
+// CHECK: define i32 @_ZN2S23fooEi.sse4.2(%struct.S2* %this, i32)
+// CHECK: define i32 @_ZN2S23fooEi.arch_ivybridge(%struct.S2* %this, i32)
+// CHECK: define i32 @_ZN2S23fooEi(%struct.S2* %this, i32)
+
+// CHECK: define i32 @_Z9templ_usev()
+// CHECK: call i32 @_ZN5templIiE3fooEi.ifunc
+// CHECK: call i32 @_ZN5templIdE3fooEi.ifunc
+
+
+// CHECK: define i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.resolver() comdat
+// CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.arch_sandybridge
+// CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.arch_ivybridge
+// CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.sse4.2
+// CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi
+//
+// CHECK: define i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.resolver() comdat
+// CHECK: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.arch_sandybridge
+// CHECK: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.arch_ivybridge
+// CHECK: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.sse4.2
+// CHECK: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi
+
+// CHECK: define linkonce_odr i32 @_ZN1S3fooEi.sse4.2(%struct.S* %this, i32)
+// CHECK: ret i32 0
+
+// CHECK: declare i32 @_ZN1S3fooEi.arch_sandybridge(%struct.S*, i32)
+
+// CHECK: define linkonce_odr i32 @_ZN1S3fooEi.arch_ivybridge(%struct.S* %this, i32)
+// CHECK: ret i32 1
+
+// CHECK: define linkonce_odr i32 @_ZN1S3fooEi(%struct.S* %this, i32)
+// CHECK: ret i32 2
+
diff --git a/test/CodeGenCXX/attr-target-mv-modules.cpp b/test/CodeGenCXX/attr-target-mv-modules.cpp
new file mode 100644
index 000000000000..6ff2046831e6
--- /dev/null
+++ b/test/CodeGenCXX/attr-target-mv-modules.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -fmodules -emit-llvm %s -o - | FileCheck %s
+#pragma clang module build A
+module A {}
+#pragma clang module contents
+#pragma clang module begin A
+__attribute__((target("default"))) void f();
+__attribute__((target("sse4.2"))) void f();
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module build B
+module B {}
+#pragma clang module contents
+#pragma clang module begin B
+__attribute__((target("default"))) void f();
+__attribute__((target("sse4.2"))) void f();
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module import A
+#pragma clang module import B
+void g() { f(); }
+
+// Negative tests to validate that the resolver only calls each 1x.
+// CHECK: define void ()* @_Z1fv.resolver
+// CHECK: ret void ()* @_Z1fv.sse4.2
+// CHECK-NOT: ret void ()* @_Z1fv.sse4.2
+// CHECK: ret void ()* @_Z1fv
+// CHECK-NOT: ret void ()* @_Z1fv
diff --git a/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp b/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp
new file mode 100644
index 000000000000..63353c12d29a
--- /dev/null
+++ b/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s
+struct S {
+ int __attribute__((target("sse4.2"))) foo(int);
+ int __attribute__((target("arch=sandybridge"))) foo(int);
+ int __attribute__((target("arch=ivybridge"))) foo(int);
+ int __attribute__((target("default"))) foo(int);
+};
+
+int __attribute__((target("default"))) S::foo(int) { return 2; }
+int __attribute__((target("sse4.2"))) S::foo(int) { return 0; }
+int __attribute__((target("arch=ivybridge"))) S::foo(int) { return 1; }
+
+int bar() {
+ S s;
+ return s.foo(0);
+}
+
+// CHECK: @_ZN1S3fooEi.ifunc = ifunc i32 (%struct.S*, i32), i32 (%struct.S*, i32)* ()* @_ZN1S3fooEi.resolver
+
+// CHECK: define i32 @_ZN1S3fooEi(%struct.S* %this, i32)
+// CHECK: ret i32 2
+
+// CHECK: define i32 @_ZN1S3fooEi.sse4.2(%struct.S* %this, i32)
+// CHECK: ret i32 0
+
+// CHECK: define i32 @_ZN1S3fooEi.arch_ivybridge(%struct.S* %this, i32)
+// CHECK: ret i32 1
+
+// CHECK: define i32 @_Z3barv()
+// CHECK: %s = alloca %struct.S, align 1
+// CHECK: %call = call i32 @_ZN1S3fooEi.ifunc(%struct.S* %s, i32 0)
+
+// CHECK: define i32 (%struct.S*, i32)* @_ZN1S3fooEi.resolver() comdat
+// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_sandybridge
+// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_ivybridge
+// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.sse4.2
+// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi
+
+// CHECK: declare i32 @_ZN1S3fooEi.arch_sandybridge(%struct.S*, i32)
diff --git a/test/CodeGenCXX/attr-target-mv-overloads.cpp b/test/CodeGenCXX/attr-target-mv-overloads.cpp
new file mode 100644
index 000000000000..c72ea77fa46f
--- /dev/null
+++ b/test/CodeGenCXX/attr-target-mv-overloads.cpp
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s
+
+int __attribute__((target("sse4.2"))) foo_overload(int) { return 0; }
+int __attribute__((target("arch=sandybridge"))) foo_overload(int);
+int __attribute__((target("arch=ivybridge"))) foo_overload(int) {return 1;}
+int __attribute__((target("default"))) foo_overload(int) { return 2; }
+int __attribute__((target("sse4.2"))) foo_overload(void) { return 0; }
+int __attribute__((target("arch=sandybridge"))) foo_overload(void);
+int __attribute__((target("arch=ivybridge"))) foo_overload(void) {return 1;}
+int __attribute__((target("default"))) foo_overload(void) { return 2; }
+
+int bar2() {
+ return foo_overload() + foo_overload(1);
+}
+
+// CHECK: @_Z12foo_overloadv.ifunc = ifunc i32 (), i32 ()* ()* @_Z12foo_overloadv.resolver
+// CHECK: @_Z12foo_overloadi.ifunc = ifunc i32 (i32), i32 (i32)* ()* @_Z12foo_overloadi.resolver
+
+
+// CHECK: define i32 @_Z12foo_overloadi.sse4.2(i32)
+// CHECK: ret i32 0
+// CHECK: define i32 @_Z12foo_overloadi.arch_ivybridge(i32)
+// CHECK: ret i32 1
+// CHECK: define i32 @_Z12foo_overloadi(i32)
+// CHECK: ret i32 2
+// CHECK: define i32 @_Z12foo_overloadv.sse4.2()
+// CHECK: ret i32 0
+// CHECK: define i32 @_Z12foo_overloadv.arch_ivybridge()
+// CHECK: ret i32 1
+// CHECK: define i32 @_Z12foo_overloadv()
+// CHECK: ret i32 2
+
+// CHECK: define i32 @_Z4bar2v()
+// CHECK: call i32 @_Z12foo_overloadv.ifunc()
+// CHECK: call i32 @_Z12foo_overloadi.ifunc(i32 1)
+
+// CHECK: define i32 ()* @_Z12foo_overloadv.resolver() comdat
+// CHECK: ret i32 ()* @_Z12foo_overloadv.arch_sandybridge
+// CHECK: ret i32 ()* @_Z12foo_overloadv.arch_ivybridge
+// CHECK: ret i32 ()* @_Z12foo_overloadv.sse4.2
+// CHECK: ret i32 ()* @_Z12foo_overloadv
+
+// CHECK: define i32 (i32)* @_Z12foo_overloadi.resolver() comdat
+// CHECK: ret i32 (i32)* @_Z12foo_overloadi.arch_sandybridge
+// CHECK: ret i32 (i32)* @_Z12foo_overloadi.arch_ivybridge
+// CHECK: ret i32 (i32)* @_Z12foo_overloadi.sse4.2
+// CHECK: ret i32 (i32)* @_Z12foo_overloadi
+
+// CHECK: declare i32 @_Z12foo_overloadv.arch_sandybridge()
+// CHECK: declare i32 @_Z12foo_overloadi.arch_sandybridge(i32)
diff --git a/test/CodeGenCXX/attr-x86-interrupt.cpp b/test/CodeGenCXX/attr-x86-interrupt.cpp
index 500010469035..30cf58b1e2e3 100644
--- a/test/CodeGenCXX/attr-x86-interrupt.cpp
+++ b/test/CodeGenCXX/attr-x86-interrupt.cpp
@@ -26,10 +26,10 @@ static void foo9(int *a) __attribute__((interrupt)) {}
// X86_LINUX: define x86_intrcc void @{{.*}}foo8{{.*}}(i32* %{{.+}})
// X86_LINUX: define linkonce_odr x86_intrcc void @{{.*}}foo9{{.*}}(i32* %{{.+}})
// X86_64_WIN: @llvm.used = appending global [3 x i8*] [i8* bitcast (void (i32*, i64)* @{{.*}}foo7{{.*}} to i8*), i8* bitcast (void (i32*)* @{{.*}}foo8{{.*}} to i8*), i8* bitcast (void (i32*)* @{{.*}}foo9{{.*}} to i8*)], section "llvm.metadata"
-// X86_64_WIN: define x86_intrcc void @{{.*}}foo7{{.*}}(i32* %{{.+}}, i64 %{{.+}})
-// X86_64_WIN: define x86_intrcc void @{{.*}}foo8{{.*}}(i32* %{{.+}})
-// X86_64_WIN: define linkonce_odr x86_intrcc void @{{.*}}foo9{{.*}}(i32* %{{.+}})
+// X86_64_WIN: define dso_local x86_intrcc void @{{.*}}foo7{{.*}}(i32* %{{.+}}, i64 %{{.+}})
+// X86_64_WIN: define dso_local x86_intrcc void @{{.*}}foo8{{.*}}(i32* %{{.+}})
+// X86_64_WIN: define linkonce_odr dso_local x86_intrcc void @{{.*}}foo9{{.*}}(i32* %{{.+}})
// X86_WIN: @llvm.used = appending global [3 x i8*] [i8* bitcast (void (i32*, i32)* @{{.*}}foo7{{.*}} to i8*), i8* bitcast (void (i32*)* @{{.*}}foo8{{.*}} to i8*), i8* bitcast (void (i32*)* @{{.*}}foo9{{.*}} to i8*)], section "llvm.metadata"
-// X86_WIN: define x86_intrcc void @{{.*}}foo7{{.*}}(i32* %{{.+}}, i32 %{{.+}})
-// X86_WIN: define x86_intrcc void @{{.*}}foo8{{.*}}(i32* %{{.+}})
-// X86_WIN: define linkonce_odr x86_intrcc void @{{.*}}foo9{{.*}}(i32* %{{.+}})
+// X86_WIN: define dso_local x86_intrcc void @{{.*}}foo7{{.*}}(i32* %{{.+}}, i32 %{{.+}})
+// X86_WIN: define dso_local x86_intrcc void @{{.*}}foo8{{.*}}(i32* %{{.+}})
+// X86_WIN: define linkonce_odr dso_local x86_intrcc void @{{.*}}foo9{{.*}}(i32* %{{.+}})
diff --git a/test/CodeGenCXX/block-capture.cpp b/test/CodeGenCXX/block-capture.cpp
new file mode 100644
index 000000000000..623838357a38
--- /dev/null
+++ b/test/CodeGenCXX/block-capture.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -x c++ -std=c++11 -fblocks -emit-llvm %s -o - | FileCheck %s
+
+// CHECK: %struct.__block_byref_baz = type { i8*, %struct.__block_byref_baz*, i32, i32, i32 }
+// CHECK: [[baz:%[0-9a-z_]*]] = alloca %struct.__block_byref_baz
+// CHECK: [[bazref:%[0-9a-z_\.]*]] = getelementptr inbounds %struct.__block_byref_baz, %struct.__block_byref_baz* [[baz]], i32 0, i32 1
+// CHECK: store %struct.__block_byref_baz* [[baz]], %struct.__block_byref_baz** [[bazref]]
+// CHECK: [[disposable:%[0-9a-z_]*]] = bitcast %struct.__block_byref_baz* [[baz]] to i8*
+// CHECK: call void @_Block_object_dispose(i8* [[disposable]]
+
+int main() {
+ __block int baz = [&]() { return 0; }();
+ return 0;
+}
diff --git a/test/CodeGenCXX/block-inalloca.cpp b/test/CodeGenCXX/block-inalloca.cpp
new file mode 100644
index 000000000000..b827dde7abdc
--- /dev/null
+++ b/test/CodeGenCXX/block-inalloca.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fblocks -emit-llvm -o - %s | FileCheck %s
+
+struct S {
+ S(const struct S &) {}
+};
+
+void (^b)(S) = ^(S) {};
+
+// CHECK: [[DESCRIPTOR:%.*]] = getelementptr inbounds <{ i8*, %struct.S, [3 x i8] }>, <{ i8*, %struct.S, [3 x i8] }>* %0, i32 0, i32 0
+// CHECK: load i8*, i8** [[DESCRIPTOR]]
+
diff --git a/test/CodeGenCXX/builtin-operator-new-delete.cpp b/test/CodeGenCXX/builtin-operator-new-delete.cpp
new file mode 100644
index 000000000000..712805a62390
--- /dev/null
+++ b/test/CodeGenCXX/builtin-operator-new-delete.cpp
@@ -0,0 +1,71 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s \
+// RUN: -faligned-allocation -fsized-deallocation -emit-llvm -o - \
+// RUN: | FileCheck %s
+
+typedef __SIZE_TYPE__ size_t;
+
+// Declare an 'operator new' template to tickle a bug in __builtin_operator_new.
+template<typename T> void *operator new(size_t, int (*)(T));
+
+// Ensure that this declaration doesn't cause operator new to lose its
+// 'noalias' attribute.
+void *operator new(size_t);
+
+namespace std {
+ struct nothrow_t {};
+ enum class align_val_t : size_t { __zero = 0,
+ __max = (size_t)-1 };
+}
+std::nothrow_t nothrow;
+
+// Declare the reserved placement operators.
+void *operator new(size_t, void*) throw();
+void operator delete(void*, void*) throw();
+void *operator new[](size_t, void*) throw();
+void operator delete[](void*, void*) throw();
+
+// Declare the replaceable global allocation operators.
+void *operator new(size_t, const std::nothrow_t &) throw();
+void *operator new[](size_t, const std::nothrow_t &) throw();
+void operator delete(void *, const std::nothrow_t &) throw();
+void operator delete[](void *, const std::nothrow_t &) throw();
+
+// Declare some other placement operators.
+void *operator new(size_t, void*, bool) throw();
+void *operator new[](size_t, void*, bool) throw();
+
+
+// CHECK-LABEL: define void @test_basic(
+extern "C" void test_basic() {
+ // CHECK: call i8* @_Znwm(i64 4) [[ATTR_BUILTIN_NEW:#[^ ]*]]
+ // CHECK: call void @_ZdlPv({{.*}}) [[ATTR_BUILTIN_DELETE:#[^ ]*]]
+ // CHECK: ret void
+ __builtin_operator_delete(__builtin_operator_new(4));
+}
+// CHECK: declare noalias i8* @_Znwm(i64) [[ATTR_NOBUILTIN:#[^ ]*]]
+// CHECK: declare void @_ZdlPv(i8*) [[ATTR_NOBUILTIN_NOUNWIND:#[^ ]*]]
+
+// CHECK-LABEL: define void @test_aligned_alloc(
+extern "C" void test_aligned_alloc() {
+ // CHECK: call i8* @_ZnwmSt11align_val_t(i64 4, i64 4) [[ATTR_BUILTIN_NEW:#[^ ]*]]
+ // CHECK: call void @_ZdlPvSt11align_val_t({{.*}}, i64 4) [[ATTR_BUILTIN_DELETE:#[^ ]*]]
+ __builtin_operator_delete(__builtin_operator_new(4, std::align_val_t(4)), std::align_val_t(4));
+}
+// CHECK: declare noalias i8* @_ZnwmSt11align_val_t(i64, i64) [[ATTR_NOBUILTIN:#[^ ]*]]
+// CHECK: declare void @_ZdlPvSt11align_val_t(i8*, i64) [[ATTR_NOBUILTIN_NOUNWIND:#[^ ]*]]
+
+
+// CHECK-LABEL: define void @test_sized_delete(
+extern "C" void test_sized_delete() {
+ // CHECK: call i8* @_Znwm(i64 4) [[ATTR_BUILTIN_NEW:#[^ ]*]]
+ // CHECK: call void @_ZdlPvm({{.*}}, i64 4) [[ATTR_BUILTIN_DELETE:#[^ ]*]]
+ __builtin_operator_delete(__builtin_operator_new(4), 4);
+}
+// CHECK: declare void @_ZdlPvm(i8*, i64) [[ATTR_NOBUILTIN_UNWIND:#[^ ]*]]
+
+
+// CHECK-DAG: attributes [[ATTR_NOBUILTIN]] = {{[{].*}} nobuiltin {{.*[}]}}
+// CHECK-DAG: attributes [[ATTR_NOBUILTIN_NOUNWIND]] = {{[{].*}} nobuiltin nounwind {{.*[}]}}
+
+// CHECK-DAG: attributes [[ATTR_BUILTIN_NEW]] = {{[{].*}} builtin {{.*[}]}}
+// CHECK-DAG: attributes [[ATTR_BUILTIN_DELETE]] = {{[{].*}} builtin {{.*[}]}}
diff --git a/test/CodeGenCXX/builtins.cpp b/test/CodeGenCXX/builtins.cpp
index a49deea2524c..33c714e9e186 100644
--- a/test/CodeGenCXX/builtins.cpp
+++ b/test/CodeGenCXX/builtins.cpp
@@ -30,3 +30,19 @@ long y = __builtin_abs(-2l);
extern const char char_memchr_arg[32];
char *memchr_result = __builtin_char_memchr(char_memchr_arg, 123, 32);
// CHECK: call i8* @memchr(i8* getelementptr inbounds ([32 x i8], [32 x i8]* @char_memchr_arg, i32 0, i32 0), i32 123, i64 32)
+
+int constexpr_overflow_result() {
+ constexpr int x = 1;
+ // CHECK: alloca i32
+ constexpr int y = 2;
+ // CHECK: alloca i32
+ int z;
+ // CHECK: [[Z:%.+]] = alloca i32
+
+ __builtin_sadd_overflow(x, y, &z);
+ return z;
+ // CHECK: [[RET_PTR:%.+]] = extractvalue { i32, i1 } %0, 0
+ // CHECK: store i32 [[RET_PTR]], i32* [[Z]]
+ // CHECK: [[RET_VAL:%.+]] = load i32, i32* [[Z]]
+ // CHECK: ret i32 [[RET_VAL]]
+}
diff --git a/test/CodeGenCXX/captured-statements.cpp b/test/CodeGenCXX/captured-statements.cpp
index 95e73e548399..c8832f1db714 100644
--- a/test/CodeGenCXX/captured-statements.cpp
+++ b/test/CodeGenCXX/captured-statements.cpp
@@ -182,7 +182,7 @@ void test_capture_lambda() {
}
inline int test_captured_linkage() {
- // CHECK-7: @_ZZ21test_captured_linkagevE1i = linkonce_odr global i32 0
+ // CHECK-7: @_ZZ21test_captured_linkagevE1i = linkonce_odr {{(dso_local )?}}global i32 0
int j;
#pragma clang __debug captured
{
diff --git a/test/CodeGenCXX/catch-undef-behavior.cpp b/test/CodeGenCXX/catch-undef-behavior.cpp
index e8287538982b..4513936e49a3 100644
--- a/test/CodeGenCXX/catch-undef-behavior.cpp
+++ b/test/CodeGenCXX/catch-undef-behavior.cpp
@@ -206,7 +206,7 @@ void bad_downcast_pointer(S *p) {
// CHECK: %[[NONNULL:.*]] = icmp ne {{.*}}, null
// CHECK: br i1 %[[NONNULL]],
- // A null poiner access is guarded without -fsanitize=null.
+ // A null pointer access is guarded without -fsanitize=null.
// DOWNCAST-NULL: %[[NONNULL:.*]] = icmp ne {{.*}}, null
// DOWNCAST-NULL: br i1 %[[NONNULL]],
@@ -371,7 +371,7 @@ class C : public A, public B // align=16
void downcast_pointer(B *b) {
(void) static_cast<C*>(b);
// Alignment check from EmitTypeCheck(TCK_DowncastPointer, ...)
- // CHECK: [[SUB:%[.a-z0-9]*]] = getelementptr i8, i8* {{.*}}, i64 -16
+ // CHECK: [[SUB:%[.a-z0-9]*]] = getelementptr inbounds i8, i8* {{.*}}, i64 -16
// CHECK-NEXT: [[C:%.+]] = bitcast i8* [[SUB]] to %class.C*
// null check goes here
// CHECK: [[FROM_PHI:%.+]] = phi %class.C* [ [[C]], {{.*}} ], {{.*}}
@@ -388,7 +388,7 @@ void downcast_pointer(B *b) {
void downcast_reference(B &b) {
(void) static_cast<C&>(b);
// Alignment check from EmitTypeCheck(TCK_DowncastReference, ...)
- // CHECK: [[SUB:%[.a-z0-9]*]] = getelementptr i8, i8* {{.*}}, i64 -16
+ // CHECK: [[SUB:%[.a-z0-9]*]] = getelementptr inbounds i8, i8* {{.*}}, i64 -16
// CHECK-NEXT: [[C:%.+]] = bitcast i8* [[SUB]] to %class.C*
// Objectsize check goes here
// CHECK: [[C_INT:%.+]] = ptrtoint %class.C* [[C]] to i64
diff --git a/test/CodeGenCXX/cfi-cross-dso.cpp b/test/CodeGenCXX/cfi-cross-dso.cpp
index bfa0705c6f8f..6d5e0591191c 100644
--- a/test/CodeGenCXX/cfi-cross-dso.cpp
+++ b/test/CodeGenCXX/cfi-cross-dso.cpp
@@ -26,7 +26,7 @@ void g() {
b.f();
}
-// MS: @[[B_VTABLE:.*]] = private unnamed_addr constant { [2 x i8*] } {{.*}}@"\01??_R4B@?A@@6B@"{{.*}}@"\01?f@B@?A@@UEAAXXZ"
+// MS: @[[B_VTABLE:.*]] = private unnamed_addr constant { [2 x i8*] } {{.*}}@"??_R4B@?A@@6B@"{{.*}}@"?f@B@?A@@UEAAXXZ"
// CHECK: %[[VT:.*]] = load void (%struct.A*)**, void (%struct.A*)***
// CHECK: %[[VT2:.*]] = bitcast {{.*}}%[[VT]] to i8*, !nosanitize
diff --git a/test/CodeGenCXX/cfi-icall.cpp b/test/CodeGenCXX/cfi-icall.cpp
index 5f5778fc1f7c..e53aeefd8a9b 100644
--- a/test/CodeGenCXX/cfi-icall.cpp
+++ b/test/CodeGenCXX/cfi-icall.cpp
@@ -21,7 +21,7 @@ void g() {
}
// ITANIUM: define internal void @_ZN12_GLOBAL__N_11fENS_1SE({{.*}} !type [[TS1:![0-9]+]] !type [[TS2:![0-9]+]]
-// MS: define internal void @"\01?f@?A@@YAXUS@?A@@@Z"({{.*}} !type [[TS1:![0-9]+]] !type [[TS2:![0-9]+]]
+// MS: define internal void @"?f@?A@@YAXUS@?A@@@Z"({{.*}} !type [[TS1:![0-9]+]] !type [[TS2:![0-9]+]]
// CHECK: [[VOIDS1]] = distinct !{}
// CHECK: [[TS1]] = !{i64 0, [[VOIDS1]]}
diff --git a/test/CodeGenCXX/cfi-mfcall-incomplete.cpp b/test/CodeGenCXX/cfi-mfcall-incomplete.cpp
new file mode 100644
index 000000000000..345be124e93b
--- /dev/null
+++ b/test/CodeGenCXX/cfi-mfcall-incomplete.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-mfcall -fsanitize-trap=cfi-mfcall -fvisibility hidden -emit-llvm -o - %s | FileCheck %s
+
+struct S;
+
+void f(S *s, void (S::*p)()) {
+ // CHECK-NOT: llvm.type.test
+ // CHECK: llvm.type.test{{.*}}!"_ZTSM1SFvvE.virtual"
+ // CHECK-NOT: llvm.type.test
+ (s->*p)();
+}
+
+// CHECK: declare i1 @llvm.type.test
diff --git a/test/CodeGenCXX/cfi-mfcall.cpp b/test/CodeGenCXX/cfi-mfcall.cpp
new file mode 100644
index 000000000000..c16b20b8dcec
--- /dev/null
+++ b/test/CodeGenCXX/cfi-mfcall.cpp
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-mfcall -fsanitize-trap=cfi-mfcall -fvisibility hidden -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-mfcall -fsanitize-trap=cfi-mfcall -fvisibility default -emit-llvm -o - %s | FileCheck --check-prefix=DEFAULT %s
+
+struct B1 {};
+struct B2 {};
+struct B3 : B2 {};
+struct S : B1, B3 {};
+
+// DEFAULT-NOT: llvm.type.test
+
+void f(S *s, void (S::*p)()) {
+ // CHECK: [[OFFSET:%.*]] = sub i64 {{.*}}, 1
+ // CHECK: [[VFPTR:%.*]] = getelementptr i8, i8* %{{.*}}, i64 [[OFFSET]]
+ // CHECK: [[TT:%.*]] = call i1 @llvm.type.test(i8* [[VFPTR]], metadata !"_ZTSM1SFvvE.virtual")
+ // CHECK: br i1 [[TT]], label {{.*}}, label %[[TRAP1:[^,]*]]
+
+ // CHECK: [[TRAP1]]:
+ // CHECK-NEXT: llvm.trap
+
+ // CHECK: [[NVFPTR:%.*]] = bitcast void (%struct.S*)* {{.*}} to i8*
+ // CHECK: [[TT1:%.*]] = call i1 @llvm.type.test(i8* [[NVFPTR]], metadata !"_ZTSM2B1FvvE")
+ // CHECK: [[OR1:%.*]] = or i1 false, [[TT1]]
+ // CHECK: [[TT2:%.*]] = call i1 @llvm.type.test(i8* [[NVFPTR]], metadata !"_ZTSM2B2FvvE")
+ // CHECK: [[OR2:%.*]] = or i1 [[OR1]], [[TT2]]
+ // CHECK: br i1 [[OR2]], label {{.*}}, label %[[TRAP2:[^,]*]]
+
+ // CHECK: [[TRAP2]]:
+ // CHECK-NEXT: llvm.trap
+ (s->*p)();
+}
diff --git a/test/CodeGenCXX/cfi-ms-vbase-derived-cast.cpp b/test/CodeGenCXX/cfi-ms-vbase-derived-cast.cpp
index 3276d8f33edc..6142ca56878f 100644
--- a/test/CodeGenCXX/cfi-ms-vbase-derived-cast.cpp
+++ b/test/CodeGenCXX/cfi-ms-vbase-derived-cast.cpp
@@ -8,7 +8,7 @@ struct foo {
template <typename T>
struct bar : virtual public foo {
void f() {
- // CHECK: define{{.*}}@"\01?f@?$bar@Ubaz@@@@UEAAXXZ"
+ // CHECK: define{{.*}}@"?f@?$bar@Ubaz@@@@UEAAXXZ"
// Load "this", vbtable, vbase offset and vtable.
// CHECK: load
// CHECK: load
diff --git a/test/CodeGenCXX/cfi-ms-vbase-nvcall.cpp b/test/CodeGenCXX/cfi-ms-vbase-nvcall.cpp
index ab610628232e..d4232555c9d8 100644
--- a/test/CodeGenCXX/cfi-ms-vbase-nvcall.cpp
+++ b/test/CodeGenCXX/cfi-ms-vbase-nvcall.cpp
@@ -16,7 +16,7 @@ struct baz : public bar<baz> {
};
void f(baz *z) {
- // CHECK: define{{.*}}@"\01?f@@YAXPEAUbaz@@@Z"
+ // CHECK: define{{.*}}@"?f@@YAXPEAUbaz@@@Z"
// Load z, vbtable, vbase offset and vtable.
// CHECK: load
// CHECK: load
diff --git a/test/CodeGenCXX/cfi-vcall-check-after-args.cpp b/test/CodeGenCXX/cfi-vcall-check-after-args.cpp
new file mode 100644
index 000000000000..4c2ea8c9e85f
--- /dev/null
+++ b/test/CodeGenCXX/cfi-vcall-check-after-args.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -flto -flto-unit -triple x86_64-unknown-linux -fvisibility hidden -fsanitize=cfi-vcall -fsanitize-trap=cfi-vcall -emit-llvm -o - %s | FileCheck %s
+
+struct A {
+ virtual void f(int);
+};
+
+int g();
+void f(A *a) {
+ // CHECK: call i32 @_Z1gv()
+ // CHECK: call i1 @llvm.type.test
+ a->f(g());
+}
diff --git a/test/CodeGenCXX/char8_t.cpp b/test/CodeGenCXX/char8_t.cpp
new file mode 100644
index 000000000000..f24f12d6df40
--- /dev/null
+++ b/test/CodeGenCXX/char8_t.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -std=c++17 -emit-llvm -fchar8_t -triple x86_64-linux %s -o - | FileCheck %s
+// RUN: %clang_cc1 -std=c++17 -emit-llvm -fchar8_t -triple x86_64-windows %s -o - -verify
+
+// CHECK: define void @_Z1fDu(
+void f(char8_t c) {} // expected-error {{cannot mangle this built-in char8_t type yet}}
+
+// CHECK: define weak_odr void @_Z1gIiEvDTplplcvT__ELA4_KDuELDu114EE
+template<typename T> void g(decltype(T() + u8"foo" + u8'r')) {}
+template void g<int>(const char8_t*);
diff --git a/test/CodeGenCXX/code-seg.cpp b/test/CodeGenCXX/code-seg.cpp
new file mode 100644
index 000000000000..7dad9274208a
--- /dev/null
+++ b/test/CodeGenCXX/code-seg.cpp
@@ -0,0 +1,139 @@
+// RUN: %clang_cc1 -emit-llvm -triple i686-pc-win32 -fms-extensions -verify -o - %s | FileCheck %s
+// expected-no-diagnostics
+
+// Simple case
+
+int __declspec(code_seg("foo_one")) bar_one() { return 1; }
+//CHECK: define {{.*}}bar_one{{.*}} section "foo_one"
+
+// Simple case - explicit attribute used over pragma
+#pragma code_seg("foo_two")
+int __declspec(code_seg("foo_three")) bar2() { return 2; }
+//CHECK: define {{.*}}bar2{{.*}} section "foo_three"
+
+// Check that attribute on one function doesn't affect another
+int another1() { return 1001; }
+//CHECK: define {{.*}}another1{{.*}} section "foo_two"
+
+// Member functions
+
+struct __declspec(code_seg("foo_four")) Foo {
+ int bar3() {return 0;}
+ int bar4();
+ int __declspec(code_seg("foo_six")) bar6() { return 6; }
+ int bar7() { return 7; }
+ struct Inner {
+ int bar5() { return 5; }
+ } z;
+ virtual int baz1() { return 1; }
+};
+
+struct __declspec(code_seg("foo_four")) FooTwo : Foo {
+ int baz1() { return 20; }
+};
+
+int caller1() {
+ Foo f; return f.bar3();
+}
+
+//CHECK: define {{.*}}bar3@Foo{{.*}} section "foo_four"
+int Foo::bar4() { return 4; }
+//CHECK: define {{.*}}bar4@Foo{{.*}} section "foo_four"
+
+#pragma code_seg("someother")
+
+int caller2() {
+ Foo f;
+ Foo *fp = new FooTwo;
+ return f.z.bar5() + f.bar6() + f.bar7() + fp->baz1();
+}
+// MS Compiler and Docs do not match for nested routines
+// Doc says: define {{.*}}bar5@Inner@Foo{{.*}} section "foo_four"
+// Compiler says: define {{.*}}bar5@Inner@Foo{{.*}} section "foo_two"
+// A bug has been reported: see https://reviews.llvm.org/D22931, the
+// Microsoft feedback page is no longer available.
+//CHECK: define {{.*}}bar5@Inner@Foo{{.*}} section "foo_two"
+//CHECK: define {{.*}}bar6@Foo{{.*}} section "foo_six"
+//CHECK: define {{.*}}bar7@Foo{{.*}} section "foo_four"
+// Check that code_seg active at class declaration is not used on member
+// declared outside class when it is not active.
+
+#pragma code_seg(push,"AnotherSeg")
+
+struct FooThree {
+ int bar8();
+ int bar9() { return 9; }
+};
+
+#pragma code_seg(pop)
+
+
+int FooThree::bar8() {return 0;}
+
+int caller3()
+{
+ FooThree f;
+ return f.bar8() + f.bar9();
+}
+
+//CHECK: define {{.*}}bar8@FooThree{{.*}} section "someother"
+//CHECK: define {{.*}}bar9@FooThree{{.*}} section "AnotherSeg"
+
+struct NonTrivialCopy {
+ NonTrivialCopy();
+ NonTrivialCopy(const NonTrivialCopy&);
+ ~NonTrivialCopy();
+};
+
+// check the section for compiler-generated function with declspec.
+
+struct __declspec(code_seg("foo_seven")) FooFour {
+ FooFour() {}
+ int __declspec(code_seg("foo_eight")) bar10(int t) { return t; }
+ NonTrivialCopy f;
+};
+
+//CHECK: define {{.*}}0FooFour@@QAE@ABU0@@Z{{.*}} section "foo_seven"
+// check the section for compiler-generated function with no declspec.
+
+struct FooFive {
+ FooFive() {}
+ int __declspec(code_seg("foo_nine")) bar11(int t) { return t; }
+ NonTrivialCopy f;
+};
+
+//CHECK: define {{.*}}0FooFive@@QAE@ABU0@@Z{{.*}} section "someother"
+
+#pragma code_seg("YetAnother")
+int caller4()
+{
+ FooFour z1;
+ FooFour z2 = z1;
+ FooFive y1;
+ FooFive y2 = y1;
+ return z2.bar10(0) + y2.bar11(1);
+}
+
+//CHECK: define {{.*}}bar10@FooFour{{.*}} section "foo_eight"
+//CHECK: define {{.*}}bar11@FooFive{{.*}} section "foo_nine"
+
+struct FooSix {
+ #pragma code_seg("foo_ten")
+ int bar12() { return 12; }
+ #pragma code_seg("foo_eleven")
+ int bar13() { return 13; }
+};
+
+int bar14() { return 14; }
+//CHECK: define {{.*}}bar14{{.*}} section "foo_eleven"
+
+int caller5()
+{
+ FooSix fsix;
+ return fsix.bar12() + fsix.bar13();
+}
+
+//CHECK: define {{.*}}bar12@FooSix{{.*}} section "foo_ten"
+//CHECK: define {{.*}}bar13@FooSix{{.*}} section "foo_eleven"
+//CHECK: define {{.*}}baz1@FooTwo{{.*}} section "foo_four"
+
diff --git a/test/CodeGenCXX/code-seg1.cpp b/test/CodeGenCXX/code-seg1.cpp
new file mode 100644
index 000000000000..93be3e520a54
--- /dev/null
+++ b/test/CodeGenCXX/code-seg1.cpp
@@ -0,0 +1,87 @@
+// RUN: %clang_cc1 -emit-llvm -triple i686-pc-win32 -fms-extensions -verify -o - %s | FileCheck %s
+// expected-no-diagnostics
+// The Microsoft document says: "When this attribute 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."
+// But the MS compiler does not always follow that. A bug has been reported:
+// see https://reviews.llvm.org/D22931, the Microsoft feedback page is no
+// longer available.
+// The MS compiler will apply a declspec from the parent class if there is no
+// #pragma code_seg active at the class definition. If there is an active
+// code_seg that is used instead.
+
+// No active code_seg
+
+struct __declspec(code_seg("foo_outer")) Foo1 {
+ struct Inner {
+ void bar1();
+ static void bar2();
+ };
+};
+void Foo1::Inner::bar1() {}
+void Foo1::Inner::bar2() {}
+
+//CHECK: define {{.*}}bar1@Inner@Foo1{{.*}} section "foo_outer"
+//CHECK: define {{.*}}bar2@Inner@Foo1{{.*}} section "foo_outer"
+
+struct __declspec(code_seg("foo_outer")) Foo2 {
+ struct __declspec(code_seg("foo_inner")) Inner {
+ void bar1();
+ static void bar2();
+ };
+};
+void Foo2::Inner::bar1() {}
+void Foo2::Inner::bar2() {}
+
+//CHECK: define {{.*}}bar1@Inner@Foo2{{.*}} section "foo_inner"
+//CHECK: define {{.*}}bar2@Inner@Foo2{{.*}} section "foo_inner"
+
+#pragma code_seg(push, "otherseg")
+struct __declspec(code_seg("foo_outer")) Foo3 {
+ struct Inner {
+ void bar1();
+ static void bar2();
+ };
+};
+void Foo3::Inner::bar1() {}
+void Foo3::Inner::bar2() {}
+
+//CHECK: define {{.*}}bar1@Inner@Foo3{{.*}} section "otherseg"
+//CHECK: define {{.*}}bar2@Inner@Foo3{{.*}} section "otherseg"
+
+struct __declspec(code_seg("foo_outer")) Foo4 {
+ struct __declspec(code_seg("foo_inner")) Inner {
+ void bar1();
+ static void bar2();
+ };
+};
+void Foo4::Inner::bar1() {}
+void Foo4::Inner::bar2() {}
+
+//CHECK: define {{.*}}bar1@Inner@Foo4{{.*}} section "foo_inner"
+//CHECK: define {{.*}}bar2@Inner@Foo4{{.*}} section "foo_inner"
+
+#pragma code_seg(pop)
+// Back to no active pragma
+struct __declspec(code_seg("foo_outer")) Foo5 {
+ struct Inner {
+ void bar1();
+ static void bar2();
+ struct __declspec(code_seg("inner1_seg")) Inner1 {
+ struct Inner2 {
+ void bar1();
+ static void bar2();
+ };
+ };
+ };
+};
+void Foo5::Inner::bar1() {}
+void Foo5::Inner::bar2() {}
+void Foo5::Inner::Inner1::Inner2::bar1() {}
+void Foo5::Inner::Inner1::Inner2::bar2() {}
+
+//CHECK: define {{.*}}bar1@Inner@Foo5{{.*}} section "foo_outer"
+//CHECK: define {{.*}}bar2@Inner@Foo5{{.*}} section "foo_outer"
+//CHECK: define {{.*}}bar1@Inner2@Inner1@Inner@Foo5{{.*}} section "inner1_seg"
+//CHECK: define {{.*}}bar2@Inner2@Inner1@Inner@Foo5{{.*}} section "inner1_seg"
+
diff --git a/test/CodeGenCXX/code-seg2.cpp b/test/CodeGenCXX/code-seg2.cpp
new file mode 100644
index 000000000000..ab72bf44cb89
--- /dev/null
+++ b/test/CodeGenCXX/code-seg2.cpp
@@ -0,0 +1,111 @@
+// RUN: %clang_cc1 -emit-llvm -triple i686-pc-win32 -std=c++11 -fms-extensions -verify -o - %s | FileCheck %s
+// expected-no-diagnostics
+
+// Class member templates
+
+#pragma code_seg(push, "something")
+
+template <typename T>
+struct __declspec(code_seg("foo_one")) ClassOne {
+ int bar1(T t) { return int(t); }
+ int bar2(T t);
+ int bar3(T t);
+};
+
+template <typename T>
+int ClassOne<T>::bar2(T t) {
+ return int(t);
+}
+
+int caller1() {
+ ClassOne<int> coi;
+ return coi.bar1(6) + coi.bar2(3);
+}
+
+//CHECK: define {{.*}}bar1@?$ClassOne{{.*}} section "foo_one"
+//CHECK: define {{.*}}bar2@?$ClassOne{{.*}} section "foo_one"
+
+
+template <typename T>
+struct ClassTwo {
+ int bar11(T t) { return int(t); }
+ int bar22(T t);
+ int bar33(T t);
+};
+
+#pragma code_seg("newone")
+
+template <typename T>
+int ClassTwo<T>::bar22(T t) {
+ return int(t);
+}
+
+#pragma code_seg("someother")
+
+template <typename T>
+int ClassTwo<T>::bar33(T t) {
+ return int(t);
+}
+
+#pragma code_seg("yetanother")
+
+int caller2() {
+ ClassTwo<int> coi;
+ return coi.bar11(6) + coi.bar22(3) + coi.bar33(44);
+}
+
+//CHECK: define {{.*}}bar11@?$ClassTwo{{.*}} section "something"
+//CHECK: define {{.*}}bar22@?$ClassTwo{{.*}} section "newone"
+//CHECK: define {{.*}}bar33@?$ClassTwo{{.*}} section "someother"
+
+template<>
+struct ClassOne<double>
+{
+ int bar44(double d) { return 1; }
+};
+template<>
+struct __declspec(code_seg("foo_three")) ClassOne<long>
+{
+ int bar55(long d) { return 1; }
+};
+
+#pragma code_seg("onemore")
+int caller3() {
+ ClassOne<double> d;
+ ClassOne<long> l;
+ return d.bar44(1.0)+l.bar55(1);
+}
+
+//CHECK: define {{.*}}bar44{{.*}} section "yetanother"
+//CHECK: define {{.*}}bar55{{.*}} section "foo_three"
+
+
+// Function templates
+template <typename T>
+int __declspec(code_seg("foo_four")) bar66(T t) { return int(t); }
+
+// specializations do not take the segment from primary
+template<>
+int bar66(int i) { return 0; }
+
+#pragma code_seg(pop)
+
+template<>
+int bar66(char c) { return 0; }
+
+struct A1 {int i;};
+template<>
+int __declspec(code_seg("foo_five")) bar66(A1 a) { return a.i; }
+
+int caller4()
+{
+// but instantiations do use the section from the primary
+return bar66(0) + bar66(1.0) + bar66('c');
+}
+//CHECK: define {{.*}}bar66@H{{.*}} section "onemore"
+//CHECK-NOT: define {{.*}}bar66@D{{.*}} section
+//CHECK: define {{.*}}bar66@UA1{{.*}} section "foo_five"
+//CHECK: define {{.*}}bar66@N{{.*}} section "foo_four"
+
+
+
diff --git a/test/CodeGenCXX/code-seg3.cpp b/test/CodeGenCXX/code-seg3.cpp
new file mode 100644
index 000000000000..d6f267747e3c
--- /dev/null
+++ b/test/CodeGenCXX/code-seg3.cpp
@@ -0,0 +1,65 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions %s -triple x86_64-pc-win32
+// expected-no-diagnostics
+
+// Non-Member Function Overloading is involved
+
+int __declspec(code_seg("foo_one")) bar_one(int) { return 1; }
+//CHECK: define {{.*}}bar_one{{.*}} section "foo_one"
+int __declspec(code_seg("foo_two")) bar_one(int,float) { return 11; }
+//CHECK: define {{.*}}bar_one{{.*}} section "foo_two"
+int __declspec(code_seg("foo_three")) bar_one(float) { return 12; }
+//CHECK: define {{.*}}bar_one{{.*}} section "foo_three"
+
+// virtual function overloading is involved
+
+struct __declspec(code_seg("my_one")) Base3 {
+ virtual int barA(int) { return 1; }
+ virtual int barA(int,float) { return 2; }
+ virtual int barA(float) { return 3; }
+
+ virtual void __declspec(code_seg("my_two")) barB(int) { }
+ virtual void __declspec(code_seg("my_three")) barB(float) { }
+ virtual void __declspec(code_seg("my_four")) barB(int, float) { }
+
+};
+
+//CHECK: define {{.*}}barA@Base3{{.*}} section "my_one"
+//CHECK: define {{.*}}barA@Base3{{.*}} section "my_one"
+//CHECK: define {{.*}}barA@Base3{{.*}} section "my_one"
+//CHECK: define {{.*}}barB@Base3{{.*}} section "my_two"
+//CHECK: define {{.*}}barB@Base3{{.*}} section "my_three"
+//CHECK: define {{.*}}barB@Base3{{.*}} section "my_four"
+
+#pragma code_seg("another")
+// Member functions
+struct __declspec(code_seg("foo_four")) Foo {
+ int bar3() {return 0;}
+ __declspec(code_seg("foo_lala")) int bar4() {return 0;} }; int caller() {Foo f; return f.bar3() + f.bar4(); }
+
+//CHECK: define {{.*}}bar3@Foo{{.*}} section "foo_four"
+//CHECK: define {{.*}}bar4@Foo{{.*}} section "foo_lala"
+
+// Lambdas
+#pragma code_seg("something")
+
+int __declspec(code_seg("foo")) bar1()
+{
+ int lala = 4;
+ auto l = [=](int i) { return i+4; };
+ return l(-4);
+}
+
+//CHECK: define {{.*}}bar1{{.*}} section "foo"
+//CHECK: define {{.*}}lambda{{.*}}bar1{{.*}} section "something"
+
+double __declspec(code_seg("foo")) bar2()
+{
+ double lala = 4.0;
+ auto l = [=](double d) __declspec(code_seg("another")) { return d+4.0; };
+ return l(4.0);
+}
+
+//CHECK: define {{.*}}bar2{{.*}} section "foo"
+//CHECK: define {{.*}}lambda{{.*}}bar2{{.*}} section "another"
+
+
diff --git a/test/CodeGenCXX/conditional-temporaries.cpp b/test/CodeGenCXX/conditional-temporaries.cpp
index a3cc2fef1e8f..e08de61f9d41 100644
--- a/test/CodeGenCXX/conditional-temporaries.cpp
+++ b/test/CodeGenCXX/conditional-temporaries.cpp
@@ -1,4 +1,6 @@
+// REQUIRES: amdgpu-registered-target
// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -O3 | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=amdgcn-amd-amdhsa -O3 | FileCheck %s
namespace {
diff --git a/test/CodeGenCXX/const-base-cast.cpp b/test/CodeGenCXX/const-base-cast.cpp
index dd980d5469bf..bb08b9d21fcf 100644
--- a/test/CodeGenCXX/const-base-cast.cpp
+++ b/test/CodeGenCXX/const-base-cast.cpp
@@ -7,4 +7,4 @@ struct B { char y; };
struct C : A,B {};
unsigned char x = ((char*)(B*)(C*)0x1000) - (char*)0x1000;
-// CHECK: @x = global i8 1
+// CHECK: @x = {{(dso_local )?}}global i8 1
diff --git a/test/CodeGenCXX/const-global-linkage.cpp b/test/CodeGenCXX/const-global-linkage.cpp
index e1e932197479..2ec64cfeeecf 100644
--- a/test/CodeGenCXX/const-global-linkage.cpp
+++ b/test/CodeGenCXX/const-global-linkage.cpp
@@ -4,7 +4,7 @@ const int x = 10;
const int y = 20;
const volatile int z = 30;
// CHECK-NOT: @x
-// CHECK: @z = constant i32 30
+// CHECK: @z = {{(dso_local )?}}constant i32 30
// CHECK: @_ZL1y = internal constant i32 20
const int& b() { return y; }
@@ -12,6 +12,6 @@ const char z1[] = "asdf";
const char z2[] = "zxcv";
const volatile char z3[] = "zxcv";
// CHECK-NOT: @z1
-// CHECK: @z3 = constant
+// CHECK: @z3 = {{(dso_local )?}}constant
// CHECK: @_ZL2z2 = internal constant
const char* b2() { return z2; }
diff --git a/test/CodeGenCXX/const-init-cxx11.cpp b/test/CodeGenCXX/const-init-cxx11.cpp
index c4962bc08ad6..801d7b1e19cc 100644
--- a/test/CodeGenCXX/const-init-cxx11.cpp
+++ b/test/CodeGenCXX/const-init-cxx11.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -w -triple x86_64-elf-gnu -emit-llvm -o - %s -std=c++11 | FileCheck %s
+// RUN: %clang_cc1 -w -fmerge-all-constants -triple x86_64-elf-gnu -emit-llvm -o - %s -std=c++11 | FileCheck %s
// FIXME: The padding in all these objects should be zero-initialized.
namespace StructUnion {
diff --git a/test/CodeGenCXX/constructor-alias.cpp b/test/CodeGenCXX/constructor-alias.cpp
index 8359bb90a051..ee2e57b711c9 100644
--- a/test/CodeGenCXX/constructor-alias.cpp
+++ b/test/CodeGenCXX/constructor-alias.cpp
@@ -9,4 +9,4 @@ struct B {
B::B() {
}
-// CHECK: @_ZN1BC1Ev = alias void (%struct.B*), void (%struct.B*)* @_ZN1BC2Ev
+// CHECK: @_ZN1BC1Ev = unnamed_addr alias void (%struct.B*), void (%struct.B*)* @_ZN1BC2Ev
diff --git a/test/CodeGenCXX/constructor-destructor-return-this.cpp b/test/CodeGenCXX/constructor-destructor-return-this.cpp
index 164fda3c1c38..f6450e2d4d77 100644
--- a/test/CodeGenCXX/constructor-destructor-return-this.cpp
+++ b/test/CodeGenCXX/constructor-destructor-return-this.cpp
@@ -45,8 +45,8 @@ B::~B() { }
// CHECKIOS5-LABEL: define %class.B* @_ZN1BD2Ev(%class.B* %this)
// CHECKIOS5-LABEL: define %class.B* @_ZN1BD1Ev(%class.B* %this)
-// CHECKMS-LABEL: define x86_thiscallcc %class.B* @"\01??0B@@QAE@PAH@Z"(%class.B* returned %this, i32* %i)
-// CHECKMS-LABEL: define x86_thiscallcc void @"\01??1B@@UAE@XZ"(%class.B* %this)
+// CHECKMS-LABEL: define dso_local x86_thiscallcc %class.B* @"??0B@@QAE@PAH@Z"(%class.B* returned %this, i32* %i)
+// CHECKMS-LABEL: define dso_local x86_thiscallcc void @"??1B@@UAE@XZ"(%class.B* %this)
class C : public A, public B {
public:
@@ -83,8 +83,8 @@ C::~C() { }
// CHECKIOS5-LABEL: define void @_ZN1CD0Ev(%class.C* %this)
// CHECKIOS5-LABEL: define void @_ZThn8_N1CD0Ev(%class.C* %this)
-// CHECKMS-LABEL: define x86_thiscallcc %class.C* @"\01??0C@@QAE@PAHPAD@Z"(%class.C* returned %this, i32* %i, i8* %c)
-// CHECKMS-LABEL: define x86_thiscallcc void @"\01??1C@@UAE@XZ"(%class.C* %this)
+// CHECKMS-LABEL: define dso_local x86_thiscallcc %class.C* @"??0C@@QAE@PAHPAD@Z"(%class.C* returned %this, i32* %i, i8* %c)
+// CHECKMS-LABEL: define dso_local x86_thiscallcc void @"??1C@@UAE@XZ"(%class.C* %this)
class D : public virtual A {
public:
@@ -110,8 +110,8 @@ D::~D() { }
// CHECKIOS5-LABEL: define %class.D* @_ZN1DD2Ev(%class.D* %this, i8** %vtt)
// CHECKIOS5-LABEL: define %class.D* @_ZN1DD1Ev(%class.D* %this)
-// CHECKMS-LABEL: define x86_thiscallcc %class.D* @"\01??0D@@QAE@XZ"(%class.D* returned %this, i32 %is_most_derived)
-// CHECKMS-LABEL: define x86_thiscallcc void @"\01??1D@@UAE@XZ"(%class.D* %this)
+// CHECKMS-LABEL: define dso_local x86_thiscallcc %class.D* @"??0D@@QAE@XZ"(%class.D* returned %this, i32 %is_most_derived)
+// CHECKMS-LABEL: define dso_local x86_thiscallcc void @"??1D@@UAE@XZ"(%class.D* %this)
class E {
public:
diff --git a/test/CodeGenCXX/constructor-direct-call.cpp b/test/CodeGenCXX/constructor-direct-call.cpp
index 9567d0968dae..bcddc0fa7a49 100644
--- a/test/CodeGenCXX/constructor-direct-call.cpp
+++ b/test/CodeGenCXX/constructor-direct-call.cpp
@@ -9,7 +9,7 @@ void f1() {
Test1 var;
var.Test1::Test1();
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %{{.*}}, i8* %{{.*}}, i32 4, i32 4, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %{{.*}}, i8* align 4 %{{.*}}, i32 4, i1 false)
var.Test1::Test1(var);
}
@@ -28,7 +28,7 @@ void f2() {
// CHECK-NEXT: call x86_thiscallcc void @_ZN5Test2C1Ev(%class.Test2* %var)
var.Test2::Test2();
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %{{.*}}, i8* %{{.*}}, i32 8, i32 4, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %{{.*}}, i8* align 4 %{{.*}}, i32 8, i1 false)
var.Test2::Test2(var);
}
diff --git a/test/CodeGenCXX/constructors.cpp b/test/CodeGenCXX/constructors.cpp
index a89814038340..9322c410f272 100644
--- a/test/CodeGenCXX/constructors.cpp
+++ b/test/CodeGenCXX/constructors.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 %s -emit-llvm -o - | FileCheck %s --implicit-check-not=should_not_appear_in_output
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 %s -emit-llvm -o - | FileCheck %s --implicit-check-not=should_not_appear_in_output --check-prefixes=CHECK,NULL-INVALID
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 %s -emit-llvm -fno-delete-null-pointer-checks -o - | FileCheck %s --implicit-check-not=should_not_appear_in_output --check-prefixes=CHECK,NULL-VALID
struct Member { int x; Member(); Member(int); Member(const Member &); };
struct VBase { int x; VBase(); VBase(int); VBase(const VBase &); };
@@ -21,10 +22,12 @@ struct A {
A::A(struct Undeclared &ref) : mem(0) {}
// Check that delegation works.
-// CHECK-LABEL: define void @_ZN1AC2ER10Undeclared(%struct.A* %this, %struct.Undeclared* nonnull %ref) unnamed_addr
+// NULL-INVALID-LABEL: define void @_ZN1AC2ER10Undeclared(%struct.A* %this, %struct.Undeclared* nonnull %ref) unnamed_addr
+// NULL-VALID-LABEL: define void @_ZN1AC2ER10Undeclared(%struct.A* %this, %struct.Undeclared* %ref) unnamed_addr
// CHECK: call void @_ZN6MemberC1Ei(
-// CHECK-LABEL: define void @_ZN1AC1ER10Undeclared(%struct.A* %this, %struct.Undeclared* nonnull %ref) unnamed_addr
+// NULL-INVALID-LABEL: define void @_ZN1AC1ER10Undeclared(%struct.A* %this, %struct.Undeclared* nonnull %ref) unnamed_addr
+// NULL-VALID-LABEL: define void @_ZN1AC1ER10Undeclared(%struct.A* %this, %struct.Undeclared* %ref) unnamed_addr
// CHECK: call void @_ZN1AC2ER10Undeclared(
A::A(ValueClass v) : mem(v.y - v.x) {}
@@ -43,11 +46,13 @@ struct B : A {
B::B(struct Undeclared &ref) : A(ref), mem(1) {}
-// CHECK-LABEL: define void @_ZN1BC2ER10Undeclared(%struct.B* %this, %struct.Undeclared* nonnull %ref) unnamed_addr
+// NULL-INVALID-LABEL: define void @_ZN1BC2ER10Undeclared(%struct.B* %this, %struct.Undeclared* nonnull %ref) unnamed_addr
+// NULL-VALID-LABEL: define void @_ZN1BC2ER10Undeclared(%struct.B* %this, %struct.Undeclared* %ref) unnamed_addr
// CHECK: call void @_ZN1AC2ER10Undeclared(
// CHECK: call void @_ZN6MemberC1Ei(
-// CHECK-LABEL: define void @_ZN1BC1ER10Undeclared(%struct.B* %this, %struct.Undeclared* nonnull %ref) unnamed_addr
+// NULL-INVALID-LABEL: define void @_ZN1BC1ER10Undeclared(%struct.B* %this, %struct.Undeclared* nonnull %ref) unnamed_addr
+// NULL-VALID-LABEL: define void @_ZN1BC1ER10Undeclared(%struct.B* %this, %struct.Undeclared* %ref) unnamed_addr
// CHECK: call void @_ZN1BC2ER10Undeclared(
diff --git a/test/CodeGenCXX/copy-constructor-elim.cpp b/test/CodeGenCXX/copy-constructor-elim.cpp
index 4abe456e4b29..7ba231071e76 100644
--- a/test/CodeGenCXX/copy-constructor-elim.cpp
+++ b/test/CodeGenCXX/copy-constructor-elim.cpp
@@ -56,4 +56,4 @@ extern "C" V f() { return gv1; }
// Make sure that we obey the destination's alignment requirements when emitting
// the copy.
// CHECK-LABEL: define {{.*}} @f(
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}({{.*}}, i8* bitcast (%struct.V* @gv1 to i8*), {{i64|i32}} 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}({{.*}}align 4{{.*}}, i8* align 8 bitcast (%struct.V* @gv1 to i8*), {{i64|i32}} 4, i1 false)
diff --git a/test/CodeGenCXX/copy-constructor-synthesis-2.cpp b/test/CodeGenCXX/copy-constructor-synthesis-2.cpp
index 9d7e18e80f67..7940101c0cfb 100644
--- a/test/CodeGenCXX/copy-constructor-synthesis-2.cpp
+++ b/test/CodeGenCXX/copy-constructor-synthesis-2.cpp
@@ -10,15 +10,15 @@ extern PR23373 pr23373_a;
PR23373 pr23373_b(pr23373_a);
// CHECK-LABEL: define {{.*}} @__cxx_global_var_init(
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i32|i64}}({{.*}} @pr23373_b{{.*}}, {{.*}} @pr23373_a{{.*}}, [[W:i32|i64]] 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i32|i64}}({{.*}}align 4{{.*}}@pr23373_b{{.*}}, {{.*}}align 4{{.*}} @pr23373_a{{.*}}, [[W:i32|i64]] 4, i1 false)
PR23373 pr23373_f() { return pr23373_a; }
// CHECK-LABEL: define {{.*}} @_Z9pr23373_fv(
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.[[W]]({{.*}}, [[W]] 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.[[W]]({{.*}}align 4{{.*}}align 4{{.*}}, [[W]] 4, i1 false)
void pr23373_g(PR23373 &a, PR23373 &b) { a = b; }
// CHECK-LABEL: define {{.*}} @_Z9pr23373_g
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.[[W]]({{.*}}, [[W]] 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.[[W]]({{.*}}align 4{{.*}}align 4{{.*}}, [[W]] 4, i1 false)
struct A { virtual void a(); };
A x(A& y) { return y; }
diff --git a/test/CodeGenCXX/copy-constructor-synthesis.cpp b/test/CodeGenCXX/copy-constructor-synthesis.cpp
index 5a2cc1440f74..4fdd8a35c4de 100644
--- a/test/CodeGenCXX/copy-constructor-synthesis.cpp
+++ b/test/CodeGenCXX/copy-constructor-synthesis.cpp
@@ -143,7 +143,7 @@ void f(B b1) {
// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[A]], [[A]]* [[OTHER]], i32 0, i32 1
// CHECK-NEXT: [[T4:%.*]] = bitcast i16* [[T0]] to i8*
// CHECK-NEXT: [[T5:%.*]] = bitcast i16* [[T2]] to i8*
-// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T4]], i8* [[T5]], i64 8, i32 8, i1 false)
+// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[T4]], i8* align 8 [[T5]], i64 8, i1 false)
// CHECK-NEXT: ret [[A]]* [[THIS]]
// CHECK-LABEL: define linkonce_odr void @_ZN6PR66281BC2ERKS0_(%"struct.PR6628::B"* %this, %"struct.PR6628::B"* dereferenceable({{[0-9]+}})) unnamed_addr
@@ -172,7 +172,7 @@ void f(B b1) {
// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[A]], [[A]]* [[OTHER]], i32 0, i32 1
// CHECK-NEXT: [[T4:%.*]] = bitcast i16* [[T0]] to i8*
// CHECK-NEXT: [[T5:%.*]] = bitcast i16* [[T2]] to i8*
-// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T4]], i8* [[T5]], i64 8, i32 8, i1 false)
+// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[T4]], i8* align 8 [[T5]], i64 8, i1 false)
// CHECK-NEXT: ret void
}
diff --git a/test/CodeGenCXX/ctor-dtor-alias.cpp b/test/CodeGenCXX/ctor-dtor-alias.cpp
index 6826ee5796ca..4715111a1439 100644
--- a/test/CodeGenCXX/ctor-dtor-alias.cpp
+++ b/test/CodeGenCXX/ctor-dtor-alias.cpp
@@ -1,5 +1,7 @@
-// RUN: %clang_cc1 %s -triple i686-linux -emit-llvm -o - -mconstructor-aliases | FileCheck --check-prefix=NOOPT %s
-
+// RUN: %clang_cc1 %s -triple i686-linux -emit-llvm -o - -mconstructor-aliases > %t
+// RUN: FileCheck --check-prefix=NOOPT1 --input-file=%t %s
+// RUN: FileCheck --check-prefix=NOOPT2 --input-file=%t %s
+// RUN: FileCheck --check-prefix=NOOPT3 --input-file=%t %s
// RUN: %clang_cc1 %s -triple i686-linux -emit-llvm -o - -mconstructor-aliases -O1 -disable-llvm-passes > %t
// RUN: FileCheck --check-prefix=CHECK1 --input-file=%t %s
// RUN: FileCheck --check-prefix=CHECK2 --input-file=%t %s
@@ -11,16 +13,23 @@
// RUN: %clang_cc1 %s -triple i686-pc-windows-gnu -emit-llvm -o - -mconstructor-aliases -O1 -disable-llvm-passes | FileCheck --check-prefix=COFF %s
namespace test1 {
-// Test that we produce the apropriate comdats when creating aliases to
+// Test that we produce the appropriate comdats when creating aliases to
// weak_odr constructors and destructors.
-// CHECK1: @_ZN5test16foobarIvEC1Ev = weak_odr alias void {{.*}} @_ZN5test16foobarIvEC2Ev
-// CHECK1: @_ZN5test16foobarIvED1Ev = weak_odr alias void (%"struct.test1::foobar"*), void (%"struct.test1::foobar"*)* @_ZN5test16foobarIvED2Ev
+// CHECK1: @_ZN5test16foobarIvEC1Ev = weak_odr unnamed_addr alias void {{.*}} @_ZN5test16foobarIvEC2Ev
+// CHECK1: @_ZN5test16foobarIvED1Ev = weak_odr unnamed_addr alias void (%"struct.test1::foobar"*), void (%"struct.test1::foobar"*)* @_ZN5test16foobarIvED2Ev
// CHECK1: define weak_odr void @_ZN5test16foobarIvEC2Ev({{.*}} comdat($_ZN5test16foobarIvEC5Ev)
// CHECK1: define weak_odr void @_ZN5test16foobarIvED2Ev({{.*}} comdat($_ZN5test16foobarIvED5Ev)
// CHECK1: define weak_odr void @_ZN5test16foobarIvED0Ev({{.*}} comdat($_ZN5test16foobarIvED5Ev)
// CHECK1-NOT: comdat
+// This should happen regardless of the opt level.
+// NOOPT1: @_ZN5test16foobarIvEC1Ev = weak_odr unnamed_addr alias void {{.*}} @_ZN5test16foobarIvEC2Ev
+// NOOPT1: @_ZN5test16foobarIvED1Ev = weak_odr unnamed_addr alias void (%"struct.test1::foobar"*), void (%"struct.test1::foobar"*)* @_ZN5test16foobarIvED2Ev
+// NOOPT1: define weak_odr void @_ZN5test16foobarIvEC2Ev({{.*}} comdat($_ZN5test16foobarIvEC5Ev)
+// NOOPT1: define weak_odr void @_ZN5test16foobarIvED2Ev({{.*}} comdat($_ZN5test16foobarIvED5Ev)
+// NOOPT1: define weak_odr void @_ZN5test16foobarIvED0Ev({{.*}} comdat($_ZN5test16foobarIvED5Ev)
+
// COFF doesn't support comdats with arbitrary names (C5/D5).
// COFF: define weak_odr {{.*}} void @_ZN5test16foobarIvEC2Ev({{.*}} comdat align
// COFF: define weak_odr {{.*}} void @_ZN5test16foobarIvEC1Ev({{.*}} comdat align
@@ -37,12 +46,17 @@ template struct foobar<void>;
}
namespace test2 {
-// test that when the destrucor is linkonce_odr we just replace every use of
+// test that when the destructor is linkonce_odr we just replace every use of
// C1 with C2.
// CHECK1: define internal void @__cxx_global_var_init()
// CHECK1: call void @_ZN5test26foobarIvEC2Ev
// CHECK1: define linkonce_odr void @_ZN5test26foobarIvEC2Ev({{.*}} comdat align
+
+// At -O0, we should still emit the complete constructor.
+// NOOPT1: define internal void @__cxx_global_var_init()
+// NOOPT1: call void @_ZN5test26foobarIvEC1Ev
+// NOOPT1: define linkonce_odr void @_ZN5test26foobarIvEC1Ev({{.*}} comdat align
void g();
template <typename T> struct foobar {
foobar() { g(); }
@@ -57,6 +71,11 @@ namespace test3 {
// CHECK1: define internal void @__cxx_global_var_init.1()
// CHECK1: call i32 @__cxa_atexit{{.*}}_ZN5test312_GLOBAL__N_11AD2Ev
// CHECK1: define internal void @_ZN5test312_GLOBAL__N_11AD2Ev(
+
+// We can use an alias for internal symbols at -O0.
+// NOOPT2: _ZN5test312_GLOBAL__N_11BD1Ev = internal unnamed_addr alias void {{.*}} @_ZN5test312_GLOBAL__N_11BD2Ev
+// NOOPT2: define internal void @__cxx_global_var_init.1()
+// NOOPT2: call i32 @__cxa_atexit{{.*}}_ZN5test312_GLOBAL__N_11BD1Ev
namespace {
struct A {
~A() {}
@@ -77,11 +96,12 @@ namespace test4 {
// CHECK1: call i32 @__cxa_atexit{{.*}}_ZN5test41AD2Ev
// CHECK1: define linkonce_odr void @_ZN5test41AD2Ev({{.*}} comdat align
- // test that we don't do this optimization at -O0 so that the debugger can
- // see both destructors.
- // NOOPT: define internal void @__cxx_global_var_init.2()
- // NOOPT: call i32 @__cxa_atexit{{.*}}@_ZN5test41BD2Ev
- // NOOPT: define linkonce_odr void @_ZN5test41BD2Ev({{.*}} comdat align
+ // Test that we don't do this optimization at -O0 and call the complete
+ // destructor for B instead. This enables the debugger to see both
+ // destructors.
+ // NOOPT2: define internal void @__cxx_global_var_init.2()
+ // NOOPT2: call i32 @__cxa_atexit{{.*}}@_ZN5test41BD1Ev
+ // NOOPT2: define linkonce_odr void @_ZN5test41BD1Ev({{.*}} comdat align
struct A {
virtual ~A() {}
};
@@ -129,6 +149,11 @@ namespace test7 {
// out if we should).
// pr17875.
// CHECK3: define void @_ZN5test71BD2Ev
+
+ // At -O0, we should emit both destructors, the complete can be an alias to
+ // the base one.
+ // NOOPT3: @_ZN5test71BD1Ev = unnamed_addr alias void {{.*}} @_ZN5test71BD2Ev
+ // NOOPT3: define void @_ZN5test71BD2Ev
template <typename> struct A {
~A() {}
};
@@ -141,7 +166,7 @@ namespace test7 {
namespace test8 {
// Test that we replace ~zed with ~bar which is an alias to ~foo.
- // CHECK4: @_ZN5test83barD2Ev = alias {{.*}} @_ZN5test83fooD2Ev
+ // CHECK4: @_ZN5test83barD2Ev = unnamed_addr alias {{.*}} @_ZN5test83fooD2Ev
// CHECK4: define internal void @__cxx_global_var_init.5()
// CHECK4: call i32 @__cxa_atexit({{.*}}@_ZN5test83barD2Ev
struct foo {
@@ -232,8 +257,8 @@ struct foo : public bar {
~foo();
};
foo::~foo() {}
-// CHECK6: @_ZN6test113fooD2Ev = alias {{.*}} @_ZN6test113barD2Ev
-// CHECK6: @_ZN6test113fooD1Ev = alias {{.*}} @_ZN6test113fooD2Ev
+// CHECK6: @_ZN6test113fooD2Ev = unnamed_addr alias {{.*}} @_ZN6test113barD2Ev
+// CHECK6: @_ZN6test113fooD1Ev = unnamed_addr alias {{.*}} @_ZN6test113fooD2Ev
}
namespace test12 {
@@ -243,6 +268,6 @@ struct foo {
};
template class foo<1>;
-// CHECK6: @_ZN6test123fooILi1EED1Ev = weak_odr alias {{.*}} @_ZN6test123fooILi1EED2Ev
+// CHECK6: @_ZN6test123fooILi1EED1Ev = weak_odr unnamed_addr alias {{.*}} @_ZN6test123fooILi1EED2Ev
// CHECK6: define weak_odr void @_ZN6test123fooILi1EED2Ev({{.*}}) {{.*}} comdat($_ZN6test123fooILi1EED5Ev)
}
diff --git a/test/CodeGenCXX/cxx0x-delegating-ctors.cpp b/test/CodeGenCXX/cxx0x-delegating-ctors.cpp
index dcc055696e4d..614983d4fc59 100644
--- a/test/CodeGenCXX/cxx0x-delegating-ctors.cpp
+++ b/test/CodeGenCXX/cxx0x-delegating-ctors.cpp
@@ -66,7 +66,7 @@ namespace PR12890 {
X::X(int) : X() {}
}
// CHECK: define {{.*}} @_ZN7PR128901XC1Ei(%"class.PR12890::X"* %this, i32)
-// CHECK: call void @llvm.memset.p0i8.{{i32|i64}}(i8* {{.*}}, i8 0, {{i32|i64}} 4, i32 4, i1 false)
+// CHECK: call void @llvm.memset.p0i8.{{i32|i64}}(i8* align 4 {{.*}}, i8 0, {{i32|i64}} 4, i1 false)
namespace PR14588 {
void other();
diff --git a/test/CodeGenCXX/cxx0x-initializer-array.cpp b/test/CodeGenCXX/cxx0x-initializer-array.cpp
index de10aee67f13..4a7e452304cc 100644
--- a/test/CodeGenCXX/cxx0x-initializer-array.cpp
+++ b/test/CodeGenCXX/cxx0x-initializer-array.cpp
@@ -39,7 +39,7 @@ namespace ValueInitArrayOfMemPtr {
// CHECK: store i32 -1,
Agg2 b = { n };
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %{{.*}}, i8* bitcast ([3 x i32]* @[[THREE_NULL_MEMPTRS]] to i8*), i32 12, i32 4, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %{{.*}}, i8* align 4 bitcast ([3 x i32]* @[[THREE_NULL_MEMPTRS]] to i8*), i32 12, i1 false)
}
// Test dynamic initialization.
diff --git a/test/CodeGenCXX/cxx0x-initializer-references.cpp b/test/CodeGenCXX/cxx0x-initializer-references.cpp
index 318c8ea0d770..595d27ca2e83 100644
--- a/test/CodeGenCXX/cxx0x-initializer-references.cpp
+++ b/test/CodeGenCXX/cxx0x-initializer-references.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 -S -triple armv7-none-eabi -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -S -triple armv7-none-eabi -fmerge-all-constants -emit-llvm -o - %s | FileCheck %s
namespace reference {
struct A {
diff --git a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
index 67215ef48fb3..e3c7e26afa81 100644
--- a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
+++ b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-none-linux-gnu -emit-llvm -o - %s | FileCheck -check-prefixes=X86,CHECK %s
-// RUN: %clang_cc1 -std=c++11 -triple amdgcn-amd-amdhsa-amdgiz -DNO_TLS -emit-llvm -o - %s | FileCheck -check-prefixes=AMD,CHECK %s
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-none-linux-gnu -fmerge-all-constants -emit-llvm -o - %s | FileCheck -check-prefixes=X86,CHECK %s
+// RUN: %clang_cc1 -std=c++11 -triple amdgcn-amd-amdhsa -DNO_TLS -fmerge-all-constants -emit-llvm -o - %s | FileCheck -check-prefixes=AMDGCN,CHECK %s
namespace std {
typedef decltype(sizeof(int)) size_t;
@@ -49,8 +49,8 @@ struct wantslist1 {
};
// X86: @_ZGR15globalInitList1_ = internal constant [3 x i32] [i32 1, i32 2, i32 3]
// X86: @globalInitList1 = global %{{[^ ]+}} { i32* getelementptr inbounds ([3 x i32], [3 x i32]* @_ZGR15globalInitList1_, i32 0, i32 0), i{{32|64}} 3 }
-// AMD: @_ZGR15globalInitList1_ = internal addrspace(1) constant [3 x i32] [i32 1, i32 2, i32 3]
-// AMD: @globalInitList1 = addrspace(1) global %{{[^ ]+}} { i32* addrspacecast (i32 addrspace(1)* getelementptr inbounds ([3 x i32], [3 x i32] addrspace(1)* @_ZGR15globalInitList1_, i32 0, i32 0) to i32*), i{{32|64}} 3 }
+// AMDGCN: @_ZGR15globalInitList1_ = internal addrspace(1) constant [3 x i32] [i32 1, i32 2, i32 3]
+// AMDGCN: @globalInitList1 = addrspace(1) global %{{[^ ]+}} { i32* addrspacecast (i32 addrspace(1)* getelementptr inbounds ([3 x i32], [3 x i32] addrspace(1)* @_ZGR15globalInitList1_, i32 0, i32 0) to i32*), i{{32|64}} 3 }
std::initializer_list<int> globalInitList1 = {1, 2, 3};
#ifndef NO_TLS
@@ -67,28 +67,28 @@ std::initializer_list<int> thread_local x = {1, 2, 3, 4};
// X86: @globalInitList2 = global %{{[^ ]+}} zeroinitializer
// X86: @_ZGR15globalInitList2_ = internal global [2 x %[[WITHARG:[^ ]*]]] zeroinitializer
-// AMD: @globalInitList2 = addrspace(1) global %{{[^ ]+}} zeroinitializer
-// AMD: @_ZGR15globalInitList2_ = internal addrspace(1) global [2 x %[[WITHARG:[^ ]*]]] zeroinitializer
+// AMDGCN: @globalInitList2 = addrspace(1) global %{{[^ ]+}} zeroinitializer
+// AMDGCN: @_ZGR15globalInitList2_ = internal addrspace(1) global [2 x %[[WITHARG:[^ ]*]]] zeroinitializer
// X86: @_ZN15partly_constant1kE = global i32 0, align 4
// X86: @_ZN15partly_constant2ilE = global {{.*}} null, align 8
-// X86: @[[PARTLY_CONSTANT_OUTER:_ZGRN15partly_constant2ilE.*]] = internal global {{.*}} zeroinitializer, align 8
-// X86: @[[PARTLY_CONSTANT_INNER:_ZGRN15partly_constant2ilE.*]] = internal global [3 x {{.*}}] zeroinitializer, align 8
-// X86: @[[PARTLY_CONSTANT_FIRST:_ZGRN15partly_constant2ilE.*]] = internal constant [3 x i32] [i32 1, i32 2, i32 3], align 4
-// X86: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE.*]] = internal global [2 x i32] zeroinitializer, align 4
-// X86: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE.*]] = internal constant [4 x i32] [i32 5, i32 6, i32 7, i32 8], align 4
-// AMD: @_ZN15partly_constant1kE = addrspace(1) global i32 0, align 4
-// AMD: @_ZN15partly_constant2ilE = addrspace(2) global {{.*}} null, align 8
-// AMD: @[[PARTLY_CONSTANT_OUTER:_ZGRN15partly_constant2ilE.*]] = internal addrspace(2) global {{.*}} zeroinitializer, align 8
-// AMD: @[[PARTLY_CONSTANT_INNER:_ZGRN15partly_constant2ilE.*]] = internal addrspace(2) global [3 x {{.*}}] zeroinitializer, align 8
-// AMD: @[[PARTLY_CONSTANT_FIRST:_ZGRN15partly_constant2ilE.*]] = internal addrspace(2) constant [3 x i32] [i32 1, i32 2, i32 3], align 4
-// AMD: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE.*]] = internal addrspace(2) global [2 x i32] zeroinitializer, align 4
-// AMD: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE.*]] = internal addrspace(2) constant [4 x i32] [i32 5, i32 6, i32 7, i32 8], align 4
+// X86: @[[PARTLY_CONSTANT_OUTER:_ZGRN15partly_constant2ilE_]] = internal global {{.*}} zeroinitializer, align 8
+// X86: @[[PARTLY_CONSTANT_INNER:_ZGRN15partly_constant2ilE0_]] = internal global [3 x {{.*}}] zeroinitializer, align 8
+// X86: @[[PARTLY_CONSTANT_FIRST:_ZGRN15partly_constant2ilE1_]] = internal constant [3 x i32] [i32 1, i32 2, i32 3], align 4
+// X86: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE2_]] = internal global [2 x i32] zeroinitializer, align 4
+// X86: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE3_]] = internal constant [4 x i32] [i32 5, i32 6, i32 7, i32 8], align 4
+// AMDGCN: @_ZN15partly_constant1kE = addrspace(1) global i32 0, align 4
+// AMDGCN: @_ZN15partly_constant2ilE = addrspace(4) global {{.*}} null, align 8
+// AMDGCN: @[[PARTLY_CONSTANT_OUTER:_ZGRN15partly_constant2ilE_]] = internal addrspace(4) global {{.*}} zeroinitializer, align 8
+// AMDGCN: @[[PARTLY_CONSTANT_INNER:_ZGRN15partly_constant2ilE0_]] = internal addrspace(4) global [3 x {{.*}}] zeroinitializer, align 8
+// AMDGCN: @[[PARTLY_CONSTANT_FIRST:_ZGRN15partly_constant2ilE1_]] = internal addrspace(4) constant [3 x i32] [i32 1, i32 2, i32 3], align 4
+// AMDGCN: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE2_]] = internal addrspace(4) global [2 x i32] zeroinitializer, align 4
+// AMDGCN: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE3_]] = internal addrspace(4) constant [4 x i32] [i32 5, i32 6, i32 7, i32 8], align 4
// X86: @[[REFTMP1:.*]] = private constant [2 x i32] [i32 42, i32 43], align 4
// X86: @[[REFTMP2:.*]] = private constant [3 x %{{.*}}] [%{{.*}} { i32 1 }, %{{.*}} { i32 2 }, %{{.*}} { i32 3 }], align 4
-// AMD: @[[REFTMP1:.*]] = private addrspace(2) constant [2 x i32] [i32 42, i32 43], align 4
-// AMD: @[[REFTMP2:.*]] = private addrspace(2) constant [3 x %{{.*}}] [%{{.*}} { i32 1 }, %{{.*}} { i32 2 }, %{{.*}} { i32 3 }], align 4
+// AMDGCN: @[[REFTMP1:.*]] = private addrspace(4) constant [2 x i32] [i32 42, i32 43], align 4
+// AMDGCN: @[[REFTMP2:.*]] = private addrspace(4) constant [3 x %{{.*}}] [%{{.*}} { i32 1 }, %{{.*}} { i32 2 }, %{{.*}} { i32 3 }], align 4
// CHECK: appending global
@@ -101,15 +101,15 @@ std::initializer_list<int> thread_local x = {1, 2, 3, 4};
// CHECK-LABEL: define internal void @__cxx_global_var_init
// X86: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]], [2 x %[[WITHARG]]]* @_ZGR15globalInitList2_, i{{32|64}} 0, i{{32|64}} 0
// X86: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]], [2 x %[[WITHARG]]]* @_ZGR15globalInitList2_, i{{32|64}} 0, i{{32|64}} 1
-// AMD: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]], [2 x %[[WITHARG]]]* addrspacecast ({{[^@]+}} @_ZGR15globalInitList2_ {{[^)]+}}), i{{32|64}} 0, i{{32|64}} 0
-// AMD: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]], [2 x %[[WITHARG]]]* addrspacecast ({{[^@]+}} @_ZGR15globalInitList2_ {{[^)]+}}), i{{32|64}} 0, i{{32|64}} 1
+// AMDGCN: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]], [2 x %[[WITHARG]]]* addrspacecast ({{[^@]+}} @_ZGR15globalInitList2_ {{[^)]+}}), i{{32|64}} 0, i{{32|64}} 0
+// AMDGCN: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]], [2 x %[[WITHARG]]]* addrspacecast ({{[^@]+}} @_ZGR15globalInitList2_ {{[^)]+}}), i{{32|64}} 0, i{{32|64}} 1
// CHECK: call i32 @__cxa_atexit
// X86: store %[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]], [2 x %[[WITHARG]]]* @_ZGR15globalInitList2_, i64 0, i64 0),
// X86: %[[WITHARG]]** getelementptr inbounds (%{{.*}}, %{{.*}}* @globalInitList2, i32 0, i32 0), align 8
// X86: store i64 2, i64* getelementptr inbounds (%{{.*}}, %{{.*}}* @globalInitList2, i32 0, i32 1), align 8
-// AMD: store %[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]], [2 x %[[WITHARG]]]* addrspacecast ({{[^@]+}} @_ZGR15globalInitList2_ {{[^)]+}}), i64 0, i64 0),
-// AMD: %[[WITHARG]]** getelementptr inbounds (%{{.*}}, %{{.*}}* addrspacecast ({{[^@]+}} @globalInitList2 {{[^)]+}}), i32 0, i32 0), align 8
-// AMD: store i64 2, i64* getelementptr inbounds (%{{.*}}, %{{.*}}* addrspacecast ({{[^@]+}} @globalInitList2 {{[^)]+}}), i32 0, i32 1), align 8
+// AMDGCN: store %[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]], [2 x %[[WITHARG]]]* addrspacecast ({{[^@]+}} @_ZGR15globalInitList2_ {{[^)]+}}), i64 0, i64 0),
+// AMDGCN: %[[WITHARG]]** getelementptr inbounds (%{{.*}}, %{{.*}}* addrspacecast ({{[^@]+}} @globalInitList2 {{[^)]+}}), i32 0, i32 0), align 8
+// AMDGCN: store i64 2, i64* getelementptr inbounds (%{{.*}}, %{{.*}}* addrspacecast ({{[^@]+}} @globalInitList2 {{[^)]+}}), i32 0, i32 1), align 8
// CHECK: call void @_ZN10destroyme1D1Ev
// CHECK-NEXT: call void @_ZN10destroyme1D1Ev
// CHECK-NEXT: ret void
@@ -121,8 +121,8 @@ void fn1(int i) {
// CHECK-LABEL: define void @_Z3fn1i
// temporary array
// X86: [[array:%[^ ]+]] = alloca [3 x i32]
- // AMD: [[alloca:%[^ ]+]] = alloca [3 x i32], align 4, addrspace(5)
- // AMD: [[array:%[^ ]+]] = addrspacecast [3 x i32] addrspace(5)* [[alloca]] to [3 x i32]*
+ // AMDGCN: [[alloca:%[^ ]+]] = alloca [3 x i32], align 4, addrspace(5)
+ // AMDGCN: [[array:%[^ ]+]] = addrspacecast [3 x i32] addrspace(5)* [[alloca]] to [3 x i32]*
// CHECK: getelementptr inbounds [3 x i32], [3 x i32]* [[array]], i{{32|64}} 0
// CHECK-NEXT: store i32 1, i32*
// CHECK-NEXT: getelementptr
@@ -236,36 +236,6 @@ void fn9() {
// CHECK: ret void
}
-struct haslist1 {
- std::initializer_list<int> il;
- haslist1(int i);
-};
-
-// CHECK-LABEL: define void @_ZN8haslist1C2Ei
-haslist1::haslist1(int i)
-// CHECK: alloca [3 x i32]
-// CHECK: store i32 %
-// CHECK: store i32 2
-// CHECK: store i32 3
- : il{i, 2, 3}
-{
- destroyme2 dm2;
-}
-
-struct haslist2 {
- std::initializer_list<destroyme1> il;
- haslist2();
-};
-
-// CHECK-LABEL: define void @_ZN8haslist2C2Ev
-haslist2::haslist2()
- : il{destroyme1(), destroyme1()}
-{
- destroyme2 dm2;
- // CHECK: call void @_ZN10destroyme2D1Ev
- // CHECK: call void @_ZN10destroyme1D1Ev
-}
-
void fn10(int i) {
// CHECK-LABEL: define void @_Z4fn10i
// CHECK: alloca [3 x i32]
@@ -405,7 +375,7 @@ namespace partly_constant {
// CHECK-NOT: @[[PARTLY_CONSTANT_THIRD]],
// CHECK: store i32* getelementptr inbounds ({{.*}}, {{.*}}* {{.*}}@[[PARTLY_CONSTANT_THIRD]]{{.*}}, i64 0, i64 0),
// CHECK: i32** getelementptr inbounds ({{.*}}, {{.*}}* {{.*}}@[[PARTLY_CONSTANT_INNER]]{{.*}}, i64 0, i64 2, i32 0)
- // CHECK: store i64 4, i64* getelementptr inbounds ({{.*}}, {{.*}}* {{.*}}@_ZGRN15partly_constant2ilE4_{{.*}}, i64 0, i64 2, i32 1)
+ // CHECK: store i64 4, i64* getelementptr inbounds ({{.*}}, {{.*}}* {{.*}}@[[PARTLY_CONSTANT_INNER]]{{.*}}, i64 0, i64 2, i32 1)
// CHECK-NOT: @[[PARTLY_CONSTANT_THIRD]],
//
// Outer init list.
@@ -518,12 +488,12 @@ namespace B19773010 {
// CHECK-LABEL: @_ZN9B197730102f1Ev
testcase a{{"", ENUM_CONSTANT}};
// X86: store %"struct.B19773010::pair"* getelementptr inbounds ([1 x %"struct.B19773010::pair"], [1 x %"struct.B19773010::pair"]* bitcast ([1 x { i8*, i32 }]* @.ref.tmp{{.*}} to [1 x %"struct.B19773010::pair"]*), i64 0, i64 0), %"struct.B19773010::pair"** %{{.*}}, align 8
- // AMD: store %"struct.B19773010::pair"* getelementptr inbounds ([1 x %"struct.B19773010::pair"], [1 x %"struct.B19773010::pair"]* addrspacecast{{.*}} bitcast ([1 x { i8*, i32 }] addrspace(2)* @.ref.tmp{{.*}} to [1 x %"struct.B19773010::pair"] addrspace(2)*){{.*}}, i64 0, i64 0), %"struct.B19773010::pair"** %{{.*}}, align 8
+ // AMDGCN: store %"struct.B19773010::pair"* getelementptr inbounds ([1 x %"struct.B19773010::pair"], [1 x %"struct.B19773010::pair"]* addrspacecast{{.*}} bitcast ([1 x { i8*, i32 }] addrspace(4)* @.ref.tmp{{.*}} to [1 x %"struct.B19773010::pair"] addrspace(4)*){{.*}}, i64 0, i64 0), %"struct.B19773010::pair"** %{{.*}}, align 8
}
void f2() {
// CHECK-LABEL: @_ZN9B197730102f2Ev
// X86: store %"struct.B19773010::pair"* getelementptr inbounds ([1 x %"struct.B19773010::pair"], [1 x %"struct.B19773010::pair"]* bitcast ([1 x { i8*, i32 }]* @_ZGRZN9B197730102f2EvE1p_ to [1 x %"struct.B19773010::pair"]*), i64 0, i64 0), %"struct.B19773010::pair"** getelementptr inbounds ([2 x %"class.std::initializer_list.10"], [2 x %"class.std::initializer_list.10"]* @_ZZN9B197730102f2EvE1p, i64 0, i64 1, i32 0), align 16
- // AMD: store %"struct.B19773010::pair"* getelementptr inbounds ([1 x %"struct.B19773010::pair"], [1 x %"struct.B19773010::pair"]* addrspacecast{{.*}} bitcast ([1 x { i8*, i32 }] addrspace(1)* @_ZGRZN9B197730102f2EvE1p_ to [1 x %"struct.B19773010::pair"] addrspace(1)*){{.*}}, i64 0, i64 0), %"struct.B19773010::pair"** getelementptr inbounds ([2 x %"class.std::initializer_list.10"], [2 x %"class.std::initializer_list.10"]* addrspacecast{{.*}}@_ZZN9B197730102f2EvE1p{{.*}}, i64 0, i64 1, i32 0), align 8
+ // AMDGCN: store %"struct.B19773010::pair"* getelementptr inbounds ([1 x %"struct.B19773010::pair"], [1 x %"struct.B19773010::pair"]* addrspacecast{{.*}} bitcast ([1 x { i8*, i32 }] addrspace(1)* @_ZGRZN9B197730102f2EvE1p_ to [1 x %"struct.B19773010::pair"] addrspace(1)*){{.*}}, i64 0, i64 0), %"struct.B19773010::pair"** getelementptr inbounds ([2 x %"class.std::initializer_list.10"], [2 x %"class.std::initializer_list.10"]* addrspacecast{{.*}}@_ZZN9B197730102f2EvE1p{{.*}}, i64 0, i64 1, i32 0), align 8
static std::initializer_list<pair<const char *, E>> a, p[2] =
{a, {{"", ENUM_CONSTANT}}};
}
diff --git a/test/CodeGenCXX/cxx11-initializer-aggregate.cpp b/test/CodeGenCXX/cxx11-initializer-aggregate.cpp
index 8bf35966f5b9..325607f69fb5 100644
--- a/test/CodeGenCXX/cxx11-initializer-aggregate.cpp
+++ b/test/CodeGenCXX/cxx11-initializer-aggregate.cpp
@@ -11,6 +11,42 @@ namespace NonAggregateCopyInAggregateInit { // PR32044
struct C { A &&p; } c{{1}};
}
+namespace NearlyZeroInit {
+ // CHECK-DAG: @_ZN14NearlyZeroInit1aE = global {{.*}} <{ i32 1, i32 2, i32 3, [120 x i32] zeroinitializer }>
+ int a[123] = {1, 2, 3};
+ // CHECK-DAG: @_ZN14NearlyZeroInit1bE = global {{.*}} { i32 1, <{ i32, [2147483647 x i32] }> <{ i32 2, [2147483647 x i32] zeroinitializer }> }
+ struct B { int n; int arr[1024 * 1024 * 1024 * 2u]; } b = {1, {2}};
+}
+
+namespace PR37560 {
+ union U {
+ char x;
+ int a;
+ };
+ // FIXME: [dcl.init]p2, the padding bits of the union object should be
+ // initialized to 0, not undef, which would allow us to collapse the tail
+ // of these arrays to zeroinitializer.
+ // CHECK-DAG: @_ZN7PR375601cE = global <{ { i8, [3 x i8] } }> <{ { i8, [3 x i8] } { i8 0, [3 x i8] undef } }>
+ U c[1] = {};
+ // CHECK-DAG: @_ZN7PR375601dE = global {{.*}} <{ { i8, [3 x i8] } { i8 97, [3 x i8] undef }, %"{{[^"]*}}" { i32 123 }, { i8, [3 x i8] } { i8 98, [3 x i8] undef }, { i8, [3 x i8] } { i8 0, [3 x i8] undef },
+ U d[16] = {'a', {.a = 123}, 'b'};
+ // CHECK-DAG: @_ZN7PR375601eE = global {{.*}} <{ %"{{[^"]*}}" { i32 123 }, %"{{[^"]*}}" { i32 456 }, { i8, [3 x i8] } { i8 0, [3 x i8] undef },
+ U e[16] = {{.a = 123}, {.a = 456}};
+
+ union V {
+ int a;
+ char x;
+ };
+ // CHECK-DAG: @_ZN7PR375601fE = global [1 x %"{{[^"]*}}"] zeroinitializer
+ V f[1] = {};
+ // CHECK-DAG: @_ZN7PR375601gE = global {{.*}} <{ { i8, [3 x i8] } { i8 97, [3 x i8] undef }, %"{{[^"]*}}" { i32 123 }, { i8, [3 x i8] } { i8 98, [3 x i8] undef }, [13 x %"{{[^"]*}}"] zeroinitializer }>
+ V g[16] = {{.x = 'a'}, {.a = 123}, {.x = 'b'}};
+ // CHECK-DAG: @_ZN7PR375601hE = global {{.*}} <{ %"{{[^"]*}}" { i32 123 }, %"{{[^"]*}}" { i32 456 }, [14 x %"{{[^"]*}}"] zeroinitializer }>
+ V h[16] = {{.a = 123}, {.a = 456}};
+ // CHECK-DAG: @_ZN7PR375601iE = global [4 x %"{{[^"]*}}"] [%"{{[^"]*}}" { i32 123 }, %"{{[^"]*}}" { i32 456 }, %"{{[^"]*}}" zeroinitializer, %"{{[^"]*}}" zeroinitializer]
+ V i[4] = {{.a = 123}, {.a = 456}};
+}
+
// CHECK-LABEL: define {{.*}}@_Z3fn1i(
int fn1(int x) {
// CHECK: %[[INITLIST:.*]] = alloca %struct.A
@@ -51,3 +87,35 @@ namespace NonTrivialInit {
// meaningful.
B b[30] = {};
}
+
+namespace ZeroInit {
+ enum { Zero, One };
+ constexpr int zero() { return 0; }
+ constexpr int *null() { return nullptr; }
+ struct Filler {
+ int x;
+ Filler();
+ };
+ struct S1 {
+ int x;
+ };
+
+ // These declarations, if implemented elementwise, require huge
+ // amout of memory and compiler time.
+ unsigned char data_1[1024 * 1024 * 1024 * 2u] = { 0 };
+ unsigned char data_2[1024 * 1024 * 1024 * 2u] = { Zero };
+ unsigned char data_3[1024][1024][1024] = {{{0}}};
+ unsigned char data_4[1024 * 1024 * 1024 * 2u] = { zero() };
+ int *data_5[1024 * 1024 * 512] = { nullptr };
+ int *data_6[1024 * 1024 * 512] = { null() };
+ struct S1 data_7[1024 * 1024 * 512] = {{0}};
+ char data_8[1000 * 1000 * 1000] = {};
+ int (&&data_9)[1000 * 1000 * 1000] = {0};
+ unsigned char data_10[1024 * 1024 * 1024 * 2u] = { 1 };
+ unsigned char data_11[1024 * 1024 * 1024 * 2u] = { One };
+ unsigned char data_12[1024][1024][1024] = {{{1}}};
+
+ // This variable must be initialized elementwise.
+ Filler data_e1[1024] = {};
+ // CHECK: getelementptr inbounds {{.*}} @_ZN8ZeroInit7data_e1E
+}
diff --git a/test/CodeGenCXX/cxx11-initializer-array-new.cpp b/test/CodeGenCXX/cxx11-initializer-array-new.cpp
index 59f96031fc40..6e242124fea0 100644
--- a/test/CodeGenCXX/cxx11-initializer-array-new.cpp
+++ b/test/CodeGenCXX/cxx11-initializer-array-new.cpp
@@ -154,7 +154,7 @@ void *r = new T[n][3]{ { 1, 2, 3 }, { 4, 5, 6 } };
//
// CHECK: %[[SIZE:.*]] = sub i64 %{{.*}}, 24
// CHECK: %[[REST:.*]] = bitcast %[[T]]* %[[T_2_AS_T]] to i8*
-// CHECK: call void @llvm.memset.p0i8.i64(i8* %[[REST]], i8 0, i64 %[[SIZE]], i32 4, i1 false)
+// CHECK: call void @llvm.memset.p0i8.i64(i8* align 4 %[[REST]], i8 0, i64 %[[SIZE]], i1 false)
//
// CHECK: }
diff --git a/test/CodeGenCXX/cxx11-thread-local.cpp b/test/CodeGenCXX/cxx11-thread-local.cpp
index 3231a76ba920..70f5a47fd3b8 100644
--- a/test/CodeGenCXX/cxx11-thread-local.cpp
+++ b/test/CodeGenCXX/cxx11-thread-local.cpp
@@ -166,7 +166,8 @@ int f() {
// DARWIN: call cxx_fast_tlscc void @_ZTHN1XIiE1mE()
// CHECK: ret {{.*}}* @_ZN1XIiE1mE
-// CHECK: define internal {{.*}} @[[VF_M_INIT]]()
+// LINUX: define internal void @[[VF_M_INIT]]()
+// DARWIN: define internal cxx_fast_tlscc void @[[VF_M_INIT]]()
// LINUX-SAME: comdat($_ZN1VIfE1mE)
// DARWIN-NOT: comdat
// CHECK: load i8, i8* bitcast (i64* @_ZGVN1VIfE1mE to i8*)
@@ -178,7 +179,8 @@ int f() {
// CHECK: store i64 1, i64* @_ZGVN1VIfE1mE
// CHECK: br label
-// CHECK: define internal {{.*}} @[[XF_M_INIT]]()
+// LINUX: define internal void @[[XF_M_INIT]]()
+// DARWIN: define internal cxx_fast_tlscc void @[[XF_M_INIT]]()
// LINUX-SAME: comdat($_ZN1XIfE1mE)
// DARWIN-NOT: comdat
// CHECK: load i8, i8* bitcast (i64* @_ZGVN1XIfE1mE to i8*)
@@ -268,7 +270,8 @@ void set_anon_i() {
// LINUX-LABEL: define internal i32* @_ZTWN12_GLOBAL__N_16anon_iE()
// DARWIN-LABEL: define internal cxx_fast_tlscc i32* @_ZTWN12_GLOBAL__N_16anon_iE()
-// CHECK: define internal {{.*}} @[[V_M_INIT]]()
+// LINUX: define internal void @[[V_M_INIT]]()
+// DARWIN: define internal cxx_fast_tlscc void @[[V_M_INIT]]()
// LINUX-SAME: comdat($_ZN1VIiE1mE)
// DARWIN-NOT: comdat
// CHECK: load i8, i8* bitcast (i64* @_ZGVN1VIiE1mE to i8*)
@@ -280,7 +283,8 @@ void set_anon_i() {
// CHECK: store i64 1, i64* @_ZGVN1VIiE1mE
// CHECK: br label
-// CHECK: define internal {{.*}} @[[X_M_INIT]]()
+// LINUX: define internal void @[[X_M_INIT]]()
+// DARWIN: define internal cxx_fast_tlscc void @[[X_M_INIT]]()
// LINUX-SAME: comdat($_ZN1XIiE1mE)
// DARWIN-NOT: comdat
// CHECK: load i8, i8* bitcast (i64* @_ZGVN1XIiE1mE to i8*)
diff --git a/test/CodeGenCXX/cxx1z-aligned-allocation.cpp b/test/CodeGenCXX/cxx1z-aligned-allocation.cpp
index 4c579978cb96..2e2bfc5b941b 100644
--- a/test/CodeGenCXX/cxx1z-aligned-allocation.cpp
+++ b/test/CodeGenCXX/cxx1z-aligned-allocation.cpp
@@ -29,10 +29,10 @@ struct OVERALIGNED A { A(); int n[128]; };
// CHECK-LABEL: define {{.*}} @_Z2a0v()
// CHECK: %[[ALLOC:.*]] = call i8* @_ZnwmSt11align_val_t(i64 512, i64 32)
// CHECK: call void @_ZdlPvSt11align_val_t(i8* %[[ALLOC]], i64 32)
-// CHECK-MS-LABEL: define {{.*}} @"\01?a0@@YAPEAXXZ"()
-// CHECK-MS: %[[ALLOC:.*]] = call i8* @"\01??2@YAPEAX_KW4align_val_t@std@@@Z"(i64 512, i64 32)
+// CHECK-MS-LABEL: define {{.*}} @"?a0@@YAPEAXXZ"()
+// CHECK-MS: %[[ALLOC:.*]] = call i8* @"??2@YAPEAX_KW4align_val_t@std@@@Z"(i64 512, i64 32)
// CHECK-MS: cleanuppad
-// CHECK-MS: call void @"\01??3@YAXPEAXW4align_val_t@std@@@Z"(i8* %[[ALLOC]], i64 32)
+// CHECK-MS: call void @"??3@YAXPEAXW4align_val_t@std@@@Z"(i8* %[[ALLOC]], i64 32)
void *a0() { return new A; }
// FIXME: Why don't we call the sized array deallocation overload in this case?
@@ -44,13 +44,13 @@ void *a0() { return new A; }
// CHECK-NOT: store
// CHECK: invoke void @_ZN1AC1Ev(
// CHECK: call void @_ZdaPvSt11align_val_t(i8* %[[ALLOC]], i64 32)
-// CHECK-MS-LABEL: define {{.*}} @"\01?a1@@YAPEAXJ@Z"(
-// CHECK-MS: %[[ALLOC:.*]] = call i8* @"\01??_U@YAPEAX_KW4align_val_t@std@@@Z"(i64 %{{.*}}, i64 32)
+// CHECK-MS-LABEL: define {{.*}} @"?a1@@YAPEAXJ@Z"(
+// CHECK-MS: %[[ALLOC:.*]] = call i8* @"??_U@YAPEAX_KW4align_val_t@std@@@Z"(i64 %{{.*}}, i64 32)
// No array cookie.
// CHECK-MS-NOT: store
-// CHECK-MS: invoke %struct.A* @"\01??0A@@QEAA@XZ"(
+// CHECK-MS: invoke %struct.A* @"??0A@@QEAA@XZ"(
// CHECK-MS: cleanuppad
-// CHECK-MS: call void @"\01??_V@YAXPEAXW4align_val_t@std@@@Z"(i8* %[[ALLOC]], i64 32)
+// CHECK-MS: call void @"??_V@YAXPEAXW4align_val_t@std@@@Z"(i8* %[[ALLOC]], i64 32)
void *a1(long n) { return new A[n]; }
// CHECK-LABEL: define {{.*}} @_Z2a2P1A(
diff --git a/test/CodeGenCXX/cxx1z-eval-order.cpp b/test/CodeGenCXX/cxx1z-eval-order.cpp
index 1106719a4748..04c1b50f497e 100644
--- a/test/CodeGenCXX/cxx1z-eval-order.cpp
+++ b/test/CodeGenCXX/cxx1z-eval-order.cpp
@@ -56,13 +56,13 @@ void (*get_f())(A);
void postfix_before_args() {
// CHECK: call {{.*}}@{{.*}}get_f{{.*}}(
// CHECK-ITANIUM: call {{.*}}@_ZN1AC1Ev(
- // CHECK-WINDOWS: call {{.*}}@"\01??0A@@Q{{AE|EAA}}@XZ"(
+ // CHECK-WINDOWS: call {{.*}}@"??0A@@Q{{AE|EAA}}@XZ"(
// CHECK: call {{.*}}%{{.*}}(
get_f()(A{});
// CHECK: call {{.*}}@{{.*}}side_effect{{.*}}(
// CHECK-ITANIUM: call {{.*}}@_ZN1AC1Ev(
- // CHECK-WINDOWS: call {{.*}}@"\01??0A@@Q{{AE|EAA}}@XZ"(
+ // CHECK-WINDOWS: call {{.*}}@"??0A@@Q{{AE|EAA}}@XZ"(
// CHECK: call {{.*}}@{{.*}}callee{{.*}}(
(side_effect(), callee)(A{});
// CHECK: }
@@ -126,7 +126,7 @@ void *operator new(decltype(sizeof(0)), C);
void alloc_before_init() {
struct Q { Q(A) {} };
// CHECK-ITANIUM: call {{.*}}@_Znw{{.*}}(
- // CHECK-WINDOWS: call {{.*}}@"\01??2@YAP{{EAX_K|AXI}}@Z"(
+ // CHECK-WINDOWS: call {{.*}}@"??2@YAP{{EAX_K|AXI}}@Z"(
// CHECK: call {{.*}}@{{.*}}make_a{{.*}}(
delete new Q(make_a());
diff --git a/test/CodeGenCXX/cxx1z-initializer-aggregate.cpp b/test/CodeGenCXX/cxx1z-initializer-aggregate.cpp
index 9110e49f93a1..f59ec51136fe 100644
--- a/test/CodeGenCXX/cxx1z-initializer-aggregate.cpp
+++ b/test/CodeGenCXX/cxx1z-initializer-aggregate.cpp
@@ -112,3 +112,21 @@ namespace Dynamic {
// A_CLEANUP:
// CHECK: call void @_ZN7Dynamic1AD1Ev({{.*}} @_ZN7Dynamic2d3E
}
+
+namespace Instantiated1 {
+ struct A { A(); };
+ struct B : A { using A::A; };
+ template<int> B v({});
+ template B v<0>;
+ // CHECK-LABEL: define {{.*}}global_var_init{{.*}} comdat($_ZN13Instantiated11vILi0EEE) {
+ // CHECK: call void @_ZN13Instantiated11BC1Ev(%{{.*}}* @_ZN13Instantiated11vILi0EEE)
+}
+
+namespace Instantiated2 {
+ struct A { A(); };
+ struct B : A {};
+ template<int> B v({});
+ template B v<0>;
+ // CHECK-LABEL: define {{.*}}global_var_init{{.*}} comdat($_ZN13Instantiated21vILi0EEE) {
+ // CHECK: call void @_ZN13Instantiated21AC2Ev(
+}
diff --git a/test/CodeGenCXX/cxx1z-inline-variables.cpp b/test/CodeGenCXX/cxx1z-inline-variables.cpp
index 2d16acd8a8c2..938ebbbeb3ab 100644
--- a/test/CodeGenCXX/cxx1z-inline-variables.cpp
+++ b/test/CodeGenCXX/cxx1z-inline-variables.cpp
@@ -58,14 +58,22 @@ template<typename T> struct X {
static int a;
static inline int b;
static int c;
+ static const int d;
+ static int e;
};
// CHECK: @_ZN1XIiE1aE = linkonce_odr global i32 10
// CHECK: @_ZN1XIiE1bE = global i32 20
// CHECK-NOT: @_ZN1XIiE1cE
+// CHECK: @_ZN1XIiE1dE = linkonce_odr constant i32 40
+// CHECK: @_ZN1XIiE1eE = linkonce_odr global i32 50
template<> inline int X<int>::a = 10;
int &use3 = X<int>::a;
template<> int X<int>::b = 20;
template<> inline int X<int>::c = 30;
+template<typename T> constexpr int X<T>::d = 40;
+template<typename T> inline int X<T>::e = 50;
+const int *use_x_int_d = &X<int>::d;
+const int *use_x_int_e = &X<int>::e;
template<typename T> struct Y;
template<> struct Y<int> {
@@ -103,3 +111,29 @@ int e = d<int>;
// CHECK-NOT: __cxa_guard_acquire(i64* @_ZGV1b)
// CHECK: call i32 @_Z1fv
// CHECK-NOT: __cxa_guard_release(i64* @_ZGV1b)
+
+namespace PR35599 {
+struct Marker1 {};
+struct Marker2 {};
+
+template <typename>
+struct Foo {
+ struct Bar { Bar(); };
+ inline static Bar bar;
+};
+
+void run() {
+ // All we want here are ODR uses. Anything that requires that the type is
+ // complete is uninteresting.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-value"
+ Foo<Marker1>::bar;
+#pragma clang diagnostic pop
+ static_cast<void>(Foo<Marker2>::bar);
+}
+
+// CHECK-LABEL: define {{.*}}global_var_init{{.*}}comdat
+// CHECK: call void @_ZN7PR355993FooINS_7Marker1EE3BarC1Ev
+// CHECK-LABEL: define {{.*}}global_var_init{{.*}}comdat
+// CHECK: call void @_ZN7PR355993FooINS_7Marker2EE3BarC1Ev
+}
diff --git a/test/CodeGenCXX/cxx1z-lambda-star-this.cpp b/test/CodeGenCXX/cxx1z-lambda-star-this.cpp
index a7e4aadbd573..114791c6558b 100644
--- a/test/CodeGenCXX/cxx1z-lambda-star-this.cpp
+++ b/test/CodeGenCXX/cxx1z-lambda-star-this.cpp
@@ -10,13 +10,13 @@ namespace ns1 {
int X = A{}.foo()();
} //end ns1
-//CHECK: @"\01?foo@A@@QAE?A?<auto>@@XZ"(%struct.A* %this, %class.anon* noalias sret %[[A_LAMBDA_RETVAL:.*]])
+//CHECK: @"?foo@A@@QAE?A?<auto>@@XZ"(%struct.A* %this, %class.anon* noalias sret %[[A_LAMBDA_RETVAL:.*]])
// get the first object with the closure type, which is of type 'struct.A'
//CHECK: %[[I0:.+]] = getelementptr inbounds %[[A_LAMBDA]], %[[A_LAMBDA]]* %[[A_LAMBDA_RETVAL]], i32 0, i32 0
//CHECK: %[[I1:.+]] = bitcast %struct.A* %[[I0]] to i8*
//CHECK: %[[I2:.+]] = bitcast %struct.A* %this1 to i8*
// copy the contents ...
-//CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %[[I1]], i8* %[[I2]], i32 8, i32 8, i1 false)
+//CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %[[I1]], i8* align 8 %[[I2]], i32 8, i1 false)
struct B {
double b = 222;
@@ -26,6 +26,6 @@ struct B {
namespace ns2 {
int X = B{}.bar()();
}
-//CHECK: @"\01?bar@B@@QAE?A?<auto>@@XZ"(%struct.B* %this, %class.anon.0* noalias sret %agg.result)
+//CHECK: @"?bar@B@@QAE?A?<auto>@@XZ"(%struct.B* %this, %class.anon.0* noalias sret %agg.result)
//CHECK: %[[I20:.+]] = getelementptr inbounds %class.anon.0, %class.anon.0* %agg.result, i32 0, i32 0
//CHECK: store %struct.B* %this1, %struct.B** %[[I20]], align 4
diff --git a/test/CodeGenCXX/cxx2a-compare.cpp b/test/CodeGenCXX/cxx2a-compare.cpp
new file mode 100644
index 000000000000..ef6bb5556e22
--- /dev/null
+++ b/test/CodeGenCXX/cxx2a-compare.cpp
@@ -0,0 +1,188 @@
+// RUN: %clang_cc1 -std=c++2a -emit-llvm %s -o - -triple %itanium_abi_triple | \
+// RUN: FileCheck %s \
+// RUN: '-DWE="class.std::__1::weak_equality"' \
+// RUN: '-DSO="class.std::__1::strong_ordering"' \
+// RUN: '-DSE="class.std::__1::strong_equality"' \
+// RUN: '-DPO="class.std::__1::partial_ordering"' \
+// RUN: -DEQ=0 -DLT=-1 -DGT=1 -DUNORD=-127 -DNE=1
+
+#include "Inputs/std-compare.h"
+
+// Ensure we don't emit definitions for the global variables
+// since the builtins shouldn't ODR use them.
+// CHECK-NOT: constant %[[SO]]
+// CHECK-NOT: constant %[[SE]]
+// CHECK-NOT: constant %[[WE]]
+// CHECK-NOT: constant %[[PO]]
+
+// CHECK-LABEL: @_Z11test_signedii
+auto test_signed(int x, int y) {
+ // CHECK: %[[DEST:retval|agg.result]]
+ // CHECK: %cmp.lt = icmp slt i32 %0, %1
+ // CHECK: %sel.lt = select i1 %cmp.lt, i8 [[LT]], i8 [[GT]]
+ // CHECK: %cmp.eq = icmp eq i32 %0, %1
+ // CHECK: %sel.eq = select i1 %cmp.eq, i8 [[EQ]], i8 %sel.lt
+ // CHECK: %__value_ = getelementptr inbounds %[[SO]], %[[SO]]* %[[DEST]]
+ // CHECK: store i8 %sel.eq, i8* %__value_, align 1
+ // CHECK: ret
+ return x <=> y;
+}
+
+// CHECK-LABEL: @_Z13test_unsignedjj
+auto test_unsigned(unsigned x, unsigned y) {
+ // CHECK: %[[DEST:retval|agg.result]]
+ // CHECK: %cmp.lt = icmp ult i32 %0, %1
+ // CHECK: %sel.lt = select i1 %cmp.lt, i8 [[LT]], i8 [[GT]]
+ // CHECK: %cmp.eq = icmp eq i32 %0, %1
+ // CHECK: %sel.eq = select i1 %cmp.eq, i8 [[EQ]], i8 %sel.lt
+ // CHECK: %__value_ = getelementptr inbounds %[[SO]], %[[SO]]* %[[DEST]]
+ // CHECK: store i8 %sel.eq, i8* %__value_
+ // CHECK: ret
+ return x <=> y;
+}
+
+// CHECK-LABEL: @_Z10float_testdd
+auto float_test(double x, double y) {
+ // CHECK: %[[DEST:retval|agg.result]]
+ // CHECK: %cmp.eq = fcmp oeq double %0, %1
+ // CHECK: %sel.eq = select i1 %cmp.eq, i8 [[EQ]], i8 [[UNORD]]
+ // CHECK: %cmp.gt = fcmp ogt double %0, %1
+ // CHECK: %sel.gt = select i1 %cmp.gt, i8 [[GT]], i8 %sel.eq
+ // CHECK: %cmp.lt = fcmp olt double %0, %1
+ // CHECK: %sel.lt = select i1 %cmp.lt, i8 [[LT]], i8 %sel.gt
+ // CHECK: %__value_ = getelementptr inbounds %[[PO]], %[[PO]]* %[[DEST]]
+ // CHECK: store i8 %sel.lt, i8* %__value_
+ // CHECK: ret
+ return x <=> y;
+}
+
+// CHECK-LABEL: @_Z8ptr_testPiS_
+auto ptr_test(int *x, int *y) {
+ // CHECK: %[[DEST:retval|agg.result]]
+ // CHECK: %cmp.lt = icmp ult i32* %0, %1
+ // CHECK: %sel.lt = select i1 %cmp.lt, i8 [[LT]], i8 [[GT]]
+ // CHECK: %cmp.eq = icmp eq i32* %0, %1
+ // CHECK: %sel.eq = select i1 %cmp.eq, i8 [[EQ]], i8 %sel.lt
+ // CHECK: %__value_ = getelementptr inbounds %[[SO]], %[[SO]]* %[[DEST]]
+ // CHECK: store i8 %sel.eq, i8* %__value_, align 1
+ // CHECK: ret
+ return x <=> y;
+}
+
+struct MemPtr {};
+using MemPtrT = void (MemPtr::*)();
+using MemDataT = int(MemPtr::*);
+
+// CHECK-LABEL: @_Z12mem_ptr_testM6MemPtrFvvES1_
+auto mem_ptr_test(MemPtrT x, MemPtrT y) {
+ // CHECK: %[[DEST:retval|agg.result]]
+ // CHECK: %cmp.ptr = icmp eq [[TY:i[0-9]+]] %lhs.memptr.ptr, %rhs.memptr.ptr
+ // CHECK: %cmp.ptr.null = icmp eq [[TY]] %lhs.memptr.ptr, 0
+ // CHECK: %cmp.adj = icmp eq [[TY]] %lhs.memptr.adj, %rhs.memptr.adj
+ // CHECK: %[[OR:.*]] = or i1
+ // CHECK-SAME %cmp.adj
+ // CHECK: %memptr.eq = and i1 %cmp.ptr, %[[OR]]
+ // CHECK: %sel.eq = select i1 %memptr.eq, i8 [[EQ]], i8 [[NE]]
+ // CHECK: %__value_ = getelementptr inbounds %[[SE]], %[[SE]]* %[[DEST]]
+ // CHECK: store i8 %sel.eq, i8* %__value_, align 1
+ // CHECK: ret
+ return x <=> y;
+}
+
+// CHECK-LABEL: @_Z13mem_data_testM6MemPtriS0_
+auto mem_data_test(MemDataT x, MemDataT y) {
+ // CHECK: %[[DEST:retval|agg.result]]
+ // CHECK: %[[CMP:.*]] = icmp eq i{{[0-9]+}} %0, %1
+ // CHECK: %sel.eq = select i1 %[[CMP]], i8 [[EQ]], i8 [[NE]]
+ // CHECK: %__value_ = getelementptr inbounds %[[SE]], %[[SE]]* %[[DEST]]
+ // CHECK: store i8 %sel.eq, i8* %__value_, align 1
+ return x <=> y;
+}
+
+// CHECK-LABEL: @_Z13test_constantv
+auto test_constant() {
+ // CHECK: %[[DEST:retval|agg.result]]
+ // CHECK-NOT: icmp
+ // CHECK: %__value_ = getelementptr inbounds %[[SO]], %[[SO]]* %[[DEST]]
+ // CHECK-NEXT: store i8 -1, i8* %__value_
+ // CHECK: ret
+ const int x = 42;
+ const int y = 101;
+ return x <=> y;
+}
+
+// CHECK-LABEL: @_Z16test_nullptr_objPiDn
+auto test_nullptr_obj(int* x, decltype(nullptr) y) {
+ // CHECK: %[[DEST:retval|agg.result]]
+ // CHECK: %cmp.eq = icmp eq i32* %0, null
+ // CHECK: %sel.eq = select i1 %cmp.eq, i8 [[EQ]], i8 [[NE]]
+ // CHECK: %__value_ = getelementptr inbounds %[[SE]], %[[SE]]* %[[DEST]]
+ // CHECK: store i8 %sel.eq, i8* %__value_, align 1
+ return x <=> y;
+}
+
+// CHECK-LABEL: @_Z18unscoped_enum_testijxy
+void unscoped_enum_test(int i, unsigned u, long long l, unsigned long long ul) {
+ enum EnumA : int { A };
+ enum EnumB : unsigned { B };
+ // CHECK: %[[I:.*]] = load {{.*}} %i.addr
+ // CHECK: icmp slt i32 {{.*}} %[[I]]
+ (void)(A <=> i);
+
+ // CHECK: %[[U:.*]] = load {{.*}} %u.addr
+ // CHECK: icmp ult i32 {{.*}} %[[U]]
+ (void)(A <=> u);
+
+ // CHECK: %[[L:.*]] = load {{.*}} %l.addr
+ // CHECK: icmp slt i64 {{.*}} %[[L]]
+ (void)(A <=> l);
+
+ // CHECK: %[[U2:.*]] = load {{.*}} %u.addr
+ // CHECK: icmp ult i32 {{.*}} %[[U2]]
+ (void)(B <=> u);
+
+ // CHECK: %[[UL:.*]] = load {{.*}} %ul.addr
+ // CHECK: icmp ult i64 {{.*}} %[[UL]]
+ (void)(B <=> ul);
+}
+
+namespace NullptrTest {
+using nullptr_t = decltype(nullptr);
+
+// CHECK-LABEL: @_ZN11NullptrTest4testEDnDn(
+auto test(nullptr_t x, nullptr_t y) {
+ // CHECK: %[[DEST:retval|agg.result]]
+ // CHECK-NOT: select
+ // CHECK: %__value_ = getelementptr inbounds %[[SE]], %[[SE]]* %[[DEST]]
+ // CHECK-NEXT: store i8 [[EQ]], i8* %__value_
+ // CHECK: ret
+ return x <=> y;
+}
+} // namespace NullptrTest
+
+namespace ComplexTest {
+
+auto test_float(_Complex float x, _Complex float y) {
+ // CHECK: %[[DEST:retval|agg.result]]
+ // CHECK: %cmp.eq.r = fcmp oeq float %x.real, %y.real
+ // CHECK: %cmp.eq.i = fcmp oeq float %x.imag, %y.imag
+ // CHECK: %and.eq = and i1 %cmp.eq.r, %cmp.eq.i
+ // CHECK: %sel.eq = select i1 %and.eq, i8 [[EQ]], i8 [[NE]]
+ // CHECK: %__value_ = getelementptr inbounds %[[WE]], %[[WE]]* %[[DEST]]
+ // CHECK: store i8 %sel.eq, i8* %__value_, align 1
+ return x <=> y;
+}
+
+// CHECK-LABEL: @_ZN11ComplexTest8test_intECiS0_(
+auto test_int(_Complex int x, _Complex int y) {
+ // CHECK: %[[DEST:retval|agg.result]]
+ // CHECK: %cmp.eq.r = icmp eq i32 %x.real, %y.real
+ // CHECK: %cmp.eq.i = icmp eq i32 %x.imag, %y.imag
+ // CHECK: %and.eq = and i1 %cmp.eq.r, %cmp.eq.i
+ // CHECK: %sel.eq = select i1 %and.eq, i8 [[EQ]], i8 [[NE]]
+ // CHECK: %__value_ = getelementptr inbounds %[[SE]], %[[SE]]* %[[DEST]]
+ // CHECK: store i8 %sel.eq, i8* %__value_, align 1
+ return x <=> y;
+}
+
+} // namespace ComplexTest
diff --git a/test/CodeGenCXX/cxx2a-destroying-delete.cpp b/test/CodeGenCXX/cxx2a-destroying-delete.cpp
index 2e4d40715e15..60c5970cb94f 100644
--- a/test/CodeGenCXX/cxx2a-destroying-delete.cpp
+++ b/test/CodeGenCXX/cxx2a-destroying-delete.cpp
@@ -21,7 +21,7 @@ void delete_A(A *a) { delete a; }
// Ensure that we call the destroying delete and not the destructor.
// CHECK-NOT: call
// CHECK-ITANIUM: call void @_ZN1AdlEPS_St19destroying_delete_t(%{{.*}}* %[[a]])
-// CHECK-MSABI: call void @"\01??3A@@SAXPEAU0@Udestroying_delete_t@std@@@Z"(%{{.*}}* %[[a]], i8
+// CHECK-MSABI: call void @"??3A@@SAXPEAU0@Udestroying_delete_t@std@@@Z"(%{{.*}}* %[[a]], i8
// CHECK-NOT: call
// CHECK: }
@@ -65,7 +65,7 @@ void delete_C(C *c) { delete c; }
//
// CHECK-NOT: call
// CHECK-ITANIUM: call void @_ZN1AdlEPS_St19destroying_delete_t(%{{.*}}* %[[a]])
-// CHECK-MSABI: call void @"\01??3A@@SAXPEAU0@Udestroying_delete_t@std@@@Z"(%{{.*}}* %[[a]], i8
+// CHECK-MSABI: call void @"??3A@@SAXPEAU0@Udestroying_delete_t@std@@@Z"(%{{.*}}* %[[a]], i8
// CHECK-NOT: call
// CHECK: }
@@ -78,15 +78,15 @@ void delete_D(D *d) { delete d; }
// CHECK: br i1
//
// CHECK-NOT: call
-// CHECK: %[[VTABLE:.*]] = load
-// CHECK: %[[DTOR:.*]] = load
-//
// For MS, we don't add a new vtable slot to the primary vtable for the virtual
// destructor. Instead we cast to the VDel base class.
// CHECK-MSABI: bitcast {{.*}} %[[d]]
// CHECK-MSABI-NEXT: getelementptr {{.*}}, i64 8
// CHECK-MSABI-NEXT: %[[d:.*]] = bitcast i8*
//
+// CHECK: %[[VTABLE:.*]] = load
+// CHECK: %[[DTOR:.*]] = load
+//
// CHECK: call {{void|i8\*}} %[[DTOR]](%{{.*}}* %[[d]]
// CHECK-MSABI-SAME: , i32 1)
// CHECK-NOT: call
@@ -100,7 +100,7 @@ void delete_G(G *g) { delete g; }
// CHECK-LABEL: define {{.*}}delete_G
// CHECK-NOT: call
// CHECK-ITANIUM: call void @_ZN1FdlEPS_St19destroying_delete_tmSt11align_val_t(%{{.*}}* %[[a]], i64 32, i64 16)
-// CHECK-MSABI: call void @"\01??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"(%{{.*}}* %[[a]], i8 {{[^,]*}}, i64 32, i64 16)
+// CHECK-MSABI: call void @"??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"(%{{.*}}* %[[a]], i8 {{[^,]*}}, i64 32, i64 16)
// CHECK-NOT: call
// CHECK: }
@@ -116,7 +116,7 @@ H::~H() { call_in_dtor(); }
// CHECK-ITANIUM-NOT: call
// CHECK-ITANIUM: }
-// CHECK-MSABI: define {{.*}} @"\01??_GH@@UEAAPEAXI@Z"(
+// CHECK-MSABI: define {{.*}} @"??_GH@@UEAAPEAXI@Z"(
// CHECK-MSABI-NOT: call{{ }}
// CHECK-MSABI: load i32
// CHECK-MSABI: icmp eq i32 {{.*}}, 0
@@ -125,10 +125,10 @@ H::~H() { call_in_dtor(); }
// CHECK-MSABI-NOT: call{{ }}
// CHECK-MSABI: getelementptr {{.*}}, i64 24
// CHECK-MSABI-NOT: call{{ }}
-// CHECK-MSABI: call void @"\01??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"({{.*}}, i64 48, i64 16)
+// CHECK-MSABI: call void @"??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"({{.*}}, i64 48, i64 16)
// CHECK-MSABI: br label %[[RETURN:.*]]
//
-// CHECK-MSABI: call void @"\01??_DH@@QEAAXXZ"(
+// CHECK-MSABI: call void @"??1H@@UEAA@XZ"(
// CHECK-MSABI: br label %[[RETURN]]
//
// CHECK-MSABI: }
@@ -143,7 +143,7 @@ I::~I() { call_in_dtor(); }
// CHECK-ITANIUM-NOT: call
// CHECK-ITANIUM: }
-// CHECK-MSABI: define {{.*}} @"\01??_GI@@UEAAPEAXI@Z"(
+// CHECK-MSABI: define {{.*}} @"??_GI@@UEAAPEAXI@Z"(
// CHECK-MSABI-NOT: call{{ }}
// CHECK-MSABI: load i32
// CHECK-MSABI: icmp eq i32 {{.*}}, 0
@@ -152,10 +152,10 @@ I::~I() { call_in_dtor(); }
// CHECK-MSABI-NOT: call{{ }}
// CHECK-MSABI: getelementptr {{.*}}, i64 24
// CHECK-MSABI-NOT: call{{ }}
-// CHECK-MSABI: call void @"\01??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"({{.*}}, i64 96, i64 32)
+// CHECK-MSABI: call void @"??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"({{.*}}, i64 96, i64 32)
// CHECK-MSABI: br label %[[RETURN:.*]]
//
-// CHECK-MSABI: call void @"\01??_DI@@QEAAXXZ"(
+// CHECK-MSABI: call void @"??1I@@UEAA@XZ"(
// CHECK-MSABI: br label %[[RETURN]]
//
// CHECK-MSABI: }
diff --git a/test/CodeGenCXX/debug-info-access.cpp b/test/CodeGenCXX/debug-info-access.cpp
index 82f29ea4d38a..44d6b4da17a3 100644
--- a/test/CodeGenCXX/debug-info-access.cpp
+++ b/test/CodeGenCXX/debug-info-access.cpp
@@ -10,7 +10,7 @@ struct A {
};
-// CHECK: !DIDerivedType(tag: DW_TAG_inheritance,{{.*}} baseType: ![[A]],{{.*}} flags: DIFlagPublic)
+// CHECK: !DIDerivedType(tag: DW_TAG_inheritance,{{.*}} baseType: ![[A]],{{.*}} flags: DIFlagPublic, extraData: i32 0)
class B : public A {
public:
// CHECK-DAG: !DISubprogram(name: "pub",{{.*}} line: [[@LINE+1]],{{.*}} flags: DIFlagPublic | DIFlagPrototyped,
diff --git a/test/CodeGenCXX/debug-info-class-nolimit.cpp b/test/CodeGenCXX/debug-info-class-nolimit.cpp
index 0b3b38dd17b1..b184b9e08da7 100644
--- a/test/CodeGenCXX/debug-info-class-nolimit.cpp
+++ b/test/CodeGenCXX/debug-info-class-nolimit.cpp
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin -debug-info-kind=standalone -o - -emit-llvm %s | FileCheck %s
// We had a bug in -fstandalone-debug where UnicodeString would not be completed
-// when it was required to be complete. This orginally manifested as an
+// when it was required to be complete. This originally manifested as an
// assertion in CodeView emission on Windows with some dllexport stuff, but it's
// more general than that.
diff --git a/test/CodeGenCXX/debug-info-codeview-unnamed.cpp b/test/CodeGenCXX/debug-info-codeview-unnamed.cpp
new file mode 100644
index 000000000000..dd4cc9cb4787
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-codeview-unnamed.cpp
@@ -0,0 +1,108 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -debug-info-kind=limited -S -emit-llvm -std=c++11 -o - %s | FileCheck --check-prefix LINUX %s
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -debug-info-kind=limited -gcodeview -S -emit-llvm -std=c++11 -o - %s | FileCheck --check-prefix MSVC %s
+
+int main(int argc, char* argv[], char* arge[]) {
+ //
+ // In CodeView, the LF_MFUNCTION entry for "bar()" refers to the forward
+ // reference of the unnamed struct. Visual Studio requires a unique
+ // identifier to match the LF_STRUCTURE forward reference to the definition.
+ //
+ struct { void bar() {} } one;
+ //
+ // LINUX: !{{[0-9]+}} = !DILocalVariable(name: "one"
+ // LINUX-SAME: type: [[TYPE_OF_ONE:![0-9]+]]
+ // LINUX-SAME: )
+ // LINUX: [[TYPE_OF_ONE]] = distinct !DICompositeType(
+ // LINUX-SAME: tag: DW_TAG_structure_type
+ // LINUX-NOT: name:
+ // LINUX-NOT: identifier:
+ // LINUX-SAME: )
+ //
+ // MSVC: !{{[0-9]+}} = !DILocalVariable(name: "one"
+ // MSVC-SAME: type: [[TYPE_OF_ONE:![0-9]+]]
+ // MSVC-SAME: )
+ // MSVC: [[TYPE_OF_ONE]] = distinct !DICompositeType
+ // MSVC-SAME: tag: DW_TAG_structure_type
+ // MSVC-SAME: name: "<unnamed-type-one>"
+ // MSVC-SAME: identifier: ".?AU<unnamed-type-one>@?1??main@@9@"
+ // MSVC-SAME: )
+
+
+ // In CodeView, the LF_POINTER entry for "ptr2unnamed" refers to the forward
+ // reference of the unnamed struct. Visual Studio requires a unique
+ // identifier to match the LF_STRUCTURE forward reference to the definition.
+ //
+ struct { int bar; } two = { 42 };
+ int decltype(two)::*ptr2unnamed = &decltype(two)::bar;
+ //
+ // LINUX: !{{[0-9]+}} = !DILocalVariable(name: "two"
+ // LINUX-SAME: type: [[TYPE_OF_TWO:![0-9]+]]
+ // LINUX-SAME: )
+ // LINUX: [[TYPE_OF_TWO]] = distinct !DICompositeType(
+ // LINUX-SAME: tag: DW_TAG_structure_type
+ // LINUX-NOT: name:
+ // LINUX-NOT: identifier:
+ // LINUX-SAME: )
+ //
+ // MSVC: !{{[0-9]+}} = !DILocalVariable(name: "two"
+ // MSVC-SAME: type: [[TYPE_OF_TWO:![0-9]+]]
+ // MSVC-SAME: )
+ // MSVC: [[TYPE_OF_TWO]] = distinct !DICompositeType
+ // MSVC-SAME: tag: DW_TAG_structure_type
+ // MSVC-SAME: name: "<unnamed-type-two>"
+ // MSVC-SAME: identifier: ".?AU<unnamed-type-two>@?2??main@@9@"
+ // MSVC-SAME: )
+
+
+ // In DWARF, named structures which are not externally visibile do not
+ // require an identifier. In CodeView, named structures are given an
+ // identifier.
+ //
+ struct named { int bar; int named::* p2mem; } three = { 42, &named::bar };
+ //
+ // LINUX: !{{[0-9]+}} = !DILocalVariable(name: "three"
+ // LINUX-SAME: type: [[TYPE_OF_THREE:![0-9]+]]
+ // LINUX-SAME: )
+ // LINUX: [[TYPE_OF_THREE]] = distinct !DICompositeType(
+ // LINUX-SAME: tag: DW_TAG_structure_type
+ // LINUX-SAME: name: "named"
+ // LINUX-NOT: identifier:
+ // LINUX-SAME: )
+ //
+ // MSVC: !{{[0-9]+}} = !DILocalVariable(name: "three"
+ // MSVC-SAME: type: [[TYPE_OF_THREE:![0-9]+]]
+ // MSVC-SAME: )
+ // MSVC: [[TYPE_OF_THREE]] = distinct !DICompositeType
+ // MSVC-SAME: tag: DW_TAG_structure_type
+ // MSVC-SAME: name: "named"
+ // MSVC-SAME: identifier: ".?AUnamed@?1??main@@9@"
+ // MSVC-SAME: )
+
+
+ // In CodeView, the LF_MFUNCTION entry for the lambda "operator()" routine
+ // refers to the forward reference of the unnamed LF_CLASS for the lambda.
+ // Visual Studio requires a unique identifier to match the forward reference
+ // of the LF_CLASS to its definition.
+ //
+ auto four = [argc](int i) -> int { return argc == i ? 1 : 0; };
+ //
+ // LINUX: !{{[0-9]+}} = !DILocalVariable(name: "four"
+ // LINUX-SAME: type: [[TYPE_OF_FOUR:![0-9]+]]
+ // LINUX-SAME: )
+ // LINUX: [[TYPE_OF_FOUR]] = distinct !DICompositeType(
+ // LINUX-SAME: tag: DW_TAG_class_type
+ // LINUX-NOT: name:
+ // LINUX-NOT: identifier:
+ // LINUX-SAME: )
+ //
+ // MSVC: !{{[0-9]+}} = !DILocalVariable(name: "four"
+ // MSVC-SAME: type: [[TYPE_OF_FOUR:![0-9]+]]
+ // MSVC-SAME: )
+ // MSVC: [[TYPE_OF_FOUR]] = distinct !DICompositeType
+ // MSVC-SAME: tag: DW_TAG_class_type
+ // MSVC-NOT: name:
+ // MSVC-SAME: identifier: ".?AV<lambda_0>@?0??main@@9@"
+ // MSVC-SAME: )
+
+ return 0;
+}
diff --git a/test/CodeGenCXX/debug-info-codeview-var-templates.cpp b/test/CodeGenCXX/debug-info-codeview-var-templates.cpp
new file mode 100644
index 000000000000..0470c133688c
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-codeview-var-templates.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 %s -std=c++14 -triple=i686-pc-windows-msvc -debug-info-kind=limited -gcodeview -emit-llvm -o - | FileCheck %s
+
+// Don't emit static data member debug info for variable templates.
+// PR38004
+
+struct TestImplicit {
+ template <typename T>
+ static const __SIZE_TYPE__ size_var = sizeof(T);
+};
+int instantiate_test1() { return TestImplicit::size_var<int> + TestImplicit::size_var<TestImplicit>; }
+TestImplicit gv1;
+
+// CHECK: ![[empty:[0-9]+]] = !{}
+
+// CHECK: ![[A:[^ ]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "TestImplicit",
+// CHECK-SAME: elements: ![[empty]]
+
+template <typename T> bool vtpl;
+struct TestSpecialization {
+ template <typename T, typename U> static const auto sdm = vtpl<T>;
+ template <> static const auto sdm<int, int> = false;
+} gv2;
+
+// CHECK: ![[A:[^ ]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "TestSpecialization",
+// CHECK-SAME: elements: ![[empty]]
+
+template <class> bool a;
+template <typename> struct b;
+struct TestPartial {
+ template <typename... e> static auto d = a<e...>;
+ template <typename... e> static auto d<b<e...>> = d<e...>;
+} c;
+
+// CHECK: ![[A:[^ ]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "TestPartial",
+// CHECK-SAME: elements: ![[empty]]
diff --git a/test/CodeGenCXX/debug-info-composite-cc.cpp b/test/CodeGenCXX/debug-info-composite-cc.cpp
new file mode 100644
index 000000000000..d4d4046105e1
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-composite-cc.cpp
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -emit-llvm -debug-info-kind=standalone -triple %itanium_abi_triple %s -o - | FileCheck %s
+
+// Not trivially copyable because of the explicit destructor.
+// CHECK-DAG: !DICompositeType({{.*}}, name: "RefDtor",{{.*}}flags: DIFlagTypePassByReference
+struct RefDtor {
+ int i;
+ ~RefDtor() {}
+} refDtor;
+
+// Not trivially copyable because of the explicit copy constructor.
+// CHECK-DAG: !DICompositeType({{.*}}, name: "RefCopy",{{.*}}flags: DIFlagTypePassByReference
+struct RefCopy {
+ int i;
+ RefCopy() = default;
+ RefCopy(RefCopy &Copy) {}
+} refCopy;
+
+// POD-like type even though it defines a destructor.
+// CHECK-DAG: !DICompositeType({{.*}}, name: "Podlike", {{.*}}flags: DIFlagTypePassByValue
+struct Podlike {
+ int i;
+ Podlike() = default;
+ Podlike(Podlike &&Move) = default;
+ ~Podlike() = default;
+} podlike;
+
+
+// This is a POD type.
+// CHECK-DAG: !DICompositeType({{.*}}, name: "Pod",{{.*}}flags: DIFlagTypePassByValue
+struct Pod {
+ int i;
+} pod;
+
+// This is definitely not a POD type.
+// CHECK-DAG: !DICompositeType({{.*}}, name: "Complex",{{.*}}flags: DIFlagTypePassByReference
+struct Complex {
+ Complex() {}
+ Complex(Complex &Copy) : i(Copy.i) {};
+ int i;
+} complex;
+
+// This type is manually marked as trivial_abi.
+// CHECK-DAG: !DICompositeType({{.*}}, name: "Marked",{{.*}}flags: DIFlagTypePassByValue
+struct __attribute__((trivial_abi)) Marked {
+ int *p;
+ Marked();
+ ~Marked();
+ Marked(const Marked &) noexcept;
+ Marked &operator=(const Marked &);
+} marked;
diff --git a/test/CodeGenCXX/debug-info-enum-class.cpp b/test/CodeGenCXX/debug-info-enum-class.cpp
index b615d5b09626..e857bb195913 100644
--- a/test/CodeGenCXX/debug-info-enum-class.cpp
+++ b/test/CodeGenCXX/debug-info-enum-class.cpp
@@ -15,7 +15,7 @@ D d;
// CHECK-SAME: baseType: ![[INT:[0-9]+]]
// CHECK-SAME: size: 32
// CHECK-NOT: offset:
-// CHECK-NOT: flags:
+// CHECK-SAME: flags: DIFlagFixedEnum
// CHECK-SAME: ){{$}}
// CHECK: ![[INT]] = !DIBasicType(name: "int"
// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "B"
@@ -23,12 +23,12 @@ D d;
// CHECK-SAME: baseType: ![[ULONG:[0-9]+]]
// CHECK-SAME: size: 64
// CHECK-NOT: offset:
-// CHECK-NOT: flags:
+// CHECK-SAME: flags: DIFlagFixedEnum
// CHECK-SAME: ){{$}}
// CHECK: ![[ULONG]] = !DIBasicType(name: "long unsigned int"
// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "C"
// CHECK-SAME: line: 5
-// CHECK-NOT: baseType:
+// CHECK-SAME: baseType: ![[ULONG:[0-9]+]]
// CHECK-SAME: size: 32
// CHECK-NOT: offset:
// CHECK-NOT: flags:
diff --git a/test/CodeGenCXX/debug-info-enum.cpp b/test/CodeGenCXX/debug-info-enum.cpp
index 8f54f9d71224..447edba446dc 100644
--- a/test/CodeGenCXX/debug-info-enum.cpp
+++ b/test/CodeGenCXX/debug-info-enum.cpp
@@ -11,7 +11,7 @@ namespace test1 {
// CHECK-SAME: identifier: "_ZTSN5test11eE"
// CHECK: [[TEST1]] = !DINamespace(name: "test1"
// CHECK: [[TEST1_ENUMS]] = !{[[TEST1_E:![0-9]*]]}
-// CHECK: [[TEST1_E]] = !DIEnumerator(name: "E", value: 0)
+// CHECK: [[TEST1_E]] = !DIEnumerator(name: "E", value: 0, isUnsigned: true)
enum e { E };
void foo() {
int v = E;
diff --git a/test/CodeGenCXX/debug-info-line-if.cpp b/test/CodeGenCXX/debug-info-line-if.cpp
index 41770b135619..7e6cdb2eb9d8 100644
--- a/test/CodeGenCXX/debug-info-line-if.cpp
+++ b/test/CodeGenCXX/debug-info-line-if.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -debug-info-kind=limited -std=c++11 -S -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -debug-info-kind=limited -std=c++11 -S -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s
// PR19864
extern int v[2];
int a = 0, b = 0;
diff --git a/test/CodeGenCXX/debug-info-ms-dtor-thunks.cpp b/test/CodeGenCXX/debug-info-ms-dtor-thunks.cpp
index f876267eb5d6..d6fdee62d677 100644
--- a/test/CodeGenCXX/debug-info-ms-dtor-thunks.cpp
+++ b/test/CodeGenCXX/debug-info-ms-dtor-thunks.cpp
@@ -4,11 +4,11 @@ struct __declspec(dllexport) S { virtual ~S(); };
struct __declspec(dllexport) T { virtual ~T(); };
struct __declspec(dllexport) U : S, T { virtual ~U(); };
-// CHECK-LABEL: define {{.*}} @"\01??_GS@@UAEPAXI@Z"
-// CHECK: call x86_thiscallcc void @"\01??_DS@@QAEXXZ"(%struct.S* %this1){{.*}}!dbg !{{[0-9]+}}
+// CHECK-LABEL: define {{.*}} @"??_GS@@UAEPAXI@Z"
+// CHECK: call x86_thiscallcc void @"??1S@@UAE@XZ"(%struct.S* %this1){{.*}}!dbg !{{[0-9]+}}
-// CHECK-LABEL: define {{.*}} @"\01??_GT@@UAEPAXI@Z"
-// CHECK: call x86_thiscallcc void @"\01??_DT@@QAEXXZ"(%struct.T* %this1){{.*}}!dbg !{{[0-9]+}}
+// CHECK-LABEL: define {{.*}} @"??_GT@@UAEPAXI@Z"
+// CHECK: call x86_thiscallcc void @"??1T@@UAE@XZ"(%struct.T* %this1){{.*}}!dbg !{{[0-9]+}}
-// CHECK-LABEL: define {{.*}} @"\01??_GU@@UAEPAXI@Z"
-// CHECK: call x86_thiscallcc void @"\01??_DU@@QAEXXZ"(%struct.U* %this1){{.*}}!dbg !{{[0-9]+}}
+// CHECK-LABEL: define {{.*}} @"??_GU@@UAEPAXI@Z"
+// CHECK: call x86_thiscallcc void @"??1U@@UAE@XZ"(%struct.U* %this1){{.*}}!dbg !{{[0-9]+}}
diff --git a/test/CodeGenCXX/debug-info-ms-vbase.cpp b/test/CodeGenCXX/debug-info-ms-vbase.cpp
index 3de3a751cba1..04c9a6d2ba74 100644
--- a/test/CodeGenCXX/debug-info-ms-vbase.cpp
+++ b/test/CodeGenCXX/debug-info-ms-vbase.cpp
@@ -8,7 +8,7 @@
// CHECK: ![[elements]] = !{![[NoPrimaryBase_base:[0-9]+]]}
// CHECK: ![[NoPrimaryBase_base]] = !DIDerivedType(tag: DW_TAG_inheritance, scope: ![[NoPrimaryBase]],
-// CHECK-SAME: baseType: ![[HasVirtualMethod:[0-9]+]], offset: 4, flags: DIFlagVirtual)
+// CHECK-SAME: baseType: ![[HasVirtualMethod:[0-9]+]], offset: 4, flags: DIFlagVirtual, extraData: i32 0)
// CHECK: ![[HasVirtualMethod]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "HasVirtualMethod"
@@ -18,11 +18,11 @@
// CHECK: ![[elements]] = !{![[SecondaryVTable_base:[0-9]+]], ![[HasVirtualMethod_base:[0-9]+]], ![[vshape:[0-9]+]]}
// CHECK: ![[SecondaryVTable_base]] = !DIDerivedType(tag: DW_TAG_inheritance, scope: ![[HasPrimaryBase]],
-// CHECK-SAME: baseType: ![[SecondaryVTable:[0-9]+]], offset: 4, flags: DIFlagVirtual)
+// CHECK-SAME: baseType: ![[SecondaryVTable:[0-9]+]], offset: 4, flags: DIFlagVirtual, extraData: i32 4)
// CHECK: ![[SecondaryVTable]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "SecondaryVTable"
-// CHECK: ![[HasVirtualMethod_base]] = !DIDerivedType(tag: DW_TAG_inheritance, scope: ![[HasPrimaryBase]], baseType: ![[HasVirtualMethod]])
+// CHECK: ![[HasVirtualMethod_base]] = !DIDerivedType(tag: DW_TAG_inheritance, scope: ![[HasPrimaryBase]], baseType: ![[HasVirtualMethod]], extraData: i32 0)
// CHECK: ![[HasIndirectVirtualBase:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "HasIndirectVirtualBase"
// CHECK-SAME: elements: ![[elements:[0-9]+]]
@@ -41,7 +41,7 @@
// CHECK: ![[elements]] = !{![[POD_base:[0-9]+]]}
// CHECK: ![[POD_base]] = !DIDerivedType(tag: DW_TAG_inheritance, scope: ![[DynamicNoVFPtr]],
-// CHECK-SAME: baseType: ![[POD:[0-9]+]], offset: 4, flags: DIFlagVirtual)
+// CHECK-SAME: baseType: ![[POD:[0-9]+]], offset: 4, flags: DIFlagVirtual, extraData: i32 0)
// CHECK: ![[POD]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "POD"
diff --git a/test/CodeGenCXX/debug-info-range-for-var-names.cpp b/test/CodeGenCXX/debug-info-range-for-var-names.cpp
new file mode 100644
index 000000000000..6cd70fe0820d
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-range-for-var-names.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s
+
+struct vec {
+ using itr = int*;
+ itr begin() { return nullptr; }
+ itr end() { return nullptr; }
+};
+
+void test() {
+ vec as, bs, cs;
+
+ for (auto a : as)
+ for (auto b : bs)
+ for (auto c : cs) {
+ }
+}
+
+// CHECK: call void @llvm.dbg.declare(metadata %struct.vec** {{.*}}, metadata ![[RANGE1:[0-9]+]]
+// CHECK: call void @llvm.dbg.declare(metadata i32** {{.*}}, metadata ![[BEGIN1:[0-9]+]]
+// CHECK: call void @llvm.dbg.declare(metadata i32** {{.*}}, metadata ![[END1:[0-9]+]]
+// CHECK: call void @llvm.dbg.declare(metadata %struct.vec** {{.*}}, metadata ![[RANGE2:[0-9]+]]
+// CHECK: call void @llvm.dbg.declare(metadata i32** {{.*}}, metadata ![[BEGIN2:[0-9]+]]
+// CHECK: call void @llvm.dbg.declare(metadata i32** {{.*}}, metadata ![[END2:[0-9]+]]
+// CHECK: call void @llvm.dbg.declare(metadata %struct.vec** {{.*}}, metadata ![[RANGE3:[0-9]+]]
+// CHECK: call void @llvm.dbg.declare(metadata i32** {{.*}}, metadata ![[BEGIN3:[0-9]+]]
+// CHECK: call void @llvm.dbg.declare(metadata i32** {{.*}}, metadata ![[END3:[0-9]+]]
+// CHECK: ![[RANGE1]] = !DILocalVariable(name: "__range1",
+// CHECK: ![[BEGIN1]] = !DILocalVariable(name: "__begin1",
+// CHECK: ![[END1]] = !DILocalVariable(name: "__end1",
+// CHECK: ![[RANGE2]] = !DILocalVariable(name: "__range2",
+// CHECK: ![[BEGIN2]] = !DILocalVariable(name: "__begin2",
+// CHECK: ![[END2]] = !DILocalVariable(name: "__end2",
+// CHECK: ![[RANGE3]] = !DILocalVariable(name: "__range3",
+// CHECK: ![[BEGIN3]] = !DILocalVariable(name: "__begin3",
+// CHECK: ![[END3]] = !DILocalVariable(name: "__end3",
diff --git a/test/CodeGenCXX/debug-info-scope.cpp b/test/CodeGenCXX/debug-info-scope.cpp
index e81eccc5168f..112428269749 100644
--- a/test/CodeGenCXX/debug-info-scope.cpp
+++ b/test/CodeGenCXX/debug-info-scope.cpp
@@ -58,7 +58,7 @@ void func() {
}
int x[] = {1, 2};
- // CHECK: = !DILocalVariable(name: "__range"
+ // CHECK: = !DILocalVariable(name: "__range1"
// CHECK-SAME: scope: [[RANGE_FOR:![0-9]*]]
// CHECK-NOT: line:
// CHECK-SAME: ){{$}}
diff --git a/test/CodeGenCXX/debug-info-static-member.cpp b/test/CodeGenCXX/debug-info-static-member.cpp
index 3537754ced76..702d1f87e752 100644
--- a/test/CodeGenCXX/debug-info-static-member.cpp
+++ b/test/CodeGenCXX/debug-info-static-member.cpp
@@ -3,9 +3,9 @@
// RUN: %clangxx -target x86_64-unknown-unknown -g -std=c++11 %s -emit-llvm -S -o - | FileCheck %s
// PR14471
-// CHECK: @_ZN1C1aE = global i32 4, align 4, !dbg [[A:![0-9]+]]
-// CHECK: @_ZN1C1bE = global i32 2, align 4, !dbg [[B:![0-9]+]]
-// CHECK: @_ZN1C1cE = global i32 1, align 4, !dbg [[C:![0-9]+]]
+// CHECK: @_ZN1C1aE = dso_local global i32 4, align 4, !dbg [[A:![0-9]+]]
+// CHECK: @_ZN1C1bE = dso_local global i32 2, align 4, !dbg [[B:![0-9]+]]
+// CHECK: @_ZN1C1cE = dso_local global i32 1, align 4, !dbg [[C:![0-9]+]]
enum X {
Y
diff --git a/test/CodeGenCXX/debug-info-template.cpp b/test/CodeGenCXX/debug-info-template.cpp
index 0c3414516215..4b330a0b0a11 100644
--- a/test/CodeGenCXX/debug-info-template.cpp
+++ b/test/CodeGenCXX/debug-info-template.cpp
@@ -1,8 +1,8 @@
// RUN: %clang -S -emit-llvm -target x86_64-unknown_unknown -g %s -o - -std=c++11 | FileCheck %s
-// CHECK: @tci = global %"struct.TC<unsigned int, 2, &glb, &foo::e, &foo::f, &foo::g, 1, 2, 3>::nested" zeroinitializer, align 1, !dbg [[TCI:![0-9]+]]
-// CHECK: @tcn = global %struct.TC zeroinitializer, align 1, !dbg [[TCN:![0-9]+]]
-// CHECK: @nn = global %struct.NN zeroinitializer, align 1, !dbg [[NN:![0-9]+]]
+// CHECK: @tci = dso_local global %"struct.TC<unsigned int, 2, &glb, &foo::e, &foo::f, &foo::g, 1, 2, 3>::nested" zeroinitializer, align 1, !dbg [[TCI:![0-9]+]]
+// CHECK: @tcn = dso_local global %struct.TC zeroinitializer, align 1, !dbg [[TCN:![0-9]+]]
+// CHECK: @nn = dso_local global %struct.NN zeroinitializer, align 1, !dbg [[NN:![0-9]+]]
// CHECK: !DICompileUnit(
// CHECK: [[EMPTY:![0-9]*]] = !{}
diff --git a/test/CodeGenCXX/debug-info-thunk-msabi.cpp b/test/CodeGenCXX/debug-info-thunk-msabi.cpp
index 5c705ac0ac13..565992ad2a3d 100644
--- a/test/CodeGenCXX/debug-info-thunk-msabi.cpp
+++ b/test/CodeGenCXX/debug-info-thunk-msabi.cpp
@@ -3,10 +3,10 @@
class __declspec(dllexport) A {
A(int * = new int) {}
};
-// CHECK: define {{.*}}void @"\01??_FA@@AAEXXZ"
+// CHECK: define {{.*}}void @"??_FA@@AAEXXZ"
// CHECK-SAME: !dbg ![[SP:[0-9]+]]
// CHECK-NOT: {{ret }}
-// CHECK: call x86_thiscallcc %class.A* @"\01??0A@@AAE@PAH@Z"
+// CHECK: call x86_thiscallcc %class.A* @"??0A@@AAE@PAH@Z"
// CHECK-SAME: !dbg ![[DBG:[0-9]+]]
// CHECK: ret void, !dbg
//
diff --git a/test/CodeGenCXX/debug-info-thunk.cpp b/test/CodeGenCXX/debug-info-thunk.cpp
index f7d16f493256..56dec93f6b39 100644
--- a/test/CodeGenCXX/debug-info-thunk.cpp
+++ b/test/CodeGenCXX/debug-info-thunk.cpp
@@ -1,29 +1,277 @@
-// RUN: %clang_cc1 %s -triple %itanium_abi_triple -debug-info-kind=limited -S -emit-llvm -o - | FileCheck %s
-
-struct A {
- virtual void f();
-};
-
-struct B {
- virtual void f();
-};
-
-struct C : A, B {
- virtual void f();
-};
-
-void C::f() { }
-// CHECK: define {{.*}}void @_ZThn{{[48]}}_N1C1fEv
-// CHECK-SAME: !dbg ![[SP:[0-9]+]]
-// CHECK-NOT: {{ret }}
-// CHECK: = load{{.*}} !dbg ![[DBG:[0-9]+]]
-// CHECK-NOT: {{ret }}
-// CHECK: ret void, !dbg ![[DBG]]
+// RUN: %clang_cc1 %s -triple=x86_64-pc-windows-msvc -debug-info-kind=limited -S -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple %itanium_abi_triple -debug-info-kind=limited -S -emit-llvm -o - | FileCheck %s -check-prefix=ITANIUM
//
-// CHECK: ![[SP]] = distinct !DISubprogram(linkageName: "_ZThn{{[48]}}_N1C1fEv"
-// CHECK-SAME: line: 15
-// CHECK-SAME: isDefinition: true
-// CHECK-SAME: DIFlagArtificial
-// CHECK-SAME: ){{$}}
+// Validate we emit a "DIFlagThunk" flag on DISubprogram entries for thunks.
+// This flag is used for emitting S_THUNK32 symbols for CodeView debugging.
//
-// CHECK: ![[DBG]] = !DILocation(line: 0
+// NOTE:
+// Because thunks are compiler generated and don't exist in the source, this
+// test is dependent upon the linkage name to identify the thunk. Any changes
+// in the name mangling may require this test to be updated.
+//
+// NOTE:
+// The FileCheck directives below use CHECK-DAG because the thunks may not be
+// emitted in source order.
+//
+
+namespace Test1 {
+ struct A {
+ virtual void f();
+ };
+
+ struct B {
+ virtual void f();
+ };
+
+ struct C : A, B {
+ virtual void c();
+
+ virtual void f();
+ };
+
+// CHECK-DAG: DISubprogram{{.*}}linkageName: "?f@C@Test1@@W7EAAXXZ"{{.*}} flags: {{.*}}DIFlagThunk
+ void C::f() { }
+}
+
+namespace Test2 {
+ struct V1 { };
+ struct V2 : virtual V1 { };
+
+ struct A {
+ virtual V1 *f();
+ };
+
+ struct B : A {
+ virtual void b();
+
+ virtual V2 *f();
+ };
+
+// CHECK-DAG: DISubprogram{{.*}}linkageName: "?f@B@Test2@@QEAAPEAUV1@2@XZ"{{.*}} flags: {{.*}}DIFlagThunk
+ V2 *B::f() { return 0; }
+}
+
+namespace Test3 {
+ struct A {
+ virtual void f();
+ };
+
+ struct B {
+ virtual void f();
+ };
+
+ struct __attribute__((visibility("protected"))) C : A, B {
+ virtual void c();
+
+ virtual void f();
+ };
+
+// CHECK-DAG: DISubprogram{{.*}}linkageName: "?f@C@Test3@@W7EAAXXZ"{{.*}} flags: {{.*}}DIFlagThunk
+ void C::f() { }
+}
+
+namespace Test4 {
+ struct A {
+ virtual void f();
+ };
+
+ struct B {
+ virtual void f();
+ };
+
+ namespace {
+ struct C : A, B {
+ virtual void c();
+ virtual void f();
+ };
+ }
+ void C::c() {}
+// CHECK-DAG: DISubprogram{{.*}}linkageName: "?f@C@?A@Test4@@W7EAAXXZ"{{.*}} flags: {{.*}}DIFlagThunk
+ void C::f() {}
+
+ // Force C::f to be used.
+ void f() {
+ C c;
+ c.f();
+ }
+}
+
+namespace Test5 {
+ struct X {
+ X();
+ X(const X&);
+ X &operator=(const X&);
+ ~X();
+ };
+
+ struct P {
+ P();
+ P(const P&);
+ ~P();
+ X first;
+ X second;
+ };
+
+ P getP();
+
+ struct Base1 {
+ int i;
+
+ virtual X f() { return X(); }
+ };
+
+ struct Base2 {
+ float real;
+
+ virtual X f() { return X(); }
+ };
+
+ struct Thunks : Base1, Base2 {
+ long l;
+
+ virtual X f();
+ };
+
+// CHECK-DAG: DISubprogram{{.*}}linkageName: "?f@Thunks@Test5@@WBA@EAA?AUX@2@XZ"{{.*}} flags: {{.*}}DIFlagThunk
+ X Thunks::f() { return X(); }
+}
+
+namespace Test6 {
+ struct X {
+ X();
+ X(const X&);
+ X &operator=(const X&);
+ ~X();
+ };
+
+ struct Small { short s; };
+ struct Large {
+ char array[1024];
+ };
+
+ class A {
+ protected:
+ virtual void foo() = 0;
+ };
+
+ class B : public A {
+ protected:
+ virtual void bar() = 0;
+ };
+
+ class C : public A {
+ protected:
+ virtual void baz(X, X&, _Complex float, Small, Small&, Large) = 0;
+ };
+
+ class D : public B,
+ public C {
+// CHECK-DAG: DISubprogram{{.*}}linkageName: "?foo@D@Test6@@G7EAAXXZ"{{.*}} flags: {{.*}}DIFlagThunk
+ void foo() {}
+ void bar() {}
+ void baz(X, X&, _Complex float, Small, Small&, Large);
+ };
+
+ void D::baz(X, X&, _Complex float, Small, Small&, Large) { }
+
+ void testD() { D d; }
+}
+
+namespace Test7 {
+ struct A { virtual void foo(); };
+ struct B { virtual void foo(); };
+// CHECK-DAG: DISubprogram{{.*}}linkageName: "?foo@C@Test7@@W7EAAXXZ"{{.*}} flags: {{.*}}DIFlagThunk
+ struct C : A, B { void foo() {} };
+
+ // Test later.
+ void test() {
+ C c;
+ }
+}
+
+namespace Test8 {
+ struct A { virtual A* f(); };
+ struct B : virtual A { virtual A* f(); };
+ struct C : B { virtual C* f(); };
+// CHECK-DAG: DISubprogram{{.*}}linkageName: "?f@C@Test8@@QEAAPEAUA@2@XZ"{{.*}} flags: {{.*}}DIFlagThunk
+ C* C::f() { return 0; }
+}
+
+namespace Test9 {
+ struct B1 {
+ virtual B1 &foo1();
+ };
+ struct Pad1 {
+ virtual ~Pad1();
+ };
+ struct Proxy1 : Pad1, B1 {
+ virtual ~Proxy1();
+ };
+ struct D : virtual Proxy1 {
+ virtual ~D();
+ virtual D &foo1();
+ };
+// CHECK-DAG: DISubprogram{{.*}}linkageName: "?foo1@D@Test9@@$4PPPPPPPE@A@EAAAEAUB1@2@XZ"{{.*}} flags: {{.*}}DIFlagThunk
+// CHECK-DAG: DISubprogram{{.*}}linkageName: "?foo1@D@Test9@@$4PPPPPPPE@A@EAAAEAU12@XZ"{{.*}} flags: {{.*}}DIFlagThunk
+ D& D::foo1() {
+ return *this;
+ }
+}
+
+namespace Test10 {
+ class A {
+ virtual void f();
+ };
+ class B {
+ virtual void f();
+ };
+ class C : public A, public B {
+ virtual void f();
+ };
+// CHECK-DAG: DISubprogram{{.*}}linkageName: "?f@C@Test10@@G7EAAXXZ"{{.*}} flags: {{.*}}DIFlagThunk
+ void C::f() {
+ }
+}
+
+namespace Test11 {
+ class A {
+ public:
+ virtual void f();
+ };
+
+ void test() {
+// CHECK-DAG: DISubprogram{{.*}}linkageName: "??_9A@Test11@@$BA@AA"{{.*}} flags: {{.*}}DIFlagThunk
+ void (A::*p)() = &A::f;
+ }
+}
+
+namespace Test12 {
+ struct A {
+ virtual void f();
+ };
+
+ struct B {
+ virtual void f();
+ };
+
+ struct C : A, B {
+ virtual void f();
+ };
+
+ void C::f() { }
+ // ITANIUM: define {{.*}}void @_ZThn{{[48]}}_N6Test121C1fEv
+ // ITANIUM-SAME: !dbg ![[SP:[0-9]+]]
+ // ITANIUM-NOT: {{ret }}
+ // ITANIUM: = load{{.*}} !dbg ![[DBG:[0-9]+]]
+ // ITANIUM-NOT: {{ret }}
+ // ITANIUM: ret void, !dbg ![[DBG]]
+ //
+ // ITANIUM: ![[SP]] = distinct !DISubprogram(linkageName: "_ZThn{{[48]}}_N6Test121C1fEv"
+ // ITANIUM-SAME: line: 261
+ // ITANIUM-SAME: isDefinition: true
+ // ITANIUM-SAME: DIFlagArtificial
+ // ITANIUM-SAME: DIFlagThunk
+ // ITANIUM-SAME: ){{$}}
+ //
+ // ITANIUM: ![[DBG]] = !DILocation(line: 0
+}
diff --git a/test/CodeGenCXX/debug-info-vla.cpp b/test/CodeGenCXX/debug-info-vla.cpp
index 88f3a3f55dab..6c35f301f968 100644
--- a/test/CodeGenCXX/debug-info-vla.cpp
+++ b/test/CodeGenCXX/debug-info-vla.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang -target x86_64-unknown-unknown -fverbose-asm -g -O0 -S -emit-llvm %s -o - -std=c++11 | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -std=c++11 -triple x86_64-unknown-unknown %s -o - | FileCheck %s
void f(int m) {
@@ -13,8 +13,10 @@ int (*fp)(int[][*]) = nullptr;
// CHECK: [[ELEM_TYPE]] = !{[[NOCOUNT:.*]]}
// CHECK: [[NOCOUNT]] = !DISubrange(count: -1)
//
+// CHECK: [[VAR:![0-9]+]] = !DILocalVariable(name: "__vla_expr", {{.*}}flags: DIFlagArtificial
// CHECK: !DICompositeType(tag: DW_TAG_array_type,
// CHECK-NOT: size:
// CHECK-SAME: elements: [[ELEM_TYPE:![0-9]+]]
-// CHECK: [[ELEM_TYPE]] = !{[[THREE:.*]], [[NOCOUNT]]}
+// CHECK: [[ELEM_TYPE]] = !{[[THREE:.*]], [[VARRANGE:![0-9]+]]}
// CHECK: [[THREE]] = !DISubrange(count: 3)
+// CHECK: [[VARRANGE]] = !DISubrange(count: [[VAR]])
diff --git a/test/CodeGenCXX/debug-info-windows-dtor.cpp b/test/CodeGenCXX/debug-info-windows-dtor.cpp
index 8eb744a61bc7..0b3d7e17e3fa 100644
--- a/test/CodeGenCXX/debug-info-windows-dtor.cpp
+++ b/test/CodeGenCXX/debug-info-windows-dtor.cpp
@@ -14,8 +14,8 @@ struct AB: A, B {
template struct AB<int>;
-// CHECK: define {{.*}}@"\01??_E?$AB@H@@W3AEPAXI@Z"({{.*}} !dbg [[THUNK_VEC_DEL_DTOR:![0-9]*]]
-// CHECK: call {{.*}}@"\01??_G?$AB@H@@UAEPAXI@Z"({{.*}}) #{{[0-9]*}}, !dbg [[THUNK_LOC:![0-9]*]]
+// CHECK: define {{.*}}@"??_E?$AB@H@@W3AEPAXI@Z"({{.*}} !dbg [[THUNK_VEC_DEL_DTOR:![0-9]*]]
+// CHECK: call {{.*}}@"??_G?$AB@H@@UAEPAXI@Z"({{.*}}) #{{[0-9]*}}, !dbg [[THUNK_LOC:![0-9]*]]
// CHECK: define
// CHECK: [[THUNK_VEC_DEL_DTOR]] = distinct !DISubprogram
diff --git a/test/CodeGenCXX/delayed-template-parsing.cpp b/test/CodeGenCXX/delayed-template-parsing.cpp
index c5f448641544..c0e9425d5184 100644
--- a/test/CodeGenCXX/delayed-template-parsing.cpp
+++ b/test/CodeGenCXX/delayed-template-parsing.cpp
@@ -11,8 +11,8 @@ namespace ClassScopeSpecialization {
void call() {
Type T;
-// CHECK: call {{.*}} @"\01??$Foo@$0A@@Type@ClassScopeSpecialization@@QAEXXZ"
-// X64: call {{.*}} @"\01??$Foo@$0A@@Type@ClassScopeSpecialization@@QEAAXXZ"
+// CHECK: call {{.*}} @"??$Foo@$0A@@Type@ClassScopeSpecialization@@QAEXXZ"
+// X64: call {{.*}} @"??$Foo@$0A@@Type@ClassScopeSpecialization@@QEAAXXZ"
T.Foo<0>();
}
}
diff --git a/test/CodeGenCXX/derived-cast.cpp b/test/CodeGenCXX/derived-cast.cpp
new file mode 100644
index 000000000000..bf2b258c5e9f
--- /dev/null
+++ b/test/CodeGenCXX/derived-cast.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck %s
+
+class A {
+ int a;
+};
+
+class B {
+ int b;
+public:
+ A *getAsA();
+};
+
+class X : public A, public B {
+ int x;
+};
+
+// PR35909 - https://bugs.llvm.org/show_bug.cgi?id=35909
+
+A *B::getAsA() {
+ return static_cast<X*>(this);
+
+ // CHECK-LABEL: define %class.A* @_ZN1B6getAsAEv
+ // CHECK: %[[THIS:.*]] = load %class.B*, %class.B**
+ // CHECK-NEXT: %[[BC:.*]] = bitcast %class.B* %[[THIS]] to i8*
+ // CHECK-NEXT: getelementptr inbounds i8, i8* %[[BC]], i64 -4
+}
+
diff --git a/test/CodeGenCXX/destructors.cpp b/test/CodeGenCXX/destructors.cpp
index 180e82de9fff..ba8333b00dd6 100644
--- a/test/CodeGenCXX/destructors.cpp
+++ b/test/CodeGenCXX/destructors.cpp
@@ -96,7 +96,7 @@ namespace test0 {
// complete destructor alias tested above
-// CHECK2-LABEL: @_ZN5test01AD1Ev = alias {{.*}} @_ZN5test01AD2Ev
+// CHECK2-LABEL: @_ZN5test01AD1Ev = unnamed_addr alias {{.*}} @_ZN5test01AD2Ev
// CHECK2-LABEL: define void @_ZN5test01AD2Ev(%"struct.test0::A"* %this) unnamed_addr
// CHECK2: invoke void @_ZN5test06MemberD1Ev
// CHECK2: unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]]
@@ -104,7 +104,7 @@ namespace test0 {
// CHECK2: unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]]
// In C++11, the destructors are often known not to throw.
-// CHECK2v11-LABEL: @_ZN5test01AD1Ev = alias {{.*}} @_ZN5test01AD2Ev
+// CHECK2v11-LABEL: @_ZN5test01AD1Ev = unnamed_addr alias {{.*}} @_ZN5test01AD2Ev
// CHECK2v11-LABEL: define void @_ZN5test01AD2Ev(%"struct.test0::A"* %this) unnamed_addr
// CHECK2v11: call void @_ZN5test06MemberD1Ev
// CHECK2v11: call void @_ZN5test04BaseD2Ev
@@ -153,15 +153,15 @@ namespace test1 {
struct M : A { ~M(); };
M::~M() {}
- // CHECK3: @_ZN5test11MD2Ev = alias {{.*}} @_ZN5test11AD2Ev
+ // CHECK3: @_ZN5test11MD2Ev = unnamed_addr alias {{.*}} @_ZN5test11AD2Ev
struct N : A, Empty { ~N(); };
N::~N() {}
- // CHECK3: @_ZN5test11ND2Ev = alias {{.*}} @_ZN5test11AD2Ev
+ // CHECK3: @_ZN5test11ND2Ev = unnamed_addr alias {{.*}} @_ZN5test11AD2Ev
struct O : Empty, A { ~O(); };
O::~O() {}
- // CHECK3: @_ZN5test11OD2Ev = alias {{.*}} @_ZN5test11AD2Ev
+ // CHECK3: @_ZN5test11OD2Ev = unnamed_addr alias {{.*}} @_ZN5test11AD2Ev
struct P : NonEmpty, A { ~P(); };
P::~P() {} // CHECK3-LABEL: define void @_ZN5test11PD2Ev(%"struct.test1::P"* %this) unnamed_addr
@@ -174,7 +174,7 @@ namespace test1 {
struct S : A { ~S(); int x; };
S::~S() {}
- // CHECK4: @_ZN5test11SD2Ev = alias {{.*}}, bitcast {{.*}} @_ZN5test11AD2Ev
+ // CHECK4: @_ZN5test11SD2Ev = unnamed_addr alias {{.*}}, bitcast {{.*}} @_ZN5test11AD2Ev
struct T : A { ~T(); B x; };
T::~T() {} // CHECK4-LABEL: define void @_ZN5test11TD2Ev(%"struct.test1::T"* %this) unnamed_addr
diff --git a/test/CodeGenCXX/devirtualize-ms-dtor.cpp b/test/CodeGenCXX/devirtualize-ms-dtor.cpp
new file mode 100644
index 000000000000..d999b0c2dc40
--- /dev/null
+++ b/test/CodeGenCXX/devirtualize-ms-dtor.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-msvc %s -emit-llvm -o - | FileCheck %s
+
+// If we de-virtualize ~Foo, we still need to call ??1Foo, not ??_DFoo.
+
+struct Base {
+ virtual ~Base();
+};
+struct Foo final : Base {
+};
+void f(Foo *p) {
+ p->~Foo();
+}
+
+// CHECK-LABEL: define{{.*}} void @"?f@@YAXPEAUFoo@@@Z"(%struct.Foo* %p)
+// CHECK: call void @"??1Foo@@UEAA@XZ"
+// CHECK: ret void
diff --git a/test/CodeGenCXX/discard-name-values.cpp b/test/CodeGenCXX/discard-name-values.cpp
index 49cb7d2fc058..d4d7527c2856 100644
--- a/test/CodeGenCXX/discard-name-values.cpp
+++ b/test/CodeGenCXX/discard-name-values.cpp
@@ -1,10 +1,29 @@
-// RUN: %clang_cc1 -emit-llvm -triple=armv7-apple-darwin -emit-llvm -std=c++11 %s -o - -O1 | FileCheck %s
-// RUN: %clang_cc1 -emit-llvm -triple=armv7-apple-darwin -emit-llvm -std=c++11 %s -o - -O1 -discard-value-names | FileCheck %s --check-prefix=DISCARDVALUE
+// RUN: %clang_cc1 -emit-llvm -triple=armv7-apple-darwin -std=c++11 %s -o - -O1 \
+// RUN: | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -triple=armv7-apple-darwin -std=c++11 %s -o - -O1 \
+// RUN: -discard-value-names | FileCheck %s --check-prefix=DISCARDVALUE
-int foo(int bar) {
- return bar;
-}
+extern "C" void branch();
+
+bool test(bool pred) {
+ // DISCARDVALUE: br i1 %0, label %2, label %3
+ // CHECK: br i1 %pred, label %if.then, label %if.end
+
+ if (pred) {
+ // DISCARDVALUE: ; <label>:2:
+ // DISCARDVALUE-NEXT: tail call void @branch()
+ // DISCARDVALUE-NEXT: br label %3
-// CHECK: ret i32 %bar
-// DISCARDVALUE: ret i32 %0
+ // CHECK: if.then:
+ // CHECK-NEXT: tail call void @branch()
+ // CHECK-NEXT: br label %if.end
+ branch();
+ }
+ // DISCARDVALUE: ; <label>:3:
+ // DISCARDVALUE-NEXT: ret i1 %0
+
+ // CHECK: if.end:
+ // CHECK-NEXT: ret i1 %pred
+ return pred;
+}
diff --git a/test/CodeGenCXX/dllexport-alias.cpp b/test/CodeGenCXX/dllexport-alias.cpp
index a3dc61edde5d..7eec9cf78388 100644
--- a/test/CodeGenCXX/dllexport-alias.cpp
+++ b/test/CodeGenCXX/dllexport-alias.cpp
@@ -14,5 +14,5 @@ A::A() {}
A::~A() {}
-// CHECK: @_ZN1AC1Ev = dllexport alias void (%class.A*), void (%class.A*)* @_ZN1AC2Ev
-// CHECK: @_ZN1AD1Ev = dllexport alias void (%class.A*), void (%class.A*)* @_ZN1AD2Ev
+// CHECK: @_ZN1AC1Ev = dso_local dllexport unnamed_addr alias void (%class.A*), void (%class.A*)* @_ZN1AC2Ev
+// CHECK: @_ZN1AD1Ev = dso_local dllexport unnamed_addr alias void (%class.A*), void (%class.A*)* @_ZN1AD2Ev
diff --git a/test/CodeGenCXX/dllexport-ctor-closure.cpp b/test/CodeGenCXX/dllexport-ctor-closure.cpp
index 4fae7e10e8b6..72d674dae7c0 100644
--- a/test/CodeGenCXX/dllexport-ctor-closure.cpp
+++ b/test/CodeGenCXX/dllexport-ctor-closure.cpp
@@ -5,11 +5,11 @@
struct CtorWithClosure {
__declspec(dllexport) CtorWithClosure(...) {}
-// CHECK-LABEL: define weak_odr dllexport x86_thiscallcc void @"\01??_FCtorWithClosure@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
+// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"??_FCtorWithClosure@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
// CHECK: %[[this_addr:.*]] = alloca %struct.CtorWithClosure*, align 4
// CHECK: store %struct.CtorWithClosure* %this, %struct.CtorWithClosure** %[[this_addr]], align 4
// CHECK: %[[this:.*]] = load %struct.CtorWithClosure*, %struct.CtorWithClosure** %[[this_addr]]
-// CHECK: call %struct.CtorWithClosure* (%struct.CtorWithClosure*, ...) @"\01??0CtorWithClosure@@QAA@ZZ"(%struct.CtorWithClosure* %[[this]])
+// CHECK: call %struct.CtorWithClosure* (%struct.CtorWithClosure*, ...) @"??0CtorWithClosure@@QAA@ZZ"(%struct.CtorWithClosure* %[[this]])
// CHECK: ret void
};
@@ -17,7 +17,7 @@ struct CtorWithClosureOutOfLine {
__declspec(dllexport) CtorWithClosureOutOfLine(...);
};
CtorWithClosureOutOfLine::CtorWithClosureOutOfLine(...) {}
-// CHECK-LABEL: define weak_odr dllexport x86_thiscallcc void @"\01??_FCtorWithClosureOutOfLine@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
+// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"??_FCtorWithClosureOutOfLine@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
#define DELETE_IMPLICIT_MEMBERS(ClassName) \
ClassName(ClassName &&) = delete; \
@@ -28,11 +28,11 @@ CtorWithClosureOutOfLine::CtorWithClosureOutOfLine(...) {}
struct __declspec(dllexport) ClassWithClosure {
DELETE_IMPLICIT_MEMBERS(ClassWithClosure);
ClassWithClosure(...) {}
-// CHECK-LABEL: define weak_odr dllexport x86_thiscallcc void @"\01??_FClassWithClosure@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
+// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"??_FClassWithClosure@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
// CHECK: %[[this_addr:.*]] = alloca %struct.ClassWithClosure*, align 4
// CHECK: store %struct.ClassWithClosure* %this, %struct.ClassWithClosure** %[[this_addr]], align 4
// CHECK: %[[this:.*]] = load %struct.ClassWithClosure*, %struct.ClassWithClosure** %[[this_addr]]
-// CHECK: call %struct.ClassWithClosure* (%struct.ClassWithClosure*, ...) @"\01??0ClassWithClosure@@QAA@ZZ"(%struct.ClassWithClosure* %[[this]])
+// CHECK: call %struct.ClassWithClosure* (%struct.ClassWithClosure*, ...) @"??0ClassWithClosure@@QAA@ZZ"(%struct.ClassWithClosure* %[[this]])
// CHECK: ret void
};
@@ -44,11 +44,11 @@ template struct __declspec(dllexport) TemplateWithClosure<char>;
extern template struct TemplateWithClosure<int>;
template struct __declspec(dllexport) TemplateWithClosure<int>;
-// CHECK-LABEL: define weak_odr dllexport x86_thiscallcc void @"\01??_F?$TemplateWithClosure@D@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
-// CHECK: call {{.*}} @"\01??0?$TemplateWithClosure@D@@QAE@H@Z"({{.*}}, i32 1)
+// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"??_F?$TemplateWithClosure@D@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
+// CHECK: call {{.*}} @"??0?$TemplateWithClosure@D@@QAE@H@Z"({{.*}}, i32 1)
-// CHECK-LABEL: define weak_odr dllexport x86_thiscallcc void @"\01??_F?$TemplateWithClosure@H@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
-// CHECK: call {{.*}} @"\01??0?$TemplateWithClosure@H@@QAE@H@Z"({{.*}}, i32 4)
+// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"??_F?$TemplateWithClosure@H@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
+// CHECK: call {{.*}} @"??0?$TemplateWithClosure@H@@QAE@H@Z"({{.*}}, i32 4)
struct __declspec(dllexport) NestedOuter {
DELETE_IMPLICIT_MEMBERS(NestedOuter);
@@ -59,8 +59,8 @@ struct __declspec(dllexport) NestedOuter {
};
};
-// CHECK-LABEL: define weak_odr dllexport x86_thiscallcc void @"\01??_FNestedOuter@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
-// CHECK-LABEL: define weak_odr dllexport x86_thiscallcc void @"\01??_FNestedInner@NestedOuter@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
+// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"??_FNestedOuter@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
+// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"??_FNestedInner@NestedOuter@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
struct HasDtor {
~HasDtor();
@@ -76,7 +76,7 @@ struct __declspec(dllexport) CtorClosureOutOfLine {
};
CtorClosureOutOfLine::CtorClosureOutOfLine(const HasImplicitDtor2 &v) {}
-// CHECK-LABEL: define weak_odr dllexport x86_thiscallcc void @"\01??_FCtorClosureInline@@QAEXXZ"
-// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01??1HasImplicitDtor1@@QAE@XZ"
-// CHECK-LABEL: define weak_odr dllexport x86_thiscallcc void @"\01??_FCtorClosureOutOfLine@@QAEXXZ"
-// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01??1HasImplicitDtor2@@QAE@XZ"
+// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"??_FCtorClosureInline@@QAEXXZ"
+// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"??1HasImplicitDtor1@@QAE@XZ"
+// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"??_FCtorClosureOutOfLine@@QAEXXZ"
+// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"??1HasImplicitDtor2@@QAE@XZ"
diff --git a/test/CodeGenCXX/dllexport-dtor-thunks.cpp b/test/CodeGenCXX/dllexport-dtor-thunks.cpp
index 52f9901620fa..bda126eba855 100644
--- a/test/CodeGenCXX/dllexport-dtor-thunks.cpp
+++ b/test/CodeGenCXX/dllexport-dtor-thunks.cpp
@@ -5,6 +5,6 @@ struct __declspec(dllexport) B { virtual ~B(); };
struct __declspec(dllexport) C : A, B { virtual ~C(); };
C::~C() {}
+// CHECK: define dso_local dllexport void @"??1C@@UEAA@XZ"
// This thunk should *not* be dllexport.
-// CHECK: define linkonce_odr i8* @"\01??_EC@@W7EAAPEAXI@Z"
-// CHECK: define dllexport void @"\01??1C@@UEAA@XZ"
+// CHECK: define linkonce_odr dso_local i8* @"??_EC@@W7EAAPEAXI@Z"
diff --git a/test/CodeGenCXX/dllexport-members.cpp b/test/CodeGenCXX/dllexport-members.cpp
index 1c56251328d6..b0275384022e 100644
--- a/test/CodeGenCXX/dllexport-members.cpp
+++ b/test/CodeGenCXX/dllexport-members.cpp
@@ -26,101 +26,101 @@ extern "C" void free(void* p);
struct ExportMembers {
struct Nested;
- // M32-DAG: define dllexport x86_thiscallcc void @"\01?normalDef@ExportMembers@@QAEXXZ"(%struct.ExportMembers* %this)
- // M64-DAG: define dllexport void @"\01?normalDef@ExportMembers@@QEAAXXZ"(%struct.ExportMembers* %this)
- // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?normalInclass@ExportMembers@@QAEXXZ"(%struct.ExportMembers* %this)
- // M64-DAG: define weak_odr dllexport void @"\01?normalInclass@ExportMembers@@QEAAXXZ"(%struct.ExportMembers* %this)
- // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?normalInlineDef@ExportMembers@@QAEXXZ"(%struct.ExportMembers* %this)
- // M64-DAG: define weak_odr dllexport void @"\01?normalInlineDef@ExportMembers@@QEAAXXZ"(%struct.ExportMembers* %this)
- // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?normalInlineDecl@ExportMembers@@QAEXXZ"(%struct.ExportMembers* %this)
- // M64-DAG: define weak_odr dllexport void @"\01?normalInlineDecl@ExportMembers@@QEAAXXZ"(%struct.ExportMembers* %this)
- // G32-DAG: define dllexport x86_thiscallcc void @_ZN13ExportMembers9normalDefEv(%struct.ExportMembers* %this)
- // G64-DAG: define dllexport void @_ZN13ExportMembers9normalDefEv(%struct.ExportMembers* %this)
- // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers13normalInclassEv(%struct.ExportMembers* %this)
- // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers13normalInclassEv(%struct.ExportMembers* %this)
- // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers15normalInlineDefEv(%struct.ExportMembers* %this)
- // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers15normalInlineDefEv(%struct.ExportMembers* %this)
- // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers16normalInlineDeclEv(%struct.ExportMembers* %this)
- // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers16normalInlineDeclEv(%struct.ExportMembers* %this)
- // M32-DAG: define linkonce_odr x86_thiscallcc void @"\01?referencedNonExportedInClass@ExportMembers@@QAEXXZ"
+ // M32-DAG: define dso_local dllexport x86_thiscallcc void @"?normalDef@ExportMembers@@QAEXXZ"(%struct.ExportMembers* %this)
+ // M64-DAG: define dso_local dllexport void @"?normalDef@ExportMembers@@QEAAXXZ"(%struct.ExportMembers* %this)
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?normalInclass@ExportMembers@@QAEXXZ"(%struct.ExportMembers* %this)
+ // M64-DAG: define weak_odr dso_local dllexport void @"?normalInclass@ExportMembers@@QEAAXXZ"(%struct.ExportMembers* %this)
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?normalInlineDef@ExportMembers@@QAEXXZ"(%struct.ExportMembers* %this)
+ // M64-DAG: define weak_odr dso_local dllexport void @"?normalInlineDef@ExportMembers@@QEAAXXZ"(%struct.ExportMembers* %this)
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?normalInlineDecl@ExportMembers@@QAEXXZ"(%struct.ExportMembers* %this)
+ // M64-DAG: define weak_odr dso_local dllexport void @"?normalInlineDecl@ExportMembers@@QEAAXXZ"(%struct.ExportMembers* %this)
+ // G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN13ExportMembers9normalDefEv(%struct.ExportMembers* %this)
+ // G64-DAG: define dso_local dllexport void @_ZN13ExportMembers9normalDefEv(%struct.ExportMembers* %this)
+ // G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN13ExportMembers13normalInclassEv(%struct.ExportMembers* %this)
+ // G64-DAG: define weak_odr dso_local dllexport void @_ZN13ExportMembers13normalInclassEv(%struct.ExportMembers* %this)
+ // G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN13ExportMembers15normalInlineDefEv(%struct.ExportMembers* %this)
+ // G64-DAG: define weak_odr dso_local dllexport void @_ZN13ExportMembers15normalInlineDefEv(%struct.ExportMembers* %this)
+ // G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN13ExportMembers16normalInlineDeclEv(%struct.ExportMembers* %this)
+ // G64-DAG: define weak_odr dso_local dllexport void @_ZN13ExportMembers16normalInlineDeclEv(%struct.ExportMembers* %this)
+ // M32-DAG: define linkonce_odr dso_local x86_thiscallcc void @"?referencedNonExportedInClass@ExportMembers@@QAEXXZ"
__declspec(dllexport) void normalDef();
__declspec(dllexport) void normalInclass() { referencedNonExportedInClass(); }
__declspec(dllexport) void normalInlineDef();
__declspec(dllexport) inline void normalInlineDecl();
void referencedNonExportedInClass() {}
- // M32-DAG: define dllexport x86_thiscallcc void @"\01?virtualDef@ExportMembers@@UAEXXZ"(%struct.ExportMembers* %this)
- // M64-DAG: define dllexport void @"\01?virtualDef@ExportMembers@@UEAAXXZ"(%struct.ExportMembers* %this)
- // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?virtualInclass@ExportMembers@@UAEXXZ"(%struct.ExportMembers* %this)
- // M64-DAG: define weak_odr dllexport void @"\01?virtualInclass@ExportMembers@@UEAAXXZ"(%struct.ExportMembers* %this)
- // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?virtualInlineDef@ExportMembers@@UAEXXZ"(%struct.ExportMembers* %this)
- // M64-DAG: define weak_odr dllexport void @"\01?virtualInlineDef@ExportMembers@@UEAAXXZ"(%struct.ExportMembers* %this)
- // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?virtualInlineDecl@ExportMembers@@UAEXXZ"(%struct.ExportMembers* %this)
- // M64-DAG: define weak_odr dllexport void @"\01?virtualInlineDecl@ExportMembers@@UEAAXXZ"(%struct.ExportMembers* %this)
- // G32-DAG: define dllexport x86_thiscallcc void @_ZN13ExportMembers10virtualDefEv(%struct.ExportMembers* %this)
- // G64-DAG: define dllexport void @_ZN13ExportMembers10virtualDefEv(%struct.ExportMembers* %this)
- // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers14virtualInclassEv(%struct.ExportMembers* %this)
- // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers14virtualInclassEv(%struct.ExportMembers* %this)
- // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers16virtualInlineDefEv(%struct.ExportMembers* %this)
- // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers16virtualInlineDefEv(%struct.ExportMembers* %this)
- // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers17virtualInlineDeclEv(%struct.ExportMembers* %this)
- // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers17virtualInlineDeclEv(%struct.ExportMembers* %this)
+ // M32-DAG: define dso_local dllexport x86_thiscallcc void @"?virtualDef@ExportMembers@@UAEXXZ"(%struct.ExportMembers* %this)
+ // M64-DAG: define dso_local dllexport void @"?virtualDef@ExportMembers@@UEAAXXZ"(%struct.ExportMembers* %this)
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?virtualInclass@ExportMembers@@UAEXXZ"(%struct.ExportMembers* %this)
+ // M64-DAG: define weak_odr dso_local dllexport void @"?virtualInclass@ExportMembers@@UEAAXXZ"(%struct.ExportMembers* %this)
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?virtualInlineDef@ExportMembers@@UAEXXZ"(%struct.ExportMembers* %this)
+ // M64-DAG: define weak_odr dso_local dllexport void @"?virtualInlineDef@ExportMembers@@UEAAXXZ"(%struct.ExportMembers* %this)
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?virtualInlineDecl@ExportMembers@@UAEXXZ"(%struct.ExportMembers* %this)
+ // M64-DAG: define weak_odr dso_local dllexport void @"?virtualInlineDecl@ExportMembers@@UEAAXXZ"(%struct.ExportMembers* %this)
+ // G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN13ExportMembers10virtualDefEv(%struct.ExportMembers* %this)
+ // G64-DAG: define dso_local dllexport void @_ZN13ExportMembers10virtualDefEv(%struct.ExportMembers* %this)
+ // G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN13ExportMembers14virtualInclassEv(%struct.ExportMembers* %this)
+ // G64-DAG: define weak_odr dso_local dllexport void @_ZN13ExportMembers14virtualInclassEv(%struct.ExportMembers* %this)
+ // G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN13ExportMembers16virtualInlineDefEv(%struct.ExportMembers* %this)
+ // G64-DAG: define weak_odr dso_local dllexport void @_ZN13ExportMembers16virtualInlineDefEv(%struct.ExportMembers* %this)
+ // G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN13ExportMembers17virtualInlineDeclEv(%struct.ExportMembers* %this)
+ // G64-DAG: define weak_odr dso_local dllexport void @_ZN13ExportMembers17virtualInlineDeclEv(%struct.ExportMembers* %this)
__declspec(dllexport) virtual void virtualDef();
__declspec(dllexport) virtual void virtualInclass() {}
__declspec(dllexport) virtual void virtualInlineDef();
__declspec(dllexport) virtual inline void virtualInlineDecl();
- // MSC-DAG: define dllexport void @"\01?staticDef@ExportMembers@@SAXXZ"()
- // MSC-DAG: define weak_odr dllexport void @"\01?staticInclass@ExportMembers@@SAXXZ"()
- // MSC-DAG: define weak_odr dllexport void @"\01?staticInlineDef@ExportMembers@@SAXXZ"()
- // MSC-DAG: define weak_odr dllexport void @"\01?staticInlineDecl@ExportMembers@@SAXXZ"()
- // GNU-DAG: define dllexport void @_ZN13ExportMembers9staticDefEv()
- // GNU-DAG: define weak_odr dllexport void @_ZN13ExportMembers13staticInclassEv()
- // GNU-DAG: define weak_odr dllexport void @_ZN13ExportMembers15staticInlineDefEv()
- // GNU-DAG: define weak_odr dllexport void @_ZN13ExportMembers16staticInlineDeclEv()
+ // MSC-DAG: define dso_local dllexport void @"?staticDef@ExportMembers@@SAXXZ"()
+ // MSC-DAG: define weak_odr dso_local dllexport void @"?staticInclass@ExportMembers@@SAXXZ"()
+ // MSC-DAG: define weak_odr dso_local dllexport void @"?staticInlineDef@ExportMembers@@SAXXZ"()
+ // MSC-DAG: define weak_odr dso_local dllexport void @"?staticInlineDecl@ExportMembers@@SAXXZ"()
+ // GNU-DAG: define dso_local dllexport void @_ZN13ExportMembers9staticDefEv()
+ // GNU-DAG: define weak_odr dso_local dllexport void @_ZN13ExportMembers13staticInclassEv()
+ // GNU-DAG: define weak_odr dso_local dllexport void @_ZN13ExportMembers15staticInlineDefEv()
+ // GNU-DAG: define weak_odr dso_local dllexport void @_ZN13ExportMembers16staticInlineDeclEv()
__declspec(dllexport) static void staticDef();
__declspec(dllexport) static void staticInclass() {}
__declspec(dllexport) static void staticInlineDef();
__declspec(dllexport) static inline void staticInlineDecl();
- // M32-DAG: define dllexport x86_thiscallcc void @"\01?protectedDef@ExportMembers@@IAEXXZ"(%struct.ExportMembers* %this)
- // M64-DAG: define dllexport void @"\01?protectedDef@ExportMembers@@IEAAXXZ"(%struct.ExportMembers* %this)
- // G32-DAG: define dllexport x86_thiscallcc void @_ZN13ExportMembers12protectedDefEv(%struct.ExportMembers* %this)
- // G64-DAG: define dllexport void @_ZN13ExportMembers12protectedDefEv(%struct.ExportMembers* %this)
- // MSC-DAG: define dllexport void @"\01?protectedStaticDef@ExportMembers@@KAXXZ"()
- // GNU-DAG: define dllexport void @_ZN13ExportMembers18protectedStaticDefEv()
+ // M32-DAG: define dso_local dllexport x86_thiscallcc void @"?protectedDef@ExportMembers@@IAEXXZ"(%struct.ExportMembers* %this)
+ // M64-DAG: define dso_local dllexport void @"?protectedDef@ExportMembers@@IEAAXXZ"(%struct.ExportMembers* %this)
+ // G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN13ExportMembers12protectedDefEv(%struct.ExportMembers* %this)
+ // G64-DAG: define dso_local dllexport void @_ZN13ExportMembers12protectedDefEv(%struct.ExportMembers* %this)
+ // MSC-DAG: define dso_local dllexport void @"?protectedStaticDef@ExportMembers@@KAXXZ"()
+ // GNU-DAG: define dso_local dllexport void @_ZN13ExportMembers18protectedStaticDefEv()
protected:
__declspec(dllexport) void protectedDef();
__declspec(dllexport) static void protectedStaticDef();
- // M32-DAG: define dllexport x86_thiscallcc void @"\01?privateDef@ExportMembers@@AAEXXZ"(%struct.ExportMembers* %this)
- // M64-DAG: define dllexport void @"\01?privateDef@ExportMembers@@AEAAXXZ"(%struct.ExportMembers* %this)
- // G32-DAG: define dllexport x86_thiscallcc void @_ZN13ExportMembers10privateDefEv(%struct.ExportMembers* %this)
- // G64-DAG: define dllexport void @_ZN13ExportMembers10privateDefEv(%struct.ExportMembers* %this)
- // MSC-DAG: define dllexport void @"\01?privateStaticDef@ExportMembers@@CAXXZ"()
- // GNU-DAG: define dllexport void @_ZN13ExportMembers16privateStaticDefEv()
+ // M32-DAG: define dso_local dllexport x86_thiscallcc void @"?privateDef@ExportMembers@@AAEXXZ"(%struct.ExportMembers* %this)
+ // M64-DAG: define dso_local dllexport void @"?privateDef@ExportMembers@@AEAAXXZ"(%struct.ExportMembers* %this)
+ // G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN13ExportMembers10privateDefEv(%struct.ExportMembers* %this)
+ // G64-DAG: define dso_local dllexport void @_ZN13ExportMembers10privateDefEv(%struct.ExportMembers* %this)
+ // MSC-DAG: define dso_local dllexport void @"?privateStaticDef@ExportMembers@@CAXXZ"()
+ // GNU-DAG: define dso_local dllexport void @_ZN13ExportMembers16privateStaticDefEv()
private:
__declspec(dllexport) void privateDef();
__declspec(dllexport) static void privateStaticDef();
- // M32-DAG: define x86_thiscallcc void @"\01?ignored@ExportMembers@@QAEXXZ"(%struct.ExportMembers* %this)
- // M64-DAG: define void @"\01?ignored@ExportMembers@@QEAAXXZ"(%struct.ExportMembers* %this)
- // G32-DAG: define x86_thiscallcc void @_ZN13ExportMembers7ignoredEv(%struct.ExportMembers* %this)
- // G64-DAG: define void @_ZN13ExportMembers7ignoredEv(%struct.ExportMembers* %this)
+ // M32-DAG: define dso_local x86_thiscallcc void @"?ignored@ExportMembers@@QAEXXZ"(%struct.ExportMembers* %this)
+ // M64-DAG: define dso_local void @"?ignored@ExportMembers@@QEAAXXZ"(%struct.ExportMembers* %this)
+ // G32-DAG: define dso_local x86_thiscallcc void @_ZN13ExportMembers7ignoredEv(%struct.ExportMembers* %this)
+ // G64-DAG: define dso_local void @_ZN13ExportMembers7ignoredEv(%struct.ExportMembers* %this)
public:
void ignored();
- // MSC-DAG: @"\01?StaticField@ExportMembers@@2HA" = dllexport global i32 1, align 4
- // MSC-DAG: @"\01?StaticConstField@ExportMembers@@2HB" = dllexport constant i32 1, align 4
- // MSC-DAG: @"\01?StaticConstFieldEqualInit@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4
- // MSC-DAG: @"\01?StaticConstFieldBraceInit@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4
- // MSC-DAG: @"\01?StaticConstFieldRefNotDef@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4
- // MSC-DAG: @"\01?ConstexprField@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4
- // GNU-DAG: @_ZN13ExportMembers11StaticFieldE = dllexport global i32 1, align 4
- // GNU-DAG: @_ZN13ExportMembers16StaticConstFieldE = dllexport constant i32 1, align 4
- // GNU-DAG: @_ZN13ExportMembers25StaticConstFieldEqualInitE = dllexport constant i32 1, align 4
- // GNU-DAG: @_ZN13ExportMembers25StaticConstFieldBraceInitE = dllexport constant i32 1, align 4
- // GNU-DAG: @_ZN13ExportMembers14ConstexprFieldE = dllexport constant i32 1, align 4
+ // MSC-DAG: @"?StaticField@ExportMembers@@2HA" = dso_local dllexport global i32 1, align 4
+ // MSC-DAG: @"?StaticConstField@ExportMembers@@2HB" = dso_local dllexport constant i32 1, align 4
+ // MSC-DAG: @"?StaticConstFieldEqualInit@ExportMembers@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
+ // MSC-DAG: @"?StaticConstFieldBraceInit@ExportMembers@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
+ // MSC-DAG: @"?StaticConstFieldRefNotDef@ExportMembers@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
+ // MSC-DAG: @"?ConstexprField@ExportMembers@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
+ // GNU-DAG: @_ZN13ExportMembers11StaticFieldE = dso_local dllexport global i32 1, align 4
+ // GNU-DAG: @_ZN13ExportMembers16StaticConstFieldE = dso_local dllexport constant i32 1, align 4
+ // GNU-DAG: @_ZN13ExportMembers25StaticConstFieldEqualInitE = dso_local dllexport constant i32 1, align 4
+ // GNU-DAG: @_ZN13ExportMembers25StaticConstFieldBraceInitE = dso_local dllexport constant i32 1, align 4
+ // GNU-DAG: @_ZN13ExportMembers14ConstexprFieldE = dso_local dllexport constant i32 1, align 4
__declspec(dllexport) static int StaticField;
__declspec(dllexport) static const int StaticConstField;
__declspec(dllexport) static const int StaticConstFieldEqualInit = 1;
@@ -154,99 +154,99 @@ constexpr int ExportMembers::ConstexprField;
// Export individual members of a nested class.
struct ExportMembers::Nested {
- // M32-DAG: define dllexport x86_thiscallcc void @"\01?normalDef@Nested@ExportMembers@@QAEXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M64-DAG: define dllexport void @"\01?normalDef@Nested@ExportMembers@@QEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?normalInclass@Nested@ExportMembers@@QAEXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M64-DAG: define weak_odr dllexport void @"\01?normalInclass@Nested@ExportMembers@@QEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?normalInlineDef@Nested@ExportMembers@@QAEXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M64-DAG: define weak_odr dllexport void @"\01?normalInlineDef@Nested@ExportMembers@@QEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?normalInlineDecl@Nested@ExportMembers@@QAEXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M64-DAG: define weak_odr dllexport void @"\01?normalInlineDecl@Nested@ExportMembers@@QEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
- // G32-DAG: define dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested9normalDefEv(%"struct.ExportMembers::Nested"* %this)
- // G64-DAG: define dllexport void @_ZN13ExportMembers6Nested9normalDefEv(%"struct.ExportMembers::Nested"* %this)
- // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested13normalInclassEv(%"struct.ExportMembers::Nested"* %this)
- // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers6Nested13normalInclassEv(%"struct.ExportMembers::Nested"* %this)
- // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested15normalInlineDefEv(%"struct.ExportMembers::Nested"* %this)
- // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers6Nested15normalInlineDefEv(%"struct.ExportMembers::Nested"* %this)
- // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested16normalInlineDeclEv(%"struct.ExportMembers::Nested"* %this)
- // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers6Nested16normalInlineDeclEv(%"struct.ExportMembers::Nested"* %this)
+ // M32-DAG: define dso_local dllexport x86_thiscallcc void @"?normalDef@Nested@ExportMembers@@QAEXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M64-DAG: define dso_local dllexport void @"?normalDef@Nested@ExportMembers@@QEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?normalInclass@Nested@ExportMembers@@QAEXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M64-DAG: define weak_odr dso_local dllexport void @"?normalInclass@Nested@ExportMembers@@QEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?normalInlineDef@Nested@ExportMembers@@QAEXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M64-DAG: define weak_odr dso_local dllexport void @"?normalInlineDef@Nested@ExportMembers@@QEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?normalInlineDecl@Nested@ExportMembers@@QAEXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M64-DAG: define weak_odr dso_local dllexport void @"?normalInlineDecl@Nested@ExportMembers@@QEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested9normalDefEv(%"struct.ExportMembers::Nested"* %this)
+ // G64-DAG: define dso_local dllexport void @_ZN13ExportMembers6Nested9normalDefEv(%"struct.ExportMembers::Nested"* %this)
+ // G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested13normalInclassEv(%"struct.ExportMembers::Nested"* %this)
+ // G64-DAG: define weak_odr dso_local dllexport void @_ZN13ExportMembers6Nested13normalInclassEv(%"struct.ExportMembers::Nested"* %this)
+ // G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested15normalInlineDefEv(%"struct.ExportMembers::Nested"* %this)
+ // G64-DAG: define weak_odr dso_local dllexport void @_ZN13ExportMembers6Nested15normalInlineDefEv(%"struct.ExportMembers::Nested"* %this)
+ // G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested16normalInlineDeclEv(%"struct.ExportMembers::Nested"* %this)
+ // G64-DAG: define weak_odr dso_local dllexport void @_ZN13ExportMembers6Nested16normalInlineDeclEv(%"struct.ExportMembers::Nested"* %this)
__declspec(dllexport) void normalDef();
__declspec(dllexport) void normalInclass() {}
__declspec(dllexport) void normalInlineDef();
__declspec(dllexport) inline void normalInlineDecl();
- // M32-DAG: define dllexport x86_thiscallcc void @"\01?virtualDef@Nested@ExportMembers@@UAEXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M64-DAG: define dllexport void @"\01?virtualDef@Nested@ExportMembers@@UEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?virtualInclass@Nested@ExportMembers@@UAEXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M64-DAG: define weak_odr dllexport void @"\01?virtualInclass@Nested@ExportMembers@@UEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?virtualInlineDef@Nested@ExportMembers@@UAEXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M64-DAG: define weak_odr dllexport void @"\01?virtualInlineDef@Nested@ExportMembers@@UEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?virtualInlineDecl@Nested@ExportMembers@@UAEXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M64-DAG: define weak_odr dllexport void @"\01?virtualInlineDecl@Nested@ExportMembers@@UEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
- // G32-DAG: define dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested10virtualDefEv(%"struct.ExportMembers::Nested"* %this)
- // G64-DAG: define dllexport void @_ZN13ExportMembers6Nested10virtualDefEv(%"struct.ExportMembers::Nested"* %this)
- // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested14virtualInclassEv(%"struct.ExportMembers::Nested"* %this)
- // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers6Nested14virtualInclassEv(%"struct.ExportMembers::Nested"* %this)
- // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested16virtualInlineDefEv(%"struct.ExportMembers::Nested"* %this)
- // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers6Nested16virtualInlineDefEv(%"struct.ExportMembers::Nested"* %this)
- // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested17virtualInlineDeclEv(%"struct.ExportMembers::Nested"* %this)
- // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers6Nested17virtualInlineDeclEv(%"struct.ExportMembers::Nested"* %this)
+ // M32-DAG: define dso_local dllexport x86_thiscallcc void @"?virtualDef@Nested@ExportMembers@@UAEXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M64-DAG: define dso_local dllexport void @"?virtualDef@Nested@ExportMembers@@UEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?virtualInclass@Nested@ExportMembers@@UAEXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M64-DAG: define weak_odr dso_local dllexport void @"?virtualInclass@Nested@ExportMembers@@UEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?virtualInlineDef@Nested@ExportMembers@@UAEXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M64-DAG: define weak_odr dso_local dllexport void @"?virtualInlineDef@Nested@ExportMembers@@UEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?virtualInlineDecl@Nested@ExportMembers@@UAEXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M64-DAG: define weak_odr dso_local dllexport void @"?virtualInlineDecl@Nested@ExportMembers@@UEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested10virtualDefEv(%"struct.ExportMembers::Nested"* %this)
+ // G64-DAG: define dso_local dllexport void @_ZN13ExportMembers6Nested10virtualDefEv(%"struct.ExportMembers::Nested"* %this)
+ // G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested14virtualInclassEv(%"struct.ExportMembers::Nested"* %this)
+ // G64-DAG: define weak_odr dso_local dllexport void @_ZN13ExportMembers6Nested14virtualInclassEv(%"struct.ExportMembers::Nested"* %this)
+ // G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested16virtualInlineDefEv(%"struct.ExportMembers::Nested"* %this)
+ // G64-DAG: define weak_odr dso_local dllexport void @_ZN13ExportMembers6Nested16virtualInlineDefEv(%"struct.ExportMembers::Nested"* %this)
+ // G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested17virtualInlineDeclEv(%"struct.ExportMembers::Nested"* %this)
+ // G64-DAG: define weak_odr dso_local dllexport void @_ZN13ExportMembers6Nested17virtualInlineDeclEv(%"struct.ExportMembers::Nested"* %this)
__declspec(dllexport) virtual void virtualDef();
__declspec(dllexport) virtual void virtualInclass() {}
__declspec(dllexport) virtual void virtualInlineDef();
__declspec(dllexport) virtual inline void virtualInlineDecl();
- // MSC-DAG: define dllexport void @"\01?staticDef@Nested@ExportMembers@@SAXXZ"()
- // MSC-DAG: define weak_odr dllexport void @"\01?staticInclass@Nested@ExportMembers@@SAXXZ"()
- // MSC-DAG: define weak_odr dllexport void @"\01?staticInlineDef@Nested@ExportMembers@@SAXXZ"()
- // MSC-DAG: define weak_odr dllexport void @"\01?staticInlineDecl@Nested@ExportMembers@@SAXXZ"()
- // GNU-DAG: define dllexport void @_ZN13ExportMembers6Nested9staticDefEv()
- // GNU-DAG: define weak_odr dllexport void @_ZN13ExportMembers6Nested13staticInclassEv()
- // GNU-DAG: define weak_odr dllexport void @_ZN13ExportMembers6Nested15staticInlineDefEv()
- // GNU-DAG: define weak_odr dllexport void @_ZN13ExportMembers6Nested16staticInlineDeclEv()
+ // MSC-DAG: define dso_local dllexport void @"?staticDef@Nested@ExportMembers@@SAXXZ"()
+ // MSC-DAG: define weak_odr dso_local dllexport void @"?staticInclass@Nested@ExportMembers@@SAXXZ"()
+ // MSC-DAG: define weak_odr dso_local dllexport void @"?staticInlineDef@Nested@ExportMembers@@SAXXZ"()
+ // MSC-DAG: define weak_odr dso_local dllexport void @"?staticInlineDecl@Nested@ExportMembers@@SAXXZ"()
+ // GNU-DAG: define dso_local dllexport void @_ZN13ExportMembers6Nested9staticDefEv()
+ // GNU-DAG: define weak_odr dso_local dllexport void @_ZN13ExportMembers6Nested13staticInclassEv()
+ // GNU-DAG: define weak_odr dso_local dllexport void @_ZN13ExportMembers6Nested15staticInlineDefEv()
+ // GNU-DAG: define weak_odr dso_local dllexport void @_ZN13ExportMembers6Nested16staticInlineDeclEv()
__declspec(dllexport) static void staticDef();
__declspec(dllexport) static void staticInclass() {}
__declspec(dllexport) static void staticInlineDef();
__declspec(dllexport) static inline void staticInlineDecl();
- // M32-DAG: define dllexport x86_thiscallcc void @"\01?protectedDef@Nested@ExportMembers@@IAEXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M64-DAG: define dllexport void @"\01?protectedDef@Nested@ExportMembers@@IEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
- // G32-DAG: define dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested12protectedDefEv(%"struct.ExportMembers::Nested"* %this)
- // G64-DAG: define dllexport void @_ZN13ExportMembers6Nested12protectedDefEv(%"struct.ExportMembers::Nested"* %this)
- // MSC-DAG: define dllexport void @"\01?protectedStaticDef@Nested@ExportMembers@@KAXXZ"()
- // GNU-DAG: define dllexport void @_ZN13ExportMembers6Nested18protectedStaticDefEv()
+ // M32-DAG: define dso_local dllexport x86_thiscallcc void @"?protectedDef@Nested@ExportMembers@@IAEXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M64-DAG: define dso_local dllexport void @"?protectedDef@Nested@ExportMembers@@IEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested12protectedDefEv(%"struct.ExportMembers::Nested"* %this)
+ // G64-DAG: define dso_local dllexport void @_ZN13ExportMembers6Nested12protectedDefEv(%"struct.ExportMembers::Nested"* %this)
+ // MSC-DAG: define dso_local dllexport void @"?protectedStaticDef@Nested@ExportMembers@@KAXXZ"()
+ // GNU-DAG: define dso_local dllexport void @_ZN13ExportMembers6Nested18protectedStaticDefEv()
protected:
__declspec(dllexport) void protectedDef();
__declspec(dllexport) static void protectedStaticDef();
- // M32-DAG: define dllexport x86_thiscallcc void @"\01?privateDef@Nested@ExportMembers@@AAEXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M64-DAG: define dllexport void @"\01?privateDef@Nested@ExportMembers@@AEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
- // G32-DAG: define dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested10privateDefEv(%"struct.ExportMembers::Nested"* %this)
- // G64-DAG: define dllexport void @_ZN13ExportMembers6Nested10privateDefEv(%"struct.ExportMembers::Nested"* %this)
- // MSC-DAG: define dllexport void @"\01?privateStaticDef@Nested@ExportMembers@@CAXXZ"()
- // GNU-DAG: define dllexport void @_ZN13ExportMembers6Nested16privateStaticDefEv()
+ // M32-DAG: define dso_local dllexport x86_thiscallcc void @"?privateDef@Nested@ExportMembers@@AAEXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M64-DAG: define dso_local dllexport void @"?privateDef@Nested@ExportMembers@@AEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested10privateDefEv(%"struct.ExportMembers::Nested"* %this)
+ // G64-DAG: define dso_local dllexport void @_ZN13ExportMembers6Nested10privateDefEv(%"struct.ExportMembers::Nested"* %this)
+ // MSC-DAG: define dso_local dllexport void @"?privateStaticDef@Nested@ExportMembers@@CAXXZ"()
+ // GNU-DAG: define dso_local dllexport void @_ZN13ExportMembers6Nested16privateStaticDefEv()
private:
__declspec(dllexport) void privateDef();
__declspec(dllexport) static void privateStaticDef();
- // M32-DAG: define x86_thiscallcc void @"\01?ignored@Nested@ExportMembers@@QAEXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M64-DAG: define void @"\01?ignored@Nested@ExportMembers@@QEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
- // G32-DAG: define x86_thiscallcc void @_ZN13ExportMembers6Nested7ignoredEv(%"struct.ExportMembers::Nested"* %this)
- // G64-DAG: define void @_ZN13ExportMembers6Nested7ignoredEv(%"struct.ExportMembers::Nested"* %this)
+ // M32-DAG: define dso_local x86_thiscallcc void @"?ignored@Nested@ExportMembers@@QAEXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M64-DAG: define dso_local void @"?ignored@Nested@ExportMembers@@QEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // G32-DAG: define dso_local x86_thiscallcc void @_ZN13ExportMembers6Nested7ignoredEv(%"struct.ExportMembers::Nested"* %this)
+ // G64-DAG: define dso_local void @_ZN13ExportMembers6Nested7ignoredEv(%"struct.ExportMembers::Nested"* %this)
public:
void ignored();
- // MSC-DAG: @"\01?StaticField@Nested@ExportMembers@@2HA" = dllexport global i32 1, align 4
- // MSC-DAG: @"\01?StaticConstField@Nested@ExportMembers@@2HB" = dllexport constant i32 1, align 4
- // MSC-DAG: @"\01?StaticConstFieldEqualInit@Nested@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4
- // MSC-DAG: @"\01?StaticConstFieldBraceInit@Nested@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4
- // MSC-DAG: @"\01?StaticConstFieldRefNotDef@Nested@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4
- // MSC-DAG: @"\01?ConstexprField@Nested@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4
- // GNU-DAG: @_ZN13ExportMembers6Nested11StaticFieldE = dllexport global i32 1, align 4
- // GNU-DAG: @_ZN13ExportMembers6Nested16StaticConstFieldE = dllexport constant i32 1, align 4
- // GNU-DAG: @_ZN13ExportMembers6Nested25StaticConstFieldEqualInitE = dllexport constant i32 1, align 4
- // GNU-DAG: @_ZN13ExportMembers6Nested25StaticConstFieldBraceInitE = dllexport constant i32 1, align 4
- // GNU-DAG: @_ZN13ExportMembers6Nested14ConstexprFieldE = dllexport constant i32 1, align 4
+ // MSC-DAG: @"?StaticField@Nested@ExportMembers@@2HA" = dso_local dllexport global i32 1, align 4
+ // MSC-DAG: @"?StaticConstField@Nested@ExportMembers@@2HB" = dso_local dllexport constant i32 1, align 4
+ // MSC-DAG: @"?StaticConstFieldEqualInit@Nested@ExportMembers@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
+ // MSC-DAG: @"?StaticConstFieldBraceInit@Nested@ExportMembers@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
+ // MSC-DAG: @"?StaticConstFieldRefNotDef@Nested@ExportMembers@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
+ // MSC-DAG: @"?ConstexprField@Nested@ExportMembers@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
+ // GNU-DAG: @_ZN13ExportMembers6Nested11StaticFieldE = dso_local dllexport global i32 1, align 4
+ // GNU-DAG: @_ZN13ExportMembers6Nested16StaticConstFieldE = dso_local dllexport constant i32 1, align 4
+ // GNU-DAG: @_ZN13ExportMembers6Nested25StaticConstFieldEqualInitE = dso_local dllexport constant i32 1, align 4
+ // GNU-DAG: @_ZN13ExportMembers6Nested25StaticConstFieldBraceInitE = dso_local dllexport constant i32 1, align 4
+ // GNU-DAG: @_ZN13ExportMembers6Nested14ConstexprFieldE = dso_local dllexport constant i32 1, align 4
__declspec(dllexport) static int StaticField;
__declspec(dllexport) static const int StaticConstField;
__declspec(dllexport) static const int StaticConstFieldEqualInit = 1;
@@ -280,48 +280,48 @@ constexpr int ExportMembers::Nested::ConstexprField;
// Export special member functions.
struct ExportSpecials {
- // M32-DAG: define dllexport x86_thiscallcc %struct.ExportSpecials* @"\01??0ExportSpecials@@QAE@XZ"(%struct.ExportSpecials* returned %this)
- // M64-DAG: define dllexport %struct.ExportSpecials* @"\01??0ExportSpecials@@QEAA@XZ"(%struct.ExportSpecials* returned %this)
- // G32-DAG: define dllexport x86_thiscallcc void @_ZN14ExportSpecialsC1Ev(%struct.ExportSpecials* %this)
- // G64-DAG: define dllexport void @_ZN14ExportSpecialsC1Ev(%struct.ExportSpecials* %this)
- // G32-DAG: define dllexport x86_thiscallcc void @_ZN14ExportSpecialsC2Ev(%struct.ExportSpecials* %this)
- // G64-DAG: define dllexport void @_ZN14ExportSpecialsC2Ev(%struct.ExportSpecials* %this)
+ // M32-DAG: define dso_local dllexport x86_thiscallcc %struct.ExportSpecials* @"??0ExportSpecials@@QAE@XZ"(%struct.ExportSpecials* returned %this)
+ // M64-DAG: define dso_local dllexport %struct.ExportSpecials* @"??0ExportSpecials@@QEAA@XZ"(%struct.ExportSpecials* returned %this)
+ // G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN14ExportSpecialsC1Ev(%struct.ExportSpecials* %this)
+ // G64-DAG: define dso_local dllexport void @_ZN14ExportSpecialsC1Ev(%struct.ExportSpecials* %this)
+ // G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN14ExportSpecialsC2Ev(%struct.ExportSpecials* %this)
+ // G64-DAG: define dso_local dllexport void @_ZN14ExportSpecialsC2Ev(%struct.ExportSpecials* %this)
__declspec(dllexport) ExportSpecials();
- // M32-DAG: define dllexport x86_thiscallcc void @"\01??1ExportSpecials@@QAE@XZ"(%struct.ExportSpecials* %this)
- // M64-DAG: define dllexport void @"\01??1ExportSpecials@@QEAA@XZ"(%struct.ExportSpecials* %this)
- // G32-DAG: define dllexport x86_thiscallcc void @_ZN14ExportSpecialsD1Ev(%struct.ExportSpecials* %this)
- // G64-DAG: define dllexport void @_ZN14ExportSpecialsD1Ev(%struct.ExportSpecials* %this)
- // G32-DAG: define dllexport x86_thiscallcc void @_ZN14ExportSpecialsD2Ev(%struct.ExportSpecials* %this)
- // G64-DAG: define dllexport void @_ZN14ExportSpecialsD2Ev(%struct.ExportSpecials* %this)
+ // M32-DAG: define dso_local dllexport x86_thiscallcc void @"??1ExportSpecials@@QAE@XZ"(%struct.ExportSpecials* %this)
+ // M64-DAG: define dso_local dllexport void @"??1ExportSpecials@@QEAA@XZ"(%struct.ExportSpecials* %this)
+ // G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN14ExportSpecialsD1Ev(%struct.ExportSpecials* %this)
+ // G64-DAG: define dso_local dllexport void @_ZN14ExportSpecialsD1Ev(%struct.ExportSpecials* %this)
+ // G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN14ExportSpecialsD2Ev(%struct.ExportSpecials* %this)
+ // G64-DAG: define dso_local dllexport void @_ZN14ExportSpecialsD2Ev(%struct.ExportSpecials* %this)
__declspec(dllexport) ~ExportSpecials();
- // M32-DAG: define dllexport x86_thiscallcc %struct.ExportSpecials* @"\01??0ExportSpecials@@QAE@ABU0@@Z"(%struct.ExportSpecials* returned %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
- // M64-DAG: define dllexport %struct.ExportSpecials* @"\01??0ExportSpecials@@QEAA@AEBU0@@Z"(%struct.ExportSpecials* returned %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
- // G32-DAG: define dllexport x86_thiscallcc void @_ZN14ExportSpecialsC1ERKS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
- // G64-DAG: define dllexport void @_ZN14ExportSpecialsC1ERKS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
- // G32-DAG: define dllexport x86_thiscallcc void @_ZN14ExportSpecialsC2ERKS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
- // G64-DAG: define dllexport void @_ZN14ExportSpecialsC2ERKS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // M32-DAG: define dso_local dllexport x86_thiscallcc %struct.ExportSpecials* @"??0ExportSpecials@@QAE@ABU0@@Z"(%struct.ExportSpecials* returned %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: define dso_local dllexport %struct.ExportSpecials* @"??0ExportSpecials@@QEAA@AEBU0@@Z"(%struct.ExportSpecials* returned %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN14ExportSpecialsC1ERKS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // G64-DAG: define dso_local dllexport void @_ZN14ExportSpecialsC1ERKS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN14ExportSpecialsC2ERKS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // G64-DAG: define dso_local dllexport void @_ZN14ExportSpecialsC2ERKS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
__declspec(dllexport) ExportSpecials(const ExportSpecials&);
- // M32-DAG: define dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @"\01??4ExportSpecials@@QAEAAU0@ABU0@@Z"(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
- // M64-DAG: define dllexport dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @"\01??4ExportSpecials@@QEAAAEAU0@AEBU0@@Z"(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
- // G32-DAG: define dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @_ZN14ExportSpecialsaSERKS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
- // G64-DAG: define dllexport dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @_ZN14ExportSpecialsaSERKS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // M32-DAG: define dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @"??4ExportSpecials@@QAEAAU0@ABU0@@Z"(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: define dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @"??4ExportSpecials@@QEAAAEAU0@AEBU0@@Z"(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // G32-DAG: define dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @_ZN14ExportSpecialsaSERKS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // G64-DAG: define dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @_ZN14ExportSpecialsaSERKS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
__declspec(dllexport) ExportSpecials& operator=(const ExportSpecials&);
- // M32-DAG: define dllexport x86_thiscallcc %struct.ExportSpecials* @"\01??0ExportSpecials@@QAE@$$QAU0@@Z"(%struct.ExportSpecials* returned %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
- // M64-DAG: define dllexport %struct.ExportSpecials* @"\01??0ExportSpecials@@QEAA@$$QEAU0@@Z"(%struct.ExportSpecials* returned %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
- // G32-DAG: define dllexport x86_thiscallcc void @_ZN14ExportSpecialsC1EOS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
- // G64-DAG: define dllexport void @_ZN14ExportSpecialsC1EOS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
- // G32-DAG: define dllexport x86_thiscallcc void @_ZN14ExportSpecialsC2EOS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
- // G64-DAG: define dllexport void @_ZN14ExportSpecialsC2EOS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // M32-DAG: define dso_local dllexport x86_thiscallcc %struct.ExportSpecials* @"??0ExportSpecials@@QAE@$$QAU0@@Z"(%struct.ExportSpecials* returned %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: define dso_local dllexport %struct.ExportSpecials* @"??0ExportSpecials@@QEAA@$$QEAU0@@Z"(%struct.ExportSpecials* returned %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN14ExportSpecialsC1EOS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // G64-DAG: define dso_local dllexport void @_ZN14ExportSpecialsC1EOS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN14ExportSpecialsC2EOS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // G64-DAG: define dso_local dllexport void @_ZN14ExportSpecialsC2EOS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
__declspec(dllexport) ExportSpecials(ExportSpecials&&);
- // M32-DAG: define dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @"\01??4ExportSpecials@@QAEAAU0@$$QAU0@@Z"(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
- // M64-DAG: define dllexport dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @"\01??4ExportSpecials@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
- // G32-DAG: define dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @_ZN14ExportSpecialsaSEOS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
- // G64-DAG: define dllexport dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @_ZN14ExportSpecialsaSEOS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // M32-DAG: define dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @"??4ExportSpecials@@QAEAAU0@$$QAU0@@Z"(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: define dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @"??4ExportSpecials@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // G32-DAG: define dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @_ZN14ExportSpecialsaSEOS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // G64-DAG: define dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @_ZN14ExportSpecialsaSEOS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
__declspec(dllexport) ExportSpecials& operator=(ExportSpecials&&);
};
ExportSpecials::ExportSpecials() {}
@@ -334,40 +334,40 @@ ExportSpecials& ExportSpecials::operator=(ExportSpecials&&) { return *this; }
// Export class with inline special member functions.
struct ExportInlineSpecials {
- // M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExportInlineSpecials* @"\01??0ExportInlineSpecials@@QAE@XZ"(%struct.ExportInlineSpecials* returned %this)
- // M64-DAG: define weak_odr dllexport %struct.ExportInlineSpecials* @"\01??0ExportInlineSpecials@@QEAA@XZ"(
- // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN20ExportInlineSpecialsC1Ev(
- // G64-DAG: define weak_odr dllexport void @_ZN20ExportInlineSpecialsC1Ev(
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportInlineSpecials* @"??0ExportInlineSpecials@@QAE@XZ"(%struct.ExportInlineSpecials* returned %this)
+ // M64-DAG: define weak_odr dso_local dllexport %struct.ExportInlineSpecials* @"??0ExportInlineSpecials@@QEAA@XZ"(
+ // G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN20ExportInlineSpecialsC1Ev(
+ // G64-DAG: define weak_odr dso_local dllexport void @_ZN20ExportInlineSpecialsC1Ev(
__declspec(dllexport) ExportInlineSpecials() {}
- // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??1ExportInlineSpecials@@QAE@XZ"(
- // M64-DAG: define weak_odr dllexport void @"\01??1ExportInlineSpecials@@QEAA@XZ"(
- // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN20ExportInlineSpecialsD1Ev(
- // G64-DAG: define weak_odr dllexport void @_ZN20ExportInlineSpecialsD1Ev(
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"??1ExportInlineSpecials@@QAE@XZ"(
+ // M64-DAG: define weak_odr dso_local dllexport void @"??1ExportInlineSpecials@@QEAA@XZ"(
+ // G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN20ExportInlineSpecialsD1Ev(
+ // G64-DAG: define weak_odr dso_local dllexport void @_ZN20ExportInlineSpecialsD1Ev(
__declspec(dllexport) ~ExportInlineSpecials() {}
- // M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExportInlineSpecials* @"\01??0ExportInlineSpecials@@QAE@ABU0@@Z"(
- // M64-DAG: define weak_odr dllexport %struct.ExportInlineSpecials* @"\01??0ExportInlineSpecials@@QEAA@AEBU0@@Z"(
- // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN20ExportInlineSpecialsC1ERKS_(
- // G64-DAG: define weak_odr dllexport void @_ZN20ExportInlineSpecialsC1ERKS_(
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportInlineSpecials* @"??0ExportInlineSpecials@@QAE@ABU0@@Z"(
+ // M64-DAG: define weak_odr dso_local dllexport %struct.ExportInlineSpecials* @"??0ExportInlineSpecials@@QEAA@AEBU0@@Z"(
+ // G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN20ExportInlineSpecialsC1ERKS_(
+ // G64-DAG: define weak_odr dso_local dllexport void @_ZN20ExportInlineSpecialsC1ERKS_(
__declspec(dllexport) inline ExportInlineSpecials(const ExportInlineSpecials&);
- // M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @"\01??4ExportInlineSpecials@@QAEAAU0@ABU0@@Z"(
- // M64-DAG: define weak_odr dllexport dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @"\01??4ExportInlineSpecials@@QEAAAEAU0@AEBU0@@Z"(
- // G32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @_ZN20ExportInlineSpecialsaSERKS_(
- // G64-DAG: define weak_odr dllexport dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @_ZN20ExportInlineSpecialsaSERKS_(
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @"??4ExportInlineSpecials@@QAEAAU0@ABU0@@Z"(
+ // M64-DAG: define weak_odr dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @"??4ExportInlineSpecials@@QEAAAEAU0@AEBU0@@Z"(
+ // G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @_ZN20ExportInlineSpecialsaSERKS_(
+ // G64-DAG: define weak_odr dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @_ZN20ExportInlineSpecialsaSERKS_(
__declspec(dllexport) ExportInlineSpecials& operator=(const ExportInlineSpecials&);
- // M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExportInlineSpecials* @"\01??0ExportInlineSpecials@@QAE@$$QAU0@@Z"(
- // M64-DAG: define weak_odr dllexport %struct.ExportInlineSpecials* @"\01??0ExportInlineSpecials@@QEAA@$$QEAU0@@Z"(
- // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN20ExportInlineSpecialsC1EOS_(
- // G64-DAG: define weak_odr dllexport void @_ZN20ExportInlineSpecialsC1EOS_(
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportInlineSpecials* @"??0ExportInlineSpecials@@QAE@$$QAU0@@Z"(
+ // M64-DAG: define weak_odr dso_local dllexport %struct.ExportInlineSpecials* @"??0ExportInlineSpecials@@QEAA@$$QEAU0@@Z"(
+ // G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN20ExportInlineSpecialsC1EOS_(
+ // G64-DAG: define weak_odr dso_local dllexport void @_ZN20ExportInlineSpecialsC1EOS_(
__declspec(dllexport) ExportInlineSpecials(ExportInlineSpecials&&) {}
- // M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @"\01??4ExportInlineSpecials@@QAEAAU0@$$QAU0@@Z"(
- // M64-DAG: define weak_odr dllexport dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @"\01??4ExportInlineSpecials@@QEAAAEAU0@$$QEAU0@@Z"(
- // G32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @_ZN20ExportInlineSpecialsaSEOS_(
- // G64-DAG: define weak_odr dllexport dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @_ZN20ExportInlineSpecialsaSEOS_(
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @"??4ExportInlineSpecials@@QAEAAU0@$$QAU0@@Z"(
+ // M64-DAG: define weak_odr dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @"??4ExportInlineSpecials@@QEAAAEAU0@$$QEAU0@@Z"(
+ // G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @_ZN20ExportInlineSpecialsaSEOS_(
+ // G64-DAG: define weak_odr dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @_ZN20ExportInlineSpecialsaSEOS_(
__declspec(dllexport) ExportInlineSpecials& operator=(ExportInlineSpecials&&) { return *this; }
};
ExportInlineSpecials::ExportInlineSpecials(const ExportInlineSpecials&) {}
@@ -384,74 +384,74 @@ struct ExportDefaultedDefs {
__declspec(dllexport) ExportDefaultedDefs& operator=(ExportDefaultedDefs&&);
};
-// M32-DAG: define dllexport x86_thiscallcc %struct.ExportDefaultedDefs* @"\01??0ExportDefaultedDefs@@QAE@XZ"(%struct.ExportDefaultedDefs* returned %this)
-// M64-DAG: define dllexport %struct.ExportDefaultedDefs* @"\01??0ExportDefaultedDefs@@QEAA@XZ"(%struct.ExportDefaultedDefs* returned %this)
-// G32-DAG: define dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsC1Ev(%struct.ExportDefaultedDefs* %this)
-// G64-DAG: define dllexport void @_ZN19ExportDefaultedDefsC1Ev(%struct.ExportDefaultedDefs* %this)
-// G32-DAG: define dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsC2Ev(%struct.ExportDefaultedDefs* %this)
-// G64-DAG: define dllexport void @_ZN19ExportDefaultedDefsC2Ev(%struct.ExportDefaultedDefs* %this)
+// M32-DAG: define dso_local dllexport x86_thiscallcc %struct.ExportDefaultedDefs* @"??0ExportDefaultedDefs@@QAE@XZ"(%struct.ExportDefaultedDefs* returned %this)
+// M64-DAG: define dso_local dllexport %struct.ExportDefaultedDefs* @"??0ExportDefaultedDefs@@QEAA@XZ"(%struct.ExportDefaultedDefs* returned %this)
+// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsC1Ev(%struct.ExportDefaultedDefs* %this)
+// G64-DAG: define dso_local dllexport void @_ZN19ExportDefaultedDefsC1Ev(%struct.ExportDefaultedDefs* %this)
+// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsC2Ev(%struct.ExportDefaultedDefs* %this)
+// G64-DAG: define dso_local dllexport void @_ZN19ExportDefaultedDefsC2Ev(%struct.ExportDefaultedDefs* %this)
__declspec(dllexport) ExportDefaultedDefs::ExportDefaultedDefs() = default;
-// M32-DAG: define dllexport x86_thiscallcc void @"\01??1ExportDefaultedDefs@@QAE@XZ"(%struct.ExportDefaultedDefs* %this)
-// M64-DAG: define dllexport void @"\01??1ExportDefaultedDefs@@QEAA@XZ"(%struct.ExportDefaultedDefs* %this)
-// G32-DAG: define dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsD1Ev(%struct.ExportDefaultedDefs* %this)
-// G64-DAG: define dllexport void @_ZN19ExportDefaultedDefsD1Ev(%struct.ExportDefaultedDefs* %this)
-// G32-DAG: define dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsD2Ev(%struct.ExportDefaultedDefs* %this)
-// G64-DAG: define dllexport void @_ZN19ExportDefaultedDefsD2Ev(%struct.ExportDefaultedDefs* %this)
+// M32-DAG: define dso_local dllexport x86_thiscallcc void @"??1ExportDefaultedDefs@@QAE@XZ"(%struct.ExportDefaultedDefs* %this)
+// M64-DAG: define dso_local dllexport void @"??1ExportDefaultedDefs@@QEAA@XZ"(%struct.ExportDefaultedDefs* %this)
+// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsD1Ev(%struct.ExportDefaultedDefs* %this)
+// G64-DAG: define dso_local dllexport void @_ZN19ExportDefaultedDefsD1Ev(%struct.ExportDefaultedDefs* %this)
+// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsD2Ev(%struct.ExportDefaultedDefs* %this)
+// G64-DAG: define dso_local dllexport void @_ZN19ExportDefaultedDefsD2Ev(%struct.ExportDefaultedDefs* %this)
ExportDefaultedDefs::~ExportDefaultedDefs() = default;
-// M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExportDefaultedDefs* @"\01??0ExportDefaultedDefs@@QAE@ABU0@@Z"(%struct.ExportDefaultedDefs* returned %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// M64-DAG: define weak_odr dllexport %struct.ExportDefaultedDefs* @"\01??0ExportDefaultedDefs@@QEAA@AEBU0@@Z"(%struct.ExportDefaultedDefs* returned %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsC1ERKS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// G64-DAG: define weak_odr dllexport void @_ZN19ExportDefaultedDefsC1ERKS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsC2ERKS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// G64-DAG: define weak_odr dllexport void @_ZN19ExportDefaultedDefsC2ERKS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportDefaultedDefs* @"??0ExportDefaultedDefs@@QAE@ABU0@@Z"(%struct.ExportDefaultedDefs* returned %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M64-DAG: define weak_odr dso_local dllexport %struct.ExportDefaultedDefs* @"??0ExportDefaultedDefs@@QEAA@AEBU0@@Z"(%struct.ExportDefaultedDefs* returned %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsC1ERKS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G64-DAG: define weak_odr dso_local dllexport void @_ZN19ExportDefaultedDefsC1ERKS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsC2ERKS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G64-DAG: define weak_odr dso_local dllexport void @_ZN19ExportDefaultedDefsC2ERKS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
__declspec(dllexport) ExportDefaultedDefs::ExportDefaultedDefs(const ExportDefaultedDefs&) = default;
-// M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @"\01??4ExportDefaultedDefs@@QAEAAU0@ABU0@@Z"(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// M64-DAG: define weak_odr dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @"\01??4ExportDefaultedDefs@@QEAAAEAU0@AEBU0@@Z"(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// G32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @_ZN19ExportDefaultedDefsaSERKS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// G64-DAG: define weak_odr dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @_ZN19ExportDefaultedDefsaSERKS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @"??4ExportDefaultedDefs@@QAEAAU0@ABU0@@Z"(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M64-DAG: define weak_odr dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @"??4ExportDefaultedDefs@@QEAAAEAU0@AEBU0@@Z"(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @_ZN19ExportDefaultedDefsaSERKS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G64-DAG: define weak_odr dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @_ZN19ExportDefaultedDefsaSERKS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
inline ExportDefaultedDefs& ExportDefaultedDefs::operator=(const ExportDefaultedDefs&) = default;
-// M32-DAG: define dllexport x86_thiscallcc %struct.ExportDefaultedDefs* @"\01??0ExportDefaultedDefs@@QAE@$$QAU0@@Z"(%struct.ExportDefaultedDefs* returned %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// M64-DAG: define dllexport %struct.ExportDefaultedDefs* @"\01??0ExportDefaultedDefs@@QEAA@$$QEAU0@@Z"(%struct.ExportDefaultedDefs* returned %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// G32-DAG: define dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsC1EOS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// G64-DAG: define dllexport void @_ZN19ExportDefaultedDefsC1EOS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// G32-DAG: define dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsC2EOS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// G64-DAG: define dllexport void @_ZN19ExportDefaultedDefsC2EOS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M32-DAG: define dso_local dllexport x86_thiscallcc %struct.ExportDefaultedDefs* @"??0ExportDefaultedDefs@@QAE@$$QAU0@@Z"(%struct.ExportDefaultedDefs* returned %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M64-DAG: define dso_local dllexport %struct.ExportDefaultedDefs* @"??0ExportDefaultedDefs@@QEAA@$$QEAU0@@Z"(%struct.ExportDefaultedDefs* returned %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsC1EOS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G64-DAG: define dso_local dllexport void @_ZN19ExportDefaultedDefsC1EOS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsC2EOS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G64-DAG: define dso_local dllexport void @_ZN19ExportDefaultedDefsC2EOS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
__declspec(dllexport) ExportDefaultedDefs::ExportDefaultedDefs(ExportDefaultedDefs&&) = default;
-// M32-DAG: define dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @"\01??4ExportDefaultedDefs@@QAEAAU0@$$QAU0@@Z"(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// M64-DAG: define dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @"\01??4ExportDefaultedDefs@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// G32-DAG: define dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @_ZN19ExportDefaultedDefsaSEOS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// G64-DAG: define dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @_ZN19ExportDefaultedDefsaSEOS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M32-DAG: define dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @"??4ExportDefaultedDefs@@QAEAAU0@$$QAU0@@Z"(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M64-DAG: define dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @"??4ExportDefaultedDefs@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G32-DAG: define dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @_ZN19ExportDefaultedDefsaSEOS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G64-DAG: define dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @_ZN19ExportDefaultedDefsaSEOS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
ExportDefaultedDefs& ExportDefaultedDefs::operator=(ExportDefaultedDefs&&) = default;
// Export defaulted member function definitions declared inside class.
struct ExportDefaultedInclassDefs {
__declspec(dllexport) ExportDefaultedInclassDefs() = default;
- // M32VS2013-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
- // M64VS2013-DAG: define weak_odr dllexport %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
- // M32VS2015-NOT: define weak_odr dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
- // M64VS2015-NOT: define weak_odr dllexport %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
+ // M32VS2013-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"??0ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
+ // M64VS2013-DAG: define weak_odr dso_local dllexport %struct.ExportDefaultedInclassDefs* @"??0ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
+ // M32VS2015-NOT: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"??0ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
+ // M64VS2015-NOT: define weak_odr dso_local dllexport %struct.ExportDefaultedInclassDefs* @"??0ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
__declspec(dllexport) ~ExportDefaultedInclassDefs() = default;
- // M32VS2013-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??1ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* %this)
- // M64VS2013-DAG: define weak_odr dllexport void @"\01??1ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* %this)
- // M32VS2015-NOT: define weak_odr dllexport x86_thiscallcc void @"\01??1ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* %this)
- // M64VS2015-NOT: define weak_odr dllexport void @"\01??1ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* %this)
+ // M32VS2013-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"??1ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* %this)
+ // M64VS2013-DAG: define weak_odr dso_local dllexport void @"??1ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* %this)
+ // M32VS2015-NOT: define weak_odr dso_local dllexport x86_thiscallcc void @"??1ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* %this)
+ // M64VS2015-NOT: define weak_odr dso_local dllexport void @"??1ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* %this)
__declspec(dllexport) ExportDefaultedInclassDefs(const ExportDefaultedInclassDefs&) = default;
- // M32VS2013-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QAE@ABU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
- // M64VS2013-DAG: define weak_odr dllexport %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QEAA@AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
- // M32VS2015-NOT: define weak_odr dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QAE@ABU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
- // M64VS2015-NOT: define weak_odr dllexport %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QEAA@AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+ // M32VS2013-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"??0ExportDefaultedInclassDefs@@QAE@ABU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+ // M64VS2013-DAG: define weak_odr dso_local dllexport %struct.ExportDefaultedInclassDefs* @"??0ExportDefaultedInclassDefs@@QEAA@AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+ // M32VS2015-NOT: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"??0ExportDefaultedInclassDefs@@QAE@ABU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+ // M64VS2015-NOT: define weak_odr dso_local dllexport %struct.ExportDefaultedInclassDefs* @"??0ExportDefaultedInclassDefs@@QEAA@AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
__declspec(dllexport) ExportDefaultedInclassDefs& operator=(const ExportDefaultedInclassDefs&) = default;
- // M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedInclassDefs* @"\01??4ExportDefaultedInclassDefs@@QAEAAU0@ABU0@@Z"(%struct.ExportDefaultedInclassDefs* %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
- // M64-DAG: define weak_odr dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedInclassDefs* @"\01??4ExportDefaultedInclassDefs@@QEAAAEAU0@AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedInclassDefs* @"??4ExportDefaultedInclassDefs@@QAEAAU0@ABU0@@Z"(%struct.ExportDefaultedInclassDefs* %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+ // M64-DAG: define weak_odr dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedInclassDefs* @"??4ExportDefaultedInclassDefs@@QEAAAEAU0@AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
};
@@ -463,28 +463,28 @@ struct ExportAlloc {
__declspec(dllexport) void operator delete[](void*);
};
-// M32-DAG: define dllexport i8* @"\01??2ExportAlloc@@SAPAXI@Z"(i32 %n)
-// M64-DAG: define dllexport i8* @"\01??2ExportAlloc@@SAPEAX_K@Z"(i64 %n)
-// G32-DAG: define dllexport i8* @_ZN11ExportAllocnwEj(i32 %n)
-// G64-DAG: define dllexport i8* @_ZN11ExportAllocnwEy(i64 %n)
+// M32-DAG: define dso_local dllexport i8* @"??2ExportAlloc@@SAPAXI@Z"(i32 %n)
+// M64-DAG: define dso_local dllexport i8* @"??2ExportAlloc@@SAPEAX_K@Z"(i64 %n)
+// G32-DAG: define dso_local dllexport i8* @_ZN11ExportAllocnwEj(i32 %n)
+// G64-DAG: define dso_local dllexport i8* @_ZN11ExportAllocnwEy(i64 %n)
void* ExportAlloc::operator new(__SIZE_TYPE__ n) { return malloc(n); }
-// M32-DAG: define dllexport i8* @"\01??_UExportAlloc@@SAPAXI@Z"(i32 %n)
-// M64-DAG: define dllexport i8* @"\01??_UExportAlloc@@SAPEAX_K@Z"(i64 %n)
-// G32-DAG: define dllexport i8* @_ZN11ExportAllocnaEj(i32 %n)
-// G64-DAG: define dllexport i8* @_ZN11ExportAllocnaEy(i64 %n)
+// M32-DAG: define dso_local dllexport i8* @"??_UExportAlloc@@SAPAXI@Z"(i32 %n)
+// M64-DAG: define dso_local dllexport i8* @"??_UExportAlloc@@SAPEAX_K@Z"(i64 %n)
+// G32-DAG: define dso_local dllexport i8* @_ZN11ExportAllocnaEj(i32 %n)
+// G64-DAG: define dso_local dllexport i8* @_ZN11ExportAllocnaEy(i64 %n)
void* ExportAlloc::operator new[](__SIZE_TYPE__ n) { return malloc(n); }
-// M32-DAG: define dllexport void @"\01??3ExportAlloc@@SAXPAX@Z"(i8* %p)
-// M64-DAG: define dllexport void @"\01??3ExportAlloc@@SAXPEAX@Z"(i8* %p)
-// G32-DAG: define dllexport void @_ZN11ExportAllocdlEPv(i8* %p)
-// G64-DAG: define dllexport void @_ZN11ExportAllocdlEPv(i8* %p)
+// M32-DAG: define dso_local dllexport void @"??3ExportAlloc@@SAXPAX@Z"(i8* %p)
+// M64-DAG: define dso_local dllexport void @"??3ExportAlloc@@SAXPEAX@Z"(i8* %p)
+// G32-DAG: define dso_local dllexport void @_ZN11ExportAllocdlEPv(i8* %p)
+// G64-DAG: define dso_local dllexport void @_ZN11ExportAllocdlEPv(i8* %p)
void ExportAlloc::operator delete(void* p) { free(p); }
-// M32-DAG: define dllexport void @"\01??_VExportAlloc@@SAXPAX@Z"(i8* %p)
-// M64-DAG: define dllexport void @"\01??_VExportAlloc@@SAXPEAX@Z"(i8* %p)
-// G32-DAG: define dllexport void @_ZN11ExportAllocdaEPv(i8* %p)
-// G64-DAG: define dllexport void @_ZN11ExportAllocdaEPv(i8* %p)
+// M32-DAG: define dso_local dllexport void @"??_VExportAlloc@@SAXPAX@Z"(i8* %p)
+// M64-DAG: define dso_local dllexport void @"??_VExportAlloc@@SAXPEAX@Z"(i8* %p)
+// G32-DAG: define dso_local dllexport void @_ZN11ExportAllocdaEPv(i8* %p)
+// G64-DAG: define dso_local dllexport void @_ZN11ExportAllocdaEPv(i8* %p)
void ExportAlloc::operator delete[](void* p) { free(p); }
@@ -501,125 +501,125 @@ struct MemFunTmpl {
// Export implicit instantiation of an exported member function template.
void useMemFunTmpl() {
- // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??$exportedNormal@UImplicitInst_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
- // M64-DAG: define weak_odr dllexport void @"\01??$exportedNormal@UImplicitInst_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
- // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN10MemFunTmpl14exportedNormalI21ImplicitInst_ExportedEEvv(%struct.MemFunTmpl* %this)
- // G64-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl14exportedNormalI21ImplicitInst_ExportedEEvv(%struct.MemFunTmpl* %this)
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"??$exportedNormal@UImplicitInst_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
+ // M64-DAG: define weak_odr dso_local dllexport void @"??$exportedNormal@UImplicitInst_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
+ // G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN10MemFunTmpl14exportedNormalI21ImplicitInst_ExportedEEvv(%struct.MemFunTmpl* %this)
+ // G64-DAG: define weak_odr dso_local dllexport void @_ZN10MemFunTmpl14exportedNormalI21ImplicitInst_ExportedEEvv(%struct.MemFunTmpl* %this)
MemFunTmpl().exportedNormal<ImplicitInst_Exported>();
- // MSC-DAG: define weak_odr dllexport void @"\01??$exportedStatic@UImplicitInst_Exported@@@MemFunTmpl@@SAXXZ"()
- // GNU-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl14exportedStaticI21ImplicitInst_ExportedEEvv()
+ // MSC-DAG: define weak_odr dso_local dllexport void @"??$exportedStatic@UImplicitInst_Exported@@@MemFunTmpl@@SAXXZ"()
+ // GNU-DAG: define weak_odr dso_local dllexport void @_ZN10MemFunTmpl14exportedStaticI21ImplicitInst_ExportedEEvv()
MemFunTmpl().exportedStatic<ImplicitInst_Exported>();
}
// Export explicit instantiation declaration of an exported member function
// template.
-// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??$exportedNormal@UExplicitDecl_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
-// M64-DAG: define weak_odr dllexport void @"\01??$exportedNormal@UExplicitDecl_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
-// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN10MemFunTmpl14exportedNormalI21ExplicitDecl_ExportedEEvv(%struct.MemFunTmpl* %this)
-// G64-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl14exportedNormalI21ExplicitDecl_ExportedEEvv(%struct.MemFunTmpl* %this)
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"??$exportedNormal@UExplicitDecl_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
+// M64-DAG: define weak_odr dso_local dllexport void @"??$exportedNormal@UExplicitDecl_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
+// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN10MemFunTmpl14exportedNormalI21ExplicitDecl_ExportedEEvv(%struct.MemFunTmpl* %this)
+// G64-DAG: define weak_odr dso_local dllexport void @_ZN10MemFunTmpl14exportedNormalI21ExplicitDecl_ExportedEEvv(%struct.MemFunTmpl* %this)
extern template void MemFunTmpl::exportedNormal<ExplicitDecl_Exported>();
template void MemFunTmpl::exportedNormal<ExplicitDecl_Exported>();
-// MSC-DAG: define weak_odr dllexport void @"\01??$exportedStatic@UExplicitDecl_Exported@@@MemFunTmpl@@SAXXZ"()
-// GNU-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl14exportedStaticI21ExplicitDecl_ExportedEEvv()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$exportedStatic@UExplicitDecl_Exported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: define weak_odr dso_local dllexport void @_ZN10MemFunTmpl14exportedStaticI21ExplicitDecl_ExportedEEvv()
extern template void MemFunTmpl::exportedStatic<ExplicitDecl_Exported>();
template void MemFunTmpl::exportedStatic<ExplicitDecl_Exported>();
// Export explicit instantiation definition of an exported member function
// template.
-// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??$exportedNormal@UExplicitInst_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
-// M64-DAG: define weak_odr dllexport void @"\01??$exportedNormal@UExplicitInst_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
-// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN10MemFunTmpl14exportedNormalI21ExplicitInst_ExportedEEvv(%struct.MemFunTmpl* %this)
-// G64-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl14exportedNormalI21ExplicitInst_ExportedEEvv(%struct.MemFunTmpl* %this)
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"??$exportedNormal@UExplicitInst_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
+// M64-DAG: define weak_odr dso_local dllexport void @"??$exportedNormal@UExplicitInst_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
+// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN10MemFunTmpl14exportedNormalI21ExplicitInst_ExportedEEvv(%struct.MemFunTmpl* %this)
+// G64-DAG: define weak_odr dso_local dllexport void @_ZN10MemFunTmpl14exportedNormalI21ExplicitInst_ExportedEEvv(%struct.MemFunTmpl* %this)
template void MemFunTmpl::exportedNormal<ExplicitInst_Exported>();
-// MSC-DAG: define weak_odr dllexport void @"\01??$exportedStatic@UExplicitInst_Exported@@@MemFunTmpl@@SAXXZ"()
-// GNU-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl14exportedStaticI21ExplicitInst_ExportedEEvv()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$exportedStatic@UExplicitInst_Exported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: define weak_odr dso_local dllexport void @_ZN10MemFunTmpl14exportedStaticI21ExplicitInst_ExportedEEvv()
template void MemFunTmpl::exportedStatic<ExplicitInst_Exported>();
// Export specialization of an exported member function template.
-// M32-DAG: define dllexport x86_thiscallcc void @"\01??$exportedNormal@UExplicitSpec_Def_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
-// M64-DAG: define dllexport void @"\01??$exportedNormal@UExplicitSpec_Def_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
-// G32-DAG: define dllexport x86_thiscallcc void @_ZN10MemFunTmpl14exportedNormalI25ExplicitSpec_Def_ExportedEEvv(%struct.MemFunTmpl* %this)
-// G64-DAG: define dllexport void @_ZN10MemFunTmpl14exportedNormalI25ExplicitSpec_Def_ExportedEEvv(%struct.MemFunTmpl* %this)
+// M32-DAG: define dso_local dllexport x86_thiscallcc void @"??$exportedNormal@UExplicitSpec_Def_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
+// M64-DAG: define dso_local dllexport void @"??$exportedNormal@UExplicitSpec_Def_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
+// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN10MemFunTmpl14exportedNormalI25ExplicitSpec_Def_ExportedEEvv(%struct.MemFunTmpl* %this)
+// G64-DAG: define dso_local dllexport void @_ZN10MemFunTmpl14exportedNormalI25ExplicitSpec_Def_ExportedEEvv(%struct.MemFunTmpl* %this)
template<> __declspec(dllexport) void MemFunTmpl::exportedNormal<ExplicitSpec_Def_Exported>() {}
-// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??$exportedNormal@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
-// M64-DAG: define weak_odr dllexport void @"\01??$exportedNormal@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
-// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN10MemFunTmpl14exportedNormalI31ExplicitSpec_InlineDef_ExportedEEvv(%struct.MemFunTmpl* %this)
-// G64-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl14exportedNormalI31ExplicitSpec_InlineDef_ExportedEEvv(%struct.MemFunTmpl* %this)
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"??$exportedNormal@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
+// M64-DAG: define weak_odr dso_local dllexport void @"??$exportedNormal@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
+// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN10MemFunTmpl14exportedNormalI31ExplicitSpec_InlineDef_ExportedEEvv(%struct.MemFunTmpl* %this)
+// G64-DAG: define weak_odr dso_local dllexport void @_ZN10MemFunTmpl14exportedNormalI31ExplicitSpec_InlineDef_ExportedEEvv(%struct.MemFunTmpl* %this)
template<> __declspec(dllexport) inline void MemFunTmpl::exportedNormal<ExplicitSpec_InlineDef_Exported>() {}
-// MSC-DAG: define dllexport void @"\01??$exportedStatic@UExplicitSpec_Def_Exported@@@MemFunTmpl@@SAXXZ"()
-// GNU-DAG: define dllexport void @_ZN10MemFunTmpl14exportedStaticI25ExplicitSpec_Def_ExportedEEvv()
+// MSC-DAG: define dso_local dllexport void @"??$exportedStatic@UExplicitSpec_Def_Exported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: define dso_local dllexport void @_ZN10MemFunTmpl14exportedStaticI25ExplicitSpec_Def_ExportedEEvv()
template<> __declspec(dllexport) void MemFunTmpl::exportedStatic<ExplicitSpec_Def_Exported>() {}
-// MSC-DAG: define weak_odr dllexport void @"\01??$exportedStatic@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@SAXXZ"()
-// GNU-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl14exportedStaticI31ExplicitSpec_InlineDef_ExportedEEvv()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$exportedStatic@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: define weak_odr dso_local dllexport void @_ZN10MemFunTmpl14exportedStaticI31ExplicitSpec_InlineDef_ExportedEEvv()
template<> __declspec(dllexport) inline void MemFunTmpl::exportedStatic<ExplicitSpec_InlineDef_Exported>() {}
// Not exporting specialization of an exported member function template without
-// explicit dllexport.
-// M32-DAG: define x86_thiscallcc void @"\01??$exportedNormal@UExplicitSpec_NotExported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
-// M64-DAG: define void @"\01??$exportedNormal@UExplicitSpec_NotExported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
-// G32-DAG: define x86_thiscallcc void @_ZN10MemFunTmpl14exportedNormalI24ExplicitSpec_NotExportedEEvv(%struct.MemFunTmpl* %this)
-// G64-DAG: define void @_ZN10MemFunTmpl14exportedNormalI24ExplicitSpec_NotExportedEEvv(%struct.MemFunTmpl* %this)
+// explicit dso_local dllexport.
+// M32-DAG: define dso_local x86_thiscallcc void @"??$exportedNormal@UExplicitSpec_NotExported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
+// M64-DAG: define dso_local void @"??$exportedNormal@UExplicitSpec_NotExported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
+// G32-DAG: define dso_local x86_thiscallcc void @_ZN10MemFunTmpl14exportedNormalI24ExplicitSpec_NotExportedEEvv(%struct.MemFunTmpl* %this)
+// G64-DAG: define dso_local void @_ZN10MemFunTmpl14exportedNormalI24ExplicitSpec_NotExportedEEvv(%struct.MemFunTmpl* %this)
template<> void MemFunTmpl::exportedNormal<ExplicitSpec_NotExported>() {}
-// M32-DAG: define void @"\01??$exportedStatic@UExplicitSpec_NotExported@@@MemFunTmpl@@SAXXZ"()
-// GNU-DAG: define void @_ZN10MemFunTmpl14exportedStaticI24ExplicitSpec_NotExportedEEvv()
+// M32-DAG: define dso_local void @"??$exportedStatic@UExplicitSpec_NotExported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: define dso_local void @_ZN10MemFunTmpl14exportedStaticI24ExplicitSpec_NotExportedEEvv()
template<> void MemFunTmpl::exportedStatic<ExplicitSpec_NotExported>() {}
// Export explicit instantiation declaration of a non-exported member function
// template.
-// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??$normalDef@UExplicitDecl_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
-// M64-DAG: define weak_odr dllexport void @"\01??$normalDef@UExplicitDecl_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
-// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI21ExplicitDecl_ExportedEEvv(%struct.MemFunTmpl* %this)
-// G64-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl9normalDefI21ExplicitDecl_ExportedEEvv(%struct.MemFunTmpl* %this)
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"??$normalDef@UExplicitDecl_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
+// M64-DAG: define weak_odr dso_local dllexport void @"??$normalDef@UExplicitDecl_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
+// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI21ExplicitDecl_ExportedEEvv(%struct.MemFunTmpl* %this)
+// G64-DAG: define weak_odr dso_local dllexport void @_ZN10MemFunTmpl9normalDefI21ExplicitDecl_ExportedEEvv(%struct.MemFunTmpl* %this)
extern template __declspec(dllexport) void MemFunTmpl::normalDef<ExplicitDecl_Exported>();
template __declspec(dllexport) void MemFunTmpl::normalDef<ExplicitDecl_Exported>();
-// M32-DAG: define weak_odr dllexport void @"\01??$staticDef@UExplicitDecl_Exported@@@MemFunTmpl@@SAXXZ"()
-// GNU-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl9staticDefI21ExplicitDecl_ExportedEEvv()
+// M32-DAG: define weak_odr dso_local dllexport void @"??$staticDef@UExplicitDecl_Exported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: define weak_odr dso_local dllexport void @_ZN10MemFunTmpl9staticDefI21ExplicitDecl_ExportedEEvv()
extern template __declspec(dllexport) void MemFunTmpl::staticDef<ExplicitDecl_Exported>();
template __declspec(dllexport) void MemFunTmpl::staticDef<ExplicitDecl_Exported>();
// Export explicit instantiation definition of a non-exported member function
// template.
-// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??$normalDef@UExplicitInst_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
-// M64-DAG: define weak_odr dllexport void @"\01??$normalDef@UExplicitInst_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
-// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI21ExplicitInst_ExportedEEvv(%struct.MemFunTmpl* %this)
-// G64-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl9normalDefI21ExplicitInst_ExportedEEvv(%struct.MemFunTmpl* %this)
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"??$normalDef@UExplicitInst_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
+// M64-DAG: define weak_odr dso_local dllexport void @"??$normalDef@UExplicitInst_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
+// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI21ExplicitInst_ExportedEEvv(%struct.MemFunTmpl* %this)
+// G64-DAG: define weak_odr dso_local dllexport void @_ZN10MemFunTmpl9normalDefI21ExplicitInst_ExportedEEvv(%struct.MemFunTmpl* %this)
template __declspec(dllexport) void MemFunTmpl::normalDef<ExplicitInst_Exported>();
-// MSC-DAG: define weak_odr dllexport void @"\01??$staticDef@UExplicitInst_Exported@@@MemFunTmpl@@SAXXZ"()
-// GNU-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl9staticDefI21ExplicitInst_ExportedEEvv()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$staticDef@UExplicitInst_Exported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: define weak_odr dso_local dllexport void @_ZN10MemFunTmpl9staticDefI21ExplicitInst_ExportedEEvv()
template __declspec(dllexport) void MemFunTmpl::staticDef<ExplicitInst_Exported>();
// Export specialization of a non-exported member function template.
-// M32-DAG: define dllexport x86_thiscallcc void @"\01??$normalDef@UExplicitSpec_Def_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
-// M64-DAG: define dllexport void @"\01??$normalDef@UExplicitSpec_Def_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
-// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??$normalDef@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
-// M64-DAG: define weak_odr dllexport void @"\01??$normalDef@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
-// G32-DAG: define dllexport x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI25ExplicitSpec_Def_ExportedEEvv(%struct.MemFunTmpl* %this)
-// G64-DAG: define dllexport void @_ZN10MemFunTmpl9normalDefI25ExplicitSpec_Def_ExportedEEvv(%struct.MemFunTmpl* %this)
-// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI31ExplicitSpec_InlineDef_ExportedEEvv(%struct.MemFunTmpl* %this)
-// G64-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl9normalDefI31ExplicitSpec_InlineDef_ExportedEEvv(%struct.MemFunTmpl* %this)
+// M32-DAG: define dso_local dllexport x86_thiscallcc void @"??$normalDef@UExplicitSpec_Def_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
+// M64-DAG: define dso_local dllexport void @"??$normalDef@UExplicitSpec_Def_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"??$normalDef@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
+// M64-DAG: define weak_odr dso_local dllexport void @"??$normalDef@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
+// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI25ExplicitSpec_Def_ExportedEEvv(%struct.MemFunTmpl* %this)
+// G64-DAG: define dso_local dllexport void @_ZN10MemFunTmpl9normalDefI25ExplicitSpec_Def_ExportedEEvv(%struct.MemFunTmpl* %this)
+// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI31ExplicitSpec_InlineDef_ExportedEEvv(%struct.MemFunTmpl* %this)
+// G64-DAG: define weak_odr dso_local dllexport void @_ZN10MemFunTmpl9normalDefI31ExplicitSpec_InlineDef_ExportedEEvv(%struct.MemFunTmpl* %this)
template<> __declspec(dllexport) void MemFunTmpl::normalDef<ExplicitSpec_Def_Exported>() {}
template<> __declspec(dllexport) inline void MemFunTmpl::normalDef<ExplicitSpec_InlineDef_Exported>() {}
-// MSC-DAG: define dllexport void @"\01??$staticDef@UExplicitSpec_Def_Exported@@@MemFunTmpl@@SAXXZ"()
-// MSC-DAG: define weak_odr dllexport void @"\01??$staticDef@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@SAXXZ"()
-// GNU-DAG: define dllexport void @_ZN10MemFunTmpl9staticDefI25ExplicitSpec_Def_ExportedEEvv()
-// GNU-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl9staticDefI31ExplicitSpec_InlineDef_ExportedEEvv()
+// MSC-DAG: define dso_local dllexport void @"??$staticDef@UExplicitSpec_Def_Exported@@@MemFunTmpl@@SAXXZ"()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$staticDef@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: define dso_local dllexport void @_ZN10MemFunTmpl9staticDefI25ExplicitSpec_Def_ExportedEEvv()
+// GNU-DAG: define weak_odr dso_local dllexport void @_ZN10MemFunTmpl9staticDefI31ExplicitSpec_InlineDef_ExportedEEvv()
template<> __declspec(dllexport) void MemFunTmpl::staticDef<ExplicitSpec_Def_Exported>() {}
template<> __declspec(dllexport) inline void MemFunTmpl::staticDef<ExplicitSpec_InlineDef_Exported>() {}
@@ -633,49 +633,49 @@ template<typename T> const int MemVarTmpl::StaticVar;
template<typename T> const int MemVarTmpl::ExportedStaticVar;
// Export implicit instantiation of an exported member variable template.
-// MSC-DAG: @"\01??$ExportedStaticVar@UImplicitInst_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4
-// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI21ImplicitInst_ExportedEE = weak_odr dllexport constant i32 1, comdat, align 4
+// MSC-DAG: @"??$ExportedStaticVar@UImplicitInst_Exported@@@MemVarTmpl@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
+// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI21ImplicitInst_ExportedEE = weak_odr dso_local dllexport constant i32 1, comdat, align 4
int useMemVarTmpl() { return MemVarTmpl::ExportedStaticVar<ImplicitInst_Exported>; }
// Export explicit instantiation declaration of an exported member variable
// template.
-// MSC-DAG: @"\01??$ExportedStaticVar@UExplicitDecl_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4
-// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI21ExplicitDecl_ExportedEE = weak_odr dllexport constant i32 1, comdat, align 4
+// MSC-DAG: @"??$ExportedStaticVar@UExplicitDecl_Exported@@@MemVarTmpl@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
+// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI21ExplicitDecl_ExportedEE = weak_odr dso_local dllexport constant i32 1, comdat, align 4
extern template const int MemVarTmpl::ExportedStaticVar<ExplicitDecl_Exported>;
template const int MemVarTmpl::ExportedStaticVar<ExplicitDecl_Exported>;
// Export explicit instantiation definition of an exported member variable
// template.
-// MSC-DAG: @"\01??$ExportedStaticVar@UExplicitInst_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4
-// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI21ExplicitInst_ExportedEE = weak_odr dllexport constant i32 1, comdat, align 4
+// MSC-DAG: @"??$ExportedStaticVar@UExplicitInst_Exported@@@MemVarTmpl@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
+// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI21ExplicitInst_ExportedEE = weak_odr dso_local dllexport constant i32 1, comdat, align 4
template const int MemVarTmpl::ExportedStaticVar<ExplicitInst_Exported>;
// Export specialization of an exported member variable template.
-// MSC-DAG: @"\01??$ExportedStaticVar@UExplicitSpec_Def_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4
-// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI25ExplicitSpec_Def_ExportedEE = dllexport constant i32 1, align 4
+// MSC-DAG: @"??$ExportedStaticVar@UExplicitSpec_Def_Exported@@@MemVarTmpl@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
+// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI25ExplicitSpec_Def_ExportedEE = dso_local dllexport constant i32 1, align 4
template<> __declspec(dllexport) const int MemVarTmpl::ExportedStaticVar<ExplicitSpec_Def_Exported> = 1;
// Not exporting specialization of an exported member variable template without
// explicit dllexport.
-// MSC-DAG: @"\01??$ExportedStaticVar@UExplicitSpec_NotExported@@@MemVarTmpl@@2HB" = weak_odr constant i32 1, comdat, align 4
-// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI24ExplicitSpec_NotExportedEE = constant i32 1, align 4
+// MSC-DAG: @"??$ExportedStaticVar@UExplicitSpec_NotExported@@@MemVarTmpl@@2HB" = weak_odr dso_local constant i32 1, comdat, align 4
+// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI24ExplicitSpec_NotExportedEE = dso_local constant i32 1, align 4
template<> const int MemVarTmpl::ExportedStaticVar<ExplicitSpec_NotExported> = 1;
// Export explicit instantiation declaration of a non-exported member variable
// template.
-// MSC-DAG: @"\01??$StaticVar@UExplicitDecl_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4
-// GNU-DAG: @_ZN10MemVarTmpl9StaticVarI21ExplicitDecl_ExportedEE = weak_odr dllexport constant i32 1, comdat, align 4
+// MSC-DAG: @"??$StaticVar@UExplicitDecl_Exported@@@MemVarTmpl@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
+// GNU-DAG: @_ZN10MemVarTmpl9StaticVarI21ExplicitDecl_ExportedEE = weak_odr dso_local dllexport constant i32 1, comdat, align 4
extern template __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitDecl_Exported>;
template __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitDecl_Exported>;
// Export explicit instantiation definition of a non-exported member variable
// template.
-// MSC-DAG: @"\01??$StaticVar@UExplicitInst_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4
-// GNU-DAG: @_ZN10MemVarTmpl9StaticVarI21ExplicitInst_ExportedEE = weak_odr dllexport constant i32 1, comdat, align 4
+// MSC-DAG: @"??$StaticVar@UExplicitInst_Exported@@@MemVarTmpl@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
+// GNU-DAG: @_ZN10MemVarTmpl9StaticVarI21ExplicitInst_ExportedEE = weak_odr dso_local dllexport constant i32 1, comdat, align 4
template __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitInst_Exported>;
// Export specialization of a non-exported member variable template.
-// MSC-DAG: @"\01??$StaticVar@UExplicitSpec_Def_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4
-// GNU-DAG: @_ZN10MemVarTmpl9StaticVarI25ExplicitSpec_Def_ExportedEE = dllexport constant i32 1, align 4
+// MSC-DAG: @"??$StaticVar@UExplicitSpec_Def_Exported@@@MemVarTmpl@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
+// GNU-DAG: @_ZN10MemVarTmpl9StaticVarI25ExplicitSpec_Def_ExportedEE = dso_local dllexport constant i32 1, align 4
template<> __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitSpec_Def_Exported> = 1;
diff --git a/test/CodeGenCXX/dllexport-ms-friend.cpp b/test/CodeGenCXX/dllexport-ms-friend.cpp
index 7bcf5905e5e5..670264704e89 100644
--- a/test/CodeGenCXX/dllexport-ms-friend.cpp
+++ b/test/CodeGenCXX/dllexport-ms-friend.cpp
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -triple %ms_abi_triple -fms-extensions -emit-llvm -O0 -o - %s | FileCheck %s
// Friend functions defined in classes are emitted.
-// CHECK: define weak_odr dllexport void @"\01?friend1@@YAXXZ"()
+// CHECK: define weak_odr dso_local dllexport void @"?friend1@@YAXXZ"()
struct FuncFriend1 {
friend __declspec(dllexport) void friend1() {}
};
diff --git a/test/CodeGenCXX/dllexport-pr26549.cpp b/test/CodeGenCXX/dllexport-pr26549.cpp
index ceb2e0685ef1..c5ac1c1dea3a 100644
--- a/test/CodeGenCXX/dllexport-pr26549.cpp
+++ b/test/CodeGenCXX/dllexport-pr26549.cpp
@@ -3,7 +3,7 @@
template <typename> struct MessageT { };
extern template struct MessageT<int>;
-// CHECK: define weak_odr dllexport {{.*}} %struct.MessageT* @"\01??4?$MessageT@H@@QEAAAEAU0@AEBU0@@Z"(
+// CHECK: define weak_odr dso_local dllexport {{.*}} %struct.MessageT* @"??4?$MessageT@H@@QEAAAEAU0@AEBU0@@Z"(
template struct __declspec(dllexport) MessageT<int>;
// Previously we crashed when this dllexport was the last thing in the file.
// DO NOT ADD MORE TESTS AFTER THIS LINE!
diff --git a/test/CodeGenCXX/dllexport-vtable-thunks.cpp b/test/CodeGenCXX/dllexport-vtable-thunks.cpp
index 81811ace2ee6..52947840d8d1 100644
--- a/test/CodeGenCXX/dllexport-vtable-thunks.cpp
+++ b/test/CodeGenCXX/dllexport-vtable-thunks.cpp
@@ -11,7 +11,7 @@ struct __declspec(dllexport) C : A, B {
virtual void m();
};
void C::m() {}
-// CHECK: define dllexport void @_ZThn8_N1C1mEv
+// CHECK: define dso_local dllexport void @_ZThn8_N1C1mEv
struct Base {
virtual void m();
@@ -20,4 +20,4 @@ struct __declspec(dllexport) Derived : virtual Base {
virtual void m();
};
void Derived::m() {}
-// CHECK: define dllexport void @_ZTv0_n24_N7Derived1mEv
+// CHECK: define dso_local dllexport void @_ZTv0_n24_N7Derived1mEv
diff --git a/test/CodeGenCXX/dllexport.cpp b/test/CodeGenCXX/dllexport.cpp
index a446147b6cdc..a7b6aad357e5 100644
--- a/test/CodeGenCXX/dllexport.cpp
+++ b/test/CodeGenCXX/dllexport.cpp
@@ -1,11 +1,11 @@
-// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O1 -mconstructor-aliases -disable-llvm-passes -o - %s -w -fms-compatibility-version=19.00 | FileCheck --check-prefix=MSC --check-prefix=M32 -check-prefix=MSVC2015 -check-prefix=M32MSVC2015 %s
-// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O1 -mconstructor-aliases -disable-llvm-passes -o - %s -w -fms-compatibility-version=18.00 | FileCheck --check-prefix=MSC --check-prefix=M32 -check-prefix=MSVC2013 -check-prefix=M32MSVC2013 %s
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O1 -mconstructor-aliases -disable-llvm-passes -o - %s -w -fms-compatibility-version=19.00 | FileCheck -allow-deprecated-dag-overlap --check-prefix=MSC --check-prefix=M32 -check-prefix=MSVC2015 -check-prefix=M32MSVC2015 %s
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O1 -mconstructor-aliases -disable-llvm-passes -o - %s -w -fms-compatibility-version=18.00 | FileCheck -allow-deprecated-dag-overlap --check-prefix=MSC --check-prefix=M32 -check-prefix=MSVC2013 -check-prefix=M32MSVC2013 %s
-// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O0 -o - %s -w -fms-compatibility-version=19.00 | FileCheck --check-prefix=MSC --check-prefix=M64 -check-prefix=MSVC2015 -check-prefix=M64MSVC2015 %s
-// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O0 -o - %s -w -fms-compatibility-version=18.00 | FileCheck --check-prefix=MSC --check-prefix=M64 -check-prefix=MSVC2013 -check-prefix=M64MSVC2013 %s
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O0 -o - %s -w -fms-compatibility-version=19.00 | FileCheck -allow-deprecated-dag-overlap --check-prefix=MSC --check-prefix=M64 -check-prefix=MSVC2015 -check-prefix=M64MSVC2015 %s
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O0 -o - %s -w -fms-compatibility-version=18.00 | FileCheck -allow-deprecated-dag-overlap --check-prefix=MSC --check-prefix=M64 -check-prefix=MSVC2013 -check-prefix=M64MSVC2013 %s
-// RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O0 -o - %s -w | FileCheck --check-prefix=GNU --check-prefix=G32 %s
-// RUN: %clang_cc1 -triple x86_64-windows-gnu -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O0 -o - %s -w | FileCheck --check-prefix=GNU --check-prefix=G64 %s
+// RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O0 -o - %s -w | FileCheck -allow-deprecated-dag-overlap --check-prefix=GNU --check-prefix=G32 %s
+// RUN: %clang_cc1 -triple x86_64-windows-gnu -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O0 -o - %s -w | FileCheck -allow-deprecated-dag-overlap --check-prefix=GNU --check-prefix=G64 %s
// Helper structs to make templates more expressive.
struct ImplicitInst_Exported {};
@@ -27,7 +27,9 @@ struct External { int v; };
#define INST(func) template void func();
// The vftable for struct W is comdat largest because we have RTTI.
-// M32-DAG: $"\01??_7W@@6B@" = comdat largest
+// M32-DAG: $"??_7W@@6B@" = comdat largest
+
+// M32-DAG: $"?smember@?$Base@H@PR32992@@0HA" = comdat any
//===----------------------------------------------------------------------===//
@@ -35,66 +37,98 @@ struct External { int v; };
//===----------------------------------------------------------------------===//
// Declarations are not exported.
-// MSC-NOT: @"\01?ExternGlobalDecl@@3HA"
+// MSC-NOT: @"?ExternGlobalDecl@@3HA"
// GNU-NOT: @ExternGlobalDecl
__declspec(dllexport) extern int ExternGlobalDecl;
+// M64-DAG: @__ImageBase = external dso_local constant i8
+
+// GNU-DAG: @_ZTVN10__cxxabiv117__class_type_infoE = external dso_local global
+
// dllexport implies a definition.
-// MSC-DAG: @"\01?GlobalDef@@3HA" = dllexport global i32 0, align 4
-// GNU-DAG: @GlobalDef = dllexport global i32 0, align 4
+// MSC-DAG: @"?GlobalDef@@3HA" = dso_local dllexport global i32 0, align 4
+// GNU-DAG: @GlobalDef = dso_local dllexport global i32 0, align 4
__declspec(dllexport) int GlobalDef;
// Export definition.
-// MSC-DAG: @"\01?GlobalInit1@@3HA" = dllexport global i32 1, align 4
-// GNU-DAG: @GlobalInit1 = dllexport global i32 1, align 4
+// MSC-DAG: @"?GlobalInit1@@3HA" = dso_local dllexport global i32 1, align 4
+// GNU-DAG: @GlobalInit1 = dso_local dllexport global i32 1, align 4
__declspec(dllexport) int GlobalInit1 = 1;
-// MSC-DAG: @"\01?GlobalInit2@@3HA" = dllexport global i32 1, align 4
-// GNU-DAG: @GlobalInit2 = dllexport global i32 1, align 4
+// MSC-DAG: @"?GlobalInit2@@3HA" = dso_local dllexport global i32 1, align 4
+// GNU-DAG: @GlobalInit2 = dso_local dllexport global i32 1, align 4
int __declspec(dllexport) GlobalInit2 = 1;
// Declare, then export definition.
-// MSC-DAG: @"\01?GlobalDeclInit@@3HA" = dllexport global i32 1, align 4
-// GNU-DAG: @GlobalDeclInit = dllexport global i32 1, align 4
+// MSC-DAG: @"?GlobalDeclInit@@3HA" = dso_local dllexport global i32 1, align 4
+// GNU-DAG: @GlobalDeclInit = dso_local dllexport global i32 1, align 4
__declspec(dllexport) extern int GlobalDeclInit;
int GlobalDeclInit = 1;
// Redeclarations
-// MSC-DAG: @"\01?GlobalRedecl1@@3HA" = dllexport global i32 0, align 4
-// GNU-DAG: @GlobalRedecl1 = dllexport global i32 0, align 4
+// MSC-DAG: @"?GlobalRedecl1@@3HA" = dso_local dllexport global i32 0, align 4
+// GNU-DAG: @GlobalRedecl1 = dso_local dllexport global i32 0, align 4
__declspec(dllexport) extern int GlobalRedecl1;
__declspec(dllexport) int GlobalRedecl1;
-// MSC-DAG: @"\01?GlobalRedecl2@@3HA" = dllexport global i32 0, align 4
-// GNU-DAG: @GlobalRedecl2 = dllexport global i32 0, align 4
+// MSC-DAG: @"?GlobalRedecl2@@3HA" = dso_local dllexport global i32 0, align 4
+// GNU-DAG: @GlobalRedecl2 = dso_local dllexport global i32 0, align 4
__declspec(dllexport) extern int GlobalRedecl2;
int GlobalRedecl2;
-// MSC-DAG: @"\01?ExternalGlobal@ns@@3HA" = dllexport global i32 0, align 4
-// GNU-DAG: @_ZN2ns14ExternalGlobalE = dllexport global i32 0, align 4
+// MSC-DAG: @"?ExternalGlobal@ns@@3HA" = dso_local dllexport global i32 0, align 4
+// GNU-DAG: @_ZN2ns14ExternalGlobalE = dso_local dllexport global i32 0, align 4
namespace ns { __declspec(dllexport) int ExternalGlobal; }
-// MSC-DAG: @"\01?ExternalAutoTypeGlobal@@3UExternal@@A" = dllexport global %struct.External zeroinitializer, align 4
-// GNU-DAG: @ExternalAutoTypeGlobal = dllexport global %struct.External zeroinitializer, align 4
+// MSC-DAG: @"?ExternalAutoTypeGlobal@@3UExternal@@A" = dso_local dllexport global %struct.External zeroinitializer, align 4
+// GNU-DAG: @ExternalAutoTypeGlobal = dso_local dllexport global %struct.External zeroinitializer, align 4
__declspec(dllexport) auto ExternalAutoTypeGlobal = External();
int f();
-// MSC-DAG: @"\01?x@?1??nonInlineStaticLocalsFunc@@YAHXZ@4HA" = internal {{(unnamed_addr )*}}global i32 0
-// MSC-DAG: @"\01?$S1@?1??nonInlineStaticLocalsFunc@@YAHXZ@4IA" = internal {{(unnamed_addr )*}}global i32 0
+// MSC-DAG: @"?x@?1??nonInlineStaticLocalsFunc@@YAHXZ@4HA" = internal {{(unnamed_addr )*}}global i32 0
+// MSC-DAG: @"?$S1@?1??nonInlineStaticLocalsFunc@@YAHXZ@4IA" = internal {{(unnamed_addr )*}}global i32 0
int __declspec(dllexport) nonInlineStaticLocalsFunc() {
static int x = f();
return x++;
};
-// MSC-DAG: @"\01?x@?1??inlineStaticLocalsFunc@@YAHXZ@4HA" = weak_odr dllexport global i32 0, comdat
-// MSC-DAG: @"\01??_B?1??inlineStaticLocalsFunc@@YAHXZ@51" = weak_odr dllexport global i32 0, comdat
+// MSC-DAG: @"?x@?1??inlineStaticLocalsFunc@@YAHXZ@4HA" = weak_odr dso_local dllexport global i32 0, comdat
+// MSC-DAG: @"??_B?1??inlineStaticLocalsFunc@@YAHXZ@51" = weak_odr dllexport global i32 0, comdat
// Note: MinGW doesn't seem to export the static local here.
inline int __declspec(dllexport) inlineStaticLocalsFunc() {
static int x = f();
return x++;
}
+namespace PR32992 {
+// Static data members of a instantiated base class should be exported.
+template <class T>
+class Base {
+ virtual void myfunc() {}
+ static int smember;
+};
+// MSC-DAG: @"?smember@?$Base@H@PR32992@@0HA" = weak_odr dso_local dllexport global i32 77, comdat, align 4
+template <class T> int Base<T>::smember = 77;
+template <class T>
+class __declspec(dllexport) Derived2 : Base<T> {
+ void myfunc() {}
+};
+class Derived : public Derived2<int> {
+ void myfunc() {}
+};
+} // namespace PR32992
+namespace PR32992_1 {
+namespace a { enum b { c }; }
+template <typename> class d {
+ static constexpr a::b e = a::c;
+};
+namespace f {
+ template <typename g = int> class h : d<g> {};
+}
+using f::h;
+class __declspec(dllexport) i : h<> {};
+}
//===----------------------------------------------------------------------===//
// Variable templates
@@ -102,49 +136,49 @@ inline int __declspec(dllexport) inlineStaticLocalsFunc() {
// Declarations are not exported.
-// MSC-DAG: @"\01??$VarTmplImplicitDef@UImplicitInst_Exported@@@@3HA" = external global
-// GNU-DAG: @_Z18VarTmplImplicitDefI21ImplicitInst_ExportedE = external global
+// MSC-DAG: @"??$VarTmplImplicitDef@UImplicitInst_Exported@@@@3HA" = external dso_local global
+// GNU-DAG: @_Z18VarTmplImplicitDefI21ImplicitInst_ExportedE = external dso_local global
template<typename T> __declspec(dllexport) extern int VarTmplImplicitDef;
USEVAR(VarTmplImplicitDef<ImplicitInst_Exported>)
// Export definition.
-// MSC-DAG: @"\01??$VarTmplInit1@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, comdat, align 4
-// GNU-DAG: @_Z12VarTmplInit1I21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, comdat, align 4
+// MSC-DAG: @"??$VarTmplInit1@UExplicitInst_Exported@@@@3HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
+// GNU-DAG: @_Z12VarTmplInit1I21ExplicitInst_ExportedE = weak_odr dso_local dllexport global i32 1, comdat, align 4
template<typename T> __declspec(dllexport) int VarTmplInit1 = 1;
INSTVAR(VarTmplInit1<ExplicitInst_Exported>)
-// MSC-DAG: @"\01??$VarTmplInit2@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, comdat, align 4
-// GNU-DAG: @_Z12VarTmplInit2I21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, comdat, align 4
+// MSC-DAG: @"??$VarTmplInit2@UExplicitInst_Exported@@@@3HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
+// GNU-DAG: @_Z12VarTmplInit2I21ExplicitInst_ExportedE = weak_odr dso_local dllexport global i32 1, comdat, align 4
template<typename T> int __declspec(dllexport) VarTmplInit2 = 1;
INSTVAR(VarTmplInit2<ExplicitInst_Exported>)
// Declare, then export definition.
-// MSC-DAG: @"\01??$VarTmplDeclInit@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, comdat, align 4
-// GNU-DAG: @_Z15VarTmplDeclInitI21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, comdat, align 4
+// MSC-DAG: @"??$VarTmplDeclInit@UExplicitInst_Exported@@@@3HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
+// GNU-DAG: @_Z15VarTmplDeclInitI21ExplicitInst_ExportedE = weak_odr dso_local dllexport global i32 1, comdat, align 4
template<typename T> __declspec(dllexport) extern int VarTmplDeclInit;
template<typename T> int VarTmplDeclInit = 1;
INSTVAR(VarTmplDeclInit<ExplicitInst_Exported>)
// Redeclarations
-// MSC-DAG: @"\01??$VarTmplRedecl1@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, comdat, align 4
-// GNU-DAG: @_Z14VarTmplRedecl1I21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, comdat, align 4
+// MSC-DAG: @"??$VarTmplRedecl1@UExplicitInst_Exported@@@@3HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
+// GNU-DAG: @_Z14VarTmplRedecl1I21ExplicitInst_ExportedE = weak_odr dso_local dllexport global i32 1, comdat, align 4
template<typename T> __declspec(dllexport) extern int VarTmplRedecl1;
template<typename T> __declspec(dllexport) int VarTmplRedecl1 = 1;
INSTVAR(VarTmplRedecl1<ExplicitInst_Exported>)
-// MSC-DAG: @"\01??$VarTmplRedecl2@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, comdat, align 4
-// GNU-DAG: @_Z14VarTmplRedecl2I21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, comdat, align 4
+// MSC-DAG: @"??$VarTmplRedecl2@UExplicitInst_Exported@@@@3HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
+// GNU-DAG: @_Z14VarTmplRedecl2I21ExplicitInst_ExportedE = weak_odr dso_local dllexport global i32 1, comdat, align 4
template<typename T> __declspec(dllexport) extern int VarTmplRedecl2;
template<typename T> int VarTmplRedecl2 = 1;
INSTVAR(VarTmplRedecl2<ExplicitInst_Exported>)
-// MSC-DAG: @"\01??$ExternalVarTmpl@UExplicitInst_Exported@@@ns@@3HA" = weak_odr dllexport global i32 1, comdat, align 4
-// GNU-DAG: @_ZN2ns15ExternalVarTmplI21ExplicitInst_ExportedEE = weak_odr dllexport global i32 1, comdat, align 4
+// MSC-DAG: @"??$ExternalVarTmpl@UExplicitInst_Exported@@@ns@@3HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
+// GNU-DAG: @_ZN2ns15ExternalVarTmplI21ExplicitInst_ExportedEE = weak_odr dso_local dllexport global i32 1, comdat, align 4
namespace ns { template<typename T> __declspec(dllexport) int ExternalVarTmpl = 1; }
INSTVAR(ns::ExternalVarTmpl<ExplicitInst_Exported>)
-// MSC-DAG: @"\01??$ExternalAutoTypeVarTmpl@UExplicitInst_Exported@@@@3UExternal@@A" = weak_odr dllexport global %struct.External zeroinitializer, comdat, align 4
-// GNU-DAG: @_Z23ExternalAutoTypeVarTmplI21ExplicitInst_ExportedE = weak_odr dllexport global %struct.External zeroinitializer, comdat, align 4
+// MSC-DAG: @"??$ExternalAutoTypeVarTmpl@UExplicitInst_Exported@@@@3UExternal@@A" = weak_odr dso_local dllexport global %struct.External zeroinitializer, comdat, align 4
+// GNU-DAG: @_Z23ExternalAutoTypeVarTmplI21ExplicitInst_ExportedE = weak_odr dso_local dllexport global %struct.External zeroinitializer, comdat, align 4
template<typename T> __declspec(dllexport) auto ExternalAutoTypeVarTmpl = External();
template External ExternalAutoTypeVarTmpl<ExplicitInst_Exported>;
@@ -153,55 +187,55 @@ template<typename T> int VarTmpl = 1;
template<typename T> __declspec(dllexport) int ExportedVarTmpl = 1;
// Export implicit instantiation of an exported variable template.
-// MSC-DAG: @"\01??$ExportedVarTmpl@UImplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, comdat, align 4
-// GNU-DAG: @_Z15ExportedVarTmplI21ImplicitInst_ExportedE = weak_odr dllexport global i32 1, comdat, align 4
+// MSC-DAG: @"??$ExportedVarTmpl@UImplicitInst_Exported@@@@3HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
+// GNU-DAG: @_Z15ExportedVarTmplI21ImplicitInst_ExportedE = weak_odr dso_local dllexport global i32 1, comdat, align 4
USEVAR(ExportedVarTmpl<ImplicitInst_Exported>)
// Export explicit instantiation declaration of an exported variable template.
-// MSC-DAG: @"\01??$ExportedVarTmpl@UImplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, comdat, align 4
-// GNU-DAG: @_Z15ExportedVarTmplI21ExplicitDecl_ExportedE = weak_odr dllexport global i32 1, comdat, align 4
+// MSC-DAG: @"??$ExportedVarTmpl@UImplicitInst_Exported@@@@3HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
+// GNU-DAG: @_Z15ExportedVarTmplI21ExplicitDecl_ExportedE = weak_odr dso_local dllexport global i32 1, comdat, align 4
extern template int ExportedVarTmpl<ExplicitDecl_Exported>;
template int ExportedVarTmpl<ExplicitDecl_Exported>;
// Export explicit instantiation definition of an exported variable template.
-// MSC-DAG: @"\01??$ExportedVarTmpl@UImplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, comdat, align 4
-// GNU-DAG: @_Z15ExportedVarTmplI21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, comdat, align 4
+// MSC-DAG: @"??$ExportedVarTmpl@UImplicitInst_Exported@@@@3HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
+// GNU-DAG: @_Z15ExportedVarTmplI21ExplicitInst_ExportedE = weak_odr dso_local dllexport global i32 1, comdat, align 4
template __declspec(dllexport) int ExportedVarTmpl<ExplicitInst_Exported>;
// Export specialization of an exported variable template.
-// MSC-DAG: @"\01??$ExportedVarTmpl@UExplicitSpec_Exported@@@@3HA" = dllexport global i32 0, align 4
-// GNU-DAG: @_Z15ExportedVarTmplI21ExplicitSpec_ExportedE = dllexport global i32 0, align 4
+// MSC-DAG: @"??$ExportedVarTmpl@UExplicitSpec_Exported@@@@3HA" = dso_local dllexport global i32 0, align 4
+// GNU-DAG: @_Z15ExportedVarTmplI21ExplicitSpec_ExportedE = dso_local dllexport global i32 0, align 4
template<> __declspec(dllexport) int ExportedVarTmpl<ExplicitSpec_Exported>;
-// MSC-DAG: @"\01??$ExportedVarTmpl@UExplicitSpec_Def_Exported@@@@3HA" = dllexport global i32 1, align 4
-// GNU-DAG: @_Z15ExportedVarTmplI25ExplicitSpec_Def_ExportedE = dllexport global i32 1, align 4
+// MSC-DAG: @"??$ExportedVarTmpl@UExplicitSpec_Def_Exported@@@@3HA" = dso_local dllexport global i32 1, align 4
+// GNU-DAG: @_Z15ExportedVarTmplI25ExplicitSpec_Def_ExportedE = dso_local dllexport global i32 1, align 4
template<> __declspec(dllexport) int ExportedVarTmpl<ExplicitSpec_Def_Exported> = 1;
// Not exporting specialization of an exported variable template without
// explicit dllexport.
-// MSC-DAG: @"\01??$ExportedVarTmpl@UExplicitSpec_NotExported@@@@3HA" = global i32 0, align 4
-// GNU-DAG: @_Z15ExportedVarTmplI24ExplicitSpec_NotExportedE = global i32 0, align 4
+// MSC-DAG: @"??$ExportedVarTmpl@UExplicitSpec_NotExported@@@@3HA" = dso_local global i32 0, align 4
+// GNU-DAG: @_Z15ExportedVarTmplI24ExplicitSpec_NotExportedE = dso_local global i32 0, align 4
template<> int ExportedVarTmpl<ExplicitSpec_NotExported>;
// Export explicit instantiation declaration of a non-exported variable template.
-// MSC-DAG: @"\01??$VarTmpl@UExplicitDecl_Exported@@@@3HA" = weak_odr dllexport global i32 1, comdat, align 4
-// GNU-DAG: @_Z7VarTmplI21ExplicitDecl_ExportedE = weak_odr dllexport global i32 1, comdat, align 4
+// MSC-DAG: @"??$VarTmpl@UExplicitDecl_Exported@@@@3HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
+// GNU-DAG: @_Z7VarTmplI21ExplicitDecl_ExportedE = weak_odr dso_local dllexport global i32 1, comdat, align 4
extern template __declspec(dllexport) int VarTmpl<ExplicitDecl_Exported>;
template __declspec(dllexport) int VarTmpl<ExplicitDecl_Exported>;
// Export explicit instantiation definition of a non-exported variable template.
-// MSC-DAG: @"\01??$VarTmpl@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, comdat, align 4
-// GNU-DAG: @_Z7VarTmplI21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, comdat, align 4
+// MSC-DAG: @"??$VarTmpl@UExplicitInst_Exported@@@@3HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
+// GNU-DAG: @_Z7VarTmplI21ExplicitInst_ExportedE = weak_odr dso_local dllexport global i32 1, comdat, align 4
template __declspec(dllexport) int VarTmpl<ExplicitInst_Exported>;
// Export specialization of a non-exported variable template.
-// MSC-DAG: @"\01??$VarTmpl@UExplicitSpec_Exported@@@@3HA" = dllexport global i32 0, align 4
-// GNU-DAG: @_Z7VarTmplI21ExplicitSpec_ExportedE = dllexport global i32 0, align 4
+// MSC-DAG: @"??$VarTmpl@UExplicitSpec_Exported@@@@3HA" = dso_local dllexport global i32 0, align 4
+// GNU-DAG: @_Z7VarTmplI21ExplicitSpec_ExportedE = dso_local dllexport global i32 0, align 4
template<> __declspec(dllexport) int VarTmpl<ExplicitSpec_Exported>;
-// MSC-DAG: @"\01??$VarTmpl@UExplicitSpec_Def_Exported@@@@3HA" = dllexport global i32 1, align 4
-// GNU-DAG: @_Z7VarTmplI25ExplicitSpec_Def_ExportedE = dllexport global i32 1, align 4
+// MSC-DAG: @"??$VarTmpl@UExplicitSpec_Def_Exported@@@@3HA" = dso_local dllexport global i32 1, align 4
+// GNU-DAG: @_Z7VarTmplI25ExplicitSpec_Def_ExportedE = dso_local dllexport global i32 1, align 4
template<> __declspec(dllexport) int VarTmpl<ExplicitSpec_Def_Exported> = 1;
@@ -213,46 +247,46 @@ template<> __declspec(dllexport) int VarTmpl<ExplicitSpec_Def_Exported> = 1;
// Declarations are not exported.
// Export function definition.
-// MSC-DAG: define dllexport void @"\01?def@@YAXXZ"()
-// GNU-DAG: define dllexport void @_Z3defv()
+// MSC-DAG: define dso_local dllexport void @"?def@@YAXXZ"()
+// GNU-DAG: define dso_local dllexport void @_Z3defv()
__declspec(dllexport) void def() {}
// extern "C"
-// MSC-DAG: define dllexport void @externC()
-// GNU-DAG: define dllexport void @externC()
+// MSC-DAG: define dso_local dllexport void @externC()
+// GNU-DAG: define dso_local dllexport void @externC()
extern "C" __declspec(dllexport) void externC() {}
// Export inline function.
-// MSC-DAG: define weak_odr dllexport void @"\01?inlineFunc@@YAXXZ"()
-// GNU-DAG: define weak_odr dllexport void @_Z10inlineFuncv()
+// MSC-DAG: define weak_odr dso_local dllexport void @"?inlineFunc@@YAXXZ"()
+// GNU-DAG: define weak_odr dso_local dllexport void @_Z10inlineFuncv()
__declspec(dllexport) inline void inlineFunc() {}
-// MSC-DAG: define weak_odr dllexport void @"\01?inlineDecl@@YAXXZ"()
-// GNU-DAG: define weak_odr dllexport void @_Z10inlineDeclv()
+// MSC-DAG: define weak_odr dso_local dllexport void @"?inlineDecl@@YAXXZ"()
+// GNU-DAG: define weak_odr dso_local dllexport void @_Z10inlineDeclv()
__declspec(dllexport) inline void inlineDecl();
void inlineDecl() {}
-// MSC-DAG: define weak_odr dllexport void @"\01?inlineDef@@YAXXZ"()
-// GNU-DAG: define weak_odr dllexport void @_Z9inlineDefv()
+// MSC-DAG: define weak_odr dso_local dllexport void @"?inlineDef@@YAXXZ"()
+// GNU-DAG: define weak_odr dso_local dllexport void @_Z9inlineDefv()
__declspec(dllexport) void inlineDef();
inline void inlineDef() {}
// Redeclarations
-// MSC-DAG: define dllexport void @"\01?redecl1@@YAXXZ"()
-// GNU-DAG: define dllexport void @_Z7redecl1v()
+// MSC-DAG: define dso_local dllexport void @"?redecl1@@YAXXZ"()
+// GNU-DAG: define dso_local dllexport void @_Z7redecl1v()
__declspec(dllexport) void redecl1();
__declspec(dllexport) void redecl1() {}
-// MSC-DAG: define dllexport void @"\01?redecl2@@YAXXZ"()
-// GNU-DAG: define dllexport void @_Z7redecl2v()
+// MSC-DAG: define dso_local dllexport void @"?redecl2@@YAXXZ"()
+// GNU-DAG: define dso_local dllexport void @_Z7redecl2v()
__declspec(dllexport) void redecl2();
void redecl2() {}
// Friend functions
-// MSC-DAG: define dllexport void @"\01?friend1@@YAXXZ"()
-// GNU-DAG: define dllexport void @_Z7friend1v()
-// MSC-DAG: define dllexport void @"\01?friend2@@YAXXZ"()
-// GNU-DAG: define dllexport void @_Z7friend2v()
+// MSC-DAG: define dso_local dllexport void @"?friend1@@YAXXZ"()
+// GNU-DAG: define dso_local dllexport void @_Z7friend1v()
+// MSC-DAG: define dso_local dllexport void @"?friend2@@YAXXZ"()
+// GNU-DAG: define dso_local dllexport void @_Z7friend2v()
struct FuncFriend {
friend __declspec(dllexport) void friend1();
friend __declspec(dllexport) void friend2();
@@ -260,14 +294,24 @@ struct FuncFriend {
__declspec(dllexport) void friend1() {}
void friend2() {}
+// MSC-DAG: define dso_local dllexport void @"?func@Befriended@@SAXXZ"()
+// GNU-DAG: define dso_local dllexport void @_ZN10Befriended4funcEv()
+struct __declspec(dllexport) Befriended {
+ static void func();
+ struct Befriending {
+ friend void Befriended::func();
+ };
+};
+void Befriended::func() {}
+
// Implicit declarations can be redeclared with dllexport.
-// MSC-DAG: define dllexport noalias i8* @"\01??2@{{YAPAXI|YAPEAX_K}}@Z"(
-// GNU-DAG: define dllexport noalias i8* @_Znw{{[yj]}}(
+// MSC-DAG: define dso_local dllexport noalias i8* @"??2@{{YAPAXI|YAPEAX_K}}@Z"(
+// GNU-DAG: define dso_local dllexport noalias i8* @_Znw{{[yj]}}(
void* alloc(__SIZE_TYPE__ n);
__declspec(dllexport) void* operator new(__SIZE_TYPE__ n) { return alloc(n); }
-// MSC-DAG: define dllexport void @"\01?externalFunc@ns@@YAXXZ"()
-// GNU-DAG: define dllexport void @_ZN2ns12externalFuncEv()
+// MSC-DAG: define dso_local dllexport void @"?externalFunc@ns@@YAXXZ"()
+// GNU-DAG: define dso_local dllexport void @_ZN2ns12externalFuncEv()
namespace ns { __declspec(dllexport) void externalFunc() {} }
@@ -277,60 +321,60 @@ namespace ns { __declspec(dllexport) void externalFunc() {} }
//===----------------------------------------------------------------------===//
// Export function template definition.
-// MSC-DAG: define weak_odr dllexport void @"\01??$funcTmplDef@UExplicitInst_Exported@@@@YAXXZ"()
-// GNU-DAG: define weak_odr dllexport void @_Z11funcTmplDefI21ExplicitInst_ExportedEvv()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$funcTmplDef@UExplicitInst_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dso_local dllexport void @_Z11funcTmplDefI21ExplicitInst_ExportedEvv()
template<typename T> __declspec(dllexport) void funcTmplDef() {}
INST(funcTmplDef<ExplicitInst_Exported>)
// Export inline function template.
-// MSC-DAG: define weak_odr dllexport void @"\01??$inlineFuncTmpl1@UExplicitInst_Exported@@@@YAXXZ"()
-// GNU-DAG: define weak_odr dllexport void @_Z15inlineFuncTmpl1I21ExplicitInst_ExportedEvv()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$inlineFuncTmpl1@UExplicitInst_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dso_local dllexport void @_Z15inlineFuncTmpl1I21ExplicitInst_ExportedEvv()
template<typename T> __declspec(dllexport) inline void inlineFuncTmpl1() {}
INST(inlineFuncTmpl1<ExplicitInst_Exported>)
-// MSC-DAG: define weak_odr dllexport void @"\01??$inlineFuncTmpl2@UExplicitInst_Exported@@@@YAXXZ"()
-// GNU-DAG: define weak_odr dllexport void @_Z15inlineFuncTmpl2I21ExplicitInst_ExportedEvv()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$inlineFuncTmpl2@UExplicitInst_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dso_local dllexport void @_Z15inlineFuncTmpl2I21ExplicitInst_ExportedEvv()
template<typename T> inline void __attribute__((dllexport)) inlineFuncTmpl2() {}
INST(inlineFuncTmpl2<ExplicitInst_Exported>)
-// MSC-DAG: define weak_odr dllexport void @"\01??$inlineFuncTmplDecl@UExplicitInst_Exported@@@@YAXXZ"()
-// GNU-DAG: define weak_odr dllexport void @_Z18inlineFuncTmplDeclI21ExplicitInst_ExportedEvv()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$inlineFuncTmplDecl@UExplicitInst_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dso_local dllexport void @_Z18inlineFuncTmplDeclI21ExplicitInst_ExportedEvv()
template<typename T> __declspec(dllexport) inline void inlineFuncTmplDecl();
template<typename T> void inlineFuncTmplDecl() {}
INST(inlineFuncTmplDecl<ExplicitInst_Exported>)
-// MSC-DAG: define weak_odr dllexport void @"\01??$inlineFuncTmplDef@UExplicitInst_Exported@@@@YAXXZ"()
-// GNU-DAG: define weak_odr dllexport void @_Z17inlineFuncTmplDefI21ExplicitInst_ExportedEvv()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$inlineFuncTmplDef@UExplicitInst_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dso_local dllexport void @_Z17inlineFuncTmplDefI21ExplicitInst_ExportedEvv()
template<typename T> __declspec(dllexport) void inlineFuncTmplDef();
template<typename T> inline void inlineFuncTmplDef() {}
INST(inlineFuncTmplDef<ExplicitInst_Exported>)
// Redeclarations
-// MSC-DAG: define weak_odr dllexport void @"\01??$funcTmplRedecl1@UExplicitInst_Exported@@@@YAXXZ"()
-// GNU-DAG: define weak_odr dllexport void @_Z15funcTmplRedecl1I21ExplicitInst_ExportedEvv()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$funcTmplRedecl1@UExplicitInst_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dso_local dllexport void @_Z15funcTmplRedecl1I21ExplicitInst_ExportedEvv()
template<typename T> __declspec(dllexport) void funcTmplRedecl1();
template<typename T> __declspec(dllexport) void funcTmplRedecl1() {}
INST(funcTmplRedecl1<ExplicitInst_Exported>)
-// MSC-DAG: define weak_odr dllexport void @"\01??$funcTmplRedecl2@UExplicitInst_Exported@@@@YAXXZ"()
-// GNU-DAG: define weak_odr dllexport void @_Z15funcTmplRedecl2I21ExplicitInst_ExportedEvv()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$funcTmplRedecl2@UExplicitInst_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dso_local dllexport void @_Z15funcTmplRedecl2I21ExplicitInst_ExportedEvv()
template<typename T> __declspec(dllexport) void funcTmplRedecl2();
template<typename T> void funcTmplRedecl2() {}
INST(funcTmplRedecl2<ExplicitInst_Exported>)
-// MSC-DAG: define weak_odr dllexport void @"\01??$funcTmplRedecl3@UExplicitInst_Exported@@@@YAXXZ"()
-// GNU-DAG: define weak_odr dllexport void @_Z15funcTmplRedecl3I21ExplicitInst_ExportedEvv()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$funcTmplRedecl3@UExplicitInst_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dso_local dllexport void @_Z15funcTmplRedecl3I21ExplicitInst_ExportedEvv()
template<typename T> __declspec(dllexport) void funcTmplRedecl3();
template<typename T> void funcTmplRedecl3() {}
INST(funcTmplRedecl3<ExplicitInst_Exported>)
// Function template friends
-// MSC-DAG: define weak_odr dllexport void @"\01??$funcTmplFriend1@UExplicitInst_Exported@@@@YAXXZ"()
-// GNU-DAG: define weak_odr dllexport void @_Z15funcTmplFriend1I21ExplicitInst_ExportedEvv()
-// MSC-DAG: define weak_odr dllexport void @"\01??$funcTmplFriend2@UExplicitInst_Exported@@@@YAXXZ"()
-// GNU-DAG: define weak_odr dllexport void @_Z15funcTmplFriend2I21ExplicitInst_ExportedEvv()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$funcTmplFriend1@UExplicitInst_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dso_local dllexport void @_Z15funcTmplFriend1I21ExplicitInst_ExportedEvv()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$funcTmplFriend2@UExplicitInst_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dso_local dllexport void @_Z15funcTmplFriend2I21ExplicitInst_ExportedEvv()
struct FuncTmplFriend {
template<typename T> friend __declspec(dllexport) void funcTmplFriend1();
template<typename T> friend __declspec(dllexport) void funcTmplFriend2();
@@ -340,8 +384,8 @@ template<typename T> void funcTmplFriend2() {}
INST(funcTmplFriend1<ExplicitInst_Exported>)
INST(funcTmplFriend2<ExplicitInst_Exported>)
-// MSC-DAG: define weak_odr dllexport void @"\01??$externalFuncTmpl@UExplicitInst_Exported@@@ns@@YAXXZ"()
-// GNU-DAG: define weak_odr dllexport void @_ZN2ns16externalFuncTmplI21ExplicitInst_ExportedEEvv()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$externalFuncTmpl@UExplicitInst_Exported@@@ns@@YAXXZ"()
+// GNU-DAG: define weak_odr dso_local dllexport void @_ZN2ns16externalFuncTmplI21ExplicitInst_ExportedEEvv()
namespace ns { template<typename T> __declspec(dllexport) void externalFuncTmpl() {} }
INST(ns::externalFuncTmpl<ExplicitInst_Exported>)
@@ -350,55 +394,55 @@ template<typename T> void funcTmpl() {}
template<typename T> __declspec(dllexport) void exportedFuncTmpl() {}
// Export implicit instantiation of an exported function template.
-// MSC-DAG: define weak_odr dllexport void @"\01??$exportedFuncTmpl@UImplicitInst_Exported@@@@YAXXZ"()
-// GNU-DAG: define weak_odr dllexport void @_Z16exportedFuncTmplI21ImplicitInst_ExportedEvv()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$exportedFuncTmpl@UImplicitInst_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dso_local dllexport void @_Z16exportedFuncTmplI21ImplicitInst_ExportedEvv()
USE(exportedFuncTmpl<ImplicitInst_Exported>)
// Export explicit instantiation declaration of an exported function template.
-// MSC-DAG: define weak_odr dllexport void @"\01??$exportedFuncTmpl@UExplicitDecl_Exported@@@@YAXXZ"()
-// GNU-DAG: define weak_odr dllexport void @_Z16exportedFuncTmplI21ExplicitDecl_ExportedEvv()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$exportedFuncTmpl@UExplicitDecl_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dso_local dllexport void @_Z16exportedFuncTmplI21ExplicitDecl_ExportedEvv()
extern template void exportedFuncTmpl<ExplicitDecl_Exported>();
template void exportedFuncTmpl<ExplicitDecl_Exported>();
// Export explicit instantiation definition of an exported function template.
-// MSC-DAG: define weak_odr dllexport void @"\01??$exportedFuncTmpl@UExplicitInst_Exported@@@@YAXXZ"()
-// GNU-DAG: define weak_odr dllexport void @_Z16exportedFuncTmplI21ExplicitInst_ExportedEvv()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$exportedFuncTmpl@UExplicitInst_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dso_local dllexport void @_Z16exportedFuncTmplI21ExplicitInst_ExportedEvv()
template void exportedFuncTmpl<ExplicitInst_Exported>();
// Export specialization of an exported function template.
-// MSC-DAG: define dllexport void @"\01??$exportedFuncTmpl@UExplicitSpec_Def_Exported@@@@YAXXZ"()
-// GNU-DAG: define dllexport void @_Z16exportedFuncTmplI25ExplicitSpec_Def_ExportedEvv()
+// MSC-DAG: define dso_local dllexport void @"??$exportedFuncTmpl@UExplicitSpec_Def_Exported@@@@YAXXZ"()
+// GNU-DAG: define dso_local dllexport void @_Z16exportedFuncTmplI25ExplicitSpec_Def_ExportedEvv()
template<> __declspec(dllexport) void exportedFuncTmpl<ExplicitSpec_Def_Exported>() {}
-// MSC-DAG: define weak_odr dllexport void @"\01??$exportedFuncTmpl@UExplicitSpec_InlineDef_Exported@@@@YAXXZ"()
-// GNU-DAG: define weak_odr dllexport void @_Z16exportedFuncTmplI31ExplicitSpec_InlineDef_ExportedEvv()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$exportedFuncTmpl@UExplicitSpec_InlineDef_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dso_local dllexport void @_Z16exportedFuncTmplI31ExplicitSpec_InlineDef_ExportedEvv()
template<> __declspec(dllexport) inline void exportedFuncTmpl<ExplicitSpec_InlineDef_Exported>() {}
// Not exporting specialization of an exported function template without
// explicit dllexport.
-// MSC-DAG: define void @"\01??$exportedFuncTmpl@UExplicitSpec_NotExported@@@@YAXXZ"()
-// GNU-DAG: define void @_Z16exportedFuncTmplI24ExplicitSpec_NotExportedEvv()
+// MSC-DAG: define dso_local void @"??$exportedFuncTmpl@UExplicitSpec_NotExported@@@@YAXXZ"()
+// GNU-DAG: define dso_local void @_Z16exportedFuncTmplI24ExplicitSpec_NotExportedEvv()
template<> void exportedFuncTmpl<ExplicitSpec_NotExported>() {}
// Export explicit instantiation declaration of a non-exported function template.
-// MSC-DAG: define weak_odr dllexport void @"\01??$funcTmpl@UExplicitDecl_Exported@@@@YAXXZ"()
-// GNU-DAG: define weak_odr dllexport void @_Z8funcTmplI21ExplicitDecl_ExportedEvv()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$funcTmpl@UExplicitDecl_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dso_local dllexport void @_Z8funcTmplI21ExplicitDecl_ExportedEvv()
extern template __declspec(dllexport) void funcTmpl<ExplicitDecl_Exported>();
template __declspec(dllexport) void funcTmpl<ExplicitDecl_Exported>();
// Export explicit instantiation definition of a non-exported function template.
-// MSC-DAG: define weak_odr dllexport void @"\01??$funcTmpl@UExplicitInst_Exported@@@@YAXXZ"()
-// GNU-DAG: define weak_odr dllexport void @_Z8funcTmplI21ExplicitInst_ExportedEvv()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$funcTmpl@UExplicitInst_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dso_local dllexport void @_Z8funcTmplI21ExplicitInst_ExportedEvv()
template __declspec(dllexport) void funcTmpl<ExplicitInst_Exported>();
// Export specialization of a non-exported function template.
-// MSC-DAG: define dllexport void @"\01??$funcTmpl@UExplicitSpec_Def_Exported@@@@YAXXZ"()
-// GNU-DAG: define dllexport void @_Z8funcTmplI25ExplicitSpec_Def_ExportedEvv()
+// MSC-DAG: define dso_local dllexport void @"??$funcTmpl@UExplicitSpec_Def_Exported@@@@YAXXZ"()
+// GNU-DAG: define dso_local dllexport void @_Z8funcTmplI25ExplicitSpec_Def_ExportedEvv()
template<> __declspec(dllexport) void funcTmpl<ExplicitSpec_Def_Exported>() {}
-// MSC-DAG: define weak_odr dllexport void @"\01??$funcTmpl@UExplicitSpec_InlineDef_Exported@@@@YAXXZ"()
-// GNU-DAG: define weak_odr dllexport void @_Z8funcTmplI31ExplicitSpec_InlineDef_ExportedEvv()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$funcTmpl@UExplicitSpec_InlineDef_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dso_local dllexport void @_Z8funcTmplI31ExplicitSpec_InlineDef_ExportedEvv()
template<> __declspec(dllexport) inline void funcTmpl<ExplicitSpec_InlineDef_Exported>() {}
@@ -408,61 +452,61 @@ template<> __declspec(dllexport) inline void funcTmpl<ExplicitSpec_InlineDef_Exp
//===----------------------------------------------------------------------===//
// dllexport takes precedence over the dllimport if both are specified.
-// MSC-DAG: @"\01?PrecedenceGlobal1A@@3HA" = dllexport global i32 0, align 4
-// MSC-DAG: @"\01?PrecedenceGlobal1B@@3HA" = dllexport global i32 0, align 4
-// GNU-DAG: @PrecedenceGlobal1A = dllexport global i32 0, align 4
-// GNU-DAG: @PrecedenceGlobal1B = dllexport global i32 0, align 4
+// MSC-DAG: @"?PrecedenceGlobal1A@@3HA" = dso_local dllexport global i32 0, align 4
+// MSC-DAG: @"?PrecedenceGlobal1B@@3HA" = dso_local dllexport global i32 0, align 4
+// GNU-DAG: @PrecedenceGlobal1A = dso_local dllexport global i32 0, align 4
+// GNU-DAG: @PrecedenceGlobal1B = dso_local dllexport global i32 0, align 4
__attribute__((dllimport, dllexport)) int PrecedenceGlobal1A; // dllimport ignored
__declspec(dllimport) __declspec(dllexport) int PrecedenceGlobal1B; // dllimport ignored
-// MSC-DAG: @"\01?PrecedenceGlobal2A@@3HA" = dllexport global i32 0, align 4
-// MSC-DAG: @"\01?PrecedenceGlobal2B@@3HA" = dllexport global i32 0, align 4
-// GNU-DAG: @PrecedenceGlobal2A = dllexport global i32 0, align 4
-// GNU-DAG: @PrecedenceGlobal2B = dllexport global i32 0, align 4
+// MSC-DAG: @"?PrecedenceGlobal2A@@3HA" = dso_local dllexport global i32 0, align 4
+// MSC-DAG: @"?PrecedenceGlobal2B@@3HA" = dso_local dllexport global i32 0, align 4
+// GNU-DAG: @PrecedenceGlobal2A = dso_local dllexport global i32 0, align 4
+// GNU-DAG: @PrecedenceGlobal2B = dso_local dllexport global i32 0, align 4
__attribute__((dllexport, dllimport)) int PrecedenceGlobal2A; // dllimport ignored
__declspec(dllexport) __declspec(dllimport) int PrecedenceGlobal2B; // dllimport ignored
-// MSC-DAG: @"\01?PrecedenceGlobalRedecl1@@3HA" = dllexport global i32 0, align 4
-// GNU-DAG: @PrecedenceGlobalRedecl1 = dllexport global i32 0, align 4
+// MSC-DAG: @"?PrecedenceGlobalRedecl1@@3HA" = dso_local dllexport global i32 0, align 4
+// GNU-DAG: @PrecedenceGlobalRedecl1 = dso_local dllexport global i32 0, align 4
__declspec(dllexport) extern int PrecedenceGlobalRedecl1;
__declspec(dllimport) int PrecedenceGlobalRedecl1 = 0;
-// MSC-DAG: @"\01?PrecedenceGlobalRedecl2@@3HA" = dllexport global i32 0, align 4
-// GNU-DAG: @PrecedenceGlobalRedecl2 = dllexport global i32 0, align 4
+// MSC-DAG: @"?PrecedenceGlobalRedecl2@@3HA" = dso_local dllexport global i32 0, align 4
+// GNU-DAG: @PrecedenceGlobalRedecl2 = dso_local dllexport global i32 0, align 4
__declspec(dllimport) extern int PrecedenceGlobalRedecl2;
__declspec(dllexport) int PrecedenceGlobalRedecl2;
-// MSC-DAG: @"\01?PrecedenceGlobalMixed1@@3HA" = dllexport global i32 0, align 4
-// GNU-DAG: @PrecedenceGlobalMixed1 = dllexport global i32 0, align 4
+// MSC-DAG: @"?PrecedenceGlobalMixed1@@3HA" = dso_local dllexport global i32 0, align 4
+// GNU-DAG: @PrecedenceGlobalMixed1 = dso_local dllexport global i32 0, align 4
__attribute__((dllexport)) extern int PrecedenceGlobalMixed1;
__declspec(dllimport) int PrecedenceGlobalMixed1 = 0;
-// MSC-DAG: @"\01?PrecedenceGlobalMixed2@@3HA" = dllexport global i32 0, align 4
-// GNU-DAG: @PrecedenceGlobalMixed2 = dllexport global i32 0, align 4
+// MSC-DAG: @"?PrecedenceGlobalMixed2@@3HA" = dso_local dllexport global i32 0, align 4
+// GNU-DAG: @PrecedenceGlobalMixed2 = dso_local dllexport global i32 0, align 4
__attribute__((dllimport)) extern int PrecedenceGlobalMixed2;
__declspec(dllexport) int PrecedenceGlobalMixed2;
-// MSC-DAG: define dllexport void @"\01?precedence1A@@YAXXZ"
-// MSC-DAG: define dllexport void @"\01?precedence1B@@YAXXZ"
-// GNU-DAG: define dllexport void @_Z12precedence1Av()
-// GNU-DAG: define dllexport void @_Z12precedence1Bv()
+// MSC-DAG: define dso_local dllexport void @"?precedence1A@@YAXXZ"
+// MSC-DAG: define dso_local dllexport void @"?precedence1B@@YAXXZ"
+// GNU-DAG: define dso_local dllexport void @_Z12precedence1Av()
+// GNU-DAG: define dso_local dllexport void @_Z12precedence1Bv()
void __attribute__((dllimport, dllexport)) precedence1A() {}
void __declspec(dllimport) __declspec(dllexport) precedence1B() {}
-// MSC-DAG: define dllexport void @"\01?precedence2A@@YAXXZ"
-// MSC-DAG: define dllexport void @"\01?precedence2B@@YAXXZ"
-// GNU-DAG: define dllexport void @_Z12precedence2Av()
-// GNU-DAG: define dllexport void @_Z12precedence2Bv()
+// MSC-DAG: define dso_local dllexport void @"?precedence2A@@YAXXZ"
+// MSC-DAG: define dso_local dllexport void @"?precedence2B@@YAXXZ"
+// GNU-DAG: define dso_local dllexport void @_Z12precedence2Av()
+// GNU-DAG: define dso_local dllexport void @_Z12precedence2Bv()
void __attribute__((dllexport, dllimport)) precedence2A() {}
void __declspec(dllexport) __declspec(dllimport) precedence2B() {}
-// MSC-DAG: define dllexport void @"\01?precedenceRedecl1@@YAXXZ"
-// GNU-DAG: define dllexport void @_Z17precedenceRedecl1v()
+// MSC-DAG: define dso_local dllexport void @"?precedenceRedecl1@@YAXXZ"
+// GNU-DAG: define dso_local dllexport void @_Z17precedenceRedecl1v()
void __declspec(dllimport) precedenceRedecl1();
void __declspec(dllexport) precedenceRedecl1() {}
-// MSC-DAG: define dllexport void @"\01?precedenceRedecl2@@YAXXZ"
-// GNU-DAG: define dllexport void @_Z17precedenceRedecl2v()
+// MSC-DAG: define dso_local dllexport void @"?precedenceRedecl2@@YAXXZ"
+// GNU-DAG: define dso_local dllexport void @_Z17precedenceRedecl2v()
void __declspec(dllexport) precedenceRedecl2();
void __declspec(dllimport) precedenceRedecl2() {}
@@ -474,11 +518,11 @@ void __declspec(dllimport) precedenceRedecl2() {}
struct S {
void __declspec(dllexport) a() {}
- // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?a@S@@QAEXXZ"
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?a@S@@QAEXXZ"
struct T {
void __declspec(dllexport) a() {}
- // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?a@T@S@@QAEXXZ"
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?a@T@S@@QAEXXZ"
};
};
@@ -487,11 +531,11 @@ struct SomeTemplate {
SomeTemplate(T o = T()) : o(o) {}
T o;
};
-// MSVC2015-DAG: define weak_odr dllexport {{.+}} @"\01??4?$SomeTemplate@H@@Q{{.+}}@$$Q{{.+}}@@Z"
-// MSVC2013-DAG: define weak_odr dllexport {{.+}} @"\01??4?$SomeTemplate@H@@Q{{.+}}0@A{{.+}}0@@Z"
+// MSVC2015-DAG: define weak_odr dso_local dllexport {{.+}} @"??4?$SomeTemplate@H@@Q{{.+}}@$$Q{{.+}}@@Z"
+// MSVC2013-DAG: define weak_odr dso_local dllexport {{.+}} @"??4?$SomeTemplate@H@@Q{{.+}}0@A{{.+}}0@@Z"
struct __declspec(dllexport) InheritFromTemplate : SomeTemplate<int> {};
-// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??_F?$SomeTemplate@H@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"??_F?$SomeTemplate@H@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
namespace PR23801 {
template <typename>
@@ -508,32 +552,32 @@ struct __declspec(dllexport) B {
}
//
-// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??_FB@PR23801@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"??_FB@PR23801@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
struct __declspec(dllexport) T {
// Copy assignment operator:
- // M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.T* @"\01??4T@@QAEAAU0@ABU0@@Z"
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.T* @"??4T@@QAEAAU0@ABU0@@Z"
// Explicitly defaulted copy constructur:
T(const T&) = default;
- // M32MSVC2013-DAG: define weak_odr dllexport x86_thiscallcc %struct.T* @"\01??0T@@QAE@ABU0@@Z"
+ // M32MSVC2013-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.T* @"??0T@@QAE@ABU0@@Z"
void a() {}
- // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?a@T@@QAEXXZ"
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?a@T@@QAEXXZ"
static int b;
- // M32-DAG: @"\01?b@T@@2HA" = external global i32
+ // M32-DAG: @"?b@T@@2HA" = external dso_local global i32
static int c;
- // M32-DAG: @"\01?c@T@@2HA" = dllexport global i32 0, align 4
+ // M32-DAG: @"?c@T@@2HA" = dso_local dllexport global i32 0, align 4
};
USEVAR(T::b)
int T::c;
// Export template class with static member variable
-// MSC-DAG: @"\01?StaticClassVarExpTmplClass@?$TmplClass@H@@2HA" = weak_odr dllexport global i32 0, comdat, align 4
-// GNU-DAG: @_ZN9TmplClassIiE26StaticClassVarExpTmplClassE = weak_odr dllexport global i32 0, comdat, align 4
+// MSC-DAG: @"?StaticClassVarExpTmplClass@?$TmplClass@H@@2HA" = weak_odr dso_local dllexport global i32 0, comdat, align 4
+// GNU-DAG: @_ZN9TmplClassIiE26StaticClassVarExpTmplClassE = weak_odr dso_local dllexport global i32 0, comdat, align 4
template<typename T>
struct __declspec(dllexport) TmplClass
{
@@ -544,8 +588,8 @@ template<typename T>
T TmplClass<T>::StaticClassVarExpTmplClass;
// Export a definition of a template function.
-// MSC-DAG: define weak_odr dllexport i32 @"\01??$TypeFunTmpl@H@@YAHH@Z"
-// GNU-DAG: define weak_odr dllexport i32 @_Z11TypeFunTmplIiET_S0_
+// MSC-DAG: define weak_odr dso_local dllexport i32 @"??$TypeFunTmpl@H@@YAHH@Z"
+// GNU-DAG: define weak_odr dso_local dllexport i32 @_Z11TypeFunTmplIiET_S0_
template<typename T>
T __declspec(dllexport) TypeFunTmpl(T t) { return t + t; }
@@ -558,38 +602,38 @@ int useExportedTmplStaticAndFun()
template <typename T> struct __declspec(dllexport) U { void foo() {} };
struct __declspec(dllexport) V : public U<int> { };
// U<int>'s assignment operator is emitted.
-// M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.U* @"\01??4?$U@H@@QAEAAU0@ABU0@@Z"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.U* @"??4?$U@H@@QAEAAU0@ABU0@@Z"
struct __declspec(dllexport) W { virtual void foo(); };
void W::foo() {}
// Default ctor:
-// M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.W* @"\01??0W@@QAE@XZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.W* @"??0W@@QAE@XZ"
// Copy ctor:
-// M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.W* @"\01??0W@@QAE@ABU0@@Z"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.W* @"??0W@@QAE@ABU0@@Z"
// vftable:
-// M32-DAG: [[W_VTABLE:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4W@@6B@" to i8*), i8* bitcast (void (%struct.W*)* @"\01?foo@W@@UAEXXZ" to i8*)] }, comdat($"\01??_7W@@6B@")
-// M32-DAG: @"\01??_7W@@6B@" = dllexport unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[W_VTABLE]], i32 0, i32 0, i32 1)
-// G32-DAG: @_ZTV1W = dllexport unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI1W to i8*), i8* bitcast (void (%struct.W*)* @_ZN1W3fooEv to i8*)] }
+// M32-DAG: [[W_VTABLE:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"??_R4W@@6B@" to i8*), i8* bitcast (void (%struct.W*)* @"?foo@W@@UAEXXZ" to i8*)] }, comdat($"??_7W@@6B@")
+// M32-DAG: @"??_7W@@6B@" = dllexport unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[W_VTABLE]], i32 0, i32 0, i32 1)
+// G32-DAG: @_ZTV1W = dso_local dllexport unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI1W to i8*), i8* bitcast (void (%struct.W*)* @_ZN1W3fooEv to i8*)] }
struct __declspec(dllexport) X : public virtual W {};
// vbtable:
-// M32-DAG: @"\01??_8X@@7B@" = weak_odr dllexport unnamed_addr constant [2 x i32] [i32 0, i32 4]
+// M32-DAG: @"??_8X@@7B@" = weak_odr dllexport unnamed_addr constant [2 x i32] [i32 0, i32 4]
struct __declspec(dllexport) Y {
// Move assignment operator:
- // MSVC2015-DAG: define weak_odr dllexport {{.+}} @"\01??4Y@@Q{{.+}}@$$Q{{.+}}@@Z"
- // MSVC2013-DAG: define weak_odr dllexport {{.+}} @"\01??4Y@@Q{{.+}}0@A{{.+}}0@@Z"
+ // MSVC2015-DAG: define weak_odr dso_local dllexport {{.+}} @"??4Y@@Q{{.+}}@$$Q{{.+}}@@Z"
+ // MSVC2013-DAG: define weak_odr dso_local dllexport {{.+}} @"??4Y@@Q{{.+}}0@A{{.+}}0@@Z"
int x;
};
struct __declspec(dllexport) Z { virtual ~Z() {} };
// The scalar deleting dtor does not get exported:
-// M32-DAG: define linkonce_odr x86_thiscallcc i8* @"\01??_GZ@@UAEPAXI@Z"
+// M32-DAG: define linkonce_odr dso_local x86_thiscallcc i8* @"??_GZ@@UAEPAXI@Z"
// The user-defined dtor does get exported:
-// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??1Z@@UAE@XZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"??1Z@@UAE@XZ"
namespace UseDtorAlias {
struct __declspec(dllexport) A { ~A(); };
@@ -597,39 +641,39 @@ namespace UseDtorAlias {
A::~A() { }
B::~B() { }
// Emit a alias definition of B's constructor.
- // M32-DAG: @"\01??1B@UseDtorAlias@@QAE@XZ" = dllexport alias {{.*}} @"\01??1A@UseDtorAlias@@QAE@XZ"
+ // M32-DAG: @"??1B@UseDtorAlias@@QAE@XZ" = dso_local dllexport unnamed_addr alias {{.*}} @"??1A@UseDtorAlias@@QAE@XZ"
}
struct __declspec(dllexport) DefaultedCtorsDtors {
DefaultedCtorsDtors() = default;
- // M32MSVC2013-DAG: define weak_odr dllexport x86_thiscallcc %struct.DefaultedCtorsDtors* @"\01??0DefaultedCtorsDtors@@QAE@XZ"
+ // M32MSVC2013-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.DefaultedCtorsDtors* @"??0DefaultedCtorsDtors@@QAE@XZ"
~DefaultedCtorsDtors() = default;
- // M32MSVC2013-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??1DefaultedCtorsDtors@@QAE@XZ"
+ // M32MSVC2013-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"??1DefaultedCtorsDtors@@QAE@XZ"
};
// Export defaulted member function definitions declared inside class.
struct __declspec(dllexport) ExportDefaultedInclassDefs {
ExportDefaultedInclassDefs() = default;
- // M32VS2013-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
- // M64VS2013-DAG: define weak_odr dllexport %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
- // M32VS2015-NOT: define weak_odr dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
- // M64VS2015-NOT: define weak_odr dllexport %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
+ // M32VS2013-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"??0ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
+ // M64VS2013-DAG: define weak_odr dso_local dllexport %struct.ExportDefaultedInclassDefs* @"??0ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
+ // M32VS2015-NOT: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"??0ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
+ // M64VS2015-NOT: define weak_odr dso_local dllexport %struct.ExportDefaultedInclassDefs* @"??0ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
~ExportDefaultedInclassDefs() = default;
- // M32VS2013-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??1ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* %this)
- // M64VS2013-DAG: define weak_odr dllexport void @"\01??1ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* %this)
- // M32VS2015-NOT: define weak_odr dllexport x86_thiscallcc void @"\01??1ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* %this)
- // M64VS2015-NOT: define weak_odr dllexport void @"\01??1ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* %this)
+ // M32VS2013-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"??1ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* %this)
+ // M64VS2013-DAG: define weak_odr dso_local dllexport void @"??1ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* %this)
+ // M32VS2015-NOT: define weak_odr dso_local dllexport x86_thiscallcc void @"??1ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* %this)
+ // M64VS2015-NOT: define weak_odr dso_local dllexport void @"??1ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* %this)
ExportDefaultedInclassDefs(const ExportDefaultedInclassDefs&) = default;
- // M32VS2013-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QAE@ABU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
- // M64VS2013-DAG: define weak_odr dllexport %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QEAA@AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
- // M32VS2015-NOT: define weak_odr dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QAE@ABU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
- // M64VS2015-NOT: define weak_odr dllexport %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QEAA@AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+ // M32VS2013-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"??0ExportDefaultedInclassDefs@@QAE@ABU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+ // M64VS2013-DAG: define weak_odr dso_local dllexport %struct.ExportDefaultedInclassDefs* @"??0ExportDefaultedInclassDefs@@QEAA@AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+ // M32VS2015-NOT: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"??0ExportDefaultedInclassDefs@@QAE@ABU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+ // M64VS2015-NOT: define weak_odr dso_local dllexport %struct.ExportDefaultedInclassDefs* @"??0ExportDefaultedInclassDefs@@QEAA@AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
ExportDefaultedInclassDefs& operator=(const ExportDefaultedInclassDefs&) = default;
- // M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedInclassDefs* @"\01??4ExportDefaultedInclassDefs@@QAEAAU0@ABU0@@Z"(%struct.ExportDefaultedInclassDefs* %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
- // M64-DAG: define weak_odr dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedInclassDefs* @"\01??4ExportDefaultedInclassDefs@@QEAAAEAU0@AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedInclassDefs* @"??4ExportDefaultedInclassDefs@@QAEAAU0@ABU0@@Z"(%struct.ExportDefaultedInclassDefs* %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+ // M64-DAG: define weak_odr dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedInclassDefs* @"??4ExportDefaultedInclassDefs@@QEAAAEAU0@AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
};
namespace ReferencedInlineMethodInNestedClass {
@@ -642,8 +686,8 @@ namespace ReferencedInlineMethodInNestedClass {
};
T *t;
};
- // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?foo@S@ReferencedInlineMethodInNestedClass@@QAEXXZ"
- // M32-DAG: define linkonce_odr x86_thiscallcc void @"\01?bar@T@S@ReferencedInlineMethodInNestedClass@@QAEXXZ"
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?foo@S@ReferencedInlineMethodInNestedClass@@QAEXXZ"
+ // M32-DAG: define linkonce_odr dso_local x86_thiscallcc void @"?bar@T@S@ReferencedInlineMethodInNestedClass@@QAEXXZ"
}
// MS ignores DLL attributes on partial specializations.
@@ -651,37 +695,37 @@ template <typename T> struct PartiallySpecializedClassTemplate {};
template <typename T> struct __declspec(dllexport) PartiallySpecializedClassTemplate<T*> { void f(); };
template <typename T> void PartiallySpecializedClassTemplate<T*>::f() {}
USEMEMFUNC(PartiallySpecializedClassTemplate<void*>, f);
-// M32-DAG: define linkonce_odr x86_thiscallcc void @"\01?f@?$PartiallySpecializedClassTemplate@PAX@@QAEXXZ"
-// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN33PartiallySpecializedClassTemplateIPvE1fEv
+// M32-DAG: define linkonce_odr dso_local x86_thiscallcc void @"?f@?$PartiallySpecializedClassTemplate@PAX@@QAEXXZ"
+// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN33PartiallySpecializedClassTemplateIPvE1fEv
// Attributes on explicit specializations are honored.
template <typename T> struct ExplicitlySpecializedClassTemplate {};
template <> struct __declspec(dllexport) ExplicitlySpecializedClassTemplate<void*> { void f(); };
void ExplicitlySpecializedClassTemplate<void*>::f() {}
USEMEMFUNC(ExplicitlySpecializedClassTemplate<void*>, f);
-// M32-DAG: define dllexport x86_thiscallcc void @"\01?f@?$ExplicitlySpecializedClassTemplate@PAX@@QAEXXZ"
-// G32-DAG: define dllexport x86_thiscallcc void @_ZN34ExplicitlySpecializedClassTemplateIPvE1fEv
+// M32-DAG: define dso_local dllexport x86_thiscallcc void @"?f@?$ExplicitlySpecializedClassTemplate@PAX@@QAEXXZ"
+// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN34ExplicitlySpecializedClassTemplateIPvE1fEv
// MS inherits DLL attributes to partial specializations.
template <typename T> struct __declspec(dllexport) PartiallySpecializedExportedClassTemplate {};
template <typename T> struct PartiallySpecializedExportedClassTemplate<T*> { void f() {} };
USEMEMFUNC(PartiallySpecializedExportedClassTemplate<void*>, f);
-// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$PartiallySpecializedExportedClassTemplate@PAX@@QAEXXZ"
-// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN41PartiallySpecializedExportedClassTemplateIPvE1fEv
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?f@?$PartiallySpecializedExportedClassTemplate@PAX@@QAEXXZ"
+// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN41PartiallySpecializedExportedClassTemplateIPvE1fEv
// MS ignores DLL attributes on partial specializations; inheritance still works though.
template <typename T> struct __declspec(dllexport) PartiallySpecializedExportedClassTemplate2 {};
template <typename T> struct __declspec(dllimport) PartiallySpecializedExportedClassTemplate2<T*> { void f(); };
template <typename T> void PartiallySpecializedExportedClassTemplate2<T*>::f() {}
USEMEMFUNC(PartiallySpecializedExportedClassTemplate2<void*>, f);
-// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$PartiallySpecializedExportedClassTemplate2@PAX@@QAEXXZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?f@?$PartiallySpecializedExportedClassTemplate2@PAX@@QAEXXZ"
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN42PartiallySpecializedExportedClassTemplate2IPvE1fEv
// Attributes on the instantiation take precedence over attributes on the template.
template <typename T> struct __declspec(dllimport) ExplicitlyInstantiatedWithDifferentAttr { void f() {} };
template struct __declspec(dllexport) ExplicitlyInstantiatedWithDifferentAttr<int>;
USEMEMFUNC(ExplicitlyInstantiatedWithDifferentAttr<int>, f);
-// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$ExplicitlyInstantiatedWithDifferentAttr@H@@QAEXXZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?f@?$ExplicitlyInstantiatedWithDifferentAttr@H@@QAEXXZ"
// Don't create weak dllexport aliases. (PR21373)
struct NonExportedBaseClass {
@@ -690,62 +734,62 @@ struct NonExportedBaseClass {
NonExportedBaseClass::~NonExportedBaseClass() {}
struct __declspec(dllexport) ExportedDerivedClass : NonExportedBaseClass {};
-// M32-DAG: weak_odr dllexport x86_thiscallcc void @"\01??1ExportedDerivedClass@@UAE@XZ"
+// M32-DAG: weak_odr dso_local dllexport x86_thiscallcc void @"??1ExportedDerivedClass@@UAE@XZ"
// Do not assert about generating code for constexpr functions twice during explicit instantiation (PR21718).
template <typename T> struct ExplicitInstConstexprMembers {
// Copy assignment operator
- // M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable(1) %struct.ExplicitInstConstexprMembers* @"\01??4?$ExplicitInstConstexprMembers@X@@QAEAAU0@ABU0@@Z"
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable(1) %struct.ExplicitInstConstexprMembers* @"??4?$ExplicitInstConstexprMembers@X@@QAEAAU0@ABU0@@Z"
constexpr ExplicitInstConstexprMembers() {}
- // M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExplicitInstConstexprMembers* @"\01??0?$ExplicitInstConstexprMembers@X@@QAE@XZ"
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExplicitInstConstexprMembers* @"??0?$ExplicitInstConstexprMembers@X@@QAE@XZ"
ExplicitInstConstexprMembers(const ExplicitInstConstexprMembers&) = default;
- // M32MSVC2013-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExplicitInstConstexprMembers* @"\01??0?$ExplicitInstConstexprMembers@X@@QAE@ABU0@@Z"
+ // M32MSVC2013-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExplicitInstConstexprMembers* @"??0?$ExplicitInstConstexprMembers@X@@QAE@ABU0@@Z"
constexpr int f() const { return 42; }
- // M32-DAG: define weak_odr dllexport x86_thiscallcc i32 @"\01?f@?$ExplicitInstConstexprMembers@X@@QBEHXZ"
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc i32 @"?f@?$ExplicitInstConstexprMembers@X@@QBEHXZ"
};
template struct __declspec(dllexport) ExplicitInstConstexprMembers<void>;
template <typename T> struct ExplicitInstantiationDeclTemplate { void f() {} };
extern template struct __declspec(dllexport) ExplicitInstantiationDeclTemplate<int>;
USEMEMFUNC(ExplicitInstantiationDeclTemplate<int>, f);
-// M32-DAG: {{declare|define available_externally}} x86_thiscallcc void @"\01?f@?$ExplicitInstantiationDeclTemplate@H@@QAEXXZ"
+// M32-DAG: {{declare|define available_externally}} dso_local x86_thiscallcc void @"?f@?$ExplicitInstantiationDeclTemplate@H@@QAEXXZ"
template <typename T> struct __declspec(dllexport) ExplicitInstantiationDeclExportedTemplate { void f() {} };
extern template struct ExplicitInstantiationDeclExportedTemplate<int>;
USEMEMFUNC(ExplicitInstantiationDeclExportedTemplate<int>, f);
-// M32-DAG: {{declare|define available_externally}} x86_thiscallcc void @"\01?f@?$ExplicitInstantiationDeclExportedTemplate@H@@QAEXXZ"
+// M32-DAG: {{declare|define available_externally}} dso_local x86_thiscallcc void @"?f@?$ExplicitInstantiationDeclExportedTemplate@H@@QAEXXZ"
template <typename T> struct ExplicitInstantiationDeclExportedDefTemplate { void f() {} ExplicitInstantiationDeclExportedDefTemplate() {} };
extern template struct ExplicitInstantiationDeclExportedDefTemplate<int>;
template struct __declspec(dllexport) ExplicitInstantiationDeclExportedDefTemplate<int>;
USEMEMFUNC(ExplicitInstantiationDeclExportedDefTemplate<int>, f);
-// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$ExplicitInstantiationDeclExportedDefTemplate@H@@QAEXXZ"
-// M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExplicitInstantiationDeclExportedDefTemplate* @"\01??0?$ExplicitInstantiationDeclExportedDefTemplate@H@@QAE@XZ"
-// G32-DAG: define weak_odr x86_thiscallcc void @_ZN44ExplicitInstantiationDeclExportedDefTemplateIiE1fEv
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?f@?$ExplicitInstantiationDeclExportedDefTemplate@H@@QAEXXZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExplicitInstantiationDeclExportedDefTemplate* @"??0?$ExplicitInstantiationDeclExportedDefTemplate@H@@QAE@XZ"
+// G32-DAG: define weak_odr dso_local x86_thiscallcc void @_ZN44ExplicitInstantiationDeclExportedDefTemplateIiE1fEv
template <typename T> struct ImplicitInstantiationExportedExplicitInstantiationDefTemplate { virtual void f() {} };
ImplicitInstantiationExportedExplicitInstantiationDefTemplate<int> ImplicitInstantiationExportedExplicitInstantiationDefTemplateInstance;
template struct __declspec(dllexport) ImplicitInstantiationExportedExplicitInstantiationDefTemplate<int>;
USEMEMFUNC(ImplicitInstantiationExportedExplicitInstantiationDefTemplate<int>, f);
-// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$ImplicitInstantiationExportedExplicitInstantiationDefTemplate@H@@UAEXXZ"
-// G32-DAG: define weak_odr x86_thiscallcc void @_ZN61ImplicitInstantiationExportedExplicitInstantiationDefTemplateIiE1fEv
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?f@?$ImplicitInstantiationExportedExplicitInstantiationDefTemplate@H@@UAEXXZ"
+// G32-DAG: define weak_odr dso_local x86_thiscallcc void @_ZN61ImplicitInstantiationExportedExplicitInstantiationDefTemplateIiE1fEv
template <typename T> struct __declspec(dllexport) ImplicitInstantiationExplicitInstantiationDefExportedTemplate { virtual void f() {} };
ImplicitInstantiationExplicitInstantiationDefExportedTemplate<int> ImplicitInstantiationExplicitInstantiationDefExportedTemplateInstance;
template struct ImplicitInstantiationExplicitInstantiationDefExportedTemplate<int>;
USEMEMFUNC(ImplicitInstantiationExplicitInstantiationDefExportedTemplate<int>, f);
-// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$ImplicitInstantiationExplicitInstantiationDefExportedTemplate@H@@UAEXXZ"
-// G32-DAG: define weak_odr x86_thiscallcc void @_ZN61ImplicitInstantiationExplicitInstantiationDefExportedTemplateIiE1fEv
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?f@?$ImplicitInstantiationExplicitInstantiationDefExportedTemplate@H@@UAEXXZ"
+// G32-DAG: define weak_odr dso_local x86_thiscallcc void @_ZN61ImplicitInstantiationExplicitInstantiationDefExportedTemplateIiE1fEv
template <typename T> struct __declspec(dllexport) ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplate { virtual void f() {} };
ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplate<int> ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplateInstance;
template struct __declspec(dllexport) ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplate<int>;
USEMEMFUNC(ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplate<int>, f);
-// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplate@H@@UAEXXZ"
-// G32-DAG: define weak_odr x86_thiscallcc void @_ZN69ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplateIiE1fEv
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?f@?$ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplate@H@@UAEXXZ"
+// G32-DAG: define weak_odr dso_local x86_thiscallcc void @_ZN69ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplateIiE1fEv
namespace { struct InternalLinkageType {}; }
struct __declspec(dllexport) PR23308 {
@@ -753,20 +797,20 @@ struct __declspec(dllexport) PR23308 {
};
void PR23308::f(InternalLinkageType*) {}
long use(PR23308* p) { p->f(nullptr); }
-// M32-DAG: define internal x86_thiscallcc void @"\01?f@PR23308@@QAEXPAUInternalLinkageType@?A@@@Z"
+// M32-DAG: define internal x86_thiscallcc void @"?f@PR23308@@QAEXPAUInternalLinkageType@?A@@@Z"
template <typename T> struct PR23770BaseTemplate { void f() {} };
template <typename T> struct PR23770DerivedTemplate : PR23770BaseTemplate<int> {};
extern template struct PR23770DerivedTemplate<int>;
template struct __declspec(dllexport) PR23770DerivedTemplate<int>;
-// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$PR23770BaseTemplate@H@@QAEXXZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?f@?$PR23770BaseTemplate@H@@QAEXXZ"
namespace InClassInits {
struct __declspec(dllexport) S {
int x = 42;
};
-// M32-DAG: define weak_odr dllexport x86_thiscallcc %"struct.InClassInits::S"* @"\01??0S@InClassInits@@QAE@XZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %"struct.InClassInits::S"* @"??0S@InClassInits@@QAE@XZ"
// dllexport an already instantiated class template.
template <typename T> struct Base {
@@ -774,7 +818,7 @@ template <typename T> struct Base {
};
Base<int> base;
struct __declspec(dllexport) T : Base<int> { };
-// M32-DAG: define weak_odr dllexport x86_thiscallcc %"struct.InClassInits::Base"* @"\01??0?$Base@H@InClassInits@@QAE@XZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %"struct.InClassInits::Base"* @"??0?$Base@H@InClassInits@@QAE@XZ"
struct A { A(int); };
struct __declspec(dllexport) U {
@@ -782,7 +826,7 @@ struct __declspec(dllexport) U {
U(A = 0) {}
int x = 0;
};
-// M32-DAG: define weak_odr dllexport x86_thiscallcc %"struct.InClassInits::U"* @"\01??0U@InClassInits@@QAE@UA@1@@Z"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %"struct.InClassInits::U"* @"??0U@InClassInits@@QAE@UA@1@@Z"
struct Evil {
template <typename T> struct Base {
@@ -794,7 +838,7 @@ struct Evil {
// the default ctor must still be delayed.
struct __declspec(dllexport) T : Base<int> {};
};
-// M32-DAG: define weak_odr dllexport x86_thiscallcc %"struct.InClassInits::Evil::Base"* @"\01??0?$Base@H@Evil@InClassInits@@QAE@XZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %"struct.InClassInits::Evil::Base"* @"??0?$Base@H@Evil@InClassInits@@QAE@XZ"
template <typename T> struct Foo {};
template <typename T> struct Bar {
@@ -806,7 +850,7 @@ struct __declspec(dllexport) Baz {
// After parsing Baz, in ActOnFinishCXXNonNestedClass we would synthesize
// Baz's operator=, causing instantiation of Foo<int> after which
// ActOnFinishCXXNonNestedClass is called, and we would bite our own tail.
-// M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable(1) %"struct.InClassInits::Baz"* @"\01??4Baz@InClassInits@@QAEAAU01@ABU01@@Z"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable(1) %"struct.InClassInits::Baz"* @"??4Baz@InClassInits@@QAEAAU01@ABU01@@Z"
}
// We had an issue where instantiating A would force emission of B's delayed
@@ -817,28 +861,28 @@ struct __declspec(dllexport) B {
B(int = 0) {}
A<int> m_fn1() {}
};
-// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??_FB@pr26490@@QAEXXZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"??_FB@pr26490@@QAEXXZ"
}
// dllexport trumps dllimport on an explicit instantiation.
template <typename T> struct ExplicitInstantiationTwoAttributes { void f() {} };
template struct __declspec(dllexport) __declspec(dllimport) ExplicitInstantiationTwoAttributes<int>;
-// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$ExplicitInstantiationTwoAttributes@H@@QAEXXZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?f@?$ExplicitInstantiationTwoAttributes@H@@QAEXXZ"
namespace pr34849 {
// Specializations of exported class template member functions get exported.
template <typename> struct __declspec(dllexport) ExportedClassTemplate { void foo(); };
template<> void ExportedClassTemplate<int>::foo() {}
template struct ExportedClassTemplate<int>;
-// M32-DAG: define dllexport x86_thiscallcc void @"\01?foo@?$ExportedClassTemplate@H@pr34849@@QAEXXZ"
+// M32-DAG: define dso_local dllexport x86_thiscallcc void @"?foo@?$ExportedClassTemplate@H@pr34849@@QAEXXZ"
// Specializations of exported class member template functions do not get exported.
struct __declspec(dllexport) ExportedClass { template <typename> void bar() ; };
template<> void ExportedClass::bar<int>() {}
-// M32-DAG: define x86_thiscallcc void @"\01??$bar@H@ExportedClass@pr34849@@QAEXXZ"
+// M32-DAG: define dso_local x86_thiscallcc void @"??$bar@H@ExportedClass@pr34849@@QAEXXZ"
template <typename> struct __declspec(dllexport) ExportedClassTemplate2 { template <typename> void baz(); };
template<> template<> void ExportedClassTemplate2<int>::baz<int>() {}
-// M32-DAG: define x86_thiscallcc void @"\01??$baz@H@?$ExportedClassTemplate2@H@pr34849@@QAEXXZ"
+// M32-DAG: define dso_local x86_thiscallcc void @"??$baz@H@?$ExportedClassTemplate2@H@pr34849@@QAEXXZ"
}
//===----------------------------------------------------------------------===//
@@ -874,69 +918,69 @@ template struct __declspec(dllimport) ExplicitlyImportInstantiatedTemplate<int>;
// MS: ClassTemplate<int> gets exported.
struct __declspec(dllexport) DerivedFromTemplate : public ClassTemplate<int> {};
USEMEMFUNC(DerivedFromTemplate, func)
-// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ClassTemplate@H@@QAEXXZ"
-// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ClassTemplateIiE4funcEv
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?func@?$ClassTemplate@H@@QAEXXZ"
+// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ClassTemplateIiE4funcEv
// ExportedTemplate is explicitly exported.
struct __declspec(dllexport) DerivedFromExportedTemplate : public ExportedClassTemplate<int> {};
USEMEMFUNC(DerivedFromExportedTemplate, func)
-// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ExportedClassTemplate@H@@QAEXXZ"
-// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN21ExportedClassTemplateIiE4funcEv
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?func@?$ExportedClassTemplate@H@@QAEXXZ"
+// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN21ExportedClassTemplateIiE4funcEv
// ImportedClassTemplate is explicitly imported.
struct __declspec(dllexport) DerivedFromImportedTemplate : public ImportedClassTemplate<int> {};
USEMEMFUNC(DerivedFromImportedTemplate, func)
-// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ImportedClassTemplate@H@@QAEXXZ"
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"?func@?$ImportedClassTemplate@H@@QAEXXZ"
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN21ImportedClassTemplateIiE4funcEv
// Base class already implicitly instantiated without dll attribute.
struct DerivedFromTemplateD : public ClassTemplate<double> {};
struct __declspec(dllexport) DerivedFromTemplateD2 : public ClassTemplate<double> {};
USEMEMFUNC(DerivedFromTemplateD2, func)
-// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ClassTemplate@N@@QAEXXZ"
-// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ClassTemplateIdE4funcEv
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?func@?$ClassTemplate@N@@QAEXXZ"
+// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ClassTemplateIdE4funcEv
// MS: Base class already instantiated with different dll attribute.
struct __declspec(dllimport) DerivedFromTemplateB : public ClassTemplate<bool> {};
struct __declspec(dllexport) DerivedFromTemplateB2 : public ClassTemplate<bool> {};
USEMEMFUNC(DerivedFromTemplateB2, func)
-// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ClassTemplate@_N@@QAEXXZ"
-// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ClassTemplateIbE4funcEv
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"?func@?$ClassTemplate@_N@@QAEXXZ"
+// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ClassTemplateIbE4funcEv
// Base class already specialized without dll attribute.
struct __declspec(dllexport) DerivedFromExplicitlySpecializedTemplate : public ExplicitlySpecializedTemplate<int> {};
USEMEMFUNC(DerivedFromExplicitlySpecializedTemplate, func)
-// M32-DAG: define x86_thiscallcc void @"\01?func@?$ExplicitlySpecializedTemplate@H@@QAEXXZ"
-// G32-DAG: define x86_thiscallcc void @_ZN29ExplicitlySpecializedTemplateIiE4funcEv
+// M32-DAG: define dso_local x86_thiscallcc void @"?func@?$ExplicitlySpecializedTemplate@H@@QAEXXZ"
+// G32-DAG: define dso_local x86_thiscallcc void @_ZN29ExplicitlySpecializedTemplateIiE4funcEv
// Base class alredy specialized with export attribute.
struct __declspec(dllexport) DerivedFromExplicitlyExportSpecializedTemplate : public ExplicitlyExportSpecializedTemplate<int> {};
USEMEMFUNC(DerivedFromExplicitlyExportSpecializedTemplate, func)
-// M32-DAG: define dllexport x86_thiscallcc void @"\01?func@?$ExplicitlyExportSpecializedTemplate@H@@QAEXXZ"
-// G32-DAG: define dllexport x86_thiscallcc void @_ZN35ExplicitlyExportSpecializedTemplateIiE4funcEv
+// M32-DAG: define dso_local dllexport x86_thiscallcc void @"?func@?$ExplicitlyExportSpecializedTemplate@H@@QAEXXZ"
+// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN35ExplicitlyExportSpecializedTemplateIiE4funcEv
// Base class already specialized with import attribute.
struct __declspec(dllexport) DerivedFromExplicitlyImportSpecializedTemplate : public ExplicitlyImportSpecializedTemplate<int> {};
USEMEMFUNC(DerivedFromExplicitlyImportSpecializedTemplate, func)
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01?func@?$ExplicitlyImportSpecializedTemplate@H@@QAEXXZ"
+// M32-DAG: declare dllimport x86_thiscallcc void @"?func@?$ExplicitlyImportSpecializedTemplate@H@@QAEXXZ"
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN35ExplicitlyImportSpecializedTemplateIiE4funcEv
// Base class already instantiated without dll attribute.
struct __declspec(dllexport) DerivedFromExplicitlyInstantiatedTemplate : public ExplicitlyInstantiatedTemplate<int> {};
USEMEMFUNC(DerivedFromExplicitlyInstantiatedTemplate, func)
-// M32-DAG: define weak_odr x86_thiscallcc void @"\01?func@?$ExplicitlyInstantiatedTemplate@H@@QAEXXZ"
-// G32-DAG: define weak_odr x86_thiscallcc void @_ZN30ExplicitlyInstantiatedTemplateIiE4funcEv
+// M32-DAG: define weak_odr dso_local x86_thiscallcc void @"?func@?$ExplicitlyInstantiatedTemplate@H@@QAEXXZ"
+// G32-DAG: define weak_odr dso_local x86_thiscallcc void @_ZN30ExplicitlyInstantiatedTemplateIiE4funcEv
// Base class already instantiated with export attribute.
struct __declspec(dllexport) DerivedFromExplicitlyExportInstantiatedTemplate : public ExplicitlyExportInstantiatedTemplate<int> {};
USEMEMFUNC(DerivedFromExplicitlyExportInstantiatedTemplate, func)
-// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ExplicitlyExportInstantiatedTemplate@H@@QAEXXZ"
-// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN36ExplicitlyExportInstantiatedTemplateIiE4funcEv
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?func@?$ExplicitlyExportInstantiatedTemplate@H@@QAEXXZ"
+// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN36ExplicitlyExportInstantiatedTemplateIiE4funcEv
// Base class already instantiated with import attribute.
struct __declspec(dllexport) DerivedFromExplicitlyImportInstantiatedTemplate : public ExplicitlyImportInstantiatedTemplate<int> {};
USEMEMFUNC(DerivedFromExplicitlyImportInstantiatedTemplate, func)
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01?func@?$ExplicitlyImportInstantiatedTemplate@H@@QAEXXZ"
+// M32-DAG: declare dllimport x86_thiscallcc void @"?func@?$ExplicitlyImportInstantiatedTemplate@H@@QAEXXZ"
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN36ExplicitlyImportInstantiatedTemplateIiE4funcEv
// MS: A dll attribute propagates through multiple levels of instantiation.
@@ -944,15 +988,15 @@ template <typename T> struct TopClass { void func() {} };
template <typename T> struct MiddleClass : public TopClass<T> { };
struct __declspec(dllexport) BottomClass : public MiddleClass<int> { };
USEMEMFUNC(BottomClass, func)
-// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$TopClass@H@@QAEXXZ"
-// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN8TopClassIiE4funcEv
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?func@?$TopClass@H@@QAEXXZ"
+// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN8TopClassIiE4funcEv
template <typename T> struct ExplicitInstantiationDeclTemplateBase { void func() {} };
extern template struct ExplicitInstantiationDeclTemplateBase<int>;
struct __declspec(dllexport) DerivedFromExplicitInstantiationDeclTemplateBase : public ExplicitInstantiationDeclTemplateBase<int> {};
template struct ExplicitInstantiationDeclTemplateBase<int>;
-// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ExplicitInstantiationDeclTemplateBase@H@@QAEXXZ"
-// G32-DAG: define weak_odr x86_thiscallcc void @_ZN37ExplicitInstantiationDeclTemplateBaseIiE4funcEv
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?func@?$ExplicitInstantiationDeclTemplateBase@H@@QAEXXZ"
+// G32-DAG: define weak_odr dso_local x86_thiscallcc void @_ZN37ExplicitInstantiationDeclTemplateBaseIiE4funcEv
// PR26076
struct LayerSelectionBound;
@@ -965,8 +1009,8 @@ struct __declspec(dllexport) LayerTreeImpl {
};
LayerSelection foo;
};
-// M32-DAG: define weak_odr dllexport x86_thiscallcc %"struct.LayerTreeImpl::ElementLayers"* @"\01??0ElementLayers@LayerTreeImpl@@QAE@XZ"
-// M64-DAG: define weak_odr dllexport %"struct.LayerTreeImpl::ElementLayers"* @"\01??0ElementLayers@LayerTreeImpl@@QEAA@XZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %"struct.LayerTreeImpl::ElementLayers"* @"??0ElementLayers@LayerTreeImpl@@QAE@XZ"
+// M64-DAG: define weak_odr dso_local dllexport %"struct.LayerTreeImpl::ElementLayers"* @"??0ElementLayers@LayerTreeImpl@@QEAA@XZ"
class __declspec(dllexport) ACE_Shared_Object {
public:
@@ -974,6 +1018,6 @@ public:
};
class __declspec(dllexport) ACE_Service_Object : public ACE_Shared_Object {};
// Implicit move constructor declaration.
-// MSVC2015-DAG: define weak_odr dllexport {{.+}}ACE_Service_Object@@Q{{.+}}@$$Q
+// MSVC2015-DAG: define weak_odr dso_local dllexport {{.+}}ACE_Service_Object@@Q{{.+}}@$$Q
// The declarations should not be exported.
-// MSVC2013-NOT: define weak_odr dllexport {{.+}}ACE_Service_Object@@Q{{.+}}@$$Q
+// MSVC2013-NOT: define weak_odr dso_local dllexport {{.+}}ACE_Service_Object@@Q{{.+}}@$$Q
diff --git a/test/CodeGenCXX/dllimport-dtor-thunks.cpp b/test/CodeGenCXX/dllimport-dtor-thunks.cpp
index b381fff450da..da3227a49a4b 100644
--- a/test/CodeGenCXX/dllimport-dtor-thunks.cpp
+++ b/test/CodeGenCXX/dllimport-dtor-thunks.cpp
@@ -1,9 +1,5 @@
// RUN: %clang_cc1 -mconstructor-aliases %s -triple x86_64-windows-msvc -fms-extensions -emit-llvm -o - | FileCheck %s
-// FIXME: We should really consider removing -mconstructor-aliases for MS C++
-// ABI. The risk of bugs introducing ABI incompatibility under
-// -mno-constructor-aliases is too high.
-
// PR32990
// Introduces the virtual destructor. We should use the base destructor
@@ -39,11 +35,11 @@ extern "C" void testit() {
// The destructors are called in reverse order of construction. Only the third
// needs the complete destructor (_D).
-// CHECK-LABEL: define void @testit()
-// CHECK: call void @"\01??_DImportVBaseOverrideVDtor@@QEAAXXZ"(%struct.ImportVBaseOverrideVDtor* %{{.*}})
-// CHECK: call void @"\01??1ImportOverrideVDtor@@UEAA@XZ"(%struct.ImportOverrideVDtor* %{{.*}})
-// CHECK: call void @"\01??1ImportIntroVDtor@@UEAA@XZ"(%struct.ImportIntroVDtor* %{{.*}})
-
-// CHECK-LABEL: define linkonce_odr void @"\01??_DImportVBaseOverrideVDtor@@QEAAXXZ"
-// CHECK-LABEL: declare dllimport void @"\01??1ImportOverrideVDtor@@UEAA@XZ"
-// CHECK-LABEL: declare dllimport void @"\01??1ImportIntroVDtor@@UEAA@XZ"
+// CHECK-LABEL: define dso_local void @testit()
+// CHECK: call void @"??_DImportVBaseOverrideVDtor@@QEAAXXZ"(%struct.ImportVBaseOverrideVDtor* %{{.*}})
+// CHECK: call void @"??1ImportOverrideVDtor@@UEAA@XZ"(%struct.ImportOverrideVDtor* %{{.*}})
+// CHECK: call void @"??1ImportIntroVDtor@@UEAA@XZ"(%struct.ImportIntroVDtor* %{{.*}})
+
+// CHECK-LABEL: declare dllimport void @"??_DImportVBaseOverrideVDtor@@QEAAXXZ"
+// CHECK-LABEL: declare dllimport void @"??1ImportOverrideVDtor@@UEAA@XZ"
+// CHECK-LABEL: declare dllimport void @"??1ImportIntroVDtor@@UEAA@XZ"
diff --git a/test/CodeGenCXX/dllimport-members.cpp b/test/CodeGenCXX/dllimport-members.cpp
index ff7868382d8c..7a7519f66831 100644
--- a/test/CodeGenCXX/dllimport-members.cpp
+++ b/test/CodeGenCXX/dllimport-members.cpp
@@ -63,124 +63,124 @@ struct __declspec(dllimport) ForceNonTrivial {
struct ImportMembers {
struct Nested;
- // M32-DAG: define dllexport x86_thiscallcc void @"\01?normalDef@ImportMembers@@QAEXXZ"(%struct.ImportMembers* %this)
- // M64-DAG: define dllexport void @"\01?normalDef@ImportMembers@@QEAAXXZ"(%struct.ImportMembers* %this)
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalDecl@ImportMembers@@QAEXXZ"(%struct.ImportMembers*)
- // M64-DAG: declare dllimport void @"\01?normalDecl@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*)
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInclass@ImportMembers@@QAEXXZ"(%struct.ImportMembers*)
- // M64-DAG: declare dllimport void @"\01?normalInclass@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*)
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInlineDef@ImportMembers@@QAEXXZ"(%struct.ImportMembers*)
- // M64-DAG: declare dllimport void @"\01?normalInlineDef@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*)
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInlineDecl@ImportMembers@@QAEXXZ"(%struct.ImportMembers*)
- // M64-DAG: declare dllimport void @"\01?normalInlineDecl@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*)
- // G32-DAG: define x86_thiscallcc void @_ZN13ImportMembers9normalDefEv(%struct.ImportMembers* %this)
- // G64-DAG: define void @_ZN13ImportMembers9normalDefEv(%struct.ImportMembers* %this)
- // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers10normalDeclEv(%struct.ImportMembers*)
- // G64-DAG: declare dllimport void @_ZN13ImportMembers10normalDeclEv(%struct.ImportMembers*)
- // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers13normalInclassEv(%struct.ImportMembers* %this)
- // G64-DAG: define linkonce_odr void @_ZN13ImportMembers13normalInclassEv(%struct.ImportMembers* %this)
- // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers15normalInlineDefEv(%struct.ImportMembers* %this)
- // G64-DAG: define linkonce_odr void @_ZN13ImportMembers15normalInlineDefEv(%struct.ImportMembers* %this)
- // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers16normalInlineDeclEv(%struct.ImportMembers* %this)
- // G64-DAG: define linkonce_odr void @_ZN13ImportMembers16normalInlineDeclEv(%struct.ImportMembers* %this)
- // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?normalInclass@ImportMembers@@QAEXXZ"(
- // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?normalInlineDef@ImportMembers@@QAEXXZ"(
- // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?normalInlineDecl@ImportMembers@@QAEXXZ"(
- // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers13normalInclassEv(
- // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers15normalInlineDefEv(
- // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers16normalInlineDeclEv(
+ // M32-DAG: define dso_local dllexport x86_thiscallcc void @"?normalDef@ImportMembers@@QAEXXZ"(%struct.ImportMembers* %this)
+ // M64-DAG: define dso_local dllexport void @"?normalDef@ImportMembers@@QEAAXXZ"(%struct.ImportMembers* %this)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?normalDecl@ImportMembers@@QAEXXZ"(%struct.ImportMembers*)
+ // M64-DAG: declare dllimport void @"?normalDecl@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?normalInclass@ImportMembers@@QAEXXZ"(%struct.ImportMembers*)
+ // M64-DAG: declare dllimport void @"?normalInclass@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?normalInlineDef@ImportMembers@@QAEXXZ"(%struct.ImportMembers*)
+ // M64-DAG: declare dllimport void @"?normalInlineDef@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?normalInlineDecl@ImportMembers@@QAEXXZ"(%struct.ImportMembers*)
+ // M64-DAG: declare dllimport void @"?normalInlineDecl@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*)
+ // G32-DAG: define dso_local x86_thiscallcc void @_ZN13ImportMembers9normalDefEv(%struct.ImportMembers* %this)
+ // G64-DAG: define dso_local void @_ZN13ImportMembers9normalDefEv(%struct.ImportMembers* %this)
+ // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers10normalDeclEv(%struct.ImportMembers*)
+ // G64-DAG: declare dllimport void @_ZN13ImportMembers10normalDeclEv(%struct.ImportMembers*)
+ // G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers13normalInclassEv(%struct.ImportMembers* %this)
+ // G64-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers13normalInclassEv(%struct.ImportMembers* %this)
+ // G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers15normalInlineDefEv(%struct.ImportMembers* %this)
+ // G64-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers15normalInlineDefEv(%struct.ImportMembers* %this)
+ // G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers16normalInlineDeclEv(%struct.ImportMembers* %this)
+ // G64-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers16normalInlineDeclEv(%struct.ImportMembers* %this)
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"?normalInclass@ImportMembers@@QAEXXZ"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"?normalInlineDef@ImportMembers@@QAEXXZ"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"?normalInlineDecl@ImportMembers@@QAEXXZ"(
+ // GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers13normalInclassEv(
+ // GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers15normalInlineDefEv(
+ // GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers16normalInlineDeclEv(
__declspec(dllimport) void normalDef(); // dllimport ignored
__declspec(dllimport) void normalDecl();
__declspec(dllimport) void normalInclass() {}
__declspec(dllimport) void normalInlineDef();
__declspec(dllimport) inline void normalInlineDecl();
- // M32-DAG: define dllexport x86_thiscallcc void @"\01?virtualDef@ImportMembers@@UAEXXZ"(%struct.ImportMembers* %this)
- // M64-DAG: define dllexport void @"\01?virtualDef@ImportMembers@@UEAAXXZ"(%struct.ImportMembers* %this)
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualDecl@ImportMembers@@UAEXXZ"(%struct.ImportMembers*)
- // M64-DAG: declare dllimport void @"\01?virtualDecl@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*)
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInclass@ImportMembers@@UAEXXZ"(%struct.ImportMembers*)
- // M64-DAG: declare dllimport void @"\01?virtualInclass@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*)
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInlineDef@ImportMembers@@UAEXXZ"(%struct.ImportMembers*)
- // M64-DAG: declare dllimport void @"\01?virtualInlineDef@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*)
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInlineDecl@ImportMembers@@UAEXXZ"(%struct.ImportMembers*)
- // M64-DAG: declare dllimport void @"\01?virtualInlineDecl@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*)
- // G32-DAG: define x86_thiscallcc void @_ZN13ImportMembers10virtualDefEv(%struct.ImportMembers* %this)
- // G64-DAG: define void @_ZN13ImportMembers10virtualDefEv(%struct.ImportMembers* %this)
+ // M32-DAG: define dso_local dllexport x86_thiscallcc void @"?virtualDef@ImportMembers@@UAEXXZ"(%struct.ImportMembers* %this)
+ // M64-DAG: define dso_local dllexport void @"?virtualDef@ImportMembers@@UEAAXXZ"(%struct.ImportMembers* %this)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?virtualDecl@ImportMembers@@UAEXXZ"(%struct.ImportMembers*)
+ // M64-DAG: declare dllimport void @"?virtualDecl@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?virtualInclass@ImportMembers@@UAEXXZ"(%struct.ImportMembers*)
+ // M64-DAG: declare dllimport void @"?virtualInclass@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?virtualInlineDef@ImportMembers@@UAEXXZ"(%struct.ImportMembers*)
+ // M64-DAG: declare dllimport void @"?virtualInlineDef@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?virtualInlineDecl@ImportMembers@@UAEXXZ"(%struct.ImportMembers*)
+ // M64-DAG: declare dllimport void @"?virtualInlineDecl@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*)
+ // G32-DAG: define dso_local x86_thiscallcc void @_ZN13ImportMembers10virtualDefEv(%struct.ImportMembers* %this)
+ // G64-DAG: define dso_local void @_ZN13ImportMembers10virtualDefEv(%struct.ImportMembers* %this)
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers11virtualDeclEv(%struct.ImportMembers*)
// G64-DAG: declare dllimport void @_ZN13ImportMembers11virtualDeclEv(%struct.ImportMembers*)
- // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers14virtualInclassEv(%struct.ImportMembers* %this)
- // G64-DAG: define linkonce_odr void @_ZN13ImportMembers14virtualInclassEv(%struct.ImportMembers* %this)
- // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers16virtualInlineDefEv(%struct.ImportMembers* %this)
- // G64-DAG: define linkonce_odr void @_ZN13ImportMembers16virtualInlineDefEv(%struct.ImportMembers* %this)
- // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers17virtualInlineDeclEv(%struct.ImportMembers* %this)
- // G64-DAG: define linkonce_odr void @_ZN13ImportMembers17virtualInlineDeclEv(%struct.ImportMembers* %this)
- // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?virtualInclass@ImportMembers@@UAEXXZ"(
- // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?virtualInlineDef@ImportMembers@@UAEXXZ"(
- // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?virtualInlineDecl@ImportMembers@@UAEXXZ"(
- // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers14virtualInclassEv(
- // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers16virtualInlineDefEv(
- // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers17virtualInlineDeclEv(
+ // G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers14virtualInclassEv(%struct.ImportMembers* %this)
+ // G64-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers14virtualInclassEv(%struct.ImportMembers* %this)
+ // G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers16virtualInlineDefEv(%struct.ImportMembers* %this)
+ // G64-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers16virtualInlineDefEv(%struct.ImportMembers* %this)
+ // G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers17virtualInlineDeclEv(%struct.ImportMembers* %this)
+ // G64-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers17virtualInlineDeclEv(%struct.ImportMembers* %this)
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"?virtualInclass@ImportMembers@@UAEXXZ"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"?virtualInlineDef@ImportMembers@@UAEXXZ"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"?virtualInlineDecl@ImportMembers@@UAEXXZ"(
+ // GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers14virtualInclassEv(
+ // GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers16virtualInlineDefEv(
+ // GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers17virtualInlineDeclEv(
__declspec(dllimport) virtual void virtualDef(); // dllimport ignored
__declspec(dllimport) virtual void virtualDecl();
__declspec(dllimport) virtual void virtualInclass() {}
__declspec(dllimport) virtual void virtualInlineDef();
__declspec(dllimport) virtual inline void virtualInlineDecl();
- // MSC-DAG: define dllexport void @"\01?staticDef@ImportMembers@@SAXXZ"()
- // MSC-DAG: declare dllimport void @"\01?staticDecl@ImportMembers@@SAXXZ"()
- // MSC-DAG: declare dllimport void @"\01?staticInclass@ImportMembers@@SAXXZ"()
- // MSC-DAG: declare dllimport void @"\01?staticInlineDef@ImportMembers@@SAXXZ"()
- // MSC-DAG: declare dllimport void @"\01?staticInlineDecl@ImportMembers@@SAXXZ"()
- // GNU-DAG: define void @_ZN13ImportMembers9staticDefEv()
- // GNU-DAG: declare dllimport void @_ZN13ImportMembers10staticDeclEv()
- // GNU-DAG: define linkonce_odr void @_ZN13ImportMembers13staticInclassEv()
- // GNU-DAG: define linkonce_odr void @_ZN13ImportMembers15staticInlineDefEv()
- // GNU-DAG: define linkonce_odr void @_ZN13ImportMembers16staticInlineDeclEv()
- // MO1-DAG: define available_externally dllimport void @"\01?staticInclass@ImportMembers@@SAXXZ"()
- // MO1-DAG: define available_externally dllimport void @"\01?staticInlineDef@ImportMembers@@SAXXZ"()
- // MO1-DAG: define available_externally dllimport void @"\01?staticInlineDecl@ImportMembers@@SAXXZ"()
- // GO1-DAG: define linkonce_odr void @_ZN13ImportMembers13staticInclassEv()
- // GO1-DAG: define linkonce_odr void @_ZN13ImportMembers15staticInlineDefEv()
- // GO1-DAG: define linkonce_odr void @_ZN13ImportMembers16staticInlineDeclEv()
+ // MSC-DAG: define dso_local dllexport void @"?staticDef@ImportMembers@@SAXXZ"()
+ // MSC-DAG: declare dllimport void @"?staticDecl@ImportMembers@@SAXXZ"()
+ // MSC-DAG: declare dllimport void @"?staticInclass@ImportMembers@@SAXXZ"()
+ // MSC-DAG: declare dllimport void @"?staticInlineDef@ImportMembers@@SAXXZ"()
+ // MSC-DAG: declare dllimport void @"?staticInlineDecl@ImportMembers@@SAXXZ"()
+ // GNU-DAG: define dso_local void @_ZN13ImportMembers9staticDefEv()
+ // GNU-DAG: declare dllimport void @_ZN13ImportMembers10staticDeclEv()
+ // GNU-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers13staticInclassEv()
+ // GNU-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers15staticInlineDefEv()
+ // GNU-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers16staticInlineDeclEv()
+ // MO1-DAG: define available_externally dllimport void @"?staticInclass@ImportMembers@@SAXXZ"()
+ // MO1-DAG: define available_externally dllimport void @"?staticInlineDef@ImportMembers@@SAXXZ"()
+ // MO1-DAG: define available_externally dllimport void @"?staticInlineDecl@ImportMembers@@SAXXZ"()
+ // GO1-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers13staticInclassEv()
+ // GO1-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers15staticInlineDefEv()
+ // GO1-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers16staticInlineDeclEv()
__declspec(dllimport) static void staticDef(); // dllimport ignored
__declspec(dllimport) static void staticDecl();
__declspec(dllimport) static void staticInclass() {}
__declspec(dllimport) static void staticInlineDef();
__declspec(dllimport) static inline void staticInlineDecl();
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?protectedNormalDecl@ImportMembers@@IAEXXZ"(%struct.ImportMembers*)
- // M64-DAG: declare dllimport void @"\01?protectedNormalDecl@ImportMembers@@IEAAXXZ"(%struct.ImportMembers*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?protectedNormalDecl@ImportMembers@@IAEXXZ"(%struct.ImportMembers*)
+ // M64-DAG: declare dllimport void @"?protectedNormalDecl@ImportMembers@@IEAAXXZ"(%struct.ImportMembers*)
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers19protectedNormalDeclEv(%struct.ImportMembers*)
// G64-DAG: declare dllimport void @_ZN13ImportMembers19protectedNormalDeclEv(%struct.ImportMembers*)
- // MSC-DAG: declare dllimport void @"\01?protectedStaticDecl@ImportMembers@@KAXXZ"()
+ // MSC-DAG: declare dllimport void @"?protectedStaticDecl@ImportMembers@@KAXXZ"()
// GNU-DAG: declare dllimport void @_ZN13ImportMembers19protectedStaticDeclEv()
protected:
__declspec(dllimport) void protectedNormalDecl();
__declspec(dllimport) static void protectedStaticDecl();
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?privateNormalDecl@ImportMembers@@AAEXXZ"(%struct.ImportMembers*)
- // M64-DAG: declare dllimport void @"\01?privateNormalDecl@ImportMembers@@AEAAXXZ"(%struct.ImportMembers*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?privateNormalDecl@ImportMembers@@AAEXXZ"(%struct.ImportMembers*)
+ // M64-DAG: declare dllimport void @"?privateNormalDecl@ImportMembers@@AEAAXXZ"(%struct.ImportMembers*)
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers17privateNormalDeclEv(%struct.ImportMembers*)
// G64-DAG: declare dllimport void @_ZN13ImportMembers17privateNormalDeclEv(%struct.ImportMembers*)
- // MSC-DAG: declare dllimport void @"\01?privateStaticDecl@ImportMembers@@CAXXZ"()
+ // MSC-DAG: declare dllimport void @"?privateStaticDecl@ImportMembers@@CAXXZ"()
// GNU-DAG: declare dllimport void @_ZN13ImportMembers17privateStaticDeclEv()
private:
__declspec(dllimport) void privateNormalDecl();
__declspec(dllimport) static void privateStaticDecl();
- // M32-DAG: declare x86_thiscallcc void @"\01?ignored@ImportMembers@@QAEXXZ"(%struct.ImportMembers*)
- // M64-DAG: declare void @"\01?ignored@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*)
- // G32-DAG: declare x86_thiscallcc void @_ZN13ImportMembers7ignoredEv(%struct.ImportMembers*)
- // G64-DAG: declare void @_ZN13ImportMembers7ignoredEv(%struct.ImportMembers*)
+ // M32-DAG: declare dso_local x86_thiscallcc void @"?ignored@ImportMembers@@QAEXXZ"(%struct.ImportMembers*)
+ // M64-DAG: declare dso_local void @"?ignored@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*)
+ // G32-DAG: declare dso_local x86_thiscallcc void @_ZN13ImportMembers7ignoredEv(%struct.ImportMembers*)
+ // G64-DAG: declare dso_local void @_ZN13ImportMembers7ignoredEv(%struct.ImportMembers*)
public:
void ignored();
- // MSC-DAG: @"\01?StaticField@ImportMembers@@2HA" = external dllimport global i32
- // MSC-DAG: @"\01?StaticConstField@ImportMembers@@2HB" = external dllimport constant i32
- // MSC-DAG: @"\01?StaticConstFieldEqualInit@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4
- // MSC-DAG: @"\01?StaticConstFieldBraceInit@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4
- // MSC-DAG: @"\01?ConstexprField@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4
+ // MSC-DAG: @"?StaticField@ImportMembers@@2HA" = external dllimport global i32
+ // MSC-DAG: @"?StaticConstField@ImportMembers@@2HB" = external dllimport constant i32
+ // MSC-DAG: @"?StaticConstFieldEqualInit@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4
+ // MSC-DAG: @"?StaticConstFieldBraceInit@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4
+ // MSC-DAG: @"?ConstexprField@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4
// GNU-DAG: @_ZN13ImportMembers11StaticFieldE = external dllimport global i32
// GNU-DAG: @_ZN13ImportMembers16StaticConstFieldE = external dllimport constant i32
// GNU-DAG: @_ZN13ImportMembers25StaticConstFieldEqualInitE = external dllimport constant i32
@@ -235,125 +235,125 @@ USEMV(ImportMembers, ConstexprField)
// Import individual members of a nested class.
struct ImportMembers::Nested {
- // M32-DAG: define dllexport x86_thiscallcc void @"\01?normalDef@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"* %this)
- // M64-DAG: define dllexport void @"\01?normalDef@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"* %this)
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalDecl@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*)
- // M64-DAG: declare dllimport void @"\01?normalDecl@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*)
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInclass@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*)
- // M64-DAG: declare dllimport void @"\01?normalInclass@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*)
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInlineDef@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*)
- // M64-DAG: declare dllimport void @"\01?normalInlineDef@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*)
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInlineDecl@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*)
- // M64-DAG: declare dllimport void @"\01?normalInlineDecl@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*)
- // G32-DAG: define x86_thiscallcc void @_ZN13ImportMembers6Nested9normalDefEv(%"struct.ImportMembers::Nested"* %this)
- // G64-DAG: define void @_ZN13ImportMembers6Nested9normalDefEv(%"struct.ImportMembers::Nested"* %this)
+ // M32-DAG: define dso_local dllexport x86_thiscallcc void @"?normalDef@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"* %this)
+ // M64-DAG: define dso_local dllexport void @"?normalDef@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"* %this)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?normalDecl@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*)
+ // M64-DAG: declare dllimport void @"?normalDecl@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?normalInclass@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*)
+ // M64-DAG: declare dllimport void @"?normalInclass@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?normalInlineDef@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*)
+ // M64-DAG: declare dllimport void @"?normalInlineDef@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?normalInlineDecl@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*)
+ // M64-DAG: declare dllimport void @"?normalInlineDecl@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*)
+ // G32-DAG: define dso_local x86_thiscallcc void @_ZN13ImportMembers6Nested9normalDefEv(%"struct.ImportMembers::Nested"* %this)
+ // G64-DAG: define dso_local void @_ZN13ImportMembers6Nested9normalDefEv(%"struct.ImportMembers::Nested"* %this)
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested10normalDeclEv(%"struct.ImportMembers::Nested"*)
// G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested10normalDeclEv(%"struct.ImportMembers::Nested"*)
- // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers6Nested13normalInclassEv(%"struct.ImportMembers::Nested"* %this)
- // G64-DAG: define linkonce_odr void @_ZN13ImportMembers6Nested13normalInclassEv(%"struct.ImportMembers::Nested"* %this)
- // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers6Nested15normalInlineDefEv(%"struct.ImportMembers::Nested"* %this)
- // G64-DAG: define linkonce_odr void @_ZN13ImportMembers6Nested15normalInlineDefEv(%"struct.ImportMembers::Nested"* %this)
- // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers6Nested16normalInlineDeclEv(%"struct.ImportMembers::Nested"* %this)
- // G64-DAG: define linkonce_odr void @_ZN13ImportMembers6Nested16normalInlineDeclEv(%"struct.ImportMembers::Nested"* %this)
- // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?normalInclass@Nested@ImportMembers@@QAEXXZ"(
- // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?normalInlineDef@Nested@ImportMembers@@QAEXXZ"(
- // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?normalInlineDecl@Nested@ImportMembers@@QAEXXZ"(
- // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers6Nested13normalInclassEv(
- // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers6Nested15normalInlineDefEv(
- // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers6Nested16normalInlineDeclEv(
+ // G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers6Nested13normalInclassEv(%"struct.ImportMembers::Nested"* %this)
+ // G64-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers6Nested13normalInclassEv(%"struct.ImportMembers::Nested"* %this)
+ // G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers6Nested15normalInlineDefEv(%"struct.ImportMembers::Nested"* %this)
+ // G64-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers6Nested15normalInlineDefEv(%"struct.ImportMembers::Nested"* %this)
+ // G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers6Nested16normalInlineDeclEv(%"struct.ImportMembers::Nested"* %this)
+ // G64-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers6Nested16normalInlineDeclEv(%"struct.ImportMembers::Nested"* %this)
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"?normalInclass@Nested@ImportMembers@@QAEXXZ"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"?normalInlineDef@Nested@ImportMembers@@QAEXXZ"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"?normalInlineDecl@Nested@ImportMembers@@QAEXXZ"(
+ // GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers6Nested13normalInclassEv(
+ // GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers6Nested15normalInlineDefEv(
+ // GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers6Nested16normalInlineDeclEv(
__declspec(dllimport) void normalDef(); // dllimport ignored
__declspec(dllimport) void normalDecl();
__declspec(dllimport) void normalInclass() {}
__declspec(dllimport) void normalInlineDef();
__declspec(dllimport) inline void normalInlineDecl();
- // M32-DAG: define dllexport x86_thiscallcc void @"\01?virtualDef@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"* %this)
- // M64-DAG: define dllexport void @"\01?virtualDef@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"* %this)
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualDecl@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*)
- // M64-DAG: declare dllimport void @"\01?virtualDecl@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"*)
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInclass@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*)
- // M64-DAG: declare dllimport void @"\01?virtualInclass@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"*)
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInlineDef@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*)
- // M64-DAG: declare dllimport void @"\01?virtualInlineDef@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"*)
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInlineDecl@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*)
- // M64-DAG: declare dllimport void @"\01?virtualInlineDecl@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"*)
- // G32-DAG: define x86_thiscallcc void @_ZN13ImportMembers6Nested10virtualDefEv(%"struct.ImportMembers::Nested"* %this)
- // G64-DAG: define void @_ZN13ImportMembers6Nested10virtualDefEv(%"struct.ImportMembers::Nested"* %this)
+ // M32-DAG: define dso_local dllexport x86_thiscallcc void @"?virtualDef@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"* %this)
+ // M64-DAG: define dso_local dllexport void @"?virtualDef@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"* %this)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?virtualDecl@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*)
+ // M64-DAG: declare dllimport void @"?virtualDecl@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?virtualInclass@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*)
+ // M64-DAG: declare dllimport void @"?virtualInclass@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?virtualInlineDef@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*)
+ // M64-DAG: declare dllimport void @"?virtualInlineDef@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?virtualInlineDecl@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*)
+ // M64-DAG: declare dllimport void @"?virtualInlineDecl@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"*)
+ // G32-DAG: define dso_local x86_thiscallcc void @_ZN13ImportMembers6Nested10virtualDefEv(%"struct.ImportMembers::Nested"* %this)
+ // G64-DAG: define dso_local void @_ZN13ImportMembers6Nested10virtualDefEv(%"struct.ImportMembers::Nested"* %this)
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested11virtualDeclEv(%"struct.ImportMembers::Nested"*)
// G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested11virtualDeclEv(%"struct.ImportMembers::Nested"*)
- // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers6Nested14virtualInclassEv(%"struct.ImportMembers::Nested"* %this)
- // G64-DAG: define linkonce_odr void @_ZN13ImportMembers6Nested14virtualInclassEv(%"struct.ImportMembers::Nested"* %this)
- // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers6Nested16virtualInlineDefEv(%"struct.ImportMembers::Nested"* %this)
- // G64-DAG: define linkonce_odr void @_ZN13ImportMembers6Nested16virtualInlineDefEv(%"struct.ImportMembers::Nested"* %this)
- // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers6Nested17virtualInlineDeclEv(%"struct.ImportMembers::Nested"* %this)
- // G64-DAG: define linkonce_odr void @_ZN13ImportMembers6Nested17virtualInlineDeclEv(%"struct.ImportMembers::Nested"* %this)
-
- // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?virtualInclass@Nested@ImportMembers@@UAEXXZ"(
- // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?virtualInlineDef@Nested@ImportMembers@@UAEXXZ"(
- // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?virtualInlineDecl@Nested@ImportMembers@@UAEXXZ"(
- // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers6Nested14virtualInclassEv(
- // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers6Nested16virtualInlineDefEv(
- // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers6Nested17virtualInlineDeclEv(
+ // G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers6Nested14virtualInclassEv(%"struct.ImportMembers::Nested"* %this)
+ // G64-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers6Nested14virtualInclassEv(%"struct.ImportMembers::Nested"* %this)
+ // G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers6Nested16virtualInlineDefEv(%"struct.ImportMembers::Nested"* %this)
+ // G64-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers6Nested16virtualInlineDefEv(%"struct.ImportMembers::Nested"* %this)
+ // G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers6Nested17virtualInlineDeclEv(%"struct.ImportMembers::Nested"* %this)
+ // G64-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers6Nested17virtualInlineDeclEv(%"struct.ImportMembers::Nested"* %this)
+
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"?virtualInclass@Nested@ImportMembers@@UAEXXZ"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"?virtualInlineDef@Nested@ImportMembers@@UAEXXZ"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"?virtualInlineDecl@Nested@ImportMembers@@UAEXXZ"(
+ // GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers6Nested14virtualInclassEv(
+ // GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers6Nested16virtualInlineDefEv(
+ // GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers6Nested17virtualInlineDeclEv(
__declspec(dllimport) virtual void virtualDef(); // dllimport ignored
__declspec(dllimport) virtual void virtualDecl();
__declspec(dllimport) virtual void virtualInclass() {}
__declspec(dllimport) virtual void virtualInlineDef();
__declspec(dllimport) virtual inline void virtualInlineDecl();
- // MSC-DAG: define dllexport void @"\01?staticDef@Nested@ImportMembers@@SAXXZ"()
- // MSC-DAG: declare dllimport void @"\01?staticDecl@Nested@ImportMembers@@SAXXZ"()
- // MSC-DAG: declare dllimport void @"\01?staticInclass@Nested@ImportMembers@@SAXXZ"()
- // MSC-DAG: declare dllimport void @"\01?staticInlineDef@Nested@ImportMembers@@SAXXZ"()
- // MSC-DAG: declare dllimport void @"\01?staticInlineDecl@Nested@ImportMembers@@SAXXZ"()
- // GNU-DAG: define void @_ZN13ImportMembers6Nested9staticDefEv()
- // GNU-DAG: declare dllimport void @_ZN13ImportMembers6Nested10staticDeclEv()
- // GNU-DAG: define linkonce_odr void @_ZN13ImportMembers6Nested13staticInclassEv()
- // GNU-DAG: define linkonce_odr void @_ZN13ImportMembers6Nested15staticInlineDefEv()
- // GNU-DAG: define linkonce_odr void @_ZN13ImportMembers6Nested16staticInlineDeclEv()
- // MO1-DAG: define available_externally dllimport void @"\01?staticInclass@Nested@ImportMembers@@SAXXZ"()
- // MO1-DAG: define available_externally dllimport void @"\01?staticInlineDef@Nested@ImportMembers@@SAXXZ"()
- // MO1-DAG: define available_externally dllimport void @"\01?staticInlineDecl@Nested@ImportMembers@@SAXXZ"()
- // GO1-DAG: define linkonce_odr void @_ZN13ImportMembers6Nested13staticInclassEv()
- // GO1-DAG: define linkonce_odr void @_ZN13ImportMembers6Nested15staticInlineDefEv()
- // GO1-DAG: define linkonce_odr void @_ZN13ImportMembers6Nested16staticInlineDeclEv()
+ // MSC-DAG: define dso_local dllexport void @"?staticDef@Nested@ImportMembers@@SAXXZ"()
+ // MSC-DAG: declare dllimport void @"?staticDecl@Nested@ImportMembers@@SAXXZ"()
+ // MSC-DAG: declare dllimport void @"?staticInclass@Nested@ImportMembers@@SAXXZ"()
+ // MSC-DAG: declare dllimport void @"?staticInlineDef@Nested@ImportMembers@@SAXXZ"()
+ // MSC-DAG: declare dllimport void @"?staticInlineDecl@Nested@ImportMembers@@SAXXZ"()
+ // GNU-DAG: define dso_local void @_ZN13ImportMembers6Nested9staticDefEv()
+ // GNU-DAG: declare dllimport void @_ZN13ImportMembers6Nested10staticDeclEv()
+ // GNU-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers6Nested13staticInclassEv()
+ // GNU-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers6Nested15staticInlineDefEv()
+ // GNU-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers6Nested16staticInlineDeclEv()
+ // MO1-DAG: define available_externally dllimport void @"?staticInclass@Nested@ImportMembers@@SAXXZ"()
+ // MO1-DAG: define available_externally dllimport void @"?staticInlineDef@Nested@ImportMembers@@SAXXZ"()
+ // MO1-DAG: define available_externally dllimport void @"?staticInlineDecl@Nested@ImportMembers@@SAXXZ"()
+ // GO1-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers6Nested13staticInclassEv()
+ // GO1-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers6Nested15staticInlineDefEv()
+ // GO1-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers6Nested16staticInlineDeclEv()
__declspec(dllimport) static void staticDef(); // dllimport ignored
__declspec(dllimport) static void staticDecl();
__declspec(dllimport) static void staticInclass() {}
__declspec(dllimport) static void staticInlineDef();
__declspec(dllimport) static inline void staticInlineDecl();
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?protectedNormalDecl@Nested@ImportMembers@@IAEXXZ"(%"struct.ImportMembers::Nested"*)
- // M64-DAG: declare dllimport void @"\01?protectedNormalDecl@Nested@ImportMembers@@IEAAXXZ"(%"struct.ImportMembers::Nested"*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?protectedNormalDecl@Nested@ImportMembers@@IAEXXZ"(%"struct.ImportMembers::Nested"*)
+ // M64-DAG: declare dllimport void @"?protectedNormalDecl@Nested@ImportMembers@@IEAAXXZ"(%"struct.ImportMembers::Nested"*)
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested19protectedNormalDeclEv(%"struct.ImportMembers::Nested"*)
// G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested19protectedNormalDeclEv(%"struct.ImportMembers::Nested"*)
- // MSC-DAG: declare dllimport void @"\01?protectedStaticDecl@Nested@ImportMembers@@KAXXZ"()
+ // MSC-DAG: declare dllimport void @"?protectedStaticDecl@Nested@ImportMembers@@KAXXZ"()
// GNU-DAG: declare dllimport void @_ZN13ImportMembers6Nested19protectedStaticDeclEv()
protected:
__declspec(dllimport) void protectedNormalDecl();
__declspec(dllimport) static void protectedStaticDecl();
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?privateNormalDecl@Nested@ImportMembers@@AAEXXZ"(%"struct.ImportMembers::Nested"*)
- // M64-DAG: declare dllimport void @"\01?privateNormalDecl@Nested@ImportMembers@@AEAAXXZ"(%"struct.ImportMembers::Nested"*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?privateNormalDecl@Nested@ImportMembers@@AAEXXZ"(%"struct.ImportMembers::Nested"*)
+ // M64-DAG: declare dllimport void @"?privateNormalDecl@Nested@ImportMembers@@AEAAXXZ"(%"struct.ImportMembers::Nested"*)
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested17privateNormalDeclEv(%"struct.ImportMembers::Nested"*)
// G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested17privateNormalDeclEv(%"struct.ImportMembers::Nested"*)
- // MSC-DAG: declare dllimport void @"\01?privateStaticDecl@Nested@ImportMembers@@CAXXZ"()
+ // MSC-DAG: declare dllimport void @"?privateStaticDecl@Nested@ImportMembers@@CAXXZ"()
// GNU-DAG: declare dllimport void @_ZN13ImportMembers6Nested17privateStaticDeclEv()
private:
__declspec(dllimport) void privateNormalDecl();
__declspec(dllimport) static void privateStaticDecl();
- // M32-DAG: declare x86_thiscallcc void @"\01?ignored@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*)
- // M64-DAG: declare void @"\01?ignored@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*)
- // G32-DAG: declare x86_thiscallcc void @_ZN13ImportMembers6Nested7ignoredEv(%"struct.ImportMembers::Nested"*)
- // G64-DAG: declare void @_ZN13ImportMembers6Nested7ignoredEv(%"struct.ImportMembers::Nested"*)
+ // M32-DAG: declare dso_local x86_thiscallcc void @"?ignored@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*)
+ // M64-DAG: declare dso_local void @"?ignored@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*)
+ // G32-DAG: declare dso_local x86_thiscallcc void @_ZN13ImportMembers6Nested7ignoredEv(%"struct.ImportMembers::Nested"*)
+ // G64-DAG: declare dso_local void @_ZN13ImportMembers6Nested7ignoredEv(%"struct.ImportMembers::Nested"*)
public:
void ignored();
- // MSC-DAG: @"\01?StaticField@Nested@ImportMembers@@2HA" = external dllimport global i32
- // MSC-DAG: @"\01?StaticConstField@Nested@ImportMembers@@2HB" = external dllimport constant i32
- // MSC-DAG: @"\01?StaticConstFieldEqualInit@Nested@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4
- // MSC-DAG: @"\01?StaticConstFieldBraceInit@Nested@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4
- // MSC-DAG: @"\01?ConstexprField@Nested@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4
+ // MSC-DAG: @"?StaticField@Nested@ImportMembers@@2HA" = external dllimport global i32
+ // MSC-DAG: @"?StaticConstField@Nested@ImportMembers@@2HB" = external dllimport constant i32
+ // MSC-DAG: @"?StaticConstFieldEqualInit@Nested@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4
+ // MSC-DAG: @"?StaticConstFieldBraceInit@Nested@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4
+ // MSC-DAG: @"?ConstexprField@Nested@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4
// GNU-DAG: @_ZN13ImportMembers6Nested11StaticFieldE = external dllimport global i32
// GNU-DAG: @_ZN13ImportMembers6Nested16StaticConstFieldE = external dllimport constant i32
// GNU-DAG: @_ZN13ImportMembers6Nested25StaticConstFieldEqualInitE = external dllimport constant i32
@@ -408,38 +408,38 @@ USEMV(ImportMembers::Nested, ConstexprField)
// Import special member functions.
struct ImportSpecials {
- // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportSpecials* @"\01??0ImportSpecials@@QAE@XZ"(%struct.ImportSpecials* returned)
- // M64-DAG: declare dllimport %struct.ImportSpecials* @"\01??0ImportSpecials@@QEAA@XZ"(%struct.ImportSpecials* returned)
+ // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportSpecials* @"??0ImportSpecials@@QAE@XZ"(%struct.ImportSpecials* returned)
+ // M64-DAG: declare dllimport %struct.ImportSpecials* @"??0ImportSpecials@@QEAA@XZ"(%struct.ImportSpecials* returned)
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN14ImportSpecialsC1Ev(%struct.ImportSpecials*)
// G64-DAG: declare dllimport void @_ZN14ImportSpecialsC1Ev(%struct.ImportSpecials*)
__declspec(dllimport) ImportSpecials();
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01??1ImportSpecials@@QAE@XZ"(%struct.ImportSpecials*)
- // M64-DAG: declare dllimport void @"\01??1ImportSpecials@@QEAA@XZ"(%struct.ImportSpecials*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"??1ImportSpecials@@QAE@XZ"(%struct.ImportSpecials*)
+ // M64-DAG: declare dllimport void @"??1ImportSpecials@@QEAA@XZ"(%struct.ImportSpecials*)
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN14ImportSpecialsD1Ev(%struct.ImportSpecials*)
// G64-DAG: declare dllimport void @_ZN14ImportSpecialsD1Ev(%struct.ImportSpecials*)
__declspec(dllimport) ~ImportSpecials();
- // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportSpecials* @"\01??0ImportSpecials@@QAE@ABU0@@Z"(%struct.ImportSpecials* returned, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
- // M64-DAG: declare dllimport %struct.ImportSpecials* @"\01??0ImportSpecials@@QEAA@AEBU0@@Z"(%struct.ImportSpecials* returned, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
+ // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportSpecials* @"??0ImportSpecials@@QAE@ABU0@@Z"(%struct.ImportSpecials* returned, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport %struct.ImportSpecials* @"??0ImportSpecials@@QEAA@AEBU0@@Z"(%struct.ImportSpecials* returned, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN14ImportSpecialsC1ERKS_(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
// G64-DAG: declare dllimport void @_ZN14ImportSpecialsC1ERKS_(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
__declspec(dllimport) ImportSpecials(const ImportSpecials&);
- // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @"\01??4ImportSpecials@@QAEAAU0@ABU0@@Z"(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
- // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @"\01??4ImportSpecials@@QEAAAEAU0@AEBU0@@Z"(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
+ // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @"??4ImportSpecials@@QAEAAU0@ABU0@@Z"(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @"??4ImportSpecials@@QEAAAEAU0@AEBU0@@Z"(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
// G32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @_ZN14ImportSpecialsaSERKS_(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
// G64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @_ZN14ImportSpecialsaSERKS_(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
__declspec(dllimport) ImportSpecials& operator=(const ImportSpecials&);
- // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportSpecials* @"\01??0ImportSpecials@@QAE@$$QAU0@@Z"(%struct.ImportSpecials* returned, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
- // M64-DAG: declare dllimport %struct.ImportSpecials* @"\01??0ImportSpecials@@QEAA@$$QEAU0@@Z"(%struct.ImportSpecials* returned, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
+ // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportSpecials* @"??0ImportSpecials@@QAE@$$QAU0@@Z"(%struct.ImportSpecials* returned, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport %struct.ImportSpecials* @"??0ImportSpecials@@QEAA@$$QEAU0@@Z"(%struct.ImportSpecials* returned, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN14ImportSpecialsC1EOS_(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
// G64-DAG: declare dllimport void @_ZN14ImportSpecialsC1EOS_(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
__declspec(dllimport) ImportSpecials(ImportSpecials&&);
- // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @"\01??4ImportSpecials@@QAEAAU0@$$QAU0@@Z"(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
- // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @"\01??4ImportSpecials@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
+ // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @"??4ImportSpecials@@QAEAAU0@$$QAU0@@Z"(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @"??4ImportSpecials@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
// G32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @_ZN14ImportSpecialsaSEOS_(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
// G64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @_ZN14ImportSpecialsaSEOS_(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
__declspec(dllimport) ImportSpecials& operator=(ImportSpecials&&);
@@ -449,52 +449,52 @@ USESPECIALS(ImportSpecials)
// Export inline special member functions.
struct ImportInlineSpecials {
- // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QAE@XZ"(%struct.ImportInlineSpecials* returned)
- // M64-DAG: declare dllimport %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QEAA@XZ"(%struct.ImportInlineSpecials* returned)
- // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN20ImportInlineSpecialsC1Ev(%struct.ImportInlineSpecials* %this)
- // G64-DAG: define linkonce_odr void @_ZN20ImportInlineSpecialsC1Ev(%struct.ImportInlineSpecials* %this)
- // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QAE@XZ"(
- // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN20ImportInlineSpecialsC1Ev(
+ // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"??0ImportInlineSpecials@@QAE@XZ"(%struct.ImportInlineSpecials* returned)
+ // M64-DAG: declare dllimport %struct.ImportInlineSpecials* @"??0ImportInlineSpecials@@QEAA@XZ"(%struct.ImportInlineSpecials* returned)
+ // G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN20ImportInlineSpecialsC1Ev(%struct.ImportInlineSpecials* %this)
+ // G64-DAG: define linkonce_odr dso_local void @_ZN20ImportInlineSpecialsC1Ev(%struct.ImportInlineSpecials* %this)
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"??0ImportInlineSpecials@@QAE@XZ"(
+ // GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN20ImportInlineSpecialsC1Ev(
__declspec(dllimport) ImportInlineSpecials() {}
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01??1ImportInlineSpecials@@QAE@XZ"(%struct.ImportInlineSpecials*)
- // M64-DAG: declare dllimport void @"\01??1ImportInlineSpecials@@QEAA@XZ"(%struct.ImportInlineSpecials*)
- // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN20ImportInlineSpecialsD1Ev(%struct.ImportInlineSpecials* %this)
- // G64-DAG: define linkonce_odr void @_ZN20ImportInlineSpecialsD1Ev(%struct.ImportInlineSpecials* %this)
- // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01??1ImportInlineSpecials@@QAE@XZ"(
- // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN20ImportInlineSpecialsD1Ev(
+ // M32-DAG: declare dllimport x86_thiscallcc void @"??1ImportInlineSpecials@@QAE@XZ"(%struct.ImportInlineSpecials*)
+ // M64-DAG: declare dllimport void @"??1ImportInlineSpecials@@QEAA@XZ"(%struct.ImportInlineSpecials*)
+ // G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN20ImportInlineSpecialsD1Ev(%struct.ImportInlineSpecials* %this)
+ // G64-DAG: define linkonce_odr dso_local void @_ZN20ImportInlineSpecialsD1Ev(%struct.ImportInlineSpecials* %this)
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"??1ImportInlineSpecials@@QAE@XZ"(
+ // GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN20ImportInlineSpecialsD1Ev(
__declspec(dllimport) ~ImportInlineSpecials() {}
- // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QAE@ABU0@@Z"(%struct.ImportInlineSpecials* returned, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
- // M64-DAG: declare dllimport %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QEAA@AEBU0@@Z"(%struct.ImportInlineSpecials* returned, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
- // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN20ImportInlineSpecialsC1ERKS_(%struct.ImportInlineSpecials* %this, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
- // G64-DAG: define linkonce_odr void @_ZN20ImportInlineSpecialsC1ERKS_(%struct.ImportInlineSpecials* %this, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
- // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QAE@ABU0@@Z"(
- // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN20ImportInlineSpecialsC1ERKS_(
+ // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"??0ImportInlineSpecials@@QAE@ABU0@@Z"(%struct.ImportInlineSpecials* returned, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport %struct.ImportInlineSpecials* @"??0ImportInlineSpecials@@QEAA@AEBU0@@Z"(%struct.ImportInlineSpecials* returned, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN20ImportInlineSpecialsC1ERKS_(%struct.ImportInlineSpecials* %this, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // G64-DAG: define linkonce_odr dso_local void @_ZN20ImportInlineSpecialsC1ERKS_(%struct.ImportInlineSpecials* %this, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"??0ImportInlineSpecials@@QAE@ABU0@@Z"(
+ // GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN20ImportInlineSpecialsC1ERKS_(
__declspec(dllimport) inline ImportInlineSpecials(const ImportInlineSpecials&);
- // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QAEAAU0@ABU0@@Z"(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
- // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QEAAAEAU0@AEBU0@@Z"(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
- // G32-DAG: define linkonce_odr x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSERKS_(%struct.ImportInlineSpecials* %this, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
- // G64-DAG: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSERKS_(%struct.ImportInlineSpecials* %this, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
- // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QAEAAU0@ABU0@@Z"(
- // GO1-DAG: define linkonce_odr x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSERKS_(
+ // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"??4ImportInlineSpecials@@QAEAAU0@ABU0@@Z"(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"??4ImportInlineSpecials@@QEAAAEAU0@AEBU0@@Z"(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // G32-DAG: define linkonce_odr dso_local x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSERKS_(%struct.ImportInlineSpecials* %this, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // G64-DAG: define linkonce_odr dso_local dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSERKS_(%struct.ImportInlineSpecials* %this, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"??4ImportInlineSpecials@@QAEAAU0@ABU0@@Z"(
+ // GO1-DAG: define linkonce_odr dso_local x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSERKS_(
__declspec(dllimport) ImportInlineSpecials& operator=(const ImportInlineSpecials&);
- // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QAE@$$QAU0@@Z"(%struct.ImportInlineSpecials* returned, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
- // M64-DAG: declare dllimport %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QEAA@$$QEAU0@@Z"(%struct.ImportInlineSpecials* returned, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
- // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN20ImportInlineSpecialsC1EOS_(%struct.ImportInlineSpecials* %this, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
- // G64-DAG: define linkonce_odr void @_ZN20ImportInlineSpecialsC1EOS_(%struct.ImportInlineSpecials* %this, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
- // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QAE@$$QAU0@@Z"(
- // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN20ImportInlineSpecialsC1EOS_(
+ // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"??0ImportInlineSpecials@@QAE@$$QAU0@@Z"(%struct.ImportInlineSpecials* returned, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport %struct.ImportInlineSpecials* @"??0ImportInlineSpecials@@QEAA@$$QEAU0@@Z"(%struct.ImportInlineSpecials* returned, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN20ImportInlineSpecialsC1EOS_(%struct.ImportInlineSpecials* %this, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // G64-DAG: define linkonce_odr dso_local void @_ZN20ImportInlineSpecialsC1EOS_(%struct.ImportInlineSpecials* %this, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"??0ImportInlineSpecials@@QAE@$$QAU0@@Z"(
+ // GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN20ImportInlineSpecialsC1EOS_(
__declspec(dllimport) ImportInlineSpecials(ImportInlineSpecials&&) {}
- // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QAEAAU0@$$QAU0@@Z"(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
- // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
- // G32-DAG: define linkonce_odr x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSEOS_(%struct.ImportInlineSpecials* %this, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
- // G64-DAG: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSEOS_(%struct.ImportInlineSpecials* %this, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
- // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QAEAAU0@$$QAU0@@Z"(
- // GO1-DAG: define linkonce_odr x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSEOS_(
+ // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"??4ImportInlineSpecials@@QAEAAU0@$$QAU0@@Z"(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"??4ImportInlineSpecials@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // G32-DAG: define linkonce_odr dso_local x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSEOS_(%struct.ImportInlineSpecials* %this, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // G64-DAG: define linkonce_odr dso_local dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSEOS_(%struct.ImportInlineSpecials* %this, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"??4ImportInlineSpecials@@QAEAAU0@$$QAU0@@Z"(
+ // GO1-DAG: define linkonce_odr dso_local x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSEOS_(
__declspec(dllimport) ImportInlineSpecials& operator=(ImportInlineSpecials&&) { return *this; }
};
ImportInlineSpecials::ImportInlineSpecials(const ImportInlineSpecials&) {}
@@ -504,52 +504,52 @@ USESPECIALS(ImportInlineSpecials)
// Import defaulted member functions.
struct ImportDefaulted {
- // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QAE@XZ"(%struct.ImportDefaulted* returned)
- // M64-DAG: declare dllimport %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QEAA@XZ"(%struct.ImportDefaulted* returned)
- // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN15ImportDefaultedC1Ev(%struct.ImportDefaulted* %this)
- // G64-DAG: define linkonce_odr void @_ZN15ImportDefaultedC1Ev(%struct.ImportDefaulted* %this)
- // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QAE@XZ"(%struct.ImportDefaulted* returned %this)
- // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN15ImportDefaultedC1Ev(%struct.ImportDefaulted* %this)
+ // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaulted* @"??0ImportDefaulted@@QAE@XZ"(%struct.ImportDefaulted* returned)
+ // M64-DAG: declare dllimport %struct.ImportDefaulted* @"??0ImportDefaulted@@QEAA@XZ"(%struct.ImportDefaulted* returned)
+ // G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN15ImportDefaultedC1Ev(%struct.ImportDefaulted* %this)
+ // G64-DAG: define linkonce_odr dso_local void @_ZN15ImportDefaultedC1Ev(%struct.ImportDefaulted* %this)
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportDefaulted* @"??0ImportDefaulted@@QAE@XZ"(%struct.ImportDefaulted* returned %this)
+ // GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN15ImportDefaultedC1Ev(%struct.ImportDefaulted* %this)
__declspec(dllimport) ImportDefaulted() = default;
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01??1ImportDefaulted@@QAE@XZ"(%struct.ImportDefaulted*)
- // M64-DAG: declare dllimport void @"\01??1ImportDefaulted@@QEAA@XZ"(%struct.ImportDefaulted*)
- // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN15ImportDefaultedD1Ev(%struct.ImportDefaulted* %this)
- // G64-DAG: define linkonce_odr void @_ZN15ImportDefaultedD1Ev(%struct.ImportDefaulted* %this)
- // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01??1ImportDefaulted@@QAE@XZ"(%struct.ImportDefaulted* %this)
- // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN15ImportDefaultedD1Ev(%struct.ImportDefaulted* %this)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"??1ImportDefaulted@@QAE@XZ"(%struct.ImportDefaulted*)
+ // M64-DAG: declare dllimport void @"??1ImportDefaulted@@QEAA@XZ"(%struct.ImportDefaulted*)
+ // G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN15ImportDefaultedD1Ev(%struct.ImportDefaulted* %this)
+ // G64-DAG: define linkonce_odr dso_local void @_ZN15ImportDefaultedD1Ev(%struct.ImportDefaulted* %this)
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"??1ImportDefaulted@@QAE@XZ"(%struct.ImportDefaulted* %this)
+ // GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN15ImportDefaultedD1Ev(%struct.ImportDefaulted* %this)
__declspec(dllimport) ~ImportDefaulted() = default;
- // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QAE@ABU0@@Z"(%struct.ImportDefaulted* returned, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
- // M64-DAG: declare dllimport %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QEAA@AEBU0@@Z"(%struct.ImportDefaulted* returned, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
- // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN15ImportDefaultedC1ERKS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
- // G64-DAG: define linkonce_odr void @_ZN15ImportDefaultedC1ERKS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
- // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QAE@ABU0@@Z"(%struct.ImportDefaulted* returned %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
- // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN15ImportDefaultedC1ERKS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaulted* @"??0ImportDefaulted@@QAE@ABU0@@Z"(%struct.ImportDefaulted* returned, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport %struct.ImportDefaulted* @"??0ImportDefaulted@@QEAA@AEBU0@@Z"(%struct.ImportDefaulted* returned, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN15ImportDefaultedC1ERKS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // G64-DAG: define linkonce_odr dso_local void @_ZN15ImportDefaultedC1ERKS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportDefaulted* @"??0ImportDefaulted@@QAE@ABU0@@Z"(%struct.ImportDefaulted* returned %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN15ImportDefaultedC1ERKS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
__declspec(dllimport) ImportDefaulted(const ImportDefaulted&) = default;
- // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QAEAAU0@ABU0@@Z"(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
- // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QEAAAEAU0@AEBU0@@Z"(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
- // G32-DAG: define linkonce_odr x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSERKS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
- // G64-DAG: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSERKS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
- // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QAEAAU0@ABU0@@Z"(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
- // GO1-DAG: define linkonce_odr x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSERKS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"??4ImportDefaulted@@QAEAAU0@ABU0@@Z"(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"??4ImportDefaulted@@QEAAAEAU0@AEBU0@@Z"(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // G32-DAG: define linkonce_odr dso_local x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSERKS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // G64-DAG: define linkonce_odr dso_local dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSERKS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"??4ImportDefaulted@@QAEAAU0@ABU0@@Z"(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // GO1-DAG: define linkonce_odr dso_local x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSERKS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
__declspec(dllimport) ImportDefaulted& operator=(const ImportDefaulted&) = default;
- // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QAE@$$QAU0@@Z"(%struct.ImportDefaulted* returned, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
- // M64-DAG: declare dllimport %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QEAA@$$QEAU0@@Z"(%struct.ImportDefaulted* returned, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
- // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN15ImportDefaultedC1EOS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
- // G64-DAG: define linkonce_odr void @_ZN15ImportDefaultedC1EOS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
- // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QAE@$$QAU0@@Z"(%struct.ImportDefaulted* returned %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
- // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN15ImportDefaultedC1EOS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaulted* @"??0ImportDefaulted@@QAE@$$QAU0@@Z"(%struct.ImportDefaulted* returned, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport %struct.ImportDefaulted* @"??0ImportDefaulted@@QEAA@$$QEAU0@@Z"(%struct.ImportDefaulted* returned, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN15ImportDefaultedC1EOS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // G64-DAG: define linkonce_odr dso_local void @_ZN15ImportDefaultedC1EOS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportDefaulted* @"??0ImportDefaulted@@QAE@$$QAU0@@Z"(%struct.ImportDefaulted* returned %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN15ImportDefaultedC1EOS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
__declspec(dllimport) ImportDefaulted(ImportDefaulted&&) = default;
- // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QAEAAU0@$$QAU0@@Z"(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
- // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
- // G32-DAG: define linkonce_odr x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSEOS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
- // G64-DAG: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSEOS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
- // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QAEAAU0@$$QAU0@@Z"(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
- // GO1-DAG: define linkonce_odr x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSEOS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"??4ImportDefaulted@@QAEAAU0@$$QAU0@@Z"(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"??4ImportDefaulted@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // G32-DAG: define linkonce_odr dso_local x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSEOS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // G64-DAG: define linkonce_odr dso_local dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSEOS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"??4ImportDefaulted@@QAEAAU0@$$QAU0@@Z"(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // GO1-DAG: define linkonce_odr dso_local x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSEOS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
__declspec(dllimport) ImportDefaulted& operator=(ImportDefaulted&&) = default;
ForceNonTrivial v; // ensure special members are non-trivial
@@ -571,42 +571,42 @@ struct ImportDefaultedDefs {
#ifdef MSABI
// For MinGW, the function will not be dllimport, and we cannot add the attribute now.
-// M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QAE@XZ"(%struct.ImportDefaultedDefs* returned)
-// M64-DAG: declare dllimport %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QEAA@XZ"(%struct.ImportDefaultedDefs* returned)
+// M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaultedDefs* @"??0ImportDefaultedDefs@@QAE@XZ"(%struct.ImportDefaultedDefs* returned)
+// M64-DAG: declare dllimport %struct.ImportDefaultedDefs* @"??0ImportDefaultedDefs@@QEAA@XZ"(%struct.ImportDefaultedDefs* returned)
__declspec(dllimport) ImportDefaultedDefs::ImportDefaultedDefs() = default;
#endif
#ifdef MSABI
// For MinGW, the function will not be dllimport, and we cannot add the attribute now.
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01??1ImportDefaultedDefs@@QAE@XZ"(%struct.ImportDefaultedDefs*)
-// M64-DAG: declare dllimport void @"\01??1ImportDefaultedDefs@@QEAA@XZ"(%struct.ImportDefaultedDefs*)
+// M32-DAG: declare dllimport x86_thiscallcc void @"??1ImportDefaultedDefs@@QAE@XZ"(%struct.ImportDefaultedDefs*)
+// M64-DAG: declare dllimport void @"??1ImportDefaultedDefs@@QEAA@XZ"(%struct.ImportDefaultedDefs*)
__declspec(dllimport) ImportDefaultedDefs::~ImportDefaultedDefs() = default;
#endif
-// M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QAE@ABU0@@Z"(%struct.ImportDefaultedDefs* returned, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// M64-DAG: declare dllimport %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QEAA@AEBU0@@Z"(%struct.ImportDefaultedDefs* returned, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN19ImportDefaultedDefsC1ERKS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// G64-DAG: define linkonce_odr void @_ZN19ImportDefaultedDefsC1ERKS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaultedDefs* @"??0ImportDefaultedDefs@@QAE@ABU0@@Z"(%struct.ImportDefaultedDefs* returned, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M64-DAG: declare dllimport %struct.ImportDefaultedDefs* @"??0ImportDefaultedDefs@@QEAA@AEBU0@@Z"(%struct.ImportDefaultedDefs* returned, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN19ImportDefaultedDefsC1ERKS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G64-DAG: define linkonce_odr dso_local void @_ZN19ImportDefaultedDefsC1ERKS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
inline ImportDefaultedDefs::ImportDefaultedDefs(const ImportDefaultedDefs&) = default;
-// M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"\01??4ImportDefaultedDefs@@QAEAAU0@ABU0@@Z"(%struct.ImportDefaultedDefs*, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"\01??4ImportDefaultedDefs@@QEAAAEAU0@AEBU0@@Z"(%struct.ImportDefaultedDefs*, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// G32-DAG: define linkonce_odr x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @_ZN19ImportDefaultedDefsaSERKS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// G64-DAG: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @_ZN19ImportDefaultedDefsaSERKS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"??4ImportDefaultedDefs@@QAEAAU0@ABU0@@Z"(%struct.ImportDefaultedDefs*, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"??4ImportDefaultedDefs@@QEAAAEAU0@AEBU0@@Z"(%struct.ImportDefaultedDefs*, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G32-DAG: define linkonce_odr dso_local x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @_ZN19ImportDefaultedDefsaSERKS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G64-DAG: define linkonce_odr dso_local dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @_ZN19ImportDefaultedDefsaSERKS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
inline ImportDefaultedDefs& ImportDefaultedDefs::operator=(const ImportDefaultedDefs&) = default;
-// M32-DAG: define dllexport x86_thiscallcc %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QAE@$$QAU0@@Z"(%struct.ImportDefaultedDefs* returned %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// M64-DAG: define dllexport %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QEAA@$$QEAU0@@Z"(%struct.ImportDefaultedDefs* returned %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// G32-DAG: define x86_thiscallcc void @_ZN19ImportDefaultedDefsC1EOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// G64-DAG: define void @_ZN19ImportDefaultedDefsC1EOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// G32-DAG: define x86_thiscallcc void @_ZN19ImportDefaultedDefsC2EOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// G64-DAG: define void @_ZN19ImportDefaultedDefsC2EOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M32-DAG: define dso_local dllexport x86_thiscallcc %struct.ImportDefaultedDefs* @"??0ImportDefaultedDefs@@QAE@$$QAU0@@Z"(%struct.ImportDefaultedDefs* returned %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M64-DAG: define dso_local dllexport %struct.ImportDefaultedDefs* @"??0ImportDefaultedDefs@@QEAA@$$QEAU0@@Z"(%struct.ImportDefaultedDefs* returned %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G32-DAG: define dso_local x86_thiscallcc void @_ZN19ImportDefaultedDefsC1EOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G64-DAG: define dso_local void @_ZN19ImportDefaultedDefsC1EOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G32-DAG: define dso_local x86_thiscallcc void @_ZN19ImportDefaultedDefsC2EOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G64-DAG: define dso_local void @_ZN19ImportDefaultedDefsC2EOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
ImportDefaultedDefs::ImportDefaultedDefs(ImportDefaultedDefs&&) = default; // dllimport ignored
-// M32-DAG: define dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"\01??4ImportDefaultedDefs@@QAEAAU0@$$QAU0@@Z"(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// M64-DAG: define dllexport dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"\01??4ImportDefaultedDefs@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// G32-DAG: define x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @_ZN19ImportDefaultedDefsaSEOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// G64-DAG: define dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @_ZN19ImportDefaultedDefsaSEOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M32-DAG: define dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"??4ImportDefaultedDefs@@QAEAAU0@$$QAU0@@Z"(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M64-DAG: define dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"??4ImportDefaultedDefs@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G32-DAG: define dso_local x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @_ZN19ImportDefaultedDefsaSEOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G64-DAG: define dso_local dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @_ZN19ImportDefaultedDefsaSEOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
ImportDefaultedDefs& ImportDefaultedDefs::operator=(ImportDefaultedDefs&&) = default; // dllimport ignored
USESPECIALS(ImportDefaultedDefs)
@@ -620,26 +620,26 @@ struct ImportAlloc {
__declspec(dllimport) void operator delete[](void*);
};
-// M32-DAG: declare dllimport i8* @"\01??2ImportAlloc@@SAPAXI@Z"(i32)
-// M64-DAG: declare dllimport i8* @"\01??2ImportAlloc@@SAPEAX_K@Z"(i64)
+// M32-DAG: declare dllimport i8* @"??2ImportAlloc@@SAPAXI@Z"(i32)
+// M64-DAG: declare dllimport i8* @"??2ImportAlloc@@SAPEAX_K@Z"(i64)
// G32-DAG: declare dllimport i8* @_ZN11ImportAllocnwEj(i32)
// G64-DAG: declare dllimport i8* @_ZN11ImportAllocnwEy(i64)
void UNIQ(use)() { new ImportAlloc(); }
-// M32-DAG: declare dllimport i8* @"\01??_UImportAlloc@@SAPAXI@Z"(i32)
-// M64-DAG: declare dllimport i8* @"\01??_UImportAlloc@@SAPEAX_K@Z"(i64)
+// M32-DAG: declare dllimport i8* @"??_UImportAlloc@@SAPAXI@Z"(i32)
+// M64-DAG: declare dllimport i8* @"??_UImportAlloc@@SAPEAX_K@Z"(i64)
// G32-DAG: declare dllimport i8* @_ZN11ImportAllocnaEj(i32)
// G64-DAG: declare dllimport i8* @_ZN11ImportAllocnaEy(i64)
void UNIQ(use)() { new ImportAlloc[1]; }
-// M32-DAG: declare dllimport void @"\01??3ImportAlloc@@SAXPAX@Z"(i8*)
-// M64-DAG: declare dllimport void @"\01??3ImportAlloc@@SAXPEAX@Z"(i8*)
+// M32-DAG: declare dllimport void @"??3ImportAlloc@@SAXPAX@Z"(i8*)
+// M64-DAG: declare dllimport void @"??3ImportAlloc@@SAXPEAX@Z"(i8*)
// G32-DAG: declare dllimport void @_ZN11ImportAllocdlEPv(i8*)
// G64-DAG: declare dllimport void @_ZN11ImportAllocdlEPv(i8*)
void UNIQ(use)(ImportAlloc* ptr) { delete ptr; }
-// M32-DAG: declare dllimport void @"\01??_VImportAlloc@@SAXPAX@Z"(i8*)
-// M64-DAG: declare dllimport void @"\01??_VImportAlloc@@SAXPEAX@Z"(i8*)
+// M32-DAG: declare dllimport void @"??_VImportAlloc@@SAXPAX@Z"(i8*)
+// M64-DAG: declare dllimport void @"??_VImportAlloc@@SAXPEAX@Z"(i8*)
// G32-DAG: declare dllimport void @_ZN11ImportAllocdaEPv(i8*)
// G64-DAG: declare dllimport void @_ZN11ImportAllocdaEPv(i8*)
void UNIQ(use)(ImportAlloc* ptr) { delete[] ptr; }
@@ -657,168 +657,168 @@ struct MemFunTmpl {
};
// Import implicit instantiation of an imported member function template.
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$importedNormal@UImplicitInst_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
-// M64-DAG: declare dllimport void @"\01??$importedNormal@UImplicitInst_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
-// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI21ImplicitInst_ImportedEEvv(%struct.MemFunTmpl* %this)
-// G64-DAG: define linkonce_odr void @_ZN10MemFunTmpl14importedNormalI21ImplicitInst_ImportedEEvv(%struct.MemFunTmpl* %this)
+// M32-DAG: declare dllimport x86_thiscallcc void @"??$importedNormal@UImplicitInst_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
+// M64-DAG: declare dllimport void @"??$importedNormal@UImplicitInst_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
+// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI21ImplicitInst_ImportedEEvv(%struct.MemFunTmpl* %this)
+// G64-DAG: define linkonce_odr dso_local void @_ZN10MemFunTmpl14importedNormalI21ImplicitInst_ImportedEEvv(%struct.MemFunTmpl* %this)
USEMF(MemFunTmpl, importedNormal<ImplicitInst_Imported>)
-// MSC-DAG: declare dllimport void @"\01??$importedStatic@UImplicitInst_Imported@@@MemFunTmpl@@SAXXZ"()
-// GNU-DAG: define linkonce_odr void @_ZN10MemFunTmpl14importedStaticI21ImplicitInst_ImportedEEvv()
+// MSC-DAG: declare dllimport void @"??$importedStatic@UImplicitInst_Imported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: define linkonce_odr dso_local void @_ZN10MemFunTmpl14importedStaticI21ImplicitInst_ImportedEEvv()
USE(MemFunTmpl::importedStatic<ImplicitInst_Imported>)
// Import explicit instantiation declaration of an imported member function
// template.
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$importedNormal@UExplicitDecl_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
-// M64-DAG: declare dllimport void @"\01??$importedNormal@UExplicitDecl_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
-// G32-DAG: declare x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI21ExplicitDecl_ImportedEEvv(%struct.MemFunTmpl*)
-// G64-DAG: declare void @_ZN10MemFunTmpl14importedNormalI21ExplicitDecl_ImportedEEvv(%struct.MemFunTmpl*)
+// M32-DAG: declare dllimport x86_thiscallcc void @"??$importedNormal@UExplicitDecl_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
+// M64-DAG: declare dllimport void @"??$importedNormal@UExplicitDecl_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
+// G32-DAG: declare dso_local x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI21ExplicitDecl_ImportedEEvv(%struct.MemFunTmpl*)
+// G64-DAG: declare dso_local void @_ZN10MemFunTmpl14importedNormalI21ExplicitDecl_ImportedEEvv(%struct.MemFunTmpl*)
extern template void MemFunTmpl::importedNormal<ExplicitDecl_Imported>();
USEMF(MemFunTmpl, importedNormal<ExplicitDecl_Imported>)
-// MSC-DAG: declare dllimport void @"\01??$importedStatic@UExplicitDecl_Imported@@@MemFunTmpl@@SAXXZ"()
-// GNU-DAG: declare void @_ZN10MemFunTmpl14importedStaticI21ExplicitDecl_ImportedEEvv()
+// MSC-DAG: declare dllimport void @"??$importedStatic@UExplicitDecl_Imported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: declare dso_local void @_ZN10MemFunTmpl14importedStaticI21ExplicitDecl_ImportedEEvv()
extern template void MemFunTmpl::importedStatic<ExplicitDecl_Imported>();
USE(MemFunTmpl::importedStatic<ExplicitDecl_Imported>)
// Import explicit instantiation definition of an imported member function
// template.
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$importedNormal@UExplicitInst_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
-// M64-DAG: declare dllimport void @"\01??$importedNormal@UExplicitInst_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
-// G32-DAG: define weak_odr x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI21ExplicitInst_ImportedEEvv(%struct.MemFunTmpl* %this)
-// G64-DAG: define weak_odr void @_ZN10MemFunTmpl14importedNormalI21ExplicitInst_ImportedEEvv(%struct.MemFunTmpl* %this)
+// M32-DAG: declare dllimport x86_thiscallcc void @"??$importedNormal@UExplicitInst_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
+// M64-DAG: declare dllimport void @"??$importedNormal@UExplicitInst_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
+// G32-DAG: define weak_odr dso_local x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI21ExplicitInst_ImportedEEvv(%struct.MemFunTmpl* %this)
+// G64-DAG: define weak_odr dso_local void @_ZN10MemFunTmpl14importedNormalI21ExplicitInst_ImportedEEvv(%struct.MemFunTmpl* %this)
template void MemFunTmpl::importedNormal<ExplicitInst_Imported>();
USEMF(MemFunTmpl, importedNormal<ExplicitInst_Imported>)
-// MSC-DAG: declare dllimport void @"\01??$importedStatic@UExplicitInst_Imported@@@MemFunTmpl@@SAXXZ"()
-// GNU-DAG: define weak_odr void @_ZN10MemFunTmpl14importedStaticI21ExplicitInst_ImportedEEvv()
+// MSC-DAG: declare dllimport void @"??$importedStatic@UExplicitInst_Imported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: define weak_odr dso_local void @_ZN10MemFunTmpl14importedStaticI21ExplicitInst_ImportedEEvv()
template void MemFunTmpl::importedStatic<ExplicitInst_Imported>();
USE(MemFunTmpl::importedStatic<ExplicitInst_Imported>)
// Import specialization of an imported member function template.
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$importedNormal@UExplicitSpec_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
-// M64-DAG: declare dllimport void @"\01??$importedNormal@UExplicitSpec_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
+// M32-DAG: declare dllimport x86_thiscallcc void @"??$importedNormal@UExplicitSpec_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
+// M64-DAG: declare dllimport void @"??$importedNormal@UExplicitSpec_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI21ExplicitSpec_ImportedEEvv(%struct.MemFunTmpl*)
// G64-DAG: declare dllimport void @_ZN10MemFunTmpl14importedNormalI21ExplicitSpec_ImportedEEvv(%struct.MemFunTmpl*)
template<> __declspec(dllimport) void MemFunTmpl::importedNormal<ExplicitSpec_Imported>();
USEMF(MemFunTmpl, importedNormal<ExplicitSpec_Imported>)
-// M32-DAG-FIXME: declare dllimport x86_thiscallcc void @"\01??$importedNormal@UExplicitSpec_Def_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
-// M64-DAG-FIXME: declare dllimport void @"\01??$importedNormal@UExplicitSpec_Def_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
+// M32-DAG-FIXME: declare dllimport x86_thiscallcc void @"??$importedNormal@UExplicitSpec_Def_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
+// M64-DAG-FIXME: declare dllimport void @"??$importedNormal@UExplicitSpec_Def_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
#ifdef MSABI
//template<> __declspec(dllimport) void MemFunTmpl::importedNormal<ExplicitSpec_Def_Imported>() {}
//USEMF(MemFunTmpl, importedNormal<ExplicitSpec_Def_Imported>)
#endif
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$importedNormal@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
-// M64-DAG: declare dllimport void @"\01??$importedNormal@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
-// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI31ExplicitSpec_InlineDef_ImportedEEvv(%struct.MemFunTmpl* %this)
-// G64-DAG: define linkonce_odr void @_ZN10MemFunTmpl14importedNormalI31ExplicitSpec_InlineDef_ImportedEEvv(%struct.MemFunTmpl* %this)
+// M32-DAG: declare dllimport x86_thiscallcc void @"??$importedNormal@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
+// M64-DAG: declare dllimport void @"??$importedNormal@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
+// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI31ExplicitSpec_InlineDef_ImportedEEvv(%struct.MemFunTmpl* %this)
+// G64-DAG: define linkonce_odr dso_local void @_ZN10MemFunTmpl14importedNormalI31ExplicitSpec_InlineDef_ImportedEEvv(%struct.MemFunTmpl* %this)
template<> __declspec(dllimport) inline void MemFunTmpl::importedNormal<ExplicitSpec_InlineDef_Imported>() {}
USEMF(MemFunTmpl, importedNormal<ExplicitSpec_InlineDef_Imported>)
-// MSC-DAG: declare dllimport void @"\01??$importedStatic@UExplicitSpec_Imported@@@MemFunTmpl@@SAXXZ"()
+// MSC-DAG: declare dllimport void @"??$importedStatic@UExplicitSpec_Imported@@@MemFunTmpl@@SAXXZ"()
// GNU-DAG: declare dllimport void @_ZN10MemFunTmpl14importedStaticI21ExplicitSpec_ImportedEEvv()
template<> __declspec(dllimport) void MemFunTmpl::importedStatic<ExplicitSpec_Imported>();
USE(MemFunTmpl::importedStatic<ExplicitSpec_Imported>)
-// MSC-DAG-FIXME: declare dllimport void @"\01??$importedStatic@UExplicitSpec_Def_Imported@@@MemFunTmpl@@SAXXZ"()
+// MSC-DAG-FIXME: declare dllimport void @"??$importedStatic@UExplicitSpec_Def_Imported@@@MemFunTmpl@@SAXXZ"()
#ifdef MSABI
//template<> __declspec(dllimport) void MemFunTmpl::importedStatic<ExplicitSpec_Def_Imported>() {}
//USE(MemFunTmpl::importedStatic<ExplicitSpec_Def_Imported>)
#endif
-// MSC-DAG: declare dllimport void @"\01??$importedStatic@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@SAXXZ"()
-// GNU-DAG: define linkonce_odr void @_ZN10MemFunTmpl14importedStaticI31ExplicitSpec_InlineDef_ImportedEEvv()
+// MSC-DAG: declare dllimport void @"??$importedStatic@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: define linkonce_odr dso_local void @_ZN10MemFunTmpl14importedStaticI31ExplicitSpec_InlineDef_ImportedEEvv()
template<> __declspec(dllimport) inline void MemFunTmpl::importedStatic<ExplicitSpec_InlineDef_Imported>() {}
USE(MemFunTmpl::importedStatic<ExplicitSpec_InlineDef_Imported>)
// Not importing specialization of an imported member function template without
// explicit dllimport.
-// M32-DAG: define x86_thiscallcc void @"\01??$importedNormal@UExplicitSpec_NotImported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
-// M64-DAG: define void @"\01??$importedNormal@UExplicitSpec_NotImported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
-// G32-DAG: define x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI24ExplicitSpec_NotImportedEEvv(%struct.MemFunTmpl* %this)
-// G64-DAG: define void @_ZN10MemFunTmpl14importedNormalI24ExplicitSpec_NotImportedEEvv(%struct.MemFunTmpl* %this)
+// M32-DAG: define dso_local x86_thiscallcc void @"??$importedNormal@UExplicitSpec_NotImported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
+// M64-DAG: define dso_local void @"??$importedNormal@UExplicitSpec_NotImported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
+// G32-DAG: define dso_local x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI24ExplicitSpec_NotImportedEEvv(%struct.MemFunTmpl* %this)
+// G64-DAG: define dso_local void @_ZN10MemFunTmpl14importedNormalI24ExplicitSpec_NotImportedEEvv(%struct.MemFunTmpl* %this)
template<> void MemFunTmpl::importedNormal<ExplicitSpec_NotImported>() {}
USEMF(MemFunTmpl, importedNormal<ExplicitSpec_NotImported>)
-// MSC-DAG: define void @"\01??$importedStatic@UExplicitSpec_NotImported@@@MemFunTmpl@@SAXXZ"()
-// GNU-DAG: define void @_ZN10MemFunTmpl14importedStaticI24ExplicitSpec_NotImportedEEvv()
+// MSC-DAG: define dso_local void @"??$importedStatic@UExplicitSpec_NotImported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: define dso_local void @_ZN10MemFunTmpl14importedStaticI24ExplicitSpec_NotImportedEEvv()
template<> void MemFunTmpl::importedStatic<ExplicitSpec_NotImported>() {}
USE(MemFunTmpl::importedStatic<ExplicitSpec_NotImported>)
// Import explicit instantiation declaration of a non-imported member function
// template.
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$normalDef@UExplicitDecl_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
-// M64-DAG: declare dllimport void @"\01??$normalDef@UExplicitDecl_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
-// G32-DAG: declare x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI21ExplicitDecl_ImportedEEvv(%struct.MemFunTmpl*)
-// G64-DAG: declare void @_ZN10MemFunTmpl9normalDefI21ExplicitDecl_ImportedEEvv(%struct.MemFunTmpl*)
+// M32-DAG: declare dllimport x86_thiscallcc void @"??$normalDef@UExplicitDecl_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
+// M64-DAG: declare dllimport void @"??$normalDef@UExplicitDecl_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
+// G32-DAG: declare dso_local x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI21ExplicitDecl_ImportedEEvv(%struct.MemFunTmpl*)
+// G64-DAG: declare dso_local void @_ZN10MemFunTmpl9normalDefI21ExplicitDecl_ImportedEEvv(%struct.MemFunTmpl*)
extern template __declspec(dllimport) void MemFunTmpl::normalDef<ExplicitDecl_Imported>();
USEMF(MemFunTmpl, normalDef<ExplicitDecl_Imported>)
-// MSC-DAG: declare dllimport void @"\01??$staticDef@UExplicitDecl_Imported@@@MemFunTmpl@@SAXXZ"()
-// GNU-DAG: declare void @_ZN10MemFunTmpl9staticDefI21ExplicitDecl_ImportedEEvv()
+// MSC-DAG: declare dllimport void @"??$staticDef@UExplicitDecl_Imported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: declare dso_local void @_ZN10MemFunTmpl9staticDefI21ExplicitDecl_ImportedEEvv()
extern template __declspec(dllimport) void MemFunTmpl::staticDef<ExplicitDecl_Imported>();
USE(MemFunTmpl::staticDef<ExplicitDecl_Imported>)
// Import explicit instantiation definition of a non-imported member function
// template.
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$normalDef@UExplicitInst_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
-// M64-DAG: declare dllimport void @"\01??$normalDef@UExplicitInst_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
-// G32-DAG: define weak_odr x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI21ExplicitInst_ImportedEEvv(%struct.MemFunTmpl* %this)
-// G64-DAG: define weak_odr void @_ZN10MemFunTmpl9normalDefI21ExplicitInst_ImportedEEvv(%struct.MemFunTmpl* %this)
+// M32-DAG: declare dllimport x86_thiscallcc void @"??$normalDef@UExplicitInst_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
+// M64-DAG: declare dllimport void @"??$normalDef@UExplicitInst_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
+// G32-DAG: define weak_odr dso_local x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI21ExplicitInst_ImportedEEvv(%struct.MemFunTmpl* %this)
+// G64-DAG: define weak_odr dso_local void @_ZN10MemFunTmpl9normalDefI21ExplicitInst_ImportedEEvv(%struct.MemFunTmpl* %this)
template __declspec(dllimport) void MemFunTmpl::normalDef<ExplicitInst_Imported>();
USEMF(MemFunTmpl, normalDef<ExplicitInst_Imported>)
-// MSC-DAG: declare dllimport void @"\01??$staticDef@UExplicitInst_Imported@@@MemFunTmpl@@SAXXZ"()
-// GNU-DAG: define weak_odr void @_ZN10MemFunTmpl9staticDefI21ExplicitInst_ImportedEEvv()
+// MSC-DAG: declare dllimport void @"??$staticDef@UExplicitInst_Imported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: define weak_odr dso_local void @_ZN10MemFunTmpl9staticDefI21ExplicitInst_ImportedEEvv()
template __declspec(dllimport) void MemFunTmpl::staticDef<ExplicitInst_Imported>();
USE(MemFunTmpl::staticDef<ExplicitInst_Imported>)
// Import specialization of a non-imported member function template.
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$normalDef@UExplicitSpec_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
-// M64-DAG: declare dllimport void @"\01??$normalDef@UExplicitSpec_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
+// M32-DAG: declare dllimport x86_thiscallcc void @"??$normalDef@UExplicitSpec_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
+// M64-DAG: declare dllimport void @"??$normalDef@UExplicitSpec_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI21ExplicitSpec_ImportedEEvv(%struct.MemFunTmpl*)
// G64-DAG: declare dllimport void @_ZN10MemFunTmpl9normalDefI21ExplicitSpec_ImportedEEvv(%struct.MemFunTmpl*)
template<> __declspec(dllimport) void MemFunTmpl::normalDef<ExplicitSpec_Imported>();
USEMF(MemFunTmpl, normalDef<ExplicitSpec_Imported>)
-// M32-DAG-FIXME: declare dllimport x86_thiscallcc void @"\01??$normalDef@UExplicitSpec_Def_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
-// M64-DAG-FIXME: declare dllimport void @"\01??$normalDef@UExplicitSpec_Def_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
+// M32-DAG-FIXME: declare dllimport x86_thiscallcc void @"??$normalDef@UExplicitSpec_Def_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
+// M64-DAG-FIXME: declare dllimport void @"??$normalDef@UExplicitSpec_Def_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
#ifdef MSABI
//template<> __declspec(dllimport) void MemFunTmpl::normalDef<ExplicitSpec_Def_Imported>() {}
//USEMF(MemFunTmpl, normalDef<ExplicitSpec_Def_Imported>)
#endif
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$normalDef@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
-// M64-DAG: declare dllimport void @"\01??$normalDef@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
-// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI31ExplicitSpec_InlineDef_ImportedEEvv(%struct.MemFunTmpl* %this)
-// G64-DAG: define linkonce_odr void @_ZN10MemFunTmpl9normalDefI31ExplicitSpec_InlineDef_ImportedEEvv(%struct.MemFunTmpl* %this)
+// M32-DAG: declare dllimport x86_thiscallcc void @"??$normalDef@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
+// M64-DAG: declare dllimport void @"??$normalDef@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
+// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI31ExplicitSpec_InlineDef_ImportedEEvv(%struct.MemFunTmpl* %this)
+// G64-DAG: define linkonce_odr dso_local void @_ZN10MemFunTmpl9normalDefI31ExplicitSpec_InlineDef_ImportedEEvv(%struct.MemFunTmpl* %this)
template<> __declspec(dllimport) inline void MemFunTmpl::normalDef<ExplicitSpec_InlineDef_Imported>() {}
USEMF(MemFunTmpl, normalDef<ExplicitSpec_InlineDef_Imported>)
-// MSC-DAG: declare dllimport void @"\01??$staticDef@UExplicitSpec_Imported@@@MemFunTmpl@@SAXXZ"()
+// MSC-DAG: declare dllimport void @"??$staticDef@UExplicitSpec_Imported@@@MemFunTmpl@@SAXXZ"()
// GNU-DAG: declare dllimport void @_ZN10MemFunTmpl9staticDefI21ExplicitSpec_ImportedEEvv()
template<> __declspec(dllimport) void MemFunTmpl::staticDef<ExplicitSpec_Imported>();
USE(MemFunTmpl::staticDef<ExplicitSpec_Imported>)
-// MSC-DAG-FIXME: declare dllimport void @"\01??$staticDef@UExplicitSpec_Def_Imported@@@MemFunTmpl@@SAXXZ"()
+// MSC-DAG-FIXME: declare dllimport void @"??$staticDef@UExplicitSpec_Def_Imported@@@MemFunTmpl@@SAXXZ"()
#ifdef MSABI
//template<> __declspec(dllimport) void MemFunTmpl::staticDef<ExplicitSpec_Def_Imported>() {}
//USE(MemFunTmpl::staticDef<ExplicitSpec_Def_Imported>)
#endif
-// MSC-DAG: declare dllimport void @"\01??$staticDef@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@SAXXZ"()
-// GNU-DAG: define linkonce_odr void @_ZN10MemFunTmpl9staticDefI31ExplicitSpec_InlineDef_ImportedEEvv()
+// MSC-DAG: declare dllimport void @"??$staticDef@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: define linkonce_odr dso_local void @_ZN10MemFunTmpl9staticDefI31ExplicitSpec_InlineDef_ImportedEEvv()
template<> __declspec(dllimport) inline void MemFunTmpl::staticDef<ExplicitSpec_InlineDef_Imported>() {}
USE(MemFunTmpl::staticDef<ExplicitSpec_InlineDef_Imported>)
@@ -830,13 +830,13 @@ struct MemVarTmpl {
};
// Import implicit instantiation of an imported member variable template.
-// MSC-DAG: @"\01??$ImportedStaticVar@UImplicitInst_Imported@@@MemVarTmpl@@2HB" = available_externally dllimport constant i32 1, align 4
+// MSC-DAG: @"??$ImportedStaticVar@UImplicitInst_Imported@@@MemVarTmpl@@2HB" = available_externally dllimport constant i32 1, align 4
// GNU-DAG: @_ZN10MemVarTmpl17ImportedStaticVarI21ImplicitInst_ImportedEE = external dllimport constant i32
USEMV(MemVarTmpl, ImportedStaticVar<ImplicitInst_Imported>)
// Import explicit instantiation declaration of an imported member variable
// template.
-// MSC-DAG: @"\01??$ImportedStaticVar@UExplicitDecl_Imported@@@MemVarTmpl@@2HB" = available_externally dllimport constant i32 1
+// MSC-DAG: @"??$ImportedStaticVar@UExplicitDecl_Imported@@@MemVarTmpl@@2HB" = available_externally dllimport constant i32 1
// GNU-DAG: @_ZN10MemVarTmpl17ImportedStaticVarI21ExplicitDecl_ImportedEE = external dllimport constant i32
extern template const int MemVarTmpl::ImportedStaticVar<ExplicitDecl_Imported>;
USEMV(MemVarTmpl, ImportedStaticVar<ExplicitDecl_Imported>)
@@ -846,22 +846,22 @@ USEMV(MemVarTmpl, ImportedStaticVar<ExplicitDecl_Imported>)
// in-class initializer does not count.
// Import specialization of an imported member variable template.
-// MSC-DAG: @"\01??$ImportedStaticVar@UExplicitSpec_Imported@@@MemVarTmpl@@2HB" = external dllimport constant i32
+// MSC-DAG: @"??$ImportedStaticVar@UExplicitSpec_Imported@@@MemVarTmpl@@2HB" = external dllimport constant i32
// GNU-DAG: @_ZN10MemVarTmpl17ImportedStaticVarI21ExplicitSpec_ImportedEE = external dllimport constant i32
template<> __declspec(dllimport) const int MemVarTmpl::ImportedStaticVar<ExplicitSpec_Imported>;
USEMV(MemVarTmpl, ImportedStaticVar<ExplicitSpec_Imported>)
// Not importing specialization of a member variable template without explicit
// dllimport.
-// MSC-DAG: @"\01??$ImportedStaticVar@UExplicitSpec_NotImported@@@MemVarTmpl@@2HB" = external constant i32
-// GNU-DAG: @_ZN10MemVarTmpl17ImportedStaticVarI24ExplicitSpec_NotImportedEE = external constant i32
+// MSC-DAG: @"??$ImportedStaticVar@UExplicitSpec_NotImported@@@MemVarTmpl@@2HB" = external dso_local constant i32
+// GNU-DAG: @_ZN10MemVarTmpl17ImportedStaticVarI24ExplicitSpec_NotImportedEE = external dso_local constant i32
template<> const int MemVarTmpl::ImportedStaticVar<ExplicitSpec_NotImported>;
USEMV(MemVarTmpl, ImportedStaticVar<ExplicitSpec_NotImported>)
// Import explicit instantiation declaration of a non-imported member variable
// template.
-// MSC-DAG: @"\01??$StaticVar@UExplicitDecl_Imported@@@MemVarTmpl@@2HB" = available_externally dllimport constant i32 1
+// MSC-DAG: @"??$StaticVar@UExplicitDecl_Imported@@@MemVarTmpl@@2HB" = available_externally dllimport constant i32 1
// GNU-DAG: @_ZN10MemVarTmpl9StaticVarI21ExplicitDecl_ImportedEE = external dllimport constant i32
extern template __declspec(dllimport) const int MemVarTmpl::StaticVar<ExplicitDecl_Imported>;
USEMV(MemVarTmpl, StaticVar<ExplicitDecl_Imported>)
@@ -871,7 +871,7 @@ USEMV(MemVarTmpl, StaticVar<ExplicitDecl_Imported>)
// in-class initializer does not count.
// Import specialization of a non-imported member variable template.
-// MSC-DAG: @"\01??$StaticVar@UExplicitSpec_Imported@@@MemVarTmpl@@2HB" = external dllimport constant i32
+// MSC-DAG: @"??$StaticVar@UExplicitSpec_Imported@@@MemVarTmpl@@2HB" = external dllimport constant i32
// GNU-DAG: @_ZN10MemVarTmpl9StaticVarI21ExplicitSpec_ImportedEE = external dllimport constant i32
template<> __declspec(dllimport) const int MemVarTmpl::StaticVar<ExplicitSpec_Imported>;
USEMV(MemVarTmpl, StaticVar<ExplicitSpec_Imported>)
diff --git a/test/CodeGenCXX/dllimport-memptr-global.cpp b/test/CodeGenCXX/dllimport-memptr-global.cpp
index e64537b8b9f9..91abfeb14838 100644
--- a/test/CodeGenCXX/dllimport-memptr-global.cpp
+++ b/test/CodeGenCXX/dllimport-memptr-global.cpp
@@ -40,19 +40,19 @@ auto mp_general_v = &General::virt;
// All of the non-virtual globals need dynamic initializers.
-// CHECK: @"\01?mp_single_nv@@3P8Single@@AEXXZQ1@" = global i8* null, align 4
-// CHECK: @"\01?mp_multi_nv@@3P8Multi@@AEXXZQ1@" = global { i8*, i32 } zeroinitializer, align 4
-// CHECK: @"\01?mp_virtual_nv@@3P8Virtual@@AEXXZQ1@" = global { i8*, i32, i32 } zeroinitializer, align 4
-// CHECK: @"\01?mp_general_nv@@3P8General@@AEXXZQ1@" = global { i8*, i32, i32, i32 } zeroinitializer, align 4
+// CHECK: @"?mp_single_nv@@3P8Single@@AEXXZQ1@" = dso_local global i8* null, align 4
+// CHECK: @"?mp_multi_nv@@3P8Multi@@AEXXZQ1@" = dso_local global { i8*, i32 } zeroinitializer, align 4
+// CHECK: @"?mp_virtual_nv@@3P8Virtual@@AEXXZQ1@" = dso_local global { i8*, i32, i32 } zeroinitializer, align 4
+// CHECK: @"?mp_general_nv@@3P8General@@AEXXZQ1@" = dso_local global { i8*, i32, i32, i32 } zeroinitializer, align 4
-// CHECK: @"\01?mp_single_v@@3P8Single@@AEXXZQ1@" = global i8* bitcast (void (%struct.Single*, ...)* @"\01??_9Single@@$BA@AE" to i8*), align 4
-// CHECK: @"\01?mp_multi_v@@3P8Multi@@AEXXZQ1@" = global { i8*, i32 } { i8* bitcast (void (%struct.Multi*, ...)* @"\01??_9Multi@@$BA@AE" to i8*), i32 0 }, align 4
-// CHECK: @"\01?mp_virtual_v@@3P8Virtual@@AEXXZQ1@" = global { i8*, i32, i32 } { i8* bitcast (void (%struct.Virtual*, ...)* @"\01??_9Virtual@@$BA@AE" to i8*), i32 0, i32 0 }, align 4
-// CHECK: @"\01?mp_general_v@@3P8General@@AEXXZQ1@" = global { i8*, i32, i32, i32 } { i8* bitcast (void (%struct.General*, ...)* @"\01??_9General@@$BA@AE" to i8*), i32 0, i32 0, i32 0 }, align 4
+// CHECK: @"?mp_single_v@@3P8Single@@AEXXZQ1@" = dso_local global i8* bitcast (void (%struct.Single*, ...)* @"??_9Single@@$BA@AE" to i8*), align 4
+// CHECK: @"?mp_multi_v@@3P8Multi@@AEXXZQ1@" = dso_local global { i8*, i32 } { i8* bitcast (void (%struct.Multi*, ...)* @"??_9Multi@@$BA@AE" to i8*), i32 0 }, align 4
+// CHECK: @"?mp_virtual_v@@3P8Virtual@@AEXXZQ1@" = dso_local global { i8*, i32, i32 } { i8* bitcast (void (%struct.Virtual*, ...)* @"??_9Virtual@@$BA@AE" to i8*), i32 0, i32 0 }, align 4
+// CHECK: @"?mp_general_v@@3P8General@@AEXXZQ1@" = dso_local global { i8*, i32, i32, i32 } { i8* bitcast (void (%struct.General*, ...)* @"??_9General@@$BA@AE" to i8*), i32 0, i32 0, i32 0 }, align 4
// CHECK: define internal void @_GLOBAL__sub_I{{.*}}() {{.*}} {
-// CHECK: call void @"\01??__Emp_single_nv@@YAXXZ"()
-// CHECK: call void @"\01??__Emp_multi_nv@@YAXXZ"()
-// CHECK: call void @"\01??__Emp_virtual_nv@@YAXXZ"()
-// CHECK: call void @"\01??__Emp_general_nv@@YAXXZ"()
+// CHECK: call void @"??__Emp_single_nv@@YAXXZ"()
+// CHECK: call void @"??__Emp_multi_nv@@YAXXZ"()
+// CHECK: call void @"??__Emp_virtual_nv@@YAXXZ"()
+// CHECK: call void @"??__Emp_general_nv@@YAXXZ"()
// CHECK: }
diff --git a/test/CodeGenCXX/dllimport-missing-key.cpp b/test/CodeGenCXX/dllimport-missing-key.cpp
new file mode 100644
index 000000000000..d8ef7aa7ea68
--- /dev/null
+++ b/test/CodeGenCXX/dllimport-missing-key.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -std=c++1y -O0 -o - %s -w | FileCheck --check-prefix=GNU %s
+
+class __declspec(dllimport) QObjectData {
+public:
+ virtual ~QObjectData() = 0;
+ void *ptr;
+
+ int method() const;
+};
+
+class LocalClass : public QObjectData {
+};
+
+void call() {
+ (new LocalClass())->method();
+}
+
+// GNU-DAG: @_ZTV11QObjectData = available_externally dllimport
+// GNU-DAG: @_ZTS11QObjectData = linkonce_odr
+// GNU-DAG: @_ZTI11QObjectData = linkonce_odr
diff --git a/test/CodeGenCXX/dllimport-rtti.cpp b/test/CodeGenCXX/dllimport-rtti.cpp
index 91e747ae1c15..d8e6f8e1b9ab 100644
--- a/test/CodeGenCXX/dllimport-rtti.cpp
+++ b/test/CodeGenCXX/dllimport-rtti.cpp
@@ -5,14 +5,14 @@ struct __declspec(dllimport) S {
virtual void f() {}
} s;
// MSVC: [[VF_S:.*]] = private unnamed_addr constant { [2 x i8*] }
-// MSVC-DAG: @"\01??_SS@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VF_S]], i32 0, i32 0, i32 1)
-// MSVC-DAG: @"\01??_R0?AUS@@@8" = linkonce_odr
-// MSVC-DAG: @"\01??_R1A@?0A@EA@S@@8" = linkonce_odr
-// MSVC-DAG: @"\01??_R2S@@8" = linkonce_odr
-// MSVC-DAG: @"\01??_R3S@@8" = linkonce_odr
+// MSVC-DAG: @"??_SS@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VF_S]], i32 0, i32 0, i32 1)
+// MSVC-DAG: @"??_R0?AUS@@@8" = linkonce_odr
+// MSVC-DAG: @"??_R1A@?0A@EA@S@@8" = linkonce_odr
+// MSVC-DAG: @"??_R2S@@8" = linkonce_odr
+// MSVC-DAG: @"??_R3S@@8" = linkonce_odr
// GNU-DAG: @_ZTV1S = available_externally dllimport
-// GNU-DAG: @_ZTI1S = external dllimport
+// GNU-DAG: @_ZTI1S = linkonce_odr dso_local
struct U : S {
} u;
@@ -21,13 +21,13 @@ struct __declspec(dllimport) V {
virtual void f();
} v;
// GNU-DAG: @_ZTV1V = available_externally dllimport
-// GNU-DAG: @_ZTS1V = linkonce_odr
-// GNU-DAG: @_ZTI1V = linkonce_odr
+// GNU-DAG: @_ZTS1V = linkonce_odr dso_local
+// GNU-DAG: @_ZTI1V = linkonce_odr dso_local
struct W {
__declspec(dllimport) virtual void f();
virtual void g();
} w;
-// GNU-DAG: @_ZTV1W = linkonce_odr
-// GNU-DAG: @_ZTS1W = linkonce_odr
-// GNU-DAG: @_ZTI1W = linkonce_odr
+// GNU-DAG: @_ZTV1W = linkonce_odr dso_local
+// GNU-DAG: @_ZTS1W = linkonce_odr dso_local
+// GNU-DAG: @_ZTI1W = linkonce_odr dso_local
diff --git a/test/CodeGenCXX/dllimport-template-sdm.cpp b/test/CodeGenCXX/dllimport-template-sdm.cpp
new file mode 100644
index 000000000000..33cbdf6b7e4b
--- /dev/null
+++ b/test/CodeGenCXX/dllimport-template-sdm.cpp
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -std=c++14 -fms-extensions -o - %s | FileCheck %s --check-prefix=IMPORT
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -std=c++14 -fms-extensions -o - %s -DTEST_EXPORT | FileCheck %s --check-prefix=EXPORT
+
+#ifndef TEST_EXPORT
+#define DLLATTR __declspec(dllimport)
+#else
+#define DLLATTR __declspec(dllexport)
+#endif
+
+// PR37232: When a dllimport attribute is propagated from a derived class to a
+// base class that happens to be a template specialization, it is only applied
+// to template *methods*, and not static data members. If a dllexport attribute
+// is propagated, it still applies to static data members.
+
+// IMPORT-DAG: @"?sdm@Exporter@@2HB" = available_externally dllimport constant i32 2, align 4
+// IMPORT-DAG: @"?csdm@?$A@H@@2HB" = linkonce_odr dso_local constant i32 2, comdat, align 4
+// IMPORT-DAG: @"?sdm@?$A@H@@2HA" = linkonce_odr dso_local global i32 1, comdat, align 4
+// IMPORT-DAG: @"?sdm@?$B@H@@2HB" = available_externally dllimport constant i32 2, align 4
+// IMPORT-DAG: @"?sdm@?$C@H@@2HB" = available_externally dllimport constant i32 2, align 4
+
+// EXPORT-DAG: @"?sdm@Exporter@@2HB" = weak_odr dso_local dllexport constant i32 2, comdat, align 4
+// EXPORT-DAG: @"?csdm@?$A@H@@2HB" = weak_odr dso_local dllexport constant i32 2, comdat, align 4
+// EXPORT-DAG: @"?sdm@?$A@H@@2HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
+// EXPORT-DAG: @"?sdm@?$B@H@@2HB" = weak_odr dso_local dllexport constant i32 2, comdat, align 4
+// EXPORT-DAG: @"?sdm@?$C@H@@2HB" = weak_odr dso_local dllexport constant i32 2, comdat, align 4
+
+
+template <typename T> struct A {
+ static constexpr int csdm = 2;
+ static int sdm;
+};
+template <typename T> int A<T>::sdm = 1;
+
+struct DLLATTR Exporter : A<int> {
+ static constexpr int sdm = 2;
+};
+
+template <typename T> struct DLLATTR B { static constexpr int sdm = 2; };
+
+template <typename T> struct DLLATTR C;
+template <typename T> struct C { static constexpr int sdm = 2; };
+
+void takeRef(const int &_Args) {}
+
+int main() {
+ takeRef(Exporter::sdm);
+ takeRef(A<int>::csdm);
+ takeRef(A<int>::sdm);
+ takeRef(B<int>::sdm);
+ takeRef(C<int>::sdm);
+
+ return 1;
+}
diff --git a/test/CodeGenCXX/dllimport.cpp b/test/CodeGenCXX/dllimport.cpp
index 14558aec39a4..74f58cc3b171 100644
--- a/test/CodeGenCXX/dllimport.cpp
+++ b/test/CodeGenCXX/dllimport.cpp
@@ -38,38 +38,38 @@ struct ExplicitSpec_NotImported {};
//===----------------------------------------------------------------------===//
// Import declaration.
-// MSC-DAG: @"\01?ExternGlobalDecl@@3HA" = external dllimport global i32
+// MSC-DAG: @"?ExternGlobalDecl@@3HA" = external dllimport global i32
// GNU-DAG: @ExternGlobalDecl = external dllimport global i32
__declspec(dllimport) extern int ExternGlobalDecl;
USEVAR(ExternGlobalDecl)
// dllimport implies a declaration.
-// MSC-DAG: @"\01?GlobalDecl@@3HA" = external dllimport global i32
+// MSC-DAG: @"?GlobalDecl@@3HA" = external dllimport global i32
// GNU-DAG: @GlobalDecl = external dllimport global i32
__declspec(dllimport) int GlobalDecl;
USEVAR(GlobalDecl)
// Redeclarations
-// MSC-DAG: @"\01?GlobalRedecl1@@3HA" = external dllimport global i32
+// MSC-DAG: @"?GlobalRedecl1@@3HA" = external dllimport global i32
// GNU-DAG: @GlobalRedecl1 = external dllimport global i32
__declspec(dllimport) extern int GlobalRedecl1;
__declspec(dllimport) extern int GlobalRedecl1;
USEVAR(GlobalRedecl1)
-// MSC-DAG: @"\01?GlobalRedecl2a@@3HA" = external dllimport global i32
+// MSC-DAG: @"?GlobalRedecl2a@@3HA" = external dllimport global i32
// GNU-DAG: @GlobalRedecl2a = external dllimport global i32
__declspec(dllimport) int GlobalRedecl2a;
__declspec(dllimport) int GlobalRedecl2a;
USEVAR(GlobalRedecl2a)
-// M32-DAG: @"\01?GlobalRedecl2b@@3PAHA" = external dllimport global i32*
-// M64-DAG: @"\01?GlobalRedecl2b@@3PEAHEA" = external dllimport global i32*
+// M32-DAG: @"?GlobalRedecl2b@@3PAHA" = external dllimport global i32*
+// M64-DAG: @"?GlobalRedecl2b@@3PEAHEA" = external dllimport global i32*
// GNU-DAG: @GlobalRedecl2b = external dllimport global i32*
int *__attribute__((dllimport)) GlobalRedecl2b;
int *__attribute__((dllimport)) GlobalRedecl2b;
USEVARTYPE(int*, GlobalRedecl2b)
-// MSC-DAG: @"\01?GlobalRedecl2c@@3HA" = external dllimport global i32
+// MSC-DAG: @"?GlobalRedecl2c@@3HA" = external dllimport global i32
// GNU-DAG: @GlobalRedecl2c = external dllimport global i32
int GlobalRedecl2c __attribute__((dllimport));
int GlobalRedecl2c __attribute__((dllimport));
@@ -77,20 +77,20 @@ USEVAR(GlobalRedecl2c)
// NB: MSC issues a warning and makes GlobalRedecl3 dllexport. We follow GCC
// and drop the dllimport with a warning.
-// MSC-DAG: @"\01?GlobalRedecl3@@3HA" = external global i32
-// GNU-DAG: @GlobalRedecl3 = external global i32
+// MSC-DAG: @"?GlobalRedecl3@@3HA" = external dso_local global i32
+// GNU-DAG: @GlobalRedecl3 = external dso_local global i32
__declspec(dllimport) extern int GlobalRedecl3;
extern int GlobalRedecl3; // dllimport ignored
USEVAR(GlobalRedecl3)
-// MSC-DAG: @"\01?ExternalGlobal@ns@@3HA" = external dllimport global i32
+// MSC-DAG: @"?ExternalGlobal@ns@@3HA" = external dllimport global i32
// GNU-DAG: @_ZN2ns14ExternalGlobalE = external dllimport global i32
namespace ns { __declspec(dllimport) int ExternalGlobal; }
USEVAR(ns::ExternalGlobal)
int __declspec(dllimport) f();
-// MO1-DAG: @"\01?x@?1??inlineStaticLocalsFunc@@YAHXZ@4HA" = available_externally dllimport global i32 0
-// MO1-DAG: @"\01??_B?1??inlineStaticLocalsFunc@@YAHXZ@51" = available_externally dllimport global i32 0
+// MO1-DAG: @"?x@?1??inlineStaticLocalsFunc@@YAHXZ@4HA" = available_externally dllimport global i32 0
+// MO1-DAG: @"??_B?1??inlineStaticLocalsFunc@@YAHXZ@51" = available_externally dllimport global i32 0
inline int __declspec(dllimport) inlineStaticLocalsFunc() {
static int x = f();
return x++;
@@ -98,7 +98,7 @@ inline int __declspec(dllimport) inlineStaticLocalsFunc() {
USE(inlineStaticLocalsFunc);
// The address of a dllimport global cannot be used in constant initialization.
-// M32-DAG: @"\01?arr@?1??initializationFunc@@YAPAHXZ@4QBQAHB" = internal global [1 x i32*] zeroinitializer
+// M32-DAG: @"?arr@?1??initializationFunc@@YAPAHXZ@4QBQAHB" = internal global [1 x i32*] zeroinitializer
// GNU-DAG: @_ZZ18initializationFuncvE3arr = internal global [1 x i32*] zeroinitializer
int *initializationFunc() {
static int *const arr[] = {&ExternGlobalDecl};
@@ -112,38 +112,38 @@ USE(initializationFunc);
//===----------------------------------------------------------------------===//
// Import declaration.
-// MSC-DAG: @"\01??$ExternVarTmplDecl@UImplicitInst_Imported@@@@3HA" = external dllimport global i32
+// MSC-DAG: @"??$ExternVarTmplDecl@UImplicitInst_Imported@@@@3HA" = external dllimport global i32
// GNU-DAG: @_Z17ExternVarTmplDeclI21ImplicitInst_ImportedE = external dllimport global i32
template<typename T> __declspec(dllimport) extern int ExternVarTmplDecl;
USEVAR(ExternVarTmplDecl<ImplicitInst_Imported>)
// dllimport implies a declaration.
-// MSC-DAG: @"\01??$VarTmplDecl@UImplicitInst_Imported@@@@3HA" = external dllimport global i32
+// MSC-DAG: @"??$VarTmplDecl@UImplicitInst_Imported@@@@3HA" = external dllimport global i32
// GNU-DAG: @_Z11VarTmplDeclI21ImplicitInst_ImportedE = external dllimport global i32
template<typename T> __declspec(dllimport) int VarTmplDecl;
USEVAR(VarTmplDecl<ImplicitInst_Imported>)
// Redeclarations
-// MSC-DAG: @"\01??$VarTmplRedecl1@UImplicitInst_Imported@@@@3HA" = external dllimport global i32
+// MSC-DAG: @"??$VarTmplRedecl1@UImplicitInst_Imported@@@@3HA" = external dllimport global i32
// GNU-DAG: @_Z14VarTmplRedecl1I21ImplicitInst_ImportedE = external dllimport global i32
template<typename T> __declspec(dllimport) extern int VarTmplRedecl1;
template<typename T> __declspec(dllimport) extern int VarTmplRedecl1;
USEVAR(VarTmplRedecl1<ImplicitInst_Imported>)
-// MSC-DAG: @"\01??$VarTmplRedecl2@UImplicitInst_Imported@@@@3HA" = external dllimport global i32
+// MSC-DAG: @"??$VarTmplRedecl2@UImplicitInst_Imported@@@@3HA" = external dllimport global i32
// GNU-DAG: @_Z14VarTmplRedecl2I21ImplicitInst_ImportedE = external dllimport global i32
template<typename T> __declspec(dllimport) int VarTmplRedecl2;
template<typename T> __declspec(dllimport) int VarTmplRedecl2;
USEVAR(VarTmplRedecl2<ImplicitInst_Imported>)
-// MSC-DAG: @"\01??$VarTmplRedecl3@UImplicitInst_Imported@@@@3HA" = external global i32
-// GNU-DAG: @_Z14VarTmplRedecl3I21ImplicitInst_ImportedE = external global i32
+// MSC-DAG: @"??$VarTmplRedecl3@UImplicitInst_Imported@@@@3HA" = external dso_local global i32
+// GNU-DAG: @_Z14VarTmplRedecl3I21ImplicitInst_ImportedE = external dso_local global i32
template<typename T> __declspec(dllimport) extern int VarTmplRedecl3;
template<typename T> extern int VarTmplRedecl3; // dllimport ignored
USEVAR(VarTmplRedecl3<ImplicitInst_Imported>)
-// MSC-DAG: @"\01??$ExternalVarTmpl@UImplicitInst_Imported@@@ns@@3HA" = external dllimport global i32
+// MSC-DAG: @"??$ExternalVarTmpl@UImplicitInst_Imported@@@ns@@3HA" = external dllimport global i32
// GNU-DAG: @_ZN2ns15ExternalVarTmplI21ImplicitInst_ImportedEE = external dllimport global i32
namespace ns { template<typename T> __declspec(dllimport) int ExternalVarTmpl; }
USEVAR(ns::ExternalVarTmpl<ImplicitInst_Imported>)
@@ -153,12 +153,12 @@ template<typename T> int VarTmpl;
template<typename T> __declspec(dllimport) int ImportedVarTmpl;
// Import implicit instantiation of an imported variable template.
-// MSC-DAG: @"\01??$ImportedVarTmpl@UImplicitInst_Imported@@@@3HA" = external dllimport global i32
+// MSC-DAG: @"??$ImportedVarTmpl@UImplicitInst_Imported@@@@3HA" = external dllimport global i32
// GNU-DAG: @_Z15ImportedVarTmplI21ImplicitInst_ImportedE = external dllimport global i32
USEVAR(ImportedVarTmpl<ImplicitInst_Imported>)
// Import explicit instantiation declaration of an imported variable template.
-// MSC-DAG: @"\01??$ImportedVarTmpl@UExplicitDecl_Imported@@@@3HA" = external dllimport global i32
+// MSC-DAG: @"??$ImportedVarTmpl@UExplicitDecl_Imported@@@@3HA" = external dllimport global i32
// GNU-DAG: @_Z15ImportedVarTmplI21ExplicitDecl_ImportedE = external dllimport global i32
extern template int ImportedVarTmpl<ExplicitDecl_Imported>;
USEVAR(ImportedVarTmpl<ExplicitDecl_Imported>)
@@ -167,32 +167,32 @@ USEVAR(ImportedVarTmpl<ExplicitDecl_Imported>)
// be imported because the template must be defined which is illegal.
// Import specialization of an imported variable template.
-// MSC-DAG: @"\01??$ImportedVarTmpl@UExplicitSpec_Imported@@@@3HA" = external dllimport global i32
+// MSC-DAG: @"??$ImportedVarTmpl@UExplicitSpec_Imported@@@@3HA" = external dllimport global i32
// GNU-DAG: @_Z15ImportedVarTmplI21ExplicitSpec_ImportedE = external dllimport global i32
template<> __declspec(dllimport) int ImportedVarTmpl<ExplicitSpec_Imported>;
USEVAR(ImportedVarTmpl<ExplicitSpec_Imported>)
// Not importing specialization of an imported variable template without
// explicit dllimport.
-// MSC-DAG: @"\01??$ImportedVarTmpl@UExplicitSpec_NotImported@@@@3HA" = global i32 0, align 4
-// GNU-DAG: @_Z15ImportedVarTmplI24ExplicitSpec_NotImportedE = global i32 0, align 4
+// MSC-DAG: @"??$ImportedVarTmpl@UExplicitSpec_NotImported@@@@3HA" = dso_local global i32 0, align 4
+// GNU-DAG: @_Z15ImportedVarTmplI24ExplicitSpec_NotImportedE = dso_local global i32 0, align 4
template<> int ImportedVarTmpl<ExplicitSpec_NotImported>;
USEVAR(ImportedVarTmpl<ExplicitSpec_NotImported>)
// Import explicit instantiation declaration of a non-imported variable template.
-// MSC-DAG: @"\01??$VarTmpl@UExplicitDecl_Imported@@@@3HA" = external dllimport global i32
+// MSC-DAG: @"??$VarTmpl@UExplicitDecl_Imported@@@@3HA" = external dllimport global i32
// GNU-DAG: @_Z7VarTmplI21ExplicitDecl_ImportedE = external dllimport global i32
extern template __declspec(dllimport) int VarTmpl<ExplicitDecl_Imported>;
USEVAR(VarTmpl<ExplicitDecl_Imported>)
// Import explicit instantiation definition of a non-imported variable template.
-// MSC-DAG: @"\01??$VarTmpl@UExplicitInst_Imported@@@@3HA" = external dllimport global i32
+// MSC-DAG: @"??$VarTmpl@UExplicitInst_Imported@@@@3HA" = external dllimport global i32
// GNU-DAG: @_Z7VarTmplI21ExplicitInst_ImportedE = external dllimport global i32
template __declspec(dllimport) int VarTmpl<ExplicitInst_Imported>;
USEVAR(VarTmpl<ExplicitInst_Imported>)
// Import specialization of a non-imported variable template.
-// MSC-DAG: @"\01??$VarTmpl@UExplicitSpec_Imported@@@@3HA" = external dllimport global i32
+// MSC-DAG: @"??$VarTmpl@UExplicitSpec_Imported@@@@3HA" = external dllimport global i32
// GNU-DAG: @_Z7VarTmplI21ExplicitSpec_ImportedE = external dllimport global i32
template<> __declspec(dllimport) int VarTmpl<ExplicitSpec_Imported>;
USEVAR(VarTmpl<ExplicitSpec_Imported>)
@@ -203,8 +203,10 @@ USEVAR(VarTmpl<ExplicitSpec_Imported>)
// Functions
//===----------------------------------------------------------------------===//
+// GNU-DAG: declare dso_local void @_ZdlPv(i8*)
+
// Import function declaration.
-// MSC-DAG: declare dllimport void @"\01?decl@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"?decl@@YAXXZ"()
// GNU-DAG: declare dllimport void @_Z4declv()
__declspec(dllimport) void decl();
USE(decl)
@@ -216,42 +218,42 @@ extern "C" __declspec(dllimport) void externC();
USE(externC)
// Import inline function.
-// MSC-DAG: declare dllimport void @"\01?inlineFunc@@YAXXZ"()
-// GNU-DAG: define linkonce_odr void @_Z10inlineFuncv()
-// MO1-DAG: define available_externally dllimport void @"\01?inlineFunc@@YAXXZ"()
-// GO1-DAG: define linkonce_odr void @_Z10inlineFuncv()
+// MSC-DAG: declare dllimport void @"?inlineFunc@@YAXXZ"()
+// GNU-DAG: define linkonce_odr dso_local void @_Z10inlineFuncv()
+// MO1-DAG: define available_externally dllimport void @"?inlineFunc@@YAXXZ"()
+// GO1-DAG: define linkonce_odr dso_local void @_Z10inlineFuncv()
__declspec(dllimport) inline void inlineFunc() {}
USE(inlineFunc)
-// MSC-DAG: declare dllimport void @"\01?inlineDecl@@YAXXZ"()
-// GNU-DAG: define linkonce_odr void @_Z10inlineDeclv()
-// MO1-DAG: define available_externally dllimport void @"\01?inlineDecl@@YAXXZ"()
-// GO1-DAG: define linkonce_odr void @_Z10inlineDeclv()
+// MSC-DAG: declare dllimport void @"?inlineDecl@@YAXXZ"()
+// GNU-DAG: define linkonce_odr dso_local void @_Z10inlineDeclv()
+// MO1-DAG: define available_externally dllimport void @"?inlineDecl@@YAXXZ"()
+// GO1-DAG: define linkonce_odr dso_local void @_Z10inlineDeclv()
__declspec(dllimport) inline void inlineDecl();
void inlineDecl() {}
USE(inlineDecl)
-// MSC-DAG: declare dllimport void @"\01?inlineDef@@YAXXZ"()
-// GNU-DAG: define linkonce_odr void @_Z9inlineDefv()
-// MO1-DAG: define available_externally dllimport void @"\01?inlineDef@@YAXXZ"()
-// GO1-DAG: define linkonce_odr void @_Z9inlineDefv()
+// MSC-DAG: declare dllimport void @"?inlineDef@@YAXXZ"()
+// GNU-DAG: define linkonce_odr dso_local void @_Z9inlineDefv()
+// MO1-DAG: define available_externally dllimport void @"?inlineDef@@YAXXZ"()
+// GO1-DAG: define linkonce_odr dso_local void @_Z9inlineDefv()
__declspec(dllimport) void inlineDef();
inline void inlineDef() {}
USE(inlineDef)
// inline attributes
-// MSC-DAG: declare dllimport void @"\01?noinline@@YAXXZ"()
-// GNU-DAG: define linkonce_odr void @_Z8noinlinev()
+// MSC-DAG: declare dllimport void @"?noinline@@YAXXZ"()
+// GNU-DAG: define linkonce_odr dso_local void @_Z8noinlinev()
__declspec(dllimport) __attribute__((noinline)) inline void noinline() {}
USE(noinline)
-// MSC2-NOT: @"\01?alwaysInline@@YAXXZ"()
+// MSC2-NOT: @"?alwaysInline@@YAXXZ"()
// GNU2-NOT: @_Z12alwaysInlinev()
__declspec(dllimport) __attribute__((always_inline)) inline void alwaysInline() {}
USE(alwaysInline)
// Redeclarations
-// MSC-DAG: declare dllimport void @"\01?redecl1@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"?redecl1@@YAXXZ"()
// GNU-DAG: declare dllimport void @_Z7redecl1v()
__declspec(dllimport) void redecl1();
__declspec(dllimport) void redecl1();
@@ -259,30 +261,30 @@ USE(redecl1)
// NB: MSC issues a warning and makes redecl2/redecl3 dllexport. We follow GCC
// and drop the dllimport with a warning.
-// MSC-DAG: declare void @"\01?redecl2@@YAXXZ"()
-// GNU-DAG: declare void @_Z7redecl2v()
+// MSC-DAG: declare dso_local void @"?redecl2@@YAXXZ"()
+// GNU-DAG: declare dso_local void @_Z7redecl2v()
__declspec(dllimport) void redecl2();
void redecl2();
USE(redecl2)
-// MSC-DAG: define dllexport void @"\01?redecl3@@YAXXZ"()
-// GNU-DAG: define void @_Z7redecl3v()
+// MSC-DAG: define dso_local dllexport void @"?redecl3@@YAXXZ"()
+// GNU-DAG: define dso_local void @_Z7redecl3v()
__declspec(dllimport) void redecl3();
void redecl3() {} // dllimport ignored
USE(redecl3)
// Friend functions
-// MSC-DAG: declare dllimport void @"\01?friend1@@YAXXZ"()
-// GNU-DAG: declare dllimport void @_Z7friend1v()
-// MSC-DAG: declare void @"\01?friend2@@YAXXZ"()
-// GNU-DAG: declare void @_Z7friend2v()
-// MSC-DAG: define dllexport void @"\01?friend3@@YAXXZ"()
-// GNU-DAG: define void @_Z7friend3v()
-// MSC-DAG: declare void @"\01?friend4@@YAXXZ"()
-// GNU-DAG: declare void @_Z7friend4v()
-// MSC-DAG: declare dllimport void @"\01?friend5@@YAXXZ"()
-// GNU-DAG: declare dllimport void @_Z7friend5v()
+// MSC-DAG: declare dllimport void @"?friend1@@YAXXZ"()
+// GNU-DAG: declare dllimport void @_Z7friend1v()
+// MSC-DAG: declare dso_local void @"?friend2@@YAXXZ"()
+// GNU-DAG: declare dso_local void @_Z7friend2v()
+// MSC-DAG: define dso_local dllexport void @"?friend3@@YAXXZ"()
+// GNU-DAG: define dso_local void @_Z7friend3v()
+// MSC-DAG: declare dso_local void @"?friend4@@YAXXZ"()
+// GNU-DAG: declare dso_local void @_Z7friend4v()
+// MSC-DAG: declare dllimport void @"?friend5@@YAXXZ"()
+// GNU-DAG: declare dllimport void @_Z7friend5v()
struct FuncFriend {
friend __declspec(dllimport) void friend1();
@@ -306,12 +308,12 @@ USE(friend4)
USE(friend5)
// Implicit declarations can be redeclared with dllimport.
-// MSC-DAG: declare dllimport noalias i8* @"\01??2@{{YAPAXI|YAPEAX_K}}@Z"(
+// MSC-DAG: declare dllimport noalias i8* @"??2@{{YAPAXI|YAPEAX_K}}@Z"(
// GNU-DAG: declare dllimport noalias i8* @_Znw{{[yj]}}(
__declspec(dllimport) void* operator new(__SIZE_TYPE__ n);
void UNIQ(use)() { ::operator new(42); }
-// MSC-DAG: declare dllimport void @"\01?externalFunc@ns@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"?externalFunc@ns@@YAXXZ"()
// GNU-DAG: declare dllimport void @_ZN2ns12externalFuncEv()
namespace ns { __declspec(dllimport) void externalFunc(); }
USE(ns::externalFunc)
@@ -325,17 +327,17 @@ int NonImportedFunc();
struct ClassWithNonImportedMethod { int f(); };
__declspec(dllimport) inline int ReferencingImportedVar() { return ImportedVar; }
-// MO1-DAG: define available_externally dllimport i32 @"\01?ReferencingImportedVar@@YAHXZ"
+// MO1-DAG: define available_externally dllimport i32 @"?ReferencingImportedVar@@YAHXZ"
__declspec(dllimport) inline int ReferencingNonImportedVar() { return NonImportedVar; }
-// MO1-DAG: declare dllimport i32 @"\01?ReferencingNonImportedVar@@YAHXZ"()
+// MO1-DAG: declare dllimport i32 @"?ReferencingNonImportedVar@@YAHXZ"()
__declspec(dllimport) inline int ReferencingImportedFunc() { return ImportedFunc(); }
-// MO1-DAG: define available_externally dllimport i32 @"\01?ReferencingImportedFunc@@YAHXZ"
+// MO1-DAG: define available_externally dllimport i32 @"?ReferencingImportedFunc@@YAHXZ"
__declspec(dllimport) inline int ReferencingNonImportedFunc() { return NonImportedFunc(); }
-// MO1-DAG: declare dllimport i32 @"\01?ReferencingNonImportedFunc@@YAHXZ"()
+// MO1-DAG: declare dllimport i32 @"?ReferencingNonImportedFunc@@YAHXZ"()
__declspec(dllimport) inline int ReferencingNonImportedMethod(ClassWithNonImportedMethod *x) { return x->f(); }
-// MO1-DAG: declare dllimport i32 @"\01?ReferencingNonImportedMethod
+// MO1-DAG: declare dllimport i32 @"?ReferencingNonImportedMethod
__declspec(dllimport) inline int ReferencingClassMemberPtr(int (ClassWithNonImportedMethod::*p)(), ClassWithNonImportedMethod *x) { return (x->*p)(); }
-// MO1-DAG: define available_externally dllimport i32 @"\01?ReferencingClassMemberPtr@@YAHP8ClassWithNonImportedMethod@@AEHXZPAU1@@Z"
+// MO1-DAG: define available_externally dllimport i32 @"?ReferencingClassMemberPtr@@YAHP8ClassWithNonImportedMethod@@AEHXZPAU1@@Z"
USE(ReferencingImportedVar)
USE(ReferencingNonImportedVar)
USE(ReferencingImportedFunc)
@@ -344,17 +346,17 @@ USE1(ReferencingNonImportedMethod)
void UNIQ(use)() { ReferencingClassMemberPtr(&ClassWithNonImportedMethod::f, nullptr); }
// References to operator new and delete count too, despite not being DeclRefExprs.
__declspec(dllimport) inline int *ReferencingNonImportedNew() { return new int[2]; }
-// MO1-DAG: declare dllimport i32* @"\01?ReferencingNonImportedNew@@YAPAHXZ"
+// MO1-DAG: declare dllimport i32* @"?ReferencingNonImportedNew@@YAPAHXZ"
__declspec(dllimport) inline int *ReferencingNonImportedDelete() { delete (int*)nullptr; }
-// MO1-DAG: declare dllimport i32* @"\01?ReferencingNonImportedDelete@@YAPAHXZ"
+// MO1-DAG: declare dllimport i32* @"?ReferencingNonImportedDelete@@YAPAHXZ"
USE(ReferencingNonImportedNew)
USE(ReferencingNonImportedDelete)
__declspec(dllimport) void* operator new[](__SIZE_TYPE__);
__declspec(dllimport) void operator delete(void*);
__declspec(dllimport) inline int *ReferencingImportedNew() { return new int[2]; }
-// MO1-DAG: define available_externally dllimport i32* @"\01?ReferencingImportedNew@@YAPAHXZ"
+// MO1-DAG: define available_externally dllimport i32* @"?ReferencingImportedNew@@YAPAHXZ"
__declspec(dllimport) inline int *ReferencingImportedDelete() { delete (int*)nullptr; }
-// MO1-DAG: define available_externally dllimport i32* @"\01?ReferencingImportedDelete@@YAPAHXZ"
+// MO1-DAG: define available_externally dllimport i32* @"?ReferencingImportedDelete@@YAPAHXZ"
USE(ReferencingImportedNew)
USE(ReferencingImportedDelete)
struct ClassWithDtor { ~ClassWithDtor() {} };
@@ -362,25 +364,25 @@ struct __declspec(dllimport) ClassWithNonDllImportField { using X = ClassWithDto
struct __declspec(dllimport) ClassWithNonDllImportBase : public ClassWithDtor { };
USECLASS(ClassWithNonDllImportField);
USECLASS(ClassWithNonDllImportBase);
-// MO1-DAG: declare dllimport x86_thiscallcc void @"\01??1ClassWithNonDllImportBase@@QAE@XZ"(%struct.ClassWithNonDllImportBase*)
-// MO1-DAG: declare dllimport x86_thiscallcc void @"\01??1ClassWithNonDllImportField@@QAE@XZ"(%struct.ClassWithNonDllImportField*)
+// MO1-DAG: declare dllimport x86_thiscallcc void @"??1ClassWithNonDllImportBase@@QAE@XZ"(%struct.ClassWithNonDllImportBase*)
+// MO1-DAG: declare dllimport x86_thiscallcc void @"??1ClassWithNonDllImportField@@QAE@XZ"(%struct.ClassWithNonDllImportField*)
struct ClassWithCtor { ClassWithCtor() {} };
struct __declspec(dllimport) ClassWithNonDllImportFieldWithCtor { ClassWithCtor t; };
USECLASS(ClassWithNonDllImportFieldWithCtor);
-// MO1-DAG: declare dllimport x86_thiscallcc %struct.ClassWithNonDllImportFieldWithCtor* @"\01??0ClassWithNonDllImportFieldWithCtor@@QAE@XZ"(%struct.ClassWithNonDllImportFieldWithCtor* returned)
+// MO1-DAG: declare dllimport x86_thiscallcc %struct.ClassWithNonDllImportFieldWithCtor* @"??0ClassWithNonDllImportFieldWithCtor@@QAE@XZ"(%struct.ClassWithNonDllImportFieldWithCtor* returned)
struct ClassWithImplicitDtor { __declspec(dllimport) ClassWithImplicitDtor(); ClassWithDtor member; };
__declspec(dllimport) inline void ReferencingDtorThroughDefinition() { ClassWithImplicitDtor x; };
USE(ReferencingDtorThroughDefinition)
-// MO1-DAG: declare dllimport void @"\01?ReferencingDtorThroughDefinition@@YAXXZ"()
+// MO1-DAG: declare dllimport void @"?ReferencingDtorThroughDefinition@@YAXXZ"()
__declspec(dllimport) inline void ReferencingDtorThroughTemporary() { ClassWithImplicitDtor(); };
USE(ReferencingDtorThroughTemporary)
-// MO1-DAG: declare dllimport void @"\01?ReferencingDtorThroughTemporary@@YAXXZ"()
+// MO1-DAG: declare dllimport void @"?ReferencingDtorThroughTemporary@@YAXXZ"()
// A dllimport function with a TLS variable must not be available_externally.
__declspec(dllimport) inline void FunctionWithTLSVar() { static __thread int x = 42; }
-// MO1-DAG: declare dllimport void @"\01?FunctionWithTLSVar@@YAXXZ"
+// MO1-DAG: declare dllimport void @"?FunctionWithTLSVar@@YAXXZ"
__declspec(dllimport) inline void FunctionWithNormalVar() { static int x = 42; }
-// MO1-DAG: define available_externally dllimport void @"\01?FunctionWithNormalVar@@YAXXZ"
+// MO1-DAG: define available_externally dllimport void @"?FunctionWithNormalVar@@YAXXZ"
USE(FunctionWithTLSVar)
USE(FunctionWithNormalVar)
@@ -390,7 +392,7 @@ USE(FunctionWithNormalVar)
//===----------------------------------------------------------------------===//
// Import function template declaration.
-// MSC-DAG: declare dllimport void @"\01??$funcTmplDecl@UImplicitInst_Imported@@@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"??$funcTmplDecl@UImplicitInst_Imported@@@@YAXXZ"()
// GNU-DAG: declare dllimport void @_Z12funcTmplDeclI21ImplicitInst_ImportedEvv()
template<typename T> __declspec(dllimport) void funcTmplDecl();
USE(funcTmplDecl<ImplicitInst_Imported>)
@@ -398,66 +400,66 @@ USE(funcTmplDecl<ImplicitInst_Imported>)
// Function template definitions cannot be imported.
// Import inline function template.
-// MSC-DAG: declare dllimport void @"\01??$inlineFuncTmpl1@UImplicitInst_Imported@@@@YAXXZ"()
-// GNU-DAG: define linkonce_odr void @_Z15inlineFuncTmpl1I21ImplicitInst_ImportedEvv()
-// MO1-DAG: define available_externally dllimport void @"\01??$inlineFuncTmpl1@UImplicitInst_Imported@@@@YAXXZ"()
-// GO1-DAG: define linkonce_odr void @_Z15inlineFuncTmpl1I21ImplicitInst_ImportedEvv()
+// MSC-DAG: declare dllimport void @"??$inlineFuncTmpl1@UImplicitInst_Imported@@@@YAXXZ"()
+// GNU-DAG: define linkonce_odr dso_local void @_Z15inlineFuncTmpl1I21ImplicitInst_ImportedEvv()
+// MO1-DAG: define available_externally dllimport void @"??$inlineFuncTmpl1@UImplicitInst_Imported@@@@YAXXZ"()
+// GO1-DAG: define linkonce_odr dso_local void @_Z15inlineFuncTmpl1I21ImplicitInst_ImportedEvv()
template<typename T> __declspec(dllimport) inline void inlineFuncTmpl1() {}
USE(inlineFuncTmpl1<ImplicitInst_Imported>)
-// MSC-DAG: declare dllimport void @"\01??$inlineFuncTmpl2@UImplicitInst_Imported@@@@YAXXZ"()
-// GNU-DAG: define linkonce_odr void @_Z15inlineFuncTmpl2I21ImplicitInst_ImportedEvv()
-// MO1-DAG: define available_externally dllimport void @"\01??$inlineFuncTmpl2@UImplicitInst_Imported@@@@YAXXZ"()
-// GO1-DAG: define linkonce_odr void @_Z15inlineFuncTmpl2I21ImplicitInst_ImportedEvv()
+// MSC-DAG: declare dllimport void @"??$inlineFuncTmpl2@UImplicitInst_Imported@@@@YAXXZ"()
+// GNU-DAG: define linkonce_odr dso_local void @_Z15inlineFuncTmpl2I21ImplicitInst_ImportedEvv()
+// MO1-DAG: define available_externally dllimport void @"??$inlineFuncTmpl2@UImplicitInst_Imported@@@@YAXXZ"()
+// GO1-DAG: define linkonce_odr dso_local void @_Z15inlineFuncTmpl2I21ImplicitInst_ImportedEvv()
template<typename T> inline void __attribute__((dllimport)) inlineFuncTmpl2() {}
USE(inlineFuncTmpl2<ImplicitInst_Imported>)
-// MSC-DAG: define linkonce_odr void @"\01??$inlineFuncTmplDecl@UImplicitInst_Imported@@@@YAXXZ"()
-// GNU-DAG: define linkonce_odr void @_Z18inlineFuncTmplDeclI21ImplicitInst_ImportedEvv()
-// MO1-DAG: define linkonce_odr void @"\01??$inlineFuncTmplDecl@UImplicitInst_Imported@@@@YAXXZ"()
-// GO1-DAG: define linkonce_odr void @_Z18inlineFuncTmplDeclI21ImplicitInst_ImportedEvv()
+// MSC-DAG: define linkonce_odr dso_local void @"??$inlineFuncTmplDecl@UImplicitInst_Imported@@@@YAXXZ"()
+// GNU-DAG: define linkonce_odr dso_local void @_Z18inlineFuncTmplDeclI21ImplicitInst_ImportedEvv()
+// MO1-DAG: define linkonce_odr dso_local void @"??$inlineFuncTmplDecl@UImplicitInst_Imported@@@@YAXXZ"()
+// GO1-DAG: define linkonce_odr dso_local void @_Z18inlineFuncTmplDeclI21ImplicitInst_ImportedEvv()
template<typename T> __declspec(dllimport) inline void inlineFuncTmplDecl();
template<typename T> void inlineFuncTmplDecl() {}
USE(inlineFuncTmplDecl<ImplicitInst_Imported>)
-// MSC-DAG: define linkonce_odr void @"\01??$inlineFuncTmplDef@UImplicitInst_Imported@@@@YAXXZ"()
-// GNU-DAG: define linkonce_odr void @_Z17inlineFuncTmplDefI21ImplicitInst_ImportedEvv()
-// MO1-DAG: define linkonce_odr void @"\01??$inlineFuncTmplDef@UImplicitInst_Imported@@@@YAXXZ"()
-// GO1-DAG: define linkonce_odr void @_Z17inlineFuncTmplDefI21ImplicitInst_ImportedEvv()
+// MSC-DAG: define linkonce_odr dso_local void @"??$inlineFuncTmplDef@UImplicitInst_Imported@@@@YAXXZ"()
+// GNU-DAG: define linkonce_odr dso_local void @_Z17inlineFuncTmplDefI21ImplicitInst_ImportedEvv()
+// MO1-DAG: define linkonce_odr dso_local void @"??$inlineFuncTmplDef@UImplicitInst_Imported@@@@YAXXZ"()
+// GO1-DAG: define linkonce_odr dso_local void @_Z17inlineFuncTmplDefI21ImplicitInst_ImportedEvv()
template<typename T> __declspec(dllimport) void inlineFuncTmplDef();
template<typename T> inline void inlineFuncTmplDef() {}
USE(inlineFuncTmplDef<ImplicitInst_Imported>)
// Redeclarations
-// MSC-DAG: declare dllimport void @"\01??$funcTmplRedecl1@UImplicitInst_Imported@@@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"??$funcTmplRedecl1@UImplicitInst_Imported@@@@YAXXZ"()
// GNU-DAG: declare dllimport void @_Z15funcTmplRedecl1I21ImplicitInst_ImportedEvv()
template<typename T> __declspec(dllimport) void funcTmplRedecl1();
template<typename T> __declspec(dllimport) void funcTmplRedecl1();
USE(funcTmplRedecl1<ImplicitInst_Imported>)
-// MSC-DAG: declare void @"\01??$funcTmplRedecl2@UImplicitInst_NotImported@@@@YAXXZ"()
-// GNU-DAG: declare void @_Z15funcTmplRedecl2I24ImplicitInst_NotImportedEvv()
+// MSC-DAG: declare dso_local void @"??$funcTmplRedecl2@UImplicitInst_NotImported@@@@YAXXZ"()
+// GNU-DAG: declare dso_local void @_Z15funcTmplRedecl2I24ImplicitInst_NotImportedEvv()
template<typename T> __declspec(dllimport) void funcTmplRedecl2();
template<typename T> void funcTmplRedecl2(); // dllimport ignored
USE(funcTmplRedecl2<ImplicitInst_NotImported>)
-// MSC-DAG: define linkonce_odr void @"\01??$funcTmplRedecl3@UImplicitInst_NotImported@@@@YAXXZ"()
-// GNU-DAG: define linkonce_odr void @_Z15funcTmplRedecl3I24ImplicitInst_NotImportedEvv()
+// MSC-DAG: define linkonce_odr dso_local void @"??$funcTmplRedecl3@UImplicitInst_NotImported@@@@YAXXZ"()
+// GNU-DAG: define linkonce_odr dso_local void @_Z15funcTmplRedecl3I24ImplicitInst_NotImportedEvv()
template<typename T> __declspec(dllimport) void funcTmplRedecl3();
template<typename T> void funcTmplRedecl3() {} // dllimport ignored
USE(funcTmplRedecl3<ImplicitInst_NotImported>)
// Function template friends
-// MSC-DAG: declare dllimport void @"\01??$funcTmplFriend1@UImplicitInst_Imported@@@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"??$funcTmplFriend1@UImplicitInst_Imported@@@@YAXXZ"()
// GNU-DAG: declare dllimport void @_Z15funcTmplFriend1I21ImplicitInst_ImportedEvv()
-// MSC-DAG: declare void @"\01??$funcTmplFriend2@UImplicitInst_NotImported@@@@YAXXZ"()
-// GNU-DAG: declare void @_Z15funcTmplFriend2I24ImplicitInst_NotImportedEvv()
-// MSC-DAG: define linkonce_odr void @"\01??$funcTmplFriend3@UImplicitInst_NotImported@@@@YAXXZ"()
-// GNU-DAG: define linkonce_odr void @_Z15funcTmplFriend3I24ImplicitInst_NotImportedEvv()
-// MSC-DAG: define linkonce_odr void @"\01??$funcTmplFriend4@UImplicitInst_Imported@@@@YAXXZ"()
-// GNU-DAG: define linkonce_odr void @_Z15funcTmplFriend4I21ImplicitInst_ImportedEvv()
+// MSC-DAG: declare dso_local void @"??$funcTmplFriend2@UImplicitInst_NotImported@@@@YAXXZ"()
+// GNU-DAG: declare dso_local void @_Z15funcTmplFriend2I24ImplicitInst_NotImportedEvv()
+// MSC-DAG: define linkonce_odr dso_local void @"??$funcTmplFriend3@UImplicitInst_NotImported@@@@YAXXZ"()
+// GNU-DAG: define linkonce_odr dso_local void @_Z15funcTmplFriend3I24ImplicitInst_NotImportedEvv()
+// MSC-DAG: define linkonce_odr dso_local void @"??$funcTmplFriend4@UImplicitInst_Imported@@@@YAXXZ"()
+// GNU-DAG: define linkonce_odr dso_local void @_Z15funcTmplFriend4I21ImplicitInst_ImportedEvv()
struct FuncTmplFriend {
template<typename T> friend __declspec(dllimport) void funcTmplFriend1();
template<typename T> friend __declspec(dllimport) void funcTmplFriend2();
@@ -473,7 +475,7 @@ USE(funcTmplFriend2<ImplicitInst_NotImported>)
USE(funcTmplFriend3<ImplicitInst_NotImported>)
USE(funcTmplFriend4<ImplicitInst_Imported>)
-// MSC-DAG: declare dllimport void @"\01??$externalFuncTmpl@UImplicitInst_Imported@@@ns@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"??$externalFuncTmpl@UImplicitInst_Imported@@@ns@@YAXXZ"()
// GNU-DAG: declare dllimport void @_ZN2ns16externalFuncTmplI21ImplicitInst_ImportedEEvv()
namespace ns { template<typename T> __declspec(dllimport) void externalFuncTmpl(); }
USE(ns::externalFuncTmpl<ImplicitInst_Imported>)
@@ -485,89 +487,89 @@ template<typename T> __declspec(dllimport) void importedFuncTmplDecl();
template<typename T> __declspec(dllimport) inline void importedFuncTmpl() {}
// Import implicit instantiation of an imported function template.
-// MSC-DAG: declare dllimport void @"\01??$importedFuncTmplDecl@UImplicitInst_Imported@@@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"??$importedFuncTmplDecl@UImplicitInst_Imported@@@@YAXXZ"()
// GNU-DAG: declare dllimport void @_Z20importedFuncTmplDeclI21ImplicitInst_ImportedEvv()
USE(importedFuncTmplDecl<ImplicitInst_Imported>)
-// MSC-DAG: declare dllimport void @"\01??$importedFuncTmpl@UImplicitInst_Imported@@@@YAXXZ"()
-// GNU-DAG: define linkonce_odr void @_Z16importedFuncTmplI21ImplicitInst_ImportedEvv()
-// MO1-DAG: define available_externally dllimport void @"\01??$importedFuncTmpl@UImplicitInst_Imported@@@@YAXXZ"()
-// GO1-DAG: define linkonce_odr void @_Z16importedFuncTmplI21ImplicitInst_ImportedEvv()
+// MSC-DAG: declare dllimport void @"??$importedFuncTmpl@UImplicitInst_Imported@@@@YAXXZ"()
+// GNU-DAG: define linkonce_odr dso_local void @_Z16importedFuncTmplI21ImplicitInst_ImportedEvv()
+// MO1-DAG: define available_externally dllimport void @"??$importedFuncTmpl@UImplicitInst_Imported@@@@YAXXZ"()
+// GO1-DAG: define linkonce_odr dso_local void @_Z16importedFuncTmplI21ImplicitInst_ImportedEvv()
USE(importedFuncTmpl<ImplicitInst_Imported>)
// Import explicit instantiation declaration of an imported function template.
-// MSC-DAG: declare dllimport void @"\01??$importedFuncTmpl@UExplicitDecl_Imported@@@@YAXXZ"()
-// GNU-DAG: declare void @_Z16importedFuncTmplI21ExplicitDecl_ImportedEvv()
-// MO1-DAG: define available_externally dllimport void @"\01??$importedFuncTmpl@UExplicitDecl_Imported@@@@YAXXZ"()
-// GO1-DAG: define available_externally void @_Z16importedFuncTmplI21ExplicitDecl_ImportedEvv()
+// MSC-DAG: declare dllimport void @"??$importedFuncTmpl@UExplicitDecl_Imported@@@@YAXXZ"()
+// GNU-DAG: declare dso_local void @_Z16importedFuncTmplI21ExplicitDecl_ImportedEvv()
+// MO1-DAG: define available_externally dllimport void @"??$importedFuncTmpl@UExplicitDecl_Imported@@@@YAXXZ"()
+// GO1-DAG: define available_externally dso_local void @_Z16importedFuncTmplI21ExplicitDecl_ImportedEvv()
extern template void importedFuncTmpl<ExplicitDecl_Imported>();
USE(importedFuncTmpl<ExplicitDecl_Imported>)
// Import explicit instantiation definition of an imported function template.
-// MSC-DAG: declare dllimport void @"\01??$importedFuncTmpl@UExplicitInst_Imported@@@@YAXXZ"()
-// GNU-DAG: define weak_odr void @_Z16importedFuncTmplI21ExplicitInst_ImportedEvv()
-// MO1-DAG: define available_externally dllimport void @"\01??$importedFuncTmpl@UExplicitInst_Imported@@@@YAXXZ"()
-// GO1-DAG: define weak_odr void @_Z16importedFuncTmplI21ExplicitInst_ImportedEvv()
+// MSC-DAG: declare dllimport void @"??$importedFuncTmpl@UExplicitInst_Imported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dso_local void @_Z16importedFuncTmplI21ExplicitInst_ImportedEvv()
+// MO1-DAG: define available_externally dllimport void @"??$importedFuncTmpl@UExplicitInst_Imported@@@@YAXXZ"()
+// GO1-DAG: define weak_odr dso_local void @_Z16importedFuncTmplI21ExplicitInst_ImportedEvv()
template void importedFuncTmpl<ExplicitInst_Imported>();
USE(importedFuncTmpl<ExplicitInst_Imported>)
// Import specialization of an imported function template.
-// MSC-DAG: declare dllimport void @"\01??$importedFuncTmplDecl@UExplicitSpec_Imported@@@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"??$importedFuncTmplDecl@UExplicitSpec_Imported@@@@YAXXZ"()
// GNU-DAG: declare dllimport void @_Z20importedFuncTmplDeclI21ExplicitSpec_ImportedEvv()
template<> __declspec(dllimport) void importedFuncTmplDecl<ExplicitSpec_Imported>();
USE(importedFuncTmplDecl<ExplicitSpec_Imported>)
-// MSC-DAG-FIXME: declare dllimport void @"\01??$importedFuncTmplDecl@UExplicitSpec_Def_Imported@@@@YAXXZ"()
-// MO1-DAG-FIXME: define available_externally dllimport void @"\01??$importedFuncTmplDecl@UExplicitSpec_Def_Imported@@@@YAXXZ"()
+// MSC-DAG-FIXME: declare dllimport void @"??$importedFuncTmplDecl@UExplicitSpec_Def_Imported@@@@YAXXZ"()
+// MO1-DAG-FIXME: define available_externally dllimport void @"??$importedFuncTmplDecl@UExplicitSpec_Def_Imported@@@@YAXXZ"()
#ifdef MSABI
//template<> __declspec(dllimport) void importedFuncTmplDecl<ExplicitSpec_Def_Imported>() {}
//USE(importedFuncTmplDecl<ExplicitSpec_Def_Imported>)
#endif
-// MSC-DAG: declare dllimport void @"\01??$importedFuncTmplDecl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"()
-// GNU-DAG: define linkonce_odr void @_Z20importedFuncTmplDeclI31ExplicitSpec_InlineDef_ImportedEvv()
-// MO1-DAG: define available_externally dllimport void @"\01??$importedFuncTmplDecl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"()
-// GO1-DAG: define linkonce_odr void @_Z20importedFuncTmplDeclI31ExplicitSpec_InlineDef_ImportedEvv()
+// MSC-DAG: declare dllimport void @"??$importedFuncTmplDecl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"()
+// GNU-DAG: define linkonce_odr dso_local void @_Z20importedFuncTmplDeclI31ExplicitSpec_InlineDef_ImportedEvv()
+// MO1-DAG: define available_externally dllimport void @"??$importedFuncTmplDecl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"()
+// GO1-DAG: define linkonce_odr dso_local void @_Z20importedFuncTmplDeclI31ExplicitSpec_InlineDef_ImportedEvv()
template<> __declspec(dllimport) inline void importedFuncTmplDecl<ExplicitSpec_InlineDef_Imported>() {}
USE(importedFuncTmplDecl<ExplicitSpec_InlineDef_Imported>)
-// MSC-DAG: declare dllimport void @"\01??$importedFuncTmpl@UExplicitSpec_Imported@@@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"??$importedFuncTmpl@UExplicitSpec_Imported@@@@YAXXZ"()
// GNU-DAG: declare dllimport void @_Z16importedFuncTmplI21ExplicitSpec_ImportedEvv()
template<> __declspec(dllimport) void importedFuncTmpl<ExplicitSpec_Imported>();
USE(importedFuncTmpl<ExplicitSpec_Imported>)
-// MSC-DAG-FIXME: declare dllimport void @"\01??$importedFuncTmpl@UExplicitSpec_Def_Imported@@@@YAXXZ"()
-// MO1-DAG-FIXME: define available_externally dllimport void @"\01??$importedFuncTmpl@UExplicitSpec_Def_Imported@@@@YAXXZ"()
+// MSC-DAG-FIXME: declare dllimport void @"??$importedFuncTmpl@UExplicitSpec_Def_Imported@@@@YAXXZ"()
+// MO1-DAG-FIXME: define available_externally dllimport void @"??$importedFuncTmpl@UExplicitSpec_Def_Imported@@@@YAXXZ"()
#ifdef MSABI
//template<> __declspec(dllimport) void importedFuncTmpl<ExplicitSpec_Def_Imported>() {}
//USE(importedFuncTmpl<ExplicitSpec_Def_Imported>)
#endif
-// MSC-DAG: declare dllimport void @"\01??$importedFuncTmpl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"()
-// GNU-DAG: define linkonce_odr void @_Z16importedFuncTmplI31ExplicitSpec_InlineDef_ImportedEvv()
-// MO1-DAG: define available_externally dllimport void @"\01??$importedFuncTmpl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"()
-// GO1-DAG: define linkonce_odr void @_Z16importedFuncTmplI31ExplicitSpec_InlineDef_ImportedEvv()
+// MSC-DAG: declare dllimport void @"??$importedFuncTmpl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"()
+// GNU-DAG: define linkonce_odr dso_local void @_Z16importedFuncTmplI31ExplicitSpec_InlineDef_ImportedEvv()
+// MO1-DAG: define available_externally dllimport void @"??$importedFuncTmpl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"()
+// GO1-DAG: define linkonce_odr dso_local void @_Z16importedFuncTmplI31ExplicitSpec_InlineDef_ImportedEvv()
template<> __declspec(dllimport) inline void importedFuncTmpl<ExplicitSpec_InlineDef_Imported>() {}
USE(importedFuncTmpl<ExplicitSpec_InlineDef_Imported>)
// Not importing specialization of an imported function template without
// explicit dllimport.
-// MSC-DAG: define void @"\01??$importedFuncTmpl@UExplicitSpec_NotImported@@@@YAXXZ"()
-// GNU-DAG: define void @_Z16importedFuncTmplI24ExplicitSpec_NotImportedEvv()
+// MSC-DAG: define dso_local void @"??$importedFuncTmpl@UExplicitSpec_NotImported@@@@YAXXZ"()
+// GNU-DAG: define dso_local void @_Z16importedFuncTmplI24ExplicitSpec_NotImportedEvv()
template<> void importedFuncTmpl<ExplicitSpec_NotImported>() {}
USE(importedFuncTmpl<ExplicitSpec_NotImported>)
// Import explicit instantiation declaration of a non-imported function template.
-// MSC-DAG: declare dllimport void @"\01??$funcTmpl@UExplicitDecl_Imported@@@@YAXXZ"()
-// MSC-DAG: declare dllimport void @"\01??$inlineFuncTmpl@UExplicitDecl_Imported@@@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"??$funcTmpl@UExplicitDecl_Imported@@@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"??$inlineFuncTmpl@UExplicitDecl_Imported@@@@YAXXZ"()
// GNU-DAG: declare dllimport void @_Z8funcTmplI21ExplicitDecl_ImportedEvv()
-// GNU-DAG: declare void @_Z14inlineFuncTmplI21ExplicitDecl_ImportedEvv()
-// MO1-DAG: define available_externally dllimport void @"\01??$inlineFuncTmpl@UExplicitDecl_Imported@@@@YAXXZ"()
-// GO1-DAG: define available_externally void @_Z14inlineFuncTmplI21ExplicitDecl_ImportedEvv()
+// GNU-DAG: declare dso_local void @_Z14inlineFuncTmplI21ExplicitDecl_ImportedEvv()
+// MO1-DAG: define available_externally dllimport void @"??$inlineFuncTmpl@UExplicitDecl_Imported@@@@YAXXZ"()
+// GO1-DAG: define available_externally dso_local void @_Z14inlineFuncTmplI21ExplicitDecl_ImportedEvv()
extern template __declspec(dllimport) void funcTmpl<ExplicitDecl_Imported>();
extern template __declspec(dllimport) void inlineFuncTmpl<ExplicitDecl_Imported>();
USE(funcTmpl<ExplicitDecl_Imported>)
@@ -575,14 +577,14 @@ USE(inlineFuncTmpl<ExplicitDecl_Imported>)
// Import explicit instantiation definition of a non-imported function template.
-// MSC-DAG: declare dllimport void @"\01??$funcTmpl@UExplicitInst_Imported@@@@YAXXZ"()
-// MSC-DAG: declare dllimport void @"\01??$inlineFuncTmpl@UExplicitInst_Imported@@@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"??$funcTmpl@UExplicitInst_Imported@@@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"??$inlineFuncTmpl@UExplicitInst_Imported@@@@YAXXZ"()
// GNU-DAG: declare dllimport void @_Z8funcTmplI21ExplicitInst_ImportedEvv()
-// GNU-DAG: define weak_odr void @_Z14inlineFuncTmplI21ExplicitInst_ImportedEvv()
-// MO1-DAG: declare dllimport void @"\01??$funcTmpl@UExplicitInst_Imported@@@@YAXXZ"()
-// MO1-DAG: define available_externally dllimport void @"\01??$inlineFuncTmpl@UExplicitInst_Imported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dso_local void @_Z14inlineFuncTmplI21ExplicitInst_ImportedEvv()
+// MO1-DAG: declare dllimport void @"??$funcTmpl@UExplicitInst_Imported@@@@YAXXZ"()
+// MO1-DAG: define available_externally dllimport void @"??$inlineFuncTmpl@UExplicitInst_Imported@@@@YAXXZ"()
// GO1-DAG: define available_externally dllimport void @_Z8funcTmplI21ExplicitInst_ImportedEvv()
-// GO1-DAG: define weak_odr void @_Z14inlineFuncTmplI21ExplicitInst_ImportedEvv()
+// GO1-DAG: define weak_odr dso_local void @_Z14inlineFuncTmplI21ExplicitInst_ImportedEvv()
template __declspec(dllimport) void funcTmpl<ExplicitInst_Imported>();
template __declspec(dllimport) void inlineFuncTmpl<ExplicitInst_Imported>();
USE(funcTmpl<ExplicitInst_Imported>)
@@ -590,22 +592,22 @@ USE(inlineFuncTmpl<ExplicitInst_Imported>)
// Import specialization of a non-imported function template.
-// MSC-DAG: declare dllimport void @"\01??$funcTmpl@UExplicitSpec_Imported@@@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"??$funcTmpl@UExplicitSpec_Imported@@@@YAXXZ"()
// GNU-DAG: declare dllimport void @_Z8funcTmplI21ExplicitSpec_ImportedEvv()
template<> __declspec(dllimport) void funcTmpl<ExplicitSpec_Imported>();
USE(funcTmpl<ExplicitSpec_Imported>)
-// MSC-DAG-FIXME: declare dllimport void @"\01??$funcTmpl@UExplicitSpec_Def_Imported@@@@YAXXZ"()
-// MO1-DAG-FIXME: define available_externally dllimport void @"\01??$funcTmpl@UExplicitSpec_Def_Imported@@@@YAXXZ"()
+// MSC-DAG-FIXME: declare dllimport void @"??$funcTmpl@UExplicitSpec_Def_Imported@@@@YAXXZ"()
+// MO1-DAG-FIXME: define available_externally dllimport void @"??$funcTmpl@UExplicitSpec_Def_Imported@@@@YAXXZ"()
#ifdef MSABI
//template<> __declspec(dllimport) void funcTmpl<ExplicitSpec_Def_Imported>() {}
//USE(funcTmpl<ExplicitSpec_Def_Imported>)
#endif
-// MSC-DAG: declare dllimport void @"\01??$funcTmpl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"()
-// GNU-DAG: define linkonce_odr void @_Z8funcTmplI31ExplicitSpec_InlineDef_ImportedEvv()
-// MO1-DAG: define available_externally dllimport void @"\01??$funcTmpl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"()
-// GO1-DAG: define linkonce_odr void @_Z8funcTmplI31ExplicitSpec_InlineDef_ImportedEvv()
+// MSC-DAG: declare dllimport void @"??$funcTmpl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"()
+// GNU-DAG: define linkonce_odr dso_local void @_Z8funcTmplI31ExplicitSpec_InlineDef_ImportedEvv()
+// MO1-DAG: define available_externally dllimport void @"??$funcTmpl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"()
+// GO1-DAG: define linkonce_odr dso_local void @_Z8funcTmplI31ExplicitSpec_InlineDef_ImportedEvv()
template<> __declspec(dllimport) inline void funcTmpl<ExplicitSpec_InlineDef_Imported>() {}
USE(funcTmpl<ExplicitSpec_InlineDef_Imported>)
@@ -626,22 +628,22 @@ template void S<X>::foo(X*); // Cannot be instantiated because X is incomplete;
struct __declspec(dllimport) T {
void a() {}
- // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?a@T@@QAEXXZ"
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"?a@T@@QAEXXZ"
static void StaticMethod();
- // MSC-DAG: declare dllimport void @"\01?StaticMethod@T@@SAXXZ"()
+ // MSC-DAG: declare dllimport void @"?StaticMethod@T@@SAXXZ"()
// GNU-DAG: declare dllimport void @_ZN1T12StaticMethodEv()
static int b;
- // MO1-DAG: @"\01?b@T@@2HA" = external dllimport global i32
+ // MO1-DAG: @"?b@T@@2HA" = external dllimport global i32
T& operator=(T&) = default;
- // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.T* @"\01??4T@@QAEAAU0@AAU0@@Z"
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.T* @"??4T@@QAEAAU0@AAU0@@Z"
T& operator=(T&&) = default;
// Note: Don't mark inline move operators dllimport because current MSVC versions don't export them.
- // M18-DAG: define linkonce_odr x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.T* @"\01??4T@@QAEAAU0@$$QAU0@@Z"
- // M19-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.T* @"\01??4T@@QAEAAU0@$$QAU0@@Z"
+ // M18-DAG: define linkonce_odr dso_local x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.T* @"??4T@@QAEAAU0@$$QAU0@@Z"
+ // M19-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.T* @"??4T@@QAEAAU0@$$QAU0@@Z"
};
USEMEMFUNC(T, a)
USESTATICMEMFUNC(T, StaticMethod)
@@ -650,14 +652,14 @@ USECOPYASSIGN(T)
USEMOVEASSIGN(T)
template <typename T> struct __declspec(dllimport) U { void foo() {} };
-// MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?foo@?$U@H@@QAEXXZ"
+// MO1-DAG: define available_externally dllimport x86_thiscallcc void @"?foo@?$U@H@@QAEXXZ"
struct __declspec(dllimport) V : public U<int> { };
USEMEMFUNC(V, foo)
struct __declspec(dllimport) W { virtual void foo() {} };
USECLASS(W)
// vftable:
-// MO1-DAG: @"\01??_SW@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast (void (%struct.W*)* @"\01?foo@W@@UAEXXZ" to i8*)] }
+// MO1-DAG: @"??_SW@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast (void (%struct.W*)* @"?foo@W@@UAEXXZ" to i8*)] }
// GO1-DAG: @_ZTV1W = available_externally dllimport unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* null, i8* null, i8* bitcast (void (%struct.W*)* @_ZN1W3fooEv to i8*)] }
struct __declspec(dllimport) KeyFuncClass {
@@ -670,7 +672,7 @@ extern constexpr KeyFuncClass keyFuncClassVar = {};
struct __declspec(dllimport) X : public virtual W {};
USECLASS(X)
// vbtable:
-// MO1-DAG: @"\01??_8X@@7B@" = available_externally dllimport unnamed_addr constant [2 x i32] [i32 0, i32 4]
+// MO1-DAG: @"??_8X@@7B@" = available_externally dllimport unnamed_addr constant [2 x i32] [i32 0, i32 4]
struct __declspec(dllimport) Y {
int x;
@@ -679,7 +681,7 @@ struct __declspec(dllimport) Y {
struct __declspec(dllimport) Z { virtual ~Z() {} };
USECLASS(Z)
// User-defined dtor:
-// MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01??1Z@@UAE@XZ"
+// MO1-DAG: define available_externally dllimport x86_thiscallcc void @"??1Z@@UAE@XZ"
namespace DontUseDtorAlias {
struct __declspec(dllimport) A { ~A(); };
@@ -687,13 +689,13 @@ namespace DontUseDtorAlias {
inline A::~A() { }
inline B::~B() { }
// Emit a real definition of B's constructor; don't alias it to A's.
- // MO1-DAG: available_externally dllimport x86_thiscallcc void @"\01??1B@DontUseDtorAlias@@QAE@XZ"
+ // MO1-DAG: available_externally dllimport x86_thiscallcc void @"??1B@DontUseDtorAlias@@QAE@XZ"
USECLASS(B)
}
namespace Vtordisp {
// Don't dllimport the vtordisp.
- // MO1-DAG: define linkonce_odr x86_thiscallcc void @"\01?f@?$C@H@Vtordisp@@$4PPPPPPPM@A@AEXXZ"
+ // MO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @"?f@?$C@H@Vtordisp@@$4PPPPPPPM@A@AEXXZ"
class __declspec(dllimport) Base {
virtual void f() {}
@@ -713,7 +715,7 @@ namespace ClassTemplateStaticDef {
static int x;
};
template <typename T> int S<T>::x;
- // MSC-DAG: @"\01?x@?$S@H@ClassTemplateStaticDef@@2HA" = external dllimport global i32
+ // MSC-DAG: @"?x@?$S@H@ClassTemplateStaticDef@@2HA" = external dllimport global i32
int f() { return S<int>::x; }
// Partial class template specialization static field:
@@ -736,21 +738,21 @@ namespace PR19933 {
template <typename T> NonPOD A<T>::x;
template struct __declspec(dllimport) A<int>;
USEVARTYPE(NonPOD, A<int>::x);
- // MSC-DAG: @"\01?x@?$A@H@PR19933@@2UNonPOD@2@A" = external dllimport global %"struct.PR19933::NonPOD"
+ // MSC-DAG: @"?x@?$A@H@PR19933@@2UNonPOD@2@A" = external dllimport global %"struct.PR19933::NonPOD"
int f();
template <typename T> struct B { static int x; };
template <typename T> int B<T>::x = f();
template struct __declspec(dllimport) B<int>;
USEVAR(B<int>::x);
- // MSC-DAG: @"\01?x@?$B@H@PR19933@@2HA" = external dllimport global i32
+ // MSC-DAG: @"?x@?$B@H@PR19933@@2HA" = external dllimport global i32
constexpr int g() { return 42; }
template <typename T> struct C { static int x; };
template <typename T> int C<T>::x = g();
template struct __declspec(dllimport) C<int>;
USEVAR(C<int>::x);
- // MSC-DAG: @"\01?x@?$C@H@PR19933@@2HA" = external dllimport global i32
+ // MSC-DAG: @"?x@?$C@H@PR19933@@2HA" = external dllimport global i32
template <int I> struct D { static int x, y; };
template <int I> int D<I>::x = I + 1;
@@ -758,8 +760,8 @@ namespace PR19933 {
template struct __declspec(dllimport) D<42>;
USEVAR(D<42>::x);
USEVAR(D<42>::y);
- // MSC-DAG: @"\01?x@?$D@$0CK@@PR19933@@2HA" = external dllimport global i32
- // MSC-DAG: @"\01?y@?$D@$0CK@@PR19933@@2HA" = external dllimport global i32
+ // MSC-DAG: @"?x@?$D@$0CK@@PR19933@@2HA" = external dllimport global i32
+ // MSC-DAG: @"?y@?$D@$0CK@@PR19933@@2HA" = external dllimport global i32
}
namespace PR21355 {
@@ -793,59 +795,59 @@ namespace PR27319 {
};
extern template struct __declspec(dllimport) A<int>;
void f() { new A<int>(); }
- // MO1-DAG: @"\01??_S?$A@H@PR27319@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] }
+ // MO1-DAG: @"??_S?$A@H@PR27319@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] }
}
// MS ignores DLL attributes on partial specializations.
template <typename T> struct PartiallySpecializedClassTemplate {};
template <typename T> struct __declspec(dllimport) PartiallySpecializedClassTemplate<T*> { void f(); };
USEMEMFUNC(PartiallySpecializedClassTemplate<void*>, f);
-// M32-DAG: declare x86_thiscallcc void @"\01?f@?$PartiallySpecializedClassTemplate@PAX@@QAEXXZ"
+// M32-DAG: declare dso_local x86_thiscallcc void @"?f@?$PartiallySpecializedClassTemplate@PAX@@QAEXXZ"
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN33PartiallySpecializedClassTemplateIPvE1fEv
// Attributes on explicit specializations are honored.
template <typename T> struct ExplicitlySpecializedClassTemplate {};
template <> struct __declspec(dllimport) ExplicitlySpecializedClassTemplate<void*> { void f(); };
USEMEMFUNC(ExplicitlySpecializedClassTemplate<void*>, f);
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01?f@?$ExplicitlySpecializedClassTemplate@PAX@@QAEXXZ"
+// M32-DAG: declare dllimport x86_thiscallcc void @"?f@?$ExplicitlySpecializedClassTemplate@PAX@@QAEXXZ"
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN34ExplicitlySpecializedClassTemplateIPvE1fEv
// MS inherits DLL attributes to partial specializations.
template <typename T> struct __declspec(dllimport) PartiallySpecializedImportedClassTemplate {};
template <typename T> struct PartiallySpecializedImportedClassTemplate<T*> { void f() {} };
USEMEMFUNC(PartiallySpecializedImportedClassTemplate<void*>, f);
-// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?f@?$PartiallySpecializedImportedClassTemplate@PAX@@QAEXXZ"
-// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN41PartiallySpecializedImportedClassTemplateIPvE1fEv
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"?f@?$PartiallySpecializedImportedClassTemplate@PAX@@QAEXXZ"
+// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN41PartiallySpecializedImportedClassTemplateIPvE1fEv
// Attributes on the instantiation take precedence over attributes on the template.
template <typename T> struct __declspec(dllexport) ExplicitlyInstantiatedWithDifferentAttr { void f() {} };
template struct __declspec(dllimport) ExplicitlyInstantiatedWithDifferentAttr<int>;
USEMEMFUNC(ExplicitlyInstantiatedWithDifferentAttr<int>, f);
-// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?f@?$ExplicitlyInstantiatedWithDifferentAttr@H@@QAEXXZ"
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"?f@?$ExplicitlyInstantiatedWithDifferentAttr@H@@QAEXXZ"
template <typename T> struct ExplicitInstantiationDeclImportedDefTemplate { void f() {} ExplicitInstantiationDeclImportedDefTemplate() {}};
extern template struct ExplicitInstantiationDeclImportedDefTemplate<int>;
template struct __declspec(dllimport) ExplicitInstantiationDeclImportedDefTemplate<int>;
USECLASS(ExplicitInstantiationDeclImportedDefTemplate<int>);
USEMEMFUNC(ExplicitInstantiationDeclImportedDefTemplate<int>, f);
-// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?f@?$ExplicitInstantiationDeclImportedDefTemplate@H@@QAEXXZ"
-// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc %struct.ExplicitInstantiationDeclImportedDefTemplate* @"\01??0?$ExplicitInstantiationDeclImportedDefTemplate@H@@QAE@XZ"
-// G32-DAG: define weak_odr x86_thiscallcc void @_ZN44ExplicitInstantiationDeclImportedDefTemplateIiE1fEv
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"?f@?$ExplicitInstantiationDeclImportedDefTemplate@H@@QAEXXZ"
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc %struct.ExplicitInstantiationDeclImportedDefTemplate* @"??0?$ExplicitInstantiationDeclImportedDefTemplate@H@@QAE@XZ"
+// G32-DAG: define weak_odr dso_local x86_thiscallcc void @_ZN44ExplicitInstantiationDeclImportedDefTemplateIiE1fEv
template <typename T> struct __declspec(dllimport) ExplicitInstantiationDeclExportedDefImportedTemplate { void f() {} ExplicitInstantiationDeclExportedDefImportedTemplate() {} };
extern template struct __declspec(dllimport) ExplicitInstantiationDeclExportedDefImportedTemplate <int>;
template struct __declspec(dllexport) ExplicitInstantiationDeclExportedDefImportedTemplate<int>;
USECLASS(ExplicitInstantiationDeclExportedDefImportedTemplate<int>);
USEMEMFUNC(ExplicitInstantiationDeclExportedDefImportedTemplate<int>, f);
-// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?f@?$ExplicitInstantiationDeclExportedDefImportedTemplate@H@@QAEXXZ"
-// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc %struct.ExplicitInstantiationDeclExportedDefImportedTemplate* @"\01??0?$ExplicitInstantiationDeclExportedDefImportedTemplate@H@@QAE@XZ"
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"?f@?$ExplicitInstantiationDeclExportedDefImportedTemplate@H@@QAEXXZ"
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc %struct.ExplicitInstantiationDeclExportedDefImportedTemplate* @"??0?$ExplicitInstantiationDeclExportedDefImportedTemplate@H@@QAE@XZ"
template <typename T> struct PR23770BaseTemplate { void f() {} };
template <typename T> struct PR23770DerivedTemplate : PR23770BaseTemplate<int> {};
extern template struct PR23770DerivedTemplate<int>;
template struct __declspec(dllimport) PR23770DerivedTemplate<int>;
USEMEMFUNC(PR23770BaseTemplate<int>, f);
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01?f@?$PR23770BaseTemplate@H@@QAEXXZ"
+// M32-DAG: declare dllimport x86_thiscallcc void @"?f@?$PR23770BaseTemplate@H@@QAEXXZ"
namespace PR27810 {
template <class T>
@@ -861,7 +863,7 @@ namespace PR27810 {
// functions are emitted unless they are used.
USEMEMFUNC(basic_ostream<char>::sentry, foo);
- // M32-DAG: define linkonce_odr x86_thiscallcc void @"\01?foo@sentry@?$basic_ostream@D@PR27810@@QAEXXZ"
+ // M32-DAG: define linkonce_odr dso_local x86_thiscallcc void @"?foo@sentry@?$basic_ostream@D@PR27810@@QAEXXZ"
// M32-NOT: ??0sentry@?$basic_ostream@D@PR27810@@QAE@XZ
}
@@ -906,69 +908,69 @@ template struct __declspec(dllimport) ExplicitlyImportInstantiatedTemplate<int>;
// MS: ClassTemplate<int> gets imported.
struct __declspec(dllimport) DerivedFromTemplate : public ClassTemplate<int> {};
USEMEMFUNC(ClassTemplate<int>, func)
-// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ClassTemplate@H@@QAEXXZ"
-// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ClassTemplateIiE4funcEv
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"?func@?$ClassTemplate@H@@QAEXXZ"
+// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ClassTemplateIiE4funcEv
// ImportedTemplate is explicitly imported.
struct __declspec(dllimport) DerivedFromImportedTemplate : public ImportedClassTemplate<int> {};
USEMEMFUNC(ImportedClassTemplate<int>, func)
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01?func@?$ImportedClassTemplate@H@@QAEXXZ"
+// M32-DAG: declare dllimport x86_thiscallcc void @"?func@?$ImportedClassTemplate@H@@QAEXXZ"
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN21ImportedClassTemplateIiE4funcEv
// ExportedTemplate is explicitly exported.
struct __declspec(dllimport) DerivedFromExportedTemplate : public ExportedClassTemplate<int> {};
USEMEMFUNC(ExportedClassTemplate<int>, func)
-// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ExportedClassTemplate@H@@QAEXXZ"
-// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN21ExportedClassTemplateIiE4funcEv
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?func@?$ExportedClassTemplate@H@@QAEXXZ"
+// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN21ExportedClassTemplateIiE4funcEv
// Base class already implicitly instantiated without attribute.
struct DerivedFromTemplateD : public ClassTemplate<double> {};
struct __declspec(dllimport) DerivedFromTemplateD2 : public ClassTemplate<double> {};
USEMEMFUNC(ClassTemplate<double>, func)
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01?func@?$ClassTemplate@N@@QAEXXZ"
-// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ClassTemplateIdE4funcEv
+// M32-DAG: declare dllimport x86_thiscallcc void @"?func@?$ClassTemplate@N@@QAEXXZ"
+// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ClassTemplateIdE4funcEv
// MS: Base class already instantiated with dfferent attribute.
struct __declspec(dllexport) DerivedFromTemplateB : public ClassTemplate<bool> {};
struct __declspec(dllimport) DerivedFromTemplateB2 : public ClassTemplate<bool> {};
USEMEMFUNC(ClassTemplate<bool>, func)
-// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ClassTemplate@_N@@QAEXXZ"
-// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ClassTemplateIbE4funcEv
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?func@?$ClassTemplate@_N@@QAEXXZ"
+// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ClassTemplateIbE4funcEv
// Base class already specialized without dll attribute.
struct __declspec(dllimport) DerivedFromExplicitlySpecializedTemplate : public ExplicitlySpecializedTemplate<int> {};
USEMEMFUNC(ExplicitlySpecializedTemplate<int>, func)
-// M32-DAG: define linkonce_odr x86_thiscallcc void @"\01?func@?$ExplicitlySpecializedTemplate@H@@QAEXXZ"
-// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN29ExplicitlySpecializedTemplateIiE4funcEv
+// M32-DAG: define linkonce_odr dso_local x86_thiscallcc void @"?func@?$ExplicitlySpecializedTemplate@H@@QAEXXZ"
+// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN29ExplicitlySpecializedTemplateIiE4funcEv
// Base class alredy specialized with export attribute.
struct __declspec(dllimport) DerivedFromExplicitlyExportSpecializedTemplate : public ExplicitlyExportSpecializedTemplate<int> {};
USEMEMFUNC(ExplicitlyExportSpecializedTemplate<int>, func)
-// M32-DAG: define dllexport x86_thiscallcc void @"\01?func@?$ExplicitlyExportSpecializedTemplate@H@@QAEXXZ"
-// G32-DAG: define dllexport x86_thiscallcc void @_ZN35ExplicitlyExportSpecializedTemplateIiE4funcEv
+// M32-DAG: define dso_local dllexport x86_thiscallcc void @"?func@?$ExplicitlyExportSpecializedTemplate@H@@QAEXXZ"
+// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN35ExplicitlyExportSpecializedTemplateIiE4funcEv
// Base class already specialized with import attribute.
struct __declspec(dllimport) DerivedFromExplicitlyImportSpecializedTemplate : public ExplicitlyImportSpecializedTemplate<int> {};
USEMEMFUNC(ExplicitlyImportSpecializedTemplate<int>, func)
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01?func@?$ExplicitlyImportSpecializedTemplate@H@@QAEXXZ"
+// M32-DAG: declare dllimport x86_thiscallcc void @"?func@?$ExplicitlyImportSpecializedTemplate@H@@QAEXXZ"
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN35ExplicitlyImportSpecializedTemplateIiE4funcEv
// Base class already instantiated without dll attribute.
struct __declspec(dllimport) DerivedFromExplicitlyInstantiatedTemplate : public ExplicitlyInstantiatedTemplate<int> {};
USEMEMFUNC(ExplicitlyInstantiatedTemplate<int>, func)
-// M32-DAG: define weak_odr x86_thiscallcc void @"\01?func@?$ExplicitlyInstantiatedTemplate@H@@QAEXXZ"
-// G32-DAG: define weak_odr x86_thiscallcc void @_ZN30ExplicitlyInstantiatedTemplateIiE4funcEv
+// M32-DAG: define weak_odr dso_local x86_thiscallcc void @"?func@?$ExplicitlyInstantiatedTemplate@H@@QAEXXZ"
+// G32-DAG: define weak_odr dso_local x86_thiscallcc void @_ZN30ExplicitlyInstantiatedTemplateIiE4funcEv
// Base class already instantiated with export attribute.
struct __declspec(dllimport) DerivedFromExplicitlyExportInstantiatedTemplate : public ExplicitlyExportInstantiatedTemplate<int> {};
USEMEMFUNC(ExplicitlyExportInstantiatedTemplate<int>, func)
-// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ExplicitlyExportInstantiatedTemplate@H@@QAEXXZ"
-// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN36ExplicitlyExportInstantiatedTemplateIiE4funcEv
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?func@?$ExplicitlyExportInstantiatedTemplate@H@@QAEXXZ"
+// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN36ExplicitlyExportInstantiatedTemplateIiE4funcEv
// Base class already instantiated with import attribute.
struct __declspec(dllimport) DerivedFromExplicitlyImportInstantiatedTemplate : public ExplicitlyImportInstantiatedTemplate<int> {};
USEMEMFUNC(ExplicitlyImportInstantiatedTemplate<int>, func)
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01?func@?$ExplicitlyImportInstantiatedTemplate@H@@QAEXXZ"
+// M32-DAG: declare dllimport x86_thiscallcc void @"?func@?$ExplicitlyImportInstantiatedTemplate@H@@QAEXXZ"
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN36ExplicitlyImportInstantiatedTemplateIiE4funcEv
// MS: A dll attribute propagates through multiple levels of instantiation.
@@ -976,21 +978,21 @@ template <typename T> struct TopClass { void func() {} };
template <typename T> struct MiddleClass : public TopClass<T> { };
struct __declspec(dllimport) BottomClass : public MiddleClass<int> { };
USEMEMFUNC(TopClass<int>, func)
-// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$TopClass@H@@QAEXXZ"
-// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN8TopClassIiE4funcEv
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"?func@?$TopClass@H@@QAEXXZ"
+// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN8TopClassIiE4funcEv
template <typename T> struct ExplicitInstantiationDeclTemplateBase { void func() {} };
extern template struct ExplicitInstantiationDeclTemplateBase<int>;
struct __declspec(dllimport) DerivedFromExplicitInstantiationDeclTemplateBase : public ExplicitInstantiationDeclTemplateBase<int> {};
template struct ExplicitInstantiationDeclTemplateBase<int>;
USEMEMFUNC(ExplicitInstantiationDeclTemplateBase<int>, func)
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01?func@?$ExplicitInstantiationDeclTemplateBase@H@@QAEXXZ"
-// G32-DAG: define weak_odr x86_thiscallcc void @_ZN37ExplicitInstantiationDeclTemplateBaseIiE4funcEv
+// M32-DAG: declare dllimport x86_thiscallcc void @"?func@?$ExplicitInstantiationDeclTemplateBase@H@@QAEXXZ"
+// G32-DAG: define weak_odr dso_local x86_thiscallcc void @_ZN37ExplicitInstantiationDeclTemplateBaseIiE4funcEv
template <typename T> struct ExplicitInstantiationDeclTemplateBase2 { void func() {} };
extern template struct ExplicitInstantiationDeclTemplateBase2<int>;
struct __declspec(dllimport) DerivedFromExplicitInstantiationDeclTemplateBase2 : public ExplicitInstantiationDeclTemplateBase2<int> {};
template struct __declspec(dllexport) ExplicitInstantiationDeclTemplateBase2<int>;
USEMEMFUNC(ExplicitInstantiationDeclTemplateBase2<int>, func)
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01?func@?$ExplicitInstantiationDeclTemplateBase2@H@@QAEXXZ"
-// G32-DAG: define weak_odr x86_thiscallcc void @_ZN38ExplicitInstantiationDeclTemplateBase2IiE4funcEv
+// M32-DAG: declare dllimport x86_thiscallcc void @"?func@?$ExplicitInstantiationDeclTemplateBase2@H@@QAEXXZ"
+// G32-DAG: define weak_odr dso_local x86_thiscallcc void @_ZN38ExplicitInstantiationDeclTemplateBase2IiE4funcEv
diff --git a/test/CodeGenCXX/dso-local-executable.cpp b/test/CodeGenCXX/dso-local-executable.cpp
new file mode 100644
index 000000000000..cc8d50f09c9e
--- /dev/null
+++ b/test/CodeGenCXX/dso-local-executable.cpp
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -triple x86_64-pc-linux -mrelocation-model static -O1 -emit-llvm %s -o - | FileCheck --check-prefix=STATIC %s
+// RUN: %clang_cc1 -triple x86_64-pc-linux -mrelocation-model static -fno-plt -O1 -emit-llvm %s -o - | FileCheck --check-prefix=NOPLT %s
+
+// STATIC-DAG: @_ZTV1C = linkonce_odr dso_local unnamed_addr constant
+// STATIC-DAG: @_ZTS1C = linkonce_odr dso_local constant
+// STATIC-DAG: @_ZTI1C = linkonce_odr dso_local constant
+// STATIC-DAG: @_ZZ14useStaticLocalvE3obj = linkonce_odr dso_local global
+// STATIC-DAG: @_ZGVZN5guard1gEvE1a = linkonce_odr dso_local global
+// STATIC-DAG: define dso_local void @_ZN1CC2Ev(
+// STATIC-DAG: define dso_local void @_ZN1CC1Ev(
+// STATIC-DAG: define linkonce_odr dso_local void @_ZN1C3fooEv(
+
+// NOPLT-DAG: @_ZTV1C = linkonce_odr dso_local unnamed_addr constant
+// NOPLT-DAG: @_ZTS1C = linkonce_odr dso_local constant
+// NOPLT-DAG: @_ZTI1C = linkonce_odr dso_local constant
+// NOPLT-DAG: @_ZZ14useStaticLocalvE3obj = linkonce_odr dso_local global
+// NOPLT-DAG: @_ZGVZN5guard1gEvE1a = linkonce_odr dso_local global
+// NOPLT-DAG: define dso_local void @_ZN1CC2Ev(
+// NOPLT-DAG: define dso_local void @_ZN1CC1Ev(
+// NOPLT-DAG: define linkonce_odr dso_local void @_ZN1C3fooEv(
+
+struct C {
+ C();
+ virtual void foo() {}
+};
+C::C() {}
+
+struct HasVTable {
+ virtual void f();
+};
+inline HasVTable &useStaticLocal() {
+ static HasVTable obj;
+ return obj;
+}
+void useit() {
+ useStaticLocal();
+}
+
+namespace guard {
+int f();
+inline int g() {
+ static int a = f();
+ return a;
+}
+int h() {
+ return g();
+}
+} // namespace guard
+
+
+// STATIC-DAG: define available_externally dso_local void @_ZN5test23barIcEC1Ev(
+// NOPLT-DAG: define available_externally void @_ZN5test23barIcEC1Ev(
+namespace test2 {
+void foo();
+template <typename T>
+struct bar {
+ virtual void zed();
+ bar() { foo(); }
+};
+extern template class bar<char>;
+bar<char> abc;
+} // namespace test2
diff --git a/test/CodeGenCXX/duplicate-mangled-name.cpp b/test/CodeGenCXX/duplicate-mangled-name.cpp
index 8c8f6e0311c3..741e021db984 100644
--- a/test/CodeGenCXX/duplicate-mangled-name.cpp
+++ b/test/CodeGenCXX/duplicate-mangled-name.cpp
@@ -11,7 +11,7 @@ class MyClass {
};
void MyClass::meth() { } // expected-note {{previous}}
extern "C" {
- void _ZN7MyClass4methEv() { } // expected-error {{definition with same mangled name as another definition}}
+ void _ZN7MyClass4methEv() { } // expected-error {{definition with same mangled name '_ZN7MyClass4methEv' as another definition}}
}
#elif TEST2
@@ -34,7 +34,7 @@ extern "C" {
namespace nm {
float abc = 2;
}
-// CHECK: @_ZN2nm3abcE = global float
+// CHECK: @_ZN2nm3abcE = {{(dso_local )?}}global float
float foo() {
_ZN1TD1Ev();
@@ -49,7 +49,7 @@ float foo() {
extern "C" void _ZN2T2D2Ev() {}; // expected-note {{previous definition is here}}
struct T2 {
- ~T2() {} // expected-error {{definition with same mangled name as another definition}}
+ ~T2() {} // expected-error {{definition with same mangled name '_ZN2T2D2Ev' as another definition}}
};
void foo() {
@@ -64,7 +64,7 @@ extern "C" {
}
namespace nm {
- float abc = 2; // expected-error {{definition with same mangled name as another definition}}
+ float abc = 2; // expected-error {{definition with same mangled name '_ZN2nm3abcE' as another definition}}
}
float foo() {
@@ -73,7 +73,7 @@ float foo() {
#else
-#error Unknwon test
+#error Unknown test
#endif
diff --git a/test/CodeGenCXX/eh.cpp b/test/CodeGenCXX/eh.cpp
index dfbe48c37239..d393ee13b1ca 100644
--- a/test/CodeGenCXX/eh.cpp
+++ b/test/CodeGenCXX/eh.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -triple x86_64-apple-darwin -std=c++11 -emit-llvm %s -o %t.ll
-// RUN: FileCheck --input-file=%t.ll %s
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -triple x86_64-apple-darwin -std=c++11 -emit-llvm %s -o - \
+// RUN: | FileCheck %s
struct test1_D {
double d;
@@ -13,7 +13,7 @@ void test1() {
// CHECK: [[EXNOBJ:%.*]] = call i8* @__cxa_allocate_exception(i64 8)
// CHECK-NEXT: [[EXN:%.*]] = bitcast i8* [[EXNOBJ]] to [[DSTAR:%[^*]*\*]]
// CHECK-NEXT: [[EXN2:%.*]] = bitcast [[DSTAR]] [[EXN]] to i8*
-// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[EXN2]], i8* bitcast ([[DSTAR]] @d1 to i8*), i64 8, i32 8, i1 false)
+// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[EXN2]], i8* align 8 bitcast ([[DSTAR]] @d1 to i8*), i64 8, i1 false)
// CHECK-NEXT: call void @__cxa_throw(i8* [[EXNOBJ]], i8* bitcast ({ i8*, i8* }* @_ZTI7test1_D to i8*), i8* null) [[NR:#[0-9]+]]
// CHECK-NEXT: unreachable
@@ -466,7 +466,7 @@ int foo() {
// CHECK: [[T0:%.*]] = call i8* @__cxa_allocate_exception(i64 16)
// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to %"class.test17::DerivedException"*
// CHECK-NEXT: [[T2:%.*]] = bitcast %"class.test17::DerivedException"* [[T1]] to i8*
- // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T2]], i8 0, i64 16, i32 16, i1 false)
+ // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 16 [[T2]], i8 0, i64 16, i1 false)
}
}
diff --git a/test/CodeGenCXX/exceptions-cxx-ehsc.cpp b/test/CodeGenCXX/exceptions-cxx-ehsc.cpp
index c660d145393a..ae1f463d386c 100644
--- a/test/CodeGenCXX/exceptions-cxx-ehsc.cpp
+++ b/test/CodeGenCXX/exceptions-cxx-ehsc.cpp
@@ -11,9 +11,9 @@ void caller() {
may_throw();
}
}
-// CHECK-LABEL: define void @"\01?caller@test1@@YAXXZ"(
+// CHECK-LABEL: define dso_local void @"?caller@test1@@YAXXZ"(
// CHECK: call void @never_throws(
-// CHECK: invoke void @"\01?may_throw@test1@@YAXXZ"(
+// CHECK: invoke void @"?may_throw@test1@@YAXXZ"(
namespace test2 {
struct Cleanup { ~Cleanup(); };
@@ -26,6 +26,6 @@ void caller() {
may_throw();
}
}
-// CHECK-LABEL: define void @"\01?caller@test2@@YAXXZ"(
+// CHECK-LABEL: define dso_local void @"?caller@test2@@YAXXZ"(
// CHECK: invoke void @throws_int(
-// CHECK: invoke void @"\01?may_throw@test2@@YAXXZ"(
+// CHECK: invoke void @"?may_throw@test2@@YAXXZ"(
diff --git a/test/CodeGenCXX/exceptions-cxx-new.cpp b/test/CodeGenCXX/exceptions-cxx-new.cpp
index 9836da8e540b..4906a7b19098 100644
--- a/test/CodeGenCXX/exceptions-cxx-new.cpp
+++ b/test/CodeGenCXX/exceptions-cxx-new.cpp
@@ -12,16 +12,16 @@ void test_catch() {
}
}
-// CHECK-LABEL: define void @"\01?test_catch@@YAXXZ"(
-// CHECK: invoke i32 @"\01?f@@YAHH@Z"(i32 1)
+// CHECK-LABEL: define dso_local void @"?test_catch@@YAXXZ"(
+// CHECK: invoke i32 @"?f@@YAHH@Z"(i32 1)
// CHECK: to label %[[NORMAL:.*]] unwind label %[[CATCHSWITCH:.*]]
// CHECK: [[CATCHSWITCH]]
// CHECK: %[[CATCHSWITCHPAD:.*]] = catchswitch within none [label %[[CATCH_INT:.*]], label %[[CATCH_DOUBLE:.*]]] unwind to caller
// CHECK: [[CATCH_INT]]
-// CHECK: %[[CATCHPAD_INT:.*]] = catchpad within %[[CATCHSWITCHPAD]] [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
-// CHECK: call i32 @"\01?f@@YAHH@Z"(i32 2)
+// CHECK: %[[CATCHPAD_INT:.*]] = catchpad within %[[CATCHSWITCHPAD]] [%rtti.TypeDescriptor2* @"??_R0H@8", i32 0, i8* null]
+// CHECK: call i32 @"?f@@YAHH@Z"(i32 2)
// CHECK: catchret from %[[CATCHPAD_INT]] to label %[[LEAVE_INT_CATCH:.*]]
// CHECK: [[LEAVE_INT_CATCH]]
@@ -31,8 +31,8 @@ void test_catch() {
// CHECK: ret void
// CHECK: [[CATCH_DOUBLE]]
-// CHECK: %[[CATCHPAD_DOUBLE:.*]] = catchpad within %[[CATCHSWITCHPAD]] [%rtti.TypeDescriptor2* @"\01??_R0N@8", i32 0, i8* null]
-// CHECK: call i32 @"\01?f@@YAHH@Z"(i32 3)
+// CHECK: %[[CATCHPAD_DOUBLE:.*]] = catchpad within %[[CATCHSWITCHPAD]] [%rtti.TypeDescriptor2* @"??_R0N@8", i32 0, i8* null]
+// CHECK: call i32 @"?f@@YAHH@Z"(i32 3)
// CHECK: catchret from %[[CATCHPAD_DOUBLE]] to label %[[LEAVE_DOUBLE_CATCH:.*]]
// CHECK: [[LEAVE_DOUBLE_CATCH]]
@@ -50,22 +50,22 @@ void test_cleanup() {
f(1);
}
-// CHECK-LABEL: define {{.*}} @"\01?test_cleanup@@YAXXZ"(
-// CHECK: invoke i32 @"\01?f@@YAHH@Z"(i32 1)
+// CHECK-LABEL: define dso_local {{.*}} @"?test_cleanup@@YAXXZ"(
+// CHECK: invoke i32 @"?f@@YAHH@Z"(i32 1)
// CHECK: to label %[[LEAVE_FUNC:.*]] unwind label %[[CLEANUP:.*]]
// CHECK: [[LEAVE_FUNC]]
-// CHECK: call x86_thiscallcc void @"\01??_DCleanup@@QAEXXZ"(
+// CHECK: call x86_thiscallcc void @"??1Cleanup@@QAE@XZ"(
// CHECK: ret void
// CHECK: [[CLEANUP]]
// CHECK: %[[CLEANUPPAD:.*]] = cleanuppad within none []
-// CHECK: call x86_thiscallcc void @"\01??_DCleanup@@QAEXXZ"(
+// CHECK: call x86_thiscallcc void @"??1Cleanup@@QAE@XZ"(
// CHECK: cleanupret from %[[CLEANUPPAD]] unwind to caller
-// CHECK-LABEL: define {{.*}} void @"\01??1Cleanup@@QAE@XZ"(
-// CHECK: invoke i32 @"\01?f@@YAHH@Z"(i32 -1)
+// CHECK-LABEL: define {{.*}} void @"??1Cleanup@@QAE@XZ"(
+// CHECK: invoke i32 @"?f@@YAHH@Z"(i32 -1)
// CHECK: to label %[[LEAVE_FUNC:.*]] unwind label %[[TERMINATE:.*]]
// CHECK: [[LEAVE_FUNC]]
@@ -73,5 +73,5 @@ void test_cleanup() {
// CHECK: [[TERMINATE]]
// CHECK: %[[CLEANUPPAD:.*]] = cleanuppad within none []
-// CHECK-NEXT: call void @"\01?terminate@@YAXXZ"() {{.*}} [ "funclet"(token %[[CLEANUPPAD]]) ]
+// CHECK-NEXT: call void @"?terminate@@YAXXZ"() {{.*}} [ "funclet"(token %[[CLEANUPPAD]]) ]
diff --git a/test/CodeGenCXX/exceptions-seh-filter-captures.cpp b/test/CodeGenCXX/exceptions-seh-filter-captures.cpp
index ab75a87698ab..0e9766220828 100644
--- a/test/CodeGenCXX/exceptions-seh-filter-captures.cpp
+++ b/test/CodeGenCXX/exceptions-seh-filter-captures.cpp
@@ -14,19 +14,19 @@ extern "C" void test_freefunc(int p1) {
}
}
-// CHECK-LABEL: define void @test_freefunc(i32 %p1)
+// CHECK-LABEL: define dso_local void @test_freefunc(i32 %p1)
// CHECK: @llvm.localescape(i32* %[[p1_ptr:[^, ]*]], i32* %[[l1_ptr:[^, ]*]])
// CHECK: store i32 %p1, i32* %[[p1_ptr]], align 4
// CHECK: store i32 13, i32* %[[l1_ptr]], align 4
// CHECK: invoke void @might_crash()
-// CHECK-LABEL: define internal i32 @"\01?filt$0@0@test_freefunc@@"(i8* %exception_pointers, i8* %frame_pointer)
+// CHECK-LABEL: define internal i32 @"?filt$0@0@test_freefunc@@"(i8* %exception_pointers, i8* %frame_pointer)
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %frame_pointer)
// CHECK: %[[p1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %[[fp]], i32 0)
// CHECK: %[[p1_ptr:[^ ]*]] = bitcast i8* %[[p1_i8]] to i32*
// CHECK: %[[l1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %[[fp]], i32 1)
// CHECK: %[[l1_ptr:[^ ]*]] = bitcast i8* %[[l1_i8]] to i32*
-// CHECK: %[[s1:[^ ]*]] = load i32, i32* @"\01?s1@?1??test_freefunc@@9@4HA", align 4
+// CHECK: %[[s1:[^ ]*]] = load i32, i32* @"?s1@?1??test_freefunc@@9@4HA", align 4
// CHECK: %[[l1:[^ ]*]] = load i32, i32* %[[l1_ptr]]
// CHECK: %[[p1:[^ ]*]] = load i32, i32* %[[p1_ptr]]
// CHECK: call i32 (i32, ...) @basic_filter(i32 %[[p1]], i32 %[[l1]], i32 %[[s1]])
@@ -45,14 +45,14 @@ void S::test_method() {
}
}
-// CHECK-LABEL: define void @"\01?test_method@S@@QEAAXXZ"(%struct.S* %this)
+// CHECK-LABEL: define dso_local void @"?test_method@S@@QEAAXXZ"(%struct.S* %this)
// CHECK: @llvm.localescape(i32* %[[l1_addr:[^, ]*]])
// CHECK: store i32 13, i32* %[[l1_addr]], align 4
// CHECK: invoke void @might_crash()
-// CHECK-LABEL: define internal i32 @"\01?filt$0@0@test_method@S@@"(i8* %exception_pointers, i8* %frame_pointer)
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void (%struct.S*)* @"\01?test_method@S@@QEAAXXZ" to i8*), i8* %frame_pointer)
-// CHECK: %[[l1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%struct.S*)* @"\01?test_method@S@@QEAAXXZ" to i8*), i8* %[[fp]], i32 0)
+// CHECK-LABEL: define internal i32 @"?filt$0@0@test_method@S@@"(i8* %exception_pointers, i8* %frame_pointer)
+// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void (%struct.S*)* @"?test_method@S@@QEAAXXZ" to i8*), i8* %frame_pointer)
+// CHECK: %[[l1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%struct.S*)* @"?test_method@S@@QEAAXXZ" to i8*), i8* %[[fp]], i32 0)
// CHECK: %[[l1_ptr:[^ ]*]] = bitcast i8* %[[l1_i8]] to i32*
// CHECK: %[[l1:[^ ]*]] = load i32, i32* %[[l1_ptr]]
// CHECK: call i32 (i32, ...) @basic_filter(i32 %[[l1]])
@@ -70,14 +70,14 @@ void test_lambda() {
lambda();
}
-// CHECK-LABEL: define internal void @"\01??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ"(%class.anon* %this)
+// CHECK-LABEL: define internal void @"??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ"(%class.anon* %this)
// CHECK: @llvm.localescape(i32* %[[l2_addr:[^, ]*]])
// CHECK: store i32 42, i32* %[[l2_addr]], align 4
// CHECK: invoke void @might_crash()
-// CHECK-LABEL: define internal i32 @"\01?filt$0@0@?R<lambda_0>@?0??test_lambda@@YAXXZ@"(i8* %exception_pointers, i8* %frame_pointer)
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void (%class.anon*)* @"\01??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ" to i8*), i8* %frame_pointer)
-// CHECK: %[[l2_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%class.anon*)* @"\01??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ" to i8*), i8* %[[fp]], i32 0)
+// CHECK-LABEL: define internal i32 @"?filt$0@0@?R<lambda_0>@?0??test_lambda@@YAXXZ@"(i8* %exception_pointers, i8* %frame_pointer)
+// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void (%class.anon*)* @"??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ" to i8*), i8* %frame_pointer)
+// CHECK: %[[l2_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%class.anon*)* @"??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ" to i8*), i8* %[[fp]], i32 0)
// CHECK: %[[l2_ptr:[^ ]*]] = bitcast i8* %[[l2_i8]] to i32*
// CHECK: %[[l2:[^ ]*]] = load i32, i32* %[[l2_ptr]]
// CHECK: call i32 (i32, ...) @basic_filter(i32 %[[l2]])
diff --git a/test/CodeGenCXX/exceptions-seh.cpp b/test/CodeGenCXX/exceptions-seh.cpp
index fa2d834c1e38..5f88a7b62978 100644
--- a/test/CodeGenCXX/exceptions-seh.cpp
+++ b/test/CodeGenCXX/exceptions-seh.cpp
@@ -21,28 +21,28 @@ extern "C" void use_cxx() {
// Make sure we use __CxxFrameHandler3 for C++ EH.
-// CXXEH-LABEL: define void @use_cxx()
+// CXXEH-LABEL: define dso_local void @use_cxx()
// CXXEH-SAME: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
-// CXXEH: call %struct.HasCleanup* @"\01??0HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
+// CXXEH: call %struct.HasCleanup* @"??0HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
// CXXEH: invoke void @might_throw()
// CXXEH: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
//
// CXXEH: [[cont]]
-// CXXEH: call void @"\01??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
+// CXXEH: call void @"??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
// CXXEH: ret void
//
// CXXEH: [[lpad]]
// CXXEH: cleanuppad
-// CXXEH: call void @"\01??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
+// CXXEH: call void @"??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
// CXXEH: cleanupret
-// NOCXX-LABEL: define void @use_cxx()
+// NOCXX-LABEL: define dso_local void @use_cxx()
// NOCXX-NOT: invoke
-// NOCXX: call %struct.HasCleanup* @"\01??0HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
+// NOCXX: call %struct.HasCleanup* @"??0HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
// NOCXX-NOT: invoke
// NOCXX: call void @might_throw()
// NOCXX-NOT: invoke
-// NOCXX: call void @"\01??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
+// NOCXX: call void @"??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
// NOCXX-NOT: invoke
// NOCXX: ret void
@@ -55,7 +55,7 @@ extern "C" void use_seh() {
// Make sure we use __C_specific_handler for SEH.
-// CHECK-LABEL: define void @use_seh()
+// CHECK-LABEL: define dso_local void @use_seh()
// CHECK-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
// CHECK: invoke void @might_throw() #[[NOINLINE:[0-9]+]]
// CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
@@ -87,15 +87,15 @@ extern "C" void nested_finally() {
}
}
-// CHECK-LABEL: define void @nested_finally() #{{[0-9]+}}
+// CHECK-LABEL: define dso_local void @nested_finally() #{{[0-9]+}}
// CHECK-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
// CHECK: invoke void @might_throw()
-// CHECK: call void @"\01?fin$0@0@nested_finally@@"(i8 1, i8* {{.*}})
+// CHECK: call void @"?fin$0@0@nested_finally@@"(i8 1, i8* {{.*}})
-// CHECK-LABEL: define internal void @"\01?fin$0@0@nested_finally@@"
+// CHECK-LABEL: define internal void @"?fin$0@0@nested_finally@@"
// CHECK-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
// CHECK: invoke void @might_throw()
-// CHECK: call void @"\01?fin$1@0@nested_finally@@"(i8 1, i8* {{.*}})
+// CHECK: call void @"?fin$1@0@nested_finally@@"(i8 1, i8* {{.*}})
void use_seh_in_lambda() {
([]() {
@@ -108,15 +108,15 @@ void use_seh_in_lambda() {
might_throw();
}
-// CXXEH-LABEL: define void @"\01?use_seh_in_lambda@@YAXXZ"()
+// CXXEH-LABEL: define dso_local void @"?use_seh_in_lambda@@YAXXZ"()
// CXXEH-SAME: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
// CXXEH: cleanuppad
-// NOCXX-LABEL: define void @"\01?use_seh_in_lambda@@YAXXZ"()
+// NOCXX-LABEL: define dso_local void @"?use_seh_in_lambda@@YAXXZ"()
// NOCXX-NOT: invoke
// NOCXX: ret void
-// CHECK-LABEL: define internal void @"\01??R<lambda_0>@?0??use_seh_in_lambda@@YAXXZ@QEBA@XZ"(%class.anon* %this)
+// CHECK-LABEL: define internal void @"??R<lambda_0>@?0??use_seh_in_lambda@@YAXXZ@QEBA@XZ"(%class.anon* %this)
// CXXEH-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
// CHECK: invoke void @might_throw() #[[NOINLINE]]
// CHECK: catchpad
@@ -139,28 +139,28 @@ void use_inline() {
use_seh_in_inline_func();
}
-// CHECK-LABEL: define linkonce_odr void @use_seh_in_inline_func() #{{[0-9]+}}
+// CHECK-LABEL: define linkonce_odr dso_local void @use_seh_in_inline_func() #{{[0-9]+}}
// CHECK-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
// CHECK: invoke void @might_throw()
//
-// CHECK: catchpad {{.*}} [i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@use_seh_in_inline_func@@" to i8*)]
+// CHECK: catchpad {{.*}} [i8* bitcast (i32 (i8*, i8*)* @"?filt$0@0@use_seh_in_inline_func@@" to i8*)]
//
// CHECK: invoke void @might_throw()
//
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK: call void @"\01?fin$0@0@use_seh_in_inline_func@@"(i8 0, i8* %[[fp]])
+// CHECK: call void @"?fin$0@0@use_seh_in_inline_func@@"(i8 0, i8* %[[fp]])
// CHECK: ret void
//
// CHECK: cleanuppad
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK: call void @"\01?fin$0@0@use_seh_in_inline_func@@"(i8 1, i8* %[[fp]])
+// CHECK: call void @"?fin$0@0@use_seh_in_inline_func@@"(i8 1, i8* %[[fp]])
-// CHECK-LABEL: define internal i32 @"\01?filt$0@0@use_seh_in_inline_func@@"(i8* %exception_pointers, i8* %frame_pointer) #{{[0-9]+}}
+// CHECK-LABEL: define internal i32 @"?filt$0@0@use_seh_in_inline_func@@"(i8* %exception_pointers, i8* %frame_pointer) #{{[0-9]+}}
// CHECK: icmp eq i32 %{{.*}}, 424242
// CHECK: zext i1 %{{.*}} to i32
// CHECK: ret i32
-// CHECK-LABEL: define internal void @"\01?fin$0@0@use_seh_in_inline_func@@"(i8 %abnormal_termination, i8* %frame_pointer) #{{[0-9]+}}
+// CHECK-LABEL: define internal void @"?fin$0@0@use_seh_in_inline_func@@"(i8 %abnormal_termination, i8* %frame_pointer) #{{[0-9]+}}
// CHECK: store i32 1234, i32* @my_unique_global
// CHECK: attributes #[[NOINLINE]] = { {{.*noinline.*}} }
diff --git a/test/CodeGenCXX/explicit-instantiation.cpp b/test/CodeGenCXX/explicit-instantiation.cpp
index ad20abde8f11..07c5f7265acd 100644
--- a/test/CodeGenCXX/explicit-instantiation.cpp
+++ b/test/CodeGenCXX/explicit-instantiation.cpp
@@ -119,14 +119,14 @@ namespace NestedClasses {
// definition of Inner.
template struct Outer<int>;
// CHECK: define weak_odr void @_ZN13NestedClasses5OuterIiE5Inner1fEv
- // CHECK-MS: define weak_odr x86_thiscallcc void @"\01?f@Inner@?$Outer@H@NestedClasses@@QAEXXZ"
+ // CHECK-MS: define weak_odr dso_local x86_thiscallcc void @"?f@Inner@?$Outer@H@NestedClasses@@QAEXXZ"
// Explicit instantiation declaration of Outer causes explicit instantiation
// declaration of Inner, but not in MSVC mode.
extern template struct Outer<char>;
auto use = &Outer<char>::Inner::f;
// CHECK: {{declare|define available_externally}} void @_ZN13NestedClasses5OuterIcE5Inner1fEv
- // CHECK-MS: define linkonce_odr x86_thiscallcc void @"\01?f@Inner@?$Outer@D@NestedClasses@@QAEXXZ"
+ // CHECK-MS: define linkonce_odr dso_local x86_thiscallcc void @"?f@Inner@?$Outer@D@NestedClasses@@QAEXXZ"
}
// Check that we emit definitions from explicit instantiations even when they
diff --git a/test/CodeGenCXX/extern-c.cpp b/test/CodeGenCXX/extern-c.cpp
index 1046915fcaa2..b80d3257e5de 100644
--- a/test/CodeGenCXX/extern-c.cpp
+++ b/test/CodeGenCXX/extern-c.cpp
@@ -7,7 +7,7 @@ extern "C" int a;
// CHECK-NOT: @_ZN3foo1bE = global
extern int b;
-// CHECK: @_ZN3foo1cE = global
+// CHECK: @_ZN3foo1cE = {{(dso_local )?}}global
int c = 5;
// CHECK-NOT: @_ZN3foo1dE
@@ -16,21 +16,21 @@ extern "C" struct d;
// CHECK-NOT: should_not_appear
extern "C++" int should_not_appear;
-// CHECK: @_ZN3foo10extern_cxxE = global
+// CHECK: @_ZN3foo10extern_cxxE = {{(dso_local )?}}global
extern "C++" int extern_cxx = 0;
}
-// CHECK-NOT: @global_a = global
+// CHECK-NOT: @global_a = {{(dso_local )?}}global
extern "C" int global_a;
-// CHECK: @global_b = global
+// CHECK: @global_b = {{(dso_local )?}}global
extern "C" int global_b = 0;
// CHECK-NOT: should_not_appear
extern "C++" int should_not_appear;
-// CHECK: @extern_cxx = global
+// CHECK: @extern_cxx = {{(dso_local )?}}global
extern "C++" int extern_cxx = 0;
namespace test1 {
@@ -38,11 +38,11 @@ namespace test1 {
struct X {};
}
extern "C" {
- // CHECK: @test1_b = global
+ // CHECK: @test1_b = {{(dso_local )?}}global
X test1_b = X();
}
void *use = &test1_b;
- // CHECK: @_ZN5test13useE = global
+ // CHECK: @_ZN5test13useE = {{(dso_local )?}}global
}
namespace test2 {
@@ -50,7 +50,7 @@ namespace test2 {
struct X {};
}
- // CHECK: @test2_b = global
+ // CHECK: @test2_b = {{(dso_local )?}}global
extern "C" X test2_b;
X test2_b;
}
diff --git a/test/CodeGenCXX/finegrain-bitfield-type.cpp b/test/CodeGenCXX/finegrain-bitfield-type.cpp
new file mode 100644
index 000000000000..ff02d46de5e4
--- /dev/null
+++ b/test/CodeGenCXX/finegrain-bitfield-type.cpp
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -ffine-grained-bitfield-accesses \
+// RUN: -emit-llvm -o - %s | FileCheck %s
+struct S4 {
+ unsigned long f1:28;
+ unsigned long f2:4;
+ unsigned long f3:12;
+};
+struct S4 a4;
+
+struct S5 {
+ unsigned long f1:28;
+ unsigned long f2:4;
+ unsigned long f3:28;
+ unsigned long f4:4;
+ unsigned long f5:12;
+};
+struct S5 a5;
+
+// CHECK: %struct.S4 = type { i32, i16 }
+// CHECK-NOT: %struct.S4 = type { i48 }
+// CHECK: %struct.S5 = type { i32, i32, i16, [6 x i8] }
+// CHECK-NOT: %struct.S5 = type { i80 } \ No newline at end of file
diff --git a/test/CodeGenCXX/float128-declarations.cpp b/test/CodeGenCXX/float128-declarations.cpp
index f1db8f41c608..07e73b281728 100644
--- a/test/CodeGenCXX/float128-declarations.cpp
+++ b/test/CodeGenCXX/float128-declarations.cpp
@@ -12,6 +12,10 @@
// RUN: %s -o - | FileCheck %s -check-prefix=CHECK-X86
// RUN: %clang_cc1 -emit-llvm -triple amd64-pc-openbsd -std=c++11 \
// RUN: %s -o - | FileCheck %s -check-prefix=CHECK-X86
+// RUN: %clang_cc1 -emit-llvm -triple i386-pc-solaris2.11 -std=c++11 \
+// RUN: %s -o - | FileCheck %s -check-prefix=CHECK-X86
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-pc-solaris2.11 -std=c++11 \
+// RUN: %s -o - | FileCheck %s -check-prefix=CHECK-X86
//
/* Various contexts where type __float128 can appear. The different check
prefixes are due to different mangling on X86 and different calling
diff --git a/test/CodeGenCXX/float16-declarations.cpp b/test/CodeGenCXX/float16-declarations.cpp
index 87ef139f8634..1d6999fef073 100644
--- a/test/CodeGenCXX/float16-declarations.cpp
+++ b/test/CodeGenCXX/float16-declarations.cpp
@@ -29,18 +29,18 @@ namespace {
/* File */
_Float16 f1f;
-// CHECK-AARCH64-DAG: @f1f = global half 0xH0000, align 2
-// CHECK-X86-DAG: @f1f = global half 0xH0000, align 2
+// CHECK-AARCH64-DAG: @f1f = dso_local global half 0xH0000, align 2
+// CHECK-X86-DAG: @f1f = dso_local global half 0xH0000, align 2
_Float16 f2f = 32.4;
-// CHECK-DAG: @f2f = global half 0xH500D, align 2
+// CHECK-DAG: @f2f = dso_local global half 0xH500D, align 2
_Float16 arr1f[10];
-// CHECK-AARCH64-DAG: @arr1f = global [10 x half] zeroinitializer, align 2
-// CHECK-X86-DAG: @arr1f = global [10 x half] zeroinitializer, align 16
+// CHECK-AARCH64-DAG: @arr1f = dso_local global [10 x half] zeroinitializer, align 2
+// CHECK-X86-DAG: @arr1f = dso_local global [10 x half] zeroinitializer, align 16
_Float16 arr2f[] = { -1.2, -3.0, -3.e4 };
-// CHECK-DAG: @arr2f = global [3 x half] [half 0xHBCCD, half 0xHC200, half 0xHF753], align 2
+// CHECK-DAG: @arr2f = dso_local global [3 x half] [half 0xHBCCD, half 0xHC200, half 0xHF753], align 2
_Float16 func1f(_Float16 arg);
@@ -51,24 +51,24 @@ class C1 {
_Float16 f1c;
static const _Float16 f2c;
-// CHECK-DAG: @_ZN2C13f2cE = external constant half, align 2
+// CHECK-DAG: @_ZN2C13f2cE = external dso_local constant half, align 2
volatile _Float16 f3c;
public:
C1(_Float16 arg) : f1c(arg), f3c(arg) { }
// Check that we mangle _Float16 to DF16_
-// CHECK-DAG: define linkonce_odr void @_ZN2C1C2EDF16_(%class.C1*{{.*}}, half{{.*}})
+// CHECK-DAG: define linkonce_odr dso_local void @_ZN2C1C2EDF16_(%class.C1*{{.*}}, half{{.*}})
_Float16 func1c(_Float16 arg ) {
return f1c + arg;
}
-// CHECK-DAG: define linkonce_odr half @_ZN2C16func1cEDF16_(%class.C1*{{.*}}, half{{.*}})
+// CHECK-DAG: define linkonce_odr dso_local half @_ZN2C16func1cEDF16_(%class.C1*{{.*}}, half{{.*}})
static _Float16 func2c(_Float16 arg) {
return arg * C1::f2c;
}
-// CHECK-DAG: define linkonce_odr half @_ZN2C16func2cEDF16_(half{{.*}})
+// CHECK-DAG: define linkonce_odr dso_local half @_ZN2C16func2cEDF16_(half{{.*}})
};
/* Template */
@@ -76,7 +76,7 @@ public:
template <class C> C func1t(C arg) {
return arg * 2.f16;
}
-// CHECK-DAG: define linkonce_odr half @_Z6func1tIDF16_ET_S0_(half{{.*}})
+// CHECK-DAG: define linkonce_odr dso_local half @_Z6func1tIDF16_ET_S0_(half{{.*}})
template <class C> struct S1 {
C mem1;
@@ -103,12 +103,12 @@ int main(void) {
C1 c1(f1l);
// CHECK-DAG: [[F1L:%[a-z0-9]+]] = load half, half* %{{.*}}, align 2
-// CHECK-DAG: call void @_ZN2C1C2EDF16_(%class.C1* %{{.*}}, half %{{.*}})
+// CHECK-DAG: call void @_ZN2C1C1EDF16_(%class.C1* %{{.*}}, half %{{.*}})
S1<_Float16> s1 = { 132.f16 };
// CHECK-DAG: @_ZZ4mainE2s1 = private unnamed_addr constant %struct.S1 { half 0xH5820 }, align 2
// CHECK-DAG: [[S1:%[0-9]+]] = bitcast %struct.S1* %{{.*}} to i8*
-// CHECK-DAG: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[S1]], i8* bitcast (%struct.S1* @_ZZ4mainE2s1 to i8*), i64 2, i32 2, i1 false)
+// CHECK-DAG: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 2 [[S1]], i8* align 2 bitcast (%struct.S1* @_ZZ4mainE2s1 to i8*), i64 2, i1 false)
_Float16 f4l = func1n(f1l) + func1f(f2l) + c1.func1c(f3l) + c1.func2c(f1l) +
func1t(f1l) + s1.mem2 - f1n + f2n;
diff --git a/test/CodeGenCXX/funcsig.cpp b/test/CodeGenCXX/funcsig.cpp
index 16e5f7e1c9b1..5328ff946206 100644
--- a/test/CodeGenCXX/funcsig.cpp
+++ b/test/CodeGenCXX/funcsig.cpp
@@ -12,24 +12,24 @@ int printf(const char *, ...);
void funcNoProto() {
printf("__FUNCSIG__ %s\n\n", __FUNCSIG__);
}
-// CHECK-C: @"\01??_C@_0BL@IHLLLCAO@void?5__cdecl?5funcNoProto?$CI?$CJ?$AA@" = linkonce_odr unnamed_addr constant [27 x i8] c"void __cdecl funcNoProto()\00"
-// CHECK-CXX: @"\01??_C@_0BP@PJOECCJN@void?5__cdecl?5funcNoProto?$CIvoid?$CJ?$AA@" = linkonce_odr unnamed_addr constant [31 x i8] c"void __cdecl funcNoProto(void)\00"
+// CHECK-C: @"??_C@_0BL@IHLLLCAO@void?5__cdecl?5funcNoProto?$CI?$CJ?$AA@" = linkonce_odr dso_local unnamed_addr constant [27 x i8] c"void __cdecl funcNoProto()\00"
+// CHECK-CXX: @"??_C@_0BP@PJOECCJN@void?5__cdecl?5funcNoProto?$CIvoid?$CJ?$AA@" = linkonce_odr dso_local unnamed_addr constant [31 x i8] c"void __cdecl funcNoProto(void)\00"
void funcNoParams(void) {
printf("__FUNCSIG__ %s\n\n", __FUNCSIG__);
}
-// CHECK: @"\01??_C@_0CA@GBIDFNBN@void?5__cdecl?5funcNoParams?$CIvoid?$CJ?$AA@" = linkonce_odr unnamed_addr constant [32 x i8] c"void __cdecl funcNoParams(void)\00"
+// CHECK: @"??_C@_0CA@GBIDFNBN@void?5__cdecl?5funcNoParams?$CIvoid?$CJ?$AA@" = linkonce_odr dso_local unnamed_addr constant [32 x i8] c"void __cdecl funcNoParams(void)\00"
void freeFunc(int *p, char c) {
printf("__FUNCSIG__ %s\n\n", __FUNCSIG__);
}
-// CHECK: @"\01??_C@_0CD@KLGMNNL@void?5__cdecl?5freeFunc?$CIint?5?$CK?0?5cha@" = linkonce_odr unnamed_addr constant [{{.*}} x i8] c"void __cdecl freeFunc(int *, char)\00"
+// CHECK: @"??_C@_0CD@KLGMNNL@void?5__cdecl?5freeFunc?$CIint?5?$CK?0?5cha@" = linkonce_odr dso_local unnamed_addr constant [{{.*}} x i8] c"void __cdecl freeFunc(int *, char)\00"
#ifdef __cplusplus
void funcVarargs(...) {
printf("__FUNCSIG__ %s\n\n", __FUNCSIG__);
}
-// CHECK-CXX: @"\01??_C@_0BO@BOBPLEKP@void?5__cdecl?5funcVarargs?$CI?4?4?4?$CJ?$AA@" = linkonce_odr unnamed_addr constant [30 x i8] c"void __cdecl funcVarargs(...)\00"
+// CHECK-CXX: @"??_C@_0BO@BOBPLEKP@void?5__cdecl?5funcVarargs?$CI?4?4?4?$CJ?$AA@" = linkonce_odr dso_local unnamed_addr constant [30 x i8] c"void __cdecl funcVarargs(...)\00"
struct TopLevelClass {
void topLevelMethod(int *, char);
@@ -37,7 +37,7 @@ struct TopLevelClass {
void TopLevelClass::topLevelMethod(int *, char) {
printf("__FUNCSIG__ %s\n\n", __FUNCSIG__);
}
-// CHECK-CXX: @"\01??_C@_0DL@OBHNMDP@void?5__thiscall?5TopLevelClass?3?3t@" = linkonce_odr unnamed_addr constant [{{.*}} x i8] c"void __thiscall TopLevelClass::topLevelMethod(int *, char)\00"
+// CHECK-CXX: @"??_C@_0DL@OBHNMDP@void?5__thiscall?5TopLevelClass?3?3t@" = linkonce_odr dso_local unnamed_addr constant [{{.*}} x i8] c"void __thiscall TopLevelClass::topLevelMethod(int *, char)\00"
namespace NS {
struct NamespacedClass {
@@ -46,6 +46,6 @@ struct NamespacedClass {
void NamespacedClass::namespacedMethod(int *, char) {
printf("__FUNCSIG__ %s\n\n", __FUNCSIG__);
}
-// CHECK-CXX: @"\01??_C@_0ED@PFDKIEBA@void?5__thiscall?5NS?3?3NamespacedCl@" = linkonce_odr unnamed_addr constant [{{.*}} x i8] c"void __thiscall NS::NamespacedClass::namespacedMethod(int *, char)\00"
+// CHECK-CXX: @"??_C@_0ED@PFDKIEBA@void?5__thiscall?5NS?3?3NamespacedCl@" = linkonce_odr dso_local unnamed_addr constant [{{.*}} x i8] c"void __thiscall NS::NamespacedClass::namespacedMethod(int *, char)\00"
}
#endif
diff --git a/test/CodeGenCXX/global-llvm-constant.cpp b/test/CodeGenCXX/global-llvm-constant.cpp
index 55933eecfc3e..877683eead07 100644
--- a/test/CodeGenCXX/global-llvm-constant.cpp
+++ b/test/CodeGenCXX/global-llvm-constant.cpp
@@ -15,7 +15,7 @@ struct X {
int add(int x, int y) { return x + y; }
-// CHECK: @x2 = constant
+// CHECK: @x2 = {{(dso_local )?}}constant
extern const X x2;
const X x2 = { &add };
@@ -27,6 +27,6 @@ struct X2 {
X1 array[3];
};
-// CHECK: @x2b = global
+// CHECK: @x2b = {{(dso_local )?}}global
extern const X2 x2b;
const X2 x2b = { { { 1 }, { 2 }, { 3 } } };
diff --git a/test/CodeGenCXX/hidden-dllimport.cpp b/test/CodeGenCXX/hidden-dllimport.cpp
new file mode 100644
index 000000000000..573b4210bfb3
--- /dev/null
+++ b/test/CodeGenCXX/hidden-dllimport.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -emit-llvm -fvisibility-inlines-hidden -o - %s | FileCheck %s
+
+// We used to declare this hidden dllimport, which is contradictory.
+
+// CHECK: declare dllimport void @"?bar@foo@@QEAAXXZ"(%struct.foo*)
+
+struct __attribute__((dllimport)) foo {
+ void bar() {}
+};
+void zed(foo *p) { p->bar(); }
diff --git a/test/CodeGenCXX/homogeneous-aggregates.cpp b/test/CodeGenCXX/homogeneous-aggregates.cpp
index 1338b25e21ae..05fb7f1d20a4 100644
--- a/test/CodeGenCXX/homogeneous-aggregates.cpp
+++ b/test/CodeGenCXX/homogeneous-aggregates.cpp
@@ -41,13 +41,13 @@ struct D5 : I1, I2, I3 {}; // homogeneous aggregate
// PPC: define void @_Z7func_D12D1(%struct.D1* noalias sret %agg.result, [3 x i64] %x.coerce)
// ARM32: define arm_aapcs_vfpcc void @_Z7func_D12D1(%struct.D1* noalias sret %agg.result, [3 x i64] %x.coerce)
// ARM64: define void @_Z7func_D12D1(%struct.D1* noalias sret %agg.result, %struct.D1* %x)
-// X64: define x86_vectorcallcc void @"\01_Z7func_D12D1@@24"(%struct.D1* noalias sret %agg.result, %struct.D1* %x)
+// X64: define dso_local x86_vectorcallcc void @"\01_Z7func_D12D1@@24"(%struct.D1* noalias sret %agg.result, %struct.D1* %x)
D1 CC func_D1(D1 x) { return x; }
// PPC: define [3 x double] @_Z7func_D22D2([3 x double] %x.coerce)
// ARM32: define arm_aapcs_vfpcc %struct.D2 @_Z7func_D22D2(%struct.D2 %x.coerce)
// ARM64: define %struct.D2 @_Z7func_D22D2([3 x double] %x.coerce)
-// X64: define x86_vectorcallcc %struct.D2 @"\01_Z7func_D22D2@@24"(%struct.D2 inreg %x.coerce)
+// X64: define dso_local x86_vectorcallcc %struct.D2 @"\01_Z7func_D22D2@@24"(%struct.D2 inreg %x.coerce)
D2 CC func_D2(D2 x) { return x; }
// PPC: define void @_Z7func_D32D3(%struct.D3* noalias sret %agg.result, [4 x i64] %x.coerce)
@@ -92,7 +92,7 @@ struct HVAWithEmptyBase : Float1, Empty, Float2 { float z; };
void CC with_empty_base(HVAWithEmptyBase a) {}
// FIXME: MSVC doesn't consider this an HVA because of the empty base.
-// X64: define x86_vectorcallcc void @"\01_Z15with_empty_base16HVAWithEmptyBase@@16"(%struct.HVAWithEmptyBase inreg %a.coerce)
+// X64: define dso_local x86_vectorcallcc void @"\01_Z15with_empty_base16HVAWithEmptyBase@@16"(%struct.HVAWithEmptyBase inreg %a.coerce)
struct HVAWithEmptyBitField : Float1, Float2 {
int : 0; // Takes no space.
@@ -102,5 +102,5 @@ struct HVAWithEmptyBitField : Float1, Float2 {
// PPC: define void @_Z19with_empty_bitfield20HVAWithEmptyBitField([3 x float] %a.coerce)
// ARM64: define void @_Z19with_empty_bitfield20HVAWithEmptyBitField([3 x float] %a.coerce)
// ARM32: define arm_aapcs_vfpcc void @_Z19with_empty_bitfield20HVAWithEmptyBitField(%struct.HVAWithEmptyBitField %a.coerce)
-// X64: define x86_vectorcallcc void @"\01_Z19with_empty_bitfield20HVAWithEmptyBitField@@16"(%struct.HVAWithEmptyBitField inreg %a.coerce)
+// X64: define dso_local x86_vectorcallcc void @"\01_Z19with_empty_bitfield20HVAWithEmptyBitField@@16"(%struct.HVAWithEmptyBitField inreg %a.coerce)
void CC with_empty_bitfield(HVAWithEmptyBitField a) {}
diff --git a/test/CodeGenCXX/inheriting-constructor.cpp b/test/CodeGenCXX/inheriting-constructor.cpp
index 1be59b9305d3..fa3e5ab8aab7 100644
--- a/test/CodeGenCXX/inheriting-constructor.cpp
+++ b/test/CodeGenCXX/inheriting-constructor.cpp
@@ -18,8 +18,8 @@ D d(123);
// ITANIUM-LABEL: define void @_ZN1BD2Ev
// ITANIUM-LABEL: define void @_ZN1BD1Ev
// ITANIUM-LABEL: define void @_ZN1BD0Ev
-// WIN32-LABEL: define {{.*}}void @"\01??1B@@UAE@XZ"
-// WIN64-LABEL: define {{.*}}void @"\01??1B@@UEAA@XZ"
+// WIN32-LABEL: define {{.*}}void @"??1B@@UAE@XZ"
+// WIN64-LABEL: define {{.*}}void @"??1B@@UEAA@XZ"
// ITANIUM-LABEL: define linkonce_odr void @_ZN1BCI11AEi(
// ITANIUM: call void @_ZN1BCI21AEi(
@@ -27,15 +27,15 @@ D d(123);
// ITANIUM-LABEL: define linkonce_odr void @_ZN1DCI11CIiEET_(
// ITANIUM: call void @_ZN1DCI21CIiEET_(
-// WIN32-LABEL: define internal {{.*}} @"\01??0B@@QAE@H@Z"(
-// WIN32: call {{.*}} @"\01??0A@@QAE@H@Z"(
-// WIN64-LABEL: define internal {{.*}} @"\01??0B@@QEAA@H@Z"(
-// WIN64: call {{.*}} @"\01??0A@@QEAA@H@Z"(
+// WIN32-LABEL: define internal {{.*}} @"??0B@@QAE@H@Z"(
+// WIN32: call {{.*}} @"??0A@@QAE@H@Z"(
+// WIN64-LABEL: define internal {{.*}} @"??0B@@QEAA@H@Z"(
+// WIN64: call {{.*}} @"??0A@@QEAA@H@Z"(
-// WIN32-LABEL: define internal {{.*}} @"\01??0D@@QAE@H@Z"(
-// WIN32: call {{.*}} @"\01??$?0H@C@@QAE@H@Z"
-// WIN64-LABEL: define internal {{.*}} @"\01??0D@@QEAA@H@Z"(
-// WIN64: call {{.*}} @"\01??$?0H@C@@QEAA@H@Z"
+// WIN32-LABEL: define internal {{.*}} @"??0D@@QAE@H@Z"(
+// WIN32: call {{.*}} @"??$?0H@C@@QAE@H@Z"
+// WIN64-LABEL: define internal {{.*}} @"??0D@@QEAA@H@Z"(
+// WIN64: call {{.*}} @"??$?0H@C@@QEAA@H@Z"
struct Q { Q(int); Q(const Q&); ~Q(); };
struct Z { Z(); Z(int); ~Z(); int n; };
@@ -55,10 +55,10 @@ namespace noninline_nonvirt {
// ITANIUM: call void @_ZN17noninline_nonvirt1BCI2NS_1AEEiO1QPvU17pass_object_size0({{.*}}, i32 {{.*}}, %{{.*}}* {{.*}}, i8* {{.*}}, i{{32|64}} {{.*}})
// In MSABI, we don't have ctor variants. B ctor forwards to A ctor.
- // MSABI-LABEL: define internal {{.*}} @"\01??0B@noninline_nonvirt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}})
- // MSABI: call {{.*}} @"\01??0Z@@Q{{AE|EAA}}@XZ"(
- // MSABI: call {{.*}} @"\01??0A@noninline_nonvirt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}})
- // MSABI: call {{.*}} @"\01??0Z@@Q{{AE|EAA}}@XZ"(
+ // MSABI-LABEL: define internal {{.*}} @"??0B@noninline_nonvirt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}})
+ // MSABI: call {{.*}} @"??0Z@@Q{{AE|EAA}}@XZ"(
+ // MSABI: call {{.*}} @"??0A@noninline_nonvirt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}})
+ // MSABI: call {{.*}} @"??0Z@@Q{{AE|EAA}}@XZ"(
struct C : B { using B::B; };
C c(1, 2, &c);
@@ -66,8 +66,8 @@ namespace noninline_nonvirt {
// ITANIUM-LABEL: define linkonce_odr void @_ZN17noninline_nonvirt1CCI1NS_1AEEiO1QPvU17pass_object_size0(
// ITANIUM: call void @_ZN17noninline_nonvirt1CCI2NS_1AEEiO1QPvU17pass_object_size0({{.*}}, i32 {{.*}}, %{{.*}}* {{.*}}, i8* {{.*}}, i{{32|64}} {{.*}})
- // MSABI-LABEL: define internal {{.*}} @"\01??0C@noninline_nonvirt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}})
- // MSABI: call {{.*}} @"\01??0B@noninline_nonvirt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}})
+ // MSABI-LABEL: define internal {{.*}} @"??0C@noninline_nonvirt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}})
+ // MSABI: call {{.*}} @"??0B@noninline_nonvirt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}})
}
namespace noninline_virt {
@@ -81,13 +81,13 @@ namespace noninline_virt {
// ITANIUM: store {{.*}} @_ZTVN14noninline_virt1BE
// ITANIUM: call void @_ZN1ZC1Ev(
- // MSABI-LABEL: define internal {{.*}} @"\01??0B@noninline_virt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}}, i32 %{{.*}})
+ // MSABI-LABEL: define internal {{.*}} @"??0B@noninline_virt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}}, i32 %{{.*}})
// MSABI: %[[COMPLETE:.*]] = icmp ne
// MSABI: br i1 %[[COMPLETE]],
- // MSABI: call {{.*}} @"\01??0A@noninline_virt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}})
+ // MSABI: call {{.*}} @"??0A@noninline_virt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}})
// MSABI: br
- // MSABI: call {{.*}} @"\01??0Z@@Q{{AE|EAA}}@XZ"(
- // MSABI: call {{.*}} @"\01??0Z@@Q{{AE|EAA}}@XZ"(
+ // MSABI: call {{.*}} @"??0Z@@Q{{AE|EAA}}@XZ"(
+ // MSABI: call {{.*}} @"??0Z@@Q{{AE|EAA}}@XZ"(
struct C : B { using B::B; };
C c(1, 2, &c);
@@ -101,12 +101,12 @@ namespace noninline_virt {
// C constructor forwards to B constructor and A constructor. We pass the args
// to both. FIXME: Can we pass undef here instead, for the base object
// constructor call?
- // MSABI-LABEL: define internal {{.*}} @"\01??0C@noninline_virt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}}, i32 %{{.*}})
+ // MSABI-LABEL: define internal {{.*}} @"??0C@noninline_virt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}}, i32 %{{.*}})
// MSABI: %[[COMPLETE:.*]] = icmp ne
// MSABI: br i1 %[[COMPLETE]],
- // MSABI: call {{.*}} @"\01??0A@noninline_virt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}})
+ // MSABI: call {{.*}} @"??0A@noninline_virt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}})
// MSABI: br
- // MSABI: call {{.*}} @"\01??0B@noninline_virt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}}, i32 0)
+ // MSABI: call {{.*}} @"??0B@noninline_virt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}}, i32 0)
}
// For MSABI only, check that inalloca arguments result in inlining.
@@ -118,75 +118,75 @@ namespace inalloca_nonvirt {
// ITANIUM-LABEL: define linkonce_odr void @_ZN16inalloca_nonvirt1BCI1NS_1AEE1QiS1_OS1_(
// ITANIUM: call void @_ZN16inalloca_nonvirt1BCI2NS_1AEE1QiS1_OS1_(
- // MSABI-LABEL: define internal void @"\01??__Eb@inalloca_nonvirt@@YAXXZ"(
+ // MSABI-LABEL: define internal void @"??__Eb@inalloca_nonvirt@@YAXXZ"(
// On Win32, the inalloca call can't be forwarded so we force inlining.
// WIN32: %[[TMP:.*]] = alloca
// WIN32: call i8* @llvm.stacksave()
// WIN32: %[[ARGMEM:.*]] = alloca inalloca
- // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"(%{{.*}}* %[[TMP]], i32 4)
+ // WIN32: call {{.*}} @"??0Q@@QAE@H@Z"(%{{.*}}* %[[TMP]], i32 4)
// WIN32: %[[ARG3:.*]] = getelementptr {{.*}} %[[ARGMEM]]
- // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"({{.*}}* %[[ARG3]], i32 3)
+ // WIN32: call {{.*}} @"??0Q@@QAE@H@Z"({{.*}}* %[[ARG3]], i32 3)
// WIN32: %[[ARG1:.*]] = getelementptr {{.*}} %[[ARGMEM]]
- // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"({{.*}}* %[[ARG1]], i32 1)
- // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"(
+ // WIN32: call {{.*}} @"??0Q@@QAE@H@Z"({{.*}}* %[[ARG1]], i32 1)
+ // WIN32: call {{.*}} @"??0Z@@QAE@XZ"(
// WIN32: %[[ARG2:.*]] = getelementptr {{.*}} %[[ARGMEM]]
// WIN32: store i32 2, i32* %[[ARG2]]
// WIN32: %[[ARG4:.*]] = getelementptr {{.*}} %[[ARGMEM]]
// WIN32: store {{.*}}* %[[TMP]], {{.*}}** %[[ARG4]]
- // WIN32: call {{.*}} @"\01??0A@inalloca_nonvirt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]])
+ // WIN32: call {{.*}} @"??0A@inalloca_nonvirt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]])
// WIN32: call void @llvm.stackrestore(
- // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"(
- // WIN32: call {{.*}} @"\01??_DQ@@QAEXXZ"(
+ // WIN32: call {{.*}} @"??0Z@@QAE@XZ"(
+ // WIN32: call {{.*}} @"??1Q@@QAE@XZ"(
// On Win64, the Q arguments would be destroyed in the callee. We don't yet
// support that in the non-inlined case, so we force inlining.
// WIN64: %[[TMP:.*]] = alloca
// WIN64: %[[ARG3:.*]] = alloca
// WIN64: %[[ARG1:.*]] = alloca
- // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[TMP]], i32 4)
- // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[ARG3]], i32 3)
- // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[ARG1]], i32 1)
- // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"(
- // WIN64: call {{.*}} @"\01??0A@inalloca_nonvirt@@QEAA@UQ@@H0$$QEAU2@@Z"(%{{.*}}, %{{.*}}* %[[ARG1]], i32 2, %{{.*}}* %[[ARG3]], %{{.*}} %[[TMP]])
- // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"(
- // WIN64: call void @"\01??_DQ@@QEAAXXZ"({{.*}}* %[[TMP]])
+ // WIN64: call {{.*}} @"??0Q@@QEAA@H@Z"({{.*}}* %[[TMP]], i32 4)
+ // WIN64: call {{.*}} @"??0Q@@QEAA@H@Z"({{.*}}* %[[ARG3]], i32 3)
+ // WIN64: call {{.*}} @"??0Q@@QEAA@H@Z"({{.*}}* %[[ARG1]], i32 1)
+ // WIN64: call {{.*}} @"??0Z@@QEAA@XZ"(
+ // WIN64: call {{.*}} @"??0A@inalloca_nonvirt@@QEAA@UQ@@H0$$QEAU2@@Z"(%{{.*}}, %{{.*}}* %[[ARG1]], i32 2, %{{.*}}* %[[ARG3]], %{{.*}} %[[TMP]])
+ // WIN64: call {{.*}} @"??0Z@@QEAA@XZ"(
+ // WIN64: call void @"??1Q@@QEAA@XZ"({{.*}}* %[[TMP]])
struct C : B { using B::B; };
C c(1, 2, 3, 4);
- // MSABI-LABEL: define internal void @"\01??__Ec@inalloca_nonvirt@@YAXXZ"(
+ // MSABI-LABEL: define internal void @"??__Ec@inalloca_nonvirt@@YAXXZ"(
// On Win32, the inalloca call can't be forwarded so we force inlining.
// WIN32: %[[TMP:.*]] = alloca
// WIN32: call i8* @llvm.stacksave()
// WIN32: %[[ARGMEM:.*]] = alloca inalloca
- // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"(%{{.*}}* %[[TMP]], i32 4)
+ // WIN32: call {{.*}} @"??0Q@@QAE@H@Z"(%{{.*}}* %[[TMP]], i32 4)
// WIN32: %[[ARG3:.*]] = getelementptr {{.*}} %[[ARGMEM]]
- // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"({{.*}}* %[[ARG3]], i32 3)
+ // WIN32: call {{.*}} @"??0Q@@QAE@H@Z"({{.*}}* %[[ARG3]], i32 3)
// WIN32: %[[ARG1:.*]] = getelementptr {{.*}} %[[ARGMEM]]
- // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"({{.*}}* %[[ARG1]], i32 1)
- // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"(
+ // WIN32: call {{.*}} @"??0Q@@QAE@H@Z"({{.*}}* %[[ARG1]], i32 1)
+ // WIN32: call {{.*}} @"??0Z@@QAE@XZ"(
// WIN32: %[[ARG2:.*]] = getelementptr {{.*}} %[[ARGMEM]]
// WIN32: store i32 2, i32* %[[ARG2]]
// WIN32: %[[ARG4:.*]] = getelementptr {{.*}} %[[ARGMEM]]
// WIN32: store {{.*}}* %[[TMP]], {{.*}}** %[[ARG4]]
- // WIN32: call {{.*}} @"\01??0A@inalloca_nonvirt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]])
+ // WIN32: call {{.*}} @"??0A@inalloca_nonvirt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]])
// WIN32: call void @llvm.stackrestore(
- // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"(
- // WIN32: call {{.*}} @"\01??_DQ@@QAEXXZ"(
+ // WIN32: call {{.*}} @"??0Z@@QAE@XZ"(
+ // WIN32: call {{.*}} @"??1Q@@QAE@XZ"(
// On Win64, the Q arguments would be destroyed in the callee. We don't yet
// support that in the non-inlined case, so we force inlining.
// WIN64: %[[TMP:.*]] = alloca
// WIN64: %[[ARG3:.*]] = alloca
// WIN64: %[[ARG1:.*]] = alloca
- // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[TMP]], i32 4)
- // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[ARG3]], i32 3)
- // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[ARG1]], i32 1)
- // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"(
- // WIN64: call {{.*}} @"\01??0A@inalloca_nonvirt@@QEAA@UQ@@H0$$QEAU2@@Z"(%{{.*}}, %{{.*}}* %[[ARG1]], i32 2, %{{.*}}* %[[ARG3]], %{{.*}} %[[TMP]])
- // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"(
- // WIN64: call void @"\01??_DQ@@QEAAXXZ"({{.*}}* %[[TMP]])
+ // WIN64: call {{.*}} @"??0Q@@QEAA@H@Z"({{.*}}* %[[TMP]], i32 4)
+ // WIN64: call {{.*}} @"??0Q@@QEAA@H@Z"({{.*}}* %[[ARG3]], i32 3)
+ // WIN64: call {{.*}} @"??0Q@@QEAA@H@Z"({{.*}}* %[[ARG1]], i32 1)
+ // WIN64: call {{.*}} @"??0Z@@QEAA@XZ"(
+ // WIN64: call {{.*}} @"??0A@inalloca_nonvirt@@QEAA@UQ@@H0$$QEAU2@@Z"(%{{.*}}, %{{.*}}* %[[ARG1]], i32 2, %{{.*}}* %[[ARG3]], %{{.*}} %[[TMP]])
+ // WIN64: call {{.*}} @"??0Z@@QEAA@XZ"(
+ // WIN64: call void @"??1Q@@QEAA@XZ"({{.*}}* %[[TMP]])
}
namespace inalloca_virt {
@@ -194,79 +194,79 @@ namespace inalloca_virt {
struct B : Z, virtual A { Z z; using A::A; };
B b(1, 2, 3, 4);
- // MSABI-LABEL: define internal void @"\01??__Eb@inalloca_virt@@YAXXZ"(
+ // MSABI-LABEL: define internal void @"??__Eb@inalloca_virt@@YAXXZ"(
// On Win32, the inalloca call can't be forwarded so we force inlining.
// WIN32: %[[TMP:.*]] = alloca
// WIN32: call i8* @llvm.stacksave()
// WIN32: %[[ARGMEM:.*]] = alloca inalloca
- // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"(%{{.*}}* %[[TMP]], i32 4)
+ // WIN32: call {{.*}} @"??0Q@@QAE@H@Z"(%{{.*}}* %[[TMP]], i32 4)
// WIN32: %[[ARG3:.*]] = getelementptr {{.*}} %[[ARGMEM]]
- // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"({{.*}}* %[[ARG3]], i32 3)
+ // WIN32: call {{.*}} @"??0Q@@QAE@H@Z"({{.*}}* %[[ARG3]], i32 3)
// WIN32: %[[ARG1:.*]] = getelementptr {{.*}} %[[ARGMEM]]
- // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"({{.*}}* %[[ARG1]], i32 1)
+ // WIN32: call {{.*}} @"??0Q@@QAE@H@Z"({{.*}}* %[[ARG1]], i32 1)
// FIXME: It's dumb to round-trip this though memory and generate a branch.
// WIN32: store i32 1, i32* %[[IS_MOST_DERIVED_ADDR:.*]]
// WIN32: %[[IS_MOST_DERIVED:.*]] = load i32, i32* %[[IS_MOST_DERIVED_ADDR]]
// WIN32: %[[IS_MOST_DERIVED_i1:.*]] = icmp ne i32 %[[IS_MOST_DERIVED]], 0
// WIN32: br i1 %[[IS_MOST_DERIVED_i1]]
//
- // WIN32: store {{.*}} @"\01??_8B@inalloca_virt@@7B@"
+ // WIN32: store {{.*}} @"??_8B@inalloca_virt@@7B@"
// WIN32: %[[ARG2:.*]] = getelementptr {{.*}} %[[ARGMEM]]
// WIN32: store i32 2, i32* %[[ARG2]]
// WIN32: %[[ARG4:.*]] = getelementptr {{.*}} %[[ARGMEM]]
// WIN32: store {{.*}}* %[[TMP]], {{.*}}** %[[ARG4]]
- // WIN32: call {{.*}} @"\01??0A@inalloca_virt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]])
+ // WIN32: call {{.*}} @"??0A@inalloca_virt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]])
// WIN32: call void @llvm.stackrestore(
// WIN32: br
//
// Note that if we jumped directly to here we would fail to stackrestore and
// destroy the parameters, but that's not actually possible.
- // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"(
- // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"(
- // WIN32: call {{.*}} @"\01??_DQ@@QAEXXZ"(
+ // WIN32: call {{.*}} @"??0Z@@QAE@XZ"(
+ // WIN32: call {{.*}} @"??0Z@@QAE@XZ"(
+ // WIN32: call {{.*}} @"??1Q@@QAE@XZ"(
// On Win64, the Q arguments would be destroyed in the callee. We don't yet
// support that in the non-inlined case, so we force inlining.
// WIN64: %[[TMP:.*]] = alloca
// WIN64: %[[ARG3:.*]] = alloca
// WIN64: %[[ARG1:.*]] = alloca
- // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[TMP]], i32 4)
- // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[ARG3]], i32 3)
- // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[ARG1]], i32 1)
+ // WIN64: call {{.*}} @"??0Q@@QEAA@H@Z"({{.*}}* %[[TMP]], i32 4)
+ // WIN64: call {{.*}} @"??0Q@@QEAA@H@Z"({{.*}}* %[[ARG3]], i32 3)
+ // WIN64: call {{.*}} @"??0Q@@QEAA@H@Z"({{.*}}* %[[ARG1]], i32 1)
// WIN64: br i1
- // WIN64: call {{.*}} @"\01??0A@inalloca_virt@@QEAA@UQ@@H0$$QEAU2@@Z"(%{{.*}}, %{{.*}}* %[[ARG1]], i32 2, %{{.*}}* %[[ARG3]], %{{.*}} %[[TMP]])
+ // WIN64: call {{.*}} @"??0A@inalloca_virt@@QEAA@UQ@@H0$$QEAU2@@Z"(%{{.*}}, %{{.*}}* %[[ARG1]], i32 2, %{{.*}}* %[[ARG3]], %{{.*}} %[[TMP]])
// WIN64: br
- // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"(
- // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"(
- // WIN64: call void @"\01??_DQ@@QEAAXXZ"({{.*}}* %[[TMP]])
+ // WIN64: call {{.*}} @"??0Z@@QEAA@XZ"(
+ // WIN64: call {{.*}} @"??0Z@@QEAA@XZ"(
+ // WIN64: call void @"??1Q@@QEAA@XZ"({{.*}}* %[[TMP]])
struct C : B { using B::B; };
C c(1, 2, 3, 4);
// ITANIUM-LABEL: define linkonce_odr void @_ZN13inalloca_virt1CD1Ev(
- // MSABI-LABEL: define internal void @"\01??__Ec@inalloca_virt@@YAXXZ"(
+ // MSABI-LABEL: define internal void @"??__Ec@inalloca_virt@@YAXXZ"(
// On Win32, the inalloca call can't be forwarded so we force inlining.
// WIN32: %[[TMP:.*]] = alloca
// WIN32: call i8* @llvm.stacksave()
// WIN32: %[[ARGMEM:.*]] = alloca inalloca
- // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"(%{{.*}}* %[[TMP]], i32 4)
+ // WIN32: call {{.*}} @"??0Q@@QAE@H@Z"(%{{.*}}* %[[TMP]], i32 4)
// WIN32: %[[ARG3:.*]] = getelementptr {{.*}} %[[ARGMEM]]
- // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"({{.*}}* %[[ARG3]], i32 3)
+ // WIN32: call {{.*}} @"??0Q@@QAE@H@Z"({{.*}}* %[[ARG3]], i32 3)
// WIN32: %[[ARG1:.*]] = getelementptr {{.*}} %[[ARGMEM]]
- // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"({{.*}}* %[[ARG1]], i32 1)
+ // WIN32: call {{.*}} @"??0Q@@QAE@H@Z"({{.*}}* %[[ARG1]], i32 1)
// WIN32: store i32 1, i32* %[[IS_MOST_DERIVED_ADDR:.*]]
// WIN32: %[[IS_MOST_DERIVED:.*]] = load i32, i32* %[[IS_MOST_DERIVED_ADDR]]
// WIN32: %[[IS_MOST_DERIVED_i1:.*]] = icmp ne i32 %[[IS_MOST_DERIVED]], 0
// WIN32: br i1 %[[IS_MOST_DERIVED_i1]]
//
- // WIN32: store {{.*}} @"\01??_8C@inalloca_virt@@7B@"
+ // WIN32: store {{.*}} @"??_8C@inalloca_virt@@7B@"
// WIN32: %[[ARG2:.*]] = getelementptr {{.*}} %[[ARGMEM]]
// WIN32: store i32 2, i32* %[[ARG2]]
// WIN32: %[[ARG4:.*]] = getelementptr {{.*}} %[[ARGMEM]]
// WIN32: store {{.*}}* %[[TMP]], {{.*}}** %[[ARG4]]
- // WIN32: call {{.*}} @"\01??0A@inalloca_virt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]])
+ // WIN32: call {{.*}} @"??0A@inalloca_virt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]])
// WIN32: call void @llvm.stackrestore(
// WIN32: br
//
@@ -276,32 +276,32 @@ namespace inalloca_virt {
// WIN32: br i1 %[[IS_MOST_DERIVED_i1]]
//
// Note: this block is unreachable.
- // WIN32: store {{.*}} @"\01??_8B@inalloca_virt@@7B@"
+ // WIN32: store {{.*}} @"??_8B@inalloca_virt@@7B@"
// WIN32: br
//
- // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"(
- // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"(
- // WIN32: call {{.*}} @"\01??_DQ@@QAEXXZ"(
+ // WIN32: call {{.*}} @"??0Z@@QAE@XZ"(
+ // WIN32: call {{.*}} @"??0Z@@QAE@XZ"(
+ // WIN32: call {{.*}} @"??1Q@@QAE@XZ"(
// On Win64, the Q arguments would be destroyed in the callee. We don't yet
// support that in the non-inlined case, so we force inlining.
// WIN64: %[[TMP:.*]] = alloca
// WIN64: %[[ARG3:.*]] = alloca
// WIN64: %[[ARG1:.*]] = alloca
- // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[TMP]], i32 4)
- // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[ARG3]], i32 3)
- // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[ARG1]], i32 1)
+ // WIN64: call {{.*}} @"??0Q@@QEAA@H@Z"({{.*}}* %[[TMP]], i32 4)
+ // WIN64: call {{.*}} @"??0Q@@QEAA@H@Z"({{.*}}* %[[ARG3]], i32 3)
+ // WIN64: call {{.*}} @"??0Q@@QEAA@H@Z"({{.*}}* %[[ARG1]], i32 1)
// WIN64: br i1
- // WIN64: store {{.*}} @"\01??_8C@inalloca_virt@@7B@"
- // WIN64: call {{.*}} @"\01??0A@inalloca_virt@@QEAA@UQ@@H0$$QEAU2@@Z"(%{{.*}}, %{{.*}}* %[[ARG1]], i32 2, %{{.*}}* %[[ARG3]], %{{.*}} %[[TMP]])
+ // WIN64: store {{.*}} @"??_8C@inalloca_virt@@7B@"
+ // WIN64: call {{.*}} @"??0A@inalloca_virt@@QEAA@UQ@@H0$$QEAU2@@Z"(%{{.*}}, %{{.*}}* %[[ARG1]], i32 2, %{{.*}}* %[[ARG3]], %{{.*}} %[[TMP]])
// WIN64: br
// WIN64: br i1
// (Unreachable block)
- // WIN64: store {{.*}} @"\01??_8B@inalloca_virt@@7B@"
+ // WIN64: store {{.*}} @"??_8B@inalloca_virt@@7B@"
// WIN64: br
- // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"(
- // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"(
- // WIN64: call void @"\01??_DQ@@QEAAXXZ"({{.*}}* %[[TMP]])
+ // WIN64: call {{.*}} @"??0Z@@QEAA@XZ"(
+ // WIN64: call {{.*}} @"??0Z@@QEAA@XZ"(
+ // WIN64: call void @"??1Q@@QEAA@XZ"({{.*}}* %[[TMP]])
}
namespace inline_nonvirt {
diff --git a/test/CodeGenCXX/initializer-list-ctor-order.cpp b/test/CodeGenCXX/initializer-list-ctor-order.cpp
index 390fe4f5c304..6bb9c1b07b73 100644
--- a/test/CodeGenCXX/initializer-list-ctor-order.cpp
+++ b/test/CodeGenCXX/initializer-list-ctor-order.cpp
@@ -15,7 +15,7 @@ void foo() {
A a{f(), g()};
}
// CHECK-ITANIUM-LABEL: define void @_Z3foov
-// CHECK-MS-LABEL: define void @"\01?foo@@YAXXZ"
+// CHECK-MS-LABEL: define dso_local void @"?foo@@YAXXZ"
// CHECK: call i32 @f()
// CHECK: call i32 @g()
@@ -24,6 +24,6 @@ struct B : A {
};
B::B() : A{f(), g()} {}
// CHECK-ITANIUM-LABEL: define void @_ZN1BC2Ev
-// CHECK-MS-LABEL: define x86_thiscallcc %struct.B* @"\01??0B@@QAE@XZ"
+// CHECK-MS-LABEL: define dso_local x86_thiscallcc %struct.B* @"??0B@@QAE@XZ"
// CHECK: call i32 @f()
// CHECK: call i32 @g()
diff --git a/test/CodeGenCXX/inline-dllexport-member.cpp b/test/CodeGenCXX/inline-dllexport-member.cpp
index a98f5601d3bc..d6b004d66dc6 100644
--- a/test/CodeGenCXX/inline-dllexport-member.cpp
+++ b/test/CodeGenCXX/inline-dllexport-member.cpp
@@ -1,13 +1,13 @@
// RUN: %clang_cc1 -triple i686-windows-win32 -fms-extensions -debug-info-kind=limited -emit-llvm %s -o - \
// RUN: | FileCheck %s
-// CHECK: @"\01?ui@s@@2IB" = weak_odr dllexport constant i32 0, comdat, align 4, !dbg [[UI:![0-9]+]]
+// CHECK: @"?ui@s@@2IB" = weak_odr dso_local dllexport constant i32 0, comdat, align 4, !dbg [[UI:![0-9]+]]
struct __declspec(dllexport) s {
static const unsigned int ui = 0;
};
// CHECK: [[UI]] = !DIGlobalVariableExpression(var: [[UIV:.*]], expr: !DIExpression())
-// CHECK: [[UIV]] = distinct !DIGlobalVariable(name: "ui", linkageName: "\01?ui@s@@2IB", scope: ![[SCOPE:[0-9]+]],
+// CHECK: [[UIV]] = distinct !DIGlobalVariable(name: "ui", linkageName: "?ui@s@@2IB", scope: ![[SCOPE:[0-9]+]],
// CHECK: ![[SCOPE]] = distinct !DICompileUnit(
diff --git a/test/CodeGenCXX/inline-functions.cpp b/test/CodeGenCXX/inline-functions.cpp
index f1169f91913e..95aec8b5d684 100644
--- a/test/CodeGenCXX/inline-functions.cpp
+++ b/test/CodeGenCXX/inline-functions.cpp
@@ -7,7 +7,7 @@ struct A {
};
// NORMAL-NOT: define void @_ZN1A1fEv
-// MSVCCOMPAT-NOT: define void @"\01?f@A@@QEAAXXZ"
+// MSVCCOMPAT-NOT: define void @"?f@A@@QEAAXXZ"
void A::f() { }
template<typename> struct B { };
@@ -17,20 +17,20 @@ template<> struct B<char> {
};
// NORMAL-NOT: _ZN1BIcE1fEv
-// MSVCCOMPAT-NOT: @"\01?f@?$B@D@@QEAAXXZ"
+// MSVCCOMPAT-NOT: @"?f@?$B@D@@QEAAXXZ"
void B<char>::f() { }
// We need a final CHECK line here.
// NORMAL-LABEL: define void @_Z1fv
-// MSVCCOMPAT-LABEL: define void @"\01?f@@YAXXZ"
+// MSVCCOMPAT-LABEL: define dso_local void @"?f@@YAXXZ"
void f() { }
// <rdar://problem/8740363>
inline void f1(int);
// NORMAL-LABEL: define linkonce_odr void @_Z2f1i
-// MSVCCOMPAT-LABEL: define linkonce_odr void @"\01?f1@@YAXH@Z"
+// MSVCCOMPAT-LABEL: define linkonce_odr dso_local void @"?f1@@YAXH@Z"
void f1(int) { }
void test_f1() { f1(17); }
@@ -44,7 +44,7 @@ namespace test1 {
};
// NORMAL-LABEL: define linkonce_odr void @_ZN5test11C4funcEv(
- // MSVCCOMPAT-LABEL: define linkonce_odr void @"\01?func@C@test1@@QEAAXXZ"(
+ // MSVCCOMPAT-LABEL: define linkonce_odr dso_local void @"?func@C@test1@@QEAAXXZ"(
class C {
public:
@@ -72,47 +72,47 @@ namespace test2 {
f(a);
}
// NORMAL-LABEL: define linkonce_odr void @_ZN5test21fERKNS_1AE
- // MSVCCOMPAT-LABEL: define linkonce_odr void @"\01?f@test2@@YAXAEBUA@1@@Z"
+ // MSVCCOMPAT-LABEL: define linkonce_odr dso_local void @"?f@test2@@YAXAEBUA@1@@Z"
}
// NORMAL-NOT: _Z17ExternAndInlineFnv
-// MSVCCOMPAT-LABEL: define weak_odr void @"\01?ExternAndInlineFn@@YAXXZ"
+// MSVCCOMPAT-LABEL: define weak_odr dso_local void @"?ExternAndInlineFn@@YAXXZ"
extern inline void ExternAndInlineFn() {}
// NORMAL-NOT: _Z18InlineThenExternFnv
-// MSVCCOMPAT-LABEL: define weak_odr void @"\01?InlineThenExternFn@@YAXXZ"
+// MSVCCOMPAT-LABEL: define weak_odr dso_local void @"?InlineThenExternFn@@YAXXZ"
inline void InlineThenExternFn() {}
extern void InlineThenExternFn();
// NORMAL-LABEL: define void @_Z18ExternThenInlineFnv
-// MSVCCOMPAT-LABEL: define void @"\01?ExternThenInlineFn@@YAXXZ"
+// MSVCCOMPAT-LABEL: define dso_local void @"?ExternThenInlineFn@@YAXXZ"
extern void ExternThenInlineFn() {}
// NORMAL-NOT: _Z25ExternThenInlineThenDefFnv
-// MSVCCOMPAT-LABEL: define weak_odr void @"\01?ExternThenInlineThenDefFn@@YAXXZ"
+// MSVCCOMPAT-LABEL: define weak_odr dso_local void @"?ExternThenInlineThenDefFn@@YAXXZ"
extern void ExternThenInlineThenDefFn();
inline void ExternThenInlineThenDefFn();
void ExternThenInlineThenDefFn() {}
// NORMAL-NOT: _Z25InlineThenExternThenDefFnv
-// MSVCCOMPAT-LABEL: define weak_odr void @"\01?InlineThenExternThenDefFn@@YAXXZ"
+// MSVCCOMPAT-LABEL: define weak_odr dso_local void @"?InlineThenExternThenDefFn@@YAXXZ"
inline void InlineThenExternThenDefFn();
extern void InlineThenExternThenDefFn();
void InlineThenExternThenDefFn() {}
// NORMAL-NOT: _Z17ExternAndConstexprFnv
-// MSVCCOMPAT-LABEL: define weak_odr i32 @"\01?ExternAndConstexprFn@@YAHXZ"
+// MSVCCOMPAT-LABEL: define weak_odr dso_local i32 @"?ExternAndConstexprFn@@YAHXZ"
extern constexpr int ExternAndConstexprFn() { return 0; }
// NORMAL-NOT: _Z11ConstexprFnv
-// MSVCCOMPAT-NOT: @"\01?ConstexprFn@@YAHXZ"
+// MSVCCOMPAT-NOT: @"?ConstexprFn@@YAHXZ"
constexpr int ConstexprFn() { return 0; }
template <typename T>
extern inline void ExternInlineOnPrimaryTemplate(T);
// NORMAL-LABEL: define void @_Z29ExternInlineOnPrimaryTemplateIiEvT_
-// MSVCCOMPAT-LABEL: define void @"\01??$ExternInlineOnPrimaryTemplate@H@@YAXH@Z"
+// MSVCCOMPAT-LABEL: define dso_local void @"??$ExternInlineOnPrimaryTemplate@H@@YAXH@Z"
template <>
void ExternInlineOnPrimaryTemplate(int) {}
@@ -120,16 +120,16 @@ template <typename T>
extern inline void ExternInlineOnPrimaryTemplateAndSpecialization(T);
// NORMAL-NOT: _Z46ExternInlineOnPrimaryTemplateAndSpecializationIiEvT_
-// MSVCCOMPAT-LABEL: define weak_odr void @"\01??$ExternInlineOnPrimaryTemplateAndSpecialization@H@@YAXH@Z"
+// MSVCCOMPAT-LABEL: define weak_odr dso_local void @"??$ExternInlineOnPrimaryTemplateAndSpecialization@H@@YAXH@Z"
template <>
extern inline void ExternInlineOnPrimaryTemplateAndSpecialization(int) {}
struct TypeWithInlineMethods {
// NORMAL-NOT: _ZN21TypeWithInlineMethods9StaticFunEv
- // MSVCCOMPAT-NOT: @"\01?StaticFun@TypeWithInlineMethods@@SAXXZ"
+ // MSVCCOMPAT-NOT: @"?StaticFun@TypeWithInlineMethods@@SAXXZ"
static void StaticFun() {}
// NORMAL-NOT: _ZN21TypeWithInlineMethods12NonStaticFunEv
- // MSVCCOMPAT-NOT: @"\01?NonStaticFun@TypeWithInlineMethods@@QEAAXXZ"
+ // MSVCCOMPAT-NOT: @"?NonStaticFun@TypeWithInlineMethods@@QEAAXXZ"
void NonStaticFun() { StaticFun(); }
};
@@ -146,5 +146,5 @@ struct S {
__attribute__((used)) inline S<int> Foo() { return S<int>(); }
// NORMAL-LABEL: define linkonce_odr void @_ZN7PR229593FooEv(
-// MSVCCOMPAT-LABEL: define linkonce_odr i8 @"\01?Foo@PR22959@@YA?AU?$S@H@1@XZ"(
+// MSVCCOMPAT-LABEL: define linkonce_odr dso_local i8 @"?Foo@PR22959@@YA?AU?$S@H@1@XZ"(
}
diff --git a/test/CodeGenCXX/inline-hint.cpp b/test/CodeGenCXX/inline-hint.cpp
index c4de751ba76e..e8c067dec174 100644
--- a/test/CodeGenCXX/inline-hint.cpp
+++ b/test/CodeGenCXX/inline-hint.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -O2 -finline-functions -emit-llvm -disable-llvm-passes -o - | FileCheck %s --check-prefix=CHECK --check-prefix=SUITABLE
-// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -O2 -finline-hint-functions -emit-llvm -disable-llvm-passes -o - | FileCheck %s --check-prefix=CHECK --check-prefix=HINTED
-// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -O2 -fno-inline -emit-llvm -disable-llvm-passes -o - | FileCheck %s --check-prefix=CHECK --check-prefix=NOINLINE
+// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -O2 -finline-functions -emit-llvm -disable-llvm-passes -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix=CHECK --check-prefix=SUITABLE
+// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -O2 -finline-hint-functions -emit-llvm -disable-llvm-passes -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix=CHECK --check-prefix=HINTED
+// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -O2 -fno-inline -emit-llvm -disable-llvm-passes -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix=CHECK --check-prefix=NOINLINE
// Force non-trivial implicit constructors/destructors/operators for B by having explicit ones for A
struct A {
diff --git a/test/CodeGenCXX/internal-linkage.cpp b/test/CodeGenCXX/internal-linkage.cpp
index 77b16704dd17..f3c0ad18459f 100644
--- a/test/CodeGenCXX/internal-linkage.cpp
+++ b/test/CodeGenCXX/internal-linkage.cpp
@@ -51,7 +51,7 @@ extern char const * extern_nonconst_xyzzy;
char const * *test4()
{
- // CHECK: @extern_nonconst_xyzzy = global
+ // CHECK: @extern_nonconst_xyzzy = {{(dso_local )?}}global
return &extern_nonconst_xyzzy;
}
diff --git a/test/CodeGenCXX/invariant.group-for-vptrs.cpp b/test/CodeGenCXX/invariant.group-for-vptrs.cpp
index 45671e5a2c2a..d4f80dde90cd 100644
--- a/test/CodeGenCXX/invariant.group-for-vptrs.cpp
+++ b/test/CodeGenCXX/invariant.group-for-vptrs.cpp
@@ -56,7 +56,7 @@ void testInternallyVisible(bool p) {
// Checking D::D()
// CHECK-LABEL: define linkonce_odr void @_ZN1DC2Ev(
-// CHECK: = call i8* @llvm.invariant.group.barrier.p0i8(i8*
+// CHECK: = call i8* @llvm.launder.invariant.group.p0i8(i8*
// CHECK: call void @_ZN1AC2Ev(%struct.A*
// CHECK: store {{.*}} !invariant.group ![[MD]]
diff --git a/test/CodeGenCXX/lambda-expressions-inside-auto-functions.cpp b/test/CodeGenCXX/lambda-expressions-inside-auto-functions.cpp
index 0083f0826ecc..59acba7be26e 100644
--- a/test/CodeGenCXX/lambda-expressions-inside-auto-functions.cpp
+++ b/test/CodeGenCXX/lambda-expressions-inside-auto-functions.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -fblocks -emit-llvm -o - %s -fexceptions -std=c++1y | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -fblocks -emit-llvm -o - %s -fexceptions -std=c++1y | FileCheck --check-prefix CHECK_ABI_LATEST %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -fblocks -emit-llvm -o - %s -fexceptions -std=c++1y -fclang-abi-compat=6.0 | FileCheck --check-prefix CHECK_ABIV6 %s
// CHECK-LABEL: define void @_ZN19non_inline_function3fooEv
// CHECK-LABEL: define internal void @"_ZZN19non_inline_function3fooEvENK3$_0clEi"(%class.anon
@@ -52,10 +53,12 @@ struct A {
template<class T> auto foo() { return [](const T&) { return 42; }; }
};
-//CHECK-LABEL: define linkonce_odr i32 @_ZZN22inline_member_function1AIdE14default_lambdaIdEEDavENKUlRKdE_clES5_(%class.anon
+//CHECK_ABIV6: define linkonce_odr i32 @_ZZN22inline_member_function1AIdE14default_lambdaIdEEDavENKUlRKdE_clES5_(%class.anon
+//CHECK_ABI_LATEST: define linkonce_odr i32 @_ZZN22inline_member_function1AIdE14default_lambdaIdEEDavENKUlRKdE_clES4_(%class.anon
int run2 = A<double>{}.func()(3.14);
-//CHECK-LABEL: define linkonce_odr i32 @_ZZN22inline_member_function1AIcE14default_lambdaIcEEDavENKUlRKcE_clES5_(%class.anon
+//CHECK_ABIV6: define linkonce_odr i32 @_ZZN22inline_member_function1AIcE14default_lambdaIcEEDavENKUlRKcE_clES5_(%class.anon
+//CHECK_ABI_LATEST: define linkonce_odr i32 @_ZZN22inline_member_function1AIcE14default_lambdaIcEEDavENKUlRKcE_clES4_(%class.anon
int run3 = A<char>{}.func()('a');
} // end inline_member_function
diff --git a/test/CodeGenCXX/lambda-to-function-pointer-conversion.cpp b/test/CodeGenCXX/lambda-to-function-pointer-conversion.cpp
new file mode 100644
index 000000000000..87d21a3461d2
--- /dev/null
+++ b/test/CodeGenCXX/lambda-to-function-pointer-conversion.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc19.0.0 -std=c++11 -emit-llvm -o - %s | FileCheck %s
+
+// This code used to cause an assertion failure in EmitDelegateCallArg.
+
+// CHECK: define internal void @"?__invoke@<lambda_0>@?0??test@@YAXXZ@CA@UTrivial@@@Z"(
+// CHECK: call void @"??R<lambda_0>@?0??test@@YAXXZ@QEBA@UTrivial@@@Z"(
+
+// CHECK: define internal void @"??R<lambda_0>@?0??test@@YAXXZ@QEBA@UTrivial@@@Z"(
+
+struct Trivial {
+ int x;
+};
+
+void (*fnptr)(Trivial);
+
+void test() {
+ fnptr = [](Trivial a){ (void)a; };
+}
diff --git a/test/CodeGenCXX/linetable-eh.cpp b/test/CodeGenCXX/linetable-eh.cpp
index 8c0a3971c599..b31df54f7c45 100644
--- a/test/CodeGenCXX/linetable-eh.cpp
+++ b/test/CodeGenCXX/linetable-eh.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-apple-macosx10.9.0 -munwind-tables -std=c++11 -fcxx-exceptions -fexceptions %s -o - | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-apple-macosx10.9.0 -munwind-tables -std=c++11 -fcxx-exceptions -fexceptions %s -o - | FileCheck -allow-deprecated-dag-overlap %s
// Test that emitting a landing pad does not affect the line table
// entries for the code that triggered it.
diff --git a/test/CodeGenCXX/mangle-abi-tag.cpp b/test/CodeGenCXX/mangle-abi-tag.cpp
index a653ff42228a..5d84096d24cd 100644
--- a/test/CodeGenCXX/mangle-abi-tag.cpp
+++ b/test/CodeGenCXX/mangle-abi-tag.cpp
@@ -145,7 +145,7 @@ void f13_test() {
f13();
}
// f13()::L::foo[abi:C][abi:D]()
-// CHECK-DAG: define linkonce_odr %struct.E* @_ZZ3f13vEN1L3fooB1CB1DEv(
+// CHECK-DAG: define linkonce_odr {{(dso_local )?}}%struct.E* @_ZZ3f13vEN1L3fooB1CB1DEv(
// f13()::L::foo[abi:C][abi:D]()::a[abi:A][abi:B]
// CHECK-DAG: @_ZZZ3f13vEN1L3fooB1CB1DEvE1aB1AB1B =
@@ -218,7 +218,7 @@ namespace N19 {
void f19_test(N19::C<N19::A, &N19::foo>, N19::F, N19::D) {
}
// f19_test(N19::C<N19::A, &N19::foo[abi:B]>, N19::F, N19::D)
-// CHECK-DAG: define void @_Z8f19_testN3N191CINS_1AEXadL_ZNS_3fooB1BES1_NS_1DEEEEENS_1FES2_(
+// CHECK-DAG: define {{(dso_local )?}}void @_Z8f19_testN3N191CINS_1AEXadL_ZNS_3fooB1BES1_NS_1DEEEEENS_1FES2_(
namespace pr30440 {
diff --git a/test/CodeGenCXX/mangle-mingw.cpp b/test/CodeGenCXX/mangle-mingw.cpp
new file mode 100644
index 000000000000..90a9826455d4
--- /dev/null
+++ b/test/CodeGenCXX/mangle-mingw.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-w64-mingw32 | FileCheck %s
+
+int func() { return 0; }
+// CHECK-DAG: @_Z4funcv
+
+int main() { return 0; }
+// CHECK-DAG: @main
+
+int wmain() { return 0; }
+// CHECK-DAG: @wmain
+
+int WinMain() { return 0; }
+// CHECK-DAG: @WinMain
+
+int wWinMain() { return 0; }
+// CHECK-DAG: @wWinMain
+
+int DllMain() { return 0; }
+// CHECK-DAG: @DllMain
diff --git a/test/CodeGenCXX/mangle-ms-abi-examples.cpp b/test/CodeGenCXX/mangle-ms-abi-examples.cpp
index 6b6ad89b4344..2f8490ac35a8 100644
--- a/test/CodeGenCXX/mangle-ms-abi-examples.cpp
+++ b/test/CodeGenCXX/mangle-ms-abi-examples.cpp
@@ -1,10 +1,10 @@
// RUN: %clang_cc1 -fms-extensions -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -fms-compatibility-version=19.00 | FileCheck %s --check-prefix=CHECK --check-prefix=MSVC2015
// RUN: %clang_cc1 -fms-extensions -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -fms-compatibility-version=18.00 | FileCheck %s --check-prefix=CHECK --check-prefix=MSVC2013
-// CHECK: @"\01??_7B@?1??foo@A@@QAEXH@Z@6B@" =
-// CHECK: @"\01??_7D@C@?1??foo@@YAXXZ@6B@" =
-// MSVC2013: define {{.*}} @"\01?baz@E@?3??bar@C@?1??foo@@YAXXZ@QAEXXZ@QAEXXZ"(
-// MSVC2015: define {{.*}} @"\01?baz@E@?1??bar@C@?1??foo@@YAXXZ@QAEXXZ@QAEXXZ"(
+// CHECK: @"??_7B@?1??foo@A@@QAEXH@Z@6B@" =
+// CHECK: @"??_7D@C@?1??foo@@YAXXZ@6B@" =
+// MSVC2013: define {{.*}} @"?baz@E@?3??bar@C@?1??foo@@YAXXZ@QAEXXZ@QAEXXZ"(
+// MSVC2015: define {{.*}} @"?baz@E@?1??bar@C@?1??foo@@YAXXZ@QAEXXZ@QAEXXZ"(
// Microsoft Visual C++ ABI examples.
struct A {
diff --git a/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp b/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp
index ad0299ea5c12..23582c6c0316 100644
--- a/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp
+++ b/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp
@@ -2,268 +2,268 @@
// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-win32 | FileCheck -check-prefix=X64 %s
void foo(const unsigned int) {}
-// CHECK: "\01?foo@@YAXI@Z"
-// X64: "\01?foo@@YAXI@Z"
+// CHECK: "?foo@@YAXI@Z"
+// X64: "?foo@@YAXI@Z"
void foo(const double) {}
-// CHECK: "\01?foo@@YAXN@Z"
-// X64: "\01?foo@@YAXN@Z"
+// CHECK: "?foo@@YAXN@Z"
+// X64: "?foo@@YAXN@Z"
void bar(const volatile double) {}
-// CHECK: "\01?bar@@YAXN@Z"
-// X64: "\01?bar@@YAXN@Z"
+// CHECK: "?bar@@YAXN@Z"
+// X64: "?bar@@YAXN@Z"
void foo_pad(char * x) {}
-// CHECK: "\01?foo_pad@@YAXPAD@Z"
-// X64: "\01?foo_pad@@YAXPEAD@Z"
+// CHECK: "?foo_pad@@YAXPAD@Z"
+// X64: "?foo_pad@@YAXPEAD@Z"
void foo_pbd(const char * x) {}
-// CHECK: "\01?foo_pbd@@YAXPBD@Z"
-// X64: "\01?foo_pbd@@YAXPEBD@Z"
+// CHECK: "?foo_pbd@@YAXPBD@Z"
+// X64: "?foo_pbd@@YAXPEBD@Z"
void foo_pcd(volatile char * x) {}
-// CHECK: "\01?foo_pcd@@YAXPCD@Z"
-// X64: "\01?foo_pcd@@YAXPECD@Z"
+// CHECK: "?foo_pcd@@YAXPCD@Z"
+// X64: "?foo_pcd@@YAXPECD@Z"
void foo_qad(char * const x) {}
-// CHECK: "\01?foo_qad@@YAXQAD@Z"
-// X64: "\01?foo_qad@@YAXQEAD@Z"
+// CHECK: "?foo_qad@@YAXQAD@Z"
+// X64: "?foo_qad@@YAXQEAD@Z"
void foo_rad(char * volatile x) {}
-// CHECK: "\01?foo_rad@@YAXRAD@Z"
-// X64: "\01?foo_rad@@YAXREAD@Z"
+// CHECK: "?foo_rad@@YAXRAD@Z"
+// X64: "?foo_rad@@YAXREAD@Z"
void foo_sad(char * const volatile x) {}
-// CHECK: "\01?foo_sad@@YAXSAD@Z"
-// X64: "\01?foo_sad@@YAXSEAD@Z"
+// CHECK: "?foo_sad@@YAXSAD@Z"
+// X64: "?foo_sad@@YAXSEAD@Z"
void foo_piad(char * __restrict x) {}
-// CHECK: "\01?foo_piad@@YAXPIAD@Z"
-// X64: "\01?foo_piad@@YAXPEIAD@Z"
+// CHECK: "?foo_piad@@YAXPIAD@Z"
+// X64: "?foo_piad@@YAXPEIAD@Z"
void foo_qiad(char * const __restrict x) {}
-// CHECK: "\01?foo_qiad@@YAXQIAD@Z"
-// X64: "\01?foo_qiad@@YAXQEIAD@Z"
+// CHECK: "?foo_qiad@@YAXQIAD@Z"
+// X64: "?foo_qiad@@YAXQEIAD@Z"
void foo_riad(char * volatile __restrict x) {}
-// CHECK: "\01?foo_riad@@YAXRIAD@Z"
-// X64: "\01?foo_riad@@YAXREIAD@Z"
+// CHECK: "?foo_riad@@YAXRIAD@Z"
+// X64: "?foo_riad@@YAXREIAD@Z"
void foo_siad(char * const volatile __restrict x) {}
-// CHECK: "\01?foo_siad@@YAXSIAD@Z"
-// X64: "\01?foo_siad@@YAXSEIAD@Z"
+// CHECK: "?foo_siad@@YAXSIAD@Z"
+// X64: "?foo_siad@@YAXSEIAD@Z"
void foo_papad(char ** x) {}
-// CHECK: "\01?foo_papad@@YAXPAPAD@Z"
-// X64: "\01?foo_papad@@YAXPEAPEAD@Z"
+// CHECK: "?foo_papad@@YAXPAPAD@Z"
+// X64: "?foo_papad@@YAXPEAPEAD@Z"
void foo_papbd(char const ** x) {}
-// CHECK: "\01?foo_papbd@@YAXPAPBD@Z"
-// X64: "\01?foo_papbd@@YAXPEAPEBD@Z"
+// CHECK: "?foo_papbd@@YAXPAPBD@Z"
+// X64: "?foo_papbd@@YAXPEAPEBD@Z"
void foo_papcd(char volatile ** x) {}
-// CHECK: "\01?foo_papcd@@YAXPAPCD@Z"
-// X64: "\01?foo_papcd@@YAXPEAPECD@Z"
+// CHECK: "?foo_papcd@@YAXPAPCD@Z"
+// X64: "?foo_papcd@@YAXPEAPECD@Z"
void foo_pbqad(char * const* x) {}
-// CHECK: "\01?foo_pbqad@@YAXPBQAD@Z"
-// X64: "\01?foo_pbqad@@YAXPEBQEAD@Z"
+// CHECK: "?foo_pbqad@@YAXPBQAD@Z"
+// X64: "?foo_pbqad@@YAXPEBQEAD@Z"
void foo_pcrad(char * volatile* x) {}
-// CHECK: "\01?foo_pcrad@@YAXPCRAD@Z"
-// X64: "\01?foo_pcrad@@YAXPECREAD@Z"
+// CHECK: "?foo_pcrad@@YAXPCRAD@Z"
+// X64: "?foo_pcrad@@YAXPECREAD@Z"
void foo_qapad(char ** const x) {}
-// CHECK: "\01?foo_qapad@@YAXQAPAD@Z"
-// X64: "\01?foo_qapad@@YAXQEAPEAD@Z"
+// CHECK: "?foo_qapad@@YAXQAPAD@Z"
+// X64: "?foo_qapad@@YAXQEAPEAD@Z"
void foo_rapad(char ** volatile x) {}
-// CHECK: "\01?foo_rapad@@YAXRAPAD@Z"
-// X64: "\01?foo_rapad@@YAXREAPEAD@Z"
+// CHECK: "?foo_rapad@@YAXRAPAD@Z"
+// X64: "?foo_rapad@@YAXREAPEAD@Z"
void foo_pbqbd(const char * const* x) {}
-// CHECK: "\01?foo_pbqbd@@YAXPBQBD@Z"
-// X64: "\01?foo_pbqbd@@YAXPEBQEBD@Z"
+// CHECK: "?foo_pbqbd@@YAXPBQBD@Z"
+// X64: "?foo_pbqbd@@YAXPEBQEBD@Z"
void foo_pbqcd(volatile char * const* x) {}
-// CHECK: "\01?foo_pbqcd@@YAXPBQCD@Z"
-// X64: "\01?foo_pbqcd@@YAXPEBQECD@Z"
+// CHECK: "?foo_pbqcd@@YAXPBQCD@Z"
+// X64: "?foo_pbqcd@@YAXPEBQECD@Z"
void foo_pcrbd(const char * volatile* x) {}
-// CHECK: "\01?foo_pcrbd@@YAXPCRBD@Z"
-// X64: "\01?foo_pcrbd@@YAXPECREBD@Z"
+// CHECK: "?foo_pcrbd@@YAXPCRBD@Z"
+// X64: "?foo_pcrbd@@YAXPECREBD@Z"
void foo_pcrcd(volatile char * volatile* x) {}
-// CHECK: "\01?foo_pcrcd@@YAXPCRCD@Z"
-// X64: "\01?foo_pcrcd@@YAXPECRECD@Z"
+// CHECK: "?foo_pcrcd@@YAXPCRCD@Z"
+// X64: "?foo_pcrcd@@YAXPECRECD@Z"
void foo_aad(char &x) {}
-// CHECK: "\01?foo_aad@@YAXAAD@Z"
-// X64: "\01?foo_aad@@YAXAEAD@Z"
+// CHECK: "?foo_aad@@YAXAAD@Z"
+// X64: "?foo_aad@@YAXAEAD@Z"
void foo_abd(const char &x) {}
-// CHECK: "\01?foo_abd@@YAXABD@Z"
-// X64: "\01?foo_abd@@YAXAEBD@Z"
+// CHECK: "?foo_abd@@YAXABD@Z"
+// X64: "?foo_abd@@YAXAEBD@Z"
void foo_aapad(char *&x) {}
-// CHECK: "\01?foo_aapad@@YAXAAPAD@Z"
-// X64: "\01?foo_aapad@@YAXAEAPEAD@Z"
+// CHECK: "?foo_aapad@@YAXAAPAD@Z"
+// X64: "?foo_aapad@@YAXAEAPEAD@Z"
void foo_aapbd(const char *&x) {}
-// CHECK: "\01?foo_aapbd@@YAXAAPBD@Z"
-// X64: "\01?foo_aapbd@@YAXAEAPEBD@Z"
+// CHECK: "?foo_aapbd@@YAXAAPBD@Z"
+// X64: "?foo_aapbd@@YAXAEAPEBD@Z"
void foo_abqad(char * const &x) {}
-// CHECK: "\01?foo_abqad@@YAXABQAD@Z"
-// X64: "\01?foo_abqad@@YAXAEBQEAD@Z"
+// CHECK: "?foo_abqad@@YAXABQAD@Z"
+// X64: "?foo_abqad@@YAXAEBQEAD@Z"
void foo_abqbd(const char * const &x) {}
-// CHECK: "\01?foo_abqbd@@YAXABQBD@Z"
-// X64: "\01?foo_abqbd@@YAXAEBQEBD@Z"
+// CHECK: "?foo_abqbd@@YAXABQBD@Z"
+// X64: "?foo_abqbd@@YAXAEBQEBD@Z"
void foo_aay144h(int (&x)[5][5]) {}
-// CHECK: "\01?foo_aay144h@@YAXAAY144H@Z"
-// X64: "\01?foo_aay144h@@YAXAEAY144H@Z"
+// CHECK: "?foo_aay144h@@YAXAAY144H@Z"
+// X64: "?foo_aay144h@@YAXAEAY144H@Z"
void foo_aay144cbh(const int (&x)[5][5]) {}
-// CHECK: "\01?foo_aay144cbh@@YAXAAY144$$CBH@Z"
-// X64: "\01?foo_aay144cbh@@YAXAEAY144$$CBH@Z"
+// CHECK: "?foo_aay144cbh@@YAXAAY144$$CBH@Z"
+// X64: "?foo_aay144cbh@@YAXAEAY144$$CBH@Z"
void foo_qay144h(int (&&x)[5][5]) {}
-// CHECK: "\01?foo_qay144h@@YAX$$QAY144H@Z"
-// X64: "\01?foo_qay144h@@YAX$$QEAY144H@Z"
+// CHECK: "?foo_qay144h@@YAX$$QAY144H@Z"
+// X64: "?foo_qay144h@@YAX$$QEAY144H@Z"
void foo_qay144cbh(const int (&&x)[5][5]) {}
-// CHECK: "\01?foo_qay144cbh@@YAX$$QAY144$$CBH@Z"
-// X64: "\01?foo_qay144cbh@@YAX$$QEAY144$$CBH@Z"
+// CHECK: "?foo_qay144cbh@@YAX$$QAY144$$CBH@Z"
+// X64: "?foo_qay144cbh@@YAX$$QEAY144$$CBH@Z"
void foo_p6ahxz(int x()) {}
-// CHECK: "\01?foo_p6ahxz@@YAXP6AHXZ@Z"
-// X64: "\01?foo_p6ahxz@@YAXP6AHXZ@Z"
+// CHECK: "?foo_p6ahxz@@YAXP6AHXZ@Z"
+// X64: "?foo_p6ahxz@@YAXP6AHXZ@Z"
void foo_a6ahxz(int (&x)()) {}
-// CHECK: "\01?foo_a6ahxz@@YAXA6AHXZ@Z"
-// X64: "\01?foo_a6ahxz@@YAXA6AHXZ@Z"
+// CHECK: "?foo_a6ahxz@@YAXA6AHXZ@Z"
+// X64: "?foo_a6ahxz@@YAXA6AHXZ@Z"
void foo_q6ahxz(int (&&x)()) {}
-// CHECK: "\01?foo_q6ahxz@@YAX$$Q6AHXZ@Z"
-// X64: "\01?foo_q6ahxz@@YAX$$Q6AHXZ@Z"
+// CHECK: "?foo_q6ahxz@@YAX$$Q6AHXZ@Z"
+// X64: "?foo_q6ahxz@@YAX$$Q6AHXZ@Z"
void foo_qay04h(int x[5][5]) {}
-// CHECK: "\01?foo_qay04h@@YAXQAY04H@Z"
-// X64: "\01?foo_qay04h@@YAXQEAY04H@Z"
+// CHECK: "?foo_qay04h@@YAXQAY04H@Z"
+// X64: "?foo_qay04h@@YAXQEAY04H@Z"
void foo_qay04cbh(const int x[5][5]) {}
-// CHECK: "\01?foo_qay04cbh@@YAXQAY04$$CBH@Z"
-// X64: "\01?foo_qay04cbh@@YAXQEAY04$$CBH@Z"
+// CHECK: "?foo_qay04cbh@@YAXQAY04$$CBH@Z"
+// X64: "?foo_qay04cbh@@YAXQEAY04$$CBH@Z"
typedef double Vector[3];
void foo(Vector*) {}
-// CHECK: "\01?foo@@YAXPAY02N@Z"
-// X64: "\01?foo@@YAXPEAY02N@Z"
+// CHECK: "?foo@@YAXPAY02N@Z"
+// X64: "?foo@@YAXPEAY02N@Z"
void foo(Vector) {}
-// CHECK: "\01?foo@@YAXQAN@Z"
-// X64: "\01?foo@@YAXQEAN@Z"
+// CHECK: "?foo@@YAXQAN@Z"
+// X64: "?foo@@YAXQEAN@Z"
void foo_const(const Vector) {}
-// CHECK: "\01?foo_const@@YAXQBN@Z"
-// X64: "\01?foo_const@@YAXQEBN@Z"
+// CHECK: "?foo_const@@YAXQBN@Z"
+// X64: "?foo_const@@YAXQEBN@Z"
void foo_volatile(volatile Vector) {}
-// CHECK: "\01?foo_volatile@@YAXQCN@Z"
-// X64: "\01?foo_volatile@@YAXQECN@Z"
+// CHECK: "?foo_volatile@@YAXQCN@Z"
+// X64: "?foo_volatile@@YAXQECN@Z"
void foo(Vector*, const Vector, const double) {}
-// CHECK: "\01?foo@@YAXPAY02NQBNN@Z"
-// X64: "\01?foo@@YAXPEAY02NQEBNN@Z"
+// CHECK: "?foo@@YAXPAY02NQBNN@Z"
+// X64: "?foo@@YAXPEAY02NQEBNN@Z"
typedef void (*ConstFunPtr)(int *const d);
void foo_fnptrconst(ConstFunPtr f) { }
-// CHECK: "\01?foo_fnptrconst@@YAXP6AXQAH@Z@Z"
-// X64: "\01?foo_fnptrconst@@YAXP6AXQEAH@Z@Z"
+// CHECK: "?foo_fnptrconst@@YAXP6AXQAH@Z@Z"
+// X64: "?foo_fnptrconst@@YAXP6AXQEAH@Z@Z"
typedef void (*ArrayFunPtr)(int d[1]);
void foo_fnptrarray(ArrayFunPtr f) { }
-// CHECK: "\01?foo_fnptrarray@@YAXP6AXQAH@Z@Z"
-// X64: "\01?foo_fnptrarray@@YAXP6AXQEAH@Z@Z"
+// CHECK: "?foo_fnptrarray@@YAXP6AXQAH@Z@Z"
+// X64: "?foo_fnptrarray@@YAXP6AXQEAH@Z@Z"
void foo_fnptrbackref1(ArrayFunPtr f1, ArrayFunPtr f2) { }
-// CHECK: "\01?foo_fnptrbackref1@@YAXP6AXQAH@Z1@Z"
-// X64: "\01?foo_fnptrbackref1@@YAXP6AXQEAH@Z1@Z"
+// CHECK: "?foo_fnptrbackref1@@YAXP6AXQAH@Z1@Z"
+// X64: "?foo_fnptrbackref1@@YAXP6AXQEAH@Z1@Z"
void foo_fnptrbackref2(ArrayFunPtr f1, ConstFunPtr f2) { }
-// CHECK: "\01?foo_fnptrbackref2@@YAXP6AXQAH@Z1@Z"
-// X64: "\01?foo_fnptrbackref2@@YAXP6AXQEAH@Z1@Z"
+// CHECK: "?foo_fnptrbackref2@@YAXP6AXQAH@Z1@Z"
+// X64: "?foo_fnptrbackref2@@YAXP6AXQEAH@Z1@Z"
typedef void (*NormalFunPtr)(int *d);
void foo_fnptrbackref3(ArrayFunPtr f1, NormalFunPtr f2) { }
-// CHECK: "\01?foo_fnptrbackref3@@YAXP6AXQAH@Z1@Z"
-// X64: "\01?foo_fnptrbackref3@@YAXP6AXQEAH@Z1@Z"
+// CHECK: "?foo_fnptrbackref3@@YAXP6AXQAH@Z1@Z"
+// X64: "?foo_fnptrbackref3@@YAXP6AXQEAH@Z1@Z"
void foo_fnptrbackref4(NormalFunPtr f1, ArrayFunPtr f2) { }
-// CHECK: "\01?foo_fnptrbackref4@@YAXP6AXPAH@Z1@Z"
-// X64: "\01?foo_fnptrbackref4@@YAXP6AXPEAH@Z1@Z"
+// CHECK: "?foo_fnptrbackref4@@YAXP6AXPAH@Z1@Z"
+// X64: "?foo_fnptrbackref4@@YAXP6AXPEAH@Z1@Z"
ArrayFunPtr ret_fnptrarray() { return 0; }
-// CHECK: "\01?ret_fnptrarray@@YAP6AXQAH@ZXZ"
-// X64: "\01?ret_fnptrarray@@YAP6AXQEAH@ZXZ"
+// CHECK: "?ret_fnptrarray@@YAP6AXQAH@ZXZ"
+// X64: "?ret_fnptrarray@@YAP6AXQEAH@ZXZ"
// Test that we mangle the forward decl when we have a redeclaration with a
// slightly different type.
void mangle_fwd(char * const x);
void mangle_fwd(char * x) {}
-// CHECK: "\01?mangle_fwd@@YAXQAD@Z"
-// X64: "\01?mangle_fwd@@YAXQEAD@Z"
+// CHECK: "?mangle_fwd@@YAXQAD@Z"
+// X64: "?mangle_fwd@@YAXQEAD@Z"
void mangle_no_fwd(char * x) {}
-// CHECK: "\01?mangle_no_fwd@@YAXPAD@Z"
-// X64: "\01?mangle_no_fwd@@YAXPEAD@Z"
+// CHECK: "?mangle_no_fwd@@YAXPAD@Z"
+// X64: "?mangle_no_fwd@@YAXPEAD@Z"
// The first argument gets mangled as-if it were written "int *const"
// The second arg should not form a backref because it isn't qualified
void mangle_no_backref0(int[], int *) {}
-// CHECK: "\01?mangle_no_backref0@@YAXQAHPAH@Z"
-// X64: "\01?mangle_no_backref0@@YAXQEAHPEAH@Z"
+// CHECK: "?mangle_no_backref0@@YAXQAHPAH@Z"
+// X64: "?mangle_no_backref0@@YAXQEAHPEAH@Z"
void mangle_no_backref1(int[], int *const) {}
-// CHECK: "\01?mangle_no_backref1@@YAXQAHQAH@Z"
-// X64: "\01?mangle_no_backref1@@YAXQEAHQEAH@Z"
+// CHECK: "?mangle_no_backref1@@YAXQAHQAH@Z"
+// X64: "?mangle_no_backref1@@YAXQEAHQEAH@Z"
typedef void fun_type(void);
typedef void (*ptr_to_fun_type)(void);
// Pointer to function types don't backref with function types
void mangle_no_backref2(fun_type, ptr_to_fun_type) {}
-// CHECK: "\01?mangle_no_backref2@@YAXP6AXXZP6AXXZ@Z"
-// X64: "\01?mangle_no_backref2@@YAXP6AXXZP6AXXZ@Z"
+// CHECK: "?mangle_no_backref2@@YAXP6AXXZP6AXXZ@Z"
+// X64: "?mangle_no_backref2@@YAXP6AXXZP6AXXZ@Z"
void mangle_yes_backref0(int[], int []) {}
-// CHECK: "\01?mangle_yes_backref0@@YAXQAH0@Z"
-// X64: "\01?mangle_yes_backref0@@YAXQEAH0@Z"
+// CHECK: "?mangle_yes_backref0@@YAXQAH0@Z"
+// X64: "?mangle_yes_backref0@@YAXQEAH0@Z"
void mangle_yes_backref1(int *const, int *const) {}
-// CHECK: "\01?mangle_yes_backref1@@YAXQAH0@Z"
-// X64: "\01?mangle_yes_backref1@@YAXQEAH0@Z"
+// CHECK: "?mangle_yes_backref1@@YAXQAH0@Z"
+// X64: "?mangle_yes_backref1@@YAXQEAH0@Z"
void mangle_yes_backref2(fun_type *const[], ptr_to_fun_type const[]) {}
-// CHECK: "\01?mangle_yes_backref2@@YAXQBQ6AXXZ0@Z"
-// X64: "\01?mangle_yes_backref2@@YAXQEBQ6AXXZ0@Z"
+// CHECK: "?mangle_yes_backref2@@YAXQBQ6AXXZ0@Z"
+// X64: "?mangle_yes_backref2@@YAXQEBQ6AXXZ0@Z"
void mangle_yes_backref3(ptr_to_fun_type *const, void (**const)(void)) {}
-// CHECK: "\01?mangle_yes_backref3@@YAXQAP6AXXZ0@Z"
-// X64: "\01?mangle_yes_backref3@@YAXQEAP6AXXZ0@Z"
+// CHECK: "?mangle_yes_backref3@@YAXQAP6AXXZ0@Z"
+// X64: "?mangle_yes_backref3@@YAXQEAP6AXXZ0@Z"
void mangle_yes_backref4(int *const __restrict, int *const __restrict) {}
-// CHECK: "\01?mangle_yes_backref4@@YAXQIAH0@Z"
-// X64: "\01?mangle_yes_backref4@@YAXQEIAH0@Z"
+// CHECK: "?mangle_yes_backref4@@YAXQIAH0@Z"
+// X64: "?mangle_yes_backref4@@YAXQEIAH0@Z"
struct S {};
void pr23325(const S[1], const S[]) {}
-// CHECK: "\01?pr23325@@YAXQBUS@@0@Z"
-// X64: "\01?pr23325@@YAXQEBUS@@0@Z"
+// CHECK: "?pr23325@@YAXQBUS@@0@Z"
+// X64: "?pr23325@@YAXQEBUS@@0@Z"
void vla_arg(int i, int a[][i]) {}
-// CHECK: "\01?vla_arg@@YAXHQAY0A@H@Z"
-// X64: "\01?vla_arg@@YAXHQEAY0A@H@Z"
+// CHECK: "?vla_arg@@YAXHQAY0A@H@Z"
+// X64: "?vla_arg@@YAXHQEAY0A@H@Z"
diff --git a/test/CodeGenCXX/mangle-ms-back-references-pr13207.cpp b/test/CodeGenCXX/mangle-ms-back-references-pr13207.cpp
index 5d4b6722f507..c68b97e68c05 100644
--- a/test/CodeGenCXX/mangle-ms-back-references-pr13207.cpp
+++ b/test/CodeGenCXX/mangle-ms-back-references-pr13207.cpp
@@ -8,13 +8,13 @@ template<class X>
class C {};
void foo_abbb(A<B<char>, B<char>, B<char> >) {}
-// CHECK: "\01?foo_abbb@@YAXV?$A@V?$B@D@@V1@V1@@@@Z"
+// CHECK: "?foo_abbb@@YAXV?$A@V?$B@D@@V1@V1@@@@Z"
void foo_abb(A<char, B<char>, B<char> >) {}
-// CHECK: "\01?foo_abb@@YAXV?$A@DV?$B@D@@V1@@@@Z"
+// CHECK: "?foo_abb@@YAXV?$A@DV?$B@D@@V1@@@@Z"
void foo_abc(A<char, B<char>, C<char> >) {}
-// CHECK: "\01?foo_abc@@YAXV?$A@DV?$B@D@@V?$C@D@@@@@Z"
+// CHECK: "?foo_abc@@YAXV?$A@DV?$B@D@@V?$C@D@@@@@Z"
void foo_bt(bool a, B<bool(bool)> b) {}
-// CHECK: "\01?foo_bt@@YAX_NV?$B@$$A6A_N_N@Z@@@Z"
+// CHECK: "?foo_bt@@YAX_NV?$B@$$A6A_N_N@Z@@@Z"
namespace N {
template<class X, class Y, class Z>
@@ -29,11 +29,11 @@ class Z {};
}
void foo_abbb(N::A<N::B<char>, N::B<char>, N::B<char> >) {}
-// CHECK: "\01?foo_abbb@@YAXV?$A@V?$B@D@N@@V12@V12@@N@@@Z"
+// CHECK: "?foo_abbb@@YAXV?$A@V?$B@D@N@@V12@V12@@N@@@Z"
void foo_abb(N::A<char, N::B<char>, N::B<char> >) {}
-// CHECK: "\01?foo_abb@@YAXV?$A@DV?$B@D@N@@V12@@N@@@Z"
+// CHECK: "?foo_abb@@YAXV?$A@DV?$B@D@N@@V12@@N@@@Z"
void foo_abc(N::A<char, N::B<char>, N::C<char> >) {}
-// CHECK: "\01?foo_abc@@YAXV?$A@DV?$B@D@N@@V?$C@D@2@@N@@@Z"
+// CHECK: "?foo_abc@@YAXV?$A@DV?$B@D@N@@V?$C@D@2@@N@@@Z"
N::A<char, N::B<char>, N::C<char> > abc_foo() {
// CHECK: ?abc_foo@@YA?AV?$A@DV?$B@D@N@@V?$C@D@2@@N@@XZ
@@ -71,16 +71,16 @@ template<class T> class Y {};
}
void foo5(NA::Y<NB::Y<NA::Y<NB::Y<NA::X> > > > arg) {}
-// CHECK: "\01?foo5@@YAXV?$Y@V?$Y@V?$Y@V?$Y@VX@NA@@@NB@@@NA@@@NB@@@NA@@@Z"
+// CHECK: "?foo5@@YAXV?$Y@V?$Y@V?$Y@V?$Y@VX@NA@@@NB@@@NA@@@NB@@@NA@@@Z"
void foo11(NA::Y<NA::X>, NB::Y<NA::X>) {}
-// CHECK: "\01?foo11@@YAXV?$Y@VX@NA@@@NA@@V1NB@@@Z"
+// CHECK: "?foo11@@YAXV?$Y@VX@NA@@@NA@@V1NB@@@Z"
void foo112(NA::Y<NA::X>, NB::Y<NB::X>) {}
-// CHECK: "\01?foo112@@YAXV?$Y@VX@NA@@@NA@@V?$Y@VX@NB@@@NB@@@Z"
+// CHECK: "?foo112@@YAXV?$Y@VX@NA@@@NA@@V?$Y@VX@NB@@@NB@@@Z"
void foo22(NA::Y<NB::Y<NA::X> >, NB::Y<NA::Y<NA::X> >) {}
-// CHECK: "\01?foo22@@YAXV?$Y@V?$Y@VX@NA@@@NB@@@NA@@V?$Y@V?$Y@VX@NA@@@NA@@@NB@@@Z"
+// CHECK: "?foo22@@YAXV?$Y@V?$Y@VX@NA@@@NB@@@NA@@V?$Y@V?$Y@VX@NA@@@NA@@@NB@@@Z"
namespace PR13207 {
class A {};
@@ -100,56 +100,56 @@ class L {
public:
void foo(I<A> x) {}
};
-// CHECK: "\01?foo@L@PR13207@@QAEXV?$I@VA@PR13207@@@2@@Z"
+// CHECK: "?foo@L@PR13207@@QAEXV?$I@VA@PR13207@@@2@@Z"
void call_l_foo(L* l) { l->foo(I<A>()); }
void foo(I<A> x) {}
-// CHECK: "\01?foo@PR13207@@YAXV?$I@VA@PR13207@@@1@@Z"
+// CHECK: "?foo@PR13207@@YAXV?$I@VA@PR13207@@@1@@Z"
void foo2(I<A> x, I<A> y) { }
-// CHECK: "\01?foo2@PR13207@@YAXV?$I@VA@PR13207@@@1@0@Z"
+// CHECK: "?foo2@PR13207@@YAXV?$I@VA@PR13207@@@1@0@Z"
void bar(J<A,B> x) {}
-// CHECK: "\01?bar@PR13207@@YAXV?$J@VA@PR13207@@VB@2@@1@@Z"
+// CHECK: "?bar@PR13207@@YAXV?$J@VA@PR13207@@VB@2@@1@@Z"
void spam(K<A,B,C> x) {}
-// CHECK: "\01?spam@PR13207@@YAXV?$K@VA@PR13207@@VB@2@VC@2@@1@@Z"
+// CHECK: "?spam@PR13207@@YAXV?$K@VA@PR13207@@VB@2@VC@2@@1@@Z"
void baz(K<char, F<char>, I<char> >) {}
-// CHECK: "\01?baz@PR13207@@YAXV?$K@DV?$F@D@PR13207@@V?$I@D@2@@1@@Z"
+// CHECK: "?baz@PR13207@@YAXV?$K@DV?$F@D@PR13207@@V?$I@D@2@@1@@Z"
void qux(K<char, I<char>, I<char> >) {}
-// CHECK: "\01?qux@PR13207@@YAXV?$K@DV?$I@D@PR13207@@V12@@1@@Z"
+// CHECK: "?qux@PR13207@@YAXV?$K@DV?$I@D@PR13207@@V12@@1@@Z"
namespace NA {
class X {};
template<class T> class Y {};
void foo(Y<X> x) {}
-// CHECK: "\01?foo@NA@PR13207@@YAXV?$Y@VX@NA@PR13207@@@12@@Z"
+// CHECK: "?foo@NA@PR13207@@YAXV?$Y@VX@NA@PR13207@@@12@@Z"
void foofoo(Y<Y<X> > x) {}
-// CHECK: "\01?foofoo@NA@PR13207@@YAXV?$Y@V?$Y@VX@NA@PR13207@@@NA@PR13207@@@12@@Z"
+// CHECK: "?foofoo@NA@PR13207@@YAXV?$Y@V?$Y@VX@NA@PR13207@@@NA@PR13207@@@12@@Z"
}
namespace NB {
class X {};
template<class T> class Y {};
void foo(Y<NA::X> x) {}
-// CHECK: "\01?foo@NB@PR13207@@YAXV?$Y@VX@NA@PR13207@@@12@@Z"
+// CHECK: "?foo@NB@PR13207@@YAXV?$Y@VX@NA@PR13207@@@12@@Z"
void bar(NA::Y<X> x) {}
-// CHECK: "\01?bar@NB@PR13207@@YAXV?$Y@VX@NB@PR13207@@@NA@2@@Z"
+// CHECK: "?bar@NB@PR13207@@YAXV?$Y@VX@NB@PR13207@@@NA@2@@Z"
void spam(NA::Y<NA::X> x) {}
-// CHECK: "\01?spam@NB@PR13207@@YAXV?$Y@VX@NA@PR13207@@@NA@2@@Z"
+// CHECK: "?spam@NB@PR13207@@YAXV?$Y@VX@NA@PR13207@@@NA@2@@Z"
void foobar(NA::Y<Y<X> > a, Y<Y<X> >) {}
-// CHECK: "\01?foobar@NB@PR13207@@YAXV?$Y@V?$Y@VX@NB@PR13207@@@NB@PR13207@@@NA@2@V312@@Z"
+// CHECK: "?foobar@NB@PR13207@@YAXV?$Y@V?$Y@VX@NB@PR13207@@@NB@PR13207@@@NA@2@V312@@Z"
void foobarspam(Y<X> a, NA::Y<Y<X> > b, Y<Y<X> >) {}
-// CHECK: "\01?foobarspam@NB@PR13207@@YAXV?$Y@VX@NB@PR13207@@@12@V?$Y@V?$Y@VX@NB@PR13207@@@NB@PR13207@@@NA@2@V412@@Z"
+// CHECK: "?foobarspam@NB@PR13207@@YAXV?$Y@VX@NB@PR13207@@@12@V?$Y@V?$Y@VX@NB@PR13207@@@NB@PR13207@@@NA@2@V412@@Z"
void foobarbaz(Y<X> a, NA::Y<Y<X> > b, Y<Y<X> >, Y<Y<X> > c) {}
-// CHECK: "\01?foobarbaz@NB@PR13207@@YAXV?$Y@VX@NB@PR13207@@@12@V?$Y@V?$Y@VX@NB@PR13207@@@NB@PR13207@@@NA@2@V412@2@Z"
+// CHECK: "?foobarbaz@NB@PR13207@@YAXV?$Y@VX@NB@PR13207@@@12@V?$Y@V?$Y@VX@NB@PR13207@@@NB@PR13207@@@NA@2@V412@2@Z"
void foobarbazqux(Y<X> a, NA::Y<Y<X> > b, Y<Y<X> >, Y<Y<X> > c , NA::Y<Y<Y<X> > > d) {}
-// CHECK: "\01?foobarbazqux@NB@PR13207@@YAXV?$Y@VX@NB@PR13207@@@12@V?$Y@V?$Y@VX@NB@PR13207@@@NB@PR13207@@@NA@2@V412@2V?$Y@V?$Y@V?$Y@VX@NB@PR13207@@@NB@PR13207@@@NB@PR13207@@@52@@Z"
+// CHECK: "?foobarbazqux@NB@PR13207@@YAXV?$Y@VX@NB@PR13207@@@12@V?$Y@V?$Y@VX@NB@PR13207@@@NB@PR13207@@@NA@2@V412@2V?$Y@V?$Y@V?$Y@VX@NB@PR13207@@@NB@PR13207@@@NB@PR13207@@@52@@Z"
}
namespace NC {
@@ -157,10 +157,10 @@ class X {};
template<class T> class Y {};
void foo(Y<NB::X> x) {}
-// CHECK: "\01?foo@NC@PR13207@@YAXV?$Y@VX@NB@PR13207@@@12@@Z"
+// CHECK: "?foo@NC@PR13207@@YAXV?$Y@VX@NB@PR13207@@@12@@Z"
void foobar(NC::Y<NB::Y<NA::Y<NA::X> > > x) {}
-// CHECK: "\01?foobar@NC@PR13207@@YAXV?$Y@V?$Y@V?$Y@VX@NA@PR13207@@@NA@PR13207@@@NB@PR13207@@@12@@Z"
+// CHECK: "?foobar@NC@PR13207@@YAXV?$Y@V?$Y@V?$Y@VX@NA@PR13207@@@NA@PR13207@@@NB@PR13207@@@12@@Z"
}
}
@@ -175,8 +175,8 @@ void fun_instantiate() {
fun_normal(1);
fun_tmpl(1);
}
-// CHECK: "\01?fun_normal@fn_space@@YA?AURetVal@1@H@Z"
-// CHECK: "\01??$fun_tmpl@H@fn_space@@YA?AURetVal@0@ABH@Z"
+// CHECK: "?fun_normal@fn_space@@YA?AURetVal@1@H@Z"
+// CHECK: "??$fun_tmpl@H@fn_space@@YA?AURetVal@0@ABH@Z"
template <typename T, RetVal (*F)(T)>
RetVal fun_tmpl_recurse(T t) {
@@ -188,6 +188,6 @@ RetVal ident(int x) { return RetVal(); }
void fun_instantiate2() {
fun_tmpl_recurse<int, fun_tmpl_recurse<int, ident> >(10);
}
-// CHECK: "\01??$fun_tmpl_recurse@H$1??$fun_tmpl_recurse@H$1?ident@fn_space@@YA?AURetVal@2@H@Z@fn_space@@YA?AURetVal@1@H@Z@fn_space@@YA?AURetVal@0@H@Z"
-// CHECK: "\01??$fun_tmpl_recurse@H$1?ident@fn_space@@YA?AURetVal@2@H@Z@fn_space@@YA?AURetVal@0@H@Z"
+// CHECK: "??$fun_tmpl_recurse@H$1??$fun_tmpl_recurse@H$1?ident@fn_space@@YA?AURetVal@2@H@Z@fn_space@@YA?AURetVal@1@H@Z@fn_space@@YA?AURetVal@0@H@Z"
+// CHECK: "??$fun_tmpl_recurse@H$1?ident@fn_space@@YA?AURetVal@2@H@Z@fn_space@@YA?AURetVal@0@H@Z"
}
diff --git a/test/CodeGenCXX/mangle-ms-back-references.cpp b/test/CodeGenCXX/mangle-ms-back-references.cpp
index 25a058a30dbe..cd4d1e249458 100644
--- a/test/CodeGenCXX/mangle-ms-back-references.cpp
+++ b/test/CodeGenCXX/mangle-ms-back-references.cpp
@@ -1,25 +1,25 @@
// RUN: %clang_cc1 -fms-extensions -fblocks -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s
void f1(const char* a, const char* b) {}
-// CHECK: "\01?f1@@YAXPBD0@Z"
+// CHECK: "?f1@@YAXPBD0@Z"
void f2(const char* a, char* b) {}
-// CHECK: "\01?f2@@YAXPBDPAD@Z"
+// CHECK: "?f2@@YAXPBDPAD@Z"
void f3(int a, const char* b, const char* c) {}
-// CHECK: "\01?f3@@YAXHPBD0@Z"
+// CHECK: "?f3@@YAXHPBD0@Z"
const char *f4(const char* a, const char* b) { return 0; }
-// CHECK: "\01?f4@@YAPBDPBD0@Z"
+// CHECK: "?f4@@YAPBDPBD0@Z"
void f5(char const* a, unsigned int b, char c, void const* d, char const* e, unsigned int f) {}
-// CHECK: "\01?f5@@YAXPBDIDPBX0I@Z"
+// CHECK: "?f5@@YAXPBDIDPBX0I@Z"
void f6(bool a, bool b) {}
-// CHECK: "\01?f6@@YAX_N0@Z"
+// CHECK: "?f6@@YAX_N0@Z"
void f7(int a, int* b, int c, int* d, bool e, bool f, bool* g) {}
-// CHECK: "\01?f7@@YAXHPAHH0_N1PA_N@Z"
+// CHECK: "?f7@@YAXHPAHH0_N1PA_N@Z"
// FIXME: tests for more than 10 types?
@@ -28,18 +28,18 @@ struct S {
};
void g1(struct S a) {}
-// CHECK: "\01?g1@@YAXUS@@@Z"
+// CHECK: "?g1@@YAXUS@@@Z"
void g2(struct S a, struct S b) {}
-// CHECK: "\01?g2@@YAXUS@@0@Z"
+// CHECK: "?g2@@YAXUS@@0@Z"
void g3(struct S a, struct S b, struct S* c, struct S* d) {}
-// CHECK: "\01?g3@@YAXUS@@0PAU1@1@Z"
+// CHECK: "?g3@@YAXUS@@0PAU1@1@Z"
void g4(const char* a, struct S* b, const char* c, struct S* d) {
-// CHECK: "\01?g4@@YAXPBDPAUS@@01@Z"
+// CHECK: "?g4@@YAXPBDPAUS@@01@Z"
b->mbb(false, false);
-// CHECK: "\01?mbb@S@@QAEX_N0@Z"
+// CHECK: "?mbb@S@@QAEX_N0@Z"
}
// Make sure that different aliases of built-in types end up mangled as the
@@ -47,22 +47,22 @@ void g4(const char* a, struct S* b, const char* c, struct S* d) {
typedef unsigned int uintptr_t;
typedef unsigned int size_t;
void *h(size_t a, uintptr_t b) { return 0; }
-// CHECK: "\01?h@@YAPAXII@Z"
+// CHECK: "?h@@YAPAXII@Z"
// Function pointers might be mangled in a complex way.
typedef void (*VoidFunc)();
typedef int* (*PInt3Func)(int* a, int* b);
void h1(const char* a, const char* b, VoidFunc c, VoidFunc d) {}
-// CHECK: "\01?h1@@YAXPBD0P6AXXZ1@Z"
+// CHECK: "?h1@@YAXPBD0P6AXXZ1@Z"
void h2(void (*f_ptr)(void *), void *arg) {}
-// CHECK: "\01?h2@@YAXP6AXPAX@Z0@Z"
+// CHECK: "?h2@@YAXP6AXPAX@Z0@Z"
PInt3Func h3(PInt3Func x, PInt3Func y, int* z) { return 0; }
-// CHECK: "\01?h3@@YAP6APAHPAH0@ZP6APAH00@Z10@Z"
+// CHECK: "?h3@@YAP6APAHPAH0@ZP6APAH00@Z10@Z"
namespace foo {
void foo() { }
-// CHECK: "\01?foo@0@YAXXZ"
+// CHECK: "?foo@0@YAXXZ"
}
diff --git a/test/CodeGenCXX/mangle-ms-cxx11.cpp b/test/CodeGenCXX/mangle-ms-cxx11.cpp
index b22c04698ea2..1e3b7ceca717 100644
--- a/test/CodeGenCXX/mangle-ms-cxx11.cpp
+++ b/test/CodeGenCXX/mangle-ms-cxx11.cpp
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 -std=c++11 -fms-extensions -emit-llvm %s -o - -triple=i386-pc-win32 -fms-compatibility-version=19.00 | FileCheck %s --check-prefix=CHECK --check-prefix=MSVC2015
// RUN: %clang_cc1 -std=c++11 -fms-extensions -emit-llvm %s -o - -triple=i386-pc-win32 -fms-compatibility-version=18.00 | FileCheck %s --check-prefix=CHECK --check-prefix=MSVC2013
+// RUN: %clang_cc1 -std=c++11 -fms-extensions -emit-llvm %s -o - -triple=i386-pc-win32 -gcodeview -debug-info-kind=limited | FileCheck %s --check-prefix=DBG
namespace FTypeWithQuals {
template <typename T>
@@ -7,69 +8,69 @@ struct S {};
using A = int () const;
S<A> a;
-// CHECK-DAG: @"\01?a@FTypeWithQuals@@3U?$S@$$A8@@BAHXZ@1@A"
+// CHECK-DAG: @"?a@FTypeWithQuals@@3U?$S@$$A8@@BAHXZ@1@A"
using B = int () volatile;
S<B> b;
-// CHECK-DAG: @"\01?b@FTypeWithQuals@@3U?$S@$$A8@@CAHXZ@1@A"
+// CHECK-DAG: @"?b@FTypeWithQuals@@3U?$S@$$A8@@CAHXZ@1@A"
using C = int () __restrict;
S<C> c;
-// CHECK-DAG: @"\01?c@FTypeWithQuals@@3U?$S@$$A8@@IAAHXZ@1@A"
+// CHECK-DAG: @"?c@FTypeWithQuals@@3U?$S@$$A8@@IAAHXZ@1@A"
using D = int () const &;
S<D> d;
-// CHECK-DAG: @"\01?d@FTypeWithQuals@@3U?$S@$$A8@@GBAHXZ@1@A"
+// CHECK-DAG: @"?d@FTypeWithQuals@@3U?$S@$$A8@@GBAHXZ@1@A"
using E = int () volatile &;
S<E> e;
-// CHECK-DAG: @"\01?e@FTypeWithQuals@@3U?$S@$$A8@@GCAHXZ@1@A"
+// CHECK-DAG: @"?e@FTypeWithQuals@@3U?$S@$$A8@@GCAHXZ@1@A"
using F = int () __restrict &;
S<F> f;
-// CHECK-DAG: @"\01?f@FTypeWithQuals@@3U?$S@$$A8@@IGAAHXZ@1@A"
+// CHECK-DAG: @"?f@FTypeWithQuals@@3U?$S@$$A8@@IGAAHXZ@1@A"
using G = int () const &&;
S<G> g;
-// CHECK-DAG: @"\01?g@FTypeWithQuals@@3U?$S@$$A8@@HBAHXZ@1@A"
+// CHECK-DAG: @"?g@FTypeWithQuals@@3U?$S@$$A8@@HBAHXZ@1@A"
using H = int () volatile &&;
S<H> h;
-// CHECK-DAG: @"\01?h@FTypeWithQuals@@3U?$S@$$A8@@HCAHXZ@1@A"
+// CHECK-DAG: @"?h@FTypeWithQuals@@3U?$S@$$A8@@HCAHXZ@1@A"
using I = int () __restrict &&;
S<I> i;
-// CHECK-DAG: @"\01?i@FTypeWithQuals@@3U?$S@$$A8@@IHAAHXZ@1@A"
+// CHECK-DAG: @"?i@FTypeWithQuals@@3U?$S@$$A8@@IHAAHXZ@1@A"
using J = int ();
S<J> j;
-// CHECK-DAG: @"\01?j@FTypeWithQuals@@3U?$S@$$A6AHXZ@1@A"
+// CHECK-DAG: @"?j@FTypeWithQuals@@3U?$S@$$A6AHXZ@1@A"
using K = int () &;
S<K> k;
-// CHECK-DAG: @"\01?k@FTypeWithQuals@@3U?$S@$$A8@@GAAHXZ@1@A"
+// CHECK-DAG: @"?k@FTypeWithQuals@@3U?$S@$$A8@@GAAHXZ@1@A"
using L = int () &&;
S<L> l;
-// CHECK-DAG: @"\01?l@FTypeWithQuals@@3U?$S@$$A8@@HAAHXZ@1@A"
+// CHECK-DAG: @"?l@FTypeWithQuals@@3U?$S@$$A8@@HAAHXZ@1@A"
}
-// CHECK: "\01?DeducedType@@3HA"
+// CHECK: "?DeducedType@@3HA"
auto DeducedType = 30;
-// CHECK-DAG: @"\01?Char16Var@@3_SA"
+// CHECK-DAG: @"?Char16Var@@3_SA"
char16_t Char16Var;
-// CHECK-DAG: @"\01?Char32Var@@3_UA"
+// CHECK-DAG: @"?Char32Var@@3_UA"
char32_t Char32Var;
-// CHECK: "\01?LRef@@YAXAAH@Z"
+// CHECK: "?LRef@@YAXAAH@Z"
void LRef(int& a) { }
-// CHECK: "\01?RRef@@YAH$$QAH@Z"
+// CHECK: "?RRef@@YAH$$QAH@Z"
int RRef(int&& a) { return a; }
-// CHECK: "\01?Null@@YAX$$T@Z"
+// CHECK: "?Null@@YAX$$T@Z"
namespace std { typedef decltype(__nullptr) nullptr_t; }
void Null(std::nullptr_t) {}
@@ -87,19 +88,19 @@ namespace EnumMangling {
extern enum Enum11 : unsigned long { } ULongEnum;
extern enum Enum12 : long long { } SLongLongEnum;
extern enum Enum13 : unsigned long long { } ULongLongEnum;
-// CHECK-DAG: @"\01?Enum@EnumMangling@@3W4Enum01@1@A"
-// CHECK-DAG: @"\01?BoolEnum@EnumMangling@@3W4Enum02@1@A
-// CHECK-DAG: @"\01?CharEnum@EnumMangling@@3W4Enum03@1@A
-// CHECK-DAG: @"\01?SCharEnum@EnumMangling@@3W4Enum04@1@A
-// CHECK-DAG: @"\01?UCharEnum@EnumMangling@@3W4Enum05@1@A
-// CHECK-DAG: @"\01?SShortEnum@EnumMangling@@3W4Enum06@1@A"
-// CHECK-DAG: @"\01?UShortEnum@EnumMangling@@3W4Enum07@1@A"
-// CHECK-DAG: @"\01?SIntEnum@EnumMangling@@3W4Enum08@1@A"
-// CHECK-DAG: @"\01?UIntEnum@EnumMangling@@3W4Enum09@1@A"
-// CHECK-DAG: @"\01?SLongEnum@EnumMangling@@3W4Enum10@1@A"
-// CHECK-DAG: @"\01?ULongEnum@EnumMangling@@3W4Enum11@1@A"
-// CHECK-DAG: @"\01?SLongLongEnum@EnumMangling@@3W4Enum12@1@A"
-// CHECK-DAG: @"\01?ULongLongEnum@EnumMangling@@3W4Enum13@1@A"
+// CHECK-DAG: @"?Enum@EnumMangling@@3W4Enum01@1@A"
+// CHECK-DAG: @"?BoolEnum@EnumMangling@@3W4Enum02@1@A
+// CHECK-DAG: @"?CharEnum@EnumMangling@@3W4Enum03@1@A
+// CHECK-DAG: @"?SCharEnum@EnumMangling@@3W4Enum04@1@A
+// CHECK-DAG: @"?UCharEnum@EnumMangling@@3W4Enum05@1@A
+// CHECK-DAG: @"?SShortEnum@EnumMangling@@3W4Enum06@1@A"
+// CHECK-DAG: @"?UShortEnum@EnumMangling@@3W4Enum07@1@A"
+// CHECK-DAG: @"?SIntEnum@EnumMangling@@3W4Enum08@1@A"
+// CHECK-DAG: @"?UIntEnum@EnumMangling@@3W4Enum09@1@A"
+// CHECK-DAG: @"?SLongEnum@EnumMangling@@3W4Enum10@1@A"
+// CHECK-DAG: @"?ULongEnum@EnumMangling@@3W4Enum11@1@A"
+// CHECK-DAG: @"?SLongLongEnum@EnumMangling@@3W4Enum12@1@A"
+// CHECK-DAG: @"?ULongLongEnum@EnumMangling@@3W4Enum13@1@A"
decltype(Enum) *UseEnum() { return &Enum; }
decltype(BoolEnum) *UseBoolEnum() { return &BoolEnum; }
decltype(CharEnum) *UseCharEnum() { return &CharEnum; }
@@ -126,19 +127,19 @@ namespace EnumMangling {
extern enum class EnumClass11 : unsigned long { } ULongEnumClass;
extern enum class EnumClass12 : long long { } SLongLongEnumClass;
extern enum class EnumClass13 : unsigned long long { } ULongLongEnumClass;
-// CHECK-DAG: @"\01?EnumClass@EnumMangling@@3W4EnumClass01@1@A"
-// CHECK-DAG: @"\01?BoolEnumClass@EnumMangling@@3W4EnumClass02@1@A
-// CHECK-DAG: @"\01?CharEnumClass@EnumMangling@@3W4EnumClass03@1@A
-// CHECK-DAG: @"\01?SCharEnumClass@EnumMangling@@3W4EnumClass04@1@A
-// CHECK-DAG: @"\01?UCharEnumClass@EnumMangling@@3W4EnumClass05@1@A
-// CHECK-DAG: @"\01?SShortEnumClass@EnumMangling@@3W4EnumClass06@1@A"
-// CHECK-DAG: @"\01?UShortEnumClass@EnumMangling@@3W4EnumClass07@1@A"
-// CHECK-DAG: @"\01?SIntEnumClass@EnumMangling@@3W4EnumClass08@1@A"
-// CHECK-DAG: @"\01?UIntEnumClass@EnumMangling@@3W4EnumClass09@1@A"
-// CHECK-DAG: @"\01?SLongEnumClass@EnumMangling@@3W4EnumClass10@1@A"
-// CHECK-DAG: @"\01?ULongEnumClass@EnumMangling@@3W4EnumClass11@1@A"
-// CHECK-DAG: @"\01?SLongLongEnumClass@EnumMangling@@3W4EnumClass12@1@A"
-// CHECK-DAG: @"\01?ULongLongEnumClass@EnumMangling@@3W4EnumClass13@1@A"
+// CHECK-DAG: @"?EnumClass@EnumMangling@@3W4EnumClass01@1@A"
+// CHECK-DAG: @"?BoolEnumClass@EnumMangling@@3W4EnumClass02@1@A
+// CHECK-DAG: @"?CharEnumClass@EnumMangling@@3W4EnumClass03@1@A
+// CHECK-DAG: @"?SCharEnumClass@EnumMangling@@3W4EnumClass04@1@A
+// CHECK-DAG: @"?UCharEnumClass@EnumMangling@@3W4EnumClass05@1@A
+// CHECK-DAG: @"?SShortEnumClass@EnumMangling@@3W4EnumClass06@1@A"
+// CHECK-DAG: @"?UShortEnumClass@EnumMangling@@3W4EnumClass07@1@A"
+// CHECK-DAG: @"?SIntEnumClass@EnumMangling@@3W4EnumClass08@1@A"
+// CHECK-DAG: @"?UIntEnumClass@EnumMangling@@3W4EnumClass09@1@A"
+// CHECK-DAG: @"?SLongEnumClass@EnumMangling@@3W4EnumClass10@1@A"
+// CHECK-DAG: @"?ULongEnumClass@EnumMangling@@3W4EnumClass11@1@A"
+// CHECK-DAG: @"?SLongLongEnumClass@EnumMangling@@3W4EnumClass12@1@A"
+// CHECK-DAG: @"?ULongLongEnumClass@EnumMangling@@3W4EnumClass13@1@A"
decltype(EnumClass) *UseEnumClass() { return &EnumClass; }
decltype(BoolEnumClass) *UseBoolEnumClass() { return &BoolEnumClass; }
decltype(CharEnumClass) *UseCharEnumClass() { return &CharEnumClass; }
@@ -158,7 +159,7 @@ namespace PR18022 {
struct { } a;
decltype(a) fun(decltype(a) x, decltype(a)) { return x; }
-// CHECK-DAG: @"\01?fun@PR18022@@YA?AU<unnamed-type-a>@1@U21@0@Z"
+// CHECK-DAG: @"?fun@PR18022@@YA?AU<unnamed-type-a>@1@U21@0@Z"
void use_fun() { fun(a, a); }
@@ -168,14 +169,14 @@ inline int define_lambda() {
static auto lambda = [] { static int local; ++local; return local; };
// First, we have the static local variable of type "<lambda_1>" inside of
// "define_lambda".
-// CHECK-DAG: @"\01?lambda@?1??define_lambda@@YAHXZ@4V<lambda_1>@?0??1@YAHXZ@A"
+// CHECK-DAG: @"?lambda@?1??define_lambda@@YAHXZ@4V<lambda_1>@?0??1@YAHXZ@A"
// Next, we have the "operator()" for "<lambda_1>" which is inside of
// "define_lambda".
-// CHECK-DAG: @"\01??R<lambda_1>@?0??define_lambda@@YAHXZ@QBE@XZ"
+// CHECK-DAG: @"??R<lambda_1>@?0??define_lambda@@YAHXZ@QBE@XZ"
// Finally, we have the local which is inside of "<lambda_1>" which is inside of
// "define_lambda". Hooray.
-// MSVC2013-DAG: @"\01?local@?2???R<lambda_1>@?0??define_lambda@@YAHXZ@QBE@XZ@4HA"
-// MSVC2015-DAG: @"\01?local@?1???R<lambda_1>@?0??define_lambda@@YAHXZ@QBE@XZ@4HA"
+// MSVC2013-DAG: @"?local@?2???R<lambda_1>@?0??define_lambda@@YAHXZ@QBE@XZ@4HA"
+// MSVC2015-DAG: @"?local@?1???R<lambda_1>@?0??define_lambda@@YAHXZ@QBE@XZ@4HA"
return lambda();
}
@@ -184,12 +185,12 @@ void use_lambda_arg(T) {}
inline void call_with_lambda_arg1() {
use_lambda_arg([]{});
- // CHECK-DAG: @"\01??$use_lambda_arg@V<lambda_1>@?0??call_with_lambda_arg1@@YAXXZ@@@YAXV<lambda_1>@?0??call_with_lambda_arg1@@YAXXZ@@Z"
+ // CHECK-DAG: @"??$use_lambda_arg@V<lambda_1>@?0??call_with_lambda_arg1@@YAXXZ@@@YAXV<lambda_1>@?0??call_with_lambda_arg1@@YAXXZ@@Z"
}
inline void call_with_lambda_arg2() {
use_lambda_arg([]{});
- // CHECK-DAG: @"\01??$use_lambda_arg@V<lambda_1>@?0??call_with_lambda_arg2@@YAXXZ@@@YAXV<lambda_1>@?0??call_with_lambda_arg2@@YAXXZ@@Z"
+ // CHECK-DAG: @"??$use_lambda_arg@V<lambda_1>@?0??call_with_lambda_arg2@@YAXXZ@@@YAXV<lambda_1>@?0??call_with_lambda_arg2@@YAXXZ@@Z"
}
int call_lambda() {
@@ -204,33 +205,33 @@ struct A {
void foo() __restrict &&;
};
void A::foo() __restrict & {}
-// CHECK-DAG: @"\01?foo@A@PR19361@@QIGAEXXZ"
+// CHECK-DAG: @"?foo@A@PR19361@@QIGAEXXZ"
void A::foo() __restrict && {}
-// CHECK-DAG: @"\01?foo@A@PR19361@@QIHAEXXZ"
+// CHECK-DAG: @"?foo@A@PR19361@@QIHAEXXZ"
}
int operator"" _deg(long double) { return 0; }
-// CHECK-DAG: @"\01??__K_deg@@YAHO@Z"
+// CHECK-DAG: @"??__K_deg@@YAHO@Z"
template <char...>
void templ_fun_with_pack() {}
template void templ_fun_with_pack<>();
-// CHECK-DAG: @"\01??$templ_fun_with_pack@$S@@YAXXZ"
+// CHECK-DAG: @"??$templ_fun_with_pack@$S@@YAXXZ"
template <typename...>
void templ_fun_with_ty_pack() {}
template void templ_fun_with_ty_pack<>();
-// MSVC2013-DAG: @"\01??$templ_fun_with_ty_pack@$$$V@@YAXXZ"
-// MSVC2015-DAG: @"\01??$templ_fun_with_ty_pack@$$V@@YAXXZ"
+// MSVC2013-DAG: @"??$templ_fun_with_ty_pack@$$$V@@YAXXZ"
+// MSVC2015-DAG: @"??$templ_fun_with_ty_pack@$$V@@YAXXZ"
template <template <class> class...>
void templ_fun_with_templ_templ_pack() {}
template void templ_fun_with_templ_templ_pack<>();
-// MSVC2013-DAG: @"\01??$templ_fun_with_templ_templ_pack@$$$V@@YAXXZ"
-// MSVC2015-DAG: @"\01??$templ_fun_with_templ_templ_pack@$$V@@YAXXZ"
+// MSVC2013-DAG: @"??$templ_fun_with_templ_templ_pack@$$$V@@YAXXZ"
+// MSVC2015-DAG: @"??$templ_fun_with_templ_templ_pack@$$V@@YAXXZ"
namespace PR20047 {
template <typename T>
@@ -243,7 +244,7 @@ template <template <typename> class>
void f() {}
template void f<AliasA>();
-// CHECK-DAG: @"\01??$f@$$YAliasA@PR20047@@@PR20047@@YAXXZ"
+// CHECK-DAG: @"??$f@$$YAliasA@PR20047@@@PR20047@@YAXXZ"
}
namespace UnnamedType {
@@ -252,7 +253,7 @@ struct A {
};
void f(decltype(*A::TD)) {}
-// CHECK-DAG: @"\01?f@UnnamedType@@YAXAAU<unnamed-type-TD>@A@1@@Z"
+// CHECK-DAG: @"?f@UnnamedType@@YAXAAU<unnamed-type-TD>@A@1@@Z"
template <typename T>
struct B {
@@ -261,7 +262,7 @@ struct B {
};
void f(decltype(B<int>::e)) {}
-// CHECK-DAG: @"\01?f@UnnamedType@@YAXPAW4<unnamed-type-e>@?$B@H@1@@Z
+// CHECK-DAG: @"?f@UnnamedType@@YAXPAW4<unnamed-type-e>@?$B@H@1@@Z
}
namespace PR24651 {
@@ -276,8 +277,8 @@ void g() {
f(E);
}
}
-// CHECK-DAG: @"\01??$f@W4<unnamed-type-E>@?1??g@PR24651@@YAXXZ@@PR24651@@YAXW4<unnamed-type-E>@?1??g@0@YAXXZ@@Z"
-// CHECK-DAG: @"\01??$f@W4<unnamed-type-E>@?2??g@PR24651@@YAXXZ@@PR24651@@YAXW4<unnamed-type-E>@?2??g@0@YAXXZ@@Z"
+// CHECK-DAG: @"??$f@W4<unnamed-type-E>@?1??g@PR24651@@YAXXZ@@PR24651@@YAXW4<unnamed-type-E>@?1??g@0@YAXXZ@@Z"
+// CHECK-DAG: @"??$f@W4<unnamed-type-E>@?2??g@PR24651@@YAXXZ@@PR24651@@YAXW4<unnamed-type-E>@?2??g@0@YAXXZ@@Z"
}
namespace PR18204 {
@@ -286,15 +287,15 @@ int f(T *) { return 0; }
static union {
int n = f(this);
};
-// CHECK-DAG: @"\01??$f@T<unnamed-type-$S1>@PR18204@@@PR18204@@YAHPAT<unnamed-type-$S1>@0@@Z"
+// CHECK-DAG: @"??$f@T<unnamed-type-$S1>@PR18204@@@PR18204@@YAHPAT<unnamed-type-$S1>@0@@Z"
}
int PR26105() {
auto add = [](int x) { return ([x](int y) { return x + y; }); };
return add(3)(4);
}
-// CHECK-DAG: @"\01??R<lambda_0>@?0??PR26105@@YAHXZ@QBE@H@Z"
-// CHECK-DAG: @"\01??R<lambda_1>@?0???R<lambda_0>@?0??PR26105@@YAHXZ@QBE@H@Z@QBE@H@Z"
+// CHECK-DAG: @"??R<lambda_0>@?0??PR26105@@YAHXZ@QBE@H@Z"
+// CHECK-DAG: @"??R<lambda_1>@?0???R<lambda_0>@?0??PR26105@@YAHXZ@QBE@H@Z@QBE@H@Z"
int __unaligned * unaligned_foo1() { return 0; }
int __unaligned * __unaligned * unaligned_foo2() { return 0; }
@@ -304,13 +305,13 @@ void unaligned_foo5(int __unaligned * __restrict p1) {}
template <typename T> T unaligned_foo6(T t) { return t; }
void unaligned_foo7() { unaligned_foo6<int *>(0); unaligned_foo6<int __unaligned *>(0); }
-// CHECK-DAG: @"\01?unaligned_foo1@@YAPFAHXZ"
-// CHECK-DAG: @"\01?unaligned_foo2@@YAPFAPFAHXZ"
-// CHECK-DAG: @"\01?unaligned_foo3@@YAHXZ"
-// CHECK-DAG: @"\01?unaligned_foo4@@YAXPFAH@Z"
-// CHECK-DAG: @"\01?unaligned_foo5@@YAXPIFAH@Z"
-// CHECK-DAG: @"\01??$unaligned_foo6@PAH@@YAPAHPAH@Z"
-// CHECK-DAG: @"\01??$unaligned_foo6@PFAH@@YAPFAHPFAH@Z"
+// CHECK-DAG: @"?unaligned_foo1@@YAPFAHXZ"
+// CHECK-DAG: @"?unaligned_foo2@@YAPFAPFAHXZ"
+// CHECK-DAG: @"?unaligned_foo3@@YAHXZ"
+// CHECK-DAG: @"?unaligned_foo4@@YAXPFAH@Z"
+// CHECK-DAG: @"?unaligned_foo5@@YAXPIFAH@Z"
+// CHECK-DAG: @"??$unaligned_foo6@PAH@@YAPAHPAH@Z"
+// CHECK-DAG: @"??$unaligned_foo6@PFAH@@YAPFAHPFAH@Z"
// __unaligned qualifier for function types
struct unaligned_foo8_S {
@@ -318,28 +319,28 @@ struct unaligned_foo8_S {
};
void unaligned_foo8_S::unaligned_foo8() volatile __unaligned {}
-// CHECK-DAG: @"\01?unaligned_foo8@unaligned_foo8_S@@QFCEXXZ"
+// CHECK-DAG: @"?unaligned_foo8@unaligned_foo8_S@@QFCEXXZ"
namespace PR31197 {
struct A {
- // CHECK-DAG: define linkonce_odr x86_thiscallcc i32* @"\01??R<lambda_1>@x@A@PR31197@@QBE@XZ"(
+ // CHECK-DAG: define linkonce_odr dso_local x86_thiscallcc i32* @"??R<lambda_1>@x@A@PR31197@@QBE@XZ"(
int *x = []() {
static int white;
- // CHECK-DAG: @"\01?white@?1???R<lambda_1>@x@A@PR31197@@QBE@XZ@4HA"
+ // CHECK-DAG: @"?white@?1???R<lambda_1>@x@A@PR31197@@QBE@XZ@4HA"
return &white;
}();
- // CHECK-DAG: define linkonce_odr x86_thiscallcc i32* @"\01??R<lambda_1>@y@A@PR31197@@QBE@XZ"(
+ // CHECK-DAG: define linkonce_odr dso_local x86_thiscallcc i32* @"??R<lambda_1>@y@A@PR31197@@QBE@XZ"(
int *y = []() {
static int black;
- // CHECK-DAG: @"\01?black@?1???R<lambda_1>@y@A@PR31197@@QBE@XZ@4HA"
+ // CHECK-DAG: @"?black@?1???R<lambda_1>@y@A@PR31197@@QBE@XZ@4HA"
return &black;
}();
using FPtrTy = void(void);
static void default_args(FPtrTy x = [] {}, FPtrTy y = [] {}, int z = [] { return 1; }() + [] { return 2; }()) {}
- // CHECK-DAG: @"\01??R<lambda_1_1>@?0??default_args@A@PR31197@@SAXP6AXXZ0H@Z@QBE@XZ"(
- // CHECK-DAG: @"\01??R<lambda_1_2>@?0??default_args@A@PR31197@@SAXP6AXXZ0H@Z@QBE@XZ"(
- // CHECK-DAG: @"\01??R<lambda_2_1>@?0??default_args@A@PR31197@@SAXP6AXXZ0H@Z@QBE@XZ"(
- // CHECK-DAG: @"\01??R<lambda_3_1>@?0??default_args@A@PR31197@@SAXP6AXXZ0H@Z@QBE@XZ"(
+ // CHECK-DAG: @"??R<lambda_1_1>@?0??default_args@A@PR31197@@SAXP6AXXZ0H@Z@QBE@XZ"(
+ // CHECK-DAG: @"??R<lambda_1_2>@?0??default_args@A@PR31197@@SAXP6AXXZ0H@Z@QBE@XZ"(
+ // CHECK-DAG: @"??R<lambda_2_1>@?0??default_args@A@PR31197@@SAXP6AXXZ0H@Z@QBE@XZ"(
+ // CHECK-DAG: @"??R<lambda_3_1>@?0??default_args@A@PR31197@@SAXP6AXXZ0H@Z@QBE@XZ"(
};
A a;
@@ -348,5 +349,12 @@ int call_it = (A::default_args(), 1);
enum { enumerator };
void f(decltype(enumerator)) {}
-// CHECK-DAG: define internal void @"\01?f@@YAXW4<unnamed-enum-enumerator>@@@Z"(
+// CHECK-DAG: define internal void @"?f@@YAXW4<unnamed-enum-enumerator>@@@Z"(
void use_f() { f(enumerator); }
+
+namespace pr37723 {
+struct s { enum {}; enum {}; };
+// DBG-DAG: DW_TAG_enumeration_type{{.*}}identifier: ".?AW4<unnamed-type-$S2>@s@pr37723@@"
+// DBG-DAG: DW_TAG_enumeration_type{{.*}}identifier: ".?AW4<unnamed-type-$S3>@s@pr37723@@"
+s x;
+}
diff --git a/test/CodeGenCXX/mangle-ms-cxx14.cpp b/test/CodeGenCXX/mangle-ms-cxx14.cpp
index 798a390aeaaa..c58d055880a1 100644
--- a/test/CodeGenCXX/mangle-ms-cxx14.cpp
+++ b/test/CodeGenCXX/mangle-ms-cxx14.cpp
@@ -1,29 +1,29 @@
-// RUN: %clang_cc1 -std=c++1y -fms-extensions -emit-llvm %s -o - -triple=i386-pc-win32 -fms-compatibility-version=19.00 | FileCheck %s --check-prefix=CHECK --check-prefix=MSVC2015
-// RUN: %clang_cc1 -std=c++1y -fms-extensions -emit-llvm %s -o - -triple=i386-pc-win32 -fms-compatibility-version=18.00 | FileCheck %s --check-prefix=CHECK --check-prefix=MSVC2013
+// RUN: %clang_cc1 -std=c++1y -fms-extensions -emit-llvm %s -o - -triple=i386-pc-win32 -fms-compatibility-version=19.00 | FileCheck -allow-deprecated-dag-overlap %s --check-prefix=CHECK --check-prefix=MSVC2015
+// RUN: %clang_cc1 -std=c++1y -fms-extensions -emit-llvm %s -o - -triple=i386-pc-win32 -fms-compatibility-version=18.00 | FileCheck -allow-deprecated-dag-overlap %s --check-prefix=CHECK --check-prefix=MSVC2013
template <typename> int x = 0;
-// CHECK-DAG: "\01??$x@X@@3HA"
+// CHECK-DAG: "??$x@X@@3HA"
template <> int x<void>;
-// CHECK-DAG: "\01??$x@H@@3HA"
+// CHECK-DAG: "??$x@H@@3HA"
template <> int x<int>;
-// CHECK-DAG: "\01?FunctionWithLocalType@@YA?A?<auto>@@XZ"
+// CHECK-DAG: "?FunctionWithLocalType@@YA?A?<auto>@@XZ"
auto FunctionWithLocalType() {
struct LocalType {};
return LocalType{};
}
-// CHECK-DAG: "\01?ValueFromFunctionWithLocalType@@3ULocalType@?1??FunctionWithLocalType@@YA?A?<auto>@@XZ@A"
+// CHECK-DAG: "?ValueFromFunctionWithLocalType@@3ULocalType@?1??FunctionWithLocalType@@YA?A?<auto>@@XZ@A"
auto ValueFromFunctionWithLocalType = FunctionWithLocalType();
-// CHECK-DAG: "\01??R<lambda_0>@@QBE?A?<auto>@@XZ"
+// CHECK-DAG: "??R<lambda_0>@@QBE?A?<auto>@@XZ"
auto LambdaWithLocalType = [] {
struct LocalType {};
return LocalType{};
};
-// CHECK-DAG: "\01?ValueFromLambdaWithLocalType@@3ULocalType@?1???R<lambda_0>@@QBE?A?<auto>@@XZ@A"
+// CHECK-DAG: "?ValueFromLambdaWithLocalType@@3ULocalType@?1???R<lambda_0>@@QBE?A?<auto>@@XZ@A"
auto ValueFromLambdaWithLocalType = LambdaWithLocalType();
template <typename T>
@@ -35,12 +35,12 @@ auto TemplateFuncionWithLocalLambda(T) {
return LocalLambdaWithLocalType();
}
-// MSVC2013-DAG: "\01?ValueFromTemplateFuncionWithLocalLambda@@3ULocalType@?2???R<lambda_1>@?0???$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBE?A?3@XZ@A"
-// MSVC2013-DAG: "\01?ValueFromTemplateFuncionWithLocalLambda@@3ULocalType@?2???R<lambda_1>@?0???$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBE?A?3@XZ@A"
-// MSVC2015-DAG: "\01?ValueFromTemplateFuncionWithLocalLambda@@3ULocalType@?1???R<lambda_1>@?0???$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBE?A?3@XZ@A"
-// MSVC2015-DAG: "\01?ValueFromTemplateFuncionWithLocalLambda@@3ULocalType@?1???R<lambda_1>@?0???$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBE?A?3@XZ@A"
-// CHECK-DAG: "\01??$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z"
-// CHECK-DAG: "\01??R<lambda_1>@?0???$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBE?A?1@XZ"
+// MSVC2013-DAG: "?ValueFromTemplateFuncionWithLocalLambda@@3ULocalType@?2???R<lambda_1>@?0???$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBE?A?3@XZ@A"
+// MSVC2013-DAG: "?ValueFromTemplateFuncionWithLocalLambda@@3ULocalType@?2???R<lambda_1>@?0???$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBE?A?3@XZ@A"
+// MSVC2015-DAG: "?ValueFromTemplateFuncionWithLocalLambda@@3ULocalType@?1???R<lambda_1>@?0???$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBE?A?3@XZ@A"
+// MSVC2015-DAG: "?ValueFromTemplateFuncionWithLocalLambda@@3ULocalType@?1???R<lambda_1>@?0???$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBE?A?3@XZ@A"
+// CHECK-DAG: "??$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z"
+// CHECK-DAG: "??R<lambda_1>@?0???$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBE?A?1@XZ"
auto ValueFromTemplateFuncionWithLocalLambda = TemplateFuncionWithLocalLambda(0);
struct S;
@@ -48,15 +48,15 @@ template <int S::*>
int WithPMD = 0;
template <> int WithPMD<nullptr>;
-// CHECK-DAG: "\01??$WithPMD@$GA@A@?0@@3HA"
+// CHECK-DAG: "??$WithPMD@$GA@A@?0@@3HA"
template <const int *, const int *>
struct Foo {};
Foo<&x<int>, &x<int>> Zoo;
-// CHECK-DAG: "\01?Zoo@@3U?$Foo@$1??$x@H@@3HA$1?1@3HA@@A"
+// CHECK-DAG: "?Zoo@@3U?$Foo@$1??$x@H@@3HA$1?1@3HA@@A"
template <typename T> T unaligned_x;
extern auto test_unaligned() { return unaligned_x<int __unaligned *>; }
-// CHECK-DAG: "\01??$unaligned_x@PFAH@@3PFAHA"
+// CHECK-DAG: "??$unaligned_x@PFAH@@3PFAHA"
diff --git a/test/CodeGenCXX/mangle-ms-md5.cpp b/test/CodeGenCXX/mangle-ms-md5.cpp
index aef268304832..740fd61576cc 100644
--- a/test/CodeGenCXX/mangle-ms-md5.cpp
+++ b/test/CodeGenCXX/mangle-ms-md5.cpp
@@ -1,11 +1,11 @@
// RUN: %clang_cc1 -emit-llvm -o - -triple i686-pc-win32 %s | FileCheck %s
int xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
-// CHECK-DAG: @"\01??@bf7ea7b95f260b0b24e7f1e8fc8370ab@" = global i32 0, align 4
+// CHECK-DAG: @"??@bf7ea7b95f260b0b24e7f1e8fc8370ab@" = dso_local global i32 0, align 4
struct yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy {
yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy();
virtual void f();
};
yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy::yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy() {}
-// CHECK-DAG: @"\01??@a6a285da2eea70dba6b578022be61d81@??_R4@" = linkonce_odr constant %rtti.CompleteObjectLocator
-// CHECK-DAG: @"\01??@a6a285da2eea70dba6b578022be61d81@" = unnamed_addr alias
+// CHECK-DAG: @"??@a6a285da2eea70dba6b578022be61d81@??_R4@" = linkonce_odr constant %rtti.CompleteObjectLocator
+// CHECK-DAG: @"??@a6a285da2eea70dba6b578022be61d81@" = unnamed_addr alias
diff --git a/test/CodeGenCXX/mangle-ms-return-qualifiers.cpp b/test/CodeGenCXX/mangle-ms-return-qualifiers.cpp
index 8b666e4f7d62..0054279692fb 100644
--- a/test/CodeGenCXX/mangle-ms-return-qualifiers.cpp
+++ b/test/CodeGenCXX/mangle-ms-return-qualifiers.cpp
@@ -1,189 +1,189 @@
// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s
void a1() {}
-// CHECK: "\01?a1@@YAXXZ"
+// CHECK: "?a1@@YAXXZ"
int a2() { return 0; }
-// CHECK: "\01?a2@@YAHXZ"
+// CHECK: "?a2@@YAHXZ"
const int a3() { return 0; }
-// CHECK: "\01?a3@@YA?BHXZ"
+// CHECK: "?a3@@YA?BHXZ"
volatile int a4() { return 0; }
-// CHECK: "\01?a4@@YA?CHXZ"
+// CHECK: "?a4@@YA?CHXZ"
const volatile int a5() { return 0; }
-// CHECK: "\01?a5@@YA?DHXZ"
+// CHECK: "?a5@@YA?DHXZ"
float a6() { return 0.0f; }
-// CHECK: "\01?a6@@YAMXZ"
+// CHECK: "?a6@@YAMXZ"
int *b1() { return 0; }
-// CHECK: "\01?b1@@YAPAHXZ"
+// CHECK: "?b1@@YAPAHXZ"
const char *b2() { return 0; }
-// CHECK: "\01?b2@@YAPBDXZ"
+// CHECK: "?b2@@YAPBDXZ"
float *b3() { return 0; }
-// CHECK: "\01?b3@@YAPAMXZ"
+// CHECK: "?b3@@YAPAMXZ"
const float *b4() { return 0; }
-// CHECK: "\01?b4@@YAPBMXZ"
+// CHECK: "?b4@@YAPBMXZ"
volatile float *b5() { return 0; }
-// CHECK: "\01?b5@@YAPCMXZ"
+// CHECK: "?b5@@YAPCMXZ"
const volatile float *b6() { return 0; }
-// CHECK: "\01?b6@@YAPDMXZ"
+// CHECK: "?b6@@YAPDMXZ"
float &b7() { return *(float*)0; }
-// CHECK: "\01?b7@@YAAAMXZ"
+// CHECK: "?b7@@YAAAMXZ"
const float &b8() { return *(float*)0; }
-// CHECK: "\01?b8@@YAABMXZ"
+// CHECK: "?b8@@YAABMXZ"
volatile float &b9() { return *(float*)0; }
-// CHECK: "\01?b9@@YAACMXZ"
+// CHECK: "?b9@@YAACMXZ"
const volatile float &b10() { return *(float*)0; }
-// CHECK: "\01?b10@@YAADMXZ"
+// CHECK: "?b10@@YAADMXZ"
const char** b11() { return 0; }
-// CHECK: "\01?b11@@YAPAPBDXZ"
+// CHECK: "?b11@@YAPAPBDXZ"
class A {};
A c1() { return A(); }
-// CHECK: "\01?c1@@YA?AVA@@XZ"
+// CHECK: "?c1@@YA?AVA@@XZ"
const A c2() { return A(); }
-// CHECK: "\01?c2@@YA?BVA@@XZ"
+// CHECK: "?c2@@YA?BVA@@XZ"
volatile A c3() { return A(); }
-// CHECK: "\01?c3@@YA?CVA@@XZ"
+// CHECK: "?c3@@YA?CVA@@XZ"
const volatile A c4() { return A(); }
-// CHECK: "\01?c4@@YA?DVA@@XZ"
+// CHECK: "?c4@@YA?DVA@@XZ"
const A* c5() { return 0; }
-// CHECK: "\01?c5@@YAPBVA@@XZ"
+// CHECK: "?c5@@YAPBVA@@XZ"
volatile A* c6() { return 0; }
-// CHECK: "\01?c6@@YAPCVA@@XZ"
+// CHECK: "?c6@@YAPCVA@@XZ"
const volatile A* c7() { return 0; }
-// CHECK: "\01?c7@@YAPDVA@@XZ"
+// CHECK: "?c7@@YAPDVA@@XZ"
A &c8() { return *(A*)0; }
-// CHECK: "\01?c8@@YAAAVA@@XZ"
+// CHECK: "?c8@@YAAAVA@@XZ"
const A &c9() { return *(A*)0; }
-// CHECK: "\01?c9@@YAABVA@@XZ"
+// CHECK: "?c9@@YAABVA@@XZ"
volatile A &c10() { return *(A*)0; }
-// CHECK: "\01?c10@@YAACVA@@XZ"
+// CHECK: "?c10@@YAACVA@@XZ"
const volatile A &c11() { return *(A*)0; }
-// CHECK: "\01?c11@@YAADVA@@XZ"
+// CHECK: "?c11@@YAADVA@@XZ"
template<typename T> class B {};
B<int> d1() { return B<int>(); }
-// CHECK: "\01?d1@@YA?AV?$B@H@@XZ"
+// CHECK: "?d1@@YA?AV?$B@H@@XZ"
B<const char*> d2() {return B<const char*>(); }
-// CHECK: "\01?d2@@YA?AV?$B@PBD@@XZ"
+// CHECK: "?d2@@YA?AV?$B@PBD@@XZ"
B<A> d3() {return B<A>(); }
-// CHECK: "\01?d3@@YA?AV?$B@VA@@@@XZ"
+// CHECK: "?d3@@YA?AV?$B@VA@@@@XZ"
B<A>* d4() { return 0; }
-// CHECK: "\01?d4@@YAPAV?$B@VA@@@@XZ"
+// CHECK: "?d4@@YAPAV?$B@VA@@@@XZ"
const B<A>* d5() { return 0; }
-// CHECK: "\01?d5@@YAPBV?$B@VA@@@@XZ"
+// CHECK: "?d5@@YAPBV?$B@VA@@@@XZ"
volatile B<A>* d6() { return 0; }
-// CHECK: "\01?d6@@YAPCV?$B@VA@@@@XZ"
+// CHECK: "?d6@@YAPCV?$B@VA@@@@XZ"
const volatile B<A>* d7() { return 0; }
-// CHECK: "\01?d7@@YAPDV?$B@VA@@@@XZ"
+// CHECK: "?d7@@YAPDV?$B@VA@@@@XZ"
B<A>& d8() { return *(B<A>*)0; }
-// CHECK: "\01?d8@@YAAAV?$B@VA@@@@XZ"
+// CHECK: "?d8@@YAAAV?$B@VA@@@@XZ"
const B<A>& d9() { return *(B<A>*)0; }
-// CHECK: "\01?d9@@YAABV?$B@VA@@@@XZ"
+// CHECK: "?d9@@YAABV?$B@VA@@@@XZ"
volatile B<A>& d10() { return *(B<A>*)0; }
-// CHECK: "\01?d10@@YAACV?$B@VA@@@@XZ"
+// CHECK: "?d10@@YAACV?$B@VA@@@@XZ"
const volatile B<A>& d11() { return *(B<A>*)0; }
-// CHECK: "\01?d11@@YAADV?$B@VA@@@@XZ"
+// CHECK: "?d11@@YAADV?$B@VA@@@@XZ"
enum Enum { DEFAULT };
Enum e1() { return DEFAULT; }
-// CHECK: "\01?e1@@YA?AW4Enum@@XZ"
+// CHECK: "?e1@@YA?AW4Enum@@XZ"
const Enum e2() { return DEFAULT; }
-// CHECK: "\01?e2@@YA?BW4Enum@@XZ"
+// CHECK: "?e2@@YA?BW4Enum@@XZ"
Enum* e3() { return 0; }
-// CHECK: "\01?e3@@YAPAW4Enum@@XZ"
+// CHECK: "?e3@@YAPAW4Enum@@XZ"
Enum& e4() { return *(Enum*)0; }
-// CHECK: "\01?e4@@YAAAW4Enum@@XZ"
+// CHECK: "?e4@@YAAAW4Enum@@XZ"
struct S {};
struct S f1() { struct S s; return s; }
-// CHECK: "\01?f1@@YA?AUS@@XZ"
+// CHECK: "?f1@@YA?AUS@@XZ"
const struct S f2() { struct S s; return s; }
-// CHECK: "\01?f2@@YA?BUS@@XZ"
+// CHECK: "?f2@@YA?BUS@@XZ"
struct S* f3() { return 0; }
-// CHECK: "\01?f3@@YAPAUS@@XZ"
+// CHECK: "?f3@@YAPAUS@@XZ"
const struct S* f4() { return 0; }
-// CHECK: "\01?f4@@YAPBUS@@XZ"
+// CHECK: "?f4@@YAPBUS@@XZ"
const volatile struct S* f5() { return 0; }
-// CHECK: "\01?f5@@YAPDUS@@XZ"
+// CHECK: "?f5@@YAPDUS@@XZ"
struct S& f6() { return *(struct S*)0; }
-// CHECK: "\01?f6@@YAAAUS@@XZ"
+// CHECK: "?f6@@YAAAUS@@XZ"
struct S* const f7() { return 0; }
-// CHECK: "\01?f7@@YAQAUS@@XZ"
+// CHECK: "?f7@@YAQAUS@@XZ"
int S::* f8() { return 0; }
-// CHECK: "\01?f8@@YAPQS@@HXZ"
+// CHECK: "?f8@@YAPQS@@HXZ"
int S::* const f9() { return 0; }
-// CHECK: "\01?f9@@YAQQS@@HXZ"
+// CHECK: "?f9@@YAQQS@@HXZ"
int S::* __restrict f10() { return 0; }
-// CHECK: "\01?f10@@YAPIQS@@HXZ"
+// CHECK: "?f10@@YAPIQS@@HXZ"
int S::* const __restrict f11() { return 0; }
-// CHECK: "\01?f11@@YAQIQS@@HXZ"
+// CHECK: "?f11@@YAQIQS@@HXZ"
typedef int (*function_pointer)(int);
function_pointer g1() { return 0; }
-// CHECK: "\01?g1@@YAP6AHH@ZXZ"
+// CHECK: "?g1@@YAP6AHH@ZXZ"
const function_pointer g2() { return 0; }
-// CHECK: "\01?g2@@YAQ6AHH@ZXZ"
+// CHECK: "?g2@@YAQ6AHH@ZXZ"
function_pointer* g3() { return 0; }
-// CHECK: "\01?g3@@YAPAP6AHH@ZXZ"
+// CHECK: "?g3@@YAPAP6AHH@ZXZ"
const function_pointer* g4() { return 0; }
-// CHECK: "\01?g4@@YAPBQ6AHH@ZXZ"
+// CHECK: "?g4@@YAPBQ6AHH@ZXZ"
extern int &z;
int & __restrict h1() { return z; }
-// CHECK: "\01?h1@@YAAIAHXZ"
+// CHECK: "?h1@@YAAIAHXZ"
diff --git a/test/CodeGenCXX/mangle-ms-string-literals.cpp b/test/CodeGenCXX/mangle-ms-string-literals.cpp
index e5ebc086e148..214586d7329c 100644
--- a/test/CodeGenCXX/mangle-ms-string-literals.cpp
+++ b/test/CodeGenCXX/mangle-ms-string-literals.cpp
@@ -258,262 +258,262 @@ const char *l2 = "\x2";
const char *l1 = "\x1";
const char *l0 = "\x0";
-// CHECK: @"\01??_C@_01CNACBAHC@?$PP?$AA@"
-// CHECK: @"\01??_C@_01DEBJCBDD@?$PO?$AA@"
-// CHECK: @"\01??_C@_01BPDEHCPA@?$PN?$AA@"
-// CHECK: @"\01??_C@_01GCPEDLB@?$PM?$AA@"
-// CHECK: @"\01??_C@_01EJGONFHG@?$PL?$AA@"
-// CHECK: @"\01??_C@_01FAHFOEDH@?z?$AA@"
-// CHECK: @"\01??_C@_01HLFILHPE@?y?$AA@"
-// CHECK: @"\01??_C@_01GCEDIGLF@?x?$AA@"
-// CHECK: @"\01??_C@_01OFNLJKHK@?w?$AA@"
-// CHECK: @"\01??_C@_01PMMAKLDL@?v?$AA@"
-// CHECK: @"\01??_C@_01NHONPIPI@?u?$AA@"
-// CHECK: @"\01??_C@_01MOPGMJLJ@?t?$AA@"
-// CHECK: @"\01??_C@_01IBLHFPHO@?s?$AA@"
-// CHECK: @"\01??_C@_01JIKMGODP@?r?$AA@"
-// CHECK: @"\01??_C@_01LDIBDNPM@?q?$AA@"
-// CHECK: @"\01??_C@_01KKJKAMLN@?p?$AA@"
-// CHECK: @"\01??_C@_01GHMAACCD@?o?$AA@"
-// CHECK: @"\01??_C@_01HONLDDGC@?n?$AA@"
-// CHECK: @"\01??_C@_01FFPGGAKB@?m?$AA@"
-// CHECK: @"\01??_C@_01EMONFBOA@?l?$AA@"
-// CHECK: @"\01??_C@_01DKMMHCH@?k?$AA@"
-// CHECK: @"\01??_C@_01BKLHPGGG@?j?$AA@"
-// CHECK: @"\01??_C@_01DBJKKFKF@?i?$AA@"
-// CHECK: @"\01??_C@_01CIIBJEOE@?h?$AA@"
-// CHECK: @"\01??_C@_01KPBJIICL@?g?$AA@"
-// CHECK: @"\01??_C@_01LGACLJGK@?f?$AA@"
-// CHECK: @"\01??_C@_01JNCPOKKJ@?e?$AA@"
-// CHECK: @"\01??_C@_01IEDENLOI@?d?$AA@"
-// CHECK: @"\01??_C@_01MLHFENCP@?c?$AA@"
-// CHECK: @"\01??_C@_01NCGOHMGO@?b?$AA@"
-// CHECK: @"\01??_C@_01PJEDCPKN@?a?$AA@"
-// CHECK: @"\01??_C@_01OAFIBOOM@?$OA?$AA@"
-// CHECK: @"\01??_C@_01LIIGDENA@?$NP?$AA@"
-// CHECK: @"\01??_C@_01KBJNAFJB@?$NO?$AA@"
-// CHECK: @"\01??_C@_01IKLAFGFC@?$NN?$AA@"
-// CHECK: @"\01??_C@_01JDKLGHBD@?$NM?$AA@"
-// CHECK: @"\01??_C@_01NMOKPBNE@?$NL?$AA@"
-// CHECK: @"\01??_C@_01MFPBMAJF@?Z?$AA@"
-// CHECK: @"\01??_C@_01OONMJDFG@?Y?$AA@"
-// CHECK: @"\01??_C@_01PHMHKCBH@?X?$AA@"
-// CHECK: @"\01??_C@_01HAFPLONI@?W?$AA@"
-// CHECK: @"\01??_C@_01GJEEIPJJ@?V?$AA@"
-// CHECK: @"\01??_C@_01ECGJNMFK@?U?$AA@"
-// CHECK: @"\01??_C@_01FLHCONBL@?T?$AA@"
-// CHECK: @"\01??_C@_01BEDDHLNM@?S?$AA@"
-// CHECK: @"\01??_C@_01NCIEKJN@?R?$AA@"
-// CHECK: @"\01??_C@_01CGAFBJFO@?Q?$AA@"
-// CHECK: @"\01??_C@_01DPBOCIBP@?P?$AA@"
-// CHECK: @"\01??_C@_01PCEECGIB@?O?$AA@"
-// CHECK: @"\01??_C@_01OLFPBHMA@?N?$AA@"
-// CHECK: @"\01??_C@_01MAHCEEAD@?M?$AA@"
-// CHECK: @"\01??_C@_01NJGJHFEC@?L?$AA@"
-// CHECK: @"\01??_C@_01JGCIODIF@?K?$AA@"
-// CHECK: @"\01??_C@_01IPDDNCME@?J?$AA@"
-// CHECK: @"\01??_C@_01KEBOIBAH@?I?$AA@"
-// CHECK: @"\01??_C@_01LNAFLAEG@?H?$AA@"
-// CHECK: @"\01??_C@_01DKJNKMIJ@?G?$AA@"
-// CHECK: @"\01??_C@_01CDIGJNMI@?F?$AA@"
-// CHECK: @"\01??_C@_01IKLMOAL@?E?$AA@"
-// CHECK: @"\01??_C@_01BBLAPPEK@?D?$AA@"
-// CHECK: @"\01??_C@_01FOPBGJIN@?C?$AA@"
-// CHECK: @"\01??_C@_01EHOKFIMM@?B?$AA@"
-// CHECK: @"\01??_C@_01GMMHALAP@?A?$AA@"
-// CHECK: @"\01??_C@_01HFNMDKEO@?$MA?$AA@"
-// CHECK: @"\01??_C@_01NNHLFPHH@?$LP?$AA@"
-// CHECK: @"\01??_C@_01MEGAGODG@?$LO?$AA@"
-// CHECK: @"\01??_C@_01OPENDNPF@?$LN?$AA@"
-// CHECK: @"\01??_C@_01PGFGAMLE@?$LM?$AA@"
-// CHECK: @"\01??_C@_01LJBHJKHD@?$LL?$AA@"
-// CHECK: @"\01??_C@_01KAAMKLDC@?$LK?$AA@"
-// CHECK: @"\01??_C@_01ILCBPIPB@?$LJ?$AA@"
-// CHECK: @"\01??_C@_01JCDKMJLA@?$LI?$AA@"
-// CHECK: @"\01??_C@_01BFKCNFHP@?$LH?$AA@"
-// CHECK: @"\01??_C@_01MLJOEDO@?$LG?$AA@"
-// CHECK: @"\01??_C@_01CHJELHPN@?$LF?$AA@"
-// CHECK: @"\01??_C@_01DOIPIGLM@?$LE?$AA@"
-// CHECK: @"\01??_C@_01HBMOBAHL@?$LD?$AA@"
-// CHECK: @"\01??_C@_01GINFCBDK@?$LC?$AA@"
-// CHECK: @"\01??_C@_01EDPIHCPJ@?$LB?$AA@"
-// CHECK: @"\01??_C@_01FKODEDLI@?$LA?$AA@"
-// CHECK: @"\01??_C@_01JHLJENCG@?$KP?$AA@"
-// CHECK: @"\01??_C@_01IOKCHMGH@?$KO?$AA@"
-// CHECK: @"\01??_C@_01KFIPCPKE@?$KN?$AA@"
-// CHECK: @"\01??_C@_01LMJEBOOF@?$KM?$AA@"
-// CHECK: @"\01??_C@_01PDNFIICC@?$KL?$AA@"
-// CHECK: @"\01??_C@_01OKMOLJGD@?$KK?$AA@"
-// CHECK: @"\01??_C@_01MBODOKKA@?$KJ?$AA@"
-// CHECK: @"\01??_C@_01NIPINLOB@?$KI?$AA@"
-// CHECK: @"\01??_C@_01FPGAMHCO@?$KH?$AA@"
-// CHECK: @"\01??_C@_01EGHLPGGP@?$KG?$AA@"
-// CHECK: @"\01??_C@_01GNFGKFKM@?$KF?$AA@"
-// CHECK: @"\01??_C@_01HEENJEON@?$KE?$AA@"
-// CHECK: @"\01??_C@_01DLAMACCK@?$KD?$AA@"
-// CHECK: @"\01??_C@_01CCBHDDGL@?$KC?$AA@"
-// CHECK: @"\01??_C@_01JDKGAKI@?$KB?$AA@"
-// CHECK: @"\01??_C@_01BACBFBOJ@?$KA?$AA@"
-// CHECK: @"\01??_C@_01EIPPHLNF@?$JP?$AA@"
-// CHECK: @"\01??_C@_01FBOEEKJE@?$JO?$AA@"
-// CHECK: @"\01??_C@_01HKMJBJFH@?$JN?$AA@"
-// CHECK: @"\01??_C@_01GDNCCIBG@?$JM?$AA@"
-// CHECK: @"\01??_C@_01CMJDLONB@?$JL?$AA@"
-// CHECK: @"\01??_C@_01DFIIIPJA@?$JK?$AA@"
-// CHECK: @"\01??_C@_01BOKFNMFD@?$JJ?$AA@"
-// CHECK: @"\01??_C@_01HLOONBC@?$JI?$AA@"
-// CHECK: @"\01??_C@_01IACGPBNN@?$JH?$AA@"
-// CHECK: @"\01??_C@_01JJDNMAJM@?$JG?$AA@"
-// CHECK: @"\01??_C@_01LCBAJDFP@?$JF?$AA@"
-// CHECK: @"\01??_C@_01KLALKCBO@?$JE?$AA@"
-// CHECK: @"\01??_C@_01OEEKDENJ@?$JD?$AA@"
-// CHECK: @"\01??_C@_01PNFBAFJI@?$JC?$AA@"
-// CHECK: @"\01??_C@_01NGHMFGFL@?$JB?$AA@"
-// CHECK: @"\01??_C@_01MPGHGHBK@?$JA?$AA@"
-// CHECK: @"\01??_C@_01CDNGJIE@?$IP?$AA@"
-// CHECK: @"\01??_C@_01BLCGFIMF@?$IO?$AA@"
-// CHECK: @"\01??_C@_01DAALALAG@?$IN?$AA@"
-// CHECK: @"\01??_C@_01CJBADKEH@?$IM?$AA@"
-// CHECK: @"\01??_C@_01GGFBKMIA@?$IL?$AA@"
-// CHECK: @"\01??_C@_01HPEKJNMB@?$IK?$AA@"
-// CHECK: @"\01??_C@_01FEGHMOAC@?$IJ?$AA@"
-// CHECK: @"\01??_C@_01ENHMPPED@?$II?$AA@"
-// CHECK: @"\01??_C@_01MKOEODIM@?$IH?$AA@"
-// CHECK: @"\01??_C@_01NDPPNCMN@?$IG?$AA@"
-// CHECK: @"\01??_C@_01PINCIBAO@?$IF?$AA@"
-// CHECK: @"\01??_C@_01OBMJLAEP@?$IE?$AA@"
-// CHECK: @"\01??_C@_01KOIICGII@?$ID?$AA@"
-// CHECK: @"\01??_C@_01LHJDBHMJ@?$IC?$AA@"
-// CHECK: @"\01??_C@_01JMLOEEAK@?$IB?$AA@"
-// CHECK: @"\01??_C@_01IFKFHFEL@?$IA?$AA@"
-// CHECK: @"\01??_C@_01BGIBIIDJ@?$HP?$AA@"
-// CHECK: @"\01??_C@_01PJKLJHI@?$HO?$AA@"
-// CHECK: @"\01??_C@_01CELHOKLL@?$HN?$AA@"
-// CHECK: @"\01??_C@_01DNKMNLPK@?$HM?$AA@"
-// CHECK: @"\01??_C@_01HCONENDN@?$HL?$AA@"
-// CHECK: @"\01??_C@_01GLPGHMHM@z?$AA@"
-// CHECK: @"\01??_C@_01EANLCPLP@y?$AA@"
-// CHECK: @"\01??_C@_01FJMABOPO@x?$AA@"
-// CHECK: @"\01??_C@_01NOFIACDB@w?$AA@"
-// CHECK: @"\01??_C@_01MHEDDDHA@v?$AA@"
-// CHECK: @"\01??_C@_01OMGOGALD@u?$AA@"
-// CHECK: @"\01??_C@_01PFHFFBPC@t?$AA@"
-// CHECK: @"\01??_C@_01LKDEMHDF@s?$AA@"
-// CHECK: @"\01??_C@_01KDCPPGHE@r?$AA@"
-// CHECK: @"\01??_C@_01IIACKFLH@q?$AA@"
-// CHECK: @"\01??_C@_01JBBJJEPG@p?$AA@"
-// CHECK: @"\01??_C@_01FMEDJKGI@o?$AA@"
-// CHECK: @"\01??_C@_01EFFIKLCJ@n?$AA@"
-// CHECK: @"\01??_C@_01GOHFPIOK@m?$AA@"
-// CHECK: @"\01??_C@_01HHGOMJKL@l?$AA@"
-// CHECK: @"\01??_C@_01DICPFPGM@k?$AA@"
-// CHECK: @"\01??_C@_01CBDEGOCN@j?$AA@"
-// CHECK: @"\01??_C@_01KBJDNOO@i?$AA@"
-// CHECK: @"\01??_C@_01BDACAMKP@h?$AA@"
-// CHECK: @"\01??_C@_01JEJKBAGA@g?$AA@"
-// CHECK: @"\01??_C@_01INIBCBCB@f?$AA@"
-// CHECK: @"\01??_C@_01KGKMHCOC@e?$AA@"
-// CHECK: @"\01??_C@_01LPLHEDKD@d?$AA@"
-// CHECK: @"\01??_C@_01PAPGNFGE@c?$AA@"
-// CHECK: @"\01??_C@_01OJONOECF@b?$AA@"
-// CHECK: @"\01??_C@_01MCMALHOG@a?$AA@"
-// CHECK: @"\01??_C@_01NLNLIGKH@?$GA?$AA@"
-// CHECK: @"\01??_C@_01IDAFKMJL@_?$AA@"
-// CHECK: @"\01??_C@_01JKBOJNNK@?$FO?$AA@"
-// CHECK: @"\01??_C@_01LBDDMOBJ@?$FN?$AA@"
-// CHECK: @"\01??_C@_01KICIPPFI@?2?$AA@"
-// CHECK: @"\01??_C@_01OHGJGJJP@?$FL?$AA@"
-// CHECK: @"\01??_C@_01POHCFINO@Z?$AA@"
-// CHECK: @"\01??_C@_01NFFPALBN@Y?$AA@"
-// CHECK: @"\01??_C@_01MMEEDKFM@X?$AA@"
-// CHECK: @"\01??_C@_01ELNMCGJD@W?$AA@"
-// CHECK: @"\01??_C@_01FCMHBHNC@V?$AA@"
-// CHECK: @"\01??_C@_01HJOKEEBB@U?$AA@"
-// CHECK: @"\01??_C@_01GAPBHFFA@T?$AA@"
-// CHECK: @"\01??_C@_01CPLAODJH@S?$AA@"
-// CHECK: @"\01??_C@_01DGKLNCNG@R?$AA@"
-// CHECK: @"\01??_C@_01BNIGIBBF@Q?$AA@"
-// CHECK: @"\01??_C@_01EJNLAFE@P?$AA@"
-// CHECK: @"\01??_C@_01MJMHLOMK@O?$AA@"
-// CHECK: @"\01??_C@_01NANMIPIL@N?$AA@"
-// CHECK: @"\01??_C@_01PLPBNMEI@M?$AA@"
-// CHECK: @"\01??_C@_01OCOKONAJ@L?$AA@"
-// CHECK: @"\01??_C@_01KNKLHLMO@K?$AA@"
-// CHECK: @"\01??_C@_01LELAEKIP@J?$AA@"
-// CHECK: @"\01??_C@_01JPJNBJEM@I?$AA@"
-// CHECK: @"\01??_C@_01IGIGCIAN@H?$AA@"
-// CHECK: @"\01??_C@_01BBODEMC@G?$AA@"
-// CHECK: @"\01??_C@_01BIAFAFID@F?$AA@"
-// CHECK: @"\01??_C@_01DDCIFGEA@E?$AA@"
-// CHECK: @"\01??_C@_01CKDDGHAB@D?$AA@"
-// CHECK: @"\01??_C@_01GFHCPBMG@C?$AA@"
-// CHECK: @"\01??_C@_01HMGJMAIH@B?$AA@"
-// CHECK: @"\01??_C@_01FHEEJDEE@A?$AA@"
-// CHECK: @"\01??_C@_01EOFPKCAF@?$EA?$AA@"
-// CHECK: @"\01??_C@_01OGPIMHDM@?$DP?$AA@"
-// CHECK: @"\01??_C@_01PPODPGHN@?$DO?$AA@"
-// CHECK: @"\01??_C@_01NEMOKFLO@?$DN?$AA@"
-// CHECK: @"\01??_C@_01MNNFJEPP@?$DM?$AA@"
-// CHECK: @"\01??_C@_01ICJEACDI@?$DL?$AA@"
-// CHECK: @"\01??_C@_01JLIPDDHJ@?3?$AA@"
-// CHECK: @"\01??_C@_01LAKCGALK@9?$AA@"
-// CHECK: @"\01??_C@_01KJLJFBPL@8?$AA@"
-// CHECK: @"\01??_C@_01COCBENDE@7?$AA@"
-// CHECK: @"\01??_C@_01DHDKHMHF@6?$AA@"
-// CHECK: @"\01??_C@_01BMBHCPLG@5?$AA@"
-// CHECK: @"\01??_C@_01FAMBOPH@4?$AA@"
-// CHECK: @"\01??_C@_01EKENIIDA@3?$AA@"
-// CHECK: @"\01??_C@_01FDFGLJHB@2?$AA@"
-// CHECK: @"\01??_C@_01HIHLOKLC@1?$AA@"
-// CHECK: @"\01??_C@_01GBGANLPD@0?$AA@"
-// CHECK: @"\01??_C@_01KMDKNFGN@?1?$AA@"
-// CHECK: @"\01??_C@_01LFCBOECM@?4?$AA@"
-// CHECK: @"\01??_C@_01JOAMLHOP@?9?$AA@"
-// CHECK: @"\01??_C@_01IHBHIGKO@?0?$AA@"
-// CHECK: @"\01??_C@_01MIFGBAGJ@?$CL?$AA@"
-// CHECK: @"\01??_C@_01NBENCBCI@?$CK?$AA@"
-// CHECK: @"\01??_C@_01PKGAHCOL@?$CJ?$AA@"
-// CHECK: @"\01??_C@_01ODHLEDKK@?$CI?$AA@"
-// CHECK: @"\01??_C@_01GEODFPGF@?8?$AA@"
-// CHECK: @"\01??_C@_01HNPIGOCE@?$CG?$AA@"
-// CHECK: @"\01??_C@_01FGNFDNOH@?$CF?$AA@"
-// CHECK: @"\01??_C@_01EPMOAMKG@$?$AA@"
-// CHECK: @"\01??_C@_01IPJKGB@?$CD?$AA@"
-// CHECK: @"\01??_C@_01BJJEKLCA@?$CC?$AA@"
-// CHECK: @"\01??_C@_01DCLJPIOD@?$CB?$AA@"
-// CHECK: @"\01??_C@_01CLKCMJKC@?5?$AA@"
-// CHECK: @"\01??_C@_01HDHMODJO@?$BP?$AA@"
-// CHECK: @"\01??_C@_01GKGHNCNP@?$BO?$AA@"
-// CHECK: @"\01??_C@_01EBEKIBBM@?$BN?$AA@"
-// CHECK: @"\01??_C@_01FIFBLAFN@?$BM?$AA@"
-// CHECK: @"\01??_C@_01BHBACGJK@?$BL?$AA@"
-// CHECK: @"\01??_C@_01OALBHNL@?$BK?$AA@"
-// CHECK: @"\01??_C@_01CFCGEEBI@?$BJ?$AA@"
-// CHECK: @"\01??_C@_01DMDNHFFJ@?$BI?$AA@"
-// CHECK: @"\01??_C@_01LLKFGJJG@?$BH?$AA@"
-// CHECK: @"\01??_C@_01KCLOFINH@?$BG?$AA@"
-// CHECK: @"\01??_C@_01IJJDALBE@?$BF?$AA@"
-// CHECK: @"\01??_C@_01JAIIDKFF@?$BE?$AA@"
-// CHECK: @"\01??_C@_01NPMJKMJC@?$BD?$AA@"
-// CHECK: @"\01??_C@_01MGNCJNND@?$BC?$AA@"
-// CHECK: @"\01??_C@_01ONPPMOBA@?$BB?$AA@"
-// CHECK: @"\01??_C@_01PEOEPPFB@?$BA?$AA@"
-// CHECK: @"\01??_C@_01DJLOPBMP@?$AP?$AA@"
-// CHECK: @"\01??_C@_01CAKFMAIO@?$AO?$AA@"
-// CHECK: @"\01??_C@_01LIIJDEN@?$AN?$AA@"
-// CHECK: @"\01??_C@_01BCJDKCAM@?$AM?$AA@"
-// CHECK: @"\01??_C@_01FNNCDEML@?$AL?$AA@"
-// CHECK: @"\01??_C@_01EEMJAFIK@?6?$AA@"
-// CHECK: @"\01??_C@_01GPOEFGEJ@?7?$AA@"
-// CHECK: @"\01??_C@_01HGPPGHAI@?$AI?$AA@"
-// CHECK: @"\01??_C@_01PBGHHLMH@?$AH?$AA@"
-// CHECK: @"\01??_C@_01OIHMEKIG@?$AG?$AA@"
-// CHECK: @"\01??_C@_01MDFBBJEF@?$AF?$AA@"
-// CHECK: @"\01??_C@_01NKEKCIAE@?$AE?$AA@"
-// CHECK: @"\01??_C@_01JFALLOMD@?$AD?$AA@"
-// CHECK: @"\01??_C@_01IMBAIPIC@?$AC?$AA@"
-// CHECK: @"\01??_C@_01KHDNNMEB@?$AB?$AA@"
-// CHECK: @"\01??_C@_01LOCGONAA@?$AA?$AA@"
+// CHECK: @"??_C@_01CNACBAHC@?$PP?$AA@"
+// CHECK: @"??_C@_01DEBJCBDD@?$PO?$AA@"
+// CHECK: @"??_C@_01BPDEHCPA@?$PN?$AA@"
+// CHECK: @"??_C@_01GCPEDLB@?$PM?$AA@"
+// CHECK: @"??_C@_01EJGONFHG@?$PL?$AA@"
+// CHECK: @"??_C@_01FAHFOEDH@?z?$AA@"
+// CHECK: @"??_C@_01HLFILHPE@?y?$AA@"
+// CHECK: @"??_C@_01GCEDIGLF@?x?$AA@"
+// CHECK: @"??_C@_01OFNLJKHK@?w?$AA@"
+// CHECK: @"??_C@_01PMMAKLDL@?v?$AA@"
+// CHECK: @"??_C@_01NHONPIPI@?u?$AA@"
+// CHECK: @"??_C@_01MOPGMJLJ@?t?$AA@"
+// CHECK: @"??_C@_01IBLHFPHO@?s?$AA@"
+// CHECK: @"??_C@_01JIKMGODP@?r?$AA@"
+// CHECK: @"??_C@_01LDIBDNPM@?q?$AA@"
+// CHECK: @"??_C@_01KKJKAMLN@?p?$AA@"
+// CHECK: @"??_C@_01GHMAACCD@?o?$AA@"
+// CHECK: @"??_C@_01HONLDDGC@?n?$AA@"
+// CHECK: @"??_C@_01FFPGGAKB@?m?$AA@"
+// CHECK: @"??_C@_01EMONFBOA@?l?$AA@"
+// CHECK: @"??_C@_01DKMMHCH@?k?$AA@"
+// CHECK: @"??_C@_01BKLHPGGG@?j?$AA@"
+// CHECK: @"??_C@_01DBJKKFKF@?i?$AA@"
+// CHECK: @"??_C@_01CIIBJEOE@?h?$AA@"
+// CHECK: @"??_C@_01KPBJIICL@?g?$AA@"
+// CHECK: @"??_C@_01LGACLJGK@?f?$AA@"
+// CHECK: @"??_C@_01JNCPOKKJ@?e?$AA@"
+// CHECK: @"??_C@_01IEDENLOI@?d?$AA@"
+// CHECK: @"??_C@_01MLHFENCP@?c?$AA@"
+// CHECK: @"??_C@_01NCGOHMGO@?b?$AA@"
+// CHECK: @"??_C@_01PJEDCPKN@?a?$AA@"
+// CHECK: @"??_C@_01OAFIBOOM@?$OA?$AA@"
+// CHECK: @"??_C@_01LIIGDENA@?$NP?$AA@"
+// CHECK: @"??_C@_01KBJNAFJB@?$NO?$AA@"
+// CHECK: @"??_C@_01IKLAFGFC@?$NN?$AA@"
+// CHECK: @"??_C@_01JDKLGHBD@?$NM?$AA@"
+// CHECK: @"??_C@_01NMOKPBNE@?$NL?$AA@"
+// CHECK: @"??_C@_01MFPBMAJF@?Z?$AA@"
+// CHECK: @"??_C@_01OONMJDFG@?Y?$AA@"
+// CHECK: @"??_C@_01PHMHKCBH@?X?$AA@"
+// CHECK: @"??_C@_01HAFPLONI@?W?$AA@"
+// CHECK: @"??_C@_01GJEEIPJJ@?V?$AA@"
+// CHECK: @"??_C@_01ECGJNMFK@?U?$AA@"
+// CHECK: @"??_C@_01FLHCONBL@?T?$AA@"
+// CHECK: @"??_C@_01BEDDHLNM@?S?$AA@"
+// CHECK: @"??_C@_01NCIEKJN@?R?$AA@"
+// CHECK: @"??_C@_01CGAFBJFO@?Q?$AA@"
+// CHECK: @"??_C@_01DPBOCIBP@?P?$AA@"
+// CHECK: @"??_C@_01PCEECGIB@?O?$AA@"
+// CHECK: @"??_C@_01OLFPBHMA@?N?$AA@"
+// CHECK: @"??_C@_01MAHCEEAD@?M?$AA@"
+// CHECK: @"??_C@_01NJGJHFEC@?L?$AA@"
+// CHECK: @"??_C@_01JGCIODIF@?K?$AA@"
+// CHECK: @"??_C@_01IPDDNCME@?J?$AA@"
+// CHECK: @"??_C@_01KEBOIBAH@?I?$AA@"
+// CHECK: @"??_C@_01LNAFLAEG@?H?$AA@"
+// CHECK: @"??_C@_01DKJNKMIJ@?G?$AA@"
+// CHECK: @"??_C@_01CDIGJNMI@?F?$AA@"
+// CHECK: @"??_C@_01IKLMOAL@?E?$AA@"
+// CHECK: @"??_C@_01BBLAPPEK@?D?$AA@"
+// CHECK: @"??_C@_01FOPBGJIN@?C?$AA@"
+// CHECK: @"??_C@_01EHOKFIMM@?B?$AA@"
+// CHECK: @"??_C@_01GMMHALAP@?A?$AA@"
+// CHECK: @"??_C@_01HFNMDKEO@?$MA?$AA@"
+// CHECK: @"??_C@_01NNHLFPHH@?$LP?$AA@"
+// CHECK: @"??_C@_01MEGAGODG@?$LO?$AA@"
+// CHECK: @"??_C@_01OPENDNPF@?$LN?$AA@"
+// CHECK: @"??_C@_01PGFGAMLE@?$LM?$AA@"
+// CHECK: @"??_C@_01LJBHJKHD@?$LL?$AA@"
+// CHECK: @"??_C@_01KAAMKLDC@?$LK?$AA@"
+// CHECK: @"??_C@_01ILCBPIPB@?$LJ?$AA@"
+// CHECK: @"??_C@_01JCDKMJLA@?$LI?$AA@"
+// CHECK: @"??_C@_01BFKCNFHP@?$LH?$AA@"
+// CHECK: @"??_C@_01MLJOEDO@?$LG?$AA@"
+// CHECK: @"??_C@_01CHJELHPN@?$LF?$AA@"
+// CHECK: @"??_C@_01DOIPIGLM@?$LE?$AA@"
+// CHECK: @"??_C@_01HBMOBAHL@?$LD?$AA@"
+// CHECK: @"??_C@_01GINFCBDK@?$LC?$AA@"
+// CHECK: @"??_C@_01EDPIHCPJ@?$LB?$AA@"
+// CHECK: @"??_C@_01FKODEDLI@?$LA?$AA@"
+// CHECK: @"??_C@_01JHLJENCG@?$KP?$AA@"
+// CHECK: @"??_C@_01IOKCHMGH@?$KO?$AA@"
+// CHECK: @"??_C@_01KFIPCPKE@?$KN?$AA@"
+// CHECK: @"??_C@_01LMJEBOOF@?$KM?$AA@"
+// CHECK: @"??_C@_01PDNFIICC@?$KL?$AA@"
+// CHECK: @"??_C@_01OKMOLJGD@?$KK?$AA@"
+// CHECK: @"??_C@_01MBODOKKA@?$KJ?$AA@"
+// CHECK: @"??_C@_01NIPINLOB@?$KI?$AA@"
+// CHECK: @"??_C@_01FPGAMHCO@?$KH?$AA@"
+// CHECK: @"??_C@_01EGHLPGGP@?$KG?$AA@"
+// CHECK: @"??_C@_01GNFGKFKM@?$KF?$AA@"
+// CHECK: @"??_C@_01HEENJEON@?$KE?$AA@"
+// CHECK: @"??_C@_01DLAMACCK@?$KD?$AA@"
+// CHECK: @"??_C@_01CCBHDDGL@?$KC?$AA@"
+// CHECK: @"??_C@_01JDKGAKI@?$KB?$AA@"
+// CHECK: @"??_C@_01BACBFBOJ@?$KA?$AA@"
+// CHECK: @"??_C@_01EIPPHLNF@?$JP?$AA@"
+// CHECK: @"??_C@_01FBOEEKJE@?$JO?$AA@"
+// CHECK: @"??_C@_01HKMJBJFH@?$JN?$AA@"
+// CHECK: @"??_C@_01GDNCCIBG@?$JM?$AA@"
+// CHECK: @"??_C@_01CMJDLONB@?$JL?$AA@"
+// CHECK: @"??_C@_01DFIIIPJA@?$JK?$AA@"
+// CHECK: @"??_C@_01BOKFNMFD@?$JJ?$AA@"
+// CHECK: @"??_C@_01HLOONBC@?$JI?$AA@"
+// CHECK: @"??_C@_01IACGPBNN@?$JH?$AA@"
+// CHECK: @"??_C@_01JJDNMAJM@?$JG?$AA@"
+// CHECK: @"??_C@_01LCBAJDFP@?$JF?$AA@"
+// CHECK: @"??_C@_01KLALKCBO@?$JE?$AA@"
+// CHECK: @"??_C@_01OEEKDENJ@?$JD?$AA@"
+// CHECK: @"??_C@_01PNFBAFJI@?$JC?$AA@"
+// CHECK: @"??_C@_01NGHMFGFL@?$JB?$AA@"
+// CHECK: @"??_C@_01MPGHGHBK@?$JA?$AA@"
+// CHECK: @"??_C@_01CDNGJIE@?$IP?$AA@"
+// CHECK: @"??_C@_01BLCGFIMF@?$IO?$AA@"
+// CHECK: @"??_C@_01DAALALAG@?$IN?$AA@"
+// CHECK: @"??_C@_01CJBADKEH@?$IM?$AA@"
+// CHECK: @"??_C@_01GGFBKMIA@?$IL?$AA@"
+// CHECK: @"??_C@_01HPEKJNMB@?$IK?$AA@"
+// CHECK: @"??_C@_01FEGHMOAC@?$IJ?$AA@"
+// CHECK: @"??_C@_01ENHMPPED@?$II?$AA@"
+// CHECK: @"??_C@_01MKOEODIM@?$IH?$AA@"
+// CHECK: @"??_C@_01NDPPNCMN@?$IG?$AA@"
+// CHECK: @"??_C@_01PINCIBAO@?$IF?$AA@"
+// CHECK: @"??_C@_01OBMJLAEP@?$IE?$AA@"
+// CHECK: @"??_C@_01KOIICGII@?$ID?$AA@"
+// CHECK: @"??_C@_01LHJDBHMJ@?$IC?$AA@"
+// CHECK: @"??_C@_01JMLOEEAK@?$IB?$AA@"
+// CHECK: @"??_C@_01IFKFHFEL@?$IA?$AA@"
+// CHECK: @"??_C@_01BGIBIIDJ@?$HP?$AA@"
+// CHECK: @"??_C@_01PJKLJHI@?$HO?$AA@"
+// CHECK: @"??_C@_01CELHOKLL@?$HN?$AA@"
+// CHECK: @"??_C@_01DNKMNLPK@?$HM?$AA@"
+// CHECK: @"??_C@_01HCONENDN@?$HL?$AA@"
+// CHECK: @"??_C@_01GLPGHMHM@z?$AA@"
+// CHECK: @"??_C@_01EANLCPLP@y?$AA@"
+// CHECK: @"??_C@_01FJMABOPO@x?$AA@"
+// CHECK: @"??_C@_01NOFIACDB@w?$AA@"
+// CHECK: @"??_C@_01MHEDDDHA@v?$AA@"
+// CHECK: @"??_C@_01OMGOGALD@u?$AA@"
+// CHECK: @"??_C@_01PFHFFBPC@t?$AA@"
+// CHECK: @"??_C@_01LKDEMHDF@s?$AA@"
+// CHECK: @"??_C@_01KDCPPGHE@r?$AA@"
+// CHECK: @"??_C@_01IIACKFLH@q?$AA@"
+// CHECK: @"??_C@_01JBBJJEPG@p?$AA@"
+// CHECK: @"??_C@_01FMEDJKGI@o?$AA@"
+// CHECK: @"??_C@_01EFFIKLCJ@n?$AA@"
+// CHECK: @"??_C@_01GOHFPIOK@m?$AA@"
+// CHECK: @"??_C@_01HHGOMJKL@l?$AA@"
+// CHECK: @"??_C@_01DICPFPGM@k?$AA@"
+// CHECK: @"??_C@_01CBDEGOCN@j?$AA@"
+// CHECK: @"??_C@_01KBJDNOO@i?$AA@"
+// CHECK: @"??_C@_01BDACAMKP@h?$AA@"
+// CHECK: @"??_C@_01JEJKBAGA@g?$AA@"
+// CHECK: @"??_C@_01INIBCBCB@f?$AA@"
+// CHECK: @"??_C@_01KGKMHCOC@e?$AA@"
+// CHECK: @"??_C@_01LPLHEDKD@d?$AA@"
+// CHECK: @"??_C@_01PAPGNFGE@c?$AA@"
+// CHECK: @"??_C@_01OJONOECF@b?$AA@"
+// CHECK: @"??_C@_01MCMALHOG@a?$AA@"
+// CHECK: @"??_C@_01NLNLIGKH@?$GA?$AA@"
+// CHECK: @"??_C@_01IDAFKMJL@_?$AA@"
+// CHECK: @"??_C@_01JKBOJNNK@?$FO?$AA@"
+// CHECK: @"??_C@_01LBDDMOBJ@?$FN?$AA@"
+// CHECK: @"??_C@_01KICIPPFI@?2?$AA@"
+// CHECK: @"??_C@_01OHGJGJJP@?$FL?$AA@"
+// CHECK: @"??_C@_01POHCFINO@Z?$AA@"
+// CHECK: @"??_C@_01NFFPALBN@Y?$AA@"
+// CHECK: @"??_C@_01MMEEDKFM@X?$AA@"
+// CHECK: @"??_C@_01ELNMCGJD@W?$AA@"
+// CHECK: @"??_C@_01FCMHBHNC@V?$AA@"
+// CHECK: @"??_C@_01HJOKEEBB@U?$AA@"
+// CHECK: @"??_C@_01GAPBHFFA@T?$AA@"
+// CHECK: @"??_C@_01CPLAODJH@S?$AA@"
+// CHECK: @"??_C@_01DGKLNCNG@R?$AA@"
+// CHECK: @"??_C@_01BNIGIBBF@Q?$AA@"
+// CHECK: @"??_C@_01EJNLAFE@P?$AA@"
+// CHECK: @"??_C@_01MJMHLOMK@O?$AA@"
+// CHECK: @"??_C@_01NANMIPIL@N?$AA@"
+// CHECK: @"??_C@_01PLPBNMEI@M?$AA@"
+// CHECK: @"??_C@_01OCOKONAJ@L?$AA@"
+// CHECK: @"??_C@_01KNKLHLMO@K?$AA@"
+// CHECK: @"??_C@_01LELAEKIP@J?$AA@"
+// CHECK: @"??_C@_01JPJNBJEM@I?$AA@"
+// CHECK: @"??_C@_01IGIGCIAN@H?$AA@"
+// CHECK: @"??_C@_01BBODEMC@G?$AA@"
+// CHECK: @"??_C@_01BIAFAFID@F?$AA@"
+// CHECK: @"??_C@_01DDCIFGEA@E?$AA@"
+// CHECK: @"??_C@_01CKDDGHAB@D?$AA@"
+// CHECK: @"??_C@_01GFHCPBMG@C?$AA@"
+// CHECK: @"??_C@_01HMGJMAIH@B?$AA@"
+// CHECK: @"??_C@_01FHEEJDEE@A?$AA@"
+// CHECK: @"??_C@_01EOFPKCAF@?$EA?$AA@"
+// CHECK: @"??_C@_01OGPIMHDM@?$DP?$AA@"
+// CHECK: @"??_C@_01PPODPGHN@?$DO?$AA@"
+// CHECK: @"??_C@_01NEMOKFLO@?$DN?$AA@"
+// CHECK: @"??_C@_01MNNFJEPP@?$DM?$AA@"
+// CHECK: @"??_C@_01ICJEACDI@?$DL?$AA@"
+// CHECK: @"??_C@_01JLIPDDHJ@?3?$AA@"
+// CHECK: @"??_C@_01LAKCGALK@9?$AA@"
+// CHECK: @"??_C@_01KJLJFBPL@8?$AA@"
+// CHECK: @"??_C@_01COCBENDE@7?$AA@"
+// CHECK: @"??_C@_01DHDKHMHF@6?$AA@"
+// CHECK: @"??_C@_01BMBHCPLG@5?$AA@"
+// CHECK: @"??_C@_01FAMBOPH@4?$AA@"
+// CHECK: @"??_C@_01EKENIIDA@3?$AA@"
+// CHECK: @"??_C@_01FDFGLJHB@2?$AA@"
+// CHECK: @"??_C@_01HIHLOKLC@1?$AA@"
+// CHECK: @"??_C@_01GBGANLPD@0?$AA@"
+// CHECK: @"??_C@_01KMDKNFGN@?1?$AA@"
+// CHECK: @"??_C@_01LFCBOECM@?4?$AA@"
+// CHECK: @"??_C@_01JOAMLHOP@?9?$AA@"
+// CHECK: @"??_C@_01IHBHIGKO@?0?$AA@"
+// CHECK: @"??_C@_01MIFGBAGJ@?$CL?$AA@"
+// CHECK: @"??_C@_01NBENCBCI@?$CK?$AA@"
+// CHECK: @"??_C@_01PKGAHCOL@?$CJ?$AA@"
+// CHECK: @"??_C@_01ODHLEDKK@?$CI?$AA@"
+// CHECK: @"??_C@_01GEODFPGF@?8?$AA@"
+// CHECK: @"??_C@_01HNPIGOCE@?$CG?$AA@"
+// CHECK: @"??_C@_01FGNFDNOH@?$CF?$AA@"
+// CHECK: @"??_C@_01EPMOAMKG@$?$AA@"
+// CHECK: @"??_C@_01IPJKGB@?$CD?$AA@"
+// CHECK: @"??_C@_01BJJEKLCA@?$CC?$AA@"
+// CHECK: @"??_C@_01DCLJPIOD@?$CB?$AA@"
+// CHECK: @"??_C@_01CLKCMJKC@?5?$AA@"
+// CHECK: @"??_C@_01HDHMODJO@?$BP?$AA@"
+// CHECK: @"??_C@_01GKGHNCNP@?$BO?$AA@"
+// CHECK: @"??_C@_01EBEKIBBM@?$BN?$AA@"
+// CHECK: @"??_C@_01FIFBLAFN@?$BM?$AA@"
+// CHECK: @"??_C@_01BHBACGJK@?$BL?$AA@"
+// CHECK: @"??_C@_01OALBHNL@?$BK?$AA@"
+// CHECK: @"??_C@_01CFCGEEBI@?$BJ?$AA@"
+// CHECK: @"??_C@_01DMDNHFFJ@?$BI?$AA@"
+// CHECK: @"??_C@_01LLKFGJJG@?$BH?$AA@"
+// CHECK: @"??_C@_01KCLOFINH@?$BG?$AA@"
+// CHECK: @"??_C@_01IJJDALBE@?$BF?$AA@"
+// CHECK: @"??_C@_01JAIIDKFF@?$BE?$AA@"
+// CHECK: @"??_C@_01NPMJKMJC@?$BD?$AA@"
+// CHECK: @"??_C@_01MGNCJNND@?$BC?$AA@"
+// CHECK: @"??_C@_01ONPPMOBA@?$BB?$AA@"
+// CHECK: @"??_C@_01PEOEPPFB@?$BA?$AA@"
+// CHECK: @"??_C@_01DJLOPBMP@?$AP?$AA@"
+// CHECK: @"??_C@_01CAKFMAIO@?$AO?$AA@"
+// CHECK: @"??_C@_01LIIJDEN@?$AN?$AA@"
+// CHECK: @"??_C@_01BCJDKCAM@?$AM?$AA@"
+// CHECK: @"??_C@_01FNNCDEML@?$AL?$AA@"
+// CHECK: @"??_C@_01EEMJAFIK@?6?$AA@"
+// CHECK: @"??_C@_01GPOEFGEJ@?7?$AA@"
+// CHECK: @"??_C@_01HGPPGHAI@?$AI?$AA@"
+// CHECK: @"??_C@_01PBGHHLMH@?$AH?$AA@"
+// CHECK: @"??_C@_01OIHMEKIG@?$AG?$AA@"
+// CHECK: @"??_C@_01MDFBBJEF@?$AF?$AA@"
+// CHECK: @"??_C@_01NKEKCIAE@?$AE?$AA@"
+// CHECK: @"??_C@_01JFALLOMD@?$AD?$AA@"
+// CHECK: @"??_C@_01IMBAIPIC@?$AC?$AA@"
+// CHECK: @"??_C@_01KHDNNMEB@?$AB?$AA@"
+// CHECK: @"??_C@_01LOCGONAA@?$AA?$AA@"
const wchar_t *wl9 = L"\t";
const wchar_t *wl10 = L"\n";
@@ -614,114 +614,140 @@ const wchar_t *wl124 = L"|";
const wchar_t *wl125 = L"}";
const wchar_t *wl126 = L"~";
-// CHECK: @"\01??_C@_13KDLDGPGJ@?$AA?7?$AA?$AA@"
-// CHECK: @"\01??_C@_13LBAGMAIH@?$AA?6?$AA?$AA@"
-// CHECK: @"\01??_C@_13JLKKHOC@?$AA?$AL?$AA?$AA@"
-// CHECK: @"\01??_C@_13HOIJIPNN@?$AA?5?$AA?$AA@"
-// CHECK: @"\01??_C@_13MGDFOILI@?$AA?$CB?$AA?$AA@"
-// CHECK: @"\01??_C@_13NEIAEHFG@?$AA?$CC?$AA?$AA@"
-// CHECK: @"\01??_C@_13GMDMCADD@?$AA?$CD?$AA?$AA@"
-// CHECK: @"\01??_C@_13PBOLBIIK@?$AA$?$AA?$AA@"
-// CHECK: @"\01??_C@_13EJFHHPOP@?$AA?$CF?$AA?$AA@"
-// CHECK: @"\01??_C@_13FLOCNAAB@?$AA?$CG?$AA?$AA@"
-// CHECK: @"\01??_C@_13ODFOLHGE@?$AA?8?$AA?$AA@"
-// CHECK: @"\01??_C@_13LLDNKHDC@?$AA?$CI?$AA?$AA@"
-// CHECK: @"\01??_C@_13DIBMAFH@?$AA?$CJ?$AA?$AA@"
-// CHECK: @"\01??_C@_13BBDEGPLJ@?$AA?$CK?$AA?$AA@"
-// CHECK: @"\01??_C@_13KJIIAINM@?$AA?$CL?$AA?$AA@"
-// CHECK: @"\01??_C@_13DEFPDAGF@?$AA?0?$AA?$AA@"
-// CHECK: @"\01??_C@_13IMODFHAA@?$AA?9?$AA?$AA@"
-// CHECK: @"\01??_C@_13JOFGPIOO@?$AA?4?$AA?$AA@"
-// CHECK: @"\01??_C@_13CGOKJPIL@?$AA?1?$AA?$AA@"
-// CHECK: @"\01??_C@_13COJANIEC@?$AA0?$AA?$AA@"
-// CHECK: @"\01??_C@_13JGCMLPCH@?$AA1?$AA?$AA@"
-// CHECK: @"\01??_C@_13IEJJBAMJ@?$AA2?$AA?$AA@"
-// CHECK: @"\01??_C@_13DMCFHHKM@?$AA3?$AA?$AA@"
-// CHECK: @"\01??_C@_13KBPCEPBF@?$AA4?$AA?$AA@"
-// CHECK: @"\01??_C@_13BJEOCIHA@?$AA5?$AA?$AA@"
-// CHECK: @"\01??_C@_13LPLIHJO@?$AA6?$AA?$AA@"
-// CHECK: @"\01??_C@_13LDEHOAPL@?$AA7?$AA?$AA@"
-// CHECK: @"\01??_C@_13OLCEPAKN@?$AA8?$AA?$AA@"
-// CHECK: @"\01??_C@_13FDJIJHMI@?$AA9?$AA?$AA@"
-// CHECK: @"\01??_C@_13EBCNDICG@?$AA?3?$AA?$AA@"
-// CHECK: @"\01??_C@_13PJJBFPED@?$AA?$DL?$AA?$AA@"
-// CHECK: @"\01??_C@_13GEEGGHPK@?$AA?$DM?$AA?$AA@"
-// CHECK: @"\01??_C@_13NMPKAAJP@?$AA?$DN?$AA?$AA@"
-// CHECK: @"\01??_C@_13MOEPKPHB@?$AA?$DO?$AA?$AA@"
-// CHECK: @"\01??_C@_13HGPDMIBE@?$AA?$DP?$AA?$AA@"
-// CHECK: @"\01??_C@_13EFKPHINO@?$AA?$EA?$AA?$AA@"
-// CHECK: @"\01??_C@_13PNBDBPLL@?$AAA?$AA?$AA@"
-// CHECK: @"\01??_C@_13OPKGLAFF@?$AAB?$AA?$AA@"
-// CHECK: @"\01??_C@_13FHBKNHDA@?$AAC?$AA?$AA@"
-// CHECK: @"\01??_C@_13MKMNOPIJ@?$AAD?$AA?$AA@"
-// CHECK: @"\01??_C@_13HCHBIIOM@?$AAE?$AA?$AA@"
-// CHECK: @"\01??_C@_13GAMECHAC@?$AAF?$AA?$AA@"
-// CHECK: @"\01??_C@_13NIHIEAGH@?$AAG?$AA?$AA@"
-// CHECK: @"\01??_C@_13IABLFADB@?$AAH?$AA?$AA@"
-// CHECK: @"\01??_C@_13DIKHDHFE@?$AAI?$AA?$AA@"
-// CHECK: @"\01??_C@_13CKBCJILK@?$AAJ?$AA?$AA@"
-// CHECK: @"\01??_C@_13JCKOPPNP@?$AAK?$AA?$AA@"
-// CHECK: @"\01??_C@_13PHJMHGG@?$AAL?$AA?$AA@"
-// CHECK: @"\01??_C@_13LHMFKAAD@?$AAM?$AA?$AA@"
-// CHECK: @"\01??_C@_13KFHAAPON@?$AAN?$AA?$AA@"
-// CHECK: @"\01??_C@_13BNMMGIII@?$AAO?$AA?$AA@"
-// CHECK: @"\01??_C@_13BFLGCPEB@?$AAP?$AA?$AA@"
-// CHECK: @"\01??_C@_13KNAKEICE@?$AAQ?$AA?$AA@"
-// CHECK: @"\01??_C@_13LPLPOHMK@?$AAR?$AA?$AA@"
-// CHECK: @"\01??_C@_13HADIAKP@?$AAS?$AA?$AA@"
-// CHECK: @"\01??_C@_13JKNELIBG@?$AAT?$AA?$AA@"
-// CHECK: @"\01??_C@_13CCGINPHD@?$AAU?$AA?$AA@"
-// CHECK: @"\01??_C@_13DANNHAJN@?$AAV?$AA?$AA@"
-// CHECK: @"\01??_C@_13IIGBBHPI@?$AAW?$AA?$AA@"
-// CHECK: @"\01??_C@_13NAACAHKO@?$AAX?$AA?$AA@"
-// CHECK: @"\01??_C@_13GILOGAML@?$AAY?$AA?$AA@"
-// CHECK: @"\01??_C@_13HKALMPCF@?$AAZ?$AA?$AA@"
-// CHECK: @"\01??_C@_13MCLHKIEA@?$AA?$FL?$AA?$AA@"
-// CHECK: @"\01??_C@_13FPGAJAPJ@?$AA?2?$AA?$AA@"
-// CHECK: @"\01??_C@_13OHNMPHJM@?$AA?$FN?$AA?$AA@"
-// CHECK: @"\01??_C@_13PFGJFIHC@?$AA?$FO?$AA?$AA@"
-// CHECK: @"\01??_C@_13ENNFDPBH@?$AA_?$AA?$AA@"
-// CHECK: @"\01??_C@_13OFJNNHOA@?$AA?$GA?$AA?$AA@"
-// CHECK: @"\01??_C@_13FNCBLAIF@?$AAa?$AA?$AA@"
-// CHECK: @"\01??_C@_13EPJEBPGL@?$AAb?$AA?$AA@"
-// CHECK: @"\01??_C@_13PHCIHIAO@?$AAc?$AA?$AA@"
-// CHECK: @"\01??_C@_13GKPPEALH@?$AAd?$AA?$AA@"
-// CHECK: @"\01??_C@_13NCEDCHNC@?$AAe?$AA?$AA@"
-// CHECK: @"\01??_C@_13MAPGIIDM@?$AAf?$AA?$AA@"
-// CHECK: @"\01??_C@_13HIEKOPFJ@?$AAg?$AA?$AA@"
-// CHECK: @"\01??_C@_13CACJPPAP@?$AAh?$AA?$AA@"
-// CHECK: @"\01??_C@_13JIJFJIGK@?$AAi?$AA?$AA@"
-// CHECK: @"\01??_C@_13IKCADHIE@?$AAj?$AA?$AA@"
-// CHECK: @"\01??_C@_13DCJMFAOB@?$AAk?$AA?$AA@"
-// CHECK: @"\01??_C@_13KPELGIFI@?$AAl?$AA?$AA@"
-// CHECK: @"\01??_C@_13BHPHAPDN@?$AAm?$AA?$AA@"
-// CHECK: @"\01??_C@_13FECKAND@?$AAn?$AA?$AA@"
-// CHECK: @"\01??_C@_13LNPOMHLG@?$AAo?$AA?$AA@"
-// CHECK: @"\01??_C@_13LFIEIAHP@?$AAp?$AA?$AA@"
-// CHECK: @"\01??_C@_13NDIOHBK@?$AAq?$AA?$AA@"
-// CHECK: @"\01??_C@_13BPINEIPE@?$AAr?$AA?$AA@"
-// CHECK: @"\01??_C@_13KHDBCPJB@?$AAs?$AA?$AA@"
-// CHECK: @"\01??_C@_13DKOGBHCI@?$AAt?$AA?$AA@"
-// CHECK: @"\01??_C@_13ICFKHAEN@?$AAu?$AA?$AA@"
-// CHECK: @"\01??_C@_13JAOPNPKD@?$AAv?$AA?$AA@"
-// CHECK: @"\01??_C@_13CIFDLIMG@?$AAw?$AA?$AA@"
-// CHECK: @"\01??_C@_13HADAKIJA@?$AAx?$AA?$AA@"
-// CHECK: @"\01??_C@_13MIIMMPPF@?$AAy?$AA?$AA@"
-// CHECK: @"\01??_C@_13NKDJGABL@?$AAz?$AA?$AA@"
-// CHECK: @"\01??_C@_13GCIFAHHO@?$AA?$HL?$AA?$AA@"
-// CHECK: @"\01??_C@_13PPFCDPMH@?$AA?$HM?$AA?$AA@"
-// CHECK: @"\01??_C@_13EHOOFIKC@?$AA?$HN?$AA?$AA@"
-// CHECK: @"\01??_C@_13FFFLPHEM@?$AA?$HO?$AA?$AA@"
+// CHECK: @"??_C@_13KDLDGPGJ@?$AA?7?$AA?$AA@"
+// CHECK: @"??_C@_13LBAGMAIH@?$AA?6?$AA?$AA@"
+// CHECK: @"??_C@_13JLKKHOC@?$AA?$AL?$AA?$AA@"
+// CHECK: @"??_C@_13HOIJIPNN@?$AA?5?$AA?$AA@"
+// CHECK: @"??_C@_13MGDFOILI@?$AA?$CB?$AA?$AA@"
+// CHECK: @"??_C@_13NEIAEHFG@?$AA?$CC?$AA?$AA@"
+// CHECK: @"??_C@_13GMDMCADD@?$AA?$CD?$AA?$AA@"
+// CHECK: @"??_C@_13PBOLBIIK@?$AA$?$AA?$AA@"
+// CHECK: @"??_C@_13EJFHHPOP@?$AA?$CF?$AA?$AA@"
+// CHECK: @"??_C@_13FLOCNAAB@?$AA?$CG?$AA?$AA@"
+// CHECK: @"??_C@_13ODFOLHGE@?$AA?8?$AA?$AA@"
+// CHECK: @"??_C@_13LLDNKHDC@?$AA?$CI?$AA?$AA@"
+// CHECK: @"??_C@_13DIBMAFH@?$AA?$CJ?$AA?$AA@"
+// CHECK: @"??_C@_13BBDEGPLJ@?$AA?$CK?$AA?$AA@"
+// CHECK: @"??_C@_13KJIIAINM@?$AA?$CL?$AA?$AA@"
+// CHECK: @"??_C@_13DEFPDAGF@?$AA?0?$AA?$AA@"
+// CHECK: @"??_C@_13IMODFHAA@?$AA?9?$AA?$AA@"
+// CHECK: @"??_C@_13JOFGPIOO@?$AA?4?$AA?$AA@"
+// CHECK: @"??_C@_13CGOKJPIL@?$AA?1?$AA?$AA@"
+// CHECK: @"??_C@_13COJANIEC@?$AA0?$AA?$AA@"
+// CHECK: @"??_C@_13JGCMLPCH@?$AA1?$AA?$AA@"
+// CHECK: @"??_C@_13IEJJBAMJ@?$AA2?$AA?$AA@"
+// CHECK: @"??_C@_13DMCFHHKM@?$AA3?$AA?$AA@"
+// CHECK: @"??_C@_13KBPCEPBF@?$AA4?$AA?$AA@"
+// CHECK: @"??_C@_13BJEOCIHA@?$AA5?$AA?$AA@"
+// CHECK: @"??_C@_13LPLIHJO@?$AA6?$AA?$AA@"
+// CHECK: @"??_C@_13LDEHOAPL@?$AA7?$AA?$AA@"
+// CHECK: @"??_C@_13OLCEPAKN@?$AA8?$AA?$AA@"
+// CHECK: @"??_C@_13FDJIJHMI@?$AA9?$AA?$AA@"
+// CHECK: @"??_C@_13EBCNDICG@?$AA?3?$AA?$AA@"
+// CHECK: @"??_C@_13PJJBFPED@?$AA?$DL?$AA?$AA@"
+// CHECK: @"??_C@_13GEEGGHPK@?$AA?$DM?$AA?$AA@"
+// CHECK: @"??_C@_13NMPKAAJP@?$AA?$DN?$AA?$AA@"
+// CHECK: @"??_C@_13MOEPKPHB@?$AA?$DO?$AA?$AA@"
+// CHECK: @"??_C@_13HGPDMIBE@?$AA?$DP?$AA?$AA@"
+// CHECK: @"??_C@_13EFKPHINO@?$AA?$EA?$AA?$AA@"
+// CHECK: @"??_C@_13PNBDBPLL@?$AAA?$AA?$AA@"
+// CHECK: @"??_C@_13OPKGLAFF@?$AAB?$AA?$AA@"
+// CHECK: @"??_C@_13FHBKNHDA@?$AAC?$AA?$AA@"
+// CHECK: @"??_C@_13MKMNOPIJ@?$AAD?$AA?$AA@"
+// CHECK: @"??_C@_13HCHBIIOM@?$AAE?$AA?$AA@"
+// CHECK: @"??_C@_13GAMECHAC@?$AAF?$AA?$AA@"
+// CHECK: @"??_C@_13NIHIEAGH@?$AAG?$AA?$AA@"
+// CHECK: @"??_C@_13IABLFADB@?$AAH?$AA?$AA@"
+// CHECK: @"??_C@_13DIKHDHFE@?$AAI?$AA?$AA@"
+// CHECK: @"??_C@_13CKBCJILK@?$AAJ?$AA?$AA@"
+// CHECK: @"??_C@_13JCKOPPNP@?$AAK?$AA?$AA@"
+// CHECK: @"??_C@_13PHJMHGG@?$AAL?$AA?$AA@"
+// CHECK: @"??_C@_13LHMFKAAD@?$AAM?$AA?$AA@"
+// CHECK: @"??_C@_13KFHAAPON@?$AAN?$AA?$AA@"
+// CHECK: @"??_C@_13BNMMGIII@?$AAO?$AA?$AA@"
+// CHECK: @"??_C@_13BFLGCPEB@?$AAP?$AA?$AA@"
+// CHECK: @"??_C@_13KNAKEICE@?$AAQ?$AA?$AA@"
+// CHECK: @"??_C@_13LPLPOHMK@?$AAR?$AA?$AA@"
+// CHECK: @"??_C@_13HADIAKP@?$AAS?$AA?$AA@"
+// CHECK: @"??_C@_13JKNELIBG@?$AAT?$AA?$AA@"
+// CHECK: @"??_C@_13CCGINPHD@?$AAU?$AA?$AA@"
+// CHECK: @"??_C@_13DANNHAJN@?$AAV?$AA?$AA@"
+// CHECK: @"??_C@_13IIGBBHPI@?$AAW?$AA?$AA@"
+// CHECK: @"??_C@_13NAACAHKO@?$AAX?$AA?$AA@"
+// CHECK: @"??_C@_13GILOGAML@?$AAY?$AA?$AA@"
+// CHECK: @"??_C@_13HKALMPCF@?$AAZ?$AA?$AA@"
+// CHECK: @"??_C@_13MCLHKIEA@?$AA?$FL?$AA?$AA@"
+// CHECK: @"??_C@_13FPGAJAPJ@?$AA?2?$AA?$AA@"
+// CHECK: @"??_C@_13OHNMPHJM@?$AA?$FN?$AA?$AA@"
+// CHECK: @"??_C@_13PFGJFIHC@?$AA?$FO?$AA?$AA@"
+// CHECK: @"??_C@_13ENNFDPBH@?$AA_?$AA?$AA@"
+// CHECK: @"??_C@_13OFJNNHOA@?$AA?$GA?$AA?$AA@"
+// CHECK: @"??_C@_13FNCBLAIF@?$AAa?$AA?$AA@"
+// CHECK: @"??_C@_13EPJEBPGL@?$AAb?$AA?$AA@"
+// CHECK: @"??_C@_13PHCIHIAO@?$AAc?$AA?$AA@"
+// CHECK: @"??_C@_13GKPPEALH@?$AAd?$AA?$AA@"
+// CHECK: @"??_C@_13NCEDCHNC@?$AAe?$AA?$AA@"
+// CHECK: @"??_C@_13MAPGIIDM@?$AAf?$AA?$AA@"
+// CHECK: @"??_C@_13HIEKOPFJ@?$AAg?$AA?$AA@"
+// CHECK: @"??_C@_13CACJPPAP@?$AAh?$AA?$AA@"
+// CHECK: @"??_C@_13JIJFJIGK@?$AAi?$AA?$AA@"
+// CHECK: @"??_C@_13IKCADHIE@?$AAj?$AA?$AA@"
+// CHECK: @"??_C@_13DCJMFAOB@?$AAk?$AA?$AA@"
+// CHECK: @"??_C@_13KPELGIFI@?$AAl?$AA?$AA@"
+// CHECK: @"??_C@_13BHPHAPDN@?$AAm?$AA?$AA@"
+// CHECK: @"??_C@_13FECKAND@?$AAn?$AA?$AA@"
+// CHECK: @"??_C@_13LNPOMHLG@?$AAo?$AA?$AA@"
+// CHECK: @"??_C@_13LFIEIAHP@?$AAp?$AA?$AA@"
+// CHECK: @"??_C@_13NDIOHBK@?$AAq?$AA?$AA@"
+// CHECK: @"??_C@_13BPINEIPE@?$AAr?$AA?$AA@"
+// CHECK: @"??_C@_13KHDBCPJB@?$AAs?$AA?$AA@"
+// CHECK: @"??_C@_13DKOGBHCI@?$AAt?$AA?$AA@"
+// CHECK: @"??_C@_13ICFKHAEN@?$AAu?$AA?$AA@"
+// CHECK: @"??_C@_13JAOPNPKD@?$AAv?$AA?$AA@"
+// CHECK: @"??_C@_13CIFDLIMG@?$AAw?$AA?$AA@"
+// CHECK: @"??_C@_13HADAKIJA@?$AAx?$AA?$AA@"
+// CHECK: @"??_C@_13MIIMMPPF@?$AAy?$AA?$AA@"
+// CHECK: @"??_C@_13NKDJGABL@?$AAz?$AA?$AA@"
+// CHECK: @"??_C@_13GCIFAHHO@?$AA?$HL?$AA?$AA@"
+// CHECK: @"??_C@_13PPFCDPMH@?$AA?$HM?$AA?$AA@"
+// CHECK: @"??_C@_13EHOOFIKC@?$AA?$HN?$AA?$AA@"
+// CHECK: @"??_C@_13FFFLPHEM@?$AA?$HO?$AA?$AA@"
const char *LongASCIIString = "012345678901234567890123456789ABCDEF";
-// CHECK: @"\01??_C@_0CF@LABBIIMO@012345678901234567890123456789AB@"
+// CHECK: @"??_C@_0CF@LABBIIMO@012345678901234567890123456789AB@"
const wchar_t *LongWideString = L"012345678901234567890123456789ABCDEF";
-// CHECK: @"\01??_C@_1EK@KFPEBLPK@?$AA0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AA0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AA0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AAA?$AAB@"
+// CHECK: @"??_C@_1EK@KFPEBLPK@?$AA0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AA0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AA0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AAA?$AAB@"
const wchar_t *UnicodeLiteral = L"\ud7ff";
-// CHECK: @"\01??_C@_13IIHIAFKH@?W?$PP?$AA?$AA@"
+// CHECK: @"??_C@_13IIHIAFKH@?W?$PP?$AA?$AA@"
+
const char *U8Literal = u8"hi";
-// CHECK: @"\01??_C@_02PCEFGMJL@hi?$AA@"
+// CHECK: @"??_C@_02PCEFGMJL@hi?$AA@"
+const char *LongU8Literal = u8"012345678901234567890123456789ABCDEF";
+// CHECK: @"??_C@_0CF@LABBIIMO@012345678901234567890123456789AB@"
+
const char16_t *U16Literal = u"hi";
-// CHECK: @"\01??_C@_05OMLEGLOC@h?$AAi?$AA?$AA?$AA@"
+// CHECK: @"??_C@_05OMLEGLOC@h?$AAi?$AA?$AA?$AA@"
+// Note this starts with o instead of 0. Else LongWideString would have
+// the same initializer and CodeGenModule::ConstantStringMap would map them
+// to the same global with a shared mangling.
+// FIXME: ConstantStringMap probably shouldn't map things with the same data
+// but different manglings to the same variable.
+const char16_t *LongU16Literal = u"o12345678901234567890123456789ABCDEF";
+// CHECK: @"??_C@_0EK@FEAOBHPP@o?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AA0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA@"
+
const char32_t *U32Literal = U"hi";
-// CHECK: @"\01??_C@_0M@GFNAJIPG@h?$AA?$AA?$AAi?$AA?$AA?$AA?$AA?$AA?$AA?$AA@"
+// CHECK: @"??_C@_0M@GFNAJIPG@h?$AA?$AA?$AAi?$AA?$AA?$AA?$AA?$AA?$AA?$AA@"
+const char32_t *LongU32Literal = U"012345678901234567890123456789ABCDEF";
+// CHECK: @"??_C@_0JE@IMHFEDAA@0?$AA?$AA?$AA1?$AA?$AA?$AA2?$AA?$AA?$AA3?$AA?$AA?$AA4?$AA?$AA?$AA5?$AA?$AA?$AA6?$AA?$AA?$AA7?$AA?$AA?$AA@"
+
+// These all have just the right length that the trailing 0 just fits.
+const char *MaxASCIIString = "012345678901234567890123456789A";
+// CHECK: @"??_C@_0CA@NMANGEKF@012345678901234567890123456789A?$AA@"
+const wchar_t *MaxWideString = L"012345678901234567890123456789A";
+// CHECK: @"??_C@_1EA@LJAFPILO@?$AA0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AA0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AA0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AAA?$AA?$AA@"
+const char *MaxU8String = u8"012345678901234567890123456789A";
+// CHECK: @"??_C@_0CA@NMANGEKF@012345678901234567890123456789A?$AA@"
+const char16_t *MaxU16String = u"012345678901234";
+// CHECK: @"??_C@_0CA@NFEFHIFO@0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AA0?$AA1?$AA2?$AA3?$AA4?$AA?$AA?$AA@"
+const char32_t *MaxU32String = U"0123456";
+// CHECK: @"??_C@_0CA@KFPHPCC@0?$AA?$AA?$AA1?$AA?$AA?$AA2?$AA?$AA?$AA3?$AA?$AA?$AA4?$AA?$AA?$AA5?$AA?$AA?$AA6?$AA?$AA?$AA?$AA?$AA?$AA?$AA@"
diff --git a/test/CodeGenCXX/mangle-ms-template-callback.cpp b/test/CodeGenCXX/mangle-ms-template-callback.cpp
index 1a8f82fc8256..25e719f5e697 100644
--- a/test/CodeGenCXX/mangle-ms-template-callback.cpp
+++ b/test/CodeGenCXX/mangle-ms-template-callback.cpp
@@ -14,42 +14,42 @@ template<typename Ret, typename Arg1, typename Arg2>
class C<Ret(Arg1, Arg2)> {};
C0 callback_void;
-// CHECK: "\01?callback_void@@3V?$C@$$A6AXXZ@@A"
+// CHECK: "?callback_void@@3V?$C@$$A6AXXZ@@A"
volatile C0 callback_void_volatile;
-// CHECK: "\01?callback_void_volatile@@3V?$C@$$A6AXXZ@@C"
+// CHECK: "?callback_void_volatile@@3V?$C@$$A6AXXZ@@C"
class Type {};
C<int(void)> callback_int;
-// CHECK: "\01?callback_int@@3V?$C@$$A6AHXZ@@A"
+// CHECK: "?callback_int@@3V?$C@$$A6AHXZ@@A"
C<Type(void)> callback_Type;
-// CHECK: "\01?callback_Type@@3V?$C@$$A6A?AVType@@XZ@@A"
+// CHECK: "?callback_Type@@3V?$C@$$A6A?AVType@@XZ@@A"
C<void(int)> callback_void_int;
-// CHECK: "\01?callback_void_int@@3V?$C@$$A6AXH@Z@@A"
+// CHECK: "?callback_void_int@@3V?$C@$$A6AXH@Z@@A"
C<int(int)> callback_int_int;
-// CHECK: "\01?callback_int_int@@3V?$C@$$A6AHH@Z@@A"
+// CHECK: "?callback_int_int@@3V?$C@$$A6AHH@Z@@A"
C<void(Type)> callback_void_Type;
-// CHECK: "\01?callback_void_Type@@3V?$C@$$A6AXVType@@@Z@@A"
+// CHECK: "?callback_void_Type@@3V?$C@$$A6AXVType@@@Z@@A"
void foo(C0 c) {}
-// CHECK: "\01?foo@@YAXV?$C@$$A6AXXZ@@@Z"
+// CHECK: "?foo@@YAXV?$C@$$A6AXXZ@@@Z"
// Here be dragons!
// Let's face the magic of template partial specialization...
void function(C<void(void)>) {}
-// CHECK: "\01?function@@YAXV?$C@$$A6AXXZ@@@Z"
+// CHECK: "?function@@YAXV?$C@$$A6AXXZ@@@Z"
template<typename Ret> class C<Ret(*)(void)> {};
void function_pointer(C<void(*)(void)>) {}
-// CHECK: "\01?function_pointer@@YAXV?$C@P6AXXZ@@@Z"
+// CHECK: "?function_pointer@@YAXV?$C@P6AXXZ@@@Z"
// Block equivalent to the previous definitions.
template<typename Ret> class C<Ret(^)(void)> {};
void block(C<void(^)(void)>) {}
-// CHECK: "\01?block@@YAXV?$C@P_EAXXZ@@@Z"
+// CHECK: "?block@@YAXV?$C@P_EAXXZ@@@Z"
// FYI blocks are not present in MSVS, so we're free to choose the spec.
template<typename T> class C<void (T::*)(void)> {};
@@ -58,16 +58,16 @@ class Z {
void method() {}
};
void member_pointer(C<void (Z::*)(void)>) {}
-// CHECK: "\01?member_pointer@@YAXV?$C@P8Z@@AEXXZ@@@Z"
+// CHECK: "?member_pointer@@YAXV?$C@P8Z@@AEXXZ@@@Z"
template<typename T> void bar(T) {}
void call_bar() {
bar<int (*)(int)>(0);
-// CHECK: "\01??$bar@P6AHH@Z@@YAXP6AHH@Z@Z"
+// CHECK: "??$bar@P6AHH@Z@@YAXP6AHH@Z@Z"
bar<int (^)(int)>(0);
-// CHECK: "\01??$bar@P_EAHH@Z@@YAXP_EAHH@Z@Z"
+// CHECK: "??$bar@P_EAHH@Z@@YAXP_EAHH@Z@Z"
// FYI blocks are not present in MSVS, so we're free to choose the spec.
}
@@ -83,7 +83,7 @@ void CallWrapper() {
WrapFnPtr<Thing::VoidStaticMethod>();
WrapFnRef<Thing::VoidStaticMethod>();
}
-// CHECK: call {{.*}} @"\01??$WrapFnPtr@$1?VoidFn@@YAXXZ@@YAXXZ"
-// CHECK: call {{.*}} @"\01??$WrapFnRef@$1?VoidFn@@YAXXZ@@YAXXZ"
-// CHECK: call {{.*}} @"\01??$WrapFnPtr@$1?VoidStaticMethod@Thing@@SAXXZ@@YAXXZ"
-// CHECK: call {{.*}} @"\01??$WrapFnRef@$1?VoidStaticMethod@Thing@@SAXXZ@@YAXXZ"
+// CHECK: call {{.*}} @"??$WrapFnPtr@$1?VoidFn@@YAXXZ@@YAXXZ"
+// CHECK: call {{.*}} @"??$WrapFnRef@$1?VoidFn@@YAXXZ@@YAXXZ"
+// CHECK: call {{.*}} @"??$WrapFnPtr@$1?VoidStaticMethod@Thing@@SAXXZ@@YAXXZ"
+// CHECK: call {{.*}} @"??$WrapFnRef@$1?VoidStaticMethod@Thing@@SAXXZ@@YAXXZ"
diff --git a/test/CodeGenCXX/mangle-ms-templates-memptrs-2.cpp b/test/CodeGenCXX/mangle-ms-templates-memptrs-2.cpp
index b01d6099d8f7..e4a608aa6c25 100644
--- a/test/CodeGenCXX/mangle-ms-templates-memptrs-2.cpp
+++ b/test/CodeGenCXX/mangle-ms-templates-memptrs-2.cpp
@@ -8,31 +8,31 @@ struct K {};
struct __single_inheritance M;
J<M> m;
-// CHECK-DAG: @"\01?m@@3U?$J@UM@@$0A@@@A"
+// CHECK-DAG: @"?m@@3U?$J@UM@@$0A@@@A"
K<M> m2;
-// CHECK-DAG: @"\01?m2@@3U?$K@UM@@$0?0@@A"
+// CHECK-DAG: @"?m2@@3U?$K@UM@@$0?0@@A"
struct __multiple_inheritance N;
J<N> n;
-// CHECK-DAG: @"\01?n@@3U?$J@UN@@$HA@@@A"
+// CHECK-DAG: @"?n@@3U?$J@UN@@$HA@@@A"
K<N> n2;
-// CHECK-DAG: @"\01?n2@@3U?$K@UN@@$0?0@@A"
+// CHECK-DAG: @"?n2@@3U?$K@UN@@$0?0@@A"
struct __virtual_inheritance O;
J<O> o;
-// CHECK-DAG: @"\01?o@@3U?$J@UO@@$IA@A@@@A"
+// CHECK-DAG: @"?o@@3U?$J@UO@@$IA@A@@@A"
K<O> o2;
-// CHECK-DAG: @"\01?o2@@3U?$K@UO@@$FA@?0@@A"
+// CHECK-DAG: @"?o2@@3U?$K@UO@@$FA@?0@@A"
struct P;
J<P> p;
-// CHECK-DAG: @"\01?p@@3U?$J@UP@@$JA@A@?0@@A"
+// CHECK-DAG: @"?p@@3U?$J@UP@@$JA@A@?0@@A"
K<P> p2;
-// CHECK-DAG: @"\01?p2@@3U?$K@UP@@$GA@A@?0@@A"
+// CHECK-DAG: @"?p2@@3U?$K@UP@@$GA@A@?0@@A"
#pragma pointers_to_members(full_generality, virtual_inheritance)
@@ -57,4 +57,4 @@ template struct ClassTemplate<&MostGeneral::h>;
// Test that we mangle in the vbptr offset, which is 12 here.
//
-// CHECK: define weak_odr x86_thiscallcc %struct.ClassTemplate* @"\01??0?$ClassTemplate@$J??_9MostGeneral@@$BA@AEA@M@3@@QAE@XZ"
+// CHECK: define weak_odr dso_local x86_thiscallcc %struct.ClassTemplate* @"??0?$ClassTemplate@$J??_9MostGeneral@@$BA@AEA@M@3@@QAE@XZ"
diff --git a/test/CodeGenCXX/mangle-ms-templates-memptrs.cpp b/test/CodeGenCXX/mangle-ms-templates-memptrs.cpp
index e710abe97e98..3078c5a5d268 100644
--- a/test/CodeGenCXX/mangle-ms-templates-memptrs.cpp
+++ b/test/CodeGenCXX/mangle-ms-templates-memptrs.cpp
@@ -56,31 +56,31 @@ void ReadFields() {
}
// CHECK-LABEL: define {{.*}}ReadFields
-// CHECK: call {{.*}} @"\01??$ReadField@US@@$03@@YAHAAUS@@@Z"
-// CHECK: call {{.*}} @"\01??$ReadField@UM@@$0M@@@YAHAAUM@@@Z"
-// CHECK: call {{.*}} @"\01??$ReadField@UV@@$F7A@@@YAHAAUV@@@Z"
-// CHECK: call {{.*}} @"\01??$ReadField@UU@@$G3A@A@@@YAHAAUU@@@Z"
-// CHECK: call {{.*}} @"\01??$ReadField@US@@$07@@YAHAAUS@@@Z"
-// CHECK: call {{.*}} @"\01??$ReadField@UM@@$0BA@@@YAHAAUM@@@Z"
-// CHECK: call {{.*}} @"\01??$ReadField@UV@@$FM@A@@@YAHAAUV@@@Z"
-// CHECK: call {{.*}} @"\01??$ReadField@UU@@$G7A@A@@@YAHAAUU@@@Z"
+// CHECK: call {{.*}} @"??$ReadField@US@@$03@@YAHAAUS@@@Z"
+// CHECK: call {{.*}} @"??$ReadField@UM@@$0M@@@YAHAAUM@@@Z"
+// CHECK: call {{.*}} @"??$ReadField@UV@@$F7A@@@YAHAAUV@@@Z"
+// CHECK: call {{.*}} @"??$ReadField@UU@@$G3A@A@@@YAHAAUU@@@Z"
+// CHECK: call {{.*}} @"??$ReadField@US@@$07@@YAHAAUS@@@Z"
+// CHECK: call {{.*}} @"??$ReadField@UM@@$0BA@@@YAHAAUM@@@Z"
+// CHECK: call {{.*}} @"??$ReadField@UV@@$FM@A@@@YAHAAUV@@@Z"
+// CHECK: call {{.*}} @"??$ReadField@UU@@$G7A@A@@@YAHAAUU@@@Z"
// MSVC mangles null member pointers in function templates wrong, but it gets
// them right in class templates.
-// CHECK: call {{.*}} @"\01??$ReadField@US@@$0A@@@YAHAAUS@@@Z"
-// CHECK: call {{.*}} @"\01??$ReadField@UM@@$0A@@@YAHAAUM@@@Z"
-// CHECK: call {{.*}} @"\01??$ReadField@UV@@$0A@@@YAHAAUV@@@Z"
-// CHECK: call {{.*}} @"\01??$ReadField@UU@@$0A@@@YAHAAUU@@@Z"
+// CHECK: call {{.*}} @"??$ReadField@US@@$0A@@@YAHAAUS@@@Z"
+// CHECK: call {{.*}} @"??$ReadField@UM@@$0A@@@YAHAAUM@@@Z"
+// CHECK: call {{.*}} @"??$ReadField@UV@@$0A@@@YAHAAUV@@@Z"
+// CHECK: call {{.*}} @"??$ReadField@UU@@$0A@@@YAHAAUU@@@Z"
// Non-polymorphic null data memptr vs first field memptr. MSVC mangles these
// the same.
-// CHECK: call {{.*}} @"\01??$ReadField@UA@@$0A@@@YAHAAUA@@@Z"
-// CHECK: call {{.*}} @"\01??$ReadField@UA@@$0?0@@YAHAAUA@@@Z"
+// CHECK: call {{.*}} @"??$ReadField@UA@@$0A@@@YAHAAUA@@@Z"
+// CHECK: call {{.*}} @"??$ReadField@UA@@$0?0@@YAHAAUA@@@Z"
// Indirect fields are handled as-if they were simply members of their enclosing
// record.
-// CHECK: call {{.*}} @"\01??$ReadField@UI@@$0A@@@YAHAAUI@@@Z"
-// CHECK: call {{.*}} @"\01??$ReadField@UI@@$03@@YAHAAUI@@@Z"
+// CHECK: call {{.*}} @"??$ReadField@UI@@$0A@@@YAHAAUI@@@Z"
+// CHECK: call {{.*}} @"??$ReadField@UI@@$03@@YAHAAUI@@@Z"
// Test member function pointers.
template <typename T, void (T::*MFP)()>
@@ -119,10 +119,10 @@ void CallMethods() {
}
// CHECK-LABEL: define {{.*}}CallMethods
-// CHECK: call {{.*}} @"\01??$CallMethod@US@@$1?f@1@QAEXXZ@@YAXAAUS@@@Z"
-// CHECK: call {{.*}} @"\01??$CallMethod@UM@@$H?f@1@QAEXXZA@@@YAXAAUM@@@Z"
-// CHECK: call {{.*}} @"\01??$CallMethod@UV@@$I?f@1@QAEXXZA@A@@@YAXAAUV@@@Z"
-// CHECK: call {{.*}} @"\01??$CallMethod@UU@@$J?f@1@QAEXXZA@A@A@@@YAXAAUU@@@Z"
+// CHECK: call {{.*}} @"??$CallMethod@US@@$1?f@1@QAEXXZ@@YAXAAUS@@@Z"
+// CHECK: call {{.*}} @"??$CallMethod@UM@@$H?f@1@QAEXXZA@@@YAXAAUM@@@Z"
+// CHECK: call {{.*}} @"??$CallMethod@UV@@$I?f@1@QAEXXZA@A@@@YAXAAUV@@@Z"
+// CHECK: call {{.*}} @"??$CallMethod@UU@@$J?f@1@QAEXXZA@A@A@@@YAXAAUU@@@Z"
// PR17034: MSVC reuses the same thunk for every virtual g method because they
// are all at vftable offset zero. They then mangle the name of the first thunk
@@ -130,17 +130,17 @@ void CallMethods() {
// bug. We don't follow them here. Instead of ?_91@ backref below, they would
// get ?_9S@@ in every instantiation after the first.
-// CHECK: call {{.*}} @"\01??$CallMethod@US@@$1??_91@$BA@AE@@YAXAAUS@@@Z"
-// CHECK: call {{.*}} @"\01??$CallMethod@UM@@$H??_91@$BA@AEA@@@YAXAAUM@@@Z"
-// CHECK: call {{.*}} @"\01??$CallMethod@UV@@$I??_91@$BA@AEA@A@@@YAXAAUV@@@Z"
-// CHECK: call {{.*}} @"\01??$CallMethod@UU@@$J??_91@$BA@AEA@A@A@@@YAXAAUU@@@Z"
+// CHECK: call {{.*}} @"??$CallMethod@US@@$1??_91@$BA@AE@@YAXAAUS@@@Z"
+// CHECK: call {{.*}} @"??$CallMethod@UM@@$H??_91@$BA@AEA@@@YAXAAUM@@@Z"
+// CHECK: call {{.*}} @"??$CallMethod@UV@@$I??_91@$BA@AEA@A@@@YAXAAUV@@@Z"
+// CHECK: call {{.*}} @"??$CallMethod@UU@@$J??_91@$BA@AEA@A@A@@@YAXAAUU@@@Z"
-// CHECK: call {{.*}} @"\01??$CallMethod@UO@@$H??_91@$BA@AE3@@YAXAAUO@@@Z"
+// CHECK: call {{.*}} @"??$CallMethod@UO@@$H??_91@$BA@AE3@@YAXAAUO@@@Z"
-// CHECK: call {{.*}} @"\01??$CallMethod@US@@$0A@@@YAXAAUS@@@Z"
-// CHECK: call {{.*}} @"\01??$CallMethod@UM@@$0A@@@YAXAAUM@@@Z"
-// CHECK: call {{.*}} @"\01??$CallMethod@UV@@$0A@@@YAXAAUV@@@Z"
-// CHECK: call {{.*}} @"\01??$CallMethod@UU@@$0A@@@YAXAAUU@@@Z"
+// CHECK: call {{.*}} @"??$CallMethod@US@@$0A@@@YAXAAUS@@@Z"
+// CHECK: call {{.*}} @"??$CallMethod@UM@@$0A@@@YAXAAUM@@@Z"
+// CHECK: call {{.*}} @"??$CallMethod@UV@@$0A@@@YAXAAUV@@@Z"
+// CHECK: call {{.*}} @"??$CallMethod@UU@@$0A@@@YAXAAUU@@@Z"
namespace NegativeNVOffset {
struct A {};
@@ -152,4 +152,4 @@ struct C : B {
template void CallMethod<NegativeNVOffset::C, &NegativeNVOffset::C::f>(NegativeNVOffset::C &);
-// CHECK-LABEL: define {{.*}} @"\01??$CallMethod@UC@NegativeNVOffset@@$I??_912@$BA@AEPPPPPPPM@A@@@YAXAAUC@NegativeNVOffset@@@Z"
+// CHECK-LABEL: define {{.*}} @"??$CallMethod@UC@NegativeNVOffset@@$I??_912@$BA@AEPPPPPPPM@A@@@YAXAAUC@NegativeNVOffset@@@Z"
diff --git a/test/CodeGenCXX/mangle-ms-templates.cpp b/test/CodeGenCXX/mangle-ms-templates.cpp
index 46ab251af14f..8c6062b6d5ee 100644
--- a/test/CodeGenCXX/mangle-ms-templates.cpp
+++ b/test/CodeGenCXX/mangle-ms-templates.cpp
@@ -51,118 +51,118 @@ class BoolTemplate<true> {
void template_mangling() {
Class<Typename> c1;
-// CHECK: call {{.*}} @"\01??0?$Class@VTypename@@@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$Class@VTypename@@@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$Class@VTypename@@@@QAE@XZ"
+// X64: call {{.*}} @"??0?$Class@VTypename@@@@QEAA@XZ"
Class<const Typename> c1_const;
-// CHECK: call {{.*}} @"\01??0?$Class@$$CBVTypename@@@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$Class@$$CBVTypename@@@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$Class@$$CBVTypename@@@@QAE@XZ"
+// X64: call {{.*}} @"??0?$Class@$$CBVTypename@@@@QEAA@XZ"
Class<volatile Typename> c1_volatile;
-// CHECK: call {{.*}} @"\01??0?$Class@$$CCVTypename@@@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$Class@$$CCVTypename@@@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$Class@$$CCVTypename@@@@QAE@XZ"
+// X64: call {{.*}} @"??0?$Class@$$CCVTypename@@@@QEAA@XZ"
Class<const volatile Typename> c1_cv;
-// CHECK: call {{.*}} @"\01??0?$Class@$$CDVTypename@@@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$Class@$$CDVTypename@@@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$Class@$$CDVTypename@@@@QAE@XZ"
+// X64: call {{.*}} @"??0?$Class@$$CDVTypename@@@@QEAA@XZ"
Class<Nested<Typename> > c2;
-// CHECK: call {{.*}} @"\01??0?$Class@V?$Nested@VTypename@@@@@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$Class@V?$Nested@VTypename@@@@@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$Class@V?$Nested@VTypename@@@@@@QAE@XZ"
+// X64: call {{.*}} @"??0?$Class@V?$Nested@VTypename@@@@@@QEAA@XZ"
Class<int * const> c_intpc;
-// CHECK: call {{.*}} @"\01??0?$Class@QAH@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$Class@QEAH@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$Class@QAH@@QAE@XZ"
+// X64: call {{.*}} @"??0?$Class@QEAH@@QEAA@XZ"
Class<int()> c_ft;
-// CHECK: call {{.*}} @"\01??0?$Class@$$A6AHXZ@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$Class@$$A6AHXZ@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$Class@$$A6AHXZ@@QAE@XZ"
+// X64: call {{.*}} @"??0?$Class@$$A6AHXZ@@QEAA@XZ"
Class<int[]> c_inti;
-// CHECK: call {{.*}} @"\01??0?$Class@$$BY0A@H@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$Class@$$BY0A@H@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$Class@$$BY0A@H@@QAE@XZ"
+// X64: call {{.*}} @"??0?$Class@$$BY0A@H@@QEAA@XZ"
Class<int[5]> c_int5;
-// CHECK: call {{.*}} @"\01??0?$Class@$$BY04H@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$Class@$$BY04H@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$Class@$$BY04H@@QAE@XZ"
+// X64: call {{.*}} @"??0?$Class@$$BY04H@@QEAA@XZ"
Class<const int[5]> c_intc5;
-// CHECK: call {{.*}} @"\01??0?$Class@$$BY04$$CBH@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$Class@$$BY04$$CBH@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$Class@$$BY04$$CBH@@QAE@XZ"
+// X64: call {{.*}} @"??0?$Class@$$BY04$$CBH@@QEAA@XZ"
Class<int * const[5]> c_intpc5;
-// CHECK: call {{.*}} @"\01??0?$Class@$$BY04QAH@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$Class@$$BY04QEAH@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$Class@$$BY04QAH@@QAE@XZ"
+// X64: call {{.*}} @"??0?$Class@$$BY04QEAH@@QEAA@XZ"
BoolTemplate<false> _false;
-// CHECK: call {{.*}} @"\01??0?$BoolTemplate@$0A@@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$BoolTemplate@$0A@@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$BoolTemplate@$0A@@@QAE@XZ"
+// X64: call {{.*}} @"??0?$BoolTemplate@$0A@@@QEAA@XZ"
BoolTemplate<true> _true;
// PR13158
_true.Foo(1);
-// CHECK: call {{.*}} @"\01??0?$BoolTemplate@$00@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$BoolTemplate@$00@@QEAA@XZ"
-// CHECK: call {{.*}} @"\01??$Foo@H@?$BoolTemplate@$00@@QAEXH@Z"
-// X64: call {{.*}} @"\01??$Foo@H@?$BoolTemplate@$00@@QEAAXH@Z"
+// CHECK: call {{.*}} @"??0?$BoolTemplate@$00@@QAE@XZ"
+// X64: call {{.*}} @"??0?$BoolTemplate@$00@@QEAA@XZ"
+// CHECK: call {{.*}} @"??$Foo@H@?$BoolTemplate@$00@@QAEXH@Z"
+// X64: call {{.*}} @"??$Foo@H@?$BoolTemplate@$00@@QEAAXH@Z"
IntTemplate<0> zero;
-// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0A@@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$IntTemplate@$0A@@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$IntTemplate@$0A@@@QAE@XZ"
+// X64: call {{.*}} @"??0?$IntTemplate@$0A@@@QEAA@XZ"
IntTemplate<5> five;
-// CHECK: call {{.*}} @"\01??0?$IntTemplate@$04@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$IntTemplate@$04@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$IntTemplate@$04@@QAE@XZ"
+// X64: call {{.*}} @"??0?$IntTemplate@$04@@QEAA@XZ"
IntTemplate<11> eleven;
-// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0L@@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$IntTemplate@$0L@@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$IntTemplate@$0L@@@QAE@XZ"
+// X64: call {{.*}} @"??0?$IntTemplate@$0L@@@QEAA@XZ"
IntTemplate<256> _256;
-// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0BAA@@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$IntTemplate@$0BAA@@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$IntTemplate@$0BAA@@@QAE@XZ"
+// X64: call {{.*}} @"??0?$IntTemplate@$0BAA@@@QEAA@XZ"
IntTemplate<513> _513;
-// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0CAB@@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$IntTemplate@$0CAB@@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$IntTemplate@$0CAB@@@QAE@XZ"
+// X64: call {{.*}} @"??0?$IntTemplate@$0CAB@@@QEAA@XZ"
IntTemplate<1026> _1026;
-// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0EAC@@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$IntTemplate@$0EAC@@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$IntTemplate@$0EAC@@@QAE@XZ"
+// X64: call {{.*}} @"??0?$IntTemplate@$0EAC@@@QEAA@XZ"
IntTemplate<65535> ffff;
-// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0PPPP@@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$IntTemplate@$0PPPP@@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$IntTemplate@$0PPPP@@@QAE@XZ"
+// X64: call {{.*}} @"??0?$IntTemplate@$0PPPP@@@QEAA@XZ"
IntTemplate<-1> neg_1;
-// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0?0@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$IntTemplate@$0?0@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$IntTemplate@$0?0@@QAE@XZ"
+// X64: call {{.*}} @"??0?$IntTemplate@$0?0@@QEAA@XZ"
IntTemplate<-9> neg_9;
-// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0?8@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$IntTemplate@$0?8@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$IntTemplate@$0?8@@QAE@XZ"
+// X64: call {{.*}} @"??0?$IntTemplate@$0?8@@QEAA@XZ"
IntTemplate<-10> neg_10;
-// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0?9@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$IntTemplate@$0?9@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$IntTemplate@$0?9@@QAE@XZ"
+// X64: call {{.*}} @"??0?$IntTemplate@$0?9@@QEAA@XZ"
IntTemplate<-11> neg_11;
-// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0?L@@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$IntTemplate@$0?L@@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$IntTemplate@$0?L@@@QAE@XZ"
+// X64: call {{.*}} @"??0?$IntTemplate@$0?L@@@QEAA@XZ"
UnsignedIntTemplate<4294967295> ffffffff;
-// CHECK: call {{.*}} @"\01??0?$UnsignedIntTemplate@$0PPPPPPPP@@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$UnsignedIntTemplate@$0PPPPPPPP@@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$UnsignedIntTemplate@$0PPPPPPPP@@@QAE@XZ"
+// X64: call {{.*}} @"??0?$UnsignedIntTemplate@$0PPPPPPPP@@@QEAA@XZ"
LongLongTemplate<-9223372036854775807LL-1LL> int64_min;
-// CHECK: call {{.*}} @"\01??0?$LongLongTemplate@$0?IAAAAAAAAAAAAAAA@@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$LongLongTemplate@$0?IAAAAAAAAAAAAAAA@@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$LongLongTemplate@$0?IAAAAAAAAAAAAAAA@@@QAE@XZ"
+// X64: call {{.*}} @"??0?$LongLongTemplate@$0?IAAAAAAAAAAAAAAA@@@QEAA@XZ"
LongLongTemplate<9223372036854775807LL> int64_max;
-// CHECK: call {{.*}} @"\01??0?$LongLongTemplate@$0HPPPPPPPPPPPPPPP@@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$LongLongTemplate@$0HPPPPPPPPPPPPPPP@@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$LongLongTemplate@$0HPPPPPPPPPPPPPPP@@@QAE@XZ"
+// X64: call {{.*}} @"??0?$LongLongTemplate@$0HPPPPPPPPPPPPPPP@@@QEAA@XZ"
UnsignedLongLongTemplate<18446744073709551615ULL> uint64_max;
-// CHECK: call {{.*}} @"\01??0?$UnsignedLongLongTemplate@$0?0@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$UnsignedLongLongTemplate@$0?0@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$UnsignedLongLongTemplate@$0?0@@QAE@XZ"
+// X64: call {{.*}} @"??0?$UnsignedLongLongTemplate@$0?0@@QEAA@XZ"
UnsignedLongLongTemplate<(unsigned long long)-1> uint64_neg_1;
-// CHECK: call {{.*}} @"\01??0?$UnsignedLongLongTemplate@$0?0@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$UnsignedLongLongTemplate@$0?0@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$UnsignedLongLongTemplate@$0?0@@QAE@XZ"
+// X64: call {{.*}} @"??0?$UnsignedLongLongTemplate@$0?0@@QEAA@XZ"
}
namespace space {
template<class T> const T& foo(const T& l) { return l; }
}
-// CHECK: "\01??$foo@H@space@@YAABHABH@Z"
-// X64: "\01??$foo@H@space@@YAAEBHAEBH@Z"
+// CHECK: "??$foo@H@space@@YAABHABH@Z"
+// X64: "??$foo@H@space@@YAAEBHAEBH@Z"
void use() {
space::foo(42);
@@ -178,8 +178,8 @@ void FunctionPointerTemplate() {
void spam() {
FunctionPointerTemplate<spam>();
-// CHECK: "\01??$FunctionPointerTemplate@$1?spam@@YAXXZ@@YAXXZ"
-// X64: "\01??$FunctionPointerTemplate@$1?spam@@YAXXZ@@YAXXZ"
+// CHECK: "??$FunctionPointerTemplate@$1?spam@@YAXXZ@@YAXXZ"
+// X64: "??$FunctionPointerTemplate@$1?spam@@YAXXZ@@YAXXZ"
}
// Unlike Itanium, there is no character code to indicate an argument pack.
@@ -190,8 +190,8 @@ void variadic_fn_instantiate() {
variadic_fn_template(0, 1, 3, 4);
variadic_fn_template(0, 1, 'a', "b");
}
-// CHECK: "\01??$variadic_fn_template@HHHH@@YAXABH000@Z"
-// CHECK: "\01??$variadic_fn_template@HHD$$BY01D@@YAXABH0ABDAAY01$$CBD@Z"
+// CHECK: "??$variadic_fn_template@HHHH@@YAXABH000@Z"
+// CHECK: "??$variadic_fn_template@HHD$$BY01D@@YAXABH0ABDAAY01$$CBD@Z"
template <typename ...Ts>
struct VariadicClass {
@@ -202,8 +202,8 @@ void variadic_class_instantiate() {
VariadicClass<int, char, bool> a;
VariadicClass<bool, char, int> b;
}
-// CHECK: call {{.*}} @"\01??0?$VariadicClass@HD_N@@QAE@XZ"
-// CHECK: call {{.*}} @"\01??0?$VariadicClass@_NDH@@QAE@XZ"
+// CHECK: call {{.*}} @"??0?$VariadicClass@HD_N@@QAE@XZ"
+// CHECK: call {{.*}} @"??0?$VariadicClass@_NDH@@QAE@XZ"
template <typename T>
struct Second {};
@@ -224,7 +224,7 @@ template <template <class> class T>
struct Thing<T, true> { };
void template_template_fun(Type<Thing<Second, true>, Second>) { }
-// CHECK: "\01?template_template_fun@@YAXU?$Type@U?$Thing@USecond@@$00@@USecond@@@@@Z"
+// CHECK: "?template_template_fun@@YAXU?$Type@U?$Thing@USecond@@$00@@USecond@@@@@Z"
template <typename T>
void template_template_specialization();
@@ -232,12 +232,12 @@ void template_template_specialization();
template <>
void template_template_specialization<void (Type<Thing<Second, true>, Second>)>() {
}
-// CHECK: "\01??$template_template_specialization@$$A6AXU?$Type@U?$Thing@USecond@@$00@@USecond@@@@@Z@@YAXXZ"
+// CHECK: "??$template_template_specialization@$$A6AXU?$Type@U?$Thing@USecond@@$00@@USecond@@@@@Z@@YAXXZ"
// PR16788
template <decltype(nullptr)> struct S1 {};
void f(S1<nullptr>) {}
-// CHECK: "\01?f@@YAXU?$S1@$0A@@@@Z"
+// CHECK: "?f@@YAXU?$S1@$0A@@@@Z"
struct record {
int first;
@@ -248,7 +248,7 @@ struct type1 {
};
extern const record inst;
void recref(type1<inst>) {}
-// CHECK: "\01?recref@@YAXU?$type1@$E?inst@@3Urecord@@B@@@Z"
+// CHECK: "?recref@@YAXU?$type1@$E?inst@@3Urecord@@B@@@Z"
struct _GUID {};
struct __declspec(uuid("{12345678-1234-1234-1234-1234567890aB}")) uuid;
@@ -260,18 +260,18 @@ template <typename T, const _GUID &G = __uuidof(T)>
struct UUIDType2 {};
void fun(UUIDType1<uuid> a) {}
-// CHECK: "\01?fun@@YAXU?$UUIDType1@Uuuid@@$1?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@@Z"
+// CHECK: "?fun@@YAXU?$UUIDType1@Uuuid@@$1?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@@Z"
void fun(UUIDType2<uuid> b) {}
-// CHECK: "\01?fun@@YAXU?$UUIDType2@Uuuid@@$E?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@@Z"
+// CHECK: "?fun@@YAXU?$UUIDType2@Uuuid@@$E?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@@Z"
template <typename T> struct TypeWithFriendDefinition {
friend void FunctionDefinedWithInjectedName(TypeWithFriendDefinition<T>) {}
};
-// CHECK: call {{.*}} @"\01?FunctionDefinedWithInjectedName@@YAXU?$TypeWithFriendDefinition@H@@@Z"
+// CHECK: call {{.*}} @"?FunctionDefinedWithInjectedName@@YAXU?$TypeWithFriendDefinition@H@@@Z"
void CallFunctionDefinedWithInjectedName() {
FunctionDefinedWithInjectedName(TypeWithFriendDefinition<int>());
}
-// CHECK: @"\01?FunctionDefinedWithInjectedName@@YAXU?$TypeWithFriendDefinition@H@@@Z"
+// CHECK: @"?FunctionDefinedWithInjectedName@@YAXU?$TypeWithFriendDefinition@H@@@Z"
// We need to be able to feed GUIDs through a couple rounds of template
// substitution.
@@ -284,5 +284,5 @@ struct UUIDType4 : UUIDType3<G> {
void bar() { UUIDType4::foo(); }
};
template struct UUIDType4<&__uuidof(uuid)>;
-// CHECK: "\01?bar@?$UUIDType4@$1?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@QAEXXZ"
-// CHECK: "\01?foo@?$UUIDType3@$1?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@QAEXXZ"
+// CHECK: "?bar@?$UUIDType4@$1?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@QAEXXZ"
+// CHECK: "?foo@?$UUIDType3@$1?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@QAEXXZ"
diff --git a/test/CodeGenCXX/mangle-ms-vector-types.cpp b/test/CodeGenCXX/mangle-ms-vector-types.cpp
index 53a1a43fe4af..f55713e6c0c8 100644
--- a/test/CodeGenCXX/mangle-ms-vector-types.cpp
+++ b/test/CodeGenCXX/mangle-ms-vector-types.cpp
@@ -1,37 +1,98 @@
-// RUN: %clang_cc1 -fms-extensions -ffreestanding -target-feature +avx -emit-llvm %s -o - -triple=i686-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -fms-extensions -fcxx-exceptions -ffreestanding -target-feature +avx -emit-llvm %s -o - -triple=i686-pc-win32 | FileCheck %s
#include <xmmintrin.h>
#include <emmintrin.h>
#include <immintrin.h>
+void thow(int i) {
+ switch (i) {
+ case 0: throw __m64();
+ // CHECK: ??_R0?AT__m64@@@8
+ // CHECK: _CT??_R0?AT__m64@@@88
+ // CHECK: _CTA1?AT__m64@@
+ // CHECK: _TI1?AT__m64@@
+ case 1: throw __m128();
+ // CHECK: ??_R0?AT__m128@@@8
+ // CHECK: _CT??_R0?AT__m128@@@816
+ // CHECK: _CTA1?AT__m128@@
+ // CHECK: _TI1?AT__m128@@
+ case 2: throw __m128d();
+ // CHECK: ??_R0?AU__m128d@@@8
+ // CHECK: _CT??_R0?AU__m128d@@@816
+ // CHECK: _CTA1?AU__m128d@@
+ // CHECK: _TI1?AU__m128d@@
+ case 3: throw __m128i();
+ // CHECK: ??_R0?AT__m128i@@@8
+ // CHECK: _CT??_R0?AT__m128i@@@816
+ // CHECK: _CTA1?AT__m128i@@
+ // CHECK: _TI1?AT__m128i@@
+ case 4: throw __m256();
+ // CHECK: ??_R0?AT__m256@@@8
+ // CHECK: _CT??_R0?AT__m256@@@832
+ // CHECK: _CTA1?AT__m256@@
+ // CHECK: _TI1?AT__m256@@
+ case 5: throw __m256d();
+ // CHECK: ??_R0?AU__m256d@@@8
+ // CHECK: _CT??_R0?AU__m256d@@@832
+ // CHECK: _CTA1?AU__m256d@@
+ // CHECK: _TI1?AU__m256d@@
+ case 6: throw __m256i();
+ // CHECK: ??_R0?AT__m256@@@8
+ // CHECK: _CT??_R0?AT__m256@@@832
+ // CHECK: _CTA1?AT__m256@@
+ // CHECK: _TI1?AT__m256@@
+ }
+}
+
void foo64(__m64) {}
-// CHECK: define void @"\01?foo64@@YAXT__m64@@@Z"
+// CHECK: define dso_local void @"?foo64@@YAXT__m64@@@Z"
+
+__m64 rfoo64() { return __m64(); }
+// CHECK: define dso_local <1 x i64> @"?rfoo64@@YA?AT__m64@@XZ"
void foo128(__m128) {}
-// CHECK: define void @"\01?foo128@@YAXT__m128@@@Z"
+// CHECK: define dso_local void @"?foo128@@YAXT__m128@@@Z"
+
+const __m128 rfoo128() { return __m128(); }
+// CHECK: define dso_local <4 x float> @"?rfoo128@@YA?BT__m128@@XZ"
void foo128d(__m128d) {}
-// CHECK: define void @"\01?foo128d@@YAXU__m128d@@@Z"
+// CHECK: define dso_local void @"?foo128d@@YAXU__m128d@@@Z"
+
+volatile __m128d rfoo128d() { return __m128d(); }
+// CHECK: define dso_local <2 x double> @"?rfoo128d@@YA?CU__m128d@@XZ"
void foo128i(__m128i) {}
-// CHECK: define void @"\01?foo128i@@YAXT__m128i@@@Z"
+// CHECK: define dso_local void @"?foo128i@@YAXT__m128i@@@Z"
+
+const volatile __m128i rfoo128i() { return __m128i(); }
+// CHECK: define dso_local <2 x i64> @"?rfoo128i@@YA?DT__m128i@@XZ"
void foo256(__m256) {}
-// CHECK: define void @"\01?foo256@@YAXT__m256@@@Z"
+// CHECK: define dso_local void @"?foo256@@YAXT__m256@@@Z"
+
+__m256 rfoo256() { return __m256(); }
+// CHECK: define dso_local <8 x float> @"?rfoo256@@YA?AT__m256@@XZ"
void foo256d(__m256d) {}
-// CHECK: define void @"\01?foo256d@@YAXU__m256d@@@Z"
+// CHECK: define dso_local void @"?foo256d@@YAXU__m256d@@@Z"
+
+__m256d rfoo256d() { return __m256d(); }
+// CHECK: define dso_local <4 x double> @"?rfoo256d@@YA?AU__m256d@@XZ"
void foo256i(__m256i) {}
-// CHECK: define void @"\01?foo256i@@YAXT__m256i@@@Z"
+// CHECK: define dso_local void @"?foo256i@@YAXT__m256i@@@Z"
+
+__m256i rfoo256i() { return __m256i(); }
+// CHECK: define dso_local <4 x i64> @"?rfoo256i@@YA?AT__m256i@@XZ"
// We have a custom mangling for vector types not standardized by Intel.
void foov8hi(__v8hi) {}
-// CHECK: define void @"\01?foov8hi@@YAXT?$__vector@F$07@__clang@@@Z"
+// CHECK: define dso_local void @"?foov8hi@@YAXT?$__vector@F$07@__clang@@@Z"
typedef __attribute__((ext_vector_type(4))) int vi4b;
void foovi4b(vi4b) {}
-// CHECK: define void @"\01?foovi4b@@YAXT?$__vector@H$03@__clang@@@Z"
+// CHECK: define dso_local void @"?foovi4b@@YAXT?$__vector@H$03@__clang@@@Z"
// Clang does not support vectors of complex types, so we can't test the
// mangling of them.
diff --git a/test/CodeGenCXX/mangle-ms.cpp b/test/CodeGenCXX/mangle-ms.cpp
index 7e2f17f27a96..3cc1b1645e9c 100644
--- a/test/CodeGenCXX/mangle-ms.cpp
+++ b/test/CodeGenCXX/mangle-ms.cpp
@@ -2,7 +2,7 @@
// RUN: %clang_cc1 -fblocks -emit-llvm %s -o - -triple=x86_64-pc-win32 -std=c++98| FileCheck -check-prefix X64 %s
int a;
-// CHECK-DAG: @"\01?a@@3HA"
+// CHECK-DAG: @"?a@@3HA"
extern "C++" {
static int __attribute__((used)) ignore_transparent_context;
@@ -11,11 +11,11 @@ static int __attribute__((used)) ignore_transparent_context;
namespace N {
int b;
-// CHECK-DAG: @"\01?b@N@@3HA"
+// CHECK-DAG: @"?b@N@@3HA"
namespace {
int anonymous;
-// CHECK-DAG: @"\01?anonymous@?A@N@@3HA"
+// CHECK-DAG: @"?anonymous@?A@N@@3HA"
}
}
@@ -23,38 +23,38 @@ static int c;
// CHECK-DAG: @c
int _c(void) {return N::anonymous + c;}
-// CHECK-DAG: @"\01?_c@@YAHXZ"
-// X64-DAG: @"\01?_c@@YAHXZ"
+// CHECK-DAG: @"?_c@@YAHXZ"
+// X64-DAG: @"?_c@@YAHXZ"
const int &NeedsReferenceTemporary = 2;
-// CHECK-DAG: @"\01?NeedsReferenceTemporary@@3ABHB" = constant i32* @"\01?$RT1@NeedsReferenceTemporary@@3ABHB"
-// X64-DAG: @"\01?NeedsReferenceTemporary@@3AEBHEB" = constant i32* @"\01?$RT1@NeedsReferenceTemporary@@3AEBHEB"
+// CHECK-DAG: @"?NeedsReferenceTemporary@@3ABHB" = dso_local constant i32* @"?$RT1@NeedsReferenceTemporary@@3ABHB"
+// X64-DAG: @"?NeedsReferenceTemporary@@3AEBHEB" = dso_local constant i32* @"?$RT1@NeedsReferenceTemporary@@3AEBHEB"
class foo {
static const short d;
-// CHECK-DAG: @"\01?d@foo@@0FB"
+// CHECK-DAG: @"?d@foo@@0FB"
protected:
static volatile long e;
-// CHECK-DAG: @"\01?e@foo@@1JC"
+// CHECK-DAG: @"?e@foo@@1JC"
public:
static const volatile char f;
-// CHECK-DAG: @"\01?f@foo@@2DD"
+// CHECK-DAG: @"?f@foo@@2DD"
int operator+(int a);
foo(){}
-// CHECK-DAG: @"\01??0foo@@QAE@XZ"
-// X64-DAG: @"\01??0foo@@QEAA@XZ"
+// CHECK-DAG: @"??0foo@@QAE@XZ"
+// X64-DAG: @"??0foo@@QEAA@XZ"
~foo(){}
-// CHECK-DAG: @"\01??1foo@@QAE@XZ"
-// X64-DAG: @"\01??1foo@@QEAA@XZ
+// CHECK-DAG: @"??1foo@@QAE@XZ"
+// X64-DAG: @"??1foo@@QEAA@XZ
foo(int i){}
-// CHECK-DAG: @"\01??0foo@@QAE@H@Z"
-// X64-DAG: @"\01??0foo@@QEAA@H@Z"
+// CHECK-DAG: @"??0foo@@QAE@H@Z"
+// X64-DAG: @"??0foo@@QEAA@H@Z"
foo(char *q){}
-// CHECK-DAG: @"\01??0foo@@QAE@PAD@Z"
-// X64-DAG: @"\01??0foo@@QEAA@PEAD@Z"
+// CHECK-DAG: @"??0foo@@QAE@PAD@Z"
+// X64-DAG: @"??0foo@@QEAA@PEAD@Z"
static foo* static_method() { return 0; }
@@ -79,16 +79,16 @@ enum quux {
};
foo bar() { return foo(); }
-// CHECK-DAG: @"\01?bar@@YA?AVfoo@@XZ"
-// X64-DAG: @"\01?bar@@YA?AVfoo@@XZ"
+// CHECK-DAG: @"?bar@@YA?AVfoo@@XZ"
+// X64-DAG: @"?bar@@YA?AVfoo@@XZ"
int foo::operator+(int a) {
-// CHECK-DAG: @"\01??Hfoo@@QAEHH@Z"
-// X64-DAG: @"\01??Hfoo@@QEAAHH@Z"
+// CHECK-DAG: @"??Hfoo@@QAEHH@Z"
+// X64-DAG: @"??Hfoo@@QEAAHH@Z"
foo::static_method();
-// CHECK-DAG: @"\01?static_method@foo@@SAPAV1@XZ"
-// X64-DAG: @"\01?static_method@foo@@SAPEAV1@XZ"
+// CHECK-DAG: @"?static_method@foo@@SAPAV1@XZ"
+// X64-DAG: @"?static_method@foo@@SAPEAV1@XZ"
bar();
return a;
}
@@ -98,33 +98,33 @@ volatile long foo::e;
const volatile char foo::f = 'C';
int bar::g;
-// CHECK-DAG: @"\01?g@bar@@2HA"
+// CHECK-DAG: @"?g@bar@@2HA"
extern int * const h1 = &a;
-// CHECK-DAG: @"\01?h1@@3QAHA"
+// CHECK-DAG: @"?h1@@3QAHA"
extern const int * const h2 = &a;
-// CHECK-DAG: @"\01?h2@@3QBHB"
+// CHECK-DAG: @"?h2@@3QBHB"
extern int * const __restrict h3 = &a;
-// CHECK-DAG: @"\01?h3@@3QIAHIA"
-// X64-DAG: @"\01?h3@@3QEIAHEIA"
+// CHECK-DAG: @"?h3@@3QIAHIA"
+// X64-DAG: @"?h3@@3QEIAHEIA"
int i[10][20];
-// CHECK-DAG: @"\01?i@@3PAY0BE@HA"
+// CHECK-DAG: @"?i@@3PAY0BE@HA"
typedef int (*FunT)(int, int);
FunT FunArr[10][20];
-// CHECK-DAG: @"\01?FunArr@@3PAY0BE@P6AHHH@ZA"
-// X64-DAG: @"\01?FunArr@@3PAY0BE@P6AHHH@ZA"
+// CHECK-DAG: @"?FunArr@@3PAY0BE@P6AHHH@ZA"
+// X64-DAG: @"?FunArr@@3PAY0BE@P6AHHH@ZA"
int (__stdcall *j)(signed char, unsigned char);
-// CHECK-DAG: @"\01?j@@3P6GHCE@ZA"
+// CHECK-DAG: @"?j@@3P6GHCE@ZA"
const volatile char foo2::*k;
-// CHECK-DAG: @"\01?k@@3PTfoo@@DT1@"
-// X64-DAG: @"\01?k@@3PETfoo@@DET1@"
+// CHECK-DAG: @"?k@@3PTfoo@@DT1@"
+// X64-DAG: @"?k@@3PETfoo@@DET1@"
int (foo2::*l)(int);
-// CHECK-DAG: @"\01?l@@3P8foo@@AEHH@ZQ1@"
+// CHECK-DAG: @"?l@@3P8foo@@AEHH@ZQ1@"
// Ensure typedef CV qualifiers are mangled correctly
typedef const int cInt;
@@ -135,141 +135,141 @@ extern cInt g_cInt = 1;
vInt g_vInt = 2;
cvInt g_cvInt = 3;
-// CHECK-DAG: @"\01?g_cInt@@3HB"
-// CHECK-DAG: @"\01?g_vInt@@3HC"
-// CHECK-DAG: @"\01?g_cvInt@@3HD"
+// CHECK-DAG: @"?g_cInt@@3HB"
+// CHECK-DAG: @"?g_vInt@@3HC"
+// CHECK-DAG: @"?g_cvInt@@3HD"
// Static functions are mangled, too.
// Also make sure calling conventions, arglists, and throw specs work.
static void __stdcall alpha(float a, double b) throw() {}
bool __fastcall beta(long long a, wchar_t b) throw(signed char, unsigned char) {
-// CHECK-DAG: @"\01?beta@@YI_N_J_W@Z"
-// X64-DAG: @"\01?beta@@YA_N_J_W@Z"
+// CHECK-DAG: @"?beta@@YI_N_J_W@Z"
+// X64-DAG: @"?beta@@YA_N_J_W@Z"
alpha(0.f, 0.0);
return false;
}
-// CHECK-DAG: @"\01?alpha@@YGXMN@Z"
-// X64-DAG: @"\01?alpha@@YAXMN@Z"
+// CHECK-DAG: @"?alpha@@YGXMN@Z"
+// X64-DAG: @"?alpha@@YAXMN@Z"
// Make sure tag-type mangling works.
void gamma(class foo, struct bar, union baz, enum quux) {}
-// CHECK-DAG: @"\01?gamma@@YAXVfoo@@Ubar@@Tbaz@@W4quux@@@Z"
-// X64-DAG: @"\01?gamma@@YAXVfoo@@Ubar@@Tbaz@@W4quux@@@Z"
+// CHECK-DAG: @"?gamma@@YAXVfoo@@Ubar@@Tbaz@@W4quux@@@Z"
+// X64-DAG: @"?gamma@@YAXVfoo@@Ubar@@Tbaz@@W4quux@@@Z"
// Make sure pointer/reference-type mangling works.
void delta(int * const a, const long &) {}
-// CHECK-DAG: @"\01?delta@@YAXQAHABJ@Z"
-// X64-DAG: @"\01?delta@@YAXQEAHAEBJ@Z"
+// CHECK-DAG: @"?delta@@YAXQAHABJ@Z"
+// X64-DAG: @"?delta@@YAXQEAHAEBJ@Z"
// Array mangling.
void epsilon(int a[][10][20]) {}
-// CHECK-DAG: @"\01?epsilon@@YAXQAY19BE@H@Z"
-// X64-DAG: @"\01?epsilon@@YAXQEAY19BE@H@Z"
+// CHECK-DAG: @"?epsilon@@YAXQAY19BE@H@Z"
+// X64-DAG: @"?epsilon@@YAXQEAY19BE@H@Z"
void zeta(int (*)(int, int)) {}
-// CHECK-DAG: @"\01?zeta@@YAXP6AHHH@Z@Z"
-// X64-DAG: @"\01?zeta@@YAXP6AHHH@Z@Z"
+// CHECK-DAG: @"?zeta@@YAXP6AHHH@Z@Z"
+// X64-DAG: @"?zeta@@YAXP6AHHH@Z@Z"
// Blocks mangling (Clang extension). A block should be mangled slightly
// differently from a similar function pointer.
void eta(int (^)(int, int)) {}
-// CHECK-DAG: @"\01?eta@@YAXP_EAHHH@Z@Z"
+// CHECK-DAG: @"?eta@@YAXP_EAHHH@Z@Z"
typedef int theta_arg(int,int);
void theta(theta_arg^ block) {}
-// CHECK-DAG: @"\01?theta@@YAXP_EAHHH@Z@Z"
+// CHECK-DAG: @"?theta@@YAXP_EAHHH@Z@Z"
void operator_new_delete() {
char *ptr = new char;
-// CHECK-DAG: @"\01??2@YAPAXI@Z"
+// CHECK-DAG: @"??2@YAPAXI@Z"
delete ptr;
-// CHECK-DAG: @"\01??3@YAXPAX@Z"
+// CHECK-DAG: @"??3@YAXPAX@Z"
char *array = new char[42];
-// CHECK-DAG: @"\01??_U@YAPAXI@Z"
+// CHECK-DAG: @"??_U@YAPAXI@Z"
delete [] array;
-// CHECK-DAG: @"\01??_V@YAXPAX@Z"
+// CHECK-DAG: @"??_V@YAXPAX@Z"
}
// PR13022
void (redundant_parens)();
void redundant_parens_use() { redundant_parens(); }
-// CHECK-DAG: @"\01?redundant_parens@@YAXXZ"
-// X64-DAG: @"\01?redundant_parens@@YAXXZ"
+// CHECK-DAG: @"?redundant_parens@@YAXXZ"
+// X64-DAG: @"?redundant_parens@@YAXXZ"
// PR13047
typedef double RGB[3];
RGB color1;
-// CHECK-DAG: @"\01?color1@@3PANA"
+// CHECK-DAG: @"?color1@@3PANA"
extern const RGB color2 = {};
-// CHECK-DAG: @"\01?color2@@3QBNB"
+// CHECK-DAG: @"?color2@@3QBNB"
extern RGB const color3[5] = {};
-// CHECK-DAG: @"\01?color3@@3QAY02$$CBNA"
+// CHECK-DAG: @"?color3@@3QAY02$$CBNA"
extern RGB const ((color4)[5]) = {};
-// CHECK-DAG: @"\01?color4@@3QAY02$$CBNA"
+// CHECK-DAG: @"?color4@@3QAY02$$CBNA"
struct B;
volatile int B::* volatile memptr1;
-// X64-DAG: @"\01?memptr1@@3RESB@@HES1@"
+// X64-DAG: @"?memptr1@@3RESB@@HES1@"
volatile int B::* memptr2;
-// X64-DAG: @"\01?memptr2@@3PESB@@HES1@"
+// X64-DAG: @"?memptr2@@3PESB@@HES1@"
int B::* volatile memptr3;
-// X64-DAG: @"\01?memptr3@@3REQB@@HEQ1@"
+// X64-DAG: @"?memptr3@@3REQB@@HEQ1@"
typedef int (*fun)();
volatile fun B::* volatile funmemptr1;
-// X64-DAG: @"\01?funmemptr1@@3RESB@@R6AHXZES1@"
+// X64-DAG: @"?funmemptr1@@3RESB@@R6AHXZES1@"
volatile fun B::* funmemptr2;
-// X64-DAG: @"\01?funmemptr2@@3PESB@@R6AHXZES1@"
+// X64-DAG: @"?funmemptr2@@3PESB@@R6AHXZES1@"
fun B::* volatile funmemptr3;
-// X64-DAG: @"\01?funmemptr3@@3REQB@@P6AHXZEQ1@"
+// X64-DAG: @"?funmemptr3@@3REQB@@P6AHXZEQ1@"
void (B::* volatile memptrtofun1)();
-// X64-DAG: @"\01?memptrtofun1@@3R8B@@EAAXXZEQ1@"
+// X64-DAG: @"?memptrtofun1@@3R8B@@EAAXXZEQ1@"
const void (B::* memptrtofun2)();
-// X64-DAG: @"\01?memptrtofun2@@3P8B@@EAAXXZEQ1@"
+// X64-DAG: @"?memptrtofun2@@3P8B@@EAAXXZEQ1@"
volatile void (B::* memptrtofun3)();
-// X64-DAG: @"\01?memptrtofun3@@3P8B@@EAAXXZEQ1@"
+// X64-DAG: @"?memptrtofun3@@3P8B@@EAAXXZEQ1@"
int (B::* volatile memptrtofun4)();
-// X64-DAG: @"\01?memptrtofun4@@3R8B@@EAAHXZEQ1@"
+// X64-DAG: @"?memptrtofun4@@3R8B@@EAAHXZEQ1@"
volatile int (B::* memptrtofun5)();
-// X64-DAG: @"\01?memptrtofun5@@3P8B@@EAA?CHXZEQ1@"
+// X64-DAG: @"?memptrtofun5@@3P8B@@EAA?CHXZEQ1@"
const int (B::* memptrtofun6)();
-// X64-DAG: @"\01?memptrtofun6@@3P8B@@EAA?BHXZEQ1@"
+// X64-DAG: @"?memptrtofun6@@3P8B@@EAA?BHXZEQ1@"
fun (B::* volatile memptrtofun7)();
-// X64-DAG: @"\01?memptrtofun7@@3R8B@@EAAP6AHXZXZEQ1@"
+// X64-DAG: @"?memptrtofun7@@3R8B@@EAAP6AHXZXZEQ1@"
volatile fun (B::* memptrtofun8)();
-// X64-DAG: @"\01?memptrtofun8@@3P8B@@EAAR6AHXZXZEQ1@"
+// X64-DAG: @"?memptrtofun8@@3P8B@@EAAR6AHXZXZEQ1@"
const fun (B::* memptrtofun9)();
-// X64-DAG: @"\01?memptrtofun9@@3P8B@@EAAQ6AHXZXZEQ1@"
+// X64-DAG: @"?memptrtofun9@@3P8B@@EAAQ6AHXZXZEQ1@"
// PR12603
enum E {};
-// CHECK-DAG: "\01?fooE@@YA?AW4E@@XZ"
-// X64-DAG: "\01?fooE@@YA?AW4E@@XZ"
+// CHECK-DAG: "?fooE@@YA?AW4E@@XZ"
+// X64-DAG: "?fooE@@YA?AW4E@@XZ"
E fooE() { return E(); }
class X {};
-// CHECK-DAG: "\01?fooX@@YA?AVX@@XZ"
-// X64-DAG: "\01?fooX@@YA?AVX@@XZ"
+// CHECK-DAG: "?fooX@@YA?AVX@@XZ"
+// X64-DAG: "?fooX@@YA?AVX@@XZ"
X fooX() { return X(); }
namespace PR13182 {
extern char s0[];
- // CHECK-DAG: @"\01?s0@PR13182@@3PADA"
+ // CHECK-DAG: @"?s0@PR13182@@3PADA"
extern char s1[42];
- // CHECK-DAG: @"\01?s1@PR13182@@3PADA"
+ // CHECK-DAG: @"?s1@PR13182@@3PADA"
extern const char s2[];
- // CHECK-DAG: @"\01?s2@PR13182@@3QBDB"
+ // CHECK-DAG: @"?s2@PR13182@@3QBDB"
extern const char s3[42];
- // CHECK-DAG: @"\01?s3@PR13182@@3QBDB"
+ // CHECK-DAG: @"?s3@PR13182@@3QBDB"
extern volatile char s4[];
- // CHECK-DAG: @"\01?s4@PR13182@@3RCDC"
+ // CHECK-DAG: @"?s4@PR13182@@3RCDC"
extern const volatile char s5[];
- // CHECK-DAG: @"\01?s5@PR13182@@3SDDD"
+ // CHECK-DAG: @"?s5@PR13182@@3SDDD"
extern const char* const* s6;
- // CHECK-DAG: @"\01?s6@PR13182@@3PBQBDB"
+ // CHECK-DAG: @"?s6@PR13182@@3PBQBDB"
char foo() {
return s0[0] + s1[0] + s2[0] + s3[0] + s4[0] + s5[0] + s6[0][0];
@@ -278,8 +278,8 @@ namespace PR13182 {
extern "C" inline void extern_c_func() {
static int local;
-// CHECK-DAG: @"\01?local@?1??extern_c_func@@9@4HA"
-// X64-DAG: @"\01?local@?1??extern_c_func@@9@4HA"
+// CHECK-DAG: @"?local@?1??extern_c_func@@9@4HA"
+// X64-DAG: @"?local@?1??extern_c_func@@9@4HA"
}
void call_extern_c_func() {
@@ -310,7 +310,7 @@ inline int inline_function_with_local_type() {
static struct {
int a_field;
} static_variable_in_inline_function = { 20 }, second_static = { 40 };
- // CHECK: @"\01?static_variable_in_inline_function@?1??inline_function_with_local_type@@YAHXZ@4U<unnamed-type-static_variable_in_inline_function>@?1??1@YAHXZ@A"
+ // CHECK: @"?static_variable_in_inline_function@?1??inline_function_with_local_type@@YAHXZ@4U<unnamed-type-static_variable_in_inline_function>@?1??1@YAHXZ@A"
return static_variable_in_inline_function.a_field + second_static.a_field;
}
@@ -325,7 +325,7 @@ inline int templated_inline_function_with_local_type() {
int a_field;
} static_variable_in_templated_inline_function = { 20 },
second_static = { 40 };
- // CHECK: @"\01?static_variable_in_templated_inline_function@?1???$templated_inline_function_with_local_type@H@@YAHXZ@4U<unnamed-type-static_variable_in_templated_inline_function>@?1???$templated_inline_function_with_local_type@H@@YAHXZ@A"
+ // CHECK: @"?static_variable_in_templated_inline_function@?1???$templated_inline_function_with_local_type@H@@YAHXZ@4U<unnamed-type-static_variable_in_templated_inline_function>@?1???$templated_inline_function_with_local_type@H@@YAHXZ@A"
return static_variable_in_templated_inline_function.a_field +
second_static.a_field;
@@ -388,16 +388,16 @@ void TypedefNewDelete::operator delete[](void *) { }
// CHECK-DAG: ??_VTypedefNewDelete@@SAXPAX@Z
void __vectorcall vector_func() { }
-// CHECK-DAG: @"\01?vector_func@@YQXXZ"
+// CHECK-DAG: @"?vector_func@@YQXXZ"
template <void (*)(void)>
void fn_tmpl() {}
template void fn_tmpl<extern_c_func>();
-// CHECK-DAG: @"\01??$fn_tmpl@$1?extern_c_func@@YAXXZ@@YAXXZ"
+// CHECK-DAG: @"??$fn_tmpl@$1?extern_c_func@@YAXXZ@@YAXXZ"
extern "C" void __attribute__((overloadable)) overloaded_fn() {}
-// CHECK-DAG: @"\01?overloaded_fn@@$$J0YAXXZ"
+// CHECK-DAG: @"?overloaded_fn@@$$J0YAXXZ"
extern "C" void overloaded_fn2() {}
// CHECK-DAG: @overloaded_fn2
@@ -420,19 +420,19 @@ void f(S::T3) {}
void f(S::T4) {}
void f(S::T5) {}
void f(S::T6) {}
-// CHECK-DAG: @"\01?f@UnnamedType@@YAXQAPAU<unnamed-type-T1>@S@1@@Z"
-// CHECK-DAG: @"\01?f@UnnamedType@@YAXUT2@S@1@@Z"
-// CHECK-DAG: @"\01?f@UnnamedType@@YAXPAUT4@S@1@@Z"
-// CHECK-DAG: @"\01?f@UnnamedType@@YAXUT4@S@1@@Z"
-// CHECK-DAG: @"\01?f@UnnamedType@@YAXUT5@S@1@@Z"
-// CHECK-DAG: @"\01?f@UnnamedType@@YAXPAU<unnamed-type-T6>@S@1@@Z"
-
-// X64-DAG: @"\01?f@UnnamedType@@YAXQEAPEAU<unnamed-type-T1>@S@1@@Z"
-// X64-DAG: @"\01?f@UnnamedType@@YAXUT2@S@1@@Z"
-// X64-DAG: @"\01?f@UnnamedType@@YAXPEAUT4@S@1@@Z"(%"struct.UnnamedType::S::T4"
-// X64-DAG: @"\01?f@UnnamedType@@YAXUT4@S@1@@Z"
-// X64-DAG: @"\01?f@UnnamedType@@YAXUT5@S@1@@Z"
-// X64-DAG: @"\01?f@UnnamedType@@YAXPEAU<unnamed-type-T6>@S@1@@Z"
+// CHECK-DAG: @"?f@UnnamedType@@YAXQAPAU<unnamed-type-T1>@S@1@@Z"
+// CHECK-DAG: @"?f@UnnamedType@@YAXUT2@S@1@@Z"
+// CHECK-DAG: @"?f@UnnamedType@@YAXPAUT4@S@1@@Z"
+// CHECK-DAG: @"?f@UnnamedType@@YAXUT4@S@1@@Z"
+// CHECK-DAG: @"?f@UnnamedType@@YAXUT5@S@1@@Z"
+// CHECK-DAG: @"?f@UnnamedType@@YAXPAU<unnamed-type-T6>@S@1@@Z"
+
+// X64-DAG: @"?f@UnnamedType@@YAXQEAPEAU<unnamed-type-T1>@S@1@@Z"
+// X64-DAG: @"?f@UnnamedType@@YAXUT2@S@1@@Z"
+// X64-DAG: @"?f@UnnamedType@@YAXPEAUT4@S@1@@Z"(%"struct.UnnamedType::S::T4"
+// X64-DAG: @"?f@UnnamedType@@YAXUT4@S@1@@Z"
+// X64-DAG: @"?f@UnnamedType@@YAXUT5@S@1@@Z"
+// X64-DAG: @"?f@UnnamedType@@YAXPEAU<unnamed-type-T6>@S@1@@Z"
}
namespace PassObjectSize {
@@ -448,24 +448,28 @@ namespace PassObjectSize {
// void foo(void *const, __clang::__pass_object_size0);
// where __clang is a top-level namespace.
-// CHECK-DAG: define i32 @"\01?foo@PassObjectSize@@YAHQAHW4__pass_object_size0@__clang@@@Z"
+// CHECK-DAG: define dso_local i32 @"?foo@PassObjectSize@@YAHQAHW4__pass_object_size0@__clang@@@Z"
int foo(int *const i __attribute__((pass_object_size(0)))) { return 0; }
-// CHECK-DAG: define i32 @"\01?bar@PassObjectSize@@YAHQAHW4__pass_object_size1@__clang@@@Z"
+// CHECK-DAG: define dso_local i32 @"?bar@PassObjectSize@@YAHQAHW4__pass_object_size1@__clang@@@Z"
int bar(int *const i __attribute__((pass_object_size(1)))) { return 0; }
-// CHECK-DAG: define i32 @"\01?qux@PassObjectSize@@YAHQAHW4__pass_object_size1@__clang@@0W4__pass_object_size0@3@@Z"
+// CHECK-DAG: define dso_local i32 @"?qux@PassObjectSize@@YAHQAHW4__pass_object_size1@__clang@@0W4__pass_object_size0@3@@Z"
int qux(int *const i __attribute__((pass_object_size(1))), int *const j __attribute__((pass_object_size(0)))) { return 0; }
-// CHECK-DAG: define i32 @"\01?zot@PassObjectSize@@YAHQAHW4__pass_object_size1@__clang@@01@Z"
+// CHECK-DAG: define dso_local i32 @"?zot@PassObjectSize@@YAHQAHW4__pass_object_size1@__clang@@01@Z"
int zot(int *const i __attribute__((pass_object_size(1))), int *const j __attribute__((pass_object_size(1)))) { return 0; }
}
namespace Atomic {
-// CHECK-DAG: define void @"\01?f@Atomic@@YAXU?$_Atomic@H@__clang@@@Z"(
+// CHECK-DAG: define dso_local void @"?f@Atomic@@YAXU?$_Atomic@H@__clang@@@Z"(
void f(_Atomic(int)) {}
}
namespace Complex {
-// CHECK-DAG: define void @"\01?f@Complex@@YAXU?$_Complex@H@__clang@@@Z"(
+// CHECK-DAG: define dso_local void @"?f@Complex@@YAXU?$_Complex@H@__clang@@@Z"(
void f(_Complex int) {}
}
+namespace Float16 {
+// CHECK-DAG: define dso_local void @"?f@Float16@@YAXU_Float16@__clang@@@Z"(
+void f(_Float16) {}
+}
namespace PR26029 {
template <class>
@@ -489,5 +493,5 @@ void runOnFunction() {
L<H<int *> > b;
m_fn3<int>();
}
-// CHECK-DAG: call {{.*}} @"\01??0?$L@V?$H@PAH@PR26029@@@PR26029@@QAE@XZ"
+// CHECK-DAG: call {{.*}} @"??0?$L@V?$H@PAH@PR26029@@@PR26029@@QAE@XZ"
}
diff --git a/test/CodeGenCXX/mangle-windows.cpp b/test/CodeGenCXX/mangle-windows.cpp
index 85644475ddf5..a9d7be1197cc 100644
--- a/test/CodeGenCXX/mangle-windows.cpp
+++ b/test/CodeGenCXX/mangle-windows.cpp
@@ -5,20 +5,20 @@
// RUN: FileCheck --check-prefix=ITANIUM %s
void __stdcall f1(void) {}
-// WIN: define x86_stdcallcc void @"\01?f1@@YGXXZ"
-// ITANIUM: define x86_stdcallcc void @"\01__Z2f1v@0"
+// WIN: define dso_local x86_stdcallcc void @"?f1@@YGXXZ"
+// ITANIUM: define dso_local x86_stdcallcc void @"\01__Z2f1v@0"
void __fastcall f2(void) {}
-// WIN: define x86_fastcallcc void @"\01?f2@@YIXXZ"
-// ITANIUM: define x86_fastcallcc void @"\01@_Z2f2v@0"
+// WIN: define dso_local x86_fastcallcc void @"?f2@@YIXXZ"
+// ITANIUM: define dso_local x86_fastcallcc void @"\01@_Z2f2v@0"
extern "C" void __stdcall f3(void) {}
-// WIN: define x86_stdcallcc void @"\01_f3@0"
-// ITANIUM: define x86_stdcallcc void @"\01_f3@0"
+// WIN: define dso_local x86_stdcallcc void @"\01_f3@0"
+// ITANIUM: define dso_local x86_stdcallcc void @"\01_f3@0"
extern "C" void __fastcall f4(void) {}
-// WIN: define x86_fastcallcc void @"\01@f4@0"
-// ITANIUM: define x86_fastcallcc void @"\01@f4@0"
+// WIN: define dso_local x86_fastcallcc void @"\01@f4@0"
+// ITANIUM: define dso_local x86_fastcallcc void @"\01@f4@0"
struct Foo {
void __stdcall foo();
@@ -26,17 +26,17 @@ struct Foo {
};
void Foo::foo() {}
-// WIN: define x86_stdcallcc void @"\01?foo@Foo@@QAGXXZ"
-// ITANIUM: define x86_stdcallcc void @"\01__ZN3Foo3fooEv@4"
+// WIN: define dso_local x86_stdcallcc void @"?foo@Foo@@QAGXXZ"
+// ITANIUM: define dso_local x86_stdcallcc void @"\01__ZN3Foo3fooEv@4"
void Foo::bar() {}
-// WIN: define x86_stdcallcc void @"\01?bar@Foo@@SGXXZ"
-// ITANIUM: define x86_stdcallcc void @"\01__ZN3Foo3barEv@0"
+// WIN: define dso_local x86_stdcallcc void @"?bar@Foo@@SGXXZ"
+// ITANIUM: define dso_local x86_stdcallcc void @"\01__ZN3Foo3barEv@0"
// Mostly a test that we don't crash and that the names start with a \01.
// gcc on mingw produces __Zpp@4
// cl produces _++@4
extern "C" void __stdcall operator++(Foo &x) {
}
-// WIN: define x86_stdcallcc void @"\01??E@YGXAAUFoo@@@Z"
-// ITANIUM: define x86_stdcallcc void @"\01__ZppR3Foo@4"
+// WIN: define dso_local x86_stdcallcc void @"??E@YGXAAUFoo@@@Z"
+// ITANIUM: define dso_local x86_stdcallcc void @"\01__ZppR3Foo@4"
diff --git a/test/CodeGenCXX/member-function-pointer-calls.cpp b/test/CodeGenCXX/member-function-pointer-calls.cpp
index 67417ef04693..198119b7cdcf 100644
--- a/test/CodeGenCXX/member-function-pointer-calls.cpp
+++ b/test/CodeGenCXX/member-function-pointer-calls.cpp
@@ -11,7 +11,7 @@ int f(A* a, int (A::*fp)()) {
// CHECK-LABEL: define i32 @_Z2g1v()
// CHECK: ret i32 1
-// MINGW64-LABEL: define i32 @_Z2g1v()
+// MINGW64-LABEL: define dso_local i32 @_Z2g1v()
// MINGW64: call i32 @_Z1fP1AMS_FivE(%struct.A* %{{.*}}, { i64, i64 }* %{{.*}})
int g1() {
A a;
@@ -20,7 +20,7 @@ int g1() {
// CHECK-LABEL: define i32 @_Z2g2v()
// CHECK: ret i32 2
-// MINGW64-LABEL: define i32 @_Z2g2v()
+// MINGW64-LABEL: define dso_local i32 @_Z2g2v()
// MINGW64: call i32 @_Z1fP1AMS_FivE(%struct.A* %{{.*}}, { i64, i64 }* %{{.*}})
int g2() {
A a;
diff --git a/test/CodeGenCXX/microsoft-abi-arg-order.cpp b/test/CodeGenCXX/microsoft-abi-arg-order.cpp
index 68c141f1620f..df945f9885e6 100644
--- a/test/CodeGenCXX/microsoft-abi-arg-order.cpp
+++ b/test/CodeGenCXX/microsoft-abi-arg-order.cpp
@@ -13,21 +13,21 @@ void foo(A a, A b, A c) {
// Order of destruction should be left to right.
//
-// X86-LABEL: define void @"\01?foo@@YAXUA@@00@Z"
+// X86-LABEL: define dso_local void @"?foo@@YAXUA@@00@Z"
// X86: ([[argmem_ty:<{ %struct.A, %struct.A, %struct.A }>]]* inalloca)
// X86: %[[a:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %0, i32 0, i32 0
// X86: %[[b:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %0, i32 0, i32 1
// X86: %[[c:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %0, i32 0, i32 2
-// X86: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[a]])
-// X86: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[b]])
-// X86: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[c]])
+// X86: call x86_thiscallcc void @"??1A@@QAE@XZ"(%struct.A* %[[a]])
+// X86: call x86_thiscallcc void @"??1A@@QAE@XZ"(%struct.A* %[[b]])
+// X86: call x86_thiscallcc void @"??1A@@QAE@XZ"(%struct.A* %[[c]])
// X86: ret void
-// X64-LABEL: define void @"\01?foo@@YAXUA@@00@Z"
+// X64-LABEL: define dso_local void @"?foo@@YAXUA@@00@Z"
// X64: (%struct.A* %[[a:[^,]*]], %struct.A* %[[b:[^,]*]], %struct.A* %[[c:[^)]*]])
-// X64: call void @"\01??1A@@QEAA@XZ"(%struct.A* %[[a]])
-// X64: call void @"\01??1A@@QEAA@XZ"(%struct.A* %[[b]])
-// X64: call void @"\01??1A@@QEAA@XZ"(%struct.A* %[[c]])
+// X64: call void @"??1A@@QEAA@XZ"(%struct.A* %[[a]])
+// X64: call void @"??1A@@QEAA@XZ"(%struct.A* %[[b]])
+// X64: call void @"??1A@@QEAA@XZ"(%struct.A* %[[c]])
// X64: ret void
@@ -38,39 +38,39 @@ void call_foo() {
// Order of evaluation should be right to left, and we should clean up the right
// things as we unwind.
//
-// X86-LABEL: define void @"\01?call_foo@@YAXXZ"()
+// X86-LABEL: define dso_local void @"?call_foo@@YAXXZ"()
// X86: call i8* @llvm.stacksave()
// X86: %[[argmem:[^ ]*]] = alloca inalloca [[argmem_ty]]
// X86: %[[arg3:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 2
-// X86: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@H@Z"(%struct.A* %[[arg3]], i32 3)
+// X86: call x86_thiscallcc %struct.A* @"??0A@@QAE@H@Z"(%struct.A* %[[arg3]], i32 3)
// X86: %[[arg2:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 1
-// X86: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@H@Z"(%struct.A* %[[arg2]], i32 2)
+// X86: invoke x86_thiscallcc %struct.A* @"??0A@@QAE@H@Z"(%struct.A* %[[arg2]], i32 2)
// X86: %[[arg1:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 0
-// X86: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@H@Z"(%struct.A* %[[arg1]], i32 1)
-// X86: call void @"\01?foo@@YAXUA@@00@Z"([[argmem_ty]]* inalloca %[[argmem]])
+// X86: invoke x86_thiscallcc %struct.A* @"??0A@@QAE@H@Z"(%struct.A* %[[arg1]], i32 1)
+// X86: call void @"?foo@@YAXUA@@00@Z"([[argmem_ty]]* inalloca %[[argmem]])
// X86: call void @llvm.stackrestore
// X86: ret void
//
// lpad2:
// X86: cleanuppad within none []
-// X86: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg2]])
+// X86: call x86_thiscallcc void @"??1A@@QAE@XZ"(%struct.A* %[[arg2]])
// X86: cleanupret
//
// ehcleanup:
-// X86: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg3]])
+// X86: call x86_thiscallcc void @"??1A@@QAE@XZ"(%struct.A* %[[arg3]])
-// X64-LABEL: define void @"\01?call_foo@@YAXXZ"()
-// X64: call %struct.A* @"\01??0A@@QEAA@H@Z"(%struct.A* %[[arg3:[^,]*]], i32 3)
-// X64: invoke %struct.A* @"\01??0A@@QEAA@H@Z"(%struct.A* %[[arg2:[^,]*]], i32 2)
-// X64: invoke %struct.A* @"\01??0A@@QEAA@H@Z"(%struct.A* %[[arg1:[^,]*]], i32 1)
-// X64: call void @"\01?foo@@YAXUA@@00@Z"
+// X64-LABEL: define dso_local void @"?call_foo@@YAXXZ"()
+// X64: call %struct.A* @"??0A@@QEAA@H@Z"(%struct.A* %[[arg3:[^,]*]], i32 3)
+// X64: invoke %struct.A* @"??0A@@QEAA@H@Z"(%struct.A* %[[arg2:[^,]*]], i32 2)
+// X64: invoke %struct.A* @"??0A@@QEAA@H@Z"(%struct.A* %[[arg1:[^,]*]], i32 1)
+// X64: call void @"?foo@@YAXUA@@00@Z"
// X64: (%struct.A* %[[arg1]], %struct.A* %[[arg2]], %struct.A* %[[arg3]])
// X64: ret void
//
// lpad2:
// X64: cleanuppad within none []
-// X64: call void @"\01??1A@@QEAA@XZ"(%struct.A* %[[arg2]])
+// X64: call void @"??1A@@QEAA@XZ"(%struct.A* %[[arg2]])
// X64: cleanupret
//
// ehcleanup:
-// X64: call void @"\01??1A@@QEAA@XZ"(%struct.A* %[[arg3]])
+// X64: call void @"??1A@@QEAA@XZ"(%struct.A* %[[arg3]])
diff --git a/test/CodeGenCXX/microsoft-abi-array-cookies.cpp b/test/CodeGenCXX/microsoft-abi-array-cookies.cpp
index 146a6c8eda06..28140451529d 100644
--- a/test/CodeGenCXX/microsoft-abi-array-cookies.cpp
+++ b/test/CodeGenCXX/microsoft-abi-array-cookies.cpp
@@ -5,12 +5,12 @@ struct ClassWithoutDtor {
};
void check_array_no_cookies() {
-// CHECK: define void @"\01?check_array_no_cookies@@YAXXZ"() [[NUW:#[0-9]+]]
+// CHECK: define dso_local void @"?check_array_no_cookies@@YAXXZ"() [[NUW:#[0-9]+]]
-// CHECK: call i8* @"\01??_U@YAPAXI@Z"(i32 42)
+// CHECK: call i8* @"??_U@YAPAXI@Z"(i32 42)
ClassWithoutDtor *array = new ClassWithoutDtor[42];
-// CHECK: call void @"\01??_V@YAXPAX@Z"(
+// CHECK: call void @"??_V@YAXPAX@Z"(
delete [] array;
}
@@ -21,10 +21,10 @@ struct ClassWithDtor {
};
void check_array_cookies_simple() {
-// CHECK: define {{.*}} @"\01?check_array_cookies_simple@@YAXXZ"()
+// CHECK: define {{.*}} @"?check_array_cookies_simple@@YAXXZ"()
ClassWithDtor *array = new ClassWithDtor[42];
-// CHECK: [[ALLOCATED:%.*]] = call i8* @"\01??_U@YAPAXI@Z"(i32 46)
+// CHECK: [[ALLOCATED:%.*]] = call i8* @"??_U@YAPAXI@Z"(i32 46)
// 46 = 42 + size of cookie (4)
// CHECK: [[COOKIE:%.*]] = bitcast i8* [[ALLOCATED]] to i32*
// CHECK: store i32 42, i32* [[COOKIE]]
@@ -44,9 +44,9 @@ struct __attribute__((aligned(8))) ClassWithAlignment {
};
void check_array_cookies_aligned() {
-// CHECK: define {{.*}} @"\01?check_array_cookies_aligned@@YAXXZ"()
+// CHECK: define {{.*}} @"?check_array_cookies_aligned@@YAXXZ"()
ClassWithAlignment *array = new ClassWithAlignment[42];
-// CHECK: [[ALLOCATED:%.*]] = call i8* @"\01??_U@YAPAXI@Z"(i32 344)
+// CHECK: [[ALLOCATED:%.*]] = call i8* @"??_U@YAPAXI@Z"(i32 344)
// 344 = 42*8 + size of cookie (8, due to alignment)
// CHECK: [[COOKIE:%.*]] = bitcast i8* [[ALLOCATED]] to i32*
// CHECK: store i32 42, i32* [[COOKIE]]
@@ -62,8 +62,8 @@ namespace PR23990 {
struct S {
char x[42];
void operator delete[](void *p, __SIZE_TYPE__);
- // CHECK-LABEL: define void @"\01?delete_s@PR23990@@YAXPAUS@1@@Z"(
- // CHECK: call void @"\01??_VS@PR23990@@SAXPAXI@Z"(i8* {{.*}}, i32 42)
+ // CHECK-LABEL: define dso_local void @"?delete_s@PR23990@@YAXPAUS@1@@Z"(
+ // CHECK: call void @"??_VS@PR23990@@SAXPAXI@Z"(i8* {{.*}}, i32 42)
};
void delete_s(S *s) { delete[] s; }
}
diff --git a/test/CodeGenCXX/microsoft-abi-byval-sret.cpp b/test/CodeGenCXX/microsoft-abi-byval-sret.cpp
index 57ac79500aa8..cbedec69583f 100644
--- a/test/CodeGenCXX/microsoft-abi-byval-sret.cpp
+++ b/test/CodeGenCXX/microsoft-abi-byval-sret.cpp
@@ -18,7 +18,7 @@ A B::foo(A x) {
return x;
}
-// CHECK-LABEL: define x86_thiscallcc %struct.A* @"\01?foo@B@@QAE?AUA@@U2@@Z"
+// CHECK-LABEL: define dso_local x86_thiscallcc %struct.A* @"?foo@B@@QAE?AUA@@U2@@Z"
// CHECK: (%struct.B* %this, <{ %struct.A*, %struct.A }>* inalloca)
// CHECK: getelementptr inbounds <{ %struct.A*, %struct.A }>, <{ %struct.A*, %struct.A }>* %{{.*}}, i32 0, i32 0
// CHECK: load %struct.A*, %struct.A**
@@ -28,7 +28,7 @@ A B::bar(A x) {
return x;
}
-// CHECK-LABEL: define %struct.A* @"\01?bar@B@@QAA?AUA@@U2@@Z"
+// CHECK-LABEL: define dso_local %struct.A* @"?bar@B@@QAA?AUA@@U2@@Z"
// CHECK: (<{ %struct.B*, %struct.A*, %struct.A }>* inalloca)
// CHECK: getelementptr inbounds <{ %struct.B*, %struct.A*, %struct.A }>, <{ %struct.B*, %struct.A*, %struct.A }>* %{{.*}}, i32 0, i32 1
// CHECK: load %struct.A*, %struct.A**
@@ -38,7 +38,7 @@ A B::baz(A x) {
return x;
}
-// CHECK-LABEL: define x86_stdcallcc %struct.A* @"\01?baz@B@@QAG?AUA@@U2@@Z"
+// CHECK-LABEL: define dso_local x86_stdcallcc %struct.A* @"?baz@B@@QAG?AUA@@U2@@Z"
// CHECK: (<{ %struct.B*, %struct.A*, %struct.A }>* inalloca)
// CHECK: getelementptr inbounds <{ %struct.B*, %struct.A*, %struct.A }>, <{ %struct.B*, %struct.A*, %struct.A }>* %{{.*}}, i32 0, i32 1
// CHECK: load %struct.A*, %struct.A**
@@ -48,7 +48,7 @@ A B::qux(A x) {
return x;
}
-// CHECK-LABEL: define x86_fastcallcc void @"\01?qux@B@@QAI?AUA@@U2@@Z"
+// CHECK-LABEL: define dso_local x86_fastcallcc void @"?qux@B@@QAI?AUA@@U2@@Z"
// CHECK: (%struct.B* inreg %this, %struct.A* inreg noalias sret %agg.result, <{ %struct.A }>* inalloca)
// CHECK: ret void
@@ -60,11 +60,11 @@ int main() {
a = b.qux(a);
}
-// CHECK: call x86_thiscallcc %struct.A* @"\01?foo@B@@QAE?AUA@@U2@@Z"
+// CHECK: call x86_thiscallcc %struct.A* @"?foo@B@@QAE?AUA@@U2@@Z"
// CHECK: (%struct.B* %{{[^,]*}}, <{ %struct.A*, %struct.A }>* inalloca %{{[^,]*}})
-// CHECK: call %struct.A* @"\01?bar@B@@QAA?AUA@@U2@@Z"
+// CHECK: call %struct.A* @"?bar@B@@QAA?AUA@@U2@@Z"
// CHECK: (<{ %struct.B*, %struct.A*, %struct.A }>* inalloca %{{[^,]*}})
-// CHECK: call x86_stdcallcc %struct.A* @"\01?baz@B@@QAG?AUA@@U2@@Z"
+// CHECK: call x86_stdcallcc %struct.A* @"?baz@B@@QAG?AUA@@U2@@Z"
// CHECK: (<{ %struct.B*, %struct.A*, %struct.A }>* inalloca %{{[^,]*}})
-// CHECK: call x86_fastcallcc void @"\01?qux@B@@QAI?AUA@@U2@@Z"
+// CHECK: call x86_fastcallcc void @"?qux@B@@QAI?AUA@@U2@@Z"
// CHECK: (%struct.B* inreg %{{[^,]*}}, %struct.A* inreg sret %{{.*}}, <{ %struct.A }>* inalloca %{{[^,]*}})
diff --git a/test/CodeGenCXX/microsoft-abi-byval-thunks.cpp b/test/CodeGenCXX/microsoft-abi-byval-thunks.cpp
index 8ae85c0b66a3..45dd4d0ca74e 100644
--- a/test/CodeGenCXX/microsoft-abi-byval-thunks.cpp
+++ b/test/CodeGenCXX/microsoft-abi-byval-thunks.cpp
@@ -14,17 +14,17 @@ struct B { virtual void foo(Agg x); };
struct C : A, B { C(); virtual void foo(Agg x); };
C::C() {} // force emission
-// CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"\01?foo@C@byval_thunk@@W3AEXUAgg@2@@Z"
+// CHECK32-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"?foo@C@byval_thunk@@W3AEXUAgg@2@@Z"
// CHECK32: (%"struct.byval_thunk::C"* %this, <{ %"struct.byval_thunk::Agg" }>* inalloca)
// CHECK32: getelementptr i8, i8* %{{.*}}, i32 -4
-// CHECK32: musttail call x86_thiscallcc void @"\01?foo@C@byval_thunk@@UAEXUAgg@2@@Z"
+// CHECK32: musttail call x86_thiscallcc void @"?foo@C@byval_thunk@@UAEXUAgg@2@@Z"
// CHECK32: (%"struct.byval_thunk::C"* %{{.*}}, <{ %"struct.byval_thunk::Agg" }>* inalloca %0)
// CHECK32-NEXT: ret void
-// CHECK64-LABEL: define linkonce_odr void @"\01?foo@C@byval_thunk@@W7EAAXUAgg@2@@Z"
+// CHECK64-LABEL: define linkonce_odr dso_local void @"?foo@C@byval_thunk@@W7EAAXUAgg@2@@Z"
// CHECK64: (%"struct.byval_thunk::C"* %this, %"struct.byval_thunk::Agg"* %x)
// CHECK64: getelementptr i8, i8* %{{.*}}, i32 -8
-// CHECK64: call void @"\01?foo@C@byval_thunk@@UEAAXUAgg@2@@Z"
+// CHECK64: call void @"?foo@C@byval_thunk@@UEAAXUAgg@2@@Z"
// CHECK64: (%"struct.byval_thunk::C"* %{{.*}}, %"struct.byval_thunk::Agg"* %x)
// CHECK64-NOT: call
// CHECK64: ret void
@@ -43,20 +43,20 @@ struct B { virtual void __stdcall foo(Agg x); };
struct C : A, B { C(); virtual void __stdcall foo(Agg x); };
C::C() {} // force emission
-// CHECK32-LABEL: define linkonce_odr x86_stdcallcc void @"\01?foo@C@stdcall_thunk@@W3AGXUAgg@2@@Z"
+// CHECK32-LABEL: define linkonce_odr dso_local x86_stdcallcc void @"?foo@C@stdcall_thunk@@W3AGXUAgg@2@@Z"
// CHECK32: (<{ %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::Agg" }>* inalloca)
// CHECK32: %[[this_slot:[^ ]*]] = getelementptr inbounds <{ %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::Agg" }>, <{ %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::Agg" }>* %0, i32 0, i32 0
// CHECK32: load %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::C"** %[[this_slot]]
// CHECK32: getelementptr i8, i8* %{{.*}}, i32 -4
// CHECK32: store %"struct.stdcall_thunk::C"* %{{.*}}, %"struct.stdcall_thunk::C"** %[[this_slot]]
-// CHECK32: musttail call x86_stdcallcc void @"\01?foo@C@stdcall_thunk@@UAGXUAgg@2@@Z"
+// CHECK32: musttail call x86_stdcallcc void @"?foo@C@stdcall_thunk@@UAGXUAgg@2@@Z"
// CHECK32: (<{ %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::Agg" }>* inalloca %0)
// CHECK32-NEXT: ret void
-// CHECK64-LABEL: define linkonce_odr void @"\01?foo@C@stdcall_thunk@@W7EAAXUAgg@2@@Z"
+// CHECK64-LABEL: define linkonce_odr dso_local void @"?foo@C@stdcall_thunk@@W7EAAXUAgg@2@@Z"
// CHECK64: (%"struct.stdcall_thunk::C"* %this, %"struct.stdcall_thunk::Agg"* %x)
// CHECK64: getelementptr i8, i8* %{{.*}}, i32 -8
-// CHECK64: call void @"\01?foo@C@stdcall_thunk@@UEAAXUAgg@2@@Z"
+// CHECK64: call void @"?foo@C@stdcall_thunk@@UEAAXUAgg@2@@Z"
// CHECK64: (%"struct.stdcall_thunk::C"* %{{.*}}, %"struct.stdcall_thunk::Agg"* %x)
// CHECK64-NOT: call
// CHECK64: ret void
@@ -75,20 +75,20 @@ struct B { virtual Agg __cdecl foo(Agg x); };
struct C : A, B { C(); virtual Agg __cdecl foo(Agg x); };
C::C() {} // force emission
-// CHECK32-LABEL: define linkonce_odr %"struct.sret_thunk::Agg"* @"\01?foo@C@sret_thunk@@W3AA?AUAgg@2@U32@@Z"
+// CHECK32-LABEL: define linkonce_odr dso_local %"struct.sret_thunk::Agg"* @"?foo@C@sret_thunk@@W3AA?AUAgg@2@U32@@Z"
// CHECK32: (<{ %"struct.sret_thunk::C"*, %"struct.sret_thunk::Agg"*, %"struct.sret_thunk::Agg" }>* inalloca)
// CHECK32: %[[this_slot:[^ ]*]] = getelementptr inbounds <{ %"struct.sret_thunk::C"*, %"struct.sret_thunk::Agg"*, %"struct.sret_thunk::Agg" }>, <{ %"struct.sret_thunk::C"*, %"struct.sret_thunk::Agg"*, %"struct.sret_thunk::Agg" }>* %0, i32 0, i32 0
// CHECK32: load %"struct.sret_thunk::C"*, %"struct.sret_thunk::C"** %[[this_slot]]
// CHECK32: getelementptr i8, i8* %{{.*}}, i32 -4
// CHECK32: store %"struct.sret_thunk::C"* %{{.*}}, %"struct.sret_thunk::C"** %[[this_slot]]
-// CHECK32: %[[rv:[^ ]*]] = musttail call %"struct.sret_thunk::Agg"* @"\01?foo@C@sret_thunk@@UAA?AUAgg@2@U32@@Z"
+// CHECK32: %[[rv:[^ ]*]] = musttail call %"struct.sret_thunk::Agg"* @"?foo@C@sret_thunk@@UAA?AUAgg@2@U32@@Z"
// CHECK32: (<{ %"struct.sret_thunk::C"*, %"struct.sret_thunk::Agg"*, %"struct.sret_thunk::Agg" }>* inalloca %0)
// CHECK32-NEXT: ret %"struct.sret_thunk::Agg"* %[[rv]]
-// CHECK64-LABEL: define linkonce_odr void @"\01?foo@C@sret_thunk@@W7EAA?AUAgg@2@U32@@Z"
+// CHECK64-LABEL: define linkonce_odr dso_local void @"?foo@C@sret_thunk@@W7EAA?AUAgg@2@U32@@Z"
// CHECK64: (%"struct.sret_thunk::C"* %this, %"struct.sret_thunk::Agg"* noalias sret %agg.result, %"struct.sret_thunk::Agg"* %x)
// CHECK64: getelementptr i8, i8* %{{.*}}, i32 -8
-// CHECK64: call void @"\01?foo@C@sret_thunk@@UEAA?AUAgg@2@U32@@Z"
+// CHECK64: call void @"?foo@C@sret_thunk@@UEAA?AUAgg@2@U32@@Z"
// CHECK64: (%"struct.sret_thunk::C"* %{{.*}}, %"struct.sret_thunk::Agg"* sret %agg.result, %"struct.sret_thunk::Agg"* %x)
// CHECK64-NOT: call
// CHECK64: ret void
diff --git a/test/CodeGenCXX/microsoft-abi-byval-vararg.cpp b/test/CodeGenCXX/microsoft-abi-byval-vararg.cpp
index 6a0a8601c0cc..e6a36e243b67 100644
--- a/test/CodeGenCXX/microsoft-abi-byval-vararg.cpp
+++ b/test/CodeGenCXX/microsoft-abi-byval-vararg.cpp
@@ -19,14 +19,14 @@ int foo(A a, ...) {
return sum;
}
-// CHECK-LABEL: define i32 @"\01?foo@@YAHUA@@ZZ"(<{ %struct.A }>* inalloca, ...)
+// CHECK-LABEL: define dso_local i32 @"?foo@@YAHUA@@ZZ"(<{ %struct.A }>* inalloca, ...)
int main() {
return foo(A(3), 1, 2, 3);
}
-// CHECK-LABEL: define i32 @main()
+// CHECK-LABEL: define dso_local i32 @main()
// CHECK: %[[argmem:[^ ]*]] = alloca inalloca <{ %struct.A, i32, i32, i32 }>
-// CHECK: call i32 {{.*bitcast.*}}@"\01?foo@@YAHUA@@ZZ"{{.*}}(<{ %struct.A, i32, i32, i32 }>* inalloca %[[argmem]])
+// CHECK: call i32 {{.*bitcast.*}}@"?foo@@YAHUA@@ZZ"{{.*}}(<{ %struct.A, i32, i32, i32 }>* inalloca %[[argmem]])
void varargs_zero(...);
void varargs_one(int, ...);
@@ -40,13 +40,13 @@ void call_var_args() {
varargs_three(1, 2, 3, x);
}
-// CHECK-LABEL: define void @"\01?call_var_args@@YAXXZ"()
+// CHECK-LABEL: define dso_local void @"?call_var_args@@YAXXZ"()
// CHECK: call void {{.*bitcast.*varargs_zero.*}}(<{ %struct.A }>* inalloca %{{.*}})
// CHECK: call void {{.*bitcast.*varargs_one.*}}(<{ i32, %struct.A }>* inalloca %{{.*}})
// CHECK: call void {{.*bitcast.*varargs_two.*}}(<{ i32, i32, %struct.A }>* inalloca %{{.*}})
// CHECK: call void {{.*bitcast.*varargs_three.*}}(<{ i32, i32, i32, %struct.A }>* inalloca %{{.*}})
-// CHECK-LABEL: declare void @"\01?varargs_zero@@YAXZZ"(...)
-// CHECK-LABEL: declare void @"\01?varargs_one@@YAXHZZ"(i32, ...)
-// CHECK-LABEL: declare void @"\01?varargs_two@@YAXHHZZ"(i32, i32, ...)
-// CHECK-LABEL: declare void @"\01?varargs_three@@YAXHHHZZ"(i32, i32, i32, ...)
+// CHECK-LABEL: declare dso_local void @"?varargs_zero@@YAXZZ"(...)
+// CHECK-LABEL: declare dso_local void @"?varargs_one@@YAXHZZ"(i32, ...)
+// CHECK-LABEL: declare dso_local void @"?varargs_two@@YAXHHZZ"(i32, i32, ...)
+// CHECK-LABEL: declare dso_local void @"?varargs_three@@YAXHHHZZ"(i32, i32, i32, ...)
diff --git a/test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp b/test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp
index 6da7a50b617e..34e2bc570635 100644
--- a/test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp
+++ b/test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp
@@ -19,9 +19,9 @@ S C::variadic_sret(const char *f, ...) { return S(); }
S C::cdecl_sret() { return S(); }
S C::byval_and_sret(S a) { return S(); }
-// CHECK: define void @"\01?variadic_sret@C@@QAA?AUS@@PBDZZ"(%struct.C* %this, %struct.S* noalias sret %agg.result, i8* %f, ...)
-// CHECK: define void @"\01?cdecl_sret@C@@QAA?AUS@@XZ"(%struct.C* %this, %struct.S* noalias sret %agg.result)
-// CHECK: define void @"\01?byval_and_sret@C@@QAA?AUS@@U2@@Z"(%struct.C* %this, %struct.S* noalias sret %agg.result, %struct.S* byval align 4 %a)
+// CHECK: define dso_local void @"?variadic_sret@C@@QAA?AUS@@PBDZZ"(%struct.C* %this, %struct.S* noalias sret %agg.result, i8* %f, ...)
+// CHECK: define dso_local void @"?cdecl_sret@C@@QAA?AUS@@XZ"(%struct.C* %this, %struct.S* noalias sret %agg.result)
+// CHECK: define dso_local void @"?byval_and_sret@C@@QAA?AUS@@U2@@Z"(%struct.C* %this, %struct.S* noalias sret %agg.result, %struct.S* byval align 4 %a)
int main() {
C c;
@@ -29,10 +29,10 @@ int main() {
c.cdecl_sret();
c.byval_and_sret(S());
}
-// CHECK-LABEL: define i32 @main()
-// CHECK: call void {{.*}} @"\01?variadic_sret@C@@QAA?AUS@@PBDZZ"
-// CHECK: call void @"\01?cdecl_sret@C@@QAA?AUS@@XZ"
-// CHECK: call void @"\01?byval_and_sret@C@@QAA?AUS@@U2@@Z"
+// CHECK-LABEL: define dso_local i32 @main()
+// CHECK: call void {{.*}} @"?variadic_sret@C@@QAA?AUS@@PBDZZ"
+// CHECK: call void @"?cdecl_sret@C@@QAA?AUS@@XZ"
+// CHECK: call void @"?byval_and_sret@C@@QAA?AUS@@U2@@Z"
// __fastcall has similar issues.
struct A {
@@ -41,4 +41,4 @@ struct A {
S A::f(int x) {
return S();
}
-// CHECK-LABEL: define x86_fastcallcc void @"\01?f@A@@QAI?AUS@@H@Z"(%struct.A* inreg %this, %struct.S* inreg noalias sret %agg.result, i32 %x)
+// CHECK-LABEL: define dso_local x86_fastcallcc void @"?f@A@@QAI?AUS@@H@Z"(%struct.A* inreg %this, %struct.S* inreg noalias sret %agg.result, i32 %x)
diff --git a/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp
index 6972dacd774f..6f426038252b 100644
--- a/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp
+++ b/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp
@@ -7,7 +7,7 @@ struct A {
};
A a(42);
-// CHECK: @"\01?a@@3UA@@A" = global { { [1 x i8*] }*, i32 } { { [1 x i8*] }* @"\01??_7A@@6B@", i32 42 }, align 4
+// CHECK: @"?a@@3UA@@A" = dso_local global { { [1 x i8*] }*, i32 } { { [1 x i8*] }* @"??_7A@@6B@", i32 42 }, align 4
struct B {
constexpr B(int y) : y(y) {}
@@ -20,4 +20,4 @@ struct C : A, B {
};
C c;
-// CHECK: @"\01?c@@3UC@@A" = global { { [1 x i8*] }*, i32, { [1 x i8*] }*, i32 } { { [1 x i8*] }* @"\01??_7C@@6BA@@@", i32 777, { [1 x i8*] }* @"\01??_7C@@6BB@@@", i32 13 }
+// CHECK: @"?c@@3UC@@A" = dso_local global { { [1 x i8*] }*, i32, { [1 x i8*] }*, i32 } { { [1 x i8*] }* @"??_7C@@6BA@@@", i32 777, { [1 x i8*] }* @"??_7C@@6BB@@@", i32 13 }
diff --git a/test/CodeGenCXX/microsoft-abi-default-cc.cpp b/test/CodeGenCXX/microsoft-abi-default-cc.cpp
index 6259a53dbf39..804ee5197b85 100644
--- a/test/CodeGenCXX/microsoft-abi-default-cc.cpp
+++ b/test/CodeGenCXX/microsoft-abi-default-cc.cpp
@@ -13,13 +13,13 @@ void foo();
void __cdecl foo();
void __cdecl foo() {}
// GCABI-LABEL: define void @_Z3foov()
-// MSABI: define void @"\01?foo@@YAXXZ"
+// MSABI: define dso_local void @"?foo@@YAXXZ"
void __cdecl bar();
void bar();
void bar() {}
// GCABI-LABEL: define void @_Z3barv()
-// MSABI: define void @"\01?bar@@YAXXZ"
+// MSABI: define dso_local void @"?bar@@YAXXZ"
// Test that it's OK to mark either the method declaration or method definition
// with a default CC explicitly.
@@ -34,23 +34,23 @@ public:
void METHOD_CC A::baz() {}
// GCABI-LABEL: define void @_ZN1A3bazEv
-// MSABI: define x86_thiscallcc void @"\01?baz@A@@QAEXXZ"
+// MSABI: define dso_local x86_thiscallcc void @"?baz@A@@QAEXXZ"
void A::qux() {}
// GCABI-LABEL: define void @_ZN1A3quxEv
-// MSABI: define x86_thiscallcc void @"\01?qux@A@@QAEXXZ"
+// MSABI: define dso_local x86_thiscallcc void @"?qux@A@@QAEXXZ"
void __cdecl static_baz() {}
// GCABI-LABEL: define void @_Z10static_bazv
-// MSABI: define void @"\01?static_baz@@YAXXZ"
+// MSABI: define dso_local void @"?static_baz@@YAXXZ"
void static_qux() {}
// GCABI-LABEL: define void @_Z10static_quxv
-// MSABI: define void @"\01?static_qux@@YAXXZ"
+// MSABI: define dso_local void @"?static_qux@@YAXXZ"
namespace PR31656 {
template <int I>
void __cdecl callee(int args[I]);
// GCABI-LABEL: declare void @_ZN7PR316566calleeILi1EEEvPi(
-// MSABI: declare void @"\01??$callee@$00@PR31656@@YAXQAH@Z"(
+// MSABI: declare dso_local void @"??$callee@$00@PR31656@@YAXQAH@Z"(
void caller() { callee<1>(0); }
}
diff --git a/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp b/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp
index 8d75ed4d9d69..e45d37273cea 100644
--- a/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp
+++ b/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp
@@ -7,30 +7,30 @@ struct B : S, virtual V {};
struct T {};
T* test0() { return dynamic_cast<T*>((B*)0); }
-// CHECK-LABEL: define noalias %struct.T* @"\01?test0@@YAPAUT@@XZ"()
+// CHECK-LABEL: define dso_local noalias %struct.T* @"?test0@@YAPAUT@@XZ"()
// CHECK: ret %struct.T* null
T* test1(V* x) { return &dynamic_cast<T&>(*x); }
-// CHECK-LABEL: define %struct.T* @"\01?test1@@YAPAUT@@PAUV@@@Z"(%struct.V* %x)
+// CHECK-LABEL: define dso_local %struct.T* @"?test1@@YAPAUT@@PAUV@@@Z"(%struct.V* %x)
// CHECK: [[CAST:%.*]] = bitcast %struct.V* %x to i8*
-// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[CAST]], i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUV@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 1)
+// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[CAST]], i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUV@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUT@@@8" to i8*), i32 1)
// CHECK-NEXT: [[RET:%.*]] = bitcast i8* [[CALL]] to %struct.T*
// CHECK-NEXT: ret %struct.T* [[RET]]
T* test2(A* x) { return &dynamic_cast<T&>(*x); }
-// CHECK-LABEL: define %struct.T* @"\01?test2@@YAPAUT@@PAUA@@@Z"(%struct.A* %x)
+// CHECK-LABEL: define dso_local %struct.T* @"?test2@@YAPAUT@@PAUA@@@Z"(%struct.A* %x)
// CHECK: [[CAST:%.*]] = bitcast %struct.A* %x to i8*
// CHECK-NEXT: [[VBPTRPTR:%.*]] = getelementptr inbounds %struct.A, %struct.A* %x, i32 0, i32 0
// CHECK-NEXT: [[VBTBL:%.*]] = load i32*, i32** [[VBPTRPTR]], align 4
// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i32, i32* [[VBTBL]], i32 1
// CHECK-NEXT: [[VBOFFS:%.*]] = load i32, i32* [[VBOFFP]], align 4
// CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8, i8* [[CAST]], i32 [[VBOFFS]]
-// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[VBOFFS]], i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 1)
+// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[VBOFFS]], i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUA@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUT@@@8" to i8*), i32 1)
// CHECK-NEXT: [[RET:%.*]] = bitcast i8* [[CALL]] to %struct.T*
// CHECK-NEXT: ret %struct.T* [[RET]]
T* test3(B* x) { return &dynamic_cast<T&>(*x); }
-// CHECK-LABEL: define %struct.T* @"\01?test3@@YAPAUT@@PAUB@@@Z"(%struct.B* %x)
+// CHECK-LABEL: define dso_local %struct.T* @"?test3@@YAPAUT@@PAUB@@@Z"(%struct.B* %x)
// CHECK: [[VOIDP:%.*]] = getelementptr inbounds %struct.B, %struct.B* %x, i32 0, i32 0, i32 0
// CHECK-NEXT: [[VBPTR:%.*]] = getelementptr inbounds i8, i8* [[VOIDP]], i32 4
// CHECK-NEXT: [[VBPTRPTR:%.*]] = bitcast i8* [[VBPTR:%.*]] to i32**
@@ -39,19 +39,19 @@ T* test3(B* x) { return &dynamic_cast<T&>(*x); }
// CHECK-NEXT: [[VBOFFS:%.*]] = load i32, i32* [[VBOFFP]], align 4
// CHECK-NEXT: [[DELTA:%.*]] = add nsw i32 [[VBOFFS]], 4
// CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8, i8* [[VOIDP]], i32 [[DELTA]]
-// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[DELTA]], i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 1)
+// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[DELTA]], i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUB@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUT@@@8" to i8*), i32 1)
// CHECK-NEXT: [[RET:%.*]] = bitcast i8* [[CALL]] to %struct.T*
// CHECK-NEXT: ret %struct.T* [[RET]]
T* test4(V* x) { return dynamic_cast<T*>(x); }
-// CHECK-LABEL: define %struct.T* @"\01?test4@@YAPAUT@@PAUV@@@Z"(%struct.V* %x)
+// CHECK-LABEL: define dso_local %struct.T* @"?test4@@YAPAUT@@PAUV@@@Z"(%struct.V* %x)
// CHECK: [[CAST:%.*]] = bitcast %struct.V* %x to i8*
-// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[CAST]], i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUV@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 0)
+// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[CAST]], i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUV@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUT@@@8" to i8*), i32 0)
// CHECK-NEXT: [[RET:%.*]] = bitcast i8* [[CALL]] to %struct.T*
// CHECK-NEXT: ret %struct.T* [[RET]]
T* test5(A* x) { return dynamic_cast<T*>(x); }
-// CHECK-LABEL: define %struct.T* @"\01?test5@@YAPAUT@@PAUA@@@Z"(%struct.A* %x)
+// CHECK-LABEL: define dso_local %struct.T* @"?test5@@YAPAUT@@PAUA@@@Z"(%struct.A* %x)
// CHECK: [[CHECK:%.*]] = icmp eq %struct.A* %x, null
// CHECK-NEXT: br i1 [[CHECK]]
// CHECK: [[VOIDP:%.*]] = bitcast %struct.A* %x to i8*
@@ -60,14 +60,14 @@ T* test5(A* x) { return dynamic_cast<T*>(x); }
// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i32, i32* [[VBTBL]], i32 1
// CHECK-NEXT: [[VBOFFS:%.*]] = load i32, i32* [[VBOFFP]], align 4
// CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8, i8* [[VOIDP]], i32 [[VBOFFS]]
-// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[VBOFFS]], i8* {{.*}}bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8" to i8*), i8* {{.*}}bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 0)
+// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[VBOFFS]], i8* {{.*}}bitcast (%rtti.TypeDescriptor7* @"??_R0?AUA@@@8" to i8*), i8* {{.*}}bitcast (%rtti.TypeDescriptor7* @"??_R0?AUT@@@8" to i8*), i32 0)
// CHECK-NEXT: [[RES:%.*]] = bitcast i8* [[CALL]] to %struct.T*
// CHECK-NEXT: br label
// CHECK: [[RET:%.*]] = phi %struct.T*
// CHECK-NEXT: ret %struct.T* [[RET]]
T* test6(B* x) { return dynamic_cast<T*>(x); }
-// CHECK-LABEL: define %struct.T* @"\01?test6@@YAPAUT@@PAUB@@@Z"(%struct.B* %x)
+// CHECK-LABEL: define dso_local %struct.T* @"?test6@@YAPAUT@@PAUB@@@Z"(%struct.B* %x)
// CHECK: [[CHECK:%.*]] = icmp eq %struct.B* %x, null
// CHECK-NEXT: br i1 [[CHECK]]
// CHECK: [[CAST:%.*]] = getelementptr inbounds %struct.B, %struct.B* %x, i32 0, i32 0, i32 0
@@ -78,20 +78,20 @@ T* test6(B* x) { return dynamic_cast<T*>(x); }
// CHECK-NEXT: [[VBOFFS:%.*]] = load i32, i32* [[VBOFFP]], align 4
// CHECK-NEXT: [[DELTA:%.*]] = add nsw i32 [[VBOFFS]], 4
// CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8, i8* [[CAST]], i32 [[DELTA]]
-// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* nonnull [[ADJ]], i32 [[DELTA]], i8* {{.*}}bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8" to i8*), i8* {{.*}}bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 0)
+// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* nonnull [[ADJ]], i32 [[DELTA]], i8* {{.*}}bitcast (%rtti.TypeDescriptor7* @"??_R0?AUB@@@8" to i8*), i8* {{.*}}bitcast (%rtti.TypeDescriptor7* @"??_R0?AUT@@@8" to i8*), i32 0)
// CHECK-NEXT: [[RES:%.*]] = bitcast i8* [[CALL]] to %struct.T*
// CHECK-NEXT: br label
// CHECK: [[RET:%.*]] = phi %struct.T*
// CHECK-NEXT: ret %struct.T* [[RET]]
void* test7(V* x) { return dynamic_cast<void*>(x); }
-// CHECK-LABEL: define i8* @"\01?test7@@YAPAXPAUV@@@Z"(%struct.V* %x)
+// CHECK-LABEL: define dso_local i8* @"?test7@@YAPAXPAUV@@@Z"(%struct.V* %x)
// CHECK: [[CAST:%.*]] = bitcast %struct.V* %x to i8*
// CHECK-NEXT: [[RET:%.*]] = tail call i8* @__RTCastToVoid(i8* [[CAST]])
// CHECK-NEXT: ret i8* [[RET]]
void* test8(A* x) { return dynamic_cast<void*>(x); }
-// CHECK-LABEL: define i8* @"\01?test8@@YAPAXPAUA@@@Z"(%struct.A* %x)
+// CHECK-LABEL: define dso_local i8* @"?test8@@YAPAXPAUA@@@Z"(%struct.A* %x)
// CHECK: [[CHECK:%.*]] = icmp eq %struct.A* %x, null
// CHECK-NEXT: br i1 [[CHECK]]
// CHECK: [[VOIDP:%.*]] = bitcast %struct.A* %x to i8*
@@ -106,7 +106,7 @@ void* test8(A* x) { return dynamic_cast<void*>(x); }
// CHECK-NEXT: ret i8* [[RET]]
void* test9(B* x) { return dynamic_cast<void*>(x); }
-// CHECK-LABEL: define i8* @"\01?test9@@YAPAXPAUB@@@Z"(%struct.B* %x)
+// CHECK-LABEL: define dso_local i8* @"?test9@@YAPAXPAUB@@@Z"(%struct.B* %x)
// CHECK: [[CHECK:%.*]] = icmp eq %struct.B* %x, null
// CHECK-NEXT: br i1 [[CHECK]]
// CHECK: [[CAST:%.*]] = getelementptr inbounds %struct.B, %struct.B* %x, i32 0, i32 0, i32 0
@@ -134,10 +134,10 @@ S3 *f(S2 &s) {
Cleanup c;
return dynamic_cast<S3 *>(&s);
}
-// CHECK-LABEL: define %"struct.PR25606::S3"* @"\01?f@PR25606@@YAPAUS3@1@AAUS2@1@@Z"(
+// CHECK-LABEL: define dso_local %"struct.PR25606::S3"* @"?f@PR25606@@YAPAUS3@1@AAUS2@1@@Z"(
// CHECK: [[CALL:%.*]] = invoke i8* @__RTDynamicCast
// CHECK: [[BC:%.*]] = bitcast i8* [[CALL]] to %"struct.PR25606::S3"*
-// CHECK: call x86_thiscallcc void @"\01??_DCleanup@PR25606@@QAEXXZ"(
+// CHECK: call x86_thiscallcc void @"??1Cleanup@PR25606@@QAE@XZ"(
// CHECK: ret %"struct.PR25606::S3"* [[BC]]
}
diff --git a/test/CodeGenCXX/microsoft-abi-eh-catch.cpp b/test/CodeGenCXX/microsoft-abi-eh-catch.cpp
index 6e18b92e0f41..53f87177e700 100644
--- a/test/CodeGenCXX/microsoft-abi-eh-catch.cpp
+++ b/test/CodeGenCXX/microsoft-abi-eh-catch.cpp
@@ -17,7 +17,7 @@ extern "C" void catch_all() {
}
}
-// WIN64-LABEL: define void @catch_all()
+// WIN64-LABEL: define dso_local void @catch_all()
// WIN64: invoke void @might_throw()
// WIN64-NEXT: to label %[[cont:[^ ]*]] unwind label %[[catchswitch_lpad:[^ ]*]]
//
@@ -46,8 +46,8 @@ extern "C" void catch_int() {
}
}
-// WIN64-LABEL: define void @catch_int()
-// WIN64: catchpad within %{{[^ ]*}} [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i32* %[[e_addr:[^\]]*]]]
+// WIN64-LABEL: define dso_local void @catch_int()
+// WIN64: catchpad within %{{[^ ]*}} [%rtti.TypeDescriptor2* @"??_R0H@8", i32 0, i32* %[[e_addr:[^\]]*]]]
//
// The catchpad instruction starts the lifetime of 'e'. Unfortunately, that
// leaves us with nowhere to put lifetime.start, so we don't emit lifetime
@@ -68,8 +68,8 @@ extern "C" void catch_int_unnamed() {
}
}
-// WIN64-LABEL: define void @catch_int_unnamed()
-// WIN64: catchpad within %{{.*}} [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
+// WIN64-LABEL: define dso_local void @catch_int_unnamed()
+// WIN64: catchpad within %{{.*}} [%rtti.TypeDescriptor2* @"??_R0H@8", i32 0, i8* null]
// WIN64: catchret
struct A {
@@ -94,9 +94,9 @@ extern "C" void catch_a_byval() {
}
}
-// WIN64-LABEL: define void @catch_a_byval()
+// WIN64-LABEL: define dso_local void @catch_a_byval()
// WIN64: %[[e_addr:[^ ]*]] = alloca %struct.A
-// WIN64: catchpad within %{{[^ ]*}} [%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8", i32 0, %struct.A* %[[e_addr]]]
+// WIN64: catchpad within %{{[^ ]*}} [%rtti.TypeDescriptor7* @"??_R0?AUA@@@8", i32 0, %struct.A* %[[e_addr]]]
// WIN64: %[[e_i8:[^ ]*]] = bitcast %struct.A* %[[e_addr]] to i8*
// WIN64: call void @handle_exception(i8* %[[e_i8]])
// WIN64: catchret
@@ -109,9 +109,9 @@ extern "C" void catch_a_ref() {
}
}
-// WIN64-LABEL: define void @catch_a_ref()
+// WIN64-LABEL: define dso_local void @catch_a_ref()
// WIN64: %[[e_addr:[^ ]*]] = alloca %struct.A*
-// WIN64: catchpad within %{{[^ ]*}} [%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8", i32 8, %struct.A** %[[e_addr]]]
+// WIN64: catchpad within %{{[^ ]*}} [%rtti.TypeDescriptor7* @"??_R0?AUA@@@8", i32 8, %struct.A** %[[e_addr]]]
// WIN64: %[[eptr:[^ ]*]] = load %struct.A*, %struct.A** %[[e_addr]]
// WIN64: %[[eptr_i8:[^ ]*]] = bitcast %struct.A* %[[eptr]] to i8*
// WIN64: call void @handle_exception(i8* %[[eptr_i8]])
@@ -121,7 +121,7 @@ extern "C" void fn_with_exc_spec() throw(int) {
might_throw();
}
-// WIN64-LABEL: define void @fn_with_exc_spec()
+// WIN64-LABEL: define dso_local void @fn_with_exc_spec()
// WIN64: call void @might_throw()
// WIN64-NEXT: ret void
@@ -137,7 +137,7 @@ extern "C" void catch_nested() {
}
}
-// WIN64-LABEL: define void @catch_nested()
+// WIN64-LABEL: define dso_local void @catch_nested()
// WIN64: invoke void @might_throw()
// WIN64-NEXT: to label %{{.*}} unwind label %[[catchswitch_outer:[^ ]*]]
//
@@ -145,7 +145,7 @@ extern "C" void catch_nested() {
// WIN64: %[[catchswitch_outer_scope:[^ ]*]] = catchswitch within none [label %[[catch_int_outer:[^ ]*]]] unwind to caller
//
// WIN64: [[catch_int_outer]]
-// WIN64: %[[catchpad:[^ ]*]] = catchpad within %[[catchswitch_outer_scope]] [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
+// WIN64: %[[catchpad:[^ ]*]] = catchpad within %[[catchswitch_outer_scope]] [%rtti.TypeDescriptor2* @"??_R0H@8", i32 0, i8* null]
// WIN64: invoke void @might_throw()
// WIN64-NEXT: to label %[[cont2:[^ ]*]] unwind label %[[catchswitch_inner:[^ ]*]]
//
@@ -153,7 +153,7 @@ extern "C" void catch_nested() {
// WIN64: %[[catchswitch_inner_scope:[^ ]*]] = catchswitch within %[[catchpad]] [label %[[catch_int_inner:[^ ]*]]] unwind to caller
//
// WIN64: [[catch_int_inner]]
-// WIN64: catchpad within %[[catchswitch_inner_scope]] [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
+// WIN64: catchpad within %[[catchswitch_inner_scope]] [%rtti.TypeDescriptor2* @"??_R0H@8", i32 0, i8* null]
// WIN64-NEXT: call void @might_throw()
// WIN64: catchret {{.*}} to label %[[catchret2:[^ ]*]]
//
diff --git a/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp b/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp
index 96b4fa3478a2..6682fafc91f9 100644
--- a/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp
+++ b/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp
@@ -15,21 +15,21 @@ void HasEHCleanup() {
}
// With exceptions, we need to clean up at least one of these temporaries.
-// WIN32-LABEL: define void @"\01?HasEHCleanup@@YAXXZ"() {{.*}} {
+// WIN32-LABEL: define dso_local void @"?HasEHCleanup@@YAXXZ"() {{.*}} {
// WIN32: %[[base:.*]] = call i8* @llvm.stacksave()
// If this call throws, we have to restore the stack.
-// WIN32: call void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}})
+// WIN32: call void @"?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}})
// If this call throws, we have to cleanup the first temporary.
-// WIN32: invoke void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}})
+// WIN32: invoke void @"?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}})
// If this call throws, we have to cleanup the stacksave.
-// WIN32: call i32 @"\01?TakesTwo@@YAHUA@@0@Z"
+// WIN32: call i32 @"?TakesTwo@@YAHUA@@0@Z"
// WIN32: call void @llvm.stackrestore
// WIN32: ret void
//
// There should be one dtor call for unwinding from the second getA.
// WIN32: cleanuppad
-// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
-// WIN32-NOT: @"\01??1A@@QAE@XZ"
+// WIN32: call x86_thiscallcc void @"??1A@@QAE@XZ"({{.*}})
+// WIN32-NOT: @"??1A@@QAE@XZ"
// WIN32: }
void TakeRef(const A &a);
@@ -37,33 +37,33 @@ int HasDeactivatedCleanups() {
return TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A()));
}
-// WIN32-LABEL: define i32 @"\01?HasDeactivatedCleanups@@YAHXZ"() {{.*}} {
+// WIN32-LABEL: define dso_local i32 @"?HasDeactivatedCleanups@@YAHXZ"() {{.*}} {
// WIN32: %[[isactive:.*]] = alloca i1
// WIN32: call i8* @llvm.stacksave()
// WIN32: %[[argmem:.*]] = alloca inalloca [[argmem_ty:<{ %struct.A, %struct.A }>]]
// WIN32: %[[arg1:.*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 1
-// WIN32: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
-// WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z"
+// WIN32: call x86_thiscallcc %struct.A* @"??0A@@QAE@XZ"
+// WIN32: invoke void @"?TakeRef@@YAXABUA@@@Z"
//
-// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1]])
+// WIN32: invoke x86_thiscallcc %struct.A* @"??0A@@QAE@XZ"(%struct.A* %[[arg1]])
// WIN32: store i1 true, i1* %[[isactive]]
//
// WIN32: %[[arg0:.*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 0
-// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
-// WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z"
-// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
+// WIN32: invoke x86_thiscallcc %struct.A* @"??0A@@QAE@XZ"
+// WIN32: invoke void @"?TakeRef@@YAXABUA@@@Z"
+// WIN32: invoke x86_thiscallcc %struct.A* @"??0A@@QAE@XZ"
// WIN32: store i1 false, i1* %[[isactive]]
//
-// WIN32: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"([[argmem_ty]]* inalloca %[[argmem]])
+// WIN32: invoke i32 @"?TakesTwo@@YAHUA@@0@Z"([[argmem_ty]]* inalloca %[[argmem]])
// Destroy the two const ref temporaries.
-// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
-// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
+// WIN32: call x86_thiscallcc void @"??1A@@QAE@XZ"({{.*}})
+// WIN32: call x86_thiscallcc void @"??1A@@QAE@XZ"({{.*}})
// WIN32: ret i32
//
// Conditionally destroy arg1.
// WIN32: %[[cond:.*]] = load i1, i1* %[[isactive]]
// WIN32: br i1 %[[cond]]
-// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]])
+// WIN32: call x86_thiscallcc void @"??1A@@QAE@XZ"(%struct.A* %[[arg1]])
// WIN32: }
// Test putting the cleanups inside a conditional.
@@ -72,22 +72,22 @@ int HasConditionalCleanup(bool cond) {
return (cond ? TakesTwo(A(), A()) : CouldThrow());
}
-// WIN32-LABEL: define i32 @"\01?HasConditionalCleanup@@YAH_N@Z"(i1 zeroext %{{.*}}) {{.*}} {
+// WIN32-LABEL: define dso_local i32 @"?HasConditionalCleanup@@YAH_N@Z"(i1 zeroext %{{.*}}) {{.*}} {
// WIN32: store i1 false
// WIN32: br i1
// WIN32: call i8* @llvm.stacksave()
-// WIN32: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %{{.*}})
+// WIN32: call x86_thiscallcc %struct.A* @"??0A@@QAE@XZ"(%struct.A* %{{.*}})
// WIN32: store i1 true
-// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %{{.*}})
-// WIN32: call i32 @"\01?TakesTwo@@YAHUA@@0@Z"
+// WIN32: invoke x86_thiscallcc %struct.A* @"??0A@@QAE@XZ"(%struct.A* %{{.*}})
+// WIN32: call i32 @"?TakesTwo@@YAHUA@@0@Z"
//
// WIN32: call void @llvm.stackrestore
//
-// WIN32: call i32 @"\01?CouldThrow@@YAHXZ"()
+// WIN32: call i32 @"?CouldThrow@@YAHXZ"()
//
// Only one dtor in the invoke for arg1
-// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
-// WIN32-NOT: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
+// WIN32: call x86_thiscallcc void @"??1A@@QAE@XZ"({{.*}})
+// WIN32-NOT: invoke x86_thiscallcc void @"??1A@@QAE@XZ"
// WIN32: }
// Now test both.
@@ -95,7 +95,7 @@ int HasConditionalDeactivatedCleanups(bool cond) {
return (cond ? TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A())) : CouldThrow());
}
-// WIN32-O0-LABEL: define i32 @"\01?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} {
+// WIN32-O0-LABEL: define dso_local i32 @"?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} {
// WIN32-O0: alloca i1
// WIN32-O0: %[[arg1_cond:.*]] = alloca i1
// Start all four cleanups as deactivated.
@@ -105,32 +105,32 @@ int HasConditionalDeactivatedCleanups(bool cond) {
// WIN32-O0: store i1 false
// WIN32-O0: br i1
// True condition.
-// WIN32-O0: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
+// WIN32-O0: call x86_thiscallcc %struct.A* @"??0A@@QAE@XZ"
// WIN32-O0: store i1 true
-// WIN32-O0: invoke void @"\01?TakeRef@@YAXABUA@@@Z"
-// WIN32-O0: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
+// WIN32-O0: invoke void @"?TakeRef@@YAXABUA@@@Z"
+// WIN32-O0: invoke x86_thiscallcc %struct.A* @"??0A@@QAE@XZ"
// WIN32-O0: store i1 true, i1* %[[arg1_cond]]
-// WIN32-O0: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
+// WIN32-O0: invoke x86_thiscallcc %struct.A* @"??0A@@QAE@XZ"
// WIN32-O0: store i1 true
-// WIN32-O0: invoke void @"\01?TakeRef@@YAXABUA@@@Z"
-// WIN32-O0: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
+// WIN32-O0: invoke void @"?TakeRef@@YAXABUA@@@Z"
+// WIN32-O0: invoke x86_thiscallcc %struct.A* @"??0A@@QAE@XZ"
// WIN32-O0: store i1 true
// WIN32-O0: store i1 false, i1* %[[arg1_cond]]
-// WIN32-O0: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"
+// WIN32-O0: invoke i32 @"?TakesTwo@@YAHUA@@0@Z"
// False condition.
-// WIN32-O0: invoke i32 @"\01?CouldThrow@@YAHXZ"()
+// WIN32-O0: invoke i32 @"?CouldThrow@@YAHXZ"()
// Two normal cleanups for TakeRef args.
-// WIN32-O0: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
-// WIN32-O0-NOT: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
+// WIN32-O0: call x86_thiscallcc void @"??1A@@QAE@XZ"({{.*}})
+// WIN32-O0-NOT: invoke x86_thiscallcc void @"??1A@@QAE@XZ"
// WIN32-O0: ret i32
//
// Somewhere in the landing pad soup, we conditionally destroy arg1.
// WIN32-O0: %[[isactive:.*]] = load i1, i1* %[[arg1_cond]]
// WIN32-O0: br i1 %[[isactive]]
-// WIN32-O0: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
+// WIN32-O0: call x86_thiscallcc void @"??1A@@QAE@XZ"({{.*}})
// WIN32-O0: }
-// WIN32-O3-LABEL: define i32 @"\01?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} {
+// WIN32-O3-LABEL: define dso_local i32 @"?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} {
// WIN32-O3: alloca i1
// WIN32-O3: alloca i1
// WIN32-O3: %[[arg1_cond:.*]] = alloca i1
@@ -143,29 +143,29 @@ int HasConditionalDeactivatedCleanups(bool cond) {
// WIN32-O3: store i1 false
// WIN32-O3: br i1
// True condition.
-// WIN32-O3: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
+// WIN32-O3: call x86_thiscallcc %struct.A* @"??0A@@QAE@XZ"
// WIN32-O3: store i1 true
-// WIN32-O3: invoke void @"\01?TakeRef@@YAXABUA@@@Z"
-// WIN32-O3: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
+// WIN32-O3: invoke void @"?TakeRef@@YAXABUA@@@Z"
+// WIN32-O3: invoke x86_thiscallcc %struct.A* @"??0A@@QAE@XZ"
// WIN32-O3: store i1 true, i1* %[[arg1_cond]]
-// WIN32-O3: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
+// WIN32-O3: invoke x86_thiscallcc %struct.A* @"??0A@@QAE@XZ"
// WIN32-O3: store i1 true
-// WIN32-O3: invoke void @"\01?TakeRef@@YAXABUA@@@Z"
-// WIN32-O3: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
+// WIN32-O3: invoke void @"?TakeRef@@YAXABUA@@@Z"
+// WIN32-O3: invoke x86_thiscallcc %struct.A* @"??0A@@QAE@XZ"
// WIN32-O3: store i1 true
// WIN32-O3: store i1 false, i1* %[[arg1_cond]]
-// WIN32-O3: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"
+// WIN32-O3: invoke i32 @"?TakesTwo@@YAHUA@@0@Z"
// False condition.
-// WIN32-O3: invoke i32 @"\01?CouldThrow@@YAHXZ"()
+// WIN32-O3: invoke i32 @"?CouldThrow@@YAHXZ"()
// Two normal cleanups for TakeRef args.
-// WIN32-O3: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
-// WIN32-O3-NOT: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
+// WIN32-O3: call x86_thiscallcc void @"??1A@@QAE@XZ"({{.*}})
+// WIN32-O3-NOT: invoke x86_thiscallcc void @"??1A@@QAE@XZ"
// WIN32-O3: ret i32
//
// Somewhere in the landing pad soup, we conditionally destroy arg1.
// WIN32-O3: %[[isactive:.*]] = load i1, i1* %[[arg1_cond]]
// WIN32-O3: br i1 %[[isactive]]
-// WIN32-O3: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
+// WIN32-O3: call x86_thiscallcc void @"??1A@@QAE@XZ"({{.*}})
// WIN32-O3: }
namespace crash_on_partial_destroy {
@@ -187,7 +187,7 @@ C::C() { foo(); }
// Verify that we don't bother with a vbtable lookup when adjusting the this
// pointer to call a base destructor from a constructor while unwinding.
-// WIN32-LABEL: define {{.*}} @"\01??0C@crash_on_partial_destroy@@QAE@XZ"{{.*}} {
+// WIN32-LABEL: define dso_local {{.*}} @"??0C@crash_on_partial_destroy@@QAE@XZ"{{.*}} {
// WIN32: cleanuppad
//
// We shouldn't do any vbptr loads, just constant GEPs.
@@ -195,7 +195,7 @@ C::C() { foo(); }
// WIN32: getelementptr i8, i8* %{{.*}}, i32 4
// WIN32-NOT: load
// WIN32: bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::B"*
-// WIN32: call x86_thiscallcc void @"\01??1B@crash_on_partial_destroy@@UAE@XZ"
+// WIN32: call x86_thiscallcc void @"??1B@crash_on_partial_destroy@@UAE@XZ"
//
// WIN32-NOT: load
// WIN32: bitcast %"struct.crash_on_partial_destroy::C"* %{{.*}} to i8*
@@ -203,7 +203,7 @@ C::C() { foo(); }
// WIN32: getelementptr inbounds i8, i8* %{{.*}}, i32 4
// WIN32-NOT: load
// WIN32: bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::A"*
-// WIN32: call x86_thiscallcc void @"\01??1A@crash_on_partial_destroy@@UAE@XZ"({{.*}})
+// WIN32: call x86_thiscallcc void @"??1A@crash_on_partial_destroy@@UAE@XZ"({{.*}})
// WIN32: }
}
@@ -217,16 +217,16 @@ void f() {
g();
}
-// WIN32-LABEL: define void @"\01?f@dont_call_terminate@@YAXXZ"()
-// WIN32: invoke void @"\01?g@dont_call_terminate@@YAXXZ"()
+// WIN32-LABEL: define dso_local void @"?f@dont_call_terminate@@YAXXZ"()
+// WIN32: invoke void @"?g@dont_call_terminate@@YAXXZ"()
// WIN32-NEXT: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
//
// WIN32: [[cont]]
-// WIN32: call x86_thiscallcc void @"\01??1C@dont_call_terminate@@QAE@XZ"({{.*}})
+// WIN32: call x86_thiscallcc void @"??1C@dont_call_terminate@@QAE@XZ"({{.*}})
//
// WIN32: [[lpad]]
// WIN32-NEXT: cleanuppad
-// WIN32: call x86_thiscallcc void @"\01??1C@dont_call_terminate@@QAE@XZ"({{.*}})
+// WIN32: call x86_thiscallcc void @"??1C@dont_call_terminate@@QAE@XZ"({{.*}})
}
namespace noexcept_false_dtor {
@@ -239,11 +239,11 @@ void f() {
}
}
-// WIN32-LABEL: define void @"\01?f@noexcept_false_dtor@@YAXXZ"()
-// WIN32: invoke i32 @"\01?CouldThrow@@YAHXZ"()
-// WIN32: call x86_thiscallcc void @"\01??1D@noexcept_false_dtor@@QAE@XZ"(%"struct.noexcept_false_dtor::D"* %{{.*}})
+// WIN32-LABEL: define dso_local void @"?f@noexcept_false_dtor@@YAXXZ"()
+// WIN32: invoke i32 @"?CouldThrow@@YAHXZ"()
+// WIN32: call x86_thiscallcc void @"??1D@noexcept_false_dtor@@QAE@XZ"(%"struct.noexcept_false_dtor::D"* %{{.*}})
// WIN32: cleanuppad
-// WIN32: call x86_thiscallcc void @"\01??1D@noexcept_false_dtor@@QAE@XZ"(%"struct.noexcept_false_dtor::D"* %{{.*}})
+// WIN32: call x86_thiscallcc void @"??1D@noexcept_false_dtor@@QAE@XZ"(%"struct.noexcept_false_dtor::D"* %{{.*}})
// WIN32: cleanupret
namespace lifetime_marker {
@@ -256,21 +256,21 @@ void f() {
g();
}
-// WIN32-LIFETIME-LABEL: define void @"\01?f@lifetime_marker@@YAXXZ"()
+// WIN32-LIFETIME-LABEL: define dso_local void @"?f@lifetime_marker@@YAXXZ"()
// WIN32-LIFETIME: %[[c:.*]] = alloca %"struct.lifetime_marker::C"
// WIN32-LIFETIME: %[[bc0:.*]] = bitcast %"struct.lifetime_marker::C"* %c to i8*
// WIN32-LIFETIME: call void @llvm.lifetime.start.p0i8(i64 1, i8* %[[bc0]])
-// WIN32-LIFETIME: invoke void @"\01?g@lifetime_marker@@YAXXZ"()
+// WIN32-LIFETIME: invoke void @"?g@lifetime_marker@@YAXXZ"()
// WIN32-LIFETIME-NEXT: to label %[[cont:[^ ]*]] unwind label %[[lpad0:[^ ]*]]
//
// WIN32-LIFETIME: [[cont]]
-// WIN32-LIFETIME: call x86_thiscallcc void @"\01??1C@lifetime_marker@@QAE@XZ"({{.*}})
+// WIN32-LIFETIME: call x86_thiscallcc void @"??1C@lifetime_marker@@QAE@XZ"({{.*}})
// WIN32-LIFETIME: %[[bc1:.*]] = bitcast %"struct.lifetime_marker::C"* %[[c]] to i8*
// WIN32-LIFETIME: call void @llvm.lifetime.end.p0i8(i64 1, i8* %[[bc1]])
//
// WIN32-LIFETIME: [[lpad0]]
// WIN32-LIFETIME-NEXT: cleanuppad
-// WIN32-LIFETIME: call x86_thiscallcc void @"\01??1C@lifetime_marker@@QAE@XZ"({{.*}})
+// WIN32-LIFETIME: call x86_thiscallcc void @"??1C@lifetime_marker@@QAE@XZ"({{.*}})
// WIN32-LIFETIME: cleanupret {{.*}} unwind label %[[lpad1:[^ ]*]]
//
// WIN32-LIFETIME: [[lpad1]]
@@ -293,7 +293,7 @@ struct class_0 : class_1 {
};
class_0::class_0() {
- // WIN32: define x86_thiscallcc %struct.class_0* @"\01??0class_0@@QAE@XZ"(%struct.class_0* returned %this, i32 %is_most_derived)
+ // WIN32: define dso_local x86_thiscallcc %struct.class_0* @"??0class_0@@QAE@XZ"(%struct.class_0* returned %this, i32 %is_most_derived)
// WIN32: store i32 %is_most_derived, i32* %[[IS_MOST_DERIVED_VAR:.*]], align 4
// WIN32: %[[IS_MOST_DERIVED_VAL:.*]] = load i32, i32* %[[IS_MOST_DERIVED_VAR]]
// WIN32: %[[SHOULD_CALL_VBASE_CTORS:.*]] = icmp ne i32 %[[IS_MOST_DERIVED_VAL]], 0
@@ -309,7 +309,31 @@ class_0::class_0() {
// WIN32-NEXT: %[[SHOULD_CALL_VBASE_DTOR:.*]] = icmp ne i32 %[[IS_MOST_DERIVED_VAL]], 0
// WIN32-NEXT: br i1 %[[SHOULD_CALL_VBASE_DTOR]], label %[[DTOR_VBASE:.*]], label %[[SKIP_VBASE:.*]]
// WIN32: [[DTOR_VBASE]]
- // WIN32-NEXT: call x86_thiscallcc void @"\01??1class_2@@UAE@XZ"
+ // WIN32-NEXT: call x86_thiscallcc void @"??1class_2@@UAE@XZ"
// WIN32: br label %[[SKIP_VBASE]]
// WIN32: [[SKIP_VBASE]]
}
+
+namespace PR37146 {
+// Check that IRGen doesn't emit calls to synthesized destructors for
+// non-trival C structs.
+
+// WIN32: define dso_local void @"?test@PR37146@@YAXXZ"()
+// WIN32: call void @llvm.memset.p0i8.i32(
+// WIN32: call i32 @"?getS@PR37146@@YA?AUS@1@XZ"(
+// WIN32: call void @"?func@PR37146@@YAXUS@1@0@Z"(
+// WIN32-NEXT: ret void
+// WIN32-NEXT: {{^}$}}
+
+struct S {
+ int f;
+};
+
+void func(S, S);
+S getS();
+
+void test() {
+ func(getS(), S());
+}
+
+}
diff --git a/test/CodeGenCXX/microsoft-abi-eh-inlineasm.cpp b/test/CodeGenCXX/microsoft-abi-eh-inlineasm.cpp
new file mode 100644
index 000000000000..4179508a8da5
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-eh-inlineasm.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=x86_64-pc-windows-msvc \
+// RUN: -fexceptions -fcxx-exceptions | FileCheck %s
+
+// Make sure calls to inline asm have funclet bundles.
+
+extern "C" void might_throw();
+extern "C" void foo() {
+ try {
+ might_throw();
+ } catch (int) {
+ __asm__("nop");
+ }
+}
+
+// CHECK-LABEL: define dso_local void @foo()
+// CHECK: invoke void @might_throw()
+// CHECK: %[[CATCHPAD:[^ ]*]] = catchpad within
+// CHECK: call void asm sideeffect "nop", {{.*}} [ "funclet"(token %[[CATCHPAD]]) ]
diff --git a/test/CodeGenCXX/microsoft-abi-eh-terminate.cpp b/test/CodeGenCXX/microsoft-abi-eh-terminate.cpp
index 7836dcf32b11..394b83485b52 100644
--- a/test/CodeGenCXX/microsoft-abi-eh-terminate.cpp
+++ b/test/CodeGenCXX/microsoft-abi-eh-terminate.cpp
@@ -6,11 +6,11 @@ void never_throws() noexcept(true) {
may_throw();
}
-// CHECK-LABEL: define void @"\01?never_throws@@YAXXZ"()
+// CHECK-LABEL: define dso_local void @"?never_throws@@YAXXZ"()
// CHECK-SAME: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
-// CHECK: invoke void @"\01?may_throw@@YAXXZ"()
+// CHECK: invoke void @"?may_throw@@YAXXZ"()
// CHECK: %[[cp:.*]] = cleanuppad within none []
-// MSVC2013: call void @"\01?terminate@@YAXXZ"()
+// MSVC2013: call void @"?terminate@@YAXXZ"()
// MSVC2015: call void @__std_terminate()
// CHECK-SAME: [ "funclet"(token %[[cp]]) ]
// CHECK-NEXT: unreachable
diff --git a/test/CodeGenCXX/microsoft-abi-emit-dependent.cpp b/test/CodeGenCXX/microsoft-abi-emit-dependent.cpp
new file mode 100644
index 000000000000..e74ebc879f5b
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-emit-dependent.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -emit-llvm-only -fmodules -triple x86_64-windows %s
+// PR36181
+#pragma clang module build foo
+module foo {}
+#pragma clang module contents
+template <typename T> struct A {
+ friend void f(A<T>) {}
+};
+#pragma clang module endbuild
+#pragma clang module import foo
+void g() { f(A<int>()); }
diff --git a/test/CodeGenCXX/microsoft-abi-extern-template.cpp b/test/CodeGenCXX/microsoft-abi-extern-template.cpp
index c69b4f5b8d86..83592363844f 100644
--- a/test/CodeGenCXX/microsoft-abi-extern-template.cpp
+++ b/test/CodeGenCXX/microsoft-abi-extern-template.cpp
@@ -3,17 +3,17 @@
// Even though Foo<int> has an extern template declaration, we have to emit our
// own copy the vftable when emitting the available externally constructor.
-// CHECK: @"\01??_7?$Foo@H@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [
-// CHECK-SAME: i8* bitcast (i8* (%struct.Foo*, i32)* @"\01??_G?$Foo@H@@UEAAPEAXI@Z" to i8*)
+// CHECK: @"??_7?$Foo@H@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [
+// CHECK-SAME: i8* bitcast (i8* (%struct.Foo*, i32)* @"??_G?$Foo@H@@UEAAPEAXI@Z" to i8*)
// CHECK-SAME: ] }, comdat
-// CHECK-LABEL: define %struct.Foo* @"\01?f@@YAPEAU?$Foo@H@@XZ"()
-// CHECK: call %struct.Foo* @"\01??0?$Foo@H@@QEAA@XZ"(%struct.Foo* %{{.*}})
+// CHECK-LABEL: define dso_local %struct.Foo* @"?f@@YAPEAU?$Foo@H@@XZ"()
+// CHECK: call %struct.Foo* @"??0?$Foo@H@@QEAA@XZ"(%struct.Foo* %{{.*}})
-// CHECK: define available_externally %struct.Foo* @"\01??0?$Foo@H@@QEAA@XZ"(%struct.Foo* returned %this)
-// CHECK: store {{.*}} @"\01??_7?$Foo@H@@6B@"
+// CHECK: define available_externally dso_local %struct.Foo* @"??0?$Foo@H@@QEAA@XZ"(%struct.Foo* returned %this)
+// CHECK: store {{.*}} @"??_7?$Foo@H@@6B@"
-// CHECK: define linkonce_odr i8* @"\01??_G?$Foo@H@@UEAAPEAXI@Z"(%struct.Foo* %this, i32 %should_call_delete)
+// CHECK: define linkonce_odr dso_local i8* @"??_G?$Foo@H@@UEAAPEAXI@Z"(%struct.Foo* %this, i32 %should_call_delete)
struct Base {
virtual ~Base();
diff --git a/test/CodeGenCXX/microsoft-abi-member-pointers.cpp b/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
index a3985ba09c02..cb3b41bbb4f1 100755
--- a/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
+++ b/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
@@ -1,8 +1,126 @@
-// RUN: %clang_cc1 -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -fms-extensions | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -fms-extensions | FileCheck -allow-deprecated-dag-overlap %s
// RUN: %clang_cc1 -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=x86_64-pc-win32 -fms-extensions | FileCheck %s -check-prefix=X64
// RUN: %clang_cc1 -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -fms-extensions -verify
// RUN: %clang_cc1 -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -DMEMFUN -fms-extensions -verify
+namespace pr37399 {
+template <typename T>
+struct Functor {
+ void (T::*PtrToMemberFunction)();
+};
+// CHECK-DAG: %"struct.pr37399::Functor" = type { i8* }
+
+template <typename SomeType>
+class SimpleDerivedFunctor;
+template <typename SomeType>
+class SimpleDerivedFunctor : public Functor<SimpleDerivedFunctor<SomeType>> {};
+// CHECK-DAG: %"class.pr37399::SimpleDerivedFunctor" = type { %"struct.pr37399::Functor" }
+
+SimpleDerivedFunctor<void> SimpleFunctor;
+// CHECK-DAG: @"?SimpleFunctor@pr37399@@3V?$SimpleDerivedFunctor@X@1@A" = dso_local global %"class.pr37399::SimpleDerivedFunctor" zeroinitializer, align 4
+
+short Global = 0;
+template <typename SomeType>
+class DerivedFunctor;
+template <typename SomeType>
+class DerivedFunctor
+ : public Functor<DerivedFunctor<void>> {
+public:
+ void Foo() {
+ Global = 42;
+ }
+};
+
+class MultipleBase {
+public:
+ MultipleBase() : Value() {}
+ short Value;
+};
+// CHECK-DAG: %"class.pr37399::MultipleBase" = type { i16 }
+
+template <typename SomeType>
+class MultiplyDerivedFunctor;
+template <typename SomeType>
+class MultiplyDerivedFunctor
+ : public Functor<MultiplyDerivedFunctor<void>>,
+ public MultipleBase {
+public:
+ void Foo() {
+ MultipleBase::Value = 42*2;
+ }
+};
+
+class VirtualBase {
+public:
+ VirtualBase() : Value() {}
+ short Value;
+};
+// CHECK-DAG: %"class.pr37399::VirtualBase" = type { i16 }
+
+template <typename SomeType>
+class VirtBaseFunctor
+ : public Functor<SomeType>,
+ public virtual VirtualBase{};
+template <typename SomeType>
+class VirtuallyDerivedFunctor;
+template <typename SomeType>
+class VirtuallyDerivedFunctor
+ : public VirtBaseFunctor<VirtuallyDerivedFunctor<void>>,
+ public virtual VirtualBase {
+public:
+ void Foo() {
+ VirtualBase::Value = 42*3;
+ }
+};
+} // namespace pr37399
+
+pr37399::DerivedFunctor<int> BFunctor;
+// CHECK-DAG: @"?BFunctor@@3V?$DerivedFunctor@H@pr37399@@A" = dso_local global %"[[BFUNCTOR:class.pr37399::DerivedFunctor(\.[0-9]+)?]]" zeroinitializer, align 8
+// CHECK-DAG: %"[[BFUNCTOR]]" = type { %"[[BFUNCTORBASE:struct.pr37399::Functor(\.[0-9]+)?]]" }
+// CHECK-DAG: %"[[BFUNCTORBASE]]" = type { { i8*, i32, i32, i32 } }
+pr37399::DerivedFunctor<void> AFunctor;
+// CHECK-DAG: @"?AFunctor@@3V?$DerivedFunctor@X@pr37399@@A" = dso_local global %"[[AFUNCTOR:class.pr37399::DerivedFunctor(\.[0-9]+)?]]" zeroinitializer, align 8
+// CHECK-DAG: %"[[AFUNCTOR]]" = type { %"[[AFUNCTORBASE:struct.pr37399::Functor(\.[0-9]+)?]]" }
+// CHECK-DAG: %"[[AFUNCTORBASE]]" = type { { i8*, i32, i32, i32 } }
+
+pr37399::MultiplyDerivedFunctor<int> DFunctor;
+// CHECK-DAG: @"?DFunctor@@3V?$MultiplyDerivedFunctor@H@pr37399@@A" = dso_local global %"[[DFUNCTOR:class.pr37399::MultiplyDerivedFunctor(\.[0-9]+)?]]" zeroinitializer, align 8
+// CHECK-DAG: %"[[DFUNCTOR]]" = type { %"[[DFUNCTORBASE:struct.pr37399::Functor(\.[0-9]+)?]]", %"class.pr37399::MultipleBase", [6 x i8] }
+// CHECK-DAG: %"[[DFUNCTORBASE]]" = type { { i8*, i32, i32, i32 } }
+pr37399::MultiplyDerivedFunctor<void> CFunctor;
+// CHECK-DAG: @"?CFunctor@@3V?$MultiplyDerivedFunctor@X@pr37399@@A" = dso_local global %"[[CFUNCTOR:class.pr37399::MultiplyDerivedFunctor(\.[0-9]+)?]]" zeroinitializer, align 8
+// CHECK-DAG: %"[[CFUNCTOR]]" = type { %"[[CFUNCTORBASE:struct.pr37399::Functor(\.[0-9]+)?]]", %"class.pr37399::MultipleBase", [6 x i8] }
+// CHECK-DAG: %"[[CFUNCTORBASE]]" = type { { i8*, i32, i32, i32 } }
+
+pr37399::VirtuallyDerivedFunctor<int> FFunctor;
+// CHECK-DAG: @"?FFunctor@@3V?$VirtuallyDerivedFunctor@H@pr37399@@A" = dso_local global %"[[FFUNCTOR:class.pr37399::VirtuallyDerivedFunctor(\.[0-9]+)?]]" zeroinitializer, align 8
+// CHECK-DAG: %"[[FFUNCTOR]]" = type { %"class.pr37399::VirtBaseFunctor.base", %"class.pr37399::VirtualBase" }
+pr37399::VirtuallyDerivedFunctor<void> EFunctor;
+// CHECK-DAG: @"?EFunctor@@3V?$VirtuallyDerivedFunctor@X@pr37399@@A" = dso_local global %"[[EFUNCTOR:class.pr37399::VirtuallyDerivedFunctor(\.[0-9]+)?]]" zeroinitializer, align 8
+// CHECK-DAG: %"[[EFUNCTOR]]" = type { %"class.pr37399::VirtBaseFunctor.base", %"class.pr37399::VirtualBase" }
+
+// CHECK-DAG: %"class.pr37399::VirtBaseFunctor.base" = type <{ %"[[VFUNCTORBASE:struct.pr37399::Functor(\.[0-9]+)?]]", i32*, [4 x i8] }>
+// CHECK-DAG: %"[[VFUNCTORBASE]]" = type { { i8*, i32, i32, i32 } }
+
+namespace pr37399 {
+void SingleInheritanceFnPtrCall() {
+ BFunctor.PtrToMemberFunction = &DerivedFunctor<void>::Foo;
+ (AFunctor.*(BFunctor.PtrToMemberFunction))();
+}
+void MultipleInheritanceFnPtrCall() {
+ DFunctor.PtrToMemberFunction = &MultiplyDerivedFunctor<void>::Foo;
+ Global = CFunctor.MultipleBase::Value;
+ (CFunctor.*(DFunctor.PtrToMemberFunction))();
+ Global = CFunctor.MultipleBase::Value;
+}
+void VirtualInheritanceFnPtrCall() {
+ FFunctor.PtrToMemberFunction = &VirtuallyDerivedFunctor<void>::Foo;
+ Global = EFunctor.VirtualBase::Value;
+ (EFunctor.*(FFunctor.PtrToMemberFunction))();
+ Global = EFunctor.VirtualBase::Value;
+}
+} // namespace pr37399
+
struct PR26313_Y;
typedef void (PR26313_Y::*PR26313_FUNC)();
struct PR26313_X {
@@ -15,17 +133,17 @@ void PR26313_f(PR26313_FUNC *p) { delete p; }
struct PR26313_Z;
int PR26313_Z::**a = nullptr;
int PR26313_Z::*b = *a;
-// CHECK-DAG: @"\01?a@@3PAPQPR26313_Z@@HA" = global %0* null, align 4
-// CHECK-DAG: @"\01?b@@3PQPR26313_Z@@HQ1@" = global { i32, i32, i32 } { i32 0, i32 0, i32 -1 }, align 4
+// CHECK-DAG: @"?a@@3PAPQPR26313_Z@@HA" = dso_local global %0* null, align 4
+// CHECK-DAG: @"?b@@3PQPR26313_Z@@HQ1@" = dso_local global { i32, i32, i32 } { i32 0, i32 0, i32 -1 }, align 4
namespace PR20947 {
struct A;
int A::**a = nullptr;
-// CHECK-DAG: @"\01?a@PR20947@@3PAPQA@1@HA" = global %{{.*}}* null, align 4
+// CHECK-DAG: @"?a@PR20947@@3PAPQA@1@HA" = dso_local global %{{.*}}* null, align 4
struct B;
int B::*&b = b;
-// CHECK-DAG: @"\01?b@PR20947@@3AAPQB@1@HA" = global %{{.*}}* null, align 4
+// CHECK-DAG: @"?b@PR20947@@3AAPQB@1@HA" = dso_local global %{{.*}}* null, align 4
}
namespace PR20017 {
@@ -35,7 +153,7 @@ struct A {
};
struct B;
auto a = &A<B>::m_fn1;
-// CHECK-DAG: @"\01?a@PR20017@@3P8?$A@UB@PR20017@@@1@AEPQB@1@HXZQ21@" = global i8* bitcast ({ i32, i32, i32 } ({{.*}}*)* @"\01?m_fn1@?$A@UB@PR20017@@@PR20017@@QAEPQB@2@HXZ" to i8*), align 4
+// CHECK-DAG: @"?a@PR20017@@3P8?$A@UB@PR20017@@@1@AEPQB@1@HXZQ21@" = dso_local global i8* bitcast ({ i32, i32, i32 } ({{.*}}*)* @"?m_fn1@?$A@UB@PR20017@@@PR20017@@QAEPQB@2@HXZ" to i8*), align 4
}
#ifndef INCOMPLETE_VIRTUAL
@@ -89,24 +207,24 @@ int Virtual ::*v_d_memptr;
int NonZeroVBPtr::*n_d_memptr;
int Unspecified::*u_d_memptr;
int UnspecSingle::*us_d_memptr;
-// CHECK: @"\01?s_d_memptr@@3PQSingle@@HQ1@" = global i32 -1, align 4
-// CHECK: @"\01?p_d_memptr@@3PQPolymorphic@@HQ1@" = global i32 0, align 4
-// CHECK: @"\01?m_d_memptr@@3PQMultiple@@HQ1@" = global i32 -1, align 4
-// CHECK: @"\01?v_d_memptr@@3PQVirtual@@HQ1@" = global { i32, i32 }
+// CHECK: @"?s_d_memptr@@3PQSingle@@HQ1@" = dso_local global i32 -1, align 4
+// CHECK: @"?p_d_memptr@@3PQPolymorphic@@HQ1@" = dso_local global i32 0, align 4
+// CHECK: @"?m_d_memptr@@3PQMultiple@@HQ1@" = dso_local global i32 -1, align 4
+// CHECK: @"?v_d_memptr@@3PQVirtual@@HQ1@" = dso_local global { i32, i32 }
// CHECK: { i32 0, i32 -1 }, align 4
-// CHECK: @"\01?n_d_memptr@@3PQNonZeroVBPtr@@HQ1@" = global { i32, i32 }
+// CHECK: @"?n_d_memptr@@3PQNonZeroVBPtr@@HQ1@" = dso_local global { i32, i32 }
// CHECK: { i32 0, i32 -1 }, align 4
-// CHECK: @"\01?u_d_memptr@@3PQUnspecified@@HQ1@" = global { i32, i32, i32 }
+// CHECK: @"?u_d_memptr@@3PQUnspecified@@HQ1@" = dso_local global { i32, i32, i32 }
// CHECK: { i32 0, i32 0, i32 -1 }, align 4
-// CHECK: @"\01?us_d_memptr@@3PQUnspecSingle@@HQ1@" = global { i32, i32, i32 }
+// CHECK: @"?us_d_memptr@@3PQUnspecSingle@@HQ1@" = dso_local global { i32, i32, i32 }
// CHECK: { i32 0, i32 0, i32 -1 }, align 4
void (Single ::*s_f_memptr)();
void (Multiple::*m_f_memptr)();
void (Virtual ::*v_f_memptr)();
-// CHECK: @"\01?s_f_memptr@@3P8Single@@AEXXZQ1@" = global i8* null, align 4
-// CHECK: @"\01?m_f_memptr@@3P8Multiple@@AEXXZQ1@" = global { i8*, i32 } zeroinitializer, align 4
-// CHECK: @"\01?v_f_memptr@@3P8Virtual@@AEXXZQ1@" = global { i8*, i32, i32 } zeroinitializer, align 4
+// CHECK: @"?s_f_memptr@@3P8Single@@AEXXZQ1@" = dso_local global i8* null, align 4
+// CHECK: @"?m_f_memptr@@3P8Multiple@@AEXXZQ1@" = dso_local global { i8*, i32 } zeroinitializer, align 4
+// CHECK: @"?v_f_memptr@@3P8Virtual@@AEXXZQ1@" = dso_local global { i8*, i32, i32 } zeroinitializer, align 4
// We can define Unspecified after locking in the inheritance model.
struct Unspecified : Multiple, Virtual {
@@ -125,16 +243,16 @@ void (Multiple ::*m_f_mp)() = &B2::foo;
void (Virtual ::*v_f_mp)() = &Virtual::foo;
void (Unspecified::*u_f_mp)() = &Unspecified::foo;
void (UnspecSingle::*us_f_mp)() = &UnspecSingle::foo;
-// CHECK: @"\01?s_f_mp@Const@@3P8Single@@AEXXZQ2@" =
-// CHECK: global i8* bitcast ({{.*}} @"\01?foo@Single@@QAEXXZ" to i8*), align 4
-// CHECK: @"\01?m_f_mp@Const@@3P8Multiple@@AEXXZQ2@" =
-// CHECK: global { i8*, i32 } { i8* bitcast ({{.*}} @"\01?foo@B2@@QAEXXZ" to i8*), i32 4 }, align 4
-// CHECK: @"\01?v_f_mp@Const@@3P8Virtual@@AEXXZQ2@" =
-// CHECK: global { i8*, i32, i32 } { i8* bitcast ({{.*}} @"\01?foo@Virtual@@QAEXXZ" to i8*), i32 0, i32 0 }, align 4
-// CHECK: @"\01?u_f_mp@Const@@3P8Unspecified@@AEXXZQ2@" =
-// CHECK: global { i8*, i32, i32, i32 } { i8* bitcast ({{.*}} @"\01?foo@Unspecified@@QAEXXZ" to i8*), i32 0, i32 0, i32 0 }, align 4
-// CHECK: @"\01?us_f_mp@Const@@3P8UnspecSingle@@AEXXZQ2@" =
-// CHECK: global { i8*, i32, i32, i32 } { i8* bitcast ({{.*}} @"\01?foo@UnspecSingle@@QAEXXZ" to i8*), i32 0, i32 0, i32 0 }, align 4
+// CHECK: @"?s_f_mp@Const@@3P8Single@@AEXXZQ2@" =
+// CHECK: global i8* bitcast ({{.*}} @"?foo@Single@@QAEXXZ" to i8*), align 4
+// CHECK: @"?m_f_mp@Const@@3P8Multiple@@AEXXZQ2@" =
+// CHECK: global { i8*, i32 } { i8* bitcast ({{.*}} @"?foo@B2@@QAEXXZ" to i8*), i32 4 }, align 4
+// CHECK: @"?v_f_mp@Const@@3P8Virtual@@AEXXZQ2@" =
+// CHECK: global { i8*, i32, i32 } { i8* bitcast ({{.*}} @"?foo@Virtual@@QAEXXZ" to i8*), i32 0, i32 0 }, align 4
+// CHECK: @"?u_f_mp@Const@@3P8Unspecified@@AEXXZQ2@" =
+// CHECK: global { i8*, i32, i32, i32 } { i8* bitcast ({{.*}} @"?foo@Unspecified@@QAEXXZ" to i8*), i32 0, i32 0, i32 0 }, align 4
+// CHECK: @"?us_f_mp@Const@@3P8UnspecSingle@@AEXXZQ2@" =
+// CHECK: global { i8*, i32, i32, i32 } { i8* bitcast ({{.*}} @"?foo@UnspecSingle@@QAEXXZ" to i8*), i32 0, i32 0, i32 0 }, align 4
}
namespace CastParam {
@@ -150,16 +268,16 @@ struct B { int b; };
struct C : B, A { int c; };
void (A::*ptr1)(void *) = (void (A::*)(void *)) &A::foo;
-// CHECK: @"\01?ptr1@CastParam@@3P8A@1@AEXPAX@ZQ21@" =
-// CHECK: global i8* bitcast (void ({{.*}})* @"\01?foo@A@CastParam@@QAEXPAU12@@Z" to i8*), align 4
+// CHECK: @"?ptr1@CastParam@@3P8A@1@AEXPAX@ZQ21@" =
+// CHECK: global i8* bitcast (void ({{.*}})* @"?foo@A@CastParam@@QAEXPAU12@@Z" to i8*), align 4
// Try a reinterpret_cast followed by a memptr conversion.
void (C::*ptr2)(void *) = (void (C::*)(void *)) (void (A::*)(void *)) &A::foo;
-// CHECK: @"\01?ptr2@CastParam@@3P8C@1@AEXPAX@ZQ21@" =
-// CHECK: global { i8*, i32 } { i8* bitcast (void ({{.*}})* @"\01?foo@A@CastParam@@QAEXPAU12@@Z" to i8*), i32 4 }, align 4
+// CHECK: @"?ptr2@CastParam@@3P8C@1@AEXPAX@ZQ21@" =
+// CHECK: global { i8*, i32 } { i8* bitcast (void ({{.*}})* @"?foo@A@CastParam@@QAEXPAU12@@Z" to i8*), i32 4 }, align 4
void (C::*ptr3)(void *) = (void (C::*)(void *)) (void (A::*)(void *)) (void (A::*)(A *)) 0;
-// CHECK: @"\01?ptr3@CastParam@@3P8C@1@AEXPAX@ZQ21@" =
+// CHECK: @"?ptr3@CastParam@@3P8C@1@AEXPAX@ZQ21@" =
// CHECK: global { i8*, i32 } zeroinitializer, align 4
struct D : C {
@@ -170,11 +288,11 @@ struct D : C {
// Try a cast that changes the inheritance model. Null for D is 0, but null for
// C is -1. We need the cast to long in order to hit the non-APValue path.
int C::*ptr4 = (int C::*) (int D::*) (long D::*) 0;
-// CHECK: @"\01?ptr4@CastParam@@3PQC@1@HQ21@" = global i32 -1, align 4
+// CHECK: @"?ptr4@CastParam@@3PQC@1@HQ21@" = dso_local global i32 -1, align 4
// MSVC rejects this but we accept it.
int C::*ptr5 = (int C::*) (long D::*) 0;
-// CHECK: @"\01?ptr5@CastParam@@3PQC@1@HQ21@" = global i32 -1, align 4
+// CHECK: @"?ptr5@CastParam@@3PQC@1@HQ21@" = dso_local global i32 -1, align 4
}
struct UnspecWithVBPtr;
@@ -191,23 +309,23 @@ void EmitNonVirtualMemberPointers() {
void (Virtual ::*v_f_memptr)() = &Virtual::foo;
void (Unspecified::*u_f_memptr)() = &Unspecified::foo;
void (UnspecWithVBPtr::*u2_f_memptr)() = &UnspecWithVBPtr::foo;
-// CHECK: define void @"\01?EmitNonVirtualMemberPointers@@YAXXZ"() {{.*}} {
+// CHECK: define dso_local void @"?EmitNonVirtualMemberPointers@@YAXXZ"() {{.*}} {
// CHECK: alloca i8*, align 4
// CHECK: alloca { i8*, i32 }, align 4
// CHECK: alloca { i8*, i32, i32 }, align 4
// CHECK: alloca { i8*, i32, i32, i32 }, align 4
-// CHECK: store i8* bitcast (void (%{{.*}}*)* @"\01?foo@Single@@QAEXXZ" to i8*), i8** %{{.*}}, align 4
+// CHECK: store i8* bitcast (void (%{{.*}}*)* @"?foo@Single@@QAEXXZ" to i8*), i8** %{{.*}}, align 4
// CHECK: store { i8*, i32 }
-// CHECK: { i8* bitcast (void (%{{.*}}*)* @"\01?foo@Multiple@@QAEXXZ" to i8*), i32 0 },
+// CHECK: { i8* bitcast (void (%{{.*}}*)* @"?foo@Multiple@@QAEXXZ" to i8*), i32 0 },
// CHECK: { i8*, i32 }* %{{.*}}, align 4
// CHECK: store { i8*, i32, i32 }
-// CHECK: { i8* bitcast (void (%{{.*}}*)* @"\01?foo@Virtual@@QAEXXZ" to i8*), i32 0, i32 0 },
+// CHECK: { i8* bitcast (void (%{{.*}}*)* @"?foo@Virtual@@QAEXXZ" to i8*), i32 0, i32 0 },
// CHECK: { i8*, i32, i32 }* %{{.*}}, align 4
// CHECK: store { i8*, i32, i32, i32 }
-// CHECK: { i8* bitcast (void (%{{.*}}*)* @"\01?foo@Unspecified@@QAEXXZ" to i8*), i32 0, i32 0, i32 0 },
+// CHECK: { i8* bitcast (void (%{{.*}}*)* @"?foo@Unspecified@@QAEXXZ" to i8*), i32 0, i32 0, i32 0 },
// CHECK: { i8*, i32, i32, i32 }* %{{.*}}, align 4
// CHECK: store { i8*, i32, i32, i32 }
-// CHECK: { i8* bitcast (void (%{{.*}}*)* @"\01?foo@UnspecWithVBPtr@@QAEXXZ" to i8*),
+// CHECK: { i8* bitcast (void (%{{.*}}*)* @"?foo@UnspecWithVBPtr@@QAEXXZ" to i8*),
// CHECK: i32 0, i32 0, i32 0 },
// CHECK: { i8*, i32, i32, i32 }* %{{.*}}, align 4
// CHECK: ret void
@@ -221,7 +339,7 @@ void podMemPtrs() {
if (memptr)
memptr = 0;
// Check that member pointers use the right offsets and that null is -1.
-// CHECK: define void @"\01?podMemPtrs@@YAXXZ"() {{.*}} {
+// CHECK: define dso_local void @"?podMemPtrs@@YAXXZ"() {{.*}} {
// CHECK: %[[memptr:.*]] = alloca i32, align 4
// CHECK-NEXT: store i32 0, i32* %[[memptr]], align 4
// CHECK-NEXT: store i32 4, i32* %[[memptr]], align 4
@@ -241,7 +359,7 @@ void polymorphicMemPtrs() {
memptr = 0;
// Member pointers for polymorphic classes include the vtable slot in their
// offset and use 0 to represent null.
-// CHECK: define void @"\01?polymorphicMemPtrs@@YAXXZ"() {{.*}} {
+// CHECK: define dso_local void @"?polymorphicMemPtrs@@YAXXZ"() {{.*}} {
// CHECK: %[[memptr:.*]] = alloca i32, align 4
// CHECK-NEXT: store i32 4, i32* %[[memptr]], align 4
// CHECK-NEXT: store i32 8, i32* %[[memptr]], align 4
@@ -255,7 +373,7 @@ void polymorphicMemPtrs() {
bool nullTestDataUnspecified(int Unspecified::*mp) {
return mp;
-// CHECK: define zeroext i1 @"\01?nullTestDataUnspecified@@YA_NPQUnspecified@@H@Z"{{.*}} {
+// CHECK: define dso_local zeroext i1 @"?nullTestDataUnspecified@@YA_NPQUnspecified@@H@Z"{{.*}} {
// CHECK: %{{.*}} = load { i32, i32, i32 }, { i32, i32, i32 }* %{{.*}}, align 4
// CHECK: store { i32, i32, i32 } {{.*}} align 4
// CHECK: %[[mp:.*]] = load { i32, i32, i32 }, { i32, i32, i32 }* %{{.*}}, align 4
@@ -271,13 +389,13 @@ bool nullTestDataUnspecified(int Unspecified::*mp) {
// CHECK: }
// Pass this large type indirectly.
-// X64-LABEL: define zeroext i1 @"\01?nullTestDataUnspecified@@
+// X64-LABEL: define dso_local zeroext i1 @"?nullTestDataUnspecified@@
// X64: ({ i32, i32, i32 }*)
}
bool nullTestFunctionUnspecified(void (Unspecified::*mp)()) {
return mp;
-// CHECK: define zeroext i1 @"\01?nullTestFunctionUnspecified@@YA_NP8Unspecified@@AEXXZ@Z"{{.*}} {
+// CHECK: define dso_local zeroext i1 @"?nullTestFunctionUnspecified@@YA_NP8Unspecified@@AEXXZ@Z"{{.*}} {
// CHECK: %{{.*}} = load { i8*, i32, i32, i32 }, { i8*, i32, i32, i32 }* %{{.*}}, align 4
// CHECK: store { i8*, i32, i32, i32 } {{.*}} align 4
// CHECK: %[[mp:.*]] = load { i8*, i32, i32, i32 }, { i8*, i32, i32, i32 }* %{{.*}}, align 4
@@ -291,7 +409,7 @@ int loadDataMemberPointerVirtual(Virtual *o, int Virtual::*memptr) {
return o->*memptr;
// Test that we can unpack this aggregate member pointer and load the member
// data pointer.
-// CHECK: define i32 @"\01?loadDataMemberPointerVirtual@@YAHPAUVirtual@@PQ1@H@Z"{{.*}} {
+// CHECK: define dso_local i32 @"?loadDataMemberPointerVirtual@@YAHPAUVirtual@@PQ1@H@Z"{{.*}} {
// CHECK: %[[o:.*]] = load %{{.*}}*, %{{.*}}** %{{.*}}, align 4
// CHECK: %[[memptr:.*]] = load { i32, i32 }, { i32, i32 }* %{{.*}}, align 4
// CHECK: %[[memptr0:.*]] = extractvalue { i32, i32 } %[[memptr:.*]], 0
@@ -312,7 +430,7 @@ int loadDataMemberPointerVirtual(Virtual *o, int Virtual::*memptr) {
// A two-field data memptr on x64 gets coerced to i64 and is passed in a
// register or memory.
-// X64-LABEL: define i32 @"\01?loadDataMemberPointerVirtual@@YAHPEAUVirtual@@PEQ1@H@Z"
+// X64-LABEL: define dso_local i32 @"?loadDataMemberPointerVirtual@@YAHPEAUVirtual@@PEQ1@H@Z"
// X64: (%struct.Virtual* %o, i64 %memptr.coerce)
}
@@ -320,7 +438,7 @@ int loadDataMemberPointerUnspecified(Unspecified *o, int Unspecified::*memptr) {
return o->*memptr;
// Test that we can unpack this aggregate member pointer and load the member
// data pointer.
-// CHECK: define i32 @"\01?loadDataMemberPointerUnspecified@@YAHPAUUnspecified@@PQ1@H@Z"{{.*}} {
+// CHECK: define dso_local i32 @"?loadDataMemberPointerUnspecified@@YAHPAUUnspecified@@PQ1@H@Z"{{.*}} {
// CHECK: %[[o:.*]] = load %{{.*}}*, %{{.*}}** %{{.*}}, align 4
// CHECK: %[[memptr:.*]] = load { i32, i32, i32 }, { i32, i32, i32 }* %{{.*}}, align 4
// CHECK: %[[memptr0:.*]] = extractvalue { i32, i32, i32 } %[[memptr:.*]], 0
@@ -351,12 +469,12 @@ int loadDataMemberPointerUnspecified(Unspecified *o, int Unspecified::*memptr) {
void callMemberPointerSingle(Single *o, void (Single::*memptr)()) {
(o->*memptr)();
// Just look for an indirect thiscall.
-// CHECK: define void @"\01?callMemberPointerSingle@@{{.*}} {{.*}} {
+// CHECK: define dso_local void @"?callMemberPointerSingle@@{{.*}} {{.*}} {
// CHECK: call x86_thiscallcc void %{{.*}}(%{{.*}} %{{.*}})
// CHECK: ret void
// CHECK: }
-// X64-LABEL: define void @"\01?callMemberPointerSingle@@
+// X64-LABEL: define dso_local void @"?callMemberPointerSingle@@
// X64: (%struct.Single* %o, i8* %memptr)
// X64: bitcast i8* %{{[^ ]*}} to void (%struct.Single*)*
// X64: ret void
@@ -364,7 +482,7 @@ void callMemberPointerSingle(Single *o, void (Single::*memptr)()) {
void callMemberPointerMultiple(Multiple *o, void (Multiple::*memptr)()) {
(o->*memptr)();
-// CHECK: define void @"\01?callMemberPointerMultiple@@{{.*}} {
+// CHECK: define dso_local void @"?callMemberPointerMultiple@@{{.*}} {
// CHECK: %[[memptr0:.*]] = extractvalue { i8*, i32 } %{{.*}}, 0
// CHECK: %[[memptr1:.*]] = extractvalue { i8*, i32 } %{{.*}}, 1
// CHECK: %[[this_adjusted:.*]] = getelementptr inbounds i8, i8* %{{.*}}, i32 %[[memptr1]]
@@ -378,7 +496,7 @@ void callMemberPointerMultiple(Multiple *o, void (Multiple::*memptr)()) {
void callMemberPointerVirtualBase(Virtual *o, void (Virtual::*memptr)()) {
(o->*memptr)();
// This shares a lot with virtual data member pointers.
-// CHECK: define void @"\01?callMemberPointerVirtualBase@@{{.*}} {
+// CHECK: define dso_local void @"?callMemberPointerVirtualBase@@{{.*}} {
// CHECK: %[[memptr0:.*]] = extractvalue { i8*, i32, i32 } %{{.*}}, 0
// CHECK: %[[memptr1:.*]] = extractvalue { i8*, i32, i32 } %{{.*}}, 1
// CHECK: %[[memptr2:.*]] = extractvalue { i8*, i32, i32 } %{{.*}}, 2
@@ -400,21 +518,21 @@ void callMemberPointerVirtualBase(Virtual *o, void (Virtual::*memptr)()) {
bool compareSingleFunctionMemptr(void (Single::*l)(), void (Single::*r)()) {
return l == r;
// Should only be one comparison here.
-// CHECK: define zeroext i1 @"\01?compareSingleFunctionMemptr@@YA_NP8Single@@AEXXZ0@Z"{{.*}} {
+// CHECK: define dso_local zeroext i1 @"?compareSingleFunctionMemptr@@YA_NP8Single@@AEXXZ0@Z"{{.*}} {
// CHECK-NOT: icmp
// CHECK: %[[r:.*]] = icmp eq
// CHECK-NOT: icmp
// CHECK: ret i1 %[[r]]
// CHECK: }
-// X64-LABEL: define zeroext i1 @"\01?compareSingleFunctionMemptr@@
+// X64-LABEL: define dso_local zeroext i1 @"?compareSingleFunctionMemptr@@
// X64: (i8* %{{[^,]*}}, i8* %{{[^)]*}})
}
bool compareNeqSingleFunctionMemptr(void (Single::*l)(), void (Single::*r)()) {
return l != r;
// Should only be one comparison here.
-// CHECK: define zeroext i1 @"\01?compareNeqSingleFunctionMemptr@@YA_NP8Single@@AEXXZ0@Z"{{.*}} {
+// CHECK: define dso_local zeroext i1 @"?compareNeqSingleFunctionMemptr@@YA_NP8Single@@AEXXZ0@Z"{{.*}} {
// CHECK-NOT: icmp
// CHECK: %[[r:.*]] = icmp ne
// CHECK-NOT: icmp
@@ -424,7 +542,7 @@ bool compareNeqSingleFunctionMemptr(void (Single::*l)(), void (Single::*r)()) {
bool unspecFuncMemptrEq(void (Unspecified::*l)(), void (Unspecified::*r)()) {
return l == r;
-// CHECK: define zeroext i1 @"\01?unspecFuncMemptrEq@@YA_NP8Unspecified@@AEXXZ0@Z"{{.*}} {
+// CHECK: define dso_local zeroext i1 @"?unspecFuncMemptrEq@@YA_NP8Unspecified@@AEXXZ0@Z"{{.*}} {
// CHECK: %[[lhs0:.*]] = extractvalue { i8*, i32, i32, i32 } %[[l:.*]], 0
// CHECK: %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[r:.*]], 0
// CHECK: %[[cmp0:.*]] = icmp eq i8* %[[lhs0]], %{{.*}}
@@ -445,13 +563,13 @@ bool unspecFuncMemptrEq(void (Unspecified::*l)(), void (Unspecified::*r)()) {
// CHECK: ret i1 %{{.*}}
// CHECK: }
-// X64-LABEL: define zeroext i1 @"\01?unspecFuncMemptrEq@@
+// X64-LABEL: define dso_local zeroext i1 @"?unspecFuncMemptrEq@@
// X64: ({ i8*, i32, i32, i32 }*, { i8*, i32, i32, i32 }*)
}
bool unspecFuncMemptrNeq(void (Unspecified::*l)(), void (Unspecified::*r)()) {
return l != r;
-// CHECK: define zeroext i1 @"\01?unspecFuncMemptrNeq@@YA_NP8Unspecified@@AEXXZ0@Z"{{.*}} {
+// CHECK: define dso_local zeroext i1 @"?unspecFuncMemptrNeq@@YA_NP8Unspecified@@AEXXZ0@Z"{{.*}} {
// CHECK: %[[lhs0:.*]] = extractvalue { i8*, i32, i32, i32 } %[[l:.*]], 0
// CHECK: %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[r:.*]], 0
// CHECK: %[[cmp0:.*]] = icmp ne i8* %[[lhs0]], %{{.*}}
@@ -475,7 +593,7 @@ bool unspecFuncMemptrNeq(void (Unspecified::*l)(), void (Unspecified::*r)()) {
bool unspecDataMemptrEq(int Unspecified::*l, int Unspecified::*r) {
return l == r;
-// CHECK: define zeroext i1 @"\01?unspecDataMemptrEq@@YA_NPQUnspecified@@H0@Z"{{.*}} {
+// CHECK: define dso_local zeroext i1 @"?unspecDataMemptrEq@@YA_NPQUnspecified@@H0@Z"{{.*}} {
// CHECK: extractvalue { i32, i32, i32 } %{{.*}}, 0
// CHECK: extractvalue { i32, i32, i32 } %{{.*}}, 0
// CHECK: icmp eq i32
@@ -490,13 +608,13 @@ bool unspecDataMemptrEq(int Unspecified::*l, int Unspecified::*r) {
// CHECK: ret i1
// CHECK: }
-// X64-LABEL: define zeroext i1 @"\01?unspecDataMemptrEq@@
+// X64-LABEL: define dso_local zeroext i1 @"?unspecDataMemptrEq@@
// X64: ({ i32, i32, i32 }*, { i32, i32, i32 }*)
}
void (Multiple::*convertB2FuncToMultiple(void (B2::*mp)()))() {
return mp;
-// CHECK: define i64 @"\01?convertB2FuncToMultiple@@YAP8Multiple@@AEXXZP8B2@@AEXXZ@Z"{{.*}} {
+// CHECK: define dso_local i64 @"?convertB2FuncToMultiple@@YAP8Multiple@@AEXXZP8B2@@AEXXZ@Z"{{.*}} {
// CHECK: store
// CHECK: %[[mp:.*]] = load i8*, i8** %{{.*}}, align 4
// CHECK: icmp ne i8* %[[mp]], null
@@ -520,7 +638,7 @@ void (B2::*convertMultipleFuncToB2(void (Multiple::*mp)()))() {
// LLVM from optimizing away the branch. This is likely a bug in
// lib/CodeGen/TargetInfo.cpp with how we classify memptr types for returns.
//
-// CHECK: define i32 @"\01?convertMultipleFuncToB2@@YAP8B2@@AEXXZP8Multiple@@AEXXZ@Z"{{.*}} {
+// CHECK: define dso_local i32 @"?convertMultipleFuncToB2@@YAP8B2@@AEXXZP8Multiple@@AEXXZ@Z"{{.*}} {
// CHECK: store
// CHECK: %[[src:.*]] = load { i8*, i32 }, { i8*, i32 }* %{{.*}}, align 4
// CHECK: extractvalue { i8*, i32 } %[[src]], 0
@@ -545,7 +663,7 @@ struct D : B, C { int d; };
void (D::*convertCToD(void (C::*mp)()))() {
return mp;
-// CHECK: define void @"\01?convertCToD@Test1@@YAP8D@1@AEXXZP8C@1@AEXXZ@Z"{{.*}} {
+// CHECK: define dso_local void @"?convertCToD@Test1@@YAP8D@1@AEXXZP8C@1@AEXXZ@Z"{{.*}} {
// CHECK: store
// CHECK: load { i8*, i32, i32 }, { i8*, i32, i32 }* %{{.*}}, align 4
// CHECK: extractvalue { i8*, i32, i32 } %{{.*}}, 0
@@ -585,7 +703,7 @@ struct C : A {
int A::*reinterpret(int B::*mp) {
return reinterpret_cast<int A::*>(mp);
-// CHECK: define i32 @"\01?reinterpret@Test2@@YAPQA@1@HPQB@1@H@Z"{{.*}} {
+// CHECK: define dso_local i32 @"?reinterpret@Test2@@YAPQA@1@HPQB@1@H@Z"{{.*}} {
// CHECK-NOT: select
// CHECK: ret i32
// CHECK: }
@@ -593,7 +711,7 @@ int A::*reinterpret(int B::*mp) {
int A::*reinterpret(int C::*mp) {
return reinterpret_cast<int A::*>(mp);
-// CHECK: define i32 @"\01?reinterpret@Test2@@YAPQA@1@HPQC@1@H@Z"{{.*}} {
+// CHECK: define dso_local i32 @"?reinterpret@Test2@@YAPQA@1@HPQC@1@H@Z"{{.*}} {
// CHECK: %[[mp:.*]] = load i32, i32*
// CHECK: %[[cmp:.*]] = icmp ne i32 %[[mp]], 0
// CHECK: select i1 %[[cmp]], i32 %[[mp]], i32 -1
@@ -612,7 +730,7 @@ struct A {
int *load_data(A *a, int A::*mp) {
return &(a->*mp);
-// CHECK-LABEL: define i32* @"\01?load_data@Test3@@YAPAHPAUA@1@PQ21@H@Z"{{.*}} {
+// CHECK-LABEL: define dso_local i32* @"?load_data@Test3@@YAPAHPAUA@1@PQ21@H@Z"{{.*}} {
// CHECK: %[[a:.*]] = load %"struct.Test3::A"*, %"struct.Test3::A"** %{{.*}}, align 4
// CHECK: %[[mp:.*]] = load i32, i32* %{{.*}}, align 4
// CHECK: %[[a_i8:.*]] = bitcast %"struct.Test3::A"* %[[a]] to i8*
@@ -631,11 +749,11 @@ struct C : A, B { virtual void g(); };
void (C::*getmp())() {
return &C::g;
}
-// CHECK-LABEL: define i64 @"\01?getmp@Test4@@YAP8C@1@AEXXZXZ"()
-// CHECK: store { i8*, i32 } { i8* bitcast (void (%"struct.Test4::C"*, ...)* @"\01??_9C@Test4@@$BA@AE" to i8*), i32 4 }, { i8*, i32 }* %{{.*}}
+// CHECK-LABEL: define dso_local i64 @"?getmp@Test4@@YAP8C@1@AEXXZXZ"()
+// CHECK: store { i8*, i32 } { i8* bitcast (void (%"struct.Test4::C"*, ...)* @"??_9C@Test4@@$BA@AE" to i8*), i32 4 }, { i8*, i32 }* %{{.*}}
//
-// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@Test4@@$BA@AE"(%"struct.Test4::C"* %this, ...) {{.*}} comdat
+// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"??_9C@Test4@@$BA@AE"(%"struct.Test4::C"* %this, ...) {{.*}} comdat
// CHECK-NOT: getelementptr
// CHECK: load void (%"struct.Test4::C"*, ...)**, void (%"struct.Test4::C"*, ...)*** %{{.*}}
// CHECK: getelementptr inbounds void (%"struct.Test4::C"*, ...)*, void (%"struct.Test4::C"*, ...)** %{{.*}}, i64 0
@@ -651,8 +769,8 @@ struct A {
};
struct B : public A {};
void test() { void (B::*a)() = &B::f; }
-// CHECK-LABEL: define void @"\01?test@pr20007@@YAXXZ"
-// CHECK: store i8* bitcast (void (%"struct.pr20007::A"*)* @"\01?f@A@pr20007@@QAEXXZ" to i8*)
+// CHECK-LABEL: define dso_local void @"?test@pr20007@@YAXXZ"
+// CHECK: store i8* bitcast (void (%"struct.pr20007::A"*)* @"?f@A@pr20007@@QAEXXZ" to i8*)
}
namespace pr20007_kw {
@@ -663,8 +781,8 @@ struct A {
struct __single_inheritance B;
struct B : public A {};
void test() { void (B::*a)() = &B::f; }
-// CHECK-LABEL: define void @"\01?test@pr20007_kw@@YAXXZ"
-// CHECK: store i8* bitcast (void (%"struct.pr20007_kw::A"*)* @"\01?f@A@pr20007_kw@@QAEXXZ" to i8*)
+// CHECK-LABEL: define dso_local void @"?test@pr20007_kw@@YAXXZ"
+// CHECK: store i8* bitcast (void (%"struct.pr20007_kw::A"*)* @"?f@A@pr20007_kw@@QAEXXZ" to i8*)
}
namespace pr20007_pragma {
@@ -678,7 +796,7 @@ void test() { (void)(void (B::*)()) &B::f; }
static_assert(sizeof(int B::*) == 4, "");
static_assert(sizeof(int A::*) == 4, "");
#pragma pointers_to_members(best_case)
-// CHECK-LABEL: define void @"\01?test@pr20007_pragma@@YAXXZ"
+// CHECK-LABEL: define dso_local void @"?test@pr20007_pragma@@YAXXZ"
}
namespace pr20007_pragma2 {
@@ -692,7 +810,7 @@ void test() { (void)&B::f; }
static_assert(sizeof(int B::*) == 4, "");
static_assert(sizeof(int A::*) == 12, "");
#pragma pointers_to_members(best_case)
-// CHECK-LABEL: define void @"\01?test@pr20007_pragma2@@YAXXZ"
+// CHECK-LABEL: define dso_local void @"?test@pr20007_pragma2@@YAXXZ"
}
namespace pr23823 {
@@ -738,8 +856,8 @@ struct D : A, C {};
typedef void (D::*DMemPtrTy)();
-// CHECK-LABEL: define void @"\01?get_memptr@pr23878@@YAP8D@1@AEXXZXZ"
-// CHECK: @"\01??_9C@pr23878@@$BA@AE" to i8*), i32 0, i32 4
+// CHECK-LABEL: define dso_local void @"?get_memptr@pr23878@@YAP8D@1@AEXXZXZ"
+// CHECK: @"??_9C@pr23878@@$BA@AE" to i8*), i32 0, i32 4
DMemPtrTy get_memptr() { return &D::f; }
}
@@ -755,14 +873,14 @@ public:
// CHECK-LABEL: foo_fun
void foo_fun() {
- // CHECK: store i8* bitcast (void (%class.CA*)* @"\01?OnHelp@CA@@QAEXXZ" to i8*), i8**
+ // CHECK: store i8* bitcast (void (%class.CA*)* @"?OnHelp@CA@@QAEXXZ" to i8*), i8**
f func = (f)&CA::OnHelp;
}
namespace PR24703 {
struct S;
void f(int S::*&p) {}
-// CHECK-LABEL: define void @"\01?f@PR24703@@YAXAAPQS@1@H@Z"(
+// CHECK-LABEL: define dso_local void @"?f@PR24703@@YAXAAPQS@1@H@Z"(
}
namespace ReferenceToMPTWithIncompleteClass {
@@ -771,14 +889,14 @@ struct J;
struct K;
extern K *k;
-// CHECK-LABEL: @"\01?f@ReferenceToMPTWithIncompleteClass@@YAIAAPQS@1@H@Z"(
+// CHECK-LABEL: @"?f@ReferenceToMPTWithIncompleteClass@@YAIAAPQS@1@H@Z"(
// CHECK: ret i32 12
unsigned f(int S::*&p) { return sizeof p; }
-// CHECK-LABEL: @"\01?g@ReferenceToMPTWithIncompleteClass@@YA_NAAPQJ@1@H0@Z"(
+// CHECK-LABEL: @"?g@ReferenceToMPTWithIncompleteClass@@YA_NAAPQJ@1@H0@Z"(
bool g(int J::*&p, int J::*&q) { return p == q; }
-// CHECK-LABEL: @"\01?h@ReferenceToMPTWithIncompleteClass@@YAHAAPQK@1@H@Z"(
+// CHECK-LABEL: @"?h@ReferenceToMPTWithIncompleteClass@@YAHAAPQK@1@H@Z"(
int h(int K::*&p) { return k->*p; }
}
@@ -790,5 +908,5 @@ class A {
void printd();
};
void A::printd() { JSMethod<A, &A::printd>(); }
-// CHECK-LABEL: @"\01??$JSMethod@VA@PMFInTemplateArgument@@$1?printd@12@AAEHH@Z@PMFInTemplateArgument@@YAXXZ"(
+// CHECK-LABEL: @"??$JSMethod@VA@PMFInTemplateArgument@@$1?printd@12@AAEHH@Z@PMFInTemplateArgument@@YAXXZ"(
}
diff --git a/test/CodeGenCXX/microsoft-abi-methods.cpp b/test/CodeGenCXX/microsoft-abi-methods.cpp
index e58d1033e12e..f4186a20ec52 100644
--- a/test/CodeGenCXX/microsoft-abi-methods.cpp
+++ b/test/CodeGenCXX/microsoft-abi-methods.cpp
@@ -18,11 +18,11 @@ void call_simple_method() {
instance.simple_method();
// Make sure that the call uses the right calling convention:
-// CHECK: call x86_thiscallcc void @"\01?simple_method@C@@QAEXXZ"
+// CHECK: call x86_thiscallcc void @"?simple_method@C@@QAEXXZ"
// CHECK: ret
// Make sure that the definition uses the right calling convention:
-// CHECK: define linkonce_odr x86_thiscallcc void @"\01?simple_method@C@@QAEXXZ"
+// CHECK: define linkonce_odr dso_local x86_thiscallcc void @"?simple_method@C@@QAEXXZ"
// CHECK: ret
}
@@ -30,11 +30,11 @@ void call_cdecl_method() {
C instance;
instance.cdecl_method();
// Make sure that the call uses the right calling convention:
-// CHECK: call void @"\01?cdecl_method@C@@QAAXXZ"
+// CHECK: call void @"?cdecl_method@C@@QAAXXZ"
// CHECK: ret
// Make sure that the definition uses the right calling convention:
-// CHECK: define linkonce_odr void @"\01?cdecl_method@C@@QAAXXZ"
+// CHECK: define linkonce_odr dso_local void @"?cdecl_method@C@@QAAXXZ"
// CHECK: ret
}
@@ -42,21 +42,21 @@ void call_vararg_method() {
C instance;
instance.vararg_method("Hello");
// Make sure that the call uses the right calling convention:
-// CHECK: call void (%class.C*, i8*, ...) @"\01?vararg_method@C@@QAAXPBDZZ"
+// CHECK: call void (%class.C*, i8*, ...) @"?vararg_method@C@@QAAXPBDZZ"
// CHECK: ret
// Make sure that the definition uses the right calling convention:
-// CHECK: define linkonce_odr void @"\01?vararg_method@C@@QAAXPBDZZ"
+// CHECK: define linkonce_odr dso_local void @"?vararg_method@C@@QAAXPBDZZ"
}
void call_static_method() {
C::static_method();
// Make sure that the call uses the right calling convention:
-// CHECK: call void @"\01?static_method@C@@SAXXZ"
+// CHECK: call void @"?static_method@C@@SAXXZ"
// CHECK: ret
// Make sure that the definition uses the right calling convention:
-// CHECK: define linkonce_odr void @"\01?static_method@C@@SAXXZ"
+// CHECK: define linkonce_odr dso_local void @"?static_method@C@@SAXXZ"
}
class Base {
@@ -71,19 +71,19 @@ void constructors() {
Child c;
// Make sure that the Base constructor call in the Child constructor uses
// the right calling convention:
-// CHECK: define linkonce_odr x86_thiscallcc %class.Child* @"\01??0Child@@QAE@XZ"
-// CHECK: %{{[.0-9A-Z_a-z]+}} = call x86_thiscallcc %class.Base* @"\01??0Base@@QAE@XZ"
+// CHECK: define linkonce_odr dso_local x86_thiscallcc %class.Child* @"??0Child@@QAE@XZ"
+// CHECK: %{{[.0-9A-Z_a-z]+}} = call x86_thiscallcc %class.Base* @"??0Base@@QAE@XZ"
// CHECK: ret
-// Make sure that the Base constructor definition uses the right CC:
-// CHECK: define linkonce_odr x86_thiscallcc %class.Base* @"\01??0Base@@QAE@XZ"
-
// Make sure that the Base destructor call in the Child denstructor uses
// the right calling convention:
-// CHECK: define linkonce_odr x86_thiscallcc void @"\01??1Child@@QAE@XZ"
-// CHECK: call x86_thiscallcc void @"\01??1Base@@QAE@XZ"
+// CHECK: define linkonce_odr dso_local x86_thiscallcc void @"??1Child@@QAE@XZ"
+// CHECK: call x86_thiscallcc void @"??1Base@@QAE@XZ"
// CHECK: ret
+// Make sure that the Base constructor definition uses the right CC:
+// CHECK: define linkonce_odr dso_local x86_thiscallcc %class.Base* @"??0Base@@QAE@XZ"
+
// Make sure that the Base destructor definition uses the right CC:
-// CHECK: define linkonce_odr x86_thiscallcc void @"\01??1Base@@QAE@XZ"
+// CHECK: define linkonce_odr dso_local x86_thiscallcc void @"??1Base@@QAE@XZ"
}
diff --git a/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp
index 5bed69ff117f..cefbdafe5fc0 100644
--- a/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp
+++ b/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp
@@ -19,7 +19,7 @@ struct ChildOverride : Left, Right {
extern "C" void foo(void *);
void call_left_no_override(ChildNoOverride *child) {
-// CHECK-LABEL: define void @"\01?call_left_no_override
+// CHECK-LABEL: define dso_local void @"?call_left_no_override
// CHECK: %[[CHILD:.*]] = load %struct.ChildNoOverride
child->left();
@@ -34,7 +34,7 @@ void call_left_no_override(ChildNoOverride *child) {
}
void ChildOverride::left() {
-// CHECK-LABEL: define x86_thiscallcc void @"\01?left@ChildOverride@@UAEXXZ"
+// CHECK-LABEL: define dso_local x86_thiscallcc void @"?left@ChildOverride@@UAEXXZ"
// CHECK-SAME: (%struct.ChildOverride* %[[THIS:.*]])
//
// No need to adjust 'this' as the ChildOverride's layout begins with Left.
@@ -49,7 +49,7 @@ void ChildOverride::left() {
}
void call_left_override(ChildOverride *child) {
-// CHECK-LABEL: define void @"\01?call_left_override
+// CHECK-LABEL: define dso_local void @"?call_left_override
// CHECK: %[[CHILD:.*]] = load %struct.ChildOverride
child->left();
@@ -63,7 +63,7 @@ void call_left_override(ChildOverride *child) {
}
void call_right_no_override(ChildNoOverride *child) {
-// CHECK-LABEL: define void @"\01?call_right_no_override
+// CHECK-LABEL: define dso_local void @"?call_right_no_override
// CHECK: %[[CHILD:.*]] = load %struct.ChildNoOverride
child->right();
@@ -83,13 +83,16 @@ void call_right_no_override(ChildNoOverride *child) {
}
void ChildOverride::right() {
-// CHECK-LABEL: define x86_thiscallcc void @"\01?right@ChildOverride@@UAEXXZ"(i8*
+// CHECK-LABEL: define dso_local x86_thiscallcc void @"?right@ChildOverride@@UAEXXZ"(i8*
//
// ChildOverride::right gets 'this' cast to Right* in ECX (i.e. this+4) so we
// need to adjust 'this' before use.
//
+// CHECK: %[[THIS_STORE:.*]] = alloca %struct.ChildOverride*, align 4
// CHECK: %[[THIS_ADDR:.*]] = alloca %struct.ChildOverride*, align 4
-// CHECK: %[[THIS_INIT:.*]] = bitcast i8* %[[ECX:.*]] to %struct.ChildOverride*
+// CHECK: %[[COERCE_VAL:.*]] = bitcast i8* %[[ECX:.*]] to %struct.ChildOverride*
+// CHECK: store %struct.ChildOverride* %[[COERCE_VAL]], %struct.ChildOverride** %[[THIS_STORE]], align 4
+// CHECK: %[[THIS_INIT:.*]] = load %struct.ChildOverride*, %struct.ChildOverride** %[[THIS_STORE]], align 4
// CHECK: store %struct.ChildOverride* %[[THIS_INIT]], %struct.ChildOverride** %[[THIS_ADDR]], align 4
// CHECK: %[[THIS_RELOAD:.*]] = load %struct.ChildOverride*, %struct.ChildOverride** %[[THIS_ADDR]]
// CHECK: %[[THIS_i8:.*]] = bitcast %struct.ChildOverride* %[[THIS_RELOAD]] to i8*
@@ -103,7 +106,7 @@ void ChildOverride::right() {
}
void call_right_override(ChildOverride *child) {
-// CHECK-LABEL: define void @"\01?call_right_override
+// CHECK-LABEL: define dso_local void @"?call_right_override
// CHECK: %[[CHILD:.*]] = load %struct.ChildOverride
child->right();
@@ -111,16 +114,15 @@ void call_right_override(ChildOverride *child) {
// the caller site.
//
// CHECK: %[[CHILD_i8:.*]] = bitcast %struct.ChildOverride* %[[CHILD]] to i8*
+// CHECK: %[[RIGHT:.*]] = getelementptr inbounds i8, i8* %[[CHILD_i8]], i32 4
//
+// CHECK: %[[CHILD_i8:.*]] = bitcast %struct.ChildOverride* %[[CHILD]] to i8*
// CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8, i8* %[[CHILD_i8]], i32 4
// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to void (i8*)***
// CHECK: %[[VFTABLE:.*]] = load void (i8*)**, void (i8*)*** %[[VFPTR]]
// CHECK: %[[VFUN:.*]] = getelementptr inbounds void (i8*)*, void (i8*)** %[[VFTABLE]], i64 0
// CHECK: %[[VFUN_VALUE:.*]] = load void (i8*)*, void (i8*)** %[[VFUN]]
//
-// CHECK: %[[CHILD_i8:.*]] = bitcast %struct.ChildOverride* %[[CHILD]] to i8*
-// CHECK: %[[RIGHT:.*]] = getelementptr inbounds i8, i8* %[[CHILD_i8]], i32 4
-//
// CHECK: call x86_thiscallcc void %[[VFUN_VALUE]](i8* %[[RIGHT]])
// CHECK: ret
}
@@ -130,10 +132,13 @@ struct GrandchildOverride : ChildOverride {
};
void GrandchildOverride::right() {
-// CHECK-LABEL: define x86_thiscallcc void @"\01?right@GrandchildOverride@@UAEXXZ"(i8*
+// CHECK-LABEL: define dso_local x86_thiscallcc void @"?right@GrandchildOverride@@UAEXXZ"(i8*
//
+// CHECK: %[[THIS_STORE:.*]] = alloca %struct.GrandchildOverride*, align 4
// CHECK: %[[THIS_ADDR:.*]] = alloca %struct.GrandchildOverride*, align 4
-// CHECK: %[[THIS_INIT:.*]] = bitcast i8* %[[ECX:.*]] to %struct.GrandchildOverride*
+// CHECK: %[[COERCE_VAL:.*]] = bitcast i8* %[[ECX:.*]] to %struct.GrandchildOverride*
+// CHECK: store %struct.GrandchildOverride* %[[COERCE_VAL]], %struct.GrandchildOverride** %[[THIS_STORE]], align 4
+// CHECK: %[[THIS_INIT:.*]] = load %struct.GrandchildOverride*, %struct.GrandchildOverride** %[[THIS_STORE]], align 4
// CHECK: store %struct.GrandchildOverride* %[[THIS_INIT]], %struct.GrandchildOverride** %[[THIS_ADDR]], align 4
// CHECK: %[[THIS_RELOAD:.*]] = load %struct.GrandchildOverride*, %struct.GrandchildOverride** %[[THIS_ADDR]]
// CHECK: %[[THIS_i8:.*]] = bitcast %struct.GrandchildOverride* %[[THIS_RELOAD]] to i8*
@@ -153,37 +158,37 @@ void call_grandchild_right(GrandchildOverride *obj) {
void emit_ctors() {
Left l;
- // CHECK-LABEL: define {{.*}} @"\01??0Left@@QAE@XZ"
+ // CHECK-LABEL: define {{.*}} @"??0Left@@QAE@XZ"
// CHECK-NOT: getelementptr
- // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7Left@@6B@" to i32 (...)**)
+ // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7Left@@6B@" to i32 (...)**)
// CHECK: ret
Right r;
- // CHECK-LABEL: define {{.*}} @"\01??0Right@@QAE@XZ"
+ // CHECK-LABEL: define {{.*}} @"??0Right@@QAE@XZ"
// CHECK-NOT: getelementptr
- // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7Right@@6B@" to i32 (...)**)
+ // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7Right@@6B@" to i32 (...)**)
// CHECK: ret
ChildOverride co;
- // CHECK-LABEL: define {{.*}} @"\01??0ChildOverride@@QAE@XZ"
+ // CHECK-LABEL: define {{.*}} @"??0ChildOverride@@QAE@XZ"
// CHECK: %[[THIS:.*]] = load %struct.ChildOverride*, %struct.ChildOverride**
// CHECK: %[[VFPTR:.*]] = bitcast %struct.ChildOverride* %[[THIS]] to i32 (...)***
- // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7ChildOverride@@6BLeft@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
+ // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7ChildOverride@@6BLeft@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
// CHECK: %[[THIS_i8:.*]] = bitcast %struct.ChildOverride* %[[THIS]] to i8*
// CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 4
// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to i32 (...)***
- // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7ChildOverride@@6BRight@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
+ // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7ChildOverride@@6BRight@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
// CHECK: ret
GrandchildOverride gc;
- // CHECK-LABEL: define {{.*}} @"\01??0GrandchildOverride@@QAE@XZ"
+ // CHECK-LABEL: define {{.*}} @"??0GrandchildOverride@@QAE@XZ"
// CHECK: %[[THIS:.*]] = load %struct.GrandchildOverride*, %struct.GrandchildOverride**
// CHECK: %[[VFPTR:.*]] = bitcast %struct.GrandchildOverride* %[[THIS]] to i32 (...)***
- // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7GrandchildOverride@@6BLeft@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
+ // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7GrandchildOverride@@6BLeft@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
// CHECK: %[[THIS_i8:.*]] = bitcast %struct.GrandchildOverride* %[[THIS]] to i8*
// CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 4
// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to i32 (...)***
- // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7GrandchildOverride@@6BRight@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
+ // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7GrandchildOverride@@6BRight@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
// CHECK: ret
}
@@ -197,10 +202,10 @@ struct AsymmetricChild : LeftWithNonVirtualDtor, Right {
};
void call_asymmetric_child_complete_dtor() {
- // CHECK-LABEL: define void @"\01?call_asymmetric_child_complete_dtor@@YAXXZ"
+ // CHECK-LABEL: define dso_local void @"?call_asymmetric_child_complete_dtor@@YAXXZ"
AsymmetricChild obj;
- // CHECK: call x86_thiscallcc %struct.AsymmetricChild* @"\01??0AsymmetricChild@@QAE@XZ"(%struct.AsymmetricChild* %[[OBJ:.*]])
+ // CHECK: call x86_thiscallcc %struct.AsymmetricChild* @"??0AsymmetricChild@@QAE@XZ"(%struct.AsymmetricChild* %[[OBJ:.*]])
// CHECK-NOT: getelementptr
- // CHECK: call x86_thiscallcc void @"\01??1AsymmetricChild@@UAE@XZ"(%struct.AsymmetricChild* %[[OBJ]])
+ // CHECK: call x86_thiscallcc void @"??1AsymmetricChild@@UAE@XZ"(%struct.AsymmetricChild* %[[OBJ]])
// CHECK: ret
}
diff --git a/test/CodeGenCXX/microsoft-abi-rtti.cpp b/test/CodeGenCXX/microsoft-abi-rtti.cpp
index 5738b606c111..a9ec5f3c9d68 100644
--- a/test/CodeGenCXX/microsoft-abi-rtti.cpp
+++ b/test/CodeGenCXX/microsoft-abi-rtti.cpp
@@ -26,242 +26,242 @@ struct Y2 { virtual void f() {} };
struct A2 : Z2, Y2 {};
struct B2 : virtual A2 { B2() {} virtual void f() {} } b2;
-// CHECK-DAG: @"\01??_R4B2@@6BZ2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 8, i32 4, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUB2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3B2@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AUB2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUB2@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3B2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 4, %rtti.BaseClassDescriptor** getelementptr inbounds ([5 x %rtti.BaseClassDescriptor*], [5 x %rtti.BaseClassDescriptor*]* @"\01??_R2B2@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2B2@@8" = linkonce_odr constant [5 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@B2@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@A2@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3EA@Z2@@8", %rtti.BaseClassDescriptor* @"\01??_R13A@3EA@Y2@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@B2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUB2@@@8" to i8*), i32 3, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3B2@@8" }, comdat
-// CHECK-DAG: @"\01??_R1A@A@3FA@A2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUA2@@@8" to i8*), i32 2, i32 0, i32 0, i32 4, i32 80, %rtti.ClassHierarchyDescriptor* @"\01??_R3A2@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AUA2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUA2@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3A2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 1, i32 3, %rtti.BaseClassDescriptor** getelementptr inbounds ([4 x %rtti.BaseClassDescriptor*], [4 x %rtti.BaseClassDescriptor*]* @"\01??_R2A2@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2A2@@8" = linkonce_odr constant [4 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@A2@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Z2@@8", %rtti.BaseClassDescriptor* @"\01??_R13?0A@EA@Y2@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@A2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUA2@@@8" to i8*), i32 2, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3A2@@8" }, comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@Z2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUZ2@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3Z2@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AUZ2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUZ2@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3Z2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*], [2 x %rtti.BaseClassDescriptor*]* @"\01??_R2Z2@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2Z2@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Z2@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R13?0A@EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUY2@@@8" to i8*), i32 0, i32 4, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3Y2@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AUY2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUY2@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3Y2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*], [2 x %rtti.BaseClassDescriptor*]* @"\01??_R2Y2@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2Y2@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Y2@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUY2@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3Y2@@8" }, comdat
-// CHECK-DAG: @"\01??_R1A@A@3EA@Z2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUZ2@@@8" to i8*), i32 0, i32 0, i32 0, i32 4, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3Z2@@8" }, comdat
-// CHECK-DAG: @"\01??_R13A@3EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUY2@@@8" to i8*), i32 0, i32 4, i32 0, i32 4, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3Y2@@8" }, comdat
-// CHECK-DAG: @"\01??_R4B2@@6BY2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 12, i32 8, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUB2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3B2@@8" }, comdat
-// CHECK-DAG: @"\01??_R4A2@@6BZ2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUA2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3A2@@8" }, comdat
-// CHECK-DAG: @"\01??_R4A2@@6BY2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 4, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUA2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3A2@@8" }, comdat
-// CHECK-DAG: @"\01??_R4Y2@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUY2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3Y2@@8" }, comdat
-// CHECK-DAG: @"\01??_R4Z2@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUZ2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3Z2@@8" }, comdat
-// CHECK-DAG: @"\01??_R4B1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 8, i32 4, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUB1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3B1@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AUB1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUB1@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3B1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, %rtti.BaseClassDescriptor** getelementptr inbounds ([3 x %rtti.BaseClassDescriptor*], [3 x %rtti.BaseClassDescriptor*]* @"\01??_R2B1@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2B1@@8" = linkonce_odr constant [3 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@B1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@A1@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@B1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUB1@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3B1@@8" }, comdat
-// CHECK-DAG: @"\01??_R1A@A@3FA@A1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUA1@@@8" to i8*), i32 0, i32 0, i32 0, i32 4, i32 80, %rtti.ClassHierarchyDescriptor* @"\01??_R3A1@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AUA1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUA1@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3A1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*], [2 x %rtti.BaseClassDescriptor*]* @"\01??_R2A1@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2A1@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@A1@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@A1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUA1@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3A1@@8" }, comdat
-// CHECK-DAG: @"\01??_R4A1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUA1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3A1@@8" }, comdat
-// CHECK-DAG: @"\01??_R4Y1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 4, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUY1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3Y1@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AUY1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUY1@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3Y1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 6, %rtti.BaseClassDescriptor** getelementptr inbounds ([7 x %rtti.BaseClassDescriptor*], [7 x %rtti.BaseClassDescriptor*]* @"\01??_R2Y1@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2Y1@@8" = linkonce_odr constant [7 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Y1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@W1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@V1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3EA@X1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@V1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3EA@X1@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@Y1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUY1@@@8" to i8*), i32 5, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3Y1@@8" }, comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@W1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUW1@@@8" to i8*), i32 2, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3W1@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AUW1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUW1@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3W1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 3, %rtti.BaseClassDescriptor** getelementptr inbounds ([4 x %rtti.BaseClassDescriptor*], [4 x %rtti.BaseClassDescriptor*]* @"\01??_R2W1@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2W1@@8" = linkonce_odr constant [4 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@W1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@V1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3EA@X1@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@A@3FA@V1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUV1@@@8" to i8*), i32 1, i32 0, i32 0, i32 4, i32 80, %rtti.ClassHierarchyDescriptor* @"\01??_R3V1@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AUV1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUV1@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3V1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, %rtti.BaseClassDescriptor** getelementptr inbounds ([3 x %rtti.BaseClassDescriptor*], [3 x %rtti.BaseClassDescriptor*]* @"\01??_R2V1@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2V1@@8" = linkonce_odr constant [3 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@V1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@X1@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@V1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUV1@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3V1@@8" }, comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@X1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUX1@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3X1@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AUX1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUX1@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3X1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*], [2 x %rtti.BaseClassDescriptor*]* @"\01??_R2X1@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2X1@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@X1@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@A@3EA@X1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUX1@@@8" to i8*), i32 0, i32 0, i32 0, i32 4, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3X1@@8" }, comdat
-// CHECK-DAG: @"\01??_R4W1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 4, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUW1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3W1@@8" }, comdat
-// CHECK-DAG: @"\01??_R4V1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUV1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3V1@@8" }, comdat
-// CHECK-DAG: @"\01??_R4X1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUX1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3X1@@8" }, comdat
-// CHECK-DAG: @"\01??_R4C@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUC@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3C@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AUC@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUC@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3C@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 3, %rtti.BaseClassDescriptor** getelementptr inbounds ([4 x %rtti.BaseClassDescriptor*], [4 x %rtti.BaseClassDescriptor*]* @"\01??_R2C@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2C@@8" = linkonce_odr constant [4 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@C@@8", %rtti.BaseClassDescriptor* @"\01??_R13?0A@EA@B@@8", %rtti.BaseClassDescriptor* @"\01??_R13?0A@EA@A@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@C@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUC@@@8" to i8*), i32 2, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3C@@8" }, comdat
-// CHECK-DAG: @"\01??_R13?0A@EA@B@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8" to i8*), i32 1, i32 4, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3B@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AUB@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUB@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3B@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, %rtti.BaseClassDescriptor** getelementptr inbounds ([3 x %rtti.BaseClassDescriptor*], [3 x %rtti.BaseClassDescriptor*]* @"\01??_R2B@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2B@@8" = linkonce_odr constant [3 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@B@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@A@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@B@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3B@@8" }, comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@A@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3A@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AUA@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUA@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3A@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*], [2 x %rtti.BaseClassDescriptor*]* @"\01??_R2A@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2A@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@A@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R13?0A@EA@A@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8" to i8*), i32 0, i32 4, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3A@@8" }, comdat
-// CHECK-DAG: @"\01??_R4Y@@6BZ@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVY@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3Y@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AVY@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVY@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3Y@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 9, %rtti.BaseClassDescriptor** getelementptr inbounds ([10 x %rtti.BaseClassDescriptor*], [10 x %rtti.BaseClassDescriptor*]* @"\01??_R2Y@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2Y@@8" = linkonce_odr constant [10 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Y@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EN@Z@@8", %rtti.BaseClassDescriptor* @"\01??_R13?0A@EN@W@@8", %rtti.BaseClassDescriptor* @"\01??_R17?0A@EN@M@@8", %rtti.BaseClassDescriptor* @"\01??_R17?0A@EN@N@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@33FN@V@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@33EJ@X@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@33FN@V@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@33EJ@X@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@Y@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVY@@@8" to i8*), i32 8, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3Y@@8" }, comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EN@Z@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVZ@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"\01??_R3Z@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AVZ@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVZ@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3Z@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*], [2 x %rtti.BaseClassDescriptor*]* @"\01??_R2Z@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2Z@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Z@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@Z@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVZ@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3Z@@8" }, comdat
-// CHECK-DAG: @"\01??_R13?0A@EN@W@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVW@@@8" to i8*), i32 4, i32 4, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"\01??_R3W@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AVW@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVW@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3W@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 5, %rtti.BaseClassDescriptor** getelementptr inbounds ([6 x %rtti.BaseClassDescriptor*], [6 x %rtti.BaseClassDescriptor*]* @"\01??_R2W@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2W@@8" = linkonce_odr constant [6 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@W@@8", %rtti.BaseClassDescriptor* @"\01??_R13?0A@EN@M@@8", %rtti.BaseClassDescriptor* @"\01??_R13?0A@EN@N@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3FN@V@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3EJ@X@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@W@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVW@@@8" to i8*), i32 4, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3W@@8" }, comdat
-// CHECK-DAG: @"\01??_R13?0A@EN@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUM@@@8" to i8*), i32 1, i32 4, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"\01??_R3M@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AUM@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUM@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3M@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, %rtti.BaseClassDescriptor** getelementptr inbounds ([3 x %rtti.BaseClassDescriptor*], [3 x %rtti.BaseClassDescriptor*]* @"\01??_R2M@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2M@@8" = linkonce_odr constant [3 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@M@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EN@N@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUM@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3M@@8" }, comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUN@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"\01??_R3N@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AUN@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUN@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3N@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*], [2 x %rtti.BaseClassDescriptor*]* @"\01??_R2N@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2N@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@N@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUN@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3N@@8" }, comdat
-// CHECK-DAG: @"\01??_R13?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUN@@@8" to i8*), i32 0, i32 4, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"\01??_R3N@@8" }, comdat
-// CHECK-DAG: @"\01??_R1A@A@3FN@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVV@@@8" to i8*), i32 1, i32 0, i32 0, i32 4, i32 93, %rtti.ClassHierarchyDescriptor* @"\01??_R3V@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AVV@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVV@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3V@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, %rtti.BaseClassDescriptor** getelementptr inbounds ([3 x %rtti.BaseClassDescriptor*], [3 x %rtti.BaseClassDescriptor*]* @"\01??_R2V@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2V@@8" = linkonce_odr constant [3 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@V@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@X@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVV@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3V@@8" }, comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUX@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3X@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AUX@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUX@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3X@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*], [2 x %rtti.BaseClassDescriptor*]* @"\01??_R2X@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2X@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@X@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@A@3EJ@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUX@@@8" to i8*), i32 0, i32 0, i32 0, i32 4, i32 73, %rtti.ClassHierarchyDescriptor* @"\01??_R3X@@8" }, comdat
-// CHECK-DAG: @"\01??_R17?0A@EN@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUM@@@8" to i8*), i32 1, i32 8, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"\01??_R3M@@8" }, comdat
-// CHECK-DAG: @"\01??_R17?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUN@@@8" to i8*), i32 0, i32 8, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"\01??_R3N@@8" }, comdat
-// CHECK-DAG: @"\01??_R1A@33FN@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVV@@@8" to i8*), i32 1, i32 0, i32 4, i32 4, i32 93, %rtti.ClassHierarchyDescriptor* @"\01??_R3V@@8" }, comdat
-// CHECK-DAG: @"\01??_R1A@33EJ@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUX@@@8" to i8*), i32 0, i32 0, i32 4, i32 4, i32 73, %rtti.ClassHierarchyDescriptor* @"\01??_R3X@@8" }, comdat
-// CHECK-DAG: @"\01??_R4Y@@6BW@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 8, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVY@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3Y@@8" }, comdat
-// CHECK-DAG: @"\01??_R4W@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 4, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVW@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3W@@8" }, comdat
-// CHECK-DAG: @"\01??_R4Z@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVZ@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3Z@@8" }, comdat
-// CHECK-DAG: @"\01??_R4V@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVV@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3V@@8" }, comdat
-// CHECK-DAG: @"\01??_R4X@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUX@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3X@@8" }, comdat
+// CHECK-DAG: @"??_R4B2@@6BZ2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 8, i32 4, i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUB2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3B2@@8" }, comdat
+// CHECK-DAG: @"??_R0?AUB2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUB2@@\00" }, comdat
+// CHECK-DAG: @"??_R3B2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 4, %rtti.BaseClassDescriptor** getelementptr inbounds ([5 x %rtti.BaseClassDescriptor*], [5 x %rtti.BaseClassDescriptor*]* @"??_R2B2@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2B2@@8" = linkonce_odr constant [5 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@B2@@8", %rtti.BaseClassDescriptor* @"??_R1A@A@3FA@A2@@8", %rtti.BaseClassDescriptor* @"??_R1A@A@3EA@Z2@@8", %rtti.BaseClassDescriptor* @"??_R13A@3EA@Y2@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@B2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUB2@@@8" to i8*), i32 3, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3B2@@8" }, comdat
+// CHECK-DAG: @"??_R1A@A@3FA@A2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUA2@@@8" to i8*), i32 2, i32 0, i32 0, i32 4, i32 80, %rtti.ClassHierarchyDescriptor* @"??_R3A2@@8" }, comdat
+// CHECK-DAG: @"??_R0?AUA2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUA2@@\00" }, comdat
+// CHECK-DAG: @"??_R3A2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 1, i32 3, %rtti.BaseClassDescriptor** getelementptr inbounds ([4 x %rtti.BaseClassDescriptor*], [4 x %rtti.BaseClassDescriptor*]* @"??_R2A2@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2A2@@8" = linkonce_odr constant [4 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@A2@@8", %rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@Z2@@8", %rtti.BaseClassDescriptor* @"??_R13?0A@EA@Y2@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@A2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUA2@@@8" to i8*), i32 2, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3A2@@8" }, comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@Z2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUZ2@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3Z2@@8" }, comdat
+// CHECK-DAG: @"??_R0?AUZ2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUZ2@@\00" }, comdat
+// CHECK-DAG: @"??_R3Z2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*], [2 x %rtti.BaseClassDescriptor*]* @"??_R2Z2@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2Z2@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@Z2@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R13?0A@EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUY2@@@8" to i8*), i32 0, i32 4, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3Y2@@8" }, comdat
+// CHECK-DAG: @"??_R0?AUY2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUY2@@\00" }, comdat
+// CHECK-DAG: @"??_R3Y2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*], [2 x %rtti.BaseClassDescriptor*]* @"??_R2Y2@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2Y2@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@Y2@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUY2@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3Y2@@8" }, comdat
+// CHECK-DAG: @"??_R1A@A@3EA@Z2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUZ2@@@8" to i8*), i32 0, i32 0, i32 0, i32 4, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3Z2@@8" }, comdat
+// CHECK-DAG: @"??_R13A@3EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUY2@@@8" to i8*), i32 0, i32 4, i32 0, i32 4, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3Y2@@8" }, comdat
+// CHECK-DAG: @"??_R4B2@@6BY2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 12, i32 8, i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUB2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3B2@@8" }, comdat
+// CHECK-DAG: @"??_R4A2@@6BZ2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUA2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3A2@@8" }, comdat
+// CHECK-DAG: @"??_R4A2@@6BY2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 4, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUA2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3A2@@8" }, comdat
+// CHECK-DAG: @"??_R4Y2@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUY2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3Y2@@8" }, comdat
+// CHECK-DAG: @"??_R4Z2@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUZ2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3Z2@@8" }, comdat
+// CHECK-DAG: @"??_R4B1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 8, i32 4, i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUB1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3B1@@8" }, comdat
+// CHECK-DAG: @"??_R0?AUB1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUB1@@\00" }, comdat
+// CHECK-DAG: @"??_R3B1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, %rtti.BaseClassDescriptor** getelementptr inbounds ([3 x %rtti.BaseClassDescriptor*], [3 x %rtti.BaseClassDescriptor*]* @"??_R2B1@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2B1@@8" = linkonce_odr constant [3 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@B1@@8", %rtti.BaseClassDescriptor* @"??_R1A@A@3FA@A1@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@B1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUB1@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3B1@@8" }, comdat
+// CHECK-DAG: @"??_R1A@A@3FA@A1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUA1@@@8" to i8*), i32 0, i32 0, i32 0, i32 4, i32 80, %rtti.ClassHierarchyDescriptor* @"??_R3A1@@8" }, comdat
+// CHECK-DAG: @"??_R0?AUA1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUA1@@\00" }, comdat
+// CHECK-DAG: @"??_R3A1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*], [2 x %rtti.BaseClassDescriptor*]* @"??_R2A1@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2A1@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@A1@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@A1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUA1@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3A1@@8" }, comdat
+// CHECK-DAG: @"??_R4A1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUA1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3A1@@8" }, comdat
+// CHECK-DAG: @"??_R4Y1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 4, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUY1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3Y1@@8" }, comdat
+// CHECK-DAG: @"??_R0?AUY1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUY1@@\00" }, comdat
+// CHECK-DAG: @"??_R3Y1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 6, %rtti.BaseClassDescriptor** getelementptr inbounds ([7 x %rtti.BaseClassDescriptor*], [7 x %rtti.BaseClassDescriptor*]* @"??_R2Y1@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2Y1@@8" = linkonce_odr constant [7 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@Y1@@8", %rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@W1@@8", %rtti.BaseClassDescriptor* @"??_R1A@A@3FA@V1@@8", %rtti.BaseClassDescriptor* @"??_R1A@A@3EA@X1@@8", %rtti.BaseClassDescriptor* @"??_R1A@A@3FA@V1@@8", %rtti.BaseClassDescriptor* @"??_R1A@A@3EA@X1@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@Y1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUY1@@@8" to i8*), i32 5, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3Y1@@8" }, comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@W1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUW1@@@8" to i8*), i32 2, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3W1@@8" }, comdat
+// CHECK-DAG: @"??_R0?AUW1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUW1@@\00" }, comdat
+// CHECK-DAG: @"??_R3W1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 3, %rtti.BaseClassDescriptor** getelementptr inbounds ([4 x %rtti.BaseClassDescriptor*], [4 x %rtti.BaseClassDescriptor*]* @"??_R2W1@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2W1@@8" = linkonce_odr constant [4 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@W1@@8", %rtti.BaseClassDescriptor* @"??_R1A@A@3FA@V1@@8", %rtti.BaseClassDescriptor* @"??_R1A@A@3EA@X1@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@A@3FA@V1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUV1@@@8" to i8*), i32 1, i32 0, i32 0, i32 4, i32 80, %rtti.ClassHierarchyDescriptor* @"??_R3V1@@8" }, comdat
+// CHECK-DAG: @"??_R0?AUV1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUV1@@\00" }, comdat
+// CHECK-DAG: @"??_R3V1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, %rtti.BaseClassDescriptor** getelementptr inbounds ([3 x %rtti.BaseClassDescriptor*], [3 x %rtti.BaseClassDescriptor*]* @"??_R2V1@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2V1@@8" = linkonce_odr constant [3 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@V1@@8", %rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@X1@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@V1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUV1@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3V1@@8" }, comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@X1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUX1@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3X1@@8" }, comdat
+// CHECK-DAG: @"??_R0?AUX1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUX1@@\00" }, comdat
+// CHECK-DAG: @"??_R3X1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*], [2 x %rtti.BaseClassDescriptor*]* @"??_R2X1@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2X1@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@X1@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@A@3EA@X1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUX1@@@8" to i8*), i32 0, i32 0, i32 0, i32 4, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3X1@@8" }, comdat
+// CHECK-DAG: @"??_R4W1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 4, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUW1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3W1@@8" }, comdat
+// CHECK-DAG: @"??_R4V1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUV1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3V1@@8" }, comdat
+// CHECK-DAG: @"??_R4X1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUX1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3X1@@8" }, comdat
+// CHECK-DAG: @"??_R4C@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUC@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3C@@8" }, comdat
+// CHECK-DAG: @"??_R0?AUC@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUC@@\00" }, comdat
+// CHECK-DAG: @"??_R3C@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 3, %rtti.BaseClassDescriptor** getelementptr inbounds ([4 x %rtti.BaseClassDescriptor*], [4 x %rtti.BaseClassDescriptor*]* @"??_R2C@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2C@@8" = linkonce_odr constant [4 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@C@@8", %rtti.BaseClassDescriptor* @"??_R13?0A@EA@B@@8", %rtti.BaseClassDescriptor* @"??_R13?0A@EA@A@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@C@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUC@@@8" to i8*), i32 2, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3C@@8" }, comdat
+// CHECK-DAG: @"??_R13?0A@EA@B@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUB@@@8" to i8*), i32 1, i32 4, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3B@@8" }, comdat
+// CHECK-DAG: @"??_R0?AUB@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUB@@\00" }, comdat
+// CHECK-DAG: @"??_R3B@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, %rtti.BaseClassDescriptor** getelementptr inbounds ([3 x %rtti.BaseClassDescriptor*], [3 x %rtti.BaseClassDescriptor*]* @"??_R2B@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2B@@8" = linkonce_odr constant [3 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@B@@8", %rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@A@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@B@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUB@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3B@@8" }, comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@A@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUA@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3A@@8" }, comdat
+// CHECK-DAG: @"??_R0?AUA@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUA@@\00" }, comdat
+// CHECK-DAG: @"??_R3A@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*], [2 x %rtti.BaseClassDescriptor*]* @"??_R2A@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2A@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@A@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R13?0A@EA@A@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUA@@@8" to i8*), i32 0, i32 4, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3A@@8" }, comdat
+// CHECK-DAG: @"??_R4Y@@6BZ@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AVY@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3Y@@8" }, comdat
+// CHECK-DAG: @"??_R0?AVY@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AVY@@\00" }, comdat
+// CHECK-DAG: @"??_R3Y@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 9, %rtti.BaseClassDescriptor** getelementptr inbounds ([10 x %rtti.BaseClassDescriptor*], [10 x %rtti.BaseClassDescriptor*]* @"??_R2Y@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2Y@@8" = linkonce_odr constant [10 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@Y@@8", %rtti.BaseClassDescriptor* @"??_R1A@?0A@EN@Z@@8", %rtti.BaseClassDescriptor* @"??_R13?0A@EN@W@@8", %rtti.BaseClassDescriptor* @"??_R17?0A@EN@M@@8", %rtti.BaseClassDescriptor* @"??_R17?0A@EN@N@@8", %rtti.BaseClassDescriptor* @"??_R1A@33FN@V@@8", %rtti.BaseClassDescriptor* @"??_R1A@33EJ@X@@8", %rtti.BaseClassDescriptor* @"??_R1A@33FN@V@@8", %rtti.BaseClassDescriptor* @"??_R1A@33EJ@X@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@Y@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AVY@@@8" to i8*), i32 8, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3Y@@8" }, comdat
+// CHECK-DAG: @"??_R1A@?0A@EN@Z@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AVZ@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"??_R3Z@@8" }, comdat
+// CHECK-DAG: @"??_R0?AVZ@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AVZ@@\00" }, comdat
+// CHECK-DAG: @"??_R3Z@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*], [2 x %rtti.BaseClassDescriptor*]* @"??_R2Z@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2Z@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@Z@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@Z@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AVZ@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3Z@@8" }, comdat
+// CHECK-DAG: @"??_R13?0A@EN@W@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AVW@@@8" to i8*), i32 4, i32 4, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"??_R3W@@8" }, comdat
+// CHECK-DAG: @"??_R0?AVW@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AVW@@\00" }, comdat
+// CHECK-DAG: @"??_R3W@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 5, %rtti.BaseClassDescriptor** getelementptr inbounds ([6 x %rtti.BaseClassDescriptor*], [6 x %rtti.BaseClassDescriptor*]* @"??_R2W@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2W@@8" = linkonce_odr constant [6 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@W@@8", %rtti.BaseClassDescriptor* @"??_R13?0A@EN@M@@8", %rtti.BaseClassDescriptor* @"??_R13?0A@EN@N@@8", %rtti.BaseClassDescriptor* @"??_R1A@A@3FN@V@@8", %rtti.BaseClassDescriptor* @"??_R1A@A@3EJ@X@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@W@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AVW@@@8" to i8*), i32 4, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3W@@8" }, comdat
+// CHECK-DAG: @"??_R13?0A@EN@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUM@@@8" to i8*), i32 1, i32 4, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"??_R3M@@8" }, comdat
+// CHECK-DAG: @"??_R0?AUM@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUM@@\00" }, comdat
+// CHECK-DAG: @"??_R3M@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, %rtti.BaseClassDescriptor** getelementptr inbounds ([3 x %rtti.BaseClassDescriptor*], [3 x %rtti.BaseClassDescriptor*]* @"??_R2M@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2M@@8" = linkonce_odr constant [3 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@M@@8", %rtti.BaseClassDescriptor* @"??_R1A@?0A@EN@N@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUM@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3M@@8" }, comdat
+// CHECK-DAG: @"??_R1A@?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUN@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"??_R3N@@8" }, comdat
+// CHECK-DAG: @"??_R0?AUN@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUN@@\00" }, comdat
+// CHECK-DAG: @"??_R3N@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*], [2 x %rtti.BaseClassDescriptor*]* @"??_R2N@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2N@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@N@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUN@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3N@@8" }, comdat
+// CHECK-DAG: @"??_R13?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUN@@@8" to i8*), i32 0, i32 4, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"??_R3N@@8" }, comdat
+// CHECK-DAG: @"??_R1A@A@3FN@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AVV@@@8" to i8*), i32 1, i32 0, i32 0, i32 4, i32 93, %rtti.ClassHierarchyDescriptor* @"??_R3V@@8" }, comdat
+// CHECK-DAG: @"??_R0?AVV@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AVV@@\00" }, comdat
+// CHECK-DAG: @"??_R3V@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, %rtti.BaseClassDescriptor** getelementptr inbounds ([3 x %rtti.BaseClassDescriptor*], [3 x %rtti.BaseClassDescriptor*]* @"??_R2V@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2V@@8" = linkonce_odr constant [3 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@V@@8", %rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@X@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AVV@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3V@@8" }, comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUX@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3X@@8" }, comdat
+// CHECK-DAG: @"??_R0?AUX@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUX@@\00" }, comdat
+// CHECK-DAG: @"??_R3X@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*], [2 x %rtti.BaseClassDescriptor*]* @"??_R2X@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2X@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@X@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@A@3EJ@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUX@@@8" to i8*), i32 0, i32 0, i32 0, i32 4, i32 73, %rtti.ClassHierarchyDescriptor* @"??_R3X@@8" }, comdat
+// CHECK-DAG: @"??_R17?0A@EN@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUM@@@8" to i8*), i32 1, i32 8, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"??_R3M@@8" }, comdat
+// CHECK-DAG: @"??_R17?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUN@@@8" to i8*), i32 0, i32 8, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"??_R3N@@8" }, comdat
+// CHECK-DAG: @"??_R1A@33FN@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AVV@@@8" to i8*), i32 1, i32 0, i32 4, i32 4, i32 93, %rtti.ClassHierarchyDescriptor* @"??_R3V@@8" }, comdat
+// CHECK-DAG: @"??_R1A@33EJ@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUX@@@8" to i8*), i32 0, i32 0, i32 4, i32 4, i32 73, %rtti.ClassHierarchyDescriptor* @"??_R3X@@8" }, comdat
+// CHECK-DAG: @"??_R4Y@@6BW@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 8, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AVY@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3Y@@8" }, comdat
+// CHECK-DAG: @"??_R4W@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 4, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AVW@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3W@@8" }, comdat
+// CHECK-DAG: @"??_R4Z@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AVZ@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3Z@@8" }, comdat
+// CHECK-DAG: @"??_R4V@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AVV@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3V@@8" }, comdat
+// CHECK-DAG: @"??_R4X@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUX@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3X@@8" }, comdat
-// X64-DAG: @"\01??_R4B2@@6BZ2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 16, i32 4, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUB2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3B2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4B2@@6BZ2@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AUB2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUB2@@\00" }, comdat
-// X64-DAG: @"\01??_R3B2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 4, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([5 x i32]* @"\01??_R2B2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2B2@@8" = linkonce_odr constant [5 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@B2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3EA@Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R17A@3EA@Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@B2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUB2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 3, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3B2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R1A@A@3FA@A2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUA2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 2, i32 0, i32 0, i32 4, i32 80, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AUA2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUA2@@\00" }, comdat
-// X64-DAG: @"\01??_R3A2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 1, i32 3, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([4 x i32]* @"\01??_R2A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2A2@@8" = linkonce_odr constant [4 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R17?0A@EA@Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@A2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUA2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 2, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@Z2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUZ2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AUZ2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUZ2@@\00" }, comdat
-// X64-DAG: @"\01??_R3Z2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"\01??_R2Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2Z2@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R17?0A@EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUY2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 8, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AUY2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUY2@@\00" }, comdat
-// X64-DAG: @"\01??_R3Y2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"\01??_R2Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2Y2@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUY2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R1A@A@3EA@Z2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUZ2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 0, i32 4, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R17A@3EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUY2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 8, i32 0, i32 4, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4B2@@6BY2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 24, i32 12, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUB2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3B2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4B2@@6BY2@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4A2@@6BZ2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUA2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4A2@@6BZ2@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4A2@@6BY2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 8, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUA2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4A2@@6BY2@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4Y2@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUY2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4Y2@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4Z2@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUZ2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4Z2@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4B1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 16, i32 4, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUB1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3B1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4B1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AUB1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUB1@@\00" }, comdat
-// X64-DAG: @"\01??_R3B1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([3 x i32]* @"\01??_R2B1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2B1@@8" = linkonce_odr constant [3 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@B1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@B1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUB1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3B1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R1A@A@3FA@A1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUA1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 0, i32 4, i32 80, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AUA1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUA1@@\00" }, comdat
-// X64-DAG: @"\01??_R3A1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"\01??_R2A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2A1@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@A1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUA1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4A1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUA1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4A1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4Y1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 8, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUY1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4Y1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AUY1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUY1@@\00" }, comdat
-// X64-DAG: @"\01??_R3Y1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 6, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([7 x i32]* @"\01??_R2Y1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2Y1@@8" = linkonce_odr constant [7 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Y1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@W1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3EA@X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3EA@X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@Y1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUY1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 5, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@W1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUW1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 2, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3W1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AUW1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUW1@@\00" }, comdat
-// X64-DAG: @"\01??_R3W1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 3, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([4 x i32]* @"\01??_R2W1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2W1@@8" = linkonce_odr constant [4 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@W1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3EA@X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@A@3FA@V1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUV1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 0, i32 4, i32 80, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AUV1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUV1@@\00" }, comdat
-// X64-DAG: @"\01??_R3V1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([3 x i32]* @"\01??_R2V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2V1@@8" = linkonce_odr constant [3 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@V1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUV1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@X1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUX1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AUX1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUX1@@\00" }, comdat
-// X64-DAG: @"\01??_R3X1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"\01??_R2X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2X1@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@A@3EA@X1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUX1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 0, i32 4, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4W1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 8, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUW1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3W1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4W1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4V1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUV1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4V1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4X1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUX1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4X1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4C@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUC@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3C@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4C@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AUC@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUC@@\00" }, comdat
-// X64-DAG: @"\01??_R3C@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 3, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([4 x i32]* @"\01??_R2C@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2C@@8" = linkonce_odr constant [4 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@C@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R17?0A@EA@B@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R17?0A@EA@A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@C@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUC@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 2, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3C@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R17?0A@EA@B@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 8, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3B@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AUB@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUB@@\00" }, comdat
-// X64-DAG: @"\01??_R3B@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([3 x i32]* @"\01??_R2B@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2B@@8" = linkonce_odr constant [3 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@B@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@B@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3B@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@A@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AUA@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUA@@\00" }, comdat
-// X64-DAG: @"\01??_R3A@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"\01??_R2A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2A@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R17?0A@EA@A@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 8, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4Y@@6BZ@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVY@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4Y@@6BZ@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AVY@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVY@@\00" }, comdat
-// X64-DAG: @"\01??_R3Y@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 9, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([10 x i32]* @"\01??_R2Y@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2Y@@8" = linkonce_odr constant [10 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Y@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EN@Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R17?0A@EN@W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1BA@?0A@EN@M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1BA@?0A@EN@N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@73FN@V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@73EJ@X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@73FN@V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@73EJ@X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@Y@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVY@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 8, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R1A@?0A@EN@Z@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVZ@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AVZ@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVZ@@\00" }, comdat
-// X64-DAG: @"\01??_R3Z@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"\01??_R2Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2Z@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@Z@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVZ@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R17?0A@EN@W@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVW@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 4, i32 8, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AVW@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVW@@\00" }, comdat
-// X64-DAG: @"\01??_R3W@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 5, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([6 x i32]* @"\01??_R2W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2W@@8" = linkonce_odr constant [6 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R17?0A@EN@M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R17?0A@EN@N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3FN@V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3EJ@X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@W@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVW@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 4, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R17?0A@EN@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUM@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 8, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AUM@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUM@@\00" }, comdat
-// X64-DAG: @"\01??_R3M@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([3 x i32]* @"\01??_R2M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2M@@8" = linkonce_odr constant [3 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EN@N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUM@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R1A@?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUN@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AUN@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUN@@\00" }, comdat
-// X64-DAG: @"\01??_R3N@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"\01??_R2N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2N@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUN@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R17?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUN@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 8, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R1A@A@3FN@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVV@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 0, i32 4, i32 93, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AVV@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVV@@\00" }, comdat
-// X64-DAG: @"\01??_R3V@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([3 x i32]* @"\01??_R2V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2V@@8" = linkonce_odr constant [3 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVV@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUX@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AUX@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUX@@\00" }, comdat
-// X64-DAG: @"\01??_R3X@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"\01??_R2X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2X@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@A@3EJ@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUX@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 0, i32 4, i32 73, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R1BA@?0A@EN@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUM@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 16, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R1BA@?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUN@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 16, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R1A@73FN@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVV@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 8, i32 4, i32 93, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R1A@73EJ@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUX@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 8, i32 4, i32 73, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4Y@@6BW@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 16, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVY@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4Y@@6BW@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4W@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 8, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVW@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4W@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4Z@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVZ@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4Z@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4V@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVV@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4V@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4X@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUX@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4X@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4B2@@6BZ2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 16, i32 4, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUB2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3B2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4B2@@6BZ2@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AUB2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUB2@@\00" }, comdat
+// X64-DAG: @"??_R3B2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 4, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([5 x i32]* @"??_R2B2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2B2@@8" = linkonce_odr constant [5 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@B2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@A@3FA@A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@A@3EA@Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R17A@3EA@Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@?0A@EA@B2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUB2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 3, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3B2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R1A@A@3FA@A2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUA2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 2, i32 0, i32 0, i32 4, i32 80, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AUA2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUA2@@\00" }, comdat
+// X64-DAG: @"??_R3A2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 1, i32 3, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([4 x i32]* @"??_R2A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2A2@@8" = linkonce_odr constant [4 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R17?0A@EA@Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@?0A@EA@A2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUA2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 2, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R1A@?0A@EA@Z2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUZ2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AUZ2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUZ2@@\00" }, comdat
+// X64-DAG: @"??_R3Z2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"??_R2Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2Z2@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R17?0A@EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUY2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 8, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AUY2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUY2@@\00" }, comdat
+// X64-DAG: @"??_R3Y2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"??_R2Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2Y2@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@?0A@EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUY2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R1A@A@3EA@Z2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUZ2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 0, i32 4, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R17A@3EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUY2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 8, i32 0, i32 4, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4B2@@6BY2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 24, i32 12, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUB2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3B2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4B2@@6BY2@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4A2@@6BZ2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUA2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4A2@@6BZ2@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4A2@@6BY2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 8, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUA2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4A2@@6BY2@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4Y2@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUY2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4Y2@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4Z2@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUZ2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4Z2@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4B1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 16, i32 4, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUB1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3B1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4B1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AUB1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUB1@@\00" }, comdat
+// X64-DAG: @"??_R3B1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([3 x i32]* @"??_R2B1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2B1@@8" = linkonce_odr constant [3 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@B1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@A@3FA@A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@?0A@EA@B1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUB1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3B1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R1A@A@3FA@A1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUA1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 0, i32 4, i32 80, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AUA1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUA1@@\00" }, comdat
+// X64-DAG: @"??_R3A1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"??_R2A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2A1@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@?0A@EA@A1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUA1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4A1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUA1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4A1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4Y1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 8, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUY1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3Y1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4Y1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AUY1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUY1@@\00" }, comdat
+// X64-DAG: @"??_R3Y1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 6, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([7 x i32]* @"??_R2Y1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2Y1@@8" = linkonce_odr constant [7 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@Y1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@W1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@A@3FA@V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@A@3EA@X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@A@3FA@V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@A@3EA@X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@?0A@EA@Y1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUY1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 5, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3Y1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R1A@?0A@EA@W1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUW1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 2, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3W1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AUW1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUW1@@\00" }, comdat
+// X64-DAG: @"??_R3W1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 3, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([4 x i32]* @"??_R2W1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2W1@@8" = linkonce_odr constant [4 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@W1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@A@3FA@V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@A@3EA@X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@A@3FA@V1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUV1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 0, i32 4, i32 80, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AUV1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUV1@@\00" }, comdat
+// X64-DAG: @"??_R3V1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([3 x i32]* @"??_R2V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2V1@@8" = linkonce_odr constant [3 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@?0A@EA@V1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUV1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R1A@?0A@EA@X1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUX1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AUX1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUX1@@\00" }, comdat
+// X64-DAG: @"??_R3X1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"??_R2X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2X1@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@A@3EA@X1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUX1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 0, i32 4, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4W1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 8, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUW1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3W1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4W1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4V1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUV1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4V1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4X1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUX1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4X1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4C@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUC@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3C@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4C@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AUC@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUC@@\00" }, comdat
+// X64-DAG: @"??_R3C@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 3, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([4 x i32]* @"??_R2C@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2C@@8" = linkonce_odr constant [4 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@C@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R17?0A@EA@B@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R17?0A@EA@A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@?0A@EA@C@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUC@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 2, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3C@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R17?0A@EA@B@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUB@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 8, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3B@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AUB@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUB@@\00" }, comdat
+// X64-DAG: @"??_R3B@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([3 x i32]* @"??_R2B@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2B@@8" = linkonce_odr constant [3 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@B@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@?0A@EA@B@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUB@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3B@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R1A@?0A@EA@A@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUA@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AUA@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUA@@\00" }, comdat
+// X64-DAG: @"??_R3A@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"??_R2A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2A@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R17?0A@EA@A@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUA@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 8, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4Y@@6BZ@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AVY@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3Y@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4Y@@6BZ@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AVY@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AVY@@\00" }, comdat
+// X64-DAG: @"??_R3Y@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 9, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([10 x i32]* @"??_R2Y@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2Y@@8" = linkonce_odr constant [10 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@Y@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EN@Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R17?0A@EN@W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1BA@?0A@EN@M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1BA@?0A@EN@N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@73FN@V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@73EJ@X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@73FN@V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@73EJ@X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@?0A@EA@Y@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AVY@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 8, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3Y@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R1A@?0A@EN@Z@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AVZ@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AVZ@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AVZ@@\00" }, comdat
+// X64-DAG: @"??_R3Z@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"??_R2Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2Z@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@?0A@EA@Z@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AVZ@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R17?0A@EN@W@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AVW@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 4, i32 8, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AVW@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AVW@@\00" }, comdat
+// X64-DAG: @"??_R3W@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 5, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([6 x i32]* @"??_R2W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2W@@8" = linkonce_odr constant [6 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R17?0A@EN@M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R17?0A@EN@N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@A@3FN@V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@A@3EJ@X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@?0A@EA@W@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AVW@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 4, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R17?0A@EN@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUM@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 8, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AUM@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUM@@\00" }, comdat
+// X64-DAG: @"??_R3M@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([3 x i32]* @"??_R2M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2M@@8" = linkonce_odr constant [3 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EN@N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@?0A@EA@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUM@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R1A@?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUN@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AUN@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUN@@\00" }, comdat
+// X64-DAG: @"??_R3N@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"??_R2N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2N@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@?0A@EA@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUN@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R17?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUN@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 8, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R1A@A@3FN@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AVV@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 0, i32 4, i32 93, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AVV@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AVV@@\00" }, comdat
+// X64-DAG: @"??_R3V@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([3 x i32]* @"??_R2V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2V@@8" = linkonce_odr constant [3 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@?0A@EA@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AVV@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R1A@?0A@EA@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUX@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AUX@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUX@@\00" }, comdat
+// X64-DAG: @"??_R3X@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"??_R2X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2X@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@A@3EJ@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUX@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 0, i32 4, i32 73, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R1BA@?0A@EN@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUM@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 16, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R1BA@?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUN@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 16, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R1A@73FN@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AVV@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 8, i32 4, i32 93, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R1A@73EJ@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUX@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 8, i32 4, i32 73, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4Y@@6BW@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 16, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AVY@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3Y@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4Y@@6BW@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4W@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 8, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AVW@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4W@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4Z@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AVZ@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4Z@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4V@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AVV@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4V@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4X@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUX@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4X@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
diff --git a/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp b/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
index eaae3493ccdc..a910a2d7f736 100644
--- a/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
+++ b/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
@@ -2,6 +2,7 @@
// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WIN32 %s
// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=thumb-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WOA %s
// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=x86_64-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WIN64 %s
+// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=aarch64-windows-msvc -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WOA64 %s
struct Empty {};
@@ -68,7 +69,7 @@ struct BaseNoByval : Small {
int bb;
};
-// WIN32: declare void @"{{.*take_bools_and_chars.*}}"
+// WIN32: declare dso_local void @"{{.*take_bools_and_chars.*}}"
// WIN32: (<{ i8, [3 x i8], i8, [3 x i8], %struct.SmallWithDtor,
// WIN32: i8, [3 x i8], i8, [3 x i8], i32, i8, [3 x i8] }>* inalloca)
void take_bools_and_chars(char a, char b, SmallWithDtor c, char d, bool e, int f, bool g);
@@ -79,117 +80,117 @@ void call_bools_and_chars() {
// Returning structs that fit into a register.
Small small_return() { return Small(); }
// LINUX-LABEL: define void @_Z12small_returnv(%struct.Small* noalias sret %agg.result)
-// WIN32: define i32 @"\01?small_return@@YA?AUSmall@@XZ"()
-// WIN64: define i32 @"\01?small_return@@YA?AUSmall@@XZ"()
+// WIN32: define dso_local i32 @"?small_return@@YA?AUSmall@@XZ"()
+// WIN64: define dso_local i32 @"?small_return@@YA?AUSmall@@XZ"()
Medium medium_return() { return Medium(); }
// LINUX-LABEL: define void @_Z13medium_returnv(%struct.Medium* noalias sret %agg.result)
-// WIN32: define i64 @"\01?medium_return@@YA?AUMedium@@XZ"()
-// WIN64: define i64 @"\01?medium_return@@YA?AUMedium@@XZ"()
+// WIN32: define dso_local i64 @"?medium_return@@YA?AUMedium@@XZ"()
+// WIN64: define dso_local i64 @"?medium_return@@YA?AUMedium@@XZ"()
// Returning structs that fit into a register but are not POD.
SmallCpp11NotCpp03Pod small_non_pod_return() { return SmallCpp11NotCpp03Pod(); }
// LINUX-LABEL: define void @_Z20small_non_pod_returnv(%struct.SmallCpp11NotCpp03Pod* noalias sret %agg.result)
-// WIN32: define void @"\01?small_non_pod_return@@YA?AUSmallCpp11NotCpp03Pod@@XZ"(%struct.SmallCpp11NotCpp03Pod* noalias sret %agg.result)
-// WIN64: define void @"\01?small_non_pod_return@@YA?AUSmallCpp11NotCpp03Pod@@XZ"(%struct.SmallCpp11NotCpp03Pod* noalias sret %agg.result)
+// WIN32: define dso_local void @"?small_non_pod_return@@YA?AUSmallCpp11NotCpp03Pod@@XZ"(%struct.SmallCpp11NotCpp03Pod* noalias sret %agg.result)
+// WIN64: define dso_local void @"?small_non_pod_return@@YA?AUSmallCpp11NotCpp03Pod@@XZ"(%struct.SmallCpp11NotCpp03Pod* noalias sret %agg.result)
SmallWithCtor small_with_ctor_return() { return SmallWithCtor(); }
// LINUX-LABEL: define void @_Z22small_with_ctor_returnv(%struct.SmallWithCtor* noalias sret %agg.result)
-// WIN32: define void @"\01?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret %agg.result)
-// WIN64: define void @"\01?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret %agg.result)
+// WIN32: define dso_local void @"?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret %agg.result)
+// WIN64: define dso_local void @"?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret %agg.result)
// FIXME: The 'sret' mark here doesn't seem to be enough to convince LLVM to
// preserve the hidden sret pointer in R0 across the function.
-// WOA: define arm_aapcs_vfpcc void @"\01?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret %agg.result)
+// WOA: define dso_local arm_aapcs_vfpcc void @"?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret %agg.result)
SmallWithVftable small_with_vftable_return() { return SmallWithVftable(); }
// LINUX-LABEL: define void @_Z25small_with_vftable_returnv(%struct.SmallWithVftable* noalias sret %agg.result)
-// WIN32: define void @"\01?small_with_vftable_return@@YA?AUSmallWithVftable@@XZ"(%struct.SmallWithVftable* noalias sret %agg.result)
-// WIN64: define void @"\01?small_with_vftable_return@@YA?AUSmallWithVftable@@XZ"(%struct.SmallWithVftable* noalias sret %agg.result)
+// WIN32: define dso_local void @"?small_with_vftable_return@@YA?AUSmallWithVftable@@XZ"(%struct.SmallWithVftable* noalias sret %agg.result)
+// WIN64: define dso_local void @"?small_with_vftable_return@@YA?AUSmallWithVftable@@XZ"(%struct.SmallWithVftable* noalias sret %agg.result)
MediumWithCopyCtor medium_with_copy_ctor_return() { return MediumWithCopyCtor(); }
// LINUX-LABEL: define void @_Z28medium_with_copy_ctor_returnv(%struct.MediumWithCopyCtor* noalias sret %agg.result)
-// WIN32: define void @"\01?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(%struct.MediumWithCopyCtor* noalias sret %agg.result)
-// WIN64: define void @"\01?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(%struct.MediumWithCopyCtor* noalias sret %agg.result)
-// WOA: define arm_aapcs_vfpcc void @"\01?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(%struct.MediumWithCopyCtor* noalias sret %agg.result)
+// WIN32: define dso_local void @"?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(%struct.MediumWithCopyCtor* noalias sret %agg.result)
+// WIN64: define dso_local void @"?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(%struct.MediumWithCopyCtor* noalias sret %agg.result)
+// WOA: define dso_local arm_aapcs_vfpcc void @"?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(%struct.MediumWithCopyCtor* noalias sret %agg.result)
// Returning a large struct that doesn't fit into a register.
Big big_return() { return Big(); }
// LINUX-LABEL: define void @_Z10big_returnv(%struct.Big* noalias sret %agg.result)
-// WIN32: define void @"\01?big_return@@YA?AUBig@@XZ"(%struct.Big* noalias sret %agg.result)
-// WIN64: define void @"\01?big_return@@YA?AUBig@@XZ"(%struct.Big* noalias sret %agg.result)
+// WIN32: define dso_local void @"?big_return@@YA?AUBig@@XZ"(%struct.Big* noalias sret %agg.result)
+// WIN64: define dso_local void @"?big_return@@YA?AUBig@@XZ"(%struct.Big* noalias sret %agg.result)
void small_arg(Small s) {}
// LINUX-LABEL: define void @_Z9small_arg5Small(i32 %s.0)
-// WIN32: define void @"\01?small_arg@@YAXUSmall@@@Z"(i32 %s.0)
-// WIN64: define void @"\01?small_arg@@YAXUSmall@@@Z"(i32 %s.coerce)
-// WOA: define arm_aapcs_vfpcc void @"\01?small_arg@@YAXUSmall@@@Z"([1 x i32] %s.coerce)
+// WIN32: define dso_local void @"?small_arg@@YAXUSmall@@@Z"(i32 %s.0)
+// WIN64: define dso_local void @"?small_arg@@YAXUSmall@@@Z"(i32 %s.coerce)
+// WOA: define dso_local arm_aapcs_vfpcc void @"?small_arg@@YAXUSmall@@@Z"([1 x i32] %s.coerce)
void medium_arg(Medium s) {}
// LINUX-LABEL: define void @_Z10medium_arg6Medium(i32 %s.0, i32 %s.1)
-// WIN32: define void @"\01?medium_arg@@YAXUMedium@@@Z"(i32 %s.0, i32 %s.1)
-// WIN64: define void @"\01?medium_arg@@YAXUMedium@@@Z"(i64 %s.coerce)
-// WOA: define arm_aapcs_vfpcc void @"\01?medium_arg@@YAXUMedium@@@Z"([2 x i32] %s.coerce)
+// WIN32: define dso_local void @"?medium_arg@@YAXUMedium@@@Z"(i32 %s.0, i32 %s.1)
+// WIN64: define dso_local void @"?medium_arg@@YAXUMedium@@@Z"(i64 %s.coerce)
+// WOA: define dso_local arm_aapcs_vfpcc void @"?medium_arg@@YAXUMedium@@@Z"([2 x i32] %s.coerce)
void base_no_byval_arg(BaseNoByval s) {}
// LINUX-LABEL: define void @_Z17base_no_byval_arg11BaseNoByval(%struct.BaseNoByval* byval align 4 %s)
-// WIN32: define void @"\01?base_no_byval_arg@@YAXUBaseNoByval@@@Z"(i32 %s.0, i32 %s.1)
-// WIN64: define void @"\01?base_no_byval_arg@@YAXUBaseNoByval@@@Z"(i64 %s.coerce)
-// WOA: define arm_aapcs_vfpcc void @"\01?base_no_byval_arg@@YAXUBaseNoByval@@@Z"([2 x i32] %s.coerce)
+// WIN32: define dso_local void @"?base_no_byval_arg@@YAXUBaseNoByval@@@Z"(i32 %s.0, i32 %s.1)
+// WIN64: define dso_local void @"?base_no_byval_arg@@YAXUBaseNoByval@@@Z"(i64 %s.coerce)
+// WOA: define dso_local arm_aapcs_vfpcc void @"?base_no_byval_arg@@YAXUBaseNoByval@@@Z"([2 x i32] %s.coerce)
void small_arg_with_ctor(SmallWithCtor s) {}
// LINUX-LABEL: define void @_Z19small_arg_with_ctor13SmallWithCtor(%struct.SmallWithCtor* byval align 4 %s)
-// WIN32: define void @"\01?small_arg_with_ctor@@YAXUSmallWithCtor@@@Z"(i32 %s.0)
-// WIN64: define void @"\01?small_arg_with_ctor@@YAXUSmallWithCtor@@@Z"(i32 %s.coerce)
-// WOA: define arm_aapcs_vfpcc void @"\01?small_arg_with_ctor@@YAXUSmallWithCtor@@@Z"([1 x i32] %s.coerce)
+// WIN32: define dso_local void @"?small_arg_with_ctor@@YAXUSmallWithCtor@@@Z"(i32 %s.0)
+// WIN64: define dso_local void @"?small_arg_with_ctor@@YAXUSmallWithCtor@@@Z"(i32 %s.coerce)
+// WOA: define dso_local arm_aapcs_vfpcc void @"?small_arg_with_ctor@@YAXUSmallWithCtor@@@Z"([1 x i32] %s.coerce)
// FIXME: We could coerce to a series of i32s here if we wanted to.
void multibyte_arg(Multibyte s) {}
// LINUX-LABEL: define void @_Z13multibyte_arg9Multibyte(%struct.Multibyte* byval align 4 %s)
-// WIN32: define void @"\01?multibyte_arg@@YAXUMultibyte@@@Z"(%struct.Multibyte* byval align 4 %s)
-// WIN64: define void @"\01?multibyte_arg@@YAXUMultibyte@@@Z"(i32 %s.coerce)
-// WOA: define arm_aapcs_vfpcc void @"\01?multibyte_arg@@YAXUMultibyte@@@Z"([1 x i32] %s.coerce)
+// WIN32: define dso_local void @"?multibyte_arg@@YAXUMultibyte@@@Z"(%struct.Multibyte* byval align 4 %s)
+// WIN64: define dso_local void @"?multibyte_arg@@YAXUMultibyte@@@Z"(i32 %s.coerce)
+// WOA: define dso_local arm_aapcs_vfpcc void @"?multibyte_arg@@YAXUMultibyte@@@Z"([1 x i32] %s.coerce)
void packed_arg(Packed s) {}
// LINUX-LABEL: define void @_Z10packed_arg6Packed(%struct.Packed* byval align 4 %s)
-// WIN32: define void @"\01?packed_arg@@YAXUPacked@@@Z"(%struct.Packed* byval align 4 %s)
-// WIN64: define void @"\01?packed_arg@@YAXUPacked@@@Z"(%struct.Packed* %s)
+// WIN32: define dso_local void @"?packed_arg@@YAXUPacked@@@Z"(%struct.Packed* byval align 4 %s)
+// WIN64: define dso_local void @"?packed_arg@@YAXUPacked@@@Z"(%struct.Packed* %s)
// Test that dtors are invoked in the callee.
void small_arg_with_dtor(SmallWithDtor s) {}
-// WIN32: define void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(<{ %struct.SmallWithDtor }>* inalloca) {{.*}} {
-// WIN32: call x86_thiscallcc void @"\01??1SmallWithDtor@@QAE@XZ"
+// WIN32: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(<{ %struct.SmallWithDtor }>* inalloca) {{.*}} {
+// WIN32: call x86_thiscallcc void @"??1SmallWithDtor@@QAE@XZ"
// WIN32: }
-// WIN64: define void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i32 %s.coerce) {{.*}} {
-// WIN64: call void @"\01??1SmallWithDtor@@QEAA@XZ"
+// WIN64: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i32 %s.coerce) {{.*}} {
+// WIN64: call void @"??1SmallWithDtor@@QEAA@XZ"
// WIN64: }
+// WOA64: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i64 %s.coerce) {{.*}} {
+// WOA64: call void @"??1SmallWithDtor@@QEAA@XZ"
+// WOA64: }
// FIXME: MSVC incompatible!
-// WOA: define arm_aapcs_vfpcc void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(%struct.SmallWithDtor* %s) {{.*}} {
-// WOA: call arm_aapcs_vfpcc void @"\01??1SmallWithDtor@@QAA@XZ"(%struct.SmallWithDtor* %s)
+// WOA: define dso_local arm_aapcs_vfpcc void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(%struct.SmallWithDtor* %s) {{.*}} {
+// WOA: call arm_aapcs_vfpcc void @"??1SmallWithDtor@@QAA@XZ"(%struct.SmallWithDtor* %s)
// WOA: }
void call_small_arg_with_dtor() {
small_arg_with_dtor(SmallWithDtor());
}
-// The temporary is copied, so it's destroyed in the caller as well as the
-// callee.
-// WIN64-LABEL: define void @"\01?call_small_arg_with_dtor@@YAXXZ"()
-// WIN64: call %struct.SmallWithDtor* @"\01??0SmallWithDtor@@QEAA@XZ"
-// WIN64: call void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i32 %{{.*}})
-// WIN64: call void @"\01??1SmallWithDtor@@QEAA@XZ"
+// WIN64-LABEL: define dso_local void @"?call_small_arg_with_dtor@@YAXXZ"()
+// WIN64: call %struct.SmallWithDtor* @"??0SmallWithDtor@@QEAA@XZ"
+// WIN64: call void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i32 %{{.*}})
// WIN64: ret void
// Test that references aren't destroyed in the callee.
void ref_small_arg_with_dtor(const SmallWithDtor &s) { }
-// WIN32: define void @"\01?ref_small_arg_with_dtor@@YAXABUSmallWithDtor@@@Z"(%struct.SmallWithDtor* dereferenceable({{[0-9]+}}) %s) {{.*}} {
-// WIN32-NOT: call x86_thiscallcc void @"\01??1SmallWithDtor@@QAE@XZ"
+// WIN32: define dso_local void @"?ref_small_arg_with_dtor@@YAXABUSmallWithDtor@@@Z"(%struct.SmallWithDtor* dereferenceable({{[0-9]+}}) %s) {{.*}} {
+// WIN32-NOT: call x86_thiscallcc void @"??1SmallWithDtor@@QAE@XZ"
// WIN32: }
-// WIN64-LABEL: define void @"\01?ref_small_arg_with_dtor@@YAXAEBUSmallWithDtor@@@Z"(%struct.SmallWithDtor* dereferenceable({{[0-9]+}}) %s)
+// WIN64-LABEL: define dso_local void @"?ref_small_arg_with_dtor@@YAXAEBUSmallWithDtor@@@Z"(%struct.SmallWithDtor* dereferenceable({{[0-9]+}}) %s)
void big_arg_with_dtor(BigWithDtor s) {}
-// WIN64-LABEL: define void @"\01?big_arg_with_dtor@@YAXUBigWithDtor@@@Z"(%struct.BigWithDtor* %s)
-// WIN64: call void @"\01??1BigWithDtor@@QEAA@XZ"
+// WIN64-LABEL: define dso_local void @"?big_arg_with_dtor@@YAXUBigWithDtor@@@Z"(%struct.BigWithDtor* %s)
+// WIN64: call void @"??1BigWithDtor@@QEAA@XZ"
// WIN64: }
void call_big_arg_with_dtor() {
@@ -197,20 +198,20 @@ void call_big_arg_with_dtor() {
}
// We can elide the copy of the temporary in the caller, because this object is
// larger than 8 bytes and is passed indirectly.
-// WIN64-LABEL: define void @"\01?call_big_arg_with_dtor@@YAXXZ"()
-// WIN64: call %struct.BigWithDtor* @"\01??0BigWithDtor@@QEAA@XZ"
-// WIN64: call void @"\01?big_arg_with_dtor@@YAXUBigWithDtor@@@Z"(%struct.BigWithDtor* %{{.*}})
-// WIN64-NOT: call void @"\01??1BigWithDtor@@QEAA@XZ"
+// WIN64-LABEL: define dso_local void @"?call_big_arg_with_dtor@@YAXXZ"()
+// WIN64: call %struct.BigWithDtor* @"??0BigWithDtor@@QEAA@XZ"
+// WIN64: call void @"?big_arg_with_dtor@@YAXUBigWithDtor@@@Z"(%struct.BigWithDtor* %{{.*}})
+// WIN64-NOT: call void @"??1BigWithDtor@@QEAA@XZ"
// WIN64: ret void
// Test that temporaries passed by reference are destroyed in the caller.
void temporary_ref_with_dtor() {
ref_small_arg_with_dtor(SmallWithDtor());
}
-// WIN32: define void @"\01?temporary_ref_with_dtor@@YAXXZ"() {{.*}} {
-// WIN32: call x86_thiscallcc %struct.SmallWithDtor* @"\01??0SmallWithDtor@@QAE@XZ"
-// WIN32: call void @"\01?ref_small_arg_with_dtor@@YAXABUSmallWithDtor@@@Z"
-// WIN32: call x86_thiscallcc void @"\01??1SmallWithDtor@@QAE@XZ"
+// WIN32: define dso_local void @"?temporary_ref_with_dtor@@YAXXZ"() {{.*}} {
+// WIN32: call x86_thiscallcc %struct.SmallWithDtor* @"??0SmallWithDtor@@QAE@XZ"
+// WIN32: call void @"?ref_small_arg_with_dtor@@YAXABUSmallWithDtor@@@Z"
+// WIN32: call x86_thiscallcc void @"??1SmallWithDtor@@QAE@XZ"
// WIN32: }
void takes_two_by_val_with_dtor(SmallWithDtor a, SmallWithDtor b);
@@ -219,28 +220,30 @@ void eh_cleanup_arg_with_dtor() {
}
// When exceptions are off, we don't have any cleanups. See
// microsoft-abi-exceptions.cpp for these cleanups.
-// WIN32: define void @"\01?eh_cleanup_arg_with_dtor@@YAXXZ"() {{.*}} {
-// WIN32: call x86_thiscallcc %struct.SmallWithDtor* @"\01??0SmallWithDtor@@QAE@XZ"
-// WIN32: call x86_thiscallcc %struct.SmallWithDtor* @"\01??0SmallWithDtor@@QAE@XZ"
-// WIN32: call void @"\01?takes_two_by_val_with_dtor@@YAXUSmallWithDtor@@0@Z"
-// WIN32-NOT: call x86_thiscallcc void @"\01??1SmallWithDtor@@QAE@XZ"
+// WIN32: define dso_local void @"?eh_cleanup_arg_with_dtor@@YAXXZ"() {{.*}} {
+// WIN32: call x86_thiscallcc %struct.SmallWithDtor* @"??0SmallWithDtor@@QAE@XZ"
+// WIN32: call x86_thiscallcc %struct.SmallWithDtor* @"??0SmallWithDtor@@QAE@XZ"
+// WIN32: call void @"?takes_two_by_val_with_dtor@@YAXUSmallWithDtor@@0@Z"
+// WIN32-NOT: call x86_thiscallcc void @"??1SmallWithDtor@@QAE@XZ"
// WIN32: }
void small_arg_with_vftable(SmallWithVftable s) {}
// LINUX-LABEL: define void @_Z22small_arg_with_vftable16SmallWithVftable(%struct.SmallWithVftable* %s)
-// WIN32: define void @"\01?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(<{ %struct.SmallWithVftable }>* inalloca)
-// WIN64: define void @"\01?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(%struct.SmallWithVftable* %s)
+// WIN32: define dso_local void @"?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(<{ %struct.SmallWithVftable }>* inalloca)
+// WIN64: define dso_local void @"?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(%struct.SmallWithVftable* %s)
+// WOA64: define dso_local void @"?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(%struct.SmallWithVftable* %s)
void medium_arg_with_copy_ctor(MediumWithCopyCtor s) {}
// LINUX-LABEL: define void @_Z25medium_arg_with_copy_ctor18MediumWithCopyCtor(%struct.MediumWithCopyCtor* %s)
-// WIN32: define void @"\01?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(<{ %struct.MediumWithCopyCtor }>* inalloca)
-// WIN64: define void @"\01?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* %s)
-// WOA: define arm_aapcs_vfpcc void @"\01?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* %s)
+// WIN32: define dso_local void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(<{ %struct.MediumWithCopyCtor }>* inalloca)
+// WIN64: define dso_local void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* %s)
+// WOA: define dso_local arm_aapcs_vfpcc void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* %s)
+// WOA64: define dso_local void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* %s)
void big_arg(Big s) {}
// LINUX-LABEL: define void @_Z7big_arg3Big(%struct.Big* byval align 4 %s)
-// WIN32: define void @"\01?big_arg@@YAXUBig@@@Z"(%struct.Big* byval align 4 %s)
-// WIN64: define void @"\01?big_arg@@YAXUBig@@@Z"(%struct.Big* %s)
+// WIN32: define dso_local void @"?big_arg@@YAXUBig@@@Z"(%struct.Big* byval align 4 %s)
+// WIN64: define dso_local void @"?big_arg@@YAXUBig@@@Z"(%struct.Big* %s)
// PR27607: We would attempt to load i32 value out of the reference instead of
// just loading the pointer from the struct during argument expansion.
@@ -250,8 +253,8 @@ struct RefField {
};
void takes_ref_field(RefField s) {}
// LINUX-LABEL: define void @_Z15takes_ref_field8RefField(%struct.RefField* byval align 4 %s)
-// WIN32: define void @"\01?takes_ref_field@@YAXURefField@@@Z"(i32* %s.0)
-// WIN64: define void @"\01?takes_ref_field@@YAXURefField@@@Z"(i64 %s.coerce)
+// WIN32: define dso_local void @"?takes_ref_field@@YAXURefField@@@Z"(i32* %s.0)
+// WIN64: define dso_local void @"?takes_ref_field@@YAXURefField@@@Z"(i64 %s.coerce)
void pass_ref_field() {
int x;
@@ -259,57 +262,57 @@ void pass_ref_field() {
}
// LINUX-LABEL: define void @_Z14pass_ref_fieldv()
// LINUX: call void @_Z15takes_ref_field8RefField(%struct.RefField* byval align 4 %{{.*}})
-// WIN32-LABEL: define void @"\01?pass_ref_field@@YAXXZ"()
-// WIN32: call void @"\01?takes_ref_field@@YAXURefField@@@Z"(i32* %{{.*}})
-// WIN64-LABEL: define void @"\01?pass_ref_field@@YAXXZ"()
-// WIN64: call void @"\01?takes_ref_field@@YAXURefField@@@Z"(i64 %{{.*}})
+// WIN32-LABEL: define dso_local void @"?pass_ref_field@@YAXXZ"()
+// WIN32: call void @"?takes_ref_field@@YAXURefField@@@Z"(i32* %{{.*}})
+// WIN64-LABEL: define dso_local void @"?pass_ref_field@@YAXXZ"()
+// WIN64: call void @"?takes_ref_field@@YAXURefField@@@Z"(i64 %{{.*}})
class Class {
public:
Small thiscall_method_small() { return Small(); }
// LINUX: define {{.*}} void @_ZN5Class21thiscall_method_smallEv(%struct.Small* noalias sret %agg.result, %class.Class* %this)
- // WIN32: define {{.*}} x86_thiscallcc void @"\01?thiscall_method_small@Class@@QAE?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret %agg.result)
- // WIN64: define linkonce_odr void @"\01?thiscall_method_small@Class@@QEAA?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret %agg.result)
+ // WIN32: define {{.*}} x86_thiscallcc void @"?thiscall_method_small@Class@@QAE?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret %agg.result)
+ // WIN64: define linkonce_odr dso_local void @"?thiscall_method_small@Class@@QEAA?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret %agg.result)
SmallWithCtor thiscall_method_small_with_ctor() { return SmallWithCtor(); }
// LINUX: define {{.*}} void @_ZN5Class31thiscall_method_small_with_ctorEv(%struct.SmallWithCtor* noalias sret %agg.result, %class.Class* %this)
- // WIN32: define {{.*}} x86_thiscallcc void @"\01?thiscall_method_small_with_ctor@Class@@QAE?AUSmallWithCtor@@XZ"(%class.Class* %this, %struct.SmallWithCtor* noalias sret %agg.result)
- // WIN64: define linkonce_odr void @"\01?thiscall_method_small_with_ctor@Class@@QEAA?AUSmallWithCtor@@XZ"(%class.Class* %this, %struct.SmallWithCtor* noalias sret %agg.result)
+ // WIN32: define {{.*}} x86_thiscallcc void @"?thiscall_method_small_with_ctor@Class@@QAE?AUSmallWithCtor@@XZ"(%class.Class* %this, %struct.SmallWithCtor* noalias sret %agg.result)
+ // WIN64: define linkonce_odr dso_local void @"?thiscall_method_small_with_ctor@Class@@QEAA?AUSmallWithCtor@@XZ"(%class.Class* %this, %struct.SmallWithCtor* noalias sret %agg.result)
Small __cdecl cdecl_method_small() { return Small(); }
// LINUX: define {{.*}} void @_ZN5Class18cdecl_method_smallEv(%struct.Small* noalias sret %agg.result, %class.Class* %this)
- // WIN32: define {{.*}} void @"\01?cdecl_method_small@Class@@QAA?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret %agg.result)
- // WIN64: define linkonce_odr void @"\01?cdecl_method_small@Class@@QEAA?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret %agg.result)
+ // WIN32: define {{.*}} void @"?cdecl_method_small@Class@@QAA?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret %agg.result)
+ // WIN64: define linkonce_odr dso_local void @"?cdecl_method_small@Class@@QEAA?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret %agg.result)
Big __cdecl cdecl_method_big() { return Big(); }
// LINUX: define {{.*}} void @_ZN5Class16cdecl_method_bigEv(%struct.Big* noalias sret %agg.result, %class.Class* %this)
- // WIN32: define {{.*}} void @"\01?cdecl_method_big@Class@@QAA?AUBig@@XZ"(%class.Class* %this, %struct.Big* noalias sret %agg.result)
- // WIN64: define linkonce_odr void @"\01?cdecl_method_big@Class@@QEAA?AUBig@@XZ"(%class.Class* %this, %struct.Big* noalias sret %agg.result)
+ // WIN32: define {{.*}} void @"?cdecl_method_big@Class@@QAA?AUBig@@XZ"(%class.Class* %this, %struct.Big* noalias sret %agg.result)
+ // WIN64: define linkonce_odr dso_local void @"?cdecl_method_big@Class@@QEAA?AUBig@@XZ"(%class.Class* %this, %struct.Big* noalias sret %agg.result)
void thiscall_method_arg(Empty s) {}
// LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE5Empty(%class.Class* %this)
- // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUEmpty@@@Z"(%class.Class* %this, %struct.Empty* byval align 4 %s)
- // WIN64: define linkonce_odr void @"\01?thiscall_method_arg@Class@@QEAAXUEmpty@@@Z"(%class.Class* %this, i8 %s.coerce)
+ // WIN32: define {{.*}} void @"?thiscall_method_arg@Class@@QAEXUEmpty@@@Z"(%class.Class* %this, %struct.Empty* byval align 4 %s)
+ // WIN64: define linkonce_odr dso_local void @"?thiscall_method_arg@Class@@QEAAXUEmpty@@@Z"(%class.Class* %this, i8 %s.coerce)
void thiscall_method_arg(EmptyWithCtor s) {}
// LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE13EmptyWithCtor(%class.Class* %this)
- // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUEmptyWithCtor@@@Z"(%class.Class* %this, %struct.EmptyWithCtor* byval align 4 %s)
- // WIN64: define linkonce_odr void @"\01?thiscall_method_arg@Class@@QEAAXUEmptyWithCtor@@@Z"(%class.Class* %this, i8 %s.coerce)
+ // WIN32: define {{.*}} void @"?thiscall_method_arg@Class@@QAEXUEmptyWithCtor@@@Z"(%class.Class* %this, %struct.EmptyWithCtor* byval align 4 %s)
+ // WIN64: define linkonce_odr dso_local void @"?thiscall_method_arg@Class@@QEAAXUEmptyWithCtor@@@Z"(%class.Class* %this, i8 %s.coerce)
void thiscall_method_arg(Small s) {}
// LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE5Small(%class.Class* %this, i32 %s.0)
- // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUSmall@@@Z"(%class.Class* %this, i32 %s.0)
- // WIN64: define linkonce_odr void @"\01?thiscall_method_arg@Class@@QEAAXUSmall@@@Z"(%class.Class* %this, i32 %s.coerce)
+ // WIN32: define {{.*}} void @"?thiscall_method_arg@Class@@QAEXUSmall@@@Z"(%class.Class* %this, i32 %s.0)
+ // WIN64: define linkonce_odr dso_local void @"?thiscall_method_arg@Class@@QEAAXUSmall@@@Z"(%class.Class* %this, i32 %s.coerce)
void thiscall_method_arg(SmallWithCtor s) {}
// LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE13SmallWithCtor(%class.Class* %this, %struct.SmallWithCtor* byval align 4 %s)
- // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUSmallWithCtor@@@Z"(%class.Class* %this, i32 %s.0)
- // WIN64: define linkonce_odr void @"\01?thiscall_method_arg@Class@@QEAAXUSmallWithCtor@@@Z"(%class.Class* %this, i32 %s.coerce)
+ // WIN32: define {{.*}} void @"?thiscall_method_arg@Class@@QAEXUSmallWithCtor@@@Z"(%class.Class* %this, i32 %s.0)
+ // WIN64: define linkonce_odr dso_local void @"?thiscall_method_arg@Class@@QEAAXUSmallWithCtor@@@Z"(%class.Class* %this, i32 %s.coerce)
void thiscall_method_arg(Big s) {}
// LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE3Big(%class.Class* %this, %struct.Big* byval align 4 %s)
- // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUBig@@@Z"(%class.Class* %this, %struct.Big* byval align 4 %s)
- // WIN64: define linkonce_odr void @"\01?thiscall_method_arg@Class@@QEAAXUBig@@@Z"(%class.Class* %this, %struct.Big* %s)
+ // WIN32: define {{.*}} void @"?thiscall_method_arg@Class@@QAEXUBig@@@Z"(%class.Class* %this, %struct.Big* byval align 4 %s)
+ // WIN64: define linkonce_odr dso_local void @"?thiscall_method_arg@Class@@QEAAXUBig@@@Z"(%class.Class* %this, %struct.Big* %s)
};
void use_class() {
@@ -333,14 +336,14 @@ struct X {
};
void g(X) {
}
-// WIN32: define void @"\01?g@@YAXUX@@@Z"(<{ %struct.X, [3 x i8] }>* inalloca) {{.*}} {
-// WIN32: call x86_thiscallcc void @"\01??1X@@QAE@XZ"(%struct.X* {{.*}})
+// WIN32: define dso_local void @"?g@@YAXUX@@@Z"(<{ %struct.X, [3 x i8] }>* inalloca) {{.*}} {
+// WIN32: call x86_thiscallcc void @"??1X@@QAE@XZ"(%struct.X* {{.*}})
// WIN32: }
void f() {
g(X());
}
-// WIN32: define void @"\01?f@@YAXXZ"() {{.*}} {
-// WIN32-NOT: call {{.*}} @"\01??1X@@QAE@XZ"
+// WIN32: define dso_local void @"?f@@YAXXZ"() {{.*}} {
+// WIN32-NOT: call {{.*}} @"??1X@@QAE@XZ"
// WIN32: }
@@ -362,13 +365,13 @@ void bar() {
b.b = 13;
int c = foo(NonTrivial(), b);
}
-// WIN32-LABEL: define void @"\01?bar@test2@@YAXXZ"() {{.*}} {
+// WIN32-LABEL: define dso_local void @"?bar@test2@@YAXXZ"() {{.*}} {
// WIN32: %[[argmem:[^ ]*]] = alloca inalloca [[argmem_ty:<{ %"struct.test2::NonTrivial", %"struct.test2::POD" }>]]
// WIN32: getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 1
// WIN32: call void @llvm.memcpy
// WIN32: getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 0
-// WIN32: call x86_thiscallcc %"struct.test2::NonTrivial"* @"\01??0NonTrivial@test2@@QAE@XZ"
-// WIN32: call i32 @"\01?foo@test2@@YAHUNonTrivial@1@UPOD@1@@Z"([[argmem_ty]]* inalloca %argmem)
+// WIN32: call x86_thiscallcc %"struct.test2::NonTrivial"* @"??0NonTrivial@test2@@QAE@XZ"
+// WIN32: call i32 @"?foo@test2@@YAHUNonTrivial@1@UPOD@1@@Z"([[argmem_ty]]* inalloca %argmem)
// WIN32: ret void
// WIN32: }
@@ -384,7 +387,7 @@ struct NonTrivial {
int a;
};
void foo(NonTrivial a, bool b) { }
-// WIN32-LABEL: define void @"\01?foo@test3@@YAXUNonTrivial@1@_N@Z"(<{ %"struct.test3::NonTrivial", i8, [3 x i8] }>* inalloca)
+// WIN32-LABEL: define dso_local void @"?foo@test3@@YAXUNonTrivial@1@_N@Z"(<{ %"struct.test3::NonTrivial", i8, [3 x i8] }>* inalloca)
}
@@ -399,18 +402,18 @@ void fn1(FnPtr1 a, SmallWithDtor b) { }
struct ForwardDeclare1 {};
void fn2(FnPtr1 a, SmallWithDtor b) { fn1(a, b); };
-// WIN32-LABEL: define void @"\01?fn2@@YAXP6AXUForwardDeclare1@@@ZUSmallWithDtor@@@Z"
+// WIN32-LABEL: define dso_local void @"?fn2@@YAXP6AXUForwardDeclare1@@@ZUSmallWithDtor@@@Z"
// WIN32: %[[a:[^ ]*]] = getelementptr inbounds [[argmem_ty:<{ {}\*, %struct.SmallWithDtor }>]], [[argmem_ty:<{ {}\*, %struct.SmallWithDtor }>]]* %{{.*}}, i32 0, i32 0
// WIN32: %[[a1:[^ ]*]] = bitcast {}** %[[a]] to void [[dst_ty:\(%struct.ForwardDeclare1\*\)\*]]*
// WIN32: %[[argmem:[^ ]*]] = alloca inalloca [[argmem_ty]]
// WIN32: %[[gep1:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 1
// WIN32: %[[bc1:[^ ]*]] = bitcast %struct.SmallWithDtor* %[[gep1]] to i8*
-// WIN32: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %[[bc1]], i8* {{.*}}, i32 4, i32 4, i1 false)
+// WIN32: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %[[bc1]], i8* align 4 {{.*}}, i32 4, i1 false)
// WIN32: %[[a2:[^ ]*]] = load void [[dst_ty]], void [[dst_ty]]* %[[a1]], align 4
// WIN32: %[[gep2:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 0
// WIN32: %[[addr:[^ ]*]] = bitcast {}** %[[gep2]] to void [[dst_ty]]*
// WIN32: store void [[dst_ty]] %[[a2]], void [[dst_ty]]* %[[addr]], align 4
-// WIN32: call void @"\01?fn1@@YAXP6AXUForwardDeclare1@@@ZUSmallWithDtor@@@Z"([[argmem_ty]]* inalloca %[[argmem]])
+// WIN32: call void @"?fn1@@YAXP6AXUForwardDeclare1@@@ZUSmallWithDtor@@@Z"([[argmem_ty]]* inalloca %[[argmem]])
namespace pr30293 {
// Virtual methods living in a secondary vtable take i8* as their 'this'
@@ -430,11 +433,11 @@ struct C final : A, B {
};
void C::g() { return h(SmallWithDtor()); }
-// WIN32-LABEL: define x86_thiscallcc void @"\01?g@C@pr30293@@QAEXXZ"(%"struct.pr30293::C"* %this)
-// WIN32: call x86_thiscallcc %struct.SmallWithDtor* @"\01??0SmallWithDtor@@QAE@XZ"
-// WIN32: call void @"\01?h@C@pr30293@@UAAXUSmallWithDtor@@@Z"(<{ i8*, %struct.SmallWithDtor }>* inalloca %{{[^,)]*}})
-// WIN32: declare void @"\01?h@C@pr30293@@UAAXUSmallWithDtor@@@Z"(<{ i8*, %struct.SmallWithDtor }>* inalloca)
+// WIN32-LABEL: define dso_local x86_thiscallcc void @"?g@C@pr30293@@QAEXXZ"(%"struct.pr30293::C"* %this)
+// WIN32: call x86_thiscallcc %struct.SmallWithDtor* @"??0SmallWithDtor@@QAE@XZ"
+// WIN32: call void @"?h@C@pr30293@@UAAXUSmallWithDtor@@@Z"(<{ i8*, %struct.SmallWithDtor }>* inalloca %{{[^,)]*}})
+// WIN32: declare dso_local void @"?h@C@pr30293@@UAAXUSmallWithDtor@@@Z"(<{ i8*, %struct.SmallWithDtor }>* inalloca)
-// WIN64-LABEL: define void @"\01?g@C@pr30293@@QEAAXXZ"(%"struct.pr30293::C"* %this)
-// WIN64: declare void @"\01?h@C@pr30293@@UEAAXUSmallWithDtor@@@Z"(i8*, i32)
+// WIN64-LABEL: define dso_local void @"?g@C@pr30293@@QEAAXXZ"(%"struct.pr30293::C"* %this)
+// WIN64: declare dso_local void @"?h@C@pr30293@@UEAAXUSmallWithDtor@@@Z"(i8*, i32)
}
diff --git a/test/CodeGenCXX/microsoft-abi-static-initializers.cpp b/test/CodeGenCXX/microsoft-abi-static-initializers.cpp
index 0b84f07e1154..db9526633ff1 100644
--- a/test/CodeGenCXX/microsoft-abi-static-initializers.cpp
+++ b/test/CodeGenCXX/microsoft-abi-static-initializers.cpp
@@ -1,10 +1,10 @@
// RUN: %clang_cc1 -fms-extensions -fno-threadsafe-statics -emit-llvm %s -o - -mconstructor-aliases -triple=i386-pc-win32 | FileCheck %s
// CHECK: @llvm.global_ctors = appending global [5 x { i32, void ()*, i8* }] [
-// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"\01??__Eselectany1@@YAXXZ", i8* getelementptr inbounds (%struct.S, %struct.S* @"\01?selectany1@@3US@@A", i32 0, i32 0) },
-// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"\01??__Eselectany2@@YAXXZ", i8* getelementptr inbounds (%struct.S, %struct.S* @"\01?selectany2@@3US@@A", i32 0, i32 0) },
-// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"\01??__Es@?$ExportedTemplate@H@@2US@@A@YAXXZ", i8* getelementptr inbounds (%struct.S, %struct.S* @"\01?s@?$ExportedTemplate@H@@2US@@A", i32 0, i32 0) },
-// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"\01??__Efoo@?$B@H@@2VA@@A@YAXXZ", i8* bitcast (%class.A* @"\01?foo@?$B@H@@2VA@@A" to i8*) },
+// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"??__Eselectany1@@YAXXZ", i8* getelementptr inbounds (%struct.S, %struct.S* @"?selectany1@@3US@@A", i32 0, i32 0) },
+// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"??__Eselectany2@@YAXXZ", i8* getelementptr inbounds (%struct.S, %struct.S* @"?selectany2@@3US@@A", i32 0, i32 0) },
+// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"??__Es@?$ExportedTemplate@H@@2US@@A@YAXXZ", i8* getelementptr inbounds (%struct.S, %struct.S* @"?s@?$ExportedTemplate@H@@2US@@A", i32 0, i32 0) },
+// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"??__Efoo@?$B@H@@2VA@@A@YAXXZ", i8* bitcast (%class.A* @"?foo@?$B@H@@2VA@@A" to i8*) },
// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_microsoft_abi_static_initializers.cpp, i8* null }
// CHECK: ]
@@ -15,26 +15,26 @@ struct S {
S s;
-// CHECK: define internal void @"\01??__Es@@YAXXZ"()
-// CHECK: call x86_thiscallcc %struct.S* @"\01??0S@@QAE@XZ"
-// CHECK: call i32 @atexit(void ()* @"\01??__Fs@@YAXXZ")
+// CHECK: define internal void @"??__Es@@YAXXZ"()
+// CHECK: call x86_thiscallcc %struct.S* @"??0S@@QAE@XZ"
+// CHECK: call i32 @atexit(void ()* @"??__Fs@@YAXXZ")
// CHECK: ret void
-// CHECK: define internal void @"\01??__Fs@@YAXXZ"()
-// CHECK: call x86_thiscallcc void @"\01??1S@@QAE@XZ"
+// CHECK: define internal void @"??__Fs@@YAXXZ"()
+// CHECK: call x86_thiscallcc void @"??1S@@QAE@XZ"
// CHECK: ret void
// These globals should have initializers comdat associative with the global.
// See @llvm.global_ctors above.
__declspec(selectany) S selectany1;
__declspec(selectany) S selectany2;
-// CHECK: define linkonce_odr void @"\01??__Eselectany1@@YAXXZ"() {{.*}} comdat
-// CHECK-NOT: @"\01??_Bselectany1
-// CHECK: call x86_thiscallcc %struct.S* @"\01??0S@@QAE@XZ"
+// CHECK: define linkonce_odr dso_local void @"??__Eselectany1@@YAXXZ"() {{.*}} comdat
+// CHECK-NOT: @"??_Bselectany1
+// CHECK: call x86_thiscallcc %struct.S* @"??0S@@QAE@XZ"
// CHECK: ret void
-// CHECK: define linkonce_odr void @"\01??__Eselectany2@@YAXXZ"() {{.*}} comdat
-// CHECK-NOT: @"\01??_Bselectany2
-// CHECK: call x86_thiscallcc %struct.S* @"\01??0S@@QAE@XZ"
+// CHECK: define linkonce_odr dso_local void @"??__Eselectany2@@YAXXZ"() {{.*}} comdat
+// CHECK-NOT: @"??_Bselectany2
+// CHECK: call x86_thiscallcc %struct.S* @"??0S@@QAE@XZ"
// CHECK: ret void
// The implicitly instantiated static data member should have initializer
@@ -51,9 +51,9 @@ void StaticLocal() {
static S TheS;
}
-// CHECK-LABEL: define void @"\01?StaticLocal@@YAXXZ"()
-// CHECK: load i32, i32* @"\01?$S1@?1??StaticLocal@@YAXXZ@4IA"
-// CHECK: store i32 {{.*}}, i32* @"\01?$S1@?1??StaticLocal@@YAXXZ@4IA"
+// CHECK-LABEL: define dso_local void @"?StaticLocal@@YAXXZ"()
+// CHECK: load i32, i32* @"?$S1@?1??StaticLocal@@YAXXZ@4IA"
+// CHECK: store i32 {{.*}}, i32* @"?$S1@?1??StaticLocal@@YAXXZ@4IA"
// CHECK: ret
void MultipleStatics() {
@@ -93,8 +93,8 @@ void MultipleStatics() {
static S S34;
static S S35;
}
-// CHECK-LABEL: define void @"\01?MultipleStatics@@YAXXZ"()
-// CHECK: load i32, i32* @"\01?$S1@?1??MultipleStatics@@YAXXZ@4IA"
+// CHECK-LABEL: define dso_local void @"?MultipleStatics@@YAXXZ"()
+// CHECK: load i32, i32* @"?$S1@?1??MultipleStatics@@YAXXZ@4IA"
// CHECK: and i32 {{.*}}, 1
// CHECK: and i32 {{.*}}, 2
// CHECK: and i32 {{.*}}, 4
@@ -102,7 +102,7 @@ void MultipleStatics() {
// CHECK: and i32 {{.*}}, 16
// ...
// CHECK: and i32 {{.*}}, -2147483648
-// CHECK: load i32, i32* @"\01?$S1@?1??MultipleStatics@@YAXXZ@4IA.1"
+// CHECK: load i32, i32* @"?$S1@?1??MultipleStatics@@YAXXZ@4IA.1"
// CHECK: and i32 {{.*}}, 1
// CHECK: and i32 {{.*}}, 2
// CHECK: and i32 {{.*}}, 4
@@ -133,7 +133,7 @@ inline S &UnreachableStatic() {
return s;
}
-// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.S* @"\01?UnreachableStatic@@YAAAUS@@XZ"() {{.*}} comdat
+// CHECK-LABEL: define linkonce_odr dso_local dereferenceable({{[0-9]+}}) %struct.S* @"?UnreachableStatic@@YAAAUS@@XZ"() {{.*}} comdat
// CHECK: and i32 {{.*}}, 2
// CHECK: or i32 {{.*}}, 2
// CHECK: ret
@@ -143,54 +143,54 @@ inline S &getS() {
return TheS;
}
-// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.S* @"\01?getS@@YAAAUS@@XZ"() {{.*}} comdat
-// CHECK: load i32, i32* @"\01??_B?1??getS@@YAAAUS@@XZ@51"
+// CHECK-LABEL: define linkonce_odr dso_local dereferenceable({{[0-9]+}}) %struct.S* @"?getS@@YAAAUS@@XZ"() {{.*}} comdat
+// CHECK: load i32, i32* @"??_B?1??getS@@YAAAUS@@XZ@51"
// CHECK: and i32 {{.*}}, 1
// CHECK: icmp eq i32 {{.*}}, 0
// CHECK: br i1
// init:
// CHECK: or i32 {{.*}}, 1
-// CHECK: store i32 {{.*}}, i32* @"\01??_B?1??getS@@YAAAUS@@XZ@51"
-// CHECK: call x86_thiscallcc %struct.S* @"\01??0S@@QAE@XZ"(%struct.S* @"\01?TheS@?1??getS@@YAAAUS@@XZ@4U2@A")
-// CHECK: call i32 @atexit(void ()* @"\01??__FTheS@?1??getS@@YAAAUS@@XZ@YAXXZ")
+// CHECK: store i32 {{.*}}, i32* @"??_B?1??getS@@YAAAUS@@XZ@51"
+// CHECK: call x86_thiscallcc %struct.S* @"??0S@@QAE@XZ"(%struct.S* @"?TheS@?1??getS@@YAAAUS@@XZ@4U2@A")
+// CHECK: call i32 @atexit(void ()* @"??__FTheS@?1??getS@@YAAAUS@@XZ@YAXXZ")
// CHECK: br label
// init.end:
-// CHECK: ret %struct.S* @"\01?TheS@?1??getS@@YAAAUS@@XZ@4U2@A"
+// CHECK: ret %struct.S* @"?TheS@?1??getS@@YAAAUS@@XZ@4U2@A"
inline int enum_in_function() {
- // CHECK-LABEL: define linkonce_odr i32 @"\01?enum_in_function@@YAHXZ"() {{.*}} comdat
+ // CHECK-LABEL: define linkonce_odr dso_local i32 @"?enum_in_function@@YAHXZ"() {{.*}} comdat
static enum e { foo, bar, baz } x;
- // CHECK: @"\01?x@?1??enum_in_function@@YAHXZ@4W4e@?1??1@YAHXZ@A"
+ // CHECK: @"?x@?1??enum_in_function@@YAHXZ@4W4e@?1??1@YAHXZ@A"
static int y;
- // CHECK: @"\01?y@?1??enum_in_function@@YAHXZ@4HA"
+ // CHECK: @"?y@?1??enum_in_function@@YAHXZ@4HA"
return x + y;
};
struct T {
enum e { foo, bar, baz };
int enum_in_struct() {
- // CHECK-LABEL: define linkonce_odr x86_thiscallcc i32 @"\01?enum_in_struct@T@@QAEHXZ"({{.*}}) {{.*}} comdat
+ // CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc i32 @"?enum_in_struct@T@@QAEHXZ"({{.*}}) {{.*}} comdat
static int x;
- // CHECK: @"\01?x@?1??enum_in_struct@T@@QAEHXZ@4HA"
+ // CHECK: @"?x@?1??enum_in_struct@T@@QAEHXZ@4HA"
return x++;
}
};
inline int switch_test(int x) {
- // CHECK-LABEL: define linkonce_odr i32 @"\01?switch_test@@YAHH@Z"(i32 %x) {{.*}} comdat
+ // CHECK-LABEL: define linkonce_odr dso_local i32 @"?switch_test@@YAHH@Z"(i32 %x) {{.*}} comdat
switch (x) {
static int a;
- // CHECK: @"\01?a@?3??switch_test@@YAHH@Z@4HA"
+ // CHECK: @"?a@?3??switch_test@@YAHH@Z@4HA"
case 0:
a++;
return 1;
case 1:
static int b;
- // CHECK: @"\01?b@?3??switch_test@@YAHH@Z@4HA"
+ // CHECK: @"?b@?3??switch_test@@YAHH@Z@4HA"
return b++;
case 2: {
static int c;
- // CHECK: @"\01?c@?4??switch_test@@YAHH@Z@4HA"
+ // CHECK: @"?c@?4??switch_test@@YAHH@Z@4HA"
return b + c++;
}
};
@@ -198,8 +198,8 @@ inline int switch_test(int x) {
int f();
inline void switch_test2() {
- // CHECK-LABEL: define linkonce_odr void @"\01?switch_test2@@YAXXZ"() {{.*}} comdat
- // CHECK: @"\01?x@?2??switch_test2@@YAXXZ@4HA"
+ // CHECK-LABEL: define linkonce_odr dso_local void @"?switch_test2@@YAXXZ"() {{.*}} comdat
+ // CHECK: @"?x@?2??switch_test2@@YAXXZ@4HA"
switch (1) default: static int x = f();
}
@@ -213,9 +213,9 @@ namespace DynamicDLLImportInitVSMangling {
template struct __declspec(dllimport) A<int>;
inline int switch_test3() {
- // CHECK-LABEL: define linkonce_odr i32 @"\01?switch_test3@DynamicDLLImportInitVSMangling@@YAHXZ"() {{.*}} comdat
+ // CHECK-LABEL: define linkonce_odr dso_local i32 @"?switch_test3@DynamicDLLImportInitVSMangling@@YAHXZ"() {{.*}} comdat
static int local;
- // CHECK: @"\01?local@?1??switch_test3@DynamicDLLImportInitVSMangling@@YAHXZ@4HA"
+ // CHECK: @"?local@?1??switch_test3@DynamicDLLImportInitVSMangling@@YAHXZ@4HA"
return local++;
}
}
@@ -231,21 +231,21 @@ void force_usage() {
DynamicDLLImportInitVSMangling::switch_test3();
}
-// CHECK: define linkonce_odr void @"\01??__Efoo@?$B@H@@2VA@@A@YAXXZ"() {{.*}} comdat
+// CHECK: define linkonce_odr dso_local void @"??__Efoo@?$B@H@@2VA@@A@YAXXZ"() {{.*}} comdat
// CHECK-NOT: and
// CHECK-NOT: ?_Bfoo@
-// CHECK: call x86_thiscallcc %class.A* @"\01??0A@@QAE@XZ"
-// CHECK: call i32 @atexit(void ()* @"\01??__Ffoo@?$B@H@@2VA@@A@YAXXZ")
+// CHECK: call x86_thiscallcc %class.A* @"??0A@@QAE@XZ"
+// CHECK: call i32 @atexit(void ()* @"??__Ffoo@?$B@H@@2VA@@A@YAXXZ")
// CHECK: ret void
-// CHECK: define linkonce_odr x86_thiscallcc %class.A* @"\01??0A@@QAE@XZ"({{.*}}) {{.*}} comdat
+// CHECK: define linkonce_odr dso_local x86_thiscallcc %class.A* @"??0A@@QAE@XZ"({{.*}}) {{.*}} comdat
-// CHECK: define linkonce_odr x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) {{.*}} comdat
+// CHECK: define linkonce_odr dso_local x86_thiscallcc void @"??1A@@QAE@XZ"({{.*}}) {{.*}} comdat
-// CHECK: define internal void @"\01??__Ffoo@?$B@H@@2VA@@A@YAXXZ"
-// CHECK: call x86_thiscallcc void @"\01??1A@@QAE@XZ"{{.*}}foo
+// CHECK: define internal void @"??__Ffoo@?$B@H@@2VA@@A@YAXXZ"
+// CHECK: call x86_thiscallcc void @"??1A@@QAE@XZ"{{.*}}foo
// CHECK: ret void
// CHECK: define internal void @_GLOBAL__sub_I_microsoft_abi_static_initializers.cpp()
-// CHECK: call void @"\01??__Es@@YAXXZ"()
+// CHECK: call void @"??__Es@@YAXXZ"()
// CHECK: ret void
diff --git a/test/CodeGenCXX/microsoft-abi-structors-alias.cpp b/test/CodeGenCXX/microsoft-abi-structors-alias.cpp
index 4eb757af3f8b..38f7b4c8b58d 100644
--- a/test/CodeGenCXX/microsoft-abi-structors-alias.cpp
+++ b/test/CodeGenCXX/microsoft-abi-structors-alias.cpp
@@ -5,7 +5,7 @@ template <typename T> class A {
~A() {}
};
template class A<char>;
-// CHECK-DAG: define weak_odr x86_thiscallcc void @"\01??1?$A@D@test1@@AAE@XZ"
+// CHECK-DAG: define weak_odr dso_local x86_thiscallcc void @"??1?$A@D@test1@@AAE@XZ"
}
namespace test2 {
@@ -22,14 +22,14 @@ B::~B() {}
void foo() {
B b;
}
-// CHECK-DAG: @"\01??1B@test2@@UAE@XZ" = alias void (%"struct.test2::B"*), bitcast (void (%"struct.test2::A"*)* @"\01??1A@test2@@UAE@XZ" to void (%"struct.test2::B"*)*)
+// CHECK-DAG: @"??1B@test2@@UAE@XZ" = dso_local unnamed_addr alias void (%"struct.test2::B"*), bitcast (void (%"struct.test2::A"*)* @"??1A@test2@@UAE@XZ" to void (%"struct.test2::B"*)*)
}
namespace test3 {
struct A { virtual ~A(); };
A::~A() {}
}
-// CHECK-DAG: define x86_thiscallcc void @"\01??1A@test3@@UAE@XZ"(
+// CHECK-DAG: define dso_local x86_thiscallcc void @"??1A@test3@@UAE@XZ"(
namespace test3 {
template <typename T>
struct B : A {
@@ -39,4 +39,4 @@ template struct B<int>;
}
// This has to be weak, and emitting weak aliases is fragile, so we don't do the
// aliasing.
-// CHECK-DAG: define weak_odr x86_thiscallcc void @"\01??1?$B@H@test3@@UAE@XZ"(
+// CHECK-DAG: define weak_odr dso_local x86_thiscallcc void @"??1?$B@H@test3@@UAE@XZ"(
diff --git a/test/CodeGenCXX/microsoft-abi-structors-delayed-template.cpp b/test/CodeGenCXX/microsoft-abi-structors-delayed-template.cpp
index f9e188033ca4..6c4f37052d15 100644
--- a/test/CodeGenCXX/microsoft-abi-structors-delayed-template.cpp
+++ b/test/CodeGenCXX/microsoft-abi-structors-delayed-template.cpp
@@ -8,5 +8,5 @@ struct ImplicitCtor {
};
template <class T> void foo(T t) { new ImplicitCtor; }
void bar() { foo(0); }
-// CHECK: store {{.*}} @"\01??_7ImplicitCtor@vtable_referenced_from_template@@6B@"
+// CHECK: store {{.*}} @"??_7ImplicitCtor@vtable_referenced_from_template@@6B@"
}
diff --git a/test/CodeGenCXX/microsoft-abi-structors.cpp b/test/CodeGenCXX/microsoft-abi-structors.cpp
index 4de6c3346611..97b90ce6b9eb 100644
--- a/test/CodeGenCXX/microsoft-abi-structors.cpp
+++ b/test/CodeGenCXX/microsoft-abi-structors.cpp
@@ -20,7 +20,7 @@ class A {
void no_constructor_destructor_infinite_recursion() {
A a;
-// CHECK: define linkonce_odr x86_thiscallcc %"class.basic::A"* @"\01??0A@basic@@QAE@XZ"(%"class.basic::A"* returned %this) {{.*}} comdat {{.*}} {
+// CHECK: define linkonce_odr dso_local x86_thiscallcc %"class.basic::A"* @"??0A@basic@@QAE@XZ"(%"class.basic::A"* returned %this) {{.*}} comdat {{.*}} {
// CHECK: [[THIS_ADDR:%[.0-9A-Z_a-z]+]] = alloca %"class.basic::A"*, align 4
// CHECK-NEXT: store %"class.basic::A"* %this, %"class.basic::A"** [[THIS_ADDR]], align 4
// CHECK-NEXT: [[T1:%[.0-9A-Z_a-z]+]] = load %"class.basic::A"*, %"class.basic::A"** [[THIS_ADDR]]
@@ -30,8 +30,8 @@ void no_constructor_destructor_infinite_recursion() {
A::~A() {
// Make sure that the destructor doesn't call itself:
-// CHECK: define {{.*}} @"\01??1A@basic@@QAE@XZ"
-// CHECK-NOT: call void @"\01??1A@basic@@QAE@XZ"
+// CHECK: define {{.*}} @"??1A@basic@@QAE@XZ"
+// CHECK-NOT: call void @"??1A@basic@@QAE@XZ"
// CHECK: ret
}
@@ -41,23 +41,23 @@ struct B {
// Tests that we can define constructors outside the class (PR12784).
B::B() {
- // CHECK: define x86_thiscallcc %"struct.basic::B"* @"\01??0B@basic@@QAE@XZ"(%"struct.basic::B"* returned %this)
+ // CHECK: define dso_local x86_thiscallcc %"struct.basic::B"* @"??0B@basic@@QAE@XZ"(%"struct.basic::B"* returned %this)
// CHECK: ret
}
struct C {
virtual ~C() {
-// DTORS: define linkonce_odr x86_thiscallcc i8* @"\01??_GC@basic@@UAEPAXI@Z"(%"struct.basic::C"* %this, i32 %should_call_delete) {{.*}} comdat {{.*}} {
+// DTORS: define linkonce_odr dso_local x86_thiscallcc i8* @"??_GC@basic@@UAEPAXI@Z"(%"struct.basic::C"* %this, i32 %should_call_delete) {{.*}} comdat {{.*}} {
// DTORS: store i32 %should_call_delete, i32* %[[SHOULD_DELETE_VAR:[0-9a-z._]+]], align 4
// DTORS: store i8* %{{.*}}, i8** %[[RETVAL:[0-9a-z._]+]]
// DTORS: %[[SHOULD_DELETE_VALUE:[0-9a-z._]+]] = load i32, i32* %[[SHOULD_DELETE_VAR]]
-// DTORS: call x86_thiscallcc void @"\01??1C@basic@@UAE@XZ"(%"struct.basic::C"* %[[THIS:[0-9a-z]+]])
+// DTORS: call x86_thiscallcc void @"??1C@basic@@UAE@XZ"(%"struct.basic::C"* %[[THIS:[0-9a-z]+]])
// DTORS-NEXT: %[[CONDITION:[0-9]+]] = icmp eq i32 %[[SHOULD_DELETE_VALUE]], 0
// DTORS-NEXT: br i1 %[[CONDITION]], label %[[CONTINUE_LABEL:[0-9a-z._]+]], label %[[CALL_DELETE_LABEL:[0-9a-z._]+]]
//
// DTORS: [[CALL_DELETE_LABEL]]
// DTORS-NEXT: %[[THIS_AS_VOID:[0-9a-z]+]] = bitcast %"struct.basic::C"* %[[THIS]] to i8*
-// DTORS-NEXT: call void @"\01??3@YAXPAX@Z"(i8* %[[THIS_AS_VOID]])
+// DTORS-NEXT: call void @"??3@YAXPAX@Z"(i8* %[[THIS_AS_VOID]])
// DTORS-NEXT: br label %[[CONTINUE_LABEL]]
//
// DTORS: [[CONTINUE_LABEL]]
@@ -65,7 +65,7 @@ struct C {
// DTORS-NEXT: ret i8* %[[RET]]
// Check that we do the mangling correctly on x64.
-// DTORS-X64: @"\01??_GC@basic@@UEAAPEAXI@Z"
+// DTORS-X64: @"??_GC@basic@@UEAAPEAXI@Z"
}
virtual void foo();
};
@@ -77,11 +77,11 @@ void check_vftable_offset() {
C c;
// The vftable pointer should point at the beginning of the vftable.
// CHECK: [[THIS_PTR:%[0-9]+]] = bitcast %"struct.basic::C"* {{.*}} to i32 (...)***
-// CHECK: store i32 (...)** bitcast ({ [2 x i8*] }* @"\01??_7C@basic@@6B@" to i32 (...)**), i32 (...)*** [[THIS_PTR]]
+// CHECK: store i32 (...)** bitcast ({ [2 x i8*] }* @"??_7C@basic@@6B@" to i32 (...)**), i32 (...)*** [[THIS_PTR]]
}
void call_complete_dtor(C *obj_ptr) {
-// CHECK: define void @"\01?call_complete_dtor@basic@@YAXPAUC@1@@Z"(%"struct.basic::C"* %obj_ptr)
+// CHECK: define dso_local void @"?call_complete_dtor@basic@@YAXPAUC@1@@Z"(%"struct.basic::C"* %obj_ptr)
obj_ptr->~C();
// CHECK: %[[OBJ_PTR_VALUE:.*]] = load %"struct.basic::C"*, %"struct.basic::C"** %{{.*}}, align 4
// CHECK-NEXT: %[[PVTABLE:.*]] = bitcast %"struct.basic::C"* %[[OBJ_PTR_VALUE]] to i8* (%"struct.basic::C"*, i32)***
@@ -93,7 +93,7 @@ void call_complete_dtor(C *obj_ptr) {
}
void call_deleting_dtor(C *obj_ptr) {
-// CHECK: define void @"\01?call_deleting_dtor@basic@@YAXPAUC@1@@Z"(%"struct.basic::C"* %obj_ptr)
+// CHECK: define dso_local void @"?call_deleting_dtor@basic@@YAXPAUC@1@@Z"(%"struct.basic::C"* %obj_ptr)
delete obj_ptr;
// CHECK: %[[OBJ_PTR_VALUE:.*]] = load %"struct.basic::C"*, %"struct.basic::C"** %{{.*}}, align 4
// CHECK: br i1 {{.*}}, label %[[DELETE_NULL:.*]], label %[[DELETE_NOTNULL:.*]]
@@ -108,7 +108,7 @@ void call_deleting_dtor(C *obj_ptr) {
}
void call_deleting_dtor_and_global_delete(C *obj_ptr) {
-// CHECK: define void @"\01?call_deleting_dtor_and_global_delete@basic@@YAXPAUC@1@@Z"(%"struct.basic::C"* %obj_ptr)
+// CHECK: define dso_local void @"?call_deleting_dtor_and_global_delete@basic@@YAXPAUC@1@@Z"(%"struct.basic::C"* %obj_ptr)
::delete obj_ptr;
// CHECK: %[[OBJ_PTR_VALUE:.*]] = load %"struct.basic::C"*, %"struct.basic::C"** %{{.*}}, align 4
// CHECK: br i1 {{.*}}, label %[[DELETE_NULL:.*]], label %[[DELETE_NOTNULL:.*]]
@@ -119,7 +119,7 @@ void call_deleting_dtor_and_global_delete(C *obj_ptr) {
// CHECK-NEXT: %[[PVDTOR:.*]] = getelementptr inbounds i8* (%"struct.basic::C"*, i32)*, i8* (%"struct.basic::C"*, i32)** %[[VTABLE]], i64 0
// CHECK-NEXT: %[[VDTOR:.*]] = load i8* (%"struct.basic::C"*, i32)*, i8* (%"struct.basic::C"*, i32)** %[[PVDTOR]]
// CHECK-NEXT: %[[CALL:.*]] = call x86_thiscallcc i8* %[[VDTOR]](%"struct.basic::C"* %[[OBJ_PTR_VALUE]], i32 0)
-// CHECK-NEXT: call void @"\01??3@YAXPAX@Z"(i8* %[[CALL]])
+// CHECK-NEXT: call void @"??3@YAXPAX@Z"(i8* %[[CALL]])
// CHECK: ret void
}
@@ -129,12 +129,12 @@ struct D {
D() {
static int ctor_static = foo();
// CHECK that the static in the ctor gets mangled correctly:
- // CHECK: @"\01?ctor_static@?1???0D@basic@@QAE@XZ@4HA"
+ // CHECK: @"?ctor_static@?1???0D@basic@@QAE@XZ@4HA"
}
~D() {
static int dtor_static = foo();
// CHECK that the static in the dtor gets mangled correctly:
- // CHECK: @"\01?dtor_static@?1???1D@basic@@QAE@XZ@4HA"
+ // CHECK: @"?dtor_static@?1???1D@basic@@QAE@XZ@4HA"
}
};
@@ -155,7 +155,7 @@ struct C : A, B {
};
C::~C() {
-// CHECK-LABEL: define x86_thiscallcc void @"\01??1C@dtor_in_second_nvbase@@UAE@XZ"
+// CHECK-LABEL: define dso_local x86_thiscallcc void @"??1C@dtor_in_second_nvbase@@UAE@XZ"
// CHECK: (%"struct.dtor_in_second_nvbase::C"* %this)
// No this adjustment!
// CHECK-NOT: getelementptr
@@ -164,7 +164,7 @@ C::~C() {
// CHECK: bitcast %"struct.dtor_in_second_nvbase::C"* %{{.*}} to i8*
// CHECK: getelementptr inbounds i8, i8* %{{.*}}, i32 4
// CHECK: bitcast i8* %{{.*}} to %"struct.dtor_in_second_nvbase::B"*
-// CHECK: call x86_thiscallcc void @"\01??1B@dtor_in_second_nvbase@@UAE@XZ"
+// CHECK: call x86_thiscallcc void @"??1B@dtor_in_second_nvbase@@UAE@XZ"
// CHECK: (%"struct.dtor_in_second_nvbase::B"* %{{.*}})
// CHECK: ret void
}
@@ -172,12 +172,12 @@ C::~C() {
void foo() {
C c;
}
-// DTORS2-LABEL: define linkonce_odr x86_thiscallcc i8* @"\01??_EC@dtor_in_second_nvbase@@W3AEPAXI@Z"
+// DTORS2-LABEL: define linkonce_odr dso_local x86_thiscallcc i8* @"??_EC@dtor_in_second_nvbase@@W3AEPAXI@Z"
// DTORS2: (%"struct.dtor_in_second_nvbase::C"* %this, i32 %should_call_delete)
// Do an adjustment from B* to C*.
// DTORS2: getelementptr i8, i8* %{{.*}}, i32 -4
// DTORS2: bitcast i8* %{{.*}} to %"struct.dtor_in_second_nvbase::C"*
-// DTORS2: %[[CALL:.*]] = tail call x86_thiscallcc i8* @"\01??_GC@dtor_in_second_nvbase@@UAEPAXI@Z"
+// DTORS2: %[[CALL:.*]] = tail call x86_thiscallcc i8* @"??_GC@dtor_in_second_nvbase@@UAEPAXI@Z"
// DTORS2: ret i8* %[[CALL]]
}
@@ -196,7 +196,7 @@ struct E : virtual C { int e; };
struct F : D, E { ~F(); int f; };
F::~F() {
-// CHECK-LABEL: define x86_thiscallcc void @"\01??1F@test2@@UAE@XZ"(%"struct.test2::F"*{{[^,]*}})
+// CHECK-LABEL: define dso_local x86_thiscallcc void @"??1F@test2@@UAE@XZ"(%"struct.test2::F"*{{[^,]*}})
// Do an adjustment from C vbase subobject to F as though F was the
// complete type.
// CHECK: getelementptr inbounds i8, i8* %{{.*}}, i32 -20
@@ -207,11 +207,11 @@ F::~F() {
void foo() {
F f;
}
-// DTORS3-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_DF@test2@@QAEXXZ"({{.*}} {{.*}} comdat
+// DTORS3-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"??_DF@test2@@QAEXXZ"({{.*}} {{.*}} comdat
// Do an adjustment from C* to F*.
// DTORS3: getelementptr i8, i8* %{{.*}}, i32 20
// DTORS3: bitcast i8* %{{.*}} to %"struct.test2::F"*
-// DTORS3: call x86_thiscallcc void @"\01??1F@test2@@UAE@XZ"
+// DTORS3: call x86_thiscallcc void @"??1F@test2@@UAE@XZ"
// DTORS3: ret void
}
@@ -228,8 +228,8 @@ struct B : A {
};
B::B() {
- // CHECK: define x86_thiscallcc %"struct.constructors::B"* @"\01??0B@constructors@@QAE@XZ"(%"struct.constructors::B"* returned %this)
- // CHECK: call x86_thiscallcc %"struct.constructors::A"* @"\01??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}})
+ // CHECK: define dso_local x86_thiscallcc %"struct.constructors::B"* @"??0B@constructors@@QAE@XZ"(%"struct.constructors::B"* returned %this)
+ // CHECK: call x86_thiscallcc %"struct.constructors::A"* @"??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}})
// CHECK: ret
}
@@ -238,7 +238,7 @@ struct C : virtual A {
};
C::C() {
- // CHECK: define x86_thiscallcc %"struct.constructors::C"* @"\01??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* returned %this, i32 %is_most_derived)
+ // CHECK: define dso_local x86_thiscallcc %"struct.constructors::C"* @"??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* returned %this, i32 %is_most_derived)
// TODO: make sure this works in the Release build too;
// CHECK: store i32 %is_most_derived, i32* %[[IS_MOST_DERIVED_VAR:.*]], align 4
// CHECK: %[[IS_MOST_DERIVED_VAL:.*]] = load i32, i32* %[[IS_MOST_DERIVED_VAR]]
@@ -249,23 +249,23 @@ C::C() {
// CHECK-NEXT: %[[this_i8:.*]] = bitcast %"struct.constructors::C"* %{{.*}} to i8*
// CHECK-NEXT: %[[vbptr_off:.*]] = getelementptr inbounds i8, i8* %[[this_i8]], i32 0
// CHECK-NEXT: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i32**
- // CHECK-NEXT: store i32* getelementptr inbounds ([2 x i32], [2 x i32]* @"\01??_8C@constructors@@7B@", i32 0, i32 0), i32** %[[vbptr]]
+ // CHECK-NEXT: store i32* getelementptr inbounds ([2 x i32], [2 x i32]* @"??_8C@constructors@@7B@", i32 0, i32 0), i32** %[[vbptr]]
// CHECK-NEXT: bitcast %"struct.constructors::C"* %{{.*}} to i8*
// CHECK-NEXT: getelementptr inbounds i8, i8* %{{.*}}, i32 4
// CHECK-NEXT: bitcast i8* %{{.*}} to %"struct.constructors::A"*
- // CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"* @"\01??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}})
+ // CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"* @"??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}})
// CHECK-NEXT: br label %[[SKIP_VBASES]]
//
// CHECK: [[SKIP_VBASES]]
// Class C does not define or override methods, so shouldn't change the vfptr.
- // CHECK-NOT: @"\01??_7C@constructors@@6B@"
+ // CHECK-NOT: @"??_7C@constructors@@6B@"
// CHECK: ret
}
void create_C() {
C c;
- // CHECK: define void @"\01?create_C@constructors@@YAXXZ"()
- // CHECK: call x86_thiscallcc %"struct.constructors::C"* @"\01??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* %c, i32 1)
+ // CHECK: define dso_local void @"?create_C@constructors@@YAXXZ"()
+ // CHECK: call x86_thiscallcc %"struct.constructors::C"* @"??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* %c, i32 1)
// CHECK: ret
}
@@ -274,7 +274,7 @@ struct D : C {
};
D::D() {
- // CHECK: define x86_thiscallcc %"struct.constructors::D"* @"\01??0D@constructors@@QAE@XZ"(%"struct.constructors::D"* returned %this, i32 %is_most_derived) unnamed_addr
+ // CHECK: define dso_local x86_thiscallcc %"struct.constructors::D"* @"??0D@constructors@@QAE@XZ"(%"struct.constructors::D"* returned %this, i32 %is_most_derived) unnamed_addr
// CHECK: store i32 %is_most_derived, i32* %[[IS_MOST_DERIVED_VAR:.*]], align 4
// CHECK: %[[IS_MOST_DERIVED_VAL:.*]] = load i32, i32* %[[IS_MOST_DERIVED_VAR]]
// CHECK: %[[SHOULD_CALL_VBASE_CTORS:.*]] = icmp ne i32 %[[IS_MOST_DERIVED_VAL]], 0
@@ -284,15 +284,15 @@ D::D() {
// CHECK-NEXT: %[[this_i8:.*]] = bitcast %"struct.constructors::D"* %{{.*}} to i8*
// CHECK-NEXT: %[[vbptr_off:.*]] = getelementptr inbounds i8, i8* %[[this_i8]], i32 0
// CHECK-NEXT: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i32**
- // CHECK-NEXT: store i32* getelementptr inbounds ([2 x i32], [2 x i32]* @"\01??_8D@constructors@@7B@", i32 0, i32 0), i32** %[[vbptr]]
+ // CHECK-NEXT: store i32* getelementptr inbounds ([2 x i32], [2 x i32]* @"??_8D@constructors@@7B@", i32 0, i32 0), i32** %[[vbptr]]
// CHECK-NEXT: bitcast %"struct.constructors::D"* %{{.*}} to i8*
// CHECK-NEXT: getelementptr inbounds i8, i8* %{{.*}}, i32 4
// CHECK-NEXT: bitcast i8* %{{.*}} to %"struct.constructors::A"*
- // CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"* @"\01??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}})
+ // CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"* @"??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}})
// CHECK-NEXT: br label %[[SKIP_VBASES]]
//
// CHECK: [[SKIP_VBASES]]
- // CHECK: call x86_thiscallcc %"struct.constructors::C"* @"\01??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* %{{.*}}, i32 0)
+ // CHECK: call x86_thiscallcc %"struct.constructors::C"* @"??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* %{{.*}}, i32 0)
// CHECK: ret
}
@@ -301,7 +301,7 @@ struct E : virtual C {
};
E::E() {
- // CHECK: define x86_thiscallcc %"struct.constructors::E"* @"\01??0E@constructors@@QAE@XZ"(%"struct.constructors::E"* returned %this, i32 %is_most_derived) unnamed_addr
+ // CHECK: define dso_local x86_thiscallcc %"struct.constructors::E"* @"??0E@constructors@@QAE@XZ"(%"struct.constructors::E"* returned %this, i32 %is_most_derived) unnamed_addr
// CHECK: store i32 %is_most_derived, i32* %[[IS_MOST_DERIVED_VAR:.*]], align 4
// CHECK: %[[IS_MOST_DERIVED_VAL:.*]] = load i32, i32* %[[IS_MOST_DERIVED_VAR]]
// CHECK: %[[SHOULD_CALL_VBASE_CTORS:.*]] = icmp ne i32 %[[IS_MOST_DERIVED_VAL]], 0
@@ -311,15 +311,15 @@ E::E() {
// CHECK-NEXT: %[[this_i8:.*]] = bitcast %"struct.constructors::E"* %{{.*}} to i8*
// CHECK-NEXT: %[[offs:.*]] = getelementptr inbounds i8, i8* %[[this_i8]], i32 0
// CHECK-NEXT: %[[vbptr_E:.*]] = bitcast i8* %[[offs]] to i32**
- // CHECK-NEXT: store i32* getelementptr inbounds ([3 x i32], [3 x i32]* @"\01??_8E@constructors@@7B01@@", i32 0, i32 0), i32** %[[vbptr_E]]
+ // CHECK-NEXT: store i32* getelementptr inbounds ([3 x i32], [3 x i32]* @"??_8E@constructors@@7B01@@", i32 0, i32 0), i32** %[[vbptr_E]]
// CHECK-NEXT: %[[offs:.*]] = getelementptr inbounds i8, i8* %[[this_i8]], i32 4
// CHECK-NEXT: %[[vbptr_C:.*]] = bitcast i8* %[[offs]] to i32**
- // CHECK-NEXT: store i32* getelementptr inbounds ([2 x i32], [2 x i32]* @"\01??_8E@constructors@@7BC@1@@", i32 0, i32 0), i32** %[[vbptr_C]]
+ // CHECK-NEXT: store i32* getelementptr inbounds ([2 x i32], [2 x i32]* @"??_8E@constructors@@7BC@1@@", i32 0, i32 0), i32** %[[vbptr_C]]
// CHECK-NEXT: bitcast %"struct.constructors::E"* %{{.*}} to i8*
// CHECK-NEXT: getelementptr inbounds i8, i8* %{{.*}}, i32 4
// CHECK-NEXT: bitcast i8* %{{.*}} to %"struct.constructors::A"*
- // CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"* @"\01??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}})
- // CHECK: call x86_thiscallcc %"struct.constructors::C"* @"\01??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* %{{.*}}, i32 0)
+ // CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"* @"??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}})
+ // CHECK: call x86_thiscallcc %"struct.constructors::C"* @"??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* %{{.*}}, i32 0)
// CHECK-NEXT: br label %[[SKIP_VBASES]]
//
// CHECK: [[SKIP_VBASES]]
@@ -333,7 +333,7 @@ struct F {
};
F::F() {}
-// CHECK: define x86_thiscallcc %"struct.constructors::F"* @"\01??0F@constructors@@QAE@XZ"
+// CHECK: define dso_local x86_thiscallcc %"struct.constructors::F"* @"??0F@constructors@@QAE@XZ"
} // end namespace constructors
@@ -345,12 +345,12 @@ struct A {
void call_nv_complete(A *a) {
a->~A();
-// CHECK: define void @"\01?call_nv_complete@dtors@@YAXPAUA@1@@Z"
-// CHECK: call x86_thiscallcc void @"\01??1A@dtors@@QAE@XZ"
+// CHECK: define dso_local void @"?call_nv_complete@dtors@@YAXPAUA@1@@Z"
+// CHECK: call x86_thiscallcc void @"??1A@dtors@@QAE@XZ"
// CHECK: ret
}
-// CHECK: declare x86_thiscallcc void @"\01??1A@dtors@@QAE@XZ"
+// CHECK: declare dso_local x86_thiscallcc void @"??1A@dtors@@QAE@XZ"
// Now try some virtual bases, where we need the complete dtor.
@@ -360,24 +360,24 @@ struct D : B, C { ~D(); };
void call_vbase_complete(D *d) {
d->~D();
-// CHECK: define void @"\01?call_vbase_complete@dtors@@YAXPAUD@1@@Z"
-// CHECK: call x86_thiscallcc void @"\01??_DD@dtors@@QAEXXZ"(%"struct.dtors::D"* %{{[^,]+}})
+// CHECK: define dso_local void @"?call_vbase_complete@dtors@@YAXPAUD@1@@Z"
+// CHECK: call x86_thiscallcc void @"??_DD@dtors@@QAEXXZ"(%"struct.dtors::D"* %{{[^,]+}})
// CHECK: ret
}
// The complete dtor should call the base dtors for D and the vbase A (once).
-// CHECK: define linkonce_odr x86_thiscallcc void @"\01??_DD@dtors@@QAEXXZ"({{.*}}) {{.*}} comdat
+// CHECK: define linkonce_odr dso_local x86_thiscallcc void @"??_DD@dtors@@QAEXXZ"({{.*}}) {{.*}} comdat
// CHECK-NOT: call
-// CHECK: call x86_thiscallcc void @"\01??1D@dtors@@QAE@XZ"
+// CHECK: call x86_thiscallcc void @"??1D@dtors@@QAE@XZ"
// CHECK-NOT: call
-// CHECK: call x86_thiscallcc void @"\01??1A@dtors@@QAE@XZ"
+// CHECK: call x86_thiscallcc void @"??1A@dtors@@QAE@XZ"
// CHECK-NOT: call
// CHECK: ret
void destroy_d_complete() {
D d;
-// CHECK: define void @"\01?destroy_d_complete@dtors@@YAXXZ"
-// CHECK: call x86_thiscallcc void @"\01??_DD@dtors@@QAEXXZ"(%"struct.dtors::D"* %{{[^,]+}})
+// CHECK: define dso_local void @"?destroy_d_complete@dtors@@YAXXZ"
+// CHECK: call x86_thiscallcc void @"??_DD@dtors@@QAEXXZ"(%"struct.dtors::D"* %{{[^,]+}})
// CHECK: ret
}
@@ -386,9 +386,9 @@ void destroy_d_complete() {
// a vftable.
void call_nv_deleting_dtor(D *d) {
delete d;
-// CHECK: define void @"\01?call_nv_deleting_dtor@dtors@@YAXPAUD@1@@Z"
-// CHECK: call x86_thiscallcc void @"\01??_DD@dtors@@QAEXXZ"(%"struct.dtors::D"* %{{[^,]+}})
-// CHECK: call void @"\01??3@YAXPAX@Z"
+// CHECK: define dso_local void @"?call_nv_deleting_dtor@dtors@@YAXPAUD@1@@Z"
+// CHECK: call x86_thiscallcc void @"??_DD@dtors@@QAEXXZ"(%"struct.dtors::D"* %{{[^,]+}})
+// CHECK: call void @"??3@YAXPAX@Z"
// CHECK: ret
}
@@ -404,11 +404,11 @@ struct B : virtual A {
B::B(int *a) {}
B::B(const char *a, ...) {}
B::B(short *a) {}
-// CHECK: define x86_thiscallcc %"struct.test1::B"* @"\01??0B@test1@@QAE@PAH@Z"
+// CHECK: define dso_local x86_thiscallcc %"struct.test1::B"* @"??0B@test1@@QAE@PAH@Z"
// CHECK: (%"struct.test1::B"* returned %this, i32* %a, i32 %is_most_derived)
-// CHECK: define %"struct.test1::B"* @"\01??0B@test1@@QAA@PBDZZ"
+// CHECK: define dso_local %"struct.test1::B"* @"??0B@test1@@QAA@PBDZZ"
// CHECK: (%"struct.test1::B"* returned %this, i32 %is_most_derived, i8* %a, ...)
-// CHECK: define x86_thiscallcc %"struct.test1::B"* @"\01??0B@test1@@QAE@PAF@Z"
+// CHECK: define dso_local x86_thiscallcc %"struct.test1::B"* @"??0B@test1@@QAE@PAF@Z"
// CHECK: (%"struct.test1::B"* returned %this, i16* %a, i32 %is_most_derived)
void construct_b() {
@@ -416,10 +416,10 @@ void construct_b() {
B b1(&a);
B b2("%d %d", 1, 2);
}
-// CHECK-LABEL: define void @"\01?construct_b@test1@@YAXXZ"()
-// CHECK: call x86_thiscallcc %"struct.test1::B"* @"\01??0B@test1@@QAE@PAH@Z"
+// CHECK-LABEL: define dso_local void @"?construct_b@test1@@YAXXZ"()
+// CHECK: call x86_thiscallcc %"struct.test1::B"* @"??0B@test1@@QAE@PAH@Z"
// CHECK: (%"struct.test1::B"* {{.*}}, i32* {{.*}}, i32 1)
-// CHECK: call %"struct.test1::B"* (%"struct.test1::B"*, i32, i8*, ...) @"\01??0B@test1@@QAA@PBDZZ"
+// CHECK: call %"struct.test1::B"* (%"struct.test1::B"*, i32, i8*, ...) @"??0B@test1@@QAA@PBDZZ"
// CHECK: (%"struct.test1::B"* {{.*}}, i32 1, i8* {{.*}}, i32 1, i32 2)
}
@@ -432,7 +432,7 @@ struct ImplicitCopy {
void CreateCopy(ImplicitCopy *a) {
new ImplicitCopy(*a);
}
-// CHECK: store {{.*}} @"\01??_7ImplicitCopy@implicit_copy_vtable@@6B@"
+// CHECK: store {{.*}} @"??_7ImplicitCopy@implicit_copy_vtable@@6B@"
struct MoveOnly {
MoveOnly(MoveOnly &&o) = default;
@@ -440,7 +440,7 @@ struct MoveOnly {
};
MoveOnly &&f();
void g() { new MoveOnly(f()); }
-// CHECK: store {{.*}} @"\01??_7MoveOnly@implicit_copy_vtable@@6B@"
+// CHECK: store {{.*}} @"??_7MoveOnly@implicit_copy_vtable@@6B@"
}
namespace delegating_ctor {
@@ -451,11 +451,11 @@ struct X : virtual Y {
};
X::X(int) : X() {}
}
-// CHECK: define x86_thiscallcc %"struct.delegating_ctor::X"* @"\01??0X@delegating_ctor@@QAE@H@Z"(
+// CHECK: define dso_local x86_thiscallcc %"struct.delegating_ctor::X"* @"??0X@delegating_ctor@@QAE@H@Z"(
// CHECK: %[[is_most_derived_addr:.*]] = alloca i32, align 4
// CHECK: store i32 %is_most_derived, i32* %[[is_most_derived_addr]]
// CHECK: %[[is_most_derived:.*]] = load i32, i32* %[[is_most_derived_addr]]
-// CHECK: call x86_thiscallcc {{.*}}* @"\01??0X@delegating_ctor@@QAE@XZ"({{.*}} i32 %[[is_most_derived]])
+// CHECK: call x86_thiscallcc {{.*}}* @"??0X@delegating_ctor@@QAE@XZ"({{.*}} i32 %[[is_most_derived]])
// Dtor thunks for classes in anonymous namespaces should be internal, not
// linkonce_odr.
@@ -467,9 +467,9 @@ struct A {
void *getA() {
return (void*)new A();
}
-// CHECK: define internal x86_thiscallcc i8* @"\01??_GA@?A@@UAEPAXI@Z"
+// CHECK: define internal x86_thiscallcc i8* @"??_GA@?A@@UAEPAXI@Z"
// CHECK: (%"struct.(anonymous namespace)::A"* %this, i32 %should_call_delete)
-// CHECK: define internal x86_thiscallcc void @"\01??1A@?A@@UAE@XZ"
+// CHECK: define internal x86_thiscallcc void @"??1A@?A@@UAE@XZ"
// CHECK: (%"struct.(anonymous namespace)::A"* %this)
// Check that we correctly transform __stdcall to __thiscall for ctors and
@@ -477,9 +477,9 @@ void *getA() {
class G {
public:
__stdcall G() {};
-// DTORS4: define linkonce_odr x86_thiscallcc %class.G* @"\01??0G@@QAE@XZ"
+// DTORS4: define linkonce_odr dso_local x86_thiscallcc %class.G* @"??0G@@QAE@XZ"
__stdcall ~G() {};
-// DTORS4: define linkonce_odr x86_thiscallcc void @"\01??1G@@QAE@XZ"
+// DTORS4: define linkonce_odr dso_local x86_thiscallcc void @"??1G@@QAE@XZ"
};
extern void testG() {
diff --git a/test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp b/test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp
index 3f53e631c964..a5bb87414d6a 100644
--- a/test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp
+++ b/test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp
@@ -6,79 +6,79 @@ struct S {
~S();
};
-// CHECK-DAG: @"\01?s@?1??f@@YAAAUS@@XZ@4U2@A" = linkonce_odr thread_local global %struct.S zeroinitializer
-// CHECK-DAG: @"\01??__J?1??f@@YAAAUS@@XZ@51" = linkonce_odr thread_local global i32 0
-// CHECK-DAG: @"\01?s@?1??g@@YAAAUS@@XZ@4U2@A" = linkonce_odr global %struct.S zeroinitializer
-// CHECK-DAG: @"\01?$TSS0@?1??g@@YAAAUS@@XZ@4HA" = linkonce_odr global i32 0
+// CHECK-DAG: @"?s@?1??f@@YAAAUS@@XZ@4U2@A" = linkonce_odr dso_local thread_local global %struct.S zeroinitializer
+// CHECK-DAG: @"??__J?1??f@@YAAAUS@@XZ@51" = linkonce_odr thread_local global i32 0
+// CHECK-DAG: @"?s@?1??g@@YAAAUS@@XZ@4U2@A" = linkonce_odr dso_local global %struct.S zeroinitializer
+// CHECK-DAG: @"?$TSS0@?1??g@@YAAAUS@@XZ@4HA" = linkonce_odr global i32 0
// CHECK-DAG: @_Init_thread_epoch = external thread_local global i32, align 4
-// CHECK-DAG: @"\01?j@?1??h@@YAAAUS@@_N@Z@4U2@A" = linkonce_odr thread_local global %struct.S zeroinitializer
-// CHECK-DAG: @"\01??__J?1??h@@YAAAUS@@_N@Z@51" = linkonce_odr thread_local global i32 0
-// CHECK-DAG: @"\01?i@?1??h@@YAAAUS@@_N@Z@4U2@A" = linkonce_odr global %struct.S zeroinitializer
-// CHECK-DAG: @"\01?$TSS0@?1??h@@YAAAUS@@_N@Z@4HA" = linkonce_odr global i32 0
-// CHECK-DAG: @"\01?i@?1??g1@@YAHXZ@4HA" = internal global i32 0, align 4
-// CHECK-DAG: @"\01?$TSS0@?1??g1@@YAHXZ@4HA" = internal global i32 0, align 4
+// CHECK-DAG: @"?j@?1??h@@YAAAUS@@_N@Z@4U2@A" = linkonce_odr dso_local thread_local global %struct.S zeroinitializer
+// CHECK-DAG: @"??__J?1??h@@YAAAUS@@_N@Z@51" = linkonce_odr thread_local global i32 0
+// CHECK-DAG: @"?i@?1??h@@YAAAUS@@_N@Z@4U2@A" = linkonce_odr dso_local global %struct.S zeroinitializer
+// CHECK-DAG: @"?$TSS0@?1??h@@YAAAUS@@_N@Z@4HA" = linkonce_odr global i32 0
+// CHECK-DAG: @"?i@?1??g1@@YAHXZ@4HA" = internal global i32 0, align 4
+// CHECK-DAG: @"?$TSS0@?1??g1@@YAHXZ@4HA" = internal global i32 0, align 4
-// CHECK-LABEL: define {{.*}} @"\01?f@@YAAAUS@@XZ"()
+// CHECK-LABEL: define {{.*}} @"?f@@YAAAUS@@XZ"()
// CHECK-SAME: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
extern inline S &f() {
static thread_local S s;
-// CHECK: %[[guard:.*]] = load i32, i32* @"\01??__J?1??f@@YAAAUS@@XZ@51"
+// CHECK: %[[guard:.*]] = load i32, i32* @"??__J?1??f@@YAAAUS@@XZ@51"
// CHECK-NEXT: %[[mask:.*]] = and i32 %[[guard]], 1
// CHECK-NEXT: %[[cmp:.*]] = icmp eq i32 %[[mask]], 0
// CHECK-NEXT: br i1 %[[cmp]], label %[[init:.*]], label %[[init_end:.*]], !prof ![[unlikely_threadlocal:.*]]
//
// CHECK: [[init]]:
// CHECK-NEXT: %[[or:.*]] = or i32 %[[guard]], 1
-// CHECK-NEXT: store i32 %[[or]], i32* @"\01??__J?1??f@@YAAAUS@@XZ@51"
-// CHECK-NEXT: invoke {{.*}} @"\01??0S@@QAE@XZ"(%struct.S* @"\01?s@?1??f@@YAAAUS@@XZ@4U2@A")
+// CHECK-NEXT: store i32 %[[or]], i32* @"??__J?1??f@@YAAAUS@@XZ@51"
+// CHECK-NEXT: invoke {{.*}} @"??0S@@QAE@XZ"(%struct.S* @"?s@?1??f@@YAAAUS@@XZ@4U2@A")
// CHECK-NEXT: to label %[[invoke_cont:.*]] unwind label %[[lpad:.*]]
//
// CHECK: [[invoke_cont]]:
-// CHECK-NEXT: call i32 @__tlregdtor(void ()* @"\01??__Fs@?1??f@@YAAAUS@@XZ@YAXXZ")
+// CHECK-NEXT: call i32 @__tlregdtor(void ()* @"??__Fs@?1??f@@YAAAUS@@XZ@YAXXZ")
// CHECK-NEXT: br label %[[init_end:.*]]
// CHECK: [[init_end]]:
-// CHECK-NEXT: ret %struct.S* @"\01?s@?1??f@@YAAAUS@@XZ@4U2@A"
+// CHECK-NEXT: ret %struct.S* @"?s@?1??f@@YAAAUS@@XZ@4U2@A"
// CHECK: [[lpad:.*]]:
// CHECK-NEXT: cleanuppad within none []
-// CHECK: %[[guard:.*]] = load i32, i32* @"\01??__J?1??f@@YAAAUS@@XZ@51"
+// CHECK: %[[guard:.*]] = load i32, i32* @"??__J?1??f@@YAAAUS@@XZ@51"
// CHECK-NEXT: %[[mask:.*]] = and i32 %[[guard]], -2
-// CHECK-NEXT: store i32 %[[mask]], i32* @"\01??__J?1??f@@YAAAUS@@XZ@51"
+// CHECK-NEXT: store i32 %[[mask]], i32* @"??__J?1??f@@YAAAUS@@XZ@51"
// CHECK-NEXT: cleanupret {{.*}} unwind to caller
return s;
}
-// CHECK-LABEL: define {{.*}} @"\01?g@@YAAAUS@@XZ"()
+// CHECK-LABEL: define {{.*}} @"?g@@YAAAUS@@XZ"()
extern inline S &g() {
static S s;
-// CHECK: %[[guard:.*]] = load atomic i32, i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ@4HA" unordered, align 4
+// CHECK: %[[guard:.*]] = load atomic i32, i32* @"?$TSS0@?1??g@@YAAAUS@@XZ@4HA" unordered, align 4
// CHECK-NEXT: %[[epoch:.*]] = load i32, i32* @_Init_thread_epoch
// CHECK-NEXT: %[[cmp:.*]] = icmp sgt i32 %[[guard]], %[[epoch]]
// CHECK-NEXT: br i1 %[[cmp]], label %[[init_attempt:.*]], label %[[init_end:.*]], !prof ![[unlikely_staticlocal:.*]]
//
// CHECK: [[init_attempt]]:
-// CHECK-NEXT: call void @_Init_thread_header(i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ@4HA")
-// CHECK-NEXT: %[[guard2:.*]] = load atomic i32, i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ@4HA" unordered, align 4
+// CHECK-NEXT: call void @_Init_thread_header(i32* @"?$TSS0@?1??g@@YAAAUS@@XZ@4HA")
+// CHECK-NEXT: %[[guard2:.*]] = load atomic i32, i32* @"?$TSS0@?1??g@@YAAAUS@@XZ@4HA" unordered, align 4
// CHECK-NEXT: %[[cmp2:.*]] = icmp eq i32 %[[guard2]], -1
// CHECK-NEXT: br i1 %[[cmp2]], label %[[init:.*]], label %[[init_end:.*]]
//
// CHECK: [[init]]:
-// CHECK-NEXT: invoke {{.*}} @"\01??0S@@QAE@XZ"(%struct.S* @"\01?s@?1??g@@YAAAUS@@XZ@4U2@A")
+// CHECK-NEXT: invoke {{.*}} @"??0S@@QAE@XZ"(%struct.S* @"?s@?1??g@@YAAAUS@@XZ@4U2@A")
// CHECK-NEXT: to label %[[invoke_cont:.*]] unwind label %[[lpad:.*]]
//
// CHECK: [[invoke_cont]]:
-// CHECK-NEXT: call i32 @atexit(void ()* @"\01??__Fs@?1??g@@YAAAUS@@XZ@YAXXZ")
-// CHECK-NEXT: call void @_Init_thread_footer(i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ@4HA")
+// CHECK-NEXT: call i32 @atexit(void ()* @"??__Fs@?1??g@@YAAAUS@@XZ@YAXXZ")
+// CHECK-NEXT: call void @_Init_thread_footer(i32* @"?$TSS0@?1??g@@YAAAUS@@XZ@4HA")
// CHECK-NEXT: br label %init.end
//
// CHECK: [[init_end]]:
-// CHECK-NEXT: ret %struct.S* @"\01?s@?1??g@@YAAAUS@@XZ@4U2@A"
+// CHECK-NEXT: ret %struct.S* @"?s@?1??g@@YAAAUS@@XZ@4U2@A"
//
// CHECK: [[lpad]]:
// CHECK-NEXT: cleanuppad within none []
-// CHECK: call void @_Init_thread_abort(i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ@4HA")
+// CHECK: call void @_Init_thread_abort(i32* @"?$TSS0@?1??g@@YAAAUS@@XZ@4HA")
// CHECK-NEXT: cleanupret {{.*}} unwind to caller
return s;
}
@@ -89,7 +89,7 @@ extern inline S&h(bool b) {
return b ? j : i;
}
-// CHECK-LABEL: define i32 @"\01?g1@@YAHXZ"()
+// CHECK-LABEL: define dso_local i32 @"?g1@@YAHXZ"()
int f1();
int g1() {
static int i = f1();
diff --git a/test/CodeGenCXX/microsoft-abi-throw.cpp b/test/CodeGenCXX/microsoft-abi-throw.cpp
index 51076f841611..cbbce2daaad8 100644
--- a/test/CodeGenCXX/microsoft-abi-throw.cpp
+++ b/test/CodeGenCXX/microsoft-abi-throw.cpp
@@ -1,27 +1,28 @@
// RUN: %clang_cc1 -emit-llvm -o - -triple=i386-pc-win32 -std=c++11 %s -fcxx-exceptions -fms-extensions | FileCheck %s
// RUN: %clang_cc1 -emit-llvm -o - -triple=i386-pc-win32 -std=c++11 %s -fcxx-exceptions -fms-extensions -DSTD | FileCheck %s
-// CHECK-DAG: @"\01??_R0?AUY@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUY@@\00" }, comdat
-// CHECK-DAG: @"_CT??_R0?AUY@@@8??0Y@@QAE@ABU0@@Z8" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 4, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUY@@@8" to i8*), i32 0, i32 -1, i32 0, i32 8, i8* bitcast (%struct.Y* (%struct.Y*, %struct.Y*, i32)* @"\01??0Y@@QAE@ABU0@@Z" to i8*) }, section ".xdata", comdat
-// CHECK-DAG: @"\01??_R0?AUZ@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUZ@@\00" }, comdat
-// CHECK-DAG: @"_CT??_R0?AUZ@@@81" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUZ@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* null }, section ".xdata", comdat
-// CHECK-DAG: @"\01??_R0?AUW@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUW@@\00" }, comdat
-// CHECK-DAG: @"_CT??_R0?AUW@@@8??0W@@QAE@ABU0@@Z44" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 4, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUW@@@8" to i8*), i32 4, i32 -1, i32 0, i32 4, i8* bitcast (%struct.W* (%struct.W*, %struct.W*, i32)* @"\01??0W@@QAE@ABU0@@Z" to i8*) }, section ".xdata", comdat
-// CHECK-DAG: @"\01??_R0?AUM@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUM@@\00" }, comdat
-// CHECK-DAG: @"_CT??_R0?AUM@@@818" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUM@@@8" to i8*), i32 8, i32 -1, i32 0, i32 1, i8* null }, section ".xdata", comdat
-// CHECK-DAG: @"\01??_R0?AUV@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUV@@\00" }, comdat
-// CHECK-DAG: @"_CT??_R0?AUV@@@81044" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUV@@@8" to i8*), i32 0, i32 4, i32 4, i32 1, i8* null }, section ".xdata", comdat
+// CHECK-DAG: @"??_R0?AUY@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUY@@\00" }, comdat
+// CHECK-DAG: @"_CT??_R0?AUY@@@8??0Y@@QAE@ABU0@@Z8" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 4, i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUY@@@8" to i8*), i32 0, i32 -1, i32 0, i32 8, i8* bitcast (%struct.Y* (%struct.Y*, %struct.Y*, i32)* @"??0Y@@QAE@ABU0@@Z" to i8*) }, section ".xdata", comdat
+// CHECK-DAG: @"??_R0?AUZ@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUZ@@\00" }, comdat
+// CHECK-DAG: @"_CT??_R0?AUZ@@@81" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUZ@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* null }, section ".xdata", comdat
+// CHECK-DAG: @"??_R0?AUW@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUW@@\00" }, comdat
+// CHECK-DAG: @"_CT??_R0?AUW@@@8??0W@@QAE@ABU0@@Z44" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 4, i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUW@@@8" to i8*), i32 4, i32 -1, i32 0, i32 4, i8* bitcast (%struct.W* (%struct.W*, %struct.W*, i32)* @"??0W@@QAE@ABU0@@Z" to i8*) }, section ".xdata", comdat
+// CHECK-DAG: @"??_R0?AUM@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUM@@\00" }, comdat
+// CHECK-DAG: @"_CT??_R0?AUM@@@818" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUM@@@8" to i8*), i32 8, i32 -1, i32 0, i32 1, i8* null }, section ".xdata", comdat
+// CHECK-DAG: @"??_R0?AUV@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUV@@\00" }, comdat
+// CHECK-DAG: @"_CT??_R0?AUV@@@81044" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUV@@@8" to i8*), i32 0, i32 4, i32 4, i32 1, i8* null }, section ".xdata", comdat
// CHECK-DAG: @"_CTA5?AUY@@" = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.5 { i32 5, [5 x %eh.CatchableType*] [%eh.CatchableType* @"_CT??_R0?AUY@@@8??0Y@@QAE@ABU0@@Z8", %eh.CatchableType* @"_CT??_R0?AUZ@@@81", %eh.CatchableType* @"_CT??_R0?AUW@@@8??0W@@QAE@ABU0@@Z44", %eh.CatchableType* @"_CT??_R0?AUM@@@818", %eh.CatchableType* @"_CT??_R0?AUV@@@81044"] }, section ".xdata", comdat
-// CHECK-DAG: @"_TI5?AUY@@" = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, i8* bitcast (void (%struct.Y*)* @"\01??_DY@@QAEXXZ" to i8*), i8* null, i8* bitcast (%eh.CatchableTypeArray.5* @"_CTA5?AUY@@" to i8*) }, section ".xdata", comdat
-// CHECK-DAG: @"_CT??_R0?AUDefault@@@8??_ODefault@@QAEXAAU0@@Z1" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor13* @"\01??_R0?AUDefault@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* bitcast (void (%struct.Default*, %struct.Default*)* @"\01??_ODefault@@QAEXAAU0@@Z" to i8*) }, section ".xdata", comdat
-// CHECK-DAG: @"_CT??_R0?AUVariadic@@@8??_OVariadic@@QAEXAAU0@@Z1" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor14* @"\01??_R0?AUVariadic@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* bitcast (void (%struct.Variadic*, %struct.Variadic*)* @"\01??_OVariadic@@QAEXAAU0@@Z" to i8*) }, section ".xdata", comdat
-// CHECK-DAG: @"_CT??_R0?AUTemplateWithDefault@@@8??$?_OH@TemplateWithDefault@@QAEXAAU0@@Z1" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor25* @"\01??_R0?AUTemplateWithDefault@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* bitcast (void (%struct.TemplateWithDefault*, %struct.TemplateWithDefault*)* @"\01??$?_OH@TemplateWithDefault@@QAEXAAU0@@Z" to i8*) }, section ".xdata", comdat
+// CHECK-DAG: @"_TI5?AUY@@" = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, i8* bitcast (void (%struct.Y*)* @"??_DY@@QAEXXZ" to i8*), i8* null, i8* bitcast (%eh.CatchableTypeArray.5* @"_CTA5?AUY@@" to i8*) }, section ".xdata", comdat
+// CHECK-DAG: @"_CT??_R0?AUDefault@@@8??_ODefault@@QAEXAAU0@@Z1" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor13* @"??_R0?AUDefault@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* bitcast (void (%struct.Default*, %struct.Default*)* @"??_ODefault@@QAEXAAU0@@Z" to i8*) }, section ".xdata", comdat
+// CHECK-DAG: @"_CT??_R0?AUVariadic@@@8??_OVariadic@@QAEXAAU0@@Z1" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor14* @"??_R0?AUVariadic@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* bitcast (void (%struct.Variadic*, %struct.Variadic*)* @"??_OVariadic@@QAEXAAU0@@Z" to i8*) }, section ".xdata", comdat
+// CHECK-DAG: @"_CT??_R0?AUTemplateWithDefault@@@8??$?_OH@TemplateWithDefault@@QAEXAAU0@@Z1" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor25* @"??_R0?AUTemplateWithDefault@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* bitcast (void (%struct.TemplateWithDefault*, %struct.TemplateWithDefault*)* @"??$?_OH@TemplateWithDefault@@QAEXAAU0@@Z" to i8*) }, section ".xdata", comdat
// CHECK-DAG: @"_CTA2$$T" = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.2 { i32 2, [2 x %eh.CatchableType*] [%eh.CatchableType* @"_CT??_R0$$T@84", %eh.CatchableType* @"_CT??_R0PAX@84"] }, section ".xdata", comdat
-// CHECK-DAG: @"_CT??_R0P6AXXZ@84" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 1, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0P6AXXZ@8" to i8*), i32 0, i32 -1, i32 0, i32 4, i8* null }, section ".xdata", comdat
+// CHECK-DAG: @"_CT??_R0P6AXXZ@84" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 1, i8* bitcast (%rtti.TypeDescriptor7* @"??_R0P6AXXZ@8" to i8*), i32 0, i32 -1, i32 0, i32 4, i8* null }, section ".xdata", comdat
// CHECK-DAG: @_CTA1P6AXXZ = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.1 { i32 1, [1 x %eh.CatchableType*] [%eh.CatchableType* @"_CT??_R0P6AXXZ@84"] }, section ".xdata", comdat
// CHECK-DAG: @_TI1P6AXXZ = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, i8* null, i8* null, i8* bitcast (%eh.CatchableTypeArray.1* @_CTA1P6AXXZ to i8*) }, section ".xdata", comdat
// CHECK-DAG: @_TIU2PAPFAH = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 4, i8* null, i8* null, i8* bitcast (%eh.CatchableTypeArray.2* @_CTA2PAPFAH to i8*) }, section ".xdata", comdat
// CHECK-DAG: @_CTA2PAPFAH = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.2 { i32 2, [2 x %eh.CatchableType*] [%eh.CatchableType* @"_CT??_R0PAPFAH@84", %eh.CatchableType* @"_CT??_R0PAX@84"] }, section ".xdata", comdat
+// CHECK-DAG: @"_TI1?AUFoo@?A@@" = internal unnamed_addr constant %eh.ThrowInfo { i32 0, i8* null, i8* null, i8* bitcast (%eh.CatchableTypeArray.1* @"_CTA1?AUFoo@?A@@" to i8*) }, section ".xdata"
struct N { ~N(); };
@@ -33,21 +34,21 @@ struct W : M, virtual V {};
struct Y : Z, W, virtual V {};
void f(const Y &y) {
- // CHECK-LABEL: @"\01?f@@YAXABUY@@@Z"
- // CHECK: call x86_thiscallcc %struct.Y* @"\01??0Y@@QAE@ABU0@@Z"(%struct.Y* %[[mem:.*]], %struct.Y*
+ // CHECK-LABEL: @"?f@@YAXABUY@@@Z"
+ // CHECK: call x86_thiscallcc %struct.Y* @"??0Y@@QAE@ABU0@@Z"(%struct.Y* %[[mem:.*]], %struct.Y*
// CHECK: %[[cast:.*]] = bitcast %struct.Y* %[[mem]] to i8*
// CHECK: call void @_CxxThrowException(i8* %[[cast]], %eh.ThrowInfo* @"_TI5?AUY@@")
throw y;
}
void g(const int *const *y) {
- // CHECK-LABEL: @"\01?g@@YAXPBQBH@Z"
+ // CHECK-LABEL: @"?g@@YAXPBQBH@Z"
// CHECK: call void @_CxxThrowException(i8* %{{.*}}, %eh.ThrowInfo* @_TIC2PAPBH)
throw y;
}
void h(__unaligned int * __unaligned *y) {
- // CHECK-LABEL: @"\01?h@@YAXPFAPFAH@Z"
+ // CHECK-LABEL: @"?h@@YAXPFAPFAH@Z"
// CHECK: call void @_CxxThrowException(i8* %{{.*}}, %eh.ThrowInfo* @_TIU2PAPFAH)
throw y;
}
@@ -56,14 +57,14 @@ struct Default {
Default(Default &, int = 42);
};
-// CHECK-LABEL: @"\01??_ODefault@@QAEXAAU0@@Z"
+// CHECK-LABEL: @"??_ODefault@@QAEXAAU0@@Z"
// CHECK: %[[src_addr:.*]] = alloca
// CHECK: %[[this_addr:.*]] = alloca
// CHECK: store {{.*}} %src, {{.*}} %[[src_addr]], align 4
// CHECK: store {{.*}} %this, {{.*}} %[[this_addr]], align 4
// CHECK: %[[this:.*]] = load {{.*}} %[[this_addr]]
// CHECK: %[[src:.*]] = load {{.*}} %[[src_addr]]
-// CHECK: call x86_thiscallcc {{.*}} @"\01??0Default@@QAE@AAU0@H@Z"({{.*}} %[[this]], {{.*}} %[[src]], i32 42)
+// CHECK: call x86_thiscallcc {{.*}} @"??0Default@@QAE@AAU0@H@Z"({{.*}} %[[this]], {{.*}} %[[src]], i32 42)
// CHECK: ret void
void h(Default &d) {
@@ -78,14 +79,14 @@ void i(Variadic &v) {
throw v;
}
-// CHECK-LABEL: @"\01??_OVariadic@@QAEXAAU0@@Z"
+// CHECK-LABEL: @"??_OVariadic@@QAEXAAU0@@Z"
// CHECK: %[[src_addr:.*]] = alloca
// CHECK: %[[this_addr:.*]] = alloca
// CHECK: store {{.*}} %src, {{.*}} %[[src_addr:.*]], align
// CHECK: store {{.*}} %this, {{.*}} %[[this_addr:.*]], align
// CHECK: %[[this:.*]] = load {{.*}} %[[this_addr]]
// CHECK: %[[src:.*]] = load {{.*}} %[[src_addr]]
-// CHECK: call {{.*}} @"\01??0Variadic@@QAA@AAU0@ZZ"({{.*}} %[[this]], {{.*}} %[[src]])
+// CHECK: call {{.*}} @"??0Variadic@@QAA@AAU0@ZZ"({{.*}} %[[this]], {{.*}} %[[src]])
// CHECK: ret void
struct TemplateWithDefault {
@@ -118,13 +119,22 @@ void *__GetExceptionInfo(T);
using namespace std;
void *GetExceptionInfo_test0() {
-// CHECK-LABEL: @"\01?GetExceptionInfo_test0@@YAPAXXZ"
+// CHECK-LABEL: @"?GetExceptionInfo_test0@@YAPAXXZ"
// CHECK: ret i8* bitcast (%eh.ThrowInfo* @_TI1H to i8*)
return __GetExceptionInfo(0);
}
void *GetExceptionInfo_test1() {
-// CHECK-LABEL: @"\01?GetExceptionInfo_test1@@YAPAXXZ"
+// CHECK-LABEL: @"?GetExceptionInfo_test1@@YAPAXXZ"
// CHECK: ret i8* bitcast (%eh.ThrowInfo* @_TI1P6AXXZ to i8*)
return __GetExceptionInfo<void (*)()>(&h);
}
+
+// PR36327: Try an exception type with no linkage.
+namespace { struct Foo { } foo_exc; }
+
+void *GetExceptionInfo_test2() {
+// CHECK-LABEL: @"?GetExceptionInfo_test2@@YAPAXXZ"
+// CHECK: ret i8* bitcast (%eh.ThrowInfo* @"_TI1?AUFoo@?A@@" to i8*)
+ return __GetExceptionInfo(foo_exc);
+}
diff --git a/test/CodeGenCXX/microsoft-abi-thunks.cpp b/test/CodeGenCXX/microsoft-abi-thunks.cpp
index 823033461612..c2f64f38417c 100644
--- a/test/CodeGenCXX/microsoft-abi-thunks.cpp
+++ b/test/CodeGenCXX/microsoft-abi-thunks.cpp
@@ -10,7 +10,7 @@ struct A {
virtual ~A();
virtual void public_f();
// Make sure we don't emit unneeded thunks:
- // XMANGLING-NOT: @"\01?public_f@A@@QAEXXZ"
+ // XMANGLING-NOT: @"?public_f@A@@QAEXXZ"
protected:
virtual void protected_f();
private:
@@ -31,45 +31,45 @@ struct C : A, B {
C();
virtual ~C();
- // MANGLING-DAG: declare {{.*}} @"\01??1C@@UAE@XZ"({{.*}})
- // MANGLING-DAG: define {{.*}} @"\01??_GC@@UAEPAXI@Z"({{.*}})
- // MANGLING-DAG: define {{.*}} @"\01??_EC@@W3AEPAXI@Z"({{.*}}) {{.*}} comdat
- // MANGLING-X64-DAG: declare {{.*}} @"\01??1C@@UEAA@XZ"({{.*}})
- // MANGLING-X64-DAG: define {{.*}} @"\01??_GC@@UEAAPEAXI@Z"({{.*}})
- // MANGLING-X64-DAG: define {{.*}} @"\01??_EC@@W7EAAPEAXI@Z"({{.*}}) {{.*}} comdat
+ // MANGLING-DAG: declare {{.*}} @"??1C@@UAE@XZ"({{.*}})
+ // MANGLING-DAG: define {{.*}} @"??_GC@@UAEPAXI@Z"({{.*}})
+ // MANGLING-DAG: define {{.*}} @"??_EC@@W3AEPAXI@Z"({{.*}}) {{.*}} comdat
+ // MANGLING-X64-DAG: declare {{.*}} @"??1C@@UEAA@XZ"({{.*}})
+ // MANGLING-X64-DAG: define {{.*}} @"??_GC@@UEAAPEAXI@Z"({{.*}})
+ // MANGLING-X64-DAG: define {{.*}} @"??_EC@@W7EAAPEAXI@Z"({{.*}}) {{.*}} comdat
// Overrides public_f() of two subobjects with distinct vfptrs, thus needs a thunk.
virtual void public_f();
- // MANGLING-DAG: @"\01?public_f@C@@UAEXXZ"
- // MANGLING-DAG: @"\01?public_f@C@@W3AEXXZ"
- // MANGLING-X64-DAG: @"\01?public_f@C@@UEAAXXZ"
- // MANGLING-X64-DAG: @"\01?public_f@C@@W7EAAXXZ"
+ // MANGLING-DAG: @"?public_f@C@@UAEXXZ"
+ // MANGLING-DAG: @"?public_f@C@@W3AEXXZ"
+ // MANGLING-X64-DAG: @"?public_f@C@@UEAAXXZ"
+ // MANGLING-X64-DAG: @"?public_f@C@@W7EAAXXZ"
protected:
virtual void protected_f();
- // MANGLING-DAG: @"\01?protected_f@C@@MAEXXZ"
- // MANGLING-DAG: @"\01?protected_f@C@@O3AEXXZ"
- // MANGLING-X64-DAG: @"\01?protected_f@C@@MEAAXXZ"
- // MANGLING-X64-DAG: @"\01?protected_f@C@@O7EAAXXZ"
+ // MANGLING-DAG: @"?protected_f@C@@MAEXXZ"
+ // MANGLING-DAG: @"?protected_f@C@@O3AEXXZ"
+ // MANGLING-X64-DAG: @"?protected_f@C@@MEAAXXZ"
+ // MANGLING-X64-DAG: @"?protected_f@C@@O7EAAXXZ"
private:
virtual void private_f();
- // MANGLING-DAG: @"\01?private_f@C@@EAEXXZ"
- // MANGLING-DAG: @"\01?private_f@C@@G3AEXXZ"
- // MANGLING-X64-DAG: @"\01?private_f@C@@EEAAXXZ"
- // MANGLING-X64-DAG: @"\01?private_f@C@@G7EAAXXZ"
+ // MANGLING-DAG: @"?private_f@C@@EAEXXZ"
+ // MANGLING-DAG: @"?private_f@C@@G3AEXXZ"
+ // MANGLING-X64-DAG: @"?private_f@C@@EEAAXXZ"
+ // MANGLING-X64-DAG: @"?private_f@C@@G7EAAXXZ"
};
C::C() {} // Emits vftable and forces thunk generation.
-// CODEGEN-LABEL: define linkonce_odr x86_thiscallcc i8* @"\01??_EC@@W3AEPAXI@Z"(%struct.C* %this, i32 %should_call_delete) {{.*}} comdat
+// CODEGEN-LABEL: define linkonce_odr dso_local x86_thiscallcc i8* @"??_EC@@W3AEPAXI@Z"(%struct.C* %this, i32 %should_call_delete) {{.*}} comdat
// CODEGEN: getelementptr i8, i8* {{.*}}, i32 -4
// FIXME: should actually call _EC, not _GC.
-// CODEGEN: call x86_thiscallcc i8* @"\01??_GC@@UAEPAXI@Z"
+// CODEGEN: call x86_thiscallcc i8* @"??_GC@@UAEPAXI@Z"
// CODEGEN: ret
-// CODEGEN-LABEL: define linkonce_odr x86_thiscallcc void @"\01?public_f@C@@W3AEXXZ"(%struct.C*
+// CODEGEN-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"?public_f@C@@W3AEXXZ"(%struct.C*
// CODEGEN: getelementptr i8, i8* {{.*}}, i32 -4
-// CODEGEN: call x86_thiscallcc void @"\01?public_f@C@@UAEXXZ"(%struct.C*
+// CODEGEN: call x86_thiscallcc void @"?public_f@C@@UAEXXZ"(%struct.C*
// CODEGEN: ret
void zoo(C* obj) {
@@ -83,16 +83,16 @@ struct D {
struct E : D {
E();
virtual C* goo();
- // MANGLING-DAG: @"\01?goo@E@@UAEPAUC@@XZ"
- // MANGLING-DAG: @"\01?goo@E@@QAEPAUB@@XZ"
- // MANGLING-X64-DAG: @"\01?goo@E@@UEAAPEAUC@@XZ"
- // MANGLING-X64-DAG: @"\01?goo@E@@QEAAPEAUB@@XZ"
+ // MANGLING-DAG: @"?goo@E@@UAEPAUC@@XZ"
+ // MANGLING-DAG: @"?goo@E@@QAEPAUB@@XZ"
+ // MANGLING-X64-DAG: @"?goo@E@@UEAAPEAUC@@XZ"
+ // MANGLING-X64-DAG: @"?goo@E@@QEAAPEAUB@@XZ"
};
E::E() {} // Emits vftable and forces thunk generation.
-// CODEGEN-LABEL: define weak_odr x86_thiscallcc %struct.C* @"\01?goo@E@@QAEPAUB@@XZ"{{.*}} comdat
-// CODEGEN: call x86_thiscallcc %struct.C* @"\01?goo@E@@UAEPAUC@@XZ"
+// CODEGEN-LABEL: define weak_odr dso_local x86_thiscallcc %struct.C* @"?goo@E@@QAEPAUB@@XZ"{{.*}} comdat
+// CODEGEN: call x86_thiscallcc %struct.C* @"?goo@E@@UAEPAUC@@XZ"
// CODEGEN: getelementptr inbounds i8, i8* {{.*}}, i32 4
// CODEGEN: ret
@@ -107,12 +107,12 @@ struct G : C { };
struct H : E {
virtual G* goo();
- // MANGLING-DAG: @"\01?goo@H@@UAEPAUG@@XZ"
- // MANGLING-DAG: @"\01?goo@H@@QAEPAUB@@XZ"
- // MANGLING-DAG: @"\01?goo@H@@QAEPAUC@@XZ"
- // MANGLING-X64-DAG: @"\01?goo@H@@UEAAPEAUG@@XZ"
- // MANGLING-X64-DAG: @"\01?goo@H@@QEAAPEAUB@@XZ"
- // MANGLING-X64-DAG: @"\01?goo@H@@QEAAPEAUC@@XZ"
+ // MANGLING-DAG: @"?goo@H@@UAEPAUG@@XZ"
+ // MANGLING-DAG: @"?goo@H@@QAEPAUB@@XZ"
+ // MANGLING-DAG: @"?goo@H@@QAEPAUC@@XZ"
+ // MANGLING-X64-DAG: @"?goo@H@@UEAAPEAUG@@XZ"
+ // MANGLING-X64-DAG: @"?goo@H@@QEAAPEAUB@@XZ"
+ // MANGLING-X64-DAG: @"?goo@H@@QEAAPEAUC@@XZ"
};
H h;
@@ -124,8 +124,8 @@ struct I : D {
I::I() {} // Emits vftable and forces thunk generation.
-// CODEGEN-LABEL: define weak_odr x86_thiscallcc %struct.{{[BF]}}* @"\01?goo@I@@QAEPAUB@@XZ"{{.*}} comdat
-// CODEGEN: %[[ORIG_RET:.*]] = call x86_thiscallcc %struct.F* @"\01?goo@I@@UAEPAUF@@XZ"
+// CODEGEN-LABEL: define weak_odr dso_local x86_thiscallcc %struct.{{[BF]}}* @"?goo@I@@QAEPAUB@@XZ"{{.*}} comdat
+// CODEGEN: %[[ORIG_RET:.*]] = call x86_thiscallcc %struct.F* @"?goo@I@@UAEPAUF@@XZ"
// CODEGEN: %[[ORIG_RET_i8:.*]] = bitcast %struct.F* %[[ORIG_RET]] to i8*
// CODEGEN: %[[VBPTR_i8:.*]] = getelementptr inbounds i8, i8* %[[ORIG_RET_i8]], i32 4
// CODEGEN: %[[VBPTR:.*]] = bitcast i8* %[[VBPTR_i8]] to i32**
@@ -160,5 +160,5 @@ struct E : D {
E::E() {}
E e;
// Class with internal linkage has internal linkage thunks.
-// CODEGEN: define internal x86_thiscallcc %struct.C* @"\01?goo@E@?A@@QAEPAUB@@XZ"
+// CODEGEN: define internal x86_thiscallcc %struct.C* @"?goo@E@?A@@QAEPAUB@@XZ"
}
diff --git a/test/CodeGenCXX/microsoft-abi-try-throw.cpp b/test/CodeGenCXX/microsoft-abi-try-throw.cpp
index bf1834e8594e..1a1e941ebf88 100644
--- a/test/CodeGenCXX/microsoft-abi-try-throw.cpp
+++ b/test/CodeGenCXX/microsoft-abi-try-throw.cpp
@@ -1,8 +1,8 @@
// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fcxx-exceptions -fexceptions -fno-rtti -DTRY | FileCheck %s -check-prefix=TRY
// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fcxx-exceptions -fexceptions -fno-rtti -DTHROW | FileCheck %s -check-prefix=THROW
-// THROW-DAG: @"\01??_R0H@8" = linkonce_odr global %rtti.TypeDescriptor2 { i8** @"\01??_7type_info@@6B@", i8* null, [3 x i8] c".H\00" }, comdat
-// THROW-DAG: @"_CT??_R0H@84" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*), i32 0, i32 -1, i32 0, i32 4, i8* null }, section ".xdata", comdat
+// THROW-DAG: @"??_R0H@8" = linkonce_odr global %rtti.TypeDescriptor2 { i8** @"??_7type_info@@6B@", i8* null, [3 x i8] c".H\00" }, comdat
+// THROW-DAG: @"_CT??_R0H@84" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"??_R0H@8" to i8*), i32 0, i32 -1, i32 0, i32 4, i8* null }, section ".xdata", comdat
// THROW-DAG: @_CTA1H = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.1 { i32 1, [1 x %eh.CatchableType*] [%eh.CatchableType* @"_CT??_R0H@84"] }, section ".xdata", comdat
// THROW-DAG: @_TI1H = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, i8* null, i8* null, i8* bitcast (%eh.CatchableTypeArray.1* @_CTA1H to i8*) }, section ".xdata", comdat
@@ -16,10 +16,10 @@ int main() {
int rv = 0;
#ifdef TRY
try {
- external(); // TRY: invoke void @"\01?external@@YAXXZ"
+ external(); // TRY: invoke void @"?external@@YAXXZ"
} catch (int) {
rv = 1;
- // TRY: catchpad within {{.*}} [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
+ // TRY: catchpad within {{.*}} [%rtti.TypeDescriptor2* @"??_R0H@8", i32 0, i8* null]
// TRY: catchret
}
#endif
@@ -33,13 +33,13 @@ int main() {
}
#ifdef TRY
-// TRY-LABEL: define void @"\01?qual_catch@@YAXXZ"
+// TRY-LABEL: define dso_local void @"?qual_catch@@YAXXZ"
void qual_catch() {
try {
external();
} catch (const int *) {
}
- // TRY: catchpad within {{.*}} [%rtti.TypeDescriptor4* @"\01??_R0PAH@8", i32 1, i8* null]
+ // TRY: catchpad within {{.*}} [%rtti.TypeDescriptor4* @"??_R0PAH@8", i32 1, i8* null]
// TRY: catchret
}
#endif
diff --git a/test/CodeGenCXX/microsoft-abi-typeid.cpp b/test/CodeGenCXX/microsoft-abi-typeid.cpp
index d73f8483a713..a571654ef062 100644
--- a/test/CodeGenCXX/microsoft-abi-typeid.cpp
+++ b/test/CodeGenCXX/microsoft-abi-typeid.cpp
@@ -12,20 +12,20 @@ extern int b;
A* fn();
const std::type_info* test0_typeid() { return &typeid(int); }
-// CHECK-LABEL: define %struct.type_info* @"\01?test0_typeid@@YAPBUtype_info@@XZ"()
-// CHECK: ret %struct.type_info* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to %struct.type_info*)
+// CHECK-LABEL: define dso_local %struct.type_info* @"?test0_typeid@@YAPBUtype_info@@XZ"()
+// CHECK: ret %struct.type_info* bitcast (%rtti.TypeDescriptor2* @"??_R0H@8" to %struct.type_info*)
const std::type_info* test1_typeid() { return &typeid(A); }
-// CHECK-LABEL: define %struct.type_info* @"\01?test1_typeid@@YAPBUtype_info@@XZ"()
-// CHECK: ret %struct.type_info* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8" to %struct.type_info*)
+// CHECK-LABEL: define dso_local %struct.type_info* @"?test1_typeid@@YAPBUtype_info@@XZ"()
+// CHECK: ret %struct.type_info* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUA@@@8" to %struct.type_info*)
const std::type_info* test2_typeid() { return &typeid(&a); }
-// CHECK-LABEL: define %struct.type_info* @"\01?test2_typeid@@YAPBUtype_info@@XZ"()
-// CHECK: ret %struct.type_info* bitcast (%rtti.TypeDescriptor7* @"\01??_R0PAUA@@@8" to %struct.type_info*)
+// CHECK-LABEL: define dso_local %struct.type_info* @"?test2_typeid@@YAPBUtype_info@@XZ"()
+// CHECK: ret %struct.type_info* bitcast (%rtti.TypeDescriptor7* @"??_R0PAUA@@@8" to %struct.type_info*)
const std::type_info* test3_typeid() { return &typeid(*fn()); }
-// CHECK-LABEL: define %struct.type_info* @"\01?test3_typeid@@YAPBUtype_info@@XZ"()
-// CHECK: [[CALL:%.*]] = tail call %struct.A* @"\01?fn@@YAPAUA@@XZ"()
+// CHECK-LABEL: define dso_local %struct.type_info* @"?test3_typeid@@YAPBUtype_info@@XZ"()
+// CHECK: [[CALL:%.*]] = tail call %struct.A* @"?fn@@YAPAUA@@XZ"()
// CHECK-NEXT: [[CMP:%.*]] = icmp eq %struct.A* [[CALL]], null
// CHECK-NEXT: br i1 [[CMP]]
// CHECK: tail call i8* @__RTtypeid(i8* null)
@@ -41,12 +41,12 @@ const std::type_info* test3_typeid() { return &typeid(*fn()); }
// CHECK-NEXT: ret %struct.type_info* [[RET]]
const std::type_info* test4_typeid() { return &typeid(b); }
-// CHECK: define %struct.type_info* @"\01?test4_typeid@@YAPBUtype_info@@XZ"()
-// CHECK: ret %struct.type_info* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to %struct.type_info*)
+// CHECK: define dso_local %struct.type_info* @"?test4_typeid@@YAPBUtype_info@@XZ"()
+// CHECK: ret %struct.type_info* bitcast (%rtti.TypeDescriptor2* @"??_R0H@8" to %struct.type_info*)
const std::type_info* test5_typeid() { return &typeid(v); }
-// CHECK: define %struct.type_info* @"\01?test5_typeid@@YAPBUtype_info@@XZ"()
-// CHECK: [[RT:%.*]] = tail call i8* @__RTtypeid(i8* bitcast (%struct.V* @"\01?v@@3UV@@A" to i8*))
+// CHECK: define dso_local %struct.type_info* @"?test5_typeid@@YAPBUtype_info@@XZ"()
+// CHECK: [[RT:%.*]] = tail call i8* @__RTtypeid(i8* bitcast (%struct.V* @"?v@@3UV@@A" to i8*))
// CHECK-NEXT: [[RET:%.*]] = bitcast i8* [[RT]] to %struct.type_info*
// CHECK-NEXT: ret %struct.type_info* [[RET]]
@@ -63,7 +63,7 @@ void f(const Polymorphic &poly) {
typeid(poly);
}
}
-// CHECK-LABEL: define void @"\01?f@PR26329@@YAXABUPolymorphic@1@@Z"(
+// CHECK-LABEL: define dso_local void @"?f@PR26329@@YAXABUPolymorphic@1@@Z"(
// CHECK: %[[cs:.*]] = catchswitch within none [label %{{.*}}] unwind to caller
// CHECK: %[[cp:.*]] = catchpad within %[[cs]] [i8* null, i32 64, i8* null]
// CHECK: invoke i8* @__RTtypeid(i8* {{.*}}) [ "funclet"(token %[[cp]]) ]
diff --git a/test/CodeGenCXX/microsoft-abi-vbtables.cpp b/test/CodeGenCXX/microsoft-abi-vbtables.cpp
index df0689423872..46e159c628f0 100644
--- a/test/CodeGenCXX/microsoft-abi-vbtables.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vbtables.cpp
@@ -19,11 +19,11 @@ D d; // Force vbtable emission.
// C: vbptr C
// int c
-// CHECK-DAG: @"\01??_8D@Test1@@7B01@@" = linkonce_odr unnamed_addr constant [4 x i32] [i32 0, i32 8, i32 12, i32 20]
-// CHECK-DAG: @"\01??_8D@Test1@@7BB@1@@" = {{.*}} [2 x i32] [i32 0, i32 -4]
-// CHECK-DAG: @"\01??_8D@Test1@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 -12]
-// CHECK-DAG: @"\01??_8C@Test1@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
-// CHECK-DAG: @"\01??_8B@Test1@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"??_8D@Test1@@7B01@@" = linkonce_odr unnamed_addr constant [4 x i32] [i32 0, i32 8, i32 12, i32 20]
+// CHECK-DAG: @"??_8D@Test1@@7BB@1@@" = {{.*}} [2 x i32] [i32 0, i32 -4]
+// CHECK-DAG: @"??_8D@Test1@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 -12]
+// CHECK-DAG: @"??_8C@Test1@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"??_8B@Test1@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
}
namespace Test2 {
@@ -42,10 +42,10 @@ D d; // Force vbtable emission.
// D: int d
// A: int a
-// CHECK-DAG: @"\01??_8D@Test2@@7BB@1@@" = {{.*}} [2 x i32] [i32 0, i32 20]
-// CHECK-DAG: @"\01??_8D@Test2@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 12]
-// CHECK-DAG: @"\01??_8C@Test2@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
-// CHECK-DAG: @"\01??_8B@Test2@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"??_8D@Test2@@7BB@1@@" = {{.*}} [2 x i32] [i32 0, i32 20]
+// CHECK-DAG: @"??_8D@Test2@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 12]
+// CHECK-DAG: @"??_8C@Test2@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"??_8B@Test2@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
}
namespace Test3 {
@@ -54,7 +54,7 @@ struct B { int b; };
struct C : virtual A, virtual B { int c; };
C c;
-// CHECK-DAG: @"\01??_8C@Test3@@7B@" = {{.*}} [3 x i32] [i32 0, i32 8, i32 12]
+// CHECK-DAG: @"??_8C@Test3@@7B@" = {{.*}} [3 x i32] [i32 0, i32 8, i32 12]
}
namespace Test4 {
@@ -64,8 +64,8 @@ struct B : virtual A { int b; };
struct C : B, virtual A { int c; };
C c; // Force vbtable emission.
-// CHECK-DAG: @"\01??_8C@Test4@@7B@" = {{.*}} [2 x i32] [i32 0, i32 12]
-// CHECK-DAG: @"\01??_8B@Test4@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"??_8C@Test4@@7B@" = {{.*}} [2 x i32] [i32 0, i32 12]
+// CHECK-DAG: @"??_8B@Test4@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
}
namespace Test5 {
@@ -77,10 +77,10 @@ struct C : B { int c; };
struct D : B, C { int d; };
D d; // Force vbtable emission.
-// CHECK-DAG: @"\01??_8D@Test5@@7BB@1@@"
-// CHECK-DAG: @"\01??_8D@Test5@@7BC@1@@"
-// CHECK-DAG: @"\01??_8C@Test5@@7B@"
-// CHECK-DAG: @"\01??_8B@Test5@@7B@"
+// CHECK-DAG: @"??_8D@Test5@@7BB@1@@"
+// CHECK-DAG: @"??_8D@Test5@@7BC@1@@"
+// CHECK-DAG: @"??_8C@Test5@@7B@"
+// CHECK-DAG: @"??_8B@Test5@@7B@"
}
namespace Test6 {
@@ -94,22 +94,22 @@ struct F : E, B, C { int f; };
struct G : F, virtual E { int g; };
G g;
-// CHECK-DAG: @"\01??_8G@Test6@@7BB@1@E@1@F@1@@" =
-// CHECK-DAG: @"\01??_8G@Test6@@7BC@1@E@1@F@1@@" =
-// CHECK-DAG: @"\01??_8G@Test6@@7BB@1@F@1@@" =
-// CHECK-DAG: @"\01??_8G@Test6@@7BC@1@F@1@@" =
-// CHECK-DAG: @"\01??_8G@Test6@@7BB@1@E@1@@" =
-// CHECK-DAG: @"\01??_8G@Test6@@7BC@1@E@1@@" =
-// CHECK-DAG: @"\01??_8F@Test6@@7BB@1@E@1@@" = {{.*}} [2 x i32] [i32 0, i32 52]
-// CHECK-DAG: @"\01??_8F@Test6@@7BC@1@E@1@@" = {{.*}} [2 x i32] [i32 0, i32 44]
-// CHECK-DAG: @"\01??_8F@Test6@@7BB@1@@" = {{.*}} [2 x i32] [i32 0, i32 24]
-// CHECK-DAG: @"\01??_8F@Test6@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 16]
-// CHECK-DAG: @"\01??_8C@Test6@@7B@" = {{.*}} [2 x i32] [i32 0, i32 12]
-// CHECK-DAG: @"\01??_8B@Test6@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
-// CHECK-DAG: @"\01??_8E@Test6@@7BB@1@@" = {{.*}} [2 x i32] [i32 0, i32 28]
-// CHECK-DAG: @"\01??_8E@Test6@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 20]
-// CHECK-DAG: @"\01??_8D@Test6@@7BB@1@@" = {{.*}} [2 x i32] [i32 0, i32 24]
-// CHECK-DAG: @"\01??_8D@Test6@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 16]
+// CHECK-DAG: @"??_8G@Test6@@7BB@1@E@1@F@1@@" =
+// CHECK-DAG: @"??_8G@Test6@@7BC@1@E@1@F@1@@" =
+// CHECK-DAG: @"??_8G@Test6@@7BB@1@F@1@@" =
+// CHECK-DAG: @"??_8G@Test6@@7BC@1@F@1@@" =
+// CHECK-DAG: @"??_8G@Test6@@7BB@1@E@1@@" =
+// CHECK-DAG: @"??_8G@Test6@@7BC@1@E@1@@" =
+// CHECK-DAG: @"??_8F@Test6@@7BB@1@E@1@@" = {{.*}} [2 x i32] [i32 0, i32 52]
+// CHECK-DAG: @"??_8F@Test6@@7BC@1@E@1@@" = {{.*}} [2 x i32] [i32 0, i32 44]
+// CHECK-DAG: @"??_8F@Test6@@7BB@1@@" = {{.*}} [2 x i32] [i32 0, i32 24]
+// CHECK-DAG: @"??_8F@Test6@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 16]
+// CHECK-DAG: @"??_8C@Test6@@7B@" = {{.*}} [2 x i32] [i32 0, i32 12]
+// CHECK-DAG: @"??_8B@Test6@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"??_8E@Test6@@7BB@1@@" = {{.*}} [2 x i32] [i32 0, i32 28]
+// CHECK-DAG: @"??_8E@Test6@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 20]
+// CHECK-DAG: @"??_8D@Test6@@7BB@1@@" = {{.*}} [2 x i32] [i32 0, i32 24]
+// CHECK-DAG: @"??_8D@Test6@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 16]
}
namespace Test7 {
@@ -121,8 +121,8 @@ struct D : virtual A { int d; };
struct E : B, D, virtual A, virtual C { int e; };
E o;
-// CHECK-DAG: @"\01??_8E@Test7@@7B@" = {{.*}} [3 x i32] [i32 0, i32 12, i32 16]
-// CHECK-DAG: @"\01??_8D@Test7@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"??_8E@Test7@@7B@" = {{.*}} [3 x i32] [i32 0, i32 12, i32 16]
+// CHECK-DAG: @"??_8D@Test7@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
}
namespace Test8 {
@@ -133,10 +133,10 @@ struct C : B { int c; };
struct D : virtual C { int d; };
D o;
-// CHECK-DAG: @"\01??_8D@Test8@@7B01@@" = {{.*}} [3 x i32] [i32 0, i32 8, i32 12]
-// CHECK-DAG: @"\01??_8D@Test8@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 -4]
-// CHECK-DAG: @"\01??_8C@Test8@@7B@" = {{.*}} [2 x i32] [i32 0, i32 12]
-// CHECK-DAG: @"\01??_8B@Test8@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"??_8D@Test8@@7B01@@" = {{.*}} [3 x i32] [i32 0, i32 8, i32 12]
+// CHECK-DAG: @"??_8D@Test8@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 -4]
+// CHECK-DAG: @"??_8C@Test8@@7B@" = {{.*}} [2 x i32] [i32 0, i32 12]
+// CHECK-DAG: @"??_8B@Test8@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
}
namespace Test9 {
@@ -150,17 +150,17 @@ struct D : BB, C { int d; };
struct E : virtual D { };
E e;
-// CHECK-DAG: @"\01??_8E@Test9@@7B01@@" =
-// CHECK-DAG: @"\01??_8E@Test9@@7BD@1@@" =
-// CHECK-DAG: @"\01??_8E@Test9@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8E@Test9@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8D@Test9@@7B@" =
-// CHECK-DAG: @"\01??_8D@Test9@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8D@Test9@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8C@Test9@@7B01@@" =
-// CHECK-DAG: @"\01??_8C@Test9@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8BB@Test9@@7B@" =
-// CHECK-DAG: @"\01??_8B@Test9@@7B@" =
+// CHECK-DAG: @"??_8E@Test9@@7B01@@" =
+// CHECK-DAG: @"??_8E@Test9@@7BD@1@@" =
+// CHECK-DAG: @"??_8E@Test9@@7BC@1@@" =
+// CHECK-DAG: @"??_8E@Test9@@7BB@1@@" =
+// CHECK-DAG: @"??_8D@Test9@@7B@" =
+// CHECK-DAG: @"??_8D@Test9@@7BC@1@@" =
+// CHECK-DAG: @"??_8D@Test9@@7BB@1@@" =
+// CHECK-DAG: @"??_8C@Test9@@7B01@@" =
+// CHECK-DAG: @"??_8C@Test9@@7BB@1@@" =
+// CHECK-DAG: @"??_8BB@Test9@@7B@" =
+// CHECK-DAG: @"??_8B@Test9@@7B@" =
}
namespace Test10 {
@@ -170,8 +170,8 @@ struct C : virtual A { int c; };
struct D : B, C { int d; };
D d;
-// CHECK-DAG: @"\01??_8D@Test10@@7B@" =
-// CHECK-DAG: @"\01??_8C@Test10@@7B@" =
+// CHECK-DAG: @"??_8D@Test10@@7B@" =
+// CHECK-DAG: @"??_8C@Test10@@7B@" =
}
@@ -185,12 +185,12 @@ struct E : C { int e; };
struct F : D, E { int f; };
F f;
-// CHECK-DAG: @"\01??_8F@Test11@@7BD@1@@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 28]
-// CHECK-DAG: @"\01??_8F@Test11@@7BE@1@@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 16]
-// CHECK-DAG: @"\01??_8E@Test11@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 12]
-// CHECK-DAG: @"\01??_8C@Test11@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
-// CHECK-DAG: @"\01??_8D@Test11@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 12]
-// CHECK-DAG: @"\01??_8B@Test11@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"??_8F@Test11@@7BD@1@@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 28]
+// CHECK-DAG: @"??_8F@Test11@@7BE@1@@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 16]
+// CHECK-DAG: @"??_8E@Test11@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 12]
+// CHECK-DAG: @"??_8C@Test11@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"??_8D@Test11@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 12]
+// CHECK-DAG: @"??_8B@Test11@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
}
@@ -203,17 +203,17 @@ struct D : C, B { int d; };
struct E : D, C, B { int e; };
E e;
-// CHECK-DAG: @"\01??_8E@Test12@@7BC@1@D@1@@" =
-// CHECK-DAG: @"\01??_8E@Test12@@7BB@1@D@1@@" =
-// CHECK-DAG: @"\01??_8E@Test12@@7BD@1@@" =
-// CHECK-DAG: @"\01??_8E@Test12@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8E@Test12@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8C@Test12@@7B01@@" =
-// CHECK-DAG: @"\01??_8C@Test12@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8D@Test12@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8D@Test12@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8D@Test12@@7B@" =
-// CHECK-DAG: @"\01??_8B@Test12@@7B@" =
+// CHECK-DAG: @"??_8E@Test12@@7BC@1@D@1@@" =
+// CHECK-DAG: @"??_8E@Test12@@7BB@1@D@1@@" =
+// CHECK-DAG: @"??_8E@Test12@@7BD@1@@" =
+// CHECK-DAG: @"??_8E@Test12@@7BC@1@@" =
+// CHECK-DAG: @"??_8E@Test12@@7BB@1@@" =
+// CHECK-DAG: @"??_8C@Test12@@7B01@@" =
+// CHECK-DAG: @"??_8C@Test12@@7BB@1@@" =
+// CHECK-DAG: @"??_8D@Test12@@7BC@1@@" =
+// CHECK-DAG: @"??_8D@Test12@@7BB@1@@" =
+// CHECK-DAG: @"??_8D@Test12@@7B@" =
+// CHECK-DAG: @"??_8B@Test12@@7B@" =
}
namespace Test13 {
@@ -224,17 +224,17 @@ struct D : virtual C { int d; };
struct E : D, C, B { int e; };
E e;
-// CHECK-DAG: @"\01??_8E@Test13@@7BD@1@@" =
-// CHECK-DAG: @"\01??_8E@Test13@@7BC@1@D@1@@" =
-// CHECK-DAG: @"\01??_8E@Test13@@7BB@1@D@1@@" =
-// CHECK-DAG: @"\01??_8E@Test13@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8E@Test13@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8D@Test13@@7B@" =
-// CHECK-DAG: @"\01??_8D@Test13@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8D@Test13@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8C@Test13@@7B01@@" =
-// CHECK-DAG: @"\01??_8C@Test13@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8B@Test13@@7B@" =
+// CHECK-DAG: @"??_8E@Test13@@7BD@1@@" =
+// CHECK-DAG: @"??_8E@Test13@@7BC@1@D@1@@" =
+// CHECK-DAG: @"??_8E@Test13@@7BB@1@D@1@@" =
+// CHECK-DAG: @"??_8E@Test13@@7BC@1@@" =
+// CHECK-DAG: @"??_8E@Test13@@7BB@1@@" =
+// CHECK-DAG: @"??_8D@Test13@@7B@" =
+// CHECK-DAG: @"??_8D@Test13@@7BC@1@@" =
+// CHECK-DAG: @"??_8D@Test13@@7BB@1@@" =
+// CHECK-DAG: @"??_8C@Test13@@7B01@@" =
+// CHECK-DAG: @"??_8C@Test13@@7BB@1@@" =
+// CHECK-DAG: @"??_8B@Test13@@7B@" =
}
namespace Test14 {
@@ -245,15 +245,15 @@ struct D : virtual C { int d; };
struct E : D, virtual C, virtual B { int e; };
E e;
-// CHECK-DAG: @"\01??_8E@Test14@@7B@" =
-// CHECK-DAG: @"\01??_8E@Test14@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8E@Test14@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8D@Test14@@7B@" =
-// CHECK-DAG: @"\01??_8D@Test14@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8D@Test14@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8C@Test14@@7B01@@" =
-// CHECK-DAG: @"\01??_8C@Test14@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8B@Test14@@7B@" =
+// CHECK-DAG: @"??_8E@Test14@@7B@" =
+// CHECK-DAG: @"??_8E@Test14@@7BC@1@@" =
+// CHECK-DAG: @"??_8E@Test14@@7BB@1@@" =
+// CHECK-DAG: @"??_8D@Test14@@7B@" =
+// CHECK-DAG: @"??_8D@Test14@@7BC@1@@" =
+// CHECK-DAG: @"??_8D@Test14@@7BB@1@@" =
+// CHECK-DAG: @"??_8C@Test14@@7B01@@" =
+// CHECK-DAG: @"??_8C@Test14@@7BB@1@@" =
+// CHECK-DAG: @"??_8B@Test14@@7B@" =
}
namespace Test15 {
@@ -264,14 +264,14 @@ struct D : virtual B { int d; };
struct E : D, C, B { int e; };
E e;
-// CHECK-DAG: @"\01??_8E@Test15@@7BD@1@@" =
-// CHECK-DAG: @"\01??_8E@Test15@@7BB@1@D@1@@" =
-// CHECK-DAG: @"\01??_8E@Test15@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8E@Test15@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8C@Test15@@7B@" =
-// CHECK-DAG: @"\01??_8D@Test15@@7B01@@" =
-// CHECK-DAG: @"\01??_8D@Test15@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8B@Test15@@7B@" =
+// CHECK-DAG: @"??_8E@Test15@@7BD@1@@" =
+// CHECK-DAG: @"??_8E@Test15@@7BB@1@D@1@@" =
+// CHECK-DAG: @"??_8E@Test15@@7BC@1@@" =
+// CHECK-DAG: @"??_8E@Test15@@7BB@1@@" =
+// CHECK-DAG: @"??_8C@Test15@@7B@" =
+// CHECK-DAG: @"??_8D@Test15@@7B01@@" =
+// CHECK-DAG: @"??_8D@Test15@@7BB@1@@" =
+// CHECK-DAG: @"??_8B@Test15@@7B@" =
}
namespace Test16 {
@@ -283,23 +283,23 @@ struct E : virtual D { int e; }; // ambig
struct F : E, D, C, B { int f; }; // ambig
F f;
-// CHECK-DAG: @"\01??_8F@Test16@@7BE@1@@" =
-// CHECK-DAG: @"\01??_8F@Test16@@7BD@1@E@1@@" =
-// CHECK-DAG: @"\01??_8F@Test16@@7BC@1@E@1@@" =
-// CHECK-DAG: @"\01??_8F@Test16@@7BB@1@E@1@@" =
-// CHECK-DAG: @"\01??_8F@Test16@@7BD@1@@" =
-// CHECK-DAG: @"\01??_8F@Test16@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8F@Test16@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8E@Test16@@7B01@@" =
-// CHECK-DAG: @"\01??_8E@Test16@@7BD@1@@" =
-// CHECK-DAG: @"\01??_8E@Test16@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8E@Test16@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8D@Test16@@7B@" =
-// CHECK-DAG: @"\01??_8D@Test16@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8D@Test16@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8C@Test16@@7B01@@" =
-// CHECK-DAG: @"\01??_8C@Test16@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8B@Test16@@7B@" =
+// CHECK-DAG: @"??_8F@Test16@@7BE@1@@" =
+// CHECK-DAG: @"??_8F@Test16@@7BD@1@E@1@@" =
+// CHECK-DAG: @"??_8F@Test16@@7BC@1@E@1@@" =
+// CHECK-DAG: @"??_8F@Test16@@7BB@1@E@1@@" =
+// CHECK-DAG: @"??_8F@Test16@@7BD@1@@" =
+// CHECK-DAG: @"??_8F@Test16@@7BC@1@@" =
+// CHECK-DAG: @"??_8F@Test16@@7BB@1@@" =
+// CHECK-DAG: @"??_8E@Test16@@7B01@@" =
+// CHECK-DAG: @"??_8E@Test16@@7BD@1@@" =
+// CHECK-DAG: @"??_8E@Test16@@7BC@1@@" =
+// CHECK-DAG: @"??_8E@Test16@@7BB@1@@" =
+// CHECK-DAG: @"??_8D@Test16@@7B@" =
+// CHECK-DAG: @"??_8D@Test16@@7BC@1@@" =
+// CHECK-DAG: @"??_8D@Test16@@7BB@1@@" =
+// CHECK-DAG: @"??_8C@Test16@@7B01@@" =
+// CHECK-DAG: @"??_8C@Test16@@7BB@1@@" =
+// CHECK-DAG: @"??_8B@Test16@@7B@" =
}
namespace Test17 {
@@ -318,16 +318,16 @@ struct J : virtual I { int j; };
struct K : virtual J { int k; }; // ambig
K k;
-// CHECK-DAG: @"\01??_8K@Test17@@7B01@@" =
-// CHECK-DAG: @"\01??_8J@Test17@@7B@" =
-// CHECK-DAG: @"\01??_8I@Test17@@7B01@@" =
-// CHECK-DAG: @"\01??_8H@Test17@@7B@" =
-// CHECK-DAG: @"\01??_8G@Test17@@7B01@@" =
-// CHECK-DAG: @"\01??_8F@Test17@@7B@" =
-// CHECK-DAG: @"\01??_8E@Test17@@7B01@@" =
-// CHECK-DAG: @"\01??_8D@Test17@@7B@" =
-// CHECK-DAG: @"\01??_8C@Test17@@7B01@@" =
-// CHECK-DAG: @"\01??_8B@Test17@@7B@" =
+// CHECK-DAG: @"??_8K@Test17@@7B01@@" =
+// CHECK-DAG: @"??_8J@Test17@@7B@" =
+// CHECK-DAG: @"??_8I@Test17@@7B01@@" =
+// CHECK-DAG: @"??_8H@Test17@@7B@" =
+// CHECK-DAG: @"??_8G@Test17@@7B01@@" =
+// CHECK-DAG: @"??_8F@Test17@@7B@" =
+// CHECK-DAG: @"??_8E@Test17@@7B01@@" =
+// CHECK-DAG: @"??_8D@Test17@@7B@" =
+// CHECK-DAG: @"??_8C@Test17@@7B01@@" =
+// CHECK-DAG: @"??_8B@Test17@@7B@" =
}
namespace Test18 {
@@ -338,14 +338,14 @@ struct D : C, B { int d; };
struct E : D, C, B { int e; };
E e;
-// CHECK-DAG: @"\01??_8E@Test18@@7BC@1@D@1@@" =
-// CHECK-DAG: @"\01??_8E@Test18@@7BB@1@D@1@@" =
-// CHECK-DAG: @"\01??_8E@Test18@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8E@Test18@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8B@Test18@@7B@" =
-// CHECK-DAG: @"\01??_8C@Test18@@7B@" =
-// CHECK-DAG: @"\01??_8D@Test18@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8D@Test18@@7BB@1@@" =
+// CHECK-DAG: @"??_8E@Test18@@7BC@1@D@1@@" =
+// CHECK-DAG: @"??_8E@Test18@@7BB@1@D@1@@" =
+// CHECK-DAG: @"??_8E@Test18@@7BC@1@@" =
+// CHECK-DAG: @"??_8E@Test18@@7BB@1@@" =
+// CHECK-DAG: @"??_8B@Test18@@7B@" =
+// CHECK-DAG: @"??_8C@Test18@@7B@" =
+// CHECK-DAG: @"??_8D@Test18@@7BC@1@@" =
+// CHECK-DAG: @"??_8D@Test18@@7BB@1@@" =
}
namespace Test19 {
@@ -356,16 +356,16 @@ struct D : virtual C, virtual B { int d; };
struct E : virtual D, virtual C, virtual B { int e; };
E e;
-// CHECK-DAG: @"\01??_8E@Test19@@7B01@@" =
-// CHECK-DAG: @"\01??_8E@Test19@@7BD@1@@" =
-// CHECK-DAG: @"\01??_8E@Test19@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8E@Test19@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8D@Test19@@7B@" =
-// CHECK-DAG: @"\01??_8D@Test19@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8D@Test19@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8C@Test19@@7B01@@" =
-// CHECK-DAG: @"\01??_8C@Test19@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8B@Test19@@7B@" =
+// CHECK-DAG: @"??_8E@Test19@@7B01@@" =
+// CHECK-DAG: @"??_8E@Test19@@7BD@1@@" =
+// CHECK-DAG: @"??_8E@Test19@@7BC@1@@" =
+// CHECK-DAG: @"??_8E@Test19@@7BB@1@@" =
+// CHECK-DAG: @"??_8D@Test19@@7B@" =
+// CHECK-DAG: @"??_8D@Test19@@7BC@1@@" =
+// CHECK-DAG: @"??_8D@Test19@@7BB@1@@" =
+// CHECK-DAG: @"??_8C@Test19@@7B01@@" =
+// CHECK-DAG: @"??_8C@Test19@@7BB@1@@" =
+// CHECK-DAG: @"??_8B@Test19@@7B@" =
}
namespace Test20 {
@@ -377,10 +377,10 @@ struct D : virtual B { int d; };
struct E : C, D { int e; };
E f;
-// CHECK-DAG: @"\01??_8E@Test20@@7BC@1@@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 0, i32 20, i32 24]
-// CHECK-DAG: @"\01??_8E@Test20@@7BD@1@@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 16]
-// CHECK-DAG: @"\01??_8D@Test20@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
-// CHECK-DAG: @"\01??_8C@Test20@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"??_8E@Test20@@7BC@1@@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 0, i32 20, i32 24]
+// CHECK-DAG: @"??_8E@Test20@@7BD@1@@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 16]
+// CHECK-DAG: @"??_8D@Test20@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"??_8C@Test20@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
}
namespace Test21 {
@@ -394,21 +394,21 @@ struct G : E { int g; };
struct H : F, G { int h; };
H h;
-// CHECK-DAG: @"\01??_8H@Test21@@7B@" =
-// CHECK-DAG: @"\01??_8H@Test21@@7BC@1@F@1@@" =
-// CHECK-DAG: @"\01??_8H@Test21@@7BD@1@F@1@@" =
-// CHECK-DAG: @"\01??_8H@Test21@@7BC@1@G@1@@" =
-// CHECK-DAG: @"\01??_8H@Test21@@7BD@1@G@1@@" =
-// CHECK-DAG: @"\01??_8G@Test21@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8G@Test21@@7BD@1@@" =
-// CHECK-DAG: @"\01??_8F@Test21@@7B@" =
-// CHECK-DAG: @"\01??_8F@Test21@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8F@Test21@@7BD@1@@" =
-// CHECK-DAG: @"\01??_8E@Test21@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8E@Test21@@7BD@1@@" =
-// CHECK-DAG: @"\01??_8D@Test21@@7B@" =
-// CHECK-DAG: @"\01??_8B@Test21@@7B@" =
-// CHECK-DAG: @"\01??_8C@Test21@@7B@" =
+// CHECK-DAG: @"??_8H@Test21@@7B@" =
+// CHECK-DAG: @"??_8H@Test21@@7BC@1@F@1@@" =
+// CHECK-DAG: @"??_8H@Test21@@7BD@1@F@1@@" =
+// CHECK-DAG: @"??_8H@Test21@@7BC@1@G@1@@" =
+// CHECK-DAG: @"??_8H@Test21@@7BD@1@G@1@@" =
+// CHECK-DAG: @"??_8G@Test21@@7BC@1@@" =
+// CHECK-DAG: @"??_8G@Test21@@7BD@1@@" =
+// CHECK-DAG: @"??_8F@Test21@@7B@" =
+// CHECK-DAG: @"??_8F@Test21@@7BC@1@@" =
+// CHECK-DAG: @"??_8F@Test21@@7BD@1@@" =
+// CHECK-DAG: @"??_8E@Test21@@7BC@1@@" =
+// CHECK-DAG: @"??_8E@Test21@@7BD@1@@" =
+// CHECK-DAG: @"??_8D@Test21@@7B@" =
+// CHECK-DAG: @"??_8B@Test21@@7B@" =
+// CHECK-DAG: @"??_8C@Test21@@7B@" =
}
namespace Test22 {
@@ -418,8 +418,8 @@ struct C { int c; };
struct D : B, virtual C { int d; };
D d;
-// CHECK-DAG: @"\01??_8D@Test22@@7B@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 0, i32 12, i32 16]
-// CHECK-DAG: @"\01??_8B@Test22@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"??_8D@Test22@@7B@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 0, i32 12, i32 16]
+// CHECK-DAG: @"??_8B@Test22@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
}
namespace Test23 {
@@ -430,8 +430,8 @@ struct C { int c; };
struct D : virtual C, B { int d; };
D d;
-// CHECK-DAG: @"\01??_8D@Test23@@7B@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 0, i32 16, i32 12]
-// CHECK-DAG: @"\01??_8B@Test23@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"??_8D@Test23@@7B@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 0, i32 16, i32 12]
+// CHECK-DAG: @"??_8B@Test23@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
}
namespace Test24 {
@@ -444,8 +444,8 @@ struct D : virtual C, B {
};
D d;
-// CHECK-DAG: @"\01??_8D@Test24@@7B@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 0, i32 16, i32 12]
-// CHECK-DAG: @"\01??_8B@Test24@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"??_8D@Test24@@7B@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 0, i32 16, i32 12]
+// CHECK-DAG: @"??_8B@Test24@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
}
namespace Test25 {
@@ -458,8 +458,8 @@ struct C { int c; };
struct D : virtual C, B { int d; };
D d;
-// CHECK-DAG: @"\01??_8D@Test25@@7B@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 -4, i32 16, i32 12]
-// CHECK-DAG: @"\01??_8B@Test25@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 -4, i32 8]
+// CHECK-DAG: @"??_8D@Test25@@7B@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 -4, i32 16, i32 12]
+// CHECK-DAG: @"??_8B@Test25@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 -4, i32 8]
}
namespace Test26 {
@@ -474,8 +474,8 @@ struct E : virtual B {
struct F: virtual C, D, E { int f; };
F f;
// F reuses the D's vbptr, even though D is laid out after E.
-// CHECK-DAG: @"\01??_8F@Test26@@7BD@1@@" = linkonce_odr unnamed_addr constant [4 x i32] [i32 0, i32 16, i32 12, i32 20]
-// CHECK-DAG: @"\01??_8F@Test26@@7BE@1@@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 -4, i32 28]
+// CHECK-DAG: @"??_8F@Test26@@7BD@1@@" = linkonce_odr unnamed_addr constant [4 x i32] [i32 0, i32 16, i32 12, i32 20]
+// CHECK-DAG: @"??_8F@Test26@@7BE@1@@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 -4, i32 28]
}
namespace Test27 {
@@ -489,14 +489,14 @@ struct F : C, E {};
struct G : F, D, C, B {};
G x;
-// CHECK-DAG: @"\01??_8G@Test27@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8G@Test27@@7BB@1@F@1@@" =
-// CHECK-DAG: @"\01??_8G@Test27@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8G@Test27@@7BC@1@D@1@@" =
-// CHECK-DAG: @"\01??_8G@Test27@@7BC@1@E@1@@" =
-// CHECK-DAG: @"\01??_8G@Test27@@7BC@1@F@1@@" =
-// CHECK-DAG: @"\01??_8G@Test27@@7BD@1@@" =
-// CHECK-DAG: @"\01??_8G@Test27@@7BF@1@@" =
+// CHECK-DAG: @"??_8G@Test27@@7BB@1@@" =
+// CHECK-DAG: @"??_8G@Test27@@7BB@1@F@1@@" =
+// CHECK-DAG: @"??_8G@Test27@@7BC@1@@" =
+// CHECK-DAG: @"??_8G@Test27@@7BC@1@D@1@@" =
+// CHECK-DAG: @"??_8G@Test27@@7BC@1@E@1@@" =
+// CHECK-DAG: @"??_8G@Test27@@7BC@1@F@1@@" =
+// CHECK-DAG: @"??_8G@Test27@@7BD@1@@" =
+// CHECK-DAG: @"??_8G@Test27@@7BF@1@@" =
}
namespace Test28 {
@@ -509,14 +509,14 @@ struct E : C, D {};
struct F : virtual E, virtual D, virtual C {};
F x;
-// CHECK-DAG: @"\01??_8F@Test28@@7B01@@" =
-// CHECK-DAG: @"\01??_8F@Test28@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8F@Test28@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8F@Test28@@7BC@1@D@1@@" =
-// CHECK-DAG: @"\01??_8F@Test28@@7BC@1@D@1@E@1@@" =
-// CHECK-DAG: @"\01??_8F@Test28@@7BC@1@E@1@@" =
-// CHECK-DAG: @"\01??_8F@Test28@@7BD@1@@" =
-// CHECK-DAG: @"\01??_8F@Test28@@7BE@1@@" =
+// CHECK-DAG: @"??_8F@Test28@@7B01@@" =
+// CHECK-DAG: @"??_8F@Test28@@7BB@1@@" =
+// CHECK-DAG: @"??_8F@Test28@@7BC@1@@" =
+// CHECK-DAG: @"??_8F@Test28@@7BC@1@D@1@@" =
+// CHECK-DAG: @"??_8F@Test28@@7BC@1@D@1@E@1@@" =
+// CHECK-DAG: @"??_8F@Test28@@7BC@1@E@1@@" =
+// CHECK-DAG: @"??_8F@Test28@@7BD@1@@" =
+// CHECK-DAG: @"??_8F@Test28@@7BE@1@@" =
}
namespace Test29 {
@@ -526,7 +526,7 @@ struct C : virtual B {};
struct D : C {};
D d;
-// CHECK-DAG: @"\01??_8D@Test29@@7BB@1@@" = linkonce_odr unnamed_addr constant [2 x i32] zeroinitializer
+// CHECK-DAG: @"??_8D@Test29@@7BB@1@@" = linkonce_odr unnamed_addr constant [2 x i32] zeroinitializer
}
namespace Test30 {
@@ -537,5 +537,5 @@ template <class> struct B : virtual A {
extern template class B<int>;
template B<int>::B();
-// CHECK-DAG: @"\01??_8?$B@H@Test30@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 4], comdat
+// CHECK-DAG: @"??_8?$B@H@Test30@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 4], comdat
}
diff --git a/test/CodeGenCXX/microsoft-abi-vftables.cpp b/test/CodeGenCXX/microsoft-abi-vftables.cpp
index 968955f4ee1b..65370ab1ece5 100644
--- a/test/CodeGenCXX/microsoft-abi-vftables.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vftables.cpp
@@ -1,45 +1,45 @@
// RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -fms-extensions -emit-llvm -o - -O1 -disable-llvm-passes | FileCheck %s -check-prefix=NO-RTTI
// RUN: %clang_cc1 %s -triple=i386-pc-win32 -fms-extensions -emit-llvm -o - -O1 -disable-llvm-passes | FileCheck %s -check-prefix=RTTI
-// RTTI-DAG: $"\01??_7S@@6B@" = comdat largest
-// RTTI-DAG: $"\01??_7V@@6B@" = comdat largest
+// RTTI-DAG: $"??_7S@@6B@" = comdat largest
+// RTTI-DAG: $"??_7V@@6B@" = comdat largest
struct S {
virtual ~S();
} s;
-// RTTI-DAG: [[VTABLE_S:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast ({{.*}} @"\01??_R4S@@6B@" to i8*), i8* bitcast ({{.*}} @"\01??_GS@@UAEPAXI@Z" to i8*)] }, comdat($"\01??_7S@@6B@")
-// RTTI-DAG: @"\01??_7S@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VTABLE_S]], i32 0, i32 0, i32 1)
+// RTTI-DAG: [[VTABLE_S:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast ({{.*}} @"??_R4S@@6B@" to i8*), i8* bitcast ({{.*}} @"??_GS@@UAEPAXI@Z" to i8*)] }, comdat($"??_7S@@6B@")
+// RTTI-DAG: @"??_7S@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VTABLE_S]], i32 0, i32 0, i32 1)
-// NO-RTTI-DAG: @"\01??_7S@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GS@@UAEPAXI@Z" to i8*)] }
+// NO-RTTI-DAG: @"??_7S@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast ({{.*}} @"??_GS@@UAEPAXI@Z" to i8*)] }
struct __declspec(dllimport) U {
virtual ~U();
} u;
-// RTTI-DAG: [[VTABLE_U:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast ({{.*}} @"\01??_R4U@@6B@" to i8*), i8* bitcast ({{.*}} @"\01??_GU@@UAEPAXI@Z" to i8*)] }
-// RTTI-DAG: @"\01??_SU@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VTABLE_U]], i32 0, i32 0, i32 1)
+// RTTI-DAG: [[VTABLE_U:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast ({{.*}} @"??_R4U@@6B@" to i8*), i8* bitcast ({{.*}} @"??_GU@@UAEPAXI@Z" to i8*)] }
+// RTTI-DAG: @"??_SU@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VTABLE_U]], i32 0, i32 0, i32 1)
-// NO-RTTI-DAG: @"\01??_SU@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GU@@UAEPAXI@Z" to i8*)] }
+// NO-RTTI-DAG: @"??_SU@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast ({{.*}} @"??_GU@@UAEPAXI@Z" to i8*)] }
struct __declspec(dllexport) V {
virtual ~V();
} v;
-// RTTI-DAG: [[VTABLE_V:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast ({{.*}} @"\01??_R4V@@6B@" to i8*), i8* bitcast ({{.*}} @"\01??_GV@@UAEPAXI@Z" to i8*)] }, comdat($"\01??_7V@@6B@")
-// RTTI-DAG: @"\01??_7V@@6B@" = dllexport unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VTABLE_V]], i32 0, i32 0, i32 1)
+// RTTI-DAG: [[VTABLE_V:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast ({{.*}} @"??_R4V@@6B@" to i8*), i8* bitcast ({{.*}} @"??_GV@@UAEPAXI@Z" to i8*)] }, comdat($"??_7V@@6B@")
+// RTTI-DAG: @"??_7V@@6B@" = dllexport unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VTABLE_V]], i32 0, i32 0, i32 1)
-// NO-RTTI-DAG: @"\01??_7V@@6B@" = weak_odr dllexport unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GV@@UAEPAXI@Z" to i8*)] }
+// NO-RTTI-DAG: @"??_7V@@6B@" = weak_odr dllexport unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast ({{.*}} @"??_GV@@UAEPAXI@Z" to i8*)] }
namespace {
struct W {
virtual ~W() {}
} w;
}
-// RTTI-DAG: [[VTABLE_W:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast ({{.*}} @"\01??_R4W@?A@@6B@" to i8*), i8* bitcast ({{.*}} @"\01??_GW@?A@@UAEPAXI@Z" to i8*)] }
-// RTTI-DAG: @"\01??_7W@?A@@6B@" = internal unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VTABLE_W]], i32 0, i32 0, i32 1)
+// RTTI-DAG: [[VTABLE_W:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast ({{.*}} @"??_R4W@?A@@6B@" to i8*), i8* bitcast ({{.*}} @"??_GW@?A@@UAEPAXI@Z" to i8*)] }
+// RTTI-DAG: @"??_7W@?A@@6B@" = internal unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VTABLE_W]], i32 0, i32 0, i32 1)
-// NO-RTTI-DAG: @"\01??_7W@?A@@6B@" = internal unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GW@?A@@UAEPAXI@Z" to i8*)] }
+// NO-RTTI-DAG: @"??_7W@?A@@6B@" = internal unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast ({{.*}} @"??_GW@?A@@UAEPAXI@Z" to i8*)] }
struct X {};
template <class> struct Y : virtual X {
@@ -49,7 +49,7 @@ template <class> struct Y : virtual X {
extern template class Y<int>;
template Y<int>::Y();
-// RTTI-DAG: [[VTABLE_Y:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4?$Y@H@@6B@" to i8*), i8* bitcast (i8* (%struct.Y*, i32)* @"\01??_G?$Y@H@@UAEPAXI@Z" to i8*)] }, comdat($"\01??_7?$Y@H@@6B@")
-// RTTI-DAG: @"\01??_7?$Y@H@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VTABLE_Y]], i32 0, i32 0, i32 1)
+// RTTI-DAG: [[VTABLE_Y:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"??_R4?$Y@H@@6B@" to i8*), i8* bitcast (i8* (%struct.Y*, i32)* @"??_G?$Y@H@@UAEPAXI@Z" to i8*)] }, comdat($"??_7?$Y@H@@6B@")
+// RTTI-DAG: @"??_7?$Y@H@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VTABLE_Y]], i32 0, i32 0, i32 1)
-// NO-RTTI-DAG: @"\01??_7?$Y@H@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast (i8* (%struct.Y*, i32)* @"\01??_G?$Y@H@@UAEPAXI@Z" to i8*)] }, comdat
+// NO-RTTI-DAG: @"??_7?$Y@H@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast (i8* (%struct.Y*, i32)* @"??_G?$Y@H@@UAEPAXI@Z" to i8*)] }, comdat
diff --git a/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp b/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp
index 2f141b2a66ec..0120299a7da4 100644
--- a/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp
+++ b/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp
@@ -23,8 +23,9 @@ struct D : virtual C {
D::D() {} // Forces vftable emission.
-// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01?f@D@@$4PPPPPPPM@A@AEXXZ"
+// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"?f@D@@$4PPPPPPPM@A@AEXXZ"
// Note that the vtordisp is applied before really adjusting to D*.
+// CHECK: %[[COERCE_LOAD:.*]] = load %struct.D*, %struct.D** %{{.*}}
// CHECK: %[[ECX:.*]] = load %struct.D*, %struct.D** %{{.*}}
// CHECK: %[[ECX_i8:.*]] = bitcast %struct.D* %[[ECX]] to i8*
// CHECK: %[[VTORDISP_PTR_i8:.*]] = getelementptr inbounds i8, i8* %[[ECX_i8]], i32 -4
@@ -32,10 +33,11 @@ D::D() {} // Forces vftable emission.
// CHECK: %[[VTORDISP:.*]] = load i32, i32* %[[VTORDISP_PTR]]
// CHECK: %[[VTORDISP_NEG:.*]] = sub i32 0, %[[VTORDISP]]
// CHECK: %[[ADJUSTED_i8:.*]] = getelementptr i8, i8* %[[ECX_i8]], i32 %[[VTORDISP_NEG]]
-// CHECK: call x86_thiscallcc void @"\01?f@D@@UAEXXZ"(i8* %[[ADJUSTED_i8]])
+// CHECK: call x86_thiscallcc void @"?f@D@@UAEXXZ"(i8* %[[ADJUSTED_i8]])
// CHECK: ret void
-// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01?f@D@@$4PPPPPPPI@3AEXXZ"
+// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"?f@D@@$4PPPPPPPI@3AEXXZ"
+// CHECK: %[[COERCE_LOAD:.*]] = load %struct.D*, %struct.D** %{{.*}}
// CHECK: %[[ECX:.*]] = load %struct.D*, %struct.D** %{{.*}}
// CHECK: %[[ECX_i8:.*]] = bitcast %struct.D* %[[ECX]] to i8*
// CHECK: %[[VTORDISP_PTR_i8:.*]] = getelementptr inbounds i8, i8* %[[ECX_i8]], i32 -8
@@ -44,7 +46,7 @@ D::D() {} // Forces vftable emission.
// CHECK: %[[VTORDISP_NEG:.*]] = sub i32 0, %[[VTORDISP]]
// CHECK: %[[VTORDISP_ADJUSTED_i8:.*]] = getelementptr i8, i8* %[[ECX_i8]], i32 %[[VTORDISP_NEG]]
// CHECK: %[[ADJUSTED_i8:.*]] = getelementptr i8, i8* %[[VTORDISP_ADJUSTED_i8]], i32 -4
-// CHECK: call x86_thiscallcc void @"\01?f@D@@UAEXXZ"(i8* %[[ADJUSTED_i8]])
+// CHECK: call x86_thiscallcc void @"?f@D@@UAEXXZ"(i8* %[[ADJUSTED_i8]])
// CHECK: ret void
struct E : virtual A {
@@ -64,7 +66,8 @@ struct G : virtual F, virtual E {
G::G() {} // Forces vftable emission.
-// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01?f@E@@$R4BA@M@PPPPPPPM@7AEXXZ"(i8*)
+// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"?f@E@@$R4BA@M@PPPPPPPM@7AEXXZ"(i8*
+// CHECK: %[[COERCE_LOAD:.*]] = load %struct.E*, %struct.E** %{{.*}}
// CHECK: %[[ECX:.*]] = load %struct.E*, %struct.E** %{{.*}}
// CHECK: %[[ECX_i8:.*]] = bitcast %struct.E* %[[ECX]] to i8*
// CHECK: %[[VTORDISP_PTR_i8:.*]] = getelementptr inbounds i8, i8* %[[ECX_i8]], i32 -4
@@ -79,5 +82,5 @@ G::G() {} // Forces vftable emission.
// CHECK: %[[VBASE_OFFSET:.*]] = load i32, i32* %[[VBOFFSET_PTR]]
// CHECK: %[[VBASE:.*]] = getelementptr inbounds i8, i8* %[[VBPTR_i8]], i32 %[[VBASE_OFFSET]]
// CHECK: %[[ARG_i8:.*]] = getelementptr i8, i8* %[[VBASE]], i32 8
-// CHECK: call x86_thiscallcc void @"\01?f@E@@UAEXXZ"(i8* %[[ARG_i8]])
+// CHECK: call x86_thiscallcc void @"?f@E@@UAEXXZ"(i8* %[[ARG_i8]])
// CHECK: ret void
diff --git a/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
index c9dd1dd7d8e2..212c8dc84ae3 100644
--- a/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
+++ b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
@@ -20,7 +20,7 @@ struct B : virtual VBase {
};
B::B() {
- // CHECK-LABEL: define x86_thiscallcc %struct.B* @"\01??0B@@QAE@XZ"
+ // CHECK-LABEL: define dso_local x86_thiscallcc %struct.B* @"??0B@@QAE@XZ"
// CHECK: %[[THIS:.*]] = load %struct.B*, %struct.B**
// CHECK: br i1 %{{.*}}, label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]]
@@ -33,7 +33,7 @@ B::B() {
// CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
// CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 %{{.*}}
// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to i32 (...)***
- // CHECK: store i32 (...)** bitcast ({ [3 x i8*] }* @"\01??_7B@@6B@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
+ // CHECK: store i32 (...)** bitcast ({ [3 x i8*] }* @"??_7B@@6B@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
// Initialize vtorDisp:
// CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
@@ -51,7 +51,7 @@ B::B() {
}
B::~B() {
- // CHECK-LABEL: define x86_thiscallcc void @"\01??1B@@UAE@XZ"
+ // CHECK-LABEL: define dso_local x86_thiscallcc void @"??1B@@UAE@XZ"
// Store initial this:
// CHECK: %[[THIS_ADDR:.*]] = alloca %struct.B*
// CHECK: store %struct.B* %{{.*}}, %struct.B** %[[THIS_ADDR]], align 4
@@ -68,7 +68,7 @@ B::~B() {
// CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
// CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 %{{.*}}
// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to i32 (...)***
- // CHECK: store i32 (...)** bitcast ({ [3 x i8*] }* @"\01??_7B@@6B@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
+ // CHECK: store i32 (...)** bitcast ({ [3 x i8*] }* @"??_7B@@6B@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
// Initialize vtorDisp:
// CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
@@ -86,38 +86,44 @@ B::~B() {
// CHECK: ret
- // CHECK2-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_DB@@QAEXXZ"(%struct.B*
+ // CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"??_DB@@QAEXXZ"(%struct.B*
// CHECK2: %[[THIS:.*]] = load %struct.B*, %struct.B** {{.*}}
// CHECK2: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
// CHECK2: %[[B_i8:.*]] = getelementptr i8, i8* %[[THIS_i8]], i32 8
// CHECK2: %[[B:.*]] = bitcast i8* %[[B_i8]] to %struct.B*
- // CHECK2: call x86_thiscallcc void @"\01??1B@@UAE@XZ"(%struct.B* %[[B]])
+ // CHECK2: call x86_thiscallcc void @"??1B@@UAE@XZ"(%struct.B* %[[B]])
// CHECK2: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
// CHECK2: %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 8
// CHECK2: %[[VBASE:.*]] = bitcast i8* %[[VBASE_i8]] to %struct.VBase*
- // CHECK2: call x86_thiscallcc void @"\01??1VBase@@UAE@XZ"(%struct.VBase* %[[VBASE]])
+ // CHECK2: call x86_thiscallcc void @"??1VBase@@UAE@XZ"(%struct.VBase* %[[VBASE]])
// CHECK2: ret
- // CHECK2-LABEL: define linkonce_odr x86_thiscallcc i8* @"\01??_GB@@UAEPAXI@Z"
+ // CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc i8* @"??_GB@@UAEPAXI@Z"
// CHECK2: store %struct.B* %{{.*}}, %struct.B** %[[THIS_ADDR:.*]], align 4
// CHECK2: %[[THIS:.*]] = load %struct.B*, %struct.B** %[[THIS_ADDR]]
// CHECK2: %[[THIS_PARAM_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
// CHECK2: %[[THIS_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_PARAM_i8:.*]], i32 -8
// CHECK2: %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %struct.B*
- // CHECK2: call x86_thiscallcc void @"\01??_DB@@QAEXXZ"(%struct.B* %[[THIS]])
+ // CHECK2: call x86_thiscallcc void @"??_DB@@QAEXXZ"(%struct.B* %[[THIS]])
// ...
// CHECK2: ret
}
void B::foo() {
-// CHECK-LABEL: define x86_thiscallcc void @"\01?foo@B@@UAEXXZ"(i8*
+// CHECK-LABEL: define dso_local x86_thiscallcc void @"?foo@B@@UAEXXZ"(i8*
//
// B::foo gets 'this' cast to VBase* in ECX (i.e. this+8) so we
// need to adjust 'this' before use.
//
-// Store initial this:
+// Coerce this to correct type:
+// CHECK: %[[THIS_STORE:.*]] = alloca %struct.B*
// CHECK: %[[THIS_ADDR:.*]] = alloca %struct.B*
-// CHECK: store %struct.B* %{{.*}}, %struct.B** %[[THIS_ADDR]], align 4
+// CHECK: %[[COERCE_VAL:.*]] = bitcast i8* %{{.*}} to %struct.B*
+// CHECK: store %struct.B* %[[COERCE_VAL]], %struct.B** %[[THIS_STORE]], align 4
+//
+// Store initial this:
+// CHECK: %[[THIS_INIT:.*]] = load %struct.B*, %struct.B** %[[THIS_STORE]]
+// CHECK: store %struct.B* %[[THIS_INIT]], %struct.B** %[[THIS_ADDR]], align 4
//
// Reload and adjust the this parameter:
// CHECK: %[[THIS_RELOAD:.*]] = load %struct.B*, %struct.B** %[[THIS_ADDR]]
@@ -143,7 +149,7 @@ void B::foo() {
}
void call_vbase_bar(B *obj) {
-// CHECK-LABEL: define void @"\01?call_vbase_bar@@YAXPAUB@@@Z"(%struct.B* %obj)
+// CHECK-LABEL: define dso_local void @"?call_vbase_bar@@YAXPAUB@@@Z"(%struct.B* %obj)
// CHECK: %[[OBJ:.*]] = load %struct.B
obj->bar();
@@ -157,11 +163,7 @@ void call_vbase_bar(B *obj) {
// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32, i32* %[[VBTABLE]], i32 1
// CHECK: %[[VBOFFSET32:.*]] = load i32, i32* %[[VBENTRY]]
// CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
-// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
-// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VBASE_i8]] to void (i8*)***
-// CHECK: %[[VFTABLE:.*]] = load void (i8*)**, void (i8*)*** %[[VFPTR]]
-// CHECK: %[[VFUN:.*]] = getelementptr inbounds void (i8*)*, void (i8*)** %[[VFTABLE]], i64 2
-// CHECK: %[[VFUN_VALUE:.*]] = load void (i8*)*, void (i8*)** %[[VFUN]]
+// CHECK: %[[VBASE:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
//
// CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8*
// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 0
@@ -170,7 +172,11 @@ void call_vbase_bar(B *obj) {
// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32, i32* %[[VBTABLE]], i32 1
// CHECK: %[[VBOFFSET32:.*]] = load i32, i32* %[[VBENTRY]]
// CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
-// CHECK: %[[VBASE:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
+// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
+// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VBASE_i8]] to void (i8*)***
+// CHECK: %[[VFTABLE:.*]] = load void (i8*)**, void (i8*)*** %[[VFPTR]]
+// CHECK: %[[VFUN:.*]] = getelementptr inbounds void (i8*)*, void (i8*)** %[[VFTABLE]], i64 2
+// CHECK: %[[VFUN_VALUE:.*]] = load void (i8*)*, void (i8*)** %[[VFUN]]
//
// CHECK: call x86_thiscallcc void %[[VFUN_VALUE]](i8* %[[VBASE]])
//
@@ -178,7 +184,7 @@ void call_vbase_bar(B *obj) {
}
void delete_B(B *obj) {
-// CHECK-LABEL: define void @"\01?delete_B@@YAXPAUB@@@Z"(%struct.B* %obj)
+// CHECK-LABEL: define dso_local void @"?delete_B@@YAXPAUB@@@Z"(%struct.B* %obj)
// CHECK: %[[OBJ:.*]] = load %struct.B
delete obj;
@@ -190,10 +196,7 @@ void delete_B(B *obj) {
// CHECK: %[[VBOFFSET32:.*]] = load i32, i32* %[[VBENTRY]]
// CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
-// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VBASE_i8]] to i8* (%struct.B*, i32)***
-// CHECK: %[[VFTABLE:.*]] = load i8* (%struct.B*, i32)**, i8* (%struct.B*, i32)*** %[[VFPTR]]
-// CHECK: %[[VFUN:.*]] = getelementptr inbounds i8* (%struct.B*, i32)*, i8* (%struct.B*, i32)** %[[VFTABLE]], i64 0
-// CHECK: %[[VFUN_VALUE:.*]] = load i8* (%struct.B*, i32)*, i8* (%struct.B*, i32)** %[[VFUN]]
+// CHECK: %[[VBASE:.*]] = bitcast i8* %[[VBASE_i8]] to %struct.B*
//
// CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8*
// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 0
@@ -203,18 +206,21 @@ void delete_B(B *obj) {
// CHECK: %[[VBOFFSET32:.*]] = load i32, i32* %[[VBENTRY]]
// CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
-// CHECK: %[[VBASE:.*]] = bitcast i8* %[[VBASE_i8]] to %struct.B*
+// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VBASE_i8]] to i8* (%struct.B*, i32)***
+// CHECK: %[[VFTABLE:.*]] = load i8* (%struct.B*, i32)**, i8* (%struct.B*, i32)*** %[[VFPTR]]
+// CHECK: %[[VFUN:.*]] = getelementptr inbounds i8* (%struct.B*, i32)*, i8* (%struct.B*, i32)** %[[VFTABLE]], i64 0
+// CHECK: %[[VFUN_VALUE:.*]] = load i8* (%struct.B*, i32)*, i8* (%struct.B*, i32)** %[[VFUN]]
//
// CHECK: call x86_thiscallcc i8* %[[VFUN_VALUE]](%struct.B* %[[VBASE]], i32 1)
// CHECK: ret void
}
void call_complete_dtor() {
- // CHECK-LABEL: define void @"\01?call_complete_dtor@@YAXXZ"
+ // CHECK-LABEL: define dso_local void @"?call_complete_dtor@@YAXXZ"
B b;
- // CHECK: call x86_thiscallcc %struct.B* @"\01??0B@@QAE@XZ"(%struct.B* %[[B:.*]], i32 1)
+ // CHECK: call x86_thiscallcc %struct.B* @"??0B@@QAE@XZ"(%struct.B* %[[B:.*]], i32 1)
// CHECK-NOT: getelementptr
- // CHECK: call x86_thiscallcc void @"\01??_DB@@QAEXXZ"(%struct.B* %[[B]])
+ // CHECK: call x86_thiscallcc void @"??_DB@@QAEXXZ"(%struct.B* %[[B]])
// CHECK: ret
}
@@ -225,7 +231,7 @@ struct C : B {
// Used to crash on an assertion.
C::C() {
-// CHECK-LABEL: define x86_thiscallcc %struct.C* @"\01??0C@@QAE@XZ"
+// CHECK-LABEL: define dso_local x86_thiscallcc %struct.C* @"??0C@@QAE@XZ"
}
namespace multiple_vbases {
@@ -249,11 +255,11 @@ struct D : virtual A, virtual B, virtual C {
};
D::D() {
- // CHECK-LABEL: define x86_thiscallcc %"struct.multiple_vbases::D"* @"\01??0D@multiple_vbases@@QAE@XZ"
+ // CHECK-LABEL: define dso_local x86_thiscallcc %"struct.multiple_vbases::D"* @"??0D@multiple_vbases@@QAE@XZ"
// Just make sure we emit 3 vtordisps after initializing vfptrs.
- // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7D@multiple_vbases@@6BA@1@@" to i32 (...)**), i32 (...)*** %{{.*}}
- // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7D@multiple_vbases@@6BB@1@@" to i32 (...)**), i32 (...)*** %{{.*}}
- // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7D@multiple_vbases@@6BC@1@@" to i32 (...)**), i32 (...)*** %{{.*}}
+ // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7D@multiple_vbases@@6BA@1@@" to i32 (...)**), i32 (...)*** %{{.*}}
+ // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7D@multiple_vbases@@6BB@1@@" to i32 (...)**), i32 (...)*** %{{.*}}
+ // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7D@multiple_vbases@@6BC@1@@" to i32 (...)**), i32 (...)*** %{{.*}}
// ...
// CHECK: store i32 %{{.*}}, i32* %{{.*}}
// CHECK: store i32 %{{.*}}, i32* %{{.*}}
@@ -289,7 +295,7 @@ struct D : virtual Z, B, C {
} d;
D::~D() {
- // CHECK-LABEL: define x86_thiscallcc void @"\01??1D@diamond@@UAE@XZ"(%"struct.diamond::D"*{{.*}})
+ // CHECK-LABEL: define dso_local x86_thiscallcc void @"??1D@diamond@@UAE@XZ"(%"struct.diamond::D"*{{.*}})
// Store initial this:
// CHECK: %[[THIS_ADDR:.*]] = alloca %"struct.diamond::D"*
// CHECK: store %"struct.diamond::D"* %{{.*}}, %"struct.diamond::D"** %[[THIS_ADDR]], align 4
@@ -307,13 +313,13 @@ D::~D() {
// CHECK: %[[ARG_i8:.*]] = getelementptr i8, i8* %{{.*}}, i32 16
// FIXME: We might consider changing the dtor this parameter type to i8*.
// CHECK: %[[ARG:.*]] = bitcast i8* %[[ARG_i8]] to %"struct.diamond::C"*
- // CHECK: call x86_thiscallcc void @"\01??1C@diamond@@UAE@XZ"(%"struct.diamond::C"* %[[ARG]])
+ // CHECK: call x86_thiscallcc void @"??1C@diamond@@UAE@XZ"(%"struct.diamond::C"* %[[ARG]])
// CHECK: %[[B:.*]] = bitcast %"struct.diamond::D"* %[[THIS]] to %"struct.diamond::B"*
// CHECK: %[[B_i8:.*]] = bitcast %"struct.diamond::B"* %[[B]] to i8*
// CHECK: %[[ARG_i8:.*]] = getelementptr i8, i8* %[[B_i8]], i32 4
// CHECK: %[[ARG:.*]] = bitcast i8* %[[ARG_i8]] to %"struct.diamond::B"*
- // CHECK: call x86_thiscallcc void @"\01??1B@diamond@@UAE@XZ"(%"struct.diamond::B"* %[[ARG]])
+ // CHECK: call x86_thiscallcc void @"??1B@diamond@@UAE@XZ"(%"struct.diamond::B"* %[[ARG]])
// CHECK: ret void
}
@@ -328,20 +334,20 @@ struct C : B, A { C() {} };
// call to B() from C().
void callC() { C x; }
-// CHECK-LABEL: define linkonce_odr x86_thiscallcc %"struct.test2::C"* @"\01??0C@test2@@QAE@XZ"
+// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc %"struct.test2::C"* @"??0C@test2@@QAE@XZ"
// CHECK: (%"struct.test2::C"* returned %this, i32 %is_most_derived)
// CHECK: br i1
// Virtual bases
-// CHECK: call x86_thiscallcc %"struct.test2::A"* @"\01??0A@test2@@QAE@XZ"(%"struct.test2::A"* %{{.*}})
+// CHECK: call x86_thiscallcc %"struct.test2::A"* @"??0A@test2@@QAE@XZ"(%"struct.test2::A"* %{{.*}})
// CHECK: br label
// Non-virtual bases
-// CHECK: call x86_thiscallcc %"struct.test2::B"* @"\01??0B@test2@@QAE@XZ"(%"struct.test2::B"* %{{.*}}, i32 0)
-// CHECK: call x86_thiscallcc %"struct.test2::A"* @"\01??0A@test2@@QAE@XZ"(%"struct.test2::A"* %{{.*}})
+// CHECK: call x86_thiscallcc %"struct.test2::B"* @"??0B@test2@@QAE@XZ"(%"struct.test2::B"* %{{.*}}, i32 0)
+// CHECK: call x86_thiscallcc %"struct.test2::A"* @"??0A@test2@@QAE@XZ"(%"struct.test2::A"* %{{.*}})
// CHECK: ret
-// CHECK2-LABEL: define linkonce_odr x86_thiscallcc %"struct.test2::B"* @"\01??0B@test2@@QAE@XZ"
+// CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc %"struct.test2::B"* @"??0B@test2@@QAE@XZ"
// CHECK2: (%"struct.test2::B"* returned %this, i32 %is_most_derived)
-// CHECK2: call x86_thiscallcc %"struct.test2::A"* @"\01??0A@test2@@QAE@XZ"(%"struct.test2::A"* %{{.*}})
+// CHECK2: call x86_thiscallcc %"struct.test2::A"* @"??0A@test2@@QAE@XZ"(%"struct.test2::A"* %{{.*}})
// CHECK2: ret
}
@@ -368,7 +374,7 @@ struct D : B, C {
};
void D::bar() {
- // CHECK-LABEL: define x86_thiscallcc void @"\01?bar@D@test3@@UAEXXZ"(%"struct.test3::D"* %this)
+ // CHECK-LABEL: define dso_local x86_thiscallcc void @"?bar@D@test3@@UAEXXZ"(%"struct.test3::D"* %this)
C::foo();
// Shouldn't need any vbtable lookups. All we have to do is adjust to C*,
@@ -379,7 +385,7 @@ void D::bar() {
// CHECK: %[[C:.*]] = bitcast i8* %[[C_i8]] to %"struct.test3::C"*
// CHECK: %[[C_i8:.*]] = bitcast %"struct.test3::C"* %[[C]] to i8*
// CHECK: %[[ARG:.*]] = getelementptr i8, i8* %[[C_i8]], i32 4
- // CHECK: call x86_thiscallcc void @"\01?foo@C@test3@@UAEXXZ"(i8* %[[ARG]])
+ // CHECK: call x86_thiscallcc void @"?foo@C@test3@@UAEXXZ"(i8* %[[ARG]])
// CHECK: ret
}
}
@@ -402,20 +408,20 @@ struct C : virtual A, B {
void foo(void*);
C::~C() {
- // CHECK-LABEL: define x86_thiscallcc void @"\01??1C@test4@@UAE@XZ"(%"struct.test4::C"* %this)
+ // CHECK-LABEL: define dso_local x86_thiscallcc void @"??1C@test4@@UAE@XZ"(%"struct.test4::C"* %this)
// In this case "this" points to the most derived class, so no GEPs needed.
// CHECK-NOT: getelementptr
// CHECK-NOT: bitcast
// CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::C"* %{{.*}} to i32 (...)***
- // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7C@test4@@6BB@1@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]]
+ // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7C@test4@@6BB@1@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]]
foo(this);
// CHECK: ret
}
void destroy(C *obj) {
- // CHECK-LABEL: define void @"\01?destroy@test4@@YAXPAUC@1@@Z"(%"struct.test4::C"* %obj)
+ // CHECK-LABEL: define dso_local void @"?destroy@test4@@YAXPAUC@1@@Z"(%"struct.test4::C"* %obj)
delete obj;
// CHECK: %[[VPTR:.*]] = bitcast %"struct.test4::C"* %[[OBJ:.*]] to i8* (%"struct.test4::C"*, i32)***
@@ -437,30 +443,30 @@ struct E : D, B, virtual A {
};
E::~E() {
- // CHECK-LABEL: define x86_thiscallcc void @"\01??1E@test4@@UAE@XZ"(%"struct.test4::E"* %this)
+ // CHECK-LABEL: define dso_local x86_thiscallcc void @"??1E@test4@@UAE@XZ"(%"struct.test4::E"* %this)
// In this case "this" points to the most derived class, so no GEPs needed.
// CHECK-NOT: getelementptr
// CHECK-NOT: bitcast
// CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::E"* %{{.*}} to i32 (...)***
- // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7E@test4@@6BD@1@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]]
+ // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7E@test4@@6BD@1@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]]
foo(this);
}
void destroy(E *obj) {
- // CHECK-LABEL: define void @"\01?destroy@test4@@YAXPAUE@1@@Z"(%"struct.test4::E"* %obj)
+ // CHECK-LABEL: define dso_local void @"?destroy@test4@@YAXPAUE@1@@Z"(%"struct.test4::E"* %obj)
// CHECK-NOT: getelementptr
+ // CHECK: %[[OBJ_i8:.*]] = bitcast %"struct.test4::E"* %[[OBJ]] to i8*
+ // CHECK: %[[B_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 4
+ // FIXME: in fact, the call should take i8* and the bitcast is redundant.
+ // CHECK: %[[B_as_E:.*]] = bitcast i8* %[[B_i8]] to %"struct.test4::E"*
// CHECK: %[[OBJ_i8:.*]] = bitcast %"struct.test4::E"* %[[OBJ:.*]] to i8*
// CHECK: %[[B_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 4
// CHECK: %[[VPTR:.*]] = bitcast i8* %[[B_i8]] to i8* (%"struct.test4::E"*, i32)***
// CHECK: %[[VFTABLE:.*]] = load i8* (%"struct.test4::E"*, i32)**, i8* (%"struct.test4::E"*, i32)*** %[[VPTR]]
// CHECK: %[[VFTENTRY:.*]] = getelementptr inbounds i8* (%"struct.test4::E"*, i32)*, i8* (%"struct.test4::E"*, i32)** %[[VFTABLE]], i64 0
// CHECK: %[[VFUN:.*]] = load i8* (%"struct.test4::E"*, i32)*, i8* (%"struct.test4::E"*, i32)** %[[VFTENTRY]]
- // CHECK: %[[OBJ_i8:.*]] = bitcast %"struct.test4::E"* %[[OBJ]] to i8*
- // CHECK: %[[B_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 4
- // FIXME: in fact, the call should take i8* and the bitcast is redundant.
- // CHECK: %[[B_as_E:.*]] = bitcast i8* %[[B_i8]] to %"struct.test4::E"*
// CHECK: call x86_thiscallcc i8* %[[VFUN]](%"struct.test4::E"* %[[B_as_E]], i32 1)
delete obj;
}
@@ -482,7 +488,7 @@ struct C : B {
};
C::C() : B() {}
-// CHECK-LABEL: define x86_thiscallcc %"struct.test5::C"* @"\01??0C@test5@@QAE@XZ"(
+// CHECK-LABEL: define dso_local x86_thiscallcc %"struct.test5::C"* @"??0C@test5@@QAE@XZ"(
// CHECK: %[[THIS:.*]] = load %"struct.test5::C"*, %"struct.test5::C"**
// CHECK: br i1 %{{.*}}, label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]]
@@ -490,7 +496,7 @@ C::C() : B() {}
// CHECK: %[[B:.*]] = bitcast %"struct.test5::C"* %[[THIS]] to %"struct.test5::B"*
// CHECK: %[[B_i8:.*]] = bitcast %"struct.test5::B"* %[[B]] to i8*
// CHECK: %[[FIELD:.*]] = getelementptr inbounds i8, i8* %[[B_i8]], i32 4
-// CHECK: call void @llvm.memset.p0i8.i32(i8* %[[FIELD]], i8 0, i32 4, i32 4, i1 false)
+// CHECK: call void @llvm.memset.p0i8.i32(i8* align 4 %[[FIELD]], i8 0, i32 4, i1 false)
}
namespace pr27621 {
@@ -506,9 +512,9 @@ struct C final : A, B {
void callit(C *p) {
static_cast<B*>(p)->g();
}
-// CHECK-LABEL: define void @"\01?callit@pr27621@@YAXPAUC@1@@Z"(%"struct.pr27621::C"* %{{.*}})
+// CHECK-LABEL: define dso_local void @"?callit@pr27621@@YAXPAUC@1@@Z"(%"struct.pr27621::C"* %{{.*}})
// CHECK: %[[B_i8:.*]] = getelementptr i8, i8* %{{.*}}, i32 4
-// CHECK: call x86_thiscallcc void @"\01?g@C@pr27621@@UAEXXZ"(i8* %[[B_i8]])
+// CHECK: call x86_thiscallcc void @"?g@C@pr27621@@UAEXXZ"(i8* %[[B_i8]])
}
namespace test6 {
@@ -522,7 +528,7 @@ class D : C {
D();
};
D::D() : C() {}
-// CHECK-LABEL: define x86_thiscallcc %"class.test6::D"* @"\01??0D@test6@@AAE@XZ"(
+// CHECK-LABEL: define dso_local x86_thiscallcc %"class.test6::D"* @"??0D@test6@@AAE@XZ"(
// CHECK: %[[THIS:.*]] = load %"class.test6::D"*, %"class.test6::D"**
// CHECK: br i1 %{{.*}}, label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]]
@@ -530,5 +536,22 @@ D::D() : C() {}
// CHECK: %[[C:.*]] = bitcast %"class.test6::D"* %[[THIS]] to %"class.test6::C"*
// CHECK: %[[C_i8:.*]] = bitcast %"class.test6::C"* %[[C]] to i8*
// CHECK: %[[FIELD:.*]] = getelementptr inbounds i8, i8* %[[C_i8]], i32 8
-// CHECK: call void @llvm.memset.p0i8.i32(i8* %[[FIELD]], i8 0, i32 4, i32 4, i1 false)
+// CHECK: call void @llvm.memset.p0i8.i32(i8* align 4 %[[FIELD]], i8 0, i32 4, i1 false)
+}
+
+namespace pr36921 {
+struct A {
+ virtual ~A() {}
+};
+struct B {
+ virtual ~B() {}
+};
+struct C : virtual B {};
+struct D : virtual A, C {};
+D d;
+// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc i8* @"??_GD@pr36921@@UAEPAXI@Z"(
+// CHECK: %[[THIS:.*]] = load %"struct.pr36921::D"*, %"struct.pr36921::D"**
+// CHECK: %[[THIS_UNADJ_i8:.*]] = bitcast %"struct.pr36921::D"* %[[THIS_RELOAD]] to i8*
+// CHECK: %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_UNADJ_i8]], i32 -4
+// CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_ADJ_i8]] to %"struct.pr36921::D"*
}
diff --git a/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp b/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp
index af930c84720b..ef8a5e486825 100644
--- a/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp
+++ b/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp
@@ -53,24 +53,24 @@ void f() {
auto ptr7 = &C::plugh;
-// CHECK32-LABEL: define void @"\01?f@@YAXXZ"()
-// CHECK32: store i8* bitcast (void (%struct.C*, ...)* @"\01??_9C@@$BA@AE" to i8*), i8** %ptr
-// CHECK32: store i8* bitcast (void (%struct.C*, ...)* @"\01??_9C@@$B3AE" to i8*), i8** %ptr2
-// CHECK32: store i8* bitcast (void (%struct.C*, ...)* @"\01??_9C@@$B7AE" to i8*), i8** %ptr3
-// CHECK32: store i8* bitcast (void (%"struct.(anonymous namespace)::D"*, ...)* @"\01??_9D@?A@@$BA@AE" to i8*), i8** %ptr4
+// CHECK32-LABEL: define dso_local void @"?f@@YAXXZ"()
+// CHECK32: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$BA@AE" to i8*), i8** %ptr
+// CHECK32: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$B3AE" to i8*), i8** %ptr2
+// CHECK32: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$B7AE" to i8*), i8** %ptr3
+// CHECK32: store i8* bitcast (void (%"struct.(anonymous namespace)::D"*, ...)* @"??_9D@?A@@$BA@AE" to i8*), i8** %ptr4
// CHECK32: }
//
-// CHECK64-LABEL: define void @"\01?f@@YAXXZ"()
-// CHECK64: store i8* bitcast (void (%struct.C*, ...)* @"\01??_9C@@$BA@AA" to i8*), i8** %ptr
-// CHECK64: store i8* bitcast (void (%struct.C*, ...)* @"\01??_9C@@$B7AA" to i8*), i8** %ptr2
-// CHECK64: store i8* bitcast (void (%struct.C*, ...)* @"\01??_9C@@$BBA@AA" to i8*), i8** %ptr3
-// CHECK64: store i8* bitcast (void (%"struct.(anonymous namespace)::D"*, ...)* @"\01??_9D@?A@@$BA@AA" to i8*), i8** %ptr
+// CHECK64-LABEL: define dso_local void @"?f@@YAXXZ"()
+// CHECK64: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$BA@AA" to i8*), i8** %ptr
+// CHECK64: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$B7AA" to i8*), i8** %ptr2
+// CHECK64: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$BBA@AA" to i8*), i8** %ptr3
+// CHECK64: store i8* bitcast (void (%"struct.(anonymous namespace)::D"*, ...)* @"??_9D@?A@@$BA@AA" to i8*), i8** %ptr
// CHECK64: }
}
// Thunk for calling the 1st virtual function in C with no parameters.
-// CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@@$BA@AE"(%struct.C* %this, ...)
+// CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"??_9C@@$BA@AE"(%struct.C* %this, ...)
// CHECK32: #[[ATTR:[0-9]+]]
// CHECK32-NOT: unnamed_addr
// CHECK32: comdat
@@ -80,7 +80,7 @@ void f() {
// CHECK32-NEXT: ret void
// CHECK32: }
//
-// CHECK64-LABEL: define linkonce_odr void @"\01??_9C@@$BA@AA"(%struct.C* %this, ...)
+// CHECK64-LABEL: define linkonce_odr void @"??_9C@@$BA@AA"(%struct.C* %this, ...)
// CHECK64: #[[ATTR:[0-9]+]]
// CHECK64-NOT: unnamed_addr
// CHECK64: comdat
@@ -91,7 +91,7 @@ void f() {
// CHECK64: }
// Thunk for calling the 2nd virtual function in C, taking int and double as parameters, returning int.
-// CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@@$B3AE"(%struct.C* %this, ...)
+// CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"??_9C@@$B3AE"(%struct.C* %this, ...)
// CHECK32: #[[ATTR]] comdat
// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 1
// CHECK32: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]]
@@ -99,7 +99,7 @@ void f() {
// CHECK32-NEXT: ret void
// CHECK32: }
//
-// CHECK64-LABEL: define linkonce_odr void @"\01??_9C@@$B7AA"(%struct.C* %this, ...)
+// CHECK64-LABEL: define linkonce_odr void @"??_9C@@$B7AA"(%struct.C* %this, ...)
// CHECK64: #[[ATTR]] comdat
// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 1
// CHECK64: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]]
@@ -108,7 +108,7 @@ void f() {
// CHECK64: }
// Thunk for calling the 3rd virtual function in C, taking an int parameter, returning a struct.
-// CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@@$B7AE"(%struct.C* %this, ...)
+// CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"??_9C@@$B7AE"(%struct.C* %this, ...)
// CHECK32: #[[ATTR]] comdat
// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 2
// CHECK32: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]]
@@ -116,7 +116,7 @@ void f() {
// CHECK32-NEXT: ret void
// CHECK32: }
//
-// CHECK64-LABEL: define linkonce_odr void @"\01??_9C@@$BBA@AA"(%struct.C* %this, ...)
+// CHECK64-LABEL: define linkonce_odr void @"??_9C@@$BBA@AA"(%struct.C* %this, ...)
// CHECK64: #[[ATTR]] comdat
// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 2
// CHECK64: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]]
@@ -125,7 +125,7 @@ void f() {
// CHECK64: }
// Thunk for calling the virtual function in internal class D.
-// CHECK32-LABEL: define internal x86_thiscallcc void @"\01??_9D@?A@@$BA@AE"(%"struct.(anonymous namespace)::D"* %this, ...)
+// CHECK32-LABEL: define internal x86_thiscallcc void @"??_9D@?A@@$BA@AE"(%"struct.(anonymous namespace)::D"* %this, ...)
// CHECK32: #[[ATTR]]
// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%"struct.(anonymous namespace)::D"*, ...)*, void (%"struct.(anonymous namespace)::D"*, ...)** %{{.*}}, i64 0
// CHECK32: [[CALLEE:%.*]] = load void (%"struct.(anonymous namespace)::D"*, ...)*, void (%"struct.(anonymous namespace)::D"*, ...)** [[VPTR]]
@@ -133,7 +133,7 @@ void f() {
// CHECK32-NEXT: ret void
// CHECK32: }
//
-// CHECK64-LABEL: define internal void @"\01??_9D@?A@@$BA@AA"(%"struct.(anonymous namespace)::D"* %this, ...)
+// CHECK64-LABEL: define internal void @"??_9D@?A@@$BA@AA"(%"struct.(anonymous namespace)::D"* %this, ...)
// CHECK64: #[[ATTR]]
// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%"struct.(anonymous namespace)::D"*, ...)*, void (%"struct.(anonymous namespace)::D"*, ...)** %{{.*}}, i64 0
// CHECK64: [[CALLEE:%.*]] = load void (%"struct.(anonymous namespace)::D"*, ...)*, void (%"struct.(anonymous namespace)::D"*, ...)** [[VPTR]]
@@ -143,14 +143,14 @@ void f() {
// Thunk for calling the fourth virtual function in C, taking a struct parameter
// and returning a struct.
-// CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@@$BM@AE"(%struct.C* %this, ...) {{.*}} comdat
+// CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"??_9C@@$BM@AE"(%struct.C* %this, ...) {{.*}} comdat
// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 3
// CHECK32: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]]
// CHECK32: musttail call x86_thiscallcc void (%struct.C*, ...) [[CALLEE]](%struct.C* %{{.*}}, ...)
// CHECK32-NEXT: ret void
// CHECK32: }
//
-// CHECK64-LABEL: define linkonce_odr void @"\01??_9C@@$BBI@AA"(%struct.C* %this, ...) {{.*}} comdat
+// CHECK64-LABEL: define linkonce_odr void @"??_9C@@$BBI@AA"(%struct.C* %this, ...) {{.*}} comdat
// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 3
// CHECK64: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]]
// CHECK64: musttail call void (%struct.C*, ...) [[CALLEE]](%struct.C* %{{.*}}, ...)
@@ -158,28 +158,28 @@ void f() {
// CHECK64: }
// Thunk for calling the fifth virtual function in C which uses the __cdecl calling convention.
-// CHECK32-LABEL: define linkonce_odr void @"\01??_9C@@$BBA@AA"(%struct.C* %this, ...) {{.*}} comdat align 2 {
+// CHECK32-LABEL: define linkonce_odr void @"??_9C@@$BBA@AA"(%struct.C* %this, ...) {{.*}} comdat align 2 {
// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 4
// CHECK32: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]]
// CHECK32: musttail call void (%struct.C*, ...) [[CALLEE]](%struct.C* %{{.*}}, ...)
// CHECK32: ret void
// CHECK32: }
//
-// CHECK64-LABEL: define linkonce_odr void @"\01??_9C@@$BCA@AA"(%struct.C* %this, ...) {{.*}} comdat align 2 {
+// CHECK64-LABEL: define linkonce_odr void @"??_9C@@$BCA@AA"(%struct.C* %this, ...) {{.*}} comdat align 2 {
// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 4
// CHECK64: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]]
// CHECK64: musttail call void (%struct.C*, ...) [[CALLEE]](%struct.C* %{{.*}}, ...)
// CHECK64: ret void
// CHECK64: }
-// CHECK32: define linkonce_odr x86_thiscallcc void @"\01??_9C@@$BBE@AE"(%struct.C* %this, ...) {{.*}} comdat align 2 {
+// CHECK32: define linkonce_odr x86_thiscallcc void @"??_9C@@$BBE@AE"(%struct.C* %this, ...) {{.*}} comdat align 2 {
// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 5
// CHECK32: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]]
// CHECK32: musttail call x86_thiscallcc void (%struct.C*, ...) [[CALLEE]](%struct.C* %{{.*}}, ...)
// CHECK32: ret void
// CHECK32: }
-// CHECK64: define linkonce_odr void @"\01??_9C@@$BCI@AA"(%struct.C* %this, ...) {{.*}} comdat align 2 {
+// CHECK64: define linkonce_odr void @"??_9C@@$BCI@AA"(%struct.C* %this, ...) {{.*}} comdat align 2 {
// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 5
// CHECK64: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]]
// CHECK64: musttail call void (%struct.C*, ...) [[CALLEE]](%struct.C* %{{.*}}, ...)
diff --git a/test/CodeGenCXX/microsoft-abi-vmemptr-conflicts.cpp b/test/CodeGenCXX/microsoft-abi-vmemptr-conflicts.cpp
index f8a12e64c6ac..607ec816aefb 100644
--- a/test/CodeGenCXX/microsoft-abi-vmemptr-conflicts.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vmemptr-conflicts.cpp
@@ -19,11 +19,11 @@ void f(C *c) {
}
}
-// CHECK-LABEL: define void @"\01?f@num_params@@YAXPAUC@1@@Z"(%"struct.num_params::C"* %c)
-// CHECK: call x86_thiscallcc void bitcast (void (%"struct.num_params::C"*, ...)* @"\01??_9C@num_params@@$BA@AE" to void (%"struct.num_params::C"*, i32)*)(%"struct.num_params::C"* %{{.*}}, i32 0)
-// CHECK: call x86_thiscallcc void bitcast (void (%"struct.num_params::C"*, ...)* @"\01??_9C@num_params@@$BA@AE" to void (%"struct.num_params::C"*, i32, i32)*)(%"struct.num_params::C"* %{{.*}}, i32 0, i32 0)
+// CHECK-LABEL: define dso_local void @"?f@num_params@@YAXPAUC@1@@Z"(%"struct.num_params::C"* %c)
+// CHECK: call x86_thiscallcc void bitcast (void (%"struct.num_params::C"*, ...)* @"??_9C@num_params@@$BA@AE" to void (%"struct.num_params::C"*, i32)*)(%"struct.num_params::C"* %{{.*}}, i32 0)
+// CHECK: call x86_thiscallcc void bitcast (void (%"struct.num_params::C"*, ...)* @"??_9C@num_params@@$BA@AE" to void (%"struct.num_params::C"*, i32, i32)*)(%"struct.num_params::C"* %{{.*}}, i32 0, i32 0)
-// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@num_params@@$BA@AE"(%"struct.num_params::C"* %this, ...) {{.*}} comdat
+// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"??_9C@num_params@@$BA@AE"(%"struct.num_params::C"* %this, ...) {{.*}} comdat
// CHECK: musttail call x86_thiscallcc void (%"struct.num_params::C"*, ...) %{{.*}}(%"struct.num_params::C"* %{{.*}}, ...)
// CHECK-NEXT: ret void
@@ -41,11 +41,11 @@ long long f(C *c) {
}
}
-// CHECK-LABEL: define i64 @"\01?f@i64_return@@YA_JPAUC@1@@Z"(%"struct.i64_return::C"* %c)
-// CHECK: call x86_thiscallcc i32 bitcast (void (%"struct.i64_return::C"*, ...)* @"\01??_9C@i64_return@@$BA@AE" to i32 (%"struct.i64_return::C"*)*)(%"struct.i64_return::C"* %{{.*}})
-// CHECK: call x86_thiscallcc i64 bitcast (void (%"struct.i64_return::C"*, ...)* @"\01??_9C@i64_return@@$BA@AE" to i64 (%"struct.i64_return::C"*)*)(%"struct.i64_return::C"* %{{.*}})
+// CHECK-LABEL: define dso_local i64 @"?f@i64_return@@YA_JPAUC@1@@Z"(%"struct.i64_return::C"* %c)
+// CHECK: call x86_thiscallcc i32 bitcast (void (%"struct.i64_return::C"*, ...)* @"??_9C@i64_return@@$BA@AE" to i32 (%"struct.i64_return::C"*)*)(%"struct.i64_return::C"* %{{.*}})
+// CHECK: call x86_thiscallcc i64 bitcast (void (%"struct.i64_return::C"*, ...)* @"??_9C@i64_return@@$BA@AE" to i64 (%"struct.i64_return::C"*)*)(%"struct.i64_return::C"* %{{.*}})
-// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@i64_return@@$BA@AE"(%"struct.i64_return::C"* %this, ...) {{.*}} comdat
+// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"??_9C@i64_return@@$BA@AE"(%"struct.i64_return::C"* %this, ...) {{.*}} comdat
// CHECK: musttail call x86_thiscallcc void (%"struct.i64_return::C"*, ...) %{{.*}}(%"struct.i64_return::C"* %{{.*}}, ...)
// CHECK-NEXT: ret void
@@ -63,11 +63,11 @@ void f(C *c) {
}
}
-// CHECK-LABEL: define void @"\01?f@sret@@YAXPAUC@1@@Z"(%"struct.sret::C"* %c)
-// CHECK: call x86_thiscallcc i32 bitcast (void (%"struct.sret::C"*, ...)* @"\01??_9C@sret@@$BA@AE" to i32 (%"struct.sret::C"*)*)(%"struct.sret::C"* %{{.*}})
-// CHECK: call x86_thiscallcc void bitcast (void (%"struct.sret::C"*, ...)* @"\01??_9C@sret@@$BA@AE" to void (%"struct.sret::C"*, %"struct.sret::Big"*)*)(%"struct.sret::C"* %{{.*}}, %"struct.sret::Big"* sret %{{.*}})
+// CHECK-LABEL: define dso_local void @"?f@sret@@YAXPAUC@1@@Z"(%"struct.sret::C"* %c)
+// CHECK: call x86_thiscallcc i32 bitcast (void (%"struct.sret::C"*, ...)* @"??_9C@sret@@$BA@AE" to i32 (%"struct.sret::C"*)*)(%"struct.sret::C"* %{{.*}})
+// CHECK: call x86_thiscallcc void bitcast (void (%"struct.sret::C"*, ...)* @"??_9C@sret@@$BA@AE" to void (%"struct.sret::C"*, %"struct.sret::Big"*)*)(%"struct.sret::C"* %{{.*}}, %"struct.sret::Big"* sret %{{.*}})
-// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@sret@@$BA@AE"(%"struct.sret::C"* %this, ...) {{.*}} comdat
+// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"??_9C@sret@@$BA@AE"(%"struct.sret::C"* %this, ...) {{.*}} comdat
// CHECK: musttail call x86_thiscallcc void (%"struct.sret::C"*, ...) %{{.*}}(%"struct.sret::C"* %{{.*}}, ...)
// CHECK-NEXT: ret void
@@ -92,10 +92,10 @@ void f(C *c) {
}
}
-// CHECK-LABEL: define void @"\01?f@cdecl_inalloca@@YAXPAUC@1@@Z"(%"struct.cdecl_inalloca::C"* %c)
-// CHECK: call void bitcast (void (%"struct.cdecl_inalloca::C"*, ...)* @"\01??_9C@cdecl_inalloca@@$BA@AA" to void (%"struct.cdecl_inalloca::C"*)*)(%"struct.cdecl_inalloca::C"* %{{.*}})
-// CHECK: call void bitcast (void (%"struct.cdecl_inalloca::C"*, ...)* @"\01??_9C@cdecl_inalloca@@$BA@AA" to void (<{ %"struct.cdecl_inalloca::C"*, %"struct.cdecl_inalloca::Big" }>*)*)(<{ %"struct.cdecl_inalloca::C"*, %"struct.cdecl_inalloca::Big" }>* inalloca %{{.*}})
+// CHECK-LABEL: define dso_local void @"?f@cdecl_inalloca@@YAXPAUC@1@@Z"(%"struct.cdecl_inalloca::C"* %c)
+// CHECK: call void bitcast (void (%"struct.cdecl_inalloca::C"*, ...)* @"??_9C@cdecl_inalloca@@$BA@AA" to void (%"struct.cdecl_inalloca::C"*)*)(%"struct.cdecl_inalloca::C"* %{{.*}})
+// CHECK: call void bitcast (void (%"struct.cdecl_inalloca::C"*, ...)* @"??_9C@cdecl_inalloca@@$BA@AA" to void (<{ %"struct.cdecl_inalloca::C"*, %"struct.cdecl_inalloca::Big" }>*)*)(<{ %"struct.cdecl_inalloca::C"*, %"struct.cdecl_inalloca::Big" }>* inalloca %{{.*}})
-// CHECK-LABEL: define linkonce_odr void @"\01??_9C@cdecl_inalloca@@$BA@AA"(%"struct.cdecl_inalloca::C"* %this, ...) {{.*}} comdat
+// CHECK-LABEL: define linkonce_odr void @"??_9C@cdecl_inalloca@@$BA@AA"(%"struct.cdecl_inalloca::C"* %this, ...) {{.*}} comdat
// CHECK: musttail call void (%"struct.cdecl_inalloca::C"*, ...) %{{.*}}(%"struct.cdecl_inalloca::C"* %{{.*}}, ...)
// CHECK-NEXT: ret void
diff --git a/test/CodeGenCXX/microsoft-abi-vmemptr-fastcall.cpp b/test/CodeGenCXX/microsoft-abi-vmemptr-fastcall.cpp
index 97ab1996c8bc..59e8b0b8c2c8 100644
--- a/test/CodeGenCXX/microsoft-abi-vmemptr-fastcall.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vmemptr-fastcall.cpp
@@ -7,7 +7,7 @@ void (__fastcall A::*doit())(int, int) {
return &A::f;
}
-// CHECK: define linkonce_odr x86_fastcallcc void @"\01??_9A@@$BA@AI"(%struct.A* inreg %this, ...) {{.*}} comdat align 2 {
+// CHECK: define linkonce_odr x86_fastcallcc void @"??_9A@@$BA@AI"(%struct.A* inreg %this, ...) {{.*}} comdat align 2 {
// CHECK: [[VPTR:%.*]] = getelementptr inbounds void (%struct.A*, ...)*, void (%struct.A*, ...)** %{{.*}}, i64 0
// CHECK: [[CALLEE:%.*]] = load void (%struct.A*, ...)*, void (%struct.A*, ...)** [[VPTR]]
// CHECK: musttail call x86_fastcallcc void (%struct.A*, ...) [[CALLEE]](%struct.A* inreg %{{.*}}, ...)
diff --git a/test/CodeGenCXX/microsoft-abi-vmemptr-vbase.cpp b/test/CodeGenCXX/microsoft-abi-vmemptr-vbase.cpp
index 85cc84fb0367..972428af80e3 100644
--- a/test/CodeGenCXX/microsoft-abi-vmemptr-vbase.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vmemptr-vbase.cpp
@@ -8,5 +8,5 @@ struct B : virtual A {
virtual void f();
};
void (B::*MemPtr)(void) = &B::f;
-// CHECK-DAG: @"\01?MemPtr@PR23452@@3P8B@1@AEXXZQ21@" = global { i8*, i32, i32 } { i8* bitcast ({{.*}} @"\01??_9B@PR23452@@$BA@AE" to i8*), i32 0, i32 4 }
+// CHECK-DAG: @"?MemPtr@PR23452@@3P8B@1@AEXXZQ21@" = dso_local global { i8*, i32, i32 } { i8* bitcast ({{.*}} @"??_9B@PR23452@@$BA@AE" to i8*), i32 0, i32 4 }
}
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-no-thunks.cpp b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-no-thunks.cpp
index 86314cff324e..62289e42804d 100644
--- a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-no-thunks.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-no-thunks.cpp
@@ -24,8 +24,8 @@ struct X : A, B {
// CHECK-LABEL: VFTable indices for 'test1::X' (1 entry)
// CHECK-NEXT: 0 | void test1::X::f()
- // MANGLING-DAG: @"\01??_7X@test1@@6BA@1@@"
- // MANGLING-DAG: @"\01??_7X@test1@@6BB@1@@"
+ // MANGLING-DAG: @"??_7X@test1@@6BA@1@@"
+ // MANGLING-DAG: @"??_7X@test1@@6BB@1@@"
// Overrides only the left child's method (A::f), needs no thunks.
virtual void f();
@@ -108,7 +108,7 @@ struct X : Empty, A {
// CHECK-LABEL: VFTable indices for 'test4::X' (1 entry).
// CHECK-NEXT: 0 | void test4::X::f()
- // MANGLING-DAG: @"\01??_7X@test4@@6B@"
+ // MANGLING-DAG: @"??_7X@test4@@6B@"
virtual void f();
} x;
@@ -141,8 +141,8 @@ struct X : C {
// CHECK-LABEL: VFTable indices for 'test5::X' (1 entry).
// CHECK-NEXT: 0 | void test5::X::f()
- // MANGLING-DAG: @"\01??_7X@test5@@6BA@1@@"
- // MANGLING-DAG: @"\01??_7X@test5@@6BB@1@@"
+ // MANGLING-DAG: @"??_7X@test5@@6BA@1@@"
+ // MANGLING-DAG: @"??_7X@test5@@6BB@1@@"
// Overrides both C::f and A::f.
virtual void f();
@@ -241,8 +241,8 @@ struct X : A, B {
// CHECK-LABEL: VFTable indices for 'test8::X' (1 entry).
// CHECK-NEXT: 1 | void test8::X::h()
- // MANGLING-DAG: @"\01??_7X@test8@@6BA@1@@"
- // MANGLING-DAG: @"\01??_7X@test8@@6BB@1@@"
+ // MANGLING-DAG: @"??_7X@test8@@6BA@1@@"
+ // MANGLING-DAG: @"??_7X@test8@@6BB@1@@"
virtual void h();
} x;
@@ -290,10 +290,10 @@ struct X : C, D {
// CHECK-LABEL: VFTable indices for 'test9::X' (1 entry).
// CHECK-NEXT: 1 | void test9::X::z()
- // MANGLING-DAG: @"\01??_7X@test9@@6BA@1@C@1@@"
- // MANGLING-DAG: @"\01??_7X@test9@@6BA@1@D@1@@"
- // MANGLING-DAG: @"\01??_7X@test9@@6BB@1@C@1@@"
- // MANGLING-DAG: @"\01??_7X@test9@@6BB@1@D@1@@"
+ // MANGLING-DAG: @"??_7X@test9@@6BA@1@C@1@@"
+ // MANGLING-DAG: @"??_7X@test9@@6BA@1@D@1@@"
+ // MANGLING-DAG: @"??_7X@test9@@6BB@1@C@1@@"
+ // MANGLING-DAG: @"??_7X@test9@@6BB@1@D@1@@"
virtual void z();
} x;
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-pure-virtual.cpp b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-pure-virtual.cpp
index 76182a2e331e..85022fc3c858 100644
--- a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-pure-virtual.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-pure-virtual.cpp
@@ -23,8 +23,8 @@ struct C : A, B {
// CHECK-NEXT: via vfptr at offset 4
// CHECK-NEXT: 0 | void C::g()
- // MANGLING-DAG: @"\01??_7C@@6BA@@@"
- // MANGLING-DAG: @"\01??_7C@@6BB@@@"
+ // MANGLING-DAG: @"??_7C@@6BA@@@"
+ // MANGLING-DAG: @"??_7C@@6BB@@@"
// Overrides only the right child's method (B::g),
// needs this adjustment but not thunks.
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-return-adjustment.cpp b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-return-adjustment.cpp
index 232c0d9c4dd8..f7b79a9fa5d6 100644
--- a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-return-adjustment.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-return-adjustment.cpp
@@ -36,7 +36,7 @@ struct X : D {
// CHECK-LABEL: VFTable indices for 'test1::X' (1 entry).
// CHECK-NEXT: 2 | test1::C *test1::X::foo()
- // MANGLING-DAG: @"\01??_7X@test1@@6B@"
+ // MANGLING-DAG: @"??_7X@test1@@6B@"
virtual C* foo();
} x;
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp
index 385e9cc17b1b..e34c4d0cddd0 100644
--- a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp
@@ -29,8 +29,8 @@ struct X : A, B {
// CHECK-LABEL: VFTable indices for 'test1::X' (1 entry).
// CHECK-NEXT: 0 | void test1::X::g()
- // BITCODE-DAG: @"\01??_7X@test1@@6BA@1@@"
- // BITCODE-DAG: @"\01??_7X@test1@@6BB@1@@"
+ // BITCODE-DAG: @"??_7X@test1@@6BA@1@@"
+ // BITCODE-DAG: @"??_7X@test1@@6BB@1@@"
virtual void g();
} x;
@@ -71,9 +71,9 @@ struct X : A, B, C {
// CHECK-NEXT: via vfptr at offset 4
// CHECK-NEXT: 0 | void test2::X::g()
- // BITCODE-DAG: @"\01??_7X@test2@@6BA@1@@"
- // BITCODE-DAG: @"\01??_7X@test2@@6BB@1@@"
- // BITCODE-DAG: @"\01??_7X@test2@@6BC@1@@"
+ // BITCODE-DAG: @"??_7X@test2@@6BA@1@@"
+ // BITCODE-DAG: @"??_7X@test2@@6BB@1@@"
+ // BITCODE-DAG: @"??_7X@test2@@6BC@1@@"
virtual void g();
} x;
@@ -154,25 +154,19 @@ struct C : public A, public B {
virtual int bar();
};
-// BITCODE-LABEL: define {{.*}}\01?ffun@test4@@YAXAAUC@1@@Z
+// BITCODE-LABEL: define {{.*}}"?ffun@test4@@YAXAAUC@1@@Z
void ffun(C &c) {
- // BITCODE: load
- // BITCODE: bitcast
- // BITCODE: bitcast
// BITCODE: [[THIS1:%.+]] = bitcast %"struct.test4::C"* {{.*}} to i8*
// BITCODE: [[THIS2:%.+]] = getelementptr inbounds i8, i8* [[THIS1]], i32 4
- // BITCODE-NEXT: call x86_thiscallcc {{.*}}(i8* [[THIS2]])
+ // BITCODE: call x86_thiscallcc {{.*}}(i8* [[THIS2]])
c.bar();
}
-// BITCODE-LABEL: define {{.*}}\01?fop@test4@@YAXAAUC@1@@Z
+// BITCODE-LABEL: define {{.*}}"?fop@test4@@YAXAAUC@1@@Z
void fop(C &c) {
- // BITCODE: load
- // BITCODE: bitcast
- // BITCODE: bitcast
// BITCODE: [[THIS1:%.+]] = bitcast %"struct.test4::C"* {{.*}} to i8*
// BITCODE: [[THIS2:%.+]] = getelementptr inbounds i8, i8* [[THIS1]], i32 4
- // BITCODE-NEXT: call x86_thiscallcc {{.*}}(i8* [[THIS2]])
+ // BITCODE: call x86_thiscallcc {{.*}}(i8* [[THIS2]])
-c;
}
@@ -195,12 +189,12 @@ void C::g(NonTrivial o) {
whatsthis = this;
}
-// BITCODE-LABEL: define void @"\01?g@C@pr30293@@UAAXUNonTrivial@2@@Z"(<{ i8*, %"struct.pr30293::NonTrivial" }>* inalloca)
+// BITCODE-LABEL: define dso_local void @"?g@C@pr30293@@UAAXUNonTrivial@2@@Z"(<{ i8*, %"struct.pr30293::NonTrivial" }>* inalloca)
// BITCODE: %[[thisaddr:[^ ]*]] = getelementptr inbounds <{ i8*, %"struct.pr30293::NonTrivial" }>, <{ i8*, %"struct.pr30293::NonTrivial" }>* {{.*}}, i32 0, i32 0
// BITCODE: %[[thisaddr1:[^ ]*]] = bitcast i8** %[[thisaddr]] to %"struct.pr30293::C"**
// BITCODE: %[[this1:[^ ]*]] = load %"struct.pr30293::C"*, %"struct.pr30293::C"** %[[thisaddr1]], align 4
// BITCODE: %[[this2:[^ ]*]] = bitcast %"struct.pr30293::C"* %[[this1]] to i8*
// BITCODE: %[[this3:[^ ]*]] = getelementptr inbounds i8, i8* %[[this2]], i32 -4
// BITCODE: %[[this4:[^ ]*]] = bitcast i8* %[[this3]] to %"struct.pr30293::C"*
-// BITCODE: store %"struct.pr30293::C"* %[[this4]], %"struct.pr30293::C"** @"\01?whatsthis@pr30293@@3PAUC@1@A", align 4
+// BITCODE: store %"struct.pr30293::C"* %[[this4]], %"struct.pr30293::C"** @"?whatsthis@pr30293@@3PAUC@1@A", align 4
}
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp b/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp
index feba91c50556..38e6ed56847b 100644
--- a/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp
@@ -26,10 +26,10 @@ J::J() {}
// VFTABLES-NEXT: [return adjustment (to type 'struct test1::C *'): 0 non-virtual]
// VFTABLES-NEXT: 2 | test1::D *test1::J::foo()
-// GLOBALS-LABEL: @"\01??_7J@test1@@6B@" = linkonce_odr unnamed_addr constant { [3 x i8*] }
-// GLOBALS: @"\01?foo@J@test1@@QAEPAUB@2@XZ"
-// GLOBALS: @"\01?foo@J@test1@@QAEPAUC@2@XZ"
-// GLOBALS: @"\01?foo@J@test1@@UAEPAUD@2@XZ"
+// GLOBALS-LABEL: @"??_7J@test1@@6B@" = linkonce_odr unnamed_addr constant { [3 x i8*] }
+// GLOBALS: @"?foo@J@test1@@QAEPAUB@2@XZ"
+// GLOBALS: @"?foo@J@test1@@QAEPAUC@2@XZ"
+// GLOBALS: @"?foo@J@test1@@UAEPAUD@2@XZ"
K::K() {}
@@ -44,26 +44,26 @@ K::K() {}
// Only B to C requires adjustment, but we get 3 thunks in K's vftable, two of
// which are trivial.
-// GLOBALS-LABEL: @"\01??_7K@test1@@6B@" = linkonce_odr unnamed_addr constant { [4 x i8*] }
-// GLOBALS: @"\01?foo@K@test1@@QAEPAUB@2@XZ"
-// GLOBALS: @"\01?foo@K@test1@@QAEPAUC@2@XZ"
-// GLOBALS: @"\01?foo@K@test1@@QAEPAUD@2@XZ"
-// GLOBALS: @"\01?foo@K@test1@@UAEPAUE@2@XZ"
+// GLOBALS-LABEL: @"??_7K@test1@@6B@" = linkonce_odr unnamed_addr constant { [4 x i8*] }
+// GLOBALS: @"?foo@K@test1@@QAEPAUB@2@XZ"
+// GLOBALS: @"?foo@K@test1@@QAEPAUC@2@XZ"
+// GLOBALS: @"?foo@K@test1@@QAEPAUD@2@XZ"
+// GLOBALS: @"?foo@K@test1@@UAEPAUE@2@XZ"
// This thunk has a return adjustment.
-// CODEGEN-LABEL: define {{.*}} @"\01?foo@K@test1@@QAEPAUB@2@XZ"
-// CODEGEN: call {{.*}} @"\01?foo@K@test1@@UAEPAUE@2@XZ"
+// CODEGEN-LABEL: define {{.*}} @"?foo@K@test1@@QAEPAUB@2@XZ"
+// CODEGEN: call {{.*}} @"?foo@K@test1@@UAEPAUE@2@XZ"
// CODEGEN: icmp {{.*}}, null
// CODEGEN: getelementptr
// CODEGEN: ret
// These two don't.
-// CODEGEN-LABEL: define {{.*}} @"\01?foo@K@test1@@QAEPAUC@2@XZ"
-// CODEGEN: call {{.*}} @"\01?foo@K@test1@@UAEPAUE@2@XZ"
+// CODEGEN-LABEL: define {{.*}} @"?foo@K@test1@@QAEPAUC@2@XZ"
+// CODEGEN: call {{.*}} @"?foo@K@test1@@UAEPAUE@2@XZ"
// CODEGEN-NEXT: ret
-// CODEGEN-LABEL: define {{.*}} @"\01?foo@K@test1@@QAEPAUD@2@XZ"
-// CODEGEN: call {{.*}} @"\01?foo@K@test1@@UAEPAUE@2@XZ"
+// CODEGEN-LABEL: define {{.*}} @"?foo@K@test1@@QAEPAUD@2@XZ"
+// CODEGEN: call {{.*}} @"?foo@K@test1@@UAEPAUE@2@XZ"
// CODEGEN-NEXT: ret
}
@@ -90,7 +90,7 @@ J::J() {}
// VFTABLES-NEXT: [return adjustment (to type 'struct test2::B *'): 4 non-virtual]
// VFTABLES-NEXT: 1 | test2::D *test2::J::foo()
-// GLOBALS-LABEL: @"\01??_7J@test2@@6B@" = linkonce_odr unnamed_addr constant { [2 x i8*] }
+// GLOBALS-LABEL: @"??_7J@test2@@6B@" = linkonce_odr unnamed_addr constant { [2 x i8*] }
K::K() {}
@@ -101,7 +101,7 @@ K::K() {}
// VFTABLES-NEXT: [return adjustment (to type 'struct test2::D *'): 0 non-virtual]
// VFTABLES-NEXT: 2 | test2::E *test2::K::foo()
-// GLOBALS-LABEL: @"\01??_7K@test2@@6B@" = linkonce_odr unnamed_addr constant { [3 x i8*] }
+// GLOBALS-LABEL: @"??_7K@test2@@6B@" = linkonce_odr unnamed_addr constant { [3 x i8*] }
}
@@ -124,9 +124,9 @@ struct C : virtual A, B {
C::C() {}
-// GLOBALS-LABEL: @"\01??_7C@pr20479@@6B@" = linkonce_odr unnamed_addr constant { [2 x i8*] }
-// GLOBALS: @"\01?f@B@pr20479@@QAEPAUA@2@XZ"
-// GLOBALS: @"\01?f@B@pr20479@@UAEPAU12@XZ"
+// GLOBALS-LABEL: @"??_7C@pr20479@@6B@" = linkonce_odr unnamed_addr constant { [2 x i8*] }
+// GLOBALS: @"?f@B@pr20479@@QAEPAUA@2@XZ"
+// GLOBALS: @"?f@B@pr20479@@UAEPAU12@XZ"
}
namespace pr21073 {
@@ -151,9 +151,9 @@ struct C : virtual A, virtual B {
C::C() {}
-// GLOBALS-LABEL: @"\01??_7C@pr21073@@6B@" = linkonce_odr unnamed_addr constant { [2 x i8*] }
-// GLOBALS: @"\01?f@B@pr21073@@WPPPPPPPI@AEPAUA@2@XZ"
-// GLOBALS: @"\01?f@B@pr21073@@WPPPPPPPI@AEPAU12@XZ"
+// GLOBALS-LABEL: @"??_7C@pr21073@@6B@" = linkonce_odr unnamed_addr constant { [2 x i8*] }
+// GLOBALS: @"?f@B@pr21073@@WPPPPPPPI@AEPAUA@2@XZ"
+// GLOBALS: @"?f@B@pr21073@@WPPPPPPPI@AEPAU12@XZ"
}
namespace pr21073_2 {
@@ -168,9 +168,9 @@ D::D() {}
// VFTABLES-NEXT: [return adjustment (to type 'struct pr21073_2::A *'): vbase #1, 0 non-virtual]
// VFTABLES-NEXT: 1 | pr21073_2::C *pr21073_2::C::foo()
-// GLOBALS-LABEL: @"\01??_7D@pr21073_2@@6B@" = {{.*}} constant { [2 x i8*] }
-// GLOBALS: @"\01?foo@C@pr21073_2@@QAEPAUA@2@XZ"
-// GLOBALS: @"\01?foo@C@pr21073_2@@UAEPAU12@XZ"
+// GLOBALS-LABEL: @"??_7D@pr21073_2@@6B@" = {{.*}} constant { [2 x i8*] }
+// GLOBALS: @"?foo@C@pr21073_2@@QAEPAUA@2@XZ"
+// GLOBALS: @"?foo@C@pr21073_2@@UAEPAU12@XZ"
}
namespace test3 {
@@ -196,10 +196,10 @@ D::D() {}
// VFTABLES-NEXT: [return adjustment (to type 'struct test3::D *'): 0 non-virtual]
// VFTABLES-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual]
-// GLOBALS-LABEL: @"\01??_7D@test3@@6B@" = {{.*}} constant { [3 x i8*] }
-// GLOBALS: @"\01?fn@D@test3@@$4PPPPPPPM@A@AEPAUA@2@XZ"
-// GLOBALS: @"\01?fn@D@test3@@$4PPPPPPPM@A@AEPAUB@2@XZ"
-// GLOBALS: @"\01?fn@D@test3@@$4PPPPPPPM@A@AEPAU12@XZ"
+// GLOBALS-LABEL: @"??_7D@test3@@6B@" = {{.*}} constant { [3 x i8*] }
+// GLOBALS: @"?fn@D@test3@@$4PPPPPPPM@A@AEPAUA@2@XZ"
+// GLOBALS: @"?fn@D@test3@@$4PPPPPPPM@A@AEPAUB@2@XZ"
+// GLOBALS: @"?fn@D@test3@@$4PPPPPPPM@A@AEPAU12@XZ"
}
namespace pr34302 {
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
index 738c15d89d21..f84ffd5427df 100644
--- a/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
@@ -19,7 +19,7 @@ struct A {
int ia;
};
A a;
-// EMITS-VFTABLE-DAG: @"\01??_7A@@6B@" = linkonce_odr unnamed_addr constant { [3 x i8*] }
+// EMITS-VFTABLE-DAG: @"??_7A@@6B@" = linkonce_odr unnamed_addr constant { [3 x i8*] }
void use(A *obj) { obj->f(); }
struct B : A {
@@ -39,7 +39,7 @@ struct B : A {
virtual void j();
};
B b;
-// EMITS-VFTABLE-DAG: @"\01??_7B@@6B@" = linkonce_odr unnamed_addr constant { [5 x i8*] }
+// EMITS-VFTABLE-DAG: @"??_7B@@6B@" = linkonce_odr unnamed_addr constant { [5 x i8*] }
void use(B *obj) { obj->f(); }
struct C {
@@ -54,7 +54,7 @@ struct C {
virtual void f();
};
void C::f() {}
-// NO-VFTABLE-NOT: @"\01??_7C@@6B@"
+// NO-VFTABLE-NOT: @"??_7C@@6B@"
void use(C *obj) { obj->f(); }
struct D {
@@ -69,7 +69,7 @@ struct D {
virtual ~D();
};
D d;
-// EMITS-VFTABLE-DAG: @"\01??_7D@@6B@" = linkonce_odr unnamed_addr constant { [2 x i8*] }
+// EMITS-VFTABLE-DAG: @"??_7D@@6B@" = linkonce_odr unnamed_addr constant { [2 x i8*] }
void use(D *obj) { obj->f(); }
struct E : A {
@@ -89,7 +89,7 @@ struct E : A {
virtual void i();
};
void E::i() {}
-// NO-VFTABLE-NOT: @"\01??_7E@@6B@"
+// NO-VFTABLE-NOT: @"??_7E@@6B@"
void use(E *obj) { obj->i(); }
struct F : A {
@@ -107,7 +107,7 @@ struct F : A {
virtual ~F();
};
F f;
-// EMITS-VFTABLE-DAG: @"\01??_7F@@6B@" = linkonce_odr unnamed_addr constant { [5 x i8*] }
+// EMITS-VFTABLE-DAG: @"??_7F@@6B@" = linkonce_odr unnamed_addr constant { [5 x i8*] }
void use(F *obj) { obj->i(); }
struct G : E {
@@ -128,7 +128,7 @@ struct G : E {
virtual void j();
};
void G::j() {}
-// NO-VFTABLE-NOT: @"\01??_7G@@6B@"
+// NO-VFTABLE-NOT: @"??_7G@@6B@"
void use(G *obj) { obj->j(); }
// Test that the usual Itanium-style key method does not emit a vtable.
@@ -136,7 +136,7 @@ struct H {
virtual void f();
};
void H::f() {}
-// NO-VFTABLE-NOT: @"\01??_7H@@6B@"
+// NO-VFTABLE-NOT: @"??_7H@@6B@"
struct Empty { };
@@ -295,7 +295,7 @@ struct S {
// CHECK-NEXT: 0 | void S::f() [deleted]
virtual void f() = delete;
S();
- // EMITS-VFTABLE-DAG: @"\01??_7S@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast (void ()* @_purecall to i8*)] }
+ // EMITS-VFTABLE-DAG: @"??_7S@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast (void ()* @_purecall to i8*)] }
};
S::S() {}
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp
index e26d333bad12..c5ce69f5cbca 100644
--- a/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp
@@ -67,10 +67,10 @@ struct A : virtual V1 {
// CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, 0 non-virtual]
virtual void f();
- // MANGLING-DAG: @"\01?f@A@simple@@$4PPPPPPPM@A@AEXXZ"
+ // MANGLING-DAG: @"?f@A@simple@@$4PPPPPPPM@A@AEXXZ"
virtual ~A();
- // MANGLING-DAG: @"\01??_EA@simple@@$4PPPPPPPM@A@AEPAXI@Z"
+ // MANGLING-DAG: @"??_EA@simple@@$4PPPPPPPM@A@AEPAXI@Z"
};
A a;
@@ -102,11 +102,11 @@ struct B : virtual V3 {
B() { use_somewhere_else(this); }
virtual void f();
- // MANGLING-DAG: @"\01?f@B@simple@@$4PPPPPPPE@A@AEXXZ"
+ // MANGLING-DAG: @"?f@B@simple@@$4PPPPPPPE@A@AEXXZ"
// Has an implicit destructor.
- // MANGLING-DAG: @"\01??_EB@simple@@$4PPPPPPPE@7AEPAXI@Z"
- // MANGLING-DAG: @"\01??_EB@simple@@$4PPPPPPPM@A@AEPAXI@Z"
+ // MANGLING-DAG: @"??_EB@simple@@$4PPPPPPPE@7AEPAXI@Z"
+ // MANGLING-DAG: @"??_EB@simple@@$4PPPPPPPM@A@AEPAXI@Z"
};
B b;
@@ -147,12 +147,12 @@ struct C : virtual V4 {
int x;
virtual void f();
- // MANGLING-DAG: @"\01?f@C@simple@@$4PPPPPPPA@3AEXXZ"
- // MANGLING-DAG: @"\01?f@C@simple@@$4PPPPPPPE@A@AEXXZ"
+ // MANGLING-DAG: @"?f@C@simple@@$4PPPPPPPA@3AEXXZ"
+ // MANGLING-DAG: @"?f@C@simple@@$4PPPPPPPE@A@AEXXZ"
virtual ~C();
- // MANGLING-DAG: @"\01??_EC@simple@@$4PPPPPPPA@M@AEPAXI@Z"
- // MANGLING-DAG: @"\01??_EC@simple@@$4PPPPPPPE@7AEPAXI@Z"
- // MANGLING-DAG: @"\01??_EC@simple@@$4PPPPPPPM@A@AEPAXI@Z"
+ // MANGLING-DAG: @"??_EC@simple@@$4PPPPPPPA@M@AEPAXI@Z"
+ // MANGLING-DAG: @"??_EC@simple@@$4PPPPPPPE@7AEPAXI@Z"
+ // MANGLING-DAG: @"??_EC@simple@@$4PPPPPPPM@A@AEPAXI@Z"
};
C c;
@@ -167,7 +167,7 @@ class D : B {
D();
int z;
- // MANGLING-DAG: @"\01?f@B@simple@@$4PPPPPPPE@3AEXXZ"
+ // MANGLING-DAG: @"?f@B@simple@@$4PPPPPPPE@3AEXXZ"
};
D::D() {}
@@ -192,7 +192,7 @@ struct F : virtual E {
virtual void g(); // Force a vtordisp.
int f;
- // MANGLING-DAG: @"\01?g@F@simple@@$4PPPPPPPM@A@AEXXZ"{{.*}}??_EF@simple@@$4PPPPPPPM@A@AEPAXI@Z
+ // MANGLING-DAG: @"?g@F@simple@@$4PPPPPPPM@A@AEXXZ"{{.*}}??_EF@simple@@$4PPPPPPPM@A@AEPAXI@Z
// MANGLING-DAG: ?f@E@simple@@UAEXXZ{{.*}}??_EF@simple@@$4PPPPPPPE@7AEPAXI@Z
};
@@ -213,8 +213,8 @@ struct G : F {
G();
int g;
- // MANGLING-DAG: @"\01?g@F@simple@@$4PPPPPPPM@3AEXXZ"{{.*}}@"\01??_EG@simple@@$4PPPPPPPM@A@AEPAXI@Z"
- // MANGLING-DAG: @"\01?f@E@simple@@UAEXXZ"{{.*}}@"\01??_EG@simple@@$4PPPPPPPE@7AEPAXI@Z"
+ // MANGLING-DAG: @"?g@F@simple@@$4PPPPPPPM@3AEXXZ"{{.*}}@"??_EG@simple@@$4PPPPPPPM@A@AEPAXI@Z"
+ // MANGLING-DAG: @"?f@E@simple@@UAEXXZ"{{.*}}@"??_EG@simple@@$4PPPPPPPE@7AEPAXI@Z"
};
G::G() {}
@@ -248,11 +248,11 @@ struct A : virtual simple::A {
// CHECK-NEXT: vboffset at 8 in the vbtable, 8 non-virtual]
// `vtordispex{8,8,4294967292,8}'
- // MANGLING-DAG: @"\01?f@A@simple@@$R477PPPPPPPM@7AEXXZ"
+ // MANGLING-DAG: @"?f@A@simple@@$R477PPPPPPPM@7AEXXZ"
virtual ~A();
// vtordisp{4294967292,0}
- // MANGLING-DAG: @"\01??_EA@extended@@$4PPPPPPPM@A@AEPAXI@Z"
+ // MANGLING-DAG: @"??_EA@extended@@$4PPPPPPPM@A@AEPAXI@Z"
};
A a;
@@ -273,7 +273,7 @@ struct B : virtual simple::A {
// CHECK-NEXT: vboffset at 8 in the vbtable, 8 non-virtual]
// vtordisp{4294967292,0}
- // MANGLING-DAG: @"\01??_EB@extended@@$4PPPPPPPM@A@AEPAXI@Z"
+ // MANGLING-DAG: @"??_EB@extended@@$4PPPPPPPM@A@AEPAXI@Z"
};
B b;
@@ -290,10 +290,10 @@ struct C : virtual simple::A {
// CHECK-NEXT: vboffset at 8 in the vbtable, 8 non-virtual]
// `vtordispex{12,8,4294967292,8}'
- // MANGLING-DAG: @"\01?f@A@simple@@$R4M@7PPPPPPPM@7AEXXZ"
+ // MANGLING-DAG: @"?f@A@simple@@$R4M@7PPPPPPPM@7AEXXZ"
int x;
virtual ~C();
- // MANGLING-DAG: @"\01??_EC@extended@@$4PPPPPPPM@A@AEPAXI@Z"
+ // MANGLING-DAG: @"??_EC@extended@@$4PPPPPPPM@A@AEPAXI@Z"
};
C c;
@@ -316,10 +316,10 @@ struct E : virtual D {
// CHECK-NEXT: vboffset at 8 in the vbtable, 12 non-virtual]
// `vtordispex{8,8,4294967292,12}'
- // MANGLING-DAG: @"\01?f@D@extended@@$R477PPPPPPPM@M@AEXXZ"
+ // MANGLING-DAG: @"?f@D@extended@@$R477PPPPPPPM@M@AEXXZ"
virtual ~E();
- // MANGLING-DAG: @"\01??_EE@extended@@$4PPPPPPPM@A@AEPAXI@Z"
+ // MANGLING-DAG: @"??_EE@extended@@$4PPPPPPPM@A@AEPAXI@Z"
};
E e;
@@ -336,10 +336,10 @@ struct F : virtual Z, virtual D {
// CHECK-NEXT: vboffset at 12 in the vbtable, 12 non-virtual]
// `vtordispex{20,12,4294967292,12}'
- // MANGLING-DAG: @"\01?f@D@extended@@$R4BE@M@PPPPPPPM@M@AEXXZ"
+ // MANGLING-DAG: @"?f@D@extended@@$R4BE@M@PPPPPPPM@M@AEXXZ"
int x;
virtual ~F();
- // MANGLING-DAG: @"\01??_EF@extended@@$4PPPPPPPM@M@AEPAXI@Z"
+ // MANGLING-DAG: @"??_EF@extended@@$4PPPPPPPM@M@AEPAXI@Z"
};
F f;
@@ -365,7 +365,7 @@ struct G : virtual simple::A {
virtual ~G();
// vtordisp{4294967292,0}
- // MANGLING-DAG: @"\01??_EG@extended@@$4PPPPPPPM@A@AEPAXI@Z"
+ // MANGLING-DAG: @"??_EG@extended@@$4PPPPPPPM@A@AEPAXI@Z"
};
G g;
@@ -385,8 +385,8 @@ struct H : Z, A {
// CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, vbptr at 8 to the left,
// CHECK-NEXT: vboffset at 8 in the vbtable, 8 non-virtual]
- // MANGLING-DAG: @"\01?f@A@simple@@$R477PPPPPPPM@7AEXXZ"
- // MANGLING-DAG: @"\01??_EH@extended@@$4PPPPPPPM@BA@AEPAXI@Z"
+ // MANGLING-DAG: @"?f@A@simple@@$R477PPPPPPPM@7AEXXZ"
+ // MANGLING-DAG: @"??_EH@extended@@$4PPPPPPPM@BA@AEPAXI@Z"
};
H h;
@@ -407,7 +407,7 @@ struct A : virtual simple::B {
// CHECK-NEXT: 0 | [this adjustment: vtordisp at -12, vbptr at 20 to the left,
// CHECK-NEXT: vboffset at 8 in the vbtable, 16 non-virtual]
- // MANGLING-DAG: @"\01?f@B@simple@@$R4BE@7PPPPPPPE@BA@AEXXZ"
+ // MANGLING-DAG: @"?f@B@simple@@$R4BE@7PPPPPPPE@BA@AEXXZ"
int a;
virtual ~A();
};
@@ -442,7 +442,7 @@ struct D : C {
// CHECK-NEXT: 0 | void pr19408::C::f()
// CHECK-NEXT: [this adjustment: vtordisp at -4, -4 non-virtual]
- // MANGLING-DAG: @"\01?f@C@pr19408@@$4PPPPPPPM@3AEXXZ"
+ // MANGLING-DAG: @"?f@C@pr19408@@$4PPPPPPPM@3AEXXZ"
D();
int d;
};
@@ -463,10 +463,10 @@ struct B : virtual A {
virtual ~B();
protected:
virtual void prot();
- // MANGLING-DAG: @"\01?prot@B@access@@$2PPPPPPPM@A@AEXXZ"
+ // MANGLING-DAG: @"?prot@B@access@@$2PPPPPPPM@A@AEXXZ"
private:
virtual void priv();
- // MANGLING-DAG: @"\01?priv@B@access@@$0PPPPPPPM@A@AEXXZ"
+ // MANGLING-DAG: @"?priv@B@access@@$0PPPPPPPM@A@AEXXZ"
};
B b;
@@ -474,8 +474,8 @@ B b;
struct C : virtual B {
virtual ~C();
- // MANGLING-DAG: @"\01?prot@B@access@@$R277PPPPPPPM@7AEXXZ"
- // MANGLING-DAG: @"\01?priv@B@access@@$R077PPPPPPPM@7AEXXZ"
+ // MANGLING-DAG: @"?prot@B@access@@$R277PPPPPPPM@7AEXXZ"
+ // MANGLING-DAG: @"?priv@B@access@@$R077PPPPPPPM@7AEXXZ"
};
C c;
@@ -503,7 +503,7 @@ struct X : B, virtual C {
// CHECK-NEXT: 0 | void pr19505::B::f()
// CHECK-NEXT: 1 | void pr19505::A::z()
- // MANGLING-DAG: @"\01??_7X@pr19505@@6BB@1@@" = {{.*}}@"\01?f@B@pr19505@@UAEXXZ"
+ // MANGLING-DAG: @"??_7X@pr19505@@6BB@1@@" = {{.*}}@"?f@B@pr19505@@UAEXXZ"
} x;
void build_vftable(X *obj) { obj->g(); }
@@ -530,7 +530,7 @@ struct X : C, virtual B {
// CHECK-NEXT: 1 | void pr19506::X::g()
// CHECK-NEXT: [this adjustment: vtordisp at -4, -12 non-virtual]
- // MANGLING-DAG: @"\01??_7X@pr19506@@6BB@1@@" = {{.*}}@"\01?f@B@pr19506@@UAEXXZ"
+ // MANGLING-DAG: @"??_7X@pr19506@@6BB@1@@" = {{.*}}@"?f@B@pr19506@@UAEXXZ"
} x;
void build_vftable(X *obj) { obj->g(); }
@@ -562,7 +562,7 @@ struct X : B, C {
// CHECK-NEXT: 1 | void pr19519::C::g()
// CHECK-NEXT: [this adjustment: vtordisp at -4, -4 non-virtual]
- // MANGLING-DAG: @"\01??_7X@pr19519@@6B@" = {{.*}}@"\01?g@C@pr19519@@$4PPPPPPPM@3AEXXZ"
+ // MANGLING-DAG: @"??_7X@pr19519@@6B@" = {{.*}}@"?g@C@pr19519@@$4PPPPPPPM@3AEXXZ"
};
X::X() {}
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp
index 342a584182cc..8e309acc9188 100644
--- a/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp
@@ -22,7 +22,7 @@ struct C: virtual A {
// CHECK-NEXT: vbtable index 1, vfptr at offset 0
// CHECK-NEXT: 0 | void C::f()
- // MANGLING-DAG: @"\01??_7C@@6B@"
+ // MANGLING-DAG: @"??_7C@@6B@"
virtual void f() {}
};
@@ -44,8 +44,8 @@ struct D: virtual A {
// CHECK-NEXT: via vbtable index 1, vfptr at offset 0
// CHECK-NEXT: 0 | void D::f()
- // MANGLING-DAG: @"\01??_7D@@6B0@@"
- // MANGLING-DAG: @"\01??_7D@@6BA@@@"
+ // MANGLING-DAG: @"??_7D@@6B0@@"
+ // MANGLING-DAG: @"??_7D@@6BA@@@"
virtual void f();
virtual void h();
@@ -60,7 +60,7 @@ struct X { int x; };
// X and A get reordered in the layout since X doesn't have a vfptr while A has.
struct Y : X, A { };
-// MANGLING-DAG: @"\01??_7Y@Test1@@6B@"
+// MANGLING-DAG: @"??_7Y@Test1@@6B@"
struct Z : virtual Y {
Z();
@@ -70,7 +70,7 @@ struct Z : virtual Y {
// CHECK-NOT: VFTable indices for 'Test1::Z'
- // MANGLING-DAG: @"\01??_7Z@Test1@@6B@"
+ // MANGLING-DAG: @"??_7Z@Test1@@6B@"
};
Z::Z() {}
@@ -92,9 +92,9 @@ struct X: virtual A, virtual B {
// CHECK-LABEL: VFTable indices for 'Test2::X' (1 entry).
// CHECK-NEXT: 0 | void Test2::X::h()
- // MANGLING-DAG: @"\01??_7X@Test2@@6B01@@"
- // MANGLING-DAG: @"\01??_7X@Test2@@6BA@@@"
- // MANGLING-DAG: @"\01??_7X@Test2@@6BB@@@"
+ // MANGLING-DAG: @"??_7X@Test2@@6B01@@"
+ // MANGLING-DAG: @"??_7X@Test2@@6BA@@@"
+ // MANGLING-DAG: @"??_7X@Test2@@6BB@@@"
virtual void h();
};
@@ -106,7 +106,7 @@ void use(X *obj) { obj->h(); }
namespace Test3 {
struct X : virtual A {
- // MANGLING-DAG: @"\01??_7X@Test3@@6B@"
+ // MANGLING-DAG: @"??_7X@Test3@@6B@"
};
struct Y: virtual X {
@@ -117,7 +117,7 @@ struct Y: virtual X {
// CHECK-NOT: VFTable indices for 'Test3::Y'
- // MANGLING-DAG: @"\01??_7Y@Test3@@6B@"
+ // MANGLING-DAG: @"??_7Y@Test3@@6B@"
};
Y::Y() {}
@@ -142,10 +142,10 @@ struct X: virtual C {
// CHECK-NOT: VFTable indices for 'Test4::X'
- // MANGLING-DAG: @"\01??_7X@Test4@@6B@"
+ // MANGLING-DAG: @"??_7X@Test4@@6B@"
// Also check the mangling of the thunk.
- // MANGLING-DAG: define linkonce_odr x86_thiscallcc void @"\01?f@C@@WPPPPPPPI@AEXXZ"
+ // MANGLING-DAG: define linkonce_odr dso_local x86_thiscallcc void @"?f@C@@WPPPPPPPI@AEXXZ"
};
X::X() {}
@@ -155,7 +155,7 @@ namespace Test5 {
// New methods are added to the base's vftable.
struct X : A {
- // MANGLING-DAG: @"\01??_7X@Test5@@6B@"
+ // MANGLING-DAG: @"??_7X@Test5@@6B@"
virtual void g();
};
@@ -171,8 +171,8 @@ struct Y : virtual X {
// CHECK-LABEL: VFTable indices for 'Test5::Y' (1 entry).
// CHECK-NEXT: 0 | void Test5::Y::h()
- // MANGLING-DAG: @"\01??_7Y@Test5@@6B01@@"
- // MANGLING-DAG: @"\01??_7Y@Test5@@6BX@1@@"
+ // MANGLING-DAG: @"??_7Y@Test5@@6B01@@"
+ // MANGLING-DAG: @"??_7Y@Test5@@6BX@1@@"
virtual void h();
};
@@ -191,7 +191,7 @@ struct X : A, virtual Empty {
// CHECK-NOT: VFTable indices for 'Test6::X'
- // MANGLING-DAG: @"\01??_7X@Test6@@6B@"
+ // MANGLING-DAG: @"??_7X@Test6@@6B@"
};
X::X() {}
@@ -200,7 +200,7 @@ X::X() {}
namespace Test7 {
struct X : C {
- // MANGLING-DAG: @"\01??_7X@Test7@@6B@"
+ // MANGLING-DAG: @"??_7X@Test7@@6B@"
};
struct Y : virtual X {
@@ -215,7 +215,7 @@ struct Y : virtual X {
// CHECK-NOT: VFTable indices for 'Test7::Y'
- // MANGLING-DAG: @"\01??_7Y@Test7@@6B@"
+ // MANGLING-DAG: @"??_7Y@Test7@@6B@"
};
Y::Y() {}
@@ -236,8 +236,8 @@ struct X : D, C {
// CHECK-NEXT: via vbtable index 1, vfptr at offset 0
// CHECK-NEXT: 0 | void Test8::X::f()
- // MANGLING-DAG: @"\01??_7X@Test8@@6BA@@@"
- // MANGLING-DAG: @"\01??_7X@Test8@@6BD@@@"
+ // MANGLING-DAG: @"??_7X@Test8@@6BA@@@"
+ // MANGLING-DAG: @"??_7X@Test8@@6BD@@@"
virtual void f();
};
@@ -299,8 +299,8 @@ struct Y : virtual X {
// CHECK-LABEL: VFTable indices for 'Test9::Y' (1 entry).
// CHECK-NEXT: 0 | void Test9::Y::h()
- // MANGLING-DAG: @"\01??_7Y@Test9@@6B01@@"
- // MANGLING-DAG: @"\01??_7Y@Test9@@6BX@1@@"
+ // MANGLING-DAG: @"??_7Y@Test9@@6B01@@"
+ // MANGLING-DAG: @"??_7Y@Test9@@6BX@1@@"
virtual void h();
};
@@ -322,10 +322,10 @@ struct Z : Y, virtual B {
// CHECK-NOT: VFTable indices for 'Test9::Z'
- // MANGLING-DAG: @"\01??_7Z@Test9@@6BX@1@@"
- // MANGLING-DAG: @"\01??_7Z@Test9@@6BY@1@@"
+ // MANGLING-DAG: @"??_7Z@Test9@@6BX@1@@"
+ // MANGLING-DAG: @"??_7Z@Test9@@6BY@1@@"
- // MANGLING-DAG: @"\01??_7Z@Test9@@6B@"
+ // MANGLING-DAG: @"??_7Z@Test9@@6B@"
};
Z::Z() {}
@@ -355,12 +355,12 @@ struct W : Z, D, virtual A, virtual B {
// CHECK-NOT: VFTable indices for 'Test9::W'
- // MANGLING-DAG: @"\01??_7W@Test9@@6BA@@@"
- // MANGLING-DAG: @"\01??_7W@Test9@@6BD@@@"
- // MANGLING-DAG: @"\01??_7W@Test9@@6BX@1@@"
+ // MANGLING-DAG: @"??_7W@Test9@@6BA@@@"
+ // MANGLING-DAG: @"??_7W@Test9@@6BD@@@"
+ // MANGLING-DAG: @"??_7W@Test9@@6BX@1@@"
- // MANGLING-DAG: @"\01??_7W@Test9@@6B@"
- // MANGLING-DAG: @"\01??_7W@Test9@@6BY@1@@"
+ // MANGLING-DAG: @"??_7W@Test9@@6B@"
+ // MANGLING-DAG: @"??_7W@Test9@@6BY@1@@"
};
W::W() {}
@@ -404,12 +404,12 @@ struct T : Z, D, virtual A, virtual B {
// CHECK-NEXT: via vbtable index 2, vfptr at offset 0
// CHECK-NEXT: 0 | void Test9::T::g()
- // MANGLING-DAG: @"\01??_7T@Test9@@6BA@@@"
- // MANGLING-DAG: @"\01??_7T@Test9@@6BD@@@"
- // MANGLING-DAG: @"\01??_7T@Test9@@6BX@1@@"
+ // MANGLING-DAG: @"??_7T@Test9@@6BA@@@"
+ // MANGLING-DAG: @"??_7T@Test9@@6BD@@@"
+ // MANGLING-DAG: @"??_7T@Test9@@6BX@1@@"
- // MANGLING-DAG: @"\01??_7T@Test9@@6B@"
- // MANGLING-DAG: @"\01??_7T@Test9@@6BY@1@@"
+ // MANGLING-DAG: @"??_7T@Test9@@6B@"
+ // MANGLING-DAG: @"??_7T@Test9@@6BY@1@@"
virtual void f();
virtual void g();
@@ -443,8 +443,8 @@ struct X : virtual A {};
struct Y { virtual void g(); };
struct Z : virtual X, Y {
- // MANGLING-DAG: @"\01??_7Z@Test11@@6BY@1@@"
- // MANGLING-DAG: @"\01??_7Z@Test11@@6BX@1@@"
+ // MANGLING-DAG: @"??_7Z@Test11@@6BY@1@@"
+ // MANGLING-DAG: @"??_7Z@Test11@@6BX@1@@"
};
Z z;
@@ -468,7 +468,7 @@ struct Z : virtual Y {
// CHECK-NEXT: 1 | void A::z()
int z;
- // MANGLING-DAG: @"\01??_7Z@Test12@@6BA@@@" = {{.*}}@"\01?f@Y@Test12@@UAEXXZ"
+ // MANGLING-DAG: @"??_7Z@Test12@@6BA@@@" = {{.*}}@"?f@Y@Test12@@UAEXXZ"
};
struct W : Z {
@@ -478,7 +478,7 @@ struct W : Z {
W();
int w;
- // MANGLING-DAG: @"\01??_7W@Test12@@6BA@@@" = {{.*}}@"\01?f@Y@Test12@@UAEXXZ"
+ // MANGLING-DAG: @"??_7W@Test12@@6BA@@@" = {{.*}}@"?f@Y@Test12@@UAEXXZ"
};
W::W() {}
@@ -683,10 +683,10 @@ struct C : virtual B, A {
};
C c;
-// MANGLING-DAG: @"\01??_7A@pr17748@@6B@"
-// MANGLING-DAG: @"\01??_7B@pr17748@@6B@"
-// MANGLING-DAG: @"\01??_7C@pr17748@@6BA@1@@"
-// MANGLING-DAG: @"\01??_7C@pr17748@@6BB@1@@"
+// MANGLING-DAG: @"??_7A@pr17748@@6B@"
+// MANGLING-DAG: @"??_7B@pr17748@@6B@"
+// MANGLING-DAG: @"??_7C@pr17748@@6BA@1@@"
+// MANGLING-DAG: @"??_7C@pr17748@@6BB@1@@"
}
namespace pr19066 {
@@ -721,9 +721,9 @@ D obj;
// Each MDC only has one vftable.
-// MANGLING-DAG: @"\01??_7D@pr19240@@6B@"
-// MANGLING-DAG: @"\01??_7A@pr19240@@6B@"
-// MANGLING-DAG: @"\01??_7B@pr19240@@6B@"
+// MANGLING-DAG: @"??_7D@pr19240@@6B@"
+// MANGLING-DAG: @"??_7A@pr19240@@6B@"
+// MANGLING-DAG: @"??_7B@pr19240@@6B@"
}
@@ -746,7 +746,7 @@ struct Z : Y {
Z();
int z;
- // MANGLING-DAG: @"\01??_7Z@pr19408@@6B@" = {{.*}}@"\01?f@Y@pr19408@@W3AEXXZ"
+ // MANGLING-DAG: @"??_7Z@pr19408@@6B@" = {{.*}}@"?f@Y@pr19408@@W3AEXXZ"
};
Z::Z() {}
@@ -759,7 +759,7 @@ struct W : B, Y {
W();
int w;
- // MANGLING-DAG: @"\01??_7W@pr19408@@6BY@1@@" = {{.*}}@"\01?f@Y@pr19408@@W3AEXXZ"
+ // MANGLING-DAG: @"??_7W@pr19408@@6BY@1@@" = {{.*}}@"?f@Y@pr19408@@W3AEXXZ"
};
W::W() {}
@@ -771,7 +771,7 @@ struct A {
};
struct __declspec(dllexport) B : virtual A {
virtual void f() = 0;
- // MANGLING-DAG: @"\01??_7B@Test13@@6B@" = weak_odr dllexport unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast (void ()* @_purecall to i8*)] }
+ // MANGLING-DAG: @"??_7B@Test13@@6B@" = weak_odr dllexport unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast (void ()* @_purecall to i8*)] }
};
}
@@ -788,8 +788,8 @@ C::C() {}
// CHECK-LABEL: VFTable for 'pr21031_1::B' in 'pr21031_1::C' (1 entry)
// CHECK-NEXT: 0 | void pr21031_1::B::g()
-// MANGLING-DAG: @"\01??_7C@pr21031_1@@6BB@1@@" = {{.*}} constant { [1 x i8*] }
-// MANGLING-DAG: @"\01??_7C@pr21031_1@@6B@" = {{.*}} constant { [1 x i8*] }
+// MANGLING-DAG: @"??_7C@pr21031_1@@6BB@1@@" = {{.*}} constant { [1 x i8*] }
+// MANGLING-DAG: @"??_7C@pr21031_1@@6B@" = {{.*}} constant { [1 x i8*] }
}
namespace pr21031_2 {
@@ -804,8 +804,8 @@ C::C() {}
// CHECK-LABEL: VFTable for 'pr21031_2::A' in 'pr21031_2::B' in 'pr21031_2::C' (1 entry)
// CHECK-NEXT: 0 | void pr21031_2::A::f()
-// MANGLING-DAG: @"\01??_7C@pr21031_2@@6BA@1@@" = {{.*}} constant { [1 x i8*] }
-// MANGLING-DAG: @"\01??_7C@pr21031_2@@6BB@1@@" = {{.*}} constant { [1 x i8*] }
+// MANGLING-DAG: @"??_7C@pr21031_2@@6BA@1@@" = {{.*}} constant { [1 x i8*] }
+// MANGLING-DAG: @"??_7C@pr21031_2@@6BB@1@@" = {{.*}} constant { [1 x i8*] }
}
namespace pr21062_1 {
@@ -818,7 +818,7 @@ D::D() {}
// CHECK-LABEL: VFTable for 'pr21062_1::A' in 'pr21062_1::D' (1 entry)
// CHECK-NEXT: 0 | void pr21062_1::A::f()
-// MANGLING-DAG: @"\01??_7D@pr21062_1@@6B@" = {{.*}} constant { [1 x i8*] }
+// MANGLING-DAG: @"??_7D@pr21062_1@@6B@" = {{.*}} constant { [1 x i8*] }
}
namespace pr21062_2 {
@@ -831,7 +831,7 @@ D::D() {}
// CHECK-LABEL: VFTable for 'pr21062_2::A' in 'pr21062_2::D' (1 entry)
// CHECK-NEXT: 0 | void pr21062_2::A::f()
-// MANGLING-DAG: @"\01??_7D@pr21062_2@@6B@" = {{.*}} constant { [1 x i8*] }
+// MANGLING-DAG: @"??_7D@pr21062_2@@6B@" = {{.*}} constant { [1 x i8*] }
}
namespace pr21064 {
@@ -843,5 +843,5 @@ D::D() {}
// CHECK-LABEL: VFTable for 'pr21064::B' in 'pr21064::C' in 'pr21064::D' (1 entry)
// CHECK-NEXT: 0 | void pr21064::B::f()
-// MANGLING-DAG: @"\01??_7D@pr21064@@6B@" = {{.*}} constant { [1 x i8*] }
+// MANGLING-DAG: @"??_7D@pr21064@@6B@" = {{.*}} constant { [1 x i8*] }
}
diff --git a/test/CodeGenCXX/microsoft-compatibility.cpp b/test/CodeGenCXX/microsoft-compatibility.cpp
index 36760243d49b..64d10a54c006 100644
--- a/test/CodeGenCXX/microsoft-compatibility.cpp
+++ b/test/CodeGenCXX/microsoft-compatibility.cpp
@@ -8,7 +8,7 @@ struct S {
template <>
const int S<char>::x[] = {1};
-// CHECK-LABEL: @"\01?x@?$S@D@@2QBHB" = weak_odr constant [1 x i32] [i32 1], comdat
+// CHECK-LABEL: @"?x@?$S@D@@2QBHB" = weak_odr dso_local constant [1 x i32] [i32 1], comdat
template<class T>
void destroy(T *p) {
@@ -20,11 +20,11 @@ extern "C" void f() {
destroy((void*)&a);
}
-// CHECK-LABEL: define void @f()
-// CHECK: call void @"\01??$destroy@X@@YAXPAX@Z"
+// CHECK-LABEL: define dso_local void @f()
+// CHECK: call void @"??$destroy@X@@YAXPAX@Z"
// CHECK: ret void
-// CHECK-LABEL: define linkonce_odr void @"\01??$destroy@X@@YAXPAX@Z"(i8* %p)
+// CHECK-LABEL: define linkonce_odr dso_local void @"??$destroy@X@@YAXPAX@Z"(i8* %p)
// The pseudo-dtor expr should not generate calls to anything.
// CHECK-NOT: call
// CHECK-NOT: invoke
diff --git a/test/CodeGenCXX/microsoft-inaccessible-base.cpp b/test/CodeGenCXX/microsoft-inaccessible-base.cpp
index 2c0d124eb01e..d8af8ef9eaf7 100644
--- a/test/CodeGenCXX/microsoft-inaccessible-base.cpp
+++ b/test/CodeGenCXX/microsoft-inaccessible-base.cpp
@@ -10,11 +10,11 @@ struct B : A { int b; };
struct C : A, B { };
extern "C" A *a_from_c(C *p) { return p; }
-// CHECK-LABEL: define %struct.A* @a_from_c(%struct.C* %{{.*}})
+// CHECK-LABEL: define dso_local %struct.A* @a_from_c(%struct.C* %{{.*}})
// CHECK: bitcast %struct.C* %{{.*}} to %struct.A*
struct D : B, A { };
extern "C" A *a_from_d(D *p) { return p; }
-// CHECK-LABEL: define %struct.A* @a_from_d(%struct.D* %{{.*}})
+// CHECK-LABEL: define dso_local %struct.A* @a_from_d(%struct.D* %{{.*}})
// CHECK: %[[p_i8:[^ ]*]] = bitcast %struct.D* %{{.*}} to i8*
// CHECK: getelementptr inbounds i8, i8* %[[p_i8]], i64 8
diff --git a/test/CodeGenCXX/microsoft-interface.cpp b/test/CodeGenCXX/microsoft-interface.cpp
index 5f3a94a494b7..74a52097d793 100644
--- a/test/CodeGenCXX/microsoft-interface.cpp
+++ b/test/CodeGenCXX/microsoft-interface.cpp
@@ -17,24 +17,24 @@ int fn() {
return s.test();
}
-// CHECK: @_ZTV1S = linkonce_odr unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* null, i8* bitcast ({ i8*, i8*, i8* }* @_ZTI1S to i8*), i8* bitcast (i32 (%struct.S*)* @_ZN1S4testEv to i8*)] }
+// CHECK: @_ZTV1S = linkonce_odr dso_local unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* null, i8* bitcast ({ i8*, i8*, i8* }* @_ZTI1S to i8*), i8* bitcast (i32 (%struct.S*)* @_ZN1S4testEv to i8*)] }
-// CHECK-LABEL: define i32 @_Z2fnv()
+// CHECK-LABEL: define dso_local i32 @_Z2fnv()
// CHECK: call x86_thiscallcc void @_ZN1SC1Ev(%struct.S* %s)
// CHECK: %{{[.0-9A-Z_a-z]+}} = call x86_thiscallcc i32 @_ZN1S4testEv(%struct.S* %s)
-// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @_ZN1SC1Ev(%struct.S* %this)
+// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc void @_ZN1SC1Ev(%struct.S* %this)
// CHECK: call x86_thiscallcc void @_ZN1SC2Ev(%struct.S* %{{[.0-9A-Z_a-z]+}})
-// CHECK-LABEL: define linkonce_odr x86_thiscallcc i32 @_ZN1S4testEv(%struct.S* %this)
+// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc i32 @_ZN1S4testEv(%struct.S* %this)
// CHECK: %{{[.0-9A-Z_a-z]+}} = call x86_thiscallcc i32 @_ZN1I4testEv(%__interface.I* %{{[.0-9A-Z_a-z]+}})
-// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @_ZN1SC2Ev(%struct.S* %this)
+// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc void @_ZN1SC2Ev(%struct.S* %this)
// CHECK: call x86_thiscallcc void @_ZN1IC2Ev(%__interface.I* %{{[.0-9A-Z_a-z]+}})
// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV1S, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)*** %{{[.0-9A-Z_a-z]+}}
-// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @_ZN1IC2Ev(%__interface.I* %this)
+// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc void @_ZN1IC2Ev(%__interface.I* %this)
// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV1I, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)*** %{{[.0-9A-Z_a-z]+}}
-// CHECK-LABEL: define linkonce_odr x86_thiscallcc i32 @_ZN1I4testEv(%__interface.I* %this)
+// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc i32 @_ZN1I4testEv(%__interface.I* %this)
// CHECK: ret i32 1
diff --git a/test/CodeGenCXX/microsoft-new.cpp b/test/CodeGenCXX/microsoft-new.cpp
index 7857e478ef82..01b0960968be 100644
--- a/test/CodeGenCXX/microsoft-new.cpp
+++ b/test/CodeGenCXX/microsoft-new.cpp
@@ -13,7 +13,7 @@ namespace PR13164 {
// MSVC will fall back on the non-array operator new.
void *a;
int *p = new(arbitrary) int[4];
- // CHECK: call i8* @"\01??2@YAPAXIUarbitrary_t@@@Z"(i32 16, %struct.arbitrary_t*
+ // CHECK: call i8* @"??2@YAPAXIUarbitrary_t@@@Z"(i32 16, %struct.arbitrary_t*
}
struct S {
@@ -22,9 +22,9 @@ namespace PR13164 {
void g() {
S *s = new(arbitrary) S[2];
- // CHECK: call i8* @"\01??_US@PR13164@@SAPAXIUarbitrary_t@@@Z"(i32 2, %struct.arbitrary_t*
+ // CHECK: call i8* @"??_US@PR13164@@SAPAXIUarbitrary_t@@@Z"(i32 2, %struct.arbitrary_t*
S *s1 = new(arbitrary) S;
- // CHECK: call i8* @"\01??2@YAPAXIUarbitrary_t@@@Z"(i32 1, %struct.arbitrary_t*
+ // CHECK: call i8* @"??2@YAPAXIUarbitrary_t@@@Z"(i32 1, %struct.arbitrary_t*
}
struct T {
@@ -34,6 +34,6 @@ namespace PR13164 {
void h() {
// This should still call the global operator new[].
T *t = new(arbitrary2) T[2];
- // CHECK: call i8* @"\01??_U@YAPAXIUarbitrary2_t@@@Z"(i32 2, %struct.arbitrary2_t*
+ // CHECK: call i8* @"??_U@YAPAXIUarbitrary2_t@@@Z"(i32 2, %struct.arbitrary2_t*
}
}
diff --git a/test/CodeGenCXX/microsoft-no-rtti-data.cpp b/test/CodeGenCXX/microsoft-no-rtti-data.cpp
index 05255909ced3..3d218ed08fde 100644
--- a/test/CodeGenCXX/microsoft-no-rtti-data.cpp
+++ b/test/CodeGenCXX/microsoft-no-rtti-data.cpp
@@ -1,8 +1,8 @@
// RUN: %clang_cc1 %s -fno-rtti-data -triple=i386-pc-win32 -o - -emit-llvm | FileCheck %s
// vftable shouldn't have RTTI data in it.
-// CHECK-NOT: @"\01??_R4S@@6B@"
-// CHECK: @"\01??_7S@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GS@@UAEPAXI@Z" to i8*)] }, comdat
+// CHECK-NOT: @"??_R4S@@6B@"
+// CHECK: @"??_7S@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast ({{.*}} @"??_GS@@UAEPAXI@Z" to i8*)] }, comdat
struct type_info;
namespace std { using ::type_info; }
@@ -19,4 +19,4 @@ extern S *getS();
const std::type_info &ti = typeid(*getS());
const U &u = dynamic_cast<U &>(*getS());
-// CHECK: call i8* @__RTDynamicCast(i8* %{{.+}}, i32 0, i8* bitcast ({{.*}} @"\01??_R0?AUS@@@8" to i8*), i8* bitcast ({{.*}} @"\01??_R0?AUU@@@8" to i8*), i32 1)
+// CHECK: call i8* @__RTDynamicCast(i8* %{{.+}}, i32 0, i8* bitcast ({{.*}} @"??_R0?AUS@@@8" to i8*), i8* bitcast ({{.*}} @"??_R0?AUU@@@8" to i8*), i32 1)
diff --git a/test/CodeGenCXX/microsoft-templ-uuidof.cpp b/test/CodeGenCXX/microsoft-templ-uuidof.cpp
index 74d6069bbacf..7d40a15c93a5 100644
--- a/test/CodeGenCXX/microsoft-templ-uuidof.cpp
+++ b/test/CodeGenCXX/microsoft-templ-uuidof.cpp
@@ -15,13 +15,15 @@ struct __declspec(uuid("{BBBBBBBB-BBBB-BBBB-BBBB-BBBBBBBBBBBB}")) X<B> {};
struct __declspec(uuid("{CCCCCCCC-CCCC-CCCC-CCCC-CCCCCCCCCCCC}")) C {};
+// CHECK-DAG: @_GUID_aaaaaaaa_aaaa_aaaa_aaaa_aaaaaaaaaaaa = linkonce_odr dso_local
+
const _GUID &xa = __uuidof(X<A>);
-// CHECK-DAG: @"\01?xa@@3ABU_GUID@@B" = {{.*}} @_GUID_aaaaaaaa_aaaa_aaaa_aaaa_aaaaaaaaaaaa
+// CHECK-DAG: @"?xa@@3ABU_GUID@@B" = {{.*}} @_GUID_aaaaaaaa_aaaa_aaaa_aaaa_aaaaaaaaaaaa
const _GUID &xb = __uuidof(X<B>);
-// CHECK-DAG: @"\01?xb@@3ABU_GUID@@B" = {{.*}} @_GUID_bbbbbbbb_bbbb_bbbb_bbbb_bbbbbbbbbbbb
+// CHECK-DAG: @"?xb@@3ABU_GUID@@B" = {{.*}} @_GUID_bbbbbbbb_bbbb_bbbb_bbbb_bbbbbbbbbbbb
const _GUID &xc = __uuidof(X<C>);
-// CHECK-DAG: @"\01?xc@@3ABU_GUID@@B" = {{.*}} @_GUID_cccccccc_cccc_cccc_cccc_cccccccccccc
+// CHECK-DAG: @"?xc@@3ABU_GUID@@B" = {{.*}} @_GUID_cccccccc_cccc_cccc_cccc_cccccccccccc
template <>
struct __declspec(uuid("{DDDDDDDD-DDDD-DDDD-DDDD-DDDDDDDDDDDD}")) X<C> {};
@@ -31,7 +33,7 @@ struct __declspec(uuid("{EEEEEEEE-EEEE-EEEE-EEEE-EEEEEEEEEEEE}")) Y {
};
const _GUID &xd = __uuidof(X<C>);
-// CHECK-DAG: @"\01?xd@@3ABU_GUID@@B" = {{.*}} @_GUID_dddddddd_dddd_dddd_dddd_dddddddddddd
+// CHECK-DAG: @"?xd@@3ABU_GUID@@B" = {{.*}} @_GUID_dddddddd_dddd_dddd_dddd_dddddddddddd
const _GUID &yd = __uuidof(Y<X<C> >);
-// CHECK-DAG: @"\01?yd@@3ABU_GUID@@B" = {{.*}} @_GUID_dddddddd_dddd_dddd_dddd_dddddddddddd
+// CHECK-DAG: @"?yd@@3ABU_GUID@@B" = {{.*}} @_GUID_dddddddd_dddd_dddd_dddd_dddddddddddd
diff --git a/test/CodeGenCXX/microsoft-uuidof.cpp b/test/CodeGenCXX/microsoft-uuidof.cpp
index 9b4ff68d9aa8..f8d2da737910 100644
--- a/test/CodeGenCXX/microsoft-uuidof.cpp
+++ b/test/CodeGenCXX/microsoft-uuidof.cpp
@@ -63,12 +63,12 @@ const GUID& zeroiid = __uuidof(0);
// CHECK: @_GUID_87654321_4321_4321_4321_ba0987654321 = linkonce_odr constant { i32, i16, i16, [8 x i8] } { i32 -2023406815, i16 17185, i16 17185, [8 x i8] c"C!\BA\09\87eC!" }, comdat
// The static initializer for thing.
-// CHECK-DEFINE-GUID: call void @llvm.memcpy.p0i8.p0i8.i32(i8* bitcast (%struct._GUID* @thing to i8*), i8* bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ac to i8*), i32 16, i32 4, i1 false)
-// CHECK-DEFINE-WRONG-GUID: call void @llvm.memcpy.p0i8.p0i8.i32(i8* bitcast (%struct._GUID* @thing to i8*), i8* bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ac to i8*), i32 4, i32 4, i1 false)
+// CHECK-DEFINE-GUID: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 bitcast (%struct._GUID* @thing to i8*), i8* align 4 bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ac to i8*), i32 16, i1 false)
+// CHECK-DEFINE-WRONG-GUID: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 bitcast (%struct._GUID* @thing to i8*), i8* align 4 bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ac to i8*), i32 4, i1 false)
// The static initializer for g.
-// CHECK-DEFINE-GUID: call void @llvm.memcpy.p0i8.p0i8.i32(i8* bitcast (%struct._GUID* @g to i8*), i8* bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab to i8*), i32 16, i32 4, i1 false)
-// CHECK-DEFINE-WRONG-GUID: call void @llvm.memcpy.p0i8.p0i8.i32(i8* bitcast (%struct._GUID* @g to i8*), i8* bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab to i8*), i32 4, i32 4, i1 false)
+// CHECK-DEFINE-GUID: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 bitcast (%struct._GUID* @g to i8*), i8* align 4 bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab to i8*), i32 16, i1 false)
+// CHECK-DEFINE-WRONG-GUID: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 bitcast (%struct._GUID* @g to i8*), i8* align 4 bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab to i8*), i32 4, i1 false)
#ifdef DEFINE_GUID
void fun() {
@@ -81,20 +81,20 @@ void fun() {
// CHECK-DEFINE-GUID: [[U1:%.+]] = bitcast %struct._GUID* %s1_1 to i8*
// CHECK-DEFINE-WRONG-GUID: [[U1:%.+]] = bitcast %struct._GUID* %s1_1 to i8*
- // CHECK-DEFINE-GUID: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[U1]], i8* bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab to i8*), i32 16, i32 4, i1 false)
- // CHECK-DEFINE-WRONG-GUID: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[U1]], i8* bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab to i8*), i32 4, i32 4, i1 false)
+ // CHECK-DEFINE-GUID: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 [[U1]], i8* align 4 bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab to i8*), i32 16, i1 false)
+ // CHECK-DEFINE-WRONG-GUID: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 [[U1]], i8* align 4 bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab to i8*), i32 4, i1 false)
GUID s1_1 = __uuidof(S1);
// CHECK-DEFINE-GUID: [[U2:%.+]] = bitcast %struct._GUID* %s1_2 to i8*
// CHECK-DEFINE-WRONG-GUID: [[U2:%.+]] = bitcast %struct._GUID* %s1_2 to i8*
- // CHECK-DEFINE-GUID: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[U2]], i8* bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab to i8*), i32 16, i32 4, i1 false)
- // CHECK-DEFINE-WRONG-GUID: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[U2]], i8* bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab to i8*), i32 4, i32 4, i1 false)
+ // CHECK-DEFINE-GUID: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 [[U2]], i8* align 4 bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab to i8*), i32 16, i1 false)
+ // CHECK-DEFINE-WRONG-GUID: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 [[U2]], i8* align 4 bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab to i8*), i32 4, i1 false)
GUID s1_2 = __uuidof(S1);
// CHECK-DEFINE-GUID: [[U3:%.+]] = bitcast %struct._GUID* %s1_3 to i8*
// CHECK-DEFINE-WRONG-GUID: [[U3:%.+]] = bitcast %struct._GUID* %s1_3 to i8*
- // CHECK-DEFINE-GUID: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[U3]], i8* bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab to i8*), i32 16, i32 4, i1 false)
- // CHECK-DEFINE-WRONG-GUID: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[U3]], i8* bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab to i8*), i32 4, i32 4, i1 false)
+ // CHECK-DEFINE-GUID: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 [[U3]], i8* align 4 bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab to i8*), i32 16, i1 false)
+ // CHECK-DEFINE-WRONG-GUID: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 [[U3]], i8* align 4 bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab to i8*), i32 4, i1 false)
GUID s1_3 = __uuidof(s1);
}
#endif
diff --git a/test/CodeGenCXX/mingw-new-abi.cpp b/test/CodeGenCXX/mingw-new-abi.cpp
index 2b05253b0985..fe98a1fb2f02 100644
--- a/test/CodeGenCXX/mingw-new-abi.cpp
+++ b/test/CodeGenCXX/mingw-new-abi.cpp
@@ -3,8 +3,8 @@
namespace test1 {
struct foo {
- // MINGW: declare x86_thiscallcc void @_ZN5test13foo1fEv
- // CYGWIN: declare void @_ZN5test13foo1fEv
+ // MINGW: declare dso_local x86_thiscallcc void @_ZN5test13foo1fEv
+ // CYGWIN: declare dso_local void @_ZN5test13foo1fEv
void f();
};
void g(foo *x) {
diff --git a/test/CodeGenCXX/mingw-w64-seh-exceptions.cpp b/test/CodeGenCXX/mingw-w64-seh-exceptions.cpp
index 046c4a815f46..f3c3dca30387 100644
--- a/test/CodeGenCXX/mingw-w64-seh-exceptions.cpp
+++ b/test/CodeGenCXX/mingw-w64-seh-exceptions.cpp
@@ -16,12 +16,12 @@ extern "C" void test() {
foo();
}
-// X64: define void @test()
+// X64: define dso_local void @test()
// X64-SAME: personality i8* bitcast (i32 (...)* @__gxx_personality_seh0 to i8*)
// X64: invoke void @foo()
// X64: landingpad { i8*, i32 }
-// X86: define void @test()
+// X86: define dso_local void @test()
// X86-SAME: personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
// X86: invoke void @foo()
// X86: landingpad { i8*, i32 }
diff --git a/test/CodeGenCXX/ms-eh-personality.cpp b/test/CodeGenCXX/ms-eh-personality.cpp
deleted file mode 100644
index 592ab69efaf2..000000000000
--- a/test/CodeGenCXX/ms-eh-personality.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-// RUN: %clang_cc1 -triple x86_64-windows-msvc -fexceptions -fcxx-exceptions %s -emit-llvm -o - | FileCheck %s --check-prefix=MSVC
-// RUN: %clang_cc1 -triple x86_64-windows-msvc -fexceptions -fcxx-exceptions -fsjlj-exceptions %s -emit-llvm -o - | FileCheck %s --check-prefix=SJLJ
-// RUN: %clang_cc1 -triple x86_64-windows-msvc -fexceptions -fcxx-exceptions -fseh-exceptions %s -emit-llvm -o - | FileCheck %s --check-prefix=MSVC
-// RUN: %clang_cc1 -triple x86_64-windows-msvc -fexceptions -fcxx-exceptions -fdwarf-exceptions %s -emit-llvm -o - | FileCheck %s --check-prefix=DWARF
-
-// MSVC: define void @f(){{.*}}@__CxxFrameHandler3
-// SJLJ: define void @f(){{.*}}@__gxx_personality_sj0
-// DWARF: define void @f(){{.*}}@__gxx_personality_v0
-
-struct Cleanup {
- Cleanup();
- ~Cleanup();
- int x = 0;
-};
-
-void g();
-extern "C" void f() {
- Cleanup c;
- g();
-}
diff --git a/test/CodeGenCXX/ms-inline-asm-return.cpp b/test/CodeGenCXX/ms-inline-asm-return.cpp
index 837f1b437a4c..4a7165ab075e 100644
--- a/test/CodeGenCXX/ms-inline-asm-return.cpp
+++ b/test/CodeGenCXX/ms-inline-asm-return.cpp
@@ -12,7 +12,7 @@ long long f_i64() {
mov edx, 1
}
}
-// CHECK-LABEL: define i64 @f_i64()
+// CHECK-LABEL: define dso_local i64 @f_i64()
// CHECK: %[[r:[^ ]*]] = call i64 asm sideeffect inteldialect "mov eax, $$1\0A\09mov edx, $$1", "=A,~{eax},{{.*}}"
// CHECK: ret i64 %[[r]]
@@ -22,7 +22,7 @@ int f_i32() {
mov edx, 1
}
}
-// CHECK-LABEL: define i32 @f_i32()
+// CHECK-LABEL: define dso_local i32 @f_i32()
// CHECK: %[[r:[^ ]*]] = call i32 asm sideeffect inteldialect "mov eax, $$1\0A\09mov edx, $$1", "={eax},~{eax},{{.*}}"
// CHECK: ret i32 %[[r]]
@@ -32,7 +32,7 @@ short f_i16() {
mov edx, 1
}
}
-// CHECK-LABEL: define signext i16 @f_i16()
+// CHECK-LABEL: define dso_local signext i16 @f_i16()
// CHECK: %[[r:[^ ]*]] = call i32 asm sideeffect inteldialect "mov eax, $$1\0A\09mov edx, $$1", "={eax},~{eax},{{.*}}"
// CHECK: %[[r_i16:[^ ]*]] = trunc i32 %[[r]] to i16
// CHECK: ret i16 %[[r_i16]]
@@ -43,7 +43,7 @@ char f_i8() {
mov edx, 1
}
}
-// CHECK-LABEL: define signext i8 @f_i8()
+// CHECK-LABEL: define dso_local signext i8 @f_i8()
// CHECK: %[[r:[^ ]*]] = call i32 asm sideeffect inteldialect "mov eax, $$1\0A\09mov edx, $$1", "={eax},~{eax},{{.*}}"
// CHECK: %[[r_i8:[^ ]*]] = trunc i32 %[[r]] to i8
// CHECK: ret i8 %[[r_i8]]
@@ -54,7 +54,7 @@ bool f_i1() {
mov edx, 1U
}
}
-// CHECK-LABEL: define zeroext i1 @f_i1()
+// CHECK-LABEL: define dso_local zeroext i1 @f_i1()
// CHECK: %[[r:[^ ]*]] = call i32 asm sideeffect inteldialect "mov eax, $$1\0A\09mov edx, $$1", "={eax},~{eax},{{.*}}"
// CHECK: %[[r_i8:[^ ]*]] = trunc i32 %[[r]] to i8
// CHECK: store i8 %[[r_i8]], i8* %{{.*}}
@@ -69,7 +69,7 @@ FourChars f_s4() {
mov eax, 0x01010101
}
}
-// CHECK-LABEL: define i32 @f_s4()
+// CHECK-LABEL: define dso_local i32 @f_s4()
// CHECK: %[[r:[^ ]*]] = call i32 asm sideeffect inteldialect "mov eax, $$16843009", "={eax},~{eax},{{.*}}"
// CHECK: store i32 %[[r]], i32* %{{.*}}
// CHECK: %[[r_i32:[^ ]*]] = load i32, i32* %{{.*}}
@@ -84,7 +84,7 @@ EightChars f_s8() {
mov edx, 01010101b
}
}
-// CHECK-LABEL: define i64 @f_s8()
+// CHECK-LABEL: define dso_local i64 @f_s8()
// CHECK: %[[r:[^ ]*]] = call i64 asm sideeffect inteldialect "mov eax, $$16843009\0A\09mov edx, $$85", "=A,~{eax},{{.*}}"
// CHECK: store i64 %[[r]], i64* %{{.*}}
// CHECK: %[[r_i64:[^ ]*]] = load i64, i64* %{{.*}}
@@ -95,6 +95,6 @@ EightChars f_s8() {
int main() {
__asm xor eax, eax
}
-// CHECK-LABEL: define i32 @main()
+// CHECK-LABEL: define dso_local i32 @main()
// CHECK: %[[r:[^ ]*]] = call i32 asm sideeffect inteldialect "xor eax, eax", "={eax},{{.*}}"
// CHECK: ret i32 %[[r]]
diff --git a/test/CodeGenCXX/ms-integer-static-data-members-exported.cpp b/test/CodeGenCXX/ms-integer-static-data-members-exported.cpp
index 78bb3a2b1afa..2537361383e6 100644
--- a/test/CodeGenCXX/ms-integer-static-data-members-exported.cpp
+++ b/test/CodeGenCXX/ms-integer-static-data-members-exported.cpp
@@ -17,6 +17,6 @@ struct __declspec(dllexport) S {
};
};
-// CHECK: @"\01?x@S@@2FB" = weak_odr dllexport constant i16 42, comdat, align 2
-// CHECK: @"\01?y@S@@2W4Enum@@B" = weak_odr dllexport constant i32 2, comdat, align 4
+// CHECK: @"?x@S@@2FB" = weak_odr dso_local dllexport constant i16 42, comdat, align 2
+// CHECK: @"?y@S@@2W4Enum@@B" = weak_odr dso_local dllexport constant i32 2, comdat, align 4
// CHECK-NOT: NonExported
diff --git a/test/CodeGenCXX/ms-integer-static-data-members.cpp b/test/CodeGenCXX/ms-integer-static-data-members.cpp
index b2bfc92d264c..98414350b451 100644
--- a/test/CodeGenCXX/ms-integer-static-data-members.cpp
+++ b/test/CodeGenCXX/ms-integer-static-data-members.cpp
@@ -33,20 +33,20 @@ const int S::OutOfLine_Def_Ref = 5;
// No initialization.
-// CHECK-DAG: @"\01?NoInit_Ref@S@@2HB" = external constant i32
+// CHECK-DAG: @"?NoInit_Ref@S@@2HB" = external dso_local constant i32
// Inline initialization, no real definiton, not referenced.
-// CHECK-NOT: @"\01?Inline_NotDef_NotRef@S@@2HB" = {{.*}} constant i32 5
+// CHECK-NOT: @"?Inline_NotDef_NotRef@S@@2HB" = {{.*}} constant i32 5
// Inline initialization, no real definiton, referenced.
-// CHECK-DAG: @"\01?Inline_NotDef_Ref@S@@2HB" = linkonce_odr constant i32 5, comdat, align 4
+// CHECK-DAG: @"?Inline_NotDef_Ref@S@@2HB" = linkonce_odr dso_local constant i32 5, comdat, align 4
// Inline initialization, real definiton, not referenced.
-// CHECK-NOT: @"\01?Inline_Def_NotRef@S@@2HB" = constant i32 5, align 4
+// CHECK-NOT: @"?Inline_Def_NotRef@S@@2HB" = dso_local constant i32 5, align 4
// Inline initialization, real definiton, referenced.
-// CHECK-DAG: @"\01?Inline_Def_Ref@S@@2HB" = linkonce_odr constant i32 5, comdat, align 4
+// CHECK-DAG: @"?Inline_Def_Ref@S@@2HB" = linkonce_odr dso_local constant i32 5, comdat, align 4
// Out-of-line initialization.
-// CHECK-DAG: @"\01?OutOfLine_Def_NotRef@S@@2HB" = constant i32 5, align 4
-// CHECK-DAG: @"\01?OutOfLine_Def_Ref@S@@2HB" = constant i32 5, align 4
+// CHECK-DAG: @"?OutOfLine_Def_NotRef@S@@2HB" = dso_local constant i32 5, align 4
+// CHECK-DAG: @"?OutOfLine_Def_Ref@S@@2HB" = dso_local constant i32 5, align 4
diff --git a/test/CodeGenCXX/ms-novtable.cpp b/test/CodeGenCXX/ms-novtable.cpp
index 8d54878d23f9..db0cf6886ca2 100644
--- a/test/CodeGenCXX/ms-novtable.cpp
+++ b/test/CodeGenCXX/ms-novtable.cpp
@@ -1,14 +1,14 @@
// RUN: %clang_cc1 -triple i386-pc-win32 %s -emit-llvm -fms-extensions -fms-compatibility -fno-rtti -o - | FileCheck %s
-// CHECK-NOT: @"\01??_7C@@6B@"
+// CHECK-NOT: @"??_7C@@6B@"
-// CHECK-DAG: @"\01??_7A2@@6B@"
+// CHECK-DAG: @"??_7A2@@6B@"
-// CHECK-DAG: @"\01??_7B2@@6B@"
+// CHECK-DAG: @"??_7B2@@6B@"
-// CHECK-NOT: @"\01??_7B1@@6B@"
+// CHECK-NOT: @"??_7B1@@6B@"
-// CHECK-NOT: @"\01??_7A1@@6B@"
+// CHECK-NOT: @"??_7A1@@6B@"
struct __declspec(novtable) A1 {
virtual void a();
diff --git a/test/CodeGenCXX/ms-property.cpp b/test/CodeGenCXX/ms-property.cpp
index 49e957b58e33..4f01528dda87 100644
--- a/test/CodeGenCXX/ms-property.cpp
+++ b/test/CodeGenCXX/ms-property.cpp
@@ -53,61 +53,61 @@ int main(int argc, char **argv) {
Test1 t(argc);
S *p1 = 0;
St<float> *p2 = 0;
- // CHECK: call i32 @"\01?GetX@S@@QEAAHHH@Z"(%class.S* %{{.+}}, i32 223, i32 11)
+ // CHECK: call i32 @"?GetX@S@@QEAAHHH@Z"(%class.S* %{{.+}}, i32 223, i32 11)
int j = p1->x[223][11];
// CHECK: [[J:%.+]] = load i32, i32* %
- // CHECK-NEXT: call void @"\01?PutX@S@@QEAAXHHH@Z"(%class.S* %{{.+}}, i32 23, i32 1, i32 [[J]])
+ // CHECK-NEXT: call void @"?PutX@S@@QEAAXHHH@Z"(%class.S* %{{.+}}, i32 23, i32 1, i32 [[J]])
p1->x[23][1] = j;
- // CHECK: call float @"\01?GetX@?$St@M@@QEAAMMM@Z"(%class.St* %{{.+}}, float 2.230000e+02, float 1.100000e+01)
+ // CHECK: call float @"?GetX@?$St@M@@QEAAMMM@Z"(%class.St* %{{.+}}, float 2.230000e+02, float 1.100000e+01)
float j1 = p2->x[223][11];
// CHECK: [[J1:%.+]] = load float, float* %
- // CHECK-NEXT: [[CALL:%.+]] = call float @"\01?PutX@?$St@M@@QEAAMMMM@Z"(%class.St* %{{.+}}, float 2.300000e+01, float 1.000000e+00, float [[J1]])
+ // CHECK-NEXT: [[CALL:%.+]] = call float @"?PutX@?$St@M@@QEAAMMMM@Z"(%class.St* %{{.+}}, float 2.300000e+01, float 1.000000e+00, float [[J1]])
// CHECK-NEXT: [[CONV:%.+]] = fptosi float [[CALL]] to i32
// CHECK-NEXT: store i32 [[CONV]], i32*
argc = p2->x[23][1] = j1;
- // CHECK: [[IDX:%.+]] = call i32 @"\01?idx@@YAHXZ"()
+ // CHECK: [[IDX:%.+]] = call i32 @"?idx@@YAHXZ"()
// CHECK-NEXT: [[CONV:%.+]] = sitofp i32 [[IDX]] to float
- // CHECK-NEXT: [[GET:%.+]] = call float @"\01?GetX@?$St@M@@QEAAMMM@Z"(%class.St* %{{.+}}, float [[CONV]], float 1.000000e+00)
+ // CHECK-NEXT: [[GET:%.+]] = call float @"?GetX@?$St@M@@QEAAMMM@Z"(%class.St* %{{.+}}, float [[CONV]], float 1.000000e+00)
// CHECK-NEXT: [[INC:%.+]] = fadd float [[GET]], 1.000000e+00
// CHECK-NEXT: [[CONV:%.+]] = sitofp i32 [[IDX]] to float
- // CHECK-NEXT: call float @"\01?PutX@?$St@M@@QEAAMMMM@Z"(%class.St* %{{.+}}, float [[CONV]], float 1.000000e+00, float [[INC]])
+ // CHECK-NEXT: call float @"?PutX@?$St@M@@QEAAMMMM@Z"(%class.St* %{{.+}}, float [[CONV]], float 1.000000e+00, float [[INC]])
++p2->x[idx()][1];
- // CHECK: call void @"\01??$foo@H@@YAXHH@Z"(i32 %{{.+}}, i32 %{{.+}})
+ // CHECK: call void @"??$foo@H@@YAXHH@Z"(i32 %{{.+}}, i32 %{{.+}})
foo(argc, (int)argv[0][0]);
// CHECK: [[P2:%.+]] = load %class.St*, %class.St** %
- // CHECK: [[T_X:%.+]] = call i32 @"\01?get_x@Test1@@QEBAHXZ"(%class.Test1* %{{.+}})
// CHECK: [[P1:%.+]] = load %class.S*, %class.S** %
- // CHECK: [[P1_X_22_33:%.+]] = call i32 @"\01?GetX@S@@QEAAHHH@Z"(%class.S* [[P1]], i32 22, i32 33)
+ // CHECK: [[P1_X_22_33:%.+]] = call i32 @"?GetX@S@@QEAAHHH@Z"(%class.S* [[P1]], i32 22, i32 33)
// CHECK: [[CAST:%.+]] = sitofp i32 [[P1_X_22_33]] to double
// CHECK: [[ARGC:%.+]] = load i32, i32* %
+ // CHECK: [[T_X:%.+]] = call i32 @"?get_x@Test1@@QEBAHXZ"(%class.Test1* %{{.+}})
// CHECK: [[CAST2:%.+]] = trunc i32 [[T_X]] to i8
- // CHECK: call void @"\01?PutY@?$St@M@@QEAAXDHN@Z"(%class.St* [[P2]], i8 [[CAST2]], i32 [[ARGC]], double [[CAST]])
+ // CHECK: call void @"?PutY@?$St@M@@QEAAXDHN@Z"(%class.St* [[P2]], i8 [[CAST2]], i32 [[ARGC]], double [[CAST]])
p2->y[t.X][argc] = p1->x[22][33];
// CHECK: [[P2_1:%.+]] = load %class.St*, %class.St**
// CHECK: [[P2_2:%.+]] = load %class.St*, %class.St**
// CHECK: [[P1:%.+]] = load %class.S*, %class.S**
// CHECK: [[ARGC:%.+]] = load i32, i32* %
- // CHECK: [[P1_X_ARGC_0:%.+]] = call i32 @"\01?GetX@S@@QEAAHHH@Z"(%class.S* [[P1]], i32 [[ARGC]], i32 0)
+ // CHECK: [[P1_X_ARGC_0:%.+]] = call i32 @"?GetX@S@@QEAAHHH@Z"(%class.S* [[P1]], i32 [[ARGC]], i32 0)
// CHECK: [[CAST:%.+]] = trunc i32 [[P1_X_ARGC_0]] to i8
- // CHECK: [[P2_Y_p1_X_ARGC_0_T:%.+]] = call i8 @"\01?GetY@?$St@M@@QEAADDVTest1@@@Z"(%class.St* [[P2_2]], i8 [[CAST]], %class.Test1* %{{.+}})
+ // CHECK: [[P2_Y_p1_X_ARGC_0_T:%.+]] = call i8 @"?GetY@?$St@M@@QEAADDVTest1@@@Z"(%class.St* [[P2_2]], i8 [[CAST]], %class.Test1* %{{.+}})
// CHECK: [[CAST:%.+]] = sitofp i8 [[P2_Y_p1_X_ARGC_0_T]] to float
// CHECK: [[J:%.+]] = load i32, i32* %
// CHECK: [[CAST1:%.+]] = sitofp i32 [[J]] to float
// CHECK: [[J:%.+]] = load i32, i32* %
// CHECK: [[CAST2:%.+]] = sitofp i32 [[J]] to float
- // CHECK: call float @"\01?PutX@?$St@M@@QEAAMMMM@Z"(%class.St* [[P2_1]], float [[CAST2]], float [[CAST1]], float [[CAST]])
+ // CHECK: call float @"?PutX@?$St@M@@QEAAMMMM@Z"(%class.St* [[P2_1]], float [[CAST2]], float [[CAST1]], float [[CAST]])
p2->x[j][j] = p2->y[p1->x[argc][0]][t];
- // CHECK: [[CALL:%.+]] = call %class.Test1* @"\01?GetTest1@Test1@@SAPEAV1@XZ"()
- // CHECK-NEXT: call i32 @"\01?get_x@Test1@@QEBAHXZ"(%class.Test1* [[CALL]])
+ // CHECK: [[CALL:%.+]] = call %class.Test1* @"?GetTest1@Test1@@SAPEAV1@XZ"()
+ // CHECK-NEXT: call i32 @"?get_x@Test1@@QEBAHXZ"(%class.Test1* [[CALL]])
return Test1::GetTest1()->X;
}
-// CHECK: define linkonce_odr void @"\01??$foo@H@@YAXHH@Z"(i32 %{{.+}}, i32 %{{.+}})
-// CHECK: call i32 @"\01?GetX@?$St@H@@QEAAHHH@Z"(%class.St{{.+}}* [[BAR:%.+]], i32 %{{.+}} i32 %{{.+}})
-// CHECK: call i32 @"\01?PutX@?$St@H@@QEAAHHHH@Z"(%class.St{{.+}}* [[BAR]], i32 %{{.+}}, i32 %{{.+}}, i32 %{{.+}})
-// CHECK: call i32 @"\01?GetX@?$St@H@@QEAAHHH@Z"(%class.St{{.+}}* [[BAR]], i32 %{{.+}} i32 %{{.+}})
-// CHECK: call void @"\01?PutY@?$St@H@@QEAAXDHN@Z"(%class.St{{.+}}* [[BAR]], i8 %{{.+}}, i32 %{{.+}}, double %{{.+}}
-// CHECK: call i32 @"\01?GetX@?$St@H@@QEAAHHH@Z"(%class.St{{.+}}* [[BAR]], i32 %{{.+}} i32 %{{.+}})
-// CHECK: call i8 @"\01?GetY@?$St@H@@QEAADDVTest1@@@Z"(%class.St{{.+}}* [[BAR]], i8 %{{.+}}, %class.Test1* %{{.+}})
-// CHECK: call i32 @"\01?PutX@?$St@H@@QEAAHHHH@Z"(%class.St{{.+}}* [[BAR]], i32 %{{.+}}, i32 %{{.+}}, i32 %{{.+}})
+// CHECK: define linkonce_odr dso_local void @"??$foo@H@@YAXHH@Z"(i32 %{{.+}}, i32 %{{.+}})
+// CHECK: call i32 @"?GetX@?$St@H@@QEAAHHH@Z"(%class.St{{.+}}* [[BAR:%.+]], i32 %{{.+}} i32 %{{.+}})
+// CHECK: call i32 @"?PutX@?$St@H@@QEAAHHHH@Z"(%class.St{{.+}}* [[BAR]], i32 %{{.+}}, i32 %{{.+}}, i32 %{{.+}})
+// CHECK: call i32 @"?GetX@?$St@H@@QEAAHHH@Z"(%class.St{{.+}}* [[BAR]], i32 %{{.+}} i32 %{{.+}})
+// CHECK: call void @"?PutY@?$St@H@@QEAAXDHN@Z"(%class.St{{.+}}* [[BAR]], i8 %{{.+}}, i32 %{{.+}}, double %{{.+}}
+// CHECK: call i32 @"?GetX@?$St@H@@QEAAHHH@Z"(%class.St{{.+}}* [[BAR]], i32 %{{.+}} i32 %{{.+}})
+// CHECK: call i8 @"?GetY@?$St@H@@QEAADDVTest1@@@Z"(%class.St{{.+}}* [[BAR]], i8 %{{.+}}, %class.Test1* %{{.+}})
+// CHECK: call i32 @"?PutX@?$St@H@@QEAAHHHH@Z"(%class.St{{.+}}* [[BAR]], i32 %{{.+}}, i32 %{{.+}}, i32 %{{.+}})
#endif //HEADER
diff --git a/test/CodeGenCXX/ms-thread_local.cpp b/test/CodeGenCXX/ms-thread_local.cpp
index dc7958d6eacf..76eba52b1634 100644
--- a/test/CodeGenCXX/ms-thread_local.cpp
+++ b/test/CodeGenCXX/ms-thread_local.cpp
@@ -5,18 +5,18 @@ struct A {
~A();
};
-// CHECK-DAG: $"\01??$a@X@@3UA@@A" = comdat any
-// CHECK-DAG: @"\01??$a@X@@3UA@@A" = linkonce_odr thread_local global %struct.A zeroinitializer, comdat, align 1
-// CHECK-DAG: @"\01??__E?$a@X@@YAXXZ$initializer$" = internal constant void ()* @"\01??__E?$a@X@@YAXXZ", section ".CRT$XDU", comdat($"\01??$a@X@@3UA@@A")
+// CHECK-DAG: $"??$a@X@@3UA@@A" = comdat any
+// CHECK-DAG: @"??$a@X@@3UA@@A" = linkonce_odr dso_local thread_local global %struct.A zeroinitializer, comdat, align 1
+// CHECK-DAG: @"??__E?$a@X@@YAXXZ$initializer$" = internal constant void ()* @"??__E?$a@X@@YAXXZ", section ".CRT$XDU", comdat($"??$a@X@@3UA@@A")
template <typename T>
thread_local A a = A();
-// CHECK-DAG: @"\01?b@@3UA@@A" = thread_local global %struct.A zeroinitializer, align 1
+// CHECK-DAG: @"?b@@3UA@@A" = dso_local thread_local global %struct.A zeroinitializer, align 1
// CHECK-DAG: @"__tls_init$initializer$" = internal constant void ()* @__tls_init, section ".CRT$XDU"
thread_local A b;
// CHECK-LABEL: define internal void @__tls_init()
-// CHECK: call void @"\01??__Eb@@YAXXZ"
+// CHECK: call void @"??__Eb@@YAXXZ"
thread_local A &c = b;
thread_local A &d = c;
diff --git a/test/CodeGenCXX/ms-thunks-unprototyped-return.cpp b/test/CodeGenCXX/ms-thunks-unprototyped-return.cpp
new file mode 100644
index 000000000000..ef39fd70607c
--- /dev/null
+++ b/test/CodeGenCXX/ms-thunks-unprototyped-return.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fno-rtti-data -triple x86_64-windows-msvc -emit-llvm-only %s -verify
+
+// Verify that we error out on this return adjusting thunk that we can't emit.
+
+struct Incomplete;
+
+struct A {
+ virtual A * clone(Incomplete p) = 0;
+};
+struct B : virtual A {
+ // expected-error@+1 2 {{cannot compile this return-adjusting thunk with incomplete parameter type yet}}
+ B * clone(Incomplete p) override;
+};
+struct C : B { int c; };
+C c;
diff --git a/test/CodeGenCXX/ms-thunks-unprototyped.cpp b/test/CodeGenCXX/ms-thunks-unprototyped.cpp
new file mode 100644
index 000000000000..0a232b98518e
--- /dev/null
+++ b/test/CodeGenCXX/ms-thunks-unprototyped.cpp
@@ -0,0 +1,73 @@
+// RUN: %clang_cc1 -fno-rtti-data -triple x86_64-windows-msvc -emit-llvm %s -o - | FileCheck %s
+
+// In this example, C does not override B::foo, but it needs to emit a thunk to
+// adjust for the relative difference of position between A-in-B and A-in-C.
+
+struct Incomplete;
+template <typename T>
+struct DoNotInstantiate {
+ typename T::does_not_exist field;
+};
+template <typename T>
+struct InstantiateLater;
+
+struct A {
+ virtual void foo(Incomplete p) = 0;
+ virtual void bar(DoNotInstantiate<int> p) = 0;
+ virtual int baz(InstantiateLater<int> p) = 0;
+};
+struct B : virtual A {
+ void foo(Incomplete p) override;
+ void bar(DoNotInstantiate<int> p) override;
+ inline int baz(InstantiateLater<int> p) override;
+};
+struct C : B { int c; };
+C c;
+
+// Do the same thing, but with an incomplete return type.
+struct B1 { virtual DoNotInstantiate<void> f() = 0; };
+struct B2 { virtual DoNotInstantiate<void> f() = 0; };
+struct S : B1, B2 { DoNotInstantiate<void> f() override; };
+S s;
+
+// CHECK: @"??_7S@@6BB2@@@" = linkonce_odr unnamed_addr constant
+// CHECK-SAME: void (%struct.S*, ...)* @"?f@S@@W7EAA?AU?$DoNotInstantiate@X@@XZ"
+
+// CHECK: @"??_7C@@6B@" = linkonce_odr unnamed_addr constant
+// CHECK-SAME: void (%struct.B*, ...)* @"?foo@B@@W7EAAXUIncomplete@@@Z"
+// CHECK-SAME: void (%struct.B*, ...)* @"?bar@B@@W7EAAXU?$DoNotInstantiate@H@@@Z"
+// CHECK-SAME: i32 (i8*, i32)* @"?baz@B@@W7EAAHU?$InstantiateLater@H@@@Z"
+
+
+// CHECK-LABEL: define linkonce_odr dso_local void @"?f@S@@W7EAA?AU?$DoNotInstantiate@X@@XZ"(%struct.S* %this, ...)
+// CHECK: %[[THIS_ADJ_i8:[^ ]*]] = getelementptr i8, i8* {{.*}}, i32 -8
+// CHECK: %[[THIS_ADJ:[^ ]*]] = bitcast i8* %[[THIS_ADJ_i8]] to %struct.S*
+// CHECK: musttail call void (%struct.S*, ...) {{.*}}@"?f@S@@UEAA?AU?$DoNotInstantiate@X@@XZ"
+// CHECK-SAME: (%struct.S* %[[THIS_ADJ]], ...)
+// CHECK: ret void
+
+// The thunks should have a -8 adjustment.
+
+// CHECK-LABEL: define linkonce_odr dso_local void @"?foo@B@@W7EAAXUIncomplete@@@Z"(%struct.B* %this, ...)
+// CHECK: %[[THIS_ADJ_i8:[^ ]*]] = getelementptr i8, i8* {{.*}}, i32 -8
+// CHECK: %[[THIS_ADJ:[^ ]*]] = bitcast i8* %[[THIS_ADJ_i8]] to %struct.B*
+// CHECK: musttail call void (%struct.B*, ...) {{.*}}@"?foo@B@@UEAAXUIncomplete@@@Z"
+// CHECK-SAME: (%struct.B* %[[THIS_ADJ]], ...)
+// CHECK-NEXT: ret void
+
+// CHECK-LABEL: define linkonce_odr dso_local void @"?bar@B@@W7EAAXU?$DoNotInstantiate@H@@@Z"(%struct.B* %this, ...)
+// CHECK: %[[THIS_ADJ_i8:[^ ]*]] = getelementptr i8, i8* {{.*}}, i32 -8
+// CHECK: %[[THIS_ADJ:[^ ]*]] = bitcast i8* %[[THIS_ADJ_i8]] to %struct.B*
+// CHECK: musttail call void (%struct.B*, ...) {{.*}}@"?bar@B@@UEAAXU?$DoNotInstantiate@H@@@Z"
+// CHECK-SAME: (%struct.B* %[[THIS_ADJ]], ...)
+// CHECK-NEXT: ret void
+
+// If we complete the definition later, things work out.
+template <typename T> struct InstantiateLater { T x; };
+inline int B::baz(InstantiateLater<int> p) { return p.x; }
+
+// CHECK-LABEL: define linkonce_odr dso_local i32 @"?baz@B@@W7EAAHU?$InstantiateLater@H@@@Z"(i8* %this.coerce, i32 %p.coerce)
+// CHECK: = getelementptr i8, i8* {{.*}}, i32 -8
+// CHECK: tail call i32 @"?baz@B@@UEAAHU?$InstantiateLater@H@@@Z"(i8* {{[^,]*}}, i32 {{.*}})
+
+// CHECK-LABEL: define linkonce_odr dso_local i32 @"?baz@B@@UEAAHU?$InstantiateLater@H@@@Z"(i8* %this.coerce, i32 %p.coerce)
diff --git a/test/CodeGenCXX/ms_wide_predefined_expr.cpp b/test/CodeGenCXX/ms_wide_predefined_expr.cpp
index 03c78d982f1c..bdfd1cd650ba 100644
--- a/test/CodeGenCXX/ms_wide_predefined_expr.cpp
+++ b/test/CodeGenCXX/ms_wide_predefined_expr.cpp
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 %s -fms-extensions -triple i686-pc-win32 -emit-llvm -o - | FileCheck %s
-// CHECK: @"\01??_C@_19DPFBEKIN@?$AAf?$AAu?$AAn?$AAc?$AA?$AA@" = linkonce_odr unnamed_addr constant [5 x i16] [i16 102, i16 117, i16 110, i16 99, i16 0], comdat, align 2
+// CHECK: @"??_C@_19DPFBEKIN@?$AAf?$AAu?$AAn?$AAc?$AA?$AA@" = linkonce_odr dso_local unnamed_addr constant [5 x i16] [i16 102, i16 117, i16 110, i16 99, i16 0], comdat, align 2
void wprint(const wchar_t*);
diff --git a/test/CodeGenCXX/msabi-blocks.cpp b/test/CodeGenCXX/msabi-blocks.cpp
index bee59d9ed535..02d0958f635c 100644
--- a/test/CodeGenCXX/msabi-blocks.cpp
+++ b/test/CodeGenCXX/msabi-blocks.cpp
@@ -7,25 +7,25 @@ void (^b)() = ^{
static int i = 0;
};
-// CHECK-X86-DAG: @"\01?i@?1??_block_invoke@@YAXPAU__block_literal@@@Z@4HA" ={{.*}} global i32 0
-// CHECK-X64-DAG: @"\01?i@?1??_block_invoke@@YAXPEAU__block_literal@@@Z@4HA" ={{.*}} global i32 0
+// CHECK-X86-DAG: @"?i@?1??_block_invoke@@YAXPAU__block_literal@@@Z@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"?i@?1??_block_invoke@@YAXPEAU__block_literal@@@Z@4HA" ={{.*}} global i32 0
void f(void) {
static int i = 0;
^{ static int i = e(); }();
-// CHECK-X86-DAG: @"\01?i@?1??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
-// CHECK-X64-DAG: @"\01?i@?1??_block_invoke_1@@YAXPEAU__block_literal_1@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X86-DAG: @"?i@?1??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"?i@?1??_block_invoke_1@@YAXPEAU__block_literal_1@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
^{ static int i = e(); }();
-// CHECK-X86-DAG: @"\01?i@?1??_block_invoke_2@@YAXPAU__block_literal_2@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
-// CHECK-X64-DAG: @"\01?i@?1??_block_invoke_2@@YAXPEAU__block_literal_2@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X86-DAG: @"?i@?1??_block_invoke_2@@YAXPAU__block_literal_2@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"?i@?1??_block_invoke_2@@YAXPEAU__block_literal_2@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
^{ ^{ static int i = e(); }(); }();
-// CHECK-X86-DAG: @"\01?i@?1??_block_invoke_3@@YAXPAU__block_literal_3@@@Z?1??_block_invoke_4@@YAXPAU__block_literal_4@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
-// CHECK-X64-DAG: @"\01?i@?1??_block_invoke_3@@YAXPEAU__block_literal_3@@@Z?1??_block_invoke_4@@YAXPEAU__block_literal_4@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X86-DAG: @"?i@?1??_block_invoke_3@@YAXPAU__block_literal_3@@@Z?1??_block_invoke_4@@YAXPAU__block_literal_4@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"?i@?1??_block_invoke_3@@YAXPEAU__block_literal_3@@@Z?1??_block_invoke_4@@YAXPEAU__block_literal_4@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
}
@@ -36,47 +36,47 @@ void g(void) {
template void g<char>(void);
-// CHECK-X86-DAG: @"\01?i@?2??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?2???$g@D@@YAXXZ@4HA" ={{.*}} global i32 0
-// CHECK-X64-DAG: @"\01?i@?2??_block_invoke_1@@YAXPEAU__block_literal_1@@@Z?2???$g@D@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X86-DAG: @"?i@?2??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?2???$g@D@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"?i@?2??_block_invoke_1@@YAXPEAU__block_literal_1@@@Z?2???$g@D@@YAXXZ@4HA" ={{.*}} global i32 0
template void g<int>(void);
-// CHECK-X86-DAG: @"\01?i@?2??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?2???$g@H@@YAXXZ@4HA" ={{.*}} global i32 0
-// CHECK-X64-DAG: @"\01?i@?2??_block_invoke_1@@YAXPEAU__block_literal_1@@@Z?2???$g@H@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X86-DAG: @"?i@?2??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?2???$g@H@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"?i@?2??_block_invoke_1@@YAXPEAU__block_literal_1@@@Z?2???$g@H@@YAXXZ@4HA" ={{.*}} global i32 0
inline void h(void) {
^{ static int i = e(); }();
}
-// CHECK-X86-DAG: @"\01?i@?2??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?2??h@@YAXXZ@4HA" ={{.*}} global i32 0
-// CHECK-X64-DAG: @"\01?i@?2??_block_invoke_1@@YAXPEAU__block_literal_1@@@Z?2??h@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X86-DAG: @"?i@?2??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?2??h@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"?i@?2??_block_invoke_1@@YAXPEAU__block_literal_1@@@Z?2??h@@YAXXZ@4HA" ={{.*}} global i32 0
struct s {
int i = ^{ static int i = e(); return ++i; }();
-// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1@0s@@YAXPAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
-// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1@0s@@YAXPEAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
+// CHECK-X86-DAG: @"?i@?0??_block_invoke_1@0s@@YAXPAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"?i@?0??_block_invoke_1@0s@@YAXPEAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
int j = ^{ static int i = e(); return ++i; }();
-// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1@j@s@@YAXPAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
-// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1@j@s@@YAXPEAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
+// CHECK-X86-DAG: @"?i@?0??_block_invoke_1@j@s@@YAXPAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"?i@?0??_block_invoke_1@j@s@@YAXPEAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
void m(int i = ^{ static int i = e(); return ++i; }(),
int j = ^{ static int i = e(); return ++i; }()) {}
-// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1_1@@YAXPAU__block_literal_1_1@@@Z?0??m@s@@QAEXHH@Z@4HA" ={{.*}} global i32 0
-// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1_2@@YAXPAU__block_literal_1_2@@@Z?0??m@s@@QAEXHH@Z@4HA" ={{.*}} global i32 0
-// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1_1@@YAXPEAU__block_literal_1_1@@@Z?0??m@s@@QEAAXHH@Z@4HA" ={{.*}} global i32 0
-// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1_2@@YAXPEAU__block_literal_1_2@@@Z?0??m@s@@QEAAXHH@Z@4HA" ={{.*}} global i32 0
+// CHECK-X86-DAG: @"?i@?0??_block_invoke_1_1@@YAXPAU__block_literal_1_1@@@Z?0??m@s@@QAEXHH@Z@4HA" ={{.*}} global i32 0
+// CHECK-X86-DAG: @"?i@?0??_block_invoke_1_2@@YAXPAU__block_literal_1_2@@@Z?0??m@s@@QAEXHH@Z@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"?i@?0??_block_invoke_1_1@@YAXPEAU__block_literal_1_1@@@Z?0??m@s@@QEAAXHH@Z@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"?i@?0??_block_invoke_1_2@@YAXPEAU__block_literal_1_2@@@Z?0??m@s@@QEAAXHH@Z@4HA" ={{.*}} global i32 0
void n(int = ^{ static int i = e(); return ++i; }(),
int = ^{ static int i = e(); return ++i; }()) {}
-// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1_1@@YAXPAU__block_literal_1_1@@@Z?0??n@s@@QAEXHH@Z@4HA" ={{.*}} global i32 0
-// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1_2@@YAXPAU__block_literal_1_2@@@Z?0??n@s@@QAEXHH@Z@4HA" ={{.*}} global i32 0
-// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1_1@@YAXPEAU__block_literal_1_1@@@Z?0??n@s@@QEAAXHH@Z@4HA" ={{.*}} global i32 0
-// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1_2@@YAXPEAU__block_literal_1_2@@@Z?0??n@s@@QEAAXHH@Z@4HA" ={{.*}} global i32 0
+// CHECK-X86-DAG: @"?i@?0??_block_invoke_1_1@@YAXPAU__block_literal_1_1@@@Z?0??n@s@@QAEXHH@Z@4HA" ={{.*}} global i32 0
+// CHECK-X86-DAG: @"?i@?0??_block_invoke_1_2@@YAXPAU__block_literal_1_2@@@Z?0??n@s@@QAEXHH@Z@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"?i@?0??_block_invoke_1_1@@YAXPEAU__block_literal_1_1@@@Z?0??n@s@@QEAAXHH@Z@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"?i@?0??_block_invoke_1_2@@YAXPEAU__block_literal_1_2@@@Z?0??n@s@@QEAAXHH@Z@4HA" ={{.*}} global i32 0
};
@@ -84,8 +84,8 @@ struct t {
struct u {
int i = ^{ static int i = e(); return ++i; }();
-// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1@0u@t@@YAXPAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
-// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1@0u@t@@YAXPEAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
+// CHECK-X86-DAG: @"?i@?0??_block_invoke_1@0u@t@@YAXPAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"?i@?0??_block_invoke_1@0u@t@@YAXPEAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
};
};
diff --git a/test/CodeGenCXX/msabi-swiftcall-cc.cpp b/test/CodeGenCXX/msabi-swiftcall-cc.cpp
new file mode 100644
index 000000000000..d8205ed192a5
--- /dev/null
+++ b/test/CodeGenCXX/msabi-swiftcall-cc.cpp
@@ -0,0 +1,67 @@
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fdeclspec -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -fdeclspec -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-64
+
+void __attribute__((__swiftcall__)) f() {}
+// CHECK-DAG: @"?f@@YSXXZ"
+// CHECK-64-DAG: @"?f@@YSXXZ"
+
+void (__attribute__((__swiftcall__)) *p)();
+// CHECK-DAG: @"?p@@3P6SXXZA"
+// CHECK-64-DAG: @"?p@@3P6SXXZEA
+
+namespace {
+void __attribute__((__swiftcall__)) __attribute__((__used__)) f() { }
+}
+// CHECK-DAG: @"?f@?A@@YSXXZ"
+// CHECK-64-DAG: @"?f@?A@@YSXXZ"
+
+namespace n {
+void __attribute__((__swiftcall__)) f() {}
+}
+// CHECK-DAG: @"?f@n@@YSXXZ"
+// CHECK-64-DAG: @"?f@n@@YSXXZ"
+
+struct __declspec(dllexport) S {
+ S(const S &) = delete;
+ S & operator=(const S &) = delete;
+ void __attribute__((__swiftcall__)) m() { }
+};
+// CHECK-DAG: @"?m@S@@QASXXZ"
+// CHECK-64-DAG: @"?m@S@@QEASXXZ"
+
+void f(void (__attribute__((__swiftcall__))())) {}
+// CHECK-DAG: @"?f@@YAXP6SXXZ@Z"
+// CHECK-64-DAG: @"?f@@YAXP6SXXZ@Z"
+
+void __attribute__((__preserve_most__)) g() {}
+// CHECK-DAG: @"?g@@YUXXZ"
+// CHECK-64-DAG: @"?g@@YUXXZ"
+
+void (__attribute__((__preserve_most__)) *q)();
+// CHECK-DAG: @"?q@@3P6UXXZA"
+// CHECK-64-DAG: @"?q@@3P6UXXZEA"
+
+namespace {
+void __attribute__((__preserve_most__)) __attribute__((__used__)) g() {}
+}
+// CHECK-DAG: @"?g@?A@@YUXXZ"
+// CHECK-64-DAG: @"?g@?A@@YUXXZ"
+
+namespace n {
+void __attribute__((__preserve_most__)) g() {}
+}
+// CHECK-DAG: @"?g@n@@YUXXZ"
+// CHECK-64-DAG: @"?g@n@@YUXXZ"
+
+struct __declspec(dllexport) T {
+ T(const T &) = delete;
+ T & operator=(const T &) = delete;
+ void __attribute__((__preserve_most__)) m() {}
+};
+// CHECK-DAG: @"?m@T@@QAUXXZ"
+// CHECK-64-DAG: @"?m@T@@QEAUXXZ"
+
+void g(void (__attribute__((__preserve_most__))())) {}
+// CHECK-DAG: @"?g@@YAXP6UXXZ@Z"
+// CHECK-64-DAG: @"?g@@YAXP6UXXZ@Z"
+
diff --git a/test/CodeGenCXX/naked.cpp b/test/CodeGenCXX/naked.cpp
index 34f22b3636b5..c6fe1330cbfd 100644
--- a/test/CodeGenCXX/naked.cpp
+++ b/test/CodeGenCXX/naked.cpp
@@ -7,7 +7,7 @@ public:
};
__attribute__((naked)) void TestNaked::NakedFunction() {
- // CHECK-LABEL: define {{(x86_thiscallcc )?}}void @
+ // CHECK-LABEL: define {{(dso_local )?}}{{(x86_thiscallcc )?}}void @
// CHECK: call void asm sideeffect
asm("");
}
diff --git a/test/CodeGenCXX/new-array-init.cpp b/test/CodeGenCXX/new-array-init.cpp
index ccc218e2b2dc..90cd600229b5 100644
--- a/test/CodeGenCXX/new-array-init.cpp
+++ b/test/CodeGenCXX/new-array-init.cpp
@@ -50,10 +50,10 @@ void string_nonconst(int n) {
// FIXME: Conditionally throw an exception rather than passing -1 to alloc function
// CHECK: select
// CHECK: %[[PTR:.*]] = call i8* @_Zna{{.}}(i{{32|64}}
- // CHECK: call void @llvm.memcpy{{.*}}(i8* %[[PTR]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[ABC4]], i32 0, i32 0), i32 4,
+ // CHECK: call void @llvm.memcpy{{.*}}(i8* align {{[0-9]+}} %[[PTR]], i8* align {{[0-9]+}} getelementptr inbounds ([4 x i8], [4 x i8]* @[[ABC4]], i32 0, i32 0), i32 4,
// CHECK: %[[REST:.*]] = getelementptr inbounds i8, i8* %[[PTR]], i32 4
// CHECK: %[[RESTSIZE:.*]] = sub {{.*}}, 4
- // CHECK: call void @llvm.memset{{.*}}(i8* %[[REST]], i8 0, i{{32|64}} %[[RESTSIZE]],
+ // CHECK: call void @llvm.memset{{.*}}(i8* align {{[0-9]+}} %[[REST]], i8 0, i{{32|64}} %[[RESTSIZE]],
new char[n] { "abc" };
}
@@ -61,7 +61,7 @@ void string_nonconst(int n) {
void string_exact() {
// CHECK-NOT: icmp
// CHECK: %[[PTR:.*]] = call i8* @_Zna{{.}}(i{{32|64}} 4)
- // CHECK: call void @llvm.memcpy{{.*}}(i8* %[[PTR]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[ABC4]], i32 0, i32 0), i32 4,
+ // CHECK: call void @llvm.memcpy{{.*}}(i8* align {{[0-9]+}} %[[PTR]], i8* align {{[0-9]+}} getelementptr inbounds ([4 x i8], [4 x i8]* @[[ABC4]], i32 0, i32 0), i32 4,
// CHECK-NOT: memset
new char[4] { "abc" };
}
@@ -71,7 +71,7 @@ void string_sufficient() {
// CHECK-NOT: icmp
// CHECK: %[[PTR:.*]] = call i8* @_Zna{{.}}(i{{32|64}} 15)
// FIXME: For very large arrays, it would be preferable to emit a small copy and a memset.
- // CHECK: call void @llvm.memcpy{{.*}}(i8* %[[PTR]], i8* getelementptr inbounds ([15 x i8], [15 x i8]* @[[ABC15]], i32 0, i32 0), i32 15,
+ // CHECK: call void @llvm.memcpy{{.*}}(i8* align {{[0-9]+}} %[[PTR]], i8* align {{[0-9]+}} getelementptr inbounds ([15 x i8], [15 x i8]* @[[ABC15]], i32 0, i32 0), i32 15,
// CHECK-NOT: memset
new char[15] { "abc" };
}
@@ -113,7 +113,7 @@ void aggr_sufficient(int n) {
// CHECK: %[[PTR2:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR1]], i32 1{{$}}
// CHECK: %[[REMAIN:.*]] = sub i32 {{.*}}, 16
// CHECK: %[[MEM:.*]] = bitcast %[[AGGR]]* %[[PTR2]] to i8*
- // CHECK: call void @llvm.memset{{.*}}(i8* %[[MEM]], i8 0, i32 %[[REMAIN]],
+ // CHECK: call void @llvm.memset{{.*}}(i8* align {{[0-9]+}} %[[MEM]], i8 0, i32 %[[REMAIN]],
struct Aggr { int a, b; };
new Aggr[n] { 1, 2, 3 };
}
diff --git a/test/CodeGenCXX/no-opt-volatile-memcpy.cpp b/test/CodeGenCXX/no-opt-volatile-memcpy.cpp
index a061daaf2636..a51421cdb3df 100644
--- a/test/CodeGenCXX/no-opt-volatile-memcpy.cpp
+++ b/test/CodeGenCXX/no-opt-volatile-memcpy.cpp
@@ -18,10 +18,10 @@ void foo (void) {
// CHECK: %[[LS:.*]] = alloca %struct.s, align 4
// CHECK-NEXT: %[[ZERO:.*]] = bitcast %struct.s* %[[LS]] to i8*
// CHECK-NEXT: %[[ONE:.*]] = bitcast %struct.s* %[[LS]] to i8*
-// CHECK-NEXT: call void @llvm.memcpy.{{.*}}(i8* %[[ZERO]], i8* %[[ONE]], i64 132, i32 4, i1 true)
-// CHECK-NEXT: call void @llvm.memcpy.{{.*}}(i8* getelementptr inbounds (%struct.s, %struct.s* @gs, i32 0, i32 0, i32 0), i8* getelementptr inbounds (%struct.s, %struct.s* @gs, i32 0, i32 0, i32 0), i64 132, i32 4, i1 true)
+// CHECK-NEXT: call void @llvm.memcpy.{{.*}}(i8* align 4 %[[ZERO]], i8* align 4 %[[ONE]], i64 132, i1 true)
+// CHECK-NEXT: call void @llvm.memcpy.{{.*}}(i8* align 4 getelementptr inbounds (%struct.s, %struct.s* @gs, i32 0, i32 0, i32 0), i8* align 4 getelementptr inbounds (%struct.s, %struct.s* @gs, i32 0, i32 0, i32 0), i64 132, i1 true)
// CHECK-NEXT: %[[TWO:.*]] = bitcast %struct.s* %[[LS]] to i8*
-// CHECK-NEXT: call void @llvm.memcpy.{{.*}}(i8* %[[TWO]], i8* getelementptr inbounds (%struct.s, %struct.s* @gs, i32 0, i32 0, i32 0), i64 132, i32 4, i1 true)
+// CHECK-NEXT: call void @llvm.memcpy.{{.*}}(i8* align 4 %[[TWO]], i8* align 4 getelementptr inbounds (%struct.s, %struct.s* @gs, i32 0, i32 0, i32 0), i64 132, i1 true)
struct s1 {
@@ -35,8 +35,8 @@ void fee (void) {
s.y = gs;
}
// CHECK-LABEL: define void @_Z3feev()
-// CHECK: call void @llvm.memcpy.{{.*}}(i8* getelementptr inbounds (%struct.s1, %struct.s1* @s, i32 0, i32 0, i32 0, i32 0), i8* getelementptr inbounds (%struct.s1, %struct.s1* @s, i32 0, i32 0, i32 0, i32 0), i64 132, i32 4, i1 true)
-// CHECK-NEXT: call void @llvm.memcpy.{{.*}}(i8* getelementptr inbounds (%struct.s1, %struct.s1* @s, i32 0, i32 0, i32 0, i32 0), i8* getelementptr inbounds (%struct.s, %struct.s* @gs, i32 0, i32 0, i32 0), i64 132, i32 4, i1 true)
+// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 4 getelementptr inbounds (%struct.s1, %struct.s1* @s, i32 0, i32 0, i32 0, i32 0), i8* align 4 getelementptr inbounds (%struct.s1, %struct.s1* @s, i32 0, i32 0, i32 0, i32 0), i64 132, i1 true)
+// CHECK-NEXT: call void @llvm.memcpy.{{.*}}(i8* align 4 getelementptr inbounds (%struct.s1, %struct.s1* @s, i32 0, i32 0, i32 0, i32 0), i8* align 4 getelementptr inbounds (%struct.s, %struct.s* @gs, i32 0, i32 0, i32 0), i64 132, i1 true)
struct d : s1 {
};
@@ -47,4 +47,4 @@ void gorf(void) {
gd = gd;
}
// CHECK-LABEL: define void @_Z4gorfv()
-// CHECK: call void @llvm.memcpy.{{.*}}(i8* getelementptr inbounds (%struct.d, %struct.d* @gd, i32 0, i32 0, i32 0, i32 0, i32 0), i8* getelementptr inbounds (%struct.d, %struct.d* @gd, i32 0, i32 0, i32 0, i32 0, i32 0), i64 132, i32 4, i1 true)
+// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 4 getelementptr inbounds (%struct.d, %struct.d* @gd, i32 0, i32 0, i32 0, i32 0, i32 0), i8* align 4 getelementptr inbounds (%struct.d, %struct.d* @gd, i32 0, i32 0, i32 0, i32 0, i32 0), i64 132, i1 true)
diff --git a/test/CodeGenCXX/optnone-pragma-optimize-off.cpp b/test/CodeGenCXX/optnone-pragma-optimize-off.cpp
new file mode 100644
index 000000000000..d750c4c2848c
--- /dev/null
+++ b/test/CodeGenCXX/optnone-pragma-optimize-off.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 %s -triple %itanium_abi_triple -O1 -disable-llvm-passes -emit-llvm -o - | FileCheck %s
+
+// Test the attributes for the lambda function contains 'optnone' as result of
+// the _Pragma("clang optimize off").
+
+_Pragma("clang optimize off")
+
+void foo(int p) {
+ auto lambda = [&p]() { ++p; };
+ lambda();
+ // CHECK: define {{.*}} @"_ZZ3fooiENK3$_0clEv"({{.*}}) #[[LAMBDA_ATR:[0-9]+]]
+}
+
+_Pragma("clang optimize on")
+
+// CHECK: attributes #[[LAMBDA_ATR]] = { {{.*}} optnone {{.*}} } \ No newline at end of file
diff --git a/test/CodeGenCXX/override-bit-field-layout.cpp b/test/CodeGenCXX/override-bit-field-layout.cpp
new file mode 100644
index 000000000000..e84fcb0f450d
--- /dev/null
+++ b/test/CodeGenCXX/override-bit-field-layout.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -w -fdump-record-layouts-simple -foverride-record-layout=%S/Inputs/override-bit-field-layout.layout %s | FileCheck %s
+
+// CHECK: Type: struct S1
+// CHECK: FieldOffsets: [0, 11]
+struct S1 {
+ short a : 3;
+ short b : 5;
+};
+
+// CHECK: Type: struct S2
+// CHECK: FieldOffsets: [64]
+struct S2 {
+ virtual ~S2() = default;
+ short a : 3;
+};
+
+void use_structs() {
+ S1 s1s[sizeof(S1)];
+ S2 s2s[sizeof(S2)];
+}
diff --git a/test/CodeGenCXX/personality.cpp b/test/CodeGenCXX/personality.cpp
new file mode 100644
index 000000000000..ce4bad370d91
--- /dev/null
+++ b/test/CodeGenCXX/personality.cpp
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNU
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fdwarf-exceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNU-DWARF
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fseh-exceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNU-SEH
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fsjlj-exceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNU-SJLJ
+
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -D __SEH_EXCEPTIONS__ -fms-extensions -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-SEH-X86
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -D __SEH_EXCEPTIONS__ -fms-extensions -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-SEH-X64
+
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNU
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fdwarf-exceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNU-DWARF
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fseh-exceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNU-SEH
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fsjlj-exceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNU-SJLJ
+
+extern void g();
+
+// CHECK-GNU: personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+// CHECK-GNU-DWARF: personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+// CHECK-GNU-SEH: personality i8* bitcast (i32 (...)* @__gxx_personality_seh0 to i8*)
+// CHECK-GNU-SJLJ: personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*)
+
+// CHECK-WIN: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
+
+void f() {
+ try {
+ g();
+ } catch (...) {
+ }
+}
+
+#if defined(__SEH_EXCEPTIONS__)
+// CHECK-WIN-SEH-X86: personality i8* bitcast (i32 (...)* @_except_handler3 to i8*)
+// CHECK-WIN-SEH-X64: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
+
+void h(void) {
+ __try {
+ g();
+ } __finally {
+ }
+}
+#endif
+
diff --git a/test/CodeGenCXX/pod-member-memcpys.cpp b/test/CodeGenCXX/pod-member-memcpys.cpp
index 97d203fde2e0..9facb8ad507c 100644
--- a/test/CodeGenCXX/pod-member-memcpys.cpp
+++ b/test/CodeGenCXX/pod-member-memcpys.cpp
@@ -116,59 +116,59 @@ CALL_AO(PackedMembers)
// Basic copy-assignment:
// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.Basic* @_ZN5BasicaSERKS_(%struct.Basic* %this, %struct.Basic* dereferenceable({{[0-9]+}}))
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 4 {{.*}} align 4 {{.*}}i64 16, i1 {{.*}})
// CHECK: call dereferenceable({{[0-9]+}}) %struct.NonPOD* @_ZN6NonPODaSERKS_
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 4 {{.*}} align 4 {{.*}}i64 16, i1 {{.*}})
// CHECK: ret %struct.Basic*
// PODMember copy-assignment:
// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.PODMember* @_ZN9PODMemberaSERKS_(%struct.PODMember* %this, %struct.PODMember* dereferenceable({{[0-9]+}}))
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 32, i32 4{{.*}})
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 4 {{.*}} align 4 {{.*}}i64 32, i1 {{.*}})
// CHECK: call dereferenceable({{[0-9]+}}) %struct.NonPOD* @_ZN6NonPODaSERKS_
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 4 {{.*}} align 4 {{.*}}i64 16, i1 {{.*}})
// CHECK: ret %struct.PODMember*
// PODLikeMember copy-assignment:
// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.PODLikeMember* @_ZN13PODLikeMemberaSERKS_(%struct.PODLikeMember* %this, %struct.PODLikeMember* dereferenceable({{[0-9]+}}))
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 32, i32 4{{.*}})
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 4 {{.*}} align 4 {{.*}}i64 32, i1 {{.*}})
// CHECK: call dereferenceable({{[0-9]+}}) %struct.NonPOD* @_ZN6NonPODaSERKS_
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 4 {{.*}} align 4 {{.*}}i64 16, i1 {{.*}})
// CHECK: ret %struct.PODLikeMember*
// ArrayMember copy-assignment:
// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.ArrayMember* @_ZN11ArrayMemberaSERKS_(%struct.ArrayMember* %this, %struct.ArrayMember* dereferenceable({{[0-9]+}}))
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 64, i32 4{{.*}})
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 4 {{.*}} align 4 {{.*}}i64 64, i1 {{.*}})
// CHECK: call dereferenceable({{[0-9]+}}) %struct.NonPOD* @_ZN6NonPODaSERKS_
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 64, i32 4{{.*}})
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 4 {{.*}} align 4 {{.*}}i64 64, i1 {{.*}})
// CHECK: ret %struct.ArrayMember*
// VolatileMember copy-assignment:
// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.VolatileMember* @_ZN14VolatileMemberaSERKS_(%struct.VolatileMember* %this, %struct.VolatileMember* dereferenceable({{[0-9]+}}))
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 4 {{.*}} align 4 {{.*}}i64 16, i1 {{.*}})
// CHECK: load volatile i32, i32* {{.*}}, align 4
// CHECK: store volatile i32 {{.*}}, align 4
// CHECK: call dereferenceable({{[0-9]+}}) %struct.NonPOD* @_ZN6NonPODaSERKS_
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 4 {{.*}} align 4 {{.*}}i64 16, i1 {{.*}})
// CHECK: ret %struct.VolatileMember*
// BitfieldMember copy-assignment:
// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.BitfieldMember* @_ZN14BitfieldMemberaSERKS_(%struct.BitfieldMember* %this, %struct.BitfieldMember* dereferenceable({{[0-9]+}}))
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 4 {{.*}} align 4 {{.*}}i64 16, i1 {{.*}})
// CHECK: call dereferenceable({{[0-9]+}}) %struct.NonPOD* @_ZN6NonPODaSERKS_
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 3, i32 1{{.*}})
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 1 {{.*}} align 1 {{.*}}i64 3, i1 {{.*}})
// CHECK: ret %struct.BitfieldMember*
// InnerClass copy-assignment:
// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.InnerClassMember* @_ZN16InnerClassMemberaSERKS_(%struct.InnerClassMember* %this, %struct.InnerClassMember* dereferenceable({{[0-9]+}}))
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 32, i32 4{{.*}})
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 4 {{.*}} align 4 {{.*}}i64 32, i1 {{.*}})
// CHECK: call dereferenceable({{[0-9]+}}) %struct.NonPOD* @_ZN6NonPODaSERKS_
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 4 {{.*}} align 4 {{.*}}i64 16, i1 {{.*}})
// CHECK: ret %struct.InnerClassMember*
// PackedMembers copy-assignment:
// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.PackedMembers* @_ZN13PackedMembersaSERKS_(%struct.PackedMembers* %this, %struct.PackedMembers* dereferenceable({{[0-9]+}}))
// CHECK: call dereferenceable({{[0-9]+}}) %struct.NonPOD* @_ZN6NonPODaSERKS_
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 1{{.*}})
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 1 {{.*}} align 1 {{.*}}i64 16, i1 {{.*}})
// CHECK: ret %struct.PackedMembers*
// COPY-CONSTRUCTORS:
@@ -183,70 +183,70 @@ CALL_CC(PackedMembers)
// PackedMembers copy-assignment:
// CHECK-LABEL: define linkonce_odr void @_ZN13PackedMembersC2ERKS_(%struct.PackedMembers* %this, %struct.PackedMembers* dereferenceable({{[0-9]+}}))
// CHECK: call void @_ZN6NonPODC1ERKS_
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 1{{.*}})
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 1 {{.*}} align 1 {{.*}}i64 16, i1 {{.*}})
// CHECK: ret void
CALL_CC(BitfieldMember2)
// BitfieldMember2 copy-constructor:
// CHECK-2-LABEL: define linkonce_odr void @_ZN15BitfieldMember2C2ERKS_(%struct.BitfieldMember2* %this, %struct.BitfieldMember2* dereferenceable({{[0-9]+}}))
-// CHECK-2: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4, i1 false)
+// CHECK-2: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 4 {{.*}} align 4 {{.*}}i64 16, i1 false)
// CHECK-2: call void @_ZN6NonPODC1ERKS_
// CHECK-2: ret void
CALL_CC(BitfieldMember3)
// BitfieldMember3 copy-constructor:
// CHECK-LABEL: define linkonce_odr void @_ZN15BitfieldMember3C2ERKS_(%struct.BitfieldMember3* %this, %struct.BitfieldMember3* dereferenceable({{[0-9]+}}))
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 8, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 8 {{.*}} align 8 {{.*}}i64 8, i1 false)
// CHECK: ret void
CALL_CC(ReferenceMember)
// ReferenceMember copy-constructor:
// CHECK-LABEL: define linkonce_odr void @_ZN15ReferenceMemberC2ERKS_(%struct.ReferenceMember* %this, %struct.ReferenceMember* dereferenceable({{[0-9]+}}))
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 8{{.*}})
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 8 {{.*}} align 8 {{.*}}i64 16, i1 {{.*}})
// CHECK: call void @_ZN6NonPODC1ERKS_
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 8{{.*}})
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 8 {{.*}} align 8 {{.*}}i64 16, i1 {{.*}})
// CHECK: ret void
CALL_CC(InnerClassMember)
// InnerClass copy-constructor:
// CHECK-LABEL: define linkonce_odr void @_ZN16InnerClassMemberC2ERKS_(%struct.InnerClassMember* %this, %struct.InnerClassMember* dereferenceable({{[0-9]+}}))
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 32, i32 4{{.*}})
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 4 {{.*}} align 4 {{.*}}i64 32, i1 {{.*}})
// CHECK: call void @_ZN6NonPODC1ERKS_
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 4 {{.*}} align 4 {{.*}}i64 16, i1 {{.*}})
// CHECK: ret void
CALL_CC(BitfieldMember)
// BitfieldMember copy-constructor:
// CHECK-LABEL: define linkonce_odr void @_ZN14BitfieldMemberC2ERKS_(%struct.BitfieldMember* %this, %struct.BitfieldMember* dereferenceable({{[0-9]+}}))
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 4 {{.*}} align 4 {{.*}}i64 16, i1 {{.*}})
// CHECK: call void @_ZN6NonPODC1ERKS_
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 3, i32 1{{.*}})
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 1 {{.*}} align 1 {{.*}}i64 3, i1 {{.*}})
// CHECK: ret void
CALL_CC(VolatileMember)
// VolatileMember copy-constructor:
// CHECK-LABEL: define linkonce_odr void @_ZN14VolatileMemberC2ERKS_(%struct.VolatileMember* %this, %struct.VolatileMember* dereferenceable({{[0-9]+}}))
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 4 {{.*}} align 4 {{.*}}i64 16, i1 {{.*}})
// CHECK: load volatile i32, i32* {{.*}}, align 4
// CHECK: store volatile i32 {{.*}}, align 4
// CHECK: call void @_ZN6NonPODC1ERKS_
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 4 {{.*}} align 4 {{.*}}i64 16, i1 {{.*}})
// CHECK: ret void
CALL_CC(ArrayMember)
// ArrayMember copy-constructor:
// CHECK-LABEL: define linkonce_odr void @_ZN11ArrayMemberC2ERKS_(%struct.ArrayMember* %this, %struct.ArrayMember* dereferenceable({{[0-9]+}}))
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 64, i32 4{{.*}})
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 4 {{.*}} align 4 {{.*}}i64 64, i1 {{.*}})
// CHECK: call void @_ZN6NonPODC1ERKS_
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 64, i32 4{{.*}})
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 4 {{.*}} align 4 {{.*}}i64 64, i1 {{.*}})
// CHECK: ret void
CALL_CC(PODLikeMember)
// PODLikeMember copy-constructor:
// CHECK-LABEL: define linkonce_odr void @_ZN13PODLikeMemberC2ERKS_(%struct.PODLikeMember* %this, %struct.PODLikeMember* dereferenceable({{[0-9]+}}))
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 32, i32 4{{.*}})
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 4 {{.*}} align 4 {{.*}}i64 32, i1 {{.*}})
// CHECK: invoke void @_ZN6NonPODC1ERKS_
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 4 {{.*}} align 4 {{.*}}i64 16, i1 {{.*}})
// CHECK: ret void
// CHECK: landingpad
// CHECK: invoke void @_ZN7PODLikeD1Ev
@@ -254,15 +254,15 @@ CALL_CC(PODLikeMember)
CALL_CC(PODMember)
// PODMember copy-constructor:
// CHECK-LABEL: define linkonce_odr void @_ZN9PODMemberC2ERKS_(%struct.PODMember* %this, %struct.PODMember* dereferenceable({{[0-9]+}}))
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 32, i32 4{{.*}})
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 4 {{.*}} align 4 {{.*}}i64 32, i1 {{.*}})
// CHECK: call void @_ZN6NonPODC1ERKS_
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 4 {{.*}} align 4 {{.*}}i64 16, i1 {{.*}})
// CHECK: ret void
CALL_CC(Basic)
// Basic copy-constructor:
// CHECK-LABEL: define linkonce_odr void @_ZN5BasicC2ERKS_(%struct.Basic* %this, %struct.Basic* dereferenceable({{[0-9]+}}))
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 4 {{.*}} align 4 {{.*}}i64 16, i1 {{.*}})
// CHECK: call void @_ZN6NonPODC1ERKS_
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 4 {{.*}} align 4 {{.*}}i64 16, i1 {{.*}})
// CHECK: ret void
diff --git a/test/CodeGenCXX/pr20719.cpp b/test/CodeGenCXX/pr20719.cpp
index 1c3b21b0b84e..79fdd7416024 100644
--- a/test/CodeGenCXX/pr20719.cpp
+++ b/test/CodeGenCXX/pr20719.cpp
@@ -2,8 +2,8 @@
// Make sure that we emit H's constructor twice: once with the first lambda
// inside of 'lep' and again with the second lambda inside of 'lep'.
-// CHECK-DAG: @"\01??0?$H@V<lambda_1>@?0???$lep@X@@YAXXZ@@@QAE@XZ"
-// CHECK-DAG: @"\01??0?$H@V<lambda_2>@?0???$lep@X@@YAXXZ@@@QAE@XZ"
+// CHECK-DAG: @"??0?$H@V<lambda_1>@?0???$lep@X@@YAXXZ@@@QAE@XZ"
+// CHECK-DAG: @"??0?$H@V<lambda_2>@?0???$lep@X@@YAXXZ@@@QAE@XZ"
template <typename>
struct H {
diff --git a/test/CodeGenCXX/pr20897.cpp b/test/CodeGenCXX/pr20897.cpp
index 9a7fdb999ba4..73995fc27155 100644
--- a/test/CodeGenCXX/pr20897.cpp
+++ b/test/CodeGenCXX/pr20897.cpp
@@ -3,13 +3,13 @@ struct Base {};
// __declspec(dllexport) causes us to export the implicit constructor.
struct __declspec(dllexport) Derived : virtual Base {
-// CHECK-LABEL: define weak_odr dllexport x86_thiscallcc %struct.Derived* @"\01??0Derived@@QAE@ABU0@@Z"
+// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc %struct.Derived* @"??0Derived@@QAE@ABU0@@Z"
// CHECK: %[[this:.*]] = load %struct.Derived*, %struct.Derived** {{.*}}
// CHECK-NEXT: store %struct.Derived* %[[this]], %struct.Derived** %[[retval:.*]]
// CHECK: %[[dest_a_gep:.*]] = getelementptr inbounds %struct.Derived, %struct.Derived* %[[this]], i32 0, i32 1
// CHECK-NEXT: %[[src_load:.*]] = load %struct.Derived*, %struct.Derived** {{.*}}
// CHECK-NEXT: %[[src_a_gep:.*]] = getelementptr inbounds %struct.Derived, %struct.Derived* %[[src_load:.*]], i32 0, i32 1
-// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %[[dest_a_gep]], i8* %[[src_a_gep]], i64 1, i32 4, i1 false)
+// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %[[dest_a_gep]], i8* align 4 %[[src_a_gep]], i64 1, i1 false)
// CHECK-NEXT: %[[dest_this:.*]] = load %struct.Derived*, %struct.Derived** %[[retval]]
// CHECK-NEXT: ret %struct.Derived* %[[dest_this]]
bool a : 1;
@@ -18,7 +18,7 @@ struct __declspec(dllexport) Derived : virtual Base {
// __declspec(dllexport) causes us to export the implicit copy constructor.
struct __declspec(dllexport) Derived2 : virtual Base {
-// CHECK-LABEL: define weak_odr dllexport x86_thiscallcc %struct.Derived2* @"\01??0Derived2@@QAE@ABU0@@Z"
+// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc %struct.Derived2* @"??0Derived2@@QAE@ABU0@@Z"
// CHECK: %[[this:.*]] = load %struct.Derived2*, %struct.Derived2** {{.*}}
// CHECK-NEXT: store %struct.Derived2* %[[this]], %struct.Derived2** %[[retval:.*]]
// CHECK: %[[dest_a_gep:.*]] = getelementptr inbounds %struct.Derived2, %struct.Derived2* %[[this]], i32 0, i32 1
@@ -26,7 +26,7 @@ struct __declspec(dllexport) Derived2 : virtual Base {
// CHECK-NEXT: %[[src_a_gep:.*]] = getelementptr inbounds %struct.Derived2, %struct.Derived2* %[[src_load:.*]], i32 0, i32 1
// CHECK-NEXT: %[[dest_a_bitcast:.*]] = bitcast [1 x i32]* %[[dest_a_gep]] to i8*
// CHECK-NEXT: %[[src_a_bitcast:.*]] = bitcast [1 x i32]* %[[src_a_gep]] to i8*
-// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %[[dest_a_bitcast]], i8* %[[src_a_bitcast]], i32 4, i32 4, i1 false)
+// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %[[dest_a_bitcast]], i8* align 4 %[[src_a_bitcast]], i32 4, i1 false)
// CHECK-NEXT: %[[dest_this:.*]] = load %struct.Derived2*, %struct.Derived2** %[[retval]]
// CHECK-NEXT: ret %struct.Derived2* %[[dest_this]]
int Array[1];
diff --git a/test/CodeGenCXX/pr27030.cpp b/test/CodeGenCXX/pr27030.cpp
index 5c24051d7a2b..ce83c8979891 100644
--- a/test/CodeGenCXX/pr27030.cpp
+++ b/test/CodeGenCXX/pr27030.cpp
@@ -5,7 +5,7 @@ extern "C" {
extern int B::*a;
void test1() { (int A::*)(a); }
}
-// CHECK-LABEL: define void @test1(
+// CHECK-LABEL: define dso_local void @test1(
// CHECK: %[[load:.*]] = load i32, i32* @a
// CHECK: %[[memptr_cmp:.*]] = icmp ne i32 %[[load]], -1
// CHECK: br i1 %[[memptr_cmp]]
diff --git a/test/CodeGenCXX/pr28360.cpp b/test/CodeGenCXX/pr28360.cpp
index 5d7e1ae0c1fd..6bf2ea78b938 100644
--- a/test/CodeGenCXX/pr28360.cpp
+++ b/test/CodeGenCXX/pr28360.cpp
@@ -10,7 +10,7 @@ void Bar(const MpTy &);
void Baz() { Bar(&A::Foo); }
-// CHECK-LABEL: define void @"\01?Baz@@YAXXZ"(
+// CHECK-LABEL: define dso_local void @"?Baz@@YAXXZ"(
// CHECK: %[[ref_tmp:.*]] = alloca i8*, align 4
-// CHECK: store i8* bitcast (void (%struct.A*)* @"\01?Foo@A@@QAEXXZ" to i8*), i8** %[[ref_tmp]], align 4
-// CHECK: call void @"\01?Bar@@YAXABQ8A@@AEXXZ@Z"(i8** dereferenceable(4) %[[ref_tmp]])
+// CHECK: store i8* bitcast (void (%struct.A*)* @"?Foo@A@@QAEXXZ" to i8*), i8** %[[ref_tmp]], align 4
+// CHECK: call void @"?Bar@@YAXABQ8A@@AEXXZ@Z"(i8** dereferenceable(4) %[[ref_tmp]])
diff --git a/test/CodeGenCXX/pr30731.cpp b/test/CodeGenCXX/pr30731.cpp
index 078f21ceda4f..36da43fe29b0 100644
--- a/test/CodeGenCXX/pr30731.cpp
+++ b/test/CodeGenCXX/pr30731.cpp
@@ -16,6 +16,6 @@ struct S : A, virtual B, C {
void f(S* s) { s->f(); }
-// CHECK-LABEL: define void @"\01?f@@YAXPAUS@@@Z"
+// CHECK-LABEL: define dso_local void @"?f@@YAXPAUS@@@Z"
// CHECK: call
// CHECK: ret void
diff --git a/test/CodeGenCXX/pr33080.cpp b/test/CodeGenCXX/pr33080.cpp
index a744bca18986..bae47cc2e068 100644
--- a/test/CodeGenCXX/pr33080.cpp
+++ b/test/CodeGenCXX/pr33080.cpp
@@ -1,25 +1,29 @@
// RUN: %clang_cc1 -triple %itanium_abi_triple -fms-extensions -emit-llvm -o- %s | FileCheck %s
void fa(__unaligned struct A *) {}
-// CHECK: define void @_Z2faPU11__unaligned1A(
+// CHECK: define {{(dso_local )?}}void @_Z2faPU11__unaligned1A(
void ga(struct A *, struct A *) {}
-// CHECK: define void @_Z2gaP1AS0_(
+// CHECK: define {{(dso_local )?}}void @_Z2gaP1AS0_(
void gb(__unaligned struct A *, struct A *) {}
-// CHECK: define void @_Z2gbPU11__unaligned1APS_(
+// CHECK: define {{(dso_local )?}}void @_Z2gbPU11__unaligned1APS_(
void gc(struct A *, __unaligned struct A *) {}
-// CHECK: define void @_Z2gcP1APU11__unalignedS_(
+// CHECK: define {{(dso_local )?}}void @_Z2gcP1APU11__unalignedS_(
void gd(__unaligned struct A *, __unaligned struct A *) {}
-// CHECK: define void @_Z2gdPU11__unaligned1AS1_(
+// CHECK: define {{(dso_local )?}}void @_Z2gdPU11__unaligned1AS1_(
void hb(__unaligned struct A *, __unaligned const struct A *) {}
-// CHECK: define void @_Z2hbPU11__unaligned1APU11__unalignedKS_(
+// CHECK: define {{(dso_local )?}}void @_Z2hbPU11__unaligned1APU11__unalignedKS_(
void ja(__unaligned struct A *, __unaligned struct A *__unaligned *, __unaligned struct A *__unaligned *__unaligned *) {}
-// CHECK: define void @_Z2jaPU11__unaligned1APU11__unalignedS1_PU11__unalignedS3_(
+// CHECK: define {{(dso_local )?}}void @_Z2jaPU11__unaligned1APU11__unalignedS1_PU11__unalignedS3_(
+
+struct A;
+void memptr(void (A::*a)(int) __unaligned) {}
+// CHECK: define {{.*}} @_Z6memptrM1AU11__unalignedFviE(
void jb(__unaligned struct A *, __unaligned struct A **, __unaligned struct A *__unaligned *__unaligned *) {}
// CHECK: @_Z2jbPU11__unaligned1APS1_PU11__unalignedPU11__unalignedS1_(
diff --git a/test/CodeGenCXX/pragma-init_seg.cpp b/test/CodeGenCXX/pragma-init_seg.cpp
index 1ed841f23ddd..8b33b854fd21 100644
--- a/test/CodeGenCXX/pragma-init_seg.cpp
+++ b/test/CodeGenCXX/pragma-init_seg.cpp
@@ -2,24 +2,24 @@
int f();
-// CHECK: $"\01?x@selectany_init@@3HA" = comdat any
-// CHECK: $"\01?x@?$A@H@explicit_template_instantiation@@2HB" = comdat any
-// CHECK: $"\01?x@?$A@H@implicit_template_instantiation@@2HB" = comdat any
+// CHECK: $"?x@selectany_init@@3HA" = comdat any
+// CHECK: $"?x@?$A@H@explicit_template_instantiation@@2HB" = comdat any
+// CHECK: $"?x@?$A@H@implicit_template_instantiation@@2HB" = comdat any
namespace simple_init {
#pragma init_seg(compiler)
int x = f();
-// CHECK: @"\01?x@simple_init@@3HA" = global i32 0, align 4
-// CHECK: @__cxx_init_fn_ptr = private constant void ()* @"\01??__Ex@simple_init@@YAXXZ", section ".CRT$XCC"
+// CHECK: @"?x@simple_init@@3HA" = dso_local global i32 0, align 4
+// CHECK: @__cxx_init_fn_ptr = private constant void ()* @"??__Ex@simple_init@@YAXXZ", section ".CRT$XCC"
#pragma init_seg(lib)
int y = f();
-// CHECK: @"\01?y@simple_init@@3HA" = global i32 0, align 4
-// CHECK: @__cxx_init_fn_ptr.1 = private constant void ()* @"\01??__Ey@simple_init@@YAXXZ", section ".CRT$XCL"
+// CHECK: @"?y@simple_init@@3HA" = dso_local global i32 0, align 4
+// CHECK: @__cxx_init_fn_ptr.1 = private constant void ()* @"??__Ey@simple_init@@YAXXZ", section ".CRT$XCL"
#pragma init_seg(user)
int z = f();
-// CHECK: @"\01?z@simple_init@@3HA" = global i32 0, align 4
+// CHECK: @"?z@simple_init@@3HA" = dso_local global i32 0, align 4
// No function pointer! This one goes on @llvm.global_ctors.
}
@@ -28,31 +28,31 @@ int z = f();
namespace internal_init {
namespace {
int x = f();
-// CHECK: @"\01?x@?A@internal_init@@3HA" = internal global i32 0, align 4
-// CHECK: @__cxx_init_fn_ptr.2 = private constant void ()* @"\01??__Ex@?A@internal_init@@YAXXZ", section ".asdf"
+// CHECK: @"?x@?A@internal_init@@3HA" = internal global i32 0, align 4
+// CHECK: @__cxx_init_fn_ptr.2 = private constant void ()* @"??__Ex@?A@internal_init@@YAXXZ", section ".asdf"
}
}
namespace selectany_init {
int __declspec(selectany) x = f();
-// CHECK: @"\01?x@selectany_init@@3HA" = weak_odr global i32 0, comdat, align 4
-// CHECK: @__cxx_init_fn_ptr.3 = private constant void ()* @"\01??__Ex@selectany_init@@YAXXZ", section ".asdf", comdat($"\01?x@selectany_init@@3HA")
+// CHECK: @"?x@selectany_init@@3HA" = weak_odr dso_local global i32 0, comdat, align 4
+// CHECK: @__cxx_init_fn_ptr.3 = private constant void ()* @"??__Ex@selectany_init@@YAXXZ", section ".asdf", comdat($"?x@selectany_init@@3HA")
}
namespace explicit_template_instantiation {
template <typename T> struct A { static const int x; };
template <typename T> const int A<T>::x = f();
template struct A<int>;
-// CHECK: @"\01?x@?$A@H@explicit_template_instantiation@@2HB" = weak_odr global i32 0, comdat, align 4
-// CHECK: @__cxx_init_fn_ptr.4 = private constant void ()* @"\01??__Ex@?$A@H@explicit_template_instantiation@@2HB@YAXXZ", section ".asdf", comdat($"\01?x@?$A@H@explicit_template_instantiation@@2HB")
+// CHECK: @"?x@?$A@H@explicit_template_instantiation@@2HB" = weak_odr dso_local global i32 0, comdat, align 4
+// CHECK: @__cxx_init_fn_ptr.4 = private constant void ()* @"??__Ex@?$A@H@explicit_template_instantiation@@2HB@YAXXZ", section ".asdf", comdat($"?x@?$A@H@explicit_template_instantiation@@2HB")
}
namespace implicit_template_instantiation {
template <typename T> struct A { static const int x; };
template <typename T> const int A<T>::x = f();
int g() { return A<int>::x; }
-// CHECK: @"\01?x@?$A@H@implicit_template_instantiation@@2HB" = linkonce_odr global i32 0, comdat, align 4
-// CHECK: @__cxx_init_fn_ptr.5 = private constant void ()* @"\01??__Ex@?$A@H@implicit_template_instantiation@@2HB@YAXXZ", section ".asdf", comdat($"\01?x@?$A@H@implicit_template_instantiation@@2HB")
+// CHECK: @"?x@?$A@H@implicit_template_instantiation@@2HB" = linkonce_odr dso_local global i32 0, comdat, align 4
+// CHECK: @__cxx_init_fn_ptr.5 = private constant void ()* @"??__Ex@?$A@H@implicit_template_instantiation@@2HB@YAXXZ", section ".asdf", comdat($"?x@?$A@H@implicit_template_instantiation@@2HB")
}
// ... and here's where we emitted user level ctors.
diff --git a/test/CodeGenCXX/pragma-weak.cpp b/test/CodeGenCXX/pragma-weak.cpp
index caab2662a9f5..83d66bca3b5a 100644
--- a/test/CodeGenCXX/pragma-weak.cpp
+++ b/test/CodeGenCXX/pragma-weak.cpp
@@ -5,7 +5,7 @@ int zex;
// GCC produces a weak symbol for this because it matches mangled names.
// Different c++ ABIs may or may not mangle this, so we produce a strong
// symbol.
-// CHECK: @zex = global i32
+// CHECK: @zex = {{(dso_local )?}}global i32
#pragma weak foo
struct S { void foo(); };
diff --git a/test/CodeGenCXX/reference-init.cpp b/test/CodeGenCXX/reference-init.cpp
index ba7b282028cf..5a91d3bd6d1f 100644
--- a/test/CodeGenCXX/reference-init.cpp
+++ b/test/CodeGenCXX/reference-init.cpp
@@ -3,6 +3,12 @@
// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o - -std=c++11 | FileCheck %s --check-prefix=CHECK-CXX11
// expected-no-diagnostics
+#if __cplusplus >= 201103L
+// CHECK-CXX11: @_ZZ15InitRefWithListvE1r = internal constant i32* @_ZGRZ15InitRefWithListvE1r_
+// CHECK-CXX11: @_ZGRZ15InitRefWithListvE1r_ = internal constant i32 123
+int InitRefWithList() { static const int &r = {123}; return r; }
+#endif
+
struct XPTParamDescriptor {};
struct nsXPTParamInfo {
nsXPTParamInfo(const XPTParamDescriptor& desc);
@@ -31,6 +37,6 @@ const int &s2 = s.bitfield;
struct SelfReference { SelfReference &r; };
extern SelfReference self_reference_1;
SelfReference self_reference_2 = {self_reference_1};
-// CHECK-CXX98: @self_reference_2 = global %[[SELF_REF:.*]] { %[[SELF_REF]]* @self_reference_1 }
-// CHECK-CXX11: @self_reference_2 = global %[[SELF_REF:.*]] zeroinitializer
+// CHECK-CXX98: @self_reference_2 = {{.*}}global %[[SELF_REF:.*]] { %[[SELF_REF]]* @self_reference_1 }
+// CHECK-CXX11: @self_reference_2 = {{(dso_local )?}}global %[[SELF_REF:.*]] zeroinitializer
// CHECK-CXX11: call {{.*}}memcpy{{.*}} @self_reference_2 {{.*}} @self_reference_1
diff --git a/test/CodeGenCXX/regcall.cpp b/test/CodeGenCXX/regcall.cpp
index 2b7b9e2a6eff..fbc1dbf7d7c9 100644
--- a/test/CodeGenCXX/regcall.cpp
+++ b/test/CodeGenCXX/regcall.cpp
@@ -1,7 +1,7 @@
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -std=c++11 %s -o - | FileCheck -check-prefix=CHECK-LIN -check-prefix=CHECK-LIN64 %s
-// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -std=c++11 %s -o - | FileCheck -check-prefix=CHECK-LIN -check-prefix=CHECK-LIN32 %s
-// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -std=c++11 %s -o - -DWIN_TEST | FileCheck -check-prefix=CHECK-WIN64 %s
-// RUN: %clang_cc1 -triple i386-windows-msvc -emit-llvm -std=c++11 %s -o - -DWIN_TEST | FileCheck -check-prefix=CHECK-WIN32 %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -std=c++11 %s -o - | FileCheck -allow-deprecated-dag-overlap -check-prefix=CHECK-LIN -check-prefix=CHECK-LIN64 %s
+// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -std=c++11 %s -o - | FileCheck -allow-deprecated-dag-overlap -check-prefix=CHECK-LIN -check-prefix=CHECK-LIN32 %s
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -std=c++11 %s -o - -DWIN_TEST | FileCheck -allow-deprecated-dag-overlap -check-prefix=CHECK-WIN64 %s
+// RUN: %clang_cc1 -triple i386-windows-msvc -emit-llvm -std=c++11 %s -o - -DWIN_TEST | FileCheck -allow-deprecated-dag-overlap -check-prefix=CHECK-WIN32 %s
int __regcall foo(int i);
@@ -15,15 +15,15 @@ int main()
return lambda(p);
}
// CHECK-LIN: call x86_regcallcc {{.+}} @_Z15__regcall3__foo
-// CHECK-WIN64: call x86_regcallcc {{.+}} @"\01?foo@@YwHH@Z"
-// CHECK-WIN32: call x86_regcallcc {{.+}} @"\01?foo@@YwHH@Z"
+// CHECK-WIN64: call x86_regcallcc {{.+}} @"?foo@@YwHH@Z"
+// CHECK-WIN32: call x86_regcallcc {{.+}} @"?foo@@YwHH@Z"
int __regcall foo (int i){
return i;
}
// CHECK-LIN: define x86_regcallcc {{.+}}@_Z15__regcall3__foo
-// CHECK-WIN64: define x86_regcallcc {{.+}}@"\01?foo@@YwHH@Z"
-// CHECK-WIN32: define x86_regcallcc {{.+}}@"\01?foo@@YwHH@Z"
+// CHECK-WIN64: define dso_local x86_regcallcc {{.+}}@"?foo@@YwHH@Z"
+// CHECK-WIN32: define dso_local x86_regcallcc {{.+}}@"?foo@@YwHH@Z"
// used to give a body to test_class functions
static int x = 0;
@@ -37,8 +37,8 @@ public:
// CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_classC1Ev
// CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_classC2Ev
// Windows ignores calling convention on constructor/destructors.
- // CHECK-WIN64-DAG: define linkonce_odr %class.test_class* @"\01??0test_class@@QEAA@XZ"
- // CHECK-WIN32-DAG: define linkonce_odr x86_thiscallcc %class.test_class* @"\01??0test_class@@QAE@XZ"
+ // CHECK-WIN64-DAG: define linkonce_odr dso_local %class.test_class* @"??0test_class@@QEAA@XZ"
+ // CHECK-WIN32-DAG: define linkonce_odr dso_local x86_thiscallcc %class.test_class* @"??0test_class@@QAE@XZ"
#ifndef WIN_TEST
__regcall
@@ -47,43 +47,43 @@ public:
// CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_classD2Ev
// CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_classD1Ev
// Windows ignores calling convention on constructor/destructors.
- // CHECK-WIN64-DAG: define linkonce_odr void @"\01??_Dtest_class@@QEAAXXZ"
- // CHECK-WIN32-DAG: define linkonce_odr x86_thiscallcc void @"\01??_Dtest_class@@QAEXXZ"
+ // CHECK-WIN64-DAG: define linkonce_odr dso_local void @"??1test_class@@QEAA@XZ"
+ // CHECK-WIN32-DAG: define linkonce_odr dso_local x86_thiscallcc void @"??1test_class@@QAE@XZ"
test_class& __regcall operator+=(const test_class&){
return *this;
}
// CHECK-LIN-DAG: define linkonce_odr x86_regcallcc dereferenceable(4) %class.test_class* @_ZN10test_classpLERKS_
- // CHECK-WIN64-DAG: define linkonce_odr x86_regcallcc dereferenceable(4) %class.test_class* @"\01??Ytest_class@@QEAwAEAV0@AEBV0@@Z"
- // CHECK-WIN32-DAG: define linkonce_odr x86_regcallcc dereferenceable(4) %class.test_class* @"\01??Ytest_class@@QAwAAV0@ABV0@@Z"
+ // CHECK-WIN64-DAG: define linkonce_odr dso_local x86_regcallcc dereferenceable(4) %class.test_class* @"??Ytest_class@@QEAwAEAV0@AEBV0@@Z"
+ // CHECK-WIN32-DAG: define linkonce_odr dso_local x86_regcallcc dereferenceable(4) %class.test_class* @"??Ytest_class@@QAwAAV0@ABV0@@Z"
void __regcall do_thing(){}
// CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_class20__regcall3__do_thingEv
- // CHECK-WIN64-DAG: define linkonce_odr x86_regcallcc void @"\01?do_thing@test_class@@QEAwXXZ"
- // CHECK-WIN32-DAG: define linkonce_odr x86_regcallcc void @"\01?do_thing@test_class@@QAwXXZ"
+ // CHECK-WIN64-DAG: define linkonce_odr dso_local x86_regcallcc void @"?do_thing@test_class@@QEAwXXZ"
+ // CHECK-WIN32-DAG: define linkonce_odr dso_local x86_regcallcc void @"?do_thing@test_class@@QAwXXZ"
template<typename T>
void __regcall tempFunc(T i){}
// CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_class20__regcall3__tempFuncIiEEvT_
- // CHECK-WIN64-DAG: define linkonce_odr x86_regcallcc void @"\01??$freeTempFunc@H@@YwXH@Z"
- // CHECK-WIN32-DAG: define linkonce_odr x86_regcallcc void @"\01??$freeTempFunc@H@@YwXH@Z"
+ // CHECK-WIN64-DAG: define linkonce_odr dso_local x86_regcallcc void @"??$freeTempFunc@H@@YwXH@Z"
+ // CHECK-WIN32-DAG: define linkonce_odr dso_local x86_regcallcc void @"??$freeTempFunc@H@@YwXH@Z"
};
bool __regcall operator ==(const test_class&, const test_class&){ --x; return false;}
// CHECK-LIN-DAG: define x86_regcallcc zeroext i1 @_ZeqRK10test_classS1_
-// CHECK-WIN64-DAG: define x86_regcallcc zeroext i1 @"\01??8@Yw_NAEBVtest_class@@0@Z"
-// CHECK-WIN32-DAG: define x86_regcallcc zeroext i1 @"\01??8@Yw_NABVtest_class@@0@Z"
+// CHECK-WIN64-DAG: define dso_local x86_regcallcc zeroext i1 @"??8@Yw_NAEBVtest_class@@0@Z"
+// CHECK-WIN32-DAG: define dso_local x86_regcallcc zeroext i1 @"??8@Yw_NABVtest_class@@0@Z"
test_class __regcall operator""_test_class (unsigned long long) { ++x; return test_class{};}
// CHECK-LIN64-DAG: define x86_regcallcc void @_Zli11_test_classy(%class.test_class* noalias sret %agg.result, i64)
// CHECK-LIN32-DAG: define x86_regcallcc void @_Zli11_test_classy(%class.test_class* inreg noalias sret %agg.result, i64)
-// CHECK-WIN64-DAG: \01??__K_test_class@@Yw?AVtest_class@@_K@Z"
-// CHECK-WIN32-DAG: \01??__K_test_class@@Yw?AVtest_class@@_K@Z"
+// CHECK-WIN64-DAG: ??__K_test_class@@Yw?AVtest_class@@_K@Z"
+// CHECK-WIN32-DAG: ??__K_test_class@@Yw?AVtest_class@@_K@Z"
template<typename T>
void __regcall freeTempFunc(T i){}
// CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_Z24__regcall3__freeTempFuncIiEvT_
-// CHECK-WIN64-DAG: define linkonce_odr x86_regcallcc void @"\01??$freeTempFunc@H@@YwXH@Z"
-// CHECK-WIN32-DAG: define linkonce_odr x86_regcallcc void @"\01??$freeTempFunc@H@@YwXH@Z"
+// CHECK-WIN64-DAG: define linkonce_odr dso_local x86_regcallcc void @"??$freeTempFunc@H@@YwXH@Z"
+// CHECK-WIN32-DAG: define linkonce_odr dso_local x86_regcallcc void @"??$freeTempFunc@H@@YwXH@Z"
// class to force generation of functions
void force_gen() {
@@ -101,5 +101,5 @@ long double _Complex __regcall foo(long double _Complex f) {
}
// CHECK-LIN64-DAG: define x86_regcallcc void @_Z15__regcall3__fooCe({ x86_fp80, x86_fp80 }* noalias sret %agg.result, { x86_fp80, x86_fp80 }* byval align 16 %f)
// CHECK-LIN32-DAG: define x86_regcallcc void @_Z15__regcall3__fooCe({ x86_fp80, x86_fp80 }* inreg noalias sret %agg.result, { x86_fp80, x86_fp80 }* byval align 4 %f)
-// CHECK-WIN64-DAG: define x86_regcallcc { double, double } @"\01?foo@@YwU?$_Complex@O@__clang@@U12@@Z"(double %f.0, double %f.1)
-// CHECK-WIN32-DAG: define x86_regcallcc { double, double } @"\01?foo@@YwU?$_Complex@O@__clang@@U12@@Z"(double %f.0, double %f.1)
+// CHECK-WIN64-DAG: define dso_local x86_regcallcc { double, double } @"?foo@@YwU?$_Complex@O@__clang@@U12@@Z"(double %f.0, double %f.1)
+// CHECK-WIN32-DAG: define dso_local x86_regcallcc { double, double } @"?foo@@YwU?$_Complex@O@__clang@@U12@@Z"(double %f.0, double %f.1)
diff --git a/test/CodeGenCXX/rtti-fundamental.cpp b/test/CodeGenCXX/rtti-fundamental.cpp
index a0ad80d7c98a..d0e5890f89c7 100644
--- a/test/CodeGenCXX/rtti-fundamental.cpp
+++ b/test/CodeGenCXX/rtti-fundamental.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm -fvisibility hidden -o - | FileCheck %s -check-prefix=CHECK-HIDDEN
#include <typeinfo>
@@ -16,116 +17,184 @@ namespace __cxxabiv1 {
// void
// CHECK: @_ZTIv = constant
+// CHECK-HIDDEN: @_ZTIv = hidden constant
// CHECK: @_ZTIPv = constant
+// CHECK-HIDDEN: @_ZTIPv = hidden constant
// CHECK: @_ZTIPKv = constant
+// CHECK-HIDDEN: @_ZTIPKv = hidden constant
// std::nullptr_t
// CHECK: @_ZTIDn = constant
+// CHECK-HIDDEN: @_ZTIDn = hidden constant
// CHECK: @_ZTIPDn = constant
+// CHECK-HIDDEN: @_ZTIPDn = hidden constant
// CHECK: @_ZTIPKDn = constant
+// CHECK-HIDDEN: @_ZTIPKDn = hidden constant
// bool
// CHECK: @_ZTIb = constant
+// CHECK-HIDDEN: @_ZTIb = hidden constant
// CHECK: @_ZTIPb = constant
+// CHECK-HIDDEN: @_ZTIPb = hidden constant
// CHECK: @_ZTIPKb = constant
+// CHECK-HIDDEN: @_ZTIPKb = hidden constant
// wchar_t
// CHECK: @_ZTIw = constant
+// CHECK-HIDDEN: @_ZTIw = hidden constant
// CHECK: @_ZTIPw = constant
+// CHECK-HIDDEN: @_ZTIPw = hidden constant
// CHECK: @_ZTIPKw = constant
+// CHECK-HIDDEN: @_ZTIPKw = hidden constant
// char
// CHECK: @_ZTIc = constant
+// CHECK-HIDDEN: @_ZTIc = hidden constant
// CHECK: @_ZTIPc = constant
+// CHECK-HIDDEN: @_ZTIPc = hidden constant
// CHECK: @_ZTIPKc = constant
+// CHECK-HIDDEN: @_ZTIPKc = hidden constant
// unsigned char
// CHECK: @_ZTIh = constant
+// CHECK-HIDDEN: @_ZTIh = hidden constant
// CHECK: @_ZTIPh = constant
+// CHECK-HIDDEN: @_ZTIPh = hidden constant
// CHECK: @_ZTIPKh = constant
+// CHECK-HIDDEN: @_ZTIPKh = hidden constant
// signed char
// CHECK: @_ZTIa = constant
+// CHECK-HIDDEN: @_ZTIa = hidden constant
// CHECK: @_ZTIPa = constant
+// CHECK-HIDDEN: @_ZTIPa = hidden constant
// CHECK: @_ZTIPKa = constant
+// CHECK-HIDDEN: @_ZTIPKa = hidden constant
// short
// CHECK: @_ZTIs = constant
+// CHECK-HIDDEN: @_ZTIs = hidden constant
// CHECK: @_ZTIPs = constant
+// CHECK-HIDDEN: @_ZTIPs = hidden constant
// CHECK: @_ZTIPKs = constant
+// CHECK-HIDDEN: @_ZTIPKs = hidden constant
// unsigned short
// CHECK: @_ZTIt = constant
+// CHECK-HIDDEN: @_ZTIt = hidden constant
// CHECK: @_ZTIPt = constant
+// CHECK-HIDDEN: @_ZTIPt = hidden constant
// CHECK: @_ZTIPKt = constant
+// CHECK-HIDDEN: @_ZTIPKt = hidden constant
// int
// CHECK: @_ZTIi = constant
+// CHECK-HIDDEN: @_ZTIi = hidden constant
// CHECK: @_ZTIPi = constant
+// CHECK-HIDDEN: @_ZTIPi = hidden constant
// CHECK: @_ZTIPKi = constant
+// CHECK-HIDDEN: @_ZTIPKi = hidden constant
// unsigned int
// CHECK: @_ZTIj = constant
+// CHECK-HIDDEN: @_ZTIj = hidden constant
// CHECK: @_ZTIPj = constant
+// CHECK-HIDDEN: @_ZTIPj = hidden constant
// CHECK: @_ZTIPKj = constant
+// CHECK-HIDDEN: @_ZTIPKj = hidden constant
// long
// CHECK: @_ZTIl = constant
+// CHECK-HIDDEN: @_ZTIl = hidden constant
// CHECK: @_ZTIPl = constant
+// CHECK-HIDDEN: @_ZTIPl = hidden constant
// CHECK: @_ZTIPKl = constant
+// CHECK-HIDDEN: @_ZTIPKl = hidden constant
// unsigned long
// CHECK: @_ZTIm = constant
+// CHECK-HIDDEN: @_ZTIm = hidden constant
// CHECK: @_ZTIPm = constant
+// CHECK-HIDDEN: @_ZTIPm = hidden constant
// CHECK: @_ZTIPKm = constant
+// CHECK-HIDDEN: @_ZTIPKm = hidden constant
// long long
// CHECK: @_ZTIx = constant
+// CHECK-HIDDEN: @_ZTIx = hidden constant
// CHECK: @_ZTIPx = constant
+// CHECK-HIDDEN: @_ZTIPx = hidden constant
// CHECK: @_ZTIPKx = constant
+// CHECK-HIDDEN: @_ZTIPKx = hidden constant
// unsigned long long
// CHECK: @_ZTIy = constant
+// CHECK-HIDDEN: @_ZTIy = hidden constant
// CHECK: @_ZTIPy = constant
+// CHECK-HIDDEN: @_ZTIPy = hidden constant
// CHECK: @_ZTIPKy = constant
+// CHECK-HIDDEN: @_ZTIPKy = hidden constant
// __int128
// CHECK: @_ZTIn = constant
+// CHECK-HIDDEN: @_ZTIn = hidden constant
// CHECK: @_ZTIPn = constant
+// CHECK-HIDDEN: @_ZTIPn = hidden constant
// CHECK: @_ZTIPKn = constant
+// CHECK-HIDDEN: @_ZTIPKn = hidden constant
// unsigned __int128
// CHECK: @_ZTIo = constant
+// CHECK-HIDDEN: @_ZTIo = hidden constant
// CHECK: @_ZTIPo = constant
+// CHECK-HIDDEN: @_ZTIPo = hidden constant
// CHECK: @_ZTIPKo = constant
+// CHECK-HIDDEN: @_ZTIPKo = hidden constant
// half
// CHECK: @_ZTIDh = constant
+// CHECK-HIDDEN: @_ZTIDh = hidden constant
// CHECK: @_ZTIPDh = constant
+// CHECK-HIDDEN: @_ZTIPDh = hidden constant
// CHECK: @_ZTIPKDh = constant
+// CHECK-HIDDEN: @_ZTIPKDh = hidden constant
// float
// CHECK: @_ZTIf = constant
+// CHECK-HIDDEN: @_ZTIf = hidden constant
// CHECK: @_ZTIPf = constant
+// CHECK-HIDDEN: @_ZTIPf = hidden constant
// CHECK: @_ZTIPKf = constant
+// CHECK-HIDDEN: @_ZTIPKf = hidden constant
// double
// CHECK: @_ZTId = constant
+// CHECK-HIDDEN: @_ZTId = hidden constant
// CHECK: @_ZTIPd = constant
+// CHECK-HIDDEN: @_ZTIPd = hidden constant
// CHECK: @_ZTIPKd = constant
+// CHECK-HIDDEN: @_ZTIPKd = hidden constant
// long double
// CHECK: @_ZTIe = constant
+// CHECK-HIDDEN: @_ZTIe = hidden constant
// CHECK: @_ZTIPe = constant
+// CHECK-HIDDEN: @_ZTIPe = hidden constant
// CHECK: @_ZTIPKe = constant
+// CHECK-HIDDEN: @_ZTIPKe = hidden constant
// char16_t
// CHECK: @_ZTIDs = constant
+// CHECK-HIDDEN: @_ZTIDs = hidden constant
// CHECK: @_ZTIPDs = constant
+// CHECK-HIDDEN: @_ZTIPDs = hidden constant
// CHECK: @_ZTIPKDs = constant
+// CHECK-HIDDEN: @_ZTIPKDs = hidden constant
// char32_t
// CHECK: @_ZTIDi = constant
+// CHECK-HIDDEN: @_ZTIDi = hidden constant
// CHECK: @_ZTIPDi = constant
+// CHECK-HIDDEN: @_ZTIPDi = hidden constant
// CHECK: @_ZTIPKDi = constant
-
+// CHECK-HIDDEN: @_ZTIPKDi = hidden constant
diff --git a/test/CodeGenCXX/rtti-hidden.cpp b/test/CodeGenCXX/rtti-hidden.cpp
new file mode 100644
index 000000000000..3ae487f58025
--- /dev/null
+++ b/test/CodeGenCXX/rtti-hidden.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 %s -triple=x86_64-pc-linux -emit-llvm -o - | FileCheck %s
+
+// Test that this is not hidden.
+// CHECK: @_ZTVN10__cxxabiv120__si_class_type_infoE = external global
+
+class foo {
+ virtual void baz();
+};
+struct __attribute__((__visibility__("hidden"))) bar : public foo {};
+bar zed;
diff --git a/test/CodeGenCXX/rtti-mingw64.cpp b/test/CodeGenCXX/rtti-mingw64.cpp
index 9f3e03961e89..628a4d0313c7 100644
--- a/test/CodeGenCXX/rtti-mingw64.cpp
+++ b/test/CodeGenCXX/rtti-mingw64.cpp
@@ -7,8 +7,8 @@ class C {
};
C::~C() {}
-// CHECK: @_ZTI1C = linkonce_odr
-// CHECK: @_ZTI1B = linkonce_odr constant { i8*, i8*, i32, i32, i8*, i64 }
+// CHECK: @_ZTI1C = linkonce_odr dso_local
+// CHECK: @_ZTI1B = linkonce_odr dso_local constant { i8*, i8*, i32, i32, i8*, i64 }
// CHECK-SAME: i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv121__vmi_class_type_infoE, i64 2) to i8*),
// CHECK-SAME: i8* getelementptr inbounds ([3 x i8], [3 x i8]* @_ZTS1B, i32 0, i32 0),
// CHECK-SAME: i32 0,
diff --git a/test/CodeGenCXX/runtime-dllstorage.cpp b/test/CodeGenCXX/runtime-dllstorage.cpp
index 8ccf0291687c..7220fa50b0ee 100644
--- a/test/CodeGenCXX/runtime-dllstorage.cpp
+++ b/test/CodeGenCXX/runtime-dllstorage.cpp
@@ -1,21 +1,21 @@
-// RUN: %clang_cc1 -triple i686-windows-msvc -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-MS -check-prefix CHECK-MS-DYNAMIC
-// RUN: %clang_cc1 -triple i686-windows-msvc -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-MS -check-prefix CHECK-MS-STATIC
-
-// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA -check-prefix CHECK-DYNAMIC-NODECL-IA -check-prefix CHECK-DYANMIC-IA-CXA-ATEXIT
-// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA -check-prefix CHECK-STATIC-NODECL-IA -check-prefix CHECK-IA-STATIC-CXA-ATEXIT
-// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -DIMPORT_DECLARATIONS -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA -check-prefix CHECK-DYNAMIC-IMPORT-IA -check-prefix CHECK-DYANMIC-IA-CXA-ATEXIT
-// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -DIMPORT_DECLARATIONS -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA -check-prefix CHECK-STATIC-IMPORT-IA -check-prefix CHECK-IA-STATIC-CXA-ATEXIT
-// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -DEXPORT_DECLARATIONS -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA -check-prefix CHECK-DYANMIC-IA-CXA-ATEXIT
-// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -DEXPORT_DECLARATIONS -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA -check-prefix CHECK-IA-STATIC-CXA-ATEXIT
-// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -DDECL -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA -check-prefix CHECK-DYNAMIC-DECL-IA -check-prefix CHECK-DYANMIC-IA-CXA-ATEXIT
-// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -DDECL -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA -check-prefix CHECK-STATIC-DECL-IA -check-prefix CHECK-IA-STATIC-CXA-ATEXIT
+// RUN: %clang_cc1 -triple i686-windows-msvc -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap %s -check-prefix CHECK-MS -check-prefix CHECK-MS-DYNAMIC
+// RUN: %clang_cc1 -triple i686-windows-msvc -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap %s -check-prefix CHECK-MS -check-prefix CHECK-MS-STATIC
+
+// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA -check-prefix CHECK-DYNAMIC-NODECL-IA -check-prefix CHECK-DYANMIC-IA-CXA-ATEXIT
+// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA -check-prefix CHECK-STATIC-NODECL-IA -check-prefix CHECK-IA-STATIC-CXA-ATEXIT
+// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -DIMPORT_DECLARATIONS -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA -check-prefix CHECK-DYNAMIC-IMPORT-IA -check-prefix CHECK-DYANMIC-IA-CXA-ATEXIT
+// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -DIMPORT_DECLARATIONS -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA -check-prefix CHECK-STATIC-IMPORT-IA -check-prefix CHECK-IA-STATIC-CXA-ATEXIT
+// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -DEXPORT_DECLARATIONS -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA -check-prefix CHECK-DYANMIC-IA-CXA-ATEXIT
+// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -DEXPORT_DECLARATIONS -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA -check-prefix CHECK-IA-STATIC-CXA-ATEXIT
+// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -DDECL -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA -check-prefix CHECK-DYNAMIC-DECL-IA -check-prefix CHECK-DYANMIC-IA-CXA-ATEXIT
+// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -DDECL -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA -check-prefix CHECK-STATIC-DECL-IA -check-prefix CHECK-IA-STATIC-CXA-ATEXIT
// %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -fno-use-cxa-atexit -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA -check-prefix CHECK-DYNAMIC-IA-ATEXIT
// %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -fno-use-cxa-atexit -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA -check-prefix CHECK-STATIC-IA-ATEXIT
-// RUN: %clang_cc1 -triple i686-windows-gnu -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA
-// RUN: %clang_cc1 -triple i686-windows-gnu -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA
-// RUN: %clang_cc1 -triple i686-windows-cygnus -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA
-// RUN: %clang_cc1 -triple i686-windows-cygnus -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA
+// RUN: %clang_cc1 -triple i686-windows-gnu -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA
+// RUN: %clang_cc1 -triple i686-windows-gnu -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA
+// RUN: %clang_cc1 -triple i686-windows-cygnus -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA
+// RUN: %clang_cc1 -triple i686-windows-cygnus -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA
#if defined(IMPORT_DECLARATIONS)
namespace __cxxabiv1 {
@@ -106,15 +106,16 @@ void l() {
}
// CHECK-MS-DAG: @_Init_thread_epoch = external thread_local global i32
-// CHECK-MS-DAG: declare i32 @__tlregdtor(void ()*)
-// CHECK-MS-DAG: declare i32 @atexit(void ()*)
+// CHECK-MS-DAG: declare dso_local i32 @__tlregdtor(void ()*)
+// CHECK-MS-DAG: declare dso_local i32 @atexit(void ()*)
// CHECK-MS-DYNAMIC-DAG: declare dllimport {{.*}} void @_CxxThrowException
// CHECK-MS-STATIC-DAG: declare {{.*}} void @_CxxThrowException
-// CHECK-MS-DAG: declare noalias i8* @"\01??2@YAPAXI@Z"
-// CHECK-MS-DAG: declare void @_Init_thread_header(i32*)
-// CHECK-MS-DAG: declare void @_Init_thread_footer(i32*)
+// CHECK-MS-DAG: declare dso_local noalias i8* @"??2@YAPAXI@Z"
+// CHECK-MS-DAG: declare dso_local void @_Init_thread_header(i32*)
+// CHECK-MS-DAG: declare dso_local void @_Init_thread_footer(i32*)
-// CHECK-IA-DAG: declare i32 @__gxx_personality_v0(...)
+// CHECK-IA-DAG: @_ZTH1t = dso_local alias void (), void ()* @__tls_init
+// CHECK-IA-DAG: declare dso_local i32 @__gxx_personality_v0(...)
// CHECK-IA-DAG: define linkonce_odr hidden void @__clang_call_terminate(i8*)
// CHECK-DYNAMIC-IA-DAG: declare dllimport i32 @__cxa_thread_atexit(void (i8*)*, i8*, i8*)
@@ -128,31 +129,31 @@ void l() {
// CHECK-DYNAMIC-NODECL-IA-DAG: declare dllimport i32 @__cxa_guard_acquire(i64*)
// CHECK-DYNAMIC-IMPORT-IA-DAG: declare dllimport i32 @__cxa_guard_acquire(i64*)
// CHECK-DYNAMIC-EXPORT-IA-DAG: declare dllexport i32 @__cxa_guard_acquire(i64*)
-// CHECK-IA-DAG: declare noalias i8* @_Znwj(i32)
+// CHECK-IA-DAG: declare dso_local noalias i8* @_Znwj(i32)
// CHECK-DYNAMIC-DECL-IA-DAG: declare dllimport void @__cxa_guard_release(i64*)
// CHECK-DYNAMIC-NODECL-IA-DAG: declare dllimport void @__cxa_guard_release(i64*)
// CHECK-DYNAMIC-IMPORT-IA-DAG: declare dllimport void @__cxa_guard_release(i64*)
// CHECK-DYNAMIC-EXPORT-IA-DAG: declare dllimport void @__cxa_guard_release(i64*)
// CHECK-DYANMIC-IA-DAG: declare dllimport void @_ZSt9terminatev()
-// CHECK-DYNAMIC-NODECL-IA-DAG: declare void @_ZSt9terminatev()
+// CHECK-DYNAMIC-NODECL-IA-DAG: declare dso_local void @_ZSt9terminatev()
// CHECK-DYNAMIC-IMPORT-IA-DAG: declare dllimport void @_ZSt9terminatev()
-// CHECK-DYNAMIC-EXPORT-IA-DAG: declare dllexport void @_ZSt9terminatev()
-
-// CHECK-STATIC-IA-DAG: declare i32 @__cxa_thread_atexit(void (i8*)*, i8*, i8*)
-// CHECK-STATIC-IA-DAG: declare i32 @__cxa_atexit(void (i8*)*, i8*, i8*)
-// CHECK-STATIC-IA-DAG: declare i8* @__cxa_allocate_exception(i32)
-// CHECK-STATIC-IA-DAG: declare void @__cxa_throw(i8*, i8*, i8*)
-// CHECK-STATIC-DECL-IA-DAG: declare i32 @__cxa_guard_acquire(i64*)
-// CHECK-STATIC-NODECL-IA-DAG: declare i32 @__cxa_guard_acquire(i64*)
-// CHECK-STATIC-IMPORT-IA-DAG: declare i32 @__cxa_guard_acquire(i64*)
-// CHECK-STATIC-EXPORT-IA-DAG: declare i32 @__cxa_guard_acquire(i64*)
-// CHECK-IA-DAG: declare noalias i8* @_Znwj(i32)
-// CHECK-STATIC-DECL-IA-DAG: declare void @__cxa_guard_release(i64*)
-// CHECK-STATIC-NODECL-IA-DAG: declare void @__cxa_guard_release(i64*)
-// CHECK-STATIC-IMPORT-IA-DAG: declare void @__cxa_guard_release(i64*)
-// CHECK-STATIC-EXPORT-IA-DAG: declare void @__cxa_guard_release(i64*)
-// CHECK-STATIC-IA-DAG: declare void @_ZSt9terminatev()
-// CHECK-STATIC-NODECL-IA-DAG: declare void @_ZSt9terminatev()
-// CHECK-STATIC-IMPORT-IA-DAG: declare void @_ZSt9terminatev()
-// CHECK-STATIC-EXPORT-IA-DAG: declare dllexport void @_ZSt9terminatev()
+// CHECK-DYNAMIC-EXPORT-IA-DAG: declare dso_local dllexport void @_ZSt9terminatev()
+
+// CHECK-STATIC-IA-DAG: declare dso_local i32 @__cxa_thread_atexit(void (i8*)*, i8*, i8*)
+// CHECK-STATIC-IA-DAG: declare dso_local i32 @__cxa_atexit(void (i8*)*, i8*, i8*)
+// CHECK-STATIC-IA-DAG: declare dso_local i8* @__cxa_allocate_exception(i32)
+// CHECK-STATIC-IA-DAG: declare dso_local void @__cxa_throw(i8*, i8*, i8*)
+// CHECK-STATIC-DECL-IA-DAG: declare dso_local i32 @__cxa_guard_acquire(i64*)
+// CHECK-STATIC-NODECL-IA-DAG: declare dso_local i32 @__cxa_guard_acquire(i64*)
+// CHECK-STATIC-IMPORT-IA-DAG: declare dso_local i32 @__cxa_guard_acquire(i64*)
+// CHECK-STATIC-EXPORT-IA-DAG: declare dso_local i32 @__cxa_guard_acquire(i64*)
+// CHECK-IA-DAG: declare dso_local noalias i8* @_Znwj(i32)
+// CHECK-STATIC-DECL-IA-DAG: declare dso_local void @__cxa_guard_release(i64*)
+// CHECK-STATIC-NODECL-IA-DAG: declare dso_local void @__cxa_guard_release(i64*)
+// CHECK-STATIC-IMPORT-IA-DAG: declare dso_local void @__cxa_guard_release(i64*)
+// CHECK-STATIC-EXPORT-IA-DAG: declare dso_local void @__cxa_guard_release(i64*)
+// CHECK-STATIC-IA-DAG: declare dso_local void @_ZSt9terminatev()
+// CHECK-STATIC-NODECL-IA-DAG: declare dso_local void @_ZSt9terminatev()
+// CHECK-STATIC-IMPORT-IA-DAG: declare dso_local void @_ZSt9terminatev()
+// CHECK-STATIC-EXPORT-IA-DAG: declare dso_local dllexport void @_ZSt9terminatev()
diff --git a/test/CodeGenCXX/sanitize-no-dtor-callback.cpp b/test/CodeGenCXX/sanitize-no-dtor-callback.cpp
index 2c355766216d..afc5382eb464 100644
--- a/test/CodeGenCXX/sanitize-no-dtor-callback.cpp
+++ b/test/CodeGenCXX/sanitize-no-dtor-callback.cpp
@@ -1,8 +1,9 @@
-// Test without the flag -fsanitize-memory-use-after-dtor, to ensure that
+// Test with the flag -fno-sanitize-memory-use-after-dtor, to ensure that
// instrumentation is not erroneously inserted
-// RUN: %clang_cc1 -fsanitize=memory -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -fsanitize=memory -fno-sanitize-memory-use-after-dtor -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s
struct Simple {
+ int x;
~Simple() {}
};
Simple s;
@@ -10,6 +11,7 @@ Simple s;
// CHECK-NOT: call void @__sanitizer_dtor_callback
struct Inlined {
+ int x;
inline ~Inlined() {}
};
Inlined i;
diff --git a/test/CodeGenCXX/sections.cpp b/test/CodeGenCXX/sections.cpp
index c33871a97f56..899bdfa8b9b6 100644
--- a/test/CodeGenCXX/sections.cpp
+++ b/test/CodeGenCXX/sections.cpp
@@ -76,26 +76,26 @@ __declspec(allocate("long_section")) long long_var = 42;
__declspec(allocate("short_section")) short short_var = 42;
}
-//CHECK: @D = global i32 1
-//CHECK: @a = global i32 1, section ".data"
-//CHECK: @b = constant i32 1, section ".my_const"
+//CHECK: @D = dso_local global i32 1
+//CHECK: @a = dso_local global i32 1, section ".data"
+//CHECK: @b = dso_local constant i32 1, section ".my_const"
//CHECK: @[[MYSTR:.*]] = {{.*}} unnamed_addr constant [11 x i8] c"my string!\00"
-//CHECK: @s = global i8* getelementptr inbounds ([11 x i8], [11 x i8]* @[[MYSTR]], i32 0, i32 0), section ".data2"
-//CHECK: @c = global i32 1, section ".my_seg"
-//CHECK: @d = global i32 1, section ".data"
-//CHECK: @e = global i32 0, section ".my_bss"
-//CHECK: @f = global i32 0, section ".c"
-//CHECK: @i = global i32 0
-//CHECK: @TEST1 = global i32 0
-//CHECK: @TEST2 = global i32 0, section ".bss1"
-//CHECK: @TEST3 = global i32 0, section ".bss1"
-//CHECK: @d2 = global i32 1, section ".data"
-//CHECK: @b2 = constant i32 1, section ".my_const"
-//CHECK: @unreferenced = constant i32 0, section "read_flag_section"
-//CHECK: @referenced = constant i32 42, section "read_flag_section"
-//CHECK: @implicitly_read_write = global i32 42, section "no_section_attributes"
-//CHECK: @long_var = global i32 42, section "long_section"
-//CHECK: @short_var = global i16 42, section "short_section"
-//CHECK: define void @g()
-//CHECK: define void @h() {{.*}} section ".my_code"
-//CHECK: define void @h2() {{.*}} section ".my_code"
+//CHECK: @s = dso_local global i8* getelementptr inbounds ([11 x i8], [11 x i8]* @[[MYSTR]], i32 0, i32 0), section ".data2"
+//CHECK: @c = dso_local global i32 1, section ".my_seg"
+//CHECK: @d = dso_local global i32 1, section ".data"
+//CHECK: @e = dso_local global i32 0, section ".my_bss"
+//CHECK: @f = dso_local global i32 0, section ".c"
+//CHECK: @i = dso_local global i32 0
+//CHECK: @TEST1 = dso_local global i32 0
+//CHECK: @TEST2 = dso_local global i32 0, section ".bss1"
+//CHECK: @TEST3 = dso_local global i32 0, section ".bss1"
+//CHECK: @d2 = dso_local global i32 1, section ".data"
+//CHECK: @b2 = dso_local constant i32 1, section ".my_const"
+//CHECK: @unreferenced = dso_local constant i32 0, section "read_flag_section"
+//CHECK: @referenced = dso_local constant i32 42, section "read_flag_section"
+//CHECK: @implicitly_read_write = dso_local global i32 42, section "no_section_attributes"
+//CHECK: @long_var = dso_local global i32 42, section "long_section"
+//CHECK: @short_var = dso_local global i16 42, section "short_section"
+//CHECK: define dso_local void @g()
+//CHECK: define dso_local void @h() {{.*}} section ".my_code"
+//CHECK: define dso_local void @h2() {{.*}} section ".my_code"
diff --git a/test/CodeGenCXX/specialized-static-data-mem-init.cpp b/test/CodeGenCXX/specialized-static-data-mem-init.cpp
index 68799624f26e..d793242be1a0 100644
--- a/test/CodeGenCXX/specialized-static-data-mem-init.cpp
+++ b/test/CodeGenCXX/specialized-static-data-mem-init.cpp
@@ -2,8 +2,8 @@
// rdar: // 8562966
// pr8409
-// CHECK: @_ZN1CIiE11needs_guardE = linkonce_odr global
-// CHECK: @_ZGVN1CIiE11needs_guardE = linkonce_odr global
+// CHECK: @_ZN1CIiE11needs_guardE = linkonce_odr {{(dso_local )?}}global
+// CHECK: @_ZGVN1CIiE11needs_guardE = linkonce_odr {{(dso_local )?}}global
struct K
{
diff --git a/test/CodeGenCXX/split-stacks.cpp b/test/CodeGenCXX/split-stacks.cpp
index 76e1b79b8f1a..2373bcc982f5 100644
--- a/test/CodeGenCXX/split-stacks.cpp
+++ b/test/CodeGenCXX/split-stacks.cpp
@@ -16,18 +16,18 @@ int nosplit() {
return tnosplit<int>();
}
-// CHECK-SEGSTK: define i32 @_Z3foov() [[SS:#[0-9]+]] {
-// CHECK-SEGSTK: define i32 @_Z7nosplitv() [[NSS1:#[0-9]+]] {
-// CHECK-SEGSTK: define linkonce_odr i32 @_Z8tnosplitIiEiv() [[NSS2:#[0-9]+]] comdat {
+// CHECK-SEGSTK: define dso_local i32 @_Z3foov() [[SS:#[0-9]+]] {
+// CHECK-SEGSTK: define dso_local i32 @_Z7nosplitv() [[NSS1:#[0-9]+]] {
+// CHECK-SEGSTK: define linkonce_odr dso_local i32 @_Z8tnosplitIiEiv() [[NSS2:#[0-9]+]] comdat {
// CHECK-SEGSTK-NOT: [[NSS1]] = { {{.*}} "split-stack" {{.*}} }
// CHECK-SEGSTK-NOT: [[NSS2]] = { {{.*}} "split-stack" {{.*}} }
// CHECK-SEGSTK: [[SS]] = { {{.*}} "split-stack" {{.*}} }
// CHECK-SEGSTK-NOT: [[NSS1]] = { {{.*}} "split-stack" {{.*}} }
// CHECK-SEGSTK-NOT: [[NSS2]] = { {{.*}} "split-stack" {{.*}} }
-// CHECK-NOSEGSTK: define i32 @_Z3foov() [[NSS0:#[0-9]+]] {
-// CHECK-NOSEGSTK: define i32 @_Z7nosplitv() [[NSS1:#[0-9]+]] {
-// CHECK-NOSEGSTK: define linkonce_odr i32 @_Z8tnosplitIiEiv() [[NSS2:#[0-9]+]] comdat {
+// CHECK-NOSEGSTK: define dso_local i32 @_Z3foov() [[NSS0:#[0-9]+]] {
+// CHECK-NOSEGSTK: define dso_local i32 @_Z7nosplitv() [[NSS1:#[0-9]+]] {
+// CHECK-NOSEGSTK: define linkonce_odr dso_local i32 @_Z8tnosplitIiEiv() [[NSS2:#[0-9]+]] comdat {
// CHECK-NOSEGSTK-NOT: [[NSS1]] = { {{.*}} "split-stack" {{.*}} }
// CHECK-NOSEGSTK-NOT: [[NSS2]] = { {{.*}} "split-stack" {{.*}} }
// CHECK-NOSEGSTK-NOT: [[NSS3]] = { {{.*}} "split-stack" {{.*}} }
diff --git a/test/CodeGenCXX/stack-reuse-exceptions.cpp b/test/CodeGenCXX/stack-reuse-exceptions.cpp
new file mode 100644
index 000000000000..de870c530504
--- /dev/null
+++ b/test/CodeGenCXX/stack-reuse-exceptions.cpp
@@ -0,0 +1,189 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu %s -o - -emit-llvm -O1 \
+// RUN: -fexceptions -fcxx-exceptions | FileCheck %s
+//
+// We should emit lifetime.ends for these temporaries in both the 'exception'
+// and 'normal' paths in functions.
+//
+// -O1 is necessary to make lifetime markers appear.
+
+struct Large {
+ int cs[32];
+};
+
+Large getLarge();
+
+// Used to ensure we emit invokes.
+struct NontrivialDtor {
+ int i;
+ ~NontrivialDtor();
+};
+
+// CHECK-LABEL: define void @_Z33cleanupsAreEmittedWithoutTryCatchv
+void cleanupsAreEmittedWithoutTryCatch() {
+// CHECK: %[[CLEAN:[^ ]+]] = bitcast %struct.NontrivialDtor* %{{[^ ]+}} to i8*
+// CHECK: call void @llvm.lifetime.start.p0i8({{[^,]+}}, i8* nonnull %[[CLEAN]])
+// CHECK: %[[T1:[^ ]+]] = bitcast %struct.Large* %{{[^ ]+}} to i8*
+// CHECK: call void @llvm.lifetime.start.p0i8({{[^,]+}}, i8* nonnull %[[T1]])
+// CHECK-NEXT: invoke void @_Z8getLargev
+// CHECK-NEXT: to label %[[CONT:[^ ]+]] unwind label %[[LPAD:[^ ]+]]
+//
+// CHECK: [[CONT]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T1]])
+// CHECK: %[[T2:[^ ]+]] = bitcast %struct.Large* %{{[^ ]+}} to i8*
+// CHECK: call void @llvm.lifetime.start.p0i8({{[^,]+}}, i8* nonnull %[[T2]])
+// CHECK-NEXT: invoke void @_Z8getLargev
+// CHECK-NEXT: to label %[[CONT2:[^ ]+]] unwind label %[[LPAD2:.+]]
+//
+// CHECK: [[CONT2]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T2]])
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[CLEAN]])
+// CHECK: ret void
+//
+// CHECK: [[LPAD]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T1]])
+// CHECK: br label %[[EHCLEANUP:.+]]
+//
+// CHECK: [[LPAD2]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T2]])
+// CHECK: br label %[[EHCLEANUP]]
+//
+// CHECK: [[EHCLEANUP]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[CLEAN]])
+
+ NontrivialDtor clean;
+
+ getLarge();
+ getLarge();
+}
+
+// CHECK-LABEL: define void @_Z30cleanupsAreEmittedWithTryCatchv
+void cleanupsAreEmittedWithTryCatch() {
+// CHECK: %[[CLEAN:[^ ]+]] = bitcast %struct.NontrivialDtor* %{{[^ ]+}} to i8*
+// CHECK: call void @llvm.lifetime.start.p0i8({{[^,]+}}, i8* nonnull %[[CLEAN]])
+// CHECK: %[[T1:[^ ]+]] = bitcast %struct.Large* %{{[^ ]+}} to i8*
+// CHECK: call void @llvm.lifetime.start.p0i8({{[^,]+}}, i8* nonnull %[[T1]])
+// CHECK-NEXT: invoke void @_Z8getLargev
+// CHECK-NEXT: to label %[[CONT:[^ ]+]] unwind label %[[LPAD:[^ ]+]]
+//
+// CHECK: [[CONT]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T1]])
+// CHECK: %[[T2:[^ ]+]] = bitcast %struct.Large* %{{[^ ]+}} to i8*
+// CHECK: call void @llvm.lifetime.start.p0i8({{[^,]+}}, i8* nonnull %[[T2]])
+// CHECK-NEXT: invoke void @_Z8getLargev
+// CHECK-NEXT: to label %[[CONT2:[^ ]+]] unwind label %[[LPAD2:.+]]
+//
+// CHECK: [[CONT2]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T2]])
+// CHECK: br label %[[TRY_CONT:.+]]
+//
+// CHECK: [[LPAD]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T1]])
+// CHECK: br label %[[CATCH:.+]]
+//
+// CHECK: [[LPAD2]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T2]])
+// CHECK: br label %[[CATCH]]
+//
+// CHECK: [[CATCH]]:
+// CHECK-NOT: call void @llvm.lifetime
+// CHECK: invoke void
+// CHECK-NEXT: to label %[[TRY_CONT]] unwind label %[[OUTER_LPAD:.+]]
+//
+// CHECK: [[TRY_CONT]]:
+// CHECK: %[[T_OUTER:[^ ]+]] = bitcast %struct.Large* %{{[^ ]+}} to i8*
+// CHECK: call void @llvm.lifetime.start.p0i8({{[^,]+}}, i8* nonnull %[[T_OUTER]])
+// CHECK-NEXT: invoke void @_Z8getLargev
+// CHECK-NEXT: to label %[[OUTER_CONT:[^ ]+]] unwind label %[[OUTER_LPAD2:.+]]
+//
+// CHECK: [[OUTER_CONT]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T_OUTER]])
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[CLEAN]])
+// CHECK: ret void
+//
+// CHECK: [[OUTER_LPAD]]:
+// CHECK-NOT: call void @llvm.lifetime
+// CHECK: br label %[[EHCLEANUP:.+]]
+//
+// CHECK: [[OUTER_LPAD2]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T_OUTER]])
+// CHECK: br label %[[EHCLEANUP]]
+//
+// CHECK: [[EHCLEANUP]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[CLEAN]])
+
+ NontrivialDtor clean;
+
+ try {
+ getLarge();
+ getLarge();
+ } catch (...) {}
+
+ getLarge();
+}
+
+// CHECK-LABEL: define void @_Z39cleanupInTryHappensBeforeCleanupInCatchv
+void cleanupInTryHappensBeforeCleanupInCatch() {
+// CHECK: %[[T1:[^ ]+]] = bitcast %struct.Large* %{{[^ ]+}} to i8*
+// CHECK: call void @llvm.lifetime.start.p0i8({{[^,]+}}, i8* nonnull %[[T1]])
+// CHECK-NEXT: invoke void @_Z8getLargev
+// CHECK-NEXT: to label %[[CONT:[^ ]+]] unwind label %[[LPAD:[^ ]+]]
+//
+// CHECK: [[CONT]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T1]])
+// CHECK: br label %[[TRY_CONT]]
+//
+// CHECK: [[LPAD]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T1]])
+// CHECK: br i1 {{[^,]+}}, label %[[CATCH_INT_MATCH:[^,]+]], label %[[CATCH_ALL:.+]]
+//
+// CHECK: [[CATCH_INT_MATCH]]:
+// CHECK: %[[T2:[^ ]+]] = bitcast %struct.Large* %{{[^ ]+}} to i8*
+// CHECK: call void @llvm.lifetime.start.p0i8({{[^,]+}}, i8* nonnull %[[T2]])
+// CHECK-NEXT: invoke void @_Z8getLargev
+// CHECK-NEXT: to label %[[CATCH_INT_CONT:[^ ]+]] unwind label %[[CATCH_INT_LPAD:[^ ]+]]
+//
+// CHECK: [[CATCH_INT_CONT]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T2]])
+// CHECK: br label %[[TRY_CONT]]
+//
+// CHECK: [[TRY_CONT]]:
+// CHECK: ret void
+//
+// CHECK: [[CATCH_ALL]]:
+// CHECK: %[[T3:[^ ]+]] = bitcast %struct.Large* %{{[^ ]+}} to i8*
+// CHECK: call void @llvm.lifetime.start.p0i8({{[^,]+}}, i8* nonnull %[[T3]])
+// CHECK-NEXT: invoke void @_Z8getLargev
+// CHECK-NEXT: to label %[[CATCH_ALL_CONT:[^ ]+]] unwind label %[[CATCH_ALL_LPAD:[^ ]+]]
+//
+// CHECK: [[CATCH_ALL_CONT]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T3]])
+// CHECK: br label %[[TRY_CONT]]
+//
+// CHECK: [[CATCH_ALL_LPAD]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T3]])
+//
+// CHECK: [[CATCH_INT_LPAD]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T2]])
+// CHECK-NOT: call void @llvm.lifetime
+
+ try {
+ getLarge();
+ } catch (const int &) {
+ getLarge();
+ } catch (...) {
+ getLarge();
+ }
+}
+
+// FIXME: We don't currently emit lifetime markers for aggregate by-value
+// temporaries (e.g. given a function `Large combine(Large, Large);`
+// combine(getLarge(), getLarge()) "leaks" two `Large`s). We probably should. We
+// also don't emit markers for things like:
+//
+// {
+// Large L = getLarge();
+// combine(L, L);
+// }
+//
+// Though this arguably isn't as bad, since we pass a pointer to `L` as one of
+// the two args.
diff --git a/test/CodeGenCXX/stack-reuse-miscompile.cpp b/test/CodeGenCXX/stack-reuse-miscompile.cpp
index 3b860a573955..4e824d94f510 100644
--- a/test/CodeGenCXX/stack-reuse-miscompile.cpp
+++ b/test/CodeGenCXX/stack-reuse-miscompile.cpp
@@ -1,8 +1,4 @@
-// RUN: %clang_cc1 -triple armv7l-unknown-linux-gnueabihf -emit-llvm -O1 -disable-llvm-passes -std=c++03 %s -o - | FileCheck %s
-
-// This test should not to generate llvm.lifetime.start/llvm.lifetime.end for
-// f function because all temporary objects in this function are used for the
-// final result
+// RUN: %clang_cc1 -triple armv7l-unknown-linux-gnueabihf -emit-llvm -O1 -disable-llvm-passes -std=c++03 %s -o - | FileCheck %s --implicit-check-not=llvm.lifetime
class S {
char *ptr;
@@ -23,14 +19,36 @@ public:
const char * f(S s)
{
+// It's essential that the lifetimes of all three T temporaries here are
+// overlapping. They must all remain alive through the call to str().
+//
// CHECK: [[T1:%.*]] = alloca %class.T, align 4
// CHECK: [[T2:%.*]] = alloca %class.T, align 4
// CHECK: [[T3:%.*]] = alloca %class.T, align 4
-// CHECK: [[T4:%.*]] = call %class.T* @_ZN1TC1EPKc(%class.T* [[T1]], i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str, i32 0, i32 0))
-// CHECK: [[T5:%.*]] = call %class.T* @_ZN1TC1E1S(%class.T* [[T2]], [2 x i32] %{{.*}})
-// CHECK: call void @_ZNK1T6concatERKS_(%class.T* sret [[T3]], %class.T* [[T1]], %class.T* dereferenceable(16) [[T2]])
-// CHECK: [[T6:%.*]] = call i8* @_ZNK1T3strEv(%class.T* [[T3]])
+//
+// FIXME: We could defer starting the lifetime of the return object of concat
+// until the call.
+// CHECK: [[T1i8:%.*]] = bitcast %class.T* [[T1]] to i8*
+// CHECK: call void @llvm.lifetime.start.p0i8(i64 16, i8* [[T1i8]])
+//
+// CHECK: [[T2i8:%.*]] = bitcast %class.T* [[T2]] to i8*
+// CHECK: call void @llvm.lifetime.start.p0i8(i64 16, i8* [[T2i8]])
+// CHECK: [[T4:%.*]] = call %class.T* @_ZN1TC1EPKc(%class.T* [[T2]], i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str, i32 0, i32 0))
+//
+// CHECK: [[T3i8:%.*]] = bitcast %class.T* [[T3]] to i8*
+// CHECK: call void @llvm.lifetime.start.p0i8(i64 16, i8* [[T3i8]])
+// CHECK: [[T5:%.*]] = call %class.T* @_ZN1TC1E1S(%class.T* [[T3]], [2 x i32] %{{.*}})
+//
+// CHECK: call void @_ZNK1T6concatERKS_(%class.T* sret [[T1]], %class.T* [[T2]], %class.T* dereferenceable(16) [[T3]])
+// CHECK: [[T6:%.*]] = call i8* @_ZNK1T3strEv(%class.T* [[T1]])
+//
+// CHECK: call void @llvm.lifetime.end.p0i8(
+// CHECK: call void @llvm.lifetime.end.p0i8(
+// CHECK: call void @llvm.lifetime.end.p0i8(
// CHECK: ret i8* [[T6]]
return T("[").concat(T(s)).str();
}
+
+// CHECK: declare {{.*}}llvm.lifetime.start
+// CHECK: declare {{.*}}llvm.lifetime.end
diff --git a/test/CodeGenCXX/strict-vtable-pointers.cpp b/test/CodeGenCXX/strict-vtable-pointers.cpp
index c45e7a60fa8f..098c77989506 100644
--- a/test/CodeGenCXX/strict-vtable-pointers.cpp
+++ b/test/CodeGenCXX/strict-vtable-pointers.cpp
@@ -5,7 +5,8 @@
// RUN: FileCheck --check-prefix=CHECK-LINK-REQ %s < %t.ll
typedef __typeof__(sizeof(0)) size_t;
-void *operator new(size_t, void*) throw();
+void *operator new(size_t, void *) throw();
+using uintptr_t = unsigned long long;
struct NotTrivialDtor {
~NotTrivialDtor();
@@ -17,7 +18,7 @@ struct DynamicBase1 {
};
struct DynamicDerived : DynamicBase1 {
- void foo();
+ void foo() override;
};
struct DynamicBase2 {
@@ -28,8 +29,8 @@ struct DynamicBase2 {
};
struct DynamicDerivedMultiple : DynamicBase1, DynamicBase2 {
- virtual void foo();
- virtual void bar();
+ void foo() override;
+ void bar() override;
};
struct StaticBase {
@@ -47,13 +48,12 @@ struct DynamicFromVirtualStatic1 : virtual StaticBase {
struct DynamicFromVirtualStatic2 : virtual StaticBase {
};
-struct DynamicFrom2Virtuals :
- DynamicFromVirtualStatic1,
- DynamicFromVirtualStatic2 {
+struct DynamicFrom2Virtuals : DynamicFromVirtualStatic1,
+ DynamicFromVirtualStatic2 {
};
// CHECK-NEW-LABEL: define void @_Z12LocalObjectsv()
-// CHECK-NEW-NOT: @llvm.invariant.group.barrier.p0i8(
+// CHECK-NEW-NOT: @llvm.launder.invariant.group.p0i8(
// CHECK-NEW-LABEL: {{^}}}
void LocalObjects() {
DynamicBase1 DB;
@@ -81,20 +81,19 @@ void LocalObjects() {
struct DynamicFromVirtualStatic1;
// CHECK-CTORS-LABEL: define linkonce_odr void @_ZN25DynamicFromVirtualStatic1C1Ev
-// CHECK-CTORS-NOT: @llvm.invariant.group.barrier.p0i8(
+// CHECK-CTORS-NOT: @llvm.launder.invariant.group.p0i8(
// CHECK-CTORS-LABEL: {{^}}}
struct DynamicFrom2Virtuals;
// CHECK-CTORS-LABEL: define linkonce_odr void @_ZN20DynamicFrom2VirtualsC1Ev
-// CHECK-CTORS: call i8* @llvm.invariant.group.barrier.p0i8(
+// CHECK-CTORS: call i8* @llvm.launder.invariant.group.p0i8(
// CHECK-CTORS-LABEL: {{^}}}
-
// CHECK-NEW-LABEL: define void @_Z9Pointers1v()
-// CHECK-NEW-NOT: @llvm.invariant.group.barrier.p0i8(
+// CHECK-NEW-NOT: @llvm.launder.invariant.group.p0i8(
// CHECK-NEW-LABEL: call void @_ZN12DynamicBase1C1Ev(
-// CHECK-NEW: %[[THIS3:.*]] = call i8* @llvm.invariant.group.barrier.p0i8(i8* %[[THIS2:.*]])
+// CHECK-NEW: %[[THIS3:.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* %[[THIS2:.*]])
// CHECK-NEW: %[[THIS4:.*]] = bitcast i8* %[[THIS3]] to %[[DynamicDerived:.*]]*
// CHECK-NEW: call void @_ZN14DynamicDerivedC1Ev(%[[DynamicDerived:.*]]* %[[THIS4]])
// CHECK-NEW-LABEL: {{^}}}
@@ -109,9 +108,9 @@ void Pointers1() {
// CHECK-NEW-LABEL: define void @_Z14HackingObjectsv()
// CHECK-NEW: call void @_ZN12DynamicBase1C1Ev
-// CHECK-NEW: call i8* @llvm.invariant.group.barrier.p0i8(
+// CHECK-NEW: call i8* @llvm.launder.invariant.group.p0i8(
// CHECK-NEW: call void @_ZN14DynamicDerivedC1Ev(
-// CHECK-NEW: call i8* @llvm.invariant.group.barrier.p0i8(
+// CHECK-NEW: call i8* @llvm.launder.invariant.group.p0i8(
// CHECK-NEW: call void @_ZN12DynamicBase1C1Ev(
// CHECK-NEW-LABEL: {{^}}}
void HackingObjects() {
@@ -131,16 +130,15 @@ void HackingObjects() {
/*** Testing Constructors ***/
struct DynamicBase1;
// CHECK-CTORS-LABEL: define linkonce_odr void @_ZN12DynamicBase1C2Ev(
-// CHECK-CTORS-NOT: call i8* @llvm.invariant.group.barrier.p0i8(
+// CHECK-CTORS-NOT: call i8* @llvm.launder.invariant.group.p0i8(
// CHECK-CTORS-LABEL: {{^}}}
-
struct DynamicDerived;
// CHECK-CTORS-LABEL: define linkonce_odr void @_ZN14DynamicDerivedC2Ev(
// CHECK-CTORS: %[[THIS0:.*]] = load %[[DynamicDerived:.*]]*, %[[DynamicDerived]]** {{.*}}
// CHECK-CTORS: %[[THIS1:.*]] = bitcast %[[DynamicDerived:.*]]* %[[THIS0]] to i8*
-// CHECK-CTORS: %[[THIS2:.*]] = call i8* @llvm.invariant.group.barrier.p0i8(i8* %[[THIS1:.*]])
+// CHECK-CTORS: %[[THIS2:.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* %[[THIS1:.*]])
// CHECK-CTORS: %[[THIS3:.*]] = bitcast i8* %[[THIS2]] to %[[DynamicDerived]]*
// CHECK-CTORS: %[[THIS4:.*]] = bitcast %[[DynamicDerived]]* %[[THIS3]] to %[[DynamicBase:.*]]*
// CHECK-CTORS: call void @_ZN12DynamicBase1C2Ev(%[[DynamicBase]]* %[[THIS4]])
@@ -154,16 +152,15 @@ struct DynamicDerivedMultiple;
// CHECK-CTORS: %[[THIS0:.*]] = load %[[CLASS:.*]]*, %[[CLASS]]** {{.*}}
// CHECK-CTORS: %[[THIS1:.*]] = bitcast %[[CLASS:.*]]* %[[THIS0]] to i8*
-// CHECK-CTORS: %[[THIS2:.*]] = call i8* @llvm.invariant.group.barrier.p0i8(i8* %[[THIS1]])
+// CHECK-CTORS: %[[THIS2:.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* %[[THIS1]])
// CHECK-CTORS: %[[THIS3:.*]] = bitcast i8* %[[THIS2]] to %[[CLASS]]*
// CHECK-CTORS: %[[THIS4:.*]] = bitcast %[[CLASS]]* %[[THIS3]] to %[[BASE_CLASS:.*]]*
// CHECK-CTORS: call void @_ZN12DynamicBase1C2Ev(%[[BASE_CLASS]]* %[[THIS4]])
-// CHECK-CTORS: call i8* @llvm.invariant.group.barrier.p0i8(
+// CHECK-CTORS: call i8* @llvm.launder.invariant.group.p0i8(
// CHECK-CTORS: call void @_ZN12DynamicBase2C2Ev(
-// CHECK-CTORS-NOT: @llvm.invariant.group.barrier.p0i8
-
+// CHECK-CTORS-NOT: @llvm.launder.invariant.group.p0i8
// CHECK-CTORS: %[[THIS10:.*]] = bitcast %struct.DynamicDerivedMultiple* %[[THIS0]] to i32 (...)***
// CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i32 0, inrange i32 0, i32 2) {{.*}} %[[THIS10]]
@@ -171,20 +168,20 @@ struct DynamicDerivedMultiple;
// CHECK-CTORS: %[[THIS_ADD:.*]] = getelementptr inbounds i8, i8* %[[THIS11]], i64 16
// CHECK-CTORS: %[[THIS12:.*]] = bitcast i8* %[[THIS_ADD]] to i32 (...)***
-
// CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i32 0, inrange i32 1, i32 2) {{.*}} %[[THIS12]]
// CHECK-CTORS-LABEL: {{^}}}
struct DynamicFromStatic;
// CHECK-CTORS-LABEL: define linkonce_odr void @_ZN17DynamicFromStaticC2Ev(
-// CHECK-CTORS-NOT: @llvm.invariant.group.barrier.p0i8(
+// CHECK-CTORS-NOT: @llvm.launder.invariant.group.p0i8(
// CHECK-CTORS-LABEL: {{^}}}
struct A {
virtual void foo();
+ int m;
};
struct B : A {
- virtual void foo();
+ void foo() override;
};
union U {
@@ -206,15 +203,15 @@ void g2(A *a) {
void UnionsBarriers(U *u) {
// CHECK-NEW: call void @_Z9changeToBP1U(
changeToB(u);
- // CHECK-NEW: call i8* @llvm.invariant.group.barrier.p0i8(i8*
+ // CHECK-NEW: call i8* @llvm.launder.invariant.group.p0i8(i8*
// CHECK-NEW: call void @_Z2g2P1A(%struct.A*
g2(&u->b);
- // CHECK-NEW: call void @_Z9changeToAP1U(%union.U*
+ // CHECK-NEW: call void @_Z9changeToAP1U(%union.U*
changeToA(u);
- // CHECK-NEW: call i8* @llvm.invariant.group.barrier.p0i8(i8*
+ // CHECK-NEW: call i8* @llvm.launder.invariant.group.p0i8(i8*
// call void @_Z2g2P1A(%struct.A* %a)
g2(&u->a);
- // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier.p0i8(i8*
+ // CHECK-NEW-NOT: call i8* @llvm.launder.invariant.group.p0i8(i8*
}
struct HoldingVirtuals {
@@ -233,10 +230,10 @@ void take(AnotherEmpty &);
// CHECK-NEW-LABEL: noBarriers
void noBarriers(NoVptrs &noVptrs) {
- // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier.p0i8(i8*
+ // CHECK-NEW-NOT: call i8* @llvm.launder.invariant.group.p0i8(i8*
// CHECK-NEW: 42
noVptrs.a += 42;
- // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier.p0i8(i8*
+ // CHECK-NEW-NOT: call i8* @llvm.launder.invariant.group.p0i8(i8*
// CHECK-NEW: call void @_Z4takeR12AnotherEmpty(
take(noVptrs.empty);
}
@@ -249,10 +246,10 @@ void take(HoldingVirtuals &);
// CHECK-NEW-LABEL: define void @_Z15UnionsBarriers2R2U2
void UnionsBarriers2(U2 &u) {
- // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier.p0i8(i8*
+ // CHECK-NEW-NOT: call i8* @llvm.launder.invariant.group.p0i8(i8*
// CHECK-NEW: 42
u.z += 42;
- // CHECK-NEW: call i8* @llvm.invariant.group.barrier.p0i8(i8*
+ // CHECK-NEW: call i8* @llvm.launder.invariant.group.p0i8(i8*
// CHECK-NEW: call void @_Z4takeR15HoldingVirtuals(
take(u.h);
}
@@ -279,54 +276,318 @@ void take(VirtualInVBase &);
void take(VirtualInheritance &);
void UnionsBarrier3(U3 &u) {
- // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier.p0i8(i8*
+ // CHECK-NEW-NOT: call i8* @llvm.launder.invariant.group.p0i8(i8*
// CHECK-NEW: 42
u.z += 42;
- // CHECK-NEW: call i8* @llvm.invariant.group.barrier.p0i8(i8*
+ // CHECK-NEW: call i8* @llvm.launder.invariant.group.p0i8(i8*
// CHECK-NEW: call void @_Z4takeR13VirtualInBase(
take(u.v1);
- // CHECK-NEW: call i8* @llvm.invariant.group.barrier.p0i8(i8*
+ // CHECK-NEW: call i8* @llvm.launder.invariant.group.p0i8(i8*
// CHECK-NEW: call void @_Z4takeR13VirtualInBase(
take(u.v2);
- // CHECK-NEW: call i8* @llvm.invariant.group.barrier.p0i8(i8*
+ // CHECK-NEW: call i8* @llvm.launder.invariant.group.p0i8(i8*
// CHECK-NEW: call void @_Z4takeR18VirtualInheritance(
take(u.v3);
}
+// CHECK-NEW-LABEL: define void @_Z7comparev()
+void compare() {
+ A *a = new A;
+ a->foo();
+ // CHECK-NEW: call i8* @llvm.launder.invariant.group.p0i8(i8*
+ A *b = new (a) B;
+
+ // CHECK-NEW: %[[a:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8*
+ // CHECK-NEW: %[[a2:.*]] = bitcast i8* %[[a]] to %struct.A*
+ // CHECK-NEW: %[[b:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8*
+ // CHECK-NEW: %[[b2:.*]] = bitcast i8* %[[b]] to %struct.A*
+ // CHECK-NEW: %cmp = icmp eq %struct.A* %[[a2]], %[[b2]]
+ if (a == b)
+ b->foo();
+}
+
+// CHECK-NEW-LABEL: compare2
+bool compare2(A *a, A *a2) {
+ // CHECK-NEW: %[[a:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8*
+ // CHECK-NEW: %[[a2:.*]] = bitcast i8* %[[a]] to %struct.A*
+ // CHECK-NEW: %[[b:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8*
+ // CHECK-NEW: %[[b2:.*]] = bitcast i8* %[[b]] to %struct.A*
+ // CHECK-NEW: %cmp = icmp ult %struct.A* %[[a2]], %[[b2]]
+ return a < a2;
+}
+// CHECK-NEW-LABEL: compareIntPointers
+bool compareIntPointers(int *a, int *b) {
+ // CHECK-NEW-NOT: call i8* @llvm.strip.invariant.group
+ return a == b;
+}
+
+struct HoldingOtherVirtuals {
+ B b;
+};
+
+// There is no need to add barriers for comparision of pointer to classes
+// that are not dynamic.
+// CHECK-NEW-LABEL: compare5
+bool compare5(HoldingOtherVirtuals *a, HoldingOtherVirtuals *b) {
+ // CHECK-NEW-NOT: call i8* @llvm.strip.invariant.group
+ return a == b;
+}
+// CHECK-NEW-LABEL: compareNull
+bool compareNull(A *a) {
+ // CHECK-NEW-NOT: call i8* @llvm.strip.invariant.group
+
+ if (a != nullptr)
+ return false;
+ if (!a)
+ return false;
+ return a == nullptr;
+}
+
+struct X;
+// We have to also introduce the barriers if comparing pointers to incomplete
+// objects
+// CHECK-NEW-LABEL: define zeroext i1 @_Z8compare4P1XS0_
+bool compare4(X *x, X *x2) {
+ // CHECK-NEW: %[[x:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8*
+ // CHECK-NEW: %[[xp:.*]] = bitcast i8* %[[x]] to %struct.X*
+ // CHECK-NEW: %[[x2:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8*
+ // CHECK-NEW: %[[x2p:.*]] = bitcast i8* %[[x2]] to %struct.X*
+ // CHECK-NEW: %cmp = icmp eq %struct.X* %[[xp]], %[[x2p]]
+ return x == x2;
+}
+
+// CHECK-NEW-LABEL: define void @_Z7member1P20HoldingOtherVirtuals(
+void member1(HoldingOtherVirtuals *p) {
+
+ // CHECK-NEW-NOT: call i8* @llvm.strip.invariant.group.p0i8(
+ (void)p->b;
+}
+
+// CHECK-NEW-LABEL: member2
+void member2(A *a) {
+ // CHECK-NEW: call i8* @llvm.strip.invariant.group.p0i8
+ (void)a->m;
+}
+
+// Check if from comparison of addresses of member we can't infer the equality
+// of ap and bp.
+// CHECK-NEW-LABEL: @_Z18testCompareMembersv(
+void testCompareMembers() {
+ // CHECK-NEW: [[AP:%.*]] = alloca %struct.A*
+ // CHECK-NEW: [[APM:%.*]] = alloca i32*
+ // CHECK-NEW: [[BP:%.*]] = alloca %struct.B*
+ // CHECK-NEW: [[BPM:%.*]] = alloca i32*
+
+ A *ap = new A;
+ // CHECK-NEW: call void %{{.*}}(%struct.A* %{{.*}})
+ ap->foo();
+ // CHECK-NEW: [[TMP7:%.*]] = load %struct.A*, %struct.A** [[AP]]
+ // CHECK-NEW: [[TMP8:%.*]] = bitcast %struct.A* [[TMP7]] to i8*
+ // CHECK-NEW: [[TMP9:%.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* [[TMP8]])
+ // CHECK-NEW: [[TMP10:%.*]] = bitcast i8* [[TMP9]] to %struct.A*
+ // CHECK-NEW: [[M:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], %struct.A* [[TMP10]], i32 0, i32 1
+ // CHECK-NEW: store i32* [[M]], i32** [[APM]]
+ int *const apm = &ap->m;
+
+ B *bp = new (ap) B;
+
+ // CHECK-NEW: [[TMP20:%.*]] = load %struct.B*, %struct.B** [[BP]]
+ // CHECK-NEW: [[TMP21:%.*]] = bitcast %struct.B* [[TMP20]] to %struct.A*
+ // CHECK-NEW: [[TMP22:%.*]] = bitcast %struct.A* [[TMP21]] to i8*
+ // CHECK-NEW: [[TMP23:%.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* [[TMP22]])
+ // CHECK-NEW: [[TMP24:%.*]] = bitcast i8* [[TMP23]] to %struct.A*
+ // CHECK-NEW: [[M4:%.*]] = getelementptr inbounds [[STRUCT_A]], %struct.A* [[TMP24]], i32 0, i32 1
+ // CHECK-NEW: store i32* [[M4]], i32** [[BPM]]
+ int *const bpm = &bp->m;
+
+ // CHECK-NEW: [[TMP25:%.*]] = load i32*, i32** [[APM]]
+ // CHECK-NEW: [[TMP26:%.*]] = load i32*, i32** [[BPM]]
+ // CHECK-NEW-NOT: strip.invariant.group
+ // CHECK-NEW-NOT: launder.invariant.group
+ // CHECK-NEW: [[CMP:%.*]] = icmp eq i32* [[TMP25]], [[TMP26]]
+ if (apm == bpm) {
+ bp->foo();
+ }
+}
+
+// CHECK-NEW-LABEL: define void @_Z9testCast1P1A(%struct.A*
+void testCast1(A *a) {
+ // Here we get rid of dynamic info
+ // CHECK-NEW: call i8* @llvm.strip.invariant.group
+ auto *v = (void *)a;
+
+ // CHECK-NEW: call i8* @llvm.strip.invariant.group
+ auto i2 = (uintptr_t)a;
+ (void)i2;
+
+ // CHECK-NEW-NOT: @llvm.strip.invariant.group
+ // CHECK-NEW-NOT: @llvm.launder.invariant.group
+
+ // The information is already stripped
+ auto i = (uintptr_t)v;
+}
+
+struct Incomplete;
+// CHECK-NEW-LABEL: define void @_Z9testCast2P10Incomplete(%struct.Incomplete*
+void testCast2(Incomplete *I) {
+ // Here we get rid of potential dynamic info
+ // CHECK-NEW: call i8* @llvm.strip.invariant.group
+ auto *v = (void *)I;
+
+ // CHECK-NEW: call i8* @llvm.strip.invariant.group
+ auto i2 = (uintptr_t)I;
+ (void)i2;
+
+ // CHECK-NEW-NOT: @llvm.strip.invariant.group
+ // CHECK-NEW-NOT: @llvm.launder.invariant.group
+
+ // The information is already stripped
+ auto i = (uintptr_t)v;
+}
+
+// CHECK-NEW-LABEL: define void @_Z9testCast3y(
+void testCast3(uintptr_t i) {
+ // CHECK-NEW-NOT: @llvm.strip.invariant.group
+ // CHECK-NEW: @llvm.launder.invariant.group
+ A *a3 = (A *)i;
+ (void)a3;
+
+ auto *v2 = (void *)i;
+
+ // CHECK-NEW: @llvm.launder.invariant.group
+ A *a2 = (A *)v2;
+ (void)a2;
+
+ // CHECK-NEW-NOT: @llvm.launder.invariant.group
+ auto *v3 = (void *)i;
+ (void)v3;
+}
+
+// CHECK-NEW-LABEL: define void @_Z9testCast4y(
+void testCast4(uintptr_t i) {
+ // CHECK-NEW-NOT: @llvm.strip.invariant.group
+ // CHECK-NEW: @llvm.launder.invariant.group
+ auto *a3 = (Incomplete *)i;
+ (void)a3;
+
+ // CHECK-NEW: @llvm.launder.invariant.group
+ auto *v2 = (void *)i;
+ // CHECK-NEW-NOT: @llvm.launder.invariant.group
+ auto *a2 = (Incomplete *)v2;
+ (void)a2;
+}
+
+// CHECK-NEW-LABEL: define void @_Z9testCast5P1B(
+void testCast5(B *b) {
+ // CHECK-NEW-NOT: @llvm.strip.invariant.group
+ // CHECK-NEW-NOT: @llvm.launder.invariant.group
+ A *a = b;
+ (void)a;
+
+ auto *b2 = (B *)a;
+ (void)b2;
+}
+
+// CHECK-NEW-LABEL: define void @_Z9testCast6P1A(
+void testCast6(A *a) {
+
+ // CHECK-NEW: @llvm.strip.invariant.group
+ auto *I = (Incomplete *)a;
+ (void)I;
+ // CHECK-NEW: @llvm.launder.invariant.group
+ auto *a2 = (A *)I;
+ (void)a2;
+
+ // CHECK-NEW: @llvm.strip.invariant.group
+ auto *E = (Empty *)a;
+ (void)E;
+
+ // CHECK-NEW: @llvm.launder.invariant.group
+ auto *a3 = (A *)E;
+ (void)a3;
+
+ // CHECK-NEW-NOT: @llvm.strip.invariant.group
+ auto i = (uintptr_t)E;
+ (void)i;
+}
+
+class Incomplete2;
+// CHECK-NEW-LABEL: define void @_Z9testCast7P10Incomplete(
+void testCast7(Incomplete *I) {
+ // CHECK-NEW-NOT: @llvm.strip.invariant.group
+
+ // Incomplete2 could be dynamic where Incomplete may not be dynamic, thus
+ // launder is needed. We don't strip firstly because launder is sufficient.
+
+ // CHECK-NEW: @llvm.launder.invariant.group
+ auto *I2 = (Incomplete2 *)I;
+ (void)I2;
+ // CHECK-NEW-LABEL: ret void
+}
+
+template <typename Base>
+struct PossiblyDerivingFromDynamicBase : Base {
+};
+
+// CHECK-NEW-LABEL: define void @_Z9testCast8P10Incomplete(
+void testCast8(Incomplete *I) {
+ // CHECK-NEW-NOT: @llvm.strip.invariant.group
+ // CHECK-NEW: @llvm.launder.invariant.group
+ auto *P = (PossiblyDerivingFromDynamicBase<Incomplete> *)I;
+ (void)P;
+
+ // CHECK-NEW: @llvm.launder.invariant.group
+ auto *P2 = (PossiblyDerivingFromDynamicBase<Empty> *)I;
+ (void)P2;
+
+ // CHECK-NEW: @llvm.launder.invariant.group
+ auto *P3 = (PossiblyDerivingFromDynamicBase<A> *)I;
+ (void)P3;
+
+ // CHECK-NEW-NOT: @llvm.launder.invariant.group
+ auto *a3 = (A *)P3;
+
+ // CHECK-NEW-LABEL: ret void
+}
+
+// CHECK-NEW-LABEL: define void @_Z9testCast9
+void testCast9(PossiblyDerivingFromDynamicBase<Incomplete> *P) {
+ // CHECK-NEW: @llvm.strip.invariant.group
+ auto *V = (void *)P;
+
+ // CHECK-NEW-LABEL: ret void
+}
+
/** DTORS **/
// CHECK-DTORS-LABEL: define linkonce_odr void @_ZN10StaticBaseD2Ev(
-// CHECK-DTORS-NOT: call i8* @llvm.invariant.group.barrier.p0i8(
+// CHECK-DTORS-NOT: call i8* @llvm.launder.invariant.group.p0i8(
// CHECK-DTORS-LABEL: {{^}}}
-
// CHECK-DTORS-LABEL: define linkonce_odr void @_ZN25DynamicFromVirtualStatic2D2Ev(
// CHECK-DTORS-NOT: invariant.barrier
// CHECK-DTORS-LABEL: {{^}}}
// CHECK-DTORS-LABEL: define linkonce_odr void @_ZN17DynamicFromStaticD2Ev
-// CHECK-DTORS-NOT: call i8* @llvm.invariant.group.barrier.p0i8(
+// CHECK-DTORS-NOT: call i8* @llvm.launder.invariant.group.p0i8(
// CHECK-DTORS-LABEL: {{^}}}
-
// CHECK-DTORS-LABEL: define linkonce_odr void @_ZN22DynamicDerivedMultipleD2Ev(
// CHECK-DTORS-LABEL: define linkonce_odr void @_ZN12DynamicBase2D2Ev(
-// CHECK-DTORS: call i8* @llvm.invariant.group.barrier.p0i8(
+// CHECK-DTORS: call i8* @llvm.launder.invariant.group.p0i8(
// CHECK-DTORS-LABEL: {{^}}}
// CHECK-DTORS-LABEL: define linkonce_odr void @_ZN12DynamicBase1D2Ev
-// CHECK-DTORS: call i8* @llvm.invariant.group.barrier.p0i8(
+// CHECK-DTORS: call i8* @llvm.launder.invariant.group.p0i8(
// CHECK-DTORS-LABEL: {{^}}}
// CHECK-DTORS-LABEL: define linkonce_odr void @_ZN14DynamicDerivedD2Ev
-// CHECK-DTORS-NOT: call i8* @llvm.invariant.group.barrier.p0i8(
+// CHECK-DTORS-NOT: call i8* @llvm.launder.invariant.group.p0i8(
// CHECK-DTORS-LABEL: {{^}}}
-
// CHECK-LINK-REQ: !llvm.module.flags = !{![[FIRST:[0-9]+]], ![[SEC:[0-9]+]]{{.*}}}
// CHECK-LINK-REQ: ![[FIRST]] = !{i32 1, !"StrictVTablePointers", i32 1}
// CHECK-LINK-REQ: ![[SEC]] = !{i32 3, !"StrictVTablePointersRequirement", ![[META:.*]]}
// CHECK-LINK-REQ: ![[META]] = !{!"StrictVTablePointers", i32 1}
-
diff --git a/test/CodeGenCXX/tail-padding.cpp b/test/CodeGenCXX/tail-padding.cpp
new file mode 100644
index 000000000000..b8b9e4ccf9a7
--- /dev/null
+++ b/test/CodeGenCXX/tail-padding.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s
+
+// PR36992
+namespace Implicit {
+ struct A { char c; A(const A&); };
+ struct B { int n; char c[3]; ~B(); };
+ struct C : B, virtual A {};
+ static_assert(sizeof(C) == sizeof(void*) + 8);
+ C f(C c) { return c; }
+
+ // CHECK: define {{.*}} @_ZN8Implicit1CC1EOS0_
+ // CHECK: call {{.*}} @_ZN8Implicit1AC2ERKS0_(
+ // Note: this must memcpy 7 bytes, not 8, to avoid trampling over the virtual base class.
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{32|64}}(i8* {{.*}}, i8* {{.*}}, i{{32|64}} 7, i1 false)
+ // CHECK: store i32 {{.*}} @_ZTVN8Implicit1CE
+}
+
+namespace InitWithinNVSize {
+ // This is the same as the previous test, except that the A base lies
+ // entirely within the nvsize of C. This makes it valid to copy at the
+ // full width.
+ struct A { char c; A(const A&); };
+ struct B { int n; char c[3]; ~B(); };
+ struct C : B, virtual A { char x; };
+ static_assert(sizeof(C) > sizeof(void*) + 8);
+ C f(C c) { return c; }
+
+ // CHECK: define {{.*}} @_ZN16InitWithinNVSize1CC1EOS0_
+ // CHECK: call {{.*}} @_ZN16InitWithinNVSize1AC2ERKS0_(
+ // This copies over the 'C::x' member, but that's OK because we've not initialized it yet.
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{32|64}}(i8* {{.*}}, i8* {{.*}}, i{{32|64}} 8, i1 false)
+ // CHECK: store i32 {{.*}} @_ZTVN16InitWithinNVSize1CE
+ // CHECK: store i8
+}
diff --git a/test/CodeGenCXX/temporaries.cpp b/test/CodeGenCXX/temporaries.cpp
index bad51ba353cd..294ff29a8eab 100644
--- a/test/CodeGenCXX/temporaries.cpp
+++ b/test/CodeGenCXX/temporaries.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -std=c++11 | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -std=c++11 | FileCheck %s -check-prefixes=CHECK,NULL-INVALID,CHECK-CXX11
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -std=c++17 | FileCheck %s -check-prefixes=CHECK,NULL-INVALID,CHECK-CXX17
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -std=c++11 -fno-delete-null-pointer-checks | FileCheck %s -check-prefixes=CHECK,NULL-VALID,CHECK-CXX11
namespace PR16263 {
const unsigned int n = 1234;
@@ -45,7 +47,9 @@ namespace PR20227 {
namespace BraceInit {
typedef const int &CIR;
CIR x = CIR{3};
- // CHECK: @_ZGRN9BraceInit1xE_ = internal constant i32 3
+ // CHECK-CXX11: @_ZGRN9BraceInit1xE_ = internal constant i32 3
+ // FIXME: This should still be emitted as 'constant' in C++17.
+ // CHECK-CXX17: @_ZGRN9BraceInit1xE_ = internal global i32 3
// CHECK: @_ZN9BraceInit1xE = constant i32* @_ZGRN9BraceInit1xE_
}
@@ -198,20 +202,6 @@ B::B()
f();
}
-struct C {
- C();
-
- const B& b;
-};
-
-C::C()
- // CHECK: call void @_ZN6PR50771BC1Ev
- : b(B()) {
- // CHECK: call void @_ZN6PR50771fEv
- f();
-
- // CHECK: call void @_ZN6PR50771BD1Ev
-}
}
A f8() {
@@ -347,7 +337,8 @@ namespace PR6648 {
struct D;
D& zed(B);
void foobar() {
- // CHECK: call nonnull %"struct.PR6648::D"* @_ZN6PR66483zedENS_1BE
+ // NULL-INVALID: call nonnull %"struct.PR6648::D"* @_ZN6PR66483zedENS_1BE
+ // NULL-VALID: call %"struct.PR6648::D"* @_ZN6PR66483zedENS_1BE
zed(foo);
}
}
@@ -817,15 +808,91 @@ namespace PR14130 {
// CHECK: store {{.*}} @_ZGRN7PR141301vE_, {{.*}} @_ZN7PR141301vE
}
-namespace Ctor {
- struct A { A(); ~A(); };
- void f();
- struct B {
- A &&a;
- B() : a{} { f(); }
- } b;
- // CHECK: define {{.*}}void @_ZN4Ctor1BC1Ev(
- // CHECK: call void @_ZN4Ctor1AC1Ev(
- // CHECK: call void @_ZN4Ctor1fEv(
- // CHECK: call void @_ZN4Ctor1AD1Ev(
+namespace Conditional {
+ struct A {};
+ struct B : A { B(); ~B(); };
+ struct C : A { C(); ~C(); };
+
+ void g();
+
+ // CHECK-LABEL: define {{.*}} @_ZN11Conditional1fEb(
+ void f(bool b) {
+ // CHECK: store i1 false, i1* %[[CLEANUP_B:.*]],
+ // CHECK: store i1 false, i1* %[[CLEANUP_C:.*]],
+ // CHECK: br i1
+ //
+ // CHECK: call {{.*}} @_ZN11Conditional1BC1Ev(
+ // CHECK: store i1 true, i1* %[[CLEANUP_B]],
+ // CHECK: br label
+ //
+ // CHECK: call {{.*}} @_ZN11Conditional1CC1Ev(
+ // CHECK: store i1 true, i1* %[[CLEANUP_C]],
+ // CHECK: br label
+ A &&r = b ? static_cast<A&&>(B()) : static_cast<A&&>(C());
+
+ // CHECK: call {{.*}} @_ZN11Conditional1gEv(
+ g();
+
+ // CHECK: load {{.*}} %[[CLEANUP_C]]
+ // CHECK: br i1
+ // CHECK: call {{.*}} @_ZN11Conditional1CD1Ev(
+ // CHECK: br label
+
+ // CHECK: load {{.*}} %[[CLEANUP_B]]
+ // CHECK: br i1
+ // CHECK: call {{.*}} @_ZN11Conditional1BD1Ev(
+ // CHECK: br label
+ }
+
+ struct D { A &&a; };
+ // CHECK-LABEL: define {{.*}} @_ZN11Conditional10f_indirectEb(
+ void f_indirect(bool b) {
+ // CHECK: store i1 false, i1* %[[CLEANUP_B:.*]],
+ // CHECK: store i1 false, i1* %[[CLEANUP_C:.*]],
+ // CHECK: br i1
+ //
+ // CHECK: call {{.*}} @_ZN11Conditional1BC1Ev(
+ // CHECK: store i1 true, i1* %[[CLEANUP_B]],
+ // CHECK: br label
+ //
+ // CHECK: call {{.*}} @_ZN11Conditional1CC1Ev(
+ // CHECK: store i1 true, i1* %[[CLEANUP_C]],
+ // CHECK: br label
+ D d = b ? D{B()} : D{C()};
+
+ // In C++17, the expression D{...} directly initializes the 'd' object, so
+ // lifetime-extending the temporaries to the lifetime of the D object
+ // extends them past the call to g().
+ //
+ // In C++14 and before, D is move-constructed from the result of the
+ // conditional expression, so no lifetime extension occurs.
+
+ // CHECK-CXX17: call {{.*}} @_ZN11Conditional1gEv(
+
+ // CHECK: load {{.*}} %[[CLEANUP_C]]
+ // CHECK: br i1
+ // CHECK: call {{.*}} @_ZN11Conditional1CD1Ev(
+ // CHECK: br label
+
+ // CHECK: load {{.*}} %[[CLEANUP_B]]
+ // CHECK: br i1
+ // CHECK: call {{.*}} @_ZN11Conditional1BD1Ev(
+ // CHECK: br label
+
+ // CHECK-CXX11: call {{.*}} @_ZN11Conditional1gEv(
+ g();
+ }
+
+ extern bool b;
+ // CHECK: load {{.*}} @_ZN11Conditional1b
+ // CHECK: br i1
+ //
+ // CHECK: call {{.*}} @_ZN11Conditional1BC1Ev({{.*}} @_ZGRN11Conditional1rE_)
+ // CHECK: call {{.*}} @__cxa_atexit({{.*}} @_ZN11Conditional1BD1Ev {{.*}} @_ZGRN11Conditional1rE_,
+ // CHECK: br label
+ //
+ // CHECK: call {{.*}} @_ZN11Conditional1CC1Ev({{.*}} @_ZGRN11Conditional1rE0_)
+ // CHECK: call {{.*}} @__cxa_atexit({{.*}} @_ZN11Conditional1CD1Ev {{.*}} @_ZGRN11Conditional1rE0_,
+ // CHECK: br label
+ A &&r = b ? static_cast<A&&>(B()) : static_cast<A&&>(C());
}
diff --git a/test/CodeGenCXX/trap-fnattr.cpp b/test/CodeGenCXX/trap-fnattr.cpp
index b73ea432b787..166bbadc84eb 100644
--- a/test/CodeGenCXX/trap-fnattr.cpp
+++ b/test/CodeGenCXX/trap-fnattr.cpp
@@ -1,29 +1,29 @@
// RUN: %clang_cc1 -O0 -emit-llvm -ftrapv -ftrap-function=mytrap %s -o - | FileCheck %s -check-prefix=TRAPFUNC
// RUN: %clang_cc1 -O0 -emit-llvm -ftrapv %s -o - | FileCheck %s -check-prefix=NOOPTION
-// TRAPFUNC-LABEL: define void @{{_Z12test_builtinv|\"\\01\?test_builtin@@YAXXZ\"}}
+// TRAPFUNC-LABEL: define {{(dso_local )?}}void @{{_Z12test_builtinv|\"\?test_builtin@@YAXXZ\"}}
// TRAPFUNC: call void @llvm.trap() [[ATTR0:#[0-9]+]]
-// NOOPTION-LABEL: define void @{{_Z12test_builtinv|\"\\01\?test_builtin@@YAXXZ\"}}
+// NOOPTION-LABEL: define {{(dso_local )?}}void @{{_Z12test_builtinv|\"\?test_builtin@@YAXXZ\"}}
// NOOPTION: call void @llvm.trap(){{$}}
void test_builtin(void) {
__builtin_trap();
}
-// TRAPFUNC-LABEL: define {{.*}}i32 @{{_Z13test_noreturnv|\"\\01\?test_noreturn@@YAHXZ\"}}
+// TRAPFUNC-LABEL: define {{.*}}i32 @{{_Z13test_noreturnv|\"\?test_noreturn@@YAHXZ\"}}
// TRAPFUNC: call void @llvm.trap() [[ATTR0]]
-// NOOPTION-LABEL: define {{.*}}i32 @{{_Z13test_noreturnv|\"\\01\?test_noreturn@@YAHXZ\"}}
+// NOOPTION-LABEL: define {{.*}}i32 @{{_Z13test_noreturnv|\"\?test_noreturn@@YAHXZ\"}}
// NOOPTION: call void @llvm.trap(){{$}}
int test_noreturn(void) {
}
-// TRAPFUNC-LABEL: define {{.*}}i32 @{{_Z17test_add_overflowii|\"\\01\?test_add_overflow@@YAHHH@Z\"}}
+// TRAPFUNC-LABEL: define {{.*}}i32 @{{_Z17test_add_overflowii|\"\?test_add_overflow@@YAHHH@Z\"}}
// TRAPFUNC: call void @llvm.trap() [[ATTR1:#[0-9]+]]
-// NOOPTION-LABEL: define {{.*}}i32 @{{_Z17test_add_overflowii|\"\\01\?test_add_overflow@@YAHHH@Z\"}}
+// NOOPTION-LABEL: define {{.*}}i32 @{{_Z17test_add_overflowii|\"\?test_add_overflow@@YAHHH@Z\"}}
// NOOPTION: call void @llvm.trap() [[ATTR2:#[0-9]+]]
int test_add_overflow(int a, int b) {
diff --git a/test/CodeGenCXX/trivial_abi.cpp b/test/CodeGenCXX/trivial_abi.cpp
new file mode 100644
index 000000000000..2cf07b22581a
--- /dev/null
+++ b/test/CodeGenCXX/trivial_abi.cpp
@@ -0,0 +1,239 @@
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fcxx-exceptions -fexceptions -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fcxx-exceptions -fexceptions -fclang-abi-compat=4.0 -emit-llvm -o - %s | FileCheck %s
+
+// CHECK: %[[STRUCT_SMALL:.*]] = type { i32* }
+// CHECK: %[[STRUCT_LARGE:.*]] = type { i32*, [128 x i32] }
+// CHECK: %[[STRUCT_TRIVIAL:.*]] = type { i32 }
+// CHECK: %[[STRUCT_NONTRIVIAL:.*]] = type { i32 }
+
+struct __attribute__((trivial_abi)) Small {
+ int *p;
+ Small();
+ ~Small();
+ Small(const Small &) noexcept;
+ Small &operator=(const Small &);
+};
+
+struct __attribute__((trivial_abi)) Large {
+ int *p;
+ int a[128];
+ Large();
+ ~Large();
+ Large(const Large &) noexcept;
+ Large &operator=(const Large &);
+};
+
+struct Trivial {
+ int a;
+};
+
+struct NonTrivial {
+ NonTrivial();
+ ~NonTrivial();
+ int a;
+};
+
+struct HasTrivial {
+ Small s;
+ Trivial m;
+};
+
+struct HasNonTrivial {
+ Small s;
+ NonTrivial m;
+};
+
+// CHECK: define void @_Z14testParamSmall5Small(i64 %[[A_COERCE:.*]])
+// CHECK: %[[A:.*]] = alloca %[[STRUCT_SMALL]], align 8
+// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[A]], i32 0, i32 0
+// CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[A_COERCE]] to i32*
+// CHECK: store i32* %[[COERCE_VAL_IP]], i32** %[[COERCE_DIVE]], align 8
+// CHECK: %[[CALL:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallD1Ev(%[[STRUCT_SMALL]]* %[[A]])
+// CHECK: ret void
+// CHECK: }
+
+void testParamSmall(Small a) noexcept {
+}
+
+// CHECK: define i64 @_Z15testReturnSmallv()
+// CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_SMALL:.*]], align 8
+// CHECK: %[[CALL:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallC1Ev(%[[STRUCT_SMALL]]* %[[RETVAL]])
+// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[RETVAL]], i32 0, i32 0
+// CHECK: %[[V0:.*]] = load i32*, i32** %[[COERCE_DIVE]], align 8
+// CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i32* %[[V0]] to i64
+// CHECK: ret i64 %[[COERCE_VAL_PI]]
+// CHECK: }
+
+Small testReturnSmall() {
+ Small t;
+ return t;
+}
+
+// CHECK: define void @_Z14testCallSmall0v()
+// CHECK: %[[T:.*]] = alloca %[[STRUCT_SMALL:.*]], align 8
+// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_SMALL]], align 8
+// CHECK: %[[CALL:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallC1Ev(%[[STRUCT_SMALL]]* %[[T]])
+// CHECK: %[[CALL1:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallC1ERKS_(%[[STRUCT_SMALL]]* %[[AGG_TMP]], %[[STRUCT_SMALL]]* dereferenceable(8) %[[T]])
+// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[AGG_TMP]], i32 0, i32 0
+// CHECK: %[[V0:.*]] = load i32*, i32** %[[COERCE_DIVE]], align 8
+// CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i32* %[[V0]] to i64
+// CHECK: call void @_Z14testParamSmall5Small(i64 %[[COERCE_VAL_PI]])
+// CHECK: %[[CALL2:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallD1Ev(%[[STRUCT_SMALL]]* %[[T]])
+// CHECK: ret void
+// CHECK: }
+
+void testCallSmall0() {
+ Small t;
+ testParamSmall(t);
+}
+
+// CHECK: define void @_Z14testCallSmall1v()
+// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_SMALL:.*]], align 8
+// CHECK: %[[CALL:.*]] = call i64 @_Z15testReturnSmallv()
+// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[AGG_TMP]], i32 0, i32 0
+// CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[CALL]] to i32*
+// CHECK: store i32* %[[COERCE_VAL_IP]], i32** %[[COERCE_DIVE]], align 8
+// CHECK: %[[COERCE_DIVE1:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[AGG_TMP]], i32 0, i32 0
+// CHECK: %[[V0:.*]] = load i32*, i32** %[[COERCE_DIVE1]], align 8
+// CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i32* %[[V0]] to i64
+// CHECK: call void @_Z14testParamSmall5Small(i64 %[[COERCE_VAL_PI]])
+// CHECK: ret void
+// CHECK: }
+
+void testCallSmall1() {
+ testParamSmall(testReturnSmall());
+}
+
+// CHECK: define void @_Z16testIgnoredSmallv()
+// CHECK: %[[AGG_TMP_ENSURED:.*]] = alloca %[[STRUCT_SMALL:.*]], align 8
+// CHECK: %[[CALL:.*]] = call i64 @_Z15testReturnSmallv()
+// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[AGG_TMP_ENSURED]], i32 0, i32 0
+// CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[CALL]] to i32*
+// CHECK: store i32* %[[COERCE_VAL_IP]], i32** %[[COERCE_DIVE]], align 8
+// CHECK: %[[CALL1:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallD1Ev(%[[STRUCT_SMALL]]* %[[AGG_TMP_ENSURED]])
+// CHECK: ret void
+// CHECK: }
+
+void testIgnoredSmall() {
+ testReturnSmall();
+}
+
+// CHECK: define void @_Z14testParamLarge5Large(%[[STRUCT_LARGE:.*]]* %[[A:.*]])
+// CHECK: %[[CALL:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeD1Ev(%[[STRUCT_LARGE]]* %[[A]])
+// CHECK: ret void
+// CHECK: }
+
+void testParamLarge(Large a) noexcept {
+}
+
+// CHECK: define void @_Z15testReturnLargev(%[[STRUCT_LARGE:.*]]* noalias sret %[[AGG_RESULT:.*]])
+// CHECK: %[[CALL:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeC1Ev(%[[STRUCT_LARGE]]* %[[AGG_RESULT]])
+// CHECK: ret void
+// CHECK: }
+
+Large testReturnLarge() {
+ Large t;
+ return t;
+}
+
+// CHECK: define void @_Z14testCallLarge0v()
+// CHECK: %[[T:.*]] = alloca %[[STRUCT_LARGE:.*]], align 8
+// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_LARGE]], align 8
+// CHECK: %[[CALL:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeC1Ev(%[[STRUCT_LARGE]]* %[[T]])
+// CHECK: %[[CALL1:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeC1ERKS_(%[[STRUCT_LARGE]]* %[[AGG_TMP]], %[[STRUCT_LARGE]]* dereferenceable(520) %[[T]])
+// CHECK: call void @_Z14testParamLarge5Large(%[[STRUCT_LARGE]]* %[[AGG_TMP]])
+// CHECK: %[[CALL2:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeD1Ev(%[[STRUCT_LARGE]]* %[[T]])
+// CHECK: ret void
+// CHECK: }
+
+void testCallLarge0() {
+ Large t;
+ testParamLarge(t);
+}
+
+// CHECK: define void @_Z14testCallLarge1v()
+// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_LARGE:.*]], align 8
+// CHECK: call void @_Z15testReturnLargev(%[[STRUCT_LARGE]]* sret %[[AGG_TMP]])
+// CHECK: call void @_Z14testParamLarge5Large(%[[STRUCT_LARGE]]* %[[AGG_TMP]])
+// CHECK: ret void
+// CHECK: }
+
+void testCallLarge1() {
+ testParamLarge(testReturnLarge());
+}
+
+// CHECK: define void @_Z16testIgnoredLargev()
+// CHECK: %[[AGG_TMP_ENSURED:.*]] = alloca %[[STRUCT_LARGE:.*]], align 8
+// CHECK: call void @_Z15testReturnLargev(%[[STRUCT_LARGE]]* sret %[[AGG_TMP_ENSURED]])
+// CHECK: %[[CALL:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeD1Ev(%[[STRUCT_LARGE]]* %[[AGG_TMP_ENSURED]])
+// CHECK: ret void
+// CHECK: }
+
+void testIgnoredLarge() {
+ testReturnLarge();
+}
+
+// CHECK: define i64 @_Z20testReturnHasTrivialv()
+// CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_TRIVIAL:.*]], align 4
+// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_TRIVIAL]], %[[STRUCT_TRIVIAL]]* %[[RETVAL]], i32 0, i32 0
+// CHECK: %[[V0:.*]] = load i32, i32* %[[COERCE_DIVE]], align 4
+// CHECK: %[[COERCE_VAL_II:.*]] = zext i32 %[[V0]] to i64
+// CHECK: ret i64 %[[COERCE_VAL_II]]
+// CHECK: }
+
+Trivial testReturnHasTrivial() {
+ Trivial t;
+ return t;
+}
+
+// CHECK: define void @_Z23testReturnHasNonTrivialv(%[[STRUCT_NONTRIVIAL:.*]]* noalias sret %[[AGG_RESULT:.*]])
+// CHECK: %[[CALL:.*]] = call %[[STRUCT_NONTRIVIAL]]* @_ZN10NonTrivialC1Ev(%[[STRUCT_NONTRIVIAL]]* %[[AGG_RESULT]])
+// CHECK: ret void
+// CHECK: }
+
+NonTrivial testReturnHasNonTrivial() {
+ NonTrivial t;
+ return t;
+}
+
+// CHECK: define void @_Z18testExceptionSmallv()
+// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_SMALL]], align 8
+// CHECK: %[[AGG_TMP1:.*]] = alloca %[[STRUCT_SMALL]], align 8
+// CHECK: call %[[STRUCT_SMALL]]* @_ZN5SmallC1Ev(%[[STRUCT_SMALL]]* %[[AGG_TMP]])
+// CHECK: invoke %[[STRUCT_SMALL]]* @_ZN5SmallC1Ev(%[[STRUCT_SMALL]]* %[[AGG_TMP1]])
+
+// CHECK: call void @_Z20calleeExceptionSmall5SmallS_(i64 %{{.*}}, i64 %{{.*}})
+// CHECK-NEXT: ret void
+
+// CHECK: landingpad { i8*, i32 }
+// CHECK: call %[[STRUCT_SMALL]]* @_ZN5SmallD1Ev(%[[STRUCT_SMALL]]* %[[AGG_TMP]])
+// CHECK: br
+
+// CHECK: resume { i8*, i32 }
+
+void calleeExceptionSmall(Small, Small);
+
+void testExceptionSmall() {
+ calleeExceptionSmall(Small(), Small());
+}
+
+// CHECK: define void @_Z18testExceptionLargev()
+// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_LARGE]], align 8
+// CHECK: %[[AGG_TMP1:.*]] = alloca %[[STRUCT_LARGE]], align 8
+// CHECK: call %[[STRUCT_LARGE]]* @_ZN5LargeC1Ev(%[[STRUCT_LARGE]]* %[[AGG_TMP]])
+// CHECK: invoke %[[STRUCT_LARGE]]* @_ZN5LargeC1Ev(%[[STRUCT_LARGE]]* %[[AGG_TMP1]])
+
+// CHECK: call void @_Z20calleeExceptionLarge5LargeS_(%[[STRUCT_LARGE]]* %[[AGG_TMP]], %[[STRUCT_LARGE]]* %[[AGG_TMP1]])
+// CHECK-NEXT: ret void
+
+// CHECK: landingpad { i8*, i32 }
+// CHECK: call %[[STRUCT_LARGE]]* @_ZN5LargeD1Ev(%[[STRUCT_LARGE]]* %[[AGG_TMP]])
+// CHECK: br
+
+// CHECK: resume { i8*, i32 }
+
+void calleeExceptionLarge(Large, Large);
+
+void testExceptionLarge() {
+ calleeExceptionLarge(Large(), Large());
+}
diff --git a/test/CodeGenCXX/type-metadata-memfun.cpp b/test/CodeGenCXX/type-metadata-memfun.cpp
new file mode 100644
index 000000000000..2ff574e7da42
--- /dev/null
+++ b/test/CodeGenCXX/type-metadata-memfun.cpp
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -flto -flto-unit -triple x86_64-unknown-linux -fvisibility hidden -emit-llvm -o - %s | FileCheck %s
+
+struct S1 {
+ S1();
+ ~S1();
+ virtual void vf();
+ void f();
+ void fdecl();
+};
+
+struct [[clang::lto_visibility_public]] S2 {
+ void f();
+};
+
+// CHECK-NOT: declare{{.*}}!type
+// CHECK-NOT: define{{.*}}!type
+
+S1::S1() {}
+S1::~S1() {}
+void S1::vf() {}
+// CHECK: define hidden void @_ZN2S11fEv{{.*}} !type [[S2F:![0-9]+]]
+void S1::f() {
+ fdecl();
+}
+
+void S2::f() {}
+
+// CHECK-NOT: declare{{.*}}!type
+// CHECK-NOT: define{{.*}}!type
+
+// CHECK: [[S2F]] = !{i64 0, !"_ZTSM2S1FvvE"}
diff --git a/test/CodeGenCXX/type-metadata.cpp b/test/CodeGenCXX/type-metadata.cpp
index 6821e3624093..8e3e4bd182fe 100644
--- a/test/CodeGenCXX/type-metadata.cpp
+++ b/test/CodeGenCXX/type-metadata.cpp
@@ -14,16 +14,25 @@
// ITANIUM: @_ZTV1A = {{[^!]*}}, !type [[A16:![0-9]+]]
// ITANIUM-DIAG-SAME: !type [[ALL16:![0-9]+]]
+// ITANIUM-SAME: !type [[AF16:![0-9]+]]
// ITANIUM: @_ZTV1B = {{[^!]*}}, !type [[A32:![0-9]+]]
// ITANIUM-DIAG-SAME: !type [[ALL32:![0-9]+]]
+// ITANIUM-SAME: !type [[AF32:![0-9]+]]
+// ITANIUM-SAME: !type [[AF40:![0-9]+]]
+// ITANIUM-SAME: !type [[AF48:![0-9]+]]
// ITANIUM-SAME: !type [[B32:![0-9]+]]
// ITANIUM-DIAG-SAME: !type [[ALL32]]
+// ITANIUM-SAME: !type [[BF32:![0-9]+]]
+// ITANIUM-SAME: !type [[BF40:![0-9]+]]
+// ITANIUM-SAME: !type [[BF48:![0-9]+]]
// ITANIUM: @_ZTV1C = {{[^!]*}}, !type [[A32]]
// ITANIUM-DIAG-SAME: !type [[ALL32]]
+// ITANIUM-SAME: !type [[AF32]]
// ITANIUM-SAME: !type [[C32:![0-9]+]]
// ITANIUM-DIAG-SAME: !type [[ALL32]]
+// ITANIUM-SAME: !type [[CF32:![0-9]+]]
// DIAG: @[[SRC:.*]] = private unnamed_addr constant [{{.*}} x i8] c"{{.*}}type-metadata.cpp\00", align 1
// DIAG: @[[TYPE:.*]] = private unnamed_addr constant { i16, i16, [4 x i8] } { i16 -1, i16 0, [4 x i8] c"'A'\00" }
@@ -31,12 +40,24 @@
// ITANIUM: @_ZTVN12_GLOBAL__N_11DE = {{[^!]*}}, !type [[A32]]
// ITANIUM-DIAG-SAME: !type [[ALL32]]
+// ITANIUM-SAME: !type [[AF32]]
+// ITANIUM-SAME: !type [[AF40]]
+// ITANIUM-SAME: !type [[AF48]]
// ITANIUM-SAME: !type [[B32]]
// ITANIUM-DIAG-SAME: !type [[ALL32]]
+// ITANIUM-SAME: !type [[BF32]]
+// ITANIUM-SAME: !type [[BF40]]
+// ITANIUM-SAME: !type [[BF48]]
// ITANIUM-SAME: !type [[C88:![0-9]+]]
// ITANIUM-DIAG-SAME: !type [[ALL88:![0-9]+]]
+// ITANIUM-SAME: !type [[CF32]]
+// ITANIUM-SAME: !type [[CF40:![0-9]+]]
+// ITANIUM-SAME: !type [[CF48:![0-9]+]]
// ITANIUM-SAME: !type [[D32:![0-9]+]]
// ITANIUM-DIAG-SAME: !type [[ALL32]]
+// ITANIUM-SAME: !type [[DF32:![0-9]+]]
+// ITANIUM-SAME: !type [[DF40:![0-9]+]]
+// ITANIUM-SAME: !type [[DF48:![0-9]+]]
// ITANIUM: @_ZTCN12_GLOBAL__N_11DE0_1B = {{[^!]*}}, !type [[A32]]
// ITANIUM-DIAG-SAME: !type [[ALL32]]
@@ -45,21 +66,25 @@
// ITANIUM: @_ZTCN12_GLOBAL__N_11DE8_1C = {{[^!]*}}, !type [[A64:![0-9]+]]
// ITANIUM-DIAG-SAME: !type [[ALL64:![0-9]+]]
+// ITANIUM-SAME: !type [[AF64:![0-9]+]]
// ITANIUM-SAME: !type [[C32]]
// ITANIUM-DIAG-SAME: !type [[ALL32]]
+// ITANIUM-SAME: !type [[CF64:![0-9]+]]
// ITANIUM: @_ZTVZ3foovE2FA = {{[^!]*}}, !type [[A16]]
// ITANIUM-DIAG-SAME: !type [[ALL16]]
+// ITANIUM-SAME: !type [[AF16]]
// ITANIUM-SAME: !type [[FA16:![0-9]+]]
// ITANIUM-DIAG-SAME: !type [[ALL16]]
+// ITANIUM-SAME: !type [[FAF16:![0-9]+]]
-// MS: comdat($"\01??_7A@@6B@"), !type [[A8:![0-9]+]]
-// MS: comdat($"\01??_7B@@6B0@@"), !type [[B8:![0-9]+]]
-// MS: comdat($"\01??_7B@@6BA@@@"), !type [[A8]]
-// MS: comdat($"\01??_7C@@6B@"), !type [[A8]]
-// MS: comdat($"\01??_7D@?A@@6BB@@@"), !type [[B8]], !type [[D8:![0-9]+]]
-// MS: comdat($"\01??_7D@?A@@6BA@@@"), !type [[A8]]
-// MS: comdat($"\01??_7FA@?1??foo@@YAXXZ@6B@"), !type [[A8]], !type [[FA8:![0-9]+]]
+// MS: comdat($"??_7A@@6B@"), !type [[A8:![0-9]+]]
+// MS: comdat($"??_7B@@6B0@@"), !type [[B8:![0-9]+]]
+// MS: comdat($"??_7B@@6BA@@@"), !type [[A8]]
+// MS: comdat($"??_7C@@6B@"), !type [[A8]]
+// MS: comdat($"??_7D@?A@@6BB@@@"), !type [[B8]], !type [[D8:![0-9]+]]
+// MS: comdat($"??_7D@?A@@6BA@@@"), !type [[A8]]
+// MS: comdat($"??_7FA@?1??foo@@YAXXZ@6B@"), !type [[A8]], !type [[FA8:![0-9]+]]
struct A {
A();
@@ -104,7 +129,7 @@ void D::h() {
}
// ITANIUM: define hidden void @_Z2afP1A
-// MS: define void @"\01?af@@YAXPEAUA@@@Z"
+// MS: define dso_local void @"?af@@YAXPEAUA@@@Z"
void af(A *a) {
// TT-ITANIUM: [[P:%[^ ]*]] = call i1 @llvm.type.test(i8* [[VT:%[^ ]*]], metadata !"_ZTS1A")
// TT-MS: [[P:%[^ ]*]] = call i1 @llvm.type.test(i8* [[VT:%[^ ]*]], metadata !"?AUA@@")
@@ -136,7 +161,7 @@ void af(A *a) {
}
// ITANIUM: define internal void @_Z3df1PN12_GLOBAL__N_11DE
-// MS: define internal void @"\01?df1@@YAXPEAUD@?A@@@Z"
+// MS: define internal void @"?df1@@YAXPEAUD@?A@@@Z"
void df1(D *d) {
// TT-ITANIUM: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata ![[DTYPE:[0-9]+]])
// TT-MS: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"?AUA@@")
@@ -146,7 +171,7 @@ void df1(D *d) {
}
// ITANIUM: define internal void @_Z3dg1PN12_GLOBAL__N_11DE
-// MS: define internal void @"\01?dg1@@YAXPEAUD@?A@@@Z"
+// MS: define internal void @"?dg1@@YAXPEAUD@?A@@@Z"
void dg1(D *d) {
// TT-ITANIUM: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
// TT-MS: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"?AUB@@")
@@ -156,7 +181,7 @@ void dg1(D *d) {
}
// ITANIUM: define internal void @_Z3dh1PN12_GLOBAL__N_11DE
-// MS: define internal void @"\01?dh1@@YAXPEAUD@?A@@@Z"
+// MS: define internal void @"?dh1@@YAXPEAUD@?A@@@Z"
void dh1(D *d) {
// TT-ITANIUM: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata ![[DTYPE]])
// TT-MS: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata ![[DTYPE:[0-9]+]])
@@ -166,7 +191,7 @@ void dh1(D *d) {
}
// ITANIUM: define internal void @_Z3df2PN12_GLOBAL__N_11DE
-// MS: define internal void @"\01?df2@@YAXPEAUD@?A@@@Z"
+// MS: define internal void @"?df2@@YAXPEAUD@?A@@@Z"
__attribute__((no_sanitize("cfi")))
void df2(D *d) {
// CFI-NVT-NOT: call i1 @llvm.type.test
@@ -176,7 +201,7 @@ void df2(D *d) {
}
// ITANIUM: define internal void @_Z3df3PN12_GLOBAL__N_11DE
-// MS: define internal void @"\01?df3@@YAXPEAUD@?A@@@Z"
+// MS: define internal void @"?df3@@YAXPEAUD@?A@@@Z"
__attribute__((no_sanitize("address"))) __attribute__((no_sanitize("cfi-vcall")))
void df3(D *d) {
// CFI-NVT-NOT: call i1 @llvm.type.test
@@ -214,7 +239,7 @@ struct D : C {
};
// ITANIUM: define hidden void @_ZN5test21fEPNS_1DE
-// MS: define void @"\01?f@test2@@YAXPEAUD@1@@Z"
+// MS: define dso_local void @"?f@test2@@YAXPEAUD@1@@Z"
void f(D *d) {
// TT-ITANIUM: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTSN5test21DE")
// TT-MS: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"?AUA@test2@@")
@@ -227,18 +252,36 @@ void f(D *d) {
// ITANIUM: [[A16]] = !{i64 16, !"_ZTS1A"}
// ITANIUM-DIAG: [[ALL16]] = !{i64 16, !"all-vtables"}
+// ITANIUM: [[AF16]] = !{i64 16, !"_ZTSM1AFvvE.virtual"}
// ITANIUM: [[A32]] = !{i64 32, !"_ZTS1A"}
// ITANIUM-DIAG: [[ALL32]] = !{i64 32, !"all-vtables"}
+// ITANIUM: [[AF32]] = !{i64 32, !"_ZTSM1AFvvE.virtual"}
+// ITANIUM: [[AF40]] = !{i64 40, !"_ZTSM1AFvvE.virtual"}
+// ITANIUM: [[AF48]] = !{i64 48, !"_ZTSM1AFvvE.virtual"}
// ITANIUM: [[B32]] = !{i64 32, !"_ZTS1B"}
+// ITANIUM: [[BF32]] = !{i64 32, !"_ZTSM1BFvvE.virtual"}
+// ITANIUM: [[BF40]] = !{i64 40, !"_ZTSM1BFvvE.virtual"}
+// ITANIUM: [[BF48]] = !{i64 48, !"_ZTSM1BFvvE.virtual"}
// ITANIUM: [[C32]] = !{i64 32, !"_ZTS1C"}
+// ITANIUM: [[CF32]] = !{i64 32, !"_ZTSM1CFvvE.virtual"}
// ITANIUM: [[C88]] = !{i64 88, !"_ZTS1C"}
// ITANIUM-DIAG: [[ALL88]] = !{i64 88, !"all-vtables"}
+// ITANIUM: [[CF40]] = !{i64 40, !"_ZTSM1CFvvE.virtual"}
+// ITANIUM: [[CF48]] = !{i64 48, !"_ZTSM1CFvvE.virtual"}
// ITANIUM: [[D32]] = !{i64 32, [[D_ID:![0-9]+]]}
// ITANIUM: [[D_ID]] = distinct !{}
+// ITANIUM: [[DF32]] = !{i64 32, [[DF_ID:![0-9]+]]}
+// ITANIUM: [[DF_ID]] = distinct !{}
+// ITANIUM: [[DF40]] = !{i64 40, [[DF_ID]]}
+// ITANIUM: [[DF48]] = !{i64 48, [[DF_ID]]}
// ITANIUM: [[A64]] = !{i64 64, !"_ZTS1A"}
// ITANIUM-DIAG: [[ALL64]] = !{i64 64, !"all-vtables"}
+// ITANIUM: [[AF64]] = !{i64 64, !"_ZTSM1AFvvE.virtual"}
+// ITANIUM: [[CF64]] = !{i64 64, !"_ZTSM1CFvvE.virtual"}
// ITANIUM: [[FA16]] = !{i64 16, [[FA_ID:![0-9]+]]}
// ITANIUM: [[FA_ID]] = distinct !{}
+// ITANIUM: [[FAF16]] = !{i64 16, [[FAF_ID:![0-9]+]]}
+// ITANIUM: [[FAF_ID]] = distinct !{}
// MS: [[A8]] = !{i64 8, !"?AUA@@"}
// MS: [[B8]] = !{i64 8, !"?AUB@@"}
diff --git a/test/CodeGenCXX/ubsan-ctor-srcloc.cpp b/test/CodeGenCXX/ubsan-ctor-srcloc.cpp
new file mode 100644
index 000000000000..da27a668cf62
--- /dev/null
+++ b/test/CodeGenCXX/ubsan-ctor-srcloc.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-linux -emit-llvm -fsanitize=alignment -fblocks %s -o %t.ll
+// RUN: FileCheck -check-prefix=ZEROINIT < %t.ll %s
+// RUN: FileCheck -check-prefix=SRCLOC < %t.ll %s
+// ZEROINIT-NOT: @{{.+}} = private unnamed_addr global {{.+}} zeroinitializer
+
+struct A {
+ A(int);
+ int k;
+};
+
+struct B : A {
+ B();
+ B(const B &);
+// SRCLOC-DAG: @{{.+}} = private unnamed_addr global {{.+}} @.src, i32 [[@LINE+1]], i32 12 }
+ using A::A;
+ void f() const;
+};
+
+// SRCLOC-DAG: @{{.+}} = private unnamed_addr global {{.+}} @.src, i32 [[@LINE+1]], i32 10 }
+B::B() : A(1) {}
+
+void foo() {
+ B b(2);
+// SRCLOC-DAG: @{{.+}} = private unnamed_addr global {{.+}} @.src, i32 [[@LINE+1]], i32 5 }
+ ^{b.f();}();
+}
diff --git a/test/CodeGenCXX/ubsan-devirtualized-calls.cpp b/test/CodeGenCXX/ubsan-devirtualized-calls.cpp
index f4ccdbf6474a..1510a4a08dd0 100644
--- a/test/CodeGenCXX/ubsan-devirtualized-calls.cpp
+++ b/test/CodeGenCXX/ubsan-devirtualized-calls.cpp
@@ -32,7 +32,7 @@ struct Derived4 final : Base1 {
// CHECK: [[UBSAN_TI_DERIVED4_1:@[0-9]+]] = private unnamed_addr global {{.*}} i8* bitcast {{.*}} @_ZTI8Derived4 to i8*
// CHECK: [[UBSAN_TI_DERIVED4_2:@[0-9]+]] = private unnamed_addr global {{.*}} i8* bitcast {{.*}} @_ZTI8Derived4 to i8*
-// CHECK-LABEL: define void @_Z2t1v
+// CHECK-LABEL: define {{(dso_local )?}}void @_Z2t1v
void t1() {
Derived1 d1;
static_cast<Base1 *>(&d1)->f1(); //< Devirt Base1::f1 to Derived1::f1.
@@ -40,7 +40,7 @@ void t1() {
// CHECK-NEXT: call void @__ubsan_handle_dynamic_type_cache{{[_a-z]*}}({{.*}} [[UBSAN_TI_DERIVED1_1]] {{.*}}, i{{[0-9]+}} %[[D1]]
}
-// CHECK-LABEL: define void @_Z2t2v
+// CHECK-LABEL: define {{(dso_local )?}}void @_Z2t2v
void t2() {
Derived2 d2;
static_cast<Base1 *>(&d2)->f1(); //< Devirt Base1::f1 to Derived2::f1.
@@ -48,7 +48,7 @@ void t2() {
// CHECK-NEXT: call void @__ubsan_handle_dynamic_type_cache{{[_a-z]*}}({{.*}} [[UBSAN_TI_DERIVED2_1]] {{.*}}, i{{[0-9]+}} %[[D2_1]]
}
-// CHECK-LABEL: define void @_Z2t3v
+// CHECK-LABEL: define {{(dso_local )?}}void @_Z2t3v
void t3() {
Derived2 d2;
static_cast<Base2 *>(&d2)->f1(); //< Devirt Base2::f1 to Derived2::f1.
@@ -56,7 +56,7 @@ void t3() {
// CHECK-NEXT: call void @__ubsan_handle_dynamic_type_cache{{[_a-z]*}}({{.*}} [[UBSAN_TI_DERIVED2_2]] {{.*}}, i{{[0-9]+}} %[[D2_2]]
}
-// CHECK-LABEL: define void @_Z2t4v
+// CHECK-LABEL: define {{(dso_local )?}}void @_Z2t4v
void t4() {
Base1 p;
Derived3 *badp = static_cast<Derived3 *>(&p); //< Check that &p isa Derived3.
@@ -73,7 +73,7 @@ void t4() {
// CHECK-NEXT: call void @__ubsan_handle_dynamic_type_cache{{[_a-z]*}}({{.*}} [[UBSAN_TI_BASE1]] {{.*}}, i{{[0-9]+}} %[[BADP1]]
}
-// CHECK-LABEL: define void @_Z2t5v
+// CHECK-LABEL: define {{(dso_local )?}}void @_Z2t5v
void t5() {
Base1 p;
Derived4 *badp = static_cast<Derived4 *>(&p); //< Check that &p isa Derived4.
diff --git a/test/CodeGenCXX/ubsan-function-noexcept.cpp b/test/CodeGenCXX/ubsan-function-noexcept.cpp
new file mode 100644
index 000000000000..45c2764add7d
--- /dev/null
+++ b/test/CodeGenCXX/ubsan-function-noexcept.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -std=c++17 -fsanitize=function -emit-llvm -triple x86_64-linux-gnu %s -o - | FileCheck %s
+
+// Check that typeinfo recorded in function prolog doesn't have "Do" noexcept
+// qualifier in its mangled name.
+// CHECK: @[[RTTI:[0-9]+]] = private constant i8* bitcast ({ i8*, i8* }* @_ZTIFvvE to i8*)
+// CHECK: define void @_Z1fv() #{{.*}} prologue <{ i32, i32 }> <{ i32 {{.*}}, i32 trunc (i64 sub (i64 ptrtoint (i8** @[[RTTI]] to i64), i64 ptrtoint (void ()* @_Z1fv to i64)) to i32) }>
+void f() noexcept {}
+
+// CHECK: define void @_Z1gPDoFvvE
+void g(void (*p)() noexcept) {
+ // Check that reference typeinfo at call site doesn't have "Do" noexcept
+ // qualifier in its mangled name, either.
+ // CHECK: icmp eq i8* %{{.*}}, bitcast ({ i8*, i8* }* @_ZTIFvvE to i8*), !nosanitize
+ p();
+}
diff --git a/test/CodeGenCXX/ubsan-vtable-checks.cpp b/test/CodeGenCXX/ubsan-vtable-checks.cpp
index 090707c29d74..ec4a21a2b2b4 100644
--- a/test/CodeGenCXX/ubsan-vtable-checks.cpp
+++ b/test/CodeGenCXX/ubsan-vtable-checks.cpp
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-linux -emit-llvm -fsanitize=null %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NULL --check-prefix=ITANIUM
// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows -emit-llvm -fsanitize=null %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NULL --check-prefix=MSABI
// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-linux -emit-llvm -fsanitize=null,vptr %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-VPTR --check-prefix=ITANIUM
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows -emit-llvm -fsanitize=null,vptr %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-VPTR --check-prefix=MSABI
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows -emit-llvm -fsanitize=null,vptr %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-VPTR --check-prefix=MSABI --check-prefix=CHECK-VPTR-MS
struct T {
virtual ~T() {}
virtual int v() { return 1; }
@@ -14,8 +14,10 @@ struct U : T {
U::~U() {}
+// CHECK-VPTR-MS: @__ubsan_vptr_type_cache = external dso_local
+
// ITANIUM: define i32 @_Z5get_vP1T
-// MSABI: define i32 @"\01?get_v
+// MSABI: define dso_local i32 @"?get_v
int get_v(T* t) {
// First, we check that vtable is not loaded before a type check.
// CHECK-NULL-NOT: load {{.*}} (%struct.T*{{.*}})**, {{.*}} (%struct.T*{{.*}})***
@@ -28,7 +30,7 @@ int get_v(T* t) {
}
// ITANIUM: define void @_Z9delete_itP1T
-// MSABI: define void @"\01?delete_it
+// MSABI: define dso_local void @"?delete_it
void delete_it(T *t) {
// First, we check that vtable is not loaded before a type check.
// CHECK-VPTR-NOT: load {{.*}} (%struct.T*{{.*}})**, {{.*}} (%struct.T*{{.*}})***
@@ -40,7 +42,7 @@ void delete_it(T *t) {
}
// ITANIUM: define %struct.U* @_Z7dyncastP1T
-// MSABI: define %struct.U* @"\01?dyncast
+// MSABI: define dso_local %struct.U* @"?dyncast
U* dyncast(T *t) {
// First, we check that dynamic_cast is not called before a type check.
// CHECK-VPTR-NOT: call i8* @__{{dynamic_cast|RTDynamicCast}}
diff --git a/test/CodeGenCXX/unaligned-member-qualifier.cpp b/test/CodeGenCXX/unaligned-member-qualifier.cpp
index 0d326a666830..57cfbd9e2c21 100644
--- a/test/CodeGenCXX/unaligned-member-qualifier.cpp
+++ b/test/CodeGenCXX/unaligned-member-qualifier.cpp
@@ -8,13 +8,13 @@ struct A {
};
void A::foo() __unaligned {}
-// CHECK: define [[THISCALL:(x86_thiscallcc )?]]void @_ZNU11__unaligned1A3fooEv(
+// CHECK: define {{(dso_local )?}}[[THISCALL:(x86_thiscallcc )?]]void @_ZNU11__unaligned1A3fooEv(
void A::foo() const __unaligned {}
-// CHECK: define [[THISCALL]]void @_ZNU11__unalignedK1A3fooEv(
+// CHECK: define {{(dso_local )?}}[[THISCALL]]void @_ZNU11__unalignedK1A3fooEv(
void A::foo() volatile __unaligned {}
-// CHECK: define [[THISCALL]]void @_ZNU11__unalignedV1A3fooEv(
+// CHECK: define {{(dso_local )?}}[[THISCALL]]void @_ZNU11__unalignedV1A3fooEv(
void A::foo() const volatile __unaligned {}
-// CHECK: define [[THISCALL]]void @_ZNU11__unalignedVK1A3fooEv(
+// CHECK: define {{(dso_local )?}}[[THISCALL]]void @_ZNU11__unalignedVK1A3fooEv(
diff --git a/test/CodeGenCXX/uncopyable-args.cpp b/test/CodeGenCXX/uncopyable-args.cpp
index 66d67e4a34d5..baada1ccdfdf 100644
--- a/test/CodeGenCXX/uncopyable-args.cpp
+++ b/test/CodeGenCXX/uncopyable-args.cpp
@@ -19,7 +19,7 @@ void bar() {
// CHECK: call void @_ZN7trivial3fooENS_1AE(i8* %{{.*}})
// CHECK-LABEL: declare void @_ZN7trivial3fooENS_1AE(i8*)
-// WIN64-LABEL: declare void @"\01?foo@trivial@@YAXUA@1@@Z"(i64)
+// WIN64-LABEL: declare dso_local void @"?foo@trivial@@YAXUA@1@@Z"(i64)
}
namespace default_ctor {
@@ -40,7 +40,7 @@ void bar() {
// CHECK: call void @_ZN12default_ctor3fooENS_1AE(i8* %{{.*}})
// CHECK-LABEL: declare void @_ZN12default_ctor3fooENS_1AE(i8*)
-// WIN64-LABEL: declare void @"\01?foo@default_ctor@@YAXUA@1@@Z"(i64)
+// WIN64-LABEL: declare dso_local void @"?foo@default_ctor@@YAXUA@1@@Z"(i64)
}
namespace move_ctor {
@@ -63,7 +63,7 @@ void bar() {
// NEWABI-LABEL: declare void @_ZN9move_ctor3fooENS_1AE(%"struct.move_ctor::A"*)
// OLDABI-LABEL: declare void @_ZN9move_ctor3fooENS_1AE(i8*)
-// WIN64-LABEL: declare void @"\01?foo@move_ctor@@YAXUA@1@@Z"(%"struct.move_ctor::A"*)
+// WIN64-LABEL: declare dso_local void @"?foo@move_ctor@@YAXUA@1@@Z"(%"struct.move_ctor::A"*)
}
namespace all_deleted {
@@ -85,7 +85,7 @@ void bar() {
// NEWABI-LABEL: declare void @_ZN11all_deleted3fooENS_1AE(%"struct.all_deleted::A"*)
// OLDABI-LABEL: declare void @_ZN11all_deleted3fooENS_1AE(i8*)
-// WIN64-LABEL: declare void @"\01?foo@all_deleted@@YAXUA@1@@Z"(%"struct.all_deleted::A"*)
+// WIN64-LABEL: declare dso_local void @"?foo@all_deleted@@YAXUA@1@@Z"(%"struct.all_deleted::A"*)
}
namespace implicitly_deleted {
@@ -107,8 +107,8 @@ void bar() {
// OLDABI-LABEL: declare void @_ZN18implicitly_deleted3fooENS_1AE(i8*)
// In MSVC 2013, the copy ctor is not deleted by a move assignment. In MSVC 2015, it is.
-// WIN64-18-LABEL: declare void @"\01?foo@implicitly_deleted@@YAXUA@1@@Z"(i64
-// WIN64-19-LABEL: declare void @"\01?foo@implicitly_deleted@@YAXUA@1@@Z"(%"struct.implicitly_deleted::A"*)
+// WIN64-18-LABEL: declare dso_local void @"?foo@implicitly_deleted@@YAXUA@1@@Z"(i64
+// WIN64-19-LABEL: declare dso_local void @"?foo@implicitly_deleted@@YAXUA@1@@Z"(%"struct.implicitly_deleted::A"*)
}
namespace one_deleted {
@@ -129,7 +129,7 @@ void bar() {
// NEWABI-LABEL: declare void @_ZN11one_deleted3fooENS_1AE(%"struct.one_deleted::A"*)
// OLDABI-LABEL: declare void @_ZN11one_deleted3fooENS_1AE(i8*)
-// WIN64-LABEL: declare void @"\01?foo@one_deleted@@YAXUA@1@@Z"(%"struct.one_deleted::A"*)
+// WIN64-LABEL: declare dso_local void @"?foo@one_deleted@@YAXUA@1@@Z"(%"struct.one_deleted::A"*)
}
namespace copy_defaulted {
@@ -149,7 +149,7 @@ void bar() {
// CHECK: call void @_ZN14copy_defaulted3fooENS_1AE(i8* %{{.*}})
// CHECK-LABEL: declare void @_ZN14copy_defaulted3fooENS_1AE(i8*)
-// WIN64-LABEL: declare void @"\01?foo@copy_defaulted@@YAXUA@1@@Z"(i64)
+// WIN64-LABEL: declare dso_local void @"?foo@copy_defaulted@@YAXUA@1@@Z"(i64)
}
namespace move_defaulted {
@@ -169,7 +169,7 @@ void bar() {
// CHECK: call void @_ZN14move_defaulted3fooENS_1AE(i8* %{{.*}})
// CHECK-LABEL: declare void @_ZN14move_defaulted3fooENS_1AE(i8*)
-// WIN64-LABEL: declare void @"\01?foo@move_defaulted@@YAXUA@1@@Z"(%"struct.move_defaulted::A"*)
+// WIN64-LABEL: declare dso_local void @"?foo@move_defaulted@@YAXUA@1@@Z"(%"struct.move_defaulted::A"*)
}
namespace trivial_defaulted {
@@ -188,7 +188,7 @@ void bar() {
// CHECK: call void @_ZN17trivial_defaulted3fooENS_1AE(i8* %{{.*}})
// CHECK-LABEL: declare void @_ZN17trivial_defaulted3fooENS_1AE(i8*)
-// WIN64-LABEL: declare void @"\01?foo@trivial_defaulted@@YAXUA@1@@Z"(i64)
+// WIN64-LABEL: declare dso_local void @"?foo@trivial_defaulted@@YAXUA@1@@Z"(i64)
}
namespace two_copy_ctors {
@@ -211,7 +211,7 @@ void bar() {
// NEWABI-LABEL: declare void @_ZN14two_copy_ctors3fooENS_1BE(%"struct.two_copy_ctors::B"*)
// OLDABI-LABEL: declare void @_ZN14two_copy_ctors3fooENS_1BE(%"struct.two_copy_ctors::B"* byval
-// WIN64-LABEL: declare void @"\01?foo@two_copy_ctors@@YAXUB@1@@Z"(%"struct.two_copy_ctors::B"*)
+// WIN64-LABEL: declare dso_local void @"?foo@two_copy_ctors@@YAXUB@1@@Z"(%"struct.two_copy_ctors::B"*)
}
namespace definition_only {
@@ -223,7 +223,7 @@ struct A {
void *foo(A a) { return a.p; }
// NEWABI-LABEL: define i8* @_ZN15definition_only3fooENS_1AE(%"struct.definition_only::A"*
// OLDABI-LABEL: define i8* @_ZN15definition_only3fooENS_1AE(i8*
-// WIN64-LABEL: define i8* @"\01?foo@definition_only@@YAPEAXUA@1@@Z"(%"struct.definition_only::A"*
+// WIN64-LABEL: define dso_local i8* @"?foo@definition_only@@YAPEAXUA@1@@Z"(%"struct.definition_only::A"*
}
namespace deleted_by_member {
@@ -239,7 +239,7 @@ struct A {
void *foo(A a) { return a.b.p; }
// NEWABI-LABEL: define i8* @_ZN17deleted_by_member3fooENS_1AE(%"struct.deleted_by_member::A"*
// OLDABI-LABEL: define i8* @_ZN17deleted_by_member3fooENS_1AE(i8*
-// WIN64-LABEL: define i8* @"\01?foo@deleted_by_member@@YAPEAXUA@1@@Z"(%"struct.deleted_by_member::A"*
+// WIN64-LABEL: define dso_local i8* @"?foo@deleted_by_member@@YAPEAXUA@1@@Z"(%"struct.deleted_by_member::A"*
}
namespace deleted_by_base {
@@ -254,7 +254,7 @@ struct A : B {
void *foo(A a) { return a.p; }
// NEWABI-LABEL: define i8* @_ZN15deleted_by_base3fooENS_1AE(%"struct.deleted_by_base::A"*
// OLDABI-LABEL: define i8* @_ZN15deleted_by_base3fooENS_1AE(i8*
-// WIN64-LABEL: define i8* @"\01?foo@deleted_by_base@@YAPEAXUA@1@@Z"(%"struct.deleted_by_base::A"*
+// WIN64-LABEL: define dso_local i8* @"?foo@deleted_by_base@@YAPEAXUA@1@@Z"(%"struct.deleted_by_base::A"*
}
namespace deleted_by_member_copy {
@@ -270,7 +270,7 @@ struct A {
void *foo(A a) { return a.b.p; }
// NEWABI-LABEL: define i8* @_ZN22deleted_by_member_copy3fooENS_1AE(%"struct.deleted_by_member_copy::A"*
// OLDABI-LABEL: define i8* @_ZN22deleted_by_member_copy3fooENS_1AE(i8*
-// WIN64-LABEL: define i8* @"\01?foo@deleted_by_member_copy@@YAPEAXUA@1@@Z"(%"struct.deleted_by_member_copy::A"*
+// WIN64-LABEL: define dso_local i8* @"?foo@deleted_by_member_copy@@YAPEAXUA@1@@Z"(%"struct.deleted_by_member_copy::A"*
}
namespace deleted_by_base_copy {
@@ -285,7 +285,7 @@ struct A : B {
void *foo(A a) { return a.p; }
// NEWABI-LABEL: define i8* @_ZN20deleted_by_base_copy3fooENS_1AE(%"struct.deleted_by_base_copy::A"*
// OLDABI-LABEL: define i8* @_ZN20deleted_by_base_copy3fooENS_1AE(i8*
-// WIN64-LABEL: define i8* @"\01?foo@deleted_by_base_copy@@YAPEAXUA@1@@Z"(%"struct.deleted_by_base_copy::A"*
+// WIN64-LABEL: define dso_local i8* @"?foo@deleted_by_base_copy@@YAPEAXUA@1@@Z"(%"struct.deleted_by_base_copy::A"*
}
namespace explicit_delete {
@@ -296,7 +296,7 @@ struct A {
};
// NEWABI-LABEL: define i8* @_ZN15explicit_delete3fooENS_1AE(%"struct.explicit_delete::A"*
// OLDABI-LABEL: define i8* @_ZN15explicit_delete3fooENS_1AE(i8*
-// WIN64-LABEL: define i8* @"\01?foo@explicit_delete@@YAPEAXUA@1@@Z"(%"struct.explicit_delete::A"*
+// WIN64-LABEL: define dso_local i8* @"?foo@explicit_delete@@YAPEAXUA@1@@Z"(%"struct.explicit_delete::A"*
void *foo(A a) { return a.p; }
}
@@ -309,7 +309,7 @@ struct A {
};
// NEWABI-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1AE(%"struct.implicitly_deleted_copy_ctor::A"*
// OLDABI-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1AE(i32*
-// WIN64-LABEL: define {{.*}} @"\01?foo@implicitly_deleted_copy_ctor@@YAAEAHUA@1@@Z"(%"struct.implicitly_deleted_copy_ctor::A"*
+// WIN64-LABEL: define {{.*}} @"?foo@implicitly_deleted_copy_ctor@@YAAEAHUA@1@@Z"(%"struct.implicitly_deleted_copy_ctor::A"*
int &foo(A a) { return a.ref; }
struct B {
@@ -319,7 +319,7 @@ struct B {
};
int &foo(B b) { return b.ref; }
// CHECK-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1BE(i32*
-// WIN64-LABEL: define {{.*}} @"\01?foo@implicitly_deleted_copy_ctor@@YAAEAHUB@1@@Z"(i64
+// WIN64-LABEL: define {{.*}} @"?foo@implicitly_deleted_copy_ctor@@YAAEAHUB@1@@Z"(i64
struct X { X(const X&); };
struct Y { Y(const Y&) = default; };
@@ -332,7 +332,7 @@ union C {
};
int foo(C c) { return c.n; }
// CHECK-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1CE(%"union.implicitly_deleted_copy_ctor::C"*
-// WIN64-LABEL: define {{.*}} @"\01?foo@implicitly_deleted_copy_ctor@@YAHTC@1@@Z"(%"union.implicitly_deleted_copy_ctor::C"*
+// WIN64-LABEL: define {{.*}} @"?foo@implicitly_deleted_copy_ctor@@YAHTC@1@@Z"(%"union.implicitly_deleted_copy_ctor::C"*
struct D {
D &operator=(const D&);
@@ -344,7 +344,7 @@ struct D {
};
int foo(D d) { return d.n; }
// CHECK-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1DE(%"struct.implicitly_deleted_copy_ctor::D"*
-// WIN64-LABEL: define {{.*}} @"\01?foo@implicitly_deleted_copy_ctor@@YAHUD@1@@Z"(%"struct.implicitly_deleted_copy_ctor::D"*
+// WIN64-LABEL: define {{.*}} @"?foo@implicitly_deleted_copy_ctor@@YAHUD@1@@Z"(%"struct.implicitly_deleted_copy_ctor::D"*
union E {
// Passed direct: has non-deleted trivial copy ctor.
@@ -354,7 +354,7 @@ union E {
};
int foo(E e) { return e.n; }
// CHECK-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1EE(i32
-// WIN64-LABEL: define {{.*}} @"\01?foo@implicitly_deleted_copy_ctor@@YAHTE@1@@Z"(i32
+// WIN64-LABEL: define {{.*}} @"?foo@implicitly_deleted_copy_ctor@@YAHTE@1@@Z"(i32
struct F {
// Passed direct: has non-deleted trivial copy ctor.
@@ -366,5 +366,5 @@ struct F {
};
int foo(F f) { return f.n; }
// CHECK-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1FE(i32
-// WIN64-LABEL: define {{.*}} @"\01?foo@implicitly_deleted_copy_ctor@@YAHUF@1@@Z"(i32
+// WIN64-LABEL: define {{.*}} @"?foo@implicitly_deleted_copy_ctor@@YAHUF@1@@Z"(i32
}
diff --git a/test/CodeGenCXX/value-init.cpp b/test/CodeGenCXX/value-init.cpp
index fc4e0d3a55e0..8d76fc534611 100644
--- a/test/CodeGenCXX/value-init.cpp
+++ b/test/CodeGenCXX/value-init.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -std=c++98 %s -triple x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -std=c++98 %s -triple x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-CXX98
+// RUN: %clang_cc1 -std=c++17 %s -triple x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-CXX17
struct A {
virtual ~A();
@@ -114,13 +115,15 @@ void f() {
// CHECK: call void @llvm.memset.p0i8.i64
// CHECK-NOT: call void @llvm.memset.p0i8.i64
- // CHECK: call void @_ZN6PR98015Test2C1Ev
+ // CHECK-CXX98: call void @_ZN6PR98015Test2C1Ev
+ // CHECK-CXX17: call void @_ZN6PR98014TestC1Ev
// CHECK-NOT: call void @_ZN6PR98015Test2C1Ev
Test2 empty2[3] = {};
// CHECK: call void @llvm.memset.p0i8.i64
// CHECK-NOT: call void @llvm.memset.p0i8.i64
- // CHECK: call void @_ZN6PR98015Test3C1Ev
+ // CHECK-CXX98: call void @_ZN6PR98015Test3C1Ev
+ // CHECK-CXX17: call void @_ZN6PR98014TestC2Ev
// CHECK-NOT: call void @llvm.memset.p0i8.i64
// CHECK-NOT: call void @_ZN6PR98015Test3C1Ev
Test3 empty3[3] = {};
@@ -222,7 +225,7 @@ namespace test6 {
// CHECK: [[CUR:%.*]] = phi [20 x [[A]]]* [ [[BEGIN]], {{%.*}} ], [ [[NEXT:%.*]], {{%.*}} ]
// Inner loop.
- // CHECK-NEXT: [[IBEGIN:%.*]] = getelementptr inbounds [20 x [[A]]], [20 x [[A]]]* [[CUR]], i32 0, i32 0
+ // CHECK-NEXT: [[IBEGIN:%.*]] = getelementptr inbounds [20 x [[A]]], [20 x [[A]]]* [[CUR]], i{{32|64}} 0, i{{32|64}} 0
// CHECK-NEXT: [[IEND:%.*]] = getelementptr inbounds [[A]], [[A]]* [[IBEGIN]], i64 20
// CHECK-NEXT: br label
// CHECK: [[ICUR:%.*]] = phi [[A]]* [ [[IBEGIN]], {{%.*}} ], [ [[INEXT:%.*]], {{%.*}} ]
@@ -244,7 +247,7 @@ namespace PR11124 {
struct C : B { C(); };
C::C() : A(3), B() {}
// CHECK-LABEL: define void @_ZN7PR111241CC1Ev
- // CHECK: call void @llvm.memset.p0i8.i64(i8* {{.*}}, i8 0, i64 12, i32 8, i1 false)
+ // CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 {{.*}}, i8 0, i64 12, i1 false)
// CHECK-NEXT: call void @_ZN7PR111241BC2Ev
// Make sure C::C doesn't overwrite parts of A while it is zero-initializing B
@@ -252,7 +255,7 @@ namespace PR11124 {
struct C2 : B2 { C2(); };
C2::C2() : A(3), B2() {}
// CHECK-LABEL: define void @_ZN7PR111242C2C1Ev
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.*}}, i8* {{.*}}, i64 16, i32 8, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %{{.*}}, i8* align 8 {{.*}}, i64 16, i1 false)
// CHECK-NEXT: call void @_ZN7PR111242B2C2Ev
}
@@ -327,3 +330,12 @@ int explicitly_defaulted() {
// CHECK: call void @llvm.memset.p0i8.i64
// CHECK-NEXT: call void @_ZN8zeroinit2X2IiEC2Ev
// CHECK-NEXT: ret void
+
+#if __cplusplus >= 201103L
+namespace transparent_init_list {
+ struct optional_assign_base {};
+ struct optional_data_dtor_base { char dummy_[24]; };
+ struct optional : optional_data_dtor_base, optional_assign_base {};
+ optional f(optional a) { return {optional(a)}; }
+}
+#endif
diff --git a/test/CodeGenCXX/vararg-non-pod-ms-compat.cpp b/test/CodeGenCXX/vararg-non-pod-ms-compat.cpp
index 64b1c525a614..8f413021b3d0 100644
--- a/test/CodeGenCXX/vararg-non-pod-ms-compat.cpp
+++ b/test/CodeGenCXX/vararg-non-pod-ms-compat.cpp
@@ -10,17 +10,17 @@ struct X {
void vararg(...);
void test(X x) {
- // CHECK-LABEL: define void @"\01?test@@YAXUX@@@Z"
+ // CHECK-LABEL: define dso_local void @"?test@@YAXUX@@@Z"
// X86: %[[argmem:[^ ]*]] = alloca inalloca <{ %struct.X }>
- // X86: call void (<{ %struct.X }>*, ...) bitcast (void (...)* @"\01?vararg@@YAXZZ" to void (<{ %struct.X }>*, ...)*)(<{ %struct.X }>* inalloca %[[argmem]])
+ // X86: call void (<{ %struct.X }>*, ...) bitcast (void (...)* @"?vararg@@YAXZZ" to void (<{ %struct.X }>*, ...)*)(<{ %struct.X }>* inalloca %[[argmem]])
// X64: alloca %struct.X
// X64: %[[agg:[^ ]*]] = alloca %struct.X
// X64: %[[valptr:[^ ]*]] = getelementptr inbounds %struct.X, %struct.X* %[[agg]], i32 0, i32 0
// X64: %[[val:[^ ]*]] = load i32, i32* %[[valptr]]
- // X64: call void (...) @"\01?vararg@@YAXZZ"(i32 %[[val]])
+ // X64: call void (...) @"?vararg@@YAXZZ"(i32 %[[val]])
// CHECK-NOT: llvm.trap
vararg(x);
diff --git a/test/CodeGenCXX/varargs.cpp b/test/CodeGenCXX/varargs.cpp
index e0165994d013..1f82d6098269 100644
--- a/test/CodeGenCXX/varargs.cpp
+++ b/test/CodeGenCXX/varargs.cpp
@@ -35,7 +35,7 @@ namespace test1 {
// CHECK-NEXT: [[TMP:%.*]] = alloca [[A]], align 4
// CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]* [[TMP]] to i8*
// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[X]] to i8*
- // CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T0]], i8* [[T1]], i64 8, i32 4, i1 false)
+ // CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[T0]], i8* align 4 [[T1]], i64 8, i1 false)
// CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]* [[TMP]] to i64*
// CHECK-NEXT: [[T1:%.*]] = load i64, i64* [[T0]], align 4
// CHECK-NEXT: call void (...) @_ZN5test13fooEz(i64 [[T1]])
diff --git a/test/CodeGenCXX/virt-template-vtable.cpp b/test/CodeGenCXX/virt-template-vtable.cpp
index a71db48a79a0..66d2332ca334 100644
--- a/test/CodeGenCXX/virt-template-vtable.cpp
+++ b/test/CodeGenCXX/virt-template-vtable.cpp
@@ -16,10 +16,10 @@ extern template class A<short>;
template class A<short>;
-// CHECK: @_ZTV1B = linkonce_odr unnamed_addr constant
-// CHECK: @_ZTV1AIlE = weak_odr unnamed_addr constant
-// CHECK: @_ZTV1AIsE = weak_odr unnamed_addr constant
-// CHECK: @_ZTV1AIiE = linkonce_odr unnamed_addr constant
+// CHECK: @_ZTV1B = linkonce_odr {{(dso_local )?}}unnamed_addr constant
+// CHECK: @_ZTV1AIlE = weak_odr {{(dso_local )?}}unnamed_addr constant
+// CHECK: @_ZTV1AIsE = weak_odr {{(dso_local )?}}unnamed_addr constant
+// CHECK: @_ZTV1AIiE = linkonce_odr {{(dso_local )?}}unnamed_addr constant
template<class T> struct C {
virtual void c() {}
diff --git a/test/CodeGenCXX/virtual-base-cast.cpp b/test/CodeGenCXX/virtual-base-cast.cpp
index b2f2b4f2b319..d3a799933db4 100644
--- a/test/CodeGenCXX/virtual-base-cast.cpp
+++ b/test/CodeGenCXX/virtual-base-cast.cpp
@@ -18,7 +18,7 @@ A* a() { return x; }
// CHECK: load i32, i32* [[CASTVBASEOFFSETPTRA]]
// CHECK: }
-// MSVC: @"\01?a@@YAPAUA@@XZ"() [[NUW:#[0-9]+]] {
+// MSVC: @"?a@@YAPAUA@@XZ"() [[NUW:#[0-9]+]] {
// MSVC: %[[vbptr_off:.*]] = getelementptr inbounds i8, i8* {{.*}}, i32 0
// MSVC: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i32**
// MSVC: %[[vbtable:.*]] = load i32*, i32** %[[vbptr]]
@@ -35,7 +35,7 @@ B* b() { return x; }
// CHECK: }
// Same as 'a' except we use a different vbtable offset.
-// MSVC: @"\01?b@@YAPAUB@@XZ"() [[NUW:#[0-9]+]] {
+// MSVC: @"?b@@YAPAUB@@XZ"() [[NUW:#[0-9]+]] {
// MSVC: %[[vbptr_off:.*]] = getelementptr inbounds i8, i8* {{.*}}, i32 0
// MSVC: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i32**
// MSVC: %[[vbtable:.*]] = load i32*, i32** %[[vbptr]]
@@ -54,7 +54,7 @@ BB* c() { return x; }
// CHECK: }
// Same as 'a' except we use a different vbtable offset.
-// MSVC: @"\01?c@@YAPAUBB@@XZ"() [[NUW:#[0-9]+]] {
+// MSVC: @"?c@@YAPAUBB@@XZ"() [[NUW:#[0-9]+]] {
// MSVC: %[[vbptr_off:.*]] = getelementptr inbounds i8, i8* {{.*}}, i32 0
// MSVC: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i32**
// MSVC: %[[vbtable:.*]] = load i32*, i32** %[[vbptr]]
@@ -73,7 +73,7 @@ BB* d() { return y; }
// Same as 'c' except the vbptr offset is 4, changing the initial GEP and the
// final add.
-// MSVC: @"\01?d@@YAPAUBB@@XZ"() [[NUW:#[0-9]+]] {
+// MSVC: @"?d@@YAPAUBB@@XZ"() [[NUW:#[0-9]+]] {
// MSVC: %[[vbptr_off:.*]] = getelementptr inbounds i8, i8* {{.*}}, i32 4
// MSVC: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i32**
// MSVC: %[[vbtable:.*]] = load i32*, i32** %[[vbptr]]
diff --git a/test/CodeGenCXX/virtual-base-ctor.cpp b/test/CodeGenCXX/virtual-base-ctor.cpp
index 8c8c310421dc..e32296f1641f 100644
--- a/test/CodeGenCXX/virtual-base-ctor.cpp
+++ b/test/CodeGenCXX/virtual-base-ctor.cpp
@@ -8,4 +8,4 @@ struct A { int a; A() { y = ((size_t)this - (size_t)&x) / sizeof(void*); } };
struct B : virtual A { void* x; };
B x;
-// CHECK: @y = local_unnamed_addr global i8 2
+// CHECK: @y = {{(dso_local )?}}local_unnamed_addr global i8 2
diff --git a/test/CodeGenCXX/virtual-bases.cpp b/test/CodeGenCXX/virtual-bases.cpp
index e9c568c31b48..259b1c157b1e 100644
--- a/test/CodeGenCXX/virtual-bases.cpp
+++ b/test/CodeGenCXX/virtual-bases.cpp
@@ -4,7 +4,7 @@ struct A {
A();
};
-// CHECK: @_ZN1AC1Ev = alias {{.*}} @_ZN1AC2Ev
+// CHECK: @_ZN1AC1Ev = unnamed_addr alias {{.*}} @_ZN1AC2Ev
// CHECK-LABEL: define void @_ZN1AC2Ev(%struct.A* %this) unnamed_addr
A::A() { }
@@ -46,3 +46,37 @@ struct D : B, C {
D::D() { }
}
+
+namespace virtualBaseAlignment {
+
+// Check that the store to B::x in the base constructor has an 8-byte alignment.
+
+// CHECK: define linkonce_odr void @_ZN20virtualBaseAlignment1BC1Ev(%[[STRUCT_B:.*]]* %[[THIS:.*]])
+// CHECK: %[[THIS_ADDR:.*]] = alloca %[[STRUCT_B]]*, align 8
+// CHECK: store %[[STRUCT_B]]* %[[THIS]], %[[STRUCT_B]]** %[[THIS_ADDR]], align 8
+// CHECK: %[[THIS1:.*]] = load %[[STRUCT_B]]*, %[[STRUCT_B]]** %[[THIS_ADDR]], align 8
+// CHECK: %[[X:.*]] = getelementptr inbounds %[[STRUCT_B]], %[[STRUCT_B]]* %[[THIS1]], i32 0, i32 2
+// CHECK: store i32 123, i32* %[[X]], align 16
+
+// CHECK: define linkonce_odr void @_ZN20virtualBaseAlignment1BC2Ev(%[[STRUCT_B]]* %[[THIS:.*]], i8** %{{.*}})
+// CHECK: %[[THIS_ADDR:.*]] = alloca %[[STRUCT_B]]*, align 8
+// CHECK: store %[[STRUCT_B]]* %[[THIS]], %[[STRUCT_B]]** %[[THIS_ADDR]], align 8
+// CHECK: %[[THIS1:.*]] = load %[[STRUCT_B]]*, %[[STRUCT_B]]** %[[THIS_ADDR]], align 8
+// CHECK: %[[X:.*]] = getelementptr inbounds %[[STRUCT_B]], %[[STRUCT_B]]* %[[THIS1]], i32 0, i32 2
+// CHECK: store i32 123, i32* %[[X]], align 8
+
+struct A {
+ __attribute__((aligned(16))) double data1;
+};
+
+struct B : public virtual A {
+ B() : x(123) {}
+ double a;
+ int x;
+};
+
+struct C : public virtual B {};
+
+void test() { B b; C c; }
+
+}
diff --git a/test/CodeGenCXX/virtual-destructor-calls.cpp b/test/CodeGenCXX/virtual-destructor-calls.cpp
index 2e63daac31de..10d82367fde8 100644
--- a/test/CodeGenCXX/virtual-destructor-calls.cpp
+++ b/test/CodeGenCXX/virtual-destructor-calls.cpp
@@ -14,11 +14,11 @@ struct B : A {
};
// Complete dtor: just an alias because there are no virtual bases.
-// CHECK: @_ZN1BD1Ev = alias {{.*}} @_ZN1BD2Ev
+// CHECK: @_ZN1BD1Ev = unnamed_addr alias {{.*}} @_ZN1BD2Ev
// (aliases from C)
-// CHECK: @_ZN1CD2Ev = alias {{.*}}, bitcast {{.*}} @_ZN1BD2Ev
-// CHECK: @_ZN1CD1Ev = alias {{.*}} @_ZN1CD2Ev
+// CHECK: @_ZN1CD2Ev = unnamed_addr alias {{.*}}, bitcast {{.*}} @_ZN1BD2Ev
+// CHECK: @_ZN1CD1Ev = unnamed_addr alias {{.*}} @_ZN1CD2Ev
// Base dtor: actually calls A's base dtor.
// CHECK-LABEL: define void @_ZN1BD2Ev(%struct.B* %this) unnamed_addr
diff --git a/test/CodeGenCXX/virtual-function-attrs.cpp b/test/CodeGenCXX/virtual-function-attrs.cpp
index 3a9a1a28ddf4..873412d47545 100644
--- a/test/CodeGenCXX/virtual-function-attrs.cpp
+++ b/test/CodeGenCXX/virtual-function-attrs.cpp
@@ -8,7 +8,7 @@ class A {
void A::f() {}
-// CHECK: define [[CC:(x86_thiscallcc )?]]void @_ZN1A1fEv({{.*}}) unnamed_addr
-// CHECK: declare [[CC]]void @_ZN1A1gEv({{.*}}) unnamed_addr
+// CHECK: define {{(dso_local )?}}[[CC:(x86_thiscallcc )?]]void @_ZN1A1fEv({{.*}}) unnamed_addr
+// CHECK: declare {{(dso_local )?}}[[CC]]void @_ZN1A1gEv({{.*}}) unnamed_addr
// CHECK: declare {{.*}} @_ZN1AD1Ev({{.*}}) unnamed_addr
-// CHECK: declare [[CC]]void @_ZN1AD0Ev({{.*}}) unnamed_addr
+// CHECK: declare {{(dso_local )?}}[[CC]]void @_ZN1AD0Ev({{.*}}) unnamed_addr
diff --git a/test/CodeGenCXX/virtual-function-calls.cpp b/test/CodeGenCXX/virtual-function-calls.cpp
index 22944d94ca88..61b2fbad7a3a 100644
--- a/test/CodeGenCXX/virtual-function-calls.cpp
+++ b/test/CodeGenCXX/virtual-function-calls.cpp
@@ -44,7 +44,7 @@ namespace VirtualNoreturn {
};
// CHECK-LABEL: @_ZN15VirtualNoreturn1f
- // CHECK-INVARIANT-LABEL: define void @_ZN15VirtualNoreturn1f
+ // CHECK-INVARIANT-LABEL: define {{(dso_local )?}}void @_ZN15VirtualNoreturn1f
void f(A *p) {
p->f();
// CHECK: call {{.*}}void %{{[^#]*$}}
diff --git a/test/CodeGenCXX/visibility-pr36810.cpp b/test/CodeGenCXX/visibility-pr36810.cpp
new file mode 100644
index 000000000000..5df1df685136
--- /dev/null
+++ b/test/CodeGenCXX/visibility-pr36810.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -triple x86_64-apple-macosx -std=c++11 -fvisibility hidden -emit-llvm -o - %s -O2 -disable-llvm-passes | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx -DUNDEF_G -std=c++11 -fvisibility hidden -emit-llvm -o - %s -O2 -disable-llvm-passes | FileCheck %s
+
+namespace std {
+template <class>
+class __attribute__((__type_visibility__("default"))) shared_ptr {
+ template <class> friend class shared_ptr;
+};
+}
+struct dict;
+#ifndef UNDEF_G
+std::shared_ptr<dict> g;
+#endif
+class __attribute__((visibility("default"))) Bar;
+template <class = std::shared_ptr<Bar>>
+class __attribute__((visibility("default"))) i {
+ std::shared_ptr<int> foo() const;
+};
+
+// CHECK: define void @_ZNK1iISt10shared_ptrI3BarEE3fooEv
+template <> std::shared_ptr<int> i<>::foo() const {
+ return std::shared_ptr<int>();
+}
diff --git a/test/CodeGenCXX/vla-consruct.cpp b/test/CodeGenCXX/vla-consruct.cpp
index fd8314a5d716..87191fe99da7 100644
--- a/test/CodeGenCXX/vla-consruct.cpp
+++ b/test/CodeGenCXX/vla-consruct.cpp
@@ -21,6 +21,8 @@ void test(int n) {
// CHECK: define void {{.*test.*}}(i32 [[n:%.+]]) #
// CHECK: [[n_addr:%.+]] = alloca
// CHECK-NEXT: [[saved_stack:%.+]] = alloca
+ // CHECK-NEXT: [[vla_expr:%.+]] = alloca i64, align 8
+ // CHECK-NEXT: [[vla_expr1:%.+]] = alloca i64, align 8
// CHECK-NEXT: [[sizeof_S:%.+]] = alloca
// CHECK-NEXT: [[sizeof_array_t_0_0:%.+]] = alloca
// CHECK-NEXT: [[sizeof_array_t_0:%.+]] = alloca
@@ -37,6 +39,8 @@ void test(int n) {
// CHECK-NEXT: store i8* [[t4]], i8** [[saved_stack]]
// CHECK-NEXT: [[t5:%.+]] = mul nuw i64 [[t1]], [[t3]]
// CHECK-NEXT: [[vla:%.+]] = alloca [[struct_S]], i64 [[t5]]
+ // CHECK-NEXT: store i64 [[t1]], i64* [[vla_expr]]
+ // CHECK-NEXT: store i64 [[t3]], i64* [[vla_expr1]]
// CHECK-NEXT: [[t6:%.+]] = mul nuw i64 [[t1]], [[t3]]
// CHECK-NEXT: [[isempty:%.+]] = icmp eq i64 [[t6]], 0
// CHECK-NEXT: br i1 [[isempty]], label %[[arrayctor_cont:.+]], label %[[new_ctorloop:.+]]
diff --git a/test/CodeGenCXX/vla.cpp b/test/CodeGenCXX/vla.cpp
index b8652f8329a5..81ff62d2cbf8 100644
--- a/test/CodeGenCXX/vla.cpp
+++ b/test/CodeGenCXX/vla.cpp
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin %s -emit-llvm -o - | FileCheck -check-prefixes=X64,CHECK %s
-// RUN: %clang_cc1 -std=c++11 -triple amdgcn---amdgiz %s -emit-llvm -o - | FileCheck -check-prefixes=AMD,CHECK %s
+// RUN: %clang_cc1 -std=c++11 -triple amdgcn %s -emit-llvm -o - | FileCheck -check-prefixes=AMDGCN,CHECK %s
template<typename T>
struct S {
@@ -19,17 +19,17 @@ int f() {
void test0(void *array, int n) {
// CHECK-LABEL: define void @_Z5test0Pvi(
// X64: [[ARRAY:%.*]] = alloca i8*, align 8
- // AMD: [[ARRAY0:%.*]] = alloca i8*, align 8, addrspace(5)
- // AMD-NEXT: [[ARRAY:%.*]] = addrspacecast i8* addrspace(5)* [[ARRAY0]] to i8**
+ // AMDGCN: [[ARRAY0:%.*]] = alloca i8*, align 8, addrspace(5)
+ // AMDGCN-NEXT: [[ARRAY:%.*]] = addrspacecast i8* addrspace(5)* [[ARRAY0]] to i8**
// X64-NEXT: [[N:%.*]] = alloca i32, align 4
- // AMD: [[N0:%.*]] = alloca i32, align 4, addrspace(5)
- // AMD-NEXT: [[N:%.*]] = addrspacecast i32 addrspace(5)* [[N0]] to i32*
+ // AMDGCN: [[N0:%.*]] = alloca i32, align 4, addrspace(5)
+ // AMDGCN-NEXT: [[N:%.*]] = addrspacecast i32 addrspace(5)* [[N0]] to i32*
// X64-NEXT: [[REF:%.*]] = alloca i16*, align 8
- // AMD: [[REF0:%.*]] = alloca i16*, align 8, addrspace(5)
- // AMD-NEXT: [[REF:%.*]] = addrspacecast i16* addrspace(5)* [[REF0]] to i16**
+ // AMDGCN: [[REF0:%.*]] = alloca i16*, align 8, addrspace(5)
+ // AMDGCN-NEXT: [[REF:%.*]] = addrspacecast i16* addrspace(5)* [[REF0]] to i16**
// X64-NEXT: [[S:%.*]] = alloca i16, align 2
- // AMD: [[S0:%.*]] = alloca i16, align 2, addrspace(5)
- // AMD-NEXT: [[S:%.*]] = addrspacecast i16 addrspace(5)* [[S0]] to i16*
+ // AMDGCN: [[S0:%.*]] = alloca i16, align 2, addrspace(5)
+ // AMDGCN-NEXT: [[S:%.*]] = addrspacecast i16 addrspace(5)* [[S0]] to i16*
// CHECK-NEXT: store i8*
// CHECK-NEXT: store i32
@@ -68,8 +68,8 @@ void test0(void *array, int n) {
void test2(int b) {
// CHECK-LABEL: define void {{.*}}test2{{.*}}(i32 %b)
int varr[b];
- // AMD: %__end = alloca i32*, align 8, addrspace(5)
- // AMD: [[END:%.*]] = addrspacecast i32* addrspace(5)* %__end to i32**
+ // AMDGCN: %__end1 = alloca i32*, align 8, addrspace(5)
+ // AMDGCN: [[END:%.*]] = addrspacecast i32* addrspace(5)* %__end1 to i32**
// get the address of %b by checking the first store that stores it
//CHECK: store i32 %b, i32* [[PTR_B:%.*]]
@@ -86,16 +86,16 @@ void test2(int b) {
//CHECK: [[VLA_SIZEOF:%.*]] = mul nuw i64 4, [[VLA_NUM_ELEMENTS_PRE]]
//CHECK-NEXT: [[VLA_NUM_ELEMENTS_POST:%.*]] = udiv i64 [[VLA_SIZEOF]], 4
//CHECK-NEXT: [[VLA_END_PTR:%.*]] = getelementptr inbounds i32, i32* {{%.*}}, i64 [[VLA_NUM_ELEMENTS_POST]]
- //X64-NEXT: store i32* [[VLA_END_PTR]], i32** %__end
- //AMD-NEXT: store i32* [[VLA_END_PTR]], i32** [[END]]
+ //X64-NEXT: store i32* [[VLA_END_PTR]], i32** %__end1
+ //AMDGCN-NEXT: store i32* [[VLA_END_PTR]], i32** [[END]]
for (int d : varr) 0;
}
void test3(int b, int c) {
// CHECK-LABEL: define void {{.*}}test3{{.*}}(i32 %b, i32 %c)
int varr[b][c];
- // AMD: %__end = alloca i32*, align 8, addrspace(5)
- // AMD: [[END:%.*]] = addrspacecast i32* addrspace(5)* %__end to i32**
+ // AMDGCN: %__end1 = alloca i32*, align 8, addrspace(5)
+ // AMDGCN: [[END:%.*]] = addrspacecast i32* addrspace(5)* %__end1 to i32**
// get the address of %b by checking the first store that stores it
//CHECK: store i32 %b, i32* [[PTR_B:%.*]]
//CHECK-NEXT: store i32 %c, i32* [[PTR_C:%.*]]
@@ -120,7 +120,7 @@ void test3(int b, int c) {
//CHECK-NEXT: [[VLA_END_INDEX:%.*]] = mul nsw i64 [[VLA_NUM_ELEMENTS]], [[VLA_DIM2_PRE]]
//CHECK-NEXT: [[VLA_END_PTR:%.*]] = getelementptr inbounds i32, i32* {{%.*}}, i64 [[VLA_END_INDEX]]
//X64-NEXT: store i32* [[VLA_END_PTR]], i32** %__end
- //AMD-NEXT: store i32* [[VLA_END_PTR]], i32** [[END]]
+ //AMDGCN-NEXT: store i32* [[VLA_END_PTR]], i32** [[END]]
for (auto &d : varr) 0;
}
diff --git a/test/CodeGenCXX/volatile-1.cpp b/test/CodeGenCXX/volatile-1.cpp
index 75fb0d26f413..525e828da393 100644
--- a/test/CodeGenCXX/volatile-1.cpp
+++ b/test/CodeGenCXX/volatile-1.cpp
@@ -1,11 +1,11 @@
// RUN: %clang_cc1 -Wno-unused-value -triple %itanium_abi_triple -emit-llvm %s -std=c++98 -o - | FileCheck %s
// RUN: %clang_cc1 -Wno-unused-value -triple %itanium_abi_triple -emit-llvm %s -std=c++11 -o - | FileCheck -check-prefix=CHECK -check-prefix=CHECK11 %s
-// CHECK: @i = global [[INT:i[0-9]+]] 0
+// CHECK: @i = {{(dso_local )?}}global [[INT:i[0-9]+]] 0
volatile int i, j, k;
volatile int ar[5];
volatile char c;
-// CHECK: @ci = global [[CINT:.*]] zeroinitializer
+// CHECK: @ci = {{(dso_local )?}}global [[CINT:.*]] zeroinitializer
volatile _Complex int ci;
volatile struct S {
#ifdef __cplusplus
diff --git a/test/CodeGenCXX/vtable-assume-load.cpp b/test/CodeGenCXX/vtable-assume-load.cpp
index b0857c29c654..d1c235039156 100644
--- a/test/CodeGenCXX/vtable-assume-load.cpp
+++ b/test/CodeGenCXX/vtable-assume-load.cpp
@@ -163,8 +163,8 @@ struct __declspec(novtable) S {
void g(S &s) { s.foo(); }
// if struct has novtable specifier, then we can't generate assumes
-// CHECK-MS-LABEL: define void @"\01?test@testMS@@YAXXZ"()
-// CHECK-MS: call x86_thiscallcc %"struct.testMS::S"* @"\01??0S@testMS@@QAE@XZ"(
+// CHECK-MS-LABEL: define dso_local void @"?test@testMS@@YAXXZ"()
+// CHECK-MS: call x86_thiscallcc %"struct.testMS::S"* @"??0S@testMS@@QAE@XZ"(
// CHECK-MS-NOT: @llvm.assume
// CHECK-MS-LABEL: {{^}}}
diff --git a/test/CodeGenCXX/vtable-available-externally.cpp b/test/CodeGenCXX/vtable-available-externally.cpp
index 0e7e8b4a3226..24c2eac23bec 100644
--- a/test/CodeGenCXX/vtable-available-externally.cpp
+++ b/test/CodeGenCXX/vtable-available-externally.cpp
@@ -1,22 +1,26 @@
// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -emit-llvm -o %t
// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.opt
-// RUN: FileCheck --check-prefix=CHECK-TEST1 %s < %t
-// RUN: FileCheck --check-prefix=CHECK-TEST2 %s < %t
-// RUN: FileCheck --check-prefix=CHECK-TEST5 %s < %t
-// RUN: FileCheck --check-prefix=CHECK-TEST8 %s < %t.opt
-// RUN: FileCheck --check-prefix=CHECK-TEST9 %s < %t.opt
-// RUN: FileCheck --check-prefix=CHECK-TEST10 %s < %t.opt
-// RUN: FileCheck --check-prefix=CHECK-TEST11 %s < %t.opt
-// RUN: FileCheck --check-prefix=CHECK-TEST12 %s < %t.opt
-// RUN: FileCheck --check-prefix=CHECK-TEST13 %s < %t.opt
-// RUN: FileCheck --check-prefix=CHECK-TEST14 %s < %t.opt
-// RUN: FileCheck --check-prefix=CHECK-TEST15 %s < %t.opt
-// RUN: FileCheck --check-prefix=CHECK-TEST16 %s < %t.opt
-// RUN: FileCheck --check-prefix=CHECK-TEST17 %s < %t.opt
+// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.vtable -fforce-emit-vtables -fstrict-vtable-pointers -mconstructor-aliases
+// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-TEST1 %s < %t
+// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-TEST2 %s < %t
+// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-TEST5 %s < %t
+// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-TEST8 %s < %t.opt
+// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-TEST9 %s < %t.opt
+// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-TEST10 %s < %t.opt
+// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-TEST11 %s < %t.opt
+// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-TEST12 %s < %t.opt
+// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-TEST13 %s < %t.opt
+// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-TEST14 %s < %t.opt
+// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-TEST15 %s < %t.opt
+// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-TEST16 %s < %t.opt
+// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-TEST17 %s < %t.opt
+// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-FORCE-EMIT %s < %t.vtable
+
#include <typeinfo>
// CHECK-TEST1: @_ZTVN5Test11AE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN5Test11AE = available_externally unnamed_addr constant
namespace Test1 {
struct A {
@@ -213,6 +217,7 @@ namespace Test10 {
// because A's key function is defined here, vtable is generated in this TU
// CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101AE = unnamed_addr constant
struct A {
virtual void foo();
virtual void bar();
@@ -221,6 +226,7 @@ void A::foo() {}
// Because key function is inline we will generate vtable as linkonce_odr.
// CHECK-TEST10-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant
struct D : A {
void bar();
};
@@ -237,6 +243,7 @@ struct B : A {
// can't guarantee that we will be able to refer to bar from name
// so (at the moment) we can't emit vtable available_externally.
// CHECK-TEST10-DAG: @_ZTVN6Test101CE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101CE = available_externally unnamed_addr constant
struct C : A {
void bar() {} // defined in body - not key function
virtual inline void gar(); // inline in body - not key function
@@ -245,6 +252,8 @@ struct C : A {
// no key function, vtable will be generated everywhere it will be used
// CHECK-TEST10-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant
+
struct E : A {};
void g(A& a) {
@@ -298,11 +307,13 @@ void g() {
namespace Test12 {
// CHECK-TEST12: @_ZTVN6Test121AE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121AE = available_externally unnamed_addr constant
struct A {
virtual void foo();
virtual ~A() {}
};
// CHECK-TEST12: @_ZTVN6Test121BE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121BE = available_externally unnamed_addr constant
struct B : A {
void foo();
};
@@ -319,6 +330,9 @@ namespace Test13 {
// CHECK-TEST13-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant
// CHECK-TEST13-DAG: @_ZTVN6Test131BE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131BE = available_externally unnamed_addr constant
+
struct A {
virtual ~A();
};
@@ -371,6 +385,8 @@ namespace Test16 {
// generate available_externally vtable for it.
// CHECK-TEST16-DAG: @_ZTVN6Test161SE = external unnamed_addr constant
// CHECK-TEST16-DAG: @_ZTVN6Test162S2E = available_externally
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test161SE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test162S2E = available_externally
struct S {
__attribute__((visibility("hidden"))) virtual void doStuff();
@@ -395,6 +411,10 @@ namespace Test17 {
// This test checks if we emit vtables opportunistically.
// CHECK-TEST17-DAG: @_ZTVN6Test171AE = available_externally
// CHECK-TEST17-DAG: @_ZTVN6Test171BE = external
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test171AE = available_externally
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test171BE = available_externally
+// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test171BD2Ev(
+// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test171BD0Ev(
struct A {
virtual void key();
@@ -418,3 +438,111 @@ void testcaseB() {
}
} // namespace Test17
+
+namespace Test18 {
+// Here vtable will be only emitted because it is referenced by assume-load
+// after the Derived construction.
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test187DerivedE = linkonce_odr unnamed_addr constant {{.*}} @_ZTIN6Test187DerivedE {{.*}} @_ZN6Test184Base3funEv {{.*}} @_ZN6Test184BaseD2Ev {{.*}} @_ZN6Test187DerivedD0Ev
+// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test187DerivedD0Ev
+// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test184BaseD2Ev
+// CHECK-FORCE-EMIT-DAG: define linkonce_odr i32 @_ZN6Test184Base3funEv
+// CHECK-FORCE-EMIT-DAG: @_ZTIN6Test187DerivedE = linkonce_odr constant
+
+struct Base {
+ virtual int fun() { return 42; }
+ virtual ~Base() { }
+};
+
+struct Derived : Base {
+ Derived();
+};
+
+int foo() {
+ Derived *der = new Derived();
+ return der->fun();
+}
+}
+
+namespace TestTemplates {
+
+// CHECK-FORCE-EMIT-DAG: @_ZTVN13TestTemplates8TemplateIiEE = linkonce_odr unnamed_addr constant {{.*}} @_ZTIN13TestTemplates8TemplateIiEE {{.*}} @_ZN13TestTemplates8TemplateIiE3fooEi {{.*}}@_ZN13TestTemplates8TemplateIiE22thisShouldBeEmittedTooEi {{.*}}@_ZN13TestTemplates8TemplateIiED1Ev {{.*}}@_ZN13TestTemplates8TemplateIiED0Ev
+// CHECK-FORCE-EMIT-DAG: define linkonce_odr i32 @_ZN13TestTemplates8TemplateIiE22thisShouldBeEmittedTooEi
+
+template<class T>
+struct Template {
+ Template();
+ virtual T foo(T val);
+ // CHECK-FORCE-EMIT-DAG: define linkonce_odr i32 @_ZN13TestTemplates8TemplateIiE22thisShouldBeEmittedTooEi
+ virtual T thisShouldBeEmittedToo(T val) { return val; }
+ virtual ~Template();
+};
+
+
+struct NonTemplate {
+ typedef int T;
+ NonTemplate();
+ virtual T foo(T val);
+ // CHECK-FORCE-EMIT-DAG: define linkonce_odr i32 @_ZN13TestTemplates11NonTemplate22thisShouldBeEmittedTooEi
+ virtual T thisShouldBeEmittedToo(T val) { return val; }
+ virtual ~NonTemplate();
+};
+
+// CHECK-FORCE-EMIT-DAG: @_ZTVN13TestTemplates16OuterNonTemplate27NestedTemplateInNonTemplateIiEE = linkonce_odr {{.*}} @_ZTIN13TestTemplates16OuterNonTemplate27NestedTemplateInNonTemplateIiEE {{.*}} @_ZN13TestTemplates16OuterNonTemplate27NestedTemplateInNonTemplateIiE3fooEi {{.*}} @_ZN13TestTemplates16OuterNonTemplate27NestedTemplateInNonTemplateIiE22thisShouldBeEmittedTooEi {{.*}} @_ZN13TestTemplates16OuterNonTemplate27NestedTemplateInNonTemplateIiED1Ev {{.*}} @_ZN13TestTemplates16OuterNonTemplate27NestedTemplateInNonTemplateIiED0Ev
+
+struct OuterNonTemplate {
+ template<class T>
+ struct NestedTemplateInNonTemplate {
+ NestedTemplateInNonTemplate();
+ virtual T foo(T val);
+ // CHECK-FORCE-EMIT-DAG: define linkonce_odr i32 @_ZN13TestTemplates16OuterNonTemplate27NestedTemplateInNonTemplateIiE22thisShouldBeEmittedTooEi
+ virtual T thisShouldBeEmittedToo(T val) { return val; }
+ virtual ~NestedTemplateInNonTemplate();
+ };
+
+ struct NestedNonTemplateInNonTemplate {
+ typedef int T;
+ NestedNonTemplateInNonTemplate();
+ virtual T foo(T val);
+ // CHECK-FORCE-EMIT-DAG: define linkonce_odr i32 @_ZN13TestTemplates16OuterNonTemplate30NestedNonTemplateInNonTemplate22thisShouldBeEmittedTooEi
+ virtual T thisShouldBeEmittedToo(T val) { return val; }
+ virtual ~NestedNonTemplateInNonTemplate();
+ };
+};
+
+template<class>
+struct OuterTemplate {
+ template<class T>
+ struct NestedTemplateInTemplate {
+ NestedTemplateInTemplate();
+ virtual T foo(T val);
+ // CHECK-FORCE-EMIT-DAG: define linkonce_odr i32 @_ZN13TestTemplates13OuterTemplateIlE24NestedTemplateInTemplateIiE22thisShouldBeEmittedTooEi
+ virtual T thisShouldBeEmittedToo(T val) { return val; }
+ virtual ~NestedTemplateInTemplate();
+ };
+
+ struct NestedNonTemplateInTemplate {
+ typedef int T;
+ NestedNonTemplateInTemplate();
+ virtual T foo(T val);
+ // CHECK-FORCE-EMIT-DAG: define linkonce_odr i32 @_ZN13TestTemplates13OuterTemplateIlE27NestedNonTemplateInTemplate22thisShouldBeEmittedTooEi
+ virtual T thisShouldBeEmittedToo(T val) { return val; }
+ virtual ~NestedNonTemplateInTemplate();
+ };
+};
+
+template<class T>
+int use() {
+ T *ptr = new T();
+ return ptr->foo(42);
+}
+
+void test() {
+ use<Template<int> >();
+ use<OuterTemplate<long>::NestedTemplateInTemplate<int> >();
+ use<OuterNonTemplate::NestedTemplateInNonTemplate<int> >();
+
+ use<NonTemplate>();
+ use<OuterTemplate<long>::NestedNonTemplateInTemplate>();
+ use<OuterNonTemplate::NestedNonTemplateInNonTemplate>();
+}
+}
diff --git a/test/CodeGenCXX/vtable-key-function-ios.cpp b/test/CodeGenCXX/vtable-key-function-ios.cpp
index 8a3466beda44..a119c780bb4e 100644
--- a/test/CodeGenCXX/vtable-key-function-ios.cpp
+++ b/test/CodeGenCXX/vtable-key-function-ios.cpp
@@ -28,8 +28,8 @@ struct Test0a {
// V-table should be defined externally.
Test0a::Test0a() { use(typeid(Test0a)); }
-// CHECK: @_ZTV6Test0a = external unnamed_addr constant
-// CHECK: @_ZTI6Test0a = external constant
+// CHECK: @_ZTV6Test0a = external {{(dso_local )?}}unnamed_addr constant
+// CHECK: @_ZTI6Test0a = external {{(dso_local )?}}constant
// This is not a key function.
void Test0a::foo() {}
@@ -47,8 +47,8 @@ void Test0b::foo() {}
// V-table should be defined externally.
Test0b::Test0b() { use(typeid(Test0b)); }
-// CHECK: @_ZTV6Test0b = external unnamed_addr constant
-// CHECK: @_ZTI6Test0b = external constant
+// CHECK: @_ZTV6Test0b = external {{(dso_local )?}}unnamed_addr constant
+// CHECK: @_ZTI6Test0b = external {{(dso_local )?}}constant
/*** Test1a ******************************************************************/
@@ -60,9 +60,9 @@ struct Test1a {
// V-table needs to be defined weakly.
Test1a::Test1a() { use(typeid(Test1a)); }
-// CHECK: @_ZTV6Test1a = linkonce_odr unnamed_addr constant
-// CHECK-LATE: @_ZTS6Test1a = linkonce_odr constant
-// CHECK-LATE: @_ZTI6Test1a = linkonce_odr constant
+// CHECK: @_ZTV6Test1a = linkonce_odr {{(dso_local )?}}unnamed_addr constant
+// CHECK-LATE: @_ZTS6Test1a = linkonce_odr {{(dso_local )?}}constant
+// CHECK-LATE: @_ZTI6Test1a = linkonce_odr {{(dso_local )?}}constant
// This defines the key function.
inline void Test1a::foo() {}
@@ -80,9 +80,9 @@ inline void Test1b::foo() {}
// V-table should be defined weakly..
Test1b::Test1b() { use(typeid(Test1b)); }
-// CHECK: @_ZTV6Test1b = linkonce_odr unnamed_addr constant
-// CHECK: @_ZTS6Test1b = linkonce_odr constant
-// CHECK: @_ZTI6Test1b = linkonce_odr constant
+// CHECK: @_ZTV6Test1b = linkonce_odr {{(dso_local )?}}unnamed_addr constant
+// CHECK: @_ZTS6Test1b = linkonce_odr {{(dso_local )?}}constant
+// CHECK: @_ZTI6Test1b = linkonce_odr {{(dso_local )?}}constant
/*** Test2a ******************************************************************/
@@ -94,9 +94,9 @@ struct Test2a {
// V-table should be defined with weak linkage.
Test2a::Test2a() { use(typeid(Test2a)); }
-// CHECK: @_ZTV6Test2a = linkonce_odr unnamed_addr constant
-// CHECK-LATE: @_ZTS6Test2a = linkonce_odr constant
-// CHECK-LATE: @_ZTI6Test2a = linkonce_odr constant
+// CHECK: @_ZTV6Test2a = linkonce_odr {{(dso_local )?}}unnamed_addr constant
+// CHECK-LATE: @_ZTS6Test2a = linkonce_odr {{(dso_local )?}}constant
+// CHECK-LATE: @_ZTI6Test2a = linkonce_odr {{(dso_local )?}}constant
void Test2a::bar() {}
inline void Test2a::foo() {}
@@ -113,9 +113,9 @@ void Test2b::bar() {}
// V-table should be defined with weak linkage.
Test2b::Test2b() { use(typeid(Test2b)); }
-// CHECK: @_ZTV6Test2b = linkonce_odr unnamed_addr constant
-// CHECK-LATE: @_ZTS6Test2b = linkonce_odr constant
-// CHECK-LATE: @_ZTI6Test2b = linkonce_odr constant
+// CHECK: @_ZTV6Test2b = linkonce_odr {{(dso_local )?}}unnamed_addr constant
+// CHECK-LATE: @_ZTS6Test2b = linkonce_odr {{(dso_local )?}}constant
+// CHECK-LATE: @_ZTI6Test2b = linkonce_odr {{(dso_local )?}}constant
inline void Test2b::foo() {}
@@ -132,9 +132,9 @@ inline void Test2c::foo() {}
// V-table should be defined with weak linkage.
Test2c::Test2c() { use(typeid(Test2c)); }
-// CHECK: @_ZTV6Test2c = linkonce_odr unnamed_addr constant
-// CHECK: @_ZTS6Test2c = linkonce_odr constant
-// CHECK: @_ZTI6Test2c = linkonce_odr constant
+// CHECK: @_ZTV6Test2c = linkonce_odr {{(dso_local )?}}unnamed_addr constant
+// CHECK: @_ZTS6Test2c = linkonce_odr {{(dso_local )?}}constant
+// CHECK: @_ZTI6Test2c = linkonce_odr {{(dso_local )?}}constant
/*** Test3a ******************************************************************/
@@ -146,9 +146,9 @@ struct Test3a {
// V-table should be defined with weak linkage.
Test3a::Test3a() { use(typeid(Test3a)); }
-// CHECK: @_ZTV6Test3a = linkonce_odr unnamed_addr constant
-// CHECK-LATE: @_ZTS6Test3a = linkonce_odr constant
-// CHECK-LATE: @_ZTI6Test3a = linkonce_odr constant
+// CHECK: @_ZTV6Test3a = linkonce_odr {{(dso_local )?}}unnamed_addr constant
+// CHECK-LATE: @_ZTS6Test3a = linkonce_odr {{(dso_local )?}}constant
+// CHECK-LATE: @_ZTI6Test3a = linkonce_odr {{(dso_local )?}}constant
// This defines the key function.
inline void Test3a::bar() {}
@@ -166,9 +166,9 @@ inline void Test3b::bar() {}
// V-table should be defined with weak linkage.
Test3b::Test3b() { use(typeid(Test3b)); }
-// CHECK: @_ZTV6Test3b = linkonce_odr unnamed_addr constant
-// CHECK-LATE: @_ZTS6Test3b = linkonce_odr constant
-// CHECK-LATE: @_ZTI6Test3b = linkonce_odr constant
+// CHECK: @_ZTV6Test3b = linkonce_odr {{(dso_local )?}}unnamed_addr constant
+// CHECK-LATE: @_ZTS6Test3b = linkonce_odr {{(dso_local )?}}constant
+// CHECK-LATE: @_ZTI6Test3b = linkonce_odr {{(dso_local )?}}constant
// This defines the key function.
inline void Test3b::foo() {}
@@ -187,6 +187,6 @@ inline void Test3c::foo() {}
// V-table should be defined with weak linkage.
Test3c::Test3c() { use(typeid(Test3c)); }
-// CHECK: @_ZTV6Test3c = linkonce_odr unnamed_addr constant
-// CHECK: @_ZTS6Test3c = linkonce_odr constant
-// CHECK: @_ZTI6Test3c = linkonce_odr constant
+// CHECK: @_ZTV6Test3c = linkonce_odr {{(dso_local )?}}unnamed_addr constant
+// CHECK: @_ZTS6Test3c = linkonce_odr {{(dso_local )?}}constant
+// CHECK: @_ZTI6Test3c = linkonce_odr {{(dso_local )?}}constant
diff --git a/test/CodeGenCXX/vtable-key-function-win-comdat.cpp b/test/CodeGenCXX/vtable-key-function-win-comdat.cpp
index 3dd1be7dc69c..e7c5be93b807 100644
--- a/test/CodeGenCXX/vtable-key-function-win-comdat.cpp
+++ b/test/CodeGenCXX/vtable-key-function-win-comdat.cpp
@@ -20,6 +20,6 @@ inline void Test1a::foo() {}
// CHECK-NOT: $_ZTS6Test1a.1 = comdat any
// CHECK-NOT: $_ZTI6Test1a.1 = comdat any
-// CHECK: @_ZTV6Test1a = linkonce_odr unnamed_addr constant {{.*}} ({ i8*, i8* }* @_ZTI6Test1a to i8*)
-// CHECK: @_ZTS6Test1a = linkonce_odr constant
-// CHECK: @_ZTI6Test1a = linkonce_odr constant {{.*}} [8 x i8]* @_ZTS6Test1a
+// CHECK: @_ZTV6Test1a = linkonce_odr dso_local unnamed_addr constant {{.*}} ({ i8*, i8* }* @_ZTI6Test1a to i8*)
+// CHECK: @_ZTS6Test1a = linkonce_odr dso_local constant
+// CHECK: @_ZTI6Test1a = linkonce_odr dso_local constant {{.*}} [8 x i8]* @_ZTS6Test1a
diff --git a/test/CodeGenCXX/wasm-eh.cpp b/test/CodeGenCXX/wasm-eh.cpp
new file mode 100644
index 000000000000..ea77fec82039
--- /dev/null
+++ b/test/CodeGenCXX/wasm-eh.cpp
@@ -0,0 +1,384 @@
+// RUN: %clang_cc1 %s -triple wasm32-unknown-unknown -fms-extensions -fexceptions -fcxx-exceptions -target-feature +exception-handling -emit-llvm -o - -std=c++11 | FileCheck %s
+// RUN: %clang_cc1 %s -triple wasm64-unknown-unknown -fms-extensions -fexceptions -fcxx-exceptions -target-feature +exception-handling -emit-llvm -o - -std=c++11 | FileCheck %s
+
+void may_throw();
+void dont_throw() noexcept;
+
+struct Cleanup {
+ ~Cleanup() { dont_throw(); }
+};
+
+// Multiple catch clauses w/o catch-all
+void test0() {
+ try {
+ may_throw();
+ } catch (int) {
+ dont_throw();
+ } catch (double) {
+ dont_throw();
+ }
+}
+
+// CHECK-LABEL: define void @_Z5test0v() {{.*}} personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*)
+
+// CHECK: %[[INT_ALLOCA:.*]] = alloca i32
+// CHECK: invoke void @_Z9may_throwv()
+// CHECK-NEXT: to label %[[NORMAL_BB:.*]] unwind label %[[CATCHDISPATCH_BB:.*]]
+
+// CHECK: [[CATCHDISPATCH_BB]]:
+// CHECK-NEXT: %[[CATCHSWITCH:.*]] = catchswitch within none [label %[[CATCHSTART_BB:.*]]] unwind to caller
+
+// CHECK: [[CATCHSTART_BB]]:
+// CHECK-NEXT: %[[CATCHPAD:.*]] = catchpad within %[[CATCHSWITCH]] [i8* bitcast (i8** @_ZTIi to i8*), i8* bitcast (i8** @_ZTId to i8*)]
+// CHECK-NEXT: %[[EXN:.*]] = call i8* @llvm.wasm.get.exception(token %[[CATCHPAD]])
+// CHECK-NEXT: store i8* %[[EXN]], i8** %exn.slot
+// CHECK-NEXT: %[[SELECTOR:.*]] = call i32 @llvm.wasm.get.ehselector(token %[[CATCHPAD]])
+// CHECK-NEXT: %[[TYPEID:.*]] = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) #2
+// CHECK-NEXT: %[[MATCHES:.*]] = icmp eq i32 %[[SELECTOR]], %[[TYPEID]]
+// CHECK-NEXT: br i1 %[[MATCHES]], label %[[CATCH_INT_BB:.*]], label %[[CATCH_FALLTHROUGH_BB:.*]]
+
+// CHECK: [[CATCH_INT_BB]]:
+// CHECK-NEXT: %[[EXN:.*]] = load i8*, i8** %exn.slot
+// CHECK-NEXT: %[[ADDR:.*]] = call i8* @__cxa_begin_catch(i8* %[[EXN]]) {{.*}} [ "funclet"(token %[[CATCHPAD]]) ]
+// CHECK-NEXT: %[[ADDR_CAST:.*]] = bitcast i8* %[[ADDR]] to i32*
+// CHECK-NEXT: %[[INT_VAL:.*]] = load i32, i32* %[[ADDR_CAST]]
+// CHECK-NEXT: store i32 %[[INT_VAL]], i32* %[[INT_ALLOCA]]
+// CHECK-NEXT: call void @_Z10dont_throwv() {{.*}} [ "funclet"(token %[[CATCHPAD]]) ]
+// CHECK-NEXT: call void @__cxa_end_catch() {{.*}} [ "funclet"(token %[[CATCHPAD]]) ]
+// CHECK-NEXT: catchret from %[[CATCHPAD]] to label %[[CATCHRET_DEST_BB0:.*]]
+
+// CHECK: [[CATCHRET_DEST_BB0]]:
+// CHECK-NEXT: br label %[[TRY_CONT_BB:.*]]
+
+// CHECK: [[CATCH_FALLTHROUGH_BB]]
+// CHECK-NEXT: %[[TYPEID:.*]] = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTId to i8*)) #2
+// CHECK-NEXT: %[[MATCHES:.*]] = icmp eq i32 %[[SELECTOR]], %[[TYPEID]]
+// CHECK-NEXT: br i1 %[[MATCHES]], label %[[CATCH_FLOAT_BB:.*]], label %[[RETHROW_BB:.*]]
+
+// CHECK: [[CATCH_FLOAT_BB]]:
+// CHECK: catchret from %[[CATCHPAD]] to label %[[CATCHRET_DEST_BB1:.*]]
+
+// CHECK: [[CATCHRET_DEST_BB1]]:
+// CHECK-NEXT: br label %[[TRY_CONT_BB]]
+
+// CHECK: [[RETHROW_BB]]:
+// CHECK-NEXT: call void @__cxa_rethrow() {{.*}} [ "funclet"(token %[[CATCHPAD]]) ]
+// CHECK-NEXT: unreachable
+
+// Single catch-all
+void test1() {
+ try {
+ may_throw();
+ } catch (...) {
+ dont_throw();
+ }
+}
+
+// CATCH-LABEL: @_Z5test1v()
+
+// CHECK: %[[CATCHSWITCH:.*]] = catchswitch within none [label %[[CATCHSTART_BB:.*]]] unwind to caller
+
+// CHECK: [[CATCHSTART_BB]]:
+// CHECK-NEXT: %[[CATCHPAD:.*]] = catchpad within %[[CATCHSWITCH]] [i8* null]
+// CHECK: br label %[[CATCH_ALL_BB:.*]]
+
+// CHECK: [[CATCH_ALL_BB]]:
+// CHECK: catchret from %[[CATCHPAD]] to label
+
+// Multiple catch clauses w/ catch-all
+void test2() {
+ try {
+ may_throw();
+ } catch (int) {
+ dont_throw();
+ } catch (...) {
+ dont_throw();
+ }
+}
+
+// CHECK-LABEL: @_Z5test2v()
+
+// CHECK: %[[CATCHSWITCH:.*]] = catchswitch within none [label %[[CATCHSTART_BB:.*]]] unwind to caller
+
+// CHECK: [[CATCHSTART_BB]]:
+// CHECK-NEXT: %[[CATCHPAD:.*]] = catchpad within %[[CATCHSWITCH]] [i8* bitcast (i8** @_ZTIi to i8*), i8* null]
+// CHECK: br i1 %{{.*}}, label %[[CATCH_INT_BB:.*]], label %[[CATCH_ALL_BB:.*]]
+
+// CHECK: [[CATCH_INT_BB]]:
+// CHECK: catchret from %[[CATCHPAD]] to label
+
+// CHECK: [[CATCH_ALL_BB]]:
+// CHECK: catchret from %[[CATCHPAD]] to label
+
+// Cleanup
+void test3() {
+ Cleanup c;
+ may_throw();
+}
+
+// CHECK-LABEL: @_Z5test3v()
+
+// CHECK: invoke void @_Z9may_throwv()
+// CHECK-NEXT: to label {{.*}} unwind label %[[EHCLEANUP_BB:.*]]
+
+// CHECK: [[EHCLEANUP_BB]]:
+// CHECK-NEXT: %[[CLEANUPPAD:.*]] = cleanuppad within none []
+// CHECK-NEXT: call %struct.Cleanup* @_ZN7CleanupD1Ev(%struct.Cleanup* %{{.*}}) {{.*}} [ "funclet"(token %[[CLEANUPPAD]]) ]
+// CHECK-NEXT: cleanupret from %[[CLEANUPPAD]] unwind to caller
+
+// Possibly throwing function call within a catch
+void test4() {
+ try {
+ may_throw();
+ } catch (int) {
+ may_throw();
+ }
+}
+
+// CHECK-LABEL: @_Z5test4v()
+
+// CHECK: %[[CATCHSWITCH]] = catchswitch within none [label %[[CATCHSTART_BB]]] unwind to caller
+
+// CHECK: [[CATCHSTART_BB]]:
+// CHECK: %[[CATCHPAD:.*]] = catchpad within %[[CATCHSWITCH]] [i8* bitcast (i8** @_ZTIi to i8*)]
+
+// CHECK: invoke void @_Z9may_throwv() [ "funclet"(token %[[CATCHPAD]]) ]
+// CHECK-NEXT: to label %[[INVOKE_CONT_BB:.*]] unwind label %[[EHCLEANUP_BB:.*]]
+
+// CHECK: [[INVOKE_CONT_BB]]:
+// CHECK-NEXT: call void @__cxa_end_catch() {{.*}} [ "funclet"(token %[[CATCHPAD]]) ]
+// CHECK-NEXT: catchret from %[[CATCHPAD]] to label
+
+// CHECK: [[EHCLEANUP_BB]]:
+// CHECK-NEXT: %[[CLEANUPPAD:.*]] = cleanuppad within %[[CATCHPAD]] []
+// CHECK-NEXT: call void @__cxa_end_catch() {{.*}} [ "funclet"(token %[[CLEANUPPAD]]) ]
+// CHECK-NEXT: cleanupret from %[[CLEANUPPAD]] unwind to caller
+
+// Possibly throwing function call within a catch-all
+void test5() {
+ try {
+ may_throw();
+ } catch (...) {
+ may_throw();
+ }
+}
+
+// CHECK-LABEL: @_Z5test5v()
+
+// CHECK: %[[CATCHSWITCH:.*]] = catchswitch within none [label %[[CATCHSTART_BB]]] unwind to caller
+
+// CHECK: [[CATCHSTART_BB]]:
+// CHECK: %[[CATCHPAD:.*]] = catchpad within %[[CATCHSWITCH]] [i8* null]
+
+// CHECK: invoke void @_Z9may_throwv() [ "funclet"(token %[[CATCHPAD]]) ]
+// CHECK-NEXT: to label %[[INVOKE_CONT_BB0:.*]] unwind label %[[EHCLEANUP_BB:.*]]
+
+// CHECK: [[INVOKE_CONT_BB0]]:
+// CHECK-NEXT: call void @__cxa_end_catch() [ "funclet"(token %[[CATCHPAD]]) ]
+// CHECK-NEXT: catchret from %[[CATCHPAD]] to label
+
+// CHECK: [[EHCLEANUP_BB]]:
+// CHECK-NEXT: %[[CLEANUPPAD0:.*]] = cleanuppad within %[[CATCHPAD]] []
+// CHECK-NEXT: invoke void @__cxa_end_catch() [ "funclet"(token %[[CLEANUPPAD0]]) ]
+// CHECK-NEXT: to label %[[INVOKE_CONT_BB1:.*]] unwind label %[[TERMINATE_BB:.*]]
+
+// CHECK: [[INVOKE_CONT_BB1]]:
+// CHECK-NEXT: cleanupret from %[[CLEANUPPAD0]] unwind to caller
+
+// CHECK: [[TERMINATE_BB]]:
+// CHECK-NEXT: %[[CLEANUPPAD1:.*]] = cleanuppad within %[[CLEANUPPAD0]] []
+// CHECK-NEXT: %[[EXN:.*]] = call i8* @llvm.wasm.get.exception(token %[[CLEANUPPAD1]])
+// CHECK-NEXT: call void @__clang_call_terminate(i8* %[[EXN]]) {{.*}} [ "funclet"(token %[[CLEANUPPAD1]]) ]
+// CHECK-NEXT: unreachable
+
+// CHECK-LABEL: define {{.*}} void @__clang_call_terminate(i8*)
+// CHECK-NEXT: call i8* @__cxa_begin_catch(i8* %{{.*}})
+// CHECK-NEXT: call void @_ZSt9terminatev()
+// CHECK-NEXT: unreachable
+
+// Try-catch with cleanups
+void test6() {
+ Cleanup c1;
+ try {
+ Cleanup c2;
+ may_throw();
+ } catch (int) {
+ Cleanup c3;
+ may_throw();
+ }
+}
+
+// CHECK-LABEL: @_Z5test6v()
+// CHECK: invoke void @_Z9may_throwv()
+// CHECK-NEXT: to label %{{.*}} unwind label %[[EHCLEANUP_BB0:.*]]
+
+// CHECK: [[EHCLEANUP_BB0]]:
+// CHECK-NEXT: %[[CLEANUPPAD0:.*]] = cleanuppad within none []
+// CHECK-NEXT: call %struct.Cleanup* @_ZN7CleanupD1Ev(%struct.Cleanup* {{.*}}) {{.*}} [ "funclet"(token %[[CLEANUPPAD0]]) ]
+// CHECK-NEXT: cleanupret from %[[CLEANUPPAD0]] unwind label %[[CATCH_DISPATCH_BB:.*]]
+
+// CHECK: [[CATCH_DISPATCH_BB]]:
+// CHECK-NEXT: %[[CATCHSWITCH:.*]] = catchswitch within none [label %[[CATCHSTART_BB:.*]]] unwind label %[[EHCLEANUP_BB1:.*]]
+
+// CHECK: [[CATCHSTART_BB]]:
+// CHECK-NEXT: %[[CATCHPAD:.*]] = catchpad within %[[CATCHSWITCH]] [i8* bitcast (i8** @_ZTIi to i8*)]
+// CHECK: br i1 %{{.*}}, label %[[CATCH_INT_BB:.*]], label %[[RETHROW_BB:.*]]
+
+// CHECK: [[CATCH_INT_BB]]:
+// CHECK: invoke void @_Z9may_throwv() [ "funclet"(token %[[CATCHPAD]]) ]
+// CHECK-NEXT: to label %[[INVOKE_CONT_BB:.*]] unwind label %[[EHCLEANUP_BB2:.*]]
+
+// CHECK: [[INVOKE_CONT_BB]]:
+// CHECK: catchret from %[[CATCHPAD]] to label %{{.*}}
+
+// CHECK: [[RETHROW_BB]]:
+// CHECK-NEXT: invoke void @__cxa_rethrow() {{.*}} [ "funclet"(token %[[CATCHPAD]]) ]
+// CHECK-NEXT: to label %[[UNREACHABLE_BB:.*]] unwind label %[[EHCLEANUP_BB1:.*]]
+
+// CHECK: [[EHCLEANUP_BB2]]:
+// CHECK-NEXT: %[[CLEANUPPAD2:.*]] = cleanuppad within %[[CATCHPAD]] []
+// CHECK-NEXT: call %struct.Cleanup* @_ZN7CleanupD1Ev(%struct.Cleanup* %{{.*}}) {{.*}} [ "funclet"(token %[[CLEANUPPAD2]]) ]
+// CHECK-NEXT: cleanupret from %[[CLEANUPPAD2]] unwind label %[[EHCLEANUP_BB3:.*]]
+
+// CHECK: [[EHCLEANUP_BB3]]:
+// CHECK-NEXT: %[[CLEANUPPAD3:.*]] = cleanuppad within %[[CATCHPAD]] []
+// CHECK: cleanupret from %[[CLEANUPPAD3]] unwind label %[[EHCLEANUP_BB1:.*]]
+
+// CHECK: [[EHCLEANUP_BB1]]:
+// CHECK-NEXT: %[[CLEANUPPAD1:.*]] = cleanuppad within none []
+// CHECK-NEXT: call %struct.Cleanup* @_ZN7CleanupD1Ev(%struct.Cleanup* %{{.*}}) {{.*}} [ "funclet"(token %[[CLEANUPPAD1]]) ]
+// CHECK-NEXT: cleanupret from %[[CLEANUPPAD1]] unwind to caller
+
+// CHECK: [[UNREACHABLE_BB]]:
+// CHECK-NEXT: unreachable
+
+// Nested try-catches within a try with cleanups
+void test7() {
+ Cleanup c1;
+ may_throw();
+ try {
+ Cleanup c2;
+ may_throw();
+ try {
+ Cleanup c3;
+ may_throw();
+ } catch (int) {
+ may_throw();
+ } catch (double) {
+ may_throw();
+ }
+ } catch (int) {
+ may_throw();
+ } catch (...) {
+ may_throw();
+ }
+}
+
+// CHECK-LABEL: @_Z5test7v()
+// CHECK: invoke void @_Z9may_throwv()
+
+// CHECK: invoke void @_Z9may_throwv()
+
+// CHECK: invoke void @_Z9may_throwv()
+
+// CHECK: %[[CLEANUPPAD0:.*]] = cleanuppad within none []
+// CHECK: cleanupret from %[[CLEANUPPAD0]] unwind label
+
+// CHECK: %[[CATCHSWITCH0:.*]] = catchswitch within none
+
+// CHECK: %[[CATCHPAD0:.*]] = catchpad within %[[CATCHSWITCH0]] [i8* bitcast (i8** @_ZTIi to i8*), i8* bitcast (i8** @_ZTId to i8*)]
+
+// CHECK: invoke void @_Z9may_throwv() [ "funclet"(token %[[CATCHPAD0]]) ]
+
+// CHECK: catchret from %[[CATCHPAD0]] to label
+
+// CHECK: invoke void @_Z9may_throwv() [ "funclet"(token %[[CATCHPAD0]]) ]
+
+// CHECK: catchret from %[[CATCHPAD0]] to label
+
+// CHECK: invoke void @__cxa_rethrow() {{.*}} [ "funclet"(token %[[CATCHPAD0]]) ]
+
+// CHECK: %[[CLEANUPPAD1:.*]] = cleanuppad within %[[CATCHPAD0]] []
+// CHECK: cleanupret from %[[CLEANUPPAD1]] unwind label
+
+// CHECK: %[[CLEANUPPAD2:.*]] = cleanuppad within %[[CATCHPAD0]] []
+// CHECK: cleanupret from %[[CLEANUPPAD2]] unwind label
+
+// CHECK: %[[CLEANUPPAD3:.*]] = cleanuppad within none []
+// CHECK: cleanupret from %[[CLEANUPPAD3]] unwind label
+
+// CHECK: %[[CATCHSWITCH1:.*]] = catchswitch within none
+
+// CHECK: %[[CATCHPAD1:.*]] = catchpad within %[[CATCHSWITCH1]] [i8* bitcast (i8** @_ZTIi to i8*), i8* null]
+
+// CHECK: invoke void @_Z9may_throwv() [ "funclet"(token %[[CATCHPAD1]]) ]
+
+// CHECK: catchret from %[[CATCHPAD1]] to label
+
+// CHECK: invoke void @_Z9may_throwv() [ "funclet"(token %[[CATCHPAD1]]) ]
+
+// CHECK: invoke void @__cxa_end_catch() [ "funclet"(token %[[CATCHPAD1]]) ]
+
+// CHECK: catchret from %[[CATCHPAD1]] to label
+
+// CHECK: %[[CLEANUPPAD4:.*]] = cleanuppad within %[[CATCHPAD1]] []
+// CHECK: invoke void @__cxa_end_catch() [ "funclet"(token %[[CLEANUPPAD4]]) ]
+
+// CHECK: cleanupret from %[[CLEANUPPAD4]] unwind label
+
+// CHECK: %[[CLEANUPPAD5:.*]] = cleanuppad within %[[CATCHPAD1]] []
+// CHECK: cleanupret from %[[CLEANUPPAD5]] unwind label
+
+// CHECK: %[[CLEANUPPAD6:.*]] = cleanuppad within none []
+// CHECK: cleanupret from %[[CLEANUPPAD6]] unwind to caller
+
+// CHECK: unreachable
+
+// CHECK: %[[CLEANUPPAD7:.*]] = cleanuppad within %[[CLEANUPPAD4]] []
+// CHECK: call void @__clang_call_terminate(i8* %{{.*}}) {{.*}} [ "funclet"(token %[[CLEANUPPAD7]]) ]
+// CHECK: unreachable
+
+// Nested try-catches within a catch
+void test8() {
+ try {
+ may_throw();
+ } catch (int) {
+ try {
+ may_throw();
+ } catch (int) {
+ may_throw();
+ }
+ }
+}
+
+// CHECK-LABEL: @_Z5test8v()
+// CHECK: invoke void @_Z9may_throwv()
+
+// CHECK: %[[CATCHSWITCH0:.*]] = catchswitch within none
+
+// CHECK: %[[CATCHPAD0:.*]] = catchpad within %[[CATCHSWITCH0]] [i8* bitcast (i8** @_ZTIi to i8*)]
+
+// CHECK: invoke void @_Z9may_throwv() [ "funclet"(token %[[CATCHPAD0]]) ]
+
+// CHECK: %[[CATCHSWITCH1:.*]] = catchswitch within %[[CATCHPAD0]]
+
+// CHECK: %[[CATCHPAD1:.*]] = catchpad within %[[CATCHSWITCH1]] [i8* bitcast (i8** @_ZTIi to i8*)]
+
+// CHECK: invoke void @_Z9may_throwv() [ "funclet"(token %[[CATCHPAD1]]) ]
+
+// CHECK: catchret from %[[CATCHPAD1]] to label
+
+// CHECK: invoke void @__cxa_rethrow() {{.*}} [ "funclet"(token %[[CATCHPAD1]]) ]
+
+// CHECK: catchret from %[[CATCHPAD0]] to label
+
+// CHECK: call void @__cxa_rethrow() {{.*}} [ "funclet"(token %[[CATCHPAD0]]) ]
+// CHECK: unreachable
+
+// CHECK: %[[CLEANUPPAD0:.*]] = cleanuppad within %[[CATCHPAD1]] []
+// CHECK: cleanupret from %[[CLEANUPPAD0]] unwind label
+
+// CHECK: %[[CLEANUPPAD1:.*]] = cleanuppad within %[[CATCHPAD0]] []
+// CHECK: cleanupret from %[[CLEANUPPAD1]] unwind to caller
+
+// CHECK: unreachable
diff --git a/test/CodeGenCXX/weak-extern-typeinfo.cpp b/test/CodeGenCXX/weak-extern-typeinfo.cpp
index 38f6a3e46233..6bbb473a8e8d 100644
--- a/test/CodeGenCXX/weak-extern-typeinfo.cpp
+++ b/test/CodeGenCXX/weak-extern-typeinfo.cpp
@@ -31,17 +31,17 @@ class V2 : public virtual V1 {
void V1::foo() { }
void V2::foo() { }
-// CHECK: @_ZTS1A = weak_odr constant
-// CHECK: @_ZTI1A = weak_odr constant
-// CHECK: @_ZTS1B = weak_odr constant
-// CHECK: @_ZTI1B = weak_odr constant
-// CHECK: @_ZTS1C = weak_odr constant
-// CHECK: @_ZTS2T1 = linkonce_odr constant
-// CHECK: @_ZTI2T1 = linkonce_odr constant
-// CHECK: @_ZTS1T = linkonce_odr constant
-// CHECK: @_ZTI1T = linkonce_odr constant
-// CHECK: @_ZTI1C = weak_odr constant
-// CHECK: @_ZTS2V1 = weak_odr constant
-// CHECK: @_ZTI2V1 = weak_odr constant
-// CHECK: @_ZTS2V2 = weak_odr constant
-// CHECK: @_ZTI2V2 = weak_odr constant
+// CHECK: @_ZTS1A = weak_odr {{(dso_local )?}}constant
+// CHECK: @_ZTI1A = weak_odr {{(dso_local )?}}constant
+// CHECK: @_ZTS1B = weak_odr {{(dso_local )?}}constant
+// CHECK: @_ZTI1B = weak_odr {{(dso_local )?}}constant
+// CHECK: @_ZTS1C = weak_odr {{(dso_local )?}}constant
+// CHECK: @_ZTS2T1 = linkonce_odr {{(dso_local )?}}constant
+// CHECK: @_ZTI2T1 = linkonce_odr {{(dso_local )?}}constant
+// CHECK: @_ZTS1T = linkonce_odr {{(dso_local )?}}constant
+// CHECK: @_ZTI1T = linkonce_odr {{(dso_local )?}}constant
+// CHECK: @_ZTI1C = weak_odr {{(dso_local )?}}constant
+// CHECK: @_ZTS2V1 = weak_odr {{(dso_local )?}}constant
+// CHECK: @_ZTI2V1 = weak_odr {{(dso_local )?}}constant
+// CHECK: @_ZTS2V2 = weak_odr {{(dso_local )?}}constant
+// CHECK: @_ZTI2V2 = weak_odr {{(dso_local )?}}constant
diff --git a/test/CodeGenCXX/windows-implicit-dllexport-template-specialization.cpp b/test/CodeGenCXX/windows-implicit-dllexport-template-specialization.cpp
index c2f2a0773e90..20ba4bc5d040 100644
--- a/test/CodeGenCXX/windows-implicit-dllexport-template-specialization.cpp
+++ b/test/CodeGenCXX/windows-implicit-dllexport-template-specialization.cpp
@@ -10,8 +10,8 @@ class t : s<T_> {};
extern template class t<char>;
template class __declspec(dllexport) t<char>;
-// CHECK-MS: dllexport {{.*}} @"\01??4?$t@D@@QAEAAV0@ABV0@@Z"
-// CHECK-MS: dllexport {{.*}} @"\01??4?$s@D@@QAEAAU0@ABU0@@Z"
+// CHECK-MS: dllexport {{.*}} @"??4?$t@D@@QAEAAV0@ABV0@@Z"
+// CHECK-MS: dllexport {{.*}} @"??4?$s@D@@QAEAAU0@ABU0@@Z"
// CHECK-IA: dllexport {{.*}} @_ZN1tIcEaSERKS0_
// CHECK-IA: dllexport {{.*}} @_ZN1sIcEaSERKS0_
diff --git a/test/CodeGenCXX/windows-itanium-exceptions.cpp b/test/CodeGenCXX/windows-itanium-exceptions.cpp
index b2c8707efc06..1bca4e891717 100644
--- a/test/CodeGenCXX/windows-itanium-exceptions.cpp
+++ b/test/CodeGenCXX/windows-itanium-exceptions.cpp
@@ -10,7 +10,7 @@ void attempt() {
try { except(); } catch (...) { }
}
-// CHECK: @_ZTIi = external constant i8*
+// CHECK: @_ZTIi = external dso_local constant i8*
// CHECK: define {{.*}}void @_Z6exceptv() {{.*}} {
// CHECK: %exception = call {{.*}}i8* @__cxa_allocate_exception(i32 4)
diff --git a/test/CodeGenCXX/windows-itanium-type-info.cpp b/test/CodeGenCXX/windows-itanium-type-info.cpp
index 285b59815da2..20bd78df5098 100644
--- a/test/CodeGenCXX/windows-itanium-type-info.cpp
+++ b/test/CodeGenCXX/windows-itanium-type-info.cpp
@@ -24,17 +24,17 @@ void f() {
throw base();
}
-// CHECK-DAG: @_ZTIi = dllexport constant
-// CHECK-DAG: @_ZTSi = dllexport constant
+// CHECK-DAG: @_ZTIi = dso_local dllexport constant
+// CHECK-DAG: @_ZTSi = dso_local dllexport constant
-// CHECK-DAG: @_ZTI7derived = dllexport constant
-// CHECK-DAG: @_ZTS7derived = dllexport constant
-// CHECK-DAG: @_ZTV7derived = dllexport unnamed_addr constant
+// CHECK-DAG: @_ZTI7derived = dso_local dllexport constant
+// CHECK-DAG: @_ZTS7derived = dso_local dllexport constant
+// CHECK-DAG: @_ZTV7derived = dso_local dllexport unnamed_addr constant
// CHECK-DAG: @_ZTI4base = external dllimport constant
-// CHECK-EH-IMPORT: @_ZTS4base = linkonce_odr constant
-// CHECK-EH-IMPORT: @_ZTI4base = linkonce_odr constant
+// CHECK-EH-IMPORT: @_ZTS4base = linkonce_odr dso_local constant
+// CHECK-EH-IMPORT: @_ZTI4base = linkonce_odr dso_local constant
struct __declspec(dllimport) gatekeeper {};
struct zuul : gatekeeper {
@@ -42,5 +42,5 @@ struct zuul : gatekeeper {
};
zuul::~zuul() {}
-// CHECK-DAG: @_ZTI10gatekeeper = linkonce_odr constant
-// CHECK-DAG: @_ZTS10gatekeeper = linkonce_odr constant
+// CHECK-DAG: @_ZTI10gatekeeper = linkonce_odr dso_local constant
+// CHECK-DAG: @_ZTS10gatekeeper = linkonce_odr dso_local constant
diff --git a/test/CodeGenCoroutines/coro-alloc.cpp b/test/CodeGenCoroutines/coro-alloc.cpp
index 820201db357f..20b00d4fec21 100644
--- a/test/CodeGenCoroutines/coro-alloc.cpp
+++ b/test/CodeGenCoroutines/coro-alloc.cpp
@@ -106,6 +106,60 @@ extern "C" void f1(promise_new_tag ) {
co_return;
}
+struct promise_matching_placement_new_tag {};
+
+template<>
+struct std::experimental::coroutine_traits<void, promise_matching_placement_new_tag, int, float, double> {
+ struct promise_type {
+ void *operator new(unsigned long, promise_matching_placement_new_tag,
+ int, float, double);
+ void get_return_object() {}
+ suspend_always initial_suspend() { return {}; }
+ suspend_always final_suspend() { return {}; }
+ void return_void() {}
+ };
+};
+
+// CHECK-LABEL: f1a(
+extern "C" void f1a(promise_matching_placement_new_tag, int x, float y , double z) {
+ // CHECK: store i32 %x, i32* %x.addr, align 4
+ // CHECK: store float %y, float* %y.addr, align 4
+ // CHECK: store double %z, double* %z.addr, align 8
+ // CHECK: %[[ID:.+]] = call token @llvm.coro.id(i32 16
+ // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64()
+ // CHECK: %[[INT:.+]] = load i32, i32* %x.addr, align 4
+ // CHECK: %[[FLOAT:.+]] = load float, float* %y.addr, align 4
+ // CHECK: %[[DOUBLE:.+]] = load double, double* %z.addr, align 8
+ // CHECK: call i8* @_ZNSt12experimental16coroutine_traitsIJv34promise_matching_placement_new_tagifdEE12promise_typenwEmS1_ifd(i64 %[[SIZE]], i32 %[[INT]], float %[[FLOAT]], double %[[DOUBLE]])
+ co_return;
+}
+
+// Declare a placement form operator new, such as the one described in
+// C++ 18.6.1.3.1, which takes a void* argument.
+void* operator new(SizeT __sz, void *__p) noexcept;
+
+struct promise_matching_global_placement_new_tag {};
+struct dummy {};
+template<>
+struct std::experimental::coroutine_traits<void, promise_matching_global_placement_new_tag, dummy*> {
+ struct promise_type {
+ void get_return_object() {}
+ suspend_always initial_suspend() { return {}; }
+ suspend_always final_suspend() { return {}; }
+ void return_void() {}
+ };
+};
+
+// A coroutine that takes a single pointer argument should not invoke this
+// placement form operator. [dcl.fct.def.coroutine]/7 dictates that lookup for
+// allocation functions matching the coroutine function's signature be done
+// within the scope of the promise type's class.
+// CHECK-LABEL: f1b(
+extern "C" void f1b(promise_matching_global_placement_new_tag, dummy *) {
+ // CHECK: call i8* @_Znwm(i64
+ co_return;
+}
+
struct promise_delete_tag {};
template<>
@@ -173,6 +227,7 @@ struct std::experimental::coroutine_traits<int, promise_on_alloc_failure_tag> {
// CHECK-LABEL: f4(
extern "C" int f4(promise_on_alloc_failure_tag) {
// CHECK: %[[RetVal:.+]] = alloca i32
+ // CHECK: %[[Gro:.+]] = alloca i32
// CHECK: %[[ID:.+]] = call token @llvm.coro.id(i32 16
// CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64()
// CHECK: %[[MEM:.+]] = call i8* @_ZnwmRKSt9nothrow_t(i64 %[[SIZE]], %"struct.std::nothrow_t"* dereferenceable(1) @_ZStL7nothrow)
@@ -186,7 +241,11 @@ extern "C" int f4(promise_on_alloc_failure_tag) {
// CHECK: [[OKBB]]:
// CHECK: %[[OkRet:.+]] = call i32 @_ZNSt12experimental16coroutine_traitsIJi28promise_on_alloc_failure_tagEE12promise_type17get_return_objectEv(
- // CHECK: store i32 %[[OkRet]], i32* %[[RetVal]]
+ // CHECK: store i32 %[[OkRet]], i32* %[[Gro]]
+
+ // CHECK: %[[Tmp1:.*]] = load i32, i32* %[[Gro]]
+ // CHECK-NEXT: store i32 %[[Tmp1]], i32* %[[RetVal]]
+ // CHECK-NEXT: br label %[[RetBB]]
// CHECK: [[RetBB]]:
// CHECK: %[[LoadRet:.+]] = load i32, i32* %[[RetVal]], align 4
diff --git a/test/CodeGenCoroutines/coro-await-resume-eh.cpp b/test/CodeGenCoroutines/coro-await-resume-eh.cpp
new file mode 100644
index 000000000000..f0f8855fbd4d
--- /dev/null
+++ b/test/CodeGenCoroutines/coro-await-resume-eh.cpp
@@ -0,0 +1,108 @@
+// Test the behavior of http://wg21.link/P0664, a proposal to catch any
+// exceptions thrown after the initial suspend point of a coroutine by
+// executing the handler specified by the promise type's 'unhandled_exception'
+// member function.
+//
+// RUN: %clang_cc1 -std=c++14 -fcoroutines-ts \
+// RUN: -triple=x86_64-unknown-linux-gnu -emit-llvm -o - %s \
+// RUN: -fexceptions -fcxx-exceptions -disable-llvm-passes \
+// RUN: | FileCheck %s
+
+#include "Inputs/coroutine.h"
+
+namespace coro = std::experimental::coroutines_v1;
+
+struct throwing_awaitable {
+ bool await_ready() { return true; }
+ void await_suspend(coro::coroutine_handle<>) {}
+ void await_resume() { throw 42; }
+};
+
+struct throwing_task {
+ struct promise_type {
+ auto get_return_object() { return throwing_task{}; }
+ auto initial_suspend() { return throwing_awaitable{}; }
+ auto final_suspend() { return coro::suspend_never{}; }
+ void return_void() {}
+ void unhandled_exception() {}
+ };
+};
+
+// CHECK-LABEL: define void @_Z1fv()
+throwing_task f() {
+ // A variable RESUMETHREW is used to keep track of whether the body
+ // of 'await_resume' threw an exception. Exceptions thrown in
+ // 'await_resume' are unwound to RESUMELPAD.
+ // CHECK: init.ready:
+ // CHECK-NEXT: store i1 true, i1* %[[RESUMETHREW:.+]], align 1
+ // CHECK-NEXT: invoke void @_ZN18throwing_awaitable12await_resumeEv
+ // CHECK-NEXT: to label %[[RESUMECONT:.+]] unwind label %[[RESUMELPAD:.+]]
+
+ // If 'await_resume' does not throw an exception, 'false' is stored in
+ // variable RESUMETHREW.
+ // CHECK: [[RESUMECONT]]:
+ // CHECK-NEXT: store i1 false, i1* %[[RESUMETHREW]]
+ // CHECK-NEXT: br label %[[RESUMETRYCONT:.+]]
+
+ // 'unhandled_exception' is called for the exception thrown in
+ // 'await_resume'. The variable RESUMETHREW is never set to false,
+ // and a jump is made to RESUMETRYCONT.
+ // CHECK: [[RESUMELPAD]]:
+ // CHECK: br label %[[RESUMECATCH:.+]]
+ // CHECK: [[RESUMECATCH]]:
+ // CHECK: invoke void @_ZN13throwing_task12promise_type19unhandled_exceptionEv
+ // CHECK-NEXT: to label %[[RESUMEENDCATCH:.+]] unwind label
+ // CHECK: [[RESUMEENDCATCH]]:
+ // CHECK-NEXT: invoke void @__cxa_end_catch()
+ // CHECK-NEXT: to label %[[RESUMEENDCATCHCONT:.+]] unwind label
+ // CHECK: [[RESUMEENDCATCHCONT]]:
+ // CHECK-NEXT: br label %[[RESUMETRYCONT]]
+
+ // The variable RESUMETHREW is loaded and if true, then 'await_resume'
+ // threw an exception and the coroutine body is skipped, and the final
+ // suspend is executed immediately. Otherwise, the coroutine body is
+ // executed, and then the final suspend.
+ // CHECK: [[RESUMETRYCONT]]:
+ // CHECK-NEXT: %[[RESUMETHREWLOAD:.+]] = load i1, i1* %[[RESUMETHREW]]
+ // CHECK-NEXT: br i1 %[[RESUMETHREWLOAD]], label %[[RESUMEDCONT:.+]], label %[[RESUMEDBODY:.+]]
+
+ // CHECK: [[RESUMEDBODY]]:
+ // CHECK: invoke void @_ZN13throwing_task12promise_type11return_voidEv
+ // CHECK-NEXT: to label %[[REDUMEDBODYCONT:.+]] unwind label
+ // CHECK: [[REDUMEDBODYCONT]]:
+ // CHECK-NEXT: br label %[[COROFINAL:.+]]
+
+ // CHECK: [[RESUMEDCONT]]:
+ // CHECK-NEXT: br label %[[COROFINAL]]
+
+ // CHECK: [[COROFINAL]]:
+ // CHECK-NEXT: invoke void @_ZN13throwing_task12promise_type13final_suspendEv
+ co_return;
+}
+
+struct noexcept_awaitable {
+ bool await_ready() { return true; }
+ void await_suspend(coro::coroutine_handle<>) {}
+ void await_resume() noexcept {}
+};
+
+struct noexcept_task {
+ struct promise_type {
+ auto get_return_object() { return noexcept_task{}; }
+ auto initial_suspend() { return noexcept_awaitable{}; }
+ auto final_suspend() { return coro::suspend_never{}; }
+ void return_void() {}
+ void unhandled_exception() {}
+ };
+};
+
+// CHECK-LABEL: define void @_Z1gv()
+noexcept_task g() {
+ // If the await_resume function is marked as noexcept, none of the additional
+ // conditions that are present in f() above are added to the IR.
+ // This means that no i1 are stored before or after calling await_resume:
+ // CHECK: init.ready:
+ // CHECK-NEXT: call void @_ZN18noexcept_awaitable12await_resumeEv
+ // CHECK-NOT: store i1 false, i1*
+ co_return;
+}
diff --git a/test/CodeGenCoroutines/coro-builtins.c b/test/CodeGenCoroutines/coro-builtins.c
index 9ec214764258..9800eef0ed81 100644
--- a/test/CodeGenCoroutines/coro-builtins.c
+++ b/test/CodeGenCoroutines/coro-builtins.c
@@ -17,6 +17,9 @@ void f(int n) {
// CHECK-NEXT: call i1 @llvm.coro.alloc(token %[[COROID]])
__builtin_coro_alloc();
+ // CHECK-NEXT: call i8* @llvm.coro.noop()
+ __builtin_coro_noop();
+
// CHECK-NEXT: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64()
// CHECK-NEXT: %[[MEM:.+]] = call i8* @myAlloc(i64 %[[SIZE]])
// CHECK-NEXT: %[[FRAME:.+]] = call i8* @llvm.coro.begin(token %[[COROID]], i8* %[[MEM]])
diff --git a/test/CodeGenCoroutines/coro-eh-cleanup.cpp b/test/CodeGenCoroutines/coro-eh-cleanup.cpp
index 5a3ecd1da494..9801151b4f14 100644
--- a/test/CodeGenCoroutines/coro-eh-cleanup.cpp
+++ b/test/CodeGenCoroutines/coro-eh-cleanup.cpp
@@ -45,18 +45,18 @@ coro_t f() {
co_return;
}
-// CHECK: @"\01?f@@YA?AUcoro_t@@XZ"(
-// CHECK: invoke void @"\01?may_throw@@YAXXZ"()
+// CHECK: @"?f@@YA?AUcoro_t@@XZ"(
+// CHECK: invoke void @"?may_throw@@YAXXZ"()
// CHECK: to label %[[CONT:.+]] unwind label %[[EHCLEANUP:.+]]
// CHECK: [[EHCLEANUP]]:
// CHECK: %[[INNERPAD:.+]] = cleanuppad within none []
-// CHECK: call void @"\01??_DCleanup@@QEAAXXZ"(
+// CHECK: call void @"??1Cleanup@@QEAA@XZ"(
// CHECK: cleanupret from %{{.+}} unwind label %[[CATCHDISPATCH:.+]]
// CHECK: [[CATCHDISPATCH]]:
// CHECK: catchswitch within none [label %[[CATCHPAD:.+]]] unwind label %[[COROENDBB:.+]]
// CHECK: [[CATCHPAD]]:
-// CHECK: call void @"\01?unhandled_exception@promise_type@coro_t@@QEAAXXZ"
+// CHECK: call void @"?unhandled_exception@promise_type@coro_t@@QEAAXXZ"
// CHECK: [[COROENDBB]]:
// CHECK-NEXT: %[[CLPAD:.+]] = cleanuppad within none
diff --git a/test/CodeGenCoroutines/coro-gro-nrvo.cpp b/test/CodeGenCoroutines/coro-gro-nrvo.cpp
new file mode 100644
index 000000000000..48931cbf0dbc
--- /dev/null
+++ b/test/CodeGenCoroutines/coro-gro-nrvo.cpp
@@ -0,0 +1,87 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fcoroutines-ts -std=c++14 -emit-llvm %s -o - -disable-llvm-passes | FileCheck %s
+
+#include "Inputs/coroutine.h"
+
+using namespace std::experimental;
+
+namespace std {
+
+struct nothrow_t {};
+constexpr nothrow_t nothrow = {};
+
+} // end namespace std
+
+// Required when get_return_object_on_allocation_failure() is defined by
+// the promise.
+void* operator new(__SIZE_TYPE__ __sz, const std::nothrow_t&) noexcept;
+void operator delete(void* __p, const std::nothrow_t&) noexcept;
+
+
+template <class RetObject>
+struct promise_type {
+ RetObject get_return_object();
+ suspend_always initial_suspend();
+ suspend_never final_suspend();
+ void return_void();
+ static void unhandled_exception();
+};
+
+struct coro {
+ using promise_type = promise_type<coro>;
+ coro(coro const&);
+ struct Impl;
+ Impl *impl;
+};
+
+// Verify that the NRVO is applied to the Gro object.
+// CHECK-LABEL: define void @_Z1fi(%struct.coro* noalias sret %agg.result, i32)
+coro f(int) {
+// CHECK: %call = call i8* @_Znwm(
+// CHECK-NEXT: br label %[[CoroInit:.*]]
+
+// CHECK: {{.*}}[[CoroInit]]:
+// CHECK: store i1 false, i1* %gro.active
+// CHECK: call void @{{.*get_return_objectEv}}(%struct.coro* sret %agg.result
+// CHECK-NEXT: store i1 true, i1* %gro.active
+ co_return;
+}
+
+
+template <class RetObject>
+struct promise_type_with_on_alloc_failure {
+ static RetObject get_return_object_on_allocation_failure();
+ RetObject get_return_object();
+ suspend_always initial_suspend();
+ suspend_never final_suspend();
+ void return_void();
+ static void unhandled_exception();
+};
+
+struct coro_two {
+ using promise_type = promise_type_with_on_alloc_failure<coro_two>;
+ coro_two(coro_two const&);
+ struct Impl;
+ Impl *impl;
+};
+
+// Verify that the NRVO is applied to the Gro object.
+// CHECK-LABEL: define void @_Z1hi(%struct.coro_two* noalias sret %agg.result, i32)
+ coro_two h(int) {
+
+// CHECK: %call = call i8* @_ZnwmRKSt9nothrow_t
+// CHECK-NEXT: %[[CheckNull:.*]] = icmp ne i8* %call, null
+// CHECK-NEXT: br i1 %[[CheckNull]], label %[[InitOnSuccess:.*]], label %[[InitOnFailure:.*]]
+
+// CHECK: {{.*}}[[InitOnFailure]]:
+// CHECK-NEXT: call void @{{.*get_return_object_on_allocation_failureEv}}(%struct.coro_two* sret %agg.result
+// CHECK-NEXT: br label %[[RetLabel:.*]]
+
+// CHECK: {{.*}}[[InitOnSuccess]]:
+// CHECK: store i1 false, i1* %gro.active
+// CHECK: call void @{{.*get_return_objectEv}}(%struct.coro_two* sret %agg.result
+// CHECK-NEXT: store i1 true, i1* %gro.active
+
+// CHECK: [[RetLabel]]:
+// CHECK-NEXT: ret void
+ co_return;
+}
diff --git a/test/CodeGenCoroutines/coro-params.cpp b/test/CodeGenCoroutines/coro-params.cpp
index 540f84585c8e..d15286a52cb9 100644
--- a/test/CodeGenCoroutines/coro-params.cpp
+++ b/test/CodeGenCoroutines/coro-params.cpp
@@ -1,6 +1,7 @@
// Verifies that parameters are copied with move constructors
// Verifies that parameter copies are destroyed
// Vefifies that parameter copies are used in the body of the coroutine
+// Verifies that parameter copies are used to construct the promise type, if that type has a matching constructor
// RUN: %clang_cc1 -std=c++1z -fcoroutines-ts -triple=x86_64-unknown-linux-gnu -emit-llvm -o - %s -disable-llvm-passes -fexceptions | FileCheck %s
namespace std::experimental {
@@ -68,12 +69,12 @@ void f(int val, MoveOnly moParam, MoveAndCopy mcParam) {
// CHECK: store i32 %val, i32* %[[ValAddr:.+]]
// CHECK: call i8* @llvm.coro.begin(
- // CHECK-NEXT: call void @_ZN8MoveOnlyC1EOS_(%struct.MoveOnly* %[[MoCopy]], %struct.MoveOnly* dereferenceable(4) %[[MoParam]])
+ // CHECK: call void @_ZN8MoveOnlyC1EOS_(%struct.MoveOnly* %[[MoCopy]], %struct.MoveOnly* dereferenceable(4) %[[MoParam]])
// CHECK-NEXT: call void @_ZN11MoveAndCopyC1EOS_(%struct.MoveAndCopy* %[[McCopy]], %struct.MoveAndCopy* dereferenceable(4) %[[McParam]]) #
// CHECK-NEXT: invoke void @_ZNSt12experimental16coroutine_traitsIJvi8MoveOnly11MoveAndCopyEE12promise_typeC1Ev(
// CHECK: call void @_ZN14suspend_always12await_resumeEv(
- // CHECK: %[[IntParam:.+]] = load i32, i32* %val.addr
+ // CHECK: %[[IntParam:.+]] = load i32, i32* %val1
// CHECK: %[[MoGep:.+]] = getelementptr inbounds %struct.MoveOnly, %struct.MoveOnly* %[[MoCopy]], i32 0, i32 0
// CHECK: %[[MoVal:.+]] = load i32, i32* %[[MoGep]]
// CHECK: %[[McGep:.+]] = getelementptr inbounds %struct.MoveAndCopy, %struct.MoveAndCopy* %[[McCopy]], i32 0, i32 0
@@ -127,3 +128,56 @@ struct B {
void call_dependent_params() {
dependent_params(A{}, B{}, B{});
}
+
+// Test that, when the promise type has a constructor whose signature matches
+// that of the coroutine function, that constructor is used. This is an
+// experimental feature that will be proposed for the Coroutines TS.
+
+struct promise_matching_constructor {};
+
+template<>
+struct std::experimental::coroutine_traits<void, promise_matching_constructor, int, float, double> {
+ struct promise_type {
+ promise_type(promise_matching_constructor, int, float, double) {}
+ promise_type() = delete;
+ void get_return_object() {}
+ suspend_always initial_suspend() { return {}; }
+ suspend_always final_suspend() { return {}; }
+ void return_void() {}
+ void unhandled_exception() {}
+ };
+};
+
+// CHECK-LABEL: void @_Z38coroutine_matching_promise_constructor28promise_matching_constructorifd(i32, float, double)
+void coroutine_matching_promise_constructor(promise_matching_constructor, int, float, double) {
+ // CHECK: %[[INT:.+]] = load i32, i32* %5, align 4
+ // CHECK: %[[FLOAT:.+]] = load float, float* %6, align 4
+ // CHECK: %[[DOUBLE:.+]] = load double, double* %7, align 8
+ // CHECK: invoke void @_ZNSt12experimental16coroutine_traitsIJv28promise_matching_constructorifdEE12promise_typeC1ES1_ifd(%"struct.std::experimental::coroutine_traits<void, promise_matching_constructor, int, float, double>::promise_type"* %__promise, i32 %[[INT]], float %[[FLOAT]], double %[[DOUBLE]])
+ co_return;
+}
+
+struct some_class;
+
+struct method {};
+
+template <typename... Args> struct std::experimental::coroutine_traits<method, Args...> {
+ struct promise_type {
+ promise_type(some_class&, float);
+ method get_return_object();
+ suspend_always initial_suspend();
+ suspend_always final_suspend();
+ void return_void();
+ void unhandled_exception();
+ };
+};
+
+struct some_class {
+ method good_coroutine_calls_custom_constructor(float);
+};
+
+// CHECK-LABEL: define void @_ZN10some_class39good_coroutine_calls_custom_constructorEf(%struct.some_class*
+method some_class::good_coroutine_calls_custom_constructor(float) {
+ // CHECK: invoke void @_ZNSt12experimental16coroutine_traitsIJ6methodR10some_classfEE12promise_typeC1ES3_f(%"struct.std::experimental::coroutine_traits<method, some_class &, float>::promise_type"* %__promise, %struct.some_class* dereferenceable(1) %{{.+}}, float
+ co_return;
+}
diff --git a/test/CodeGenCoroutines/coro-promise-dtor.cpp b/test/CodeGenCoroutines/coro-promise-dtor.cpp
index 4142cebe6132..bc190c9d1cb5 100644
--- a/test/CodeGenCoroutines/coro-promise-dtor.cpp
+++ b/test/CodeGenCoroutines/coro-promise-dtor.cpp
@@ -28,12 +28,12 @@ coro_t f() {
co_return;
}
-// CHECK-LABEL: define void @"\01?f@@YA?AUcoro_t@@XZ"(
+// CHECK-LABEL: define dso_local void @"?f@@YA?AUcoro_t@@XZ"(
// CHECK: %gro.active = alloca i1
// CHECK: store i1 false, i1* %gro.active
-// CHECK: invoke %"struct.coro_t::promise_type"* @"\01??0promise_type@coro_t@@QEAA@XZ"(
-// CHECK: invoke void @"\01?get_return_object@promise_type@coro_t@@QEAA?AU2@XZ"(
+// CHECK: invoke %"struct.coro_t::promise_type"* @"??0promise_type@coro_t@@QEAA@XZ"(
+// CHECK: invoke void @"?get_return_object@promise_type@coro_t@@QEAA?AU2@XZ"(
// CHECK: store i1 true, i1* %gro.active
// CHECK: %[[IS_ACTIVE:.+]] = load i1, i1* %gro.active
@@ -44,4 +44,4 @@ coro_t f() {
// CHECK: br i1 %[[NRVO]], label %{{.+}}, label %[[DTOR:.+]]
// CHECK: [[DTOR]]:
-// CHECK: call void @"\01??_Dcoro_t@@QEAAXXZ"(
+// CHECK: call void @"??1coro_t@@QEAA@XZ"(
diff --git a/test/CodeGenCoroutines/coro-unhandled-exception.cpp b/test/CodeGenCoroutines/coro-unhandled-exception.cpp
index e26a51861d9f..039f02352cfc 100644
--- a/test/CodeGenCoroutines/coro-unhandled-exception.cpp
+++ b/test/CodeGenCoroutines/coro-unhandled-exception.cpp
@@ -32,25 +32,27 @@ coro_t f() {
co_return;
}
-// CHECK: @"\01?f@@YA?AUcoro_t@@XZ"(
-// CHECK: invoke void @"\01?may_throw@@YAXXZ"()
+// CHECK: @"?f@@YA?AUcoro_t@@XZ"(
+// CHECK: invoke void @"?may_throw@@YAXXZ"()
// CHECK: to label %{{.+}} unwind label %[[EHCLEANUP:.+]]
// CHECK: [[EHCLEANUP]]:
// CHECK: %[[INNERPAD:.+]] = cleanuppad within none []
-// CHECK: call void @"\01??_DCleanup@@QEAAXXZ"(
+// CHECK: call void @"??1Cleanup@@QEAA@XZ"(
// CHECK: cleanupret from %[[INNERPAD]] unwind label %[[CATCHSW:.+]]
// CHECK: [[CATCHSW]]:
// CHECK: %[[CATCHSWTOK:.+]] = catchswitch within none [label %[[CATCH:.+]]] unwind label
// CHECK: [[CATCH]]:
// CHECK: %[[CATCHTOK:.+]] = catchpad within [[CATCHSWTOK:.+]]
-// CHECK: call void @"\01?unhandled_exception@promise_type@coro_t@@QEAAXXZ"
+// CHECK: call void @"?unhandled_exception@promise_type@coro_t@@QEAAXXZ"
// CHECK: catchret from %[[CATCHTOK]] to label %[[CATCHRETDEST:.+]]
// CHECK: [[CATCHRETDEST]]:
// CHECK-NEXT: br label %[[TRYCONT:.+]]
// CHECK: [[TRYCONT]]:
+// CHECK-NEXT: br label %[[RESUMECONT:.+]]
+// CHECK: [[RESUMECONT]]:
// CHECK-NEXT: br label %[[COROFIN:.+]]
// CHECK: [[COROFIN]]:
-// CHECK-NEXT: invoke void @"\01?final_suspend@promise_type@coro_t@@QEAA?AUsuspend_never@coroutines_v1@experimental@std@@XZ"(
+// CHECK-NEXT: invoke void @"?final_suspend@promise_type@coro_t@@QEAA?AUsuspend_never@coroutines_v1@experimental@std@@XZ"(
// CHECK-LPAD: @_Z1fv(
// CHECK-LPAD: invoke void @_Z9may_throwv()
@@ -67,6 +69,8 @@ coro_t f() {
// CHECK-LPAD: [[CATCHRETDEST]]:
// CHECK-LPAD-NEXT: br label %[[TRYCONT:.+]]
// CHECK-LPAD: [[TRYCONT]]:
+// CHECK-LPAD: br label %[[RESUMECONT:.+]]
+// CHECK-LPAD: [[RESUMECONT]]:
// CHECK-LPAD-NEXT: br label %[[COROFIN:.+]]
// CHECK-LPAD: [[COROFIN]]:
// CHECK-LPAD-NEXT: invoke void @_ZN6coro_t12promise_type13final_suspendEv(
diff --git a/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp b/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
index 1921c06e5af0..26e379493088 100644
--- a/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
+++ b/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
@@ -17,9 +17,9 @@ no_suspend operator co_await(B const&) { return {}; }
extern "C" void f() {
A a;
B b;
- // CHECK: call void @"\01??__LA@@QEAA?AUno_suspend@@XZ"(
+ // CHECK: call void @"??__LA@@QEAA?AUno_suspend@@XZ"(
a.operator co_await();
- // CHECK-NEXT: call i8 @"\01??__L@YA?AUno_suspend@@AEBUB@@@Z"(
+ // CHECK-NEXT: call i8 @"??__L@YA?AUno_suspend@@AEBUB@@@Z"(
operator co_await(b);
}
diff --git a/test/CodeGenObjC/Inputs/strong_in_union.h b/test/CodeGenObjC/Inputs/strong_in_union.h
new file mode 100644
index 000000000000..abe4549055c6
--- /dev/null
+++ b/test/CodeGenObjC/Inputs/strong_in_union.h
@@ -0,0 +1,10 @@
+#ifndef STRONG_IN_UNION_H
+#define STRONG_IN_UNION_H
+#pragma clang system_header
+
+typedef union {
+ id f0;
+ int *f1;
+} U;
+
+#endif // STRONG_IN_UNION_H
diff --git a/test/CodeGenObjC/arc-foreach.m b/test/CodeGenObjC/arc-foreach.m
index 77cb068187fa..ffeb37247b1b 100644
--- a/test/CodeGenObjC/arc-foreach.m
+++ b/test/CodeGenObjC/arc-foreach.m
@@ -42,7 +42,7 @@ void test0(NSArray *array) {
// Initialize the fast enumaration state.
// CHECK-LP64-NEXT: [[T0:%.*]] = bitcast [[STATE_T]]* [[STATE]] to i8*
-// CHECK-LP64-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 64, i32 8, i1 false)
+// CHECK-LP64-NEXT: call void @llvm.memset.p0i8.i64(i8* align 8 [[T0]], i8 0, i64 64, i1 false)
// Evaluate the collection expression and retain.
// CHECK-LP64-NEXT: [[T0:%.*]] = load [[ARRAY_T]]*, [[ARRAY_T]]** [[ARRAY]], align 8
diff --git a/test/CodeGenObjC/arc.m b/test/CodeGenObjC/arc.m
index d34156ee3473..3243952a36b3 100644
--- a/test/CodeGenObjC/arc.m
+++ b/test/CodeGenObjC/arc.m
@@ -7,30 +7,30 @@
// RUN: %clang_cc1 -fobjc-runtime=macosx-10.7.0 -triple x86_64-apple-darwin11 -Wno-objc-root-class -Wno-incompatible-pointer-types -Wno-arc-unsafe-retained-assign -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=ARC-NATIVE %s
// ARC-ALIEN: declare extern_weak void @objc_storeStrong(i8**, i8*)
-// ARC-ALIEN: declare extern_weak i8* @objc_retain(i8* returned)
-// ARC-ALIEN: declare extern_weak i8* @objc_autoreleaseReturnValue(i8* returned)
+// ARC-ALIEN: declare extern_weak i8* @objc_retain(i8*)
+// ARC-ALIEN: declare extern_weak i8* @objc_autoreleaseReturnValue(i8*)
// ARC-ALIEN: declare i8* @objc_msgSend(i8*, i8*, ...) [[NLB:#[0-9]+]]
// ARC-ALIEN: declare extern_weak void @objc_release(i8*)
-// ARC-ALIEN: declare extern_weak i8* @objc_retainAutoreleasedReturnValue(i8* returned)
+// ARC-ALIEN: declare extern_weak i8* @objc_retainAutoreleasedReturnValue(i8*)
// ARC-ALIEN: declare extern_weak i8* @objc_initWeak(i8**, i8*)
// ARC-ALIEN: declare extern_weak i8* @objc_storeWeak(i8**, i8*)
// ARC-ALIEN: declare extern_weak i8* @objc_loadWeakRetained(i8**)
// ARC-ALIEN: declare extern_weak void @objc_destroyWeak(i8**)
-// declare extern_weak i8* @objc_autorelease(i8*)
-// ARC-ALIEN: declare extern_weak i8* @objc_retainAutorelease(i8* returned)
+// ARC-ALIEN: declare extern_weak i8* @objc_autorelease(i8*)
+// ARC-ALIEN: declare extern_weak i8* @objc_retainAutorelease(i8*)
// ARC-NATIVE: declare void @objc_storeStrong(i8**, i8*)
-// ARC-NATIVE: declare i8* @objc_retain(i8* returned) [[NLB:#[0-9]+]]
-// ARC-NATIVE: declare i8* @objc_autoreleaseReturnValue(i8* returned)
+// ARC-NATIVE: declare i8* @objc_retain(i8*) [[NLB:#[0-9]+]]
+// ARC-NATIVE: declare i8* @objc_autoreleaseReturnValue(i8*)
// ARC-NATIVE: declare i8* @objc_msgSend(i8*, i8*, ...) [[NLB]]
// ARC-NATIVE: declare void @objc_release(i8*) [[NLB]]
-// ARC-NATIVE: declare i8* @objc_retainAutoreleasedReturnValue(i8* returned)
+// ARC-NATIVE: declare i8* @objc_retainAutoreleasedReturnValue(i8*)
// ARC-NATIVE: declare i8* @objc_initWeak(i8**, i8*)
// ARC-NATIVE: declare i8* @objc_storeWeak(i8**, i8*)
// ARC-NATIVE: declare i8* @objc_loadWeakRetained(i8**)
// ARC-NATIVE: declare void @objc_destroyWeak(i8**)
-// declare i8* @objc_autorelease(i8*)
-// ARC-NATIVE: declare i8* @objc_retainAutorelease(i8* returned)
+// ARC-NATIVE: declare i8* @objc_autorelease(i8*)
+// ARC-NATIVE: declare i8* @objc_retainAutorelease(i8*)
// CHECK-LABEL: define void @test0
void test0(id x) {
@@ -507,7 +507,7 @@ void test19() {
// CHECK: [[X:%.*]] = alloca [5 x i8*], align 16
// CHECK: call void @llvm.lifetime.start
// CHECK-NEXT: [[T0:%.*]] = bitcast [5 x i8*]* [[X]] to i8*
- // CHECK: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 40, i32 16, i1 false)
+ // CHECK: call void @llvm.memset.p0i8.i64(i8* align 16 [[T0]], i8 0, i64 40, i1 false)
id x[5];
extern id test19_helper(void);
@@ -538,6 +538,7 @@ void test20(unsigned n) {
// CHECK-LABEL: define void @test20
// CHECK: [[N:%.*]] = alloca i32, align 4
// CHECK-NEXT: [[SAVED_STACK:%.*]] = alloca i8*
+ // CHECK-NEXT: [[VLA_EXPR:%.*]] = alloca i64, align 8
// CHECK-NEXT: store i32 {{%.*}}, i32* [[N]], align 4
id x[n];
@@ -553,10 +554,13 @@ void test20(unsigned n) {
// Allocate the VLA.
// CHECK-NEXT: [[VLA:%.*]] = alloca i8*, i64 [[DIM]], align 16
+ // Store the VLA #elements expression.
+ // CHECK-NEXT: store i64 [[DIM]], i64* [[VLA_EXPR]], align 8
+
// Zero-initialize.
// CHECK-NEXT: [[T0:%.*]] = bitcast i8** [[VLA]] to i8*
// CHECK-NEXT: [[T1:%.*]] = mul nuw i64 [[DIM]], 8
- // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 [[T1]], i32 16, i1 false)
+ // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 16 [[T0]], i8 0, i64 [[T1]], i1 false)
// Destroy.
// CHECK-NEXT: [[END:%.*]] = getelementptr inbounds i8*, i8** [[VLA]], i64 [[DIM]]
@@ -579,6 +583,7 @@ void test21(unsigned n) {
// CHECK-LABEL: define void @test21
// CHECK: [[N:%.*]] = alloca i32, align 4
// CHECK-NEXT: [[SAVED_STACK:%.*]] = alloca i8*
+ // CHECK-NEXT: [[VLA_EXPR:%.*]] = alloca i64, align 8
// CHECK-NEXT: store i32 {{%.*}}, i32* [[N]], align 4
id x[2][n][3];
@@ -595,11 +600,14 @@ void test21(unsigned n) {
// CHECK-NEXT: [[T0:%.*]] = mul nuw i64 2, [[DIM]]
// CHECK-NEXT: [[VLA:%.*]] = alloca [3 x i8*], i64 [[T0]], align 16
+ // Store the VLA #elements expression.
+ // CHECK-NEXT: store i64 [[DIM]], i64* [[VLA_EXPR]], align 8
+
// Zero-initialize.
// CHECK-NEXT: [[T0:%.*]] = bitcast [3 x i8*]* [[VLA]] to i8*
// CHECK-NEXT: [[T1:%.*]] = mul nuw i64 2, [[DIM]]
// CHECK-NEXT: [[T2:%.*]] = mul nuw i64 [[T1]], 24
- // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 [[T2]], i32 16, i1 false)
+ // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 16 [[T0]], i8 0, i64 [[T2]], i1 false)
// Destroy.
// CHECK-NEXT: [[T0:%.*]] = mul nuw i64 2, [[DIM]]
@@ -1504,9 +1512,7 @@ void test68(void) {
// CHECK: [[SELF:%.*]] = alloca [[TEST69:%.*]]*, align 8
// CHECK: [[T0:%.*]] = load [[TEST69]]*, [[TEST69]]** [[SELF]], align 8
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST69]]* [[T0]] to i8*
-// CHECK-NEXT: [[RETAIN:%.*]] = call i8* @objc_retain(i8* [[T1]])
-// CHECK-NEXT: [[AUTORELEASE:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[RETAIN]])
-// CHECK-NEXT: ret i8* [[AUTORELEASE]]
+// CHECK-NEXT: ret i8* [[T1]]
// rdar://problem/10907547
void test70(id i) {
@@ -1520,6 +1526,37 @@ void test70(id i) {
};
}
+// Be sure that we emit lifetime intrinsics only after dtors
+struct AggDtor {
+ char cs[40];
+ id x;
+};
+
+struct AggDtor getAggDtor(void);
+
+// CHECK-LABEL: define void @test71
+void test71(void) {
+ // FIXME: It would be nice if the __destructor_8_s40 for the first call (and
+ // the following lifetime.end) came before the second call.
+ //
+ // CHECK: %[[T:[^ ]+]] = bitcast %struct.AggDtor* %[[TMP1:[^ ]+]] to i8*
+ // CHECK: call void @llvm.lifetime.start.p0i8({{[^,]+}}, i8* %[[T]])
+ // CHECK: call void @getAggDtor(%struct.AggDtor* sret %[[TMP1]])
+ // CHECK: %[[T:[^ ]+]] = bitcast %struct.AggDtor* %[[TMP2:[^ ]+]] to i8*
+ // CHECK: call void @llvm.lifetime.start.p0i8({{[^,]+}}, i8* %[[T]])
+ // CHECK: call void @getAggDtor(%struct.AggDtor* sret %[[TMP2]])
+ // CHECK: %[[T:[^ ]+]] = bitcast %struct.AggDtor* %[[TMP2]] to i8**
+ // CHECK: call void @__destructor_8_s40(i8** %[[T]])
+ // CHECK: %[[T:[^ ]+]] = bitcast %struct.AggDtor* %[[TMP2:[^ ]+]] to i8*
+ // CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* %[[T]])
+ // CHECK: %[[T:[^ ]+]] = bitcast %struct.AggDtor* %[[TMP1]] to i8**
+ // CHECK: call void @__destructor_8_s40(i8** %[[T]])
+ // CHECK: %[[T:[^ ]+]] = bitcast %struct.AggDtor* %[[TMP1:[^ ]+]] to i8*
+ // CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* %[[T]])
+ getAggDtor();
+ getAggDtor();
+}
+
// ARC-ALIEN: attributes [[NLB]] = { nonlazybind }
// ARC-NATIVE: attributes [[NLB]] = { nonlazybind }
// CHECK: attributes [[NUW]] = { nounwind }
diff --git a/test/CodeGenObjC/availability-dso-local.m b/test/CodeGenObjC/availability-dso-local.m
new file mode 100644
index 000000000000..8ff41d87f1e2
--- /dev/null
+++ b/test/CodeGenObjC/availability-dso-local.m
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -triple thumbv7-apple-ios10.0.0 -emit-llvm -fvisibility hidden -w %s -o - | FileCheck %s
+
+// CHECK: @"OBJC_CLASS_$_a" = hidden global %struct._class_t
+
+__attribute__((availability(ios, introduced = 11.0))) @interface a @end
+ @implementation a @end
diff --git a/test/CodeGenObjC/blocks.m b/test/CodeGenObjC/blocks.m
index d485bb4053b0..05880dea79b8 100644
--- a/test/CodeGenObjC/blocks.m
+++ b/test/CodeGenObjC/blocks.m
@@ -79,10 +79,9 @@ void test2(Test2 *x) {
// Then we initialize the block, blah blah blah.
// CHECK: call void @test2_helper(
- // Finally, kill the variable with BLOCK_FIELD_IS_BYREF. We're not
- // supposed to pass BLOCK_FIELD_IS_WEAK here.
+ // Finally, kill the variable with BLOCK_FIELD_IS_BYREF.
// CHECK: [[T0:%.*]] = bitcast [[WEAK_T]]* [[WEAKX]] to i8*
- // CHECK: call void @_Block_object_dispose(i8* [[T0]], i32 8)
+ // CHECK: call void @_Block_object_dispose(i8* [[T0]], i32 24)
__attribute__((objc_gc(weak))) __block Test2 *weakX = x;
test2_helper(^{ [weakX destroy]; });
diff --git a/test/CodeGenObjC/builtin-memfns.m b/test/CodeGenObjC/builtin-memfns.m
index bb425c037c64..6cc91b109cf5 100644
--- a/test/CodeGenObjC/builtin-memfns.m
+++ b/test/CodeGenObjC/builtin-memfns.m
@@ -5,6 +5,6 @@ void *memcpy(void *restrict s1, const void *restrict s2, unsigned long n);
// PR13697
void test1(int *a, id b) {
// CHECK: @test1
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 8, i32 1, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 8, i1 false)
memcpy(a, b, 8);
}
diff --git a/test/CodeGenObjC/constant-strings.m b/test/CodeGenObjC/constant-strings.m
index a1daa9284b81..df821968917a 100644
--- a/test/CodeGenObjC/constant-strings.m
+++ b/test/CodeGenObjC/constant-strings.m
@@ -14,5 +14,18 @@
// RUN: %clang_cc1 -triple x86_64-macho -fobjc-runtime=gcc -fconstant-string-class NSConstantString -emit-llvm -o %t %s
// RUN: FileCheck --check-prefix=CHECK-GNU-WITH-CLASS < %t %s
// CHECK-GNU-WITH-CLASS: NSConstantString
-id a = @"Hello World!";
+//
+// RUN: %clang_cc1 -triple x86_64-unknown-freebsd -fobjc-runtime=gnustep-2.0 -emit-llvm -o %t %s
+// RUN: FileCheck --check-prefix=CHECK-GNUSTEP2 < %t %s
+// CHECK-GNUSTEP2: @._OBJC_CLASS_NSConstantString = external global i8*
+// CHECK-GNUSTEP2: @0 = private unnamed_addr constant [13 x i8] c"Hello World!\00", align 1
+// CHECK-GNUSTEP2: @.objc_string = private global { i8**, i32, i32, i32, i32, i8* } { i8** @._OBJC_CLASS_NSConstantString, i32 0, i32 12, i32 12, i32 0, i8* getelementptr inbounds ([13 x i8], [13 x i8]* @0, i64 0, i64 0) }, section "__objc_constant_string", align 8
+// CHECK-GNUSTEP2: @b = global i8* inttoptr (i64 -3340545023602065388 to i8*), align 8
+// CHECK-GNUSTEP2: @.objc_str_Hello_World = linkonce_odr hidden global { i8**, i32, i32, i32, i32, i8* } { i8** @._OBJC_CLASS_NSConstantString, i32 0, i32 11, i32 11, i32 0, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @1, i64 0, i64 0) }, section "__objc_constant_string", comdat, align 8
+// CHECK-GNUSTEP2: @c =
+// CHECK-SAME-GNUSTEP2: @.objc_str_Hello_World
+//
+id a = @"Hello World!";
+id b = @"hi";
+id c = @"Hello World";
diff --git a/test/CodeGenObjC/debug-info-category.m b/test/CodeGenObjC/debug-info-category.m
new file mode 100644
index 000000000000..faca3a49c23e
--- /dev/null
+++ b/test/CodeGenObjC/debug-info-category.m
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -dwarf-version=5 -emit-llvm -debug-info-kind=limited -w -triple x86_64-apple-darwin10 %s -o - | FileCheck %s --check-prefix CHECK --check-prefix DWARF5
+// RUN: %clang_cc1 -dwarf-version=4 -emit-llvm -debug-info-kind=limited -w -triple x86_64-apple-darwin10 %s -o - | FileCheck %s --check-prefix CHECK --check-prefix DWARF4
+
+@interface Foo {
+ int integer;
+}
+
+- (int)integer;
+- (id)integer:(int)_integer;
+@end
+
+@implementation Foo
+- (int)integer {
+ return integer;
+}
+
+- (id)integer:(int)_integer {
+ integer = _integer;
+ return self;
+}
+@end
+
+@interface Foo (Bar)
++ (id)zero:(Foo *)zeroend;
+- (id)add:(Foo *)addend;
+@end
+
+@implementation Foo (Bar)
++ (id)zero:(Foo *)zeroend {
+ return [self integer:0];
+}
+- (id)add:(Foo *)addend {
+ return [self integer:[self integer] + [addend integer]];
+}
+@end
+
+// CHECK: ![[STRUCT:.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Foo"
+
+// DWARF5: !DISubprogram(name: "-[Foo integer]", scope: ![[STRUCT]], {{.*}}isDefinition: false
+// DWARF5: !DISubprogram(name: "-[Foo integer:]", scope: ![[STRUCT]], {{.*}}isDefinition: false
+// DWARF5: !DISubprogram(name: "+[Foo(Bar) zero:]", scope: ![[STRUCT]], {{.*}}isDefinition: false
+// DWARF5: !DISubprogram(name: "-[Foo(Bar) add:]", scope: ![[STRUCT]], {{.*}}isDefinition: false
+
+// DWARF4-NOT: !DISubprogram(name: "-[Foo integer]", scope: ![[STRUCT]], {{.*}}isDefinition: false
+// DWARF4-NOT: !DISubprogram(name: "-[Foo integer:]", scope: ![[STRUCT]], {{.*}}isDefinition: false
+// DWARF4-NOT: !DISubprogram(name: "+[Foo(Bar) zero:]", scope: ![[STRUCT]], {{.*}}isDefinition: false
+// DWARF4-NOT: !DISubprogram(name: "-[Foo(Bar) add:]", scope: ![[STRUCT]], {{.*}}isDefinition: false
+
+// CHECK: = distinct !DISubprogram(name: "-[Foo integer]"{{.*}}isDefinition: true
+// CHECK: = distinct !DISubprogram(name: "-[Foo integer:]"{{.*}}isDefinition: true
+// CHECK: = distinct !DISubprogram(name: "+[Foo(Bar) zero:]"{{.*}}isDefinition: true
+// CHECK: = distinct !DISubprogram(name: "-[Foo(Bar) add:]"{{.*}}isDefinition: true
diff --git a/test/CodeGenObjC/disable-tail-call-escaping-block.m b/test/CodeGenObjC/disable-tail-call-escaping-block.m
new file mode 100644
index 000000000000..48b0eda5a562
--- /dev/null
+++ b/test/CodeGenObjC/disable-tail-call-escaping-block.m
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -fblocks -fno-escaping-block-tail-calls -emit-llvm -o - %s | FileCheck %s
+
+// CHECK-LABEL: define void @test(
+// CHECK: store i8* bitcast (void (i8*)* @[[TEST_BLOCK_INVOKE0:.*]] to i8*)
+// CHECK: store i8* bitcast (void (i8*)* @[[TEST_BLOCK_INVOKE1:.*]] to i8*)
+// CHECK: store i8* bitcast (void (i8*)* @[[TEST_BLOCK_INVOKE2:.*]] to i8*)
+// CHECK: store i8* bitcast (void (i8*)* @[[TEST_BLOCK_INVOKE3:.*]] to i8*)
+// CHECK: store i8* bitcast (void (i8*)* @[[TEST_BLOCK_INVOKE4:.*]] to i8*)
+// CHECK: store i8* bitcast (void (i8*)* @[[TEST_BLOCK_INVOKE5:.*]] to i8*)
+// CHECK: store i8* bitcast (void (i8*)* @[[TEST_BLOCK_INVOKE6:.*]] to i8*)
+
+// CHECK: define internal void @[[TEST_BLOCK_INVOKE0]]({{.*}}) #[[DISABLEATTR:.*]] {
+// CHECK: define internal void @[[TEST_BLOCK_INVOKE1]]({{.*}}) #[[ENABLEATTR:.*]] {
+// CHECK: define internal void @[[TEST_BLOCK_INVOKE2]]({{.*}}) #[[DISABLEATTR]] {
+// CHECK: define internal void @[[TEST_BLOCK_INVOKE3]]({{.*}}) #[[DISABLEATTR]] {
+// CHECK: define internal void @[[TEST_BLOCK_INVOKE4]]({{.*}}) #[[ENABLEATTR]] {
+// CHECK: define internal void @[[TEST_BLOCK_INVOKE5]]({{.*}}) #[[DISABLEATTR]] {
+// CHECK: define internal void @[[TEST_BLOCK_INVOKE6]]({{.*}}) #[[ENABLEATTR]] {
+
+// CHECK: attributes #[[ENABLEATTR]] = {{{.*}}"disable-tail-calls"="false"{{.*}}}
+// CHECK: attributes #[[DISABLEATTR]] = {{{.*}}"disable-tail-calls"="true"{{.*}}}
+
+typedef void (^BlockTy)(void);
+typedef void (*NoEscapeFnTy)(__attribute__((noescape)) BlockTy);
+
+void callee0(__attribute__((noescape)) BlockTy);
+void callee1(BlockTy);
+
+__attribute__((objc_root_class))
+@interface C0
+-(void)m0:(__attribute__((noescape)) BlockTy)p;
+-(void)m1:(BlockTy)p;
+@end
+
+@implementation C0
+-(void)m0:(__attribute__((noescape)) BlockTy)p {}
+-(void)m1:(BlockTy)p {}
+@end
+
+NoEscapeFnTy noescapefunc;
+
+void test(id a, C0 *c0) {
+ BlockTy b0 = ^{ (void)a; }; // disable tail-call optimization.
+ callee0(b0);
+ callee0(^{ (void)a; }); // enable tail-call optimization.
+ callee1(^{ (void)a; }); // disable tail-call optimization.
+
+ BlockTy b1 = ^{ (void)a; }; // disable tail-call optimization.
+ [c0 m0:b1];
+ [c0 m0:^{ (void)a; }]; // enable tail-call optimization.
+ [c0 m1:^{ (void)a; }]; // disable tail-call optimization.
+
+ noescapefunc(^{ (void)a; }); // enable tail-call optimization.
+}
diff --git a/test/CodeGenObjC/dllstorage.m b/test/CodeGenObjC/dllstorage.m
index a2665eefad85..2cc4dc72a0cb 100644
--- a/test/CodeGenObjC/dllstorage.m
+++ b/test/CodeGenObjC/dllstorage.m
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -fdeclspec -fobjc-runtime=ios -fobjc-exceptions -S -emit-llvm -o - %s | FileCheck -check-prefix CHECK-IR %s
-// RUN: %clang_cc1 -triple i686-windows-itanium -fms-extensions -fobjc-runtime=macosx -fdeclspec -fobjc-exceptions -S -emit-llvm -o - %s | FileCheck -check-prefix CHECK-IR %s
-// RUN: %clang_cc1 -triple i686-windows-itanium -fms-extensions -fobjc-runtime=objfw -fdeclspec -fobjc-exceptions -S -emit-llvm -o - %s | FileCheck -check-prefix CHECK-FW %s
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -fdeclspec -fobjc-runtime=ios -fobjc-exceptions -S -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap -check-prefix CHECK-IR %s
+// RUN: %clang_cc1 -triple i686-windows-itanium -fms-extensions -fobjc-runtime=macosx -fdeclspec -fobjc-exceptions -S -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap -check-prefix CHECK-IR %s
+// RUN: %clang_cc1 -triple i686-windows-itanium -fms-extensions -fobjc-runtime=objfw -fdeclspec -fobjc-exceptions -S -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap -check-prefix CHECK-FW %s
// CHECK-IR-DAG: @_objc_empty_cache = external dllimport global %struct._objc_cache
@@ -16,11 +16,11 @@ __declspec(dllexport)
@interface J : I
@end
-// CHECK-IR-DAG: @"OBJC_METACLASS_$_J" = dllexport global %struct._class_t
-// CHECK-IR-DAG: @"OBJC_CLASS_$_J" = dllexport global %struct._class_t
+// CHECK-IR-DAG: @"OBJC_METACLASS_$_J" = dso_local dllexport global %struct._class_t
+// CHECK-IR-DAG: @"OBJC_CLASS_$_J" = dso_local dllexport global %struct._class_t
-// CHECK-FW-DAG: @_OBJC_METACLASS_J = dllexport global
-// CHECK-FW-DAG: @_OBJC_CLASS_J = dllexport global
+// CHECK-FW-DAG: @_OBJC_METACLASS_J = dso_local dllexport global
+// CHECK-FW-DAG: @_OBJC_CLASS_J = dso_local dllexport global
@implementation J {
id _ivar;
@@ -32,11 +32,11 @@ __declspec(dllexport)
@interface K : J
@end
-// CHECK-IR-DAG: @"OBJC_METACLASS_$_K" = global %struct._class_t
-// CHECK-IR-DAG: @"OBJC_CLASS_$_K" = global %struct._class_t
+// CHECK-IR-DAG: @"OBJC_METACLASS_$_K" = dso_local global %struct._class_t
+// CHECK-IR-DAG: @"OBJC_CLASS_$_K" = dso_local global %struct._class_t
-// CHECK-FW-DAG: @_OBJC_METACLASS_K = global
-// CHECK-FW-DAG: @_OBJC_CLASS_K = global
+// CHECK-FW-DAG: @_OBJC_METACLASS_K = dso_local global
+// CHECK-FW-DAG: @_OBJC_CLASS_K = dso_local global
@implementation K {
id _ivar;
@@ -49,11 +49,11 @@ __declspec(dllexport)
@interface L : K
@end
-// CHECK-IR-DAG: @"OBJC_METACLASS_$_L" = dllexport global %struct._class_t
-// CHECK-IR-DAG: @"OBJC_CLASS_$_L" = dllexport global %struct._class_t
+// CHECK-IR-DAG: @"OBJC_METACLASS_$_L" = dso_local dllexport global %struct._class_t
+// CHECK-IR-DAG: @"OBJC_CLASS_$_L" = dso_local dllexport global %struct._class_t
-// CHECK-FW-DAG: @_OBJC_METACLASS_L = dllexport global
-// CHECK-FW-DAG: @_OBJC_CLASS_L = dllexport global
+// CHECK-FW-DAG: @_OBJC_METACLASS_L = dso_local dllexport global
+// CHECK-FW-DAG: @_OBJC_CLASS_L = dso_local dllexport global
@implementation L {
id _none;
@@ -94,13 +94,13 @@ __attribute__((__objc_exception__))
@interface N : I
@end
-// CHECK-FW-DAG: @_OBJC_METACLASS_N = dllexport global
-// CHECK-FW-DAG: @_OBJC_CLASS_N = dllexport global
+// CHECK-FW-DAG: @_OBJC_METACLASS_N = dso_local dllexport global
+// CHECK-FW-DAG: @_OBJC_CLASS_N = dso_local dllexport global
@implementation N : I
@end
-// CHECK-IR-DAG: @"OBJC_EHTYPE_$_N" = dllexport global %struct._objc_typeinfo
+// CHECK-IR-DAG: @"OBJC_EHTYPE_$_N" = dso_local dllexport global %struct._objc_typeinfo
__declspec(dllimport)
__attribute__((__objc_exception__))
@@ -113,7 +113,7 @@ __attribute__((__objc_exception__))
@interface P : I
@end
-// CHECK-IR-DAG: @"OBJC_EHTYPE_$_P" = external global %struct._objc_typeinfo
+// CHECK-IR-DAG: @"OBJC_EHTYPE_$_P" = external dso_local global %struct._objc_typeinfo
@interface Q : M
@end
diff --git a/test/CodeGenObjC/forward-declare-protocol-gnu.m b/test/CodeGenObjC/forward-declare-protocol-gnu.m
new file mode 100644
index 000000000000..b57a4a48d4a0
--- /dev/null
+++ b/test/CodeGenObjC/forward-declare-protocol-gnu.m
@@ -0,0 +1,11 @@
+// RUN: %clang -S -emit-llvm %s -o - -x objective-c -fobjc-runtime=gnustep-1.5 | FileCheck %s
+
+// Regression test: check that we don't crash when referencing a forward-declared protocol.
+@protocol P;
+
+Protocol *getProtocol(void)
+{
+ return @protocol(P);
+}
+
+// CHECK: @.objc_protocol
diff --git a/test/CodeGenObjC/forward-protocol-metadata-symbols.m b/test/CodeGenObjC/forward-protocol-metadata-symbols.m
index 78c51e490137..16d33ec15d82 100644
--- a/test/CodeGenObjC/forward-protocol-metadata-symbols.m
+++ b/test/CodeGenObjC/forward-protocol-metadata-symbols.m
@@ -23,4 +23,17 @@ int main() {
// CHECK: @"\01l_OBJC_LABEL_PROTOCOL_$_P0" = weak hidden global
// CHECK: @"\01l_OBJC_PROTOCOL_REFERENCE_$_P0" = weak hidden global
-// CHECK: llvm.compiler.used = appending global [10 x i8*] {{[^"]*}}OBJC_CLASS_NAME_{{[^"]*}}OBJC_METH_VAR_NAME_{{[^"]*}}OBJC_METH_VAR_TYPE_{{[^"]*}}"\01l_OBJC_$_CLASS_METHODS_A"{{[^"]*}}"\01l_OBJC_CLASS_PROTOCOLS_$_A"{{[^"]*}}OBJC_CLASS_NAME_.1{{[^"]*}}"\01l_OBJC_PROTOCOL_$_P0"{{[^"]*}}"\01l_OBJC_LABEL_PROTOCOL_$_P0"{{[^"]*}}"\01l_OBJC_PROTOCOL_REFERENCE_$_P0"{{[^"]*}}"OBJC_LABEL_CLASS_$"{{[^"]*}} section "llvm.metadata"
+// CHECK: llvm.used = appending global [3 x i8*]
+// CHECK-SAME: "\01l_OBJC_PROTOCOL_$_P0"
+// CHECK-SAME: "\01l_OBJC_LABEL_PROTOCOL_$_P0"
+// CHECK-SAME: "\01l_OBJC_PROTOCOL_REFERENCE_$_P0"
+
+// CHECK: llvm.compiler.used = appending global [7 x i8*]
+// CHECK-SAME: OBJC_CLASS_NAME_
+// CHECK-SAME: OBJC_METH_VAR_NAME_
+// CHECK-SAME: OBJC_METH_VAR_TYPE_
+// CHECK-SAME: "\01l_OBJC_$_CLASS_METHODS_A"
+// CHECK-SAME: "\01l_OBJC_CLASS_PROTOCOLS_$_A"
+// CHECK-SAME: OBJC_CLASS_NAME_.1
+// CHECK-SAME: "OBJC_LABEL_CLASS_$"
+// CHECK-SAME: section "llvm.metadata"
diff --git a/test/CodeGenObjC/gnu-empty-protocol-v3.m b/test/CodeGenObjC/gnu-empty-protocol-v3.m
new file mode 100644
index 000000000000..151427bf062e
--- /dev/null
+++ b/test/CodeGenObjC/gnu-empty-protocol-v3.m
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -triple i686-pc-linux-gnu -fobjc-runtime=gnustep-1.9 -emit-llvm -o - %s | FileCheck %s
+
+@protocol X;
+
+__attribute__((objc_root_class))
+@interface Z <X>
+@end
+
+@implementation Z
+@end
+
+
+// CHECK: @.objc_protocol_list = internal global { i8*, i32, [0 x i8*] } zeroinitializer, align 4
+// CHECK: @.objc_method_list = internal global { i32, [0 x { i8*, i8* }] } zeroinitializer, align 4
+// CHECK: @.objc_protocol_name = private unnamed_addr constant [2 x i8] c"X\00", align 1
+// CHECK: @._OBJC_PROTOCOL_X = internal global { i8*, i8*, { i8*, i32, [0 x i8*] }*, i8*, i8*, i8*, i8*, i8*, i8* } {
+// CHECK-SAME: i8* inttoptr (i32 3 to i8*),
+// CHECK-SAME: i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.objc_protocol_name, i32 0, i32 0),
+// CHECK-SAME: { i8*, i32, [0 x i8*] }* @.objc_protocol_list
+// CHECK-SAME: { i32, [0 x { i8*, i8* }] }* @.objc_method_list
+// CHECK-SAME: { i32, [0 x { i8*, i8* }] }* @.objc_method_list
+// CHECK-SAME: { i32, [0 x { i8*, i8* }] }* @.objc_method_list
+// CHECK-SAME: { i32, [0 x { i8*, i8* }] }* @.objc_method_list
+// CHECK-SAME: i8* null
+// CHECK-SAME: i8* null
+// CHECK-SAME: }, align 4
diff --git a/test/CodeGenObjC/gnu-init.m b/test/CodeGenObjC/gnu-init.m
new file mode 100644
index 000000000000..beb06bbe0df4
--- /dev/null
+++ b/test/CodeGenObjC/gnu-init.m
@@ -0,0 +1,69 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-freebsd -S -emit-llvm -fobjc-runtime=gnustep-2.0 -o - %s | FileCheck %s -check-prefix=CHECK-NEW
+// RUN: %clang_cc1 -triple x86_64-unknown-freebsd -S -emit-llvm -fobjc-runtime=gnustep-1.8 -o - %s | FileCheck %s -check-prefix=CHECK-OLD
+
+// Almost minimal Objective-C file, check that it emits calls to the correct
+// runtime entry points.
+@interface X @end
+@implementation X @end
+
+
+// Check that we emit a class ref
+// CHECK-NEW: @._OBJC_REF_CLASS_X
+// CHECK-NEW-SAME: section "__objc_class_refs"
+
+// Check that we get a class ref to the defined class.
+// CHECK-NEW: @._OBJC_INIT_CLASS_X = global
+// CHECK-NEW-SAME* @._OBJC_CLASS_X, section "__objc_classes"
+
+// Check that we emit the section start and end symbols as hidden globals.
+// CHECK-NEW: @__start___objc_selectors = external hidden global i8*
+// CHECK-NEW: @__stop___objc_selectors = external hidden global i8*
+// CHECK-NEW: @__start___objc_classes = external hidden global i8*
+// CHECK-NEW: @__stop___objc_classes = external hidden global i8*
+// CHECK-NEW: @__start___objc_class_refs = external hidden global i8*
+// CHECK-NEW: @__stop___objc_class_refs = external hidden global i8*
+// CHECK-NEW: @__start___objc_cats = external hidden global i8*
+// CHECK-NEW: @__stop___objc_cats = external hidden global i8*
+// CHECK-NEW: @__start___objc_protocols = external hidden global i8*
+// CHECK-NEW: @__stop___objc_protocols = external hidden global i8*
+// CHECK-NEW: @__start___objc_protocol_refs = external hidden global i8*
+// CHECK-NEW: @__stop___objc_protocol_refs = external hidden global i8*
+// CHECK-NEW: @__start___objc_class_aliases = external hidden global i8*
+// CHECK-NEW: @__stop___objc_class_aliases = external hidden global i8*
+// CHECK-NEW: @__start___objc_constant_string = external hidden global i8*
+// CHECK-NEW: @__stop___objc_constant_string = external hidden global i8*
+
+// Check that we emit the init structure correctly, including in a comdat.
+// CHECK-NEW: @.objc_init = linkonce_odr hidden global { i64, i8**, i8**, i8**, i8**, i8**, i8**, i8**, i8**, i8**, i8**, i8**, i8**, i8**, i8**, i8**, i8** } { i64 0, i8** @__start___objc_selectors, i8** @__stop___objc_selectors, i8** @__start___objc_classes, i8** @__stop___objc_classes, i8** @__start___objc_class_refs, i8** @__stop___objc_class_refs, i8** @__start___objc_cats, i8** @__stop___objc_cats, i8** @__start___objc_protocols, i8** @__stop___objc_protocols, i8** @__start___objc_protocol_refs, i8** @__stop___objc_protocol_refs, i8** @__start___objc_class_aliases, i8** @__stop___objc_class_aliases, i8** @__start___objc_constant_string, i8** @__stop___objc_constant_string }, comdat, align 8
+
+// Check that the load function is manually inserted into .ctors.
+// CHECK-NEW: @.objc_ctor = linkonce hidden constant void ()* @.objcv2_load_function, section ".ctors", comdat
+
+
+// Make sure that we provide null versions of everything so the __start /
+// __stop symbols work.
+// CHECK-NEW: @.objc_null_selector = linkonce_odr hidden global { i8*, i8* } zeroinitializer, section "__objc_selectors", comdat, align 8
+// CHECK-NEW: @.objc_null_category = linkonce_odr hidden global { i8*, i8*, i8*, i8*, i8*, i8*, i8* } zeroinitializer, section "__objc_cats", comdat, align 8
+// CHECK-NEW: @.objc_null_protocol = linkonce_odr hidden global { i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8* } zeroinitializer, section "__objc_protocols", comdat, align 8
+// CHECK-NEW: @.objc_null_protocol_ref = linkonce_odr hidden global { i8* } zeroinitializer, section "__objc_protocol_refs", comdat, align 8
+// CHECK-NEW: @.objc_null_class_alias = linkonce_odr hidden global { i8*, i8* } zeroinitializer, section "__objc_class_aliases", comdat, align 8
+// CHECK-NEW: @.objc_null_constant_string = linkonce_odr hidden global { i8*, i32, i32, i32, i32, i8* } zeroinitializer, section "__objc_constant_string", comdat, align 8
+// Make sure that the null symbols are not going to be removed, even by linking.
+// CHECK-NEW: @llvm.used = appending global [7 x i8*] [i8* bitcast ({ { i8*, i8*, i8*, i64, i64, i64, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i64, i8* }*, i8*, i8*, i64, i64, i64, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i64, i8* }** @._OBJC_INIT_CLASS_X to i8*), i8* bitcast ({ i8*, i8* }* @.objc_null_selector to i8*), i8* bitcast ({ i8*, i8*, i8*, i8*, i8*, i8*, i8* }* @.objc_null_category to i8*), i8* bitcast ({ i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8* }* @.objc_null_protocol to i8*), i8* bitcast ({ i8* }* @.objc_null_protocol_ref to i8*), i8* bitcast ({ i8*, i8* }* @.objc_null_class_alias to i8*), i8* bitcast ({ i8*, i32, i32, i32, i32, i8* }* @.objc_null_constant_string to i8*)], section "llvm.metadata"
+// Make sure that the load function and the reference to it are marked as used.
+// CHECK-NEW: @llvm.compiler.used = appending global [2 x i8*] [i8* bitcast (void ()* @.objcv2_load_function to i8*), i8* bitcast (void ()** @.objc_ctor to i8*)], section "llvm.metadata"
+
+// Check that we emit the load function in a comdat and that it does the right thing.
+// CHECK-NEW: define linkonce_odr hidden void @.objcv2_load_function() comdat {
+// CHECK-NEW-NEXT: entry:
+// CHECK-NEW-NEXT: call void @__objc_load(
+// CHECK-NEW-SAME: @.objc_init
+// CHECK-NEW-NEXT: ret void
+
+// CHECK-OLD: @4 = internal global { i64, i64, i8*, { i64, { i8*, i8* }*, i16, i16, [4 x i8*] }* } { i64 9, i64 32, i8* getelementptr inbounds ([{{[0-9]+}} x i8], [{{[0-9]+}} x i8]* @.objc_source_file_name, i64 0, i64 0), { i64, { i8*, i8* }*, i16, i16, [4 x i8*] }* @3 }, align 8
+// CHECK-OLD: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @.objc_load_function, i8* null }]
+
+// CHECK-OLD: define internal void @.objc_load_function() {
+// CHECK-OLD-NEXT: entry:
+// CHECK-OLD-NEXT: call void ({ i64, i64, i8*, { i64, { i8*, i8* }*, i16, i16, [4 x i8*] }* }*, ...) @__objc_exec_class({ i64, i64, i8*, { i64, { i8*, i8* }*, i16, i16, [4 x i8*] }* }* @4)
+
diff --git a/test/CodeGenObjC/gnustep2-category.m b/test/CodeGenObjC/gnustep2-category.m
new file mode 100644
index 000000000000..e0dd7e3f5474
--- /dev/null
+++ b/test/CodeGenObjC/gnustep2-category.m
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-freebsd -S -emit-llvm -fobjc-runtime=gnustep-2.0 -o - %s | FileCheck %s
+
+
+// Check that we have a method list that refers to the correct thing method:
+// CHECK: internal global { i8*, i32, i64, [1 x { i8* (i8*, i8*, ...)*, i8*, i8* }] } { i8* null, i32 1, i64 24,
+// CHECK-SAME: @_i_X_Cat_x
+// CHECK-SAME: @".objc_selector_x_i16\010:8"
+
+// Check that we emit the correct encoding for the property (somewhere)
+// CHECK: c"Ti,R\00"
+
+// Check that we emit a single-element property list of the correct form.
+// CHECK: internal global { i32, i32, i8*, [1 x { i8*, i8*, i8*, i8*, i8* }] }
+
+// CHECK: @.objc_category_XCat = internal global { i8*, i8*, i8*, i8*, i8*, i8*, i8* }
+// CHECK-SAME: section "__objc_cats", align 8
+
+@interface X @end
+
+@interface X (Cat)
+@property (readonly) int x;
+@end
+
+@implementation X (Cat)
+- (int)x { return 12; }
+@end
diff --git a/test/CodeGenObjC/gnustep2-class.m b/test/CodeGenObjC/gnustep2-class.m
new file mode 100644
index 000000000000..0103a6fceee3
--- /dev/null
+++ b/test/CodeGenObjC/gnustep2-class.m
@@ -0,0 +1,55 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-freebsd -S -emit-llvm -fobjc-runtime=gnustep-2.0 -o - %s | FileCheck %s
+
+@interface Super @end
+
+@interface X : Super
+{
+ int ivar1;
+ id ivar2;
+}
+@property (readonly) int x;
+@property id y;
+@end
+
+@implementation X
+@synthesize y;
+
+- (int)x { return 12; }
++ (int)clsMeth { return 42; }
+- (id)meth { return ivar2; }
+@end
+
+// Check that we get an ivar offset variable for the synthesised ivar.
+// CHECK: @"__objc_ivar_offset_X.y.\01" = hidden global i32 16
+//
+// Check that we get a sensible metaclass method list.
+// CHECK: internal global { i8*, i32, i64, [1 x { i8* (i8*, i8*, ...)*, i8*, i8* }] }
+// CHECK-SAME: @_c_X__clsMeth
+
+// Check that we get a metaclass and that it is not an exposed symbol:
+// CHECK: @._OBJC_METACLASS_X = internal global
+
+// Check that we get a reference to the superclass symbol:
+// CHECK: @._OBJC_CLASS_Super = external global i8*
+
+// Check that we get an ivar list with all three ivars, in the correct order
+// CHECK: private global { i32, i64, [3 x { i8*, i8*, i32*, i32, i32 }] }
+// CHECK-SAME: @__objc_ivar_offset_X.ivar1.i
+// CHECK-SAME: @"__objc_ivar_offset_X.ivar2.\01"
+// CHECK-SAME: @"__objc_ivar_offset_X.y.\01"
+
+// Check that we get some plausible property metadata.
+// CHECK: private unnamed_addr constant [5 x i8] c"Ti,R\00", align 1
+// CHECK: private unnamed_addr constant [6 x i8] c"T@,Vy\00", align 1
+// CHECK: = internal global { i32, i32, i8*, [2 x { i8*, i8*, i8*, i8*, i8* }] } { i32 2, i32 40, i8* null,
+
+// Check that we get a class structure.
+// CHECK: @._OBJC_CLASS_X = global { { i8*, i8*, i8*, i64, i64, i64, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i64, i8* }*, i8*, i8*, i64, i64, i64, { i32, i64, [3 x { i8*, i8*, i32*, i32, i32 }] }*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i64, { i32, i32, i8*, [2 x { i8*, i8*, i8*, i8*, i8* }] }* }
+// CHECK-SAME: @._OBJC_METACLASS_X
+// CHECK-SAME: @._OBJC_CLASS_Super
+
+// And check that we get a pointer to it in the right place
+// CHECK: @._OBJC_REF_CLASS_X = global
+// CHECK-SAME: @._OBJC_CLASS_X
+// CHECK-SAME: section "__objc_class_refs"
+
diff --git a/test/CodeGenObjC/gnustep2-ivar-offset.m b/test/CodeGenObjC/gnustep2-ivar-offset.m
new file mode 100644
index 000000000000..432fa567de30
--- /dev/null
+++ b/test/CodeGenObjC/gnustep2-ivar-offset.m
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-freebsd -S -emit-llvm -fobjc-runtime=gnustep-2.0 -o - %s | FileCheck %s
+
+
+@class NSString;
+
+@interface ANObject {
+@public
+// Public ivars have default visibility
+// CHECK: @"__objc_ivar_offset_ANObject.isa.\01" = global i32 0
+ struct objc_object *isa;
+@private
+// Private and package ivars should have hidden linkage.
+// Check that in the GNUstep v2 ABI, instance variable offset names include
+// type encodings (with @ mangled to \01 to avoid collisions with ELF symbol
+// versions).
+// CHECK: private unnamed_addr constant [12 x i8] c"@\22NSString\22\00"
+// CHECK: @"__objc_ivar_offset_ANObject._stringIvar.\01" = hidden global i32 8
+ NSString *_stringIvar;
+@package
+// CHECK: @__objc_ivar_offset_ANObject._intIvar.i = hidden global i32 16
+ int _intIvar;
+}
+@end
+@implementation ANObject @end
+
+// Check that the ivar metadata contains 3 entries of the correct form and correctly sets the size.
+// CHECK: @.objc_ivar_list = private global { i32, i64, [3 x { i8*, i8*, i32*, i32, i32 }] } { i32 3, i64 32,
+// Check that we're emitting the extended type encoding for the string ivar.
diff --git a/test/CodeGenObjC/gnustep2-proto.m b/test/CodeGenObjC/gnustep2-proto.m
new file mode 100644
index 000000000000..536714f03a99
--- /dev/null
+++ b/test/CodeGenObjC/gnustep2-proto.m
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-freebsd -S -emit-llvm -fobjc-runtime=gnustep-2.0 -o - %s | FileCheck %s
+
+@protocol X
+@optional
+- (id)x;
+@required
++ (void*)y;
+@property int reqProp;
+@optional
+@property int optProp;
+@end
+
+// Check that we get some plausible-looking method lists.
+// CHECK: internal global { i32, i32, [2 x { i8*, i8* }] } { i32 2, i32 16,
+// CHECK-SAME: @".objc_selector_reqProp_i16\010:8"
+// CHECK-SAME: @".objc_selector_setReqProp:_v20\010:8i16"
+// CHECK: internal global { i32, i32, [3 x { i8*, i8* }] } { i32 3, i32 16,
+// CHECK-SAME: @".objc_selector_x_\0116\010:8"
+// CHECK-SAME: @".objc_selector_optProp_i16\010:8"
+// CHECK-SAME: @".objc_selector_setOptProp:_v20\010:8i16"
+
+
+// Check that we're emitting the protocol and a correctly initialised
+// indirection variable.
+// CHECK: @._OBJC_PROTOCOL_X = global
+// CHECK-SAME: , section "__objc_protocols", comdat, align 8
+// CHECK: @._OBJC_REF_PROTOCOL_X = global
+// CHECK-SAME: @._OBJC_PROTOCOL_X
+// CHECK-SAME: , section "__objc_protocol_refs", align 8
+
+
+// Check that we load from the indirection variable on protocol references.
+// CHECK: define i8* @x()
+// CHECK: = load
+// CHECK-SAME: @._OBJC_REF_PROTOCOL_X, align 8
+void *x()
+{
+ return @protocol(X);
+}
diff --git a/test/CodeGenObjC/ivar-type-encoding.m b/test/CodeGenObjC/ivar-type-encoding.m
index 2fd962cf07bb..a7ad55c6715c 100644
--- a/test/CodeGenObjC/ivar-type-encoding.m
+++ b/test/CodeGenObjC/ivar-type-encoding.m
@@ -29,10 +29,10 @@ int main() {
return 0;
}
-// CHECK: @0 = private unnamed_addr constant [12 x i8] c"_stringIvar\00"
-// CHECK: @1 = private unnamed_addr constant [12 x i8] c"@\22NSString\22\00"
-// CHECK: @2 = private unnamed_addr constant [9 x i8] c"_intIvar\00"
-// CHECK: @3 = private unnamed_addr constant [2 x i8] c"i\00"
+// CHECK: = private unnamed_addr constant [12 x i8] c"_stringIvar\00"
+// CHECK: = private unnamed_addr constant [12 x i8] c"@\22NSString\22\00"
+// CHECK: = private unnamed_addr constant [9 x i8] c"_intIvar\00"
+// CHECK: = private unnamed_addr constant [2 x i8] c"i\00"
@interface Class1 {
int : 3;
diff --git a/test/CodeGenObjC/messages-2.m b/test/CodeGenObjC/messages-2.m
index be66f71f66f7..38c5d5016a92 100644
--- a/test/CodeGenObjC/messages-2.m
+++ b/test/CodeGenObjC/messages-2.m
@@ -157,7 +157,7 @@ void test0(A *x) {
// CHECK: call {{.*}} @objc_msgSend_stret to
// CHECK-NEXT: br label
// CHECK: [[T0:%.*]] = bitcast [[POINT_T]]* [[POINT]] to i8*
- // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 48, i32 4, i1 false)
+ // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 4 [[T0]], i8 0, i64 48, i1 false)
// CHECK-NEXT: br label
// CHECK-NF: [[X:%.*]] = alloca [[A]]*
@@ -169,7 +169,7 @@ void test0(A *x) {
// CHECK-NF: call {{.*}} @objc_msgSend_stret to
// CHECK-NF-NEXT: br label
// CHECK-NF: [[T0:%.*]] = bitcast [[POINT_T]]* [[POINT]] to i8*
- // CHECK-NF-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 48, i32 4, i1 false)
+ // CHECK-NF-NEXT: call void @llvm.memset.p0i8.i64(i8* align 4 [[T0]], i8 0, i64 48, i1 false)
// CHECK-NF-NEXT: br label
MyPoint point = [x returnAPoint];
}
diff --git a/test/CodeGenObjC/noescape.m b/test/CodeGenObjC/noescape.m
index 49bc0e4a7d33..56e1e51e5d3f 100644
--- a/test/CodeGenObjC/noescape.m
+++ b/test/CodeGenObjC/noescape.m
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -fblocks -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -fblocks -emit-llvm -o - %s | FileCheck -check-prefix CHECK -check-prefix CHECK-NOARC %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -fblocks -emit-llvm -fobjc-arc -o - %s | FileCheck -check-prefix CHECK -check-prefix CHECK-ARC %s
typedef void (^BlockTy)(void);
@@ -12,6 +13,12 @@ void noescapeFunc1(__attribute__((noescape)) int *);
void noescapeFunc2(__attribute__((noescape)) id);
void noescapeFunc3(__attribute__((noescape)) union U);
+// Block descriptors of non-escaping blocks don't need pointers to copy/dispose
+// helper functions.
+
+// CHECK: %[[STRUCT_BLOCK_DESCRIPTOR:.*]] = type { i64, i64 }
+// CHECK: @[[BLOCK_DESCIPTOR_TMP_2:.*]] = internal constant { i64, i64, i8*, i64 } { i64 0, i64 40, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @{{.*}}, i32 0, i32 0), i64 256 }, align 8
+
// CHECK-LABEL: define void @test0(
// CHECK: call void @noescapeFunc0({{.*}}, {{.*}} nocapture {{.*}})
// CHECK: declare void @noescapeFunc0(i8*, {{.*}} nocapture)
@@ -69,3 +76,41 @@ void test5(BlockTy2 b, int *p) {
^(int *__attribute__((noescape)) p0){}(p);
b(p);
}
+
+// If the block is non-escaping, set the BLOCK_IS_NOESCAPE and BLOCK_IS_GLOBAL
+// bits of field 'flags' and set the 'isa' field to 'NSConcreteGlobalBlock'.
+
+// CHECK: define void @test6(i8* %{{.*}}, i8* %[[B:.*]])
+// CHECK: %{{.*}} = alloca i8*, align 8
+// CHECK: %[[B_ADDR:.*]] = alloca i8*, align 8
+// CHECK: %[[BLOCK:.*]] = alloca <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, align 8
+// CHECK-NOARC: store i8* %[[B]], i8** %[[B_ADDR]], align 8
+// CHECK-ARC: store i8* null, i8** %[[B_ADDR]], align 8
+// CHECK-ARC: call void @objc_storeStrong(i8** %[[B_ADDR]], i8* %[[B]])
+// CHECK-ARC: %[[V0:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %[[BLOCK]], i32 0, i32 5
+// CHECK: %[[BLOCK_ISA:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %[[BLOCK]], i32 0, i32 0
+// CHECK: store i8* bitcast (i8** @_NSConcreteGlobalBlock to i8*), i8** %[[BLOCK_ISA]], align 8
+// CHECK: %[[BLOCK_FLAGS:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %[[BLOCK]], i32 0, i32 1
+// CHECK: store i32 -796917760, i32* %[[BLOCK_FLAGS]], align 8
+// CHECK: %[[BLOCK_DESCRIPTOR:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %[[BLOCK]], i32 0, i32 4
+// CHECK: store %[[STRUCT_BLOCK_DESCRIPTOR]]* bitcast ({ i64, i64, i8*, i64 }* @[[BLOCK_DESCIPTOR_TMP_2]] to %[[STRUCT_BLOCK_DESCRIPTOR]]*), %[[STRUCT_BLOCK_DESCRIPTOR]]** %[[BLOCK_DESCRIPTOR]], align 8
+// CHECK: %[[BLOCK_CAPTURED:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %[[BLOCK]], i32 0, i32 5
+// CHECK-NOARC: %[[V1:.*]] = load i8*, i8** %[[B_ADDR]], align 8
+// CHECK-NOARC: store i8* %[[V1]], i8** %[[BLOCK_CAPTURED]], align 8
+// CHECK-ARC: %[[V2:.*]] = load i8*, i8** %[[B_ADDR]], align 8
+// CHECK-ARC: %[[V3:.*]] = call i8* @objc_retain(i8* %[[V2]]) #3
+// CHECK-ARC: store i8* %[[V3]], i8** %[[BLOCK_CAPTURED]], align 8
+// CHECK: call void @noescapeFunc0(
+// CHECK-ARC: call void @objc_storeStrong(i8** %[[V0]], i8* null)
+// CHECK-ARC: call void @objc_storeStrong(i8** %[[B_ADDR]], i8* null)
+
+// Non-escaping blocks don't need copy/dispose helper functions.
+
+// CHECK-NOT: define internal void @__copy_helper_block_
+// CHECK-NOT: define internal void @__destroy_helper_block_
+
+void func(id);
+
+void test6(id a, id b) {
+ noescapeFunc0(a, ^{ func(b); });
+}
diff --git a/test/CodeGenObjC/nontrivial-c-struct-exception.m b/test/CodeGenObjC/nontrivial-c-struct-exception.m
new file mode 100644
index 000000000000..7db53bb74249
--- /dev/null
+++ b/test/CodeGenObjC/nontrivial-c-struct-exception.m
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -fobjc-exceptions -fexceptions -emit-llvm -o - %s | FileCheck %s
+
+// CHECK: %[[STRUCT_STRONG:.*]] = type { i32, i8* }
+// CHECK: %[[STRUCT_WEAK:.*]] = type { i32, i8* }
+
+typedef struct {
+ int i;
+ id f1;
+} Strong;
+
+typedef struct {
+ int i;
+ __weak id f1;
+} Weak;
+
+// CHECK: define void @testStrongException()
+// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_STRONG]], align 8
+// CHECK: %[[AGG_TMP1:.*]] = alloca %[[STRUCT_STRONG]], align 8
+// CHECK: %[[CALL:.*]] = call [2 x i64] @genStrong()
+// CHECK: %[[V0:.*]] = bitcast %[[STRUCT_STRONG]]* %[[AGG_TMP]] to [2 x i64]*
+// CHECK: store [2 x i64] %[[CALL]], [2 x i64]* %[[V0]], align 8
+// CHECK: invoke [2 x i64] @genStrong()
+
+// CHECK: call void @calleeStrong([2 x i64] %{{.*}}, [2 x i64] %{{.*}})
+// CHECK-NEXT: ret void
+
+// CHECK: landingpad { i8*, i32 }
+// CHECK: %[[V9:.*]] = bitcast %[[STRUCT_STRONG]]* %[[AGG_TMP]] to i8**
+// CHECK: call void @__destructor_8_s8(i8** %[[V9]])
+// CHECK: br label
+
+// CHECK: resume
+
+Strong genStrong(void);
+void calleeStrong(Strong, Strong);
+
+void testStrongException(void) {
+ calleeStrong(genStrong(), genStrong());
+}
+
+// CHECK: define void @testWeakException()
+// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_WEAK]], align 8
+// CHECK: %[[AGG_TMP1:.*]] = alloca %[[STRUCT_WEAK]], align 8
+// CHECK: call void @genWeak(%[[STRUCT_WEAK]]* sret %[[AGG_TMP]])
+// CHECK: invoke void @genWeak(%[[STRUCT_WEAK]]* sret %[[AGG_TMP1]])
+
+// CHECK: call void @calleeWeak(%[[STRUCT_WEAK]]* %[[AGG_TMP]], %[[STRUCT_WEAK]]* %[[AGG_TMP1]])
+// CHECK: ret void
+
+// CHECK: landingpad { i8*, i32 }
+// CHECK: %[[V3:.*]] = bitcast %[[STRUCT_WEAK]]* %[[AGG_TMP]] to i8**
+// CHECK: call void @__destructor_8_w8(i8** %[[V3]])
+// CHECK: br label
+
+// CHECK: resume
+
+Weak genWeak(void);
+void calleeWeak(Weak, Weak);
+
+void testWeakException(void) {
+ calleeWeak(genWeak(), genWeak());
+}
diff --git a/test/CodeGenObjC/nontrivial-c-struct-func-name-collision.m b/test/CodeGenObjC/nontrivial-c-struct-func-name-collision.m
new file mode 100644
index 000000000000..bf512ec88b7f
--- /dev/null
+++ b/test/CodeGenObjC/nontrivial-c-struct-func-name-collision.m
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -emit-llvm -verify -o - %s
+
+typedef struct { // expected-error {{special function __default_constructor_8_s8 for non-trivial C struct has incorrect type}}
+ int i;
+ id f1;
+} StrongSmall;
+
+int __default_constructor_8_s8(double a) {
+ return 0;
+}
+
+void testIncorrectFunctionType(void) {
+ StrongSmall x;
+}
diff --git a/test/CodeGenObjC/objc-container-subscripting-1.m b/test/CodeGenObjC/objc-container-subscripting-1.m
index f9322fa63c1e..18f2f8cf6ffd 100644
--- a/test/CodeGenObjC/objc-container-subscripting-1.m
+++ b/test/CodeGenObjC/objc-container-subscripting-1.m
@@ -25,8 +25,8 @@ int main() {
// CHECK-NEXT: store i8* [[CALL]], i8** [[OLDOBJ:%.*]], align 8
val = (array[10] = oldObject);
-// CHECK: [[THREE:%.*]] = load {{%.*}} [[array:%.*]], align 8
-// CHECK-NEXT: [[FOUR:%.*]] = load i8*, i8** [[oldObject:%.*]], align 8
+// CHECK: [[FOUR:%.*]] = load i8*, i8** [[oldObject:%.*]], align 8
+// CHECK-NEXT: [[THREE:%.*]] = load {{%.*}} [[array:%.*]], align 8
// CHECK-NEXT: [[FIVE:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_.2
// CHECK-NEXT: [[SIX:%.*]] = bitcast {{%.*}} [[THREE]] to i8*
// CHECK-NEXT: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i8*, i32)*)(i8* [[SIX]], i8* [[FIVE]], i8* [[FOUR]], i32 10)
@@ -45,9 +45,9 @@ int main() {
val = (dictionary[key] = newObject);
-// CHECK: [[TWELVE:%.*]] = load {{%.*}} [[DICTIONARY]], align 8
+// CHECK: [[FOURTEEN:%.*]] = load i8*, i8** [[NEWOBJECT:%.*]], align 8
+// CHECK-NEXT: [[TWELVE:%.*]] = load {{%.*}} [[DICTIONARY]], align 8
// CHECK-NEXT: [[THIRTEEN:%.*]] = load i8*, i8** [[KEY]], align 8
-// CHECK-NEXT: [[FOURTEEN:%.*]] = load i8*, i8** [[NEWOBJECT:%.*]], align 8
// CHECK-NEXT: [[SIXTEEN:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_.6
// CHECK-NEXT: [[SEVENTEEN:%.*]] = bitcast {{%.*}} [[TWELVE]] to i8*
// CHECK-NEXT: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i8*, i8*)*)(i8* [[SEVENTEEN]], i8* [[SIXTEEN]], i8* [[FOURTEEN]], i8* [[THIRTEEN]])
diff --git a/test/CodeGenObjC/objc-non-trivial-struct-nrvo.m b/test/CodeGenObjC/objc-non-trivial-struct-nrvo.m
new file mode 100644
index 000000000000..798aba248941
--- /dev/null
+++ b/test/CodeGenObjC/objc-non-trivial-struct-nrvo.m
@@ -0,0 +1,134 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck %s
+
+// CHECK: %[[STRUCT_TRIVIAL:.*]] = type { i32 }
+// CHECK: %[[STRUCT_TRIVIALBIG:.*]] = type { [64 x i32] }
+// CHECK: %[[STRUCT_STRONG:.*]] = type { i8* }
+// CHECK: %[[STRUCT_WEAK:.*]] = type { i8* }
+
+typedef struct {
+ int x;
+} Trivial;
+
+typedef struct {
+ int x[64];
+} TrivialBig;
+
+typedef struct {
+ id x;
+} Strong;
+
+typedef struct {
+ __weak id x;
+} Weak;
+
+// CHECK: define i32 @testTrivial()
+// CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_TRIVIAL]], align 4
+// CHECK-NEXT: call void @func0(%[[STRUCT_TRIVIAL]]* %[[RETVAL]])
+// CHECK-NOT: memcpy
+// CHECK: ret i32 %
+
+void func0(Trivial *);
+
+Trivial testTrivial(void) {
+ Trivial a;
+ func0(&a);
+ return a;
+}
+
+void func1(TrivialBig *);
+
+// CHECK: define void @testTrivialBig(%[[STRUCT_TRIVIALBIG]]* noalias sret %[[AGG_RESULT:.*]])
+// CHECK-NOT: alloca
+// CHECK: call void @func1(%[[STRUCT_TRIVIALBIG]]* %[[AGG_RESULT]])
+// CHECK-NEXT: ret void
+
+TrivialBig testTrivialBig(void) {
+ TrivialBig a;
+ func1(&a);
+ return a;
+}
+
+// CHECK: define i8* @testStrong()
+// CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_STRONG]], align 8
+// CHECK: %[[NRVO:.*]] = alloca i1, align 1
+// CHECK: %[[V0:.*]] = bitcast %[[STRUCT_STRONG]]* %[[RETVAL]] to i8**
+// CHECK: call void @__default_constructor_8_s0(i8** %[[V0]])
+// CHECK: store i1 true, i1* %[[NRVO]], align 1
+// CHECK: %[[NRVO_VAL:.*]] = load i1, i1* %[[NRVO]], align 1
+// CHECK: br i1 %[[NRVO_VAL]],
+
+// CHECK: %[[V1:.*]] = bitcast %[[STRUCT_STRONG]]* %[[RETVAL]] to i8**
+// CHECK: call void @__destructor_8_s0(i8** %[[V1]])
+// CHECK: br
+
+// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_STRONG]], %[[STRUCT_STRONG]]* %[[RETVAL]], i32 0, i32 0
+// CHECK: %[[V2:.*]] = load i8*, i8** %[[COERCE_DIVE]], align 8
+// CHECK: ret i8* %[[V2]]
+
+Strong testStrong(void) {
+ Strong a;
+ return a;
+}
+
+// CHECK: define void @testWeak(%[[STRUCT_WEAK]]* noalias sret %[[AGG_RESULT:.*]])
+// CHECK: %[[NRVO:.*]] = alloca i1, align 1
+// CHECK: %[[V0:.*]] = bitcast %[[STRUCT_WEAK]]* %[[AGG_RESULT]] to i8**
+// CHECK: call void @__default_constructor_8_w0(i8** %[[V0]])
+// CHECK: store i1 true, i1* %[[NRVO]], align 1
+// CHECK: %[[NRVO_VAL:.*]] = load i1, i1* %[[NRVO]], align 1
+// CHECK: br i1 %[[NRVO_VAL]],
+
+// CHECK: %[[V1:.*]] = bitcast %[[STRUCT_WEAK]]* %[[AGG_RESULT]] to i8**
+// CHECK: call void @__destructor_8_w0(i8** %[[V1]])
+// CHECK: br
+
+// CHECK-NOT: call
+// CHECK: ret void
+
+Weak testWeak(void) {
+ Weak a;
+ return a;
+}
+
+// CHECK: define void @testWeak2(
+// CHECK: call void @__default_constructor_8_w0(
+// CHECK: call void @__default_constructor_8_w0(
+// CHECK: call void @__copy_constructor_8_8_w0(
+// CHECK: call void @__copy_constructor_8_8_w0(
+// CHECK: call void @__destructor_8_w0(
+// CHECK: call void @__destructor_8_w0(
+
+Weak testWeak2(int c) {
+ Weak a, b;
+ if (c)
+ return a;
+ else
+ return b;
+}
+
+// CHECK: define internal void @"\01-[C1 foo1]"(%[[STRUCT_WEAK]]* noalias sret %[[AGG_RESULT:.*]], %{{.*}}* %{{.*}}, i8* %{{.*}})
+// CHECK: %[[NRVO:.*]] = alloca i1, align 1
+// CHECK: %[[V0:.*]] = bitcast %[[STRUCT_WEAK]]* %[[AGG_RESULT]] to i8**
+// CHECK: call void @__default_constructor_8_w0(i8** %[[V0]])
+// CHECK: store i1 true, i1* %[[NRVO]], align 1
+// CHECK: %[[NRVO_VAL:.*]] = load i1, i1* %[[NRVO]], align 1
+// CHECK: br i1 %[[NRVO_VAL]],
+
+// CHECK: %[[V1:.*]] = bitcast %[[STRUCT_WEAK]]* %[[AGG_RESULT]] to i8**
+// CHECK: call void @__destructor_8_w0(i8** %[[V1]])
+// CHECK: br
+
+// CHECK-NOT: call
+// CHECK: ret void
+
+__attribute__((objc_root_class))
+@interface C1
+- (Weak)foo1;
+@end
+
+@implementation C1
+- (Weak)foo1 {
+ Weak a;
+ return a;
+}
+@end
diff --git a/test/CodeGenObjC/objc-runtime-name.m b/test/CodeGenObjC/objc-runtime-name.m
new file mode 100644
index 000000000000..228525fc55c0
--- /dev/null
+++ b/test/CodeGenObjC/objc-runtime-name.m
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -triple i386-apple-macosx10.13.0 -fobjc-runtime=macosx-fragile-10.13.0 -fobjc-subscripting-legacy-runtime -emit-llvm -o - %s | FileCheck %s
+
+// Check that the runtime name is emitted and used instead of the class
+// identifier.
+
+// CHECK: module asm {{.*}}objc_class_name_XYZ=0
+// CHECK: module asm {{.*}}globl .objc_class_name_XYZ
+// CHECK: module asm {{.*}}lazy_reference .objc_class_name_XYZ
+
+// CHECK: @[[OBJC_CLASS_NAME:.*]] = private unnamed_addr constant [4 x i8] c"XYZ{{.*}}, section "__TEXT,__cstring,cstring_literals",
+// CHECK: = private global {{.*}} bitcast ([4 x i8]* @[[OBJC_CLASS_NAME]] to {{.*}}), section "__OBJC,__cls_refs,literal_pointers,no_dead_strip"
+
+__attribute__((objc_root_class,objc_runtime_name("XYZ")))
+@interface A
++(void)m1;
+@end
+
+@implementation A
++(void)m1 {}
+@end
+
+void test(void) {
+ [A m1];
+}
diff --git a/test/CodeGenObjC/personality.m b/test/CodeGenObjC/personality.m
new file mode 100644
index 000000000000..0db0803c455d
--- /dev/null
+++ b/test/CodeGenObjC/personality.m
@@ -0,0 +1,76 @@
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=gnustep-1.7 -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP-1_7
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=gnustep -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC-SEH
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC-SJLJ
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW-SEH
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW-SJLJ
+
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MSVC
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MSVC
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MSVC
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MSVC
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=gnustep-1.7 -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MSVC
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=gnustep -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MSVC
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MSVC
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MSVC
+
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fdwarf-exceptions -fobjc-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE-MINGW-DWARF
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE-MINGW-SEH
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE-MINGW-SJLJ
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=gnustep-1.7 -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP-1_7
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=gnustep -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC-SEH
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC-SJLJ
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW-SEH
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW-SJLJ
+
+void g(void);
+
+// CHECK-MACOSX-FRAGILE: personality i8* bitcast (i32 (...)* @__gcc_personality_v0 to i8*)
+// CHECK-NS: personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*)
+// CHECK-GNUSTEP-1_7: personality i8* bitcast (i32 (...)* @__gnustep_objc_personality_v0 to i8*)
+// CHECK-GNUSTEP: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_v0 to i8*)
+// CHECK-GCC: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_v0 to i8*)
+// CHECK-GCC-SEH: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_seh0 to i8*)
+// CHECK-GCC-SJLJ: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_sj0 to i8*)
+// CHECK-OBJFW: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_v0 to i8*)
+// CHECK-OBJFW-SEH: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_seh0 to i8*)
+// CHECK-OBJFW-SJLJ: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_sj0 to i8*)
+
+// CHECK-WIN-MSVC: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
+
+// CHECK-MACOSX-FRAGILE-MINGW-DWARF: personality i8* bitcast (i32 (...)* @__gcc_personality_v0 to i8*)
+// CHECK-MACOSX-FRAGILE-MINGW-SEH: personality i8* bitcast (i32 (...)* @__gcc_personality_seh0 to i8*)
+// CHECK-MACOSX-FRAGILE-MINGW-SJLJ: personality i8* bitcast (i32 (...)* @__gcc_personality_sj0 to i8*)
+
+void f(void) {
+ @try {
+ g();
+ } @catch (...) {
+ }
+}
+
+#if defined(__SEH_EXCEPTIONS__)
+// CHECK-WIN-SEH-X86: personality i8* bitcast (i32 (...)* @_except_handler3 to i8*)
+// CHECK-WIN-SEH-X64: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
+
+void h(void) {
+ __try {
+ i();
+ } __finally {
+ }
+}
+#endif
+
diff --git a/test/CodeGenObjC/runtime-abi-match.m b/test/CodeGenObjC/runtime-abi-match.m
index ef391724ece0..ac8eea6cd421 100644
--- a/test/CodeGenObjC/runtime-abi-match.m
+++ b/test/CodeGenObjC/runtime-abi-match.m
@@ -1,4 +1,4 @@
-// RUN: %clang -target armv7-windows -fobjc-runtime=ios -O1 -fexceptions -S -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple thumbv7--windows-itanium -fobjc-runtime=ios -O1 -fexceptions -fobjc-exceptions -emit-llvm %s -o - | FileCheck %s
// REQUIRES: arm-registered-target
void (*f)(id);
diff --git a/test/CodeGenObjC/stret-1.m b/test/CodeGenObjC/stret-1.m
index 2314d5a9ecf5..1122c28a468b 100644
--- a/test/CodeGenObjC/stret-1.m
+++ b/test/CodeGenObjC/stret-1.m
@@ -16,7 +16,7 @@ int main(int argc, const char **argv)
s = [(id)(argc&~255) method];
// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (%struct.stret*, i8*, i8*)*)(%struct.stret* sret [[T0:%[^,]+]]
// CHECK: [[T0P:%.*]] = bitcast %struct.stret* [[T0]] to i8*
- // CHECK: call void @llvm.memset.p0i8.i64(i8* [[T0P]], i8 0, i64 400, i32 4, i1 false)
+ // CHECK: call void @llvm.memset.p0i8.i64(i8* align 4 [[T0P]], i8 0, i64 400, i1 false)
s = [Test method];
// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (%struct.stret*, i8*, i8*)*)(%struct.stret* sret [[T1:%[^,]+]]
diff --git a/test/CodeGenObjC/strong-in-c-struct.m b/test/CodeGenObjC/strong-in-c-struct.m
new file mode 100644
index 000000000000..36e9049635f2
--- /dev/null
+++ b/test/CodeGenObjC/strong-in-c-struct.m
@@ -0,0 +1,563 @@
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -emit-llvm -o - -DUSESTRUCT -I %S/Inputs %s | FileCheck %s
+
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -emit-pch -I %S/Inputs -o %t %s
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -include-pch %t -emit-llvm -o - -DUSESTRUCT -I %S/Inputs %s | FileCheck %s
+
+#ifndef HEADER
+#define HEADER
+#include "strong_in_union.h"
+
+typedef void (^BlockTy)(void);
+
+typedef struct {
+ int a[4];
+} Trivial;
+
+typedef struct {
+ Trivial f0;
+ id f1;
+} Strong;
+
+typedef struct {
+ int i;
+ id f1;
+} StrongSmall;
+
+typedef struct {
+ Strong f0;
+ id f1;
+ double d;
+} StrongOuter;
+
+typedef struct {
+ int f0;
+ volatile id f1;
+} StrongVolatile;
+
+typedef struct {
+ BlockTy f0;
+} StrongBlock;
+
+typedef struct {
+ int i;
+ id f0[2][2];
+} IDArray;
+
+typedef struct {
+ double d;
+ Strong f0[2][2];
+} StructArray;
+
+typedef struct {
+ id f0;
+ int i : 9;
+} Bitfield0;
+
+typedef struct {
+ char c;
+ int i0 : 2;
+ int i1 : 4;
+ id f0;
+ int i2 : 31;
+ int i3 : 1;
+ id f1;
+ int : 0;
+ int a[3];
+ id f2;
+ double d;
+ int i4 : 1;
+ volatile int i5 : 2;
+ volatile char i6;
+} Bitfield1;
+
+typedef struct {
+ id x;
+ volatile int a[16];
+} VolatileArray ;
+
+#endif
+
+#ifdef USESTRUCT
+
+StrongSmall getStrongSmall(void);
+StrongOuter getStrongOuter(void);
+void calleeStrongSmall(StrongSmall);
+void func(Strong *);
+
+// CHECK: %[[STRUCT_BITFIELD1:.*]] = type { i8, i8, i8*, i32, i8*, [3 x i32], i8*, double, i8, i8 }
+
+// CHECK: define void @test_constructor_destructor_StrongOuter()
+// CHECK: %[[T:.*]] = alloca %[[STRUCT_STRONGOUTER:.*]], align 8
+// CHECK: %[[V0:.*]] = bitcast %[[STRUCT_STRONGOUTER]]* %[[T]] to i8**
+// CHECK: call void @__default_constructor_8_s16_s24(i8** %[[V0]])
+// CHECK: %[[V1:.*]] = bitcast %[[STRUCT_STRONGOUTER]]* %[[T]] to i8**
+// CHECK: call void @__destructor_8_s16_s24(i8** %[[V1]])
+// CHECK: ret void
+
+// CHECK: define linkonce_odr hidden void @__default_constructor_8_s16_s24(i8** %[[DST:.*]])
+// CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8
+// CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
+// CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
+// CHECK: call void @__default_constructor_8_s16(i8** %[[V0]])
+// CHECK: %[[V1:.*]] = bitcast i8** %[[V0]] to i8*
+// CHECK: %[[V2:.*]] = getelementptr inbounds i8, i8* %[[V1]], i64 24
+// CHECK: %[[V3:.*]] = bitcast i8* %[[V2]] to i8**
+// CHECK: %[[V4:.*]] = bitcast i8** %[[V3]] to i8*
+// CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 %[[V4]], i8 0, i64 8, i1 false)
+// CHECK: ret void
+
+// CHECK: define linkonce_odr hidden void @__default_constructor_8_s16(i8** %[[DST:.*]])
+// CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8
+// CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
+// CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
+// CHECK: %[[V1:.*]] = bitcast i8** %[[V0]] to i8*
+// CHECK: %[[V2:.*]] = getelementptr inbounds i8, i8* %[[V1]], i64 16
+// CHECK: %[[V3:.*]] = bitcast i8* %[[V2]] to i8**
+// CHECK: %[[V4:.*]] = bitcast i8** %[[V3]] to i8*
+// CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 %[[V4]], i8 0, i64 8, i1 false)
+// CHECK: ret void
+
+// CHECK: define linkonce_odr hidden void @__destructor_8_s16_s24(i8** %[[DST:.*]])
+// CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8
+// CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
+// CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
+// CHECK: call void @__destructor_8_s16(i8** %[[V0]])
+// CHECK: %[[V1:.*]] = bitcast i8** %[[V0]] to i8*
+// CHECK: %[[V2:.*]] = getelementptr inbounds i8, i8* %[[V1]], i64 24
+// CHECK: %[[V3:.*]] = bitcast i8* %[[V2]] to i8**
+// CHECK: call void @objc_storeStrong(i8** %[[V3]], i8* null)
+// CHECK: ret void
+
+// CHECK: define linkonce_odr hidden void @__destructor_8_s16(i8** %[[DST:.*]])
+// CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8
+// CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
+// CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
+// CHECK: %[[V1:.*]] = bitcast i8** %[[V0]] to i8*
+// CHECK: %[[V2:.*]] = getelementptr inbounds i8, i8* %[[V1]], i64 16
+// CHECK: %[[V3:.*]] = bitcast i8* %[[V2]] to i8**
+// CHECK: call void @objc_storeStrong(i8** %[[V3]], i8* null)
+// CHECK: ret void
+
+void test_constructor_destructor_StrongOuter(void) {
+ StrongOuter t;
+}
+
+// CHECK: define void @test_copy_constructor_StrongOuter(%[[STRUCT_STRONGOUTER:.*]]* %[[S:.*]])
+// CHECK: %[[S_ADDR:.*]] = alloca %[[STRUCT_STRONGOUTER]]*, align 8
+// CHECK: %[[T:.*]] = alloca %[[STRUCT_STRONGOUTER]], align 8
+// CHECK: store %[[STRUCT_STRONGOUTER]]* %[[S]], %[[STRUCT_STRONGOUTER]]** %[[S_ADDR]], align 8
+// CHECK: %[[V0:.*]] = load %[[STRUCT_STRONGOUTER]]*, %[[STRUCT_STRONGOUTER]]** %[[S_ADDR]], align 8
+// CHECK: %[[V1:.*]] = bitcast %[[STRUCT_STRONGOUTER]]* %[[T]] to i8**
+// CHECK: %[[V2:.*]] = bitcast %[[STRUCT_STRONGOUTER]]* %[[V0]] to i8**
+// CHECK: call void @__copy_constructor_8_8_t0w16_s16_s24_t32w8(i8** %[[V1]], i8** %[[V2]])
+// CHECK: %[[V3:.*]] = bitcast %[[STRUCT_STRONGOUTER]]* %[[T]] to i8**
+// CHECK: call void @__destructor_8_s16_s24(i8** %[[V3]])
+// CHECK: ret void
+
+// CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_t0w16_s16_s24_t32w8(i8** %[[DST:.*]], i8** %[[SRC:.*]])
+// CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8
+// CHECK: %[[SRC_ADDR:.*]] = alloca i8**, align 8
+// CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
+// CHECK: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8
+// CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
+// CHECK: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8
+// CHECK: call void @__copy_constructor_8_8_t0w16_s16(i8** %[[V0]], i8** %[[V1]])
+// CHECK: %[[V2:.*]] = bitcast i8** %[[V0]] to i8*
+// CHECK: %[[V3:.*]] = getelementptr inbounds i8, i8* %[[V2]], i64 24
+// CHECK: %[[V4:.*]] = bitcast i8* %[[V3]] to i8**
+// CHECK: %[[V5:.*]] = bitcast i8** %[[V1]] to i8*
+// CHECK: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 24
+// CHECK: %[[V7:.*]] = bitcast i8* %[[V6]] to i8**
+// CHECK: %[[V8:.*]] = load i8*, i8** %[[V7]], align 8
+// CHECK: %[[V9:.*]] = call i8* @objc_retain(i8* %[[V8]])
+// CHECK: store i8* %[[V9]], i8** %[[V4]], align 8
+// CHECK: %[[V10:.*]] = bitcast i8** %[[V0]] to i8*
+// CHECK: %[[V11:.*]] = getelementptr inbounds i8, i8* %[[V10]], i64 32
+// CHECK: %[[V12:.*]] = bitcast i8* %[[V11]] to i8**
+// CHECK: %[[V13:.*]] = bitcast i8** %[[V1]] to i8*
+// CHECK: %[[V14:.*]] = getelementptr inbounds i8, i8* %[[V13]], i64 32
+// CHECK: %[[V15:.*]] = bitcast i8* %[[V14]] to i8**
+// CHECK: %[[V16:.*]] = bitcast i8** %[[V12]] to i64*
+// CHECK: %[[V17:.*]] = bitcast i8** %[[V15]] to i64*
+// CHECK: %[[V18:.*]] = load i64, i64* %[[V17]], align 8
+// CHECK: store i64 %[[V18]], i64* %[[V16]], align 8
+// CHECK: ret void
+
+// CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_t0w16_s16(i8** %[[DST:.*]], i8** %[[SRC:.*]])
+// CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8
+// CHECK: %[[SRC_ADDR:.*]] = alloca i8**, align 8
+// CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
+// CHECK: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8
+// CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
+// CHECK: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8
+// CHECK: %[[V2:.*]] = bitcast i8** %[[V0]] to i8*
+// CHECK: %[[V3:.*]] = bitcast i8** %[[V1]] to i8*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %[[V2]], i8* align 8 %[[V3]], i64 16, i1 false)
+// CHECK: %[[V4:.*]] = bitcast i8** %[[V0]] to i8*
+// CHECK: %[[V5:.*]] = getelementptr inbounds i8, i8* %[[V4]], i64 16
+// CHECK: %[[V6:.*]] = bitcast i8* %[[V5]] to i8**
+// CHECK: %[[V7:.*]] = bitcast i8** %[[V1]] to i8*
+// CHECK: %[[V8:.*]] = getelementptr inbounds i8, i8* %[[V7]], i64 16
+// CHECK: %[[V9:.*]] = bitcast i8* %[[V8]] to i8**
+// CHECK: %[[V10:.*]] = load i8*, i8** %[[V9]], align 8
+// CHECK: %[[V11:.*]] = call i8* @objc_retain(i8* %[[V10]])
+// CHECK: store i8* %[[V11]], i8** %[[V6]], align 8
+// CHECK: ret void
+
+void test_copy_constructor_StrongOuter(StrongOuter *s) {
+ StrongOuter t = *s;
+}
+
+/// CHECK: define linkonce_odr hidden void @__copy_assignment_8_8_t0w16_s16_s24_t32w8(i8** %[[DST:.*]], i8** %[[SRC:.*]])
+// CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8
+// CHECK: %[[SRC_ADDR:.*]] = alloca i8**, align 8
+// CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
+// CHECK: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8
+// CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
+// CHECK: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8
+// CHECK: %[[V2:.*]] = bitcast i8** %[[V0]] to i8*
+// CHECK: %[[V3:.*]] = getelementptr inbounds i8, i8* %[[V2]], i64 24
+// CHECK: %[[V4:.*]] = bitcast i8* %[[V3]] to i8**
+// CHECK: %[[V5:.*]] = bitcast i8** %[[V1]] to i8*
+// CHECK: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 24
+// CHECK: %[[V7:.*]] = bitcast i8* %[[V6]] to i8**
+// CHECK: %[[V8:.*]] = load i8*, i8** %[[V7]], align 8
+// CHECK: call void @objc_storeStrong(i8** %[[V4]], i8* %[[V8]])
+
+void test_copy_assignment_StrongOuter(StrongOuter *d, StrongOuter *s) {
+ *d = *s;
+}
+
+// CHECK: define void @test_move_constructor_StrongOuter()
+// CHECK: %[[T1:.*]] = getelementptr inbounds %[[STRUCT_BLOCK_BYREF_T:.*]], %[[STRUCT_BLOCK_BYREF_T]]* %{{.*}}, i32 0, i32 7
+// CHECK: %[[V1:.*]] = bitcast %[[STRUCT_STRONGOUTER]]* %[[T1]] to i8**
+// CHECK: call void @__default_constructor_8_s16_s24(i8** %[[V1]])
+// CHECK: %[[T2:.*]] = getelementptr inbounds %[[STRUCT_BLOCK_BYREF_T]], %[[STRUCT_BLOCK_BYREF_T]]* %{{.*}}, i32 0, i32 7
+// CHECK: %[[V9:.*]] = bitcast %[[STRUCT_STRONGOUTER]]* %[[T2]] to i8**
+// CHECK: call void @__destructor_8_s16_s24(i8** %[[V9]])
+
+// CHECK: define internal void @__Block_byref_object_copy_(i8*, i8*)
+// CHECK: call void @__move_constructor_8_8_t0w16_s16_s24_t32w8(
+
+// CHECK: define linkonce_odr hidden void @__move_constructor_8_8_t0w16_s16_s24_t32w8(i8** %[[DST:.*]], i8** %[[SRC:.*]])
+// CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8
+// CHECK: %[[SRC_ADDR:.*]] = alloca i8**, align 8
+// CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
+// CHECK: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8
+// CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
+// CHECK: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8
+// CHECK: call void @__move_constructor_8_8_t0w16_s16(i8** %[[V0]], i8** %[[V1]])
+// CHECK: %[[V2:.*]] = bitcast i8** %[[V0]] to i8*
+// CHECK: %[[V3:.*]] = getelementptr inbounds i8, i8* %[[V2]], i64 24
+// CHECK: %[[V4:.*]] = bitcast i8* %[[V3]] to i8**
+// CHECK: %[[V5:.*]] = bitcast i8** %[[V1]] to i8*
+// CHECK: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 24
+// CHECK: %[[V7:.*]] = bitcast i8* %[[V6]] to i8**
+// CHECK: %[[V8:.*]] = load i8*, i8** %[[V7]], align 8
+// CHECK: store i8* null, i8** %[[V7]], align 8
+// CHECK: store i8* %[[V8]], i8** %[[V4]], align 8
+
+// CHECK: define internal void @__Block_byref_object_dispose_(i8*)
+// CHECK: call void @__destructor_8_s16_s24(
+
+void test_move_constructor_StrongOuter(void) {
+ __block StrongOuter t;
+ BlockTy b = ^{ (void)t; };
+}
+
+// CHECK: define linkonce_odr hidden void @__move_assignment_8_8_t0w16_s16_s24_t32w8(i8** %[[DST:.*]], i8** %[[SRC:.*]])
+// CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8
+// CHECK: %[[SRC_ADDR:.*]] = alloca i8**, align 8
+// CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
+// CHECK: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8
+// CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
+// CHECK: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8
+// CHECK: call void @__move_assignment_8_8_t0w16_s16(i8** %[[V0]], i8** %[[V1]])
+// CHECK: %[[V2:.*]] = bitcast i8** %[[V0]] to i8*
+// CHECK: %[[V3:.*]] = getelementptr inbounds i8, i8* %[[V2]], i64 24
+// CHECK: %[[V4:.*]] = bitcast i8* %[[V3]] to i8**
+// CHECK: %[[V5:.*]] = bitcast i8** %[[V1]] to i8*
+// CHECK: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 24
+// CHECK: %[[V7:.*]] = bitcast i8* %[[V6]] to i8**
+// CHECK: %[[V8:.*]] = load i8*, i8** %[[V7]], align 8
+// CHECK: store i8* null, i8** %[[V7]], align 8
+// CHECK: %[[V9:.*]] = load i8*, i8** %[[V4]], align 8
+// CHECK: store i8* %[[V8]], i8** %[[V4]], align 8
+// CHECK: call void @objc_release(i8* %[[V9]])
+
+void test_move_assignment_StrongOuter(StrongOuter *p) {
+ *p = getStrongOuter();
+}
+
+// CHECK: define void @test_parameter_StrongSmall([2 x i64] %[[A_COERCE:.*]])
+// CHECK: %[[A:.*]] = alloca %[[STRUCT_STRONG:.*]], align 8
+// CHECK: %[[V0:.*]] = bitcast %[[STRUCT_STRONG]]* %[[A]] to [2 x i64]*
+// CHECK: store [2 x i64] %[[A_COERCE]], [2 x i64]* %[[V0]], align 8
+// CHECK: %[[V1:.*]] = bitcast %[[STRUCT_STRONG]]* %[[A]] to i8**
+// CHECK: call void @__destructor_8_s8(i8** %[[V1]])
+// CHECK: ret void
+
+void test_parameter_StrongSmall(StrongSmall a) {
+}
+
+// CHECK: define void @test_argument_StrongSmall([2 x i64] %[[A_COERCE:.*]])
+// CHECK: %[[A:.*]] = alloca %[[STRUCT_STRONGSMALL:.*]], align 8
+// CHECK: %[[TEMP_LVALUE:.*]] = alloca %[[STRUCT_STRONGSMALL]], align 8
+// CHECK: %[[V0:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[A]] to [2 x i64]*
+// CHECK: store [2 x i64] %[[A_COERCE]], [2 x i64]* %[[V0]], align 8
+// CHECK: %[[V1:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[TEMP_LVALUE]] to i8**
+// CHECK: %[[V2:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[A]] to i8**
+// CHECK: call void @__copy_constructor_8_8_t0w4_s8(i8** %[[V1]], i8** %[[V2]])
+// CHECK: %[[V3:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[TEMP_LVALUE]] to [2 x i64]*
+// CHECK: %[[V4:.*]] = load [2 x i64], [2 x i64]* %[[V3]], align 8
+// CHECK: call void @calleeStrongSmall([2 x i64] %[[V4]])
+// CHECK: %[[V5:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[A]] to i8**
+// CHECK: call void @__destructor_8_s8(i8** %[[V5]])
+// CHECK: ret void
+
+void test_argument_StrongSmall(StrongSmall a) {
+ calleeStrongSmall(a);
+}
+
+// CHECK: define [2 x i64] @test_return_StrongSmall([2 x i64] %[[A_COERCE:.*]])
+// CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_STRONGSMALL:.*]], align 8
+// CHECK: %[[A:.*]] = alloca %[[STRUCT_STRONGSMALL]], align 8
+// CHECK: %[[V0:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[A]] to [2 x i64]*
+// CHECK: store [2 x i64] %[[A_COERCE]], [2 x i64]* %[[V0]], align 8
+// CHECK: %[[V1:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[RETVAL]] to i8**
+// CHECK: %[[V2:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[A]] to i8**
+// CHECK: call void @__copy_constructor_8_8_t0w4_s8(i8** %[[V1]], i8** %[[V2]])
+// CHECK: %[[V3:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[A]] to i8**
+// CHECK: call void @__destructor_8_s8(i8** %[[V3]])
+// CHECK: %[[V4:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[RETVAL]] to [2 x i64]*
+// CHECK: %[[V5:.*]] = load [2 x i64], [2 x i64]* %[[V4]], align 8
+// CHECK: ret [2 x i64] %[[V5]]
+
+StrongSmall test_return_StrongSmall(StrongSmall a) {
+ return a;
+}
+
+// CHECK: define void @test_destructor_ignored_result()
+// CHECK: %[[COERCE:.*]] = alloca %[[STRUCT_STRONGSMALL:.*]], align 8
+// CHECK: %[[CALL:.*]] = call [2 x i64] @getStrongSmall()
+// CHECK: %[[V0:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[COERCE]] to [2 x i64]*
+// CHECK: store [2 x i64] %[[CALL]], [2 x i64]* %[[V0]], align 8
+// CHECK: %[[V1:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[COERCE]] to i8**
+// CHECK: call void @__destructor_8_s8(i8** %[[V1]])
+// CHECK: ret void
+
+void test_destructor_ignored_result(void) {
+ getStrongSmall();
+}
+
+// CHECK: define void @test_copy_constructor_StrongBlock(
+// CHECK: call void @__copy_constructor_8_8_sb0(
+// CHECK: call void @__destructor_8_sb0(
+// CHECK: ret void
+
+// CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_sb0(i8** %[[DST:.*]], i8** %[[SRC:.*]])
+// CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8
+// CHECK: %[[SRC_ADDR:.*]] = alloca i8**, align 8
+// CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
+// CHECK: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8
+// CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
+// CHECK: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8
+// CHECK: %[[V2:.*]] = load i8*, i8** %[[V1]], align 8
+// CHECK: %[[V3:.*]] = call i8* @objc_retainBlock(i8* %[[V2]])
+// CHECK: store i8* %[[V3]], i8** %[[V0]], align 8
+// CHECK: ret void
+
+void test_copy_constructor_StrongBlock(StrongBlock *s) {
+ StrongBlock t = *s;
+}
+
+// CHECK: define void @test_copy_assignment_StrongBlock(%[[STRUCT_STRONGBLOCK:.*]]* %[[D:.*]], %[[STRUCT_STRONGBLOCK]]* %[[S:.*]])
+// CHECK: call void @__copy_assignment_8_8_sb0(
+
+// CHECK: define linkonce_odr hidden void @__copy_assignment_8_8_sb0(i8** %[[DST:.*]], i8** %[[SRC:.*]])
+// CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8
+// CHECK: %[[SRC_ADDR:.*]] = alloca i8**, align 8
+// CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
+// CHECK: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8
+// CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
+// CHECK: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8
+// CHECK: %[[V2:.*]] = load i8*, i8** %[[V1]], align 8
+// CHECK: %[[V3:.*]] = call i8* @objc_retainBlock(i8* %[[V2]])
+// CHECK: %[[V4:.*]] = load i8*, i8** %[[V0]], align 8
+// CHECK: store i8* %[[V3]], i8** %[[V0]], align 8
+// CHECK: call void @objc_release(i8* %[[V4]])
+// CHECK: ret void
+
+void test_copy_assignment_StrongBlock(StrongBlock *d, StrongBlock *s) {
+ *d = *s;
+}
+
+// CHECK: define void @test_copy_constructor_StrongVolatile0(
+// CHECK: call void @__copy_constructor_8_8_t0w4_sv8(
+// CHECK: call void @__destructor_8_sv8(
+
+// CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_t0w4_sv8(
+// CHECK: %[[V8:.*]] = load volatile i8*, i8** %{{.*}}, align 8
+// CHECK: %[[V9:.*]] = call i8* @objc_retain(i8* %[[V8]])
+// CHECK: store volatile i8* %[[V9]], i8** %{{.*}}, align 8
+
+void test_copy_constructor_StrongVolatile0(StrongVolatile *s) {
+ StrongVolatile t = *s;
+}
+
+// CHECK: define void @test_copy_constructor_StrongVolatile1(
+// CHECK: call void @__copy_constructor_8_8_tv0w128_sv16(
+
+void test_copy_constructor_StrongVolatile1(Strong *s) {
+ volatile Strong t = *s;
+}
+
+// CHECK: define void @test_block_capture_Strong()
+// CHECK: call void @__default_constructor_8_s16(
+// CHECK: call void @__copy_constructor_8_8_t0w16_s16(
+// CHECK: call void @__destructor_8_s16(
+// CHECK: call void @__destructor_8_s16(
+// CHECK: ret void
+
+// CHECK: define internal void @__copy_helper_block_.1(i8*, i8*)
+// CHECK: call void @__copy_constructor_8_8_t0w16_s16(
+// CHECK: ret void
+
+// CHECK: define internal void @__destroy_helper_block_.2(
+// CHECK: call void @__destructor_8_s16(
+// CHECK: ret void
+
+void test_block_capture_Strong(void) {
+ Strong t;
+ BlockTy b = ^(){ (void)t; };
+}
+
+// CHECK: define void @test_variable_length_array(i32 %[[N:.*]])
+// CHECK: %[[N_ADDR:.*]] = alloca i32, align 4
+// CHECK: store i32 %[[N]], i32* %[[N_ADDR]], align 4
+// CHECK: %[[V0:.*]] = load i32, i32* %[[N_ADDR]], align 4
+// CHECK: %[[V1:.*]] = zext i32 %[[V0]] to i64
+// CHECK: %[[VLA:.*]] = alloca %[[STRUCT_STRONG:.*]], i64 %[[V1]], align 8
+// CHECK: %[[V3:.*]] = bitcast %[[STRUCT_STRONG]]* %[[VLA]] to i8**
+// CHECK: %[[V4:.*]] = mul nuw i64 24, %[[V1]]
+// CHECK: %[[V5:.*]] = bitcast i8** %[[V3]] to i8*
+// CHECK: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 %[[V4]]
+// CHECK: %[[DSTARRAY_END:.*]] = bitcast i8* %[[V6]] to i8**
+// CHECK: br label
+
+// CHECK: %[[DSTADDR_CUR:.*]] = phi i8** [ %[[V3]], {{.*}} ], [ %[[V7:.*]], {{.*}} ]
+// CHECK: %[[DONE:.*]] = icmp eq i8** %[[DSTADDR_CUR]], %[[DSTARRAY_END]]
+// CHECK: br i1 %[[DONE]], label
+
+// CHECK: call void @__default_constructor_8_s16(i8** %[[DSTADDR_CUR]])
+// CHECK: %[[V8:.*]] = bitcast i8** %[[DSTADDR_CUR]] to i8*
+// CHECK: %[[V9:.*]] = getelementptr inbounds i8, i8* %[[V8]], i64 24
+// CHECK: %[[V7]] = bitcast i8* %[[V9]] to i8**
+// CHECK: br label
+
+// CHECK: call void @func(%[[STRUCT_STRONG]]* %[[VLA]])
+// CHECK: %[[V10:.*]] = getelementptr inbounds %[[STRUCT_STRONG]], %[[STRUCT_STRONG]]* %[[VLA]], i64 %[[V1]]
+// CHECK: %[[ARRAYDESTROY_ISEMPTY:.*]] = icmp eq %[[STRUCT_STRONG]]* %[[VLA]], %[[V10]]
+// CHECK: br i1 %[[ARRAYDESTROY_ISEMPTY]], label
+
+// CHECK: %[[ARRAYDESTROY_ELEMENTPAST:.*]] = phi %[[STRUCT_STRONG]]* [ %[[V10]], {{.*}} ], [ %[[ARRAYDESTROY_ELEMENT:.*]], {{.*}} ]
+// CHECK: %[[ARRAYDESTROY_ELEMENT]] = getelementptr inbounds %[[STRUCT_STRONG]], %[[STRUCT_STRONG]]* %[[ARRAYDESTROY_ELEMENTPAST]], i64 -1
+// CHECK: %[[V11:.*]] = bitcast %[[STRUCT_STRONG]]* %[[ARRAYDESTROY_ELEMENT]] to i8**
+// CHECK: call void @__destructor_8_s16(i8** %[[V11]])
+// CHECK: %[[ARRAYDESTROY_DONE:.*]] = icmp eq %[[STRUCT_STRONG]]* %[[ARRAYDESTROY_ELEMENT]], %[[VLA]]
+// CHECK: br i1 %[[ARRAYDESTROY_DONE]], label
+
+// CHECK: ret void
+
+void test_variable_length_array(int n) {
+ Strong a[n];
+ func(a);
+}
+
+// CHECK: define linkonce_odr hidden void @__default_constructor_8_AB8s8n4_s8_AE(
+// CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 %{{.*}}, i8 0, i64 32, i1 false)
+void test_constructor_destructor_IDArray(void) {
+ IDArray t;
+}
+
+// CHECK: define linkonce_odr hidden void @__default_constructor_8_AB8s24n4_s24_AE(
+void test_constructor_destructor_StructArray(void) {
+ StructArray t;
+}
+
+// Check that IRGen copies the 9-bit bitfield emitting i16 load and store.
+
+// CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_s0_t8w2(
+// CHECK: %[[V4:.*]] = bitcast i8** %{{.*}} to i8*
+// CHECK: %[[V5:.*]] = getelementptr inbounds i8, i8* %[[V4]], i64 8
+// CHECK: %[[V6:.*]] = bitcast i8* %[[V5]] to i8**
+// CHECK: %[[V7:.*]] = bitcast i8** %{{.*}} to i8*
+// CHECK: %[[V8:.*]] = getelementptr inbounds i8, i8* %[[V7]], i64 8
+// CHECK: %[[V9:.*]] = bitcast i8* %[[V8]] to i8**
+// CHECK: %[[V10:.*]] = bitcast i8** %[[V6]] to i16*
+// CHECK: %[[V11:.*]] = bitcast i8** %[[V9]] to i16*
+// CHECK: %[[V12:.*]] = load i16, i16* %[[V11]], align 8
+// CHECK: store i16 %[[V12]], i16* %[[V10]], align 8
+// CHECK: ret void
+
+void test_copy_constructor_Bitfield0(Bitfield0 *a) {
+ Bitfield0 t = *a;
+}
+
+// CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_t0w2_s8_t16w4_s24_t32w12_s48_t56w9_tv513w2_tv520w8
+// CHECK: %[[V4:.*]] = load i16, i16* %{{.*}}, align 8
+// CHECK: store i16 %[[V4]], i16* %{{.*}}, align 8
+// CHECK: %[[V21:.*]] = load i32, i32* %{{.*}}, align 8
+// CHECK: store i32 %[[V21]], i32* %{{.*}}, align 8
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %{{.*}}, i8* align 8 %{{.*}}, i64 12, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %{{.*}}, i8* align 8 %{{.*}}, i64 9, i1 false)
+// CHECK: %[[V54:.*]] = bitcast i8** %[[V0:.*]] to %[[STRUCT_BITFIELD1]]*
+// CHECK: %[[I5:.*]] = getelementptr inbounds %[[STRUCT_BITFIELD1]], %[[STRUCT_BITFIELD1]]* %[[V54]], i32 0, i32 8
+// CHECK: %[[V55:.*]] = bitcast i8** %[[V1:.*]] to %[[STRUCT_BITFIELD1]]*
+// CHECK: %[[I51:.*]] = getelementptr inbounds %[[STRUCT_BITFIELD1]], %[[STRUCT_BITFIELD1]]* %[[V55]], i32 0, i32 8
+// CHECK: %[[BF_LOAD:.*]] = load volatile i8, i8* %[[I51]], align 8
+// CHECK: %[[BF_SHL:.*]] = shl i8 %[[BF_LOAD]], 5
+// CHECK: %[[BF_ASHR:.*]] = ashr i8 %[[BF_SHL]], 6
+// CHECK: %[[BF_CAST:.*]] = sext i8 %[[BF_ASHR]] to i32
+// CHECK: %[[V56:.*]] = trunc i32 %[[BF_CAST]] to i8
+// CHECK: %[[BF_LOAD2:.*]] = load volatile i8, i8* %[[I5]], align 8
+// CHECK: %[[BF_VALUE:.*]] = and i8 %[[V56]], 3
+// CHECK: %[[BF_SHL3:.*]] = shl i8 %[[BF_VALUE]], 1
+// CHECK: %[[BF_CLEAR:.*]] = and i8 %[[BF_LOAD2]], -7
+// CHECK: %[[BF_SET:.*]] = or i8 %[[BF_CLEAR]], %[[BF_SHL3]]
+// CHECK: store volatile i8 %[[BF_SET]], i8* %[[I5]], align 8
+// CHECK: %[[V57:.*]] = bitcast i8** %[[V0]] to %[[STRUCT_BITFIELD1]]*
+// CHECK: %[[I6:.*]] = getelementptr inbounds %[[STRUCT_BITFIELD1]], %[[STRUCT_BITFIELD1]]* %[[V57]], i32 0, i32 9
+// CHECK: %[[V58:.*]] = bitcast i8** %[[V1]] to %[[STRUCT_BITFIELD1]]*
+// CHECK: %[[I64:.*]] = getelementptr inbounds %[[STRUCT_BITFIELD1]], %[[STRUCT_BITFIELD1]]* %[[V58]], i32 0, i32 9
+// CHECK: %[[V59:.*]] = load volatile i8, i8* %[[I64]], align 1
+// CHECK: store volatile i8 %[[V59]], i8* %[[I6]], align 1
+
+void test_copy_constructor_Bitfield1(Bitfield1 *a) {
+ Bitfield1 t = *a;
+}
+
+// CHECK: define void @test_strong_in_union()
+// CHECK: alloca %{{.*}}
+// CHECK-NEXT: ret void
+
+void test_strong_in_union() {
+ U t;
+}
+
+// CHECK: define void @test_copy_constructor_VolatileArray(
+// CHECK: call void @__copy_constructor_8_8_s0_AB8s4n16_tv64w32_AE(
+
+// CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_s0_AB8s4n16_tv64w32_AE(
+// CHECK: %[[ADDR_CUR:.*]] = phi i8**
+// CHECK: %[[ADDR_CUR1:.*]] = phi i8**
+// CHECK: %[[V12:.*]] = bitcast i8** %[[ADDR_CUR]] to i32*
+// CHECK: %[[V13:.*]] = bitcast i8** %[[ADDR_CUR1]] to i32*
+// CHECK: %[[V14:.*]] = load volatile i32, i32* %[[V13]], align 4
+// CHECK: store volatile i32 %[[V14]], i32* %[[V12]], align 4
+
+void test_copy_constructor_VolatileArray(VolatileArray *a) {
+ VolatileArray t = *a;
+}
+
+#endif /* USESTRUCT */
diff --git a/test/CodeGenObjC/ubsan-nullability.m b/test/CodeGenObjC/ubsan-nullability.m
index eeb24b03c868..8e7a9cba7c71 100644
--- a/test/CodeGenObjC/ubsan-nullability.m
+++ b/test/CodeGenObjC/ubsan-nullability.m
@@ -1,6 +1,6 @@
// REQUIRES: asserts
-// RUN: %clang_cc1 -x objective-c -emit-llvm -triple x86_64-apple-macosx10.10.0 -fsanitize=nullability-arg,nullability-assign,nullability-return -w %s -o - | FileCheck %s
-// RUN: %clang_cc1 -x objective-c++ -emit-llvm -triple x86_64-apple-macosx10.10.0 -fsanitize=nullability-arg,nullability-assign,nullability-return -w %s -o - | FileCheck %s
+// RUN: %clang_cc1 -x objective-c -emit-llvm -triple x86_64-apple-macosx10.10.0 -fblocks -fobjc-arc -fsanitize=nullability-arg,nullability-assign,nullability-return -w %s -o - | FileCheck %s
+// RUN: %clang_cc1 -x objective-c++ -emit-llvm -triple x86_64-apple-macosx10.10.0 -fblocks -fobjc-arc -fsanitize=nullability-arg,nullability-assign,nullability-return -w %s -o - | FileCheck %s
// CHECK: [[NONNULL_RV_LOC1:@.*]] = private unnamed_addr global {{.*}} i32 100, i32 6
// CHECK: [[NONNULL_ARG_LOC:@.*]] = private unnamed_addr global {{.*}} i32 204, i32 15 {{.*}} i32 190, i32 23
@@ -177,6 +177,37 @@ void call_A(A *a, int *p) {
void dont_crash(int *_Nonnull p, ...) {}
+@protocol NSObject
+- (id)init;
+@end
+@interface NSObject <NSObject> {}
+@end
+
+#pragma clang assume_nonnull begin
+
+/// Create a "NSObject * _Nonnull" instance.
+NSObject *get_nonnull_error() {
+ // Use nil for convenience. The actual object doesn't matter.
+ return (NSObject *)NULL;
+}
+
+NSObject *_Nullable no_null_return_value_diagnostic(int flag) {
+// CHECK-LABEL: define internal {{.*}}no_null_return_value_diagnostic{{i?}}_block_invoke
+// CHECK-NOT: @__ubsan_handle_nullability_return
+ NSObject *_Nullable (^foo)() = ^() {
+ if (flag) {
+ // Clang should not infer a nonnull return value for this block when this
+ // call is present.
+ return get_nonnull_error();
+ } else {
+ return (NSObject *)NULL;
+ }
+ };
+ return foo();
+}
+
+#pragma clang assume_nonnull end
+
int main() {
nonnull_retval1(INULL);
nonnull_retval2(INNULL, INNULL, INULL, (int *_Nullable)NULL, 0, 0, 0, 0);
@@ -188,5 +219,7 @@ int main() {
nonnull_init2(INULL);
call_A((A *)NULL, INULL);
dont_crash(INNULL, NULL);
+ no_null_return_value_diagnostic(0);
+ no_null_return_value_diagnostic(1);
return 0;
}
diff --git a/test/CodeGenObjC/weak-in-c-struct.m b/test/CodeGenObjC/weak-in-c-struct.m
new file mode 100644
index 000000000000..b0f4c0851021
--- /dev/null
+++ b/test/CodeGenObjC/weak-in-c-struct.m
@@ -0,0 +1,193 @@
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -emit-llvm -o - %s | FileCheck -check-prefix=ARM64 -check-prefix=COMMON %s
+// RUN: %clang_cc1 -triple thumbv7-apple-ios10 -fobjc-arc -fblocks -fobjc-runtime=ios-10.0 -emit-llvm -o - %s | FileCheck -check-prefix=COMMON %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.13 -fobjc-arc -fblocks -fobjc-runtime=macosx-10.13.0 -emit-llvm -o - %s | FileCheck -check-prefix=COMMON %s
+// RUN: %clang_cc1 -triple i386-apple-macosx10.13.0 -fobjc-arc -fblocks -fobjc-runtime=macosx-fragile-10.13.0 -emit-llvm -o - %s | FileCheck -check-prefix=COMMON %s
+
+typedef void (^BlockTy)(void);
+
+// COMMON: %[[STRUCT_WEAK:.*]] = type { i32, i8* }
+
+typedef struct {
+ int f0;
+ __weak id f1;
+} Weak;
+
+Weak getWeak(void);
+void calleeWeak(Weak);
+
+// ARM64: define void @test_constructor_destructor_Weak()
+// ARM64: %[[T:.*]] = alloca %[[STRUCT_WEAK]], align 8
+// ARM64: %[[V0:.*]] = bitcast %[[STRUCT_WEAK]]* %[[T]] to i8**
+// ARM64: call void @__default_constructor_8_w8(i8** %[[V0]])
+// ARM64: %[[V1:.*]] = bitcast %[[STRUCT_WEAK]]* %[[T]] to i8**
+// ARM64: call void @__destructor_8_w8(i8** %[[V1]])
+// ARM64: ret void
+
+// ARM64: define linkonce_odr hidden void @__default_constructor_8_w8(i8** %[[DST:.*]])
+// ARM64: %[[DST_ADDR:.*]] = alloca i8**, align 8
+// ARM64: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
+// ARM64: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
+// ARM64: %[[V1]] = bitcast i8** %[[V0]] to i8*
+// ARM64: %[[V2:.*]] = getelementptr inbounds i8, i8* %[[V1]], i64 8
+// ARM64: %[[V3:.*]] = bitcast i8* %[[V2]] to i8**
+// ARM64: %[[V4:.*]] = bitcast i8** %[[V3]] to i8*
+// ARM64: call void @llvm.memset.p0i8.i64(i8* align 8 %[[V4]], i8 0, i64 8, i1 false)
+
+// ARM64: define linkonce_odr hidden void @__destructor_8_w8(i8** %[[DST:.*]])
+// ARM64: %[[DST_ADDR:.*]] = alloca i8**, align 8
+// ARM64: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
+// ARM64: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
+// ARM64: %[[V1:.*]] = bitcast i8** %[[V0]] to i8*
+// ARM64: %[[V2:.*]] = getelementptr inbounds i8, i8* %[[V1]], i64 8
+// ARM64: %[[V3:.*]] = bitcast i8* %[[V2]] to i8**
+// ARM64: call void @objc_destroyWeak(i8** %[[V3]])
+
+void test_constructor_destructor_Weak(void) {
+ Weak t;
+}
+
+// ARM64: define void @test_copy_constructor_Weak(%[[STRUCT_WEAK]]* %{{.*}})
+// ARM64: call void @__copy_constructor_8_8_t0w4_w8(i8** %{{.*}}, i8** %{{.*}})
+// ARM64: call void @__destructor_8_w8(i8** %{{.*}})
+
+// ARM64: define linkonce_odr hidden void @__copy_constructor_8_8_t0w4_w8(i8** %[[DST:.*]], i8** %[[SRC:.*]])
+// ARM64: %[[DST_ADDR:.*]] = alloca i8**, align 8
+// ARM64: %[[SRC_ADDR:.*]] = alloca i8**, align 8
+// ARM64: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
+// ARM64: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8
+// ARM64: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
+// ARM64: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8
+// ARM64: %[[V2:.*]] = bitcast i8** %[[V0]] to i32*
+// ARM64: %[[V3:.*]] = bitcast i8** %[[V1]] to i32*
+// ARM64: %[[V4:.*]] = load i32, i32* %[[V3]], align 8
+// ARM64: store i32 %[[V4]], i32* %[[V2]], align 8
+// ARM64: %[[V5:.*]] = bitcast i8** %[[V0]] to i8*
+// ARM64: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 8
+// ARM64: %[[V7:.*]] = bitcast i8* %[[V6]] to i8**
+// ARM64: %[[V8:.*]] = bitcast i8** %[[V1]] to i8*
+// ARM64: %[[V9:.*]] = getelementptr inbounds i8, i8* %[[V8]], i64 8
+// ARM64: %[[V10:.*]] = bitcast i8* %[[V9]] to i8**
+// ARM64: call void @objc_copyWeak(i8** %[[V7]], i8** %[[V10]])
+
+void test_copy_constructor_Weak(Weak *s) {
+ Weak t = *s;
+}
+
+// ARM64: define void @test_copy_assignment_Weak(%[[STRUCT_WEAK]]* %{{.*}}, %[[STRUCT_WEAK]]* %{{.*}})
+// ARM64: call void @__copy_assignment_8_8_t0w4_w8(i8** %{{.*}}, i8** %{{.*}})
+
+// ARM64: define linkonce_odr hidden void @__copy_assignment_8_8_t0w4_w8(i8** %[[DST:.*]], i8** %[[SRC:.*]])
+// ARM64: %[[DST_ADDR:.*]] = alloca i8**, align 8
+// ARM64: %[[SRC_ADDR:.*]] = alloca i8**, align 8
+// ARM64: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
+// ARM64: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8
+// ARM64: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
+// ARM64: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8
+// ARM64: %[[V2:.*]] = bitcast i8** %[[V0]] to i32*
+// ARM64: %[[V3:.*]] = bitcast i8** %[[V1]] to i32*
+// ARM64: %[[V4:.*]] = load i32, i32* %[[V3]], align 8
+// ARM64: store i32 %[[V4]], i32* %[[V2]], align 8
+// ARM64: %[[V5:.*]] = bitcast i8** %[[V0]] to i8*
+// ARM64: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 8
+// ARM64: %[[V7:.*]] = bitcast i8* %[[V6]] to i8**
+// ARM64: %[[V8:.*]] = bitcast i8** %[[V1]] to i8*
+// ARM64: %[[V9:.*]] = getelementptr inbounds i8, i8* %[[V8]], i64 8
+// ARM64: %[[V10:.*]] = bitcast i8* %[[V9]] to i8**
+// ARM64: %[[V11:.*]] = call i8* @objc_loadWeakRetained(i8** %[[V10]])
+// ARM64: %[[V12:.*]] = call i8* @objc_storeWeak(i8** %[[V7]], i8* %[[V11]])
+// ARM64: call void @objc_release(i8* %[[V11]])
+
+void test_copy_assignment_Weak(Weak *d, Weak *s) {
+ *d = *s;
+}
+
+// ARM64: define internal void @__Block_byref_object_copy_(i8*, i8*)
+// ARM64: call void @__move_constructor_8_8_t0w4_w8(i8** %{{.*}}, i8** %{{.*}})
+
+// ARM64: define linkonce_odr hidden void @__move_constructor_8_8_t0w4_w8(i8** %[[DST:.*]], i8** %[[SRC:.*]])
+// ARM64: %[[DST_ADDR:.*]] = alloca i8**, align 8
+// ARM64: %[[SRC_ADDR:.*]] = alloca i8**, align 8
+// ARM64: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
+// ARM64: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8
+// ARM64: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
+// ARM64: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8
+// ARM64: %[[V2:.*]] = bitcast i8** %[[V0]] to i32*
+// ARM64: %[[V3:.*]] = bitcast i8** %[[V1]] to i32*
+// ARM64: %[[V4:.*]] = load i32, i32* %[[V3]], align 8
+// ARM64: store i32 %[[V4]], i32* %[[V2]], align 8
+// ARM64: %[[V5:.*]] = bitcast i8** %[[V0]] to i8*
+// ARM64: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 8
+// ARM64: %[[V7:.*]] = bitcast i8* %[[V6]] to i8**
+// ARM64: %[[V8:.*]] = bitcast i8** %[[V1]] to i8*
+// ARM64: %[[V9:.*]] = getelementptr inbounds i8, i8* %[[V8]], i64 8
+// ARM64: %[[V10:.*]] = bitcast i8* %[[V9]] to i8**
+// ARM64: call void @objc_moveWeak(i8** %[[V7]], i8** %[[V10]])
+
+void test_move_constructor_Weak(void) {
+ __block Weak t;
+ BlockTy b = ^{ (void)t; };
+}
+
+// ARM64: define void @test_move_assignment_Weak(%[[STRUCT_WEAK]]* %{{.*}})
+// ARM64: call void @__move_assignment_8_8_t0w4_w8(i8** %{{.*}}, i8** %{{.*}})
+
+// ARM64: define linkonce_odr hidden void @__move_assignment_8_8_t0w4_w8(i8** %[[DST:.*]], i8** %[[SRC:.*]])
+// ARM64: %[[DST_ADDR:.*]] = alloca i8**, align 8
+// ARM64: %[[SRC_ADDR:.*]] = alloca i8**, align 8
+// ARM64: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
+// ARM64: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8
+// ARM64: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
+// ARM64: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8
+// ARM64: %[[V2:.*]] = bitcast i8** %[[V0]] to i32*
+// ARM64: %[[V3:.*]] = bitcast i8** %[[V1]] to i32*
+// ARM64: %[[V4:.*]] = load i32, i32* %[[V3]], align 8
+// ARM64: store i32 %[[V4]], i32* %[[V2]], align 8
+// ARM64: %[[V5:.*]] = bitcast i8** %[[V0]] to i8*
+// ARM64: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 8
+// ARM64: %[[V7:.*]] = bitcast i8* %[[V6]] to i8**
+// ARM64: %[[V8:.*]] = bitcast i8** %[[V1]] to i8*
+// ARM64: %[[V9:.*]] = getelementptr inbounds i8, i8* %[[V8]], i64 8
+// ARM64: %[[V10:.*]] = bitcast i8* %[[V9]] to i8**
+// ARM64: %[[V11:.*]] = call i8* @objc_loadWeakRetained(i8** %[[V10]])
+// ARM64: %[[V12:.*]] = call i8* @objc_storeWeak(i8** %[[V7]], i8* %[[V11]])
+// ARM64: call void @objc_destroyWeak(i8** %[[V10]])
+// ARM64: call void @objc_release(i8* %[[V11]])
+
+void test_move_assignment_Weak(Weak *p) {
+ *p = getWeak();
+}
+
+// COMMON: define void @test_parameter_Weak(%[[STRUCT_WEAK]]* %[[A:.*]])
+// COMMON: %[[V0:.*]] = bitcast %[[STRUCT_WEAK]]* %[[A]] to i8**
+// COMMON: call void @__destructor_{{.*}}(i8** %[[V0]])
+
+void test_parameter_Weak(Weak a) {
+}
+
+// COMMON: define void @test_argument_Weak(%[[STRUCT_WEAK]]* %[[A:.*]])
+// COMMON: %[[A_ADDR:.*]] = alloca %[[STRUCT_WEAK]]*
+// COMMON: %[[AGG_TMP:.*]] = alloca %[[STRUCT_WEAK]]
+// COMMON: store %[[STRUCT_WEAK]]* %[[A]], %[[STRUCT_WEAK]]** %[[A_ADDR]]
+// COMMON: %[[V0:.*]] = load %[[STRUCT_WEAK]]*, %[[STRUCT_WEAK]]** %[[A_ADDR]]
+// COMMON: %[[V1:.*]] = bitcast %[[STRUCT_WEAK]]* %[[AGG_TMP]] to i8**
+// COMMON: %[[V2:.*]] = bitcast %[[STRUCT_WEAK]]* %[[V0]] to i8**
+// COMMON: call void @__copy_constructor_{{.*}}(i8** %[[V1]], i8** %[[V2]])
+// COMMON: call void @calleeWeak(%[[STRUCT_WEAK]]* %[[AGG_TMP]])
+// COMMON-NEXT: ret
+
+void test_argument_Weak(Weak *a) {
+ calleeWeak(*a);
+}
+
+// COMMON: define void @test_return_Weak(%[[STRUCT_WEAK]]* noalias sret %[[AGG_RESULT:.*]], %[[STRUCT_WEAK]]* %[[A:.*]])
+// COMMON: %[[A_ADDR:.*]] = alloca %[[STRUCT_WEAK]]*
+// COMMON: store %[[STRUCT_WEAK]]* %[[A]], %[[STRUCT_WEAK]]** %[[A_ADDR]]
+// COMMON: %[[V0:.*]] = load %[[STRUCT_WEAK]]*, %[[STRUCT_WEAK]]** %[[A_ADDR]]
+// COMMON: %[[V1:.*]] = bitcast %[[STRUCT_WEAK]]* %[[AGG_RESULT]] to i8**
+// COMMON: %[[V2:.*]] = bitcast %[[STRUCT_WEAK]]* %[[V0]] to i8**
+// COMMON: call void @__copy_constructor_{{.*}}(i8** %[[V1]], i8** %[[V2]])
+// COMMON: ret void
+
+Weak test_return_Weak(Weak *a) {
+ return *a;
+}
diff --git a/test/CodeGenObjCXX/arc-blocks.mm b/test/CodeGenObjCXX/arc-blocks.mm
index 1e439578e8e9..3a75576681d8 100644
--- a/test/CodeGenObjCXX/arc-blocks.mm
+++ b/test/CodeGenObjCXX/arc-blocks.mm
@@ -1,6 +1,9 @@
-// RUN: %clang_cc1 -std=gnu++98 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -o - %s | FileCheck %s
+// RUN: %clang_cc1 -std=gnu++98 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -fexceptions -fobjc-arc-exceptions -o - %s | FileCheck -check-prefix CHECK %s
+// RUN: %clang_cc1 -std=gnu++98 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -fexceptions -fobjc-arc-exceptions -O1 -o - %s | FileCheck -check-prefix CHECK-O1 %s
// CHECK: [[A:.*]] = type { i64, [10 x i8*] }
+// CHECK: %[[STRUCT_TEST1_S0:.*]] = type { i32 }
+// CHECK: %[[STRUCT_BLOCK_DESCRIPTOR:.*]] = type { i64, i64 }
// CHECK: [[LAYOUT0:@.*]] = private unnamed_addr constant [3 x i8] c" 9\00"
@@ -47,3 +50,133 @@ namespace test0 {
// CHECK-NEXT: call void @_ZN5test01AD1Ev([[A]]* [[T1]])
// CHECK-NEXT: ret void
}
+
+namespace test1 {
+
+// Check that copy/dispose helper functions are exception safe.
+
+// CHECK-LABEL: define internal void @__copy_helper_block_(
+// CHECK: %[[BLOCK_SOURCE:.*]] = bitcast i8* %{{.*}} to <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>*
+// CHECK: %[[BLOCK_DEST:.*]] = bitcast i8* %{{.*}} to <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>*
+
+// CHECK: %[[V4:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK_SOURCE]], i32 0, i32 6
+// CHECK: %[[V5:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK_DEST]], i32 0, i32 6
+// CHECK: %[[BLOCKCOPY_SRC:.*]] = load i8*, i8** %[[V4]], align 8
+// CHECK: %[[V6:.*]] = bitcast i8** %[[V5]] to i8*
+// CHECK: call void @_Block_object_assign(i8* %[[V6]], i8* %[[BLOCKCOPY_SRC]], i32 8)
+
+// CHECK: %[[V7:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK_SOURCE]], i32 0, i32 7
+// CHECK: %[[V8:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK_DEST]], i32 0, i32 7
+// CHECK: call void @objc_copyWeak(i8** %[[V8]], i8** %[[V7]])
+
+// CHECK: %[[V9:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK_SOURCE]], i32 0, i32 5
+// CHECK: %[[V10:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK_DEST]], i32 0, i32 5
+// CHECK: %[[BLOCKCOPY_SRC2:.*]] = load i8*, i8** %[[V9]], align 8
+// CHECK: store i8* null, i8** %[[V10]], align 8
+// CHECK: call void @objc_storeStrong(i8** %[[V10]], i8* %[[BLOCKCOPY_SRC2]])
+
+// CHECK: %[[V11:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK_SOURCE]], i32 0, i32 8
+// CHECK: %[[V12:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK_DEST]], i32 0, i32 8
+// CHECK: invoke void @_ZN5test12S0C1ERKS0_(%[[STRUCT_TEST1_S0]]* %[[V12]], %[[STRUCT_TEST1_S0]]* dereferenceable(4) %[[V11]])
+// CHECK: to label %[[INVOKE_CONT:.*]] unwind label %[[LPAD:.*]]
+
+// CHECK: [[INVOKE_CONT]]:
+// CHECK: %[[V13:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK_SOURCE]], i32 0, i32 9
+// CHECK: %[[V14:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK_DEST]], i32 0, i32 9
+// CHECK: invoke void @_ZN5test12S0C1ERKS0_(%[[STRUCT_TEST1_S0]]* %[[V14]], %[[STRUCT_TEST1_S0]]* dereferenceable(4) %[[V13]])
+// CHECK: to label %[[INVOKE_CONT4:.*]] unwind label %[[LPAD3:.*]]
+
+// CHECK: [[INVOKE_CONT4]]:
+// CHECK: ret void
+
+// CHECK: [[LPAD]]:
+// CHECK: br label %[[EHCLEANUP:.*]]
+
+// CHECK: [[LPAD3]]:
+// CHECK: invoke void @_ZN5test12S0D1Ev(%[[STRUCT_TEST1_S0]]* %[[V12]])
+// CHECK: to label %[[INVOKE_CONT5:.*]] unwind label %[[TERMINATE_LPAD:.*]]
+
+// CHECK: [[INVOKE_CONT5]]:
+// CHECK: br label %[[EHCLEANUP]]
+
+// CHECK: [[EHCLEANUP]]:
+// CHECK: call void @objc_storeStrong(i8** %[[V10]], i8* null)
+// CHECK: call void @objc_destroyWeak(i8** %[[V8]])
+// CHECK: %[[V21:.*]] = load i8*, i8** %[[V5]], align 8
+// CHECK: call void @_Block_object_dispose(i8* %[[V21]], i32 8)
+// CHECK: br label %[[EH_RESUME:.*]]
+
+// CHECK: [[EH_RESUME]]:
+// CHECK: resume { i8*, i32 }
+
+// CHECK: [[TERMINATE_LPAD]]:
+// CHECK: call void @__clang_call_terminate(
+
+// CHECK-O1-LABEL: define internal void @__copy_helper_block_(
+// CHECK-O1: tail call void @objc_release({{.*}}) {{.*}} !clang.imprecise_release
+
+// CHECK: define internal void @__destroy_helper_block_(
+// CHECK: %[[BLOCK:.*]] = bitcast i8* %{{.*}} to <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>*
+// CHECK: %[[V2:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK]], i32 0, i32 6
+// CHECK: %[[V3:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK]], i32 0, i32 7
+// CHECK: %[[V4:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK]], i32 0, i32 5
+// CHECK: %[[V5:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK]], i32 0, i32 8
+// CHECK: %[[V6:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK]], i32 0, i32 9
+// CHECK: invoke void @_ZN5test12S0D1Ev(%[[STRUCT_TEST1_S0]]* %[[V6]])
+// CHECK: to label %[[INVOKE_CONT:.*]] unwind label %[[LPAD:.*]]
+
+// CHECK: [[INVOKE_CONT]]:
+// CHECK: invoke void @_ZN5test12S0D1Ev(%[[STRUCT_TEST1_S0]]* %[[V5]])
+// CHECK: to label %[[INVOKE_CONT2:.*]] unwind label %[[LPAD1:.*]]
+
+// CHECK: [[INVOKE_CONT2]]:
+// CHECK: call void @objc_storeStrong(i8** %[[V4]], i8* null)
+// CHECK: call void @objc_destroyWeak(i8** %[[V3]])
+// CHECK: %[[V7:.*]] = load i8*, i8** %[[V2]], align 8
+// CHECK: call void @_Block_object_dispose(i8* %[[V7]], i32 8)
+// CHECK: ret void
+
+// CHECK: [[LPAD]]:
+// CHECK: invoke void @_ZN5test12S0D1Ev(%[[STRUCT_TEST1_S0]]* %[[V5]])
+// CHECK: to label %[[INVOKE_CONT3:.*]] unwind label %[[TERMINATE_LPAD]]
+
+// CHECK: [[LPAD1]]
+// CHECK: br label %[[EHCLEANUP:.*]]
+
+// CHECK: [[INVOKE_CONT3]]:
+// CHECK: br label %[[EHCLEANUP]]
+
+// CHECK: [[EHCLEANUP]]:
+// CHECK: call void @objc_storeStrong(i8** %[[V4]], i8* null)
+// CHECK: call void @objc_destroyWeak(i8** %[[V3]])
+// CHECK: %[[V14:.*]] = load i8*, i8** %[[V2]], align 8
+// CHECK: call void @_Block_object_dispose(i8* %[[V14]], i32 8)
+// CHECK: br label %[[EH_RESUME]]
+
+// CHECK: [[EH_RESUME]]:
+// CHECK: resume { i8*, i32 }
+
+// CHECK: [[TERMINATE_LPAD]]:
+// CHECK: call void @__clang_call_terminate(
+
+// CHECK-O1-LABEL: define internal void @__destroy_helper_block_(
+// CHECK-O1: tail call void @objc_release({{.*}}) {{.*}} !clang.imprecise_release
+// CHECK-O1: tail call void @objc_release({{.*}}) {{.*}} !clang.imprecise_release
+
+struct S0 {
+ S0();
+ S0(const S0 &);
+ ~S0();
+ int f0;
+};
+
+id getObj();
+
+void foo1() {
+ __block id t0 = getObj();
+ __weak id t1 = getObj();
+ id t2 = getObj();
+ S0 t3, t4;
+ ^{ (void)t0; (void)t1; (void)t2; (void)t3; (void)t4; };
+}
+}
diff --git a/test/CodeGenObjCXX/arc-cxx11-init-list.mm b/test/CodeGenObjCXX/arc-cxx11-init-list.mm
index c3723c619ab0..af607654e159 100644
--- a/test/CodeGenObjCXX/arc-cxx11-init-list.mm
+++ b/test/CodeGenObjCXX/arc-cxx11-init-list.mm
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple armv7-ios5.0 -std=c++11 -fobjc-arc -Os -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple armv7-ios5.0 -std=c++11 -fmerge-all-constants -fobjc-arc -Os -emit-llvm -o - %s | FileCheck %s
// CHECK: @[[STR0:.*]] = private unnamed_addr constant [5 x i8] c"str0\00", section "__TEXT,__cstring,cstring_literals"
// CHECK: @[[UNNAMED_CFSTRING0:.*]] = private global %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @[[STR0]], i32 0, i32 0), i32 4 }, section "__DATA,__cfstring"
diff --git a/test/CodeGenObjCXX/arc-exceptions.mm b/test/CodeGenObjCXX/arc-exceptions.mm
index 0ae306943186..3d5046135078 100644
--- a/test/CodeGenObjCXX/arc-exceptions.mm
+++ b/test/CodeGenObjCXX/arc-exceptions.mm
@@ -101,7 +101,7 @@ namespace test4 {
// Construct array.
// CHECK-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[A]], [[A]]* [[THIS]], i32 0, i32 1
// CHECK-NEXT: [[T0:%.*]] = bitcast [2 x [3 x i8*]]* [[ARRAY]] to i8*
- // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 48, i32 8, i1 false)
+ // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 8 [[T0]], i8 0, i64 48, i1 false)
// throw 0;
// CHECK: invoke void @__cxa_throw(
// Landing pad from throw site:
diff --git a/test/CodeGenObjCXX/arc-forwarded-lambda-call.mm b/test/CodeGenObjCXX/arc-forwarded-lambda-call.mm
index 35abe19183bf..0a575c7697cb 100644
--- a/test/CodeGenObjCXX/arc-forwarded-lambda-call.mm
+++ b/test/CodeGenObjCXX/arc-forwarded-lambda-call.mm
@@ -10,6 +10,17 @@ void test0(id x) {
// CHECK-NEXT: ret i8* [[T2]]
}
+// Check that the delegating block invoke function doesn't destruct the Weak
+// object that is passed.
+
+// CHECK-LABEL: define internal void @___Z8testWeakv_block_invoke(
+// CHECK: call void @"_ZZ8testWeakvENK3$_2clE4Weak"(
+// CHECK-NEXT: ret void
+
+// CHECK-LABEL: define internal void @"_ZZ8testWeakvENK3$_2clE4Weak"(
+// CHECK: call void @_ZN4WeakD1Ev(
+// CHECK-NEXT: ret void
+
id test1_rv;
void test1() {
@@ -21,3 +32,12 @@ void test1() {
// CHECK-NEXT: [[T2:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[T1]])
// CHECK-NEXT: ret i8* [[T2]]
}
+
+struct Weak {
+ __weak id x;
+};
+
+void testWeak() {
+ extern void testWeak_helper(void (^)(Weak));
+ testWeak_helper([](Weak){});
+}
diff --git a/test/CodeGenObjCXX/arc-marker-funclet.mm b/test/CodeGenObjCXX/arc-marker-funclet.mm
new file mode 100644
index 000000000000..900c2788daed
--- /dev/null
+++ b/test/CodeGenObjCXX/arc-marker-funclet.mm
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fobjc-runtime=ios-6.0 -fobjc-arc \
+// RUN: -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck %s
+
+id f();
+void g() {
+ try {
+ f();
+ } catch (...) {
+ f();
+ }
+}
+
+// CHECK: call i8* @"?f@@YAPAUobjc_object@@XZ"() [ "funclet"(token %1) ]
+// CHECK-NEXT: call void asm sideeffect "movl{{.*}}%ebp, %ebp{{.*}}", ""() [ "funclet"(token %1) ]
+
+// The corresponding f() call was invoked from the entry basic block.
+// CHECK: call void asm sideeffect "movl{{.*}}%ebp, %ebp{{.*}}", ""(){{$}}
diff --git a/test/CodeGenObjCXX/arc-special-member-functions.mm b/test/CodeGenObjCXX/arc-special-member-functions.mm
index af161ddc5ad5..d620187d7017 100644
--- a/test/CodeGenObjCXX/arc-special-member-functions.mm
+++ b/test/CodeGenObjCXX/arc-special-member-functions.mm
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fobjc-arc -fblocks -triple x86_64-apple-darwin10.0.0 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -fobjc-arc -fblocks -triple x86_64-apple-darwin10.0.0 -fobjc-runtime-has-weak -emit-llvm -o - %s | FileCheck %s
struct ObjCMember {
id member;
@@ -12,6 +12,59 @@ struct ObjCBlockMember {
int (^bp)(int);
};
+// CHECK: %[[STRUCT_CONTAINSWEAK:.*]] = type { %[[STRUCT_WEAK:.*]] }
+// CHECK: %[[STRUCT_WEAK]] = type { i8* }
+
+// The Weak object that is passed is destructed in this constructor.
+
+// CHECK: define void @_ZN12ContainsWeakC2E4Weak(
+// CHECK: call void @_ZN4WeakC1ERKS_(
+// CHECK: call void @_ZN4WeakD1Ev(
+
+// Check that the Weak object passed to this constructor is not destructed after
+// the delegate constructor is called.
+
+// CHECK: define void @_ZN12ContainsWeakC1E4Weak(
+// CHECK: call void @_ZN12ContainsWeakC2E4Weak(
+// CHECK-NEXT: ret void
+
+struct Weak {
+ Weak(id);
+ __weak id x;
+};
+
+struct ContainsWeak {
+ ContainsWeak(Weak);
+ Weak w;
+};
+
+ContainsWeak::ContainsWeak(Weak a) : w(a) {}
+
+// The Weak object that is passed is destructed in this constructor.
+
+// CHECK: define void @_ZN4BaseC2E4Weak(
+// CHECK: call void @_ZN4WeakD1Ev(
+// CHECK: ret void
+
+// Check that the Weak object passed to this constructor is not destructed after
+// the delegate constructor is called.
+
+// CHECK: define linkonce_odr void @_ZN7DerivedCI14BaseE4Weak(
+// CHECK: call void @_ZN7DerivedCI24BaseE4Weak(
+// CHECK-NEXT: ret void
+
+struct Base {
+ Base(Weak);
+};
+
+Base::Base(Weak a) {}
+
+struct Derived : Base {
+ using Base::Base;
+};
+
+Derived d(Weak(0));
+
// CHECK-LABEL: define void @_Z42test_ObjCMember_default_construct_destructv(
void test_ObjCMember_default_construct_destruct() {
// CHECK: call void @_ZN10ObjCMemberC1Ev
@@ -31,6 +84,8 @@ void test_ObjCMember_copy_construct_destruct(ObjCMember m1) {
void test_ObjCMember_copy_assign(ObjCMember m1, ObjCMember m2) {
// CHECK: {{call.*_ZN10ObjCMemberaSERKS_}}
m1 = m2;
+ // CHECK-NEXT: call void @_ZN10ObjCMemberD1Ev(
+ // CHECK-NEXT: call void @_ZN10ObjCMemberD1Ev(
// CHECK-NEXT: ret void
}
@@ -58,6 +113,8 @@ void test_ObjCArrayMember_copy_construct_destruct(ObjCArrayMember m1) {
void test_ObjCArrayMember_copy_assign(ObjCArrayMember m1, ObjCArrayMember m2) {
// CHECK: {{call.*@_ZN15ObjCArrayMemberaSERKS_}}
m1 = m2;
+ // CHECK-NEXT: call void @_ZN15ObjCArrayMemberD1Ev(
+ // CHECK-NEXT: call void @_ZN15ObjCArrayMemberD1Ev(
// CHECK-NEXT: ret void
}
@@ -79,7 +136,8 @@ void test_ObjCBlockMember_default_construct_destruct() {
void test_ObjCBlockMember_copy_construct_destruct(ObjCBlockMember m1) {
// CHECK: call void @_ZN15ObjCBlockMemberC1ERKS_
ObjCBlockMember m2 = m1;
- // CHECK-NEXT: call void @_ZN15ObjCBlockMemberD1Ev
+ // CHECK-NEXT: call void @_ZN15ObjCBlockMemberD1Ev(
+ // CHECK-NEXT: call void @_ZN15ObjCBlockMemberD1Ev(
// CHECK-NEXT: ret void
}
@@ -87,6 +145,8 @@ void test_ObjCBlockMember_copy_construct_destruct(ObjCBlockMember m1) {
void test_ObjCBlockMember_copy_assign(ObjCBlockMember m1, ObjCBlockMember m2) {
// CHECK: {{call.*_ZN15ObjCBlockMemberaSERKS_}}
m1 = m2;
+ // CHECK-NEXT: call void @_ZN15ObjCBlockMemberD1Ev(
+ // CHECK-NEXT: call void @_ZN15ObjCBlockMemberD1Ev(
// CHECK-NEXT: ret void
}
@@ -104,6 +164,13 @@ void test_ObjCBlockMember_copy_assign(ObjCBlockMember m1, ObjCBlockMember m2) {
// CHECK-NEXT: call void @objc_release(i8* [[T7]])
// CHECK-NEXT: ret
+// Check that the Weak object passed to this constructor is not destructed after
+// the delegate constructor is called.
+
+// CHECK: define linkonce_odr void @_ZN7DerivedCI24BaseE4Weak(
+// CHECK: call void @_ZN4BaseC2E4Weak(
+// CHECK-NEXT: ret void
+
// Implicitly-generated default constructor for ObjCMember
// CHECK-LABEL: define linkonce_odr void @_ZN10ObjCMemberC2Ev
// CHECK-NOT: objc_release
diff --git a/test/CodeGenObjCXX/debug-info-line.mm b/test/CodeGenObjCXX/debug-info-line.mm
index 98ec2ce77c37..7cdb4d20fba0 100644
--- a/test/CodeGenObjCXX/debug-info-line.mm
+++ b/test/CodeGenObjCXX/debug-info-line.mm
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -debug-info-kind=line-tables-only -fblocks -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-gnu -fcxx-exceptions -fexceptions -debug-info-kind=line-tables-only -fblocks -emit-llvm %s -o - | FileCheck %s
void fn();
diff --git a/test/CodeGenObjCXX/instantiate-return.mm b/test/CodeGenObjCXX/instantiate-return.mm
new file mode 100644
index 000000000000..fe59602b395d
--- /dev/null
+++ b/test/CodeGenObjCXX/instantiate-return.mm
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -std=c++11 -o - %s | FileCheck %s
+
+template <class T>
+struct TemplateClass {
+ int a = 0;
+};
+
+struct S0;
+
+@interface C1
+- (TemplateClass<S0>)m1;
+@end
+
+// This code used to assert in CodeGen because the return type TemplateClass<S0>
+// wasn't instantiated.
+
+// CHECK: define internal i32 @"\01-[C1 m1]"(
+
+@implementation C1
+- (TemplateClass<S0>)m1 {
+}
+@end
diff --git a/test/CodeGenObjCXX/lambda-expressions.mm b/test/CodeGenObjCXX/lambda-expressions.mm
index c8247e2e0a26..f60655c61b18 100644
--- a/test/CodeGenObjCXX/lambda-expressions.mm
+++ b/test/CodeGenObjCXX/lambda-expressions.mm
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -emit-llvm -o - %s -fexceptions -std=c++11 -fblocks -fobjc-arc | FileCheck -check-prefix=ARC %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -emit-llvm -o - %s -fexceptions -std=c++11 -fblocks -fobjc-arc -fobjc-runtime-has-weak -DWEAK_SUPPORTED | FileCheck -check-prefix=ARC %s
// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -emit-llvm -o - %s -fexceptions -std=c++11 -fblocks | FileCheck -check-prefix=MRC %s
typedef int (^fp)();
@@ -138,5 +138,31 @@ namespace BlockInLambda {
}
@end
+// Check that the delegating invoke function doesn't destruct the Weak object
+// that is passed.
+
+// ARC-LABEL: define internal void @"_ZZN14LambdaDelegate4testEvEN3$_58__invokeENS_4WeakE"(
+// ARC: call void @"_ZZN14LambdaDelegate4testEvENK3$_5clENS_4WeakE"(
+// ARC-NEXT: ret void
+
+// ARC-LABEL: define internal void @"_ZZN14LambdaDelegate4testEvENK3$_5clENS_4WeakE"(
+// ARC: call void @_ZN14LambdaDelegate4WeakD1Ev(
+
+#ifdef WEAK_SUPPORTED
+
+namespace LambdaDelegate {
+
+struct Weak {
+ __weak id x;
+};
+
+void test() {
+ void (*p)(Weak) = [](Weak a) { };
+}
+
+};
+
+#endif
+
// ARC: attributes [[NUW]] = { noinline nounwind{{.*}} }
// MRC: attributes [[NUW]] = { noinline nounwind{{.*}} }
diff --git a/test/CodeGenObjCXX/literals.mm b/test/CodeGenObjCXX/literals.mm
index 6a112312bd88..a42070b00c30 100644
--- a/test/CodeGenObjCXX/literals.mm
+++ b/test/CodeGenObjCXX/literals.mm
@@ -18,19 +18,25 @@ struct Y {
void test_array() {
// CHECK: [[ARR:%[a-zA-Z0-9.]+]] = alloca i8*
// CHECK: [[OBJECTS:%[a-zA-Z0-9.]+]] = alloca [2 x i8*]
+ // CHECK: [[TMPX:%[a-zA-Z0-9.]+]] = alloca %
+ // CHECK: [[TMPY:%[a-zA-Z0-9.]+]] = alloca %
// Initializing first element
// CHECK: [[PTR1:%.*]] = bitcast i8** [[ARR]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PTR1]])
// CHECK: [[ELEMENT0:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[OBJECTS]], i64 0, i64 0
- // CHECK-NEXT: call void @_ZN1XC1Ev
+ // CHECK-NEXT: [[TMP_CAST:%.*]] = bitcast {{.*}} [[TMPX]] to i8*
+ // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 1, i8* [[TMP_CAST]])
+ // CHECK-NEXT: call void @_ZN1XC1Ev({{.*}} [[TMPX]])
// CHECK-NEXT: [[OBJECT0:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1XcvP11objc_objectEv
// CHECK: [[RET0:%[a-zA-Z0-9.]+]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[OBJECT0]])
// CHECK: store i8* [[RET0]], i8** [[ELEMENT0]]
// Initializing the second element
// CHECK: [[ELEMENT1:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[OBJECTS]], i64 0, i64 1
- // CHECK-NEXT: invoke void @_ZN1YC1Ev
+ // CHECK-NEXT: [[TMP_CAST:%.*]] = bitcast {{.*}} [[TMPY]] to i8*
+ // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 1, i8* [[TMP_CAST]])
+ // CHECK-NEXT: invoke void @_ZN1YC1Ev({{.*}} [[TMPY]])
// CHECK: [[OBJECT1:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1YcvP11objc_objectEv
// CHECK: [[RET1:%[a-zA-Z0-9.]+]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[OBJECT1]])
// CHECK: store i8* [[RET1]], i8** [[ELEMENT1]]
@@ -75,14 +81,14 @@ void test_array_instantiation() {
// CHECK: [[PTR1:%.*]] = bitcast i8** [[ARR]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PTR1]])
// CHECK: [[ELEMENT0:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[OBJECTS]], i64 0, i64 0
- // CHECK-NEXT: call void @_ZN1XC1Ev
+ // CHECK: call void @_ZN1XC1Ev
// CHECK-NEXT: [[OBJECT0:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1XcvP11objc_objectEv
// CHECK: [[RET0:%[a-zA-Z0-9.]+]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[OBJECT0]])
// CHECK: store i8* [[RET0]], i8** [[ELEMENT0]]
// Initializing the second element
// CHECK: [[ELEMENT1:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[OBJECTS]], i64 0, i64 1
- // CHECK-NEXT: invoke void @_ZN1YC1Ev
+ // CHECK: invoke void @_ZN1YC1Ev
// CHECK: [[OBJECT1:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1YcvP11objc_objectEv
// CHECK: [[RET1:%[a-zA-Z0-9.]+]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[OBJECT1]])
// CHECK: store i8* [[RET1]], i8** [[ELEMENT1]]
diff --git a/test/CodeGenObjCXX/microsoft-abi-arc-param-order.mm b/test/CodeGenObjCXX/microsoft-abi-arc-param-order.mm
index cb71bcf0aad3..910a7db73404 100644
--- a/test/CodeGenObjCXX/microsoft-abi-arc-param-order.mm
+++ b/test/CodeGenObjCXX/microsoft-abi-arc-param-order.mm
@@ -9,12 +9,12 @@ struct A {
// Verify that we destruct things from left to right in the MS C++ ABI: a, b, c, d.
//
-// CHECK-LABEL: define void @"\01?test_arc_order@@YAXUA@@PAUobjc_object@@01@Z"
+// CHECK-LABEL: define dso_local void @"?test_arc_order@@YAXUA@@PAUobjc_object@@01@Z"
// CHECK: (<{ %struct.A, i8*, %struct.A, i8* }>* inalloca)
void test_arc_order(A a, id __attribute__((ns_consumed)) b , A c, id __attribute__((ns_consumed)) d) {
- // CHECK: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %{{.*}})
+ // CHECK: call x86_thiscallcc void @"??1A@@QAE@XZ"(%struct.A* %{{.*}})
// CHECK: call void @objc_storeStrong(i8** %{{.*}}, i8* null)
- // CHECK: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %{{.*}})
+ // CHECK: call x86_thiscallcc void @"??1A@@QAE@XZ"(%struct.A* %{{.*}})
// CHECK: call void @objc_storeStrong(i8** %{{.*}}, i8* null)
// CHECK: ret void
}
diff --git a/test/CodeGenObjCXX/msabi-objc-extensions.mm b/test/CodeGenObjCXX/msabi-objc-extensions.mm
new file mode 100644
index 000000000000..2f724a985f33
--- /dev/null
+++ b/test/CodeGenObjCXX/msabi-objc-extensions.mm
@@ -0,0 +1,66 @@
+// RUN: %clang_cc1 -triple thumbv7-windows-msvc -fobjc-runtime=ios-6.0 -fobjc-arc -o - -emit-llvm %s | FileCheck %s
+
+@protocol P;
+@protocol Q;
+
+@class I;
+
+void f(id<P>, id, id<P>, id) {}
+// CHECK-LABEL: "?f@@YAXPAU?$objc_object@U?$Protocol@UP@@@__ObjC@@@@PAUobjc_object@@01@Z"
+
+void f(id, id<P>, id<P>, id) {}
+// CHECK-LABEL: "?f@@YAXPAUobjc_object@@PAU?$objc_object@U?$Protocol@UP@@@__ObjC@@@@10@Z"
+
+void f(id<P>, id<P>) {}
+// CHECK-LABEL: "?f@@YAXPAU?$objc_object@U?$Protocol@UP@@@__ObjC@@@@0@Z"
+
+void f(id<P>) {}
+// CHECK-LABEL: "?f@@YAXPAU?$objc_object@U?$Protocol@UP@@@__ObjC@@@@@Z"
+
+void f(id<P, Q>) {}
+// CHECK-LABEL: "?f@@YAXPAU?$objc_object@U?$Protocol@UP@@@__ObjC@@U?$Protocol@UQ@@@2@@@@Z"
+
+void f(Class<P>) {}
+// CHECK-LABEL: "?f@@YAXPAU?$objc_class@U?$Protocol@UP@@@__ObjC@@@@@Z"
+
+void f(Class<P, Q>) {}
+// CHECK-LABEL: "?f@@YAXPAU?$objc_class@U?$Protocol@UP@@@__ObjC@@U?$Protocol@UQ@@@2@@@@Z"
+
+void f(I<P> *) {}
+// CHECK-LABEL: "?f@@YAXPAU?$I@U?$Protocol@UP@@@__ObjC@@@@@Z"
+
+void f(I<P, Q> *) {}
+// CHECK-LABEL: "?f@@YAXPAU?$I@U?$Protocol@UP@@@__ObjC@@U?$Protocol@UQ@@@2@@@@Z"
+
+template <typename>
+struct S {};
+
+void f(S<__unsafe_unretained id>) {}
+// CHECK-LABEL: "?f@@YAXU?$S@PAUobjc_object@@@@@Z"
+
+void f(S<__autoreleasing id>) {}
+// CHECK-LABEL: "?f@@YAXU?$S@U?$Autoreleasing@PAUobjc_object@@@__ObjC@@@@@Z"
+
+void f(S<__strong id>) {}
+// CHECK-LABEL: "?f@@YAXU?$S@U?$Strong@PAUobjc_object@@@__ObjC@@@@@Z"
+
+void f(S<__weak id>) {}
+// CHECK-LABEL: "?f@@YAXU?$S@U?$Weak@PAUobjc_object@@@__ObjC@@@@@Z"
+
+void w(__weak id) {}
+// CHECK-LABEL: "?w@@YAXPAUobjc_object@@@Z"
+
+void s(__strong id) {}
+// CHECK-LABEL: "?s@@YAXPAUobjc_object@@@Z"
+
+void a(__autoreleasing id) {}
+// CHECK-LABEL: "?a@@YAXPAUobjc_object@@@Z"
+
+void u(__unsafe_unretained id) {}
+// CHECK-LABEL: "?u@@YAXPAUobjc_object@@@Z"
+
+S<__autoreleasing id> g() { return S<__autoreleasing id>(); }
+// CHECK-LABEL: "?g@@YA?AU?$S@U?$Autoreleasing@PAUobjc_object@@@__ObjC@@@@XZ"
+
+__autoreleasing id h() { return nullptr; }
+// CHECK-LABEL: "?h@@YAPAUobjc_object@@XZ"
diff --git a/test/CodeGenObjCXX/msabi-objc-types.mm b/test/CodeGenObjCXX/msabi-objc-types.mm
index 013a9c84daee..192dd4c23ffa 100644
--- a/test/CodeGenObjCXX/msabi-objc-types.mm
+++ b/test/CodeGenObjCXX/msabi-objc-types.mm
@@ -3,120 +3,190 @@
@class I;
id kid;
-// CHECK: @"\01?kid@@3PAUobjc_object@@A" = global
+// CHECK: @"?kid@@3PAUobjc_object@@A" = dso_local global
Class klass;
-// CHECK: @"\01?klass@@3PAUobjc_class@@A" = global
+// CHECK: @"?klass@@3PAUobjc_class@@A" = dso_local global
I *kI;
-// CHECK: @"\01?kI@@3PAUI@@A" = global
+// CHECK: @"?kI@@3PAUI@@A" = dso_local global
void f(I *) {}
-// CHECK-LABEL: "\01?f@@YAXPAUI@@@Z"
+// CHECK-LABEL: "?f@@YAXPAUI@@@Z"
void f(const I *) {}
-// CHECK-LABEL: "\01?f@@YAXPBUI@@@Z"
+// CHECK-LABEL: "?f@@YAXPBUI@@@Z"
void f(I &) {}
-// CHECK-LABEL: "\01?f@@YAXAAUI@@@Z"
+// CHECK-LABEL: "?f@@YAXAAUI@@@Z"
void f(const I &) {}
-// CHECK-LABEL: "\01?f@@YAXABUI@@@Z"
+// CHECK-LABEL: "?f@@YAXABUI@@@Z"
void f(const I &&) {}
-// CHECK-LABEL: "\01?f@@YAX$$QBUI@@@Z"
+// CHECK-LABEL: "?f@@YAX$$QBUI@@@Z"
void g(id) {}
-// CHECK-LABEL: "\01?g@@YAXPAUobjc_object@@@Z"
+// CHECK-LABEL: "?g@@YAXPAUobjc_object@@@Z"
void g(id &) {}
-// CHECK-LABEL: "\01?g@@YAXAAPAUobjc_object@@@Z"
+// CHECK-LABEL: "?g@@YAXAAPAUobjc_object@@@Z"
void g(const id &) {}
-// CHECK-LABEL: "\01?g@@YAXABPAUobjc_object@@@Z"
+// CHECK-LABEL: "?g@@YAXABQAUobjc_object@@@Z"
void g(id &&) {}
-// CHECK-LABEL: "\01?g@@YAX$$QAPAUobjc_object@@@Z"
+// CHECK-LABEL: "?g@@YAX$$QAPAUobjc_object@@@Z"
void h(Class) {}
-// CHECK-LABEL: "\01?h@@YAXPAUobjc_class@@@Z"
+// CHECK-LABEL: "?h@@YAXPAUobjc_class@@@Z"
void h(Class &) {}
-// CHECK-LABEL: "\01?h@@YAXAAPAUobjc_class@@@Z"
+// CHECK-LABEL: "?h@@YAXAAPAUobjc_class@@@Z"
void h(const Class &) {}
-// CHECK-LABEL: "\01?h@@YAXABPAUobjc_class@@@Z"
+// CHECK-LABEL: "?h@@YAXABQAUobjc_class@@@Z"
void h(Class &&) {}
-// CHECK-LABEL: "\01?h@@YAX$$QAPAUobjc_class@@@Z"
+// CHECK-LABEL: "?h@@YAX$$QAPAUobjc_class@@@Z"
I *i() { return nullptr; }
-// CHECK-LABEL: "\01?i@@YAPAUI@@XZ"
+// CHECK-LABEL: "?i@@YAPAUI@@XZ"
const I *j() { return nullptr; }
-// CHECK-LABEL: "\01?j@@YAPBUI@@XZ"
+// CHECK-LABEL: "?j@@YAPBUI@@XZ"
I &k() { return *kI; }
-// CHECK-LABEL: "\01?k@@YAAAUI@@XZ"
+// CHECK-LABEL: "?k@@YAAAUI@@XZ"
const I &l() { return *kI; }
-// CHECK-LABEL: "\01?l@@YAABUI@@XZ"
+// CHECK-LABEL: "?l@@YAABUI@@XZ"
+
+void m(const id) {}
+// CHECK-LABEL: "?m@@YAXQAUobjc_object@@@Z"
+
+void m(const I *) {}
+// CHECK-LABEL: "?m@@YAXPBUI@@@Z"
+
+void n(SEL) {}
+// CHECK-LABEL: "?n@@YAXPAUobjc_selector@@@Z"
+
+void n(SEL *) {}
+// CHECK-LABEL: "?n@@YAXPAPAUobjc_selector@@@Z"
+
+void n(const SEL *) {}
+// CHECK-LABEL: "?n@@YAXPBQAUobjc_selector@@@Z"
+
+void n(SEL &) {}
+// CHECK-LABEL: "?n@@YAXAAPAUobjc_selector@@@Z"
+
+void n(const SEL &) {}
+// CHECK-LABEL: "?n@@YAXABQAUobjc_selector@@@Z"
+
+void n(SEL &&) {}
+// CHECK-LABEL: "?n@@YAX$$QAPAUobjc_selector@@@Z"
struct __declspec(dllexport) s {
struct s &operator=(const struct s &) = delete;
void m(I *) {}
- // CHECK-LABEL: "\01?m@s@@QAAXPAUI@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAXPAUI@@@Z"
void m(const I *) {}
- // CHECK-LABEL: "\01?m@s@@QAAXPBUI@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAXPBUI@@@Z"
void m(I &) {}
- // CHECK-LABEL: "\01?m@s@@QAAXAAUI@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAXAAUI@@@Z"
void m(const I &) {}
- // CHECK-LABEL: "\01?m@s@@QAAXABUI@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAXABUI@@@Z"
void m(I &&) {}
- // CHECK-LABEL: "\01?m@s@@QAAX$$QAUI@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAX$$QAUI@@@Z"
void m(const I &&) {}
- // CHECK-LABEL: "\01?m@s@@QAAX$$QBUI@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAX$$QBUI@@@Z"
void m(id) {}
- // CHECK-LABEL: "\01?m@s@@QAAXPAUobjc_object@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAXPAUobjc_object@@@Z"
void m(id &) {}
- // CHECK-LABEL: "\01?m@s@@QAAXAAPAUobjc_object@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAXAAPAUobjc_object@@@Z"
void m(id &&) {}
- // CHECK-LABEL: "\01?m@s@@QAAX$$QAPAUobjc_object@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAX$$QAPAUobjc_object@@@Z"
void m(const id &) {}
- // CHECK-LABEL: "\01?m@s@@QAAXABPAUobjc_object@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAXABQAUobjc_object@@@Z"
void m(const id &&) {}
- // CHECK-LABEL: "\01?m@s@@QAAX$$QBPAUobjc_object@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAX$$QBQAUobjc_object@@@Z"
void m(Class *) {}
- // CHECK-LABEL: "\01?m@s@@QAAXPAPAUobjc_class@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAXPAPAUobjc_class@@@Z"
void m(const Class *) {}
- // CHECK-LABEL: "\01?m@s@@QAAXPBPAUobjc_class@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAXPBQAUobjc_class@@@Z"
void m(Class) {}
- // CHECK-LABEL: "\01?m@s@@QAAXPAUobjc_class@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAXPAUobjc_class@@@Z"
void m(Class &) {}
- // CHECK-LABEL: "\01?m@s@@QAAXAAPAUobjc_class@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAXAAPAUobjc_class@@@Z"
void m(const Class &) {}
- // CHECK-LABEL: "\01?m@s@@QAAXABPAUobjc_class@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAXABQAUobjc_class@@@Z"
void m(Class &&) {}
- // CHECK-LABEL: "\01?m@s@@QAAX$$QAPAUobjc_class@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAX$$QAPAUobjc_class@@@Z"
void m(const Class &&) {}
- // CHECK-LABEL: "\01?m@s@@QAAX$$QBPAUobjc_class@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAX$$QBQAUobjc_class@@@Z"
+
+ void m(SEL) {}
+ // CHECK-LABEL: "?m@s@@QAAXPAUobjc_selector@@@Z"
+
+ void m(SEL *) {}
+ // CHECK-LABEL: "?m@s@@QAAXPAPAUobjc_selector@@@Z"
+
+ void m(const SEL *) {}
+ // CHECK-LABEL: "?m@s@@QAAXPBQAUobjc_selector@@@Z"
+
+ void m(SEL &) {}
+ // CHECK-LABEL: "?m@s@@QAAXAAPAUobjc_selector@@@Z"
+
+ void m(const SEL &) {}
+ // CHECK-LABEL: "?m@s@@QAAXABQAUobjc_selector@@@Z"
+
+ void m(SEL &&) {}
+ // CHECK-LABEL: "?m@s@@QAAX$$QAPAUobjc_selector@@@Z"
+
+ void m(const SEL &&) {}
+ // CHECK-LABEL: "?m@s@@QAAX$$QBQAUobjc_selector@@@Z"
+};
+
+template <typename T>
+struct remove_pointer { typedef T type; };
+
+template <typename T>
+struct remove_pointer<T *> {
+ typedef T type;
};
+template <typename T>
+struct t {
+ t() {}
+};
+
+template struct t<id>;
+// CHECK-LABEL: "??0?$t@PAUobjc_object@@@@QAA@XZ"
+
+template struct t<remove_pointer<id>::type>;
+// CHECK-LABEL: "??0?$t@Uobjc_object@@@@QAA@XZ"
+
+template struct t<SEL>;
+// CHECK-LABEL: "??0?$t@PAUobjc_selector@@@@QAA@XZ"
+
+template struct t<remove_pointer<SEL>::type>;
+// CHECK-LABEL: "??0?$t@Uobjc_selector@@@@QAA@XZ"
+
diff --git a/test/CodeGenObjCXX/msabi-stret.mm b/test/CodeGenObjCXX/msabi-stret.mm
new file mode 100644
index 000000000000..765c23887bac
--- /dev/null
+++ b/test/CodeGenObjCXX/msabi-stret.mm
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fobjc-runtime=ios-6.0 -Os -S -emit-llvm -o - %s -mdisable-fp-elim | FileCheck %s
+
+struct S {
+ S() = default;
+ S(const S &) {}
+};
+
+@interface I
++ (S)m:(S)s;
+@end
+
+S f() {
+ return [I m:S()];
+}
+
+// CHECK: declare dllimport void @objc_msgSend_stret(i8*, i8*, ...)
+// CHECK-NOT: declare dllimport void @objc_msgSend(i8*, i8*, ...)
+
diff --git a/test/CodeGenObjCXX/objc-struct-cxx-abi.mm b/test/CodeGenObjCXX/objc-struct-cxx-abi.mm
new file mode 100644
index 000000000000..dd9b88b0234d
--- /dev/null
+++ b/test/CodeGenObjCXX/objc-struct-cxx-abi.mm
@@ -0,0 +1,180 @@
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fobjc-arc -fobjc-weak -fobjc-runtime-has-weak -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fobjc-arc -fobjc-weak -fobjc-runtime-has-weak -fclang-abi-compat=4.0 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fobjc-arc -fobjc-weak -fobjc-runtime-has-weak -emit-llvm -o - -DTRIVIALABI %s | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fobjc-arc -fobjc-weak -fobjc-runtime-has-weak -fclang-abi-compat=4.0 -emit-llvm -o - -DTRIVIALABI %s | FileCheck %s
+
+// Check that structs consisting solely of __strong or __weak pointer fields are
+// destructed in the callee function and structs consisting solely of __strong
+// pointer fields are passed directly.
+
+// CHECK: %[[STRUCT_STRONGWEAK:.*]] = type { i8*, i8* }
+// CHECK: %[[STRUCT_CONTAINSSTRONGWEAK:.*]] = type { %[[STRUCT_STRONGWEAK]] }
+// CHECK: %[[STRUCT_DERIVEDSTRONGWEAK:.*]] = type { %[[STRUCT_STRONGWEAK]] }
+// CHECK: %[[STRUCT_STRONG:.*]] = type { i8* }
+// CHECK: %[[STRUCT_S:.*]] = type { i8* }
+// CHECK: %[[STRUCT_CONTAINSNONTRIVIAL:.*]] = type { %{{.*}}, i8* }
+
+#ifdef TRIVIALABI
+struct __attribute__((trivial_abi)) StrongWeak {
+#else
+struct StrongWeak {
+#endif
+ id fstrong;
+ __weak id fweak;
+};
+
+#ifdef TRIVIALABI
+struct __attribute__((trivial_abi)) ContainsStrongWeak {
+#else
+struct ContainsStrongWeak {
+#endif
+ StrongWeak sw;
+};
+
+#ifdef TRIVIALABI
+struct __attribute__((trivial_abi)) DerivedStrongWeak : StrongWeak {
+#else
+struct DerivedStrongWeak : StrongWeak {
+#endif
+};
+
+#ifdef TRIVIALABI
+struct __attribute__((trivial_abi)) Strong {
+#else
+struct Strong {
+#endif
+ id fstrong;
+};
+
+template<class T>
+#ifdef TRIVIALABI
+struct __attribute__((trivial_abi)) S {
+#else
+struct S {
+#endif
+ T a;
+};
+
+struct NonTrivial {
+ NonTrivial();
+ NonTrivial(const NonTrivial &);
+ ~NonTrivial();
+ int *a;
+};
+
+// This struct is not passed directly nor destructed in the callee because f0
+// has type NonTrivial.
+struct ContainsNonTrivial {
+ NonTrivial f0;
+ id f1;
+};
+
+// CHECK: define void @_Z19testParamStrongWeak10StrongWeak(%[[STRUCT_STRONGWEAK]]* %{{.*}})
+// CHECK: call %struct.StrongWeak* @_ZN10StrongWeakD1Ev(
+// CHECK-NEXT: ret void
+
+void testParamStrongWeak(StrongWeak a) {
+}
+
+// CHECK: define void @_Z18testCallStrongWeakP10StrongWeak(%[[STRUCT_STRONGWEAK]]* %[[A:.*]])
+// CHECK: %[[A_ADDR:.*]] = alloca %[[STRUCT_STRONGWEAK]]*, align 8
+// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_STRONGWEAK]], align 8
+// CHECK: store %[[STRUCT_STRONGWEAK]]* %[[A]], %[[STRUCT_STRONGWEAK]]** %[[A_ADDR]], align 8
+// CHECK: %[[V0:.*]] = load %[[STRUCT_STRONGWEAK]]*, %[[STRUCT_STRONGWEAK]]** %[[A_ADDR]], align 8
+// CHECK: %[[CALL:.*]] = call %[[STRUCT_STRONGWEAK]]* @_ZN10StrongWeakC1ERKS_(%[[STRUCT_STRONGWEAK]]* %[[AGG_TMP]], %[[STRUCT_STRONGWEAK]]* dereferenceable(16) %[[V0]])
+// CHECK: call void @_Z19testParamStrongWeak10StrongWeak(%[[STRUCT_STRONGWEAK]]* %[[AGG_TMP]])
+// CHECK-NOT: call
+// CHECK: ret void
+
+void testCallStrongWeak(StrongWeak *a) {
+ testParamStrongWeak(*a);
+}
+
+// CHECK: define void @_Z20testReturnStrongWeakP10StrongWeak(%[[STRUCT_STRONGWEAK:.*]]* noalias sret %[[AGG_RESULT:.*]], %[[STRUCT_STRONGWEAK]]* %[[A:.*]])
+// CHECK: %[[A_ADDR:.*]] = alloca %[[STRUCT_STRONGWEAK]]*, align 8
+// CHECK: store %[[STRUCT_STRONGWEAK]]* %[[A]], %[[STRUCT_STRONGWEAK]]** %[[A_ADDR]], align 8
+// CHECK: %[[V0:.*]] = load %[[STRUCT_STRONGWEAK]]*, %[[STRUCT_STRONGWEAK]]** %[[A_ADDR]], align 8
+// CHECK: %[[CALL:.*]] = call %[[STRUCT_STRONGWEAK]]* @_ZN10StrongWeakC1ERKS_(%[[STRUCT_STRONGWEAK]]* %[[AGG_RESULT]], %[[STRUCT_STRONGWEAK]]* dereferenceable(16) %[[V0]])
+// CHECK: ret void
+
+StrongWeak testReturnStrongWeak(StrongWeak *a) {
+ return *a;
+}
+
+// CHECK: define void @_Z27testParamContainsStrongWeak18ContainsStrongWeak(%[[STRUCT_CONTAINSSTRONGWEAK]]* %[[A:.*]])
+// CHECK: call %[[STRUCT_CONTAINSSTRONGWEAK]]* @_ZN18ContainsStrongWeakD1Ev(%[[STRUCT_CONTAINSSTRONGWEAK]]* %[[A]])
+
+void testParamContainsStrongWeak(ContainsStrongWeak a) {
+}
+
+// CHECK: define void @_Z26testParamDerivedStrongWeak17DerivedStrongWeak(%[[STRUCT_DERIVEDSTRONGWEAK]]* %[[A:.*]])
+// CHECK: call %[[STRUCT_DERIVEDSTRONGWEAK]]* @_ZN17DerivedStrongWeakD1Ev(%[[STRUCT_DERIVEDSTRONGWEAK]]* %[[A]])
+
+void testParamDerivedStrongWeak(DerivedStrongWeak a) {
+}
+
+// CHECK: define void @_Z15testParamStrong6Strong(i64 %[[A_COERCE:.*]])
+// CHECK: %[[A:.*]] = alloca %[[STRUCT_STRONG]], align 8
+// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_STRONG]], %[[STRUCT_STRONG]]* %[[A]], i32 0, i32 0
+// CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[A_COERCE]] to i8*
+// CHECK: store i8* %[[COERCE_VAL_IP]], i8** %[[COERCE_DIVE]], align 8
+// CHECK: %[[CALL:.*]] = call %[[STRUCT_STRONG]]* @_ZN6StrongD1Ev(%[[STRUCT_STRONG]]* %[[A]])
+// CHECK: ret void
+
+// CHECK: define linkonce_odr %[[STRUCT_STRONG]]* @_ZN6StrongD1Ev(
+
+void testParamStrong(Strong a) {
+}
+
+// CHECK: define void @_Z14testCallStrongP6Strong(%[[STRUCT_STRONG]]* %[[A:.*]])
+// CHECK: %[[A_ADDR:.*]] = alloca %[[STRUCT_STRONG]]*, align 8
+// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_STRONG]], align 8
+// CHECK: store %[[STRUCT_STRONG]]* %[[A]], %[[STRUCT_STRONG]]** %[[A_ADDR]], align 8
+// CHECK: %[[V0:.*]] = load %[[STRUCT_STRONG]]*, %[[STRUCT_STRONG]]** %[[A_ADDR]], align 8
+// CHECK: %[[CALL:.*]] = call %[[STRUCT_STRONG]]* @_ZN6StrongC1ERKS_(%[[STRUCT_STRONG]]* %[[AGG_TMP]], %[[STRUCT_STRONG]]* dereferenceable(8) %[[V0]])
+// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_STRONG]], %[[STRUCT_STRONG]]* %[[AGG_TMP]], i32 0, i32 0
+// CHECK: %[[V1:.*]] = load i8*, i8** %[[COERCE_DIVE]], align 8
+// CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i8* %[[V1]] to i64
+// CHECK: call void @_Z15testParamStrong6Strong(i64 %[[COERCE_VAL_PI]])
+// CHECK: ret void
+
+void testCallStrong(Strong *a) {
+ testParamStrong(*a);
+}
+
+// CHECK: define i64 @_Z16testReturnStrongP6Strong(%[[STRUCT_STRONG]]* %[[A:.*]])
+// CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_STRONG]], align 8
+// CHECK: %[[A_ADDR:.*]] = alloca %[[STRUCT_STRONG]]*, align 8
+// CHECK: store %[[STRUCT_STRONG]]* %[[A]], %[[STRUCT_STRONG]]** %[[A_ADDR]], align 8
+// CHECK: %[[V0:.*]] = load %[[STRUCT_STRONG]]*, %[[STRUCT_STRONG]]** %[[A_ADDR]], align 8
+// CHECK: %[[CALL:.*]] = call %[[STRUCT_STRONG]]* @_ZN6StrongC1ERKS_(%[[STRUCT_STRONG]]* %[[RETVAL]], %[[STRUCT_STRONG]]* dereferenceable(8) %[[V0]])
+// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_STRONG]], %[[STRUCT_STRONG]]* %[[RETVAL]], i32 0, i32 0
+// CHECK: %[[V1:.*]] = load i8*, i8** %[[COERCE_DIVE]], align 8
+// CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i8* %[[V1]] to i64
+// CHECK: ret i64 %[[COERCE_VAL_PI]]
+
+Strong testReturnStrong(Strong *a) {
+ return *a;
+}
+
+// CHECK: define void @_Z21testParamWeakTemplate1SIU6__weakP11objc_objectE(%[[STRUCT_S]]* %{{.*}})
+// CHECK: call %struct.S* @_ZN1SIU6__weakP11objc_objectED1Ev(
+// CHECK-NEXT: ret void
+
+void testParamWeakTemplate(S<__weak id> a) {
+}
+
+// CHECK: define void @_Z27testParamContainsNonTrivial18ContainsNonTrivial(%[[STRUCT_CONTAINSNONTRIVIAL]]* %{{.*}})
+// CHECK-NOT: call
+// CHECK: ret void
+
+void testParamContainsNonTrivial(ContainsNonTrivial a) {
+}
+
+// CHECK: define void @_Z26testCallContainsNonTrivialP18ContainsNonTrivial(
+// CHECK: call void @_Z27testParamContainsNonTrivial18ContainsNonTrivial(%[[STRUCT_CONTAINSNONTRIVIAL]]* %{{.*}})
+// CHECK: call %struct.ContainsNonTrivial* @_ZN18ContainsNonTrivialD1Ev(%[[STRUCT_CONTAINSNONTRIVIAL]]* %{{.*}})
+
+void testCallContainsNonTrivial(ContainsNonTrivial *a) {
+ testParamContainsNonTrivial(*a);
+}
diff --git a/test/CodeGenObjCXX/personality.mm b/test/CodeGenObjCXX/personality.mm
new file mode 100644
index 000000000000..22cfc2c45bee
--- /dev/null
+++ b/test/CodeGenObjCXX/personality.mm
@@ -0,0 +1,105 @@
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE-SEH
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE-SJLJ
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gnustep-1.7 -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP-1_7
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gnustep -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC-SEH
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC-SJLJ
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW-SEH
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW-SJLJ
+
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MSVC
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MSVC
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MSVC
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MSVC
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gnustep-1.7 -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MSVC
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gnustep -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MSVC
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MSVC
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MSVC
+
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE-SEH
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE-SJLJ
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gnustep-1.7 -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP-1_7
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gnustep -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC-SEH
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC-SJLJ
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW-SEH
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW-SJLJ
+
+void g(void);
+
+@interface use
++ (void)e:(id)xception;
+@end
+
+// CHECK-MACOSX-FRAGILE: personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+// CHECK-MACOSX-FRAGILE-SEH: personality i8* bitcast (i32 (...)* @__gxx_personality_seh0 to i8*)
+// CHECK-MACOSX-FRAGILE-SJLJ: personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*)
+// CHECK-NS: personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*)
+// CHECK-GNUSTEP-1_7: personality i8* bitcast (i32 (...)* @__gnustep_objcxx_personality_v0 to i8*)
+// CHECK-GNUSTEP: personality i8* bitcast (i32 (...)* @__gnustep_objcxx_personality_v0 to i8*)
+// CHECK-GCC: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_v0 to i8*)
+// CHECK-GCC-SEH: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_seh0 to i8*)
+// CHECK-GCC-SJLJ: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_sj0 to i8*)
+// CHECK-OBJFW: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_v0 to i8*)
+// CHECK-OBJFW-SEH: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_seh0 to i8*)
+// CHECK-OBJFW-SJLJ: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_sj0 to i8*)
+
+// CHECK-WIN-MSVC: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
+
+void f(void) {
+ @try {
+ g();
+ } @catch (id xception) {
+ [use e:xception];
+ }
+}
+
+#if defined(__SEH_EXCEPTIONS__)
+// CHECK-WIN-SEH-X86: personality i8* bitcast (i32 (...)* @_except_handler3 to i8*)
+// CHECK-WIN-SEH-X64: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
+
+void h(void) {
+ __try {
+ i();
+ } __finally {
+ }
+}
+#endif
+
+
diff --git a/test/CodeGenObjCXX/property-dot-copy-elision.mm b/test/CodeGenObjCXX/property-dot-copy-elision.mm
new file mode 100644
index 000000000000..c13a7d9da568
--- /dev/null
+++ b/test/CodeGenObjCXX/property-dot-copy-elision.mm
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -std=c++1z -fobjc-arc -o - %s | FileCheck %s
+
+struct S0 {
+ ~S0();
+ id f;
+};
+
+struct S1 {
+ S1();
+ ~S1();
+ S1(S0);
+ id f;
+};
+
+@interface C
+@property S1 f;
+@end
+@implementation C
+@end
+
+// CHECK-LABEL: define void @_Z5test0P1C(
+// CHECK: %{{.*}} = alloca %
+// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_S1:.*]], align
+// CHECK: %[[AGG_TMP_1:.*]] = alloca %[[STRUCT_S0:.*]], align
+// CHECK: call void @_ZN2S0C1Ev(%[[STRUCT_S0]]* %[[AGG_TMP_1]])
+// CHECK: call void @_ZN2S1C1E2S0(%[[STRUCT_S1]]* %[[AGG_TMP]], %[[STRUCT_S0]]* %[[AGG_TMP_1]])
+// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, %[[STRUCT_S1]]*)*)(i8* %{{.*}}, i8* %{{.*}}, %[[STRUCT_S1]]* %[[AGG_TMP]])
+
+void test0(C *c) {
+ c.f = S0();
+}
+
+// CHECK: define void @_Z5test1P1C(
+// CHECK: %{{.*}} = alloca %
+// CHECK: %[[TEMP_LVALUE:.*]] = alloca %[[STRUCT_S1:.*]], align
+// CHECK: call void @_ZN2S1C1Ev(%[[STRUCT_S1]]* %[[TEMP_LVALUE]])
+// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, %[[STRUCT_S1]]*)*)(i8* %{{.*}}, i8* %{{.*}}, %[[STRUCT_S1]]* %[[TEMP_LVALUE]])
+
+void test1(C *c) {
+ c.f = S1();
+}
diff --git a/test/CodeGenObjCXX/property-objects.mm b/test/CodeGenObjCXX/property-objects.mm
index 8e0b6aebe149..62188e8bb230 100644
--- a/test/CodeGenObjCXX/property-objects.mm
+++ b/test/CodeGenObjCXX/property-objects.mm
@@ -119,11 +119,11 @@ void testB1(B *b) {
// CHECK: define void @_Z6testB0P1B([[B:%.*]]*
// CHECK: [[BVAR:%.*]] = alloca [[B]]*, align 8
// CHECK: [[TEMP:%.*]] = alloca [[B0:%.*]], align 8
-// CHECK: load [[B]]*, [[B]]** [[BVAR]]
-// CHECK-NEXT: [[X:%.*]] = getelementptr inbounds [[B0]], [[B0]]* [[TEMP]], i32 0, i32 0
+// CHECK: [[X:%.*]] = getelementptr inbounds [[B0]], [[B0]]* [[TEMP]], i32 0, i32 0
// CHECK-NEXT: [[T0:%.*]] = call i32 @_Z9b_makeIntv()
// CHECK-NEXT: [[T1:%.*]] = sext i32 [[T0]] to i64
// CHECK-NEXT: store i64 [[T1]], i64* [[X]], align 8
+// CHECK: load [[B]]*, [[B]]** [[BVAR]]
// CHECK-NOT: call
// CHECK: call void @llvm.memcpy
// CHECK-NOT: call
@@ -161,12 +161,12 @@ void testB2(B *b) {
// CHECK: define void @_Z6testB2P1B([[B]]*
// CHECK: [[BVAR:%.*]] = alloca [[B]]*, align 8
-// CHECK: load [[B]]*, [[B]]** [[BVAR]]
-// CHECK-NOT: call
+// CHECK: call void @llvm.dbg.declare(
// CHECK: call void @_ZN2B3C1Ev(
// CHECK-NEXT: [[T0:%.*]] = call i64 @_ZN2B3cv2B1Ev(
// CHECK-NOT: call
// CHECK: store i64 [[T0]],
+// CHECK: load [[B]]*, [[B]]** [[BVAR]]
// CHECK-NOT: call
// CHECK: call void @llvm.memcpy
// CHECK-NOT: call
diff --git a/test/CodeGenOpenCL/addr-space-struct-arg.cl b/test/CodeGenOpenCL/addr-space-struct-arg.cl
index 68fc8035b4cc..f8d7073f92ee 100644
--- a/test/CodeGenOpenCL/addr-space-struct-arg.cl
+++ b/test/CodeGenOpenCL/addr-space-struct-arg.cl
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 %s -emit-llvm -o - -O0 -finclude-default-header -ffake-address-space-map -triple i686-pc-darwin | FileCheck -enable-var-scope -check-prefixes=COM,X86 %s
-// RUN: %clang_cc1 %s -emit-llvm -o - -O0 -finclude-default-header -triple amdgcn-amdhsa-amd-amdgizcl | FileCheck -enable-var-scope -check-prefixes=COM,AMD %s
+// RUN: %clang_cc1 %s -emit-llvm -o - -O0 -finclude-default-header -triple amdgcn | FileCheck -enable-var-scope -check-prefixes=COM,AMDGCN %s
+// RUN: %clang_cc1 %s -emit-llvm -o - -cl-std=CL2.0 -O0 -finclude-default-header -triple amdgcn | FileCheck -enable-var-scope -check-prefixes=COM,AMDGCN,AMDGCN20 %s
typedef struct {
int cells[9];
@@ -35,9 +36,12 @@ struct LargeStructTwoMember {
int2 y[20];
};
+#if __OPENCL_C_VERSION__ >= 200
+struct LargeStructOneMember g_s;
+#endif
// X86-LABEL: define void @foo(%struct.Mat4X4* noalias sret %agg.result, %struct.Mat3X3* byval align 4 %in)
-// AMD-LABEL: define %struct.Mat4X4 @foo([9 x i32] %in.coerce)
+// AMDGCN-LABEL: define %struct.Mat4X4 @foo([9 x i32] %in.coerce)
Mat4X4 __attribute__((noinline)) foo(Mat3X3 in) {
Mat4X4 out;
return out;
@@ -49,15 +53,15 @@ Mat4X4 __attribute__((noinline)) foo(Mat3X3 in) {
// X86: call void @llvm.memcpy.p0i8.p1i8.i32(i8*
// X86: call void @llvm.memcpy.p1i8.p0i8.i32(i8 addrspace(1)*
-// AMD: load [9 x i32], [9 x i32] addrspace(1)*
-// AMD: call %struct.Mat4X4 @foo([9 x i32]
-// AMD: call void @llvm.memcpy.p1i8.p5i8.i64(i8 addrspace(1)*
+// AMDGCN: load [9 x i32], [9 x i32] addrspace(1)*
+// AMDGCN: call %struct.Mat4X4 @foo([9 x i32]
+// AMDGCN: call void @llvm.memcpy.p1i8.p5i8.i64(i8 addrspace(1)*
kernel void ker(global Mat3X3 *in, global Mat4X4 *out) {
out[0] = foo(in[1]);
}
// X86-LABEL: define void @foo_large(%struct.Mat64X64* noalias sret %agg.result, %struct.Mat32X32* byval align 4 %in)
-// AMD-LABEL: define void @foo_large(%struct.Mat64X64 addrspace(5)* noalias sret %agg.result, %struct.Mat32X32 addrspace(5)* byval align 4 %in)
+// AMDGCN-LABEL: define void @foo_large(%struct.Mat64X64 addrspace(5)* noalias sret %agg.result, %struct.Mat32X32 addrspace(5)* byval align 4 %in)
Mat64X64 __attribute__((noinline)) foo_large(Mat32X32 in) {
Mat64X64 out;
return out;
@@ -68,66 +72,97 @@ Mat64X64 __attribute__((noinline)) foo_large(Mat32X32 in) {
// the return value.
// X86: call void @llvm.memcpy.p0i8.p1i8.i32(i8*
// X86: call void @llvm.memcpy.p1i8.p0i8.i32(i8 addrspace(1)*
-// AMD: call void @llvm.memcpy.p5i8.p1i8.i64(i8 addrspace(5)*
-// AMD: call void @llvm.memcpy.p1i8.p5i8.i64(i8 addrspace(1)*
+// AMDGCN: call void @llvm.memcpy.p5i8.p1i8.i64(i8 addrspace(5)*
+// AMDGCN: call void @llvm.memcpy.p1i8.p5i8.i64(i8 addrspace(1)*
kernel void ker_large(global Mat32X32 *in, global Mat64X64 *out) {
out[0] = foo_large(in[1]);
}
-// AMD-LABEL: define void @FuncOneMember(<2 x i32> %u.coerce)
+// AMDGCN-LABEL: define void @FuncOneMember(<2 x i32> %u.coerce)
void FuncOneMember(struct StructOneMember u) {
u.x = (int2)(0, 0);
}
-// AMD-LABEL: define void @FuncOneLargeMember(%struct.LargeStructOneMember addrspace(5)* byval align 8 %u)
+// AMDGCN-LABEL: define void @FuncOneLargeMember(%struct.LargeStructOneMember addrspace(5)* byval align 8 %u)
+// AMDGCN-NOT: addrspacecast
+// AMDGCN: store <2 x i32> %{{.*}}, <2 x i32> addrspace(5)*
void FuncOneLargeMember(struct LargeStructOneMember u) {
u.x[0] = (int2)(0, 0);
}
-// AMD-LABEL: define amdgpu_kernel void @KernelOneMember
-// AMD-SAME: (<2 x i32> %[[u_coerce:.*]])
-// AMD: %[[u:.*]] = alloca %struct.StructOneMember, align 8, addrspace(5)
-// AMD: %[[coerce_dive:.*]] = getelementptr inbounds %struct.StructOneMember, %struct.StructOneMember addrspace(5)* %[[u]], i32 0, i32 0
-// AMD: store <2 x i32> %[[u_coerce]], <2 x i32> addrspace(5)* %[[coerce_dive]]
-// AMD: call void @FuncOneMember(<2 x i32>
+// AMDGCN20-LABEL: define void @test_indirect_arg_globl()
+// AMDGCN20: %[[byval_temp:.*]] = alloca %struct.LargeStructOneMember, align 8, addrspace(5)
+// AMDGCN20: %[[r0:.*]] = bitcast %struct.LargeStructOneMember addrspace(5)* %[[byval_temp]] to i8 addrspace(5)*
+// AMDGCN20: call void @llvm.memcpy.p5i8.p1i8.i64(i8 addrspace(5)* align 8 %[[r0]], i8 addrspace(1)* align 8 bitcast (%struct.LargeStructOneMember addrspace(1)* @g_s to i8 addrspace(1)*), i64 800, i1 false)
+// AMDGCN20: call void @FuncOneLargeMember(%struct.LargeStructOneMember addrspace(5)* byval align 8 %[[byval_temp]])
+#if __OPENCL_C_VERSION__ >= 200
+void test_indirect_arg_globl(void) {
+ FuncOneLargeMember(g_s);
+}
+#endif
+
+// AMDGCN-LABEL: define amdgpu_kernel void @test_indirect_arg_local()
+// AMDGCN: %[[byval_temp:.*]] = alloca %struct.LargeStructOneMember, align 8, addrspace(5)
+// AMDGCN: %[[r0:.*]] = bitcast %struct.LargeStructOneMember addrspace(5)* %[[byval_temp]] to i8 addrspace(5)*
+// AMDGCN: call void @llvm.memcpy.p5i8.p3i8.i64(i8 addrspace(5)* align 8 %[[r0]], i8 addrspace(3)* align 8 bitcast (%struct.LargeStructOneMember addrspace(3)* @test_indirect_arg_local.l_s to i8 addrspace(3)*), i64 800, i1 false)
+// AMDGCN: call void @FuncOneLargeMember(%struct.LargeStructOneMember addrspace(5)* byval align 8 %[[byval_temp]])
+kernel void test_indirect_arg_local(void) {
+ local struct LargeStructOneMember l_s;
+ FuncOneLargeMember(l_s);
+}
+
+// AMDGCN-LABEL: define void @test_indirect_arg_private()
+// AMDGCN: %[[p_s:.*]] = alloca %struct.LargeStructOneMember, align 8, addrspace(5)
+// AMDGCN-NOT: @llvm.memcpy
+// AMDGCN-NEXT: call void @FuncOneLargeMember(%struct.LargeStructOneMember addrspace(5)* byval align 8 %[[p_s]])
+void test_indirect_arg_private(void) {
+ struct LargeStructOneMember p_s;
+ FuncOneLargeMember(p_s);
+}
+
+// AMDGCN-LABEL: define amdgpu_kernel void @KernelOneMember
+// AMDGCN-SAME: (<2 x i32> %[[u_coerce:.*]])
+// AMDGCN: %[[u:.*]] = alloca %struct.StructOneMember, align 8, addrspace(5)
+// AMDGCN: %[[coerce_dive:.*]] = getelementptr inbounds %struct.StructOneMember, %struct.StructOneMember addrspace(5)* %[[u]], i32 0, i32 0
+// AMDGCN: store <2 x i32> %[[u_coerce]], <2 x i32> addrspace(5)* %[[coerce_dive]]
+// AMDGCN: call void @FuncOneMember(<2 x i32>
kernel void KernelOneMember(struct StructOneMember u) {
FuncOneMember(u);
}
-// AMD-LABEL: define amdgpu_kernel void @KernelLargeOneMember(
-// AMD: %[[U:.*]] = alloca %struct.LargeStructOneMember, align 8, addrspace(5)
-// AMD: store %struct.LargeStructOneMember %u.coerce, %struct.LargeStructOneMember addrspace(5)* %[[U]], align 8
-// AMD: call void @FuncOneLargeMember(%struct.LargeStructOneMember addrspace(5)* byval align 8 %[[U]])
+// AMDGCN-LABEL: define amdgpu_kernel void @KernelLargeOneMember(
+// AMDGCN: %[[U:.*]] = alloca %struct.LargeStructOneMember, align 8, addrspace(5)
+// AMDGCN: store %struct.LargeStructOneMember %u.coerce, %struct.LargeStructOneMember addrspace(5)* %[[U]], align 8
+// AMDGCN: call void @FuncOneLargeMember(%struct.LargeStructOneMember addrspace(5)* byval align 8 %[[U]])
kernel void KernelLargeOneMember(struct LargeStructOneMember u) {
FuncOneLargeMember(u);
}
-// AMD-LABEL: define void @FuncTwoMember(<2 x i32> %u.coerce0, <2 x i32> %u.coerce1)
+// AMDGCN-LABEL: define void @FuncTwoMember(<2 x i32> %u.coerce0, <2 x i32> %u.coerce1)
void FuncTwoMember(struct StructTwoMember u) {
u.y = (int2)(0, 0);
}
-// AMD-LABEL: define void @FuncLargeTwoMember(%struct.LargeStructTwoMember addrspace(5)* byval align 8 %u)
+// AMDGCN-LABEL: define void @FuncLargeTwoMember(%struct.LargeStructTwoMember addrspace(5)* byval align 8 %u)
void FuncLargeTwoMember(struct LargeStructTwoMember u) {
u.y[0] = (int2)(0, 0);
}
-
-// AMD-LABEL: define amdgpu_kernel void @KernelTwoMember
-// AMD-SAME: (%struct.StructTwoMember %[[u_coerce:.*]])
-// AMD: %[[u:.*]] = alloca %struct.StructTwoMember, align 8, addrspace(5)
-// AMD: %[[LD0:.*]] = load <2 x i32>, <2 x i32> addrspace(5)*
-// AMD: %[[LD1:.*]] = load <2 x i32>, <2 x i32> addrspace(5)*
-// AMD: call void @FuncTwoMember(<2 x i32> %[[LD0]], <2 x i32> %[[LD1]])
+// AMDGCN-LABEL: define amdgpu_kernel void @KernelTwoMember
+// AMDGCN-SAME: (%struct.StructTwoMember %[[u_coerce:.*]])
+// AMDGCN: %[[u:.*]] = alloca %struct.StructTwoMember, align 8, addrspace(5)
+// AMDGCN: %[[LD0:.*]] = load <2 x i32>, <2 x i32> addrspace(5)*
+// AMDGCN: %[[LD1:.*]] = load <2 x i32>, <2 x i32> addrspace(5)*
+// AMDGCN: call void @FuncTwoMember(<2 x i32> %[[LD0]], <2 x i32> %[[LD1]])
kernel void KernelTwoMember(struct StructTwoMember u) {
FuncTwoMember(u);
}
-// AMD-LABEL: define amdgpu_kernel void @KernelLargeTwoMember
-// AMD-SAME: (%struct.LargeStructTwoMember %[[u_coerce:.*]])
-// AMD: %[[u:.*]] = alloca %struct.LargeStructTwoMember, align 8, addrspace(5)
-// AMD: store %struct.LargeStructTwoMember %[[u_coerce]], %struct.LargeStructTwoMember addrspace(5)* %[[u]]
-// AMD: call void @FuncLargeTwoMember(%struct.LargeStructTwoMember addrspace(5)* byval align 8 %[[u]])
+// AMDGCN-LABEL: define amdgpu_kernel void @KernelLargeTwoMember
+// AMDGCN-SAME: (%struct.LargeStructTwoMember %[[u_coerce:.*]])
+// AMDGCN: %[[u:.*]] = alloca %struct.LargeStructTwoMember, align 8, addrspace(5)
+// AMDGCN: store %struct.LargeStructTwoMember %[[u_coerce]], %struct.LargeStructTwoMember addrspace(5)* %[[u]]
+// AMDGCN: call void @FuncLargeTwoMember(%struct.LargeStructTwoMember addrspace(5)* byval align 8 %[[u]])
kernel void KernelLargeTwoMember(struct LargeStructTwoMember u) {
FuncLargeTwoMember(u);
}
diff --git a/test/CodeGenOpenCL/address-space-constant-initializers.cl b/test/CodeGenOpenCL/address-space-constant-initializers.cl
index a03d939fae54..da971cfee383 100644
--- a/test/CodeGenOpenCL/address-space-constant-initializers.cl
+++ b/test/CodeGenOpenCL/address-space-constant-initializers.cl
@@ -1,6 +1,5 @@
-// RUN: %clang_cc1 %s -ffake-address-space-map -emit-llvm -o - | FileCheck %s
-// RUN: %clang_cc1 %s -triple amdgcn-amd-amdhsa-opencl -emit-llvm -o - | FileCheck %s
-// RUN: %clang_cc1 %s -triple amdgcn-amd-amdhsa-amdgizcl -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -ffake-address-space-map -emit-llvm -o - | FileCheck -check-prefix=FAKE %s
+// RUN: %clang_cc1 %s -triple amdgcn-amd-amdhsa -emit-llvm -o - | FileCheck -check-prefix=AMDGCN %s
typedef struct {
int i;
@@ -13,10 +12,22 @@ typedef struct {
__constant float* constant_float_ptr;
} ConstantArrayPointerStruct;
-// CHECK: %struct.ConstantArrayPointerStruct = type { float addrspace(2)* }
-// CHECK: addrspace(2) constant %struct.ConstantArrayPointerStruct { float addrspace(2)* bitcast (i8 addrspace(2)* getelementptr (i8, i8 addrspace(2)* bitcast (%struct.ArrayStruct addrspace(2)* @constant_array_struct to i8 addrspace(2)*), i64 4) to float addrspace(2)*) }
+// FAKE: %struct.ConstantArrayPointerStruct = type { float addrspace(2)* }
+// FAKE: addrspace(2) constant %struct.ConstantArrayPointerStruct { float addrspace(2)* bitcast (i8 addrspace(2)* getelementptr (i8, i8 addrspace(2)* bitcast (%struct.ArrayStruct addrspace(2)* @constant_array_struct to i8 addrspace(2)*), i64 4) to float addrspace(2)*) }
+// AMDGCN: %struct.ConstantArrayPointerStruct = type { float addrspace(4)* }
+// AMDGCN: addrspace(4) constant %struct.ConstantArrayPointerStruct { float addrspace(4)* bitcast (i8 addrspace(4)* getelementptr (i8, i8 addrspace(4)* bitcast (%struct.ArrayStruct addrspace(4)* @constant_array_struct to i8 addrspace(4)*), i64 4) to float addrspace(4)*) }
// Bug 18567
__constant ConstantArrayPointerStruct constant_array_pointer_struct = {
&constant_array_struct.f
};
+__kernel void initializer_cast_is_valid_crash()
+{
+ unsigned char v512[64] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00
+ };
+
+}
diff --git a/test/CodeGenOpenCL/address-spaces.cl b/test/CodeGenOpenCL/address-spaces.cl
index cb641f593711..60f5e30d328b 100644
--- a/test/CodeGenOpenCL/address-spaces.cl
+++ b/test/CodeGenOpenCL/address-spaces.cl
@@ -1,11 +1,9 @@
// RUN: %clang_cc1 %s -O0 -ffake-address-space-map -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,SPIR
// RUN: %clang_cc1 %s -O0 -DCL20 -cl-std=CL2.0 -ffake-address-space-map -emit-llvm -o - | FileCheck %s --check-prefixes=CL20,CL20SPIR
-// RUN: %clang_cc1 %s -O0 -triple amdgcn-amd-amdhsa-opencl -emit-llvm -o - | FileCheck --check-prefixes=CHECK,SPIR %s
-// RUN: %clang_cc1 %s -O0 -triple amdgcn-amd-amdhsa-opencl -DCL20 -cl-std=CL2.0 -emit-llvm -o - | FileCheck %s --check-prefixes=CL20,CL20SPIR
-// RUN: %clang_cc1 %s -O0 -triple amdgcn-amd-amdhsa-amdgizcl -emit-llvm -o - | FileCheck %s -check-prefixes=CHECK,GIZ
-// RUN: %clang_cc1 %s -O0 -triple amdgcn-amd-amdhsa-amdgizcl -DCL20 -cl-std=CL2.0 -emit-llvm -o - | FileCheck %s --check-prefixes=CL20,CL20GIZ
-// RUN: %clang_cc1 %s -O0 -triple amdgcn-mesa-mesa3d -emit-llvm -o - | FileCheck --check-prefixes=CHECK,SPIR %s
-// RUN: %clang_cc1 %s -O0 -triple r600-- -emit-llvm -o - | FileCheck --check-prefixes=CHECK,SPIR %s
+// RUN: %clang_cc1 %s -O0 -triple amdgcn-amd-amdhsa -emit-llvm -o - | FileCheck --check-prefixes=CHECK,AMDGCN %s
+// RUN: %clang_cc1 %s -O0 -triple amdgcn-amd-amdhsa -DCL20 -cl-std=CL2.0 -emit-llvm -o - | FileCheck %s --check-prefixes=CL20,CL20AMDGCN
+// RUN: %clang_cc1 %s -O0 -triple amdgcn-mesa-mesa3d -emit-llvm -o - | FileCheck --check-prefixes=CHECK,AMDGCN %s
+// RUN: %clang_cc1 %s -O0 -triple r600-- -emit-llvm -o - | FileCheck --check-prefixes=CHECK,AMDGCN %s
// SPIR: %struct.S = type { i32, i32, i32* }
// CL20SPIR: %struct.S = type { i32, i32, i32 addrspace(4)* }
@@ -15,18 +13,18 @@ struct S {
int *z;
};
-// CL20-DAG: @g_extern_var = external addrspace(1) global float
-// CL20-DAG: @l_extern_var = external addrspace(1) global float
+// CL20-DAG: @g_extern_var = external {{(dso_local )?}}addrspace(1) global float
+// CL20-DAG: @l_extern_var = external {{(dso_local )?}}addrspace(1) global float
// CL20-DAG: @test_static.l_static_var = internal addrspace(1) global float 0.000000e+00
// CL20-DAG: @g_static_var = internal addrspace(1) global float 0.000000e+00
#ifdef CL20
-// CL20-DAG: @g_s = common addrspace(1) global %struct.S zeroinitializer
+// CL20-DAG: @g_s = common {{(dso_local )?}}addrspace(1) global %struct.S zeroinitializer
struct S g_s;
#endif
// SPIR: i32* %arg
-// GIZ: i32 addrspace(5)* %arg
+// AMDGCN: i32 addrspace(5)* %arg
void f__p(__private int *arg) {}
// CHECK: i32 addrspace(1)* %arg
@@ -35,11 +33,12 @@ void f__g(__global int *arg) {}
// CHECK: i32 addrspace(3)* %arg
void f__l(__local int *arg) {}
-// CHECK: i32 addrspace(2)* %arg
+// SPIR: i32 addrspace(2)* %arg
+// AMDGCN: i32 addrspace(4)* %arg
void f__c(__constant int *arg) {}
// SPIR: i32* %arg
-// GIZ: i32 addrspace(5)* %arg
+// AMDGCN: i32 addrspace(5)* %arg
void fp(private int *arg) {}
// CHECK: i32 addrspace(1)* %arg
@@ -48,28 +47,29 @@ void fg(global int *arg) {}
// CHECK: i32 addrspace(3)* %arg
void fl(local int *arg) {}
-// CHECK: i32 addrspace(2)* %arg
+// SPIR: i32 addrspace(2)* %arg
+// AMDGCN: i32 addrspace(4)* %arg
void fc(constant int *arg) {}
#ifdef CL20
int i;
-// CL20-DAG: @i = common addrspace(1) global i32 0
+// CL20-DAG: @i = common {{(dso_local )?}}addrspace(1) global i32 0
int *ptr;
-// CL20SPIR-DAG: @ptr = common addrspace(1) global i32 addrspace(4)* null
-// CL20GIZ-DAG: @ptr = common addrspace(1) global i32* null
+// CL20SPIR-DAG: @ptr = common {{(dso_local )?}}addrspace(1) global i32 addrspace(4)* null
+// CL20AMDGCN-DAG: @ptr = common {{(dso_local )?}}addrspace(1) global i32* null
#endif
// SPIR: i32* %arg
-// GIZ: i32 addrspace(5)* %arg
+// AMDGCN: i32 addrspace(5)* %arg
// CL20SPIR-DAG: i32 addrspace(4)* %arg
-// CL20GIZ-DAG: i32* %arg
+// CL20AMDGCN-DAG: i32* %arg
void f(int *arg) {
int i;
// SPIR: %i = alloca i32,
-// GIZ: %i = alloca i32{{.*}}addrspace(5)
+// AMDGCN: %i = alloca i32{{.*}}addrspace(5)
// CL20SPIR-DAG: %i = alloca i32,
-// CL20GIZ-DAG: %i = alloca i32{{.*}}addrspace(5)
+// CL20AMDGCN-DAG: %i = alloca i32{{.*}}addrspace(5)
#ifdef CL20
static int ii;
@@ -79,13 +79,13 @@ void f(int *arg) {
typedef int int_td;
typedef int *intp_td;
-// SPIR: define void @test_typedef(i32 addrspace(1)* %x, i32 addrspace(2)* %y, i32* %z)
+// SPIR: define {{(dso_local )?}}void @test_typedef(i32 addrspace(1)* %x, i32 addrspace(2)* %y, i32* %z)
void test_typedef(global int_td *x, constant int_td *y, intp_td z) {
*x = *y;
*z = 0;
}
-// SPIR: define void @test_struct()
+// SPIR: define {{(dso_local )?}}void @test_struct()
void test_struct() {
// SPIR: %ps = alloca %struct.S*
// CL20SPIR: %ps = alloca %struct.S addrspace(4)*
@@ -99,7 +99,7 @@ void test_struct() {
#endif
}
-// SPIR-LABEL: define void @test_void_par()
+// SPIR-LABEL: define {{(dso_local )?}}void @test_void_par()
void test_void_par(void) {}
// On ppc64 returns signext i32.
diff --git a/test/CodeGenOpenCL/amdgcn-automatic-variable.cl b/test/CodeGenOpenCL/amdgcn-automatic-variable.cl
index fefe1c4a41d5..59f38f80dca4 100644
--- a/test/CodeGenOpenCL/amdgcn-automatic-variable.cl
+++ b/test/CodeGenOpenCL/amdgcn-automatic-variable.cl
@@ -62,7 +62,7 @@ void func2(void) {
// CHECK-LABEL: define void @func3()
// CHECK: %a = alloca [16 x [1 x float]], align 4, addrspace(5)
// CHECK: %[[CAST:.+]] = bitcast [16 x [1 x float]] addrspace(5)* %a to i8 addrspace(5)*
-// CHECK: call void @llvm.memset.p5i8.i64(i8 addrspace(5)* %[[CAST]], i8 0, i64 64, i32 4, i1 false)
+// CHECK: call void @llvm.memset.p5i8.i64(i8 addrspace(5)* align 4 %[[CAST]], i8 0, i64 64, i1 false)
void func3(void) {
float a[16][1] = {{0.}};
}
diff --git a/test/CodeGenOpenCL/amdgpu-abi-struct-coerce.cl b/test/CodeGenOpenCL/amdgpu-abi-struct-coerce.cl
index 21bdb15b094d..aec00e76014e 100644
--- a/test/CodeGenOpenCL/amdgpu-abi-struct-coerce.cl
+++ b/test/CodeGenOpenCL/amdgpu-abi-struct-coerce.cl
@@ -1,6 +1,6 @@
// REQUIRES: amdgpu-registered-target
-// RUN: %clang_cc1 -triple amdgcn-unknown-unknown-amdgiz -S -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK,AMDGCN %s
-// RUN: %clang_cc1 -triple r600-unknown-unknown -S -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK,R600 %s
+// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -S -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple r600-unknown-unknown -S -emit-llvm -o - %s | FileCheck %s
typedef __attribute__(( ext_vector_type(2) )) char char2;
typedef __attribute__(( ext_vector_type(3) )) char char3;
@@ -309,8 +309,7 @@ void func_single_struct_element_struct_arg(single_struct_element_struct_arg_t ar
// CHECK: void @func_different_size_type_pair_arg(i64 %arg1.coerce0, i32 %arg1.coerce1)
void func_different_size_type_pair_arg(different_size_type_pair arg1) { }
-// AMDGCN: void @func_flexible_array_arg(%struct.flexible_array addrspace(5)* byval nocapture align 4 %arg)
-// R600: void @func_flexible_array_arg(%struct.flexible_array* byval nocapture align 4 %arg)
+// CHECK: void @func_flexible_array_arg(%struct.flexible_array addrspace(5)* byval nocapture align 4 %arg)
void func_flexible_array_arg(flexible_array arg) { }
// CHECK: define float @func_f32_ret()
@@ -405,16 +404,14 @@ struct_arr16 func_ret_struct_arr16()
return s;
}
-// AMDGCN: define void @func_ret_struct_arr32(%struct.struct_arr32 addrspace(5)* noalias nocapture sret %agg.result)
-// R600: define void @func_ret_struct_arr32(%struct.struct_arr32* noalias nocapture sret %agg.result)
+// CHECK: define void @func_ret_struct_arr32(%struct.struct_arr32 addrspace(5)* noalias nocapture sret %agg.result)
struct_arr32 func_ret_struct_arr32()
{
struct_arr32 s = { 0 };
return s;
}
-// AMDGCN: define void @func_ret_struct_arr33(%struct.struct_arr33 addrspace(5)* noalias nocapture sret %agg.result)
-// R600: define void @func_ret_struct_arr33(%struct.struct_arr33* noalias nocapture sret %agg.result)
+// CHECK: define void @func_ret_struct_arr33(%struct.struct_arr33 addrspace(5)* noalias nocapture sret %agg.result)
struct_arr33 func_ret_struct_arr33()
{
struct_arr33 s = { 0 };
@@ -428,7 +425,7 @@ struct_char_arr32 func_ret_struct_char_arr32()
return s;
}
-// CHECK: define i32 @func_transparent_union_ret() local_unnamed_addr #0 {
+// CHECK: define i32 @func_transparent_union_ret() local_unnamed_addr #1 {
// CHECK: ret i32 0
transparent_u func_transparent_union_ret()
{
@@ -443,8 +440,7 @@ different_size_type_pair func_different_size_type_pair_ret()
return s;
}
-// AMDGCN: define void @func_flexible_array_ret(%struct.flexible_array addrspace(5)* noalias nocapture sret %agg.result)
-// R600: define void @func_flexible_array_ret(%struct.flexible_array* noalias nocapture sret %agg.result)
+// CHECK: define void @func_flexible_array_ret(%struct.flexible_array addrspace(5)* noalias nocapture sret %agg.result)
flexible_array func_flexible_array_ret()
{
flexible_array s = { 0 };
@@ -454,13 +450,11 @@ flexible_array func_flexible_array_ret()
// CHECK: define void @func_reg_state_lo(<4 x i32> %arg0, <4 x i32> %arg1, <4 x i32> %arg2, i32 %arg3, i32 %s.coerce0, float %s.coerce1, i32 %s.coerce2)
void func_reg_state_lo(int4 arg0, int4 arg1, int4 arg2, int arg3, struct_arg_t s) { }
-// AMDGCN: define void @func_reg_state_hi(<4 x i32> %arg0, <4 x i32> %arg1, <4 x i32> %arg2, i32 %arg3, i32 %arg4, %struct.struct_arg addrspace(5)* byval nocapture align 4 %s)
-// R600: define void @func_reg_state_hi(<4 x i32> %arg0, <4 x i32> %arg1, <4 x i32> %arg2, i32 %arg3, i32 %arg4, %struct.struct_arg* byval nocapture align 4 %s)
+// CHECK: define void @func_reg_state_hi(<4 x i32> %arg0, <4 x i32> %arg1, <4 x i32> %arg2, i32 %arg3, i32 %arg4, %struct.struct_arg addrspace(5)* byval nocapture align 4 %s)
void func_reg_state_hi(int4 arg0, int4 arg1, int4 arg2, int arg3, int arg4, struct_arg_t s) { }
// XXX - Why don't the inner structs flatten?
-// AMDGCN: define void @func_reg_state_num_regs_nested_struct(<4 x i32> %arg0, i32 %arg1, i32 %arg2.coerce0, %struct.nested %arg2.coerce1, i32 %arg3.coerce0, %struct.nested %arg3.coerce1, %struct.num_regs_nested_struct addrspace(5)* byval nocapture align 8 %arg4)
-// R600: define void @func_reg_state_num_regs_nested_struct(<4 x i32> %arg0, i32 %arg1, i32 %arg2.coerce0, %struct.nested %arg2.coerce1, i32 %arg3.coerce0, %struct.nested %arg3.coerce1, %struct.num_regs_nested_struct* byval nocapture align 8 %arg4)
+// CHECK: define void @func_reg_state_num_regs_nested_struct(<4 x i32> %arg0, i32 %arg1, i32 %arg2.coerce0, %struct.nested %arg2.coerce1, i32 %arg3.coerce0, %struct.nested %arg3.coerce1, %struct.num_regs_nested_struct addrspace(5)* byval nocapture align 8 %arg4)
void func_reg_state_num_regs_nested_struct(int4 arg0, int arg1, num_regs_nested_struct arg2, num_regs_nested_struct arg3, num_regs_nested_struct arg4) { }
// CHECK: define void @func_double_nested_struct_arg(<4 x i32> %arg0, i32 %arg1, i32 %arg2.coerce0, %struct.double_nested %arg2.coerce1, i16 %arg2.coerce2)
@@ -475,8 +469,7 @@ double_nested_struct func_double_nested_struct_ret(int4 arg0, int arg1) {
// CHECK: define void @func_large_struct_padding_arg_direct(i8 %arg.coerce0, i32 %arg.coerce1, i8 %arg.coerce2, i32 %arg.coerce3, i8 %arg.coerce4, i8 %arg.coerce5, i16 %arg.coerce6, i16 %arg.coerce7, [3 x i8] %arg.coerce8, i64 %arg.coerce9, i32 %arg.coerce10, i8 %arg.coerce11, i32 %arg.coerce12, i16 %arg.coerce13, i8 %arg.coerce14)
void func_large_struct_padding_arg_direct(large_struct_padding arg) { }
-// AMDGCN: define void @func_large_struct_padding_arg_store(%struct.large_struct_padding addrspace(1)* nocapture %out, %struct.large_struct_padding addrspace(5)* byval nocapture readonly align 8 %arg)
-// R600: define void @func_large_struct_padding_arg_store(%struct.large_struct_padding addrspace(1)* nocapture %out, %struct.large_struct_padding* byval nocapture readonly align 8 %arg)
+// CHECK: define void @func_large_struct_padding_arg_store(%struct.large_struct_padding addrspace(1)* nocapture %out, %struct.large_struct_padding addrspace(5)* byval nocapture readonly align 8 %arg)
void func_large_struct_padding_arg_store(global large_struct_padding* out, large_struct_padding arg) {
*out = arg;
}
@@ -486,8 +479,7 @@ void v3i32_reg_count(int3 arg1, int3 arg2, int3 arg3, int3 arg4, struct_arg_t ar
// Function signature from blender, nothing should be passed byval. The v3i32
// should not count as 4 passed registers.
-// AMDGCN: define void @v3i32_pair_reg_count(%struct.int3_pair addrspace(5)* nocapture %arg0, <3 x i32> %arg1.coerce0, <3 x i32> %arg1.coerce1, <3 x i32> %arg2, <3 x i32> %arg3.coerce0, <3 x i32> %arg3.coerce1, <3 x i32> %arg4, float %arg5)
-// R600: define void @v3i32_pair_reg_count(%struct.int3_pair* nocapture %arg0, <3 x i32> %arg1.coerce0, <3 x i32> %arg1.coerce1, <3 x i32> %arg2, <3 x i32> %arg3.coerce0, <3 x i32> %arg3.coerce1, <3 x i32> %arg4, float %arg5)
+// CHECK: define void @v3i32_pair_reg_count(%struct.int3_pair addrspace(5)* nocapture %arg0, <3 x i32> %arg1.coerce0, <3 x i32> %arg1.coerce1, <3 x i32> %arg2, <3 x i32> %arg3.coerce0, <3 x i32> %arg3.coerce1, <3 x i32> %arg4, float %arg5)
void v3i32_pair_reg_count(int3_pair *arg0, int3_pair arg1, int3 arg2, int3_pair arg3, int3 arg4, float arg5) { }
// Each short4 should fit pack into 2 registers.
@@ -495,8 +487,7 @@ void v3i32_pair_reg_count(int3_pair *arg0, int3_pair arg1, int3 arg2, int3_pair
void v4i16_reg_count(short4 arg0, short4 arg1, short4 arg2, short4 arg3,
short4 arg4, short4 arg5, struct_4regs arg6) { }
-// AMDGCN: define void @v4i16_pair_reg_count_over(<4 x i16> %arg0, <4 x i16> %arg1, <4 x i16> %arg2, <4 x i16> %arg3, <4 x i16> %arg4, <4 x i16> %arg5, <4 x i16> %arg6, %struct.struct_4regs addrspace(5)* byval nocapture align 4 %arg7)
-// R600: define void @v4i16_pair_reg_count_over(<4 x i16> %arg0, <4 x i16> %arg1, <4 x i16> %arg2, <4 x i16> %arg3, <4 x i16> %arg4, <4 x i16> %arg5, <4 x i16> %arg6, %struct.struct_4regs* byval nocapture align 4 %arg7)
+// CHECK: define void @v4i16_pair_reg_count_over(<4 x i16> %arg0, <4 x i16> %arg1, <4 x i16> %arg2, <4 x i16> %arg3, <4 x i16> %arg4, <4 x i16> %arg5, <4 x i16> %arg6, %struct.struct_4regs addrspace(5)* byval nocapture align 4 %arg7)
void v4i16_pair_reg_count_over(short4 arg0, short4 arg1, short4 arg2, short4 arg3,
short4 arg4, short4 arg5, short4 arg6, struct_4regs arg7) { }
@@ -504,8 +495,7 @@ void v4i16_pair_reg_count_over(short4 arg0, short4 arg1, short4 arg2, short4 arg
void v3i16_reg_count(short3 arg0, short3 arg1, short3 arg2, short3 arg3,
short3 arg4, short3 arg5, struct_4regs arg6) { }
-// AMDGCN: define void @v3i16_reg_count_over(<3 x i16> %arg0, <3 x i16> %arg1, <3 x i16> %arg2, <3 x i16> %arg3, <3 x i16> %arg4, <3 x i16> %arg5, <3 x i16> %arg6, %struct.struct_4regs addrspace(5)* byval nocapture align 4 %arg7)
-// R600: define void @v3i16_reg_count_over(<3 x i16> %arg0, <3 x i16> %arg1, <3 x i16> %arg2, <3 x i16> %arg3, <3 x i16> %arg4, <3 x i16> %arg5, <3 x i16> %arg6, %struct.struct_4regs* byval nocapture align 4 %arg7)
+// CHECK: define void @v3i16_reg_count_over(<3 x i16> %arg0, <3 x i16> %arg1, <3 x i16> %arg2, <3 x i16> %arg3, <3 x i16> %arg4, <3 x i16> %arg5, <3 x i16> %arg6, %struct.struct_4regs addrspace(5)* byval nocapture align 4 %arg7)
void v3i16_reg_count_over(short3 arg0, short3 arg1, short3 arg2, short3 arg3,
short3 arg4, short3 arg5, short3 arg6, struct_4regs arg7) { }
@@ -515,8 +505,7 @@ void v2i16_reg_count(short2 arg0, short2 arg1, short2 arg2, short2 arg3,
short2 arg8, short2 arg9, short2 arg10, short2 arg11,
struct_4regs arg13) { }
-// AMDGCN: define void @v2i16_reg_count_over(<2 x i16> %arg0, <2 x i16> %arg1, <2 x i16> %arg2, <2 x i16> %arg3, <2 x i16> %arg4, <2 x i16> %arg5, <2 x i16> %arg6, <2 x i16> %arg7, <2 x i16> %arg8, <2 x i16> %arg9, <2 x i16> %arg10, <2 x i16> %arg11, <2 x i16> %arg12, %struct.struct_4regs addrspace(5)* byval nocapture align 4 %arg13)
-// R600: define void @v2i16_reg_count_over(<2 x i16> %arg0, <2 x i16> %arg1, <2 x i16> %arg2, <2 x i16> %arg3, <2 x i16> %arg4, <2 x i16> %arg5, <2 x i16> %arg6, <2 x i16> %arg7, <2 x i16> %arg8, <2 x i16> %arg9, <2 x i16> %arg10, <2 x i16> %arg11, <2 x i16> %arg12, %struct.struct_4regs* byval nocapture align 4 %arg13)
+// CHECK: define void @v2i16_reg_count_over(<2 x i16> %arg0, <2 x i16> %arg1, <2 x i16> %arg2, <2 x i16> %arg3, <2 x i16> %arg4, <2 x i16> %arg5, <2 x i16> %arg6, <2 x i16> %arg7, <2 x i16> %arg8, <2 x i16> %arg9, <2 x i16> %arg10, <2 x i16> %arg11, <2 x i16> %arg12, %struct.struct_4regs addrspace(5)* byval nocapture align 4 %arg13)
void v2i16_reg_count_over(short2 arg0, short2 arg1, short2 arg2, short2 arg3,
short2 arg4, short2 arg5, short2 arg6, short2 arg7,
short2 arg8, short2 arg9, short2 arg10, short2 arg11,
@@ -526,8 +515,7 @@ void v2i16_reg_count_over(short2 arg0, short2 arg1, short2 arg2, short2 arg3,
void v2i8_reg_count(char2 arg0, char2 arg1, char2 arg2, char2 arg3,
char2 arg4, char2 arg5, struct_4regs arg6) { }
-// AMDGCN: define void @v2i8_reg_count_over(<2 x i8> %arg0, <2 x i8> %arg1, <2 x i8> %arg2, <2 x i8> %arg3, <2 x i8> %arg4, <2 x i8> %arg5, i32 %arg6, %struct.struct_4regs addrspace(5)* byval nocapture align 4 %arg7)
-// R600: define void @v2i8_reg_count_over(<2 x i8> %arg0, <2 x i8> %arg1, <2 x i8> %arg2, <2 x i8> %arg3, <2 x i8> %arg4, <2 x i8> %arg5, i32 %arg6, %struct.struct_4regs* byval nocapture align 4 %arg7)
+// CHECK: define void @v2i8_reg_count_over(<2 x i8> %arg0, <2 x i8> %arg1, <2 x i8> %arg2, <2 x i8> %arg3, <2 x i8> %arg4, <2 x i8> %arg5, i32 %arg6, %struct.struct_4regs addrspace(5)* byval nocapture align 4 %arg7)
void v2i8_reg_count_over(char2 arg0, char2 arg1, char2 arg2, char2 arg3,
char2 arg4, char2 arg5, int arg6, struct_4regs arg7) { }
diff --git a/test/CodeGenOpenCL/amdgpu-alignment.cl b/test/CodeGenOpenCL/amdgpu-alignment.cl
index 70a22c9f756c..b5dc47adbc2c 100644
--- a/test/CodeGenOpenCL/amdgpu-alignment.cl
+++ b/test/CodeGenOpenCL/amdgpu-alignment.cl
@@ -336,91 +336,91 @@ kernel void local_memory_alignment_arg(
}
// CHECK-LABEL: @private_memory_alignment_alloca(
-// CHECK: %private_i8 = alloca [4 x i8], align 1
-// CHECK: %private_v2i8 = alloca [4 x <2 x i8>], align 2
-// CHECK: %private_v3i8 = alloca [4 x <3 x i8>], align 4
-// CHECK: %private_v4i8 = alloca [4 x <4 x i8>], align 4
-// CHECK: %private_v8i8 = alloca [4 x <8 x i8>], align 8
-// CHECK: %private_v16i8 = alloca [4 x <16 x i8>], align 16
-// CHECK: %private_i16 = alloca [4 x i16], align 2
-// CHECK: %private_v2i16 = alloca [4 x <2 x i16>], align 4
-// CHECK: %private_v3i16 = alloca [4 x <3 x i16>], align 8
-// CHECK: %private_v4i16 = alloca [4 x <4 x i16>], align 8
-// CHECK: %private_v8i16 = alloca [4 x <8 x i16>], align 16
-// CHECK: %private_v16i16 = alloca [4 x <16 x i16>], align 32
-// CHECK: %private_i32 = alloca [4 x i32], align 4
-// CHECK: %private_v2i32 = alloca [4 x <2 x i32>], align 8
-// CHECK: %private_v3i32 = alloca [4 x <3 x i32>], align 16
-// CHECK: %private_v4i32 = alloca [4 x <4 x i32>], align 16
-// CHECK: %private_v8i32 = alloca [4 x <8 x i32>], align 32
-// CHECK: %private_v16i32 = alloca [4 x <16 x i32>], align 64
-// CHECK: %private_i64 = alloca [4 x i64], align 8
-// CHECK: %private_v2i64 = alloca [4 x <2 x i64>], align 16
-// CHECK: %private_v3i64 = alloca [4 x <3 x i64>], align 32
-// CHECK: %private_v4i64 = alloca [4 x <4 x i64>], align 32
-// CHECK: %private_v8i64 = alloca [4 x <8 x i64>], align 64
-// CHECK: %private_v16i64 = alloca [4 x <16 x i64>], align 128
-// CHECK: %private_f16 = alloca [4 x half], align 2
-// CHECK: %private_v2f16 = alloca [4 x <2 x half>], align 4
-// CHECK: %private_v3f16 = alloca [4 x <3 x half>], align 8
-// CHECK: %private_v4f16 = alloca [4 x <4 x half>], align 8
-// CHECK: %private_v8f16 = alloca [4 x <8 x half>], align 16
-// CHECK: %private_v16f16 = alloca [4 x <16 x half>], align 32
-// CHECK: %private_f32 = alloca [4 x float], align 4
-// CHECK: %private_v2f32 = alloca [4 x <2 x float>], align 8
-// CHECK: %private_v3f32 = alloca [4 x <3 x float>], align 16
-// CHECK: %private_v4f32 = alloca [4 x <4 x float>], align 16
-// CHECK: %private_v8f32 = alloca [4 x <8 x float>], align 32
-// CHECK: %private_v16f32 = alloca [4 x <16 x float>], align 64
-// CHECK: %private_f64 = alloca [4 x double], align 8
-// CHECK: %private_v2f64 = alloca [4 x <2 x double>], align 16
-// CHECK: %private_v3f64 = alloca [4 x <3 x double>], align 32
-// CHECK: %private_v4f64 = alloca [4 x <4 x double>], align 32
-// CHECK: %private_v8f64 = alloca [4 x <8 x double>], align 64
-// CHECK: %private_v16f64 = alloca [4 x <16 x double>], align 128
-
-// CHECK: store volatile i8 0, i8* %arraydecay, align 1
-// CHECK: store volatile <2 x i8> zeroinitializer, <2 x i8>* %arraydecay{{[0-9]+}}, align 2
-// CHECK: store volatile <4 x i8> <i8 0, i8 0, i8 0, i8 undef>, <4 x i8>* %storetmp, align 4
-// CHECK: store volatile <4 x i8> zeroinitializer, <4 x i8>* %arraydecay{{[0-9]+}}, align 4
-// CHECK: store volatile <8 x i8> zeroinitializer, <8 x i8>* %arraydecay{{[0-9]+}}, align 8
-// CHECK: store volatile <16 x i8> zeroinitializer, <16 x i8>* %arraydecay{{[0-9]+}}, align 16
-// CHECK: store volatile i16 0, i16* %arraydecay{{[0-9]+}}, align 2
-// CHECK: store volatile <2 x i16> zeroinitializer, <2 x i16>* %arraydecay{{[0-9]+}}, align 4
-// CHECK: store volatile <4 x i16> <i16 0, i16 0, i16 0, i16 undef>, <4 x i16>* %storetmp{{[0-9]+}}, align 8
-// CHECK: store volatile <4 x i16> zeroinitializer, <4 x i16>* %arraydecay{{[0-9]+}}, align 8
-// CHECK: store volatile <8 x i16> zeroinitializer, <8 x i16>* %arraydecay{{[0-9]+}}, align 16
-// CHECK: store volatile <16 x i16> zeroinitializer, <16 x i16>* %arraydecay{{[0-9]+}}, align 32
-// CHECK: store volatile i32 0, i32* %arraydecay{{[0-9]+}}, align 4
-// CHECK: store volatile <2 x i32> zeroinitializer, <2 x i32>* %arraydecay{{[0-9]+}}, align 8
-// CHECK: store volatile <4 x i32> <i32 0, i32 0, i32 0, i32 undef>, <4 x i32>* %storetmp16, align 16
-// CHECK: store volatile <4 x i32> zeroinitializer, <4 x i32>* %arraydecay{{[0-9]+}}, align 16
-// CHECK: store volatile <8 x i32> zeroinitializer, <8 x i32>* %arraydecay{{[0-9]+}}, align 32
-// CHECK: store volatile <16 x i32> zeroinitializer, <16 x i32>* %arraydecay{{[0-9]+}}, align 64
-// CHECK: store volatile i64 0, i64* %arraydecay{{[0-9]+}}, align 8
-// CHECK: store volatile <2 x i64> zeroinitializer, <2 x i64>* %arraydecay{{[0-9]+}}, align 16
-// CHECK: store volatile <4 x i64> <i64 0, i64 0, i64 0, i64 undef>, <4 x i64>* %storetmp23, align 32
-// CHECK: store volatile <4 x i64> zeroinitializer, <4 x i64>* %arraydecay{{[0-9]+}}, align 32
-// CHECK: store volatile <8 x i64> zeroinitializer, <8 x i64>* %arraydecay{{[0-9]+}}, align 64
-// CHECK: store volatile <16 x i64> zeroinitializer, <16 x i64>* %arraydecay{{[0-9]+}}, align 128
-// CHECK: store volatile half 0xH0000, half* %arraydecay{{[0-9]+}}, align 2
-// CHECK: store volatile <2 x half> zeroinitializer, <2 x half>* %arraydecay{{[0-9]+}}, align 4
-// CHECK: store volatile <4 x half> <half 0xH0000, half 0xH0000, half 0xH0000, half undef>, <4 x half>* %storetmp{{[0-9]+}}, align 8
-// CHECK: store volatile <4 x half> zeroinitializer, <4 x half>* %arraydecay{{[0-9]+}}, align 8
-// CHECK: store volatile <8 x half> zeroinitializer, <8 x half>* %arraydecay{{[0-9]+}}, align 16
-// CHECK: store volatile <16 x half> zeroinitializer, <16 x half>* %arraydecay{{[0-9]+}}, align 32
-// CHECK: store volatile float 0.000000e+00, float* %arraydecay34, align 4
-// CHECK: store volatile <2 x float> zeroinitializer, <2 x float>* %arraydecay{{[0-9]+}}, align 8
-// CHECK: store volatile <4 x float> <float 0.000000e+00, float 0.000000e+00, float 0.000000e+00, float undef>, <4 x float>* %storetmp{{[0-9]+}}, align 16
-// CHECK: store volatile <4 x float> zeroinitializer, <4 x float>* %arraydecay{{[0-9]+}}, align 16
-// CHECK: store volatile <8 x float> zeroinitializer, <8 x float>* %arraydecay{{[0-9]+}}, align 32
-// CHECK: store volatile <16 x float> zeroinitializer, <16 x float>* %arraydecay{{[0-9]+}}, align 64
-// CHECK: store volatile double 0.000000e+00, double* %arraydecay{{[0-9]+}}, align 8
-// CHECK: store volatile <2 x double> zeroinitializer, <2 x double>* %arraydecay{{[0-9]+}}, align 16
-// CHECK: store volatile <4 x double> <double 0.000000e+00, double 0.000000e+00, double 0.000000e+00, double undef>, <4 x double>* %storetmp{{[0-9]+}}, align 32
-// CHECK: store volatile <4 x double> zeroinitializer, <4 x double>* %arraydecay{{[0-9]+}}, align 32
-// CHECK: store volatile <8 x double> zeroinitializer, <8 x double>* %arraydecay{{[0-9]+}}, align 64
-// CHECK: store volatile <16 x double> zeroinitializer, <16 x double>* %arraydecay{{[0-9]+}}, align 128
+// CHECK: %private_i8 = alloca [4 x i8], align 1, addrspace(5)
+// CHECK: %private_v2i8 = alloca [4 x <2 x i8>], align 2, addrspace(5)
+// CHECK: %private_v3i8 = alloca [4 x <3 x i8>], align 4, addrspace(5)
+// CHECK: %private_v4i8 = alloca [4 x <4 x i8>], align 4, addrspace(5)
+// CHECK: %private_v8i8 = alloca [4 x <8 x i8>], align 8, addrspace(5)
+// CHECK: %private_v16i8 = alloca [4 x <16 x i8>], align 16, addrspace(5)
+// CHECK: %private_i16 = alloca [4 x i16], align 2, addrspace(5)
+// CHECK: %private_v2i16 = alloca [4 x <2 x i16>], align 4, addrspace(5)
+// CHECK: %private_v3i16 = alloca [4 x <3 x i16>], align 8, addrspace(5)
+// CHECK: %private_v4i16 = alloca [4 x <4 x i16>], align 8, addrspace(5)
+// CHECK: %private_v8i16 = alloca [4 x <8 x i16>], align 16, addrspace(5)
+// CHECK: %private_v16i16 = alloca [4 x <16 x i16>], align 32, addrspace(5)
+// CHECK: %private_i32 = alloca [4 x i32], align 4, addrspace(5)
+// CHECK: %private_v2i32 = alloca [4 x <2 x i32>], align 8, addrspace(5)
+// CHECK: %private_v3i32 = alloca [4 x <3 x i32>], align 16, addrspace(5)
+// CHECK: %private_v4i32 = alloca [4 x <4 x i32>], align 16, addrspace(5)
+// CHECK: %private_v8i32 = alloca [4 x <8 x i32>], align 32, addrspace(5)
+// CHECK: %private_v16i32 = alloca [4 x <16 x i32>], align 64, addrspace(5)
+// CHECK: %private_i64 = alloca [4 x i64], align 8, addrspace(5)
+// CHECK: %private_v2i64 = alloca [4 x <2 x i64>], align 16, addrspace(5)
+// CHECK: %private_v3i64 = alloca [4 x <3 x i64>], align 32, addrspace(5)
+// CHECK: %private_v4i64 = alloca [4 x <4 x i64>], align 32, addrspace(5)
+// CHECK: %private_v8i64 = alloca [4 x <8 x i64>], align 64, addrspace(5)
+// CHECK: %private_v16i64 = alloca [4 x <16 x i64>], align 128, addrspace(5)
+// CHECK: %private_f16 = alloca [4 x half], align 2, addrspace(5)
+// CHECK: %private_v2f16 = alloca [4 x <2 x half>], align 4, addrspace(5)
+// CHECK: %private_v3f16 = alloca [4 x <3 x half>], align 8, addrspace(5)
+// CHECK: %private_v4f16 = alloca [4 x <4 x half>], align 8, addrspace(5)
+// CHECK: %private_v8f16 = alloca [4 x <8 x half>], align 16, addrspace(5)
+// CHECK: %private_v16f16 = alloca [4 x <16 x half>], align 32, addrspace(5)
+// CHECK: %private_f32 = alloca [4 x float], align 4, addrspace(5)
+// CHECK: %private_v2f32 = alloca [4 x <2 x float>], align 8, addrspace(5)
+// CHECK: %private_v3f32 = alloca [4 x <3 x float>], align 16, addrspace(5)
+// CHECK: %private_v4f32 = alloca [4 x <4 x float>], align 16, addrspace(5)
+// CHECK: %private_v8f32 = alloca [4 x <8 x float>], align 32, addrspace(5)
+// CHECK: %private_v16f32 = alloca [4 x <16 x float>], align 64, addrspace(5)
+// CHECK: %private_f64 = alloca [4 x double], align 8, addrspace(5)
+// CHECK: %private_v2f64 = alloca [4 x <2 x double>], align 16, addrspace(5)
+// CHECK: %private_v3f64 = alloca [4 x <3 x double>], align 32, addrspace(5)
+// CHECK: %private_v4f64 = alloca [4 x <4 x double>], align 32, addrspace(5)
+// CHECK: %private_v8f64 = alloca [4 x <8 x double>], align 64, addrspace(5)
+// CHECK: %private_v16f64 = alloca [4 x <16 x double>], align 128, addrspace(5)
+
+// CHECK: store volatile i8 0, i8 addrspace(5)* %arraydecay, align 1
+// CHECK: store volatile <2 x i8> zeroinitializer, <2 x i8> addrspace(5)* %arraydecay{{[0-9]+}}, align 2
+// CHECK: store volatile <4 x i8> <i8 0, i8 0, i8 0, i8 undef>, <4 x i8> addrspace(5)* %storetmp, align 4
+// CHECK: store volatile <4 x i8> zeroinitializer, <4 x i8> addrspace(5)* %arraydecay{{[0-9]+}}, align 4
+// CHECK: store volatile <8 x i8> zeroinitializer, <8 x i8> addrspace(5)* %arraydecay{{[0-9]+}}, align 8
+// CHECK: store volatile <16 x i8> zeroinitializer, <16 x i8> addrspace(5)* %arraydecay{{[0-9]+}}, align 16
+// CHECK: store volatile i16 0, i16 addrspace(5)* %arraydecay{{[0-9]+}}, align 2
+// CHECK: store volatile <2 x i16> zeroinitializer, <2 x i16> addrspace(5)* %arraydecay{{[0-9]+}}, align 4
+// CHECK: store volatile <4 x i16> <i16 0, i16 0, i16 0, i16 undef>, <4 x i16> addrspace(5)* %storetmp{{[0-9]+}}, align 8
+// CHECK: store volatile <4 x i16> zeroinitializer, <4 x i16> addrspace(5)* %arraydecay{{[0-9]+}}, align 8
+// CHECK: store volatile <8 x i16> zeroinitializer, <8 x i16> addrspace(5)* %arraydecay{{[0-9]+}}, align 16
+// CHECK: store volatile <16 x i16> zeroinitializer, <16 x i16> addrspace(5)* %arraydecay{{[0-9]+}}, align 32
+// CHECK: store volatile i32 0, i32 addrspace(5)* %arraydecay{{[0-9]+}}, align 4
+// CHECK: store volatile <2 x i32> zeroinitializer, <2 x i32> addrspace(5)* %arraydecay{{[0-9]+}}, align 8
+// CHECK: store volatile <4 x i32> <i32 0, i32 0, i32 0, i32 undef>, <4 x i32> addrspace(5)* %storetmp16, align 16
+// CHECK: store volatile <4 x i32> zeroinitializer, <4 x i32> addrspace(5)* %arraydecay{{[0-9]+}}, align 16
+// CHECK: store volatile <8 x i32> zeroinitializer, <8 x i32> addrspace(5)* %arraydecay{{[0-9]+}}, align 32
+// CHECK: store volatile <16 x i32> zeroinitializer, <16 x i32> addrspace(5)* %arraydecay{{[0-9]+}}, align 64
+// CHECK: store volatile i64 0, i64 addrspace(5)* %arraydecay{{[0-9]+}}, align 8
+// CHECK: store volatile <2 x i64> zeroinitializer, <2 x i64> addrspace(5)* %arraydecay{{[0-9]+}}, align 16
+// CHECK: store volatile <4 x i64> <i64 0, i64 0, i64 0, i64 undef>, <4 x i64> addrspace(5)* %storetmp23, align 32
+// CHECK: store volatile <4 x i64> zeroinitializer, <4 x i64> addrspace(5)* %arraydecay{{[0-9]+}}, align 32
+// CHECK: store volatile <8 x i64> zeroinitializer, <8 x i64> addrspace(5)* %arraydecay{{[0-9]+}}, align 64
+// CHECK: store volatile <16 x i64> zeroinitializer, <16 x i64> addrspace(5)* %arraydecay{{[0-9]+}}, align 128
+// CHECK: store volatile half 0xH0000, half addrspace(5)* %arraydecay{{[0-9]+}}, align 2
+// CHECK: store volatile <2 x half> zeroinitializer, <2 x half> addrspace(5)* %arraydecay{{[0-9]+}}, align 4
+// CHECK: store volatile <4 x half> <half 0xH0000, half 0xH0000, half 0xH0000, half undef>, <4 x half> addrspace(5)* %storetmp{{[0-9]+}}, align 8
+// CHECK: store volatile <4 x half> zeroinitializer, <4 x half> addrspace(5)* %arraydecay{{[0-9]+}}, align 8
+// CHECK: store volatile <8 x half> zeroinitializer, <8 x half> addrspace(5)* %arraydecay{{[0-9]+}}, align 16
+// CHECK: store volatile <16 x half> zeroinitializer, <16 x half> addrspace(5)* %arraydecay{{[0-9]+}}, align 32
+// CHECK: store volatile float 0.000000e+00, float addrspace(5)* %arraydecay34, align 4
+// CHECK: store volatile <2 x float> zeroinitializer, <2 x float> addrspace(5)* %arraydecay{{[0-9]+}}, align 8
+// CHECK: store volatile <4 x float> <float 0.000000e+00, float 0.000000e+00, float 0.000000e+00, float undef>, <4 x float> addrspace(5)* %storetmp{{[0-9]+}}, align 16
+// CHECK: store volatile <4 x float> zeroinitializer, <4 x float> addrspace(5)* %arraydecay{{[0-9]+}}, align 16
+// CHECK: store volatile <8 x float> zeroinitializer, <8 x float> addrspace(5)* %arraydecay{{[0-9]+}}, align 32
+// CHECK: store volatile <16 x float> zeroinitializer, <16 x float> addrspace(5)* %arraydecay{{[0-9]+}}, align 64
+// CHECK: store volatile double 0.000000e+00, double addrspace(5)* %arraydecay{{[0-9]+}}, align 8
+// CHECK: store volatile <2 x double> zeroinitializer, <2 x double> addrspace(5)* %arraydecay{{[0-9]+}}, align 16
+// CHECK: store volatile <4 x double> <double 0.000000e+00, double 0.000000e+00, double 0.000000e+00, double undef>, <4 x double> addrspace(5)* %storetmp{{[0-9]+}}, align 32
+// CHECK: store volatile <4 x double> zeroinitializer, <4 x double> addrspace(5)* %arraydecay{{[0-9]+}}, align 32
+// CHECK: store volatile <8 x double> zeroinitializer, <8 x double> addrspace(5)* %arraydecay{{[0-9]+}}, align 64
+// CHECK: store volatile <16 x double> zeroinitializer, <16 x double> addrspace(5)* %arraydecay{{[0-9]+}}, align 128
kernel void private_memory_alignment_alloca()
{
volatile private char private_i8[4];
diff --git a/test/CodeGenOpenCL/amdgpu-attrs.cl b/test/CodeGenOpenCL/amdgpu-attrs.cl
index 2696123f1434..ad13a2cae3c3 100644
--- a/test/CodeGenOpenCL/amdgpu-attrs.cl
+++ b/test/CodeGenOpenCL/amdgpu-attrs.cl
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -triple amdgcn-- -target-cpu tahiti -O0 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -target-cpu tahiti -O0 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple amdgcn-- -target-cpu tahiti -O0 -emit-llvm -o - %s | FileCheck %s -check-prefix=NONAMDHSA
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O0 -emit-llvm -verify -o - %s | FileCheck -check-prefix=X86 %s
__attribute__((amdgpu_flat_work_group_size(0, 0))) // expected-no-diagnostics
@@ -138,12 +139,18 @@ kernel void reqd_work_group_size_32_2_1_flat_work_group_size_16_128() {
// CHECK: define amdgpu_kernel void @reqd_work_group_size_32_2_1_flat_work_group_size_16_128() [[FLAT_WORK_GROUP_SIZE_16_128:#[0-9]+]]
}
+void a_function() {
+// CHECK: define void @a_function() [[A_FUNCTION:#[0-9]+]]
+}
+
// Make sure this is silently accepted on other targets.
// X86-NOT: "amdgpu-flat-work-group-size"
// X86-NOT: "amdgpu-waves-per-eu"
// X86-NOT: "amdgpu-num-vgpr"
// X86-NOT: "amdgpu-num-sgpr"
+// X86-NOT: "amdgpu-implicitarg-num-bytes"
+// NONAMDHSA-NOT: "amdgpu-implicitarg-num-bytes"
// CHECK-NOT: "amdgpu-flat-work-group-size"="0,0"
// CHECK-NOT: "amdgpu-waves-per-eu"="0"
@@ -151,28 +158,30 @@ kernel void reqd_work_group_size_32_2_1_flat_work_group_size_16_128() {
// CHECK-NOT: "amdgpu-num-sgpr"="0"
// CHECK-NOT: "amdgpu-num-vgpr"="0"
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64"
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_64_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="64,64"
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_16_128]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="16,128"
-// CHECK-DAG: attributes [[WAVES_PER_EU_2]] = { convergent noinline nounwind optnone "amdgpu-waves-per-eu"="2"
-// CHECK-DAG: attributes [[WAVES_PER_EU_2_4]] = { convergent noinline nounwind optnone "amdgpu-waves-per-eu"="2,4"
-// CHECK-DAG: attributes [[NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-num-sgpr"="32"
-// CHECK-DAG: attributes [[NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-num-vgpr"="64"
-
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-waves-per-eu"="2"
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-waves-per-eu"="2,4"
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32"
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-vgpr"="64"
-// CHECK-DAG: attributes [[WAVES_PER_EU_2_NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2"
-// CHECK-DAG: attributes [[WAVES_PER_EU_2_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2"
-// CHECK-DAG: attributes [[WAVES_PER_EU_2_4_NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2,4"
-// CHECK-DAG: attributes [[WAVES_PER_EU_2_4_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4"
-// CHECK-DAG: attributes [[NUM_SGPR_32_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64"
-
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2"
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2"
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2,4"
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4"
-
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_SGPR_32_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2"
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_SGPR_32_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4"
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="48"
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_64_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="64,64" "amdgpu-implicitarg-num-bytes"="48"
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_16_128]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="16,128" "amdgpu-implicitarg-num-bytes"="48"
+// CHECK-DAG: attributes [[WAVES_PER_EU_2]] = { convergent noinline nounwind optnone "amdgpu-implicitarg-num-bytes"="48" "amdgpu-waves-per-eu"="2"
+// CHECK-DAG: attributes [[WAVES_PER_EU_2_4]] = { convergent noinline nounwind optnone "amdgpu-implicitarg-num-bytes"="48" "amdgpu-waves-per-eu"="2,4"
+// CHECK-DAG: attributes [[NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-implicitarg-num-bytes"="48" "amdgpu-num-sgpr"="32"
+// CHECK-DAG: attributes [[NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-implicitarg-num-bytes"="48" "amdgpu-num-vgpr"="64"
+
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="48" "amdgpu-waves-per-eu"="2"
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="48" "amdgpu-waves-per-eu"="2,4"
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="48" "amdgpu-num-sgpr"="32"
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="48" "amdgpu-num-vgpr"="64"
+// CHECK-DAG: attributes [[WAVES_PER_EU_2_NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-implicitarg-num-bytes"="48" "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2"
+// CHECK-DAG: attributes [[WAVES_PER_EU_2_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-implicitarg-num-bytes"="48" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2"
+// CHECK-DAG: attributes [[WAVES_PER_EU_2_4_NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-implicitarg-num-bytes"="48" "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2,4"
+// CHECK-DAG: attributes [[WAVES_PER_EU_2_4_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-implicitarg-num-bytes"="48" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4"
+// CHECK-DAG: attributes [[NUM_SGPR_32_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-implicitarg-num-bytes"="48" "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64"
+
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="48" "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2"
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="48" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2"
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="48" "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2,4"
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="48" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4"
+
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_SGPR_32_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="48" "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2"
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_SGPR_32_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="48" "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4"
+
+// CHECK-DAG: attributes [[A_FUNCTION]] = { convergent noinline nounwind optnone "correctly-rounded-divide-sqrt-fp-math"="false"
diff --git a/test/CodeGenOpenCL/amdgpu-debug-info-variable-expression.cl b/test/CodeGenOpenCL/amdgpu-debug-info-variable-expression.cl
index 4d46b40561ee..894611ea88e8 100644
--- a/test/CodeGenOpenCL/amdgpu-debug-info-variable-expression.cl
+++ b/test/CodeGenOpenCL/amdgpu-debug-info-variable-expression.cl
@@ -51,31 +51,31 @@ int *constant FileVar14 = 0;
kernel void kernel1(
// CHECK-DAG: ![[KERNELARG0:[0-9]+]] = !DILocalVariable(name: "KernelArg0", arg: {{[0-9]+}}, scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}})
- // CHECK-DAG: call void @llvm.dbg.declare(metadata i32 addrspace(1)** {{.*}}, metadata ![[KERNELARG0]], metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !{{[0-9]+}}
+ // CHECK-DAG: call void @llvm.dbg.declare(metadata i32 addrspace(1)* addrspace(5)* {{.*}}, metadata ![[KERNELARG0]], metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !{{[0-9]+}}
global int *KernelArg0,
// CHECK-DAG: ![[KERNELARG1:[0-9]+]] = !DILocalVariable(name: "KernelArg1", arg: {{[0-9]+}}, scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}})
- // CHECK-DAG: call void @llvm.dbg.declare(metadata i32 addrspace(2)** {{.*}}, metadata ![[KERNELARG1]], metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !{{[0-9]+}}
+ // CHECK-DAG: call void @llvm.dbg.declare(metadata i32 addrspace(4)* addrspace(5)* {{.*}}, metadata ![[KERNELARG1]], metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !{{[0-9]+}}
constant int *KernelArg1,
// CHECK-DAG: ![[KERNELARG2:[0-9]+]] = !DILocalVariable(name: "KernelArg2", arg: {{[0-9]+}}, scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}})
- // CHECK-DAG: call void @llvm.dbg.declare(metadata i32 addrspace(3)** {{.*}}, metadata ![[KERNELARG2]], metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !{{[0-9]+}}
+ // CHECK-DAG: call void @llvm.dbg.declare(metadata i32 addrspace(3)* addrspace(5)* {{.*}}, metadata ![[KERNELARG2]], metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !{{[0-9]+}}
local int *KernelArg2) {
private int *Tmp0;
int *Tmp1;
// CHECK-DAG: ![[FUNCVAR0:[0-9]+]] = !DILocalVariable(name: "FuncVar0", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}})
- // CHECK-DAG: call void @llvm.dbg.declare(metadata i32 addrspace(1)** {{.*}}, metadata ![[FUNCVAR0]], metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !{{[0-9]+}}
+ // CHECK-DAG: call void @llvm.dbg.declare(metadata i32 addrspace(1)* addrspace(5)* {{.*}}, metadata ![[FUNCVAR0]], metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !{{[0-9]+}}
global int *FuncVar0 = KernelArg0;
// CHECK-DAG: ![[FUNCVAR1:[0-9]+]] = !DILocalVariable(name: "FuncVar1", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}})
- // CHECK-DAG: call void @llvm.dbg.declare(metadata i32 addrspace(2)** {{.*}}, metadata ![[FUNCVAR1]], metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !{{[0-9]+}}
+ // CHECK-DAG: call void @llvm.dbg.declare(metadata i32 addrspace(4)* addrspace(5)* {{.*}}, metadata ![[FUNCVAR1]], metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !{{[0-9]+}}
constant int *FuncVar1 = KernelArg1;
// CHECK-DAG: ![[FUNCVAR2:[0-9]+]] = !DILocalVariable(name: "FuncVar2", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}})
- // CHECK-DAG: call void @llvm.dbg.declare(metadata i32 addrspace(3)** {{.*}}, metadata ![[FUNCVAR2]], metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !{{[0-9]+}}
+ // CHECK-DAG: call void @llvm.dbg.declare(metadata i32 addrspace(3)* addrspace(5)* {{.*}}, metadata ![[FUNCVAR2]], metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !{{[0-9]+}}
local int *FuncVar2 = KernelArg2;
// CHECK-DAG: ![[FUNCVAR3:[0-9]+]] = !DILocalVariable(name: "FuncVar3", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}})
- // CHECK-DAG: call void @llvm.dbg.declare(metadata i32** {{.*}}, metadata ![[FUNCVAR3]], metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !{{[0-9]+}}
+ // CHECK-DAG: call void @llvm.dbg.declare(metadata i32 addrspace(5)* addrspace(5)* {{.*}}, metadata ![[FUNCVAR3]], metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !{{[0-9]+}}
private int *FuncVar3 = Tmp0;
// CHECK-DAG: ![[FUNCVAR4:[0-9]+]] = !DILocalVariable(name: "FuncVar4", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}})
- // CHECK-DAG: call void @llvm.dbg.declare(metadata i32 addrspace(4)** {{.*}}, metadata ![[FUNCVAR4]], metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !{{[0-9]+}}
+ // CHECK-DAG: call void @llvm.dbg.declare(metadata i32* addrspace(5)* {{.*}}, metadata ![[FUNCVAR4]], metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !{{[0-9]+}}
int *FuncVar4 = Tmp1;
// CHECK-DAG: ![[FUNCVAR5:[0-9]+]] = distinct !DIGlobalVariable(name: "FuncVar5", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}}, isLocal: true, isDefinition: true)
@@ -111,18 +111,18 @@ kernel void kernel1(
int *local FuncVar14; FuncVar14 = Tmp1;
// CHECK-DAG: ![[FUNCVAR15:[0-9]+]] = !DILocalVariable(name: "FuncVar15", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}})
- // CHECK-DAG: call void @llvm.dbg.declare(metadata i32 addrspace(1)** {{.*}}, metadata ![[FUNCVAR15]], metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !{{[0-9]+}}
+ // CHECK-DAG: call void @llvm.dbg.declare(metadata i32 addrspace(1)* addrspace(5)* {{.*}}, metadata ![[FUNCVAR15]], metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !{{[0-9]+}}
global int *private FuncVar15 = KernelArg0;
// CHECK-DAG: ![[FUNCVAR16:[0-9]+]] = !DILocalVariable(name: "FuncVar16", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}})
- // CHECK-DAG: call void @llvm.dbg.declare(metadata i32 addrspace(2)** {{.*}}, metadata ![[FUNCVAR16]], metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !{{[0-9]+}}
+ // CHECK-DAG: call void @llvm.dbg.declare(metadata i32 addrspace(4)* addrspace(5)* {{.*}}, metadata ![[FUNCVAR16]], metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !{{[0-9]+}}
constant int *private FuncVar16 = KernelArg1;
// CHECK-DAG: ![[FUNCVAR17:[0-9]+]] = !DILocalVariable(name: "FuncVar17", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}})
- // CHECK-DAG: call void @llvm.dbg.declare(metadata i32 addrspace(3)** {{.*}}, metadata ![[FUNCVAR17]], metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !{{[0-9]+}}
+ // CHECK-DAG: call void @llvm.dbg.declare(metadata i32 addrspace(3)* addrspace(5)* {{.*}}, metadata ![[FUNCVAR17]], metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !{{[0-9]+}}
local int *private FuncVar17 = KernelArg2;
// CHECK-DAG: ![[FUNCVAR18:[0-9]+]] = !DILocalVariable(name: "FuncVar18", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}})
- // CHECK-DAG: call void @llvm.dbg.declare(metadata i32** {{.*}}, metadata ![[FUNCVAR18]], metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !{{[0-9]+}}
+ // CHECK-DAG: call void @llvm.dbg.declare(metadata i32 addrspace(5)* addrspace(5)* {{.*}}, metadata ![[FUNCVAR18]], metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !{{[0-9]+}}
private int *private FuncVar18 = Tmp0;
// CHECK-DAG: ![[FUNCVAR19:[0-9]+]] = !DILocalVariable(name: "FuncVar19", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}})
- // CHECK-DAG: call void @llvm.dbg.declare(metadata i32 addrspace(4)** {{.*}}, metadata ![[FUNCVAR19]], metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !{{[0-9]+}}
+ // CHECK-DAG: call void @llvm.dbg.declare(metadata i32* addrspace(5)* {{.*}}, metadata ![[FUNCVAR19]], metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !{{[0-9]+}}
int *private FuncVar19 = Tmp1;
}
diff --git a/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl b/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl
index b2db4d782719..75fceccb2a45 100644
--- a/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl
+++ b/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl
@@ -1,7 +1,11 @@
-// RUN: %clang_cc1 %s -cl-std=CL2.0 -O0 -emit-llvm -o - -triple amdgcn | FileCheck %s --check-prefix=CHECK
+// RUN: %clang_cc1 %s -cl-std=CL2.0 -O0 -emit-llvm -o - -triple amdgcn | FileCheck %s
typedef struct {int a;} ndrange_t;
+void callee(long id, global long *out) {
+ out[id] = id;
+}
+
// CHECK-LABEL: define amdgpu_kernel void @test
kernel void test(global char *a, char b, global long *c, long d) {
queue_t default_queue;
@@ -24,22 +28,31 @@ kernel void test(global char *a, char b, global long *c, long d) {
c[0] = d;
((local int*)lp)[0] = 1;
}, 100);
+
+ void (^block)(void) = ^{
+ callee(d, c);
+ };
+
+ enqueue_kernel(default_queue, flags, ndrange, block);
}
-// CHECK-LABEL: define internal amdgpu_kernel void @__test_block_invoke_kernel(<{ i32, i32, i8 addrspace(4)*, i8 addrspace(1)*, i8 }>)
+// CHECK-LABEL: define internal amdgpu_kernel void @__test_block_invoke_kernel(<{ i32, i32, i8 addrspace(1)*, i8 }>)
// CHECK-SAME: #[[ATTR:[0-9]+]] !kernel_arg_addr_space !{{.*}} !kernel_arg_access_qual !{{.*}} !kernel_arg_type !{{.*}} !kernel_arg_base_type !{{.*}} !kernel_arg_type_qual !{{.*}}
// CHECK: entry:
-// CHECK: %1 = alloca <{ i32, i32, i8 addrspace(4)*, i8 addrspace(1)*, i8 }>, align 8
-// CHECK: store <{ i32, i32, i8 addrspace(4)*, i8 addrspace(1)*, i8 }> %0, <{ i32, i32, i8 addrspace(4)*, i8 addrspace(1)*, i8 }>* %1, align 8
-// CHECK: %2 = addrspacecast <{ i32, i32, i8 addrspace(4)*, i8 addrspace(1)*, i8 }>* %1 to i8 addrspace(4)*
-// CHECK: call void @__test_block_invoke(i8 addrspace(4)* %2)
+// CHECK: %1 = alloca <{ i32, i32, i8 addrspace(1)*, i8 }>, align 8, addrspace(5)
+// CHECK: store <{ i32, i32, i8 addrspace(1)*, i8 }> %0, <{ i32, i32, i8 addrspace(1)*, i8 }> addrspace(5)* %1, align 8
+// CHECK: %2 = addrspacecast <{ i32, i32, i8 addrspace(1)*, i8 }> addrspace(5)* %1 to i8*
+// CHECK: call void @__test_block_invoke(i8* %2)
// CHECK: ret void
// CHECK:}
-// CHECK-LABEL: define internal amdgpu_kernel void @__test_block_invoke_2_kernel(<{ i32, i32, i8 addrspace(4)*, i8 addrspace(1)*, i64 addrspace(1)*, i64, i8 }>)
+// CHECK-LABEL: define internal amdgpu_kernel void @__test_block_invoke_2_kernel(<{ i32, i32, i8 addrspace(1)*, i64 addrspace(1)*, i64, i8 }>)
+// CHECK-SAME: #[[ATTR]] !kernel_arg_addr_space !{{.*}} !kernel_arg_access_qual !{{.*}} !kernel_arg_type !{{.*}} !kernel_arg_base_type !{{.*}} !kernel_arg_type_qual !{{.*}}
+
+// CHECK-LABEL: define internal amdgpu_kernel void @__test_block_invoke_3_kernel(<{ i32, i32, i8 addrspace(1)*, i64 addrspace(1)*, i64, i8 }>, i8 addrspace(3)*)
// CHECK-SAME: #[[ATTR]] !kernel_arg_addr_space !{{.*}} !kernel_arg_access_qual !{{.*}} !kernel_arg_type !{{.*}} !kernel_arg_base_type !{{.*}} !kernel_arg_type_qual !{{.*}}
-// CHECK-LABEL: define internal amdgpu_kernel void @__test_block_invoke_3_kernel(<{ i32, i32, i8 addrspace(4)*, i8 addrspace(1)*, i64 addrspace(1)*, i64, i8 }>, i8 addrspace(3)*)
+// CHECK-LABEL: define internal amdgpu_kernel void @__test_block_invoke_4_kernel(<{ i32, i32, i64, i64 addrspace(1)* }>)
// CHECK-SAME: #[[ATTR]] !kernel_arg_addr_space !{{.*}} !kernel_arg_access_qual !{{.*}} !kernel_arg_type !{{.*}} !kernel_arg_base_type !{{.*}} !kernel_arg_type_qual !{{.*}}
// CHECK: attributes #[[ATTR]] = { nounwind "enqueued-block" }
diff --git a/test/CodeGenOpenCL/amdgpu-env-amdgcn.cl b/test/CodeGenOpenCL/amdgpu-env-amdgcn.cl
new file mode 100644
index 000000000000..bcb00be8c802
--- /dev/null
+++ b/test/CodeGenOpenCL/amdgpu-env-amdgcn.cl
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 %s -O0 -triple amdgcn -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -O0 -triple amdgcn---opencl -emit-llvm -o - | FileCheck %s
+
+// CHECK: target datalayout = "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-S32-A5"
+void foo(void) {}
diff --git a/test/CodeGenOpenCL/amdgpu-env-amdgiz.cl b/test/CodeGenOpenCL/amdgpu-env-amdgiz.cl
deleted file mode 100644
index 4cb8d95fa098..000000000000
--- a/test/CodeGenOpenCL/amdgpu-env-amdgiz.cl
+++ /dev/null
@@ -1,9 +0,0 @@
-// RUN: %clang_cc1 %s -O0 -triple amdgcn -emit-llvm -o - | FileCheck %s
-// RUN: %clang_cc1 %s -O0 -triple amdgcn---opencl -emit-llvm -o - | FileCheck %s
-// RUN: %clang_cc1 %s -O0 -triple amdgcn---amdgiz -emit-llvm -o - | FileCheck -check-prefix=GIZ %s
-// RUN: %clang_cc1 %s -O0 -triple amdgcn---amdgizcl -emit-llvm -o - | FileCheck -check-prefix=GIZ %s
-
-// CHECK: target datalayout = "e-p:32:32-p1:64:64-p2:64:64-p3:32:32-p4:64:64-p5:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64"
-// GIZ: target datalayout = "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"
-void foo(void) {}
-
diff --git a/test/CodeGenOpenCL/amdgpu-features.cl b/test/CodeGenOpenCL/amdgpu-features.cl
new file mode 100644
index 000000000000..a1815cedcd49
--- /dev/null
+++ b/test/CodeGenOpenCL/amdgpu-features.cl
@@ -0,0 +1,12 @@
+// REQUIRES: amdgpu-registered-target
+
+// Check that appropriate features are defined for every supported AMDGPU
+// "-target" and "-mcpu" options.
+
+// RUN: %clang_cc1 -triple amdgcn -target-cpu gfx904 -S -emit-llvm -o - %s | FileCheck --check-prefix=GFX904 %s
+// RUN: %clang_cc1 -triple amdgcn -target-cpu gfx906 -S -emit-llvm -o - %s | FileCheck --check-prefix=GFX906 %s
+
+// GFX904: "target-features"="+16-bit-insts,+dpp,+fp32-denormals,+fp64-fp16-denormals,+gfx9-insts,+s-memrealtime"
+// GFX906: "target-features"="+16-bit-insts,+dl-insts,+dpp,+fp32-denormals,+fp64-fp16-denormals,+gfx9-insts,+s-memrealtime"
+
+kernel void test() {}
diff --git a/test/CodeGenOpenCL/amdgpu-nullptr.cl b/test/CodeGenOpenCL/amdgpu-nullptr.cl
index 513d56c19d60..688d3a58e90b 100644
--- a/test/CodeGenOpenCL/amdgpu-nullptr.cl
+++ b/test/CodeGenOpenCL/amdgpu-nullptr.cl
@@ -21,48 +21,48 @@ typedef struct {
// Test 0 as initializer.
-// CHECK: @private_p = local_unnamed_addr addrspace(1) global i8* null, align 4
+// CHECK: @private_p = local_unnamed_addr addrspace(1) global i8 addrspace(5)* null, align 4
private char *private_p = 0;
-// CHECK: @local_p = local_unnamed_addr addrspace(1) global i8 addrspace(3)* addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*), align 4
+// CHECK: @local_p = local_unnamed_addr addrspace(1) global i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), align 4
local char *local_p = 0;
// CHECK: @global_p = local_unnamed_addr addrspace(1) global i8 addrspace(1)* null, align 8
global char *global_p = 0;
-// CHECK: @constant_p = local_unnamed_addr addrspace(1) global i8 addrspace(2)* null, align 8
+// CHECK: @constant_p = local_unnamed_addr addrspace(1) global i8 addrspace(4)* null, align 8
constant char *constant_p = 0;
-// CHECK: @generic_p = local_unnamed_addr addrspace(1) global i8 addrspace(4)* null, align 8
+// CHECK: @generic_p = local_unnamed_addr addrspace(1) global i8* null, align 8
generic char *generic_p = 0;
// Test NULL as initializer.
-// CHECK: @private_p_NULL = local_unnamed_addr addrspace(1) global i8* null, align 4
+// CHECK: @private_p_NULL = local_unnamed_addr addrspace(1) global i8 addrspace(5)* null, align 4
private char *private_p_NULL = NULL;
-// CHECK: @local_p_NULL = local_unnamed_addr addrspace(1) global i8 addrspace(3)* addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*), align 4
+// CHECK: @local_p_NULL = local_unnamed_addr addrspace(1) global i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), align 4
local char *local_p_NULL = NULL;
// CHECK: @global_p_NULL = local_unnamed_addr addrspace(1) global i8 addrspace(1)* null, align 8
global char *global_p_NULL = NULL;
-// CHECK: @constant_p_NULL = local_unnamed_addr addrspace(1) global i8 addrspace(2)* null, align 8
+// CHECK: @constant_p_NULL = local_unnamed_addr addrspace(1) global i8 addrspace(4)* null, align 8
constant char *constant_p_NULL = NULL;
-// CHECK: @generic_p_NULL = local_unnamed_addr addrspace(1) global i8 addrspace(4)* null, align 8
+// CHECK: @generic_p_NULL = local_unnamed_addr addrspace(1) global i8* null, align 8
generic char *generic_p_NULL = NULL;
// Test constant folding of null pointer.
// A null pointer should be folded to a null pointer in the target address space.
-// CHECK: @fold_generic = local_unnamed_addr addrspace(1) global i32 addrspace(4)* null, align 8
+// CHECK: @fold_generic = local_unnamed_addr addrspace(1) global i32* null, align 8
generic int *fold_generic = (global int*)(generic float*)(private char*)0;
-// CHECK: @fold_priv = local_unnamed_addr addrspace(1) global i16* null, align 4
+// CHECK: @fold_priv = local_unnamed_addr addrspace(1) global i16 addrspace(5)* null, align 4
private short *fold_priv = (private short*)(generic int*)(global void*)0;
-// CHECK: @fold_priv_arith = local_unnamed_addr addrspace(1) global i8* inttoptr (i32 10 to i8*), align 4
+// CHECK: @fold_priv_arith = local_unnamed_addr addrspace(1) global i8 addrspace(5)* inttoptr (i32 10 to i8 addrspace(5)*), align 4
private char *fold_priv_arith = (private char*)0 + 10;
// CHECK: @fold_int = local_unnamed_addr addrspace(1) global i32 14, align 4
@@ -99,12 +99,12 @@ int fold_int5_local = (int) &((local StructTy1*)0)->p2;
// Test static variable initialization.
-// NOOPT: @test_static_var_private.sp1 = internal addrspace(1) global i8* null, align 4
-// NOOPT: @test_static_var_private.sp2 = internal addrspace(1) global i8* null, align 4
-// NOOPT: @test_static_var_private.sp3 = internal addrspace(1) global i8* null, align 4
-// NOOPT: @test_static_var_private.sp4 = internal addrspace(1) global i8* null, align 4
-// NOOPT: @test_static_var_private.sp5 = internal addrspace(1) global i8* null, align 4
-// NOOPT: @test_static_var_private.SS1 = internal addrspace(1) global %struct.StructTy1 { i8* null, i8 addrspace(3)* addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*), i8 addrspace(2)* null, i8 addrspace(1)* null, i8 addrspace(4)* null }, align 8
+// NOOPT: @test_static_var_private.sp1 = internal addrspace(1) global i8 addrspace(5)* null, align 4
+// NOOPT: @test_static_var_private.sp2 = internal addrspace(1) global i8 addrspace(5)* null, align 4
+// NOOPT: @test_static_var_private.sp3 = internal addrspace(1) global i8 addrspace(5)* null, align 4
+// NOOPT: @test_static_var_private.sp4 = internal addrspace(1) global i8 addrspace(5)* null, align 4
+// NOOPT: @test_static_var_private.sp5 = internal addrspace(1) global i8 addrspace(5)* null, align 4
+// NOOPT: @test_static_var_private.SS1 = internal addrspace(1) global %struct.StructTy1 { i8 addrspace(5)* null, i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), i8 addrspace(4)* null, i8 addrspace(1)* null, i8* null }, align 8
// NOOPT: @test_static_var_private.SS2 = internal addrspace(1) global %struct.StructTy2 zeroinitializer, align 8
void test_static_var_private(void) {
@@ -118,12 +118,12 @@ void test_static_var_private(void) {
static StructTy2 SS2;
}
-// NOOPT: @test_static_var_local.sp1 = internal addrspace(1) global i8 addrspace(3)* addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*), align 4
-// NOOPT: @test_static_var_local.sp2 = internal addrspace(1) global i8 addrspace(3)* addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*), align 4
-// NOOPT: @test_static_var_local.sp3 = internal addrspace(1) global i8 addrspace(3)* addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*), align 4
+// NOOPT: @test_static_var_local.sp1 = internal addrspace(1) global i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), align 4
+// NOOPT: @test_static_var_local.sp2 = internal addrspace(1) global i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), align 4
+// NOOPT: @test_static_var_local.sp3 = internal addrspace(1) global i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), align 4
// NOOPT: @test_static_var_local.sp4 = internal addrspace(1) global i8 addrspace(3)* null, align 4
// NOOPT: @test_static_var_local.sp5 = internal addrspace(1) global i8 addrspace(3)* null, align 4
-// NOOPT: @test_static_var_local.SS1 = internal addrspace(1) global %struct.StructTy1 { i8* null, i8 addrspace(3)* addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*), i8 addrspace(2)* null, i8 addrspace(1)* null, i8 addrspace(4)* null }, align 8
+// NOOPT: @test_static_var_local.SS1 = internal addrspace(1) global %struct.StructTy1 { i8 addrspace(5)* null, i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), i8 addrspace(4)* null, i8 addrspace(1)* null, i8* null }, align 8
// NOOPT: @test_static_var_local.SS2 = internal addrspace(1) global %struct.StructTy2 zeroinitializer, align 8
void test_static_var_local(void) {
static local char *sp1 = 0;
@@ -138,14 +138,14 @@ void test_static_var_local(void) {
// Test function-scope variable initialization.
// NOOPT-LABEL: @test_func_scope_var_private(
-// NOOPT: store i8* null, i8** %sp1, align 4
-// NOOPT: store i8* null, i8** %sp2, align 4
-// NOOPT: store i8* null, i8** %sp3, align 4
-// NOOPT: store i8* null, i8** %sp4, align 4
-// NOOPT: %[[SS1:.*]] = bitcast %struct.StructTy1* %SS1 to i8*
-// NOOPT: call void @llvm.memcpy.p0i8.p2i8.i64(i8* %[[SS1]], i8 addrspace(2)* bitcast (%struct.StructTy1 addrspace(2)* @test_func_scope_var_private.SS1 to i8 addrspace(2)*), i64 32, i32 8, i1 false)
-// NOOPT: %[[SS2:.*]] = bitcast %struct.StructTy2* %SS2 to i8*
-// NOOPT: call void @llvm.memset.p0i8.i64(i8* %[[SS2]], i8 0, i64 24, i32 8, i1 false)
+// NOOPT: store i8 addrspace(5)* null, i8 addrspace(5)* addrspace(5)* %sp1, align 4
+// NOOPT: store i8 addrspace(5)* null, i8 addrspace(5)* addrspace(5)* %sp2, align 4
+// NOOPT: store i8 addrspace(5)* null, i8 addrspace(5)* addrspace(5)* %sp3, align 4
+// NOOPT: store i8 addrspace(5)* null, i8 addrspace(5)* addrspace(5)* %sp4, align 4
+// NOOPT: %[[SS1:.*]] = bitcast %struct.StructTy1 addrspace(5)* %SS1 to i8 addrspace(5)*
+// NOOPT: call void @llvm.memcpy.p5i8.p4i8.i64(i8 addrspace(5)* align 8 %[[SS1]], i8 addrspace(4)* align 8 bitcast (%struct.StructTy1 addrspace(4)* @test_func_scope_var_private.SS1 to i8 addrspace(4)*), i64 32, i1 false)
+// NOOPT: %[[SS2:.*]] = bitcast %struct.StructTy2 addrspace(5)* %SS2 to i8 addrspace(5)*
+// NOOPT: call void @llvm.memset.p5i8.i64(i8 addrspace(5)* align 8 %[[SS2]], i8 0, i64 24, i1 false)
void test_func_scope_var_private(void) {
private char *sp1 = 0;
private char *sp2 = NULL;
@@ -158,14 +158,14 @@ void test_func_scope_var_private(void) {
// Test function-scope variable initialization.
// NOOPT-LABEL: @test_func_scope_var_local(
-// NOOPT: store i8 addrspace(3)* addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*), i8 addrspace(3)** %sp1, align 4
-// NOOPT: store i8 addrspace(3)* addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*), i8 addrspace(3)** %sp2, align 4
-// NOOPT: store i8 addrspace(3)* null, i8 addrspace(3)** %sp3, align 4
-// NOOPT: store i8 addrspace(3)* null, i8 addrspace(3)** %sp4, align 4
-// NOOPT: %[[SS1:.*]] = bitcast %struct.StructTy1* %SS1 to i8*
-// NOOPT: call void @llvm.memcpy.p0i8.p2i8.i64(i8* %[[SS1]], i8 addrspace(2)* bitcast (%struct.StructTy1 addrspace(2)* @test_func_scope_var_local.SS1 to i8 addrspace(2)*), i64 32, i32 8, i1 false)
-// NOOPT: %[[SS2:.*]] = bitcast %struct.StructTy2* %SS2 to i8*
-// NOOPT: call void @llvm.memset.p0i8.i64(i8* %[[SS2]], i8 0, i64 24, i32 8, i1 false)
+// NOOPT: store i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), i8 addrspace(3)* addrspace(5)* %sp1, align 4
+// NOOPT: store i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), i8 addrspace(3)* addrspace(5)* %sp2, align 4
+// NOOPT: store i8 addrspace(3)* null, i8 addrspace(3)* addrspace(5)* %sp3, align 4
+// NOOPT: store i8 addrspace(3)* null, i8 addrspace(3)* addrspace(5)* %sp4, align 4
+// NOOPT: %[[SS1:.*]] = bitcast %struct.StructTy1 addrspace(5)* %SS1 to i8 addrspace(5)*
+// NOOPT: call void @llvm.memcpy.p5i8.p4i8.i64(i8 addrspace(5)* align 8 %[[SS1]], i8 addrspace(4)* align 8 bitcast (%struct.StructTy1 addrspace(4)* @test_func_scope_var_local.SS1 to i8 addrspace(4)*), i64 32, i1 false)
+// NOOPT: %[[SS2:.*]] = bitcast %struct.StructTy2 addrspace(5)* %SS2 to i8 addrspace(5)*
+// NOOPT: call void @llvm.memset.p5i8.i64(i8 addrspace(5)* align 8 %[[SS2]], i8 0, i64 24, i1 false)
void test_func_scope_var_local(void) {
local char *sp1 = 0;
local char *sp2 = NULL;
@@ -183,31 +183,31 @@ void test_func_scope_var_local(void) {
// cannot have common linkage since common linkage requires zero initialization
// and does not have explicit section.
-// CHECK: @p1 = common local_unnamed_addr addrspace(1) global i8* null, align 4
+// CHECK: @p1 = common local_unnamed_addr addrspace(1) global i8 addrspace(5)* null, align 4
private char *p1;
-// CHECK: @p2 = weak local_unnamed_addr addrspace(1) global i8 addrspace(3)* addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*), align 4
+// CHECK: @p2 = weak local_unnamed_addr addrspace(1) global i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), align 4
local char *p2;
-// CHECK: @p3 = common local_unnamed_addr addrspace(1) global i8 addrspace(2)* null, align 8
+// CHECK: @p3 = common local_unnamed_addr addrspace(1) global i8 addrspace(4)* null, align 8
constant char *p3;
// CHECK: @p4 = common local_unnamed_addr addrspace(1) global i8 addrspace(1)* null, align 8
global char *p4;
-// CHECK: @p5 = common local_unnamed_addr addrspace(1) global i8 addrspace(4)* null, align 8
+// CHECK: @p5 = common local_unnamed_addr addrspace(1) global i8* null, align 8
generic char *p5;
-// Test default initialization of sturcture.
+// Test default initialization of structure.
-// CHECK: @S1 = weak local_unnamed_addr addrspace(1) global %struct.StructTy1 { i8* null, i8 addrspace(3)* addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*), i8 addrspace(2)* null, i8 addrspace(1)* null, i8 addrspace(4)* null }, align 8
+// CHECK: @S1 = weak local_unnamed_addr addrspace(1) global %struct.StructTy1 { i8 addrspace(5)* null, i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), i8 addrspace(4)* null, i8 addrspace(1)* null, i8* null }, align 8
StructTy1 S1;
// CHECK: @S2 = common local_unnamed_addr addrspace(1) global %struct.StructTy2 zeroinitializer, align 8
StructTy2 S2;
// Test default initialization of array.
-// CHECK: @A1 = weak local_unnamed_addr addrspace(1) global [2 x %struct.StructTy1] [%struct.StructTy1 { i8* null, i8 addrspace(3)* addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*), i8 addrspace(2)* null, i8 addrspace(1)* null, i8 addrspace(4)* null }, %struct.StructTy1 { i8* null, i8 addrspace(3)* addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*), i8 addrspace(2)* null, i8 addrspace(1)* null, i8 addrspace(4)* null }], align 8
+// CHECK: @A1 = weak local_unnamed_addr addrspace(1) global [2 x %struct.StructTy1] [%struct.StructTy1 { i8 addrspace(5)* null, i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), i8 addrspace(4)* null, i8 addrspace(1)* null, i8* null }, %struct.StructTy1 { i8 addrspace(5)* null, i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), i8 addrspace(4)* null, i8 addrspace(1)* null, i8* null }], align 8
StructTy1 A1[2];
// CHECK: @A2 = common local_unnamed_addr addrspace(1) global [2 x %struct.StructTy2] zeroinitializer, align 8
@@ -216,14 +216,14 @@ StructTy2 A2[2];
// Test comparison with 0.
// CHECK-LABEL: cmp_private
-// CHECK: icmp eq i8* %p, null
+// CHECK: icmp eq i8 addrspace(5)* %p, null
void cmp_private(private char* p) {
if (p != 0)
*p = 0;
}
// CHECK-LABEL: cmp_local
-// CHECK: icmp eq i8 addrspace(3)* %p, addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*)
+// CHECK: icmp eq i8 addrspace(3)* %p, addrspacecast (i8* null to i8 addrspace(3)*)
void cmp_local(local char* p) {
if (p != 0)
*p = 0;
@@ -237,7 +237,7 @@ void cmp_global(global char* p) {
}
// CHECK-LABEL: cmp_constant
-// CHECK: icmp eq i8 addrspace(2)* %p, null
+// CHECK: icmp eq i8 addrspace(4)* %p, null
char cmp_constant(constant char* p) {
if (p != 0)
return *p;
@@ -246,7 +246,7 @@ char cmp_constant(constant char* p) {
}
// CHECK-LABEL: cmp_generic
-// CHECK: icmp eq i8 addrspace(4)* %p, null
+// CHECK: icmp eq i8* %p, null
void cmp_generic(generic char* p) {
if (p != 0)
*p = 0;
@@ -255,14 +255,14 @@ void cmp_generic(generic char* p) {
// Test comparison with NULL.
// CHECK-LABEL: cmp_NULL_private
-// CHECK: icmp eq i8* %p, null
+// CHECK: icmp eq i8 addrspace(5)* %p, null
void cmp_NULL_private(private char* p) {
if (p != NULL)
*p = 0;
}
// CHECK-LABEL: cmp_NULL_local
-// CHECK: icmp eq i8 addrspace(3)* %p, addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*)
+// CHECK: icmp eq i8 addrspace(3)* %p, addrspacecast (i8* null to i8 addrspace(3)*)
void cmp_NULL_local(local char* p) {
if (p != NULL)
*p = 0;
@@ -276,7 +276,7 @@ void cmp_NULL_global(global char* p) {
}
// CHECK-LABEL: cmp_NULL_constant
-// CHECK: icmp eq i8 addrspace(2)* %p, null
+// CHECK: icmp eq i8 addrspace(4)* %p, null
char cmp_NULL_constant(constant char* p) {
if (p != NULL)
return *p;
@@ -285,7 +285,7 @@ char cmp_NULL_constant(constant char* p) {
}
// CHECK-LABEL: cmp_NULL_generic
-// CHECK: icmp eq i8 addrspace(4)* %p, null
+// CHECK: icmp eq i8* %p, null
void cmp_NULL_generic(generic char* p) {
if (p != NULL)
*p = 0;
@@ -293,11 +293,11 @@ void cmp_NULL_generic(generic char* p) {
// Test storage 0 as null pointer.
// CHECK-LABEL: test_storage_null_pointer
-// CHECK: store i8* null, i8* addrspace(4)* %arg_private
-// CHECK: store i8 addrspace(3)* addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*), i8 addrspace(3)* addrspace(4)* %arg_local
-// CHECK: store i8 addrspace(1)* null, i8 addrspace(1)* addrspace(4)* %arg_global
-// CHECK: store i8 addrspace(2)* null, i8 addrspace(2)* addrspace(4)* %arg_constant
-// CHECK: store i8 addrspace(4)* null, i8 addrspace(4)* addrspace(4)* %arg_generic
+// CHECK: store i8 addrspace(5)* null, i8 addrspace(5)** %arg_private
+// CHECK: store i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), i8 addrspace(3)** %arg_local
+// CHECK: store i8 addrspace(1)* null, i8 addrspace(1)** %arg_global
+// CHECK: store i8 addrspace(4)* null, i8 addrspace(4)** %arg_constant
+// CHECK: store i8* null, i8** %arg_generic
void test_storage_null_pointer(private char** arg_private,
local char** arg_local,
global char** arg_global,
@@ -312,11 +312,11 @@ void test_storage_null_pointer(private char** arg_private,
// Test storage NULL as null pointer.
// CHECK-LABEL: test_storage_null_pointer_NULL
-// CHECK: store i8* null, i8* addrspace(4)* %arg_private
-// CHECK: store i8 addrspace(3)* addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*), i8 addrspace(3)* addrspace(4)* %arg_local
-// CHECK: store i8 addrspace(1)* null, i8 addrspace(1)* addrspace(4)* %arg_global
-// CHECK: store i8 addrspace(2)* null, i8 addrspace(2)* addrspace(4)* %arg_constant
-// CHECK: store i8 addrspace(4)* null, i8 addrspace(4)* addrspace(4)* %arg_generic
+// CHECK: store i8 addrspace(5)* null, i8 addrspace(5)** %arg_private
+// CHECK: store i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), i8 addrspace(3)** %arg_local
+// CHECK: store i8 addrspace(1)* null, i8 addrspace(1)** %arg_global
+// CHECK: store i8 addrspace(4)* null, i8 addrspace(4)** %arg_constant
+// CHECK: store i8* null, i8** %arg_generic
void test_storage_null_pointer_NULL(private char** arg_private,
local char** arg_local,
global char** arg_global,
@@ -337,8 +337,8 @@ void test_pass_null_pointer_arg_calee(private char* arg_private,
generic char* arg_generic);
// CHECK-LABEL: test_pass_null_pointer_arg
-// CHECK: call void @test_pass_null_pointer_arg_calee(i8* null, i8 addrspace(3)* addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*), i8 addrspace(1)* null, i8 addrspace(2)* null, i8 addrspace(4)* null)
-// CHECK: call void @test_pass_null_pointer_arg_calee(i8* null, i8 addrspace(3)* addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*), i8 addrspace(1)* null, i8 addrspace(2)* null, i8 addrspace(4)* null)
+// CHECK: call void @test_pass_null_pointer_arg_calee(i8 addrspace(5)* null, i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), i8 addrspace(1)* null, i8 addrspace(4)* null, i8* null)
+// CHECK: call void @test_pass_null_pointer_arg_calee(i8 addrspace(5)* null, i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), i8 addrspace(1)* null, i8 addrspace(4)* null, i8* null)
void test_pass_null_pointer_arg(void) {
test_pass_null_pointer_arg_calee(0, 0, 0, 0, 0);
test_pass_null_pointer_arg_calee(NULL, NULL, NULL, NULL, NULL);
@@ -352,8 +352,8 @@ void test_cast_null_pointer_to_sizet_calee(size_t arg_private,
size_t arg_generic);
// CHECK-LABEL: test_cast_null_pointer_to_sizet
-// CHECK: call void @test_cast_null_pointer_to_sizet_calee(i64 0, i64 ptrtoint (i8 addrspace(3)* addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*) to i64), i64 0, i64 0, i64 0)
-// CHECK: call void @test_cast_null_pointer_to_sizet_calee(i64 0, i64 ptrtoint (i8 addrspace(3)* addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*) to i64), i64 0, i64 0, i64 0)
+// CHECK: call void @test_cast_null_pointer_to_sizet_calee(i64 0, i64 ptrtoint (i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*) to i64), i64 0, i64 0, i64 0)
+// CHECK: call void @test_cast_null_pointer_to_sizet_calee(i64 0, i64 ptrtoint (i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*) to i64), i64 0, i64 0, i64 0)
void test_cast_null_pointer_to_sizet(void) {
test_cast_null_pointer_to_sizet_calee((size_t)((private char*)0),
(size_t)((local char*)0),
@@ -367,7 +367,7 @@ void test_cast_null_pointer_to_sizet(void) {
(size_t)((generic char*)NULL));
}
-// Test comparision between null pointers.
+// Test comparison between null pointers.
#define TEST_EQ00(addr1, addr2) int test_eq00_##addr1##_##addr2(void) { return (addr1 char*)0 == (addr2 char*)0; }
#define TEST_EQ0N(addr1, addr2) int test_eq0N_##addr1##_##addr2(void) { return (addr1 char*)0 == (addr2 char*)NULL; }
#define TEST_EQN0(addr1, addr2) int test_eqN0_##addr1##_##addr2(void) { return (addr1 char*)NULL == (addr2 char*)0; }
@@ -465,14 +465,14 @@ TEST_EQ00(constant, constant)
// Test cast to bool.
// CHECK-LABEL: cast_bool_private
-// CHECK: icmp eq i8* %p, null
+// CHECK: icmp eq i8 addrspace(5)* %p, null
void cast_bool_private(private char* p) {
if (p)
*p = 0;
}
// CHECK-LABEL: cast_bool_local
-// CHECK: icmp eq i8 addrspace(3)* %p, addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*)
+// CHECK: icmp eq i8 addrspace(3)* %p, addrspacecast (i8* null to i8 addrspace(3)*)
void cast_bool_local(local char* p) {
if (p)
*p = 0;
@@ -486,7 +486,7 @@ void cast_bool_global(global char* p) {
}
// CHECK-LABEL: cast_bool_constant
-// CHECK: icmp eq i8 addrspace(2)* %p, null
+// CHECK: icmp eq i8 addrspace(4)* %p, null
char cast_bool_constant(constant char* p) {
if (p)
return *p;
@@ -495,7 +495,7 @@ char cast_bool_constant(constant char* p) {
}
// CHECK-LABEL: cast_bool_generic
-// CHECK: icmp eq i8 addrspace(4)* %p, null
+// CHECK: icmp eq i8* %p, null
void cast_bool_generic(generic char* p) {
if (p)
*p = 0;
@@ -510,7 +510,7 @@ typedef struct {
} StructTy3;
// CHECK-LABEL: test_memset_private
-// CHECK: call void @llvm.memset.p0i8.i64(i8* nonnull {{.*}}, i8 0, i64 40, i32 8, i1 false)
+// CHECK: call void @llvm.memset.p5i8.i64(i8 addrspace(5)* align 8 {{.*}}, i8 0, i64 40, i1 false)
void test_memset_private(private StructTy3 *ptr) {
StructTy3 S3 = {0, 0, 0, 0, 0};
*ptr = S3;
@@ -520,13 +520,13 @@ void test_memset_private(private StructTy3 *ptr) {
// A 0 literal casted to pointer should become a null pointer.
// CHECK-LABEL: test_cast_0_to_local_ptr
-// CHECK: ret i32 addrspace(3)* addrspacecast (i32 addrspace(4)* null to i32 addrspace(3)*)
+// CHECK: ret i32 addrspace(3)* addrspacecast (i32* null to i32 addrspace(3)*)
local int* test_cast_0_to_local_ptr(void) {
return (local int*)0;
}
// CHECK-LABEL: test_cast_0_to_private_ptr
-// CHECK: ret i32* null
+// CHECK: ret i32 addrspace(5)* null
private int* test_cast_0_to_private_ptr(void) {
return (private int*)0;
}
@@ -536,7 +536,7 @@ private int* test_cast_0_to_private_ptr(void) {
// zero value.
// CHECK-LABEL: test_cast_int_to_ptr1_private
-// CHECK: ret i32* null
+// CHECK: ret i32 addrspace(5)* null
private int* test_cast_int_to_ptr1_private(void) {
return (private int*)((void)0, 0);
}
@@ -548,7 +548,7 @@ local int* test_cast_int_to_ptr1_local(void) {
}
// CHECK-LABEL: test_cast_int_to_ptr2
-// CHECK: ret i32* null
+// CHECK: ret i32 addrspace(5)* null
private int* test_cast_int_to_ptr2(void) {
int x = 0;
return (private int*)x;
@@ -568,7 +568,7 @@ int test_and_nullptr(int a) {
}
// CHECK-LABEL: test_not_private_ptr
-// CHECK: %[[lnot:.*]] = icmp eq i8* %p, null
+// CHECK: %[[lnot:.*]] = icmp eq i8 addrspace(5)* %p, null
// CHECK: %[[lnot_ext:.*]] = zext i1 %[[lnot]] to i32
// CHECK: ret i32 %[[lnot_ext]]
int test_not_private_ptr(private char* p) {
@@ -576,7 +576,7 @@ int test_not_private_ptr(private char* p) {
}
// CHECK-LABEL: test_not_local_ptr
-// CHECK: %[[lnot:.*]] = icmp eq i8 addrspace(3)* %p, addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*)
+// CHECK: %[[lnot:.*]] = icmp eq i8 addrspace(3)* %p, addrspacecast (i8* null to i8 addrspace(3)*)
// CHECK: %[[lnot_ext:.*]] = zext i1 %[[lnot]] to i32
// CHECK: ret i32 %[[lnot_ext]]
int test_not_local_ptr(local char* p) {
@@ -585,8 +585,8 @@ int test_not_local_ptr(local char* p) {
// CHECK-LABEL: test_and_ptr
-// CHECK: %[[tobool:.*]] = icmp ne i8* %p1, null
-// CHECK: %[[tobool1:.*]] = icmp ne i8 addrspace(3)* %p2, addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*)
+// CHECK: %[[tobool:.*]] = icmp ne i8 addrspace(5)* %p1, null
+// CHECK: %[[tobool1:.*]] = icmp ne i8 addrspace(3)* %p2, addrspacecast (i8* null to i8 addrspace(3)*)
// CHECK: %[[res:.*]] = and i1 %[[tobool]], %[[tobool1]]
// CHECK: %[[land_ext:.*]] = zext i1 %[[res]] to i32
// CHECK: ret i32 %[[land_ext]]
@@ -597,7 +597,7 @@ int test_and_ptr(private char* p1, local char* p2) {
// Test folding of null pointer in function scope.
// NOOPT-LABEL: test_fold_private
// NOOPT: call void @test_fold_callee
-// NOOPT: store i32 addrspace(1)* null, i32 addrspace(1)** %glob, align 8
+// NOOPT: store i32 addrspace(1)* null, i32 addrspace(1)* addrspace(5)* %glob, align 8
// NOOPT: %{{.*}} = sub i64 %{{.*}}, 0
// NOOPT: call void @test_fold_callee
// NOOPT: %{{.*}} = add nsw i64 %{{.*}}, 0
@@ -612,10 +612,10 @@ void test_fold_private(void) {
// NOOPT-LABEL: test_fold_local
// NOOPT: call void @test_fold_callee
-// NOOPT: store i32 addrspace(1)* null, i32 addrspace(1)** %glob, align 8
+// NOOPT: store i32 addrspace(1)* null, i32 addrspace(1)* addrspace(5)* %glob, align 8
// NOOPT: %{{.*}} = sub i64 %{{.*}}, 0
// NOOPT: call void @test_fold_callee
-// NOOPT: %{{.*}} = add nsw i64 %{{.*}}, sext (i32 ptrtoint (i32 addrspace(3)* addrspacecast (i32 addrspace(4)* null to i32 addrspace(3)*) to i32) to i64)
+// NOOPT: %{{.*}} = add nsw i64 %{{.*}}, sext (i32 ptrtoint (i32 addrspace(3)* addrspacecast (i32* null to i32 addrspace(3)*) to i32) to i64)
// NOOPT: %{{.*}} = sub nsw i64 %{{.*}}, 1
void test_fold_local(void) {
global int* glob = (test_fold_callee(), (global int*)(generic char*)0);
diff --git a/test/CodeGenOpenCL/blocks.cl b/test/CodeGenOpenCL/blocks.cl
index 146d9dc113a8..0e125fd703f5 100644
--- a/test/CodeGenOpenCL/blocks.cl
+++ b/test/CodeGenOpenCL/blocks.cl
@@ -1,12 +1,11 @@
// RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-llvm -o - -O0 -triple spir-unknown-unknown | FileCheck -check-prefixes=COMMON,SPIR %s
-// RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-llvm -o - -O0 -triple amdgcn-amd-amdhsa-opencl | FileCheck -check-prefixes=COMMON,AMD %s
+// RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-llvm -o - -O0 -triple amdgcn-amd-amdhsa | FileCheck -check-prefixes=COMMON,AMDGCN %s
-// COMMON: %struct.__opencl_block_literal_generic = type { i32, i32, i8 addrspace(4)* }
-// SPIR: @__block_literal_global = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 12, i32 4, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* @block_A_block_invoke to i8*) to i8 addrspace(4)*) }
-// AMD: @__block_literal_global = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 16, i32 8, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* @block_A_block_invoke to i8*) to i8 addrspace(4)*) }
+// COMMON: @__block_literal_global = internal addrspace(1) constant { i32, i32 } { i32 8, i32 4 }
// COMMON-NOT: .str
-// COMMON-LABEL: define internal {{.*}}void @block_A_block_invoke(i8 addrspace(4)* %.block_descriptor, i8 addrspace(3)* %a)
+// SPIR-LABEL: define internal {{.*}}void @block_A_block_invoke(i8 addrspace(4)* %.block_descriptor, i8 addrspace(3)* %a)
+// AMDGCN-LABEL: define internal {{.*}}void @block_A_block_invoke(i8* %.block_descriptor, i8 addrspace(3)* %a)
void (^block_A)(local void *) = ^(local void *a) {
return;
};
@@ -18,27 +17,32 @@ void foo(){
// COMMON-NOT: %block.flags
// COMMON-NOT: %block.reserved
// COMMON-NOT: %block.descriptor
- // COMMON: %[[block_size:.*]] = getelementptr inbounds <{ i32, i32, i8 addrspace(4)*, i32 }>, <{ i32, i32, i8 addrspace(4)*, i32 }>* %block, i32 0, i32 0
- // SPIR: store i32 16, i32* %[[block_size]]
- // AMD: store i32 20, i32* %[[block_size]]
- // COMMON: %[[block_align:.*]] = getelementptr inbounds <{ i32, i32, i8 addrspace(4)*, i32 }>, <{ i32, i32, i8 addrspace(4)*, i32 }>* %block, i32 0, i32 1
+ // SPIR: %[[block_size:.*]] = getelementptr inbounds <{ i32, i32, i32 }>, <{ i32, i32, i32 }>* %[[block:.*]], i32 0, i32 0
+ // AMDGCN: %[[block_size:.*]] = getelementptr inbounds <{ i32, i32, i32 }>, <{ i32, i32, i32 }> addrspace(5)* %[[block:.*]], i32 0, i32 0
+ // SPIR: store i32 12, i32* %[[block_size]]
+ // AMDGCN: store i32 12, i32 addrspace(5)* %[[block_size]]
+ // SPIR: %[[block_align:.*]] = getelementptr inbounds <{ i32, i32, i32 }>, <{ i32, i32, i32 }>* %[[block]], i32 0, i32 1
+ // AMDGCN: %[[block_align:.*]] = getelementptr inbounds <{ i32, i32, i32 }>, <{ i32, i32, i32 }> addrspace(5)* %[[block]], i32 0, i32 1
// SPIR: store i32 4, i32* %[[block_align]]
- // AMD: store i32 8, i32* %[[block_align]]
- // COMMON: %[[block_invoke:.*]] = getelementptr inbounds <{ i32, i32, i8 addrspace(4)*, i32 }>, <{ i32, i32, i8 addrspace(4)*, i32 }>* %[[block:.*]], i32 0, i32 2
- // COMMON: store i8 addrspace(4)* addrspacecast (i8* bitcast (i32 (i8 addrspace(4)*)* @__foo_block_invoke to i8*) to i8 addrspace(4)*), i8 addrspace(4)** %[[block_invoke]]
- // COMMON: %[[block_captured:.*]] = getelementptr inbounds <{ i32, i32, i8 addrspace(4)*, i32 }>, <{ i32, i32, i8 addrspace(4)*, i32 }>* %[[block]], i32 0, i32 3
- // COMMON: %[[i_value:.*]] = load i32, i32* %i
- // COMMON: store i32 %[[i_value]], i32* %[[block_captured]],
- // COMMON: %[[blk_ptr:.*]] = bitcast <{ i32, i32, i8 addrspace(4)*, i32 }>* %[[block]] to i32 ()*
- // COMMON: %[[blk_gen_ptr:.*]] = addrspacecast i32 ()* %[[blk_ptr]] to i32 () addrspace(4)*
- // COMMON: store i32 () addrspace(4)* %[[blk_gen_ptr]], i32 () addrspace(4)** %[[block_B:.*]],
- // COMMON: %[[blk_gen_ptr:.*]] = load i32 () addrspace(4)*, i32 () addrspace(4)** %[[block_B]]
- // COMMON: %[[block_literal:.*]] = bitcast i32 () addrspace(4)* %[[blk_gen_ptr]] to %struct.__opencl_block_literal_generic addrspace(4)*
- // COMMON: %[[invoke_addr:.*]] = getelementptr inbounds %struct.__opencl_block_literal_generic, %struct.__opencl_block_literal_generic addrspace(4)* %[[block_literal]], i32 0, i32 2
- // COMMON: %[[blk_gen_ptr:.*]] = bitcast %struct.__opencl_block_literal_generic addrspace(4)* %[[block_literal]] to i8 addrspace(4)*
- // COMMON: %[[invoke_func_ptr:.*]] = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %[[invoke_addr]]
- // COMMON: %[[invoke_func:.*]] = addrspacecast i8 addrspace(4)* %[[invoke_func_ptr]] to i32 (i8 addrspace(4)*)*
- // COMMON: call {{.*}}i32 %[[invoke_func]](i8 addrspace(4)* %[[blk_gen_ptr]])
+ // AMDGCN: store i32 4, i32 addrspace(5)* %[[block_align]]
+ // SPIR: %[[block_captured:.*]] = getelementptr inbounds <{ i32, i32, i32 }>, <{ i32, i32, i32 }>* %[[block]], i32 0, i32 2
+ // SPIR: %[[i_value:.*]] = load i32, i32* %i
+ // SPIR: store i32 %[[i_value]], i32* %[[block_captured]],
+ // SPIR: %[[blk_ptr:.*]] = bitcast <{ i32, i32, i32 }>* %[[block]] to i32 ()*
+ // SPIR: %[[blk_gen_ptr:.*]] = addrspacecast i32 ()* %[[blk_ptr]] to i32 () addrspace(4)*
+ // SPIR: store i32 () addrspace(4)* %[[blk_gen_ptr]], i32 () addrspace(4)** %[[block_B:.*]],
+ // SPIR: %[[block_literal:.*]] = load i32 () addrspace(4)*, i32 () addrspace(4)** %[[block_B]]
+ // SPIR: %[[blk_gen_ptr:.*]] = bitcast i32 () addrspace(4)* %[[block_literal]] to i8 addrspace(4)*
+ // SPIR: call {{.*}}i32 @__foo_block_invoke(i8 addrspace(4)* %[[blk_gen_ptr]])
+ // AMDGCN: %[[block_captured:.*]] = getelementptr inbounds <{ i32, i32, i32 }>, <{ i32, i32, i32 }> addrspace(5)* %[[block]], i32 0, i32 2
+ // AMDGCN: %[[i_value:.*]] = load i32, i32 addrspace(5)* %i
+ // AMDGCN: store i32 %[[i_value]], i32 addrspace(5)* %[[block_captured]],
+ // AMDGCN: %[[blk_ptr:.*]] = bitcast <{ i32, i32, i32 }> addrspace(5)* %[[block]] to i32 () addrspace(5)*
+ // AMDGCN: %[[blk_gen_ptr:.*]] = addrspacecast i32 () addrspace(5)* %[[blk_ptr]] to i32 ()*
+ // AMDGCN: store i32 ()* %[[blk_gen_ptr]], i32 ()* addrspace(5)* %[[block_B:.*]],
+ // AMDGCN: %[[block_literal:.*]] = load i32 ()*, i32 ()* addrspace(5)* %[[block_B]]
+ // AMDGCN: %[[blk_gen_ptr:.*]] = bitcast i32 ()* %[[block_literal]] to i8*
+ // AMDGCN: call {{.*}}i32 @__foo_block_invoke(i8* %[[blk_gen_ptr]])
int (^ block_B)(void) = ^{
return i;
@@ -46,9 +50,13 @@ void foo(){
block_B();
}
-// COMMON-LABEL: define internal {{.*}}i32 @__foo_block_invoke(i8 addrspace(4)* %.block_descriptor)
-// COMMON: %[[block:.*]] = bitcast i8 addrspace(4)* %.block_descriptor to <{ i32, i32, i8 addrspace(4)*, i32 }> addrspace(4)*
-// COMMON: %[[block_capture_addr:.*]] = getelementptr inbounds <{ i32, i32, i8 addrspace(4)*, i32 }>, <{ i32, i32, i8 addrspace(4)*, i32 }> addrspace(4)* %[[block]], i32 0, i32 3
-// COMMON: %[[block_capture:.*]] = load i32, i32 addrspace(4)* %[[block_capture_addr]]
+// SPIR-LABEL: define internal {{.*}}i32 @__foo_block_invoke(i8 addrspace(4)* %.block_descriptor)
+// SPIR: %[[block:.*]] = bitcast i8 addrspace(4)* %.block_descriptor to <{ i32, i32, i32 }> addrspace(4)*
+// SPIR: %[[block_capture_addr:.*]] = getelementptr inbounds <{ i32, i32, i32 }>, <{ i32, i32, i32 }> addrspace(4)* %[[block]], i32 0, i32 2
+// SPIR: %[[block_capture:.*]] = load i32, i32 addrspace(4)* %[[block_capture_addr]]
+// AMDGCN-LABEL: define internal {{.*}}i32 @__foo_block_invoke(i8* %.block_descriptor)
+// AMDGCN: %[[block:.*]] = bitcast i8* %.block_descriptor to <{ i32, i32, i32 }>*
+// AMDGCN: %[[block_capture_addr:.*]] = getelementptr inbounds <{ i32, i32, i32 }>, <{ i32, i32, i32 }>* %[[block]], i32 0, i32 2
+// AMDGCN: %[[block_capture:.*]] = load i32, i32* %[[block_capture_addr]]
// COMMON-NOT: define{{.*}}@__foo_block_invoke_kernel
diff --git a/test/CodeGenOpenCL/builtins-amdgcn-dl-insts-err.cl b/test/CodeGenOpenCL/builtins-amdgcn-dl-insts-err.cl
new file mode 100644
index 000000000000..bfc811e29556
--- /dev/null
+++ b/test/CodeGenOpenCL/builtins-amdgcn-dl-insts-err.cl
@@ -0,0 +1,25 @@
+// REQUIRES: amdgpu-registered-target
+
+// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu gfx900 -verify -S -emit-llvm -o - %s
+
+typedef unsigned int uint;
+typedef half __attribute__((ext_vector_type(2))) half2;
+typedef short __attribute__((ext_vector_type(2))) short2;
+typedef unsigned short __attribute__((ext_vector_type(2))) ushort2;
+
+kernel void builtins_amdgcn_dl_insts_err(
+ global float *fOut, global int *siOut, global uint *uiOut,
+ half2 v2hA, half2 v2hB, float fC,
+ short2 v2ssA, short2 v2ssB, int siA, int siB, int siC,
+ ushort2 v2usA, ushort2 v2usB, uint uiA, uint uiB, uint uiC) {
+ fOut[0] = __builtin_amdgcn_fdot2(v2hA, v2hB, fC); // expected-error {{'__builtin_amdgcn_fdot2' needs target feature dl-insts}}
+
+ siOut[0] = __builtin_amdgcn_sdot2(v2ssA, v2ssB, siC); // expected-error {{'__builtin_amdgcn_sdot2' needs target feature dl-insts}}
+ uiOut[0] = __builtin_amdgcn_udot2(v2usA, v2usB, uiC); // expected-error {{'__builtin_amdgcn_udot2' needs target feature dl-insts}}
+
+ siOut[1] = __builtin_amdgcn_sdot4(siA, siB, siC); // expected-error {{'__builtin_amdgcn_sdot4' needs target feature dl-insts}}
+ uiOut[1] = __builtin_amdgcn_udot4(uiA, uiB, uiC); // expected-error {{'__builtin_amdgcn_udot4' needs target feature dl-insts}}
+
+ siOut[2] = __builtin_amdgcn_sdot8(siA, siB, siC); // expected-error {{'__builtin_amdgcn_sdot8' needs target feature dl-insts}}
+ uiOut[2] = __builtin_amdgcn_udot8(uiA, uiB, uiC); // expected-error {{'__builtin_amdgcn_udot8' needs target feature dl-insts}}
+}
diff --git a/test/CodeGenOpenCL/builtins-amdgcn-dl-insts.cl b/test/CodeGenOpenCL/builtins-amdgcn-dl-insts.cl
new file mode 100644
index 000000000000..c407bd6fe155
--- /dev/null
+++ b/test/CodeGenOpenCL/builtins-amdgcn-dl-insts.cl
@@ -0,0 +1,36 @@
+// REQUIRES: amdgpu-registered-target
+
+// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu gfx906 -S -emit-llvm -o - %s | FileCheck %s
+
+typedef unsigned int uint;
+typedef half __attribute__((ext_vector_type(2))) half2;
+typedef short __attribute__((ext_vector_type(2))) short2;
+typedef unsigned short __attribute__((ext_vector_type(2))) ushort2;
+
+// CHECK-LABEL: @builtins_amdgcn_dl_insts
+// CHECK: call float @llvm.amdgcn.fdot2
+
+// CHECK: call i32 @llvm.amdgcn.sdot2
+// CHECK: call i32 @llvm.amdgcn.udot2
+
+// CHECK: call i32 @llvm.amdgcn.sdot4
+// CHECK: call i32 @llvm.amdgcn.udot4
+
+// CHECK: call i32 @llvm.amdgcn.sdot8
+// CHECK: call i32 @llvm.amdgcn.udot8
+kernel void builtins_amdgcn_dl_insts(
+ global float *fOut, global int *siOut, global uint *uiOut,
+ half2 v2hA, half2 v2hB, float fC,
+ short2 v2ssA, short2 v2ssB, int siA, int siB, int siC,
+ ushort2 v2usA, ushort2 v2usB, uint uiA, uint uiB, uint uiC) {
+ fOut[0] = __builtin_amdgcn_fdot2(v2hA, v2hB, fC);
+
+ siOut[0] = __builtin_amdgcn_sdot2(v2ssA, v2ssB, siC);
+ uiOut[0] = __builtin_amdgcn_udot2(v2usA, v2usB, uiC);
+
+ siOut[1] = __builtin_amdgcn_sdot4(siA, siB, siC);
+ uiOut[1] = __builtin_amdgcn_udot4(uiA, uiB, uiC);
+
+ siOut[2] = __builtin_amdgcn_sdot8(siA, siB, siC);
+ uiOut[2] = __builtin_amdgcn_udot8(uiA, uiB, uiC);
+}
diff --git a/test/CodeGenOpenCL/builtins-amdgcn-vi.cl b/test/CodeGenOpenCL/builtins-amdgcn-vi.cl
index 1dad67491832..afa312cfcb12 100644
--- a/test/CodeGenOpenCL/builtins-amdgcn-vi.cl
+++ b/test/CodeGenOpenCL/builtins-amdgcn-vi.cl
@@ -89,3 +89,20 @@ void test_mov_dpp(global int* out, int src)
*out = __builtin_amdgcn_mov_dpp(src, 0, 0, 0, false);
}
+// CHECK-LABEL: @test_ds_fadd
+// CHECK: call float @llvm.amdgcn.ds.fadd(float addrspace(3)* %out, float %src, i32 0, i32 0, i1 false)
+void test_ds_faddf(local float *out, float src) {
+ *out = __builtin_amdgcn_ds_faddf(out, src, 0, 0, false);
+}
+
+// CHECK-LABEL: @test_ds_fmin
+// CHECK: call float @llvm.amdgcn.ds.fmin(float addrspace(3)* %out, float %src, i32 0, i32 0, i1 false)
+void test_ds_fminf(local float *out, float src) {
+ *out = __builtin_amdgcn_ds_fminf(out, src, 0, 0, false);
+}
+
+// CHECK-LABEL: @test_ds_fmax
+// CHECK: call float @llvm.amdgcn.ds.fmax(float addrspace(3)* %out, float %src, i32 0, i32 0, i1 false)
+void test_ds_fmaxf(local float *out, float src) {
+ *out = __builtin_amdgcn_ds_fmaxf(out, src, 0, 0, false);
+}
diff --git a/test/CodeGenOpenCL/builtins-amdgcn.cl b/test/CodeGenOpenCL/builtins-amdgcn.cl
index 9f036547bf41..2015f36e93dc 100644
--- a/test/CodeGenOpenCL/builtins-amdgcn.cl
+++ b/test/CodeGenOpenCL/builtins-amdgcn.cl
@@ -434,22 +434,22 @@ void test_read_exec_hi(global uint* out) {
}
// CHECK-LABEL: @test_dispatch_ptr
-// CHECK: call i8 addrspace(2)* @llvm.amdgcn.dispatch.ptr()
-void test_dispatch_ptr(__attribute__((address_space(2))) unsigned char ** out)
+// CHECK: call i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr()
+void test_dispatch_ptr(__attribute__((address_space(4))) unsigned char ** out)
{
*out = __builtin_amdgcn_dispatch_ptr();
}
// CHECK-LABEL: @test_kernarg_segment_ptr
-// CHECK: call i8 addrspace(2)* @llvm.amdgcn.kernarg.segment.ptr()
-void test_kernarg_segment_ptr(__attribute__((address_space(2))) unsigned char ** out)
+// CHECK: call i8 addrspace(4)* @llvm.amdgcn.kernarg.segment.ptr()
+void test_kernarg_segment_ptr(__attribute__((address_space(4))) unsigned char ** out)
{
*out = __builtin_amdgcn_kernarg_segment_ptr();
}
// CHECK-LABEL: @test_implicitarg_ptr
-// CHECK: call i8 addrspace(2)* @llvm.amdgcn.implicitarg.ptr()
-void test_implicitarg_ptr(__attribute__((address_space(2))) unsigned char ** out)
+// CHECK: call i8 addrspace(4)* @llvm.amdgcn.implicitarg.ptr()
+void test_implicitarg_ptr(__attribute__((address_space(4))) unsigned char ** out)
{
*out = __builtin_amdgcn_implicitarg_ptr();
}
diff --git a/test/CodeGenOpenCL/byval.cl b/test/CodeGenOpenCL/byval.cl
index 90afdfab5256..05c72c514ca2 100644
--- a/test/CodeGenOpenCL/byval.cl
+++ b/test/CodeGenOpenCL/byval.cl
@@ -1,6 +1,4 @@
// RUN: %clang_cc1 -emit-llvm -o - -triple amdgcn %s | FileCheck %s
-// RUN: %clang_cc1 -emit-llvm -o - -triple amdgcn---opencl %s | FileCheck %s
-// RUN: %clang_cc1 -emit-llvm -o - -triple amdgcn---amdgizcl %s | FileCheck %s -check-prefix=AMDGIZ
struct A {
int x[100];
@@ -10,10 +8,8 @@ int f(struct A a);
int g() {
struct A a;
- // CHECK: call i32 @f(%struct.A* byval{{.*}}%a)
- // AMDGIZ: call i32 @f(%struct.A addrspace(5)* byval{{.*}}%a)
+ // CHECK: call i32 @f(%struct.A addrspace(5)* byval{{.*}}%a)
return f(a);
}
-// CHECK: declare i32 @f(%struct.A* byval{{.*}})
-// AMDGIZ: declare i32 @f(%struct.A addrspace(5)* byval{{.*}})
+// CHECK: declare i32 @f(%struct.A addrspace(5)* byval{{.*}})
diff --git a/test/CodeGenOpenCL/cast_image.cl b/test/CodeGenOpenCL/cast_image.cl
index 479404a91371..d4e24b4f051b 100644
--- a/test/CodeGenOpenCL/cast_image.cl
+++ b/test/CodeGenOpenCL/cast_image.cl
@@ -4,7 +4,7 @@
#ifdef __AMDGCN__
constant int* convert(image2d_t img) {
- // AMDGCN: bitcast %opencl.image2d_ro_t addrspace(2)* %img to i32 addrspace(2)*
+ // AMDGCN: bitcast %opencl.image2d_ro_t addrspace(4)* %img to i32 addrspace(4)*
return __builtin_astype(img, constant int*);
}
diff --git a/test/CodeGenOpenCL/cl-uniform-wg-size.cl b/test/CodeGenOpenCL/cl-uniform-wg-size.cl
new file mode 100644
index 000000000000..76ace5dca21e
--- /dev/null
+++ b/test/CodeGenOpenCL/cl-uniform-wg-size.cl
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -emit-llvm -O0 -cl-std=CL1.2 -o - %s 2>&1 | FileCheck %s -check-prefixes CHECK,CHECK-UNIFORM
+// RUN: %clang_cc1 -emit-llvm -O0 -cl-std=CL2.0 -o - %s 2>&1 | FileCheck %s -check-prefixes CHECK,CHECK-NONUNIFORM
+// RUN: %clang_cc1 -emit-llvm -O0 -cl-std=CL2.0 -cl-uniform-work-group-size -o - %s 2>&1 | FileCheck %s -check-prefixes CHECK,CHECK-UNIFORM
+
+kernel void ker() {};
+// CHECK: define{{.*}}@ker() #0
+
+void foo() {};
+// CHECK: define{{.*}}@foo() #1
+
+// CHECK-LABEL: attributes #0
+// CHECK-UNIFORM: "uniform-work-group-size"="true"
+// CHECK-NONUNIFORM: "uniform-work-group-size"="false"
+
+// CHECK-LABEL: attributes #1
+// CHECK-NOT: uniform-work-group-size
diff --git a/test/CodeGenOpenCL/cl20-device-side-enqueue.cl b/test/CodeGenOpenCL/cl20-device-side-enqueue.cl
index 0bf87c25bd83..d74a1dfbd484 100644
--- a/test/CodeGenOpenCL/cl20-device-side-enqueue.cl
+++ b/test/CodeGenOpenCL/cl20-device-side-enqueue.cl
@@ -6,29 +6,31 @@
typedef void (^bl_t)(local void *);
typedef struct {int a;} ndrange_t;
-// COMMON: %struct.__opencl_block_literal_generic = type { i32, i32, i8 addrspace(4)* }
-
// For a block global variable, first emit the block literal as a global variable, then emit the block variable itself.
-// COMMON: [[BL_GLOBAL:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* [[INV_G:@[^ ]+]] to i8*) to i8 addrspace(4)*) }
-// COMMON: @block_G = addrspace(1) constant void (i8 addrspace(3)*) addrspace(4)* addrspacecast (void (i8 addrspace(3)*) addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BL_GLOBAL]] to void (i8 addrspace(3)*) addrspace(1)*) to void (i8 addrspace(3)*) addrspace(4)*)
+// COMMON: [[BL_GLOBAL:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
+// COMMON: @block_G = addrspace(1) constant void (i8 addrspace(3)*) addrspace(4)* addrspacecast (void (i8 addrspace(3)*) addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BL_GLOBAL]] to void (i8 addrspace(3)*) addrspace(1)*) to void (i8 addrspace(3)*) addrspace(4)*)
// For anonymous blocks without captures, emit block literals as global variable.
-// COMMON: [[BLG1:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) }
-// COMMON: [[BLG2:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) }
-// COMMON: [[BLG3:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) }
-// COMMON: [[BLG4:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) }
-// COMMON: [[BLG5:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) }
-// COMMON: [[BLG6:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*, i8 addrspace(3)*, i8 addrspace(3)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) }
-// COMMON: [[BLG7:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) }
-// COMMON: [[BLG8:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*)* [[INVG8:@[^ ]+]] to i8*) to i8 addrspace(4)*) }
-// COMMON: [[BLG9:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* [[INVG9:@[^ ]+]] to i8*) to i8 addrspace(4)*) }
-// COMMON: [[BLG10:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) }
-// COMMON: [[BLG11:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) }
+// COMMON: [[BLG1:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
+// COMMON: [[BLG2:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
+// COMMON: [[BLG3:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
+// COMMON: [[BLG4:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
+// COMMON: [[BLG5:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
+// COMMON: [[BLG6:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
+// COMMON: [[BLG7:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
+// COMMON: [[BLG8:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
+// COMMON: [[BLG9:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
+// COMMON: [[BLG10:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
+// COMMON: [[BLG11:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
// Emits block literal [[BL_GLOBAL]], invoke function [[INV_G]] and global block variable @block_G
-// COMMON: define internal spir_func void [[INV_G]](i8 addrspace(4)* %{{.*}}, i8 addrspace(3)* %{{.*}})
+// COMMON: define internal spir_func void [[INV_G:.*]](i8 addrspace(4)* %{{.*}}, i8 addrspace(3)* %{{.*}})
const bl_t block_G = (bl_t) ^ (local void *a) {};
+void callee(int id, __global int *out) {
+ out[id] = id;
+}
+
// COMMON-LABEL: define spir_kernel void @device_side_enqueue(i32 addrspace(1)* %{{.*}}, i32 addrspace(1)* %b, i32 %i)
kernel void device_side_enqueue(global int *a, global int *b, int i) {
// COMMON: %default_queue = alloca %opencl.queue_t*
@@ -48,9 +50,8 @@ kernel void device_side_enqueue(global int *a, global int *b, int i) {
// COMMON: [[NDR:%[a-z0-9]+]] = alloca %struct.ndrange_t, align 4
// COMMON: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t{{.*}}*, %opencl.queue_t{{.*}}** %default_queue
// COMMON: [[FLAGS:%[0-9]+]] = load i32, i32* %flags
- // COMMON: store i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*)* [[INVL1:@__device_side_enqueue_block_invoke[^ ]*]] to i8*) to i8 addrspace(4)*), i8 addrspace(4)** %block.invoke
- // B32: [[BL:%[0-9]+]] = bitcast <{ i32, i32, i8 addrspace(4)*, i32 addrspace(1)*, i32, i32 addrspace(1)* }>* %block to void ()*
- // B64: [[BL:%[0-9]+]] = bitcast <{ i32, i32, i8 addrspace(4)*, i32 addrspace(1)*, i32 addrspace(1)*, i32 }>* %block to void ()*
+ // B32: [[BL:%[0-9]+]] = bitcast <{ i32, i32, i32 addrspace(1)*, i32, i32 addrspace(1)* }>* %block to void ()*
+ // B64: [[BL:%[0-9]+]] = bitcast <{ i32, i32, i32 addrspace(1)*, i32 addrspace(1)*, i32 }>* %block to void ()*
// COMMON: [[BL_I8:%[0-9]+]] = addrspacecast void ()* [[BL]] to i8 addrspace(4)*
// COMMON-LABEL: call i32 @__enqueue_kernel_basic(
// COMMON-SAME: %opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* byval [[NDR]]{{([0-9]+)?}},
@@ -66,8 +67,7 @@ kernel void device_side_enqueue(global int *a, global int *b, int i) {
// COMMON: [[FLAGS:%[0-9]+]] = load i32, i32* %flags
// COMMON: [[WAIT_EVNT:%[0-9]+]] = addrspacecast %opencl.clk_event_t{{.*}}** %event_wait_list to %opencl.clk_event_t{{.*}}* addrspace(4)*
// COMMON: [[EVNT:%[0-9]+]] = addrspacecast %opencl.clk_event_t{{.*}}** %clk_event to %opencl.clk_event_t{{.*}}* addrspace(4)*
- // COMMON: store i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*)* [[INVL2:@__device_side_enqueue_block_invoke[^ ]*]] to i8*) to i8 addrspace(4)*), i8 addrspace(4)** %block.invoke
- // COMMON: [[BL:%[0-9]+]] = bitcast <{ i32, i32, i8 addrspace(4)*, i32{{.*}}, i32{{.*}}, i32{{.*}} }>* %block3 to void ()*
+ // COMMON: [[BL:%[0-9]+]] = bitcast <{ i32, i32, i32{{.*}}, i32{{.*}}, i32{{.*}} }>* %block3 to void ()*
// COMMON: [[BL_I8:%[0-9]+]] = addrspacecast void ()* [[BL]] to i8 addrspace(4)*
// COMMON-LABEL: call i32 @__enqueue_kernel_basic_events
// COMMON-SAME: (%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* {{.*}}, i32 2, %opencl.clk_event_t{{.*}}* addrspace(4)* [[WAIT_EVNT]], %opencl.clk_event_t{{.*}}* addrspace(4)* [[EVNT]],
@@ -88,10 +88,10 @@ kernel void device_side_enqueue(global int *a, global int *b, int i) {
// B64: %[[TMP:.*]] = alloca [1 x i64]
// B64: %[[TMP1:.*]] = getelementptr [1 x i64], [1 x i64]* %[[TMP]], i32 0, i32 0
// B64: store i64 256, i64* %[[TMP1]], align 8
- // COMMON-LABEL: call i32 @__enqueue_kernel_vaargs(
+ // COMMON-LABEL: call i32 @__enqueue_kernel_varargs(
// COMMON-SAME: %opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* [[NDR]]{{([0-9]+)?}},
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK1:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG1]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG1]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
// B32-SAME: i32* %[[TMP1]])
// B64-SAME: i64* %[[TMP1]])
enqueue_kernel(default_queue, flags, ndrange,
@@ -109,10 +109,10 @@ kernel void device_side_enqueue(global int *a, global int *b, int i) {
// B64: %[[TMP:.*]] = alloca [1 x i64]
// B64: %[[TMP1:.*]] = getelementptr [1 x i64], [1 x i64]* %[[TMP]], i32 0, i32 0
// B64: store i64 %{{.*}}, i64* %[[TMP1]], align 8
- // COMMON-LABEL: call i32 @__enqueue_kernel_vaargs(
+ // COMMON-LABEL: call i32 @__enqueue_kernel_varargs(
// COMMON-SAME: %opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* [[NDR]]{{([0-9]+)?}},
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK2:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG2]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG2]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
// B32-SAME: i32* %[[TMP1]])
// B64-SAME: i64* %[[TMP1]])
enqueue_kernel(default_queue, flags, ndrange,
@@ -133,10 +133,10 @@ kernel void device_side_enqueue(global int *a, global int *b, int i) {
// B64: %[[TMP:.*]] = alloca [1 x i64]
// B64: %[[TMP1:.*]] = getelementptr [1 x i64], [1 x i64]* %[[TMP]], i32 0, i32 0
// B64: store i64 256, i64* %[[TMP1]], align 8
- // COMMON-LABEL: call i32 @__enqueue_kernel_events_vaargs
+ // COMMON-LABEL: call i32 @__enqueue_kernel_events_varargs
// COMMON-SAME: (%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* {{.*}}, i32 2, %opencl.clk_event_t{{.*}} [[WAIT_EVNT]], %opencl.clk_event_t{{.*}} [[EVNT]],
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK3:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG3]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG3]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
// B32-SAME: i32* %[[TMP1]])
// B64-SAME: i64* %[[TMP1]])
enqueue_kernel(default_queue, flags, ndrange, 2, event_wait_list2, &clk_event,
@@ -157,10 +157,10 @@ kernel void device_side_enqueue(global int *a, global int *b, int i) {
// B64: %[[TMP:.*]] = alloca [1 x i64]
// B64: %[[TMP1:.*]] = getelementptr [1 x i64], [1 x i64]* %[[TMP]], i32 0, i32 0
// B64: store i64 %{{.*}}, i64* %[[TMP1]], align 8
- // COMMON-LABEL: call i32 @__enqueue_kernel_events_vaargs
+ // COMMON-LABEL: call i32 @__enqueue_kernel_events_varargs
// COMMON-SAME: (%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* {{.*}}, i32 2, %opencl.clk_event_t{{.*}}* addrspace(4)* [[WAIT_EVNT]], %opencl.clk_event_t{{.*}}* addrspace(4)* [[EVNT]],
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK4:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG4]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG4]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
// B32-SAME: i32* %[[TMP1]])
// B64-SAME: i64* %[[TMP1]])
enqueue_kernel(default_queue, flags, ndrange, 2, event_wait_list2, &clk_event,
@@ -179,10 +179,10 @@ kernel void device_side_enqueue(global int *a, global int *b, int i) {
// B64: %[[TMP:.*]] = alloca [1 x i64]
// B64: %[[TMP1:.*]] = getelementptr [1 x i64], [1 x i64]* %[[TMP]], i32 0, i32 0
// B64: store i64 %{{.*}}, i64* %[[TMP1]], align 8
- // COMMON-LABEL: call i32 @__enqueue_kernel_vaargs
+ // COMMON-LABEL: call i32 @__enqueue_kernel_varargs
// COMMON-SAME: (%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* [[NDR]]{{([0-9]+)?}},
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK5:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG5]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG5]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
// B32-SAME: i32* %[[TMP1]])
// B64-SAME: i64* %[[TMP1]])
enqueue_kernel(default_queue, flags, ndrange,
@@ -208,10 +208,10 @@ kernel void device_side_enqueue(global int *a, global int *b, int i) {
// B64: store i64 2, i64* %[[TMP2]], align 8
// B64: %[[TMP3:.*]] = getelementptr [3 x i64], [3 x i64]* %[[TMP]], i32 0, i32 2
// B64: store i64 4, i64* %[[TMP3]], align 8
- // COMMON-LABEL: call i32 @__enqueue_kernel_vaargs
+ // COMMON-LABEL: call i32 @__enqueue_kernel_varargs
// COMMON-SAME: (%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* [[NDR]]{{([0-9]+)?}},
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK6:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG6]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 3,
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG6]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 3,
// B32-SAME: i32* %[[TMP1]])
// B64-SAME: i64* %[[TMP1]])
enqueue_kernel(default_queue, flags, ndrange,
@@ -229,10 +229,10 @@ kernel void device_side_enqueue(global int *a, global int *b, int i) {
// B64: %[[TMP:.*]] = alloca [1 x i64]
// B64: %[[TMP1:.*]] = getelementptr [1 x i64], [1 x i64]* %[[TMP]], i32 0, i32 0
// B64: store i64 4294967296, i64* %[[TMP1]], align 8
- // COMMON-LABEL: call i32 @__enqueue_kernel_vaargs
+ // COMMON-LABEL: call i32 @__enqueue_kernel_varargs
// COMMON-SAME: (%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* [[NDR]]{{([0-9]+)?}},
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK7:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG7]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG7]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
// B32-SAME: i32* %[[TMP1]])
// B64-SAME: i64* %[[TMP1]])
enqueue_kernel(default_queue, flags, ndrange,
@@ -244,21 +244,19 @@ kernel void device_side_enqueue(global int *a, global int *b, int i) {
// Emits global block literal [[BLG8]] and invoke function [[INVG8]].
// The full type of these expressions are long (and repeated elsewhere), so we
// capture it as part of the regex for convenience and clarity.
- // COMMON: store void () addrspace(4)* addrspacecast (void () addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG8]] to void () addrspace(1)*) to void () addrspace(4)*), void () addrspace(4)** %block_A
+ // COMMON: store void () addrspace(4)* addrspacecast (void () addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG8]] to void () addrspace(1)*) to void () addrspace(4)*), void () addrspace(4)** %block_A
void (^const block_A)(void) = ^{
return;
};
// Emits global block literal [[BLG9]] and invoke function [[INVG9]].
- // COMMON: store void (i8 addrspace(3)*) addrspace(4)* addrspacecast (void (i8 addrspace(3)*) addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG9]] to void (i8 addrspace(3)*) addrspace(1)*) to void (i8 addrspace(3)*) addrspace(4)*), void (i8 addrspace(3)*) addrspace(4)** %block_B
+ // COMMON: store void (i8 addrspace(3)*) addrspace(4)* addrspacecast (void (i8 addrspace(3)*) addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG9]] to void (i8 addrspace(3)*) addrspace(1)*) to void (i8 addrspace(3)*) addrspace(4)*), void (i8 addrspace(3)*) addrspace(4)** %block_B
void (^const block_B)(local void *) = ^(local void *a) {
return;
};
// Uses global block literal [[BLG8]] and invoke function [[INVG8]].
- // COMMON: [[r1:%.*]] = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* getelementptr inbounds (%struct.__opencl_block_literal_generic, %struct.__opencl_block_literal_generic addrspace(4)* addrspacecast (%struct.__opencl_block_literal_generic addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG8]] to %struct.__opencl_block_literal_generic addrspace(1)*) to %struct.__opencl_block_literal_generic addrspace(4)*), i32 0, i32 2)
- // COMMON: [[r2:%.*]] = addrspacecast i8 addrspace(4)* [[r1]] to void (i8 addrspace(4)*)*
- // COMMON: call spir_func void [[r2]](i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*))
+ // COMMON: call spir_func void [[INVG8:.*]](i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*))
block_A();
// Emits global block literal [[BLG8]] and block kernel [[INVGK8]]. [[INVGK8]] calls [[INVG8]].
@@ -267,49 +265,61 @@ kernel void device_side_enqueue(global int *a, global int *b, int i) {
// COMMON-LABEL: call i32 @__enqueue_kernel_basic(
// COMMON-SAME: %opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* byval [[NDR]]{{([0-9]+)?}},
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK8:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*))
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*))
enqueue_kernel(default_queue, flags, ndrange, block_A);
// Uses block kernel [[INVGK8]] and global block literal [[BLG8]].
// COMMON: call i32 @__get_kernel_work_group_size_impl(
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK8]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*))
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*))
unsigned size = get_kernel_work_group_size(block_A);
// Uses global block literal [[BLG8]] and invoke function [[INVG8]]. Make sure no redundant block literal and invoke functions are emitted.
- // COMMON: [[r1:%.*]] = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* getelementptr inbounds (%struct.__opencl_block_literal_generic, %struct.__opencl_block_literal_generic addrspace(4)* addrspacecast (%struct.__opencl_block_literal_generic addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG8]] to %struct.__opencl_block_literal_generic addrspace(1)*) to %struct.__opencl_block_literal_generic addrspace(4)*), i32 0, i32 2)
- // COMMON: [[r2:%.*]] = addrspacecast i8 addrspace(4)* [[r1]] to void (i8 addrspace(4)*)*
- // COMMON: call spir_func void [[r2]](i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*))
+ // COMMON: call spir_func void [[INVG8]](i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*))
block_A();
- // Emits global block literal [[BLG9]] and block kernel [[INVGK9]]. [[INVGK9]] calls [[INV9]].
+ void (^block_C)(void) = ^{
+ callee(i, a);
+ };
+
+ // Emits block literal on stack and block kernel [[INVLK3]].
+ // COMMON: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t{{.*}}*, %opencl.queue_t{{.*}}** %default_queue
+ // COMMON: [[FLAGS:%[0-9]+]] = load i32, i32* %flags
+ // COMMON: [[BL_I8:%[0-9]+]] = addrspacecast void ()* {{.*}} to i8 addrspace(4)*
+ // COMMON-LABEL: call i32 @__enqueue_kernel_basic(
+ // COMMON-SAME: %opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* byval [[NDR]]{{([0-9]+)?}},
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVLK3:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
+ // COMMON-SAME: i8 addrspace(4)* [[BL_I8]])
+ enqueue_kernel(default_queue, flags, ndrange, block_C);
+
+ // Emits global block literal [[BLG9]] and block kernel [[INVGK9]]. [[INVGK9]] calls [[INVG9]].
// COMMON: call i32 @__get_kernel_work_group_size_impl(
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK9:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG9]] to i8 addrspace(1)*) to i8 addrspace(4)*))
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG9]] to i8 addrspace(1)*) to i8 addrspace(4)*))
size = get_kernel_work_group_size(block_B);
// Uses global block literal [[BLG8]] and block kernel [[INVGK8]]. Make sure no redundant block literal ind invoke functions are emitted.
- // COMMON: call i32 @__get_kernel_preferred_work_group_multiple_impl(
+ // COMMON: call i32 @__get_kernel_preferred_work_group_size_multiple_impl(
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK8]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*))
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*))
size = get_kernel_preferred_work_group_size_multiple(block_A);
// Uses global block literal [[BL_GLOBAL]] and block kernel [[INV_G_K]]. [[INV_G_K]] calls [[INV_G]].
- // COMMON: call i32 @__get_kernel_preferred_work_group_multiple_impl(
+ // COMMON: call i32 @__get_kernel_preferred_work_group_size_multiple_impl(
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INV_G_K:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BL_GLOBAL]] to i8 addrspace(1)*) to i8 addrspace(4)*))
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BL_GLOBAL]] to i8 addrspace(1)*) to i8 addrspace(4)*))
size = get_kernel_preferred_work_group_size_multiple(block_G);
// Emits global block literal [[BLG10]] and block kernel [[INVGK10]].
// COMMON: call i32 @__get_kernel_max_sub_group_size_for_ndrange_impl(%struct.ndrange_t* {{[^,]+}},
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK10:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG10]] to i8 addrspace(1)*) to i8 addrspace(4)*))
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG10]] to i8 addrspace(1)*) to i8 addrspace(4)*))
size = get_kernel_max_sub_group_size_for_ndrange(ndrange, ^(){});
// Emits global block literal [[BLG11]] and block kernel [[INVGK11]].
// COMMON: call i32 @__get_kernel_sub_group_count_for_ndrange_impl(%struct.ndrange_t* {{[^,]+}},
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK11:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG11]] to i8 addrspace(1)*) to i8 addrspace(4)*))
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG11]] to i8 addrspace(1)*) to i8 addrspace(4)*))
size = get_kernel_sub_group_count_for_ndrange(ndrange, ^(){});
}
@@ -331,8 +341,9 @@ kernel void device_side_enqueue(global int *a, global int *b, int i) {
// COMMON: }
// COMMON: define internal spir_kernel void [[INVGK7]](i8 addrspace(4)*{{.*}}, i8 addrspace(3)*{{.*}})
// COMMON: define internal spir_func void [[INVG8]](i8 addrspace(4)*{{.*}})
-// COMMON: define internal spir_func void [[INVG9]](i8 addrspace(4)*{{.*}}, i8 addrspace(3)* %{{.*}})
+// COMMON: define internal spir_func void [[INVG9:.*]](i8 addrspace(4)*{{.*}}, i8 addrspace(3)* %{{.*}})
// COMMON: define internal spir_kernel void [[INVGK8]](i8 addrspace(4)*{{.*}})
+// COMMON: define internal spir_kernel void [[INVLK3]](i8 addrspace(4)*{{.*}})
// COMMON: define internal spir_kernel void [[INVGK9]](i8 addrspace(4)*{{.*}}, i8 addrspace(3)*{{.*}})
// COMMON: define internal spir_kernel void [[INV_G_K]](i8 addrspace(4)*{{.*}}, i8 addrspace(3)*{{.*}})
// COMMON: define internal spir_kernel void [[INVGK10]](i8 addrspace(4)*{{.*}})
diff --git a/test/CodeGenOpenCL/convergent.cl b/test/CodeGenOpenCL/convergent.cl
index 285b637ca687..a011920761f3 100644
--- a/test/CodeGenOpenCL/convergent.cl
+++ b/test/CodeGenOpenCL/convergent.cl
@@ -127,7 +127,7 @@ void test_not_unroll() {
// CHECK: declare spir_func void @nodupfun(){{[^#]*}} #[[attr3:[0-9]+]]
// CHECK-LABEL: @assume_convergent_asm
-// CHECK: tail call void asm sideeffect "s_barrier", ""() #4
+// CHECK: tail call void asm sideeffect "s_barrier", ""() #5
kernel void assume_convergent_asm()
{
__asm__ volatile("s_barrier");
@@ -138,4 +138,5 @@ kernel void assume_convergent_asm()
// CHECK: attributes #2 = { {{[^}]*}}convergent{{[^}]*}} }
// CHECK: attributes #3 = { {{[^}]*}}convergent noduplicate{{[^}]*}} }
// CHECK: attributes #4 = { {{[^}]*}}convergent{{[^}]*}} }
-// CHECK: attributes #5 = { {{[^}]*}}convergent noduplicate{{[^}]*}} }
+// CHECK: attributes #5 = { {{[^}]*}}convergent{{[^}]*}} }
+// CHECK: attributes #6 = { {{[^}]*}}convergent noduplicate{{[^}]*}} }
diff --git a/test/CodeGenOpenCL/denorms-are-zero.cl b/test/CodeGenOpenCL/denorms-are-zero.cl
index ca7969ad5f40..ab8bf7641c87 100644
--- a/test/CodeGenOpenCL/denorms-are-zero.cl
+++ b/test/CodeGenOpenCL/denorms-are-zero.cl
@@ -1,19 +1,25 @@
-// RUN: %clang_cc1 -S -cl-denorms-are-zero -o - %s 2>&1
-// RUN: %clang_cc1 -emit-llvm -cl-denorms-are-zero -o - -triple amdgcn--amdhsa -target-cpu fiji %s | FileCheck %s
-// RUN: %clang_cc1 -emit-llvm -o - -triple amdgcn--amdhsa -target-cpu fiji %s | FileCheck %s --check-prefix=CHECK-DENORM
-// RUN: %clang_cc1 -emit-llvm -target-feature +fp32-denormals -target-feature -fp64-fp16-denormals -cl-denorms-are-zero -o - -triple amdgcn--amdhsa -target-cpu fiji %s | FileCheck --check-prefix=CHECK-FEATURE %s
+// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -cl-denorms-are-zero -o - %s | FileCheck %s --check-prefix=DENORM-ZERO
+// RUN: %clang_cc1 -emit-llvm -cl-denorms-are-zero -o - -triple amdgcn--amdhsa -target-cpu fiji %s | FileCheck %s --check-prefix=AMDGCN
+// RUN: %clang_cc1 -emit-llvm -o - -triple amdgcn--amdhsa -target-cpu fiji %s | FileCheck %s --check-prefix=AMDGCN-DENORM
+// RUN: %clang_cc1 -emit-llvm -target-feature +fp32-denormals -target-feature -fp64-fp16-denormals -cl-denorms-are-zero -o - -triple amdgcn--amdhsa -target-cpu fiji %s | FileCheck --check-prefix=AMDGCN-FEATURE %s
-// For non-amdgcn targets, this test just checks that the -cl-denorms-are-zero argument is accepted
-// by clang. This option is currently a no-op, which is allowed by the
-// OpenCL specification.
+// For all targets 'denorms-are-zero' attribute is set to 'true'
+// if '-cl-denorms-are-zero' was specified and to 'false' otherwise.
+
+// CHECK-LABEL: define {{(dso_local )?}}void @f()
+// CHECK: attributes #{{[0-9]*}} = {{{[^}]*}} "denorms-are-zero"="false"
+//
+// DENORM-ZERO-LABEL: define {{(dso_local )?}}void @f()
+// DENORM-ZERO: attributes #{{[0-9]*}} = {{{[^}]*}} "denorms-are-zero"="true"
// For amdgcn target cpu fiji, fp32 should be flushed since fiji does not support fp32 denormals, unless +fp32-denormals is
// explicitly set. amdgcn target always do not flush fp64 denormals. The control for fp64 and fp16 denormals is the same.
-// CHECK-DENORM-LABEL: define void @f()
-// CHECK-DENORM: attributes #{{[0-9]*}} = {{{[^}]*}} "target-features"="{{[^"]*}}+fp64-fp16-denormals,{{[^"]*}}-fp32-denormals{{[^"]*}}"
-// CHECK-LABEL: define void @f()
-// CHECK: attributes #{{[0-9]*}} = {{{[^}]*}} "target-features"="{{[^"]*}}+fp64-fp16-denormals,{{[^"]*}}-fp32-denormals{{[^"]*}}"
-// CHECK-FEATURE-LABEL: define void @f()
-// CHECK-FEATURE: attributes #{{[0-9]*}} = {{{[^}]*}} "target-features"="{{[^"]*}}+fp32-denormals,{{[^"]*}}-fp64-fp16-denormals{{[^"]*}}"
+// AMDGCN-LABEL: define void @f()
+// AMDGCN: attributes #{{[0-9]*}} = {{{[^}]*}} "denorms-are-zero"="true" {{.*}} "target-features"="{{[^"]*}}+fp64-fp16-denormals,{{[^"]*}}-fp32-denormals{{[^"]*}}"
+// AMDGCN-DENORM-LABEL: define void @f()
+// AMDGCN-DENORM: attributes #{{[0-9]*}} = {{{[^}]*}} "denorms-are-zero"="false" {{.*}} "target-features"="{{[^"]*}}+fp64-fp16-denormals,{{[^"]*}}-fp32-denormals{{[^"]*}}"
+// AMDGCN-FEATURE-LABEL: define void @f()
+// AMDGCN-FEATURE: attributes #{{[0-9]*}} = {{{[^}]*}} "denorms-are-zero"="true" {{.*}} "target-features"="{{[^"]*}}+fp32-denormals,{{[^"]*}}-fp64-fp16-denormals{{[^"]*}}"
void f() {}
diff --git a/test/CodeGenOpenCL/half.cl b/test/CodeGenOpenCL/half.cl
index a10ba4d7f9e9..eae8cdcb03ec 100644
--- a/test/CodeGenOpenCL/half.cl
+++ b/test/CodeGenOpenCL/half.cl
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 %s -emit-llvm -o - -triple spir-unknown-unknown | FileCheck %s
+// RUN: %clang_cc1 %s -emit-llvm -o - -triple x86_64-pc-win32 | FileCheck %s
#pragma OPENCL EXTENSION cl_khr_fp16 : enable
diff --git a/test/CodeGenOpenCL/inline-asm-amdgcn.cl b/test/CodeGenOpenCL/inline-asm-amdgcn.cl
new file mode 100644
index 000000000000..ccd98210d3a3
--- /dev/null
+++ b/test/CodeGenOpenCL/inline-asm-amdgcn.cl
@@ -0,0 +1,8 @@
+// REQUIRES: amdgpu-registered-target
+// RUN: %clang_cc1 -emit-llvm -o - -triple amdgcn %s | FileCheck %s
+
+kernel void test_long(int arg0) {
+ long v15_16;
+ // CHECK: tail call i64 asm sideeffect "v_lshlrev_b64 v[15:16], 0, $0", "={v[15:16]},v"(i32 %arg0)
+ __asm volatile("v_lshlrev_b64 v[15:16], 0, %0" : "={v[15:16]}"(v15_16) : "v"(arg0));
+}
diff --git a/test/CodeGenOpenCL/kernel-attributes.cl b/test/CodeGenOpenCL/kernel-attributes.cl
index eff2e57d8c9b..c9ecb144c9f3 100644
--- a/test/CodeGenOpenCL/kernel-attributes.cl
+++ b/test/CodeGenOpenCL/kernel-attributes.cl
@@ -3,13 +3,13 @@
typedef unsigned int uint4 __attribute__((ext_vector_type(4)));
kernel __attribute__((vec_type_hint(int))) __attribute__((reqd_work_group_size(1,2,4))) void kernel1(int a) {}
-// CHECK: define spir_kernel void @kernel1(i32 {{[^%]*}}%a) {{[^{]+}} !vec_type_hint ![[MD1:[0-9]+]] !reqd_work_group_size ![[MD2:[0-9]+]]
+// CHECK: define {{(dso_local )?}}spir_kernel void @kernel1(i32 {{[^%]*}}%a) {{[^{]+}} !vec_type_hint ![[MD1:[0-9]+]] !reqd_work_group_size ![[MD2:[0-9]+]]
kernel __attribute__((vec_type_hint(uint4))) __attribute__((work_group_size_hint(8,16,32))) void kernel2(int a) {}
-// CHECK: define spir_kernel void @kernel2(i32 {{[^%]*}}%a) {{[^{]+}} !vec_type_hint ![[MD3:[0-9]+]] !work_group_size_hint ![[MD4:[0-9]+]]
+// CHECK: define {{(dso_local )?}}spir_kernel void @kernel2(i32 {{[^%]*}}%a) {{[^{]+}} !vec_type_hint ![[MD3:[0-9]+]] !work_group_size_hint ![[MD4:[0-9]+]]
kernel __attribute__((intel_reqd_sub_group_size(8))) void kernel3(int a) {}
-// CHECK: define spir_kernel void @kernel3(i32 {{[^%]*}}%a) {{[^{]+}} !intel_reqd_sub_group_size ![[MD5:[0-9]+]]
+// CHECK: define {{(dso_local )?}}spir_kernel void @kernel3(i32 {{[^%]*}}%a) {{[^{]+}} !intel_reqd_sub_group_size ![[MD5:[0-9]+]]
// CHECK: [[MD1]] = !{i32 undef, i32 1}
// CHECK: [[MD2]] = !{i32 1, i32 2, i32 4}
diff --git a/test/CodeGenOpenCL/kernel-metadata.cl b/test/CodeGenOpenCL/kernel-metadata.cl
index 95be43015aa9..cdec97b7df28 100644
--- a/test/CodeGenOpenCL/kernel-metadata.cl
+++ b/test/CodeGenOpenCL/kernel-metadata.cl
@@ -6,5 +6,5 @@ void normal_function() {
__kernel void kernel_function() {
}
-// CHECK: define spir_kernel void @kernel_function() {{[^{]+}} !kernel_arg_addr_space ![[MD:[0-9]+]] !kernel_arg_access_qual ![[MD]] !kernel_arg_type ![[MD]] !kernel_arg_base_type ![[MD]] !kernel_arg_type_qual ![[MD]] {
+// CHECK: define {{.*}}spir_kernel void @kernel_function() {{[^{]+}} !kernel_arg_addr_space ![[MD:[0-9]+]] !kernel_arg_access_qual ![[MD]] !kernel_arg_type ![[MD]] !kernel_arg_base_type ![[MD]] !kernel_arg_type_qual ![[MD]] {
// CHECK: ![[MD]] = !{}
diff --git a/test/CodeGenOpenCL/lifetime.cl b/test/CodeGenOpenCL/lifetime.cl
index 430e0582aeda..ed9f32fde933 100644
--- a/test/CodeGenOpenCL/lifetime.cl
+++ b/test/CodeGenOpenCL/lifetime.cl
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
-// RUN: %clang_cc1 -emit-llvm -o - -triple amdgcn---amdgizcl %s | FileCheck %s -check-prefix=AMDGIZ
+// RUN: %clang_cc1 -emit-llvm -o - -triple amdgcn %s | FileCheck %s -check-prefix=AMDGCN
void use(char *a);
@@ -10,6 +10,6 @@ __attribute__((always_inline)) void helper_no_markers() {
void lifetime_test() {
// CHECK: @llvm.lifetime.start.p0i
-// AMDGIZ: @llvm.lifetime.start.p5i
+// AMDGCN: @llvm.lifetime.start.p5i
helper_no_markers();
}
diff --git a/test/CodeGenOpenCL/opencl_types.cl b/test/CodeGenOpenCL/opencl_types.cl
index 3501f9fd34e9..1f1294bd99aa 100644
--- a/test/CodeGenOpenCL/opencl_types.cl
+++ b/test/CodeGenOpenCL/opencl_types.cl
@@ -11,37 +11,39 @@ constant sampler_t glb_smp = CLK_ADDRESS_CLAMP_TO_EDGE|CLK_NORMALIZED_COORDS_TRU
void fnc1(image1d_t img) {}
// CHECK-SPIR: @fnc1(%opencl.image1d_ro_t addrspace(1)*
-// CHECK-AMDGCN: @fnc1(%opencl.image1d_ro_t addrspace(2)*
+// CHECK-AMDGCN: @fnc1(%opencl.image1d_ro_t addrspace(4)*
void fnc1arr(image1d_array_t img) {}
// CHECK-SPIR: @fnc1arr(%opencl.image1d_array_ro_t addrspace(1)*
-// CHECK-AMDGCN: @fnc1arr(%opencl.image1d_array_ro_t addrspace(2)*
+// CHECK-AMDGCN: @fnc1arr(%opencl.image1d_array_ro_t addrspace(4)*
void fnc1buff(image1d_buffer_t img) {}
// CHECK-SPIR: @fnc1buff(%opencl.image1d_buffer_ro_t addrspace(1)*
-// CHECK-AMDGCN: @fnc1buff(%opencl.image1d_buffer_ro_t addrspace(2)*
+// CHECK-AMDGCN: @fnc1buff(%opencl.image1d_buffer_ro_t addrspace(4)*
void fnc2(image2d_t img) {}
// CHECK-SPIR: @fnc2(%opencl.image2d_ro_t addrspace(1)*
-// CHECK-AMDGCN: @fnc2(%opencl.image2d_ro_t addrspace(2)*
+// CHECK-AMDGCN: @fnc2(%opencl.image2d_ro_t addrspace(4)*
void fnc2arr(image2d_array_t img) {}
// CHECK-SPIR: @fnc2arr(%opencl.image2d_array_ro_t addrspace(1)*
-// CHECK-AMDGCN: @fnc2arr(%opencl.image2d_array_ro_t addrspace(2)*
+// CHECK-AMDGCN: @fnc2arr(%opencl.image2d_array_ro_t addrspace(4)*
void fnc3(image3d_t img) {}
// CHECK-SPIR: @fnc3(%opencl.image3d_ro_t addrspace(1)*
-// CHECK-AMDGCN: @fnc3(%opencl.image3d_ro_t addrspace(2)*
+// CHECK-AMDGCN: @fnc3(%opencl.image3d_ro_t addrspace(4)*
void fnc4smp(sampler_t s) {}
// CHECK-SPIR-LABEL: define {{.*}}void @fnc4smp(%opencl.sampler_t addrspace(2)*
-// CHECK-AMDGCN-LABEL: define {{.*}}void @fnc4smp(%opencl.sampler_t addrspace(2)*
+// CHECK-AMDGCN-LABEL: define {{.*}}void @fnc4smp(%opencl.sampler_t addrspace(4)*
kernel void foo(image1d_t img) {
sampler_t smp = CLK_ADDRESS_CLAMP_TO_EDGE|CLK_NORMALIZED_COORDS_TRUE|CLK_FILTER_LINEAR;
- // CHECK-COM: alloca %opencl.sampler_t addrspace(2)*
+ // CHECK-SPIR: alloca %opencl.sampler_t addrspace(2)*
+ // CHECK-AMDGCN: alloca %opencl.sampler_t addrspace(4)*
event_t evt;
- // CHECK-COM: alloca %opencl.event_t*
+ // CHECK-SPIR: alloca %opencl.event_t*
+ // CHECK-AMDGCN: alloca %opencl.event_t addrspace(5)*
clk_event_t clk_evt;
// CHECK-SPIR: alloca %opencl.clk_event_t*
// CHECK-AMDGCN: alloca %opencl.clk_event_t addrspace(1)*
@@ -51,17 +53,24 @@ kernel void foo(image1d_t img) {
reserve_id_t rid;
// CHECK-SPIR: alloca %opencl.reserve_id_t*
// CHECK-AMDGCN: alloca %opencl.reserve_id_t addrspace(1)*
- // CHECK-COM: store %opencl.sampler_t addrspace(2)*
+ // CHECK-SPIR: store %opencl.sampler_t addrspace(2)*
+ // CHECK-AMDGCN: store %opencl.sampler_t addrspace(4)*
fnc4smp(smp);
- // CHECK-COM: call {{.*}}void @fnc4smp(%opencl.sampler_t addrspace(2)*
+ // CHECK-SPIR: call {{.*}}void @fnc4smp(%opencl.sampler_t addrspace(2)*
+ // CHECK-AMDGCN: call {{.*}}void @fnc4smp(%opencl.sampler_t addrspace(4)*
fnc4smp(glb_smp);
- // CHECK-COM: call {{.*}}void @fnc4smp(%opencl.sampler_t addrspace(2)*
+ // CHECK-SPIR: call {{.*}}void @fnc4smp(%opencl.sampler_t addrspace(2)*
+ // CHECK-AMDGCN: call {{.*}}void @fnc4smp(%opencl.sampler_t addrspace(4)*
}
-kernel void foo_pipe(read_only pipe int p) {}
-// CHECK-SPIR: @foo_pipe(%opencl.pipe_t addrspace(1)* %p)
-// CHECK_AMDGCN: @foo_pipe(%opencl.pipe_t addrspace(1)* %p)
+kernel void foo_ro_pipe(read_only pipe int p) {}
+// CHECK-SPIR: @foo_ro_pipe(%opencl.pipe_ro_t addrspace(1)* %p)
+// CHECK_AMDGCN: @foo_ro_pipe(%opencl.pipe_ro_t addrspace(1)* %p)
+
+kernel void foo_wo_pipe(write_only pipe int p) {}
+// CHECK-SPIR: @foo_wo_pipe(%opencl.pipe_wo_t addrspace(1)* %p)
+// CHECK_AMDGCN: @foo_wo_pipe(%opencl.pipe_wo_t addrspace(1)* %p)
void __attribute__((overloadable)) bad1(image1d_t b, image2d_t c, image2d_t d) {}
// CHECK-SPIR-LABEL: @{{_Z4bad114ocl_image1d_ro14ocl_image2d_roS0_|"\\01\?bad1@@\$\$J0YAXPAUocl_image1d_ro@@PAUocl_image2d_ro@@1@Z"}}
-// CHECK-AMDGCN-LABEL: @{{_Z4bad114ocl_image1d_ro14ocl_image2d_roS0_|"\\01\?bad1@@\$\$J0YAXPAUocl_image1d_ro@@PAUocl_image2d_ro@@1@Z"}}(%opencl.image1d_ro_t addrspace(2)*{{.*}}%opencl.image2d_ro_t addrspace(2)*{{.*}}%opencl.image2d_ro_t addrspace(2)*{{.*}})
+// CHECK-AMDGCN-LABEL: @{{_Z4bad114ocl_image1d_ro14ocl_image2d_roS0_|"\\01\?bad1@@\$\$J0YAXPAUocl_image1d_ro@@PAUocl_image2d_ro@@1@Z"}}(%opencl.image1d_ro_t addrspace(4)*{{.*}}%opencl.image2d_ro_t addrspace(4)*{{.*}}%opencl.image2d_ro_t addrspace(4)*{{.*}})
diff --git a/test/CodeGenOpenCL/partial_initializer.cl b/test/CodeGenOpenCL/partial_initializer.cl
index 454c82f89299..ee6be919a7fa 100644
--- a/test/CodeGenOpenCL/partial_initializer.cl
+++ b/test/CodeGenOpenCL/partial_initializer.cl
@@ -36,17 +36,17 @@ void f(void) {
// CHECK: %[[V2:.*]] = alloca <4 x i32>, align 16
// CHECK: %[[v0:.*]] = bitcast [6 x [6 x float]]* %A to i8*
- // CHECK: call void @llvm.memset.p0i8.i32(i8* %[[v0]], i8 0, i32 144, i32 4, i1 false)
+ // CHECK: call void @llvm.memset.p0i8.i32(i8* align 4 %[[v0]], i8 0, i32 144, i1 false)
// CHECK: %[[v1:.*]] = bitcast i8* %[[v0]] to [6 x [6 x float]]*
- // CHECK: %[[v2:.*]] = getelementptr [6 x [6 x float]], [6 x [6 x float]]* %[[v1]], i32 0, i32 0
- // CHECK: %[[v3:.*]] = getelementptr [6 x float], [6 x float]* %[[v2]], i32 0, i32 0
- // CHECK: store float 1.000000e+00, float* %[[v3]]
- // CHECK: %[[v4:.*]] = getelementptr [6 x float], [6 x float]* %[[v2]], i32 0, i32 1
- // CHECK: store float 2.000000e+00, float* %[[v4]]
+ // CHECK: %[[v2:.*]] = getelementptr inbounds [6 x [6 x float]], [6 x [6 x float]]* %[[v1]], i32 0, i32 0
+ // CHECK: %[[v3:.*]] = getelementptr inbounds [6 x float], [6 x float]* %[[v2]], i32 0, i32 0
+ // CHECK: store float 1.000000e+00, float* %[[v3]], align 4
+ // CHECK: %[[v4:.*]] = getelementptr inbounds [6 x float], [6 x float]* %[[v2]], i32 0, i32 1
+ // CHECK: store float 2.000000e+00, float* %[[v4]], align 4
float A[6][6] = {1.0f, 2.0f};
// CHECK: %[[v5:.*]] = bitcast %struct.StrucTy* %S to i8*
- // CHECK: call void @llvm.memcpy.p0i8.p2i8.i32(i8* %[[v5]], i8 addrspace(2)* bitcast (%struct.StrucTy addrspace(2)* @f.S to i8 addrspace(2)*), i32 12, i32 4, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p2i8.i32(i8* align 4 %[[v5]], i8 addrspace(2)* align 4 bitcast (%struct.StrucTy addrspace(2)* @f.S to i8 addrspace(2)*), i32 12, i1 false)
StrucTy S = {1, 2};
// CHECK: store <2 x i32> <i32 1, i32 2>, <2 x i32>* %[[compoundliteral1]], align 8
diff --git a/test/CodeGenOpenCL/pipe_builtin.cl b/test/CodeGenOpenCL/pipe_builtin.cl
index 4b4b4ef97ab2..d912fce5e95d 100644
--- a/test/CodeGenOpenCL/pipe_builtin.cl
+++ b/test/CodeGenOpenCL/pipe_builtin.cl
@@ -1,68 +1,76 @@
// RUN: %clang_cc1 -emit-llvm -cl-ext=+cl_khr_subgroups -O0 -cl-std=CL2.0 -o - %s | FileCheck %s
-// CHECK: %opencl.pipe_t = type opaque
-// CHECK: %opencl.reserve_id_t = type opaque
+// CHECK-DAG: %opencl.pipe_ro_t = type opaque
+// CHECK-DAG: %opencl.pipe_wo_t = type opaque
+// CHECK-DAG: %opencl.reserve_id_t = type opaque
#pragma OPENCL EXTENSION cl_khr_subgroups : enable
void test1(read_only pipe int p, global int *ptr) {
- // CHECK: call i32 @__read_pipe_2(%opencl.pipe_t* %{{.*}}, i8* %{{.*}}, i32 4, i32 4)
+ // CHECK: call i32 @__read_pipe_2(%opencl.pipe_ro_t* %{{.*}}, i8* %{{.*}}, i32 4, i32 4)
read_pipe(p, ptr);
- // CHECK: call %opencl.reserve_id_t* @__reserve_read_pipe(%opencl.pipe_t* %{{.*}}, i32 {{.*}}, i32 4, i32 4)
+ // CHECK: call %opencl.reserve_id_t* @__reserve_read_pipe(%opencl.pipe_ro_t* %{{.*}}, i32 {{.*}}, i32 4, i32 4)
reserve_id_t rid = reserve_read_pipe(p, 2);
- // CHECK: call i32 @__read_pipe_4(%opencl.pipe_t* %{{.*}}, %opencl.reserve_id_t* %{{.*}}, i32 {{.*}}, i8* %{{.*}}, i32 4, i32 4)
+ // CHECK: call i32 @__read_pipe_4(%opencl.pipe_ro_t* %{{.*}}, %opencl.reserve_id_t* %{{.*}}, i32 {{.*}}, i8* %{{.*}}, i32 4, i32 4)
read_pipe(p, rid, 2, ptr);
- // CHECK: call void @__commit_read_pipe(%opencl.pipe_t* %{{.*}}, %opencl.reserve_id_t* %{{.*}}, i32 4, i32 4)
+ // CHECK: call void @__commit_read_pipe(%opencl.pipe_ro_t* %{{.*}}, %opencl.reserve_id_t* %{{.*}}, i32 4, i32 4)
commit_read_pipe(p, rid);
}
void test2(write_only pipe int p, global int *ptr) {
- // CHECK: call i32 @__write_pipe_2(%opencl.pipe_t* %{{.*}}, i8* %{{.*}}, i32 4, i32 4)
+ // CHECK: call i32 @__write_pipe_2(%opencl.pipe_wo_t* %{{.*}}, i8* %{{.*}}, i32 4, i32 4)
write_pipe(p, ptr);
- // CHECK: call %opencl.reserve_id_t* @__reserve_write_pipe(%opencl.pipe_t* %{{.*}}, i32 {{.*}}, i32 4, i32 4)
+ // CHECK: call %opencl.reserve_id_t* @__reserve_write_pipe(%opencl.pipe_wo_t* %{{.*}}, i32 {{.*}}, i32 4, i32 4)
reserve_id_t rid = reserve_write_pipe(p, 2);
- // CHECK: call i32 @__write_pipe_4(%opencl.pipe_t* %{{.*}}, %opencl.reserve_id_t* %{{.*}}, i32 {{.*}}, i8* %{{.*}}, i32 4, i32 4)
+ // CHECK: call i32 @__write_pipe_4(%opencl.pipe_wo_t* %{{.*}}, %opencl.reserve_id_t* %{{.*}}, i32 {{.*}}, i8* %{{.*}}, i32 4, i32 4)
write_pipe(p, rid, 2, ptr);
- // CHECK: call void @__commit_write_pipe(%opencl.pipe_t* %{{.*}}, %opencl.reserve_id_t* %{{.*}}, i32 4, i32 4)
+ // CHECK: call void @__commit_write_pipe(%opencl.pipe_wo_t* %{{.*}}, %opencl.reserve_id_t* %{{.*}}, i32 4, i32 4)
commit_write_pipe(p, rid);
}
void test3(read_only pipe int p, global int *ptr) {
- // CHECK: call %opencl.reserve_id_t* @__work_group_reserve_read_pipe(%opencl.pipe_t* %{{.*}}, i32 {{.*}}, i32 4, i32 4)
+ // CHECK: call %opencl.reserve_id_t* @__work_group_reserve_read_pipe(%opencl.pipe_ro_t* %{{.*}}, i32 {{.*}}, i32 4, i32 4)
reserve_id_t rid = work_group_reserve_read_pipe(p, 2);
- // CHECK: call void @__work_group_commit_read_pipe(%opencl.pipe_t* %{{.*}}, %opencl.reserve_id_t* %{{.*}}, i32 4, i32 4)
+ // CHECK: call void @__work_group_commit_read_pipe(%opencl.pipe_ro_t* %{{.*}}, %opencl.reserve_id_t* %{{.*}}, i32 4, i32 4)
work_group_commit_read_pipe(p, rid);
}
void test4(write_only pipe int p, global int *ptr) {
- // CHECK: call %opencl.reserve_id_t* @__work_group_reserve_write_pipe(%opencl.pipe_t* %{{.*}}, i32 {{.*}}, i32 4, i32 4)
+ // CHECK: call %opencl.reserve_id_t* @__work_group_reserve_write_pipe(%opencl.pipe_wo_t* %{{.*}}, i32 {{.*}}, i32 4, i32 4)
reserve_id_t rid = work_group_reserve_write_pipe(p, 2);
- // CHECK: call void @__work_group_commit_write_pipe(%opencl.pipe_t* %{{.*}}, %opencl.reserve_id_t* %{{.*}}, i32 4, i32 4)
+ // CHECK: call void @__work_group_commit_write_pipe(%opencl.pipe_wo_t* %{{.*}}, %opencl.reserve_id_t* %{{.*}}, i32 4, i32 4)
work_group_commit_write_pipe(p, rid);
}
void test5(read_only pipe int p, global int *ptr) {
- // CHECK: call %opencl.reserve_id_t* @__sub_group_reserve_read_pipe(%opencl.pipe_t* %{{.*}}, i32 {{.*}}, i32 4, i32 4)
+ // CHECK: call %opencl.reserve_id_t* @__sub_group_reserve_read_pipe(%opencl.pipe_ro_t* %{{.*}}, i32 {{.*}}, i32 4, i32 4)
reserve_id_t rid = sub_group_reserve_read_pipe(p, 2);
- // CHECK: call void @__sub_group_commit_read_pipe(%opencl.pipe_t* %{{.*}}, %opencl.reserve_id_t* %{{.*}}, i32 4, i32 4)
+ // CHECK: call void @__sub_group_commit_read_pipe(%opencl.pipe_ro_t* %{{.*}}, %opencl.reserve_id_t* %{{.*}}, i32 4, i32 4)
sub_group_commit_read_pipe(p, rid);
}
void test6(write_only pipe int p, global int *ptr) {
- // CHECK: call %opencl.reserve_id_t* @__sub_group_reserve_write_pipe(%opencl.pipe_t* %{{.*}}, i32 {{.*}}, i32 4, i32 4)
+ // CHECK: call %opencl.reserve_id_t* @__sub_group_reserve_write_pipe(%opencl.pipe_wo_t* %{{.*}}, i32 {{.*}}, i32 4, i32 4)
reserve_id_t rid = sub_group_reserve_write_pipe(p, 2);
- // CHECK: call void @__sub_group_commit_write_pipe(%opencl.pipe_t* %{{.*}}, %opencl.reserve_id_t* %{{.*}}, i32 4, i32 4)
+ // CHECK: call void @__sub_group_commit_write_pipe(%opencl.pipe_wo_t* %{{.*}}, %opencl.reserve_id_t* %{{.*}}, i32 4, i32 4)
sub_group_commit_write_pipe(p, rid);
}
-void test7(write_only pipe int p, global int *ptr) {
- // CHECK: call i32 @__get_pipe_num_packets(%opencl.pipe_t* %{{.*}}, i32 4, i32 4)
+void test7(read_only pipe int p, global int *ptr) {
+ // CHECK: call i32 @__get_pipe_num_packets_ro(%opencl.pipe_ro_t* %{{.*}}, i32 4, i32 4)
*ptr = get_pipe_num_packets(p);
- // CHECK: call i32 @__get_pipe_max_packets(%opencl.pipe_t* %{{.*}}, i32 4, i32 4)
+ // CHECK: call i32 @__get_pipe_max_packets_ro(%opencl.pipe_ro_t* %{{.*}}, i32 4, i32 4)
*ptr = get_pipe_max_packets(p);
}
-void test8(read_only pipe int r, write_only pipe int w, global int *ptr) {
+void test8(write_only pipe int p, global int *ptr) {
+ // CHECK: call i32 @__get_pipe_num_packets_wo(%opencl.pipe_wo_t* %{{.*}}, i32 4, i32 4)
+ *ptr = get_pipe_num_packets(p);
+ // CHECK: call i32 @__get_pipe_max_packets_wo(%opencl.pipe_wo_t* %{{.*}}, i32 4, i32 4)
+ *ptr = get_pipe_max_packets(p);
+}
+
+void test9(read_only pipe int r, write_only pipe int w, global int *ptr) {
// verify that return type is correctly casted to i1 value
// CHECK: %[[R:[0-9]+]] = call i32 @__read_pipe_2
// CHECK: icmp ne i32 %[[R]], 0
@@ -70,10 +78,16 @@ void test8(read_only pipe int r, write_only pipe int w, global int *ptr) {
// CHECK: %[[W:[0-9]+]] = call i32 @__write_pipe_2
// CHECK: icmp ne i32 %[[W]], 0
if (write_pipe(w, ptr)) *ptr = -1;
- // CHECK: %[[N:[0-9]+]] = call i32 @__get_pipe_num_packets
- // CHECK: icmp ne i32 %[[N]], 0
+ // CHECK: %[[NR:[0-9]+]] = call i32 @__get_pipe_num_packets_ro
+ // CHECK: icmp ne i32 %[[NR]], 0
if (get_pipe_num_packets(r)) *ptr = -1;
- // CHECK: %[[M:[0-9]+]] = call i32 @__get_pipe_max_packets
- // CHECK: icmp ne i32 %[[M]], 0
+ // CHECK: %[[NW:[0-9]+]] = call i32 @__get_pipe_num_packets_wo
+ // CHECK: icmp ne i32 %[[NW]], 0
+ if (get_pipe_num_packets(w)) *ptr = -1;
+ // CHECK: %[[MR:[0-9]+]] = call i32 @__get_pipe_max_packets_ro
+ // CHECK: icmp ne i32 %[[MR]], 0
+ if (get_pipe_max_packets(r)) *ptr = -1;
+ // CHECK: %[[MW:[0-9]+]] = call i32 @__get_pipe_max_packets_wo
+ // CHECK: icmp ne i32 %[[MW]], 0
if (get_pipe_max_packets(w)) *ptr = -1;
}
diff --git a/test/CodeGenOpenCL/pipe_types.cl b/test/CodeGenOpenCL/pipe_types.cl
index 7c11f74ad7b9..ba064c6d7557 100644
--- a/test/CodeGenOpenCL/pipe_types.cl
+++ b/test/CodeGenOpenCL/pipe_types.cl
@@ -1,34 +1,35 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -O0 -cl-std=CL2.0 -o - %s | FileCheck %s
-// CHECK: %opencl.pipe_t = type opaque
+// CHECK: %opencl.pipe_ro_t = type opaque
+// CHECK: %opencl.pipe_wo_t = type opaque
typedef unsigned char __attribute__((ext_vector_type(3))) uchar3;
typedef int __attribute__((ext_vector_type(4))) int4;
void test1(read_only pipe int p) {
-// CHECK: define void @test1(%opencl.pipe_t* %p)
+// CHECK: define void @test1(%opencl.pipe_ro_t* %p)
reserve_id_t rid;
// CHECK: %rid = alloca %opencl.reserve_id_t
}
void test2(write_only pipe float p) {
-// CHECK: define void @test2(%opencl.pipe_t* %p)
+// CHECK: define void @test2(%opencl.pipe_wo_t* %p)
}
void test3(read_only pipe const int p) {
-// CHECK: define void @test3(%opencl.pipe_t* %p)
+// CHECK: define void @test3(%opencl.pipe_ro_t* %p)
}
void test4(read_only pipe uchar3 p) {
-// CHECK: define void @test4(%opencl.pipe_t* %p)
+// CHECK: define void @test4(%opencl.pipe_ro_t* %p)
}
void test5(read_only pipe int4 p) {
-// CHECK: define void @test5(%opencl.pipe_t* %p)
+// CHECK: define void @test5(%opencl.pipe_ro_t* %p)
}
typedef read_only pipe int MyPipe;
kernel void test6(MyPipe p) {
-// CHECK: define spir_kernel void @test6(%opencl.pipe_t* %p)
+// CHECK: define spir_kernel void @test6(%opencl.pipe_ro_t* %p)
}
struct Person {
@@ -41,7 +42,7 @@ void test_reserved_read_pipe(global struct Person *SDst,
read_only pipe struct Person SPipe) {
// CHECK: define void @test_reserved_read_pipe
read_pipe (SPipe, SDst);
- // CHECK: call i32 @__read_pipe_2(%opencl.pipe_t* %{{.*}}, i8* %{{.*}}, i32 16, i32 8)
+ // CHECK: call i32 @__read_pipe_2(%opencl.pipe_ro_t* %{{.*}}, i8* %{{.*}}, i32 16, i32 8)
read_pipe (SPipe, SDst);
- // CHECK: call i32 @__read_pipe_2(%opencl.pipe_t* %{{.*}}, i8* %{{.*}}, i32 16, i32 8)
+ // CHECK: call i32 @__read_pipe_2(%opencl.pipe_ro_t* %{{.*}}, i8* %{{.*}}, i32 16, i32 8)
}
diff --git a/test/CodeGenOpenCL/private-array-initialization.cl b/test/CodeGenOpenCL/private-array-initialization.cl
index a7d4a9891977..9aa058dcfacf 100644
--- a/test/CodeGenOpenCL/private-array-initialization.cl
+++ b/test/CodeGenOpenCL/private-array-initialization.cl
@@ -1,9 +1,33 @@
-// RUN: %clang_cc1 %s -triple spir-unknown-unknown -O0 -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple spir-unknown-unknown -O0 -emit-llvm -o - | FileCheck -check-prefix=PRIVATE0 %s
+// RUN: %clang_cc1 %s -triple amdgcn-amd-amdhsa-unknown -O0 -emit-llvm -o - | FileCheck -check-prefix=PRIVATE5 %s
// CHECK: @test.arr = private unnamed_addr addrspace(2) constant [3 x i32] [i32 1, i32 2, i32 3], align 4
void test() {
__private int arr[] = {1, 2, 3};
-// CHECK: %[[arr_i8_ptr:[0-9]+]] = bitcast [3 x i32]* %arr to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p2i8.i32(i8* %[[arr_i8_ptr]], i8 addrspace(2)* bitcast ([3 x i32] addrspace(2)* @test.arr to i8 addrspace(2)*), i32 12, i32 4, i1 false)
+// PRIVATE0: %[[arr_i8_ptr:[0-9]+]] = bitcast [3 x i32]* %arr to i8*
+// PRIVATE0: call void @llvm.memcpy.p0i8.p2i8.i32(i8* align 4 %[[arr_i8_ptr]], i8 addrspace(2)* align 4 bitcast ([3 x i32] addrspace(2)* @test.arr to i8 addrspace(2)*), i32 12, i1 false)
+
+// PRIVATE5: %arr = alloca [3 x i32], align 4, addrspace(5)
+// PRIVATE5: %0 = bitcast [3 x i32] addrspace(5)* %arr to i8 addrspace(5)*
+// PRIVATE5: call void @llvm.memcpy.p5i8.p4i8.i64(i8 addrspace(5)* align 4 %0, i8 addrspace(4)* align 4 bitcast ([3 x i32] addrspace(4)* @test.arr to i8 addrspace(4)*), i64 12, i1 false)
+}
+
+__kernel void initializer_cast_is_valid_crash() {
+// PRIVATE0: %v512 = alloca [64 x i8], align 1
+// PRIVATE0: %0 = bitcast [64 x i8]* %v512 to i8*
+// PRIVATE0: call void @llvm.memset.p0i8.i32(i8* align 1 %0, i8 0, i32 64, i1 false)
+// PRIVATE0: %1 = bitcast i8* %0 to [64 x i8]*
+
+
+// PRIVATE5: %v512 = alloca [64 x i8], align 1, addrspace(5)
+// PRIVATE5: %0 = bitcast [64 x i8] addrspace(5)* %v512 to i8 addrspace(5)*
+// PRIVATE5: call void @llvm.memset.p5i8.i64(i8 addrspace(5)* align 1 %0, i8 0, i64 64, i1 false)
+// PRIVATE5: %1 = bitcast i8 addrspace(5)* %0 to [64 x i8] addrspace(5)*
+ unsigned char v512[64] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00
+ };
}
diff --git a/test/CodeGenOpenCL/shifts.cl b/test/CodeGenOpenCL/shifts.cl
index 14cd7aff65be..7011a4234bb5 100644
--- a/test/CodeGenOpenCL/shifts.cl
+++ b/test/CodeGenOpenCL/shifts.cl
@@ -58,16 +58,17 @@ int4 vectorVectorTest(int4 a,int4 b) {
return f;
}
-//OPT: @vectorScalarTest
+//NOOPT-LABEL: @vectorScalarTest
int4 vectorScalarTest(int4 a,int b) {
- //OPT: [[SP0:%.+]] = insertelement <4 x i32> undef, i32 %b, i32 0
- //OPT: [[SP1:%.+]] = shufflevector <4 x i32> [[SP0]], <4 x i32> undef, <4 x i32> zeroinitializer
- //OPT: [[VSM:%.+]] = and <4 x i32> [[SP1]], <i32 31, i32 31, i32 31, i32 31>
- //OPT-NEXT: [[VSC:%.+]] = shl <4 x i32> %a, [[VSM]]
+ //NOOPT: [[SP0:%.+]] = insertelement <4 x i32> undef
+ //NOOPT: [[SP1:%.+]] = shufflevector <4 x i32> [[SP0]], <4 x i32> undef, <4 x i32> zeroinitializer
+ //NOOPT: [[VSM:%.+]] = and <4 x i32> [[SP1]], <i32 31, i32 31, i32 31, i32 31>
+ //NOOPT: [[VSC:%.+]] = shl <4 x i32> [[VSS:%.+]], [[VSM]]
int4 c = a << b;
- //OPT-NEXT: [[VSF:%.+]] = add <4 x i32> [[VSC]], <i32 4, i32 4, i32 4, i32 4>
+ //NOOPT: [[VSF:%.+]] = shl <4 x i32> [[VSC1:%.+]], <i32 2, i32 2, i32 2, i32 2>
+ //NOOPT: [[VSA:%.+]] = add <4 x i32> [[VSC2:%.+]], [[VSF]]
int4 d = {1, 1, 1, 1};
int4 f = c + (d << 34);
- //OPT-NEXT: ret <4 x i32> [[VSF]]
+ //NOOPT: ret <4 x i32>
return f;
}
diff --git a/test/CodeGenOpenCL/size_t.cl b/test/CodeGenOpenCL/size_t.cl
index 02950bb66270..63a062268da3 100644
--- a/test/CodeGenOpenCL/size_t.cl
+++ b/test/CodeGenOpenCL/size_t.cl
@@ -1,12 +1,14 @@
// RUN: %clang_cc1 %s -cl-std=CL2.0 -finclude-default-header -emit-llvm -O0 -triple spir-unknown-unknown -o - | FileCheck --check-prefix=SZ32 %s
// RUN: %clang_cc1 %s -cl-std=CL2.0 -finclude-default-header -emit-llvm -O0 -triple spir64-unknown-unknown -o - | FileCheck --check-prefix=SZ64 --check-prefix=SZ64ONLY %s
-// RUN: %clang_cc1 %s -cl-std=CL2.0 -finclude-default-header -emit-llvm -O0 -triple amdgcn -o - | FileCheck --check-prefix=SZ64 --check-prefix=AMDONLY %s
-// RUN: %clang_cc1 %s -cl-std=CL2.0 -finclude-default-header -emit-llvm -O0 -triple amdgcn---opencl -o - | FileCheck --check-prefix=SZ64 --check-prefix=AMDONLY %s
+// RUN: %clang_cc1 %s -cl-std=CL2.0 -finclude-default-header -emit-llvm -O0 -triple amdgcn -o - | FileCheck --check-prefix=SZ64 --check-prefix=AMDGCN %s
+// RUN: %clang_cc1 %s -cl-std=CL2.0 -finclude-default-header -emit-llvm -O0 -triple amdgcn---opencl -o - | FileCheck --check-prefix=SZ64 --check-prefix=AMDGCN %s
//SZ32: define{{.*}} i32 @test_ptrtoint_private(i8* %x)
//SZ32: ptrtoint i8* %{{.*}} to i32
-//SZ64: define{{.*}} i64 @test_ptrtoint_private(i8* %x)
-//SZ64: ptrtoint i8* %{{.*}} to i64
+//SZ64ONLY: define{{.*}} i64 @test_ptrtoint_private(i8* %x)
+//SZ64ONLY: ptrtoint i8* %{{.*}} to i64
+//AMDGCN: define{{.*}} i64 @test_ptrtoint_private(i8 addrspace(5)* %x)
+//AMDGCN: ptrtoint i8 addrspace(5)* %{{.*}} to i64
size_t test_ptrtoint_private(private char* x) {
return (size_t)x;
}
@@ -21,8 +23,10 @@ intptr_t test_ptrtoint_global(global char* x) {
//SZ32: define{{.*}} i32 @test_ptrtoint_constant(i8 addrspace(2)* %x)
//SZ32: ptrtoint i8 addrspace(2)* %{{.*}} to i32
-//SZ64: define{{.*}} i64 @test_ptrtoint_constant(i8 addrspace(2)* %x)
-//SZ64: ptrtoint i8 addrspace(2)* %{{.*}} to i64
+//SZ64ONLY: define{{.*}} i64 @test_ptrtoint_constant(i8 addrspace(2)* %x)
+//SZ64ONLY: ptrtoint i8 addrspace(2)* %{{.*}} to i64
+//AMDGCN: define{{.*}} i64 @test_ptrtoint_constant(i8 addrspace(4)* %x)
+//AMDGCN: ptrtoint i8 addrspace(4)* %{{.*}} to i64
uintptr_t test_ptrtoint_constant(constant char* x) {
return (uintptr_t)x;
}
@@ -37,18 +41,21 @@ size_t test_ptrtoint_local(local char* x) {
//SZ32: define{{.*}} i32 @test_ptrtoint_generic(i8 addrspace(4)* %x)
//SZ32: ptrtoint i8 addrspace(4)* %{{.*}} to i32
-//SZ64: define{{.*}} i64 @test_ptrtoint_generic(i8 addrspace(4)* %x)
-//SZ64: ptrtoint i8 addrspace(4)* %{{.*}} to i64
+//SZ64ONLY: define{{.*}} i64 @test_ptrtoint_generic(i8 addrspace(4)* %x)
+//SZ64ONLY: ptrtoint i8 addrspace(4)* %{{.*}} to i64
+//AMDGCN: define{{.*}} i64 @test_ptrtoint_generic(i8* %x)
+//AMDGCN: ptrtoint i8* %{{.*}} to i64
size_t test_ptrtoint_generic(generic char* x) {
return (size_t)x;
}
//SZ32: define{{.*}} i8* @test_inttoptr_private(i32 %x)
//SZ32: inttoptr i32 %{{.*}} to i8*
-//SZ64: define{{.*}} i8* @test_inttoptr_private(i64 %x)
-//AMDONLY: trunc i64 %{{.*}} to i32
-//AMDONLY: inttoptr i32 %{{.*}} to i8*
+//SZ64ONLY: define{{.*}} i8* @test_inttoptr_private(i64 %x)
//SZ64ONLY: inttoptr i64 %{{.*}} to i8*
+//AMDGCN: define{{.*}} i8 addrspace(5)* @test_inttoptr_private(i64 %x)
+//AMDGCN: trunc i64 %{{.*}} to i32
+//AMDGCN: inttoptr i32 %{{.*}} to i8 addrspace(5)*
private char* test_inttoptr_private(size_t x) {
return (private char*)x;
}
@@ -64,8 +71,8 @@ global char* test_inttoptr_global(size_t x) {
//SZ32: define{{.*}} i8 addrspace(3)* @test_add_local(i8 addrspace(3)* %x, i32 %y)
//SZ32: getelementptr inbounds i8, i8 addrspace(3)* %{{.*}}, i32
//SZ64: define{{.*}} i8 addrspace(3)* @test_add_local(i8 addrspace(3)* %x, i64 %y)
-//AMDONLY: trunc i64 %{{.*}} to i32
-//AMDONLY: getelementptr inbounds i8, i8 addrspace(3)* %{{.*}}, i32
+//AMDGCN: trunc i64 %{{.*}} to i32
+//AMDGCN: getelementptr inbounds i8, i8 addrspace(3)* %{{.*}}, i32
//SZ64ONLY: getelementptr inbounds i8, i8 addrspace(3)* %{{.*}}, i64
local char* test_add_local(local char* x, ptrdiff_t y) {
return x + y;
@@ -92,9 +99,12 @@ ptrdiff_t test_sub_local(local char* x, local char *y) {
//SZ32: define{{.*}} i32 @test_sub_private(i8* %x, i8* %y)
//SZ32: ptrtoint i8* %{{.*}} to i32
//SZ32: ptrtoint i8* %{{.*}} to i32
-//SZ64: define{{.*}} i64 @test_sub_private(i8* %x, i8* %y)
-//SZ64: ptrtoint i8* %{{.*}} to i64
-//SZ64: ptrtoint i8* %{{.*}} to i64
+//SZ64ONLY: define{{.*}} i64 @test_sub_private(i8* %x, i8* %y)
+//SZ64ONLY: ptrtoint i8* %{{.*}} to i64
+//SZ64ONLY: ptrtoint i8* %{{.*}} to i64
+//AMDGCN: define{{.*}} i64 @test_sub_private(i8 addrspace(5)* %x, i8 addrspace(5)* %y)
+//AMDGCN: ptrtoint i8 addrspace(5)* %{{.*}} to i64
+//AMDGCN: ptrtoint i8 addrspace(5)* %{{.*}} to i64
ptrdiff_t test_sub_private(private char* x, private char *y) {
return x - y;
}
@@ -102,9 +112,12 @@ ptrdiff_t test_sub_private(private char* x, private char *y) {
//SZ32: define{{.*}} i32 @test_sub_mix(i8* %x, i8 addrspace(4)* %y)
//SZ32: ptrtoint i8* %{{.*}} to i32
//SZ32: ptrtoint i8 addrspace(4)* %{{.*}} to i32
-//SZ64: define{{.*}} i64 @test_sub_mix(i8* %x, i8 addrspace(4)* %y)
-//SZ64: ptrtoint i8* %{{.*}} to i64
-//SZ64: ptrtoint i8 addrspace(4)* %{{.*}} to i64
+//SZ64ONLY: define{{.*}} i64 @test_sub_mix(i8* %x, i8 addrspace(4)* %y)
+//SZ64ONLY: ptrtoint i8* %{{.*}} to i64
+//SZ64ONLY: ptrtoint i8 addrspace(4)* %{{.*}} to i64
+//AMDGCN: define{{.*}} i64 @test_sub_mix(i8 addrspace(5)* %x, i8* %y)
+//AMDGCN: ptrtoint i8 addrspace(5)* %{{.*}} to i64
+//AMDGCN: ptrtoint i8* %{{.*}} to i64
ptrdiff_t test_sub_mix(private char* x, generic char *y) {
return x - y;
}
diff --git a/test/CodeGenOpenCL/str_literals.cl b/test/CodeGenOpenCL/str_literals.cl
index 8fe5cefc8d75..514044cdcc7d 100644
--- a/test/CodeGenOpenCL/str_literals.cl
+++ b/test/CodeGenOpenCL/str_literals.cl
@@ -1,9 +1,15 @@
// RUN: %clang_cc1 %s -cl-opt-disable -emit-llvm -o - -ffake-address-space-map | FileCheck %s
-__constant char * __constant x = "hello world";
-__constant char * __constant y = "hello world";
+__constant char *__constant x = "hello world";
+__constant char *__constant y = "hello world";
-// CHECK: unnamed_addr addrspace(2) constant
+// CHECK: unnamed_addr addrspace(2) constant{{.*}}"hello world\00"
// CHECK-NOT: addrspace(2) unnamed_addr constant
-// CHECK: @x = addrspace(2) constant i8 addrspace(2)*
-// CHECK: @y = addrspace(2) constant i8 addrspace(2)*
+// CHECK: @x = {{(dso_local )?}}addrspace(2) constant i8 addrspace(2)*
+// CHECK: @y = {{(dso_local )?}}addrspace(2) constant i8 addrspace(2)*
+// CHECK: unnamed_addr addrspace(2) constant{{.*}}"f\00"
+
+void f() {
+ //CHECK: store i8 addrspace(2)* {{.*}}, i8 addrspace(2)**
+ constant const char *f3 = __func__;
+}
diff --git a/test/CodeGenOpenCL/vla.cl b/test/CodeGenOpenCL/vla.cl
index 5d3599fc3cce..f3d868a7b21b 100644
--- a/test/CodeGenOpenCL/vla.cl
+++ b/test/CodeGenOpenCL/vla.cl
@@ -1,13 +1,14 @@
// RUN: %clang_cc1 -emit-llvm -triple "spir-unknown-unknown" -O0 -cl-std=CL2.0 -o - %s | FileCheck -check-prefixes=CHECK,SPIR %s
-// RUN: %clang_cc1 -emit-llvm -triple amdgcn-amd-amdhsa-opencl -O0 -cl-std=CL2.0 -o - %s | FileCheck -check-prefixes=CHECK,SPIR %s
-// RUN: %clang_cc1 -emit-llvm -triple amdgcn-amd-amdhsa-amdgizcl -O0 -cl-std=CL2.0 -o - %s | FileCheck -check-prefixes=CHECK,GIZ %s
+// RUN: %clang_cc1 -emit-llvm -triple amdgcn-amd-amdhsa -O0 -cl-std=CL2.0 -o - %s | FileCheck -check-prefixes=CHECK,AMDGCN %s
constant int sz0 = 5;
-// CHECK: @sz0 = addrspace(2) constant i32 5
+// SPIR: @sz0 = addrspace(2) constant i32 5
+// AMDGCN: @sz0 = addrspace(4) constant i32 5
const global int sz1 = 16;
// CHECK: @sz1 = addrspace(1) constant i32 16
const constant int sz2 = 8;
-// CHECK: @sz2 = addrspace(2) constant i32 8
+// SPIR: @sz2 = addrspace(2) constant i32 8
+// AMDGCN: @sz2 = addrspace(4) constant i32 8
// CHECK: @testvla.vla2 = internal addrspace(3) global [8 x i16] undef
kernel void testvla()
@@ -15,10 +16,10 @@ kernel void testvla()
int vla0[sz0];
// SPIR: %vla0 = alloca [5 x i32]
// SPIR-NOT: %vla0 = alloca [5 x i32]{{.*}}addrspace
-// GIZ: %vla0 = alloca [5 x i32]{{.*}}addrspace(5)
+// AMDGCN: %vla0 = alloca [5 x i32]{{.*}}addrspace(5)
char vla1[sz1];
// SPIR: %vla1 = alloca [16 x i8]
// SPIR-NOT: %vla1 = alloca [16 x i8]{{.*}}addrspace
-// GIZ: %vla1 = alloca [16 x i8]{{.*}}addrspace(5)
+// AMDGCN: %vla1 = alloca [16 x i8]{{.*}}addrspace(5)
local short vla2[sz2];
}
diff --git a/test/Coverage/ast-printing.m b/test/Coverage/ast-printing.m
index 81c3a6b0ba53..d9909b285915 100644
--- a/test/Coverage/ast-printing.m
+++ b/test/Coverage/ast-printing.m
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -fsyntax-only -fobjc-exceptions %s
-// RUN: %clang_cc1 -ast-print -fobjc-exceptions %s
-// RUN: %clang_cc1 -ast-dump -fobjc-exceptions %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.10 -fsyntax-only -fobjc-exceptions %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.10 -ast-print -fobjc-exceptions %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.10 -ast-dump -fobjc-exceptions %s
#include "objc-language-features.inc"
diff --git a/test/Coverage/html-multifile-diagnostics.c b/test/Coverage/html-multifile-diagnostics.c
index abd54ae83938..39cddc99ba6f 100644
--- a/test/Coverage/html-multifile-diagnostics.c
+++ b/test/Coverage/html-multifile-diagnostics.c
@@ -4,6 +4,8 @@
// REQUIRES: staticanalyzer
+// CHECK: <!-- FILENAME html-multifile-diagnostics.h -->
+
// CHECK: <h3>Annotated Source Code</h3>
// Make sure it's generated as multi-file HTML output
diff --git a/test/CoverageMapping/break.c b/test/CoverageMapping/break.c
index d42c1bd082d2..08461d7ed2de 100644
--- a/test/CoverageMapping/break.c
+++ b/test/CoverageMapping/break.c
@@ -31,3 +31,14 @@ int main() { // CHECK: File 0, [[@LINE]]:12 -> {{[0-9]+}}:2 = #0
++cnt;
}
}
+
+// CHECK-LABEL: break_continue_in_increment:
+// CHECK: [[@LINE+6]]:11 -> [[@LINE+6]]:45 = #1
+// CHECK: [[@LINE+5]]:18 -> [[@LINE+5]]:19 = #1
+// CHECK: [[@LINE+4]]:21 -> [[@LINE+4]]:26 = #2
+// CHECK: [[@LINE+3]]:33 -> [[@LINE+3]]:41 = (#1 - #2)
+// CHECK: [[@LINE+3]]:5 -> [[@LINE+3]]:6 = #1
+void break_continue_in_increment(int x) {
+ for (;; ({ if (x) break; else continue; }))
+ ;
+}
diff --git a/test/CoverageMapping/classtemplate.cpp b/test/CoverageMapping/classtemplate.cpp
index 0ccdcb2431b5..0dbb0c0ede84 100644
--- a/test/CoverageMapping/classtemplate.cpp
+++ b/test/CoverageMapping/classtemplate.cpp
@@ -2,6 +2,7 @@
// RUN: FileCheck -input-file %tmapping %s --check-prefix=CHECK-CONSTRUCTOR
// RUN: FileCheck -input-file %tmapping %s --check-prefix=CHECK-GETTER
// RUN: FileCheck -input-file %tmapping %s --check-prefix=CHECK-SETTER
+// RUN: FileCheck -input-file %tmapping %s --check-prefix=CHECK-INIT-LIST
template<class TT>
class Test {
@@ -44,11 +45,51 @@ template <class T> class Test3 {
void unmangleable(UninstantiatedClassWithTraits<T> x) {}
};
+void abort() __attribute__((noreturn));
+
+namespace std {
+typedef decltype(sizeof(int)) size_t;
+
+template <typename E> struct initializer_list {
+ const E *p;
+ size_t n;
+ initializer_list(const E *p, size_t n) : p(p), n(n) {}
+};
+
+template <typename F, typename S> struct pair {
+ F f;
+ S s;
+ pair(const F &f, const S &s) : f(f), s(s) {}
+};
+
+struct string {
+ const char *str;
+ string() { abort(); }
+ string(const char *S) : str(S) {}
+ ~string() { abort(); }
+};
+
+template<typename K, typename V>
+struct map {
+ using T = pair<K, V>;
+ map(initializer_list<T> i, const string &s = string()) {}
+ ~map() { abort(); }
+};
+
+}; // namespace std
+
+// CHECK-INIT-LIST-LABEL: _Z5Test4v:
+std::map<int, int> Test4() { // CHECK-INIT-LIST: File 0, [[@LINE]]:28 -> [[@LINE+3]]:2 = #0
+ abort();
+ return std::map<int, int>{{0, 0}}; // CHECK-INIT-LIST-NEXT: [[@LINE]]:3 -> [[@LINE]]:36 = 0
+}
+
int main() {
Test<unsigned> t;
t.set(Test<unsigned>::A, 5.5);
t.set(Test<unsigned>::T, 5.6);
t.set(Test<unsigned>::G, 5.7);
t.set(Test<unsigned>::C, 5.8);
+ Test4();
return 0;
}
diff --git a/test/CoverageMapping/deferred-region.cpp b/test/CoverageMapping/deferred-region.cpp
index 5a104f778979..45113e46f02b 100644
--- a/test/CoverageMapping/deferred-region.cpp
+++ b/test/CoverageMapping/deferred-region.cpp
@@ -7,11 +7,12 @@
void foo(int x) {
if (x == 0) {
return;
- } // CHECK: Gap,File 0, [[@LINE]]:4 -> [[@LINE+2]]:2 = (#0 - #1)
-
+ } // CHECK-NOT: Gap,File 0, [[@LINE]]:4
+ //< Don't complete the last deferred region in a decl, even though it may
+ //< leave some whitespace marked with the same counter as the final return.
}
-// CHECK-NEXT: _Z4foooi:
+// CHECK-LABEL: _Z4foooi:
void fooo(int x) {
if (x == 0) {
return;
@@ -19,7 +20,7 @@ void fooo(int x) {
if (x == 1) {
return;
- } // CHECK: Gap,File 0, [[@LINE]]:4 -> [[@LINE+2]]:2 = ((#0 - #1) - #2)
+ } // CHECK-NOT: Gap,File 0, [[@LINE]]:4
}
@@ -108,7 +109,7 @@ void weird_if() {
}
if (false)
- return; // CHECK: Gap,File 0, [[@LINE]]:11 -> [[@LINE+1]]:2
+ return; // CHECK-NOT: Gap,File 0, [[@LINE]]:11
}
// CHECK-LABEL: _Z8for_loopv:
@@ -167,7 +168,18 @@ void gotos() {
return; // CHECK: [[@LINE]]:3 -> [[@LINE+4]]:2 = (#0 - #1)
out:
- return; // CHECK: Gap,File 0, [[@LINE]]:8 -> [[@LINE+1]]:2 = 0
+ return; // CHECK-NOT: Gap,File 0, [[@LINE]]:8
+}
+
+// CHECK-LABEL: _Z8switchesv:
+void switches() {
+ int x;
+ switch (x) {
+ case 0:
+ return;
+ default:
+ return; // CHECK-NOT: Gap,File 0, [[@LINE]]
+ }
}
#include "deferred-region-helper.h"
diff --git a/test/CoverageMapping/label.cpp b/test/CoverageMapping/label.cpp
index 8cac5b0cbe76..995835ad6b2f 100644
--- a/test/CoverageMapping/label.cpp
+++ b/test/CoverageMapping/label.cpp
@@ -16,11 +16,10 @@ void func() { // CHECK-NEXT: File 0, [[@LINE]]:13 -> {{[0-9]+}}:2
goto x; // CHECK: File 0, [[@LINE]]:7 -> [[@LINE]]:13 = (#1 - #2)
int k = 3; // CHECK-NEXT: File 0, [[@LINE-1]]:13 -> [[@LINE]]:5 = #3
} // CHECK-NEXT: File 0, [[@LINE-1]]:5 -> [[@LINE]]:4 = #3
- static int j = 0; // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+5]]:2 = ((#0 + #3) - #1)
+ static int j = 0; // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+4]]:2 = ((#0 + #3) - #1)
++j;
if(j == 1) // CHECK-NEXT: File 0, [[@LINE]]:6 -> [[@LINE]]:12 = ((#0 + #3) - #1)
goto x; // CHECK: File 0, [[@LINE]]:5 -> [[@LINE]]:11 = #4
- // CHECK-NEXT: File 0, [[@LINE-1]]:11 -> [[@LINE+1]]:2 = (((#0 + #3) - #1) - #4)
}
// CHECK-NEXT: test1
@@ -28,7 +27,7 @@ void test1(int x) { // CHECK-NEXT: File 0, [[@LINE]]:19 -> {{[0-9]+}}:2
if(x == 0) // CHECK-NEXT: File 0, [[@LINE]]:6 -> [[@LINE]]:12 = #0
goto a; // CHECK: File 0, [[@LINE]]:5 -> [[@LINE]]:11 = #1
// CHECK-NEXT: File 0, [[@LINE-1]]:11 -> [[@LINE+1]]:3 = (#0 - #1)
- goto b; // CHECK: Gap,File 0, [[@LINE]]:3 -> [[@LINE+5]]:2 = #3
+ goto b; // CHECK: File 0, [[@LINE]]:3 -> [[@LINE+5]]:2 = (#0 - #1)
// CHECK-NEXT: Gap,File 0, [[@LINE-1]]:9 -> [[@LINE+1]]:1 = #2
a: // CHECK-NEXT: File 0, [[@LINE]]:1 -> [[@LINE+3]]:2 = #2
b: // CHECK-NEXT: File 0, [[@LINE]]:1 -> [[@LINE+2]]:2 = #3
@@ -49,7 +48,17 @@ b: // CHECK-NEXT: File 0, [[@LINE]]:1 -> [[@LINE+2]]:2
x = x + 1;
}
- // CHECK-NEXT: main
+// CHECK-NEXT: test3
+#define a b
+void test3() {
+ if (0)
+ goto b; // CHECK: Gap,File 0, [[@LINE]]:11 -> [[@LINE+1]]:1 = [[retnCount:#[0-9]+]]
+a: // CHECK-NEXT: Expansion,File 0, [[@LINE]]:1 -> [[@LINE]]:2 = [[retnCount]] (Expanded file = 1)
+ return; // CHECK-NEXT: File 0, [[@LINE-1]]:2 -> [[@LINE]]:9 = [[retnCount]]
+}
+#undef a
+
+ // CHECK: main
int main() { // CHECK-NEXT: File 0, [[@LINE]]:12 -> {{[0-9]+}}:2 = #0
int j = 0;
for(int i = 0; i < 10; ++i) { // CHECK: File 0, [[@LINE]]:31 -> [[@LINE+13]]:4 = #1
diff --git a/test/CoverageMapping/moremacros.c b/test/CoverageMapping/moremacros.c
index 88411f3ba916..5e0d4a6abf25 100644
--- a/test/CoverageMapping/moremacros.c
+++ b/test/CoverageMapping/moremacros.c
@@ -31,7 +31,7 @@ int main(int argc, const char *argv[]) {
if (!argc) {
return 0;
// CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:8 = #4
- RBRAC // CHECK-NEXT: [[@LINE]]:8 -> [[@LINE+1]]:2 = (((#0 - #2) - #3) - #4)
+ RBRAC
}
// CHECK-NEXT: File 1, 3:15 -> 3:16 = #2
diff --git a/test/CoverageMapping/openmp.c b/test/CoverageMapping/openmp.c
new file mode 100644
index 000000000000..1ac12624e01a
--- /dev/null
+++ b/test/CoverageMapping/openmp.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -fopenmp -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -main-file-name openmp.c %s | FileCheck %s
+
+// CHECK: openmp.c:{{.+}}omp_outlined{{.+}}:
+// CHECK: File 0, 10:3 -> 10:31
+// CHECK: File 0, 10:19 -> 10:24
+// CHECK: File 0, 10:26 -> 10:29
+// CHECK: File 0, 10:30 -> 10:31
+int foo(int time, int n) {
+#pragma omp parallel for default(shared) schedule(dynamic, 1) reduction(+ : time)
+ for (int i = 1; i < n; ++i);
+ return 0;
+}
diff --git a/test/CoverageMapping/trycatch.cpp b/test/CoverageMapping/trycatch.cpp
index 560354320912..5d284daaca01 100644
--- a/test/CoverageMapping/trycatch.cpp
+++ b/test/CoverageMapping/trycatch.cpp
@@ -18,7 +18,7 @@ void func(int i) { // CHECK-NEXT: File 0, [[@LINE]]:18 -> {{[
// CHECK: File 0, [[@LINE+1]]:10 -> [[@LINE+2]]:27 = (#0 - #1)
} else if(i == 8) // CHECK-NEXT: File 0, [[@LINE]]:13 -> [[@LINE]]:19 = (#0 - #1)
throw ImportantError(); // CHECK: File 0, [[@LINE]]:5 -> [[@LINE]]:27 = #2
-} // CHECK-NEXT: File 0, [[@LINE-1]]:27 -> [[@LINE]]:2 = ((#0 - #1) - #2)
+}
// CHECK-NEXT: main
int main() { // CHECK-NEXT: File 0, [[@LINE]]:12 -> [[@LINE+13]]:2 = #0
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/crtbegin_dynamic.o b/test/Driver/Inputs/CUDA-nolibdevice/usr/local/cuda/bin/ptxas
index e69de29bb2d1..e69de29bb2d1 100644..100755
--- a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/crtbegin_dynamic.o
+++ b/test/Driver/Inputs/CUDA-nolibdevice/usr/local/cuda/bin/ptxas
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/crtbegin_so.o b/test/Driver/Inputs/CUDA-symlinks/opt/cuda/bin/ptxas
index e69de29bb2d1..e69de29bb2d1 100644..100755
--- a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/crtbegin_so.o
+++ b/test/Driver/Inputs/CUDA-symlinks/opt/cuda/bin/ptxas
diff --git a/test/Driver/Inputs/mingw_ubuntu_tree/usr/include/c++/4.8/86_64-w64-mingw32/.keep b/test/Driver/Inputs/CUDA-symlinks/opt/cuda/include/.keep
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/mingw_ubuntu_tree/usr/include/c++/4.8/86_64-w64-mingw32/.keep
+++ b/test/Driver/Inputs/CUDA-symlinks/opt/cuda/include/.keep
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/crtbegin_static.o b/test/Driver/Inputs/CUDA-symlinks/opt/cuda/lib/.keep
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/crtbegin_static.o
+++ b/test/Driver/Inputs/CUDA-symlinks/opt/cuda/lib/.keep
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/crtend_android.o b/test/Driver/Inputs/CUDA-symlinks/opt/cuda/nvvm/libdevice/libdevice.compute_30.10.bc
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/crtend_android.o
+++ b/test/Driver/Inputs/CUDA-symlinks/opt/cuda/nvvm/libdevice/libdevice.compute_30.10.bc
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/crtend_so.o b/test/Driver/Inputs/CUDA-symlinks/opt/cuda/nvvm/libdevice/libdevice.compute_35.10.bc
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/crtend_so.o
+++ b/test/Driver/Inputs/CUDA-symlinks/opt/cuda/nvvm/libdevice/libdevice.compute_35.10.bc
diff --git a/test/Driver/Inputs/CUDA-symlinks/usr/bin/ptxas b/test/Driver/Inputs/CUDA-symlinks/usr/bin/ptxas
new file mode 120000
index 000000000000..59eefd95a902
--- /dev/null
+++ b/test/Driver/Inputs/CUDA-symlinks/usr/bin/ptxas
@@ -0,0 +1 @@
+../../opt/cuda/bin/ptxas \ No newline at end of file
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr2/crtbegin_dynamic.o b/test/Driver/Inputs/CUDA/usr/local/cuda/bin/ptxas
index e69de29bb2d1..e69de29bb2d1 100644..100755
--- a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr2/crtbegin_dynamic.o
+++ b/test/Driver/Inputs/CUDA/usr/local/cuda/bin/ptxas
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr2/crtbegin_so.o b/test/Driver/Inputs/ami_linux_tree/lib/.keep
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr2/crtbegin_so.o
+++ b/test/Driver/Inputs/ami_linux_tree/lib/.keep
diff --git a/test/Driver/Inputs/sparc-sun-solaris2.11/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/crtbegin.o b/test/Driver/Inputs/ami_linux_tree/usr/lib/gcc/x86_64-amazon-linux/7/crtbegin.o
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/sparc-sun-solaris2.11/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/crtbegin.o
+++ b/test/Driver/Inputs/ami_linux_tree/usr/lib/gcc/x86_64-amazon-linux/7/crtbegin.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr2/crtbegin_static.o b/test/Driver/Inputs/ami_linux_tree/usr/lib/gcc/x86_64-amazon-linux/7/crtbeginT.o
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr2/crtbegin_static.o
+++ b/test/Driver/Inputs/ami_linux_tree/usr/lib/gcc/x86_64-amazon-linux/7/crtbeginT.o
diff --git a/test/Driver/Inputs/sparc-sun-solaris2.11/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/crtend.o b/test/Driver/Inputs/ami_linux_tree/usr/lib/gcc/x86_64-amazon-linux/7/crtend.o
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/sparc-sun-solaris2.11/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/crtend.o
+++ b/test/Driver/Inputs/ami_linux_tree/usr/lib/gcc/x86_64-amazon-linux/7/crtend.o
diff --git a/test/Driver/Inputs/sparc-sun-solaris2.11/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/crt1.o b/test/Driver/Inputs/ami_linux_tree/usr/lib64/crt1.o
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/sparc-sun-solaris2.11/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/crt1.o
+++ b/test/Driver/Inputs/ami_linux_tree/usr/lib64/crt1.o
diff --git a/test/Driver/Inputs/sparc-sun-solaris2.11/usr/lib/crti.o b/test/Driver/Inputs/ami_linux_tree/usr/lib64/crti.o
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/sparc-sun-solaris2.11/usr/lib/crti.o
+++ b/test/Driver/Inputs/ami_linux_tree/usr/lib64/crti.o
diff --git a/test/Driver/Inputs/sparc-sun-solaris2.11/usr/lib/crtn.o b/test/Driver/Inputs/ami_linux_tree/usr/lib64/crtn.o
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/sparc-sun-solaris2.11/usr/lib/crtn.o
+++ b/test/Driver/Inputs/ami_linux_tree/usr/lib64/crtn.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr2/crtend_android.o b/test/Driver/Inputs/basic_android_ndk_tree/include/c++/4.9/x86_64-linux-android/.keep
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr2/crtend_android.o
+++ b/test/Driver/Inputs/basic_android_ndk_tree/include/c++/4.9/x86_64-linux-android/.keep
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr2/crtend_so.o b/test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/x86_64-linux-android/4.9/crtbegin.o
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr2/crtend_so.o
+++ b/test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/x86_64-linux-android/4.9/crtbegin.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr6/crtbegin_dynamic.o b/test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/x86_64-linux-android/4.9/crtend.o
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr6/crtbegin_dynamic.o
+++ b/test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/x86_64-linux-android/4.9/crtend.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr6/crtbegin_so.o b/test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/x86_64-linux-android/4.9/include/.keep
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr6/crtbegin_so.o
+++ b/test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/x86_64-linux-android/4.9/include/.keep
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr6/crtbegin_static.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/include/aarch64-linux-android/.keep
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr6/crtbegin_static.o
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/include/aarch64-linux-android/.keep
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr6/crtend_android.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/include/arm-linux-androideabi/.keep
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr6/crtend_android.o
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/include/arm-linux-androideabi/.keep
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr6/crtend_so.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/include/i686-linux-android/.keep
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr6/crtend_so.o
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/include/i686-linux-android/.keep
diff --git a/test/Driver/Inputs/resource_dir/asan_blacklist.txt b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/include/x86_64-linux-android/.keep
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/resource_dir/asan_blacklist.txt
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/include/x86_64-linux-android/.keep
diff --git a/test/Driver/Inputs/resource_dir/hwasan_blacklist.txt b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/21/crtbegin_dynamic.o
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/resource_dir/hwasan_blacklist.txt
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/21/crtbegin_dynamic.o
diff --git a/test/Driver/Inputs/resource_dir/ubsan_blacklist.txt b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/21/crtbegin_so.o
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/resource_dir/ubsan_blacklist.txt
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/21/crtbegin_so.o
diff --git a/test/Driver/Inputs/resource_dir/vtables_blacklist.txt b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/21/crtbegin_static.o
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/resource_dir/vtables_blacklist.txt
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/21/crtbegin_static.o
diff --git a/test/Driver/Inputs/sparc-sun-solaris2.11/usr/lib/ld.so.1 b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/21/crtend_android.o
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/sparc-sun-solaris2.11/usr/lib/ld.so.1
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/21/crtend_android.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/21/crtend_so.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/21/crtend_so.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/21/crtend_so.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/21/libc.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/21/libc.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/21/libc.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/21/libdl.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/21/libdl.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/21/libdl.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/21/libm.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/21/libm.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/21/libm.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/21/libstdc++.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/21/libstdc++.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/21/libstdc++.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/libc.a b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/libc.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/libc.a
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/libdl.a b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/libdl.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/libdl.a
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/libm.a b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/libm.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/libm.a
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/libstdc++.a b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/libstdc++.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/aarch64-linux-android/libstdc++.a
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/crtbegin_dynamic.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/crtbegin_dynamic.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/crtbegin_dynamic.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/crtbegin_so.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/crtbegin_so.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/crtbegin_so.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/crtbegin_static.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/crtbegin_static.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/crtbegin_static.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/crtend_android.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/crtend_android.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/crtend_android.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/crtend_so.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/crtend_so.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/crtend_so.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/libc.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/libc.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/libc.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/libdl.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/libdl.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/libdl.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/libm.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/libm.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/libm.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/libstdc++.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/libstdc++.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/14/libstdc++.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/crtbegin_dynamic.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/crtbegin_dynamic.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/crtbegin_dynamic.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/crtbegin_so.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/crtbegin_so.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/crtbegin_so.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/crtbegin_static.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/crtbegin_static.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/crtbegin_static.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/crtend_android.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/crtend_android.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/crtend_android.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/crtend_so.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/crtend_so.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/crtend_so.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/libc.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/libc.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/libc.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/libdl.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/libdl.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/libdl.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/libm.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/libm.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/libm.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/libstdc++.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/libstdc++.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/21/libstdc++.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/libc.a b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/libc.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/libc.a
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/libdl.a b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/libdl.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/libdl.a
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/libm.a b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/libm.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/libm.a
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/libstdc++.a b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/libstdc++.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/arm-linux-androideabi/libstdc++.a
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/crtbegin_dynamic.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/crtbegin_dynamic.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/crtbegin_dynamic.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/crtbegin_so.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/crtbegin_so.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/crtbegin_so.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/crtbegin_static.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/crtbegin_static.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/crtbegin_static.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/crtend_android.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/crtend_android.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/crtend_android.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/crtend_so.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/crtend_so.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/crtend_so.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/libc.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/libc.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/libc.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/libdl.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/libdl.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/libdl.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/libm.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/libm.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/libm.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/libstdc++.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/libstdc++.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/14/libstdc++.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/crtbegin_dynamic.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/crtbegin_dynamic.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/crtbegin_dynamic.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/crtbegin_so.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/crtbegin_so.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/crtbegin_so.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/crtbegin_static.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/crtbegin_static.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/crtbegin_static.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/crtend_android.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/crtend_android.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/crtend_android.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/crtend_so.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/crtend_so.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/crtend_so.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/libc.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/libc.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/libc.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/libdl.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/libdl.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/libdl.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/libm.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/libm.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/libm.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/libstdc++.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/libstdc++.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/21/libstdc++.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/libc.a b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/libc.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/libc.a
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/libdl.a b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/libdl.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/libdl.a
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/libm.a b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/libm.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/libm.a
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/libstdc++.a b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/libstdc++.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/i686-linux-android/libstdc++.a
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/crtbegin_dynamic.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/crtbegin_dynamic.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/crtbegin_dynamic.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/crtbegin_so.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/crtbegin_so.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/crtbegin_so.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/crtbegin_static.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/crtbegin_static.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/crtbegin_static.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/crtend_android.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/crtend_android.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/crtend_android.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/crtend_so.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/crtend_so.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/crtend_so.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/libc.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/libc.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/libc.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/libdl.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/libdl.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/libdl.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/libm.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/libm.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/libm.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/libstdc++.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/libstdc++.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mips64el-linux-android/21/libstdc++.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/crtbegin_dynamic.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/crtbegin_dynamic.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/crtbegin_dynamic.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/crtbegin_so.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/crtbegin_so.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/crtbegin_so.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/crtbegin_static.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/crtbegin_static.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/crtbegin_static.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/crtend_android.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/crtend_android.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/crtend_android.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/crtend_so.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/crtend_so.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/crtend_so.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/libc.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/libc.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/libc.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/libdl.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/libdl.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/libdl.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/libm.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/libm.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/libm.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/libstdc++.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/libstdc++.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/14/libstdc++.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/crtbegin_dynamic.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/crtbegin_dynamic.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/crtbegin_dynamic.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/crtbegin_so.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/crtbegin_so.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/crtbegin_so.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/crtbegin_static.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/crtbegin_static.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/crtbegin_static.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/crtend_android.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/crtend_android.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/crtend_android.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/crtend_so.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/crtend_so.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/crtend_so.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/libc.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/libc.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/libc.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/libdl.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/libdl.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/libdl.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/libm.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/libm.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/libm.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/libstdc++.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/libstdc++.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/mipsel-linux-android/21/libstdc++.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/crtbegin_dynamic.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/crtbegin_dynamic.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/crtbegin_dynamic.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/crtbegin_so.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/crtbegin_so.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/crtbegin_so.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/crtbegin_static.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/crtbegin_static.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/crtbegin_static.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/crtend_android.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/crtend_android.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/crtend_android.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/crtend_so.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/crtend_so.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/crtend_so.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/libc.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/libc.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/libc.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/libdl.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/libdl.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/libdl.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/libm.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/libm.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/libm.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/libstdc++.so b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/libstdc++.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/21/libstdc++.so
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/libc.a b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/libc.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/libc.a
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/libdl.a b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/libdl.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/libdl.a
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/libm.a b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/libm.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/libm.a
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/libstdc++.a b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/libstdc++.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/lib/x86_64-linux-android/libstdc++.a
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/x86_64-linux-android/bin/ld b/test/Driver/Inputs/basic_android_ndk_tree/x86_64-linux-android/bin/ld
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/x86_64-linux-android/bin/ld
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/x86_64-linux-android/bin/ld.bfd b/test/Driver/Inputs/basic_android_ndk_tree/x86_64-linux-android/bin/ld.bfd
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/x86_64-linux-android/bin/ld.bfd
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/x86_64-linux-android/bin/ld.gold b/test/Driver/Inputs/basic_android_ndk_tree/x86_64-linux-android/bin/ld.gold
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/x86_64-linux-android/bin/ld.gold
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/x86_64-linux-android/lib/.keep b/test/Driver/Inputs/basic_android_ndk_tree/x86_64-linux-android/lib/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/x86_64-linux-android/lib/.keep
diff --git a/test/Driver/Inputs/config-1.cfg b/test/Driver/Inputs/config-1.cfg
new file mode 100644
index 000000000000..7d1326fe8bc8
--- /dev/null
+++ b/test/Driver/Inputs/config-1.cfg
@@ -0,0 +1,6 @@
+
+# Empty lines and line started with # are ignored
+-Werror
+
+ # Language
+ -std=c99
diff --git a/test/Driver/Inputs/config-2.cfg b/test/Driver/Inputs/config-2.cfg
new file mode 100644
index 000000000000..c803bd2a78f1
--- /dev/null
+++ b/test/Driver/Inputs/config-2.cfg
@@ -0,0 +1,2 @@
+# nested inclusion
+@config-3.cfg
diff --git a/test/Driver/Inputs/config-2a.cfg b/test/Driver/Inputs/config-2a.cfg
new file mode 100644
index 000000000000..ecdc55515682
--- /dev/null
+++ b/test/Driver/Inputs/config-2a.cfg
@@ -0,0 +1,2 @@
+# nested inclusion
+@config/config-4.cfg
diff --git a/test/Driver/Inputs/config-3.cfg b/test/Driver/Inputs/config-3.cfg
new file mode 100644
index 000000000000..d5086a8e4e08
--- /dev/null
+++ b/test/Driver/Inputs/config-3.cfg
@@ -0,0 +1 @@
+-Wundefined-func-template
diff --git a/test/Driver/Inputs/config-4.cfg b/test/Driver/Inputs/config-4.cfg
new file mode 100644
index 000000000000..bbfc0c51f296
--- /dev/null
+++ b/test/Driver/Inputs/config-4.cfg
@@ -0,0 +1,3 @@
+-L/usr/local/lib
+-lfoo
+-stdlib=libc++
diff --git a/test/Driver/Inputs/config-5.cfg b/test/Driver/Inputs/config-5.cfg
new file mode 100644
index 000000000000..09787ae6c492
--- /dev/null
+++ b/test/Driver/Inputs/config-5.cfg
@@ -0,0 +1,2 @@
+--serialize-diagnostics diag.ser
+-target
diff --git a/test/Driver/Inputs/config-6.cfg b/test/Driver/Inputs/config-6.cfg
new file mode 100644
index 000000000000..24d93cf8eca6
--- /dev/null
+++ b/test/Driver/Inputs/config-6.cfg
@@ -0,0 +1 @@
+--config config-5
diff --git a/test/Driver/Inputs/config/config-4.cfg b/test/Driver/Inputs/config/config-4.cfg
new file mode 100644
index 000000000000..033e86a52a64
--- /dev/null
+++ b/test/Driver/Inputs/config/config-4.cfg
@@ -0,0 +1 @@
+-isysroot /opt/data
diff --git a/test/Driver/Inputs/config/i386-qqq.cfg b/test/Driver/Inputs/config/i386-qqq.cfg
new file mode 100644
index 000000000000..41e1a9460b63
--- /dev/null
+++ b/test/Driver/Inputs/config/i386-qqq.cfg
@@ -0,0 +1 @@
+-target i386
diff --git a/test/Driver/Inputs/config/i386-qqq3.cfg b/test/Driver/Inputs/config/i386-qqq3.cfg
new file mode 100644
index 000000000000..59928c10cba8
--- /dev/null
+++ b/test/Driver/Inputs/config/i386-qqq3.cfg
@@ -0,0 +1 @@
+-target i383
diff --git a/test/Driver/Inputs/config/x86_64-qqq.cfg b/test/Driver/Inputs/config/x86_64-qqq.cfg
new file mode 100644
index 000000000000..9d8565a336e1
--- /dev/null
+++ b/test/Driver/Inputs/config/x86_64-qqq.cfg
@@ -0,0 +1 @@
+-target x86_64
diff --git a/test/Driver/Inputs/config/x86_64-qqq2.cfg b/test/Driver/Inputs/config/x86_64-qqq2.cfg
new file mode 100644
index 000000000000..9d8565a336e1
--- /dev/null
+++ b/test/Driver/Inputs/config/x86_64-qqq2.cfg
@@ -0,0 +1 @@
+-target x86_64
diff --git a/test/Driver/Inputs/config/x86_64.cfg b/test/Driver/Inputs/config/x86_64.cfg
new file mode 100644
index 000000000000..9d8565a336e1
--- /dev/null
+++ b/test/Driver/Inputs/config/x86_64.cfg
@@ -0,0 +1 @@
+-target x86_64
diff --git a/test/Driver/Inputs/config2/config-4.cfg b/test/Driver/Inputs/config2/config-4.cfg
new file mode 100644
index 000000000000..bd866b6966d0
--- /dev/null
+++ b/test/Driver/Inputs/config2/config-4.cfg
@@ -0,0 +1 @@
+-Wall
diff --git a/test/Driver/Inputs/config2/i386.cfg b/test/Driver/Inputs/config2/i386.cfg
new file mode 100644
index 000000000000..41e1a9460b63
--- /dev/null
+++ b/test/Driver/Inputs/config2/i386.cfg
@@ -0,0 +1 @@
+-target i386
diff --git a/test/Driver/Inputs/empty.cfg b/test/Driver/Inputs/empty.cfg
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/empty.cfg
diff --git a/test/Driver/Inputs/fuse_ld_windows/ld.foo.exe b/test/Driver/Inputs/fuse_ld_windows/ld.foo.exe
new file mode 100755
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/fuse_ld_windows/ld.foo.exe
diff --git a/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/etc/env.d/gcc/config-x86_64-pc-linux-gnu b/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/etc/env.d/gcc/config-x86_64-pc-linux-gnu
new file mode 100644
index 000000000000..5ef56a33a669
--- /dev/null
+++ b/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/etc/env.d/gcc/config-x86_64-pc-linux-gnu
@@ -0,0 +1 @@
+CURRENT=x86_64-pc-linux-gnu-4.9.3
diff --git a/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/etc/env.d/gcc/x86_64-pc-linux-gnu-4.9.3 b/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/etc/env.d/gcc/x86_64-pc-linux-gnu-4.9.3
new file mode 100644
index 000000000000..5805b7f4fdd4
--- /dev/null
+++ b/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/etc/env.d/gcc/x86_64-pc-linux-gnu-4.9.3
@@ -0,0 +1,10 @@
+PATH="/usr/x86_64-pc-linux-gnu/gcc-bin/4.9.x"
+ROOTPATH="/usr/x86_64-pc-linux-gnu/gcc-bin/4.9.x"
+GCC_PATH="/usr/x86_64-pc-linux-gnu/gcc-bin/4.9.x"
+LDPATH="/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x:/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x/32:/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x/x32"
+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="g++-v4"
+CTARGET="x86_64-pc-linux-gnu"
+GCC_SPECS=""
+MULTIOSDIRS="../lib64:../lib32"
diff --git a/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/etc/gentoo-release b/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/etc/gentoo-release
new file mode 100644
index 000000000000..5f0944f7d9a7
--- /dev/null
+++ b/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/etc/gentoo-release
@@ -0,0 +1 @@
+Gentoo Base System release 2.3
diff --git a/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/include/.keep b/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/include/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/include/.keep
diff --git a/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x/32/crtbegin.o b/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x/32/crtbegin.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x/32/crtbegin.o
diff --git a/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x/crtbegin.o b/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x/crtbegin.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x/crtbegin.o
diff --git a/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x/include/g++-v4.9.3/.keep b/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x/include/g++-v4.9.3/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x/include/g++-v4.9.3/.keep
diff --git a/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x/x32/crtbegin.o b/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x/x32/crtbegin.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x/x32/crtbegin.o
diff --git a/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/lib/gcc/x86_64-pc-linux-gnu/5.4.0/32/crtbegin.o b/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/lib/gcc/x86_64-pc-linux-gnu/5.4.0/32/crtbegin.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/lib/gcc/x86_64-pc-linux-gnu/5.4.0/32/crtbegin.o
diff --git a/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/lib/gcc/x86_64-pc-linux-gnu/5.4.0/crtbegin.o b/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/lib/gcc/x86_64-pc-linux-gnu/5.4.0/crtbegin.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/lib/gcc/x86_64-pc-linux-gnu/5.4.0/crtbegin.o
diff --git a/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/lib/gcc/x86_64-pc-linux-gnu/5.4.0/include/g++-v5.4.0/.keep b/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/lib/gcc/x86_64-pc-linux-gnu/5.4.0/include/g++-v5.4.0/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/lib/gcc/x86_64-pc-linux-gnu/5.4.0/include/g++-v5.4.0/.keep
diff --git a/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/lib/gcc/x86_64-pc-linux-gnu/5.4.0/x32/crtbegin.o b/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/lib/gcc/x86_64-pc-linux-gnu/5.4.0/x32/crtbegin.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/lib/gcc/x86_64-pc-linux-gnu/5.4.0/x32/crtbegin.o
diff --git a/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/x86_64-pc-linux-gnu/lib/.keep b/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/x86_64-pc-linux-gnu/lib/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/gentoo_linux_gcc_4.9.x_tree/usr/x86_64-pc-linux-gnu/lib/.keep
diff --git a/test/Driver/Inputs/hip_dev_lib/irif.amdgcn.bc b/test/Driver/Inputs/hip_dev_lib/irif.amdgcn.bc
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/hip_dev_lib/irif.amdgcn.bc
diff --git a/test/Driver/Inputs/hip_dev_lib/ockl.amdgcn.bc b/test/Driver/Inputs/hip_dev_lib/ockl.amdgcn.bc
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/hip_dev_lib/ockl.amdgcn.bc
diff --git a/test/Driver/Inputs/hip_dev_lib/oclc_correctly_rounded_sqrt_on.amdgcn.bc b/test/Driver/Inputs/hip_dev_lib/oclc_correctly_rounded_sqrt_on.amdgcn.bc
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/hip_dev_lib/oclc_correctly_rounded_sqrt_on.amdgcn.bc
diff --git a/test/Driver/Inputs/hip_dev_lib/oclc_daz_opt_off.amdgcn.bc b/test/Driver/Inputs/hip_dev_lib/oclc_daz_opt_off.amdgcn.bc
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/hip_dev_lib/oclc_daz_opt_off.amdgcn.bc
diff --git a/test/Driver/Inputs/hip_dev_lib/oclc_daz_opt_on.amdgcn.bc b/test/Driver/Inputs/hip_dev_lib/oclc_daz_opt_on.amdgcn.bc
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/hip_dev_lib/oclc_daz_opt_on.amdgcn.bc
diff --git a/test/Driver/Inputs/hip_dev_lib/oclc_finite_only_off.amdgcn.bc b/test/Driver/Inputs/hip_dev_lib/oclc_finite_only_off.amdgcn.bc
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/hip_dev_lib/oclc_finite_only_off.amdgcn.bc
diff --git a/test/Driver/Inputs/hip_dev_lib/oclc_isa_version_803.amdgcn.bc b/test/Driver/Inputs/hip_dev_lib/oclc_isa_version_803.amdgcn.bc
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/hip_dev_lib/oclc_isa_version_803.amdgcn.bc
diff --git a/test/Driver/Inputs/hip_dev_lib/oclc_isa_version_900.amdgcn.bc b/test/Driver/Inputs/hip_dev_lib/oclc_isa_version_900.amdgcn.bc
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/hip_dev_lib/oclc_isa_version_900.amdgcn.bc
diff --git a/test/Driver/Inputs/hip_dev_lib/oclc_unsafe_math_off.amdgcn.bc b/test/Driver/Inputs/hip_dev_lib/oclc_unsafe_math_off.amdgcn.bc
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/hip_dev_lib/oclc_unsafe_math_off.amdgcn.bc
diff --git a/test/Driver/Inputs/hip_dev_lib/ocml.amdgcn.bc b/test/Driver/Inputs/hip_dev_lib/ocml.amdgcn.bc
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/hip_dev_lib/ocml.amdgcn.bc
diff --git a/test/Driver/Inputs/hip_dev_lib/opencl.amdgcn.bc b/test/Driver/Inputs/hip_dev_lib/opencl.amdgcn.bc
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/hip_dev_lib/opencl.amdgcn.bc
diff --git a/test/Driver/Inputs/hip_multiple_inputs/a.cu b/test/Driver/Inputs/hip_multiple_inputs/a.cu
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/hip_multiple_inputs/a.cu
diff --git a/test/Driver/Inputs/hip_multiple_inputs/b.hip b/test/Driver/Inputs/hip_multiple_inputs/b.hip
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/hip_multiple_inputs/b.hip
diff --git a/test/Driver/Inputs/hip_multiple_inputs/lib1/lib1.bc b/test/Driver/Inputs/hip_multiple_inputs/lib1/lib1.bc
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/hip_multiple_inputs/lib1/lib1.bc
diff --git a/test/Driver/Inputs/hip_multiple_inputs/lib2/lib2.bc b/test/Driver/Inputs/hip_multiple_inputs/lib2/lib2.bc
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/hip_multiple_inputs/lib2/lib2.bc
diff --git a/test/Driver/Inputs/libomptarget/libomptarget-nvptx-sm_20.bc b/test/Driver/Inputs/libomptarget/libomptarget-nvptx-sm_20.bc
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/libomptarget/libomptarget-nvptx-sm_20.bc
diff --git a/test/Driver/Inputs/mingw_ubuntu_posix_tree/usr/lib/gcc/x86_64-w64-mingw32/5.3-posix/include-fixed/.keep b/test/Driver/Inputs/mingw_ubuntu_posix_tree/usr/lib/gcc/x86_64-w64-mingw32/5.3-posix/include-fixed/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/mingw_ubuntu_posix_tree/usr/lib/gcc/x86_64-w64-mingw32/5.3-posix/include-fixed/.keep
diff --git a/test/Driver/Inputs/mingw_ubuntu_posix_tree/usr/lib/gcc/x86_64-w64-mingw32/5.3-posix/include/c++/backward/.keep b/test/Driver/Inputs/mingw_ubuntu_posix_tree/usr/lib/gcc/x86_64-w64-mingw32/5.3-posix/include/c++/backward/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/mingw_ubuntu_posix_tree/usr/lib/gcc/x86_64-w64-mingw32/5.3-posix/include/c++/backward/.keep
diff --git a/test/Driver/Inputs/mingw_ubuntu_posix_tree/usr/lib/gcc/x86_64-w64-mingw32/5.3-posix/include/c++/x86_64-w64-mingw32/.keep b/test/Driver/Inputs/mingw_ubuntu_posix_tree/usr/lib/gcc/x86_64-w64-mingw32/5.3-posix/include/c++/x86_64-w64-mingw32/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/mingw_ubuntu_posix_tree/usr/lib/gcc/x86_64-w64-mingw32/5.3-posix/include/c++/x86_64-w64-mingw32/.keep
diff --git a/test/Driver/Inputs/mingw_ubuntu_posix_tree/usr/x86_64-w64-mingw32/include/.keep b/test/Driver/Inputs/mingw_ubuntu_posix_tree/usr/x86_64-w64-mingw32/include/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/mingw_ubuntu_posix_tree/usr/x86_64-w64-mingw32/include/.keep
diff --git a/test/Driver/Inputs/mingw_ubuntu_tree/usr/include/c++/4.8/x86_64-w64-mingw32/.keep b/test/Driver/Inputs/mingw_ubuntu_tree/usr/include/c++/4.8/x86_64-w64-mingw32/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/mingw_ubuntu_tree/usr/include/c++/4.8/x86_64-w64-mingw32/.keep
diff --git a/test/Driver/Inputs/multilib_riscv_linux_sdk/bin/.keep b/test/Driver/Inputs/multilib_riscv_linux_sdk/bin/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/multilib_riscv_linux_sdk/bin/.keep
diff --git a/test/Driver/Inputs/multilib_riscv_linux_sdk/include/.keep b/test/Driver/Inputs/multilib_riscv_linux_sdk/include/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/multilib_riscv_linux_sdk/include/.keep
diff --git a/test/Driver/Inputs/multilib_riscv_linux_sdk/lib/gcc/riscv64-unknown-linux-gnu/7.2.0/crtbegin.o b/test/Driver/Inputs/multilib_riscv_linux_sdk/lib/gcc/riscv64-unknown-linux-gnu/7.2.0/crtbegin.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/multilib_riscv_linux_sdk/lib/gcc/riscv64-unknown-linux-gnu/7.2.0/crtbegin.o
diff --git a/test/Driver/Inputs/multilib_riscv_linux_sdk/lib/gcc/riscv64-unknown-linux-gnu/7.2.0/lib32/ilp32/crtbegin.o b/test/Driver/Inputs/multilib_riscv_linux_sdk/lib/gcc/riscv64-unknown-linux-gnu/7.2.0/lib32/ilp32/crtbegin.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/multilib_riscv_linux_sdk/lib/gcc/riscv64-unknown-linux-gnu/7.2.0/lib32/ilp32/crtbegin.o
diff --git a/test/Driver/Inputs/multilib_riscv_linux_sdk/lib/gcc/riscv64-unknown-linux-gnu/7.2.0/lib32/ilp32d/crtbegin.o b/test/Driver/Inputs/multilib_riscv_linux_sdk/lib/gcc/riscv64-unknown-linux-gnu/7.2.0/lib32/ilp32d/crtbegin.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/multilib_riscv_linux_sdk/lib/gcc/riscv64-unknown-linux-gnu/7.2.0/lib32/ilp32d/crtbegin.o
diff --git a/test/Driver/Inputs/multilib_riscv_linux_sdk/lib/gcc/riscv64-unknown-linux-gnu/7.2.0/lib64/lp64/crtbegin.o b/test/Driver/Inputs/multilib_riscv_linux_sdk/lib/gcc/riscv64-unknown-linux-gnu/7.2.0/lib64/lp64/crtbegin.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/multilib_riscv_linux_sdk/lib/gcc/riscv64-unknown-linux-gnu/7.2.0/lib64/lp64/crtbegin.o
diff --git a/test/Driver/Inputs/multilib_riscv_linux_sdk/lib/gcc/riscv64-unknown-linux-gnu/7.2.0/lib64/lp64d/crtbegin.o b/test/Driver/Inputs/multilib_riscv_linux_sdk/lib/gcc/riscv64-unknown-linux-gnu/7.2.0/lib64/lp64d/crtbegin.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/multilib_riscv_linux_sdk/lib/gcc/riscv64-unknown-linux-gnu/7.2.0/lib64/lp64d/crtbegin.o
diff --git a/test/Driver/Inputs/multilib_riscv_linux_sdk/riscv64-unknown-linux-gnu/bin/ld b/test/Driver/Inputs/multilib_riscv_linux_sdk/riscv64-unknown-linux-gnu/bin/ld
new file mode 100755
index 000000000000..b23e55619b2f
--- /dev/null
+++ b/test/Driver/Inputs/multilib_riscv_linux_sdk/riscv64-unknown-linux-gnu/bin/ld
@@ -0,0 +1 @@
+#!/bin/true
diff --git a/test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/lib/.keep b/test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/lib/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/lib/.keep
diff --git a/test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/lib32/ilp32/.keep b/test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/lib32/ilp32/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/lib32/ilp32/.keep
diff --git a/test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/lib32/ilp32d/.keep b/test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/lib32/ilp32d/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/lib32/ilp32d/.keep
diff --git a/test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/lib64/lp64/.keep b/test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/lib64/lp64/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/lib64/lp64/.keep
diff --git a/test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/lib64/lp64d/.keep b/test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/lib64/lp64d/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/lib64/lp64d/.keep
diff --git a/test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/usr/lib32/ilp32/.keep b/test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/usr/lib32/ilp32/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/usr/lib32/ilp32/.keep
diff --git a/test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/usr/lib32/ilp32d/.keep b/test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/usr/lib32/ilp32d/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/usr/lib32/ilp32d/.keep
diff --git a/test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/usr/lib64/lp64/.keep b/test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/usr/lib64/lp64/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/usr/lib64/lp64/.keep
diff --git a/test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/usr/lib64/lp64d/.keep b/test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/usr/lib64/lp64d/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/multilib_riscv_linux_sdk/sysroot/usr/lib64/lp64d/.keep
diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_ios_dynamic.dylib b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_ios_dynamic.dylib
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_ios_dynamic.dylib
diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_iossim_dynamic.dylib b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_iossim_dynamic.dylib
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_iossim_dynamic.dylib
diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_osx_dynamic.dylib b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_osx_dynamic.dylib
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_osx_dynamic.dylib
diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_tvos_dynamic.dylib b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_tvos_dynamic.dylib
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_tvos_dynamic.dylib
diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_tvossim_dynamic.dylib b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_tvossim_dynamic.dylib
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_tvossim_dynamic.dylib
diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_watchos_dynamic.dylib b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_watchos_dynamic.dylib
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_watchos_dynamic.dylib
diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_watchossim_dynamic.dylib b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_watchossim_dynamic.dylib
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_watchossim_dynamic.dylib
diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.fuzzer_osx.a b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.fuzzer_osx.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.fuzzer_osx.a
diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.lsan_ios_dynamic.dylib b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.lsan_ios_dynamic.dylib
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.lsan_ios_dynamic.dylib
diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.lsan_iossim_dynamic.dylib b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.lsan_iossim_dynamic.dylib
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.lsan_iossim_dynamic.dylib
diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.lsan_osx_dynamic.dylib b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.lsan_osx_dynamic.dylib
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.lsan_osx_dynamic.dylib
diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.lsan_tvossim_dynamic.dylib b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.lsan_tvossim_dynamic.dylib
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.lsan_tvossim_dynamic.dylib
diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.tsan_iossim_dynamic.dylib b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.tsan_iossim_dynamic.dylib
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.tsan_iossim_dynamic.dylib
diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.tsan_osx_dynamic.dylib b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.tsan_osx_dynamic.dylib
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.tsan_osx_dynamic.dylib
diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.tsan_tvossim_dynamic.dylib b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.tsan_tvossim_dynamic.dylib
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.tsan_tvossim_dynamic.dylib
diff --git a/test/Driver/Inputs/resource_dir/lib/linux/libclang_rt.hwasan-x86_64.a.syms b/test/Driver/Inputs/resource_dir/lib/linux/libclang_rt.hwasan-x86_64.a.syms
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir/lib/linux/libclang_rt.hwasan-x86_64.a.syms
diff --git a/test/Driver/Inputs/resource_dir/share/asan_blacklist.txt b/test/Driver/Inputs/resource_dir/share/asan_blacklist.txt
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir/share/asan_blacklist.txt
diff --git a/test/Driver/Inputs/resource_dir/share/hwasan_blacklist.txt b/test/Driver/Inputs/resource_dir/share/hwasan_blacklist.txt
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir/share/hwasan_blacklist.txt
diff --git a/test/Driver/Inputs/resource_dir/share/ubsan_blacklist.txt b/test/Driver/Inputs/resource_dir/share/ubsan_blacklist.txt
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir/share/ubsan_blacklist.txt
diff --git a/test/Driver/Inputs/resource_dir/share/vtables_blacklist.txt b/test/Driver/Inputs/resource_dir/share/vtables_blacklist.txt
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir/share/vtables_blacklist.txt
diff --git a/test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/.keep b/test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/.keep
diff --git a/test/Driver/Inputs/resource_dir_with_per_target_subdir/i386-linux-gnu/lib/.keep b/test/Driver/Inputs/resource_dir_with_per_target_subdir/i386-linux-gnu/lib/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir_with_per_target_subdir/i386-linux-gnu/lib/.keep
diff --git a/test/Driver/Inputs/resource_dir_with_per_target_subdir/include/c++/v1/.keep b/test/Driver/Inputs/resource_dir_with_per_target_subdir/include/c++/v1/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir_with_per_target_subdir/include/c++/v1/.keep
diff --git a/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/.keep b/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/.keep
diff --git a/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-linux-gnu/lib/.keep b/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-linux-gnu/lib/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-linux-gnu/lib/.keep
diff --git a/test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/include/c++/4.8.2/sparc-sun-solaris2.11/bits/gthr.h b/test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/include/c++/4.8.2/sparc-sun-solaris2.11/bits/gthr.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/include/c++/4.8.2/sparc-sun-solaris2.11/bits/gthr.h
diff --git a/test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/include/c++/4.8.2/typeinfo b/test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/include/c++/4.8.2/typeinfo
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/include/c++/4.8.2/typeinfo
diff --git a/test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/crt1.o b/test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/crt1.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/crt1.o
diff --git a/test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/crtbegin.o b/test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/crtbegin.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/crtbegin.o
diff --git a/test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/crtend.o b/test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/crtend.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/crtend.o
diff --git a/test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/sparcv9/crt1.o b/test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/sparcv9/crt1.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/sparcv9/crt1.o
diff --git a/test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/sparcv9/crtbegin.o b/test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/sparcv9/crtbegin.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/sparcv9/crtbegin.o
diff --git a/test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/sparcv9/crtend.o b/test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/sparcv9/crtend.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/sparcv9/crtend.o
diff --git a/test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/lib/libatomic.a b/test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/lib/libatomic.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/lib/libatomic.a
diff --git a/test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/lib/sparcv9/libatomic.a b/test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/lib/sparcv9/libatomic.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/solaris_sparc_tree/usr/gcc/4.8/lib/sparcv9/libatomic.a
diff --git a/test/Driver/Inputs/solaris_sparc_tree/usr/lib/crti.o b/test/Driver/Inputs/solaris_sparc_tree/usr/lib/crti.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/solaris_sparc_tree/usr/lib/crti.o
diff --git a/test/Driver/Inputs/solaris_sparc_tree/usr/lib/crtn.o b/test/Driver/Inputs/solaris_sparc_tree/usr/lib/crtn.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/solaris_sparc_tree/usr/lib/crtn.o
diff --git a/test/Driver/Inputs/solaris_sparc_tree/usr/lib/ld.so.1 b/test/Driver/Inputs/solaris_sparc_tree/usr/lib/ld.so.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/solaris_sparc_tree/usr/lib/ld.so.1
diff --git a/test/Driver/Inputs/solaris_sparc_tree/usr/lib/sparcv9/crti.o b/test/Driver/Inputs/solaris_sparc_tree/usr/lib/sparcv9/crti.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/solaris_sparc_tree/usr/lib/sparcv9/crti.o
diff --git a/test/Driver/Inputs/solaris_sparc_tree/usr/lib/sparcv9/crtn.o b/test/Driver/Inputs/solaris_sparc_tree/usr/lib/sparcv9/crtn.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/solaris_sparc_tree/usr/lib/sparcv9/crtn.o
diff --git a/test/Driver/Inputs/solaris_sparc_tree/usr/lib/sparcv9/ld.so.1 b/test/Driver/Inputs/solaris_sparc_tree/usr/lib/sparcv9/ld.so.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/solaris_sparc_tree/usr/lib/sparcv9/ld.so.1
diff --git a/test/Driver/Inputs/solaris_x86_tree/usr/gcc/4.9/include/c++/4.9.4/i386-pc-solaris2.11/bits/gthr.h b/test/Driver/Inputs/solaris_x86_tree/usr/gcc/4.9/include/c++/4.9.4/i386-pc-solaris2.11/bits/gthr.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/solaris_x86_tree/usr/gcc/4.9/include/c++/4.9.4/i386-pc-solaris2.11/bits/gthr.h
diff --git a/test/Driver/Inputs/solaris_x86_tree/usr/gcc/4.9/include/c++/4.9.4/typeinfo b/test/Driver/Inputs/solaris_x86_tree/usr/gcc/4.9/include/c++/4.9.4/typeinfo
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/solaris_x86_tree/usr/gcc/4.9/include/c++/4.9.4/typeinfo
diff --git a/test/Driver/Inputs/solaris_x86_tree/usr/gcc/4.9/lib/amd64/libatomic.a b/test/Driver/Inputs/solaris_x86_tree/usr/gcc/4.9/lib/amd64/libatomic.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/solaris_x86_tree/usr/gcc/4.9/lib/amd64/libatomic.a
diff --git a/test/Driver/Inputs/solaris_x86_tree/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4/amd64/crtbegin.o b/test/Driver/Inputs/solaris_x86_tree/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4/amd64/crtbegin.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/solaris_x86_tree/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4/amd64/crtbegin.o
diff --git a/test/Driver/Inputs/solaris_x86_tree/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4/amd64/crtend.o b/test/Driver/Inputs/solaris_x86_tree/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4/amd64/crtend.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/solaris_x86_tree/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4/amd64/crtend.o
diff --git a/test/Driver/Inputs/solaris_x86_tree/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4/crtbegin.o b/test/Driver/Inputs/solaris_x86_tree/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4/crtbegin.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/solaris_x86_tree/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4/crtbegin.o
diff --git a/test/Driver/Inputs/solaris_x86_tree/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4/crtend.o b/test/Driver/Inputs/solaris_x86_tree/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4/crtend.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/solaris_x86_tree/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4/crtend.o
diff --git a/test/Driver/Inputs/solaris_x86_tree/usr/gcc/4.9/lib/libatomic.a b/test/Driver/Inputs/solaris_x86_tree/usr/gcc/4.9/lib/libatomic.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/solaris_x86_tree/usr/gcc/4.9/lib/libatomic.a
diff --git a/test/Driver/Inputs/solaris_x86_tree/usr/lib/amd64/crt1.o b/test/Driver/Inputs/solaris_x86_tree/usr/lib/amd64/crt1.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/solaris_x86_tree/usr/lib/amd64/crt1.o
diff --git a/test/Driver/Inputs/solaris_x86_tree/usr/lib/amd64/crti.o b/test/Driver/Inputs/solaris_x86_tree/usr/lib/amd64/crti.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/solaris_x86_tree/usr/lib/amd64/crti.o
diff --git a/test/Driver/Inputs/solaris_x86_tree/usr/lib/amd64/crtn.o b/test/Driver/Inputs/solaris_x86_tree/usr/lib/amd64/crtn.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/solaris_x86_tree/usr/lib/amd64/crtn.o
diff --git a/test/Driver/Inputs/solaris_x86_tree/usr/lib/amd64/ld.so.1 b/test/Driver/Inputs/solaris_x86_tree/usr/lib/amd64/ld.so.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/solaris_x86_tree/usr/lib/amd64/ld.so.1
diff --git a/test/Driver/Inputs/solaris_x86_tree/usr/lib/crt1.o b/test/Driver/Inputs/solaris_x86_tree/usr/lib/crt1.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/solaris_x86_tree/usr/lib/crt1.o
diff --git a/test/Driver/Inputs/solaris_x86_tree/usr/lib/crti.o b/test/Driver/Inputs/solaris_x86_tree/usr/lib/crti.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/solaris_x86_tree/usr/lib/crti.o
diff --git a/test/Driver/Inputs/solaris_x86_tree/usr/lib/crtn.o b/test/Driver/Inputs/solaris_x86_tree/usr/lib/crtn.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/solaris_x86_tree/usr/lib/crtn.o
diff --git a/test/Driver/Inputs/solaris_x86_tree/usr/lib/ld.so.1 b/test/Driver/Inputs/solaris_x86_tree/usr/lib/ld.so.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/solaris_x86_tree/usr/lib/ld.so.1
diff --git a/test/Driver/XRay/lit.local.cfg b/test/Driver/XRay/lit.local.cfg
index 7cc6c70dcb22..41bd41395f7b 100644
--- a/test/Driver/XRay/lit.local.cfg
+++ b/test/Driver/XRay/lit.local.cfg
@@ -1,15 +1,16 @@
+import platform
target_triple_components = config.target_triple.split('-')
config.available_features.update(target_triple_components)
# Only run the tests in platforms where XRay instrumentation is supported.
supported_targets = [
- 'x86_64', 'x86_64h', 'arm', 'aarch64', 'arm64', 'powerpc64le', 'mips',
+ 'amd64', 'x86_64', 'x86_64h', 'arm', 'aarch64', 'arm64', 'powerpc64le', 'mips',
'mipsel', 'mips64', 'mips64el'
]
# Only on platforms we support.
supported_oses = [
- 'linux'
+ 'Linux', 'FreeBSD'
]
triple_set = set(target_triple_components)
@@ -17,7 +18,7 @@ if len(triple_set.intersection(supported_targets)) == 0:
config.unsupported = True
# Do not run for 'android' despite being linux.
-if len(triple_set.intersection(supported_oses)) == 0 or 'android' in triple_set:
+if platform.system() not in supported_oses or 'android' in triple_set:
config.unsupported = True
if config.enable_shared:
diff --git a/test/Driver/XRay/xray-instrument-os.c b/test/Driver/XRay/xray-instrument-os.c
index 86b109b6dbfe..7e221365d611 100644
--- a/test/Driver/XRay/xray-instrument-os.c
+++ b/test/Driver/XRay/xray-instrument-os.c
@@ -1,4 +1,4 @@
// RUN: not %clang -o /dev/null -v -fxray-instrument -c %s
-// XFAIL: -linux-
+// XFAIL: -linux-, -freebsd
// REQUIRES-ANY: amd64, x86_64, x86_64h, arm, aarch64, arm64
typedef int a;
diff --git a/test/Driver/XRay/xray-mode-flags.cpp b/test/Driver/XRay/xray-mode-flags.cpp
new file mode 100644
index 000000000000..0a040881d332
--- /dev/null
+++ b/test/Driver/XRay/xray-mode-flags.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang -v -o /dev/null -fxray-instrument -fxray-modes=xray-fdr %s -### \
+// RUN: 2>&1 | FileCheck --check-prefix FDR %s
+// RUN: %clang -v -o /dev/null -fxray-instrument -fxray-modes=xray-basic %s \
+// RUN: -### 2>&1 | FileCheck --check-prefix BASIC %s
+// RUN: %clang -v -o /dev/null -fxray-instrument -fxray-modes=all -### %s \
+// RUN: 2>&1 | FileCheck --check-prefixes FDR,BASIC %s
+// RUN: %clang -v -o /dev/null -fxray-instrument \
+// RUN: -fxray-modes=xray-fdr,xray-basic -### %s 2>&1 | \
+// RUN: FileCheck --check-prefixes FDR,BASIC %s
+// RUN: %clang -v -o /dev/null -fxray-instrument \
+// RUN: -fxray-modes=xray-fdr -fxray-modes=xray-basic -### %s 2>&1 | \
+// RUN: FileCheck --check-prefixes FDR,BASIC %s
+// RUN: %clang -v -o /dev/null -fxray-instrument -### %s \
+// RUN: 2>&1 | FileCheck --check-prefixes FDR,BASIC %s
+// RUN: %clang -v -o /dev/null -fxray-instrument -fxray-modes=none -### %s \
+// RUN: 2>&1 | FileCheck --check-prefixes NONE %s
+//
+// We also should support overriding the modes in an additive manner.
+//
+// RUN: %clang -v -o /dev/null -fxray-instrument -fxray-modes=none,xray-fdr \
+// RUN: -### %s \
+// RUN: 2>&1 | FileCheck --check-prefixes FDR %s
+// RUN: %clang -v -o /dev/null -fxray-instrument -fxray-modes=xray-fdr,none \
+// RUN: -### %s \
+// RUN: 2>&1 | FileCheck --check-prefixes NONE %s
+// RUN: %clang -v -o /dev/null -fxray-instrument -fxray-modes=none,all \
+// RUN: -### %s \
+// RUN: 2>&1 | FileCheck --check-prefixes FDR,BASIC %s
+
+// BASIC: libclang_rt.xray-basic
+// FDR: libclang_rt.xray-fdr
+// NONE-NOT: libclang_rt.xray-basic
+// NONE-NOT: libclang_rt.xray-fdr
+// REQUIRES-ANY: linux, freebsd
+// REQUIRES-ANY: amd64, x86_64, x86_64h, arm, aarch64, arm64
diff --git a/test/Driver/XRay/xray-nolinkdeps.cpp b/test/Driver/XRay/xray-nolinkdeps.cpp
new file mode 100644
index 000000000000..5a79e362e356
--- /dev/null
+++ b/test/Driver/XRay/xray-nolinkdeps.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang -v -o /dev/null -fxray-instrument -fnoxray-link-deps %s -### \
+// RUN: 2>&1 | FileCheck --check-prefix DISABLE %s
+// RUN: %clang -v -o /dev/null -fxray-instrument -fxray-link-deps %s -### \
+// RUN: 2>&1 | FileCheck --check-prefix ENABLE %s
+// ENABLE: clang_rt.xray
+// DISABLE-NOT: clang_rt.xray
+// REQUIRES-ANY: linux, freebsd
+// REQUIRES-ANY: amd64, x86_64, x86_64h, arm, aarch64, arm64
diff --git a/test/Driver/aarch64-cpus.c b/test/Driver/aarch64-cpus.c
index 229484b2577b..330af351182d 100644
--- a/test/Driver/aarch64-cpus.c
+++ b/test/Driver/aarch64-cpus.c
@@ -15,6 +15,11 @@
// ARM64-GENERIC: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "generic"
+// We cannot check much for -mcpu=native, but it should be replaced by either generic or a valid
+// Arm cpu string, depending on the host.
+// RUN: %clang -target arm64 -mcpu=native -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-NATIVE %s
+// ARM64-NATIVE-NOT: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "native"
+
// RUN: %clang -target arm64-apple-darwin -arch arm64 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-DARWIN %s
// ARM64-DARWIN: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "cyclone"
@@ -155,6 +160,15 @@
// M3: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "exynos-m3"
// M3-TUNE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "generic"
+// RUN: %clang -target aarch64_be -mcpu=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=M4 %s
+// RUN: %clang -target aarch64 -mbig-endian -mcpu=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=M4 %s
+// RUN: %clang -target aarch64_be -mbig-endian -mcpu=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=M4 %s
+// RUN: %clang -target aarch64_be -mtune=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=M4-TUNE %s
+// RUN: %clang -target aarch64 -mbig-endian -mtune=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=M4-TUNE %s
+// RUN: %clang -target aarch64_be -mbig-endian -mtune=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=M4-TUNE %s
+// M4: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "exynos-m4"
+// M4-TUNE: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic"
+
// RUN: %clang -target arm64 -mcpu=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-M1 %s
// RUN: %clang -target arm64 -mlittle-endian -mcpu=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-M1 %s
// RUN: %clang -target arm64 -mtune=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-M1-TUNE %s
@@ -176,6 +190,13 @@
// ARM64-M3: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "exynos-m3"
// ARM64-M3-TUNE: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "generic"
+// RUN: %clang -target arm64 -mcpu=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-M4 %s
+// RUN: %clang -target arm64 -mlittle-endian -mcpu=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-M4 %s
+// RUN: %clang -target arm64 -mtune=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-M4-TUNE %s
+// RUN: %clang -target arm64 -mlittle-endian -mtune=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-M4-TUNE %s
+// ARM64-M4: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "exynos-m4"
+// ARM64-M4-TUNE: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "generic"
+
// RUN: %clang -target aarch64 -mcpu=falkor -### -c %s 2>&1 | FileCheck -check-prefix=FALKOR %s
// RUN: %clang -target aarch64 -mlittle-endian -mcpu=falkor -### -c %s 2>&1 | FileCheck -check-prefix=FALKOR %s
// RUN: %clang -target aarch64 -mtune=falkor -### -c %s 2>&1 | FileCheck -check-prefix=FALKOR-TUNE %s
@@ -308,6 +329,15 @@
// M3-BE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "exynos-m3"
// M3-BE-TUNE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "generic"
+// RUN: %clang -target aarch64_be -mcpu=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=M4-BE %s
+// RUN: %clang -target aarch64 -mbig-endian -mcpu=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=M4-BE %s
+// RUN: %clang -target aarch64_be -mbig-endian -mcpu=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=M4-BE %s
+// RUN: %clang -target aarch64_be -mtune=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=M4-BE-TUNE %s
+// RUN: %clang -target aarch64 -mbig-endian -mtune=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=M4-BE-TUNE %s
+// RUN: %clang -target aarch64_be -mbig-endian -mtune=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=M4-BE-TUNE %s
+// M4-BE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "exynos-m4"
+// M4-BE-TUNE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "generic"
+
// RUN: %clang -target aarch64_be -mcpu=thunderx2t99 -### -c %s 2>&1 | FileCheck -check-prefix=THUNDERX2T99-BE %s
// RUN: %clang -target aarch64 -mbig-endian -mcpu=thunderx2t99 -### -c %s 2>&1 | FileCheck -check-prefix=THUNDERX2T99-BE %s
// RUN: %clang -target aarch64_be -mbig-endian -mcpu=thunderx2t99 -### -c %s 2>&1 | FileCheck -check-prefix=THUNDERX2T99-BE %s
diff --git a/test/Driver/aarch64-fix-cortex-a53-835769.c b/test/Driver/aarch64-fix-cortex-a53-835769.c
index 3fe918adec45..56de7c7b9d2a 100644
--- a/test/Driver/aarch64-fix-cortex-a53-835769.c
+++ b/test/Driver/aarch64-fix-cortex-a53-835769.c
@@ -8,6 +8,6 @@
// RUN: %clang -target aarch64-android-eabi %s -### 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-YES %s
-// CHECK-DEF-NOT: "-backend-option" "-aarch64-fix-cortex-a53-835769"
-// CHECK-YES: "-backend-option" "-aarch64-fix-cortex-a53-835769=1"
-// CHECK-NO: "-backend-option" "-aarch64-fix-cortex-a53-835769=0"
+// CHECK-DEF-NOT: "-mllvm" "-aarch64-fix-cortex-a53-835769"
+// CHECK-YES: "-mllvm" "-aarch64-fix-cortex-a53-835769=1"
+// CHECK-NO: "-mllvm" "-aarch64-fix-cortex-a53-835769=0"
diff --git a/test/Driver/aarch64-fixed-x20.c b/test/Driver/aarch64-fixed-x20.c
new file mode 100644
index 000000000000..0be63971a441
--- /dev/null
+++ b/test/Driver/aarch64-fixed-x20.c
@@ -0,0 +1,4 @@
+// RUN: %clang -target aarch64-none-gnu -ffixed-x20 -### %s 2> %t
+// RUN: FileCheck --check-prefix=CHECK-FIXED-X20 < %t %s
+
+// CHECK-FIXED-X20: "-target-feature" "+reserve-x20"
diff --git a/test/Driver/aarch64-outliner.c b/test/Driver/aarch64-outliner.c
new file mode 100644
index 000000000000..eaf4e8ad96f9
--- /dev/null
+++ b/test/Driver/aarch64-outliner.c
@@ -0,0 +1,8 @@
+// REQUIRES: aarch64-registered-target
+// RUN: %clang -target aarch64 -moutline -S %s -### 2>&1 | FileCheck %s -check-prefix=ON
+// ON: "-mllvm" "-enable-machine-outliner"
+// RUN: %clang -target aarch64 -moutline -mno-outline -S %s -### 2>&1 | FileCheck %s -check-prefix=OFF
+// OFF: "-mllvm" "-enable-machine-outliner=never"
+// RUN: %clang -target x86_64 -moutline -S %s -### 2>&1 | FileCheck %s -check-prefix=WARN
+// WARN: warning: The 'x86_64' architecture does not support -moutline; flag ignored [-Woption-ignored]
+// WARN-NOT: "-mllvm" "-enable-machine-outliner"
diff --git a/test/Driver/addrsig.c b/test/Driver/addrsig.c
new file mode 100644
index 000000000000..fd5598c472e9
--- /dev/null
+++ b/test/Driver/addrsig.c
@@ -0,0 +1,8 @@
+// RUN: %clang -### -target x86_64-unknown-linux -c %s 2>&1 | FileCheck -check-prefix=ADDRSIG %s
+// RUN: %clang -### -target x86_64-unknown-linux -fno-integrated-as -c %s 2>&1 | FileCheck -check-prefix=NO-ADDRSIG %s
+// RUN: %clang -### -target x86_64-unknown-linux -fno-integrated-as -faddrsig -c %s 2>&1 | FileCheck -check-prefix=ADDRSIG %s
+// RUN: %clang -### -target x86_64-unknown-linux -fno-addrsig -c %s 2>&1 | FileCheck -check-prefix=NO-ADDRSIG %s
+// RUN: %clang -### -target x86_64-apple-darwin -c %s 2>&1 | FileCheck -check-prefix=NO-ADDRSIG %s
+
+// ADDRSIG: -faddrsig
+// NO-ADDRSIG-NOT: -faddrsig
diff --git a/test/Driver/amdgcn-toolchain-pic.cl b/test/Driver/amdgcn-toolchain-pic.cl
new file mode 100644
index 000000000000..fc2978a2f24a
--- /dev/null
+++ b/test/Driver/amdgcn-toolchain-pic.cl
@@ -0,0 +1,7 @@
+// RUN: %clang -no-canonical-prefixes -### -target amdgcn-- -mcpu=gfx803 %s 2>&1 | FileCheck %s
+// RUN: %clang -no-canonical-prefixes -### -target amdgcn-amd- -mcpu=gfx803 %s 2>&1 | FileCheck %s
+// RUN: %clang -no-canonical-prefixes -### -target amdgcn-amd-amdhsa -mcpu=gfx803 %s 2>&1 | FileCheck %s
+// RUN: %clang -no-canonical-prefixes -### -target amdgcn-amd-amdpal -mcpu=gfx803 %s 2>&1 | FileCheck %s
+// RUN: %clang -no-canonical-prefixes -### -target amdgcn-amd-mesa3d -mcpu=gfx803 %s 2>&1 | FileCheck %s
+
+// CHECK: clang{{.*}} "-mrelocation-model" "pic" "-pic-level" "1"
diff --git a/test/Driver/amdgpu-features.c b/test/Driver/amdgpu-features.c
index 23ba72b26df5..0e54a5e2512f 100644
--- a/test/Driver/amdgpu-features.c
+++ b/test/Driver/amdgpu-features.c
@@ -4,7 +4,7 @@
// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=kaveri -mamdgpu-debugger-abi=1.0 %s -o - 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MAMDGPU-DEBUGGER-ABI-1-0 %s
-// CHECK-MAMDGPU-DEBUGGER-ABI-1-0: "-target-feature" "+amdgpu-debugger-insert-nops" "-target-feature" "+amdgpu-debugger-reserve-regs" "-target-feature" "+amdgpu-debugger-emit-prologue"
+// CHECK-MAMDGPU-DEBUGGER-ABI-1-0: "-target-feature" "+amdgpu-debugger-insert-nops" "-target-feature" "+amdgpu-debugger-emit-prologue"
// RUN: %clang -### -target amdgcn -mcpu=gfx700 -mxnack %s 2>&1 | FileCheck --check-prefix=XNACK %s
// XNACK: "-target-feature" "+xnack"
diff --git a/test/Driver/amdgpu-macros.cl b/test/Driver/amdgpu-macros.cl
new file mode 100644
index 000000000000..c57d3805be7a
--- /dev/null
+++ b/test/Driver/amdgpu-macros.cl
@@ -0,0 +1,277 @@
+// Check that appropriate macros are defined for every supported AMDGPU
+// "-target" and "-mcpu" options.
+
+//
+// R600-based processors.
+//
+
+// RUN: %clang -E -dM -target r600 -mcpu=r600 %s 2>&1 | FileCheck --check-prefixes=ARCH-R600,R600 %s
+// RUN: %clang -E -dM -target r600 -mcpu=rv630 %s 2>&1 | FileCheck --check-prefixes=ARCH-R600,R600 %s
+// RUN: %clang -E -dM -target r600 -mcpu=rv635 %s 2>&1 | FileCheck --check-prefixes=ARCH-R600,R600 %s
+// RUN: %clang -E -dM -target r600 -mcpu=r630 %s 2>&1 | FileCheck --check-prefixes=ARCH-R600,R630 %s
+// RUN: %clang -E -dM -target r600 -mcpu=rs780 %s 2>&1 | FileCheck --check-prefixes=ARCH-R600,RS880 %s
+// RUN: %clang -E -dM -target r600 -mcpu=rs880 %s 2>&1 | FileCheck --check-prefixes=ARCH-R600,RS880 %s
+// RUN: %clang -E -dM -target r600 -mcpu=rv610 %s 2>&1 | FileCheck --check-prefixes=ARCH-R600,RS880 %s
+// RUN: %clang -E -dM -target r600 -mcpu=rv620 %s 2>&1 | FileCheck --check-prefixes=ARCH-R600,RS880 %s
+// RUN: %clang -E -dM -target r600 -mcpu=rv670 %s 2>&1 | FileCheck --check-prefixes=ARCH-R600,RV670 %s
+// RUN: %clang -E -dM -target r600 -mcpu=rv710 %s 2>&1 | FileCheck --check-prefixes=ARCH-R600,RV710 %s
+// RUN: %clang -E -dM -target r600 -mcpu=rv730 %s 2>&1 | FileCheck --check-prefixes=ARCH-R600,RV730 %s
+// RUN: %clang -E -dM -target r600 -mcpu=rv740 %s 2>&1 | FileCheck --check-prefixes=ARCH-R600,RV770 %s
+// RUN: %clang -E -dM -target r600 -mcpu=rv770 %s 2>&1 | FileCheck --check-prefixes=ARCH-R600,RV770 %s
+// RUN: %clang -E -dM -target r600 -mcpu=cedar %s 2>&1 | FileCheck --check-prefixes=ARCH-R600,CEDAR %s
+// RUN: %clang -E -dM -target r600 -mcpu=palm %s 2>&1 | FileCheck --check-prefixes=ARCH-R600,CEDAR %s
+// RUN: %clang -E -dM -target r600 -mcpu=cypress %s 2>&1 | FileCheck --check-prefixes=ARCH-R600,CYPRESS %s
+// RUN: %clang -E -dM -target r600 -mcpu=hemlock %s 2>&1 | FileCheck --check-prefixes=ARCH-R600,CYPRESS %s
+// RUN: %clang -E -dM -target r600 -mcpu=juniper %s 2>&1 | FileCheck --check-prefixes=ARCH-R600,JUNIPER %s
+// RUN: %clang -E -dM -target r600 -mcpu=redwood %s 2>&1 | FileCheck --check-prefixes=ARCH-R600,REDWOOD %s
+// RUN: %clang -E -dM -target r600 -mcpu=sumo %s 2>&1 | FileCheck --check-prefixes=ARCH-R600,SUMO %s
+// RUN: %clang -E -dM -target r600 -mcpu=sumo2 %s 2>&1 | FileCheck --check-prefixes=ARCH-R600,SUMO %s
+// RUN: %clang -E -dM -target r600 -mcpu=barts %s 2>&1 | FileCheck --check-prefixes=ARCH-R600,BARTS %s
+// RUN: %clang -E -dM -target r600 -mcpu=caicos %s 2>&1 | FileCheck --check-prefixes=ARCH-R600,CAICOS %s
+// RUN: %clang -E -dM -target r600 -mcpu=aruba %s 2>&1 | FileCheck --check-prefixes=ARCH-R600,CAYMAN %s
+// RUN: %clang -E -dM -target r600 -mcpu=cayman %s 2>&1 | FileCheck --check-prefixes=ARCH-R600,CAYMAN %s
+// RUN: %clang -E -dM -target r600 -mcpu=turks %s 2>&1 | FileCheck --check-prefixes=ARCH-R600,TURKS %s
+
+// R600-NOT: #define FP_FAST_FMA 1
+// R630-NOT: #define FP_FAST_FMA 1
+// RS880-NOT: #define FP_FAST_FMA 1
+// RV670-NOT: #define FP_FAST_FMA 1
+// RV710-NOT: #define FP_FAST_FMA 1
+// RV730-NOT: #define FP_FAST_FMA 1
+// RV770-NOT: #define FP_FAST_FMA 1
+// CEDAR-NOT: #define FP_FAST_FMA 1
+// CYPRESS-NOT: #define FP_FAST_FMA 1
+// JUNIPER-NOT: #define FP_FAST_FMA 1
+// REDWOOD-NOT: #define FP_FAST_FMA 1
+// SUMO-NOT: #define FP_FAST_FMA 1
+// BARTS-NOT: #define FP_FAST_FMA 1
+// CAICOS-NOT: #define FP_FAST_FMA 1
+// CAYMAN-NOT: #define FP_FAST_FMA 1
+// TURKS-NOT: #define FP_FAST_FMA 1
+
+// R600-NOT: #define FP_FAST_FMAF 1
+// R630-NOT: #define FP_FAST_FMAF 1
+// RS880-NOT: #define FP_FAST_FMAF 1
+// RV670-NOT: #define FP_FAST_FMAF 1
+// RV710-NOT: #define FP_FAST_FMAF 1
+// RV730-NOT: #define FP_FAST_FMAF 1
+// RV770-NOT: #define FP_FAST_FMAF 1
+// CEDAR-NOT: #define FP_FAST_FMAF 1
+// CYPRESS-NOT: #define FP_FAST_FMAF 1
+// JUNIPER-NOT: #define FP_FAST_FMAF 1
+// REDWOOD-NOT: #define FP_FAST_FMAF 1
+// SUMO-NOT: #define FP_FAST_FMAF 1
+// BARTS-NOT: #define FP_FAST_FMAF 1
+// CAICOS-NOT: #define FP_FAST_FMAF 1
+// CAYMAN-NOT: #define FP_FAST_FMAF 1
+// TURKS-NOT: #define FP_FAST_FMAF 1
+
+// ARCH-R600-DAG: #define __AMDGPU__ 1
+// ARCH-R600-DAG: #define __AMD__ 1
+
+// R600-NOT: #define __HAS_FMAF__ 1
+// R630-NOT: #define __HAS_FMAF__ 1
+// RS880-NOT: #define __HAS_FMAF__ 1
+// RV670-NOT: #define __HAS_FMAF__ 1
+// RV710-NOT: #define __HAS_FMAF__ 1
+// RV730-NOT: #define __HAS_FMAF__ 1
+// RV770-NOT: #define __HAS_FMAF__ 1
+// CEDAR-NOT: #define __HAS_FMAF__ 1
+// CYPRESS-DAG: #define __HAS_FMAF__ 1
+// JUNIPER-NOT: #define __HAS_FMAF__ 1
+// REDWOOD-NOT: #define __HAS_FMAF__ 1
+// SUMO-NOT: #define __HAS_FMAF__ 1
+// BARTS-NOT: #define __HAS_FMAF__ 1
+// CAICOS-NOT: #define __HAS_FMAF__ 1
+// CAYMAN-DAG: #define __HAS_FMAF__ 1
+// TURKS-NOT: #define __HAS_FMAF__ 1
+
+// R600-NOT: #define __HAS_FP64__ 1
+// R630-NOT: #define __HAS_FP64__ 1
+// RS880-NOT: #define __HAS_FP64__ 1
+// RV670-NOT: #define __HAS_FP64__ 1
+// RV710-NOT: #define __HAS_FP64__ 1
+// RV730-NOT: #define __HAS_FP64__ 1
+// RV770-NOT: #define __HAS_FP64__ 1
+// CEDAR-NOT: #define __HAS_FP64__ 1
+// CYPRESS-NOT: #define __HAS_FP64__ 1
+// JUNIPER-NOT: #define __HAS_FP64__ 1
+// REDWOOD-NOT: #define __HAS_FP64__ 1
+// SUMO-NOT: #define __HAS_FP64__ 1
+// BARTS-NOT: #define __HAS_FP64__ 1
+// CAICOS-NOT: #define __HAS_FP64__ 1
+// CAYMAN-NOT: #define __HAS_FP64__ 1
+// TURKS-NOT: #define __HAS_FP64__ 1
+
+// R600-NOT: #define __HAS_LDEXPF__ 1
+// R630-NOT: #define __HAS_LDEXPF__ 1
+// RS880-NOT: #define __HAS_LDEXPF__ 1
+// RV670-NOT: #define __HAS_LDEXPF__ 1
+// RV710-NOT: #define __HAS_LDEXPF__ 1
+// RV730-NOT: #define __HAS_LDEXPF__ 1
+// RV770-NOT: #define __HAS_LDEXPF__ 1
+// CEDAR-NOT: #define __HAS_LDEXPF__ 1
+// CYPRESS-NOT: #define __HAS_LDEXPF__ 1
+// JUNIPER-NOT: #define __HAS_LDEXPF__ 1
+// REDWOOD-NOT: #define __HAS_LDEXPF__ 1
+// SUMO-NOT: #define __HAS_LDEXPF__ 1
+// BARTS-NOT: #define __HAS_LDEXPF__ 1
+// CAICOS-NOT: #define __HAS_LDEXPF__ 1
+// CAYMAN-NOT: #define __HAS_LDEXPF__ 1
+// TURKS-NOT: #define __HAS_LDEXPF__ 1
+
+// ARCH-R600-DAG: #define __R600__ 1
+
+// R600-DAG: #define __r600__ 1
+// R630-DAG: #define __r630__ 1
+// RS880-DAG: #define __rs880__ 1
+// RV670-DAG: #define __rv670__ 1
+// RV710-DAG: #define __rv710__ 1
+// RV730-DAG: #define __rv730__ 1
+// RV770-DAG: #define __rv770__ 1
+// CEDAR-DAG: #define __cedar__ 1
+// CYPRESS-DAG: #define __cypress__ 1
+// JUNIPER-DAG: #define __juniper__ 1
+// REDWOOD-DAG: #define __redwood__ 1
+// SUMO-DAG: #define __sumo__ 1
+// BARTS-DAG: #define __barts__ 1
+// CAICOS-DAG: #define __caicos__ 1
+// CAYMAN-DAG: #define __cayman__ 1
+// TURKS-DAG: #define __turks__ 1
+
+//
+// AMDGCN-based processors.
+//
+
+// RUN: %clang -E -dM -target amdgcn -mcpu=gfx600 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX600 %s
+// RUN: %clang -E -dM -target amdgcn -mcpu=tahiti %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX600 %s
+// RUN: %clang -E -dM -target amdgcn -mcpu=gfx601 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX601 %s
+// RUN: %clang -E -dM -target amdgcn -mcpu=hainan %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX601 %s
+// RUN: %clang -E -dM -target amdgcn -mcpu=oland %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX601 %s
+// RUN: %clang -E -dM -target amdgcn -mcpu=pitcairn %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX601 %s
+// RUN: %clang -E -dM -target amdgcn -mcpu=verde %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX601 %s
+// RUN: %clang -E -dM -target amdgcn -mcpu=gfx700 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX700 %s
+// RUN: %clang -E -dM -target amdgcn -mcpu=kaveri %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX700 %s
+// RUN: %clang -E -dM -target amdgcn -mcpu=gfx701 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX701 %s
+// RUN: %clang -E -dM -target amdgcn -mcpu=hawaii %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX701 %s
+// RUN: %clang -E -dM -target amdgcn -mcpu=gfx702 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX702 %s
+// RUN: %clang -E -dM -target amdgcn -mcpu=gfx703 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX703 %s
+// RUN: %clang -E -dM -target amdgcn -mcpu=kabini %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX703 %s
+// RUN: %clang -E -dM -target amdgcn -mcpu=mullins %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX703 %s
+// RUN: %clang -E -dM -target amdgcn -mcpu=gfx704 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX704 %s
+// RUN: %clang -E -dM -target amdgcn -mcpu=bonaire %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX704 %s
+// RUN: %clang -E -dM -target amdgcn -mcpu=gfx801 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX801 %s
+// RUN: %clang -E -dM -target amdgcn -mcpu=carrizo %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX801 %s
+// RUN: %clang -E -dM -target amdgcn -mcpu=gfx802 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX802 %s
+// RUN: %clang -E -dM -target amdgcn -mcpu=iceland %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX802 %s
+// RUN: %clang -E -dM -target amdgcn -mcpu=tonga %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX802 %s
+// RUN: %clang -E -dM -target amdgcn -mcpu=gfx803 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX803 %s
+// RUN: %clang -E -dM -target amdgcn -mcpu=fiji %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX803 %s
+// RUN: %clang -E -dM -target amdgcn -mcpu=polaris10 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX803 %s
+// RUN: %clang -E -dM -target amdgcn -mcpu=polaris11 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX803 %s
+// RUN: %clang -E -dM -target amdgcn -mcpu=gfx810 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX810 %s
+// RUN: %clang -E -dM -target amdgcn -mcpu=stoney %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX810 %s
+// RUN: %clang -E -dM -target amdgcn -mcpu=gfx900 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX900 %s
+// RUN: %clang -E -dM -target amdgcn -mcpu=gfx902 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX902 %s
+// RUN: %clang -E -dM -target amdgcn -mcpu=gfx904 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX904 %s
+// RUN: %clang -E -dM -target amdgcn -mcpu=gfx906 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX906 %s
+
+// GFX600-DAG: #define FP_FAST_FMA 1
+// GFX601-DAG: #define FP_FAST_FMA 1
+// GFX700-DAG: #define FP_FAST_FMA 1
+// GFX701-DAG: #define FP_FAST_FMA 1
+// GFX702-DAG: #define FP_FAST_FMA 1
+// GFX703-DAG: #define FP_FAST_FMA 1
+// GFX704-DAG: #define FP_FAST_FMA 1
+// GFX801-DAG: #define FP_FAST_FMA 1
+// GFX802-DAG: #define FP_FAST_FMA 1
+// GFX803-DAG: #define FP_FAST_FMA 1
+// GFX810-DAG: #define FP_FAST_FMA 1
+// GFX900-DAG: #define FP_FAST_FMA 1
+// GFX902-DAG: #define FP_FAST_FMA 1
+// GFX904-DAG: #define FP_FAST_FMA 1
+// GFX906-DAG: #define FP_FAST_FMA 1
+
+// GFX600-DAG: #define FP_FAST_FMAF 1
+// GFX601-NOT: #define FP_FAST_FMAF 1
+// GFX700-NOT: #define FP_FAST_FMAF 1
+// GFX701-DAG: #define FP_FAST_FMAF 1
+// GFX702-DAG: #define FP_FAST_FMAF 1
+// GFX703-NOT: #define FP_FAST_FMAF 1
+// GFX704-NOT: #define FP_FAST_FMAF 1
+// GFX801-DAG: #define FP_FAST_FMAF 1
+// GFX802-NOT: #define FP_FAST_FMAF 1
+// GFX803-NOT: #define FP_FAST_FMAF 1
+// GFX810-NOT: #define FP_FAST_FMAF 1
+// GFX900-DAG: #define FP_FAST_FMAF 1
+// GFX902-DAG: #define FP_FAST_FMAF 1
+// GFX904-DAG: #define FP_FAST_FMAF 1
+// GFX906-DAG: #define FP_FAST_FMAF 1
+
+// ARCH-GCN-DAG: #define __AMDGCN__ 1
+// ARCH-GCN-DAG: #define __AMDGPU__ 1
+// ARCH-GCN-DAG: #define __AMD__ 1
+
+// GFX600-DAG: #define __HAS_FMAF__ 1
+// GFX601-DAG: #define __HAS_FMAF__ 1
+// GFX700-DAG: #define __HAS_FMAF__ 1
+// GFX701-DAG: #define __HAS_FMAF__ 1
+// GFX702-DAG: #define __HAS_FMAF__ 1
+// GFX703-DAG: #define __HAS_FMAF__ 1
+// GFX704-DAG: #define __HAS_FMAF__ 1
+// GFX801-DAG: #define __HAS_FMAF__ 1
+// GFX802-DAG: #define __HAS_FMAF__ 1
+// GFX803-DAG: #define __HAS_FMAF__ 1
+// GFX810-DAG: #define __HAS_FMAF__ 1
+// GFX900-DAG: #define __HAS_FMAF__ 1
+// GFX902-DAG: #define __HAS_FMAF__ 1
+// GFX904-DAG: #define __HAS_FMAF__ 1
+// GFX906-DAG: #define __HAS_FMAF__ 1
+
+// GFX600-DAG: #define __HAS_FP64__ 1
+// GFX601-DAG: #define __HAS_FP64__ 1
+// GFX700-DAG: #define __HAS_FP64__ 1
+// GFX701-DAG: #define __HAS_FP64__ 1
+// GFX702-DAG: #define __HAS_FP64__ 1
+// GFX703-DAG: #define __HAS_FP64__ 1
+// GFX704-DAG: #define __HAS_FP64__ 1
+// GFX801-DAG: #define __HAS_FP64__ 1
+// GFX802-DAG: #define __HAS_FP64__ 1
+// GFX803-DAG: #define __HAS_FP64__ 1
+// GFX810-DAG: #define __HAS_FP64__ 1
+// GFX900-DAG: #define __HAS_FP64__ 1
+// GFX902-DAG: #define __HAS_FP64__ 1
+// GFX904-DAG: #define __HAS_FP64__ 1
+// GFX906-DAG: #define __HAS_FP64__ 1
+
+// GFX600-DAG: #define __HAS_LDEXPF__ 1
+// GFX601-DAG: #define __HAS_LDEXPF__ 1
+// GFX700-DAG: #define __HAS_LDEXPF__ 1
+// GFX701-DAG: #define __HAS_LDEXPF__ 1
+// GFX702-DAG: #define __HAS_LDEXPF__ 1
+// GFX703-DAG: #define __HAS_LDEXPF__ 1
+// GFX704-DAG: #define __HAS_LDEXPF__ 1
+// GFX801-DAG: #define __HAS_LDEXPF__ 1
+// GFX802-DAG: #define __HAS_LDEXPF__ 1
+// GFX803-DAG: #define __HAS_LDEXPF__ 1
+// GFX810-DAG: #define __HAS_LDEXPF__ 1
+// GFX900-DAG: #define __HAS_LDEXPF__ 1
+// GFX902-DAG: #define __HAS_LDEXPF__ 1
+// GFX904-DAG: #define __HAS_LDEXPF__ 1
+// GFX906-DAG: #define __HAS_LDEXPF__ 1
+
+// GFX600-DAG: #define __gfx600__ 1
+// GFX601-DAG: #define __gfx601__ 1
+// GFX700-DAG: #define __gfx700__ 1
+// GFX701-DAG: #define __gfx701__ 1
+// GFX702-DAG: #define __gfx702__ 1
+// GFX703-DAG: #define __gfx703__ 1
+// GFX704-DAG: #define __gfx704__ 1
+// GFX801-DAG: #define __gfx801__ 1
+// GFX802-DAG: #define __gfx802__ 1
+// GFX803-DAG: #define __gfx803__ 1
+// GFX810-DAG: #define __gfx810__ 1
+// GFX900-DAG: #define __gfx900__ 1
+// GFX902-DAG: #define __gfx902__ 1
+// GFX904-DAG: #define __gfx904__ 1
+// GFX906-DAG: #define __gfx906__ 1
diff --git a/test/Driver/amdgpu-mcpu.cl b/test/Driver/amdgpu-mcpu.cl
index 26137ac68aef..c036e2ef093a 100644
--- a/test/Driver/amdgpu-mcpu.cl
+++ b/test/Driver/amdgpu-mcpu.cl
@@ -1,112 +1,119 @@
-t// Check that -mcpu works for all supported GPUs
+// Check that -mcpu works for all supported GPUs.
-// RUN: %clang -### -target r600 -x cl -S -emit-llvm -mcpu=r600 %s -o - 2>&1 | FileCheck --check-prefix=R600-CHECK %s
-// RUN: %clang -### -target r600 -x cl -S -emit-llvm -mcpu=rv630 %s -o - 2>&1 | FileCheck --check-prefix=R600-CHECK %s
-// RUN: %clang -### -target r600 -x cl -S -emit-llvm -mcpu=rv635 %s -o - 2>&1 | FileCheck --check-prefix=R600-CHECK %s
-// RUN: %clang -### -target r600 -x cl -S -emit-llvm -mcpu=rv610 %s -o - 2>&1 | FileCheck --check-prefix=RS880-CHECK %s
-// RUN: %clang -### -target r600 -x cl -S -emit-llvm -mcpu=rv620 %s -o - 2>&1 | FileCheck --check-prefix=RS880-CHECK %s
-// RUN: %clang -### -target r600 -x cl -S -emit-llvm -mcpu=rs780 %s -o - 2>&1 | FileCheck --check-prefix=RS880-CHECK %s
-// RUN: %clang -### -target r600 -x cl -S -emit-llvm -mcpu=rs880 %s -o - 2>&1 | FileCheck --check-prefix=RS880-CHECK %s
-// RUN: %clang -### -target r600 -x cl -S -emit-llvm -mcpu=rv670 %s -o - 2>&1 | FileCheck --check-prefix=RV670-CHECK %s
-// RUN: %clang -### -target r600 -x cl -S -emit-llvm -mcpu=rv710 %s -o - 2>&1 | FileCheck --check-prefix=RV710-CHECK %s
-// RUN: %clang -### -target r600 -x cl -S -emit-llvm -mcpu=rv730 %s -o - 2>&1 | FileCheck --check-prefix=RV730-CHECK %s
-// RUN: %clang -### -target r600 -x cl -S -emit-llvm -mcpu=rv740 %s -o - 2>&1 | FileCheck --check-prefix=RV770-CHECK %s
-// RUN: %clang -### -target r600 -x cl -S -emit-llvm -mcpu=rv770 %s -o - 2>&1 | FileCheck --check-prefix=RV770-CHECK %s
-// RUN: %clang -### -target r600 -x cl -S -emit-llvm -mcpu=palm %s -o - 2>&1 | FileCheck --check-prefix=CEDAR-CHECK %s
-// RUN: %clang -### -target r600 -x cl -S -emit-llvm -mcpu=cedar %s -o - 2>&1 | FileCheck --check-prefix=CEDAR-CHECK %s
-// RUN: %clang -### -target r600 -x cl -S -emit-llvm -mcpu=sumo %s -o - 2>&1 | FileCheck --check-prefix=SUMO-CHECK %s
-// RUN: %clang -### -target r600 -x cl -S -emit-llvm -mcpu=sumo2 %s -o - 2>&1 | FileCheck --check-prefix=SUMO-CHECK %s
-// RUN: %clang -### -target r600 -x cl -S -emit-llvm -mcpu=redwood %s -o - 2>&1 | FileCheck --check-prefix=REDWOOD-CHECK %s
-// RUN: %clang -### -target r600 -x cl -S -emit-llvm -mcpu=juniper %s -o - 2>&1 | FileCheck --check-prefix=JUNIPER-CHECK %s
-// RUN: %clang -### -target r600 -x cl -S -emit-llvm -mcpu=juniper %s -o - 2>&1 | FileCheck --check-prefix=JUNIPER-CHECK %s
-// RUN: %clang -### -target r600 -x cl -S -emit-llvm -mcpu=hemlock %s -o - 2>&1 | FileCheck --check-prefix=CYPRESS-CHECK %s
-// RUN: %clang -### -target r600 -x cl -S -emit-llvm -mcpu=cypress %s -o - 2>&1 | FileCheck --check-prefix=CYPRESS-CHECK %s
-// RUN: %clang -### -target r600 -x cl -S -emit-llvm -mcpu=barts %s -o - 2>&1 | FileCheck --check-prefix=BARTS-CHECK %s
-// RUN: %clang -### -target r600 -x cl -S -emit-llvm -mcpu=turks %s -o - 2>&1 | FileCheck --check-prefix=TURKS-CHECK %s
-// RUN: %clang -### -target r600 -x cl -S -emit-llvm -mcpu=caicos %s -o - 2>&1 | FileCheck --check-prefix=CAICOS-CHECK %s
-// RUN: %clang -### -target r600 -x cl -S -emit-llvm -mcpu=cayman %s -o - 2>&1 | FileCheck --check-prefix=CAYMAN-CHECK %s
-// RUN: %clang -### -target r600 -x cl -S -emit-llvm -mcpu=aruba %s -o - 2>&1 | FileCheck --check-prefix=CAYMAN-CHECK %s
+//
+// R600-based processors.
+//
-// R600-CHECK: "-target-cpu" "r600"
-// RS880-CHECK: "-target-cpu" "rs880"
-// RV670-CHECK: "-target-cpu" "rv670"
-// RV710-CHECK: "-target-cpu" "rv710"
-// RV730-CHECK: "-target-cpu" "rv730"
-// RV770-CHECK: "-target-cpu" "rv770"
-// CEDAR-CHECK: "-target-cpu" "cedar"
-// REDWOOD-CHECK: "-target-cpu" "redwood"
-// SUMO-CHECK: "-target-cpu" "sumo"
-// JUNIPER-CHECK: "-target-cpu" "juniper"
-// CYPRESS-CHECK: "-target-cpu" "cypress"
-// BARTS-CHECK: "-target-cpu" "barts"
-// TURKS-CHECK: "-target-cpu" "turks"
-// CAICOS-CHECK: "-target-cpu" "caicos"
-// CAYMAN-CHECK: "-target-cpu" "cayman"
+// RUN: %clang -### -target r600 -mcpu=r600 %s 2>&1 | FileCheck --check-prefix=R600 %s
+// RUN: %clang -### -target r600 -mcpu=rv630 %s 2>&1 | FileCheck --check-prefix=R600 %s
+// RUN: %clang -### -target r600 -mcpu=rv635 %s 2>&1 | FileCheck --check-prefix=R600 %s
+// RUN: %clang -### -target r600 -mcpu=r630 %s 2>&1 | FileCheck --check-prefix=R630 %s
+// RUN: %clang -### -target r600 -mcpu=rs780 %s 2>&1 | FileCheck --check-prefix=RS880 %s
+// RUN: %clang -### -target r600 -mcpu=rs880 %s 2>&1 | FileCheck --check-prefix=RS880 %s
+// RUN: %clang -### -target r600 -mcpu=rv610 %s 2>&1 | FileCheck --check-prefix=RS880 %s
+// RUN: %clang -### -target r600 -mcpu=rv620 %s 2>&1 | FileCheck --check-prefix=RS880 %s
+// RUN: %clang -### -target r600 -mcpu=rv670 %s 2>&1 | FileCheck --check-prefix=RV670 %s
+// RUN: %clang -### -target r600 -mcpu=rv710 %s 2>&1 | FileCheck --check-prefix=RV710 %s
+// RUN: %clang -### -target r600 -mcpu=rv730 %s 2>&1 | FileCheck --check-prefix=RV730 %s
+// RUN: %clang -### -target r600 -mcpu=rv740 %s 2>&1 | FileCheck --check-prefix=RV770 %s
+// RUN: %clang -### -target r600 -mcpu=rv770 %s 2>&1 | FileCheck --check-prefix=RV770 %s
+// RUN: %clang -### -target r600 -mcpu=cedar %s 2>&1 | FileCheck --check-prefix=CEDAR %s
+// RUN: %clang -### -target r600 -mcpu=palm %s 2>&1 | FileCheck --check-prefix=CEDAR %s
+// RUN: %clang -### -target r600 -mcpu=cypress %s 2>&1 | FileCheck --check-prefix=CYPRESS %s
+// RUN: %clang -### -target r600 -mcpu=hemlock %s 2>&1 | FileCheck --check-prefix=CYPRESS %s
+// RUN: %clang -### -target r600 -mcpu=juniper %s 2>&1 | FileCheck --check-prefix=JUNIPER %s
+// RUN: %clang -### -target r600 -mcpu=redwood %s 2>&1 | FileCheck --check-prefix=REDWOOD %s
+// RUN: %clang -### -target r600 -mcpu=sumo %s 2>&1 | FileCheck --check-prefix=SUMO %s
+// RUN: %clang -### -target r600 -mcpu=sumo2 %s 2>&1 | FileCheck --check-prefix=SUMO %s
+// RUN: %clang -### -target r600 -mcpu=barts %s 2>&1 | FileCheck --check-prefix=BARTS %s
+// RUN: %clang -### -target r600 -mcpu=caicos %s 2>&1 | FileCheck --check-prefix=CAICOS %s
+// RUN: %clang -### -target r600 -mcpu=aruba %s 2>&1 | FileCheck --check-prefix=CAYMAN %s
+// RUN: %clang -### -target r600 -mcpu=cayman %s 2>&1 | FileCheck --check-prefix=CAYMAN %s
+// RUN: %clang -### -target r600 -mcpu=turks %s 2>&1 | FileCheck --check-prefix=TURKS %s
-// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=gfx600 %s -o - 2>&1 | FileCheck --check-prefix=GFX600-CHECK %s
-// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=tahiti %s -o - 2>&1 | FileCheck --check-prefix=TAHITI-CHECK %s
-// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=gfx601 %s -o - 2>&1 | FileCheck --check-prefix=GFX601-CHECK %s
-// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=pitcairn %s -o - 2>&1 | FileCheck --check-prefix=PITCAIRN-CHECK %s
-// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=verde %s -o - 2>&1 | FileCheck --check-prefix=VERDE-CHECK %s
-// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=oland %s -o - 2>&1 | FileCheck --check-prefix=OLAND-CHECK %s
-// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=hainan %s -o - 2>&1 | FileCheck --check-prefix=HAINAN-CHECK %s
-// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=gfx700 %s -o - 2>&1 | FileCheck --check-prefix=GFX700-CHECK %s
-// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=bonaire %s -o - 2>&1 | FileCheck --check-prefix=BONAIRE-CHECK %s
-// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=kaveri %s -o - 2>&1 | FileCheck --check-prefix=KAVERI-CHECK %s
-// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=gfx701 %s -o - 2>&1 | FileCheck --check-prefix=GFX701-CHECK %s
-// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=hawaii %s -o - 2>&1 | FileCheck --check-prefix=HAWAII-CHECK %s
-// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=gfx702 %s -o - 2>&1 | FileCheck --check-prefix=GFX702-CHECK %s
-// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=gfx703 %s -o - 2>&1 | FileCheck --check-prefix=GFX703-CHECK %s
-// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=kabini %s -o - 2>&1 | FileCheck --check-prefix=KABINI-CHECK %s
-// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=mullins %s -o - 2>&1 | FileCheck --check-prefix=MULLINS-CHECK %s
-// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=gfx800 %s -o - 2>&1 | FileCheck --check-prefix=GFX800-CHECK %s
-// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=iceland %s -o - 2>&1 | FileCheck --check-prefix=ICELAND-CHECK %s
-// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=gfx801 %s -o - 2>&1 | FileCheck --check-prefix=GFX801-CHECK %s
-// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=carrizo %s -o - 2>&1 | FileCheck --check-prefix=CARRIZO-CHECK %s
-// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=gfx802 %s -o - 2>&1 | FileCheck --check-prefix=GFX802-CHECK %s
-// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=tonga %s -o - 2>&1 | FileCheck --check-prefix=TONGA-CHECK %s
-// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=gfx803 %s -o - 2>&1 | FileCheck --check-prefix=GFX803-CHECK %s
-// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=fiji %s -o - 2>&1 | FileCheck --check-prefix=FIJI-CHECK %s
-// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=polaris10 %s -o - 2>&1 | FileCheck --check-prefix=POLARIS10-CHECK %s
-// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=polaris11 %s -o - 2>&1 | FileCheck --check-prefix=POLARIS11-CHECK %s
-// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=gfx804 %s -o - 2>&1 | FileCheck --check-prefix=GFX804-CHECK %s
-// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=gfx810 %s -o - 2>&1 | FileCheck --check-prefix=GFX810-CHECK %s
-// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=stoney %s -o - 2>&1 | FileCheck --check-prefix=STONEY-CHECK %s
-// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=gfx900 %s -o - 2>&1 | FileCheck --check-prefix=GFX900-CHECK %s
-// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=gfx901 %s -o - 2>&1 | FileCheck --check-prefix=GFX901-CHECK %s
-// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=gfx902 %s -o - 2>&1 | FileCheck --check-prefix=GFX902-CHECK %s
-// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=gfx903 %s -o - 2>&1 | FileCheck --check-prefix=GFX903-CHECK %s
+// R600: "-target-cpu" "r600"
+// R630: "-target-cpu" "r630"
+// RS880: "-target-cpu" "rs880"
+// RV670: "-target-cpu" "rv670"
+// RV710: "-target-cpu" "rv710"
+// RV730: "-target-cpu" "rv730"
+// RV770: "-target-cpu" "rv770"
+// CEDAR: "-target-cpu" "cedar"
+// CYPRESS: "-target-cpu" "cypress"
+// JUNIPER: "-target-cpu" "juniper"
+// REDWOOD: "-target-cpu" "redwood"
+// SUMO: "-target-cpu" "sumo"
+// BARTS: "-target-cpu" "barts"
+// CAICOS: "-target-cpu" "caicos"
+// CAYMAN: "-target-cpu" "cayman"
+// TURKS: "-target-cpu" "turks"
-// GFX600-CHECK: "-target-cpu" "gfx600"
-// TAHITI-CHECK: "-target-cpu" "tahiti"
-// GFX601-CHECK: "-target-cpu" "gfx601"
-// PITCAIRN-CHECK: "-target-cpu" "pitcairn"
-// VERDE-CHECK: "-target-cpu" "verde"
-// OLAND-CHECK: "-target-cpu" "oland"
-// HAINAN-CHECK: "-target-cpu" "hainan"
-// GFX700-CHECK: "-target-cpu" "gfx700"
-// BONAIRE-CHECK: "-target-cpu" "bonaire"
-// KAVERI-CHECK: "-target-cpu" "kaveri"
-// GFX701-CHECK: "-target-cpu" "gfx701"
-// HAWAII-CHECK: "-target-cpu" "hawaii"
-// GFX702-CHECK: "-target-cpu" "gfx702"
-// GFX703-CHECK: "-target-cpu" "gfx703"
-// KABINI-CHECK: "-target-cpu" "kabini"
-// MULLINS-CHECK: "-target-cpu" "mullins"
-// GFX800-CHECK: "-target-cpu" "gfx800"
-// ICELAND-CHECK: "-target-cpu" "iceland"
-// GFX801-CHECK: "-target-cpu" "gfx801"
-// CARRIZO-CHECK: "-target-cpu" "carrizo"
-// GFX802-CHECK: "-target-cpu" "gfx802"
-// TONGA-CHECK: "-target-cpu" "tonga"
-// GFX803-CHECK: "-target-cpu" "gfx803"
-// FIJI-CHECK: "-target-cpu" "fiji"
-// POLARIS10-CHECK: "-target-cpu" "polaris10"
-// POLARIS11-CHECK: "-target-cpu" "polaris11"
-// GFX804-CHECK: "-target-cpu" "gfx804"
-// GFX810-CHECK: "-target-cpu" "gfx810"
-// STONEY-CHECK: "-target-cpu" "stoney"
-// GFX900-CHECK: "-target-cpu" "gfx900"
-// GFX901-CHECK: "-target-cpu" "gfx901"
-// GFX902-CHECK: "-target-cpu" "gfx902"
-// GFX903-CHECK: "-target-cpu" "gfx903"
+//
+// AMDGCN-based processors.
+//
+
+// RUN: %clang -### -target amdgcn -mcpu=gfx600 %s 2>&1 | FileCheck --check-prefix=GFX600 %s
+// RUN: %clang -### -target amdgcn -mcpu=tahiti %s 2>&1 | FileCheck --check-prefix=TAHITI %s
+// RUN: %clang -### -target amdgcn -mcpu=gfx601 %s 2>&1 | FileCheck --check-prefix=GFX601 %s
+// RUN: %clang -### -target amdgcn -mcpu=hainan %s 2>&1 | FileCheck --check-prefix=HAINAN %s
+// RUN: %clang -### -target amdgcn -mcpu=oland %s 2>&1 | FileCheck --check-prefix=OLAND %s
+// RUN: %clang -### -target amdgcn -mcpu=pitcairn %s 2>&1 | FileCheck --check-prefix=PITCAIRN %s
+// RUN: %clang -### -target amdgcn -mcpu=verde %s 2>&1 | FileCheck --check-prefix=VERDE %s
+// RUN: %clang -### -target amdgcn -mcpu=gfx700 %s 2>&1 | FileCheck --check-prefix=GFX700 %s
+// RUN: %clang -### -target amdgcn -mcpu=kaveri %s 2>&1 | FileCheck --check-prefix=KAVERI %s
+// RUN: %clang -### -target amdgcn -mcpu=gfx701 %s 2>&1 | FileCheck --check-prefix=GFX701 %s
+// RUN: %clang -### -target amdgcn -mcpu=hawaii %s 2>&1 | FileCheck --check-prefix=HAWAII %s
+// RUN: %clang -### -target amdgcn -mcpu=gfx702 %s 2>&1 | FileCheck --check-prefix=GFX702 %s
+// RUN: %clang -### -target amdgcn -mcpu=gfx703 %s 2>&1 | FileCheck --check-prefix=GFX703 %s
+// RUN: %clang -### -target amdgcn -mcpu=kabini %s 2>&1 | FileCheck --check-prefix=KABINI %s
+// RUN: %clang -### -target amdgcn -mcpu=mullins %s 2>&1 | FileCheck --check-prefix=MULLINS %s
+// RUN: %clang -### -target amdgcn -mcpu=gfx704 %s 2>&1 | FileCheck --check-prefix=GFX704 %s
+// RUN: %clang -### -target amdgcn -mcpu=bonaire %s 2>&1 | FileCheck --check-prefix=BONAIRE %s
+// RUN: %clang -### -target amdgcn -mcpu=gfx801 %s 2>&1 | FileCheck --check-prefix=GFX801 %s
+// RUN: %clang -### -target amdgcn -mcpu=carrizo %s 2>&1 | FileCheck --check-prefix=CARRIZO %s
+// RUN: %clang -### -target amdgcn -mcpu=gfx802 %s 2>&1 | FileCheck --check-prefix=GFX802 %s
+// RUN: %clang -### -target amdgcn -mcpu=iceland %s 2>&1 | FileCheck --check-prefix=ICELAND %s
+// RUN: %clang -### -target amdgcn -mcpu=tonga %s 2>&1 | FileCheck --check-prefix=TONGA %s
+// RUN: %clang -### -target amdgcn -mcpu=gfx803 %s 2>&1 | FileCheck --check-prefix=GFX803 %s
+// RUN: %clang -### -target amdgcn -mcpu=fiji %s 2>&1 | FileCheck --check-prefix=FIJI %s
+// RUN: %clang -### -target amdgcn -mcpu=polaris10 %s 2>&1 | FileCheck --check-prefix=POLARIS10 %s
+// RUN: %clang -### -target amdgcn -mcpu=polaris11 %s 2>&1 | FileCheck --check-prefix=POLARIS11 %s
+// RUN: %clang -### -target amdgcn -mcpu=gfx810 %s 2>&1 | FileCheck --check-prefix=GFX810 %s
+// RUN: %clang -### -target amdgcn -mcpu=stoney %s 2>&1 | FileCheck --check-prefix=STONEY %s
+// RUN: %clang -### -target amdgcn -mcpu=gfx900 %s 2>&1 | FileCheck --check-prefix=GFX900 %s
+// RUN: %clang -### -target amdgcn -mcpu=gfx902 %s 2>&1 | FileCheck --check-prefix=GFX902 %s
+// RUN: %clang -### -target amdgcn -mcpu=gfx904 %s 2>&1 | FileCheck --check-prefix=GFX904 %s
+// RUN: %clang -### -target amdgcn -mcpu=gfx906 %s 2>&1 | FileCheck --check-prefix=GFX906 %s
+
+// GFX600: "-target-cpu" "gfx600"
+// TAHITI: "-target-cpu" "tahiti"
+// GFX601: "-target-cpu" "gfx601"
+// HAINAN: "-target-cpu" "hainan"
+// OLAND: "-target-cpu" "oland"
+// PITCAIRN: "-target-cpu" "pitcairn"
+// VERDE: "-target-cpu" "verde"
+// GFX700: "-target-cpu" "gfx700"
+// KAVERI: "-target-cpu" "kaveri"
+// GFX701: "-target-cpu" "gfx701"
+// HAWAII: "-target-cpu" "hawaii"
+// GFX702: "-target-cpu" "gfx702"
+// GFX703: "-target-cpu" "gfx703"
+// KABINI: "-target-cpu" "kabini"
+// MULLINS: "-target-cpu" "mullins"
+// GFX704: "-target-cpu" "gfx704"
+// BONAIRE: "-target-cpu" "bonaire"
+// GFX801: "-target-cpu" "gfx801"
+// CARRIZO: "-target-cpu" "carrizo"
+// GFX802: "-target-cpu" "gfx802"
+// ICELAND: "-target-cpu" "iceland"
+// TONGA: "-target-cpu" "tonga"
+// GFX803: "-target-cpu" "gfx803"
+// FIJI: "-target-cpu" "fiji"
+// POLARIS10: "-target-cpu" "polaris10"
+// POLARIS11: "-target-cpu" "polaris11"
+// GFX810: "-target-cpu" "gfx810"
+// STONEY: "-target-cpu" "stoney"
+// GFX900: "-target-cpu" "gfx900"
+// GFX902: "-target-cpu" "gfx902"
+// GFX904: "-target-cpu" "gfx904"
+// GFX906: "-target-cpu" "gfx906"
diff --git a/test/Driver/ananas.c b/test/Driver/ananas.c
index 2a5b35ed6cec..4edc2a10941c 100644
--- a/test/Driver/ananas.c
+++ b/test/Driver/ananas.c
@@ -7,3 +7,11 @@
// CHECK-STATIC: crtbegin.o
// CHECK-STATIC: crtend.o
// CHECK-STATIC: crtn.o
+
+// RUN: %clang -no-canonical-prefixes -target x86_64-unknown-ananas -shared %s \
+// RUN: --sysroot=%S/Inputs/ananas-tree -### 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-SHARED %s
+// CHECK-SHARED: crti.o
+// CHECK-SHARED: crtbeginS.o
+// CHECK-SHARED: crtendS.o
+// CHECK-SHARED: crtn.o
diff --git a/test/Driver/android-ndk-standalone.cpp b/test/Driver/android-ndk-standalone.cpp
index 86ab85269f76..dd5ebe9754af 100644
--- a/test/Driver/android-ndk-standalone.cpp
+++ b/test/Driver/android-ndk-standalone.cpp
@@ -2,7 +2,7 @@
// toolchain.
//
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -target arm-linux-androideabi -stdlib=libstdc++ \
+// RUN: -target arm-linux-androideabi21 -stdlib=libstdc++ \
// RUN: -B%S/Inputs/basic_android_ndk_tree \
// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
// RUN: | FileCheck %s
@@ -19,6 +19,7 @@
// CHECK: "-internal-isystem" "{{.*}}/include/c++/4.9/backward"
// CHECK: "-internal-isystem" "{{.*}}/sysroot/usr/local/include"
// CHECK: "-internal-isystem" "[[RESOURCE_DIR]]{{(/|\\\\)}}include"
+// CHECK: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include/arm-linux-androideabi"
// CHECK: "-internal-externc-isystem" "{{.*}}/sysroot/include"
// CHECK: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include"
// CHECK: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
@@ -32,14 +33,23 @@
// CHECK-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib/armv7-a/thumb"
// CHECK-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib/armv7-a"
// CHECK-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib/thumb"
+// CHECK: "-L{{.*}}/sysroot/usr/lib/arm-linux-androideabi/21"
+// CHECK: "-L{{.*}}/sysroot/usr/lib/arm-linux-androideabi"
// CHECK: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/arm-linux-androideabi/lib"
// CHECK-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib/armv7-a/thumb"
// CHECK-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib/armv7-a"
// CHECK-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib/thumb"
-// CHECK: "-L{{.*}}/sysroot/usr/lib"
//
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -target armv7a-none-linux-androideabi -stdlib=libstdc++ \
+// RUN: -target arm-linux-androideabi14 \
+// RUN: -B%S/Inputs/basic_android_ndk_tree \
+// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
+// RUN: | FileCheck --check-prefix=CHECK-14 %s
+// CHECK-14: "-L{{.*}}/sysroot/usr/lib/arm-linux-androideabi/14"
+// CHECK-14: "-L{{.*}}/sysroot/usr/lib/arm-linux-androideabi"
+//
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: -target armv7a-none-linux-androideabi21 -stdlib=libstdc++ \
// RUN: -B%S/Inputs/basic_android_ndk_tree \
// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
// RUN: | FileCheck --check-prefix=CHECK-ARMV7 %s
@@ -56,6 +66,7 @@
// CHECK-ARMV7: "-internal-isystem" "{{.*}}/include/c++/4.9/backward"
// CHECK-ARMV7: "-internal-isystem" "{{.*}}/sysroot/usr/local/include"
// CHECK-ARMV7: "-internal-isystem" "[[RESOURCE_DIR]]{{(/|\\\\)}}include"
+// CHECK-ARMV7: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include/arm-linux-androideabi"
// CHECK-ARMV7: "-internal-externc-isystem" "{{.*}}/sysroot/include"
// CHECK-ARMV7: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include"
// CHECK-ARMV7: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
@@ -69,27 +80,28 @@
// CHECK-ARMV7-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib/thumb"
// CHECK-ARMV7-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib/armv7-a/thumb"
// CHECK-ARMV7-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib"
+// CHECK-ARMV7: "-L{{.*}}/sysroot/usr/lib/arm-linux-androideabi/21"
+// CHECK-ARMV7: "-L{{.*}}/sysroot/usr/lib/arm-linux-androideabi"
// CHECK-ARMV7: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib/armv7-a"
// CHECK-ARMV7-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib/thumb"
// CHECK-ARMV7-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib/armv7-a/thumb"
// CHECK-ARMV7-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib"
-// CHECK-ARMV7: "-L{{.*}}/sysroot/usr/lib"
//
// Other flags that can trigger armv7 mode.
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -target arm-linux-androideabi -stdlib=libstdc++ \
+// RUN: -target arm-linux-androideabi21 -stdlib=libstdc++ \
// RUN: -march=armv7 \
// RUN: -B%S/Inputs/basic_android_ndk_tree \
// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
// RUN: | FileCheck --check-prefix=CHECK-ARMV7 %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -target arm-linux-androideabi -stdlib=libstdc++ \
+// RUN: -target arm-linux-androideabi21 -stdlib=libstdc++ \
// RUN: -march=armv7a \
// RUN: -B%S/Inputs/basic_android_ndk_tree \
// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
// RUN: | FileCheck --check-prefix=CHECK-ARMV7 %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -target arm-linux-androideabi -stdlib=libstdc++ \
+// RUN: -target arm-linux-androideabi21 -stdlib=libstdc++ \
// RUN: -march=armv7-a \
// RUN: -B%S/Inputs/basic_android_ndk_tree \
// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
@@ -97,7 +109,7 @@
//
// ARM thumb mode.
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -target arm-linux-androideabi -stdlib=libstdc++ \
+// RUN: -target arm-linux-androideabi21 -stdlib=libstdc++ \
// RUN: -mthumb \
// RUN: -B%S/Inputs/basic_android_ndk_tree \
// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
@@ -115,6 +127,7 @@
// CHECK-THUMB: "-internal-isystem" "{{.*}}/include/c++/4.9/backward"
// CHECK-THUMB: "-internal-isystem" "{{.*}}/sysroot/usr/local/include"
// CHECK-THUMB: "-internal-isystem" "[[RESOURCE_DIR]]{{(/|\\\\)}}include"
+// CHECK-THUMB: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include/arm-linux-androideabi"
// CHECK-THUMB: "-internal-externc-isystem" "{{.*}}/sysroot/include"
// CHECK-THUMB: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include"
// CHECK-THUMB: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
@@ -128,6 +141,8 @@
// CHECK-THUMB-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib/armv7"
// CHECK-THUMB-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib/armv7/thumb"
// CHECK-THUMB-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib"
+// CHECK-THUMB: "-L{{.*}}/sysroot/usr/lib/arm-linux-androideabi/21"
+// CHECK-THUMB: "-L{{.*}}/sysroot/usr/lib/arm-linux-androideabi"
// CHECK-THUMB: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib/thumb"
// CHECK-THUMB-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib/armv7"
// CHECK-THUMB-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib/armv7/thumb"
@@ -136,7 +151,7 @@
//
// ARM V7 thumb mode.
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -target arm-linux-androideabi -stdlib=libstdc++ \
+// RUN: -target arm-linux-androideabi21 -stdlib=libstdc++ \
// RUN: -march=armv7-a -mthumb \
// RUN: -B%S/Inputs/basic_android_ndk_tree \
// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
@@ -154,6 +169,7 @@
// CHECK-ARMV7THUMB: "-internal-isystem" "{{.*}}/include/c++/4.9/backward"
// CHECK-ARMV7THUMB: "-internal-isystem" "{{.*}}/sysroot/usr/local/include"
// CHECK-ARMV7THUMB: "-internal-isystem" "[[RESOURCE_DIR]]{{(/|\\\\)}}include"
+// CHECK-ARMV7THUMB: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include/arm-linux-androideabi"
// CHECK-ARMV7THUMB: "-internal-externc-isystem" "{{.*}}/sysroot/include"
// CHECK-ARMV7THUMB: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include"
// CHECK-ARMV7THUMB: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
@@ -167,14 +183,15 @@
// CHECK-ARMV7THUMB-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib/thumb"
// CHECK-ARMV7THUMB-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib/armv7-a"
// CHECK-ARMV7THUMB-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib"
+// CHECK-ARMV7THUMB: "-L{{.*}}/sysroot/usr/lib/arm-linux-androideabi/21"
+// CHECK-ARMV7THUMB: "-L{{.*}}/sysroot/usr/lib/arm-linux-androideabi"
// CHECK-ARMV7THUMB: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib/armv7-a/thumb"
// CHECK-ARMV7THUMB-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib/thumb"
// CHECK-ARMV7THUMB-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib/armv7-a"
// CHECK-ARMV7THUMB-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib"
-// CHECK-ARMV7THUMB: "-L{{.*}}/sysroot/usr/lib"
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -target arm-linux-androideabi -stdlib=libstdc++ \
+// RUN: -target arm-linux-androideabi21 -stdlib=libstdc++ \
// RUN: -march=armv7-a -mthumb \
// RUN: -B%S/Inputs/basic_android_ndk_tree \
// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
@@ -188,14 +205,14 @@
//
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -target armv7a-none-linux-androideabi -stdlib=libstdc++ \
+// RUN: -target armv7a-none-linux-androideabi21 -stdlib=libstdc++ \
// RUN: -mthumb \
// RUN: -B%S/Inputs/basic_android_ndk_tree \
// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
// RUN: | FileCheck --check-prefix=CHECK-ARMV7THUMB %s
//
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -target aarch64-linux-android -stdlib=libstdc++ \
+// RUN: -target aarch64-linux-android21 -stdlib=libstdc++ \
// RUN: -B%S/Inputs/basic_android_ndk_tree \
// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
// RUN: | FileCheck --check-prefix=CHECK-AARCH64 %s
@@ -203,15 +220,17 @@
// CHECK-AARCH64: "-internal-isystem" "{{.*}}/include/c++/4.9"
// CHECK-AARCH64: "-internal-isystem" "{{.*}}/include/c++/4.9/aarch64-linux-android"
// CHECK-AARCH64: "-internal-isystem" "{{.*}}/include/c++/4.9/backward"
+// CHECK-AARCH64: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include/aarch64-linux-android"
// CHECK-AARCH64: "-internal-externc-isystem" "{{.*}}/sysroot/include"
// CHECK-AARCH64: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include"
// CHECK-AARCH64: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
// CHECK-AARCH64: "-L{{.*}}/lib/gcc/aarch64-linux-android/4.9"
+// CHECK-AARCH64: "-L{{.*}}/sysroot/usr/lib/aarch64-linux-android/21"
+// CHECK-AARCH64: "-L{{.*}}/sysroot/usr/lib/aarch64-linux-android"
// CHECK-AARCH64: "-L{{.*}}/lib/gcc/aarch64-linux-android/4.9/../../../../aarch64-linux-android/lib"
-// CHECK-AARCH64: "-L{{.*}}/sysroot/usr/lib"
//
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -target arm64-linux-android -stdlib=libstdc++ \
+// RUN: -target arm64-linux-android21 -stdlib=libstdc++ \
// RUN: -B%S/Inputs/basic_android_ndk_tree \
// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
// RUN: | FileCheck --check-prefix=CHECK-ARM64 %s
@@ -219,15 +238,17 @@
// CHECK-ARM64: "-internal-isystem" "{{.*}}/include/c++/4.9"
// CHECK-ARM64: "-internal-isystem" "{{.*}}/include/c++/4.9/aarch64-linux-android"
// CHECK-ARM64: "-internal-isystem" "{{.*}}/include/c++/4.9/backward"
+// CHECK-ARM64: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include/aarch64-linux-android"
// CHECK-ARM64: "-internal-externc-isystem" "{{.*}}/sysroot/include"
// CHECK-ARM64: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include"
// CHECK-ARM64: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
// CHECK-ARM64: "-L{{.*}}/lib/gcc/aarch64-linux-android/4.9"
+// CHECK-ARM64: "-L{{.*}}/sysroot/usr/lib/aarch64-linux-android/21"
+// CHECK-ARM64: "-L{{.*}}/sysroot/usr/lib/aarch64-linux-android"
// CHECK-ARM64: "-L{{.*}}/lib/gcc/aarch64-linux-android/4.9/../../../../aarch64-linux-android/lib"
-// CHECK-ARM64: "-L{{.*}}/sysroot/usr/lib"
//
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -target mipsel-linux-android \
+// RUN: -target mipsel-linux-android21 \
// RUN: -mips32 -stdlib=libstdc++ \
// RUN: -B%S/Inputs/basic_android_ndk_tree \
// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
@@ -240,79 +261,12 @@
// CHECK-MIPS: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include"
// CHECK-MIPS: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
// CHECK-MIPS: "-L{{.*}}/lib/gcc/mipsel-linux-android/4.9"
+// CHECK-MIPS: "-L{{.*}}/sysroot/usr/lib/mipsel-linux-android/21"
+// CHECK-MIPS: "-L{{.*}}/sysroot/usr/lib/mipsel-linux-android"
// CHECK-MIPS: "-L{{.*}}/lib/gcc/mipsel-linux-android/4.9/../../../../mipsel-linux-android/lib"
-// CHECK-MIPS: "-L{{.*}}/sysroot/usr/lib"
-//
-// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -target mipsel-linux-android \
-// RUN: -march=mips32 -mips32r2 -stdlib=libstdc++ \
-// RUN: -B%S/Inputs/basic_android_ndk_tree \
-// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
-// RUN: | FileCheck --check-prefix=CHECK-MIPSR2 %s
-// CHECK-MIPSR2: {{.*}}clang{{.*}}" "-cc1"
-// CHECK-MIPSR2: "-internal-isystem" "{{.*}}/include/c++/4.9"
-// CHECK-MIPSR2: "-internal-isystem" "{{.*}}/include/c++/4.9/mipsel-linux-android/mips-r2"
-// CHECK-MIPSR2: "-internal-isystem" "{{.*}}/include/c++/4.9/backward"
-// CHECK-MIPSR2: "-internal-externc-isystem" "{{.*}}/sysroot/include"
-// CHECK-MIPSR2: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include"
-// CHECK-MIPSR2: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
-// CHECK-MIPSR2: "-L{{.*}}/lib/gcc/mipsel-linux-android/4.9/mips-r2"
-// CHECK-MIPSR2: "-L{{.*}}/lib/gcc/mipsel-linux-android/4.9/../../../../mipsel-linux-android/lib/../libr2"
-// CHECK-MIPSR2: "-L{{.*}}/sysroot/usr/lib/../libr2"
-//
-// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -target mipsel-linux-android \
-// RUN: -mips32r6 -stdlib=libstdc++ \
-// RUN: -B%S/Inputs/basic_android_ndk_tree \
-// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
-// RUN: | FileCheck --check-prefix=CHECK-MIPSR6 %s
-// CHECK-MIPSR6: {{.*}}clang{{.*}}" "-cc1"
-// CHECK-MIPSR6: "-internal-isystem" "{{.*}}/include/c++/4.9"
-// CHECK-MIPSR6: "-internal-isystem" "{{.*}}/include/c++/4.9/mipsel-linux-android/mips-r6"
-// CHECK-MIPSR6: "-internal-isystem" "{{.*}}/include/c++/4.9/backward"
-// CHECK-MIPSR6: "-internal-externc-isystem" "{{.*}}/sysroot/include"
-// CHECK-MIPSR6: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include"
-// CHECK-MIPSR6: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
-// CHECK-MIPSR6: "-L{{.*}}/lib/gcc/mipsel-linux-android/4.9/mips-r6"
-// CHECK-MIPSR6: "-L{{.*}}/lib/gcc/mipsel-linux-android/4.9/../../../../mipsel-linux-android/lib/../libr6"
-// CHECK-MIPSR6: "-L{{.*}}/sysroot/usr/lib/../libr6"
-//
-// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -target mips64el-linux-android \
-// RUN: -march=mips32 -mips32r2 -stdlib=libstdc++ \
-// RUN: -B%S/Inputs/basic_android_ndk_tree \
-// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
-// RUN: | FileCheck --check-prefix=CHECK-MIPS64-R2 %s
-// CHECK-MIPS64-R2: {{.*}}clang{{.*}}" "-cc1"
-// CHECK-MIPS64-R2: "-internal-isystem" "{{.*}}/include/c++/4.9"
-// CHECK-MIPS64-R2: "-internal-isystem" "{{.*}}/include/mips64el-linux-android/c++/4.9/mips-r2"
-// CHECK-MIPS64-R2: "-internal-isystem" "{{.*}}/include/c++/4.9/backward"
-// CHECK-MIPS64-R2: "-internal-externc-isystem" "{{.*}}/sysroot/include"
-// CHECK-MIPS64-R2: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include"
-// CHECK-MIPS64-R2: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
-// CHECK-MIPS64-R2: "-L{{.*}}/lib/gcc/mips64el-linux-android/4.9/32/mips-r2"
-// CHECK-MIPS64-R2: "-L{{.*}}/lib/gcc/mips64el-linux-android/4.9/../../../../mips64el-linux-android/lib/../libr2"
-// CHECK-MIPS64-R2: "-L{{.*}}/sysroot/usr/lib/../libr2"
-//
-// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -target mips64el-linux-android \
-// RUN: -march=mips32 -mips32r6 -stdlib=libstdc++ \
-// RUN: -B%S/Inputs/basic_android_ndk_tree \
-// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
-// RUN: | FileCheck --check-prefix=CHECK-MIPS64-R6 %s
-// CHECK-MIPS64-R6: {{.*}}clang{{.*}}" "-cc1"
-// CHECK-MIPS64-R6: "-internal-isystem" "{{.*}}/include/c++/4.9"
-// CHECK-MIPS64-R6: "-internal-isystem" "{{.*}}/include/mips64el-linux-android/c++/4.9/mips-r6"
-// CHECK-MIPS64-R6: "-internal-isystem" "{{.*}}/include/c++/4.9/backward"
-// CHECK-MIPS64-R6: "-internal-externc-isystem" "{{.*}}/sysroot/include"
-// CHECK-MIPS64-R6: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include"
-// CHECK-MIPS64-R6: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
-// CHECK-MIPS64-R6: "-L{{.*}}/lib/gcc/mips64el-linux-android/4.9/32/mips-r6"
-// CHECK-MIPS64-R6: "-L{{.*}}/lib/gcc/mips64el-linux-android/4.9/../../../../mips64el-linux-android/lib/../libr6"
-// CHECK-MIPS64-R6: "-L{{.*}}/sysroot/usr/lib/../libr6"
//
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -target i686-linux-android \
+// RUN: -target i686-linux-android21 \
// RUN: -stdlib=libstdc++ \
// RUN: -B%S/Inputs/basic_android_ndk_tree \
// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
@@ -321,9 +275,65 @@
// CHECK-I686: "-internal-isystem" "{{.*}}/include/c++/4.9"
// CHECK-I686: "-internal-isystem" "{{.*}}/include/c++/4.9/i686-linux-android"
// CHECK-I686: "-internal-isystem" "{{.*}}/include/c++/4.9/backward"
+// CHECK-I686: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include/i686-linux-android"
// CHECK-I686: "-internal-externc-isystem" "{{.*}}/sysroot/include"
// CHECK-I686: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include"
// CHECK-I686: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
// CHECK-I686: "-L{{.*}}/lib/gcc/i686-linux-android/4.9"
+// CHECK-I686: "-L{{.*}}/sysroot/usr/lib/i686-linux-android/21"
+// CHECK-I686: "-L{{.*}}/sysroot/usr/lib/i686-linux-android"
// CHECK-I686: "-L{{.*}}/lib/gcc/i686-linux-android/4.9/../../../../i686-linux-android/lib"
-// CHECK-I686: "-L{{.*}}/sysroot/usr/lib"
+//
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: -target x86_64-linux-android21 \
+// RUN: -stdlib=libstdc++ \
+// RUN: -B%S/Inputs/basic_android_ndk_tree \
+// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
+// RUN: | FileCheck --check-prefix=CHECK-X86_64 %s
+// CHECK-X86_64: {{.*}}clang{{.*}}" "-cc1"
+// CHECK-X86_64: "-internal-isystem" "{{.*}}/include/c++/4.9"
+// CHECK-X86_64: "-internal-isystem" "{{.*}}/include/c++/4.9/x86_64-linux-android"
+// CHECK-X86_64: "-internal-isystem" "{{.*}}/include/c++/4.9/backward"
+// CHECK-X86_64: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include/x86_64-linux-android"
+// CHECK-X86_64: "-internal-externc-isystem" "{{.*}}/sysroot/include"
+// CHECK-X86_64: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include"
+// CHECK-X86_64: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
+// CHECK-X86_64: "-L{{.*}}/lib/gcc/x86_64-linux-android/4.9"
+// CHECK-X86_64: "-L{{.*}}/sysroot/usr/lib/x86_64-linux-android/21"
+// CHECK-X86_64: "-L{{.*}}/sysroot/usr/lib/x86_64-linux-android"
+// CHECK-X86_64: "-L{{.*}}/lib/gcc/x86_64-linux-android/4.9/../../../../x86_64-linux-android/lib"
+
+// We need two sets of tests to verify that we both don't find non-Android
+// toolchains installations and that we *do* find Android toolchains. We can't
+// do both at the same time in this environment because we need to pass
+// --sysroot to find the toolchains which would override searching in /usr. In a
+// production environment --sysroot is not used and the toolchains are instead
+// found relative to the clang binary, so both would be considered.
+
+// RUN: %clang -v --target=i686-linux-android \
+// RUN: 2>&1 | FileCheck --check-prefix=CHECK-I686-GCC-NOSYS %s
+//
+// CHECK-I686-GCC-NOSYS-NOT: Found candidate GCC installation: /usr{{.*}}
+//
+// RUN: %clang -v --target=i686-linux-android \
+// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree \
+// RUN: 2>&1 | FileCheck --check-prefix=CHECK-I686-GCC %s
+//
+// CHECK-I686-GCC-NOT: Found candidate GCC installation: /usr{{.*}}
+// CHECK-I686-GCC: Found candidate GCC installation: {{.*}}i686-linux-android{{[/\\]}}4.9
+// CHECK-I686-GCC-NEXT: Found candidate GCC installation: {{.*}}x86_64-linux-android{{[/\\]}}4.9
+// CHECK-I686-GCC-NEXT: Selected GCC installation: {{.*}}i686-linux-android{{[/\\]}}4.9
+
+// RUN: %clang -v --target=x86_64-linux-android \
+// RUN: 2>&1 | FileCheck --check-prefix=CHECK-X86_64-GCC-NOSYS %s
+//
+// CHECK-X86_64-GCC-NOSYS-NOT: Found candidate GCC installation: /usr{{.*}}
+
+// RUN: %clang -v --target=x86_64-linux-android \
+// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree \
+// RUN: 2>&1 | FileCheck --check-prefix=CHECK-X86_64-GCC %s
+//
+// CHECK-X86_64-GCC-NOT: Found candidate GCC installation: /usr{{.*}}
+// CHECK-X86_64-GCC: Found candidate GCC installation: {{.*}}i686-linux-android{{[/\\]}}4.9
+// CHECK-X86_64-GCC-NEXT: Found candidate GCC installation: {{.*}}x86_64-linux-android{{[/\\]}}4.9
+// CHECK-X86_64-GCC-NEXT: Selected GCC installation: {{.*}}x86_64-linux-android{{[/\\]}}4.9
diff --git a/test/Driver/android-pie.c b/test/Driver/android-pie.c
index 2569c55d5888..052c0bcb4064 100644
--- a/test/Driver/android-pie.c
+++ b/test/Driver/android-pie.c
@@ -64,3 +64,20 @@
// RUN: | FileCheck --check-prefix=NO-PIE %s
// RUN: %clang %s -### -o %t.o 2>&1 -pie -no-pie --target=arm-linux-androideabi24 \
// RUN: | FileCheck --check-prefix=NO-PIE %s
+
+// Static/shared/relocatable disable -pie
+
+// RUN: %clang %s -### --target=aarch64-linux-android -static 2>&1 \
+// RUN: | FileCheck %s -check-prefix=CHECK-STATIC
+// CHECK-STATIC-NOT: "-pie"
+// CHECK-STATIC: -static
+
+// RUN: %clang %s -### --target=aarch64-linux-android -shared 2>&1 \
+// RUN: | FileCheck %s -check-prefix=CHECK-SHARED
+// CHECK-SHARED-NOT: "-pie"
+// CHECK-SHARED: "-shared"
+
+// RUN: %clang %s -### --target=aarch64-linux-android -r 2>&1 \
+// RUN: | FileCheck %s -check-prefix=CHECK-RELOCATABLE
+// CHECK-RELOCATABLE-NOT: "-pie"
+// CHECK-RELOCATABLE: "-r"
diff --git a/test/Driver/apple-kext-mkernel.c b/test/Driver/apple-kext-mkernel.c
index db3fbb333602..9c60c24e36c8 100644
--- a/test/Driver/apple-kext-mkernel.c
+++ b/test/Driver/apple-kext-mkernel.c
@@ -26,7 +26,3 @@
// RUN: %clang -target x86_64-apple-darwin10 \
// RUN: -Werror -fno-builtin -fno-exceptions -fno-common -fno-rtti \
// RUN: -mkernel -fsyntax-only %s
-
-// RUN: %clang -c %s -target armv7k-apple-watchos -fapple-kext -mwatchos-version-min=1.0.0 -### 2>&1 \
-// RUN: | FileCheck %s --check-prefix=CHECK-WATCH
-// CHECK-WATCH-NOT: "-backend-option" "-arm-long-calls"
diff --git a/test/Driver/arch-specific-libdir-rpath.c b/test/Driver/arch-specific-libdir-rpath.c
index 4b210f2cb412..2ea41aade342 100644
--- a/test/Driver/arch-specific-libdir-rpath.c
+++ b/test/Driver/arch-specific-libdir-rpath.c
@@ -6,7 +6,6 @@
// RUN: %clang %s -### 2>&1 -target x86_64-linux \
// RUN: -fsanitize=address -shared-libasan \
// RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
-// RUN: -frtlib-add-rpath \
// RUN: | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,NO-RPATH-X86_64 %s
//
// Test that -rpath is not added under -fno-rtlib-add-rpath even if other
@@ -14,7 +13,7 @@
// RUN: %clang %s -### 2>&1 -target x86_64-linux \
// RUN: -fsanitize=address -shared-libasan \
// RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
-// RUN: -frtlib-add-rpath \
+// RUN: -fno-rtlib-add-rpath \
// RUN: | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,NO-RPATH-X86_64 %s
//
// Test that -rpath is added only under the right circumstance even if
@@ -24,13 +23,13 @@
// RUN: %clang %s -### 2>&1 -target x86_64-linux -fsanitize=undefined \
// RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
// RUN: -frtlib-add-rpath \
-// RUN: | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,NO-RPATH %s
+// RUN: | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,NO-RPATH-X86_64 %s
//
// Add LIBPATH but no RPATH for -fsanitizer=address w/o -shared-libasan
// RUN: %clang %s -### 2>&1 -target x86_64-linux -fsanitize=undefined \
// RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
// RUN: -frtlib-add-rpath \
-// RUN: | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,NO-RPATH %s
+// RUN: | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,NO-RPATH-X86_64 %s
//
// Add LIBPATH, RPATH for -fsanitize=address -shared-libasan
// RUN: %clang %s -### 2>&1 -target x86_64-linux \
@@ -44,7 +43,7 @@
// RUN: -fsanitize=address -shared-libasan \
// RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
// RUN: -frtlib-add-rpath \
-// RUN: | FileCheck --check-prefixes=RESDIR,LIBPATH-AArch64,RPATH-AArch64 %s
+// RUN: | FileCheck --check-prefixes=RESDIR,LIBPATH-AARCH64,RPATH-AARCH64 %s
//
// Add LIBPATH, RPATH with -fsanitize=address for Android
// RUN: %clang %s -### 2>&1 -target x86_64-linux-android -fsanitize=address \
@@ -62,24 +61,30 @@
// RUN: %clang %s -### 2>&1 -fsanitize=undefined -target x86_64-linux \
// RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
// RUN: -frtlib-add-rpath \
-// RUN: | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,NO-RPATH %s
+// RUN: | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,NO-RPATH-X86_64 %s
//
// Add LIBPATH but no RPATH if no sanitizer or runtime is specified
// RUN: %clang %s -### 2>&1 -target x86_64-linux \
// RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
// RUN: -frtlib-add-rpath \
-// RUN: | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,NO-RPATH %s
+// RUN: | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,NO-RPATH-X86_64 %s
//
// Do not add LIBPATH or RPATH if arch-specific subdir doesn't exist
// RUN: %clang %s -### 2>&1 -target x86_64-linux \
// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: -frtlib-add-rpath \
// RUN: | FileCheck --check-prefixes=RESDIR,NO-LIBPATH,NO-RPATH %s
-//
+
// RESDIR: "-resource-dir" "[[RESDIR:[^"]*]]"
-// LIBPATH-X86_64: -L[[RESDIR]]{{(/|\\\\)lib(/|\\\\)linux(/|\\\\)x86_64}}
-// RPATH-X86_64: "-rpath" "[[RESDIR]]{{(/|\\\\)lib(/|\\\\)linux(/|\\\\)x86_64}}"
-// LIBPATH-AArch64: -L[[RESDIR]]{{(/|\\\\)lib(/|\\\\)linux(/|\\\\)aarch64}}
-// RPATH-AArch64: "-rpath" "[[RESDIR]]{{(/|\\\\)lib(/|\\\\)linux(/|\\\\)aarch64}}"
-// NO-LIBPATH-NOT: "-L{{[^"]*Inputs(/|\\\\)resource_dir}}"
-// NO-RPATH-NOT: "-rpath" {{.*(/|\\\\)Inputs(/|\\\\)resource_dir}}
+//
+// LIBPATH-X86_64: -L[[RESDIR]]{{(/|\\\\)lib(/|\\\\)linux(/|\\\\)x86_64}}
+// RPATH-X86_64: "-rpath" "[[RESDIR]]{{(/|\\\\)lib(/|\\\\)linux(/|\\\\)x86_64}}"
+//
+// NO-LIBPATH-X86_64-NOT: -L[[RESDIR]]{{(/|\\\\)lib(/|\\\\)linux(/|\\\\)x86_64}}
+// NO-RPATH-X86_64-NOT: "-rpath" "[[RESDIR]]{{(/|\\\\)lib(/|\\\\)linux(/|\\\\)x86_64}}"
+//
+// LIBPATH-AARCH64: -L[[RESDIR]]{{(/|\\\\)lib(/|\\\\)linux(/|\\\\)aarch64}}
+// RPATH-AAARCH4: "-rpath" "[[RESDIR]]{{(/|\\\\)lib(/|\\\\)linux(/|\\\\)aarch64}}"
+//
+// NO-LIBPATH-NOT: "-L{{[^"]*Inputs(/|\\\\)resource_dir}}"
+// NO-RPATH-NOT: "-rpath" {{.*(/|\\\\)Inputs(/|\\\\)resource_dir}}
diff --git a/test/Driver/arclite-link.c b/test/Driver/arclite-link.c
index 3471bf6516a2..2cc0271fc022 100644
--- a/test/Driver/arclite-link.c
+++ b/test/Driver/arclite-link.c
@@ -1,6 +1,6 @@
// RUN: touch %t.o
-// RUN: %clang -### -target x86_64-apple-darwin10 -fobjc-link-runtime -lfoo -mmacosx-version-min=10.7 %t.o 2>&1 | FileCheck -check-prefix=CHECK-ARCLITE-OSX %s
-// RUN: %clang -### -target x86_64-apple-darwin10 -fobjc-link-runtime -mmacosx-version-min=10.8 %t.o 2>&1 | FileCheck -check-prefix=CHECK-NOARCLITE %s
+// RUN: %clang -### -target x86_64-apple-darwin10 -fobjc-link-runtime -lfoo -mmacosx-version-min=10.10 %t.o 2>&1 | FileCheck -check-prefix=CHECK-ARCLITE-OSX %s
+// RUN: %clang -### -target x86_64-apple-darwin10 -fobjc-link-runtime -mmacosx-version-min=10.11 %t.o 2>&1 | FileCheck -check-prefix=CHECK-NOARCLITE %s
// RUN: %clang -### -target i386-apple-darwin10 -fobjc-link-runtime -mmacosx-version-min=10.7 %t.o 2>&1 | FileCheck -check-prefix=CHECK-NOARCLITE %s
// RUN: %clang -### -target x86_64-apple-darwin10 -fobjc-link-runtime -nostdlib %t.o 2>&1 | FileCheck -check-prefix=CHECK-NOSTDLIB %s
@@ -12,6 +12,6 @@
// CHECK-NOARCLITE-NOT: libarclite
// CHECK-NOSTDLIB-NOT: -lobjc
-// RUN: %clang -### -target x86_64-apple-darwin10 -fobjc-link-runtime -fobjc-arc -mmacosx-version-min=10.7 %s 2>&1 | FileCheck -check-prefix=CHECK-UNUSED %s
+// RUN: %clang -### -target x86_64-apple-darwin10 -fobjc-link-runtime -fobjc-arc -mmacosx-version-min=10.10 %s 2>&1 | FileCheck -check-prefix=CHECK-UNUSED %s
// CHECK-UNUSED-NOT: warning: argument unused during compilation: '-fobjc-link-runtime'
diff --git a/test/Driver/arm-cortex-cpus.c b/test/Driver/arm-cortex-cpus.c
index 8f8178226d55..90542326f36c 100644
--- a/test/Driver/arm-cortex-cpus.c
+++ b/test/Driver/arm-cortex-cpus.c
@@ -284,13 +284,13 @@
// RUN: %clang -target arm -march=armebv8.2-a -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-V82A-THUMB %s
// CHECK-BE-V82A-THUMB: "-cc1"{{.*}} "-triple" "thumbebv8.2a-{{.*}}" "-target-cpu" "generic"
-// RUN: %clang -target armv8a -march=armv8.2-a+fp16 -### -c %s 2>&1 | FileCheck --check-prefix CHECK-V82A-FP16 %s
+// RUN: %clang -target armv8a-linux-eabi -march=armv8.2-a+fp16 -### -c %s 2>&1 | FileCheck --check-prefix CHECK-V82A-FP16 %s
// CHECK-V82A-FP16: "-cc1"{{.*}} "-triple" "armv8.2{{.*}}" "-target-cpu" "generic" {{.*}}"-target-feature" "+fullfp16"
// Once we have CPUs with optional v8.2-A FP16, we will need a way to turn it
// on and off. Cortex-A53 is a placeholder for now.
-// RUN: %clang -target armv8a -mcpu=cortex-a53+fp16 -### -c %s 2>&1 | FileCheck --check-prefix CHECK-CORTEX-A53-FP16 %s
-// RUN: %clang -target armv8a -mcpu=cortex-a53+nofp16 -### -c %s 2>&1 | FileCheck --check-prefix CHECK-CORTEX-A53-NOFP16 %s
+// RUN: %clang -target armv8a-linux-eabi -mcpu=cortex-a53+fp16 -### -c %s 2>&1 | FileCheck --check-prefix CHECK-CORTEX-A53-FP16 %s
+// RUN: %clang -target armv8a-linux-eabi -mcpu=cortex-a53+nofp16 -### -c %s 2>&1 | FileCheck --check-prefix CHECK-CORTEX-A53-NOFP16 %s
// CHECK-CORTEX-A53-FP16: "-cc1" {{.*}}"-target-cpu" "cortex-a53" {{.*}}"-target-feature" "+fullfp16"
// CHECK-CORTEX-A53-NOFP16: "-cc1" {{.*}}"-target-cpu" "cortex-a53" {{.*}}"-target-feature" "-fullfp16"
@@ -493,18 +493,21 @@
// RUN: %clang -target arm -mcpu=cortex-a57 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s
// RUN: %clang -target arm -mcpu=cortex-a72 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s
// RUN: %clang -target arm -mcpu=cortex-a73 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s
-// RUN: %clang -target arm -mcpu=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s
-// RUN: %clang -target arm -mcpu=exynos-m2 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s
-// RUN: %clang -target arm -mcpu=exynos-m3 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s
// RUN: %clang -target arm -mcpu=cortex-a32 -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s
// RUN: %clang -target arm -mcpu=cortex-a35 -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s
// RUN: %clang -target arm -mcpu=cortex-a53 -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s
// RUN: %clang -target arm -mcpu=cortex-a57 -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s
// RUN: %clang -target arm -mcpu=cortex-a72 -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s
// RUN: %clang -target arm -mcpu=cortex-a73 -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s
+//
+// RUN: %clang -target arm -mcpu=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s
+// RUN: %clang -target arm -mcpu=exynos-m2 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s
+// RUN: %clang -target arm -mcpu=exynos-m3 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s
+// RUN: %clang -target arm -mcpu=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s
// RUN: %clang -target arm -mcpu=exynos-m1 -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s
// RUN: %clang -target arm -mcpu=exynos-m2 -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s
// RUN: %clang -target arm -mcpu=exynos-m3 -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s
+// RUN: %clang -target arm -mcpu=exynos-m4 -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s
// CHECK-CPUV8A: "-cc1"{{.*}} "-triple" "armv8-{{.*}}
// RUN: %clang -target arm -mcpu=cortex-a55 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV82A %s
@@ -519,18 +522,21 @@
// RUN: %clang -target armeb -mcpu=cortex-a57 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s
// RUN: %clang -target armeb -mcpu=cortex-a72 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s
// RUN: %clang -target armeb -mcpu=cortex-a73 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s
-// RUN: %clang -target armeb -mcpu=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s
-// RUN: %clang -target armeb -mcpu=exynos-m2 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s
-// RUN: %clang -target armeb -mcpu=exynos-m3 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s
// RUN: %clang -target arm -mcpu=cortex-a32 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s
// RUN: %clang -target arm -mcpu=cortex-a35 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s
// RUN: %clang -target arm -mcpu=cortex-a53 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s
// RUN: %clang -target arm -mcpu=cortex-a57 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s
// RUN: %clang -target arm -mcpu=cortex-a72 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s
// RUN: %clang -target arm -mcpu=cortex-a73 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s
+//
+// RUN: %clang -target armeb -mcpu=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s
+// RUN: %clang -target armeb -mcpu=exynos-m2 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s
+// RUN: %clang -target armeb -mcpu=exynos-m3 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s
+// RUN: %clang -target armeb -mcpu=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s
// RUN: %clang -target arm -mcpu=exynos-m1 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s
// RUN: %clang -target arm -mcpu=exynos-m2 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s
// RUN: %clang -target arm -mcpu=exynos-m3 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s
+// RUN: %clang -target arm -mcpu=exynos-m4 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s
// CHECK-BE-CPUV8A: "-cc1"{{.*}} "-triple" "armebv8-{{.*}}
// RUN: %clang -target armeb -mcpu=cortex-a55 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV82A %s
@@ -548,18 +554,21 @@
// RUN: %clang -target arm -mcpu=cortex-a57 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s
// RUN: %clang -target arm -mcpu=cortex-a72 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s
// RUN: %clang -target arm -mcpu=cortex-a73 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s
-// RUN: %clang -target arm -mcpu=exynos-m1 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s
-// RUN: %clang -target arm -mcpu=exynos-m2 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s
-// RUN: %clang -target arm -mcpu=exynos-m3 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s
// RUN: %clang -target arm -mcpu=cortex-a32 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s
// RUN: %clang -target arm -mcpu=cortex-a35 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s
// RUN: %clang -target arm -mcpu=cortex-a53 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s
// RUN: %clang -target arm -mcpu=cortex-a57 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s
// RUN: %clang -target arm -mcpu=cortex-a72 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s
// RUN: %clang -target arm -mcpu=cortex-a73 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s
+//
+// RUN: %clang -target arm -mcpu=exynos-m1 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s
+// RUN: %clang -target arm -mcpu=exynos-m2 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s
+// RUN: %clang -target arm -mcpu=exynos-m3 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s
+// RUN: %clang -target arm -mcpu=exynos-m4 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s
// RUN: %clang -target arm -mcpu=exynos-m1 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s
// RUN: %clang -target arm -mcpu=exynos-m2 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s
// RUN: %clang -target arm -mcpu=exynos-m3 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s
+// RUN: %clang -target arm -mcpu=exynos-m4 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s
// CHECK-CPUV8A-THUMB: "-cc1"{{.*}} "-triple" "thumbv8-{{.*}}
// RUN: %clang -target arm -mcpu=cortex-a55 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECKCPUV82A-THUMB %s
@@ -574,18 +583,21 @@
// RUN: %clang -target armeb -mcpu=cortex-a57 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s
// RUN: %clang -target armeb -mcpu=cortex-a72 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s
// RUN: %clang -target armeb -mcpu=cortex-a73 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s
-// RUN: %clang -target armeb -mcpu=exynos-m1 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s
-// RUN: %clang -target armeb -mcpu=exynos-m2 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s
-// RUN: %clang -target armeb -mcpu=exynos-m3 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s
// RUN: %clang -target arm -mcpu=cortex-a32 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s
// RUN: %clang -target arm -mcpu=cortex-a35 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s
// RUN: %clang -target arm -mcpu=cortex-a53 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s
// RUN: %clang -target arm -mcpu=cortex-a57 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s
// RUN: %clang -target arm -mcpu=cortex-a72 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s
// RUN: %clang -target arm -mcpu=cortex-a73 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s
+//
+// RUN: %clang -target armeb -mcpu=exynos-m1 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s
+// RUN: %clang -target armeb -mcpu=exynos-m2 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s
+// RUN: %clang -target armeb -mcpu=exynos-m3 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s
+// RUN: %clang -target armeb -mcpu=exynos-m4 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s
// RUN: %clang -target arm -mcpu=exynos-m1 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s
// RUN: %clang -target arm -mcpu=exynos-m2 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s
// RUN: %clang -target arm -mcpu=exynos-m3 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s
+// RUN: %clang -target arm -mcpu=exynos-m4 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s
// CHECK-BE-CPUV8A-THUMB: "-cc1"{{.*}} "-triple" "thumbebv8-{{.*}}
// RUN: %clang -target armeb -mcpu=cortex-a55 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV82A-THUMB %s
diff --git a/test/Driver/arm-dotprod.c b/test/Driver/arm-dotprod.c
index a895d30deefc..971e0de08863 100644
--- a/test/Driver/arm-dotprod.c
+++ b/test/Driver/arm-dotprod.c
@@ -4,8 +4,21 @@
// RUN: %clang -### -target arm -march=armv8.3a %s 2>&1 | FileCheck %s --check-prefix=CHECK-NONE
// CHECK-NONE-NOT: "-target-feature" "+dotprod"
-// RUN: %clang -### -target arm -march=armv8.2a+dotprod %s 2>&1 | FileCheck %s
-// RUN: %clang -### -target arm -march=armv8.3a+dotprod %s 2>&1 | FileCheck %s
-// RUN: %clang -### -target arm -mcpu=cortex-a75 %s 2>&1 | FileCheck %s
-// RUN: %clang -### -target arm -mcpu=cortex-a55 %s 2>&1 | FileCheck %s
+// RUN: %clang -### -target arm-linux-eabi -march=armv8.2a+dotprod %s 2>&1 | FileCheck %s
+// RUN: %clang -### -target arm-linux-eabi -march=armv8.3a+dotprod %s 2>&1 | FileCheck %s
+// RUN: %clang -### -target arm-linux-eabi -mcpu=cortex-a75 %s 2>&1 | FileCheck %s
+// RUN: %clang -### -target arm-linux-eabi -mcpu=cortex-a55 %s 2>&1 | FileCheck %s
// CHECK: "+dotprod"
+
+// The following default to -msoft-float
+// RUN: %clang -### -target arm -march=armv8.2a+dotprod %s 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK-NO-DOTPROD
+// RUN: %clang -### -target arm -march=armv8.3a+dotprod %s 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK-NO-DOTPROD
+// RUN: %clang -### -target arm -mcpu=cortex-a75 %s 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK-NO-DOTPROD
+// RUN: %clang -### -target arm -mcpu=cortex-a55 %s 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK-NO-DOTPROD
+// We rely on the backend disabling dotprod as it depends on neon, so check that
+// neon is disabled after the dotprod was enabled.
+// CHECK-NO-DOTPROD-NOT: "+dotprod"
diff --git a/test/Driver/arm-execute-only.c b/test/Driver/arm-execute-only.c
index c226a7f3b4b1..866d7271d1fa 100644
--- a/test/Driver/arm-execute-only.c
+++ b/test/Driver/arm-execute-only.c
@@ -21,10 +21,6 @@
// RUN: %clang -target armv7m-eabi -x assembler -mexecute-only %s -c -### 2>&1 \
// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY -check-prefix CHECK-NO-EXECUTE-ONLY-ASM
-//
-// CHECK-NO-EXECUTE-ONLY-NOT: "-backend-option" "-arm-execute-only"
-// CHECK-EXECUTE-ONLY: "-backend-option" "-arm-execute-only"
-
// CHECK-EXECUTE-ONLY-NOT-SUPPORTED: error: execute only is not supported for the thumbv6m sub-architecture
// CHECK-EXECUTE-ONLY-NO-MOVT: error: option '-mexecute-only' cannot be specified with '-mno-movt'
// CHECK-EXECUTE-ONLY-LONG-CALLS: error: option '-mexecute-only' cannot be specified with '-mlong-calls'
diff --git a/test/Driver/arm-mfpu.c b/test/Driver/arm-mfpu.c
index 2e1c00dbcced..2f8d64f02392 100644
--- a/test/Driver/arm-mfpu.c
+++ b/test/Driver/arm-mfpu.c
@@ -2,6 +2,8 @@
// RUN: %clang -target arm-linux-eabi %s -### -o %t.o 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-DEFAULT %s
+// CHECK-DEFAULT-NOT: "-target-feature" "+soft-float"
+// CHECK-DEFAULT: "-target-feature" "+soft-float-abi"
// CHECK-DEFAULT-NOT: "-target-feature" "+vfp2"
// CHECK-DEFAULT-NOT: "-target-feature" "+vfp3"
// CHECK-DEFAULT-NOT: "-target-feature" "+d16"
@@ -19,23 +21,49 @@
// RUN: %clang -target arm-linux-eabi -mfpu=vfp %s -### -o %t.o 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-VFP %s
+// RUN: %clang -target arm-linux-eabi -mfpu=vfp %s -mfloat-abi=soft -### -o %t.o 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-SOFT-ABI-FP-2 %s
+// CHECK-VFP-NOT: "-target-feature" "+soft-float"
+// CHECK-VFP: "-target-feature" "+soft-float-abi"
// CHECK-VFP: "-target-feature" "+vfp2"
// CHECK-VFP: "-target-feature" "-vfp3"
// CHECK-VFP: "-target-feature" "-vfp4"
// CHECK-VFP: "-target-feature" "-fp-armv8"
// CHECK-VFP: "-target-feature" "-neon"
+// CHECK-SOFT-ABI-FP-2: "-target-feature" "+soft-float-abi"
+// CHECK-SOFT-ABI-FP-2: "-target-feature" "-vfp3"
+// CHECK-SOFT-ABI-FP-2: "-target-feature" "-vfp4"
+// CHECK-SOFT-ABI-FP-2: "-target-feature" "-fp-armv8"
+// CHECK-SOFT-ABI-FP-2: "-target-feature" "-neon"
+// CHECK-SOFT-ABI-FP-2: "-target-feature" "-crypto"
+// CHECK-SOFT-ABI-FP-2: "-target-feature" "-vfp2"
// RUN: %clang -target arm-linux-eabi -mfpu=vfp3 %s -### -o %t.o 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-VFP3 %s
// RUN: %clang -target arm-linux-eabi -mfpu=vfpv3 %s -### -o %t.o 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-VFP3 %s
+// RUN: %clang -target arm-linux-eabi -mfpu=vfpv3 -mfloat-abi=soft %s -### -o %t.o 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-SOFT-ABI-FP-3 %s
+// CHECK-VFP3-NOT: "-target-feature" "+soft-float"
+// CHECK-VFP3: "-target-feature" "+soft-float-abi"
// CHECK-VFP3: "-target-feature" "+vfp3"
// CHECK-VFP3: "-target-feature" "-vfp4"
// CHECK-VFP3: "-target-feature" "-fp-armv8"
// CHECK-VFP3: "-target-feature" "-neon"
+// CHECK-SOFT-ABI-FP-3: "-target-feature" "+soft-float-abi"
+// CHECK-SOFT-ABI-FP-3: "-target-feature" "-vfp2"
+// CHECK-SOFT-ABI-FP-3: "-target-feature" "-vfp4"
+// CHECK-SOFT-ABI-FP-3: "-target-feature" "-fp-armv8"
+// CHECK-SOFT-ABI-FP-3: "-target-feature" "-neon"
+// CHECK-SOFT-ABI-FP-3: "-target-feature" "-crypto"
+// CHECK-SOFT-ABI-FP-3: "-target-feature" "-vfp3"
// RUN: %clang -target arm-linux-eabi -mfpu=vfpv3-fp16 %s -### -o %t.o 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-VFP3-FP16 %s
+// RUN: %clang -target arm-linux-eabi -mfpu=vfpv3-fp16 -mfloat-abi=soft %s -### -o %t.o 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-SOFT-ABI-FP-3 %s
+// CHECK-VFP3-FP16-NOT: "-target-feature" "+soft-float"
+// CHECK-VFP3-FP16: "-target-feature" "+soft-float-abi"
// CHECK-VFP3-FP16: "-target-feature" "-fp-only-sp"
// CHECK-VFP3-FP16: "-target-feature" "-d16"
// CHECK-VFP3-FP16: "-target-feature" "+vfp3"
@@ -49,6 +77,10 @@
// RUN: | FileCheck --check-prefix=CHECK-VFP3-D16 %s
// RUN: %clang -target arm-linux-eabi -mfpu=vfpv3-d16 %s -### -o %t.o 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-VFP3-D16 %s
+// RUN: %clang -target arm-linux-eabi -mfpu=vfpv3-d16 -mfloat-abi=soft %s -### -o %t.o 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-SOFT-ABI-FP-3 %s
+// CHECK-VFP3-D16-NOT: "-target-feature" "+soft-float"
+// CHECK-VFP3-D16: "-target-feature" "+soft-float-abi"
// CHECK-VFP3-D16: "-target-feature" "-fp-only-sp"
// CHECK-VFP3-D16: "-target-feature" "+d16"
// CHECK-VFP3-D16: "-target-feature" "+vfp3"
@@ -58,6 +90,10 @@
// RUN: %clang -target arm-linux-eabi -mfpu=vfpv3-d16-fp16 %s -### -o %t.o 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-VFP3-D16-FP16 %s
+// RUN: %clang -target arm-linux-eabi -mfpu=vfpv3-d16-fp16 -mfloat-abi=soft %s -### -o %t.o 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-SOFT-ABI-FP-3 %s
+// CHECK-VFP3-D16-FP16-NOT: "-target-feature" "+soft-float"
+// CHECK-VFP3-D16-FP16: "-target-feature" "+soft-float-abi"
// CHECK-VFP3-D16-FP16: "-target-feature" "-fp-only-sp"
// CHECK-VFP3-D16-FP16: "-target-feature" "+d16"
// CHECK-VFP3-D16-FP16: "-target-feature" "+vfp3"
@@ -69,6 +105,10 @@
// RUN: %clang -target arm-linux-eabi -mfpu=vfpv3xd %s -### -o %t.o 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-VFP3XD %s
+// RUN: %clang -target arm-linux-eabi -mfpu=vfpv3xd -mfloat-abi=soft %s -### -o %t.o 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-SOFT-ABI-FP-3 %s
+// CHECK-VFP3XD-NOT: "-target-feature" "+soft-float"
+// CHECK-VFP3XD: "-target-feature" "+soft-float-abi"
// CHECK-VFP3XD: "-target-feature" "+fp-only-sp"
// CHECK-VFP3XD: "-target-feature" "+d16"
// CHECK-VFP3XD: "-target-feature" "+vfp3"
@@ -80,6 +120,10 @@
// RUN: %clang -target arm-linux-eabi -mfpu=vfpv3xd-fp16 %s -### -o %t.o 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-VFP3XD-FP16 %s
+// RUN: %clang -target arm-linux-eabi -mfpu=vfpv3xd-fp16 -mfloat-abi=soft %s -### -o %t.o 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-SOFT-ABI-FP-3 %s
+// CHECK-VFP3XD-FP16-NOT: "-target-feature" "+soft-float"
+// CHECK-VFP3XD-FP16: "-target-feature" "+soft-float-abi"
// CHECK-VFP3XD-FP16: "-target-feature" "+fp-only-sp"
// CHECK-VFP3XD-FP16: "-target-feature" "+d16"
// CHECK-VFP3XD-FP16: "-target-feature" "+vfp3"
@@ -93,14 +137,29 @@
// RUN: | FileCheck --check-prefix=CHECK-VFP4 %s
// RUN: %clang -target arm-linux-eabi -mfpu=vfpv4 %s -### -o %t.o 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-VFP4 %s
+// RUN: %clang -target arm-linux-eabi -mfpu=vfpv4 -mfloat-abi=soft %s -### -o %t.o 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-SOFT-ABI-FP-4 %s
+// CHECK-VFP4-NOT: "-target-feature" "+soft-float"
+// CHECK-VFP4: "-target-feature" "+soft-float-abi"
// CHECK-VFP4: "-target-feature" "+vfp4"
// CHECK-VFP4: "-target-feature" "-fp-armv8"
// CHECK-VFP4: "-target-feature" "-neon"
+// CHECK-SOFT-ABI-FP-4: "-target-feature" "+soft-float-abi"
+// CHECK-SOFT-ABI-FP-4: "-target-feature" "-vfp2"
+// CHECK-SOFT-ABI-FP-4: "-target-feature" "-vfp3"
+// CHECK-SOFT-ABI-FP-4: "-target-feature" "-fp-armv8"
+// CHECK-SOFT-ABI-FP-4: "-target-feature" "-neon"
+// CHECK-SOFT-ABI-FP-4: "-target-feature" "-crypto"
+// CHECK-SOFT-ABI-FP-4: "-target-feature" "-vfp4"
// RUN: %clang -target arm-linux-eabi -mfpu=vfp4-d16 %s -### -o %t.o 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-VFP4-D16 %s
// RUN: %clang -target arm-linux-eabi -mfpu=vfpv4-d16 %s -### -o %t.o 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-VFP4-D16 %s
+// RUN: %clang -target arm-linux-eabi -mfpu=vfpv4-d16 -mfloat-abi=soft %s -### -o %t.o 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-SOFT-ABI-FP-4 %s
+// CHECK-VFP4-D16-NOT: "-target-feature" "+soft-float"
+// CHECK-VFP4-D16: "-target-feature" "+soft-float-abi"
// CHECK-VFP4-D16: "-target-feature" "-fp-only-sp"
// CHECK-VFP4-D16: "-target-feature" "+d16"
// CHECK-VFP4-D16: "-target-feature" "+vfp4"
@@ -111,6 +170,10 @@
// RUN: | FileCheck --check-prefix=CHECK-FP4-SP-D16 %s
// RUN: %clang -target arm-linux-eabi -mfpu=fpv4-sp-d16 %s -### -o %t.o 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-FP4-SP-D16 %s
+// RUN: %clang -target arm-linux-eabi -mfpu=fpv4-sp-d16 -mfloat-abi=soft %s -### -o %t.o 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-SOFT-ABI-FP-4 %s
+// CHECK-FP4-SP-D16-NOT: "-target-feature" "+soft-float"
+// CHECK-FP4-SP-D16: "-target-feature" "+soft-float-abi"
// CHECK-FP4-SP-D16: "-target-feature" "+fp-only-sp"
// CHECK-FP4-SP-D16: "-target-feature" "+d16"
// CHECK-FP4-SP-D16: "-target-feature" "+vfp4"
@@ -121,6 +184,10 @@
// RUN: | FileCheck --check-prefix=CHECK-FP5-SP-D16 %s
// RUN: %clang -target arm-linux-eabi -mfpu=fpv5-sp-d16 %s -### -o %t.o 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-FP5-SP-D16 %s
+// RUN: %clang -target arm-linux-eabi -mfpu=fp-armv8-sp-d16 -mfloat-abi=soft %s -### -o %t.o \
+// RUN: 2>&1 | FileCheck --check-prefix=CHECK-SOFT-ABI-FP %s
+// CHECK-FP5-SP-D16-NOT: "-target-feature" "+soft-float"
+// CHECK-FP5-SP-D16: "-target-feature" "+soft-float-abi"
// CHECK-FP5-SP-D16: "-target-feature" "+fp-only-sp"
// CHECK-FP5-SP-D16: "-target-feature" "+d16"
// CHECK-FP5-SP-D16: "-target-feature" "+fp-armv8"
@@ -131,18 +198,44 @@
// RUN: | FileCheck --check-prefix=CHECK-FP5-DP-D16 %s
// RUN: %clang -target arm-linux-eabi -mfpu=fpv5-dp-d16 %s -### -o %t.o 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-FP5-DP-D16 %s
+// RUN: %clang -target arm-linux-eabi -mfpu=fpv5-dp-d16 %s -mfloat-abi=soft -### -o %t.o 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-SOFT-ABI-FP-5 %s
+// CHECK-FP5-DP-D16-NOT: "-target-feature" "+soft-float"
+// CHECK-FP5-DP-D16: "-target-feature" "+soft-float-abi"
// CHECK-FP5-DP-D16: "-target-feature" "-fp-only-sp"
// CHECK-FP5-DP-D16: "-target-feature" "+d16"
// CHECK-FP5-DP-D16: "-target-feature" "+fp-armv8"
// CHECK-FP5-DP-D16: "-target-feature" "-neon"
// CHECK-FP5-DP-D16: "-target-feature" "-crypto"
+// CHECK-SOFT-ABI-FP-5: "-target-feature" "+soft-float"
+// CHECK-SOFT-ABI-FP-5: "-target-feature" "+soft-float-abi"
+// CHECK-SOFT-ABI-FP-5: "-target-feature" "-vfp2"
+// CHECK-SOFT-ABI-FP-5: "-target-feature" "-vfp3"
+// CHECK-SOFT-ABI-FP-5: "-target-feature" "-vfp4"
+// CHECK-SOFT-ABI-FP-5: "-target-feature" "-neon"
+// CHECK-SOFT-ABI-FP-5: "-target-feature" "-crypto"
+// CHECK-SOFT-ABI-FP-5: "-target-feature" "-fp-armv8"
// RUN: %clang -target arm-linux-eabi -mfpu=neon %s -### -o %t.o 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NEON %s
+// RUN: %clang -target arm-linux-eabi -mfpu=neon -mfloat-abi=soft %s -### -o %t.o 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-SOFT-ABI-FP-6 %s
+// CHECK-NEON-NOT: "-target-feature" "+soft-float"
// CHECK-NEON: "-target-feature" "+neon"
+// CHECK-SOFT-ABI-FP-6: "-target-feature" "+soft-float-abi"
+// CHECK-SOFT-ABI-FP-6: "-target-feature" "-vfp2"
+// CHECK-SOFT-ABI-FP-6: "-target-feature" "-vfp4"
+// CHECK-SOFT-ABI-FP-6: "-target-feature" "-fp-armv8"
+// CHECK-SOFT-ABI-FP-6: "-target-feature" "-crypto"
+// CHECK-SOFT-ABI-FP-6: "-target-feature" "-vfp3"
+// CHECK-SOFT-ABI-FP-6: "-target-feature" "-neon"
// RUN: %clang -target arm-linux-eabi -mfpu=neon-fp16 %s -### -o %t.o 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NEON-FP16 %s
+// RUN: %clang -target arm-linux-eabi -mfpu=neon-fp16 -mfloat-abi=soft %s -### -o %t.o 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-SOFT-ABI-FP-6 %s
+// CHECK-NEON-FP16-NOT: "-target-feature" "+soft-float"
+// CHECK-NEON-FP16: "-target-feature" "+soft-float-abi"
// CHECK-NEON-FP16: "-target-feature" "-fp-only-sp"
// CHECK-NEON-FP16: "-target-feature" "-d16"
// CHECK-NEON-FP16: "-target-feature" "+vfp3"
@@ -154,48 +247,78 @@
// RUN: %clang -target arm-linux-eabi -mfpu=neon-vfpv3 %s -### -o %t.o 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NEON-VFPV3 %s
+// RUN: %clang -target arm-linux-eabi -mfpu=neon-vfpv3 -mfloat-abi=soft %s -### -o %t.o 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-SOFT-ABI-FP-6 %s
+// CHECK-NEON-VFPV3-NOT: "-target-feature" "+soft-float"
+// CHECK-NEON-VFPV3: "-target-feature" "+soft-float-abi"
+// CHECK-NEON-VFPV3: "-target-feature" "+vfp3"
// CHECK-NEON-VFPV3: "-target-feature" "+neon"
// RUN: %clang -target arm-linux-eabi -mfpu=neon-vfpv4 %s -### -o %t.o 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NEON-VFPV4 %s
+// RUN: %clang -target arm-linux-eabi -mfpu=neon-vfpv4 -mfloat-abi=soft %s -### -o %t.o 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-SOFT-ABI-FP-7 %s
+// CHECK-NEON-VFPV4-NOT: "-target-feature" "+soft-float"
+// CHECK-NEON-VFPV4: "-target-feature" "+soft-float-abi"
// CHECK-NEON-VFPV4: "-target-feature" "+vfp4"
// CHECK-NEON-VFPV4: "-target-feature" "+neon"
+// CHECK-SOFT-ABI-FP-7: "-target-feature" "+soft-float-abi"
+// CHECK-SOFT-ABI-FP-7: "-target-feature" "-vfp2"
+// CHECK-SOFT-ABI-FP-7: "-target-feature" "-vfp3"
+// CHECK-SOFT-ABI-FP-7: "-target-feature" "-fp-armv8"
+// CHECK-SOFT-ABI-FP-7: "-target-feature" "-crypto"
+// CHECK-SOFT-ABI-FP-7: "-target-feature" "-vfp4"
+// CHECK-SOFT-ABI-FP-7: "-target-feature" "-neon"
// RUN: %clang -target arm-linux-eabi -msoft-float %s -### -o %t.o 2>&1 \
-// RUN: | FileCheck --check-prefix=CHECK-SOFT-FLOAT %s
-// CHECK-SOFT-FLOAT: "-target-feature" "-neon"
-
+// RUN: | FileCheck --check-prefix=CHECK-SOFT-ABI-FP %s
// RUN: %clang -target armv8 %s -### 2>&1 \
-// RUN: | FileCheck --check-prefix=CHECK-ARMV8-DEFAULT-SOFT-FP %s
-// CHECK-ARMV8-DEFAULT-SOFT-FP: "-target-feature" "-neon"
-// CHECK-ARMV8-DEFAULT-SOFT-FP: "-target-feature" "-crypto"
+// RUN: | FileCheck --check-prefix=CHECK-SOFT-ABI-FP %s
+// RUN: %clang -target armv8a -mfpu=neon %s -### -c 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-SOFT-ABI-FP-8 %s
+// CHECK-SOFT-ABI-FP-8: "-target-feature" "+soft-float-abi"
+// CHECK-SOFT-ABI-FP-8: "-target-feature" "-vfp2"
+// CHECK-SOFT-ABI-FP-8: "-target-feature" "-vfp4"
+// CHECK-SOFT-ABI-FP-8: "-target-feature" "-fp-armv8"
+// CHECK-SOFT-ABI-FP-8: "-target-feature" "-crypto"
+// CHECK-SOFT-ABI-FP-8: "-target-feature" "-vfp3"
+// CHECK-SOFT-ABI-FP-8: "-target-feature" "-neon"
// RUN: %clang -target armv8 -mfpu=fp-armv8 %s -### 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-ARMV8-SOFT-FLOAT %s
-// CHECK-ARMV8-SOFT-FLOAT: "-target-feature" "+fp-armv8"
-// CHECK-ARMV8-SOFT-FLOAT: "-target-feature" "-neon"
+// CHECK-ARMV8-SOFT-FLOAT: "-target-feature" "+soft-float"
+// CHECK-ARMV8-SOFT-FLOAT: "-target-feature" "+soft-float-abi"
+// NOT-CHECK-ARMV8-SOFT-FLOAT: "-target-feature" "+fp-armv8"
+// CHECK-ARMV9-SOFT-FLOAT: "-target-feature" "-neon"
// CHECK-ARMV8-SOFT-FLOAT: "-target-feature" "-crypto"
// RUN: %clang -target armv8-linux-gnueabihf -mfpu=fp-armv8 %s -### 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-FP-ARMV8 %s
-// CHECK-FP-ARMV8-NOT: "-target-feature" "+neon"
+// CHECK-FP-ARMV8-NOT: "-target-feature" "+soft-float"
+// CHECK-FP-ARMV8-NOT: "-target-feature" "+soft-float-abi"
// CHECK-FP-ARMV8: "-target-feature" "+fp-armv8"
// CHECK-FP-ARMV8: "-target-feature" "-neon"
// CHECK-FP-ARMV8: "-target-feature" "-crypto"
// RUN: %clang -target armv8-linux-gnueabihf -mfpu=neon-fp-armv8 %s -### 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NEON-FP-ARMV8 %s
+// CHECK-NEON-FP-ARMV8-NOT: "-target-feature" "+soft-float"
+// CHECK-NEON-FP-ARMV8-NOT: "-target-feature" "+soft-float-abi"
// CHECK-NEON-FP-ARMV8: "-target-feature" "+fp-armv8"
// CHECK-NEON-FP-ARMV8: "-target-feature" "+neon"
// CHECK-NEON-FP-ARMV8: "-target-feature" "-crypto"
// RUN: %clang -target armv8-linux-gnueabihf -mfpu=crypto-neon-fp-armv8 %s -### 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-CRYPTO-NEON-FP-ARMV8 %s
+// CHECK-CRYPTO-NEON-FP-ARMV8-NOT: "-target-feature" "+soft-float"
+// CHECK-CRYPTO-NEON-FP-ARMV8-NOT: "-target-feature" "+soft-float-abi"
// CHECK-CRYPTO-NEON-FP-ARMV8: "-target-feature" "+fp-armv8"
// CHECK-CRYPTO-NEON-FP-ARMV8: "-target-feature" "+crypto"
// RUN: %clang -target armv8-linux-gnueabi -mfpu=none %s -### 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NO-FP %s
+// CHECK-NO-FP-NOT: "-target-feature" "+soft-float"
+// CHECK-NO-FP: "-target-feature" "+soft-float-abi"
// CHECK-NO-FP: "-target-feature" "-fp-only-sp"
// CHECK-NO-FP: "-target-feature" "-d16"
// CHECK-NO-FP: "-target-feature" "-vfp2"
@@ -209,8 +332,35 @@
// RUN: | FileCheck --check-prefix=CHECK-HF %s
// RUN: %clang -target arm-linux-musleabihf %s -### 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-HF %s
+// CHECK-HF-NOT: "-target-feature" "+soft-float"
+// CHECK-HF-NOT: "-target-feature" "+soft-float-abi"
// CHECK-HF: "-target-cpu" "arm1176jzf-s"
// RUN: %clang -target armv7-apple-darwin -x assembler %s -### -c 2>&1 \
// RUN: | FileCheck --check-prefix=ASM %s
// ASM-NOT: -target-feature
+
+// RUN: %clang -target armv8-linux-gnueabi -mfloat-abi=soft -mfpu=none %s -### -c 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-SOFT-ABI-FP %s
+// RUN: %clang -target armv7-linux-gnueabi -mfloat-abi=soft -mfpu=none %s -### -c 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-SOFT-ABI-FP %s
+// RUN: %clang -target armv6-linux-gnueabi -mfloat-abi=soft -mfpu=none %s -### -c 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-SOFT-ABI-FP %s
+// RUN: %clang -target armv5-linux-gnueabi -mfloat-abi=soft -mfpu=none %s -### -c 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-SOFT-ABI-FP %s
+// RUN: %clang -target armv4-linux-gnueabi -mfloat-abi=soft -mfpu=none %s -### -c 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-SOFT-ABI-FP %s
+// RUN: %clang -target armv8-linux-gnueabi -msoft-float -mfpu=none %s -### -c 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-SOFT-ABI-FP %s
+// RUN: %clang -target armv8-linux-gnueabi -mfloat-abi=soft %s -### -c 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-SOFT-ABI-FP %s
+// RUN: %clang -target armv8-linux-gnueabi -msoft-float %s -### -c 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-SOFT-ABI-FP %s
+// CHECK-SOFT-ABI-FP: "-target-feature" "+soft-float"
+// CHECK-SOFT-ABI-FP: "-target-feature" "+soft-float-abi"
+// CHECK-SOFT-ABI-FP: "-target-feature" "-vfp2"
+// CHECK-SOFT-ABI-FP: "-target-feature" "-vfp3"
+// CHECK-SOFT-ABI-FP: "-target-feature" "-vfp4"
+// CHECK-SOFT-ABI-FP: "-target-feature" "-fp-armv8"
+// CHECK-SOFT-ABI-FP: "-target-feature" "-neon"
+// CHECK-SOFT-ABI-FP: "-target-feature" "-crypto"
diff --git a/test/Driver/arm-restrict-it.c b/test/Driver/arm-restrict-it.c
index c2a776046b68..5e695199e389 100644
--- a/test/Driver/arm-restrict-it.c
+++ b/test/Driver/arm-restrict-it.c
@@ -4,7 +4,7 @@
// RUN: %clang -target armv8a-none-gnueabi -mrestrict-it -### %s 2> %t
// RUN: FileCheck --check-prefix=CHECK-RESTRICTED < %t %s
-// CHECK-RESTRICTED: "-backend-option" "-arm-restrict-it"
+// CHECK-RESTRICTED: "-mllvm" "-arm-restrict-it"
// RUN: %clang -target arm-none-gnueabi -mno-restrict-it -### %s 2> %t
// RUN: FileCheck --check-prefix=CHECK-NO-RESTRICTED < %t %s
@@ -12,4 +12,4 @@
// RUN: %clang -target armv8a-none-gnueabi -mno-restrict-it -### %s 2> %t
// RUN: FileCheck --check-prefix=CHECK-NO-RESTRICTED < %t %s
-// CHECK-NO-RESTRICTED: "-backend-option" "-arm-no-restrict-it"
+// CHECK-NO-RESTRICTED: "-mllvm" "-arm-no-restrict-it"
diff --git a/test/Driver/asan.c b/test/Driver/asan.c
index 288666d1ca7b..db1c042a4f70 100644
--- a/test/Driver/asan.c
+++ b/test/Driver/asan.c
@@ -10,9 +10,14 @@
// RUN: %clang -O1 -target aarch64-unknown-linux -fsanitize=hwaddress %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-HWASAN
// RUN: %clang -O2 -target aarch64-unknown-linux -fsanitize=hwaddress %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-HWASAN
// RUN: %clang -O3 -target aarch64-unknown-linux -fsanitize=hwaddress %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-HWASAN
-// Verify that -fsanitize={address,kernel-address} invoke ASan and KASan instrumentation.
+// RUN: %clang -target aarch64-unknown-linux -fsanitize=kernel-hwaddress %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-KHWASAN
+// RUN: %clang -O1 -target aarch64-unknown-linux -fsanitize=kernel-hwaddress %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-KHWASAN
+// RUN: %clang -O2 -target aarch64-unknown-linux -fsanitize=kernel-hwaddress %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-KHWASAN
+// RUN: %clang -O3 -target aarch64-unknown-linux -fsanitize=kernel-hwaddress %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-KHWASAN
+// Verify that -fsanitize={address,hwaddres,kernel-address,kernel-hwaddress} invokes ASan, HWAsan, KASan or KHWASan instrumentation.
int foo(int *a) { return *a; }
// CHECK-ASAN: __asan_init
// CHECK-KASAN: __asan_load4_noabort
// CHECK-HWASAN: __hwasan_init
+// CHECK-KHWASAN: __hwasan_load4_noabort
diff --git a/test/Driver/autocomplete.c b/test/Driver/autocomplete.c
index 8b6d6cfc89c2..16f2edf03452 100644
--- a/test/Driver/autocomplete.c
+++ b/test/Driver/autocomplete.c
@@ -3,13 +3,8 @@
// add/modify flags, change HelpTexts or the values of some flags.
// Some corner cases.
-// RUN: %clang --autocomplete= | FileCheck %s -check-prefix=ALL_FLAGS
-// RUN: %clang --autocomplete=# | FileCheck %s -check-prefix=ALL_FLAGS
-// Let's pick some example flags that are hopefully unlikely to change.
-// ALL_FLAGS: -fast
-// ALL_FLAGS: -fastcp
-// ALL_FLAGS: -fastf
// Just test that this doesn't crash:
+// RUN: %clang --autocomplete=
// RUN: %clang --autocomplete=,
// RUN: %clang --autocomplete==
// RUN: %clang --autocomplete=,,
@@ -17,28 +12,29 @@
// RUN: %clang --autocomplete=-fsyn | FileCheck %s -check-prefix=FSYN
// FSYN: -fsyntax-only
-// RUN: %clang --autocomplete=-std= | FileCheck %s -check-prefix=STD
+// RUN: %clang --autocomplete=-std | FileCheck %s -check-prefix=STD
// STD: -std= Language standard to compile for
// RUN: %clang --autocomplete=foo | FileCheck %s -check-prefix=FOO
// FOO-NOT: foo
// RUN: %clang --autocomplete=-stdlib=,l | FileCheck %s -check-prefix=STDLIB
// STDLIB: libc++
// STDLIB-NEXT: libstdc++
-// RUN: %clang --autocomplete=-stdlib=, | FileCheck %s -check-prefix=STDLIBALL
+// RUN: %clang --autocomplete=-stdlib= | FileCheck %s -check-prefix=STDLIBALL
// STDLIBALL: libc++
// STDLIBALL-NEXT: libstdc++
// STDLIBALL-NEXT: platform
// RUN: %clang --autocomplete=-meabi,d | FileCheck %s -check-prefix=MEABI
// MEABI: default
-// RUN: %clang --autocomplete=-meabi, | FileCheck %s -check-prefix=MEABIALL
+// RUN: %clang --autocomplete=-meabi | FileCheck %s -check-prefix=MEABIALL
// MEABIALL: 4
// MEABIALL-NEXT: 5
// MEABIALL-NEXT: default
// MEABIALL-NEXT: gnu
// RUN: %clang --autocomplete=-cl-std=,CL2 | FileCheck %s -check-prefix=CLSTD
// CLSTD: CL2.0
-// RUN: %clang --autocomplete=-cl-std=, | FileCheck %s -check-prefix=CLSTDALL
-// CLSTDALL: cl
+// RUN: %clang --autocomplete=-cl-std= | FileCheck %s -check-prefix=CLSTDALL
+// CLSTDALL: c++
+// CLSTDALL-NEXT: cl
// CLSTDALL-NEXT: CL
// CLSTDALL-NEXT: cl1.1
// CLSTDALL-NEXT: CL1.1
@@ -48,7 +44,7 @@
// CLSTDALL-NEXT: CL2.0
// RUN: %clang --autocomplete=-fno-sanitize-coverage=,f | FileCheck %s -check-prefix=FNOSANICOVER
// FNOSANICOVER: func
-// RUN: %clang --autocomplete=-fno-sanitize-coverage=, | FileCheck %s -check-prefix=FNOSANICOVERALL
+// RUN: %clang --autocomplete=-fno-sanitize-coverage= | FileCheck %s -check-prefix=FNOSANICOVERALL
// FNOSANICOVERALL: 8bit-counters
// FNOSANICOVERALL-NEXT: bb
// FNOSANICOVERALL-NEXT: edge
@@ -62,41 +58,37 @@
// FNOSANICOVERALL-NEXT: trace-gep
// FNOSANICOVERALL-NEXT: trace-pc
// FNOSANICOVERALL-NEXT: trace-pc-guard
-// RUN: %clang --autocomplete=-ffp-contract=, | FileCheck %s -check-prefix=FFPALL
+// RUN: %clang --autocomplete=-ffp-contract= | FileCheck %s -check-prefix=FFPALL
// FFPALL: fast
// FFPALL-NEXT: off
// FFPALL-NEXT: on
-// RUN: %clang --autocomplete=-flto=, | FileCheck %s -check-prefix=FLTOALL
+// RUN: %clang --autocomplete=-flto= | FileCheck %s -check-prefix=FLTOALL
// FLTOALL: full
// FLTOALL-NEXT: thin
-// RUN: %clang --autocomplete=-fveclib=, | FileCheck %s -check-prefix=FVECLIBALL
+// RUN: %clang --autocomplete=-fveclib= | FileCheck %s -check-prefix=FVECLIBALL
// FVECLIBALL: Accelerate
// FVECLIBALL-NEXT: none
// FVECLIBALL-NEXT: SVML
-// RUN: %clang --autocomplete=-fshow-overloads=, | FileCheck %s -check-prefix=FSOVERALL
+// RUN: %clang --autocomplete=-fshow-overloads= | FileCheck %s -check-prefix=FSOVERALL
// FSOVERALL: all
// FSOVERALL-NEXT: best
-// RUN: %clang --autocomplete=-fvisibility=, | FileCheck %s -check-prefix=FVISIBILITYALL
+// RUN: %clang --autocomplete=-fvisibility= | FileCheck %s -check-prefix=FVISIBILITYALL
// FVISIBILITYALL: default
// FVISIBILITYALL-NEXT: hidden
-// RUN: %clang --autocomplete=-mfloat-abi=, | FileCheck %s -check-prefix=MFLOATABIALL
+// RUN: %clang --autocomplete=-mfloat-abi= | FileCheck %s -check-prefix=MFLOATABIALL
// MFLOATABIALL: hard
// MFLOATABIALL-NEXT: soft
// MFLOATABIALL-NEXT: softfp
-// RUN: %clang --autocomplete=-mthread-model, | FileCheck %s -check-prefix=MTHREADMODELALL
+// RUN: %clang --autocomplete=-mthread-model | FileCheck %s -check-prefix=MTHREADMODELALL
// MTHREADMODELALL: posix
// MTHREADMODELALL-NEXT: single
-// RUN: %clang --autocomplete=-mrelocation-model, | FileCheck %s -check-prefix=MRELOCMODELALL
+// RUN: %clang --autocomplete=-mrelocation-model | FileCheck %s -check-prefix=MRELOCMODELALL
// MRELOCMODELALL: dynamic-no-pic
// MRELOCMODELALL-NEXT: pic
// MRELOCMODELALL-NEXT: ropi
// MRELOCMODELALL-NEXT: ropi-rwpi
// MRELOCMODELALL-NEXT: rwpi
// MRELOCMODELALL-NEXT: static
-// RUN: %clang --autocomplete=-mrelocation-mode | FileCheck %s -check-prefix=MRELOCMODEL_CLANG
-// MRELOCMODEL_CLANG-NOT: -mrelocation-model
-// RUN: %clang --autocomplete=#-mrelocation-mode | FileCheck %s -check-prefix=MRELOCMODEL_CC1
-// MRELOCMODEL_CC1: -mrelocation-model
// RUN: %clang --autocomplete=-Wma | FileCheck %s -check-prefix=WARNING
// WARNING: -Wmacro-redefined
// WARNING-NEXT: -Wmain
@@ -106,7 +98,20 @@
// WARNING-NEXT: -Wmax-unsigned-zero
// RUN: %clang --autocomplete=-Wno-invalid-pp- | FileCheck %s -check-prefix=NOWARNING
// NOWARNING: -Wno-invalid-pp-token
-// RUN: %clang --autocomplete=-analyzer-checker, | FileCheck %s -check-prefix=ANALYZER
+// RUN: %clang --autocomplete=-analyzer-checker | FileCheck %s -check-prefix=ANALYZER
// ANALYZER: unix.Malloc
-// RUN: %clang --autocomplete=-std=, | FileCheck %s -check-prefix=STDVAL
+// RUN: %clang --autocomplete=-std= | FileCheck %s -check-prefix=STDVAL
// STDVAL: c99
+//
+// Clang shouldn't autocomplete CC1 options unless -cc1 or -Xclang were provided
+// RUN: %clang --autocomplete=-mrelocation-mode | FileCheck %s -check-prefix=MRELOCMODEL_CLANG
+// MRELOCMODEL_CLANG-NOT: -mrelocation-model
+// RUN: %clang --autocomplete=-Xclang,-mrelocation-mode | FileCheck %s -check-prefix=MRELOCMODEL_CC1
+// RUN: %clang --autocomplete=-cc1,-mrelocation-mode | FileCheck %s -check-prefix=MRELOCMODEL_CC1
+// MRELOCMODEL_CC1: -mrelocation-model
+// Make sure it ignores passed flags unlesss they are -Xclang or -cc1
+// RUN: %clang --autocomplete=foo,bar,,-fsyn | FileCheck %s -check-prefix=FSYN-CORON
+// FSYN-CORON: -fsyntax-only
+// Check if they can autocomplete values with coron
+// RUN: %clang --autocomplete=foo,bar,,,-fno-sanitize-coverage=,f | FileCheck %s -check-prefix=FNOSANICOVER-CORON
+// FNOSANICOVER-CORON: func
diff --git a/test/Driver/cl-include.c b/test/Driver/cl-include.c
index d3dc006e575f..a69265deed02 100644
--- a/test/Driver/cl-include.c
+++ b/test/Driver/cl-include.c
@@ -10,5 +10,16 @@
// RUN: env INCLUDE=/my/system/inc %clang_cl -### -- %s 2>&1 | FileCheck %s --check-prefix=STDINC
// STDINC: "-internal-isystem" "/my/system/inc"
-// RUN: env INCLUDE=/my/system/inc %clang_cl -nostdinc -### -- %s 2>&1 | FileCheck %s --check-prefix=NOSTDINC
+// -nostdinc suppresses all of %INCLUDE%, clang resource dirs, and -imsvc dirs.
+// RUN: env INCLUDE=/my/system/inc %clang_cl -nostdinc -imsvc /my/other/inc -### -- %s 2>&1 | FileCheck %s --check-prefix=NOSTDINC
+// NOSTDINC: argument unused{{.*}}-imsvc
// NOSTDINC-NOT: "-internal-isystem" "/my/system/inc"
+// NOSTDINC-NOT: "-internal-isystem" "{{.*lib.*clang.*include}}"
+// NOSTDINC-NOT: "-internal-isystem" "/my/other/inc"
+
+// /X suppresses %INCLUDE% but not clang resource dirs or -imsvc dirs.
+// RUN: env INCLUDE=/my/system/inc %clang_cl /X -imsvc /my/other/inc -### -- %s 2>&1 | FileCheck %s --check-prefix=SLASHX
+// SLASHX-NOT: "argument unused{{.*}}-imsvc"
+// SLASHX-NOT: "-internal-isystem" "/my/system/inc"
+// SLASHX: "-internal-isystem" "{{.*lib.*clang.*include}}"
+// SLASHX: "-internal-isystem" "/my/other/inc"
diff --git a/test/Driver/cl-options.c b/test/Driver/cl-options.c
index b8a0166e7ad3..9aa6ced34994 100644
--- a/test/Driver/cl-options.c
+++ b/test/Driver/cl-options.c
@@ -198,10 +198,8 @@
// RUN: %clang_cl /E /showIncludes -### -- %s 2>&1 | FileCheck -check-prefix=showIncludes_E %s
// RUN: %clang_cl /EP /showIncludes -### -- %s 2>&1 | FileCheck -check-prefix=showIncludes_E %s
// RUN: %clang_cl /E /EP /showIncludes -### -- %s 2>&1 | FileCheck -check-prefix=showIncludes_E %s
-// showIncludes_E: warning: argument unused during compilation: '--show-includes'
-
-// RUN: %clang_cl /EP /P /showIncludes -### -- %s 2>&1 | FileCheck -check-prefix=showIncludes_E_And_P %s
-// showIncludes_E_And_P-NOT: warning: argument unused during compilation: '--show-includes'
+// RUN: %clang_cl /EP /P /showIncludes -### -- %s 2>&1 | FileCheck -check-prefix=showIncludes_E %s
+// showIncludes_E-NOT: warning: argument unused during compilation: '--show-includes'
// /source-charset: should warn on everything except UTF-8.
// RUN: %clang_cl /source-charset:utf-16 -### -- %s 2>&1 | FileCheck -check-prefix=source-charset-utf-16 %s
@@ -293,6 +291,9 @@
// RUN: %clang_cl /TP /c /GX /GX- -### -- %s 2>&1 | FileCheck -check-prefix=GX_ %s
// GX_-NOT: "-fcxx-exceptions" "-fexceptions"
+// RUN: %clang_cl /d1PP -### -- %s 2>&1 | FileCheck -check-prefix=d1PP %s
+// d1PP: -dD
+
// We forward any unrecognized -W diagnostic options to cc1.
// RUN: %clang_cl -Wunused-pragmas -### -- %s 2>&1 | FileCheck -check-prefix=WJoined %s
// WJoined: "-cc1"
@@ -343,7 +344,9 @@
// RUN: /GS- \
// RUN: /kernel- \
// RUN: /nologo \
+// RUN: /Og \
// RUN: /openmp- \
+// RUN: /permissive- \
// RUN: /RTC1 \
// RUN: /sdl \
// RUN: /sdl- \
@@ -353,6 +356,14 @@
// RUN: /volatile:iso \
// RUN: /w12345 \
// RUN: /wd1234 \
+// RUN: /Zc:__cplusplus \
+// RUN: /Zc:auto \
+// RUN: /Zc:forScope \
+// RUN: /Zc:inline \
+// RUN: /Zc:rvalueCast \
+// RUN: /Zc:ternary \
+// RUN: /Zc:wchar_t \
+// RUN: /Zm \
// RUN: /Zo \
// RUN: /Zo- \
// RUN: -### -- %s 2>&1 | FileCheck -check-prefix=IGNORED %s
@@ -376,6 +387,8 @@
// (/Zs is for syntax-only)
// RUN: %clang_cl /Zs \
// RUN: /AIfoo \
+// RUN: /Bt \
+// RUN: /Bt+ \
// RUN: /clr:pure \
// RUN: /docname \
// RUN: /EHsc \
@@ -552,8 +565,15 @@
// (/Zs is for syntax-only, -Werror makes it fail hard on unknown options)
// RUN: %clang_cl \
// RUN: --driver-mode=cl \
+// RUN: -fblocks \
+// RUN: -fno-blocks \
+// RUN: -fbuiltin \
+// RUN: -fno-builtin \
+// RUN: -fno-builtin-strcpy \
// RUN: -fcolor-diagnostics \
// RUN: -fno-color-diagnostics \
+// RUN: -fcoverage-mapping \
+// RUN: -fno-coverage-mapping \
// RUN: -fdiagnostics-color \
// RUN: -fno-diagnostics-color \
// RUN: -fdiagnostics-parseable-fixits \
@@ -575,6 +595,8 @@
// RUN: -fstandalone-debug \
// RUN: -flimit-debug-info \
// RUN: -flto \
+// RUN: -fmerge-all-constants \
+// RUN: -no-canonical-prefixes \
// RUN: --version \
// RUN: -Werror /Zs -- %s 2>&1
diff --git a/test/Driver/cl-pch-search.cpp b/test/Driver/cl-pch-search.cpp
index ca62668ef13b..3ba4a11753a2 100644
--- a/test/Driver/cl-pch-search.cpp
+++ b/test/Driver/cl-pch-search.cpp
@@ -2,5 +2,5 @@
// command-line option, e.g. on Mac where %s is commonly under /Users.
// REQUIRES: x86-registered-target
-// Check that pchfile.h next to to pchfile.cc is found correctly.
-// RUN: %clang_cl -Werror --target=x86_64 /Ycpchfile.h /FIpchfile.h /c /Fo%t.obj /Fp%t.pch -- %S/Inputs/pchfile.cpp
+// Check that pchfile.h next to pchfile.cc is found correctly.
+// RUN: %clang_cl -Werror -Wno-microsoft-include --target=x86_64-windows /Ycpchfile.h /FIpchfile.h /c /Fo%t.obj /Fp%t.pch -- %S/Inputs/pchfile.cpp
diff --git a/test/Driver/cl-pch-showincludes.cpp b/test/Driver/cl-pch-showincludes.cpp
index 7e0e1097361d..75a634bc125c 100644
--- a/test/Driver/cl-pch-showincludes.cpp
+++ b/test/Driver/cl-pch-showincludes.cpp
@@ -8,14 +8,14 @@
// When building the pch, header1.h (included by header2.h), header2.h (the pch
// input itself) and header3.h (included directly, above) should be printed.
-// RUN: %clang_cl -Werror --target=x86_64 /showIncludes /I%S/Inputs /Ycheader2.h /FIheader2.h /Fp%t.pch /c /Fo%t -- %s \
+// RUN: %clang_cl -Werror --target=x86_64-windows /showIncludes /I%S/Inputs /Ycheader2.h /FIheader2.h /Fp%t.pch /c /Fo%t -- %s \
// RUN: | FileCheck --strict-whitespace -check-prefix=CHECK-YC %s
// CHECK-YC: Note: including file: {{[^ ]*header2.h}}
// CHECK-YC: Note: including file: {{[^ ]*header1.h}}
// CHECK-YC: Note: including file: {{[^ ]*header3.h}}
// When using the pch, only the direct include is printed.
-// RUN: %clang_cl -Werror --target=x86_64 /showIncludes /I%S/Inputs /Yuheader2.h /FIheader2.h /Fp%t.pch /c /Fo%t -- %s \
+// RUN: %clang_cl -Werror --target=x86_64-windows /showIncludes /I%S/Inputs /Yuheader2.h /FIheader2.h /Fp%t.pch /c /Fo%t -- %s \
// RUN: | FileCheck --strict-whitespace -check-prefix=CHECK-YU %s
// CHECK-YU-NOT: Note: including file: {{.*pch}}
// CHECK-YU-NOT: Note: including file: {{.*header1.h}}
@@ -23,7 +23,7 @@
// CHECK-YU: Note: including file: {{[^ ]*header3.h}}
// When not using pch at all, all the /FI files are printed.
-// RUN: %clang_cl -Werror --target=x86_64 /showIncludes /I%S/Inputs /FIheader2.h /c /Fo%t -- %s \
+// RUN: %clang_cl -Werror --target=x86_64-windows /showIncludes /I%S/Inputs /FIheader2.h /c /Fo%t -- %s \
// RUN: | FileCheck --strict-whitespace -check-prefix=CHECK-FI %s
// CHECK-FI: Note: including file: {{[^ ]*header2.h}}
// CHECK-FI: Note: including file: {{[^ ]*header1.h}}
@@ -32,7 +32,7 @@
// Also check that /FI arguments before the /Yc / /Yu flags are printed right.
// /FI flags before the /Yc arg should be printed, /FI flags after it shouldn't.
-// RUN: %clang_cl -Werror --target=x86_64 /showIncludes /I%S/Inputs /Ycheader2.h /FIheader0.h /FIheader2.h /FIheader4.h /Fp%t.pch /c /Fo%t -- %s \
+// RUN: %clang_cl -Werror --target=x86_64-windows /showIncludes /I%S/Inputs /Ycheader2.h /FIheader0.h /FIheader2.h /FIheader4.h /Fp%t.pch /c /Fo%t -- %s \
// RUN: | FileCheck --strict-whitespace -check-prefix=CHECK-YCFI %s
// CHECK-YCFI: Note: including file: {{[^ ]*header0.h}}
// CHECK-YCFI: Note: including file: {{[^ ]*header2.h}}
@@ -40,7 +40,7 @@
// CHECK-YCFI: Note: including file: {{[^ ]*header4.h}}
// CHECK-YCFI: Note: including file: {{[^ ]*header3.h}}
-// RUN: %clang_cl -Werror --target=x86_64 /showIncludes /I%S/Inputs /Yuheader2.h /FIheader0.h /FIheader2.h /FIheader4.h /Fp%t.pch /c /Fo%t -- %s \
+// RUN: %clang_cl -Werror --target=x86_64-windows /showIncludes /I%S/Inputs /Yuheader2.h /FIheader0.h /FIheader2.h /FIheader4.h /Fp%t.pch /c /Fo%t -- %s \
// RUN: | FileCheck --strict-whitespace -check-prefix=CHECK-YUFI %s
// CHECK-YUFI-NOT: Note: including file: {{.*pch}}
// CHECK-YUFI-NOT: Note: including file: {{.*header0.h}}
diff --git a/test/Driver/cl-pch.cpp b/test/Driver/cl-pch.cpp
index 2503c9737335..8521d3576a7b 100644
--- a/test/Driver/cl-pch.cpp
+++ b/test/Driver/cl-pch.cpp
@@ -7,6 +7,7 @@
// 1. Build .pch file.
// CHECK-YC: cc1
// CHECK-YC: -emit-pch
+// CHECK-YC: -building-pch-with-obj
// CHECK-YC: -o
// CHECK-YC: pchfile.pch
// CHECK-YC: -x
@@ -14,6 +15,7 @@
// 2. Use .pch file.
// CHECK-YC: cc1
// CHECK-YC: -emit-obj
+// CHECK-YC: -building-pch-with-obj
// CHECK-YC: -include-pch
// CHECK-YC: pchfile.pch
@@ -24,11 +26,13 @@
// 1. Build .pch file.
// CHECK-YCO: cc1
// CHECK-YCO: -emit-pch
+// CHECK-YCO: -building-pch-with-obj
// CHECK-YCO: -o
// CHECK-YCO: pchfile.pch
// 2. Use .pch file.
// CHECK-YCO: cc1
// CHECK-YCO: -emit-obj
+// CHECK-YCO: -building-pch-with-obj
// CHECK-YCO: -include-pch
// CHECK-YCO: pchfile.pch
// CHECK-YCO: -o
@@ -46,6 +50,7 @@
// RUN: | FileCheck -check-prefix=CHECK-YU %s
// Use .pch file, but don't build it.
// CHECK-YU-NOT: -emit-pch
+// CHECK-YU-NOT: -building-pch-with-obj
// CHECK-YU: cc1
// CHECK-YU: -emit-obj
// CHECK-YU: -include-pch
@@ -63,6 +68,7 @@
// 1. Build .pch file.
// CHECK-YC-YU: cc1
// CHECK-YC-YU: -emit-pch
+// CHECK-YC-YU: -building-pch-with-obj
// CHECK-YC-YU: -o
// CHECK-YC-YU: pchfile.pch
// 2. Use .pch file.
@@ -151,26 +157,37 @@
// 1. Build .pch file: Includes foo1.h (but NOT foo3.h) and compiles foo2.h
// CHECK-YCFIFIFI: cc1
// CHECK-YCFIFIFI: -emit-pch
+// CHECK-YCFIFIFI: -pch-through-header=foo2.h
// CHECK-YCFIFIFI: -include
// CHECK-YCFIFIFI: foo1.h
-// CHECK-YCFIFIFI-NOT: foo2.h
-// CHECK-YCFIFIFI-NOT: foo3.h
+// CHECK-YCFIFIFI: -include
+// CHECK-YCFIFIFI: foo2.h
+// CHECK-YCFIFIFI: -include
+// CHECK-YCFIFIFI: foo3.h
// CHECK-YCFIFIFI: -o
// CHECK-YCFIFIFI: foo2.pch
// CHECK-YCFIFIFI: -x
// CHECK-YCFIFIFI: "c++-header"
-// CHECK-YCFIFIFI: foo2.h
+// CHECK-YCFIFIFI: cl-pch.cpp
// 2. Use .pch file: Inlucdes foo2.pch and foo3.h
// CHECK-YCFIFIFI: cc1
// CHECK-YCFIFIFI: -emit-obj
-// CHECK-YCFIFIFI-NOT: foo1.h
-// CHECK-YCFIFIFI-NOT: foo2.h
// CHECK-YCFIFIFI: -include-pch
// CHECK-YCFIFIFI: foo2.pch
+// CHECK-YCFIFIFI: -pch-through-header=foo2.h
+// CHECK-YCFIFIFI: -include
+// CHECK-YCFIFIFI: foo1.h
+// CHECK-YCFIFIFI: -include
+// CHECK-YCFIFIFI: foo2.h
// CHECK-YCFIFIFI: -include
// CHECK-YCFIFIFI: foo3.h
+// CHECK-YCFIFIFI: -o
+// CHECK-YCFIFIFI: cl-pch.obj
+// CHECK-YCFIFIFI: -x
+// CHECK-YCFIFIFI: "c++"
+// CHECK-YCFIFIFI: cl-pch.cpp
-// /Yucfoo2.h /FIfoo1.h /FIfoo2.h /FIfoo3.h
+// /Yufoo2.h /FIfoo1.h /FIfoo2.h /FIfoo3.h
// => foo1 foo2 filtered out, foo3 into main compilation
// RUN: %clang_cl -Werror /Yufoo2.h /FIfoo1.h /FIfoo2.h /FIfoo3.h /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YUFIFIFI %s
@@ -178,38 +195,47 @@
// CHECK-YUFIFIFI-NOT: -emit-pch
// CHECK-YUFIFIFI: cc1
// CHECK-YUFIFIFI: -emit-obj
-// CHECK-YUFIFIFI-NOT: foo1.h
-// CHECK-YUFIFIFI-NOT: foo2.h
// CHECK-YUFIFIFI: -include-pch
// CHECK-YUFIFIFI: foo2.pch
+// CHECK-YUFIFIFI: -pch-through-header=foo2.h
+// CHECK-YUFIFIFI: -include
+// CHECK-YUFIFIFI: foo1.h
+// CHECK-YUFIFIFI: -include
+// CHECK-YUFIFIFI: foo2.h
// CHECK-YUFIFIFI: -include
// CHECK-YUFIFIFI: foo3.h
-// FIXME: Implement support for /Ycfoo.h / /Yufoo.h without /FIfoo.h
+// Test /Ycfoo.h / /Yufoo.h without /FIfoo.h
// RUN: %clang_cl -Werror /Ycfoo.h /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YC-NOFI %s
-// CHECK-YC-NOFI: error: support for '/Yc' without a corresponding /FI flag not implemented yet; flag ignored
+// 1. Precompile
+// CHECK-YC-NOFI: cc1
+// CHECK-YC-NOFI: -emit-pch
+// CHECK-YC-NOFI: -pch-through-header=foo.h
+// CHECK-YC-NOFI: -o
+// CHECK-YC-NOFI: foo.pch
+// CHECK-YC-NOFI: -x
+// CHECK-YC-NOFI: c++-header
+// CHECK-YC-NOFI: cl-pch.cpp
+// 2. Build PCH object
+// CHECK-YC-NOFI: cc1
+// CHECK-YC-NOFI: -emit-obj
+// CHECK-YC-NOFI: -include-pch
+// CHECK-YC-NOFI: foo.pch
+// CHECK-YC-NOFI: -pch-through-header=foo.h
+// CHECK-YC-NOFI: -x
+// CHECK-YC-NOFI: c++
+// CHECK-YC-NOFI: cl-pch.cpp
// RUN: %clang_cl -Werror /Yufoo.h /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YU-NOFI %s
-// CHECK-YU-NOFI: error: support for '/Yu' without a corresponding /FI flag not implemented yet; flag ignored
-
-// /Yc and /FI relative to /I paths...
-// The rules are:
-// Yu/Yc and FI parameter must match exactly, else it's not found
-// Must match literally exactly: /FI./foo.h /Ycfoo.h does _not_ work.
-// However, the path can be relative to /I paths.
-// FIXME: Update the error messages below once /FI is no longer required, but
-// these test cases all should stay failures as they fail with cl.exe.
-
-// Check that ./ isn't canonicalized away.
-// RUN: %clang_cl -Werror /Ycpchfile.h /FI./pchfile.h /c -### -- %s 2>&1 \
-// RUN: | FileCheck -check-prefix=CHECK-YC-I1 %s
-// CHECK-YC-I1: support for '/Yc' without a corresponding /FI flag not implemented yet; flag ignored
-
-// Check that ./ isn't canonicalized away.
-// RUN: %clang_cl -Werror /Yc./pchfile.h /FIpchfile.h /c -### -- %s 2>&1 \
-// RUN: | FileCheck -check-prefix=CHECK-YC-I2 %s
-// CHECK-YC-I2: support for '/Yc' without a corresponding /FI flag not implemented yet; flag ignored
+// CHECK-YU-NOFI: cc1
+// CHECK-YU-NOFI: -emit-obj
+// CHECK-YU-NOFI: -include-pch
+// CHECK-YU-NOFI: foo.pch
+// CHECK-YU-NOFI: -pch-through-header=foo.h
+// CHECK-YU-NOFI: -x
+// CHECK-YU-NOFI: c++
+// CHECK-YU-NOFI: cl-pch.cpp
// With an actual /I argument.
// RUN: %clang_cl -Werror /Ifoo /Ycpchfile.h /FIpchfile.h /c -### -- %s 2>&1 \
@@ -226,20 +252,17 @@
// CHECK-YC-I3: -include-pch
// CHECK-YC-I3: pchfile.pch
-// Check that ./ isn't canonicalized away for /Yu either.
-// RUN: %clang_cl -Werror /Yupchfile.h /FI./pchfile.h /c -### -- %s 2>&1 \
-// RUN: | FileCheck -check-prefix=CHECK-YU-I1 %s
-// CHECK-YU-I1: support for '/Yu' without a corresponding /FI flag not implemented yet; flag ignored
-
// But /FIfoo/bar.h /Ycfoo\bar.h does work, as does /FIfOo.h /Ycfoo.H
-// FIXME: This part isn't implemented yet. The following two tests should not
-// show an error but do regular /Yu handling.
// RUN: %clang_cl -Werror /YupchFILE.h /FI./pchfile.h /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YU-CASE %s
-// CHECK-YU-CASE: support for '/Yu' without a corresponding /FI flag not implemented yet; flag ignored
-// RUN: %clang_cl -Werror /Yu./pchfile.h /FI.\pchfile.h /c -### -- %s 2>&1 \
+// CHECK-YU-CASE: -pch-through-header=pchFILE.h
+// CHECK-YU-CASE: -include
+// CHECK-YU-CASE: "./pchfile.h"
+// RUN: %clang_cl -Werror /Yu./pchfile.h /FI.\\pchfile.h /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YU-SLASH %s
-// CHECK-YU-SLASH: support for '/Yu' without a corresponding /FI flag not implemented yet; flag ignored
+// CHECK-YU-SLASH: -pch-through-header=./pchfile.h
+// CHECK-YU-SLASH: -include
+// CHECK-YU-SLASH: ".{{[/\\]+}}pchfile.h"
// cl.exe warns on multiple /Yc, /Yu, /Fp arguments, but clang-cl silently just
// uses the last one. This is true for e.g. /Fo too, so not warning on this
diff --git a/test/Driver/cl-x86-flags.c b/test/Driver/cl-x86-flags.c
index 32cd072ec1ef..595959b48828 100644
--- a/test/Driver/cl-x86-flags.c
+++ b/test/Driver/cl-x86-flags.c
@@ -1,88 +1,132 @@
// REQUIRES: x86-registered-target
+// expected-no-diagnostics
+
// We support -m32 and -m64. We support all x86 CPU feature flags in gcc's -m
// flag space.
// RUN: %clang_cl /Zs /WX -m32 -m64 -msse3 -msse4.1 -mavx -mno-avx \
// RUN: --target=i386-pc-win32 -### -- 2>&1 %s | FileCheck -check-prefix=MFLAGS %s
// MFLAGS-NOT: argument unused during compilation
-// RUN: %clang_cl -m32 -arch:IA32 --target=i386 -### -- 2>&1 %s | FileCheck -check-prefix=IA32 %s
-// IA32: "-target-cpu" "i386"
-// IA32-NOT: -target-feature
-// IA32-NOT: argument unused during compilation
+// RUN: %clang_cl -m32 -arch:IA32 --target=i386-pc-windows /c /Fo%t.obj -Xclang -verify -DTEST_32_ARCH_IA32 -- %s
+#if defined(TEST_32_ARCH_IA32)
+#if _M_IX86_FP || __AVX__ || __AVX2__ || __AVX512F__ || __AVX512BW__
+#error fail
+#endif
+#endif
-// RUN: %clang_cl -m32 -arch:ia32 --target=i386 -### -- 2>&1 %s | FileCheck -check-prefix=ia32 %s
+// arch: args are case-sensitive.
+// RUN: %clang_cl -m32 -arch:ia32 --target=i386-pc-windows -### -- 2>&1 %s | FileCheck -check-prefix=ia32 %s
// ia32: argument unused during compilation
-// ia32-NOT: -target-feature
-// RUN: %clang_cl -m64 -arch:IA32 --target=x86_64 -### -- 2>&1 %s | FileCheck -check-prefix=IA3264 %s
+// RUN: %clang_cl -m64 -arch:IA32 --target=x86_64-pc-windows -### -- 2>&1 %s | FileCheck -check-prefix=IA3264 %s
// IA3264: argument unused during compilation
-// IA3264-NOT: -target-feature
-// RUN: %clang_cl -m32 -arch:SSE --target=i386 -### -- 2>&1 %s | FileCheck -check-prefix=SSE %s
-// SSE: "-target-cpu" "pentium3"
-// SSE: -target-feature
-// SSE: +sse
-// SSE-NOT: argument unused during compilation
+// RUN: %clang_cl -m32 -arch:SSE --target=i386-pc-windows /c /Fo%t.obj -Xclang -verify -DTEST_32_ARCH_SSE -- %s
+#if defined(TEST_32_ARCH_SSE)
+#if _M_IX86_FP != 1 || __AVX__ || __AVX2__ || __AVX512F__ || __AVX512BW__
+#error fail
+#endif
+#endif
-// RUN: %clang_cl -m32 -arch:sse --target=i386 -### -- 2>&1 %s | FileCheck -check-prefix=sse %s
+// RUN: %clang_cl -m32 -arch:sse --target=i386-pc-windows -### -- 2>&1 %s | FileCheck -check-prefix=sse %s
// sse: argument unused during compilation
-// sse-NOT: -target-feature
-// RUN: %clang_cl -m32 -arch:SSE2 --target=i386 -### -- 2>&1 %s | FileCheck -check-prefix=SSE2 %s
-// SSE2: "-target-cpu" "pentium4"
-// SSE2: -target-feature
-// SSE2: +sse2
-// SSE2-NOT: argument unused during compilation
+// RUN: %clang_cl -m32 -arch:SSE2 --target=i386-pc-windows /c /Fo%t.obj -Xclang -verify -DTEST_32_ARCH_SSE2 -- %s
+#if defined(TEST_32_ARCH_SSE2)
+#if _M_IX86_FP != 2 || __AVX__ || __AVX2__ || __AVX512F__ || __AVX512BW__
+#error fail
+#endif
+#endif
-// RUN: %clang_cl -m32 -arch:sse2 --target=i386 -### -- 2>&1 %s | FileCheck -check-prefix=sse %s
+// RUN: %clang_cl -m32 -arch:sse2 --target=i386-pc-windows -### -- 2>&1 %s | FileCheck -check-prefix=sse %s
// sse2: argument unused during compilation
-// sse2-NOT: -target-feature
-// RUN: %clang_cl -m64 -arch:SSE --target=x86_64 -### -- 2>&1 %s | FileCheck -check-prefix=SSE64 %s
+// RUN: %clang_cl -m64 -arch:SSE --target=x86_64-pc-windows -### -- 2>&1 %s | FileCheck -check-prefix=SSE64 %s
// SSE64: argument unused during compilation
-// SSE64-NOT: -target-feature
-// SSE64-NOT: pentium3
-// RUN: %clang_cl -m64 -arch:SSE2 --target=x86_64 -### -- 2>&1 %s | FileCheck -check-prefix=SSE264 %s
+// RUN: %clang_cl -m64 -arch:SSE2 --target=x86_64-pc-windows -### -- 2>&1 %s | FileCheck -check-prefix=SSE264 %s
// SSE264: argument unused during compilation
-// SSE264-NOT: -target-feature
-// RUN: %clang_cl -m32 -arch:AVX --target=i386 -### -- 2>&1 %s | FileCheck -check-prefix=AVX %s
-// AVX: "-target-cpu" "sandybridge"
-// AVX: -target-feature
-// AVX: +avx
+// RUN: %clang_cl -m32 -arch:AVX --target=i386-pc-windows /c /Fo%t.obj -Xclang -verify -DTEST_32_ARCH_AVX -- %s
+#if defined(TEST_32_ARCH_AVX)
+#if _M_IX86_FP != 2 || !__AVX__ || __AVX2__ || __AVX512F__ || __AVX512BW__
+#error fail
+#endif
+#endif
-// RUN: %clang_cl -m32 -arch:avx --target=i386 -### -- 2>&1 %s | FileCheck -check-prefix=avx %s
+// RUN: %clang_cl -m32 -arch:avx --target=i386-pc-windows -### -- 2>&1 %s | FileCheck -check-prefix=avx %s
// avx: argument unused during compilation
-// avx-NOT: -target-feature
-// RUN: %clang_cl -m32 -arch:AVX2 --target=i386 -### -- 2>&1 %s | FileCheck -check-prefix=AVX2 %s
-// AVX2: "-target-cpu" "haswell"
-// AVX2: -target-feature
-// AVX2: +avx2
+// RUN: %clang_cl -m32 -arch:AVX2 --target=i386-pc-windows /c /Fo%t.obj -Xclang -verify -DTEST_32_ARCH_AVX2 -- %s
+#if defined(TEST_32_ARCH_AVX2)
+#if _M_IX86_FP != 2 || !__AVX__ || !__AVX2__ || __AVX512F__ || __AVX512BW__
+#error fail
+#endif
+#endif
-// RUN: %clang_cl -m32 -arch:avx2 --target=i386 -### -- 2>&1 %s | FileCheck -check-prefix=avx2 %s
+// RUN: %clang_cl -m32 -arch:avx2 --target=i386-pc-windows -### -- 2>&1 %s | FileCheck -check-prefix=avx2 %s
// avx2: argument unused during compilation
-// avx2-NOT: -target-feature
-
-// RUN: %clang_cl -m64 -arch:AVX --target=x86_64 -### -- 2>&1 %s | FileCheck -check-prefix=AVX64 %s
-// AVX64: "-target-cpu" "sandybridge"
-// AVX64: -target-feature
-// AVX64: +avx
-// RUN: %clang_cl -m64 -arch:avx --target=x86_64 -### -- 2>&1 %s | FileCheck -check-prefix=avx64 %s
+// RUN: %clang_cl -m32 -arch:AVX512F --target=i386-pc-windows /c /Fo%t.obj -Xclang -verify -DTEST_32_ARCH_AVX512F -- %s
+#if defined(TEST_32_ARCH_AVX512F)
+#if _M_IX86_FP != 2 || !__AVX__ || !__AVX2__ || !__AVX512F__ || __AVX512BW__
+#error fail
+#endif
+#endif
+
+// RUN: %clang_cl -m32 -arch:avx512f --target=i386-pc-windows -### -- 2>&1 %s | FileCheck -check-prefix=avx512f %s
+// avx512f: argument unused during compilation
+
+// RUN: %clang_cl -m32 -arch:AVX512 --target=i386-pc-windows /c /Fo%t.obj -Xclang -verify -DTEST_32_ARCH_AVX512 -- %s
+#if defined(TEST_32_ARCH_AVX512)
+#if _M_IX86_FP != 2 || !__AVX__ || !__AVX2__ || !__AVX512F__ || !__AVX512BW__
+#error fail
+#endif
+#endif
+
+// RUN: %clang_cl -m32 -arch:avx512 --target=i386-pc-windows -### -- 2>&1 %s | FileCheck -check-prefix=avx512 %s
+// avx512: argument unused during compilation
+
+// RUN: %clang_cl -m64 -arch:AVX --target=x86_64-pc-windows /c /Fo%t.obj -Xclang -verify -DTEST_64_ARCH_AVX -- %s
+#if defined(TEST_64_ARCH_AVX)
+#if _M_IX86_FP || !__AVX__ || __AVX2__ || __AVX512F__ || __AVX512BW__
+#error fail
+#endif
+#endif
+
+// RUN: %clang_cl -m64 -arch:avx --target=x86_64-pc-windows -### -- 2>&1 %s | FileCheck -check-prefix=avx64 %s
// avx64: argument unused during compilation
-// avx64-NOT: -target-feature
-// RUN: %clang_cl -m64 -arch:AVX2 --target=x86_64 -### -- 2>&1 %s | FileCheck -check-prefix=AVX264 %s
-// AVX264: "-target-cpu" "haswell"
-// AVX264: -target-feature
-// AVX264: +avx2
+// RUN: %clang_cl -m64 -arch:AVX2 --target=x86_64-pc-windows /c /Fo%t.obj -Xclang -verify -DTEST_64_ARCH_AVX2 -- %s
+#if defined(TEST_64_ARCH_AVX2)
+#if _M_IX86_FP || !__AVX__ || !__AVX2__ || __AVX512F__ || __AVX512BW__
+#error fail
+#endif
+#endif
-// RUN: %clang_cl -m64 -arch:avx2 --target=x86_64 -### -- 2>&1 %s | FileCheck -check-prefix=avx264 %s
+// RUN: %clang_cl -m64 -arch:avx2 --target=x86_64-pc-windows -### -- 2>&1 %s | FileCheck -check-prefix=avx264 %s
// avx264: argument unused during compilation
-// avx264-NOT: -target-feature
+
+// RUN: %clang_cl -m64 -arch:AVX512F --target=i386-pc-windows /c /Fo%t.obj -Xclang -verify -DTEST_64_ARCH_AVX512F -- %s
+#if defined(TEST_64_ARCH_AVX512F)
+#if _M_IX86_FP || !__AVX__ || !__AVX2__ || !__AVX512F__ || __AVX512BW__
+#error fail
+#endif
+#endif
+
+// RUN: %clang_cl -m64 -arch:avx512f --target=i386-pc-windows -### -- 2>&1 %s | FileCheck -check-prefix=avx512f64 %s
+// avx512f64: argument unused during compilation
+
+// RUN: %clang_cl -m64 -arch:AVX512 --target=i386-pc-windows /c /Fo%t.obj -Xclang -verify -DTEST_64_ARCH_AVX512 -- %s
+#if defined(TEST_64_ARCH_AVX512)
+#if _M_IX86_FP || !__AVX__ || !__AVX2__ || !__AVX512F__ || !__AVX512BW__
+#error fail
+#endif
+#endif
+
+// RUN: %clang_cl -m64 -arch:avx512 --target=i386-pc-windows -### -- 2>&1 %s | FileCheck -check-prefix=avx51264 %s
+// avx51264: argument unused during compilation
void f() {
}
diff --git a/test/Driver/clang-g-opts.c b/test/Driver/clang-g-opts.c
index a26fb29652b4..bc714b6c9379 100644
--- a/test/Driver/clang-g-opts.c
+++ b/test/Driver/clang-g-opts.c
@@ -3,7 +3,7 @@
// RUN: | FileCheck --check-prefix=CHECK-WITH-G %s
// Assert that the toolchains which should default to a lower Dwarf version do so.
-// RUN: %clang -### -S %s -g -target x86_64-apple-darwin 2>&1 \
+// RUN: %clang -### -S %s -g -target x86_64-apple-darwin8 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-WITH-G-DWARF2 %s
// RUN: %clang -### -S %s -g -target i686-pc-openbsd 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-WITH-G-DWARF2 %s
@@ -21,7 +21,7 @@
//
// RUN: %clang -### -S %s -g0 -g -target x86_64-linux-gnu 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-WITH-G %s
-// RUN: %clang -### -S %s -g0 -g -target x86_64-apple-darwin 2>&1 \
+// RUN: %clang -### -S %s -g0 -g -target x86_64-apple-darwin8 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-WITH-G-STANDALONE %s
// RUN: %clang -### -S %s -g0 -g -target i686-pc-openbsd 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-WITH-G-DWARF2 %s
diff --git a/test/Driver/clang-translation.cppm b/test/Driver/clang-translation.cppm
new file mode 100644
index 000000000000..01daecb7f6b8
--- /dev/null
+++ b/test/Driver/clang-translation.cppm
@@ -0,0 +1,2 @@
+// RUN: %clang %s --precompile -### 2>&1 | FileCheck %s
+// CHECK: "-o" "{{[^"]*}}clang-translation.pcm"
diff --git a/test/Driver/clang_f_opts.c b/test/Driver/clang_f_opts.c
index b22f74fb5557..9208d6b71bb5 100644
--- a/test/Driver/clang_f_opts.c
+++ b/test/Driver/clang_f_opts.c
@@ -276,6 +276,7 @@
// RUN: -fno-inline-small-functions -finline-small-functions \
// RUN: -fno-fat-lto-objects -ffat-lto-objects \
// RUN: -fno-merge-constants -fmerge-constants \
+// RUN: -fno-merge-all-constants -fmerge-all-constants \
// RUN: -fno-caller-saves -fcaller-saves \
// RUN: -fno-reorder-blocks -freorder-blocks \
// RUN: -fno-schedule-insns2 -fschedule-insns2 \
@@ -301,8 +302,6 @@
// RUN: -fkeep-inline-functions \
// RUN: -fno-keep-inline-functions \
// RUN: -freorder-blocks \
-// RUN: -falign-functions \
-// RUN: -falign-functions=1 \
// RUN: -ffloat-store \
// RUN: -fgcse \
// RUN: -fivopts \
@@ -349,7 +348,6 @@
// RUN: -fwhole-program \
// RUN: -fcaller-saves \
// RUN: -freorder-blocks \
-// RUN: -fdelete-null-pointer-checks \
// RUN: -ffat-lto-objects \
// RUN: -fmerge-constants \
// RUN: -finline-small-functions \
@@ -369,8 +367,6 @@
// CHECK-WARNING-DAG: optimization flag '-fkeep-inline-functions' is not supported
// CHECK-WARNING-DAG: optimization flag '-fno-keep-inline-functions' is not supported
// CHECK-WARNING-DAG: optimization flag '-freorder-blocks' is not supported
-// CHECK-WARNING-DAG: optimization flag '-falign-functions' is not supported
-// CHECK-WARNING-DAG: optimization flag '-falign-functions=1' is not supported
// CHECK-WARNING-DAG: optimization flag '-ffloat-store' is not supported
// CHECK-WARNING-DAG: optimization flag '-fgcse' is not supported
// CHECK-WARNING-DAG: optimization flag '-fivopts' is not supported
@@ -417,7 +413,6 @@
// CHECK-WARNING-DAG: optimization flag '-fwhole-program' is not supported
// CHECK-WARNING-DAG: optimization flag '-fcaller-saves' is not supported
// CHECK-WARNING-DAG: optimization flag '-freorder-blocks' is not supported
-// CHECK-WARNING-DAG: optimization flag '-fdelete-null-pointer-checks' is not supported
// CHECK-WARNING-DAG: optimization flag '-ffat-lto-objects' is not supported
// CHECK-WARNING-DAG: optimization flag '-fmerge-constants' is not supported
// CHECK-WARNING-DAG: optimization flag '-finline-small-functions' is not supported
@@ -503,3 +498,36 @@
// CHECK-WINDOWS-ISO10646: "-fwchar-type=int"
// CHECK-WINDOWS-ISO10646: "-fsigned-wchar"
+// RUN: %clang -### -S -fcf-protection %s 2>&1 | FileCheck -check-prefix=CHECK-CF-PROTECTION-FULL %s
+// RUN: %clang -### -S %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CF-PROTECTION-FULL %s
+// RUN: %clang -### -S -fcf-protection=full %s 2>&1 | FileCheck -check-prefix=CHECK-CF-PROTECTION-FULL %s
+// RUN: %clang -### -S %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CF-PROTECTION-FULL %s
+// CHECK-CF-PROTECTION-FULL: -fcf-protection=full
+// CHECK-NO-CF-PROTECTION-FULL-NOT: -fcf-protection=full
+// RUN: %clang -### -S -fcf-protection=return %s 2>&1 | FileCheck -check-prefix=CHECK-CF-PROTECTION-RETURN %s
+// RUN: %clang -### -S %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CF-PROTECTION-RETURN %s
+// CHECK-CF-PROTECTION-RETURN: -fcf-protection=return
+// CHECK-NO-CF-PROTECTION-RETURN-NOT: -fcf-protection=return
+// RUN: %clang -### -S -fcf-protection=branch %s 2>&1 | FileCheck -check-prefix=CHECK-CF-PROTECTION-BRANCH %s
+// RUN: %clang -### -S %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CF-PROTECTION-BRANCH %s
+// CHECK-CF-PROTECTION-BRANCH: -fcf-protection=branch
+// CHECK-NO-CF-PROTECTION-BRANCH-NOT: -fcf-protection=branch
+
+// RUN: %clang -### -S -fdiscard-value-names %s 2>&1 | FileCheck -check-prefix=CHECK-DISCARD-NAMES %s
+// RUN: %clang -### -S -fno-discard-value-names %s 2>&1 | FileCheck -check-prefix=CHECK-NO-DISCARD-NAMES %s
+// CHECK-DISCARD-NAMES: "-discard-value-names"
+// CHECK-NO-DISCARD-NAMES-NOT: "-discard-value-names"
+//
+// RUN: %clang -### -S -fmerge-all-constants %s 2>&1 | FileCheck -check-prefix=CHECK-MERGE-ALL-CONSTANTS %s
+// RUN: %clang -### -S -fno-merge-all-constants %s 2>&1 | FileCheck -check-prefix=CHECK-NO-MERGE-ALL-CONSTANTS %s
+// RUN: %clang -### -S -fmerge-all-constants -fno-merge-all-constants %s 2>&1 | FileCheck -check-prefix=CHECK-NO-MERGE-ALL-CONSTANTS %s
+// RUN: %clang -### -S -fno-merge-all-constants -fmerge-all-constants %s 2>&1 | FileCheck -check-prefix=CHECK-MERGE-ALL-CONSTANTS %s
+// CHECK-NO-MERGE-ALL-CONSTANTS-NOT: "-fmerge-all-constants"
+// CHECK-MERGE-ALL-CONSTANTS: "-fmerge-all-constants"
+
+// RUN: %clang -### -S -fdelete-null-pointer-checks %s 2>&1 | FileCheck -check-prefix=CHECK-NULL-POINTER-CHECKS %s
+// RUN: %clang -### -S -fno-delete-null-pointer-checks %s 2>&1 | FileCheck -check-prefix=CHECK-NO-NULL-POINTER-CHECKS %s
+// RUN: %clang -### -S -fdelete-null-pointer-checks -fno-delete-null-pointer-checks %s 2>&1 | FileCheck -check-prefix=CHECK-NO-NULL-POINTER-CHECKS %s
+// RUN: %clang -### -S -fno-delete-null-pointer-checks -fdelete-null-pointer-checks %s 2>&1 | FileCheck -check-prefix=CHECK-NULL-POINTER-CHECKS %s
+// CHECK-NO-NULL-POINTER-CHECKS: "-fno-delete-null-pointer-checks"
+// CHECK-NULL-POINTER-CHECKS-NOT: "-fno-delete-null-pointer-checks"
diff --git a/test/Driver/codeview-column-info.c b/test/Driver/codeview-column-info.c
new file mode 100644
index 000000000000..6b524accd7b7
--- /dev/null
+++ b/test/Driver/codeview-column-info.c
@@ -0,0 +1,15 @@
+// Check that -dwarf-column-info does not get added to the cc1 line:
+// 1) When -gcodeview is present via the clang or clang++ driver
+// 2) When /Z7 is present via the cl driver.
+
+// RUN: %clang -### --target=x86_64-windows-msvc -c -g -gcodeview %s 2> %t1
+// RUN: FileCheck < %t1 %s
+// RUN: %clangxx -### --target=x86_64-windows-msvc -c -g -gcodeview %s 2> %t2
+// RUN: FileCheck < %t2 %s
+// RUN: %clangxx -### --target=x86_64-windows-gnu -c -g -gcodeview %s 2> %t2
+// RUN: FileCheck < %t2 %s
+// RUN: %clang_cl -### --target=x86_64-windows-msvc /c /Z7 -- %s 2> %t2
+// RUN: FileCheck < %t2 %s
+
+// CHECK: "-cc1"
+// CHECK-NOT: "-dwarf-column-info"
diff --git a/test/Driver/complete-member-pointers.cpp b/test/Driver/complete-member-pointers.cpp
new file mode 100644
index 000000000000..e64b2546e4db
--- /dev/null
+++ b/test/Driver/complete-member-pointers.cpp
@@ -0,0 +1,7 @@
+// RUN: %clangxx -### -c %s -o %t.o -target x86_64-unknown-linux 2>&1 | FileCheck --check-prefix=NOFLAG %s
+// RUN: %clangxx -### -c %s -o %t.o -target x86_64-unknown-linux -fcomplete-member-pointers 2>&1 | FileCheck %s
+// RUN: %clangxx -### -c %s -o %t.o -target x86_64-unknown-linux -fcomplete-member-pointers -fno-complete-member-pointers 2>&1 | FileCheck --check-prefix=NOFLAG %s
+// RUN: %clang_cl -### /c /Fo%t.o -target x86_64-pc-win32 -fcomplete-member-pointers -- %s 2>&1 | FileCheck %s
+
+// CHECK: "-fcomplete-member-pointers"
+// NOFLAG-NOT: "-fcomplete-member-pointers"
diff --git a/test/Driver/config-file-errs.c b/test/Driver/config-file-errs.c
new file mode 100644
index 000000000000..8db2ea439298
--- /dev/null
+++ b/test/Driver/config-file-errs.c
@@ -0,0 +1,54 @@
+//--- No more than one '--config' may be specified.
+//
+// RUN: not %clang --config 1.cfg --config 2.cfg 2>&1 | FileCheck %s -check-prefix CHECK-DUPLICATE
+// CHECK-DUPLICATE: no more than one option '--config' is allowed
+
+
+//--- '--config' must be followed by config file name.
+//
+// RUN: not %clang --config 2>&1 | FileCheck %s -check-prefix CHECK-MISSING-FILE
+// CHECK-MISSING-FILE: argument to '--config' is missing (expected 1 value)
+
+
+//--- '--config' must not be found in config files.
+//
+// RUN: not %clang --config %S/Inputs/config-6.cfg 2>&1 | FileCheck %s -check-prefix CHECK-NESTED
+// CHECK-NESTED: option '--config' is not allowed inside configuration file
+
+
+//--- Argument of '--config' must be existing file, if it is specified by path.
+//
+// RUN: not %clang --config somewhere/nonexistent-config-file 2>&1 | FileCheck %s -check-prefix CHECK-NONEXISTENT
+// CHECK-NONEXISTENT: configuration file '{{.*}}somewhere/nonexistent-config-file' does not exist
+
+
+//--- Argument of '--config' must exist somewhere in well-known directories, if it is specified by bare name.
+//
+// RUN: not %clang --config-system-dir= --config-user-dir= --config nonexistent-config-file 2>&1 | FileCheck %s -check-prefix CHECK-NOTFOUND0
+// CHECK-NOTFOUND0: configuration file 'nonexistent-config-file.cfg' cannot be found
+// CHECK-NOTFOUND0-NEXT: was searched for in the directory:
+// CHECK-NOTFOUND0-NOT: was searched for in the directory:
+//
+// RUN: not %clang --config-system-dir= --config-user-dir=%S/Inputs/config2 --config nonexistent-config-file 2>&1 | FileCheck %s -check-prefix CHECK-NOTFOUND1
+// CHECK-NOTFOUND1: configuration file 'nonexistent-config-file.cfg' cannot be found
+// CHECK-NOTFOUND1-NEXT: was searched for in the directory: {{.*}}/Inputs/config2
+// CHECK-NOTFOUND1-NEXT: was searched for in the directory:
+// CHECK-NOTFOUND1-NOT: was searched for in the directory:
+//
+// RUN: not %clang --config-system-dir=%S/Inputs/config --config-user-dir= --config nonexistent-config-file 2>&1 | FileCheck %s -check-prefix CHECK-NOTFOUND2
+// CHECK-NOTFOUND2: configuration file 'nonexistent-config-file.cfg' cannot be found
+// CHECK-NOTFOUND2-NEXT: was searched for in the directory: {{.*}}/Inputs/config
+// CHECK-NOTFOUND2-NEXT: was searched for in the directory:
+// CHECK-NOTFOUND2-NOT: was searched for in the directory:
+//
+// RUN: not %clang --config-system-dir=%S/Inputs/config --config-user-dir=%S/Inputs/config2 --config nonexistent-config-file 2>&1 | FileCheck %s -check-prefix CHECK-NOTFOUND3
+// CHECK-NOTFOUND3: configuration file 'nonexistent-config-file.cfg' cannot be found
+// CHECK-NOTFOUND3-NEXT: was searched for in the directory: {{.*}}/Inputs/config2
+// CHECK-NOTFOUND3-NEXT: was searched for in the directory: {{.*}}/Inputs/config
+// CHECK-NOTFOUND3-NEXT: was searched for in the directory:
+
+
+//--- Argument in config file cannot cross the file boundary
+//
+// RUN: not %clang --config %S/Inputs/config-5.cfg x86_64-unknown-linux-gnu -c %s 2>&1 | FileCheck %s -check-prefix CHECK-CROSS
+// CHECK-CROSS: error: argument to '-target' is missing
diff --git a/test/Driver/config-file.c b/test/Driver/config-file.c
new file mode 100644
index 000000000000..04127d404f67
--- /dev/null
+++ b/test/Driver/config-file.c
@@ -0,0 +1,73 @@
+//--- Config file search directories
+//
+// RUN: %clang --config-system-dir=%S/Inputs/config --config-user-dir=%S/Inputs/config2 -o /dev/null -v 2>&1 | FileCheck %s -check-prefix CHECK-DIRS
+// CHECK-DIRS: System configuration file directory: {{.*}}/Inputs/config
+// CHECK-DIRS: User configuration file directory: {{.*}}/Inputs/config2
+
+
+//--- Config file (full path) in output of -###
+//
+// RUN: %clang --config %S/Inputs/config-1.cfg -S %s -### 2>&1 | FileCheck %s -check-prefix CHECK-HHH
+// CHECK-HHH: Configuration file: {{.*}}Inputs{{.}}config-1.cfg
+// CHECK-HHH: -Werror
+// CHECK-HHH: -std=c99
+
+
+//--- Config file (full path) in output of -v
+//
+// RUN: %clang --config %S/Inputs/config-1.cfg -S %s -o /dev/null -v 2>&1 | FileCheck %s -check-prefix CHECK-V
+// CHECK-V: Configuration file: {{.*}}Inputs{{.}}config-1.cfg
+// CHECK-V: -Werror
+// CHECK-V: -std=c99
+
+
+//--- Config file in output of -###
+//
+// RUN: %clang --config-system-dir=%S/Inputs --config-user-dir= --config config-1.cfg -S %s -### 2>&1 | FileCheck %s -check-prefix CHECK-HHH2
+// CHECK-HHH2: Configuration file: {{.*}}Inputs{{.}}config-1.cfg
+// CHECK-HHH2: -Werror
+// CHECK-HHH2: -std=c99
+
+
+//--- Config file in output of -v
+//
+// RUN: %clang --config-system-dir=%S/Inputs --config-user-dir= --config config-1.cfg -S %s -o /dev/null -v 2>&1 | FileCheck %s -check-prefix CHECK-V2
+// CHECK-V2: Configuration file: {{.*}}Inputs{{.}}config-1.cfg
+// CHECK-V2: -Werror
+// CHECK-V2: -std=c99
+
+
+//--- Nested config files
+//
+// RUN: %clang --config-system-dir=%S/Inputs --config-user-dir= --config config-2.cfg -S %s -### 2>&1 | FileCheck %s -check-prefix CHECK-NESTED
+// CHECK-NESTED: Configuration file: {{.*}}Inputs{{.}}config-2.cfg
+// CHECK-NESTED: -Wundefined-func-template
+
+// RUN: %clang --config-system-dir=%S/Inputs --config-user-dir= --config config-2.cfg -S %s -### 2>&1 | FileCheck %s -check-prefix CHECK-NESTED2
+// CHECK-NESTED2: Configuration file: {{.*}}Inputs{{.}}config-2.cfg
+// CHECK-NESTED2: -Wundefined-func-template
+
+
+// RUN: %clang --config %S/Inputs/config-2a.cfg -S %s -### 2>&1 | FileCheck %s -check-prefix CHECK-NESTEDa
+// CHECK-NESTEDa: Configuration file: {{.*}}Inputs{{.}}config-2a.cfg
+// CHECK-NESTEDa: -isysroot
+// CHECK-NESTEDa-SAME: /opt/data
+
+// RUN: %clang --config-system-dir=%S/Inputs --config-user-dir= --config config-2a.cfg -S %s -### 2>&1 | FileCheck %s -check-prefix CHECK-NESTED2a
+// CHECK-NESTED2a: Configuration file: {{.*}}Inputs{{.}}config-2a.cfg
+// CHECK-NESTED2a: -isysroot
+// CHECK-NESTED2a-SAME: /opt/data
+
+
+//--- Unused options in config file do not produce warnings
+//
+// RUN: %clang --config %S/Inputs/config-4.cfg -S %s -o /dev/null -v 2>&1 | FileCheck %s -check-prefix CHECK-UNUSED
+// CHECK-UNUSED-NOT: argument unused during compilation:
+// CHECK-UNUSED-NOT: 'linker' input unused
+
+
+//--- User directory is searched first.
+//
+// RUN: %clang --config-system-dir=%S/Inputs/config --config-user-dir=%S/Inputs/config2 --config config-4 -S %s -o /dev/null -v 2>&1 | FileCheck %s -check-prefix CHECK-PRECEDENCE
+// CHECK-PRECEDENCE: Configuration file: {{.*}}Inputs{{.}}config2{{.}}config-4.cfg
+// CHECK-PRECEDENCE: -Wall
diff --git a/test/Driver/config-file2.c b/test/Driver/config-file2.c
new file mode 100644
index 000000000000..8b57a92e1e83
--- /dev/null
+++ b/test/Driver/config-file2.c
@@ -0,0 +1,51 @@
+// REQUIRES: x86-registered-target
+
+//--- Invocation `clang --config x86_64-qqq -m32` loads `i386-qqq.cfg` if the latter exists.
+//
+// RUN: %clang --config-system-dir=%S/Inputs/config --config-user-dir= --config x86_64-qqq -m32 -c %s -### 2>&1 | FileCheck %s -check-prefix CHECK-RELOAD
+// CHECK-RELOAD: Target: i386
+// CHECK-RELOAD: Configuration file: {{.*}}Inputs{{.}}config{{.}}i386-qqq.cfg
+
+
+//--- Invocation `clang --config x86_64-qqq2 -m32` loads `i386.cfg` if the latter exists in another search directory.
+//
+// RUN: %clang --config-system-dir=%S/Inputs/config --config-user-dir=%S/Inputs/config2 --config x86_64-qqq2 -m32 -c %s -### 2>&1 | FileCheck %s -check-prefix CHECK-RELOAD1
+// CHECK-RELOAD1: Target: i386
+// CHECK-RELOAD1: Configuration file: {{.*}}Inputs{{.}}config2{{.}}i386.cfg
+
+
+//--- Invocation `clang --config x86_64-qqq2 -m32` loads `x86_64-qqq2.cfg` if `i386-qqq2.cfg` and `i386.cfg` do not exist.
+//
+// RUN: %clang --config-system-dir=%S/Inputs/config --config-user-dir= --config x86_64-qqq2 -m32 -c %s -### 2>&1 | FileCheck %s -check-prefix CHECK-RELOAD2
+// note: target is overridden due to -m32
+// CHECK-RELOAD2: Target: i386
+// CHECK-RELOAD2: Configuration file: {{.*}}Inputs{{.}}config{{.}}x86_64-qqq2.cfg
+
+
+//--- Invocation `clang --config i386-qqq3 -m64` loads `x86_64.cfg` if `x86_64-qqq3.cfg` does not exist.
+//
+// RUN: %clang --config-system-dir=%S/Inputs/config --config-user-dir= --config i386-qqq3 -m64 -c %s -### 2>&1 | FileCheck %s -check-prefix CHECK-RELOAD3
+// CHECK-RELOAD3: Target: x86_64
+// CHECK-RELOAD3: Configuration file: {{.*}}Inputs{{.}}config{{.}}x86_64.cfg
+
+
+//--- Invocation `clang --config x86_64-qqq -target i386` loads `i386-qqq.cfg` if the latter exists.
+//
+// RUN: %clang --config-system-dir=%S/Inputs/config --config-user-dir= --config x86_64-qqq -target i386 -c %s -### 2>&1 | FileCheck %s -check-prefix CHECK-RELOAD4
+// CHECK-RELOAD4: Target: i386
+// CHECK-RELOAD4: Configuration file: {{.*}}Inputs{{.}}config{{.}}i386-qqq.cfg
+
+
+//--- Invocation `clang --config x86_64-qqq2 -target i386` loads `x86_64-qqq2.cfg` if `i386-qqq2.cfg` and `i386.cfg` do not exist.
+//
+// RUN: %clang --config-system-dir=%S/Inputs/config --config-user-dir= --config x86_64-qqq2 -target i386 -c %s -### 2>&1 | FileCheck %s -check-prefix CHECK-RELOAD5
+// note: target is overridden due to -target i386
+// CHECK-RELOAD5: Target: i386
+// CHECK-RELOAD5: Configuration file: {{.*}}Inputs{{.}}config{{.}}x86_64-qqq2.cfg
+
+
+//--- Invocation `clang --config x86_64-qqq -target i386 -m64` loads `x86_64-qqq.cfg`.
+//
+// RUN: %clang --config-system-dir=%S/Inputs/config --config-user-dir= --config x86_64-qqq -target i386 -m64 -c %s -### 2>&1 | FileCheck %s -check-prefix CHECK-RELOAD6
+// CHECK-RELOAD6: Target: x86_64
+// CHECK-RELOAD6: Configuration file: {{.*}}Inputs{{.}}config{{.}}x86_64-qqq.cfg
diff --git a/test/Driver/config-file3.c b/test/Driver/config-file3.c
new file mode 100644
index 000000000000..938411cf0fff
--- /dev/null
+++ b/test/Driver/config-file3.c
@@ -0,0 +1,106 @@
+// REQUIRES: shell
+// REQUIRES: x86-registered-target
+
+//--- If config file is specified by relative path (workdir/cfg-s2), it is searched for by that path.
+//
+// RUN: mkdir -p %T/workdir
+// RUN: echo "@subdir/cfg-s2" > %T/workdir/cfg-1
+// RUN: mkdir -p %T/workdir/subdir
+// RUN: echo "-Wundefined-var-template" > %T/workdir/subdir/cfg-s2
+//
+// RUN: ( cd %T && %clang --config workdir/cfg-1 -c %s -### 2>&1 | FileCheck %s -check-prefix CHECK-REL )
+//
+// CHECK-REL: Configuration file: {{.*}}/workdir/cfg-1
+// CHECK-REL: -Wundefined-var-template
+
+
+//--- Invocation qqq-clang-g++ tries to find config file qqq-clang-g++.cfg first.
+//
+// RUN: mkdir -p %T/testdmode
+// RUN: [ ! -s %T/testdmode/qqq-clang-g++ ] || rm %T/testdmode/qqq-clang-g++
+// RUN: ln -s %clang %T/testdmode/qqq-clang-g++
+// RUN: echo "-Wundefined-func-template" > %T/testdmode/qqq-clang-g++.cfg
+// RUN: echo "-Werror" > %T/testdmode/qqq.cfg
+// RUN: %T/testdmode/qqq-clang-g++ --config-system-dir= --config-user-dir= -c -no-canonical-prefixes %s -### 2>&1 | FileCheck %s -check-prefix FULL-NAME
+//
+// FULL-NAME: Configuration file: {{.*}}/testdmode/qqq-clang-g++.cfg
+// FULL-NAME: -Wundefined-func-template
+// FULL-NAME-NOT: -Werror
+//
+//--- Invocation qqq-clang-g++ tries to find config file qqq-clang-g++.cfg even without -no-canonical-prefixes.
+// (As the clang executable and symlink are in different directories, this
+// requires specifying the path via --config-*-dir= though.)
+//
+// RUN: %T/testdmode/qqq-clang-g++ --config-system-dir= --config-user-dir=%T/testdmode -c %s -### 2>&1 | FileCheck %s -check-prefix SYMLINK
+//
+// SYMLINK: Configuration file: {{.*}}/testdmode/qqq-clang-g++.cfg
+//
+//--- File specified by --config overrides config inferred from clang executable.
+//
+// RUN: %T/testdmode/qqq-clang-g++ --config-system-dir=%S/Inputs/config --config-user-dir= --config i386-qqq -c -no-canonical-prefixes %s -### 2>&1 | FileCheck %s -check-prefix CHECK-EXPLICIT
+//
+// CHECK-EXPLICIT: Configuration file: {{.*}}/Inputs/config/i386-qqq.cfg
+//
+//--- Invocation qqq-clang-g++ tries to find config file qqq.cfg if qqq-clang-g++.cfg is not found.
+//
+// RUN: rm %T/testdmode/qqq-clang-g++.cfg
+// RUN: %T/testdmode/qqq-clang-g++ --config-system-dir= --config-user-dir= -c -no-canonical-prefixes %s -### 2>&1 | FileCheck %s -check-prefix SHORT-NAME
+//
+// SHORT-NAME: Configuration file: {{.*}}/testdmode/qqq.cfg
+// SHORT-NAME: -Werror
+// SHORT-NAME-NOT: -Wundefined-func-template
+
+
+//--- Config files are searched for in binary directory as well.
+//
+// RUN: mkdir -p %T/testbin
+// RUN: [ ! -s %T/testbin/clang ] || rm %T/testbin/clang
+// RUN: ln -s %clang %T/testbin/clang
+// RUN: echo "-Werror" > %T/testbin/aaa.cfg
+// RUN: %T/testbin/clang --config-system-dir= --config-user-dir= --config aaa.cfg -c -no-canonical-prefixes %s -### 2>&1 | FileCheck %s -check-prefix CHECK-BIN
+//
+// CHECK-BIN: Configuration file: {{.*}}/testbin/aaa.cfg
+// CHECK-BIN: -Werror
+
+
+//--- If command line contains options that change triple (for instance, -m32), clang tries
+// reloading config file.
+
+//--- When reloading config file, x86_64-clang-g++ tries to find config i386-clang-g++.cfg first.
+//
+// RUN: mkdir -p %T/testreload
+// RUN: [ ! -s %T/testreload/x86_64-clang-g++ ] || rm %T/testreload/x86_64-clang-g++
+// RUN: ln -s %clang %T/testreload/x86_64-clang-g++
+// RUN: echo "-Wundefined-func-template" > %T/testreload/i386-clang-g++.cfg
+// RUN: echo "-Werror" > %T/testreload/i386.cfg
+// RUN: %T/testreload/x86_64-clang-g++ --config-system-dir= --config-user-dir= -c -m32 -no-canonical-prefixes %s -### 2>&1 | FileCheck %s -check-prefix CHECK-RELOAD
+//
+// CHECK-RELOAD: Configuration file: {{.*}}/testreload/i386-clang-g++.cfg
+// CHECK-RELOAD: -Wundefined-func-template
+// CHECK-RELOAD-NOT: -Werror
+
+//--- If config file is specified by --config and its name does not start with architecture, it is used without reloading.
+//
+// RUN: %T/testreload/x86_64-clang-g++ --config-system-dir=%S/Inputs --config-user-dir= --config config-3 -c -m32 -no-canonical-prefixes %s -### 2>&1 | FileCheck %s -check-prefix CHECK-RELOAD1a
+//
+// CHECK-RELOAD1a: Configuration file: {{.*}}/Inputs/config-3.cfg
+//
+// RUN: %T/testreload/x86_64-clang-g++ --config-system-dir=%S/Inputs --config-user-dir= --config config-3 -c -target i386 -no-canonical-prefixes %s -### 2>&1 | FileCheck %s -check-prefix CHECK-RELOAD1b
+//
+// CHECK-RELOAD1b: Configuration file: {{.*}}/Inputs/config-3.cfg
+
+//--- If config file is specified by --config and its name starts with architecture, it is reloaded.
+//
+// RUN: %T/testreload/x86_64-clang-g++ --config-system-dir=%S/Inputs/config --config-user-dir= --config x86_64-qqq -c -m32 -no-canonical-prefixes %s -### 2>&1 | FileCheck %s -check-prefix CHECK-RELOAD1c
+//
+// CHECK-RELOAD1c: Configuration file: {{.*}}/Inputs/config/i386-qqq.cfg
+
+//--- x86_64-clang-g++ tries to find config i386.cfg if i386-clang-g++.cfg is not found.
+//
+// RUN: rm %T/testreload/i386-clang-g++.cfg
+// RUN: %T/testreload/x86_64-clang-g++ --config-system-dir= --config-user-dir= -c -m32 -no-canonical-prefixes %s -### 2>&1 | FileCheck %s -check-prefix CHECK-RELOAD1d
+//
+// CHECK-RELOAD1d: Configuration file: {{.*}}/testreload/i386.cfg
+// CHECK-RELOAD1d: -Werror
+// CHECK-RELOAD1d-NOT: -Wundefined-func-template
+
diff --git a/test/Driver/config-file4.c b/test/Driver/config-file4.c
new file mode 100644
index 000000000000..19ef7d50cd4e
--- /dev/null
+++ b/test/Driver/config-file4.c
@@ -0,0 +1,2 @@
+// RUN: %clang --config %S/Inputs/empty.cfg -Wall -Wextra -Wformat -Wstrict-aliasing -Wshadow -Wpacked -Winline -Wimplicit-function-declaration -S %s -O2 -o /dev/null -v 2>&1 | FileCheck %s -check-prefix PR37196
+// PR37196: Configuration file: {{.*}}empty.cfg
diff --git a/test/Driver/constructors.c b/test/Driver/constructors.c
index 884fbe8466cb..a3443a3321ad 100644
--- a/test/Driver/constructors.c
+++ b/test/Driver/constructors.c
@@ -80,6 +80,14 @@
// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \
// RUN: -target arm64-none-none-eabi \
// RUN: | FileCheck --check-prefix=CHECK-INIT-ARRAY %s
+
+// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \
+// RUN: -target i386-unknown-freebsd11 \
+// RUN: | FileCheck --check-prefix=CHECK-NO-INIT-ARRAY %s
+
+// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \
+// RUN: -target i386-unknown-freebsd12 \
+// RUN: | FileCheck --check-prefix=CHECK-INIT-ARRAY %s
//
// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \
// RUN: -target sparc-sun-solaris2.11 \
diff --git a/test/Driver/crash-diagnostics-dir.c b/test/Driver/crash-diagnostics-dir.c
new file mode 100644
index 000000000000..c8faf497b5a1
--- /dev/null
+++ b/test/Driver/crash-diagnostics-dir.c
@@ -0,0 +1,6 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: not %clang -fcrash-diagnostics-dir=%t -c %s -o - 2>&1 | FileCheck %s
+#pragma clang __debug parser_crash
+// CHECK: Preprocessed source(s) and associated run script(s) are located at:
+// CHECK: diagnostic msg: {{.*}}{{/|\\}}crash-diagnostics-dir.c.tmp{{(/|\\).*}}.c
diff --git a/test/Driver/crash-report-header.h b/test/Driver/crash-report-header.h
index e0193cbe45e9..c1b0ab367683 100644
--- a/test/Driver/crash-report-header.h
+++ b/test/Driver/crash-report-header.h
@@ -1,13 +1,10 @@
// RUN: rm -rf %t
// RUN: mkdir %t
-// RUN: not env TMPDIR="%t" TEMP="%t" TMP="%t" RC_DEBUG_OPTIONS=1 %clang -fsyntax-only %s 2>&1 | FileCheck %s
+// RUN: env TMPDIR="%t" TEMP="%t" TMP="%t" RC_DEBUG_OPTIONS=1 not %clang -fsyntax-only %s 2>&1 | FileCheck %s
// RUN: cat %t/crash-report-header-*.h | FileCheck --check-prefix=CHECKSRC "%s"
// RUN: cat %t/crash-report-header-*.sh | FileCheck --check-prefix=CHECKSH "%s"
// REQUIRES: crash-recovery
-// because of the glob (*.h, *.sh)
-// REQUIRES: shell
-
#pragma clang __debug parser_crash
// CHECK: Preprocessed source(s) and associated run script(s) are located at:
// CHECK-NEXT: note: diagnostic msg: {{.*}}.h
diff --git a/test/Driver/crash-report-modules.m b/test/Driver/crash-report-modules.m
index 16af75ca700b..ded31b4ed4fe 100644
--- a/test/Driver/crash-report-modules.m
+++ b/test/Driver/crash-report-modules.m
@@ -1,19 +1,20 @@
-// RUN: rm -rf %t
-// RUN: mkdir -p %t/i %t/m %t
-
-// RUN: not env FORCE_CLANG_DIAGNOSTICS_CRASH= TMPDIR=%t TEMP=%t TMP=%t \
-// RUN: %clang -fsyntax-only %s -I %S/Inputs/module -isysroot %/t/i/ \
-// RUN: -fmodules -fmodules-cache-path=%t/m/ -DFOO=BAR 2>&1 | FileCheck %s
-
-// RUN: FileCheck --check-prefix=CHECKSRC %s -input-file %t/crash-report-*.m
-// RUN: FileCheck --check-prefix=CHECKSH %s -input-file %t/crash-report-*.sh
+// FIXME: Instead of %T/crmdir, it would be nice to just use %t, but the
+// filename ran into path length limits for the rm command on some Windows
+// bots.
+// RUN: rm -rf %T/crmdir
+// RUN: mkdir -p %T/crmdir/i %T/crmdir/m
+
+// RUN: env FORCE_CLANG_DIAGNOSTICS_CRASH= TMPDIR=%T/crmdir TEMP=%T/crmdir TMP=%T/crmdir \
+// RUN: not %clang -fsyntax-only %s -I %S/Inputs/module -isysroot %/t/i/ \
+// RUN: -fmodules -fmodules-cache-path=%T/crmdir/m/ -DFOO=BAR 2>&1 | FileCheck %s
+
+// RUN: FileCheck --check-prefix=CHECKSRC %s -input-file %T/crmdir/crash-report-*.m
+// RUN: FileCheck --check-prefix=CHECKSH %s -input-file %T/crmdir/crash-report-*.sh
// REQUIRES: crash-recovery
-// because of the glob (*.m, *.sh)
-// REQUIRES: shell
-
-// FIXME: This XFAIL is cargo-culted from crash-report.c. Do we need it?
-// XFAIL: mingw32
+// FIXME: This test creates excessively deep directory hierarchies that cause
+// problems on Windows.
+// UNSUPPORTED: system-windows
@import simple;
const int x = MODULE_MACRO;
@@ -34,4 +35,4 @@ const int x = MODULE_MACRO;
// CHECKSH: "-D" "FOO=BAR"
// CHECKSH-NOT: "-fmodules-cache-path="
// CHECKSH: "crash-report-modules-{{[^ ]*}}.m"
-// CHECKSH: "-ivfsoverlay" "crash-report-modules-{{[^ ]*}}.cache/vfs/vfs.yaml"
+// CHECKSH: "-ivfsoverlay" "crash-report-modules-{{[^ ]*}}.cache{{(/|\\\\)}}vfs{{(/|\\\\)}}vfs.yaml"
diff --git a/test/Driver/crash-report-spaces.c b/test/Driver/crash-report-spaces.c
index 3e95a0de2516..e6da0873673a 100644
--- a/test/Driver/crash-report-spaces.c
+++ b/test/Driver/crash-report-spaces.c
@@ -1,14 +1,11 @@
// RUN: rm -rf "%t"
// RUN: mkdir "%t"
// RUN: cp "%s" "%t/crash report spaces.c"
-// RUN: not env TMPDIR="%t" TEMP="%t" TMP="%t" RC_DEBUG_OPTIONS=1 %clang -fsyntax-only "%t/crash report spaces.c" 2>&1 | FileCheck "%s"
+// RUN: env TMPDIR="%t" TEMP="%t" TMP="%t" RC_DEBUG_OPTIONS=1 not %clang -fsyntax-only "%t/crash report spaces.c" 2>&1 | FileCheck "%s"
// RUN: cat "%t/crash report spaces"-*.c | FileCheck --check-prefix=CHECKSRC "%s"
// RUN: cat "%t/crash report spaces"-*.sh | FileCheck --check-prefix=CHECKSH "%s"
// REQUIRES: crash-recovery
-// because of the glob (*.c, *.sh)
-// REQUIRES: shell
-
#pragma clang __debug parser_crash
// CHECK: Preprocessed source(s) and associated run script(s) are located at:
// CHECK-NEXT: note: diagnostic msg: {{.*}}.c
diff --git a/test/Driver/crash-report.c b/test/Driver/crash-report.c
index a3f1f9e72a57..711b04ea4da0 100644
--- a/test/Driver/crash-report.c
+++ b/test/Driver/crash-report.c
@@ -1,8 +1,8 @@
// RUN: rm -rf %t
// RUN: mkdir %t
-// RUN: not env TMPDIR=%t TEMP=%t TMP=%t RC_DEBUG_OPTIONS=1 \
+// RUN: env TMPDIR=%t TEMP=%t TMP=%t RC_DEBUG_OPTIONS=1 \
// RUN: CC_PRINT_HEADERS=1 CC_LOG_DIAGNOSTICS=1 \
-// RUN: %clang -fsyntax-only %s \
+// RUN: not %clang -fsyntax-only %s \
// RUN: -F/tmp/ -I /tmp/ -idirafter /tmp/ -iquote /tmp/ -isystem /tmp/ \
// RUN: -iprefix /the/prefix -iwithprefix /tmp -iwithprefixbefore /tmp/ \
// RUN: -Xclang -internal-isystem -Xclang /tmp/ \
@@ -13,9 +13,6 @@
// RUN: cat %t/crash-report-*.sh | FileCheck --check-prefix=CHECKSH %s
// REQUIRES: crash-recovery
-// because of the glob (*.c, *.sh)
-// REQUIRES: shell
-
#pragma clang __debug parser_crash
// CHECK: Preprocessed source(s) and associated run script(s) are located at:
// CHECK-NEXT: note: diagnostic msg: {{.*}}crash-report-{{.*}}.c
diff --git a/test/Driver/cuda-arch-translation.cu b/test/Driver/cuda-arch-translation.cu
index a26d3740ff16..49b87e7b4fb8 100644
--- a/test/Driver/cuda-arch-translation.cu
+++ b/test/Driver/cuda-arch-translation.cu
@@ -31,6 +31,32 @@
// RUN: | FileCheck -check-prefixes=COMMON,SM62 %s
// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_70 %s 2>&1 \
// RUN: | FileCheck -check-prefixes=COMMON,SM70 %s
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx600 %s 2>&1 \
+// RUN: | FileCheck -check-prefixes=COMMON,GFX600 %s
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx601 %s 2>&1 \
+// RUN: | FileCheck -check-prefixes=COMMON,GFX601 %s
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx700 %s 2>&1 \
+// RUN: | FileCheck -check-prefixes=COMMON,GFX700 %s
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx701 %s 2>&1 \
+// RUN: | FileCheck -check-prefixes=COMMON,GFX701 %s
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx702 %s 2>&1 \
+// RUN: | FileCheck -check-prefixes=COMMON,GFX702 %s
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx703 %s 2>&1 \
+// RUN: | FileCheck -check-prefixes=COMMON,GFX703 %s
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx704 %s 2>&1 \
+// RUN: | FileCheck -check-prefixes=COMMON,GFX704 %s
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx801 %s 2>&1 \
+// RUN: | FileCheck -check-prefixes=COMMON,GFX801 %s
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx802 %s 2>&1 \
+// RUN: | FileCheck -check-prefixes=COMMON,GFX802 %s
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx803 %s 2>&1 \
+// RUN: | FileCheck -check-prefixes=COMMON,GFX803 %s
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx810 %s 2>&1 \
+// RUN: | FileCheck -check-prefixes=COMMON,GFX810 %s
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx900 %s 2>&1 \
+// RUN: | FileCheck -check-prefixes=COMMON,GFX900 %s
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx902 %s 2>&1 \
+// RUN: | FileCheck -check-prefixes=COMMON,GFX902 %s
// COMMON: ptxas
// COMMON-SAME: -m64
@@ -49,3 +75,16 @@
// SM61:--image=profile=sm_61{{.*}}--image=profile=compute_61
// SM62:--image=profile=sm_62{{.*}}--image=profile=compute_62
// SM70:--image=profile=sm_70{{.*}}--image=profile=compute_70
+// GFX600:--image=profile=gfx600{{.*}}--image=profile=compute_amdgcn
+// GFX601:--image=profile=gfx601{{.*}}--image=profile=compute_amdgcn
+// GFX700:--image=profile=gfx700{{.*}}--image=profile=compute_amdgcn
+// GFX701:--image=profile=gfx701{{.*}}--image=profile=compute_amdgcn
+// GFX702:--image=profile=gfx702{{.*}}--image=profile=compute_amdgcn
+// GFX703:--image=profile=gfx703{{.*}}--image=profile=compute_amdgcn
+// GFX704:--image=profile=gfx704{{.*}}--image=profile=compute_amdgcn
+// GFX801:--image=profile=gfx801{{.*}}--image=profile=compute_amdgcn
+// GFX802:--image=profile=gfx802{{.*}}--image=profile=compute_amdgcn
+// GFX803:--image=profile=gfx803{{.*}}--image=profile=compute_amdgcn
+// GFX810:--image=profile=gfx810{{.*}}--image=profile=compute_amdgcn
+// GFX900:--image=profile=gfx900{{.*}}--image=profile=compute_amdgcn
+// GFX902:--image=profile=gfx902{{.*}}--image=profile=compute_amdgcn
diff --git a/test/Driver/cuda-bad-arch.cu b/test/Driver/cuda-bad-arch.cu
index a6559b0c7810..00d955233bea 100644
--- a/test/Driver/cuda-bad-arch.cu
+++ b/test/Driver/cuda-bad-arch.cu
@@ -2,6 +2,7 @@
// REQUIRES: clang-driver
// REQUIRES: x86-registered-target
// REQUIRES: nvptx-registered-target
+// REQUIRES: amdgpu-registered-target
// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=compute_20 -c %s 2>&1 \
// RUN: | FileCheck -check-prefix BAD %s
@@ -25,9 +26,12 @@
// RUN: %clang -### -target x86_64-linux-gnu -c %s 2>&1 \
// RUN: | FileCheck -check-prefix OK %s
-// We don't allow using NVPTX for host compilation.
+// We don't allow using NVPTX/AMDGCN for host compilation.
// RUN: %clang -### --cuda-host-only -target nvptx-nvidia-cuda -c %s 2>&1 \
// RUN: | FileCheck -check-prefix HOST_NVPTX %s
+// RUN: %clang -### --cuda-host-only -target amdgcn-amd-amdhsa -c %s 2>&1 \
+// RUN: | FileCheck -check-prefix HOST_AMDGCN %s
// OK-NOT: error: Unsupported CUDA gpu architecture
-// HOST_NVPTX: error: unsupported use of NVPTX for host compilation.
+// HOST_NVPTX: error: unsupported architecture 'nvptx' for host compilation.
+// HOST_AMDGCN: error: unsupported architecture 'amdgcn' for host compilation.
diff --git a/test/Driver/cuda-detect-path.cu b/test/Driver/cuda-detect-path.cu
new file mode 100644
index 000000000000..61b9400760c2
--- /dev/null
+++ b/test/Driver/cuda-detect-path.cu
@@ -0,0 +1,83 @@
+// REQUIRES: clang-driver
+// REQUIRES: x86-registered-target
+// REQUIRES: nvptx-registered-target
+// This tests uses the PATH environment variable.
+// REQUIRES: !system-windows
+
+// RUN: env PATH=%S/Inputs/CUDA/usr/local/cuda/bin \
+// RUN: %clang -v --target=i386-unknown-linux --sysroot=%S/no-cuda-there \
+// RUN: 2>&1 | FileCheck %s
+// RUN: env PATH=%S/Inputs/CUDA/usr/local/cuda/bin \
+// RUN: %clang -v --target=i386-apple-macosx --sysroot=%S/no-cuda-there \
+// RUN: 2>&1 | FileCheck %s
+// RUN: env PATH=%S/Inputs/CUDA/usr/local/cuda/bin \
+// RUN: %clang -v --target=x86_64-unknown-linux --sysroot=%S/no-cuda-there \
+// RUN: 2>&1 | FileCheck %s
+// RUN: env PATH=%S/Inputs/CUDA/usr/local/cuda/bin \
+// RUN: %clang -v --target=x86_64-apple-macosx --sysroot=%S/no-cuda-there \
+// RUN: 2>&1 | FileCheck %s
+
+
+// Check that we follow ptxas binaries that are symlinks.
+// RUN: env PATH=%S/Inputs/CUDA-symlinks/usr/bin \
+// RUN: %clang -v --target=i386-unknown-linux --sysroot=%S/no-cuda-there \
+// RUN: 2>&1 | FileCheck %s --check-prefix SYMLINKS
+// RUN: env PATH=%S/Inputs/CUDA-symlinks/usr/bin \
+// RUN: %clang -v --target=i386-apple-macosx --sysroot=%S/no-cuda-there \
+// RUN: 2>&1 | FileCheck %s --check-prefix SYMLINKS
+// RUN: env PATH=%S/Inputs/CUDA-symlinks/usr/bin \
+// RUN: %clang -v --target=x86_64-unknown-linux --sysroot=%S/no-cuda-there \
+// RUN: 2>&1 | FileCheck %s --check-prefix SYMLINKS
+// RUN: env PATH=%S/Inputs/CUDA-symlinks/usr/bin \
+// RUN: %clang -v --target=x86_64-apple-macosx --sysroot=%S/no-cuda-there \
+// RUN: 2>&1 | FileCheck %s --check-prefix SYMLINKS
+
+
+// We only take a CUDA installation from PATH if it contains libdevice.
+// RUN: env PATH=%S/Inputs/CUDA-nolibdevice/usr/local/cuda/bin \
+// RUN: %clang -v --target=i386-unknown-linux --sysroot=%S/no-cuda-there \
+// RUN: 2>&1 | FileCheck %s --check-prefix NOCUDA
+// RUN: env PATH=%S/Inputs/CUDA-nolibdevice/usr/local/cuda/bin \
+// RUN: %clang -v --target=i386-apple-macosx --sysroot=%S/no-cuda-there \
+// RUN: 2>&1 | FileCheck %s --check-prefix NOCUDA
+// RUN: env PATH=%S/Inputs/CUDA-nolibdevice/usr/local/cuda/bin \
+// RUN: %clang -v --target=x86_64-unknown-linux --sysroot=%S/no-cuda-there \
+// RUN: 2>&1 | FileCheck %s --check-prefix NOCUDA
+// RUN: env PATH=%S/Inputs/CUDA-nolibdevice/usr/local/cuda/bin \
+// RUN: %clang -v --target=x86_64-apple-macosx --sysroot=%S/no-cuda-there \
+// RUN: 2>&1 | FileCheck %s --check-prefix NOCUDA
+
+// We even require libdevice if -nocudalib is passed to avoid false positives
+// if the distribution merges CUDA into /usr and ptxas ends up /usr/bin.
+// RUN: env PATH=%S/Inputs/CUDA-nolibdevice/usr/local/cuda/bin \
+// RUN: %clang -v --target=i386-unknown-linux --sysroot=%S/no-cuda-there -nocudalib \
+// RUN: 2>&1 | FileCheck %s --check-prefix NOCUDA
+// RUN: env PATH=%S/Inputs/CUDA-nolibdevice/usr/local/cuda/bin \
+// RUN: %clang -v --target=i386-apple-macosx --sysroot=%S/no-cuda-there -nocudalib \
+// RUN: 2>&1 | FileCheck %s --check-prefix NOCUDA
+// RUN: env PATH=%S/Inputs/CUDA-nolibdevice/usr/local/cuda/bin \
+// RUN: %clang -v --target=x86_64-unknown-linux --sysroot=%S/no-cuda-there -nocudalib \
+// RUN: 2>&1 | FileCheck %s --check-prefix NOCUDA
+// RUN: env PATH=%S/Inputs/CUDA-nolibdevice/usr/local/cuda/bin \
+// RUN: %clang -v --target=x86_64-apple-macosx --sysroot=%S/no-cuda-there -nocudalib \
+// RUN: 2>&1 | FileCheck %s --check-prefix NOCUDA
+
+
+// Check that the CUDA installation in PATH is not taken when passing
+// the option --cuda-path-ignore-env.
+// RUN: env PATH=%S/Inputs/CUDA/usr/local/cuda/bin \
+// RUN: %clang -v --target=i386-unknown-linux --sysroot=%S/no-cuda-there --cuda-path-ignore-env \
+// RUN: 2>&1 | FileCheck %s --check-prefix NOCUDA
+// RUN: env PATH=%S/Inputs/CUDA/usr/local/cuda/bin \
+// RUN: %clang -v --target=i386-apple-macosx --sysroot=%S/no-cuda-there --cuda-path-ignore-env \
+// RUN: 2>&1 | FileCheck %s --check-prefix NOCUDA
+// RUN: env PATH=%S/Inputs/CUDA/usr/local/cuda/bin \
+// RUN: %clang -v --target=x86_64-unknown-linux --sysroot=%S/no-cuda-there --cuda-path-ignore-env \
+// RUN: 2>&1 | FileCheck %s --check-prefix NOCUDA
+// RUN: env PATH=%S/Inputs/CUDA/usr/local/cuda/bin \
+// RUN: %clang -v --target=x86_64-apple-macosx --sysroot=%S/no-cuda-there --cuda-path-ignore-env \
+// RUN: 2>&1 | FileCheck %s --check-prefix NOCUDA
+
+// CHECK: Found CUDA installation: {{.*}}/Inputs/CUDA/usr/local/cuda
+// SYMLINKS: Found CUDA installation: {{.*}}/Inputs/CUDA-symlinks/opt/cuda
+// NOCUDA-NOT: Found CUDA installation:
diff --git a/test/Driver/cuda-detect.cu b/test/Driver/cuda-detect.cu
index 1db0cfbfa3ce..f086ba4c42e3 100644
--- a/test/Driver/cuda-detect.cu
+++ b/test/Driver/cuda-detect.cu
@@ -4,9 +4,14 @@
//
// Check that we properly detect CUDA installation.
// RUN: %clang -v --target=i386-unknown-linux \
-// RUN: --sysroot=%S/no-cuda-there 2>&1 | FileCheck %s -check-prefix NOCUDA
+// RUN: --sysroot=%S/no-cuda-there --cuda-path-ignore-env 2>&1 | FileCheck %s -check-prefix NOCUDA
// RUN: %clang -v --target=i386-apple-macosx \
-// RUN: --sysroot=%S/no-cuda-there 2>&1 | FileCheck %s -check-prefix NOCUDA
+// RUN: --sysroot=%S/no-cuda-there --cuda-path-ignore-env 2>&1 | FileCheck %s -check-prefix NOCUDA
+// RUN: %clang -v --target=x86_64-unknown-linux \
+// RUN: --sysroot=%S/no-cuda-there --cuda-path-ignore-env 2>&1 | FileCheck %s -check-prefix NOCUDA
+// RUN: %clang -v --target=x86_64-apple-macosx \
+// RUN: --sysroot=%S/no-cuda-there --cuda-path-ignore-env 2>&1 | FileCheck %s -check-prefix NOCUDA
+
// RUN: %clang -v --target=i386-unknown-linux \
// RUN: --sysroot=%S/Inputs/CUDA 2>&1 | FileCheck %s
@@ -20,15 +25,23 @@
// Check that we don't find a CUDA installation without libdevice ...
// RUN: %clang -v --target=i386-unknown-linux \
-// RUN: --sysroot=%S/Inputs/CUDA-nolibdevice 2>&1 | FileCheck %s -check-prefix NOCUDA
+// RUN: --sysroot=%S/Inputs/CUDA-nolibdevice --cuda-path-ignore-env 2>&1 | FileCheck %s -check-prefix NOCUDA
// RUN: %clang -v --target=i386-apple-macosx \
-// RUN: --sysroot=%S/Inputs/CUDA-nolibdevice 2>&1 | FileCheck %s -check-prefix NOCUDA
+// RUN: --sysroot=%S/Inputs/CUDA-nolibdevice --cuda-path-ignore-env 2>&1 | FileCheck %s -check-prefix NOCUDA
+// RUN: %clang -v --target=x86_64-unknown-linux \
+// RUN: --sysroot=%S/Inputs/CUDA-nolibdevice --cuda-path-ignore-env 2>&1 | FileCheck %s -check-prefix NOCUDA
+// RUN: %clang -v --target=x84_64-apple-macosx \
+// RUN: --sysroot=%S/Inputs/CUDA-nolibdevice --cuda-path-ignore-env 2>&1 | FileCheck %s -check-prefix NOCUDA
// ... unless the user doesn't need libdevice
// RUN: %clang -v --target=i386-unknown-linux -nocudalib \
-// RUN: --sysroot=%S/Inputs/CUDA-nolibdevice 2>&1 | FileCheck %s -check-prefix NO-LIBDEVICE
+// RUN: --sysroot=%S/Inputs/CUDA-nolibdevice --cuda-path-ignore-env 2>&1 | FileCheck %s -check-prefix NO-LIBDEVICE
// RUN: %clang -v --target=i386-apple-macosx -nocudalib \
-// RUN: --sysroot=%S/Inputs/CUDA-nolibdevice 2>&1 | FileCheck %s -check-prefix NO-LIBDEVICE
+// RUN: --sysroot=%S/Inputs/CUDA-nolibdevice --cuda-path-ignore-env 2>&1 | FileCheck %s -check-prefix NO-LIBDEVICE
+// RUN: %clang -v --target=x86_64-unknown-linux -nocudalib \
+// RUN: --sysroot=%S/Inputs/CUDA-nolibdevice --cuda-path-ignore-env 2>&1 | FileCheck %s -check-prefix NO-LIBDEVICE
+// RUN: %clang -v --target=x86_64-apple-macosx -nocudalib \
+// RUN: --sysroot=%S/Inputs/CUDA-nolibdevice --cuda-path-ignore-env 2>&1 | FileCheck %s -check-prefix NO-LIBDEVICE
// Make sure we map libdevice bitcode files to proper GPUs. These
diff --git a/test/Driver/cuda-dwarf-2.cu b/test/Driver/cuda-dwarf-2.cu
new file mode 100644
index 000000000000..b6c7f500f5ca
--- /dev/null
+++ b/test/Driver/cuda-dwarf-2.cu
@@ -0,0 +1,47 @@
+// REQUIRES: clang-driver
+//
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 %s -g -O0 --no-cuda-noopt-device-debug 2>&1 | \
+// RUN: FileCheck %s -check-prefix NO_DEBUG
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 %s -g -O3 2>&1 | \
+// RUN: FileCheck %s -check-prefix NO_DEBUG
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 %s -g -O3 --no-cuda-noopt-device-debug 2>&1 | \
+// RUN: FileCheck %s -check-prefix NO_DEBUG
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 %s -g0 2>&1 | \
+// RUN: FileCheck %s -check-prefix NO_DEBUG
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 %s -ggdb0 -O3 --cuda-noopt-device-debug 2>&1 | \
+// RUN: FileCheck %s -check-prefix NO_DEBUG
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 %s -ggdb1 2>&1 | \
+// RUN: FileCheck %s -check-prefix NO_DEBUG -check-prefix LINE_TABLE
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 %s -gline-tables-only -O2 --cuda-noopt-device-debug 2>&1 | \
+// RUN: FileCheck %s -check-prefix NO_DEBUG -check-prefix LINE_TABLE
+
+// NO_DEBUG: ptxas
+// NO_DEBUG-NOT: "-g"
+// LINE_TABLE: "-lineinfo"
+// NO_DEBUG: fatbinary
+// NO_DEBUG-NOT: "-g"
+
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 %s -g 2>&1 | \
+// RUN: FileCheck %s -check-prefix HAS_DEBUG
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 %s -g -O0 --cuda-noopt-device-debug 2>&1 | \
+// RUN: FileCheck %s -check-prefix HAS_DEBUG
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 %s -g -O3 --cuda-noopt-device-debug 2>&1 | \
+// RUN: FileCheck %s -check-prefix HAS_DEBUG
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 %s -g2 2>&1 | \
+// RUN: FileCheck %s -check-prefix HAS_DEBUG
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 %s -ggdb2 -O0 2>&1 | \
+// RUN: FileCheck %s -check-prefix HAS_DEBUG
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 %s -g3 -O2 --cuda-noopt-device-debug 2>&1 | \
+// RUN: FileCheck %s -check-prefix HAS_DEBUG
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 %s -ggdb3 -O3 --cuda-noopt-device-debug 2>&1 | \
+// RUN: FileCheck %s -check-prefix HAS_DEBUG
+
+// HAS_DEBUG: "-fcuda-is-device"
+// HAS_DEBUG-SAME: "-dwarf-version=2"
+// HAS_DEBUG: ptxas
+// HAS_DEBUG-SAME: "-g"
+// HAS_DEBUG-SAME: "--dont-merge-basicblocks"
+// HAS_DEBUG-SAME: "--return-at-end"
+// HAS_DEBUG: fatbinary
+// HAS_DEBUG-SAME: "-g"
+
diff --git a/test/Driver/cuda-external-tools.cu b/test/Driver/cuda-external-tools.cu
index 63b74fc06b9b..367c6997ea87 100644
--- a/test/Driver/cuda-external-tools.cu
+++ b/test/Driver/cuda-external-tools.cu
@@ -7,112 +7,141 @@
// Regular compiles with -O{0,1,2,3,4,fast}. -O4 and -Ofast map to ptxas O3.
// RUN: %clang -### -target x86_64-linux-gnu -O0 -c %s 2>&1 \
-// RUN: | FileCheck -check-prefix ARCH64 -check-prefix SM20 -check-prefix OPT0 %s
+// RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM20,OPT0 %s
// RUN: %clang -### -target x86_64-linux-gnu -O1 -c %s 2>&1 \
-// RUN: | FileCheck -check-prefix ARCH64 -check-prefix SM20 -check-prefix OPT1 %s
+// RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM20,OPT1 %s
// RUN: %clang -### -target x86_64-linux-gnu -O2 -c %s 2>&1 \
-// RUN: | FileCheck -check-prefix ARCH64 -check-prefix SM20 -check-prefix OPT2 %s
+// RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM20,OPT2 %s
// RUN: %clang -### -target x86_64-linux-gnu -O3 -c %s 2>&1 \
-// RUN: | FileCheck -check-prefix ARCH64 -check-prefix SM20 -check-prefix OPT3 %s
+// RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM20,OPT3 %s
// RUN: %clang -### -target x86_64-linux-gnu -O4 -c %s 2>&1 \
-// RUN: | FileCheck -check-prefix ARCH64 -check-prefix SM20 -check-prefix OPT3 %s
+// RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM20,OPT3 %s
// RUN: %clang -### -target x86_64-linux-gnu -Ofast -c %s 2>&1 \
-// RUN: | FileCheck -check-prefix ARCH64 -check-prefix SM20 -check-prefix OPT3 %s
+// RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM20,OPT3 %s
+// Generating relocatable device code
+// RUN: %clang -### -target x86_64-linux-gnu -fcuda-rdc -c %s 2>&1 \
+// RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM20,RDC %s
// With debugging enabled, ptxas should be run with with no ptxas optimizations.
-// RUN: %clang -### -target x86_64-linux-gnu --cuda-noopt-device-debug -O2 -c %s 2>&1 \
-// RUN: | FileCheck -check-prefix ARCH64 -check-prefix SM20 -check-prefix DBG %s
+// RUN: %clang -### -target x86_64-linux-gnu --cuda-noopt-device-debug -O2 -g -c %s 2>&1 \
+// RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM20,DBG %s
// --no-cuda-noopt-device-debug overrides --cuda-noopt-device-debug.
// RUN: %clang -### -target x86_64-linux-gnu --cuda-noopt-device-debug \
// RUN: --no-cuda-noopt-device-debug -O2 -c %s 2>&1 \
-// RUN: | FileCheck -check-prefix ARCH64 -check-prefix SM20 -check-prefix OPT2 %s
+// RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM20,OPT2 %s
// Regular compile without -O. This should result in us passing -O0 to ptxas.
// RUN: %clang -### -target x86_64-linux-gnu -c %s 2>&1 \
-// RUN: | FileCheck -check-prefix ARCH64 -check-prefix SM20 -check-prefix OPT0 %s
+// RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM20,OPT0 %s
// Regular compiles with -Os and -Oz. For lack of a better option, we map
// these to ptxas -O3.
// RUN: %clang -### -target x86_64-linux-gnu -Os -c %s 2>&1 \
-// RUN: | FileCheck -check-prefix ARCH64 -check-prefix SM20 -check-prefix OPT2 %s
+// RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM20,OPT2 %s
// RUN: %clang -### -target x86_64-linux-gnu -Oz -c %s 2>&1 \
-// RUN: | FileCheck -check-prefix ARCH64 -check-prefix SM20 -check-prefix OPT2 %s
+// RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM20,OPT2 %s
// Regular compile targeting sm_35.
// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=sm_35 -c %s 2>&1 \
-// RUN: | FileCheck -check-prefix ARCH64 -check-prefix SM35 %s
+// RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM35 %s
+// Separate compilation targeting sm_35.
+// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=sm_35 -fcuda-rdc -c %s 2>&1 \
+// RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM35,RDC %s
// 32-bit compile.
-// RUN: %clang -### -target x86_32-linux-gnu -c %s 2>&1 \
-// RUN: | FileCheck -check-prefix ARCH32 -check-prefix SM20 %s
+// RUN: %clang -### -target i386-linux-gnu -c %s 2>&1 \
+// RUN: | FileCheck -check-prefixes=CHECK,ARCH32,SM20 %s
+// 32-bit compile when generating relocatable device code.
+// RUN: %clang -### -target i386-linux-gnu -fcuda-rdc -c %s 2>&1 \
+// RUN: | FileCheck -check-prefixes=CHECK,ARCH32,SM20,RDC %s
// Compile with -fintegrated-as. This should still cause us to invoke ptxas.
// RUN: %clang -### -target x86_64-linux-gnu -fintegrated-as -c %s 2>&1 \
-// RUN: | FileCheck -check-prefix ARCH64 -check-prefix SM20 -check-prefix OPT0 %s
+// RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM20,OPT0 %s
+// Check that we still pass -c when generating relocatable device code.
+// RUN: %clang -### -target x86_64-linux-gnu -fintegrated-as -fcuda-rdc -c %s 2>&1 \
+// RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM20,RDC %s
// Check -Xcuda-ptxas and -Xcuda-fatbinary
// RUN: %clang -### -target x86_64-linux-gnu -c -Xcuda-ptxas -foo1 \
// RUN: -Xcuda-fatbinary -bar1 -Xcuda-ptxas -foo2 -Xcuda-fatbinary -bar2 %s 2>&1 \
-// RUN: | FileCheck -check-prefix SM20 -check-prefix PTXAS-EXTRA \
-// RUN: -check-prefix FATBINARY-EXTRA %s
+// RUN: | FileCheck -check-prefixes=CHECK,SM20,PTXAS-EXTRA,FATBINARY-EXTRA %s
// MacOS spot-checks
// RUN: %clang -### -target x86_64-apple-macosx -O0 -c %s 2>&1 \
-// RUN: | FileCheck -check-prefix ARCH64 -check-prefix SM20 -check-prefix OPT0 %s
+// RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM20,OPT0 %s
// RUN: %clang -### -target x86_64-apple-macosx --cuda-gpu-arch=sm_35 -c %s 2>&1 \
-// RUN: | FileCheck -check-prefix ARCH64 -check-prefix SM35 %s
-// RUN: %clang -### -target x86_32-apple-macosx -c %s 2>&1 \
-// RUN: | FileCheck -check-prefix ARCH32 -check-prefix SM20 %s
+// RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM35 %s
+// RUN: %clang -### -target i386-apple-macosx -c %s 2>&1 \
+// RUN: | FileCheck -check-prefixes=CHECK,ARCH32,SM20 %s
+
+// Check relocatable device code generation on MacOS.
+// RUN: %clang -### -target x86_64-apple-macosx -O0 -fcuda-rdc -c %s 2>&1 \
+// RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM20,RDC %s
+// RUN: %clang -### -target x86_64-apple-macosx --cuda-gpu-arch=sm_35 -fcuda-rdc -c %s 2>&1 \
+// RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM35,RDC %s
+// RUN: %clang -### -target i386-apple-macosx -fcuda-rdc -c %s 2>&1 \
+// RUN: | FileCheck -check-prefixes=CHECK,ARCH32,SM20,RDC %s
// Check that CLANG forwards the -v flag to PTXAS.
// RUN: %clang -### -save-temps -no-canonical-prefixes -v %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHK-PTXAS-VERBOSE %s
// Match clang job that produces PTX assembly.
-// CHECK: "-cc1" "-triple" "nvptx64-nvidia-cuda"
-// SM20: "-target-cpu" "sm_20"
-// SM35: "-target-cpu" "sm_35"
-// SM20: "-o" "[[PTXFILE:[^"]*]]"
-// SM35: "-o" "[[PTXFILE:[^"]*]]"
+// CHECK: "-cc1"
+// ARCH64-SAME: "-triple" "nvptx64-nvidia-cuda"
+// ARCH32-SAME: "-triple" "nvptx-nvidia-cuda"
+// SM20-SAME: "-target-cpu" "sm_20"
+// SM35-SAME: "-target-cpu" "sm_35"
+// SM20-SAME: "-o" "[[PTXFILE:[^"]*]]"
+// SM35-SAME: "-o" "[[PTXFILE:[^"]*]]"
+// RDC-SAME: "-fcuda-rdc"
+// CHECK-NOT: "-fcuda-rdc"
// Match the call to ptxas (which assembles PTX to SASS).
-// CHECK:ptxas
-// ARCH64: "-m64"
-// ARCH32: "-m32"
-// OPT0: "-O0"
+// CHECK: ptxas
+// ARCH64-SAME: "-m64"
+// ARCH32-SAME: "-m32"
+// OPT0-SAME: "-O0"
// OPT0-NOT: "-g"
-// OPT1: "-O1"
+// OPT1-SAME: "-O1"
// OPT1-NOT: "-g"
-// OPT2: "-O2"
+// OPT2-SAME: "-O2"
// OPT2-NOT: "-g"
-// OPT3: "-O3"
+// OPT3-SAME: "-O3"
// OPT3-NOT: "-g"
-// DBG: "-g" "--dont-merge-basicblocks" "--return-at-end"
-// SM20: "--gpu-name" "sm_20"
-// SM35: "--gpu-name" "sm_35"
-// SM20: "--output-file" "[[CUBINFILE:[^"]*]]"
-// SM35: "--output-file" "[[CUBINFILE:[^"]*]]"
-// PTXAS-EXTRA: "-foo1"
-// PTXAS-EXTRA-SAME: "-foo2"
+// DBG-SAME: "-g" "--dont-merge-basicblocks" "--return-at-end"
+// SM20-SAME: "--gpu-name" "sm_20"
+// SM35-SAME: "--gpu-name" "sm_35"
+// SM20-SAME: "--output-file" "[[CUBINFILE:[^"]*]]"
+// SM35-SAME: "--output-file" "[[CUBINFILE:[^"]*]]"
// CHECK-SAME: "[[PTXFILE]]"
+// PTXAS-EXTRA-SAME: "-foo1"
+// PTXAS-EXTRA-SAME: "-foo2"
+// RDC-SAME: "-c"
+// CHECK-NOT: "-c"
// Match the call to fatbinary (which combines all our PTX and SASS into one
// blob).
-// CHECK:fatbinary
-// CHECK-DAG: "--cuda"
-// ARCH64-DAG: "-64"
-// ARCH32-DAG: "-32"
+// CHECK: fatbinary
+// CHECK-SAME-DAG: "--cuda"
+// ARCH64-SAME-DAG: "-64"
+// ARCH32-SAME-DAG: "-32"
// CHECK-DAG: "--create" "[[FATBINARY:[^"]*]]"
-// SM20-DAG: "--image=profile=compute_20,file=[[PTXFILE]]"
-// SM35-DAG: "--image=profile=compute_35,file=[[PTXFILE]]"
-// SM20-DAG: "--image=profile=sm_20,file=[[CUBINFILE]]"
-// SM35-DAG: "--image=profile=sm_35,file=[[CUBINFILE]]"
-// FATBINARY-EXTRA: "-bar1"
+// SM20-SAME-DAG: "--image=profile=compute_20,file=[[PTXFILE]]"
+// SM35-SAME-DAG: "--image=profile=compute_35,file=[[PTXFILE]]"
+// SM20-SAME-DAG: "--image=profile=sm_20,file=[[CUBINFILE]]"
+// SM35-SAME-DAG: "--image=profile=sm_35,file=[[CUBINFILE]]"
+// FATBINARY-EXTRA-SAME: "-bar1"
// FATBINARY-EXTRA-SAME: "-bar2"
// Match the clang job for host compilation.
-// CHECK: "-cc1" "-triple" "x86_64--linux-gnu"
+// CHECK: "-cc1"
+// ARCH64-SAME: "-triple" "x86_64-
+// ARCH32-SAME: "-triple" "i386-
// CHECK-SAME: "-fcuda-include-gpubinary" "[[FATBINARY]]"
+// RDC-SAME: "-fcuda-rdc"
+// CHECK-NOT: "-fcuda-rdc"
-// CHK-PTXAS-VERBOSE: ptxas{{.*}}" "-v" \ No newline at end of file
+// CHK-PTXAS-VERBOSE: ptxas{{.*}}" "-v"
diff --git a/test/Driver/cuda-no-pgo-or-coverage.cu b/test/Driver/cuda-no-pgo-or-coverage.cu
new file mode 100644
index 000000000000..1bfd8f432593
--- /dev/null
+++ b/test/Driver/cuda-no-pgo-or-coverage.cu
@@ -0,0 +1,34 @@
+// Check that profiling/coverage arguments doen't get passed down to device-side
+// compilation.
+//
+// REQUIRES: clang-driver
+//
+// XRUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 \
+// XRUN: -fprofile-generate %s 2>&1 | \
+// XRUN: FileCheck --check-prefixes=CHECK,PROF %s
+//
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 \
+// RUN: -fprofile-instr-generate %s 2>&1 | \
+// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefixes=CHECK,PROF %s
+//
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 \
+// RUN: -coverage %s 2>&1 | \
+// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefixes=CHECK,GCOV %s
+//
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 \
+// RUN: -ftest-coverage %s 2>&1 | \
+// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefixes=CHECK,GCOV %s
+//
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 \
+// RUN: -fprofile-instr-generate -fcoverage-mapping %s 2>&1 | \
+// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefixes=CHECK,PROF,GCOV %s
+//
+//
+// CHECK-NOT: error: unsupported option '-fprofile
+// CHECK-NOT: error: invalid argument
+// CHECK-DAG: "-fcuda-is-device"
+// CHECK-NOT: "-f{{[^"]*coverage.*}}"
+// CHECK-NOT: "-fprofile{{[^"]*}}"
+// CHECK: "-triple" "x86_64--linux-gnu"
+// PROF-DAG: "-fprofile{{.*}}"
+// GCOV-DAG: "-f{{(coverage|emit-coverage).*}}"
diff --git a/test/Driver/cuda-not-found.cu b/test/Driver/cuda-not-found.cu
index b63623ae56c1..48cf19a424cc 100644
--- a/test/Driver/cuda-not-found.cu
+++ b/test/Driver/cuda-not-found.cu
@@ -3,10 +3,10 @@
// Check that we raise an error if we're trying to compile CUDA code but can't
// find a CUDA install, unless -nocudainc was passed.
-// RUN: %clang -### --sysroot=%s/no-cuda-there %s 2>&1 | FileCheck %s --check-prefix ERR
+// RUN: %clang -### --sysroot=%s/no-cuda-there --cuda-path-ignore-env %s 2>&1 | FileCheck %s --check-prefix ERR
// RUN: %clang -### --cuda-path=%s/no-cuda-there %s 2>&1 | FileCheck %s --check-prefix ERR
// ERR: cannot find CUDA installation
-// RUN: %clang -### -nocudainc --sysroot=%s/no-cuda-there %s 2>&1 | FileCheck %s --check-prefix OK
+// RUN: %clang -### -nocudainc --sysroot=%s/no-cuda-there --cuda-path-ignore-env %s 2>&1 | FileCheck %s --check-prefix OK
// RUN: %clang -### -nocudainc --cuda-path=%s/no-cuda-there %s 2>&1 | FileCheck %s --check-prefix OK
// OK-NOT: cannot find CUDA installation
diff --git a/test/Driver/cuda-options.cu b/test/Driver/cuda-options.cu
index c4bfda903d9e..4ffab317d16a 100644
--- a/test/Driver/cuda-options.cu
+++ b/test/Driver/cuda-options.cu
@@ -62,7 +62,7 @@
// RUN: -check-prefix HOST -check-prefix INCLUDES-DEVICE \
// RUN: -check-prefix LINK %s
-// Verify that --cuda-gpu-arch option passes the correct GPU archtecture to
+// Verify that --cuda-gpu-arch option passes the correct GPU architecture to
// device compilation.
// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=sm_30 -c %s 2>&1 \
// RUN: | FileCheck -check-prefix DEVICE -check-prefix DEVICE-NOSAVE \
@@ -73,11 +73,10 @@
// and that all results are included on the host side.
// RUN: %clang -### -target x86_64-linux-gnu \
// RUN: --cuda-gpu-arch=sm_35 --cuda-gpu-arch=sm_30 -c %s 2>&1 \
-// RUN: | FileCheck -check-prefix DEVICE -check-prefix DEVICE-NOSAVE \
-// RUN: -check-prefix DEVICE2 -check-prefix DEVICE-SM30 \
-// RUN: -check-prefix DEVICE2-SM35 -check-prefix HOST \
-// RUN: -check-prefix HOST-NOSAVE -check-prefix INCLUDES-DEVICE \
-// RUN: -check-prefix NOLINK %s
+// RUN: | FileCheck -check-prefixes DEVICE,DEVICE-NOSAVE,DEVICE2 \
+// RUN: -check-prefixes DEVICE-SM30,DEVICE2-SM35 \
+// RUN: -check-prefixes INCLUDES-DEVICE,INCLUDES-DEVICE2 \
+// RUN: -check-prefixes HOST,HOST-NOSAVE,NOLINK %s
// Verify that device-side results are passed to the correct tool when
// -save-temps is used.
@@ -93,21 +92,21 @@
// RUN: -check-prefix HOST-AS -check-prefix NOLINK %s
// Verify that --[no-]cuda-gpu-arch arguments are handled correctly.
-// a) --no-cuda-gpu-arch=X negates preceeding --cuda-gpu-arch=X
+// a) --no-cuda-gpu-arch=X negates preceding --cuda-gpu-arch=X
// RUN: %clang -### -target x86_64-linux-gnu --cuda-device-only \
// RUN: --cuda-gpu-arch=sm_35 --cuda-gpu-arch=sm_30 \
// RUN: --no-cuda-gpu-arch=sm_35 \
// RUN: -c %s 2>&1 \
// RUN: | FileCheck -check-prefixes NOARCH-SM20,ARCH-SM30,NOARCH-SM35 %s
-// b) --no-cuda-gpu-arch=X negates more than one preceeding --cuda-gpu-arch=X
+// b) --no-cuda-gpu-arch=X negates more than one preceding --cuda-gpu-arch=X
// RUN: %clang -### -target x86_64-linux-gnu --cuda-device-only \
// RUN: --cuda-gpu-arch=sm_35 --cuda-gpu-arch=sm_35 --cuda-gpu-arch=sm_30 \
// RUN: --no-cuda-gpu-arch=sm_35 \
// RUN: -c %s 2>&1 \
// RUN: | FileCheck -check-prefixes NOARCH-SM20,ARCH-SM30,NOARCH-SM35 %s
-// c) if --no-cuda-gpu-arch=X negates all preceeding --cuda-gpu-arch=X
+// c) if --no-cuda-gpu-arch=X negates all preceding --cuda-gpu-arch=X
// we default to sm_20 -- same as if no --cuda-gpu-arch were passed.
// RUN: %clang -### -target x86_64-linux-gnu --cuda-device-only \
// RUN: --cuda-gpu-arch=sm_35 --cuda-gpu-arch=sm_30 \
@@ -143,6 +142,48 @@
// RUN: -c %s 2>&1 \
// RUN: | FileCheck -check-prefix ARCHALLERROR %s
+
+// Verify that --[no-]cuda-include-ptx arguments are handled correctly.
+// a) by default we're including PTX for all GPUs.
+// RUN: %clang -### -target x86_64-linux-gnu \
+// RUN: --cuda-gpu-arch=sm_35 --cuda-gpu-arch=sm_30 \
+// RUN: -c %s 2>&1 \
+// RUN: | FileCheck -check-prefixes FATBIN-COMMON,PTX-SM35,PTX-SM30 %s
+
+// b) --no-cuda-include-ptx=all disables PTX inclusion for all GPUs
+// RUN: %clang -### -target x86_64-linux-gnu \
+// RUN: --cuda-gpu-arch=sm_35 --cuda-gpu-arch=sm_30 \
+// RUN: --no-cuda-include-ptx=all \
+// RUN: -c %s 2>&1 \
+// RUN: | FileCheck -check-prefixes FATBIN-COMMON,NOPTX-SM35,NOPTX-SM30 %s
+
+// c) --no-cuda-include-ptx=sm_XX disables PTX inclusion for that GPU only.
+// RUN: %clang -### -target x86_64-linux-gnu \
+// RUN: --cuda-gpu-arch=sm_35 --cuda-gpu-arch=sm_30 \
+// RUN: --no-cuda-include-ptx=sm_35 \
+// RUN: -c %s 2>&1 \
+// RUN: | FileCheck -check-prefixes FATBIN-COMMON,NOPTX-SM35,PTX-SM30 %s
+// RUN: %clang -### -target x86_64-linux-gnu \
+// RUN: --cuda-gpu-arch=sm_35 --cuda-gpu-arch=sm_30 \
+// RUN: --no-cuda-include-ptx=sm_30 \
+// RUN: -c %s 2>&1 \
+// RUN: | FileCheck -check-prefixes FATBIN-COMMON,PTX-SM35,NOPTX-SM30 %s
+
+// d) --cuda-include-ptx=all overrides preceding --no-cuda-include-ptx=all
+// RUN: %clang -### -target x86_64-linux-gnu \
+// RUN: --cuda-gpu-arch=sm_35 --cuda-gpu-arch=sm_30 \
+// RUN: --no-cuda-include-ptx=all --cuda-include-ptx=all \
+// RUN: -c %s 2>&1 \
+// RUN: | FileCheck -check-prefixes FATBIN-COMMON,PTX-SM35,PTX-SM30 %s
+
+// e) --cuda-include-ptx=all overrides preceding --no-cuda-include-ptx=sm_XX
+// RUN: %clang -### -target x86_64-linux-gnu \
+// RUN: --cuda-gpu-arch=sm_35 --cuda-gpu-arch=sm_30 \
+// RUN: --no-cuda-include-ptx=sm_30 --cuda-include-ptx=all \
+// RUN: -c %s 2>&1 \
+// RUN: | FileCheck -check-prefixes FATBIN-COMMON,PTX-SM35,PTX-SM30 %s
+
+
// ARCH-SM20: "-cc1"{{.*}}"-target-cpu" "sm_20"
// NOARCH-SM20-NOT: "-cc1"{{.*}}"-target-cpu" "sm_20"
// ARCH-SM30: "-cc1"{{.*}}"-target-cpu" "sm_30"
@@ -182,9 +223,15 @@
// DEVICE2-SAME: "-aux-triple" "x86_64--linux-gnu"
// DEVICE2-SAME: "-fcuda-is-device"
// DEVICE2-SM35-SAME: "-target-cpu" "sm_35"
-// DEVICE2-SAME: "-o" "[[GPUBINARY2:[^"]*]]"
+// DEVICE2-SAME: "-o" "[[PTXFILE2:[^"]*]]"
// DEVICE2-SAME: "-x" "cuda"
+// Match another call to ptxas.
+// DEVICE2: ptxas
+// DEVICE2-SM35-DAG: "--gpu-name" "sm_35"
+// DEVICE2-DAG: "--output-file" "[[CUBINFILE2:[^"]*]]"
+// DEVICE2-DAG: "[[PTXFILE2]]"
+
// Match no device-side compilation.
// NODEVICE-NOT: "-cc1" "-triple" "nvptx64-nvidia-cuda"
// NODEVICE-NOT: "-fcuda-is-device"
@@ -193,6 +240,8 @@
// INCLUDES-DEVICE-DAG: "--create" "[[FATBINARY:[^"]*]]"
// INCLUDES-DEVICE-DAG: "--image=profile=sm_{{[0-9]+}},file=[[CUBINFILE]]"
// INCLUDES-DEVICE-DAG: "--image=profile=compute_{{[0-9]+}},file=[[PTXFILE]]"
+// INCLUDES-DEVICE2-DAG: "--image=profile=sm_{{[0-9]+}},file=[[CUBINFILE2]]"
+// INCLUDES-DEVICE2-DAG: "--image=profile=compute_{{[0-9]+}},file=[[PTXFILE2]]"
// Match host-side preprocessor job with -save-temps.
// HOST-SAVE: "-cc1" "-triple" "x86_64--linux-gnu"
@@ -207,7 +256,11 @@
// HOST-SAME: "-o" "[[HOSTOUTPUT:[^"]*]]"
// HOST-NOSAVE-SAME: "-x" "cuda"
// HOST-SAVE-SAME: "-x" "cuda-cpp-output"
+// There is only one GPU binary after combining it with fatbinary!
+// INCLUDES-DEVICE2-NOT: "-fcuda-include-gpubinary"
// INCLUDES-DEVICE-SAME: "-fcuda-include-gpubinary" "[[FATBINARY]]"
+// There is only one GPU binary after combining it with fatbinary.
+// INCLUDES-DEVICE2-NOT: "-fcuda-include-gpubinary"
// Match external assembler that uses compilation output.
// HOST-AS: "-o" "{{.*}}.o" "[[HOSTOUTPUT]]"
@@ -225,3 +278,12 @@
// Match no linker.
// NOLINK-NOT: "{{.*}}{{ld|link}}{{(.exe)?}}"
+
+// FATBIN-COMMON:fatbinary
+// FATBIN-COMMON: "--create" "[[FATBINARY:[^"]*]]"
+// FATBIN-COMMON: "--image=profile=sm_30,file=
+// PTX-SM30: "--image=profile=compute_30,file=
+// NOPTX-SM30-NOT: "--image=profile=compute_30,file=
+// FATBIN-COMMON: "--image=profile=sm_35,file=
+// PTX-SM35: "--image=profile=compute_35,file=
+// NOPTX-SM35-NOT: "--image=profile=compute_35,file=
diff --git a/test/Driver/cuda-phases.cu b/test/Driver/cuda-phases.cu
index 6d5d2251ade2..e34ffa802d97 100644
--- a/test/Driver/cuda-phases.cu
+++ b/test/Driver/cuda-phases.cu
@@ -7,195 +7,267 @@
// REQUIRES: clang-driver
// REQUIRES: powerpc-registered-target
// REQUIRES: nvptx-registered-target
-
+// REQUIRES: amdgpu-registered-target
//
// Test single gpu architecture with complete compilation.
//
-// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases --cuda-gpu-arch=sm_30 %s 2>&1 \
-// RUN: | FileCheck -check-prefix=BIN %s
-// BIN-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", cuda, (host-cuda)
-// BIN-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, cuda-cpp-output, (host-cuda)
-// BIN-DAG: [[P2:[0-9]+]]: compiler, {[[P1]]}, ir, (host-cuda)
-// BIN-DAG: [[P3:[0-9]+]]: input, "{{.*}}cuda-phases.cu", cuda, (device-cuda, sm_30)
-// BIN-DAG: [[P4:[0-9]+]]: preprocessor, {[[P3]]}, cuda-cpp-output, (device-cuda, sm_30)
-// BIN-DAG: [[P5:[0-9]+]]: compiler, {[[P4]]}, ir, (device-cuda, sm_30)
-// BIN-DAG: [[P6:[0-9]+]]: backend, {[[P5]]}, assembler, (device-cuda, sm_30)
-// BIN-DAG: [[P7:[0-9]+]]: assembler, {[[P6]]}, object, (device-cuda, sm_30)
-// BIN-DAG: [[P8:[0-9]+]]: offload, "device-cuda (nvptx64-nvidia-cuda:sm_30)" {[[P7]]}, object
-// BIN-DAG: [[P9:[0-9]+]]: offload, "device-cuda (nvptx64-nvidia-cuda:sm_30)" {[[P6]]}, assembler
-// BIN-DAG: [[P10:[0-9]+]]: linker, {[[P8]], [[P9]]}, cuda-fatbin, (device-cuda)
-// BIN-DAG: [[P11:[0-9]+]]: offload, "host-cuda (powerpc64le-ibm-linux-gnu)" {[[P2]]}, "device-cuda (nvptx64-nvidia-cuda)" {[[P10]]}, ir
-// BIN-DAG: [[P12:[0-9]+]]: backend, {[[P11]]}, assembler, (host-cuda)
-// BIN-DAG: [[P13:[0-9]+]]: assembler, {[[P12]]}, object, (host-cuda)
-// BIN-DAG: [[P14:[0-9]+]]: linker, {[[P13]]}, image, (host-cuda)
+// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
+// RUN: --cuda-gpu-arch=sm_30 %s 2>&1 \
+// RUN: | FileCheck -check-prefixes=BIN,BIN_NV %s
+// RUN: %clang -x hip -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
+// RUN: --cuda-gpu-arch=gfx803 %s 2>&1 \
+// RUN: | FileCheck -check-prefixes=BIN,BIN_AMD %s
+// BIN_NV-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:cuda]], (host-[[T]])
+// BIN_AMD-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:hip]], (host-[[T]])
+// BIN-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (host-[[T]])
+// BIN-DAG: [[P2:[0-9]+]]: compiler, {[[P1]]}, ir, (host-[[T]])
+// BIN_NV-DAG: [[P3:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T]], (device-[[T]], [[ARCH:sm_30]])
+// BIN_AMD-DAG: [[P3:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T]], (device-[[T]], [[ARCH:gfx803]])
+// BIN-DAG: [[P4:[0-9]+]]: preprocessor, {[[P3]]}, [[T]]-cpp-output, (device-[[T]], [[ARCH]])
+// BIN-DAG: [[P5:[0-9]+]]: compiler, {[[P4]]}, ir, (device-[[T]], [[ARCH]])
+// BIN_NV-DAG: [[P6:[0-9]+]]: backend, {[[P5]]}, assembler, (device-[[T]], [[ARCH]])
+// BIN_NV-DAG: [[P7:[0-9]+]]: assembler, {[[P6]]}, object, (device-[[T]], [[ARCH]])
+// BIN_NV-DAG: [[P8:[0-9]+]]: offload, "device-[[T]] ([[TRIPLE:nvptx64-nvidia-cuda]]:[[ARCH]])" {[[P7]]}, object
+// BIN_NV-DAG: [[P9:[0-9]+]]: offload, "device-[[T]] ([[TRIPLE]]:[[ARCH]])" {[[P6]]}, assembler
+// BIN_NV-DAG: [[P10:[0-9]+]]: linker, {[[P8]], [[P9]]}, cuda-fatbin, (device-[[T]])
+// BIN_NV-DAG: [[P11:[0-9]+]]: offload, "host-[[T]] (powerpc64le-ibm-linux-gnu)" {[[P2]]}, "device-[[T]] ([[TRIPLE]])" {[[P10]]}, ir
+// BIN_NV-DAG: [[P12:[0-9]+]]: backend, {[[P11]]}, assembler, (host-[[T]])
+// BIN_AMD-DAG: [[P12:[0-9]+]]: backend, {[[P2]]}, assembler, (host-[[T]])
+// BIN-DAG: [[P13:[0-9]+]]: assembler, {[[P12]]}, object, (host-[[T]])
+// BIN-DAG: [[P14:[0-9]+]]: linker, {[[P13]]}, image, (host-[[T]])
+// BIN_AMD-DAG: [[P15:[0-9]+]]: linker, {[[P5]]}, image, (device-[[T]], [[ARCH]])
+// BIN_AMD-DAG: [[P16:[0-9]+]]: offload, "host-[[T]] (powerpc64le-ibm-linux-gnu)" {[[P14]]},
+// BIN_AMD-DAG-SAME: "device-[[T]] ([[TRIPLE:amdgcn-amd-amdhsa]]:[[ARCH]])" {[[P15]]}, object
//
// Test single gpu architecture up to the assemble phase.
//
-// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases --cuda-gpu-arch=sm_30 %s -S 2>&1 \
-// RUN: | FileCheck -check-prefix=ASM %s
-// ASM-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", cuda, (device-cuda, sm_30)
-// ASM-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, cuda-cpp-output, (device-cuda, sm_30)
-// ASM-DAG: [[P2:[0-9]+]]: compiler, {[[P1]]}, ir, (device-cuda, sm_30)
-// ASM-DAG: [[P3:[0-9]+]]: backend, {[[P2]]}, assembler, (device-cuda, sm_30)
-// ASM-DAG: [[P4:[0-9]+]]: offload, "device-cuda (nvptx64-nvidia-cuda:sm_30)" {[[P3]]}, assembler
-// ASM-DAG: [[P5:[0-9]+]]: input, "{{.*}}cuda-phases.cu", cuda, (host-cuda)
-// ASM-DAG: [[P6:[0-9]+]]: preprocessor, {[[P5]]}, cuda-cpp-output, (host-cuda)
-// ASM-DAG: [[P7:[0-9]+]]: compiler, {[[P6]]}, ir, (host-cuda)
-// ASM-DAG: [[P8:[0-9]+]]: backend, {[[P7]]}, assembler, (host-cuda)
+// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
+// RUN: --cuda-gpu-arch=sm_30 %s -S 2>&1 \
+// RUN: | FileCheck -check-prefixes=ASM,ASM_NV %s
+// RUN: %clang -x hip -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
+// RUN: --cuda-gpu-arch=gfx803 %s -S 2>&1 \
+// RUN: | FileCheck -check-prefixes=ASM,ASM_AMD %s
+// ASM_NV-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:cuda]], (device-[[T]], [[ARCH:sm_30]])
+// ASM_AMD-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:hip]], (device-[[T]], [[ARCH:gfx803]])
+// ASM-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (device-[[T]], [[ARCH]])
+// ASM-DAG: [[P2:[0-9]+]]: compiler, {[[P1]]}, ir, (device-[[T]], [[ARCH]])
+// ASM_NV-DAG: [[P3:[0-9]+]]: backend, {[[P2]]}, assembler, (device-[[T]], [[ARCH]])
+// ASM_NV-DAG: [[P4:[0-9]+]]: offload, "device-[[T]] ([[TRIPLE:nvptx64-nvidia-cuda|amdgcn-amd-amdhsa]]:[[ARCH]])" {[[P3]]}, assembler
+// ASM-DAG: [[P5:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T]], (host-[[T]])
+// ASM-DAG: [[P6:[0-9]+]]: preprocessor, {[[P5]]}, [[T]]-cpp-output, (host-[[T]])
+// ASM-DAG: [[P7:[0-9]+]]: compiler, {[[P6]]}, ir, (host-[[T]])
+// ASM-DAG: [[P8:[0-9]+]]: backend, {[[P7]]}, assembler, (host-[[T]])
//
// Test two gpu architectures with complete compilation.
//
-// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases --cuda-gpu-arch=sm_30 --cuda-gpu-arch=sm_35 %s 2>&1 \
-// RUN: | FileCheck -check-prefix=BIN2 %s
-// BIN2-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", cuda, (host-cuda)
-// BIN2-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, cuda-cpp-output, (host-cuda)
-// BIN2-DAG: [[P2:[0-9]+]]: compiler, {[[P1]]}, ir, (host-cuda)
-// BIN2-DAG: [[P3:[0-9]+]]: input, "{{.*}}cuda-phases.cu", cuda, (device-cuda, sm_30)
-// BIN2-DAG: [[P4:[0-9]+]]: preprocessor, {[[P3]]}, cuda-cpp-output, (device-cuda, sm_30)
-// BIN2-DAG: [[P5:[0-9]+]]: compiler, {[[P4]]}, ir, (device-cuda, sm_30)
-// BIN2-DAG: [[P6:[0-9]+]]: backend, {[[P5]]}, assembler, (device-cuda, sm_30)
-// BIN2-DAG: [[P7:[0-9]+]]: assembler, {[[P6]]}, object, (device-cuda, sm_30)
-// BIN2-DAG: [[P8:[0-9]+]]: offload, "device-cuda (nvptx64-nvidia-cuda:sm_30)" {[[P7]]}, object
-// BIN2-DAG: [[P9:[0-9]+]]: offload, "device-cuda (nvptx64-nvidia-cuda:sm_30)" {[[P6]]}, assembler
-// BIN2-DAG: [[P10:[0-9]+]]: input, "{{.*}}cuda-phases.cu", cuda, (device-cuda, sm_35)
-// BIN2-DAG: [[P11:[0-9]+]]: preprocessor, {[[P10]]}, cuda-cpp-output, (device-cuda, sm_35)
-// BIN2-DAG: [[P12:[0-9]+]]: compiler, {[[P11]]}, ir, (device-cuda, sm_35)
-// BIN2-DAG: [[P13:[0-9]+]]: backend, {[[P12]]}, assembler, (device-cuda, sm_35)
-// BIN2-DAG: [[P14:[0-9]+]]: assembler, {[[P13]]}, object, (device-cuda, sm_35)
-// BIN2-DAG: [[P15:[0-9]+]]: offload, "device-cuda (nvptx64-nvidia-cuda:sm_35)" {[[P14]]}, object
-// BIN2-DAG: [[P16:[0-9]+]]: offload, "device-cuda (nvptx64-nvidia-cuda:sm_35)" {[[P13]]}, assembler
-// BIN2-DAG: [[P17:[0-9]+]]: linker, {[[P8]], [[P9]], [[P15]], [[P16]]}, cuda-fatbin, (device-cuda)
-// BIN2-DAG: [[P18:[0-9]+]]: offload, "host-cuda (powerpc64le-ibm-linux-gnu)" {[[P2]]}, "device-cuda (nvptx64-nvidia-cuda)" {[[P17]]}, ir
-// BIN2-DAG: [[P19:[0-9]+]]: backend, {[[P18]]}, assembler, (host-cuda)
-// BIN2-DAG: [[P20:[0-9]+]]: assembler, {[[P19]]}, object, (host-cuda)
-// BIN2-DAG: [[P21:[0-9]+]]: linker, {[[P20]]}, image, (host-cuda)
+// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
+// RUN: --cuda-gpu-arch=sm_30 --cuda-gpu-arch=sm_35 %s 2>&1 \
+// RUN: | FileCheck -check-prefixes=BIN2,BIN2_NV %s
+// RUN: %clang -x hip -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
+// RUN: --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s 2>&1 \
+// RUN: | FileCheck -check-prefixes=BIN2,BIN2_AMD %s
+// BIN2_NV-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:cuda]], (host-[[T]])
+// BIN2_AMD-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:hip]], (host-[[T]])
+// BIN2-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (host-[[T]])
+// BIN2-DAG: [[P2:[0-9]+]]: compiler, {[[P1]]}, ir, (host-[[T]])
+// BIN2-DAG: [[P3:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T]], (device-[[T]], [[ARCH1:sm_30|gfx803]])
+// BIN2-DAG: [[P4:[0-9]+]]: preprocessor, {[[P3]]}, [[T]]-cpp-output, (device-[[T]], [[ARCH1]])
+// BIN2-DAG: [[P5:[0-9]+]]: compiler, {[[P4]]}, ir, (device-[[T]], [[ARCH1]])
+// BIN2_NV-DAG: [[P6:[0-9]+]]: backend, {[[P5]]}, assembler, (device-[[T]], [[ARCH1]])
+// BIN2_NV-DAG: [[P7:[0-9]+]]: assembler, {[[P6]]}, object, (device-[[T]], [[ARCH1]])
+// BIN2_NV-DAG: [[P8:[0-9]+]]: offload, "device-[[T]] ([[TRIPLE:nvptx64-nvidia-cuda]]:[[ARCH1]])" {[[P7]]}, object
+// BIN2_NV-DAG: [[P9:[0-9]+]]: offload, "device-[[T]] ([[TRIPLE]]:[[ARCH1]])" {[[P6]]}, assembler
+// BIN2-DAG: [[P10:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T]], (device-[[T]], [[ARCH2:sm_35|gfx900]])
+// BIN2-DAG: [[P11:[0-9]+]]: preprocessor, {[[P10]]}, [[T]]-cpp-output, (device-[[T]], [[ARCH2]])
+// BIN2-DAG: [[P12:[0-9]+]]: compiler, {[[P11]]}, ir, (device-[[T]], [[ARCH2]])
+// BIN2_NV-DAG: [[P13:[0-9]+]]: backend, {[[P12]]}, assembler, (device-[[T]], [[ARCH2]])
+// BIN2_NV-DAG: [[P14:[0-9]+]]: assembler, {[[P13]]}, object, (device-[[T]], [[ARCH2]])
+// BIN2_NV-DAG: [[P15:[0-9]+]]: offload, "device-[[T]] ([[TRIPLE]]:[[ARCH2]])" {[[P14]]}, object
+// BIN2_NV-DAG: [[P16:[0-9]+]]: offload, "device-[[T]] ([[TRIPLE]]:[[ARCH2]])" {[[P13]]}, assembler
+// BIN2_NV-DAG: [[P17:[0-9]+]]: linker, {[[P8]], [[P9]], [[P15]], [[P16]]}, cuda-fatbin, (device-[[T]])
+// BIN2_NV-DAG: [[P18:[0-9]+]]: offload, "host-[[T]] (powerpc64le-ibm-linux-gnu)" {[[P2]]}, "device-[[T]] ([[TRIPLE]])" {[[P17]]}, ir
+// BIN2_NV-DAG: [[P19:[0-9]+]]: backend, {[[P18]]}, assembler, (host-[[T]])
+// BIN2_AMD-DAG: [[P19:[0-9]+]]: backend, {[[P2]]}, assembler, (host-[[T]])
+// BIN2-DAG: [[P20:[0-9]+]]: assembler, {[[P19]]}, object, (host-[[T]])
+// BIN2-DAG: [[P21:[0-9]+]]: linker, {[[P20]]}, image, (host-[[T]])
+// BIN2_AMD-DAG: [[P22:[0-9]+]]: linker, {[[P5]]}, image, (device-[[T]], [[ARCH1]])
+// BIN2_AMD-DAG: [[P23:[0-9]+]]: linker, {[[P12]]}, image, (device-[[T]], [[ARCH2]])
+// BIN2_AMD-DAG: [[P24:[0-9]+]]: offload, "host-[[T]] (powerpc64le-ibm-linux-gnu)" {[[P21]]},
+// BIN2_AMD-DAG-SAME: "device-[[T]] ([[TRIPLE:amdgcn-amd-amdhsa]]:[[ARCH1]])" {[[P22]]},
+// BIN2_AMD-DAG-SAME: "device-[[T]] ([[TRIPLE:amdgcn-amd-amdhsa]]:[[ARCH2]])" {[[P23]]}, object
//
// Test two gpu architecturess up to the assemble phase.
//
-// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases --cuda-gpu-arch=sm_30 --cuda-gpu-arch=sm_35 %s -S 2>&1 \
-// RUN: | FileCheck -check-prefix=ASM2 %s
-// ASM2-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", cuda, (device-cuda, sm_30)
-// ASM2-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, cuda-cpp-output, (device-cuda, sm_30)
-// ASM2-DAG: [[P2:[0-9]+]]: compiler, {[[P1]]}, ir, (device-cuda, sm_30)
-// ASM2-DAG: [[P3:[0-9]+]]: backend, {[[P2]]}, assembler, (device-cuda, sm_30)
-// ASM2-DAG: [[P4:[0-9]+]]: offload, "device-cuda (nvptx64-nvidia-cuda:sm_30)" {[[P3]]}, assembler
-// ASM2-DAG: [[P5:[0-9]+]]: input, "{{.*}}cuda-phases.cu", cuda, (device-cuda, sm_35)
-// ASM2-DAG: [[P6:[0-9]+]]: preprocessor, {[[P5]]}, cuda-cpp-output, (device-cuda, sm_35)
-// ASM2-DAG: [[P7:[0-9]+]]: compiler, {[[P6]]}, ir, (device-cuda, sm_35)
-// ASM2-DAG: [[P8:[0-9]+]]: backend, {[[P7]]}, assembler, (device-cuda, sm_35)
-// ASM2-DAG: [[P9:[0-9]+]]: offload, "device-cuda (nvptx64-nvidia-cuda:sm_35)" {[[P8]]}, assembler
-// ASM2-DAG: [[P10:[0-9]+]]: input, "{{.*}}cuda-phases.cu", cuda, (host-cuda)
-// ASM2-DAG: [[P11:[0-9]+]]: preprocessor, {[[P10]]}, cuda-cpp-output, (host-cuda)
-// ASM2-DAG: [[P12:[0-9]+]]: compiler, {[[P11]]}, ir, (host-cuda)
-// ASM2-DAG: [[P13:[0-9]+]]: backend, {[[P12]]}, assembler, (host-cuda)
+// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
+// RUN: --cuda-gpu-arch=sm_30 --cuda-gpu-arch=sm_35 %s -S 2>&1 \
+// RUN: | FileCheck -check-prefixes=ASM2,ASM2_NV %s
+// RUN: %clang -x hip -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
+// RUN: --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s -S 2>&1 \
+// RUN: | FileCheck -check-prefixes=ASM2,ASM2_AMD %s
+// ASM2_NV-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:cuda]], (device-[[T]], [[ARCH1:sm_30]])
+// ASM2_AMD-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:hip]], (device-[[T]], [[ARCH1:gfx803]])
+// ASM2-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (device-[[T]], [[ARCH1]])
+// ASM2-DAG: [[P2:[0-9]+]]: compiler, {[[P1]]}, ir, (device-[[T]], [[ARCH1]])
+// ASM2_NV-DAG: [[P3:[0-9]+]]: backend, {[[P2]]}, assembler, (device-[[T]], [[ARCH1]])
+// ASM2_NV-DAG: [[P4:[0-9]+]]: offload, "device-[[T]] ([[TRIPLE:nvptx64-nvidia-cuda|amdgcn-amd-amdhsa]]:[[ARCH1]])" {[[P3]]}, assembler
+// ASM2-DAG: [[P5:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T]], (device-[[T]], [[ARCH2:sm_35|gfx900]])
+// ASM2-DAG: [[P6:[0-9]+]]: preprocessor, {[[P5]]}, [[T]]-cpp-output, (device-[[T]], [[ARCH2]])
+// ASM2-DAG: [[P7:[0-9]+]]: compiler, {[[P6]]}, ir, (device-[[T]], [[ARCH2]])
+// ASM2_NV-DAG: [[P8:[0-9]+]]: backend, {[[P7]]}, assembler, (device-[[T]], [[ARCH2]])
+// ASM2_NV-DAG: [[P9:[0-9]+]]: offload, "device-[[T]] ([[TRIPLE]]:[[ARCH2]])" {[[P8]]}, assembler
+// ASM2-DAG: [[P10:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T]], (host-[[T]])
+// ASM2-DAG: [[P11:[0-9]+]]: preprocessor, {[[P10]]}, [[T]]-cpp-output, (host-[[T]])
+// ASM2-DAG: [[P12:[0-9]+]]: compiler, {[[P11]]}, ir, (host-[[T]])
+// ASM2-DAG: [[P13:[0-9]+]]: backend, {[[P12]]}, assembler, (host-[[T]])
//
// Test single gpu architecture with complete compilation in host-only
// compilation mode.
//
-// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases --cuda-gpu-arch=sm_30 %s --cuda-host-only 2>&1 \
-// RUN: | FileCheck -check-prefix=HBIN %s
-// HBIN-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", cuda, (host-cuda)
-// HBIN-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, cuda-cpp-output, (host-cuda)
-// HBIN-DAG: [[P2:[0-9]+]]: compiler, {[[P1]]}, ir, (host-cuda)
-// HBIN-DAG: [[P3:[0-9]+]]: backend, {[[P2]]}, assembler, (host-cuda)
-// HBIN-DAG: [[P4:[0-9]+]]: assembler, {[[P3]]}, object, (host-cuda)
-// HBIN-DAG: [[P5:[0-9]+]]: linker, {[[P4]]}, image, (host-cuda)
+// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
+// RUN: --cuda-gpu-arch=sm_30 %s --cuda-host-only 2>&1 \
+// RUN: | FileCheck -check-prefixes=HBIN,HBIN_NV %s
+// RUN: %clang -x hip -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
+// RUN: --cuda-gpu-arch=gfx803 %s --cuda-host-only 2>&1 \
+// RUN: | FileCheck -check-prefixes=HBIN,HBIN_AMD %s
+// HBIN_NV-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:cuda]], (host-[[T]])
+// HBIN_AMD-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:hip]], (host-[[T]])
+// HBIN-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (host-[[T]])
+// HBIN-DAG: [[P2:[0-9]+]]: compiler, {[[P1]]}, ir, (host-[[T]])
+// HBIN-DAG: [[P3:[0-9]+]]: backend, {[[P2]]}, assembler, (host-[[T]])
+// HBIN-DAG: [[P4:[0-9]+]]: assembler, {[[P3]]}, object, (host-[[T]])
+// HBIN-DAG: [[P5:[0-9]+]]: linker, {[[P4]]}, image, (host-[[T]])
//
// Test single gpu architecture up to the assemble phase in host-only
// compilation mode.
//
-// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases --cuda-gpu-arch=sm_30 %s --cuda-host-only -S 2>&1 \
-// RUN: | FileCheck -check-prefix=HASM %s
-// HASM-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", cuda, (host-cuda)
-// HASM-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, cuda-cpp-output, (host-cuda)
-// HASM-DAG: [[P2:[0-9]+]]: compiler, {[[P1]]}, ir, (host-cuda)
-// HASM-DAG: [[P3:[0-9]+]]: backend, {[[P2]]}, assembler, (host-cuda)
+// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
+// RUN: --cuda-gpu-arch=sm_30 %s --cuda-host-only -S 2>&1 \
+// RUN: | FileCheck -check-prefixes=HASM,HASM_NV %s
+// RUN: %clang -x hip -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
+// RUN: --cuda-gpu-arch=gfx803 %s --cuda-host-only -S 2>&1 \
+// RUN: | FileCheck -check-prefixes=HASM,HASM_AMD %s
+// HASM_NV-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:cuda]], (host-[[T]])
+// HASM_AMD-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:hip]], (host-[[T]])
+// HASM-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (host-[[T]])
+// HASM-DAG: [[P2:[0-9]+]]: compiler, {[[P1]]}, ir, (host-[[T]])
+// HASM-DAG: [[P3:[0-9]+]]: backend, {[[P2]]}, assembler, (host-[[T]])
//
// Test two gpu architectures with complete compilation in host-only
// compilation mode.
//
-// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases --cuda-gpu-arch=sm_30 --cuda-gpu-arch=sm_35 %s --cuda-host-only 2>&1 \
-// RUN: | FileCheck -check-prefix=HBIN2 %s
-// HBIN2-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", cuda, (host-cuda)
-// HBIN2-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, cuda-cpp-output, (host-cuda)
-// HBIN2-DAG: [[P2:[0-9]+]]: compiler, {[[P1]]}, ir, (host-cuda)
-// HBIN2-DAG: [[P3:[0-9]+]]: backend, {[[P2]]}, assembler, (host-cuda)
-// HBIN2-DAG: [[P4:[0-9]+]]: assembler, {[[P3]]}, object, (host-cuda)
-// HBIN2-DAG: [[P5:[0-9]+]]: linker, {[[P4]]}, image, (host-cuda)
+// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
+// RUN: --cuda-gpu-arch=sm_30 --cuda-gpu-arch=sm_35 %s --cuda-host-only 2>&1 \
+// RUN: | FileCheck -check-prefixes=HBIN2,HBIN2_NV %s
+// RUN: %clang -x hip -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
+// RUN: --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s --cuda-host-only 2>&1 \
+// RUN: | FileCheck -check-prefixes=HBIN2,HBIN2_AMD %s
+// HBIN2_NV-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:cuda]], (host-[[T]])
+// HBIN2_AMD-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:hip]], (host-[[T]])
+// HBIN2-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (host-[[T]])
+// HBIN2-DAG: [[P2:[0-9]+]]: compiler, {[[P1]]}, ir, (host-[[T]])
+// HBIN2-DAG: [[P3:[0-9]+]]: backend, {[[P2]]}, assembler, (host-[[T]])
+// HBIN2-DAG: [[P4:[0-9]+]]: assembler, {[[P3]]}, object, (host-[[T]])
+// HBIN2-DAG: [[P5:[0-9]+]]: linker, {[[P4]]}, image, (host-[[T]])
//
// Test two gpu architectures up to the assemble phase in host-only
// compilation mode.
//
-// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases --cuda-gpu-arch=sm_30 --cuda-gpu-arch=sm_35 %s --cuda-host-only -S 2>&1 \
-// RUN: | FileCheck -check-prefix=HASM2 %s
-// HASM2-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", cuda, (host-cuda)
-// HASM2-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, cuda-cpp-output, (host-cuda)
-// HASM2-DAG: [[P2:[0-9]+]]: compiler, {[[P1]]}, ir, (host-cuda)
-// HASM2-DAG: [[P3:[0-9]+]]: backend, {[[P2]]}, assembler, (host-cuda)
+// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
+// RUN: --cuda-gpu-arch=sm_30 --cuda-gpu-arch=sm_35 %s --cuda-host-only -S \
+// RUN: 2>&1 | FileCheck -check-prefixes=HASM2,HASM2_NV %s
+// RUN: %clang -x hip -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
+// RUN: --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s --cuda-host-only -S \
+// RUN: 2>&1 | FileCheck -check-prefixes=HASM2,HASM2_AMD %s
+// HASM2_NV-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:cuda]], (host-[[T]])
+// HASM2_AMD-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:hip]], (host-[[T]])
+// HASM2-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (host-[[T]])
+// HASM2-DAG: [[P2:[0-9]+]]: compiler, {[[P1]]}, ir, (host-[[T]])
+// HASM2-DAG: [[P3:[0-9]+]]: backend, {[[P2]]}, assembler, (host-[[T]])
//
// Test single gpu architecture with complete compilation in device-only
// compilation mode.
//
-// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases --cuda-gpu-arch=sm_30 %s --cuda-device-only 2>&1 \
-// RUN: | FileCheck -check-prefix=DBIN %s
-// DBIN-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", cuda, (device-cuda, sm_30)
-// DBIN-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, cuda-cpp-output, (device-cuda, sm_30)
-// DBIN-DAG: [[P2:[0-9]+]]: compiler, {[[P1]]}, ir, (device-cuda, sm_30)
-// DBIN-DAG: [[P3:[0-9]+]]: backend, {[[P2]]}, assembler, (device-cuda, sm_30)
-// DBIN-DAG: [[P4:[0-9]+]]: assembler, {[[P3]]}, object, (device-cuda, sm_30)
-// DBIN-DAG: [[P5:[0-9]+]]: offload, "device-cuda (nvptx64-nvidia-cuda:sm_30)" {[[P4]]}, object
+// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
+// RUN: --cuda-gpu-arch=sm_30 %s --cuda-device-only 2>&1 \
+// RUN: | FileCheck -check-prefixes=DBIN,DBIN_NV %s
+// RUN: %clang -x hip -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
+// RUN: --cuda-gpu-arch=gfx803 %s --cuda-device-only 2>&1 \
+// RUN: | FileCheck -check-prefixes=DBIN,DBIN_AMD %s
+// DBIN_NV-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:cuda]], (device-[[T]], [[ARCH:sm_30]])
+// DBIN_AMD-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:hip]], (device-[[T]], [[ARCH:gfx803]])
+// DBIN-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (device-[[T]], [[ARCH]])
+// DBIN-DAG: [[P2:[0-9]+]]: compiler, {[[P1]]}, ir, (device-[[T]], [[ARCH]])
+// DBIN_NV-DAG: [[P3:[0-9]+]]: backend, {[[P2]]}, assembler, (device-[[T]], [[ARCH]])
+// DBIN_NV-DAG: [[P4:[0-9]+]]: assembler, {[[P3]]}, object, (device-[[T]], [[ARCH]])
+// DBIN_NV-DAG: [[P5:[0-9]+]]: offload, "device-[[T]] (nvptx64-nvidia-cuda:[[ARCH]])" {[[P4]]}, object
//
// Test single gpu architecture up to the assemble phase in device-only
// compilation mode.
//
-// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases --cuda-gpu-arch=sm_30 %s --cuda-device-only -S 2>&1 \
-// RUN: | FileCheck -check-prefix=DASM %s
-// DASM-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", cuda, (device-cuda, sm_30)
-// DASM-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, cuda-cpp-output, (device-cuda, sm_30)
-// DASM-DAG: [[P2:[0-9]+]]: compiler, {[[P1]]}, ir, (device-cuda, sm_30)
-// DASM-DAG: [[P3:[0-9]+]]: backend, {[[P2]]}, assembler, (device-cuda, sm_30)
-// DASM-DAG: [[P4:[0-9]+]]: offload, "device-cuda (nvptx64-nvidia-cuda:sm_30)" {[[P3]]}, assembler
+// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
+// RUN: --cuda-gpu-arch=sm_30 %s --cuda-device-only -S 2>&1 \
+// RUN: | FileCheck -check-prefixes=DASM,DASM_NV %s
+// RUN: %clang -x hip -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
+// RUN: --cuda-gpu-arch=gfx803 %s --cuda-device-only -S 2>&1 \
+// RUN: | FileCheck -check-prefixes=DASM,DASM_AMD %s
+// DASM_NV-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:cuda]], (device-[[T]], [[ARCH:sm_30]])
+// DASM_AMD-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:hip]], (device-[[T]], [[ARCH:gfx803]])
+// DASM-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (device-[[T]], [[ARCH]])
+// DASM-DAG: [[P2:[0-9]+]]: compiler, {[[P1]]}, ir, (device-[[T]], [[ARCH]])
+// DASM_NV-DAG: [[P3:[0-9]+]]: backend, {[[P2]]}, assembler, (device-[[T]], [[ARCH]])
+// DASM_NV-DAG: [[P4:[0-9]+]]: offload, "device-[[T]] ([[TRIPLE:nvptx64-nvidia-cuda|amdgcn-amd-amdhsa]]:[[ARCH]])" {[[P3]]}, assembler
//
// Test two gpu architectures with complete compilation in device-only
// compilation mode.
//
-// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases --cuda-gpu-arch=sm_30 --cuda-gpu-arch=sm_35 %s --cuda-device-only 2>&1 \
-// RUN: | FileCheck -check-prefix=DBIN2 %s
-// DBIN2-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", cuda, (device-cuda, sm_30)
-// DBIN2-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, cuda-cpp-output, (device-cuda, sm_30)
-// DBIN2-DAG: [[P2:[0-9]+]]: compiler, {[[P1]]}, ir, (device-cuda, sm_30)
-// DBIN2-DAG: [[P3:[0-9]+]]: backend, {[[P2]]}, assembler, (device-cuda, sm_30)
-// DBIN2-DAG: [[P4:[0-9]+]]: assembler, {[[P3]]}, object, (device-cuda, sm_30)
-// DBIN2-DAG: [[P5:[0-9]+]]: offload, "device-cuda (nvptx64-nvidia-cuda:sm_30)" {[[P4]]}, object
-// DBIN2-DAG: [[P6:[0-9]+]]: input, "{{.*}}cuda-phases.cu", cuda, (device-cuda, sm_35)
-// DBIN2-DAG: [[P7:[0-9]+]]: preprocessor, {[[P6]]}, cuda-cpp-output, (device-cuda, sm_35)
-// DBIN2-DAG: [[P8:[0-9]+]]: compiler, {[[P7]]}, ir, (device-cuda, sm_35)
-// DBIN2-DAG: [[P9:[0-9]+]]: backend, {[[P8]]}, assembler, (device-cuda, sm_35)
-// DBIN2-DAG: [[P10:[0-9]+]]: assembler, {[[P9]]}, object, (device-cuda, sm_35)
-// DBIN2-DAG: [[P11:[0-9]+]]: offload, "device-cuda (nvptx64-nvidia-cuda:sm_35)" {[[P10]]}, object
+// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
+// RUN: --cuda-gpu-arch=sm_30 --cuda-gpu-arch=sm_35 %s --cuda-device-only 2>&1 \
+// RUN: | FileCheck -check-prefixes=DBIN2,DBIN2_NV %s
+// RUN: %clang -x hip -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
+// RUN: --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s --cuda-device-only \
+// RUN: 2>&1 | FileCheck -check-prefixes=DBIN2,DBIN2_AMD %s
+// DBIN2_NV-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:cuda]], (device-[[T]], [[ARCH:sm_30]])
+// DBIN2_AMD-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:hip]], (device-[[T]], [[ARCH:gfx803]])
+// DBIN2-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (device-[[T]], [[ARCH]])
+// DBIN2-DAG: [[P2:[0-9]+]]: compiler, {[[P1]]}, ir, (device-[[T]], [[ARCH]])
+// DBIN2_NV-DAG: [[P3:[0-9]+]]: backend, {[[P2]]}, assembler, (device-[[T]], [[ARCH]])
+// DBIN2_NV-DAG: [[P4:[0-9]+]]: assembler, {[[P3]]}, object, (device-[[T]], [[ARCH]])
+// DBIN2_NV-DAG: [[P5:[0-9]+]]: offload, "device-[[T]] ([[TRIPLE:nvptx64-nvidia-cuda]]:[[ARCH]])" {[[P4]]}, object
+// DBIN2-DAG: [[P6:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T]], (device-[[T]], [[ARCH2:sm_35|gfx900]])
+// DBIN2-DAG: [[P7:[0-9]+]]: preprocessor, {[[P6]]}, [[T]]-cpp-output, (device-[[T]], [[ARCH2]])
+// DBIN2-DAG: [[P8:[0-9]+]]: compiler, {[[P7]]}, ir, (device-[[T]], [[ARCH2]])
+// DBIN2_NV-DAG: [[P9:[0-9]+]]: backend, {[[P8]]}, assembler, (device-[[T]], [[ARCH2]])
+// DBIN2_NV-DAG: [[P10:[0-9]+]]: assembler, {[[P9]]}, object, (device-[[T]], [[ARCH2]])
+// DBIN2_NV-DAG: [[P11:[0-9]+]]: offload, "device-[[T]] ([[TRIPLE]]:[[ARCH2]])" {[[P10]]}, object
//
// Test two gpu architectures up to the assemble phase in device-only
// compilation mode.
//
-// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases --cuda-gpu-arch=sm_30 --cuda-gpu-arch=sm_35 %s --cuda-device-only -S 2>&1 \
-// RUN: | FileCheck -check-prefix=DASM2 %s
-// DASM2-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", cuda, (device-cuda, sm_30)
-// DASM2-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, cuda-cpp-output, (device-cuda, sm_30)
-// DASM2-DAG: [[P2:[0-9]+]]: compiler, {[[P1]]}, ir, (device-cuda, sm_30)
-// DASM2-DAG: [[P3:[0-9]+]]: backend, {[[P2]]}, assembler, (device-cuda, sm_30)
-// DASM2-DAG: [[P4:[0-9]+]]: offload, "device-cuda (nvptx64-nvidia-cuda:sm_30)" {[[P3]]}, assembler
-// DASM2-DAG: [[P5:[0-9]+]]: input, "{{.*}}cuda-phases.cu", cuda, (device-cuda, sm_35)
-// DASM2-DAG: [[P6:[0-9]+]]: preprocessor, {[[P5]]}, cuda-cpp-output, (device-cuda, sm_35)
-// DASM2-DAG: [[P7:[0-9]+]]: compiler, {[[P6]]}, ir, (device-cuda, sm_35)
-// DASM2-DAG: [[P8:[0-9]+]]: backend, {[[P7]]}, assembler, (device-cuda, sm_35)
-// DASM2-DAG: [[P9:[0-9]+]]: offload, "device-cuda (nvptx64-nvidia-cuda:sm_35)" {[[P8]]}, assembler
+// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
+// RUN: --cuda-gpu-arch=sm_30 --cuda-gpu-arch=sm_35 %s --cuda-device-only -S \
+// RUN: 2>&1 | FileCheck -check-prefixes=DASM2,DASM2_NV %s
+// RUN: %clang -x hip -target powerpc64le-ibm-linux-gnu \
+// RUN: -ccc-print-phases --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s \
+// RUN: --cuda-device-only -S 2>&1 \
+// RUN: | FileCheck -check-prefixes=DASM2,DASM2_AMD %s
+// DASM2_NV-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:cuda]], (device-[[T]], [[ARCH:sm_30]])
+// DASM2_AMD-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:hip]], (device-[[T]], [[ARCH:gfx803]])
+// DASM2-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (device-[[T]], [[ARCH]])
+// DASM2-DAG: [[P2:[0-9]+]]: compiler, {[[P1]]}, ir, (device-[[T]], [[ARCH]])
+// DASM2_NV-DAG: [[P3:[0-9]+]]: backend, {[[P2]]}, assembler, (device-[[T]], [[ARCH]])
+// DASM2_NV-DAG: [[P4:[0-9]+]]: offload, "device-[[T]] ([[TRIPLE:nvptx64-nvidia-cuda|amdgcn-amd-amdhsa]]:[[ARCH]])" {[[P3]]}, assembler
+// DASM2-DAG: [[P5:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T]], (device-[[T]], [[ARCH2:sm_35|gfx900]])
+// DASM2-DAG: [[P6:[0-9]+]]: preprocessor, {[[P5]]}, [[T]]-cpp-output, (device-[[T]], [[ARCH2]])
+// DASM2-DAG: [[P7:[0-9]+]]: compiler, {[[P6]]}, ir, (device-[[T]], [[ARCH2]])
+// DASM2_NV-DAG: [[P8:[0-9]+]]: backend, {[[P7]]}, assembler, (device-[[T]], [[ARCH2]])
+// DASM2_NV-DAG: [[P9:[0-9]+]]: offload, "device-[[T]] ([[TRIPLE]]:[[ARCH2]])" {[[P8]]}, assembler
diff --git a/test/Driver/cuda-version-check.cu b/test/Driver/cuda-version-check.cu
index 46ca72f2ea0c..2fdd9c4afbe4 100644
--- a/test/Driver/cuda-version-check.cu
+++ b/test/Driver/cuda-version-check.cu
@@ -2,40 +2,40 @@
// REQUIRES: x86-registered-target
// REQUIRES: nvptx-registered-target
-// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_20 --sysroot=%S/Inputs/CUDA 2>&1 %s | \
+// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_20 --cuda-path=%S/Inputs/CUDA/usr/local/cuda 2>&1 %s | \
// RUN: FileCheck %s --check-prefix=OK
-// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_20 --sysroot=%S/Inputs/CUDA_80 2>&1 %s | \
+// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_20 --cuda-path=%S/Inputs/CUDA_80/usr/local/cuda 2>&1 %s | \
// RUN: FileCheck %s --check-prefix=OK
-// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 --sysroot=%S/Inputs/CUDA_80 2>&1 %s | \
+// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 --cuda-path=%S/Inputs/CUDA_80/usr/local/cuda 2>&1 %s | \
// RUN: FileCheck %s --check-prefix=OK
// The installation at Inputs/CUDA is CUDA 7.0, which doesn't support sm_60.
-// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 --sysroot=%S/Inputs/CUDA 2>&1 %s | \
+// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 --cuda-path=%S/Inputs/CUDA/usr/local/cuda 2>&1 %s | \
// RUN: FileCheck %s --check-prefix=ERR_SM60
// This should only complain about sm_60, not sm_35.
// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 --cuda-gpu-arch=sm_35 \
-// RUN: --sysroot=%S/Inputs/CUDA 2>&1 %s | \
+// RUN: --cuda-path=%S/Inputs/CUDA/usr/local/cuda 2>&1 %s | \
// RUN: FileCheck %s --check-prefix=ERR_SM60 --check-prefix=OK_SM35
// We should get two errors here, one for sm_60 and one for sm_61.
// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 --cuda-gpu-arch=sm_61 \
-// RUN: --sysroot=%S/Inputs/CUDA 2>&1 %s | \
+// RUN: --cuda-path=%S/Inputs/CUDA/usr/local/cuda 2>&1 %s | \
// RUN: FileCheck %s --check-prefix=ERR_SM60 --check-prefix=ERR_SM61
// We should still get an error if we pass -nocudainc, because this compilation
// would invoke ptxas, and we do a version check on that, too.
-// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 -nocudainc --sysroot=%S/Inputs/CUDA 2>&1 %s | \
+// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 -nocudainc --cuda-path=%S/Inputs/CUDA/usr/local/cuda 2>&1 %s | \
// RUN: FileCheck %s --check-prefix=ERR_SM60
// If with -nocudainc and -E, we don't touch the CUDA install, so we
// shouldn't get an error.
// RUN: %clang --target=x86_64-linux -v -### -E --cuda-device-only --cuda-gpu-arch=sm_60 -nocudainc \
-// RUN: --sysroot=%S/Inputs/CUDA 2>&1 %s | \
+// RUN: --cuda-path=%S/Inputs/CUDA/usr/local/cuda 2>&1 %s | \
// RUN: FileCheck %s --check-prefix=OK
// --no-cuda-version-check should suppress all of these errors.
-// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 --sysroot=%S/Inputs/CUDA 2>&1 \
+// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 --cuda-path=%S/Inputs/CUDA/usr/local/cuda 2>&1 \
// RUN: --no-cuda-version-check %s | \
// RUN: FileCheck %s --check-prefix=OK
@@ -43,9 +43,9 @@
// therefore we should not get an error in host-only mode. We use the -S here
// to avoid the error being produced in case by the assembler tool, which does
// the same check.
-// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 --cuda-host-only --sysroot=%S/Inputs/CUDA -S 2>&1 %s | \
+// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 --cuda-host-only --cuda-path=%S/Inputs/CUDA/usr/local/cuda -S 2>&1 %s | \
// RUN: FileCheck %s --check-prefix=OK
-// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 --cuda-device-only --sysroot=%S/Inputs/CUDA -S 2>&1 %s | \
+// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 --cuda-device-only --cuda-path=%S/Inputs/CUDA/usr/local/cuda -S 2>&1 %s | \
// RUN: FileCheck %s --check-prefix=ERR_SM60
// OK-NOT: error: GPU arch
diff --git a/test/Driver/cxa-atexit.cpp b/test/Driver/cxa-atexit.cpp
index 01d4e20e7716..cc5f68b9a474 100644
--- a/test/Driver/cxa-atexit.cpp
+++ b/test/Driver/cxa-atexit.cpp
@@ -25,3 +25,20 @@
// CHECK-MTI: "-fno-use-cxa-atexit"
// CHECK-MIPS-NOT: "-fno-use-cxa-atexit"
+// RUN: %clang -target x86_64-apple-darwin -fregister-global-dtors-with-atexit -fno-register-global-dtors-with-atexit -c -### %s 2>&1 | \
+// RUN: FileCheck --check-prefix=WITHOUTATEXIT %s
+// RUN: %clang -target x86_64-apple-darwin -fno-register-global-dtors-with-atexit -fregister-global-dtors-with-atexit -c -### %s 2>&1 | \
+// RUN: FileCheck --check-prefix=WITHATEXIT %s
+// RUN: %clang -target x86_64-apple-darwin -c -### %s 2>&1 | \
+// RUN: FileCheck --check-prefix=WITHATEXIT %s
+// RUN: %clang -target x86_64-apple-darwin -c -mkernel -### %s 2>&1 | \
+// RUN: FileCheck --check-prefix=WITHOUTATEXIT %s
+// RUN: %clang -target x86_64-pc-linux-gnu -fregister-global-dtors-with-atexit -fno-register-global-dtors-with-atexit -c -### %s 2>&1 | \
+// RUN: FileCheck --check-prefix=WITHOUTATEXIT %s
+// RUN: %clang -target x86_64-pc-linux-gnu -fno-register-global-dtors-with-atexit -fregister-global-dtors-with-atexit -c -### %s 2>&1 | \
+// RUN: FileCheck --check-prefix=WITHATEXIT %s
+// RUN: %clang -target x86_64-pc-linux-gnu -c -### %s 2>&1 | \
+// RUN: FileCheck --check-prefix=WITHOUTATEXIT %s
+
+// WITHATEXIT: -fregister-global-dtors-with-atexit
+// WITHOUTATEXIT-NOT: -fregister-global-dtors-with-atexit
diff --git a/test/Driver/darwin-asan-nofortify.c b/test/Driver/darwin-asan-nofortify.c
index 58b5be9fcbb7..7d6da6d05798 100644
--- a/test/Driver/darwin-asan-nofortify.c
+++ b/test/Driver/darwin-asan-nofortify.c
@@ -1,5 +1,5 @@
// Make sure AddressSanitizer disables _FORTIFY_SOURCE on Darwin.
-// RUN: %clang -fsanitize=address %s -E -dM -target x86_64-darwin | FileCheck %s
+// RUN: %clang -fsanitize=address %s -E -dM -target x86_64-darwin -resource-dir %S/Inputs/resource_dir | FileCheck %s
// CHECK: #define _FORTIFY_SOURCE 0
diff --git a/test/Driver/darwin-infer-simulator-sdkroot.c b/test/Driver/darwin-infer-simulator-sdkroot.c
new file mode 100644
index 000000000000..1b1f1739d64c
--- /dev/null
+++ b/test/Driver/darwin-infer-simulator-sdkroot.c
@@ -0,0 +1,77 @@
+// Check that SDKROOT does not infer simulator on when it points to a regular
+// SDK.
+// REQUIRES: system-darwin
+//
+// RUN: rm -rf %t/SDKs/iPhoneOS8.0.0.sdk
+// RUN: mkdir -p %t/SDKs/iPhoneOS8.0.0.sdk
+// RUN: env SDKROOT=%t/SDKs/iPhoneOS8.0.0.sdk %clang %s -### 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-IPHONE %s
+// RUN: env SDKROOT=%t/SDKs/iPhoneOS8.0.0.sdk IPHONEOS_DEPLOYMENT_TARGET=8.0 %clang %s -### 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-IPHONE %s
+// CHECK-IPHONE: clang
+// CHECK-IPHONE: "-cc1"
+// CHECK-IPHONE: -apple-ios8.0.0"
+// CHECK-IPHONE: ld
+// CHECK-IPHONE: "-iphoneos_version_min" "8.0.0"
+//
+//
+// RUN: rm -rf %t/SDKs/iPhoneSimulator8.0.sdk
+// RUN: mkdir -p %t/SDKs/iPhoneSimulator8.0.sdk
+// RUN: env SDKROOT=%t/SDKs/iPhoneSimulator8.0.sdk %clang %s -### 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-SIMULATOR %s
+//
+// CHECK-SIMULATOR: clang
+// CHECK-SIMULATOR: "-cc1"
+// CHECK-SIMULATOR: -apple-ios8.0.0-simulator"
+// CHECK-SIMULATOR: ld
+// CHECK-SIMULATOR: "-ios_simulator_version_min" "8.0.0"
+//
+//
+// RUN: rm -rf %t/SDKs/WatchOS3.0.sdk
+// RUN: mkdir -p %t/SDKs/WatchOS3.0.sdk
+// RUN: env SDKROOT=%t/SDKs/WatchOS3.0.sdk %clang %s -### 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-WATCH %s
+// RUN: env WATCHOS_DEPLOYMENT_TARGET=3.0 %clang %s -isysroot %t/SDKs/WatchOS3.0.sdk -### 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-WATCH %s
+//
+// CHECK-WATCH: clang
+// CHECK-WATCH: "-cc1"
+// CHECK-WATCH: -apple-watchos3.0.0"
+// CHECK-WATCH: ld
+// CHECK-WATCH: "-watchos_version_min" "3.0.0"
+//
+//
+// RUN: rm -rf %t/SDKs/WatchSimulator3.0.sdk
+// RUN: mkdir -p %t/SDKs/WatchSimulator3.0.sdk
+// RUN: env SDKROOT=%t/SDKs/WatchSimulator3.0.sdk %clang %s -### 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-WATCH-SIMULATOR %s
+//
+// CHECK-WATCH-SIMULATOR: clang
+// CHECK-WATCH-SIMULATOR: "-cc1"
+// CHECK-WATCH-SIMULATOR: -apple-watchos3.0.0-simulator"
+// CHECK-WATCH-SIMULATOR: ld
+// CHECK-WATCH-SIMULATOR: "-watchos_simulator_version_min" "3.0.0"
+//
+//
+// RUN: rm -rf %t/SDKs/AppleTVOS10.0.sdk
+// RUN: mkdir -p %t/SDKs/AppleTVOS10.0.sdk
+// RUN: env SDKROOT=%t/SDKs/AppleTVOS10.0.sdk %clang %s -### 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-TV %s
+//
+// CHECK-TV: clang
+// CHECK-TV: "-cc1"
+// CHECK-TV: -apple-tvos10.0.0"
+// CHECK-TV: ld
+// CHECK-TV: "-tvos_version_min" "10.0.0"
+//
+//
+// RUN: rm -rf %t/SDKs/AppleTVSimulator10.0.sdk
+// RUN: mkdir -p %t/SDKs/AppleTVSimulator10.0.sdk
+// RUN: env SDKROOT=%t/SDKs/AppleTVSimulator10.0.sdk %clang %s -### 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-TV-SIMULATOR %s
+//
+// CHECK-TV-SIMULATOR: clang
+// CHECK-TV-SIMULATOR: "-cc1"
+// CHECK-TV-SIMULATOR: -apple-tvos10.0.0-simulator"
+// CHECK-TV-SIMULATOR: ld
+// CHECK-TV-SIMULATOR: "-tvos_simulator_version_min" "10.0.0"
diff --git a/test/Driver/darwin-ld.c b/test/Driver/darwin-ld.c
index 3ddba02a43e8..c98d1abcab29 100644
--- a/test/Driver/darwin-ld.c
+++ b/test/Driver/darwin-ld.c
@@ -342,6 +342,10 @@
// RUN: FileCheck -check-prefix=PASS_REMARKS_WITH_HOTNESS %s < %t.log
// PASS_REMARKS_WITH_HOTNESS: "-mllvm" "-lto-pass-remarks-output" "-mllvm" "foo/bar.out.opt.yaml" "-mllvm" "-lto-pass-remarks-with-hotness"
+// RUN: %clang -target x86_64-apple-darwin12 %t.o -fsave-optimization-record -fprofile-instr-use=blah -fdiagnostics-hotness-threshold=100 -### -o foo/bar.out 2> %t.log
+// RUN: FileCheck -check-prefix=PASS_REMARKS_WITH_HOTNESS_THRESHOLD %s < %t.log
+// PASS_REMARKS_WITH_HOTNESS_THRESHOLD: "-mllvm" "-lto-pass-remarks-output" "-mllvm" "foo/bar.out.opt.yaml" "-mllvm" "-lto-pass-remarks-with-hotness" "-mllvm" "-lto-pass-remarks-hotness-threshold=100"
+
// RUN: %clang -target x86_64-apple-ios6.0 -miphoneos-version-min=6.0 -fprofile-instr-generate -### %t.o 2> %t.log
// RUN: FileCheck -check-prefix=LINK_PROFILE_FIRST %s < %t.log
// RUN: %clang -target x86_64-apple-darwin12 -fprofile-instr-generate -### %t.o 2> %t.log
@@ -352,6 +356,8 @@
// RUN: FileCheck -check-prefix=LINK_PROFILE_FIRST %s < %t.log
// LINK_PROFILE_FIRST: {{ld(.exe)?"}} "{{[^"]+}}libclang_rt.profile_{{[a-z]+}}.a"
+// RUN: %clang -target x86_64-apple-darwin12 -fprofile-instr-generate -exported_symbols_list /dev/null -### %t.o 2> %t.log
+// RUN: FileCheck -check-prefix=PROFILE_EXPORT %s < %t.log
// RUN: %clang -target x86_64-apple-darwin12 -fprofile-instr-generate -Wl,-exported_symbols_list,/dev/null -### %t.o 2> %t.log
// RUN: FileCheck -check-prefix=PROFILE_EXPORT %s < %t.log
// RUN: %clang -target x86_64-apple-darwin12 -fprofile-instr-generate -Wl,-exported_symbol,foo -### %t.o 2> %t.log
@@ -360,8 +366,14 @@
// RUN: FileCheck -check-prefix=PROFILE_EXPORT %s < %t.log
// RUN: %clang -target x86_64-apple-darwin12 -fprofile-instr-generate -Xlinker -exported_symbols_list -Xlinker /dev/null -### %t.o 2> %t.log
// RUN: FileCheck -check-prefix=PROFILE_EXPORT %s < %t.log
-// PROFILE_EXPORT: "-exported_symbol" "_VPMergeHook" "-exported_symbol" "___llvm_profile_filename" "-exported_symbol" "___llvm_profile_raw_version" "-exported_symbol" "_lprofCurFilename"
+// PROFILE_EXPORT: "-exported_symbol" "___llvm_profile_filename" "-exported_symbol" "___llvm_profile_raw_version" "-exported_symbol" "_lprofCurFilename"
//
// RUN: %clang -target x86_64-apple-darwin12 -fprofile-instr-generate -### %t.o 2> %t.log
// RUN: FileCheck -check-prefix=NO_PROFILE_EXPORT %s < %t.log
// NO_PROFILE_EXPORT-NOT: "-exported_symbol"
+//
+// Check that we can pass the outliner down to the linker.
+// RUN: env IPHONEOS_DEPLOYMENT_TARGET=7.0 \
+// RUN: %clang -target arm64-apple-darwin -moutline -### %t.o 2> %t.log
+// MOUTLINE: ld
+// MOUTLINE-SAME: "-mllvm" "-enable-machine-outliner" "-mllvm" "-enable-linkonceodr-outlining"
diff --git a/test/Driver/darwin-sanitizer-ld.c b/test/Driver/darwin-sanitizer-ld.c
index 53c7fce115e7..f7dfb157b44e 100644
--- a/test/Driver/darwin-sanitizer-ld.c
+++ b/test/Driver/darwin-sanitizer-ld.c
@@ -1,6 +1,7 @@
// Test sanitizer link flags on Darwin.
// RUN: %clang -no-canonical-prefixes -### -target x86_64-darwin \
+// RUN: -resource-dir %S/Inputs/resource_dir \
// RUN: -stdlib=platform -fsanitize=address %s -o %t.o 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-ASAN %s
@@ -12,6 +13,14 @@
// CHECK-ASAN: "-rpath" "{{.*}}lib{{.*}}darwin"
// RUN: %clang -no-canonical-prefixes -### -target x86_64-darwin \
+// RUN: -resource-dir %S/Inputs/fake_resource_dir \
+// RUN: -stdlib=platform -fsanitize=address %s -o %t.o 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-LOAD-FAIL %s
+
+// CHECK-LOAD-FAIL: error: unsupported option '-fsanitize=address' for target 'x86_64--darwin'
+
+// RUN: %clang -no-canonical-prefixes -### -target x86_64-darwin \
+// RUN: -resource-dir %S/Inputs/resource_dir \
// RUN: -fPIC -shared -fsanitize=address %s -o %t.so 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-DYN-ASAN %s
@@ -22,6 +31,7 @@
// CHECK-DYN-ASAN: "-rpath" "{{.*}}lib{{.*}}darwin"
// RUN: %clang -no-canonical-prefixes -### -target x86_64-darwin \
+// RUN: -resource-dir %S/Inputs/resource_dir \
// RUN: -stdlib=platform -fsanitize=undefined %s -o %t.o 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-UBSAN %s
@@ -34,6 +44,7 @@
// RUN: %clang -no-canonical-prefixes -### -target x86_64-darwin \
// RUN: -fsanitize=bounds -fsanitize-undefined-trap-on-error \
+// RUN: -resource-dir %S/Inputs/resource_dir \
// RUN: %s -o %t.o 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-BOUNDS %s
@@ -42,6 +53,7 @@
// RUN: %clang -no-canonical-prefixes -### -target x86_64-darwin \
// RUN: -fPIC -shared -fsanitize=undefined %s -o %t.so 2>&1 \
+// RUN: -resource-dir %S/Inputs/resource_dir \
// RUN: | FileCheck --check-prefix=CHECK-DYN-UBSAN %s
// CHECK-DYN-UBSAN: "{{.*}}ld{{(.exe)?}}"
@@ -52,6 +64,7 @@
// RUN: %clang -no-canonical-prefixes -### -target x86_64-darwin \
// RUN: -fsanitize=bounds -fsanitize-undefined-trap-on-error \
+// RUN: -resource-dir %S/Inputs/resource_dir \
// RUN: %s -o %t.so -fPIC -shared 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-DYN-BOUNDS %s
@@ -60,6 +73,7 @@
// RUN: %clang -no-canonical-prefixes -### -target x86_64-darwin \
// RUN: -stdlib=platform -fsanitize=address -mios-simulator-version-min=7.0 \
+// RUN: -resource-dir %S/Inputs/resource_dir \
// RUN: %s -o %t.o 2>&1 | FileCheck --check-prefix=CHECK-ASAN-IOSSIM %s
// CHECK-ASAN-IOSSIM: "{{.*}}ld{{(.exe)?}}"
@@ -70,6 +84,7 @@
// CHECK-ASAN-IOSSIM: "-rpath" "{{.*}}lib{{.*}}darwin"
// RUN: %clang -no-canonical-prefixes -### -target x86_64-darwin \
+// RUN: -resource-dir %S/Inputs/resource_dir \
// RUN: -stdlib=platform -fsanitize=address \
// RUN: -mtvos-simulator-version-min=8.3.0 %s -o %t.o 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-ASAN-TVOSSIM %s
@@ -83,6 +98,7 @@
// RUN: %clang -no-canonical-prefixes -### -target x86_64-darwin \
// RUN: -stdlib=platform -fsanitize=address \
+// RUN: -resource-dir %S/Inputs/resource_dir \
// RUN: -mwatchos-simulator-version-min=2.0.0 %s -o %t.o 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-ASAN-WATCHOSSIM %s
@@ -94,6 +110,7 @@
// CHECK-ASAN-WATCHOSSIM: "-rpath" "{{.*}}lib{{.*}}darwin"
// RUN: %clang -no-canonical-prefixes -### -target armv7-apple-ios \
+// RUN: -resource-dir %S/Inputs/resource_dir \
// RUN: -stdlib=platform -fsanitize=address -miphoneos-version-min=7 \
// RUN: %s -o %t.o 2>&1 | FileCheck --check-prefix=CHECK-ASAN-IOS %s
@@ -106,6 +123,7 @@
// RUN: %clang -no-canonical-prefixes -### -target arm64-apple-tvos \
// RUN: -stdlib=platform -fsanitize=address -mtvos-version-min=8.3 \
+// RUN: -resource-dir %S/Inputs/resource_dir \
// RUN: %s -o %t.o 2>&1 | FileCheck --check-prefix=CHECK-ASAN-TVOS %s
// CHECK-ASAN-TVOS: "{{.*}}ld{{(.exe)?}}"
@@ -117,6 +135,7 @@
// RUN: %clang -no-canonical-prefixes -### -target armv7k-apple-watchos \
// RUN: -stdlib=platform -fsanitize=address -mwatchos-version-min=2.0 \
+// RUN: -resource-dir %S/Inputs/resource_dir \
// RUN: %s -o %t.o 2>&1 | FileCheck --check-prefix=CHECK-ASAN-WATCHOS %s
// CHECK-ASAN-WATCHOS: "{{.*}}ld{{(.exe)?}}"
diff --git a/test/Driver/darwin-version.c b/test/Driver/darwin-version.c
index 4a9cdf9e5f52..75279b9e0c5d 100644
--- a/test/Driver/darwin-version.c
+++ b/test/Driver/darwin-version.c
@@ -205,7 +205,8 @@
// RUN: %clang -target x86_64-apple-ios -miphonesimulator-version-min=10.0 -c %s -### 2>&1 | \
// RUN: FileCheck --check-prefix=CHECK-VERSION-TNO-OSV3 %s
-// CHECK-VERSION-TNO-OSV3: overriding '-mios-simulator-version-min=10.0' option with '--target=x86_64-apple-ios'
+// CHECK-VERSION-TNO-OSV3: "x86_64-apple-ios10.0.0-simulator"
+// CHECK-VERSION-TNO-OSV3-NOT: overriding '-mios-simulator-version-min
// CHECK-VERSION-TNO-OSV3-NOT: argument unused during compilation
// RUN: %clang -target arm64-apple-ios10.1.0 -miphoneos-version-min=10.1.0.1 -c %s -### 2>&1 | \
@@ -217,7 +218,7 @@
// CHECK-VERSION-TNO-SAME-NOT: overriding
// CHECK-VERSION-TNO-SAME-NOT: argument unused during compilation
-// Target with OS version is not overriden by -m<os>-version-min variables:
+// Target with OS version is not overridden by -m<os>-version-min variables:
// RUN: %clang -target x86_64-apple-macos10.11.2 -mmacos-version-min=10.6 -c %s -### 2>&1 | \
// RUN: FileCheck --check-prefix=CHECK-VERSION-TIGNORE-OSV1 %s
@@ -235,7 +236,25 @@
// RUN: FileCheck --check-prefix=CHECK-VERSION-TIGNORE-OSV4 %s
// CHECK-VERSION-TIGNORE-OSV4: "thumbv7k-apple-watchos3.0.0"
-// Target with OS version is not overriden by environment variables:
+// Target without OS version includes the OS given by -m<os>-version-min arguments:
+
+// RUN: %clang -target x86_64-apple-macos -mmacos-version-min=10.11 -c %s -### 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-USE-OS-ARG1 %s
+// CHECK-VERSION-USE-OS-ARG1: "x86_64-apple-macosx10.11.0"
+
+// RUN: %clang -target arm64-apple-ios -mios-version-min=9.0 -c %s -### 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-USE-OS-ARG2 %s
+// CHECK-VERSION-USE-OS-ARG2: "arm64-apple-ios9.0.0"
+
+// RUN: %clang -target arm64-apple-tvos -mtvos-version-min=10.0 -c %s -### 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-USE-OS-ARG3 %s
+// CHECK-VERSION-USE-OS-ARG3: "arm64-apple-tvos10.0.0"
+
+// RUN: %clang -target armv7k-apple-watchos -mwatchos-version-min=4 -c %s -### 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-USE-OS-ARG4 %s
+// CHECK-VERSION-USE-OS-ARG4: "thumbv7k-apple-watchos4.0.0"
+
+// Target with OS version is not overridden by environment variables:
// RUN: env MACOSX_DEPLOYMENT_TARGET=10.1 \
// RUN: %clang -target i386-apple-macos10.5 -c %s -### 2>&1 | \
@@ -257,7 +276,7 @@
// RUN: FileCheck --check-prefix=CHECK-VERSION-TWATCHOS-CMD %s
// CHECK-VERSION-TWATCHOS-CMD: "thumbv7k-apple-watchos3.0.0"
-// Target with OS version is not overriden by the SDK:
+// Target with OS version is not overridden by the SDK:
// RUN: %clang -target armv7-apple-ios9 -Wno-missing-sysroot -isysroot SDKs/iPhoneOS11.0.sdk -c -### %s 2>&1 | \
// RUN: FileCheck --check-prefix=CHECK-VERSION-TIOS-SDK %s
@@ -271,7 +290,7 @@
// RUN: FileCheck --check-prefix=CHECK-VERSION-TTVOS-SDK %s
// CHECK-VERSION-TTVOS-SDK: thumbv7-apple-tvos9
-// Target with OS version is not overriden by arch:
+// Target with OS version is not overridden by arch:
// RUN: %clang -target uknown-apple-macos10.11.2 -arch=armv7k -c %s -### 2>&1 | \
// RUN: FileCheck --check-prefix=CHECK-VERSION-TIGNORE-ARCH1 %s
diff --git a/test/Driver/debug-options.c b/test/Driver/debug-options.c
index 3bec1e141d10..0dd32e983ad8 100644
--- a/test/Driver/debug-options.c
+++ b/test/Driver/debug-options.c
@@ -134,15 +134,23 @@
// RUN: | FileCheck -check-prefix=GIGNORE %s
//
// RUN: %clang -### -c -ggnu-pubnames %s 2>&1 | FileCheck -check-prefix=GOPT %s
+// RUN: %clang -### -c %s 2>&1 | FileCheck -check-prefix=NOGOPT %s
+// RUN: %clang -### -c -ggnu-pubnames -gno-gnu-pubnames %s 2>&1 | FileCheck -check-prefix=NOGOPT %s
//
// RUN: %clang -### -c -gdwarf-aranges %s 2>&1 | FileCheck -check-prefix=GARANGE %s
//
-// RUN: %clang -### -fdebug-types-section %s 2>&1 \
+// RUN: %clang -### -fdebug-types-section -target x86_64-unknown-linux %s 2>&1 \
// RUN: | FileCheck -check-prefix=FDTS %s
//
-// RUN: %clang -### -fdebug-types-section -fno-debug-types-section %s 2>&1 \
+// RUN: %clang -### -fdebug-types-section -fno-debug-types-section -target x86_64-unknown-linux %s 2>&1 \
// RUN: | FileCheck -check-prefix=NOFDTS %s
//
+// RUN: %clang -### -fdebug-types-section -target x86_64-apple-darwin %s 2>&1 \
+// RUN: | FileCheck -check-prefix=FDTSE %s
+//
+// RUN: %clang -### -fdebug-types-section -fno-debug-types-section -target x86_64-apple-darwin %s 2>&1 \
+// RUN: | FileCheck -check-prefix=NOFDTSE %s
+//
// RUN: %clang -### -g -gno-column-info %s 2>&1 \
// RUN: | FileCheck -check-prefix=NOCI %s
//
@@ -222,12 +230,15 @@
// GIGNORE-NOT: "argument unused during compilation"
//
// GOPT: -ggnu-pubnames
+// NOGOPT-NOT: -ggnu-pubnames
//
// GARANGE: -generate-arange-section
//
-// FDTS: "-backend-option" "-generate-type-units"
+// FDTS: "-mllvm" "-generate-type-units"
+// FDTSE: error: unsupported option '-fdebug-types-section' for target 'x86_64-apple-darwin'
//
-// NOFDTS-NOT: "-backend-option" "-generate-type-units"
+// NOFDTS-NOT: "-mllvm" "-generate-type-units"
+// NOFDTSE-NOT: error: unsupported option '-fdebug-types-section' for target 'x86_64-apple-darwin'
//
// CI: "-dwarf-column-info"
//
@@ -245,3 +256,13 @@
// RUN: %clang -### %s 2>&1 | FileCheck -check-prefix=NOMACRO %s
// MACRO: "-debug-info-macro"
// NOMACRO-NOT: "-debug-info-macro"
+//
+// RUN: %clang -### -gdwarf-5 -gembed-source %s 2>&1 | FileCheck -check-prefix=GEMBED_5 %s
+// RUN: %clang -### -gdwarf-2 -gembed-source %s 2>&1 | FileCheck -check-prefix=GEMBED_2 %s
+// RUN: %clang -### -gdwarf-5 -gno-embed-source %s 2>&1 | FileCheck -check-prefix=NOGEMBED_5 %s
+// RUN: %clang -### -gdwarf-2 -gno-embed-source %s 2>&1 | FileCheck -check-prefix=NOGEMBED_2 %s
+//
+// GEMBED_5: "-gembed-source"
+// GEMBED_2: error: invalid argument '-gembed-source' only allowed with '-gdwarf-5'
+// NOGEMBED_5-NOT: "-gembed-source"
+// NOGEMBED_2-NOT: error: invalid argument '-gembed-source' only allowed with '-gdwarf-5'
diff --git a/test/Driver/debug-prefix-map.S b/test/Driver/debug-prefix-map.S
new file mode 100644
index 000000000000..2ba66be0edfc
--- /dev/null
+++ b/test/Driver/debug-prefix-map.S
@@ -0,0 +1,6 @@
+// RUN: %clang -### -g -fdebug-prefix-map=old=new %s 2>&1 | FileCheck %s
+
+// CHECK: cc1as
+// CHECK-SAME: -fdebug-prefix-map=old=new
+
+// More tests for this flag in debug-prefix-map.c.
diff --git a/test/Driver/emulated-tls.cpp b/test/Driver/emulated-tls.cpp
index 38edc98ac889..20abad181128 100644
--- a/test/Driver/emulated-tls.cpp
+++ b/test/Driver/emulated-tls.cpp
@@ -1,7 +1,42 @@
-// Cygwin and OpenBSD use emutls. Clang should pass -femulated-tls to cc1
-// and cc1 should pass EmulatedTLS to LLVM CodeGen.
-// FIXME: Add more targets here to use emutls.
-// RUN: %clang -### -std=c++11 -target i686-pc-cygwin %s 2>&1 | FileCheck %s
-// RUN: %clang -### -std=c++11 -target i686-pc-openbsd %s 2>&1 | FileCheck %s
+// Android, Cygwin and OpenBSD use emutls by default.
+// Clang should pass -femulated-tls or -fno-emulated-tls to cc1 if they are used,
+// and cc1 should set up EmulatedTLS and ExplicitEmulatedTLS to LLVM CodeGen.
+//
+// RUN: %clang -### -target arm-linux-androideabi %s 2>&1 \
+// RUN: | FileCheck -check-prefix=DEFAULT %s
+// RUN: %clang -### -target arm-linux-gnu %s 2>&1 \
+// RUN: | FileCheck -check-prefix=DEFAULT %s
+// RUN: %clang -### -target i686-pc-cygwin %s 2>&1 \
+// RUN: | FileCheck -check-prefix=DEFAULT %s
+// RUN: %clang -### -target i686-pc-openbsd %s 2>&1 \
+// RUN: | FileCheck -check-prefix=DEFAULT %s
-// CHECK: "-cc1" {{.*}}"-femulated-tls"
+// RUN: %clang -### -target arm-linux-androideabi -fno-emulated-tls -femulated-tls %s 2>&1 \
+// RUN: | FileCheck -check-prefix=EMU %s
+// RUN: %clang -### -target arm-linux-gnu %s -fno-emulated-tls -femulated-tls 2>&1 \
+// RUN: | FileCheck -check-prefix=EMU %s
+// RUN: %clang -### -target i686-pc-cygwin %s -fno-emulated-tls -femulated-tls 2>&1 \
+// RUN: | FileCheck -check-prefix=EMU %s
+// RUN: %clang -### -target i686-pc-openbsd %s -fno-emulated-tls -femulated-tls 2>&1 \
+// RUN: | FileCheck -check-prefix=EMU %s
+
+// RUN: %clang -### -target arm-linux-androideabi -femulated-tls -fno-emulated-tls %s 2>&1 \
+// RUN: | FileCheck -check-prefix=NOEMU %s
+// RUN: %clang -### -target arm-linux-gnu %s -femulated-tls -fno-emulated-tls 2>&1 \
+// RUN: | FileCheck -check-prefix=NOEMU %s
+// RUN: %clang -### -target i686-pc-cygwin %s -femulated-tls -fno-emulated-tls 2>&1 \
+// RUN: | FileCheck -check-prefix=NOEMU %s
+// RUN: %clang -### -target i686-pc-openbsd %s -femulated-tls -fno-emulated-tls 2>&1 \
+// RUN: | FileCheck -check-prefix=NOEMU %s
+
+
+// Default without -f[no-]emulated-tls, will be decided by the target triple.
+// DEFAULT-NOT: "-cc1" {{.*}}"-femulated-tls"
+// DEFAULT-NOT: "-cc1" {{.*}}"-fno-emulated-tls"
+
+// Explicit and last -f[no-]emulated-tls flag will be passed to cc1.
+// EMU: "-cc1" {{.*}}"-femulated-tls"
+// EMU-NOT: "-cc1" {{.*}}"-fno-emulated-tls"
+
+// NOEMU: "-cc1" {{.*}}"-fno-emulated-tls"
+// NOEMU-NOT: "-cc1" {{.*}}"-femulated-tls"
diff --git a/test/Driver/fast-math.c b/test/Driver/fast-math.c
index 7bb057fcf7d6..57e5d2c71575 100644
--- a/test/Driver/fast-math.c
+++ b/test/Driver/fast-math.c
@@ -287,3 +287,27 @@
// RUN: %clang -### -ftrapping-math -fno-trapping-math -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NO-TRAPPING-MATH %s
// CHECK-NO-TRAPPING-MATH: "-fno-trapping-math"
+
+// This isn't fast-math, but the option is handled in the same place as other FP params.
+// Last option wins, and strict behavior is assumed by default.
+
+// RUN: %clang -### -fno-strict-float-cast-overflow -c %s 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-FPOV-WORKAROUND %s
+// CHECK-FPOV-WORKAROUND: "-cc1"
+// CHECK-FPOV-WORKAROUND: "-fno-strict-float-cast-overflow"
+
+// RUN: %clang -### -c %s 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-FPOV-WORKAROUND-DEFAULT %s
+// CHECK-FPOV-WORKAROUND-DEFAULT: "-cc1"
+// CHECK-FPOV-WORKAROUND-DEFAULT-NOT: "strict-float-cast-overflow"
+
+// RUN: %clang -### -fstrict-float-cast-overflow -c %s 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-NO-FPOV-WORKAROUND %s
+// CHECK-NO-FPOV-WORKAROUND: "-cc1"
+// CHECK-NO-FPOV-WORKAROUND-NOT: "strict-float-cast-overflow"
+
+// RUN: %clang -### -fno-strict-float-cast-overflow -fstrict-float-cast-overflow -c %s 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-NO-FPOV-WORKAROUND-OVERRIDE %s
+// CHECK-NO-FPOV-WORKAROUND-OVERRIDE: "-cc1"
+// CHECK-NO-FPOV-WORKAROUND-OVERRIDE-NOT: "strict-float-cast-overflow"
+
diff --git a/test/Driver/fno-escaping-block-tail-calls.c b/test/Driver/fno-escaping-block-tail-calls.c
new file mode 100644
index 000000000000..14372c048187
--- /dev/null
+++ b/test/Driver/fno-escaping-block-tail-calls.c
@@ -0,0 +1,9 @@
+// RUN: %clang -### %s -fescaping-block-tail-calls -fno-escaping-block-tail-calls 2> %t
+// RUN: FileCheck --check-prefix=CHECK-DISABLE < %t %s
+// CHECK-DISABLE: "-fno-escaping-block-tail-calls"
+
+// RUN: %clang -### %s -fno-escaping-block-tail-calls -fescaping-block-tail-calls 2> %t
+// RUN: FileCheck --check-prefix=CHECK-NO-DISABLE < %t %s
+// RUN: %clang -### %s 2> %t
+// RUN: FileCheck --check-prefix=CHECK-NO-DISABLE < %t %s
+// CHECK-NO-DISABLE-NOT: "-fno-escaping-block-tail-calls"
diff --git a/test/Driver/fno-rtti-data.cpp b/test/Driver/fno-rtti-data.cpp
new file mode 100644
index 000000000000..cc2d5b68a1f4
--- /dev/null
+++ b/test/Driver/fno-rtti-data.cpp
@@ -0,0 +1,2 @@
+// RUN: %clang -### -fno-rtti-data %s 2>&1 | FileCheck %s
+// CHECK: -fno-rtti-data
diff --git a/test/Driver/frame-pointer-elim.c b/test/Driver/frame-pointer-elim.c
index e39499a55c24..6fcd3eb75ae5 100644
--- a/test/Driver/frame-pointer-elim.c
+++ b/test/Driver/frame-pointer-elim.c
@@ -17,6 +17,15 @@
// RUN: FileCheck --check-prefix=CLOUDABI %s
// CLOUDABI-NOT: "-momit-leaf-frame-pointer"
+// NetBSD follows the same rules as Linux.
+// RUN: %clang -### -target x86_64-unknown-netbsd -S -O1 %s 2>&1 | \
+// RUN: FileCheck --check-prefix=NETBSD-OPT %s
+// NETBSD-OPT: "-momit-leaf-frame-pointer"
+
+// RUN: %clang -### -target x86_64-unknown-netbsd -S %s 2>&1 | \
+// RUN: FileCheck --check-prefix=NETBSD %s
+// NETBSD-NOT: "-momit-leaf-frame-pointer"
+
// Darwin disables omitting the leaf frame pointer even under optimization
// unless the command lines are given.
// RUN: %clang -### -target i386-apple-darwin -S %s 2>&1 | \
diff --git a/test/Driver/frame-pointer.c b/test/Driver/frame-pointer.c
index ecb16af3cf80..85c9f3a21f10 100644
--- a/test/Driver/frame-pointer.c
+++ b/test/Driver/frame-pointer.c
@@ -33,6 +33,30 @@
// RUN: %clang -target mips64el-linux-gnu -### -S -O0 %s -o %t.s 2>&1 | FileCheck -check-prefix=CHECK0-32 %s
// RUN: %clang -target mips64el-linux-gnu -### -S -O1 %s -o %t.s 2>&1 | FileCheck -check-prefix=CHECK1-32 %s
+// RUN: %clang -target riscv32-unknown-elf -### -S -O0 %s -o %t.s 2>&1 | FileCheck -check-prefix=CHECK0-32 %s
+// RUN: %clang -target riscv32-unknown-elf -### -S -O1 %s -o %t.s 2>&1 | FileCheck -check-prefix=CHECK1-32 %s
+// RUN: %clang -target riscv32-unknown-elf -### -S -O2 %s -o %t.s 2>&1 | FileCheck -check-prefix=CHECK2-32 %s
+// RUN: %clang -target riscv32-unknown-elf -### -S -O3 %s -o %t.s 2>&1 | FileCheck -check-prefix=CHECK3-32 %s
+// RUN: %clang -target riscv32-unknown-elf -### -S -Os %s -o %t.s 2>&1 | FileCheck -check-prefix=CHECKs-32 %s
+
+// RUN: %clang -target riscv64-unknown-elf -### -S -O0 %s -o %t.s 2>&1 | FileCheck -check-prefix=CHECK0-64 %s
+// RUN: %clang -target riscv64-unknown-elf -### -S -O1 %s -o %t.s 2>&1 | FileCheck -check-prefix=CHECK1-64 %s
+// RUN: %clang -target riscv64-unknown-elf -### -S -O2 %s -o %t.s 2>&1 | FileCheck -check-prefix=CHECK2-64 %s
+// RUN: %clang -target riscv64-unknown-elf -### -S -O3 %s -o %t.s 2>&1 | FileCheck -check-prefix=CHECK3-64 %s
+// RUN: %clang -target riscv64-unknown-elf -### -S -Os %s -o %t.s 2>&1 | FileCheck -check-prefix=CHECKs-64 %s
+
+// RUN: %clang -target riscv32-unknown-linux-gnu -### -S -O0 %s -o %t.s 2>&1 | FileCheck -check-prefix=CHECK0-32 %s
+// RUN: %clang -target riscv32-unknown-linux-gnu -### -S -O1 %s -o %t.s 2>&1 | FileCheck -check-prefix=CHECK1-32 %s
+// RUN: %clang -target riscv32-unknown-linux-gnu -### -S -O2 %s -o %t.s 2>&1 | FileCheck -check-prefix=CHECK2-32 %s
+// RUN: %clang -target riscv32-unknown-linux-gnu -### -S -O3 %s -o %t.s 2>&1 | FileCheck -check-prefix=CHECK3-32 %s
+// RUN: %clang -target riscv32-unknown-linux-gnu -### -S -Os %s -o %t.s 2>&1 | FileCheck -check-prefix=CHECKs-32 %s
+
+// RUN: %clang -target riscv64-unknown-linux-gnu -### -S -O0 %s -o %t.s 2>&1 | FileCheck -check-prefix=CHECK0-64 %s
+// RUN: %clang -target riscv64-unknown-linux-gnu -### -S -O1 %s -o %t.s 2>&1 | FileCheck -check-prefix=CHECK1-64 %s
+// RUN: %clang -target riscv64-unknown-linux-gnu -### -S -O2 %s -o %t.s 2>&1 | FileCheck -check-prefix=CHECK2-64 %s
+// RUN: %clang -target riscv64-unknown-linux-gnu -### -S -O3 %s -o %t.s 2>&1 | FileCheck -check-prefix=CHECK3-64 %s
+// RUN: %clang -target riscv64-unknown-linux-gnu -### -S -Os %s -o %t.s 2>&1 | FileCheck -check-prefix=CHECKs-64 %s
+
// CHECK0-32: -mdisable-fp-elim
// CHECK1-32-NOT: -mdisable-fp-elim
// CHECK2-32-NOT: -mdisable-fp-elim
diff --git a/test/Driver/freebsd-mips-as.c b/test/Driver/freebsd-mips-as.c
index af02c38693da..a053c2180e52 100644
--- a/test/Driver/freebsd-mips-as.c
+++ b/test/Driver/freebsd-mips-as.c
@@ -3,62 +3,62 @@
// RUN: %clang -target mips-unknown-freebsd -### \
// RUN: -no-integrated-as -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=MIPS32-EB-AS %s
-// MIPS32-EB-AS: as{{(.exe)?}}" "-march" "mips32r2" "-mabi" "32" "-EB"
+// MIPS32-EB-AS: as{{(.exe)?}}" "-march" "mips2" "-mabi" "32" "-EB"
// MIPS32-EB-AS-NOT: "-KPIC"
//
// RUN: %clang -target mips-unknown-freebsd -### \
// RUN: -no-integrated-as -fPIC -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=MIPS32-EB-PIC %s
-// MIPS32-EB-PIC: as{{(.exe)?}}" "-march" "mips32r2" "-mabi" "32" "-EB"
+// MIPS32-EB-PIC: as{{(.exe)?}}" "-march" "mips2" "-mabi" "32" "-EB"
// MIPS32-EB-PIC: "-KPIC"
//
// RUN: %clang -target mips-unknown-freebsd -### \
// RUN: -no-integrated-as -fpic -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=MIPS32-EB-PIC-SMALL %s
-// MIPS32-EB-PIC-SMALL: as{{(.exe)?}}" "-march" "mips32r2" "-mabi" "32" "-EB"
+// MIPS32-EB-PIC-SMALL: as{{(.exe)?}}" "-march" "mips2" "-mabi" "32" "-EB"
// MIPS32-EB-PIC-SMALL: "-KPIC"
//
// RUN: %clang -target mips-unknown-freebsd -### \
// RUN: -no-integrated-as -fPIE -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=MIPS32-EB-PIE %s
-// MIPS32-EB-PIE: as{{(.exe)?}}" "-march" "mips32r2" "-mabi" "32" "-EB"
+// MIPS32-EB-PIE: as{{(.exe)?}}" "-march" "mips2" "-mabi" "32" "-EB"
// MIPS32-EB-PIE: "-KPIC"
//
// RUN: %clang -target mips-unknown-freebsd -### \
// RUN: -no-integrated-as -fpie -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=MIPS32-EB-PIE-SMALL %s
-// MIPS32-EB-PIE-SMALL: as{{(.exe)?}}" "-march" "mips32r2" "-mabi" "32" "-EB"
+// MIPS32-EB-PIE-SMALL: as{{(.exe)?}}" "-march" "mips2" "-mabi" "32" "-EB"
// MIPS32-EB-PIE-SMALL: "-KPIC"
//
// RUN: %clang -target mipsel-unknown-freebsd -### \
// RUN: -no-integrated-as -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=MIPS32-DEF-EL-AS %s
-// MIPS32-DEF-EL-AS: as{{(.exe)?}}" "-march" "mips32r2" "-mabi" "32" "-EL"
+// MIPS32-DEF-EL-AS: as{{(.exe)?}}" "-march" "mips2" "-mabi" "32" "-EL"
//
// RUN: %clang -target mips64-unknown-freebsd -### \
// RUN: -no-integrated-as -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=MIPS64-EB-AS %s
-// MIPS64-EB-AS: as{{(.exe)?}}" "-march" "mips64r2" "-mabi" "64" "-EB"
+// MIPS64-EB-AS: as{{(.exe)?}}" "-march" "mips3" "-mabi" "64" "-EB"
//
// RUN: %clang -target mips64el-unknown-freebsd -### \
// RUN: -no-integrated-as -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=MIPS64-DEF-EL-AS %s
-// MIPS64-DEF-EL-AS: as{{(.exe)?}}" "-march" "mips64r2" "-mabi" "64" "-EL"
+// MIPS64-DEF-EL-AS: as{{(.exe)?}}" "-march" "mips3" "-mabi" "64" "-EL"
//
// RUN: %clang -target mips64-unknown-freebsd -mabi=n32 -### \
// RUN: -no-integrated-as -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=MIPS-N32 %s
-// MIPS-N32: as{{(.exe)?}}" "-march" "mips64r2" "-mabi" "n32" "-EB"
+// MIPS-N32: as{{(.exe)?}}" "-march" "mips3" "-mabi" "n32" "-EB"
//
// RUN: %clang -target mipsel-unknown-freebsd -mabi=32 -### \
// RUN: -no-integrated-as -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=MIPS32-EL-AS %s
-// MIPS32-EL-AS: as{{(.exe)?}}" "-march" "mips32r2" "-mabi" "32" "-EL"
+// MIPS32-EL-AS: as{{(.exe)?}}" "-march" "mips2" "-mabi" "32" "-EL"
//
// RUN: %clang -target mips64el-unknown-freebsd -mabi=64 -### \
// RUN: -no-integrated-as -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=MIPS64-EL-AS %s
-// MIPS64-EL-AS: as{{(.exe)?}}" "-march" "mips64r2" "-mabi" "64" "-EL"
+// MIPS64-EL-AS: as{{(.exe)?}}" "-march" "mips3" "-mabi" "64" "-EL"
//
// RUN: %clang -target mips-linux-freebsd -march=mips32r2 -### \
// RUN: -no-integrated-as -c %s 2>&1 \
@@ -88,5 +88,5 @@
// RUN: %clang -target mips-unknown-freebsd -### \
// RUN: -no-integrated-as -G0 -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=MIPS32-EB-AS-G0 %s
-// MIPS32-EB-AS-G0: as{{(.exe)?}}" "-march" "mips32r2" "-mabi" "32" "-EB" "-G0"
+// MIPS32-EB-AS-G0: as{{(.exe)?}}" "-march" "mips2" "-mabi" "32" "-EB" "-G0"
// MIPS32-EB-AS-G0-NOT: "-KPIC"
diff --git a/test/Driver/freebsd.c b/test/Driver/freebsd.c
index 0f89d25ac4fa..aac4d9d966dd 100644
--- a/test/Driver/freebsd.c
+++ b/test/Driver/freebsd.c
@@ -36,6 +36,33 @@
// RUN: | FileCheck --check-prefix=CHECK-LIB32PATHS %s
// CHECK-LIB32PATHS: libraries: ={{.*:?}}/usr/lib32
//
+// Check that O32 MIPS uses /usr/lib32 on a 64-bit tree.
+//
+// RUN: %clang -target mips-freebsd12 %s \
+// RUN: --sysroot=%S/Inputs/multiarch_freebsd64_tree -print-search-dirs 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-LIB32PATHS %s
+//
+// Check that MIPS passes the correct linker emulation.
+//
+// RUN: %clang -target mips-freebsd %s -### %s 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-MIPS-LD %s
+// CHECK-MIPS-LD: ld{{.*}}" {{.*}} "-m" "elf32btsmip_fbsd"
+// RUN: %clang -target mipsel-freebsd %s -### %s 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-MIPSEL-LD %s
+// CHECK-MIPSEL-LD: ld{{.*}}" {{.*}} "-m" "elf32ltsmip_fbsd"
+// RUN: %clang -target mips64-freebsd %s -### %s 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-MIPS64-LD %s
+// CHECK-MIPS64-LD: ld{{.*}}" {{.*}} "-m" "elf64btsmip_fbsd"
+// RUN: %clang -target mips64el-freebsd %s -### %s 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-MIPS64EL-LD %s
+// CHECK-MIPS64EL-LD: ld{{.*}}" {{.*}} "-m" "elf64ltsmip_fbsd"
+// RUN: %clang -target mips64-freebsd -mabi=n32 %s -### %s 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-MIPSN32-LD %s
+// CHECK-MIPSN32-LD: ld{{.*}}" {{.*}} "-m" "elf32btsmipn32_fbsd"
+// RUN: %clang -target mips64el-freebsd -mabi=n32 %s -### %s 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-MIPSN32EL-LD %s
+// CHECK-MIPSN32EL-LD: ld{{.*}}" {{.*}} "-m" "elf32ltsmipn32_fbsd"
+//
// Check that the new linker flags are passed to FreeBSD
// RUN: %clang -no-canonical-prefixes -target x86_64-pc-freebsd8 -m32 %s \
// RUN: --sysroot=%S/Inputs/multiarch_freebsd64_tree -### 2>&1 \
@@ -142,3 +169,24 @@
// RUN: %clang -target mips-unknown-freebsd %s -### -G0 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MIPS-G %s
// CHECK-MIPS-G: ld{{.*}}" "-G0"
+
+// Check CPU type for MIPS
+// RUN: %clang -target mips-unknown-freebsd -### -c %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-MIPS-CPU %s
+// RUN: %clang -target mipsel-unknown-freebsd -### -c %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-MIPS-CPU %s
+// CHECK-MIPS-CPU: "-target-cpu" "mips2"
+
+// Check CPU type for MIPS64
+// RUN: %clang -target mips64-unknown-freebsd -### -c %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-MIPS64-CPU %s
+// RUN: %clang -target mips64el-unknown-freebsd -### -c %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-MIPS64-CPU %s
+// CHECK-MIPS64-CPU: "-target-cpu" "mips3"
+
+// Check that the integrated assembler is enabled for MIPS64
+// RUN: %clang -target mips64-unknown-freebsd -### -c %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-MIPS64-AS %s
+// RUN: %clang -target mips64el-unknown-freebsd -### -c %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-MIPS64-AS %s
+// CHECK-MIPS64-AS-NOT: "-no-integrated-as"
diff --git a/test/Driver/fsanitize-blacklist.c b/test/Driver/fsanitize-blacklist.c
index 0a063753dae2..927d2edf9857 100644
--- a/test/Driver/fsanitize-blacklist.c
+++ b/test/Driver/fsanitize-blacklist.c
@@ -21,23 +21,26 @@
// CHECK-BLACKLIST2: -fdepfile-entry={{.*}}.good" "-fdepfile-entry={{.*}}.second
// Check that the default blacklist is not added as an extra dependency.
-// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -resource-dir=%S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT-BLACKLIST-ASAN --implicit-check-not=fdepfile-entry
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -resource-dir=%S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT-BLACKLIST-ASAN --implicit-check-not=fdepfile-entry --implicit-check-not=-fsanitize-blacklist=
// CHECK-DEFAULT-BLACKLIST-ASAN: -fsanitize-blacklist={{.*[^w]}}asan_blacklist.txt
-// RUN: %clang -target aarch64-linux-gnu -fsanitize=hwaddress -resource-dir=%S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT-BLACKLIST-HWASAN --implicit-check-not=fdepfile-entry
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=hwaddress -resource-dir=%S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT-BLACKLIST-HWASAN --implicit-check-not=fdepfile-entry --implicit-check-not=-fsanitize-blacklist=
// CHECK-DEFAULT-BLACKLIST-HWASAN: -fsanitize-blacklist={{.*}}hwasan_blacklist.txt
-// RUN: %clang -target x86_64-linux-gnu -fsanitize=integer -resource-dir=%S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT-UBSAN-BLACKLIST --implicit-check-not=fdepfile-entry
-// RUN: %clang -target x86_64-linux-gnu -fsanitize=nullability -resource-dir=%S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT-UBSAN-BLACKLIST --implicit-check-not=fdepfile-entry
-// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -resource-dir=%S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT-UBSAN-BLACKLIST --implicit-check-not=fdepfile-entry
-// RUN: %clang -target x86_64-linux-gnu -fsanitize=alignment -resource-dir=%S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT-UBSAN-BLACKLIST --implicit-check-not=fdepfile-entry
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=integer -resource-dir=%S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT-UBSAN-BLACKLIST --implicit-check-not=fdepfile-entry --implicit-check-not=-fsanitize-blacklist=
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=nullability -resource-dir=%S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT-UBSAN-BLACKLIST --implicit-check-not=fdepfile-entry --implicit-check-not=-fsanitize-blacklist=
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -resource-dir=%S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT-UBSAN-BLACKLIST --implicit-check-not=fdepfile-entry --implicit-check-not=-fsanitize-blacklist=
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=alignment -resource-dir=%S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT-UBSAN-BLACKLIST --implicit-check-not=fdepfile-entry --implicit-check-not=-fsanitize-blacklist=
// CHECK-DEFAULT-UBSAN-BLACKLIST: -fsanitize-blacklist={{.*}}ubsan_blacklist.txt
+// Check that combining ubsan and another sanitizer results in both blacklists being used.
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined,address -resource-dir=%S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT-UBSAN-BLACKLIST --check-prefix=CHECK-DEFAULT-ASAN-BLACKLIST --implicit-check-not=fdepfile-entry --implicit-check-not=-fsanitize-blacklist=
+
// Ignore -fsanitize-blacklist flag if there is no -fsanitize flag.
// RUN: %clang -target x86_64-linux-gnu -fsanitize-blacklist=%t.good %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-SANITIZE --check-prefix=DELIMITERS
// CHECK-NO-SANITIZE-NOT: -fsanitize-blacklist
// Ignore -fsanitize-blacklist flag if there is no -fsanitize flag.
-// Now, check for the absense of -fdepfile-entry flags.
+// Now, check for the absence of -fdepfile-entry flags.
// RUN: %clang -target x86_64-linux-gnu -fsanitize-blacklist=%t.good %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-SANITIZE2 --check-prefix=DELIMITERS
// CHECK-NO-SANITIZE2-NOT: -fdepfile-entry
@@ -54,9 +57,13 @@
// CHECK-BAD-BLACKLIST: error: malformed sanitizer blacklist: 'error parsing file '{{.*}}.bad': malformed line 1: 'badline''
// -fno-sanitize-blacklist disables all blacklists specified earlier.
-// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-blacklist=%t.good -fno-sanitize-blacklist -fsanitize-blacklist=%t.second %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ONLY-FIRST-DISABLED
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-blacklist=%t.good -fno-sanitize-blacklist -fsanitize-blacklist=%t.second %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ONLY-FIRST-DISABLED --implicit-check-not=-fsanitize-blacklist=
// CHECK-ONLY_FIRST-DISABLED-NOT: good
// CHECK-ONLY-FIRST-DISABLED: -fsanitize-blacklist={{.*}}.second
// CHECK-ONLY_FIRST-DISABLED-NOT: good
+// If cfi_blacklist.txt cannot be found in the resource dir, driver should fail.
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=cfi -resource-dir=/dev/null %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-MISSING-CFI-BLACKLIST
+// CHECK-MISSING-CFI-BLACKLIST: error: no such file or directory: '{{.*}}cfi_blacklist.txt'
+
// DELIMITERS: {{^ *"}}
diff --git a/test/Driver/fsanitize-coverage.c b/test/Driver/fsanitize-coverage.c
index 4073ea4864cd..ab8b1c65d81e 100644
--- a/test/Driver/fsanitize-coverage.c
+++ b/test/Driver/fsanitize-coverage.c
@@ -7,6 +7,7 @@
// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-coverage=func,trace-pc %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-FUNC
// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-address -fsanitize-coverage=func,trace-pc %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-FUNC
// RUN: %clang -target x86_64-linux-gnu -fsanitize=hwaddress -fsanitize-coverage=func,trace-pc %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-FUNC
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-hwaddress -fsanitize-coverage=func,trace-pc %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-FUNC
// RUN: %clang -target x86_64-linux-gnu -fsanitize=memory -fsanitize-coverage=func,trace-pc %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-FUNC
// RUN: %clang -target x86_64-linux-gnu -fsanitize=leak -fsanitize-coverage=func,trace-pc %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-FUNC
// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -fsanitize-coverage=func,trace-pc %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-FUNC
diff --git a/test/Driver/fsanitize-object-size.c b/test/Driver/fsanitize-object-size.c
index b96221e0fd43..50c67838df39 100644
--- a/test/Driver/fsanitize-object-size.c
+++ b/test/Driver/fsanitize-object-size.c
@@ -2,8 +2,9 @@
//
// RUN: %clang -target x86_64-linux-gnu -fsanitize=object-size %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-OSIZE
// RUN: %clang -target x86_64-linux-gnu -fsanitize=object-size %s -O0 -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-OSIZE
-// RUN: %clang -target x86_64-linux-gnu -fsanitize=null,object-size %s -### 2>&1 | FileCheck %s --check-prefixes=CHECK-NO-OSIZE
-// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefixes=CHECK-NO-OSIZE-NO-WARNING
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=null,object-size %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-OSIZE
+// RUN: %clang -target x86_64-linux-gnu -Werror -fsanitize=null,object-size %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-OSIZE
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-OSIZE-NO-WARNING
// Check that the object size check is enabled at other optimization levels.
//
diff --git a/test/Driver/fsanitize.c b/test/Driver/fsanitize.c
index 7870f724b6c3..e6d94649f065 100644
--- a/test/Driver/fsanitize.c
+++ b/test/Driver/fsanitize.c
@@ -14,9 +14,6 @@
// RUN: %clang -target x86_64-apple-darwin10 -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-DARWIN
// CHECK-UNDEFINED-DARWIN: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|function|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|builtin|returns-nonnull-attribute|nonnull-attribute),?){19}"}}
-// RUN: %clang -target i386-unknown-openbsd -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-OPENBSD
-// CHECK-UNDEFINED-OPENBSD: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|builtin|returns-nonnull-attribute|nonnull-attribute),?){18}"}}
-
// RUN: %clang -target i386-pc-win32 -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-WIN --check-prefix=CHECK-UNDEFINED-WIN32
// RUN: %clang -target i386-pc-win32 -fsanitize=undefined -x c++ %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-WIN --check-prefix=CHECK-UNDEFINED-WIN32 --check-prefix=CHECK-UNDEFINED-WIN-CXX
// RUN: %clang -target x86_64-pc-win32 -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-WIN --check-prefix=CHECK-UNDEFINED-WIN64
@@ -86,18 +83,36 @@
// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-address,address -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANKA-SANA
// CHECK-SANKA-SANA: '-fsanitize=kernel-address' not allowed with '-fsanitize=address'
-// RUN: %clang -target aarch64-linux-gnu -fsanitize=hwaddress,thread -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANHA-SANT
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-address,leak -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANKA-SANL
+// CHECK-SANKA-SANL: '-fsanitize=kernel-address' not allowed with '-fsanitize=leak'
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-hwaddress,thread -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANKHA-SANT
+// CHECK-SANKHA-SANT: '-fsanitize=kernel-hwaddress' not allowed with '-fsanitize=thread'
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-hwaddress,memory -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANKHA-SANM
+// CHECK-SANKHA-SANM: '-fsanitize=kernel-hwaddress' not allowed with '-fsanitize=memory'
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-hwaddress,address -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANKHA-SANA
+// CHECK-SANKHA-SANA: '-fsanitize=kernel-hwaddress' not allowed with '-fsanitize=address'
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-hwaddress,leak -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANKHA-SANL
+// CHECK-SANKHA-SANL: '-fsanitize=kernel-hwaddress' not allowed with '-fsanitize=leak'
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-hwaddress,hwaddress -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANKHA-SANHA
+// CHECK-SANKHA-SANHA: '-fsanitize=kernel-hwaddress' not allowed with '-fsanitize=hwaddress'
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-hwaddress,kernel-address -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANKHA-SANKA
+// CHECK-SANKHA-SANKA: '-fsanitize=kernel-hwaddress' not allowed with '-fsanitize=kernel-address'
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=hwaddress,thread -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANHA-SANT
// CHECK-SANHA-SANT: '-fsanitize=hwaddress' not allowed with '-fsanitize=thread'
-// RUN: %clang -target aarch64-linux-gnu -fsanitize=hwaddress,memory -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANHA-SANM
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=hwaddress,memory -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANHA-SANM
// CHECK-SANHA-SANM: '-fsanitize=hwaddress' not allowed with '-fsanitize=memory'
-// RUN: %clang -target aarch64-linux-gnu -fsanitize=hwaddress,address -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANHA-SANA
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=hwaddress,address -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANHA-SANA
// CHECK-SANHA-SANA: '-fsanitize=hwaddress' not allowed with '-fsanitize=address'
-// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-address,leak -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANKA-SANL
-// CHECK-SANKA-SANL: '-fsanitize=kernel-address' not allowed with '-fsanitize=leak'
-
// RUN: %clang -target x86_64-linux-gnu -fsanitize=efficiency-cache-frag,address -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANE-SANA
// RUN: %clang -target x86_64-linux-gnu -fsanitize=efficiency-working-set,address -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANE-SANA
// CHECK-SANE-SANA: '-fsanitize=efficiency-{{.*}}' not allowed with '-fsanitize=address'
@@ -184,11 +199,11 @@
// RUN: %clang -target x86_64-linux-gnu -fsanitize=memory -fsanitize-memory-use-after-dtor %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-USE-AFTER-DTOR
// RUN: %clang -target x86_64-linux-gnu -fsanitize=memory -fno-sanitize-memory-use-after-dtor -fsanitize-memory-use-after-dtor %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-USE-AFTER-DTOR
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=memory %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-USE-AFTER-DTOR
// CHECK-USE-AFTER-DTOR: -cc1{{.*}}-fsanitize-memory-use-after-dtor
// RUN: %clang -target x86_64-linux-gnu -fsanitize=memory -fno-sanitize-memory-use-after-dtor %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-USE-AFTER-DTOR-OFF
// RUN: %clang -target x86_64-linux-gnu -fsanitize=memory -fsanitize-memory-use-after-dtor -fno-sanitize-memory-use-after-dtor %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-USE-AFTER-DTOR-OFF
-// RUN: %clang -target x86_64-linux-gnu -fsanitize=memory %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-USE-AFTER-DTOR-OFF
// CHECK-USE-AFTER-DTOR-OFF-NOT: -cc1{{.*}}memory-use-after-dtor
// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-address-field-padding=0 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-FIELD-PADDING-0
@@ -257,6 +272,11 @@
// CHECK-DEPRECATED-RECOVER: argument '-fno-sanitize-recover' is deprecated, use '-fno-sanitize-recover=undefined,integer' or '-fno-sanitize-recover=all' instead
// CHECK-DEPRECATED-RECOVER-NOT: is deprecated
+// RUN: %clang -target x86_64-linux-gnu %s -fsanitize=kernel-address -fno-sanitize-recover=kernel-address -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-RECOVER-KASAN
+// RUN: %clang -target x86_64-linux-gnu %s -fsanitize=kernel-hwaddress -fno-sanitize-recover=kernel-hwaddress -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-RECOVER-KHWASAN
+// CHECK-NO-RECOVER-KASAN: unsupported argument 'kernel-address' to option 'fno-sanitize-recover='
+// CHECK-NO-RECOVER-KHWASAN: unsupported argument 'kernel-hwaddress' to option 'fno-sanitize-recover='
+
// RUN: %clang -target x86_64-linux-gnu -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANL
// CHECK-SANL: "-fsanitize=leak"
@@ -296,6 +316,12 @@
// RUN: %clang -target mips-unknown-linux -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANL-MIPS
// CHECK-SANL-MIPS: unsupported option '-fsanitize=leak' for target 'mips-unknown-linux'
+// RUN: %clang -target mips-unknown-freebsd -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANL-MIPS-FREEBSD
+// CHECK-SANL-MIPS-FREEBSD: unsupported option '-fsanitize=leak' for target 'mips-unknown-freebsd'
+
+// RUN: %clang -target mips64-unknown-freebsd -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANL-MIPS64-FREEBSD
+// CHECK-SANL-MIPS64-FREEBSD: "-fsanitize=leak"
+
// RUN: %clang -target powerpc64-unknown-linux -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANL-PPC64
// RUN: %clang -target powerpc64le-unknown-linux -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANL-PPC64
// CHECK-SANL-PPC64: "-fsanitize=leak"
@@ -311,33 +337,30 @@
// CHECK-DIAG1: unsupported argument 'zzz' to option 'fsanitize='
// CHECK-DIAG1-NOT: unsupported argument 'zzz' to option 'fsanitize='
-// RUN: %clang -target i686-linux-gnu -fsanitize=memory %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-MSAN-X86
-// CHECK-MSAN-X86: error: unsupported option '-fsanitize=memory' for target 'i686--linux-gnu'
-
// RUN: %clang -target x86_64-apple-darwin10 -fsanitize=memory %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-MSAN-DARWIN
// CHECK-MSAN-DARWIN: unsupported option '-fsanitize=memory' for target 'x86_64-apple-darwin10'
// RUN: %clang -target x86_64-apple-darwin10 -fsanitize=memory -fno-sanitize=memory %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-MSAN-NOMSAN-DARWIN
// CHECK-MSAN-NOMSAN-DARWIN-NOT: unsupported option
-// RUN: %clang -target x86_64-apple-darwin10 -fsanitize=memory -fsanitize=thread,memory %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-MSAN-TSAN-MSAN-DARWIN
+// RUN: %clang -target x86_64-apple-darwin10 -fsanitize=memory -fsanitize=thread,memory -resource-dir %S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-MSAN-TSAN-MSAN-DARWIN
// CHECK-MSAN-TSAN-MSAN-DARWIN: unsupported option '-fsanitize=memory' for target 'x86_64-apple-darwin10'
// CHECK-MSAN-TSAN-MSAN-DARWIN-NOT: unsupported option
-// RUN: %clang -target x86_64-apple-darwin10 -fsanitize=thread,memory -fsanitize=memory %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-MSAN-MSAN-DARWIN
+// RUN: %clang -target x86_64-apple-darwin10 -fsanitize=thread,memory -fsanitize=memory -resource-dir %S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-MSAN-MSAN-DARWIN
// CHECK-TSAN-MSAN-MSAN-DARWIN: unsupported option '-fsanitize=memory' for target 'x86_64-apple-darwin10'
// CHECK-TSAN-MSAN-MSAN-DARWIN-NOT: unsupported option
-// RUN: %clang -target x86_64-apple-darwin -fsanitize=thread %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-X86-64-DARWIN
+// RUN: %clang -target x86_64-apple-darwin -fsanitize=thread -resource-dir %S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-X86-64-DARWIN
// CHECK-TSAN-X86-64-DARWIN-NOT: unsupported option
-// RUN: %clang -target x86_64-apple-iossimulator -fsanitize=thread %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-X86-64-IOSSIMULATOR
+// RUN: %clang -target x86_64-apple-iossimulator -fsanitize=thread -resource-dir %S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-X86-64-IOSSIMULATOR
// CHECK-TSAN-X86-64-IOSSIMULATOR-NOT: unsupported option
-// RUN: %clang -target x86_64-apple-tvossimulator -fsanitize=thread %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-X86-64-TVOSSIMULATOR
+// RUN: %clang -target x86_64-apple-tvossimulator -fsanitize=thread -resource-dir %S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-X86-64-TVOSSIMULATOR
// CHECK-TSAN-X86-64-TVOSSIMULATOR-NOT: unsupported option
-// RUN: %clang -target i386-apple-darwin -fsanitize=thread %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-I386-DARWIN
+// RUN: %clang -target i386-apple-darwin -fsanitize=thread -resource-dir %S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-I386-DARWIN
// CHECK-TSAN-I386-DARWIN: unsupported option '-fsanitize=thread' for target 'i386-apple-darwin'
// RUN: %clang -target arm-apple-ios -fsanitize=thread %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-ARM-IOS
@@ -391,28 +414,44 @@
// RUN: %clang -target armv7-apple-ios7 -miphoneos-version-min=7.0 -fsanitize=address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-IOS
// CHECK-ASAN-IOS: -fsanitize=address
+// RUN %clang -target i386-pc-openbsd -fsanitize=undefined %s -### 2>&1 | FileCheck --check-prefix=CHECK-UBSAN-OPENBSD
+// CHECK-UBSAN-OPENBSD: -fsanitize=undefined
+
// RUN: %clang -target i386-pc-openbsd -fsanitize=address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-OPENBSD
// CHECK-ASAN-OPENBSD: unsupported option '-fsanitize=address' for target 'i386-pc-openbsd'
-// RUN: %clang -target x86_64-apple-darwin -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-X86-64-DARWIN
+// RUN: %clang -target i386-pc-openbsd -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-OPENBSD
+// CHECK-LSAN-OPENBSD: unsupported option '-fsanitize=leak' for target 'i386-pc-openbsd'
+
+// RUN: %clang -target i386-pc-openbsd -fsanitize=thread %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-OPENBSD
+// CHECK-TSAN-OPENBSD: unsupported option '-fsanitize=thread' for target 'i386-pc-openbsd'
+
+// RUN: %clang -target i386-pc-openbsd -fsanitize=memory %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-MSAN-OPENBSD
+// CHECK-MSAN-OPENBSD: unsupported option '-fsanitize=memory' for target 'i386-pc-openbsd'
+
+// RUN: %clang -target i386-pc-openbsd -fsanitize=efficiency-cache-frag %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ESAN-OPENBSD
+// RUN: %clang -target i386-pc-openbsd -fsanitize=efficiency-working-set %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ESAN-OPENBSD
+// CHECK-ESAN-OPENBSD: error: unsupported option '-fsanitize=efficiency-{{.*}}' for target 'i386-pc-openbsd'
+
+// RUN: %clang -target x86_64-apple-darwin -fsanitize=leak -resource-dir %S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-X86-64-DARWIN
// CHECK-LSAN-X86-64-DARWIN-NOT: unsupported option
-// RUN: %clang -target x86_64-apple-iossimulator -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-X86-64-IOSSIMULATOR
+// RUN: %clang -target x86_64-apple-iossimulator -fsanitize=leak -resource-dir %S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-X86-64-IOSSIMULATOR
// CHECK-LSAN-X86-64-IOSSIMULATOR-NOT: unsupported option
-// RUN: %clang -target x86_64-apple-tvossimulator -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-X86-64-TVOSSIMULATOR
+// RUN: %clang -target x86_64-apple-tvossimulator -fsanitize=leak -resource-dir %S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-X86-64-TVOSSIMULATOR
// CHECK-LSAN-X86-64-TVOSSIMULATOR-NOT: unsupported option
-// RUN: %clang -target i386-apple-darwin -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-I386-DARWIN
+// RUN: %clang -target i386-apple-darwin -fsanitize=leak -resource-dir %S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-I386-DARWIN
// CHECK-LSAN-I386-DARWIN-NOT: unsupported option
-// RUN: %clang -target arm-apple-ios -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-ARM-IOS
+// RUN: %clang -target arm-apple-ios -fsanitize=leak -resource-dir %S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-ARM-IOS
// CHECK-LSAN-ARM-IOS-NOT: unsupported option
-// RUN: %clang -target i386-apple-iossimulator -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-I386-IOSSIMULATOR
+// RUN: %clang -target i386-apple-iossimulator -fsanitize=leak -resource-dir %S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-I386-IOSSIMULATOR
// CHECK-LSAN-I386-IOSSIMULATOR-NOT: unsupported option
-// RUN: %clang -target i386-apple-tvossimulator -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-I386-TVOSSIMULATOR
+// RUN: %clang -target i386-apple-tvossimulator -fsanitize=leak -resource-dir %S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-I386-TVOSSIMULATOR
// CHECK-LSAN-I386-TVOSSIMULATOR-NOT: unsupported option
// RUN: %clang -target i686-linux-gnu -fsanitize=efficiency-cache-frag %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ESAN-X86
@@ -443,6 +482,8 @@
// RUN: %clang -target x86_64-linux-gnu -fvisibility=hidden -fsanitize=cfi -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI
// RUN: %clang -target x86_64-apple-darwin10 -fvisibility=hidden -fsanitize=cfi -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI
+// RUN: %clang -target x86_64-pc-win32 -fvisibility=hidden -fsanitize=cfi -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-NOMFCALL
+// RUN: %clang -target x86_64-linux-gnu -fvisibility=hidden -fsanitize=cfi -fsanitize-cfi-cross-dso -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-NOMFCALL
// RUN: %clang -target x86_64-linux-gnu -fvisibility=hidden -fsanitize=cfi-derived-cast -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-DCAST
// RUN: %clang -target x86_64-linux-gnu -fvisibility=hidden -fsanitize=cfi-unrelated-cast -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-UCAST
// RUN: %clang -target x86_64-linux-gnu -flto -fvisibility=hidden -fsanitize=cfi-nvcall -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-NVCALL
@@ -451,7 +492,8 @@
// RUN: %clang -target aarch64-linux-gnu -fvisibility=hidden -fsanitize=cfi -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI
// RUN: %clang -target arm-linux-android -fvisibility=hidden -fsanitize=cfi -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI
// RUN: %clang -target aarch64-linux-android -fvisibility=hidden -fsanitize=cfi -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI
-// CHECK-CFI: -emit-llvm-bc{{.*}}-fsanitize=cfi-derived-cast,cfi-icall,cfi-unrelated-cast,cfi-nvcall,cfi-vcall
+// CHECK-CFI: -emit-llvm-bc{{.*}}-fsanitize=cfi-derived-cast,cfi-icall,cfi-mfcall,cfi-unrelated-cast,cfi-nvcall,cfi-vcall
+// CHECK-CFI-NOMFCALL: -emit-llvm-bc{{.*}}-fsanitize=cfi-derived-cast,cfi-icall,cfi-unrelated-cast,cfi-nvcall,cfi-vcall
// CHECK-CFI-DCAST: -emit-llvm-bc{{.*}}-fsanitize=cfi-derived-cast
// CHECK-CFI-UCAST: -emit-llvm-bc{{.*}}-fsanitize=cfi-unrelated-cast
// CHECK-CFI-NVCALL: -emit-llvm-bc{{.*}}-fsanitize=cfi-nvcall
@@ -474,7 +516,7 @@
// RUN: %clang -target x86_64-linux-gnu -fsanitize-trap=address -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-TRAP
// CHECK-ASAN-TRAP: error: unsupported argument 'address' to option '-fsanitize-trap'
-// RUN: %clang -target aarch64-linux-gnu -fsanitize-trap=hwaddress -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-HWASAN-TRAP
+// RUN: %clang -target x86_64-linux-gnu -fsanitize-trap=hwaddress -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-HWASAN-TRAP
// CHECK-HWASAN-TRAP: error: unsupported argument 'hwaddress' to option '-fsanitize-trap'
// RUN: %clang -target x86_64-apple-darwin10 -mmacosx-version-min=10.7 -flto -fsanitize=cfi-vcall -fno-sanitize-trap=cfi -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-NOTRAP-OLD-MACOS
@@ -493,6 +535,9 @@
// CHECK-CFI-NO-CROSS-DSO: -emit-llvm-bc
// CHECK-CFI-NO-CROSS-DSO-NOT: -fsanitize-cfi-cross-dso
+// RUN: %clang -target x86_64-linux-gnu -fvisibility=hidden -fsanitize=cfi-mfcall -fsanitize-cfi-cross-dso -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-MFCALL-CROSS-DSO
+// CHECK-CFI-MFCALL-CROSS-DSO: '-fsanitize=cfi-mfcall' not allowed with '-fsanitize-cfi-cross-dso'
+
// RUN: %clang -target x86_64-linux-gnu -fsanitize=cfi-icall -fsanitize-cfi-icall-generalize-pointers -fvisibility=hidden -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-GENERALIZE-POINTERS
// RUN: %clang -target x86_64-linux-gnu -fsanitize=cfi-icall -fvisibility=hidden -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-CFI-GENERALIZE-POINTERS
// CHECK-CFI-GENERALIZE-POINTERS: -fsanitize-cfi-icall-generalize-pointers
@@ -526,7 +571,7 @@
// NOSP-NOT: "-fsanitize=safe-stack"
// RUN: %clang -target x86_64-linux-gnu -fsanitize=safe-stack -### %s 2>&1 | FileCheck %s -check-prefix=NO-SP
-// RUN: %clang -target x86_64-linux-gnu -fsanitize=address,safe-stack -### %s 2>&1 | FileCheck %s -check-prefix=NO-SP-ASAN
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=address,safe-stack -### %s 2>&1 | FileCheck %s -check-prefix=SP-ASAN
// RUN: %clang -target x86_64-linux-gnu -fstack-protector -fsanitize=safe-stack -### %s 2>&1 | FileCheck %s -check-prefix=SP
// RUN: %clang -target x86_64-linux-gnu -fsanitize=safe-stack -fstack-protector-all -### %s 2>&1 | FileCheck %s -check-prefix=SP
// RUN: %clang -target arm-linux-androideabi -fsanitize=safe-stack -### %s 2>&1 | FileCheck %s -check-prefix=NO-SP
@@ -534,14 +579,11 @@
// RUN: %clang -target i386-contiki-unknown -fsanitize=safe-stack -### %s 2>&1 | FileCheck %s -check-prefix=NO-SP
// NO-SP-NOT: stack-protector
// NO-SP: "-fsanitize=safe-stack"
+// SP-ASAN: error: invalid argument '-fsanitize=safe-stack' not allowed with '-fsanitize=address'
// SP: "-fsanitize=safe-stack"
// SP: -stack-protector
// NO-SP-NOT: stack-protector
-// NO-SP-ASAN-NOT: stack-protector
-// NO-SP-ASAN: "-fsanitize=address,safe-stack"
-// NO-SP-ASAN-NOT: stack-protector
-
// RUN: %clang -target powerpc64-unknown-linux-gnu -fsanitize=memory %s -### 2>&1 | FileCheck %s -check-prefix=CHECK-SANM
// RUN: %clang -target powerpc64le-unknown-linux-gnu -fsanitize=memory %s -### 2>&1 | FileCheck %s -check-prefix=CHECK-SANM
// CHECK-SANM: "-fsanitize=memory"
@@ -591,6 +633,8 @@
// RUN: %clang -target x86_64-scei-ps4 -fsanitize=address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-PS4
// Make sure there are no *.{o,bc} or -l passed before the ASan library.
// CHECK-ASAN-PS4-NOT: {{(\.(o|bc)"? |-l).*-lSceDbgAddressSanitizer_stub_weak}}
+// CHECK-ASAN-PS4: --dependent-lib=libSceDbgAddressSanitizer_stub_weak.a
+// CHECK-ASAN-PS4-NOT: {{(\.(o|bc)"? |-l).*-lSceDbgAddressSanitizer_stub_weak}}
// CHECK-ASAN-PS4: -lSceDbgAddressSanitizer_stub_weak
// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-MINIMAL
@@ -608,26 +652,32 @@
// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-minimal-runtime -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-UBSAN-MINIMAL
// CHECK-ASAN-UBSAN-MINIMAL: error: invalid argument '-fsanitize-minimal-runtime' not allowed with '-fsanitize=address'
-// RUN: %clang -target aarch64-linux-gnu -fsanitize=hwaddress -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-HWASAN-MINIMAL
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=hwaddress -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-HWASAN-MINIMAL
// CHECK-HWASAN-MINIMAL: error: invalid argument '-fsanitize-minimal-runtime' not allowed with '-fsanitize=hwaddress'
// RUN: %clang -target x86_64-linux-gnu -fsanitize=cfi -flto -fvisibility=hidden -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-MINIMAL
-// CHECK-CFI-MINIMAL: "-fsanitize=cfi-derived-cast,cfi-icall,cfi-unrelated-cast,cfi-nvcall,cfi-vcall"
-// CHECK-CFI-MINIMAL: "-fsanitize-trap=cfi-derived-cast,cfi-icall,cfi-unrelated-cast,cfi-nvcall,cfi-vcall"
+// CHECK-CFI-MINIMAL: "-fsanitize=cfi-derived-cast,cfi-icall,cfi-mfcall,cfi-unrelated-cast,cfi-nvcall,cfi-vcall"
+// CHECK-CFI-MINIMAL: "-fsanitize-trap=cfi-derived-cast,cfi-icall,cfi-mfcall,cfi-unrelated-cast,cfi-nvcall,cfi-vcall"
// CHECK-CFI-MINIMAL: "-fsanitize-minimal-runtime"
// RUN: %clang -target x86_64-linux-gnu -fsanitize=cfi -fno-sanitize-trap=cfi-icall -flto -fvisibility=hidden -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-NOTRAP-MINIMAL
// CHECK-CFI-NOTRAP-MINIMAL: error: invalid argument 'fsanitize-minimal-runtime' only allowed with 'fsanitize-trap=cfi'
// RUN: %clang -target x86_64-linux-gnu -fsanitize=cfi -fno-sanitize-trap=cfi-icall -fno-sanitize=cfi-icall -flto -fvisibility=hidden -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-NOICALL-MINIMAL
-// CHECK-CFI-NOICALL-MINIMAL: "-fsanitize=cfi-derived-cast,cfi-unrelated-cast,cfi-nvcall,cfi-vcall"
-// CHECK-CFI-NOICALL-MINIMAL: "-fsanitize-trap=cfi-derived-cast,cfi-unrelated-cast,cfi-nvcall,cfi-vcall"
+// CHECK-CFI-NOICALL-MINIMAL: "-fsanitize=cfi-derived-cast,cfi-mfcall,cfi-unrelated-cast,cfi-nvcall,cfi-vcall"
+// CHECK-CFI-NOICALL-MINIMAL: "-fsanitize-trap=cfi-derived-cast,cfi-mfcall,cfi-unrelated-cast,cfi-nvcall,cfi-vcall"
// CHECK-CFI-NOICALL-MINIMAL: "-fsanitize-minimal-runtime"
// RUN: %clang -target aarch64-linux-gnu -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO
// RUN: %clang -target arm-linux-androideabi -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO
// RUN: %clang -target x86_64-linux-gnu -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO
// RUN: %clang -target i386-linux-gnu -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO
+// RUN: %clang -target mips64-unknown-linux-gnu -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO
+// RUN: %clang -target mips64el-unknown-linux-gnu -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO
+// RUN: %clang -target mips-unknown-linux-gnu -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO
+// RUN: %clang -target mipsel-unknown-linux-gnu -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO
+// RUN: %clang -target powerpc64-unknown-linux -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO
+// RUN: %clang -target powerpc64le-unknown-linux -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO
// CHECK-SCUDO: "-fsanitize=scudo"
// RUN: %clang -target x86_64-linux-gnu -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-PIE
@@ -638,6 +688,14 @@
// RUN: %clang -target x86_64-linux-gnu -fsanitize=scudo,undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-UBSAN
// CHECK-SCUDO-UBSAN: "-fsanitize={{.*}}scudo"
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=scudo -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-MINIMAL
+// CHECK-SCUDO-MINIMAL: "-fsanitize=scudo"
+// CHECK-SCUDO-MINIMAL: "-fsanitize-minimal-runtime"
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined,scudo -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-UBSAN-MINIMAL
+// CHECK-SCUDO-UBSAN-MINIMAL: "-fsanitize={{.*}}scudo"
+// CHECK-SCUDO-UBSAN-MINIMAL: "-fsanitize-minimal-runtime"
+
// RUN: %clang -target powerpc-unknown-linux -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-SCUDO
// CHECK-NO-SCUDO: unsupported option
@@ -649,8 +707,5 @@
// CHECK-SCUDO-MSAN: error: invalid argument '-fsanitize=scudo' not allowed with '-fsanitize=memory'
// RUN: %clang -target x86_64-linux-gnu -fsanitize=scudo,thread %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-TSAN
// CHECK-SCUDO-TSAN: error: invalid argument '-fsanitize=scudo' not allowed with '-fsanitize=thread'
-// RUN: %clang -target aarch64-linux-gnu -fsanitize=scudo,hwaddress %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-HWASAN
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=scudo,hwaddress %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-HWASAN
// CHECK-SCUDO-HWASAN: error: invalid argument '-fsanitize=scudo' not allowed with '-fsanitize=hwaddress'
-
-// RUN: %clang -target x86_64-linux-gnu -fsanitize=hwaddress %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANHA-X86_64
-// CHECK-SANHA-X86_64: unsupported option '-fsanitize=hwaddress' for target
diff --git a/test/Driver/fuchsia.c b/test/Driver/fuchsia.c
index b6946ef40664..fa5459962370 100644
--- a/test/Driver/fuchsia.c
+++ b/test/Driver/fuchsia.c
@@ -1,7 +1,9 @@
-// RUN: %clang %s -### -no-canonical-prefixes --target=x86_64-unknown-fuchsia \
+// RUN: %clang %s -### -no-canonical-prefixes --target=x86_64-fuchsia \
+// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
// RUN: --sysroot=%S/platform 2>&1 \
// RUN: | FileCheck -check-prefixes=CHECK,CHECK-X86_64 %s
-// RUN: %clang %s -### -no-canonical-prefixes --target=aarch64-unknown-fuchsia \
+// RUN: %clang %s -### -no-canonical-prefixes --target=aarch64-fuchsia \
+// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
// RUN: --sysroot=%S/platform 2>&1 \
// RUN: | FileCheck -check-prefixes=CHECK,CHECK-AARCH64 %s
// CHECK: {{.*}}clang{{.*}}" "-cc1"
@@ -10,6 +12,9 @@
// CHECK: "-fuse-init-array"
// CHECK: "-isysroot" "[[SYSROOT:[^"]+]]"
// CHECK: "-internal-externc-isystem" "[[SYSROOT]]{{/|\\\\}}include"
+// CHECK: "-fsanitize=safe-stack"
+// CHECK: "-stack-protector" "2"
+// CHECK: "-fno-common"
// CHECK: {{.*}}ld.lld{{.*}}" "-z" "rodynamic"
// CHECK: "--sysroot=[[SYSROOT]]"
// CHECK: "-pie"
@@ -20,79 +25,116 @@
// CHECK-NOT: crti.o
// CHECK-NOT: crtbegin.o
// CHECK: "-L[[SYSROOT]]{{/|\\\\}}lib"
-// CHECK-X86_64: "{{.*[/\\]}}libclang_rt.builtins-x86_64.a"
-// CHECK-AARCH64: "{{.*[/\\]}}libclang_rt.builtins-aarch64.a"
+// CHECK-X86_64: "{{.*[/\\]}}libclang_rt.builtins.a"
+// CHECK-AARCH64: "{{.*[/\\]}}libclang_rt.builtins.a"
// CHECK: "-lc"
// CHECK-NOT: crtend.o
// CHECK-NOT: crtn.o
-// RUN: %clang %s -### --target=x86_64-unknown-fuchsia -rtlib=libgcc 2>&1 \
+// RUN: %clang %s -### --target=x86_64-fuchsia -rtlib=libgcc 2>&1 \
// RUN: | FileCheck %s -check-prefix=CHECK-RTLIB
// CHECK-RTLIB: error: invalid runtime library name in argument '-rtlib=libgcc'
-// RUN: %clang %s -### --target=x86_64-unknown-fuchsia -static 2>&1 \
+// RUN: %clang %s -### --target=x86_64-fuchsia -static 2>&1 \
// RUN: | FileCheck %s -check-prefix=CHECK-STATIC
// CHECK-STATIC: "-Bstatic"
// CHECK-STATIC: "-Bdynamic"
// CHECK-STATIC: "-lc"
-// RUN: %clang %s -### --target=x86_64-unknown-fuchsia -shared 2>&1 \
+// RUN: %clang %s -### --target=x86_64-fuchsia -shared 2>&1 \
// RUN: | FileCheck %s -check-prefix=CHECK-SHARED
// CHECK-SHARED-NOT: "-pie"
// CHECK-SHARED: "-shared"
-// RUN: %clang %s -### --target=x86_64-unknown-fuchsia -r 2>&1 \
+// RUN: %clang %s -### --target=x86_64-fuchsia -r 2>&1 \
// RUN: | FileCheck %s -check-prefix=CHECK-RELOCATABLE
// CHECK-RELOCATABLE-NOT: "-pie"
// CHECK-RELOCATABLE-NOT: "--build-id"
// CHECK-RELOCATABLE: "-r"
-// RUN: %clang %s -### --target=x86_64-unknown-fuchsia \
+// RUN: %clang %s -### --target=x86_64-fuchsia \
// RUN: -fsanitize=safe-stack 2>&1 \
+// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
// RUN: | FileCheck %s -check-prefix=CHECK-SAFESTACK
// CHECK-SAFESTACK: "-fsanitize=safe-stack"
-// CHECK-SAFESTACK-NOT: "{{.*[/\\]}}libclang_rt.safestack-x86_64.a"
+// CHECK-SAFESTACK-NOT: "{{.*[/\\]}}libclang_rt.safestack.a"
// CHECK-SAFESTACK-NOT: "__safestack_init"
-// RUN: %clang %s -### --target=x86_64-unknown-fuchsia \
+// RUN: %clang %s -### --target=x86_64-fuchsia \
// RUN: -fsanitize=address 2>&1 \
+// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
// RUN: | FileCheck %s -check-prefix=CHECK-ASAN-X86
// CHECK-ASAN-X86: "-fsanitize=address"
// CHECK-ASAN-X86: "-fsanitize-address-globals-dead-stripping"
// CHECK-ASAN-X86: "-dynamic-linker" "asan/ld.so.1"
-// CHECK-ASAN-X86: "{{.*[/\\]}}libclang_rt.asan-x86_64.so"
-// CHECK-ASAN-X86: "{{.*[/\\]}}libclang_rt.asan-preinit-x86_64.a"
+// CHECK-ASAN-X86: "{{.*[/\\]}}libclang_rt.asan.so"
+// CHECK-ASAN-X86: "{{.*[/\\]}}libclang_rt.asan-preinit.a"
// RUN: %clang %s -### --target=aarch64-fuchsia \
// RUN: -fsanitize=address 2>&1 \
+// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
// RUN: | FileCheck %s -check-prefix=CHECK-ASAN-AARCH64
// CHECK-ASAN-AARCH64: "-fsanitize=address"
// CHECK-ASAN-AARCH64: "-fsanitize-address-globals-dead-stripping"
// CHECK-ASAN-AARCH64: "-dynamic-linker" "asan/ld.so.1"
-// CHECK-ASAN-AARCH64: "{{.*[/\\]}}libclang_rt.asan-aarch64.so"
-// CHECK-ASAN-AARCH64: "{{.*[/\\]}}libclang_rt.asan-preinit-aarch64.a"
+// CHECK-ASAN-AARCH64: "{{.*[/\\]}}libclang_rt.asan.so"
+// CHECK-ASAN-AARCH64: "{{.*[/\\]}}libclang_rt.asan-preinit.a"
-// RUN: %clang %s -### --target=x86_64-unknown-fuchsia \
+// RUN: %clang %s -### --target=x86_64-fuchsia \
// RUN: -fsanitize=address -fPIC -shared 2>&1 \
+// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
// RUN: | FileCheck %s -check-prefix=CHECK-ASAN-SHARED
// CHECK-ASAN-SHARED: "-fsanitize=address"
// CHECK-ASAN-SHARED: "-fsanitize-address-globals-dead-stripping"
-// CHECK-ASAN-SHARED: "{{.*[/\\]}}libclang_rt.asan-x86_64.so"
-// CHECK-ASAN-SHARED-NOT: "{{.*[/\\]}}libclang_rt.asan-preinit-x86_64.a"
+// CHECK-ASAN-SHARED: "{{.*[/\\]}}libclang_rt.asan.so"
+// CHECK-ASAN-SHARED-NOT: "{{.*[/\\]}}libclang_rt.asan-preinit.a"
+
+// RUN: %clang %s -### --target=x86_64-fuchsia \
+// RUN: -fsanitize=fuzzer 2>&1 \
+// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
+// RUN: | FileCheck %s -check-prefix=CHECK-FUZZER-X86
+// CHECK-FUZZER-X86: "-fsanitize=fuzzer,fuzzer-no-link,safe-stack"
+// CHECK-FUZZER-X86: "{{.*[/\\]}}libclang_rt.fuzzer.a"
+
+// RUN: %clang %s -### --target=aarch64-fuchsia \
+// RUN: -fsanitize=fuzzer 2>&1 \
+// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
+// RUN: | FileCheck %s -check-prefix=CHECK-FUZZER-AARCH64
+// CHECK-FUZZER-AARCH64: "-fsanitize=fuzzer,fuzzer-no-link,safe-stack"
+// CHECK-FUZZER-AARCH64: "{{.*[/\\]}}libclang_rt.fuzzer.a"
// RUN: %clang %s -### --target=x86_64-fuchsia \
// RUN: -fsanitize=scudo 2>&1 \
+// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
// RUN: | FileCheck %s -check-prefix=CHECK-SCUDO-X86
-// CHECK-SCUDO-X86: "-fsanitize=scudo"
+// CHECK-SCUDO-X86: "-fsanitize=safe-stack,scudo"
// CHECK-SCUDO-X86: "-pie"
+// CHECK-SCUDO-X86: "{{.*[/\\]}}libclang_rt.scudo.so"
// RUN: %clang %s -### --target=aarch64-fuchsia \
// RUN: -fsanitize=scudo 2>&1 \
+// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
// RUN: | FileCheck %s -check-prefix=CHECK-SCUDO-AARCH64
-// CHECK-SCUDO-AARCH64: "-fsanitize=scudo"
+// CHECK-SCUDO-AARCH64: "-fsanitize=safe-stack,scudo"
// CHECK-SCUDO-AARCH64: "-pie"
+// CHECK-SCUDO-AARCH64: "{{.*[/\\]}}libclang_rt.scudo.so"
// RUN: %clang %s -### --target=x86_64-fuchsia \
// RUN: -fsanitize=scudo -fPIC -shared 2>&1 \
+// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
// RUN: | FileCheck %s -check-prefix=CHECK-SCUDO-SHARED
-// CHECK-SCUDO-SHARED: "-fsanitize=scudo"
+// CHECK-SCUDO-SHARED: "-fsanitize=safe-stack,scudo"
+// CHECK-SCUDO-SHARED: "{{.*[/\\]}}libclang_rt.scudo.so"
+
+// RUN: %clang %s -### --target=aarch64-fuchsia \
+// RUN: -O3 -flto -mcpu=cortex-a53 2>&1 \
+// RUN: | FileCheck %s -check-prefix=CHECK-LTO
+// CHECK-LTO: "-plugin-opt=mcpu=cortex-a53"
+// CHECK-LTO: "-plugin-opt=O3"
+
+// RUN: %clang %s -### --target=x86_64-fuchsia \
+// RUN: -flto=thin -flto-jobs=8 2>&1 \
+// RUN: | FileCheck %s -check-prefix=CHECK-THINLTO
+// CHECK-THINLTO: "-plugin-opt=mcpu=x86-64"
+// CHECK-THINLTO: "-plugin-opt=thinlto"
+// CHECK-THINLTO: "-plugin-opt=jobs=8"
diff --git a/test/Driver/fuchsia.cpp b/test/Driver/fuchsia.cpp
index cbd08adb4490..83b18752260c 100644
--- a/test/Driver/fuchsia.cpp
+++ b/test/Driver/fuchsia.cpp
@@ -4,7 +4,7 @@
// CHECK: "-triple" "x86_64-fuchsia"
// CHECK: "-fuse-init-array"
// CHECK: "-isysroot" "[[SYSROOT:[^"]+]]"
-// CHECK: "-internal-isystem" "{{.*[/\\]}}x86_64-fuchsia{{/|\\\\}}include{{/|\\\\}}c++{{/|\\\\}}v1"
+// CHECK: "-internal-isystem" "{{.*[/\\]}}include{{/|\\\\}}c++{{/|\\\\}}v1"
// CHECK: "-internal-externc-isystem" "[[SYSROOT]]{{/|\\\\}}include"
// CHECK: {{.*}}ld.lld{{.*}}" "-z" "rodynamic"
// CHECK: "--sysroot=[[SYSROOT]]"
@@ -15,7 +15,7 @@
// CHECK-NOT: crti.o
// CHECK-NOT: crtbegin.o
// CHECK: "-L[[SYSROOT]]{{/|\\\\}}lib"
-// CHECK: "-lc++" "-lc++abi" "-lunwind" "-lm"
+// CHECK: "-lc++" "-lm"
// CHECK: "{{.*[/\\]}}libclang_rt.builtins-x86_64.a"
// CHECK: "-lc"
// CHECK-NOT: crtend.o
@@ -27,8 +27,8 @@
// RUN: %clangxx %s -### --target=x86_64-unknown-fuchsia -static-libstdc++ 2>&1 \
// RUN: | FileCheck %s -check-prefix=CHECK-STATIC
-// CHECK-STATIC-NOT: "-Bstatic"
-// CHECK-STATIC: "-lc++" "-lc++abi" "-lunwind"
-// CHECK-STATIC-NOT: "-Bdynamic"
+// CHECK-STATIC: "-Bstatic"
+// CHECK-STATIC: "-lc++"
+// CHECK-STATIC: "-Bdynamic"
// CHECK-STATIC: "-lm"
// CHECK-STATIC: "-lc"
diff --git a/test/Driver/function-alignment.c b/test/Driver/function-alignment.c
new file mode 100644
index 000000000000..3dd6ad1cbaa9
--- /dev/null
+++ b/test/Driver/function-alignment.c
@@ -0,0 +1,17 @@
+// RUN: %clang -### %s 2>&1 | FileCheck %s -check-prefix CHECK-0
+// RUN: %clang -### -falign-functions %s 2>&1 | FileCheck %s -check-prefix CHECK-1
+// RUN: %clang -### -falign-functions=1 %s 2>&1 | FileCheck %s -check-prefix CHECK-1
+// RUN: %clang -### -falign-functions=2 %s 2>&1 | FileCheck %s -check-prefix CHECK-2
+// RUN: %clang -### -falign-functions=3 %s 2>&1 | FileCheck %s -check-prefix CHECK-3
+// RUN: %clang -### -falign-functions=4 %s 2>&1 | FileCheck %s -check-prefix CHECK-4
+// RUN: %clang -### -falign-functions=65537 %s 2>&1 | FileCheck %s -check-prefix CHECK-ERR-65537
+// RUN: %clang -### -falign-functions=a %s 2>&1 | FileCheck %s -check-prefix CHECK-ERR-A
+
+// CHECK-0-NOT: "-function-alignment"
+// CHECK-1-NOT: "-function-alignment"
+// CHECK-2: "-function-alignment" "1"
+// CHECK-3: "-function-alignment" "2"
+// CHECK-4: "-function-alignment" "2"
+// CHECK-ERR-65537: error: invalid integral value '65537' in '-falign-functions=65537'
+// CHECK-ERR-A: error: invalid integral value 'a' in '-falign-functions=a'
+
diff --git a/test/Driver/fuse-ld-windows.c b/test/Driver/fuse-ld-windows.c
new file mode 100644
index 000000000000..089f2961b75d
--- /dev/null
+++ b/test/Driver/fuse-ld-windows.c
@@ -0,0 +1,25 @@
+// REQUIRES: system-windows
+
+// We used to require adding ".exe" suffix when cross-compiling on Windows.
+// RUN: %clang %s -### -o %t.o -target i386-unknown-linux \
+// RUN: -B %S/Inputs/fuse_ld_windows -fuse-ld=foo 2>&1 \
+// RUN: | FileCheck %s
+
+// Check that the old variant still works.
+// RUN: %clang %s -### -o %t.o -target i386-unknown-linux \
+// RUN: -B %S/Inputs/fuse_ld_windows -fuse-ld=foo.exe 2>&1 \
+// RUN: | FileCheck %s
+
+// With the full path, the extension can be omitted, too,
+// because Windows allows that.
+// RUN: %clang %s -### -o %t.o -target i386-unknown-linux \
+// RUN: -fuse-ld=%S/Inputs/fuse_ld_windows/ld.foo 2>&1 \
+// RUN: | FileCheck %s
+
+// Check that the full path with the extension works too.
+// RUN: %clang %s -### -o %t.o -target i386-unknown-linux \
+// RUN: -fuse-ld=%S/Inputs/fuse_ld_windows/ld.foo.exe 2>&1 \
+// RUN: | FileCheck %s
+
+// CHECK-NOT: invalid linker name
+// CHECK: /Inputs/fuse_ld_windows{{/|\\\\}}ld.foo
diff --git a/test/Driver/fuzzer.c b/test/Driver/fuzzer.c
index 3fdf5ab9c9b9..5a371e260c60 100644
--- a/test/Driver/fuzzer.c
+++ b/test/Driver/fuzzer.c
@@ -1,6 +1,6 @@
// Test flags inserted by -fsanitize=fuzzer.
-// RUN: %clang -fsanitize=fuzzer %s -target x86_64-apple-darwin14 -### 2>&1 | FileCheck --check-prefixes=CHECK-FUZZER-LIB,CHECK-COVERAGE-FLAGS %s
+// RUN: %clang -fsanitize=fuzzer %s -target x86_64-apple-darwin14 -resource-dir %S/Inputs/resource_dir -### 2>&1 | FileCheck --check-prefixes=CHECK-FUZZER-LIB,CHECK-COVERAGE-FLAGS %s
//
// CHECK-FUZZER-LIB: libclang_rt.fuzzer
// CHECK-COVERAGE: -fsanitize-coverage-inline-8bit-counters
@@ -8,21 +8,21 @@
// CHECK-COVERAGE-SAME: -fsanitize-coverage-trace-cmp
// CHECK-COVERAGE-SAME: -fsanitize-coverage-pc-table
-// RUN: %clang -fsanitize=fuzzer -target i386-unknown-linux -stdlib=platform %s -### 2>&1 | FileCheck --check-prefixes=CHECK-LIBCXX-LINUX %s
+// RUN: %clang -fsanitize=fuzzer -target i386-unknown-linux -stdlib=platform -resource-dir %S/Inputs/resource_dir %s -### 2>&1 | FileCheck --check-prefixes=CHECK-LIBCXX-LINUX %s
//
// CHECK-LIBCXX-LINUX: -lstdc++
-// RUN: %clang -target x86_64-apple-darwin14 -fsanitize=fuzzer %s -### 2>&1 | FileCheck --check-prefixes=CHECK-LIBCXX-DARWIN %s
+// RUN: %clang -target x86_64-apple-darwin14 -fsanitize=fuzzer -resource-dir %S/Inputs/resource_dir %s -### 2>&1 | FileCheck --check-prefixes=CHECK-LIBCXX-DARWIN %s
//
// CHECK-LIBCXX-DARWIN: -lc++
// Check that we don't link in libFuzzer.a when producing a shared object.
-// RUN: %clang -fsanitize=fuzzer %s -shared -o %t.so -### 2>&1 | FileCheck --check-prefixes=CHECK-NOLIB-SO %s
+// RUN: %clang -fsanitize=fuzzer %s -shared -o %t.so -resource-dir %S/Inputs/resource_dir -### 2>&1 | FileCheck --check-prefixes=CHECK-NOLIB-SO %s
// CHECK-NOLIB-SO-NOT: libclang_rt.libfuzzer
// Check that we don't link in libFuzzer when compiling with -fsanitize=fuzzer-no-link.
-// RUN: %clang -fsanitize=fuzzer-no-link %s -target x86_64-apple-darwin14 -### 2>&1 | FileCheck --check-prefixes=CHECK-NOLIB,CHECK-COV %s
+// RUN: %clang -fsanitize=fuzzer-no-link %s -target x86_64-apple-darwin14 -resource-dir %S/Inputs/resource_dir -### 2>&1 | FileCheck --check-prefixes=CHECK-NOLIB,CHECK-COV %s
// CHECK-NOLIB-NOT: libclang_rt.libfuzzer
// CHECK-COV: -fsanitize-coverage-inline-8bit-counters
diff --git a/test/Driver/gcc_forward.c b/test/Driver/gcc_forward.c
index d28e432b1e17..f75b1c738b05 100644
--- a/test/Driver/gcc_forward.c
+++ b/test/Driver/gcc_forward.c
@@ -34,3 +34,9 @@
// RUN: | FileCheck --check-prefix=CHECK-ASM %s
// CHECK-ASM: as
// CHECK-ASM-NOT: "-g"
+
+// Check that we're not forwarding -mno-unaligned-access.
+// RUN: %clang -target aarch64-none-elf -mno-unaligned-access %s -### 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-ARM %s
+// CHECK-ARM: gcc{{[^"]*}}"
+// CHECK-ARM-NOT: -mno-unaligned-access
diff --git a/test/Driver/global-isel.c b/test/Driver/global-isel.c
new file mode 100644
index 000000000000..f4fc6a758ac2
--- /dev/null
+++ b/test/Driver/global-isel.c
@@ -0,0 +1,24 @@
+// REQUIRES: x86-registered-target,aarch64-registered-target
+
+// RUN: %clang -fexperimental-isel -S -### %s 2>&1 | FileCheck --check-prefix=ENABLED %s
+// RUN: %clang -fno-experimental-isel -S -### %s 2>&1 | FileCheck --check-prefix=DISABLED %s
+
+// RUN: %clang -target aarch64 -fexperimental-isel -S %s -### 2>&1 | FileCheck --check-prefix=ARM64-DEFAULT %s
+// RUN: %clang -target aarch64 -fexperimental-isel -S -O0 %s -### 2>&1 | FileCheck --check-prefix=ARM64-O0 %s
+// RUN: %clang -target aarch64 -fexperimental-isel -S -O2 %s -### 2>&1 | FileCheck --check-prefix=ARM64-O2 %s
+// RUN: %clang -target aarch64 -fexperimental-isel -Wno-experimental-isel -S -O2 %s -### 2>&1 | FileCheck --check-prefix=ARM64-O2-NOWARN %s
+
+// RUN: %clang -target x86_64 -fexperimental-isel -S %s -### 2>&1 | FileCheck --check-prefix=X86_64 %s
+
+// ENABLED: "-mllvm" "-global-isel=1"
+// DISABLED: "-mllvm" "-global-isel=0"
+
+// ARM64-DEFAULT-NOT: warning: -fexperimental-sel
+// ARM64-DEFAULT-NOT: "-global-isel-abort=2"
+// ARM64-O0-NOT: warning: -fexperimental-sel
+// ARM64-O2: warning: -fexperimental-isel support is incomplete for this architecture at the current optimization level
+// ARM64-O2: "-mllvm" "-global-isel-abort=2"
+// ARM64-O2-NOWARN-NOT: warning: -fexperimental-isel
+
+// X86_64: -fexperimental-isel support for the 'x86_64' architecture is incomplete
+// X86_64: "-mllvm" "-global-isel-abort=2"
diff --git a/test/Driver/hexagon-hvx.c b/test/Driver/hexagon-hvx.c
index 171d586760ed..70699ce3df52 100644
--- a/test/Driver/hexagon-hvx.c
+++ b/test/Driver/hexagon-hvx.c
@@ -11,16 +11,13 @@
// CHECKHVX162: "-target-feature" "+hvxv62"
// RUN: %clang -c %s -### -target hexagon-unknown-elf -mv65 -mhvx \
-// RUN: -mhvx-double 2>&1 | FileCheck -check-prefix=CHECKHVX2 %s
+// RUN: -mhvx-length=128B 2>&1 | FileCheck -check-prefix=CHECKHVX2 %s
// RUN: %clang -c %s -### -target hexagon-unknown-elf -mv62 -mhvx \
-// RUN: -mhvx-double 2>&1 | FileCheck -check-prefix=CHECKHVX2 %s
-
-// RUN: %clang -c %s -### -target hexagon-unknown-elf -mv65 -mhvx \
// RUN: -mhvx-length=128B 2>&1 | FileCheck -check-prefix=CHECKHVX2 %s
// RUN: %clang -c %s -### -target hexagon-unknown-elf -mv62 -mhvx \
-// RUN: -mhvx-length=128B 2>&1 | FileCheck -check-prefix=CHECKHVX2 %s
+// RUN: -mhvx-length=128b 2>&1 | FileCheck -check-prefix=CHECKHVX2 %s
// CHECKHVX2-NOT: "-target-feature" "+hvx-length64b"
// CHECKHVX2: "-target-feature" "+hvx-length128b"
@@ -31,26 +28,14 @@
// RUN: | FileCheck -check-prefix=CHECKHVX3 %s
// CHECKHVX3-NOT: "-target-feature" "+hvx
-// -mhvx-double is deprecated.
-// RUN: %clang -c %s -### -target hexagon-unknown-elf -mv62 -mhvx-double \
-// RUN: 2>&1 | FileCheck -check-prefix=CHECK-DEPRECATED %s
-// CHECK-DEPRECATED: warning: argument '-mhvx-double' is deprecated, use '-mhvx-length=128B' instead [-Wdeprecated]
-
-// -mno-hvx-double is deprecated.
-// RUN: %clang -c %s -### -target hexagon-unknown-elf -mv62 -mno-hvx-double \
-// RUN: 2>&1 | FileCheck -check-prefix=CHECK-NODEPRECATED %s
-// CHECK-NODEPRECATED: warning: argument '-mno-hvx-double' is deprecated, use '-mno-hvx' instead [-Wdeprecated]
-
-// No hvx target feature must be added if -mno-hvx/-mno-hvx-double occurs last
+// No hvx target feature must be added if -mno-hvx occurs last
// RUN: %clang -c %s -### -target hexagon-unknown-elf -mv62 -mno-hvx \
// RUN: 2>&1 | FileCheck -check-prefix=CHECK-NOHVX %s
// RUN: %clang -c %s -### -target hexagon-unknown-elf -mv62 -mhvx -mno-hvx \
// RUN: 2>&1 | FileCheck -check-prefix=CHECK-NOHVX %s
-// RUN: %clang -c %s -### -target hexagon-unknown-elf -mv62 -mhvx -mno-hvx-double \
-// RUN: 2>&1 | FileCheck -check-prefix=CHECK-NOHVX %s
// CHECK-NOHVX-NOT: "-target-feature" "+hvx
-// Hvx target feature should be added if -mno-hvx doesnot occur last
+// Hvx target feature should be added if -mno-hvx doesn't occur last
// RUN: %clang -c %s -### -target hexagon-unknown-elf -mv62 -mno-hvx -mhvx\
// RUN: 2>&1 | FileCheck -check-prefix=CHECK-HVXFEAT %s
// CHECK-HVXFEAT: "-target-feature" "+hvxv62"
@@ -65,7 +50,7 @@
// RUN: 2>&1 | FileCheck -check-prefix=CHECK-HVXEQ %s
// CHECK-HVXEQ: "-target-feature" "+hvxv62"
-// Honor the last occured -mhvx=, -mhvx flag.
+// Honor the last occurred -mhvx=, -mhvx flag.
// RUN: %clang -c %s -### -target hexagon-unknown-elf -mv60 -mhvx=v62 -mhvx\
// RUN: 2>&1 | FileCheck -check-prefix=CHECK-HVXEQ-PRE %s
// CHECK-HVXEQ-PRE-NOT: "-target-feature" "+hvxv62"
@@ -79,8 +64,10 @@
// The default mode on v60,v62 is 64B.
// RUN: %clang -c %s -### -target hexagon-unknown-elf -mv60 -mhvx \
// RUN: 2>&1 | FileCheck -check-prefix=CHECK-HVXLENGTH-64B %s
-// RUN: %clang -c %s -### -target hexagon-unknown-elf -mv60 -mhvx -mhvx-length=64B\
-// RUN: 2>&1 | FileCheck -check-prefix=CHECK-HVXLENGTH-64B %s
+// RUN: %clang -c %s -### -target hexagon-unknown-elf -mv60 -mhvx \
+// RUN: -mhvx-length=64b 2>&1 | FileCheck -check-prefix=CHECK-HVXLENGTH-64B %s
+// RUN: %clang -c %s -### -target hexagon-unknown-elf -mv60 -mhvx \
+// RUN: -mhvx-length=64B 2>&1 | FileCheck -check-prefix=CHECK-HVXLENGTH-64B %s
// CHECK-HVXLENGTH-64B: "-target-feature" "+hvx{{.*}}" "-target-feature" "+hvx-length64b"
// RUN: %clang -c %s -### -target hexagon-unknown-elf -mv62 -mhvx -mhvx-length=128B\
// RUN: 2>&1 | FileCheck -check-prefix=CHECK-HVXLENGTH-128B %s
@@ -91,8 +78,6 @@
// RUN: 2>&1 | FileCheck -check-prefix=CHECK-HVXLENGTH-ERROR %s
// RUN: %clang -c %s -### -target hexagon-unknown-elf -mhvx-length=128B \
// RUN: 2>&1 | FileCheck -check-prefix=CHECK-HVXLENGTH-ERROR %s
-// RUN: %clang -c %s -### -target hexagon-unknown-elf -mhvx-double \
-// RUN: 2>&1 | FileCheck -check-prefix=CHECK-HVXLENGTH-ERROR %s
// CHECK-HVXLENGTH-ERROR: error: -mhvx-length is not supported without a -mhvx/-mhvx= flag
// Error out if an unsupported value is passed to -mhvx-length.
diff --git a/test/Driver/hexagon-memops.c b/test/Driver/hexagon-memops.c
new file mode 100644
index 000000000000..e7a94286ffda
--- /dev/null
+++ b/test/Driver/hexagon-memops.c
@@ -0,0 +1,10 @@
+// RUN: %clang -target hexagon -### -mmemops %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-MEMOPS
+
+// RUN: %clang -target hexagon -### -mno-memops %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-MEMOPS
+
+// CHECK-MEMOPS: "-target-feature" "+memops"
+
+// CHECK-NO-MEMOPS: "-target-feature" "-memops"
+
diff --git a/test/Driver/hexagon-nvj.c b/test/Driver/hexagon-nvj.c
new file mode 100644
index 000000000000..60d3839f83ac
--- /dev/null
+++ b/test/Driver/hexagon-nvj.c
@@ -0,0 +1,10 @@
+// RUN: %clang -target hexagon -### -mnvj %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NVJ
+
+// RUN: %clang -target hexagon -### -mno-nvj %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-NVJ
+
+// CHECK-NVJ: "-target-feature" "+nvj"
+
+// CHECK-NO-NVJ: "-target-feature" "-nvj"
+
diff --git a/test/Driver/hexagon-nvs.c b/test/Driver/hexagon-nvs.c
new file mode 100644
index 000000000000..a0130e32c9fd
--- /dev/null
+++ b/test/Driver/hexagon-nvs.c
@@ -0,0 +1,10 @@
+// RUN: %clang -target hexagon -### -mnvs %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NVS
+
+// RUN: %clang -target hexagon -### -mno-nvs %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-NVS
+
+// CHECK-NVS: "-target-feature" "+nvs"
+
+// CHECK-NO-NVS: "-target-feature" "-nvs"
+
diff --git a/test/Driver/hexagon-packets.c b/test/Driver/hexagon-packets.c
new file mode 100644
index 000000000000..820c7314344f
--- /dev/null
+++ b/test/Driver/hexagon-packets.c
@@ -0,0 +1,10 @@
+// RUN: %clang -target hexagon -### -mpackets %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-PACKETS
+
+// RUN: %clang -target hexagon -### -mno-packets %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-PACKETS
+
+// CHECK-PACKETS: "-target-feature" "+packets"
+
+// CHECK-NO-PACKETS: "-target-feature" "-packets"
+
diff --git a/test/Driver/hexagon-toolchain-elf.c b/test/Driver/hexagon-toolchain-elf.c
index 7dc82f351998..8f4c320ce45b 100644
--- a/test/Driver/hexagon-toolchain-elf.c
+++ b/test/Driver/hexagon-toolchain-elf.c
@@ -504,12 +504,22 @@
// CHECK060-NEXT: hexagon-link
// -----------------------------------------------------------------------------
+// ffixed-r19
+// -----------------------------------------------------------------------------
+// RUN: %clang -### -target hexagon-unknown-elf -ffixed-r19 %s 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK070 %s
+// CHECK070: "-target-feature" "+reserved-r19"
+// RUN: %clang -### -target hexagon-unknown-elf %s 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK071 %s
+// CHECK071-NOT: "+reserved-r19"
+
+// -----------------------------------------------------------------------------
// Misc Defaults
// -----------------------------------------------------------------------------
// RUN: %clang -### -target hexagon-unknown-elf \
// RUN: -ccc-install-dir %S/Inputs/hexagon_tree/Tools/bin \
// RUN: -mcpu=hexagonv60 \
// RUN: %s 2>&1 \
-// RUN: | FileCheck -check-prefix=CHECK070 %s
-// CHECK070: "-cc1"
-// CHECK070: "-Wreturn-type"
+// RUN: | FileCheck -check-prefix=CHECK080 %s
+// CHECK080: "-cc1"
+// CHECK080: "-Wreturn-type"
diff --git a/test/Driver/hexagon-vectorize.c b/test/Driver/hexagon-vectorize.c
new file mode 100644
index 000000000000..dcd6a09222eb
--- /dev/null
+++ b/test/Driver/hexagon-vectorize.c
@@ -0,0 +1,9 @@
+// RUN: %clang -target hexagon -### %s 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT
+// RUN: %clang -target hexagon -fvectorize -### %s 2>&1 | FileCheck %s --check-prefix=CHECK-VECTOR
+// RUN: %clang -target hexagon -fvectorize -fno-vectorize -### %s 2>&1 | FileCheck %s --check-prefix=CHECK-NOVECTOR
+// RUN: %clang -target hexagon -fvectorize -### %s 2>&1 | FileCheck %s --check-prefix=CHECK-NEEDHVX
+
+// CHECK-DEFAULT-NOT: hexagon-autohvx
+// CHECK-VECTOR: "-mllvm" "-hexagon-autohvx"
+// CHECK-NOVECTOR-NOT: hexagon-autohvx
+// CHECK-NEEDHVX: warning: auto-vectorization requires HVX, use -mhvx to enable it
diff --git a/test/Driver/hip-binding.hip b/test/Driver/hip-binding.hip
new file mode 100644
index 000000000000..c08cc6736211
--- /dev/null
+++ b/test/Driver/hip-binding.hip
@@ -0,0 +1,15 @@
+// REQUIRES: clang-driver
+// REQUIRES: x86-registered-target
+// REQUIRES: amdgpu-registered-target
+
+// RUN: touch %t.o
+// RUN: %clang --hip-link -ccc-print-bindings -target x86_64-linux-gnu \
+// RUN: --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %t.o\
+// RUN: 2>&1 | FileCheck %s
+
+// CHECK: # "amdgcn-amd-amdhsa" - "offload bundler", inputs: ["[[IN:.*o]]"], outputs: ["[[OBJ1:.*o]]", "[[OBJ2:.*o]]", "[[OBJ3:.*o]]"]
+// CHECK: # "amdgcn-amd-amdhsa" - "AMDGCN::Linker", inputs: ["[[OBJ2]]"], output: "[[IMG2:.*out]]"
+// CHECK-NOT: offload bundler
+// CHECK: # "amdgcn-amd-amdhsa" - "AMDGCN::Linker", inputs: ["[[OBJ3]]"], output: "[[IMG3:.*out]]"
+// CHECK-NOT: offload bundler
+// CHECK: # "x86_64--linux-gnu" - "GNU::Linker", inputs: ["[[OBJ1]]", "[[IMG2]]", "[[IMG3]]"], output: "a.out"
diff --git a/test/Driver/hip-device-libs.hip b/test/Driver/hip-device-libs.hip
new file mode 100644
index 000000000000..04afab1b73ad
--- /dev/null
+++ b/test/Driver/hip-device-libs.hip
@@ -0,0 +1,28 @@
+// REQUIRES: clang-driver
+// REQUIRES: x86-registered-target
+// REQUIRES: amdgpu-registered-target
+
+// Test flush-denormals-to-zero enabled uses oclc_daz_opt_on
+
+// RUN: %clang -### -target x86_64-linux-gnu \
+// RUN: -x hip --cuda-gpu-arch=gfx900 \
+// RUN: --hip-device-lib-path=%S/Inputs/hip_dev_lib \
+// RUN: -fcuda-flush-denormals-to-zero \
+// RUN: %S/Inputs/hip_multiple_inputs/b.hip \
+// RUN: 2>&1 | FileCheck %s --check-prefixes=COM,FLUSHD
+
+// Test flush-denormals-to-zero disabled uses oclc_daz_opt_off
+
+// RUN: %clang -### -target x86_64-linux-gnu \
+// RUN: -x hip --cuda-gpu-arch=gfx900 \
+// RUN: --hip-device-lib-path=%S/Inputs/hip_dev_lib \
+// RUN: %S/Inputs/hip_multiple_inputs/b.hip \
+// RUN: 2>&1 | FileCheck %s --check-prefixes=COM,NOFLUSHD
+
+
+// COM: [[LLVM_LINK:"*.llvm-link"]]
+// COM-SAME: {{.*}} "{{.*}}ocml.amdgcn.bc" "{{.*}}ockl.amdgcn.bc" "{{.*}}irif.amdgcn.bc"
+// FLUSHD-SAME: {{.*}} "{{.*}}oclc_daz_opt_on.amdgcn.bc"
+// NOFLUSHD-SAME: {{.*}} "{{.*}}oclc_daz_opt_off.amdgcn.bc"
+// COM-SAME: {{.*}} "-o" "{{.*}}-gfx900-linked-{{.*bc}}"
+
diff --git a/test/Driver/hip-inputs.hip b/test/Driver/hip-inputs.hip
new file mode 100644
index 000000000000..2febe2039ec0
--- /dev/null
+++ b/test/Driver/hip-inputs.hip
@@ -0,0 +1,23 @@
+// REQUIRES: clang-driver
+// REQUIRES: x86-registered-target
+// REQUIRES: amdgpu-registered-target
+
+// RUN: %clang -ccc-print-phases -target x86_64-linux-gnu \
+// RUN: -x hip --cuda-gpu-arch=gfx803 -c \
+// RUN: %S/Inputs/hip_multiple_inputs/a.cu \
+// RUN: %S/Inputs/hip_multiple_inputs/b.hip 2>&1 \
+// RUN: | FileCheck %s
+
+// RUN: not %clang -ccc-print-phases -target x86_64-linux-gnu \
+// RUN: --cuda-gpu-arch=gfx803 -c \
+// RUN: %S/Inputs/hip_multiple_inputs/a.cu \
+// RUN: %S/Inputs/hip_multiple_inputs/b.hip 2>&1 \
+// RUN: | FileCheck -check-prefix=MIX %s
+
+// RUN: not %clang -ccc-print-phases -target x86_64-linux-gnu \
+// RUN: --cuda-gpu-arch=gfx803 -c \
+// RUN: --hip-link %S/Inputs/hip_multiple_inputs/a.cu 2>&1 \
+// RUN: | FileCheck -check-prefix=MIX %s
+
+// CHECK-NOT: error: Mixed Cuda and HIP compilation is not supported.
+// MIX: error: Mixed Cuda and HIP compilation is not supported.
diff --git a/test/Driver/hip-toolchain.hip b/test/Driver/hip-toolchain.hip
new file mode 100644
index 000000000000..ce24e0b4bee8
--- /dev/null
+++ b/test/Driver/hip-toolchain.hip
@@ -0,0 +1,84 @@
+// REQUIRES: clang-driver
+// REQUIRES: x86-registered-target
+// REQUIRES: amdgpu-registered-target
+
+// RUN: %clang -### -target x86_64-linux-gnu \
+// RUN: -x hip --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 \
+// RUN: --hip-device-lib=lib1.bc --hip-device-lib=lib2.bc \
+// RUN: --hip-device-lib-path=%S/Inputs/hip_multiple_inputs/lib1 \
+// RUN: --hip-device-lib-path=%S/Inputs/hip_multiple_inputs/lib2 \
+// RUN: -fuse-ld=lld \
+// RUN: %S/Inputs/hip_multiple_inputs/a.cu \
+// RUN: %S/Inputs/hip_multiple_inputs/b.hip \
+// RUN: 2>&1 | FileCheck %s
+
+// CHECK: [[CLANG:".*clang.*"]] "-cc1" "-triple" "amdgcn-amd-amdhsa"
+// CHECK-SAME: "-aux-triple" "x86_64--linux-gnu" "-emit-llvm-bc"
+// CHECK-SAME: {{.*}} "-main-file-name" "a.cu" {{.*}} "-target-cpu" "gfx803"
+// CHECK-SAME: "-fcuda-is-device" {{.*}} "-o" [[A_BC:".*bc"]] "-x" "hip"
+// CHECK-SAME: {{.*}} [[A_SRC:".*a.cu"]]
+
+// CHECK: [[CLANG]] "-cc1" "-triple" "amdgcn-amd-amdhsa"
+// CHECK-SAME: "-aux-triple" "x86_64--linux-gnu" "-emit-llvm-bc"
+// CHECK-SAME: {{.*}} "-main-file-name" "b.hip" {{.*}} "-target-cpu" "gfx803"
+// CHECK-SAME: "-fcuda-is-device" {{.*}} "-o" [[B_BC:".*bc"]] "-x" "hip"
+// CHECK-SAME: {{.*}} [[B_SRC:".*b.hip"]]
+
+// CHECK: [[LLVM_LINK:"*.llvm-link"]] [[A_BC]] [[B_BC]]
+// CHECK-SAME: "{{.*}}lib1.bc" "{{.*}}lib2.bc"
+// CHECK-SAME: "-o" [[LINKED_BC_DEV1:".*-gfx803-linked-.*bc"]]
+
+// CHECK: [[OPT:".*opt"]] [[LINKED_BC_DEV1]] "-mtriple=amdgcn-amd-amdhsa"
+// CHECK-SAME: "-mcpu=gfx803"
+// CHECK-SAME: "-o" [[OPT_BC_DEV1:".*-gfx803-optimized.*bc"]]
+
+// CHECK: [[LLC: ".*llc"]] [[OPT_BC_DEV1]] "-mtriple=amdgcn-amd-amdhsa"
+// CHECK-SAME: "-filetype=obj" "-mcpu=gfx803" "-o" [[OBJ_DEV1:".*-gfx803-.*o"]]
+
+// CHECK: [[LLD: ".*lld"]] "-flavor" "gnu" "--no-undefined" "-shared"
+// CHECK-SAME: "-o" "[[IMG_DEV1:.*out]]" [[OBJ_DEV1]]
+
+// CHECK: [[CLANG]] "-cc1" "-triple" "amdgcn-amd-amdhsa"
+// CHECK-SAME: "-aux-triple" "x86_64--linux-gnu" "-emit-llvm-bc"
+// CHECK-SAME: {{.*}} "-main-file-name" "a.cu" {{.*}} "-target-cpu" "gfx900"
+// CHECK-SAME: "-fcuda-is-device" {{.*}} "-o" [[A_BC:".*bc"]] "-x" "hip"
+// CHECK-SAME: {{.*}} [[A_SRC]]
+
+// CHECK: [[CLANG]] "-cc1" "-triple" "amdgcn-amd-amdhsa"
+// CHECK-SAME: "-aux-triple" "x86_64--linux-gnu" "-emit-llvm-bc"
+// CHECK-SAME: {{.*}} "-main-file-name" "b.hip" {{.*}} "-target-cpu" "gfx900"
+// CHECK-SAME: "-fcuda-is-device" {{.*}} "-o" [[B_BC:".*bc"]] "-x" "hip"
+// CHECK-SAME: {{.*}} [[B_SRC]]
+
+// CHECK: [[LLVM_LINK]] [[A_BC]] [[B_BC]]
+// CHECK-SAME: "{{.*}}lib1.bc" "{{.*}}lib2.bc"
+// CHECK-SAME: "-o" [[LINKED_BC_DEV2:".*-gfx900-linked-.*bc"]]
+
+// CHECK: [[OPT]] [[LINKED_BC_DEV2]] "-mtriple=amdgcn-amd-amdhsa"
+// CHECK-SAME: "-mcpu=gfx900"
+// CHECK-SAME: "-o" [[OPT_BC_DEV2:".*-gfx900-optimized.*bc"]]
+
+// CHECK: [[LLC]] [[OPT_BC_DEV2]] "-mtriple=amdgcn-amd-amdhsa"
+// CHECK-SAME: "-filetype=obj" "-mcpu=gfx900" "-o" [[OBJ_DEV2:".*-gfx900-.*o"]]
+
+// CHECK: [[LLD]] "-flavor" "gnu" "--no-undefined" "-shared"
+// CHECK-SAME: "-o" "[[IMG_DEV2:.*out]]" [[OBJ_DEV2]]
+
+// CHECK: [[CLANG]] "-cc1" "-triple" "x86_64--linux-gnu"
+// CHECK-SAME: "-aux-triple" "amdgcn-amd-amdhsa" "-emit-obj"
+// CHECK-SAME: {{.*}} "-main-file-name" "a.cu"
+// CHECK-SAME: {{.*}} "-o" [[A_OBJ_HOST:".*o"]] "-x" "hip"
+// CHECK-SAME: {{.*}} [[A_SRC]]
+
+// CHECK: [[CLANG]] "-cc1" "-triple" "x86_64--linux-gnu"
+// CHECK-SAME: "-aux-triple" "amdgcn-amd-amdhsa" "-emit-obj"
+// CHECK-SAME: {{.*}} "-main-file-name" "b.hip"
+// CHECK-SAME: {{.*}} "-o" [[B_OBJ_HOST:".*o"]] "-x" "hip"
+// CHECK-SAME: {{.*}} [[B_SRC]]
+
+// CHECK: [[BUNDLER:".*clang-offload-bundler"]] "-type=o"
+// CHECK-SAME: "-targets={{.*}},hip-amdgcn-amd-amdhsa-gfx803,hip-amdgcn-amd-amdhsa-gfx900"
+// CHECK-SAME: "-inputs={{.*}},[[IMG_DEV1]],[[IMG_DEV2]]" "-outputs=[[BUNDLE:.*o]]"
+
+// CHECK: [[LD:".*ld.*"]] {{.*}} [[A_OBJ_HOST]] [[B_OBJ_HOST]]
+// CHECK-SAME: {{.*}} "-T" "{{.*}}.lk"
diff --git a/test/Driver/lanai-unknown-unknown.cpp b/test/Driver/lanai-unknown-unknown.cpp
index 5ce0adf9f3a4..220a84f9eb2d 100644
--- a/test/Driver/lanai-unknown-unknown.cpp
+++ b/test/Driver/lanai-unknown-unknown.cpp
@@ -11,25 +11,25 @@ typedef __PTRDIFF_TYPE__ ptrdiff_t;
extern "C" {
-// CHECK: @align_c = global i32 1
+// CHECK: @align_c = dso_local global i32 1
int align_c = __alignof(char);
-// CHECK: @align_s = global i32 2
+// CHECK: @align_s = dso_local global i32 2
int align_s = __alignof(short);
-// CHECK: @align_i = global i32 4
+// CHECK: @align_i = dso_local global i32 4
int align_i = __alignof(int);
-// CHECK: @align_l = global i32 4
+// CHECK: @align_l = dso_local global i32 4
int align_l = __alignof(long);
-// CHECK: @align_ll = global i32 8
+// CHECK: @align_ll = dso_local global i32 8
int align_ll = __alignof(long long);
-// CHECK: @align_p = global i32 4
+// CHECK: @align_p = dso_local global i32 4
int align_p = __alignof(void*);
-// CHECK: @align_vl = global i32 4
+// CHECK: @align_vl = dso_local global i32 4
int align_vl = __alignof(va_list);
// Check types
diff --git a/test/Driver/le32-unknown-nacl.cpp b/test/Driver/le32-unknown-nacl.cpp
index 379ddb6c63d8..9bbcdec037ba 100644
--- a/test/Driver/le32-unknown-nacl.cpp
+++ b/test/Driver/le32-unknown-nacl.cpp
@@ -10,34 +10,34 @@ typedef __PTRDIFF_TYPE__ ptrdiff_t;
extern "C" {
-// CHECK: @align_c = global i32 1
+// CHECK: @align_c = dso_local global i32 1
int align_c = __alignof(char);
-// CHECK: @align_s = global i32 2
+// CHECK: @align_s = dso_local global i32 2
int align_s = __alignof(short);
-// CHECK: @align_i = global i32 4
+// CHECK: @align_i = dso_local global i32 4
int align_i = __alignof(int);
-// CHECK: @align_l = global i32 4
+// CHECK: @align_l = dso_local global i32 4
int align_l = __alignof(long);
-// CHECK: @align_ll = global i32 8
+// CHECK: @align_ll = dso_local global i32 8
int align_ll = __alignof(long long);
-// CHECK: @align_p = global i32 4
+// CHECK: @align_p = dso_local global i32 4
int align_p = __alignof(void*);
-// CHECK: @align_f = global i32 4
+// CHECK: @align_f = dso_local global i32 4
int align_f = __alignof(float);
-// CHECK: @align_d = global i32 8
+// CHECK: @align_d = dso_local global i32 8
int align_d = __alignof(double);
-// CHECK: @align_ld = global i32 8
+// CHECK: @align_ld = dso_local global i32 8
int align_ld = __alignof(long double);
-// CHECK: @align_vl = global i32 4
+// CHECK: @align_vl = dso_local global i32 4
int align_vl = __alignof(va_list);
// CHECK: __LITTLE_ENDIAN__defined
diff --git a/test/Driver/le64-unknown-unknown.cpp b/test/Driver/le64-unknown-unknown.cpp
index d0a58598ffe7..8cee9dc375c1 100644
--- a/test/Driver/le64-unknown-unknown.cpp
+++ b/test/Driver/le64-unknown-unknown.cpp
@@ -9,34 +9,34 @@ typedef __PTRDIFF_TYPE__ ptrdiff_t;
extern "C" {
-// CHECK: @align_c = global i32 1
+// CHECK: @align_c = dso_local global i32 1
int align_c = __alignof(char);
-// CHECK: @align_s = global i32 2
+// CHECK: @align_s = dso_local global i32 2
int align_s = __alignof(short);
-// CHECK: @align_i = global i32 4
+// CHECK: @align_i = dso_local global i32 4
int align_i = __alignof(int);
-// CHECK: @align_l = global i32 8
+// CHECK: @align_l = dso_local global i32 8
int align_l = __alignof(long);
-// CHECK: @align_ll = global i32 8
+// CHECK: @align_ll = dso_local global i32 8
int align_ll = __alignof(long long);
-// CHECK: @align_p = global i32 8
+// CHECK: @align_p = dso_local global i32 8
int align_p = __alignof(void*);
-// CHECK: @align_f = global i32 4
+// CHECK: @align_f = dso_local global i32 4
int align_f = __alignof(float);
-// CHECK: @align_d = global i32 8
+// CHECK: @align_d = dso_local global i32 8
int align_d = __alignof(double);
-// CHECK: @align_ld = global i32 8
+// CHECK: @align_ld = dso_local global i32 8
int align_ld = __alignof(long double);
-// CHECK: @align_vl = global i32 4
+// CHECK: @align_vl = dso_local global i32 4
int align_vl = __alignof(va_list);
// CHECK: __LITTLE_ENDIAN__defined
diff --git a/test/Driver/linux-header-search.cpp b/test/Driver/linux-header-search.cpp
index 274895fb4fad..3f024aa49593 100644
--- a/test/Driver/linux-header-search.cpp
+++ b/test/Driver/linux-header-search.cpp
@@ -7,6 +7,7 @@
// RUN: -target x86_64-unknown-linux-gnu \
// RUN: -stdlib=libc++ \
// RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree \
// RUN: --gcc-toolchain="" \
// RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBCXX-SYSROOT %s
@@ -18,6 +19,7 @@
// RUN: -target x86_64-unknown-linux-gnu \
// RUN: -stdlib=libc++ \
// RUN: -ccc-install-dir %S/Inputs/basic_linux_libcxx_tree/usr/bin \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree \
// RUN: --gcc-toolchain="" \
// RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBCXX-INSTALL %s
@@ -30,6 +32,7 @@
// RUN: -target x86_64-unknown-linux-gnu \
// RUN: -stdlib=libc++ \
// RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: --sysroot=%S/Inputs/basic_linux_libcxxv2_tree \
// RUN: --gcc-toolchain="" \
// RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBCXXV2-SYSROOT %s
@@ -41,6 +44,7 @@
// RUN: -target x86_64-unknown-linux-gnu \
// RUN: -stdlib=libc++ \
// RUN: -ccc-install-dir %S/Inputs/basic_linux_libcxxv2_tree/usr/bin \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: --sysroot=%S/Inputs/basic_linux_libcxxv2_tree \
// RUN: --gcc-toolchain="" \
// RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBCXXV2-INSTALL %s
@@ -54,6 +58,7 @@
// RUN: -target x86_64-unknown-linux-gnu \
// RUN: -stdlib=libc++ \
// RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: --sysroot=%S/Inputs/basic_linux_libstdcxx_libcxxv2_tree \
// RUN: --gcc-toolchain="" \
// RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBSTDCXX-LIBCXXV2-SYSROOT %s
@@ -343,6 +348,59 @@
// CHECK-GENTOO-4-9-3-32: "-internal-externc-isystem" "[[SYSROOT]]/include"
// CHECK-GENTOO-4-9-3-32: "-internal-externc-isystem" "[[SYSROOT]]/usr/include"
//
+// Test support for parsing Gentoo's gcc-config -- clang should parse the
+// /etc/env.d/gcc/config-x86_64-pc-linux-gnu file to find CURRENT gcc used.
+// Then should pick the multilibs from version 4.9.x specified in
+// /etc/env.d/gcc/x86_64-pc-linux-gnu-4.9.3.
+// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \
+// RUN: -target x86_64-unknown-linux-gnu -stdlib=libstdc++ \
+// RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_4.9.x_tree \
+// RUN: --gcc-toolchain="" \
+// RUN: | FileCheck --check-prefix=CHECK-GENTOO-4-9-X %s
+//
+// CHECK-GENTOO-4-9-X: "{{.*}}clang{{.*}}" "-cc1"
+// CHECK-GENTOO-4-9-X: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]"
+// CHECK-GENTOO-4-9-X: "-isysroot" "[[SYSROOT:[^"]+]]"
+// CHECK-GENTOO-4-9-X: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x/include/g++-v4.9.3"
+// CHECK-GENTOO-4-9-X: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x/include/g++-v4.9.3/x86_64-pc-linux-gnu"
+// CHECK-GENTOO-4-9-X: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x/include/g++-v4.9.3/backward"
+// CHECK-GENTOO-4-9-X: "-internal-isystem" "[[SYSROOT]]/usr/local/include"
+// CHECK-GENTOO-4-9-X: "-internal-isystem" "[[RESOURCE_DIR]]{{/|\\\\}}include"
+// CHECK-GENTOO-4-9-X: "-internal-externc-isystem" "[[SYSROOT]]/include"
+// CHECK-GENTOO-4-9-X: "-internal-externc-isystem" "[[SYSROOT]]/usr/include"
+//
+// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \
+// RUN: -target x86_64-unknown-linux-gnux32 -stdlib=libstdc++ \
+// RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_4.9.x_tree \
+// RUN: --gcc-toolchain="" \
+// RUN: | FileCheck --check-prefix=CHECK-GENTOO-4-9-X-X32 %s
+// CHECK-GENTOO-4-9-X-X32: "{{.*}}clang{{.*}}" "-cc1"
+// CHECK-GENTOO-4-9-X-X32: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]"
+// CHECK-GENTOO-4-9-X-X32: "-isysroot" "[[SYSROOT:[^"]+]]"
+// CHECK-GENTOO-4-9-X-X32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x/include/g++-v4.9.3"
+// CHECK-GENTOO-4-9-X-X32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x/include/g++-v4.9.3/x86_64-pc-linux-gnu/x32"
+// CHECK-GENTOO-4-9-X-X32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x/include/g++-v4.9.3/backward"
+// CHECK-GENTOO-4-9-X-X32: "-internal-isystem" "[[SYSROOT]]/usr/local/include"
+// CHECK-GENTOO-4-9-X-X32: "-internal-isystem" "[[RESOURCE_DIR]]{{/|\\\\}}include"
+// CHECK-GENTOO-4-9-X-X32: "-internal-externc-isystem" "[[SYSROOT]]/include"
+// CHECK-GENTOO-4-9-X-X32: "-internal-externc-isystem" "[[SYSROOT]]/usr/include"
+//
+// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \
+// RUN: -target i386-unknown-linux-gnu -stdlib=libstdc++ \
+// RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_4.9.x_tree \
+// RUN: --gcc-toolchain="" \
+// RUN: | FileCheck --check-prefix=CHECK-GENTOO-4-9-X-32 %s
+// CHECK-GENTOO-4-9-X-32: "{{.*}}clang{{.*}}" "-cc1"
+// CHECK-GENTOO-4-9-X-32: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]"
+// CHECK-GENTOO-4-9-X-32: "-isysroot" "[[SYSROOT:[^"]+]]"
+// CHECK-GENTOO-4-9-X-32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x/include/g++-v4.9.3"
+// CHECK-GENTOO-4-9-X-32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x/include/g++-v4.9.3/x86_64-pc-linux-gnu/32"
+// CHECK-GENTOO-4-9-X-32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x/include/g++-v4.9.3/backward"
+// CHECK-GENTOO-4-9-X-32: "-internal-isystem" "[[SYSROOT]]/usr/local/include"
+// CHECK-GENTOO-4-9-X-32: "-internal-isystem" "[[RESOURCE_DIR]]{{/|\\\\}}include"
+// CHECK-GENTOO-4-9-X-32: "-internal-externc-isystem" "[[SYSROOT]]/include"
+// CHECK-GENTOO-4-9-X-32: "-internal-externc-isystem" "[[SYSROOT]]/usr/include"
+//
// Check header search on Debian 6 / MIPS64
// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \
// RUN: -target mips64-unknown-linux-gnuabi64 -stdlib=libstdc++ \
diff --git a/test/Driver/linux-ld.c b/test/Driver/linux-ld.c
index 662aabb8671e..02e6618a0460 100644
--- a/test/Driver/linux-ld.c
+++ b/test/Driver/linux-ld.c
@@ -156,7 +156,7 @@
// RUN: | FileCheck --check-prefix=CHECK-LD-64-STATIC %s
// CHECK-LD-64-STATIC-NOT: warning:
// CHECK-LD-64-STATIC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
-// CHECK-LD-64-STATIC-NOT: "--eh-frame-hdr"
+// CHECK-LD-64-STATIC: "--eh-frame-hdr"
// CHECK-LD-64-STATIC: "-m" "elf_x86_64"
// CHECK-LD-64-STATIC-NOT: "-dynamic-linker"
// CHECK-LD-64-STATIC: "-static"
@@ -426,6 +426,7 @@
// RUN: -stdlib=libc++ \
// RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin \
// RUN: --gcc-toolchain="" \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree \
// RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBCXX-SYSROOT %s
// CHECK-BASIC-LIBCXX-SYSROOT: "{{[^"]*}}clang{{[^"]*}}" "-cc1"
@@ -438,6 +439,7 @@
// RUN: -stdlib=libc++ \
// RUN: -ccc-install-dir %S/Inputs/basic_linux_libcxx_tree/usr/bin \
// RUN: --gcc-toolchain="" \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree \
// RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBCXX-INSTALL %s
// CHECK-BASIC-LIBCXX-INSTALL: "{{[^"]*}}clang{{[^"]*}}" "-cc1"
@@ -1780,3 +1782,35 @@
// CHECK-LD-GENTOO-X32: "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed"
// CHECK-LD-GENTOO-X32: "-lc"
// CHECK-LD-GENTOO-X32: "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed"
+
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: --target=x86_64-unknown-linux-gnu \
+// RUN: --gcc-toolchain="%S/Inputs/rhel_7_tree/opt/rh/devtoolset-7/root/usr" \
+// RUN: --sysroot=%S/Inputs/rhel_7_tree \
+// RUN: | FileCheck --check-prefix=CHECK-LD-RHEL7-DTS %s
+// CHECK-LD-RHEL7-DTS: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
+// CHECK-LD-RHLE7-DTS: Selected GCC installation: [[GCC_INSTALL:[[SYSROOT]]/lib/gcc/x86_64-redhat-linux/7]]
+// CHECK-LD-RHEL7-DTS-NOT: /usr/bin/ld
+// CHECK-LD-RHLE7-DTS: [[GCC_INSTALL]/../../../bin/ld
+
+// Check whether gcc7 install works fine on Amazon Linux AMI
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: --target=x86_64-amazon-linux -rtlib=libgcc \
+// RUN: --gcc-toolchain="" \
+// RUN: --sysroot=%S/Inputs/ami_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-LD-AMI %s
+// CHECK-LD-AMI-NOT: warning:
+// CHECK-LD-AMI: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
+// CHECK-LD-AMI: "--eh-frame-hdr"
+// CHECK-LD-AMI: "-m" "elf_x86_64"
+// CHECK-LD-AMI: "-dynamic-linker"
+// CHECK-LD-AMI: "{{.*}}/usr/lib/gcc/x86_64-amazon-linux/7{{/|\\\\}}crtbegin.o"
+// CHECK-LD-AMI: "-L[[SYSROOT]]/usr/lib/gcc/x86_64-amazon-linux/7"
+// CHECK-LD-AMI: "-L[[SYSROOT]]/usr/lib/gcc/x86_64-amazon-linux/7/../../../../lib64"
+// CHECK-LD-AMI: "-L[[SYSROOT]]/usr/lib/gcc/x86_64-amazon-linux/7/../../.."
+// CHECK-LD-AMI: "-L[[SYSROOT]]/lib"
+// CHECK-LD-AMI: "-L[[SYSROOT]]/usr/lib"
+// CHECK-LD-AMI: "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed"
+// CHECK-LD-AMI: "-lc"
+// CHECK-LD-AMI: "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed"
+//
diff --git a/test/Driver/linux-per-target-runtime-dir.c b/test/Driver/linux-per-target-runtime-dir.c
new file mode 100644
index 000000000000..aa9c1017f6ad
--- /dev/null
+++ b/test/Driver/linux-per-target-runtime-dir.c
@@ -0,0 +1,21 @@
+// RUN: %clang -no-canonical-prefixes -x c++ %s -### -o %t.o 2>&1 \
+// RUN: --target=x86_64-linux-gnu \
+// RUN: -stdlib=libc++ \
+// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
+// RUN: -ccc-install-dir %S/Inputs/basic_linux_libcxx_tree/usr/bin \
+// RUN: --gcc-toolchain="" \
+// RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree \
+// RUN: | FileCheck --check-prefix=CHECK-PER-TARGET-RUNTIME %s
+// CHECK-PER-TARGET-RUNTIME: "{{[^"]*}}clang{{[^"]*}}" "-cc1"
+// CHECK-PER-TARGET-RUNTIME: "-resource-dir" "[[RESDIR:[^"]*]]"
+// CHECK-PER-TARGET-RUNTIME: "-isysroot" "[[SYSROOT:[^"]+]]"
+// CHECK-PER-TARGET-RUNTIME: "-internal-isystem" "[[RESDIR]]/include/c++/v1"
+// CHECK-PER-TARGET-RUNTIME: "-internal-isystem" "[[SYSROOT]]/usr/local/include"
+// CHECK-PER-TARGET-RUNTIME: "--sysroot=[[SYSROOT]]"
+// CHECK-PER-TARGET-RUNTIME: "-L[[RESDIR]]{{/|\\\\}}x86_64-linux-gnu{{/|\\\\}}lib"
+
+// RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \
+// RUN: --target=x86_64-linux-gnu \
+// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
+// RUN: | FileCheck --check-prefix=CHECK-CLANGRT-X8664 %s
+// CHECK-CLANGRT-X8664: x86_64-linux-gnu{{/|\\}}lib{{/|\\}}libclang_rt.builtins.a
diff --git a/test/Driver/lit.local.cfg b/test/Driver/lit.local.cfg
index ff831e7fe488..4a4ef2af23b5 100644
--- a/test/Driver/lit.local.cfg
+++ b/test/Driver/lit.local.cfg
@@ -1,5 +1,5 @@
config.suffixes = ['.c', '.cpp', '.h', '.m', '.mm', '.S', '.s', '.f90', '.f95',
- '.cu', '.rs', '.cl']
+ '.cu', '.rs', '.cl', '.hip']
config.substitutions = list(config.substitutions)
config.substitutions.insert(0,
('%clang_cc1',
diff --git a/test/Driver/lto-dwo.c b/test/Driver/lto-dwo.c
new file mode 100644
index 000000000000..486ace43f01a
--- /dev/null
+++ b/test/Driver/lto-dwo.c
@@ -0,0 +1,6 @@
+// Confirm that -gsplit-dwarf=DIR is passed to linker
+
+// RUN: %clang -target x86_64-unknown-linux -### %s -flto=thin -gsplit-dwarf -o a.out 2> %t
+// RUN: FileCheck -check-prefix=CHECK-LINK-DWO-DIR-DEFAULT < %t %s
+//
+// CHECK-LINK-DWO-DIR-DEFAULT: "-plugin-opt=dwo_dir=a.out_dwo"
diff --git a/test/Driver/lto.cu b/test/Driver/lto.cu
new file mode 100644
index 000000000000..821dfcd20319
--- /dev/null
+++ b/test/Driver/lto.cu
@@ -0,0 +1,80 @@
+// REQUIRES: clang-driver
+// REQUIRES: x86-registered-target
+// REQUIRES: nvptx-registered-target
+
+// -flto causes a switch to llvm-bc object files.
+// RUN: %clangxx -nocudainc -nocudalib -ccc-print-phases -c %s -flto 2> %t
+// RUN: FileCheck -check-prefix=CHECK-COMPILE-ACTIONS < %t %s
+//
+// CHECK-COMPILE-ACTIONS: 2: compiler, {1}, ir, (host-cuda)
+// CHECK-COMPILE-ACTIONS-NOT: lto-bc
+// CHECK-COMPILE-ACTIONS: 12: backend, {11}, lto-bc, (host-cuda)
+
+// RUN: %clangxx -nocudainc -nocudalib -ccc-print-phases %s -flto 2> %t
+// RUN: FileCheck -check-prefix=CHECK-COMPILELINK-ACTIONS < %t %s
+//
+// CHECK-COMPILELINK-ACTIONS: 0: input, "{{.*}}lto.cu", cuda, (host-cuda)
+// CHECK-COMPILELINK-ACTIONS: 1: preprocessor, {0}, cuda-cpp-output
+// CHECK-COMPILELINK-ACTIONS: 2: compiler, {1}, ir, (host-cuda)
+// CHECK-COMPILELINK-ACTIONS: 3: input, "{{.*}}lto.cu", cuda, (device-cuda, sm_20)
+// CHECK-COMPILELINK-ACTIONS: 4: preprocessor, {3}, cuda-cpp-output, (device-cuda, sm_20)
+// CHECK-COMPILELINK-ACTIONS: 5: compiler, {4}, ir, (device-cuda, sm_20)
+// CHECK-COMPILELINK-ACTIONS: 6: backend, {5}, assembler, (device-cuda, sm_20)
+// CHECK-COMPILELINK-ACTIONS: 7: assembler, {6}, object, (device-cuda, sm_20)
+// CHECK-COMPILELINK-ACTIONS: 8: offload, "device-cuda (nvptx{{.*}}-nvidia-cuda:sm_20)" {7}, object
+// CHECK-COMPILELINK-ACTIONS: 9: offload, "device-cuda (nvptx{{.*}}-nvidia-cuda:sm_20)" {6}, assembler
+// CHECK-COMPILELINK-ACTIONS: 10: linker, {8, 9}, cuda-fatbin, (device-cuda)
+// CHECK-COMPILELINK-ACTIONS: 11: offload, "host-cuda {{.*}}" {2}, "device-cuda{{.*}}" {10}, ir
+// CHECK-COMPILELINK-ACTIONS: 12: backend, {11}, lto-bc, (host-cuda)
+// CHECK-COMPILELINK-ACTIONS: 13: linker, {12}, image, (host-cuda)
+
+// llvm-bc and llvm-ll outputs need to match regular suffixes
+// (unfortunately).
+// RUN: %clangxx %s -nocudainc -nocudalib -flto -save-temps -### 2> %t
+// RUN: FileCheck -check-prefix=CHECK-COMPILELINK-SUFFIXES < %t %s
+//
+// CHECK-COMPILELINK-SUFFIXES: "-o" "[[CPP:.*lto-host.*\.cui]]" "-x" "cuda" "{{.*}}lto.cu"
+// CHECK-COMPILELINK-SUFFIXES: "-o" "[[BC:.*lto-host.*\.bc]]" {{.*}}[[CPP]]"
+// CHECK-COMPILELINK-SUFFIXES: "-o" "[[OBJ:.*lto-host.*\.o]]" {{.*}}[[BC]]"
+// CHECK-COMPILELINK-SUFFIXES: "{{.*}}a.{{(out|exe)}}" {{.*}}[[OBJ]]"
+
+// RUN: %clangxx %s -nocudainc -nocudalib -flto -S -### 2> %t
+// RUN: FileCheck -check-prefix=CHECK-COMPILE-SUFFIXES < %t %s
+//
+// CHECK-COMPILE-SUFFIXES: "-o" "{{.*}}lto.s" "-x" "cuda" "{{.*}}lto.cu"
+
+// RUN: not %clangxx -nocudainc -nocudalib %s -emit-llvm 2>&1 \
+// RUN: | FileCheck --check-prefix=LLVM-LINK %s
+// LLVM-LINK: -emit-llvm cannot be used when linking
+
+// -flto should cause link using gold plugin
+// RUN: %clangxx -nocudainc -nocudalib \
+// RUN: -target x86_64-unknown-linux -### %s -flto 2> %t
+// RUN: FileCheck -check-prefix=CHECK-LINK-LTO-ACTION < %t %s
+//
+// CHECK-LINK-LTO-ACTION: "-plugin" "{{.*}}{{[/\\]}}LLVMgold.{{dll|dylib|so}}"
+
+// -flto=full should cause link using gold plugin
+// RUN: %clangxx -nocudainc -nocudalib \
+// RUN: -target x86_64-unknown-linux -### %s -flto=full 2> %t
+// RUN: FileCheck -check-prefix=CHECK-LINK-FULL-ACTION < %t %s
+//
+// CHECK-LINK-FULL-ACTION: "-plugin" "{{.*}}{{[/\\]}}LLVMgold.{{dll|dylib|so}}"
+
+// Check that subsequent -fno-lto takes precedence
+// RUN: %clangxx -nocudainc -nocudalib \
+// RUN: -target x86_64-unknown-linux -### %s -flto=full -fno-lto 2> %t
+// RUN: FileCheck -check-prefix=CHECK-LINK-NOLTO-ACTION < %t %s
+//
+// CHECK-LINK-NOLTO-ACTION-NOT: "-plugin" "{{.*}}{{[/\\]}}LLVMgold.{{dll|dylib|so}}"
+
+// -flto passes along an explicit debugger tuning argument.
+// RUN: %clangxx -nocudainc -nocudalib \
+// RUN: -target x86_64-unknown-linux -### %s -flto -glldb 2> %t
+// RUN: FileCheck -check-prefix=CHECK-TUNING-LLDB < %t %s
+// RUN: %clangxx -nocudainc -nocudalib \
+// RUN: -target x86_64-unknown-linux -### %s -flto -g 2> %t
+// RUN: FileCheck -check-prefix=CHECK-NO-TUNING < %t %s
+//
+// CHECK-TUNING-LLDB: "-plugin-opt=-debugger-tune=lldb"
+// CHECK-NO-TUNING-NOT: "-plugin-opt=-debugger-tune
diff --git a/test/Driver/masm.c b/test/Driver/masm.c
index 17c639358b0b..5c7251abae83 100644
--- a/test/Driver/masm.c
+++ b/test/Driver/masm.c
@@ -2,11 +2,13 @@
// RUN: %clang -target i386-unknown-linux -masm=att -S %s -### 2>&1 | FileCheck --check-prefix=CHECK-ATT %s
// RUN: %clang -target i386-unknown-linux -S -masm=somerequired %s -### 2>&1 | FileCheck --check-prefix=CHECK-SOMEREQUIRED %s
// RUN: %clang -target arm-unknown-eabi -S -masm=intel %s -### 2>&1 | FileCheck --check-prefix=CHECK-ARM %s
+// RUN: %clang_cl --target=x86_64 /FA -### -- %s 2>&1 | FileCheck --check-prefix=CHECK-CL %s
int f() {
// CHECK-INTEL: -x86-asm-syntax=intel
// CHECK-ATT: -x86-asm-syntax=att
// CHECK-SOMEREQUIRED: error: unsupported argument 'somerequired' to option 'masm='
// CHECK-ARM: warning: argument unused during compilation: '-masm=intel'
+// CHECK-CL: -x86-asm-syntax=intel
return 0;
}
diff --git a/test/Driver/mglobal-merge.c b/test/Driver/mglobal-merge.c
index 271011e985c5..4ea7ae03e78f 100644
--- a/test/Driver/mglobal-merge.c
+++ b/test/Driver/mglobal-merge.c
@@ -10,8 +10,8 @@
// RUN: -mno-global-merge
// RUN: FileCheck --check-prefix=CHECK-NONE < %t %s
-// CHECK-NGM-ARM: "-backend-option" "-arm-global-merge=false"
-// CHECK-NGM-AARCH64: "-backend-option" "-aarch64-enable-global-merge=false"
+// CHECK-NGM-ARM: "-mllvm" "-arm-global-merge=false"
+// CHECK-NGM-AARCH64: "-mllvm" "-aarch64-enable-global-merge=false"
// RUN: %clang -target armv7-unknown-unknown -### -fsyntax-only %s 2> %t \
// RUN: -mglobal-merge
@@ -25,8 +25,8 @@
// RUN: -mglobal-merge
// RUN: FileCheck --check-prefix=CHECK-NONE < %t %s
-// CHECK-GM-ARM: "-backend-option" "-arm-global-merge=true"
-// CHECK-GM-AARCH64: "-backend-option" "-aarch64-enable-global-merge=true"
+// CHECK-GM-ARM: "-mllvm" "-arm-global-merge=true"
+// CHECK-GM-AARCH64: "-mllvm" "-aarch64-enable-global-merge=true"
// RUN: %clang -target armv7-unknown-unknown -### -fsyntax-only %s 2> %t
// RUN: FileCheck --check-prefix=CHECK-NONE < %t %s
diff --git a/test/Driver/mingw-libgcc.c b/test/Driver/mingw-libgcc.c
index 1d45c91651de..bfe2360ed4e6 100644
--- a/test/Driver/mingw-libgcc.c
+++ b/test/Driver/mingw-libgcc.c
@@ -2,11 +2,11 @@
// Verified with gcc version 5.1.0 (i686-posix-dwarf-rev0, Built by MinGW-W64 project).
// gcc, static
-// RUN: %clang -v -target i686-pc-windows-gnu -rtlib=platform -### %s 2>&1 | FileCheck -check-prefix=CHECK_STATIC %s
-// RUN: %clang -static -v -target i686-pc-windows-gnu -rtlib=platform -### %s 2>&1 | FileCheck -check-prefix=CHECK_STATIC %s
-// RUN: %clang -static-libgcc -v -target i686-pc-windows-gnu -rtlib=platform -### %s 2>&1 | FileCheck -check-prefix=CHECK_STATIC %s
-// RUN: %clang -static -shared -v -target i686-pc-windows-gnu -rtlib=platform -### %s 2>&1 | FileCheck -check-prefix=CHECK_STATIC %s
-// RUN: %clang -static-libgcc -shared -v -target i686-pc-windows-gnu -rtlib=platform -### %s 2>&1 | FileCheck -check-prefix=CHECK_STATIC %s
+// RUN: %clang -v -target i686-pc-windows-gnu -rtlib=platform -### %s 2>&1 | FileCheck -check-prefixes=CHECK_STATIC,CHECK_BDYNAMIC %s
+// RUN: %clang -static -v -target i686-pc-windows-gnu -rtlib=platform -### %s 2>&1 | FileCheck -check-prefixes=CHECK_STATIC,CHECK_BSTATIC %s
+// RUN: %clang -static-libgcc -v -target i686-pc-windows-gnu -rtlib=platform -### %s 2>&1 | FileCheck -check-prefixes=CHECK_STATIC,CHECK_BDYNAMIC %s
+// RUN: %clang -static -shared -v -target i686-pc-windows-gnu -rtlib=platform -### %s 2>&1 | FileCheck -check-prefixes=CHECK_STATIC,CHECK_SHARED,CHECK_BSTATIC %s
+// RUN: %clang -static-libgcc -shared -v -target i686-pc-windows-gnu -rtlib=platform -### %s 2>&1 | FileCheck -check-prefixes=CHECK_STATIC,CHECK_SHARED,CHECK_BDYNAMIC %s
// gcc, dynamic
// RUN: %clang -shared -v -target i686-pc-windows-gnu -rtlib=platform -### %s 2>&1 | FileCheck -check-prefix=CHECK_DYNAMIC %s
@@ -21,5 +21,8 @@
// RUN: %clang --driver-mode=g++ -v -target i686-pc-windows-gnu -rtlib=platform -### %s 2>&1 | FileCheck -check-prefix=CHECK_DYNAMIC %s
// RUN: %clang -shared --driver-mode=g++ -v -target i686-pc-windows-gnu -rtlib=platform -### %s 2>&1 | FileCheck -check-prefix=CHECK_DYNAMIC %s
+// CHECK_SHARED: "--shared"
+// CHECK_BSTATIC: "-Bstatic"
+// CHECK_BDYNAMIC: "-Bdynamic"
// CHECK_STATIC: "-lgcc" "-lgcc_eh"
// CHECK_DYNAMIC: "-lgcc_s" "-lgcc"
diff --git a/test/Driver/mingw-msvcrt.c b/test/Driver/mingw-msvcrt.c
index b7c6584f95fe..89a8d2a94c28 100644
--- a/test/Driver/mingw-msvcrt.c
+++ b/test/Driver/mingw-msvcrt.c
@@ -1,5 +1,12 @@
// RUN: %clang -v -target i686-pc-windows-gnu -### %s 2>&1 | FileCheck -check-prefix=CHECK_DEFAULT %s
// RUN: %clang -v -target i686-pc-windows-gnu -lmsvcr120 -### %s 2>&1 | FileCheck -check-prefix=CHECK_MSVCR120 %s
+// RUN: %clang -v -target i686-pc-windows-gnu -lucrtbase -### %s 2>&1 | FileCheck -check-prefix=CHECK_UCRTBASE %s
+// RUN: %clang -v -target i686-pc-windows-gnu -lucrt -### %s 2>&1 | FileCheck -check-prefix=CHECK_UCRT %s
// CHECK_DEFAULT: "-lmingwex" "-lmsvcrt" "-ladvapi32"
-// CHECK_MSVCR120: "-lmingwex" "-ladvapi32"
+// CHECK_MSVCR120: "-lmsvcr120"
+// CHECK_MSVCR120-SAME: "-lmingwex" "-ladvapi32"
+// CHECK_UCRTBASE: "-lucrtbase"
+// CHECK_UCRTBASE-SAME: "-lmingwex" "-ladvapi32"
+// CHECK_UCRT: "-lucrt"
+// CHECK_UCRT-SAME: "-lmingwex" "-ladvapi32"
diff --git a/test/Driver/mingw-sysroot.cpp b/test/Driver/mingw-sysroot.cpp
new file mode 100644
index 000000000000..d477f314195f
--- /dev/null
+++ b/test/Driver/mingw-sysroot.cpp
@@ -0,0 +1,42 @@
+// REQUIRES: shell
+// UNSUPPORTED: system-windows
+
+// RUN: mkdir -p %T/testroot-gcc/bin
+// RUN: [ ! -s %T/testroot-gcc/bin/x86_64-w64-mingw32-gcc ] || rm %T/testroot-gcc/bin/x86_64-w64-mingw32-gcc
+// RUN: [ ! -s %T/testroot-gcc/bin/x86_64-w64-mingw32-clang ] || rm %T/testroot-gcc/bin/x86_64-w64-mingw32-clang
+// RUN: [ ! -s %T/testroot-gcc/x86_64-w64-mingw32 ] || rm %T/testroot-gcc/x86_64-w64-mingw32
+// RUN: [ ! -s %T/testroot-gcc/lib ] || rm %T/testroot-gcc/lib
+// RUN: ln -s %clang %T/testroot-gcc/bin/x86_64-w64-mingw32-gcc
+// RUN: ln -s %clang %T/testroot-gcc/bin/x86_64-w64-mingw32-clang
+// RUN: ln -s %S/Inputs/mingw_ubuntu_posix_tree/usr/x86_64-w64-mingw32 %T/testroot-gcc/x86_64-w64-mingw32
+// RUN: ln -s %S/Inputs/mingw_ubuntu_posix_tree/usr/lib %T/testroot-gcc/lib
+
+// RUN: mkdir -p %T/testroot-clang/bin
+// RUN: [ ! -s %T/testroot-clang/bin/x86_64-w64-mingw32-clang ] || rm %T/testroot-clang/bin/x86_64-w64-mingw32-clang
+// RUN: [ ! -s %T/testroot-clang/x86_64-w64-mingw32 ] || rm %T/testroot-clang/x86_64-w64-mingw32
+// RUN: ln -s %clang %T/testroot-clang/bin/x86_64-w64-mingw32-clang
+// RUN: ln -s %S/Inputs/mingw_ubuntu_posix_tree/usr/x86_64-w64-mingw32 %T/testroot-clang/x86_64-w64-mingw32
+
+
+// If we find a gcc in the path with the right triplet prefix, pick that as
+// sysroot:
+
+// RUN: env "PATH=%T/testroot-gcc/bin:%PATH%" %clang -target x86_64-w64-mingw32 -rtlib=platform -stdlib=libstdc++ -c -### %s 2>&1 | FileCheck -check-prefix=CHECK_TESTROOT_GCC %s
+// CHECK_TESTROOT_GCC: "{{.*}}/testroot-gcc{{/|\\\\}}lib{{/|\\\\}}gcc{{/|\\\\}}x86_64-w64-mingw32{{/|\\\\}}5.3-posix{{/|\\\\}}include{{/|\\\\}}c++"
+// CHECK_TESTROOT_GCC: "{{.*}}/testroot-gcc{{/|\\\\}}lib{{/|\\\\}}gcc{{/|\\\\}}x86_64-w64-mingw32{{/|\\\\}}5.3-posix{{/|\\\\}}include{{/|\\\\}}c++{{/|\\\\}}x86_64-w64-mingw32"
+// CHECK_TESTROOT_GCC: "{{.*}}/testroot-gcc{{/|\\\\}}lib{{/|\\\\}}gcc{{/|\\\\}}x86_64-w64-mingw32{{/|\\\\}}5.3-posix{{/|\\\\}}include{{/|\\\\}}c++{{/|\\\\}}backward"
+// CHECK_TESTROOT_GCC: "{{.*}}/testroot-gcc{{/|\\\\}}x86_64-w64-mingw32{{/|\\\\}}include"
+
+
+// If there's a matching sysroot next to the clang binary itself, prefer that
+// over a gcc in the path:
+
+// RUN: env "PATH=%T/testroot-gcc/bin:%PATH%" %T/testroot-clang/bin/x86_64-w64-mingw32-clang -target x86_64-w64-mingw32 -rtlib=compiler-rt -stdlib=libstdc++ -c -### %s 2>&1 | FileCheck -check-prefix=CHECK_TESTROOT_CLANG %s
+// CHECK_TESTROOT_CLANG: "{{.*}}/testroot-clang{{/|\\\\}}x86_64-w64-mingw32{{/|\\\\}}include"
+
+
+// If we pick a root based on a sysroot next to the clang binary, which also
+// happens to be in the same directory as gcc, make sure we still can pick up
+// the libgcc directory:
+
+// RUN: env "PATH=%T/testroot-gcc/bin:%PATH%" %T/testroot-gcc/bin/x86_64-w64-mingw32-clang -target x86_64-w64-mingw32 -rtlib=platform -stdlib=libstdc++ -c -### %s 2>&1 | FileCheck -check-prefix=CHECK_TESTROOT_GCC %s
diff --git a/test/Driver/mingw-windowsapp.c b/test/Driver/mingw-windowsapp.c
new file mode 100644
index 000000000000..bf6f2ec3fa3d
--- /dev/null
+++ b/test/Driver/mingw-windowsapp.c
@@ -0,0 +1,6 @@
+// RUN: %clang -v -target i686-pc-windows-gnu -### %s 2>&1 | FileCheck -check-prefix=CHECK_DEFAULT %s
+// RUN: %clang -v -target i686-pc-windows-gnu -### %s -lwindowsapp 2>&1 | FileCheck -check-prefix=CHECK_WINDOWSAPP %s
+
+// CHECK_DEFAULT: "-lmsvcrt" "-ladvapi32" "-lshell32" "-luser32" "-lkernel32" "-lmingw32"
+// CHECK_WINDOWSAPP: "-lwindowsapp" "-lmingw32"
+// CHECK_WINDOWSAPP-SAME: "-lmsvcrt" "-lmingw32"
diff --git a/test/Driver/mingw.cpp b/test/Driver/mingw.cpp
index 4e25c1dfa0fb..967574ffe161 100644
--- a/test/Driver/mingw.cpp
+++ b/test/Driver/mingw.cpp
@@ -3,6 +3,10 @@
// CHECK_MINGW_CLANG_TREE: "{{.*}}/Inputs/mingw_clang_tree/mingw32{{/|\\\\}}include"
+// RUN: %clang -target i686-windows-gnu -rtlib=platform -stdlib=libc++ -c -### --sysroot=%S/Inputs/mingw_clang_tree/mingw32 %s 2>&1 | FileCheck -check-prefix=CHECK_MINGW_CLANG_TREE_LIBCXX %s
+// CHECK_MINGW_CLANG_TREE_LIBCXX: "{{.*}}/Inputs/mingw_clang_tree/mingw32{{/|\\\\}}i686-w64-mingw32{{/|\\\\}}include{{/|\\\\}}c++{{/|\\\\}}v1"
+
+
// RUN: %clang -target i686-pc-windows-gnu -rtlib=platform -stdlib=libstdc++ -c -### --sysroot=%S/Inputs/mingw_mingw_org_tree/mingw %s 2>&1 | FileCheck -check-prefix=CHECK_MINGW_ORG_TREE %s
// CHECK_MINGW_ORG_TREE: "{{.*}}/Inputs/mingw_mingw_org_tree/mingw{{/|\\\\}}lib{{/|\\\\}}gcc{{/|\\\\}}mingw32{{/|\\\\}}4.8.1{{/|\\\\}}include{{/|\\\\}}c++"
// CHECK_MINGW_ORG_TREE: "{{.*}}/Inputs/mingw_mingw_org_tree/mingw{{/|\\\\}}lib{{/|\\\\}}gcc{{/|\\\\}}mingw32{{/|\\\\}}4.8.1{{/|\\\\}}include{{/|\\\\}}c++{{/|\\\\}}mingw32"
@@ -45,3 +49,10 @@
// CHECK_MINGW_UBUNTU_TREE: "{{.*}}/Inputs/mingw_ubuntu_tree/usr{{/|\\\\}}include{{/|\\\\}}c++{{/|\\\\}}4.8{{/|\\\\}}x86_64-w64-mingw32"
// CHECK_MINGW_UBUNTU_TREE: "{{.*}}/Inputs/mingw_ubuntu_tree/usr{{/|\\\\}}include{{/|\\\\}}c++{{/|\\\\}}4.8{{/|\\\\}}backward"
// CHECK_MINGW_UBUNTU_TREE: "{{.*}}/Inputs/mingw_ubuntu_tree/usr{{/|\\\\}}x86_64-w64-mingw32{{/|\\\\}}include"
+
+
+// RUN: %clang -target x86_64-pc-windows-gnu -rtlib=platform -stdlib=libstdc++ -c -### --sysroot=%S/Inputs/mingw_ubuntu_posix_tree/usr %s 2>&1 | FileCheck -check-prefix=CHECK_MINGW_UBUNTU_POSIX_TREE %s
+// CHECK_MINGW_UBUNTU_POSIX_TREE: "{{.*}}/Inputs/mingw_ubuntu_posix_tree/usr{{/|\\\\}}lib{{/|\\\\}}gcc{{/|\\\\}}x86_64-w64-mingw32{{/|\\\\}}5.3-posix{{/|\\\\}}include{{/|\\\\}}c++"
+// CHECK_MINGW_UBUNTU_POSIX_TREE: "{{.*}}/Inputs/mingw_ubuntu_posix_tree/usr{{/|\\\\}}lib{{/|\\\\}}gcc{{/|\\\\}}x86_64-w64-mingw32{{/|\\\\}}5.3-posix{{/|\\\\}}include{{/|\\\\}}c++{{/|\\\\}}x86_64-w64-mingw32"
+// CHECK_MINGW_UBUNTU_POSIX_TREE: "{{.*}}/Inputs/mingw_ubuntu_posix_tree/usr{{/|\\\\}}lib{{/|\\\\}}gcc{{/|\\\\}}x86_64-w64-mingw32{{/|\\\\}}5.3-posix{{/|\\\\}}include{{/|\\\\}}c++{{/|\\\\}}backward"
+// CHECK_MINGW_UBUNTU_POSIX_TREE: "{{.*}}/Inputs/mingw_ubuntu_posix_tree/usr{{/|\\\\}}x86_64-w64-mingw32{{/|\\\\}}include"
diff --git a/test/Driver/mips-abicalls-error.c b/test/Driver/mips-abicalls-error.c
new file mode 100644
index 000000000000..10f7201bdb07
--- /dev/null
+++ b/test/Driver/mips-abicalls-error.c
@@ -0,0 +1,2 @@
+// RUN: not %clang -c -target mips64-linux-gnu -fPIC -mno-abicalls %s 2>&1 | FileCheck %s
+// CHECK: error: position-independent code requires ‘-mabicalls’
diff --git a/test/Driver/mips-abicalls-warning.c b/test/Driver/mips-abicalls-warning.c
index 848a5bfce520..09f341eb9a33 100644
--- a/test/Driver/mips-abicalls-warning.c
+++ b/test/Driver/mips-abicalls-warning.c
@@ -1,6 +1,27 @@
// REQUIRES: mips-registered-target
-// RUN: %clang -### -c -target mips64-mti-elf -fno-PIC -mabicalls %s 2>&1 | FileCheck %s
-// CHECK: warning: ignoring '-mabicalls' option as it cannot be used with non position-independent code and the N64 ABI
+// RUN: %clang -### -c -target mips64-mti-elf -fno-pic %s 2>&1 | FileCheck -check-prefix=CHECK-PIC1-IMPLICIT %s
+// CHECK-PIC1-IMPLICIT: warning: ignoring '-fno-pic' option as it cannot be used with implicit usage of -mabicalls and the N64 ABI
+
+// RUN: %clang -### -c -target mips64-mti-elf -fno-pic -mabicalls %s 2>&1 | FileCheck -check-prefix=CHECK-PIC1-EXPLICIT %s
+// CHECK-PIC1-EXPLICIT: warning: ignoring '-fno-pic' option as it cannot be used with -mabicalls and the N64 ABI
+
+// RUN: %clang -### -c -target mips64-mti-elf -fno-PIC %s 2>&1 | FileCheck -check-prefix=CHECK-PIC2-IMPLICIT %s
+// CHECK-PIC2-IMPLICIT: warning: ignoring '-fno-PIC' option as it cannot be used with implicit usage of -mabicalls and the N64 ABI
+
+// RUN: %clang -### -c -target mips64-mti-elf -fno-PIC -mabicalls %s 2>&1 | FileCheck -check-prefix=CHECK-PIC2-EXPLICIT %s
+// CHECK-PIC2-EXPLICIT: warning: ignoring '-fno-PIC' option as it cannot be used with -mabicalls and the N64 ABI
+
+// RUN: %clang -### -c -target mips64-mti-elf -fno-pie %s 2>&1 | FileCheck -check-prefix=CHECK-PIE1-IMPLICIT %s
+// CHECK-PIE1-IMPLICIT: warning: ignoring '-fno-pie' option as it cannot be used with implicit usage of -mabicalls and the N64 ABI
+
+// RUN: %clang -### -c -target mips64-mti-elf -fno-pie -mabicalls %s 2>&1 | FileCheck -check-prefix=CHECK-PIE1-EXPLICIT %s
+// CHECK-PIE1-EXPLICIT: warning: ignoring '-fno-pie' option as it cannot be used with -mabicalls and the N64 ABI
+
+// RUN: %clang -### -c -target mips64-mti-elf -fno-PIE %s 2>&1 | FileCheck -check-prefix=CHECK-PIE2-IMPLICIT %s
+// CHECK-PIE2-IMPLICIT: warning: ignoring '-fno-PIE' option as it cannot be used with implicit usage of -mabicalls and the N64 ABI
+
+// RUN: %clang -### -c -target mips64-mti-elf -fno-PIE -mabicalls %s 2>&1 | FileCheck -check-prefix=CHECK-PIE2-EXPLICIT %s
+// CHECK-PIE2-EXPLICIT: warning: ignoring '-fno-PIE' option as it cannot be used with -mabicalls and the N64 ABI
// RUN: %clang -### -c -target mips-mti-elf -mlong-calls %s 2>&1 | FileCheck -check-prefix=LONGCALL-IMP %s
// LONGCALL-IMP: warning: ignoring '-mlong-calls' option as it is not currently supported with the implicit usage of -mabicalls
diff --git a/test/Driver/mips-as.c b/test/Driver/mips-as.c
index 560b5952db53..ced64d837071 100644
--- a/test/Driver/mips-as.c
+++ b/test/Driver/mips-as.c
@@ -21,7 +21,7 @@
// MIPS32R2-DEF-EL-AS: as{{(.exe)?}}" "-march" "mips32r2" "-mabi" "32" "-mno-shared" "-call_nonpic" "-EL"
//
// RUN: %clang -target mips64-linux-gnu -### \
-// RUN: -no-integrated-as -fno-pic -c %s 2>&1 \
+// RUN: -no-integrated-as -fno-pic -mno-abicalls -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=MIPS64R2-EB-AS %s
// MIPS64R2-EB-AS: as{{(.exe)?}}" "-march" "mips64r2" "-mabi" "64" "-mno-shared" "-EB"
//
@@ -31,7 +31,7 @@
// MIPS64R2-EB-AS-PIC: as{{(.exe)?}}" "-march" "mips64r2" "-mabi" "64" "-EB" "-KPIC"
//
// RUN: %clang -target mips64el-linux-gnu -### \
-// RUN: -no-integrated-as -c -fno-pic %s 2>&1 \
+// RUN: -no-integrated-as -c -fno-pic -mno-abicalls %s 2>&1 \
// RUN: | FileCheck -check-prefix=MIPS64R2-DEF-EL-AS %s
// MIPS64R2-DEF-EL-AS: as{{(.exe)?}}" "-march" "mips64r2" "-mabi" "64" "-mno-shared" "-EL"
//
@@ -64,7 +64,7 @@
// MIPS64R2-EL-AS-PIC: as{{(.exe)?}}" "-march" "mips64r2" "-mabi" "64" "-EL" "-KPIC"
//
// RUN: %clang -target mips64el-linux-gnu -mabi=64 -### \
-// RUN: -no-integrated-as -c %s -fno-pic 2>&1 \
+// RUN: -no-integrated-as -c %s -fno-pic -mno-abicalls 2>&1 \
// RUN: | FileCheck -check-prefix=MIPS64R2-EL-AS %s
// MIPS64R2-EL-AS: as{{(.exe)?}}" "-march" "mips64r2" "-mabi" "64" "-mno-shared" "-EL"
//
@@ -84,7 +84,7 @@
// MIPS-OCTEON-PIC: as{{(.exe)?}}" "-march" "octeon" "-mabi" "64" "-EB" "-KPIC"
//
// RUN: %clang -target mips64-linux-gnu -march=octeon -### \
-// RUN: -no-integrated-as -c %s -fno-pic 2>&1 \
+// RUN: -no-integrated-as -c %s -fno-pic -mno-abicalls 2>&1 \
// RUN: | FileCheck -check-prefix=MIPS-OCTEON %s
// MIPS-OCTEON: as{{(.exe)?}}" "-march" "octeon" "-mabi" "64" "-mno-shared" "-EB"
//
@@ -144,7 +144,7 @@
// MIPS-ALIAS-64-PIC: as{{(.exe)?}}" "-march" "mips64" "-mabi" "64" "-EB" "-KPIC"
//
// RUN: %clang -target mips64-linux-gnu -mips64 -### \
-// RUN: -no-integrated-as -c -fno-pic %s 2>&1 \
+// RUN: -no-integrated-as -c -fno-pic -mno-abicalls %s 2>&1 \
// RUN: | FileCheck -check-prefix=MIPS-ALIAS-64 %s
// MIPS-ALIAS-64: as{{(.exe)?}}" "-march" "mips64" "-mabi" "64" "-mno-shared" "-EB"
//
@@ -159,7 +159,7 @@
// MIPS-ALIAS-64R3-PIC: as{{(.exe)?}}" "-march" "mips64r3" "-mabi" "64" "-EB" "-KPIC"
//
// RUN: %clang -target mips64-linux-gnu -mips64r3 -### \
-// RUN: -no-integrated-as -c %s -fno-pic 2>&1 \
+// RUN: -no-integrated-as -c %s -fno-pic -mno-abicalls 2>&1 \
// RUN: | FileCheck -check-prefix=MIPS-ALIAS-64R3 %s
// MIPS-ALIAS-64R3: as{{(.exe)?}}" "-march" "mips64r3" "-mabi" "64" "-mno-shared" "-EB"
//
@@ -169,7 +169,7 @@
// MIPS-ALIAS-64R5-PIC: as{{(.exe)?}}" "-march" "mips64r5" "-mabi" "64" "-EB" "-KPIC"
//
// RUN: %clang -target mips64-linux-gnu -mips64r5 -### \
-// RUN: -no-integrated-as -c %s -fno-pic 2>&1 \
+// RUN: -no-integrated-as -c %s -fno-pic -mno-abicalls 2>&1 \
// RUN: | FileCheck -check-prefix=MIPS-ALIAS-64R5 %s
// MIPS-ALIAS-64R5: as{{(.exe)?}}" "-march" "mips64r5" "-mabi" "64" "-mno-shared" "-EB"
//
@@ -179,7 +179,7 @@
// MIPS-ALIAS-64R6-PIC: as{{(.exe)?}}" "-march" "mips64r6" "-mabi" "64" "-EB" "-KPIC"
//
// RUN: %clang -target mips64-linux-gnu -mips64r6 -### \
-// RUN: -no-integrated-as -c %s -fno-pic 2>&1 \
+// RUN: -no-integrated-as -c %s -fno-pic -mno-abicalls 2>&1 \
// RUN: | FileCheck -check-prefix=MIPS-ALIAS-64R6 %s
// MIPS-ALIAS-64R6: as{{(.exe)?}}" "-march" "mips64r6" "-mabi" "64" "-mno-shared" "-EB"
//
diff --git a/test/Driver/mips-features.c b/test/Driver/mips-features.c
index a9db0f101700..f63fb8de55d6 100644
--- a/test/Driver/mips-features.c
+++ b/test/Driver/mips-features.c
@@ -11,7 +11,7 @@
// CHECK-MNOABICALLS: "-target-feature" "+noabicalls"
//
// -mno-abicalls non-PIC N64
-// RUN: %clang -target mips64-linux-gnu -### -c -fno-PIC %s 2>&1 \
+// RUN: %clang -target mips64-linux-gnu -### -c -fno-PIC -mno-abicalls %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MNOABICALLS-N64NPIC %s
// CHECK-MNOABICALLS-N64NPIC: "-target-feature" "+noabicalls"
//
@@ -86,13 +86,13 @@
// CHECK-MEMBEDDEDDATADEF-NOT: "-mllvm" "-membedded-data"
//
// MIPS64 + N64: -fno-pic -> -mno-abicalls -mgpopt
-// RUN: %clang -target mips64-mti-elf -mabi=64 -### -c %s -fno-pic 2>&1 \
+// RUN: %clang -target mips64-mti-elf -mabi=64 -### -c %s -fno-pic -mno-abicalls 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-N64-GPOPT %s
// CHECK-N64-GPOPT: "-target-feature" "+noabicalls"
// CHECK-N64-GPOPT: "-mllvm" "-mgpopt"
//
// MIPS64 + N64: -fno-pic -mno-gpopt
-// RUN: %clang -target mips64-mti-elf -mabi=64 -### -c %s -fno-pic -mno-gpopt 2>&1 \
+// RUN: %clang -target mips64-mti-elf -mabi=64 -### -c %s -fno-pic -mno-abicalls -mno-gpopt 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-N64-MNO-GPOPT %s
// CHECK-N64-MNO-GPOPT: "-target-feature" "+noabicalls"
// CHECK-N64-MNO-GPOPT-NOT: "-mllvm" "-mgpopt"
@@ -402,3 +402,45 @@
// RUN: %clang -target -mips-mti-linux-gnu -### -c %s -mno-branch-likely 2>&1 \
// RUN: | FileCheck --check-prefix=NO-BRANCH-LIKELY %s
// NO-BRANCH-LIKELY: argument unused during compilation: '-mno-branch-likely'
+
+// -mindirect-jump=hazard
+// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \
+// RUN: -mindirect-jump=hazard 2>&1 \
+// RUN: | FileCheck --check-prefix=INDIRECT-BH %s
+// INDIRECT-BH: "-target-feature" "+use-indirect-jump-hazard"
+//
+// -mcrc
+// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \
+// RUN: -mno-crc -mcrc 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-CRC %s
+// CHECK-CRC: "-target-feature" "+crc"
+//
+// -mno-crc
+// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \
+// RUN: -mcrc -mno-crc 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-NO-CRC %s
+// CHECK-NO-CRC: "-target-feature" "-crc"
+//
+// -mvirt
+// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \
+// RUN: -mno-virt -mvirt 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-VIRT %s
+// CHECK-VIRT: "-target-feature" "+virt"
+//
+// -mno-virt
+// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \
+// RUN: -mvirt -mno-virt 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-NO-VIRT %s
+// CHECK-NO-VIRT: "-target-feature" "-virt"
+//
+// -mginv
+// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \
+// RUN: -mno-ginv -mginv 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-GINV %s
+// CHECK-GINV: "-target-feature" "+ginv"
+//
+// -mno-ginv
+// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \
+// RUN: -mginv -mno-ginv 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-NO-GINV %s
+// CHECK-NO-GINV: "-target-feature" "-ginv"
diff --git a/test/Driver/mips-indirect-branch.c b/test/Driver/mips-indirect-branch.c
new file mode 100644
index 000000000000..64e85d5dc5a1
--- /dev/null
+++ b/test/Driver/mips-indirect-branch.c
@@ -0,0 +1,23 @@
+// REQUIRES: mips-registered-target
+// -mindirect-jump=hazard -mips32
+// RUN: %clang -target mips-unknown-linux-gnu -mips32 -### -c %s \
+// RUN: -mindirect-jump=hazard 2>&1 | FileCheck %s --check-prefix=MIPS32
+// MIPS32: error: '-mindirect-jump=hazard' is unsupported with the 'mips32' architecture
+
+// -mindirect-jump=hazard -mmicromips
+// RUN: %clang -target mips-unknown-linux-gnu -mmicromips -### -c %s \
+// RUN: -mindirect-jump=hazard 2>&1 | FileCheck %s --check-prefix=MICROMIPS
+// MICROMIPS: error: '-mindirect-jump=hazard' is unsupported with the 'micromips' architecture
+
+// -mindirect-jump=hazard -mips16
+// RUN: %clang -target mips-unknown-linux-gnu -mips16 -### -c %s \
+// RUN: -mindirect-jump=hazard 2>&1 | FileCheck %s --check-prefix=MIPS16
+// MIPS16: error: '-mindirect-jump=hazard' is unsupported with the 'mips16' architecture
+
+// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \
+// RUN: -mindirect-jump=retopline 2>&1 | FileCheck %s --check-prefix=RETOPLINE
+// RETOPLINE: error: unknown '-mindirect-jump=' option 'retopline'
+
+// RUN: %clang -target mips-unknown-linux-gnu -### -mips32 -c %s \
+// RUN: -mindirect-jump=retopline 2>&1 | FileCheck %s --check-prefix=MIXED
+// MIXED: error: unknown '-mindirect-jump=' option 'retopline'
diff --git a/test/Driver/modules.m b/test/Driver/modules.m
index e08de94d0e86..73db4e7e0fcc 100644
--- a/test/Driver/modules.m
+++ b/test/Driver/modules.m
@@ -30,9 +30,15 @@
// RUN: %clang -### %s 2>&1 | FileCheck -check-prefix=MODULES_VALIDATE_SYSTEM_HEADERS_DEFAULT %s
// MODULES_VALIDATE_SYSTEM_HEADERS_DEFAULT-NOT: -fmodules-validate-system-headers
+// RUN: %clang -fmodules -fsyntax-only -### %s 2>&1 | FileCheck -check-prefix=MODULES_VALIDATE_SYSTEM_HEADERS_DEFAULT_MOD %s
+// MODULES_VALIDATE_SYSTEM_HEADERS_DEFAULT_MOD: -fmodules-validate-system-headers
+
// RUN: %clang -fmodules-validate-system-headers -### %s 2>&1 | FileCheck -check-prefix=MODULES_VALIDATE_SYSTEM_HEADERS %s
// MODULES_VALIDATE_SYSTEM_HEADERS: -fmodules-validate-system-headers
+// RUN: %clang -fno-modules-validate-system-headers -### %s 2>&1 | FileCheck -check-prefix=MODULES_VALIDATE_SYSTEM_HEADERS_NOSYSVALID %s
+// MODULES_VALIDATE_SYSTEM_HEADERS_NOSYSVALID-NOT: -fmodules-validate-system-headers
+
// RUN: %clang -### %s 2>&1 | FileCheck -check-prefix=MODULES_DISABLE_DIAGNOSTIC_VALIDATION_DEFAULT %s
// MODULES_DISABLE_DIAGNOSTIC_VALIDATION_DEFAULT-NOT: -fmodules-disable-diagnostic-validation
diff --git a/test/Driver/myriad-toolchain.c b/test/Driver/myriad-toolchain.c
index 26b02387093a..215a02fd0dec 100644
--- a/test/Driver/myriad-toolchain.c
+++ b/test/Driver/myriad-toolchain.c
@@ -41,7 +41,7 @@
// RUN: | FileCheck %s -check-prefix=MOVICOMPILE
// MOVICOMPILE: moviCompile{{(.exe)?}}" "-S" "-fno-exceptions" "-DMYRIAD2" "-mcpu=myriad2.2" "-isystem" "somewhere" "-I" "common"
// MOVICOMPILE: moviAsm{{(.exe)?}}" "-no6thSlotCompression" "-cv:myriad2.2" "-noSPrefixing" "-a"
-// MOVICOMPILE: "-yippee" "-i:somewhere" "-i:common" "-elf"
+// MOVICOMPILE: "-yippee" "-i:somewhere" "-i:common"
// RUN: %clang -target shave-myriad -c -### %s -DEFINE_ME -UNDEFINE_ME 2>&1 \
// RUN: | FileCheck %s -check-prefix=DEFINES
diff --git a/test/Driver/netbsd.c b/test/Driver/netbsd.c
index 06b5eadfca85..34ad6e41579f 100644
--- a/test/Driver/netbsd.c
+++ b/test/Driver/netbsd.c
@@ -5,6 +5,9 @@
// RUN: -pie --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=PIE %s
// RUN: %clang -no-canonical-prefixes -target x86_64--netbsd \
+// RUN: -static -pie --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
+// RUN: | FileCheck -check-prefix=STATIC-PIE %s
+// RUN: %clang -no-canonical-prefixes -target x86_64--netbsd \
// RUN: -shared --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=SHARED %s
@@ -139,6 +142,16 @@
// STATIC: "{{.*}}/usr/lib{{/|\\\\}}crti.o" "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o"
// STATIC: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
+// STATIC-PIE: ld{{.*}}" "--eh-frame-hdr"
+// STATIC-PIE-NOT: "-dynamic-linker" "/libexec/ld.elf_so"
+// STATIC-PIE-NOT: "-Bshareable"
+// STATIC-PIE: "-pie"
+// STATIC-PIE-NOT: "-dynamic-linker" "/libexec/ld.elf_so"
+// STATIC-PIE-NOT: "-Bshareable"
+// STATIC-PIE: "{{.*}}/usr/lib{{/|\\\\}}crt0.o"
+// STATIC-PIE: "{{.*}}/usr/lib{{/|\\\\}}crti.o" "{{.*}}/usr/lib{{/|\\\\}}crtbeginS.o"
+// STATIC-PIE: "{{.*}}/usr/lib{{/|\\\\}}crtendS.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
+
// SHARED: ld{{.*}}" "--eh-frame-hdr"
// SHARED-NOT: "-pie"
// SHARED-NOT: "-dynamic-linker"
diff --git a/test/Driver/no-canonical-prefixes.c b/test/Driver/no-canonical-prefixes.c
index 7bc76be22d75..8b9e04410ed2 100644
--- a/test/Driver/no-canonical-prefixes.c
+++ b/test/Driver/no-canonical-prefixes.c
@@ -1,9 +1,14 @@
// Due to ln -sf:
// REQUIRES: shell
+// RUN: rm -rf %t.real
// RUN: mkdir -p %t.real
// RUN: cd %t.real
// RUN: ln -sf %clang test-clang
// RUN: cd ..
+// Important to remove %t.fake: If it already is a symlink to %t.real when
+// `ln -sf %t.real %t.fake` runs, then that would symlink %t.real to itself,
+// forming a cycle.
+// RUN: rm -rf %t.fake
// RUN: ln -sf %t.real %t.fake
// RUN: cd %t.fake
// RUN: ./test-clang -v -S %s 2>&1 | FileCheck --check-prefix=CANONICAL %s
diff --git a/test/Driver/openbsd.c b/test/Driver/openbsd.c
index 2bcd70377033..d3846b7acf66 100644
--- a/test/Driver/openbsd.c
+++ b/test/Driver/openbsd.c
@@ -74,6 +74,13 @@
// CHECK-MIPS64EL: as{{.*}}" "-mabi" "64" "-EL"
// CHECK-MIPS64EL-PIC: as{{.*}}" "-mabi" "64" "-EL" "-KPIC"
+// Check that the integrated assembler is enabled for MIPS64
+// RUN: %clang -target mips64-unknown-openbsd -### -c %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-MIPS64-AS %s
+// RUN: %clang -target mips64el-unknown-openbsd -### -c %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-MIPS64-AS %s
+// CHECK-MIPS64-AS-NOT: "-no-integrated-as"
+
// Check linking against correct startup code when (not) using PIE
// RUN: %clang -no-canonical-prefixes -target i686-pc-openbsd %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-PIE %s
@@ -103,4 +110,5 @@
// Check ARM float ABI
// RUN: %clang -target arm-unknown-openbsd -### -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-ARM-FLOAT-ABI %s
-// CHECK-ARM-FLOAT-ABI: "-mfloat-abi" "soft"
+// CHECK-ARM-FLOAT-ABI-NOT: "-target-feature" "+soft-float"
+// CHECK-ARM-FLOAT-ABI: "-target-feature" "+soft-float-abi"
diff --git a/test/Driver/opencl.cl b/test/Driver/opencl.cl
index d68d424b6e36..baff86fb9067 100644
--- a/test/Driver/opencl.cl
+++ b/test/Driver/opencl.cl
@@ -2,6 +2,7 @@
// RUN: %clang -S -### -cl-std=CL1.1 %s 2>&1 | FileCheck --check-prefix=CHECK-CL11 %s
// RUN: %clang -S -### -cl-std=CL1.2 %s 2>&1 | FileCheck --check-prefix=CHECK-CL12 %s
// RUN: %clang -S -### -cl-std=CL2.0 %s 2>&1 | FileCheck --check-prefix=CHECK-CL20 %s
+// RUN: %clang -S -### -cl-std=c++ %s 2>&1 | FileCheck --check-prefix=CHECK-CLCPP %s
// RUN: %clang -S -### -cl-opt-disable %s 2>&1 | FileCheck --check-prefix=CHECK-OPT-DISABLE %s
// RUN: %clang -S -### -cl-strict-aliasing %s 2>&1 | FileCheck --check-prefix=CHECK-STRICT-ALIASING %s
// RUN: %clang -S -### -cl-single-precision-constant %s 2>&1 | FileCheck --check-prefix=CHECK-SINGLE-PRECISION-CONST %s
@@ -13,6 +14,7 @@
// RUN: %clang -S -### -cl-no-signed-zeros %s 2>&1 | FileCheck --check-prefix=CHECK-NO-SIGNED-ZEROS %s
// RUN: %clang -S -### -cl-denorms-are-zero %s 2>&1 | FileCheck --check-prefix=CHECK-DENORMS-ARE-ZERO %s
// RUN: %clang -S -### -cl-fp32-correctly-rounded-divide-sqrt %s 2>&1 | FileCheck --check-prefix=CHECK-ROUND-DIV %s
+// RUN: %clang -S -### -cl-uniform-work-group-size %s 2>&1 | FileCheck --check-prefix=CHECK-UNIFORM-WG %s
// RUN: not %clang -cl-std=c99 -DOPENCL %s 2>&1 | FileCheck --check-prefix=CHECK-C99 %s
// RUN: not %clang -cl-std=invalid -DOPENCL %s 2>&1 | FileCheck --check-prefix=CHECK-INVALID %s
@@ -20,6 +22,7 @@
// CHECK-CL11: "-cc1" {{.*}} "-cl-std=CL1.1"
// CHECK-CL12: "-cc1" {{.*}} "-cl-std=CL1.2"
// CHECK-CL20: "-cc1" {{.*}} "-cl-std=CL2.0"
+// CHECK-CLCPP: "-cc1" {{.*}} "-cl-std=c++"
// CHECK-OPT-DISABLE: "-cc1" {{.*}} "-cl-opt-disable"
// CHECK-STRICT-ALIASING: "-cc1" {{.*}} "-cl-strict-aliasing"
// CHECK-SINGLE-PRECISION-CONST: "-cc1" {{.*}} "-cl-single-precision-constant"
@@ -31,6 +34,7 @@
// CHECK-NO-SIGNED-ZEROS: "-cc1" {{.*}} "-cl-no-signed-zeros"
// CHECK-DENORMS-ARE-ZERO: "-cc1" {{.*}} "-cl-denorms-are-zero"
// CHECK-ROUND-DIV: "-cc1" {{.*}} "-cl-fp32-correctly-rounded-divide-sqrt"
+// CHECK-UNIFORM-WG: "-cc1" {{.*}} "-cl-uniform-work-group-size"
// CHECK-C99: error: invalid value 'c99' in '-cl-std=c99'
// CHECK-INVALID: error: invalid value 'invalid' in '-cl-std=invalid'
diff --git a/test/Driver/openmp-offload-gpu.c b/test/Driver/openmp-offload-gpu.c
index 16c321b9f499..3d14041a13f8 100644
--- a/test/Driver/openmp-offload-gpu.c
+++ b/test/Driver/openmp-offload-gpu.c
@@ -142,3 +142,74 @@
// RUN: | FileCheck -check-prefix=CHK-NOLIBDEVICE %s
// CHK-NOLIBDEVICE-NOT: error:{{.*}}sm_60
+
+/// ###########################################################################
+
+/// Check that the runtime bitcode library is part of the compile line. Create a bogus
+/// bitcode library and add it to the LIBRARY_PATH.
+// RUN: env LIBRARY_PATH=%S/Inputs/libomptarget %clang -### -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda \
+// RUN: -Xopenmp-target -march=sm_20 --cuda-path=%S/Inputs/CUDA_80/usr/local/cuda \
+// RUN: -fopenmp-relocatable-target -save-temps -no-canonical-prefixes %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHK-BCLIB %s
+
+// CHK-BCLIB: clang{{.*}}-triple{{.*}}nvptx64-nvidia-cuda{{.*}}-mlink-cuda-bitcode{{.*}}libomptarget-nvptx-sm_20.bc
+// CHK-BCLIB-NOT: {{error:|warning:}}
+
+/// ###########################################################################
+
+/// Check that the warning is thrown when the libomptarget bitcode library is not found.
+/// Libomptarget requires sm_35 or newer so an sm_20 bitcode library should never exist.
+// RUN: %clang -### -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda \
+// RUN: -Xopenmp-target -march=sm_20 --cuda-path=%S/Inputs/CUDA_80/usr/local/cuda \
+// RUN: -fopenmp-relocatable-target -save-temps -no-canonical-prefixes %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHK-BCLIB-WARN %s
+
+// CHK-BCLIB-WARN: No library 'libomptarget-nvptx-sm_20.bc' found in the default clang lib directory or in LIBRARY_PATH. Expect degraded performance due to no inlining of runtime functions on target devices.
+
+/// Check that debug info is emitted in dwarf-2
+// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -g -O0 --no-cuda-noopt-device-debug 2>&1 \
+// RUN: | FileCheck -check-prefix=NO_DEBUG %s
+// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -g -O3 2>&1 \
+// RUN: | FileCheck -check-prefix=NO_DEBUG %s
+// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -g -O3 --no-cuda-noopt-device-debug 2>&1 \
+// RUN: | FileCheck -check-prefix=NO_DEBUG %s
+// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -g0 2>&1 \
+// RUN: | FileCheck -check-prefix=NO_DEBUG %s
+// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -ggdb0 -O3 --cuda-noopt-device-debug 2>&1 \
+// RUN: | FileCheck -check-prefix=NO_DEBUG %s
+// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -gline-tables-only 2>&1 \
+// RUN: | FileCheck -check-prefix=NO_DEBUG -check-prefix=LINE_TABLE %s
+// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -ggdb1 -O2 --cuda-noopt-device-debug 2>&1 \
+// RUN: | FileCheck -check-prefix=NO_DEBUG -check-prefix=LINE_TABLE %s
+
+// NO_DEBUG: ptxas
+// LINE_TABLE: "-lineinfo"
+// NO_DEBUG-NOT: "-g"
+// NO_DEBUG: nvlink
+// NO_DEBUG-NOT: "-g"
+
+// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -g 2>&1 \
+// RUN: | FileCheck -check-prefix=HAS_DEBUG %s
+// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -g -O0 --cuda-noopt-device-debug 2>&1 \
+// RUN: | FileCheck -check-prefix=HAS_DEBUG %s
+// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -g -O3 --cuda-noopt-device-debug 2>&1 \
+// RUN: | FileCheck -check-prefix=HAS_DEBUG %s
+// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -g2 2>&1 \
+// RUN: | FileCheck -check-prefix=HAS_DEBUG %s
+// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -ggdb2 -O0 --cuda-noopt-device-debug 2>&1 \
+// RUN: | FileCheck -check-prefix=HAS_DEBUG %s
+// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -g3 -O3 --cuda-noopt-device-debug 2>&1 \
+// RUN: | FileCheck -check-prefix=HAS_DEBUG %s
+// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -ggdb3 -O2 --cuda-noopt-device-debug 2>&1 \
+// RUN: | FileCheck -check-prefix=HAS_DEBUG %s
+
+// HAS_DEBUG: "-triple" "nvptx64-nvidia-cuda"
+// HAS_DEBUG-SAME: "-dwarf-version=2"
+// HAS_DEBUG-SAME: "-fopenmp-is-device"
+// HAS_DEBUG: ptxas
+// HAS_DEBUG-SAME: "-g"
+// HAS_DEBUG-SAME: "--dont-merge-basicblocks"
+// HAS_DEBUG-SAME: "--return-at-end"
+// HAS_DEBUG: nvlink
+// HAS_DEBUG-SAME: "-g"
+
diff --git a/test/Driver/pic.c b/test/Driver/pic.c
index 1b4257c28bb5..68a307914f61 100644
--- a/test/Driver/pic.c
+++ b/test/Driver/pic.c
@@ -292,9 +292,9 @@
// RUN: %clang -c %s -target mipsel-linux-android14 -### 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-PIC1
// RUN: %clang -c %s -target mipsel-linux-android16 -### 2>&1 \
-// RUN: | FileCheck %s --check-prefix=CHECK-PIE2
+// RUN: | FileCheck %s --check-prefix=CHECK-PIE1
// RUN: %clang -c %s -target mipsel-linux-android24 -### 2>&1 \
-// RUN: | FileCheck %s --check-prefix=CHECK-PIE2
+// RUN: | FileCheck %s --check-prefix=CHECK-PIE1
//
// 64-bit Android targets are always PIE.
// RUN: %clang -c %s -target aarch64-linux-android -### 2>&1 \
diff --git a/test/Driver/ppc-f128-support-check.c b/test/Driver/ppc-f128-support-check.c
new file mode 100644
index 000000000000..24748905612f
--- /dev/null
+++ b/test/Driver/ppc-f128-support-check.c
@@ -0,0 +1,20 @@
+// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \
+// RUN: -mcpu=pwr9 -mfloat128 %s 2>&1 | FileCheck %s --check-prefix=HASF128
+// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \
+// RUN: -mcpu=power9 -mfloat128 %s 2>&1 | FileCheck %s --check-prefix=HASF128
+
+// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \
+// RUN: -mcpu=pwr8 -mfloat128 %s 2>&1 | FileCheck %s --check-prefix=NOF128
+// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \
+// RUN: -mcpu=pwr7 -mfloat128 %s 2>&1 | FileCheck %s --check-prefix=NOF128
+// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \
+// RUN: -mfloat128 %s 2>&1 | FileCheck %s --check-prefix=NOF128
+
+#ifdef __FLOAT128__
+static_assert(false, "__float128 enabled");
+#endif
+
+// HASF128: __float128 enabled
+// HASF128-NOT: option '-mfloat128' cannot be specified with
+// NOF128: option '-mfloat128' cannot be specified with
+
diff --git a/test/Driver/ppc-features.cpp b/test/Driver/ppc-features.cpp
index 621c407d37ef..1cb6cee061c1 100644
--- a/test/Driver/ppc-features.cpp
+++ b/test/Driver/ppc-features.cpp
@@ -22,6 +22,10 @@
// RUN: %clang -target powerpc-unknown-linux-gnu %s -msoft-float -mhard-float -### -o %t.o 2>&1 | FileCheck --check-prefix=CHECK-SOFTHARD %s
// CHECK-SOFTHARD-NOT: "-target-feature" "-hard-float"
+// check -msecure-plt option for ppc32
+// RUN: %clang -target powerpc-unknown-linux-gnu -msecure-plt %s -### -o %t.o 2>&1 | FileCheck --check-prefix=CHECK-SECUREPLT %s
+// CHECK-SECUREPLT: "-target-feature" "+secure-plt"
+
// check -mfloat-abi=x option
// RUN: %clang -target powerpc-unknown-linux-gnu %s -mfloat-abi=x -### -o %t.o 2>&1 | FileCheck --check-prefix=CHECK-ERRMSG %s
// CHECK-ERRMSG: error: invalid float ABI '-mfloat-abi=x'
diff --git a/test/Driver/print-empty-prog-name.c b/test/Driver/print-empty-prog-name.c
new file mode 100644
index 000000000000..e01715f3b0b8
--- /dev/null
+++ b/test/Driver/print-empty-prog-name.c
@@ -0,0 +1,5 @@
+// Test that -print-prog-name= correctly returns an empty string
+
+// RUN: %clang -print-prog-name= 2>&1 | FileCheck %s
+// CHECK-NOT:{{.+}}
+
diff --git a/test/Driver/rewrite-legacy-objc.m b/test/Driver/rewrite-legacy-objc.m
index 8ac357c84472..37b829e5e5a2 100644
--- a/test/Driver/rewrite-legacy-objc.m
+++ b/test/Driver/rewrite-legacy-objc.m
@@ -3,11 +3,11 @@
// TEST0: clang{{.*}}" "-cc1"
// TEST0: "-rewrite-objc"
// FIXME: CHECK-NOT is broken somehow, it doesn't work here. Check adjacency instead.
-// TEST0: "-fmessage-length" "0" "-stack-protector" "1" "-fblocks" "-fencode-extended-block-signature" "-fobjc-runtime=macosx-fragile" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fexceptions" "-fmax-type-align=16" "-fdiagnostics-show-option"
+// TEST0: "-fmessage-length" "0" "-stack-protector" "1" "-fblocks" "-fencode-extended-block-signature" "-fregister-global-dtors-with-atexit" "-fobjc-runtime=macosx-fragile" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fexceptions" "-fmax-type-align=16" "-fdiagnostics-show-option"
// TEST0: rewrite-legacy-objc.m"
// RUN: %clang -no-canonical-prefixes -target i386-apple-macosx10.9.0 -rewrite-legacy-objc %s -o - -### 2>&1 | \
// RUN: FileCheck -check-prefix=TEST1 %s
// RUN: %clang -no-canonical-prefixes -target i386-apple-macosx10.6.0 -rewrite-legacy-objc %s -o - -### 2>&1 | \
// RUN: FileCheck -check-prefix=TEST2 %s
-// TEST1: "-fmessage-length" "0" "-stack-protector" "1" "-fblocks" "-fencode-extended-block-signature" "-fobjc-runtime=macosx-fragile" "-fobjc-subscripting-legacy-runtime" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fmax-type-align=16" "-fdiagnostics-show-option"
-// TEST2: "-fmessage-length" "0" "-stack-protector" "1" "-fblocks" "-fencode-extended-block-signature" "-fobjc-runtime=macosx-fragile" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fmax-type-align=16" "-fdiagnostics-show-option"
+// TEST1: "-fmessage-length" "0" "-stack-protector" "1" "-fblocks" "-fencode-extended-block-signature" "-fregister-global-dtors-with-atexit" "-fobjc-runtime=macosx-fragile" "-fobjc-subscripting-legacy-runtime" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fmax-type-align=16" "-fdiagnostics-show-option"
+// TEST2: "-fmessage-length" "0" "-stack-protector" "1" "-fblocks" "-fencode-extended-block-signature" "-fregister-global-dtors-with-atexit" "-fobjc-runtime=macosx-fragile" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fmax-type-align=16" "-fdiagnostics-show-option"
diff --git a/test/Driver/rewrite-objc.m b/test/Driver/rewrite-objc.m
index b8a1ffe8b806..1c6dbcc329e2 100644
--- a/test/Driver/rewrite-objc.m
+++ b/test/Driver/rewrite-objc.m
@@ -3,4 +3,4 @@
// TEST0: clang{{.*}}" "-cc1"
// TEST0: "-rewrite-objc"
// FIXME: CHECK-NOT is broken somehow, it doesn't work here. Check adjacency instead.
-// TEST0: "-fmessage-length" "0" "-stack-protector" "1" "-fblocks" "-fencode-extended-block-signature" "-fobjc-runtime=macosx" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fexceptions" "-fmax-type-align=16" "-fdiagnostics-show-option"
+// TEST0: "-fmessage-length" "0" "-stack-protector" "1" "-fblocks" "-fencode-extended-block-signature" "-fregister-global-dtors-with-atexit" "-fobjc-runtime=macosx" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fexceptions" "-fmax-type-align=16" "-fdiagnostics-show-option"
diff --git a/test/Driver/riscv-abi.c b/test/Driver/riscv-abi.c
new file mode 100644
index 000000000000..8b79c8462bae
--- /dev/null
+++ b/test/Driver/riscv-abi.c
@@ -0,0 +1,47 @@
+// RUN: %clang -target riscv32-unknown-elf %s -### -o %t.o 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-ILP32 %s
+// RUN: %clang -target riscv32-unknown-elf %s -### -o %t.o -mabi=ilp32 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-ILP32 %s
+
+// CHECK-ILP32: "-target-abi" "ilp32"
+
+// TODO: ilp32f support.
+// RUN: not %clang -target riscv32-unknown-elf %s -o %t.o -mabi=ilp32f 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-ILP32F %s
+
+// CHECK-ILP32F: error: unknown target ABI 'ilp32f'
+
+// TODO: ilp32d support.
+// RUN: not %clang -target riscv32-unknown-elf %s -o %t.o -mabi=ilp32d 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-ILP32D %s
+
+// CHECK-ILP32D: error: unknown target ABI 'ilp32d'
+
+// RUN: not %clang -target riscv32-unknown-elf %s -o %t.o -mabi=lp64 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-RV32-LP64 %s
+
+// CHECK-RV32-LP64: error: unknown target ABI 'lp64'
+
+// RUN: %clang -target riscv64-unknown-elf %s -### -o %t.o 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-LP64 %s
+// RUN: %clang -target riscv64-unknown-elf %s -### -o %t.o -mabi=lp64 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-LP64 %s
+
+// CHECK-LP64: "-target-abi" "lp64"
+
+// TODO: lp64f support.
+// RUN: not %clang -target riscv64-unknown-elf %s -o %t.o -mabi=lp64f 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-LP64F %s
+
+// CHECK-LP64F: error: unknown target ABI 'lp64f'
+
+// TODO: lp64d support.
+// RUN: not %clang -target riscv64-unknown-elf %s -o %t.o -mabi=lp64d 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-LP64D %s
+
+// CHECK-LP64D: error: unknown target ABI 'lp64d'
+
+// RUN: not %clang -target riscv64-unknown-elf %s -o %t.o -mabi=ilp32 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-RV64-ILP32 %s
+
+// CHECK-RV64-ILP32: error: unknown target ABI 'ilp32'
diff --git a/test/Driver/riscv-arch.c b/test/Driver/riscv-arch.c
new file mode 100644
index 000000000000..5329fe87aac7
--- /dev/null
+++ b/test/Driver/riscv-arch.c
@@ -0,0 +1,317 @@
+// RUN: %clang -target riscv32-unknown-elf -march=rv32i -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32im -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32ima -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32imaf -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32imafd -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32ic -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32imc -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32imac -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32imafc -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32imafdc -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32ia -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32iaf -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32iafd -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32iac -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32iafc -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32iafdc -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32g -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32gc -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+
+// RUN: %clang -target riscv64-unknown-elf -march=rv64i -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -march=rv64im -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -march=rv64ima -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -march=rv64imaf -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -march=rv64imafd -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+
+// RUN: %clang -target riscv64-unknown-elf -march=rv64ic -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -march=rv64imc -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -march=rv64imac -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -march=rv64imafc -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -march=rv64imafdc -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+
+// RUN: %clang -target riscv64-unknown-elf -march=rv64ia -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -march=rv64iaf -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -march=rv64iafd -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+
+// RUN: %clang -target riscv64-unknown-elf -march=rv64iac -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -march=rv64iafc -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -march=rv64iafdc -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+
+// RUN: %clang -target riscv64-unknown-elf -march=rv64g -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -march=rv64gc -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+
+// CHECK-NOT: error: invalid arch name '
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32 -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32 %s
+// RV32: error: invalid arch name 'rv32'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32m -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32M %s
+// RV32M: error: invalid arch name 'rv32m'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32id -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32ID %s
+// RV32ID: error: invalid arch name 'rv32id'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32l -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32L %s
+// RV32L: error: invalid arch name 'rv32l'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32imadf -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32IMADF %s
+// RV32IMADF: error: invalid arch name 'rv32imadf'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32imm -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32IMM %s
+// RV32IMM: error: invalid arch name 'rv32imm'
+
+// RUN: %clang -target riscv32-unknown-elf -march=RV32I -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32I-UPPER %s
+// RV32I-UPPER: error: invalid arch name 'RV32I'
+
+// RUN: %clang -target riscv64-unknown-elf -march=rv64 -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64 %s
+// RV64: error: invalid arch name 'rv64'
+
+// RUN: %clang -target riscv64-unknown-elf -march=rv64m -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64M %s
+// RV64M: error: invalid arch name 'rv64m'
+
+// RUN: %clang -target riscv64-unknown-elf -march=rv64id -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64ID %s
+// RV64ID: error: invalid arch name 'rv64id'
+
+// RUN: %clang -target riscv64-unknown-elf -march=rv64l -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64L %s
+// RV64L: error: invalid arch name 'rv64l'
+
+// RUN: %clang -target riscv64-unknown-elf -march=rv64imadf -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64IMADF %s
+// RV64IMADF: error: invalid arch name 'rv64imadf'
+
+// RUN: %clang -target riscv64-unknown-elf -march=rv64imm -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64IMM %s
+// RV64IMM: error: invalid arch name 'rv64imm'
+
+// RUN: %clang -target riscv64-unknown-elf -march=RV64I -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64I-UPPER %s
+// RV64I-UPPER: error: invalid arch name 'RV64I'
+
+
+// Testing specific messages and unsupported extensions.
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32e -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32E %s
+// RV32E: error: invalid arch name 'rv32e',
+// RV32E: standard user-level extension 'e'
+
+// RUN: %clang -target riscv64-unknown-elf -march=rv64e -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64E %s
+// RV64E: error: invalid arch name 'rv64e',
+// RV64E: standard user-level extension 'e' requires 'rv32'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32imC -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-LOWER %s
+// RV32-LOWER: error: invalid arch name 'rv32imC',
+// RV32-LOWER: string must be lowercase
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32 -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-STR %s
+// RV32-STR: error: invalid arch name 'rv32',
+// RV32-STR: string must begin with rv32{i,e,g} or rv64{i,g}
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32q -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-LETTER %s
+// RV32-LETTER: error: invalid arch name 'rv32q',
+// RV32-LETTER: first letter should be 'e', 'i' or 'g'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32imcq -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-ORDER %s
+// RV32-ORDER: error: invalid arch name 'rv32imcq',
+// RV32-ORDER: standard user-level extension not given in canonical order 'q'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32imw -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-STD-INVAL %s
+// RV32-STD-INVAL: error: invalid arch name 'rv32imw',
+// RV32-STD-INVAL: invalid standard user-level extension 'w'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32imqc -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-STD %s
+// RV32-STD: error: invalid arch name 'rv32imqc',
+// RV32-STD: unsupported standard user-level extension 'q'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32xabc -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32X %s
+// RV32X: error: invalid arch name 'rv32xabc',
+// RV32X: first letter should be 'e', 'i' or 'g'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32sxabc -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32SX %s
+// RV32SX: error: invalid arch name 'rv32sxabc',
+// RV32SX: first letter should be 'e', 'i' or 'g'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32sabc -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32S %s
+// RV32S: error: invalid arch name 'rv32sabc',
+// RV32S: first letter should be 'e', 'i' or 'g'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32ix -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32X-NAME %s
+// RV32X-NAME: error: invalid arch name 'rv32ix',
+// RV32X-NAME: non-standard user-level extension name missing after 'x'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32isx -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32SX-NAME %s
+// RV32SX-NAME: error: invalid arch name 'rv32isx',
+// RV32SX-NAME: non-standard supervisor-level extension
+// RV32SX-NAME: name missing after 'sx'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32is -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32S-NAME %s
+// RV32S-NAME: error: invalid arch name 'rv32is',
+// RV32S-NAME: standard supervisor-level extension
+// RV32S-NAME: name missing after 's'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32ix_s_sx -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32ALL-NAME %s
+// RV32ALL-NAME: error: invalid arch name 'rv32ix_s_sx',
+// RV32ALL-NAME: non-standard user-level extension
+// RV32ALL-NAME: name missing after 'x'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32ixabc -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32X-UNS %s
+// RV32X-UNS: error: invalid arch name 'rv32ixabc',
+// RV32X-UNS: unsupported non-standard user-level extension 'xabc'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32isa -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32S-UNS %s
+// RV32S-UNS: error: invalid arch name 'rv32isa',
+// RV32S-UNS: unsupported standard supervisor-level extension 'sa'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32isxabc -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32SX-UNS %s
+// RV32SX-UNS: error: invalid arch name 'rv32isxabc',
+// RV32SX-UNS: unsupported non-standard supervisor-level extension 'sxabc'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32ixabc_sp_sxlw -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32ALL %s
+// RV32ALL: error: invalid arch name 'rv32ixabc_sp_sxlw',
+// RV32ALL: unsupported non-standard user-level extension 'xabc'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32i20 -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-IVER %s
+// RV32-IVER: error: invalid arch name 'rv32i20', unsupported
+// RV32-IVER: version number 20 for extension 'i'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32imc5 -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-CVER %s
+// RV32-CVER: error: invalid arch name 'rv32imc5', unsupported
+// RV32-CVER: version number 5 for extension 'c'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32i2p -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-IMINOR-MISS %s
+// RV32-IMINOR-MISS: error: invalid arch name 'rv32i2p',
+// RV32-IMINOR-MISS: minor version number missing after 'p' for extension 'i'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32i2p0 -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-IMINOR0 %s
+// RV32-IMINOR0: error: invalid arch name 'rv32i2p0',
+// RV32-IMINOR0: unsupported version number 2.0 for extension 'i'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32i2p1 -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-IMINOR1 %s
+// RV32-IMINOR1: error: invalid arch name 'rv32i2p1', unsupported
+// RV32-IMINOR1: version number 2.1 for extension 'i'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32ix2p -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-XMINOR-MISS %s
+// RV32-XMINOR-MISS: error: invalid arch name 'rv32ix2p',
+// RV32-XMINOR-MISS: minor version number missing after 'p' for extension 'x2p'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32is2p0 -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-SMINOR0 %s
+// RV32-SMINOR0: error: invalid arch name 'rv32is2p0',
+// RV32-SMINOR0: unsupported version number 2.0 for extension 's2p0'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32isx2p1 -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-SXMINOR1 %s
+// RV32-SXMINOR1: error: invalid arch name 'rv32isx2p1', unsupported
+// RV32-SXMINOR1: version number 2.1 for extension 'sx2p1'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32ixabc_ -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-XSEP %s
+// RV32-XSEP: error: invalid arch name 'rv32ixabc_',
+// RV32-XSEP: extension name missing after separator '_'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32ixabc_a -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-PREFIX %s
+// RV32-PREFIX: error: invalid arch name 'rv32ixabc_a',
+// RV32-PREFIX: invalid extension prefix 'a'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32isabc_xdef -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-X-ORDER %s
+// RV32-X-ORDER: error: invalid arch name 'rv32isabc_xdef',
+// RV32-X-ORDER: non-standard user-level extension not given
+// RV32-X-ORDER: in canonical order 'xdef'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32isxabc_sdef -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-S-ORDER %s
+// RV32-S-ORDER: error: invalid arch name 'rv32isxabc_sdef',
+// RV32-S-ORDER: standard supervisor-level extension not given
+// RV32-S-ORDER: in canonical order 'sdef'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32ixabc_xabc -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-XDUP %s
+// RV32-XDUP: error: invalid arch name 'rv32ixabc_xabc',
+// RV32-XDUP: duplicated non-standard user-level extension 'xabc'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32ixabc_xdef -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-X-X-INVAL %s
+// RV32-X-X-INVAL: error: invalid arch name 'rv32ixabc_xdef', unsupported
+// RV32-X-X-INVAL: non-standard user-level extension 'xabc'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32ixabc_sdef_sxghi -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-X-S-SX-INVAL %s
+// RV32-X-S-SX-INVAL: error: invalid arch name 'rv32ixabc_sdef_sxghi',
+// RV32-X-S-SX-INVAL: unsupported non-standard user-level extension 'xabc'
diff --git a/test/Driver/riscv-features.c b/test/Driver/riscv-features.c
new file mode 100644
index 000000000000..95f84f31c611
--- /dev/null
+++ b/test/Driver/riscv-features.c
@@ -0,0 +1,13 @@
+// RUN: %clang -target riscv32-unknown-elf -### %s -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -### %s -fsyntax-only 2>&1 | FileCheck %s
+
+// CHECK: fno-signed-char
+
+// RUN: %clang -target riscv32-unknown-elf -### %s -mrelax 2>&1 | FileCheck %s -check-prefix=RELAX
+// RUN: %clang -target riscv32-unknown-elf -### %s -mno-relax 2>&1 | FileCheck %s -check-prefix=NO-RELAX
+// RUN: %clang -target riscv32-unknown-elf -### %s 2>&1 | FileCheck %s -check-prefix=DEFAULT
+
+// RELAX: "-target-feature" "+relax"
+// NO-RELAX: "-target-feature" "-relax"
+// DEFAULT-NOT: "-target-feature" "+relax"
+// DEFAULT-NOT: "-target-feature" "-relax"
diff --git a/test/Driver/riscv-gnutools.c b/test/Driver/riscv-gnutools.c
new file mode 100644
index 000000000000..afcb5052aa3f
--- /dev/null
+++ b/test/Driver/riscv-gnutools.c
@@ -0,0 +1,19 @@
+// Check gnutools are invoked with propagated values for -mabi and -march.
+
+// RUN: %clang -target riscv32 -fno-integrated-as %s -### -c \
+// RUN: 2>&1 | FileCheck -check-prefix=MABI-ILP32 %s
+
+// RUN: %clang -target riscv32 -fno-integrated-as -march=rv32g %s -### -c \
+// RUN: 2>&1 | FileCheck -check-prefix=MABI-ILP32-MARCH-G %s
+
+// RUN: %clang -target riscv64 -fno-integrated-as %s -### -c \
+// RUN: 2>&1 | FileCheck -check-prefix=MABI-ILP64 %s
+
+// RUN: %clang -target riscv64 -fno-integrated-as -march=rv64g %s -### -c \
+// RUN: 2>&1 | FileCheck -check-prefix=MABI-ILP64-MARCH-G %s
+
+// MABI-ILP32: "{{.*}}as{{(.exe)?}}" "-mabi" "ilp32"
+// MABI-ILP32-MARCH-G: "{{.*}}as{{(.exe)?}}" "-mabi" "ilp32" "-march" "rv32g"
+
+// MABI-ILP64: "{{.*}}as{{(.exe)?}}" "-mabi" "lp64"
+// MABI-ILP64-MARCH-G: "{{.*}}as{{(.exe)?}}" "-mabi" "lp64" "-march" "rv64g"
diff --git a/test/Driver/riscv32-toolchain.c b/test/Driver/riscv32-toolchain.c
new file mode 100644
index 000000000000..1e93e97c5313
--- /dev/null
+++ b/test/Driver/riscv32-toolchain.c
@@ -0,0 +1,122 @@
+// A basic clang -cc1 command-line, and simple environment check.
+
+// RUN: %clang %s -### -no-canonical-prefixes -target riscv32 2>&1 | FileCheck -check-prefix=CC1 %s
+// CC1: clang{{.*}} "-cc1" "-triple" "riscv32"
+
+
+// RUN: %clang %s -### -no-canonical-prefixes -fuse-ld=ld \
+// RUN: -target riscv32-linux-unknown-elf \
+// RUN: --gcc-toolchain=%S/Inputs/multilib_riscv_linux_sdk \
+// RUN: --sysroot=%S/Inputs/multilib_riscv_linux_sdk/sysroot 2>&1 \
+// RUN: | FileCheck -check-prefix=C-RV32-LINUX-MULTI-ILP32 %s
+
+// C-RV32-LINUX-MULTI-ILP32: "{{.*}}/Inputs/multilib_riscv_linux_sdk/lib/gcc/riscv64-unknown-linux-gnu/7.2.0/../../../../riscv64-unknown-linux-gnu/bin{{/|\\\\}}ld"
+// C-RV32-LINUX-MULTI-ILP32: "--sysroot={{.*}}/Inputs/multilib_riscv_linux_sdk/sysroot"
+// C-RV32-LINUX-MULTI-ILP32: "-m" "elf32lriscv"
+// C-RV32-LINUX-MULTI-ILP32: "-dynamic-linker" "/lib/ld-linux-riscv32-ilp32.so.1"
+// C-RV32-LINUX-MULTI-ILP32: "{{.*}}/Inputs/multilib_riscv_linux_sdk/lib/gcc/riscv64-unknown-linux-gnu/7.2.0/lib32/ilp32{{/|\\\\}}crtbegin.o"
+// C-RV32-LINUX-MULTI-ILP32: "-L{{.*}}/Inputs/multilib_riscv_linux_sdk/lib/gcc/riscv64-unknown-linux-gnu/7.2.0/lib32/ilp32"
+// C-RV32-LINUX-MULTI-ILP32: "-L{{.*}}/Inputs/multilib_riscv_linux_sdk/sysroot/lib32/ilp32"
+// C-RV32-LINUX-MULTI-ILP32: "-L{{.*}}/Inputs/multilib_riscv_linux_sdk/sysroot/usr/lib32/ilp32"
+
+// RUN: %clang %s -### -no-canonical-prefixes -fuse-ld=ld \
+// RUN: -target riscv32-linux-unknown-elf -march=rv32imafd -mabi=ilp32d \
+// RUN: --gcc-toolchain=%S/Inputs/multilib_riscv_linux_sdk \
+// RUN: --sysroot=%S/Inputs/multilib_riscv_linux_sdk/sysroot 2>&1 \
+// RUN: | FileCheck -check-prefix=C-RV32-LINUX-MULTI-ILP32D %s
+
+// C-RV32-LINUX-MULTI-ILP32D: "{{.*}}/Inputs/multilib_riscv_linux_sdk/lib/gcc/riscv64-unknown-linux-gnu/7.2.0/../../../../riscv64-unknown-linux-gnu/bin{{/|\\\\}}ld"
+// C-RV32-LINUX-MULTI-ILP32D: "--sysroot={{.*}}/Inputs/multilib_riscv_linux_sdk/sysroot"
+// C-RV32-LINUX-MULTI-ILP32D: "-m" "elf32lriscv"
+// C-RV32-LINUX-MULTI-ILP32D: "-dynamic-linker" "/lib/ld-linux-riscv32-ilp32d.so.1"
+// C-RV32-LINUX-MULTI-ILP32D: "{{.*}}/Inputs/multilib_riscv_linux_sdk/lib/gcc/riscv64-unknown-linux-gnu/7.2.0/lib32/ilp32d{{/|\\\\}}crtbegin.o"
+// C-RV32-LINUX-MULTI-ILP32D: "-L{{.*}}/Inputs/multilib_riscv_linux_sdk/lib/gcc/riscv64-unknown-linux-gnu/7.2.0/lib32/ilp32d"
+// C-RV32-LINUX-MULTI-ILP32D: "-L{{.*}}/Inputs/multilib_riscv_linux_sdk/sysroot/lib32/ilp32d"
+// C-RV32-LINUX-MULTI-ILP32D: "-L{{.*}}/Inputs/multilib_riscv_linux_sdk/sysroot/usr/lib32/ilp32d"
+
+// RUN: %clang -target riscv32 %s -emit-llvm -S -o - | FileCheck %s
+
+typedef __builtin_va_list va_list;
+typedef __SIZE_TYPE__ size_t;
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+typedef __WCHAR_TYPE__ wchar_t;
+
+// CHECK: @align_c = dso_local global i32 1
+int align_c = __alignof(char);
+
+// CHECK: @align_s = dso_local global i32 2
+int align_s = __alignof(short);
+
+// CHECK: @align_i = dso_local global i32 4
+int align_i = __alignof(int);
+
+// CHECK: @align_wc = dso_local global i32 4
+int align_wc = __alignof(wchar_t);
+
+// CHECK: @align_l = dso_local global i32 4
+int align_l = __alignof(long);
+
+// CHECK: @align_ll = dso_local global i32 8
+int align_ll = __alignof(long long);
+
+// CHECK: @align_p = dso_local global i32 4
+int align_p = __alignof(void*);
+
+// CHECK: @align_f = dso_local global i32 4
+int align_f = __alignof(float);
+
+// CHECK: @align_d = dso_local global i32 8
+int align_d = __alignof(double);
+
+// CHECK: @align_ld = dso_local global i32 16
+int align_ld = __alignof(long double);
+
+// CHECK: @align_vl = dso_local global i32 4
+int align_vl = __alignof(va_list);
+
+// Check types
+
+// CHECK: zeroext i8 @check_char()
+char check_char() { return 0; }
+
+// CHECK: define dso_local signext i16 @check_short()
+short check_short() { return 0; }
+
+// CHECK: define dso_local i32 @check_int()
+int check_int() { return 0; }
+
+// CHECK: define dso_local i32 @check_wchar_t()
+int check_wchar_t() { return 0; }
+
+// CHECK: define dso_local i32 @check_long()
+long check_long() { return 0; }
+
+// CHECK: define dso_local i64 @check_longlong()
+long long check_longlong() { return 0; }
+
+// CHECK: define dso_local zeroext i8 @check_uchar()
+unsigned char check_uchar() { return 0; }
+
+// CHECK: define dso_local zeroext i16 @check_ushort()
+unsigned short check_ushort() { return 0; }
+
+// CHECK: define dso_local i32 @check_uint()
+unsigned int check_uint() { return 0; }
+
+// CHECK: define dso_local i32 @check_ulong()
+unsigned long check_ulong() { return 0; }
+
+// CHECK: define dso_local i64 @check_ulonglong()
+unsigned long long check_ulonglong() { return 0; }
+
+// CHECK: define dso_local i32 @check_size_t()
+size_t check_size_t() { return 0; }
+
+// CHECK: define dso_local float @check_float()
+float check_float() { return 0; }
+
+// CHECK: define dso_local double @check_double()
+double check_double() { return 0; }
+
+// CHECK: define dso_local fp128 @check_longdouble()
+long double check_longdouble() { return 0; }
diff --git a/test/Driver/riscv64-toolchain.c b/test/Driver/riscv64-toolchain.c
new file mode 100644
index 000000000000..44dcc937df2d
--- /dev/null
+++ b/test/Driver/riscv64-toolchain.c
@@ -0,0 +1,91 @@
+// A basic clang -cc1 command-line, and simple environment check.
+
+// RUN: %clang %s -### -no-canonical-prefixes -target riscv64 2>&1 | FileCheck -check-prefix=CC1 %s
+// CC1: clang{{.*}} "-cc1" "-triple" "riscv64"
+
+// RUN: %clang -target riscv64 %s -emit-llvm -S -o - | FileCheck %s
+
+typedef __builtin_va_list va_list;
+typedef __SIZE_TYPE__ size_t;
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+typedef __WCHAR_TYPE__ wchar_t;
+
+// CHECK: @align_c = dso_local global i32 1
+int align_c = __alignof(char);
+
+// CHECK: @align_s = dso_local global i32 2
+int align_s = __alignof(short);
+
+// CHECK: @align_i = dso_local global i32 4
+int align_i = __alignof(int);
+
+// CHECK: @align_wc = dso_local global i32 4
+int align_wc = __alignof(wchar_t);
+
+// CHECK: @align_l = dso_local global i32 8
+int align_l = __alignof(long);
+
+// CHECK: @align_ll = dso_local global i32 8
+int align_ll = __alignof(long long);
+
+// CHECK: @align_p = dso_local global i32 8
+int align_p = __alignof(void*);
+
+// CHECK: @align_f = dso_local global i32 4
+int align_f = __alignof(float);
+
+// CHECK: @align_d = dso_local global i32 8
+int align_d = __alignof(double);
+
+// CHECK: @align_ld = dso_local global i32 16
+int align_ld = __alignof(long double);
+
+// CHECK: @align_vl = dso_local global i32 8
+int align_vl = __alignof(va_list);
+
+// Check types
+
+// CHECK: define dso_local zeroext i8 @check_char()
+char check_char() { return 0; }
+
+// CHECK: define dso_local signext i16 @check_short()
+short check_short() { return 0; }
+
+// CHECK: define dso_local signext i32 @check_int()
+int check_int() { return 0; }
+
+// CHECK: define dso_local signext i32 @check_wchar_t()
+int check_wchar_t() { return 0; }
+
+// CHECK: define dso_local i64 @check_long()
+long check_long() { return 0; }
+
+// CHECK: define dso_local i64 @check_longlong()
+long long check_longlong() { return 0; }
+
+// CHECK: define dso_local zeroext i8 @check_uchar()
+unsigned char check_uchar() { return 0; }
+
+// CHECK: define dso_local zeroext i16 @check_ushort()
+unsigned short check_ushort() { return 0; }
+
+// CHECK: define dso_local signext i32 @check_uint()
+unsigned int check_uint() { return 0; }
+
+// CHECK: define dso_local i64 @check_ulong()
+unsigned long check_ulong() { return 0; }
+
+// CHECK: define dso_local i64 @check_ulonglong()
+unsigned long long check_ulonglong() { return 0; }
+
+// CHECK: define dso_local i64 @check_size_t()
+size_t check_size_t() { return 0; }
+
+// CHECK: define dso_local float @check_float()
+float check_float() { return 0; }
+
+// CHECK: define dso_local double @check_double()
+double check_double() { return 0; }
+
+// CHECK: define dso_local fp128 @check_longdouble()
+long double check_longdouble() { return 0; }
diff --git a/test/Driver/rtti-options.cpp b/test/Driver/rtti-options.cpp
index bb2958d845b6..e1d37d35bb68 100644
--- a/test/Driver/rtti-options.cpp
+++ b/test/Driver/rtti-options.cpp
@@ -1,12 +1,12 @@
// Check that we emit warnings/errors for different combinations of
-// exceptions, rtti, and vptr sanitizer flags when targetting the PS4.
+// exceptions, rtti, and vptr sanitizer flags for generic (unknown) x86 linux,
+// and for PS4 when its behaviour differs from the generic x86-linux.
// No warnings/errors should be emitted for unknown, except if combining
// the vptr sanitizer with -fno-rtti
// Special cases: -fcxx-exceptions in C code should warn about unused arguments
// We should also not have any rtti-related arguments
-// RUN: %clang -x c -### -target x86_64-scei-ps4 -c -fcxx-exceptions %s 2>&1 | FileCheck -check-prefix=CHECK-UNUSED -check-prefix=CHECK-RTTI -check-prefix=CHECK-NO-RTTI %s
-// RUN: %clang -x c -### -target x86_64-unknown-unknown -c -fcxx-exceptions %s 2>&1 | FileCheck -check-prefix=CHECK-UNUSED -check-prefix=CHECK-RTTI -check-prefix=CHECK-NO-RTTI %s
+// RUN: %clang -x c -### -target x86_64-unknown-unknown -c -fcxx-exceptions %s 2>&1 | FileCheck -check-prefix=CHECK-UNUSED -check-prefix=CHECK-RTTI %s
// Make sure we keep the last -frtti/-fno-rtti argument
// RUN: %clang -### -c -fno-rtti -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-RTTI %s
@@ -22,28 +22,18 @@
// RUN: %clang -### -c -target x86_64-unknown-linux -fsanitize=undefined %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
// RUN: %clang -### -c -target x86_64-unknown-linux -fsanitize=undefined -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
// RUN: %clang -### -c -target x86_64-scei-ps4 -fsanitize=vptr %s 2>&1 | FileCheck -check-prefix=CHECK-SAN-WARN %s
-// RUN: %clang -### -c -target x86_64-scei-ps4 -fsanitize=vptr -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
-// RUN: %clang -### -c -target x86_64-scei-ps4 -fsanitize=vptr -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-SAN-ERROR %s
-// RUN: %clang -### -c -target x86_64-scei-ps4 -fsanitize=undefined -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
// Exceptions + no/default rtti
-// RUN: %clang -### -c -target x86_64-scei-ps4 -fcxx-exceptions -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-EXC-ERROR-CXX %s
-// RUN: %clang -### -c -target x86_64-scei-ps4 -fcxx-exceptions %s 2>&1 | FileCheck -check-prefix=CHECK-EXC-WARN %s
// RUN: %clang -### -c -target x86_64-unknown-unknown -fcxx-exceptions -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
// RUN: %clang -### -c -target x86_64-unknown-unknown -fcxx-exceptions %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
// In C++, -fexceptions implies -fcxx-exceptions
-// RUN: %clang -x c++ -### -c -target x86_64-scei-ps4 -fexceptions -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-EXC-ERROR %s
-// RUN: %clang -x c++ -### -c -target x86_64-scei-ps4 -fexceptions %s 2>&1 | FileCheck -check-prefix=CHECK-EXC-WARN %s
// RUN: %clang -x c++ -### -c -target x86_64-unknown-unknown -fexceptions -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
// RUN: %clang -x c++ -### -c -target x86_64-unknown-unknown -fexceptions %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
// -frtti + exceptions
-// RUN: %clang -### -c -target x86_64-scei-ps4 -fcxx-exceptions -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
// RUN: %clang -### -c -target x86_64-unknown-unknown -fcxx-exceptions -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
// -f{no-,}rtti/default
-// RUN: %clang -### -c -target x86_64-scei-ps4 -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-RTTI %s
-// RUN: %clang -### -c -target x86_64-scei-ps4 -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-NO-RTTI %s
// RUN: %clang -### -c -target x86_64-scei-ps4 %s 2>&1 | FileCheck -check-prefix=CHECK-NO-RTTI %s
// RUN: %clang -### -c -target x86_64-unknown-unknown -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-RTTI %s
// RUN: %clang -### -c -target x86_64-unknown-unknown -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-NO-RTTI %s
@@ -52,10 +42,7 @@
// CHECK-UNUSED: warning: argument unused during compilation: '-fcxx-exceptions'
// CHECK-SAN-WARN: implicitly disabling vptr sanitizer because rtti wasn't enabled
// CHECK-SAN-ERROR: invalid argument '-fsanitize=vptr' not allowed with '-fno-rtti'
-// CHECK-EXC-WARN: implicitly enabling rtti for exception handling
-// CHECK-EXC-ERROR: invalid argument '-fno-rtti' not allowed with '-fexceptions'
-// CHECK-EXC-ERROR-CXX: invalid argument '-fno-rtti' not allowed with '-fcxx-exceptions'
// CHECK-RTTI-NOT: "-fno-rtti"
-// CHECK-NO-RTTI-NOT: "-frtti"
+// CHECK-NO-RTTI: "-fno-rtti"
// CHECK-OK-NOT: {{warning:|error:}}
diff --git a/test/Driver/sanitizer-ld.c b/test/Driver/sanitizer-ld.c
index 0da4255f6995..f07fe922ecca 100644
--- a/test/Driver/sanitizer-ld.c
+++ b/test/Driver/sanitizer-ld.c
@@ -9,9 +9,9 @@
// CHECK-ASAN-LINUX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
// CHECK-ASAN-LINUX-NOT: "-lc"
// CHECK-ASAN-LINUX: libclang_rt.asan-i386.a"
-// CHECK-ASAN-LINUX-NOT: "-export-dynamic"
+// CHECK-ASAN-LINUX-NOT: "--export-dynamic"
// CHECK-ASAN-LINUX: "--dynamic-list={{.*}}libclang_rt.asan-i386.a.syms"
-// CHECK-ASAN-LINUX-NOT: "-export-dynamic"
+// CHECK-ASAN-LINUX-NOT: "--export-dynamic"
// CHECK-ASAN-LINUX: "-lpthread"
// CHECK-ASAN-LINUX: "-lrt"
// CHECK-ASAN-LINUX: "-ldl"
@@ -39,11 +39,11 @@
// CHECK-SHARED-ASAN-LINUX-NOT: "-lc"
// CHECK-SHARED-ASAN-LINUX-NOT: libclang_rt.asan-i386.a"
// CHECK-SHARED-ASAN-LINUX: libclang_rt.asan-i386.so"
-// CHECK-SHARED-ASAN-LINUX: "-whole-archive" "{{.*}}libclang_rt.asan-preinit-i386.a" "-no-whole-archive"
+// CHECK-SHARED-ASAN-LINUX: "--whole-archive" "{{.*}}libclang_rt.asan-preinit-i386.a" "--no-whole-archive"
// CHECK-SHARED-ASAN-LINUX-NOT: "-lpthread"
// CHECK-SHARED-ASAN-LINUX-NOT: "-lrt"
// CHECK-SHARED-ASAN-LINUX-NOT: "-ldl"
-// CHECK-SHARED-ASAN-LINUX-NOT: "-export-dynamic"
+// CHECK-SHARED-ASAN-LINUX-NOT: "--export-dynamic"
// CHECK-SHARED-ASAN-LINUX-NOT: "--dynamic-list"
// RUN: %clang -no-canonical-prefixes %s -### -o %t.so -shared 2>&1 \
@@ -60,7 +60,7 @@
// CHECK-DSO-SHARED-ASAN-LINUX-NOT: "-lpthread"
// CHECK-DSO-SHARED-ASAN-LINUX-NOT: "-lrt"
// CHECK-DSO-SHARED-ASAN-LINUX-NOT: "-ldl"
-// CHECK-DSO-SHARED-ASAN-LINUX-NOT: "-export-dynamic"
+// CHECK-DSO-SHARED-ASAN-LINUX-NOT: "--export-dynamic"
// CHECK-DSO-SHARED-ASAN-LINUX-NOT: "--dynamic-list"
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
@@ -75,7 +75,7 @@
// CHECK-ASAN-FREEBSD: freebsd{{/|\\+}}libclang_rt.asan-i386.a"
// CHECK-ASAN-FREEBSD-NOT: libclang_rt.asan_cxx
// CHECK-ASAN-FREEBSD-NOT: "--dynamic-list"
-// CHECK-ASAN-FREEBSD: "-export-dynamic"
+// CHECK-ASAN-FREEBSD: "--export-dynamic"
// CHECK-ASAN-FREEBSD: "-lpthread"
// CHECK-ASAN-FREEBSD: "-lrt"
@@ -96,10 +96,10 @@
//
// CHECK-ASAN-LINUX-CXX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
// CHECK-ASAN-LINUX-CXX-NOT: "-lc"
-// CHECK-ASAN-LINUX-CXX: "-whole-archive" "{{.*}}libclang_rt.asan-i386.a" "-no-whole-archive"
-// CHECK-ASAN-LINUX-CXX: "-whole-archive" "{{.*}}libclang_rt.asan_cxx-i386.a" "-no-whole-archive"
+// CHECK-ASAN-LINUX-CXX: "--whole-archive" "{{.*}}libclang_rt.asan-i386.a" "--no-whole-archive"
+// CHECK-ASAN-LINUX-CXX: "--whole-archive" "{{.*}}libclang_rt.asan_cxx-i386.a" "--no-whole-archive"
// CHECK-ASAN-LINUX-CXX-NOT: "--dynamic-list"
-// CHECK-ASAN-LINUX-CXX: "-export-dynamic"
+// CHECK-ASAN-LINUX-CXX: "--export-dynamic"
// CHECK-ASAN-LINUX-CXX: stdc++
// CHECK-ASAN-LINUX-CXX: "-lpthread"
// CHECK-ASAN-LINUX-CXX: "-lrt"
@@ -112,7 +112,7 @@
//
// CHECK-ASAN-LINUX-CXX-STATIC: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
// CHECK-ASAN-LINUX-CXX-STATIC-NOT: stdc++
-// CHECK-ASAN-LINUX-CXX-STATIC: "-whole-archive" "{{.*}}libclang_rt.asan-i386.a" "-no-whole-archive"
+// CHECK-ASAN-LINUX-CXX-STATIC: "--whole-archive" "{{.*}}libclang_rt.asan-i386.a" "--no-whole-archive"
// CHECK-ASAN-LINUX-CXX-STATIC: stdc++
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
@@ -153,7 +153,8 @@
//
// CHECK-ASAN-ANDROID-STATICLIBASAN: "{{(.*[^.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
// CHECK-ASAN-ANDROID-STATICLIBASAN: libclang_rt.asan-arm-android.a"
-// CHECK-ASAN-ANDROID-STATICLIBASAN: "-lpthread"
+// CHECK-ASAN-ANDROID-STATICLIBASAN-NOT: "-lpthread"
+// CHECK-ASAN-ANDROID-STATICLIBASAN-NOT: "-lrt"
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN: -target arm-linux-androideabi -fuse-ld=ld -fsanitize=undefined \
@@ -175,7 +176,8 @@
//
// CHECK-UBSAN-ANDROID-STATICLIBASAN: "{{(.*[^.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
// CHECK-UBSAN-ANDROID-STATICLIBASAN: libclang_rt.ubsan_standalone-arm-android.a"
-// CHECK-UBSAN-ANDROID-STATICLIBASAN: "-lpthread"
+// CHECK-UBSAN-ANDROID-STATICLIBASAN-NOT: "-lpthread"
+// CHECK-UBSAN-ANDROID-STATICLIBASAN-NOT: "-lrt"
//
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
@@ -227,11 +229,11 @@
//
// CHECK-TSAN-LINUX-CXX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
// CHECK-TSAN-LINUX-CXX-NOT: stdc++
-// CHECK-TSAN-LINUX-CXX: "-whole-archive" "{{.*}}libclang_rt.tsan-x86_64.a" "-no-whole-archive"
+// CHECK-TSAN-LINUX-CXX: "--whole-archive" "{{.*}}libclang_rt.tsan-x86_64.a" "--no-whole-archive"
// CHECK-TSAN-LINUX-CXX: "--dynamic-list={{.*}}libclang_rt.tsan-x86_64.a.syms"
-// CHECK-TSAN-LINUX-CXX: "-whole-archive" "{{.*}}libclang_rt.tsan_cxx-x86_64.a" "-no-whole-archive"
+// CHECK-TSAN-LINUX-CXX: "--whole-archive" "{{.*}}libclang_rt.tsan_cxx-x86_64.a" "--no-whole-archive"
// CHECK-TSAN-LINUX-CXX: "--dynamic-list={{.*}}libclang_rt.tsan_cxx-x86_64.a.syms"
-// CHECK-TSAN-LINUX-CXX-NOT: "-export-dynamic"
+// CHECK-TSAN-LINUX-CXX-NOT: "--export-dynamic"
// CHECK-TSAN-LINUX-CXX: stdc++
// CHECK-TSAN-LINUX-CXX: "-lpthread"
// CHECK-TSAN-LINUX-CXX: "-lrt"
@@ -246,11 +248,11 @@
//
// CHECK-MSAN-LINUX-CXX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
// CHECK-MSAN-LINUX-CXX-NOT: stdc++
-// CHECK-MSAN-LINUX-CXX: "-whole-archive" "{{.*}}libclang_rt.msan-x86_64.a" "-no-whole-archive"
+// CHECK-MSAN-LINUX-CXX: "--whole-archive" "{{.*}}libclang_rt.msan-x86_64.a" "--no-whole-archive"
// CHECK-MSAN-LINUX-CXX: "--dynamic-list={{.*}}libclang_rt.msan-x86_64.a.syms"
-// CHECK-MSAN-LINUX-CXX: "-whole-archive" "{{.*}}libclang_rt.msan_cxx-x86_64.a" "-no-whole-archive"
+// CHECK-MSAN-LINUX-CXX: "--whole-archive" "{{.*}}libclang_rt.msan_cxx-x86_64.a" "--no-whole-archive"
// CHECK-MSAN-LINUX-CXX: "--dynamic-list={{.*}}libclang_rt.msan_cxx-x86_64.a.syms"
-// CHECK-MSAN-LINUX-CXX-NOT: "-export-dynamic"
+// CHECK-MSAN-LINUX-CXX-NOT: "--export-dynamic"
// CHECK-MSAN-LINUX-CXX: stdc++
// CHECK-MSAN-LINUX-CXX: "-lpthread"
// CHECK-MSAN-LINUX-CXX: "-lrt"
@@ -270,7 +272,7 @@
// CHECK-UBSAN-LINUX: "{{.*}}ld{{(.exe)?}}"
// CHECK-UBSAN-LINUX-NOT: libclang_rt.asan
// CHECK-UBSAN-LINUX-NOT: libclang_rt.ubsan_standalone_cxx
-// CHECK-UBSAN-LINUX: "-whole-archive" "{{.*}}libclang_rt.ubsan_standalone-i386.a" "-no-whole-archive"
+// CHECK-UBSAN-LINUX: "--whole-archive" "{{.*}}libclang_rt.ubsan_standalone-i386.a" "--no-whole-archive"
// CHECK-UBSAN-LINUX-NOT: libclang_rt.asan
// CHECK-UBSAN-LINUX-NOT: libclang_rt.ubsan_standalone_cxx
// CHECK-UBSAN-LINUX-NOT: "-lstdc++"
@@ -302,7 +304,7 @@
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
// RUN: | FileCheck --check-prefix=CHECK-UBSAN-LINUX-LINK-CXX %s
// CHECK-UBSAN-LINUX-LINK-CXX-NOT: "-lstdc++"
-// CHECK-UBSAN-LINUX-LINK-CXX: "-whole-archive" "{{.*}}libclang_rt.ubsan_standalone_cxx-i386.a" "-no-whole-archive"
+// CHECK-UBSAN-LINUX-LINK-CXX: "--whole-archive" "{{.*}}libclang_rt.ubsan_standalone_cxx-i386.a" "--no-whole-archive"
// CHECK-UBSAN-LINUX-LINK-CXX-NOT: "-lstdc++"
// RUN: %clangxx -fsanitize=undefined %s -### -o %t.o 2>&1 \
@@ -312,9 +314,9 @@
// RUN: | FileCheck --check-prefix=CHECK-UBSAN-LINUX-CXX %s
// CHECK-UBSAN-LINUX-CXX: "{{.*}}ld{{(.exe)?}}"
// CHECK-UBSAN-LINUX-CXX-NOT: libclang_rt.asan
-// CHECK-UBSAN-LINUX-CXX: "-whole-archive" "{{.*}}libclang_rt.ubsan_standalone-i386.a" "-no-whole-archive"
+// CHECK-UBSAN-LINUX-CXX: "--whole-archive" "{{.*}}libclang_rt.ubsan_standalone-i386.a" "--no-whole-archive"
// CHECK-UBSAN-LINUX-CXX-NOT: libclang_rt.asan
-// CHECK-UBSAN-LINUX-CXX: "-whole-archive" "{{.*}}libclang_rt.ubsan_standalone_cxx-i386.a" "-no-whole-archive"
+// CHECK-UBSAN-LINUX-CXX: "--whole-archive" "{{.*}}libclang_rt.ubsan_standalone_cxx-i386.a" "--no-whole-archive"
// CHECK-UBSAN-LINUX-CXX-NOT: libclang_rt.asan
// CHECK-UBSAN-LINUX-CXX: "-lstdc++"
// CHECK-UBSAN-LINUX-CXX-NOT: libclang_rt.asan
@@ -325,7 +327,7 @@
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
// RUN: | FileCheck --check-prefix=CHECK-UBSAN-MINIMAL-LINUX %s
// CHECK-UBSAN-MINIMAL-LINUX: "{{.*}}ld{{(.exe)?}}"
-// CHECK-UBSAN-MINIMAL-LINUX: "-whole-archive" "{{.*}}libclang_rt.ubsan_minimal-i386.a" "-no-whole-archive"
+// CHECK-UBSAN-MINIMAL-LINUX: "--whole-archive" "{{.*}}libclang_rt.ubsan_minimal-i386.a" "--no-whole-archive"
// CHECK-UBSAN-MINIMAL-LINUX: "-lpthread"
// RUN: %clang -fsanitize=undefined -fsanitize-minimal-runtime %s -### -o %t.o 2>&1 \
@@ -347,7 +349,7 @@
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
// RUN: | FileCheck --check-prefix=CHECK-ASAN-UBSAN-LINUX %s
// CHECK-ASAN-UBSAN-LINUX: "{{.*}}ld{{(.exe)?}}"
-// CHECK-ASAN-UBSAN-LINUX: "-whole-archive" "{{.*}}libclang_rt.asan-i386.a" "-no-whole-archive"
+// CHECK-ASAN-UBSAN-LINUX: "--whole-archive" "{{.*}}libclang_rt.asan-i386.a" "--no-whole-archive"
// CHECK-ASAN-UBSAN-LINUX-NOT: libclang_rt.ubsan
// CHECK-ASAN-UBSAN-LINUX-NOT: "-lstdc++"
// CHECK-ASAN-UBSAN-LINUX: "-lpthread"
@@ -357,8 +359,8 @@
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
// RUN: | FileCheck --check-prefix=CHECK-ASAN-UBSAN-LINUX-CXX %s
// CHECK-ASAN-UBSAN-LINUX-CXX: "{{.*}}ld{{(.exe)?}}"
-// CHECK-ASAN-UBSAN-LINUX-CXX: "-whole-archive" "{{.*}}libclang_rt.asan-i386.a" "-no-whole-archive"
-// CHECK-ASAN-UBSAN-LINUX-CXX: "-whole-archive" "{{.*}}libclang_rt.asan_cxx-i386.a" "-no-whole-archive"
+// CHECK-ASAN-UBSAN-LINUX-CXX: "--whole-archive" "{{.*}}libclang_rt.asan-i386.a" "--no-whole-archive"
+// CHECK-ASAN-UBSAN-LINUX-CXX: "--whole-archive" "{{.*}}libclang_rt.asan_cxx-i386.a" "--no-whole-archive"
// CHECK-ASAN-UBSAN-LINUX-CXX-NOT: libclang_rt.ubsan
// CHECK-ASAN-UBSAN-LINUX-CXX: "-lstdc++"
// CHECK-ASAN-UBSAN-LINUX-CXX: "-lpthread"
@@ -368,7 +370,7 @@
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
// RUN: | FileCheck --check-prefix=CHECK-MSAN-UBSAN-LINUX-CXX %s
// CHECK-MSAN-UBSAN-LINUX-CXX: "{{.*}}ld{{(.exe)?}}"
-// CHECK-MSAN-UBSAN-LINUX-CXX: "-whole-archive" "{{.*}}libclang_rt.msan-x86_64.a" "-no-whole-archive"
+// CHECK-MSAN-UBSAN-LINUX-CXX: "--whole-archive" "{{.*}}libclang_rt.msan-x86_64.a" "--no-whole-archive"
// CHECK-MSAN-UBSAN-LINUX-CXX-NOT: libclang_rt.ubsan
// RUN: %clangxx -fsanitize=thread,undefined %s -### -o %t.o 2>&1 \
@@ -376,7 +378,7 @@
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
// RUN: | FileCheck --check-prefix=CHECK-TSAN-UBSAN-LINUX-CXX %s
// CHECK-TSAN-UBSAN-LINUX-CXX: "{{.*}}ld{{(.exe)?}}"
-// CHECK-TSAN-UBSAN-LINUX-CXX: "-whole-archive" "{{.*}}libclang_rt.tsan-x86_64.a" "-no-whole-archive"
+// CHECK-TSAN-UBSAN-LINUX-CXX: "--whole-archive" "{{.*}}libclang_rt.tsan-x86_64.a" "--no-whole-archive"
// CHECK-TSAN-UBSAN-LINUX-CXX-NOT: libclang_rt.ubsan
// RUN: %clang -fsanitize=undefined %s -### -o %t.o 2>&1 \
@@ -429,7 +431,7 @@
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
// RUN: | FileCheck --check-prefix=CHECK-ASAN-COV-LINUX %s
// CHECK-ASAN-COV-LINUX: "{{.*}}ld{{(.exe)?}}"
-// CHECK-ASAN-COV-LINUX: "-whole-archive" "{{.*}}libclang_rt.asan-x86_64.a" "-no-whole-archive"
+// CHECK-ASAN-COV-LINUX: "--whole-archive" "{{.*}}libclang_rt.asan-x86_64.a" "--no-whole-archive"
// CHECK-ASAN-COV-LINUX-NOT: libclang_rt.ubsan
// CHECK-ASAN-COV-LINUX-NOT: "-lstdc++"
// CHECK-ASAN-COV-LINUX: "-lpthread"
@@ -439,7 +441,7 @@
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
// RUN: | FileCheck --check-prefix=CHECK-MSAN-COV-LINUX %s
// CHECK-MSAN-COV-LINUX: "{{.*}}ld{{(.exe)?}}"
-// CHECK-MSAN-COV-LINUX: "-whole-archive" "{{.*}}libclang_rt.msan-x86_64.a" "-no-whole-archive"
+// CHECK-MSAN-COV-LINUX: "--whole-archive" "{{.*}}libclang_rt.msan-x86_64.a" "--no-whole-archive"
// CHECK-MSAN-COV-LINUX-NOT: libclang_rt.ubsan
// CHECK-MSAN-COV-LINUX-NOT: "-lstdc++"
// CHECK-MSAN-COV-LINUX: "-lpthread"
@@ -449,7 +451,7 @@
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
// RUN: | FileCheck --check-prefix=CHECK-DFSAN-COV-LINUX %s
// CHECK-DFSAN-COV-LINUX: "{{.*}}ld{{(.exe)?}}"
-// CHECK-DFSAN-COV-LINUX: "-whole-archive" "{{.*}}libclang_rt.dfsan-x86_64.a" "-no-whole-archive"
+// CHECK-DFSAN-COV-LINUX: "--whole-archive" "{{.*}}libclang_rt.dfsan-x86_64.a" "--no-whole-archive"
// CHECK-DFSAN-COV-LINUX-NOT: libclang_rt.ubsan
// CHECK-DFSAN-COV-LINUX-NOT: "-lstdc++"
// CHECK-DFSAN-COV-LINUX: "-lpthread"
@@ -459,7 +461,7 @@
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
// RUN: | FileCheck --check-prefix=CHECK-UBSAN-COV-LINUX %s
// CHECK-UBSAN-COV-LINUX: "{{.*}}ld{{(.exe)?}}"
-// CHECK-UBSAN-COV-LINUX: "-whole-archive" "{{.*}}libclang_rt.ubsan_standalone-x86_64.a" "-no-whole-archive"
+// CHECK-UBSAN-COV-LINUX: "--whole-archive" "{{.*}}libclang_rt.ubsan_standalone-x86_64.a" "--no-whole-archive"
// CHECK-UBSAN-COV-LINUX-NOT: "-lstdc++"
// CHECK-UBSAN-COV-LINUX: "-lpthread"
@@ -468,7 +470,7 @@
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
// RUN: | FileCheck --check-prefix=CHECK-COV-LINUX %s
// CHECK-COV-LINUX: "{{.*}}ld{{(.exe)?}}"
-// CHECK-COV-LINUX: "-whole-archive" "{{.*}}libclang_rt.ubsan_standalone-x86_64.a" "-no-whole-archive"
+// CHECK-COV-LINUX: "--whole-archive" "{{.*}}libclang_rt.ubsan_standalone-x86_64.a" "--no-whole-archive"
// CHECK-COV-LINUX-NOT: "-lstdc++"
// CHECK-COV-LINUX: "-lpthread"
@@ -487,7 +489,7 @@
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
// RUN: | FileCheck --check-prefix=CHECK-CFI-DIAG-LINUX %s
// CHECK-CFI-DIAG-LINUX: "{{.*}}ld{{(.exe)?}}"
-// CHECK-CFI-DIAG-LINUX: "-whole-archive" "{{[^"]*}}libclang_rt.ubsan_standalone-x86_64.a" "-no-whole-archive"
+// CHECK-CFI-DIAG-LINUX: "--whole-archive" "{{[^"]*}}libclang_rt.ubsan_standalone-x86_64.a" "--no-whole-archive"
// Cross-DSO CFI links the CFI runtime.
// RUN: %clang -fsanitize=cfi -fsanitize-cfi-cross-dso %s -### -o %t.o 2>&1 \
@@ -495,7 +497,7 @@
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
// RUN: | FileCheck --check-prefix=CHECK-CFI-CROSS-DSO-LINUX %s
// CHECK-CFI-CROSS-DSO-LINUX: "{{.*}}ld{{(.exe)?}}"
-// CHECK-CFI-CROSS-DSO-LINUX: "-whole-archive" "{{[^"]*}}libclang_rt.cfi-x86_64.a" "-no-whole-archive"
+// CHECK-CFI-CROSS-DSO-LINUX: "--whole-archive" "{{[^"]*}}libclang_rt.cfi-x86_64.a" "--no-whole-archive"
// CHECK-CFI-CROSS-DSO-LINUX: -export-dynamic
// Cross-DSO CFI with diagnostics links just the CFI runtime.
@@ -505,7 +507,7 @@
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
// RUN: | FileCheck --check-prefix=CHECK-CFI-CROSS-DSO-DIAG-LINUX %s
// CHECK-CFI-CROSS-DSO-DIAG-LINUX: "{{.*}}ld{{(.exe)?}}"
-// CHECK-CFI-CROSS-DSO-DIAG-LINUX: "-whole-archive" "{{[^"]*}}libclang_rt.cfi_diag-x86_64.a" "-no-whole-archive"
+// CHECK-CFI-CROSS-DSO-DIAG-LINUX: "--whole-archive" "{{[^"]*}}libclang_rt.cfi_diag-x86_64.a" "--no-whole-archive"
// CHECK-CFI-CROSS-DSO-DIAG-LINUX: -export-dynamic
// Cross-DSO CFI on Android does not link runtime libraries.
@@ -514,7 +516,7 @@
// RUN: --sysroot=%S/Inputs/basic_android_tree \
// RUN: | FileCheck --check-prefix=CHECK-CFI-CROSS-DSO-ANDROID %s
// CHECK-CFI-CROSS-DSO-ANDROID: "{{.*}}ld{{(.exe)?}}"
-// CHECK-CFI-CROSS-DSO-ANDROID-NOT: libclang_rt.
+// CHECK-CFI-CROSS-DSO-ANDROID-NOT: libclang_rt.cfi
// Cross-DSO CFI with diagnostics on Android links just the UBSAN runtime.
// RUN: %clang -fsanitize=cfi -fsanitize-cfi-cross-dso %s -### -o %t.o 2>&1 \
@@ -528,6 +530,7 @@
// RUN: %clangxx -fsanitize=address %s -### -o %t.o 2>&1 \
// RUN: -mmacosx-version-min=10.6 \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: -target x86_64-apple-darwin13.4.0 -fuse-ld=ld -stdlib=platform \
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
// RUN: | FileCheck --check-prefix=CHECK-ASAN-DARWIN106-CXX %s
@@ -537,6 +540,7 @@
// RUN: %clangxx -fsanitize=leak %s -### -o %t.o 2>&1 \
// RUN: -mmacosx-version-min=10.6 \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: -target x86_64-apple-darwin13.4.0 -fuse-ld=ld -stdlib=platform \
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
// RUN: | FileCheck --check-prefix=CHECK-LSAN-DARWIN106-CXX %s
@@ -557,17 +561,46 @@
// CHECK-SAFESTACK-LINUX: "-lpthread"
// CHECK-SAFESTACK-LINUX: "-ldl"
+// RUN: %clang -fsanitize=shadow-call-stack %s -### -o %t.o 2>&1 \
+// RUN: -target x86_64-unknown-linux -fuse-ld=ld \
+// RUN: | FileCheck --check-prefix=CHECK-SHADOWCALLSTACK-LINUX-X86-64 %s
+// CHECK-SHADOWCALLSTACK-LINUX-X86-64-NOT: error:
+
+// RUN: %clang -fsanitize=shadow-call-stack %s -### -o %t.o 2>&1 \
+// RUN: -target aarch64-unknown-linux -fuse-ld=ld \
+// RUN: | FileCheck --check-prefix=CHECK-SHADOWCALLSTACK-LINUX-AARCH64 %s
+// CHECK-SHADOWCALLSTACK-LINUX-AARCH64: '-fsanitize=shadow-call-stack' only allowed with '-ffixed-x18'
+
+// RUN: %clang -fsanitize=shadow-call-stack %s -### -o %t.o 2>&1 \
+// RUN: -target aarch64-unknown-linux -fuse-ld=ld -ffixed-x18 \
+// RUN: | FileCheck --check-prefix=CHECK-SHADOWCALLSTACK-LINUX-AARCH64-X18 %s
+// RUN: %clang -fsanitize=shadow-call-stack %s -### -o %t.o 2>&1 \
+// RUN: -target arm64-unknown-ios -fuse-ld=ld \
+// RUN: | FileCheck --check-prefix=CHECK-SHADOWCALLSTACK-LINUX-AARCH64-X18 %s
+// CHECK-SHADOWCALLSTACK-LINUX-AARCH64-X18-NOT: error:
+
+// RUN: %clang -fsanitize=shadow-call-stack %s -### -o %t.o 2>&1 \
+// RUN: -target x86-unknown-linux -fuse-ld=ld \
+// RUN: | FileCheck --check-prefix=CHECK-SHADOWCALLSTACK-LINUX-X86 %s
+// CHECK-SHADOWCALLSTACK-LINUX-X86: error: unsupported option '-fsanitize=shadow-call-stack' for target 'x86-unknown-linux'
+
+// RUN: %clang -fsanitize=shadow-call-stack %s -### -o %t.o 2>&1 \
+// RUN: -fsanitize=safe-stack -target x86_64-unknown-linux -fuse-ld=ld \
+// RUN: | FileCheck --check-prefix=CHECK-SHADOWCALLSTACK-SAFESTACK %s
+// CHECK-SHADOWCALLSTACK-SAFESTACK: error: invalid argument '-fsanitize=shadow-call-stack' not allowed with '-fsanitize=safe-stack'
+
// RUN: %clang -fsanitize=cfi -fsanitize-stats %s -### -o %t.o 2>&1 \
// RUN: -target x86_64-unknown-linux -fuse-ld=ld \
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
// RUN: | FileCheck --check-prefix=CHECK-CFI-STATS-LINUX %s
// CHECK-CFI-STATS-LINUX: "{{.*}}ld{{(.exe)?}}"
-// CHECK-CFI-STATS-LINUX: "-whole-archive" "{{[^"]*}}libclang_rt.stats_client-x86_64.a" "-no-whole-archive"
-// CHECK-CFI-STATS-LINUX-NOT: "-whole-archive"
+// CHECK-CFI-STATS-LINUX: "--whole-archive" "{{[^"]*}}libclang_rt.stats_client-x86_64.a" "--no-whole-archive"
+// CHECK-CFI-STATS-LINUX-NOT: "--whole-archive"
// CHECK-CFI-STATS-LINUX: "{{[^"]*}}libclang_rt.stats-x86_64.a"
// RUN: %clang -fsanitize=cfi -fsanitize-stats %s -### -o %t.o 2>&1 \
// RUN: -target x86_64-apple-darwin -fuse-ld=ld \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
// RUN: | FileCheck --check-prefix=CHECK-CFI-STATS-DARWIN %s
// CHECK-CFI-STATS-DARWIN: "{{.*}}ld{{(.exe)?}}"
@@ -618,6 +651,7 @@
// RUN: -target x86_64-scei-ps4 -fuse-ld=ld \
// RUN: -shared \
// RUN: | FileCheck --check-prefix=CHECK-UBSAN-PS4 %s
+// CHECK-UBSAN-PS4: --dependent-lib=libSceDbgUBSanitizer_stub_weak.a
// CHECK-UBSAN-PS4: "{{.*}}ld{{(.gold)?(.exe)?}}"
// CHECK-UBSAN-PS4: -lSceDbgUBSanitizer_stub_weak
@@ -625,6 +659,7 @@
// RUN: -target x86_64-scei-ps4 -fuse-ld=ld \
// RUN: -shared \
// RUN: | FileCheck --check-prefix=CHECK-ASAN-PS4 %s
+// CHECK-ASAN-PS4: --dependent-lib=libSceDbgAddressSanitizer_stub_weak.a
// CHECK-ASAN-PS4: "{{.*}}ld{{(.gold)?(.exe)?}}"
// CHECK-ASAN-PS4: -lSceDbgAddressSanitizer_stub_weak
@@ -632,6 +667,9 @@
// RUN: -target x86_64-scei-ps4 -fuse-ld=ld \
// RUN: -shared \
// RUN: | FileCheck --check-prefix=CHECK-AUBSAN-PS4 %s
+// CHECK-AUBSAN-PS4-NOT: --dependent-lib=libSceDbgUBSanitizer_stub_weak.a
+// CHECK-AUBSAN-PS4: --dependent-lib=libSceDbgAddressSanitizer_stub_weak.a
+// CHECK-AUBSAN-PS4-NOT: --dependent-lib=libSceDbgUBSanitizer_stub_weak.a
// CHECK-AUBSAN-PS4: "{{.*}}ld{{(.gold)?(.exe)?}}"
// CHECK-AUBSAN-PS4: -lSceDbgAddressSanitizer_stub_weak
@@ -651,11 +689,20 @@
// RUN: | FileCheck --check-prefix=CHECK-SCUDO-LINUX %s
// CHECK-SCUDO-LINUX: "{{.*}}ld{{(.exe)?}}"
// CHECK-SCUDO-LINUX: "-pie"
-// CHECK-SCUDO-LINUX: "-whole-archive" "{{.*}}libclang_rt.scudo-i386.a" "-no-whole-archive"
+// CHECK-SCUDO-LINUX: "--whole-archive" "{{.*}}libclang_rt.scudo-i386.a" "--no-whole-archive"
// CHECK-SCUDO-LINUX-NOT: "-lstdc++"
// CHECK-SCUDO-LINUX: "-lpthread"
// CHECK-SCUDO-LINUX: "-ldl"
+// RUN: %clang -fsanitize=scudo -fsanitize-minimal-runtime %s -### -o %t.o 2>&1 \
+// RUN: -target i386-unknown-linux -fuse-ld=ld \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-SCUDO-MINIMAL-LINUX %s
+// CHECK-SCUDO-MINIMAL-LINUX: "{{.*}}ld{{(.exe)?}}"
+// CHECK-SCUDO-MINIMAL-LINUX: "-pie"
+// CHECK-SCUDO-MINIMAL-LINUX: "--whole-archive" "{{.*}}libclang_rt.scudo_minimal-i386.a" "--no-whole-archive"
+// CHECK-SCUDO-MINIMAL-LINUX: "-lpthread"
+
// RUN: %clang -no-canonical-prefixes %s -### -o %t.so -shared 2>&1 \
// RUN: -target i386-unknown-linux -fuse-ld=ld -fsanitize=scudo -shared-libsan \
// RUN: -resource-dir=%S/Inputs/resource_dir \
@@ -669,7 +716,7 @@
// CHECK-SCUDO-SHARED-LINUX-NOT: "-lpthread"
// CHECK-SCUDO-SHARED-LINUX-NOT: "-lrt"
// CHECK-SCUDO-SHARED-LINUX-NOT: "-ldl"
-// CHECK-SCUDO-SHARED-LINUX-NOT: "-export-dynamic"
+// CHECK-SCUDO-SHARED-LINUX-NOT: "--export-dynamic"
// CHECK-SCUDO-SHARED-LINUX-NOT: "--dynamic-list"
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
@@ -691,59 +738,106 @@
// RUN: | FileCheck --check-prefix=CHECK-SCUDO-ANDROID-STATIC %s
// CHECK-SCUDO-ANDROID-STATIC: "{{(.*[^.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
// CHECK-SCUDO-ANDROID-STATIC: "-pie"
-// CHECK-SCUDO-ANDROID-STATIC: "-whole-archive" "{{.*}}libclang_rt.scudo-arm-android.a" "-no-whole-archive"
+// CHECK-SCUDO-ANDROID-STATIC: "--whole-archive" "{{.*}}libclang_rt.scudo-arm-android.a" "--no-whole-archive"
// CHECK-SCUDO-ANDROID-STATIC-NOT: "-lstdc++"
-// CHECK-SCUDO-ANDROID-STATIC: "-lpthread"
+// CHECK-SCUDO-ANDROID-STATIC-NOT: "-lpthread"
+// CHECK-SCUDO-ANDROID-STATIC-NOT: "-lrt"
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -target aarch64-unknown-linux -fuse-ld=ld -fsanitize=hwaddress \
+// RUN: -target x86_64-unknown-linux -fuse-ld=ld -fsanitize=hwaddress \
// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
-// RUN: | FileCheck --check-prefix=CHECK-HWASAN-LINUX %s
+// RUN: | FileCheck --check-prefix=CHECK-HWASAN-X86-64-LINUX %s
//
-// CHECK-HWASAN-LINUX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
-// CHECK-HWASAN-LINUX-NOT: "-lc"
-// CHECK-HWASAN-LINUX: libclang_rt.hwasan-aarch64.a"
-// CHECK-HWASAN-LINUX-NOT: "-export-dynamic"
-// CHECK-HWASAN-LINUX: "--dynamic-list={{.*}}libclang_rt.hwasan-aarch64.a.syms"
-// CHECK-HWASAN-LINUX-NOT: "-export-dynamic"
-// CHECK-HWASAN-LINUX: "-lpthread"
-// CHECK-HWASAN-LINUX: "-lrt"
-// CHECK-HWASAN-LINUX: "-ldl"
+// CHECK-HWASAN-X86-64-LINUX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
+// CHECK-HWASAN-X86-64-LINUX: "-pie"
+// CHECK-HWASAN-X86-64-LINUX-NOT: "-lc"
+// CHECK-HWASAN-X86-64-LINUX: libclang_rt.hwasan-x86_64.a"
+// CHECK-HWASAN-X86-64-LINUX-NOT: "--export-dynamic"
+// CHECK-HWASAN-X86-64-LINUX: "--dynamic-list={{.*}}libclang_rt.hwasan-x86_64.a.syms"
+// CHECK-HWASAN-X86-64-LINUX-NOT: "--export-dynamic"
+// CHECK-HWASAN-X86-64-LINUX: "-lpthread"
+// CHECK-HWASAN-X86-64-LINUX: "-lrt"
+// CHECK-HWASAN-X86-64-LINUX: "-ldl"
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -target aarch64-unknown-linux -fuse-ld=ld -fsanitize=hwaddress -shared-libsan \
-// RUN: -resource-dir=%S/Inputs/resource_dir \
+// RUN: -target x86_64-unknown-linux -fuse-ld=ld -fsanitize=hwaddress \
+// RUN: -shared-libsan -resource-dir=%S/Inputs/resource_dir \
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
-// RUN: | FileCheck --check-prefix=CHECK-SHARED-HWASAN-LINUX %s
+// RUN: | FileCheck --check-prefix=CHECK-SHARED-HWASAN-X86-64-LINUX %s
+//
+// CHECK-SHARED-HWASAN-X86-64-LINUX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
+// CHECK-SHARED-HWASAN-X86-64-LINUX: "-pie"
+// CHECK-SHARED-HWASAN-X86-64-LINUX-NOT: "-lc"
+// CHECK-SHARED-HWASAN-X86-64-LINUX: libclang_rt.hwasan-x86_64.so"
+// CHECK-SHARED-HWASAN-X86-64-LINUX-NOT: "-lpthread"
+// CHECK-SHARED-HWASAN-X86-64-LINUX-NOT: "-lrt"
+// CHECK-SHARED-HWASAN-X86-64-LINUX-NOT: "-ldl"
+// CHECK-SHARED-HWASAN-X86-64-LINUX-NOT: "--export-dynamic"
+// CHECK-SHARED-HWASAN-X86-64-LINUX-NOT: "--dynamic-list"
+
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.so -shared 2>&1 \
+// RUN: -target x86_64-unknown-linux -fuse-ld=ld -fsanitize=hwaddress \
+// RUN: -shared-libsan -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-DSO-SHARED-HWASAN-X86-64-LINUX %s
+//
+// CHECK-DSO-SHARED-HWASAN-X86-64-LINUX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
+// CHECK-DSO_SHARED-HWASAN-X86-64-LINUX: "-pie"
+// CHECK-DSO-SHARED-HWASAN-X86-64-LINUX-NOT: "-lc"
+// CHECK-DSO-SHARED-HWASAN-X86-64-LINUX: libclang_rt.hwasan-x86_64.so"
+// CHECK-DSO-SHARED-HWASAN-X86-64-LINUX-NOT: "-lpthread"
+// CHECK-DSO-SHARED-HWASAN-X86-64-LINUX-NOT: "-lrt"
+// CHECK-DSO-SHARED-HWASAN-X86-64-LINUX-NOT: "-ldl"
+// CHECK-DSO-SHARED-HWASAN-X86-64-LINUX-NOT: "--export-dynamic"
+// CHECK-DSO-SHARED-HWASAN-X86-64-LINUX-NOT: "--dynamic-list"
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN: -target aarch64-unknown-linux -fuse-ld=ld -fsanitize=hwaddress \
-// RUN: -shared-libsan \
// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
-// RUN: | FileCheck --check-prefix=CHECK-SHARED-HWASAN-LINUX %s
+// RUN: | FileCheck --check-prefix=CHECK-HWASAN-AARCH64-LINUX %s
//
-// CHECK-SHARED-HWASAN-LINUX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
-// CHECK-SHARED-HWASAN-LINUX-NOT: "-lc"
-// CHECK-SHARED-HWASAN-LINUX: libclang_rt.hwasan-aarch64.so"
-// CHECK-SHARED-HWASAN-LINUX-NOT: "-lpthread"
-// CHECK-SHARED-HWASAN-LINUX-NOT: "-lrt"
-// CHECK-SHARED-HWASAN-LINUX-NOT: "-ldl"
-// CHECK-SHARED-HWASAN-LINUX-NOT: "-export-dynamic"
-// CHECK-SHARED-HWASAN-LINUX-NOT: "--dynamic-list"
+// CHECK-HWASAN-AARCH64-LINUX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
+// CHECK-HWASAN-AARCH64-LINUX: "-pie"
+// CHECK-HWASAN-AARCH64-LINUX-NOT: "-lc"
+// CHECK-HWASAN-AARCH64-LINUX: libclang_rt.hwasan-aarch64.a"
+// CHECK-HWASAN-AARCH64-LINUX-NOT: "--export-dynamic"
+// CHECK-HWASAN-AARCH64-LINUX: "--dynamic-list={{.*}}libclang_rt.hwasan-aarch64.a.syms"
+// CHECK-HWASAN-AARCH64-LINUX-NOT: "--export-dynamic"
+// CHECK-HWASAN-AARCH64-LINUX: "-lpthread"
+// CHECK-HWASAN-AARCH64-LINUX: "-lrt"
+// CHECK-HWASAN-AARCH64-LINUX: "-ldl"
-// RUN: %clang -no-canonical-prefixes %s -### -o %t.so -shared 2>&1 \
-// RUN: -target aarch64-unknown-linux -fuse-ld=ld -fsanitize=hwaddress -shared-libsan \
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: -target aarch64-unknown-linux -fuse-ld=ld -fsanitize=hwaddress \
+// RUN: -shared-libsan \
// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
-// RUN: | FileCheck --check-prefix=CHECK-DSO-SHARED-HWASAN-LINUX %s
+// RUN: | FileCheck --check-prefix=CHECK-SHARED-HWASAN-AARCH64-LINUX %s
//
-// CHECK-DSO-SHARED-HWASAN-LINUX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
-// CHECK-DSO-SHARED-HWASAN-LINUX-NOT: "-lc"
-// CHECK-DSO-SHARED-HWASAN-LINUX: libclang_rt.hwasan-aarch64.so"
-// CHECK-DSO-SHARED-HWASAN-LINUX-NOT: "-lpthread"
-// CHECK-DSO-SHARED-HWASAN-LINUX-NOT: "-lrt"
-// CHECK-DSO-SHARED-HWASAN-LINUX-NOT: "-ldl"
-// CHECK-DSO-SHARED-HWASAN-LINUX-NOT: "-export-dynamic"
-// CHECK-DSO-SHARED-HWASAN-LINUX-NOT: "--dynamic-list"
+// CHECK-SHARED-HWASAN-AARCH64-LINUX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
+// CHECK-SHARED-HWASAN-AARCH64-LINUX: "-pie"
+// CHECK-SHARED-HWASAN-AARCH64-LINUX-NOT: "-lc"
+// CHECK-SHARED-HWASAN-AARCH64-LINUX: libclang_rt.hwasan-aarch64.so"
+// CHECK-SHARED-HWASAN-AARCH64-LINUX-NOT: "-lpthread"
+// CHECK-SHARED-HWASAN-AARCH64-LINUX-NOT: "-lrt"
+// CHECK-SHARED-HWASAN-AARCH64-LINUX-NOT: "-ldl"
+// CHECK-SHARED-HWASAN-AARCH64-LINUX-NOT: "--export-dynamic"
+// CHECK-SHARED-HWASAN-AARCH64-LINUX-NOT: "--dynamic-list"
+
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.so -shared 2>&1 \
+// RUN: -target aarch64-unknown-linux -fuse-ld=ld -fsanitize=hwaddress \
+// RUN: -shared-libsan -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-DSO-SHARED-HWASAN-AARCH64-LINUX %s
+//
+// CHECK-DSO-SHARED-HWASAN-AARCH64-LINUX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
+// CHECK-DSO_SHARED-HWASAN-AARCH64-LINUX: "-pie"
+// CHECK-DSO-SHARED-HWASAN-AARCH64-LINUX-NOT: "-lc"
+// CHECK-DSO-SHARED-HWASAN-AARCH64-LINUX: libclang_rt.hwasan-aarch64.so"
+// CHECK-DSO-SHARED-HWASAN-AARCH64-LINUX-NOT: "-lpthread"
+// CHECK-DSO-SHARED-HWASAN-AARCH64-LINUX-NOT: "-lrt"
+// CHECK-DSO-SHARED-HWASAN-AARCH64-LINUX-NOT: "-ldl"
+// CHECK-DSO-SHARED-HWASAN-AARCH64-LINUX-NOT: "--export-dynamic"
+// CHECK-DSO-SHARED-HWASAN-AARCH64-LINUX-NOT: "--dynamic-list"
diff --git a/test/Driver/save-stats.c b/test/Driver/save-stats.c
index 5c21544ce31f..d70220331ecb 100644
--- a/test/Driver/save-stats.c
+++ b/test/Driver/save-stats.c
@@ -18,3 +18,11 @@
// RUN: %clang -target x86_64-apple-darwin -save-stats=bla -c %s -### 2>&1 | FileCheck %s -check-prefix=CHECK-INVALID
// CHECK-INVALID: invalid value 'bla' in '-save-stats=bla'
+
+// RUN: %clang -target x86_64-linux-unknown -save-stats -flto -o obj/dir/save-stats.exe %s -### 2>&1 | FileCheck %s -check-prefix=CHECK-LTO
+// CHECK-LTO: "-stats-file=save-stats.stats"
+// CHECK-LTO: "-o" "obj/dir{{/|\\\\}}save-stats.exe"
+// CHECK-LTO: "-plugin-opt=stats-file=save-stats.stats"
+
+// RUN: %clang -target x86_64-linux-unknown -save-stats=obj -flto -o obj/dir/save-stats.exe %s -### 2>&1 | FileCheck %s -check-prefix=CHECK-LTO-OBJ
+// CHECK-LTO-OBJ: "-plugin-opt=stats-file=obj/dir{{/|\\\\}}save-stats.stats"
diff --git a/test/Driver/solaris-header-search.cpp b/test/Driver/solaris-header-search.cpp
index 667b2c05d438..d5c3c0dd7468 100644
--- a/test/Driver/solaris-header-search.cpp
+++ b/test/Driver/solaris-header-search.cpp
@@ -1,11 +1,41 @@
-// Test that the C++ headers are found.
+// Test that the C++ headers are found on Solaris with gcc toolchain detection
//
-// RUN: %clang -no-canonical-prefixes %s -### 2>&1 \
-// RUN: --target=sparc-sun-solaris2.11 \
-// RUN: --gcc-toolchain="" \
-// RUN: --sysroot=%S/Inputs/sparc-sun-solaris2.11 \
-// RUN: | FileCheck %s
-// CHECK: "{{[^"]*}}clang{{[^"]*}}" "-cc1"
-// CHECK: "-internal-isystem" "{{.*}}/usr/include/c++/v1/support/solaris"
-// CHECK: "-internal-isystem" "{{.*}}/usr/gcc/4.8/include/c++/4.8.2"
-// CHECK: "-internal-isystem" "{{.*}}/usr/gcc/4.8/include/c++/4.8.2/sparc-sun-solaris2.11"
+// Sparc, 32bit
+// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \
+// RUN: --target=sparc-sun-solaris2.11 --stdlib=platform \
+// RUN: --sysroot=%S/Inputs/solaris_sparc_tree \
+// RUN: | FileCheck --check-prefix=CHECK_SOLARIS_SPARC %s
+// CHECK_SOLARIS_SPARC: "{{[^"]*}}clang{{[^"]*}}" "-cc1"
+// CHECK_SOLARIS_SPARC-SAME: "-isysroot" "[[SYSROOT:[^"]+]]"
+// CHECK_SOLARIS_SPARC-SAME: "-internal-isystem" "[[SYSROOT]]/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/../../../../include/c++/4.8.2"
+// CHECK_SOLARIS_SPARC-SAME: "-internal-isystem" "[[SYSROOT]]/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/../../../../include/c++/4.8.2/sparc-sun-solaris2.11"
+
+// Sparc, 64bit
+// RUN: %clang -no-canonical-prefixes -m64 %s -### -fsyntax-only 2>&1 \
+// RUN: --target=sparc-sun-solaris2.11 --stdlib=platform \
+// RUN: --sysroot=%S/Inputs/solaris_sparc_tree \
+// RUN: | FileCheck --check-prefix=CHECK_SOLARIS_SPARC64 %s
+// CHECK_SOLARIS_SPARC64: "{{[^"]*}}clang{{[^"]*}}" "-cc1"
+// CHECK_SOLARIS_SPARC64-SAME: "-isysroot" "[[SYSROOT:[^"]+]]"
+// CHECK_SOLARIS_SPARC64-SAME: "-internal-isystem" "[[SYSROOT]]/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/../../../../include/c++/4.8.2"
+// CHECK_SOLARIS_SPARC64-SAME: "-internal-isystem" "[[SYSROOT]]/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/../../../../include/c++/4.8.2/sparc-sun-solaris2.11/sparcv9"
+
+// Intel, 32bit
+// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \
+// RUN: --target=i386-pc-solaris2.11 --stdlib=platform \
+// RUN: --sysroot=%S/Inputs/solaris_x86_tree \
+// RUN: | FileCheck --check-prefix=CHECK_SOLARIS_X86 %s
+// CHECK_SOLARIS_X86: "{{[^"]*}}clang{{[^"]*}}" "-cc1"
+// CHECK_SOLARIS_X86-SAME: "-isysroot" "[[SYSROOT:[^"]+]]"
+// CHECK_SOLARIS_X86-SAME: "-internal-isystem" "{{.*}}/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4/../../../../include/c++/4.9.4"
+// CHECK_SOLARIS_X86-SAME: "-internal-isystem" "{{.*}}/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4/../../../../include/c++/4.9.4/i386-pc-solaris2.11"
+
+// Intel, 64bit
+// RUN: %clang -no-canonical-prefixes -m64 %s -### -fsyntax-only 2>&1 \
+// RUN: --target=i386-pc-solaris2.11 --stdlib=platform \
+// RUN: --sysroot=%S/Inputs/solaris_x86_tree \
+// RUN: | FileCheck --check-prefix=CHECK_SOLARIS_X64 %s
+// CHECK_SOLARIS_X64: "{{[^"]*}}clang{{[^"]*}}" "-cc1"
+// CHECK_SOLARIS_X64-SAME: "-isysroot" "[[SYSROOT:[^"]+]]"
+// CHECK_SOLARIS_X64-SAME: "-internal-isystem" "[[SYSROOT]]/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4/../../../../include/c++/4.9.4"
+// CHECK_SOLARIS_X64-SAME: "-internal-isystem" "[[SYSROOT]]/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4/../../../../include/c++/4.9.4/i386-pc-solaris2.11/amd64"
diff --git a/test/Driver/solaris-ld.c b/test/Driver/solaris-ld.c
index d871b592eb18..2fc5c91272aa 100644
--- a/test/Driver/solaris-ld.c
+++ b/test/Driver/solaris-ld.c
@@ -1,33 +1,110 @@
-// Test ld invocation on Solaris targets.
+// General tests that ld invocations on Solaris targets sane. Note that we use
+// sysroot to make these tests independent of the host system.
-// Check sparc-sun-solaris2.1
+// Check sparc-sun-solaris2.11, 32bit
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN: --target=sparc-sun-solaris2.11 \
// RUN: --gcc-toolchain="" \
-// RUN: --sysroot=%S/Inputs/sparc-sun-solaris2.11 \
-// RUN: | FileCheck %s
-// CHECK: "-cc1" "-triple" "sparc-sun-solaris2.11"
-// CHECK: ld{{.*}}"
-// CHECK: "--dynamic-linker" "{{.*}}/usr/lib/ld.so.1"
-// CHECK: "{{.*}}/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2{{/|\\\\}}crt1.o"
-// CHECK: "{{.*}}/usr/lib/crti.o"
-// CHECK: "{{.*}}/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2{{/|\\\\}}crtbegin.o"
-// CHECK: "{{.*}}/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2{{/|\\\\}}crtend.o"
-// CHECK: "{{.*}}/usr/lib/crtn.o"
-// CHECK "-lc"
-// CHECK "-lgcc_s"
-// CHECK "-lgcc"
-// CHECK "-lm"
+// RUN: --sysroot=%S/Inputs/solaris_sparc_tree \
+// RUN: | FileCheck --check-prefix=CHECK-LD-SPARC32 %s
+// CHECK-LD-SPARC32-NOT: warning:
+// CHECK-LD-SPARC32: {{.*}}clang{{(.exe)?}}" "-cc1" "-triple" "sparc-sun-solaris2.11"
+// CHECK-LD-SPARC32-SAME: "-isysroot" "[[SYSROOT:[^"]+]]"
+// CHECK-LD-SPARC32: "{{.*}}ld{{(.exe)?}}"
+// CHECK-LD-SPARC32-SAME: "--dynamic-linker" "[[SYSROOT]]/usr/lib{{/|\\\\}}ld.so.1"
+// CHECK-LD-SPARC32-SAME: "[[SYSROOT]]/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2{{/|\\\\}}crt1.o"
+// CHECK-LD-SPARC32-SAME: "[[SYSROOT]]/usr/lib{{/|\\\\}}crti.o"
+// CHECK-LD-SPARC32-SAME: "[[SYSROOT]]/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2{{/|\\\\}}crtbegin.o"
+// CHECK-LD-SPARC32-SAME: "-L[[SYSROOT]]/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2"
+// CHECK-LD-SPARC32-SAME: "-L[[SYSROOT]]/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/../../.."
+// CHECK-LD-SPARC32-SAME: "-L[[SYSROOT]]/usr/lib"
+// CHECK-LD-SPARC32-SAME: "-lgcc_s"
+// CHECK-LD-SPARC32-SAME: "-lc"
+// CHECK-LD-SPARC32-SAME: "-lgcc"
+// CHECK-LD-SPARC32-SAME: "-lm"
+// CHECK-LD-SPARC32-SAME: "[[SYSROOT]]/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2{{/|\\\\}}crtend.o"
+// CHECK-LD-SPARC32-SAME: "[[SYSROOT]]/usr/lib{{/|\\\\}}crtn.o"
+
+// Check sparc-sun-solaris2.11, 64bit
+// RUN: %clang -no-canonical-prefixes -m64 %s -### -o %t.o 2>&1 \
+// RUN: --target=sparc-sun-solaris2.11 \
+// RUN: --gcc-toolchain="" \
+// RUN: --sysroot=%S/Inputs/solaris_sparc_tree \
+// RUN: | FileCheck --check-prefix=CHECK-LD-SPARC64 %s
+// CHECK-LD-SPARC64-NOT: warning:
+// CHECK-LD-SPARC64: {{.*}}clang{{(.exe)?}}" "-cc1" "-triple" "sparcv9-sun-solaris2.11"
+// CHECK-LD-SPARC64-SAME: "-isysroot" "[[SYSROOT:[^"]+]]"
+// CHECK-LD-SPARC64: "{{.*}}ld{{(.exe)?}}"
+// CHECK-LD-SPARC64-SAME: "--dynamic-linker" "[[SYSROOT]]/usr/lib/sparcv9{{/|\\\\}}ld.so.1"
+// CHECK-LD-SPARC64-SAME: "[[SYSROOT]]/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/sparcv9{{/|\\\\}}crt1.o"
+// CHECK-LD-SPARC64-SAME: "[[SYSROOT]]/usr/lib/sparcv9{{/|\\\\}}crti.o"
+// CHECK-LD-SPARC64-SAME: "[[SYSROOT]]/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/sparcv9{{/|\\\\}}crtbegin.o"
+// CHECK-LD-SPARC64-SAME: "-L[[SYSROOT]]/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/sparcv9"
+// CHECK-LD-SPARC64-SAME: "-L[[SYSROOT]]/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/../../../sparcv9"
+// CHECK-LD-SPARC64-SAME: "-L[[SYSROOT]]/usr/lib/sparcv9"
+// CHECK-LD-SPARC64-SAME: "-lgcc_s"
+// CHECK-LD-SPARC64-SAME: "-lc"
+// CHECK-LD-SPARC64-SAME: "-lgcc"
+// CHECK-LD-SPARC64-SAME: "-lm"
+// CHECK-LD-SPARC64-SAME: "[[SYSROOT]]/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/sparcv9{{/|\\\\}}crtend.o"
+// CHECK-LD-SPARC64-SAME: "[[SYSROOT]]/usr/lib/sparcv9{{/|\\\\}}crtn.o"
+
+// Check i386-pc-solaris2.11, 32bit
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: --target=i386-pc-solaris2.11 \
+// RUN: --gcc-toolchain="" \
+// RUN: --sysroot=%S/Inputs/solaris_x86_tree \
+// RUN: | FileCheck --check-prefix=CHECK-LD-X32 %s
+// CHECK-LD-X32-NOT: warning:
+// CHECK-LD-X32: {{.*}}clang{{(.exe)?}}" "-cc1" "-triple" "i386-pc-solaris2.11"
+// CHECK-LD-X32-SAME: "-isysroot" "[[SYSROOT:[^"]+]]"
+// CHECK-LD-X32: "{{.*}}ld{{(.exe)?}}"
+// CHECK-LD-X32-SAME: "--dynamic-linker" "[[SYSROOT]]/usr/lib{{/|\\\\}}ld.so.1"
+// CHECK-LD-X32-SAME: "[[SYSROOT]]/usr/lib{{/|\\\\}}crt1.o"
+// CHECK-LD-X32-SAME: "[[SYSROOT]]/usr/lib{{/|\\\\}}crti.o"
+// CHECK-LD-X32-SAME: "[[SYSROOT]]/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4{{/|\\\\}}crtbegin.o"
+// CHECK-LD-X32-SAME: "-L[[SYSROOT]]/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4"
+// CHECK-LD-X32-SAME: "-L[[SYSROOT]]/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4/../../.."
+// CHECK-LD-X32-SAME: "-L[[SYSROOT]]/usr/lib"
+// CHECK-LD-X32-SAME: "-lgcc_s"
+// CHECK-LD-X32-SAME: "-lc"
+// CHECK-LD-X32-SAME: "-lgcc"
+// CHECK-LD-X32-SAME: "-lm"
+// CHECK-LD-X32-SAME: "[[SYSROOT]]/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4{{/|\\\\}}crtend.o"
+// CHECK-LD-X32-SAME: "[[SYSROOT]]/usr/lib{{/|\\\\}}crtn.o"
+
+// Check i386-pc-solaris2.11, 64bit
+// RUN: %clang -no-canonical-prefixes -m64 %s -### -o %t.o 2>&1 \
+// RUN: --target=i386-pc-solaris2.11 \
+// RUN: --gcc-toolchain="" \
+// RUN: --sysroot=%S/Inputs/solaris_x86_tree \
+// RUN: | FileCheck --check-prefix=CHECK-LD-X64 %s
+// CHECK-LD-X64-NOT: warning:
+// CHECK-LD-X64: {{.*}}clang{{(.exe)?}}" "-cc1" "-triple" "x86_64-pc-solaris2.11"
+// CHECK-LD-X64-SAME: "-isysroot" "[[SYSROOT:[^"]+]]"
+// CHECK-LD-X64: "{{.*}}ld{{(.exe)?}}"
+// CHECK-LD-X64-SAME: "--dynamic-linker" "[[SYSROOT]]/usr/lib/amd64{{/|\\\\}}ld.so.1"
+// CHECK-LD-X64-SAME: "[[SYSROOT]]/usr/lib/amd64{{/|\\\\}}crt1.o"
+// CHECK-LD-X64-SAME: "[[SYSROOT]]/usr/lib/amd64{{/|\\\\}}crti.o"
+// CHECK-LD-X64-SAME: "[[SYSROOT]]/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4/amd64{{/|\\\\}}crtbegin.o"
+// CHECK-LD-X64-SAME: "-L[[SYSROOT]]/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4/amd64"
+// CHECK-LD-X64-SAME: "-L[[SYSROOT]]/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4/../../../amd64"
+// CHECK-LD-X64-SAME: "-L[[SYSROOT]]/usr/lib/amd64"
+// CHECK-LD-X64-SAME: "-lgcc_s"
+// CHECK-LD-X64-SAME: "-lc"
+// CHECK-LD-X64-SAME: "-lgcc"
+// CHECK-LD-X64-SAME: "-lm"
+// CHECK-LD-X64-SAME: "[[SYSROOT]]/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4/amd64{{/|\\\\}}crtend.o"
+// CHECK-LD-X64-SAME: "[[SYSROOT]]/usr/lib/amd64{{/|\\\\}}crtn.o"
// Check the right -l flags are present with -shared
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o -shared 2>&1 \
// RUN: --target=sparc-sun-solaris2.11 \
// RUN: --gcc-toolchain="" \
-// RUN: --sysroot=%S/Inputs/sparc-sun-solaris2.11 \
-// RUN: | FileCheck --check-prefix=CHECK-SHARED %s
-
-// CHECK-SHARED: ld{{.*}}"
-// CHECK-SHARED "-lc"
-// CHECK-SHARED "-lgcc_s"
-// CHECK-SHARED-NOT "-lgcc"
-// CHECK-SHARED-NOT: "-lm"
+// RUN: --sysroot=%S/Inputs/solaris_sparc_tree \
+// RUN: | FileCheck --check-prefix=CHECK-SPARC32-SHARED %s
+// CHECK-SPARC32-SHARED: "{{.*}}ld{{(.exe)?}}"
+// CHECK-SPARC32-SHARED-SAME: "-lgcc_s"
+// CHECK-SPARC32-SHARED-SAME: "-lc"
+// CHECK-SPARC32-SHARED-NOT: "-lgcc"
+// CHECK-SPARC32-SHARED-NOT: "-lm"
diff --git a/test/Driver/sparc-as.c b/test/Driver/sparc-as.c
index 80122cf6dc12..65eeb4da39b4 100644
--- a/test/Driver/sparc-as.c
+++ b/test/Driver/sparc-as.c
@@ -76,6 +76,66 @@
// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=SPARC-V8PLUSD %s
+// RUN: %clang -mcpu=ma2100 -no-canonical-prefixes -target sparc \
+// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
+// RUN: | FileCheck -check-prefix=SPARC-LEON %s
+
+// RUN: %clang -mcpu=ma2150 -no-canonical-prefixes -target sparc \
+// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
+// RUN: | FileCheck -check-prefix=SPARC-LEON %s
+
+// RUN: %clang -mcpu=ma2155 -no-canonical-prefixes -target sparc \
+// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
+// RUN: | FileCheck -check-prefix=SPARC-LEON %s
+
+// RUN: %clang -mcpu=ma2450 -no-canonical-prefixes -target sparc \
+// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
+// RUN: | FileCheck -check-prefix=SPARC-LEON %s
+
+// RUN: %clang -mcpu=ma2455 -no-canonical-prefixes -target sparc \
+// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
+// RUN: | FileCheck -check-prefix=SPARC-LEON %s
+
+// RUN: %clang -mcpu=ma2x5x -no-canonical-prefixes -target sparc \
+// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
+// RUN: | FileCheck -check-prefix=SPARC-LEON %s
+
+// RUN: %clang -mcpu=ma2080 -no-canonical-prefixes -target sparc \
+// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
+// RUN: | FileCheck -check-prefix=SPARC-LEON %s
+
+// RUN: %clang -mcpu=ma2085 -no-canonical-prefixes -target sparc \
+// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
+// RUN: | FileCheck -check-prefix=SPARC-LEON %s
+
+// RUN: %clang -mcpu=ma2480 -no-canonical-prefixes -target sparc \
+// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
+// RUN: | FileCheck -check-prefix=SPARC-LEON %s
+
+// RUN: %clang -mcpu=ma2485 -no-canonical-prefixes -target sparc \
+// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
+// RUN: | FileCheck -check-prefix=SPARC-LEON %s
+
+// RUN: %clang -mcpu=ma2x8x -no-canonical-prefixes -target sparc \
+// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
+// RUN: | FileCheck -check-prefix=SPARC-LEON %s
+
+// RUN: %clang -mcpu=myriad2 -no-canonical-prefixes -target sparc \
+// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
+// RUN: | FileCheck -check-prefix=SPARC-LEON %s
+
+// RUN: %clang -mcpu=myriad2.1 -no-canonical-prefixes -target sparc \
+// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
+// RUN: | FileCheck -check-prefix=SPARC-LEON %s
+
+// RUN: %clang -mcpu=myriad2.2 -no-canonical-prefixes -target sparc \
+// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
+// RUN: | FileCheck -check-prefix=SPARC-LEON %s
+
+// RUN: %clang -mcpu=myriad2.3 -no-canonical-prefixes -target sparc \
+// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
+// RUN: | FileCheck -check-prefix=SPARC-LEON %s
+
// RUN: %clang -mcpu=leon2 -no-canonical-prefixes -target sparc \
// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=SPARC-V8 %s
@@ -90,7 +150,7 @@
// RUN: %clang -mcpu=leon3 -no-canonical-prefixes -target sparc \
// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
-// RUN: | FileCheck -check-prefix=SPARC-V8 %s
+// RUN: | FileCheck -check-prefix=SPARC-LEON %s
// RUN: %clang -mcpu=ut699 -no-canonical-prefixes -target sparc \
// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
@@ -98,18 +158,19 @@
// RUN: %clang -mcpu=gr712rc -no-canonical-prefixes -target sparc \
// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
-// RUN: | FileCheck -check-prefix=SPARC-V8 %s
+// RUN: | FileCheck -check-prefix=SPARC-LEON %s
// RUN: %clang -mcpu=leon4 -no-canonical-prefixes -target sparc \
// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
-// RUN: | FileCheck -check-prefix=SPARC-V8 %s
+// RUN: | FileCheck -check-prefix=SPARC-LEON %s
// RUN: %clang -mcpu=gr740 -no-canonical-prefixes -target sparc \
// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
-// RUN: | FileCheck -check-prefix=SPARC-V8 %s
+// RUN: | FileCheck -check-prefix=SPARC-LEON %s
// SPARC: as{{.*}}" "-32" "-Av8" "-o"
// SPARC-V8: as{{.*}}" "-32" "-Av8" "-o"
+// SPARC-LEON: as{{.*}}" "-32" "-Aleon" "-o"
// SPARC-SPARCLITE: as{{.*}}" "-32" "-Asparclite" "-o"
// SPARC-SPARCLET: as{{.*}}" "-32" "-Asparclet" "-o"
// SPARC-V8PLUS: as{{.*}}" "-32" "-Av8plus" "-o"
diff --git a/test/Driver/split-debug.c b/test/Driver/split-debug.c
index 52f53d3e712e..212c12f5395f 100644
--- a/test/Driver/split-debug.c
+++ b/test/Driver/split-debug.c
@@ -3,8 +3,7 @@
// RUN: %clang -target x86_64-unknown-linux-gnu -gsplit-dwarf -c -### %s 2> %t
// RUN: FileCheck -check-prefix=CHECK-ACTIONS < %t %s
//
-// CHECK-ACTIONS: objcopy{{.*}}--extract-dwo{{.*}}"split-debug.dwo"
-// CHECK-ACTIONS: objcopy{{.*}}--strip-dwo{{.*}}"split-debug.o"
+// CHECK-ACTIONS: "-split-dwarf-file" "split-debug.dwo"
// RUN: %clang -target x86_64-macosx -gsplit-dwarf -c -### %s 2> %t
diff --git a/test/Driver/split-debug.s b/test/Driver/split-debug.s
index 64e8f2fa03d2..6e6f8c5b8043 100644
--- a/test/Driver/split-debug.s
+++ b/test/Driver/split-debug.s
@@ -3,8 +3,7 @@
// RUN: %clang -target x86_64-unknown-linux-gnu -gsplit-dwarf -c -### %s 2> %t
// RUN: FileCheck -check-prefix=CHECK-ACTIONS < %t %s
//
-// CHECK-ACTIONS: objcopy{{.*}}--extract-dwo{{.*}}"split-debug.dwo"
-// CHECK-ACTIONS: objcopy{{.*}}--strip-dwo{{.*}}"split-debug.o"
+// CHECK-ACTIONS: "-split-dwarf-file" "split-debug.dwo"
// RUN: %clang -target x86_64-macosx -gsplit-dwarf -c -### %s 2> %t
diff --git a/test/Driver/stack-arg-probe.c b/test/Driver/stack-arg-probe.c
new file mode 100644
index 000000000000..97d2396dbebe
--- /dev/null
+++ b/test/Driver/stack-arg-probe.c
@@ -0,0 +1,7 @@
+// RUN: %clang -### %s 2>&1 | FileCheck %s -check-prefix=STACKPROBE
+// RUN: %clang -### -mno-stack-arg-probe -mstack-arg-probe %s 2>&1 | FileCheck %s -check-prefix=STACKPROBE
+// RUN: %clang -### -mstack-arg-probe -mno-stack-arg-probe %s 2>&1 | FileCheck %s -check-prefix=NO-STACKPROBE
+// REQUIRES: clang-driver
+
+// NO-STACKPROBE: -mno-stack-arg-probe
+// STACKPROBE-NOT: -mno-stack-arg-probe
diff --git a/test/Driver/stack-size-section.c b/test/Driver/stack-size-section.c
new file mode 100644
index 000000000000..461f0b5c9aee
--- /dev/null
+++ b/test/Driver/stack-size-section.c
@@ -0,0 +1,9 @@
+// RUN: %clang -target x86_64-unknown %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ABSENT
+// RUN: %clang -target x86_64-scei-ps4 -fno-stack-size-section %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ABSENT
+// CHECK-ABSENT-NOT: -fstack-size-section
+
+// RUN: %clang -target x86_64-unknown -fstack-size-section -### 2>&1 | FileCheck %s --check-prefix=CHECK-PRESENT
+// RUN: %clang -target x86_64-scei-ps4 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-PRESENT
+// CHECK-PRESENT: -fstack-size-section
+
+int foo() { return 42; }
diff --git a/test/Driver/target-triple-deployment.c b/test/Driver/target-triple-deployment.c
index 4f5de59e73d8..b59f81a0106f 100644
--- a/test/Driver/target-triple-deployment.c
+++ b/test/Driver/target-triple-deployment.c
@@ -1,5 +1,5 @@
// RUN: touch %t.o
-// RUN: %clang -target x86_64-apple-macosx -### %t.o 2> %t.log
+// RUN: %clang -target x86_64-apple-macosx10.4 -### %t.o 2> %t.log
// RUN: %clang -target x86_64-apple-darwin9 -### %t.o 2>> %t.log
// RUN: %clang -target x86_64-apple-macosx10.7 -### %t.o 2>> %t.log
//
diff --git a/test/Driver/thinlto.cu b/test/Driver/thinlto.cu
new file mode 100644
index 000000000000..c5a76b0cbdfd
--- /dev/null
+++ b/test/Driver/thinlto.cu
@@ -0,0 +1,54 @@
+// REQUIRES: clang-driver
+// REQUIRES: x86-registered-target
+// REQUIRES: nvptx-registered-target
+
+// -flto=thin causes a switch to llvm-bc object files.
+// RUN: %clangxx -ccc-print-phases -nocudainc -nocudalib -c %s -flto=thin 2> %t
+// RUN: FileCheck -check-prefix=CHECK-COMPILE-ACTIONS < %t %s
+//
+// CHECK-COMPILE-ACTIONS: 2: compiler, {1}, ir, (host-cuda)
+// CHECK-COMPILE-ACTIONS-NOT: lto-bc
+// CHECK-COMPILE-ACTIONS: 12: backend, {11}, lto-bc, (host-cuda)
+
+// RUN: %clangxx -ccc-print-phases -nocudainc -nocudalib %s -flto=thin 2> %t
+// RUN: FileCheck -check-prefix=CHECK-COMPILELINK-ACTIONS < %t %s
+//
+// CHECK-COMPILELINK-ACTIONS: 0: input, "{{.*}}thinlto.cu", cuda, (host-cuda)
+// CHECK-COMPILELINK-ACTIONS: 1: preprocessor, {0}, cuda-cpp-output
+// CHECK-COMPILELINK-ACTIONS: 2: compiler, {1}, ir, (host-cuda)
+// CHECK-COMPILELINK-ACTIONS: 3: input, "{{.*}}thinlto.cu", cuda, (device-cuda, sm_20)
+// CHECK-COMPILELINK-ACTIONS: 4: preprocessor, {3}, cuda-cpp-output, (device-cuda, sm_20)
+// CHECK-COMPILELINK-ACTIONS: 5: compiler, {4}, ir, (device-cuda, sm_20)
+// CHECK-COMPILELINK-ACTIONS: 6: backend, {5}, assembler, (device-cuda, sm_20)
+// CHECK-COMPILELINK-ACTIONS: 7: assembler, {6}, object, (device-cuda, sm_20)
+// CHECK-COMPILELINK-ACTIONS: 8: offload, "device-cuda (nvptx{{.*}}-nvidia-cuda:sm_20)" {7}, object
+// CHECK-COMPILELINK-ACTIONS: 9: offload, "device-cuda (nvptx{{.*}}-nvidia-cuda:sm_20)" {6}, assembler
+// CHECK-COMPILELINK-ACTIONS: 10: linker, {8, 9}, cuda-fatbin, (device-cuda)
+// CHECK-COMPILELINK-ACTIONS: 11: offload, "host-cuda {{.*}}" {2}, "device-cuda{{.*}}" {10}, ir
+// CHECK-COMPILELINK-ACTIONS: 12: backend, {11}, lto-bc, (host-cuda)
+// CHECK-COMPILELINK-ACTIONS: 13: linker, {12}, image, (host-cuda)
+
+// -flto=thin should cause link using gold plugin with thinlto option,
+// also confirm that it takes precedence over earlier -fno-lto and -flto=full.
+// RUN: %clangxx -nocudainc -nocudalib \
+// RUN: -target x86_64-unknown-linux -### %s -flto=full -fno-lto -flto=thin 2> %t
+// RUN: FileCheck -check-prefix=CHECK-LINK-THIN-ACTION < %t %s
+//
+// CHECK-LINK-THIN-ACTION: "-plugin" "{{.*}}{{[/\\]}}LLVMgold.{{dll|dylib|so}}"
+// CHECK-LINK-THIN-ACTION: "-plugin-opt=thinlto"
+
+// Check that subsequent -flto=full takes precedence
+// RUN: %clangxx -nocudainc -nocudalib \
+// RUN: -target x86_64-unknown-linux -### %s -flto=thin -flto=full 2> %t
+// RUN: FileCheck -check-prefix=CHECK-LINK-FULL-ACTION < %t %s
+//
+// CHECK-LINK-FULL-ACTION: "-plugin" "{{.*}}{{[/\\]}}LLVMgold.{{dll|dylib|so}}"
+// CHECK-LINK-FULL-ACTION-NOT: "-plugin-opt=thinlto"
+
+// Check that subsequent -fno-lto takes precedence
+// RUN: %clangxx -nocudainc -nocudalib \
+// RUN: -target x86_64-unknown-linux -### %s -flto=thin -fno-lto 2> %t
+// RUN: FileCheck -check-prefix=CHECK-LINK-NOLTO-ACTION < %t %s
+//
+// CHECK-LINK-NOLTO-ACTION-NOT: "-plugin" "{{.*}}{{[/\\]}}LLVMgold.{{dll|dylib|so}}"
+// CHECK-LINK-NOLTO-ACTION-NOT: "-plugin-opt=thinlto"
diff --git a/test/Driver/thinlto_backend.c b/test/Driver/thinlto_backend.c
index 6def5821b6a2..b2b45f57088a 100644
--- a/test/Driver/thinlto_backend.c
+++ b/test/Driver/thinlto_backend.c
@@ -5,6 +5,15 @@
// RUN: %clang -O2 -o %t1.o -x ir %t.o -c -fthinlto-index=%t.thinlto.bc -### 2>&1 | FileCheck %s -check-prefix=CHECK-THINLTOBE-ACTION
// CHECK-THINLTOBE-ACTION: -fthinlto-index=
+// -save-temps should be passed to cc1
+// RUN: %clang -O2 -o %t1.o -x ir %t.o -c -fthinlto-index=%t.thinlto.bc -save-temps -### 2>&1 | FileCheck %s -check-prefix=CHECK-SAVE-TEMPS -check-prefix=CHECK-SAVE-TEMPS-CWD
+// RUN: %clang -O2 -o %t1.o -x ir %t.o -c -fthinlto-index=%t.thinlto.bc -save-temps=cwd -### 2>&1 | FileCheck %s -check-prefix=CHECK-SAVE-TEMPS -check-prefix=CHECK-SAVE-TEMPS-CWD
+// RUN: %clang -O2 -o %t1.o -x ir %t.o -c -fthinlto-index=%t.thinlto.bc -save-temps=obj -### 2>&1 | FileCheck %s -check-prefix=CHECK-SAVE-TEMPS -check-prefix=CHECK-SAVE-TEMPS-OBJ
+// CHECK-SAVE-TEMPS-NOT: -emit-llvm-bc
+// CHECK-SAVE-TEMPS-CWD: -save-temps=cwd
+// CHECK-SAVE-TEMPS-OBJ: -save-temps=obj
+// CHECK-SAVE-TEMPS-NOT: -emit-llvm-bc
+
// Ensure clang driver gives the expected error for incorrect input type
// RUN: not %clang -O2 -o %t1.o %s -c -fthinlto-index=%t.thinlto.bc 2>&1 | FileCheck %s -check-prefix=CHECK-WARNING
// CHECK-WARNING: error: invalid argument '-fthinlto-index={{.*}}' only allowed with '-x ir'
diff --git a/test/Driver/types.c b/test/Driver/types.c
new file mode 100644
index 000000000000..03fe105ec4db
--- /dev/null
+++ b/test/Driver/types.c
@@ -0,0 +1,18 @@
+// Check whether __int128_t and __uint128_t are supported.
+
+// RUN: not %clang -c --target=riscv32-unknown-linux-gnu -fsyntax-only %s \
+// RUN: 2>&1 | FileCheck %s
+
+// RUN: %clang -c --target=riscv32-unknown-linux-gnu -fsyntax-only %s \
+// RUN: -fno-force-enable-int128 -fforce-enable-int128
+
+// RUN: not %clang -c --target=riscv32-unknown-linux-gnu -fsyntax-only %s \
+// RUN: -fforce-enable-int128 -fno-force-enable-int128
+
+void a() {
+ __int128_t s;
+ __uint128_t t;
+}
+
+// CHECK: error: use of undeclared identifier '__int128_t'
+// CHECK: error: use of undeclared identifier '__uint128_t'
diff --git a/test/Driver/unknown-arg.c b/test/Driver/unknown-arg.c
index 9bba74a942eb..36f5c6aabbb0 100644
--- a/test/Driver/unknown-arg.c
+++ b/test/Driver/unknown-arg.c
@@ -1,11 +1,23 @@
-// RUN: not %clang %s -cake-is-lie -%0 -%d -HHHH -munknown-to-clang-option -print-stats -funknown-to-clang-option -### 2>&1 | \
+// RUN: not %clang %s -cake-is-lie -%0 -%d -HHHH -munknown-to-clang-option -print-stats -funknown-to-clang-option -ifoo -imultilib dir -### 2>&1 | \
// RUN: FileCheck %s
+// RUN: %clang %s -imultilib dir -### 2>&1 | \
+// RUN: FileCheck %s --check-prefix=MULTILIB
+// RUN: not %clang %s -stdlibs=foo -hell -version -### 2>&1 | \
+// RUN: FileCheck %s --check-prefix=DID-YOU-MEAN
// RUN: %clang_cl -cake-is-lie -%0 -%d -HHHH -munknown-to-clang-option -print-stats -funknown-to-clang-option -### -c -- %s 2>&1 | \
// RUN: FileCheck %s --check-prefix=CL
+// RUN: %clang_cl -Brepo -### -- %s 2>&1 | \
+// RUN: FileCheck %s --check-prefix=CL-DID-YOU-MEAN
// RUN: not %clang_cl -cake-is-lie -%0 -%d -HHHH -munknown-to-clang-option -print-stats -funknown-to-clang-option -c -Werror=unknown-argument -### -- %s 2>&1 | \
// RUN: FileCheck %s --check-prefix=CL-ERROR
+// RUN: not %clang_cl -helo -Werror=unknown-argument -### -- %s 2>&1 | \
+// RUN: FileCheck %s --check-prefix=CL-ERROR-DID-YOU-MEAN
// RUN: %clang_cl -cake-is-lie -%0 -%d -HHHH -munknown-to-clang-option -print-stats -funknown-to-clang-option -c -Wno-unknown-argument -### -- %s 2>&1 | \
// RUN: FileCheck %s --check-prefix=SILENT
+// RUN: not %clang -cc1as -hell --version -debug-info-macros 2>&1 | \
+// RUN: FileCheck %s --check-prefix=CC1AS-DID-YOU-MEAN
+// RUN: not %clang -cc1asphalt -help 2>&1 | \
+// RUN: FileCheck %s --check-prefix=UNKNOWN-INTEGRATED
// CHECK: error: unknown argument: '-cake-is-lie'
// CHECK: error: unknown argument: '-%0'
@@ -14,6 +26,11 @@
// CHECK: error: unknown argument: '-munknown-to-clang-option'
// CHECK: error: unknown argument: '-print-stats'
// CHECK: error: unknown argument: '-funknown-to-clang-option'
+// CHECK: error: unknown argument: '-ifoo'
+// MULTILIB: warning: argument unused during compilation: '-imultilib dir'
+// DID-YOU-MEAN: error: unknown argument '-stdlibs=foo', did you mean '-stdlib=foo'?
+// DID-YOU-MEAN: error: unknown argument '-hell', did you mean '-help'?
+// DID-YOU-MEAN: error: unknown argument '-version', did you mean '--version'?
// CL: warning: unknown argument ignored in clang-cl: '-cake-is-lie'
// CL: warning: unknown argument ignored in clang-cl: '-%0'
// CL: warning: unknown argument ignored in clang-cl: '-%d'
@@ -21,6 +38,7 @@
// CL: warning: unknown argument ignored in clang-cl: '-munknown-to-clang-option'
// CL: warning: unknown argument ignored in clang-cl: '-print-stats'
// CL: warning: unknown argument ignored in clang-cl: '-funknown-to-clang-option'
+// CL-DID-YOU-MEAN: warning: unknown argument ignored in clang-cl '-Brepo' (did you mean '-Brepro'?)
// CL-ERROR: error: unknown argument ignored in clang-cl: '-cake-is-lie'
// CL-ERROR: error: unknown argument ignored in clang-cl: '-%0'
// CL-ERROR: error: unknown argument ignored in clang-cl: '-%d'
@@ -28,9 +46,12 @@
// CL-ERROR: error: unknown argument ignored in clang-cl: '-munknown-to-clang-option'
// CL-ERROR: error: unknown argument ignored in clang-cl: '-print-stats'
// CL-ERROR: error: unknown argument ignored in clang-cl: '-funknown-to-clang-option'
+// CL-ERROR-DID-YOU-MEAN: error: unknown argument ignored in clang-cl '-helo' (did you mean '-help'?)
// SILENT-NOT: error:
// SILENT-NOT: warning:
-
+// CC1AS-DID-YOU-MEAN: error: unknown argument '-hell', did you mean '-help'?
+// CC1AS-DID-YOU-MEAN: error: unknown argument '--version', did you mean '-version'?
+// UNKNOWN-INTEGRATED: error: unknown integrated tool 'asphalt'. Valid tools include '-cc1' and '-cc1as'.
// RUN: %clang -S %s -o %t.s -Wunknown-to-clang-option 2>&1 | FileCheck --check-prefix=IGNORED %s
diff --git a/test/Driver/unknown-std.cl b/test/Driver/unknown-std.cl
index 71c478afca88..90ee97b77f9c 100644
--- a/test/Driver/unknown-std.cl
+++ b/test/Driver/unknown-std.cl
@@ -10,6 +10,7 @@
// CHECK-NEXT: note: use 'cl1.1' for 'OpenCL 1.1' standard
// CHECK-NEXT: note: use 'cl1.2' for 'OpenCL 1.2' standard
// CHECK-NEXT: note: use 'cl2.0' for 'OpenCL 2.0' standard
+// CHECK-NEXT: note: use 'c++' for 'OpenCL C++ 1.0' standard
// Make sure that no other output is present.
// CHECK-NOT: {{^.+$}}
diff --git a/test/Driver/unsupported-option.c b/test/Driver/unsupported-option.c
new file mode 100644
index 000000000000..39f135e68348
--- /dev/null
+++ b/test/Driver/unsupported-option.c
@@ -0,0 +1,7 @@
+// RUN: not %clang %s --hedonism -### 2>&1 | \
+// RUN: FileCheck %s
+// RUN: not %clang %s --hell -### 2>&1 | \
+// RUN: FileCheck %s --check-prefix=DID-YOU-MEAN
+
+// CHECK: error: unsupported option '--hedonism'
+// DID-YOU-MEAN: error: unsupported option '--hell', did you mean '--help'?
diff --git a/test/Driver/wasm-toolchain.c b/test/Driver/wasm-toolchain.c
index e9862f0b7d8d..b1f5f48f874d 100644
--- a/test/Driver/wasm-toolchain.c
+++ b/test/Driver/wasm-toolchain.c
@@ -1,21 +1,8 @@
// A basic clang -cc1 command-line. WebAssembly is somewhat special in
-// enabling -ffunction-sections, -fdata-sections, and -fvisibility=hidden by
-// default.
+// enabling -fvisibility=hidden by default.
// RUN: %clang %s -### -no-canonical-prefixes -target wasm32-unknown-unknown 2>&1 | FileCheck -check-prefix=CC1 %s
-// CC1: clang{{.*}} "-cc1" "-triple" "wasm32-unknown-unknown" {{.*}} "-fvisibility" "hidden" {{.*}} "-ffunction-sections" "-fdata-sections"
-
-// Ditto, but ensure that a user -fno-function-sections disables the
-// default -ffunction-sections.
-
-// RUN: %clang %s -### -target wasm32-unknown-unknown -fno-function-sections 2>&1 | FileCheck -check-prefix=NO_FUNCTION_SECTIONS %s
-// NO_FUNCTION_SECTIONS-NOT: function-sections
-
-// Ditto, but ensure that a user -fno-data-sections disables the
-// default -fdata-sections.
-
-// RUN: %clang %s -### -target wasm32-unknown-unknown -fno-data-sections 2>&1 | FileCheck -check-prefix=NO_DATA_SECTIONS %s
-// NO_DATA_SECTIONS-NOT: data-sections
+// CC1: clang{{.*}} "-cc1" "-triple" "wasm32-unknown-unknown" {{.*}} "-fvisibility" "hidden" {{.*}}
// Ditto, but ensure that a user -fvisibility=default disables the default
// -fvisibility=hidden.
@@ -27,10 +14,10 @@
// RUN: %clang -### -no-canonical-prefixes -target wasm32-unknown-unknown --sysroot=/foo %s 2>&1 | FileCheck -check-prefix=LINK %s
// LINK: clang{{.*}}" "-cc1" {{.*}} "-o" "[[temp:[^"]*]]"
-// LINK: lld{{.*}}" "-flavor" "wasm" "-L/foo/lib" "crt1.o" "[[temp]]" "-allow-undefined-file" "wasm.syms" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out"
+// LINK: lld{{.*}}" "-flavor" "wasm" "-L/foo/lib" "crt1.o" "[[temp]]" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out"
// A basic C link command-line with optimization.
// RUN: %clang -### -O2 -no-canonical-prefixes -target wasm32-unknown-unknown --sysroot=/foo %s 2>&1 | FileCheck -check-prefix=LINK_OPT %s
// LINK_OPT: clang{{.*}}" "-cc1" {{.*}} "-o" "[[temp:[^"]*]]"
-// LINK_OPT: lld{{.*}}" "-flavor" "wasm" "-L/foo/lib" "crt1.o" "[[temp]]" "-allow-undefined-file" "wasm.syms" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out"
+// LINK_OPT: lld{{.*}}" "-flavor" "wasm" "-L/foo/lib" "crt1.o" "[[temp]]" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out"
diff --git a/test/Driver/wasm-toolchain.cpp b/test/Driver/wasm-toolchain.cpp
new file mode 100644
index 000000000000..ea3aa313985c
--- /dev/null
+++ b/test/Driver/wasm-toolchain.cpp
@@ -0,0 +1,23 @@
+// A basic clang -cc1 command-line. WebAssembly is somewhat special in
+// enabling -fvisibility=hidden by default.
+
+// RUN: %clangxx %s -### -no-canonical-prefixes -target wasm32-unknown-unknown 2>&1 | FileCheck -check-prefix=CC1 %s
+// CC1: clang{{.*}} "-cc1" "-triple" "wasm32-unknown-unknown" {{.*}} "-fvisibility" "hidden" {{.*}}
+
+// Ditto, but ensure that a user -fvisibility=default disables the default
+// -fvisibility=hidden.
+
+// RUN: %clangxx %s -### -target wasm32-unknown-unknown -fvisibility=default 2>&1 | FileCheck -check-prefix=FVISIBILITY_DEFAULT %s
+// FVISIBILITY_DEFAULT-NOT: hidden
+
+// A basic C++ link command-line.
+
+// RUN: %clangxx -### -no-canonical-prefixes -target wasm32-unknown-unknown --sysroot=/foo --stdlib=c++ %s 2>&1 | FileCheck -check-prefix=LINK %s
+// LINK: clang{{.*}}" "-cc1" {{.*}} "-o" "[[temp:[^"]*]]"
+// LINK: lld{{.*}}" "-flavor" "wasm" "-L/foo/lib" "crt1.o" "[[temp]]" "-lc++" "-lc++abi" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out"
+
+// A basic C++ link command-line with optimization.
+
+// RUN: %clangxx -### -O2 -no-canonical-prefixes -target wasm32-unknown-unknown --sysroot=/foo %s --stdlib=c++ 2>&1 | FileCheck -check-prefix=LINK_OPT %s
+// LINK_OPT: clang{{.*}}" "-cc1" {{.*}} "-o" "[[temp:[^"]*]]"
+// LINK_OPT: lld{{.*}}" "-flavor" "wasm" "-L/foo/lib" "crt1.o" "[[temp]]" "-lc++" "-lc++abi" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out"
diff --git a/test/Driver/windows-cross.c b/test/Driver/windows-cross.c
index 4b52e99cee34..d96b0283a90e 100644
--- a/test/Driver/windows-cross.c
+++ b/test/Driver/windows-cross.c
@@ -3,6 +3,11 @@
// CHECK-BASIC-LIBCXX: armv7-windows-itanium-ld" "--sysroot={{.*}}/Inputs/Windows/ARM/8.1" "-m" "thumb2pe" "-Bdynamic" "--entry" "mainCRTStartup" "--allow-multiple-definition" "-o" "{{[^"]*}}" "{{[^"]*}}.o" "-lmsvcrt"
+// RUN: %clang -### -target armv7-windows-itanium --sysroot %S/Inputs/Windows/ARM/8.1 -B %S/Inputs/Windows/ARM/8.1/usr/bin -fuse-ld=ld -stdlib=libstdc++ -rtlib=compiler-rt -static -o /dev/null %s 2>&1 \
+// RUN: | FileCheck %s --check-prefix CHECK-STATIC
+
+// CHECK-STATIC: armv7-windows-itanium-ld" "--sysroot={{.*}}/Inputs/Windows/ARM/8.1" "-m" "thumb2pe" "-Bstatic" "--entry" "mainCRTStartup" "--allow-multiple-definition" "-o" "{{[^"]*}}" "{{[^"]*}}.o" "-lmsvcrt"
+
// RUN: %clang -### -target armv7-windows-itanium --sysroot %s/Inputs/Windows/ARM/8.1 -B %S/Inputs/Windows/ARM/8.1/usr/bin -fuse-ld=ld -rtlib=compiler-rt -stdlib=libstdc++ -o /dev/null %s 2>&1 \
// RUN: | FileCheck %s --check-prefix CHECK-RTLIB
@@ -23,6 +28,11 @@
// CHECK-SHARED: armv7-windows-itanium-ld" "--sysroot={{.*}}/Inputs/Windows/ARM/8.1" "-m" "thumb2pe" "-shared" "-Bdynamic" "--enable-auto-image-base" "--entry" "_DllMainCRTStartup" "--allow-multiple-definition" "-o" "shared.dll" "--out-implib" "shared.lib" "{{.*}}.o" "-lmsvcrt" "{{.*[\\/]}}clang_rt.builtins-arm.lib"
+// RUN: %clang -### -target armv7-windows-itanium --sysroot %S/Inputs/Windows/ARM/8.1 -B %S/Inputs/Windows/ARM/8.1/usr/bin -fuse-ld=ld -shared -rtlib=compiler-rt -stdlib=libc++ -static -o shared.dll %s 2>&1 \
+// RUN: | FileCheck %s --check-prefix CHECK-SHARED-STATIC
+
+// CHECK-SHARED-STATIC: armv7-windows-itanium-ld" "--sysroot={{.*}}/Inputs/Windows/ARM/8.1" "-m" "thumb2pe" "-shared" "-Bstatic" "--enable-auto-image-base" "--entry" "_DllMainCRTStartup" "--allow-multiple-definition" "-o" "shared.dll" "--out-implib" "shared.lib" "{{.*}}.o" "-lmsvcrt" "{{.*[\\/]}}clang_rt.builtins-arm.lib"
+
// RUN: %clang -### -target armv7-windows-itanium --sysroot %s/Inputs/Windows/ARM/8.1 -B %S/Inputs/Windows/ARM/8.1/usr/bin -fuse-ld=ld -shared -rtlib=compiler-rt -stdlib=libc++ -nostartfiles -o shared.dll %s 2>&1 \
// RUN: | FileCheck %s --check-prefix CHECK-NOSTARTFILES
diff --git a/test/Driver/windows-exceptions.cpp b/test/Driver/windows-exceptions.cpp
new file mode 100644
index 000000000000..8bce3b8dd82f
--- /dev/null
+++ b/test/Driver/windows-exceptions.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang -target i686-windows-msvc -c %s -### 2>&1 | FileCheck -check-prefix=MSVC %s
+// RUN: %clang -target x86_64-windows-msvc -c %s -### 2>&1 | FileCheck -check-prefix=MSVC %s
+// RUN: %clang -target i686-windows-gnu -c %s -### 2>&1 | FileCheck -check-prefix=MINGW-DWARF %s
+// RUN: %clang -target x86_64-windows-gnu -c %s -### 2>&1 | FileCheck -check-prefix=MINGW-SEH %s
+
+MSVC-NOT: -fdwarf-exceptions
+MSVC-NOT: -fseh-exceptions
+MINGW-DWARF: -fdwarf-exceptions
+MINGW-SEH: -fseh-exceptions
diff --git a/test/Driver/woa-restrict-it.c b/test/Driver/woa-restrict-it.c
index c046991ae132..f9e157b262bb 100644
--- a/test/Driver/woa-restrict-it.c
+++ b/test/Driver/woa-restrict-it.c
@@ -1,4 +1,4 @@
// RUN: %clang -target armv7-windows -### %s 2>&1 | FileCheck %s
-// CHECK: "-backend-option" "-arm-restrict-it"
+// CHECK: "-mllvm" "-arm-restrict-it"
diff --git a/test/Driver/x86-march.c b/test/Driver/x86-march.c
index f08c9dfadc09..d0cd5b61d9bf 100644
--- a/test/Driver/x86-march.c
+++ b/test/Driver/x86-march.c
@@ -60,9 +60,13 @@
// RUN: | FileCheck %s -check-prefix=cannonlake
// cannonlake: "-target-cpu" "cannonlake"
//
-// RUN: %clang -target x86_64-unknown-unknown -c -### %s -march=icelake 2>&1 \
-// RUN: | FileCheck %s -check-prefix=icelake
-// icelake: "-target-cpu" "icelake"
+// RUN: %clang -target x86_64-unknown-unknown -c -### %s -march=icelake-client 2>&1 \
+// RUN: | FileCheck %s -check-prefix=icelake-client
+// icelake-client: "-target-cpu" "icelake-client"
+//
+// RUN: %clang -target x86_64-unknown-unknown -c -### %s -march=icelake-server 2>&1 \
+// RUN: | FileCheck %s -check-prefix=icelake-server
+// icelake-server: "-target-cpu" "icelake-server"
//
// RUN: %clang -target x86_64-unknown-unknown -c -### %s -march=lakemont 2>&1 \
// RUN: | FileCheck %s -check-prefix=lakemont
@@ -76,6 +80,18 @@
// RUN: | FileCheck %s -check-prefix=silvermont
// silvermont: "-target-cpu" "silvermont"
//
+// RUN: %clang -target x86_64-unknown-unknown -c -### %s -march=goldmont 2>&1 \
+// RUN: | FileCheck %s -check-prefix=goldmont
+// goldmont: "-target-cpu" "goldmont"
+//
+// RUN: %clang -target x86_64-unknown-unknown -c -### %s -march=goldmont-plus 2>&1 \
+// RUN: | FileCheck %s -check-prefix=goldmont-plus
+// goldmont-plus: "-target-cpu" "goldmont-plus"
+//
+// RUN: %clang -target x86_64-unknown-unknown -c -### %s -march=tremont 2>&1 \
+// RUN: | FileCheck %s -check-prefix=tremont
+// tremont: "-target-cpu" "tremont"
+//
// RUN: %clang -target x86_64-unknown-unknown -c -### %s -march=k8 2>&1 \
// RUN: | FileCheck %s -check-prefix=k8
// k8: "-target-cpu" "k8"
diff --git a/test/Driver/x86-target-features.c b/test/Driver/x86-target-features.c
index 1289823d1dbe..515ca425c2b5 100644
--- a/test/Driver/x86-target-features.c
+++ b/test/Driver/x86-target-features.c
@@ -60,6 +60,11 @@
// CLWB: "-target-feature" "+clwb"
// NO-CLWB: "-target-feature" "-clwb"
+// RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mwbnoinvd %s -### -o %t.o 2>&1 | FileCheck -check-prefix=WBNOINVD %s
+// RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mno-wbnoinvd %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-WBNOINVD %s
+// WBNOINVD: "-target-feature" "+wbnoinvd"
+// NO-WBNOINVD: "-target-feature" "-wbnoinvd"
+
// RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mmovbe %s -### -o %t.o 2>&1 | FileCheck -check-prefix=MOVBE %s
// RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mno-movbe %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-MOVBE %s
// MOVBE: "-target-feature" "+movbe"
@@ -75,11 +80,6 @@
// CETSS: "-target-feature" "+shstk"
// NO-CETSS: "-target-feature" "-shstk"
-// RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mibt %s -### -o %t.o 2>&1 | FileCheck -check-prefix=CETIBT %s
-// RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mno-ibt %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-CETIBT %s
-// CETIBT: "-target-feature" "+ibt"
-// NO-CETIBT: "-target-feature" "-ibt"
-
// RUN: %clang -target i386-unknown-linux-gnu -march=i386 -msgx %s -### -o %t.o 2>&1 | FileCheck -check-prefix=SGX %s
// RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mno-sgx %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-SGX %s
// SGX: "-target-feature" "+sgx"
@@ -125,3 +125,47 @@
// VBMI2: "-target-feature" "+avx512vbmi2"
// NO-VBMI2: "-target-feature" "-avx512vbmi2"
+// RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mrdpid %s -### -o %t.o 2>&1 | FileCheck -check-prefix=RDPID %s
+// RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mno-rdpid %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-RDPID %s
+// RDPID: "-target-feature" "+rdpid"
+// NO-RDPID: "-target-feature" "-rdpid"
+
+// RUN: %clang -target i386-linux-gnu -mretpoline %s -### -o %t.o 2>&1 | FileCheck -check-prefix=RETPOLINE %s
+// RUN: %clang -target i386-linux-gnu -mno-retpoline %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-RETPOLINE %s
+// RETPOLINE: "-target-feature" "+retpoline"
+// NO-RETPOLINE: "-target-feature" "-retpoline"
+
+// RUN: %clang -target i386-linux-gnu -mretpoline -mretpoline-external-thunk %s -### -o %t.o 2>&1 | FileCheck -check-prefix=RETPOLINE-EXTERNAL-THUNK %s
+// RUN: %clang -target i386-linux-gnu -mretpoline -mno-retpoline-external-thunk %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-RETPOLINE-EXTERNAL-THUNK %s
+// RETPOLINE-EXTERNAL-THUNK: "-target-feature" "+retpoline-external-thunk"
+// NO-RETPOLINE-EXTERNAL-THUNK: "-target-feature" "-retpoline-external-thunk"
+
+// RUN: %clang -target i386-linux-gnu -mwaitpkg %s -### -o %t.o 2>&1 | FileCheck -check-prefix=WAITPKG %s
+// RUN: %clang -target i386-linux-gnu -mno-waitpkg %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-WAITPKG %s
+// WAITPKG: "-target-feature" "+waitpkg"
+// NO-WAITPKG: "-target-feature" "-waitpkg"
+
+// RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mmovdiri %s -### -o %t.o 2>&1 | FileCheck -check-prefix=MOVDIRI %s
+// RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mno-movdiri %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-MOVDIRI %s
+// MOVDIRI: "-target-feature" "+movdiri"
+// NO-MOVDIRI: "-target-feature" "-movdiri"
+
+// RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mmovdir64b %s -### -o %t.o 2>&1 | FileCheck -check-prefix=MOVDIR64B %s
+// RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mno-movdir64b %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-MOVDIR64B %s
+// MOVDIR64B: "-target-feature" "+movdir64b"
+// NO-MOVDIR64B: "-target-feature" "-movdir64b"
+
+// RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mpconfig %s -### -o %t.o 2>&1 | FileCheck -check-prefix=PCONFIG %s
+// RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mno-pconfig %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-PCONFIG %s
+// PCONFIG: "-target-feature" "+pconfig"
+// NO-PCONFIG: "-target-feature" "-pconfig"
+
+// RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mptwrite %s -### -o %t.o 2>&1 | FileCheck -check-prefix=PTWRITE %s
+// RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mno-ptwrite %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-PTWRITE %s
+// PTWRITE: "-target-feature" "+ptwrite"
+// NO-PTWRITE: "-target-feature" "-ptwrite"
+
+// RUN: %clang -target i386-unknown-linux-gnu -march=i386 -minvpcid %s -### -o %t.o 2>&1 | FileCheck -check-prefix=INVPCID %s
+// RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mno-invpcid %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-INVPCID %s
+// INVPCID: "-target-feature" "+invpcid"
+// NO-INVPCID: "-target-feature" "-invpcid"
diff --git a/test/FixIt/fixit-format-ios-nopedantic.m b/test/FixIt/fixit-format-ios-nopedantic.m
new file mode 100644
index 000000000000..0b332376c068
--- /dev/null
+++ b/test/FixIt/fixit-format-ios-nopedantic.m
@@ -0,0 +1,21 @@
+// RUN: cp %s %t
+// RUN: %clang_cc1 -triple thumbv7-apple-ios8.0.0 -fsyntax-only -Wformat -Werror -fixit %t
+
+int printf(const char *restrict, ...);
+typedef unsigned int NSUInteger;
+typedef int NSInteger;
+NSUInteger getNSUInteger();
+NSInteger getNSInteger();
+
+void test() {
+ // For thumbv7-apple-ios8.0.0 the underlying type of ssize_t is long
+ // and the underlying type of size_t is unsigned long.
+
+ printf("test 1: %zu", getNSUInteger());
+
+ printf("test 2: %zu %zu", getNSUInteger(), getNSUInteger());
+
+ printf("test 3: %zd", getNSInteger());
+
+ printf("test 4: %zd %zd", getNSInteger(), getNSInteger());
+}
diff --git a/test/FixIt/fixit-format-ios.m b/test/FixIt/fixit-format-ios.m
index ef6643077869..9c3670d0c849 100644
--- a/test/FixIt/fixit-format-ios.m
+++ b/test/FixIt/fixit-format-ios.m
@@ -1,5 +1,5 @@
// RUN: cp %s %t
-// RUN: %clang_cc1 -triple thumbv7-apple-ios8.0.0 -fsyntax-only -Wformat -fixit %t
+// RUN: %clang_cc1 -triple thumbv7-apple-ios8.0.0 -fsyntax-only -Wformat-pedantic -fixit %t
// RUN: grep -v CHECK %t | FileCheck %s
int printf(const char * restrict, ...);
diff --git a/test/FixIt/fixit-typedef-instead-of-typename-typo.cpp b/test/FixIt/fixit-typedef-instead-of-typename-typo.cpp
new file mode 100644
index 000000000000..9a6f116664a4
--- /dev/null
+++ b/test/FixIt/fixit-typedef-instead-of-typename-typo.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+template <typename A, typedef B> struct Foo {
+ // expected-error@-1 {{expected template parameter}} expected-note@-1 {{did you mean to use 'typename'?}}
+
+ // Check that we are speculatively (with fixit applied) trying to parse the rest.
+
+ // Should not produce error about type since parsing speculatively with fixit applied.
+ B member;
+
+ a // expected-error {{unknown type name 'a'}} // expected-error@+1 {{expected member name or ';' after declaration specifiers}}
+};
+
+
+// RUN: not %clang_cc1 -fsyntax-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+// CHECK: fix-it:{{.*}}:{3:23-3:30}:"typename"
diff --git a/test/FixIt/fixit-unused-lambda-capture.cpp b/test/FixIt/fixit-unused-lambda-capture.cpp
new file mode 100644
index 000000000000..c3120093ed1f
--- /dev/null
+++ b/test/FixIt/fixit-unused-lambda-capture.cpp
@@ -0,0 +1,94 @@
+// RUN: cp %s %t
+// RUN: %clang_cc1 -x c++ -fsyntax-only -Wunused-lambda-capture -Wno-unused-value -std=c++1z -fixit %t
+// RUN: grep -v CHECK %t | FileCheck %s
+
+void test() {
+ int i = 0;
+ int j = 0;
+ int k = 0;
+ int c = 10;
+ int a[c];
+
+ [i,j] { return i; };
+ // CHECK: [i] { return i; };
+ [i,j] { return j; };
+ // CHECK: [j] { return j; };
+ [&i,j] { return j; };
+ // CHECK: [j] { return j; };
+ [j,&i] { return j; };
+ // CHECK: [j] { return j; };
+ [i,j,k] {};
+ // CHECK: [] {};
+ [i,j,k] { return i + j; };
+ // CHECK: [i,j] { return i + j; };
+ [i,j,k] { return j + k; };
+ // CHECK: [j,k] { return j + k; };
+ [i,j,k] { return i + k; };
+ // CHECK: [i,k] { return i + k; };
+ [i,j,k] { return i + j + k; };
+ // CHECK: [i,j,k] { return i + j + k; };
+ [&,i] { return k; };
+ // CHECK: [&] { return k; };
+ [=,&i] { return k; };
+ // CHECK: [=] { return k; };
+ [=,&i,&j] { return j; };
+ // CHECK: [=,&j] { return j; };
+ [=,&i,&j] { return i; };
+ // CHECK: [=,&i] { return i; };
+ [z = i] {};
+ // CHECK: [] {};
+ [i,z = i] { return z; };
+ // CHECK: [z = i] { return z; };
+ [z = i,i] { return z; };
+ // CHECK: [z = i] { return z; };
+ [&a] {};
+ // CHECK: [] {};
+ [i,&a] { return i; };
+ // CHECK: [i] { return i; };
+ [&a,i] { return i; };
+ // CHECK: [i] { return i; };
+
+ #define I_MACRO() i
+ #define I_REF_MACRO() &i
+ [I_MACRO()] {};
+ // CHECK: [] {};
+ [I_MACRO(),j] { return j; };
+ // CHECK: [j] { return j; };
+ [j,I_MACRO()] { return j; };
+ // CHECK: [j] { return j; };
+ [I_REF_MACRO(),j] { return j; };
+ // CHECK: [j] { return j; };
+ [j,I_REF_MACRO()] { return j; };
+ // CHECK: [j] { return j; };
+
+ int n = 0;
+ [z = (n = i),j] {};
+ // CHECK: [z = (n = i)] {};
+ [j,z = (n = i)] {};
+ // CHECK: [z = (n = i)] {};
+}
+
+class ThisTest {
+ void test() {
+ int i = 0;
+
+ [this] {};
+ // CHECK: [] {};
+ [i,this] { return i; };
+ // CHECK: [i] { return i; };
+ [this,i] { return i; };
+ // CHECK: [i] { return i; };
+ [*this] {};
+ // CHECK: [] {};
+ [*this,i] { return i; };
+ // CHECK: [i] { return i; };
+ [i,*this] { return i; };
+ // CHECK: [i] { return i; };
+ [*this] { return this; };
+ // CHECK: [*this] { return this; };
+ [*this,i] { return this; };
+ // CHECK: [*this] { return this; };
+ [i,*this] { return this; };
+ // CHECK: [*this] { return this; };
+ }
+};
diff --git a/test/Format/dump-config-cxx.h b/test/Format/dump-config-cxx.h
new file mode 100644
index 000000000000..57f3c975f96f
--- /dev/null
+++ b/test/Format/dump-config-cxx.h
@@ -0,0 +1,3 @@
+// RUN: clang-format -dump-config %s | FileCheck %s
+
+// CHECK: Language: Cpp
diff --git a/test/Format/dump-config-objc.h b/test/Format/dump-config-objc.h
new file mode 100644
index 000000000000..d33fd366a403
--- /dev/null
+++ b/test/Format/dump-config-objc.h
@@ -0,0 +1,5 @@
+// RUN: clang-format -dump-config %s | FileCheck %s
+
+// CHECK: Language: ObjC
+@interface Foo
+@end
diff --git a/test/Format/lit.local.cfg b/test/Format/lit.local.cfg
new file mode 100644
index 000000000000..abf4e8a65cc3
--- /dev/null
+++ b/test/Format/lit.local.cfg
@@ -0,0 +1,4 @@
+# Suffixes supported by clang-format.
+config.suffixes = ['.c', '.cc', '.cpp', '.h', '.m', '.mm', '.java', '.js',
+ '.ts', '.proto', '.protodevel', '.pb.txt', '.textproto',
+ '.textpb', '.asciipb', '.td']
diff --git a/test/Frontend/Inputs/NextIncludes/rewrite-includes9.h b/test/Frontend/Inputs/NextIncludes/rewrite-includes9.h
new file mode 100644
index 000000000000..b074bd1a4468
--- /dev/null
+++ b/test/Frontend/Inputs/NextIncludes/rewrite-includes9.h
@@ -0,0 +1 @@
+included_line9
diff --git a/test/Frontend/Inputs/SystemHeaderPrefix/with-header-guard.h b/test/Frontend/Inputs/SystemHeaderPrefix/with-header-guard.h
new file mode 100644
index 000000000000..7e4b6697a8a7
--- /dev/null
+++ b/test/Frontend/Inputs/SystemHeaderPrefix/with-header-guard.h
@@ -0,0 +1,3 @@
+#ifndef HEADER_GUARD
+#define HEADER_GUARD
+#endif
diff --git a/test/Frontend/Inputs/resource_dir_with_cfi_blacklist/share/cfi_blacklist.txt b/test/Frontend/Inputs/resource_dir_with_cfi_blacklist/share/cfi_blacklist.txt
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Frontend/Inputs/resource_dir_with_cfi_blacklist/share/cfi_blacklist.txt
diff --git a/test/Frontend/Inputs/rewrite-includes9.h b/test/Frontend/Inputs/rewrite-includes9.h
new file mode 100644
index 000000000000..ebd5ada97056
--- /dev/null
+++ b/test/Frontend/Inputs/rewrite-includes9.h
@@ -0,0 +1,3 @@
+#if __has_include_next(<rewrite-includes9.h>)
+#include_next <rewrite-includes9.h>
+#endif
diff --git a/test/Frontend/ast-codegen.c b/test/Frontend/ast-codegen.c
index 4a3f8a3b79fd..e1140fdd8b27 100644
--- a/test/Frontend/ast-codegen.c
+++ b/test/Frontend/ast-codegen.c
@@ -5,9 +5,9 @@
// CHECK: module asm "foo"
__asm__("foo");
-// CHECK: @g0 = common global i32 0, align 4
+// CHECK: @g0 = common dso_local global i32 0, align 4
int g0;
-// CHECK: define i32 @f0()
+// CHECK: define dso_local i32 @f0()
int f0() {
}
diff --git a/test/Frontend/backend-option.c b/test/Frontend/backend-option.c
deleted file mode 100644
index e17757422e4b..000000000000
--- a/test/Frontend/backend-option.c
+++ /dev/null
@@ -1,4 +0,0 @@
-// RUN: %clang_cc1 %s -emit-llvm -backend-option -time-passes -o - 2>&1 | FileCheck %s
-// RUN: %clang_cc1 %s -emit-llvm -backend-option -time-passes -o - -triple spir-unknown-unknown 2>&1 | FileCheck %s
-// CHECK: Pass execution timing report
-
diff --git a/test/Frontend/compiler-options-dump.cpp b/test/Frontend/compiler-options-dump.cpp
new file mode 100644
index 000000000000..daa8bb18549a
--- /dev/null
+++ b/test/Frontend/compiler-options-dump.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -compiler-options-dump -std=c++03 %s -o - | FileCheck %s --check-prefix=CXX03
+// RUN: %clang_cc1 -compiler-options-dump -std=c++17 %s -o - | FileCheck %s --check-prefix=CXX17
+// RUN: %clang_cc1 -compiler-options-dump -std=c99 -x c %s -o - | FileCheck %s --check-prefix=C99
+
+// CXX03: "features"
+// CXX03: "cxx_auto_type" : false
+// CXX03: "cxx_range_for" : false
+// CXX03: "extensions"
+// CXX03: "cxx_range_for" : true
+
+// CXX17: "features"
+// CXX17: "cxx_auto_type" : true
+// CXX17: "cxx_range_for" : true
+// CXX17: "extensions"
+// CXX17: "cxx_range_for" : true
+
+// C99: "features"
+// C99: "c_alignas" : false
+// C99: "c_atomic" : false
+// C99: "cxx_auto_type" : false
+// C99: "cxx_range_for" : false
+// C99: "extensions"
+// C99: "c_alignas" : true
+// C99: "c_atomic" : true
+// C99: "cxx_range_for" : false
diff --git a/test/Frontend/dependency-gen-extradeps-phony.c b/test/Frontend/dependency-gen-extradeps-phony.c
new file mode 100644
index 000000000000..2d67a959ed85
--- /dev/null
+++ b/test/Frontend/dependency-gen-extradeps-phony.c
@@ -0,0 +1,10 @@
+// RUN: %clang -MM -MP -Xclang -fdepfile-entry=1.extra -Xclang -fdepfile-entry=2.extra -Xclang -fdepfile-entry=2.extra %s | \
+// RUN: FileCheck %s --implicit-check-not=.c:
+//
+// Verify that phony targets are only created for the extra dependency files,
+// and not the input file.
+
+// CHECK: dependency-gen-extradeps-phony.o: 1.extra 2.extra \
+// CHECK-NEXT: dependency-gen-extradeps-phony.c
+// CHECK: 1.extra:
+// CHECK: 2.extra:
diff --git a/test/Frontend/dependency-gen-symlink.c b/test/Frontend/dependency-gen-symlink.c
new file mode 100644
index 000000000000..2fa339ad2abf
--- /dev/null
+++ b/test/Frontend/dependency-gen-symlink.c
@@ -0,0 +1,24 @@
+// REQUIRES: shell
+
+// Basic test
+// RUN: rm -rf %t.dir
+// RUN: mkdir %t.dir
+// RUN: mkdir %t.dir/a
+// RUN: mkdir %t.dir/b
+// RUN: echo "#ifndef HEADER_A" > %t.dir/a/header.h
+// RUN: echo "#define HEADER_A" >> %t.dir/a/header.h
+// RUN: echo "#endif" >> %t.dir/a/header.h
+// RUN: ln -s %t.dir/a/header.h %t.dir/b/header.h
+
+// RUN: %clang_cc1 -dependency-file %t.dir/file.deps -MT %s.o %s -fsyntax-only -I %t.dir -isystem %S/Inputs/SystemHeaderPrefix
+// RUN: FileCheck -input-file=%t.dir/file.deps %s
+// CHECK: dependency-gen-symlink.c.o
+// CHECK: dependency-gen-symlink.c
+// CHECK: a/header.h
+// CHECK: b/header.h
+// CHECK-NOT: with-header-guard.h
+#include "a/header.h"
+#include "b/header.h"
+// System header shouldn't be included in dependencies.
+#include <with-header-guard.h>
+#include <with-header-guard.h>
diff --git a/test/Frontend/dependency-gen.c b/test/Frontend/dependency-gen.c
index e4b0feea16a9..cd222c5dfd9a 100644
--- a/test/Frontend/dependency-gen.c
+++ b/test/Frontend/dependency-gen.c
@@ -21,7 +21,7 @@
// RUN: %clang -MD -MF - %s -fsyntax-only -I ./ | FileCheck -check-prefix=CHECK-SIX %s
// CHECK-SIX: {{ }}x.h
// RUN: echo "fun:foo" > %t.blacklist
-// RUN: %clang -MD -MF - %s -fsyntax-only -fsanitize=cfi-vcall -flto -fvisibility=hidden -fsanitize-blacklist=%t.blacklist -I ./ | FileCheck -check-prefix=CHECK-SEVEN %s
+// RUN: %clang -MD -MF - %s -fsyntax-only -resource-dir=%S/Inputs/resource_dir_with_cfi_blacklist -fsanitize=cfi-vcall -flto -fvisibility=hidden -fsanitize-blacklist=%t.blacklist -I ./ | FileCheck -check-prefix=CHECK-SEVEN %s
// CHECK-SEVEN: .blacklist
// CHECK-SEVEN: {{ }}x.h
#ifndef INCLUDE_FLAG_TEST
diff --git a/test/Frontend/fixed_point.c b/test/Frontend/fixed_point.c
new file mode 100644
index 000000000000..3a67718fba8e
--- /dev/null
+++ b/test/Frontend/fixed_point.c
@@ -0,0 +1,399 @@
+// RUN: %clang_cc1 -x c -ffixed-point -ast-dump %s | FileCheck %s --strict-whitespace
+
+/* Various contexts where type _Accum can appear. */
+
+// Primary fixed point types
+signed short _Accum s_short_accum;
+signed _Accum s_accum;
+signed long _Accum s_long_accum;
+unsigned short _Accum u_short_accum;
+unsigned _Accum u_accum;
+unsigned long _Accum u_long_accum;
+signed short _Fract s_short_fract;
+signed _Fract s_fract;
+signed long _Fract s_long_fract;
+unsigned short _Fract u_short_fract;
+unsigned _Fract u_fract;
+unsigned long _Fract u_long_fract;
+
+// Aliased fixed point types
+short _Accum short_accum;
+_Accum accum;
+long _Accum long_accum;
+short _Fract short_fract;
+_Fract fract;
+long _Fract long_fract;
+
+// Saturated fixed point types
+_Sat signed short _Accum sat_s_short_accum;
+_Sat signed _Accum sat_s_accum;
+_Sat signed long _Accum sat_s_long_accum;
+_Sat unsigned short _Accum sat_u_short_accum;
+_Sat unsigned _Accum sat_u_accum;
+_Sat unsigned long _Accum sat_u_long_accum;
+_Sat signed short _Fract sat_s_short_fract;
+_Sat signed _Fract sat_s_fract;
+_Sat signed long _Fract sat_s_long_fract;
+_Sat unsigned short _Fract sat_u_short_fract;
+_Sat unsigned _Fract sat_u_fract;
+_Sat unsigned long _Fract sat_u_long_fract;
+
+// Aliased saturated fixed point types
+_Sat short _Accum sat_short_accum;
+_Sat _Accum sat_accum;
+_Sat long _Accum sat_long_accum;
+_Sat short _Fract sat_short_fract;
+_Sat _Fract sat_fract;
+_Sat long _Fract sat_long_fract;
+
+//CHECK: |-VarDecl {{.*}} s_short_accum 'short _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} s_accum '_Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} s_long_accum 'long _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} u_short_accum 'unsigned short _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} u_accum 'unsigned _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} u_long_accum 'unsigned long _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} s_short_fract 'short _Fract'
+//CHECK-NEXT: |-VarDecl {{.*}} s_fract '_Fract'
+//CHECK-NEXT: |-VarDecl {{.*}} s_long_fract 'long _Fract'
+//CHECK-NEXT: |-VarDecl {{.*}} u_short_fract 'unsigned short _Fract'
+//CHECK-NEXT: |-VarDecl {{.*}} u_fract 'unsigned _Fract'
+//CHECK-NEXT: |-VarDecl {{.*}} u_long_fract 'unsigned long _Fract'
+//CHECK-NEXT: |-VarDecl {{.*}} short_accum 'short _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} accum '_Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} long_accum 'long _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} short_fract 'short _Fract'
+//CHECK-NEXT: |-VarDecl {{.*}} fract '_Fract'
+//CHECK-NEXT: |-VarDecl {{.*}} long_fract 'long _Fract'
+//CHECK-NEXT: |-VarDecl {{.*}} sat_s_short_accum '_Sat short _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} sat_s_accum '_Sat _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} sat_s_long_accum '_Sat long _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} sat_u_short_accum '_Sat unsigned short _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} sat_u_accum '_Sat unsigned _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} sat_u_long_accum '_Sat unsigned long _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} sat_s_short_fract '_Sat short _Fract'
+//CHECK-NEXT: |-VarDecl {{.*}} sat_s_fract '_Sat _Fract'
+//CHECK-NEXT: |-VarDecl {{.*}} sat_s_long_fract '_Sat long _Fract'
+//CHECK-NEXT: |-VarDecl {{.*}} sat_u_short_fract '_Sat unsigned short _Fract'
+//CHECK-NEXT: |-VarDecl {{.*}} sat_u_fract '_Sat unsigned _Fract'
+//CHECK-NEXT: |-VarDecl {{.*}} sat_u_long_fract '_Sat unsigned long _Fract'
+//CHECK-NEXT: |-VarDecl {{.*}} sat_short_accum '_Sat short _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} sat_accum '_Sat _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} sat_long_accum '_Sat long _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} sat_short_fract '_Sat short _Fract'
+//CHECK-NEXT: |-VarDecl {{.*}} sat_fract '_Sat _Fract'
+//CHECK-NEXT: |-VarDecl {{.*}} sat_long_fract '_Sat long _Fract'
+
+#define MIX_TYPE_SPEC(SPEC, SIGN, SIZE, ID) \
+ SPEC SIGN SIZE _Accum ID; \
+ SIGN SPEC SIZE _Accum ID ## 2; \
+ SIGN SIZE SPEC _Accum ID ## 3; \
+ SIGN SIZE _Accum SPEC ID ## 4;
+
+/* Mixing fixed point types with other type specifiers */
+
+#define MIX_VOLATILE(SIGN, SIZE, ID) MIX_TYPE_SPEC(volatile, SIGN, SIZE, ID)
+#define MIX_ATOMIC(SIGN, SIZE, ID) MIX_TYPE_SPEC(_Atomic, SIGN, SIZE, ID)
+#define MIX_CONST(SIGN, SIZE, ID) MIX_TYPE_SPEC(const, SIGN, SIZE, ID)
+
+MIX_VOLATILE(signed, short, vol_s_short_accum)
+MIX_ATOMIC(signed, short, atm_s_short_accum)
+MIX_CONST(signed, short, const_s_short_accum)
+
+// CHECK-NEXT: |-VarDecl {{.*}} vol_s_short_accum 'volatile short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} vol_s_short_accum2 'volatile short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} vol_s_short_accum3 'volatile short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} vol_s_short_accum4 'volatile short _Accum'
+
+// CHECK-NEXT: |-VarDecl {{.*}} atm_s_short_accum '_Atomic(short _Accum)'
+// CHECK-NEXT: |-VarDecl {{.*}} atm_s_short_accum2 '_Atomic(short _Accum)'
+// CHECK-NEXT: |-VarDecl {{.*}} atm_s_short_accum3 '_Atomic(short _Accum)'
+// CHECK-NEXT: |-VarDecl {{.*}} atm_s_short_accum4 '_Atomic(short _Accum)'
+
+// CHECK-NEXT: |-VarDecl {{.*}} const_s_short_accum 'const short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} const_s_short_accum2 'const short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} const_s_short_accum3 'const short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} const_s_short_accum4 'const short _Accum'
+
+/* Typedefs */
+
+// Primary fixed point types
+typedef signed short _Accum SsA_t;
+typedef signed _Accum SA_t;
+typedef signed long _Accum SlA_t;
+typedef unsigned short _Accum UsA_t;
+typedef unsigned _Accum UA_t;
+typedef unsigned long _Accum UlA_t;
+typedef signed short _Fract SsF_t;
+typedef signed _Fract SF_t;
+typedef signed long _Fract SlF_t;
+typedef unsigned short _Fract UsF_t;
+typedef unsigned _Fract UF_t;
+typedef unsigned long _Fract UlF_t;
+
+// Aliased fixed point types
+typedef short _Accum sA_t;
+typedef _Accum A_t;
+typedef long _Accum lA_t;
+typedef short _Fract sF_t;
+typedef _Fract F_t;
+typedef long _Fract lF_t;
+
+// Saturated fixed point types
+typedef _Sat signed short _Accum SatSsA_t;
+typedef _Sat signed _Accum SatSA_t;
+typedef _Sat signed long _Accum SatSlA_t;
+typedef _Sat unsigned short _Accum SatUsA_t;
+typedef _Sat unsigned _Accum SatUA_t;
+typedef _Sat unsigned long _Accum SatUlA_t;
+typedef _Sat signed short _Fract SatSsF_t;
+typedef _Sat signed _Fract SatSF_t;
+typedef _Sat signed long _Fract SatSlF_t;
+typedef _Sat unsigned short _Fract SatUsF_t;
+typedef _Sat unsigned _Fract SatUF_t;
+typedef _Sat unsigned long _Fract SatUlF_t;
+
+// Aliased saturated fixed point types
+typedef _Sat short _Accum SatsA_t;
+typedef _Sat _Accum SatA_t;
+typedef _Sat long _Accum SatlA_t;
+typedef _Sat short _Fract SatsF_t;
+typedef _Sat _Fract SatF_t;
+typedef _Sat long _Fract SatlF_t;
+
+SsA_t SsA_type;
+SA_t SA_type;
+SlA_t SlA_type;
+UsA_t UsA_type;
+UA_t UA_type;
+UlA_t UlA_type;
+SsF_t SsF_type;
+SF_t SF_type;
+SlF_t SlF_type;
+UsF_t UsF_type;
+UF_t UF_type;
+UlF_t UlF_type;
+
+sA_t sA_type;
+A_t A_type;
+lA_t lA_type;
+sF_t sF_type;
+F_t F_type;
+lF_t lF_type;
+
+SatSsA_t SatSsA_type;
+SatSA_t SatSA_type;
+SatSlA_t SatSlA_type;
+SatUsA_t SatUsA_type;
+SatUA_t SatUA_type;
+SatUlA_t SatUlA_type;
+SatSsF_t SatSsF_type;
+SatSF_t SatSF_type;
+SatSlF_t SatSlF_type;
+SatUsF_t SatUsF_type;
+SatUF_t SatUF_type;
+SatUlF_t SatUlF_type;
+
+SatsA_t SatsA_type;
+SatA_t SatA_type;
+SatlA_t SatlA_type;
+SatsF_t SatsF_type;
+SatF_t SatF_type;
+SatlF_t SatlF_type;
+
+//CHECK: |-VarDecl {{.*}} SsA_type 'SsA_t':'short _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} SA_type 'SA_t':'_Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} SlA_type 'SlA_t':'long _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} UsA_type 'UsA_t':'unsigned short _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} UA_type 'UA_t':'unsigned _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} UlA_type 'UlA_t':'unsigned long _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} SsF_type 'SsF_t':'short _Fract'
+//CHECK-NEXT: |-VarDecl {{.*}} SF_type 'SF_t':'_Fract'
+//CHECK-NEXT: |-VarDecl {{.*}} SlF_type 'SlF_t':'long _Fract'
+//CHECK-NEXT: |-VarDecl {{.*}} UsF_type 'UsF_t':'unsigned short _Fract'
+//CHECK-NEXT: |-VarDecl {{.*}} UF_type 'UF_t':'unsigned _Fract'
+//CHECK-NEXT: |-VarDecl {{.*}} UlF_type 'UlF_t':'unsigned long _Fract'
+//CHECK-NEXT: |-VarDecl {{.*}} sA_type 'sA_t':'short _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} A_type 'A_t':'_Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} lA_type 'lA_t':'long _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} sF_type 'sF_t':'short _Fract'
+//CHECK-NEXT: |-VarDecl {{.*}} F_type 'F_t':'_Fract'
+//CHECK-NEXT: |-VarDecl {{.*}} lF_type 'lF_t':'long _Fract'
+
+//CHECK-NEXT: |-VarDecl {{.*}} SatSsA_type 'SatSsA_t':'_Sat short _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} SatSA_type 'SatSA_t':'_Sat _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} SatSlA_type 'SatSlA_t':'_Sat long _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} SatUsA_type 'SatUsA_t':'_Sat unsigned short _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} SatUA_type 'SatUA_t':'_Sat unsigned _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} SatUlA_type 'SatUlA_t':'_Sat unsigned long _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} SatSsF_type 'SatSsF_t':'_Sat short _Fract'
+//CHECK-NEXT: |-VarDecl {{.*}} SatSF_type 'SatSF_t':'_Sat _Fract'
+//CHECK-NEXT: |-VarDecl {{.*}} SatSlF_type 'SatSlF_t':'_Sat long _Fract'
+//CHECK-NEXT: |-VarDecl {{.*}} SatUsF_type 'SatUsF_t':'_Sat unsigned short _Fract'
+//CHECK-NEXT: |-VarDecl {{.*}} SatUF_type 'SatUF_t':'_Sat unsigned _Fract'
+//CHECK-NEXT: |-VarDecl {{.*}} SatUlF_type 'SatUlF_t':'_Sat unsigned long _Fract'
+//CHECK-NEXT: |-VarDecl {{.*}} SatsA_type 'SatsA_t':'_Sat short _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} SatA_type 'SatA_t':'_Sat _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} SatlA_type 'SatlA_t':'_Sat long _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} SatsF_type 'SatsF_t':'_Sat short _Fract'
+//CHECK-NEXT: |-VarDecl {{.*}} SatF_type 'SatF_t':'_Sat _Fract'
+//CHECK-NEXT: |-VarDecl {{.*}} SatlF_type 'SatlF_t':'_Sat long _Fract'
+
+// Fixed point literal exponent syntax
+_Accum decexp1 = 1.575e1k;
+_Accum decexp2 = 1.575E1k;
+_Accum decexp3 = 1575e-2k;
+_Accum decexp4 = 1575E-2k;
+
+_Accum hexexp1 = 0x0.3p10k;
+_Accum hexexp2 = 0x0.3P10k;
+_Accum hexexp3 = 0x30000p-10k;
+_Accum hexexp4 = 0x30000P-10k;
+
+_Accum zeroexp1 = 1e0k;
+_Accum zeroexp2 = 1e-0k;
+
+//CHECK-NEXT: |-VarDecl {{.*}} decexp1 '_Accum' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 15.75
+//CHECK-NEXT: |-VarDecl {{.*}} decexp2 '_Accum' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 15.75
+//CHECK-NEXT: |-VarDecl {{.*}} decexp3 '_Accum' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 15.75
+//CHECK-NEXT: |-VarDecl {{.*}} decexp4 '_Accum' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 15.75
+
+//CHECK-NEXT: |-VarDecl {{.*}} hexexp1 '_Accum' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 192.0
+//CHECK-NEXT: |-VarDecl {{.*}} hexexp2 '_Accum' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 192.0
+//CHECK-NEXT: |-VarDecl {{.*}} hexexp3 '_Accum' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 192.0
+//CHECK-NEXT: |-VarDecl {{.*}} hexexp4 '_Accum' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 192.0
+
+//CHECK-NEXT: |-VarDecl {{.*}} zeroexp1 '_Accum' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 1.0
+//CHECK-NEXT: |-VarDecl {{.*}} zeroexp2 '_Accum' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 1.0
+
+// Fixed point literal values
+_Accum literal1 = 2.5k; // Precise decimal
+_Accum literal2 = 0.0k; // Zero
+_Accum literal3 = 1.1k; // Imprecise decimal
+_Accum literal4 = 1.11k;
+_Accum literal5 = 1.111k;
+_Accum literal6 = 1.1111k;
+_Accum literal7 = 1.11111k; // After some point after the radix, adding any more
+ // digits to the literal will not result in any
+ // further precision since the nth digit added may
+ // be less than the precision that can be
+ // represented by the fractional bits of the type.
+ // This results in the same value being stored for
+ // the type.
+
+//CHECK-NEXT: |-VarDecl {{.*}} literal1 '_Accum' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 2.5
+//CHECK-NEXT: |-VarDecl {{.*}} literal2 '_Accum' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 0.0
+//CHECK-NEXT: |-VarDecl {{.*}} literal3 '_Accum' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 1.0999755859375
+//CHECK-NEXT: |-VarDecl {{.*}} literal4 '_Accum' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 1.1099853515625
+//CHECK-NEXT: |-VarDecl {{.*}} literal5 '_Accum' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 1.110992431640625
+//CHECK-NEXT: |-VarDecl {{.*}} literal6 '_Accum' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 1.111083984375
+//CHECK-NEXT: |-VarDecl {{.*}} literal7 '_Accum' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 1.111083984375
+
+long _Accum longaccumliteral = 0.99999999lk;
+long _Accum longaccumliteral2 = 0.999999999lk;
+long _Accum verylongaccumliteral = 0.99999999999999999999999999lk;
+long _Fract longfractliteral = 0.99999999lr;
+long _Fract longfractliteral2 = 0.999999999lr;
+long _Fract verylongfractliteral = 0.99999999999999999999999999lr;
+
+//CHECK-NEXT: |-VarDecl {{.*}} longaccumliteral 'long _Accum' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'long _Accum' 0.999999989755451679229736328125
+//CHECK-NEXT: |-VarDecl {{.*}} longaccumliteral2 'long _Accum' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'long _Accum' 0.9999999986030161380767822265625
+//CHECK-NEXT: |-VarDecl {{.*}} verylongaccumliteral 'long _Accum' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'long _Accum' 0.9999999995343387126922607421875
+//CHECK-NEXT: |-VarDecl {{.*}} longfractliteral 'long _Fract' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'long _Fract' 0.999999989755451679229736328125
+//CHECK-NEXT: |-VarDecl {{.*}} longfractliteral2 'long _Fract' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'long _Fract' 0.9999999986030161380767822265625
+//CHECK-NEXT: |-VarDecl {{.*}} verylongfractliteral 'long _Fract' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'long _Fract' 0.9999999995343387126922607421875
+
+unsigned _Accum uliteral1 = 2.5uk; // Unsigned
+_Accum literal8 = -2.5k; // Negative
+
+//CHECK-NEXT: |-VarDecl {{.*}} uliteral1 'unsigned _Accum' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'unsigned _Accum' 2.5
+//CHECK-NEXT: |-VarDecl {{.*}} literal8 '_Accum' cinit
+//CHECK-NEXT: `-UnaryOperator {{.*}} '_Accum' prefix '-'
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 2.5
+
+short _Accum literalexact1 = 0.9921875hk; // Exact value
+_Accum literalexact2 = 0.999969482421875k;
+
+//CHECK-NEXT: |-VarDecl {{.*}} literalexact1 'short _Accum' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'short _Accum' 0.9921875
+//CHECK-NEXT: |-VarDecl {{.*}} literalexact2 '_Accum' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 0.999969482421875
+
+// Unfortunately we do not have enough space to store the exact decimal value of
+// 0.9999999995343387126922607421875 ((1 << 31) - 1), but we can still use a
+// large number of 9s to get the max fractional value.
+long _Accum long_accum_max = 0.999999999999999999999999999lk;
+
+//CHECK-NEXT: |-VarDecl {{.*}} long_accum_max 'long _Accum' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'long _Accum' 0.9999999995343387126922607421875
+
+// Epsilon
+short _Accum short_accum_eps = 0.0078125hk;
+short _Accum short_accum_eps2 = 0.0078124hk; // Less than epsilon floors to zero
+_Accum accum_eps = 0.000030517578125k;
+_Accum accum_eps2 = 0.000030517578124k;
+long _Accum long_accum_eps = 0x1p-31lk;
+long _Accum long_accum_eps2 = 0x0.99999999p-31lk;
+
+//CHECK-NEXT: |-VarDecl {{.*}} short_accum_eps 'short _Accum' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'short _Accum' 0.0078125
+//CHECK-NEXT: |-VarDecl {{.*}} short_accum_eps2 'short _Accum' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'short _Accum' 0.0
+//CHECK-NEXT: |-VarDecl {{.*}} accum_eps '_Accum' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 0.000030517578125
+//CHECK-NEXT: |-VarDecl {{.*}} accum_eps2 '_Accum' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 0.0
+//CHECK-NEXT: |-VarDecl {{.*}} long_accum_eps 'long _Accum' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'long _Accum' 0.0000000004656612873077392578125
+//CHECK-NEXT: |-VarDecl {{.*}} long_accum_eps2 'long _Accum' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'long _Accum' 0.0
+
+// Fract literals can be one but evaluate to the respective Fract max
+short _Fract short_fract_one = 1.0hr;
+_Fract fract_one = 1.0r;
+long _Fract long_fract_one = 1.0lr;
+unsigned short _Fract u_short_fract_one = 1.0uhr;
+unsigned _Fract u_fract_one = 1.0ur;
+unsigned long _Fract u_long_fract_one = 1.0ulr;
+
+//CHECK-NEXT: |-VarDecl {{.*}} short_fract_one 'short _Fract' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'short _Fract' 0.9921875
+//CHECK-NEXT: |-VarDecl {{.*}} fract_one '_Fract' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Fract' 0.999969482421875
+//CHECK-NEXT: |-VarDecl {{.*}} long_fract_one 'long _Fract' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'long _Fract' 0.9999999995343387126922607421875
+
+//CHECK-NEXT: |-VarDecl {{.*}} u_short_fract_one 'unsigned short _Fract' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'unsigned short _Fract' 0.99609375
+//CHECK-NEXT: |-VarDecl {{.*}} u_fract_one 'unsigned _Fract' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'unsigned _Fract' 0.9999847412109375
+//CHECK-NEXT: |-VarDecl {{.*}} u_long_fract_one 'unsigned long _Fract' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'unsigned long _Fract' 0.99999999976716935634613037109375
+
+_Accum literallast = 1.0k; // One
+
+//CHECK-NEXT: `-VarDecl {{.*}} literallast '_Accum' cinit
+//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 1.0
diff --git a/test/Frontend/fixed_point_bit_widths.c b/test/Frontend/fixed_point_bit_widths.c
new file mode 100644
index 000000000000..ac8db49ed516
--- /dev/null
+++ b/test/Frontend/fixed_point_bit_widths.c
@@ -0,0 +1,196 @@
+// RUN: %clang -x c -ffixed-point -S -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang -x c -ffixed-point -S -emit-llvm -o - --target=x86_64-scei-ps4-ubuntu-fast %s | FileCheck %s
+// RUN: %clang -x c -ffixed-point -S -emit-llvm -o - --target=ppc64 %s | FileCheck %s
+// RUN: %clang -x c -ffixed-point -S -emit-llvm -o - --target=x86_64-scei-ps4-windows10pro-fast %s | FileCheck %s
+
+/* Primary signed _Accum */
+
+int size_SsA = sizeof(signed short _Accum);
+int size_SA = sizeof(signed _Accum);
+int size_SlA = sizeof(signed long _Accum);
+int align_SsA = __alignof(signed short _Accum);
+int align_SA = __alignof(signed _Accum);
+int align_SlA = __alignof(signed long _Accum);
+
+// CHECK: @size_SsA = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @size_SA = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @size_SlA = {{.*}}global i{{[0-9]+}} 8
+// CHECK-NEXT: @align_SsA = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @align_SA = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @align_SlA = {{.*}}global i{{[0-9]+}} 8
+
+/* Primary unsigned _Accum */
+
+int size_UsA = sizeof(unsigned short _Accum);
+int size_UA = sizeof(unsigned _Accum);
+int size_UlA = sizeof(unsigned long _Accum);
+int align_UsA = __alignof(unsigned short _Accum);
+int align_UA = __alignof(unsigned _Accum);
+int align_UlA = __alignof(unsigned long _Accum);
+
+// CHECK-NEXT: @size_UsA = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @size_UA = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @size_UlA = {{.*}}global i{{[0-9]+}} 8
+// CHECK-NEXT: @align_UsA = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @align_UA = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @align_UlA = {{.*}}global i{{[0-9]+}} 8
+
+/* Primary signed _Fract */
+
+int size_SsF = sizeof(signed short _Fract);
+int size_SF = sizeof(signed _Fract);
+int size_SlF = sizeof(signed long _Fract);
+int align_SsF = __alignof(signed short _Fract);
+int align_SF = __alignof(signed _Fract);
+int align_SlF = __alignof(signed long _Fract);
+
+// CHECK-NEXT: @size_SsF = {{.*}}global i{{[0-9]+}} 1
+// CHECK-NEXT: @size_SF = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @size_SlF = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @align_SsF = {{.*}}global i{{[0-9]+}} 1
+// CHECK-NEXT: @align_SF = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @align_SlF = {{.*}}global i{{[0-9]+}} 4
+
+/* Primary unsigned _Fract */
+
+int size_UsF = sizeof(unsigned short _Fract);
+int size_UF = sizeof(unsigned _Fract);
+int size_UlF = sizeof(unsigned long _Fract);
+int align_UsF = __alignof(unsigned short _Fract);
+int align_UF = __alignof(unsigned _Fract);
+int align_UlF = __alignof(unsigned long _Fract);
+
+// CHECK-NEXT: @size_UsF = {{.*}}global i{{[0-9]+}} 1
+// CHECK-NEXT: @size_UF = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @size_UlF = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @align_UsF = {{.*}}global i{{[0-9]+}} 1
+// CHECK-NEXT: @align_UF = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @align_UlF = {{.*}}global i{{[0-9]+}} 4
+
+/* Aliased _Accum */
+
+int size_sA = sizeof(short _Accum);
+int size_A = sizeof(_Accum);
+int size_lA = sizeof(long _Accum);
+int align_sA = __alignof(short _Accum);
+int align_A = __alignof(_Accum);
+int align_lA = __alignof(long _Accum);
+
+// CHECK-NEXT: @size_sA = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @size_A = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @size_lA = {{.*}}global i{{[0-9]+}} 8
+// CHECK-NEXT: @align_sA = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @align_A = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @align_lA = {{.*}}global i{{[0-9]+}} 8
+
+/* Aliased _Fract */
+
+int size_sF = sizeof(short _Fract);
+int size_F = sizeof(_Fract);
+int size_lF = sizeof(long _Fract);
+int align_sF = __alignof(short _Fract);
+int align_F = __alignof(_Fract);
+int align_lF = __alignof(long _Fract);
+
+// CHECK-NEXT: @size_sF = {{.*}}global i{{[0-9]+}} 1
+// CHECK-NEXT: @size_F = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @size_lF = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @align_sF = {{.*}}global i{{[0-9]+}} 1
+// CHECK-NEXT: @align_F = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @align_lF = {{.*}}global i{{[0-9]+}} 4
+
+/* Saturated signed _Accum */
+
+int size_SatSsA = sizeof(_Sat signed short _Accum);
+int size_SatSA = sizeof(_Sat signed _Accum);
+int size_SatSlA = sizeof(_Sat signed long _Accum);
+int align_SatSsA = __alignof(_Sat signed short _Accum);
+int align_SatSA = __alignof(_Sat signed _Accum);
+int align_SatSlA = __alignof(_Sat signed long _Accum);
+
+// CHECK: @size_SatSsA = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @size_SatSA = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @size_SatSlA = {{.*}}global i{{[0-9]+}} 8
+// CHECK-NEXT: @align_SatSsA = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @align_SatSA = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @align_SatSlA = {{.*}}global i{{[0-9]+}} 8
+
+/* Saturated unsigned _Accum */
+
+int size_SatUsA = sizeof(_Sat unsigned short _Accum);
+int size_SatUA = sizeof(_Sat unsigned _Accum);
+int size_SatUlA = sizeof(_Sat unsigned long _Accum);
+int align_SatUsA = __alignof(_Sat unsigned short _Accum);
+int align_SatUA = __alignof(_Sat unsigned _Accum);
+int align_SatUlA = __alignof(_Sat unsigned long _Accum);
+
+// CHECK-NEXT: @size_SatUsA = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @size_SatUA = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @size_SatUlA = {{.*}}global i{{[0-9]+}} 8
+// CHECK-NEXT: @align_SatUsA = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @align_SatUA = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @align_SatUlA = {{.*}}global i{{[0-9]+}} 8
+
+/* Saturated signed _Fract */
+
+int size_SatSsF = sizeof(_Sat signed short _Fract);
+int size_SatSF = sizeof(_Sat signed _Fract);
+int size_SatSlF = sizeof(_Sat signed long _Fract);
+int align_SatSsF = __alignof(_Sat signed short _Fract);
+int align_SatSF = __alignof(_Sat signed _Fract);
+int align_SatSlF = __alignof(_Sat signed long _Fract);
+
+// CHECK-NEXT: @size_SatSsF = {{.*}}global i{{[0-9]+}} 1
+// CHECK-NEXT: @size_SatSF = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @size_SatSlF = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @align_SatSsF = {{.*}}global i{{[0-9]+}} 1
+// CHECK-NEXT: @align_SatSF = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @align_SatSlF = {{.*}}global i{{[0-9]+}} 4
+
+/* Saturated unsigned _Fract */
+
+int size_SatUsF = sizeof(_Sat unsigned short _Fract);
+int size_SatUF = sizeof(_Sat unsigned _Fract);
+int size_SatUlF = sizeof(_Sat unsigned long _Fract);
+int align_SatUsF = __alignof(_Sat unsigned short _Fract);
+int align_SatUF = __alignof(_Sat unsigned _Fract);
+int align_SatUlF = __alignof(_Sat unsigned long _Fract);
+
+// CHECK-NEXT: @size_SatUsF = {{.*}}global i{{[0-9]+}} 1
+// CHECK-NEXT: @size_SatUF = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @size_SatUlF = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @align_SatUsF = {{.*}}global i{{[0-9]+}} 1
+// CHECK-NEXT: @align_SatUF = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @align_SatUlF = {{.*}}global i{{[0-9]+}} 4
+
+/* Aliased saturated signed _Accum */
+
+int size_SatsA = sizeof(_Sat short _Accum);
+int size_SatA = sizeof(_Sat _Accum);
+int size_SatlA = sizeof(_Sat long _Accum);
+int align_SatsA = __alignof(_Sat short _Accum);
+int align_SatA = __alignof(_Sat _Accum);
+int align_SatlA = __alignof(_Sat long _Accum);
+
+// CHECK-NEXT: @size_SatsA = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @size_SatA = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @size_SatlA = {{.*}}global i{{[0-9]+}} 8
+// CHECK-NEXT: @align_SatsA = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @align_SatA = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @align_SatlA = {{.*}}global i{{[0-9]+}} 8
+
+/* Aliased saturated _Fract */
+
+int size_SatsF = sizeof(_Sat short _Fract);
+int size_SatF = sizeof(_Sat _Fract);
+int size_SatlF = sizeof(_Sat long _Fract);
+int align_SatsF = __alignof(_Sat short _Fract);
+int align_SatF = __alignof(_Sat _Fract);
+int align_SatlF = __alignof(_Sat long _Fract);
+
+// CHECK-NEXT: @size_SatsF = {{.*}}global i{{[0-9]+}} 1
+// CHECK-NEXT: @size_SatF = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @size_SatlF = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @align_SatsF = {{.*}}global i{{[0-9]+}} 1
+// CHECK-NEXT: @align_SatF = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @align_SatlF = {{.*}}global i{{[0-9]+}} 4
diff --git a/test/Frontend/fixed_point_declarations.c b/test/Frontend/fixed_point_declarations.c
new file mode 100644
index 000000000000..5df54f38d7f6
--- /dev/null
+++ b/test/Frontend/fixed_point_declarations.c
@@ -0,0 +1,113 @@
+// RUN: %clang -ffixed-point -S -emit-llvm %s -o - --target=x86_64-linux | FileCheck %s
+// RUN: %clang -ffixed-point -S -emit-llvm %s -o - --target=x86_64-scei-ps4-ubuntu-fast | FileCheck %s
+
+// Primary fixed point types
+signed short _Accum s_short_accum; // CHECK-DAG: @s_short_accum = {{.*}}global i16 0, align 2
+signed _Accum s_accum; // CHECK-DAG: @s_accum = {{.*}}global i32 0, align 4
+signed long _Accum s_long_accum; // CHECK-DAG: @s_long_accum = {{.*}}global i64 0, align 8
+unsigned short _Accum u_short_accum; // CHECK-DAG: @u_short_accum = {{.*}}global i16 0, align 2
+unsigned _Accum u_accum; // CHECK-DAG: @u_accum = {{.*}}global i32 0, align 4
+unsigned long _Accum u_long_accum; // CHECK-DAG: @u_long_accum = {{.*}}global i64 0, align 8
+signed short _Fract s_short_fract; // CHECK-DAG: @s_short_fract = {{.*}}global i8 0, align 1
+signed _Fract s_fract; // CHECK-DAG: @s_fract = {{.*}}global i16 0, align 2
+signed long _Fract s_long_fract; // CHECK-DAG: @s_long_fract = {{.*}}global i32 0, align 4
+unsigned short _Fract u_short_fract; // CHECK-DAG: @u_short_fract = {{.*}}global i8 0, align 1
+unsigned _Fract u_fract; // CHECK-DAG: @u_fract = {{.*}}global i16 0, align 2
+unsigned long _Fract u_long_fract; // CHECK-DAG: @u_long_fract = {{.*}}global i32 0, align 4
+
+// Aliased
+short _Accum short_accum; // CHECK-DAG: @short_accum = {{.*}}global i16 0, align 2
+_Accum accum; // CHECK-DAG: @accum = {{.*}}global i32 0, align 4
+long _Accum long_accum; // CHECK-DAG: @long_accum = {{.*}}global i64 0, align 8
+short _Fract short_fract; // CHECK-DAG: @short_fract = {{.*}}global i8 0, align 1
+_Fract fract; // CHECK-DAG: @fract = {{.*}}global i16 0, align 2
+long _Fract long_fract; // CHECK-DAG: @long_fract = {{.*}}global i32 0, align 4
+
+// Primary saturated
+_Sat signed short _Accum sat_s_short_accum; // CHECK-DAG: @sat_s_short_accum = {{.*}}global i16 0, align 2
+_Sat signed _Accum sat_s_accum; // CHECK-DAG: @sat_s_accum = {{.*}}global i32 0, align 4
+_Sat signed long _Accum sat_s_long_accum; // CHECK-DAG: @sat_s_long_accum = {{.*}}global i64 0, align 8
+_Sat unsigned short _Accum sat_u_short_accum; // CHECK-DAG: @sat_u_short_accum = {{.*}}global i16 0, align 2
+_Sat unsigned _Accum sat_u_accum; // CHECK-DAG: @sat_u_accum = {{.*}}global i32 0, align 4
+_Sat unsigned long _Accum sat_u_long_accum; // CHECK-DAG: @sat_u_long_accum = {{.*}}global i64 0, align 8
+_Sat signed short _Fract sat_s_short_fract; // CHECK-DAG: @sat_s_short_fract = {{.*}}global i8 0, align 1
+_Sat signed _Fract sat_s_fract; // CHECK-DAG: @sat_s_fract = {{.*}}global i16 0, align 2
+_Sat signed long _Fract sat_s_long_fract; // CHECK-DAG: @sat_s_long_fract = {{.*}}global i32 0, align 4
+_Sat unsigned short _Fract sat_u_short_fract; // CHECK-DAG: @sat_u_short_fract = {{.*}}global i8 0, align 1
+_Sat unsigned _Fract sat_u_fract; // CHECK-DAG: @sat_u_fract = {{.*}}global i16 0, align 2
+_Sat unsigned long _Fract sat_u_long_fract; // CHECK-DAG: @sat_u_long_fract = {{.*}}global i32 0, align 4
+
+// Aliased saturated
+_Sat short _Accum sat_short_accum; // CHECK-DAG: @sat_short_accum = {{.*}}global i16 0, align 2
+_Sat _Accum sat_accum; // CHECK-DAG: @sat_accum = {{.*}}global i32 0, align 4
+_Sat long _Accum sat_long_accum; // CHECK-DAG: @sat_long_accum = {{.*}}global i64 0, align 8
+_Sat short _Fract sat_short_fract; // CHECK-DAG: @sat_short_fract = {{.*}}global i8 0, align 1
+_Sat _Fract sat_fract; // CHECK-DAG: @sat_fract = {{.*}}global i16 0, align 2
+_Sat long _Fract sat_long_fract; // CHECK-DAG: @sat_long_fract = {{.*}}global i32 0, align 4
+
+/* Fixed point literals */
+short _Accum short_accum_literal = 2.5hk; // CHECK-DAG: @short_accum_literal = {{.*}}global i16 320, align 2
+_Accum accum_literal = 2.5k; // CHECK-DAG: @accum_literal = {{.*}}global i32 81920, align 4
+long _Accum long_accum_literal = 2.5lk; // CHECK-DAG: @long_accum_literal = {{.*}}global i64 5368709120, align 8
+short _Fract short_fract_literal = 0.5hr; // CHECK-DAG: @short_fract_literal = {{.*}}global i8 64, align 1
+_Fract fract_literal = 0.5r; // CHECK-DAG: @fract_literal = {{.*}}global i16 16384, align 2
+long _Fract long_fract_literal = 0.5lr; // CHECK-DAG: @long_fract_literal = {{.*}}global i32 1073741824, align 4
+
+unsigned short _Accum u_short_accum_literal = 2.5uhk; // CHECK-DAG: @u_short_accum_literal = {{.*}}global i16 640, align 2
+unsigned _Accum u_accum_literal = 2.5uk; // CHECK-DAG: @u_accum_literal = {{.*}}global i32 163840, align 4
+unsigned long _Accum u_long_accum_literal = 2.5ulk; // CHECK-DAG: @u_long_accum_literal = {{.*}}global i64 10737418240, align 8
+unsigned short _Fract u_short_fract_literal = 0.5uhr; // CHECK-DAG: @u_short_fract_literal = {{.*}}global i8 -128, align 1
+unsigned _Fract u_fract_literal = 0.5ur; // CHECK-DAG: @u_fract_literal = {{.*}}global i16 -32768, align 2
+unsigned long _Fract u_long_fract_literal = 0.5ulr; // CHECK-DAG: @u_long_fract_literal = {{.*}}global i32 -2147483648, align 4
+
+// Max literal values
+short _Accum short_accum_max = 255.9999999999999999hk; // CHECK-DAG: @short_accum_max = {{.*}}global i16 32767, align 2
+_Accum accum_max = 65535.9999999999999999k; // CHECK-DAG: @accum_max = {{.*}}global i32 2147483647, align 4
+long _Accum long_accum_max = 4294967295.9999999999999999lk; // CHECK-DAG: @long_accum_max = {{.*}}global i64 9223372036854775807, align 8
+unsigned short _Accum u_short_accum_max = 255.9999999999999999uhk; // CHECK-DAG: @u_short_accum_max = {{.*}}global i16 -1, align 2
+unsigned _Accum u_accum_max = 65535.9999999999999999uk; // CHECK-DAG: @u_accum_max = {{.*}}global i32 -1, align 4
+unsigned long _Accum u_long_accum_max = 4294967295.9999999999999999ulk; // CHECK-DAG: @u_long_accum_max = {{.*}}global i64 -1, align 8
+
+short _Fract short_fract_max = 0.9999999999999999hr; // CHECK-DAG: @short_fract_max = {{.*}}global i8 127, align 1
+_Fract fract_max = 0.9999999999999999r; // CHECK-DAG: @fract_max = {{.*}}global i16 32767, align 2
+long _Fract long_fract_max = 0.9999999999999999lr; // CHECK-DAG: @long_fract_max = {{.*}}global i32 2147483647, align 4
+unsigned short _Fract u_short_fract_max = 0.9999999999999999uhr; // CHECK-DAG: @u_short_fract_max = {{.*}}global i8 -1, align 1
+unsigned _Fract u_fract_max = 0.9999999999999999ur; // CHECK-DAG: @u_fract_max = {{.*}}global i16 -1, align 2
+unsigned long _Fract u_long_fract_max = 0.9999999999999999ulr; // CHECK-DAG: @u_long_fract_max = {{.*}}global i32 -1, align 4
+
+// Fracts may be exactly one but evaluate to the Fract max
+short _Fract short_fract_one = 1.0hr; // CHECK-DAG: @short_fract_one = {{.*}}global i8 127, align 1
+_Fract fract_one = 1.0r; // CHECK-DAG: @fract_one = {{.*}}global i16 32767, align 2
+long _Fract long_fract_one = 1.0lr; // CHECK-DAG: @long_fract_one = {{.*}}global i32 2147483647, align 4
+unsigned short _Fract u_short_fract_one = 1.0uhr; // CHECK-DAG: @u_short_fract_one = {{.*}}global i8 -1, align 1
+unsigned _Fract u_fract_one = 1.0ur; // CHECK-DAG: @u_fract_one = {{.*}}global i16 -1, align 2
+unsigned long _Fract u_long_fract_one = 1.0ulr; // CHECK-DAG: @u_long_fract_one = {{.*}}global i32 -1, align 4
+
+short _Fract short_fract_exp_one = 0.1e1hr; // CHECK-DAG: @short_fract_exp_one = {{.*}}global i8 127, align 1
+_Fract fract_exp_one = 0.1e1r; // CHECK-DAG: @fract_exp_one = {{.*}}global i16 32767, align 2
+long _Fract long_fract_exp_one = 0.1e1lr; // CHECK-DAG: @long_fract_exp_one = {{.*}}global i32 2147483647, align 4
+unsigned short _Fract u_short_fract_exp_one = 0.1e1uhr; // CHECK-DAG: @u_short_fract_exp_one = {{.*}}global i8 -1, align 1
+unsigned _Fract u_fract_exp_one = 0.1e1ur; // CHECK-DAG: @u_fract_exp_one = {{.*}}global i16 -1, align 2
+unsigned long _Fract u_long_fract_exp_one = 0.1e1ulr; // CHECK-DAG: @u_long_fract_exp_one = {{.*}}global i32 -1, align 4
+
+short _Fract short_fract_hex_exp_one = 0x0.8p1hr; // CHECK-DAG: @short_fract_hex_exp_one = {{.*}}global i8 127, align 1
+_Fract fract_hex_exp_one = 0x0.8p1r; // CHECK-DAG: @fract_hex_exp_one = {{.*}}global i16 32767, align 2
+long _Fract long_fract_hex_exp_one = 0x0.8p1lr; // CHECK-DAG: @long_fract_hex_exp_one = {{.*}}global i32 2147483647, align 4
+unsigned short _Fract u_short_fract_hex_exp_one = 0x0.8p1uhr; // CHECK-DAG: @u_short_fract_hex_exp_one = {{.*}}global i8 -1, align 1
+unsigned _Fract u_fract_hex_exp_one = 0x0.8p1ur; // CHECK-DAG: @u_fract_hex_exp_one = {{.*}}global i16 -1, align 2
+unsigned long _Fract u_long_fract_hex_exp_one = 0x0.8p1ulr; // CHECK-DAG: @u_long_fract_hex_exp_one = {{.*}}global i32 -1, align 4
+
+// Expsilon values
+short _Accum short_accum_eps = 0x1p-7hk; // CHECK-DAG: @short_accum_eps = {{.*}}global i16 1, align 2
+_Accum accum_eps = 0x1p-15k; // CHECK-DAG: @accum_eps = {{.*}}global i32 1, align 4
+long _Accum long_accum_eps = 0x1p-31lk; // CHECK-DAG: @long_accum_eps = {{.*}}global i64 1, align 8
+unsigned short _Accum u_short_accum_eps = 0x1p-8uhk; // CHECK-DAG: @u_short_accum_eps = {{.*}}global i16 1, align 2
+unsigned _Accum u_accum_eps = 0x1p-16uk; // CHECK-DAG: @u_accum_eps = {{.*}}global i32 1, align 4
+unsigned long _Accum u_long_accum_eps = 0x1p-32ulk; // CHECK-DAG: @u_long_accum_eps = {{.*}}global i64 1, align 8
+
+short _Fract short_fract_eps = 0x1p-7hr; // CHECK-DAG: @short_fract_eps = {{.*}}global i8 1, align 1
+_Fract fract_eps = 0x1p-15r; // CHECK-DAG: @fract_eps = {{.*}}global i16 1, align 2
+long _Fract long_fract_eps = 0x1p-31lr; // CHECK-DAG: @long_fract_eps = {{.*}}global i32 1, align 4
+unsigned short _Fract u_short_fract_eps = 0x1p-8uhr; // CHECK-DAG: @u_short_fract_eps = {{.*}}global i8 1, align 1
+unsigned _Fract u_fract_eps = 0x1p-16ur; // CHECK-DAG: @u_fract_eps = {{.*}}global i16 1, align 2
+unsigned long _Fract u_long_fract_eps = 0x1p-32ulr; // CHECK-DAG: @u_long_fract_eps = {{.*}}global i32 1, align 4
diff --git a/test/Frontend/fixed_point_errors.c b/test/Frontend/fixed_point_errors.c
new file mode 100644
index 000000000000..41427e343154
--- /dev/null
+++ b/test/Frontend/fixed_point_errors.c
@@ -0,0 +1,234 @@
+// RUN: %clang_cc1 -verify -ffixed-point %s
+
+/* We do not yet support long long. No recommended bit widths are given for this
+ * size. */
+
+long long _Accum longlong_accum; // expected-error{{'long long _Accum' is invalid}}
+unsigned long long _Accum u_longlong_accum; // expected-error{{'long long _Accum' is invalid}}
+long long _Fract longlong_fract; // expected-error{{'long long _Fract' is invalid}}
+unsigned long long _Fract u_longlong_fract; // expected-error{{'long long _Fract' is invalid}}
+
+_Sat long long _Accum sat_longlong_accum; // expected-error{{'long long _Accum' is invalid}}
+_Sat unsigned long long _Accum sat_u_longlong_accum; // expected-error{{'long long _Accum' is invalid}}
+_Sat long long _Fract sat_longlong_fract; // expected-error{{'long long _Fract' is invalid}}
+_Sat unsigned long long _Fract sat_u_longlong_fract; // expected-error{{'long long _Fract' is invalid}}
+
+
+/* Although _Complex types work with floating point numbers, the extension
+ * provides no info for complex fixed point types. */
+
+_Complex signed short _Accum cmplx_s_short_accum; // expected-error{{'_Complex _Accum' is invalid}}
+_Complex signed _Accum cmplx_s_accum; // expected-error{{'_Complex _Accum' is invalid}}
+_Complex signed long _Accum cmplx_s_long_accum; // expected-error{{'_Complex _Accum' is invalid}}
+_Complex unsigned short _Accum cmplx_u_short_accum; // expected-error{{'_Complex _Accum' is invalid}}
+_Complex unsigned _Accum cmplx_u_accum; // expected-error{{'_Complex _Accum' is invalid}}
+_Complex unsigned long _Accum cmplx_u_long_accum; // expected-error{{'_Complex _Accum' is invalid}}
+_Complex short _Accum cmplx_s_short_accum; // expected-error{{'_Complex _Accum' is invalid}}
+_Complex _Accum cmplx_s_accum; // expected-error{{'_Complex _Accum' is invalid}}
+_Complex long _Accum cmplx_s_long_accum; // expected-error{{'_Complex _Accum' is invalid}}
+
+_Complex signed short _Fract cmplx_s_short_fract; // expected-error{{'_Complex _Fract' is invalid}}
+_Complex signed _Fract cmplx_s_fract; // expected-error{{'_Complex _Fract' is invalid}}
+_Complex signed long _Fract cmplx_s_long_fract; // expected-error{{'_Complex _Fract' is invalid}}
+_Complex unsigned short _Fract cmplx_u_short_fract; // expected-error{{'_Complex _Fract' is invalid}}
+_Complex unsigned _Fract cmplx_u_fract; // expected-error{{'_Complex _Fract' is invalid}}
+_Complex unsigned long _Fract cmplx_u_long_fract; // expected-error{{'_Complex _Fract' is invalid}}
+_Complex short _Fract cmplx_s_short_fract; // expected-error{{'_Complex _Fract' is invalid}}
+_Complex _Fract cmplx_s_fract; // expected-error{{'_Complex _Fract' is invalid}}
+_Complex long _Fract cmplx_s_long_fract; // expected-error{{'_Complex _Fract' is invalid}}
+
+_Complex _Sat signed short _Accum cmplx_sat_s_short_accum; // expected-error{{'_Complex _Accum' is invalid}}
+_Complex _Sat signed _Accum cmplx_sat_s_accum; // expected-error{{'_Complex _Accum' is invalid}}
+_Complex _Sat signed long _Accum cmplx_sat_s_long_accum; // expected-error{{'_Complex _Accum' is invalid}}
+_Complex _Sat unsigned short _Accum cmplx_sat_u_short_accum; // expected-error{{'_Complex _Accum' is invalid}}
+_Complex _Sat unsigned _Accum cmplx_sat_u_accum; // expected-error{{'_Complex _Accum' is invalid}}
+_Complex _Sat unsigned long _Accum cmplx_sat_u_long_accum; // expected-error{{'_Complex _Accum' is invalid}}
+_Complex _Sat short _Accum cmplx_sat_s_short_accum; // expected-error{{'_Complex _Accum' is invalid}}
+_Complex _Sat _Accum cmplx_sat_s_accum; // expected-error{{'_Complex _Accum' is invalid}}
+_Complex _Sat long _Accum cmplx_sat_s_long_accum; // expected-error{{'_Complex _Accum' is invalid}}
+
+_Complex signed short _Fract cmplx_sat_s_short_fract; // expected-error{{'_Complex _Fract' is invalid}}
+_Complex signed _Fract cmplx_sat_s_fract; // expected-error{{'_Complex _Fract' is invalid}}
+_Complex signed long _Fract cmplx_sat_s_long_fract; // expected-error{{'_Complex _Fract' is invalid}}
+_Complex unsigned short _Fract cmplx_sat_u_short_fract; // expected-error{{'_Complex _Fract' is invalid}}
+_Complex unsigned _Fract cmplx_sat_u_fract; // expected-error{{'_Complex _Fract' is invalid}}
+_Complex unsigned long _Fract cmplx_sat_u_long_fract; // expected-error{{'_Complex _Fract' is invalid}}
+_Complex short _Fract cmplx_sat_s_short_fract; // expected-error{{'_Complex _Fract' is invalid}}
+_Complex _Fract cmplx_sat_s_fract; // expected-error{{'_Complex _Fract' is invalid}}
+_Complex long _Fract cmplx_sat_s_long_fract; // expected-error{{'_Complex _Fract' is invalid}}
+
+/* Bad combinations */
+float _Accum f_accum; // expected-error{{cannot combine with previous 'float' declaration specifier}}
+double _Accum d_accum; // expected-error{{cannot combine with previous 'double' declaration specifier}}
+_Bool _Accum b_accum; // expected-error{{cannot combine with previous '_Bool' declaration specifier}}
+char _Accum c_accum; // expected-error{{cannot combine with previous 'char' declaration specifier}}
+int _Accum i_accum; // expected-error{{cannot combine with previous 'int' declaration specifier}}
+
+float _Fract f_fract; // expected-error{{cannot combine with previous 'float' declaration specifier}}
+double _Fract d_fract; // expected-error{{cannot combine with previous 'double' declaration specifier}}
+_Bool _Fract b_fract; // expected-error{{cannot combine with previous '_Bool' declaration specifier}}
+char _Fract c_fract; // expected-error{{cannot combine with previous 'char' declaration specifier}}
+int _Fract i_fract; // expected-error{{cannot combine with previous 'int' declaration specifier}}
+
+/* Bad saturated combinations */
+_Sat float f; // expected-error{{'_Sat' specifier is only valid on '_Fract' or '_Accum', not 'float'}}
+_Sat double d; // expected-error{{'_Sat' specifier is only valid on '_Fract' or '_Accum', not 'double'}}
+_Sat _Bool b; // expected-error{{'_Sat' specifier is only valid on '_Fract' or '_Accum', not '_Bool'}}
+_Sat char c; // expected-error{{'_Sat' specifier is only valid on '_Fract' or '_Accum', not 'char'}}
+_Sat int i; // expected-error{{'_Sat' specifier is only valid on '_Fract' or '_Accum', not 'int'}}
+_Sat _Sat _Fract fract; // expected-warning{{duplicate '_Sat' declaration specifier}}
+
+
+/* Literals that cannot fit into types */
+signed short _Accum s_short_accum = 256.0hk; // expected-error{{this value is too large for this fixed point type}}
+unsigned short _Accum u_short_accum = 256.0uhk; // expected-error{{this value is too large for this fixed point type}}
+signed _Accum s_accum = 65536.0k; // expected-error{{this value is too large for this fixed point type}}
+unsigned _Accum u_accum = 65536.0uk; // expected-error{{this value is too large for this fixed point type}}
+signed long _Accum s_long_accum = 4294967296.0lk; // expected-error{{this value is too large for this fixed point type}}
+unsigned long _Accum u_long_accum = 4294967296.0ulk; // expected-error{{this value is too large for this fixed point type}}
+
+// Large values from decimal exponents
+short _Accum short_accum_exp = 2.56e2hk; // expected-error{{this value is too large for this fixed point type}}
+_Accum accum_exp = 6.5536e4k; // expected-error{{this value is too large for this fixed point type}}
+long _Accum long_accum_exp = 4.294967296e9lk; // expected-error{{this value is too large for this fixed point type}}
+unsigned short _Accum u_short_accum_exp = 2.56e2uhk; // expected-error{{this value is too large for this fixed point type}}
+unsigned _Accum u_accum_exp = 6.5536e4uk; // expected-error{{this value is too large for this fixed point type}}
+unsigned long _Accum u_long_accum_exp = 4.294967296e9ulk; // expected-error{{this value is too large for this fixed point type}}
+
+// Large value from hexidecimal exponents
+short _Accum short_accum_hex_exp = 0x1p8hk; // expected-error{{this value is too large for this fixed point type}}
+_Accum accum_hex_exp = 0x1p16k; // expected-error{{this value is too large for this fixed point type}}
+long _Accum long_accum_hex_exp = 0x1p32lk; // expected-error{{this value is too large for this fixed point type}}
+unsigned short _Accum u_short_accum_hex_exp = 0x1p8uhk; // expected-error{{this value is too large for this fixed point type}}
+unsigned _Accum u_accum_hex_exp = 0x1p16uk; // expected-error{{this value is too large for this fixed point type}}
+unsigned long _Accum u_long_accum_hex_exp = 0x1p32ulk; // expected-error{{this value is too large for this fixed point type}}
+
+// Very large exponent
+_Accum x = 1e1000000000000000000000000000000000k; // expected-error{{this value is too large for this fixed point type}}
+
+/* Although _Fract's cannot equal 1, _Fract literals written as 1 are allowed
+ * and the underlying value represents the max value for that _Fract type. */
+short _Fract short_fract_above_1 = 1.1hr; // expected-error{{this value is too large for this fixed point type}}
+_Fract fract_above_1 = 1.1r; // expected-error{{this value is too large for this fixed point type}}
+long _Fract long_fract_above_1 = 1.1lr; // expected-error{{this value is too large for this fixed point type}}
+unsigned short _Fract u_short_fract_above_1 = 1.1uhr; // expected-error{{this value is too large for this fixed point type}}
+unsigned _Fract u_fract_above_1 = 1.1ur; // expected-error{{this value is too large for this fixed point type}}
+unsigned long _Fract u_long_fract_above_1 = 1.1ulr; // expected-error{{this value is too large for this fixed point type}}
+
+short _Fract short_fract_hex_exp = 0x0.fp1hr; // expected-error{{this value is too large for this fixed point type}}
+_Fract fract_hex_exp = 0x0.fp1r; // expected-error{{this value is too large for this fixed point type}}
+long _Fract long_fract_hex_exp = 0x0.fp1lr; // expected-error{{this value is too large for this fixed point type}}
+unsigned short _Fract u_short_fract_hex_exp = 0x0.fp1uhr; // expected-error{{this value is too large for this fixed point type}}
+unsigned _Fract u_fract_hex_exp = 0x0.fp1ur; // expected-error{{this value is too large for this fixed point type}}
+unsigned long _Fract u_long_fract_hex_exp = 0x0.fp1ulr; // expected-error{{this value is too large for this fixed point type}}
+
+/* Do not allow typedef to be used with typedef'd types */
+typedef short _Fract shortfract_t;
+typedef short _Accum shortaccum_t;
+typedef _Fract fract_t;
+typedef _Accum accum_t;
+typedef long _Fract longfract_t;
+typedef long _Accum longaccum_t;
+_Sat shortfract_t td_sat_short_fract; // expected-error{{'_Sat' specifier is only valid on '_Fract' or '_Accum', not 'type-name'}}
+_Sat shortaccum_t td_sat_short_accum; // expected-error{{'_Sat' specifier is only valid on '_Fract' or '_Accum', not 'type-name'}}
+_Sat fract_t td_sat_fract; // expected-error{{'_Sat' specifier is only valid on '_Fract' or '_Accum', not 'type-name'}}
+_Sat accum_t td_sat_accum; // expected-error{{'_Sat' specifier is only valid on '_Fract' or '_Accum', not 'type-name'}}
+_Sat longfract_t td_sat_long_fract; // expected-error{{'_Sat' specifier is only valid on '_Fract' or '_Accum', not 'type-name'}}
+_Sat longaccum_t td_sat_long_accum; // expected-error{{'_Sat' specifier is only valid on '_Fract' or '_Accum', not 'type-name'}}
+
+/* Bad suffixes */
+_Accum fk = 1.0fk; // expected-error{{invalid suffix 'fk' on integer constant}}
+_Accum kk = 1.0kk; // expected-error{{invalid suffix 'kk' on integer constant}}
+_Accum rk = 1.0rk; // expected-error{{invalid suffix 'rk' on integer constant}}
+_Accum rk = 1.0rr; // expected-error{{invalid suffix 'rr' on integer constant}}
+_Accum qk = 1.0qr; // expected-error{{invalid suffix 'qr' on integer constant}}
+
+/* Using wrong exponent notation */
+_Accum dec_with_hex_exp1 = 0.1p10k; // expected-error{{invalid suffix 'p10k' on integer constant}}
+_Accum dec_with_hex_exp2 = 0.1P10k; // expected-error{{invalid suffix 'P10k' on integer constant}}
+_Accum hex_with_dex_exp1 = 0x0.1e10k; // expected-error{{hexadecimal floating constant requires an exponent}}
+_Accum hex_with_dex_exp2 = 0x0.1E10k; // expected-error{{hexadecimal floating constant requires an exponent}}
+
+void CheckSuffixOnIntegerLiterals() {
+ _Accum short_acc_int;
+ _Accum acc_int;
+ _Accum long_acc_int;
+
+ _Accum u_short_acc_int;
+ _Accum u_acc_int;
+ _Accum u_long_acc_int;
+
+ _Fract short_fract_int;
+ _Fract fract_int;
+ _Fract long_fract_int;
+
+ _Fract u_short_fract_int;
+ _Fract u_fract_int;
+ _Fract u_long_fract_int;
+
+ // Decimal integer literals (non-zero)
+ short_acc_int = 10hk; // expected-error{{invalid suffix 'hk' on integer constant}}
+ acc_int = 10k; // expected-error{{invalid suffix 'k' on integer constant}}
+ long_acc_int = 10lk; // expected-error{{invalid suffix 'lk' on integer constant}}
+
+ u_short_acc_int = 10uhk; // expected-error{{invalid suffix 'uhk' on integer constant}}
+ u_acc_int = 10uk; // expected-error{{invalid suffix 'uk' on integer constant}}
+ u_long_acc_int = 10ulk; // expected-error{{invalid suffix 'ulk' on integer constant}}
+
+ short_fract_int = 10hr; // expected-error{{invalid suffix 'hr' on integer constant}}
+ fract_int = 10r; // expected-error{{invalid suffix 'r' on integer constant}}
+ long_fract_int = 10lr; // expected-error{{invalid suffix 'lr' on integer constant}}
+
+ u_short_fract_int = 10uhr; // expected-error{{invalid suffix 'uhr' on integer constant}}
+ u_fract_int = 10ur; // expected-error{{invalid suffix 'ur' on integer constant}}
+ u_long_fract_int = 10ulr; // expected-error{{invalid suffix 'ulr' on integer constant}}
+
+ // Decimal integer literals (0)
+ short_acc_int = 0hk; // expected-error{{invalid suffix 'hk' on integer constant}}
+ acc_int = 0k; // expected-error{{invalid suffix 'k' on integer constant}}
+ long_acc_int = 0lk; // expected-error{{invalid suffix 'lk' on integer constant}}
+
+ // Decimal integer literals (large number)
+ acc_int = 999999999999999999k; // expected-error{{invalid suffix 'k' on integer constant}}
+ fract_int = 999999999999999999r; // expected-error{{invalid suffix 'r' on integer constant}}
+
+ // Octal integer literals
+ short_acc_int = 010hk; // expected-error{{invalid suffix 'hk' on integer constant}}
+ acc_int = 010k; // expected-error{{invalid suffix 'k' on integer constant}}
+ long_acc_int = 010lk; // expected-error{{invalid suffix 'lk' on integer constant}}
+
+ u_short_acc_int = 010uhk; // expected-error{{invalid suffix 'uhk' on integer constant}}
+ u_acc_int = 010uk; // expected-error{{invalid suffix 'uk' on integer constant}}
+ u_long_acc_int = 010ulk; // expected-error{{invalid suffix 'ulk' on integer constant}}
+
+ short_fract_int = 010hr; // expected-error{{invalid suffix 'hr' on integer constant}}
+ fract_int = 010r; // expected-error{{invalid suffix 'r' on integer constant}}
+ long_fract_int = 010lr; // expected-error{{invalid suffix 'lr' on integer constant}}
+
+ u_short_fract_int = 010uhr; // expected-error{{invalid suffix 'uhr' on integer constant}}
+ u_fract_int = 010ur; // expected-error{{invalid suffix 'ur' on integer constant}}
+ u_long_fract_int = 010ulr; // expected-error{{invalid suffix 'ulr' on integer constant}}
+
+ // Hexadecimal integer literals
+ short_acc_int = 0x10hk; // expected-error{{invalid suffix 'hk' on integer constant}}
+ acc_int = 0x10k; // expected-error{{invalid suffix 'k' on integer constant}}
+ long_acc_int = 0x10lk; // expected-error{{invalid suffix 'lk' on integer constant}}
+
+ u_short_acc_int = 0x10uhk; // expected-error{{invalid suffix 'uhk' on integer constant}}
+ u_acc_int = 0x10uk; // expected-error{{invalid suffix 'uk' on integer constant}}
+ u_long_acc_int = 0x10ulk; // expected-error{{invalid suffix 'ulk' on integer constant}}
+
+ short_fract_int = 0x10hr; // expected-error{{invalid suffix 'hr' on integer constant}}
+ fract_int = 0x10r; // expected-error{{invalid suffix 'r' on integer constant}}
+ long_fract_int = 0x10lr; // expected-error{{invalid suffix 'lr' on integer constant}}
+
+ u_short_fract_int = 0x10uhr; // expected-error{{invalid suffix 'uhr' on integer constant}}
+ u_fract_int = 0x10ur; // expected-error{{invalid suffix 'ur' on integer constant}}
+ u_long_fract_int = 0x10ulr; // expected-error{{invalid suffix 'ulr' on integer constant}}
+
+ // Using auto
+ auto auto_fract = 0r; // expected-error{{invalid suffix 'r' on integer constant}}
+ // expected-warning@-1{{type specifier missing, defaults to 'int'}}
+ auto auto_accum = 0k; // expected-error{{invalid suffix 'k' on integer constant}}
+ // expected-warning@-1{{type specifier missing, defaults to 'int'}}
+}
diff --git a/test/Frontend/fixed_point_errors.cpp b/test/Frontend/fixed_point_errors.cpp
new file mode 100644
index 000000000000..cdd90ceb7548
--- /dev/null
+++ b/test/Frontend/fixed_point_errors.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -x c++ %s -verify
+// RUN: %clang_cc1 -x c++ -ffixed-point %s -verify
+
+// Name namgling is not provided for fixed point types in c++
+
+_Accum accum; // expected-error{{unknown type name '_Accum'}}
+_Fract fract; // expected-error{{unknown type name '_Fract'}}
+_Sat _Accum sat_accum; // expected-error{{unknown type name '_Sat'}}
+ // expected-error@-1{{expected ';' after top level declarator}}
+
+int accum_int = 10k; // expected-error{{invalid suffix 'k' on integer constant}}
+int fract_int = 10r; // expected-error{{invalid suffix 'r' on integer constant}}
+float accum_flt = 10.0k; // expected-error{{invalid suffix 'k' on floating constant}}
+float fract_flt = 10.0r; // expected-error{{invalid suffix 'r' on floating constant}}
diff --git a/test/Frontend/fixed_point_not_enabled.c b/test/Frontend/fixed_point_not_enabled.c
new file mode 100644
index 000000000000..e7522213f98d
--- /dev/null
+++ b/test/Frontend/fixed_point_not_enabled.c
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -x c -verify %s
+
+// Primary fixed point types
+signed short _Accum s_short_accum; // expected-error{{compile with '-ffixed-point' to enable fixed point types}}
+signed _Accum s_accum; // expected-error{{compile with '-ffixed-point' to enable fixed point types}}
+signed long _Accum s_long_accum; // expected-error{{compile with '-ffixed-point' to enable fixed point types}}
+unsigned short _Accum u_short_accum; // expected-error{{compile with '-ffixed-point' to enable fixed point types}}
+unsigned _Accum u_accum; // expected-error{{compile with '-ffixed-point' to enable fixed point types}}
+unsigned long _Accum u_long_accum; // expected-error{{compile with '-ffixed-point' to enable fixed point types}}
+
+// Aliased fixed point types
+short _Accum short_accum; // expected-error{{compile with '-ffixed-point' to enable fixed point types}}
+_Accum accum; // expected-error{{compile with '-ffixed-point' to enable fixed point types}}
+ // expected-warning@-1{{type specifier missing, defaults to 'int'}}
+long _Accum long_accum; // expected-error{{compile with '-ffixed-point' to enable fixed point types}}
+
+// Cannot use fixed point suffixes
+int accum_int = 10k; // expected-error{{invalid suffix 'k' on integer constant}}
+int fract_int = 10r; // expected-error{{invalid suffix 'r' on integer constant}}
+float accum_flt = 10.0k; // expected-error{{invalid suffix 'k' on floating constant}}
+float fract_flt = 10.0r; // expected-error{{invalid suffix 'r' on floating constant}}
diff --git a/test/Frontend/fixed_point_same_fbits.c b/test/Frontend/fixed_point_same_fbits.c
new file mode 100644
index 000000000000..1d116b7dfa21
--- /dev/null
+++ b/test/Frontend/fixed_point_same_fbits.c
@@ -0,0 +1,28 @@
+// RUN: %clang -ffixed-point -S -emit-llvm -o - %s | FileCheck %s -check-prefix=DEFAULT
+// RUN: %clang_cc1 -ffixed-point -fpadding-on-unsigned-fixed-point -S -emit-llvm -o - %s | FileCheck %s -check-prefix=SAME
+
+/* The scale for unsigned fixed point types should be the same as that of signed
+ * fixed point types when -fsame-fbits is enabled. */
+
+void func() {
+ unsigned short _Accum u_short_accum = 0.5uhk;
+ unsigned _Accum u_accum = 0.5uk;
+ unsigned long _Accum u_long_accum = 0.5ulk;
+ unsigned short _Fract u_short_fract = 0.5uhr;
+ unsigned _Fract u_fract = 0.5ur;
+ unsigned long _Fract u_long_fract = 0.5ulr;
+
+// DEFAULT: store i16 128, i16* {{.*}}, align 2
+// DEFAULT: store i32 32768, i32* {{.*}}, align 4
+// DEFAULT: store i64 2147483648, i64* {{.*}}, align 8
+// DEFAULT: store i8 -128, i8* {{.*}}, align 1
+// DEFAULT: store i16 -32768, i16* {{.*}}, align 2
+// DEFAULT: store i32 -2147483648, i32* {{.*}}, align 4
+
+// SAME: store i16 64, i16* {{.*}}, align 2
+// SAME: store i32 16384, i32* {{.*}}, align 4
+// SAME: store i64 1073741824, i64* {{.*}}, align 8
+// SAME: store i8 64, i8* {{.*}}, align 1
+// SAME: store i16 16384, i16* {{.*}}, align 2
+// SAME: store i32 1073741824, i32* {{.*}}, align 4
+}
diff --git a/test/Frontend/ftime-report-template-decl.cpp b/test/Frontend/ftime-report-template-decl.cpp
new file mode 100644
index 000000000000..9ba9107b9804
--- /dev/null
+++ b/test/Frontend/ftime-report-template-decl.cpp
@@ -0,0 +1,159 @@
+// RUN: %clang_cc1 %s -emit-llvm -o - -ftime-report 2>&1 | FileCheck %s
+// RUN: %clang_cc1 %s -emit-llvm -o - -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING -ftime-report 2>&1 | FileCheck %s
+
+// Template function declarations
+template <typename T>
+void foo();
+template <typename T, typename U>
+void foo();
+
+// Template function definitions.
+template <typename T>
+void foo() {}
+
+// Template class (forward) declarations
+template <typename T>
+struct A;
+template <typename T, typename U>
+struct b;
+template <typename>
+struct C;
+template <typename, typename>
+struct D;
+
+// Forward declarations with default parameters?
+template <typename T = int>
+class X1;
+template <typename = int>
+class X2;
+
+// Forward declarations w/template template parameters
+template <template <typename> class T>
+class TTP1;
+template <template <typename> class>
+class TTP2;
+template <template <typename X, typename Y> class T>
+class TTP5;
+
+// Forward declarations with non-type params
+template <int>
+class NTP0;
+template <int N>
+class NTP1;
+template <int N = 5>
+class NTP2;
+template <int = 10>
+class NTP3;
+template <unsigned int N = 12u>
+class NTP4;
+template <unsigned int = 12u>
+class NTP5;
+template <unsigned = 15u>
+class NTP6;
+template <typename T, T Obj>
+class NTP7;
+
+// Template class declarations
+template <typename T>
+struct A {};
+template <typename T, typename U>
+struct B {};
+
+namespace PR6184 {
+namespace N {
+template <typename T>
+void bar(typename T::x);
+}
+
+template <typename T>
+void N::bar(typename T::x) {}
+}
+
+// This PR occurred only in template parsing mode.
+namespace PR17637 {
+template <int>
+struct L {
+ template <typename T>
+ struct O {
+ template <typename U>
+ static void Fun(U);
+ };
+};
+
+template <int k>
+template <typename T>
+template <typename U>
+void L<k>::O<T>::Fun(U) {}
+
+void Instantiate() { L<0>::O<int>::Fun(0); }
+}
+
+namespace explicit_partial_specializations {
+typedef char (&oneT)[1];
+typedef char (&twoT)[2];
+typedef char (&threeT)[3];
+typedef char (&fourT)[4];
+typedef char (&fiveT)[5];
+typedef char (&sixT)[6];
+
+char one[1];
+char two[2];
+char three[3];
+char four[4];
+char five[5];
+char six[6];
+
+template <bool b>
+struct bool_ { typedef int type; };
+template <>
+struct bool_<false> {};
+
+#define XCAT(x, y) x##y
+#define CAT(x, y) XCAT(x, y)
+#define sassert(_b_) bool_<(_b_)>::type CAT(var, __LINE__);
+
+template <int>
+struct L {
+ template <typename T>
+ struct O {
+ template <typename U>
+ static oneT Fun(U);
+ };
+};
+template <int k>
+template <typename T>
+template <typename U>
+oneT L<k>::O<T>::Fun(U) { return one; }
+
+template <>
+template <>
+template <typename U>
+oneT L<0>::O<char>::Fun(U) { return one; }
+
+void Instantiate() {
+ sassert(sizeof(L<0>::O<int>::Fun(0)) == sizeof(one));
+ sassert(sizeof(L<0>::O<char>::Fun(0)) == sizeof(one));
+}
+}
+
+template <class>
+struct Foo {
+ template <class _Other>
+ using rebind_alloc = _Other;
+};
+template <class _Alloc>
+struct _Wrap_alloc {
+ template <class _Other>
+ using rebind_alloc = typename Foo<_Alloc>::template rebind_alloc<_Other>;
+ template <class>
+ using rebind = _Wrap_alloc;
+};
+_Wrap_alloc<int>::rebind<int> w;
+
+// CHECK: Miscellaneous Ungrouped Timers
+// CHECK-DAG: LLVM IR Generation Time
+// CHECK-DAG: Code Generation Time
+// CHECK: Total
+// CHECK: Clang front-end time report
+// CHECK: Clang front-end timer
+// CHECK: Total
diff --git a/test/Frontend/gnu-mcount.c b/test/Frontend/gnu-mcount.c
index 3953d2415382..baac555d1394 100644
--- a/test/Frontend/gnu-mcount.c
+++ b/test/Frontend/gnu-mcount.c
@@ -59,7 +59,7 @@ int f() {
// CHECK-ARM-EABI-FREEBSD-NOT: attributes #{{[0-9]+}} = { {{.*}}"instrument-function-entry-inlined"="\01__gnu_mcount_nc"{{.*}} }
// CHECK-ARM64-EABI-FREEBSD: attributes #{{[0-9]+}} = { {{.*}}"instrument-function-entry-inlined"=".mcount"{{.*}} }
// CHECK-ARM64-EABI-FREEBSD-NOT: attributes #{{[0-9]+}} = { {{.*}}"instrument-function-entry-inlined"="\01__gnu_mcount_nc"{{.*}} }
-// CHECK-ARM-EABI-NETBSD: attributes #{{[0-9]+}} = { {{.*}}"instrument-function-entry-inlined"="_mcount"{{.*}} }
+// CHECK-ARM-EABI-NETBSD: attributes #{{[0-9]+}} = { {{.*}}"instrument-function-entry-inlined"="__mcount"{{.*}} }
// CHECK-ARM-EABI-NETBSD-NOT: attributes #{{[0-9]+}} = { {{.*}}"instrument-function-entry-inlined"="\01__gnu_mcount_nc"{{.*}} }
// CHECK-ARM-EABI-OPENBSD: attributes #{{[0-9]+}} = { {{.*}}"instrument-function-entry-inlined"="__mcount"{{.*}} }
// CHECK-ARM-EABI-OPENBSD-NOT: attributes #{{[0-9]+}} = { {{.*}}"instrument-function-entry-inlined"="\01__gnu_mcount_nc"{{.*}} }
diff --git a/test/Frontend/nostdlib-for-asmpp.s b/test/Frontend/nostdlib-for-asmpp.s
new file mode 100644
index 000000000000..330fee32a361
--- /dev/null
+++ b/test/Frontend/nostdlib-for-asmpp.s
@@ -0,0 +1,5 @@
+// RUN: %clang -cc1 -x assembler-with-cpp -triple arm64-apple-ios6.0.0 -isysroot %S/doesnotexist -std=c++11 -v %s 2>&1 | FileCheck %s
+// The C++ stdlib path should not be included for an assembly source.
+
+// CHECK-NOT: usr/include/c++/
+// CHECK-NOT: include path for stdlibc++ headers not found; pass '-std=libc++' on the command line to use the libc++ standard library instead
diff --git a/test/Frontend/opencl.cl b/test/Frontend/opencl.cl
index 95b5f1471625..facc735330d4 100644
--- a/test/Frontend/opencl.cl
+++ b/test/Frontend/opencl.cl
@@ -1,24 +1,33 @@
-// RUN: %clang_cc1 %s -verify -fsyntax-only
-// RUN: %clang_cc1 %s -verify -fsyntax-only -cl-std=CL1.1
-// RUN: %clang_cc1 %s -verify -fsyntax-only -cl-std=CL1.2
-// RUN: %clang_cc1 %s -verify -fsyntax-only -cl-std=CL2.0
-// RUN: %clang_cc1 %s -verify -fsyntax-only -fblocks -DBLOCKS
-// RUN: %clang_cc1 %s -verify -fsyntax-only -cl-std=CL1.1 -fblocks -DBLOCKS
-// RUN: %clang_cc1 %s -verify -fsyntax-only -cl-std=CL1.2 -fblocks -DBLOCKS
-// RUN: %clang_cc1 %s -triple amdgcn--amdhsa -x c -std=c99 -verify -fsyntax-only
+// RUN: %clang_cc1 %s -verify -fsyntax-only -DSYNTAX
+// RUN: %clang_cc1 %s -verify -fsyntax-only -cl-std=CL1.1 -DSYNTAX
+// RUN: %clang_cc1 %s -verify -fsyntax-only -cl-std=CL1.2 -DSYNTAX
+// RUN: %clang_cc1 %s -verify -fsyntax-only -cl-std=CL2.0 -DSYNTAX
+// RUN: %clang_cc1 %s -verify -fsyntax-only -cl-std=c++ -DSYNTAX
+// RUN: %clang_cc1 %s -verify -fsyntax-only -fblocks -DBLOCKS -DSYNTAX
+// RUN: %clang_cc1 %s -verify -fsyntax-only -cl-std=CL1.1 -fblocks -DBLOCKS -DSYNTAX
+// RUN: %clang_cc1 %s -verify -fsyntax-only -cl-std=CL1.2 -fblocks -DBLOCKS -DSYNTAX
+// RUN: %clang_cc1 %s -triple amdgcn--amdhsa -x c -std=c99 -verify -fsyntax-only -DSYNTAX
// RUN: %clang_cc1 -cl-std=CL1.1 -cl-strict-aliasing -fblocks %s 2>&1 | FileCheck --check-prefix=CHECK-INVALID-OPENCL-VERSION11 %s
// RUN: %clang_cc1 -cl-std=CL1.2 -cl-strict-aliasing -fblocks %s 2>&1 | FileCheck --check-prefix=CHECK-INVALID-OPENCL-VERSION12 %s
// RUN: %clang_cc1 -cl-std=CL2.0 -cl-strict-aliasing %s 2>&1 | FileCheck --check-prefix=CHECK-INVALID-OPENCL-VERSION20 %s
+#ifdef SYNTAX
+class test{
+int member;
+};
+#ifndef __OPENCL_CPP_VERSION__
+//expected-error@-4{{unknown type name 'class'}}
+//expected-error@-5{{expected ';' after top level declarator}}
+#endif
+#endif
+
void f(void (^g)(void)) {
-#ifdef __OPENCL_C_VERSION__
-#if __OPENCL_C_VERSION__ < CL_VERSION_2_0 && !defined(BLOCKS)
- // expected-error@-3{{blocks support disabled - compile with -fblocks or for OpenCL 2.0 or above}}
-#else
- // expected-no-diagnostics
+#if defined(__OPENCL_C_VERSION__) || defined(__OPENCL_CPP_VERSION__)
+#if !defined(BLOCKS) && (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ != CL_VERSION_2_0)
+ // expected-error@-3{{blocks support disabled - compile with -fblocks or for OpenCL 2.0}}
#endif
#else
- // expected-error@-8{{blocks support disabled - compile with -fblocks or pick a deployment target that supports them}}
+ // expected-error@-6{{blocks support disabled - compile with -fblocks or pick a deployment target that supports them}}
#endif
}
diff --git a/test/Frontend/print-header-includes.c b/test/Frontend/print-header-includes.c
index 045c02b941bc..7da56e23d708 100644
--- a/test/Frontend/print-header-includes.c
+++ b/test/Frontend/print-header-includes.c
@@ -5,16 +5,24 @@
// CHECK: . {{.*test.h}}
// CHECK: .. {{.*test2.h}}
-// RUN: %clang_cc1 -I%S -include Inputs/test3.h -E --show-includes -o /dev/null %s | \
-// RUN: FileCheck --strict-whitespace --check-prefix=MS %s
-// MS-NOT: <command line>
-// MS: Note: including file: {{[^ ]*test3.h}}
-// MS: Note: including file: {{[^ ]*test.h}}
-// MS: Note: including file: {{[^ ]*test2.h}}
-// MS-NOT: Note
+// RUN: %clang_cc1 -I%S -include Inputs/test3.h --show-includes -o /dev/null %s | \
+// RUN: FileCheck --strict-whitespace --check-prefix=MS-STDOUT %s
+// MS-STDOUT-NOT: <command line>
+// MS-STDOUT: Note: including file: {{[^ ]*test3.h}}
+// MS-STDOUT: Note: including file: {{[^ ]*test.h}}
+// MS-STDOUT: Note: including file: {{[^ ]*test2.h}}
+// MS-STDOUT-NOT: Note
+
+// RUN: %clang_cc1 -I%S -include Inputs/test3.h -E --show-includes -o /dev/null %s 2> %t.stderr
+// RUN: FileCheck --strict-whitespace --check-prefix=MS-STDERR < %t.stderr %s
+// MS-STDERR-NOT: <command line>
+// MS-STDERR: Note: including file: {{[^ ]*test3.h}}
+// MS-STDERR: Note: including file: {{[^ ]*test.h}}
+// MS-STDERR: Note: including file: {{[^ ]*test2.h}}
+// MS-STDERR-NOT: Note
// RUN: echo "fun:foo" > %t.blacklist
-// RUN: %clang_cc1 -I%S -fsanitize=address -fdepfile-entry=%t.blacklist -E --show-includes -o /dev/null %s | \
+// RUN: %clang_cc1 -I%S -fsanitize=address -fdepfile-entry=%t.blacklist --show-includes -o /dev/null %s | \
// RUN: FileCheck --strict-whitespace --check-prefix=MS-BLACKLIST %s
// MS-BLACKLIST: Note: including file: {{[^ ]*\.blacklist}}
// MS-BLACKLIST: Note: including file: {{[^ ]*test.h}}
diff --git a/test/Frontend/region-pragmas.c b/test/Frontend/region-pragmas.c
new file mode 100644
index 000000000000..8d929e8414fd
--- /dev/null
+++ b/test/Frontend/region-pragmas.c
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -Wall -verify %s
+// expected-no-diagnostics
+
+#pragma region foo
+#pragma endregion foo
diff --git a/test/Frontend/rewrite-includes-messages.c b/test/Frontend/rewrite-includes-messages.c
index f93fe72e58d5..a3a5cb2eae6c 100644
--- a/test/Frontend/rewrite-includes-messages.c
+++ b/test/Frontend/rewrite-includes-messages.c
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -E -frewrite-includes %s -I%S/Inputs/ | %clang_cc1 -Wall -fsyntax-only -Wunused-macros -x c - 2>&1 > %t.1
// RUN: %clang_cc1 -I%S/Inputs/ -Wall -Wunused-macros -fsyntax-only %s 2>&1 > %t.2
-// RUN: diff %t.1 %t.2 -u
+// RUN: diff -u %t.1 %t.2
// expected-no-diagnostics
#include "rewrite-includes-messages.h"
diff --git a/test/Frontend/rewrite-includes.c b/test/Frontend/rewrite-includes.c
index bed87efa1f7a..630e761cab2f 100644
--- a/test/Frontend/rewrite-includes.c
+++ b/test/Frontend/rewrite-includes.c
@@ -1,5 +1,5 @@
-// RUN: not %clang_cc1 -verify -E -frewrite-includes -DFIRST -I %S/Inputs %s -o - | FileCheck -strict-whitespace %s
-// RUN: not %clang_cc1 -verify -E -frewrite-includes -P -DFIRST -I %S/Inputs %s -o - | FileCheck -check-prefix=CHECKNL -strict-whitespace %s
+// RUN: not %clang_cc1 -verify -E -frewrite-includes -DFIRST -I %S/Inputs -I %S/Inputs/NextIncludes %s -o - | FileCheck -strict-whitespace %s
+// RUN: not %clang_cc1 -verify -E -frewrite-includes -P -DFIRST -I %S/Inputs -I %S/Inputs/NextIncludes %s -o - | FileCheck -check-prefix=CHECKNL -strict-whitespace %s
// STARTCOMPARE
#define A(a,b) a ## b
A(1,2)
@@ -20,6 +20,7 @@ A(1,2)
#include "rewrite-includes7.h"
#include "rewrite-includes7.h"
#include "rewrite-includes8.h"
+#include "rewrite-includes9.h"
// ENDCOMPARE
// CHECK: {{^}}# 1 "{{.*}}rewrite-includes.c"{{$}}
// CHECK: {{^}}// STARTCOMPARE{{$}}
@@ -109,7 +110,7 @@ A(1,2)
// CHECK-NEXT: {{^}}#endif /* expanded by -frewrite-includes */{{$}}
// CHECK-NEXT: {{^}}# 22 "{{.*}}rewrite-includes.c"{{$}}
// CHECK-NEXT: {{^}}# 1 "{{.*[/\\]Inputs(/|\\\\)}}rewrite-includes8.h" 1{{$}}
-// CHECK-NEXT: {{^}}#if (1)/*__has_include_next(<rewrite-includes8.h>)*/{{$}}
+// CHECK-NEXT: {{^}}#if (0)/*__has_include_next(<rewrite-includes8.h>)*/{{$}}
// CHECK-NEXT: {{^}}#elif (0)/*__has_include(<rewrite-includes8.hfail>)*/{{$}}
// CHECK-NEXT: {{^}}# 3 "{{.*[/\\]Inputs(/|\\\\)}}rewrite-includes8.h"{{$}}
// CHECK-NEXT: {{^}}#endif{{$}}
@@ -118,6 +119,22 @@ A(1,2)
// CHECK-NEXT: {{^}}#endif{{$}}
// CHECK-NEXT: {{^}}# 6 "{{.*[/\\]Inputs(/|\\\\)}}rewrite-includes8.h"{{$}}
// CHECK-NEXT: {{^}}# 23 "{{.*}}rewrite-includes.c" 2{{$}}
+// CHECK-NEXT: {{^}}#if 0 /* expanded by -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}#include "rewrite-includes9.h"{{$}}
+// CHECK-NEXT: {{^}}#endif /* expanded by -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}# 23 "{{.*}}rewrite-includes.c"{{$}}
+// CHECK-NEXT: {{^}}# 1 "{{.*[/\\]Inputs(/|\\\\)}}rewrite-includes9.h" 1{{$}}
+// CHECK-NEXT: {{^}}#if (1)/*__has_include_next(<rewrite-includes9.h>)*/{{$}}
+// CHECK-NEXT: {{^}}#if 0 /* expanded by -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}#include_next <rewrite-includes9.h>{{$}}
+// CHECK-NEXT: {{^}}#endif /* expanded by -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}# 2 "{{.*[/\\]Inputs(/|\\\\)}}rewrite-includes9.h"{{$}}
+// CHECK-NEXT: {{^}}# 1 "{{.*[/\\]Inputs(/|\\\\)NextIncludes(/|\\\\)}}rewrite-includes9.h" 1{{$}}
+// CHECK-NEXT: {{^}}included_line9{{$}}
+// CHECK-NEXT: {{^}}# 3 "{{.*[/\\]Inputs(/|\\\\)}}rewrite-includes9.h" 2{{$}}
+// CHECK-NEXT: {{^}}#endif{{$}}
+// CHECK-NEXT: {{^}}# 4 "{{.*[/\\]Inputs(/|\\\\)}}rewrite-includes9.h"{{$}}
+// CHECK-NEXT: {{^}}# 24 "{{.*}}rewrite-includes.c" 2{{$}}
// CHECK-NEXT: {{^}}// ENDCOMPARE{{$}}
// CHECKNL: {{^}}// STARTCOMPARE{{$}}
@@ -176,9 +193,18 @@ A(1,2)
// CHECKNL-NEXT: {{^}}#if 0 /* expanded by -frewrite-includes */{{$}}
// CHECKNL-NEXT: {{^}}#include "rewrite-includes8.h"{{$}}
// CHECKNL-NEXT: {{^}}#endif /* expanded by -frewrite-includes */{{$}}
-// CHECKNL-NEXT: {{^}}#if (1)/*__has_include_next(<rewrite-includes8.h>)*/{{$}}
+// CHECKNL-NEXT: {{^}}#if (0)/*__has_include_next(<rewrite-includes8.h>)*/{{$}}
// CHECKNL-NEXT: {{^}}#elif (0)/*__has_include(<rewrite-includes8.hfail>)*/{{$}}
// CHECKNL-NEXT: {{^}}#endif{{$}}
// CHECKNL-NEXT: {{^}}#if !(1)/*__has_include("rewrite-includes8.h")*/{{$}}
// CHECKNL-NEXT: {{^}}#endif{{$}}
+// CHECKNL-NEXT: {{^}}#if 0 /* expanded by -frewrite-includes */{{$}}
+// CHECKNL-NEXT: {{^}}#include "rewrite-includes9.h"{{$}}
+// CHECKNL-NEXT: {{^}}#endif /* expanded by -frewrite-includes */{{$}}
+// CHECKNL-NEXT: {{^}}#if (1)/*__has_include_next(<rewrite-includes9.h>)*/{{$}}
+// CHECKNL-NEXT: {{^}}#if 0 /* expanded by -frewrite-includes */{{$}}
+// CHECKNL-NEXT: {{^}}#include_next <rewrite-includes9.h>{{$}}
+// CHECKNL-NEXT: {{^}}#endif /* expanded by -frewrite-includes */{{$}}
+// CHECKNL-NEXT: {{^}}included_line9{{$}}
+// CHECKNL-NEXT: {{^}}#endif{{$}}
// CHECKNL-NEXT: {{^}}// ENDCOMPARE{{$}}
diff --git a/test/Frontend/stdlang.c b/test/Frontend/stdlang.c
index 9c3c3078aaf2..2b24c2dfea31 100644
--- a/test/Frontend/stdlang.c
+++ b/test/Frontend/stdlang.c
@@ -4,6 +4,7 @@
// RUN: %clang_cc1 -x cl -cl-std=cl1.1 -DOPENCL %s
// RUN: %clang_cc1 -x cl -cl-std=cl1.2 -DOPENCL %s
// RUN: %clang_cc1 -x cl -cl-std=cl2.0 -DOPENCL %s
+// RUN: %clang_cc1 -x cl -cl-std=c++ -DOPENCL %s
// RUN: %clang_cc1 -x cl -cl-std=CL -DOPENCL %s
// RUN: %clang_cc1 -x cl -cl-std=CL1.1 -DOPENCL %s
// RUN: %clang_cc1 -x cl -cl-std=CL1.2 -DOPENCL %s
diff --git a/test/Frontend/unknown-arg.c b/test/Frontend/unknown-arg.c
new file mode 100644
index 000000000000..00f2da6242c7
--- /dev/null
+++ b/test/Frontend/unknown-arg.c
@@ -0,0 +1,9 @@
+// RUN: not %clang_cc1 %s -E --helium 2>&1 | \
+// RUN: FileCheck %s
+// RUN: not %clang_cc1 %s -E --hel[ 2>&1 | \
+// RUN: FileCheck %s --check-prefix=DID-YOU-MEAN
+// RUN: not %clang %s -E -Xclang --hel[ 2>&1 | \
+// RUN: FileCheck %s --check-prefix=DID-YOU-MEAN
+
+// CHECK: error: unknown argument: '--helium'
+// DID-YOU-MEAN: error: unknown argument '--hel[', did you mean '--help'?
diff --git a/test/Frontend/warning-stdlibcxx-darwin.cpp b/test/Frontend/warning-stdlibcxx-darwin.cpp
new file mode 100644
index 000000000000..3c132b6a833b
--- /dev/null
+++ b/test/Frontend/warning-stdlibcxx-darwin.cpp
@@ -0,0 +1,5 @@
+// RUN: %clang -cc1 -triple arm64-apple-ios6.0.0 -isysroot %S/doesnotexist %s 2>&1 | FileCheck %s
+// RUN: %clang -cc1 -triple arm64-apple-ios6.0.0 -isysroot %S/doesnotexist -stdlib=libc++ %s -verify
+// CHECK: include path for stdlibc++ headers not found; pass '-std=libc++' on the command line to use the libc++ standard library instead
+
+// expected-no-diagnostics
diff --git a/test/Frontend/windows-exceptions.cpp b/test/Frontend/windows-exceptions.cpp
new file mode 100644
index 000000000000..56316872be48
--- /dev/null
+++ b/test/Frontend/windows-exceptions.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -triple i686--windows-msvc -fsyntax-only %s
+// RUN: not %clang_cc1 -triple i686--windows-msvc -fsyntax-only -fdwarf-exceptions %s 2>&1 | FileCheck -check-prefix=MSVC-X86-DWARF %s
+// RUN: not %clang_cc1 -triple i686--windows-msvc -fsyntax-only -fseh-exceptions %s 2>&1 | FileCheck -check-prefix=MSVC-X86-SEH %s
+// RUN: not %clang_cc1 -triple i686--windows-msvc -fsyntax-only -fsjlj-exceptions %s 2>&1 | FileCheck -check-prefix=MSVC-X86-SJLJ %s
+
+// RUN: %clang_cc1 -triple x86_64--windows-msvc -fsyntax-only %s
+// RUN: not %clang_cc1 -triple x86_64--windows-msvc -fsyntax-only -fdwarf-exceptions %s 2>&1 | FileCheck -check-prefix=MSVC-X64-DWARF %s
+// RUN: not %clang_cc1 -triple x86_64--windows-msvc -fsyntax-only -fseh-exceptions %s 2>&1 | FileCheck -check-prefix=MSVC-X64-SEH %s
+// RUN: not %clang_cc1 -triple x86_64--windows-msvc -fsyntax-only -fsjlj-exceptions %s 2>&1 | FileCheck -check-prefix=MSVC-X64-SJLJ %s
+
+// RUN: %clang_cc1 -triple i686--windows-gnu -fsyntax-only %s
+// RUN: %clang_cc1 -triple i686--windows-gnu -fsyntax-only -fdwarf-exceptions %s
+// RUN: %clang_cc1 -triple i686--windows-gnu -fsyntax-only -fseh-exceptions %s
+// RUN: %clang_cc1 -triple i686--windows-gnu -fsyntax-only -fsjlj-exceptions %s
+
+// RUN: %clang_cc1 -triple x86_64--windows-gnu -fsyntax-only %s
+// RUN: %clang_cc1 -triple x86_64--windows-gnu -fsyntax-only -fdwarf-exceptions %s
+// RUN: %clang_cc1 -triple x86_64--windows-gnu -fsyntax-only -fseh-exceptions %s
+// RUN: %clang_cc1 -triple x86_64--windows-gnu -fsyntax-only -fsjlj-exceptions %s
+
+// MSVC-X86-DWARF: error: invalid exception model 'fdwarf-exceptions' for target 'i686--windows-msvc'
+// MSVC-X86-SEH: error: invalid exception model 'fseh-exceptions' for target 'i686--windows-msvc'
+// MSVC-X86-SJLJ: error: invalid exception model 'fsjlj-exceptions' for target 'i686--windows-msvc'
+
+// MSVC-X64-DWARF: error: invalid exception model 'fdwarf-exceptions' for target 'x86_64--windows-msvc'
+// MSVC-X64-SEH: error: invalid exception model 'fseh-exceptions' for target 'x86_64--windows-msvc'
+// MSVC-X64-SJLJ: error: invalid exception model 'fsjlj-exceptions' for target 'x86_64--windows-msvc'
diff --git a/test/Frontend/x86-target-cpu.c b/test/Frontend/x86-target-cpu.c
index b5103d238c9d..0ec301f4426e 100644
--- a/test/Frontend/x86-target-cpu.c
+++ b/test/Frontend/x86-target-cpu.c
@@ -13,7 +13,8 @@
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu skylake-avx512 -verify %s
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu skx -verify %s
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu cannonlake -verify %s
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu icelake -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu icelake-client -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu icelake-server -verify %s
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu knl -verify %s
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu knm -verify %s
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu bonnell -verify %s
diff --git a/test/Headers/ms-intrin.cpp b/test/Headers/ms-intrin.cpp
index b0fef9cc06a7..d8a4d382eb37 100644
--- a/test/Headers/ms-intrin.cpp
+++ b/test/Headers/ms-intrin.cpp
@@ -42,6 +42,8 @@ void f() {
__stosw(0, 0, 0);
#ifdef _M_X64
+ __shiftleft128(1, 2, 3);
+ __shiftright128(1, 2, 3);
__movsq(0, 0, 0);
__stosq(0, 0, 0);
#endif
diff --git a/test/Headers/ms-null-ms-header-vs-stddef.cpp b/test/Headers/ms-null-ms-header-vs-stddef.cpp
index e3910896713c..f39a0cafaa0d 100644
--- a/test/Headers/ms-null-ms-header-vs-stddef.cpp
+++ b/test/Headers/ms-null-ms-header-vs-stddef.cpp
@@ -2,7 +2,7 @@
// RUN: %clang_cc1 -fsyntax-only -triple i386-mingw32 %s
// Something in MSVC's headers (pulled in e.g. by <crtdefs.h>) defines __null
-// to something, mimick that.
+// to something, mimic that.
#define __null
#include <stddef.h>
diff --git a/test/Headers/pconfigintin.c b/test/Headers/pconfigintin.c
new file mode 100644
index 000000000000..43a30acbdcc2
--- /dev/null
+++ b/test/Headers/pconfigintin.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 %s -ffreestanding -triple x86_64-unknown-unknown -target-feature +pconfig -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-64
+// RUN: %clang_cc1 %s -ffreestanding -triple i386 -target-feature +pconfig -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-32
+
+#include <immintrin.h>
+#include <stdint.h>
+#include <stddef.h>
+
+uint32_t test_pconfig(uint32_t leaf, size_t data[3]) {
+// CHECK-64: call { i32, i64, i64, i64 } asm "pconfig", "={ax},={bx},={cx},={dx},{ax},{bx},{cx},{dx},~{cc},~{dirflag},~{fpsr},~{flags}"(i32 %{{.*}}, i64 %{{.*}}, i64 %{{.*}}, i64 %{{.*}})
+// CHECK-32: call { i32, i32, i32, i32 } asm "pconfig", "={ax},={bx},={cx},={dx},{ax},{bx},{cx},{dx},~{cc},~{dirflag},~{fpsr},~{flags}"(i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}})
+ return _pconfig_u32(leaf, data);
+}
diff --git a/test/Headers/sgxintrin.c b/test/Headers/sgxintrin.c
new file mode 100644
index 000000000000..ce0d408f5d65
--- /dev/null
+++ b/test/Headers/sgxintrin.c
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 %s -ffreestanding -triple x86_64-unknown-unknown -target-feature +sgx -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-64
+// RUN: %clang_cc1 %s -ffreestanding -triple i386 -target-feature +sgx -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-32
+
+#include <immintrin.h>
+#include <stdint.h>
+#include <stddef.h>
+
+uint32_t test_encls(uint32_t leaf, size_t data[3]) {
+// CHECK-64: call { i32, i64, i64, i64 } asm "encls", "={ax},={bx},={cx},={dx},{ax},{bx},{cx},{dx},~{cc},~{dirflag},~{fpsr},~{flags}"(i32 %{{.*}}, i64 %{{.*}}, i64 %{{.*}}, i64 %{{.*}})
+// CHECK-32: call { i32, i32, i32, i32 } asm "encls", "={ax},={bx},={cx},={dx},{ax},{bx},{cx},{dx},~{cc},~{dirflag},~{fpsr},~{flags}"(i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}})
+
+ return _encls_u32(leaf, data);
+}
+
+uint32_t test_enclu(uint32_t leaf, size_t data[3]) {
+// CHECK-64: call { i32, i64, i64, i64 } asm "enclu", "={ax},={bx},={cx},={dx},{ax},{bx},{cx},{dx},~{cc},~{dirflag},~{fpsr},~{flags}"(i32 %{{.*}}, i64 %{{.*}}, i64 %{{.*}}, i64 %{{.*}})
+// CHECK-32: call { i32, i32, i32, i32 } asm "enclu", "={ax},={bx},={cx},={dx},{ax},{bx},{cx},{dx},~{cc},~{dirflag},~{fpsr},~{flags}"(i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}})
+
+ return _enclu_u32(leaf, data);
+}
+
+uint32_t test_enclv(uint32_t leaf, size_t data[3]) {
+// CHECK-64: call { i32, i64, i64, i64 } asm "enclv", "={ax},={bx},={cx},={dx},{ax},{bx},{cx},{dx},~{cc},~{dirflag},~{fpsr},~{flags}"(i32 %{{.*}}, i64 %{{.*}}, i64 %{{.*}}, i64 %{{.*}})
+// CHECK-32: call { i32, i32, i32, i32 } asm "enclv", "={ax},={bx},={cx},={dx},{ax},{bx},{cx},{dx},~{cc},~{dirflag},~{fpsr},~{flags}"(i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}})
+
+ return _enclv_u32(leaf, data);
+}
diff --git a/test/Headers/x86-intrinsics-headers-clean.cpp b/test/Headers/x86-intrinsics-headers-clean.cpp
new file mode 100644
index 000000000000..c75f0910f5da
--- /dev/null
+++ b/test/Headers/x86-intrinsics-headers-clean.cpp
@@ -0,0 +1,14 @@
+// Make sure the intrinsic headers compile cleanly with no warnings or errors.
+
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -Wsystem-headers \
+// RUN: -fsyntax-only -x c++ -Wno-ignored-attributes -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -Wsystem-headers \
+// RUN: -fsyntax-only -x c++ -Wno-ignored-attributes -target-feature +f16c \
+// RUN: -verify %s
+
+// expected-no-diagnostics
+
+// Dont' include mm_malloc.h. It's system specific.
+#define __MM_MALLOC_H
+
+#include <x86intrin.h>
diff --git a/test/Headers/x86intrin-2.c b/test/Headers/x86intrin-2.c
index 9be8545a2cd6..e6fd7c80446d 100644
--- a/test/Headers/x86intrin-2.c
+++ b/test/Headers/x86intrin-2.c
@@ -72,10 +72,6 @@ __mmask8 __attribute__((__target__("avx512vl"))) mm_cmpeq_epi32_mask_wrap(__m128
return _mm_cmpeq_epi32_mask(a, b);
}
-__m512i __attribute__((__target__("avx512bw"))) mm512_setzero_qi_wrap(void) {
- return _mm512_setzero_qi();
-}
-
__m512i __attribute__((__target__("avx512dq"))) mm512_mullo_epi64_wrap(__m512i a, __m512i b) {
return _mm512_mullo_epi64(a, b);
}
diff --git a/test/Import/attr/Inputs/S.cpp b/test/Import/attr/Inputs/S.cpp
new file mode 100644
index 000000000000..28d70c544a7c
--- /dev/null
+++ b/test/Import/attr/Inputs/S.cpp
@@ -0,0 +1,13 @@
+extern void f() __attribute__((const));
+
+struct S {
+ struct {
+ int a __attribute__((packed));
+ };
+};
+
+void stmt() {
+#pragma unroll
+ for (;;)
+ ;
+}
diff --git a/test/Import/attr/test.cpp b/test/Import/attr/test.cpp
new file mode 100644
index 000000000000..c9b2d6ed3433
--- /dev/null
+++ b/test/Import/attr/test.cpp
@@ -0,0 +1,26 @@
+// RUN: clang-import-test -dump-ast -import %S/Inputs/S.cpp -expression %s | FileCheck %s
+// CHECK: FunctionDecl
+// CHECK-SAME: S.cpp:1:1, col:38
+// CHECK-NEXT: ConstAttr
+// CHECK-SAME: col:32
+
+// CHECK: IndirectFieldDecl
+// CHECK-NEXT: Field
+// CHECK-NEXT: Field
+// CHECK-NEXT: PackedAttr
+// CHECK-SAME: col:26
+
+// CHECK: AttributedStmt
+// CHECK-NEXT: LoopHintAttr
+// CHECK-SAME: line:10:9
+
+extern void f() __attribute__((const));
+
+struct S;
+
+void stmt();
+
+void expr() {
+ f();
+ struct S s;
+}
diff --git a/test/Import/inherited-ctor-init-expr/Inputs/A.cpp b/test/Import/inherited-ctor-init-expr/Inputs/A.cpp
new file mode 100644
index 000000000000..27134333242f
--- /dev/null
+++ b/test/Import/inherited-ctor-init-expr/Inputs/A.cpp
@@ -0,0 +1,11 @@
+class A {
+public:
+ A(int a) : a(a) {}
+ int a;
+};
+class B : public A {
+ using A::A;
+};
+class C : public B {
+ C() : B(1) {}
+};
diff --git a/test/Import/inherited-ctor-init-expr/test.cpp b/test/Import/inherited-ctor-init-expr/test.cpp
new file mode 100644
index 000000000000..9e15e382edc1
--- /dev/null
+++ b/test/Import/inherited-ctor-init-expr/test.cpp
@@ -0,0 +1,6 @@
+// RUN: clang-import-test -dump-ast -expression=%s -import=%S/Inputs/A.cpp | FileCheck %s
+// CHECK: | | | `-CXXInheritedCtorInitExpr
+
+void foo() {
+ C c;
+}
diff --git a/test/Import/template-specialization/Inputs/T.cpp b/test/Import/template-specialization/Inputs/T.cpp
index b31e2439efeb..7eea95829048 100644
--- a/test/Import/template-specialization/Inputs/T.cpp
+++ b/test/Import/template-specialization/Inputs/T.cpp
@@ -12,3 +12,7 @@ template <> struct A<bool> {
int g;
};
};
+
+
+template <typename T> constexpr int f() { return 0; }
+template <> constexpr int f<int>() { return 4; }
diff --git a/test/Import/template-specialization/test.cpp b/test/Import/template-specialization/test.cpp
index 43996c53a77e..30df8187602d 100644
--- a/test/Import/template-specialization/test.cpp
+++ b/test/Import/template-specialization/test.cpp
@@ -1,7 +1,10 @@
// RUN: clang-import-test -import %S/Inputs/T.cpp -expression %s
-// XFAIL: *
+
void expr() {
A<int>::B b1;
A<bool>::B b2;
b1.f + b2.g;
}
+
+static_assert(f<char>() == 0, "");
+static_assert(f<int>() == 4, "");
diff --git a/test/Index/Core/index-macros.c b/test/Index/Core/index-macros.c
new file mode 100644
index 000000000000..61e7e7617544
--- /dev/null
+++ b/test/Index/Core/index-macros.c
@@ -0,0 +1,12 @@
+// RUN: c-index-test core -print-source-symbols -- %s | FileCheck %s
+
+// CHECK: [[@LINE+1]]:9 | macro/C | X1 | c:index-macros.c@157@macro@X1 | Def |
+#define X1 1
+// CHECK: [[@LINE+1]]:9 | macro/C | DEF | c:index-macros.c@251@macro@DEF | Def |
+#define DEF(x) int x
+// CHECK: [[@LINE+1]]:8 | macro/C | X1 | c:index-macros.c@157@macro@X1 | Undef |
+#undef X1
+
+// CHECK: [[@LINE+2]]:1 | macro/C | DEF | c:index-macros.c@251@macro@DEF | Ref |
+// CHECK: [[@LINE+1]]:5 | variable/C | i | c:@i | {{.*}} | Def | rel: 0
+DEF(i);
diff --git a/test/Index/Core/index-pch.cpp b/test/Index/Core/index-pch.cpp
new file mode 100644
index 000000000000..8c5a92b612c4
--- /dev/null
+++ b/test/Index/Core/index-pch.cpp
@@ -0,0 +1,17 @@
+// RUN: c-index-test core -print-source-symbols -- %s -std=c++14 | FileCheck %s
+// RUN: %clang_cc1 -emit-pch %s -std=c++14 -o %t.pch
+// RUN: c-index-test core -print-source-symbols -module-file %t.pch | FileCheck %s
+
+// CHECK: [[@LINE+2]]:8 | struct(Gen)/C++ | DETECTOR | [[DETECTOR_USR:.*]] | {{.*}} | Def | rel: 0
+template <class _Default, class _AlwaysVoid, template <class...> class _Op, class... _Args>
+struct DETECTOR {
+ using value_t = int;
+};
+
+struct nonesuch {};
+
+// CHECK: [[@LINE+4]]:9 | type-alias/C++ | is_detected
+// CHECK: [[@LINE+3]]:32 | struct(Gen)/C++ | DETECTOR | [[DETECTOR_USR]] | {{.*}} | Ref,RelCont | rel: 1
+// CHECK-NEXT: RelCont | is_detected
+template <template<class...> class _Op, class... _Args>
+ using is_detected = typename DETECTOR<nonesuch, void, _Op, _Args...>::value_t;
diff --git a/test/Index/Inputs/crash-preamble-classes.h b/test/Index/Inputs/crash-preamble-classes.h
new file mode 100644
index 000000000000..a8fb5cede05d
--- /dev/null
+++ b/test/Index/Inputs/crash-preamble-classes.h
@@ -0,0 +1,9 @@
+struct Incomplete;
+
+struct X : Incomplete {
+ X();
+};
+
+struct Y : X {
+ using X::X;
+};
diff --git a/test/Index/Inputs/reparse-issue.h b/test/Index/Inputs/reparse-issue.h
new file mode 100644
index 000000000000..79f1d88a7fc3
--- /dev/null
+++ b/test/Index/Inputs/reparse-issue.h
@@ -0,0 +1,3 @@
+
+asdf;
+
diff --git a/test/Index/Inputs/reparse-issue.h-0 b/test/Index/Inputs/reparse-issue.h-0
new file mode 100644
index 000000000000..f004abf1f5f0
--- /dev/null
+++ b/test/Index/Inputs/reparse-issue.h-0
@@ -0,0 +1,4 @@
+//
+//
+asdf;
+
diff --git a/test/Index/Inputs/reparse-issue.h-1 b/test/Index/Inputs/reparse-issue.h-1
new file mode 100644
index 000000000000..9f9dde858d47
--- /dev/null
+++ b/test/Index/Inputs/reparse-issue.h-1
@@ -0,0 +1,5 @@
+//
+//
+//
+asdf;
+
diff --git a/test/Index/USR/linkage.cpp b/test/Index/USR/linkage.cpp
new file mode 100644
index 000000000000..fec80dace16e
--- /dev/null
+++ b/test/Index/USR/linkage.cpp
@@ -0,0 +1,7 @@
+// RUN: c-index-test core -print-source-symbols -- %s | FileCheck %s
+
+// Linkage decls are skipped in USRs for enclosed items.
+// Linkage decls themselves don't have USRs (no lines between ns and X).
+// CHECK: {{[0-9]+}}:11 | namespace/C++ | ns | c:@N@ns |
+// CHECK-NEXT: {{[0-9]+}}:33 | variable/C | X | c:@N@ns@X |
+namespace ns { extern "C" { int X; } }
diff --git a/test/Index/annotate-tokens-unexposed.cpp b/test/Index/annotate-tokens-unexposed.cpp
new file mode 100644
index 000000000000..3e5d79426e31
--- /dev/null
+++ b/test/Index/annotate-tokens-unexposed.cpp
@@ -0,0 +1,20 @@
+// RUN: c-index-test -test-annotate-tokens=%s:1:1:16:1 %s -target x86_64-pc-windows-msvc | FileCheck %s
+class Foo
+{
+public:
+ void step(int v);
+ Foo();
+};
+
+void bar()
+{
+ // Introduce a MSInheritanceAttr node on the CXXRecordDecl for Foo. The
+ // existance of this attribute should not mark all cursors for tokens in
+ // Foo as UnexposedAttr.
+ &Foo::step;
+}
+
+Foo::Foo()
+{}
+
+// CHECK-NOT: UnexposedAttr=
diff --git a/test/Index/annotate-tokens.cpp b/test/Index/annotate-tokens.cpp
index 460ab51dd959..67bdf6317aa6 100644
--- a/test/Index/annotate-tokens.cpp
+++ b/test/Index/annotate-tokens.cpp
@@ -37,7 +37,9 @@ class C {
~C();
};
-// RUN: c-index-test -test-annotate-tokens=%s:1:1:38:1 %s -fno-delayed-template-parsing | FileCheck %s
+auto test5(X) -> X;
+
+// RUN: c-index-test -test-annotate-tokens=%s:1:1:41:1 %s -std=c++14 -fno-delayed-template-parsing | FileCheck %s
// CHECK: Keyword: "struct" [1:1 - 1:7] StructDecl=bonk:1:8 (Definition)
// CHECK: Identifier: "bonk" [1:8 - 1:12] StructDecl=bonk:1:8 (Definition)
// CHECK: Punctuation: "{" [1:13 - 1:14] StructDecl=bonk:1:8 (Definition)
@@ -184,6 +186,14 @@ class C {
// CHECK: Punctuation: "}" [29:22 - 29:23] CompoundStmt=
// CHECK: Punctuation: "~" [37:3 - 37:4] CXXDestructor=~C:37:3
// CHECK: Identifier: "C" [37:4 - 37:5] CXXDestructor=~C:37:3
+// CHECK: Keyword: "auto" [40:1 - 40:5] FunctionDecl=test5:40:6
+// CHECK: Identifier: "test5" [40:6 - 40:11] FunctionDecl=test5:40:6
+// CHECK: Punctuation: "(" [40:11 - 40:12] FunctionDecl=test5:40:6
+// CHECK: Identifier: "X" [40:12 - 40:13] TypeRef=struct X:7:8
+// CHECK: Punctuation: ")" [40:13 - 40:14] FunctionDecl=test5:40:6
+// CHECK: Punctuation: "->" [40:15 - 40:17] FunctionDecl=test5:40:6
+// CHECK: Identifier: "X" [40:18 - 40:19] TypeRef=struct X:7:8
+// CHECK: Punctuation: ";" [40:19 - 40:20]
// RUN: env LIBCLANG_DISABLE_CRASH_RECOVERY=1 c-index-test -test-annotate-tokens=%s:32:1:32:13 %s | FileCheck %s -check-prefix=CHECK2
// CHECK2: Keyword: "if" [32:3 - 32:5] IfStmt=
diff --git a/test/Index/comment-objc-parameterized-classes.m b/test/Index/comment-objc-parameterized-classes.m
index 8ee5c6bd6487..fe14dcb3e7c5 100644
--- a/test/Index/comment-objc-parameterized-classes.m
+++ b/test/Index/comment-objc-parameterized-classes.m
@@ -13,7 +13,7 @@
@interface NSObject
@end
-// CHECK: <Declaration>@interface A &lt;__covariant T : id, U : NSObject *&gt; : NSObject
+// CHECK: <Declaration>@interface A&lt;__covariant T : id, U : NSObject *&gt; : NSObject
/// A
@interface A<__covariant T : id, U : NSObject *> : NSObject
@end
diff --git a/test/Index/complete-access-checks.cpp b/test/Index/complete-access-checks.cpp
index 7eec41ec5610..54d9640f6f59 100644
--- a/test/Index/complete-access-checks.cpp
+++ b/test/Index/complete-access-checks.cpp
@@ -36,10 +36,10 @@ void Y::doSomething() {
// CHECK-SUPER-ACCESS: CXXMethod:{ResultType void}{TypedText doSomething}{LeftParen (}{RightParen )} (34)
// CHECK-SUPER-ACCESS: CXXMethod:{ResultType void}{Informative X::}{TypedText func1}{LeftParen (}{RightParen )} (36)
-// CHECK-SUPER-ACCESS: CXXMethod:{ResultType void}{Informative X::}{TypedText func2}{LeftParen (}{RightParen )} (36) (inaccessible)
+// CHECK-SUPER-ACCESS: CXXMethod:{ResultType void}{Informative X::}{TypedText func2}{LeftParen (}{RightParen )} (36)
// CHECK-SUPER-ACCESS: CXXMethod:{ResultType void}{Informative X::}{TypedText func3}{LeftParen (}{RightParen )} (36) (inaccessible)
// CHECK-SUPER-ACCESS: FieldDecl:{ResultType int}{Informative X::}{TypedText member1} (37)
-// CHECK-SUPER-ACCESS: FieldDecl:{ResultType int}{Informative X::}{TypedText member2} (37) (inaccessible)
+// CHECK-SUPER-ACCESS: FieldDecl:{ResultType int}{Informative X::}{TypedText member2} (37)
// CHECK-SUPER-ACCESS: FieldDecl:{ResultType int}{Informative X::}{TypedText member3} (37) (inaccessible)
// CHECK-SUPER-ACCESS: CXXMethod:{ResultType Y &}{TypedText operator=}{LeftParen (}{Placeholder const Y &}{RightParen )} (79)
// CHECK-SUPER-ACCESS: CXXMethod:{ResultType X &}{Text X::}{TypedText operator=}{LeftParen (}{Placeholder const X &}{RightParen )} (81)
@@ -87,3 +87,26 @@ void f(P x, Q y) {
// CHECK-USING-ACCESSIBLE: ClassDecl:{TypedText Q}{Text ::} (75)
// CHECK-USING-ACCESSIBLE: CXXDestructor:{ResultType void}{Informative P::}{TypedText ~P}{LeftParen (}{RightParen )} (81)
// CHECK-USING-ACCESSIBLE: CXXDestructor:{ResultType void}{TypedText ~Q}{LeftParen (}{RightParen )} (79)
+
+class B {
+protected:
+ int member;
+};
+
+class C : private B {};
+
+
+class D : public C {
+ public:
+ void f(::B *b);
+};
+
+void D::f(::B *that) {
+ // RUN: c-index-test -code-completion-at=%s:106:9 %s | FileCheck -check-prefix=CHECK-PRIVATE-SUPER-THIS %s
+ this->;
+// CHECK-PRIVATE-SUPER-THIS: FieldDecl:{ResultType int}{Informative B::}{TypedText member} (37) (inaccessible)
+
+ // RUN: c-index-test -code-completion-at=%s:110:9 %s | FileCheck -check-prefix=CHECK-PRIVATE-SUPER-THAT %s
+ that->;
+// CHECK-PRIVATE-SUPER-THAT: FieldDecl:{ResultType int}{TypedText member} (35) (inaccessible)
+}
diff --git a/test/Index/complete-and-plugins.c b/test/Index/complete-and-plugins.c
new file mode 100644
index 000000000000..0592aaa9ef30
--- /dev/null
+++ b/test/Index/complete-and-plugins.c
@@ -0,0 +1,6 @@
+// RUN: c-index-test -code-completion-at=%s:7:1 -load %llvmshlibdir/PrintFunctionNames%pluginext -add-plugin print-fns %s | FileCheck %s
+// REQUIRES: plugins, examples
+// CHECK: macro definition:{{.*}}
+// CHECK-NOT: top-level-decl: "x"
+
+void x();
diff --git a/test/Index/complete-arrow-dot.cpp b/test/Index/complete-arrow-dot.cpp
new file mode 100644
index 000000000000..fb5efbe6e688
--- /dev/null
+++ b/test/Index/complete-arrow-dot.cpp
@@ -0,0 +1,54 @@
+struct X {
+ void doSomething();
+
+ int field;
+};
+
+void X::doSomething() {
+ // RUN: c-index-test -code-completion-at=%s:10:8 %s | FileCheck %s
+ // RUN: env CINDEXTEST_COMPLETION_INCLUDE_FIXITS=1 c-index-test -code-completion-at=%s:10:8 %s | FileCheck -check-prefix=CHECK-WITH-CORRECTION %s
+ this.;
+}
+
+void doSomething() {
+ // RUN: c-index-test -code-completion-at=%s:17:6 %s | FileCheck -check-prefix=CHECK-ARROW-TO-DOT %s
+ // RUN: env CINDEXTEST_COMPLETION_INCLUDE_FIXITS=1 c-index-test -code-completion-at=%s:17:6 %s | FileCheck -check-prefix=CHECK-ARROW-TO-DOT-WITH-CORRECTION %s
+ X x;
+ x->
+}
+
+// CHECK-NOT: CXXMethod:{ResultType void}{TypedText doSomething}{LeftParen (}{RightParen )} (34) (requires fix-it:{{.*}}
+// CHECK-NOT: FieldDecl:{ResultType int}{TypedText field} (35) (requires fix-it:{{.*}}
+// CHECK-NOT: CXXMethod:{ResultType X &}{TypedText operator=}{LeftParen (}{Placeholder const X &}{RightParen )} (79) (requires fix-it:{{.*}}
+// CHECK-NOT: CXXMethod:{ResultType X &}{TypedText operator=}{LeftParen (}{Placeholder X &&}{RightParen )} (79) (requires fix-it:{{.*}}
+// CHECK-NOT: StructDecl:{TypedText X}{Text ::} (75) (requires fix-it:{{.*}}
+// CHECK-NOT: CXXDestructor:{ResultType void}{TypedText ~X}{LeftParen (}{RightParen )} (79) (requires fix-it:{{.*}}
+// CHECK: Completion contexts:
+// CHECK-NEXT: Dot member access
+
+// CHECK-WITH-CORRECTION: CXXMethod:{ResultType void}{TypedText doSomething}{LeftParen (}{RightParen )} (34) (requires fix-it:{{.*}}
+// CHECK-WITH-CORRECTION-NEXT: FieldDecl:{ResultType int}{TypedText field} (35) (requires fix-it:{{.*}}
+// CHECK-WITH-CORRECTION-NEXT: CXXMethod:{ResultType X &}{TypedText operator=}{LeftParen (}{Placeholder const X &}{RightParen )} (79) (requires fix-it:{{.*}}
+// CHECK-WITH-CORRECTION-NEXT: CXXMethod:{ResultType X &}{TypedText operator=}{LeftParen (}{Placeholder X &&}{RightParen )} (79) (requires fix-it:{{.*}}
+// CHECK-WITH-CORRECTION-NEXT: StructDecl:{TypedText X}{Text ::} (75) (requires fix-it:{{.*}}
+// CHECK-WITH-CORRECTION-NEXT: CXXDestructor:{ResultType void}{TypedText ~X}{LeftParen (}{RightParen )} (79) (requires fix-it:{{.*}}
+// CHECK-WITH-CORRECTION-NEXT: Completion contexts:
+// CHECK-WITH-CORRECTION-NEXT: Dot member access
+
+// CHECK-ARROW-TO-DOT-NOT: CXXMethod:{ResultType void}{TypedText doSomething}{LeftParen (}{RightParen )} (34) (requires fix-it:{{.*}}
+// CHECK-ARROW-TO-DOT-NOT: FieldDecl:{ResultType int}{TypedText field} (35) (requires fix-it:{{.*}}
+// CHECK-ARROW-TO-DOT-NOT: CXXMethod:{ResultType X &}{TypedText operator=}{LeftParen (}{Placeholder const X &}{RightParen )} (79) (requires fix-it:{{.*}}
+// CHECK-ARROW-TO-DOT-NOT: CXXMethod:{ResultType X &}{TypedText operator=}{LeftParen (}{Placeholder X &&}{RightParen )} (79) (requires fix-it:{{.*}}
+// CHECK-ARROW-TO-DOT-NOT: StructDecl:{TypedText X}{Text ::} (75) (requires fix-it:{{.*}}
+// CHECK-ARROW-TO-DOT-NOT: CXXDestructor:{ResultType void}{TypedText ~X}{LeftParen (}{RightParen )} (79) (requires fix-it:{{.*}}
+// CHECK-ARROW-TO-DOT: Completion contexts:
+// CHECK-ARROW-TO-DOT-NEXT: Unknown
+
+// CHECK-ARROW-TO-DOT-WITH-CORRECTION: CXXMethod:{ResultType void}{TypedText doSomething}{LeftParen (}{RightParen )} (34) (requires fix-it:{{.*}}
+// CHECK-ARROW-TO-DOT-WITH-CORRECTION-NEXT: FieldDecl:{ResultType int}{TypedText field} (35) (requires fix-it:{{.*}}
+// CHECK-ARROW-TO-DOT-WITH-CORRECTION-NEXT: CXXMethod:{ResultType X &}{TypedText operator=}{LeftParen (}{Placeholder const X &}{RightParen )} (79) (requires fix-it:{{.*}}
+// CHECK-ARROW-TO-DOT-WITH-CORRECTION-NEXT: CXXMethod:{ResultType X &}{TypedText operator=}{LeftParen (}{Placeholder X &&}{RightParen )} (79) (requires fix-it:{{.*}}
+// CHECK-ARROW-TO-DOT-WITH-CORRECTION-NEXT: StructDecl:{TypedText X}{Text ::} (75) (requires fix-it:{{.*}}
+// CHECK-ARROW-TO-DOT-WITH-CORRECTION-NEXT: CXXDestructor:{ResultType void}{TypedText ~X}{LeftParen (}{RightParen )} (79) (requires fix-it:{{.*}}
+// CHECK-ARROW-TO-DOT-WITH-CORRECTION-NEXT: Completion contexts:
+// CHECK-ARROW-TO-DOT-WITH-CORRECTION-NEXT: Arrow member access
diff --git a/test/Index/complete-call.cpp b/test/Index/complete-call.cpp
index ca116485ac95..95bc8d49b2b9 100644
--- a/test/Index/complete-call.cpp
+++ b/test/Index/complete-call.cpp
@@ -112,6 +112,33 @@ struct Bar2 : public Bar {
}
};
+struct BarTemplates {
+ static void foo_1() {}
+ void foo_1(float) {}
+ static void foo_1(int) {}
+
+ template<class T1, class T2>
+ static void foo_1(T1 a, T2 b) { a + b; }
+
+ template<class T1, class T2>
+ void foo_1(T1 a, T2 b, float c) { a + b + c; }
+
+ template<class T1, class T2>
+ static void foo_1(T2 a, int b, T1 c) { a + b + c; }
+};
+
+void testTemplates() {
+ BarTemplates::foo_1();
+ BarTemplates b;
+ b.foo_1();
+}
+
+struct Bar2Template : public BarTemplates {
+ Bar2Template() {
+ BarTemplates::foo_1();
+ }
+};
+
// RUN: c-index-test -code-completion-at=%s:47:9 %s | FileCheck -check-prefix=CHECK-CC1 %s
// CHECK-CC1: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1)
// CHECK-CC1: Completion contexts:
@@ -864,3 +891,26 @@ struct Bar2 : public Bar {
// CHECK-CC62-NEXT: Nested name specifier
// CHECK-CC62-NEXT: Objective-C interface
+// RUN: c-index-test -code-completion-at=%s:131:23 %s | FileCheck -check-prefix=CHECK-CC63 %s
+// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1)
+// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter float}{RightParen )} (1)
+// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter int}{RightParen )} (1)
+// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{RightParen )} (1)
+// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{Comma , }{Placeholder float c}{RightParen )} (1)
+// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T2 a}{Comma , }{Placeholder int b}{Comma , }{Placeholder T1 c}{RightParen )} (1)
+
+// RUN: c-index-test -code-completion-at=%s:133:11 %s | FileCheck -check-prefix=CHECK-CC64 %s
+// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1)
+// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter float}{RightParen )} (1)
+// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter int}{RightParen )} (1)
+// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{RightParen )} (1)
+// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T2 a}{Comma , }{Placeholder int b}{Comma , }{Placeholder T1 c}{RightParen )} (1)
+
+// RUN: c-index-test -code-completion-at=%s:138:25 %s | FileCheck -check-prefix=CHECK-CC65 %s
+// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1)
+// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter float}{RightParen )} (1)
+// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter int}{RightParen )} (1)
+// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{RightParen )} (1)
+// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{Comma , }{Placeholder float c}{RightParen )} (1)
+// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T2 a}{Comma , }{Placeholder int b}{Comma , }{Placeholder T1 c}{RightParen )} (1)
+
diff --git a/test/Index/complete-exprs.c b/test/Index/complete-exprs.c
index bace0678c4e6..dbb6019d82ce 100644
--- a/test/Index/complete-exprs.c
+++ b/test/Index/complete-exprs.c
@@ -24,15 +24,15 @@ void f5(float f) {
(type)f;
}
-// RUN: c-index-test -code-completion-at=%s:7:9 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s
-// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:7:9 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: c-index-test -code-completion-at=%s:7:10 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:7:10 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s
// CHECK-CC1: NotImplemented:{TypedText __PRETTY_FUNCTION__} (65)
// CHECK-CC1: macro definition:{TypedText __VERSION__} (70)
// CHECK-CC1: FunctionDecl:{ResultType int}{TypedText f}{LeftParen (}{Placeholder int}{RightParen )} (12) (unavailable)
// CHECK-CC1-NOT: NotImplemented:{TypedText float} (65)
// CHECK-CC1: ParmDecl:{ResultType int}{TypedText j} (8)
// CHECK-CC1: NotImplemented:{ResultType size_t}{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (40)
-// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:7:9 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:7:10 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s
// RUN: c-index-test -code-completion-at=%s:7:14 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s
// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:7:14 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s
// CHECK-CC3: macro definition:{TypedText __VERSION__} (70)
diff --git a/test/Index/complete-exprs.cpp b/test/Index/complete-exprs.cpp
index 3f3bd5c55a6b..fc60cc560b5c 100644
--- a/test/Index/complete-exprs.cpp
+++ b/test/Index/complete-exprs.cpp
@@ -58,7 +58,7 @@ namespace N {
// CHECK-CC1: CXXConstructor:{TypedText string}{LeftParen (}{Placeholder const char *}{Comma , }{Placeholder int n}{RightParen )} (50)
// CHECK-CC1: ClassTemplate:{TypedText vector}{LeftAngle <}{Placeholder typename T}{RightAngle >} (50)
// CHECK-CC1: CXXConstructor:{TypedText vector}{LeftAngle <}{Placeholder typename T}{RightAngle >}{LeftParen (}{Placeholder const T &}{Comma , }{Placeholder unsigned int n}{RightParen )} (50)
-// CHECK-CC1: FunctionTemplate:{ResultType void}{TypedText vector}{LeftAngle <}{Placeholder typename T}{RightAngle >}{LeftParen (}{Placeholder InputIterator first}{Comma , }{Placeholder InputIterator last}{RightParen )} (50)
+// CHECK-CC1: FunctionTemplate:{TypedText vector}{LeftAngle <}{Placeholder typename T}{RightAngle >}{LeftParen (}{Placeholder InputIterator first}{Comma , }{Placeholder InputIterator last}{RightParen )} (50)
// RUN: c-index-test -code-completion-at=%s:19:1 %s | FileCheck -check-prefix=CHECK-CC2 %s
// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:19:1 %s | FileCheck -check-prefix=CHECK-CC2 %s
@@ -72,7 +72,7 @@ namespace N {
// CHECK-CC3: FunctionDecl:{ResultType void}{TypedText g}{LeftParen (}{RightParen )} (50)
// CHECK-CC3: ClassTemplate:{TypedText vector}{LeftAngle <}{Placeholder typename T}{RightAngle >} (50)
// CHECK-CC3: CXXConstructor:{TypedText vector}{LeftAngle <}{Placeholder typename T}{RightAngle >}{LeftParen (}{Placeholder const T &}{Comma , }{Placeholder unsigned int n}{RightParen )} (50)
-// CHECK-CC3: FunctionTemplate:{ResultType void}{TypedText vector}{LeftAngle <}{Placeholder typename T}{RightAngle >}{LeftParen (}{Placeholder InputIterator first}{Comma , }{Placeholder InputIterator last}{RightParen )} (50)
+// CHECK-CC3: FunctionTemplate:{TypedText vector}{LeftAngle <}{Placeholder typename T}{RightAngle >}{LeftParen (}{Placeholder InputIterator first}{Comma , }{Placeholder InputIterator last}{RightParen )} (50)
// RUN: c-index-test -code-completion-at=%s:34:1 %s -std=c++0x | FileCheck -check-prefix=CHECK-CC4 %s
// CHECK-CC4: NotImplemented:{ResultType const X *}{TypedText this} (40)
diff --git a/test/Index/complete-pch-skip.cpp b/test/Index/complete-pch-skip.cpp
new file mode 100644
index 000000000000..6abf40df36c1
--- /dev/null
+++ b/test/Index/complete-pch-skip.cpp
@@ -0,0 +1,30 @@
+namespace ns {
+int bar;
+}
+
+int main() { return ns:: }
+int main2() { return ns::foo(). }
+
+// RUN: echo "namespace ns { struct foo { int baz }; }" > %t.h
+// RUN: c-index-test -write-pch %t.h.pch -x c++-header %t.h
+//
+// RUN: c-index-test -code-completion-at=%s:5:26 -include %t.h %s | FileCheck -check-prefix=WITH-PCH %s
+// WITH-PCH: {TypedText bar}
+// WITH-PCH: {TypedText foo}
+
+// RUN: env CINDEXTEST_COMPLETION_SKIP_PREAMBLE=1 c-index-test -code-completion-at=%s:5:26 -include %t.h %s | FileCheck -check-prefix=SKIP-PCH %s
+// SKIP-PCH-NOT: foo
+// SKIP-PCH: {TypedText bar}
+// SKIP-PCH-NOT: foo
+
+// Verify that with *no* preamble (no -include flag) we still get local results.
+// SkipPreamble used to break this, by making lookup *too* lazy.
+// RUN: env CINDEXTEST_COMPLETION_SKIP_PREAMBLE=1 c-index-test -code-completion-at=%s:5:26 %s | FileCheck -check-prefix=NO-PCH %s
+// NO-PCH-NOT: foo
+// NO-PCH: {TypedText bar}
+// NO-PCH-NOT: foo
+
+// Verify that we still get member results from the preamble.
+// RUN: env CINDEXTEST_COMPLETION_SKIP_PREAMBLE=1 c-index-test -code-completion-at=%s:6:32 -include %t.h %s | FileCheck -check-prefix=MEMBER %s
+// MEMBER: {TypedText baz}
+
diff --git a/test/Index/complete-preprocessor.m b/test/Index/complete-preprocessor.m
index baeb4e94562f..d22ace6e1c54 100644
--- a/test/Index/complete-preprocessor.m
+++ b/test/Index/complete-preprocessor.m
@@ -13,7 +13,7 @@
FOO(in,t) value;
-// RUN: c-index-test -code-completion-at=%s:4:2 %s | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: c-index-test -code-completion-at=%s:4:3 %s | FileCheck -check-prefix=CHECK-CC1 %s
// CHECK-CC1: NotImplemented:{TypedText define}{HorizontalSpace }{Placeholder macro} (40)
// CHECK-CC1-NEXT: NotImplemented:{TypedText define}{HorizontalSpace }{Placeholder macro}{LeftParen (}{Placeholder args}{RightParen )} (40)
// CHECK-CC1-NEXT: NotImplemented:{TypedText error}{HorizontalSpace }{Placeholder message} (40)
@@ -55,8 +55,8 @@ FOO(in,t) value;
// RUN: c-index-test -code-completion-at=%s:9:8 %s | FileCheck -check-prefix=CHECK-CC3 %s
// CHECK-CC3: macro definition:{TypedText BAR} (40)
// CHECK-CC3: macro definition:{TypedText FOO} (40)
-// RUN: c-index-test -code-completion-at=%s:11:12 %s | FileCheck -check-prefix=CHECK-CC3 %s
// RUN: c-index-test -code-completion-at=%s:11:13 %s | FileCheck -check-prefix=CHECK-CC3 %s
+// RUN: c-index-test -code-completion-at=%s:11:14 %s | FileCheck -check-prefix=CHECK-CC3 %s
// RUN: c-index-test -code-completion-at=%s:11:5 %s | FileCheck -check-prefix=CHECK-CC4 %s
// CHECK-CC4: macro definition:{TypedText BAR} (70)
// CHECK-CC4: macro definition:{TypedText FOO}{LeftParen (}{Placeholder a}{Comma , }{Placeholder b}{RightParen )} (70)
diff --git a/test/Index/crash-preamble-classes.cpp b/test/Index/crash-preamble-classes.cpp
new file mode 100644
index 000000000000..e7d4bd70aea9
--- /dev/null
+++ b/test/Index/crash-preamble-classes.cpp
@@ -0,0 +1,8 @@
+#include "crash-preamble-classes.h"
+
+struct Z : Y {
+ Z() {}
+};
+
+// RUN: env CINDEXTEST_EDITING=1 \
+// RUN: c-index-test -test-load-source-reparse 5 local -I %S/Inputs %s
diff --git a/test/Index/create-libclang-completion-reproducer.c b/test/Index/create-libclang-completion-reproducer.c
new file mode 100644
index 000000000000..5683e10075bf
--- /dev/null
+++ b/test/Index/create-libclang-completion-reproducer.c
@@ -0,0 +1,14 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: env CINDEXTEST_INVOCATION_EMISSION_PATH=%t not c-index-test -code-completion-at=%s:10:1 "-remap-file=%s,%S/Inputs/record-parsing-invocation-remap.c" %s
+// RUN: %clang -cc1gen-reproducer %t/libclang-* -v | FileCheck %s
+
+// Invocation file must be removed by clang:
+// RUN: ls %t | count 0
+
+// CHECK: REPRODUCER METAINFO: {"libclang.operation": "complete", "libclang.opts": "1", "invocation-args": ["-code-completion-at={{.*}}create-libclang-completion-reproducer.c:10:1"]}
+
+// CHECK: REPRODUCER:
+// CHECK-NEXT: {
+// CHECK-NEXT: "files":["{{.*}}.c","{{.*}}.sh"]
+// CHECK-NEXT: }
diff --git a/test/Index/create-libclang-parsing-reproducer.c b/test/Index/create-libclang-parsing-reproducer.c
new file mode 100644
index 000000000000..0cfbfb14481d
--- /dev/null
+++ b/test/Index/create-libclang-parsing-reproducer.c
@@ -0,0 +1,21 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: env CINDEXTEST_INVOCATION_EMISSION_PATH=%t not c-index-test -test-load-source all %s
+// RUN: %clang -cc1gen-reproducer %t/libclang-* -v | FileCheck %s
+
+// Invocation file must be removed by clang:
+// RUN: ls %t | count 0
+
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: env CINDEXTEST_INVOCATION_EMISSION_PATH=%t not c-index-test -test-load-source all "-remap-file=%s,%S/Inputs/record-parsing-invocation-remap.c" %s
+// RUN: %clang -cc1gen-reproducer %t/libclang-* -v | FileCheck %s
+
+#pragma clang __debug parser_crash
+
+// CHECK: REPRODUCER METAINFO: {"libclang.operation": "parse", "libclang.opts": "1"}
+
+// CHECK: REPRODUCER:
+// CHECK-NEXT: {
+// CHECK-NEXT: "files":["{{.*}}.c","{{.*}}.sh"]
+// CHECK-NEXT: }
diff --git a/test/Index/get-cursor.cpp b/test/Index/get-cursor.cpp
index e997fc493d8c..6c3c880b2d85 100644
--- a/test/Index/get-cursor.cpp
+++ b/test/Index/get-cursor.cpp
@@ -151,6 +151,8 @@ template <class T> void f_computed_noexcept(T t) noexcept(noexcept(t+t));
void f_dynamic_noexcept_none() throw();
void f_dynamic_noexcept() throw(int);
void f_dynamic_noexcept_any() throw(...);
+void f_computed_noexcept_true() noexcept(true);
+void f_computed_noexcept_false() noexcept(false);
enum EnumType { Enumerator };
struct Z {
@@ -221,7 +223,7 @@ struct Z {
// RUN: c-index-test -cursor-at=%s:66:23 %s | FileCheck -check-prefix=CHECK-TEMPLSPEC %s
// CHECK-TEMPLSPEC: 66:23 ClassDecl=TC:66:23 (Definition) [Specialization of TC:59:7] Extent=[66:1 - 66:31] Spelling=TC ([66:23 - 66:25])
-// RUN: c-index-test -cursor-at=%s:69:3 -cursor-at=%s:70:11 -cursor-at=%s:73:6 -cursor-at=%s:74:6 -cursor-at=%s:77:8 -cursor-at=%s:78:8 -cursor-at=%s:79:8 -cursor-at=%s:80:8 -cursor-at=%s:81:8 -cursor-at=%s:82:8 -cursor-at=%s:85:6 -cursor-at=%s:86:6 -cursor-at=%s:87:6 -cursor-at=%s:88:6 -cursor-at=%s:91:5 -cursor-at=%s:92:5 -cursor-at=%s:93:5 -cursor-at=%s:94:5 -cursor-at=%s:95:5 -cursor-at=%s:96:5 -cursor-at=%s:97:5 -cursor-at=%s:98:5 -cursor-at=%s:100:5 -cursor-at=%s:101:5 -cursor-at=%s:104:6 -cursor-at=%s:105:6 -cursor-at=%s:106:6 -cursor-at=%s:107:6 -cursor-at=%s:108:6 -cursor-at=%s:109:6 -cursor-at=%s:110:6 -cursor-at=%s:111:6 -cursor-at=%s:113:6 -cursor-at=%s:114:6 -cursor-at=%s:117:8 -cursor-at=%s:118:8 -cursor-at=%s:120:8 -cursor-at=%s:121:8 -cursor-at=%s:122:8 -cursor-at=%s:123:8 -cursor-at=%s:124:8 -cursor-at=%s:125:8 -cursor-at=%s:128:6 -cursor-at=%s:129:6 -cursor-at=%s:130:6 -cursor-at=%s:132:3 -cursor-at=%s:146:15 -cursor-at=%s:149:6 -cursor-at=%s:150:25 -cursor-at=%s:151:6 -cursor-at=%s:152:6 -cursor-at=%s:153:6 -std=c++11 %s | FileCheck -check-prefix=CHECK-SPELLING %s
+// RUN: c-index-test -cursor-at=%s:69:3 -cursor-at=%s:70:11 -cursor-at=%s:73:6 -cursor-at=%s:74:6 -cursor-at=%s:77:8 -cursor-at=%s:78:8 -cursor-at=%s:79:8 -cursor-at=%s:80:8 -cursor-at=%s:81:8 -cursor-at=%s:82:8 -cursor-at=%s:85:6 -cursor-at=%s:86:6 -cursor-at=%s:87:6 -cursor-at=%s:88:6 -cursor-at=%s:91:5 -cursor-at=%s:92:5 -cursor-at=%s:93:5 -cursor-at=%s:94:5 -cursor-at=%s:95:5 -cursor-at=%s:96:5 -cursor-at=%s:97:5 -cursor-at=%s:98:5 -cursor-at=%s:100:5 -cursor-at=%s:101:5 -cursor-at=%s:104:6 -cursor-at=%s:105:6 -cursor-at=%s:106:6 -cursor-at=%s:107:6 -cursor-at=%s:108:6 -cursor-at=%s:109:6 -cursor-at=%s:110:6 -cursor-at=%s:111:6 -cursor-at=%s:113:6 -cursor-at=%s:114:6 -cursor-at=%s:117:8 -cursor-at=%s:118:8 -cursor-at=%s:120:8 -cursor-at=%s:121:8 -cursor-at=%s:122:8 -cursor-at=%s:123:8 -cursor-at=%s:124:8 -cursor-at=%s:125:8 -cursor-at=%s:128:6 -cursor-at=%s:129:6 -cursor-at=%s:130:6 -cursor-at=%s:132:3 -cursor-at=%s:146:15 -cursor-at=%s:149:6 -cursor-at=%s:150:25 -cursor-at=%s:151:6 -cursor-at=%s:152:6 -cursor-at=%s:153:6 -cursor-at=%s:154:6 -cursor-at=%s:155:6 -std=c++11 %s | FileCheck -check-prefix=CHECK-SPELLING %s
// CHECK-SPELLING: 69:3 CXXConstructor=A:69:3 (default constructor) Extent=[69:3 - 69:6] Spelling=A ([69:3 - 69:4])
// CHECK-SPELLING: 70:11 CXXDestructor=~A:70:11 (virtual) Extent=[70:3 - 70:15] Spelling=~A ([70:11 - 70:13])
// CHECK-SPELLING: 73:6 CXXMethod=operator=:73:6 Extent=[73:3 - 73:25] Spelling=operator= ([73:6 - 73:15])
@@ -274,12 +276,14 @@ struct Z {
// CHECK-SPELLING: 151:6 FunctionDecl=f_dynamic_noexcept_none:151:6 (noexcept dynamic none) Extent=[151:1 - 151:39] Spelling=f_dynamic_noexcept_none ([151:6 - 151:29])
// CHECK-SPELLING: 152:6 FunctionDecl=f_dynamic_noexcept:152:6 (noexcept dynamic) Extent=[152:1 - 152:37] Spelling=f_dynamic_noexcept ([152:6 - 152:24])
// CHECK-SPELLING: 153:6 FunctionDecl=f_dynamic_noexcept_any:153:6 (noexcept dynamic any) Extent=[153:1 - 153:41] Spelling=f_dynamic_noexcept_any ([153:6 - 153:28])
+// CHECK-SPELLING: 154:6 FunctionDecl=f_computed_noexcept_true:154:6 (computed-noexcept) Extent=[154:1 - 154:47] Spelling=f_computed_noexcept_true ([154:6 - 154:30])
+// CHECK-SPELLING: 155:6 FunctionDecl=f_computed_noexcept_false:155:6 (computed-noexcept) Extent=[155:1 - 155:49] Spelling=f_computed_noexcept_false ([155:6 - 155:31])
// RUN: c-index-test -cursor-at=%s:141:13 -cursor-at=%s:141:18 -cursor-at=%s:142:11 -std=c++11 %s | FileCheck -check-prefix=CHECK-FORRANGE %s
// CHECK-FORRANGE: 141:13 VarDecl=lv:141:13 (Definition) Extent=[141:8 - 141:17] Spelling=lv ([141:13 - 141:15])
// CHECK-FORRANGE: 141:18 DeclRefExpr=coll:140:20 Extent=[141:18 - 141:22] Spelling=coll ([141:18 - 141:22])
// CHECK-FORRANGE: 142:11 DeclRefExpr=lv:141:13 Extent=[142:11 - 142:13] Spelling=lv ([142:11 - 142:13])
-// RUN: c-index-test -cursor-at=%s:157:18 -std=c++11 %s | FileCheck -check-prefix=CHECK-INCLASSINITIALIZER %s
-// CHECK-INCLASSINITIALIZER: 157:18 DeclRefExpr=Enumerator:155:17 Extent=[157:18 - 157:28] Spelling=Enumerator ([157:18 - 157:28])
+// RUN: c-index-test -cursor-at=%s:159:18 -std=c++11 %s | FileCheck -check-prefix=CHECK-INCLASSINITIALIZER %s
+// CHECK-INCLASSINITIALIZER: 159:18 DeclRefExpr=Enumerator:157:17 Extent=[159:18 - 159:28] Spelling=Enumerator ([159:18 - 159:28])
diff --git a/test/Index/headerfile-comment-to-html.m b/test/Index/headerfile-comment-to-html.m
index 8326a901402f..679314dbc1d9 100644
--- a/test/Index/headerfile-comment-to-html.m
+++ b/test/Index/headerfile-comment-to-html.m
@@ -58,11 +58,11 @@
\brief Test that headerfile can come after brief.
\headerfile VTDevice.h <VTFoundation/VTDevice.h>
- More property decription goes here.
+ More property description goes here.
*/
@interface VTDevice : Device
@end
-// CHECK: headerfile-comment-to-html.m:[[@LINE-2]]:12: ObjCInterfaceDecl=VTDevice:{{.*}} FullCommentAsXML=[<Other file="{{[^"]+}}headerfile-comment-to-html.m" line="[[@LINE-2]]" column="12"><Name>VTDevice</Name><USR>c:objc(cs)VTDevice</USR><Headerfile><Para> VTDevice.h &lt;VTFoundation/VTDevice.h&gt;</Para></Headerfile><Declaration>@interface VTDevice : Device\n@end</Declaration><Abstract><Para> Test that headerfile can come after brief. </Para></Abstract><Discussion><Para> More property decription goes here.</Para></Discussion></Other>]
+// CHECK: headerfile-comment-to-html.m:[[@LINE-2]]:12: ObjCInterfaceDecl=VTDevice:{{.*}} FullCommentAsXML=[<Other file="{{[^"]+}}headerfile-comment-to-html.m" line="[[@LINE-2]]" column="12"><Name>VTDevice</Name><USR>c:objc(cs)VTDevice</USR><Headerfile><Para> VTDevice.h &lt;VTFoundation/VTDevice.h&gt;</Para></Headerfile><Declaration>@interface VTDevice : Device\n@end</Declaration><Abstract><Para> Test that headerfile can come after brief. </Para></Abstract><Discussion><Para> More property description goes here.</Para></Discussion></Other>]
// CHECK-NEXT: CommentAST=[
// CHECK-NEXT: (CXComment_FullComment
// CHECK-NEXT: (CXComment_Paragraph IsWhitespace
@@ -77,7 +77,7 @@
// CHECK-NEXT: (CXComment_Text Text=[<VTFoundation])
// CHECK-NEXT: (CXComment_Text Text=[/VTDevice.h>])))
// CHECK-NEXT: (CXComment_Paragraph
-// CHECK-NEXT: (CXComment_Text Text=[ More property decription goes here.])))]
+// CHECK-NEXT: (CXComment_Text Text=[ More property description goes here.])))]
/*!
\headerfile <stdio.h>
diff --git a/test/Index/index-refs.cpp b/test/Index/index-refs.cpp
index d8bede0b4761..760e4cfcf978 100644
--- a/test/Index/index-refs.cpp
+++ b/test/Index/index-refs.cpp
@@ -67,6 +67,9 @@ struct S2 {
void foo5() {
struct S2 s = { .y = 1, .x = 4};
+ s.y = s.x + 1;
+ (void)&foo3;
+ foo4(s.y);
}
int ginitlist[] = {EnumVal};
@@ -105,7 +108,7 @@ int ginitlist[] = {EnumVal};
// CHECK: [indexDeclaration]: kind: c++-class-template | name: TS | {{.*}} | loc: 47:8
// CHECK-NEXT: [indexDeclaration]: kind: struct-template-partial-spec | name: TS | USR: c:@SP>1#T@TS>#t0.0#I | {{.*}} | loc: 50:8
// CHECK-NEXT: [indexDeclaration]: kind: typedef | name: MyInt | USR: c:index-refs.cpp@SP>1#T@TS>#t0.0#I@T@MyInt | {{.*}} | loc: 51:15 | semantic-container: [TS:50:8] | lexical-container: [TS:50:8]
-// CHECK-NEXT: [indexEntityReference]: kind: c++-class-template | name: TS | USR: c:@ST>2#T#T@TS | lang: C++ | cursor: TemplateRef=TS:47:8 | loc: 50:8 | <parent>:: <<NULL>> | container: [TU] | refkind: direct
+// CHECK-NEXT: [indexEntityReference]: kind: c++-class-template | name: TS | USR: c:@ST>2#T#T@TS | lang: C++ | cursor: TemplateRef=TS:47:8 | loc: 50:8 | <parent>:: <<NULL>> | container: [TU] | refkind: direct | role: ref
/* when indexing implicit instantiations
[indexDeclaration]: kind: struct-template-spec | name: TS | USR: c:@S@TS>#I | {{.*}} | loc: 50:8
[indexDeclaration]: kind: typedef | name: MyInt | USR: c:index-refs.cpp@593@S@TS>#I@T@MyInt | {{.*}} | loc: 51:15 | semantic-container: [TS:50:8] | lexical-container: [TS:50:8]
@@ -117,7 +120,7 @@ int ginitlist[] = {EnumVal};
// CHECK-NEXT: [indexEntityReference]: kind: c++-class-template | name: TS | USR: c:@ST>2#T#T@TS | {{.*}} | loc: 55:3
// CHECK: [indexEntityReference]: kind: variable | name: array_size | {{.*}} | loc: 59:22
-// CHECK: [indexEntityReference]: kind: variable | name: default_param | {{.*}} | loc: 62:19
+// CHECK: [indexEntityReference]: kind: variable | name: default_param | {{.*}} | loc: 62:19 | {{.*}} | role: ref read
// CHECK-NOT: [indexEntityReference]: kind: variable | name: default_param | {{.*}} | loc: 62:19
// CHECK: [indexEntityReference]: kind: field | name: y | {{.*}} | loc: 69:20
@@ -125,6 +128,11 @@ int ginitlist[] = {EnumVal};
// CHECK-NOT: [indexEntityReference]: kind: field | name: y | {{.*}} | loc: 69:20
// CHECK-NOT: [indexEntityReference]: kind: field | name: x | {{.*}} | loc: 69:28
+// CHECK: [indexEntityReference]: kind: field | name: y | {{.*}} | loc: 70:5 | {{.*}} | role: ref write
+// CHECK: [indexEntityReference]: kind: field | name: x | {{.*}} | loc: 70:11 | {{.*}} | role: ref read
+// CHECK: [indexEntityReference]: kind: function | name: foo3 | {{.*}} | loc: 71:10 | {{.*}} | role: ref addr
+// CHECK: [indexEntityReference]: kind: function | name: foo4 | {{.*}} | loc: 72:3 | {{.*}} | role: ref call
+
// CHECK: [indexDeclaration]: kind: variable | name: ginitlist |
-// CHECK: [indexEntityReference]: kind: enumerator | name: EnumVal | {{.*}} | loc: 72:20
-// CHECK-NOT: [indexEntityReference]: kind: enumerator | name: EnumVal | {{.*}} | loc: 72:20
+// CHECK: [indexEntityReference]: kind: enumerator | name: EnumVal | {{.*}} | loc: 75:20
+// CHECK-NOT: [indexEntityReference]: kind: enumerator | name: EnumVal | {{.*}} | loc: 75:20
diff --git a/test/Index/index-subscripting-literals.m b/test/Index/index-subscripting-literals.m
index 4ecad0b9252c..08b936a5ea8e 100644
--- a/test/Index/index-subscripting-literals.m
+++ b/test/Index/index-subscripting-literals.m
@@ -42,7 +42,7 @@ void testDict() {
// RUN: c-index-test -index-file -target x86_64-apple-macosx10.7 %s | FileCheck %s
// CHECK: [indexEntityReference]: kind: variable | name: idx | USR: c:@idx | lang: C | cursor: DeclRefExpr=idx:22:5 | loc: 27:9
-// CHECK-NEXT: [indexEntityReference]: kind: variable | name: p | USR: c:@p | lang: C | cursor: DeclRefExpr=p:23:4 | loc: 27:16 | <parent>:: kind: function | name: testArray | USR: c:@F@testArray | lang: C | container: [testArray:25:4] | refkind: direct
+// CHECK-NEXT: [indexEntityReference]: kind: variable | name: p | USR: c:@p | lang: C | cursor: DeclRefExpr=p:23:4 | loc: 27:16 | <parent>:: kind: function | name: testArray | USR: c:@F@testArray | lang: C | container: [testArray:25:4] | refkind: direct | role: ref
// CHECK-NEXT: [indexEntityReference]: kind: objc-instance-method | name: setObject:atIndexedSubscript:
// CHECK-NEXT: [indexEntityReference]: kind: objc-class | name: NSArray
// CHECK-NEXT: [indexEntityReference]: kind: objc-class-method | name: arrayWithObjects:count:
diff --git a/test/Index/index-template-specialization.cpp b/test/Index/index-template-specialization.cpp
new file mode 100644
index 000000000000..d11754113c46
--- /dev/null
+++ b/test/Index/index-template-specialization.cpp
@@ -0,0 +1,19 @@
+template <typename T>
+class Foo {
+public:
+ void f(T t) {}
+};
+
+void g() {
+ Foo<int> foo;
+ foo.f(0);
+}
+
+// FIXME: if c-index-test uses OrigD for symbol info, refererences below should
+// refer to template specialization decls.
+// RUN: env CINDEXTEST_INDEXIMPLICITTEMPLATEINSTANTIATIONS=1 c-index-test -index-file %s | FileCheck %s
+// CHECK: [indexDeclaration]: kind: c++-class-template | name: Foo
+// CHECK-NEXT: [indexDeclaration]: kind: c++-instance-method | name: f
+// CHECK-NEXT: [indexDeclaration]: kind: function | name: g
+// CHECK-NEXT: [indexEntityReference]: kind: c++-class-template | name: Foo | USR: c:@ST>1#T@Foo
+// CHECK-NEXT: [indexEntityReference]: kind: c++-instance-method | name: f | USR: c:@ST>1#T@Foo@F@f#t0.0#
diff --git a/test/Index/missing_vfs.c b/test/Index/missing_vfs.c
new file mode 100644
index 000000000000..61aedd41cfaa
--- /dev/null
+++ b/test/Index/missing_vfs.c
@@ -0,0 +1,6 @@
+// RUN: c-index-test -test-load-source local %s -ivfsoverlay %t/does-not-exist.yaml &> %t.out
+// RUN: FileCheck -check-prefix=STDERR %s < %t.out
+// STDERR: fatal error: virtual filesystem overlay file '{{.*}}' not found
+// RUN: FileCheck %s < %t.out
+// CHECK: missing_vfs.c:[[@LINE+1]]:6: FunctionDecl=foo:[[@LINE+1]]:6
+void foo(void);
diff --git a/test/Index/opencl-types.cl b/test/Index/opencl-types.cl
index fe0042aa2097..d71893a22085 100644
--- a/test/Index/opencl-types.cl
+++ b/test/Index/opencl-types.cl
@@ -16,11 +16,11 @@ void kernel testFloatTypes() {
double4 vectorDouble;
}
-// CHECK: VarDecl=scalarHalf:11:8 (Definition) [type=half] [typekind=Half] [isPOD=1]
+// CHECK: VarDecl=scalarHalf:11:8 (Definition){{( \(invalid\))?}} [type=half] [typekind=Half] [isPOD=1]
// CHECK: VarDecl=vectorHalf:12:9 (Definition) [type=half4] [typekind=Typedef] [canonicaltype=half __attribute__((ext_vector_type(4)))] [canonicaltypekind=Unexposed] [isPOD=1]
// CHECK: VarDecl=scalarFloat:13:9 (Definition) [type=float] [typekind=Float] [isPOD=1]
// CHECK: VarDecl=vectorFloat:14:10 (Definition) [type=float4] [typekind=Typedef] [canonicaltype=float __attribute__((ext_vector_type(4)))] [canonicaltypekind=Unexposed] [isPOD=1]
-// CHECK: VarDecl=scalarDouble:15:10 (Definition) [type=double] [typekind=Double] [isPOD=1]
+// CHECK: VarDecl=scalarDouble:15:10 (Definition){{( \(invalid\))?}} [type=double] [typekind=Double] [isPOD=1]
// CHECK: VarDecl=vectorDouble:16:11 (Definition) [type=double4] [typekind=Typedef] [canonicaltype=double __attribute__((ext_vector_type(4)))] [canonicaltypekind=Unexposed] [isPOD=1]
#pragma OPENCL EXTENSION cl_khr_gl_msaa_sharing : enable
@@ -45,10 +45,10 @@ void kernel OCLImage3dROTest(read_only image3d_t scalarOCLImage3dRO);
// CHECK: ParmDecl=scalarOCLImage2dArrayRO:32:61 (Definition) [type=__read_only image2d_array_t] [typekind=OCLImage2dArrayRO] [isPOD=1]
// CHECK: ParmDecl=scalarOCLImage2dDepthRO:33:61 (Definition) [type=__read_only image2d_depth_t] [typekind=OCLImage2dDepthRO] [isPOD=1]
// CHECK: ParmDecl=scalarOCLImage2dArrayDepthRO:34:72 (Definition) [type=__read_only image2d_array_depth_t] [typekind=OCLImage2dArrayDepthRO] [isPOD=1]
-// CHECK: ParmDecl=scalarOCLImage2dMSAARO:35:59 (Definition) [type=__read_only image2d_msaa_t] [typekind=OCLImage2dMSAARO] [isPOD=1]
-// CHECK: ParmDecl=scalarOCLImage2dArrayMSAARO:36:70 (Definition) [type=__read_only image2d_array_msaa_t] [typekind=OCLImage2dArrayMSAARO] [isPOD=1]
-// CHECK: ParmDecl=scalarOCLImage2dMSAADepthRO:37:70 (Definition) [type=__read_only image2d_msaa_depth_t] [typekind=OCLImage2dMSAADepthRO] [isPOD=1]
-// CHECK: ParmDecl=scalarOCLImage2dArrayMSAADepthRO:38:81 (Definition) [type=__read_only image2d_array_msaa_depth_t] [typekind=OCLImage2dArrayMSAADepthRO] [isPOD=1]
+// CHECK: ParmDecl=scalarOCLImage2dMSAARO:35:59 (Definition){{( \(invalid\))?}} [type=__read_only image2d_msaa_t] [typekind=OCLImage2dMSAARO] [isPOD=1]
+// CHECK: ParmDecl=scalarOCLImage2dArrayMSAARO:36:70 (Definition){{( \(invalid\))?}} [type=__read_only image2d_array_msaa_t] [typekind=OCLImage2dArrayMSAARO] [isPOD=1]
+// CHECK: ParmDecl=scalarOCLImage2dMSAADepthRO:37:70 (Definition){{( \(invalid\))?}} [type=__read_only image2d_msaa_depth_t] [typekind=OCLImage2dMSAADepthRO] [isPOD=1]
+// CHECK: ParmDecl=scalarOCLImage2dArrayMSAADepthRO:38:81 (Definition){{( \(invalid\))?}} [type=__read_only image2d_array_msaa_depth_t] [typekind=OCLImage2dArrayMSAADepthRO] [isPOD=1]
// CHECK: ParmDecl=scalarOCLImage3dRO:39:50 (Definition) [type=__read_only image3d_t] [typekind=OCLImage3dRO] [isPOD=1]
void kernel OCLImage1dWOTest(write_only image1d_t scalarOCLImage1dWO);
@@ -71,11 +71,11 @@ void kernel OCLImage3dWOTest(write_only image3d_t scalarOCLImage3dWO);
// CHECK: ParmDecl=scalarOCLImage2dArrayWO:58:62 (Definition) [type=__write_only image2d_array_t] [typekind=OCLImage2dArrayWO] [isPOD=1]
// CHECK: ParmDecl=scalarOCLImage2dDepthWO:59:62 (Definition) [type=__write_only image2d_depth_t] [typekind=OCLImage2dDepthWO] [isPOD=1]
// CHECK: ParmDecl=scalarOCLImage2dArrayDepthWO:60:73 (Definition) [type=__write_only image2d_array_depth_t] [typekind=OCLImage2dArrayDepthWO] [isPOD=1]
-// CHECK: ParmDecl=scalarOCLImage2dMSAAWO:61:60 (Definition) [type=__write_only image2d_msaa_t] [typekind=OCLImage2dMSAAWO] [isPOD=1]
-// CHECK: ParmDecl=scalarOCLImage2dArrayMSAAWO:62:71 (Definition) [type=__write_only image2d_array_msaa_t] [typekind=OCLImage2dArrayMSAAWO] [isPOD=1]
-// CHECK: ParmDecl=scalarOCLImage2dMSAADepthWO:63:71 (Definition) [type=__write_only image2d_msaa_depth_t] [typekind=OCLImage2dMSAADepthWO] [isPOD=1]
-// CHECK: ParmDecl=scalarOCLImage2dArrayMSAADepthWO:64:82 (Definition) [type=__write_only image2d_array_msaa_depth_t] [typekind=OCLImage2dArrayMSAADepthWO] [isPOD=1]
-// CHECK: ParmDecl=scalarOCLImage3dWO:65:51 (Definition) [type=__write_only image3d_t] [typekind=OCLImage3dWO] [isPOD=1]
+// CHECK: ParmDecl=scalarOCLImage2dMSAAWO:61:60 (Definition){{( \(invalid\))?}} [type=__write_only image2d_msaa_t] [typekind=OCLImage2dMSAAWO] [isPOD=1]
+// CHECK: ParmDecl=scalarOCLImage2dArrayMSAAWO:62:71 (Definition){{( \(invalid\))?}} [type=__write_only image2d_array_msaa_t] [typekind=OCLImage2dArrayMSAAWO] [isPOD=1]
+// CHECK: ParmDecl=scalarOCLImage2dMSAADepthWO:63:71 (Definition){{( \(invalid\))?}} [type=__write_only image2d_msaa_depth_t] [typekind=OCLImage2dMSAADepthWO] [isPOD=1]
+// CHECK: ParmDecl=scalarOCLImage2dArrayMSAADepthWO:64:82 (Definition){{( \(invalid\))?}} [type=__write_only image2d_array_msaa_depth_t] [typekind=OCLImage2dArrayMSAADepthWO] [isPOD=1]
+// CHECK: ParmDecl=scalarOCLImage3dWO:65:51 (Definition){{( \(invalid\))?}} [type=__write_only image3d_t] [typekind=OCLImage3dWO] [isPOD=1]
void kernel OCLImage1dRWTest(read_write image1d_t scalarOCLImage1dRW);
void kernel OCLImage1dArrayRWTest(read_write image1d_array_t scalarOCLImage1dArrayRW);
@@ -97,10 +97,10 @@ void kernel OCLImage3dRWTest(read_write image3d_t scalarOCLImage3dRW);
// CHECK: ParmDecl=scalarOCLImage2dArrayRW:84:62 (Definition) [type=__read_write image2d_array_t] [typekind=OCLImage2dArrayRW] [isPOD=1]
// CHECK: ParmDecl=scalarOCLImage2dDepthRW:85:62 (Definition) [type=__read_write image2d_depth_t] [typekind=OCLImage2dDepthRW] [isPOD=1]
// CHECK: ParmDecl=scalarOCLImage2dArrayDepthRW:86:73 (Definition) [type=__read_write image2d_array_depth_t] [typekind=OCLImage2dArrayDepthRW] [isPOD=1]
-// CHECK: ParmDecl=scalarOCLImage2dMSAARW:87:60 (Definition) [type=__read_write image2d_msaa_t] [typekind=OCLImage2dMSAARW] [isPOD=1]
-// CHECK: ParmDecl=scalarOCLImage2dArrayMSAARW:88:71 (Definition) [type=__read_write image2d_array_msaa_t] [typekind=OCLImage2dArrayMSAARW] [isPOD=1]
-// CHECK: ParmDecl=scalarOCLImage2dMSAADepthRW:89:71 (Definition) [type=__read_write image2d_msaa_depth_t] [typekind=OCLImage2dMSAADepthRW] [isPOD=1]
-// CHECK: ParmDecl=scalarOCLImage2dArrayMSAADepthRW:90:82 (Definition) [type=__read_write image2d_array_msaa_depth_t] [typekind=OCLImage2dArrayMSAADepthRW] [isPOD=1]
+// CHECK: ParmDecl=scalarOCLImage2dMSAARW:87:60 (Definition){{( \(invalid\))?}} [type=__read_write image2d_msaa_t] [typekind=OCLImage2dMSAARW] [isPOD=1]
+// CHECK: ParmDecl=scalarOCLImage2dArrayMSAARW:88:71 (Definition){{( \(invalid\))?}} [type=__read_write image2d_array_msaa_t] [typekind=OCLImage2dArrayMSAARW] [isPOD=1]
+// CHECK: ParmDecl=scalarOCLImage2dMSAADepthRW:89:71 (Definition){{( \(invalid\))?}} [type=__read_write image2d_msaa_depth_t] [typekind=OCLImage2dMSAADepthRW] [isPOD=1]
+// CHECK: ParmDecl=scalarOCLImage2dArrayMSAADepthRW:90:82 (Definition){{( \(invalid\))?}} [type=__read_write image2d_array_msaa_depth_t] [typekind=OCLImage2dArrayMSAADepthRW] [isPOD=1]
// CHECK: ParmDecl=scalarOCLImage3dRW:91:51 (Definition) [type=__read_write image3d_t] [typekind=OCLImage3dRW] [isPOD=1]
void kernel intPipeTestRO(read_only pipe int scalarPipe);
diff --git a/test/Index/overriding-ftemplate-comments.cpp b/test/Index/overriding-ftemplate-comments.cpp
index 855d2691d0a2..340dca49c2a3 100644
--- a/test/Index/overriding-ftemplate-comments.cpp
+++ b/test/Index/overriding-ftemplate-comments.cpp
@@ -77,10 +77,10 @@ void comment_to_html_conversion_21();
template <class C1, template <class C2, template <class C3, class C4> class BBB > class AAA>
void comment_to_html_conversion_22();
-// CHECK: FullCommentAsXML=[<Function templateKind="template" file="{{[^"]+}}overriding-ftemplate-comments.cpp" line="[[@LINE-2]]" column="6"><Name>comment_to_html_conversion_22</Name><USR>c:@FT@&gt;2#T#t&gt;2#T#t&gt;2#T#Tcomment_to_html_conversion_22#v#</USR><Declaration>template &lt;class C1, template &lt;class C2, template &lt;class C3, class C4&gt; class BBB&gt;\n class AAA&gt;\nvoid comment_to_html_conversion_22()</Declaration><TemplateParameters><Parameter><Name>C1</Name><Index>0</Index><Discussion><Para> Ccc 1 </Para></Discussion></Parameter><Parameter><Name>AAA</Name><Index>1</Index><Discussion><Para> Zzz </Para></Discussion></Parameter><Parameter><Name>C2</Name><Discussion><Para> Ccc 2 </Para></Discussion></Parameter><Parameter><Name>C3</Name><Discussion><Para> Ccc 3 </Para></Discussion></Parameter><Parameter><Name>C4</Name><Discussion><Para> Ccc 4 </Para></Discussion></Parameter><Parameter><Name>BBB</Name><Discussion><Para> Bbb</Para></Discussion></Parameter></TemplateParameters></Function>]
+// CHECK: FullCommentAsXML=[<Function templateKind="template" file="{{[^"]+}}overriding-ftemplate-comments.cpp" line="[[@LINE-2]]" column="6"><Name>comment_to_html_conversion_22</Name><USR>c:@FT@&gt;2#T#t&gt;2#T#t&gt;2#T#Tcomment_to_html_conversion_22#v#</USR><Declaration>template &lt;class C1, template &lt;class C2, template &lt;class C3, class C4&gt; class BBB&gt;\n class AAA&gt;\nvoid comment_to_html_conversion_22()</Declaration><TemplateParameters><Parameter><Name>C1</Name><Index>0</Index><Discussion><Para> Ccc 1 </Para></Discussion></Parameter><Parameter><Name>AAA</Name><Index>1</Index><Discussion><Para> Zzz </Para></Discussion></Parameter><Parameter><Name>C2</Name><Discussion><Para> Ccc 2 </Para></Discussion></Parameter><Parameter><Name>C3</Name><Discussion><Para> Ccc 3 </Para></Discussion></Parameter><Parameter><Name>C4</Name><Discussion><Para> Ccc 4 </Para></Discussion></Parameter><Parameter><Name>BBB</Name><Discussion><Para> Bbb</Para></Discussion></Parameter></TemplateParameters></Function>]
template<class CCC1, template<class CCC2, template<class CCC3, class CCC4> class QQQ> class PPP>
void comment_to_html_conversion_22();
-// CHECK: FullCommentAsXML=[<Function templateKind="template" file="{{[^"]+}}overriding-ftemplate-comments.cpp" line="[[@LINE-2]]" column="6"><Name>comment_to_html_conversion_22</Name><USR>c:@FT@&gt;2#T#t&gt;2#T#t&gt;2#T#Tcomment_to_html_conversion_22#v#</USR><Declaration>template &lt;class CCC1, template &lt;class CCC2, template &lt;class CCC3, class CCC4&gt;\n class QQQ&gt; class PPP&gt;\nvoid comment_to_html_conversion_22()</Declaration><TemplateParameters><Parameter><Name>CCC1</Name><Index>0</Index><Discussion><Para> Ccc 1 </Para></Discussion></Parameter><Parameter><Name>PPP</Name><Index>1</Index><Discussion><Para> Zzz </Para></Discussion></Parameter><Parameter><Name>CCC2</Name><Discussion><Para> Ccc 2 </Para></Discussion></Parameter><Parameter><Name>CCC3</Name><Discussion><Para> Ccc 3 </Para></Discussion></Parameter><Parameter><Name>CCC4</Name><Discussion><Para> Ccc 4 </Para></Discussion></Parameter><Parameter><Name>QQQ</Name><Discussion><Para> Bbb</Para></Discussion></Parameter></TemplateParameters></Function>]
+// CHECK: FullCommentAsXML=[<Function templateKind="template" file="{{[^"]+}}overriding-ftemplate-comments.cpp" line="[[@LINE-2]]" column="6"><Name>comment_to_html_conversion_22</Name><USR>c:@FT@&gt;2#T#t&gt;2#T#t&gt;2#T#Tcomment_to_html_conversion_22#v#</USR><Declaration>template &lt;class CCC1,\n template &lt;class CCC2, template &lt;class CCC3, class CCC4&gt; class QQQ&gt;\n class PPP&gt;\nvoid comment_to_html_conversion_22()</Declaration><TemplateParameters><Parameter><Name>CCC1</Name><Index>0</Index><Discussion><Para> Ccc 1 </Para></Discussion></Parameter><Parameter><Name>PPP</Name><Index>1</Index><Discussion><Para> Zzz </Para></Discussion></Parameter><Parameter><Name>CCC2</Name><Discussion><Para> Ccc 2 </Para></Discussion></Parameter><Parameter><Name>CCC3</Name><Discussion><Para> Ccc 3 </Para></Discussion></Parameter><Parameter><Name>CCC4</Name><Discussion><Para> Ccc 4 </Para></Discussion></Parameter><Parameter><Name>QQQ</Name><Discussion><Para> Bbb</Para></Discussion></Parameter></TemplateParameters></Function>]
diff --git a/test/Index/paren-type.c b/test/Index/paren-type.c
new file mode 100644
index 000000000000..14a7785e0580
--- /dev/null
+++ b/test/Index/paren-type.c
@@ -0,0 +1,16 @@
+// RUN: c-index-test -test-print-type %s | FileCheck --check-prefix=CHECK-TYPE %s
+// RUN: c-index-test -test-print-type-declaration %s | FileCheck --check-prefix=CHECK-TYPEDECL %s
+
+// CHECK-TYPE: VarDecl=VariableWithParentheses:
+// CHECK-TYPE-SAME: [type=int] [typekind=Int]
+// CHECK-TYPE-NOT: canonicaltype
+// CHECK-TYPE-SAME: isPOD
+extern int (VariableWithParentheses);
+
+typedef int MyTypedef;
+// CHECK-TYPE: VarDecl=VariableWithParentheses2:
+// CHECK-TYPE-SAME: [type=MyTypedef] [typekind=Typedef]
+// CHECK-TYPE-SAME: [canonicaltype=int] [canonicaltypekind=Int]
+// CHECK-TYPEDECL: VarDecl=VariableWithParentheses2
+// CHECK-TYPEDECL-SAME: [typedeclaration=MyTypedef] [typekind=Typedef]
+extern MyTypedef (VariableWithParentheses2);
diff --git a/test/Index/pipe-size.cl b/test/Index/pipe-size.cl
index cfe97935ee63..94a1255f0a48 100644
--- a/test/Index/pipe-size.cl
+++ b/test/Index/pipe-size.cl
@@ -1,16 +1,16 @@
// RUN: %clang_cc1 -x cl -O0 -cl-std=CL2.0 -emit-llvm -triple x86_64-unknown-linux-gnu %s -o - | FileCheck %s --check-prefix=X86
// RUN: %clang_cc1 -x cl -O0 -cl-std=CL2.0 -emit-llvm -triple spir-unknown-unknown %s -o - | FileCheck %s --check-prefix=SPIR
// RUN: %clang_cc1 -x cl -O0 -cl-std=CL2.0 -emit-llvm -triple spir64-unknown-unknown %s -o - | FileCheck %s --check-prefix=SPIR64
-// RUN: %clang_cc1 -x cl -O0 -cl-std=CL2.0 -emit-llvm -triple amdgcn-amd-amdhsa-amdgizcl %s -o - | FileCheck %s --check-prefix=AMD
+// RUN: %clang_cc1 -x cl -O0 -cl-std=CL2.0 -emit-llvm -triple amdgcn-amd-amdhsa %s -o - | FileCheck %s --check-prefix=AMDGCN
__kernel void testPipe( pipe int test )
{
int s = sizeof(test);
- // X86: store %opencl.pipe_t* %test, %opencl.pipe_t** %test.addr, align 8
+ // X86: store %opencl.pipe_ro_t* %test, %opencl.pipe_ro_t** %test.addr, align 8
// X86: store i32 8, i32* %s, align 4
- // SPIR: store %opencl.pipe_t addrspace(1)* %test, %opencl.pipe_t addrspace(1)** %test.addr, align 4
+ // SPIR: store %opencl.pipe_ro_t addrspace(1)* %test, %opencl.pipe_ro_t addrspace(1)** %test.addr, align 4
// SPIR: store i32 4, i32* %s, align 4
- // SPIR64: store %opencl.pipe_t addrspace(1)* %test, %opencl.pipe_t addrspace(1)** %test.addr, align 8
+ // SPIR64: store %opencl.pipe_ro_t addrspace(1)* %test, %opencl.pipe_ro_t addrspace(1)** %test.addr, align 8
// SPIR64: store i32 8, i32* %s, align 4
- // AMD: store %opencl.pipe_t addrspace(1)* %test, %opencl.pipe_t addrspace(1)* addrspace(5)* %test.addr, align 8
- // AMD: store i32 8, i32 addrspace(5)* %s, align 4
+ // AMDGCN: store %opencl.pipe_ro_t addrspace(1)* %test, %opencl.pipe_ro_t addrspace(1)* addrspace(5)* %test.addr, align 8
+ // AMDGCN: store i32 8, i32 addrspace(5)* %s, align 4
}
diff --git a/test/Index/print-display-names.cpp b/test/Index/print-display-names.cpp
index 94fe4665e630..5ba10e43bc23 100644
--- a/test/Index/print-display-names.cpp
+++ b/test/Index/print-display-names.cpp
@@ -12,9 +12,20 @@ void g(ClassTmpl<T, T>);
template<> void g<int>(ClassTmpl<int, int>);
-// RUN: c-index-test -test-load-source all-display %s | FileCheck %s
-// CHECK: print-display-names.cpp:2:7: ClassTemplate=ClassTmpl<T, typename>:2:7
-// CHECK: print-display-names.cpp:6:16: ClassDecl=ClassTmpl<Integer, Integer>:6:16 (Definition)
-// CHECK: print-display-names.cpp:8:6: FunctionDecl=f(ClassTmpl<float, Integer>):8:6
-// CHECK: print-display-names.cpp:11:6: FunctionTemplate=g(ClassTmpl<T, T>):11:6
-// CHECK: print-display-names.cpp:13:17: FunctionDecl=g<>(ClassTmpl<int, int>):13:17 [Specialization of g:11:6]
+// RUN: c-index-test -test-load-source all-display %s | FileCheck %s --check-prefix=DISPLAY_NAME
+// DISPLAY_NAME: print-display-names.cpp:2:7: ClassTemplate=ClassTmpl<T, typename>:2:7
+// DISPLAY_NAME: print-display-names.cpp:6:16: ClassDecl=ClassTmpl<Integer, Integer>:6:16 (Definition)
+// DISPLAY_NAME: print-display-names.cpp:8:6: FunctionDecl=f(ClassTmpl<float, Integer>):8:6
+// DISPLAY_NAME: print-display-names.cpp:11:6: FunctionTemplate=g(ClassTmpl<T, T>):11:6
+// DISPLAY_NAME: print-display-names.cpp:13:17: FunctionDecl=g<>(ClassTmpl<int, int>):13:17 [Specialization of g:11:6]
+
+// RUN: env CINDEXTEST_PRINTINGPOLICY_TERSEOUTPUT=1 c-index-test -test-load-source all-pretty %s | FileCheck %s --check-prefix=PRETTY
+// PRETTY: print-display-names.cpp:2:7: ClassTemplate=template <typename T, typename > class ClassTmpl {}:2:7 (Definition) Extent=[1:1 - 2:20]
+// PRETTY: print-display-names.cpp:4:13: TypedefDecl=typedef int Integer:4:13 (Definition) Extent=[4:1 - 4:20]
+// PRETTY: print-display-names.cpp:6:16: ClassDecl=template<> class ClassTmpl<int, int> {}:6:16 (Definition) [Specialization of ClassTmpl:2:7] Extent=[6:1 - 6:43]
+// PRETTY: print-display-names.cpp:8:6: FunctionDecl=void f(ClassTmpl<float, Integer> p):8:6 Extent=[8:1 - 8:36]
+// PRETTY: print-display-names.cpp:8:34: ParmDecl=ClassTmpl<float, Integer> p:8:34 (Definition) Extent=[8:8 - 8:35]
+// PRETTY: print-display-names.cpp:11:6: FunctionTemplate=template <typename T> void g(ClassTmpl<T, T>):11:6 Extent=[10:1 - 11:24]
+// PRETTY: print-display-names.cpp:11:23: ParmDecl=ClassTmpl<T, T>:11:23 (Definition) Extent=[11:8 - 11:23]
+// PRETTY: print-display-names.cpp:13:17: FunctionDecl=template<> void g<int>(ClassTmpl<int, int>):13:17 [Specialization of g:11:6] [Template arg 0: kind: 1, type: int] Extent=[13:1 - 13:44]
+// PRETTY: print-display-names.cpp:13:43: ParmDecl=ClassTmpl<int, int>:13:43 (Definition) Extent=[13:24 - 13:43]
diff --git a/test/Index/print-type-size.cpp b/test/Index/print-type-size.cpp
index 45de93f30824..1ea53462733f 100644
--- a/test/Index/print-type-size.cpp
+++ b/test/Index/print-type-size.cpp
@@ -4,8 +4,8 @@
namespace basic {
-// CHECK64: VarDecl=v:[[@LINE+2]]:6 (Definition) [type=void] [typekind=Void]
-// CHECK32: VarDecl=v:[[@LINE+1]]:6 (Definition) [type=void] [typekind=Void]
+// CHECK64: VarDecl=v:[[@LINE+2]]:6 (Definition) (invalid) [type=void] [typekind=Void]
+// CHECK32: VarDecl=v:[[@LINE+1]]:6 (Definition) (invalid) [type=void] [typekind=Void]
void v;
// CHECK64: VarDecl=v1:[[@LINE+2]]:7 (Definition) [type=void *] [typekind=Pointer] [sizeof=8] [alignof=8]
diff --git a/test/Index/print-type.c b/test/Index/print-type.c
index ebe42970eeb3..13c765543726 100644
--- a/test/Index/print-type.c
+++ b/test/Index/print-type.c
@@ -23,11 +23,11 @@ struct Struct{}; struct Struct elaboratedStructType();
// CHECK: TypeRef=FooType:1:13 [type=FooType] [typekind=Typedef] [canonicaltype=int] [canonicaltypekind=Int] [isPOD=1]
// CHECK: ParmDecl=arr:3:40 (Definition) [type=int [5]] [typekind=ConstantArray] [isPOD=1]
// CHECK: IntegerLiteral= [type=int] [typekind=Int] [isPOD=1]
-// CHECK: ParmDecl=fn:3:55 (Definition) [type=void (*)(int)] [typekind=Pointer] [canonicaltype=void (*)(int)] [canonicaltypekind=Pointer] [isPOD=1] [pointeetype=void (int)] [pointeekind=Unexposed]
+// CHECK: ParmDecl=fn:3:55 (Definition) [type=void (*)(int)] [typekind=Pointer] [canonicaltype=void (*)(int)] [canonicaltypekind=Pointer] [isPOD=1] [pointeetype=void (int)] [pointeekind=FunctionProto]
// CHECK: ParmDecl=:3:62 (Definition) [type=int] [typekind=Int] [isPOD=1]
// CHECK: CompoundStmt= [type=] [typekind=Invalid] [isPOD=0]
// CHECK: CallExpr=fn:3:55 [type=void] [typekind=Void] [args= [int] [Int]] [isPOD=0]
-// CHECK: DeclRefExpr=fn:3:55 [type=void (*)(int)] [typekind=Pointer] [canonicaltype=void (*)(int)] [canonicaltypekind=Pointer] [isPOD=1] [pointeetype=void (int)] [pointeekind=Unexposed]
+// CHECK: DeclRefExpr=fn:3:55 [type=void (*)(int)] [typekind=Pointer] [canonicaltype=void (*)(int)] [canonicaltypekind=Pointer] [isPOD=1] [pointeetype=void (int)] [pointeekind=FunctionProto]
// CHECK: UnaryOperator= [type=int] [typekind=Int] [isPOD=1]
// CHECK: DeclRefExpr=p:3:13 [type=int *] [typekind=Pointer] [isPOD=1] [pointeetype=int] [pointeekind=Int]
// CHECK: DeclStmt= [type=] [typekind=Invalid] [isPOD=0]
diff --git a/test/Index/reparsed-live-issue.cpp b/test/Index/reparsed-live-issue.cpp
new file mode 100644
index 000000000000..56423de0b72a
--- /dev/null
+++ b/test/Index/reparsed-live-issue.cpp
@@ -0,0 +1,4 @@
+// RUN: env CINDEXTEST_EDITING=1 LIBCLANG_DISABLE_CRASH_RECOVERY=1 c-index-test -test-load-source-reparse 2 none -remap-file-0=%S/Inputs/reparse-issue.h,%S/Inputs/reparse-issue.h-0 -remap-file-1=%S/Inputs/reparse-issue.h,%S/Inputs/reparse-issue.h-1 -- %s 2>&1 | FileCheck %s
+#include "Inputs/reparse-issue.h"
+
+// CHECK: reparse-issue.h:4:1:{1:1-1:1}: error: C++ requires a type specifier for all declarations
diff --git a/test/Layout/itanium-pack-and-align.cpp b/test/Layout/itanium-pack-and-align.cpp
new file mode 100644
index 000000000000..ac64979af33b
--- /dev/null
+++ b/test/Layout/itanium-pack-and-align.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm-only -fdump-record-layouts %s \
+// RUN: | FileCheck %s
+
+struct S {
+ char x;
+ int y;
+} __attribute__((packed, aligned(8)));
+
+struct alignas(8) T {
+ char x;
+ int y;
+} __attribute__((packed));
+
+S s;
+T t;
+// CHECK: 0 | struct T
+// CHECK-NEXT: 0 | char x
+// CHECK-NEXT: 1 | int y
+// CHECK-NEXT: | [sizeof=8, dsize=8, align=8,
+// CHECK-NEXT: | nvsize=8, nvalign=8]
+
+// CHECK: 0 | struct S
+// CHECK-NEXT: 0 | char x
+// CHECK-NEXT: 1 | int y
+// CHECK-NEXT: | [sizeof=8, dsize=8, align=8,
+// CHECK-NEXT: | nvsize=8, nvalign=8]
diff --git a/test/Layout/ms-x86-pack-and-align.cpp b/test/Layout/ms-x86-pack-and-align.cpp
index 958ee1958148..ccf8fac38e82 100644
--- a/test/Layout/ms-x86-pack-and-align.cpp
+++ b/test/Layout/ms-x86-pack-and-align.cpp
@@ -188,12 +188,12 @@ struct YA {
__declspec(align(32)) char : 1;
};
// CHECK: *** Dumping AST Record Layout
-// CHECK-NEXT: 0 | struct YA (empty)
+// CHECK-NEXT: 0 | struct YA
// CHECK-NEXT:0:0-0 | char
// CHECK-NEXT: | [sizeof=32, align=32
// CHECK-NEXT: | nvsize=32, nvalign=32]
// CHECK-X64: *** Dumping AST Record Layout
-// CHECK-X64-NEXT: 0 | struct YA (empty)
+// CHECK-X64-NEXT: 0 | struct YA
// CHECK-X64-NEXT:0:0-0 | char
// CHECK-X64-NEXT: | [sizeof=32, align=32
// CHECK-X64-NEXT: | nvsize=32, nvalign=32]
@@ -206,14 +206,14 @@ struct YB {
// CHECK: *** Dumping AST Record Layout
// CHECK-NEXT: 0 | struct YB
// CHECK-NEXT: 0 | char a
-// CHECK-NEXT: 1 | struct YA b (empty)
+// CHECK-NEXT: 1 | struct YA b
// CHECK-NEXT:1:0-0 | char
// CHECK-NEXT: | [sizeof=33, align=1
// CHECK-NEXT: | nvsize=33, nvalign=1]
// CHECK-X64: *** Dumping AST Record Layout
// CHECK-X64-NEXT: 0 | struct YB
// CHECK-X64-NEXT: 0 | char a
-// CHECK-X64-NEXT: 1 | struct YA b (empty)
+// CHECK-X64-NEXT: 1 | struct YA b
// CHECK-X64-NEXT:1:0-0 | char
// CHECK-X64-NEXT: | [sizeof=33, align=1
// CHECK-X64-NEXT: | nvsize=33, nvalign=1]
@@ -223,12 +223,12 @@ struct YC {
__declspec(align(32)) char : 1;
};
// CHECK: *** Dumping AST Record Layout
-// CHECK-NEXT: 0 | struct YC (empty)
+// CHECK-NEXT: 0 | struct YC
// CHECK-NEXT:0:0-0 | char
// CHECK-NEXT: | [sizeof=32, align=32
// CHECK-NEXT: | nvsize=32, nvalign=32]
// CHECK-X64: *** Dumping AST Record Layout
-// CHECK-X64-NEXT: 0 | struct YC (empty)
+// CHECK-X64-NEXT: 0 | struct YC
// CHECK-X64-NEXT: 0:0-0 | char
// CHECK-X64-NEXT: | [sizeof=8, align=32
// CHECK-X64-NEXT: | nvsize=8, nvalign=32]
@@ -241,14 +241,14 @@ struct YD {
// CHECK: *** Dumping AST Record Layout
// CHECK-NEXT: 0 | struct YD
// CHECK-NEXT: 0 | char a
-// CHECK-NEXT: 1 | struct YC b (empty)
+// CHECK-NEXT: 1 | struct YC b
// CHECK-NEXT:1:0-0 | char
// CHECK-NEXT: | [sizeof=33, align=1
// CHECK-NEXT: | nvsize=33, nvalign=1]
// CHECK-X64: *** Dumping AST Record Layout
// CHECK-X64-NEXT: 0 | struct YD
// CHECK-X64-NEXT: 0 | char a
-// CHECK-X64-NEXT: 1 | struct YC b (empty)
+// CHECK-X64-NEXT: 1 | struct YC b
// CHECK-X64-NEXT:1:0-0 | char
// CHECK-X64-NEXT: | [sizeof=9, align=1
// CHECK-X64-NEXT: | nvsize=9, nvalign=1]
@@ -258,12 +258,12 @@ struct YE {
__declspec(align(32)) char : 1;
};
// CHECK: *** Dumping AST Record Layout
-// CHECK-NEXT: 0 | struct YE (empty)
+// CHECK-NEXT: 0 | struct YE
// CHECK-NEXT: 0:0-0 | char
// CHECK-NEXT: | [sizeof=4, align=32
// CHECK-NEXT: | nvsize=4, nvalign=32]
// CHECK-X64: *** Dumping AST Record Layout
-// CHECK-X64-NEXT: 0 | struct YE (empty)
+// CHECK-X64-NEXT: 0 | struct YE
// CHECK-X64-NEXT: 0:0-0 | char
// CHECK-X64-NEXT: | [sizeof=4, align=32
// CHECK-X64-NEXT: | nvsize=4, nvalign=32]
@@ -276,14 +276,14 @@ struct YF {
// CHECK: *** Dumping AST Record Layout
// CHECK-NEXT: 0 | struct YF
// CHECK-NEXT: 0 | char a
-// CHECK-NEXT: 1 | struct YE b (empty)
+// CHECK-NEXT: 1 | struct YE b
// CHECK-NEXT:1:0-0 | char
// CHECK-NEXT: | [sizeof=5, align=1
// CHECK-NEXT: | nvsize=5, nvalign=1]
// CHECK-X64: *** Dumping AST Record Layout
// CHECK-X64-NEXT: 0 | struct YF
// CHECK-X64-NEXT: 0 | char a
-// CHECK-X64-NEXT: 1 | struct YE b (empty)
+// CHECK-X64-NEXT: 1 | struct YE b
// CHECK-X64-NEXT:1:0-0 | char
// CHECK-X64-NEXT: | [sizeof=5, align=1
// CHECK-X64-NEXT: | nvsize=5, nvalign=1]
diff --git a/test/Layout/v6-empty.cpp b/test/Layout/v6-empty.cpp
new file mode 100644
index 000000000000..d43db8dc32ec
--- /dev/null
+++ b/test/Layout/v6-empty.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -fsyntax-only -fclang-abi-compat=6 -triple x86_64-linux-gnu -fdump-record-layouts %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-V6
+// RUN: %clang_cc1 -fsyntax-only -fclang-abi-compat=7 -triple x86_64-linux-gnu -fdump-record-layouts %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-V7
+
+// In Clang 6 and before, we determined that Nonempty was empty, so we
+// applied EBO to it.
+struct Nonempty { int : 4; };
+struct A : Nonempty { int n; };
+int k = sizeof(A);
+
+// CHECK:*** Dumping AST Record Layout
+// CHECK: 0 | struct A
+// CHECK-V6-NEXT: 0 | struct Nonempty (base) (empty)
+// CHECK-V7-NEXT: 0 | struct Nonempty (base){{$}}
+// CHECK-NEXT: 0:0-3 | int
+// CHECK-V6-NEXT: 0 | int n
+// CHECK-V7-NEXT: 4 | int n
+// CHECK-V6-NEXT: | [sizeof=4, dsize=4, align=4,
+// CHECK-V6-NEXT: | nvsize=4, nvalign=4]
+// CHECK-V7-NEXT: | [sizeof=8, dsize=8, align=4,
+// CHECK-V7-NEXT: | nvsize=8, nvalign=4]
diff --git a/test/Layout/watchos-standard-layout.cpp b/test/Layout/watchos-standard-layout.cpp
new file mode 100644
index 000000000000..bd7bb1a434bd
--- /dev/null
+++ b/test/Layout/watchos-standard-layout.cpp
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -fsyntax-only -triple armv7k-apple-darwin-watchos -fdump-record-layouts %s | FileCheck %s
+
+// WatchOS, 64-bit iOS, and WebAssembly use the C++11 definition of POD to
+// determine whether we can reuse the tail padding of a struct (POD is
+// "trivially copyable and standard layout"). The definition of standard
+// layout changed some time around C++17; check that we still use the old
+// ABI rule.
+
+// B is not standard-layout, but it was under C++11's rule, so we pack
+// C::d into its tail padding anyway.
+struct A { int : 0; };
+struct B : A { int n; char c[3]; };
+struct C : B { char d; };
+int c = sizeof(C);
+static_assert(!__is_standard_layout(B));
+
+// CHECK:*** Dumping AST Record Layout
+// CHECK: 0 | struct C
+// CHECK-NEXT: 0 | struct B (base)
+// CHECK-NEXT: 0 | struct A (base) (empty)
+// CHECK-NEXT: 0:- | int
+// CHECK-NEXT: 0 | int n
+// CHECK-NEXT: 4 | char [3] c
+// CHECK-NEXT: 8 | char d
+// CHECK-NEXT: | [sizeof=12, dsize=9, align=4,
+// CHECK-NEXT: | nvsize=9, nvalign=4]
+
+// F is not standard-layout due to the repeated D base class, but it was under
+// C++11's rule, so we pack G::d into its tail padding anyway.
+struct D {};
+struct E : D {};
+struct F : D, E { int n; char c[3]; };
+struct G : F { G(const G&); char d; };
+int g = sizeof(G);
+static_assert(!__is_standard_layout(F));
+
+// CHECK:*** Dumping AST Record Layout
+// CHECK: 0 | struct G
+// CHECK-NEXT: 0 | struct F (base)
+// CHECK-NEXT: 0 | struct D (base) (empty)
+// CHECK-NEXT: 1 | struct E (base) (empty)
+// CHECK-NEXT: 1 | struct D (base) (empty)
+// CHECK-NEXT: 0 | int n
+// CHECK-NEXT: 4 | char [3] c
+// CHECK-NEXT: 8 | char d
+// CHECK-NEXT: | [sizeof=12, dsize=9, align=4,
+// CHECK-NEXT: | nvsize=9, nvalign=4]
diff --git a/test/Lexer/char8_t.cpp b/test/Lexer/char8_t.cpp
new file mode 100644
index 000000000000..20f820e24015
--- /dev/null
+++ b/test/Lexer/char8_t.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -std=c++2a -verify %s
+// RUN: %clang_cc1 -std=c++2a -verify %s -fchar8_t
+
+#if defined(__cpp_char8_t) && __is_identifier(char8_t)
+#error char8_t is an identifier under -fchar8_t
+#endif
+
+#if !defined(__cpp_char8_t) && !__is_identifier(char8_t)
+#error char8_t is a keyword under -fno-char8_t
+#endif
+
+char8_t c8t;
+#ifndef __cpp_char8_t
+// expected-error@-2 {{unknown type}}
+#else
+// expected-no-diagnostics
+#endif
diff --git a/test/Lexer/cxx-features.cpp b/test/Lexer/cxx-features.cpp
index a7d12e2e14f2..772fa26e96fc 100644
--- a/test/Lexer/cxx-features.cpp
+++ b/test/Lexer/cxx-features.cpp
@@ -1,23 +1,26 @@
// RUN: %clang_cc1 -std=c++98 -fcxx-exceptions -verify %s
// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -verify %s
-// RUN: %clang_cc1 -std=c++1y -fcxx-exceptions -fsized-deallocation -verify %s
// RUN: %clang_cc1 -std=c++14 -fcxx-exceptions -fsized-deallocation -verify %s
-// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fsized-deallocation -verify %s
-// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fsized-deallocation -fconcepts-ts -DCONCEPTS_TS=1 -verify %s
+// RUN: %clang_cc1 -std=c++17 -fcxx-exceptions -fsized-deallocation -verify %s
+// RUN: %clang_cc1 -std=c++2a -fcxx-exceptions -fsized-deallocation -verify %s
+//
+// RUN: %clang_cc1 -std=c++17 -fcxx-exceptions -fsized-deallocation -frelaxed-template-template-args -DRELAXED_TEMPLATE_TEMPLATE_ARGS=1 -verify %s
+// RUN: %clang_cc1 -std=c++17 -fcxx-exceptions -fsized-deallocation -fconcepts-ts -DCONCEPTS_TS=1 -verify %s
// RUN: %clang_cc1 -fno-rtti -fno-threadsafe-statics -verify %s -DNO_EXCEPTIONS -DNO_RTTI -DNO_THREADSAFE_STATICS -fsized-deallocation
// RUN: %clang_cc1 -fcoroutines-ts -DNO_EXCEPTIONS -DCOROUTINES -verify -fsized-deallocation %s
+// RUN: %clang_cc1 -fchar8_t -DNO_EXCEPTIONS -DCHAR8_T -verify -fsized-deallocation %s
// expected-no-diagnostics
// FIXME using `defined` in a macro has undefined behavior.
#if __cplusplus < 201103L
-#define check(macro, cxx98, cxx11, cxx14, cxx1z) cxx98 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx98
+#define check(macro, cxx98, cxx11, cxx14, cxx17) cxx98 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx98
#elif __cplusplus < 201402L
-#define check(macro, cxx98, cxx11, cxx14, cxx1z) cxx11 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx11
+#define check(macro, cxx98, cxx11, cxx14, cxx17) cxx11 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx11
#elif __cplusplus < 201406L
-#define check(macro, cxx98, cxx11, cxx14, cxx1z) cxx14 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx14
+#define check(macro, cxx98, cxx11, cxx14, cxx17) cxx14 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx14
#else
-#define check(macro, cxx98, cxx11, cxx14, cxx1z) cxx1z == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx1z
+#define check(macro, cxx98, cxx11, cxx14, cxx17) cxx17 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx17
#endif
// --- C++17 features ---
@@ -34,6 +37,10 @@
#error "wrong value for __cpp_aligned_new"
#endif
+#if check(guaranteed_copy_elision, 0, 0, 0, 201606)
+#error "wrong value for __cpp_guaranteed_copy_elision"
+#endif
+
#if check(noexcept_function_type, 0, 0, 0, 201510)
#error "wrong value for __cpp_noexcept_function_type"
#endif
@@ -56,10 +63,16 @@
// static_assert checked below
-#if check(deduction_guides, 0, 0, 0, 201611)
+#if check(deduction_guides, 0, 0, 0, 201703)
#error "wrong value for __cpp_deduction_guides"
#endif
+#if check(nontype_template_parameter_auto, 0, 0, 0, 201606)
+#error "wrong value for __cpp_nontype_template_parameter_auto"
+#endif
+
+// This is the old name (from P0096R4) for
+// __cpp_nontype_template_parameter_auto
#if check(template_auto, 0, 0, 0, 201606)
#error "wrong value for __cpp_template_auto"
#endif
@@ -74,6 +87,7 @@
#error "wrong value for __cpp_enumerator_attributes"
#endif
+// This is an old name (from P0096R4), now removed from SD-6.
#if check(nested_namespace_definitions, 0, 0, 0, 201411)
#error "wrong value for __cpp_nested_namespace_definitions"
#endif
@@ -96,7 +110,9 @@
#error "wrong value for __cpp_nontype_template_args"
#endif
-#if check(template_template_args, 0, 0, 0, 0) // FIXME: should be 201611 when feature is enabled
+#if defined(RELAXED_TEMPLATE_TEMPLATE_ARGS) \
+ ? check(template_template_args, 0, 0, 0, 201611) \
+ : check(template_template_args, 0, 0, 0, 0)
#error "wrong value for __cpp_template_template_args"
#endif
@@ -242,3 +258,9 @@
#if defined(COROUTINES) ? check(coroutines, 201703L, 201703L, 201703L, 201703L) : check(coroutines, 0, 0, 0, 0)
#error "wrong value for __cpp_coroutines"
#endif
+
+// --- not-yet-standard features --
+
+#if defined(CHAR8_T) ? check(char8_t, 201803, 201803, 201803, 201803) : check(char8_t, 0, 0, 0, 0)
+#error "wrong value for __cpp_char8_t"
+#endif
diff --git a/test/Lexer/cxx1y_digit_separators.cpp b/test/Lexer/cxx1y_digit_separators.cpp
index 55366342eda0..67dcd7c510ed 100644
--- a/test/Lexer/cxx1y_digit_separators.cpp
+++ b/test/Lexer/cxx1y_digit_separators.cpp
@@ -51,6 +51,8 @@ namespace floating {
float u = 0x.'p1f; // expected-error {{hexadecimal floating literal requires a significand}}
float v = 0e'f; // expected-error {{exponent has no digits}}
float w = 0x0p'f; // expected-error {{exponent has no digits}}
+ float x = 0'e+1; // expected-error {{digit separator cannot appear at end of digit sequence}}
+ float y = 0x0'p+1; // expected-error {{digit separator cannot appear at end of digit sequence}}
}
#line 123'456
diff --git a/test/Lexer/digraph.c b/test/Lexer/digraph.c
index e940caf44f4b..5d8a77d53950 100644
--- a/test/Lexer/digraph.c
+++ b/test/Lexer/digraph.c
@@ -1,6 +1,13 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -ffreestanding %s
-// expected-no-diagnostics
+// RUN: %clang_cc1 -DDIGRAPHS=1 -fsyntax-only -verify -ffreestanding %s
+// RUN: %clang_cc1 -DDIGRAPHS=1 -fno-digraphs -fdigraphs -fsyntax-only -verify -ffreestanding %s
+// RUN: %clang_cc1 -fno-digraphs -fsyntax-only -verify -ffreestanding %s
+// RUN: %clang_cc1 -fdigraphs -fno-digraphs -fsyntax-only -verify -ffreestanding %s
+// RUN: %clang_cc1 -std=c89 -DDIGRAPHS=1 -fdigraphs -fsyntax-only -verify -ffreestanding %s
+// RUN: %clang_cc1 -std=c89 -fno-digraphs -fsyntax-only -verify -ffreestanding %s
+
+#if DIGRAPHS
+// expected-no-diagnostics
%:include <stdint.h>
%:ifndef BUFSIZE
@@ -14,3 +21,15 @@
d<:len:> = s<:len:>;
%>
%>
+#else
+
+// expected-error@+1 {{expected identifier or '('}}
+%:include <stdint.h>
+;
+// expected-error@+1 {{expected ')'}} expected-note@+1{{to match this '('}}
+void copy(char d<::>);
+
+// expected-error@+1 {{expected function body}}
+void copy() <% %>
+
+#endif
diff --git a/test/Lexer/has_feature_address_sanitizer.cpp b/test/Lexer/has_feature_address_sanitizer.cpp
index b5b4de845be5..f8ae3643279b 100644
--- a/test/Lexer/has_feature_address_sanitizer.cpp
+++ b/test/Lexer/has_feature_address_sanitizer.cpp
@@ -1,6 +1,7 @@
// RUN: %clang_cc1 -E -fsanitize=address %s -o - | FileCheck --check-prefix=CHECK-ASAN %s
// RUN: %clang_cc1 -E -fsanitize=kernel-address %s -o - | FileCheck --check-prefix=CHECK-ASAN %s
// RUN: %clang_cc1 -E -fsanitize=hwaddress %s -o - | FileCheck --check-prefix=CHECK-HWASAN %s
+// RUN: %clang_cc1 -E -fsanitize=kernel-hwaddress %s -o - | FileCheck --check-prefix=CHECK-HWASAN %s
// RUN: %clang_cc1 -E %s -o - | FileCheck --check-prefix=CHECK-NO-ASAN %s
#if __has_feature(address_sanitizer)
diff --git a/test/Lexer/has_feature_objc_arc.m b/test/Lexer/has_feature_objc_arc.m
index 279b91af39cd..d5c8493daa7b 100644
--- a/test/Lexer/has_feature_objc_arc.m
+++ b/test/Lexer/has_feature_objc_arc.m
@@ -13,8 +13,16 @@ void has_objc_arc_weak_feature();
void no_objc_arc_weak_feature();
#endif
+#if __has_feature(objc_arc_fields)
+void has_objc_arc_fields();
+#else
+void no_objc_arc_fields();
+#endif
+
// CHECK-ARC: void has_objc_arc_feature();
// CHECK-ARC: void has_objc_arc_weak_feature();
+// CHECK-ARC: void has_objc_arc_fields();
// CHECK-ARCLITE: void has_objc_arc_feature();
// CHECK-ARCLITE: void no_objc_arc_weak_feature();
+// CHECK-ARCLITE: void has_objc_arc_fields();
diff --git a/test/Lexer/null-character-in-literal.c b/test/Lexer/null-character-in-literal.c
new file mode 100644
index 000000000000..a47954753676
--- /dev/null
+++ b/test/Lexer/null-character-in-literal.c
Binary files differ
diff --git a/test/Misc/ast-dump-attr.cpp b/test/Misc/ast-dump-attr.cpp
index 9e6f257a920e..1e4eb7c31955 100644
--- a/test/Misc/ast-dump-attr.cpp
+++ b/test/Misc/ast-dump-attr.cpp
@@ -68,12 +68,12 @@ __attribute__((pointer_with_type_tag(ident1,1,2)));
void TestBool(void *, int)
__attribute__((pointer_with_type_tag(bool1,1,2)));
// CHECK: FunctionDecl{{.*}}TestBool
-// CHECK: ArgumentWithTypeTagAttr{{.*}}pointer_with_type_tag bool1 0 1 IsPointer
+// CHECK: ArgumentWithTypeTagAttr{{.*}}pointer_with_type_tag bool1 1 2 IsPointer
void TestUnsigned(void *, int)
__attribute__((pointer_with_type_tag(unsigned1,1,2)));
// CHECK: FunctionDecl{{.*}}TestUnsigned
-// CHECK: ArgumentWithTypeTagAttr{{.*}} pointer_with_type_tag unsigned1 0 1
+// CHECK: ArgumentWithTypeTagAttr{{.*}} pointer_with_type_tag unsigned1 1 2
void TestInt(void) __attribute__((constructor(123)));
// CHECK: FunctionDecl{{.*}}TestInt
diff --git a/test/Misc/ast-dump-attr.m b/test/Misc/ast-dump-attr.m
new file mode 100644
index 000000000000..8775d40d9985
--- /dev/null
+++ b/test/Misc/ast-dump-attr.m
@@ -0,0 +1,57 @@
+// RUN: %clang_cc1 -fdouble-square-bracket-attributes -triple x86_64-apple-macosx10.10.0 -ast-dump -ast-dump-filter Test %s | FileCheck --strict-whitespace %s
+
+@interface NSObject
+@end
+
+[[clang::objc_exception]]
+@interface Test1 {
+// CHECK: ObjCInterfaceDecl{{.*}} Test1
+// CHECK-NEXT: ObjCExceptionAttr{{.*}}
+ [[clang::iboutlet]] NSObject *Test2;
+// CHECK: ObjCIvarDecl{{.*}} Test2
+// CHECK-NEXT: IBOutletAttr
+}
+@property (readonly) [[clang::objc_returns_inner_pointer]] void *Test3, *Test4;
+// CHECK: ObjCPropertyDecl{{.*}} Test3 'void *' readonly
+// CHECK-NEXT: ObjCReturnsInnerPointerAttr
+// CHECK-NEXT: ObjCPropertyDecl{{.*}} Test4 'void *' readonly
+// CHECK-NEXT: ObjCReturnsInnerPointerAttr
+
+@property (readonly) [[clang::iboutlet]] NSObject *Test5;
+// CHECK: ObjCPropertyDecl{{.*}} Test5 'NSObject *' readonly
+// CHECK-NEXT: IBOutletAttr
+
+// CHECK: ObjCMethodDecl{{.*}} implicit{{.*}} Test3
+// CHECK-NEXT: ObjCReturnsInnerPointerAttr
+// CHECK: ObjCMethodDecl{{.*}} implicit{{.*}} Test4
+// CHECK-NEXT: ObjCReturnsInnerPointerAttr
+// CHECK: ObjCMethodDecl{{.*}} implicit{{.*}} Test5
+// CHECK-NOT: IBOutletAttr
+@end
+
+[[clang::objc_runtime_name("name")]] @protocol Test6;
+// CHECK: ObjCProtocolDecl{{.*}} Test6
+// CHECK-NEXT: ObjCRuntimeNameAttr{{.*}} "name"
+
+[[clang::objc_protocol_requires_explicit_implementation]]
+@protocol Test7
+// CHECK: ObjCProtocolDecl{{.*}} Test7
+// CHECK-NEXT: ObjCExplicitProtocolImplAttr
+@end
+
+@interface Test8
+// CHECK: ObjCInterfaceDecl{{.*}} Test8
+-(void)Test9 [[clang::ns_consumes_self]];
+// CHECK: ObjCMethodDecl{{.*}} Test9 'void'
+// CHECK-NEXT: NSConsumesSelfAttr
+-(void) [[clang::ns_consumes_self]] Test10: (int)Test11;
+// CHECK: ObjCMethodDecl{{.*}} Test10: 'void'
+// CHECK-NEXT: |-ParmVarDecl{{.*}} Test11 'int'
+// CHECK-NEXT: `-NSConsumesSelfAttr
+-(void)Test12: (int *) [[clang::noescape]] Test13 to:(int)Test14 [[clang::ns_consumes_self]];
+// CHECK: ObjCMethodDecl{{.*}} Test12:to: 'void'
+// CHECK-NEXT: |-ParmVarDecl{{.*}} Test13 'int *'
+// CHECK-NEXT: | `-NoEscapeAttr
+// CHECK-NEXT: |-ParmVarDecl{{.*}} Test14 'int'
+// CHECK-NEXT: `-NSConsumesSelfAttr
+@end
diff --git a/test/Misc/ast-dump-decl.cpp b/test/Misc/ast-dump-decl.cpp
index c689149af06b..21ba7ec8dad2 100644
--- a/test/Misc/ast-dump-decl.cpp
+++ b/test/Misc/ast-dump-decl.cpp
@@ -360,7 +360,9 @@ class TestClassScopeFunctionSpecialization {
template<> void foo<int>(int a) { }
};
// CHECK: ClassScopeFunctionSpecializationDecl
-// CHECK-NEXT: CXXMethod{{.*}} 'foo' 'void (int)'
+// CHECK-NEXT: CXXMethod{{.*}} foo 'void (int)'
+// CHECK-NEXT: ParmVarDecl
+// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: TemplateArgument{{.*}} 'int'
namespace TestTemplateTypeParmDecl {
diff --git a/test/Misc/ast-dump-stmt.c b/test/Misc/ast-dump-stmt.c
index 1f21cf03f695..461893188a16 100644
--- a/test/Misc/ast-dump-stmt.c
+++ b/test/Misc/ast-dump-stmt.c
@@ -30,6 +30,38 @@ int TestOpaqueValueExpr = 0 ?: 1;
// CHECK-NEXT: IntegerLiteral
// CHECK-NEXT: OpaqueValueExpr
// CHECK-NEXT: IntegerLiteral
-// CHECK-NEXT: OpaqueValueExpr
-// CHECK-NEXT: IntegerLiteral
-// CHECK-NEXT: IntegerLiteral
+// CHECK-NEXT: OpaqueValueExpr
+// CHECK-NEXT: IntegerLiteral
+// CHECK-NEXT: IntegerLiteral
+
+void TestUnaryOperatorExpr(void) {
+ char T1 = 1;
+ int T2 = 1;
+
+ T1++;
+ T2++;
+ // CHECK: UnaryOperator{{.*}}postfix '++' cannot overflow
+ // CHECK-NEXT: DeclRefExpr{{.*}}'T1' 'char'
+ // CHECK-NOT: UnaryOperator{{.*}}postfix '++' cannot overflow
+ // CHECK: DeclRefExpr{{.*}}'T2' 'int'
+
+ -T1;
+ -T2;
+ // CHECK: UnaryOperator{{.*}}prefix '-' cannot overflow
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr{{.*}}'T1' 'char'
+ // CHECK-NOT: UnaryOperator{{.*}}prefix '-' cannot overflow
+ // CHECK: ImplicitCastExpr
+ // CHECK: DeclRefExpr{{.*}}'T2' 'int'
+
+ ~T1;
+ ~T2;
+ // CHECK: UnaryOperator{{.*}}prefix '~' cannot overflow
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr{{.*}}'T1' 'char'
+ // CHECK: UnaryOperator{{.*}}prefix '~' cannot overflow
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr{{.*}}'T2' 'int'
+}
diff --git a/test/Misc/ast-print-bool.c b/test/Misc/ast-print-bool.c
new file mode 100644
index 000000000000..05519bcd4e54
--- /dev/null
+++ b/test/Misc/ast-print-bool.c
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -verify -ast-print %s -xc -DDEF_BOOL_CBOOL \
+// RUN: | FileCheck %s --check-prefixes=BOOL-AS-CBOOL,CBOOL
+//
+// RUN: %clang_cc1 -verify -ast-print %s -xc -DDEF_BOOL_CBOOL -DDIAG \
+// RUN: | FileCheck %s --check-prefixes=BOOL-AS-CBOOL,CBOOL
+//
+// RUN: %clang_cc1 -verify -ast-print %s -xc -DDEF_BOOL_INT \
+// RUN: | FileCheck %s --check-prefixes=BOOL-AS-INT,CBOOL
+//
+// RUN: %clang_cc1 -verify -ast-print %s -xc -DDEF_BOOL_INT -DDIAG \
+// RUN: | FileCheck %s --check-prefixes=BOOL-AS-INT,CBOOL
+//
+// RUN: %clang_cc1 -verify -ast-print %s -xc++ \
+// RUN: | FileCheck %s --check-prefixes=BOOL-AS-BOOL
+//
+// RUN: %clang_cc1 -verify -ast-print %s -xc++ -DDIAG \
+// RUN: | FileCheck %s --check-prefixes=BOOL-AS-BOOL
+
+#if DEF_BOOL_CBOOL
+# define bool _Bool
+#elif DEF_BOOL_INT
+# define bool int
+#endif
+
+// BOOL-AS-CBOOL: _Bool i;
+// BOOL-AS-INT: int i;
+// BOOL-AS-BOOL: bool i;
+bool i;
+
+#ifndef __cplusplus
+// CBOOL: _Bool j;
+_Bool j;
+#endif
+
+// Induce a diagnostic (and verify we actually managed to do so), which used to
+// permanently alter the -ast-print printing policy for _Bool. How bool is
+// defined by the preprocessor is examined only once per compilation, when the
+// diagnostic is emitted, and it used to affect the entirety of -ast-print, so
+// test only one definition of bool per compilation.
+#if DIAG
+void fn() { 1; } // expected-warning {{expression result unused}}
+#else
+// expected-no-diagnostics
+#endif
diff --git a/test/Misc/ast-print-enum-decl.c b/test/Misc/ast-print-enum-decl.c
new file mode 100644
index 000000000000..fba931344285
--- /dev/null
+++ b/test/Misc/ast-print-enum-decl.c
@@ -0,0 +1,105 @@
+// First check compiling and printing of this file.
+//
+// RUN: %clang_cc1 -verify -ast-print %s > %t.c
+// RUN: FileCheck --check-prefixes=CHECK,PRINT %s --input-file %t.c
+//
+// Now check compiling and printing of the printed file.
+//
+// RUN: echo "// expected""-warning@* 6 {{'T' is deprecated}}" >> %t.c
+// RUN: echo "// expected""-note@* 6 {{'T' has been explicitly marked deprecated here}}" >> %t.c
+//
+// RUN: %clang_cc1 -verify -ast-print %t.c \
+// RUN: | FileCheck --check-prefixes=CHECK,PRINT %s
+
+// END.
+
+// CHECK-LABEL: defFirst
+void defFirst() {
+ // PRINT-NEXT: enum
+ // PRINT-DAG: __attribute__((aligned(16)))
+ // PRINT-DAG: __attribute__((deprecated("")))
+ // PRINT-SAME: T {
+ // PRINT-NEXT: E0,
+ // PRINT-NEXT: E1
+ // PRINT-NEXT: } *p0;
+ // expected-warning@+2 {{'T' is deprecated}}
+ // expected-note@+1 2 {{'T' has been explicitly marked deprecated here}}
+ enum __attribute__((aligned(16))) __attribute__((deprecated(""))) T {
+ E0, E1
+ } *p0;
+
+ // PRINT-NEXT: enum T *p1;
+ enum T *p1; // expected-warning {{'T' is deprecated}}
+}
+
+// CHECK-LABEL: defLast
+void defLast() {
+ // PRINT-NEXT: enum __attribute__((aligned(16))) T *p0;
+ enum __attribute__((aligned(16))) T *p0;
+
+ // PRINT-NEXT: enum __attribute__((deprecated(""))) T {
+ // PRINT-NEXT: E0,
+ // PRINT-NEXT: E1
+ // PRINT-NEXT: } *p1;
+ // expected-warning@+2 {{'T' is deprecated}}
+ // expected-note@+1 {{'T' has been explicitly marked deprecated here}}
+ enum __attribute__((deprecated(""))) T { E0, E1 } *p1;
+}
+
+// CHECK-LABEL: defMiddle
+void defMiddle() {
+ // PRINT-NEXT: enum __attribute__((deprecated(""))) T *p0;
+ // expected-warning@+2 {{'T' is deprecated}}
+ // expected-note@+1 3 {{'T' has been explicitly marked deprecated here}}
+ enum __attribute__((deprecated(""))) T *p0;
+
+ // PRINT-NEXT: enum __attribute__((aligned(16))) T {
+ // PRINT-NEXT: E0
+ // PRINT-NEXT: E1
+ // PRINT-NEXT: } *p1;
+ enum __attribute__((aligned(16))) T { E0, E1 } *p1; // expected-warning {{'T' is deprecated}}
+
+ // PRINT-NEXT: enum T *p2;
+ enum T *p2; // expected-warning {{'T' is deprecated}}
+}
+
+// CHECK-LABEL: declsOnly
+void declsOnly() {
+ // FIXME: For some reason, attributes are ignored if they're not on the first
+ // declaration and not on the definition.
+
+ // PRINT-NEXT: enum __attribute__((aligned)) T *p0;
+ enum __attribute__((aligned)) T *p0;
+
+ // PRINT-NEXT: enum T *p1;
+ enum __attribute__((may_alias)) T *p1;
+
+ // PRINT-NEXT: enum T *p2;
+ enum T *p2;
+
+ // PRINT-NEXT: enum T *p3;
+ enum __attribute__((deprecated(""))) T *p3;
+
+ // PRINT-NEXT: enum T *p4;
+ enum T *p4;
+}
+
+// Check that tag decl groups stay together in decl contexts.
+
+// PRINT-LABEL: enum DeclGroupAtFileScope {
+// PRINT-NEXT: DeclGroupAtFileScope0
+// PRINT-NEXT: } *DeclGroupAtFileScopePtr;
+enum DeclGroupAtFileScope { DeclGroupAtFileScope0 } *DeclGroupAtFileScopePtr;
+
+// PRINT-LABEL: struct DeclGroupInMemberList
+struct DeclGroupInMemberList {
+ // PRINT-NEXT: enum T1 {
+ // PRINT-NEXT: T10
+ // PRINT-NEXT: } *p0;
+ enum T1 { T10 } *p0;
+ // PRINT-NEXT: enum T2 {
+ // PRINT-NEXT: T20
+ // PRINT-NEXT: } *p1, *p2;
+ enum T2 { T20 } *p1, *p2;
+ // PRINT-NEXT: };
+};
diff --git a/test/Misc/ast-print-objectivec.m b/test/Misc/ast-print-objectivec.m
index cb5aacc06a49..05a0a5d4aa74 100644
--- a/test/Misc/ast-print-objectivec.m
+++ b/test/Misc/ast-print-objectivec.m
@@ -30,7 +30,7 @@
// CHECK: @end
// CHECK: @interface I(CAT)
-// CHECK: - (void)MethCAT __attribute__((availability(macos, introduced=10_1_0, deprecated=10_2)));
+// CHECK: - (void)MethCAT __attribute__((availability(macos, introduced=10.1.0, deprecated=10.2)));
// CHECK: @end
// CHECK: @implementation I
@@ -50,3 +50,13 @@ struct __attribute__((objc_bridge_related(C1,,))) S1;
// CHECK: @class C1;
// CHECK: struct __attribute__((objc_bridge_related(C1, , ))) S1;
+
+@interface ImplicitPropertyWithSetterOnly
+
+- (void)setX:(int)x;
+
+@end
+
+void printImplicitPropertyWithSetterOnly(ImplicitPropertyWithSetterOnly *x) {
+ x.x = 313; // CHECK: x.x = 313;
+}
diff --git a/test/Misc/ast-print-pragmas-xfail.cpp b/test/Misc/ast-print-pragmas-xfail.cpp
index 994e1fda3205..69ba48d0de29 100644
--- a/test/Misc/ast-print-pragmas-xfail.cpp
+++ b/test/Misc/ast-print-pragmas-xfail.cpp
@@ -5,7 +5,7 @@
void run1(int *List, int Length) {
int i = 0;
-// CEHCK: #pragma loop vectorize(4)
+// CHECK: #pragma loop vectorize(4)
// CHECK-NEXT: #pragma loop interleave(8)
// CHECK-NEXT: #pragma loop vectorize(enable)
// CHECK-NEXT: #pragma loop interleave(enable)
diff --git a/test/Misc/ast-print-pragmas.cpp b/test/Misc/ast-print-pragmas.cpp
index 5840c1a2c3be..f1a7b2479b6b 100644
--- a/test/Misc/ast-print-pragmas.cpp
+++ b/test/Misc/ast-print-pragmas.cpp
@@ -4,7 +4,7 @@
// FIXME: A bug in ParsedAttributes causes the order of the attributes to be
// reversed. The checks are consequently in the reverse order below.
-// CHECK: #pragma clang loop interleave_count(8)
+// CHECK: #pragma clang loop interleave_count(8){{$}}
// CHECK-NEXT: #pragma clang loop vectorize_width(4)
void test(int *List, int Length) {
@@ -61,7 +61,7 @@ void test_templates(int *List, int Length) {
#ifdef MS_EXT
#pragma init_seg(compiler)
-// MS-EXT: #pragma init_seg (.CRT$XCC)
+// MS-EXT: #pragma init_seg (.CRT$XCC){{$}}
// MS-EXT-NEXT: int x = 3 __declspec(thread);
int __declspec(thread) x = 3;
#endif //MS_EXT
diff --git a/test/Misc/ast-print-record-decl.c b/test/Misc/ast-print-record-decl.c
new file mode 100644
index 000000000000..c27fdf42f337
--- /dev/null
+++ b/test/Misc/ast-print-record-decl.c
@@ -0,0 +1,291 @@
+// Check struct:
+//
+// First check compiling and printing of this file.
+//
+// RUN: %clang -target x86_64-linux -Xclang -verify -S -emit-llvm \
+// RUN: -DKW=struct -DBASES= -o - %s \
+// RUN: | FileCheck --check-prefixes=CHECK,LLVM %s
+//
+// RUN: %clang_cc1 -verify -ast-print -DKW=struct -DBASES= %s > %t.c
+// RUN: FileCheck --check-prefixes=CHECK,PRINT,PRINT-C -DKW=struct -DBASES= \
+// RUN: %s --input-file %t.c
+//
+// Now check compiling and printing of the printed file.
+//
+// RUN: echo "// expected""-warning@* 10 {{'T' is deprecated}}" >> %t.c
+// RUN: echo "// expected""-note@* 10 {{'T' has been explicitly marked deprecated here}}" >> %t.c
+//
+// RUN: %clang -target x86_64-linux -Xclang -verify -S -emit-llvm -o - %t.c \
+// RUN: | FileCheck --check-prefixes=CHECK,LLVM %s
+//
+// RUN: %clang_cc1 -verify -ast-print %t.c \
+// RUN: | FileCheck --check-prefixes=CHECK,PRINT,PRINT-C -DKW=struct \
+// RUN: -DBASES= %s
+
+// Repeat for union:
+//
+// First check compiling and printing of this file.
+//
+// RUN: %clang -target x86_64-linux -Xclang -verify -S -emit-llvm \
+// RUN: -DKW=union -DBASES= -o - %s \
+// RUN: | FileCheck --check-prefixes=CHECK,LLVM %s
+//
+// RUN: %clang_cc1 -verify -ast-print -DKW=union -DBASES= %s > %t.c
+// RUN: FileCheck --check-prefixes=CHECK,PRINT,PRINT-C -DKW=union -DBASES= \
+// RUN: %s --input-file %t.c
+//
+// Now check compiling and printing of the printed file.
+//
+// RUN: echo "// expected""-warning@* 10 {{'T' is deprecated}}" >> %t.c
+// RUN: echo "// expected""-note@* 10 {{'T' has been explicitly marked deprecated here}}" >> %t.c
+//
+// RUN: %clang -target x86_64-linux -Xclang -verify -S -emit-llvm -o - %t.c \
+// RUN: | FileCheck --check-prefixes=CHECK,LLVM %s
+//
+// RUN: %clang_cc1 -verify -ast-print %t.c \
+// RUN: | FileCheck --check-prefixes=CHECK,PRINT,PRINT-C -DKW=union \
+// RUN: -DBASES= %s
+
+// Repeat for C++ (BASES helps ensure we're printing as C++ not as C):
+//
+// First check compiling and printing of this file.
+//
+// RUN: %clang -target x86_64-linux -Xclang -verify -S -emit-llvm \
+// RUN: -DKW=struct -DBASES=' : B' -o - -xc++ %s \
+// RUN: | FileCheck --check-prefixes=CHECK,LLVM %s
+//
+// RUN: %clang_cc1 -verify -ast-print -DKW=struct -DBASES=' : B' -xc++ %s \
+// RUN: > %t.cpp
+// RUN: FileCheck --check-prefixes=CHECK,PRINT,PRINT-CXX -DKW=struct \
+// RUN: -DBASES=' : B' %s --input-file %t.cpp
+//
+// Now check compiling and printing of the printed file.
+//
+// RUN: echo "// expected""-warning@* 10 {{'T' is deprecated}}" > %t.diags
+// RUN: echo "// expected""-note@* 10 {{'T' has been explicitly marked deprecated here}}" >> %t.diags
+// RUN: cat %t.diags >> %t.cpp
+//
+// RUN: %clang -target x86_64-linux -Xclang -verify -S -emit-llvm -o - %t.cpp \
+// RUN: | FileCheck --check-prefixes=CHECK,LLVM %s
+//
+// RUN: %clang_cc1 -verify -ast-print %t.cpp \
+// RUN: | FileCheck --check-prefixes=CHECK,PRINT,PRINT-CXX -DKW=struct \
+// RUN: -DBASES=' : B' %s
+//
+// Make sure implicit attributes aren't printed. See comments in inMemberPtr
+// for details.
+//
+// RUN: %clang_cc1 -triple i686-pc-win32 -verify -ast-print -DKW=struct \
+// RUN: -DBASES=' : B' -xc++ %s > %t.cpp
+// RUN: FileCheck --check-prefixes=CHECK,PRINT,PRINT-CXX -DKW=struct \
+// RUN: -DBASES=' : B' %s --input-file %t.cpp
+//
+// RUN: cat %t.diags >> %t.cpp
+// RUN: %clang_cc1 -triple i686-pc-win32 -verify -ast-print %t.cpp \
+// RUN: | FileCheck --check-prefixes=CHECK,PRINT,PRINT-CXX -DKW=struct \
+// RUN: -DBASES=' : B' %s
+
+// END.
+
+#ifndef KW
+# error KW undefined
+# define KW struct // help syntax checkers
+#endif
+
+#ifndef BASES
+# error BASES undefined
+# define BASES // help syntax checkers
+#endif
+
+struct B {};
+
+// CHECK-LABEL: defFirst
+void defFirst() {
+ // PRINT-NEXT: [[KW]]
+ // PRINT-DAG: __attribute__((aligned(16)))
+ // PRINT-DAG: __attribute__((deprecated("")))
+ // PRINT-NOT: __attribute__
+ // PRINT-SAME: T[[BASES]] {
+ // PRINT-NEXT: int i;
+ // PRINT-NEXT: } *p0;
+ // expected-warning@+2 {{'T' is deprecated}}
+ // expected-note@+1 2 {{'T' has been explicitly marked deprecated here}}
+ KW __attribute__((aligned(16))) __attribute__((deprecated(""))) T BASES {
+ int i;
+ } *p0;
+
+ // PRINT-NEXT: [[KW]] T *p1;
+ KW T *p1; // expected-warning {{'T' is deprecated}}
+
+ // LLVM: store i64 16
+ long s0 = sizeof *p0;
+ // LLVM-NEXT: store i64 16
+ long s1 = sizeof *p1;
+}
+
+// CHECK-LABEL: defLast
+void defLast() {
+ // PRINT-NEXT: [[KW]] __attribute__((aligned(16))) T *p0;
+ KW __attribute__((aligned(16))) T *p0;
+
+ // PRINT-NEXT: [[KW]] __attribute__((deprecated(""))) T[[BASES]] {
+ // PRINT-NEXT: int i;
+ // PRINT-NEXT: } *p1;
+ // expected-warning@+2 {{'T' is deprecated}}
+ // expected-note@+1 {{'T' has been explicitly marked deprecated here}}
+ KW __attribute__((deprecated(""))) T BASES { int i; } *p1;
+
+ // LLVM: store i64 16
+ long s0 = sizeof *p0;
+ // LLVM-NEXT: store i64 16
+ long s1 = sizeof *p1;
+}
+
+// CHECK-LABEL: defMiddle
+void defMiddle() {
+ // PRINT-NEXT: [[KW]] __attribute__((deprecated(""))) T *p0;
+ // expected-warning@+2 {{'T' is deprecated}}
+ // expected-note@+1 3 {{'T' has been explicitly marked deprecated here}}
+ KW __attribute__((deprecated(""))) T *p0;
+
+ // PRINT-NEXT: [[KW]] __attribute__((aligned(16))) T[[BASES]] {
+ // PRINT-NEXT: int i;
+ // PRINT-NEXT: } *p1;
+ KW __attribute__((aligned(16))) T BASES { int i; } *p1; // expected-warning {{'T' is deprecated}}
+
+ // PRINT-NEXT: [[KW]] T *p2;
+ KW T *p2; // expected-warning {{'T' is deprecated}}
+
+ // LLVM: store i64 16
+ long s0 = sizeof *p0;
+ // LLVM-NEXT: store i64 16
+ long s1 = sizeof *p1;
+ // LLVM-NEXT: store i64 16
+ long s2 = sizeof *p2;
+}
+
+// CHECK-LABEL: defSelfRef
+void defSelfRef() {
+ // PRINT-NEXT: [[KW]] __attribute__((deprecated(""))) T *p0;
+ // expected-warning@+2 {{'T' is deprecated}}
+ // expected-note@+1 2 {{'T' has been explicitly marked deprecated here}}
+ KW __attribute__((deprecated(""))) T *p0;
+
+ // PRINT-NEXT: [[KW]] __attribute__((aligned(64))) T[[BASES]] {
+ // PRINT-NEXT: int i;
+ // PRINT-NEXT: [[KW]] T *p2;
+ // PRINT-NEXT: [[KW]] __attribute__((may_alias)) T *p3;
+ // PRINT-NEXT: [[KW]] T *p4;
+ // PRINT-NEXT: } *p1;
+ KW __attribute__((aligned(64))) T BASES { // expected-warning {{'T' is deprecated}}
+ int i;
+ KW T *p2;
+ // FIXME: For C++, T at p3 loses aligned and deprecated, perhaps because
+ // that RecordDecl isn't in the same redecl list. Perhaps the redecl lists
+ // are split here but not in C due to the different scoping rules in C++
+ // classes.
+ KW __attribute__((may_alias)) T *p3;
+ KW T *p4;
+ } *p1;
+
+ // LLVM: store i64 64
+ long s0 = sizeof *p0;
+ // LLVM-NEXT: store i64 64
+ long s1 = sizeof *p1;
+ // LLVM-NEXT: store i64 64
+ long s2 = sizeof *p0->p2;
+ // LLVM-NEXT: store i64 64
+ long s3 = sizeof *p1->p3;
+ // LLVM-NEXT: store i64 64
+ long s4 = sizeof *p1->p4->p2;
+}
+
+// CHECK-LABEL: declsOnly
+void declsOnly() {
+ // PRINT-NEXT: [[KW]] T *p0;
+ KW T *p0;
+
+ // PRINT-NEXT: [[KW]] __attribute__((may_alias)) T *p1;
+ KW __attribute__((may_alias)) T *p1;
+
+ // PRINT-NEXT: [[KW]] T *p2;
+ KW T *p2;
+
+ // PRINT-NEXT: [[KW]] __attribute__((deprecated(""))) T *p3;
+ // expected-warning@+2 {{'T' is deprecated}}
+ // expected-note@+1 2 {{'T' has been explicitly marked deprecated here}}
+ KW __attribute__((deprecated(""))) T *p3;
+
+ // PRINT-NEXT: [[KW]] T *p4;
+ KW T *p4; // expected-warning {{'T' is deprecated}}
+}
+
+// Make sure expanded printing of tag types is turned back off in other parts
+// of a tag declaration. The base class list is checked above.
+
+// CHECK-LABEL: inMembers
+void inMembers() {
+ // PRINT-NEXT: [[KW]] T1 {
+ // PRINT-NEXT: int i;
+ // PRINT-NEXT: };
+ KW T1 { int i; };
+ // PRINT-NEXT: [[KW]] T2 {
+ // PRINT-NEXT: [[KW]] T1 i;
+ // PRINT-NEXT: };
+ KW T2 { KW T1 i; };
+}
+
+// CHECK-LABEL: inInit
+void inInit() {
+ // PRINT-NEXT: [[KW]] T1 {
+ // PRINT-NEXT: int i;
+ // PRINT-NEXT: };
+ KW T1 { int i; };
+ // PRINT-NEXT: [[KW]] T2 {
+ // PRINT-NEXT: long i;
+ // PRINT-NEXT: } t2 = {sizeof([[KW]] T1)};
+ KW T2 { long i; } t2 = {sizeof(KW T1)};
+}
+
+#ifdef __cplusplus
+// PRINT-CXX-LABEL: inMemberPtr
+void inMemberPtr() {
+ // Under windows, the implicit attribute __single_inheritance used to print
+ // between KW and T1 here, but that wasn't faithful to the original source.
+ //
+ // PRINT-CXX-NEXT: [[KW]] T1 {
+ // PRINT-CXX-NEXT: int i;
+ // PRINT-CXX-NEXT: };
+ KW T1 { int i; };
+ // PRINT-CXX-NEXT: [[KW]] T2 {
+ // PRINT-CXX-NEXT: } T1::*p;
+ KW T2 {} T1::*p;
+}
+#endif
+
+// Check that tag decl groups stay together in decl contexts.
+
+// PRINT-LABEL: DeclGroupAtFileScope {
+// PRINT-NEXT: int i;
+// PRINT-NEXT: } *DeclGroupAtFileScopePtr;
+KW DeclGroupAtFileScope { int i; } *DeclGroupAtFileScopePtr;
+
+// PRINT-LABEL: DeclGroupInMemberList {
+KW DeclGroupInMemberList {
+ // PRINT-NEXT: struct T1 {
+ // PRINT-NEXT: int i;
+ // PRINT-NEXT: } t1;
+ struct T1 { int i; } t1;
+ // PRINT-NEXT: union T2 {
+ // PRINT-NEXT: int i;
+ // PRINT-NEXT: } *t20, t21[2];
+ union T2 { int i; } *t20, t21[2];
+ // PRINT-NEXT: enum T3 {
+ // PRINT-NEXT: T30
+ // PRINT-NEXT: } t30;
+ enum T3 { T30 } t30;
+ // PRINT-NEXT: };
+};
+
+// A tag decl group in the tag decl's own member list is exercised in
+// defSelfRef above.
diff --git a/test/Misc/attr-print-emit.cpp b/test/Misc/attr-print-emit.cpp
new file mode 100644
index 000000000000..cc7413baf10e
--- /dev/null
+++ b/test/Misc/attr-print-emit.cpp
@@ -0,0 +1,69 @@
+// RUN: %clang_cc1 %s -ast-print | FileCheck %s
+// RUN: %clang -emit-ast -o %t.ast %s
+// RUN: %clang_cc1 %t.ast -ast-print | FileCheck %s
+
+// CHECK: void xla(int a) __attribute__((xray_log_args(1)));
+void xla(int a) __attribute__((xray_log_args(1)));
+
+// CHECK: void *as2(int, int) __attribute__((alloc_size(1, 2)));
+void *as2(int, int) __attribute__((alloc_size(1, 2)));
+// CHECK: void *as1(void *, int) __attribute__((alloc_size(2)));
+void *as1(void *, int) __attribute__((alloc_size(2)));
+
+// CHECK: void fmt(int, const char *, ...) __attribute__((format(printf, 2, 3)));
+void fmt(int, const char *, ...) __attribute__((format(printf, 2, 3)));
+
+// CHECK: char *fmta(int, const char *) __attribute__((format_arg(2)));
+char *fmta(int, const char *) __attribute__((format_arg(2)));
+
+// CHECK: void nn(int *, int *) __attribute__((nonnull(1, 2)));
+void nn(int *, int *) __attribute__((nonnull(1, 2)));
+
+// CHECK: int *aa(int i) __attribute__((alloc_align(1)));
+int *aa(int i) __attribute__((alloc_align(1)));
+
+// CHECK: void ownt(int *, int *) __attribute__((ownership_takes(foo, 1, 2)));
+void ownt(int *, int *) __attribute__((ownership_takes(foo, 1, 2)));
+// CHECK: void ownh(int *, int *) __attribute__((ownership_holds(foo, 1, 2)));
+void ownh(int *, int *) __attribute__((ownership_holds(foo, 1, 2)));
+// CHECK: void ownr(int) __attribute__((ownership_returns(foo, 1)));
+void ownr(int) __attribute__((ownership_returns(foo, 1)));
+
+// CHECK: void awtt(int, int, ...) __attribute__((argument_with_type_tag(foo, 3, 2)));
+void awtt(int, int, ...) __attribute__((argument_with_type_tag(foo, 3, 2)));
+// CHECK: void pwtt(void *, int) __attribute__((pointer_with_type_tag(foo, 1, 2)));
+void pwtt(void *, int) __attribute__((pointer_with_type_tag(foo, 1, 2)));
+
+class C {
+ // CHECK: void xla(int a) __attribute__((xray_log_args(2)));
+ void xla(int a) __attribute__((xray_log_args(2)));
+
+ // CHECK: void *as2(int, int) __attribute__((alloc_size(2, 3)));
+ void *as2(int, int) __attribute__((alloc_size(2, 3)));
+ // CHECK: void *as1(void *, int) __attribute__((alloc_size(3)));
+ void *as1(void *, int) __attribute__((alloc_size(3)));
+
+ // CHECK: void fmt(int, const char *, ...) __attribute__((format(printf, 3, 4)));
+ void fmt(int, const char *, ...) __attribute__((format(printf, 3, 4)));
+
+ // CHECK: char *fmta(int, const char *) __attribute__((format_arg(3)));
+ char *fmta(int, const char *) __attribute__((format_arg(3)));
+
+ // CHECK: void nn(int *, int *) __attribute__((nonnull(2, 3)));
+ void nn(int *, int *) __attribute__((nonnull(2, 3)));
+
+ // CHECK: int *aa(int i) __attribute__((alloc_align(2)));
+ int *aa(int i) __attribute__((alloc_align(2)));
+
+ // CHECK: void ownt(int *, int *) __attribute__((ownership_takes(foo, 2, 3)));
+ void ownt(int *, int *) __attribute__((ownership_takes(foo, 2, 3)));
+ // CHECK: void ownh(int *, int *) __attribute__((ownership_holds(foo, 2, 3)));
+ void ownh(int *, int *) __attribute__((ownership_holds(foo, 2, 3)));
+ // CHECK: void ownr(int) __attribute__((ownership_returns(foo, 2)));
+ void ownr(int) __attribute__((ownership_returns(foo, 2)));
+
+ // CHECK: void awtt(int, int, ...) __attribute__((argument_with_type_tag(foo, 4, 3)));
+ void awtt(int, int, ...) __attribute__((argument_with_type_tag(foo, 4, 3)));
+ // CHECK: void pwtt(void *, int) __attribute__((pointer_with_type_tag(foo, 2, 3)));
+ void pwtt(void *, int) __attribute__((pointer_with_type_tag(foo, 2, 3)));
+};
diff --git a/test/Misc/backend-stack-frame-diagnostics.cpp b/test/Misc/backend-stack-frame-diagnostics.cpp
index bb5566f1a431..e460294e1c7c 100644
--- a/test/Misc/backend-stack-frame-diagnostics.cpp
+++ b/test/Misc/backend-stack-frame-diagnostics.cpp
@@ -1,6 +1,6 @@
// REQUIRES: x86-registered-target
-// RUN: %clang -target i386-apple-darwin -std=c++11 -fblocks -Wframe-larger-than=70 -Xclang -verify -o /dev/null -c %s
-// RUN: %clang -target i386-apple-darwin -std=c++11 -fblocks -Wframe-larger-than=70 -Xclang -verify -o /dev/null -c %s -DIS_SYSHEADER
+// RUN: %clang -target i386-apple-darwin -std=c++11 -fblocks -Wframe-larger-than=70 -Wno-stdlibcxx-not-found -Xclang -verify -o /dev/null -c %s
+// RUN: %clang -target i386-apple-darwin -std=c++11 -fblocks -Wframe-larger-than=70 -Wno-stdlibcxx-not-found -Xclang -verify -o /dev/null -c %s -DIS_SYSHEADER
// Test that:
// * The driver passes the option through to the backend.
diff --git a/test/Misc/cc1as-split-dwarf.s b/test/Misc/cc1as-split-dwarf.s
new file mode 100644
index 000000000000..0d507b1927d2
--- /dev/null
+++ b/test/Misc/cc1as-split-dwarf.s
@@ -0,0 +1,26 @@
+// REQUIRES: x86-registered-target
+// RUN: %clang -cc1as -triple x86_64-pc-linux-gnu %s -filetype obj -o %t1 -split-dwarf-file %t2
+// RUN: llvm-objdump -s %t1 | FileCheck --check-prefix=O %s
+// RUN: llvm-objdump -s %t2 | FileCheck --check-prefix=DWO %s
+
+// O-NOT: Contents of section
+// O: Contents of section .strtab:
+// O-NOT: Contents of section
+// O: Contents of section .text:
+// O-NEXT: 0000 c3
+// O-NEXT: Contents of section .symtab:
+// O-NOT: Contents of section
+.globl main
+main:
+.Ltmp1:
+ret
+.Ltmp2:
+
+// DWO-NOT: Contents of section
+// DWO: Contents of section .strtab:
+// DWO-NOT: Contents of section
+// DWO: Contents of section .foo.dwo:
+// DWO-NEXT: 0000 01000000
+// DWO-NOT: Contents of section
+.section .foo.dwo
+.long .Ltmp2-.Ltmp1
diff --git a/test/Misc/dev-fd-fs.c b/test/Misc/dev-fd-fs.c
index d1f13286aa8e..f04b059a6436 100644
--- a/test/Misc/dev-fd-fs.c
+++ b/test/Misc/dev-fd-fs.c
@@ -1,5 +1,6 @@
// Check that we can operate on files from /dev/fd.
// REQUIRES: dev-fd-fs
+// REQUIRES: shell
// Check reading from named pipes. We cat the input here instead of redirecting
// it to ensure that /dev/fd/0 is a named pipe, not just a redirected file.
diff --git a/test/Misc/diag-format.c b/test/Misc/diag-format.c
index d34d25a3cf94..bc29894ad03e 100644
--- a/test/Misc/diag-format.c
+++ b/test/Misc/diag-format.c
@@ -37,7 +37,7 @@
// DEFAULT: {{.*}}:36:8: warning: extra tokens at end of #endif directive [-Wextra-tokens]
// MSVC2010: {{.*}}(36,7) : warning: extra tokens at end of #endif directive [-Wextra-tokens]
// MSVC2013: {{.*}}(36,8) : warning: extra tokens at end of #endif directive [-Wextra-tokens]
-// MSVC: {{.*}}(36,8){{ ?}}: warning: extra tokens at end of #endif directive [-Wextra-tokens]
+// MSVC: {{.*\(36,[78]\) ?}}: warning: extra tokens at end of #endif directive [-Wextra-tokens]
// MSVC2015: {{.*}}(36,8): warning: extra tokens at end of #endif directive [-Wextra-tokens]
// VI: {{.*}} +36:8: warning: extra tokens at end of #endif directive [-Wextra-tokens]
// MSVC2015_ORIG: {{.*}}(36): warning: extra tokens at end of #endif directive [-Wextra-tokens]
diff --git a/test/Misc/diag-greatergreater.cpp b/test/Misc/diag-greatergreater.cpp
new file mode 100644
index 000000000000..9110838cf3f5
--- /dev/null
+++ b/test/Misc/diag-greatergreater.cpp
@@ -0,0 +1,43 @@
+// RUN: not %clang_cc1 %s -fdiagnostics-print-source-range-info 2>&1 | FileCheck %s --strict-whitespace
+
+template<typename T> class C {};
+template<int> class D {};
+
+void g() {
+ // The range ending in the first > character does not extend to the second >
+ // character.
+ // CHECK: :{[[@LINE+3]]:5-[[@LINE+3]]:11}: error:
+ // CHECK-NEXT: D<C<int>> a;
+ // CHECK-NEXT: ^~~~~~{{$}}
+ D<C<int>> a;
+
+ // The range ending in the second > character does not extend to the third >
+ // character.
+ // CHECK: :{[[@LINE+3]]:5-[[@LINE+3]]:14}: error:
+ // CHECK-NEXT: D<C<C<int>>> b;
+ // CHECK-NEXT: ^~~~~~~~~{{$}}
+ D<C<C<int>>> b;
+}
+
+template<int> int V;
+// Here, we split the >>= token into a > followed by a >=.
+// Then we split the >= token into a > followed by an =,
+// which we merge with the other = to form an ==.
+// CHECK: error: a space is required
+// CHECK-NEXT: int k = V<C<int>>==0;
+// CHECK-NEXT: ^~{{$}}
+// CHECK-NEXT: > >{{$}}
+// CHECK: error: a space is required
+// CHECK-NEXT: int k = V<C<int>>==0;
+// CHECK-NEXT: ^~{{$}}
+// CHECK-NEXT: > ={{$}}
+// CHECK: :{[[@LINE+3]]:11-[[@LINE+3]]:17}: error:
+// CHECK-NEXT: int k = V<C<int>>==0;
+// CHECK-NEXT: ^~~~~~{{$}}
+int k = V<C<int>>==0;
+
+template<typename> int W;
+// CHECK: :{[[@LINE+3]]:9-[[@LINE+3]]:18}{[[@LINE+3]]:20-[[@LINE+3]]:22}: error: comparison
+// CHECK-NEXT: int l = W<C<int>>==&k;
+// CHECK-NEXT: ~~~~~~~~~^ ~~{{$}}
+int l = W<C<int>>==&k;
diff --git a/test/Misc/diag-macro-backtrace2.c b/test/Misc/diag-macro-backtrace2.c
index af79bbde6009..64fc5f630727 100644
--- a/test/Misc/diag-macro-backtrace2.c
+++ b/test/Misc/diag-macro-backtrace2.c
@@ -14,7 +14,7 @@ void PR16799() {
const char str[] = "string";
a(str);
// CHECK: :15:3: error: invalid operands to binary expression
- // CHECK: ('const char *' and 'int')
+ // CHECK: ('const char [7]' and 'int')
// CHECK: a(str);
// CHECK: ^~~~~~
// CHECK: :3:11: note: expanded from macro 'a'
diff --git a/test/Misc/diag-template-diffing.cpp b/test/Misc/diag-template-diffing.cpp
index 174a9693f3b7..5c85df434df1 100644
--- a/test/Misc/diag-template-diffing.cpp
+++ b/test/Misc/diag-template-diffing.cpp
@@ -1265,7 +1265,7 @@ void test() {
foo<BoolT<true>>(X);
}
// CHECK-ELIDE-NOTREE: no matching function for call to 'foo'
-// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'BoolT<false>' to 'BoolT<true>' for 1st argument
+// CHECK-ELIDE-NOTREE: candidate function template not viable: no known conversion from 'BoolT<false>' to 'BoolT<true>' for 1st argument
}
namespace DifferentIntegralTypes {
@@ -1401,7 +1401,7 @@ void run() {
f(1, integral_constant<bool, true>{});
}
// CHECK-ELIDE-NOTREE: error: no matching function for call to 'f'
-// CHECK-ELIDE-NOTREE: note: candidate function not viable: no known conversion from 'integral_constant<[...], true>' to 'integral_constant<[...], false>' for 2nd argument
+// CHECK-ELIDE-NOTREE: note: candidate function template not viable: no known conversion from 'integral_constant<[...], true>' to 'integral_constant<[...], false>' for 2nd argument
}
namespace ZeroArgs {
@@ -1454,7 +1454,7 @@ void run() {
D<X::X1>(VectorType<X::X2>());
}
// CHECK-ELIDE-NOTREE: error: no matching function for call to 'D'
-// CHECK-ELIDE-NOTREE: note: candidate function not viable: no known conversion from 'VectorType<X::X2>' to 'const VectorType<(TypeAlias::X)0>' for 1st argument
+// CHECK-ELIDE-NOTREE: note: candidate function template not viable: no known conversion from 'VectorType<X::X2>' to 'const VectorType<(TypeAlias::X)0>' for 1st argument
}
namespace TypeAlias2 {
diff --git a/test/Misc/pragma-attribute-supported-attributes-list.test b/test/Misc/pragma-attribute-supported-attributes-list.test
index 1171a2d3709a..4a3846be8d9b 100644
--- a/test/Misc/pragma-attribute-supported-attributes-list.test
+++ b/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -2,7 +2,7 @@
// The number of supported attributes should never go down!
-// CHECK: #pragma clang attribute supports 66 attributes:
+// CHECK: #pragma clang attribute supports 72 attributes:
// CHECK-NEXT: AMDGPUFlatWorkGroupSize (SubjectMatchRule_function)
// CHECK-NEXT: AMDGPUNumSGPR (SubjectMatchRule_function)
// CHECK-NEXT: AMDGPUNumVGPR (SubjectMatchRule_function)
@@ -12,8 +12,11 @@
// CHECK-NEXT: AlignValue (SubjectMatchRule_variable, SubjectMatchRule_type_alias)
// CHECK-NEXT: AllocSize (SubjectMatchRule_function)
// CHECK-NEXT: Annotate ()
+// CHECK-NEXT: AnyX86NoCfCheck (SubjectMatchRule_hasType_functionType)
// CHECK-NEXT: AssumeAligned (SubjectMatchRule_objc_method, SubjectMatchRule_function)
// CHECK-NEXT: Availability ((SubjectMatchRule_record, SubjectMatchRule_enum, SubjectMatchRule_enum_constant, SubjectMatchRule_field, SubjectMatchRule_function, SubjectMatchRule_namespace, SubjectMatchRule_objc_category, SubjectMatchRule_objc_interface, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property, SubjectMatchRule_objc_protocol, SubjectMatchRule_record, SubjectMatchRule_type_alias, SubjectMatchRule_variable))
+// CHECK-NEXT: CPUDispatch (SubjectMatchRule_function)
+// CHECK-NEXT: CPUSpecific (SubjectMatchRule_function)
// CHECK-NEXT: CXX11NoReturn (SubjectMatchRule_function)
// CHECK-NEXT: CallableWhen (SubjectMatchRule_function_is_member)
// CHECK-NEXT: CarriesDependency (SubjectMatchRule_variable_is_parameter, SubjectMatchRule_objc_method, SubjectMatchRule_function)
@@ -31,6 +34,7 @@
// CHECK-NEXT: InternalLinkage (SubjectMatchRule_variable, SubjectMatchRule_function, SubjectMatchRule_record)
// CHECK-NEXT: LTOVisibilityPublic (SubjectMatchRule_record)
// CHECK-NEXT: MicroMips (SubjectMatchRule_function)
+// CHECK-NEXT: MinVectorWidth (SubjectMatchRule_function)
// CHECK-NEXT: MipsLongCall (SubjectMatchRule_function)
// CHECK-NEXT: MipsShortCall (SubjectMatchRule_function)
// CHECK-NEXT: NoDebug (SubjectMatchRule_hasType_functionType, SubjectMatchRule_objc_method, SubjectMatchRule_variable_not_is_parameter)
@@ -40,6 +44,7 @@
// CHECK-NEXT: NoSanitize (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_variable_is_global)
// CHECK-NEXT: NoSanitizeSpecific (SubjectMatchRule_function, SubjectMatchRule_variable_is_global)
// CHECK-NEXT: NoSplitStack (SubjectMatchRule_function)
+// CHECK-NEXT: NoStackProtector (SubjectMatchRule_function)
// CHECK-NEXT: NoThrow (SubjectMatchRule_function)
// CHECK-NEXT: NotTailCalled (SubjectMatchRule_function)
// CHECK-NEXT: ObjCBoxable (SubjectMatchRule_record)
@@ -66,6 +71,7 @@
// CHECK-NEXT: TLSModel (SubjectMatchRule_variable_is_thread_local)
// CHECK-NEXT: Target (SubjectMatchRule_function)
// CHECK-NEXT: TestTypestate (SubjectMatchRule_function_is_member)
+// CHECK-NEXT: TrivialABI (SubjectMatchRule_record)
// CHECK-NEXT: WarnUnusedResult (SubjectMatchRule_objc_method, SubjectMatchRule_enum, SubjectMatchRule_record, SubjectMatchRule_hasType_functionType)
// CHECK-NEXT: XRayInstrument (SubjectMatchRule_function, SubjectMatchRule_objc_method)
// CHECK-NEXT: XRayLogArgs (SubjectMatchRule_function, SubjectMatchRule_objc_method)
diff --git a/test/Misc/serialized-diags-bcanalyzer.c b/test/Misc/serialized-diags-bcanalyzer.c
new file mode 100644
index 000000000000..b58f65ebaf24
--- /dev/null
+++ b/test/Misc/serialized-diags-bcanalyzer.c
@@ -0,0 +1,3 @@
+// RUN: %clang -Wall -fsyntax-only %s --serialize-diagnostics %t.diag > /dev/null 2>&1
+// RUN: llvm-bcanalyzer -dump %t.diag | FileCheck %s
+// CHECK: Stream type: Clang Serialized Diagnostics
diff --git a/test/Misc/target-invalid-cpu-note.c b/test/Misc/target-invalid-cpu-note.c
new file mode 100644
index 000000000000..f2b36d44b9f4
--- /dev/null
+++ b/test/Misc/target-invalid-cpu-note.c
@@ -0,0 +1,162 @@
+// RUN: not %clang_cc1 -triple armv5--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix ARM
+// ARM: error: unknown target CPU 'not-a-cpu'
+// ARM: note: valid target CPU values are:
+// ARM-SAME: arm2
+
+// RUN: not %clang_cc1 -triple arm64--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix AARCH64
+// AARCH64: error: unknown target CPU 'not-a-cpu'
+// AARCH64: note: valid target CPU values are:
+// AARCH64-SAME: cortex-a35,
+
+// RUN: not %clang_cc1 -triple i386--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix X86
+// X86: error: unknown target CPU 'not-a-cpu'
+// X86: note: valid target CPU values are: i386, i486, winchip-c6, winchip2, c3,
+// X86-SAME: i586, pentium, pentium-mmx, pentiumpro, i686, pentium2, pentium3,
+// X86-SAME: pentium3m, pentium-m, c3-2, yonah, pentium4, pentium4m, prescott,
+// X86-SAME: nocona, core2, penryn, bonnell, atom, silvermont, slm, goldmont, goldmont-plus, tremont,
+// X86-SAME: nehalem, corei7, westmere, sandybridge, corei7-avx, ivybridge,
+// X86-SAME: core-avx-i, haswell, core-avx2, broadwell, skylake, skylake-avx512,
+// X86-SAME: skx, cannonlake, icelake-client, icelake-server, knl, knm, lakemont, k6, k6-2, k6-3,
+// X86-SAME: athlon, athlon-tbird, athlon-xp, athlon-mp, athlon-4, k8, athlon64,
+// X86-SAME: athlon-fx, opteron, k8-sse3, athlon64-sse3, opteron-sse3, amdfam10,
+// X86-SAME: barcelona, btver1, btver2, bdver1, bdver2, bdver3, bdver4, znver1,
+// X86-SAME: x86-64, geode
+
+// RUN: not %clang_cc1 -triple x86_64--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix X86_64
+// X86_64: error: unknown target CPU 'not-a-cpu'
+// X86_64: note: valid target CPU values are: nocona, core2, penryn, bonnell,
+// X86_64-SAME: atom, silvermont, slm, goldmont, goldmont-plus, tremont, nehalem, corei7, westmere,
+// X86_64-SAME: sandybridge, corei7-avx, ivybridge, core-avx-i, haswell,
+// X86_64-SAME: core-avx2, broadwell, skylake, skylake-avx512, skx, cannonlake,
+// X86_64-SAME: icelake-client, icelake-server, knl, knm, k8, athlon64, athlon-fx, opteron, k8-sse3,
+// X86_64-SAME: athlon64-sse3, opteron-sse3, amdfam10, barcelona, btver1,
+// X86_64-SAME: btver2, bdver1, bdver2, bdver3, bdver4, znver1, x86-64
+
+// RUN: not %clang_cc1 -triple nvptx--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix NVPTX
+// NVPTX: error: unknown target CPU 'not-a-cpu'
+// NVPTX: note: valid target CPU values are: sm_20, sm_21, sm_30, sm_32, sm_35,
+// NVPTX-SAME: sm_37, sm_50, sm_52, sm_53, sm_60, sm_61, sm_62, sm_70, sm_72
+
+// RUN: not %clang_cc1 -triple r600--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix R600
+// R600: error: unknown target CPU 'not-a-cpu'
+// R600: note: valid target CPU values are: r600, rv630, rv635, r630, rs780,
+// R600-SAME: rs880, rv610, rv620, rv670, rv710, rv730, rv740, rv770, cedar,
+// R600-SAME: palm, cypress, hemlock, juniper, redwood, sumo, sumo2, barts,
+// R600-SAME: caicos, aruba, cayman, turks
+
+
+// RUN: not %clang_cc1 -triple amdgcn--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix AMDGCN
+// AMDGCN: error: unknown target CPU 'not-a-cpu'
+// AMDGCN: note: valid target CPU values are: gfx600, tahiti, gfx601, hainan,
+// AMDGCN-SAME: oland, pitcairn, verde, gfx700, kaveri, gfx701, hawaii, gfx702,
+// AMDGCN-SAME: gfx703, kabini, mullins, gfx704, bonaire, gfx801, carrizo,
+// AMDGCN-SAME: gfx802, iceland, tonga, gfx803, fiji, polaris10, polaris11,
+// AMDGCN-SAME: gfx810, stoney, gfx900, gfx902
+
+// RUN: not %clang_cc1 -triple wasm64--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix WEBASM
+// WEBASM: error: unknown target CPU 'not-a-cpu'
+// WEBASM: note: valid target CPU values are: mvp, bleeding-edge, generic
+
+// RUN: not %clang_cc1 -triple systemz--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix SYSTEMZ
+// SYSTEMZ: error: unknown target CPU 'not-a-cpu'
+// SYSTEMZ: note: valid target CPU values are: arch8, z10, arch9, z196, arch10,
+// SYSTEMZ-SAME: zEC12, arch11, z13, arch12, z14
+
+// RUN: not %clang_cc1 -triple sparc--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix SPARC
+// SPARC: error: unknown target CPU 'not-a-cpu'
+// SPARC: note: valid target CPU values are: v8, supersparc, sparclite, f934,
+// SPARC-SAME: hypersparc, sparclite86x, sparclet, tsc701, v9, ultrasparc,
+// SPARC-SAME: ultrasparc3, niagara, niagara2, niagara3, niagara4, ma2100,
+// SPARC-SAME: ma2150, ma2155, ma2450, ma2455, ma2x5x, ma2080, ma2085, ma2480,
+// SPARC-SAME: ma2485, ma2x8x, myriad2, myriad2.1, myriad2.2, myriad2.3, leon2,
+// SPARC-SAME: at697e, at697f, leon3, ut699, gr712rc, leon4, gr740
+
+// RUN: not %clang_cc1 -triple sparcv9--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix SPARCV9
+// SPARCV9: error: unknown target CPU 'not-a-cpu'
+// SPARCV9: note: valid target CPU values are: v9, ultrasparc, ultrasparc3, niagara, niagara2, niagara3, niagara4
+
+// RUN: not %clang_cc1 -triple powerpc--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix PPC
+// PPC: error: unknown target CPU 'not-a-cpu'
+// PPC: note: valid target CPU values are: generic, 440, 450, 601, 602, 603,
+// PPC-SAME: 603e, 603ev, 604, 604e, 620, 630, g3, 7400, g4, 7450, g4+, 750,
+// PPC-SAME: 970, g5, a2, a2q, e500mc, e5500, power3, pwr3, power4, pwr4,
+// PPC-SAME: power5, pwr5, power5x, pwr5x, power6, pwr6, power6x, pwr6x, power7,
+// PPC-SAME: pwr7, power8, pwr8, power9, pwr9, powerpc, ppc, powerpc64, ppc64,
+// PPC-SAME: powerpc64le, ppc64le
+
+// RUN: not %clang_cc1 -triple nios2--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix NIOS
+// NIOS: error: unknown target CPU 'not-a-cpu'
+// NIOS: note: valid target CPU values are: nios2r1, nios2r2
+
+// RUN: not %clang_cc1 -triple mips--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix MIPS
+// MIPS: error: unknown target CPU 'not-a-cpu'
+// MIPS: note: valid target CPU values are: mips1, mips2, mips3, mips4, mips5,
+// MIPS-SAME: mips32, mips32r2, mips32r3, mips32r5, mips32r6, mips64, mips64r2,
+// MIPS-SAME: mips64r3, mips64r5, mips64r6, octeon, p5600
+
+// RUN: not %clang_cc1 -triple lanai--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix LANAI
+// LANAI: error: unknown target CPU 'not-a-cpu'
+// LANAI: note: valid target CPU values are: v11
+
+// RUN: not %clang_cc1 -triple hexagon--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix HEXAGON
+// HEXAGON: error: unknown target CPU 'not-a-cpu'
+// HEXAGON: note: valid target CPU values are: hexagonv4, hexagonv5, hexagonv55,
+// HEXAGON-SAME: hexagonv60, hexagonv62, hexagonv65
+
+// RUN: not %clang_cc1 -triple bpf--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix BPF
+// BPF: error: unknown target CPU 'not-a-cpu'
+// BPF: note: valid target CPU values are: generic, v1, v2, probe
+
+// RUN: not %clang_cc1 -triple avr--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix AVR
+// AVR: error: unknown target CPU 'not-a-cpu'
+// AVR: note: valid target CPU values are: avr1, avr2, avr25, avr3, avr31,
+// AVR-SAME: avr35, avr4, avr5, avr51, avr6, avrxmega1, avrxmega2, avrxmega3,
+// AVR-SAME: avrxmega4, avrxmega5, avrxmega6, avrxmega7, avrtiny, at90s1200,
+// AVR-SAME: attiny11, attiny12, attiny15, attiny28, at90s2313, at90s2323,
+// AVR-SAME: at90s2333, at90s2343, attiny22, attiny26, at86rf401, at90s4414,
+// AVR-SAME: t90s4433, at90s4434, at90s8515, at90c8534, at90s8535, ata5272,
+// AVR-SAME: ttiny13, attiny13a, attiny2313, attiny2313a, attiny24, attiny24a,
+// AVR-SAME: ttiny4313, attiny44, attiny44a, attiny84, attiny84a, attiny25,
+// AVR-SAME: ttiny45, attiny85, attiny261, attiny261a, attiny461, attiny461a,
+// AVR-SAME: ttiny861, attiny861a, attiny87, attiny43u, attiny48, attiny88,
+// AVR-SAME: ttiny828, at43usb355, at76c711, atmega103, at43usb320, attiny167,
+// AVR-SAME: t90usb82, at90usb162, ata5505, atmega8u2, atmega16u2,
+// AVR-SAME: atmega32u2, attiny1634, atmega8, ata6289, atmega8a, ata6285,
+// AVR-SAME: ata6286, atmega48, atmega48a, atmega48pa, atmega48p, atmega88,
+// AVR-SAME: atmega88a, atmega88p, atmega88pa, atmega8515, atmega8535,
+// AVR-SAME: atmega8hva, at90pwm1, at90pwm2, at90pwm2b, at90pwm3, at90pwm3b,
+// AVR-SAME: at90pwm81, ata5790, ata5795, atmega16, atmega16a, atmega161,
+// AVR-SAME: atmega162, atmega163, atmega164a, atmega164p, atmega164pa,
+// AVR-SAME: atmega165, atmega165a, atmega165p, atmega165pa, atmega168,
+// AVR-SAME: atmega168a, atmega168p, atmega168pa, atmega169, atmega169a,
+// AVR-SAME: atmega169p, atmega169pa, atmega32, atmega32a, atmega323,
+// AVR-SAME: atmega324a, atmega324p, atmega324pa, atmega325, atmega325a,
+// AVR-SAME: atmega325p, atmega325pa, atmega3250, atmega3250a, atmega3250p,
+// AVR-SAME: atmega3250pa, atmega328, atmega328p, atmega329, atmega329a,
+// AVR-SAME: atmega329p, atmega329pa, atmega3290, atmega3290a, atmega3290p,
+// AVR-SAME: atmega3290pa, atmega406, atmega64, atmega64a, atmega640, atmega644,
+// AVR-SAME: atmega644a, atmega644p, atmega644pa, atmega645, atmega645a,
+// AVR-SAME: tmega645p, atmega649, atmega649a, atmega649p, atmega6450,
+// AVR-SAME: tmega6450a, atmega6450p, atmega6490, atmega6490a, atmega6490p,
+// AVR-SAME: tmega64rfr2, atmega644rfr2, atmega16hva, atmega16hva2,
+// AVR-SAME: tmega16hvb, atmega16hvbrevb, atmega32hvb, atmega32hvbrevb,
+// AVR-SAME: tmega64hve, at90can32, at90can64, at90pwm161, at90pwm216,
+// AVR-SAME: t90pwm316, atmega32c1, atmega64c1, atmega16m1, atmega32m1,
+// AVR-SAME: tmega64m1, atmega16u4, atmega32u4, atmega32u6, at90usb646,
+// AVR-SAME: t90usb647, at90scr100, at94k, m3000, atmega128, atmega128a,
+// AVR-SAME: tmega1280, atmega1281, atmega1284, atmega1284p, atmega128rfa1,
+// AVR-SAME: tmega128rfr2, atmega1284rfr2, at90can128, at90usb1286,
+// AVR-SAME: t90usb1287, atmega2560, atmega2561, atmega256rfr2, atmega2564rfr2,
+// AVR-SAME: txmega16a4, atxmega16a4u, atxmega16c4, atxmega16d4, atxmega32a4,
+// AVR-SAME: txmega32a4u, atxmega32c4, atxmega32d4, atxmega32e5, atxmega16e5,
+// AVR-SAME: txmega8e5, atxmega32x1, atxmega64a3, atxmega64a3u, atxmega64a4u,
+// AVR-SAME: txmega64b1, atxmega64b3, atxmega64c3, atxmega64d3, atxmega64d4,
+// AVR-SAME: txmega64a1, atxmega64a1u, atxmega128a3, atxmega128a3u,
+// AVR-SAME: txmega128b1, atxmega128b3, atxmega128c3, atxmega128d3,
+// AVR-SAME: txmega128d4, atxmega192a3, atxmega192a3u, atxmega192c3,
+// AVR-SAME: txmega192d3, atxmega256a3, atxmega256a3u, atxmega256a3b,
+// AVR-SAME: txmega256a3bu, atxmega256c3, atxmega256d3, atxmega384c3,
+// AVR-SAME: txmega384d3, atxmega128a1, atxmega128a1u, atxmega128a4u,
+// AVR-SAME: ttiny4, attiny5, attiny9, attiny10, attiny20, attiny40, attiny102,
+// AVR-SAME: attiny104
+
diff --git a/test/Misc/thinlto.c b/test/Misc/thinlto.c
deleted file mode 100644
index ec0f03f5a2af..000000000000
--- a/test/Misc/thinlto.c
+++ /dev/null
@@ -1,4 +0,0 @@
-// RUN: %clang_cc1 -flto=thin -emit-llvm-bc < %s | llvm-bcanalyzer -dump | FileCheck %s
-// ; Check that the -flto=thin option emits a summary
-// CHECK: <GLOBALVAL_SUMMARY_BLOCK
-int main() {}
diff --git a/test/Misc/warning-flags.c b/test/Misc/warning-flags.c
index 2c48fa4dbf39..4f9469f8e582 100644
--- a/test/Misc/warning-flags.c
+++ b/test/Misc/warning-flags.c
@@ -18,7 +18,7 @@ This test serves two purposes:
The list of warnings below should NEVER grow. It should gradually shrink to 0.
-CHECK: Warnings without flags (77):
+CHECK: Warnings without flags (76):
CHECK-NEXT: ext_excess_initializers
CHECK-NEXT: ext_excess_initializers_in_char_array_initializer
CHECK-NEXT: ext_expected_semi_decl_list
@@ -31,7 +31,6 @@ CHECK-NEXT: ext_plain_complex
CHECK-NEXT: ext_template_arg_extra_parens
CHECK-NEXT: ext_typecheck_comparison_of_pointer_integer
CHECK-NEXT: ext_typecheck_cond_incompatible_operands
-CHECK-NEXT: ext_typecheck_ordered_comparison_of_function_pointers
CHECK-NEXT: ext_typecheck_ordered_comparison_of_pointer_integer
CHECK-NEXT: ext_using_undefined_std
CHECK-NEXT: pp_invalid_string_literal
@@ -81,7 +80,7 @@ CHECK-NEXT: warn_on_superclass_use
CHECK-NEXT: warn_pp_convert_to_positive
CHECK-NEXT: warn_pp_expr_overflow
CHECK-NEXT: warn_pp_line_decimal
-CHECK-NEXT: warn_pragma_pack_pop_identifer_and_alignment
+CHECK-NEXT: warn_pragma_pack_pop_identifier_and_alignment
CHECK-NEXT: warn_pragma_pack_show
CHECK-NEXT: warn_property_getter_owning_mismatch
CHECK-NEXT: warn_register_objc_catch_parm
diff --git a/test/Modules/ExtDebugInfo.cpp b/test/Modules/ExtDebugInfo.cpp
index 97386bc4d007..c57f1f034eb2 100644
--- a/test/Modules/ExtDebugInfo.cpp
+++ b/test/Modules/ExtDebugInfo.cpp
@@ -187,7 +187,7 @@ void foo() {
// CHECK: !DIGlobalVariable(name: "anon_enum", {{.*}}, type: ![[ANON_ENUM:[0-9]+]]
// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, scope: ![[NS]],
-// CHECK-SAME: line: 16
+// CHECK-SAME: line: 19
// CHECK: !DIGlobalVariable(name: "GlobalUnion",
// CHECK-SAME: type: ![[GLOBAL_UNION:[0-9]+]]
diff --git a/test/Modules/Inputs/DebugCXX.h b/test/Modules/Inputs/DebugCXX.h
index 1ccf8d302f13..8f83c0bc69db 100644
--- a/test/Modules/Inputs/DebugCXX.h
+++ b/test/Modules/Inputs/DebugCXX.h
@@ -1,4 +1,7 @@
/* -*- C++ -*- */
+
+#include "dummy.h"
+
namespace DebugCXX {
// Records.
struct Struct {
diff --git a/test/Modules/Inputs/DependsOnModule.framework/module.map b/test/Modules/Inputs/DependsOnModule.framework/module.map
index 4d468f2a8c01..948a1efd743a 100644
--- a/test/Modules/Inputs/DependsOnModule.framework/module.map
+++ b/test/Modules/Inputs/DependsOnModule.framework/module.map
@@ -37,4 +37,22 @@ framework module DependsOnModule {
export *
}
}
+ explicit module CXX11 {
+ requires cplusplus11
+ }
+ explicit module CXX14 {
+ requires cplusplus14
+ }
+ explicit module CXX17 {
+ requires cplusplus17
+ }
+ explicit module C99 {
+ requires c99
+ }
+ explicit module C11 {
+ requires c11
+ }
+ explicit module C17 {
+ requires c17
+ }
}
diff --git a/test/Modules/Inputs/at-import-in-framework-header/A.framework/Headers/A.h b/test/Modules/Inputs/at-import-in-framework-header/A.framework/Headers/A.h
new file mode 100644
index 000000000000..6949a872fc99
--- /dev/null
+++ b/test/Modules/Inputs/at-import-in-framework-header/A.framework/Headers/A.h
@@ -0,0 +1,2 @@
+@import B;
+int foo();
diff --git a/test/Modules/Inputs/at-import-in-framework-header/A.framework/Modules/module.modulemap b/test/Modules/Inputs/at-import-in-framework-header/A.framework/Modules/module.modulemap
new file mode 100644
index 000000000000..126cf26ec9c7
--- /dev/null
+++ b/test/Modules/Inputs/at-import-in-framework-header/A.framework/Modules/module.modulemap
@@ -0,0 +1,4 @@
+// at-import-in-framework-header/A.framework/Modules/module.modulemap
+framework module A {
+ header "A.h"
+}
diff --git a/test/Modules/Inputs/at-import-in-framework-header/module.modulemap b/test/Modules/Inputs/at-import-in-framework-header/module.modulemap
new file mode 100644
index 000000000000..a38d66863e95
--- /dev/null
+++ b/test/Modules/Inputs/at-import-in-framework-header/module.modulemap
@@ -0,0 +1,2 @@
+// at-import-in-framework-header/module.modulemap
+module B {}
diff --git a/test/Modules/Inputs/autoload-subdirectory/a.h b/test/Modules/Inputs/autoload-subdirectory/a.h
new file mode 100644
index 000000000000..8be94312e3ef
--- /dev/null
+++ b/test/Modules/Inputs/autoload-subdirectory/a.h
@@ -0,0 +1,9 @@
+#include "b.h"
+
+class foo {
+ int x, y;
+
+public:
+ foo(){};
+ ~foo(){};
+};
diff --git a/test/Modules/Inputs/autoload-subdirectory/b.h b/test/Modules/Inputs/autoload-subdirectory/b.h
new file mode 100644
index 000000000000..bfde5bf79f81
--- /dev/null
+++ b/test/Modules/Inputs/autoload-subdirectory/b.h
@@ -0,0 +1 @@
+class bar {};
diff --git a/test/Modules/Inputs/autoload-subdirectory/c.h b/test/Modules/Inputs/autoload-subdirectory/c.h
new file mode 100644
index 000000000000..e5a45250f9f8
--- /dev/null
+++ b/test/Modules/Inputs/autoload-subdirectory/c.h
@@ -0,0 +1,7 @@
+class nyan {
+ bool x, y;
+
+public:
+ nyan(){};
+ ~nyan(){};
+};
diff --git a/test/Modules/Inputs/autoload-subdirectory/include/module.modulemap b/test/Modules/Inputs/autoload-subdirectory/include/module.modulemap
new file mode 100644
index 000000000000..880ae38b97a0
--- /dev/null
+++ b/test/Modules/Inputs/autoload-subdirectory/include/module.modulemap
@@ -0,0 +1,3 @@
+module a { header "a.h" }
+module b { header "b.h" }
+module c { header "c.h" }
diff --git a/test/Modules/Inputs/autoload-subdirectory/module.modulemap b/test/Modules/Inputs/autoload-subdirectory/module.modulemap
new file mode 100644
index 000000000000..880ae38b97a0
--- /dev/null
+++ b/test/Modules/Inputs/autoload-subdirectory/module.modulemap
@@ -0,0 +1,3 @@
+module a { header "a.h" }
+module b { header "b.h" }
+module c { header "c.h" }
diff --git a/test/Modules/Inputs/bad-private-include/Bad.framework/Headers/Bad.h b/test/Modules/Inputs/bad-private-include/Bad.framework/Headers/Bad.h
new file mode 100644
index 000000000000..eea054917048
--- /dev/null
+++ b/test/Modules/Inputs/bad-private-include/Bad.framework/Headers/Bad.h
@@ -0,0 +1 @@
+#import <Bad/Shared.h> \ No newline at end of file
diff --git a/test/Modules/Inputs/bad-private-include/Bad.framework/Modules/module.modulemap b/test/Modules/Inputs/bad-private-include/Bad.framework/Modules/module.modulemap
new file mode 100644
index 000000000000..11612dc8cb31
--- /dev/null
+++ b/test/Modules/Inputs/bad-private-include/Bad.framework/Modules/module.modulemap
@@ -0,0 +1,5 @@
+framework module Bad {
+ umbrella header "Bad.h"
+ export *
+ module * { export * }
+}
diff --git a/test/Modules/Inputs/bad-private-include/Bad.framework/Modules/module.private.modulemap b/test/Modules/Inputs/bad-private-include/Bad.framework/Modules/module.private.modulemap
new file mode 100644
index 000000000000..043139dc55d1
--- /dev/null
+++ b/test/Modules/Inputs/bad-private-include/Bad.framework/Modules/module.private.modulemap
@@ -0,0 +1,5 @@
+framework module Bad_Private {
+ umbrella header "BadPrivate.h"
+ export *
+ module * { export * }
+}
diff --git a/test/Modules/Inputs/bad-private-include/Bad.framework/PrivateHeaders/BadPrivate.h b/test/Modules/Inputs/bad-private-include/Bad.framework/PrivateHeaders/BadPrivate.h
new file mode 100644
index 000000000000..eea054917048
--- /dev/null
+++ b/test/Modules/Inputs/bad-private-include/Bad.framework/PrivateHeaders/BadPrivate.h
@@ -0,0 +1 @@
+#import <Bad/Shared.h> \ No newline at end of file
diff --git a/test/Modules/Inputs/bad-private-include/Bad.framework/PrivateHeaders/Shared.h b/test/Modules/Inputs/bad-private-include/Bad.framework/PrivateHeaders/Shared.h
new file mode 100644
index 000000000000..4f1defddefba
--- /dev/null
+++ b/test/Modules/Inputs/bad-private-include/Bad.framework/PrivateHeaders/Shared.h
@@ -0,0 +1,3 @@
+struct SomeDecl {
+ int x;
+};
diff --git a/test/Modules/Inputs/class-extension/a-private.h b/test/Modules/Inputs/class-extension/a-private.h
new file mode 100644
index 000000000000..e35402ac18ad
--- /dev/null
+++ b/test/Modules/Inputs/class-extension/a-private.h
@@ -0,0 +1,5 @@
+#import "a.h"
+#import "a-proto.h"
+
+@interface A () <AProto>
+@end
diff --git a/test/Modules/Inputs/class-extension/a-proto.h b/test/Modules/Inputs/class-extension/a-proto.h
new file mode 100644
index 000000000000..32043ec2498f
--- /dev/null
+++ b/test/Modules/Inputs/class-extension/a-proto.h
@@ -0,0 +1,7 @@
+@protocol NSObject
+@end
+
+@protocol AProto <NSObject>
+@property (nonatomic, readwrite, assign) int p0;
+@property (nonatomic, readwrite, assign) int p1;
+@end
diff --git a/test/Modules/Inputs/class-extension/a.h b/test/Modules/Inputs/class-extension/a.h
new file mode 100644
index 000000000000..28c409c33774
--- /dev/null
+++ b/test/Modules/Inputs/class-extension/a.h
@@ -0,0 +1,5 @@
+@interface NSObject
+@end
+
+@interface A : NSObject
+@end
diff --git a/test/Modules/Inputs/class-extension/module.modulemap b/test/Modules/Inputs/class-extension/module.modulemap
new file mode 100644
index 000000000000..5c30bc57e46c
--- /dev/null
+++ b/test/Modules/Inputs/class-extension/module.modulemap
@@ -0,0 +1,11 @@
+
+module A {
+ header "a.h"
+ header "a-proto.h"
+ export *
+}
+
+module AP {
+ header "a-private.h"
+ export *
+}
diff --git a/test/Modules/Inputs/declare-use/h.h b/test/Modules/Inputs/declare-use/h.h
index 379e50180ca1..8984727c565e 100644
--- a/test/Modules/Inputs/declare-use/h.h
+++ b/test/Modules/Inputs/declare-use/h.h
@@ -1,7 +1,7 @@
#ifndef H_H
#define H_H
#include "c.h"
-#include "d.h" // expected-error {{does not depend on a module exporting}}
+#include "d.h" // expected-error {{module XH does not depend on a module exporting}}
#include "h1.h"
const int h1 = aux_h*c*7*d;
#endif
diff --git a/test/Modules/Inputs/diag_flags.h b/test/Modules/Inputs/diag_flags.h
index 3b85c84c6cfd..55eeab196a31 100644
--- a/test/Modules/Inputs/diag_flags.h
+++ b/test/Modules/Inputs/diag_flags.h
@@ -1 +1,4 @@
+#define pragma _Pragma("clang diagnostic push") _Pragma("clang diagnostic error \"-Wpadded\"") _Pragma("clang diagnostic pop")
+pragma
+
struct Padded { char x; int y; };
diff --git a/test/Modules/Inputs/double-quotes/A.framework/Headers/A.h b/test/Modules/Inputs/double-quotes/A.framework/Headers/A.h
new file mode 100644
index 000000000000..17ceb83bb9ca
--- /dev/null
+++ b/test/Modules/Inputs/double-quotes/A.framework/Headers/A.h
@@ -0,0 +1,6 @@
+#include "A0.h"
+#include "B.h"
+
+#include "X.h"
+
+int foo();
diff --git a/test/Modules/Inputs/double-quotes/A.framework/Headers/A0.h b/test/Modules/Inputs/double-quotes/A.framework/Headers/A0.h
new file mode 100644
index 000000000000..79c6b8893ba4
--- /dev/null
+++ b/test/Modules/Inputs/double-quotes/A.framework/Headers/A0.h
@@ -0,0 +1 @@
+// double-quotes/A.framework/Headers/A0.h
diff --git a/test/Modules/Inputs/double-quotes/A.framework/Modules/module.modulemap b/test/Modules/Inputs/double-quotes/A.framework/Modules/module.modulemap
new file mode 100644
index 000000000000..09a887a8f489
--- /dev/null
+++ b/test/Modules/Inputs/double-quotes/A.framework/Modules/module.modulemap
@@ -0,0 +1,5 @@
+// double-quotes/A.framework/Modules/module.modulemap
+framework module A {
+ header "A.h"
+ header "A0.h"
+}
diff --git a/test/Modules/Inputs/double-quotes/B.h b/test/Modules/Inputs/double-quotes/B.h
new file mode 100644
index 000000000000..724faaef807d
--- /dev/null
+++ b/test/Modules/Inputs/double-quotes/B.h
@@ -0,0 +1 @@
+// double-quotes/B.h
diff --git a/test/Modules/Inputs/double-quotes/X.framework/Headers/X.h b/test/Modules/Inputs/double-quotes/X.framework/Headers/X.h
new file mode 100644
index 000000000000..0185751299c7
--- /dev/null
+++ b/test/Modules/Inputs/double-quotes/X.framework/Headers/X.h
@@ -0,0 +1 @@
+// double-quotes/X.framework/Headers/X.h
diff --git a/test/Modules/Inputs/double-quotes/X.framework/Modules/module.modulemap b/test/Modules/Inputs/double-quotes/X.framework/Modules/module.modulemap
new file mode 100644
index 000000000000..95524704c683
--- /dev/null
+++ b/test/Modules/Inputs/double-quotes/X.framework/Modules/module.modulemap
@@ -0,0 +1,4 @@
+// double-quotes/X.framework/Modules/module.modulemap
+framework module X {
+ header "X.h"
+}
diff --git a/test/Modules/Inputs/double-quotes/a.hmap.json b/test/Modules/Inputs/double-quotes/a.hmap.json
new file mode 100644
index 000000000000..bdd383ce4150
--- /dev/null
+++ b/test/Modules/Inputs/double-quotes/a.hmap.json
@@ -0,0 +1,6 @@
+{
+ "mappings" :
+ {
+ "A.h" : "A/A.h"
+ }
+}
diff --git a/test/Modules/Inputs/double-quotes/flat-header-path/Z.h b/test/Modules/Inputs/double-quotes/flat-header-path/Z.h
new file mode 100644
index 000000000000..db96b64962c1
--- /dev/null
+++ b/test/Modules/Inputs/double-quotes/flat-header-path/Z.h
@@ -0,0 +1 @@
+#import "B.h" // Included from Z.h & A.h
diff --git a/test/Modules/Inputs/double-quotes/flat-header-path/Z.modulemap b/test/Modules/Inputs/double-quotes/flat-header-path/Z.modulemap
new file mode 100644
index 000000000000..34441b07018c
--- /dev/null
+++ b/test/Modules/Inputs/double-quotes/flat-header-path/Z.modulemap
@@ -0,0 +1,4 @@
+// double-quotes/flat-header-path/Z.modulemap
+framework module Z {
+ header "Z.h"
+}
diff --git a/test/Modules/Inputs/double-quotes/x.hmap.json b/test/Modules/Inputs/double-quotes/x.hmap.json
new file mode 100644
index 000000000000..2b6a05956469
--- /dev/null
+++ b/test/Modules/Inputs/double-quotes/x.hmap.json
@@ -0,0 +1,7 @@
+
+{
+ "mappings" :
+ {
+ "X.h" : "X/X.h"
+ }
+}
diff --git a/test/Modules/Inputs/double-quotes/z.yaml b/test/Modules/Inputs/double-quotes/z.yaml
new file mode 100644
index 000000000000..242f821346e6
--- /dev/null
+++ b/test/Modules/Inputs/double-quotes/z.yaml
@@ -0,0 +1,28 @@
+{
+ 'version': 0,
+ 'case-sensitive': 'false',
+ 'roots': [
+ {
+ 'type': 'directory',
+ 'name': "TEST_DIR/Z.framework/Headers",
+ 'contents': [
+ {
+ 'type': 'file',
+ 'name': "Z.h",
+ 'external-contents': "TEST_DIR/flat-header-path/Z.h"
+ }
+ ]
+ },
+ {
+ 'type': 'directory',
+ 'name': "TEST_DIR/Z.framework/Modules",
+ 'contents': [
+ {
+ 'type': 'file',
+ 'name': "module.modulemap",
+ 'external-contents': "TEST_DIR/flat-header-path/Z.modulemap"
+ }
+ ]
+ }
+ ]
+}
diff --git a/test/Modules/Inputs/exportas-link/OtherKit.framework/Headers/OtherKit.h b/test/Modules/Inputs/exportas-link/OtherKit.framework/Headers/OtherKit.h
new file mode 100644
index 000000000000..f62c082d64df
--- /dev/null
+++ b/test/Modules/Inputs/exportas-link/OtherKit.framework/Headers/OtherKit.h
@@ -0,0 +1,7 @@
+// Umbrella header for OtherKit.
+#import <SomeKitCore/SomeKitCore.h>
+
+#ifdef F
+#import <SomeKit/SomeKit.h>
+#endif
+
diff --git a/test/Modules/Inputs/exportas-link/OtherKit.framework/Modules/module.modulemap b/test/Modules/Inputs/exportas-link/OtherKit.framework/Modules/module.modulemap
new file mode 100644
index 000000000000..1ce735121809
--- /dev/null
+++ b/test/Modules/Inputs/exportas-link/OtherKit.framework/Modules/module.modulemap
@@ -0,0 +1,5 @@
+
+framework module OtherKit {
+ header "OtherKit.h"
+ export *
+}
diff --git a/test/Modules/Inputs/exportas-link/SomeKit.framework/Headers/SKWidget.h b/test/Modules/Inputs/exportas-link/SomeKit.framework/Headers/SKWidget.h
new file mode 100644
index 000000000000..60473720f91b
--- /dev/null
+++ b/test/Modules/Inputs/exportas-link/SomeKit.framework/Headers/SKWidget.h
@@ -0,0 +1,2 @@
+// Delegate to SomeKitCore.
+#import <SomeKitCore/SKWidget.h>
diff --git a/test/Modules/Inputs/exportas-link/SomeKit.framework/Headers/SomeKit.h b/test/Modules/Inputs/exportas-link/SomeKit.framework/Headers/SomeKit.h
new file mode 100644
index 000000000000..15e96a7554cc
--- /dev/null
+++ b/test/Modules/Inputs/exportas-link/SomeKit.framework/Headers/SomeKit.h
@@ -0,0 +1,6 @@
+// Umbrella header for SomeKit.
+//
+// Note that this file's content must not end up to coincidentally be identical
+// to any other file in the test which can easily happen given the reduced
+// test.
+#import <SomeKit/SKWidget.h>
diff --git a/test/Modules/Inputs/exportas-link/SomeKit.framework/Modules/module.modulemap b/test/Modules/Inputs/exportas-link/SomeKit.framework/Modules/module.modulemap
new file mode 100644
index 000000000000..ae4b276d47b3
--- /dev/null
+++ b/test/Modules/Inputs/exportas-link/SomeKit.framework/Modules/module.modulemap
@@ -0,0 +1,6 @@
+framework module SomeKit {
+ umbrella header "SomeKit.h"
+ module * {
+ export *
+ }
+}
diff --git a/test/Modules/Inputs/exportas-link/SomeKit.framework/SomeKit.tbd b/test/Modules/Inputs/exportas-link/SomeKit.framework/SomeKit.tbd
new file mode 100644
index 000000000000..ab95795b98e7
--- /dev/null
+++ b/test/Modules/Inputs/exportas-link/SomeKit.framework/SomeKit.tbd
@@ -0,0 +1 @@
+dummy tbd file
diff --git a/test/Modules/Inputs/exportas-link/SomeKitCore.framework/Headers/SKWidget.h b/test/Modules/Inputs/exportas-link/SomeKitCore.framework/Headers/SKWidget.h
new file mode 100644
index 000000000000..1fb010cb39aa
--- /dev/null
+++ b/test/Modules/Inputs/exportas-link/SomeKitCore.framework/Headers/SKWidget.h
@@ -0,0 +1,4 @@
+@interface SKWidget
+- (void)someObjCMethod;
+@end
+
diff --git a/test/Modules/Inputs/exportas-link/SomeKitCore.framework/Headers/SomeKitCore.h b/test/Modules/Inputs/exportas-link/SomeKitCore.framework/Headers/SomeKitCore.h
new file mode 100644
index 000000000000..f18aa97d4218
--- /dev/null
+++ b/test/Modules/Inputs/exportas-link/SomeKitCore.framework/Headers/SomeKitCore.h
@@ -0,0 +1,6 @@
+// Umbrella header for SomeKitCore.
+//
+// Note that this file's content must not end up to coincidentally be identical
+// to any other file in the test which can easily happen given the reduced
+// test.
+#import <SomeKitCore/SKWidget.h>
diff --git a/test/Modules/Inputs/exportas-link/SomeKitCore.framework/Modules/module.modulemap b/test/Modules/Inputs/exportas-link/SomeKitCore.framework/Modules/module.modulemap
new file mode 100644
index 000000000000..30f9770c97c6
--- /dev/null
+++ b/test/Modules/Inputs/exportas-link/SomeKitCore.framework/Modules/module.modulemap
@@ -0,0 +1,7 @@
+framework module SomeKitCore {
+ umbrella header "SomeKitCore.h"
+ export_as SomeKit
+ module * {
+ export *
+ }
+}
diff --git a/test/Modules/Inputs/exportas-link/SomeKitCore.framework/SomeKitCore.tbd b/test/Modules/Inputs/exportas-link/SomeKitCore.framework/SomeKitCore.tbd
new file mode 100644
index 000000000000..ab95795b98e7
--- /dev/null
+++ b/test/Modules/Inputs/exportas-link/SomeKitCore.framework/SomeKitCore.tbd
@@ -0,0 +1 @@
+dummy tbd file
diff --git a/test/Modules/Inputs/framework-public-includes-private/A.framework/Headers/A.h b/test/Modules/Inputs/framework-public-includes-private/A.framework/Headers/A.h
new file mode 100644
index 000000000000..03bd90b4945a
--- /dev/null
+++ b/test/Modules/Inputs/framework-public-includes-private/A.framework/Headers/A.h
@@ -0,0 +1,4 @@
+#include <A/APriv.h>
+#include "APriv2.h"
+#include <Z/Z.h>
+int foo();
diff --git a/test/Modules/Inputs/framework-public-includes-private/A.framework/Modules/module.modulemap b/test/Modules/Inputs/framework-public-includes-private/A.framework/Modules/module.modulemap
new file mode 100644
index 000000000000..09639b2b50bb
--- /dev/null
+++ b/test/Modules/Inputs/framework-public-includes-private/A.framework/Modules/module.modulemap
@@ -0,0 +1,4 @@
+// framework-public-includes-private/A.framework/Modules/module.modulemap
+framework module A {
+ header "A.h"
+}
diff --git a/test/Modules/Inputs/framework-public-includes-private/A.framework/Modules/module.private.modulemap b/test/Modules/Inputs/framework-public-includes-private/A.framework/Modules/module.private.modulemap
new file mode 100644
index 000000000000..8ede0b0d6ee3
--- /dev/null
+++ b/test/Modules/Inputs/framework-public-includes-private/A.framework/Modules/module.private.modulemap
@@ -0,0 +1,4 @@
+// framework-public-includes-private/A.framework/Modules/module.private.modulemap
+framework module A_Private {
+ header "APriv.h"
+}
diff --git a/test/Modules/Inputs/framework-public-includes-private/A.framework/PrivateHeaders/APriv.h b/test/Modules/Inputs/framework-public-includes-private/A.framework/PrivateHeaders/APriv.h
new file mode 100644
index 000000000000..34cc847512f5
--- /dev/null
+++ b/test/Modules/Inputs/framework-public-includes-private/A.framework/PrivateHeaders/APriv.h
@@ -0,0 +1 @@
+// framework-public-includes-private/A.framework/PrivateHeaders/APriv.h
diff --git a/test/Modules/Inputs/framework-public-includes-private/A.framework/PrivateHeaders/APriv2.h b/test/Modules/Inputs/framework-public-includes-private/A.framework/PrivateHeaders/APriv2.h
new file mode 100644
index 000000000000..8ffeb4183740
--- /dev/null
+++ b/test/Modules/Inputs/framework-public-includes-private/A.framework/PrivateHeaders/APriv2.h
@@ -0,0 +1 @@
+// framework-public-includes-private/A.framework/PrivateHeaders/APriv2.h
diff --git a/test/Modules/Inputs/framework-public-includes-private/a.hmap.json b/test/Modules/Inputs/framework-public-includes-private/a.hmap.json
new file mode 100644
index 000000000000..42aed4551c17
--- /dev/null
+++ b/test/Modules/Inputs/framework-public-includes-private/a.hmap.json
@@ -0,0 +1,8 @@
+
+{
+ "mappings" :
+ {
+ "A.h" : "A/A.h",
+ "APriv2.h" : "A/APriv2.h"
+ }
+}
diff --git a/test/Modules/Inputs/framework-public-includes-private/flat-header-path/Z.h b/test/Modules/Inputs/framework-public-includes-private/flat-header-path/Z.h
new file mode 100644
index 000000000000..157c6daa76eb
--- /dev/null
+++ b/test/Modules/Inputs/framework-public-includes-private/flat-header-path/Z.h
@@ -0,0 +1,2 @@
+// framework-public-includes-private/flat-header-path/Z.h
+#import "ZPriv.h"
diff --git a/test/Modules/Inputs/framework-public-includes-private/flat-header-path/Z.modulemap b/test/Modules/Inputs/framework-public-includes-private/flat-header-path/Z.modulemap
new file mode 100644
index 000000000000..0a1a9710c4fa
--- /dev/null
+++ b/test/Modules/Inputs/framework-public-includes-private/flat-header-path/Z.modulemap
@@ -0,0 +1,4 @@
+// framework-public-includes-private/flat-header-path/Z.modulemap
+framework module Z {
+ header "Z.h"
+}
diff --git a/test/Modules/Inputs/framework-public-includes-private/flat-header-path/Z.private.modulemap b/test/Modules/Inputs/framework-public-includes-private/flat-header-path/Z.private.modulemap
new file mode 100644
index 000000000000..f409af8a15af
--- /dev/null
+++ b/test/Modules/Inputs/framework-public-includes-private/flat-header-path/Z.private.modulemap
@@ -0,0 +1,4 @@
+// framework-public-includes-private/flat-header-path/Z.private.modulemap
+framework module Z_Private {
+ header "ZPriv.h"
+}
diff --git a/test/Modules/Inputs/framework-public-includes-private/flat-header-path/ZPriv.h b/test/Modules/Inputs/framework-public-includes-private/flat-header-path/ZPriv.h
new file mode 100644
index 000000000000..08532fedbfa4
--- /dev/null
+++ b/test/Modules/Inputs/framework-public-includes-private/flat-header-path/ZPriv.h
@@ -0,0 +1 @@
+// framework-public-includes-private/flat-header-path/ZPriv.h
diff --git a/test/Modules/Inputs/framework-public-includes-private/z.hmap.json b/test/Modules/Inputs/framework-public-includes-private/z.hmap.json
new file mode 100644
index 000000000000..206b25ec738e
--- /dev/null
+++ b/test/Modules/Inputs/framework-public-includes-private/z.hmap.json
@@ -0,0 +1,7 @@
+
+{
+ "mappings" :
+ {
+ "ZPriv.h" : "Z/ZPriv.h"
+ }
+}
diff --git a/test/Modules/Inputs/framework-public-includes-private/z.yaml b/test/Modules/Inputs/framework-public-includes-private/z.yaml
new file mode 100644
index 000000000000..5793c1ff1f19
--- /dev/null
+++ b/test/Modules/Inputs/framework-public-includes-private/z.yaml
@@ -0,0 +1,45 @@
+{
+ 'version': 0,
+ 'case-sensitive': 'false',
+ 'use-external-names' : 'false',
+ 'roots': [
+ {
+ 'type': 'directory',
+ 'name': "TEST_DIR/Z.framework/Headers",
+ 'contents': [
+ {
+ 'type': 'file',
+ 'name': "Z.h",
+ 'external-contents': "TEST_DIR/flat-header-path/Z.h"
+ }
+ ]
+ },
+ {
+ 'type': 'directory',
+ 'name': "TEST_DIR/Z.framework/PrivateHeaders",
+ 'contents': [
+ {
+ 'type': 'file',
+ 'name': "ZPriv.h",
+ 'external-contents': "TEST_DIR/flat-header-path/ZPriv.h"
+ }
+ ]
+ },
+ {
+ 'type': 'directory',
+ 'name': "TEST_DIR/Z.framework/Modules",
+ 'contents': [
+ {
+ 'type': 'file',
+ 'name': "module.modulemap",
+ 'external-contents': "TEST_DIR/flat-header-path/Z.modulemap"
+ },
+ {
+ 'type': 'file',
+ 'name': "module.private.modulemap",
+ 'external-contents': "TEST_DIR/flat-header-path/Z.private.modulemap"
+ }
+ ]
+ }
+ ]
+}
diff --git a/test/Modules/Inputs/implicit-private-canonical/A.framework/Modules/module.modulemap b/test/Modules/Inputs/implicit-private-canonical/A.framework/Modules/module.modulemap
index 95eabf90a968..e8455fb730d1 100644
--- a/test/Modules/Inputs/implicit-private-canonical/A.framework/Modules/module.modulemap
+++ b/test/Modules/Inputs/implicit-private-canonical/A.framework/Modules/module.modulemap
@@ -1,4 +1,7 @@
framework module A {
header "a.h"
+
+ module Pirate {}
+
export *
}
diff --git a/test/Modules/Inputs/implicit-private-with-submodule/A.framework/Modules/module.modulemap b/test/Modules/Inputs/implicit-private-with-submodule/A.framework/Modules/module.modulemap
index 95eabf90a968..73d5ab7a4bbe 100644
--- a/test/Modules/Inputs/implicit-private-with-submodule/A.framework/Modules/module.modulemap
+++ b/test/Modules/Inputs/implicit-private-with-submodule/A.framework/Modules/module.modulemap
@@ -2,3 +2,9 @@ framework module A {
header "a.h"
export *
}
+
+framework module B {
+}
+
+framework module C {
+}
diff --git a/test/Modules/Inputs/implicit-private-with-submodule/A.framework/Modules/module.private.modulemap b/test/Modules/Inputs/implicit-private-with-submodule/A.framework/Modules/module.private.modulemap
index 40182969f4c7..9acb48997021 100644
--- a/test/Modules/Inputs/implicit-private-with-submodule/A.framework/Modules/module.private.modulemap
+++ b/test/Modules/Inputs/implicit-private-with-submodule/A.framework/Modules/module.private.modulemap
@@ -2,3 +2,9 @@ framework module A.Private {
header "aprivate.h"
export *
}
+
+explicit module B.Private {
+}
+
+explicit framework module C.Private {
+}
diff --git a/test/Modules/Inputs/incomplete-framework-module/Foo.framework/Headers/Foo.h b/test/Modules/Inputs/incomplete-framework-module/Foo.framework/Headers/Foo.h
new file mode 100644
index 000000000000..547f1bc6b086
--- /dev/null
+++ b/test/Modules/Inputs/incomplete-framework-module/Foo.framework/Headers/Foo.h
@@ -0,0 +1 @@
+// Inputs/incomplete-framework-module/Foo.framework/Headers/Foo.h
diff --git a/test/Modules/Inputs/incomplete-framework-module/Foo.framework/Headers/FooB.h b/test/Modules/Inputs/incomplete-framework-module/Foo.framework/Headers/FooB.h
new file mode 100644
index 000000000000..eda7c1707000
--- /dev/null
+++ b/test/Modules/Inputs/incomplete-framework-module/Foo.framework/Headers/FooB.h
@@ -0,0 +1 @@
+// FooB.h
diff --git a/test/Modules/Inputs/incomplete-framework-module/Foo.framework/Modules/module.modulemap b/test/Modules/Inputs/incomplete-framework-module/Foo.framework/Modules/module.modulemap
new file mode 100644
index 000000000000..d928a53efcdf
--- /dev/null
+++ b/test/Modules/Inputs/incomplete-framework-module/Foo.framework/Modules/module.modulemap
@@ -0,0 +1,4 @@
+module Foo {
+ umbrella header "Foo.h"
+ header "FooB.h"
+}
diff --git a/test/Modules/Inputs/module.map b/test/Modules/Inputs/module.map
index 4788daa43166..3f128c0bb0e0 100644
--- a/test/Modules/Inputs/module.map
+++ b/test/Modules/Inputs/module.map
@@ -380,6 +380,11 @@ module TargetFeatures {
module x86_32 { requires x86_32 }
module x86_64 { requires x86_64 }
}
+ module riscv {
+ requires riscv
+ module riscv32 { requires riscv32 }
+ module riscv64 { requires riscv64 }
+ }
}
module DebugSubmodules {
@@ -460,3 +465,13 @@ module innerstructredef {
header "innerstructredef.h"
}
}
+
+module template_nontrivial0 {
+ header "template-nontrivial0.h"
+ export *
+}
+
+module template_nontrivial1 {
+ header "template-nontrivial1.h"
+ export *
+}
diff --git a/test/Modules/Inputs/non-ambiguous-enum/A.framework/Headers/a.h b/test/Modules/Inputs/non-ambiguous-enum/A.framework/Headers/a.h
new file mode 100644
index 000000000000..060bc4997385
--- /dev/null
+++ b/test/Modules/Inputs/non-ambiguous-enum/A.framework/Headers/a.h
@@ -0,0 +1 @@
+#include <A/a0.h>
diff --git a/test/Modules/Inputs/non-ambiguous-enum/A.framework/Headers/a0.h b/test/Modules/Inputs/non-ambiguous-enum/A.framework/Headers/a0.h
new file mode 100644
index 000000000000..2e4d0912119e
--- /dev/null
+++ b/test/Modules/Inputs/non-ambiguous-enum/A.framework/Headers/a0.h
@@ -0,0 +1 @@
+#include <B/b.h>
diff --git a/test/Modules/Inputs/non-ambiguous-enum/A.framework/Modules/module.modulemap b/test/Modules/Inputs/non-ambiguous-enum/A.framework/Modules/module.modulemap
new file mode 100644
index 000000000000..e14f8f02053a
--- /dev/null
+++ b/test/Modules/Inputs/non-ambiguous-enum/A.framework/Modules/module.modulemap
@@ -0,0 +1,5 @@
+
+framework module A {
+ header "a.h"
+ export *
+}
diff --git a/test/Modules/Inputs/non-ambiguous-enum/B.framework/Headers/b.h b/test/Modules/Inputs/non-ambiguous-enum/B.framework/Headers/b.h
new file mode 100644
index 000000000000..def44e3a6340
--- /dev/null
+++ b/test/Modules/Inputs/non-ambiguous-enum/B.framework/Headers/b.h
@@ -0,0 +1,6 @@
+typedef long NSInteger;
+typedef enum __attribute__((flag_enum,enum_extensibility(open))) MyObjCEnum : NSInteger MyObjCEnum;
+
+enum MyObjCEnum : NSInteger {
+ MyEnumCst = 1,
+} __attribute__((availability(ios,introduced=11.0))) __attribute__((availability(tvos,unavailable))) ;
diff --git a/test/Modules/Inputs/odr_hash-Friend/Bad.h b/test/Modules/Inputs/odr_hash-Friend/Bad.h
new file mode 100644
index 000000000000..c0a6d1f9889f
--- /dev/null
+++ b/test/Modules/Inputs/odr_hash-Friend/Bad.h
@@ -0,0 +1,17 @@
+template <class T>
+struct iterator {
+ void Compare(const iterator &x) { return; }
+ friend void Check(iterator) { return; }
+};
+
+template <class T = int> struct Box {
+ iterator<T> I;
+
+ void test() {
+ Check(I);
+ I.Compare(I);
+ }
+};
+
+// Force instantiation of Box<int>
+Box<> B;
diff --git a/test/Modules/Inputs/odr_hash-Friend/Box.h b/test/Modules/Inputs/odr_hash-Friend/Box.h
new file mode 100644
index 000000000000..01ab90d601c2
--- /dev/null
+++ b/test/Modules/Inputs/odr_hash-Friend/Box.h
@@ -0,0 +1,14 @@
+template <class T>
+struct iterator {
+ void Compare(const iterator &x) { }
+ friend void Check(iterator) {}
+};
+
+template <class T = int> struct Box {
+ iterator<T> I;
+
+ void test() {
+ Check(I);
+ I.Compare(I);
+ }
+};
diff --git a/test/Modules/Inputs/odr_hash-Friend/Good.h b/test/Modules/Inputs/odr_hash-Friend/Good.h
new file mode 100644
index 000000000000..4c38392eb6ed
--- /dev/null
+++ b/test/Modules/Inputs/odr_hash-Friend/Good.h
@@ -0,0 +1,17 @@
+template <class T>
+struct iterator {
+ void Compare(const iterator &x) { }
+ friend void Check(iterator) {}
+};
+
+template <class T = int> struct Box {
+ iterator<T> I;
+
+ void test() {
+ Check(I);
+ I.Compare(I);
+ }
+};
+
+// Force instantiation of Box<int>
+Box<> B;
diff --git a/test/Modules/Inputs/odr_hash-Friend/M1.h b/test/Modules/Inputs/odr_hash-Friend/M1.h
new file mode 100644
index 000000000000..202ad06c3488
--- /dev/null
+++ b/test/Modules/Inputs/odr_hash-Friend/M1.h
@@ -0,0 +1,6 @@
+#include "Box.h"
+
+void Peek() {
+ Box<> Gift;
+ Gift.test();
+}
diff --git a/test/Modules/Inputs/odr_hash-Friend/M2.h b/test/Modules/Inputs/odr_hash-Friend/M2.h
new file mode 100644
index 000000000000..69f08a957ede
--- /dev/null
+++ b/test/Modules/Inputs/odr_hash-Friend/M2.h
@@ -0,0 +1,5 @@
+#include "Box.h"
+void x() {
+ Box<> Unused;
+ //Unused.test();
+}
diff --git a/test/Modules/Inputs/odr_hash-Friend/M3.h b/test/Modules/Inputs/odr_hash-Friend/M3.h
new file mode 100644
index 000000000000..ab457e0c08f2
--- /dev/null
+++ b/test/Modules/Inputs/odr_hash-Friend/M3.h
@@ -0,0 +1,7 @@
+#include "Box.h"
+#include "M2.h"
+
+void Party() {
+ Box<> Present;
+ Present.test();
+}
diff --git a/test/Modules/Inputs/odr_hash-Friend/module.modulemap b/test/Modules/Inputs/odr_hash-Friend/module.modulemap
new file mode 100644
index 000000000000..449d51e7f709
--- /dev/null
+++ b/test/Modules/Inputs/odr_hash-Friend/module.modulemap
@@ -0,0 +1,23 @@
+module Box {
+ header "Box.h"
+}
+
+module Module1 {
+ header "M1.h"
+}
+
+module Module2 {
+ header "M2.h"
+}
+
+module Module3 {
+ header "M3.h"
+}
+
+module Good {
+ header "Good.h"
+}
+
+module Bad {
+ header "Bad.h"
+}
diff --git a/test/Modules/Inputs/odr_hash-Unresolved/Module2/include.h b/test/Modules/Inputs/odr_hash-Unresolved/Module2/include.h
new file mode 100644
index 000000000000..fa7c017228e7
--- /dev/null
+++ b/test/Modules/Inputs/odr_hash-Unresolved/Module2/include.h
@@ -0,0 +1,3 @@
+// include.h
+#include "Sub1/Z.h"
+
diff --git a/test/Modules/Inputs/odr_hash-Unresolved/Module2/not-include.h b/test/Modules/Inputs/odr_hash-Unresolved/Module2/not-include.h
new file mode 100644
index 000000000000..98cd1ef26fce
--- /dev/null
+++ b/test/Modules/Inputs/odr_hash-Unresolved/Module2/not-include.h
@@ -0,0 +1,5 @@
+// not-include.h
+
+#include "function.h"
+#include "class.h"
+
diff --git a/test/Modules/Inputs/odr_hash-Unresolved/Sub1/X.h b/test/Modules/Inputs/odr_hash-Unresolved/Sub1/X.h
new file mode 100644
index 000000000000..f610e665e5cb
--- /dev/null
+++ b/test/Modules/Inputs/odr_hash-Unresolved/Sub1/X.h
@@ -0,0 +1,3 @@
+// X.h
+#include "Sub1/Z.h"
+
diff --git a/test/Modules/Inputs/odr_hash-Unresolved/Sub1/Y.h b/test/Modules/Inputs/odr_hash-Unresolved/Sub1/Y.h
new file mode 100644
index 000000000000..f41ddd639e76
--- /dev/null
+++ b/test/Modules/Inputs/odr_hash-Unresolved/Sub1/Y.h
@@ -0,0 +1,4 @@
+// Y.h
+#include "Sub1/Z.h"
+#include "class.h"
+
diff --git a/test/Modules/Inputs/odr_hash-Unresolved/Sub1/Z.h b/test/Modules/Inputs/odr_hash-Unresolved/Sub1/Z.h
new file mode 100644
index 000000000000..b6bdc140f997
--- /dev/null
+++ b/test/Modules/Inputs/odr_hash-Unresolved/Sub1/Z.h
@@ -0,0 +1,4 @@
+// Z.h
+#include "Sub2/A.h"
+#include "Sub2/B.h"
+
diff --git a/test/Modules/Inputs/odr_hash-Unresolved/Sub2/A.h b/test/Modules/Inputs/odr_hash-Unresolved/Sub2/A.h
new file mode 100644
index 000000000000..a65b370beae3
--- /dev/null
+++ b/test/Modules/Inputs/odr_hash-Unresolved/Sub2/A.h
@@ -0,0 +1,3 @@
+// A.h
+#include "function.h"
+
diff --git a/test/Modules/Inputs/odr_hash-Unresolved/Sub2/B.h b/test/Modules/Inputs/odr_hash-Unresolved/Sub2/B.h
new file mode 100644
index 000000000000..fa89f216b6ce
--- /dev/null
+++ b/test/Modules/Inputs/odr_hash-Unresolved/Sub2/B.h
@@ -0,0 +1,3 @@
+// B.h
+#include "function.h"
+
diff --git a/test/Modules/Inputs/odr_hash-Unresolved/class.h b/test/Modules/Inputs/odr_hash-Unresolved/class.h
new file mode 100644
index 000000000000..fe3a7116f9bf
--- /dev/null
+++ b/test/Modules/Inputs/odr_hash-Unresolved/class.h
@@ -0,0 +1,11 @@
+#ifndef Class
+#define Class
+template <class T>
+class S {
+ int Field;
+ void run() {
+ int x;
+ A::Check(&Field, 1);
+ }
+};
+#endif
diff --git a/test/Modules/Inputs/odr_hash-Unresolved/function.h b/test/Modules/Inputs/odr_hash-Unresolved/function.h
new file mode 100644
index 000000000000..de75b2c92ef6
--- /dev/null
+++ b/test/Modules/Inputs/odr_hash-Unresolved/function.h
@@ -0,0 +1,6 @@
+#ifndef Function
+#define Function
+namespace A {
+static void Check(int*, int) {}
+}
+#endif
diff --git a/test/Modules/Inputs/odr_hash-Unresolved/module.modulemap b/test/Modules/Inputs/odr_hash-Unresolved/module.modulemap
new file mode 100644
index 000000000000..ac7fc43cae63
--- /dev/null
+++ b/test/Modules/Inputs/odr_hash-Unresolved/module.modulemap
@@ -0,0 +1,21 @@
+module Module1 {
+ module Sub1 {
+ umbrella "Sub1"
+ module * { export * }
+ }
+
+ module Sub2 {
+ umbrella "Sub2"
+ module * { export * }
+ }
+}
+
+module Module2 {
+ umbrella "Module2"
+ module * { export * }
+}
+
+module Other {
+ textual header "function.h"
+ textual header "class.h"
+}
diff --git a/test/Modules/Inputs/odr_hash-elaborated-types/first.h b/test/Modules/Inputs/odr_hash-elaborated-types/first.h
new file mode 100644
index 000000000000..d2c4a033a161
--- /dev/null
+++ b/test/Modules/Inputs/odr_hash-elaborated-types/first.h
@@ -0,0 +1,6 @@
+#ifndef FIRST
+#define FIRST
+
+#include "textual_time.h"
+
+#endif
diff --git a/test/Modules/Inputs/odr_hash-elaborated-types/module.modulemap b/test/Modules/Inputs/odr_hash-elaborated-types/module.modulemap
new file mode 100644
index 000000000000..94cb4c111918
--- /dev/null
+++ b/test/Modules/Inputs/odr_hash-elaborated-types/module.modulemap
@@ -0,0 +1,5 @@
+module M {
+ module first { header "first.h" export *}
+ module second { header "second.h" export *}
+ export *
+}
diff --git a/test/Modules/Inputs/odr_hash-elaborated-types/second.h b/test/Modules/Inputs/odr_hash-elaborated-types/second.h
new file mode 100644
index 000000000000..577cf1134579
--- /dev/null
+++ b/test/Modules/Inputs/odr_hash-elaborated-types/second.h
@@ -0,0 +1,6 @@
+#ifndef SECOND
+#define SECOND
+
+#include "textual_stat.h"
+
+#endif
diff --git a/test/Modules/Inputs/odr_hash-elaborated-types/textual_stat.h b/test/Modules/Inputs/odr_hash-elaborated-types/textual_stat.h
new file mode 100644
index 000000000000..5dad510f9eb9
--- /dev/null
+++ b/test/Modules/Inputs/odr_hash-elaborated-types/textual_stat.h
@@ -0,0 +1,11 @@
+#ifndef _SYS_STAT_H
+#define _SYS_STAT_H
+
+#include "textual_time.h"
+
+struct stat {
+ struct timespec st_atim;
+ struct timespec st_mtim;
+};
+
+#endif
diff --git a/test/Modules/Inputs/odr_hash-elaborated-types/textual_time.h b/test/Modules/Inputs/odr_hash-elaborated-types/textual_time.h
new file mode 100644
index 000000000000..2a2a89c5a7eb
--- /dev/null
+++ b/test/Modules/Inputs/odr_hash-elaborated-types/textual_time.h
@@ -0,0 +1,6 @@
+#ifndef _TIME_H
+#define _TIME_H
+
+struct timespec { };
+
+#endif
diff --git a/test/Modules/Inputs/protocol-redefinition/Base.framework/Headers/Base.h b/test/Modules/Inputs/protocol-redefinition/Base.framework/Headers/Base.h
new file mode 100644
index 000000000000..e3fe33c1bdb9
--- /dev/null
+++ b/test/Modules/Inputs/protocol-redefinition/Base.framework/Headers/Base.h
@@ -0,0 +1,3 @@
+@protocol Foo
+- (void)someMethodOnFoo;
+@end
diff --git a/test/Modules/Inputs/protocol-redefinition/Base.framework/Modules/module.modulemap b/test/Modules/Inputs/protocol-redefinition/Base.framework/Modules/module.modulemap
new file mode 100644
index 000000000000..0366bb4f0390
--- /dev/null
+++ b/test/Modules/Inputs/protocol-redefinition/Base.framework/Modules/module.modulemap
@@ -0,0 +1,4 @@
+framework module Base {
+ header "Base.h"
+ export *
+} \ No newline at end of file
diff --git a/test/Modules/Inputs/protocol-redefinition/Kit.framework/Headers/Kit.h b/test/Modules/Inputs/protocol-redefinition/Kit.framework/Headers/Kit.h
new file mode 100644
index 000000000000..93384c294f13
--- /dev/null
+++ b/test/Modules/Inputs/protocol-redefinition/Kit.framework/Headers/Kit.h
@@ -0,0 +1,6 @@
+#import <Base/Base.h>
+
+// REDECLARATION
+@protocol Foo
+- (void)someMethodOnFoo;
+@end
diff --git a/test/Modules/Inputs/protocol-redefinition/Kit.framework/Modules/module.modulemap b/test/Modules/Inputs/protocol-redefinition/Kit.framework/Modules/module.modulemap
new file mode 100644
index 000000000000..2b790f449654
--- /dev/null
+++ b/test/Modules/Inputs/protocol-redefinition/Kit.framework/Modules/module.modulemap
@@ -0,0 +1,4 @@
+framework module Kit {
+ header "Kit.h"
+ export *
+} \ No newline at end of file
diff --git a/test/Modules/Inputs/self-referencing-lambda/a.h b/test/Modules/Inputs/self-referencing-lambda/a.h
new file mode 100644
index 000000000000..756fe18de629
--- /dev/null
+++ b/test/Modules/Inputs/self-referencing-lambda/a.h
@@ -0,0 +1,4 @@
+void f() {
+ int x = 0;
+ auto q = [xm = x]{};
+}
diff --git a/test/Modules/Inputs/self-referencing-lambda/module.modulemap b/test/Modules/Inputs/self-referencing-lambda/module.modulemap
new file mode 100644
index 000000000000..812ca9de82d3
--- /dev/null
+++ b/test/Modules/Inputs/self-referencing-lambda/module.modulemap
@@ -0,0 +1,4 @@
+module "a.h" {
+ header "a.h"
+ export *
+}
diff --git a/test/Modules/Inputs/shadow/A1/A.h b/test/Modules/Inputs/shadow/A1/A.h
new file mode 100644
index 000000000000..f07c681c2aa5
--- /dev/null
+++ b/test/Modules/Inputs/shadow/A1/A.h
@@ -0,0 +1 @@
+#define A1_A_h
diff --git a/test/Modules/Inputs/shadow/A1/module.modulemap b/test/Modules/Inputs/shadow/A1/module.modulemap
new file mode 100644
index 000000000000..9439a431b1db
--- /dev/null
+++ b/test/Modules/Inputs/shadow/A1/module.modulemap
@@ -0,0 +1,5 @@
+module A {
+ header "A.h"
+}
+
+module A1 {}
diff --git a/test/Modules/Inputs/shadow/A2/A.h b/test/Modules/Inputs/shadow/A2/A.h
new file mode 100644
index 000000000000..9880ed010f56
--- /dev/null
+++ b/test/Modules/Inputs/shadow/A2/A.h
@@ -0,0 +1 @@
+#define A2_A_h
diff --git a/test/Modules/Inputs/shadow/A2/module.modulemap b/test/Modules/Inputs/shadow/A2/module.modulemap
new file mode 100644
index 000000000000..935d89bb425e
--- /dev/null
+++ b/test/Modules/Inputs/shadow/A2/module.modulemap
@@ -0,0 +1,5 @@
+module A {
+ header "A.h"
+}
+
+module A2 {}
diff --git a/test/Modules/Inputs/shadowed-submodule/A1/Foo.h b/test/Modules/Inputs/shadowed-submodule/A1/Foo.h
new file mode 100644
index 000000000000..57775d1a29dd
--- /dev/null
+++ b/test/Modules/Inputs/shadowed-submodule/A1/Foo.h
@@ -0,0 +1 @@
+#include <stdarg.h> // expected-error {{could not build module 'A'}}
diff --git a/test/Modules/Inputs/shadowed-submodule/A1/module.modulemap b/test/Modules/Inputs/shadowed-submodule/A1/module.modulemap
new file mode 100644
index 000000000000..7afbc4713617
--- /dev/null
+++ b/test/Modules/Inputs/shadowed-submodule/A1/module.modulemap
@@ -0,0 +1,14 @@
+module A [system] { // expected-note {{previous definition is here}}
+ module sub {
+ header "sys/A.h"
+ }
+ module sub2 {
+ header "sys/A2.h"
+ }
+ module stdarg {
+ header "stdarg.h"
+ export *
+ }
+}
+
+module A2 {}
diff --git a/test/Modules/Inputs/shadowed-submodule/A1/sys/A.h b/test/Modules/Inputs/shadowed-submodule/A1/sys/A.h
new file mode 100644
index 000000000000..4fc3e8ea9e63
--- /dev/null
+++ b/test/Modules/Inputs/shadowed-submodule/A1/sys/A.h
@@ -0,0 +1 @@
+#include <sys/A2.h>
diff --git a/test/Modules/Inputs/shadowed-submodule/A1/sys/A2.h b/test/Modules/Inputs/shadowed-submodule/A1/sys/A2.h
new file mode 100644
index 000000000000..e9b6a44cfe21
--- /dev/null
+++ b/test/Modules/Inputs/shadowed-submodule/A1/sys/A2.h
@@ -0,0 +1 @@
+// nothing
diff --git a/test/Modules/Inputs/shadowed-submodule/A2/Foo.h b/test/Modules/Inputs/shadowed-submodule/A2/Foo.h
new file mode 100644
index 000000000000..38ade6d9f505
--- /dev/null
+++ b/test/Modules/Inputs/shadowed-submodule/A2/Foo.h
@@ -0,0 +1 @@
+#include <stdarg.h>
diff --git a/test/Modules/Inputs/shadowed-submodule/A2/module.modulemap b/test/Modules/Inputs/shadowed-submodule/A2/module.modulemap
new file mode 100644
index 000000000000..c4e44b074aa1
--- /dev/null
+++ b/test/Modules/Inputs/shadowed-submodule/A2/module.modulemap
@@ -0,0 +1,14 @@
+module A [system] {
+ module sub {
+ header "sys/A.h"
+ }
+ module sub2 { // expected-error {{build a shadowed submodule 'A.sub2'}}
+ header "sys/A2.h"
+ }
+ module stdarg {
+ header "stdarg.h"
+ export *
+ }
+}
+
+module A2 {}
diff --git a/test/Modules/Inputs/shadowed-submodule/A2/sys/A.h b/test/Modules/Inputs/shadowed-submodule/A2/sys/A.h
new file mode 100644
index 000000000000..4fc3e8ea9e63
--- /dev/null
+++ b/test/Modules/Inputs/shadowed-submodule/A2/sys/A.h
@@ -0,0 +1 @@
+#include <sys/A2.h>
diff --git a/test/Modules/Inputs/shadowed-submodule/A2/sys/A2.h b/test/Modules/Inputs/shadowed-submodule/A2/sys/A2.h
new file mode 100644
index 000000000000..e9b6a44cfe21
--- /dev/null
+++ b/test/Modules/Inputs/shadowed-submodule/A2/sys/A2.h
@@ -0,0 +1 @@
+// nothing
diff --git a/test/Modules/Inputs/shadowed-submodule/Foo/module.modulemap b/test/Modules/Inputs/shadowed-submodule/Foo/module.modulemap
new file mode 100644
index 000000000000..11db9cb05da2
--- /dev/null
+++ b/test/Modules/Inputs/shadowed-submodule/Foo/module.modulemap
@@ -0,0 +1,3 @@
+module Foo {
+ header "../A1/Foo.h"
+}
diff --git a/test/Modules/Inputs/submodule-in-private-mmap/A.framework/Headers/A.h b/test/Modules/Inputs/submodule-in-private-mmap/A.framework/Headers/A.h
new file mode 100644
index 000000000000..975f1f0437bb
--- /dev/null
+++ b/test/Modules/Inputs/submodule-in-private-mmap/A.framework/Headers/A.h
@@ -0,0 +1 @@
+// A.h
diff --git a/test/Modules/Inputs/submodule-in-private-mmap/A.framework/Headers/SomeSub.h b/test/Modules/Inputs/submodule-in-private-mmap/A.framework/Headers/SomeSub.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Modules/Inputs/submodule-in-private-mmap/A.framework/Headers/SomeSub.h
diff --git a/test/Modules/Inputs/submodule-in-private-mmap/A.framework/Modules/module.modulemap b/test/Modules/Inputs/submodule-in-private-mmap/A.framework/Modules/module.modulemap
new file mode 100644
index 000000000000..afa48392e94a
--- /dev/null
+++ b/test/Modules/Inputs/submodule-in-private-mmap/A.framework/Modules/module.modulemap
@@ -0,0 +1,3 @@
+framework module A {
+ header "A.h"
+}
diff --git a/test/Modules/Inputs/submodule-in-private-mmap/A.framework/Modules/module.private.modulemap b/test/Modules/Inputs/submodule-in-private-mmap/A.framework/Modules/module.private.modulemap
new file mode 100644
index 000000000000..1dbd9fb8096b
--- /dev/null
+++ b/test/Modules/Inputs/submodule-in-private-mmap/A.framework/Modules/module.private.modulemap
@@ -0,0 +1,7 @@
+framework module A_Private {
+ header "APrivate.h"
+}
+
+module A.SomeSub {
+ header "SomeSub.h"
+}
diff --git a/test/Modules/Inputs/submodule-in-private-mmap/A.framework/PrivateHeaders/APrivate.h b/test/Modules/Inputs/submodule-in-private-mmap/A.framework/PrivateHeaders/APrivate.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Modules/Inputs/submodule-in-private-mmap/A.framework/PrivateHeaders/APrivate.h
diff --git a/test/Modules/Inputs/template-nontrivial0.h b/test/Modules/Inputs/template-nontrivial0.h
new file mode 100644
index 000000000000..cff080ee5cc2
--- /dev/null
+++ b/test/Modules/Inputs/template-nontrivial0.h
@@ -0,0 +1,13 @@
+template <class T>
+struct Class0 {
+ Class0();
+ Class0(const Class0<T> &);
+ ~Class0();
+ T *p;
+};
+
+struct S0 {
+ id x;
+};
+
+Class0<S0> returnNonTrivial();
diff --git a/test/Modules/Inputs/template-nontrivial1.h b/test/Modules/Inputs/template-nontrivial1.h
new file mode 100644
index 000000000000..24136f0cae4e
--- /dev/null
+++ b/test/Modules/Inputs/template-nontrivial1.h
@@ -0,0 +1,6 @@
+@import template_nontrivial0;
+
+struct S1 {
+ S1();
+ Class0<S0> a;
+};
diff --git a/test/Modules/ModuleDebugInfo.cpp b/test/Modules/ModuleDebugInfo.cpp
index 008b3e4f2bab..116aa5fc3107 100644
--- a/test/Modules/ModuleDebugInfo.cpp
+++ b/test/Modules/ModuleDebugInfo.cpp
@@ -5,12 +5,13 @@
// Modules:
// RUN: rm -rf %t
-// RUN: %clang_cc1 -triple %itanium_abi_triple -x objective-c++ -std=c++11 -debug-info-kind=limited -fmodules -fmodule-format=obj -fimplicit-module-maps -DMODULES -fmodules-cache-path=%t %s -I %S/Inputs -I %t -emit-llvm -o %t.ll -mllvm -debug-only=pchcontainer &>%t-mod.ll
+// RUN: %clang_cc1 -triple %itanium_abi_triple -x objective-c++ -std=c++11 -debugger-tuning=lldb -debug-info-kind=limited -fmodules -fmodule-format=obj -fimplicit-module-maps -DMODULES -fmodules-cache-path=%t %s -I %S/Inputs -I %t -emit-llvm -o %t.ll -mllvm -debug-only=pchcontainer &>%t-mod.ll
// RUN: cat %t-mod.ll | FileCheck %s
// RUN: cat %t-mod.ll | FileCheck --check-prefix=CHECK-NEG %s
+// RUN: cat %t-mod.ll | FileCheck --check-prefix=CHECK-MOD %s
// PCH:
-// RUN: %clang_cc1 -triple %itanium_abi_triple -x c++ -std=c++11 -emit-pch -fmodule-format=obj -I %S/Inputs -o %t.pch %S/Inputs/DebugCXX.h -mllvm -debug-only=pchcontainer &>%t-pch.ll
+// RUN: %clang_cc1 -triple %itanium_abi_triple -x c++ -std=c++11 -debugger-tuning=lldb -emit-pch -fmodule-format=obj -I %S/Inputs -o %t.pch %S/Inputs/DebugCXX.h -mllvm -debug-only=pchcontainer &>%t-pch.ll
// RUN: cat %t-pch.ll | FileCheck %s
// RUN: cat %t-pch.ll | FileCheck --check-prefix=CHECK-NEG %s
@@ -18,6 +19,9 @@
@import DebugCXX;
#endif
+// CHECK-MOD: distinct !DICompileUnit(language: DW_LANG_{{.*}}C_plus_plus,
+// CHECK-MOD: distinct !DICompileUnit(language: DW_LANG_{{.*}}C_plus_plus,
+
// CHECK: distinct !DICompileUnit(language: DW_LANG_{{.*}}C_plus_plus,
// CHECK-SAME: isOptimized: false,
// CHECK-NOT: splitDebugFilename:
@@ -27,6 +31,8 @@
// CHECK-SAME: identifier: "_ZTSN8DebugCXX4EnumE")
// CHECK: !DINamespace(name: "DebugCXX"
+// CHECK-MOD: ![[DEBUGCXX:.*]] = !DIModule(scope: null, name: "DebugCXX
+
// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type,
// CHECK-NOT: name:
// CHECK-SAME: )
@@ -42,7 +48,7 @@
// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type,
// CHECK-NOT: name:
// CHECK-SAME: )
-// CHECK: !DIEnumerator(name: "e5", value: 5)
+// CHECK: !DIEnumerator(name: "e5", value: 5, isUnsigned: true)
// CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "B",
// no mangled name here yet.
@@ -150,4 +156,11 @@
// CHECK-SAME: name: "WithSpecializedBase<float>",
// CHECK-SAME: flags: DIFlagFwdDecl,
+// CHECK-MOD: !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: ![[DEBUGCXX]],
+// CHECK-MOD-SAME: entity: ![[DUMMY:[0-9]+]],
+// CHECK-MOD-SAME: line: 3)
+// CHECK-MOD: ![[DUMMY]] = !DIModule(scope: null, name: "dummy",
+// CHECK-MOD: distinct !DICompileUnit(language: DW_LANG_ObjC_plus_plus,
+// CHECK-MOD-SAME: splitDebugFilename: "{{.*}}dummy{{.*}}.pcm",
+
// CHECK-NEG-NOT: !DICompositeType(tag: DW_TAG_structure_type, name: "PureForwardDecl"
diff --git a/test/Modules/at-import-in-framework-header.m b/test/Modules/at-import-in-framework-header.m
new file mode 100644
index 000000000000..fe3663812075
--- /dev/null
+++ b/test/Modules/at-import-in-framework-header.m
@@ -0,0 +1,17 @@
+// REQUIRES: shell
+
+// RUN: rm -rf %t
+// RUN: mkdir %t
+
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache \
+// RUN: -F%S/Inputs/at-import-in-framework-header -I%S/Inputs/at-import-in-framework-header \
+// RUN: -Watimport-in-framework-header -fsyntax-only %s \
+// RUN: 2>%t/stderr
+// RUN: FileCheck --input-file=%t/stderr %s
+
+// CHECK: use of '@import' in framework header is discouraged
+
+#import <A/A.h>
+
+int bar() { return foo(); }
+
diff --git a/test/Modules/autoload-subdirectory.cpp b/test/Modules/autoload-subdirectory.cpp
new file mode 100644
index 000000000000..e76f7056abed
--- /dev/null
+++ b/test/Modules/autoload-subdirectory.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -fmodules -fmodule-name=Foo -I %S/Inputs/autoload-subdirectory/ %s -verify
+// expected-no-diagnostics
+
+#include "a.h"
+#import "c.h"
+
+int main() {
+ foo neko;
+ return 0;
+}
diff --git a/test/Modules/bad-private-include.m b/test/Modules/bad-private-include.m
new file mode 100644
index 000000000000..e12b280be7ef
--- /dev/null
+++ b/test/Modules/bad-private-include.m
@@ -0,0 +1,6 @@
+// RUN: rm -rf %t.cache
+// RUN: %clang_cc1 -fmodules-cache-path=%t.cache -fmodules -fimplicit-module-maps -F %S/Inputs/bad-private-include %s -verify
+
+// expected-no-diagnostics
+
+@import Bad;
diff --git a/test/Modules/check-for-sanitizer-feature.cpp b/test/Modules/check-for-sanitizer-feature.cpp
index 40ae46c64684..c015669071b7 100644
--- a/test/Modules/check-for-sanitizer-feature.cpp
+++ b/test/Modules/check-for-sanitizer-feature.cpp
@@ -43,7 +43,7 @@
//
// Import the PCH without ASan enabled (we expect an error).
// RUN: not %clang_cc1 -x c -include-pch %t.asan_pch %s -verify 2>&1 | FileCheck %s --check-prefix=PCH_MISMATCH
-// PCH_MISMATCH: AST file was compiled with the target feature'-fsanitize=address' but the current translation unit is not
+// PCH_MISMATCH: AST file was compiled with the target feature '-fsanitize=address' but the current translation unit is not
//
// Emit a PCH with UBSan enabled.
// RUN: %clang_cc1 -x c -fsanitize=null %S/Inputs/check-for-sanitizer-feature/check.h -emit-pch -o %t.ubsan_pch
diff --git a/test/Modules/class-extension-protocol.m b/test/Modules/class-extension-protocol.m
new file mode 100644
index 000000000000..752e4e129d29
--- /dev/null
+++ b/test/Modules/class-extension-protocol.m
@@ -0,0 +1,9 @@
+// RUN: rm -rf %t.cache
+// RUN: %clang_cc1 %s -fsyntax-only -fmodules -fimplicit-module-maps -fmodules-cache-path=%t.cache -I%S/Inputs/class-extension -verify
+// expected-no-diagnostics
+
+#import "a-private.h"
+
+int foo(A *X) {
+ return X.p0 + X.p1;
+}
diff --git a/test/Modules/codegen.test b/test/Modules/codegen.test
index a919933da2d2..2d20b078a753 100644
--- a/test/Modules/codegen.test
+++ b/test/Modules/codegen.test
@@ -6,6 +6,7 @@ RUN: %clang_cc1 -triple=x86_64-linux-gnu -fmodules-codegen -fmodules-debuginfo -
RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -debug-info-kind=limited -o - %t/foo.pcm | FileCheck --check-prefix=FOO --check-prefix=BOTH %s
RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -debug-info-kind=limited -o - -fmodules -disable-llvm-passes -fmodule-file=%t/foo.pcm %S/Inputs/codegen/use.cpp | FileCheck --check-prefix=BOTH --check-prefix=USE %s
+
For want of any better definition, inline asm goes "everywhere" the same as it
if it were in a header (with the disadvantage that the inline asm will be
included in the program if the module is used, even if the header containing
diff --git a/test/Modules/crash-vfs-headermaps.m b/test/Modules/crash-vfs-headermaps.m
index 4f88f3ba1197..118537ba2a4f 100644
--- a/test/Modules/crash-vfs-headermaps.m
+++ b/test/Modules/crash-vfs-headermaps.m
@@ -1,15 +1,9 @@
// REQUIRES: crash-recovery, shell, system-darwin
-// This uses a headermap with this entry:
-// Foo.h -> Foo/Foo.h
-
-// Copy out the headermap from test/Preprocessor/Inputs/headermap-rel and avoid
-// adding another binary format to the repository.
-
// RUN: rm -rf %t
-// RUN: mkdir -p %t/m
-// RUN: cp -a %S/../Preprocessor/Inputs/headermap-rel %t/i
+// RUN: mkdir -p %t/m %t/i/Foo.framework/Headers
// RUN: echo '// Foo.h' > %t/i/Foo.framework/Headers/Foo.h
+// RUN: %hmaptool write %S/../Preprocessor/Inputs/headermap-rel/foo.hmap.json %t/i/foo.hmap
// RUN: not env FORCE_CLANG_DIAGNOSTICS_CRASH= TMPDIR=%t TEMP=%t TMP=%t \
// RUN: %clang -fsyntax-only -fmodules -fmodules-cache-path=%t/m %s \
diff --git a/test/Modules/crash-vfs-path-emptydir-entries.m b/test/Modules/crash-vfs-path-emptydir-entries.m
index d96adbbf99ba..a50ea869f476 100644
--- a/test/Modules/crash-vfs-path-emptydir-entries.m
+++ b/test/Modules/crash-vfs-path-emptydir-entries.m
@@ -8,7 +8,7 @@
// RUN: rm -rf %t
// RUN: mkdir -p %t/i %t/m %t %t/sysroot
-// RUN: cp -a %S/Inputs/crash-recovery/usr %t/i/
+// RUN: cp -R %S/Inputs/crash-recovery/usr %t/i/
// RUN: not env FORCE_CLANG_DIAGNOSTICS_CRASH= TMPDIR=%t TEMP=%t TMP=%t \
// RUN: %clang -fsyntax-only %s -I %/t/i -isysroot %/t/sysroot/ \
diff --git a/test/Modules/crash-vfs-path-symlink-component.m b/test/Modules/crash-vfs-path-symlink-component.m
index 4723a77c7e93..565a64fb5c23 100644
--- a/test/Modules/crash-vfs-path-symlink-component.m
+++ b/test/Modules/crash-vfs-path-symlink-component.m
@@ -8,7 +8,7 @@
// RUN: rm -rf %t
// RUN: mkdir -p %t/i %t/m %t %t/sysroot
-// RUN: cp -a %S/Inputs/crash-recovery/usr %t/i/
+// RUN: cp -R %S/Inputs/crash-recovery/usr %t/i/
// RUN: ln -s include/tcl-private %t/i/usr/x
// RUN: not env FORCE_CLANG_DIAGNOSTICS_CRASH= TMPDIR=%t TEMP=%t TMP=%t \
diff --git a/test/Modules/crash-vfs-path-symlink-topheader.m b/test/Modules/crash-vfs-path-symlink-topheader.m
index 8e0c2d4c9226..fea1f01c02ae 100644
--- a/test/Modules/crash-vfs-path-symlink-topheader.m
+++ b/test/Modules/crash-vfs-path-symlink-topheader.m
@@ -8,7 +8,7 @@
// RUN: rm -rf %t
// RUN: mkdir -p %t/i %t/m %t %t/sysroot
-// RUN: cp -a %S/Inputs/crash-recovery/usr %t/i/
+// RUN: cp -R %S/Inputs/crash-recovery/usr %t/i/
// RUN: rm -f %t/i/usr/include/pthread_impl.h
// RUN: ln -s pthread/pthread_impl.h %t/i/usr/include/pthread_impl.h
diff --git a/test/Modules/crash-vfs-umbrella-frameworks.m b/test/Modules/crash-vfs-umbrella-frameworks.m
index 0c3981ddaa88..a18acf576ea3 100644
--- a/test/Modules/crash-vfs-umbrella-frameworks.m
+++ b/test/Modules/crash-vfs-umbrella-frameworks.m
@@ -5,7 +5,7 @@
// RUN: rm -rf %t
// RUN: mkdir -p %t/i %t/m %t
-// RUN: cp -a %S/Inputs/crash-recovery/Frameworks %t/i/
+// RUN: cp -R %S/Inputs/crash-recovery/Frameworks %t/i/
// RUN: mkdir -p %t/i/Frameworks/A.framework/Frameworks
// RUN: ln -s ../../B.framework %t/i/Frameworks/A.framework/Frameworks/B.framework
diff --git a/test/Modules/cxx-dtor.cpp b/test/Modules/cxx-dtor.cpp
index 63427ee0afda..d685b69d511a 100644
--- a/test/Modules/cxx-dtor.cpp
+++ b/test/Modules/cxx-dtor.cpp
@@ -1,3 +1,4 @@
// RUN: rm -rf %t
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -x c++ -std=c++11 -fmodules-cache-path=%t -I %S/Inputs/cxx-dtor -emit-llvm-only %s
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -x c++ -std=c++11 -fmodules-cache-path=%t -I %S/Inputs/cxx-dtor -emit-llvm-only %s -triple i686-windows
#include "b.h"
diff --git a/test/Modules/cxx-irgen.cpp b/test/Modules/cxx-irgen.cpp
index 6cc32adc5254..01e4384ac596 100644
--- a/test/Modules/cxx-irgen.cpp
+++ b/test/Modules/cxx-irgen.cpp
@@ -12,15 +12,15 @@ CtorInit<int> x;
// Keep these two namespace definitions separate; merging them hides the bug.
namespace EmitInlineMethods {
- // CHECK-DAG: define linkonce_odr [[CC:([0-9_a-z]*cc[ ]+)?]]void @_ZN17EmitInlineMethods1C1fEPNS_1AE(
- // CHECK-DAG: declare [[CC]]void @_ZN17EmitInlineMethods1A1gEv(
+ // CHECK-DAG: define linkonce_odr {{(dso_local )?}}[[CC:([0-9_a-z]*cc[ ]+)?]]void @_ZN17EmitInlineMethods1C1fEPNS_1AE(
+ // CHECK-DAG: declare {{(dso_local )?}}[[CC]]void @_ZN17EmitInlineMethods1A1gEv(
struct C {
__attribute__((used)) void f(A *p) { p->g(); }
};
}
namespace EmitInlineMethods {
- // CHECK-DAG: define linkonce_odr [[CC]]void @_ZN17EmitInlineMethods1D1fEPNS_1BE(
- // CHECK-DAG: define linkonce_odr [[CC]]void @_ZN17EmitInlineMethods1B1gEv(
+ // CHECK-DAG: define linkonce_odr {{(dso_local )?}}[[CC]]void @_ZN17EmitInlineMethods1D1fEPNS_1BE(
+ // CHECK-DAG: define linkonce_odr {{(dso_local )?}}[[CC]]void @_ZN17EmitInlineMethods1B1gEv(
struct D {
__attribute__((used)) void f(B *p) { p->g(); }
};
diff --git a/test/Modules/cxx17-exception-spec.cpp b/test/Modules/cxx17-exception-spec.cpp
new file mode 100644
index 000000000000..ba7be0e30d9c
--- /dev/null
+++ b/test/Modules/cxx17-exception-spec.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -fmodules -fmodules-local-submodule-visibility -fno-modules-error-recovery -fno-spell-checking -verify -std=c++17 %s
+
+#pragma clang module build a
+module a {}
+#pragma clang module contents
+#pragma clang module begin a
+constexpr bool return_true() { return true; }
+struct X {
+ static void f() noexcept(return_true());
+};
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module build b
+module b {}
+#pragma clang module contents
+#pragma clang module begin b
+#pragma clang module import a
+using T = decltype(return_true() && noexcept(X::f()));
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module import a
+#pragma clang module import b
+
+// Trigger import of return_true and then X::f in the same pass. This causes
+// the type of X::f to be loaded while we have a pending body for return_true,
+// which means evaluation of its exception specification at that point would
+// fail.
+T t;
+
+static_assert(noexcept(X().f()));
+
+// expected-no-diagnostics
diff --git a/test/Modules/diag-flags.cpp b/test/Modules/diag-flags.cpp
index ada90d24b791..14067c63fe4f 100644
--- a/test/Modules/diag-flags.cpp
+++ b/test/Modules/diag-flags.cpp
@@ -3,24 +3,24 @@
// For an implicit module, all that matters are the warning flags in the user.
// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -emit-module -fmodules-cache-path=%t -fmodule-name=diag_flags -x c++ %S/Inputs/module.map -fmodules-ts
// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts
-// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -DWARNING -Wpadded
-// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -DERROR -Wpadded -Werror
-// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -DERROR -Werror=padded
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -DWARNING -DLOCAL_WARNING -Wpadded
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -DERROR -DLOCAL_ERROR -Wpadded -Werror
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -DERROR -DLOCAL_ERROR -Werror=padded
//
// For an explicit module, all that matters are the warning flags in the module build.
// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -emit-module -fmodule-name=diag_flags -x c++ %S/Inputs/module.map -fmodules-ts -o %t/nodiag.pcm
-// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -fmodule-file=%t/nodiag.pcm -Wpadded
-// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -fmodule-file=%t/nodiag.pcm -Werror -Wpadded
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -fmodule-file=%t/nodiag.pcm -Wpadded -DLOCAL_WARNING
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -fmodule-file=%t/nodiag.pcm -Werror -Wpadded -DLOCAL_ERROR
//
// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -emit-module -fmodule-name=diag_flags -x c++ %S/Inputs/module.map -fmodules-ts -o %t/warning.pcm -Wpadded
// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -DWARNING -fmodule-file=%t/warning.pcm
-// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -DWARNING -fmodule-file=%t/warning.pcm -Werror=padded
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -DWARNING -fmodule-file=%t/warning.pcm -Werror=padded -DLOCAL_ERROR
// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -DWARNING -fmodule-file=%t/warning.pcm -Werror
//
// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -emit-module -fmodule-name=diag_flags -x c++ %S/Inputs/module.map -fmodules-ts -o %t/werror-no-error.pcm -Werror -Wpadded -Wno-error=padded
// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -DWARNING -fmodule-file=%t/werror-no-error.pcm
// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -DWARNING -fmodule-file=%t/werror-no-error.pcm -Wno-padded
-// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -DWARNING -fmodule-file=%t/werror-no-error.pcm -Werror=padded
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -DWARNING -fmodule-file=%t/werror-no-error.pcm -Werror=padded -DLOCAL_ERROR
//
// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -emit-module -fmodule-name=diag_flags -x c++ %S/Inputs/module.map -fmodules-ts -o %t/error.pcm -Werror=padded
// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -DERROR -fmodule-file=%t/error.pcm -Wno-padded
@@ -35,10 +35,22 @@ import diag_flags;
// Diagnostic flags from the module user make no difference to diagnostics
// emitted within the module when using an explicitly-loaded module.
#if ERROR
-// expected-error@diag_flags.h:14 {{padding struct}}
+// expected-error@diag_flags.h:4 {{padding struct}}
#elif WARNING
-// expected-warning@diag_flags.h:14 {{padding struct}}
-#else
-// expected-no-diagnostics
+// expected-warning@diag_flags.h:4 {{padding struct}}
#endif
int arr[sizeof(Padded)];
+
+// Diagnostic flags from the module make no difference to diagnostics emitted
+// in the module user.
+#if LOCAL_ERROR
+// expected-error@+4 {{padding struct}}
+#elif LOCAL_WARNING
+// expected-warning@+2 {{padding struct}}
+#endif
+struct Padded2 { char x; int y; };
+int arr2[sizeof(Padded2)];
+
+#if !ERROR && !WARNING && !LOCAL_ERROR && !LOCAL_WARNING
+// expected-no-diagnostics
+#endif
diff --git a/test/Modules/double-quotes.m b/test/Modules/double-quotes.m
new file mode 100644
index 000000000000..a21f12fa5e5a
--- /dev/null
+++ b/test/Modules/double-quotes.m
@@ -0,0 +1,39 @@
+// REQUIRES: shell
+
+// RUN: rm -rf %t
+// RUN: mkdir %t
+
+// RUN: %hmaptool write %S/Inputs/double-quotes/a.hmap.json %t/a.hmap
+// RUN: %hmaptool write %S/Inputs/double-quotes/x.hmap.json %t/x.hmap
+
+// RUN: sed -e "s:TEST_DIR:%S/Inputs/double-quotes:g" \
+// RUN: %S/Inputs/double-quotes/z.yaml > %t/z.yaml
+
+// The output with and without modules should be the same
+
+// RUN: %clang_cc1 \
+// RUN: -I %t/x.hmap -iquote %t/a.hmap -ivfsoverlay %t/z.yaml \
+// RUN: -F%S/Inputs/double-quotes -I%S/Inputs/double-quotes \
+// RUN: -Wquoted-include-in-framework-header -fsyntax-only %s -verify
+
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache \
+// RUN: -I %t/x.hmap -iquote %t/a.hmap -ivfsoverlay %t/z.yaml \
+// RUN: -F%S/Inputs/double-quotes -I%S/Inputs/double-quotes \
+// RUN: -Wquoted-include-in-framework-header -fsyntax-only %s \
+// RUN: 2>%t/stderr
+
+// The same warnings show up when modules is on but -verify doesn't get it
+// because they only show up under the module A building context.
+// RUN: FileCheck --input-file=%t/stderr %s
+// CHECK: double-quoted include "A0.h" in framework header, expected angle-bracketed instead
+// CHECK: double-quoted include "B.h" in framework header, expected angle-bracketed instead
+// CHECK: double-quoted include "B.h" in framework header, expected angle-bracketed instead
+
+#import "A.h"
+#import <Z/Z.h>
+
+int bar() { return foo(); }
+
+// expected-warning@Inputs/double-quotes/A.framework/Headers/A.h:1{{double-quoted include "A0.h" in framework header, expected angle-bracketed instead}}
+// expected-warning@Inputs/double-quotes/A.framework/Headers/A.h:2{{double-quoted include "B.h" in framework header, expected angle-bracketed instead}}
+// expected-warning@Inputs/double-quotes/flat-header-path/Z.h:1{{double-quoted include "B.h" in framework header, expected angle-bracketed instead}}
diff --git a/test/Modules/framework-public-includes-private.m b/test/Modules/framework-public-includes-private.m
new file mode 100644
index 000000000000..eb4d2877a1cd
--- /dev/null
+++ b/test/Modules/framework-public-includes-private.m
@@ -0,0 +1,37 @@
+// REQUIRES: shell
+
+// RUN: rm -rf %t
+// RUN: mkdir %t
+
+// RUN: %hmaptool write %S/Inputs/framework-public-includes-private/a.hmap.json %t/a.hmap
+// RUN: %hmaptool write %S/Inputs/framework-public-includes-private/z.hmap.json %t/z.hmap
+
+// RUN: sed -e "s:TEST_DIR:%S/Inputs/framework-public-includes-private:g" \
+// RUN: %S/Inputs/framework-public-includes-private/z.yaml > %t/z.yaml
+
+// The output with and without modules should be the same, without modules first.
+// RUN: %clang_cc1 \
+// RUN: -iquote %t/z.hmap -iquote %t/a.hmap -ivfsoverlay %t/z.yaml \
+// RUN: -F%S/Inputs/framework-public-includes-private \
+// RUN: -fsyntax-only %s -verify
+
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache \
+// RUN: -iquote %t/z.hmap -iquote %t/a.hmap -ivfsoverlay %t/z.yaml \
+// RUN: -F%S/Inputs/framework-public-includes-private \
+// RUN: -fsyntax-only %s \
+// RUN: 2>%t/stderr
+
+// The same warnings show up when modules is on but -verify doesn't get it
+// because they only show up under the module A building context.
+// RUN: FileCheck --input-file=%t/stderr %s
+// CHECK: public framework header includes private framework header 'A/APriv.h'
+// CHECK: public framework header includes private framework header 'A/APriv2.h'
+// CHECK: public framework header includes private framework header 'Z/ZPriv.h'
+
+#import "A.h"
+
+int bar() { return foo(); }
+
+// expected-warning@Inputs/framework-public-includes-private/A.framework/Headers/A.h:1{{public framework header includes private framework header 'A/APriv.h'}}
+// expected-warning@Inputs/framework-public-includes-private/A.framework/Headers/A.h:2{{public framework header includes private framework header 'A/APriv2.h'}}
+// expected-warning@Inputs/framework-public-includes-private/flat-header-path/Z.h:2{{public framework header includes private framework header 'Z/ZPriv.h'}}
diff --git a/test/Modules/friend-definition-2.cpp b/test/Modules/friend-definition-2.cpp
new file mode 100644
index 000000000000..b226b5c0d1e5
--- /dev/null
+++ b/test/Modules/friend-definition-2.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -fmodules %s -verify
+// RUN: %clang_cc1 -fmodules %s -verify -triple i686-windows
+// expected-no-diagnostics
+#pragma clang module build A
+module A {}
+#pragma clang module contents
+#pragma clang module begin A
+template<typename T> struct ct { friend auto operator-(ct, ct) { struct X {}; return X(); } void x(); };
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module build B
+module B {}
+#pragma clang module contents
+#pragma clang module begin B
+template<typename T> struct ct { friend auto operator-(ct, ct) { struct X{}; return X(); } void x(); };
+inline auto f() { return ct<float>() - ct<float>(); }
+#pragma clang module end
+#pragma clang module endbuild
+
+// Force the definition of ct in module A to be the primary definition.
+#pragma clang module import A
+template<typename T> void ct<T>::x() {}
+
+// Attempt to cause the definition of operator- in the ct primary template in
+// module B to be the primary definition of that function. If that happens,
+// we'll be left with a class template ct that appears to not contain a
+// definition of the inline friend function.
+#pragma clang module import B
+auto v = f();
+
+ct<int> make();
+void h() {
+ make() - make();
+}
diff --git a/test/Modules/friend-definition.cpp b/test/Modules/friend-definition.cpp
new file mode 100644
index 000000000000..8588cbd9c6f4
--- /dev/null
+++ b/test/Modules/friend-definition.cpp
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -fmodules -std=c++14 %s -verify
+// expected-no-diagnostics
+
+#pragma clang module build A
+module A {}
+#pragma clang module contents
+#pragma clang module begin A
+template<typename T> struct A {
+ friend A operator+(const A&, const A&) { return {}; }
+};
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module build B
+module B {}
+#pragma clang module contents
+#pragma clang module begin B
+#pragma clang module import A
+inline void f() { A<int> a; }
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module build C
+module C {}
+#pragma clang module contents
+#pragma clang module begin C
+#pragma clang module import A
+inline void g() { A<int> a; }
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module import A
+#pragma clang module import B
+#pragma clang module import C
+
+void h() {
+ A<int> a;
+ a + a;
+}
diff --git a/test/Modules/implicit-private-with-submodule.m b/test/Modules/implicit-private-with-submodule.m
index 1779341a5f6b..d5f23456bf88 100644
--- a/test/Modules/implicit-private-with-submodule.m
+++ b/test/Modules/implicit-private-with-submodule.m
@@ -13,7 +13,16 @@
// expected-warning@Inputs/implicit-private-with-submodule/A.framework/Modules/module.private.modulemap:1{{private submodule 'A.Private' in private module map, expected top-level module}}
// expected-note@Inputs/implicit-private-with-submodule/A.framework/Modules/module.private.modulemap:1{{rename 'A.Private' to ensure it can be found by name}}
-// CHECK: fix-it:"{{.*}}module.private.modulemap":{1:20-1:27}:"A_Private"
+
+// expected-warning@Inputs/implicit-private-with-submodule/A.framework/Modules/module.private.modulemap:6{{private submodule 'B.Private' in private module map, expected top-level module}}
+// expected-note@Inputs/implicit-private-with-submodule/A.framework/Modules/module.private.modulemap:6{{rename 'B.Private' to ensure it can be found by name}}
+
+// expected-warning@Inputs/implicit-private-with-submodule/A.framework/Modules/module.private.modulemap:9{{private submodule 'C.Private' in private module map, expected top-level module}}
+// expected-note@Inputs/implicit-private-with-submodule/A.framework/Modules/module.private.modulemap:9{{rename 'C.Private' to ensure it can be found by name}}
+
+// CHECK: fix-it:"{{.*}}module.private.modulemap":{1:1-1:27}:"framework module A_Private"
+// CHECK: fix-it:"{{.*}}module.private.modulemap":{6:1-6:26}:"framework module B_Private"
+// CHECK: fix-it:"{{.*}}module.private.modulemap":{9:1-9:36}:"framework module C_Private"
#ifndef HEADER
#define HEADER
diff --git a/test/Modules/incomplete-framework-module.m b/test/Modules/incomplete-framework-module.m
new file mode 100644
index 000000000000..9034c1aab921
--- /dev/null
+++ b/test/Modules/incomplete-framework-module.m
@@ -0,0 +1,11 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t \
+// RUN: -F%S/Inputs/incomplete-framework-module \
+// RUN: -fsyntax-only %s -verify
+
+#import <Foo/Foo.h>
+
+// expected-warning@Inputs/incomplete-framework-module/Foo.framework/Modules/module.modulemap:2{{skipping 'Foo.h' because module declaration}}
+// expected-warning@Inputs/incomplete-framework-module/Foo.framework/Modules/module.modulemap:3{{skipping 'FooB.h' because module declaration}}
+// expected-note@Inputs/incomplete-framework-module/Foo.framework/Modules/module.modulemap:1{{use 'framework module' to declare module 'Foo'}}
+// expected-note@Inputs/incomplete-framework-module/Foo.framework/Modules/module.modulemap:1{{use 'framework module' to declare module 'Foo'}}
diff --git a/test/Modules/local-visibility.cpp b/test/Modules/local-visibility.cpp
new file mode 100644
index 000000000000..fa2d20c43361
--- /dev/null
+++ b/test/Modules/local-visibility.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -fmodules %s -verify
+// RUN: %clang_cc1 -fsyntax-only %s -verify
+
+// expected-no-diagnostics
+template <typename Var>
+struct S {
+ template <unsigned N>
+ struct Inner { };
+
+ template <>
+ struct Inner<0> { };
+};
+
+S<int>::Inner<1> I1;
+S<int>::Inner<0> I0;
diff --git a/test/Modules/merge-deduced-return.cpp b/test/Modules/merge-deduced-return.cpp
new file mode 100644
index 000000000000..0a4de7b97554
--- /dev/null
+++ b/test/Modules/merge-deduced-return.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -fmodules -std=c++17 -verify %s
+// RUN: %clang_cc1 -fmodules -std=c++17 -verify %s -DLOCAL
+// expected-no-diagnostics
+
+#pragma clang module build A
+module A {}
+#pragma clang module contents
+#pragma clang module begin A
+inline auto f() { struct X {}; return X(); }
+inline auto a = f();
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module build B
+module B {}
+#pragma clang module contents
+#pragma clang module begin B
+inline auto f() { struct X {}; return X(); }
+inline auto b = f();
+#pragma clang module end
+#pragma clang module endbuild
+
+#ifdef LOCAL
+inline auto f() { struct X {}; return X(); }
+inline auto b = f();
+#else
+#pragma clang module import B
+#endif
+
+#pragma clang module import A
+
+using T = decltype(a);
+using T = decltype(b);
diff --git a/test/Modules/merge-lambdas.cpp b/test/Modules/merge-lambdas.cpp
new file mode 100644
index 000000000000..d14483aa3aa7
--- /dev/null
+++ b/test/Modules/merge-lambdas.cpp
@@ -0,0 +1,48 @@
+// RUN: %clang_cc1 -fmodules -verify %s
+// expected-no-diagnostics
+
+#pragma clang module build A
+module A {}
+#pragma clang module contents
+#pragma clang module begin A
+template<typename T> auto f() { return []{}; }
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module build B
+module B {}
+#pragma clang module contents
+#pragma clang module begin B
+#pragma clang module import A
+inline auto x1() { return f<int>(); }
+inline auto z() { return []{}; }
+inline auto x2() { return z(); }
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module build C
+module C {}
+#pragma clang module contents
+#pragma clang module begin C
+#pragma clang module import A
+inline auto y1() { return f<int>(); }
+inline auto z() { return []{}; }
+inline auto y2() { return z(); }
+inline auto q() { return []{}; }
+inline auto y3() { return q(); }
+#pragma clang module end
+#pragma clang module endbuild
+
+inline auto q() { return []{}; }
+inline auto x3() { return q(); }
+
+#pragma clang module import B
+#pragma clang module import C
+using T = decltype(x1);
+using T = decltype(y1);
+
+using U = decltype(x2);
+using U = decltype(y2);
+
+using V = decltype(x3);
+using V = decltype(y3);
diff --git a/test/Modules/merge-static-locals.cpp b/test/Modules/merge-static-locals.cpp
new file mode 100644
index 000000000000..37ae22ee38a3
--- /dev/null
+++ b/test/Modules/merge-static-locals.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -std=c++17 -fmodules -verify %s
+// expected-no-diagnostics
+
+#pragma clang module build A
+module A {}
+#pragma clang module contents
+#pragma clang module begin A
+template<int*> struct X {};
+auto get() { static int n; return X<&n>(); }
+using A = decltype(get());
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module build B
+module B {}
+#pragma clang module contents
+#pragma clang module begin B
+template<int*> struct X {};
+auto get() { static int n; return X<&n>(); }
+using B = decltype(get());
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module import A
+#pragma clang module import B
+using T = A;
+using T = B;
diff --git a/test/Modules/merge-target-features.cpp b/test/Modules/merge-target-features.cpp
index 9ca0539e6a22..6a29c2db8a8d 100644
--- a/test/Modules/merge-target-features.cpp
+++ b/test/Modules/merge-target-features.cpp
@@ -19,10 +19,9 @@
// RUN: -triple i386-unknown-unknown \
// RUN: -target-cpu i386 \
// RUN: -fsyntax-only merge-target-features.cpp 2>&1 \
-// RUN: | FileCheck --check-prefix=SUBSET %s
-// SUBSET-NOT: error:
+// RUN: | FileCheck --check-prefix=SUBSET --implicit-check-not=error: %s
+// SUBSET: error: AST file was compiled with the target feature '+sse2' but the current translation unit is not
// SUBSET: error: {{.*}} configuration mismatch
-// SUBSET-NOT: error:
//
// RUN: %clang_cc1 -fmodules -x c++ -fmodules-cache-path=%t \
// RUN: -iquote Inputs/merge-target-features \
@@ -57,10 +56,10 @@
// RUN: -triple i386-unknown-unknown \
// RUN: -target-cpu i386 -target-feature +cx16 \
// RUN: -fsyntax-only merge-target-features.cpp 2>&1 \
-// RUN: | FileCheck --check-prefix=MISMATCH %s
-// MISMATCH-NOT: error:
+// RUN: | FileCheck --check-prefix=MISMATCH --implicit-check-not=error: %s
+// MISMATCH: error: AST file was compiled with the target feature '+sse2' but the current translation unit is not
+// MISMATCH: error: current translation unit is compiled with the target feature '+cx16' but the AST file was not
// MISMATCH: error: {{.*}} configuration mismatch
-// MISMATCH-NOT: error:
#include "foo.h"
diff --git a/test/Modules/modify-module.m b/test/Modules/modify-module.m
index f9a70b25c877..d59a4799104f 100644
--- a/test/Modules/modify-module.m
+++ b/test/Modules/modify-module.m
@@ -3,9 +3,9 @@
// RUN: rm -rf %t
// RUN: mkdir -p %t/include
-// RUN: cp %S/Inputs/Modified/A.h %t/include
-// RUN: cp %S/Inputs/Modified/B.h %t/include
-// RUN: cp %S/Inputs/Modified/module.map %t/include
+// RUN: cat %S/Inputs/Modified/A.h > %t/include/A.h
+// RUN: cat %S/Inputs/Modified/B.h > %t/include/B.h
+// RUN: cat %S/Inputs/Modified/module.map > %t/include/module.map
// RUN: %clang_cc1 -fdisable-module-hash -fmodules-cache-path=%t/cache -fmodules -fimplicit-module-maps -I %t/include %s -verify
// RUN: echo '' >> %t/include/B.h
// RUN: %clang_cc1 -fdisable-module-hash -fmodules-cache-path=%t/cache -fmodules -fimplicit-module-maps -I %t/include %s -verify
diff --git a/test/Modules/module-imported-by-pch-with-modulemap.m b/test/Modules/module-imported-by-pch-with-modulemap.m
new file mode 100644
index 000000000000..493034118ad0
--- /dev/null
+++ b/test/Modules/module-imported-by-pch-with-modulemap.m
@@ -0,0 +1,16 @@
+// RUN: rm -rf %t.dst %t.cache
+// RUN: mkdir -p %t.dst/folder-with-modulemap %t.dst/pch-folder
+// RUN: echo '#import "folder-with-modulemap/included.h"' > %t.dst/header.h
+// RUN: echo 'extern int MyModuleVersion;' > %t.dst/folder-with-modulemap/MyModule.h
+// RUN: echo '@import MyModule;' > %t.dst/folder-with-modulemap/included.h
+// RUN: echo 'module MyModule { header "MyModule.h" }' > %t.dst/folder-with-modulemap/MyModule.modulemap
+
+// RUN: %clang_cc1 -emit-pch -o %t.dst/pch-folder/header.pch -fmodule-map-file=%t.dst/folder-with-modulemap/MyModule.modulemap -x objective-c-header -fmodules-cache-path=%t.cache -fmodules -fimplicit-module-maps %t.dst/header.h
+// RUN: %clang_cc1 -fsyntax-only -fmodule-map-file=%t.dst/folder-with-modulemap/MyModule.modulemap -fmodules-cache-path=%t.cache -fmodules -fimplicit-module-maps %s -include-pch %t.dst/pch-folder/header.pch -verify
+
+// expected-no-diagnostics
+
+void test() {
+ (void)MyModuleVersion; // should be found by implicit import
+}
+
diff --git a/test/Modules/module-name-private.m b/test/Modules/module-name-private.m
new file mode 100644
index 000000000000..33bd3c107580
--- /dev/null
+++ b/test/Modules/module-name-private.m
@@ -0,0 +1,12 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -verify -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-canonical -fsyntax-only %s -Wprivate-module -fmodule-name=A -Rmodule-build
+
+// Because of -fmodule-name=A, no module (A or A_Private) is supposed to be
+// built and -Rmodule-build should not produce any output.
+
+// expected-no-diagnostics
+
+#import <A/a.h>
+#import <A/aprivate.h>
+
+int foo() { return APRIVATE; }
diff --git a/test/Modules/module_file_info.m b/test/Modules/module_file_info.m
index f2967be6f8ca..05d401b9450a 100644
--- a/test/Modules/module_file_info.m
+++ b/test/Modules/module_file_info.m
@@ -43,6 +43,16 @@
// CHECK: Predefined macros:
// CHECK: -DBLARG
// CHECK: -DWIBBLE=WOBBLE
+// CHECK: Input file: {{.*}}DependsOnModulePrivate.h
+// CHECK-NEXT: Input file: {{.*}}Other.h
+// CHECK-NEXT: Input file: {{.*}}SubFramework.h
+// CHECK-NEXT: Input file: {{.*}}not_coroutines.h
+// CHECK-NEXT: Input file: {{.*}}not_cxx.h
+// CHECK-NEXT: Input file: {{.*}}other.h
+// CHECK-NEXT: Input file: {{.*}}module.map
+// CHECK-NEXT: Input file: {{.*}}DependsOnModule.h
+// CHECK-NEXT: Input file: {{.*}}module_private.map
+// CHECK-NEXT: Input file: {{.*}}module.map
// CHECK: Diagnostic options:
// CHECK: IgnoreWarnings: Yes
diff --git a/test/Modules/new-delete.cpp b/test/Modules/new-delete.cpp
new file mode 100644
index 000000000000..585a242b2247
--- /dev/null
+++ b/test/Modules/new-delete.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -fmodules -verify %s
+// expected-no-diagnostics
+
+#pragma clang module build M
+module M {}
+#pragma clang module contents
+#pragma clang module begin M
+struct A {
+ A();
+ ~A() { delete p; } // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'}}
+ int *p;
+};
+inline A::A() : p(new int[32]) {} // expected-note {{allocated}}
+struct B {
+ B();
+ ~B() { delete p; }
+ int *p;
+};
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module import M
+B::B() : p(new int[32]) {}
diff --git a/test/Modules/non-ambiguous-enum.m b/test/Modules/non-ambiguous-enum.m
new file mode 100644
index 000000000000..3400b7aec3e6
--- /dev/null
+++ b/test/Modules/non-ambiguous-enum.m
@@ -0,0 +1,10 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F%S/Inputs/non-ambiguous-enum -fsyntax-only %s -verify
+#import <B/b.h>
+#import <A/a.h>
+
+// expected-no-diagnostics
+
+int foo() {
+ return MyEnumCst;
+}
diff --git a/test/Modules/odr_hash-Friend.cpp b/test/Modules/odr_hash-Friend.cpp
new file mode 100644
index 000000000000..8a2513e2f9cd
--- /dev/null
+++ b/test/Modules/odr_hash-Friend.cpp
@@ -0,0 +1,90 @@
+// RUN: rm -rf %t
+
+// PR35939: MicrosoftMangle.cpp triggers an assertion failure on this test.
+// UNSUPPORTED: system-windows
+
+// RUN: %clang_cc1 \
+// RUN: -I %S/Inputs/odr_hash-Friend \
+// RUN: -emit-obj -o /dev/null \
+// RUN: -fmodules \
+// RUN: -fimplicit-module-maps \
+// RUN: -fmodules-cache-path=%t/modules.cache \
+// RUN: -std=c++11 -x c++ %s -verify -DTEST1 -fcolor-diagnostics
+
+// RUN: %clang_cc1 \
+// RUN: -I %S/Inputs/odr_hash-Friend \
+// RUN: -emit-obj -o /dev/null \
+// RUN: -fmodules \
+// RUN: -fimplicit-module-maps \
+// RUN: -fmodules-cache-path=%t/modules.cache \
+// RUN: -std=c++11 -x c++ %s -verify -DTEST2 -fcolor-diagnostics
+
+// RUN: %clang_cc1 \
+// RUN: -I %S/Inputs/odr_hash-Friend \
+// RUN: -emit-obj -o /dev/null \
+// RUN: -fmodules \
+// RUN: -fimplicit-module-maps \
+// RUN: -fmodules-cache-path=%t/modules.cache \
+// RUN: -std=c++11 -x c++ %s -verify -DTEST3 -fcolor-diagnostics
+
+// RUN: %clang_cc1 \
+// RUN: -I %S/Inputs/odr_hash-Friend \
+// RUN: -emit-obj -o /dev/null \
+// RUN: -fmodules \
+// RUN: -fimplicit-module-maps \
+// RUN: -fmodules-cache-path=%t/modules.cache \
+// RUN: -std=c++11 -x c++ %s -verify -DTEST3 -fcolor-diagnostics
+
+// RUN: %clang_cc1 \
+// RUN: -I %S/Inputs/odr_hash-Friend \
+// RUN: -emit-obj -o /dev/null \
+// RUN: -fmodules \
+// RUN: -fimplicit-module-maps \
+// RUN: -fmodules-cache-path=%t/modules.cache \
+// RUN: -std=c++11 -x c++ %s -verify -DTEST3 -fcolor-diagnostics
+
+#if defined(TEST1)
+#include "Box.h"
+#include "M1.h"
+#include "M3.h"
+// expected-no-diagnostics
+#endif
+
+#if defined(TEST2)
+#include "Box.h"
+#include "M1.h"
+#include "M3.h"
+#include "Good.h"
+// expected-no-diagnostics
+#endif
+
+#if defined(TEST3)
+#include "Good.h"
+#include "Box.h"
+#include "M1.h"
+#include "M3.h"
+// expected-no-diagnostics
+#endif
+
+#if defined(TEST4)
+#include "Box.h"
+#include "M1.h"
+#include "M3.h"
+#include "Bad.h"
+// expected-error@Bad.h:* {{'Check' has different definitions in different modules; definition in module 'Bad' first difference is function body}}
+// expected-note@Box.h:* {{but in 'Box' found a different body}}
+#endif
+
+#if defined(TEST5)
+#include "Bad.h"
+#include "Box.h"
+#include "M1.h"
+#include "M3.h"
+// expected-error@Bad.h:* {{'Check' has different definitions in different modules; definition in module 'Bad' first difference is function body}}
+// expected-note@Box.h:* {{but in 'Box' found a different body}}
+#endif
+
+
+void Run() {
+ Box<> Present;
+}
diff --git a/test/Modules/odr_hash-Unresolved.cpp b/test/Modules/odr_hash-Unresolved.cpp
new file mode 100644
index 000000000000..0c73b50f7085
--- /dev/null
+++ b/test/Modules/odr_hash-Unresolved.cpp
@@ -0,0 +1,14 @@
+// RUN: rm -rf %t
+
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t/modules.cache \
+// RUN: -I %S/Inputs/odr_hash-Unresolved \
+// RUN: -fmodules \
+// RUN: -fimplicit-module-maps \
+// RUN: -fmodules-cache-path=%t/modules.cache \
+// RUN: -fmodules-local-submodule-visibility \
+// RUN: -std=c++11 -x c++ %s -fsyntax-only
+
+// Note: There is no -verify in the run line because some error messages are
+// not captured from the module building stage.
+
+#include "Module2/include.h"
diff --git a/test/Modules/odr_hash-blocks.cpp b/test/Modules/odr_hash-blocks.cpp
new file mode 100644
index 000000000000..07dfa4ce2ac8
--- /dev/null
+++ b/test/Modules/odr_hash-blocks.cpp
@@ -0,0 +1,119 @@
+// Clear and create directories
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: mkdir %t/cache
+// RUN: mkdir %t/Inputs
+
+// Build first header file
+// RUN: echo "#define FIRST" >> %t/Inputs/first.h
+// RUN: cat %s >> %t/Inputs/first.h
+
+// Build second header file
+// RUN: echo "#define SECOND" >> %t/Inputs/second.h
+// RUN: cat %s >> %t/Inputs/second.h
+
+// Test that each header can compile
+// RUN: %clang_cc1 -fsyntax-only -x c++ -std=c++11 -fblocks %t/Inputs/first.h
+// RUN: %clang_cc1 -fsyntax-only -x c++ -std=c++11 -fblocks %t/Inputs/second.h
+
+// Build module map file
+// RUN: echo "module FirstModule {" >> %t/Inputs/module.map
+// RUN: echo " header \"first.h\"" >> %t/Inputs/module.map
+// RUN: echo "}" >> %t/Inputs/module.map
+// RUN: echo "module SecondModule {" >> %t/Inputs/module.map
+// RUN: echo " header \"second.h\"" >> %t/Inputs/module.map
+// RUN: echo "}" >> %t/Inputs/module.map
+
+// Run test
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps \
+// RUN: -fmodules-cache-path=%t/cache -x c++ -I%t/Inputs \
+// RUN: -verify %s -std=c++11 -fblocks
+
+#if !defined(FIRST) && !defined(SECOND)
+#include "first.h"
+#include "second.h"
+#endif
+
+// Used for testing
+#if defined(FIRST)
+#define ACCESS public:
+#elif defined(SECOND)
+#define ACCESS private:
+#endif
+
+// TODO: S1, S2, and S3 should generate errors.
+namespace Blocks {
+#if defined(FIRST)
+struct S1 {
+ void (^block)(int x) = ^(int x) { };
+};
+#elif defined(SECOND)
+struct S1 {
+ void (^block)(int x) = ^(int y) { };
+};
+#else
+S1 s1;
+#endif
+
+#if defined(FIRST)
+struct S2 {
+ int (^block)(int x) = ^(int x) { return x + 1; };
+};
+#elif defined(SECOND)
+struct S2 {
+ int (^block)(int x) = ^(int x) { return x; };
+};
+#else
+S2 s2;
+#endif
+
+#if defined(FIRST)
+struct S3 {
+ void run(int (^block)(int x));
+};
+#elif defined(SECOND)
+struct S3 {
+ void run(int (^block)(int x, int y));
+};
+#else
+S3 s3;
+#endif
+
+#define DECLS \
+ int (^block)(int x) = ^(int x) { return x + x; }; \
+ void run(int (^block)(int x, int y));
+
+#if defined(FIRST) || defined(SECOND)
+struct Valid1 {
+ DECLS
+};
+#else
+Valid1 v1;
+#endif
+
+#if defined(FIRST) || defined(SECOND)
+struct Invalid1 {
+ DECLS
+ ACCESS
+};
+#else
+Invalid1 i1;
+// expected-error@second.h:* {{'Blocks::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
+// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
+#endif
+
+#undef DECLS
+}
+
+// Keep macros contained to one file.
+#ifdef FIRST
+#undef FIRST
+#endif
+
+#ifdef SECOND
+#undef SECOND
+#endif
+
+#ifdef ACCESS
+#undef ACCESS
+#endif
diff --git a/test/Modules/odr_hash-elaborated-types.cpp b/test/Modules/odr_hash-elaborated-types.cpp
new file mode 100644
index 000000000000..7dd11ac6d7f9
--- /dev/null
+++ b/test/Modules/odr_hash-elaborated-types.cpp
@@ -0,0 +1,12 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -std=c++1z -I%S/Inputs/odr_hash-elaborated-types -verify %s
+// RUN: %clang_cc1 -std=c++1z -fmodules -fmodules-local-submodule-visibility -fmodule-map-file=%S/Inputs/odr_hash-elaborated-types/module.modulemap -fmodules-cache-path=%t -x c++ -I%S/Inputs/odr_hash-elaborated-types -verify %s
+
+#include "textual_stat.h"
+
+#include "first.h"
+#include "second.h"
+
+void use() { struct stat value; }
+
+// expected-no-diagnostics
diff --git a/test/Modules/odr_hash.cpp b/test/Modules/odr_hash.cpp
index 054e41a9eaea..16ddfefa53c7 100644
--- a/test/Modules/odr_hash.cpp
+++ b/test/Modules/odr_hash.cpp
@@ -660,6 +660,202 @@ Invalid1* i1;
#undef DECLS
} // namespace Method
+namespace MethodBody {
+#if defined(FIRST)
+struct S1 {
+ int A() { return 0; }
+};
+#elif defined(SECOND)
+struct S1 {
+ int A() { return 0; }
+};
+#else
+S1 s1;
+#endif
+
+#if defined(FIRST)
+struct S2 {
+ int BothBodies() { return 0; }
+};
+#elif defined(SECOND)
+struct S2 {
+ int BothBodies() { return 1; }
+};
+#else
+S2 s2;
+// expected-error@first.h:* {{'MethodBody::S2' has different definitions in different modules; first difference is definition in module 'FirstModule' found method 'BothBodies' with body}}
+// expected-note@second.h:* {{but in 'SecondModule' found method 'BothBodies' with different body}}
+#endif
+
+#if defined(FIRST)
+struct S3 {
+ int FirstBody() { return 0; }
+};
+#elif defined(SECOND)
+struct S3 {
+ int FirstBody();
+};
+#else
+S3 s3;
+// expected-error@first.h:* {{'MethodBody::S3' has different definitions in different modules; first difference is definition in module 'FirstModule' found method 'FirstBody' with body}}
+// expected-note@second.h:* {{but in 'SecondModule' found method 'FirstBody' with no body}}
+#endif
+
+#if defined(FIRST)
+struct S4 {
+ int SecondBody();
+};
+#elif defined(SECOND)
+struct S4 {
+ int SecondBody() { return 0; }
+};
+#else
+S4 s4;
+// expected-error@first.h:* {{'MethodBody::S4' has different definitions in different modules; first difference is definition in module 'FirstModule' found method 'SecondBody' with no body}}
+// expected-note@second.h:* {{but in 'SecondModule' found method 'SecondBody' with body}}
+#endif
+
+#if defined(FIRST)
+struct S5 {
+ int FirstBodySecondOutOfLine() { return 0; }
+};
+#elif defined(SECOND)
+struct S5 {
+ int FirstBodySecondOutOfLine();
+};
+int S5::FirstBodySecondOutOfLine() { return 0; }
+#else
+S5 s5;
+// expected-error@second.h:* {{'MethodBody::S5' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'FirstBodySecondOutOfLine' with no body}}
+// expected-note@first.h:* {{but in 'FirstModule' found method 'FirstBodySecondOutOfLine' with body}}
+#endif
+
+#if defined(FIRST)
+struct S6 {
+ int FirstOutOfLineSecondBody();
+};
+int S6::FirstOutOfLineSecondBody() { return 0; }
+#elif defined(SECOND)
+struct S6 {
+ int FirstOutOfLineSecondBody() { return 0; }
+};
+#else
+S6 s6;
+// expected-error@first.h:* {{'MethodBody::S6' has different definitions in different modules; first difference is definition in module 'FirstModule' found method 'FirstOutOfLineSecondBody' with no body}}
+// expected-note@second.h:* {{but in 'SecondModule' found method 'FirstOutOfLineSecondBody' with body}}
+#endif
+
+#if defined(FIRST)
+struct S7 {
+ int BothOutOfLine();
+};
+int S7::BothOutOfLine() { return 1; }
+#elif defined(SECOND)
+struct S7 {
+ int BothOutOfLine();
+};
+int S7::BothOutOfLine() { return 0; }
+#else
+S7 s7;
+// expected-error@second.h:* {{'MethodBody::S7::BothOutOfLine' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+#endif
+
+#if defined(FIRST)
+struct S8 {
+ int FirstBodySecondOutOfLine() { return 0; }
+};
+#elif defined(SECOND)
+struct S8 {
+ int FirstBodySecondOutOfLine();
+};
+int S8::FirstBodySecondOutOfLine() { return 1; }
+#else
+S8 s8;
+// expected-error@second.h:* {{'MethodBody::S8' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'FirstBodySecondOutOfLine' with no body}}
+// expected-note@first.h:* {{but in 'FirstModule' found method 'FirstBodySecondOutOfLine' with body}}
+#endif
+
+#if defined(FIRST)
+struct S9 {
+ int FirstOutOfLineSecondBody();
+};
+int S9::FirstOutOfLineSecondBody() { return 1; }
+#elif defined(SECOND)
+struct S9 {
+ int FirstOutOfLineSecondBody() { return 0; }
+};
+#else
+S9 s9;
+// expected-error@first.h:* {{'MethodBody::S9' has different definitions in different modules; first difference is definition in module 'FirstModule' found method 'FirstOutOfLineSecondBody' with no body}}
+// expected-note@second.h:* {{but in 'SecondModule' found method 'FirstOutOfLineSecondBody' with body}}
+#endif
+
+#if defined(FIRST)
+struct S10 {
+ S10(int);
+ S10() = delete;
+};
+#elif defined(SECOND)
+struct S10 {
+ S10(int);
+ S10();
+};
+#else
+S10 s10(10);
+// expected-error@first.h:* {{'MethodBody::S10' has different definitions in different modules; first difference is definition in module 'FirstModule' found constructor is deleted}}
+// expected-note@second.h:* {{but in 'SecondModule' found constructor is not deleted}}
+#endif
+
+#if defined(FIRST)
+struct S11 {
+ S11() = default;
+};
+#elif defined(SECOND)
+struct S11 {
+ S11();
+};
+#else
+S11 s11;
+// expected-error@first.h:* {{'MethodBody::S11' has different definitions in different modules; first difference is definition in module 'FirstModule' found constructor is defaulted}}
+// expected-note@second.h:* {{but in 'SecondModule' found constructor is not defaulted}}
+#endif
+
+#define DECLS(CLASSNAME) \
+ CLASSNAME() = default; \
+ ~CLASSNAME() = delete; \
+ void A(); \
+ void B() { return; }; \
+ void C(); \
+ void D();
+
+#define OUTOFLINEDEFS(CLASSNAME) \
+ void CLASSNAME::C() {} \
+ void CLASSNAME::D() { return; }
+
+#if defined(FIRST) || defined(SECOND)
+struct Valid1 {
+ DECLS(Valid1)
+};
+OUTOFLINEDEFS(Valid1)
+#else
+Valid1* v1;
+#endif
+
+#if defined(FIRST) || defined(SECOND)
+struct Invalid1 {
+ DECLS(Invalid1)
+ ACCESS
+};
+OUTOFLINEDEFS(Invalid1)
+#else
+Invalid1* i1;
+// expected-error@first.h:* {{'MethodBody::Invalid1' has different definitions in different modules; first difference is definition in module 'FirstModule' found public access specifier}}
+// expected-note@second.h:* {{but in 'SecondModule' found private access specifier}}
+#endif
+#undef DECLS
+} // namespace MethodBody
+
namespace Constructor {
#if defined(FIRST)
struct S1 {
@@ -1635,6 +1831,96 @@ S6 s6;
// expected-note@first.h:* {{but in 'FirstModule' found field 'x'}}
#endif
+#if defined(FIRST)
+struct S7 {
+ template<int> void run() {}
+ template<> void run<1>() {}
+};
+#elif defined(SECOND)
+struct S7 {
+ template<int> void run() {}
+ void run() {}
+};
+#else
+S7 s7;
+// expected-error@second.h:* {{'TemplateArgument::S7' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'run' with no template arguments}}
+// expected-note@first.h:* {{but in 'FirstModule' found method 'run' with template arguments}}
+#endif
+
+#if defined(FIRST)
+struct S8 {
+ static int a, b;
+ template<int&> void run() {}
+ template<int&, int&> void run() {}
+ template<> void run<a>() {}
+};
+#elif defined(SECOND)
+struct S8 {
+ static int a, b;
+ template<int&> void run() {}
+ template<int&, int&> void run() {}
+ template<> void run<a, b>() {}
+};
+#else
+S8 s8;
+// expected-error@second.h:* {{'TemplateArgument::S8' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'run' with 2 template arguments}}
+// expected-note@first.h:* {{but in 'FirstModule' found method 'run' with 1 template argument}}
+#endif
+
+#if defined(FIRST)
+struct S9 {
+ static int a, b;
+ template<int&> void run() {}
+ template<> void run<a>() {}
+};
+#elif defined(SECOND)
+struct S9 {
+ static int a, b;
+ template<int&> void run() {}
+ template<> void run<b>() {}
+};
+#else
+S9 s9;
+// expected-error@second.h:* {{'TemplateArgument::S9' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'run' with 'b' for 1st template argument}}
+// expected-note@first.h:* {{but in 'FirstModule' found method 'run' with 'a' for 1st template argument}}
+#endif
+
+#if defined(FIRST)
+struct S10 {
+ static int a, b;
+ template<int, int&...> void run() {}
+ template<> void run<1, a>() {}
+};
+#elif defined(SECOND)
+struct S10 {
+ static int a, b;
+ template<int, int&...> void run() {}
+ template<> void run<1, b>() {}
+};
+#else
+S10 s10;
+// expected-error@second.h:* {{'TemplateArgument::S10' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'run' with 'b' for 2nd template argument}}
+// expected-note@first.h:* {{but in 'FirstModule' found method 'run' with 'a' for 2nd template argument}}
+#endif
+
+#if defined(FIRST)
+struct S11 {
+ static int a, b;
+ template<int, int&...> void run() {}
+ template<> void run<1, a>() {}
+};
+#elif defined(SECOND)
+struct S11 {
+ static int a, b;
+ template<int, int&...> void run() {}
+ template<> void run<1, a, a>() {}
+};
+#else
+S11 s11;
+// expected-error@second.h:* {{'TemplateArgument::S11' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'run' with 3 template arguments}}
+// expected-note@first.h:* {{but in 'FirstModule' found method 'run' with 2 template arguments}}
+#endif
+
#define DECLS \
OneClass<int> a; \
OneInt<1> b; \
@@ -1642,7 +1928,20 @@ S6 s6;
using d = OneInt<2>; \
using e = OneInt<2 + 2>; \
OneTemplateClass<OneClass> f; \
- OneTemplateInt<OneInt> g;
+ OneTemplateInt<OneInt> g; \
+ static int i1, i2; \
+ template <int &> \
+ void Function() {} \
+ template <int &, int &> \
+ void Function() {} \
+ template <> \
+ void Function<i1>() {} \
+ template <> \
+ void Function<i2>() {} \
+ template <> \
+ void Function<i1, i2>() {} \
+ template <> \
+ void Function<i2, i1>() {}
#if defined(FIRST) || defined(SECOND)
template <class> struct OneClass{};
@@ -2286,6 +2585,737 @@ Invalid1 i1;
#undef DECLS
} // namespace BaseClass
+namespace PointersAndReferences {
+#if defined(FIRST) || defined(SECOND)
+template<typename> struct Wrapper{};
+#endif
+
+#if defined(FIRST)
+struct S1 {
+ Wrapper<int*> x;
+};
+#elif defined(SECOND)
+struct S1 {
+ Wrapper<float*> x;
+};
+#else
+S1 s1;
+// expected-error@first.h:* {{PointersAndReferences::S1::x' from module 'FirstModule' is not present in definition of 'PointersAndReferences::S1' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'x' does not match}}
+#endif
+
+#if defined(FIRST)
+struct S2 {
+ Wrapper<int &&> x;
+};
+#elif defined(SECOND)
+struct S2 {
+ Wrapper<float &&> x;
+};
+#else
+S2 s2;
+// expected-error@first.h:* {{PointersAndReferences::S2::x' from module 'FirstModule' is not present in definition of 'PointersAndReferences::S2' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'x' does not match}}
+#endif
+
+#if defined(FIRST)
+struct S3 {
+ Wrapper<int *> x;
+};
+#elif defined(SECOND)
+struct S3 {
+ Wrapper<float *> x;
+};
+#else
+S3 s3;
+// expected-error@first.h:* {{PointersAndReferences::S3::x' from module 'FirstModule' is not present in definition of 'PointersAndReferences::S3' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'x' does not match}}
+#endif
+
+#if defined(FIRST)
+struct S4 {
+ Wrapper<int &> x;
+};
+#elif defined(SECOND)
+struct S4 {
+ Wrapper<float &> x;
+};
+#else
+S4 s4;
+// expected-error@first.h:* {{PointersAndReferences::S4::x' from module 'FirstModule' is not present in definition of 'PointersAndReferences::S4' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'x' does not match}}
+#endif
+
+#if defined(FIRST)
+struct S5 {
+ Wrapper<S5 *> x;
+};
+#elif defined(SECOND)
+struct S5 {
+ Wrapper<const S5 *> x;
+};
+#else
+S5 s5;
+// expected-error@second.h:* {{'PointersAndReferences::S5::x' from module 'SecondModule' is not present in definition of 'PointersAndReferences::S5' in module 'FirstModule'}}
+// expected-note@first.h:* {{declaration of 'x' does not match}}
+#endif
+
+#if defined(FIRST)
+struct S6 {
+ Wrapper<int &> x;
+};
+#elif defined(SECOND)
+struct S6 {
+ Wrapper<const int &> x;
+};
+#else
+S6 s6;
+// expected-error@first.h:* {{PointersAndReferences::S6::x' from module 'FirstModule' is not present in definition of 'PointersAndReferences::S6' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'x' does not match}}
+#endif
+
+#define DECLS \
+ Wrapper<int *> x1; \
+ Wrapper<float *> x2; \
+ Wrapper<const float *> x3; \
+ Wrapper<int &> x4; \
+ Wrapper<int &&> x5; \
+ Wrapper<const int &> x6; \
+ Wrapper<S1 *> x7; \
+ Wrapper<S1 &> x8; \
+ Wrapper<S1 &&> x9;
+
+#if defined(FIRST) || defined(SECOND)
+struct Valid1 {
+ DECLS
+};
+#else
+Valid1 v1;
+#endif
+
+#if defined(FIRST) || defined(SECOND)
+struct Invalid1 {
+ DECLS
+ ACCESS
+};
+#else
+Invalid1 i1;
+// expected-error@second.h:* {{'PointersAndReferences::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
+// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
+#endif
+#undef DECLS
+} // namespace PointersAndReferences
+
+namespace FunctionTemplate {
+#if defined(FIRST)
+struct S1 {
+ template <int, int> void foo();
+};
+#elif defined(SECOND)
+struct S1 {
+ template <int> void foo();
+};
+#else
+S1 s1;
+// expected-error@first.h:* {{'FunctionTemplate::S1::foo' from module 'FirstModule' is not present in definition of 'FunctionTemplate::S1' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'foo' does not match}}
+#endif
+
+#if defined(FIRST)
+struct S2 {
+ template <char> void foo();
+};
+#elif defined(SECOND)
+struct S2 {
+ template <int> void foo();
+};
+#else
+S2 s2;
+// expected-error@first.h:* {{'FunctionTemplate::S2::foo' from module 'FirstModule' is not present in definition of 'FunctionTemplate::S2' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'foo' does not match}}
+#endif
+
+#if defined(FIRST)
+struct S3 {
+ template <int x> void foo();
+};
+#elif defined(SECOND)
+struct S3 {
+ template <int y> void foo();
+};
+#else
+S3 s3;
+// expected-error@second.h:* {{'FunctionTemplate::S3' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter named 'y'}}
+// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter named 'x'}}
+#endif
+
+#if defined(FIRST)
+struct S4 {
+ template <int x> void foo();
+};
+#elif defined(SECOND)
+struct S4 {
+ template <int x> void bar();
+};
+#else
+S4 s4;
+// expected-error@first.h:* {{'FunctionTemplate::S4::foo' from module 'FirstModule' is not present in definition of 'FunctionTemplate::S4' in module 'SecondModule'}}
+// expected-note@second.h:* {{definition has no member 'foo'}}
+#endif
+
+#if defined(FIRST)
+struct S5 {
+ template <int x> void foo();
+};
+#elif defined(SECOND)
+struct S5 {
+ public:
+ template <int x> void foo();
+};
+#else
+S5 s5;
+// expected-error@second.h:* {{'FunctionTemplate::S5' has different definitions in different modules; first difference is definition in module 'SecondModule' found public access specifier}}
+// expected-note@first.h:* {{but in 'FirstModule' found function template}}
+#endif
+
+#if defined(FIRST)
+struct S6 {
+ template <typename x = int> void foo();
+};
+#elif defined(SECOND)
+struct S6 {
+ template <typename x> void foo();
+};
+#else
+S6 s6;
+// expected-error@second.h:* {{'FunctionTemplate::S6' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with no default argument}}
+// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with default argument}}
+#endif
+
+#if defined(FIRST)
+struct S7 {
+ template <typename x = void> void foo();
+};
+#elif defined(SECOND)
+struct S7 {
+ template <typename x = int> void foo();
+};
+#else
+S7 s7;
+// expected-error@second.h:* {{'FunctionTemplate::S7' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with default argument 'int'}}
+// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with default argument 'void'}}
+#endif
+
+#if defined(FIRST)
+template <int>
+struct U8 {};
+struct S8 {
+ template <template<int> class x = U8> void foo();
+};
+#elif defined(SECOND)
+template <int>
+struct T8 {};
+struct S8{
+ template <template<int> class x = T8> void foo();
+};
+#else
+S8 s8;
+// expected-error@second.h:* {{'FunctionTemplate::S8' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with default argument 'T8'}}
+// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with default argument 'U8'}}
+#endif
+
+#if defined(FIRST)
+template <int>
+struct U9 {};
+struct S9 { S9();
+ template <template<int> class x = U9> void foo();
+};
+#elif defined(SECOND)
+struct S9 { S9();
+ template <template<int> class x> void foo();
+};
+#else
+S9 s9;
+// expected-error@second.h:* {{'FunctionTemplate::S9' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with no default argument}}
+// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with default argument}}
+#endif
+
+#if defined(FIRST)
+struct S10 {
+ template <template<int> class x> void foo();
+ template <template<typename> class x> void foo();
+};
+#elif defined(SECOND)
+struct S10 {
+ template <template<typename> class x> void foo();
+ template <template<int> class x> void foo();
+};
+#else
+S10 s10;
+// expected-error@second.h:* {{'FunctionTemplate::S10' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with one type}}
+// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with different type}}
+#endif
+
+#if defined(FIRST)
+struct S11 {
+ template <template<int> class x> void foo();
+};
+#elif defined(SECOND)
+struct S11 {
+ template <template<int> class> void foo();
+};
+#else
+S11 s11;
+// expected-error@second.h:* {{'FunctionTemplate::S11' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with no name}}
+// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter named 'x'}}
+#endif
+
+#if defined(FIRST)
+struct S12 {
+ template <class> void foo();
+ template <class, class> void foo();
+};
+#elif defined(SECOND)
+struct S12 {
+ template <class, class> void foo();
+ template <class> void foo();
+};
+#else
+S12 s12;
+// expected-error@second.h:* {{'FunctionTemplate::S12' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 2 template parameters}}
+// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1 template parameter}}
+#endif
+
+#if defined(FIRST)
+struct S13 {
+ template <class = int> void foo();
+};
+#elif defined(SECOND)
+struct S13 {
+ template <class = void> void foo();
+};
+#else
+S13 s13;
+// expected-error@second.h:* {{'FunctionTemplate::S13' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with default argument 'void'}}
+// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with default argument 'int'}}
+#endif
+
+#if defined(FIRST)
+struct S14 {
+ template <class = void> void foo();
+};
+#elif defined(SECOND)
+struct S14 {
+ template <class> void foo();
+};
+#else
+S14 s14;
+// expected-error@second.h:* {{'FunctionTemplate::S14' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with no default argument}}
+// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with default argument}}
+#endif
+
+#if defined(FIRST)
+struct S15 {
+ template <class> void foo();
+};
+#elif defined(SECOND)
+struct S15 {
+ template <class = void> void foo();
+};
+#else
+S15 s15;
+// expected-error@second.h:* {{'FunctionTemplate::S15' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with default argument}}
+// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with no default argument}}
+#endif
+
+#if defined(FIRST)
+struct S16 {
+ template <short> void foo();
+};
+#elif defined(SECOND)
+struct S16 {
+ template <short = 1> void foo();
+};
+#else
+S16 s16;
+// expected-error@second.h:* {{'FunctionTemplate::S16' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with default argument}}
+// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with no default argument}}
+#endif
+
+#if defined(FIRST)
+struct S17 {
+ template <short = 2> void foo();
+};
+#elif defined(SECOND)
+struct S17 {
+ template <short = 1 + 1> void foo();
+};
+#else
+S17 s17;
+// expected-error@second.h:* {{'FunctionTemplate::S17' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with default argument 1 + 1}}
+// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with default argument 2}}
+#endif
+
+#if defined(FIRST)
+struct S18 {
+ template <short> void foo();
+ template <int> void foo();
+};
+#elif defined(SECOND)
+struct S18 {
+ template <int> void foo();
+ template <short> void foo();
+};
+#else
+S18 s18;
+// expected-error@second.h:* {{'FunctionTemplate::S18' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with one type}}
+// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with different type}}
+#endif
+
+#if defined(FIRST)
+struct S19 {
+ template <short> void foo();
+ template <short...> void foo();
+};
+#elif defined(SECOND)
+struct S19 {
+ template <short...> void foo();
+ template <short> void foo();
+};
+#else
+S19 s19;
+// expected-error@second.h:* {{'FunctionTemplate::S19' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter being a template parameter pack}}
+// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter not being a template parameter pack}}
+#endif
+
+#if defined(FIRST)
+struct S20 {
+ template <class> void foo();
+ template <class...> void foo();
+};
+#elif defined(SECOND)
+struct S20 {
+ template <class...> void foo();
+ template <class> void foo();
+};
+#else
+S20 s20;
+// expected-error@second.h:* {{'FunctionTemplate::S20' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter being a template parameter pack}}
+// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter not being a template parameter pack}}
+#endif
+
+#if defined(FIRST)
+struct S21 {
+ template <template<class> class...> void foo();
+ template <template<class> class> void foo();
+};
+#elif defined(SECOND)
+struct S21 {
+ template <template<class> class> void foo();
+ template <template<class> class...> void foo();
+};
+#else
+S21 s21;
+// expected-error@second.h:* {{'FunctionTemplate::S21' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter not being a template parameter pack}}
+// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter being a template parameter pack}}
+#endif
+
+#if defined(FIRST)
+struct S22 {
+ template <template<class> class> void foo();
+ template <class> void foo();
+ template <int> void foo();
+};
+#elif defined(SECOND)
+struct S22 {
+ template <class> void foo();
+ template <int> void foo();
+ template <template<class> class> void foo();
+};
+#else
+S22 s22;
+// expected-error@second.h:* {{'FunctionTemplate::S22' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter being a type template parameter}}
+// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template paramter being a template template parameter}}
+#endif
+
+#if defined(FIRST)
+struct S23 {
+ template <class> void foo();
+ template <int> void foo();
+ template <template<class> class> void foo();
+};
+#elif defined(SECOND)
+struct S23 {
+ template <int> void foo();
+ template <template<class> class> void foo();
+ template <class> void foo();
+};
+#else
+S23 s23;
+// expected-error@second.h:* {{'FunctionTemplate::S23' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter being a non-type template parameter}}
+// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template paramter being a type template parameter}}
+#endif
+
+#if defined(FIRST)
+struct S24 {
+ template <int> void foo();
+ template <template<class> class> void foo();
+ template <class> void foo();
+};
+#elif defined(SECOND)
+struct S24 {
+ template <template<class> class> void foo();
+ template <class> void foo();
+ template <int> void foo();
+};
+#else
+S24 s24;
+// expected-error@second.h:* {{'FunctionTemplate::S24' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter being a template template parameter}}
+// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template paramter being a non-type template parameter}}
+#endif
+
+#if defined(FIRST)
+struct S25 {
+ template <int> void foo();
+};
+#elif defined(SECOND)
+struct S25 {
+ public:
+ template <int> void foo();
+};
+#else
+S25 s25;
+// expected-error@second.h:* {{'FunctionTemplate::S25' has different definitions in different modules; first difference is definition in module 'SecondModule' found public access specifier}}
+// expected-note@first.h:* {{but in 'FirstModule' found function template}}
+#endif
+
+#define DECLS \
+ template <int> \
+ void nontype1(); \
+ template <int x> \
+ void nontype2(); \
+ template <int, int> \
+ void nontype3(); \
+ template <int x = 5> \
+ void nontype4(); \
+ template <int... x> \
+ void nontype5(); \
+ \
+ template <class> \
+ void type1(); \
+ template <class x> \
+ void type2(); \
+ template <class, class> \
+ void type3(); \
+ template <class x = int> \
+ void type4(); \
+ template <class... x> \
+ void type5(); \
+ \
+ template <template <int> class> \
+ void template1(); \
+ template <template <int> class x> \
+ void template2(); \
+ template <template <int> class, template <int> class> \
+ void template3(); \
+ template <template <int> class x = U> \
+ void template4(); \
+ template <template <int> class... x> \
+ void template5();
+
+#if defined(FIRST) || defined(SECOND)
+template<int>
+struct U {};
+struct Valid1 {
+ DECLS
+};
+#else
+Valid1 v1;
+#endif
+
+#if defined(FIRST) || defined(SECOND)
+struct Invalid1 {
+ DECLS
+ ACCESS
+};
+#else
+Invalid1 i1;
+// expected-error@second.h:* {{'FunctionTemplate::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
+// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
+#endif
+#undef DECLS
+}
+
+namespace Enums {
+#if defined(FIRST)
+enum E1 { x11 };
+#elif defined(SECOND)
+enum E1 {};
+#else
+E1 e1;
+// expected-error@first.h:* {{'Enums::x11' from module 'FirstModule' is not present in definition of 'Enums::E1' in module 'SecondModule'}}
+// expected-note@second.h:* {{definition has no member 'x11'}}
+#endif
+
+#if defined(FIRST)
+enum E2 {};
+#elif defined(SECOND)
+enum E2 { x21 };
+#else
+E2 e2;
+// expected-error@second.h:* {{'Enums::E2' has different definitions in different modules; definition in module 'SecondModule' first difference is enum with 1 element}}
+// expected-note@first.h:* {{but in 'FirstModule' found enum with 0 elements}}
+#endif
+
+#if defined(FIRST)
+enum E3 { x31 };
+#elif defined(SECOND)
+enum E3 { x32 };
+#else
+E3 e3;
+// expected-error@first.h:* {{'Enums::x31' from module 'FirstModule' is not present in definition of 'Enums::E3' in module 'SecondModule'}}
+// expected-note@second.h:* {{definition has no member 'x31'}}
+#endif
+
+#if defined(FIRST)
+enum E4 { x41 };
+#elif defined(SECOND)
+enum E4 { x41, x42 };
+#else
+E4 e4;
+// expected-error@second.h:* {{'Enums::E4' has different definitions in different modules; definition in module 'SecondModule' first difference is enum with 2 elements}}
+// expected-note@first.h:* {{but in 'FirstModule' found enum with 1 element}}
+#endif
+
+#if defined(FIRST)
+enum E5 { x51, x52 };
+#elif defined(SECOND)
+enum E5 { x51 };
+#else
+E5 e5;
+// expected-error@first.h:* {{'Enums::x52' from module 'FirstModule' is not present in definition of 'Enums::E5' in module 'SecondModule'}}
+// expected-note@second.h:* {{definition has no member 'x52'}}
+#endif
+
+#if defined(FIRST)
+enum E6 { x61, x62 };
+#elif defined(SECOND)
+enum E6 { x62, x61 };
+#else
+E6 e6;
+// expected-error@second.h:* {{'Enums::E6' has different definitions in different modules; definition in module 'SecondModule' first difference is 1st element has name 'x62'}}
+// expected-note@first.h:* {{but in 'FirstModule' found 1st element has name 'x61'}}
+#endif
+
+#if defined(FIRST)
+enum E7 { x71 = 0 };
+#elif defined(SECOND)
+enum E7 { x71 };
+#else
+E7 e7;
+// expected-error@second.h:* {{'Enums::E7' has different definitions in different modules; definition in module 'SecondModule' first difference is 1st element 'x71' has an initilizer}}
+// expected-note@first.h:* {{but in 'FirstModule' found 1st element 'x71' does not have an initializer}}
+#endif
+
+#if defined(FIRST)
+enum E8 { x81 };
+#elif defined(SECOND)
+enum E8 { x81 = 0 };
+#else
+E8 e8;
+// expected-error@second.h:* {{'Enums::E8' has different definitions in different modules; definition in module 'SecondModule' first difference is 1st element 'x81' does not have an initilizer}}
+// expected-note@first.h:* {{but in 'FirstModule' found 1st element 'x81' has an initializer}}
+#endif
+
+#if defined(FIRST)
+enum E9 { x91 = 0, x92 = 1 };
+#elif defined(SECOND)
+enum E9 { x91 = 0, x92 = 2 - 1 };
+#else
+E9 e9;
+// expected-error@second.h:* {{'Enums::E9' has different definitions in different modules; definition in module 'SecondModule' first difference is 2nd element 'x92' has an initializer}}
+// expected-note@first.h:* {{but in 'FirstModule' found 2nd element 'x92' has different initializer}}
+#endif
+
+#if defined(FIRST)
+enum class E10 : int {};
+#elif defined(SECOND)
+enum class E10 {};
+#else
+E10 e10;
+// expected-error@second.h:* {{'Enums::E10' has different definitions in different modules; definition in module 'SecondModule' first difference is enum without specified type}}
+// expected-note@first.h:* {{but in 'FirstModule' found enum with specified type}}
+#endif
+
+#if defined(FIRST)
+enum E11 {};
+#elif defined(SECOND)
+enum E11 : int {};
+#else
+E11 e11;
+// expected-error@second.h:* {{'Enums::E11' has different definitions in different modules; definition in module 'SecondModule' first difference is enum with specified type}}
+// expected-note@first.h:* {{but in 'FirstModule' found enum without specified type}}
+#endif
+
+#if defined(FIRST)
+enum struct E12 : long {};
+#elif defined(SECOND)
+enum struct E12 : int {};
+#else
+E12 e12;
+// expected-error@second.h:* {{'Enums::E12' has different definitions in different modules; definition in module 'SecondModule' first difference is enum with specified type 'int'}}
+// expected-note@first.h:* {{but in 'FirstModule' found enum with specified type 'long'}}
+#endif
+
+#if defined(FIRST)
+enum struct E13 {};
+#elif defined(SECOND)
+enum E13 {};
+#else
+E13 e13;
+// expected-error@second.h:* {{'Enums::E13' has different definitions in different modules; definition in module 'SecondModule' first difference is enum that is not scoped}}
+// expected-note@first.h:* {{but in 'FirstModule' found enum that is scoped}}
+#endif
+
+#if defined(FIRST)
+enum E14 {};
+#elif defined(SECOND)
+enum struct E14 {};
+#else
+E14 e14;
+// expected-error@second.h:* {{'Enums::E14' has different definitions in different modules; definition in module 'SecondModule' first difference is enum that is scoped}}
+// expected-note@first.h:* {{but in 'FirstModule' found enum that is not scoped}}
+#endif
+
+#if defined(FIRST)
+enum class E15 {};
+#elif defined(SECOND)
+enum struct E15 {};
+#else
+E15 e15;
+// expected-error@second.h:* {{'Enums::E15' has different definitions in different modules; definition in module 'SecondModule' first difference is enum scoped with keyword struct}}
+// expected-note@first.h:* {{but in 'FirstModule' found enum scoped with keyword class}}
+#endif
+
+#if defined(FIRST)
+enum struct E16 {};
+#elif defined(SECOND)
+enum class E16 {};
+#else
+E16 e16;
+// expected-error@second.h:* {{'Enums::E16' has different definitions in different modules; definition in module 'SecondModule' first difference is enum scoped with keyword class}}
+// expected-note@first.h:* {{but in 'FirstModule' found enum scoped with keyword struct}}
+#endif
+
+#if defined(FIRST)
+enum Valid { v1 = (struct S*)0 == (struct S*)0 };
+#elif defined(SECOND)
+struct S {};
+enum Valid { v1 = (struct S*)0 == (struct S*)0 };
+#else
+Valid V;
+#endif
+} // namespace Enums
// Collection of interesting cases below.
@@ -2744,6 +3774,38 @@ struct S3 {
#else
S3 s3;
#endif
+
+#if defined(FIRST)
+using A4 = int;
+using B4 = A4;
+struct S4 {
+ B4 x;
+};
+#elif defined(SECOND)
+using A4 = int;
+using B4 = ::MultipleTypedefs::A4;
+struct S4 {
+ B4 x;
+};
+#else
+S4 s4;
+#endif
+
+#if defined(FIRST)
+using A5 = int;
+using B5 = MultipleTypedefs::A5;
+struct S5 {
+ B5 x;
+};
+#elif defined(SECOND)
+using A5 = int;
+using B5 = ::MultipleTypedefs::A5;
+struct S5 {
+ B5 x;
+};
+#else
+S5 s5;
+#endif
} // MultipleTypedefs
namespace DefaultArguments {
@@ -2922,8 +3984,63 @@ int I10 = F10();
#endif
// expected-error@second.h:* {{'FunctionDecl::F10' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+
+#if defined(FIRST)
+struct S11 {
+ template <int> void foo();
+};
+#elif defined(SECOND)
+struct S11 {
+ template <int> void foo();
+};
+template <int> void S11::foo() {}
+#else
+S11 s11;
+#endif
+
+#if defined(FIRST)
+struct S12 {
+ void foo(int x);
+};
+#elif defined(SECOND)
+struct S12 {
+ void foo(int x);
+};
+void S12::foo(int y) {}
+#else
+S12 s12;
+#endif
+
+#if defined(FIRST)
+struct S13 {
+ void foo(int x);
+};
+void S13::foo(int y) {}
+#elif defined(SECOND)
+struct S13 {
+ void foo(int x);
+};
+void S13::foo(int y) {}
+#else
+S13 s13;
+#endif
} // namespace FunctionDecl
+namespace DeclTemplateArguments {
+#if defined(FIRST)
+int foo() { return 1; }
+int bar() { return foo(); }
+#elif defined(SECOND)
+template <class T = int>
+int foo() { return 2; }
+int bar() { return foo<>(); }
+#else
+int num = bar();
+// expected-error@second.h:* {{'DeclTemplateArguments::bar' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+#endif
+}
+
// Keep macros contained to one file.
#ifdef FIRST
#undef FIRST
diff --git a/test/Modules/pr27401.cpp b/test/Modules/pr27401.cpp
index 7d5479cb9243..8db3bbb0094a 100644
--- a/test/Modules/pr27401.cpp
+++ b/test/Modules/pr27401.cpp
@@ -1,6 +1,7 @@
// RUN: rm -rf %t
// RUN: %clang_cc1 -std=c++11 -I%S/Inputs/PR27401 -verify %s
// RUN: %clang_cc1 -std=c++11 -fmodules -fmodule-map-file=%S/Inputs/PR27401/module.modulemap -fmodules-cache-path=%t -I%S/Inputs/PR27401 -verify %s
+// RUN: %clang_cc1 -std=c++11 -fmodules -fmodule-map-file=%S/Inputs/PR27401/module.modulemap -fmodules-cache-path=%t -I%S/Inputs/PR27401 -verify %s -triple i686-windows
#include "a.h"
#define _LIBCPP_VECTOR
diff --git a/test/Modules/protocol-redefinition.m b/test/Modules/protocol-redefinition.m
new file mode 100644
index 000000000000..85a957bbfd70
--- /dev/null
+++ b/test/Modules/protocol-redefinition.m
@@ -0,0 +1,6 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F%S/Inputs/protocol-redefinition -fsyntax-only %s -Wno-private-module -verify
+
+// expected-no-diagnostics
+
+@import Kit;
diff --git a/test/Modules/requires.m b/test/Modules/requires.m
index 4a83d0c2b0ec..d8f54b495089 100644
--- a/test/Modules/requires.m
+++ b/test/Modules/requires.m
@@ -1,6 +1,7 @@
// RUN: rm -rf %t
// RUN: %clang_cc1 -Wauto-import -Wno-private-module -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -I %S/Inputs %s -verify -fmodule-feature custom_req1
-
+// RUN: %clang_cc1 -Wauto-import -Wno-private-module -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -I %S/Inputs %s -verify -std=c89 -DTEST_C_FEATURES
+#ifndef TEST_C_FEATURES
// expected-error@DependsOnModule.framework/module.map:7 {{module 'DependsOnModule.CXX' requires feature 'cplusplus'}}
@import DependsOnModule.CXX; // expected-note {{module imported here}}
@import DependsOnModule.NotCXX;
@@ -15,3 +16,17 @@
@import RequiresWithMissingHeader.HeaderBefore; // expected-note {{module imported here}}
// expected-error@module.map:* {{module 'RequiresWithMissingHeader.HeaderAfter' requires feature 'missing'}}
@import RequiresWithMissingHeader.HeaderAfter; // expected-note {{module imported here}}
+// expected-error@DependsOnModule.framework/module.map:40 {{module 'DependsOnModule.CXX11' requires feature 'cplusplus11'}}
+@import DependsOnModule.CXX11; // expected-note {{module imported here}}
+// expected-error@DependsOnModule.framework/module.map:43 {{module 'DependsOnModule.CXX14' requires feature 'cplusplus14'}}
+@import DependsOnModule.CXX14; // expected-note {{module imported here}}
+// expected-error@DependsOnModule.framework/module.map:46 {{module 'DependsOnModule.CXX17' requires feature 'cplusplus17'}}
+@import DependsOnModule.CXX17; // expected-note {{module imported here}}
+#else
+// expected-error@DependsOnModule.framework/module.map:49 {{module 'DependsOnModule.C99' requires feature 'c99'}}
+@import DependsOnModule.C99; // expected-note {{module imported here}}
+// expected-error@DependsOnModule.framework/module.map:52 {{module 'DependsOnModule.C11' requires feature 'c11'}}
+@import DependsOnModule.C11; // expected-note {{module imported here}}
+// expected-error@DependsOnModule.framework/module.map:55 {{module 'DependsOnModule.C17' requires feature 'c17'}}
+@import DependsOnModule.C17; // expected-note {{module imported here}}
+#endif
diff --git a/test/Modules/self-referencing-lambda.cpp b/test/Modules/self-referencing-lambda.cpp
new file mode 100644
index 000000000000..1e75d446ebb5
--- /dev/null
+++ b/test/Modules/self-referencing-lambda.cpp
@@ -0,0 +1,5 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs/self-referencing-lambda %s -verify -emit-obj -std=c++14 -o %t2.o
+// expected-no-diagnostics
+
+#include "a.h"
diff --git a/test/Modules/shadow.m b/test/Modules/shadow.m
new file mode 100644
index 000000000000..44320af2b0c6
--- /dev/null
+++ b/test/Modules/shadow.m
@@ -0,0 +1,21 @@
+// RUN: rm -rf %t
+// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs/shadow/A1 -I %S/Inputs/shadow/A2 %s -fsyntax-only 2>&1 | FileCheck %s -check-prefix=REDEFINITION
+// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -fmodule-map-file=%S/Inputs/shadow/A1/module.modulemap -fmodule-map-file=%S/Inputs/shadow/A2/module.modulemap %s -fsyntax-only 2>&1 | FileCheck %s -check-prefix=REDEFINITION
+// REDEFINITION: error: redefinition of module 'A'
+// REDEFINITION: note: previously defined
+
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -fmodule-map-file=%S/Inputs/shadow/A1/module.modulemap -I %S/Inputs/shadow %s -verify
+
+@import A1;
+@import A2;
+@import A;
+
+#import "A2/A.h" // expected-note {{implicitly imported}}
+// expected-error@A2/module.modulemap:1 {{import of shadowed module 'A'}}
+// expected-note@A1/module.modulemap:1 {{previous definition}}
+
+#if defined(A2_A_h)
+#error got the wrong definition of module A
+#elif !defined(A1_A_h)
+#error missing definition from A1
+#endif
diff --git a/test/Modules/shadowed-submodule.m b/test/Modules/shadowed-submodule.m
new file mode 100644
index 000000000000..c9c77bd13a1c
--- /dev/null
+++ b/test/Modules/shadowed-submodule.m
@@ -0,0 +1,5 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs/shadowed-submodule/Foo -I %S/Inputs/shadowed-submodule/A2 %s -verify
+
+@import Foo; // expected-error {{module 'A' was built in directory}}
+ // expected-note@shadowed-submodule.m:4 {{imported by module 'Foo'}}
diff --git a/test/Modules/submodule-in-private-mmap.m b/test/Modules/submodule-in-private-mmap.m
new file mode 100644
index 000000000000..50e50108757f
--- /dev/null
+++ b/test/Modules/submodule-in-private-mmap.m
@@ -0,0 +1,7 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F%S/Inputs/submodule-in-private-mmap -fsyntax-only %s -Wno-private-module -verify
+
+// expected-no-diagnostics
+
+@import A.Private;
+@import A.SomeSub;
diff --git a/test/Modules/target-features.m b/test/Modules/target-features.m
index b4524835f534..b2597960cbd0 100644
--- a/test/Modules/target-features.m
+++ b/test/Modules/target-features.m
@@ -1,6 +1,7 @@
// REQUIRES: x86-registered-target
// REQUIRES: arm-registered-target
// REQUIRES: aarch64-registered-target
+// REQUIRES: riscv-registered-target
// RUN: rm -rf %t
@@ -17,6 +18,10 @@
// RUN: FileCheck %s -check-prefix=X86_32 < %t.x86_32
// RUN: not %clang_cc1 -triple x86_64-unknown-unknown -fmodules -fmodules-cache-path=%t -fimplicit-module-maps -I %S/Inputs -fsyntax-only %s 2> %t.x86_64
// RUN: FileCheck %s -check-prefix=X86_64 < %t.x86_64
+// RUN: not %clang_cc1 -triple riscv32-unknown-unknown -fmodules -fmodules-cache-path=%t -fimplicit-module-maps -I %S/Inputs -fsyntax-only %s 2> %t.riscv32
+// RUN: FileCheck %s -check-prefix=RISCV32 < %t.riscv32
+// RUN: not %clang_cc1 -triple riscv64-unknown-unknown -fmodules -fmodules-cache-path=%t -fimplicit-module-maps -I %S/Inputs -fsyntax-only %s 2> %t.riscv64
+// RUN: FileCheck %s -check-prefix=RISCV64 < %t.riscv64
#ifndef SANITY_CHECK
@import TargetFeatures;
@@ -24,16 +29,22 @@
// AARCH64-NOT: module 'TargetFeatures' requires
// X86_32-NOT: module 'TargetFeatures' requires
// X86_64-NOT: module 'TargetFeatures' requires
+// RISCV32-NOT: module 'TargetFeatures' requires
+// RISCV64-NOT: module 'TargetFeatures' requires
@import TargetFeatures.arm;
// AARCH32-NOT: module 'TargetFeatures.arm' requires
// AARCH64-NOT: module 'TargetFeatures.arm' requires
// X86_32: module 'TargetFeatures.arm' requires feature 'arm'
// X86_64: module 'TargetFeatures.arm' requires feature 'arm'
+// RISCV32: module 'TargetFeatures.arm' requires
+// RISCV64: module 'TargetFeatures.arm' requires
@import TargetFeatures.arm.aarch32;
// AARCH32-NOT: module 'TargetFeatures.arm.aarch32' requires
// AARCH64: module 'TargetFeatures.arm.aarch32' requires feature 'aarch32'
// X86_32: module 'TargetFeatures.arm.aarch32' requires feature
// X86_64: module 'TargetFeatures.arm.aarch32' requires feature
+// RISCV32: module 'TargetFeatures.arm.aarch32' requires feature
+// RISCV64: module 'TargetFeatures.arm.aarch32' requires feature
#endif
@import TargetFeatures.arm.aarch64;
@@ -41,6 +52,8 @@
// AARCH64-NOT: module 'TargetFeatures.arm.aarch64' requires
// X86_32: module 'TargetFeatures.arm.aarch64' requires feature
// X86_64: module 'TargetFeatures.arm.aarch64' requires feature
+// RISCV32: module 'TargetFeatures.arm.aarch64' requires feature
+// RISCV64: module 'TargetFeatures.arm.aarch64' requires feature
#ifndef SANITY_CHECK
@import TargetFeatures.x86;
@@ -48,14 +61,41 @@
// AARCH64: module 'TargetFeatures.x86' requires feature 'x86'
// X86_32-NOT: module 'TargetFeatures.x86' requires
// X86_64-NOT: module 'TargetFeatures.x86' requires
+// RISCV32: module 'TargetFeatures.x86' requires feature 'x86'
+// RISCV64: module 'TargetFeatures.x86' requires feature 'x86'
@import TargetFeatures.x86.x86_32;
// AARCH32: module 'TargetFeatures.x86.x86_32' requires feature
// AARCH64: module 'TargetFeatures.x86.x86_32' requires feature
// X86_32-NOT: module 'TargetFeatures.x86.x86_32' requires
// X86_64: module 'TargetFeatures.x86.x86_32' requires feature 'x86_32'
+// RISCV32: module 'TargetFeatures.x86.x86_32' requires feature
+// RISCV64: module 'TargetFeatures.x86.x86_32' requires feature
@import TargetFeatures.x86.x86_64;
// AARCH32: module 'TargetFeatures.x86.x86_64' requires feature
// AARCH64: module 'TargetFeatures.x86.x86_64' requires feature
// X86_32: module 'TargetFeatures.x86.x86_64' requires feature 'x86_64'
// X86_64-NOT: module 'TargetFeatures.x86.x86_64' requires
+// RISCV32: module 'TargetFeatures.x86.x86_64' requires feature
+// RISCV64: module 'TargetFeatures.x86.x86_64' requires feature
+@import TargetFeatures.riscv;
+// AARCH32: module 'TargetFeatures.riscv' requires feature
+// AARCH64: module 'TargetFeatures.riscv' requires feature
+// X86_32: module 'TargetFeatures.riscv' requires feature
+// X86_64: module 'TargetFeatures.riscv' requires feature
+// RISCV32-NOT: module 'TargetFeatures.riscv' requires feature
+// RISCV64-NOT: module 'TargetFeatures.riscv' requires feature
+@import TargetFeatures.riscv.riscv32;
+// AARCH32: module 'TargetFeatures.riscv.riscv32' requires feature
+// AARCH64: module 'TargetFeatures.riscv.riscv32' requires feature
+// X86_32: module 'TargetFeatures.riscv.riscv32' requires feature
+// X86_64: module 'TargetFeatures.riscv.riscv32' requires feature
+// RISCV32-NOT: module 'TargetFeatures.riscv.riscv32' requires feature
+// RISCV64: module 'TargetFeatures.riscv.riscv32' requires feature 'riscv32'
+@import TargetFeatures.riscv.riscv64;
+// AARCH32: module 'TargetFeatures.riscv.riscv64' requires feature
+// AARCH64: module 'TargetFeatures.riscv.riscv64' requires feature
+// X86_32: module 'TargetFeatures.riscv.riscv64' requires feature
+// X86_64: module 'TargetFeatures.riscv.riscv64' requires feature
+// RISCV32: module 'TargetFeatures.riscv.riscv64' requires feature 'riscv64'
+// RISCV64-NOT: module 'TargetFeatures.riscv.riscv64' requires feature
#endif
diff --git a/test/Modules/templates.mm b/test/Modules/templates.mm
index 79e975a1ad12..95e7a9caea55 100644
--- a/test/Modules/templates.mm
+++ b/test/Modules/templates.mm
@@ -77,10 +77,10 @@ unsigned testMixedStruct() {
// CHECK: %[[l:.*]] = alloca %[[ListInt:[^ ]*]], align 8
// CHECK: %[[r:.*]] = alloca %[[ListInt]], align 8
- // CHECK: call {{.*}}memcpy{{.*}}(i8* %{{.*}}, i8* bitcast ({{.*}}* @_ZZ15testMixedStructvE1l to i8*), i64 16,
+ // CHECK: call {{.*}}memcpy{{.*}}(i8* align {{[0-9]+}} %{{.*}}, i8* align {{[0-9]+}} bitcast ({{.*}}* @_ZZ15testMixedStructvE1l to i8*), i64 16,
ListInt_left l{0, 1};
- // CHECK: call {{.*}}memcpy{{.*}}(i8* %{{.*}}, i8* bitcast ({{.*}}* @_ZZ15testMixedStructvE1r to i8*), i64 16,
+ // CHECK: call {{.*}}memcpy{{.*}}(i8* align {{[0-9]+}} %{{.*}}, i8* align {{[0-9]+}} bitcast ({{.*}}* @_ZZ15testMixedStructvE1r to i8*), i64 16,
ListInt_right r{0, 2};
// CHECK: call void @_Z10useListIntR4ListIiE(%[[ListInt]]* dereferenceable({{[0-9]+}}) %[[l]])
@@ -122,3 +122,13 @@ void testWithAttributes() {
static_assert(alignof(decltype(a)) == 2, "");
static_assert(alignof(decltype(b)) == 2, "");
}
+
+// Check that returnNonTrivial doesn't return Class0<S0> directly in registers.
+
+// CHECK: declare void @_Z16returnNonTrivialv(%struct.Class0* sret)
+
+@import template_nontrivial0;
+@import template_nontrivial1;
+
+S1::S1() : a(returnNonTrivial()) {
+}
diff --git a/test/Modules/use-exportas-for-link.m b/test/Modules/use-exportas-for-link.m
new file mode 100644
index 000000000000..69773e6039f6
--- /dev/null
+++ b/test/Modules/use-exportas-for-link.m
@@ -0,0 +1,44 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -emit-llvm -o - -fmodules-cache-path=%t -DA -fmodules -fimplicit-module-maps -F %S/Inputs/exportas-link %s | FileCheck --check-prefix=CHECK_A %s
+// CHECK_A: !llvm.linker.options = !{![[MODULE:[0-9]+]]}
+// CHECK_A: ![[MODULE]] = !{!"-framework", !"SomeKit"}
+#ifdef A
+@import SomeKitCore;
+@import SomeKit;
+#endif
+
+// RUN: %clang_cc1 -emit-llvm -o - -fmodules-cache-path=%t -DB -fmodules -fimplicit-module-maps -F %S/Inputs/exportas-link %s | FileCheck --check-prefix=CHECK_B %s
+// CHECK_B: !llvm.linker.options = !{![[MODULE:[0-9]+]]}
+// CHECK_B: ![[MODULE]] = !{!"-framework", !"SomeKit"}
+#ifdef B
+@import SomeKit;
+@import SomeKitCore;
+#endif
+
+// RUN: %clang_cc1 -emit-llvm -o - -fmodules-cache-path=%t -DC -fmodules -fimplicit-module-maps -F %S/Inputs/exportas-link %s | FileCheck --check-prefix=CHECK_C %s
+// CHECK_C: !llvm.linker.options = !{![[MODULE:[0-9]+]]}
+// CHECK_C: ![[MODULE]] = !{!"-framework", !"SomeKitCore"}
+#ifdef C
+@import SomeKitCore;
+#endif
+
+// RUN: %clang_cc1 -emit-llvm -o - -fmodules-cache-path=%t -DD -fmodules -fimplicit-module-maps -F %S/Inputs/exportas-link %s | FileCheck --check-prefix=CHECK_D %s
+// CHECK_D: !llvm.linker.options = !{![[MODULE:[0-9]+]]}
+// CHECK_D: ![[MODULE]] = !{!"-framework", !"SomeKit"}
+#ifdef D
+@import SomeKit;
+#endif
+
+// RUN: %clang_cc1 -emit-llvm -o - -fmodules-cache-path=%t -DE -fmodules -fimplicit-module-maps -F %S/Inputs/exportas-link %s | FileCheck --check-prefix=CHECK_E %s
+// CHECK_E: !llvm.linker.options = !{![[MODULE:[0-9]+]]}
+// CHECK_E: ![[MODULE]] = !{!"-framework", !"SomeKitCore"}
+#ifdef E
+@import OtherKit;
+#endif
+
+// RUN: %clang_cc1 -emit-llvm -o - -fmodules-cache-path=%t -DF -fmodules -fimplicit-module-maps -F %S/Inputs/exportas-link %s | FileCheck --check-prefix=CHECK_F %s
+// CHECK_F: !llvm.linker.options = !{![[MODULE:[0-9]+]]}
+// CHECK_F: ![[MODULE]] = !{!"-framework", !"SomeKit"}
+#ifdef F
+@import OtherKit;
+#endif
diff --git a/test/Modules/using-decl-friend-2.cpp b/test/Modules/using-decl-friend-2.cpp
new file mode 100644
index 000000000000..0c71c37765f3
--- /dev/null
+++ b/test/Modules/using-decl-friend-2.cpp
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -fmodules %s -verify
+// expected-no-diagnostics
+
+#pragma clang module build A
+module A {}
+#pragma clang module contents
+#pragma clang module begin A
+namespace N { class X; }
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module build B
+module B {}
+#pragma clang module contents
+#pragma clang module begin B
+namespace N { class Friendly { friend class X; }; }
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module build C
+module C {}
+#pragma clang module contents
+#pragma clang module begin C
+#pragma clang module import A
+void use_X(N::X *p);
+#pragma clang module import B
+// UsingShadowDecl names the friend declaration
+using N::X;
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module import B
+namespace N { class AlsoFriendly { friend class X; }; }
+#pragma clang module import A
+#pragma clang module import C
+// The friend declaration from N::Friendly is now the first in the redecl
+// chain, so is not ordinarily visible. We need the IDNS of the UsingShadowDecl
+// to still consider it to be visible, though.
+X *p;
diff --git a/test/Modules/using-decl-friend.cpp b/test/Modules/using-decl-friend.cpp
new file mode 100644
index 000000000000..f11d0021a8ad
--- /dev/null
+++ b/test/Modules/using-decl-friend.cpp
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -fmodules %s -verify
+// expected-no-diagnostics
+
+#pragma clang module build A
+module A {}
+#pragma clang module contents
+#pragma clang module begin A
+namespace N {
+ class X;
+}
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module build B
+module B {
+ module X {}
+ module Y {}
+}
+#pragma clang module contents
+#pragma clang module begin B.X
+namespace N {
+ class Friendly {
+ friend class X;
+ };
+}
+#pragma clang module end
+#pragma clang module begin B.Y
+namespace N {
+ class X;
+}
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module import A
+#pragma clang module import B.X
+using N::X;
+X *p;
diff --git a/test/OpenMP/atomic_ast_print.cpp b/test/OpenMP/atomic_ast_print.cpp
index f1fc7c8e559e..c66249b708ed 100644
--- a/test/OpenMP/atomic_ast_print.cpp
+++ b/test/OpenMP/atomic_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -44,7 +48,7 @@ T foo(T argc) {
}
// CHECK: T a = T();
-// CHECK-NEXT: #pragma omp atomic
+// CHECK-NEXT: #pragma omp atomic{{$}}
// CHECK-NEXT: a++;
// CHECK-NEXT: #pragma omp atomic read
// CHECK-NEXT: a = argc;
diff --git a/test/OpenMP/atomic_capture_codegen.cpp b/test/OpenMP/atomic_capture_codegen.cpp
index 306b83f62463..51c65a09fb22 100644
--- a/test/OpenMP/atomic_capture_codegen.cpp
+++ b/test/OpenMP/atomic_capture_codegen.cpp
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -target-cpu core2 -fopenmp -x c -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c -triple x86_64-apple-darwin10 -target-cpu core2 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c -triple x86_64-apple-darwin10 -target-cpu core2 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -target-cpu core2 -fopenmp-simd -x c -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c -triple x86_64-apple-darwin10 -target-cpu core2 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c -triple x86_64-apple-darwin10 -target-cpu core2 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/atomic_codegen.cpp b/test/OpenMP/atomic_codegen.cpp
index 7f62a9bfa6fb..c7411160604c 100644
--- a/test/OpenMP/atomic_codegen.cpp
+++ b/test/OpenMP/atomic_codegen.cpp
@@ -2,6 +2,12 @@
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fexceptions -fcxx-exceptions -x c++ -emit-llvm -std=c++98 %s -o - | FileCheck %s
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fexceptions -fcxx-exceptions -x c++ -emit-llvm -std=c++11 %s -o - | FileCheck %s
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck %s --check-prefix=TERM_DEBUG
+
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -fexceptions -fcxx-exceptions -x c++ -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -fexceptions -fcxx-exceptions -x c++ -emit-llvm -std=c++98 %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -fexceptions -fcxx-exceptions -x c++ -emit-llvm -std=c++11 %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
int a;
diff --git a/test/OpenMP/atomic_messages.c b/test/OpenMP/atomic_messages.c
index 7b3178bba49f..1234e8580c02 100644
--- a/test/OpenMP/atomic_messages.c
+++ b/test/OpenMP/atomic_messages.c
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
int foo() {
L1:
foo();
diff --git a/test/OpenMP/atomic_messages.cpp b/test/OpenMP/atomic_messages.cpp
index efb368d1a7c0..d7fa8c9e0758 100644
--- a/test/OpenMP/atomic_messages.cpp
+++ b/test/OpenMP/atomic_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
int foo() {
L1:
foo();
diff --git a/test/OpenMP/atomic_read_codegen.c b/test/OpenMP/atomic_read_codegen.c
index 0cfb2d26f243..55fd03b440da 100644
--- a/test/OpenMP/atomic_read_codegen.c
+++ b/test/OpenMP/atomic_read_codegen.c
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -target-cpu core2 -fopenmp -x c -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c -triple x86_64-apple-darwin10 -target-cpu core2 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c -triple x86_64-apple-darwin10 -target-cpu core2 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -target-cpu core2 -fopenmp-simd -x c -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c -triple x86_64-apple-darwin10 -target-cpu core2 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c -triple x86_64-apple-darwin10 -target-cpu core2 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
// REQUIRES: x86-registered-target
#ifndef HEADER
diff --git a/test/OpenMP/atomic_update_codegen.cpp b/test/OpenMP/atomic_update_codegen.cpp
index 1343cd8ad2cd..d314c24a1624 100644
--- a/test/OpenMP/atomic_update_codegen.cpp
+++ b/test/OpenMP/atomic_update_codegen.cpp
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -target-cpu core2 -fopenmp -x c -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c -triple x86_64-apple-darwin10 -target-cpu core2 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c -triple x86_64-apple-darwin10 -target-cpu core2 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -target-cpu core2 -fopenmp-simd -x c -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c -triple x86_64-apple-darwin10 -target-cpu core2 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c -triple x86_64-apple-darwin10 -target-cpu core2 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/atomic_write_codegen.c b/test/OpenMP/atomic_write_codegen.c
index 0c85b6e88a3f..242708cd7cf5 100644
--- a/test/OpenMP/atomic_write_codegen.c
+++ b/test/OpenMP/atomic_write_codegen.c
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -target-cpu core2 -fopenmp -x c -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c -triple x86_64-apple-darwin10 -target-cpu core2 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c -triple x86_64-apple-darwin10 -target-cpu core2 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -target-cpu core2 -fopenmp-simd -x c -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c -triple x86_64-apple-darwin10 -target-cpu core2 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c -triple x86_64-apple-darwin10 -target-cpu core2 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
// REQUIRES: x86-registered-target
#ifndef HEADER
@@ -137,7 +142,7 @@ int main() {
dx = dv;
// CHECK: [[LD:%.+]] = load x86_fp80, x86_fp80*
// CHECK: [[BITCAST:%.+]] = bitcast x86_fp80* [[LDTEMP:%.*]] to i8*
-// CHECK: call void @llvm.memset.p0i8.i64(i8* [[BITCAST]], i8 0, i64 16, i32 16, i1 false)
+// CHECK: call void @llvm.memset.p0i8.i64(i8* align 16 [[BITCAST]], i8 0, i64 16, i1 false)
// CHECK: store x86_fp80 [[LD]], x86_fp80* [[LDTEMP]]
// CHECK: [[BITCAST:%.+]] = bitcast x86_fp80* [[LDTEMP:%.*]] to i128*
// CHECK: [[LD:%.+]] = load i128, i128* [[BITCAST]]
@@ -226,7 +231,7 @@ int main() {
// CHECK: load i64, i64*
// CHECK: [[VAL:%.+]] = uitofp i64 %{{.+}} to x86_fp80
// CHECK: [[BITCAST:%.+]] = bitcast x86_fp80* [[TEMP:%.+]] to i8*
-// CHECK: call void @llvm.memset.p0i8.i64(i8* [[BITCAST]], i8 0, i64 16, i32 16, i1 false)
+// CHECK: call void @llvm.memset.p0i8.i64(i8* align 16 [[BITCAST]], i8 0, i64 16, i1 false)
// CHECK: store x86_fp80 [[VAL]], x86_fp80* [[TEMP]]
// CHECK: [[BITCAST:%.+]] = bitcast x86_fp80* [[TEMP]] to i128*
// CHECK: [[VAL:%.+]] = load i128, i128* [[BITCAST]]
diff --git a/test/OpenMP/barrier_ast_print.cpp b/test/OpenMP/barrier_ast_print.cpp
index fd03a9ab0ffe..a8db2172c192 100644
--- a/test/OpenMP/barrier_ast_print.cpp
+++ b/test/OpenMP/barrier_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -24,7 +28,7 @@ T tmain(T argc) {
return a + argc;
}
// CHECK: static T a;
-// CHECK-NEXT: #pragma omp barrier
+// CHECK-NEXT: #pragma omp barrier{{$}}
// CHECK: static int a;
// CHECK-NEXT: #pragma omp barrier
// CHECK: static char a;
diff --git a/test/OpenMP/barrier_codegen.cpp b/test/OpenMP/barrier_codegen.cpp
index f335935050c6..aa3358cede7c 100644
--- a/test/OpenMP/barrier_codegen.cpp
+++ b/test/OpenMP/barrier_codegen.cpp
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-unknown -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/barrier_messages.cpp b/test/OpenMP/barrier_messages.cpp
index 7d79445d2857..137453a89326 100644
--- a/test/OpenMP/barrier_messages.cpp
+++ b/test/OpenMP/barrier_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
template <class T>
T tmain(T argc) {
#pragma omp barrier
diff --git a/test/OpenMP/cancel_ast_print.cpp b/test/OpenMP/cancel_ast_print.cpp
index be550843706c..b376d4ec2807 100644
--- a/test/OpenMP/cancel_ast_print.cpp
+++ b/test/OpenMP/cancel_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -22,7 +26,7 @@ int main (int argc, char **argv) {
}
// CHECK-NEXT: #pragma omp sections
// CHECK: {
-// CHECK: #pragma omp cancel sections
+// CHECK: #pragma omp cancel sections{{$}}
// CHECK: }
#pragma omp for
for (int i = 0; i < argc; ++i) {
diff --git a/test/OpenMP/cancel_codegen.cpp b/test/OpenMP/cancel_codegen.cpp
index 2ff9dcc186c9..75fd5e46618c 100644
--- a/test/OpenMP/cancel_codegen.cpp
+++ b/test/OpenMP/cancel_codegen.cpp
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -triple x86_64-apple-darwin13.4.0 -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple x86_64-apple-darwin13.4.0 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -triple x86_64-apple-darwin13.4.0 -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -triple x86_64-apple-darwin13.4.0 -emit-llvm -o - %s | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple x86_64-apple-darwin13.4.0 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -triple x86_64-apple-darwin13.4.0 -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -15,7 +20,7 @@ int main (int argc, char **argv) {
#pragma omp barrier
argv[0][0] += argc;
}
-// CHECK: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
#pragma omp sections
{
#pragma omp cancel sections
@@ -23,7 +28,7 @@ int main (int argc, char **argv) {
// CHECK: call void @__kmpc_for_static_init_4(
// CHECK: call i32 @__kmpc_cancel(
// CHECK: call void @__kmpc_for_static_fini(
-// CHECK: call void @__kmpc_barrier(%ident_t*
+// CHECK: call void @__kmpc_barrier(%struct.ident_t*
#pragma omp sections
{
#pragma omp cancel sections
@@ -33,14 +38,14 @@ int main (int argc, char **argv) {
}
}
// CHECK: call void @__kmpc_for_static_init_4(
-// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancel(%ident_t* {{[^,]+}}, i32 [[GTID]], i32 3)
+// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancel(%struct.ident_t* {{[^,]+}}, i32 [[GTID]], i32 3)
// CHECK: [[CMP:%.+]] = icmp ne i32 [[RES]], 0
// CHECK: br i1 [[CMP]], label %[[EXIT:[^,].+]], label %[[CONTINUE:.+]]
// CHECK: [[EXIT]]
// CHECK: br label
// CHECK: [[CONTINUE]]
// CHECK: br label
-// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancel(%ident_t* {{[^,]+}}, i32 [[GTID]], i32 3)
+// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancel(%struct.ident_t* {{[^,]+}}, i32 [[GTID]], i32 3)
// CHECK: [[CMP:%.+]] = icmp ne i32 [[RES]], 0
// CHECK: br i1 [[CMP]], label %[[EXIT:[^,].+]], label %[[CONTINUE:.+]]
// CHECK: [[EXIT]]
@@ -57,7 +62,7 @@ for (int i = 0; i < argc; ++i) {
// CHECK: [[BOOL:%.+]] = fcmp une float [[FLAG]], 0.000000e+00
// CHECK: br i1 [[BOOL]], label %[[THEN:[^,]+]], label %[[ELSE:[^,]+]]
// CHECK: [[THEN]]
-// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancel(%ident_t* {{[^,]+}}, i32 [[GTID]], i32 2)
+// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancel(%struct.ident_t* {{[^,]+}}, i32 [[GTID]], i32 2)
// CHECK: [[CMP:%.+]] = icmp ne i32 [[RES]], 0
// CHECK: br i1 [[CMP]], label %[[EXIT:[^,].+]], label %[[CONTINUE:.+]]
// CHECK: [[EXIT]]
@@ -67,7 +72,7 @@ for (int i = 0; i < argc; ++i) {
// CHECK: [[ELSE]]
// CHECK: br label
// CHECK: call void @__kmpc_for_static_fini(
-// CHECK: call void @__kmpc_barrier(%ident_t*
+// CHECK: call void @__kmpc_barrier(%struct.ident_t*
#pragma omp task
{
#pragma omp cancel taskgroup
@@ -78,7 +83,7 @@ for (int i = 0; i < argc; ++i) {
{
#pragma omp cancel sections
}
-// CHECK: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
#pragma omp parallel sections
{
#pragma omp cancel sections
@@ -87,14 +92,14 @@ for (int i = 0; i < argc; ++i) {
#pragma omp cancel sections
}
}
-// CHECK: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
int r = 0;
#pragma omp parallel for reduction(+: r)
for (int i = 0; i < argc; ++i) {
#pragma omp cancel for
r += i;
}
-// CHECK: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
return argc;
}
@@ -103,20 +108,20 @@ for (int i = 0; i < argc; ++i) {
// CHECK: [[BOOL:%.+]] = fcmp une float [[FLAG]], 0.000000e+00
// CHECK: br i1 [[BOOL]], label %[[THEN:[^,]+]], label %[[ELSE:[^,]+]]
// CHECK: [[THEN]]
-// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancel(%ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 1)
+// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancel(%struct.ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 1)
// CHECK: [[CMP:%.+]] = icmp ne i32 [[RES]], 0
// CHECK: br i1 [[CMP]], label %[[EXIT:[^,]+]],
// CHECK: [[EXIT]]
// CHECK: br label %[[RETURN:.+]]
// CHECK: [[ELSE]]
// The barrier directive should now call __kmpc_cancel_barrier
-// CHECK: call i32 @__kmpc_cancel_barrier(%ident_t*
+// CHECK: call i32 @__kmpc_cancel_barrier(%struct.ident_t*
// CHECK: br label
// CHECK: [[RETURN]]
// CHECK: ret void
// CHECK: define internal i32 @{{[^(]+}}(i32
-// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancel(%ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 4)
+// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancel(%struct.ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 4)
// CHECK: [[CMP:%.+]] = icmp ne i32 [[RES]], 0
// CHECK: br i1 [[CMP]], label %[[EXIT:[^,]+]],
// CHECK: [[EXIT]]
@@ -132,14 +137,14 @@ for (int i = 0; i < argc; ++i) {
// CHECK: define internal void @{{[^(]+}}(i32* {{[^,]+}}, i32* {{[^,]+}})
// CHECK: call void @__kmpc_for_static_init_4(
-// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancel(%ident_t* {{[^,]+}}, i32 [[GTID:%.+]], i32 3)
+// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancel(%struct.ident_t* {{[^,]+}}, i32 [[GTID:%.+]], i32 3)
// CHECK: [[CMP:%.+]] = icmp ne i32 [[RES]], 0
// CHECK: br i1 [[CMP]], label %[[EXIT:[^,].+]], label %[[CONTINUE:.+]]
// CHECK: [[EXIT]]
// CHECK: br label
// CHECK: [[CONTINUE]]
// CHECK: br label
-// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancel(%ident_t* {{[^,]+}}, i32 [[GTID]], i32 3)
+// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancel(%struct.ident_t* {{[^,]+}}, i32 [[GTID]], i32 3)
// CHECK: [[CMP:%.+]] = icmp ne i32 [[RES]], 0
// CHECK: br i1 [[CMP]], label %[[EXIT:[^,].+]], label %[[CONTINUE:.+]]
// CHECK: [[EXIT]]
@@ -151,7 +156,7 @@ for (int i = 0; i < argc; ++i) {
// CHECK: define internal void @{{[^(]+}}(i32* {{[^,]+}}, i32* {{[^,]+}},
// CHECK: call void @__kmpc_for_static_init_4(
-// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancel(%ident_t* {{[^,]+}}, i32 [[GTID:%.+]], i32 2)
+// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancel(%struct.ident_t* {{[^,]+}}, i32 [[GTID:%.+]], i32 2)
// CHECK: [[CMP:%.+]] = icmp ne i32 [[RES]], 0
// CHECK: br i1 [[CMP]], label %[[EXIT:[^,].+]], label %[[CONTINUE:.+]]
// CHECK: [[EXIT]]
diff --git a/test/OpenMP/cancel_codegen_cleanup.cpp b/test/OpenMP/cancel_codegen_cleanup.cpp
index 5a297bd377b1..94d49068433a 100644
--- a/test/OpenMP/cancel_codegen_cleanup.cpp
+++ b/test/OpenMP/cancel_codegen_cleanup.cpp
@@ -1,5 +1,8 @@
// RUN: %clang_cc1 -std=c++11 -fopenmp -fopenmp-version=45 -triple x86_64-apple-darwin13.4.0 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -fopenmp-simd -fopenmp-version=45 -triple x86_64-apple-darwin13.4.0 -emit-llvm -o - %s | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
//CHECK: call i32 @__kmpc_cancel
//CHECK: br {{.*}}label %[[EXIT:[^,].+]], label %[[CONTINUE:.+]]
//CHECK: [[EXIT]]:
diff --git a/test/OpenMP/cancel_if_messages.cpp b/test/OpenMP/cancel_if_messages.cpp
index 426ac49cfdfe..dc24fa4c9979 100644
--- a/test/OpenMP/cancel_if_messages.cpp
+++ b/test/OpenMP/cancel_if_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/cancel_messages.cpp b/test/OpenMP/cancel_messages.cpp
index f8bbe2c36bea..28f22d17eaf5 100644
--- a/test/OpenMP/cancel_messages.cpp
+++ b/test/OpenMP/cancel_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
int main(int argc, char **argv) {
#pragma omp cancellation // expected-error {{expected an OpenMP directive}}
#pragma omp cancel // expected-error {{one of 'for', 'parallel', 'sections' or 'taskgroup' is expected}}
diff --git a/test/OpenMP/cancellation_point_ast_print.cpp b/test/OpenMP/cancellation_point_ast_print.cpp
index c8b133cbac68..d27d2b75fd4c 100644
--- a/test/OpenMP/cancellation_point_ast_print.cpp
+++ b/test/OpenMP/cancellation_point_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -14,7 +18,7 @@ int main (int argc, char **argv) {
}
// CHECK: #pragma omp parallel
// CHECK-NEXT: {
-// CHECK-NEXT: #pragma omp cancellation point parallel
+// CHECK-NEXT: #pragma omp cancellation point parallel{{$}}
// CHECK-NEXT: }
#pragma omp sections
{
diff --git a/test/OpenMP/cancellation_point_codegen.cpp b/test/OpenMP/cancellation_point_codegen.cpp
index de65c114027a..a67015fe43f5 100644
--- a/test/OpenMP/cancellation_point_codegen.cpp
+++ b/test/OpenMP/cancellation_point_codegen.cpp
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -fopenmp -triple x86_64-apple-darwin13.4.0 -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-apple-darwin13.4.0 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -triple x86_64-apple-darwin13.4.0 -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -triple x86_64-apple-darwin13.4.0 -emit-llvm -o - %s | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-apple-darwin13.4.0 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -triple x86_64-apple-darwin13.4.0 -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -13,7 +18,7 @@ int main (int argc, char **argv) {
#pragma omp cancel parallel
argv[0][0] = argc;
}
-// CHECK: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
#pragma omp sections
{
{
@@ -22,7 +27,7 @@ int main (int argc, char **argv) {
}
}
// CHECK: call void @__kmpc_for_static_init_4(
-// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancellationpoint(%ident_t* {{[^,]+}}, i32 [[GTID]], i32 3)
+// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancellationpoint(%struct.ident_t* {{[^,]+}}, i32 [[GTID]], i32 3)
// CHECK: [[CMP:%.+]] = icmp ne i32 [[RES]], 0
// CHECK: br i1 [[CMP]], label %[[EXIT:[^,].+]], label %[[CONTINUE:.+]]
// CHECK: [[EXIT]]
@@ -30,7 +35,7 @@ int main (int argc, char **argv) {
// CHECK: [[CONTINUE]]
// CHECK: br label
// CHECK: call void @__kmpc_for_static_fini(
-// CHECK: call void @__kmpc_barrier(%ident_t*
+// CHECK: call void @__kmpc_barrier(%struct.ident_t*
#pragma omp sections
{
#pragma omp cancellation point sections
@@ -41,14 +46,14 @@ int main (int argc, char **argv) {
}
}
// CHECK: call void @__kmpc_for_static_init_4(
-// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancellationpoint(%ident_t* {{[^,]+}}, i32 [[GTID]], i32 3)
+// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancellationpoint(%struct.ident_t* {{[^,]+}}, i32 [[GTID]], i32 3)
// CHECK: [[CMP:%.+]] = icmp ne i32 [[RES]], 0
// CHECK: br i1 [[CMP]], label %[[EXIT:[^,].+]], label %[[CONTINUE:.+]]
// CHECK: [[EXIT]]
// CHECK: br label
// CHECK: [[CONTINUE]]
// CHECK: br label
-// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancellationpoint(%ident_t* {{[^,]+}}, i32 [[GTID]], i32 3)
+// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancellationpoint(%struct.ident_t* {{[^,]+}}, i32 [[GTID]], i32 3)
// CHECK: [[CMP:%.+]] = icmp ne i32 [[RES]], 0
// CHECK: br i1 [[CMP]], label %[[EXIT:[^,].+]], label %[[CONTINUE:.+]]
// CHECK: [[EXIT]]
@@ -62,7 +67,7 @@ for (int i = 0; i < argc; ++i) {
#pragma omp cancel for
}
// CHECK: call void @__kmpc_for_static_init_4(
-// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancellationpoint(%ident_t* {{[^,]+}}, i32 [[GTID]], i32 2)
+// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancellationpoint(%struct.ident_t* {{[^,]+}}, i32 [[GTID]], i32 2)
// CHECK: [[CMP:%.+]] = icmp ne i32 [[RES]], 0
// CHECK: br i1 [[CMP]], label %[[EXIT:[^,].+]], label %[[CONTINUE:.+]]
// CHECK: [[EXIT]]
@@ -70,7 +75,7 @@ for (int i = 0; i < argc; ++i) {
// CHECK: [[CONTINUE]]
// CHECK: br label
// CHECK: call void @__kmpc_for_static_fini(
-// CHECK: call void @__kmpc_barrier(%ident_t*
+// CHECK: call void @__kmpc_barrier(%struct.ident_t*
#pragma omp task
{
#pragma omp cancellation point taskgroup
@@ -91,7 +96,7 @@ for (int i = 0; i < argc; ++i) {
#pragma omp cancel sections
}
}
-// CHECK: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
#pragma omp parallel sections
{
{
@@ -103,18 +108,18 @@ for (int i = 0; i < argc; ++i) {
#pragma omp cancellation point sections
}
}
-// CHECK: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
#pragma omp parallel for
for (int i = 0; i < argc; ++i) {
#pragma omp cancellation point for
#pragma omp cancel for
}
-// CHECK: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
return argc;
}
// CHECK: define internal void @{{[^(]+}}(i32* {{[^,]+}}, i32* {{[^,]+}},
-// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancellationpoint(%ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 1)
+// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancellationpoint(%struct.ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 1)
// CHECK: [[CMP:%.+]] = icmp ne i32 [[RES]], 0
// CHECK: br i1 [[CMP]], label %[[EXIT:[^,]+]],
// CHECK: [[EXIT]]
@@ -123,7 +128,7 @@ for (int i = 0; i < argc; ++i) {
// CHECK: ret void
// CHECK: define internal i32 @{{[^(]+}}(i32
-// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancellationpoint(%ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 4)
+// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancellationpoint(%struct.ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 4)
// CHECK: [[CMP:%.+]] = icmp ne i32 [[RES]], 0
// CHECK: br i1 [[CMP]], label %[[EXIT:[^,]+]],
// CHECK: [[EXIT]]
@@ -132,7 +137,7 @@ for (int i = 0; i < argc; ++i) {
// CHECK: ret i32 0
// CHECK: define internal i32 @{{[^(]+}}(i32
-// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancellationpoint(%ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 4)
+// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancellationpoint(%struct.ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 4)
// CHECK: [[CMP:%.+]] = icmp ne i32 [[RES]], 0
// CHECK: br i1 [[CMP]], label %[[EXIT:[^,]+]],
// CHECK: [[EXIT]]
@@ -142,7 +147,7 @@ for (int i = 0; i < argc; ++i) {
// CHECK: define internal void @{{[^(]+}}(i32* {{[^,]+}}, i32* {{[^,]+}})
// CHECK: call void @__kmpc_for_static_init_4(
-// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancellationpoint(%ident_t* {{[^,]+}}, i32 [[GTID:%.+]], i32 3)
+// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancellationpoint(%struct.ident_t* {{[^,]+}}, i32 [[GTID:%.+]], i32 3)
// CHECK: [[CMP:%.+]] = icmp ne i32 [[RES]], 0
// CHECK: br i1 [[CMP]], label %[[EXIT:[^,].+]], label %[[CONTINUE:.+]]
// CHECK: [[EXIT]]
@@ -154,14 +159,14 @@ for (int i = 0; i < argc; ++i) {
// CHECK: define internal void @{{[^(]+}}(i32* {{[^,]+}}, i32* {{[^,]+}})
// CHECK: call void @__kmpc_for_static_init_4(
-// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancellationpoint(%ident_t* {{[^,]+}}, i32 [[GTID:%.+]], i32 3)
+// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancellationpoint(%struct.ident_t* {{[^,]+}}, i32 [[GTID:%.+]], i32 3)
// CHECK: [[CMP:%.+]] = icmp ne i32 [[RES]], 0
// CHECK: br i1 [[CMP]], label %[[EXIT:[^,].+]], label %[[CONTINUE:.+]]
// CHECK: [[EXIT]]
// CHECK: br label
// CHECK: [[CONTINUE]]
// CHECK: br label
-// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancellationpoint(%ident_t* {{[^,]+}}, i32 [[GTID]], i32 3)
+// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancellationpoint(%struct.ident_t* {{[^,]+}}, i32 [[GTID]], i32 3)
// CHECK: [[CMP:%.+]] = icmp ne i32 [[RES]], 0
// CHECK: br i1 [[CMP]], label %[[EXIT:[^,].+]], label %[[CONTINUE:.+]]
// CHECK: [[EXIT]]
@@ -173,7 +178,7 @@ for (int i = 0; i < argc; ++i) {
// CHECK: define internal void @{{[^(]+}}(i32* {{[^,]+}}, i32* {{[^,]+}},
// CHECK: call void @__kmpc_for_static_init_4(
-// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancellationpoint(%ident_t* {{[^,]+}}, i32 [[GTID:%.+]], i32 2)
+// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancellationpoint(%struct.ident_t* {{[^,]+}}, i32 [[GTID:%.+]], i32 2)
// CHECK: [[CMP:%.+]] = icmp ne i32 [[RES]], 0
// CHECK: br i1 [[CMP]], label %[[EXIT:[^,].+]], label %[[CONTINUE:.+]]
// CHECK: [[EXIT]]
diff --git a/test/OpenMP/cancellation_point_messages.cpp b/test/OpenMP/cancellation_point_messages.cpp
index 21b0e9c2fa2d..8bf5b3d55fdd 100644
--- a/test/OpenMP/cancellation_point_messages.cpp
+++ b/test/OpenMP/cancellation_point_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
int main(int argc, char **argv) {
#pragma omp cancellation // expected-error {{expected an OpenMP directive}}
#pragma omp cancellation point // expected-error {{one of 'for', 'parallel', 'sections' or 'taskgroup' is expected}}
diff --git a/test/OpenMP/capturing_in_templates.cpp b/test/OpenMP/capturing_in_templates.cpp
index 9b2d9d304e0a..97a935214bdb 100644
--- a/test/OpenMP/capturing_in_templates.cpp
+++ b/test/OpenMP/capturing_in_templates.cpp
@@ -1,4 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-ibm-linux-gnu -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-ibm-linux-gnu -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
template <typename T1, typename T2>
diff --git a/test/OpenMP/constexpr_codegen.cpp b/test/OpenMP/constexpr_codegen.cpp
new file mode 100644
index 000000000000..f1fa4ac2a9ef
--- /dev/null
+++ b/test/OpenMP/constexpr_codegen.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -triple x86_64-unknown-unknown -x c++ -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -debug-info-kind=limited -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -triple x86_64-unknown-unknown -x c++ -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -debug-info-kind=limited -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
+// expected-no-diagnostics
+//
+#ifndef HEADER
+#define HEADER
+
+// CHECK: @{{.*}}Foo{{.*}}bar{{.*}} = constant i32 1,
+
+// Section A - Define a class with a static constexpr data member.
+struct Foo {
+ static constexpr int bar = 1;
+};
+
+// Section B - ODR-use the data member.
+void F(const int &);
+void Test() { F(Foo::bar); }
+
+// Section C - Define the data member.
+constexpr int Foo::bar;
+#endif
+
diff --git a/test/OpenMP/critical_ast_print.cpp b/test/OpenMP/critical_ast_print.cpp
index 0579d030a8bc..f51145e5845b 100644
--- a/test/OpenMP/critical_ast_print.cpp
+++ b/test/OpenMP/critical_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -10,10 +14,10 @@ void foo() {}
// CHECK: template <typename T, int N> int tmain(T argc, char **argv)
// CHECK: static int a;
-// CHECK-NEXT: #pragma omp critical
+// CHECK-NEXT: #pragma omp critical{{$}}
// CHECK-NEXT: a = 2;
// CHECK-NEXT: ++a;
-// CHECK-NEXT: #pragma omp critical (the_name) hint(N)
+// CHECK-NEXT: #pragma omp critical (the_name) hint(N){{$}}
// CHECK-NEXT: foo();
// CHECK-NEXT: return N;
// CHECK: template<> int tmain<int, 4>(int argc, char **argv)
diff --git a/test/OpenMP/critical_codegen.cpp b/test/OpenMP/critical_codegen.cpp
index f4e449a22370..ba540059dc89 100644
--- a/test/OpenMP/critical_codegen.cpp
+++ b/test/OpenMP/critical_codegen.cpp
@@ -2,6 +2,12 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck %s --check-prefix=TERM_DEBUG
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/critical_messages.cpp b/test/OpenMP/critical_messages.cpp
index bb5ec00fdbf1..a04d2e522331 100644
--- a/test/OpenMP/critical_messages.cpp
+++ b/test/OpenMP/critical_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
int foo();
template<typename T, int N>
diff --git a/test/OpenMP/debug-info-openmp-array.cpp b/test/OpenMP/debug-info-openmp-array.cpp
index 19bf2a284ad6..e6de4763fbbc 100644
--- a/test/OpenMP/debug-info-openmp-array.cpp
+++ b/test/OpenMP/debug-info-openmp-array.cpp
@@ -1,4 +1,7 @@
// RUN: %clang_cc1 -fopenmp -x c++ %s -verify -debug-info-kind=limited -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -fopenmp-simd -x c++ %s -verify -debug-info-kind=limited -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
void f(int m) {
diff --git a/test/OpenMP/declare_reduction_ast_print.c b/test/OpenMP/declare_reduction_ast_print.c
index 7b97a7c1da7c..239b1cfd4432 100644
--- a/test/OpenMP/declare_reduction_ast_print.c
+++ b/test/OpenMP/declare_reduction_ast_print.c
@@ -1,13 +1,17 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
#pragma omp declare reduction(+ : int, char : omp_out *= omp_in)
-// CHECK: #pragma omp declare reduction (+ : int : omp_out *= omp_in)
+// CHECK: #pragma omp declare reduction (+ : int : omp_out *= omp_in){{$}}
// CHECK-NEXT: #pragma omp declare reduction (+ : char : omp_out *= omp_in)
#pragma omp declare reduction(fun : float : omp_out += omp_in) initializer(omp_priv = omp_orig + 15)
diff --git a/test/OpenMP/declare_reduction_ast_print.cpp b/test/OpenMP/declare_reduction_ast_print.cpp
index 816ff7937663..a8ca529c456b 100644
--- a/test/OpenMP/declare_reduction_ast_print.cpp
+++ b/test/OpenMP/declare_reduction_ast_print.cpp
@@ -1,13 +1,17 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
#pragma omp declare reduction(+ : int, char : omp_out *= omp_in)
-// CHECK: #pragma omp declare reduction (+ : int : omp_out *= omp_in)
+// CHECK: #pragma omp declare reduction (+ : int : omp_out *= omp_in){{$}}
// CHECK-NEXT: #pragma omp declare reduction (+ : char : omp_out *= omp_in)
template <class T>
diff --git a/test/OpenMP/declare_reduction_codegen.c b/test/OpenMP/declare_reduction_codegen.c
index 579b664a512a..8ccb8ccbaf40 100644
--- a/test/OpenMP/declare_reduction_codegen.c
+++ b/test/OpenMP/declare_reduction_codegen.c
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -fopenmp -x c -emit-llvm %s -triple %itanium_abi_triple -o - -femit-all-decls -disable-llvm-passes | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c -triple %itanium_abi_triple -emit-pch -o %t %s -femit-all-decls -disable-llvm-passes
// RUN: %clang_cc1 -fopenmp -x c -triple %itanium_abi_triple -include-pch %t -verify %s -emit-llvm -o - -femit-all-decls -disable-llvm-passes | FileCheck --check-prefix=CHECK-LOAD %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c -emit-llvm %s -triple %itanium_abi_triple -o - -femit-all-decls -disable-llvm-passes | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c -triple %itanium_abi_triple -emit-pch -o %t %s -femit-all-decls -disable-llvm-passes
+// RUN: %clang_cc1 -fopenmp-simd -x c -triple %itanium_abi_triple -include-pch %t -verify %s -emit-llvm -o - -femit-all-decls -disable-llvm-passes | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
diff --git a/test/OpenMP/declare_reduction_codegen.cpp b/test/OpenMP/declare_reduction_codegen.cpp
index ae6e047d9483..90dbd47214df 100644
--- a/test/OpenMP/declare_reduction_codegen.cpp
+++ b/test/OpenMP/declare_reduction_codegen.cpp
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -fopenmp -x c++ -emit-llvm %s -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -o - -femit-all-decls -disable-llvm-passes | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -emit-pch -o %t %s -femit-all-decls -disable-llvm-passes
// RUN: %clang_cc1 -fopenmp -x c++ -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -femit-all-decls -disable-llvm-passes | FileCheck --check-prefix=CHECK-LOAD %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -emit-llvm %s -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -o - -femit-all-decls -disable-llvm-passes | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -emit-pch -o %t %s -femit-all-decls -disable-llvm-passes
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -femit-all-decls -disable-llvm-passes | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
@@ -21,7 +26,7 @@ void add(short &out, short &in) {}
// CHECK: foo_reduction_array
void foo_reduction_array() {
short y[1];
- // CHECK: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+ // CHECK: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
#pragma omp parallel for reduction(my_add : y)
for (int i = 0; i < 1; i++) {
}
@@ -143,9 +148,9 @@ int main() {
#pragma omp parallel reduction(fun : sss)
{
}
- // CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
- // CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
- // CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call({{[^@]*}} @{{[^@]*}}[[REGION:@[^ ]+]]
+ // CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+ // CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+ // CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call({{[^@]*}} @{{[^@]*}}[[REGION:@[^ ]+]]
// CHECK-LABEL: work
work<A>();
// CHECK-LABEL: foo
diff --git a/test/OpenMP/declare_reduction_messages.c b/test/OpenMP/declare_reduction_messages.c
index fb9eacc90aa2..39387c795a3c 100644
--- a/test/OpenMP/declare_reduction_messages.c
+++ b/test/OpenMP/declare_reduction_messages.c
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
int temp; // expected-note 6 {{'temp' declared here}}
#pragma omp declare reduction // expected-error {{expected '(' after 'declare reduction'}}
diff --git a/test/OpenMP/declare_reduction_messages.cpp b/test/OpenMP/declare_reduction_messages.cpp
index 3e5a15ee3dd9..f22f92485a57 100644
--- a/test/OpenMP/declare_reduction_messages.cpp
+++ b/test/OpenMP/declare_reduction_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -std=c++11 %s
+
int temp; // expected-note 7 {{'temp' declared here}}
#pragma omp declare reduction // expected-error {{expected '(' after 'declare reduction'}}
diff --git a/test/OpenMP/declare_simd_ast_print.c b/test/OpenMP/declare_simd_ast_print.c
index 04fd73f272d8..414b01038793 100644
--- a/test/OpenMP/declare_simd_ast_print.c
+++ b/test/OpenMP/declare_simd_ast_print.c
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -12,10 +16,10 @@
#pragma omp declare simd notinbranch simdlen(2), uniform(s1, s2) linear(d: s1)
void add_1(float *d, int s1, float *s2, double b[]) __attribute__((cold));
-// CHECK: #pragma omp declare simd notinbranch simdlen(2) uniform(s1, s2) linear(val(d): s1)
-// CHECK-NEXT: #pragma omp declare simd inbranch uniform(d) linear(val(s1): 32) linear(val(s2): 32)
-// CHECK-NEXT: #pragma omp declare simd simdlen(32) aligned(d) aligned(b)
-// CHECK-NEXT: #pragma omp declare simd aligned(b: 64)
+// CHECK: #pragma omp declare simd notinbranch simdlen(2) uniform(s1, s2) linear(val(d): s1){{$}}
+// CHECK-NEXT: #pragma omp declare simd inbranch uniform(d) linear(val(s1): 32) linear(val(s2): 32){{$}}
+// CHECK-NEXT: #pragma omp declare simd simdlen(32) aligned(d) aligned(b){{$}}
+// CHECK-NEXT: #pragma omp declare simd aligned(b: 64){{$}}
// CHECK-NEXT: void add_1(float *d, int s1, float *s2, double b[]) __attribute__((cold))
#endif
diff --git a/test/OpenMP/declare_simd_ast_print.cpp b/test/OpenMP/declare_simd_ast_print.cpp
index 632e038e221d..c09f8b42e6d5 100644
--- a/test/OpenMP/declare_simd_ast_print.cpp
+++ b/test/OpenMP/declare_simd_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -80,8 +84,8 @@ private:
// CHECK-NEXT: float taddpf(float *a, T *&b) {
// CHECK-NEXT: return *a + *b;
// CHECK-NEXT: }
-// CHECK: #pragma omp declare simd
-// CHECK-NEXT: #pragma omp declare simd
+// CHECK: #pragma omp declare simd uniform(this, b)
+// CHECK-NEXT: #pragma omp declare simd{{$}}
// CHECK-NEXT: int tadd(int b) {
// CHECK-NEXT: return this->x[b] + b;
// CHECK-NEXT: }
diff --git a/test/OpenMP/declare_simd_codegen.cpp b/test/OpenMP/declare_simd_codegen.cpp
index 9ae476677c42..4ac0b7f03a0e 100644
--- a/test/OpenMP/declare_simd_codegen.cpp
+++ b/test/OpenMP/declare_simd_codegen.cpp
@@ -1,10 +1,17 @@
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -x c++ -emit-llvm %s -o - -femit-all-decls | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -include-pch %t -verify %s -emit-llvm -o - -femit-all-decls | FileCheck %s
+
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -x c++ -emit-llvm %s -o - -femit-all-decls | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -include-pch %t -verify %s -emit-llvm -o - -femit-all-decls | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
+void add_1(float *d);
+
#pragma omp declare simd linear(d : 8)
#pragma omp declare simd inbranch simdlen(32)
#pragma omp declare simd notinbranch
@@ -15,6 +22,8 @@ void add_1(float *d);
#pragma omp declare simd notinbranch
void add_1(float *d) {}
+void add_1(float *d);
+
#pragma omp declare simd linear(d : 8)
#pragma omp declare simd inbranch simdlen(32)
#pragma omp declare simd notinbranch
diff --git a/test/OpenMP/declare_simd_messages.cpp b/test/OpenMP/declare_simd_messages.cpp
index af46283f9a57..dab7d054e786 100644
--- a/test/OpenMP/declare_simd_messages.cpp
+++ b/test/OpenMP/declare_simd_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -triple=x86_64-pc-win32 -verify -fopenmp -x c++ -std=c++11 -fms-extensions -Wno-pragma-pack %s
+// RUN: %clang_cc1 -triple=x86_64-pc-win32 -verify -fopenmp-simd -x c++ -std=c++11 -fms-extensions -Wno-pragma-pack %s
+
// expected-error@+1 {{expected an OpenMP directive}}
#pragma omp declare
diff --git a/test/OpenMP/declare_target_ast_print.cpp b/test/OpenMP/declare_target_ast_print.cpp
index 6c59563d1d1e..bd1acc28dc6c 100644
--- a/test/OpenMP/declare_target_ast_print.cpp
+++ b/test/OpenMP/declare_target_ast_print.cpp
@@ -1,17 +1,21 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
#pragma omp declare target
-// CHECK: #pragma omp declare target
+// CHECK: #pragma omp declare target{{$}}
void foo() {}
// CHECK-NEXT: void foo()
#pragma omp end declare target
-// CHECK: #pragma omp end declare target
+// CHECK: #pragma omp end declare target{{$}}
extern "C" {
#pragma omp declare target
@@ -83,41 +87,41 @@ int a1;
void f1() {
}
#pragma omp declare target (a1, f1)
-// CHECK: #pragma omp declare target
+// CHECK: #pragma omp declare target{{$}}
// CHECK: int a1;
-// CHECK: #pragma omp end declare target
-// CHECK: #pragma omp declare target
+// CHECK: #pragma omp end declare target{{$}}
+// CHECK: #pragma omp declare target{{$}}
// CHECK: void f1()
-// CHECK: #pragma omp end declare target
+// CHECK: #pragma omp end declare target{{$}}
int b1, b2, b3;
void f2() {
}
#pragma omp declare target to(b1) to(b2), to(b3, f2)
-// CHECK: #pragma omp declare target
+// CHECK: #pragma omp declare target{{$}}
// CHECK: int b1;
-// CHECK: #pragma omp end declare target
-// CHECK: #pragma omp declare target
+// CHECK: #pragma omp end declare target{{$}}
+// CHECK: #pragma omp declare target{{$}}
// CHECK: int b2;
-// CHECK: #pragma omp end declare target
-// CHECK: #pragma omp declare target
+// CHECK: #pragma omp end declare target{{$}}
+// CHECK: #pragma omp declare target{{$}}
// CHECK: int b3;
-// CHECK: #pragma omp end declare target
-// CHECK: #pragma omp declare target
+// CHECK: #pragma omp end declare target{{$}}
+// CHECK: #pragma omp declare target{{$}}
// CHECK: void f2()
-// CHECK: #pragma omp end declare target
+// CHECK: #pragma omp end declare target{{$}}
int c1, c2, c3;
#pragma omp declare target link(c1) link(c2), link(c3)
-// CHECK: #pragma omp declare target link
+// CHECK: #pragma omp declare target link{{$}}
// CHECK: int c1;
-// CHECK: #pragma omp end declare target
-// CHECK: #pragma omp declare target link
+// CHECK: #pragma omp end declare target{{$}}
+// CHECK: #pragma omp declare target link{{$}}
// CHECK: int c2;
-// CHECK: #pragma omp end declare target
-// CHECK: #pragma omp declare target link
+// CHECK: #pragma omp end declare target{{$}}
+// CHECK: #pragma omp declare target link{{$}}
// CHECK: int c3;
-// CHECK: #pragma omp end declare target
+// CHECK: #pragma omp end declare target{{$}}
struct SSSt {
#pragma omp declare target
diff --git a/test/OpenMP/declare_target_codegen.cpp b/test/OpenMP/declare_target_codegen.cpp
new file mode 100644
index 000000000000..a221387c7312
--- /dev/null
+++ b/test/OpenMP/declare_target_codegen.cpp
@@ -0,0 +1,94 @@
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -emit-pch -o %t
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o -| FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -emit-pch -o %t
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify -o - | FileCheck %s --check-prefix SIMD-ONLY
+
+// expected-no-diagnostics
+
+// SIMD-ONLY-NOT: {{__kmpc|__tgt}}
+
+// CHECK-NOT: define {{.*}}{{baz1|baz4|maini1}}
+// CHECK-DAG: @{{.*}}maini1{{.*}}aaa = internal global i64 23,
+// CHECK-DAG: @b = global i32 15,
+// CHECK-DAG: @d = global i32 0,
+// CHECK-DAG: @c = external global i32,
+// CHECK-DAG: @globals = global %struct.S zeroinitializer,
+// CHECK-DAG: @{{.+}}stat = weak_odr global %struct.S zeroinitializer,
+// CHECK-DAG: @llvm.used = appending global [2 x i8*] [i8* bitcast (void ()* @__omp_offloading__{{.+}}_globals_l[[@LINE+42]]_ctor to i8*), i8* bitcast (void ()* @__omp_offloading__{{.+}}_stat_l[[@LINE+43]]_ctor to i8*)], section "llvm.metadata"
+
+// CHECK-DAG: define {{.*}}i32 @{{.*}}{{foo|bar|baz2|baz3|FA|f_method}}{{.*}}()
+// CHECK-DAG: define {{.*}}void @{{.*}}TemplateClass{{.*}}(%class.TemplateClass* %{{.*}})
+// CHECK-DAG: define {{.*}}i32 @{{.*}}TemplateClass{{.*}}f_method{{.*}}(%class.TemplateClass* %{{.*}})
+// CHECK-DAG: define {{.*}}void @__omp_offloading__{{.*}}_globals_l[[@LINE+37]]_ctor()
+// CHECK-DAG: define {{.*}}void @__omp_offloading__{{.*}}_stat_l[[@LINE+37]]_ctor()
+
+#ifndef HEADER
+#define HEADER
+
+template <typename T>
+class TemplateClass {
+ T a;
+public:
+ TemplateClass() {}
+ T f_method() const { return a; }
+};
+
+int foo();
+
+int baz1();
+
+int baz2();
+
+int baz4() { return 5; }
+
+template <typename T>
+T FA() {
+ TemplateClass<T> s;
+ return s.f_method();
+}
+
+#pragma omp declare target
+struct S {
+ int a;
+ S(int a) : a(a) {}
+};
+
+int foo() { return 0; }
+int b = 15;
+int d;
+S globals(d);
+static S stat(d);
+#pragma omp end declare target
+int c;
+
+int bar() { return 1 + foo() + bar() + baz1() + baz2(); }
+
+int maini1() {
+ int a;
+ static long aa = 32;
+// CHECK-DAG: define weak void @__omp_offloading_{{.*}}maini1{{.*}}_l[[@LINE+1]](i32* dereferenceable{{.*}}, i64 {{.*}}, i64 {{.*}})
+#pragma omp target map(tofrom \
+ : a, b)
+ {
+ S s(a);
+ static long aaa = 23;
+ a = foo() + bar() + b + c + d + aa + aaa + FA<int>();
+ }
+ return baz4();
+}
+
+int baz3() { return 2 + baz2(); }
+int baz2() {
+// CHECK-DAG: define weak void @__omp_offloading_{{.*}}baz2{{.*}}_l[[@LINE+1]](i64 {{.*}})
+#pragma omp target parallel
+ ++c;
+ return 2 + baz3();
+}
+
+// CHECK-NOT: define {{.*}}{{baz1|baz4|maini1}}
+#endif // HEADER
diff --git a/test/OpenMP/declare_target_codegen_globalization.cpp b/test/OpenMP/declare_target_codegen_globalization.cpp
new file mode 100644
index 000000000000..7ef4f8af3dec
--- /dev/null
+++ b/test/OpenMP/declare_target_codegen_globalization.cpp
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-nvidia-cuda -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s
+// expected-no-diagnostics
+
+int foo(int &a) { return a; }
+
+int bar() {
+ int a;
+ return foo(a);
+}
+
+// CHECK: define weak void @__omp_offloading_{{.*}}maini1{{.*}}_l[[@LINE+5]](i32* dereferenceable{{.*}})
+// CHECK-NOT: @__kmpc_data_sharing_push_stack
+
+int maini1() {
+ int a;
+#pragma omp target parallel map(from:a)
+ {
+ int b;
+ a = foo(b) + bar();
+ }
+ return a;
+}
+
+// parallel region
+// CHECK: define {{.*}}void @{{.*}}(i32* noalias {{.*}}, i32* noalias {{.*}}, i32* dereferenceable{{.*}})
+// CHECK-NOT: call i8* @__kmpc_data_sharing_push_stack(
+// CHECK: [[B_ADDR:%.+]] = alloca i32,
+// CHECK: call {{.*}}[[FOO:@.*foo.*]](i32* dereferenceable{{.*}} [[B_ADDR]])
+// CHECK: call {{.*}}[[BAR:@.*bar.*]]()
+// CHECK-NOT: call void @__kmpc_data_sharing_pop_stack(
+// CHECK: ret void
+
+// CHECK: define {{.*}}[[FOO]](i32* dereferenceable{{.*}})
+// CHECK-NOT: @__kmpc_data_sharing_push_stack
+
+// CHECK: define {{.*}}[[BAR]]()
+// CHECK: [[RES:%.+]] = call i8* @__kmpc_data_sharing_push_stack(i64 4, i16 0)
+// CHECK: [[GLOBALS:%.+]] = bitcast i8* [[RES]] to [[GLOBAL_ST:%struct[.].*]]*
+// CHECK: [[A_ADDR:%.+]] = getelementptr inbounds [[GLOBAL_ST]], [[GLOBAL_ST]]* [[GLOBALS]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
+// CHECK: call {{.*}}[[FOO]](i32* dereferenceable{{.*}} [[A_ADDR]])
+// CHECK: call void @__kmpc_data_sharing_pop_stack(i8* [[RES]])
+// CHECK: ret i32
diff --git a/test/OpenMP/declare_target_link_codegen.cpp b/test/OpenMP/declare_target_link_codegen.cpp
new file mode 100644
index 000000000000..fdecd728ce68
--- /dev/null
+++ b/test/OpenMP/declare_target_link_codegen.cpp
@@ -0,0 +1,69 @@
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix HOST --check-prefix CHECK
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix DEVICE --check-prefix CHECK
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -emit-pch -o %t
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -o - | FileCheck %s --check-prefix DEVICE --check-prefix CHECK
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o -| FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -emit-pch -o %t
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify -o - | FileCheck %s --check-prefix SIMD-ONLY
+
+// expected-no-diagnostics
+
+// SIMD-ONLY-NOT: {{__kmpc|__tgt}}
+
+#ifndef HEADER
+#define HEADER
+
+// HOST: @c = external global i32,
+// DEVICE-NOT: @c =
+// DEVICE: @c_decl_tgt_link_ptr = common global i32* null
+// HOST: @c_decl_tgt_link_ptr = global i32* @c
+// HOST: [[SIZES:@.+]] = private unnamed_addr constant [2 x i64] [i64 4, i64 4]
+// HOST: [[MAPTYPES:@.+]] = private unnamed_addr constant [2 x i64] [i64 35, i64 531]
+// HOST: @.omp_offloading.entry_name{{.*}} = internal unnamed_addr constant [{{[0-9]+}} x i8] c"c_decl_tgt_link_ptr\00"
+// HOST: @.omp_offloading.entry.c_decl_tgt_link_ptr = weak constant %struct.__tgt_offload_entry { i8* bitcast (i32** @c_decl_tgt_link_ptr to i8*), i8* getelementptr inbounds ([{{[0-9]+}} x i8], [{{[0-9]+}} x i8]* @.omp_offloading.entry_name, i32 0, i32 0), i64 8, i32 1, i32 0 }, section ".omp_offloading.entries", align 1
+// DEVICE-NOT: internal unnamed_addr constant [{{[0-9]+}} x i8] c"c_decl_tgt_link_ptr\00"
+// CHECK: @llvm.used = appending global [1 x i8*] [i8* bitcast (i32** @c_decl_tgt_link_ptr to i8*)]
+
+extern int c;
+#pragma omp declare target link(c)
+
+int maini1() {
+ int a;
+#pragma omp target map(tofrom : a)
+ {
+ a = c;
+ }
+ return 0;
+}
+
+// DEVICE: define weak void @__omp_offloading_{{.*}}_{{.*}}maini1{{.*}}_l[[@LINE-7]](i32* dereferenceable{{[^,]*}}
+// DEVICE: [[C_REF:%.+]] = load i32*, i32** @c_decl_tgt_link_ptr,
+// DEVICE: [[C:%.+]] = load i32, i32* [[C_REF]],
+// DEVICE: store i32 [[C]], i32* %
+
+// HOST: define {{.*}}i32 @{{.*}}maini1{{.*}}()
+// HOST: [[BASEPTRS:%.+]] = alloca [2 x i8*],
+// HOST: [[PTRS:%.+]] = alloca [2 x i8*],
+// HOST: getelementptr inbounds [2 x i8*], [2 x i8*]* [[BASEPTRS]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
+// HOST: getelementptr inbounds [2 x i8*], [2 x i8*]* [[PTRS]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
+// HOST: [[BP1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BASEPTRS]], i{{[0-9]+}} 0, i{{[0-9]+}} 1
+// HOST: [[BP1_CAST:%.+]] = bitcast i8** [[BP1]] to i32***
+// HOST: store i32** @c_decl_tgt_link_ptr, i32*** [[BP1_CAST]],
+// HOST: [[P1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[PTRS]], i{{[0-9]+}} 0, i{{[0-9]+}} 1
+// HOST: [[P1_CAST:%.+]] = bitcast i8** [[P1]] to i32**
+// HOST: store i32* @c, i32** [[P1_CAST]],
+// HOST: [[BP0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BASEPTRS]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
+// HOST: [[P0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[PTRS]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
+// HOST: call i32 @__tgt_target(i64 -1, i8* @{{[^,]+}}, i32 2, i8** [[BP0]], i8** [[P0]], i64* getelementptr inbounds ([2 x i64], [2 x i64]* [[SIZES]], i{{[0-9]+}} 0, i{{[0-9]+}} 0), i64* getelementptr inbounds ([2 x i64], [2 x i64]* [[MAPTYPES]], i{{[0-9]+}} 0, i{{[0-9]+}} 0))
+// HOST: call void @__omp_offloading_{{.*}}_{{.*}}maini1{{.*}}_l[[@LINE-26]](i32* %{{[^,]+}})
+
+// HOST: define internal void @__omp_offloading_{{.*}}_{{.*}}maini1{{.*}}_l[[@LINE-28]](i32* dereferenceable{{.*}})
+// HOST: [[C:%.*]] = load i32, i32* @c,
+// HOST: store i32 [[C]], i32* %
+
+// CHECK: !{i32 1, !"c_decl_tgt_link_ptr", i32 1, i32 {{[0-9]+}}}
+#endif // HEADER
diff --git a/test/OpenMP/declare_target_messages.cpp b/test/OpenMP/declare_target_messages.cpp
index c1c03951a3c1..c8e73f6efbd7 100644
--- a/test/OpenMP/declare_target_messages.cpp
+++ b/test/OpenMP/declare_target_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -fnoopenmp-use-tls -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -fnoopenmp-use-tls -ferror-limit 100 -o - %s
+
#pragma omp end declare target // expected-error {{unexpected OpenMP directive '#pragma omp end declare target'}}
int a, b; // expected-warning {{declaration is not declared in any declare target region}}
@@ -17,7 +19,7 @@ void f();
#pragma omp declare target link(foo2) // expected-error {{use of undeclared identifier 'foo2'}}
-void c(); // expected-warning {{declaration is not declared in any declare target region}}
+void c();
void func() {} // expected-note {{'func' defined here}}
@@ -31,6 +33,33 @@ struct NonT {
typedef int sint;
+template <typename T>
+T bla1() { return 0; }
+
+#pragma omp declare target
+template <typename T>
+T bla2() { return 0; }
+#pragma omp end declare target
+
+template<>
+float bla2() { return 1.0; }
+
+#pragma omp declare target
+void blub2() {
+ bla2<float>();
+ bla2<int>();
+}
+#pragma omp end declare target
+
+void t2() {
+#pragma omp target
+ {
+ bla2<float>();
+ bla2<long>();
+ }
+}
+
+
#pragma omp declare target // expected-note {{to match this '#pragma omp declare target'}}
#pragma omp threadprivate(a) // expected-note {{defined as threadprivate or thread local}}
extern int b;
@@ -59,7 +88,7 @@ int C::method1() {
return 0;
}
-void foo() {
+void foo(int p) {
a = 0; // expected-error {{threadprivate variables cannot be used in target constructs}}
b = 0; // expected-note {{used here}}
t = 1; // expected-error {{threadprivate variables cannot be used in target constructs}}
@@ -67,9 +96,9 @@ void foo() {
VC object1;
g = object.method();
g += object.method1();
- g += object1.method();
+ g += object1.method() + p;
f();
- c(); // expected-note {{used here}}
+ c();
}
#pragma omp declare target // expected-error {{expected '#pragma omp end declare target'}}
void foo1() {}
@@ -90,7 +119,7 @@ int main (int argc, char **argv) {
#pragma omp declare target // expected-error {{unexpected OpenMP directive '#pragma omp declare target'}}
int v;
#pragma omp end declare target // expected-error {{unexpected OpenMP directive '#pragma omp end declare target'}}
- foo();
+ foo(v);
return (0);
}
diff --git a/test/OpenMP/distribute_ast_print.cpp b/test/OpenMP/distribute_ast_print.cpp
index d4a9df938f56..f675814e57a5 100644
--- a/test/OpenMP/distribute_ast_print.cpp
+++ b/test/OpenMP/distribute_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -83,7 +87,7 @@ T tmain(T argc) {
static T a;
// CHECK: static T a;
#pragma omp distribute
-// CHECK-NEXT: #pragma omp distribute
+// CHECK-NEXT: #pragma omp distribute{{$}}
for (int i=0; i < 2; ++i)a=2;
// CHECK-NEXT: for (int i = 0; i < 2; ++i)
// CHECK-NEXT: a = 2;
diff --git a/test/OpenMP/distribute_codegen.cpp b/test/OpenMP/distribute_codegen.cpp
index 7ea17b116c88..fe89ee0c1bdb 100644
--- a/test/OpenMP/distribute_codegen.cpp
+++ b/test/OpenMP/distribute_codegen.cpp
@@ -6,6 +6,14 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix HCHECK
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// Test target codegen - host bc file has to be created first. (no significant differences with host version of target region)
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s
@@ -16,14 +24,24 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
-// CHECK-DAG: %ident_t = type { i32, i32, i32, i32, i8* }
+// CHECK-DAG: %struct.ident_t = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC_0:@.+]] = private unnamed_addr constant %ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
-// CHECK-DAG: [[DEF_LOC_DISTRIBUTE_0:@.+]] = private unnamed_addr constant %ident_t { i32 0, i32 2050, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC_0:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC_DISTRIBUTE_0:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2050, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
// CHECK-LABEL: define {{.*void}} @{{.*}}without_schedule_clause{{.*}}(float* {{.+}}, float* {{.+}}, float* {{.+}}, float* {{.+}})
void without_schedule_clause(float *a, float *b, float *c, float *d) {
@@ -49,7 +67,7 @@ void without_schedule_clause(float *a, float *b, float *c, float *d) {
// CHECK-DAG: store i32 0, i32* [[LAST]]
// CHECK-DAG: [[GBL_TID:%.+]] = load i32*, i32** [[TID_ADDR]]
// CHECK-DAG: [[GBL_TIDV:%.+]] = load i32, i32* [[GBL_TID]]
-// CHECK: call void @__kmpc_for_static_init_{{.+}}(%ident_t* [[DEF_LOC_DISTRIBUTE_0]], i32 [[GBL_TIDV]], i32 92, i32* %.omp.is_last, i32* %.omp.lb, i32* %.omp.ub, i32* %.omp.stride, i32 1, i32 1)
+// CHECK: call void @__kmpc_for_static_init_{{.+}}(%struct.ident_t* [[DEF_LOC_DISTRIBUTE_0]], i32 [[GBL_TIDV]], i32 92, i32* %.omp.is_last, i32* %.omp.lb, i32* %.omp.ub, i32* %.omp.stride, i32 1, i32 1)
// CHECK-DAG: [[UBV0:%.+]] = load i32, i32* [[UB]]
// CHECK-DAG: [[USWITCH:%.+]] = icmp sgt i32 [[UBV0]], 4571423
// CHECK: br i1 [[USWITCH]], label %[[BBCT:.+]], label %[[BBCF:.+]]
@@ -83,7 +101,7 @@ void without_schedule_clause(float *a, float *b, float *c, float *d) {
// CHECK: [[BBINNEND]]:
// CHECK: br label %[[LPEXIT:.+]]
// CHECK: [[LPEXIT]]:
-// CHECK: call void @__kmpc_for_static_fini(%ident_t* [[DEF_LOC_DISTRIBUTE_0]], i32 [[GBL_TIDV]])
+// CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* [[DEF_LOC_DISTRIBUTE_0]], i32 [[GBL_TIDV]])
// CHECK: ret void
@@ -111,7 +129,7 @@ void static_not_chunked(float *a, float *b, float *c, float *d) {
// CHECK-DAG: store i32 0, i32* [[LAST]]
// CHECK-DAG: [[GBL_TID:%.+]] = load i32*, i32** [[TID_ADDR]]
// CHECK-DAG: [[GBL_TIDV:%.+]] = load i32, i32* [[GBL_TID]]
-// CHECK: call void @__kmpc_for_static_init_{{.+}}(%ident_t* [[DEF_LOC_DISTRIBUTE_0]], i32 [[GBL_TIDV]], i32 92, i32* %.omp.is_last, i32* %.omp.lb, i32* %.omp.ub, i32* %.omp.stride, i32 1, i32 1)
+// CHECK: call void @__kmpc_for_static_init_{{.+}}(%struct.ident_t* [[DEF_LOC_DISTRIBUTE_0]], i32 [[GBL_TIDV]], i32 92, i32* %.omp.is_last, i32* %.omp.lb, i32* %.omp.ub, i32* %.omp.stride, i32 1, i32 1)
// CHECK-DAG: [[UBV0:%.+]] = load i32, i32* [[UB]]
// CHECK-DAG: [[USWITCH:%.+]] = icmp sgt i32 [[UBV0]], 4571423
// CHECK: br i1 [[USWITCH]], label %[[BBCT:.+]], label %[[BBCF:.+]]
@@ -145,7 +163,7 @@ void static_not_chunked(float *a, float *b, float *c, float *d) {
// CHECK: [[BBINNEND]]:
// CHECK: br label %[[LPEXIT:.+]]
// CHECK: [[LPEXIT]]:
-// CHECK: call void @__kmpc_for_static_fini(%ident_t* [[DEF_LOC_DISTRIBUTE_0]], i32 [[GBL_TIDV]])
+// CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* [[DEF_LOC_DISTRIBUTE_0]], i32 [[GBL_TIDV]])
// CHECK: ret void
@@ -173,7 +191,7 @@ void static_chunked(float *a, float *b, float *c, float *d) {
// CHECK-DAG: store i32 0, i32* [[LAST]]
// CHECK-DAG: [[GBL_TID:%.+]] = load i32*, i32** [[TID_ADDR]]
// CHECK-DAG: [[GBL_TIDV:%.+]] = load i32, i32* [[GBL_TID]]
-// CHECK: call void @__kmpc_for_static_init_{{.+}}(%ident_t* [[DEF_LOC_DISTRIBUTE_0]], i32 [[GBL_TIDV]], i32 91, i32* %.omp.is_last, i32* %.omp.lb, i32* %.omp.ub, i32* %.omp.stride, i32 1, i32 5)
+// CHECK: call void @__kmpc_for_static_init_{{.+}}(%struct.ident_t* [[DEF_LOC_DISTRIBUTE_0]], i32 [[GBL_TIDV]], i32 91, i32* %.omp.is_last, i32* %.omp.lb, i32* %.omp.ub, i32* %.omp.stride, i32 1, i32 5)
// CHECK-DAG: [[UBV0:%.+]] = load i32, i32* [[UB]]
// CHECK-DAG: [[USWITCH:%.+]] = icmp ugt i32 [[UBV0]], 16908288
// CHECK: br i1 [[USWITCH]], label %[[BBCT:.+]], label %[[BBCF:.+]]
@@ -207,7 +225,7 @@ void static_chunked(float *a, float *b, float *c, float *d) {
// CHECK: [[BBINNEND]]:
// CHECK: br label %[[LPEXIT:.+]]
// CHECK: [[LPEXIT]]:
-// CHECK: call void @__kmpc_for_static_fini(%ident_t* [[DEF_LOC_DISTRIBUTE_0]], i32 [[GBL_TIDV]])
+// CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* [[DEF_LOC_DISTRIBUTE_0]], i32 [[GBL_TIDV]])
// CHECK: ret void
// CHECK-LABEL: test_precond
diff --git a/test/OpenMP/distribute_collapse_messages.cpp b/test/OpenMP/distribute_collapse_messages.cpp
index 4897e6931d27..b852fd2826b1 100644
--- a/test/OpenMP/distribute_collapse_messages.cpp
+++ b/test/OpenMP/distribute_collapse_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_dist_schedule_ast_print.cpp b/test/OpenMP/distribute_dist_schedule_ast_print.cpp
index b06a56e3ee35..de5e59aef73b 100644
--- a/test/OpenMP/distribute_dist_schedule_ast_print.cpp
+++ b/test/OpenMP/distribute_dist_schedule_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -14,7 +18,7 @@ T tmain(T argc) {
static T a;
// CHECK: static T a;
#pragma omp distribute dist_schedule(static,10)
-// CHECK-NEXT: #pragma omp distribute dist_schedule(static, 10)
+// CHECK-NEXT: #pragma omp distribute dist_schedule(static, 10){{$}}
for (int i=0; i < 2; ++i)a=2;
// CHECK-NEXT: for (int i = 0; i < 2; ++i)
// CHECK-NEXT: a = 2;
diff --git a/test/OpenMP/distribute_dist_schedule_messages.cpp b/test/OpenMP/distribute_dist_schedule_messages.cpp
index 98652a20034e..9f91f41f8640 100644
--- a/test/OpenMP/distribute_dist_schedule_messages.cpp
+++ b/test/OpenMP/distribute_dist_schedule_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_firstprivate_codegen.cpp b/test/OpenMP/distribute_firstprivate_codegen.cpp
index 98c99d805ed5..29d44fde92f2 100644
--- a/test/OpenMP/distribute_firstprivate_codegen.cpp
+++ b/test/OpenMP/distribute_firstprivate_codegen.cpp
@@ -5,12 +5,28 @@
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -239,7 +255,7 @@ int main() {
// CHECK-DAG: [[VEC_ADDR_VAL:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]],
// CHECK-DAG: [[VEC_ADDR_VAL_BCAST:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i{{[0-9]+}}*
// CHECK-DAG: [[VEC_PRIV_BCAST:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i{{[0-9]+}}*
-// CHECK-DAG: call void @llvm.memcpy.{{.*}}(i{{[0-9]+}}* [[VEC_PRIV_BCAST]], i{{[0-9]+}}* [[VEC_ADDR_VAL_BCAST]],{{.+}})
+// CHECK-DAG: call void @llvm.memcpy.{{.*}}(i{{[0-9]+}}* align {{[0-9]+}} [[VEC_PRIV_BCAST]], i{{[0-9]+}}* align {{[0-9]+}} [[VEC_ADDR_VAL_BCAST]],{{.+}})
// init s_arr
// CHECK-DAG: [[S_ARR_ADDR_VAL:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[S_ARR_ADDR]],
@@ -254,7 +270,7 @@ int main() {
// CHECK-DAG: [[S_ARR_DST_PAST:%.+]] = phi{{.+}} [ [[S_ARR_PRIV_BGN]],{{.+}} ], [ [[S_ARR_DST:%.+]],{{.+}} ]
// CHECK-DAG: [[S_ARR_SRC_BCAST:%.+]] = bitcast{{.+}} [[S_ARR_SRC_PAST]] to{{.+}}
// CHECK-DAG: [[S_ARR_DST_BCAST:%.+]] = bitcast{{.+}} [[S_ARR_DST_PAST]] to{{.+}}
-// CHECK-DAG: call{{.+}} @llvm.memcpy.{{.+}}({{.+}}* [[S_ARR_DST_BCAST]], {{.+}}* [[S_ARR_SRC_BCAST]]{{.+}})
+// CHECK-DAG: call{{.+}} @llvm.memcpy.{{.+}}({{.+}}* align {{[0-9]+}} [[S_ARR_DST_BCAST]], {{.+}}* align {{[0-9]+}} [[S_ARR_SRC_BCAST]]{{.+}})
// CHECK-DAG: [[S_ARR_SRC]] = getelementptr{{.+}}
// CHECK-DAG: [[S_ARR_DST]] = getelementptr{{.+}}
// CHECK-DAG: [[S_ARR_CPY_FIN:%.+]] = icmp{{.+}} [[S_ARR_DST]], [[S_ARR_PRIV_NEXT]]
@@ -267,7 +283,7 @@ int main() {
// CHECK-DAG: [[TMP_VAL:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP]],
// CHECK-DAG: [[VAR_PRIV_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[VAR_PRIV]] to{{.+}}
// CHECK-DAG: [[TMP_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_VAL]] to{{.+}}
-// CHECK-DAG: call{{.+}} @llvm.memcpy.{{.+}}({{.+}}* [[VAR_PRIV_BCAST]], {{.+}}* [[TMP_BCAST]],{{.+}})
+// CHECK-DAG: call{{.+}} @llvm.memcpy.{{.+}}({{.+}}* align {{[0-9]+}} [[VAR_PRIV_BCAST]], {{.+}}* align {{[0-9]+}} [[TMP_BCAST]],{{.+}})
// CHECK-DAG: store [[S_FLOAT_TY]]* [[VAR_PRIV]], [[S_FLOAT_TY]]** [[TMP_PRIV]],
// init svar
@@ -334,7 +350,7 @@ int main() {
// CHECK-DAG: [[VEC_ADDR_VAL:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]],
// CHECK-DAG: [[VEC_ADDR_VAL_BCAST:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i{{[0-9]+}}*
// CHECK-DAG: [[VEC_PRIV_BCAST:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i{{[0-9]+}}*
-// CHECK-DAG: call void @llvm.memcpy.{{.*}}(i{{[0-9]+}}* [[VEC_PRIV_BCAST]], i{{[0-9]+}}* [[VEC_ADDR_VAL_BCAST]],{{.+}})
+// CHECK-DAG: call void @llvm.memcpy.{{.*}}(i{{[0-9]+}}* align {{[0-9]+}} [[VEC_PRIV_BCAST]], i{{[0-9]+}}* align {{[0-9]+}} [[VEC_ADDR_VAL_BCAST]],{{.+}})
// init s_arr
// CHECK-DAG: [[S_ARR_ADDR_VAL:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[S_ARR_ADDR]],
@@ -349,7 +365,7 @@ int main() {
// CHECK-DAG: [[S_ARR_DST_PAST:%.+]] = phi{{.+}} [ [[S_ARR_PRIV_BGN]],{{.+}} ], [ [[S_ARR_DST:%.+]],{{.+}} ]
// CHECK-DAG: [[S_ARR_SRC_BCAST:%.+]] = bitcast{{.+}} [[S_ARR_SRC_PAST]] to{{.+}}
// CHECK-DAG: [[S_ARR_DST_BCAST:%.+]] = bitcast{{.+}} [[S_ARR_DST_PAST]] to{{.+}}
-// CHECK-DAG: call{{.+}} @llvm.memcpy.{{.+}}({{.+}}* [[S_ARR_DST_BCAST]], {{.+}}* [[S_ARR_SRC_BCAST]]{{.+}})
+// CHECK-DAG: call{{.+}} @llvm.memcpy.{{.+}}({{.+}}* align {{[0-9]+}} [[S_ARR_DST_BCAST]], {{.+}}* align {{[0-9]+}} [[S_ARR_SRC_BCAST]]{{.+}})
// CHECK-DAG: [[S_ARR_SRC]] = getelementptr{{.+}}
// CHECK-DAG: [[S_ARR_DST]] = getelementptr{{.+}}
// CHECK-DAG: [[S_ARR_CPY_FIN:%.+]] = icmp{{.+}} [[S_ARR_DST]], [[S_ARR_PRIV_NEXT]]
@@ -362,7 +378,7 @@ int main() {
// CHECK-DAG: [[TMP_VAL:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP]],
// CHECK-DAG: [[VAR_PRIV_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[VAR_PRIV]] to{{.+}}
// CHECK-DAG: [[TMP_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL]] to{{.+}}
-// CHECK-DAG: call{{.+}} @llvm.memcpy.{{.+}}({{.+}}* [[VAR_PRIV_BCAST]], {{.+}}* [[TMP_BCAST]],{{.+}})
+// CHECK-DAG: call{{.+}} @llvm.memcpy.{{.+}}({{.+}}* align {{[0-9]+}} [[VAR_PRIV_BCAST]], {{.+}}* align {{[0-9]+}} [[TMP_BCAST]],{{.+}})
// CHECK-DAG: store [[S_INT_TY]]* [[VAR_PRIV]], [[S_INT_TY]]** [[TMP_PRIV]],
// CHECK-DAG: store i{{[0-9]+}} 0, i{{[0-9]+}}* %.omp{{.+}},
diff --git a/test/OpenMP/distribute_firstprivate_messages.cpp b/test/OpenMP/distribute_firstprivate_messages.cpp
index a59c9528090f..ea0e7b4a2314 100644
--- a/test/OpenMP/distribute_firstprivate_messages.cpp
+++ b/test/OpenMP/distribute_firstprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_lastprivate_codegen.cpp b/test/OpenMP/distribute_lastprivate_codegen.cpp
index bd9dae956f1c..66a860b7152e 100644
--- a/test/OpenMP/distribute_lastprivate_codegen.cpp
+++ b/test/OpenMP/distribute_lastprivate_codegen.cpp
@@ -5,12 +5,28 @@
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -240,7 +256,7 @@ int main() {
// CHECK-DAG: [[TMP_VAL:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP_PRIV]],
// CHECK-DAG: [[S_ARR_PTR_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_PTR]] to i8*
// CHECK-DAG: [[TMP_VAL_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_VAL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_PTR_BCAST]], i8* [[TMP_VAL_BCAST]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_PTR_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL_BCAST]],
// CHECK: call void @__kmpc_for_static_fini(
// lastprivates
@@ -253,7 +269,7 @@ int main() {
// CHECK: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_ADDR_REF]],
// CHECK: [[BCAST_VEC_ADDR_REF:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_REF]] to i8*
// CHECK: [[BCAST_VEC_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[BCAST_VEC_ADDR_REF]], i8* [[BCAST_VEC_PRIV]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[BCAST_VEC_ADDR_REF]], i8* align {{[0-9]+}} [[BCAST_VEC_PRIV]],
// CHECK: [[S_ARR_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_ADDR_REF]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[S_ARR_PRIV_BCAST:%.+]] = bitcast [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]] to [[S_FLOAT_TY]]*
// CHECK: [[S_ARR_BEGIN_GEP:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[S_ARR_BEGIN]], i{{[0-9]+}} 2
@@ -264,7 +280,7 @@ int main() {
// CHECK: [[S_ARR_DST_EL:%.+]] = phi [[S_FLOAT_TY]]*{{.+}}
// CHECK: [[S_ARR_DST_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_DST_EL]] to i8*
// CHECK: [[S_ARR_SRC_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_SRC_EL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_DST_BCAST]], i8* [[S_ARR_SRC_BCAST]]{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_DST_BCAST]], i8* align {{[0-9]+}} [[S_ARR_SRC_BCAST]]{{.+}})
// CHECK: [[S_ARR_DST_NEXT:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[S_ARR_DST_EL]], i{{[0-9]+}} 1
// CHECK: [[S_ARR_SRC_NEXT:%.+]] = getelementptr{{.+}}
// CHECK: [[CPY_IS_FINISHED:%.+]] = icmp eq [[S_FLOAT_TY]]* [[S_ARR_DST_NEXT]], [[S_ARR_BEGIN_GEP]]
@@ -273,7 +289,7 @@ int main() {
// CHECK: [[TMP_VAL1:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP_PRIV]],
// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_REF]] to i8*
// CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VAR_ADDR_REF_BCAST]], i8* [[TMP_VAL1_BCAST]],{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}})
// CHECK: [[SVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[S_VAR_PRIV]],
// CHECK: store i{{[0-9]+}} [[SVAR_VAL]], i{{[0-9]+}}* [[SVAR_ADDR_REF]],
// CHECK: ret void
@@ -342,7 +358,7 @@ int main() {
// CHECK-DAG: [[TMP_VAL1:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP_PRIV1]],
// CHECK-DAG: [[S_ARR_PTR_BCAST1:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_PTR1]] to i8*
// CHECK-DAG: [[TMP_VAL_BCAST1:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_PTR_BCAST1]], i8* [[TMP_VAL_BCAST1]],
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_PTR_BCAST1]], i8* align {{[0-9]+}} [[TMP_VAL_BCAST1]],
// CHECK: call void @__kmpc_for_static_fini(
// lastprivates
@@ -355,7 +371,7 @@ int main() {
// CHECK: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_ADDR_REF1]],
// CHECK: [[BCAST_VEC_ADDR_REF:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_REF1]] to i8*
// CHECK: [[BCAST_VEC_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[BCAST_VEC_ADDR_REF]], i8* [[BCAST_VEC_PRIV]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[BCAST_VEC_ADDR_REF]], i8* align {{[0-9]+}} [[BCAST_VEC_PRIV]],
// CHECK: [[S_ARR_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_ADDR_REF]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[S_ARR_PRIV_BCAST:%.+]] = bitcast [2 x [[S_INT_TY]]]* [[S_ARR_PRIV1]] to [[S_INT_TY]]*
// CHECK: [[S_ARR_BEGIN_GEP:%.+]] = getelementptr [[S_INT_TY]], [[S_INT_TY]]* [[S_ARR_BEGIN]], i{{[0-9]+}} 2
@@ -366,7 +382,7 @@ int main() {
// CHECK: [[S_ARR_DST_EL:%.+]] = phi [[S_INT_TY]]*{{.+}}
// CHECK: [[S_ARR_DST_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_DST_EL]] to i8*
// CHECK: [[S_ARR_SRC_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_SRC_EL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_DST_BCAST]], i8* [[S_ARR_SRC_BCAST]]{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_DST_BCAST]], i8* align {{[0-9]+}} [[S_ARR_SRC_BCAST]]{{.+}})
// CHECK: [[S_ARR_DST_NEXT:%.+]] = getelementptr [[S_INT_TY]], [[S_INT_TY]]* [[S_ARR_DST_EL]], i{{[0-9]+}} 1
// CHECK: [[S_ARR_SRC_NEXT:%.+]] = getelementptr{{.+}}
// CHECK: [[CPY_IS_FINISHED:%.+]] = icmp eq [[S_INT_TY]]* [[S_ARR_DST_NEXT]], [[S_ARR_BEGIN_GEP]]
@@ -375,6 +391,6 @@ int main() {
// CHECK: [[TMP_VAL1:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP_PRIV1]],
// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_REF]] to i8*
// CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VAR_ADDR_REF_BCAST]], i8* [[TMP_VAL1_BCAST]],{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}})
// CHECK: ret void
#endif
diff --git a/test/OpenMP/distribute_parallel_for_ast_print.cpp b/test/OpenMP/distribute_parallel_for_ast_print.cpp
index 351e15803c09..58e6eb8aa77a 100644
--- a/test/OpenMP/distribute_parallel_for_ast_print.cpp
+++ b/test/OpenMP/distribute_parallel_for_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -std=c++11 -fopenmp -fopenmp-version=45 -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -std=c++11 -fopenmp-simd -fopenmp-version=45 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -37,7 +41,7 @@ public:
}
};
-// CHECK: #pragma omp distribute parallel for private(this->a) private(this->a) private(T::a)
+// CHECK: #pragma omp distribute parallel for private(this->a) private(this->a) private(T::a){{$}}
// CHECK: #pragma omp distribute parallel for private(this->a) private(this->a)
// CHECK: #pragma omp distribute parallel for private(this->a) private(this->a) private(this->S::a)
diff --git a/test/OpenMP/distribute_parallel_for_codegen.cpp b/test/OpenMP/distribute_parallel_for_codegen.cpp
index 4fbca7d2f29a..a7700a3421ac 100644
--- a/test/OpenMP/distribute_parallel_for_codegen.cpp
+++ b/test/OpenMP/distribute_parallel_for_codegen.cpp
@@ -6,12 +6,28 @@
// RUN: %clang_cc1 -DLAMBDA -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/distribute_parallel_for_collapse_messages.cpp b/test/OpenMP/distribute_parallel_for_collapse_messages.cpp
index 41976a69ee2c..f01dfeea5c27 100644
--- a/test/OpenMP/distribute_parallel_for_collapse_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_collapse_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_parallel_for_copyin_messages.cpp b/test/OpenMP/distribute_parallel_for_copyin_messages.cpp
index 7d703413488d..5182f24bdb14 100644
--- a/test/OpenMP/distribute_parallel_for_copyin_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_copyin_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_parallel_for_default_messages.cpp b/test/OpenMP/distribute_parallel_for_default_messages.cpp
index 3437bd55cf3f..cb9cbcf6ba41 100644
--- a/test/OpenMP/distribute_parallel_for_default_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_default_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo();
template <class T, int N>
diff --git a/test/OpenMP/distribute_parallel_for_dist_schedule_messages.cpp b/test/OpenMP/distribute_parallel_for_dist_schedule_messages.cpp
index 0f5820ed4bbb..adcef0bab92a 100644
--- a/test/OpenMP/distribute_parallel_for_dist_schedule_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_dist_schedule_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_parallel_for_firstprivate_codegen.cpp b/test/OpenMP/distribute_parallel_for_firstprivate_codegen.cpp
index de348272950c..e4915acf69b6 100644
--- a/test/OpenMP/distribute_parallel_for_firstprivate_codegen.cpp
+++ b/test/OpenMP/distribute_parallel_for_firstprivate_codegen.cpp
@@ -5,12 +5,27 @@
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -313,7 +328,7 @@ int main() {
// CHECK-DAG: [[VEC_ADDR_VAL:%.+]] = load {{.+}}*, {{.+}}** [[VEC_ADDR]],
// CHECK-DAG: [[VEC_PRIV_BCAST:%.+]] = bitcast {{.+}} [[VEC_PRIV]] to
// CHECK-DAG: [[VEC_ADDR_BCAST:%.+]] = bitcast {{.+}} [[VEC_ADDR_VAL]] to
-// CHECK-DAG: call void @llvm.memcpy{{.+}}({{.+}}* [[VEC_PRIV_BCAST]], {{.+}}* [[VEC_ADDR_BCAST]],
+// CHECK-DAG: call void @llvm.memcpy{{.+}}({{.+}}* align {{[0-9]+}} [[VEC_PRIV_BCAST]], {{.+}}* align {{[0-9]+}} [[VEC_ADDR_BCAST]],
// s_arr
// CHECK-DAG: [[S_ARR_ADDR_VAL:%.+]] = load {{.+}}*, {{.+}}** [[S_ARR_ADDR]],
@@ -330,7 +345,7 @@ int main() {
// CHECK-DAG: [[TMP_REF:%.+]] = load {{.+}}*, {{.+}}* [[TMP]],
// CHECK-DAG: [[VAR_PRIV_BCAST:%.+]] = bitcast {{.+}}* [[VAR_PRIV]] to
// CHECK-DAG: [[TMP_REF_BCAST:%.+]] = bitcast {{.+}}* [[TMP_REF]] to
-// CHECK-DAG: call void @llvm.memcpy.{{.+}}({{.+}}* [[VAR_PRIV_BCAST]], {{.+}}* [[TMP_REF_BCAST]],
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}({{.+}}* align {{[0-9]+}} [[VAR_PRIV_BCAST]], {{.+}}* align {{[0-9]+}} [[TMP_REF_BCAST]],
// CHECK-DAG: store {{.+}}* [[VAR_PRIV]], {{.+}}** [[TMP_PRIV]],
// svar
@@ -406,7 +421,7 @@ int main() {
// CHECK-DAG: [[VEC_ADDR_VAL:%.+]] = load {{.+}}*, {{.+}}** [[VEC_ADDR]],
// CHECK-DAG: [[VEC_PRIV_BCAST:%.+]] = bitcast {{.+}} [[VEC_PRIV]] to
// CHECK-DAG: [[VEC_ADDR_BCAST:%.+]] = bitcast {{.+}} [[VEC_ADDR_VAL]] to
-// CHECK-DAG: call void @llvm.memcpy{{.+}}({{.+}}* [[VEC_PRIV_BCAST]], {{.+}}* [[VEC_ADDR_BCAST]],
+// CHECK-DAG: call void @llvm.memcpy{{.+}}({{.+}}* align {{[0-9]+}} [[VEC_PRIV_BCAST]], {{.+}}* align {{[0-9]+}} [[VEC_ADDR_BCAST]],
// s_arr
// CHECK-DAG: [[S_ARR_ADDR_VAL:%.+]] = load {{.+}}*, {{.+}}** [[S_ARR_ADDR]],
@@ -423,7 +438,7 @@ int main() {
// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load {{.+}}*, {{.+}}* [[VAR_ADDR]],
// CHECK-DAG: [[VAR_PRIV_BCAST:%.+]] = bitcast {{.+}}* [[VAR_PRIV]] to
// CHECK-DAG: [[VAR_ADDR_BCAST:%.+]] = bitcast {{.+}}* [[VAR_ADDR_REF]] to
-// CHECK-DAG: call void @llvm.memcpy.{{.+}}({{.+}}* [[VAR_PRIV_BCAST]], {{.+}}* [[VAR_ADDR_BCAST]],
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}({{.+}}* align {{[0-9]+}} [[VAR_PRIV_BCAST]], {{.+}}* align {{[0-9]+}} [[VAR_ADDR_BCAST]],
// CHECK-DAG: store {{.+}}* [[VAR_PRIV]], {{.+}}** [[TMP_PRIV]],
// CHECK: call void @__kmpc_for_static_init_4(
@@ -495,7 +510,7 @@ int main() {
// CHECK-DAG: [[VEC_ADDR_VAL:%.+]] = load {{.+}}*, {{.+}}** [[VEC_ADDR]],
// CHECK-DAG: [[VEC_PRIV_BCAST:%.+]] = bitcast {{.+}} [[VEC_PRIV]] to
// CHECK-DAG: [[VEC_ADDR_BCAST:%.+]] = bitcast {{.+}} [[VEC_ADDR_VAL]] to
-// CHECK-DAG: call void @llvm.memcpy{{.+}}({{.+}}* [[VEC_PRIV_BCAST]], {{.+}}* [[VEC_ADDR_BCAST]],
+// CHECK-DAG: call void @llvm.memcpy{{.+}}({{.+}}* align {{[0-9]+}} [[VEC_PRIV_BCAST]], {{.+}}* align {{[0-9]+}} [[VEC_ADDR_BCAST]],
// s_arr
// CHECK-DAG: [[S_ARR_ADDR_VAL:%.+]] = load {{.+}}*, {{.+}}** [[S_ARR_ADDR]],
@@ -512,7 +527,7 @@ int main() {
// CHECK-DAG: [[TMP_REF:%.+]] = load {{.+}}*, {{.+}}* [[TMP]],
// CHECK-DAG: [[VAR_PRIV_BCAST:%.+]] = bitcast {{.+}}* [[VAR_PRIV]] to
// CHECK-DAG: [[TMP_REF_BCAST:%.+]] = bitcast {{.+}}* [[TMP_REF]] to
-// CHECK-DAG: call void @llvm.memcpy.{{.+}}({{.+}}* [[VAR_PRIV_BCAST]], {{.+}}* [[TMP_REF_BCAST]],
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}({{.+}}* align {{[0-9]+}} [[VAR_PRIV_BCAST]], {{.+}}* align {{[0-9]+}} [[TMP_REF_BCAST]],
// CHECK-DAG: store {{.+}}* [[VAR_PRIV]], {{.+}}** [[TMP_PRIV]],
// CHECK: call void @__kmpc_for_static_init_4(
@@ -576,7 +591,7 @@ int main() {
// CHECK-DAG: [[VEC_ADDR_VAL:%.+]] = load {{.+}}*, {{.+}}** [[VEC_ADDR]],
// CHECK-DAG: [[VEC_PRIV_BCAST:%.+]] = bitcast {{.+}} [[VEC_PRIV]] to
// CHECK-DAG: [[VEC_ADDR_BCAST:%.+]] = bitcast {{.+}} [[VEC_ADDR_VAL]] to
-// CHECK-DAG: call void @llvm.memcpy{{.+}}({{.+}}* [[VEC_PRIV_BCAST]], {{.+}}* [[VEC_ADDR_BCAST]],
+// CHECK-DAG: call void @llvm.memcpy{{.+}}({{.+}}* align {{[0-9]+}} [[VEC_PRIV_BCAST]], {{.+}}* align {{[0-9]+}} [[VEC_ADDR_BCAST]],
// s_arr
// CHECK-DAG: [[S_ARR_ADDR_VAL:%.+]] = load {{.+}}*, {{.+}}** [[S_ARR_ADDR]],
@@ -593,7 +608,7 @@ int main() {
// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load {{.+}}*, {{.+}}* [[VAR_ADDR]],
// CHECK-DAG: [[VAR_PRIV_BCAST:%.+]] = bitcast {{.+}}* [[VAR_PRIV]] to
// CHECK-DAG: [[VAR_ADDR_BCAST:%.+]] = bitcast {{.+}}* [[VAR_ADDR_REF]] to
-// CHECK-DAG: call void @llvm.memcpy.{{.+}}({{.+}}* [[VAR_PRIV_BCAST]], {{.+}}* [[VAR_ADDR_BCAST]],
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}({{.+}}* align {{[0-9]+}} [[VAR_PRIV_BCAST]], {{.+}}* align {{[0-9]+}} [[VAR_ADDR_BCAST]],
// CHECK-DAG: store {{.+}}* [[VAR_PRIV]], {{.+}}** [[TMP_PRIV]],
// CHECK: call void @__kmpc_for_static_init_4(
diff --git a/test/OpenMP/distribute_parallel_for_firstprivate_messages.cpp b/test/OpenMP/distribute_parallel_for_firstprivate_messages.cpp
index 67075ca12939..63f4dbec1786 100644
--- a/test/OpenMP/distribute_parallel_for_firstprivate_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_firstprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_parallel_for_if_codegen.cpp b/test/OpenMP/distribute_parallel_for_if_codegen.cpp
index 9ee909e0139c..7e7f24f3c9e8 100644
--- a/test/OpenMP/distribute_parallel_for_if_codegen.cpp
+++ b/test/OpenMP/distribute_parallel_for_if_codegen.cpp
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple %itanium_abi_triple -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple %itanium_abi_triple -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple %itanium_abi_triple -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple %itanium_abi_triple -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/distribute_parallel_for_if_messages.cpp b/test/OpenMP/distribute_parallel_for_if_messages.cpp
index 5e9d9ad9e1f2..85e78d0b9253 100644
--- a/test/OpenMP/distribute_parallel_for_if_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_if_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_parallel_for_lastprivate_codegen.cpp b/test/OpenMP/distribute_parallel_for_lastprivate_codegen.cpp
index fccb0cfdb3d8..dda8c932908e 100644
--- a/test/OpenMP/distribute_parallel_for_lastprivate_codegen.cpp
+++ b/test/OpenMP/distribute_parallel_for_lastprivate_codegen.cpp
@@ -5,12 +5,28 @@
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -333,7 +349,7 @@ int main() {
// CHECK: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_ADDR_REF]],
// CHECK: [[BCAST_VEC_ADDR_REF:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_REF]] to i8*
// CHECK: [[BCAST_VEC_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[BCAST_VEC_ADDR_REF]], i8* [[BCAST_VEC_PRIV]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[BCAST_VEC_ADDR_REF]], i8* align {{[0-9]+}} [[BCAST_VEC_PRIV]],
// CHECK: [[S_ARR_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_ADDR_REF]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[S_ARR_PRIV_BCAST:%.+]] = bitcast [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]] to [[S_FLOAT_TY]]*
// CHECK: [[S_ARR_BEGIN_GEP:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[S_ARR_BEGIN]], i{{[0-9]+}} 2
@@ -344,7 +360,7 @@ int main() {
// CHECK: [[S_ARR_DST_EL:%.+]] = phi [[S_FLOAT_TY]]*{{.+}}
// CHECK: [[S_ARR_DST_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_DST_EL]] to i8*
// CHECK: [[S_ARR_SRC_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_SRC_EL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_DST_BCAST]], i8* [[S_ARR_SRC_BCAST]]{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_DST_BCAST]], i8* align {{[0-9]+}} [[S_ARR_SRC_BCAST]]{{.+}})
// CHECK: [[S_ARR_DST_NEXT:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[S_ARR_DST_EL]], i{{[0-9]+}} 1
// CHECK: [[S_ARR_SRC_NEXT:%.+]] = getelementptr{{.+}}
// CHECK: [[CPY_IS_FINISHED:%.+]] = icmp eq [[S_FLOAT_TY]]* [[S_ARR_DST_NEXT]], [[S_ARR_BEGIN_GEP]]
@@ -353,7 +369,7 @@ int main() {
// CHECK: [[TMP_VAL1:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP_PRIV]],
// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_REF]] to i8*
// CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VAR_ADDR_REF_BCAST]], i8* [[TMP_VAL1_BCAST]],{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}})
// CHECK: [[SVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[S_VAR_PRIV]],
// CHECK: store i{{[0-9]+}} [[SVAR_VAL]], i{{[0-9]+}}* [[SVAR_ADDR_REF]],
// CHECK: ret void
@@ -425,7 +441,7 @@ int main() {
// CHECK-DAG: [[TMP_VAL:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP_PRIV]],
// CHECK-DAG: [[S_ARR_PTR_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_PTR]] to i8*
// CHECK-DAG: [[TMP_VAL_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_VAL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_PTR_BCAST]], i8* [[TMP_VAL_BCAST]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_PTR_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL_BCAST]],
// CHECK: call void @__kmpc_for_static_fini(
@@ -439,7 +455,7 @@ int main() {
// CHECK: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_ADDR_REF]],
// CHECK: [[BCAST_VEC_ADDR_REF:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_REF]] to i8*
// CHECK: [[BCAST_VEC_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[BCAST_VEC_ADDR_REF]], i8* [[BCAST_VEC_PRIV]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[BCAST_VEC_ADDR_REF]], i8* align {{[0-9]+}} [[BCAST_VEC_PRIV]],
// CHECK: [[S_ARR_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_ADDR_REF]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[S_ARR_PRIV_BCAST:%.+]] = bitcast [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]] to [[S_FLOAT_TY]]*
// CHECK: [[S_ARR_BEGIN_GEP:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[S_ARR_BEGIN]], i{{[0-9]+}} 2
@@ -450,7 +466,7 @@ int main() {
// CHECK: [[S_ARR_DST_EL:%.+]] = phi [[S_FLOAT_TY]]*{{.+}}
// CHECK: [[S_ARR_DST_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_DST_EL]] to i8*
// CHECK: [[S_ARR_SRC_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_SRC_EL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_DST_BCAST]], i8* [[S_ARR_SRC_BCAST]]{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_DST_BCAST]], i8* align {{[0-9]+}} [[S_ARR_SRC_BCAST]]{{.+}})
// CHECK: [[S_ARR_DST_NEXT:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[S_ARR_DST_EL]], i{{[0-9]+}} 1
// CHECK: [[S_ARR_SRC_NEXT:%.+]] = getelementptr{{.+}}
// CHECK: [[CPY_IS_FINISHED:%.+]] = icmp eq [[S_FLOAT_TY]]* [[S_ARR_DST_NEXT]], [[S_ARR_BEGIN_GEP]]
@@ -459,7 +475,7 @@ int main() {
// CHECK: [[TMP_VAL1:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP_PRIV]],
// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[VAR_ADDR_REF]] to i8*
// CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VAR_ADDR_REF_BCAST]], i8* [[TMP_VAL1_BCAST]],{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}})
// CHECK: [[SVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[S_VAR_PRIV]],
// CHECK: store i{{[0-9]+}} [[SVAR_VAL]], i{{[0-9]+}}* [[SVAR_ADDR_REF]],
// CHECK: ret void
@@ -533,7 +549,7 @@ int main() {
// CHECK: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_ADDR_REF]],
// CHECK: [[BCAST_VEC_ADDR_REF:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_REF]] to i8*
// CHECK: [[BCAST_VEC_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[BCAST_VEC_ADDR_REF]], i8* [[BCAST_VEC_PRIV]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[BCAST_VEC_ADDR_REF]], i8* align {{[0-9]+}} [[BCAST_VEC_PRIV]],
// CHECK: [[S_ARR_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_ADDR_REF]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[S_ARR_PRIV_BCAST:%.+]] = bitcast [2 x [[S_INT_TY]]]* [[S_ARR_PRIV]] to [[S_INT_TY]]*
// CHECK: [[S_ARR_BEGIN_GEP:%.+]] = getelementptr [[S_INT_TY]], [[S_INT_TY]]* [[S_ARR_BEGIN]], i{{[0-9]+}} 2
@@ -544,7 +560,7 @@ int main() {
// CHECK: [[S_ARR_DST_EL:%.+]] = phi [[S_INT_TY]]*{{.+}}
// CHECK: [[S_ARR_DST_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_DST_EL]] to i8*
// CHECK: [[S_ARR_SRC_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_SRC_EL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_DST_BCAST]], i8* [[S_ARR_SRC_BCAST]]{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_DST_BCAST]], i8* align {{[0-9]+}} [[S_ARR_SRC_BCAST]]{{.+}})
// CHECK: [[S_ARR_DST_NEXT:%.+]] = getelementptr [[S_INT_TY]], [[S_INT_TY]]* [[S_ARR_DST_EL]], i{{[0-9]+}} 1
// CHECK: [[S_ARR_SRC_NEXT:%.+]] = getelementptr{{.+}}
// CHECK: [[CPY_IS_FINISHED:%.+]] = icmp eq [[S_INT_TY]]* [[S_ARR_DST_NEXT]], [[S_ARR_BEGIN_GEP]]
@@ -553,7 +569,7 @@ int main() {
// CHECK: [[TMP_VAL:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP_PRIV]],
// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_REF]] to i8*
// CHECK: [[TMP_VAL_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VAR_ADDR_REF_BCAST]], i8* [[TMP_VAL_BCAST]],{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL_BCAST]],{{.+}})
// CHECK: ret void
// outlined function for 'parallel for'
@@ -619,7 +635,7 @@ int main() {
// CHECK-DAG: [[TMP_VAL:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP_PRIV]],
// CHECK-DAG: [[S_ARR_PTR_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_PTR]] to i8*
// CHECK-DAG: [[TMP_VAL_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL]] to i8*
-// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_PTR_BCAST]], i8* [[TMP_VAL_BCAST]],
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_PTR_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL_BCAST]],
// CHECK: call void @__kmpc_for_static_fini(
@@ -633,7 +649,7 @@ int main() {
// CHECK: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_ADDR_REF]],
// CHECK: [[BCAST_VEC_ADDR_REF:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_REF]] to i8*
// CHECK: [[BCAST_VEC_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[BCAST_VEC_ADDR_REF]], i8* [[BCAST_VEC_PRIV]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[BCAST_VEC_ADDR_REF]], i8* align {{[0-9]+}} [[BCAST_VEC_PRIV]],
// CHECK: [[S_ARR_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_ADDR_REF]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[S_ARR_PRIV_BCAST:%.+]] = bitcast [2 x [[S_INT_TY]]]* [[S_ARR_PRIV]] to [[S_INT_TY]]*
// CHECK: [[S_ARR_BEGIN_GEP:%.+]] = getelementptr [[S_INT_TY]], [[S_INT_TY]]* [[S_ARR_BEGIN]], i{{[0-9]+}} 2
@@ -644,7 +660,7 @@ int main() {
// CHECK: [[S_ARR_DST_EL:%.+]] = phi [[S_INT_TY]]*{{.+}}
// CHECK: [[S_ARR_DST_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_DST_EL]] to i8*
// CHECK: [[S_ARR_SRC_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_SRC_EL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_DST_BCAST]], i8* [[S_ARR_SRC_BCAST]]{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_DST_BCAST]], i8* align {{[0-9]+}} [[S_ARR_SRC_BCAST]]{{.+}})
// CHECK: [[S_ARR_DST_NEXT:%.+]] = getelementptr [[S_INT_TY]], [[S_INT_TY]]* [[S_ARR_DST_EL]], i{{[0-9]+}} 1
// CHECK: [[S_ARR_SRC_NEXT:%.+]] = getelementptr{{.+}}
// CHECK: [[CPY_IS_FINISHED:%.+]] = icmp eq [[S_INT_TY]]* [[S_ARR_DST_NEXT]], [[S_ARR_BEGIN_GEP]]
@@ -653,7 +669,7 @@ int main() {
// CHECK: [[TMP_VAL1:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP_PRIV]],
// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[VAR_ADDR_REF]] to i8*
// CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VAR_ADDR_REF_BCAST]], i8* [[TMP_VAL1_BCAST]],{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}})
// CHECK: ret void
#endif
diff --git a/test/OpenMP/distribute_parallel_for_lastprivate_messages.cpp b/test/OpenMP/distribute_parallel_for_lastprivate_messages.cpp
index b38d978cca03..c8eaad8cf147 100644
--- a/test/OpenMP/distribute_parallel_for_lastprivate_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_lastprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_parallel_for_messages.cpp b/test/OpenMP/distribute_parallel_for_messages.cpp
index b1bb8d088e90..5ea73a88fc54 100644
--- a/test/OpenMP/distribute_parallel_for_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -std=c++11 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -std=c++11 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_parallel_for_num_threads_codegen.cpp b/test/OpenMP/distribute_parallel_for_num_threads_codegen.cpp
index 89e990504439..21d094945427 100644
--- a/test/OpenMP/distribute_parallel_for_num_threads_codegen.cpp
+++ b/test/OpenMP/distribute_parallel_for_num_threads_codegen.cpp
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple %itanium_abi_triple -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple %itanium_abi_triple -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/distribute_parallel_for_num_threads_messages.cpp b/test/OpenMP/distribute_parallel_for_num_threads_messages.cpp
index 7939514249a0..110f5d70f8d1 100644
--- a/test/OpenMP/distribute_parallel_for_num_threads_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_num_threads_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_parallel_for_private_codegen.cpp b/test/OpenMP/distribute_parallel_for_private_codegen.cpp
index d8d8a9a1edec..a731031db734 100644
--- a/test/OpenMP/distribute_parallel_for_private_codegen.cpp
+++ b/test/OpenMP/distribute_parallel_for_private_codegen.cpp
@@ -5,12 +5,28 @@
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/distribute_parallel_for_private_messages.cpp b/test/OpenMP/distribute_parallel_for_private_messages.cpp
index 465357a43388..75fe47ae8204 100644
--- a/test/OpenMP/distribute_parallel_for_private_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_private_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_parallel_for_proc_bind_codegen.cpp b/test/OpenMP/distribute_parallel_for_proc_bind_codegen.cpp
index 958b4e782f10..fce005be80fb 100644
--- a/test/OpenMP/distribute_parallel_for_proc_bind_codegen.cpp
+++ b/test/OpenMP/distribute_parallel_for_proc_bind_codegen.cpp
@@ -3,6 +3,11 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -60,7 +65,7 @@ int main() {
// CHECK: [[GTID_REF:%.+]] = load i32*, i32** [[GTID_ADDR]],
// CHECK: [[GTID_VAL:%.+]] = load i32, i32* [[GTID_REF]],
// CHECK: call {{.*}}void @__kmpc_push_proc_bind([[IDENT_T_TY]]* [[DEF_LOC_2]], i32 [[GTID_VAL]], i32 4)
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
// CHECK: ret void
// CHECK: define{{.+}} [[OFFL2]]()
@@ -72,7 +77,7 @@ int main() {
// CHECK: [[GTID_REF:%.+]] = load i32*, i32** [[GTID_ADDR]],
// CHECK: [[GTID_VAL:%.+]] = load i32, i32* [[GTID_REF]],
// CHECK: call {{.*}}void @__kmpc_push_proc_bind([[IDENT_T_TY]]* [[DEF_LOC_2]], i32 [[GTID_VAL]], i32 3)
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
// CHECK: ret void
// CHECK: define{{.+}} [[TMAIN]]()
@@ -88,6 +93,6 @@ int main() {
// CHECK: [[GTID_REF:%.+]] = load i32*, i32** [[GTID_ADDR]],
// CHECK: [[GTID_VAL:%.+]] = load i32, i32* [[GTID_REF]],
// CHECK: call {{.*}}void @__kmpc_push_proc_bind([[IDENT_T_TY]]* [[DEF_LOC_2]], i32 [[GTID_VAL]], i32 2)
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
// CHECK: ret void
#endif
diff --git a/test/OpenMP/distribute_parallel_for_proc_bind_messages.cpp b/test/OpenMP/distribute_parallel_for_proc_bind_messages.cpp
index 9898f9dc65b6..febf4b05643a 100644
--- a/test/OpenMP/distribute_parallel_for_proc_bind_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_proc_bind_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo();
template <class T, typename S, int N>
diff --git a/test/OpenMP/distribute_parallel_for_reduction_codegen.cpp b/test/OpenMP/distribute_parallel_for_reduction_codegen.cpp
new file mode 100644
index 000000000000..dc2a3ca5350f
--- /dev/null
+++ b/test/OpenMP/distribute_parallel_for_reduction_codegen.cpp
@@ -0,0 +1,84 @@
+// Test host code gen
+
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+
+template <typename T>
+T tmain(T &r) {
+ int n = 1000;
+ // schedule: dynamic chunk
+ #pragma omp target map(tofrom:r)
+ #pragma omp teams
+ #pragma omp distribute parallel for reduction(+:r)
+ for (int i = 0; i < n; ++i)
+ r += (T)i;
+
+ return r;
+}
+
+int main() {
+ int n = 1000;
+ int r = 0;
+ #pragma omp target map(tofrom:r)
+ #pragma omp teams
+ #pragma omp distribute parallel for reduction(+:r)
+ for (int i = 0; i < n; ++i)
+ r += i;
+
+ return tmain<int>(r);
+}
+
+// CHECK-LABEL: main
+// CHECK: call{{.+}} @__tgt_target_teams(
+// CHECK: call void [[OFFL:@.+]](
+// CHECK: call{{.+}} [[TMAIN:@.+]](i{{32|64}}
+// CHECK: ret
+
+// CHECK: define{{.+}} [[OFFL]](
+// CHECK: call{{.+}} @__kmpc_fork_teams({{.+}}, {{.+}}, {{.+}} [[TEOUTL:@.+]] to{{.+}}
+// CHECK: ret void
+
+// CHECK: define{{.+}} [[TEOUTL]](
+// CHECK: call{{.+}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} [[PAROUTL:@.+]] to{{.+}}
+// CHECK: ret void
+
+// CHECK: define{{.+}} [[PAROUTL]](
+// CHECK: call{{.+}} @__kmpc_reduce_nowait(
+// CHECK: call{{.+}} @__kmpc_end_reduce_nowait(
+// CHECK: ret void
+
+// CHECK: define{{.+}} [[TMAIN]](i{{32|64}}
+// CHECK: call{{.+}} @__tgt_target_teams(
+// CHECK: call void [[TOFFL:@.+]](
+// CHECK: ret
+
+// CHECK: define{{.+}} [[TOFFL]](
+// CHECK: call{{.+}} @__kmpc_fork_teams({{.+}}, {{.+}}, {{.+}} [[TEMPLTEOUTL:@.+]] to{{.+}}
+// CHECK: ret void
+
+// CHECK: define{{.+}} [[TEMPLTEOUTL]](
+// CHECK: call{{.+}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} [[TPAROUTL:@.+]] to{{.+}}
+// CHECK: ret void
+
+// CHECK: define{{.+}} [[TPAROUTL]](
+// CHECK: call{{.+}} @__kmpc_reduce_nowait(
+// CHECK: call{{.+}} @__kmpc_end_reduce_nowait(
+// CHECK: ret void
+
+#endif // HEADER
diff --git a/test/OpenMP/distribute_parallel_for_reduction_messages.cpp b/test/OpenMP/distribute_parallel_for_reduction_messages.cpp
index 0bf1bc0472eb..21a1eb40608d 100644
--- a/test/OpenMP/distribute_parallel_for_reduction_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_reduction_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 150 -o - %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 150 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_parallel_for_schedule_messages.cpp b/test/OpenMP/distribute_parallel_for_schedule_messages.cpp
index 6363cd7caef0..1f521d4f6fd6 100644
--- a/test/OpenMP/distribute_parallel_for_schedule_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_schedule_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_parallel_for_shared_messages.cpp b/test/OpenMP/distribute_parallel_for_shared_messages.cpp
index d5725e7f1b09..01c582cdbd44 100644
--- a/test/OpenMP/distribute_parallel_for_shared_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_shared_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
struct S1; // expected-note 2 {{declared here}}
extern S1 a;
diff --git a/test/OpenMP/distribute_parallel_for_simd_aligned_messages.cpp b/test/OpenMP/distribute_parallel_for_simd_aligned_messages.cpp
index 2d99d7d8f4bc..0c94f5b12d0c 100644
--- a/test/OpenMP/distribute_parallel_for_simd_aligned_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_aligned_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -x c++ -std=c++11 -verify -fopenmp %s
+// RUN: %clang_cc1 -x c++ -std=c++11 -verify -fopenmp-simd %s
+
struct B {
static int ib[20]; // expected-note 0 {{'B::ib' declared here}}
static constexpr int bfoo() { return 8; }
diff --git a/test/OpenMP/distribute_parallel_for_simd_ast_print.cpp b/test/OpenMP/distribute_parallel_for_simd_ast_print.cpp
index 21010638be15..fff6f965b4c2 100644
--- a/test/OpenMP/distribute_parallel_for_simd_ast_print.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -38,7 +42,7 @@ public:
}
};
-// CHECK: #pragma omp distribute parallel for simd private(this->a) private(this->a) private(T::a)
+// CHECK: #pragma omp distribute parallel for simd private(this->a) private(this->a) private(T::a){{$}}
// CHECK: #pragma omp distribute parallel for simd private(this->a) private(this->a) linear(k)
// CHECK: #pragma omp distribute parallel for simd private(this->a) private(this->a) private(this->S::a)
diff --git a/test/OpenMP/distribute_parallel_for_simd_codegen.cpp b/test/OpenMP/distribute_parallel_for_simd_codegen.cpp
index 59e6df90bbcb..129d90b746c4 100644
--- a/test/OpenMP/distribute_parallel_for_simd_codegen.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_codegen.cpp
@@ -6,12 +6,28 @@
// RUN: %clang_cc1 -DLAMBDA -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/distribute_parallel_for_simd_collapse_messages.cpp b/test/OpenMP/distribute_parallel_for_simd_collapse_messages.cpp
index 8690b4aac432..b12dcc19d020 100644
--- a/test/OpenMP/distribute_parallel_for_simd_collapse_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_collapse_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_parallel_for_simd_copyin_messages.cpp b/test/OpenMP/distribute_parallel_for_simd_copyin_messages.cpp
index 2d1a3dc5124b..2d72925518d4 100644
--- a/test/OpenMP/distribute_parallel_for_simd_copyin_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_copyin_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_parallel_for_simd_default_messages.cpp b/test/OpenMP/distribute_parallel_for_simd_default_messages.cpp
index 5c32306d96d1..3014d039d296 100644
--- a/test/OpenMP/distribute_parallel_for_simd_default_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_default_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo();
template <class T, int N>
diff --git a/test/OpenMP/distribute_parallel_for_simd_dist_schedule_messages.cpp b/test/OpenMP/distribute_parallel_for_simd_dist_schedule_messages.cpp
index 2e3ee2b1d50e..f029b0e187fa 100644
--- a/test/OpenMP/distribute_parallel_for_simd_dist_schedule_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_dist_schedule_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_parallel_for_simd_firstprivate_codegen.cpp b/test/OpenMP/distribute_parallel_for_simd_firstprivate_codegen.cpp
index b8d0f4ad7540..1447b5ff2ee2 100644
--- a/test/OpenMP/distribute_parallel_for_simd_firstprivate_codegen.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_firstprivate_codegen.cpp
@@ -5,12 +5,27 @@
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -311,7 +326,7 @@ int main() {
// CHECK-DAG: [[VEC_ADDR_VAL:%.+]] = load {{.+}}*, {{.+}}** [[VEC_ADDR]],
// CHECK-DAG: [[VEC_PRIV_BCAST:%.+]] = bitcast {{.+}} [[VEC_PRIV]] to
// CHECK-DAG: [[VEC_ADDR_BCAST:%.+]] = bitcast {{.+}} [[VEC_ADDR_VAL]] to
-// CHECK-DAG: call void @llvm.memcpy{{.+}}({{.+}}* [[VEC_PRIV_BCAST]], {{.+}}* [[VEC_ADDR_BCAST]],
+// CHECK-DAG: call void @llvm.memcpy{{.+}}({{.+}}* align {{[0-9]+}} [[VEC_PRIV_BCAST]], {{.+}}* align {{[0-9]+}} [[VEC_ADDR_BCAST]],
// s_arr
// CHECK-DAG: [[S_ARR_ADDR_VAL:%.+]] = load {{.+}}*, {{.+}}** [[S_ARR_ADDR]],
@@ -328,7 +343,7 @@ int main() {
// CHECK-DAG: [[TMP_REF:%.+]] = load {{.+}}*, {{.+}}* [[TMP]],
// CHECK-DAG: [[VAR_PRIV_BCAST:%.+]] = bitcast {{.+}}* [[VAR_PRIV]] to
// CHECK-DAG: [[TMP_REF_BCAST:%.+]] = bitcast {{.+}}* [[TMP_REF]] to
-// CHECK-DAG: call void @llvm.memcpy.{{.+}}({{.+}}* [[VAR_PRIV_BCAST]], {{.+}}* [[TMP_REF_BCAST]],
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}({{.+}}* align {{[0-9]+}} [[VAR_PRIV_BCAST]], {{.+}}* align {{[0-9]+}} [[TMP_REF_BCAST]],
// CHECK-DAG: store {{.+}}* [[VAR_PRIV]], {{.+}}** [[TMP_PRIV]],
// svar
@@ -404,7 +419,7 @@ int main() {
// CHECK-DAG: [[VEC_ADDR_VAL:%.+]] = load {{.+}}*, {{.+}}** [[VEC_ADDR]],
// CHECK-DAG: [[VEC_PRIV_BCAST:%.+]] = bitcast {{.+}} [[VEC_PRIV]] to
// CHECK-DAG: [[VEC_ADDR_BCAST:%.+]] = bitcast {{.+}} [[VEC_ADDR_VAL]] to
-// CHECK-DAG: call void @llvm.memcpy{{.+}}({{.+}}* [[VEC_PRIV_BCAST]], {{.+}}* [[VEC_ADDR_BCAST]],
+// CHECK-DAG: call void @llvm.memcpy{{.+}}({{.+}}* align {{[0-9]+}} [[VEC_PRIV_BCAST]], {{.+}}* align {{[0-9]+}} [[VEC_ADDR_BCAST]],
// s_arr
// CHECK-DAG: [[S_ARR_ADDR_VAL:%.+]] = load {{.+}}*, {{.+}}** [[S_ARR_ADDR]],
@@ -421,7 +436,7 @@ int main() {
// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load {{.+}}*, {{.+}}* [[VAR_ADDR]],
// CHECK-DAG: [[VAR_PRIV_BCAST:%.+]] = bitcast {{.+}}* [[VAR_PRIV]] to
// CHECK-DAG: [[VAR_ADDR_BCAST:%.+]] = bitcast {{.+}}* [[VAR_ADDR_REF]] to
-// CHECK-DAG: call void @llvm.memcpy.{{.+}}({{.+}}* [[VAR_PRIV_BCAST]], {{.+}}* [[VAR_ADDR_BCAST]],
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}({{.+}}* align {{[0-9]+}} [[VAR_PRIV_BCAST]], {{.+}}* align {{[0-9]+}} [[VAR_ADDR_BCAST]],
// CHECK-DAG: store {{.+}}* [[VAR_PRIV]], {{.+}}** [[TMP_PRIV]],
// CHECK: call void @__kmpc_for_static_init_4(
@@ -493,7 +508,7 @@ int main() {
// CHECK-DAG: [[VEC_ADDR_VAL:%.+]] = load {{.+}}*, {{.+}}** [[VEC_ADDR]],
// CHECK-DAG: [[VEC_PRIV_BCAST:%.+]] = bitcast {{.+}} [[VEC_PRIV]] to
// CHECK-DAG: [[VEC_ADDR_BCAST:%.+]] = bitcast {{.+}} [[VEC_ADDR_VAL]] to
-// CHECK-DAG: call void @llvm.memcpy{{.+}}({{.+}}* [[VEC_PRIV_BCAST]], {{.+}}* [[VEC_ADDR_BCAST]],
+// CHECK-DAG: call void @llvm.memcpy{{.+}}({{.+}}* align {{[0-9]+}} [[VEC_PRIV_BCAST]], {{.+}}* align {{[0-9]+}} [[VEC_ADDR_BCAST]],
// s_arr
// CHECK-DAG: [[S_ARR_ADDR_VAL:%.+]] = load {{.+}}*, {{.+}}** [[S_ARR_ADDR]],
@@ -510,7 +525,7 @@ int main() {
// CHECK-DAG: [[TMP_REF:%.+]] = load {{.+}}*, {{.+}}* [[TMP]],
// CHECK-DAG: [[VAR_PRIV_BCAST:%.+]] = bitcast {{.+}}* [[VAR_PRIV]] to
// CHECK-DAG: [[TMP_REF_BCAST:%.+]] = bitcast {{.+}}* [[TMP_REF]] to
-// CHECK-DAG: call void @llvm.memcpy.{{.+}}({{.+}}* [[VAR_PRIV_BCAST]], {{.+}}* [[TMP_REF_BCAST]],
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}({{.+}}* align {{[0-9]+}} [[VAR_PRIV_BCAST]], {{.+}}* align {{[0-9]+}} [[TMP_REF_BCAST]],
// CHECK-DAG: store {{.+}}* [[VAR_PRIV]], {{.+}}** [[TMP_PRIV]],
// CHECK: call void @__kmpc_for_static_init_4(
@@ -574,7 +589,7 @@ int main() {
// CHECK-DAG: [[VEC_ADDR_VAL:%.+]] = load {{.+}}*, {{.+}}** [[VEC_ADDR]],
// CHECK-DAG: [[VEC_PRIV_BCAST:%.+]] = bitcast {{.+}} [[VEC_PRIV]] to
// CHECK-DAG: [[VEC_ADDR_BCAST:%.+]] = bitcast {{.+}} [[VEC_ADDR_VAL]] to
-// CHECK-DAG: call void @llvm.memcpy{{.+}}({{.+}}* [[VEC_PRIV_BCAST]], {{.+}}* [[VEC_ADDR_BCAST]],
+// CHECK-DAG: call void @llvm.memcpy{{.+}}({{.+}}* align {{[0-9]+}} [[VEC_PRIV_BCAST]], {{.+}}* align {{[0-9]+}} [[VEC_ADDR_BCAST]],
// s_arr
// CHECK-DAG: [[S_ARR_ADDR_VAL:%.+]] = load {{.+}}*, {{.+}}** [[S_ARR_ADDR]],
@@ -591,7 +606,7 @@ int main() {
// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load {{.+}}*, {{.+}}* [[VAR_ADDR]],
// CHECK-DAG: [[VAR_PRIV_BCAST:%.+]] = bitcast {{.+}}* [[VAR_PRIV]] to
// CHECK-DAG: [[VAR_ADDR_BCAST:%.+]] = bitcast {{.+}}* [[VAR_ADDR_REF]] to
-// CHECK-DAG: call void @llvm.memcpy.{{.+}}({{.+}}* [[VAR_PRIV_BCAST]], {{.+}}* [[VAR_ADDR_BCAST]],
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}({{.+}}* align {{[0-9]+}} [[VAR_PRIV_BCAST]], {{.+}}* align {{[0-9]+}} [[VAR_ADDR_BCAST]],
// CHECK-DAG: store {{.+}}* [[VAR_PRIV]], {{.+}}** [[TMP_PRIV]],
// CHECK: call void @__kmpc_for_static_init_4(
diff --git a/test/OpenMP/distribute_parallel_for_simd_firstprivate_messages.cpp b/test/OpenMP/distribute_parallel_for_simd_firstprivate_messages.cpp
index 646407643b25..d6f56d5b2169 100644
--- a/test/OpenMP/distribute_parallel_for_simd_firstprivate_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_firstprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_parallel_for_simd_if_codegen.cpp b/test/OpenMP/distribute_parallel_for_simd_if_codegen.cpp
index b55038720134..2beea79c42fe 100644
--- a/test/OpenMP/distribute_parallel_for_simd_if_codegen.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_if_codegen.cpp
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple %itanium_abi_triple -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple %itanium_abi_triple -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple %itanium_abi_triple -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple %itanium_abi_triple -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/distribute_parallel_for_simd_if_messages.cpp b/test/OpenMP/distribute_parallel_for_simd_if_messages.cpp
index c6957b9a868b..0f9e12381f0e 100644
--- a/test/OpenMP/distribute_parallel_for_simd_if_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_if_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_parallel_for_simd_lastprivate_codegen.cpp b/test/OpenMP/distribute_parallel_for_simd_lastprivate_codegen.cpp
index 89ef33abd64d..af74ab7b72a5 100644
--- a/test/OpenMP/distribute_parallel_for_simd_lastprivate_codegen.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_lastprivate_codegen.cpp
@@ -5,12 +5,28 @@
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -343,7 +359,7 @@ int main() {
// CHECK: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_ADDR_REF]],
// CHECK: [[BCAST_VEC_ADDR_REF:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_REF]] to i8*
// CHECK: [[BCAST_VEC_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[BCAST_VEC_ADDR_REF]], i8* [[BCAST_VEC_PRIV]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[BCAST_VEC_ADDR_REF]], i8* align {{[0-9]+}} [[BCAST_VEC_PRIV]],
// CHECK: [[S_ARR_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_ADDR_REF]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[S_ARR_PRIV_BCAST:%.+]] = bitcast [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]] to [[S_FLOAT_TY]]*
// CHECK: [[S_ARR_BEGIN_GEP:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[S_ARR_BEGIN]], i{{[0-9]+}} 2
@@ -354,7 +370,7 @@ int main() {
// CHECK: [[S_ARR_DST_EL:%.+]] = phi [[S_FLOAT_TY]]*{{.+}}
// CHECK: [[S_ARR_DST_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_DST_EL]] to i8*
// CHECK: [[S_ARR_SRC_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_SRC_EL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_DST_BCAST]], i8* [[S_ARR_SRC_BCAST]]{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_DST_BCAST]], i8* align {{[0-9]+}} [[S_ARR_SRC_BCAST]]{{.+}})
// CHECK: [[S_ARR_DST_NEXT:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[S_ARR_DST_EL]], i{{[0-9]+}} 1
// CHECK: [[S_ARR_SRC_NEXT:%.+]] = getelementptr{{.+}}
// CHECK: [[CPY_IS_FINISHED:%.+]] = icmp eq [[S_FLOAT_TY]]* [[S_ARR_DST_NEXT]], [[S_ARR_BEGIN_GEP]]
@@ -363,7 +379,7 @@ int main() {
// CHECK: [[TMP_VAL1:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP_PRIV]],
// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_REF]] to i8*
// CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VAR_ADDR_REF_BCAST]], i8* [[TMP_VAL1_BCAST]],{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}})
// CHECK: [[SVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[S_VAR_PRIV]],
// CHECK: store i{{[0-9]+}} [[SVAR_VAL]], i{{[0-9]+}}* [[SVAR_ADDR_REF]],
// CHECK: ret void
@@ -435,7 +451,7 @@ int main() {
// CHECK-DAG: [[TMP_VAL:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP_PRIV]],
// CHECK-DAG: [[S_ARR_PTR_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_PTR]] to i8*
// CHECK-DAG: [[TMP_VAL_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_VAL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_PTR_BCAST]], i8* [[TMP_VAL_BCAST]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_PTR_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL_BCAST]],
// CHECK: call void @__kmpc_for_static_fini(
@@ -449,7 +465,7 @@ int main() {
// CHECK: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_ADDR_REF]],
// CHECK: [[BCAST_VEC_ADDR_REF:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_REF]] to i8*
// CHECK: [[BCAST_VEC_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[BCAST_VEC_ADDR_REF]], i8* [[BCAST_VEC_PRIV]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[BCAST_VEC_ADDR_REF]], i8* align {{[0-9]+}} [[BCAST_VEC_PRIV]],
// CHECK: [[S_ARR_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_ADDR_REF]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[S_ARR_PRIV_BCAST:%.+]] = bitcast [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]] to [[S_FLOAT_TY]]*
// CHECK: [[S_ARR_BEGIN_GEP:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[S_ARR_BEGIN]], i{{[0-9]+}} 2
@@ -460,7 +476,7 @@ int main() {
// CHECK: [[S_ARR_DST_EL:%.+]] = phi [[S_FLOAT_TY]]*{{.+}}
// CHECK: [[S_ARR_DST_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_DST_EL]] to i8*
// CHECK: [[S_ARR_SRC_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_SRC_EL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_DST_BCAST]], i8* [[S_ARR_SRC_BCAST]]{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_DST_BCAST]], i8* align {{[0-9]+}} [[S_ARR_SRC_BCAST]]{{.+}})
// CHECK: [[S_ARR_DST_NEXT:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[S_ARR_DST_EL]], i{{[0-9]+}} 1
// CHECK: [[S_ARR_SRC_NEXT:%.+]] = getelementptr{{.+}}
// CHECK: [[CPY_IS_FINISHED:%.+]] = icmp eq [[S_FLOAT_TY]]* [[S_ARR_DST_NEXT]], [[S_ARR_BEGIN_GEP]]
@@ -469,7 +485,7 @@ int main() {
// CHECK: [[TMP_VAL1:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP_PRIV]],
// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[VAR_ADDR_REF]] to i8*
// CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VAR_ADDR_REF_BCAST]], i8* [[TMP_VAL1_BCAST]],{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}})
// CHECK: [[SVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[S_VAR_PRIV]],
// CHECK: store i{{[0-9]+}} [[SVAR_VAL]], i{{[0-9]+}}* [[SVAR_ADDR_REF]],
// CHECK: ret void
@@ -543,7 +559,7 @@ int main() {
// CHECK: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_ADDR_REF]],
// CHECK: [[BCAST_VEC_ADDR_REF:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_REF]] to i8*
// CHECK: [[BCAST_VEC_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[BCAST_VEC_ADDR_REF]], i8* [[BCAST_VEC_PRIV]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[BCAST_VEC_ADDR_REF]], i8* align {{[0-9]+}} [[BCAST_VEC_PRIV]],
// CHECK: [[S_ARR_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_ADDR_REF]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[S_ARR_PRIV_BCAST:%.+]] = bitcast [2 x [[S_INT_TY]]]* [[S_ARR_PRIV]] to [[S_INT_TY]]*
// CHECK: [[S_ARR_BEGIN_GEP:%.+]] = getelementptr [[S_INT_TY]], [[S_INT_TY]]* [[S_ARR_BEGIN]], i{{[0-9]+}} 2
@@ -554,7 +570,7 @@ int main() {
// CHECK: [[S_ARR_DST_EL:%.+]] = phi [[S_INT_TY]]*{{.+}}
// CHECK: [[S_ARR_DST_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_DST_EL]] to i8*
// CHECK: [[S_ARR_SRC_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_SRC_EL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_DST_BCAST]], i8* [[S_ARR_SRC_BCAST]]{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_DST_BCAST]], i8* align {{[0-9]+}} [[S_ARR_SRC_BCAST]]{{.+}})
// CHECK: [[S_ARR_DST_NEXT:%.+]] = getelementptr [[S_INT_TY]], [[S_INT_TY]]* [[S_ARR_DST_EL]], i{{[0-9]+}} 1
// CHECK: [[S_ARR_SRC_NEXT:%.+]] = getelementptr{{.+}}
// CHECK: [[CPY_IS_FINISHED:%.+]] = icmp eq [[S_INT_TY]]* [[S_ARR_DST_NEXT]], [[S_ARR_BEGIN_GEP]]
@@ -563,7 +579,7 @@ int main() {
// CHECK: [[TMP_VAL:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP_PRIV]],
// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_REF]] to i8*
// CHECK: [[TMP_VAL_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VAR_ADDR_REF_BCAST]], i8* [[TMP_VAL_BCAST]],{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL_BCAST]],{{.+}})
// CHECK: ret void
// outlined function for 'parallel for'
@@ -629,7 +645,7 @@ int main() {
// CHECK-DAG: [[TMP_VAL:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP_PRIV]],
// CHECK-DAG: [[S_ARR_PTR_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_PTR]] to i8*
// CHECK-DAG: [[TMP_VAL_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL]] to i8*
-// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_PTR_BCAST]], i8* [[TMP_VAL_BCAST]],
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_PTR_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL_BCAST]],
// CHECK: call void @__kmpc_for_static_fini(
@@ -643,7 +659,7 @@ int main() {
// CHECK: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_ADDR_REF]],
// CHECK: [[BCAST_VEC_ADDR_REF:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_REF]] to i8*
// CHECK: [[BCAST_VEC_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[BCAST_VEC_ADDR_REF]], i8* [[BCAST_VEC_PRIV]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[BCAST_VEC_ADDR_REF]], i8* align {{[0-9]+}} [[BCAST_VEC_PRIV]],
// CHECK: [[S_ARR_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_ADDR_REF]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[S_ARR_PRIV_BCAST:%.+]] = bitcast [2 x [[S_INT_TY]]]* [[S_ARR_PRIV]] to [[S_INT_TY]]*
// CHECK: [[S_ARR_BEGIN_GEP:%.+]] = getelementptr [[S_INT_TY]], [[S_INT_TY]]* [[S_ARR_BEGIN]], i{{[0-9]+}} 2
@@ -654,7 +670,7 @@ int main() {
// CHECK: [[S_ARR_DST_EL:%.+]] = phi [[S_INT_TY]]*{{.+}}
// CHECK: [[S_ARR_DST_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_DST_EL]] to i8*
// CHECK: [[S_ARR_SRC_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_SRC_EL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_DST_BCAST]], i8* [[S_ARR_SRC_BCAST]]{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_DST_BCAST]], i8* align {{[0-9]+}} [[S_ARR_SRC_BCAST]]{{.+}})
// CHECK: [[S_ARR_DST_NEXT:%.+]] = getelementptr [[S_INT_TY]], [[S_INT_TY]]* [[S_ARR_DST_EL]], i{{[0-9]+}} 1
// CHECK: [[S_ARR_SRC_NEXT:%.+]] = getelementptr{{.+}}
// CHECK: [[CPY_IS_FINISHED:%.+]] = icmp eq [[S_INT_TY]]* [[S_ARR_DST_NEXT]], [[S_ARR_BEGIN_GEP]]
@@ -663,7 +679,7 @@ int main() {
// CHECK: [[TMP_VAL1:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP_PRIV]],
// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[VAR_ADDR_REF]] to i8*
// CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VAR_ADDR_REF_BCAST]], i8* [[TMP_VAL1_BCAST]],{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}})
// CHECK: ret void
// CHECK: !{!"llvm.loop.vectorize.enable", i1 true}
diff --git a/test/OpenMP/distribute_parallel_for_simd_lastprivate_messages.cpp b/test/OpenMP/distribute_parallel_for_simd_lastprivate_messages.cpp
index 73450d4f1181..45e0d44322a5 100644
--- a/test/OpenMP/distribute_parallel_for_simd_lastprivate_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_lastprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_parallel_for_simd_linear_messages.cpp b/test/OpenMP/distribute_parallel_for_simd_linear_messages.cpp
index 66fd94b9e0f2..788bace434f9 100644
--- a/test/OpenMP/distribute_parallel_for_simd_linear_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_linear_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
namespace X {
int x;
};
diff --git a/test/OpenMP/distribute_parallel_for_simd_loop_messages.cpp b/test/OpenMP/distribute_parallel_for_simd_loop_messages.cpp
index d137d47ca2a4..20ee49a6fcc4 100644
--- a/test/OpenMP/distribute_parallel_for_simd_loop_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_loop_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+
class S {
int a;
S() : a(0) {} // expected-note {{implicitly declared private here}}
diff --git a/test/OpenMP/distribute_parallel_for_simd_misc_messages.c b/test/OpenMP/distribute_parallel_for_simd_misc_messages.c
index 4d071621fcb8..c2bee7ffa70e 100644
--- a/test/OpenMP/distribute_parallel_for_simd_misc_messages.c
+++ b/test/OpenMP/distribute_parallel_for_simd_misc_messages.c
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -verify %s
+
// expected-error@+1 {{unexpected OpenMP directive '#pragma omp distribute parallel for simd'}}
#pragma omp distribute parallel for simd
diff --git a/test/OpenMP/distribute_parallel_for_simd_num_threads_codegen.cpp b/test/OpenMP/distribute_parallel_for_simd_num_threads_codegen.cpp
index 5804a2a72b71..014fb9523fe5 100644
--- a/test/OpenMP/distribute_parallel_for_simd_num_threads_codegen.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_num_threads_codegen.cpp
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple %itanium_abi_triple -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple %itanium_abi_triple -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/distribute_parallel_for_simd_num_threads_messages.cpp b/test/OpenMP/distribute_parallel_for_simd_num_threads_messages.cpp
index 0d6376d76b7b..5f5165d979c2 100644
--- a/test/OpenMP/distribute_parallel_for_simd_num_threads_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_num_threads_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_parallel_for_simd_private_codegen.cpp b/test/OpenMP/distribute_parallel_for_simd_private_codegen.cpp
index 8ffe521bfcbc..629e023b6597 100644
--- a/test/OpenMP/distribute_parallel_for_simd_private_codegen.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_private_codegen.cpp
@@ -5,12 +5,28 @@
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/distribute_parallel_for_simd_private_messages.cpp b/test/OpenMP/distribute_parallel_for_simd_private_messages.cpp
index 9df368890c8d..d23d9176ed2e 100644
--- a/test/OpenMP/distribute_parallel_for_simd_private_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_private_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_parallel_for_simd_proc_bind_codegen.cpp b/test/OpenMP/distribute_parallel_for_simd_proc_bind_codegen.cpp
index 7f0b631aee7f..4fb1f5b0274d 100644
--- a/test/OpenMP/distribute_parallel_for_simd_proc_bind_codegen.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_proc_bind_codegen.cpp
@@ -3,6 +3,11 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -60,7 +65,7 @@ int main() {
// CHECK: [[GTID_REF:%.+]] = load i32*, i32** [[GTID_ADDR]],
// CHECK: [[GTID_VAL:%.+]] = load i32, i32* [[GTID_REF]],
// CHECK: call {{.*}}void @__kmpc_push_proc_bind([[IDENT_T_TY]]* [[DEF_LOC_2]], i32 [[GTID_VAL]], i32 4)
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
// CHECK: ret void
// CHECK: define{{.+}} [[OFFL2]]()
@@ -72,7 +77,7 @@ int main() {
// CHECK: [[GTID_REF:%.+]] = load i32*, i32** [[GTID_ADDR]],
// CHECK: [[GTID_VAL:%.+]] = load i32, i32* [[GTID_REF]],
// CHECK: call {{.*}}void @__kmpc_push_proc_bind([[IDENT_T_TY]]* [[DEF_LOC_2]], i32 [[GTID_VAL]], i32 3)
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
// CHECK: ret void
// CHECK: define{{.+}} [[TMAIN]]()
@@ -88,6 +93,6 @@ int main() {
// CHECK: [[GTID_REF:%.+]] = load i32*, i32** [[GTID_ADDR]],
// CHECK: [[GTID_VAL:%.+]] = load i32, i32* [[GTID_REF]],
// CHECK: call {{.*}}void @__kmpc_push_proc_bind([[IDENT_T_TY]]* [[DEF_LOC_2]], i32 [[GTID_VAL]], i32 2)
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
// CHECK: ret void
#endif
diff --git a/test/OpenMP/distribute_parallel_for_simd_proc_bind_messages.cpp b/test/OpenMP/distribute_parallel_for_simd_proc_bind_messages.cpp
index 6b64cc3879ea..d81f7d992071 100644
--- a/test/OpenMP/distribute_parallel_for_simd_proc_bind_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_proc_bind_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo();
template <class T, typename S, int N>
diff --git a/test/OpenMP/distribute_parallel_for_simd_reduction_messages.cpp b/test/OpenMP/distribute_parallel_for_simd_reduction_messages.cpp
index 94e4541b901b..348e664b782a 100644
--- a/test/OpenMP/distribute_parallel_for_simd_reduction_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_reduction_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 150 -o - %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 150 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_parallel_for_simd_safelen_messages.cpp b/test/OpenMP/distribute_parallel_for_simd_safelen_messages.cpp
index a5fd1aeb8436..93766f9a6a35 100644
--- a/test/OpenMP/distribute_parallel_for_simd_safelen_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_safelen_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_parallel_for_simd_schedule_messages.cpp b/test/OpenMP/distribute_parallel_for_simd_schedule_messages.cpp
index b3003dd9f2a1..8a5ffd159425 100644
--- a/test/OpenMP/distribute_parallel_for_simd_schedule_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_schedule_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_parallel_for_simd_shared_messages.cpp b/test/OpenMP/distribute_parallel_for_simd_shared_messages.cpp
index 134b85257933..fd694b7ba488 100644
--- a/test/OpenMP/distribute_parallel_for_simd_shared_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_shared_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
struct S1; // expected-note 2 {{declared here}}
extern S1 a;
diff --git a/test/OpenMP/distribute_parallel_for_simd_simdlen_messages.cpp b/test/OpenMP/distribute_parallel_for_simd_simdlen_messages.cpp
index 2d813ec232ad..8e40e3547f74 100644
--- a/test/OpenMP/distribute_parallel_for_simd_simdlen_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_simdlen_messages.cpp
@@ -2,6 +2,9 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_private_codegen.cpp b/test/OpenMP/distribute_private_codegen.cpp
index c637fb489241..c470e8f01222 100644
--- a/test/OpenMP/distribute_private_codegen.cpp
+++ b/test/OpenMP/distribute_private_codegen.cpp
@@ -5,12 +5,28 @@
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/distribute_private_messages.cpp b/test/OpenMP/distribute_private_messages.cpp
index 0aa1e4796975..3cf2fdc228b5 100644
--- a/test/OpenMP/distribute_private_messages.cpp
+++ b/test/OpenMP/distribute_private_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_simd_aligned_messages.cpp b/test/OpenMP/distribute_simd_aligned_messages.cpp
index 21b1bc9da1fa..51421d6cbdd2 100644
--- a/test/OpenMP/distribute_simd_aligned_messages.cpp
+++ b/test/OpenMP/distribute_simd_aligned_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -x c++ -std=c++11 -verify -fopenmp %s
+// RUN: %clang_cc1 -x c++ -std=c++11 -verify -fopenmp-simd %s
+
struct B {
static int ib[20]; // expected-note 0 {{'B::ib' declared here}}
static constexpr int bfoo() { return 8; }
diff --git a/test/OpenMP/distribute_simd_ast_print.cpp b/test/OpenMP/distribute_simd_ast_print.cpp
index 3246ccb46ae3..5133db695b3b 100644
--- a/test/OpenMP/distribute_simd_ast_print.cpp
+++ b/test/OpenMP/distribute_simd_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -37,7 +41,7 @@ public:
}
};
-// CHECK: #pragma omp distribute simd private(this->a) private(this->a) private(T::a)
+// CHECK: #pragma omp distribute simd private(this->a) private(this->a) private(T::a){{$}}
// CHECK: #pragma omp distribute simd private(this->a) private(this->a)
// CHECK: #pragma omp distribute simd private(this->a) private(this->a) private(this->S::a)
diff --git a/test/OpenMP/distribute_simd_codegen.cpp b/test/OpenMP/distribute_simd_codegen.cpp
index d8f18c3e431b..662d66af1107 100644
--- a/test/OpenMP/distribute_simd_codegen.cpp
+++ b/test/OpenMP/distribute_simd_codegen.cpp
@@ -6,6 +6,14 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix HCHECK
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// Test target codegen - host bc file has to be created first. (no significant differences with host version of target region)
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s
@@ -16,14 +24,24 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
-// CHECK-DAG: %ident_t = type { i32, i32, i32, i32, i8* }
+// CHECK-DAG: %struct.ident_t = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC_0:@.+]] = private unnamed_addr constant %ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
-// CHECK-DAG: [[DEF_LOC_DISTRIBUTE_0:@.+]] = private unnamed_addr constant %ident_t { i32 0, i32 2050, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC_0:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC_DISTRIBUTE_0:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2050, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
// CHECK-LABEL: define {{.*void}} @{{.*}}without_schedule_clause{{.*}}(float* {{.+}}, float* {{.+}}, float* {{.+}}, float* {{.+}})
void without_schedule_clause(float *a, float *b, float *c, float *d) {
@@ -50,7 +68,7 @@ void without_schedule_clause(float *a, float *b, float *c, float *d) {
// CHECK-DAG: store i32 0, i32* [[LAST]]
// CHECK-DAG: [[GBL_TID:%.+]] = load i32*, i32** [[TID_ADDR]]
// CHECK-DAG: [[GBL_TIDV:%.+]] = load i32, i32* [[GBL_TID]]
-// CHECK: call void @__kmpc_for_static_init_{{.+}}(%ident_t* [[DEF_LOC_DISTRIBUTE_0]], i32 [[GBL_TIDV]], i32 92, i32* %.omp.is_last, i32* %.omp.lb, i32* %.omp.ub, i32* %.omp.stride, i32 1, i32 1)
+// CHECK: call void @__kmpc_for_static_init_{{.+}}(%struct.ident_t* [[DEF_LOC_DISTRIBUTE_0]], i32 [[GBL_TIDV]], i32 92, i32* %.omp.is_last, i32* %.omp.lb, i32* %.omp.ub, i32* %.omp.stride, i32 1, i32 1)
// CHECK-DAG: [[UBV0:%.+]] = load i32, i32* [[UB]]
// CHECK-DAG: [[USWITCH:%.+]] = icmp sgt i32 [[UBV0]], 4571423
// CHECK: br i1 [[USWITCH]], label %[[BBCT:.+]], label %[[BBCF:.+]]
@@ -84,7 +102,7 @@ void without_schedule_clause(float *a, float *b, float *c, float *d) {
// CHECK: [[BBINNEND]]:
// CHECK: br label %[[LPEXIT:.+]]
// CHECK: [[LPEXIT]]:
-// CHECK: call void @__kmpc_for_static_fini(%ident_t* [[DEF_LOC_DISTRIBUTE_0]], i32 [[GBL_TIDV]])
+// CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* [[DEF_LOC_DISTRIBUTE_0]], i32 [[GBL_TIDV]])
// CHECK: ret void
@@ -112,7 +130,7 @@ void static_not_chunked(float *a, float *b, float *c, float *d) {
// CHECK-DAG: store i32 0, i32* [[LAST]]
// CHECK-DAG: [[GBL_TID:%.+]] = load i32*, i32** [[TID_ADDR]]
// CHECK-DAG: [[GBL_TIDV:%.+]] = load i32, i32* [[GBL_TID]]
-// CHECK: call void @__kmpc_for_static_init_{{.+}}(%ident_t* [[DEF_LOC_DISTRIBUTE_0]], i32 [[GBL_TIDV]], i32 92, i32* %.omp.is_last, i32* %.omp.lb, i32* %.omp.ub, i32* %.omp.stride, i32 1, i32 1)
+// CHECK: call void @__kmpc_for_static_init_{{.+}}(%struct.ident_t* [[DEF_LOC_DISTRIBUTE_0]], i32 [[GBL_TIDV]], i32 92, i32* %.omp.is_last, i32* %.omp.lb, i32* %.omp.ub, i32* %.omp.stride, i32 1, i32 1)
// CHECK-DAG: [[UBV0:%.+]] = load i32, i32* [[UB]]
// CHECK-DAG: [[USWITCH:%.+]] = icmp sgt i32 [[UBV0]], 4571423
// CHECK: br i1 [[USWITCH]], label %[[BBCT:.+]], label %[[BBCF:.+]]
@@ -146,7 +164,7 @@ void static_not_chunked(float *a, float *b, float *c, float *d) {
// CHECK: [[BBINNEND]]:
// CHECK: br label %[[LPEXIT:.+]]
// CHECK: [[LPEXIT]]:
-// CHECK: call void @__kmpc_for_static_fini(%ident_t* [[DEF_LOC_DISTRIBUTE_0]], i32 [[GBL_TIDV]])
+// CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* [[DEF_LOC_DISTRIBUTE_0]], i32 [[GBL_TIDV]])
// CHECK: ret void
@@ -174,7 +192,7 @@ void static_chunked(float *a, float *b, float *c, float *d) {
// CHECK-DAG: store i32 0, i32* [[LAST]]
// CHECK-DAG: [[GBL_TID:%.+]] = load i32*, i32** [[TID_ADDR]]
// CHECK-DAG: [[GBL_TIDV:%.+]] = load i32, i32* [[GBL_TID]]
-// CHECK: call void @__kmpc_for_static_init_{{.+}}(%ident_t* [[DEF_LOC_DISTRIBUTE_0]], i32 [[GBL_TIDV]], i32 91, i32* %.omp.is_last, i32* %.omp.lb, i32* %.omp.ub, i32* %.omp.stride, i32 1, i32 5)
+// CHECK: call void @__kmpc_for_static_init_{{.+}}(%struct.ident_t* [[DEF_LOC_DISTRIBUTE_0]], i32 [[GBL_TIDV]], i32 91, i32* %.omp.is_last, i32* %.omp.lb, i32* %.omp.ub, i32* %.omp.stride, i32 1, i32 5)
// CHECK-DAG: [[UBV0:%.+]] = load i32, i32* [[UB]]
// CHECK-DAG: [[USWITCH:%.+]] = icmp ugt i32 [[UBV0]], 16908288
// CHECK: br i1 [[USWITCH]], label %[[BBCT:.+]], label %[[BBCF:.+]]
@@ -208,7 +226,7 @@ void static_chunked(float *a, float *b, float *c, float *d) {
// CHECK: [[BBINNEND]]:
// CHECK: br label %[[LPEXIT:.+]]
// CHECK: [[LPEXIT]]:
-// CHECK: call void @__kmpc_for_static_fini(%ident_t* [[DEF_LOC_DISTRIBUTE_0]], i32 [[GBL_TIDV]])
+// CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* [[DEF_LOC_DISTRIBUTE_0]], i32 [[GBL_TIDV]])
// CHECK: ret void
// CHECK-LABEL: test_precond
diff --git a/test/OpenMP/distribute_simd_collapse_messages.cpp b/test/OpenMP/distribute_simd_collapse_messages.cpp
index 182a09a92b6c..f4d5b73634c0 100644
--- a/test/OpenMP/distribute_simd_collapse_messages.cpp
+++ b/test/OpenMP/distribute_simd_collapse_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_simd_dist_schedule_messages.cpp b/test/OpenMP/distribute_simd_dist_schedule_messages.cpp
index 6a8482d8be09..c659abe71ba0 100644
--- a/test/OpenMP/distribute_simd_dist_schedule_messages.cpp
+++ b/test/OpenMP/distribute_simd_dist_schedule_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_simd_firstprivate_codegen.cpp b/test/OpenMP/distribute_simd_firstprivate_codegen.cpp
index 5da9c5dc3b1a..919a12284131 100644
--- a/test/OpenMP/distribute_simd_firstprivate_codegen.cpp
+++ b/test/OpenMP/distribute_simd_firstprivate_codegen.cpp
@@ -5,12 +5,28 @@
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -241,7 +257,7 @@ int main() {
// CHECK-DAG: [[VEC_ADDR_VAL:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]],
// CHECK-DAG: [[VEC_ADDR_VAL_BCAST:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i{{[0-9]+}}*
// CHECK-DAG: [[VEC_PRIV_BCAST:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i{{[0-9]+}}*
-// CHECK-DAG: call void @llvm.memcpy.{{.*}}(i{{[0-9]+}}* [[VEC_PRIV_BCAST]], i{{[0-9]+}}* [[VEC_ADDR_VAL_BCAST]],{{.+}})
+// CHECK-DAG: call void @llvm.memcpy.{{.*}}(i{{[0-9]+}}* align {{[0-9]+}} [[VEC_PRIV_BCAST]], i{{[0-9]+}}* align {{[0-9]+}} [[VEC_ADDR_VAL_BCAST]],{{.+}})
// init s_arr
// CHECK-DAG: [[S_ARR_ADDR_VAL:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[S_ARR_ADDR]],
@@ -256,7 +272,7 @@ int main() {
// CHECK-DAG: [[S_ARR_DST_PAST:%.+]] = phi{{.+}} [ [[S_ARR_PRIV_BGN]],{{.+}} ], [ [[S_ARR_DST:%.+]],{{.+}} ]
// CHECK-DAG: [[S_ARR_SRC_BCAST:%.+]] = bitcast{{.+}} [[S_ARR_SRC_PAST]] to{{.+}}
// CHECK-DAG: [[S_ARR_DST_BCAST:%.+]] = bitcast{{.+}} [[S_ARR_DST_PAST]] to{{.+}}
-// CHECK-DAG: call{{.+}} @llvm.memcpy.{{.+}}({{.+}}* [[S_ARR_DST_BCAST]], {{.+}}* [[S_ARR_SRC_BCAST]]{{.+}})
+// CHECK-DAG: call{{.+}} @llvm.memcpy.{{.+}}({{.+}}* align {{[0-9]+}} [[S_ARR_DST_BCAST]], {{.+}}* align {{[0-9]+}} [[S_ARR_SRC_BCAST]]{{.+}})
// CHECK-DAG: [[S_ARR_SRC]] = getelementptr{{.+}}
// CHECK-DAG: [[S_ARR_DST]] = getelementptr{{.+}}
// CHECK-DAG: [[S_ARR_CPY_FIN:%.+]] = icmp{{.+}} [[S_ARR_DST]], [[S_ARR_PRIV_NEXT]]
@@ -269,7 +285,7 @@ int main() {
// CHECK-DAG: [[TMP_VAL:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP]],
// CHECK-DAG: [[VAR_PRIV_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[VAR_PRIV]] to{{.+}}
// CHECK-DAG: [[TMP_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_VAL]] to{{.+}}
-// CHECK-DAG: call{{.+}} @llvm.memcpy.{{.+}}({{.+}}* [[VAR_PRIV_BCAST]], {{.+}}* [[TMP_BCAST]],{{.+}})
+// CHECK-DAG: call{{.+}} @llvm.memcpy.{{.+}}({{.+}}* align {{[0-9]+}} [[VAR_PRIV_BCAST]], {{.+}}* align {{[0-9]+}} [[TMP_BCAST]],{{.+}})
// CHECK-DAG: store [[S_FLOAT_TY]]* [[VAR_PRIV]], [[S_FLOAT_TY]]** [[TMP_PRIV]],
// init svar
@@ -336,7 +352,7 @@ int main() {
// CHECK-DAG: [[VEC_ADDR_VAL:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]],
// CHECK-DAG: [[VEC_ADDR_VAL_BCAST:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i{{[0-9]+}}*
// CHECK-DAG: [[VEC_PRIV_BCAST:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i{{[0-9]+}}*
-// CHECK-DAG: call void @llvm.memcpy.{{.*}}(i{{[0-9]+}}* [[VEC_PRIV_BCAST]], i{{[0-9]+}}* [[VEC_ADDR_VAL_BCAST]],{{.+}})
+// CHECK-DAG: call void @llvm.memcpy.{{.*}}(i{{[0-9]+}}* align {{[0-9]+}} [[VEC_PRIV_BCAST]], i{{[0-9]+}}* align {{[0-9]+}} [[VEC_ADDR_VAL_BCAST]],{{.+}})
// init s_arr
// CHECK-DAG: [[S_ARR_ADDR_VAL:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[S_ARR_ADDR]],
@@ -351,7 +367,7 @@ int main() {
// CHECK-DAG: [[S_ARR_DST_PAST:%.+]] = phi{{.+}} [ [[S_ARR_PRIV_BGN]],{{.+}} ], [ [[S_ARR_DST:%.+]],{{.+}} ]
// CHECK-DAG: [[S_ARR_SRC_BCAST:%.+]] = bitcast{{.+}} [[S_ARR_SRC_PAST]] to{{.+}}
// CHECK-DAG: [[S_ARR_DST_BCAST:%.+]] = bitcast{{.+}} [[S_ARR_DST_PAST]] to{{.+}}
-// CHECK-DAG: call{{.+}} @llvm.memcpy.{{.+}}({{.+}}* [[S_ARR_DST_BCAST]], {{.+}}* [[S_ARR_SRC_BCAST]]{{.+}})
+// CHECK-DAG: call{{.+}} @llvm.memcpy.{{.+}}({{.+}}* align {{[0-9]+}} [[S_ARR_DST_BCAST]], {{.+}}* align {{[0-9]+}} [[S_ARR_SRC_BCAST]]{{.+}})
// CHECK-DAG: [[S_ARR_SRC]] = getelementptr{{.+}}
// CHECK-DAG: [[S_ARR_DST]] = getelementptr{{.+}}
// CHECK-DAG: [[S_ARR_CPY_FIN:%.+]] = icmp{{.+}} [[S_ARR_DST]], [[S_ARR_PRIV_NEXT]]
@@ -364,7 +380,7 @@ int main() {
// CHECK-DAG: [[TMP_VAL:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP]],
// CHECK-DAG: [[VAR_PRIV_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[VAR_PRIV]] to{{.+}}
// CHECK-DAG: [[TMP_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL]] to{{.+}}
-// CHECK-DAG: call{{.+}} @llvm.memcpy.{{.+}}({{.+}}* [[VAR_PRIV_BCAST]], {{.+}}* [[TMP_BCAST]],{{.+}})
+// CHECK-DAG: call{{.+}} @llvm.memcpy.{{.+}}({{.+}}* align {{[0-9]+}} [[VAR_PRIV_BCAST]], {{.+}}* align {{[0-9]+}} [[TMP_BCAST]],{{.+}})
// CHECK-DAG: store [[S_INT_TY]]* [[VAR_PRIV]], [[S_INT_TY]]** [[TMP_PRIV]],
// CHECK-DAG: store i{{[0-9]+}} 0, i{{[0-9]+}}* %.omp{{.+}},
diff --git a/test/OpenMP/distribute_simd_firstprivate_messages.cpp b/test/OpenMP/distribute_simd_firstprivate_messages.cpp
index f0c293b78d80..e0f3ddeeeba1 100644
--- a/test/OpenMP/distribute_simd_firstprivate_messages.cpp
+++ b/test/OpenMP/distribute_simd_firstprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_simd_lastprivate_codegen.cpp b/test/OpenMP/distribute_simd_lastprivate_codegen.cpp
index df842a009879..cde7c81d50f9 100644
--- a/test/OpenMP/distribute_simd_lastprivate_codegen.cpp
+++ b/test/OpenMP/distribute_simd_lastprivate_codegen.cpp
@@ -5,12 +5,28 @@
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -251,7 +267,7 @@ int main() {
// CHECK-DAG: [[TMP_VAL:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP_PRIV]],
// CHECK-DAG: [[S_ARR_PTR_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_PTR]] to i8*
// CHECK-DAG: [[TMP_VAL_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_VAL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_PTR_BCAST]], i8* [[TMP_VAL_BCAST]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_PTR_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL_BCAST]],
// CHECK: call void @__kmpc_for_static_fini(
// lastprivates
@@ -264,7 +280,7 @@ int main() {
// CHECK: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_ADDR_REF]],
// CHECK: [[BCAST_VEC_ADDR_REF:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_REF]] to i8*
// CHECK: [[BCAST_VEC_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[BCAST_VEC_ADDR_REF]], i8* [[BCAST_VEC_PRIV]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[BCAST_VEC_ADDR_REF]], i8* align {{[0-9]+}} [[BCAST_VEC_PRIV]],
// CHECK: [[S_ARR_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_ADDR_REF]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[S_ARR_PRIV_BCAST:%.+]] = bitcast [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]] to [[S_FLOAT_TY]]*
// CHECK: [[S_ARR_BEGIN_GEP:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[S_ARR_BEGIN]], i{{[0-9]+}} 2
@@ -275,7 +291,7 @@ int main() {
// CHECK: [[S_ARR_DST_EL:%.+]] = phi [[S_FLOAT_TY]]*{{.+}}
// CHECK: [[S_ARR_DST_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_DST_EL]] to i8*
// CHECK: [[S_ARR_SRC_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_SRC_EL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_DST_BCAST]], i8* [[S_ARR_SRC_BCAST]]{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_DST_BCAST]], i8* align {{[0-9]+}} [[S_ARR_SRC_BCAST]]{{.+}})
// CHECK: [[S_ARR_DST_NEXT:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[S_ARR_DST_EL]], i{{[0-9]+}} 1
// CHECK: [[S_ARR_SRC_NEXT:%.+]] = getelementptr{{.+}}
// CHECK: [[CPY_IS_FINISHED:%.+]] = icmp eq [[S_FLOAT_TY]]* [[S_ARR_DST_NEXT]], [[S_ARR_BEGIN_GEP]]
@@ -284,7 +300,7 @@ int main() {
// CHECK: [[TMP_VAL1:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP_PRIV]],
// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_REF]] to i8*
// CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VAR_ADDR_REF_BCAST]], i8* [[TMP_VAL1_BCAST]],{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}})
// CHECK: [[SVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[S_VAR_PRIV]],
// CHECK: store i{{[0-9]+}} [[SVAR_VAL]], i{{[0-9]+}}* [[SVAR_ADDR_REF]],
// CHECK: ret void
@@ -353,7 +369,7 @@ int main() {
// CHECK-DAG: [[TMP_VAL1:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP_PRIV1]],
// CHECK-DAG: [[S_ARR_PTR_BCAST1:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_PTR1]] to i8*
// CHECK-DAG: [[TMP_VAL_BCAST1:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_PTR_BCAST1]], i8* [[TMP_VAL_BCAST1]],
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_PTR_BCAST1]], i8* align {{[0-9]+}} [[TMP_VAL_BCAST1]],
// CHECK: call void @__kmpc_for_static_fini(
// lastprivates
@@ -366,7 +382,7 @@ int main() {
// CHECK: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_ADDR_REF1]],
// CHECK: [[BCAST_VEC_ADDR_REF:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_REF1]] to i8*
// CHECK: [[BCAST_VEC_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[BCAST_VEC_ADDR_REF]], i8* [[BCAST_VEC_PRIV]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[BCAST_VEC_ADDR_REF]], i8* align {{[0-9]+}} [[BCAST_VEC_PRIV]],
// CHECK: [[S_ARR_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_ADDR_REF]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[S_ARR_PRIV_BCAST:%.+]] = bitcast [2 x [[S_INT_TY]]]* [[S_ARR_PRIV1]] to [[S_INT_TY]]*
// CHECK: [[S_ARR_BEGIN_GEP:%.+]] = getelementptr [[S_INT_TY]], [[S_INT_TY]]* [[S_ARR_BEGIN]], i{{[0-9]+}} 2
@@ -377,7 +393,7 @@ int main() {
// CHECK: [[S_ARR_DST_EL:%.+]] = phi [[S_INT_TY]]*{{.+}}
// CHECK: [[S_ARR_DST_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_DST_EL]] to i8*
// CHECK: [[S_ARR_SRC_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_SRC_EL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_DST_BCAST]], i8* [[S_ARR_SRC_BCAST]]{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_DST_BCAST]], i8* align {{[0-9]+}} [[S_ARR_SRC_BCAST]]{{.+}})
// CHECK: [[S_ARR_DST_NEXT:%.+]] = getelementptr [[S_INT_TY]], [[S_INT_TY]]* [[S_ARR_DST_EL]], i{{[0-9]+}} 1
// CHECK: [[S_ARR_SRC_NEXT:%.+]] = getelementptr{{.+}}
// CHECK: [[CPY_IS_FINISHED:%.+]] = icmp eq [[S_INT_TY]]* [[S_ARR_DST_NEXT]], [[S_ARR_BEGIN_GEP]]
@@ -386,7 +402,7 @@ int main() {
// CHECK: [[TMP_VAL1:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP_PRIV1]],
// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_REF]] to i8*
// CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VAR_ADDR_REF_BCAST]], i8* [[TMP_VAL1_BCAST]],{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}})
// CHECK: ret void
// CHECK: !{!"llvm.loop.vectorize.enable", i1 true}
diff --git a/test/OpenMP/distribute_simd_lastprivate_messages.cpp b/test/OpenMP/distribute_simd_lastprivate_messages.cpp
index 82ce15e55048..e47ad7ec1eef 100644
--- a/test/OpenMP/distribute_simd_lastprivate_messages.cpp
+++ b/test/OpenMP/distribute_simd_lastprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_simd_linear_messages.cpp b/test/OpenMP/distribute_simd_linear_messages.cpp
index e4d71fee8250..06d85d13501e 100644
--- a/test/OpenMP/distribute_simd_linear_messages.cpp
+++ b/test/OpenMP/distribute_simd_linear_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
namespace X {
int x;
};
diff --git a/test/OpenMP/distribute_simd_loop_messages.cpp b/test/OpenMP/distribute_simd_loop_messages.cpp
index 59fafda45f4b..1977ca789dcf 100644
--- a/test/OpenMP/distribute_simd_loop_messages.cpp
+++ b/test/OpenMP/distribute_simd_loop_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+
static int sii;
// expected-note@+1 {{defined as threadprivate or thread local}}
#pragma omp threadprivate(sii)
@@ -322,9 +324,7 @@ int test_iteration_spaces() {
#pragma omp target
#pragma omp teams
- // expected-error@+3 {{unexpected OpenMP clause 'shared' in directive '#pragma omp distribute simd'}}
- // expected-note@+2 {{defined as shared}}
- // expected-error@+2 {{loop iteration variable in the associated loop of 'omp distribute simd' directive may not be shared, predetermined as linear}}
+ // expected-error@+1 {{unexpected OpenMP clause 'shared' in directive '#pragma omp distribute simd'}}
#pragma omp distribute simd shared(ii)
for (ii = 0; ii < 10; ii++)
c[ii] = a[ii];
diff --git a/test/OpenMP/distribute_simd_misc_messages.c b/test/OpenMP/distribute_simd_misc_messages.c
index f643ed1d5b8e..2cb5e97273ca 100644
--- a/test/OpenMP/distribute_simd_misc_messages.c
+++ b/test/OpenMP/distribute_simd_misc_messages.c
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -verify %s
+
// expected-error@+1 {{unexpected OpenMP directive '#pragma omp distribute simd'}}
#pragma omp distribute simd
diff --git a/test/OpenMP/distribute_simd_private_codegen.cpp b/test/OpenMP/distribute_simd_private_codegen.cpp
index ede807a0fb63..f675158be694 100644
--- a/test/OpenMP/distribute_simd_private_codegen.cpp
+++ b/test/OpenMP/distribute_simd_private_codegen.cpp
@@ -5,12 +5,28 @@
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/distribute_simd_private_messages.cpp b/test/OpenMP/distribute_simd_private_messages.cpp
index c777c9971d4b..8d82cc816649 100644
--- a/test/OpenMP/distribute_simd_private_messages.cpp
+++ b/test/OpenMP/distribute_simd_private_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_simd_reduction_codegen.cpp b/test/OpenMP/distribute_simd_reduction_codegen.cpp
index 8485d8d27d52..85b0e80aade3 100644
--- a/test/OpenMP/distribute_simd_reduction_codegen.cpp
+++ b/test/OpenMP/distribute_simd_reduction_codegen.cpp
@@ -5,10 +5,23 @@
// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/distribute_simd_reduction_messages.cpp b/test/OpenMP/distribute_simd_reduction_messages.cpp
index ddedcb0892ba..7bb5bdea5b46 100644
--- a/test/OpenMP/distribute_simd_reduction_messages.cpp
+++ b/test/OpenMP/distribute_simd_reduction_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 150 -o - %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 150 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_simd_safelen_messages.cpp b/test/OpenMP/distribute_simd_safelen_messages.cpp
index 4ae35fb2334d..c95d121ca2c9 100644
--- a/test/OpenMP/distribute_simd_safelen_messages.cpp
+++ b/test/OpenMP/distribute_simd_safelen_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/distribute_simd_simdlen_messages.cpp b/test/OpenMP/distribute_simd_simdlen_messages.cpp
index 4ae35fb2334d..c95d121ca2c9 100644
--- a/test/OpenMP/distribute_simd_simdlen_messages.cpp
+++ b/test/OpenMP/distribute_simd_simdlen_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/driver.c b/test/OpenMP/driver.c
index 74aaea507196..4c8b1df538ea 100644
--- a/test/OpenMP/driver.c
+++ b/test/OpenMP/driver.c
@@ -1,10 +1,13 @@
+// REQUIRES: x86-registered-target
// Test that by default -fnoopenmp-use-tls is passed to frontend.
//
// RUN: %clang %s -### -o %t.o 2>&1 -fopenmp=libomp | FileCheck --check-prefix=CHECK-DEFAULT %s
+
// CHECK-DEFAULT: -cc1
// CHECK-DEFAULT-NOT: -fnoopenmp-use-tls
//
// RUN: %clang %s -### -o %t.o 2>&1 -fopenmp=libomp -fnoopenmp-use-tls | FileCheck --check-prefix=CHECK-NO-TLS %s
+
// CHECK-NO-TLS: -cc1
// CHECK-NO-TLS-SAME: -fnoopenmp-use-tls
//
@@ -13,17 +16,31 @@
// RUN: %clang %s -c -E -dM -fopenmp=libomp -fopenmp-version=0 | FileCheck --check-prefix=CHECK-DEFAULT-VERSION %s
// RUN: %clang %s -c -E -dM -fopenmp=libomp -fopenmp-version=100 | FileCheck --check-prefix=CHECK-DEFAULT-VERSION %s
// RUN: %clang %s -c -E -dM -fopenmp=libomp -fopenmp-version=31 | FileCheck --check-prefix=CHECK-DEFAULT-VERSION %s
+
// CHECK-DEFAULT-VERSION: #define _OPENMP 201107
// RUN: %clang %s -c -E -dM -fopenmp=libomp -fopenmp-version=40 | FileCheck --check-prefix=CHECK-40-VERSION %s
// CHECK-40-VERSION: #define _OPENMP 201307
// RUN: %clang %s -c -E -dM -fopenmp=libomp -fopenmp-version=45 | FileCheck --check-prefix=CHECK-45-VERSION %s
+// RUN: %clang %s -c -E -dM -fopenmp=libomp -fopenmp-simd | FileCheck --check-prefix=CHECK-45-VERSION %s
+// RUN: %clang %s -c -E -dM -fopenmp=libomp -fopenmp-targets=x86_64-unknown-unknown -o - | FileCheck --check-prefix=CHECK-45-VERSION --check-prefix=CHECK-45-VERSION2 %s
// CHECK-45-VERSION: #define _OPENMP 201511
+// CHECK-45-VERSION2: #define _OPENMP 201511
// RUN: %clang %s -c -E -dM -fopenmp-version=1 | FileCheck --check-prefix=CHECK-VERSION %s
// RUN: %clang %s -c -E -dM -fopenmp-version=31 | FileCheck --check-prefix=CHECK-VERSION %s
// RUN: %clang %s -c -E -dM -fopenmp-version=40 | FileCheck --check-prefix=CHECK-VERSION %s
// RUN: %clang %s -c -E -dM -fopenmp-version=45 | FileCheck --check-prefix=CHECK-VERSION %s
+// RUN: %clang %s -c -E -dM -fopenmp-version=45 | FileCheck --check-prefix=CHECK-VERSION %s
+// RUN: %clang %s -c -E -dM -fopenmp-simd -fno-openmp-simd -fopenmp-version=45 | FileCheck --check-prefix=CHECK-VERSION %s
+// RUN: %clang %s -c -E -dM -fopenmp-simd | FileCheck --check-prefix=CHECK-VERSION %s
+// RUN: %clang %s -c -E -dM -fopenmp-simd -fopenmp-version=1 | FileCheck --check-prefix=CHECK-VERSION %s
+// RUN: %clang %s -c -E -dM -fopenmp-simd -fopenmp-version=0 | FileCheck --check-prefix=CHECK-VERSION %s
+// RUN: %clang %s -c -E -dM -fopenmp-simd -fopenmp-version=100 | FileCheck --check-prefix=CHECK-VERSION %s
+// RUN: %clang %s -c -E -dM -fopenmp-simd -fopenmp-version=31 | FileCheck --check-prefix=CHECK-VERSION %s
+// RUN: %clang %s -c -E -dM -fopenmp-simd -fopenmp-version=40 | FileCheck --check-prefix=CHECK-VERSION %s
+// RUN: %clang %s -c -E -dM -fopenmp-simd -fopenmp-version=45 | FileCheck --check-prefix=CHECK-VERSION %s
+
// CHECK-VERSION-NOT: #define _OPENMP
diff --git a/test/OpenMP/dump.cpp b/test/OpenMP/dump.cpp
index 222c83d5ce08..812afb72f680 100644
--- a/test/OpenMP/dump.cpp
+++ b/test/OpenMP/dump.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-dump %s | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-dump %s | FileCheck %s
// expected-no-diagnostics
int ga, gb;
@@ -12,7 +13,7 @@ int ga, gb;
#pragma omp declare reduction(fun : float : omp_out += omp_in) initializer(omp_priv = omp_orig + 15)
-// CHECK: |-OMPDeclareReductionDecl {{.+}} <line:11:35> col:35 operator+ 'int' combiner
+// CHECK: |-OMPDeclareReductionDecl {{.+}} <line:12:35> col:35 operator+ 'int' combiner
// CHECK-NEXT: | |-CompoundAssignOperator {{.+}} <col:47, col:58> 'int' lvalue '*=' ComputeLHSTy='int' ComputeResultTy='int'
// CHECK-NEXT: | | |-DeclRefExpr {{.+}} <col:47> 'int' lvalue Var {{.+}} 'omp_out' 'int'
// CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} <col:58> 'int' <LValueToRValue>
@@ -27,7 +28,7 @@ int ga, gb;
// CHECK-NEXT: | | `-DeclRefExpr {{.+}} <col:58> 'char' lvalue Var {{.+}} 'omp_in' 'char'
// CHECK-NEXT: | |-VarDecl {{.+}} <col:40> col:40 implicit used omp_in 'char'
// CHECK-NEXT: | `-VarDecl {{.+}} <col:40> col:40 implicit used omp_out 'char'
-// CHECK-NEXT: |-OMPDeclareReductionDecl {{.+}} <line:13:37> col:37 fun 'float' combiner initializer
+// CHECK-NEXT: |-OMPDeclareReductionDecl {{.+}} <line:14:37> col:37 fun 'float' combiner initializer
// CHECK-NEXT: | |-CompoundAssignOperator {{.+}} <col:45, col:56> 'float' lvalue '+=' ComputeLHSTy='float' ComputeResultTy='float'
// CHECK-NEXT: | | |-DeclRefExpr {{.+}} <col:45> 'float' lvalue Var {{.+}} 'omp_out' 'float'
// CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} <col:56> 'float' <LValueToRValue>
@@ -42,27 +43,42 @@ struct S {
}
};
-// CHECK: | `-OMPParallelForDirective {{.+}} <line:39:9, col:80>
-// CHECK-NEXT: | |-OMPDefaultClause {{.+}} <col:26, col:40>
-// CHECK-NEXT: | |-OMPPrivateClause {{.+}} <col:40, col:51>
+// CHECK: | `-OMPParallelForDirective {{.+}} {{<line:40:9, col:80>|<col:9, col:80>}}
+// CHECK-NEXT: | |-OMPDefaultClause {{.+}} <col:26, col:38>
+// CHECK-NEXT: | |-OMPPrivateClause {{.+}} <col:40, col:49>
// CHECK-NEXT: | | `-DeclRefExpr {{.+}} <col:48> 'int' lvalue OMPCapturedExpr {{.+}} 'a' 'int &'
-// CHECK-NEXT: | |-OMPSharedClause {{.+}} <col:51, col:61>
+// CHECK-NEXT: | |-OMPSharedClause {{.+}} <col:51, col:59>
// CHECK-NEXT: | | `-MemberExpr {{.+}} <col:58> 'int' lvalue ->b
// CHECK-NEXT: | | `-CXXThisExpr {{.+}} <col:58> 'S *' this
// CHECK-NEXT: | |-OMPScheduleClause {{.+}} <col:61, col:79>
// CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} <col:78> 'int' <LValueToRValue>
// CHECK-NEXT: | | `-DeclRefExpr {{.+}} <col:78> 'int' lvalue OMPCapturedExpr {{.+}} '.capture_expr.' 'int'
-// CHECK-NEXT: | |-CapturedStmt {{.+}} <line:40:5, line:41:9>
-// CHECK-NEXT: | | |-CapturedDecl {{.+}} <<invalid sloc>> <invalid sloc>
-// CHECK-NEXT: | | | |-ForStmt {{.+}} <line:40:5, line:41:9>
-// CHECK: | | | | `-UnaryOperator {{.+}} <line:41:7, col:9> 'int' lvalue prefix '++'
-// CHECK-NEXT: | | | | `-DeclRefExpr {{.+}} <col:9> 'int' lvalue OMPCapturedExpr {{.+}} 'a' 'int &'
+// CHECK-NEXT: | `-CapturedStmt {{.+}} <line:41:5, line:42:9>
+// CHECK-NEXT: | |-CapturedDecl {{.+}} <<invalid sloc>> <invalid sloc>
+// CHECK-NEXT: | | |-ForStmt {{.+}} <line:41:5, line:42:9>
+// CHECK: | | | `-UnaryOperator {{.+}} <line:42:7, col:9> 'int' lvalue prefix '++'
+// CHECK-NEXT: | | | `-DeclRefExpr {{.+}} <col:9> 'int' lvalue OMPCapturedExpr {{.+}} 'a' 'int &'
#pragma omp declare simd
#pragma omp declare simd inbranch
void foo();
-// CHECK: `-FunctionDecl {{.+}} <line:63:1, col:10> col:6 foo 'void ()'
-// CHECK-NEXT: |-OMPDeclareSimdDeclAttr {{.+}} <line:62:9, col:34> Implicit BS_Inbranch
-// CHECK: `-OMPDeclareSimdDeclAttr {{.+}} <line:61:9, col:25> Implicit BS_Undefined
+// CHECK: |-FunctionDecl {{.+}} <line:64:1, col:10> col:6 foo 'void ()'
+// CHECK-NEXT: |-OMPDeclareSimdDeclAttr {{.+}} <line:63:9, col:34> Implicit BS_Inbranch
+// CHECK: `-OMPDeclareSimdDeclAttr {{.+}} <line:62:9, col:25> Implicit BS_Undefined
+#pragma omp declare target
+int bar() {
+ int f;
+ return f;
+}
+#pragma omp end declare target
+
+// CHECK: `-FunctionDecl {{.+}} <line:71:1, line:74:1> line:71:5 bar 'int ()'
+// CHECK-NEXT: |-CompoundStmt {{.+}} <col:11, line:74:1>
+// CHECK-NEXT: | |-DeclStmt {{.+}} <line:72:3, col:8>
+// CHECK-NEXT: | | `-VarDecl {{.+}} <col:3, col:7> col:7 used f 'int'
+// CHECK-NEXT: | `-ReturnStmt {{.+}} <line:73:3, col:10>
+// CHECK-NEXT: | `-ImplicitCastExpr {{.+}} <col:10> 'int' <LValueToRValue>
+// CHECK-NEXT: | `-DeclRefExpr {{.+}} <col:10> 'int' lvalue Var {{.+}} 'f' 'int'
+// CHECK-NEXT: `-OMPDeclareTargetDeclAttr {{.+}} <<invalid sloc>> Implicit MT_To
diff --git a/test/OpenMP/flush_ast_print.cpp b/test/OpenMP/flush_ast_print.cpp
index f3af47bce321..8cde315a453c 100644
--- a/test/OpenMP/flush_ast_print.cpp
+++ b/test/OpenMP/flush_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -16,7 +20,7 @@ T tmain(T argc) {
return a + argc;
}
// CHECK: static T a;
-// CHECK-NEXT: #pragma omp flush
+// CHECK-NEXT: #pragma omp flush{{$}}
// CHECK-NEXT: #pragma omp flush (a)
// CHECK: static int a;
// CHECK-NEXT: #pragma omp flush
diff --git a/test/OpenMP/flush_codegen.cpp b/test/OpenMP/flush_codegen.cpp
index 89636a5bd87a..543524c220be 100644
--- a/test/OpenMP/flush_codegen.cpp
+++ b/test/OpenMP/flush_codegen.cpp
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -fopenmp -x c++ -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -debug-info-kind=limited -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -debug-info-kind=limited -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -30,4 +35,6 @@ int main() {
// CHECK: call {{.*}}void @__kmpc_flush(%{{.+}}* {{(@|%).+}})
// CHECK: ret
+// CHECK-NOT: line: 0,
+
#endif
diff --git a/test/OpenMP/flush_messages.cpp b/test/OpenMP/flush_messages.cpp
index 1c086a3f3fa4..da1d0c241242 100644
--- a/test/OpenMP/flush_messages.cpp
+++ b/test/OpenMP/flush_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
struct S1 { // expected-note 2 {{declared here}}
int a;
};
diff --git a/test/OpenMP/for_ast_print.cpp b/test/OpenMP/for_ast_print.cpp
index f489b217de96..82318ff800aa 100644
--- a/test/OpenMP/for_ast_print.cpp
+++ b/test/OpenMP/for_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -165,7 +169,7 @@ int main(int argc, char **argv) {
for (q = &buf[0]; q <= buf + 7; q++)
foo();
// CHECK: #pragma omp parallel
- // CHECK-NEXT: #pragma omp for
+ // CHECK-NEXT: #pragma omp for{{$}}
// CHECK-NEXT: for (p = buf; p < &buf[8]; p++)
// CHECK-NEXT: for (q = &buf[0]; q <= buf + 7; q++)
// CHECK-NEXT: foo();
diff --git a/test/OpenMP/for_codegen.cpp b/test/OpenMP/for_codegen.cpp
index 1f5dd7ddd0dd..ad8674fdde7e 100644
--- a/test/OpenMP/for_codegen.cpp
+++ b/test/OpenMP/for_codegen.cpp
@@ -1,8 +1,15 @@
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - -fsanitize-address-use-after-scope | FileCheck -allow-deprecated-dag-overlap %s --check-prefix=CHECK --check-prefix=LIFETIME
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
-// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck %s --check-prefix=TERM_DEBUG
-// RUN: %clang_cc1 -main-file-name for_codegen.cpp %s -o - -emit-llvm -fprofile-instrument=clang -fprofile-instrument-path=for_codegen-test.profraw | FileCheck %s --check-prefix=PROF-INSTR-PATH
+// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix=TERM_DEBUG
+// RUN: %clang_cc1 -main-file-name for_codegen.cpp %s -o - -emit-llvm -fprofile-instrument=clang -fprofile-instrument-path=for_codegen-test.profraw | FileCheck -allow-deprecated-dag-overlap %s --check-prefix=PROF-INSTR-PATH
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -main-file-name for_codegen.cpp %s -o - -emit-llvm -fprofile-instrument=clang -fprofile-instrument-path=for_codegen-test.profraw | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
//
// expected-no-diagnostics
#ifndef HEADER
@@ -18,8 +25,20 @@
// CHECK-LABEL: loop_with_counter_collapse
void loop_with_counter_collapse() {
- // CHECK: call void @__kmpc_for_static_init_8(%ident_t* @
- // CHECK: call void @__kmpc_for_static_fini(%ident_t* @
+ // LIFETIME: call void @llvm.lifetime.end
+ // LIFETIME: call void @llvm.lifetime.end
+ // CHECK: call void @__kmpc_for_static_init_8(%struct.ident_t* @
+ // CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* @
+ // LIFETIME: call void @llvm.lifetime.end
+ // LIFETIME: call void @llvm.lifetime.end
+ // LIFETIME: call void @llvm.lifetime.end
+ // LIFETIME: call void @llvm.lifetime.end
+ // LIFETIME: call void @llvm.lifetime.end
+ // LIFETIME: call void @llvm.lifetime.end
+ // LIFETIME: call void @llvm.lifetime.end
+ // LIFETIME: call void @llvm.lifetime.end
+ // LIFETIME: call void @llvm.lifetime.end
+ // LIFETIME: call void @llvm.lifetime.end
#pragma omp for collapse(2)
for (int i = 0; i < 4; i++) {
for (int j = i; j < 4; j++) {
diff --git a/test/OpenMP/for_collapse_messages.cpp b/test/OpenMP/for_collapse_messages.cpp
index a6fdf0066592..230880b22db3 100644
--- a/test/OpenMP/for_collapse_messages.cpp
+++ b/test/OpenMP/for_collapse_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/for_firstprivate_codegen.cpp b/test/OpenMP/for_firstprivate_codegen.cpp
index 88f54103ad69..fc3caa9a2603 100644
--- a/test/OpenMP/for_firstprivate_codegen.cpp
+++ b/test/OpenMP/for_firstprivate_codegen.cpp
@@ -3,6 +3,13 @@
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -234,7 +241,7 @@ int main() {
// firstprivate vec(vec)
// CHECK: [[VEC_DEST:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VEC_DEST]], i8* bitcast ([2 x i{{[0-9]+}}]* [[VEC]] to i8*),
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST]], i8* align {{[0-9]+}} bitcast ([2 x i{{[0-9]+}}]* [[VEC]] to i8*),
// firstprivate s_arr(s_arr)
// CHECK: [[S_ARR_PRIV_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
@@ -302,7 +309,7 @@ int main() {
// firstprivate vec(vec)
// CHECK: [[VEC_DEST:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
// CHECK: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_REF]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VEC_DEST]], i8* [[VEC_SRC]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST]], i8* align {{[0-9]+}} [[VEC_SRC]],
// firstprivate s_arr(s_arr)
// CHECK: [[S_ARR_PRIV_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_PRIV]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
diff --git a/test/OpenMP/for_firstprivate_messages.cpp b/test/OpenMP/for_firstprivate_messages.cpp
index 60be4f5f2a2b..c34c918d120f 100644
--- a/test/OpenMP/for_firstprivate_messages.cpp
+++ b/test/OpenMP/for_firstprivate_messages.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
void foo() {
}
diff --git a/test/OpenMP/for_lastprivate_codegen.cpp b/test/OpenMP/for_lastprivate_codegen.cpp
index 30a17eaf581a..0061de632380 100644
--- a/test/OpenMP/for_lastprivate_codegen.cpp
+++ b/test/OpenMP/for_lastprivate_codegen.cpp
@@ -3,6 +3,13 @@
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -516,7 +523,7 @@ int main() {
// original vec[]=private_vec[];
// CHECK: [[VEC_DEST:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_REF]] to i8*
// CHECK: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VEC_DEST]], i8* [[VEC_SRC]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST]], i8* align {{[0-9]+}} [[VEC_SRC]],
// original s_arr[]=private_s_arr[];
// CHECK: [[S_ARR_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_REF]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
@@ -745,7 +752,7 @@ int main() {
// original vec[]=private_vec[];
// CHECK: [[VEC_DEST:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_REF]] to i8*
// CHECK: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VEC_DEST]], i8* [[VEC_SRC]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST]], i8* align {{[0-9]+}} [[VEC_SRC]],
// original s_arr[]=private_s_arr[];
// CHECK: [[S_ARR_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_REF]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
diff --git a/test/OpenMP/for_lastprivate_messages.cpp b/test/OpenMP/for_lastprivate_messages.cpp
index 13ef35e925a7..7787ab12d481 100644
--- a/test/OpenMP/for_lastprivate_messages.cpp
+++ b/test/OpenMP/for_lastprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/for_linear_codegen.cpp b/test/OpenMP/for_linear_codegen.cpp
index 54cdf8a4cb33..34e8c6a09aff 100644
--- a/test/OpenMP/for_linear_codegen.cpp
+++ b/test/OpenMP/for_linear_codegen.cpp
@@ -3,6 +3,13 @@
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/for_linear_messages.cpp b/test/OpenMP/for_linear_messages.cpp
index ab8934979ac3..622cd4a8a3af 100644
--- a/test/OpenMP/for_linear_messages.cpp
+++ b/test/OpenMP/for_linear_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
namespace X {
int x;
};
diff --git a/test/OpenMP/for_loop_messages.cpp b/test/OpenMP/for_loop_messages.cpp
index 01cc6020b85f..37ff0fc0ca2d 100644
--- a/test/OpenMP/for_loop_messages.cpp
+++ b/test/OpenMP/for_loop_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+
class S {
int a;
S() : a(0) {}
diff --git a/test/OpenMP/for_misc_messages.c b/test/OpenMP/for_misc_messages.c
index 0a7cdf8fc06b..901d66dd688c 100644
--- a/test/OpenMP/for_misc_messages.c
+++ b/test/OpenMP/for_misc_messages.c
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -triple x86_64-unknown-unknown -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -triple x86_64-unknown-unknown -verify %s
+
// expected-error@+1 {{unexpected OpenMP directive '#pragma omp for'}}
#pragma omp for
@@ -52,6 +54,20 @@ void test_invalid_clause() {
#pragma omp for foo bar
for (i = 0; i < 16; ++i)
;
+// At one time, this failed an assert.
+// expected-error@+1 {{unexpected OpenMP clause 'num_teams' in directive '#pragma omp for'}}
+#pragma omp for num_teams(3)
+ for (i = 0; i < 16; ++i)
+ ;
+// At one time, this error was reported twice.
+// expected-error@+1 {{unexpected OpenMP clause 'uniform' in directive '#pragma omp for'}}
+#pragma omp for uniform
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{unexpected OpenMP clause 'if' in directive '#pragma omp for'}}
+#pragma omp for if(0)
+ for (i = 0; i < 16; ++i)
+ ;
}
void test_non_identifiers() {
diff --git a/test/OpenMP/for_ordered_clause.cpp b/test/OpenMP/for_ordered_clause.cpp
index 3335f4046f57..ec29a989d0b0 100644
--- a/test/OpenMP/for_ordered_clause.cpp
+++ b/test/OpenMP/for_ordered_clause.cpp
@@ -2,6 +2,11 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
void foo() {
}
diff --git a/test/OpenMP/for_private_codegen.cpp b/test/OpenMP/for_private_codegen.cpp
index f1416d75b64b..d914a62d3bae 100644
--- a/test/OpenMP/for_private_codegen.cpp
+++ b/test/OpenMP/for_private_codegen.cpp
@@ -3,6 +3,13 @@
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DLAMBDA -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -fblocks -DBLOCKS -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -40,7 +47,7 @@ T tmain() {
int main() {
static int svar;
#ifdef LAMBDA
- // LAMBDA: [[G:@.+]] = global double
+ // LAMBDA: [[G:@.+]] = {{(dso_local )?}}global double
// LAMBDA-LABEL: @main
// LAMBDA: call{{.*}} void [[OUTER_LAMBDA:@.+]](
[&]() {
@@ -102,7 +109,7 @@ int main() {
}();
return 0;
#elif defined(BLOCKS)
- // BLOCKS: [[G:@.+]] = global double
+ // BLOCKS: [[G:@.+]] = {{(dso_local )?}}global double
// BLOCKS-LABEL: @main
// BLOCKS: call {{.*}}void {{%.+}}(i8
^{
diff --git a/test/OpenMP/for_private_messages.cpp b/test/OpenMP/for_private_messages.cpp
index 4045c5b56ff5..5b0b562869b2 100644
--- a/test/OpenMP/for_private_messages.cpp
+++ b/test/OpenMP/for_private_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/for_reduction_codegen.cpp b/test/OpenMP/for_reduction_codegen.cpp
index cef457333062..55323122f3fc 100644
--- a/test/OpenMP/for_reduction_codegen.cpp
+++ b/test/OpenMP/for_reduction_codegen.cpp
@@ -1,8 +1,15 @@
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap -check-prefix=LAMBDA %s
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap -check-prefix=BLOCKS %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -345,7 +352,7 @@ int main() {
// CHECK: [[UP:%.+]] = call dereferenceable(4) [[S_FLOAT_TY]]* @{{.+}}([[S_FLOAT_TY]]* [[VAR_REF]], [[S_FLOAT_TY]]* dereferenceable(4) [[VAR_PRIV]])
// CHECK: [[BC1:%.+]] = bitcast [[S_FLOAT_TY]]* [[VAR_REF]] to i8*
// CHECK: [[BC2:%.+]] = bitcast [[S_FLOAT_TY]]* [[UP]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[BC1]], i8* [[BC2]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[BC1]], i8* align 4 [[BC2]], i64 4, i1 false)
// var1 = var1.operator &&(var1_reduction);
// CHECK: [[TO_FLOAT:%.+]] = call float @{{.+}}([[S_FLOAT_TY]]* [[VAR1_REF]])
@@ -361,7 +368,7 @@ int main() {
// CHECK: call void @{{.+}}([[S_FLOAT_TY]]* [[COND_LVALUE:%.+]], float [[CONV]])
// CHECK: [[BC1:%.+]] = bitcast [[S_FLOAT_TY]]* [[VAR1_REF]] to i8*
// CHECK: [[BC2:%.+]] = bitcast [[S_FLOAT_TY]]* [[COND_LVALUE]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[BC1]], i8* [[BC2]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[BC1]], i8* align 4 [[BC2]], i64 4, i1 false)
// t_var1 = min(t_var1, t_var1_reduction);
// CHECK: [[T_VAR1_VAL:%.+]] = load float, float* [[T_VAR1_REF]],
@@ -399,7 +406,7 @@ int main() {
// CHECK: [[UP:%.+]] = call dereferenceable(4) [[S_FLOAT_TY]]* @{{.+}}([[S_FLOAT_TY]]* [[VAR_REF]], [[S_FLOAT_TY]]* dereferenceable(4) [[VAR_PRIV]])
// CHECK: [[BC1:%.+]] = bitcast [[S_FLOAT_TY]]* [[VAR_REF]] to i8*
// CHECK: [[BC2:%.+]] = bitcast [[S_FLOAT_TY]]* [[UP]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[BC1]], i8* [[BC2]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[BC1]], i8* align 4 [[BC2]], i64 4, i1 false)
// CHECK: call void @__kmpc_end_critical(
// var1 = var1.operator &&(var1_reduction);
@@ -417,7 +424,7 @@ int main() {
// CHECK: call void @{{.+}}([[S_FLOAT_TY]]* [[COND_LVALUE:%.+]], float [[CONV]])
// CHECK: [[BC1:%.+]] = bitcast [[S_FLOAT_TY]]* [[VAR1_REF]] to i8*
// CHECK: [[BC2:%.+]] = bitcast [[S_FLOAT_TY]]* [[COND_LVALUE]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[BC1]], i8* [[BC2]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[BC1]], i8* align 4 [[BC2]], i64 4, i1 false)
// CHECK: call void @__kmpc_end_critical(
// t_var1 = min(t_var1, t_var1_reduction);
@@ -503,7 +510,7 @@ int main() {
// CHECK: [[UP:%.+]] = call dereferenceable(4) [[S_FLOAT_TY]]* @{{.+}}([[S_FLOAT_TY]]* [[VAR_LHS]], [[S_FLOAT_TY]]* dereferenceable(4) [[VAR_RHS]])
// CHECK: [[BC1:%.+]] = bitcast [[S_FLOAT_TY]]* [[VAR_LHS]] to i8*
// CHECK: [[BC2:%.+]] = bitcast [[S_FLOAT_TY]]* [[UP]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[BC1]], i8* [[BC2]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[BC1]], i8* align 4 [[BC2]], i64 4, i1 false)
// var1_lhs = var1_lhs.operator &&(var1_rhs);
// CHECK: [[TO_FLOAT:%.+]] = call float @{{.+}}([[S_FLOAT_TY]]* [[VAR1_LHS]])
@@ -519,7 +526,7 @@ int main() {
// CHECK: call void @{{.+}}([[S_FLOAT_TY]]* [[COND_LVALUE:%.+]], float [[CONV]])
// CHECK: [[BC1:%.+]] = bitcast [[S_FLOAT_TY]]* [[VAR1_LHS]] to i8*
// CHECK: [[BC2:%.+]] = bitcast [[S_FLOAT_TY]]* [[COND_LVALUE]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[BC1]], i8* [[BC2]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[BC1]], i8* align 4 [[BC2]], i64 4, i1 false)
// t_var1_lhs = min(t_var1_lhs, t_var1_rhs);
// CHECK: [[T_VAR1_LHS_VAL:%.+]] = load float, float* [[T_VAR1_LHS]],
@@ -622,7 +629,7 @@ int main() {
// CHECK: phi [[S_FLOAT_TY]]*
// CHECK: [[AND:%.+]] = call dereferenceable(4) [[S_FLOAT_TY]]* @_ZN1SIfEanERKS0_([[S_FLOAT_TY]]* %{{.+}}, [[S_FLOAT_TY]]* dereferenceable(4) %{{.+}})
// CHECK: [[BITCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[AND]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.+}}, i8* [[BITCAST]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %{{.+}}, i8* align 4 [[BITCAST]], i64 4, i1 false)
// CHECK: [[DONE:%.+]] = icmp eq [[S_FLOAT_TY]]* %{{.+}}, [[END]]
// CHECK: br i1 [[DONE]],
@@ -652,7 +659,7 @@ int main() {
// CHECK: call void @__kmpc_critical(
// CHECK: [[AND:%.+]] = call dereferenceable(4) [[S_FLOAT_TY]]* @_ZN1SIfEanERKS0_([[S_FLOAT_TY]]* %{{.+}}, [[S_FLOAT_TY]]* dereferenceable(4) %{{.+}})
// CHECK: [[BITCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[AND]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.+}}, i8* [[BITCAST]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %{{.+}}, i8* align 4 [[BITCAST]], i64 4, i1 false)
// CHECK: call void @__kmpc_end_critical(
// CHECK: [[DONE:%.+]] = icmp eq [[S_FLOAT_TY]]* %{{.+}}, [[END]]
// CHECK: br i1 [[DONE]],
@@ -725,7 +732,7 @@ int main() {
// CHECK: phi [[S_FLOAT_TY]]*
// CHECK: [[AND:%.+]] = call dereferenceable(4) [[S_FLOAT_TY]]* @_ZN1SIfEanERKS0_([[S_FLOAT_TY]]* %{{.+}}, [[S_FLOAT_TY]]* dereferenceable(4) %{{.+}})
// CHECK: [[BITCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[AND]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.+}}, i8* [[BITCAST]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %{{.+}}, i8* align 4 [[BITCAST]], i64 4, i1 false)
// CHECK: [[DONE:%.+]] = icmp eq [[S_FLOAT_TY]]* %{{.+}}, [[END]]
// CHECK: br i1 [[DONE]],
@@ -816,7 +823,7 @@ int main() {
// CHECK: phi [[S_FLOAT_TY]]*
// CHECK: [[AND:%.+]] = call dereferenceable(4) [[S_FLOAT_TY]]* @_ZN1SIfEanERKS0_([[S_FLOAT_TY]]* %{{.+}}, [[S_FLOAT_TY]]* dereferenceable(4) %{{.+}})
// CHECK: [[BITCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[AND]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.+}}, i8* [[BITCAST]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %{{.+}}, i8* align 4 [[BITCAST]], i64 4, i1 false)
// CHECK: [[DONE:%.+]] = icmp eq [[S_FLOAT_TY]]* %{{.+}}, [[END]]
// CHECK: br i1 [[DONE]],
@@ -846,7 +853,7 @@ int main() {
// CHECK: call void @__kmpc_critical(
// CHECK: [[AND:%.+]] = call dereferenceable(4) [[S_FLOAT_TY]]* @_ZN1SIfEanERKS0_([[S_FLOAT_TY]]* %{{.+}}, [[S_FLOAT_TY]]* dereferenceable(4) %{{.+}})
// CHECK: [[BITCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[AND]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.+}}, i8* [[BITCAST]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %{{.+}}, i8* align 4 [[BITCAST]], i64 4, i1 false)
// CHECK: call void @__kmpc_end_critical(
// CHECK: [[DONE:%.+]] = icmp eq [[S_FLOAT_TY]]* %{{.+}}, [[END]]
// CHECK: br i1 [[DONE]],
@@ -915,7 +922,7 @@ int main() {
// CHECK: phi [[S_FLOAT_TY]]*
// CHECK: [[AND:%.+]] = call dereferenceable(4) [[S_FLOAT_TY]]* @_ZN1SIfEanERKS0_([[S_FLOAT_TY]]* %{{.+}}, [[S_FLOAT_TY]]* dereferenceable(4) %{{.+}})
// CHECK: [[BITCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[AND]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.+}}, i8* [[BITCAST]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %{{.+}}, i8* align 4 [[BITCAST]], i64 4, i1 false)
// CHECK: [[DONE:%.+]] = icmp eq [[S_FLOAT_TY]]* %{{.+}}, [[END]]
// CHECK: br i1 [[DONE]],
@@ -1285,7 +1292,7 @@ int main() {
// CHECK: [[UP:%.+]] = call dereferenceable(4) [[S_INT_TY]]* @{{.+}}([[S_INT_TY]]* [[VAR_REF]], [[S_INT_TY]]* dereferenceable(4) [[VAR_PRIV]])
// CHECK: [[BC1:%.+]] = bitcast [[S_INT_TY]]* [[VAR_REF]] to i8*
// CHECK: [[BC2:%.+]] = bitcast [[S_INT_TY]]* [[UP]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[BC1]], i8* [[BC2]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[BC1]], i8* align 4 [[BC2]], i64 4, i1 false)
// var1 = var1.operator &&(var1_reduction);
// CHECK: [[TO_INT:%.+]] = call i{{[0-9]+}} @{{.+}}([[S_INT_TY]]* [[VAR1_REF]])
@@ -1301,7 +1308,7 @@ int main() {
// CHECK: call void @{{.+}}([[S_INT_TY]]* [[COND_LVALUE:%.+]], i32 [[CONV]])
// CHECK: [[BC1:%.+]] = bitcast [[S_INT_TY]]* [[VAR1_REF]] to i8*
// CHECK: [[BC2:%.+]] = bitcast [[S_INT_TY]]* [[COND_LVALUE]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[BC1]], i8* [[BC2]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[BC1]], i8* align 4 [[BC2]], i64 4, i1 false)
// t_var1 = min(t_var1, t_var1_reduction);
// CHECK: [[T_VAR1_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[T_VAR1_REF]],
@@ -1327,7 +1334,7 @@ int main() {
// CHECK: [[UP:%.+]] = call dereferenceable(4) [[S_INT_TY]]* @{{.+}}([[S_INT_TY]]* [[VAR_REF]], [[S_INT_TY]]* dereferenceable(4) [[VAR_PRIV]])
// CHECK: [[BC1:%.+]] = bitcast [[S_INT_TY]]* [[VAR_REF]] to i8*
// CHECK: [[BC2:%.+]] = bitcast [[S_INT_TY]]* [[UP]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[BC1]], i8* [[BC2]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[BC1]], i8* align 4 [[BC2]], i64 4, i1 false)
// CHECK: call void @__kmpc_end_critical(
// var1 = var1.operator &&(var1_reduction);
@@ -1345,7 +1352,7 @@ int main() {
// CHECK: call void @{{.+}}([[S_INT_TY]]* [[COND_LVALUE:%.+]], i32 [[CONV]])
// CHECK: [[BC1:%.+]] = bitcast [[S_INT_TY]]* [[VAR1_REF]] to i8*
// CHECK: [[BC2:%.+]] = bitcast [[S_INT_TY]]* [[COND_LVALUE]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[BC1]], i8* [[BC2]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[BC1]], i8* align 4 [[BC2]], i64 4, i1 false)
// CHECK: call void @__kmpc_end_critical(
// t_var1 = min(t_var1, t_var1_reduction);
@@ -1412,7 +1419,7 @@ int main() {
// CHECK: [[UP:%.+]] = call dereferenceable(4) [[S_INT_TY]]* @{{.+}}([[S_INT_TY]]* [[VAR_LHS]], [[S_INT_TY]]* dereferenceable(4) [[VAR_RHS]])
// CHECK: [[BC1:%.+]] = bitcast [[S_INT_TY]]* [[VAR_LHS]] to i8*
// CHECK: [[BC2:%.+]] = bitcast [[S_INT_TY]]* [[UP]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[BC1]], i8* [[BC2]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[BC1]], i8* align 4 [[BC2]], i64 4, i1 false)
// var1_lhs = var1_lhs.operator &&(var1_rhs);
// CHECK: [[TO_INT:%.+]] = call i{{[0-9]+}} @{{.+}}([[S_INT_TY]]* [[VAR1_LHS]])
@@ -1428,7 +1435,7 @@ int main() {
// CHECK: call void @{{.+}}([[S_INT_TY]]* [[COND_LVALUE:%.+]], i32 [[CONV]])
// CHECK: [[BC1:%.+]] = bitcast [[S_INT_TY]]* [[VAR1_LHS]] to i8*
// CHECK: [[BC2:%.+]] = bitcast [[S_INT_TY]]* [[COND_LVALUE]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[BC1]], i8* [[BC2]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[BC1]], i8* align 4 [[BC2]], i64 4, i1 false)
// t_var1_lhs = min(t_var1_lhs, t_var1_rhs);
// CHECK: [[T_VAR1_LHS_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[T_VAR1_LHS]],
diff --git a/test/OpenMP/for_reduction_codegen_UDR.cpp b/test/OpenMP/for_reduction_codegen_UDR.cpp
index 05a46a6eb7ff..0a6ba1d61008 100644
--- a/test/OpenMP/for_reduction_codegen_UDR.cpp
+++ b/test/OpenMP/for_reduction_codegen_UDR.cpp
@@ -1,6 +1,11 @@
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/for_reduction_messages.cpp b/test/OpenMP/for_reduction_messages.cpp
index d4f4a795fe2c..a4f15aa6193e 100644
--- a/test/OpenMP/for_reduction_messages.cpp
+++ b/test/OpenMP/for_reduction_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 150 -o - %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 150 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/for_schedule_messages.cpp b/test/OpenMP/for_schedule_messages.cpp
index 8946ce3aedfb..f4b5b3a26d64 100644
--- a/test/OpenMP/for_schedule_messages.cpp
+++ b/test/OpenMP/for_schedule_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/for_simd_aligned_messages.cpp b/test/OpenMP/for_simd_aligned_messages.cpp
index 3ff25870e5a0..fce9aca9989a 100644
--- a/test/OpenMP/for_simd_aligned_messages.cpp
+++ b/test/OpenMP/for_simd_aligned_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -x c++ -std=c++11 -verify -fopenmp %s
+// RUN: %clang_cc1 -x c++ -std=c++11 -verify -fopenmp-simd %s
+
struct B {
static int ib[20]; // expected-note 0 {{'B::ib' declared here}}
static constexpr int bfoo() { return 8; }
diff --git a/test/OpenMP/for_simd_ast_print.cpp b/test/OpenMP/for_simd_ast_print.cpp
index befad16e0951..13e82b46472d 100644
--- a/test/OpenMP/for_simd_ast_print.cpp
+++ b/test/OpenMP/for_simd_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -33,7 +37,7 @@ public:
}
};
-// CHECK: #pragma omp for simd private(this->a) private(this->a) private(T::a)
+// CHECK: #pragma omp for simd private(this->a) private(this->a) private(T::a){{$}}
// CHECK: #pragma omp for simd private(this->a) private(this->a)
// CHECK: #pragma omp for simd private(this->a) private(this->a) private(this->S1::a)
diff --git a/test/OpenMP/for_simd_codegen.cpp b/test/OpenMP/for_simd_codegen.cpp
index 89f779db33cd..7e540e263b14 100644
--- a/test/OpenMP/for_simd_codegen.cpp
+++ b/test/OpenMP/for_simd_codegen.cpp
@@ -2,6 +2,12 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t < %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -debug-info-kind=limited -std=c++11 -include-pch %t -verify -emit-llvm -o - < %s | FileCheck %s
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm -o - < %s | FileCheck %s --check-prefix=TERM_DEBUG
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -emit-llvm -fexceptions -fcxx-exceptions -o - < %s | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t < %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -debug-info-kind=limited -std=c++11 -include-pch %t -verify -emit-llvm -o - < %s | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm -o - < %s | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -12,7 +18,7 @@ double *g_ptr;
// CHECK-LABEL: define {{.*void}} @{{.*}}simple{{.*}}(float* {{.+}}, float* {{.+}}, float* {{.+}}, float* {{.+}})
void simple(float *a, float *b, float *c, float *d) {
#pragma omp for simd
-// CHECK: call void @__kmpc_for_static_init_4(%ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i32* [[LB:%[^,]+]], i32* [[UB:%[^,]+]], i32* [[STRIDE:%[^,]+]], i32 1, i32 1)
+// CHECK: call void @__kmpc_for_static_init_4(%struct.ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i32* [[LB:%[^,]+]], i32* [[UB:%[^,]+]], i32* [[STRIDE:%[^,]+]], i32 1, i32 1)
// CHECK: [[UB_VAL:%.+]] = load i32, i32* [[UB]],
// CHECK: [[CMP:%.+]] = icmp sgt i32 [[UB_VAL]], 5
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
@@ -48,8 +54,8 @@ void simple(float *a, float *b, float *c, float *d) {
// br label %{{.+}}, !llvm.loop !{{.+}}
}
// CHECK: [[SIMPLE_LOOP1_END]]:
-// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
-// CHECK: call void @__kmpc_barrier(%ident_t* {{.+}}, i32 %{{.+}})
+// CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* {{.+}}, i32 %{{.+}})
+// CHECK: call void @__kmpc_barrier(%struct.ident_t* {{.+}}, i32 %{{.+}})
long long k = get_val();
@@ -59,8 +65,8 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: [[K0LOAD:%.+]] = load i64, i64* [[K_VAR]]
// CHECK-NEXT: store i64 [[K0LOAD]], i64* [[LIN0:%[^,]+]]
-// CHECK: call void @__kmpc_dispatch_init_4(%ident_t* {{.+}}, i32 %{{.+}}, i32 1073741859, i32 0, i32 8, i32 1, i32 1)
-// CHECK: [[NEXT:%.+]] = call i32 @__kmpc_dispatch_next_4(%ident_t* {{.+}}, i32 %{{.+}}, i32* %{{.+}}, i32* [[LB:%.+]], i32* [[UB:%.+]], i32* %{{.+}})
+// CHECK: call void @__kmpc_dispatch_init_4(%struct.ident_t* {{.+}}, i32 %{{.+}}, i32 1073741859, i32 0, i32 8, i32 1, i32 1)
+// CHECK: [[NEXT:%.+]] = call i32 @__kmpc_dispatch_next_4(%struct.ident_t* {{.+}}, i32 %{{.+}}, i32* %{{.+}}, i32* [[LB:%.+]], i32* [[UB:%.+]], i32* %{{.+}})
// CHECK: [[COND:%.+]] = icmp ne i32 [[NEXT]], 0
// CHECK: br i1 [[COND]], label %[[CONT:.+]], label %[[END:.+]]
// CHECK: [[CONT]]:
@@ -100,7 +106,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: [[LIN0_2:%.+]] = load i64, i64* [[LIN0]]
// CHECK-NEXT: [[LIN_ADD2:%.+]] = add nsw i64 [[LIN0_2]], 27
// CHECK-NEXT: store i64 [[LIN_ADD2]], i64* [[K_VAR]]
-// CHECK: call void @__kmpc_barrier(%ident_t* {{.+}}, i32 %{{.+}})
+// CHECK: call void @__kmpc_barrier(%struct.ident_t* {{.+}}, i32 %{{.+}})
int lin = 12;
#pragma omp for simd linear(lin : get_val()), linear(g_ptr)
@@ -116,7 +122,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: [[GLIN_LOAD:%.+]] = load double*, double** [[GLIN_VAR:@[^,]+]]
// CHECK-NEXT: store double* [[GLIN_LOAD]], double** [[GLIN_START:%[^,]+]]
-// CHECK: call void @__kmpc_for_static_init_8u(%ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i64* [[LB:%[^,]+]], i64* [[UB:%[^,]+]], i64* [[STRIDE:%[^,]+]], i64 1, i64 1)
+// CHECK: call void @__kmpc_for_static_init_8u(%struct.ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i64* [[LB:%[^,]+]], i64* [[UB:%[^,]+]], i64* [[STRIDE:%[^,]+]], i64 1, i64 1)
// CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
// CHECK: [[CMP:%.+]] = icmp ugt i64 [[UB_VAL]], 3
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
@@ -163,7 +169,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: store i64 [[ADD3_2]], i64* [[OMP_IV3]]
}
// CHECK: [[SIMPLE_LOOP3_END]]:
-// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
+// CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* {{.+}}, i32 %{{.+}})
//
// Linear start and step are used to calculate final value of the linear variables.
// CHECK: [[LINSTART:.+]] = load i32, i32* [[LIN_START]]
@@ -171,10 +177,10 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: store i32 {{.+}}, i32* [[LIN_VAR]],
// CHECK: [[GLINSTART:.+]] = load double*, double** [[GLIN_START]]
// CHECK: store double* {{.*}}[[GLIN_VAR]]
-// CHECK: call void @__kmpc_barrier(%ident_t* {{.+}}, i32 %{{.+}})
+// CHECK: call void @__kmpc_barrier(%struct.ident_t* {{.+}}, i32 %{{.+}})
#pragma omp for simd
-// CHECK: call void @__kmpc_for_static_init_4(%ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i32* [[LB:%[^,]+]], i32* [[UB:%[^,]+]], i32* [[STRIDE:%[^,]+]], i32 1, i32 1)
+// CHECK: call void @__kmpc_for_static_init_4(%struct.ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i32* [[LB:%[^,]+]], i32* [[UB:%[^,]+]], i32* [[STRIDE:%[^,]+]], i32 1, i32 1)
// CHECK: [[UB_VAL:%.+]] = load i32, i32* [[UB]],
// CHECK: [[CMP:%.+]] = icmp sgt i32 [[UB_VAL]], 3
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
@@ -207,11 +213,11 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: store i32 [[ADD4_2]], i32* [[OMP_IV4]]
}
// CHECK: [[SIMPLE_LOOP4_END]]:
-// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
-// CHECK: call void @__kmpc_barrier(%ident_t* {{.+}}, i32 %{{.+}})
+// CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* {{.+}}, i32 %{{.+}})
+// CHECK: call void @__kmpc_barrier(%struct.ident_t* {{.+}}, i32 %{{.+}})
#pragma omp for simd
-// CHECK: call void @__kmpc_for_static_init_4(%ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i32* [[LB:%[^,]+]], i32* [[UB:%[^,]+]], i32* [[STRIDE:%[^,]+]], i32 1, i32 1)
+// CHECK: call void @__kmpc_for_static_init_4(%struct.ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i32* [[LB:%[^,]+]], i32* [[UB:%[^,]+]], i32* [[STRIDE:%[^,]+]], i32 1, i32 1)
// CHECK: [[UB_VAL:%.+]] = load i32, i32* [[UB]],
// CHECK: [[CMP:%.+]] = icmp sgt i32 [[UB_VAL]], 25
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
@@ -244,8 +250,8 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: store i32 [[ADD5_2]], i32* [[OMP_IV5]]
}
// CHECK: [[SIMPLE_LOOP5_END]]:
-// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
-// CHECK: call void @__kmpc_barrier(%ident_t* {{.+}}, i32 %{{.+}})
+// CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* {{.+}}, i32 %{{.+}})
+// CHECK: call void @__kmpc_barrier(%struct.ident_t* {{.+}}, i32 %{{.+}})
// CHECK-NOT: mul i32 %{{.+}}, 10
#pragma omp for simd
@@ -258,7 +264,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: store i32 -1, i32* [[A:%.+]],
A = -1;
#pragma omp for simd lastprivate(A)
-// CHECK: call void @__kmpc_for_static_init_8(%ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i64* [[LB:%[^,]+]], i64* [[UB:%[^,]+]], i64* [[STRIDE:%[^,]+]], i64 1, i64 1)
+// CHECK: call void @__kmpc_for_static_init_8(%struct.ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i64* [[LB:%[^,]+]], i64* [[UB:%[^,]+]], i64* [[STRIDE:%[^,]+]], i64 1, i64 1)
// CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
// CHECK: [[CMP:%.+]] = icmp sgt i64 [[UB_VAL]], 6
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
@@ -295,14 +301,14 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: store i64 [[ADD7_2]], i64* [[OMP_IV7]]
}
// CHECK: [[SIMPLE_LOOP7_END]]:
-// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
+// CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* {{.+}}, i32 %{{.+}})
// CHECK: load i32, i32*
// CHECK: icmp ne i32 %{{.+}}, 0
// CHECK: br i1 %{{.+}}, label
// CHECK: [[A_PRIV_VAL:%.+]] = load i32, i32* [[A_PRIV]],
// CHECK-NEXT: store i32 [[A_PRIV_VAL]], i32* %{{.+}},
// CHECK-NEXT: br label
-// CHECK: call void @__kmpc_barrier(%ident_t* {{.+}}, i32 %{{.+}})
+// CHECK: call void @__kmpc_barrier(%struct.ident_t* {{.+}}, i32 %{{.+}})
}
int R;
#pragma omp parallel
@@ -311,7 +317,7 @@ void simple(float *a, float *b, float *c, float *d) {
R = -1;
// CHECK: store i32 1, i32* [[R_PRIV:%[^,]+]],
#pragma omp for simd reduction(*:R)
-// CHECK: call void @__kmpc_for_static_init_8(%ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i64* [[LB:%[^,]+]], i64* [[UB:%[^,]+]], i64* [[STRIDE:%[^,]+]], i64 1, i64 1)
+// CHECK: call void @__kmpc_for_static_init_8(%struct.ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i64* [[LB:%[^,]+]], i64* [[UB:%[^,]+]], i64* [[STRIDE:%[^,]+]], i64 1, i64 1)
// CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
// CHECK: [[CMP:%.+]] = icmp sgt i64 [[UB_VAL]], 6
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
@@ -347,13 +353,13 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: store i64 [[ADD8_2]], i64* [[OMP_IV8]]
}
// CHECK: [[SIMPLE_LOOP8_END]]:
-// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
+// CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call i32 @__kmpc_reduce(
// CHECK: [[R_PRIV_VAL:%.+]] = load i32, i32* [[R_PRIV]],
// CHECK: [[RED:%.+]] = mul nsw i32 %{{.+}}, [[R_PRIV_VAL]]
// CHECK-NEXT: store i32 [[RED]], i32* %{{.+}},
// CHECK-NEXT: call void @__kmpc_end_reduce(
-// CHECK: call void @__kmpc_barrier(%ident_t* {{.+}}, i32 %{{.+}})
+// CHECK: call void @__kmpc_barrier(%struct.ident_t* {{.+}}, i32 %{{.+}})
}
}
@@ -372,7 +378,7 @@ int templ1(T a, T *z) {
// Instatiation templ1<float,2>
// CHECK-LABEL: define {{.*i32}} @{{.*}}templ1{{.*}}(float {{.+}}, float* {{.+}})
-// CHECK: call void @__kmpc_for_static_init_8(%ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 45, i32* %{{[^,]+}}, i64* [[LB:%[^,]+]], i64* [[UB:%[^,]+]], i64* [[STRIDE:%[^,]+]], i64 1, i64 2)
+// CHECK: call void @__kmpc_for_static_init_8(%struct.ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 45, i32* %{{[^,]+}}, i64* [[LB:%[^,]+]], i64* [[UB:%[^,]+]], i64* [[STRIDE:%[^,]+]], i64 1, i64 2)
// CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
// CHECK: [[CMP:%.+]] = icmp sgt i64 [[UB_VAL]], 15
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
@@ -412,8 +418,8 @@ int templ1(T a, T *z) {
// CHECK-NEXT: store i64 [[INC]], i64* [[T1_OMP_IV]]
// CHECK-NEXT: br label {{%.+}}
// CHECK: [[T1_END]]:
-// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
-// CHECK: call void @__kmpc_barrier(%ident_t* {{.+}}, i32 %{{.+}})
+// CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* {{.+}}, i32 %{{.+}})
+// CHECK: call void @__kmpc_barrier(%struct.ident_t* {{.+}}, i32 %{{.+}})
// CHECK: ret i32 0
//
void inst_templ1() {
@@ -463,7 +469,7 @@ void iter_simple(IterDouble ia, IterDouble ib, IterDouble ic) {
// CHECK-NEXT: store i32 [[DIFF5]], i32* [[OMP_LAST_IT:%[^,]+]]{{.+}}
#pragma omp for simd
-// CHECK: call void @__kmpc_for_static_init_4(%ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i32* [[LB:%[^,]+]], i32* [[UB:%[^,]+]], i32* [[STRIDE:%[^,]+]], i32 1, i32 1)
+// CHECK: call void @__kmpc_for_static_init_4(%struct.ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i32* [[LB:%[^,]+]], i32* [[UB:%[^,]+]], i32* [[STRIDE:%[^,]+]], i32 1, i32 1)
// CHECK-DAG: [[UB_VAL:%.+]] = load i32, i32* [[UB]],
// CHECK-DAG: [[OMP_LAST_IT_VAL:%.+]] = load i32, i32* [[OMP_LAST_IT]],
// CHECK: [[CMP:%.+]] = icmp sgt i32 [[UB_VAL]], [[OMP_LAST_IT_VAL]]
@@ -504,8 +510,8 @@ void iter_simple(IterDouble ia, IterDouble ib, IterDouble ic) {
// br label %{{.*}}, !llvm.loop ![[ITER_LOOP_ID]]
}
// CHECK: [[IT_END]]:
-// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
-// CHECK: call void @__kmpc_barrier(%ident_t* {{.+}}, i32 %{{.+}})
+// CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* {{.+}}, i32 %{{.+}})
+// CHECK: call void @__kmpc_barrier(%struct.ident_t* {{.+}}, i32 %{{.+}})
// CHECK: ret void
}
@@ -516,7 +522,7 @@ void collapsed(float *a, float *b, float *c, float *d) {
unsigned j; // middle loop couter, leads to unsigned icmp in loop header.
// k declared in the loop init below
short l; // inner loop counter
-// CHECK: call void @__kmpc_for_static_init_4u(%ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i32* [[LB:%[^,]+]], i32* [[UB:%[^,]+]], i32* [[STRIDE:%[^,]+]], i32 1, i32 1)
+// CHECK: call void @__kmpc_for_static_init_4u(%struct.ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i32* [[LB:%[^,]+]], i32* [[UB:%[^,]+]], i32* [[STRIDE:%[^,]+]], i32 1, i32 1)
// CHECK: [[UB_VAL:%.+]] = load i32, i32* [[UB]],
// CHECK: [[CMP:%.+]] = icmp ugt i32 [[UB_VAL]], 119
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
@@ -580,13 +586,13 @@ void collapsed(float *a, float *b, float *c, float *d) {
// CHECK: [[COLL1_END]]:
}
// i,j,l are updated; k is not updated.
-// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
+// CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* {{.+}}, i32 %{{.+}})
// CHECK: br i1
// CHECK: store i32 3, i32*
// CHECK-NEXT: store i32 5,
// CHECK-NEXT: store i32 7,
// CHECK-NEXT: store i16 9, i16*
-// CHECK: call void @__kmpc_barrier(%ident_t* {{.+}}, i32 %{{.+}})
+// CHECK: call void @__kmpc_barrier(%struct.ident_t* {{.+}}, i32 %{{.+}})
// CHECK: ret void
}
@@ -604,7 +610,7 @@ void widened(float *a, float *b, float *c, float *d) {
// CHECK: [[MUL:%.+]] = mul nsw i64 2, %{{.+}}
// CHECK-NEXT: [[SUB:%.+]] = sub nsw i64 [[MUL]], 1
// CHECK-NEXT: store i64 [[SUB]], i64* [[OMP_LAST_IT:%[^,]+]],
-// CHECK: call void @__kmpc_for_static_init_8(%ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i64* [[LB:%[^,]+]], i64* [[UB:%[^,]+]], i64* [[STRIDE:%[^,]+]], i64 1, i64 1)
+// CHECK: call void @__kmpc_for_static_init_8(%struct.ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i64* [[LB:%[^,]+]], i64* [[UB:%[^,]+]], i64* [[STRIDE:%[^,]+]], i64 1, i64 1)
// CHECK-DAG: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
// CHECK-DAG: [[OMP_LAST_IT_VAL:%.+]] = load i64, i64* [[OMP_LAST_IT]],
// CHECK: [[CMP:%.+]] = icmp sgt i64 [[UB_VAL]], [[OMP_LAST_IT_VAL]]
@@ -684,4 +690,5 @@ void parallel_simd(float *a) {
a[i] += bar();
}
// TERM_DEBUG: !{{[0-9]+}} = !DILocation(line: [[@LINE-11]],
+// TERM_DEBUG-NOT: line: 0,
#endif // HEADER
diff --git a/test/OpenMP/for_simd_collapse_messages.cpp b/test/OpenMP/for_simd_collapse_messages.cpp
index 2efd49479ea9..9e9b8ee6752e 100644
--- a/test/OpenMP/for_simd_collapse_messages.cpp
+++ b/test/OpenMP/for_simd_collapse_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/for_simd_firstprivate_messages.cpp b/test/OpenMP/for_simd_firstprivate_messages.cpp
index 4e96866c1a2c..ceacdb6a53c1 100644
--- a/test/OpenMP/for_simd_firstprivate_messages.cpp
+++ b/test/OpenMP/for_simd_firstprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/for_simd_lastprivate_messages.cpp b/test/OpenMP/for_simd_lastprivate_messages.cpp
index a176a2d70eb9..9ed2232d6a37 100644
--- a/test/OpenMP/for_simd_lastprivate_messages.cpp
+++ b/test/OpenMP/for_simd_lastprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/for_simd_linear_messages.cpp b/test/OpenMP/for_simd_linear_messages.cpp
index 3f93125a38a2..ff522e7b7ece 100644
--- a/test/OpenMP/for_simd_linear_messages.cpp
+++ b/test/OpenMP/for_simd_linear_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
namespace X {
int x;
};
diff --git a/test/OpenMP/for_simd_loop_messages.cpp b/test/OpenMP/for_simd_loop_messages.cpp
index ea17a836cf80..a3ae84efd4ae 100644
--- a/test/OpenMP/for_simd_loop_messages.cpp
+++ b/test/OpenMP/for_simd_loop_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+
class S {
int a;
S() : a(0) {}
diff --git a/test/OpenMP/for_simd_misc_messages.c b/test/OpenMP/for_simd_misc_messages.c
index ca1e366ca092..4da2e6bb6c15 100644
--- a/test/OpenMP/for_simd_misc_messages.c
+++ b/test/OpenMP/for_simd_misc_messages.c
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -verify %s
+
// expected-error@+1 {{unexpected OpenMP directive '#pragma omp for simd'}}
#pragma omp for simd
diff --git a/test/OpenMP/for_simd_private_messages.cpp b/test/OpenMP/for_simd_private_messages.cpp
index ca4c3a33fcaf..8fe6d7b721ee 100644
--- a/test/OpenMP/for_simd_private_messages.cpp
+++ b/test/OpenMP/for_simd_private_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/for_simd_reduction_messages.cpp b/test/OpenMP/for_simd_reduction_messages.cpp
index a77ab754eff9..1f5578e611ee 100644
--- a/test/OpenMP/for_simd_reduction_messages.cpp
+++ b/test/OpenMP/for_simd_reduction_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/for_simd_safelen_messages.cpp b/test/OpenMP/for_simd_safelen_messages.cpp
index fa1b4442cee4..31b0f84cba42 100644
--- a/test/OpenMP/for_simd_safelen_messages.cpp
+++ b/test/OpenMP/for_simd_safelen_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/for_simd_schedule_messages.cpp b/test/OpenMP/for_simd_schedule_messages.cpp
index 76ba3a42eda2..b330f8cfd005 100644
--- a/test/OpenMP/for_simd_schedule_messages.cpp
+++ b/test/OpenMP/for_simd_schedule_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/for_simd_simdlen_messages.cpp b/test/OpenMP/for_simd_simdlen_messages.cpp
index 8fe197979cc2..09954283a11f 100644
--- a/test/OpenMP/for_simd_simdlen_messages.cpp
+++ b/test/OpenMP/for_simd_simdlen_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/function-attr.cpp b/test/OpenMP/function-attr.cpp
index 87aba40f2b7d..a370cc35f7e8 100644
--- a/test/OpenMP/function-attr.cpp
+++ b/test/OpenMP/function-attr.cpp
@@ -1,5 +1,8 @@
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -stack-protector 2 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -stack-protector 2 -emit-llvm -o - %s | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// Check that function attributes are added to the OpenMP runtime functions.
template <class T>
diff --git a/test/OpenMP/is_initial_device.c b/test/OpenMP/is_initial_device.c
index 0521f0bd5393..2fe93a4eb6c4 100644
--- a/test/OpenMP/is_initial_device.c
+++ b/test/OpenMP/is_initial_device.c
@@ -7,6 +7,11 @@
// RUN: %clang_cc1 -verify -fopenmp -x c -triple powerpc64le-unknown-unknown -emit-llvm -fopenmp-is-device \
// RUN: %s -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s -check-prefixes DEVICE,OUTLINED
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-unknown-unknown -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x ir -triple powerpc64le-unknown-unknown -emit-llvm %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c -triple powerpc64le-unknown-unknown -emit-llvm -fopenmp-is-device %s -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
int check() {
int host = omp_is_initial_device();
diff --git a/test/OpenMP/linking.c b/test/OpenMP/linking.c
index 71e978f7fe48..802553c1be75 100644
--- a/test/OpenMP/linking.c
+++ b/test/OpenMP/linking.c
@@ -20,9 +20,19 @@
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN: -fopenmp=libgomp -target i386-unknown-linux -rtlib=platform \
// RUN: | FileCheck --check-prefix=CHECK-GOMP-LD-32 %s
+
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 -fopenmp-simd -target i386-unknown-linux -rtlib=platform | FileCheck --check-prefix SIMD-ONLY2 %s
+// SIMD-ONLY2-NOT: lgomp
+// SIMD-ONLY2-NOT: lomp
+// SIMD-ONLY2-NOT: liomp
// CHECK-GOMP-LD-32: "{{.*}}ld{{(.exe)?}}"
// CHECK-GOMP-LD-32: "-lgomp" "-lrt"
// CHECK-GOMP-LD-32: "-lpthread" "-lc"
+
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 -fopenmp-simd -target i386-unknown-linux -rtlib=platform | FileCheck --check-prefix SIMD-ONLY2 %s
+// SIMD-ONLY2-NOT: lgomp
+// SIMD-ONLY2-NOT: lomp
+// SIMD-ONLY2-NOT: liomp
//
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN: -fopenmp=libgomp -target x86_64-unknown-linux -rtlib=platform \
@@ -79,10 +89,20 @@
// CHECK-MSVC-LINK-64-SAME: -nodefaultlib:vcompd.lib
// CHECK-MSVC-LINK-64-SAME: -libpath:{{.+}}/../lib
// CHECK-MSVC-LINK-64-SAME: -defaultlib:libomp.lib
+
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 -fopenmp-simd -target x86_64-msvc-win32 -rtlib=platform | FileCheck --check-prefix SIMD-ONLY11 %s
+// SIMD-ONLY11-NOT: libiomp
+// SIMD-ONLY11-NOT: libomp
+// SIMD-ONLY11-NOT: libgomp
//
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN: -fopenmp=libiomp5 -target x86_64-msvc-win32 -rtlib=platform \
// RUN: | FileCheck --check-prefix=CHECK-MSVC-ILINK-64 %s
+
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 -fopenmp-simd -target x86_64-msvc-win32 -rtlib=platform | FileCheck --check-prefix SIMD-ONLY11 %s
+// SIMD-ONLY11-NOT: libiomp
+// SIMD-ONLY11-NOT: libomp
+// SIMD-ONLY11-NOT: libgomp
// CHECK-MSVC-ILINK-64: link.exe
// CHECK-MSVC-ILINK-64-SAME: -nodefaultlib:vcomp.lib
// CHECK-MSVC-ILINK-64-SAME: -nodefaultlib:vcompd.lib
diff --git a/test/OpenMP/loops_explicit_clauses_codegen.cpp b/test/OpenMP/loops_explicit_clauses_codegen.cpp
index dc21fd11af6f..43fbd56b592d 100644
--- a/test/OpenMP/loops_explicit_clauses_codegen.cpp
+++ b/test/OpenMP/loops_explicit_clauses_codegen.cpp
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-unknown -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
diff --git a/test/OpenMP/master_ast_print.cpp b/test/OpenMP/master_ast_print.cpp
index a36dd02d557b..40b14c5c5086 100644
--- a/test/OpenMP/master_ast_print.cpp
+++ b/test/OpenMP/master_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -21,7 +25,7 @@ int main (int argc, char **argv) {
}
// CHECK-NEXT: #pragma omp parallel
// CHECK-NEXT: {
-// CHECK-NEXT: #pragma omp master
+// CHECK-NEXT: #pragma omp master{{$}}
// CHECK-NEXT: {
// CHECK-NEXT: a = 2;
// CHECK-NEXT: }
diff --git a/test/OpenMP/master_codegen.cpp b/test/OpenMP/master_codegen.cpp
index ad92a13e14cf..d5b8036e8e82 100644
--- a/test/OpenMP/master_codegen.cpp
+++ b/test/OpenMP/master_codegen.cpp
@@ -2,6 +2,12 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck %s --check-prefix=TERM_DEBUG
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/master_messages.cpp b/test/OpenMP/master_messages.cpp
index 397f1394a3e9..26d6bc8e9f35 100644
--- a/test/OpenMP/master_messages.cpp
+++ b/test/OpenMP/master_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
int foo();
int main() {
diff --git a/test/OpenMP/nesting_of_regions.cpp b/test/OpenMP/nesting_of_regions.cpp
index 6282de4cc478..0955ee215569 100644
--- a/test/OpenMP/nesting_of_regions.cpp
+++ b/test/OpenMP/nesting_of_regions.cpp
@@ -1,5 +1,8 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -verify %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
void bar();
template <class T>
diff --git a/test/OpenMP/no_option.c b/test/OpenMP/no_option.c
index 8a65b039fc9f..b9bc2082b3f9 100644
--- a/test/OpenMP/no_option.c
+++ b/test/OpenMP/no_option.c
@@ -1,4 +1,7 @@
// RUN: %clang_cc1 -verify -o - %s
+
+// RUN: %clang_cc1 -verify -o - %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
int a;
diff --git a/test/OpenMP/no_option_no_warn.c b/test/OpenMP/no_option_no_warn.c
index 10778c0b1e35..87556388ce0b 100644
--- a/test/OpenMP/no_option_no_warn.c
+++ b/test/OpenMP/no_option_no_warn.c
@@ -1,4 +1,7 @@
// RUN: %clang_cc1 -verify -Wno-source-uses-openmp -o - %s
+
+// RUN: %clang_cc1 -verify -Wno-source-uses-openmp -o - %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
int a;
diff --git a/test/OpenMP/nvptx_data_sharing.cpp b/test/OpenMP/nvptx_data_sharing.cpp
index 53bac3ced96b..0acb11991527 100644
--- a/test/OpenMP/nvptx_data_sharing.cpp
+++ b/test/OpenMP/nvptx_data_sharing.cpp
@@ -1,4 +1,4 @@
-// Test device data sharing codegen.
+// Test device global memory data sharing codegen.
///==========================================================================///
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
@@ -15,43 +15,92 @@ void test_ds(){
int a = 10;
#pragma omp parallel
{
- a = 1000;
+ a = 1000;
+ }
+ int b = 100;
+ int c = 1000;
+ #pragma omp parallel private(c)
+ {
+ int *c1 = &c;
+ b = a + 10000;
}
}
}
/// ========= In the worker function ========= ///
-
-// CK1: define internal void @__omp_offloading_{{.*}}test_ds{{.*}}worker() [[ATTR1:#.*]] {
-// CK1: [[SHAREDARGS:%.+]] = alloca i8**
-// CK1: call i1 @__kmpc_kernel_parallel(i8** %work_fn, i8*** [[SHAREDARGS]], i16 1)
-// CK1: [[SHARGSTMP:%.+]] = load i8**, i8*** [[SHAREDARGS]]
-// CK1: call void @__omp_outlined___wrapper{{.*}}({{.*}}, i8** [[SHARGSTMP]])
+// CK1: {{.*}}define internal void @__omp_offloading{{.*}}test_ds{{.*}}_worker()
+// CK1: call void @llvm.nvvm.barrier0()
+// CK1-NOT: call void @__kmpc_data_sharing_init_stack
/// ========= In the kernel function ========= ///
-// CK1: {{.*}}define void @__omp_offloading{{.*}}test_ds{{.*}}() [[ATTR2:#.*]] {
+// CK1: {{.*}}define weak void @__omp_offloading{{.*}}test_ds{{.*}}()
// CK1: [[SHAREDARGS1:%.+]] = alloca i8**
-// CK1: call void @__kmpc_kernel_prepare_parallel({{.*}}, i8*** [[SHAREDARGS1]], i32 1, i16 1)
+// CK1: [[SHAREDARGS2:%.+]] = alloca i8**
+// CK1: call void @__kmpc_kernel_init
+// CK1: call void @__kmpc_data_sharing_init_stack
+// CK1: [[GLOBALSTACK:%.+]] = call i8* @__kmpc_data_sharing_push_stack(i64 8, i16 0)
+// CK1: [[GLOBALSTACK2:%.+]] = bitcast i8* [[GLOBALSTACK]] to %struct._globalized_locals_ty*
+// CK1: [[A:%.+]] = getelementptr inbounds %struct._globalized_locals_ty, %struct._globalized_locals_ty* [[GLOBALSTACK2]], i32 0, i32 0
+// CK1: [[B:%.+]] = getelementptr inbounds %struct._globalized_locals_ty, %struct._globalized_locals_ty* [[GLOBALSTACK2]], i32 0, i32 1
+// CK1: store i32 10, i32* [[A]]
+// CK1: call void @__kmpc_kernel_prepare_parallel({{.*}}, i16 1)
+// CK1: call void @__kmpc_begin_sharing_variables(i8*** [[SHAREDARGS1]], i64 1)
// CK1: [[SHARGSTMP1:%.+]] = load i8**, i8*** [[SHAREDARGS1]]
-// CK1: [[SHARGSTMP2:%.+]] = getelementptr inbounds i8*, i8** [[SHARGSTMP1]]
-// CK1: [[SHAREDVAR:%.+]] = bitcast i32* {{.*}} to i8*
+// CK1: [[SHARGSTMP2:%.+]] = getelementptr inbounds i8*, i8** [[SHARGSTMP1]], i64 0
+// CK1: [[SHAREDVAR:%.+]] = bitcast i32* [[A]] to i8*
// CK1: store i8* [[SHAREDVAR]], i8** [[SHARGSTMP2]]
+// CK1: call void @llvm.nvvm.barrier0()
+// CK1: call void @llvm.nvvm.barrier0()
+// CK1: call void @__kmpc_end_sharing_variables()
+// CK1: store i32 100, i32* [[B]]
+// CK1: call void @__kmpc_kernel_prepare_parallel({{.*}}, i16 1)
+// CK1: call void @__kmpc_begin_sharing_variables(i8*** [[SHAREDARGS2]], i64 2)
+// CK1: [[SHARGSTMP3:%.+]] = load i8**, i8*** [[SHAREDARGS2]]
+// CK1: [[SHARGSTMP4:%.+]] = getelementptr inbounds i8*, i8** [[SHARGSTMP3]], i64 0
+// CK1: [[SHAREDVAR1:%.+]] = bitcast i32* [[B]] to i8*
+// CK1: store i8* [[SHAREDVAR1]], i8** [[SHARGSTMP4]]
+// CK1: [[SHARGSTMP12:%.+]] = getelementptr inbounds i8*, i8** [[SHARGSTMP3]], i64 1
+// CK1: [[SHAREDVAR2:%.+]] = bitcast i32* [[A]] to i8*
+// CK1: store i8* [[SHAREDVAR2]], i8** [[SHARGSTMP12]]
+// CK1: call void @llvm.nvvm.barrier0()
+// CK1: call void @llvm.nvvm.barrier0()
+// CK1: call void @__kmpc_end_sharing_variables()
+// CK1: call void @__kmpc_data_sharing_pop_stack(i8* [[GLOBALSTACK]])
+// CK1: call void @__kmpc_kernel_deinit(i16 1)
/// ========= In the data sharing wrapper function ========= ///
-// CK1: {{.*}}define internal void @__omp_outlined___wrapper({{.*}}i8**) [[ATTR1]] {
-// CK1: [[SHAREDARGS2:%.+]] = alloca i8**
-// CK1: store i8** %2, i8*** [[SHAREDARGS2]]
-// CK1: [[SHARGSTMP3:%.+]] = load i8**, i8*** [[SHAREDARGS2]]
-// CK1: [[SHARGSTMP4:%.+]] = getelementptr inbounds i8*, i8** [[SHARGSTMP3]]
-// CK1: [[SHARGSTMP5:%.+]] = bitcast i8** [[SHARGSTMP4]] to i32**
-// CK1: [[SHARGSTMP6:%.+]] = load i32*, i32** [[SHARGSTMP5]]
-// CK1: call void @__omp_outlined__({{.*}}, i32* [[SHARGSTMP6]])
+// CK1: {{.*}}define internal void @__omp_outlined{{.*}}wrapper({{.*}})
+// CK1: [[SHAREDARGS4:%.+]] = alloca i8**
+// CK1: call void @__kmpc_get_shared_variables(i8*** [[SHAREDARGS4]])
+// CK1: [[SHARGSTMP13:%.+]] = load i8**, i8*** [[SHAREDARGS4]]
+// CK1: [[SHARGSTMP14:%.+]] = getelementptr inbounds i8*, i8** [[SHARGSTMP13]], i64 0
+// CK1: [[SHARGSTMP15:%.+]] = bitcast i8** [[SHARGSTMP14]] to i32**
+// CK1: [[SHARGSTMP16:%.+]] = load i32*, i32** [[SHARGSTMP15]]
+// CK1: call void @__omp_outlined__{{.*}}({{.*}}, i32* [[SHARGSTMP16]])
+
+/// outlined function for the second parallel region ///
-/// ========= Attributes ========= ///
+// CK1: define internal void @{{.+}}(i32* noalias %{{.+}}, i32* noalias %{{.+}}, i32* dereferenceable{{.+}}, i32* dereferenceable{{.+}})
+// CK1-NOT: call i8* @__kmpc_data_sharing_push_stack(
+// CK1: [[C_ADDR:%.+]] = alloca i32,
+// CK1: store i32* [[C_ADDR]], i32** %
+// CK1i-NOT: call void @__kmpc_data_sharing_pop_stack(
-// CK1-NOT: attributes [[ATTR1]] = { {{.*}}"has-nvptx-shared-depot"{{.*}} }
-// CK1: attributes [[ATTR2]] = { {{.*}}"has-nvptx-shared-depot"{{.*}} }
+/// ========= In the data sharing wrapper function ========= ///
+
+// CK1: {{.*}}define internal void @__omp_outlined{{.*}}wrapper({{.*}})
+// CK1: [[SHAREDARGS3:%.+]] = alloca i8**
+// CK1: call void @__kmpc_get_shared_variables(i8*** [[SHAREDARGS3]])
+// CK1: [[SHARGSTMP5:%.+]] = load i8**, i8*** [[SHAREDARGS3]]
+// CK1: [[SHARGSTMP6:%.+]] = getelementptr inbounds i8*, i8** [[SHARGSTMP5]], i64 0
+// CK1: [[SHARGSTMP7:%.+]] = bitcast i8** [[SHARGSTMP6]] to i32**
+// CK1: [[SHARGSTMP8:%.+]] = load i32*, i32** [[SHARGSTMP7]]
+// CK1: [[SHARGSTMP9:%.+]] = getelementptr inbounds i8*, i8** [[SHARGSTMP5]], i64 1
+// CK1: [[SHARGSTMP10:%.+]] = bitcast i8** [[SHARGSTMP9]] to i32**
+// CK1: [[SHARGSTMP11:%.+]] = load i32*, i32** [[SHARGSTMP10]]
+// CK1: call void @__omp_outlined__{{.*}}({{.*}}, i32* [[SHARGSTMP8]], i32* [[SHARGSTMP11]])
#endif
+
diff --git a/test/OpenMP/nvptx_declare_target_var_ctor_dtor_codegen.cpp b/test/OpenMP/nvptx_declare_target_var_ctor_dtor_codegen.cpp
new file mode 100644
index 000000000000..3cd85eefbc2c
--- /dev/null
+++ b/test/OpenMP/nvptx_declare_target_var_ctor_dtor_codegen.cpp
@@ -0,0 +1,111 @@
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -o - | FileCheck %s --check-prefix HOST --check-prefix CHECK
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -fopenmp -x c++ -triple nvptx64-nvidia-cuda -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix DEVICE --check-prefix CHECK
+// RUN: %clang_cc1 -fopenmp -x c++ -triple nvptx64-nvidia-cuda -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -emit-pch -o %t
+// RUN: %clang_cc1 -fopenmp -x c++ -triple nvptx64-nvidia-cuda -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -o - | FileCheck %s --check-prefix DEVICE --check-prefix CHECK
+
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o -| FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -emit-pch -o %t
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -o - | FileCheck %s --check-prefix SIMD-ONLY
+
+#ifndef HEADER
+#define HEADER
+
+// SIMD-ONLY-NOT: {{__kmpc|__tgt}}
+
+// DEVICE-DAG: [[C_ADDR:.+]] = weak_odr global i32 0,
+// DEVICE-DAG: [[CD_ADDR:@.+]] = global %struct.S zeroinitializer,
+// HOST-DAG: @[[C_ADDR:.+]] = internal global i32 0,
+// HOST-DAG: @[[CD_ADDR:.+]] = global %struct.S zeroinitializer,
+
+#pragma omp declare target
+int foo() { return 0; }
+#pragma omp end declare target
+int bar() { return 0; }
+#pragma omp declare target (bar)
+int baz() { return 0; }
+
+#pragma omp declare target
+int doo() { return 0; }
+#pragma omp end declare target
+int car() { return 0; }
+#pragma omp declare target (bar)
+int caz() { return 0; }
+
+// DEVICE-DAG: define i32 [[FOO:@.*foo.*]]()
+// DEVICE-DAG: define i32 [[BAR:@.*bar.*]]()
+// DEVICE-DAG: define i32 [[BAZ:@.*baz.*]]()
+// DEVICE-DAG: define i32 [[DOO:@.*doo.*]]()
+// DEVICE-DAG: define i32 [[CAR:@.*car.*]]()
+// DEVICE-DAG: define i32 [[CAZ:@.*caz.*]]()
+
+static int c = foo() + bar() + baz();
+#pragma omp declare target (c)
+// HOST-DAG: @[[C_CTOR:__omp_offloading__.+_c_l44_ctor]] = private constant i8 0
+// DEVICE-DAG: define internal void [[C_CTOR:@__omp_offloading__.+_c_l44_ctor]]()
+// DEVICE-DAG: call i32 [[FOO]]()
+// DEVICE-DAG: call i32 [[BAR]]()
+// DEVICE-DAG: call i32 [[BAZ]]()
+// DEVICE-DAG: ret void
+
+struct S {
+ int a;
+ S() = default;
+ S(int a) : a(a) {}
+ ~S() { a = 0; }
+};
+
+#pragma omp declare target
+S cd = doo() + car() + caz() + baz();
+#pragma omp end declare target
+// HOST-DAG: @[[CD_CTOR:__omp_offloading__.+_cd_l61_ctor]] = private constant i8 0
+// DEVICE-DAG: define internal void [[CD_CTOR:@__omp_offloading__.+_cd_l61_ctor]]()
+// DEVICE-DAG: call i32 [[DOO]]()
+// DEVICE-DAG: call i32 [[CAR]]()
+// DEVICE-DAG: call i32 [[CAZ]]()
+// DEVICE-DAG: ret void
+
+// HOST-DAG: @[[CD_DTOR:__omp_offloading__.+_cd_l61_dtor]] = private constant i8 0
+// DEVICE-DAG: define internal void [[CD_DTOR:@__omp_offloading__.+_cd_l61_dtor]]()
+// DEVICE-DAG: call void
+// DEVICE-DAG: ret void
+
+// HOST-DAG: @.omp_offloading.entry_name{{.*}} = internal unnamed_addr constant [{{[0-9]+}} x i8] c"[[C_ADDR]]\00"
+// HOST-DAG: @.omp_offloading.entry.[[C_ADDR]] = weak constant %struct.__tgt_offload_entry { i8* bitcast (i32* @[[C_ADDR]] to i8*), i8* getelementptr inbounds ([{{[0-9]+}} x i8], [{{[0-9]+}} x i8]* @.omp_offloading.entry_name{{.*}}, i32 0, i32 0), i64 4, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// HOST-DAG: @.omp_offloading.entry_name{{.*}} = internal unnamed_addr constant [{{[0-9]+}} x i8] c"[[CD_ADDR]]\00"
+// HOST-DAG: @.omp_offloading.entry.[[CD_ADDR]] = weak constant %struct.__tgt_offload_entry { i8* bitcast (%struct.S* @[[CD_ADDR]] to i8*), i8* getelementptr inbounds ([{{[0-9]+}} x i8], [{{[0-9]+}} x i8]* @.omp_offloading.entry_name{{.*}}, i32 0, i32 0), i64 4, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// HOST-DAG: @.omp_offloading.entry_name{{.*}} = internal unnamed_addr constant [{{[0-9]+}} x i8] c"[[C_CTOR]]\00"
+// HOST-DAG: @.omp_offloading.entry.[[C_CTOR]] = weak constant %struct.__tgt_offload_entry { i8* @[[C_CTOR]], i8* getelementptr inbounds ([{{[0-9]+}} x i8], [{{[0-9]+}} x i8]* @.omp_offloading.entry_name{{.*}}, i32 0, i32 0), i64 0, i32 2, i32 0 }, section ".omp_offloading.entries", align 1
+// HOST-DAG: @.omp_offloading.entry_name{{.*}}= internal unnamed_addr constant [{{[0-9]+}} x i8] c"[[CD_CTOR]]\00"
+// HOST-DAG: @.omp_offloading.entry.[[CD_CTOR]] = weak constant %struct.__tgt_offload_entry { i8* @[[CD_CTOR]], i8* getelementptr inbounds ([{{[0-9]+}} x i8], [{{[0-9]+}} x i8]* @.omp_offloading.entry_name{{.*}}, i32 0, i32 0), i64 0, i32 2, i32 0 }, section ".omp_offloading.entries", align 1
+// HOST-DAG: @.omp_offloading.entry_name{{.*}}= internal unnamed_addr constant [{{[0-9]+}} x i8] c"[[CD_DTOR]]\00"
+// HOST-DAG: @.omp_offloading.entry.[[CD_DTOR]] = weak constant %struct.__tgt_offload_entry { i8* @[[CD_DTOR]], i8* getelementptr inbounds ([{{[0-9]+}} x i8], [{{[0-9]+}} x i8]* @.omp_offloading.entry_name{{.*}}, i32 0, i32 0), i64 0, i32 4, i32 0 }, section ".omp_offloading.entries", align 1
+int maini1() {
+ int a;
+#pragma omp target map(tofrom : a)
+ {
+ a = c;
+ }
+ return 0;
+}
+
+// DEVICE: define weak void @__omp_offloading_{{.*}}_{{.*}}maini1{{.*}}_l[[@LINE-7]](i32* dereferenceable{{[^,]*}}
+// DEVICE: [[C:%.+]] = load i32, i32* [[C_ADDR]],
+// DEVICE: store i32 [[C]], i32* %
+
+// HOST: define internal void @__omp_offloading_{{.*}}_{{.*}}maini1{{.*}}_l[[@LINE-11]](i32* dereferenceable{{.*}})
+// HOST: [[C:%.*]] = load i32, i32* @[[C_ADDR]],
+// HOST: store i32 [[C]], i32* %
+
+// HOST-DAG: !{i32 1, !"[[CD_ADDR]]", i32 0, i32 {{[0-9]+}}}
+// HOST-DAG: !{i32 1, !"[[C_ADDR]]", i32 0, i32 {{[0-9]+}}}
+
+// DEVICE: !nvvm.annotations
+// DEVICE-DAG: !{void ()* [[C_CTOR]], !"kernel", i32 1}
+// DEVICE-DAG: !{void ()* [[CD_CTOR]], !"kernel", i32 1}
+// DEVICE-DAG: !{void ()* [[CD_DTOR]], !"kernel", i32 1}
+
+#endif // HEADER
+
diff --git a/test/OpenMP/nvptx_distribute_parallel_generic_mode_codegen.cpp b/test/OpenMP/nvptx_distribute_parallel_generic_mode_codegen.cpp
new file mode 100644
index 000000000000..2b18f6d3f9bd
--- /dev/null
+++ b/test/OpenMP/nvptx_distribute_parallel_generic_mode_codegen.cpp
@@ -0,0 +1,51 @@
+// Test target codegen - host bc file has to be created first.
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fexceptions -fcxx-exceptions -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+int a;
+
+int foo(int *a);
+
+int main(int argc, char **argv) {
+ int b[10], c[10], d[10];
+#pragma omp target teams map(tofrom:a)
+#pragma omp distribute parallel for firstprivate(b) lastprivate(c) if(a)
+ for (int i= 0; i < argc; ++i)
+ a = foo(&i) + foo(&a) + foo(&b[i]) + foo(&c[i]) + foo(&d[i]);
+ return 0;
+}
+
+// CHECK: @__omp_offloading_{{.*}}_main_l17_exec_mode = weak constant i8 1
+
+// CHECK-LABEL: define internal void @__omp_offloading_{{.*}}_main_l17_worker(
+
+// CHECK: define weak void @__omp_offloading_{{.*}}_main_l17([10 x i32]* dereferenceable(40) %{{.+}}, [10 x i32]* dereferenceable(40) %{{.+}}, i32* dereferenceable(4) %{{.+}}, i{{64|32}} %{{.+}}, [10 x i32]* dereferenceable(40) %{{.+}})
+// CHECK: [[PTR:%.+]] = call i8* @__kmpc_data_sharing_push_stack(i{{64|32}} 84, i16 0)
+// CHECK: [[STACK:%.+]] = bitcast i8* [[PTR]] to %struct._globalized_locals_ty*
+// CHECK: [[ARGC:%.+]] = load i32, i32* %{{.+}}, align
+// CHECK: [[ARGC_ADDR:%.+]] = getelementptr inbounds %struct._globalized_locals_ty, %struct._globalized_locals_ty* [[STACK]], i{{32|64}} 0, i{{32|64}} 0
+// CHECK: store i32 [[ARGC]], i32* [[ARGC_ADDR]],
+// CHECK: getelementptr inbounds %struct._globalized_locals_ty, %struct._globalized_locals_ty* [[STACK]], i{{32|64}} 0, i{{32|64}} 1
+// CHECK: getelementptr inbounds %struct._globalized_locals_ty, %struct._globalized_locals_ty* [[STACK]], i{{32|64}} 0, i{{32|64}} 2
+// CHECK: call void @__kmpc_for_static_init_4(
+
+// CHECK: call void @__kmpc_serialized_parallel(
+// CHECK: call void [[PARALLEL:@.+]](
+// CHECK: call void @__kmpc_end_serialized_parallel(
+
+// CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* @
+
+// CHECK: call void @__kmpc_data_sharing_pop_stack(i8* [[PTR]])
+
+// CHECK: define internal void [[PARALLEL]](
+// CHECK-NOT: call i8* @__kmpc_data_sharing_push_stack(
+
+// CHECK-NOT: call void @__kmpc_data_sharing_pop_stack(
+
+#endif
diff --git a/test/OpenMP/nvptx_parallel_codegen.cpp b/test/OpenMP/nvptx_parallel_codegen.cpp
index ba889bf4975f..d1a3104407d0 100644
--- a/test/OpenMP/nvptx_parallel_codegen.cpp
+++ b/test/OpenMP/nvptx_parallel_codegen.cpp
@@ -51,6 +51,15 @@ tx ftemplate(int n) {
b[2] += 1;
}
+ #pragma omp target
+ {
+ #pragma omp parallel
+ {
+ #pragma omp critical
+ ++a;
+ }
+ ++a;
+ }
return a;
}
@@ -62,256 +71,278 @@ int bar(int n){
return a;
}
- // CHECK-NOT: define {{.*}}void {{@__omp_offloading_.+template.+l17}}_worker()
-
-
-
-
-
+// CHECK-NOT: define {{.*}}void {{@__omp_offloading_.+template.+l17}}_worker()
- // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l26}}_worker()
- // CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8,
- // CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*,
- // CHECK: store i8* null, i8** [[OMP_WORK_FN]],
- // CHECK: store i8 0, i8* [[OMP_EXEC_STATUS]],
- // CHECK: br label {{%?}}[[AWAIT_WORK:.+]]
- //
- // CHECK: [[AWAIT_WORK]]
- // CHECK: call void @llvm.nvvm.barrier0()
- // CHECK: [[KPR:%.+]] = call i1 @__kmpc_kernel_parallel(i8** [[OMP_WORK_FN]],
- // CHECK: [[KPRB:%.+]] = zext i1 [[KPR]] to i8
- // store i8 [[KPRB]], i8* [[OMP_EXEC_STATUS]], align 1
- // CHECK: [[WORK:%.+]] = load i8*, i8** [[OMP_WORK_FN]],
- // CHECK: [[SHOULD_EXIT:%.+]] = icmp eq i8* [[WORK]], null
- // CHECK: br i1 [[SHOULD_EXIT]], label {{%?}}[[EXIT:.+]], label {{%?}}[[SEL_WORKERS:.+]]
- //
- // CHECK: [[SEL_WORKERS]]
- // CHECK: [[ST:%.+]] = load i8, i8* [[OMP_EXEC_STATUS]]
- // CHECK: [[IS_ACTIVE:%.+]] = icmp ne i8 [[ST]], 0
- // CHECK: br i1 [[IS_ACTIVE]], label {{%?}}[[EXEC_PARALLEL:.+]], label {{%?}}[[BAR_PARALLEL:.+]]
- //
- // CHECK: [[EXEC_PARALLEL]]
- // CHECK: [[WF1:%.+]] = load i8*, i8** [[OMP_WORK_FN]],
- // CHECK: [[WM1:%.+]] = icmp eq i8* [[WF1]], bitcast (void (i16, i32, i8**)* [[PARALLEL_FN1:@.+]]_wrapper to i8*)
- // CHECK: br i1 [[WM1]], label {{%?}}[[EXEC_PFN1:.+]], label {{%?}}[[CHECK_NEXT1:.+]]
- //
- // CHECK: [[EXEC_PFN1]]
- // CHECK: call void [[PARALLEL_FN1]]_wrapper(
- // CHECK: br label {{%?}}[[TERM_PARALLEL:.+]]
- //
- // CHECK: [[CHECK_NEXT1]]
- // CHECK: [[WF2:%.+]] = load i8*, i8** [[OMP_WORK_FN]],
- // CHECK: [[WM2:%.+]] = icmp eq i8* [[WF2]], bitcast (void (i16, i32, i8**)* [[PARALLEL_FN2:@.+]]_wrapper to i8*)
- // CHECK: br i1 [[WM2]], label {{%?}}[[EXEC_PFN2:.+]], label {{%?}}[[CHECK_NEXT2:.+]]
- //
- // CHECK: [[EXEC_PFN2]]
- // CHECK: call void [[PARALLEL_FN2]]_wrapper(
- // CHECK: br label {{%?}}[[TERM_PARALLEL:.+]]
- //
- // CHECK: [[CHECK_NEXT2]]
- // CHECK: br label {{%?}}[[TERM_PARALLEL:.+]]
- //
- // CHECK: [[TERM_PARALLEL]]
- // CHECK: call void @__kmpc_kernel_end_parallel()
- // CHECK: br label {{%?}}[[BAR_PARALLEL]]
- //
- // CHECK: [[BAR_PARALLEL]]
- // CHECK: call void @llvm.nvvm.barrier0()
- // CHECK: br label {{%?}}[[AWAIT_WORK]]
- //
- // CHECK: [[EXIT]]
- // CHECK: ret void
+// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l26}}_worker()
+// CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8,
+// CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*,
+// CHECK: store i8* null, i8** [[OMP_WORK_FN]],
+// CHECK: store i8 0, i8* [[OMP_EXEC_STATUS]],
+// CHECK: br label {{%?}}[[AWAIT_WORK:.+]]
+//
+// CHECK: [[AWAIT_WORK]]
+// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: [[KPR:%.+]] = call i1 @__kmpc_kernel_parallel(i8** [[OMP_WORK_FN]]
+// CHECK: [[KPRB:%.+]] = zext i1 [[KPR]] to i8
+// store i8 [[KPRB]], i8* [[OMP_EXEC_STATUS]], align 1
+// CHECK: [[WORK:%.+]] = load i8*, i8** [[OMP_WORK_FN]],
+// CHECK: [[SHOULD_EXIT:%.+]] = icmp eq i8* [[WORK]], null
+// CHECK: br i1 [[SHOULD_EXIT]], label {{%?}}[[EXIT:.+]], label {{%?}}[[SEL_WORKERS:.+]]
+//
+// CHECK: [[SEL_WORKERS]]
+// CHECK: [[ST:%.+]] = load i8, i8* [[OMP_EXEC_STATUS]]
+// CHECK: [[IS_ACTIVE:%.+]] = icmp ne i8 [[ST]], 0
+// CHECK: br i1 [[IS_ACTIVE]], label {{%?}}[[EXEC_PARALLEL:.+]], label {{%?}}[[BAR_PARALLEL:.+]]
+//
+// CHECK: [[EXEC_PARALLEL]]
+// CHECK: [[WF1:%.+]] = load i8*, i8** [[OMP_WORK_FN]],
+// CHECK: [[WM1:%.+]] = icmp eq i8* [[WF1]], bitcast (void (i16, i32)* [[PARALLEL_FN1:@.+]]_wrapper to i8*)
+// CHECK: br i1 [[WM1]], label {{%?}}[[EXEC_PFN1:.+]], label {{%?}}[[CHECK_NEXT1:.+]]
+//
+// CHECK: [[EXEC_PFN1]]
+// CHECK: call void [[PARALLEL_FN1]]_wrapper(
+// CHECK: br label {{%?}}[[TERM_PARALLEL:.+]]
+//
+// CHECK: [[CHECK_NEXT1]]
+// CHECK: [[WF2:%.+]] = load i8*, i8** [[OMP_WORK_FN]],
+// CHECK: [[WM2:%.+]] = icmp eq i8* [[WF2]], bitcast (void (i16, i32)* [[PARALLEL_FN2:@.+]]_wrapper to i8*)
+// CHECK: br i1 [[WM2]], label {{%?}}[[EXEC_PFN2:.+]], label {{%?}}[[CHECK_NEXT2:.+]]
+//
+// CHECK: [[EXEC_PFN2]]
+// CHECK: call void [[PARALLEL_FN2]]_wrapper(
+// CHECK: br label {{%?}}[[TERM_PARALLEL:.+]]
+//
+// CHECK: [[CHECK_NEXT2]]
+// CHECK: br label {{%?}}[[TERM_PARALLEL:.+]]
+//
+// CHECK: [[TERM_PARALLEL]]
+// CHECK: call void @__kmpc_kernel_end_parallel()
+// CHECK: br label {{%?}}[[BAR_PARALLEL]]
+//
+// CHECK: [[BAR_PARALLEL]]
+// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: br label {{%?}}[[AWAIT_WORK]]
+//
+// CHECK: [[EXIT]]
+// CHECK: ret void
- // CHECK: define {{.*}}void [[T6:@__omp_offloading_.+template.+l26]](i[[SZ:32|64]]
- // Create local storage for each capture.
- // CHECK: [[LOCAL_A:%.+]] = alloca i[[SZ]],
- // CHECK-DAG: store i[[SZ]] [[ARG_A:%.+]], i[[SZ]]* [[LOCAL_A]]
- // Store captures in the context.
- // CHECK-64-DAG:[[REF_A:%.+]] = bitcast i[[SZ]]* [[LOCAL_A]] to i32*
- //
- // CHECK-DAG: [[TID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
- // CHECK-DAG: [[NTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
- // CHECK-DAG: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK-DAG: [[TH_LIMIT:%.+]] = sub i32 [[NTH]], [[WS]]
- // CHECK: [[IS_WORKER:%.+]] = icmp ult i32 [[TID]], [[TH_LIMIT]]
- // CHECK: br i1 [[IS_WORKER]], label {{%?}}[[WORKER:.+]], label {{%?}}[[CHECK_MASTER:.+]]
- //
- // CHECK: [[WORKER]]
- // CHECK: {{call|invoke}} void [[T6]]_worker()
- // CHECK: br label {{%?}}[[EXIT:.+]]
- //
- // CHECK: [[CHECK_MASTER]]
- // CHECK-DAG: [[CMTID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
- // CHECK-DAG: [[CMNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
- // CHECK-DAG: [[CMWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK: [[IS_MASTER:%.+]] = icmp eq i32 [[CMTID]],
- // CHECK: br i1 [[IS_MASTER]], label {{%?}}[[MASTER:.+]], label {{%?}}[[EXIT]]
- //
- // CHECK: [[MASTER]]
- // CHECK-DAG: [[MNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
- // CHECK-DAG: [[MWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK: [[MTMP1:%.+]] = sub i32 [[MNTH]], [[MWS]]
- // CHECK: call void @__kmpc_kernel_init(i32 [[MTMP1]]
- // CHECK: call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void (i16, i32, i8**)* [[PARALLEL_FN1]]_wrapper to i8*),
- // CHECK: call void @llvm.nvvm.barrier0()
- // CHECK: call void @llvm.nvvm.barrier0()
- // CHECK: call void @__kmpc_serialized_parallel(
- // CHECK: {{call|invoke}} void [[PARALLEL_FN3:@.+]](
- // CHECK: call void @__kmpc_end_serialized_parallel(
- // CHECK: call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void (i16, i32, i8**)* [[PARALLEL_FN2]]_wrapper to i8*),
- // CHECK: call void @llvm.nvvm.barrier0()
- // CHECK: call void @llvm.nvvm.barrier0()
- // CHECK-64-DAG: load i32, i32* [[REF_A]]
- // CHECK-32-DAG: load i32, i32* [[LOCAL_A]]
- // CHECK: br label {{%?}}[[TERMINATE:.+]]
- //
- // CHECK: [[TERMINATE]]
- // CHECK: call void @__kmpc_kernel_deinit(
- // CHECK: call void @llvm.nvvm.barrier0()
- // CHECK: br label {{%?}}[[EXIT]]
- //
- // CHECK: [[EXIT]]
- // CHECK: ret void
+// CHECK: define {{.*}}void [[T6:@__omp_offloading_.+template.+l26]](i[[SZ:32|64]]
+// Create local storage for each capture.
+// CHECK: [[LOCAL_A:%.+]] = alloca i[[SZ]],
+// CHECK-DAG: store i[[SZ]] [[ARG_A:%.+]], i[[SZ]]* [[LOCAL_A]]
+// Store captures in the context.
+// CHECK-64-DAG:[[REF_A:%.+]] = bitcast i[[SZ]]* [[LOCAL_A]] to i32*
+//
+// CHECK-DAG: [[TID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
+// CHECK-DAG: [[NTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
+// CHECK-DAG: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
+// CHECK-DAG: [[TH_LIMIT:%.+]] = sub nuw i32 [[NTH]], [[WS]]
+// CHECK: [[IS_WORKER:%.+]] = icmp ult i32 [[TID]], [[TH_LIMIT]]
+// CHECK: br i1 [[IS_WORKER]], label {{%?}}[[WORKER:.+]], label {{%?}}[[CHECK_MASTER:.+]]
+//
+// CHECK: [[WORKER]]
+// CHECK: {{call|invoke}} void [[T6]]_worker()
+// CHECK: br label {{%?}}[[EXIT:.+]]
+//
+// CHECK: [[CHECK_MASTER]]
+// CHECK-DAG: [[CMTID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
+// CHECK-DAG: [[CMNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
+// CHECK-DAG: [[CMWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
+// CHECK: [[IS_MASTER:%.+]] = icmp eq i32 [[CMTID]],
+// CHECK: br i1 [[IS_MASTER]], label {{%?}}[[MASTER:.+]], label {{%?}}[[EXIT]]
+//
+// CHECK: [[MASTER]]
+// CHECK-DAG: [[MNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
+// CHECK-DAG: [[MWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
+// CHECK: [[MTMP1:%.+]] = sub nuw i32 [[MNTH]], [[MWS]]
+// CHECK: call void @__kmpc_kernel_init(i32 [[MTMP1]]
+// CHECK: call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void (i16, i32)* [[PARALLEL_FN1]]_wrapper to i8*),
+// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: call void @__kmpc_serialized_parallel(
+// CHECK: {{call|invoke}} void [[PARALLEL_FN3:@.+]](
+// CHECK: call void @__kmpc_end_serialized_parallel(
+// CHECK: call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void (i16, i32)* [[PARALLEL_FN2]]_wrapper to i8*),
+// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK-64-DAG: load i32, i32* [[REF_A]]
+// CHECK-32-DAG: load i32, i32* [[LOCAL_A]]
+// CHECK: br label {{%?}}[[TERMINATE:.+]]
+//
+// CHECK: [[TERMINATE]]
+// CHECK: call void @__kmpc_kernel_deinit(
+// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: br label {{%?}}[[EXIT]]
+//
+// CHECK: [[EXIT]]
+// CHECK: ret void
- // CHECK-DAG: define internal void [[PARALLEL_FN1]](
- // CHECK: [[A:%.+]] = alloca i[[SZ:32|64]],
- // CHECK: store i[[SZ]] 42, i[[SZ]]* %a,
- // CHECK: ret void
+// CHECK-DAG: define internal void [[PARALLEL_FN1]](
+// CHECK: [[A:%.+]] = alloca i[[SZ:32|64]],
+// CHECK: store i[[SZ]] 42, i[[SZ]]* %a,
+// CHECK: ret void
- // CHECK-DAG: define internal void [[PARALLEL_FN3]](
- // CHECK: [[A:%.+]] = alloca i[[SZ:32|64]],
- // CHECK: store i[[SZ]] 43, i[[SZ]]* %a,
- // CHECK: ret void
+// CHECK-DAG: define internal void [[PARALLEL_FN3]](
+// CHECK: [[A:%.+]] = alloca i[[SZ:32|64]],
+// CHECK: store i[[SZ]] 43, i[[SZ]]* %a,
+// CHECK: ret void
- // CHECK-DAG: define internal void [[PARALLEL_FN2]](
- // CHECK: [[A:%.+]] = alloca i[[SZ:32|64]],
- // CHECK: store i[[SZ]] 44, i[[SZ]]* %a,
- // CHECK: ret void
+// CHECK-DAG: define internal void [[PARALLEL_FN2]](
+// CHECK: [[A:%.+]] = alloca i[[SZ:32|64]],
+// CHECK: store i[[SZ]] 44, i[[SZ]]* %a,
+// CHECK: ret void
+// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l43}}_worker()
+// CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8,
+// CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*,
+// CHECK: store i8* null, i8** [[OMP_WORK_FN]],
+// CHECK: store i8 0, i8* [[OMP_EXEC_STATUS]],
+// CHECK: br label {{%?}}[[AWAIT_WORK:.+]]
+//
+// CHECK: [[AWAIT_WORK]]
+// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: [[KPR:%.+]] = call i1 @__kmpc_kernel_parallel(i8** [[OMP_WORK_FN]],
+// CHECK: [[KPRB:%.+]] = zext i1 [[KPR]] to i8
+// store i8 [[KPRB]], i8* [[OMP_EXEC_STATUS]], align 1
+// CHECK: [[WORK:%.+]] = load i8*, i8** [[OMP_WORK_FN]],
+// CHECK: [[SHOULD_EXIT:%.+]] = icmp eq i8* [[WORK]], null
+// CHECK: br i1 [[SHOULD_EXIT]], label {{%?}}[[EXIT:.+]], label {{%?}}[[SEL_WORKERS:.+]]
+//
+// CHECK: [[SEL_WORKERS]]
+// CHECK: [[ST:%.+]] = load i8, i8* [[OMP_EXEC_STATUS]]
+// CHECK: [[IS_ACTIVE:%.+]] = icmp ne i8 [[ST]], 0
+// CHECK: br i1 [[IS_ACTIVE]], label {{%?}}[[EXEC_PARALLEL:.+]], label {{%?}}[[BAR_PARALLEL:.+]]
+//
+// CHECK: [[EXEC_PARALLEL]]
+// CHECK: [[WF:%.+]] = load i8*, i8** [[OMP_WORK_FN]],
+// CHECK: [[WM:%.+]] = icmp eq i8* [[WF]], bitcast (void (i16, i32)* [[PARALLEL_FN4:@.+]]_wrapper to i8*)
+// CHECK: br i1 [[WM]], label {{%?}}[[EXEC_PFN:.+]], label {{%?}}[[CHECK_NEXT:.+]]
+//
+// CHECK: [[EXEC_PFN]]
+// CHECK: call void [[PARALLEL_FN4]]_wrapper(
+// CHECK: br label {{%?}}[[TERM_PARALLEL:.+]]
+//
+// CHECK: [[CHECK_NEXT]]
+// CHECK: br label {{%?}}[[TERM_PARALLEL:.+]]
+//
+// CHECK: [[TERM_PARALLEL]]
+// CHECK: call void @__kmpc_kernel_end_parallel()
+// CHECK: br label {{%?}}[[BAR_PARALLEL]]
+//
+// CHECK: [[BAR_PARALLEL]]
+// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: br label {{%?}}[[AWAIT_WORK]]
+//
+// CHECK: [[EXIT]]
+// CHECK: ret void
+// CHECK: define {{.*}}void [[T6:@__omp_offloading_.+template.+l43]](i[[SZ:32|64]]
+// Create local storage for each capture.
+// CHECK: [[LOCAL_N:%.+]] = alloca i[[SZ]],
+// CHECK: [[LOCAL_A:%.+]] = alloca i[[SZ]],
+// CHECK: [[LOCAL_AA:%.+]] = alloca i[[SZ]],
+// CHECK: [[LOCAL_B:%.+]] = alloca [10 x i32]*
+// CHECK-DAG: store i[[SZ]] [[ARG_N:%.+]], i[[SZ]]* [[LOCAL_N]]
+// CHECK-DAG: store i[[SZ]] [[ARG_A:%.+]], i[[SZ]]* [[LOCAL_A]]
+// CHECK-DAG: store i[[SZ]] [[ARG_AA:%.+]], i[[SZ]]* [[LOCAL_AA]]
+// CHECK-DAG: store [10 x i32]* [[ARG_B:%.+]], [10 x i32]** [[LOCAL_B]]
+// Store captures in the context.
+// CHECK-64-DAG:[[REF_N:%.+]] = bitcast i[[SZ]]* [[LOCAL_N]] to i32*
+// CHECK-64-DAG:[[REF_A:%.+]] = bitcast i[[SZ]]* [[LOCAL_A]] to i32*
+// CHECK-DAG: [[REF_AA:%.+]] = bitcast i[[SZ]]* [[LOCAL_AA]] to i16*
+// CHECK-DAG: [[REF_B:%.+]] = load [10 x i32]*, [10 x i32]** [[LOCAL_B]],
+//
+// CHECK-DAG: [[TID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
+// CHECK-DAG: [[NTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
+// CHECK-DAG: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
+// CHECK-DAG: [[TH_LIMIT:%.+]] = sub nuw i32 [[NTH]], [[WS]]
+// CHECK: [[IS_WORKER:%.+]] = icmp ult i32 [[TID]], [[TH_LIMIT]]
+// CHECK: br i1 [[IS_WORKER]], label {{%?}}[[WORKER:.+]], label {{%?}}[[CHECK_MASTER:.+]]
+//
+// CHECK: [[WORKER]]
+// CHECK: {{call|invoke}} void [[T6]]_worker()
+// CHECK: br label {{%?}}[[EXIT:.+]]
+//
+// CHECK: [[CHECK_MASTER]]
+// CHECK-DAG: [[CMTID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
+// CHECK-DAG: [[CMNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
+// CHECK-DAG: [[CMWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
+// CHECK: [[IS_MASTER:%.+]] = icmp eq i32 [[CMTID]],
+// CHECK: br i1 [[IS_MASTER]], label {{%?}}[[MASTER:.+]], label {{%?}}[[EXIT]]
+//
+// CHECK: [[MASTER]]
+// CHECK-DAG: [[MNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
+// CHECK-DAG: [[MWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
+// CHECK: [[MTMP1:%.+]] = sub nuw i32 [[MNTH]], [[MWS]]
+// CHECK: call void @__kmpc_kernel_init(i32 [[MTMP1]]
+// CHECK-64: [[N:%.+]] = load i32, i32* [[REF_N]],
+// CHECK-32: [[N:%.+]] = load i32, i32* [[LOCAL_N]],
+// CHECK: [[CMP:%.+]] = icmp sgt i32 [[N]], 1000
+// CHECK: br i1 [[CMP]], label {{%?}}[[IF_THEN:.+]], label {{%?}}[[IF_ELSE:.+]]
+//
+// CHECK: [[IF_THEN]]
+// CHECK: call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void (i16, i32)* [[PARALLEL_FN4]]_wrapper to i8*),
+// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: br label {{%?}}[[IF_END:.+]]
+//
+// CHECK: [[IF_ELSE]]
+// CHECK: call void @__kmpc_serialized_parallel(
+// CHECK: {{call|invoke}} void [[PARALLEL_FN4]](
+// CHECK: call void @__kmpc_end_serialized_parallel(
+// br label [[IF_END]]
+//
+// CHECK: [[IF_END]]
+// CHECK-64-DAG: load i32, i32* [[REF_A]]
+// CHECK-32-DAG: load i32, i32* [[LOCAL_A]]
+// CHECK-DAG: load i16, i16* [[REF_AA]]
+// CHECK-DAG: getelementptr inbounds [10 x i32], [10 x i32]* [[REF_B]], i[[SZ]] 0, i[[SZ]] 2
+//
+// CHECK: br label {{%?}}[[TERMINATE:.+]]
+//
+// CHECK: [[TERMINATE]]
+// CHECK: call void @__kmpc_kernel_deinit(
+// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: br label {{%?}}[[EXIT]]
+//
+// CHECK: [[EXIT]]
+// CHECK: ret void
+// CHECK: define internal void [[PARALLEL_FN4]](
+// CHECK: [[A:%.+]] = alloca i[[SZ:32|64]],
+// CHECK: store i[[SZ]] 45, i[[SZ]]* %a,
+// CHECK: ret void
+// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l54}}_worker()
+// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l54}}(
+// CHECK-32: [[A_ADDR:%.+]] = alloca i32,
+// CHECK-64: [[A_ADDR:%.+]] = alloca i64,
+// CHECK-64: [[CONV:%.+]] = bitcast i64* [[A_ADDR]] to i32*
+// CHECK: [[STACK:%.+]] = call i8* @__kmpc_data_sharing_push_stack(i{{64|32}} 4, i16 0)
+// CHECK: [[BC:%.+]] = bitcast i8* [[STACK]] to %struct._globalized_locals_ty*
+// CHECK-32: [[A:%.+]] = load i32, i32* [[A_ADDR]],
+// CHECK-64: [[A:%.+]] = load i32, i32* [[CONV]],
+// CHECK: [[GLOBAL_A_ADDR:%.+]] = getelementptr inbounds %struct._globalized_locals_ty, %struct._globalized_locals_ty* [[BC]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
+// CHECK: store i32 [[A]], i32* [[GLOBAL_A_ADDR]],
+// CHECK-LABEL: define internal void @{{.+}}(i32* noalias %{{.+}}, i32* noalias %{{.+}}, i32* dereferenceable{{.*}})
+// CHECK: [[CC:%.+]] = alloca i32,
+// CHECK: [[TID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
+// CHECK: [[NUM_THREADS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
+// CHECK: store i32 0, i32* [[CC]],
+// CHECK: br label
+// CHECK: [[CC_VAL:%.+]] = load i32, i32* [[CC]],
+// CHECK: [[RES:%.+]] = icmp slt i32 [[CC_VAL]], [[NUM_THREADS]]
+// CHECK: br i1 [[RES]], label
- // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l43}}_worker()
- // CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8,
- // CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*,
- // CHECK: store i8* null, i8** [[OMP_WORK_FN]],
- // CHECK: store i8 0, i8* [[OMP_EXEC_STATUS]],
- // CHECK: br label {{%?}}[[AWAIT_WORK:.+]]
- //
- // CHECK: [[AWAIT_WORK]]
- // CHECK: call void @llvm.nvvm.barrier0()
- // CHECK: [[KPR:%.+]] = call i1 @__kmpc_kernel_parallel(i8** [[OMP_WORK_FN]],
- // CHECK: [[KPRB:%.+]] = zext i1 [[KPR]] to i8
- // store i8 [[KPRB]], i8* [[OMP_EXEC_STATUS]], align 1
- // CHECK: [[WORK:%.+]] = load i8*, i8** [[OMP_WORK_FN]],
- // CHECK: [[SHOULD_EXIT:%.+]] = icmp eq i8* [[WORK]], null
- // CHECK: br i1 [[SHOULD_EXIT]], label {{%?}}[[EXIT:.+]], label {{%?}}[[SEL_WORKERS:.+]]
- //
- // CHECK: [[SEL_WORKERS]]
- // CHECK: [[ST:%.+]] = load i8, i8* [[OMP_EXEC_STATUS]]
- // CHECK: [[IS_ACTIVE:%.+]] = icmp ne i8 [[ST]], 0
- // CHECK: br i1 [[IS_ACTIVE]], label {{%?}}[[EXEC_PARALLEL:.+]], label {{%?}}[[BAR_PARALLEL:.+]]
- //
- // CHECK: [[EXEC_PARALLEL]]
- // CHECK: [[WF:%.+]] = load i8*, i8** [[OMP_WORK_FN]],
- // CHECK: [[WM:%.+]] = icmp eq i8* [[WF]], bitcast (void (i16, i32, i8**)* [[PARALLEL_FN4:@.+]]_wrapper to i8*)
- // CHECK: br i1 [[WM]], label {{%?}}[[EXEC_PFN:.+]], label {{%?}}[[CHECK_NEXT:.+]]
- //
- // CHECK: [[EXEC_PFN]]
- // CHECK: call void [[PARALLEL_FN4]]_wrapper(
- // CHECK: br label {{%?}}[[TERM_PARALLEL:.+]]
- //
- // CHECK: [[CHECK_NEXT]]
- // CHECK: br label {{%?}}[[TERM_PARALLEL:.+]]
- //
- // CHECK: [[TERM_PARALLEL]]
- // CHECK: call void @__kmpc_kernel_end_parallel()
- // CHECK: br label {{%?}}[[BAR_PARALLEL]]
- //
- // CHECK: [[BAR_PARALLEL]]
- // CHECK: call void @llvm.nvvm.barrier0()
- // CHECK: br label {{%?}}[[AWAIT_WORK]]
- //
- // CHECK: [[EXIT]]
- // CHECK: ret void
+// CHECK: [[CC_VAL:%.+]] = load i32, i32* [[CC]],
+// CHECK: [[RES:%.+]] = icmp eq i32 [[TID]], [[CC_VAL]]
+// CHECK: br i1 [[RES]], label
- // CHECK: define {{.*}}void [[T6:@__omp_offloading_.+template.+l43]](i[[SZ:32|64]]
- // Create local storage for each capture.
- // CHECK: [[LOCAL_N:%.+]] = alloca i[[SZ]],
- // CHECK: [[LOCAL_A:%.+]] = alloca i[[SZ]],
- // CHECK: [[LOCAL_AA:%.+]] = alloca i[[SZ]],
- // CHECK: [[LOCAL_B:%.+]] = alloca [10 x i32]*
- // CHECK-DAG: store i[[SZ]] [[ARG_N:%.+]], i[[SZ]]* [[LOCAL_N]]
- // CHECK-DAG: store i[[SZ]] [[ARG_A:%.+]], i[[SZ]]* [[LOCAL_A]]
- // CHECK-DAG: store i[[SZ]] [[ARG_AA:%.+]], i[[SZ]]* [[LOCAL_AA]]
- // CHECK-DAG: store [10 x i32]* [[ARG_B:%.+]], [10 x i32]** [[LOCAL_B]]
- // Store captures in the context.
- // CHECK-64-DAG:[[REF_N:%.+]] = bitcast i[[SZ]]* [[LOCAL_N]] to i32*
- // CHECK-64-DAG:[[REF_A:%.+]] = bitcast i[[SZ]]* [[LOCAL_A]] to i32*
- // CHECK-DAG: [[REF_AA:%.+]] = bitcast i[[SZ]]* [[LOCAL_AA]] to i16*
- // CHECK-DAG: [[REF_B:%.+]] = load [10 x i32]*, [10 x i32]** [[LOCAL_B]],
- //
- // CHECK-DAG: [[TID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
- // CHECK-DAG: [[NTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
- // CHECK-DAG: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK-DAG: [[TH_LIMIT:%.+]] = sub i32 [[NTH]], [[WS]]
- // CHECK: [[IS_WORKER:%.+]] = icmp ult i32 [[TID]], [[TH_LIMIT]]
- // CHECK: br i1 [[IS_WORKER]], label {{%?}}[[WORKER:.+]], label {{%?}}[[CHECK_MASTER:.+]]
- //
- // CHECK: [[WORKER]]
- // CHECK: {{call|invoke}} void [[T6]]_worker()
- // CHECK: br label {{%?}}[[EXIT:.+]]
- //
- // CHECK: [[CHECK_MASTER]]
- // CHECK-DAG: [[CMTID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
- // CHECK-DAG: [[CMNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
- // CHECK-DAG: [[CMWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK: [[IS_MASTER:%.+]] = icmp eq i32 [[CMTID]],
- // CHECK: br i1 [[IS_MASTER]], label {{%?}}[[MASTER:.+]], label {{%?}}[[EXIT]]
- //
- // CHECK: [[MASTER]]
- // CHECK-DAG: [[MNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
- // CHECK-DAG: [[MWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK: [[MTMP1:%.+]] = sub i32 [[MNTH]], [[MWS]]
- // CHECK: call void @__kmpc_kernel_init(i32 [[MTMP1]]
- // CHECK-64: [[N:%.+]] = load i32, i32* [[REF_N]],
- // CHECK-32: [[N:%.+]] = load i32, i32* [[LOCAL_N]],
- // CHECK: [[CMP:%.+]] = icmp sgt i32 [[N]], 1000
- // CHECK: br i1 [[CMP]], label {{%?}}[[IF_THEN:.+]], label {{%?}}[[IF_ELSE:.+]]
- //
- // CHECK: [[IF_THEN]]
- // CHECK: call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void (i16, i32, i8**)* [[PARALLEL_FN4]]_wrapper to i8*),
- // CHECK: call void @llvm.nvvm.barrier0()
- // CHECK: call void @llvm.nvvm.barrier0()
- // CHECK: br label {{%?}}[[IF_END:.+]]
- //
- // CHECK: [[IF_ELSE]]
- // CHECK: call void @__kmpc_serialized_parallel(
- // CHECK: {{call|invoke}} void [[PARALLEL_FN4]](
- // CHECK: call void @__kmpc_end_serialized_parallel(
- // br label [[IF_END]]
- //
- // CHECK: [[IF_END]]
- // CHECK-64-DAG: load i32, i32* [[REF_A]]
- // CHECK-32-DAG: load i32, i32* [[LOCAL_A]]
- // CHECK-DAG: load i16, i16* [[REF_AA]]
- // CHECK-DAG: getelementptr inbounds [10 x i32], [10 x i32]* [[REF_B]], i[[SZ]] 0, i[[SZ]] 2
- //
- // CHECK: br label {{%?}}[[TERMINATE:.+]]
- //
- // CHECK: [[TERMINATE]]
- // CHECK: call void @__kmpc_kernel_deinit(
- // CHECK: call void @llvm.nvvm.barrier0()
- // CHECK: br label {{%?}}[[EXIT]]
- //
- // CHECK: [[EXIT]]
- // CHECK: ret void
+// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: [[NEW_CC_VAL:%.+]] = add nsw i32 [[CC_VAL]], 1
+// CHECK: store i32 [[NEW_CC_VAL]], i32* [[CC]],
+// CHECK: br label
- // CHECK: define internal void [[PARALLEL_FN4]](
- // CHECK: [[A:%.+]] = alloca i[[SZ:32|64]],
- // CHECK: store i[[SZ]] 45, i[[SZ]]* %a,
- // CHECK: ret void
#endif
diff --git a/test/OpenMP/nvptx_target_codegen.cpp b/test/OpenMP/nvptx_target_codegen.cpp
index 23b40e10c4c8..5f9b3bd32808 100644
--- a/test/OpenMP/nvptx_target_codegen.cpp
+++ b/test/OpenMP/nvptx_target_codegen.cpp
@@ -9,19 +9,22 @@
#define HEADER
// Check that the execution mode of all 6 target regions is set to Generic Mode.
-// CHECK-DAG: {{@__omp_offloading_.+l100}}_exec_mode = weak constant i8 1
-// CHECK-DAG: {{@__omp_offloading_.+l177}}_exec_mode = weak constant i8 1
-// CHECK-DAG: {{@__omp_offloading_.+l287}}_exec_mode = weak constant i8 1
-// CHECK-DAG: {{@__omp_offloading_.+l324}}_exec_mode = weak constant i8 1
-// CHECK-DAG: {{@__omp_offloading_.+l342}}_exec_mode = weak constant i8 1
-// CHECK-DAG: {{@__omp_offloading_.+l307}}_exec_mode = weak constant i8 1
+// CHECK-DAG: {{@__omp_offloading_.+l103}}_exec_mode = weak constant i8 1
+// CHECK-DAG: {{@__omp_offloading_.+l180}}_exec_mode = weak constant i8 1
+// CHECK-DAG: {{@__omp_offloading_.+l290}}_exec_mode = weak constant i8 1
+// CHECK-DAG: {{@__omp_offloading_.+l328}}_exec_mode = weak constant i8 1
+// CHECK-DAG: {{@__omp_offloading_.+l346}}_exec_mode = weak constant i8 1
+// CHECK-DAG: {{@__omp_offloading_.+l311}}_exec_mode = weak constant i8 1
__thread int id;
+int baz(int f, double &a);
+
template<typename tx, typename ty>
struct TT{
tx X;
ty Y;
+ tx &operator[](int i) { return X; }
};
int foo(int n) {
@@ -33,7 +36,7 @@ int foo(int n) {
double cn[5][n];
TT<long long, char> d;
- // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+foo.+l100}}_worker()
+ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+foo.+l103}}_worker()
// CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8,
// CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*,
// CHECK: store i8* null, i8** [[OMP_WORK_FN]],
@@ -64,11 +67,11 @@ int foo(int n) {
// CHECK: [[EXIT]]
// CHECK: ret void
- // CHECK: define {{.*}}void [[T1:@__omp_offloading_.+foo.+l100]]()
+ // CHECK: define {{.*}}void [[T1:@__omp_offloading_.+foo.+l103]]()
// CHECK-DAG: [[TID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
// CHECK-DAG: [[NTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
// CHECK-DAG: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK-DAG: [[TH_LIMIT:%.+]] = sub i32 [[NTH]], [[WS]]
+ // CHECK-DAG: [[TH_LIMIT:%.+]] = sub nuw i32 [[NTH]], [[WS]]
// CHECK: [[IS_WORKER:%.+]] = icmp ult i32 [[TID]], [[TH_LIMIT]]
// CHECK: br i1 [[IS_WORKER]], label {{%?}}[[WORKER:.+]], label {{%?}}[[CHECK_MASTER:.+]]
//
@@ -86,7 +89,7 @@ int foo(int n) {
// CHECK: [[MASTER]]
// CHECK-DAG: [[MNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
// CHECK-DAG: [[MWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK: [[MTMP1:%.+]] = sub i32 [[MNTH]], [[MWS]]
+ // CHECK: [[MTMP1:%.+]] = sub nuw i32 [[MNTH]], [[MWS]]
// CHECK: call void @__kmpc_kernel_init(i32 [[MTMP1]]
// CHECK: br label {{%?}}[[TERMINATE:.+]]
//
@@ -106,7 +109,7 @@ int foo(int n) {
{
}
- // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+foo.+l177}}_worker()
+ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+foo.+l180}}_worker()
// CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8,
// CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*,
// CHECK: store i8* null, i8** [[OMP_WORK_FN]],
@@ -137,14 +140,14 @@ int foo(int n) {
// CHECK: [[EXIT]]
// CHECK: ret void
- // CHECK: define {{.*}}void [[T2:@__omp_offloading_.+foo.+l177]](i[[SZ:32|64]] [[ARG1:%[a-zA-Z_]+]], i[[SZ:32|64]] [[ID:%[a-zA-Z_]+]])
+ // CHECK: define {{.*}}void [[T2:@__omp_offloading_.+foo.+l180]](i[[SZ:32|64]] [[ARG1:%[a-zA-Z_]+]], i[[SZ:32|64]] [[ID:%[a-zA-Z_]+]])
// CHECK: [[AA_ADDR:%.+]] = alloca i[[SZ]],
// CHECK: store i[[SZ]] [[ARG1]], i[[SZ]]* [[AA_ADDR]],
// CHECK: [[AA_CADDR:%.+]] = bitcast i[[SZ]]* [[AA_ADDR]] to i16*
// CHECK-DAG: [[TID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
// CHECK-DAG: [[NTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
// CHECK-DAG: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK-DAG: [[TH_LIMIT:%.+]] = sub i32 [[NTH]], [[WS]]
+ // CHECK-DAG: [[TH_LIMIT:%.+]] = sub nuw i32 [[NTH]], [[WS]]
// CHECK: [[IS_WORKER:%.+]] = icmp ult i32 [[TID]], [[TH_LIMIT]]
// CHECK: br i1 [[IS_WORKER]], label {{%?}}[[WORKER:.+]], label {{%?}}[[CHECK_MASTER:.+]]
//
@@ -162,7 +165,7 @@ int foo(int n) {
// CHECK: [[MASTER]]
// CHECK-DAG: [[MNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
// CHECK-DAG: [[MWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK: [[MTMP1:%.+]] = sub i32 [[MNTH]], [[MWS]]
+ // CHECK: [[MTMP1:%.+]] = sub nuw i32 [[MNTH]], [[MWS]]
// CHECK: call void @__kmpc_kernel_init(i32 [[MTMP1]]
// CHECK: load i16, i16* [[AA_CADDR]],
// CHECK: br label {{%?}}[[TERMINATE:.+]]
@@ -180,7 +183,7 @@ int foo(int n) {
id = aa;
}
- // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+foo.+l287}}_worker()
+ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+foo.+l290}}_worker()
// CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8,
// CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*,
// CHECK: store i8* null, i8** [[OMP_WORK_FN]],
@@ -211,7 +214,7 @@ int foo(int n) {
// CHECK: [[EXIT]]
// CHECK: ret void
- // CHECK: define {{.*}}void [[T3:@__omp_offloading_.+foo.+l287]](i[[SZ]]
+ // CHECK: define {{.*}}void [[T3:@__omp_offloading_.+foo.+l290]](i[[SZ]]
// Create local storage for each capture.
// CHECK: [[LOCAL_A:%.+]] = alloca i[[SZ]]
// CHECK: [[LOCAL_B:%.+]] = alloca [10 x float]*
@@ -245,7 +248,7 @@ int foo(int n) {
// CHECK-DAG: [[TID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
// CHECK-DAG: [[NTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
// CHECK-DAG: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK-DAG: [[TH_LIMIT:%.+]] = sub i32 [[NTH]], [[WS]]
+ // CHECK-DAG: [[TH_LIMIT:%.+]] = sub nuw i32 [[NTH]], [[WS]]
// CHECK: [[IS_WORKER:%.+]] = icmp ult i32 [[TID]], [[TH_LIMIT]]
// CHECK: br i1 [[IS_WORKER]], label {{%?}}[[WORKER:.+]], label {{%?}}[[CHECK_MASTER:.+]]
//
@@ -263,7 +266,7 @@ int foo(int n) {
// CHECK: [[MASTER]]
// CHECK-DAG: [[MNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
// CHECK-DAG: [[MWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK: [[MTMP1:%.+]] = sub i32 [[MNTH]], [[MWS]]
+ // CHECK: [[MTMP1:%.+]] = sub nuw i32 [[MNTH]], [[MWS]]
// CHECK: call void @__kmpc_kernel_init(i32 [[MTMP1]]
//
// Use captures.
@@ -293,6 +296,7 @@ int foo(int n) {
cn[1][3] += 1.0;
d.X += 1;
d.Y += 1;
+ d[0] += 1;
}
return a;
@@ -343,6 +347,7 @@ struct S1 {
{
this->a = (double)b + 1.5;
c[1][1] = ++a;
+ baz(a, a);
}
return c[1][1] + (int)b;
@@ -364,7 +369,13 @@ int bar(int n){
return a;
}
- // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+static.+324}}_worker()
+int baz(int f, double &a) {
+#pragma omp parallel
+ f = 2 + a;
+ return f;
+}
+
+ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+static.+328}}_worker()
// CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8,
// CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*,
// CHECK: store i8* null, i8** [[OMP_WORK_FN]],
@@ -395,7 +406,7 @@ int bar(int n){
// CHECK: [[EXIT]]
// CHECK: ret void
- // CHECK: define {{.*}}void [[T4:@__omp_offloading_.+static.+l324]](i[[SZ]]
+ // CHECK: define {{.*}}void [[T4:@__omp_offloading_.+static.+l328]](i[[SZ]]
// Create local storage for each capture.
// CHECK: [[LOCAL_A:%.+]] = alloca i[[SZ]]
// CHECK: [[LOCAL_AA:%.+]] = alloca i[[SZ]]
@@ -414,7 +425,7 @@ int bar(int n){
// CHECK-DAG: [[TID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
// CHECK-DAG: [[NTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
// CHECK-DAG: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK-DAG: [[TH_LIMIT:%.+]] = sub i32 [[NTH]], [[WS]]
+ // CHECK-DAG: [[TH_LIMIT:%.+]] = sub nuw i32 [[NTH]], [[WS]]
// CHECK: [[IS_WORKER:%.+]] = icmp ult i32 [[TID]], [[TH_LIMIT]]
// CHECK: br i1 [[IS_WORKER]], label {{%?}}[[WORKER:.+]], label {{%?}}[[CHECK_MASTER:.+]]
//
@@ -432,7 +443,7 @@ int bar(int n){
// CHECK: [[MASTER]]
// CHECK-DAG: [[MNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
// CHECK-DAG: [[MWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK: [[MTMP1:%.+]] = sub i32 [[MNTH]], [[MWS]]
+ // CHECK: [[MTMP1:%.+]] = sub nuw i32 [[MNTH]], [[MWS]]
// CHECK: call void @__kmpc_kernel_init(i32 [[MTMP1]]
// CHECK-64-DAG: load i32, i32* [[REF_A]]
// CHECK-32-DAG: load i32, i32* [[LOCAL_A]]
@@ -450,9 +461,10 @@ int bar(int n){
- // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+S1.+l342}}_worker()
+ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+S1.+l346}}_worker()
// CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8,
// CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*,
+ // CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num(%struct.ident_t*
// CHECK: store i8* null, i8** [[OMP_WORK_FN]],
// CHECK: store i8 0, i8* [[OMP_EXEC_STATUS]],
// CHECK: br label {{%?}}[[AWAIT_WORK:.+]]
@@ -469,6 +481,8 @@ int bar(int n){
// CHECK: br i1 [[IS_ACTIVE]], label {{%?}}[[EXEC_PARALLEL:.+]], label {{%?}}[[BAR_PARALLEL:.+]]
//
// CHECK: [[EXEC_PARALLEL]]
+ // CHECK: [[WORK_FN:%.+]] = bitcast i8* [[WORK]] to void (i16, i32)*
+ // CHECK: call void [[WORK_FN]](i16 0, i32 [[GTID]])
// CHECK: br label {{%?}}[[TERM_PARALLEL:.+]]
//
// CHECK: [[TERM_PARALLEL]]
@@ -481,7 +495,7 @@ int bar(int n){
// CHECK: [[EXIT]]
// CHECK: ret void
- // CHECK: define {{.*}}void [[T5:@__omp_offloading_.+S1.+l342]](
+ // CHECK: define {{.*}}void [[T5:@__omp_offloading_.+S1.+l346]](
// Create local storage for each capture.
// CHECK: [[LOCAL_THIS:%.+]] = alloca [[S1:%struct.*]]*
// CHECK: [[LOCAL_B:%.+]] = alloca i[[SZ]]
@@ -503,7 +517,7 @@ int bar(int n){
// CHECK-DAG: [[TID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
// CHECK-DAG: [[NTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
// CHECK-DAG: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK-DAG: [[TH_LIMIT:%.+]] = sub i32 [[NTH]], [[WS]]
+ // CHECK-DAG: [[TH_LIMIT:%.+]] = sub nuw i32 [[NTH]], [[WS]]
// CHECK: [[IS_WORKER:%.+]] = icmp ult i32 [[TID]], [[TH_LIMIT]]
// CHECK: br i1 [[IS_WORKER]], label {{%?}}[[WORKER:.+]], label {{%?}}[[CHECK_MASTER:.+]]
//
@@ -521,13 +535,14 @@ int bar(int n){
// CHECK: [[MASTER]]
// CHECK-DAG: [[MNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
// CHECK-DAG: [[MWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK: [[MTMP1:%.+]] = sub i32 [[MNTH]], [[MWS]]
+ // CHECK: [[MTMP1:%.+]] = sub nuw i32 [[MNTH]], [[MWS]]
// CHECK: call void @__kmpc_kernel_init(i32 [[MTMP1]]
// Use captures.
// CHECK-DAG: getelementptr inbounds [[S1]], [[S1]]* [[REF_THIS]], i32 0, i32 0
// CHECK-64-DAG:load i32, i32* [[REF_B]]
// CHECK-32-DAG:load i32, i32* [[LOCAL_B]]
// CHECK-DAG: getelementptr inbounds i16, i16* [[REF_C]], i[[SZ]] %{{.+}}
+ // CHECK: call i32 [[BAZ:@.*baz.*]](i32 %
// CHECK: br label {{%?}}[[TERMINATE:.+]]
//
// CHECK: [[TERMINATE]]
@@ -538,9 +553,53 @@ int bar(int n){
// CHECK: [[EXIT]]
// CHECK: ret void
+ // CHECK: define i32 [[BAZ]](i32 [[F:%.*]], double* dereferenceable{{.*}})
+ // CHECK: [[ZERO_ADDR:%.+]] = alloca i32,
+ // CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num(%struct.ident_t*
+ // CHECK: [[GTID_ADDR:%.+]] = alloca i32,
+ // CHECK: store i32 0, i32* [[ZERO_ADDR]]
+ // CHECK: [[PTR:%.+]] = call i8* @__kmpc_data_sharing_push_stack(i{{64|32}} 4, i16 0)
+ // CHECK: [[REC_ADDR:%.+]] = bitcast i8* [[PTR]] to %struct._globalized_locals_ty*
+ // CHECK: [[F_PTR:%.+]] = getelementptr inbounds %struct._globalized_locals_ty, %struct._globalized_locals_ty* [[REC_ADDR]], i32 0, i32 0
+ // CHECK: store i32 %{{.+}}, i32* [[F_PTR]],
+
+ // CHECK: [[RES:%.+]] = call i8 @__kmpc_is_spmd_exec_mode()
+ // CHECK: icmp ne i8 [[RES]], 0
+ // CHECK: br i1
+
+ // CHECK: [[RES:%.+]] = call i16 @__kmpc_parallel_level(%struct.ident_t* @{{.+}}, i32 [[GTID]])
+ // CHECK: icmp ne i16 [[RES]], 0
+ // CHECK: br i1
+
+ // CHECK: call void @__kmpc_serialized_parallel(%struct.ident_t* @{{.+}}, i32 [[GTID]])
+ // CHECK: call void [[OUTLINED:@.+]](i32* [[ZERO_ADDR]], i32* [[ZERO_ADDR]], i32* [[F_PTR]], double* %{{.+}})
+ // CHECK: call void @__kmpc_end_serialized_parallel(%struct.ident_t* @{{.+}}, i32 [[GTID]])
+ // CHECK: br label
+
+ // CHECK: icmp eq i32
+ // CHECK: br i1
+
+ // CHECK: call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void (i16, i32)* @{{.+}} to i8*), i16 1)
+ // CHECK: call void @__kmpc_begin_sharing_variables(i8*** [[SHARED_PTR:%.+]], i{{64|32}} 2)
+ // CHECK: [[SHARED:%.+]] = load i8**, i8*** [[SHARED_PTR]],
+ // CHECK: [[REF:%.+]] = getelementptr inbounds i8*, i8** [[SHARED]], i{{64|32}} 0
+ // CHECK: [[F_REF:%.+]] = bitcast i32* [[F_PTR]] to i8*
+ // CHECK: store i8* [[F_REF]], i8** [[REF]],
+ // CHECK: call void @llvm.nvvm.barrier0()
+ // CHECK: call void @llvm.nvvm.barrier0()
+ // CHECK: call void @__kmpc_end_sharing_variables()
+ // CHECK: br label
+
+ // CHECK: store i32 [[GTID]], i32* [[GTID_ADDR]],
+ // CHECK: call void [[OUTLINED]](i32* [[GTID_ADDR]], i32* [[ZERO_ADDR]], i32* [[F_PTR]], double* %{{.+}})
+ // CHECK: br label
+
+ // CHECK: [[RES:%.+]] = load i32, i32* [[F_PTR]],
+ // CHECK: call void @__kmpc_data_sharing_pop_stack(i8* [[PTR]])
+ // CHECK: ret i32 [[RES]]
- // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l307}}_worker()
+ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l311}}_worker()
// CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8,
// CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*,
// CHECK: store i8* null, i8** [[OMP_WORK_FN]],
@@ -571,7 +630,7 @@ int bar(int n){
// CHECK: [[EXIT]]
// CHECK: ret void
- // CHECK: define {{.*}}void [[T6:@__omp_offloading_.+template.+l307]](i[[SZ]]
+ // CHECK: define {{.*}}void [[T6:@__omp_offloading_.+template.+l311]](i[[SZ]]
// Create local storage for each capture.
// CHECK: [[LOCAL_A:%.+]] = alloca i[[SZ]]
// CHECK: [[LOCAL_AA:%.+]] = alloca i[[SZ]]
@@ -587,7 +646,7 @@ int bar(int n){
// CHECK-DAG: [[TID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
// CHECK-DAG: [[NTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
// CHECK-DAG: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK-DAG: [[TH_LIMIT:%.+]] = sub i32 [[NTH]], [[WS]]
+ // CHECK-DAG: [[TH_LIMIT:%.+]] = sub nuw i32 [[NTH]], [[WS]]
// CHECK: [[IS_WORKER:%.+]] = icmp ult i32 [[TID]], [[TH_LIMIT]]
// CHECK: br i1 [[IS_WORKER]], label {{%?}}[[WORKER:.+]], label {{%?}}[[CHECK_MASTER:.+]]
//
@@ -605,7 +664,7 @@ int bar(int n){
// CHECK: [[MASTER]]
// CHECK-DAG: [[MNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
// CHECK-DAG: [[MWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK: [[MTMP1:%.+]] = sub i32 [[MNTH]], [[MWS]]
+ // CHECK: [[MTMP1:%.+]] = sub nuw i32 [[MNTH]], [[MWS]]
// CHECK: call void @__kmpc_kernel_init(i32 [[MTMP1]]
//
// CHECK-64-DAG: load i32, i32* [[REF_A]]
diff --git a/test/OpenMP/nvptx_target_cuda_mode_messages.cpp b/test/OpenMP/nvptx_target_cuda_mode_messages.cpp
new file mode 100644
index 000000000000..eecc26c6181a
--- /dev/null
+++ b/test/OpenMP/nvptx_target_cuda_mode_messages.cpp
@@ -0,0 +1,108 @@
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-cuda-mode -fopenmp-host-ir-file-path %t-ppc-host.bc -o -
+
+template <typename tx, typename ty>
+struct TT {
+ tx X;
+ ty Y;
+};
+
+int foo(int n, double *ptr) {
+ int a = 0;
+ short aa = 0;
+ float b[10];
+ double c[5][10];
+ TT<long long, char> d;
+
+#pragma omp target firstprivate(a) map(tofrom: b) // expected-note 2 {{defined as threadprivate or thread local}}
+ {
+ int c; // expected-note {{defined as threadprivate or thread local}}
+#pragma omp parallel shared(a, b, c, aa) // expected-error 3 {{threadprivate or thread local variable cannot be shared}}
+ b[a] = a;
+#pragma omp parallel for
+ for (int i = 0; i < 10; ++i) // expected-note {{defined as threadprivate or thread local}}
+#pragma omp parallel shared(i) // expected-error {{threadprivate or thread local variable cannot be shared}}
+ ++i;
+ }
+
+#pragma omp target map(aa, b, c, d)
+ {
+ int e; // expected-note {{defined as threadprivate or thread local}}
+#pragma omp parallel private(b, e) // expected-error {{threadprivate or thread local variable cannot be private}}
+ {
+ aa += 1;
+ b[2] = 1.0;
+ c[1][2] = 1.0;
+ d.X = 1;
+ d.Y = 1;
+ }
+ }
+
+#pragma omp target private(ptr)
+ {
+ ptr[0]++;
+ }
+
+ return a;
+}
+
+template <typename tx>
+tx ftemplate(int n) {
+ tx a = 0;
+ tx b[10];
+
+#pragma omp target reduction(+ \
+ : a, b) // expected-note {{defined as threadprivate or thread local}}
+ {
+ int e; // expected-note {{defined as threadprivate or thread local}}
+#pragma omp parallel shared(a, e) // expected-error 2 {{threadprivate or thread local variable cannot be shared}}
+ a += 1;
+ b[2] += 1;
+ }
+
+ return a;
+}
+
+static int fstatic(int n) {
+ int a = 0;
+ char aaa = 0;
+ int b[10];
+
+#pragma omp target firstprivate(a, aaa, b)
+ {
+ a += 1;
+ aaa += 1;
+ b[2] += 1;
+ }
+
+ return a;
+}
+
+struct S1 {
+ double a;
+
+ int r1(int n) {
+ int b = n + 1;
+
+#pragma omp target firstprivate(b) // expected-note {{defined as threadprivate or thread local}}
+ {
+ int c; // expected-note {{defined as threadprivate or thread local}}
+#pragma omp parallel shared(b, c) // expected-error 2 {{threadprivate or thread local variable cannot be shared}}
+ this->a = (double)b + 1.5;
+ }
+
+ return (int)b;
+ }
+};
+
+int bar(int n, double *ptr) {
+ int a = 0;
+ a += foo(n, ptr);
+ S1 S;
+ a += S.r1(n);
+ a += fstatic(n);
+ a += ftemplate<int>(n); // expected-note {{in instantiation of function template specialization 'ftemplate<int>' requested here}}
+
+ return a;
+}
+
diff --git a/test/OpenMP/nvptx_target_exceptions_messages.cpp b/test/OpenMP/nvptx_target_exceptions_messages.cpp
new file mode 100644
index 000000000000..15c9522540fc
--- /dev/null
+++ b/test/OpenMP/nvptx_target_exceptions_messages.cpp
@@ -0,0 +1,71 @@
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc -fexceptions -fcxx-exceptions
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - -fexceptions -fcxx-exceptions -ferror-limit 100
+
+#ifndef HEADER
+#define HEADER
+
+template <typename T>
+class TemplateClass {
+ T a;
+public:
+ TemplateClass() { throw 1;}
+ T f_method() const { return a; }
+};
+
+int foo();
+
+int baz1();
+
+int baz2();
+
+int baz4() { return 5; }
+
+template <typename T>
+T FA() {
+ TemplateClass<T> s;
+ return s.f_method();
+}
+
+#pragma omp declare target
+struct S {
+ int a;
+ S(int a) : a(a) { throw 1; } // expected-error {{cannot use 'throw' with exceptions disabled}}
+};
+
+int foo() { return 0; }
+int b = 15;
+int d;
+#pragma omp end declare target
+int c;
+
+int bar() { return 1 + foo() + bar() + baz1() + baz2(); }
+
+int maini1() {
+ int a;
+ static long aa = 32;
+ try {
+#pragma omp target map(tofrom \
+ : a, b)
+ {
+ S s(a);
+ static long aaa = 23;
+ a = foo() + bar() + b + c + d + aa + aaa + FA<int>();
+ if (!a)
+ throw "Error"; // expected-error {{cannot use 'throw' with exceptions disabled}}
+ }
+ } catch(...) {
+ }
+ return baz4();
+}
+
+int baz3() { return 2 + baz2(); }
+int baz2() {
+#pragma omp target
+ try { // expected-error {{cannot use 'try' with exceptions disabled}}
+ ++c;
+ } catch (...) {
+ }
+ return 2 + baz3();
+}
+
+#endif // HEADER
diff --git a/test/OpenMP/nvptx_target_firstprivate_codegen.cpp b/test/OpenMP/nvptx_target_firstprivate_codegen.cpp
index f750be03e052..53b0f758852c 100644
--- a/test/OpenMP/nvptx_target_firstprivate_codegen.cpp
+++ b/test/OpenMP/nvptx_target_firstprivate_codegen.cpp
@@ -72,17 +72,17 @@ int foo(int n, double *ptr) {
// firstprivate(b): memcpy(b_priv,b_in)
// TCHECK: [[B_PRIV_BCAST:%.+]] = bitcast [10 x float]* [[B_PRIV]] to i8*
// TCHECK: [[B_ADDR_REF_BCAST:%.+]] = bitcast [10 x float]* [[B_ADDR_REF]] to i8*
- // TCHECK: call void @llvm.memcpy.{{.+}}(i8* [[B_PRIV_BCAST]], i8* [[B_ADDR_REF_BCAST]], {{.+}})
+ // TCHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[B_PRIV_BCAST]], i8* align {{[0-9]+}} [[B_ADDR_REF_BCAST]], {{.+}})
// firstprivate(c)
// TCHECK: [[C_PRIV_BCAST:%.+]] = bitcast [5 x [10 x double]]* [[C_PRIV]] to i8*
// TCHECK: [[C_IN_BCAST:%.+]] = bitcast [5 x [10 x double]]* [[C_ADDR_REF]] to i8*
- // TCHECK: call void @llvm.memcpy.{{.+}}(i8* [[C_PRIV_BCAST]], i8* [[C_IN_BCAST]],{{.+}})
+ // TCHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[C_PRIV_BCAST]], i8* align {{[0-9]+}} [[C_IN_BCAST]],{{.+}})
// firstprivate(d)
// TCHECK: [[D_PRIV_BCAST:%.+]] = bitcast [[TT]]* [[D_PRIV]] to i8*
// TCHECK: [[D_IN_BCAST:%.+]] = bitcast [[TT]]* [[D_ADDR_REF]] to i8*
- // TCHECK: call void @llvm.memcpy.{{.+}}(i8* [[D_PRIV_BCAST]], i8* [[D_IN_BCAST]],{{.+}})
+ // TCHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[D_PRIV_BCAST]], i8* align {{[0-9]+}} [[D_IN_BCAST]],{{.+}})
// TCHECK: load i16, i16* [[A2_ADDR]],
@@ -91,7 +91,7 @@ int foo(int n, double *ptr) {
ptr[0]++;
}
- // TCHECK: define void @__omp_offloading_{{.+}}(double* [[PTR_IN:%.+]])
+ // TCHECK: define weak void @__omp_offloading_{{.+}}(double* [[PTR_IN:%.+]])
// TCHECK: [[PTR_ADDR:%.+]] = alloca double*,
// TCHECK-NOT: alloca double*,
// TCHECK: store double* [[PTR_IN]], double** [[PTR_ADDR]],
@@ -151,7 +151,7 @@ static int fstatic(int n) {
// firstprivate(b)
// TCHECK: [[B_PRIV_BCAST:%.+]] = bitcast [10 x i{{[0-9]+}}]* [[B_PRIV]] to i8*
// TCHECK: [[B_IN_BCAST:%.+]] = bitcast [10 x i{{[0-9]+}}]* [[B_ADDR_REF]] to i8*
-// TCHECK: call void @llvm.memcpy.{{.+}}(i8* [[B_PRIV_BCAST]], i8* [[B_IN_BCAST]],{{.+}})
+// TCHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[B_PRIV_BCAST]], i8* align {{[0-9]+}} [[B_IN_BCAST]],{{.+}})
// TCHECK: ret void
@@ -214,8 +214,14 @@ int bar(int n, double *ptr) {
// firstprivate(b)
// TCHECK: [[B_PRIV_BCAST:%.+]] = bitcast [10 x i{{[0-9]+}}]* [[B_PRIV]] to i8*
// TCHECK: [[B_IN_BCAST:%.+]] = bitcast [10 x i{{[0-9]+}}]* [[B_ADDR_REF]] to i8*
-// TCHECK: call void @llvm.memcpy.{{.+}}(i8* [[B_PRIV_BCAST]], i8* [[B_IN_BCAST]],{{.+}})
+// TCHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[B_PRIV_BCAST]], i8* align {{[0-9]+}} [[B_IN_BCAST]],{{.+}})
// TCHECK: ret void
#endif
+
+// TCHECK-DAG: distinct !DISubprogram(linkageName: "__omp_offloading_{{.+}}_worker",
+// TCHECK-DAG: distinct !DISubprogram(linkageName: "__omp_offloading_{{.+}}_worker",
+// TCHECK-DAG: distinct !DISubprogram(linkageName: "__omp_offloading_{{.+}}_worker",
+// TCHECK-DAG: distinct !DISubprogram(linkageName: "__omp_offloading_{{.+}}_worker",
+// TCHECK-DAG: distinct !DISubprogram(linkageName: "__omp_offloading_{{.+}}_worker",
diff --git a/test/OpenMP/nvptx_target_parallel_codegen.cpp b/test/OpenMP/nvptx_target_parallel_codegen.cpp
index 7d1662435842..15611f647588 100644
--- a/test/OpenMP/nvptx_target_parallel_codegen.cpp
+++ b/test/OpenMP/nvptx_target_parallel_codegen.cpp
@@ -1,9 +1,9 @@
// Test target codegen - host bc file has to be created first.
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm-bc %s -o %t-x86-host.bc
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fexceptions -fcxx-exceptions -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple i386-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -fexceptions -fcxx-exceptions -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -55,14 +55,16 @@ int bar(int n){
// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l26}}(
// CHECK: [[AA_ADDR:%.+]] = alloca i16*, align
+ // CHECK-NOT: call i8* @__kmpc_data_sharing_push_stack
// CHECK: store i16* {{%.+}}, i16** [[AA_ADDR]], align
// CHECK: [[AA:%.+]] = load i16*, i16** [[AA_ADDR]], align
// CHECK: [[THREAD_LIMIT:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
// CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]],
+ // CHECK: call void @__kmpc_data_sharing_init_stack_spmd
// CHECK: br label {{%?}}[[EXEC:.+]]
//
// CHECK: [[EXEC]]
- // CHECK: {{call|invoke}} void [[OP1:@.+]](i32* null, i32* null, i16* [[AA]])
+ // CHECK: {{call|invoke}} void [[OP1:@.+]]({{.+}}, {{.+}}, i16* [[AA]])
// CHECK: br label {{%?}}[[DONE:.+]]
//
// CHECK: [[DONE]]
@@ -101,10 +103,11 @@ int bar(int n){
// CHECK: [[B:%.+]] = load [10 x i32]*, [10 x i32]** [[B_ADDR]], align
// CHECK: [[THREAD_LIMIT:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
// CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]],
+ // CHECK: call void @__kmpc_data_sharing_init_stack_spmd
// CHECK: br label {{%?}}[[EXEC:.+]]
//
// CHECK: [[EXEC]]
- // CHECK: {{call|invoke}} void [[OP2:@.+]](i32* null, i32* null, i32* [[A]], i16* [[AA]], [10 x i32]* [[B]])
+ // CHECK: {{call|invoke}} void [[OP2:@.+]]({{.+}}, {{.+}}, i32* [[A]], i16* [[AA]], [10 x i32]* [[B]])
// CHECK: br label {{%?}}[[DONE:.+]]
//
// CHECK: [[DONE]]
diff --git a/test/OpenMP/nvptx_target_parallel_num_threads_codegen.cpp b/test/OpenMP/nvptx_target_parallel_num_threads_codegen.cpp
index bc423c1ee605..13a7fb289dad 100644
--- a/test/OpenMP/nvptx_target_parallel_num_threads_codegen.cpp
+++ b/test/OpenMP/nvptx_target_parallel_num_threads_codegen.cpp
@@ -1,16 +1,16 @@
// Test target codegen - host bc file has to be created first.
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm-bc %s -o %t-x86-host.bc
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fexceptions -fcxx-exceptions -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple i386-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -fexceptions -fcxx-exceptions -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
-// Check that the execution mode of all 2 target regions on the gpu is set to SPMD Mode.
-// CHECK-DAG: {{@__omp_offloading_.+l21}}_exec_mode = weak constant i8 0
-// CHECK-DAG: {{@__omp_offloading_.+l26}}_exec_mode = weak constant i8 0
+// Check that the execution mode of all 2 target regions on the gpu is set to non-SPMD Mode.
+// CHECK-DAG: {{@__omp_offloading_.+l21}}_exec_mode = weak constant i8 1
+// CHECK-DAG: {{@__omp_offloading_.+l26}}_exec_mode = weak constant i8 1
template<typename tx>
tx ftemplate(int n) {
@@ -46,23 +46,13 @@ int bar(int n){
// CHECK: store i16* {{%.+}}, i16** [[AA_ADDR]], align
// CHECK: [[AA:%.+]] = load i16*, i16** [[AA_ADDR]], align
// CHECK: [[THREAD_LIMIT:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
- // CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]],
- // CHECK: br label {{%?}}[[EXEC:.+]]
- //
- // CHECK: [[EXEC]]
- // CHECK-NOT: call void @__kmpc_push_num_threads
- // CHECK: {{call|invoke}} void [[OP1:@.+]](i32* null, i32* null, i16* [[AA]])
- // CHECK: br label {{%?}}[[DONE:.+]]
- //
- // CHECK: [[DONE]]
- // CHECK: call void @__kmpc_spmd_kernel_deinit()
- // CHECK: br label {{%?}}[[EXIT:.+]]
- //
- // CHECK: [[EXIT]]
+ // CHECK: call void @__kmpc_kernel_init(i32
+ // CHECK: call void @__kmpc_push_num_threads
+ // CHECK: call void @__kmpc_kernel_deinit(i16 1)
// CHECK: ret void
// CHECK: }
- // CHECK: define internal void [[OP1]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i16* {{[^%]*}}[[ARG:%.+]])
+ // CHECK: define internal void @{{.+}}(i32* noalias %{{.+}}, i32* noalias %{{.+}}, i16* {{[^%]*}}[[ARG:%.+]])
// CHECK: = alloca i32*, align
// CHECK: = alloca i32*, align
// CHECK: [[AA_ADDR:%.+]] = alloca i16*, align
@@ -89,23 +79,13 @@ int bar(int n){
// CHECK: [[AA:%.+]] = load i16*, i16** [[AA_ADDR]], align
// CHECK: [[B:%.+]] = load [10 x i32]*, [10 x i32]** [[B_ADDR]], align
// CHECK: [[THREAD_LIMIT:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
- // CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]],
- // CHECK: br label {{%?}}[[EXEC:.+]]
- //
- // CHECK: [[EXEC]]
- // CHECK-NOT: call void @__kmpc_push_num_threads
- // CHECK: {{call|invoke}} void [[OP2:@.+]](i32* null, i32* null, i32* [[A]], i16* [[AA]], [10 x i32]* [[B]])
- // CHECK: br label {{%?}}[[DONE:.+]]
- //
- // CHECK: [[DONE]]
- // CHECK: call void @__kmpc_spmd_kernel_deinit()
- // CHECK: br label {{%?}}[[EXIT:.+]]
- //
- // CHECK: [[EXIT]]
+ // CHECK: call void @__kmpc_kernel_init(i32
+ // CHECK: call void @__kmpc_push_num_threads
+ // CHECK: call void @__kmpc_kernel_deinit(i16 1)
// CHECK: ret void
// CHECK: }
- // CHECK: define internal void [[OP2]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i32* {{[^%]*}}[[ARG1:%.+]], i16* {{[^%]*}}[[ARG2:%.+]], [10 x i32]* {{[^%]*}}[[ARG3:%.+]])
+ // CHECK: define internal void @{{.+}}(i32* noalias %{{.+}}, i32* noalias %{{.+}}, i32* {{[^%]*}}[[ARG1:%.+]], i16* {{[^%]*}}[[ARG2:%.+]], [10 x i32]* {{[^%]*}}[[ARG3:%.+]])
// CHECK: = alloca i32*, align
// CHECK: = alloca i32*, align
// CHECK: [[A_ADDR:%.+]] = alloca i32*, align
diff --git a/test/OpenMP/nvptx_target_parallel_proc_bind_codegen.cpp b/test/OpenMP/nvptx_target_parallel_proc_bind_codegen.cpp
index 91c6de1b85d3..1cdcb70417b8 100644
--- a/test/OpenMP/nvptx_target_parallel_proc_bind_codegen.cpp
+++ b/test/OpenMP/nvptx_target_parallel_proc_bind_codegen.cpp
@@ -1,9 +1,9 @@
// Test target codegen - host bc file has to be created first.
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm-bc %s -o %t-x86-host.bc
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fexceptions -fcxx-exceptions -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple i386-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -fexceptions -fcxx-exceptions -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -48,11 +48,12 @@ int bar(int n){
// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l22}}(
// CHECK: call void @__kmpc_spmd_kernel_init(
+ // CHECK: call void @__kmpc_data_sharing_init_stack_spmd
// CHECK: br label {{%?}}[[EXEC:.+]]
//
// CHECK: [[EXEC]]
// CHECK-NOT: call void @__kmpc_push_proc_bind
- // CHECK: {{call|invoke}} void [[OP1:@.+]](i32* null, i32* null
+ // CHECK: {{call|invoke}} void [[OP1:@.+]](
// CHECK: br label {{%?}}[[DONE:.+]]
//
// CHECK: [[DONE]]
@@ -69,11 +70,12 @@ int bar(int n){
// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l26}}(
// CHECK: call void @__kmpc_spmd_kernel_init(
+ // CHECK: call void @__kmpc_data_sharing_init_stack_spmd
// CHECK: br label {{%?}}[[EXEC:.+]]
//
// CHECK: [[EXEC]]
// CHECK-NOT: call void @__kmpc_push_proc_bind
- // CHECK: {{call|invoke}} void [[OP1:@.+]](i32* null, i32* null
+ // CHECK: {{call|invoke}} void [[OP1:@.+]](
// CHECK: br label {{%?}}[[DONE:.+]]
//
// CHECK: [[DONE]]
@@ -89,11 +91,12 @@ int bar(int n){
// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l31}}(
// CHECK: call void @__kmpc_spmd_kernel_init(
+ // CHECK: call void @__kmpc_data_sharing_init_stack_spmd
// CHECK: br label {{%?}}[[EXEC:.+]]
//
// CHECK: [[EXEC]]
// CHECK-NOT: call void @__kmpc_push_proc_bind
- // CHECK: {{call|invoke}} void [[OP1:@.+]](i32* null, i32* null
+ // CHECK: {{call|invoke}} void [[OP1:@.+]](
// CHECK: br label {{%?}}[[DONE:.+]]
//
// CHECK: [[DONE]]
diff --git a/test/OpenMP/nvptx_target_parallel_reduction_codegen.cpp b/test/OpenMP/nvptx_target_parallel_reduction_codegen.cpp
index c4c3e977b0e2..02676272b0fe 100644
--- a/test/OpenMP/nvptx_target_parallel_reduction_codegen.cpp
+++ b/test/OpenMP/nvptx_target_parallel_reduction_codegen.cpp
@@ -1,9 +1,9 @@
// Test target codegen - host bc file has to be created first.
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm-bc %s -o %t-x86-host.bc
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
-// RUN: %clang_cc1 -verify -fopenmp -fexceptions -fcxx-exceptions -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-cuda-mode -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-cuda-mode -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-cuda-mode -x c++ -triple i386-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-cuda-mode -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-cuda-mode -fexceptions -fcxx-exceptions -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -24,18 +24,18 @@ tx ftemplate(int n) {
float d;
double e;
- #pragma omp target parallel reduction(+: e) map(tofrom: e)
+ #pragma omp target parallel reduction(+: e)
{
e += 5;
}
- #pragma omp target parallel reduction(^: c) reduction(*: d) map(tofrom: c,d)
+ #pragma omp target parallel reduction(^: c) reduction(*: d)
{
c ^= 2;
d *= 33;
}
- #pragma omp target parallel reduction(|: a) reduction(max: b) map(tofrom: a,b)
+ #pragma omp target parallel reduction(|: a) reduction(max: b)
{
a |= 1;
b = 99 > b ? 99 : b;
@@ -55,6 +55,7 @@ int bar(int n){
// CHECK: define {{.*}}void {{@__omp_offloading_.+template.+l27}}(
//
// CHECK: call void @__kmpc_spmd_kernel_init(
+ // CHECK: call void @__kmpc_data_sharing_init_stack_spmd
// CHECK: br label {{%?}}[[EXECUTE:.+]]
//
// CHECK: [[EXECUTE]]
@@ -117,15 +118,15 @@ int bar(int n){
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
// CHECK: [[REMOTE_ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[REMOTE_RED_LIST:%.+]], i{{32|64}} 0, i{{32|64}} 0
// CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to double*
- // CHECK: [[ELT_VAL:%.+]] = load double, double* [[ELT]], align
//
- // CHECK: [[ELT_CAST:%.+]] = bitcast double [[ELT_VAL]] to i64
+ // CHECK: [[ELT_CAST:%.+]] = bitcast double* [[ELT]] to i64*
+ // CHECK: [[REMOTE_ELT_CAST:%.+]] = bitcast double* [[REMOTE_ELT]] to i64*
+ // CHECK: [[ELT_VAL:%.+]] = load i64, i64* [[ELT_CAST]], align
// CHECK: [[WS32:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
// CHECK: [[WS:%.+]] = trunc i32 [[WS32]] to i16
- // CHECK: [[REMOTE_ELT_VAL64:%.+]] = call i64 @__kmpc_shuffle_int64(i64 [[ELT_CAST]], i16 [[LANEOFFSET]], i16 [[WS]])
- // CHECK: [[REMOTE_ELT_VAL:%.+]] = bitcast i64 [[REMOTE_ELT_VAL64]] to double
+ // CHECK: [[REMOTE_ELT_VAL64:%.+]] = call i64 @__kmpc_shuffle_int64(i64 [[ELT_VAL]], i16 [[LANEOFFSET]], i16 [[WS]])
//
- // CHECK: store double [[REMOTE_ELT_VAL]], double* [[REMOTE_ELT]], align
+ // CHECK: store i64 [[REMOTE_ELT_VAL64]], i64* [[REMOTE_ELT_CAST]], align
// CHECK: [[REMOTE_ELT_VOID:%.+]] = bitcast double* [[REMOTE_ELT]] to i8*
// CHECK: store i8* [[REMOTE_ELT_VOID]], i8** [[REMOTE_ELT_REF]], align
//
@@ -168,8 +169,8 @@ int bar(int n){
// CHECK: [[REMOTE_ELT_VOID:%.+]] = load i8*, i8** [[REMOTE_ELT_REF]],
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i{{32|64}} 0, i{{32|64}} 0
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to double*
// CHECK: [[REMOTE_ELT:%.+]] = bitcast i8* [[REMOTE_ELT_VOID]] to double*
+ // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to double*
// CHECK: [[REMOTE_ELT_VAL:%.+]] = load double, double* [[REMOTE_ELT]], align
// CHECK: store double [[REMOTE_ELT_VAL]], double* [[ELT]], align
// CHECK: br label {{%?}}[[COPY_CONT:.+]]
@@ -193,10 +194,10 @@ int bar(int n){
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i{{32|64}} 0, i{{32|64}} 0
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
// CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to double*
- // CHECK: [[ELT_VAL:%.+]] = load double, double* [[ELT]], align
//
// CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]]
// CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to double addrspace([[SHARED_ADDRSPACE]])*
+ // CHECK: [[ELT_VAL:%.+]] = load double, double* [[ELT]], align
// CHECK: store double [[ELT_VAL]], double addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: br label {{%?}}[[COPY_CONT:.+]]
//
@@ -216,10 +217,10 @@ int bar(int n){
// CHECK: [[DO_READ]]
// CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]]
// CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to double addrspace([[SHARED_ADDRSPACE]])*
- // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load double, double addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i{{32|64}} 0, i{{32|64}} 0
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
// CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to double*
+ // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load double, double addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: store double [[MEDIUM_ELT_VAL]], double* [[ELT]], align
// CHECK: br label {{%?}}[[READ_CONT:.+]]
//
@@ -242,6 +243,7 @@ int bar(int n){
// CHECK: define {{.*}}void {{@__omp_offloading_.+template.+l32}}(
//
// CHECK: call void @__kmpc_spmd_kernel_init(
+ // CHECK: call void @__kmpc_data_sharing_init_stack_spmd
// CHECK: br label {{%?}}[[EXECUTE:.+]]
//
// CHECK: [[EXECUTE]]
@@ -347,15 +349,15 @@ int bar(int n){
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
// CHECK: [[REMOTE_ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[REMOTE_RED_LIST]], i{{32|64}} 0, i{{32|64}} 1
// CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to float*
- // CHECK: [[ELT_VAL:%.+]] = load float, float* [[ELT]], align
//
- // CHECK: [[ELT_CAST:%.+]] = bitcast float [[ELT_VAL]] to i32
+ // CHECK: [[ELT_CAST:%.+]] = bitcast float* [[ELT]] to i32*
+ // CHECK: [[REMOTE_ELT2_CAST:%.+]] = bitcast float* [[REMOTE_ELT2]] to i32*
+ // CHECK: [[ELT_VAL:%.+]] = load i32, i32* [[ELT_CAST]], align
// CHECK: [[WS32:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
// CHECK: [[WS:%.+]] = trunc i32 [[WS32]] to i16
- // CHECK: [[REMOTE_ELT2_VAL32:%.+]] = call i32 @__kmpc_shuffle_int32(i32 [[ELT_CAST]], i16 [[LANEOFFSET]], i16 [[WS]])
- // CHECK: [[REMOTE_ELT2_VAL:%.+]] = bitcast i32 [[REMOTE_ELT2_VAL32]] to float
+ // CHECK: [[REMOTE_ELT2_VAL32:%.+]] = call i32 @__kmpc_shuffle_int32(i32 [[ELT_VAL]], i16 [[LANEOFFSET]], i16 [[WS]])
//
- // CHECK: store float [[REMOTE_ELT2_VAL]], float* [[REMOTE_ELT2]], align
+ // CHECK: store i32 [[REMOTE_ELT2_VAL32]], i32* [[REMOTE_ELT2_CAST]], align
// CHECK: [[REMOTE_ELT2C:%.+]] = bitcast float* [[REMOTE_ELT2]] to i8*
// CHECK: store i8* [[REMOTE_ELT2C]], i8** [[REMOTE_ELT_REF]], align
//
@@ -405,8 +407,8 @@ int bar(int n){
// CHECK: [[REMOTE_ELT_VOID:%.+]] = load i8*, i8** [[REMOTE_ELT_REF]],
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i{{32|64}} 0, i{{32|64}} 1
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to float*
// CHECK: [[REMOTE_ELT:%.+]] = bitcast i8* [[REMOTE_ELT_VOID]] to float*
+ // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to float*
// CHECK: [[REMOTE_ELT_VAL:%.+]] = load float, float* [[REMOTE_ELT]], align
// CHECK: store float [[REMOTE_ELT_VAL]], float* [[ELT]], align
// CHECK: br label {{%?}}[[COPY_CONT:.+]]
@@ -429,10 +431,10 @@ int bar(int n){
// [[DO_COPY]]
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i{{32|64}} 0, i{{32|64}} 0
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[ELT_VAL:%.+]] = load i8, i8* [[ELT_VOID]], align
//
// CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]]
// CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i8 addrspace([[SHARED_ADDRSPACE]])*
+ // CHECK: [[ELT_VAL:%.+]] = load i8, i8* [[ELT_VOID]], align
// CHECK: store i8 [[ELT_VAL]], i8 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: br label {{%?}}[[COPY_CONT:.+]]
//
@@ -452,9 +454,9 @@ int bar(int n){
// CHECK: [[DO_READ]]
// CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]]
// CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i8 addrspace([[SHARED_ADDRSPACE]])*
- // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load i8, i8 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i{{32|64}} 0, i{{32|64}} 0
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
+ // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load i8, i8 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: store i8 [[MEDIUM_ELT_VAL]], i8* [[ELT_VOID]], align
// CHECK: br label {{%?}}[[READ_CONT:.+]]
//
@@ -470,10 +472,10 @@ int bar(int n){
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i{{32|64}} 0, i{{32|64}} 1
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
// CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to float*
- // CHECK: [[ELT_VAL:%.+]] = load float, float* [[ELT]], align
//
// CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]]
// CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to float addrspace([[SHARED_ADDRSPACE]])*
+ // CHECK: [[ELT_VAL:%.+]] = load float, float* [[ELT]], align
// CHECK: store float [[ELT_VAL]], float addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: br label {{%?}}[[COPY_CONT:.+]]
//
@@ -493,10 +495,10 @@ int bar(int n){
// CHECK: [[DO_READ]]
// CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]]
// CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to float addrspace([[SHARED_ADDRSPACE]])*
- // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load float, float addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i{{32|64}} 0, i{{32|64}} 1
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
// CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to float*
+ // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load float, float addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: store float [[MEDIUM_ELT_VAL]], float* [[ELT]], align
// CHECK: br label {{%?}}[[READ_CONT:.+]]
//
@@ -519,6 +521,7 @@ int bar(int n){
// CHECK: define {{.*}}void {{@__omp_offloading_.+template.+l38}}(
//
// CHECK: call void @__kmpc_spmd_kernel_init(
+ // CHECK: call void @__kmpc_data_sharing_init_stack_spmd
// CHECK: br label {{%?}}[[EXECUTE:.+]]
//
// CHECK: [[EXECUTE]]
@@ -714,8 +717,8 @@ int bar(int n){
// CHECK: [[REMOTE_ELT_VOID:%.+]] = load i8*, i8** [[REMOTE_ELT_REF]],
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i{{32|64}} 0, i{{32|64}} 0
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i32*
// CHECK: [[REMOTE_ELT:%.+]] = bitcast i8* [[REMOTE_ELT_VOID]] to i32*
+ // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i32*
// CHECK: [[REMOTE_ELT_VAL:%.+]] = load i32, i32* [[REMOTE_ELT]], align
// CHECK: store i32 [[REMOTE_ELT_VAL]], i32* [[ELT]], align
//
@@ -723,8 +726,8 @@ int bar(int n){
// CHECK: [[REMOTE_ELT_VOID:%.+]] = load i8*, i8** [[REMOTE_ELT_REF]],
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i{{32|64}} 0, i{{32|64}} 1
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i16*
// CHECK: [[REMOTE_ELT:%.+]] = bitcast i8* [[REMOTE_ELT_VOID]] to i16*
+ // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i16*
// CHECK: [[REMOTE_ELT_VAL:%.+]] = load i16, i16* [[REMOTE_ELT]], align
// CHECK: store i16 [[REMOTE_ELT_VAL]], i16* [[ELT]], align
// CHECK: br label {{%?}}[[COPY_CONT:.+]]
@@ -748,10 +751,10 @@ int bar(int n){
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i{{32|64}} 0, i{{32|64}} 0
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
// CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i32*
- // CHECK: [[ELT_VAL:%.+]] = load i32, i32* [[ELT]], align
//
// CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]]
// CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i32 addrspace([[SHARED_ADDRSPACE]])*
+ // CHECK: [[ELT_VAL:%.+]] = load i32, i32* [[ELT]], align
// CHECK: store i32 [[ELT_VAL]], i32 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: br label {{%?}}[[COPY_CONT:.+]]
//
@@ -771,10 +774,10 @@ int bar(int n){
// CHECK: [[DO_READ]]
// CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]]
// CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i32 addrspace([[SHARED_ADDRSPACE]])*
- // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load i32, i32 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i{{32|64}} 0, i{{32|64}} 0
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
// CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i32*
+ // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load i32, i32 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: store i32 [[MEDIUM_ELT_VAL]], i32* [[ELT]], align
// CHECK: br label {{%?}}[[READ_CONT:.+]]
//
@@ -790,10 +793,10 @@ int bar(int n){
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i{{32|64}} 0, i{{32|64}} 1
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
// CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i16*
- // CHECK: [[ELT_VAL:%.+]] = load i16, i16* [[ELT]], align
//
// CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]]
// CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i16 addrspace([[SHARED_ADDRSPACE]])*
+ // CHECK: [[ELT_VAL:%.+]] = load i16, i16* [[ELT]], align
// CHECK: store i16 [[ELT_VAL]], i16 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: br label {{%?}}[[COPY_CONT:.+]]
//
@@ -813,10 +816,10 @@ int bar(int n){
// CHECK: [[DO_READ]]
// CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]]
// CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i16 addrspace([[SHARED_ADDRSPACE]])*
- // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load i16, i16 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i{{32|64}} 0, i{{32|64}} 1
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
// CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i16*
+ // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load i16, i16 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: store i16 [[MEDIUM_ELT_VAL]], i16* [[ELT]], align
// CHECK: br label {{%?}}[[READ_CONT:.+]]
//
diff --git a/test/OpenMP/nvptx_target_printf_codegen.c b/test/OpenMP/nvptx_target_printf_codegen.c
index 0de6885a5a72..e7bfb874f4ef 100644
--- a/test/OpenMP/nvptx_target_printf_codegen.c
+++ b/test/OpenMP/nvptx_target_printf_codegen.c
@@ -3,12 +3,8 @@
// RUN: %clang_cc1 -verify -fopenmp -x c -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -verify -fopenmp -x c -triple i386-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm-bc %s -o %t-x86-host.bc
// RUN: %clang_cc1 -verify -fopenmp -x c -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
-
-#include <stdarg.h>
-
// expected-no-diagnostics
extern int printf(const char *, ...);
-extern int vprintf(const char *, va_list);
// Check a simple call to printf end-to-end.
// CHECK: [[SIMPLE_PRINTF_TY:%[a-zA-Z0-9_]+]] = type { i32, i64, double }
@@ -33,7 +29,7 @@ int CheckSimple() {
// CHECK: [[MASTER]]
// CHECK-DAG: [[MNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
// CHECK-DAG: [[MWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK: [[MTMP1:%.+]] = sub i32 [[MNTH]], [[MWS]]
+ // CHECK: [[MTMP1:%.+]] = sub nuw i32 [[MNTH]], [[MWS]]
// CHECK: call void @__kmpc_kernel_init(i32 [[MTMP1]]
// printf in master-only basic block.
@@ -73,7 +69,7 @@ void CheckNoArgs() {
// CHECK: [[MASTER]]
// CHECK-DAG: [[MNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
// CHECK-DAG: [[MWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK: [[MTMP1:%.+]] = sub i32 [[MNTH]], [[MWS]]
+ // CHECK: [[MTMP1:%.+]] = sub nuw i32 [[MNTH]], [[MWS]]
// CHECK: call void @__kmpc_kernel_init(i32 [[MTMP1]]
// printf in master-only basic block.
@@ -106,7 +102,7 @@ void CheckAllocaIsInEntryBlock() {
// CHECK: [[MASTER]]
// CHECK-DAG: [[MNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
// CHECK-DAG: [[MWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK: [[MTMP1:%.+]] = sub i32 [[MNTH]], [[MWS]]
+ // CHECK: [[MTMP1:%.+]] = sub nuw i32 [[MNTH]], [[MWS]]
// CHECK: call void @__kmpc_kernel_init(i32 [[MTMP1]]
if (foo) {
diff --git a/test/OpenMP/nvptx_target_simd_codegen.cpp b/test/OpenMP/nvptx_target_simd_codegen.cpp
new file mode 100644
index 000000000000..89ea173addcc
--- /dev/null
+++ b/test/OpenMP/nvptx_target_simd_codegen.cpp
@@ -0,0 +1,87 @@
+// Test target codegen - host bc file has to be created first.
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple i386-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -fexceptions -fcxx-exceptions -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+// Check that the execution mode of all 2 target regions on the gpu is set to NonSPMD Mode.
+// CHECK-DAG: {{@__omp_offloading_.+l25}}_exec_mode = weak constant i8 1
+// CHECK-DAG: {{@__omp_offloading_.+l30}}_exec_mode = weak constant i8 1
+// CHECK-DAG: {{@__omp_offloading_.+l35}}_exec_mode = weak constant i8 1
+// CHECK-DAG: {{@__omp_offloading_.+l40}}_exec_mode = weak constant i8 1
+
+#define N 1000
+
+template<typename tx>
+tx ftemplate(int n) {
+ tx a[N];
+ short aa[N];
+ tx b[10];
+
+ #pragma omp target simd
+ for(int i = 0; i < n; i++) {
+ a[i] = 1;
+ }
+
+ #pragma omp target simd
+ for (int i = 0; i < n; i++) {
+ aa[i] += 1;
+ }
+
+ #pragma omp target simd
+ for(int i = 0; i < 10; i++) {
+ b[i] += 1;
+ }
+
+ #pragma omp target simd reduction(+:n)
+ for(int i = 0; i < 10; i++) {
+ b[i] += 1;
+ }
+
+ return a[0];
+}
+
+int bar(int n){
+ int a = 0;
+
+ a += ftemplate<int>(n);
+
+ return a;
+}
+
+// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+l25}}(
+// CHECK: call void @__kmpc_kernel_init(i32 %{{.+}}, i16 1)
+// CHECK-NOT: call void @__kmpc_for_static_init
+// CHECK-NOT: call void @__kmpc_for_static_fini
+// CHECK: call void @__kmpc_kernel_deinit(i16 1)
+// CHECK: ret void
+
+// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+l30}}(
+// CHECK: call void @__kmpc_kernel_init(i32 %{{.+}}, i16 1)
+// CHECK-NOT: call void @__kmpc_for_static_init
+// CHECK-NOT: call void @__kmpc_for_static_fini
+// CHECK: call void @__kmpc_kernel_deinit(i16 1)
+// CHECK: ret void
+
+// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+l35}}(
+// CHECK: call void @__kmpc_kernel_init(i32 %{{.+}}, i16 1)
+// CHECK-NOT: call void @__kmpc_for_static_init
+// CHECK-NOT: call void @__kmpc_for_static_fini
+// CHECK: call void @__kmpc_kernel_deinit(i16 1)
+// CHECK: ret void
+
+// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+l40}}(
+// CHECK: call void @__kmpc_kernel_init(i32 %{{.+}}, i16 1)
+// CHECK-NOT: call void @__kmpc_for_static_init
+// CHECK-NOT: call void @__kmpc_for_static_fini
+// CHECK-NOT: call i32 @__kmpc_nvptx_simd_reduce_nowait(
+// CHECK-NOT: call void @__kmpc_nvptx_end_reduce_nowait(
+// CHECK: call void @__kmpc_kernel_deinit(i16 1)
+// CHECK: ret void
+
+
+#endif
diff --git a/test/OpenMP/nvptx_target_teams_codegen.cpp b/test/OpenMP/nvptx_target_teams_codegen.cpp
index 8b016cc307d5..c7667d83b9aa 100644
--- a/test/OpenMP/nvptx_target_teams_codegen.cpp
+++ b/test/OpenMP/nvptx_target_teams_codegen.cpp
@@ -9,8 +9,9 @@
#define HEADER
// Check that the execution mode of all 2 target regions is set to Generic Mode.
-// CHECK-DAG: {{@__omp_offloading_.+l26}}_exec_mode = weak constant i8 1
-// CHECK-DAG: {{@__omp_offloading_.+l31}}_exec_mode = weak constant i8 1
+// CHECK-DAG: {{@__omp_offloading_.+l27}}_exec_mode = weak constant i8 1
+// CHECK-DAG: {{@__omp_offloading_.+l32}}_exec_mode = weak constant i8 1
+// CHECK-DAG: {{@__omp_offloading_.+l37}}_exec_mode = weak constant i8 0
template<typename tx>
tx ftemplate(int n) {
@@ -33,6 +34,13 @@ tx ftemplate(int n) {
aa = 1;
}
+ #pragma omp target teams
+ {
+#pragma omp parallel
+#pragma omp parallel
+ aa = 1;
+ }
+
return a;
}
@@ -44,14 +52,14 @@ int bar(int n){
return a;
}
- // CHECK-NOT: define {{.*}}void {{@__omp_offloading_.+template.+l21}}_worker()
+ // CHECK-NOT: define {{.*}}void {{@__omp_offloading_.+template.+l22}}_worker()
- // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l26}}_worker()
+ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l27}}_worker()
// CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8,
// CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*,
// CHECK: store i8* null, i8** [[OMP_WORK_FN]],
@@ -60,7 +68,7 @@ int bar(int n){
//
// CHECK: [[AWAIT_WORK]]
// CHECK: call void @llvm.nvvm.barrier0()
- // CHECK: [[KPR:%.+]] = call i1 @__kmpc_kernel_parallel(i8** [[OMP_WORK_FN]], i8*** %shared_args, i16 1)
+ // CHECK: [[KPR:%.+]] = call i1 @__kmpc_kernel_parallel(i8** [[OMP_WORK_FN]], i16 1)
// CHECK: [[KPRB:%.+]] = zext i1 [[KPR]] to i8
// store i8 [[KPRB]], i8* [[OMP_EXEC_STATUS]], align 1
// CHECK: [[WORK:%.+]] = load i8*, i8** [[OMP_WORK_FN]],
@@ -86,14 +94,14 @@ int bar(int n){
// CHECK: [[EXIT]]
// CHECK: ret void
- // CHECK: define {{.*}}void [[T1:@__omp_offloading_.+template.+l26]](i[[SZ:32|64]] [[A:%[^)]+]])
+ // CHECK: define {{.*}}void [[T1:@__omp_offloading_.+template.+l27]](i[[SZ:32|64]] [[A:%[^)]+]])
// CHECK: store i[[SZ]] [[A]], i[[SZ]]* [[A_ADDR:%.+]], align
// CHECK: [[CONV:%.+]] = bitcast i[[SZ]]* [[A_ADDR]] to i8*
// CHECK-DAG: [[TID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
// CHECK-DAG: [[NTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
// CHECK-DAG: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK-DAG: [[TH_LIMIT:%.+]] = sub i32 [[NTH]], [[WS]]
+ // CHECK-DAG: [[TH_LIMIT:%.+]] = sub nuw i32 [[NTH]], [[WS]]
// CHECK: [[IS_WORKER:%.+]] = icmp ult i32 [[TID]], [[TH_LIMIT]]
// CHECK: br i1 [[IS_WORKER]], label {{%?}}[[WORKER:.+]], label {{%?}}[[CHECK_MASTER:.+]]
//
@@ -111,7 +119,7 @@ int bar(int n){
// CHECK: [[MASTER]]
// CHECK-DAG: [[MNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
// CHECK-DAG: [[MWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK: [[MTMP1:%.+]] = sub i32 [[MNTH]], [[MWS]]
+ // CHECK: [[MTMP1:%.+]] = sub nuw i32 [[MNTH]], [[MWS]]
// CHECK: call void @__kmpc_kernel_init(i32 [[MTMP1]]
//
// CHECK-NOT: kmpc_fork_teams
@@ -121,9 +129,7 @@ int bar(int n){
// CHECK: [[ACV:%.+]] = load i[[SZ]], i[[SZ]]* [[AC]], align
// CHECK: store i[[SZ]] [[ACV]], i[[SZ]]* [[A_ADDR_T:%.+]], align
// CHECK: [[CONV2:%.+]] = bitcast i[[SZ]]* [[A_ADDR_T]] to i8*
- // CHECK: [[LD_CONV2:%.+]] = load i8, i8* [[CONV2]],
- // CHECK: store i8 [[LD_CONV2]], i8* [[A_PRIV:%[^,]+]],
- // CHECK: store i8 49, i8* [[A_PRIV]], align
+ // CHECK: store i8 49, i8* [[CONV2]], align
// CHECK: br label {{%?}}[[TERMINATE:.+]]
//
// CHECK: [[TERMINATE]]
@@ -139,7 +145,7 @@ int bar(int n){
- // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l31}}_worker()
+ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l32}}_worker()
// CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8,
// CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*,
// CHECK: store i8* null, i8** [[OMP_WORK_FN]],
@@ -148,7 +154,7 @@ int bar(int n){
//
// CHECK: [[AWAIT_WORK]]
// CHECK: call void @llvm.nvvm.barrier0()
- // CHECK: [[KPR:%.+]] = call i1 @__kmpc_kernel_parallel(i8** [[OMP_WORK_FN]], i8*** %shared_args, i16 1)
+ // CHECK: [[KPR:%.+]] = call i1 @__kmpc_kernel_parallel(i8** [[OMP_WORK_FN]], i16 1)
// CHECK: [[KPRB:%.+]] = zext i1 [[KPR]] to i8
// store i8 [[KPRB]], i8* [[OMP_EXEC_STATUS]], align 1
// CHECK: [[WORK:%.+]] = load i8*, i8** [[OMP_WORK_FN]],
@@ -174,14 +180,14 @@ int bar(int n){
// CHECK: [[EXIT]]
// CHECK: ret void
- // CHECK: define {{.*}}void [[T2:@__omp_offloading_.+template.+l31]](i[[SZ:32|64]] [[AA:%[^)]+]])
+ // CHECK: define {{.*}}void [[T2:@__omp_offloading_.+template.+l32]](i[[SZ:32|64]] [[AA:%[^)]+]])
// CHECK: store i[[SZ]] [[AA]], i[[SZ]]* [[AA_ADDR:%.+]], align
// CHECK: [[CONV:%.+]] = bitcast i[[SZ]]* [[AA_ADDR]] to i16*
// CHECK-DAG: [[TID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
// CHECK-DAG: [[NTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
// CHECK-DAG: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK-DAG: [[TH_LIMIT:%.+]] = sub i32 [[NTH]], [[WS]]
+ // CHECK-DAG: [[TH_LIMIT:%.+]] = sub nuw i32 [[NTH]], [[WS]]
// CHECK: [[IS_WORKER:%.+]] = icmp ult i32 [[TID]], [[TH_LIMIT]]
// CHECK: br i1 [[IS_WORKER]], label {{%?}}[[WORKER:.+]], label {{%?}}[[CHECK_MASTER:.+]]
//
@@ -199,7 +205,7 @@ int bar(int n){
// CHECK: [[MASTER]]
// CHECK-DAG: [[MNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
// CHECK-DAG: [[MWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK: [[MTMP1:%.+]] = sub i32 [[MNTH]], [[MWS]]
+ // CHECK: [[MTMP1:%.+]] = sub nuw i32 [[MNTH]], [[MWS]]
// CHECK: call void @__kmpc_kernel_init(i32 [[MTMP1]]
//
// CHECK-NOT: kmpc_fork_teams
@@ -209,9 +215,7 @@ int bar(int n){
// CHECK: [[ACV:%.+]] = load i[[SZ]], i[[SZ]]* [[AC]], align
// CHECK: store i[[SZ]] [[ACV]], i[[SZ]]* [[AA_ADDR_T:%.+]], align
// CHECK: [[CONV2:%.+]] = bitcast i[[SZ]]* [[AA_ADDR_T]] to i16*
- // CHECK: [[LD_CONV2:%.+]] = load i16, i16* [[CONV2]],
- // CHECK: store i16 [[LD_CONV2]], i16* [[A_PRIV:%[^,]+]],
- // CHECK: store i16 1, i16* [[A_PRIV]], align
+ // CHECK: store i16 1, i16* [[CONV2]], align
// CHECK: br label {{%?}}[[TERMINATE:.+]]
//
// CHECK: [[TERMINATE]]
@@ -222,5 +226,25 @@ int bar(int n){
// CHECK: [[EXIT]]
// CHECK: ret void
+// CHECK: define weak void @__omp_offloading_{{.*}}ftemplate{{.*}}_l37(
+// CHECK: call void @__kmpc_spmd_kernel_init(
+// CHECK: call void @__kmpc_data_sharing_init_stack_spmd
+// CHECK: call i8* @__kmpc_data_sharing_push_stack(
+// CHECK-NOT: call void @__kmpc_serialized_parallel(
+// CHECK: call void [[L0:@.+]](i32* %{{.+}}, i32* %{{.+}}, i16* %{{.*}})
+// CHECK-NOT: call void @__kmpc_end_serialized_parallel(
+// CHECK: call void @__kmpc_data_sharing_pop_stack(
+// CHECK: call void @__kmpc_spmd_kernel_deinit()
+// CHECK: ret
+
+// CHECK: define internal void [[L0]](i32* noalias %{{.+}}, i32* noalias %{{.+}}, i16* dereferenceable
+// CHECK: call void @__kmpc_serialized_parallel(
+// CHECK: call void [[L1:@.+]](i32* %{{.+}}, i32* %{{.+}}, i16* %{{.+}})
+// CHECK: call void @__kmpc_end_serialized_parallel(
+// CHECK: ret void
+
+// CHECK: define internal void [[L1]](i32* noalias %{{.+}}, i32* noalias %{{.+}}, i16* dereferenceable
+// CHECK: store i16 1, i16* %
+// CHECK: ret void
#endif
diff --git a/test/OpenMP/nvptx_target_teams_distribute_parallel_for_codegen.cpp b/test/OpenMP/nvptx_target_teams_distribute_parallel_for_codegen.cpp
new file mode 100644
index 000000000000..f74919fc828d
--- /dev/null
+++ b/test/OpenMP/nvptx_target_teams_distribute_parallel_for_codegen.cpp
@@ -0,0 +1,136 @@
+// Test target codegen - host bc file has to be created first.
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple i386-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -fexceptions -fcxx-exceptions -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+// Check that the execution mode of all 2 target regions on the gpu is set to SPMD Mode.
+// CHECK-DAG: {{@__omp_offloading_.+l32}}_exec_mode = weak constant i8 0
+// CHECK-DAG: {{@__omp_offloading_.+l38}}_exec_mode = weak constant i8 0
+// CHECK-DAG: {{@__omp_offloading_.+l43}}_exec_mode = weak constant i8 0
+// CHECK-DAG: {{@__omp_offloading_.+l48}}_exec_mode = weak constant i8 0
+// CHECK-DAG: {{@__omp_offloading_.+l56}}_exec_mode = weak constant i8 0
+
+#define N 1000
+#define M 10
+
+template<typename tx>
+tx ftemplate(int n) {
+ tx a[N];
+ short aa[N];
+ tx b[10];
+ tx c[M][M];
+ tx f = n;
+ tx l;
+ int k;
+ tx *v;
+
+#pragma omp target teams distribute parallel for lastprivate(l) dist_schedule(static,128) schedule(static,32)
+ for(int i = 0; i < n; i++) {
+ a[i] = 1;
+ l = i;
+ }
+
+ #pragma omp target teams distribute parallel for map(tofrom: aa) num_teams(M) thread_limit(64)
+ for(int i = 0; i < n; i++) {
+ aa[i] += 1;
+ }
+
+#pragma omp target teams distribute parallel for map(tofrom:a, aa, b) if(target: n>40) proc_bind(spread)
+ for(int i = 0; i < 10; i++) {
+ b[i] += 1;
+ }
+
+#pragma omp target teams distribute parallel for collapse(2) firstprivate(f) private(k)
+ for(int i = 0; i < M; i++) {
+ for(int j = 0; j < M; j++) {
+ k = M;
+ c[i][j] = i + j * f + k;
+ }
+ }
+
+#pragma omp target teams distribute parallel for map(a, v[:N])
+ for(int i = 0; i < n; i++)
+ a[i] = v[i];
+ return a[0];
+}
+
+int bar(int n){
+ int a = 0;
+
+ a += ftemplate<int>(n);
+
+ return a;
+}
+
+// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+}}(
+// CHECK-DAG: [[THREAD_LIMIT:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]],
+// CHECK: call void @__kmpc_data_sharing_init_stack_spmd
+// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 91,
+// CHECK: {{call|invoke}} void [[OUTL1:@.+]](
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: call void @__kmpc_spmd_kernel_deinit()
+// CHECK: ret void
+
+// CHECK: define internal void [[OUTL1]](
+// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 33,
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: ret void
+
+// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+}}(
+// CHECK-DAG: [[THREAD_LIMIT:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]],
+// CHECK: call void @__kmpc_data_sharing_init_stack_spmd
+// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 92,
+// CHECK: {{call|invoke}} void [[OUTL2:@.+]](
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: call void @__kmpc_spmd_kernel_deinit()
+// CHECK: ret void
+
+// CHECK: define internal void [[OUTL2]](
+// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 34,
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: ret void
+
+// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+}}(
+// CHECK-DAG: [[THREAD_LIMIT:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]],
+// CHECK: call void @__kmpc_data_sharing_init_stack_spmd
+// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 92,
+// CHECK: {{call|invoke}} void [[OUTL3:@.+]](
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: call void @__kmpc_spmd_kernel_deinit()
+// CHECK: ret void
+
+// CHECK: define internal void [[OUTL3]](
+// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 34,
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: ret void
+
+// CHECK: define {{.*}}void {{@__omp_offloading_.+}}({{.+}}, i{{32|64}} [[F_IN:%.+]])
+// CHECK: store {{.+}} [[F_IN]], {{.+}}* {{.+}},
+// CHECK-DAG: [[THREAD_LIMIT:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]],
+// CHECK: call void @__kmpc_data_sharing_init_stack_spmd
+// CHECK: store {{.+}} 99, {{.+}}* [[COMB_UB:%.+]], align
+// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 92, {{.+}}, {{.+}}, {{.+}}* [[COMB_UB]],
+// CHECK: {{call|invoke}} void [[OUTL4:@.+]](
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: call void @__kmpc_spmd_kernel_deinit()
+// CHECK: ret void
+
+// CHECK: define internal void [[OUTL4]](
+// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 34,
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: ret void
+
+// CHECK: define weak void @__omp_offloading_{{.*}}_l56(i[[SZ:64|32]] %{{[^,]+}}, [1000 x i32]* dereferenceable{{.*}}, i32* %{{[^)]+}})
+// CHECK: call void [[OUTLINED:@__omp_outlined.*]](i32* %{{.+}}, i32* %{{.+}}, i[[SZ]] %{{.*}}, i[[SZ]] %{{.*}}, i[[SZ]] %{{.*}}, [1000 x i32]* %{{.*}}, i32* %{{.*}})
+// CHECK: define internal void [[OUTLINED]](i32* noalias %{{.*}}, i32* noalias %{{.*}} i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, [1000 x i32]* dereferenceable{{.*}}, i32* %{{.*}})
+
+#endif
diff --git a/test/OpenMP/nvptx_target_teams_distribute_parallel_for_generic_mode_codegen.cpp b/test/OpenMP/nvptx_target_teams_distribute_parallel_for_generic_mode_codegen.cpp
new file mode 100644
index 000000000000..d75a10210905
--- /dev/null
+++ b/test/OpenMP/nvptx_target_teams_distribute_parallel_for_generic_mode_codegen.cpp
@@ -0,0 +1,66 @@
+// Test target codegen - host bc file has to be created first.
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fexceptions -fcxx-exceptions -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+int a;
+
+int foo(int *a);
+
+int main(int argc, char **argv) {
+#pragma omp target teams distribute parallel for map(tofrom:a) if(target:argc) schedule(static, a)
+ for (int i= 0; i < argc; ++i)
+ a = foo(&i) + foo(&a) + foo(&argc);
+ return 0;
+}
+
+// CHECK: @__omp_offloading_{{.*}}_main_l16_exec_mode = weak constant i8 0
+
+// CHECK: define weak void @__omp_offloading_{{.*}}_main_l16(i{{64|32}} %{{[^,].*}}, i32* dereferenceable{{[^,]*}}, i{{64|32}} %{{[^,)]*}})
+// CHECK: [[TID:%.+]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @
+// CHECK: call void @__kmpc_spmd_kernel_init(
+// CHECK: call void @__kmpc_for_static_init_4(
+
+// CHECK: call void [[PARALLEL:@.+]](i32* %{{.*}}, i32* %{{.+}}, i{{64|32}} %{{.+}}, i{{64|32}} %{{.*}}, i{{64|32}} %{{.*}}, i32* %{{.*}})
+// CHECK: br label %
+
+
+// CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* @
+
+// CHECK: call void @__kmpc_spmd_kernel_deinit()
+
+// CHECK: define internal void [[PARALLEL]](i32* noalias %{{.+}}, i32* noalias %{{.+}}, i{{64|32}} %{{.+}}, i{{64|32}} %{{.+}}, i{{64|32}} [[ARGC:%.+]], i32* dereferenceable{{.*}})
+// CHECK-NOT: call i8* @__kmpc_data_sharing_push_stack(
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: [[ARGC_ADDR:%.+]] = alloca i{{32|64}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: [[I:%.+]] = alloca i32,
+// CHECK-32: store i32 [[ARGC]], i32* [[ARGC_ADDR]],
+// CHECK-64: store i{{64|32}} [[ARGC]], i{{64|32}}* [[ARGC_ADDR]],
+// CHECK-64: [[ARGC:%.+]] = bitcast i64* [[ARGC_ADDR]] to i32*
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call i32 [[FOO:@.+foo.+]](i32* [[I]])
+// CHECK: call i32 [[FOO]](i32* %{{.+}})
+// CHECK-32: call i32 [[FOO]](i32* [[ARGC_ADDR]])
+// CHECK-64: call i32 [[FOO]](i32* [[ARGC]])
+// CHECK: call void @__kmpc_for_static_fini(
+
+// CHECK-NOT: call void @__kmpc_data_sharing_pop_stack(
+
+#endif
diff --git a/test/OpenMP/nvptx_target_teams_distribute_parallel_for_simd_codegen.cpp b/test/OpenMP/nvptx_target_teams_distribute_parallel_for_simd_codegen.cpp
new file mode 100644
index 000000000000..0b945a69b054
--- /dev/null
+++ b/test/OpenMP/nvptx_target_teams_distribute_parallel_for_simd_codegen.cpp
@@ -0,0 +1,127 @@
+// Test target codegen - host bc file has to be created first.
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple i386-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -fexceptions -fcxx-exceptions -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+// Check that the execution mode of all 2 target regions on the gpu is set to SPMD Mode.
+// CHECK-DAG: {{@__omp_offloading_.+l30}}_exec_mode = weak constant i8 0
+// CHECK-DAG: {{@__omp_offloading_.+l36}}_exec_mode = weak constant i8 0
+// CHECK-DAG: {{@__omp_offloading_.+l41}}_exec_mode = weak constant i8 0
+// CHECK-DAG: {{@__omp_offloading_.+l46}}_exec_mode = weak constant i8 0
+
+#define N 1000
+#define M 10
+
+template<typename tx>
+tx ftemplate(int n) {
+ tx a[N];
+ short aa[N];
+ tx b[10];
+ tx c[M][M];
+ tx f = n;
+ tx l;
+ int k;
+
+#pragma omp target teams distribute parallel for simd lastprivate(l) dist_schedule(static,128) schedule(static,32)
+ for(int i = 0; i < n; i++) {
+ a[i] = 1;
+ l = i;
+ }
+
+ #pragma omp target teams distribute parallel for simd map(tofrom: aa) num_teams(M) thread_limit(64)
+ for(int i = 0; i < n; i++) {
+ aa[i] += 1;
+ }
+
+#pragma omp target teams distribute parallel for simd map(tofrom:a, aa, b) if(target: n>40) proc_bind(spread)
+ for(int i = 0; i < 10; i++) {
+ b[i] += 1;
+ }
+
+#pragma omp target teams distribute parallel for simd collapse(2) firstprivate(f) private(k)
+ for(int i = 0; i < M; i++) {
+ for(int j = 0; j < M; j++) {
+ k = M;
+ c[i][j] = i+j*f+k;
+ }
+ }
+
+ return a[0];
+}
+
+int bar(int n){
+ int a = 0;
+
+ a += ftemplate<int>(n);
+
+ return a;
+}
+
+// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+}}(
+// CHECK-DAG: [[THREAD_LIMIT:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]],
+// CHECK: call void @__kmpc_data_sharing_init_stack_spmd
+// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 91,
+// CHECK: {{call|invoke}} void [[OUTL1:@.+]](
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: call void @__kmpc_spmd_kernel_deinit()
+// CHECK: ret void
+
+// CHECK: define internal void [[OUTL1]](
+// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 33,
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: ret void
+
+// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+}}(
+// CHECK-DAG: [[THREAD_LIMIT:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]],
+// CHECK: call void @__kmpc_data_sharing_init_stack_spmd
+// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 92,
+// CHECK: {{call|invoke}} void [[OUTL2:@.+]](
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: call void @__kmpc_spmd_kernel_deinit()
+// CHECK: ret void
+
+// CHECK: define internal void [[OUTL2]](
+// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 34,
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: ret void
+
+// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+}}(
+// CHECK-DAG: [[THREAD_LIMIT:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]],
+// CHECK: call void @__kmpc_data_sharing_init_stack_spmd
+// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 92,
+// CHECK: {{call|invoke}} void [[OUTL3:@.+]](
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: call void @__kmpc_spmd_kernel_deinit()
+// CHECK: ret void
+
+// CHECK: define internal void [[OUTL3]](
+// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 34,
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: ret void
+
+// CHECK: define {{.*}}void {{@__omp_offloading_.+}}({{.+}}, i{{32|64}} [[F_IN:%.+]])
+// CHECK: store {{.+}} [[F_IN]], {{.+}}* {{.+}},
+// CHECK-DAG: [[THREAD_LIMIT:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]],
+// CHECK: call void @__kmpc_data_sharing_init_stack_spmd
+// CHECK: store {{.+}} 99, {{.+}}* [[COMB_UB:%.+]], align
+// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 92, {{.+}}, {{.+}}, {{.+}}* [[COMB_UB]],
+// CHECK: {{call|invoke}} void [[OUTL4:@.+]](
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: call void @__kmpc_spmd_kernel_deinit()
+// CHECK: ret void
+
+// CHECK: define internal void [[OUTL4]](
+// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 34,
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: ret void
+
+#endif
diff --git a/test/OpenMP/nvptx_target_teams_distribute_simd_codegen.cpp b/test/OpenMP/nvptx_target_teams_distribute_simd_codegen.cpp
new file mode 100644
index 000000000000..48f314785c82
--- /dev/null
+++ b/test/OpenMP/nvptx_target_teams_distribute_simd_codegen.cpp
@@ -0,0 +1,95 @@
+// Test target codegen - host bc file has to be created first.
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple i386-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -fexceptions -fcxx-exceptions -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+// Check that the execution mode of all 2 target regions on the gpu is set to NonSPMD Mode.
+// CHECK-DAG: {{@__omp_offloading_.+l30}}_exec_mode = weak constant i8 1
+// CHECK-DAG: {{@__omp_offloading_.+l36}}_exec_mode = weak constant i8 1
+// CHECK-DAG: {{@__omp_offloading_.+l41}}_exec_mode = weak constant i8 1
+// CHECK-DAG: {{@__omp_offloading_.+l46}}_exec_mode = weak constant i8 1
+
+#define N 1000
+#define M 10
+
+template<typename tx>
+tx ftemplate(int n) {
+ tx a[N];
+ short aa[N];
+ tx b[10];
+ tx c[M][M];
+ tx f = n;
+ tx l;
+ int k;
+
+#pragma omp target teams distribute simd lastprivate(l) dist_schedule(static,128)
+ for(int i = 0; i < n; i++) {
+ a[i] = 1;
+ l = i;
+ }
+
+ #pragma omp target teams distribute simd map(tofrom: aa) num_teams(M) thread_limit(64)
+ for(int i = 0; i < n; i++) {
+ aa[i] += 1;
+ }
+
+#pragma omp target teams distribute simd map(tofrom:a, aa, b) if(target: n>40)
+ for(int i = 0; i < 10; i++) {
+ b[i] += 1;
+ }
+
+#pragma omp target teams distribute simd collapse(2) firstprivate(f) private(k)
+ for(int i = 0; i < M; i++) {
+ for(int j = 0; j < M; j++) {
+ k = M;
+ c[i][j] = i+j*f+k;
+ }
+ }
+
+ return a[0];
+}
+
+int bar(int n){
+ int a = 0;
+
+ a += ftemplate<int>(n);
+
+ return a;
+}
+
+// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+}}_l30(
+// CHECK: call void @__kmpc_kernel_init(i32 %{{.+}}, i16 1)
+// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 91,
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: call void @__kmpc_kernel_deinit(i16 1)
+// CHECK: ret void
+
+// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+}}_l36(
+// CHECK: call void @__kmpc_kernel_init(i32 %{{.+}}, i16 1)
+// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 92,
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: call void @__kmpc_kernel_deinit(i16 1)
+// CHECK: ret void
+
+// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+}}_l41(
+// CHECK: call void @__kmpc_kernel_init(i32 %{{.+}}, i16 1)
+// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 92,
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: call void @__kmpc_kernel_deinit(i16 1)
+// CHECK: ret void
+
+// CHECK: define {{.*}}void {{@__omp_offloading_.+}}_l46({{.+}}, i{{32|64}} [[F_IN:%.+]])
+// CHECK: store {{.+}} [[F_IN]], {{.+}}* {{.+}},
+// CHECK: call void @__kmpc_kernel_init(i32 %{{.+}}, i16 1)
+// CHECK: store {{.+}} 99, {{.+}}* [[COMB_UB:%.+]], align
+// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 92, {{.+}}, {{.+}}, {{.+}}* [[COMB_UB]],
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: call void @__kmpc_kernel_deinit(i16 1)
+// CHECK: ret void
+
+#endif
diff --git a/test/OpenMP/nvptx_teams_codegen.cpp b/test/OpenMP/nvptx_teams_codegen.cpp
index b26d47c706ac..2c50f037b228 100644
--- a/test/OpenMP/nvptx_teams_codegen.cpp
+++ b/test/OpenMP/nvptx_teams_codegen.cpp
@@ -36,11 +36,15 @@ int main (int argc, char **argv) {
// CK1: store {{.+}} 0, {{.+}},
// CK1: store i{{[0-9]+}} [[ARGC]], i{{[0-9]+}}* [[ARGCADDR]],
// CK1-64: [[CONV:%.+]] = bitcast i{{[0-9]+}}* [[ARGCADDR]] to i{{[0-9]+}}*
-// CK1-64: store i{{[0-9]+}}* [[CONV]], i{{[0-9]+}}** [[ARGCADDR_PTR]],
-// CK1-32: store i{{[0-9]+}}* [[ARGCADDR]], i{{[0-9]+}}** [[ARGCADDR_PTR]],
+// CK1: call i8* @__kmpc_data_sharing_push_stack(i{{[0-9]+}} 4, i16 0)
+// CK1-64: [[ARG:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[CONV]]
+// CK1-32: [[ARG:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[ARGCADDR]]
+// CK1: [[ARGCADDR:%.+]] = getelementptr inbounds %struct.{{.*}}, %struct.{{.*}}* %{{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 0
+// CK1: store i{{[0-9]+}} [[ARG]], i{{[0-9]+}}* [[ARGCADDR]],
+// CK1: store i{{[0-9]+}}* [[ARGCADDR]], i{{[0-9]+}}** [[ARGCADDR_PTR]],
// CK1: [[ARGCADDR_PTR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[ARGCADDR_PTR]],
// CK1: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[ARGCADDR_PTR_REF]],
-// CK1-NOT: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(
+// CK1-NOT: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(
// CK1: ret void
// CK1-NEXT: }
@@ -49,10 +53,14 @@ int main (int argc, char **argv) {
// CK1: [[ARGCADDR_PTR:%.+]] = alloca i{{.+}}***,
// CK1: [[ARGCADDR:%.+]] = alloca i{{.+}}**,
// CK1: store i{{.+}}** [[ARGC]], i{{.+}}*** [[ARGCADDR]]
+// CK1: call i8* @__kmpc_data_sharing_push_stack(i{{[0-9]+}} {{4|8}}, i16 0)
+// CK1: [[ARG:%.+]] = load i{{[0-9]+}}**, i{{[0-9]+}}*** [[ARGCADDR]]
+// CK1: [[ARGCADDR:%.+]] = getelementptr inbounds %struct.{{.*}}, %struct.{{.*}}* %{{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 0
+// CK1: store i{{[0-9]+}}** [[ARG]], i{{[0-9]+}}*** [[ARGCADDR]],
// CK1: store i8*** [[ARGCADDR]], i8**** [[ARGCADDR_PTR]],
// CK1: [[ARGCADDR_PTR_REF:%.+]] = load i{{.+}}**, i{{.+}}*** [[ARGCADDR_PTR]],
// CK1: store i{{[0-9]+}}** null, i{{[0-9]+}}*** [[ARGCADDR_PTR_REF]],
-// CK1-NOT: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(
+// CK1-NOT: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(
// CK1: ret void
// CK1-NEXT: }
@@ -97,19 +105,23 @@ int main (int argc, char **argv) {
// CK2: [[AADDR:%.+]] = alloca i{{[0-9]+}},
// CK2: [[BADDR:%.+]] = alloca i{{[0-9]+}},
// CK2: [[ARGCADDR:%.+]] = alloca i{{[0-9]+}},
-// CK2-NOT: {{%.+}} = call i32 @__kmpc_global_thread_num(
+// CK2: {{%.+}} = call i32 @__kmpc_global_thread_num(
// CK2: store i{{[0-9]+}} [[A_IN]], i{{[0-9]+}}* [[AADDR]],
// CK2: store i{{[0-9]+}} [[B_IN]], i{{[0-9]+}}* [[BADDR]],
// CK2: store i{{[0-9]+}} [[ARGC_IN]], i{{[0-9]+}}* [[ARGCADDR]],
// CK2-64: [[ACONV:%.+]] = bitcast i64* [[AADDR]] to i32*
// CK2-64: [[BCONV:%.+]] = bitcast i64* [[BADDR]] to i32*
// CK2-64: [[CONV:%.+]] = bitcast i64* [[ARGCADDR]] to i32*
-// CK2-64: store i{{[0-9]+}}* [[CONV]], i{{[0-9]+}}** [[ARGCADDR_PTR]],
-// CK2-32: store i{{[0-9]+}}* [[ARGCADDR]], i{{[0-9]+}}** [[ARGCADDR_PTR]],
+// CK2: call i8* @__kmpc_data_sharing_push_stack(i{{[0-9]+}} 4, i16 0)
+// CK2-64: [[ARG:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[CONV]]
+// CK2-32: [[ARG:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[ARGCADDR]]
+// CK2: [[ARGCADDR:%.+]] = getelementptr inbounds %struct.{{.*}}, %struct.{{.*}}* %{{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 0
+// CK2: store i{{[0-9]+}} [[ARG]], i{{[0-9]+}}* [[ARGCADDR]],
+// CK2: store i{{[0-9]+}}* [[ARGCADDR]], i{{[0-9]+}}** [[ARGCADDR_PTR]],
// CK2: [[ARGCADDR_PTR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[ARGCADDR_PTR]],
// CK2: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[ARGCADDR_PTR_REF]],
// CK2-NOT: {{.+}} = call i32 @__kmpc_push_num_teams(
-// CK2-NOT: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(
+// CK2-NOT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(
// CK2: ret
// CK2: define {{.*}}void @{{[^,]+}}(i{{[0-9]+}} [[A_IN:%.+]], i{{[0-9]+}} [[BP:%.+]], i{{[0-9]+}}** [[ARGC:%.+]])
@@ -117,15 +129,19 @@ int main (int argc, char **argv) {
// CK2: [[AADDR:%.+]] = alloca i{{[0-9]+}},
// CK2: [[BADDR:%.+]] = alloca i{{[0-9]+}},
// CK2: [[ARGCADDR:%.+]] = alloca i{{[0-9]+}}**,
-// CK2-NOT: {{%.+}} = call i32 @__kmpc_global_thread_num(
+// CK2: {{%.+}} = call i32 @__kmpc_global_thread_num(
// CK2: store i{{[0-9]+}} [[A_IN]], i{{[0-9]+}}* [[AADDR]],
// CK2: store i{{[0-9]+}} [[B_IN]], i{{[0-9]+}}* [[BADDR]],
// CK2: store i{{[0-9]+}}** [[ARGC]], i{{[0-9]+}}*** [[ARGCADDR]],
+// CK2: call i8* @__kmpc_data_sharing_push_stack(i{{[0-9]+}} {{4|8}}, i16 0)
+// CK2: [[ARG:%.+]] = load i{{[0-9]+}}**, i{{[0-9]+}}*** [[ARGCADDR]]
+// CK2: [[ARGCADDR:%.+]] = getelementptr inbounds %struct.{{.*}}, %struct.{{.*}}* %{{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 0
+// CK2: store i{{[0-9]+}}** [[ARG]], i{{[0-9]+}}*** [[ARGCADDR]],
// CK2: store i{{[0-9]+}}*** [[ARGCADDR]], i{{[0-9]+}}**** [[ARGCADDR_PTR]],
// CK2: [[ARGCADDR_PTR_REF:%.+]] = load i{{[0-9]+}}***, i{{[0-9]+}}**** [[ARGCADDR_PTR]],
// CK2: store i{{[0-9]+}}** null, i{{[0-9]+}}*** [[ARGCADDR_PTR_REF]],
// CK2-NOT: {{.+}} = call i32 @__kmpc_push_num_teams(
-// CK2-NOT: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(
+// CK2-NOT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(
// CK2: ret void
#endif // CK2
diff --git a/test/OpenMP/nvptx_teams_reduction_codegen.cpp b/test/OpenMP/nvptx_teams_reduction_codegen.cpp
index d77231807fb4..6925b17163af 100644
--- a/test/OpenMP/nvptx_teams_reduction_codegen.cpp
+++ b/test/OpenMP/nvptx_teams_reduction_codegen.cpp
@@ -117,15 +117,15 @@ int bar(int n){
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
// CHECK: [[REMOTE_ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[REMOTE_RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 0
// CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to double*
- // CHECK: [[ELT_VAL:%.+]] = load double, double* [[ELT]], align
//
- // CHECK: [[ELT_CAST:%.+]] = bitcast double [[ELT_VAL]] to i64
+ // CHECK: [[ELT_CAST:%.+]] = bitcast double* [[ELT]] to i64*
+ // CHECK: [[REMOTE_ELT_CAST:%.+]] = bitcast double* [[REMOTE_ELT]] to i64*
+ // CHECK: [[ELT_VAL:%.+]] = load i64, i64* [[ELT_CAST]], align
// CHECK: [[WS32:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
// CHECK: [[WS:%.+]] = trunc i32 [[WS32]] to i16
- // CHECK: [[REMOTE_ELT_VAL64:%.+]] = call i64 @__kmpc_shuffle_int64(i64 [[ELT_CAST]], i16 [[LANEOFFSET]], i16 [[WS]])
- // CHECK: [[REMOTE_ELT_VAL:%.+]] = bitcast i64 [[REMOTE_ELT_VAL64]] to double
+ // CHECK: [[REMOTE_ELT_VAL64:%.+]] = call i64 @__kmpc_shuffle_int64(i64 [[ELT_VAL]], i16 [[LANEOFFSET]], i16 [[WS]])
//
- // CHECK: store double [[REMOTE_ELT_VAL]], double* [[REMOTE_ELT]], align
+ // CHECK: store i64 [[REMOTE_ELT_VAL64]], i64* [[REMOTE_ELT_CAST]], align
// CHECK: [[REMOTE_ELT_VOID:%.+]] = bitcast double* [[REMOTE_ELT]] to i8*
// CHECK: store i8* [[REMOTE_ELT_VOID]], i8** [[REMOTE_ELT_REF]], align
//
@@ -168,8 +168,8 @@ int bar(int n){
// CHECK: [[REMOTE_ELT_VOID:%.+]] = load i8*, i8** [[REMOTE_ELT_REF]],
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 0
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to double*
// CHECK: [[REMOTE_ELT:%.+]] = bitcast i8* [[REMOTE_ELT_VOID]] to double*
+ // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to double*
// CHECK: [[REMOTE_ELT_VAL:%.+]] = load double, double* [[REMOTE_ELT]], align
// CHECK: store double [[REMOTE_ELT_VAL]], double* [[ELT]], align
// CHECK: br label {{%?}}[[COPY_CONT:.+]]
@@ -193,10 +193,10 @@ int bar(int n){
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 0
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
// CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to double*
- // CHECK: [[ELT_VAL:%.+]] = load double, double* [[ELT]], align
//
// CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]]
// CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to double addrspace([[SHARED_ADDRSPACE]])*
+ // CHECK: [[ELT_VAL:%.+]] = load double, double* [[ELT]], align
// CHECK: store double [[ELT_VAL]], double addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: br label {{%?}}[[COPY_CONT:.+]]
//
@@ -216,10 +216,10 @@ int bar(int n){
// CHECK: [[DO_READ]]
// CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]]
// CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to double addrspace([[SHARED_ADDRSPACE]])*
- // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load double, double addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 0
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
// CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to double*
+ // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load double, double addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: store double [[MEDIUM_ELT_VAL]], double* [[ELT]], align
// CHECK: br label {{%?}}[[READ_CONT:.+]]
//
@@ -246,11 +246,11 @@ int bar(int n){
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 0
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
//
- // CHECK: [[P:%.+]] = mul i[[SZ]] 8, [[TEAM]]
- // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add i[[SZ]] [[SCRATCHPAD]], [[P]]
+ // CHECK: [[P:%.+]] = mul nuw i[[SZ]] 8, [[TEAM]]
+ // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add nuw i[[SZ]] [[SCRATCHPAD]], [[P]]
// CHECK: [[SCRATCHPAD_ELT_PTR_VOID:%.+]] = inttoptr i[[SZ]] [[SCRATCHPAD_ELT_PTR64]] to i8*
- // CHECK: [[SCRATCHPAD_ELT_PTR:%.+]] = bitcast i8* [[SCRATCHPAD_ELT_PTR_VOID]] to double*
// CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to double*
+ // CHECK: [[SCRATCHPAD_ELT_PTR:%.+]] = bitcast i8* [[SCRATCHPAD_ELT_PTR_VOID]] to double*
// CHECK: [[ELT_VAL:%.+]] = load double, double* [[ELT]], align
// CHECK: store double [[ELT_VAL]], double* [[SCRATCHPAD_ELT_PTR]], align
//
@@ -272,8 +272,8 @@ int bar(int n){
// CHECK: [[SHOULD_REDUCE:%.+]] = load i32, i32* {{.+}}, align
// CHECK: [[SCRATCHPAD:%.+]] = ptrtoint i8* [[SCRATCHPAD_PTR]] to i[[SZ]]
//
- // CHECK: [[P:%.+]] = mul i[[SZ]] 8, [[TEAM]]
- // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add i[[SZ]] [[SCRATCHPAD]], [[P]]
+ // CHECK: [[P:%.+]] = mul nuw i[[SZ]] 8, [[TEAM]]
+ // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add nuw i[[SZ]] [[SCRATCHPAD]], [[P]]
// CHECK: [[SCRATCHPAD_ELT_PTR_VOID:%.+]] = inttoptr i[[SZ]] [[SCRATCHPAD_ELT_PTR64]] to i8*
// CHECK: [[REMOTE_ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[REMOTE_RED_LIST]], i[[SZ]] 0, i[[SZ]] 0
@@ -283,7 +283,7 @@ int bar(int n){
// CHECK: [[REMOTE_ELT_PTR:%.+]] = bitcast double* [[REMOTE_ELT]] to i8*
// CHECK: store i8* [[REMOTE_ELT_PTR]], i8** [[REMOTE_ELT_REF]], align
//
- // CHECK: [[REDUCE:%.+]] = icmp eq i32 [[SHOULD_REDUCE]], 1
+ // CHECK: [[REDUCE:%.+]] = icmp ne i32 [[SHOULD_REDUCE]], 0
// CHECK: br i1 [[REDUCE]], label {{%?}}[[DO_REDUCE:.+]], label {{%?}}[[REDUCE_ELSE:.+]]
//
// CHECK: [[DO_REDUCE]]
@@ -298,8 +298,8 @@ int bar(int n){
// CHECK: [[REMOTE_ELT_VOID:%.+]] = load i8*, i8** [[REMOTE_ELT_REF]],
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 0
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to double*
// CHECK: [[REMOTE_ELT:%.+]] = bitcast i8* [[REMOTE_ELT_VOID]] to double*
+ // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to double*
// CHECK: [[REMOTE_ELT_VAL:%.+]] = load double, double* [[REMOTE_ELT]], align
// CHECK: store double [[REMOTE_ELT_VAL]], double* [[ELT]], align
// CHECK: br label {{%?}}[[REDUCE_CONT]]
@@ -307,16 +307,6 @@ int bar(int n){
// CHECK: [[REDUCE_CONT]]
// CHECK: ret
-
-
-
-
-
-
-
-
-
-
// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l33}}_worker()
// CHECK: define {{.*}}void [[T2:@__omp_offloading_.+template.+l33]](
@@ -422,15 +412,15 @@ int bar(int n){
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
// CHECK: [[REMOTE_ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[REMOTE_RED_LIST]], i[[SZ]] 0, i[[SZ]] 1
// CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to float*
- // CHECK: [[ELT_VAL:%.+]] = load float, float* [[ELT]], align
//
- // CHECK: [[ELT_CAST:%.+]] = bitcast float [[ELT_VAL]] to i32
+ // CHECK: [[ELT_CAST:%.+]] = bitcast float* [[ELT]] to i32*
+ // CHECK: [[REMOTE_ELT2_CAST:%.+]] = bitcast float* [[REMOTE_ELT2]] to i32*
+ // CHECK: [[ELT_VAL:%.+]] = load i32, i32* [[ELT_CAST]], align
// CHECK: [[WS32:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
// CHECK: [[WS:%.+]] = trunc i32 [[WS32]] to i16
- // CHECK: [[REMOTE_ELT2_VAL32:%.+]] = call i32 @__kmpc_shuffle_int32(i32 [[ELT_CAST]], i16 [[LANEOFFSET]], i16 [[WS]])
- // CHECK: [[REMOTE_ELT2_VAL:%.+]] = bitcast i32 [[REMOTE_ELT2_VAL32]] to float
+ // CHECK: [[REMOTE_ELT2_VAL32:%.+]] = call i32 @__kmpc_shuffle_int32(i32 [[ELT_VAL]], i16 [[LANEOFFSET]], i16 [[WS]])
//
- // CHECK: store float [[REMOTE_ELT2_VAL]], float* [[REMOTE_ELT2]], align
+ // CHECK: store i32 [[REMOTE_ELT2_VAL32]], i32* [[REMOTE_ELT2_CAST]], align
// CHECK: [[REMOTE_ELT2C:%.+]] = bitcast float* [[REMOTE_ELT2]] to i8*
// CHECK: store i8* [[REMOTE_ELT2C]], i8** [[REMOTE_ELT_REF]], align
//
@@ -480,8 +470,8 @@ int bar(int n){
// CHECK: [[REMOTE_ELT_VOID:%.+]] = load i8*, i8** [[REMOTE_ELT_REF]],
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 1
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to float*
// CHECK: [[REMOTE_ELT:%.+]] = bitcast i8* [[REMOTE_ELT_VOID]] to float*
+ // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to float*
// CHECK: [[REMOTE_ELT_VAL:%.+]] = load float, float* [[REMOTE_ELT]], align
// CHECK: store float [[REMOTE_ELT_VAL]], float* [[ELT]], align
// CHECK: br label {{%?}}[[COPY_CONT:.+]]
@@ -504,10 +494,10 @@ int bar(int n){
// [[DO_COPY]]
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 0
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[ELT_VAL:%.+]] = load i8, i8* [[ELT_VOID]], align
//
// CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]]
// CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i8 addrspace([[SHARED_ADDRSPACE]])*
+ // CHECK: [[ELT_VAL:%.+]] = load i8, i8* [[ELT_VOID]], align
// CHECK: store i8 [[ELT_VAL]], i8 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: br label {{%?}}[[COPY_CONT:.+]]
//
@@ -527,9 +517,9 @@ int bar(int n){
// CHECK: [[DO_READ]]
// CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]]
// CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i8 addrspace([[SHARED_ADDRSPACE]])*
- // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load i8, i8 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 0
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
+ // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load i8, i8 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: store i8 [[MEDIUM_ELT_VAL]], i8* [[ELT_VOID]], align
// CHECK: br label {{%?}}[[READ_CONT:.+]]
//
@@ -545,10 +535,10 @@ int bar(int n){
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 1
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
// CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to float*
- // CHECK: [[ELT_VAL:%.+]] = load float, float* [[ELT]], align
//
// CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]]
// CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to float addrspace([[SHARED_ADDRSPACE]])*
+ // CHECK: [[ELT_VAL:%.+]] = load float, float* [[ELT]], align
// CHECK: store float [[ELT_VAL]], float addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: br label {{%?}}[[COPY_CONT:.+]]
//
@@ -568,10 +558,10 @@ int bar(int n){
// CHECK: [[DO_READ]]
// CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]]
// CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to float addrspace([[SHARED_ADDRSPACE]])*
- // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load float, float addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 1
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
// CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to float*
+ // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load float, float addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: store float [[MEDIUM_ELT_VAL]], float* [[ELT]], align
// CHECK: br label {{%?}}[[READ_CONT:.+]]
//
@@ -598,27 +588,27 @@ int bar(int n){
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 0
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
//
- // CHECK: [[P:%.+]] = mul i[[SZ]] 1, [[TEAM]]
- // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add i[[SZ]] [[SCRATCHPAD]], [[P]]
+ // CHECK: [[P:%.+]] = mul nuw i[[SZ]] 1, [[TEAM]]
+ // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add nuw i[[SZ]] [[SCRATCHPAD]], [[P]]
// CHECK: [[SCRATCHPAD_ELT_PTR:%.+]] = inttoptr i[[SZ]] [[SCRATCHPAD_ELT_PTR64]] to i8*
// CHECK: [[ELT_VAL:%.+]] = load i8, i8* [[ELT_VOID]], align
// CHECK: store i8 [[ELT_VAL]], i8* [[SCRATCHPAD_ELT_PTR]], align
//
- // CHECK: [[OF:%.+]] = mul i[[SZ]] [[NUM_TEAMS]], 1
- // CHECK: [[POS1:%.+]] = add i[[SZ]] [[SCRATCHPAD]], [[OF]]
- // CHECK: [[POS2:%.+]] = sub i[[SZ]] [[POS1]], 1
- // CHECK: [[POS3:%.+]] = sdiv i[[SZ]] [[POS2]], 256
- // CHECK: [[POS4:%.+]] = add i[[SZ]] [[POS3]], 1
- // CHECK: [[SCRATCHPAD_NEXT:%.+]] = mul i[[SZ]] [[POS4]], 256
+ // CHECK: [[OF:%.+]] = mul nuw i[[SZ]] [[NUM_TEAMS]], 1
+ // CHECK: [[POS1:%.+]] = add nuw i[[SZ]] [[SCRATCHPAD]], [[OF]]
+ // CHECK: [[POS2:%.+]] = sub nuw i[[SZ]] [[POS1]], 1
+ // CHECK: [[POS3:%.+]] = udiv i[[SZ]] [[POS2]], 256
+ // CHECK: [[POS4:%.+]] = add nuw i[[SZ]] [[POS3]], 1
+ // CHECK: [[SCRATCHPAD_NEXT:%.+]] = mul nuw i[[SZ]] [[POS4]], 256
//
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 1
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
//
- // CHECK: [[P:%.+]] = mul i[[SZ]] 4, [[TEAM]]
- // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add i[[SZ]] [[SCRATCHPAD_NEXT]], [[P]]
+ // CHECK: [[P:%.+]] = mul nuw i[[SZ]] 4, [[TEAM]]
+ // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add nuw i[[SZ]] [[SCRATCHPAD_NEXT]], [[P]]
// CHECK: [[SCRATCHPAD_ELT_PTR_VOID:%.+]] = inttoptr i[[SZ]] [[SCRATCHPAD_ELT_PTR64]] to i8*
- // CHECK: [[SCRATCHPAD_ELT_PTR:%.+]] = bitcast i8* [[SCRATCHPAD_ELT_PTR_VOID]] to float*
// CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to float*
+ // CHECK: [[SCRATCHPAD_ELT_PTR:%.+]] = bitcast i8* [[SCRATCHPAD_ELT_PTR_VOID]] to float*
// CHECK: [[ELT_VAL:%.+]] = load float, float* [[ELT]], align
// CHECK: store float [[ELT_VAL]], float* [[SCRATCHPAD_ELT_PTR]], align
//
@@ -641,8 +631,8 @@ int bar(int n){
// CHECK: [[SHOULD_REDUCE:%.+]] = load i32, i32* {{.+}}, align
// CHECK: [[SCRATCHPAD:%.+]] = ptrtoint i8* [[SCRATCHPAD_PTR]] to i[[SZ]]
//
- // CHECK: [[P:%.+]] = mul i[[SZ]] 1, [[TEAM]]
- // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add i[[SZ]] [[SCRATCHPAD]], [[P]]
+ // CHECK: [[P:%.+]] = mul nuw i[[SZ]] 1, [[TEAM]]
+ // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add nuw i[[SZ]] [[SCRATCHPAD]], [[P]]
// CHECK: [[SCRATCHPAD_ELT_PTR_VOID:%.+]] = inttoptr i[[SZ]] [[SCRATCHPAD_ELT_PTR64]] to i8*
// CHECK: [[REMOTE_ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[REMOTE_RED_LIST]], i[[SZ]] 0, i[[SZ]] 0
@@ -650,15 +640,15 @@ int bar(int n){
// CHECK: store i8 [[REMOTE_ELT_VAL]], i8* [[REMOTE_ELT1]], align
// CHECK: store i8* [[REMOTE_ELT1]], i8** [[REMOTE_ELT_REF]], align
//
- // CHECK: [[OF:%.+]] = mul i[[SZ]] [[NUM_TEAMS]], 1
- // CHECK: [[POS1:%.+]] = add i[[SZ]] [[SCRATCHPAD]], [[OF]]
- // CHECK: [[POS2:%.+]] = sub i[[SZ]] [[POS1]], 1
- // CHECK: [[POS3:%.+]] = sdiv i[[SZ]] [[POS2]], 256
- // CHECK: [[POS4:%.+]] = add i[[SZ]] [[POS3]], 1
- // CHECK: [[SCRATCHPAD_NEXT:%.+]] = mul i[[SZ]] [[POS4]], 256
+ // CHECK: [[OF:%.+]] = mul nuw i[[SZ]] [[NUM_TEAMS]], 1
+ // CHECK: [[POS1:%.+]] = add nuw i[[SZ]] [[SCRATCHPAD]], [[OF]]
+ // CHECK: [[POS2:%.+]] = sub nuw i[[SZ]] [[POS1]], 1
+ // CHECK: [[POS3:%.+]] = udiv i[[SZ]] [[POS2]], 256
+ // CHECK: [[POS4:%.+]] = add nuw i[[SZ]] [[POS3]], 1
+ // CHECK: [[SCRATCHPAD_NEXT:%.+]] = mul nuw i[[SZ]] [[POS4]], 256
//
- // CHECK: [[P:%.+]] = mul i[[SZ]] 4, [[TEAM]]
- // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add i[[SZ]] [[SCRATCHPAD_NEXT]], [[P]]
+ // CHECK: [[P:%.+]] = mul nuw i[[SZ]] 4, [[TEAM]]
+ // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add nuw i[[SZ]] [[SCRATCHPAD_NEXT]], [[P]]
// CHECK: [[SCRATCHPAD_ELT_PTR_VOID:%.+]] = inttoptr i[[SZ]] [[SCRATCHPAD_ELT_PTR64]] to i8*
// CHECK: [[REMOTE_ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[REMOTE_RED_LIST]], i[[SZ]] 0, i[[SZ]] 1
@@ -668,7 +658,7 @@ int bar(int n){
// CHECK: [[REMOTE_ELT_PTR:%.+]] = bitcast float* [[REMOTE_ELT2]] to i8*
// CHECK: store i8* [[REMOTE_ELT_PTR]], i8** [[REMOTE_ELT_REF]], align
//
- // CHECK: [[REDUCE:%.+]] = icmp eq i32 [[SHOULD_REDUCE]], 1
+ // CHECK: [[REDUCE:%.+]] = icmp ne i32 [[SHOULD_REDUCE]], 0
// CHECK: br i1 [[REDUCE]], label {{%?}}[[DO_REDUCE:.+]], label {{%?}}[[REDUCE_ELSE:.+]]
//
// CHECK: [[DO_REDUCE]]
@@ -690,8 +680,8 @@ int bar(int n){
// CHECK: [[REMOTE_ELT_VOID:%.+]] = load i8*, i8** [[REMOTE_ELT_REF]],
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 1
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to float*
// CHECK: [[REMOTE_ELT:%.+]] = bitcast i8* [[REMOTE_ELT_VOID]] to float*
+ // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to float*
// CHECK: [[REMOTE_ELT_VAL:%.+]] = load float, float* [[REMOTE_ELT]], align
// CHECK: store float [[REMOTE_ELT_VAL]], float* [[ELT]], align
// CHECK: br label {{%?}}[[REDUCE_CONT]]
@@ -699,15 +689,6 @@ int bar(int n){
// CHECK: [[REDUCE_CONT]]
// CHECK: ret
-
-
-
-
-
-
-
-
-
// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l40}}_worker()
// CHECK: define {{.*}}void [[T3:@__omp_offloading_.+template.+l40]](
@@ -903,8 +884,8 @@ int bar(int n){
// CHECK: [[REMOTE_ELT_VOID:%.+]] = load i8*, i8** [[REMOTE_ELT_REF]],
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 0
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i32*
// CHECK: [[REMOTE_ELT:%.+]] = bitcast i8* [[REMOTE_ELT_VOID]] to i32*
+ // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i32*
// CHECK: [[REMOTE_ELT_VAL:%.+]] = load i32, i32* [[REMOTE_ELT]], align
// CHECK: store i32 [[REMOTE_ELT_VAL]], i32* [[ELT]], align
//
@@ -912,8 +893,8 @@ int bar(int n){
// CHECK: [[REMOTE_ELT_VOID:%.+]] = load i8*, i8** [[REMOTE_ELT_REF]],
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 1
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i16*
// CHECK: [[REMOTE_ELT:%.+]] = bitcast i8* [[REMOTE_ELT_VOID]] to i16*
+ // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i16*
// CHECK: [[REMOTE_ELT_VAL:%.+]] = load i16, i16* [[REMOTE_ELT]], align
// CHECK: store i16 [[REMOTE_ELT_VAL]], i16* [[ELT]], align
// CHECK: br label {{%?}}[[COPY_CONT:.+]]
@@ -937,10 +918,10 @@ int bar(int n){
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 0
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
// CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i32*
- // CHECK: [[ELT_VAL:%.+]] = load i32, i32* [[ELT]], align
//
// CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]]
// CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i32 addrspace([[SHARED_ADDRSPACE]])*
+ // CHECK: [[ELT_VAL:%.+]] = load i32, i32* [[ELT]], align
// CHECK: store i32 [[ELT_VAL]], i32 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: br label {{%?}}[[COPY_CONT:.+]]
//
@@ -960,10 +941,10 @@ int bar(int n){
// CHECK: [[DO_READ]]
// CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]]
// CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i32 addrspace([[SHARED_ADDRSPACE]])*
- // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load i32, i32 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 0
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
// CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i32*
+ // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load i32, i32 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: store i32 [[MEDIUM_ELT_VAL]], i32* [[ELT]], align
// CHECK: br label {{%?}}[[READ_CONT:.+]]
//
@@ -979,10 +960,10 @@ int bar(int n){
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 1
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
// CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i16*
- // CHECK: [[ELT_VAL:%.+]] = load i16, i16* [[ELT]], align
//
// CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]]
// CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i16 addrspace([[SHARED_ADDRSPACE]])*
+ // CHECK: [[ELT_VAL:%.+]] = load i16, i16* [[ELT]], align
// CHECK: store i16 [[ELT_VAL]], i16 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: br label {{%?}}[[COPY_CONT:.+]]
//
@@ -1002,10 +983,10 @@ int bar(int n){
// CHECK: [[DO_READ]]
// CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]]
// CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i16 addrspace([[SHARED_ADDRSPACE]])*
- // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load i16, i16 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 1
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
// CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i16*
+ // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load i16, i16 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: store i16 [[MEDIUM_ELT_VAL]], i16* [[ELT]], align
// CHECK: br label {{%?}}[[READ_CONT:.+]]
//
@@ -1032,29 +1013,29 @@ int bar(int n){
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 0
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
//
- // CHECK: [[P:%.+]] = mul i[[SZ]] 4, [[TEAM]]
- // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add i[[SZ]] [[SCRATCHPAD]], [[P]]
+ // CHECK: [[P:%.+]] = mul nuw i[[SZ]] 4, [[TEAM]]
+ // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add nuw i[[SZ]] [[SCRATCHPAD]], [[P]]
// CHECK: [[SCRATCHPAD_ELT_PTR_VOID:%.+]] = inttoptr i[[SZ]] [[SCRATCHPAD_ELT_PTR64]] to i8*
- // CHECK: [[SCRATCHPAD_ELT_PTR:%.+]] = bitcast i8* [[SCRATCHPAD_ELT_PTR_VOID]] to i32*
// CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i32*
+ // CHECK: [[SCRATCHPAD_ELT_PTR:%.+]] = bitcast i8* [[SCRATCHPAD_ELT_PTR_VOID]] to i32*
// CHECK: [[ELT_VAL:%.+]] = load i32, i32* [[ELT]], align
// CHECK: store i32 [[ELT_VAL]], i32* [[SCRATCHPAD_ELT_PTR]], align
//
- // CHECK: [[OF:%.+]] = mul i[[SZ]] [[NUM_TEAMS]], 4
- // CHECK: [[POS1:%.+]] = add i[[SZ]] [[SCRATCHPAD]], [[OF]]
- // CHECK: [[POS2:%.+]] = sub i[[SZ]] [[POS1]], 1
- // CHECK: [[POS3:%.+]] = sdiv i[[SZ]] [[POS2]], 256
- // CHECK: [[POS4:%.+]] = add i[[SZ]] [[POS3]], 1
- // CHECK: [[SCRATCHPAD_NEXT:%.+]] = mul i[[SZ]] [[POS4]], 256
+ // CHECK: [[OF:%.+]] = mul nuw i[[SZ]] [[NUM_TEAMS]], 4
+ // CHECK: [[POS1:%.+]] = add nuw i[[SZ]] [[SCRATCHPAD]], [[OF]]
+ // CHECK: [[POS2:%.+]] = sub nuw i[[SZ]] [[POS1]], 1
+ // CHECK: [[POS3:%.+]] = udiv i[[SZ]] [[POS2]], 256
+ // CHECK: [[POS4:%.+]] = add nuw i[[SZ]] [[POS3]], 1
+ // CHECK: [[SCRATCHPAD_NEXT:%.+]] = mul nuw i[[SZ]] [[POS4]], 256
//
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 1
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
//
- // CHECK: [[P:%.+]] = mul i[[SZ]] 2, [[TEAM]]
- // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add i[[SZ]] [[SCRATCHPAD_NEXT]], [[P]]
+ // CHECK: [[P:%.+]] = mul nuw i[[SZ]] 2, [[TEAM]]
+ // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add nuw i[[SZ]] [[SCRATCHPAD_NEXT]], [[P]]
// CHECK: [[SCRATCHPAD_ELT_PTR_VOID:%.+]] = inttoptr i[[SZ]] [[SCRATCHPAD_ELT_PTR64]] to i8*
- // CHECK: [[SCRATCHPAD_ELT_PTR:%.+]] = bitcast i8* [[SCRATCHPAD_ELT_PTR_VOID]] to i16*
// CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i16*
+ // CHECK: [[SCRATCHPAD_ELT_PTR:%.+]] = bitcast i8* [[SCRATCHPAD_ELT_PTR_VOID]] to i16*
// CHECK: [[ELT_VAL:%.+]] = load i16, i16* [[ELT]], align
// CHECK: store i16 [[ELT_VAL]], i16* [[SCRATCHPAD_ELT_PTR]], align
//
@@ -1077,8 +1058,8 @@ int bar(int n){
// CHECK: [[SHOULD_REDUCE:%.+]] = load i32, i32* {{.+}}, align
// CHECK: [[SCRATCHPAD:%.+]] = ptrtoint i8* [[SCRATCHPAD_PTR]] to i[[SZ]]
//
- // CHECK: [[P:%.+]] = mul i[[SZ]] 4, [[TEAM]]
- // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add i[[SZ]] [[SCRATCHPAD]], [[P]]
+ // CHECK: [[P:%.+]] = mul nuw i[[SZ]] 4, [[TEAM]]
+ // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add nuw i[[SZ]] [[SCRATCHPAD]], [[P]]
// CHECK: [[SCRATCHPAD_ELT_PTR_VOID:%.+]] = inttoptr i[[SZ]] [[SCRATCHPAD_ELT_PTR64]] to i8*
// CHECK: [[REMOTE_ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[REMOTE_RED_LIST]], i[[SZ]] 0, i[[SZ]] 0
@@ -1088,15 +1069,15 @@ int bar(int n){
// CHECK: [[REMOTE_ELT1_PTR:%.+]] = bitcast i32* [[REMOTE_ELT1]] to i8*
// CHECK: store i8* [[REMOTE_ELT1_PTR]], i8** [[REMOTE_ELT_REF]], align
//
- // CHECK: [[OF:%.+]] = mul i[[SZ]] [[NUM_TEAMS]], 4
- // CHECK: [[POS1:%.+]] = add i[[SZ]] [[SCRATCHPAD]], [[OF]]
- // CHECK: [[POS2:%.+]] = sub i[[SZ]] [[POS1]], 1
- // CHECK: [[POS3:%.+]] = sdiv i[[SZ]] [[POS2]], 256
- // CHECK: [[POS4:%.+]] = add i[[SZ]] [[POS3]], 1
- // CHECK: [[SCRATCHPAD_NEXT:%.+]] = mul i[[SZ]] [[POS4]], 256
+ // CHECK: [[OF:%.+]] = mul nuw i[[SZ]] [[NUM_TEAMS]], 4
+ // CHECK: [[POS1:%.+]] = add nuw i[[SZ]] [[SCRATCHPAD]], [[OF]]
+ // CHECK: [[POS2:%.+]] = sub nuw i[[SZ]] [[POS1]], 1
+ // CHECK: [[POS3:%.+]] = udiv i[[SZ]] [[POS2]], 256
+ // CHECK: [[POS4:%.+]] = add nuw i[[SZ]] [[POS3]], 1
+ // CHECK: [[SCRATCHPAD_NEXT:%.+]] = mul nuw i[[SZ]] [[POS4]], 256
//
- // CHECK: [[P:%.+]] = mul i[[SZ]] 2, [[TEAM]]
- // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add i[[SZ]] [[SCRATCHPAD_NEXT]], [[P]]
+ // CHECK: [[P:%.+]] = mul nuw i[[SZ]] 2, [[TEAM]]
+ // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add nuw i[[SZ]] [[SCRATCHPAD_NEXT]], [[P]]
// CHECK: [[SCRATCHPAD_ELT_PTR_VOID:%.+]] = inttoptr i[[SZ]] [[SCRATCHPAD_ELT_PTR64]] to i8*
// CHECK: [[REMOTE_ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[REMOTE_RED_LIST]], i[[SZ]] 0, i[[SZ]] 1
@@ -1106,7 +1087,7 @@ int bar(int n){
// CHECK: [[REMOTE_ELT_PTR:%.+]] = bitcast i16* [[REMOTE_ELT2]] to i8*
// CHECK: store i8* [[REMOTE_ELT_PTR]], i8** [[REMOTE_ELT_REF]], align
//
- // CHECK: [[REDUCE:%.+]] = icmp eq i32 [[SHOULD_REDUCE]], 1
+ // CHECK: [[REDUCE:%.+]] = icmp ne i32 [[SHOULD_REDUCE]], 0
// CHECK: br i1 [[REDUCE]], label {{%?}}[[DO_REDUCE:.+]], label {{%?}}[[REDUCE_ELSE:.+]]
//
// CHECK: [[DO_REDUCE]]
@@ -1121,8 +1102,8 @@ int bar(int n){
// CHECK: [[REMOTE_ELT_VOID:%.+]] = load i8*, i8** [[REMOTE_ELT_REF]],
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 0
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i32*
// CHECK: [[REMOTE_ELT:%.+]] = bitcast i8* [[REMOTE_ELT_VOID]] to i32*
+ // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i32*
// CHECK: [[REMOTE_ELT_VAL:%.+]] = load i32, i32* [[REMOTE_ELT]], align
// CHECK: store i32 [[REMOTE_ELT_VAL]], i32* [[ELT]], align
//
@@ -1130,8 +1111,8 @@ int bar(int n){
// CHECK: [[REMOTE_ELT_VOID:%.+]] = load i8*, i8** [[REMOTE_ELT_REF]],
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 1
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i16*
// CHECK: [[REMOTE_ELT:%.+]] = bitcast i8* [[REMOTE_ELT_VOID]] to i16*
+ // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i16*
// CHECK: [[REMOTE_ELT_VAL:%.+]] = load i16, i16* [[REMOTE_ELT]], align
// CHECK: store i16 [[REMOTE_ELT_VAL]], i16* [[ELT]], align
// CHECK: br label {{%?}}[[REDUCE_CONT]]
diff --git a/test/OpenMP/openmp_check.cpp b/test/OpenMP/openmp_check.cpp
index d46213a90e9f..cd4706b57e44 100644
--- a/test/OpenMP/openmp_check.cpp
+++ b/test/OpenMP/openmp_check.cpp
@@ -2,7 +2,16 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -std=c++11 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+#define p _Pragma("omp parallel")
+
int nested(int a) {
+#pragma omp parallel p // expected-error {{unexpected OpenMP directive}}
+ ++a;
#pragma omp parallel
++a;
@@ -11,8 +20,6 @@ int nested(int a) {
// expected-warning@-2 {{'auto' type specifier is a C++11 extension}}
// expected-error@-3 {{expected expression}}
// expected-error@-4 {{expected ';' at end of declaration}}
-#else
- // expected-no-diagnostics
#endif
#pragma omp parallel
diff --git a/test/OpenMP/openmp_common.c b/test/OpenMP/openmp_common.c
index ed55796b3374..feeefc4820ce 100644
--- a/test/OpenMP/openmp_common.c
+++ b/test/OpenMP/openmp_common.c
@@ -1,5 +1,8 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
#pragma omp // expected-error {{expected an OpenMP directive}}
#pragma omp unknown_directive // expected-error {{expected an OpenMP directive}}
diff --git a/test/OpenMP/openmp_offload_codegen.cpp b/test/OpenMP/openmp_offload_codegen.cpp
index f89bccf3b552..fff50133aa9c 100644
--- a/test/OpenMP/openmp_offload_codegen.cpp
+++ b/test/OpenMP/openmp_offload_codegen.cpp
@@ -1,12 +1,18 @@
// Test device for mapping codegen.
///==========================================================================///
-// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -S -emit-llvm %s -o - 2>&1 \
-// RUN: | FileCheck -check-prefix=CK1 %s
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -S -emit-llvm %s -o - 2>&1 | FileCheck -check-prefix=CK1 %s
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -S -emit-llvm %s -o - 2>&1 | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix CK1-DEVICE
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifdef CK1
@@ -33,4 +39,4 @@ void target_maps_parallel_integer(int a){
// CK1: [[GEPOPARG:%.+]] = getelementptr inbounds {{.*}}
// CK1: call {{.*}}tgt_target({{.*}}i8** [[GEPOBPARG]], i8** [[GEPOPARG]]
-#endif \ No newline at end of file
+#endif
diff --git a/test/OpenMP/openmp_seh.c b/test/OpenMP/openmp_seh.c
index 74dccec125e3..0bdd07947889 100644
--- a/test/OpenMP/openmp_seh.c
+++ b/test/OpenMP/openmp_seh.c
@@ -1,4 +1,7 @@
// RUN: %clang_cc1 -verify -triple x86_64-pc-windows-msvc19.0.0 -fopenmp -fms-compatibility -x c++ -emit-llvm %s -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -triple x86_64-pc-windows-msvc19.0.0 -fopenmp-simd -fms-compatibility -x c++ -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
// REQUIRES: x86-registered-target
extern "C" {
diff --git a/test/OpenMP/openmp_win_codegen.cpp b/test/OpenMP/openmp_win_codegen.cpp
index 45b2c185cb8f..289f05896644 100644
--- a/test/OpenMP/openmp_win_codegen.cpp
+++ b/test/OpenMP/openmp_win_codegen.cpp
@@ -1,5 +1,8 @@
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-pc-windows-msvc18.0.0 -std=c++11 -fms-compatibility-version=18 -fms-extensions -emit-llvm %s -fexceptions -fcxx-exceptions -o - -O1 | FileCheck %s
-// REQUIRES: x86-registered-target
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-pc-windows-msvc18.0.0 -std=c++11 -fms-compatibility-version=18 -fms-extensions -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-pc-windows-msvc18.0.0 -std=c++11 -fms-compatibility-version=18 -fms-extensions -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
void foo();
@@ -30,7 +33,7 @@ struct Test {
int main() {
// CHECK: call void @{{.+}}main
Test::main();
- // CHECK: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* {{.*}}@0, i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* [[OUTLINED:@.+]] to void (i32*, i32*, ...)*))
+ // CHECK: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* {{.*}}@0, i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* [[OUTLINED:@.+]] to void (i32*, i32*, ...)*))
#pragma omp parallel
{
try {
@@ -47,15 +50,21 @@ int main() {
}
// CHECK: define internal void [[OUTLINED]](
-// CHECK: [[GID:%.+]] = {{.*}}call i32 @__kmpc_global_thread_num(%ident_t* {{.*}}@0)
+// CHECK: [[GID:%.+]] = {{.*}}call i32 @__kmpc_global_thread_num(%struct.ident_t* {{.*}}@0)
// CHECK: invoke void @{{.+}}foo
-// CHECK: catchswitch within
-// CHECK: catchpad within
-// CHECK: call void @__kmpc_critical(%ident_t* {{.*}}@0, i32 [[GID]],
+// CHECK: [[CATCHSWITCH:%.+]] = catchswitch within none
+// CHECK: [[CATCHPAD:%.+]] = catchpad within [[CATCHSWITCH]]
+// CHECK: call void @__kmpc_critical(%struct.ident_t* {{.*}}@0, i32 [[GID]],
// CHECK: invoke void @{{.+}}bar
-// CHECK: call void @__kmpc_end_critical(%ident_t* {{.*}}@0, i32 [[GID]],
-// CHECK: catchret from
-// CHECK: cleanuppad within
-// CHECK: call void @__kmpc_end_critical(%ident_t* {{.*}}@0, i32 [[GID]],
-// CHECK: cleanupret from
-
+// CHECK: call void @__kmpc_end_critical(%struct.ident_t* {{.*}}@0, i32 [[GID]],
+// CHECK: catchret from [[CATCHPAD]] to
+// CHECK: cleanuppad within [[CATCHPAD]] []
+// CHECK-NEXT: call void @__kmpc_end_critical(%struct.ident_t* {{.*}}@0, i32 [[GID]],
+// CHECK-NEXT: cleanupret from {{.*}} unwind label %[[CATCHTERM:[^ ]+]]
+// CHECK: cleanuppad within none []
+// CHECK-NEXT: call void @"?terminate@@YAXXZ"() #5 [ "funclet"(token %{{.*}}) ]
+// CHECK-NEXT: unreachable
+// CHECK: [[CATCHTERM]]
+// CHECK-NEXT: cleanuppad within [[CATCHPAD]] []
+// CHECK-NEXT: call void @"?terminate@@YAXXZ"() #5 [ "funclet"(token %{{.*}}) ]
+// CHECK-NEXT: unreachable
diff --git a/test/OpenMP/option_warn.c b/test/OpenMP/option_warn.c
index ddec8e113e77..d9be164aad77 100644
--- a/test/OpenMP/option_warn.c
+++ b/test/OpenMP/option_warn.c
@@ -1,5 +1,8 @@
// RUN: %clang_cc1 -verify -Wsource-uses-openmp -o - %s
+// RUN: %clang_cc1 -verify -Wsource-uses-openmp -o - %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
int a;
#pragma omp threadprivate(a,b) // expected-warning {{unexpected '#pragma omp ...' in program}}
#pragma omp parallel
diff --git a/test/OpenMP/ordered_ast_print.cpp b/test/OpenMP/ordered_ast_print.cpp
index c7baa9ce0421..f36afab8b207 100644
--- a/test/OpenMP/ordered_ast_print.cpp
+++ b/test/OpenMP/ordered_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -54,7 +58,7 @@ T tmain (T argc) {
// CHECK: static T a;
// CHECK-NEXT: #pragma omp for ordered
// CHECK-NEXT: for (int i = 0; i < argc; ++i)
-// CHECK-NEXT: #pragma omp ordered
+// CHECK-NEXT: #pragma omp ordered{{$}}
// CHECK-NEXT: {
// CHECK-NEXT: a = 2;
// CHECK-NEXT: }
diff --git a/test/OpenMP/ordered_codegen.cpp b/test/OpenMP/ordered_codegen.cpp
index af6a8722438d..977aba9d4555 100644
--- a/test/OpenMP/ordered_codegen.cpp
+++ b/test/OpenMP/ordered_codegen.cpp
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/ordered_doacross_codegen.c b/test/OpenMP/ordered_doacross_codegen.c
new file mode 100644
index 000000000000..c12df2638f8f
--- /dev/null
+++ b/test/OpenMP/ordered_doacross_codegen.c
@@ -0,0 +1,61 @@
+// RUN: %clang_cc1 -verify -fopenmp -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -triple x86_64-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -triple x86_64-unknown-unknown -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -triple x86_64-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -triple x86_64-unknown-unknown -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+// CHECK: [[KMP_DIM:%.+]] = type { i64, i64, i64 }
+extern int n;
+int a[10], b[10], c[10], d[10];
+void foo();
+
+// CHECK-LABEL: @main()
+int main() {
+ int i;
+// CHECK: [[DIMS:%.+]] = alloca [[KMP_DIM]],
+// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num([[IDENT:%.+]])
+// CHECK: icmp
+// CHECK-NEXT: br i1 %
+// CHECK: [[CAST:%.+]] = bitcast [[KMP_DIM]]* [[DIMS]] to i8*
+// CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 [[CAST]], i8 0, i64 24, i1 false)
+// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIMS]], i32 0, i32 1
+// CHECK: store i64 %{{.+}}, i64* %
+// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIMS]], i32 0, i32 2
+// CHECK: store i64 1, i64* %
+// CHECK: [[CAST:%.+]] = bitcast [[KMP_DIM]]* [[DIMS]] to i8*
+// CHECK: call void @__kmpc_doacross_init([[IDENT]], i32 [[GTID]], i32 1, i8* [[CAST]])
+// CHECK: call void @__kmpc_for_static_init_4(
+#pragma omp for ordered(1)
+ for (i = 0; i < n; ++i) {
+ a[i] = b[i] + 1;
+ foo();
+// CHECK: call void [[FOO:.+]](
+// CHECK: load i32, i32* [[CNT:%.+]],
+// CHECK-NEXT: sext i32 %{{.+}} to i64
+// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP:%.+]],
+// CHECK-NEXT: call void @__kmpc_doacross_post([[IDENT]], i32 [[GTID]], i64* [[TMP]])
+#pragma omp ordered depend(source)
+ c[i] = c[i] + 1;
+ foo();
+// CHECK: call void [[FOO]]
+// CHECK: load i32, i32* [[CNT]],
+// CHECK-NEXT: sub nsw i32 %{{.+}}, 2
+// CHECK-NEXT: sext i32 %{{.+}} to i64
+// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP:%.+]],
+// CHECK-NEXT: call void @__kmpc_doacross_wait([[IDENT]], i32 [[GTID]], i64* [[TMP]])
+#pragma omp ordered depend(sink : i - 2)
+ d[i] = a[i - 2];
+ }
+ // CHECK: call void @__kmpc_for_static_fini(
+ // CHECK: call void @__kmpc_doacross_fini([[IDENT]], i32 [[GTID]])
+ // CHECK: ret i32 0
+ return 0;
+}
+#endif // HEADER
diff --git a/test/OpenMP/ordered_doacross_codegen.cpp b/test/OpenMP/ordered_doacross_codegen.cpp
index 28b02c35358b..60b0353b711e 100644
--- a/test/OpenMP/ordered_doacross_codegen.cpp
+++ b/test/OpenMP/ordered_doacross_codegen.cpp
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
@@ -19,7 +24,7 @@ int main() {
// CHECK: icmp
// CHECK-NEXT: br i1 %
// CHECK: [[CAST:%.+]] = bitcast [[KMP_DIM]]* [[DIMS]] to i8*
-// CHECK: call void @llvm.memset.p0i8.i64(i8* [[CAST]], i8 0, i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 [[CAST]], i8 0, i64 24, i1 false)
// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIMS]], i32 0, i32 1
// CHECK: store i64 %{{.+}}, i64* %
// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIMS]], i32 0, i32 2
@@ -76,7 +81,7 @@ struct TestStruct {
// CHECK: icmp
// CHECK-NEXT: br i1 %
// CHECK: [[CAST:%.+]] = bitcast [[KMP_DIM]]* [[DIMS]] to i8*
-// CHECK: call void @llvm.memset.p0i8.i64(i8* [[CAST]], i8 0, i64 24, i32 8, i1 false)
+// CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 [[CAST]], i8 0, i64 24, i1 false)
// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIMS]], i32 0, i32 1
// CHECK: store i64 %{{.+}}, i64* %
// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIMS]], i32 0, i32 2
diff --git a/test/OpenMP/ordered_messages.cpp b/test/OpenMP/ordered_messages.cpp
index 2e3d55ca8370..43ac40efe640 100644
--- a/test/OpenMP/ordered_messages.cpp
+++ b/test/OpenMP/ordered_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -std=c++98 -o - %s
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -std=c++11 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -std=c++98 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -std=c++11 -o - %s
+
int foo();
template <class T>
@@ -134,6 +138,8 @@ T foo() {
#pragma omp ordered depend(source) depend(sink : i-0, j+sizeof(T)) // expected-error {{'depend(sink:vec)' clauses cannot be mixed with 'depend(source)' clause}}
}
}
+#pragma omp ordered depend(source) // expected-error {{'ordered' directive with 'depend' clause cannot be closely nested inside ordered region without specified parameter}}
+#pragma omp ordered depend(sink:k) // expected-error {{'ordered' directive with 'depend' clause cannot be closely nested inside ordered region without specified parameter}}
return T();
}
diff --git a/test/OpenMP/parallel_ast_print.cpp b/test/OpenMP/parallel_ast_print.cpp
index 09141db5841f..19ebb7048330 100644
--- a/test/OpenMP/parallel_ast_print.cpp
+++ b/test/OpenMP/parallel_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -158,7 +162,7 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: static T a;
// CHECK-NEXT: S<T> s;
// CHECK-NEXT: T arr[C][10], arr1[C];
-// CHECK-NEXT: #pragma omp parallel
+// CHECK-NEXT: #pragma omp parallel{{$}}
// CHECK-NEXT: a = 2;
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(C) copyin(S<T>::TS,thrp) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:C][0:10])
// CHECK-NEXT: foo()
diff --git a/test/OpenMP/parallel_codegen.cpp b/test/OpenMP/parallel_codegen.cpp
index 77e8efded68b..0ecca8de64fe 100644
--- a/test/OpenMP/parallel_codegen.cpp
+++ b/test/OpenMP/parallel_codegen.cpp
@@ -1,15 +1,20 @@
// RUN: %clang_cc1 -verify -fopenmp -x c++ -emit-llvm %s -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -debug-info-kind=limited -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix=CHECK-DEBUG %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -emit-llvm %s -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -debug-info-kind=limited -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
-// CHECK-DAG: %ident_t = type { i32, i32, i32, i32, i8* }
+// CHECK-DAG: %struct.ident_t = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr constant %ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
-// CHECK-DEBUG-DAG: %ident_t = type { i32, i32, i32, i32, i8* }
+// CHECK-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DEBUG-DAG: %struct.ident_t = type { i32, i32, i32, i32, i8* }
// CHECK-DEBUG-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DEBUG-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr constant %ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DEBUG-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
// CHECK-DEBUG-DAG: [[LOC1:@.+]] = private unnamed_addr constant [{{.+}} x i8] c";{{.*}}parallel_codegen.cpp;main;[[@LINE+15]];9;;\00"
// CHECK-DEBUG-DAG: [[LOC2:@.+]] = private unnamed_addr constant [{{.+}} x i8] c";{{.*}}parallel_codegen.cpp;tmain;[[@LINE+7]];9;;\00"
@@ -33,21 +38,21 @@ int main (int argc, char **argv) {
// CHECK-LABEL: define {{[a-z\_\b]*[ ]?i32}} @main({{i32[ ]?[a-z]*}} %argc, i8** %argv)
// CHECK: store i32 %argc, i32* [[ARGC_ADDR:%.+]],
// CHECK: [[VLA:%.+]] = alloca i32, i{{[0-9]+}} [[VLA_SIZE:%[^,]+]],
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC_2]], i32 2, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i{{[0-9]+}}, i32*)* [[OMP_OUTLINED:@.+]] to void (i32*, i32*, ...)*), i{{[0-9]+}} [[VLA_SIZE]], i32* [[VLA]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC_2]], i32 2, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i{{[0-9]+}}, i32*)* [[OMP_OUTLINED:@.+]] to void (i32*, i32*, ...)*), i{{[0-9]+}} [[VLA_SIZE]], i32* [[VLA]])
// CHECK-NEXT: [[ARGV:%.+]] = load i8**, i8*** {{%[a-z0-9.]+}}
// CHECK-NEXT: [[RET:%.+]] = call {{[a-z\_\b]*[ ]?i32}} [[TMAIN:@.+tmain.+]](i8** [[ARGV]])
// CHECK: ret i32
// CHECK-NEXT: }
// CHECK-DEBUG-LABEL: define i32 @main(i32 %argc, i8** %argv)
-// CHECK-DEBUG: [[LOC_2_ADDR:%.+]] = alloca %ident_t
-// CHECK-DEBUG: [[KMPC_LOC_VOIDPTR:%.+]] = bitcast %ident_t* [[LOC_2_ADDR]] to i8*
-// CHECK-DEBUG-NEXT: [[KMPC_DEFAULT_LOC_VOIDPTR:%.+]] = bitcast %ident_t* [[DEF_LOC_2]] to i8*
-// CHECK-DEBUG-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[KMPC_LOC_VOIDPTR]], i8* [[KMPC_DEFAULT_LOC_VOIDPTR]], i64 24, i32 8, i1 false)
+// CHECK-DEBUG: [[LOC_2_ADDR:%.+]] = alloca %struct.ident_t
+// CHECK-DEBUG: [[KMPC_LOC_VOIDPTR:%.+]] = bitcast %struct.ident_t* [[LOC_2_ADDR]] to i8*
+// CHECK-DEBUG-NEXT: [[KMPC_DEFAULT_LOC_VOIDPTR:%.+]] = bitcast %struct.ident_t* [[DEF_LOC_2]] to i8*
+// CHECK-DEBUG-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[KMPC_LOC_VOIDPTR]], i8* align 8 [[KMPC_DEFAULT_LOC_VOIDPTR]], i64 24, i1 false)
// CHECK-DEBUG: store i32 %argc, i32* [[ARGC_ADDR:%.+]],
// CHECK-DEBUG: [[VLA:%.+]] = alloca i32, i64 [[VLA_SIZE:%[^,]+]],
-// CHECK-DEBUG: [[KMPC_LOC_PSOURCE_REF:%.+]] = getelementptr inbounds %ident_t, %ident_t* [[LOC_2_ADDR]], i32 0, i32 4
+// CHECK-DEBUG: [[KMPC_LOC_PSOURCE_REF:%.+]] = getelementptr inbounds %struct.ident_t, %struct.ident_t* [[LOC_2_ADDR]], i32 0, i32 4
// CHECK-DEBUG-NEXT: store i8* getelementptr inbounds ([{{.+}} x i8], [{{.+}} x i8]* [[LOC1]], i32 0, i32 0), i8** [[KMPC_LOC_PSOURCE_REF]]
-// CHECK-DEBUG: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[LOC_2_ADDR]], i32 2, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i64, i32*)* [[OMP_OUTLINED:@.+]] to void (i32*, i32*, ...)*), i64 [[VLA_SIZE]], i32* [[VLA]])
+// CHECK-DEBUG: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[LOC_2_ADDR]], i32 2, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i64, i32*)* [[OMP_OUTLINED:@.+]] to void (i32*, i32*, ...)*), i64 [[VLA_SIZE]], i32* [[VLA]])
// CHECK-DEBUG-NEXT: [[ARGV:%.+]] = load i8**, i8*** {{%[a-z0-9.]+}}
// CHECK-DEBUG-NEXT: [[RET:%.+]] = call i32 [[TMAIN:@.+tmain.+]](i8** [[ARGV]])
// CHECK-DEBUG: ret i32
@@ -77,26 +82,26 @@ int main (int argc, char **argv) {
// CHECK-DEBUG-NEXT: }
// CHECK-DAG: define linkonce_odr {{.*}}void [[FOO]]({{i32[ ]?[a-z]*}} %argc)
-// CHECK-DAG: declare {{.*}}void @__kmpc_fork_call(%ident_t*, i32, void (i32*, i32*, ...)*, ...)
+// CHECK-DAG: declare {{.*}}void @__kmpc_fork_call(%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...)
// CHECK-DEBUG-DAG: define linkonce_odr void [[FOO]](i32 %argc)
-// CHECK-DEBUG-DAG: declare void @__kmpc_fork_call(%ident_t*, i32, void (i32*, i32*, ...)*, ...)
+// CHECK-DEBUG-DAG: declare void @__kmpc_fork_call(%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...)
// CHECK-DEBUG-DAG: define internal void [[OMP_OUTLINED]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i64 [[VLA_SIZE:%.+]], i32* {{.+}} [[VLA_ADDR:%[^)]+]])
// CHECK-DEBUG-DAG: call void [[OMP_OUTLINED_DEBUG]]
// CHECK: define linkonce_odr {{[a-z\_\b]*[ ]?i32}} [[TMAIN]](i8** %argc)
// CHECK: store i8** %argc, i8*** [[ARGC_ADDR:%.+]],
-// CHECK-NEXT: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC_2]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i8***)* [[OMP_OUTLINED:@.+]] to void (i32*, i32*, ...)*), i8*** [[ARGC_ADDR]])
+// CHECK-NEXT: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC_2]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i8***)* [[OMP_OUTLINED:@.+]] to void (i32*, i32*, ...)*), i8*** [[ARGC_ADDR]])
// CHECK-NEXT: ret i32 0
// CHECK-NEXT: }
// CHECK-DEBUG: define linkonce_odr i32 [[TMAIN]](i8** %argc)
-// CHECK-DEBUG-DAG: [[LOC_2_ADDR:%.+]] = alloca %ident_t
-// CHECK-DEBUG: [[KMPC_LOC_VOIDPTR:%.+]] = bitcast %ident_t* [[LOC_2_ADDR]] to i8*
-// CHECK-DEBUG-NEXT: [[KMPC_DEFAULT_LOC_VOIDPTR:%.+]] = bitcast %ident_t* [[DEF_LOC_2]] to i8*
-// CHECK-DEBUG-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[KMPC_LOC_VOIDPTR]], i8* [[KMPC_DEFAULT_LOC_VOIDPTR]], i64 24, i32 8, i1 false)
+// CHECK-DEBUG-DAG: [[LOC_2_ADDR:%.+]] = alloca %struct.ident_t
+// CHECK-DEBUG: [[KMPC_LOC_VOIDPTR:%.+]] = bitcast %struct.ident_t* [[LOC_2_ADDR]] to i8*
+// CHECK-DEBUG-NEXT: [[KMPC_DEFAULT_LOC_VOIDPTR:%.+]] = bitcast %struct.ident_t* [[DEF_LOC_2]] to i8*
+// CHECK-DEBUG-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[KMPC_LOC_VOIDPTR]], i8* align 8 [[KMPC_DEFAULT_LOC_VOIDPTR]], i64 24, i1 false)
// CHECK-DEBUG-NEXT: store i8** %argc, i8*** [[ARGC_ADDR:%.+]],
-// CHECK-DEBUG: [[KMPC_LOC_PSOURCE_REF:%.+]] = getelementptr inbounds %ident_t, %ident_t* [[LOC_2_ADDR]], i32 0, i32 4
+// CHECK-DEBUG: [[KMPC_LOC_PSOURCE_REF:%.+]] = getelementptr inbounds %struct.ident_t, %struct.ident_t* [[LOC_2_ADDR]], i32 0, i32 4
// CHECK-DEBUG-NEXT: store i8* getelementptr inbounds ([{{.+}} x i8], [{{.+}} x i8]* [[LOC2]], i32 0, i32 0), i8** [[KMPC_LOC_PSOURCE_REF]]
-// CHECK-DEBUG-NEXT: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[LOC_2_ADDR]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i8***)* [[OMP_OUTLINED:@.+]] to void (i32*, i32*, ...)*), i8*** [[ARGC_ADDR]])
+// CHECK-DEBUG-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[LOC_2_ADDR]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i8***)* [[OMP_OUTLINED:@.+]] to void (i32*, i32*, ...)*), i8*** [[ARGC_ADDR]])
// CHECK-DEBUG-NEXT: ret i32 0
// CHECK-DEBUG-NEXT: }
diff --git a/test/OpenMP/parallel_copyin_codegen.cpp b/test/OpenMP/parallel_copyin_codegen.cpp
index 49e7b3fd618b..3d33aa2cfe0a 100644
--- a/test/OpenMP/parallel_copyin_codegen.cpp
+++ b/test/OpenMP/parallel_copyin_codegen.cpp
@@ -5,12 +5,28 @@
// RUN: %clang_cc1 -verify -fopenmp -fnoopenmp-use-tls -x c++ -fblocks -DBLOCKS -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
// RUN: %clang_cc1 -verify -fopenmp -fnoopenmp-use-tls -x c++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=ARRAY %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fnoopenmp-use-tls -x c++ -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fnoopenmp-use-tls -x c++ -std=c++11 -triple %itanium_abi_triple -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fnoopenmp-use-tls -x c++ -triple %itanium_abi_triple -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fnoopenmp-use-tls -x c++ -std=c++11 -DLAMBDA -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fnoopenmp-use-tls -x c++ -fblocks -DBLOCKS -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fnoopenmp-use-tls -x c++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s -check-prefix=TLS-CHECK
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple %itanium_abi_triple -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple %itanium_abi_triple -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s -check-prefix=TLS-CHECK
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck -check-prefix=TLS-LAMBDA %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck -check-prefix=TLS-BLOCKS %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DARRAY -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck -check-prefix=TLS-ARRAY %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple %itanium_abi_triple -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple %itanium_abi_triple -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DLAMBDA -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -fblocks -DBLOCKS -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DARRAY -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef ARRAY
#ifndef HEADER
@@ -40,18 +56,18 @@ struct S {
// CHECK-DAG: [[VEC:@.+]] = internal global [2 x i{{[0-9]+}}] [i{{[0-9]+}} 1, i{{[0-9]+}} 2],
// CHECK-DAG: [[S_ARR:@.+]] = internal global [2 x [[S_FLOAT_TY]]] zeroinitializer,
// CHECK-DAG: [[VAR:@.+]] = internal global [[S_FLOAT_TY]] zeroinitializer,
-// CHECK-DAG: [[TMAIN_T_VAR:@.+]] = linkonce_odr global i{{[0-9]+}} 333,
-// CHECK-DAG: [[TMAIN_VEC:@.+]] = linkonce_odr global [2 x i{{[0-9]+}}] [i{{[0-9]+}} 3, i{{[0-9]+}} 3],
-// CHECK-DAG: [[TMAIN_S_ARR:@.+]] = linkonce_odr global [2 x [[S_INT_TY]]] zeroinitializer,
-// CHECK-DAG: [[TMAIN_VAR:@.+]] = linkonce_odr global [[S_INT_TY]] zeroinitializer,
+// CHECK-DAG: [[TMAIN_T_VAR:@.+]] = linkonce_odr {{(dso_local )?}}global i{{[0-9]+}} 333,
+// CHECK-DAG: [[TMAIN_VEC:@.+]] = linkonce_odr {{(dso_local )?}}global [2 x i{{[0-9]+}}] [i{{[0-9]+}} 3, i{{[0-9]+}} 3],
+// CHECK-DAG: [[TMAIN_S_ARR:@.+]] = linkonce_odr {{(dso_local )?}}global [2 x [[S_INT_TY]]] zeroinitializer,
+// CHECK-DAG: [[TMAIN_VAR:@.+]] = linkonce_odr {{(dso_local )?}}global [[S_INT_TY]] zeroinitializer,
// TLS-CHECK-DAG: [[T_VAR:@.+]] = internal thread_local global i{{[0-9]+}} 1122,
// TLS-CHECK-DAG: [[VEC:@.+]] = internal thread_local global [2 x i{{[0-9]+}}] [i{{[0-9]+}} 1, i{{[0-9]+}} 2],
// TLS-CHECK-DAG: [[S_ARR:@.+]] = internal thread_local global [2 x [[S_FLOAT_TY]]] zeroinitializer,
// TLS-CHECK-DAG: [[VAR:@.+]] = internal thread_local global [[S_FLOAT_TY]] zeroinitializer,
-// TLS-CHECK-DAG: [[TMAIN_T_VAR:@.+]] = linkonce_odr thread_local global i{{[0-9]+}} 333,
-// TLS-CHECK-DAG: [[TMAIN_VEC:@.+]] = linkonce_odr thread_local global [2 x i{{[0-9]+}}] [i{{[0-9]+}} 3, i{{[0-9]+}} 3],
-// TLS-CHECK-DAG: [[TMAIN_S_ARR:@.+]] = linkonce_odr thread_local global [2 x [[S_INT_TY]]] zeroinitializer,
-// TLS-CHECK-DAG: [[TMAIN_VAR:@.+]] = linkonce_odr thread_local global [[S_INT_TY]] zeroinitializer,
+// TLS-CHECK-DAG: [[TMAIN_T_VAR:@.+]] = linkonce_odr {{(dso_local )?}}thread_local global i{{[0-9]+}} 333,
+// TLS-CHECK-DAG: [[TMAIN_VEC:@.+]] = linkonce_odr {{(dso_local )?}}thread_local global [2 x i{{[0-9]+}}] [i{{[0-9]+}} 3, i{{[0-9]+}} 3],
+// TLS-CHECK-DAG: [[TMAIN_S_ARR:@.+]] = linkonce_odr {{(dso_local )?}}thread_local global [2 x [[S_INT_TY]]] zeroinitializer,
+// TLS-CHECK-DAG: [[TMAIN_VAR:@.+]] = linkonce_odr {{(dso_local )?}}thread_local global [[S_INT_TY]] zeroinitializer,
template <typename T>
T tmain() {
@@ -74,7 +90,7 @@ T tmain() {
int main() {
#ifdef LAMBDA
- // LAMBDA: [[G:@.+]] = global i{{[0-9]+}} 1212,
+ // LAMBDA: [[G:@.+]] = {{(dso_local )?}}global i{{[0-9]+}} 1212,
// LAMBDA-LABEL: @main
// LAMBDA: call{{.*}} void [[OUTER_LAMBDA:@.+]](
// TLS-LAMBDA: [[G:@.+]] = {{.*}}thread_local {{.*}}global i{{[0-9]+}} 1212,
@@ -136,7 +152,7 @@ int main() {
}();
return 0;
#elif defined(BLOCKS)
- // BLOCKS: [[G:@.+]] = global i{{[0-9]+}} 1212,
+ // BLOCKS: [[G:@.+]] = {{(dso_local )?}}global i{{[0-9]+}} 1212,
// BLOCKS-LABEL: @main
// BLOCKS: call {{.*}}void {{%.+}}(i8
@@ -278,10 +294,10 @@ int main() {
// threadprivate_vec = vec;
// CHECK: call {{.*}}i8* @__kmpc_threadprivate_cached({{.+}} [[VEC]]
-// CHECK: call void @llvm.memcpy{{.*}}(i8* %{{.+}}, i8* bitcast ([2 x i{{[0-9]+}}]* [[VEC]] to i8*),
+// CHECK: call void @llvm.memcpy{{.*}}(i8* align {{[0-9]+}} %{{.+}}, i8* align {{[0-9]+}} bitcast ([2 x i{{[0-9]+}}]* [[VEC]] to i8*),
// TLS-CHECK: [[MASTER_CAST:%.+]] = bitcast [2 x i32]* [[MASTER_REF2]] to i8*
-// TLS-CHECK: call void @llvm.memcpy{{.*}}(i8* bitcast ([2 x i{{[0-9]+}}]* [[VEC]] to i8*), i8* [[MASTER_CAST]]
+// TLS-CHECK: call void @llvm.memcpy{{.*}}(i8* align {{[0-9]+}} bitcast ([2 x i{{[0-9]+}}]* [[VEC]] to i8*), i8* align {{[0-9]+}} [[MASTER_CAST]]
// threadprivate_s_arr = s_arr;
// CHECK: call {{.*}}i8* @__kmpc_threadprivate_cached({{.+}} [[S_ARR]]
@@ -399,10 +415,10 @@ int main() {
// threadprivate_vec = vec;
// CHECK: call {{.*}}i8* @__kmpc_threadprivate_cached({{.+}} [[TMAIN_VEC]]
-// CHECK: call {{.*}}void @llvm.memcpy{{.*}}(i8* %{{.+}}, i8* bitcast ([2 x i{{[0-9]+}}]* [[TMAIN_VEC]] to i8*),
+// CHECK: call {{.*}}void @llvm.memcpy{{.*}}(i8* align {{[0-9]+}} %{{.+}}, i8* align {{[0-9]+}} bitcast ([2 x i{{[0-9]+}}]* [[TMAIN_VEC]] to i8*),
// TLS-CHECK: [[MASTER_CAST:%.+]] = bitcast [2 x i32]* [[MASTER_REF1]] to i8*
-// TLS-CHECK: call void @llvm.memcpy{{.*}}(i8* bitcast ([2 x i{{[0-9]+}}]* [[TMAIN_VEC]] to i8*), i8* [[MASTER_CAST]]
+// TLS-CHECK: call void @llvm.memcpy{{.*}}(i8* align {{[0-9]+}} bitcast ([2 x i{{[0-9]+}}]* [[TMAIN_VEC]] to i8*), i8* align {{[0-9]+}} [[MASTER_CAST]]
// threadprivate_s_arr = s_arr;
// CHECK: call {{.*}}i8* @__kmpc_threadprivate_cached({{.+}} [[TMAIN_S_ARR]]
@@ -492,13 +508,13 @@ void array_func() {
static St s[2];
// ARRAY: @__kmpc_fork_call(
// ARRAY: call i8* @__kmpc_threadprivate_cached(
-// ARRAY: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.+}}, i8* bitcast ([2 x i32]* @{{.+}} to i8*), i64 8, i32 4, i1 false)
+// ARRAY: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %{{.+}}, i8* align 4 bitcast ([2 x i32]* @{{.+}} to i8*), i64 8, i1 false)
// ARRAY: call dereferenceable(8) %struct.St* @{{.+}}(%struct.St* %{{.+}}, %struct.St* dereferenceable(8) %{{.+}})
// TLS-ARRAY: @__kmpc_fork_call(
// TLS-ARRAY: [[REFT:%.+]] = load [2 x i32]*, [2 x i32]** [[ADDR:%.+]],
// TLS-ARRAY: [[REF:%.+]] = bitcast [2 x i32]* [[REFT]] to i8*
-// TLS-ARRAY: call void @llvm.memcpy.p0i8.p0i8.i64(i8* bitcast ([2 x i32]* @{{.+}} to i8*), i8* [[REF]], i64 8, i32 4, i1 false)
+// TLS-ARRAY: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 bitcast ([2 x i32]* @{{.+}} to i8*), i8* align 4 [[REF]], i64 8, i1 false)
// TLS-ARRAY: call dereferenceable(8) %struct.St* @{{.+}}(%struct.St* %{{.+}}, %struct.St* dereferenceable(8) %{{.+}})
#pragma omp threadprivate(a, s)
diff --git a/test/OpenMP/parallel_copyin_messages.cpp b/test/OpenMP/parallel_copyin_messages.cpp
index 2b54b43b87c6..81a507addf10 100644
--- a/test/OpenMP/parallel_copyin_messages.cpp
+++ b/test/OpenMP/parallel_copyin_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_default_messages.cpp b/test/OpenMP/parallel_default_messages.cpp
index cbc6a73fe35d..4b698bccb0fb 100644
--- a/test/OpenMP/parallel_default_messages.cpp
+++ b/test/OpenMP/parallel_default_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo();
int main(int argc, char **argv) {
diff --git a/test/OpenMP/parallel_firstprivate_codegen.cpp b/test/OpenMP/parallel_firstprivate_codegen.cpp
index d20f3f513569..6772f61779ef 100644
--- a/test/OpenMP/parallel_firstprivate_codegen.cpp
+++ b/test/OpenMP/parallel_firstprivate_codegen.cpp
@@ -4,13 +4,30 @@
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA -check-prefix=LAMBDA-32 %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS -check-prefix=BLOCKS-32 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DLAMBDA -triple i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -fblocks -DBLOCKS -triple i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-64
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-64
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple x86_64-pc-linux-gnu -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA -check-prefix=LAMBDA-64 %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple x86_64-pc-linux-gnu -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS -check-prefix=BLOCKS-64 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DLAMBDA -triple x86_64-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -fblocks -DBLOCKS -triple x86_64-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=ARRAY %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// SIMD-ONLY2-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef ARRAY
#ifndef HEADER
@@ -349,7 +366,7 @@ int main() {
// CHECK-64: [[SIVAR7_CONV:%.+]] = bitcast i64* [[SIVAR7_PRIV]] to i32*
// CHECK: [[VEC_DEST:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
// CHECK: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_REF]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VEC_DEST]], i8* [[VEC_SRC]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST]], i8* align {{[0-9]+}} [[VEC_SRC]],
// CHECK: [[S_ARR_PRIV_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[S_ARR_BEGIN:%.+]] = bitcast [2 x [[S_FLOAT_TY]]]* [[S_ARR_REF]] to [[S_FLOAT_TY]]*
// CHECK: [[S_ARR_PRIV_END:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[S_ARR_PRIV_BEGIN]], i{{[0-9]+}} 2
@@ -442,7 +459,7 @@ int main() {
// CHECK: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_PRIV]], align 128
// CHECK: [[VEC_DEST:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
// CHECK: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_REF]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VEC_DEST]], i8* [[VEC_SRC]], i{{[0-9]+}} {{[0-9]+}}, i{{[0-9]+}} 128,
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align 128 [[VEC_DEST]], i8* align 128 [[VEC_SRC]], i{{[0-9]+}} {{[0-9]+}}, i1
// CHECK: [[S_ARR_PRIV_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_PRIV]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[S_ARR_BEGIN:%.+]] = bitcast [2 x [[S_INT_TY]]]* [[S_ARR_REF]] to [[S_INT_TY]]*
// CHECK: [[S_ARR_PRIV_END:%.+]] = getelementptr [[S_INT_TY]], [[S_INT_TY]]* [[S_ARR_PRIV_BEGIN]], i{{[0-9]+}} 2
@@ -490,7 +507,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) {
// ARRAY-DAG: store double* %{{.+}}, double** [[PRIV_VLA2]],
// ARRAY: call i8* @llvm.stacksave()
// ARRAY: [[SIZE:%.+]] = mul nuw i64 %{{.+}}, 8
-// ARRAY: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.+}}, i8* %{{.+}}, i64 [[SIZE]], i32 128, i1 false)
+// ARRAY: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 128 %{{.+}}, i8* align 128 %{{.+}}, i64 [[SIZE]], i1 false)
#pragma omp parallel firstprivate(a, s, vla1, vla2)
s[0].St_func(s, n, vla1);
;
@@ -506,7 +523,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) {
// ARRAY-DAG: store double* %{{.+}}, double** [[PRIV_VLA2]],
// ARRAY: call i8* @llvm.stacksave()
// ARRAY: [[SIZE:%.+]] = mul nuw i64 %{{.+}}, 8
-// ARRAY: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.+}}, i8* %{{.+}}, i64 [[SIZE]], i32 128, i1 false)
+// ARRAY: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 128 %{{.+}}, i8* align 128 %{{.+}}, i64 [[SIZE]], i1 false)
#endif
diff --git a/test/OpenMP/parallel_firstprivate_messages.cpp b/test/OpenMP/parallel_firstprivate_messages.cpp
index b2cb4ff131ef..7de268fb3b7e 100644
--- a/test/OpenMP/parallel_firstprivate_messages.cpp
+++ b/test/OpenMP/parallel_firstprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_for_ast_print.cpp b/test/OpenMP/parallel_for_ast_print.cpp
index 3c36bd80523c..1e77bc855a22 100644
--- a/test/OpenMP/parallel_for_ast_print.cpp
+++ b/test/OpenMP/parallel_for_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -35,7 +39,7 @@ public:
}
};
-// CHECK: #pragma omp parallel for private(this->a) private(this->a) private(T::a)
+// CHECK: #pragma omp parallel for private(this->a) private(this->a) private(T::a){{$}}
// CHECK: #pragma omp parallel for private(this->a) private(this->a)
// CHECK: #pragma omp parallel for private(this->a) private(this->a) private(this->S::a)
diff --git a/test/OpenMP/parallel_for_codegen.cpp b/test/OpenMP/parallel_for_codegen.cpp
index db3a2de580d8..e6199f00eabd 100644
--- a/test/OpenMP/parallel_for_codegen.cpp
+++ b/test/OpenMP/parallel_for_codegen.cpp
@@ -3,6 +3,13 @@
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck %s --check-prefix=TERM_DEBUG
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -O1 -fopenmp -emit-llvm %s -o - | FileCheck %s --check-prefix=CLEANUP
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -O1 -fopenmp-simd -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -347,9 +354,9 @@ int foo() {return 0;};
// TERM_DEBUG-LABEL: parallel_for
// CLEANUP: parallel_for
-void parallel_for(float *a, int n) {
+void parallel_for(float *a, const int n) {
float arr[n];
-#pragma omp parallel for schedule(static, 5) private(arr)
+#pragma omp parallel for schedule(static, 5) private(arr) default(none) firstprivate(n) shared(a)
// TERM_DEBUG-NOT: __kmpc_global_thread_num
// TERM_DEBUG: call void @__kmpc_for_static_init_4u({{.+}}), !dbg [[DBG_LOC_START:![0-9]+]]
// TERM_DEBUG: invoke i32 {{.*}}foo{{.*}}()
@@ -363,7 +370,7 @@ void parallel_for(float *a, int n) {
// CLEANUP: call void @__kmpc_for_static_init_4u({{.+}})
// CLEANUP: call void @__kmpc_for_static_fini({{.+}})
for (unsigned i = 131071; i <= 2147483647; i += 127)
- a[i] += foo() + arr[i];
+ a[i] += foo() + arr[i] + n;
}
// Check source line corresponds to "#pragma omp parallel for schedule(static, 5)" above:
// TERM_DEBUG-DAG: [[DBG_LOC_START]] = !DILocation(line: [[@LINE-4]],
diff --git a/test/OpenMP/parallel_for_collapse_messages.cpp b/test/OpenMP/parallel_for_collapse_messages.cpp
index 4461df8cccdb..9d99c25efa61 100644
--- a/test/OpenMP/parallel_for_collapse_messages.cpp
+++ b/test/OpenMP/parallel_for_collapse_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_for_copyin_messages.cpp b/test/OpenMP/parallel_for_copyin_messages.cpp
index 5a5d1632c8eb..265a1953e068 100644
--- a/test/OpenMP/parallel_for_copyin_messages.cpp
+++ b/test/OpenMP/parallel_for_copyin_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_for_default_messages.cpp b/test/OpenMP/parallel_for_default_messages.cpp
index d2129a345939..743383640f3b 100644
--- a/test/OpenMP/parallel_for_default_messages.cpp
+++ b/test/OpenMP/parallel_for_default_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo();
int main(int argc, char **argv) {
diff --git a/test/OpenMP/parallel_for_firstprivate_messages.cpp b/test/OpenMP/parallel_for_firstprivate_messages.cpp
index c9a69dab2cb2..19b1ced757b3 100644
--- a/test/OpenMP/parallel_for_firstprivate_messages.cpp
+++ b/test/OpenMP/parallel_for_firstprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_for_if_messages.cpp b/test/OpenMP/parallel_for_if_messages.cpp
index b5a7fdcd1ab5..1d83d3585d60 100644
--- a/test/OpenMP/parallel_for_if_messages.cpp
+++ b/test/OpenMP/parallel_for_if_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_for_lastprivate_messages.cpp b/test/OpenMP/parallel_for_lastprivate_messages.cpp
index 134100bc1753..8d2f4b5886fc 100644
--- a/test/OpenMP/parallel_for_lastprivate_messages.cpp
+++ b/test/OpenMP/parallel_for_lastprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_for_linear_codegen.cpp b/test/OpenMP/parallel_for_linear_codegen.cpp
index 2c3cfddbd571..c565097093da 100644
--- a/test/OpenMP/parallel_for_linear_codegen.cpp
+++ b/test/OpenMP/parallel_for_linear_codegen.cpp
@@ -3,6 +3,13 @@
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/parallel_for_linear_messages.cpp b/test/OpenMP/parallel_for_linear_messages.cpp
index e5f5b61873c8..080add692cab 100644
--- a/test/OpenMP/parallel_for_linear_messages.cpp
+++ b/test/OpenMP/parallel_for_linear_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
namespace X {
int x;
};
diff --git a/test/OpenMP/parallel_for_loop_messages.cpp b/test/OpenMP/parallel_for_loop_messages.cpp
index cf1f6195cc86..193c84e27fa5 100644
--- a/test/OpenMP/parallel_for_loop_messages.cpp
+++ b/test/OpenMP/parallel_for_loop_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+
class S {
int a;
S() : a(0) {}
diff --git a/test/OpenMP/parallel_for_messages.cpp b/test/OpenMP/parallel_for_messages.cpp
index 7c4f926d6d2b..9ab4bccfc984 100644
--- a/test/OpenMP/parallel_for_messages.cpp
+++ b/test/OpenMP/parallel_for_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -std=c++11 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -std=c++11 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_for_misc_messages.c b/test/OpenMP/parallel_for_misc_messages.c
index 1a773be617c7..2d12ba450727 100644
--- a/test/OpenMP/parallel_for_misc_messages.c
+++ b/test/OpenMP/parallel_for_misc_messages.c
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -verify %s
+
// expected-error@+1 {{unexpected OpenMP directive '#pragma omp parallel for'}}
#pragma omp parallel for
diff --git a/test/OpenMP/parallel_for_num_threads_messages.cpp b/test/OpenMP/parallel_for_num_threads_messages.cpp
index 10a4e1bfb1aa..6f57d6e8f459 100644
--- a/test/OpenMP/parallel_for_num_threads_messages.cpp
+++ b/test/OpenMP/parallel_for_num_threads_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_for_ordered_messages.cpp b/test/OpenMP/parallel_for_ordered_messages.cpp
index 055fe1bba423..381bc6ae1bad 100644
--- a/test/OpenMP/parallel_for_ordered_messages.cpp
+++ b/test/OpenMP/parallel_for_ordered_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_for_private_messages.cpp b/test/OpenMP/parallel_for_private_messages.cpp
index cc1b79f4111b..7efc6eeac8f7 100644
--- a/test/OpenMP/parallel_for_private_messages.cpp
+++ b/test/OpenMP/parallel_for_private_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_for_proc_bind_messages.cpp b/test/OpenMP/parallel_for_proc_bind_messages.cpp
index 0f9c47f5f29e..0ffff89a8c95 100644
--- a/test/OpenMP/parallel_for_proc_bind_messages.cpp
+++ b/test/OpenMP/parallel_for_proc_bind_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo();
int main(int argc, char **argv) {
diff --git a/test/OpenMP/parallel_for_reduction_messages.cpp b/test/OpenMP/parallel_for_reduction_messages.cpp
index 6499ef593a3d..5cfc2b9041ab 100644
--- a/test/OpenMP/parallel_for_reduction_messages.cpp
+++ b/test/OpenMP/parallel_for_reduction_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 150 -o - %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 150 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_for_schedule_messages.cpp b/test/OpenMP/parallel_for_schedule_messages.cpp
index f446609615da..5664529956b1 100644
--- a/test/OpenMP/parallel_for_schedule_messages.cpp
+++ b/test/OpenMP/parallel_for_schedule_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_for_simd_aligned_messages.cpp b/test/OpenMP/parallel_for_simd_aligned_messages.cpp
index eed80170039e..75f4adb00b20 100644
--- a/test/OpenMP/parallel_for_simd_aligned_messages.cpp
+++ b/test/OpenMP/parallel_for_simd_aligned_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -x c++ -std=c++11 -verify -fopenmp %s
+// RUN: %clang_cc1 -x c++ -std=c++11 -verify -fopenmp-simd %s
+
struct B {
static int ib[20]; // expected-note 0 {{'B::ib' declared here}}
static constexpr int bfoo() { return 8; }
diff --git a/test/OpenMP/parallel_for_simd_ast_print.cpp b/test/OpenMP/parallel_for_simd_ast_print.cpp
index 2668961892f3..fd4153752af3 100644
--- a/test/OpenMP/parallel_for_simd_ast_print.cpp
+++ b/test/OpenMP/parallel_for_simd_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -35,7 +39,7 @@ public:
}
};
-// CHECK: #pragma omp parallel for simd private(this->a) private(this->a) private(T::a)
+// CHECK: #pragma omp parallel for simd private(this->a) private(this->a) private(T::a){{$}}
// CHECK: #pragma omp parallel for simd private(this->a) private(this->a)
// CHECK: #pragma omp parallel for simd private(this->a) private(this->a) private(this->S1::a)
diff --git a/test/OpenMP/parallel_for_simd_codegen.cpp b/test/OpenMP/parallel_for_simd_codegen.cpp
index 369ea17844e9..e8cb651e2bc5 100644
--- a/test/OpenMP/parallel_for_simd_codegen.cpp
+++ b/test/OpenMP/parallel_for_simd_codegen.cpp
@@ -2,6 +2,12 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -debug-info-kind=limited -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck %s --check-prefix=TERM_DEBUG
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -debug-info-kind=limited -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -11,21 +17,21 @@ double *g_ptr;
// CHECK-LABEL: define {{.*void}} @{{.*}}simple{{.*}}(float* {{.+}}, float* {{.+}}, float* {{.+}}, float* {{.+}})
void simple(float *a, float *b, float *c, float *d) {
-// CHECK: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
// CHECK: [[K0:%.+]] = call {{.*}}i64 @{{.*}}get_val
// CHECK-NEXT: store i64 [[K0]], i64* [[K_VAR:%[^,]+]]
-// CHECK: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
// CHECK: store i32 12, i32* [[LIN_VAR:%[^,]+]]
-// CHECK: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
-// CHECK: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
-// CHECK: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
-// CHECK: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
// CHECK: store i32 -1, i32* [[A:%.+]],
-// CHECK: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
// CHECK: store i32 -1, i32* [[R:%[^,]+]],
-// CHECK: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
#pragma omp parallel for simd
-// CHECK: call void @__kmpc_for_static_init_4(%ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i32* [[LB:%[^,]+]], i32* [[UB:%[^,]+]], i32* [[STRIDE:%[^,]+]], i32 1, i32 1)
+// CHECK: call void @__kmpc_for_static_init_4(%struct.ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i32* [[LB:%[^,]+]], i32* [[UB:%[^,]+]], i32* [[STRIDE:%[^,]+]], i32 1, i32 1)
// CHECK: [[UB_VAL:%.+]] = load i32, i32* [[UB]],
// CHECK: [[CMP:%.+]] = icmp sgt i32 [[UB_VAL]], 5
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
@@ -61,7 +67,7 @@ void simple(float *a, float *b, float *c, float *d) {
// br label %{{.+}}, !llvm.loop !{{.+}}
}
// CHECK: [[SIMPLE_LOOP1_END]]:
-// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
+// CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* {{.+}}, i32 %{{.+}})
long long k = get_val();
@@ -69,8 +75,8 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: [[K0LOAD:%.+]] = load i64, i64* [[K_VAR:%[^,]+]]
// CHECK-NEXT: store i64 [[K0LOAD]], i64* [[LIN0:%[^,]+]]
-// CHECK: call void @__kmpc_dispatch_init_4(%ident_t* {{.+}}, i32 %{{.+}}, i32 35, i32 0, i32 8, i32 1, i32 1)
-// CHECK: [[NEXT:%.+]] = call i32 @__kmpc_dispatch_next_4(%ident_t* {{.+}}, i32 %{{.+}}, i32* %{{.+}}, i32* [[LB:%.+]], i32* [[UB:%.+]], i32* %{{.+}})
+// CHECK: call void @__kmpc_dispatch_init_4(%struct.ident_t* {{.+}}, i32 %{{.+}}, i32 35, i32 0, i32 8, i32 1, i32 1)
+// CHECK: [[NEXT:%.+]] = call i32 @__kmpc_dispatch_next_4(%struct.ident_t* {{.+}}, i32 %{{.+}}, i32* %{{.+}}, i32* [[LB:%.+]], i32* [[UB:%.+]], i32* %{{.+}})
// CHECK: [[COND:%.+]] = icmp ne i32 [[NEXT]], 0
// CHECK: br i1 [[COND]], label %[[CONT:.+]], label %[[END:.+]]
// CHECK: [[CONT]]:
@@ -126,7 +132,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: [[GLIN_LOAD:%.+]] = load double*, double** [[GLIN_VAR:%.+]],
// CHECK-NEXT: store double* [[GLIN_LOAD]], double** [[GLIN_START:%[^,]+]]
-// CHECK: call void @__kmpc_for_static_init_8u(%ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i64* [[LB:%[^,]+]], i64* [[UB:%[^,]+]], i64* [[STRIDE:%[^,]+]], i64 1, i64 1)
+// CHECK: call void @__kmpc_for_static_init_8u(%struct.ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i64* [[LB:%[^,]+]], i64* [[UB:%[^,]+]], i64* [[STRIDE:%[^,]+]], i64 1, i64 1)
// CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
// CHECK: [[CMP:%.+]] = icmp ugt i64 [[UB_VAL]], 3
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
@@ -173,7 +179,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: store i64 [[ADD3_2]], i64* [[OMP_IV3]]
}
// CHECK: [[SIMPLE_LOOP3_END]]:
-// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
+// CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* {{.+}}, i32 %{{.+}})
//
// Linear start and step are used to calculate final value of the linear variables.
// CHECK: [[LINSTART:.+]] = load i32, i32* [[LIN_START]]
@@ -183,7 +189,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: store double* {{.*}}[[GLIN_VAR]]
#pragma omp parallel for simd
-// CHECK: call void @__kmpc_for_static_init_4(%ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i32* [[LB:%[^,]+]], i32* [[UB:%[^,]+]], i32* [[STRIDE:%[^,]+]], i32 1, i32 1)
+// CHECK: call void @__kmpc_for_static_init_4(%struct.ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i32* [[LB:%[^,]+]], i32* [[UB:%[^,]+]], i32* [[STRIDE:%[^,]+]], i32 1, i32 1)
// CHECK: [[UB_VAL:%.+]] = load i32, i32* [[UB]],
// CHECK: [[CMP:%.+]] = icmp sgt i32 [[UB_VAL]], 3
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
@@ -216,10 +222,10 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: store i32 [[ADD4_2]], i32* [[OMP_IV4]]
}
// CHECK: [[SIMPLE_LOOP4_END]]:
-// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
+// CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* {{.+}}, i32 %{{.+}})
#pragma omp parallel for simd
-// CHECK: call void @__kmpc_for_static_init_4(%ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i32* [[LB:%[^,]+]], i32* [[UB:%[^,]+]], i32* [[STRIDE:%[^,]+]], i32 1, i32 1)
+// CHECK: call void @__kmpc_for_static_init_4(%struct.ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i32* [[LB:%[^,]+]], i32* [[UB:%[^,]+]], i32* [[STRIDE:%[^,]+]], i32 1, i32 1)
// CHECK: [[UB_VAL:%.+]] = load i32, i32* [[UB]],
// CHECK: [[CMP:%.+]] = icmp sgt i32 [[UB_VAL]], 25
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
@@ -252,7 +258,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: store i32 [[ADD5_2]], i32* [[OMP_IV5]]
}
// CHECK: [[SIMPLE_LOOP5_END]]:
-// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
+// CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* {{.+}}, i32 %{{.+}})
// CHECK-NOT: mul i32 %{{.+}}, 10
#pragma omp parallel for simd
@@ -263,7 +269,7 @@ void simple(float *a, float *b, float *c, float *d) {
{
A = -1;
#pragma omp parallel for simd lastprivate(A)
-// CHECK: call void @__kmpc_for_static_init_8(%ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i64* [[LB:%[^,]+]], i64* [[UB:%[^,]+]], i64* [[STRIDE:%[^,]+]], i64 1, i64 1)
+// CHECK: call void @__kmpc_for_static_init_8(%struct.ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i64* [[LB:%[^,]+]], i64* [[UB:%[^,]+]], i64* [[STRIDE:%[^,]+]], i64 1, i64 1)
// CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
// CHECK: [[CMP:%.+]] = icmp sgt i64 [[UB_VAL]], 6
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
@@ -300,7 +306,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: store i64 [[ADD7_2]], i64* [[OMP_IV7]]
}
// CHECK: [[SIMPLE_LOOP7_END]]:
-// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
+// CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* {{.+}}, i32 %{{.+}})
// CHECK: load i32, i32*
// CHECK: icmp ne i32 %{{.+}}, 0
// CHECK: br i1 %{{.+}}, label
@@ -313,7 +319,7 @@ void simple(float *a, float *b, float *c, float *d) {
R = -1;
// CHECK: store i32 1, i32* [[R_PRIV:%[^,]+]],
#pragma omp parallel for simd reduction(*:R)
-// CHECK: call void @__kmpc_for_static_init_8(%ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i64* [[LB:%[^,]+]], i64* [[UB:%[^,]+]], i64* [[STRIDE:%[^,]+]], i64 1, i64 1)
+// CHECK: call void @__kmpc_for_static_init_8(%struct.ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i64* [[LB:%[^,]+]], i64* [[UB:%[^,]+]], i64* [[STRIDE:%[^,]+]], i64 1, i64 1)
// CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
// CHECK: [[CMP:%.+]] = icmp sgt i64 [[UB_VAL]], 6
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
@@ -349,7 +355,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: store i64 [[ADD8_2]], i64* [[OMP_IV8]]
}
// CHECK: [[SIMPLE_LOOP8_END]]:
-// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
+// CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call i32 @__kmpc_reduce_nowait(
// CHECK: [[R_PRIV_VAL:%.+]] = load i32, i32* [[R_PRIV]],
// CHECK: [[RED:%.+]] = mul nsw i32 %{{.+}}, [[R_PRIV_VAL]]
@@ -373,7 +379,7 @@ int templ1(T a, T *z) {
// Instatiation templ1<float,2>
// CHECK-LABEL: define {{.*i32}} @{{.*}}templ1{{.*}}(float {{.+}}, float* {{.+}})
-// CHECK: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
void inst_templ1() {
float a;
float z[100];
@@ -421,7 +427,7 @@ void iter_simple(IterDouble ia, IterDouble ib, IterDouble ic) {
// CHECK-NEXT: store i32 [[DIFF5]], i32* [[OMP_LAST_IT:%[^,]+]]{{.+}}
#pragma omp parallel for simd
-// CHECK: call void @__kmpc_for_static_init_4(%ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i32* [[LB:%[^,]+]], i32* [[UB:%[^,]+]], i32* [[STRIDE:%[^,]+]], i32 1, i32 1)
+// CHECK: call void @__kmpc_for_static_init_4(%struct.ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i32* [[LB:%[^,]+]], i32* [[UB:%[^,]+]], i32* [[STRIDE:%[^,]+]], i32 1, i32 1)
// CHECK-DAG: [[UB_VAL:%.+]] = load i32, i32* [[UB]],
// CHECK-DAG: [[OMP_LAST_IT_VAL:%.+]] = load i32, i32* [[OMP_LAST_IT]],
// CHECK: [[CMP:%.+]] = icmp sgt i32 [[UB_VAL]], [[OMP_LAST_IT_VAL]]
@@ -462,7 +468,7 @@ void iter_simple(IterDouble ia, IterDouble ib, IterDouble ic) {
// br label %{{.*}}, !llvm.loop ![[ITER_LOOP_ID]]
}
// CHECK: [[IT_END]]:
-// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
+// CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* {{.+}}, i32 %{{.+}})
// CHECK: ret void
}
@@ -473,7 +479,7 @@ void collapsed(float *a, float *b, float *c, float *d) {
unsigned j; // middle loop couter, leads to unsigned icmp in loop header.
// k declared in the loop init below
short l; // inner loop counter
-// CHECK: call void @__kmpc_for_static_init_4u(%ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i32* [[LB:%[^,]+]], i32* [[UB:%[^,]+]], i32* [[STRIDE:%[^,]+]], i32 1, i32 1)
+// CHECK: call void @__kmpc_for_static_init_4u(%struct.ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i32* [[LB:%[^,]+]], i32* [[UB:%[^,]+]], i32* [[STRIDE:%[^,]+]], i32 1, i32 1)
// CHECK: [[UB_VAL:%.+]] = load i32, i32* [[UB]],
// CHECK: [[CMP:%.+]] = icmp ugt i32 [[UB_VAL]], 119
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
@@ -537,7 +543,7 @@ void collapsed(float *a, float *b, float *c, float *d) {
// CHECK: [[COLL1_END]]:
}
// i,j,l are updated; k is not updated.
-// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
+// CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* {{.+}}, i32 %{{.+}})
// CHECK: store i32 3, i32* [[I:%[^,]+]]
// CHECK: store i32 5, i32* [[I:%[^,]+]]
// CHECK: store i16 9, i16* [[I:%[^,]+]]
@@ -558,7 +564,7 @@ void widened(float *a, float *b, float *c, float *d) {
// CHECK: [[MUL:%.+]] = mul nsw i64 2, %{{.+}}
// CHECK-NEXT: [[SUB:%.+]] = sub nsw i64 [[MUL]], 1
// CHECK-NEXT: store i64 [[SUB]], i64* [[OMP_LAST_IT:%[^,]+]],
-// CHECK: call void @__kmpc_for_static_init_8(%ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i64* [[LB:%[^,]+]], i64* [[UB:%[^,]+]], i64* [[STRIDE:%[^,]+]], i64 1, i64 1)
+// CHECK: call void @__kmpc_for_static_init_8(%struct.ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i64* [[LB:%[^,]+]], i64* [[UB:%[^,]+]], i64* [[STRIDE:%[^,]+]], i64 1, i64 1)
// CHECK-DAG: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
// CHECK-DAG: [[OMP_LAST_IT_VAL:%.+]] = load i64, i64* [[OMP_LAST_IT]],
// CHECK: [[CMP:%.+]] = icmp sgt i64 [[UB_VAL]], [[OMP_LAST_IT_VAL]]
@@ -620,7 +626,7 @@ void widened(float *a, float *b, float *c, float *d) {
// CHECK: ret void
}
-// CHECK: call void @__kmpc_for_static_init_8(%ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i64* [[LB:%[^,]+]], i64* [[UB:%[^,]+]], i64* [[STRIDE:%[^,]+]], i64 1, i64 1)
+// CHECK: call void @__kmpc_for_static_init_8(%struct.ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i64* [[LB:%[^,]+]], i64* [[UB:%[^,]+]], i64* [[STRIDE:%[^,]+]], i64 1, i64 1)
// CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
// CHECK: [[CMP:%.+]] = icmp sgt i64 [[UB_VAL]], 15
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
@@ -659,7 +665,7 @@ void widened(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: store i64 [[INC]], i64*
// CHECK-NEXT: br label {{%.+}}
// CHECK: [[T1_END]]:
-// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
+// CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* {{.+}}, i32 %{{.+}})
// CHECK: ret void
//
// TERM_DEBUG-LABEL: bar
@@ -679,5 +685,6 @@ void parallel_simd(float *a) {
a[i] += bar();
}
// TERM_DEBUG: !{{[0-9]+}} = !DILocation(line: [[@LINE-11]],
+// TERM_DEBUG-NOT: line: 0,
#endif // HEADER
diff --git a/test/OpenMP/parallel_for_simd_collapse_messages.cpp b/test/OpenMP/parallel_for_simd_collapse_messages.cpp
index c7effbddeb28..d23086b9e539 100644
--- a/test/OpenMP/parallel_for_simd_collapse_messages.cpp
+++ b/test/OpenMP/parallel_for_simd_collapse_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_for_simd_copyin_messages.cpp b/test/OpenMP/parallel_for_simd_copyin_messages.cpp
index 1e6fdc9c31b1..6b492b13f7b5 100644
--- a/test/OpenMP/parallel_for_simd_copyin_messages.cpp
+++ b/test/OpenMP/parallel_for_simd_copyin_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_for_simd_default_messages.cpp b/test/OpenMP/parallel_for_simd_default_messages.cpp
index 9bd8113c8d55..2fccb5634b44 100644
--- a/test/OpenMP/parallel_for_simd_default_messages.cpp
+++ b/test/OpenMP/parallel_for_simd_default_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -o - %s
+
void foo();
int main(int argc, char **argv) {
diff --git a/test/OpenMP/parallel_for_simd_firstprivate_messages.cpp b/test/OpenMP/parallel_for_simd_firstprivate_messages.cpp
index 7a08572f7d1a..e1e01aa661b6 100644
--- a/test/OpenMP/parallel_for_simd_firstprivate_messages.cpp
+++ b/test/OpenMP/parallel_for_simd_firstprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_for_simd_if_messages.cpp b/test/OpenMP/parallel_for_simd_if_messages.cpp
index 7842524fa40d..08f8b466ed35 100644
--- a/test/OpenMP/parallel_for_simd_if_messages.cpp
+++ b/test/OpenMP/parallel_for_simd_if_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_for_simd_lastprivate_messages.cpp b/test/OpenMP/parallel_for_simd_lastprivate_messages.cpp
index 8670e55c6e2b..84e0896f1ff2 100644
--- a/test/OpenMP/parallel_for_simd_lastprivate_messages.cpp
+++ b/test/OpenMP/parallel_for_simd_lastprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_for_simd_linear_messages.cpp b/test/OpenMP/parallel_for_simd_linear_messages.cpp
index fc1895a36854..a6bcf64806f6 100644
--- a/test/OpenMP/parallel_for_simd_linear_messages.cpp
+++ b/test/OpenMP/parallel_for_simd_linear_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
namespace X {
int x;
};
diff --git a/test/OpenMP/parallel_for_simd_loop_messages.cpp b/test/OpenMP/parallel_for_simd_loop_messages.cpp
index 7feb4b0eb6ee..d9d05cccc54c 100644
--- a/test/OpenMP/parallel_for_simd_loop_messages.cpp
+++ b/test/OpenMP/parallel_for_simd_loop_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+
class S {
int a;
S() : a(0) {}
diff --git a/test/OpenMP/parallel_for_simd_messages.cpp b/test/OpenMP/parallel_for_simd_messages.cpp
index 18f25fa0f66a..f1d4c5b935be 100644
--- a/test/OpenMP/parallel_for_simd_messages.cpp
+++ b/test/OpenMP/parallel_for_simd_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_for_simd_misc_messages.c b/test/OpenMP/parallel_for_simd_misc_messages.c
index 378c48ff8a4c..d3565bfa4f19 100644
--- a/test/OpenMP/parallel_for_simd_misc_messages.c
+++ b/test/OpenMP/parallel_for_simd_misc_messages.c
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -verify %s
+
// expected-error@+1 {{unexpected OpenMP directive '#pragma omp parallel for simd'}}
#pragma omp parallel for simd
diff --git a/test/OpenMP/parallel_for_simd_num_threads_messages.cpp b/test/OpenMP/parallel_for_simd_num_threads_messages.cpp
index 940565cc10c3..06460c397de3 100644
--- a/test/OpenMP/parallel_for_simd_num_threads_messages.cpp
+++ b/test/OpenMP/parallel_for_simd_num_threads_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_for_simd_private_messages.cpp b/test/OpenMP/parallel_for_simd_private_messages.cpp
index a33b35d57d1e..5d263d6cc276 100644
--- a/test/OpenMP/parallel_for_simd_private_messages.cpp
+++ b/test/OpenMP/parallel_for_simd_private_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_for_simd_proc_bind_messages.cpp b/test/OpenMP/parallel_for_simd_proc_bind_messages.cpp
index a05b150f5694..26cc729964dc 100644
--- a/test/OpenMP/parallel_for_simd_proc_bind_messages.cpp
+++ b/test/OpenMP/parallel_for_simd_proc_bind_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -o - %s
+
void foo();
int main(int argc, char **argv) {
diff --git a/test/OpenMP/parallel_for_simd_reduction_messages.cpp b/test/OpenMP/parallel_for_simd_reduction_messages.cpp
index 8ff246e35f6a..32222ac5a53f 100644
--- a/test/OpenMP/parallel_for_simd_reduction_messages.cpp
+++ b/test/OpenMP/parallel_for_simd_reduction_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -o - %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_for_simd_safelen_messages.cpp b/test/OpenMP/parallel_for_simd_safelen_messages.cpp
index 3e643c619c6f..49ebf428f3d0 100644
--- a/test/OpenMP/parallel_for_simd_safelen_messages.cpp
+++ b/test/OpenMP/parallel_for_simd_safelen_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_for_simd_schedule_messages.cpp b/test/OpenMP/parallel_for_simd_schedule_messages.cpp
index 4135427ce10b..29e46a7a0c79 100644
--- a/test/OpenMP/parallel_for_simd_schedule_messages.cpp
+++ b/test/OpenMP/parallel_for_simd_schedule_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_for_simd_simdlen_messages.cpp b/test/OpenMP/parallel_for_simd_simdlen_messages.cpp
index fa9e0d6802a9..167644e3886b 100644
--- a/test/OpenMP/parallel_for_simd_simdlen_messages.cpp
+++ b/test/OpenMP/parallel_for_simd_simdlen_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_if_codegen.cpp b/test/OpenMP/parallel_if_codegen.cpp
index 87dcf1dde943..49e4bd402ce8 100644
--- a/test/OpenMP/parallel_if_codegen.cpp
+++ b/test/OpenMP/parallel_if_codegen.cpp
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple %itanium_abi_triple -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple %itanium_abi_triple -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple %itanium_abi_triple -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple %itanium_abi_triple -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -24,12 +29,12 @@ void gtid_test() {
}
// CHECK: define internal {{.*}}void [[GTID_TEST_REGION1]](i{{.+}}* noalias [[GTID_PARAM:%.+]], i32* noalias
+// CHECK: store i32 0, i32* [[ZERO_ADDR:%.+]],
// CHECK: store i{{[0-9]+}}* [[GTID_PARAM]], i{{[0-9]+}}** [[GTID_ADDR_REF:%.+]],
// CHECK: [[GTID_ADDR:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[GTID_ADDR_REF]]
// CHECK: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_ADDR]]
// CHECK: call {{.*}}void @__kmpc_serialized_parallel(%{{.+}}* @{{.+}}, i{{.+}} [[GTID]])
-// CHECK: [[GTID_ADDR:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[GTID_ADDR_REF]]
-// CHECK: call void [[GTID_TEST_REGION2:@.+]](i{{[0-9]+}}* [[GTID_ADDR]]
+// CHECK: call void [[GTID_TEST_REGION2:@.+]](i{{[0-9]+}}* [[ZERO_ADDR]]
// CHECK: call {{.*}}void @__kmpc_end_serialized_parallel(%{{.+}}* @{{.+}}, i{{.+}} [[GTID]])
// CHECK: ret void
@@ -51,12 +56,13 @@ int tmain(T Arg) {
// CHECK-LABEL: define {{.*}}i{{[0-9]+}} @main()
int main() {
// CHECK: [[GTID:%.+]] = call {{.*}}i32 @__kmpc_global_thread_num(
+// CHECK: store i32 0, i32* [[ZERO_ADDR2:%.+]],
+// CHECK: store i32 0, i32* [[ZERO_ADDR1:%.+]],
// CHECK: call {{.*}}void {{.+}} @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{.+}} 0, void {{.+}}* [[CAP_FN4:@.+]] to void
#pragma omp parallel if (true)
fn4();
// CHECK: call {{.*}}void @__kmpc_serialized_parallel(%{{.+}}* @{{.+}}, i32 [[GTID]])
-// CHECK: store i32 [[GTID]], i32* [[GTID_ADDR:%.+]],
-// CHECK: call void [[CAP_FN5:@.+]](i32* [[GTID_ADDR]],
+// CHECK: call void [[CAP_FN5:@.+]](i32* [[ZERO_ADDR1]], i32* [[ZERO_ADDR1]])
// CHECK: call {{.*}}void @__kmpc_end_serialized_parallel(%{{.+}}* @{{.+}}, i32 [[GTID]])
#pragma omp parallel if (false)
fn5();
@@ -67,8 +73,7 @@ int main() {
// CHECK: br label %[[OMP_END:.+]]
// CHECK: [[OMP_ELSE]]
// CHECK: call {{.*}}void @__kmpc_serialized_parallel(%{{.+}}* @{{.+}}, i32 [[GTID]])
-// CHECK: store i32 [[GTID]], i32* [[GTID_ADDR:%.+]],
-// CHECK: call void [[CAP_FN6]](i32* [[GTID_ADDR]],
+// CHECK: call void [[CAP_FN6]](i32* [[ZERO_ADDR2]], i32* [[ZERO_ADDR2]])
// CHECK: call {{.*}}void @__kmpc_end_serialized_parallel(%{{.+}}* @{{.+}}, i32 [[GTID]])
// CHECK: br label %[[OMP_END]]
// CHECK: [[OMP_END]]
@@ -92,10 +97,11 @@ int main() {
// CHECK-LABEL: define {{.+}} @{{.+}}tmain
// CHECK: [[GTID:%.+]] = call {{.*}}i32 @__kmpc_global_thread_num(
+// CHECK: store i32 0, i32* [[ZERO_ADDR2:%.+]],
+// CHECK: store i32 0, i32* [[ZERO_ADDR1:%.+]],
// CHECK: call {{.*}}void {{.+}} @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{.+}} 0, void {{.+}}* [[CAP_FN1:@.+]] to void
// CHECK: call {{.*}}void @__kmpc_serialized_parallel(%{{.+}}* @{{.+}}, i32 [[GTID]])
-// CHECK: store i32 [[GTID]], i32* [[GTID_ADDR:%.+]],
-// CHECK: call void [[CAP_FN2:@.+]](i32* [[GTID_ADDR]],
+// CHECK: call void [[CAP_FN2:@.+]](i32* [[ZERO_ADDR1]], i32* [[ZERO_ADDR1]])
// CHECK: call {{.*}}void @__kmpc_end_serialized_parallel(%{{.+}}* @{{.+}}, i32 [[GTID]])
// CHECK: br i1 %{{.+}}, label %[[OMP_THEN:.+]], label %[[OMP_ELSE:.+]]
// CHECK: [[OMP_THEN]]
@@ -103,8 +109,7 @@ int main() {
// CHECK: br label %[[OMP_END:.+]]
// CHECK: [[OMP_ELSE]]
// CHECK: call {{.*}}void @__kmpc_serialized_parallel(%{{.+}}* @{{.+}}, i32 [[GTID]])
-// CHECK: store i32 [[GTID]], i32* [[GTID_ADDR:%.+]],
-// CHECK: call void [[CAP_FN3]](i32* [[GTID_ADDR]],
+// CHECK: call void [[CAP_FN3]](i32* [[ZERO_ADDR2]], i32* [[ZERO_ADDR2]])
// CHECK: call {{.*}}void @__kmpc_end_serialized_parallel(%{{.+}}* @{{.+}}, i32 [[GTID]])
// CHECK: br label %[[OMP_END]]
// CHECK: [[OMP_END]]
diff --git a/test/OpenMP/parallel_if_messages.cpp b/test/OpenMP/parallel_if_messages.cpp
index 094e83b63145..d0a4c6d1108d 100644
--- a/test/OpenMP/parallel_if_messages.cpp
+++ b/test/OpenMP/parallel_if_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_messages.cpp b/test/OpenMP/parallel_messages.cpp
index 4db55a019549..8b0c0353c20d 100644
--- a/test/OpenMP/parallel_messages.cpp
+++ b/test/OpenMP/parallel_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -std=c++11 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -std=c++11 -o - %s
+
void foo() {
}
@@ -29,6 +31,8 @@ int main(int argc, char **argv) {
foo();
L1:
foo();
+ #pragma omp parallel ordered // expected-error {{unexpected OpenMP clause 'ordered' in directive '#pragma omp parallel'}}
+ ;
#pragma omp parallel
;
#pragma omp parallel
diff --git a/test/OpenMP/parallel_num_threads_codegen.cpp b/test/OpenMP/parallel_num_threads_codegen.cpp
index c5f11bde19ae..9ec712f83c53 100644
--- a/test/OpenMP/parallel_num_threads_codegen.cpp
+++ b/test/OpenMP/parallel_num_threads_codegen.cpp
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple %itanium_abi_triple -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple %itanium_abi_triple -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/parallel_num_threads_messages.cpp b/test/OpenMP/parallel_num_threads_messages.cpp
index adcf6ca4253f..310e7ccfa4e8 100644
--- a/test/OpenMP/parallel_num_threads_messages.cpp
+++ b/test/OpenMP/parallel_num_threads_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_private_codegen.cpp b/test/OpenMP/parallel_private_codegen.cpp
index fbb9b18d5df5..33a5b4cba0e6 100644
--- a/test/OpenMP/parallel_private_codegen.cpp
+++ b/test/OpenMP/parallel_private_codegen.cpp
@@ -3,6 +3,13 @@
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DLAMBDA -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -fblocks -DBLOCKS -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -96,7 +103,7 @@ int main() {
static int sivar;
SS ss(sivar);
#ifdef LAMBDA
- // LAMBDA: [[G:@.+]] = global i{{[0-9]+}} 1212,
+ // LAMBDA: [[G:@.+]] = {{(dso_local )?}}global i{{[0-9]+}} 1212,
// LAMBDA-LABEL: @main
// LAMBDA: alloca [[SS_TY]],
// LAMBDA: alloca [[CAP_TY:%.+]],
@@ -168,7 +175,7 @@ int main() {
}();
return 0;
#elif defined(BLOCKS)
- // BLOCKS: [[G:@.+]] = global i{{[0-9]+}} 1212,
+ // BLOCKS: [[G:@.+]] = {{(dso_local )?}}global i{{[0-9]+}} 1212,
// BLOCKS-LABEL: @main
// BLOCKS: call
// BLOCKS: call{{.*}} void {{%.+}}(i8
diff --git a/test/OpenMP/parallel_private_messages.cpp b/test/OpenMP/parallel_private_messages.cpp
index ab535b475265..4adee55e341c 100644
--- a/test/OpenMP/parallel_private_messages.cpp
+++ b/test/OpenMP/parallel_private_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_proc_bind_codegen.cpp b/test/OpenMP/parallel_proc_bind_codegen.cpp
index 34a64de7465d..8b9e09191b24 100644
--- a/test/OpenMP/parallel_proc_bind_codegen.cpp
+++ b/test/OpenMP/parallel_proc_bind_codegen.cpp
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple %itanium_abi_triple -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple %itanium_abi_triple -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -38,14 +43,14 @@ int main() {
// CHECK-LABEL: @main
// CHECK: [[GTID:%.+]] = call {{.*}}i32 @__kmpc_global_thread_num([[IDENT_T_TY]]* [[DEF_LOC_2]])
// CHECK: call {{.*}}void @__kmpc_push_proc_bind([[IDENT_T_TY]]* [[DEF_LOC_2]], i32 [[GTID]], i32 4)
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
// CHECK: call {{.*}}void @__kmpc_push_proc_bind([[IDENT_T_TY]]* [[DEF_LOC_2]], i32 [[GTID]], i32 3)
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
// CHECK-LABEL: @{{.+}}tmain
// CHECK: [[GTID:%.+]] = call {{.*}}i32 @__kmpc_global_thread_num([[IDENT_T_TY]]* [[DEF_LOC_2]])
// CHECK: call {{.*}}void @__kmpc_push_proc_bind([[IDENT_T_TY]]* [[DEF_LOC_2]], i32 [[GTID]], i32 2)
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
// CHECK: ret i32 0
// CHECK-NEXT: }
diff --git a/test/OpenMP/parallel_proc_bind_messages.cpp b/test/OpenMP/parallel_proc_bind_messages.cpp
index 78ba297fdf5d..91be0f1a8d83 100644
--- a/test/OpenMP/parallel_proc_bind_messages.cpp
+++ b/test/OpenMP/parallel_proc_bind_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo();
int main(int argc, char **argv) {
diff --git a/test/OpenMP/parallel_reduction_codegen.cpp b/test/OpenMP/parallel_reduction_codegen.cpp
index c4c0ff473a59..c064ed071210 100644
--- a/test/OpenMP/parallel_reduction_codegen.cpp
+++ b/test/OpenMP/parallel_reduction_codegen.cpp
@@ -3,6 +3,13 @@
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -407,7 +414,7 @@ int main() {
// CHECK: [[UP:%.+]] = call dereferenceable(4) [[S_FLOAT_TY]]* @{{.+}}([[S_FLOAT_TY]]* [[VAR_REF]], [[S_FLOAT_TY]]* dereferenceable(4) [[VAR_PRIV]])
// CHECK: [[BC1:%.+]] = bitcast [[S_FLOAT_TY]]* [[VAR_REF]] to i8*
// CHECK: [[BC2:%.+]] = bitcast [[S_FLOAT_TY]]* [[UP]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[BC1]], i8* [[BC2]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[BC1]], i8* align 4 [[BC2]], i64 4, i1 false)
// var1 = var1.operator &&(var1_reduction);
// CHECK: [[TO_FLOAT:%.+]] = call float @{{.+}}([[S_FLOAT_TY]]* [[VAR1_REF]])
@@ -423,7 +430,7 @@ int main() {
// CHECK: call void @{{.+}}([[S_FLOAT_TY]]* [[COND_LVALUE:%.+]], float [[CONV]])
// CHECK: [[BC1:%.+]] = bitcast [[S_FLOAT_TY]]* [[VAR1_REF]] to i8*
// CHECK: [[BC2:%.+]] = bitcast [[S_FLOAT_TY]]* [[COND_LVALUE]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[BC1]], i8* [[BC2]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[BC1]], i8* align 4 [[BC2]], i64 4, i1 false)
// t_var1 = min(t_var1, t_var1_reduction);
// CHECK: [[T_VAR1_VAL:%.+]] = load float, float* [[T_VAR1_REF]],
@@ -461,7 +468,7 @@ int main() {
// CHECK: [[UP:%.+]] = call dereferenceable(4) [[S_FLOAT_TY]]* @{{.+}}([[S_FLOAT_TY]]* [[VAR_REF]], [[S_FLOAT_TY]]* dereferenceable(4) [[VAR_PRIV]])
// CHECK: [[BC1:%.+]] = bitcast [[S_FLOAT_TY]]* [[VAR_REF]] to i8*
// CHECK: [[BC2:%.+]] = bitcast [[S_FLOAT_TY]]* [[UP]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[BC1]], i8* [[BC2]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[BC1]], i8* align 4 [[BC2]], i64 4, i1 false)
// CHECK: call void @__kmpc_end_critical(
// var1 = var1.operator &&(var1_reduction);
@@ -479,7 +486,7 @@ int main() {
// CHECK: call void @{{.+}}([[S_FLOAT_TY]]* [[COND_LVALUE:%.+]], float [[CONV]])
// CHECK: [[BC1:%.+]] = bitcast [[S_FLOAT_TY]]* [[VAR1_REF]] to i8*
// CHECK: [[BC2:%.+]] = bitcast [[S_FLOAT_TY]]* [[COND_LVALUE]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[BC1]], i8* [[BC2]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[BC1]], i8* align 4 [[BC2]], i64 4, i1 false)
// CHECK: call void @__kmpc_end_critical(
// t_var1 = min(t_var1, t_var1_reduction);
@@ -561,7 +568,7 @@ int main() {
// CHECK: [[UP:%.+]] = call dereferenceable(4) [[S_FLOAT_TY]]* @{{.+}}([[S_FLOAT_TY]]* [[VAR_LHS]], [[S_FLOAT_TY]]* dereferenceable(4) [[VAR_RHS]])
// CHECK: [[BC1:%.+]] = bitcast [[S_FLOAT_TY]]* [[VAR_LHS]] to i8*
// CHECK: [[BC2:%.+]] = bitcast [[S_FLOAT_TY]]* [[UP]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[BC1]], i8* [[BC2]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[BC1]], i8* align 4 [[BC2]], i64 4, i1 false)
// var1_lhs = var1_lhs.operator &&(var1_rhs);
// CHECK: [[TO_FLOAT:%.+]] = call float @{{.+}}([[S_FLOAT_TY]]* [[VAR1_LHS]])
@@ -577,7 +584,7 @@ int main() {
// CHECK: call void @{{.+}}([[S_FLOAT_TY]]* [[COND_LVALUE:%.+]], float [[CONV]])
// CHECK: [[BC1:%.+]] = bitcast [[S_FLOAT_TY]]* [[VAR1_LHS]] to i8*
// CHECK: [[BC2:%.+]] = bitcast [[S_FLOAT_TY]]* [[COND_LVALUE]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[BC1]], i8* [[BC2]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[BC1]], i8* align 4 [[BC2]], i64 4, i1 false)
// t_var1_lhs = min(t_var1_lhs, t_var1_rhs);
// CHECK: [[T_VAR1_LHS_VAL:%.+]] = load float, float* [[T_VAR1_LHS]],
@@ -730,7 +737,7 @@ int main() {
// CHECK: [[UP:%.+]] = call dereferenceable(4) [[S_INT_TY]]* @{{.+}}([[S_INT_TY]]* [[VAR_REF]], [[S_INT_TY]]* dereferenceable(4) [[VAR_PRIV]])
// CHECK: [[BC1:%.+]] = bitcast [[S_INT_TY]]* [[VAR_REF]] to i8*
// CHECK: [[BC2:%.+]] = bitcast [[S_INT_TY]]* [[UP]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[BC1]], i8* [[BC2]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 128 [[BC1]], i8* align 4 [[BC2]], i64 4, i1 false)
// var1 = var1.operator &&(var1_reduction);
// CHECK: [[TO_INT:%.+]] = call i{{[0-9]+}} @{{.+}}([[S_INT_TY]]* [[VAR1_REF]])
@@ -745,7 +752,7 @@ int main() {
// CHECK: call void @{{.+}}([[S_INT_TY]]* [[COND_LVALUE:%.+]], i32 [[CONV]])
// CHECK: [[BC1:%.+]] = bitcast [[S_INT_TY]]* [[VAR1_REF]] to i8*
// CHECK: [[BC2:%.+]] = bitcast [[S_INT_TY]]* [[COND_LVALUE]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[BC1]], i8* [[BC2]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 128 [[BC1]], i8* align 4 [[BC2]], i64 4, i1 false)
// t_var1 = min(t_var1, t_var1_reduction);
// CHECK: [[T_VAR1_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[T_VAR1_REF]],
@@ -771,7 +778,7 @@ int main() {
// CHECK: [[UP:%.+]] = call dereferenceable(4) [[S_INT_TY]]* @{{.+}}([[S_INT_TY]]* [[VAR_REF]], [[S_INT_TY]]* dereferenceable(4) [[VAR_PRIV]])
// CHECK: [[BC1:%.+]] = bitcast [[S_INT_TY]]* [[VAR_REF]] to i8*
// CHECK: [[BC2:%.+]] = bitcast [[S_INT_TY]]* [[UP]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[BC1]], i8* [[BC2]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 128 [[BC1]], i8* align 4 [[BC2]], i64 4, i1 false)
// CHECK: call void @__kmpc_end_critical(
// var1 = var1.operator &&(var1_reduction);
@@ -789,7 +796,7 @@ int main() {
// CHECK: call void @{{.+}}([[S_INT_TY]]* [[COND_LVALUE:%.+]], i32 [[CONV]])
// CHECK: [[BC1:%.+]] = bitcast [[S_INT_TY]]* [[VAR1_REF]] to i8*
// CHECK: [[BC2:%.+]] = bitcast [[S_INT_TY]]* [[COND_LVALUE]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[BC1]], i8* [[BC2]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 128 [[BC1]], i8* align 4 [[BC2]], i64 4, i1 false)
// CHECK: call void @__kmpc_end_critical(
// t_var1 = min(t_var1, t_var1_reduction);
@@ -857,7 +864,7 @@ int main() {
// CHECK: [[UP:%.+]] = call dereferenceable(4) [[S_INT_TY]]* @{{.+}}([[S_INT_TY]]* [[VAR_LHS]], [[S_INT_TY]]* dereferenceable(4) [[VAR_RHS]])
// CHECK: [[BC1:%.+]] = bitcast [[S_INT_TY]]* [[VAR_LHS]] to i8*
// CHECK: [[BC2:%.+]] = bitcast [[S_INT_TY]]* [[UP]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[BC1]], i8* [[BC2]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 128 [[BC1]], i8* align 4 [[BC2]], i64 4, i1 false)
// var1_lhs = var1_lhs.operator &&(var1_rhs);
// CHECK: [[TO_INT:%.+]] = call i{{[0-9]+}} @{{.+}}([[S_INT_TY]]* [[VAR1_LHS]])
@@ -873,7 +880,7 @@ int main() {
// CHECK: call void @{{.+}}([[S_INT_TY]]* [[COND_LVALUE:%.+]], i32 [[CONV]])
// CHECK: [[BC1:%.+]] = bitcast [[S_INT_TY]]* [[VAR1_LHS]] to i8*
// CHECK: [[BC2:%.+]] = bitcast [[S_INT_TY]]* [[COND_LVALUE]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[BC1]], i8* [[BC2]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 128 [[BC1]], i8* align 4 [[BC2]], i64 4, i1 false)
// t_var1_lhs = min(t_var1_lhs, t_var1_rhs);
// CHECK: [[T_VAR1_LHS_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[T_VAR1_LHS]],
diff --git a/test/OpenMP/parallel_reduction_messages.c b/test/OpenMP/parallel_reduction_messages.c
new file mode 100644
index 000000000000..f88f8e056495
--- /dev/null
+++ b/test/OpenMP/parallel_reduction_messages.c
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 150 -o - %s
+
+int incomplete[];
+
+void test() {
+#pragma omp parallel reduction(+ : incomplete) // expected-error {{a reduction list item with incomplete type 'int []'}}
+ ;
+}
+
+// complete to suppress an additional warning, but it's too late for pragmas
+int incomplete[3];
diff --git a/test/OpenMP/parallel_reduction_messages.cpp b/test/OpenMP/parallel_reduction_messages.cpp
index 96f4b58ec8a4..b3619bb9ad4d 100644
--- a/test/OpenMP/parallel_reduction_messages.cpp
+++ b/test/OpenMP/parallel_reduction_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 150 -o - %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 150 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_sections_ast_print.cpp b/test/OpenMP/parallel_sections_ast_print.cpp
index da3bd48201a0..8c0bd0bae5f8 100644
--- a/test/OpenMP/parallel_sections_ast_print.cpp
+++ b/test/OpenMP/parallel_sections_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -54,7 +58,7 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: T b = argc, c, d, e, f, g;
// CHECK-NEXT: static T a;
// CHECK-NEXT: S<T> s;
-// CHECK-NEXT: #pragma omp parallel sections
+// CHECK-NEXT: #pragma omp parallel sections{{$}}
// CHECK-NEXT: {
// CHECK-NEXT: a = 2;
// CHECK-NEXT: }
diff --git a/test/OpenMP/parallel_sections_codegen.cpp b/test/OpenMP/parallel_sections_codegen.cpp
index a26147303611..eadc4937203a 100644
--- a/test/OpenMP/parallel_sections_codegen.cpp
+++ b/test/OpenMP/parallel_sections_codegen.cpp
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -fopenmp -x c++ -emit-llvm -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -o - %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -triple x86_64-unknown-unknown -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -include-pch %t -fsyntax-only -verify %s -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -emit-llvm -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -o - %s | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -fexceptions -fcxx-exceptions -triple x86_64-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -include-pch %t -fsyntax-only -verify %s -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/parallel_sections_copyin_messages.cpp b/test/OpenMP/parallel_sections_copyin_messages.cpp
index 62b5d05db065..da0ef5cb1e04 100644
--- a/test/OpenMP/parallel_sections_copyin_messages.cpp
+++ b/test/OpenMP/parallel_sections_copyin_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_sections_default_messages.cpp b/test/OpenMP/parallel_sections_default_messages.cpp
index 9b2bdad627aa..a62b86ff34a8 100644
--- a/test/OpenMP/parallel_sections_default_messages.cpp
+++ b/test/OpenMP/parallel_sections_default_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo();
int main(int argc, char **argv) {
diff --git a/test/OpenMP/parallel_sections_firstprivate_messages.cpp b/test/OpenMP/parallel_sections_firstprivate_messages.cpp
index b733aabb7f25..f8370f26b4d4 100644
--- a/test/OpenMP/parallel_sections_firstprivate_messages.cpp
+++ b/test/OpenMP/parallel_sections_firstprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_sections_if_messages.cpp b/test/OpenMP/parallel_sections_if_messages.cpp
index ce067a254fea..b03ed3551653 100644
--- a/test/OpenMP/parallel_sections_if_messages.cpp
+++ b/test/OpenMP/parallel_sections_if_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_sections_lastprivate_messages.cpp b/test/OpenMP/parallel_sections_lastprivate_messages.cpp
index eccbfc5e7e02..865dda01a330 100644
--- a/test/OpenMP/parallel_sections_lastprivate_messages.cpp
+++ b/test/OpenMP/parallel_sections_lastprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_sections_messages.cpp b/test/OpenMP/parallel_sections_messages.cpp
index 1e71a305069b..459953acd9a2 100644
--- a/test/OpenMP/parallel_sections_messages.cpp
+++ b/test/OpenMP/parallel_sections_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -std=c++11 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -std=c++11 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_sections_misc_messages.c b/test/OpenMP/parallel_sections_misc_messages.c
index 203d12c52aab..780837a15f9c 100644
--- a/test/OpenMP/parallel_sections_misc_messages.c
+++ b/test/OpenMP/parallel_sections_misc_messages.c
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -verify %s
+
void foo();
// expected-error@+1 {{unexpected OpenMP directive '#pragma omp parallel sections'}}
diff --git a/test/OpenMP/parallel_sections_num_threads_messages.cpp b/test/OpenMP/parallel_sections_num_threads_messages.cpp
index cda3841ace97..42bdee25e464 100644
--- a/test/OpenMP/parallel_sections_num_threads_messages.cpp
+++ b/test/OpenMP/parallel_sections_num_threads_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_sections_private_messages.cpp b/test/OpenMP/parallel_sections_private_messages.cpp
index 40b0138b5396..75e3f173ae83 100644
--- a/test/OpenMP/parallel_sections_private_messages.cpp
+++ b/test/OpenMP/parallel_sections_private_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_sections_proc_bind_messages.cpp b/test/OpenMP/parallel_sections_proc_bind_messages.cpp
index 79796daa8ce6..bb173b61e527 100644
--- a/test/OpenMP/parallel_sections_proc_bind_messages.cpp
+++ b/test/OpenMP/parallel_sections_proc_bind_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo();
int main(int argc, char **argv) {
diff --git a/test/OpenMP/parallel_sections_reduction_messages.cpp b/test/OpenMP/parallel_sections_reduction_messages.cpp
index 26b3a5355c19..bbd3737de5c1 100644
--- a/test/OpenMP/parallel_sections_reduction_messages.cpp
+++ b/test/OpenMP/parallel_sections_reduction_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 150 -o - %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 150 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_sections_shared_messages.cpp b/test/OpenMP/parallel_sections_shared_messages.cpp
index 2b8359711119..1ab923c3308c 100644
--- a/test/OpenMP/parallel_sections_shared_messages.cpp
+++ b/test/OpenMP/parallel_sections_shared_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/parallel_shared_messages.cpp b/test/OpenMP/parallel_shared_messages.cpp
index f6f4573a6693..915b6a2cfc62 100644
--- a/test/OpenMP/parallel_shared_messages.cpp
+++ b/test/OpenMP/parallel_shared_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/predefined_macro.c b/test/OpenMP/predefined_macro.c
index e18c3d26d4c2..b27b32b561fd 100644
--- a/test/OpenMP/predefined_macro.c
+++ b/test/OpenMP/predefined_macro.c
@@ -1,5 +1,8 @@
// RUN: %clang_cc1 -fopenmp -verify -DFOPENMP -o - %s
// RUN: %clang_cc1 -verify -o - %s
+
+// RUN: %clang_cc1 -fopenmp-simd -verify -o - %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -verify -o - %s
// expected-no-diagnostics
#ifdef FOPENMP
// -fopenmp option is specified
diff --git a/test/OpenMP/report_default_DSA.cpp b/test/OpenMP/report_default_DSA.cpp
index d14cd5cbe9a4..ba620a4ce8eb 100644
--- a/test/OpenMP/report_default_DSA.cpp
+++ b/test/OpenMP/report_default_DSA.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 %s
+
void foo(int x, int n) {
double vec[n];
for (int iter = 0; iter < x; iter++) {
diff --git a/test/OpenMP/schedule_codegen.cpp b/test/OpenMP/schedule_codegen.cpp
index bd5ec86b2917..394eae4a55e6 100644
--- a/test/OpenMP/schedule_codegen.cpp
+++ b/test/OpenMP/schedule_codegen.cpp
@@ -1,5 +1,8 @@
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -emit-llvm -fexceptions -fcxx-exceptions -o - %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -emit-llvm -fexceptions -fcxx-exceptions -o - %s | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
int main() {
// CHECK: @__kmpc_for_static_init
// CHECK-NOT: !llvm.mem.parallel_loop_access
diff --git a/test/OpenMP/sections_ast_print.cpp b/test/OpenMP/sections_ast_print.cpp
index 7fecd5b77771..15c8c26e8ce6 100644
--- a/test/OpenMP/sections_ast_print.cpp
+++ b/test/OpenMP/sections_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -19,7 +23,7 @@ T tmain(T argc) {
foo();
}
// CHECK-NEXT: #pragma omp parallel
- // CHECK-NEXT: #pragma omp sections private(argc,b) firstprivate(c,d) lastprivate(d,f) reduction(-: g) nowait
+ // CHECK-NEXT: #pragma omp sections private(argc,b) firstprivate(c,d) lastprivate(d,f) reduction(-: g) nowait{{$}}
// CHECK-NEXT: {
// CHECK-NEXT: foo();
// CHECK-NEXT: }
@@ -42,7 +46,7 @@ int main(int argc, char **argv) {
// CHECK-NEXT: #pragma omp parallel
// CHECK-NEXT: #pragma omp sections private(argc,b) firstprivate(argv,c) lastprivate(d,f) reduction(+: g) nowait
// CHECK-NEXT: {
- // CHECK-NEXT: #pragma omp section
+ // CHECK-NEXT: #pragma omp section{{$}}
// CHECK-NEXT: foo();
// CHECK-NEXT: #pragma omp section
// CHECK-NEXT: foo();
diff --git a/test/OpenMP/sections_codegen.cpp b/test/OpenMP/sections_codegen.cpp
index 94ded37db95d..ba918c385fc3 100644
--- a/test/OpenMP/sections_codegen.cpp
+++ b/test/OpenMP/sections_codegen.cpp
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -fopenmp -x c++ -emit-llvm -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -o - %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -triple x86_64-unknown-unknown -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -include-pch %t -fsyntax-only -verify %s -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -emit-llvm -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -o - %s | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -fexceptions -fcxx-exceptions -triple x86_64-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -include-pch %t -fsyntax-only -verify %s -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/sections_firstprivate_codegen.cpp b/test/OpenMP/sections_firstprivate_codegen.cpp
index 227bb076374f..467c10f242c6 100644
--- a/test/OpenMP/sections_firstprivate_codegen.cpp
+++ b/test/OpenMP/sections_firstprivate_codegen.cpp
@@ -3,6 +3,13 @@
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -218,7 +225,7 @@ int main() {
// firstprivate vec(vec)
// CHECK: [[VEC_DEST:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VEC_DEST]], i8* bitcast ([2 x i{{[0-9]+}}]* [[VEC]] to i8*),
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST]], i8* align {{[0-9]+}} bitcast ([2 x i{{[0-9]+}}]* [[VEC]] to i8*),
// firstprivate s_arr(s_arr)
// CHECK: [[S_ARR_PRIV_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
@@ -285,7 +292,7 @@ int main() {
// firstprivate vec(vec)
// CHECK: [[VEC_DEST:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
// CHECK: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_REF]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VEC_DEST]], i8* [[VEC_SRC]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST]], i8* align {{[0-9]+}} [[VEC_SRC]],
// firstprivate s_arr(s_arr)
// CHECK: [[S_ARR_PRIV_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_PRIV]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
diff --git a/test/OpenMP/sections_firstprivate_messages.cpp b/test/OpenMP/sections_firstprivate_messages.cpp
index cd2b4b883873..425125c11a09 100644
--- a/test/OpenMP/sections_firstprivate_messages.cpp
+++ b/test/OpenMP/sections_firstprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/sections_lastprivate_codegen.cpp b/test/OpenMP/sections_lastprivate_codegen.cpp
index c9a224db2370..bb6a54f00aef 100644
--- a/test/OpenMP/sections_lastprivate_codegen.cpp
+++ b/test/OpenMP/sections_lastprivate_codegen.cpp
@@ -3,6 +3,13 @@
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -335,7 +342,7 @@ int main() {
// original vec[]=private_vec[];
// CHECK: [[VEC_DEST:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_REF]] to i8*
// CHECK: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VEC_DEST]], i8* [[VEC_SRC]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST]], i8* align {{[0-9]+}} [[VEC_SRC]],
// original s_arr[]=private_s_arr[];
// CHECK: [[S_ARR_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_REF]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
diff --git a/test/OpenMP/sections_lastprivate_messages.cpp b/test/OpenMP/sections_lastprivate_messages.cpp
index 01bb13de5510..e24b58fa29bc 100644
--- a/test/OpenMP/sections_lastprivate_messages.cpp
+++ b/test/OpenMP/sections_lastprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/sections_misc_messages.c b/test/OpenMP/sections_misc_messages.c
index da20aa18aa12..ba030859e575 100644
--- a/test/OpenMP/sections_misc_messages.c
+++ b/test/OpenMP/sections_misc_messages.c
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -verify %s
+
void foo();
// expected-error@+1 {{unexpected OpenMP directive '#pragma omp sections'}}
diff --git a/test/OpenMP/sections_private_codegen.cpp b/test/OpenMP/sections_private_codegen.cpp
index 337a0bfe3ec1..6a6d4fe6481d 100644
--- a/test/OpenMP/sections_private_codegen.cpp
+++ b/test/OpenMP/sections_private_codegen.cpp
@@ -3,6 +3,13 @@
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DLAMBDA -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -fblocks -DBLOCKS -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -40,7 +47,7 @@ T tmain() {
int main() {
static int sivar;
#ifdef LAMBDA
- // LAMBDA: [[G:@.+]] = global double
+ // LAMBDA: [[G:@.+]] = {{(dso_local )?}}global double
// LAMBDA-LABEL: @main
// LAMBDA: call{{.*}} void [[OUTER_LAMBDA:@.+]](
[&]() {
@@ -85,7 +92,7 @@ int main() {
}();
return 0;
#elif defined(BLOCKS)
- // BLOCKS: [[G:@.+]] = global double
+ // BLOCKS: [[G:@.+]] = {{(dso_local )?}}global double
// BLOCKS-LABEL: @main
// BLOCKS: call {{.*}}void {{%.+}}(i8
^{
diff --git a/test/OpenMP/sections_private_messages.cpp b/test/OpenMP/sections_private_messages.cpp
index 27bb3136e720..81e3eb4779b9 100644
--- a/test/OpenMP/sections_private_messages.cpp
+++ b/test/OpenMP/sections_private_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/sections_reduction_codegen.cpp b/test/OpenMP/sections_reduction_codegen.cpp
index 8c474d575e0a..43b08b1160d3 100644
--- a/test/OpenMP/sections_reduction_codegen.cpp
+++ b/test/OpenMP/sections_reduction_codegen.cpp
@@ -1,8 +1,15 @@
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap -check-prefix=LAMBDA %s
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap -check-prefix=BLOCKS %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -296,7 +303,7 @@ int main() {
// CHECK: [[UP:%.+]] = call dereferenceable(4) [[S_INT_TY]]* @{{.+}}([[S_INT_TY]]* [[VAR_REF]], [[S_INT_TY]]* dereferenceable(4) [[VAR_PRIV]])
// CHECK: [[BC1:%.+]] = bitcast [[S_INT_TY]]* [[VAR_REF]] to i8*
// CHECK: [[BC2:%.+]] = bitcast [[S_INT_TY]]* [[UP]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[BC1]], i8* [[BC2]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[BC1]], i8* align 4 [[BC2]], i64 4, i1 false)
// var1 = var1.operator &&(var1_reduction);
// CHECK: [[TO_INT:%.+]] = call i{{[0-9]+}} @{{.+}}([[S_INT_TY]]* [[VAR1_REF]])
@@ -312,7 +319,7 @@ int main() {
// CHECK: call void @{{.+}}([[S_INT_TY]]* [[COND_LVALUE:%.+]], i32 [[CONV]])
// CHECK: [[BC1:%.+]] = bitcast [[S_INT_TY]]* [[VAR1_REF]] to i8*
// CHECK: [[BC2:%.+]] = bitcast [[S_INT_TY]]* [[COND_LVALUE]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[BC1]], i8* [[BC2]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[BC1]], i8* align 4 [[BC2]], i64 4, i1 false)
// t_var1 = min(t_var1, t_var1_reduction);
// CHECK: [[T_VAR1_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[T_VAR1_REF]],
@@ -338,7 +345,7 @@ int main() {
// CHECK: [[UP:%.+]] = call dereferenceable(4) [[S_INT_TY]]* @{{.+}}([[S_INT_TY]]* [[VAR_REF]], [[S_INT_TY]]* dereferenceable(4) [[VAR_PRIV]])
// CHECK: [[BC1:%.+]] = bitcast [[S_INT_TY]]* [[VAR_REF]] to i8*
// CHECK: [[BC2:%.+]] = bitcast [[S_INT_TY]]* [[UP]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[BC1]], i8* [[BC2]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[BC1]], i8* align 4 [[BC2]], i64 4, i1 false)
// CHECK: call void @__kmpc_end_critical(
// var1 = var1.operator &&(var1_reduction);
@@ -356,7 +363,7 @@ int main() {
// CHECK: call void @{{.+}}([[S_INT_TY]]* [[COND_LVALUE:%.+]], i32 [[CONV]])
// CHECK: [[BC1:%.+]] = bitcast [[S_INT_TY]]* [[VAR1_REF]] to i8*
// CHECK: [[BC2:%.+]] = bitcast [[S_INT_TY]]* [[COND_LVALUE]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[BC1]], i8* [[BC2]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[BC1]], i8* align 4 [[BC2]], i64 4, i1 false)
// CHECK: call void @__kmpc_end_critical(
// t_var1 = min(t_var1, t_var1_reduction);
@@ -423,7 +430,7 @@ int main() {
// CHECK: [[UP:%.+]] = call dereferenceable(4) [[S_INT_TY]]* @{{.+}}([[S_INT_TY]]* [[VAR_LHS]], [[S_INT_TY]]* dereferenceable(4) [[VAR_RHS]])
// CHECK: [[BC1:%.+]] = bitcast [[S_INT_TY]]* [[VAR_LHS]] to i8*
// CHECK: [[BC2:%.+]] = bitcast [[S_INT_TY]]* [[UP]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[BC1]], i8* [[BC2]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[BC1]], i8* align 4 [[BC2]], i64 4, i1 false)
// var1_lhs = var1_lhs.operator &&(var1_rhs);
// CHECK: [[TO_INT:%.+]] = call i{{[0-9]+}} @{{.+}}([[S_INT_TY]]* [[VAR1_LHS]])
@@ -439,7 +446,7 @@ int main() {
// CHECK: call void @{{.+}}([[S_INT_TY]]* [[COND_LVALUE:%.+]], i32 [[CONV]])
// CHECK: [[BC1:%.+]] = bitcast [[S_INT_TY]]* [[VAR1_LHS]] to i8*
// CHECK: [[BC2:%.+]] = bitcast [[S_INT_TY]]* [[COND_LVALUE]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[BC1]], i8* [[BC2]], i64 4, i32 4, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[BC1]], i8* align 4 [[BC2]], i64 4, i1 false)
// t_var1_lhs = min(t_var1_lhs, t_var1_rhs);
// CHECK: [[T_VAR1_LHS_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[T_VAR1_LHS]],
diff --git a/test/OpenMP/sections_reduction_messages.cpp b/test/OpenMP/sections_reduction_messages.cpp
index 58b22a5a61d0..bf302cf7b335 100644
--- a/test/OpenMP/sections_reduction_messages.cpp
+++ b/test/OpenMP/sections_reduction_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 150 -o - %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 150 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/simd_aligned_messages.cpp b/test/OpenMP/simd_aligned_messages.cpp
index d936fed01439..7621d7de096b 100644
--- a/test/OpenMP/simd_aligned_messages.cpp
+++ b/test/OpenMP/simd_aligned_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -x c++ -std=c++11 -verify -fopenmp %s
+// RUN: %clang_cc1 -x c++ -std=c++11 -verify -fopenmp-simd %s
+
struct B {
static int ib[20]; // expected-note 0 {{'B::ib' declared here}}
static constexpr int bfoo() { return 8; }
diff --git a/test/OpenMP/simd_ast_print.cpp b/test/OpenMP/simd_ast_print.cpp
index 9fcd459f4956..ad16fe2de9a4 100644
--- a/test/OpenMP/simd_ast_print.cpp
+++ b/test/OpenMP/simd_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -34,7 +38,7 @@ public:
}
};
-// CHECK: #pragma omp simd aligned(this->a)
+// CHECK: #pragma omp simd aligned(this->a){{$}}
// CHECK: #pragma omp simd aligned(this->b: 8)
// CHECK: #pragma omp simd aligned(this->a)
@@ -149,7 +153,7 @@ int main (int argc, char **argv) {
static int *a;
// CHECK: static int *a;
#pragma omp simd
-// CHECK-NEXT: #pragma omp simd
+// CHECK-NEXT: #pragma omp simd{{$}}
for (int i=0; i < 2; ++i)*a=2;
// CHECK-NEXT: for (int i = 0; i < 2; ++i)
// CHECK-NEXT: *a = 2;
diff --git a/test/OpenMP/simd_codegen.cpp b/test/OpenMP/simd_codegen.cpp
index 47f2433f0bbc..883273099ad8 100644
--- a/test/OpenMP/simd_codegen.cpp
+++ b/test/OpenMP/simd_codegen.cpp
@@ -2,6 +2,11 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -debug-info-kind=limited -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck %s --check-prefix=TERM_DEBUG
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -debug-info-kind=limited -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck --check-prefix=TERM_DEBUG %s
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -641,25 +646,26 @@ void parallel_simd(float *a) {
// TERM_DEBUG: !{{[0-9]+}} = !DILocation(line: [[@LINE-11]],
// CHECK-LABEL: S8
-// CHECK: ptrtoint [[SS_TY]]* %{{.+}} to i64
-// CHECK-NEXT: and i64 %{{.+}}, 15
-// CHECK-NEXT: icmp eq i64 %{{.+}}, 0
-// CHECK-NEXT: call void @llvm.assume(i1
-
-// CHECK: ptrtoint [[SS_TY]]* %{{.+}} to i64
-// CHECK-NEXT: and i64 %{{.+}}, 7
-// CHECK-NEXT: icmp eq i64 %{{.+}}, 0
-// CHECK-NEXT: call void @llvm.assume(i1
-
-// CHECK: ptrtoint [[SS_TY]]* %{{.+}} to i64
-// CHECK-NEXT: and i64 %{{.+}}, 15
-// CHECK-NEXT: icmp eq i64 %{{.+}}, 0
-// CHECK-NEXT: call void @llvm.assume(i1
-
-// CHECK: ptrtoint [[SS_TY]]* %{{.+}} to i64
-// CHECK-NEXT: and i64 %{{.+}}, 3
-// CHECK-NEXT: icmp eq i64 %{{.+}}, 0
-// CHECK-NEXT: call void @llvm.assume(i1
+// CHECK-DAG: ptrtoint [[SS_TY]]* %{{.+}} to i64
+// CHECK-DAG: ptrtoint [[SS_TY]]* %{{.+}} to i64
+// CHECK-DAG: ptrtoint [[SS_TY]]* %{{.+}} to i64
+// CHECK-DAG: ptrtoint [[SS_TY]]* %{{.+}} to i64
+
+// CHECK-DAG: and i64 %{{.+}}, 15
+// CHECK-DAG: icmp eq i64 %{{.+}}, 0
+// CHECK-DAG: call void @llvm.assume(i1
+
+// CHECK-DAG: and i64 %{{.+}}, 7
+// CHECK-DAG: icmp eq i64 %{{.+}}, 0
+// CHECK-DAG: call void @llvm.assume(i1
+
+// CHECK-DAG: and i64 %{{.+}}, 15
+// CHECK-DAG: icmp eq i64 %{{.+}}, 0
+// CHECK-DAG: call void @llvm.assume(i1
+
+// CHECK-DAG: and i64 %{{.+}}, 3
+// CHECK-DAG: icmp eq i64 %{{.+}}, 0
+// CHECK-DAG: call void @llvm.assume(i1
struct SS {
SS(): a(0) {}
SS(int v) : a(v) {}
@@ -702,5 +708,8 @@ public:
};
S8 s8(0);
+// TERM_DEBUG-NOT: line: 0,
+// TERM_DEBUG: distinct !DISubprogram(linkageName: "_GLOBAL__sub_I_simd_codegen.cpp",
+
#endif // HEADER
diff --git a/test/OpenMP/simd_collapse_messages.cpp b/test/OpenMP/simd_collapse_messages.cpp
index 5b8802468849..b3100c097d66 100644
--- a/test/OpenMP/simd_collapse_messages.cpp
+++ b/test/OpenMP/simd_collapse_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/simd_lastprivate_messages.cpp b/test/OpenMP/simd_lastprivate_messages.cpp
index 349d6a5b904d..0af812889cf1 100644
--- a/test/OpenMP/simd_lastprivate_messages.cpp
+++ b/test/OpenMP/simd_lastprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/simd_linear_messages.cpp b/test/OpenMP/simd_linear_messages.cpp
index 792f78aa3db6..aad0d18d4281 100644
--- a/test/OpenMP/simd_linear_messages.cpp
+++ b/test/OpenMP/simd_linear_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
namespace X {
int x;
};
diff --git a/test/OpenMP/simd_loop_messages.cpp b/test/OpenMP/simd_loop_messages.cpp
index a47ccbc87219..b9d146c2150a 100644
--- a/test/OpenMP/simd_loop_messages.cpp
+++ b/test/OpenMP/simd_loop_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+
static int sii;
// expected-note@+1 {{defined as threadprivate or thread local}}
#pragma omp threadprivate(sii)
@@ -234,9 +236,7 @@ int test_iteration_spaces() {
for (ii = 0; ii < 10; ii++)
c[ii] = a[ii];
- // expected-error@+3 {{unexpected OpenMP clause 'shared' in directive '#pragma omp simd'}}
- // expected-note@+2 {{defined as shared}}
- // expected-error@+2 {{loop iteration variable in the associated loop of 'omp simd' directive may not be shared, predetermined as linear}}
+ // expected-error@+1 {{unexpected OpenMP clause 'shared' in directive '#pragma omp simd'}}
#pragma omp simd shared(ii)
for (ii = 0; ii < 10; ii++)
c[ii] = a[ii];
diff --git a/test/OpenMP/simd_metadata.c b/test/OpenMP/simd_metadata.c
index 6ed660747dcb..8fdc306930c5 100644
--- a/test/OpenMP/simd_metadata.c
+++ b/test/OpenMP/simd_metadata.c
@@ -7,6 +7,15 @@
// RUN: %clang_cc1 -fopenmp -triple powerpc64-unknown-unknown -emit-llvm %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=PPC
// RUN: %clang_cc1 -fopenmp -triple powerpc64-unknown-unknown -target-abi elfv1-qpx -emit-llvm %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=PPC-QPX
+// RUN: %clang_cc1 -fopenmp-simd -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=X86
+// RUN: %clang_cc1 -fopenmp-simd -triple x86_64-unknown-unknown -target-feature +avx -emit-llvm %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=X86-AVX
+// RUN: %clang_cc1 -fopenmp-simd -triple x86_64-unknown-unknown -target-feature +avx512f -emit-llvm %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=X86-AVX512
+// RUN: %clang_cc1 -fopenmp-simd -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=X86
+// RUN: %clang_cc1 -fopenmp-simd -triple i386-unknown-unknown -target-feature +avx -emit-llvm %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=X86-AVX
+// RUN: %clang_cc1 -fopenmp-simd -triple i386-unknown-unknown -target-feature +avx512f -emit-llvm %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=X86-AVX512
+// RUN: %clang_cc1 -fopenmp-simd -triple powerpc64-unknown-unknown -emit-llvm %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=PPC
+// RUN: %clang_cc1 -fopenmp-simd -triple powerpc64-unknown-unknown -target-abi elfv1-qpx -emit-llvm %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=PPC-QPX
+
void h1(float *c, float *a, double b[], int size)
{
// CHECK-LABEL: define void @h1
diff --git a/test/OpenMP/simd_misc_messages.c b/test/OpenMP/simd_misc_messages.c
index 1e1548291947..75b8ce0596c7 100644
--- a/test/OpenMP/simd_misc_messages.c
+++ b/test/OpenMP/simd_misc_messages.c
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -verify %s
+
// expected-error@+1 {{unexpected OpenMP directive '#pragma omp simd'}}
#pragma omp simd
diff --git a/test/OpenMP/simd_private_messages.cpp b/test/OpenMP/simd_private_messages.cpp
index 1850101891f7..bfa26d164529 100644
--- a/test/OpenMP/simd_private_messages.cpp
+++ b/test/OpenMP/simd_private_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/simd_reduction_messages.cpp b/test/OpenMP/simd_reduction_messages.cpp
index bdf429d1967c..135a3ca71f6e 100644
--- a/test/OpenMP/simd_reduction_messages.cpp
+++ b/test/OpenMP/simd_reduction_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/simd_safelen_messages.cpp b/test/OpenMP/simd_safelen_messages.cpp
index 56cb868337e0..b75a923e7f9f 100644
--- a/test/OpenMP/simd_safelen_messages.cpp
+++ b/test/OpenMP/simd_safelen_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/simd_simdlen_messages.cpp b/test/OpenMP/simd_simdlen_messages.cpp
index 426d1878ba4c..f34d62814197 100644
--- a/test/OpenMP/simd_simdlen_messages.cpp
+++ b/test/OpenMP/simd_simdlen_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/single_ast_print.cpp b/test/OpenMP/single_ast_print.cpp
index e819ab9e14a5..a8eaeb0bff34 100644
--- a/test/OpenMP/single_ast_print.cpp
+++ b/test/OpenMP/single_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -16,7 +20,7 @@ struct SS {
#pragma omp parallel firstprivate(a, b, c)
#pragma omp single copyprivate(a, this->b, (this)->c)
// CHECK: #pragma omp parallel firstprivate(this->a,this->b,this->c)
-// CHECK-NEXT: #pragma omp single copyprivate(this->a,this->b,this->c)
+// CHECK-NEXT: #pragma omp single copyprivate(this->a,this->b,this->c){{$}}
++this->a, --b, (this)->c /= 1;
}
};
diff --git a/test/OpenMP/single_codegen.cpp b/test/OpenMP/single_codegen.cpp
index 892e16032417..b6ecac72d4f5 100644
--- a/test/OpenMP/single_codegen.cpp
+++ b/test/OpenMP/single_codegen.cpp
@@ -3,6 +3,13 @@
// RUN: %clang_cc1 -fopenmp -fnoopenmp-use-tls -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -std=c++11 -fopenmp -fnoopenmp-use-tls -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck %s --check-prefix=TERM_DEBUG
// RUN: %clang_cc1 -verify -fopenmp -fnoopenmp-use-tls -x c++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=ARRAY %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fnoopenmp-use-tls -x c++ -std=c++11 -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fnoopenmp-use-tls -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fnoopenmp-use-tls -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -std=c++11 -fopenmp-simd -fnoopenmp-use-tls -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fnoopenmp-use-tls -x c++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef ARRAY
#ifndef HEADER
@@ -173,7 +180,7 @@ int main() {
// CHECK: [[DST_A2_ADDR:%.+]] = load i8*, i8** [[DST_A2_ADDR_REF]],
// CHECK: [[SRC_A2_ADDR_REF:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[SRC_ADDR]], i{{[0-9]+}} 0, i{{[0-9]+}} 3
// CHECK: [[SRC_A2_ADDR:%.+]] = load i8*, i8** [[SRC_A2_ADDR_REF]],
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[DST_A2_ADDR]], i8* [[SRC_A2_ADDR]], i{{[0-9]+}} 2, i{{[0-9]+}} 1, i1 false)
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align 1 [[DST_A2_ADDR]], i8* align 1 [[SRC_A2_ADDR]], i{{[0-9]+}} 2, i1 false)
// CHECK: [[DST_TC2_ADDR_REF:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[DST_ADDR]], i{{[0-9]+}} 0, i{{[0-9]+}} 4
// CHECK: [[DST_TC2_ADDR_VOID_PTR:%.+]] = load i8*, i8** [[DST_TC2_ADDR_REF]],
// CHECK: [[DST_TC2_ADDR:%.+]] = bitcast i8* [[DST_TC2_ADDR_VOID_PTR]] to [[TEST_CLASS_TY]]*
@@ -214,7 +221,7 @@ struct St {
};
void array_func(int n, int a[n], St s[2]) {
-// ARRAY: call void @__kmpc_copyprivate(%ident_t* @{{.+}}, i32 %{{.+}}, i64 16, i8* %{{.+}}, void (i8*, i8*)* [[CPY:@.+]], i32 %{{.+}})
+// ARRAY: call void @__kmpc_copyprivate(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i64 16, i8* %{{.+}}, void (i8*, i8*)* [[CPY:@.+]], i32 %{{.+}})
#pragma omp single copyprivate(a, s)
;
}
diff --git a/test/OpenMP/single_copyprivate_messages.cpp b/test/OpenMP/single_copyprivate_messages.cpp
index 4714753f494e..bb18568d0f28 100644
--- a/test/OpenMP/single_copyprivate_messages.cpp
+++ b/test/OpenMP/single_copyprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/single_firstprivate_codegen.cpp b/test/OpenMP/single_firstprivate_codegen.cpp
index 4a91bc2d5bc5..23b543511b0f 100644
--- a/test/OpenMP/single_firstprivate_codegen.cpp
+++ b/test/OpenMP/single_firstprivate_codegen.cpp
@@ -3,6 +3,13 @@
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -185,7 +192,7 @@ int main() {
// firstprivate vec(vec)
// CHECK: [[VEC_DEST:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VEC_DEST]], i8* bitcast ([2 x i{{[0-9]+}}]* [[VEC]] to i8*),
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST]], i8* align {{[0-9]+}} bitcast ([2 x i{{[0-9]+}}]* [[VEC]] to i8*),
// firstprivate s_arr(s_arr)
// CHECK: [[S_ARR_PRIV_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
@@ -249,7 +256,7 @@ int main() {
// firstprivate vec(vec)
// CHECK: [[VEC_DEST:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
// CHECK: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_REF]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VEC_DEST]], i8* [[VEC_SRC]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST]], i8* align {{[0-9]+}} [[VEC_SRC]],
// firstprivate s_arr(s_arr)
// CHECK: [[S_ARR_PRIV_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_PRIV]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
diff --git a/test/OpenMP/single_firstprivate_messages.cpp b/test/OpenMP/single_firstprivate_messages.cpp
index 32de9fdc8806..4c714e392f97 100644
--- a/test/OpenMP/single_firstprivate_messages.cpp
+++ b/test/OpenMP/single_firstprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/single_misc_messages.c b/test/OpenMP/single_misc_messages.c
index 2c922ddfd4f0..b8264198079e 100644
--- a/test/OpenMP/single_misc_messages.c
+++ b/test/OpenMP/single_misc_messages.c
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -verify %s
+
void foo();
// expected-error@+1 {{unexpected OpenMP directive '#pragma omp single'}}
diff --git a/test/OpenMP/single_private_codegen.cpp b/test/OpenMP/single_private_codegen.cpp
index 6d47cb50dc59..4b4d103d7dd4 100644
--- a/test/OpenMP/single_private_codegen.cpp
+++ b/test/OpenMP/single_private_codegen.cpp
@@ -3,6 +3,13 @@
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DLAMBDA -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -fblocks -DBLOCKS -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -39,7 +46,7 @@ T tmain() {
int main() {
static int sivar;
#ifdef LAMBDA
- // LAMBDA: [[G:@.+]] = global double
+ // LAMBDA: [[G:@.+]] = {{(dso_local )?}}global double
// LAMBDA-LABEL: @main
// LAMBDA: call{{.*}} void [[OUTER_LAMBDA:@.+]](
[&]() {
@@ -79,7 +86,7 @@ int main() {
}();
return 0;
#elif defined(BLOCKS)
- // BLOCKS: [[G:@.+]] = global double
+ // BLOCKS: [[G:@.+]] = {{(dso_local )?}}global double
// BLOCKS-LABEL: @main
// BLOCKS: call {{.*}}void {{%.+}}(i8
^{
diff --git a/test/OpenMP/single_private_messages.cpp b/test/OpenMP/single_private_messages.cpp
index 0ed0e6cfb099..0a3ec2e6677f 100644
--- a/test/OpenMP/single_private_messages.cpp
+++ b/test/OpenMP/single_private_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_ast_print.cpp b/test/OpenMP/target_ast_print.cpp
index d004f738fc0d..827d6a4e3deb 100644
--- a/test/OpenMP/target_ast_print.cpp
+++ b/test/OpenMP/target_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -42,7 +46,7 @@ T tmain(T argc, T *argv) {
// CHECK: template <typename T, int C> T tmain(T argc, T *argv) {
// CHECK-NEXT: T i, j, a[20]
-// CHECK-NEXT: #pragma omp target
+// CHECK-NEXT: #pragma omp target{{$}}
// CHECK-NEXT: foo();
// CHECK-NEXT: #pragma omp target if(target: argc > 0)
// CHECK-NEXT: foo()
diff --git a/test/OpenMP/target_codegen.cpp b/test/OpenMP/target_codegen.cpp
index 20bc96b84cbf..15eb469fa280 100644
--- a/test/OpenMP/target_codegen.cpp
+++ b/test/OpenMP/target_codegen.cpp
@@ -6,6 +6,14 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// Test target codegen - host bc file has to be created first.
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
@@ -16,6 +24,16 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -31,38 +49,38 @@
// CHECK-DAG: $[[REGFN:\.omp_offloading\..+]] = comdat
// We have 8 target regions, but only 7 that actually will generate offloading
-// code, only 6 will have mapped arguments, and only 4 have all-constant map
-// sizes.
+// code and have mapped arguments, and only 5 have all-constant map sizes.
// CHECK-DAG: [[SIZET:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 0, i[[SZ]] 4]
-// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 32, i64 288]
+// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 544, i64 800]
// CHECK-DAG: [[SIZET2:@.+]] = private unnamed_addr constant [1 x i{{32|64}}] [i[[SZ]] 2]
-// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [1 x i64] [i64 288]
+// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [1 x i64] [i64 800]
// CHECK-DAG: [[SIZET3:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2]
-// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [2 x i64] [i64 288, i64 288]
-// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [9 x i64] [i64 288, i64 547, i64 288, i64 547, i64 547, i64 288, i64 288, i64 547, i64 547]
+// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [2 x i64] [i64 800, i64 800]
+// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [9 x i64] [i64 800, i64 547, i64 288, i64 547, i64 547, i64 288, i64 288, i64 547, i64 547]
// CHECK-DAG: [[SIZET5:@.+]] = private unnamed_addr constant [3 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2, i[[SZ]] 40]
-// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [3 x i64] [i64 288, i64 288, i64 547]
+// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [3 x i64] [i64 800, i64 800, i64 547]
// CHECK-DAG: [[SIZET6:@.+]] = private unnamed_addr constant [4 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2, i[[SZ]] 1, i[[SZ]] 40]
-// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [4 x i64] [i64 288, i64 288, i64 288, i64 547]
-// CHECK-DAG: [[MAPT7:@.+]] = private unnamed_addr constant [5 x i64] [i64 547, i64 288, i64 288, i64 288, i64 547]
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = {{.*}}constant [[ENTTY]]
-// TCHECK-NOT: @{{.+}} = constant [[ENTTY]]
+// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [4 x i64] [i64 800, i64 800, i64 800, i64 547]
+// CHECK-DAG: [[MAPT7:@.+]] = private unnamed_addr constant [6 x i64] [i64 32, i64 281474976711171, i64 800, i64 288, i64 288, i64 547]
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -73,7 +91,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx, typename ty>
@@ -97,7 +115,9 @@ int foo(int n) {
static long *plocal;
// CHECK: [[ADD:%.+]] = add nsw i32
- // CHECK: [[DEVICE:%.+]] = sext i32 [[ADD]] to i64
+ // CHECK: store i32 [[ADD]], i32* [[DEVICE_CAP:%.+]],
+ // CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+ // CHECK: [[DEVICE:%.+]] = sext i32 [[DEV]] to i64
// CHECK: [[RET:%.+]] = call i32 @__tgt_target(i64 [[DEVICE]], i8* @{{[^,]+}}, i32 0, i8** null, i8** null, i[[SZ]]* null, i64* null)
// CHECK-NEXT: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
@@ -110,7 +130,9 @@ int foo(int n) {
}
// CHECK-DAG: [[ADD:%.+]] = add nsw i32
- // CHECK-DAG: [[DEVICE:%.+]] = sext i32 [[ADD]] to i64
+ // CHECK-DAG: store i32 [[ADD]], i32* [[DEVICE_CAP:%.+]],
+ // CHECK-DAG: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+ // CHECK-DAG: [[DEVICE:%.+]] = sext i32 [[DEV]] to i64
// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_nowait(i64 [[DEVICE]], i8* @{{[^,]+}}, i32 2, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* getelementptr inbounds ([2 x i[[SZ]]], [2 x i[[SZ]]]* [[SIZET]], i32 0, i32 0), i64* getelementptr inbounds ([2 x i64], [2 x i64]* [[MAPT]], i32 0, i32 0)
// CHECK-DAG: [[BPR]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP:%[^,]+]], i32 0, i32 0
// CHECK-DAG: [[PR]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P:%[^,]+]], i32 0, i32 0
@@ -216,13 +238,13 @@ int foo(int n) {
// CHECK-32: store i32 [[A_VAL]], i32* [[A_CADDR:%.+]],
// CHECK-32: [[A_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[A_CADDR]],
+ // CHECK: [[IF:%.+]] = icmp sgt i32 {{[^,]+}}, 20
+ // CHECK: br i1 [[IF]], label %[[TRY:[^,]+]], label %[[IFELSE:[^,]+]]
+ // CHECK: [[TRY]]
// CHECK: [[BNSIZE:%.+]] = mul nuw i[[SZ]] [[VLA0:%.+]], 4
// CHECK: [[CNELEMSIZE2:%.+]] = mul nuw i[[SZ]] 5, [[VLA1:%.+]]
// CHECK: [[CNSIZE:%.+]] = mul nuw i[[SZ]] [[CNELEMSIZE2]], 8
- // CHECK: [[IF:%.+]] = icmp sgt i32 {{[^,]+}}, 20
- // CHECK: br i1 [[IF]], label %[[TRY:[^,]+]], label %[[IFELSE:[^,]+]]
- // CHECK: [[TRY]]
// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target(i64 -1, i8* @{{[^,]+}}, i32 9, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([9 x i64], [9 x i64]* [[MAPT4]], i32 0, i32 0))
// CHECK-DAG: [[BPR]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BP:%[^,]+]], i32 0, i32 0
// CHECK-DAG: [[PR]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P:%[^,]+]], i32 0, i32 0
@@ -489,67 +511,77 @@ int bar(int n){
// CHECK-64: store i32 %{{.+}}, i32* [[B_ADDR]],
// CHECK-64: [[B_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[B_CADDR]],
+// CHECK-32: store i32 %{{.+}}, i32* %__vla_expr
// CHECK-32: store i32 %{{.+}}, i32* [[B_ADDR:%.+]],
// CHECK-32: [[B_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[B_ADDR]],
+// CHECK: [[IF:%.+]] = icmp sgt i32 {{[^,]+}}, 60
+// CHECK: br i1 [[IF]], label %[[TRY:[^,]+]], label %[[IFELSE:[^,]+]]
+// CHECK: [[TRY]]
// We capture 2 VLA sizes in this target region
// CHECK: [[CELEMSIZE2:%.+]] = mul nuw i[[SZ]] 2, [[VLA0:%.+]]
// CHECK: [[CSIZE:%.+]] = mul nuw i[[SZ]] [[CELEMSIZE2]], 2
-// CHECK: [[IF:%.+]] = icmp sgt i32 {{[^,]+}}, 60
-// CHECK: br i1 [[IF]], label %[[TRY:[^,]+]], label %[[IFELSE:[^,]+]]
-// CHECK: [[TRY]]
-// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target(i64 -1, i8* @{{[^,]+}}, i32 5, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([5 x i64], [5 x i64]* [[MAPT7]], i32 0, i32 0))
-// CHECK-DAG: [[BPR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP:%.+]], i32 0, i32 0
-// CHECK-DAG: [[PR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P:%.+]], i32 0, i32 0
-// CHECK-DAG: [[SR]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0
-// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX0:0]]
-// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 0, i32 [[IDX0]]
-// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 0, i32 [[IDX0]]
-// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX1:1]]
-// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 0, i32 [[IDX1]]
-// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 0, i32 [[IDX1]]
-// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX2:2]]
-// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 0, i32 [[IDX2]]
-// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 0, i32 [[IDX2]]
-// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX3:3]]
-// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 0, i32 [[IDX3]]
-// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 0, i32 [[IDX3]]
-// CHECK-DAG: [[SADDR4:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX4:4]]
-// CHECK-DAG: [[BPADDR4:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 0, i32 [[IDX4]]
-// CHECK-DAG: [[PADDR4:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 0, i32 [[IDX4]]
+// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target(i64 -1, i8* @{{[^,]+}}, i32 6, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([6 x i64], [6 x i64]* [[MAPT7]], i32 0, i32 0))
+// CHECK-DAG: [[BPR]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP:%.+]], i32 0, i32 0
+// CHECK-DAG: [[PR]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P:%.+]], i32 0, i32 0
+// CHECK-DAG: [[SR]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0
+// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX0:0]]
+// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 0, i32 [[IDX0]]
+// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 0, i32 [[IDX0]]
+// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX1:1]]
+// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 0, i32 [[IDX1]]
+// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 0, i32 [[IDX1]]
+// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX2:2]]
+// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 0, i32 [[IDX2]]
+// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 0, i32 [[IDX2]]
+// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX3:3]]
+// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 0, i32 [[IDX3]]
+// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 0, i32 [[IDX3]]
+// CHECK-DAG: [[SADDR4:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX4:4]]
+// CHECK-DAG: [[BPADDR4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 0, i32 [[IDX4]]
+// CHECK-DAG: [[PADDR4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 0, i32 [[IDX4]]
+// CHECK-DAG: [[SADDR5:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX5:5]]
+// CHECK-DAG: [[BPADDR5:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 0, i32 [[IDX5]]
+// CHECK-DAG: [[PADDR5:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 0, i32 [[IDX5]]
// The names below are not necessarily consistent with the names used for the
// addresses above as some are repeated.
+// CHECK-DAG: [[CBPADDR5:%.+]] = bitcast i8** [[BPADDR5]] to i16**
+// CHECK-DAG: [[CPADDR5:%.+]] = bitcast i8** [[PADDR5]] to i16**
+// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR5]]
+// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR5]]
+// CHECK-DAG: store i[[SZ]] [[CSIZE]], i[[SZ]]* [[SADDR5]]
+
+// CHECK-DAG: [[CBPADDR4:%.+]] = bitcast i8** [[BPADDR4]] to i[[SZ]]*
+// CHECK-DAG: [[CPADDR4:%.+]] = bitcast i8** [[PADDR4]] to i[[SZ]]*
+// CHECK-DAG: store i[[SZ]] [[VLA0]], i[[SZ]]* [[CBPADDR4]]
+// CHECK-DAG: store i[[SZ]] [[VLA0]], i[[SZ]]* [[CPADDR4]]
+// CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* [[SADDR4]]
+
// CHECK-DAG: [[CBPADDR3:%.+]] = bitcast i8** [[BPADDR3]] to i[[SZ]]*
// CHECK-DAG: [[CPADDR3:%.+]] = bitcast i8** [[PADDR3]] to i[[SZ]]*
-// CHECK-DAG: store i[[SZ]] [[VLA0]], i[[SZ]]* [[CBPADDR3]]
-// CHECK-DAG: store i[[SZ]] [[VLA0]], i[[SZ]]* [[CPADDR3]]
+// CHECK-DAG: store i[[SZ]] 2, i[[SZ]]* [[CBPADDR3]]
+// CHECK-DAG: store i[[SZ]] 2, i[[SZ]]* [[CPADDR3]]
// CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* [[SADDR3]]
// CHECK-DAG: [[CBPADDR2:%.+]] = bitcast i8** [[BPADDR2]] to i[[SZ]]*
// CHECK-DAG: [[CPADDR2:%.+]] = bitcast i8** [[PADDR2]] to i[[SZ]]*
-// CHECK-DAG: store i[[SZ]] 2, i[[SZ]]* [[CBPADDR2]]
-// CHECK-DAG: store i[[SZ]] 2, i[[SZ]]* [[CPADDR2]]
-// CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* [[SADDR2]]
-
-// CHECK-DAG: [[CBPADDR1:%.+]] = bitcast i8** [[BPADDR1]] to i[[SZ]]*
-// CHECK-DAG: [[CPADDR1:%.+]] = bitcast i8** [[PADDR1]] to i[[SZ]]*
-// CHECK-DAG: store i[[SZ]] [[B_CVAL]], i[[SZ]]* [[CBPADDR1]]
-// CHECK-DAG: store i[[SZ]] [[B_CVAL]], i[[SZ]]* [[CPADDR1]]
-// CHECK-DAG: store i[[SZ]] 4, i[[SZ]]* [[SADDR1]]
+// CHECK-DAG: store i[[SZ]] [[B_CVAL]], i[[SZ]]* [[CBPADDR2]]
+// CHECK-DAG: store i[[SZ]] [[B_CVAL]], i[[SZ]]* [[CPADDR2]]
+// CHECK-DAG: store i[[SZ]] 4, i[[SZ]]* [[SADDR2]]
// CHECK-DAG: [[CBPADDR0:%.+]] = bitcast i8** [[BPADDR0]] to [[S1]]**
// CHECK-DAG: [[CPADDR0:%.+]] = bitcast i8** [[PADDR0]] to double**
-// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CBPADDR0]]
-// CHECK-DAG: store double* %{{.+}}, double** [[CPADDR0]]
-// CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* [[SADDR0]]
+// CHECK-DAG: store [[S1]]* [[THIS:%.+]], [[S1]]** [[CBPADDR0]]
+// CHECK-DAG: store double* [[A:%.+]], double** [[CPADDR0]]
+// CHECK-DAG: store i[[SZ]] %{{.+}}, i[[SZ]]* [[SADDR0]]
-// CHECK-DAG: [[CBPADDR4:%.+]] = bitcast i8** [[BPADDR4]] to i16**
-// CHECK-DAG: [[CPADDR4:%.+]] = bitcast i8** [[PADDR4]] to i16**
-// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR4]]
-// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR4]]
-// CHECK-DAG: store i[[SZ]] [[CSIZE]], i[[SZ]]* [[SADDR4]]
+// CHECK-DAG: [[CBPADDR1:%.+]] = bitcast i8** [[BPADDR1]] to [[S1]]**
+// CHECK-DAG: [[CPADDR1:%.+]] = bitcast i8** [[PADDR1]] to double**
+// CHECK-DAG: store [[S1]]* [[THIS]], [[S1]]** [[CBPADDR1]]
+// CHECK-DAG: store double* [[A]], double** [[CPADDR1]]
+// CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* [[SADDR1]]
// CHECK: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:.+]], label %[[END:[^,]+]]
@@ -727,4 +759,10 @@ int bar(int n){
// CHECK-32-DAG: load i32, i32* [[LOCAL_A]]
// CHECK-DAG: load i16, i16* [[REF_AA]]
// CHECK-DAG: getelementptr inbounds [10 x i32], [10 x i32]* [[REF_B]], i[[SZ]] 0, i[[SZ]] 2
+
+void bar () {
+#define pragma_target _Pragma("omp target")
+pragma_target
+{}
+}
#endif
diff --git a/test/OpenMP/target_codegen_global_capture.cpp b/test/OpenMP/target_codegen_global_capture.cpp
index eb34082b2940..27f8bcea020b 100644
--- a/test/OpenMP/target_codegen_global_capture.cpp
+++ b/test/OpenMP/target_codegen_global_capture.cpp
@@ -4,6 +4,14 @@
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -142,7 +150,7 @@ int foo(short a, short b, short c, short d){
// CHECK: define internal void [[OFFLOADF]]({{.+}} {{.*}}%{{.+}}, {{.+}} {{.*}}%{{.+}}, {{.+}} {{.*}}%{{.+}}, {{.+}} {{.*}}%{{.+}}, {{.+}} {{.*}}%{{.+}}, {{.+}} {{.*}}%{{.+}}, {{.+}} {{.*}}%{{.+}}, {{.+}} {{.*}}%{{.+}}, {{.+}} {{.*}}%{{.+}})
// The parallel region only uses 3 captures.
- // CHECK: call {{.*}}@__kmpc_fork_call(%ident_t* {{.+}}, i32 {{.+}}, void (i32*, i32*, ...)* bitcast ({{.*}}[[PARF:@.+]] to {{.*}}), {{.+}}* %{{.+}}, {{.+}}* %{{.+}}, {{.+}}* %{{.+}})
+ // CHECK: call {{.*}}@__kmpc_fork_call(%struct.ident_t* {{.+}}, i32 {{.+}}, void (i32*, i32*, ...)* bitcast ({{.*}}[[PARF:@.+]] to {{.*}}), {{.+}}* %{{.+}}, {{.+}}* %{{.+}}, {{.+}}* %{{.+}})
// CHECK: call void @.omp_outlined.(i32* %{{.+}}, i32* %{{.+}}, {{.+}}* %{{.+}}, {{.+}}* %{{.+}}, {{.+}}* %{{.+}})
// Capture d, Gd, Sd,
@@ -172,7 +180,7 @@ int bar(short a, short b, short c, short d){
static float Sc = 11.0;
static float Sd = 12.0;
- // CHECK: call void {{.*}}@__kmpc_fork_call(%ident_t* {{.+}}, i32 {{.+}}, void (i32*, i32*, ...)* bitcast ({{.*}}[[PARF:@.+]] to {{.*}}), i16* %{{.+}}, i16* %{{.+}}, i16* %{{.+}}, i16* %{{.+}})
+ // CHECK: call void {{.*}}@__kmpc_fork_call(%struct.ident_t* {{.+}}, i32 {{.+}}, void (i32*, i32*, ...)* bitcast ({{.*}}[[PARF:@.+]] to {{.*}}), i16* %{{.+}}, i16* %{{.+}}, i16* %{{.+}}, i16* %{{.+}})
// CHECK: define internal void [[PARF]](i32* noalias %{{.*}}, i32* noalias %{{.*}}, i16* dereferenceable(2) [[A:%.+]], i16* dereferenceable(2) [[B:%.+]], i16* dereferenceable(2) [[C:%.+]], i16* dereferenceable(2) [[D:%.+]])
// Capture a, b, c, d
// CHECK: [[ALLOCLA:%.+]] = alloca i16
@@ -280,7 +288,7 @@ int bar(short a, short b, short c, short d){
Sb += 1.0;
// CHECK: define internal void [[OFFLOADF]]({{.+}} {{.*}}%{{.+}}, {{.+}} {{.*}}%{{.+}}, {{.+}} {{.*}}%{{.+}}, {{.+}} {{.*}}%{{.+}}, {{.+}} {{.*}}%{{.+}}, {{.+}} {{.*}}%{{.+}}, {{.+}} {{.*}}%{{.+}}, {{.+}} {{.*}}%{{.+}}, {{.+}} {{.*}}%{{.+}})
- // CHECK: call void {{.*}}@__kmpc_fork_call(%ident_t* {{.+}}, i32 {{.+}}, void (i32*, i32*, ...)* bitcast ({{.*}}[[PARF:@.+]] to {{.*}})
+ // CHECK: call void {{.*}}@__kmpc_fork_call(%struct.ident_t* {{.+}}, i32 {{.+}}, void (i32*, i32*, ...)* bitcast ({{.*}}[[PARF:@.+]] to {{.*}})
// CHECK: define internal void [[PARF]](i32* noalias %{{.*}}, i32* noalias %{{.*}}, {{.+}}* dereferenceable({{.+}}) %{{.+}}, {{.+}}* dereferenceable({{.+}}) %{{.+}}, {{.+}}* dereferenceable({{.+}}) %{{.+}})
// Capture d, Gd, Sd
@@ -317,7 +325,7 @@ int tbar(T a, T b, T c, T d){
static float Sc = 19.0;
static float Sd = 20.0;
- // CHECK: call void {{.*}}@__kmpc_fork_call(%ident_t* {{.+}}, i32 {{.+}}, void (i32*, i32*, ...)* bitcast ({{.*}}[[PARF:@.+]] to {{.*}}), i16* %{{.+}}, i16* %{{.+}}, i16* %{{.+}}, i16* %{{.+}})
+ // CHECK: call void {{.*}}@__kmpc_fork_call(%struct.ident_t* {{.+}}, i32 {{.+}}, void (i32*, i32*, ...)* bitcast ({{.*}}[[PARF:@.+]] to {{.*}}), i16* %{{.+}}, i16* %{{.+}}, i16* %{{.+}}, i16* %{{.+}})
// CHECK: define internal void [[PARF]](i32* noalias %{{.*}}, i32* noalias %{{.*}}, i16* dereferenceable(2) [[A:%.+]], i16* dereferenceable(2) [[B:%.+]], i16* dereferenceable(2) [[C:%.+]], i16* dereferenceable(2) [[D:%.+]])
// Capture a, b, c, d
// CHECK: [[ALLOCLA:%.+]] = alloca i16
@@ -425,7 +433,7 @@ int tbar(T a, T b, T c, T d){
Sb += 1.0;
// CHECK: define internal void [[OFFLOADF]]({{.+}} {{.*}}%{{.+}}, {{.+}} {{.*}}%{{.+}}, {{.+}} {{.*}}%{{.+}}, {{.+}} {{.*}}%{{.+}}, {{.+}} {{.*}}%{{.+}}, {{.+}} {{.*}}%{{.+}}, {{.+}} {{.*}}%{{.+}}, {{.+}} {{.*}}%{{.+}}, {{.+}} {{.*}}%{{.+}})
- // CHECK: call void {{.*}}@__kmpc_fork_call(%ident_t* {{.+}}, i32 {{.+}}, void (i32*, i32*, ...)* bitcast ({{.*}}[[PARF:@.+]] to {{.*}})
+ // CHECK: call void {{.*}}@__kmpc_fork_call(%struct.ident_t* {{.+}}, i32 {{.+}}, void (i32*, i32*, ...)* bitcast ({{.*}}[[PARF:@.+]] to {{.*}})
// CHECK: define internal void [[PARF]](i32* noalias %{{.*}}, i32* noalias %{{.*}}, {{.+}}* dereferenceable({{.+}}) %{{.+}}, {{.+}}* dereferenceable({{.+}}) %{{.+}}, {{.+}}* dereferenceable({{.+}}) %{{.+}})
// Capture d, Gd, Sd
diff --git a/test/OpenMP/target_codegen_registration.cpp b/test/OpenMP/target_codegen_registration.cpp
index 5684b2573b6e..b98b33c9a4dd 100644
--- a/test/OpenMP/target_codegen_registration.cpp
+++ b/test/OpenMP/target_codegen_registration.cpp
@@ -6,6 +6,14 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// Test target codegen - host bc file has to be created first.
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s -check-prefix=TCHECK
@@ -16,9 +24,22 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s -check-prefix=TCHECK
-// Check that no target code is emmitted if no omptests flag was provided.
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
+// Check that no target code is emitted if no omptests flag was provided.
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s -check-prefix=CHECK-NTARGET
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// SIMD-ONLY2-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -60,96 +81,96 @@
// We have 7 target regions
-// CHECK-DAG: {{@.+}} = private constant i8 0
-// TCHECK-NOT: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = weak constant i8 0
+// TCHECK-NOT: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
-// CHECK-NTARGET-NOT: private constant i8 0
+// CHECK-NTARGET-NOT: weak constant i8 0
// CHECK-NTARGET-NOT: private unnamed_addr constant [1 x i
// CHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// CHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: @.omp_offloading.entry.[[NAME1]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// CHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: @.omp_offloading.entry.[[NAME2]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// CHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: @.omp_offloading.entry.[[NAME3]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// CHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: @.omp_offloading.entry.[[NAME4]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// CHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: @.omp_offloading.entry.[[NAME5]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// CHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: @.omp_offloading.entry.[[NAME6]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// CHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: @.omp_offloading.entry.[[NAME7]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// CHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: @.omp_offloading.entry.[[NAME8]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// CHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: @.omp_offloading.entry.[[NAME9]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// CHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: @.omp_offloading.entry.[[NAME10]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// CHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: @.omp_offloading.entry.[[NAME11]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// CHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: @.omp_offloading.entry.[[NAME12]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// TCHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: @.omp_offloading.entry.[[NAME1]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// TCHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: @.omp_offloading.entry.[[NAME2]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// TCHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: @.omp_offloading.entry.[[NAME3]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// TCHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: @.omp_offloading.entry.[[NAME4]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// TCHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: @.omp_offloading.entry.[[NAME5]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// TCHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: @.omp_offloading.entry.[[NAME6]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// TCHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: @.omp_offloading.entry.[[NAME7]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// TCHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: @.omp_offloading.entry.[[NAME8]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// TCHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: @.omp_offloading.entry.[[NAME9]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// TCHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: @.omp_offloading.entry.[[NAME10]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// TCHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: @.omp_offloading.entry.[[NAME11]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// TCHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: @.omp_offloading.entry.[[NAME12]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
// CHECK: [[ENTEND:@.+]] = external constant [[ENTTY]]
@@ -163,7 +184,7 @@
// CHECK-SAME: { i32, void ()*, i8* } { i32 500, void ()* [[P500:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 501, void ()* [[P501:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 65535, void ()* [[PMAX:@[^,]+]], i8* null },
-// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
// CHECK-NTARGET: @llvm.global_ctors = appending global [3 x { i32, void ()*, i8* }] [
@@ -319,18 +340,18 @@ struct ST {
//CHECK-DAG: define internal void @[[NAME12]](
//CHECK-DAG: call void @[[NAME12]](
-//TCHECK-DAG: define void @[[NAME1]](
-//TCHECK-DAG: define void @[[NAME2]](
-//TCHECK-DAG: define void @[[NAME3]](
-//TCHECK-DAG: define void @[[NAME4]](
-//TCHECK-DAG: define void @[[NAME5]](
-//TCHECK-DAG: define void @[[NAME6]](
-//TCHECK-DAG: define void @[[NAME7]](
-//TCHECK-DAG: define void @[[NAME8]](
-//TCHECK-DAG: define void @[[NAME9]](
-//TCHECK-DAG: define void @[[NAME10]](
-//TCHECK-DAG: define void @[[NAME11]](
-//TCHECK-DAG: define void @[[NAME12]](
+//TCHECK-DAG: define weak void @[[NAME1]](
+//TCHECK-DAG: define weak void @[[NAME2]](
+//TCHECK-DAG: define weak void @[[NAME3]](
+//TCHECK-DAG: define weak void @[[NAME4]](
+//TCHECK-DAG: define weak void @[[NAME5]](
+//TCHECK-DAG: define weak void @[[NAME6]](
+//TCHECK-DAG: define weak void @[[NAME7]](
+//TCHECK-DAG: define weak void @[[NAME8]](
+//TCHECK-DAG: define weak void @[[NAME9]](
+//TCHECK-DAG: define weak void @[[NAME10]](
+//TCHECK-DAG: define weak void @[[NAME11]](
+//TCHECK-DAG: define weak void @[[NAME12]](
// CHECK-NTARGET-NOT: __tgt_target
// CHECK-NTARGET-NOT: __tgt_register_lib
@@ -372,7 +393,7 @@ struct ST {
//CHECK: ret void
//CHECK: declare i32 @__tgt_unregister_lib([[DSCTY]]*)
-//CHECK: define linkonce hidden void @[[REGFN]](i8*)
+//CHECK: define linkonce hidden void @[[REGFN]]()
//CHECK-SAME: comdat {
//CHECK: call i32 @__tgt_register_lib([[DSCTY]]* [[DESC]])
//CHECK: call i32 @__cxa_atexit(void (i8*)* @[[UNREGFN]], i8* bitcast ([[DSCTY]]* [[DESC]] to i8*),
@@ -411,31 +432,31 @@ int bar(int a){
// Check metadata is properly generated:
// CHECK: !omp_offload.info = !{!{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 195, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 245, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 261, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 267, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 278, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 284, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 406, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 290, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 284, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 290, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 278, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 220, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 216, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 266, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 282, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 288, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 299, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 305, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 427, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 311, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 305, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 311, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 299, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 241, i32 {{[0-9]+}}}
// TCHECK: !omp_offload.info = !{!{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 195, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 245, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 261, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 267, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 278, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 284, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 406, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 290, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 284, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 290, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 278, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 220, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 216, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 266, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 282, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 288, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 299, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 305, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 427, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 311, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 305, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 311, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 299, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 241, i32 {{[0-9]+}}}
#endif
diff --git a/test/OpenMP/target_codegen_registration_naming.cpp b/test/OpenMP/target_codegen_registration_naming.cpp
index ce133eee03e8..0d584b87d251 100644
--- a/test/OpenMP/target_codegen_registration_naming.cpp
+++ b/test/OpenMP/target_codegen_registration_naming.cpp
@@ -6,6 +6,14 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// Test target codegen - host bc file has to be created first.
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s -check-prefix=TCHECK
@@ -16,6 +24,16 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s -check-prefix=TCHECK
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/target_data_ast_print.cpp b/test/OpenMP/target_data_ast_print.cpp
index bb55ea30d532..17dace8bfac8 100644
--- a/test/OpenMP/target_data_ast_print.cpp
+++ b/test/OpenMP/target_data_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -48,7 +52,7 @@ T tmain(T argc, T *argv) {
// CHECK: template <typename T, int C> T tmain(T argc, T *argv) {
// CHECK-NEXT: T i, j, b, c, d, e, x[20];
-// CHECK-NEXT: #pragma omp target data map(to: c)
+// CHECK-NEXT: #pragma omp target data map(to: c){{$}}
// CHECK-NEXT: i = argc;
// CHECK-NEXT: #pragma omp target data map(to: c) if(target data: j > 0)
// CHECK-NEXT: foo();
diff --git a/test/OpenMP/target_data_codegen.cpp b/test/OpenMP/target_data_codegen.cpp
index 2c9526de73e1..80f7096a0b52 100644
--- a/test/OpenMP/target_data_codegen.cpp
+++ b/test/OpenMP/target_data_codegen.cpp
@@ -9,6 +9,14 @@
// RUN: %clang_cc1 -DCK1 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
// RUN: %clang_cc1 -DCK1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
#ifdef CK1
// CK1: [[ST:%.+]] = type { i32, double* }
@@ -29,8 +37,9 @@ double gc[100];
// CK1: [[MTYPE03:@.+]] = {{.+}}constant [1 x i64] [i64 37]
-// CK1: [[SIZE04:@.+]] = {{.+}}constant [2 x i[[sz]]] [i[[sz]] {{8|4}}, i[[sz]] 24]
-// CK1: [[MTYPE04:@.+]] = {{.+}}constant [2 x i64] [i64 33, i64 17]
+// CK1-64: [[SIZE04:@.+]] = {{.+}}constant [2 x i64] [i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)), i64 24]
+// CK1-32: [[SIZE04:@.+]] = {{.+}}constant [2 x i32] [i32 trunc (i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)) to i32), i32 24]
+// CK1: [[MTYPE04:@.+]] = {{.+}}constant [2 x i64] [i64 32, i64 281474976710673]
// CK1-LABEL: _Z3fooi
void foo(int arg) {
@@ -57,7 +66,7 @@ void foo(int arg) {
// CK1-DAG: [[DEV]] = sext i32 [[DEVi32:%[^,]+]] to i64
// CK1-DAG: [[DEVi32]] = load i32, i32* %{{[^,]+}},
// CK1-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP]]
- // CK1-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P]]
+// CK1-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P]]
#pragma omp target data if(1+3-5) device(arg) map(from: gc)
{++arg;}
@@ -137,7 +146,6 @@ void foo(int arg) {
// CK1-DAG: store [[ST]]* @gb, [[ST]]** [[CBP0]]
// CK1-DAG: store double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1), double*** [[CP0]]
-
// CK1-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
// CK1-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
// CK1-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double***
@@ -163,6 +171,14 @@ void foo(int arg) {
// RUN: %clang_cc1 -DCK2 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
// RUN: %clang_cc1 -DCK2 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
#ifdef CK2
// CK2: [[ST:%.+]] = type { i32, double* }
@@ -179,8 +195,7 @@ struct ST {
}
};
-// CK2: [[SIZE00:@.+]] = {{.+}}constant [2 x i[[sz:64|32]]] [i{{64|32}} {{8|4}}, i{{64|32}} 24]
-// CK2: [[MTYPE00:@.+]] = {{.+}}constant [2 x i64] [i64 37, i64 21]
+// CK2: [[MTYPE00:@.+]] = {{.+}}constant [2 x i64] [i64 32, i64 281474976710677]
// CK2-LABEL: _Z3bari
int bar(int arg){
@@ -191,27 +206,31 @@ int bar(int arg){
// Region 00
// CK2: br i1 %{{[^,]+}}, label %[[IFTHEN:[^,]+]], label %[[IFELSE:[^,]+]]
// CK2: [[IFTHEN]]
-// CK2-DAG: call void @__tgt_target_data_begin(i64 [[DEV:%[^,]+]], i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[SIZE00]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE00]]{{.+}})
+// CK2-DAG: call void @__tgt_target_data_begin(i64 [[DEV:%[^,]+]], i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE00]]{{.+}})
// CK2-DAG: [[DEV]] = sext i32 [[DEVi32:%[^,]+]] to i64
// CK2-DAG: [[DEVi32]] = load i32, i32* %{{[^,]+}},
-// CK2-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
-// CK2-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
+// CK2-DAG: [[GEPBP]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP:%[^,]+]]
+// CK2-DAG: [[GEPP]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P:%[^,]+]]
+// CK2-DAG: [[GEPS]] = getelementptr inbounds [2 x i[[sz]]], [2 x i[[sz]]]* [[S:%[^,]+]]
// CK2-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK2-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
+// CK2-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
// CK2-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]**
// CK2-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double***
// CK2-DAG: store [[ST]]* [[VAR0:%.+]], [[ST]]** [[CBP0]]
// CK2-DAG: store double** [[SEC0:%.+]], double*** [[CP0]]
+// CK2-DAG: store i[[sz]] {{%.+}}, i[[sz]]* [[S0]]
// CK2-DAG: [[SEC0]] = getelementptr inbounds {{.*}}[[ST]]* [[VAR0]], i32 0, i32 1
-
// CK2-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
// CK2-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+// CK2-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1
// CK2-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double***
// CK2-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double**
// CK2-DAG: store double** [[SEC0]], double*** [[CBP1]]
// CK2-DAG: store double* [[SEC1:%.+]], double** [[CP1]]
+// CK2-DAG: store i[[sz]] 24, i[[sz]]* [[S1]]
// CK2-DAG: [[SEC1]] = getelementptr inbounds {{.*}}double* [[SEC11:%[^,]+]], i{{.+}} 1
// CK2-DAG: [[SEC11]] = load double*, double** [[SEC111:%[^,]+]],
// CK2-DAG: [[SEC111]] = getelementptr inbounds {{.*}}[[ST]]* [[VAR0]], i32 0, i32 1
@@ -225,11 +244,12 @@ int bar(int arg){
// CK2: br i1 %{{[^,]+}}, label %[[IFTHEN:[^,]+]], label %[[IFELSE:[^,]+]]
// CK2: [[IFTHEN]]
-// CK2-DAG: call void @__tgt_target_data_end(i64 [[DEV:%[^,]+]], i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[SIZE00]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE00]]{{.+}})
+// CK2-DAG: call void @__tgt_target_data_end(i64 [[DEV:%[^,]+]], i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE00]]{{.+}})
// CK2-DAG: [[DEV]] = sext i32 [[DEVi32:%[^,]+]] to i64
// CK2-DAG: [[DEVi32]] = load i32, i32* %{{[^,]+}},
// CK2-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP]]
// CK2-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P]]
+// CK2-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S]]
// CK2: br label %[[IFEND:[^,]+]]
// CK2: [[IFELSE]]
// CK2: br label %[[IFEND]]
@@ -242,6 +262,14 @@ int bar(int arg){
// RUN: %clang_cc1 -DCK3 -verify -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-32
// RUN: %clang_cc1 -DCK3 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-32
+
+// RUN: %clang_cc1 -DCK3 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// RUN: %clang_cc1 -DCK3 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// RUN: %clang_cc1 -DCK3 -verify -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// RUN: %clang_cc1 -DCK3 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// SIMD-ONLY2-NOT: {{__kmpc|__tgt}}
#ifdef CK3
// CK3-LABEL: no_target_devices
diff --git a/test/OpenMP/target_data_device_messages.cpp b/test/OpenMP/target_data_device_messages.cpp
index 9ed7a54b4399..51c809a8653e 100644
--- a/test/OpenMP/target_data_device_messages.cpp
+++ b/test/OpenMP/target_data_device_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/target_data_if_messages.cpp b/test/OpenMP/target_data_if_messages.cpp
index 229d7f564738..ae68d252a8e1 100644
--- a/test/OpenMP/target_data_if_messages.cpp
+++ b/test/OpenMP/target_data_if_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -fopenmp-version=45 -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -fopenmp-version=45 -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/target_data_messages.c b/test/OpenMP/target_data_messages.c
index fd41e7df2a4c..017a339cc017 100644
--- a/test/OpenMP/target_data_messages.c
+++ b/test/OpenMP/target_data_messages.c
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo() { }
int main(int argc, char **argv) {
diff --git a/test/OpenMP/target_data_use_device_ptr_ast_print.cpp b/test/OpenMP/target_data_use_device_ptr_ast_print.cpp
index ce1ec1d2799a..ba429f50febe 100644
--- a/test/OpenMP/target_data_use_device_ptr_ast_print.cpp
+++ b/test/OpenMP/target_data_use_device_ptr_ast_print.cpp
@@ -1,6 +1,9 @@
// RxUN: %clang_cc1 -verify -fopenmp -std=c++11 -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -23,7 +26,7 @@ struct SA {
};
// CHECK: struct SA
// CHECK: void func(
-// CHECK: #pragma omp target data map(tofrom: this->i) use_device_ptr(this->k)
+// CHECK: #pragma omp target data map(tofrom: this->i) use_device_ptr(this->k){{$}}
// CHECK: #pragma omp target data map(tofrom: this->i) use_device_ptr(this->z)
struct SB {
unsigned A;
diff --git a/test/OpenMP/target_data_use_device_ptr_codegen.cpp b/test/OpenMP/target_data_use_device_ptr_codegen.cpp
index 36c42e32ea3f..a3d8043b6b4e 100644
--- a/test/OpenMP/target_data_use_device_ptr_codegen.cpp
+++ b/test/OpenMP/target_data_use_device_ptr_codegen.cpp
@@ -9,6 +9,14 @@
// RUN: %clang_cc1 -DCK1 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
// RUN: %clang_cc1 -DCK1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
#ifdef CK1
double *g;
@@ -327,13 +335,21 @@ void bar(float *&a, int *&b) {
// RUN: %clang_cc1 -DCK2 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
// RUN: %clang_cc1 -DCK2 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
#ifdef CK2
// CK2: [[ST:%.+]] = type { double*, double** }
-// CK2: [[MTYPE00:@.+]] = {{.*}}constant [2 x i64] [i64 35, i64 83]
-// CK2: [[MTYPE01:@.+]] = {{.*}}constant [3 x i64] [i64 32, i64 19, i64 83]
-// CK2: [[MTYPE02:@.+]] = {{.*}}constant [2 x i64] [i64 96, i64 35]
-// CK2: [[MTYPE03:@.+]] = {{.*}}constant [4 x i64] [i64 96, i64 32, i64 19, i64 83]
+// CK2: [[MTYPE00:@.+]] = {{.*}}constant [2 x i64] [i64 32, i64 281474976710739]
+// CK2: [[MTYPE01:@.+]] = {{.*}}constant [2 x i64] [i64 32, i64 281474976710739]
+// CK2: [[MTYPE02:@.+]] = {{.*}}constant [3 x i64] [i64 35, i64 32, i64 562949953421392]
+// CK2: [[MTYPE03:@.+]] = {{.*}}constant [3 x i64] [i64 32, i64 281474976710739, i64 281474976710736]
template <typename T>
struct ST {
@@ -366,7 +382,7 @@ struct ST {
// CK2: getelementptr inbounds double, double* [[TTT]], i32 1
a++;
- // CK2: [[BP:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* %{{.+}}, i32 0, i32 2
+ // CK2: [[BP:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* %{{.+}}, i32 0, i32 1
// CK2: [[CBP:%.+]] = bitcast i8** [[BP]] to double***
// CK2: store double** [[RVAL:%.+]], double*** [[CBP]],
// CK2: call void @__tgt_target_data_begin{{.+}}[[MTYPE01]]
@@ -388,11 +404,12 @@ struct ST {
// CK2: getelementptr inbounds double, double* [[TTTT]], i32 1
b++;
- // CK2: [[BP:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* %{{.+}}, i32 0, i32 0
- // CK2: [[CBP:%.+]] = bitcast i8** [[BP]] to double**
- // CK2: store double* [[RVAL:%.+]], double** [[CBP]],
+ // CK2: [[BP:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* %{{.+}}, i32 0, i32 2
+ // CK2: [[CBP:%.+]] = bitcast i8** [[BP]] to double***
+ // CK2: store double** [[RVAL:%.+]], double*** [[CBP]],
// CK2: call void @__tgt_target_data_begin{{.+}}[[MTYPE02]]
- // CK2: [[VAL:%.+]] = load double*, double** [[CBP]],
+ // CK2: [[CVAL:%.+]] = bitcast double*** [[CBP]] to double**
+ // CK2: [[VAL:%.+]] = load double*, double** [[CVAL]],
// CK2: store double* [[VAL]], double** [[PVT:%.+]],
// CK2: store double** [[PVT]], double*** [[PVT2:%.+]],
// CK2: [[TT1:%.+]] = load double**, double*** [[PVT2]],
@@ -410,26 +427,27 @@ struct ST {
a++;
la++;
- // CK2: [[BP:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* %{{.+}}, i32 0, i32 0
- // CK2: [[CBP:%.+]] = bitcast i8** [[BP]] to double**
- // CK2: store double* [[RVAL:%.+]], double** [[CBP]],
- // CK2: [[_BP:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* %{{.+}}, i32 0, i32 3
- // CK2: [[_CBP:%.+]] = bitcast i8** [[_BP]] to double***
- // CK2: store double** [[_RVAL:%.+]], double*** [[_CBP]],
+ // CK2: [[BP1:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* %{{.+}}, i32 0, i32 1
+ // CK2: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double***
+ // CK2: store double** [[RVAL1:%.+]], double*** [[CBP1]],
+ // CK2: [[BP2:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* %{{.+}}, i32 0, i32 2
+ // CK2: [[CBP2:%.+]] = bitcast i8** [[BP2]] to double***
+ // CK2: store double** [[RVAL2:%.+]], double*** [[CBP2]],
// CK2: call void @__tgt_target_data_begin{{.+}}[[MTYPE03]]
- // CK2: [[VAL:%.+]] = load double*, double** [[CBP]],
- // CK2: store double* [[VAL]], double** [[PVT:%.+]],
- // CK2: store double** [[PVT]], double*** [[PVT2:%.+]],
- // CK2: [[_CBP1:%.+]] = bitcast double*** [[_CBP]] to double**
- // CK2: [[_VAL:%.+]] = load double*, double** [[_CBP1]],
- // CK2: store double* [[_VAL]], double** [[_PVT:%.+]],
- // CK2: store double** [[_PVT]], double*** [[_PVT2:%.+]],
- // CK2: [[TT1:%.+]] = load double**, double*** [[PVT2]],
- // CK2: [[TT2:%.+]] = load double*, double** [[TT1]],
- // CK2: getelementptr inbounds double, double* [[TT2]], i32 1
- // CK2: [[_TT1:%.+]] = load double**, double*** [[_PVT2]],
- // CK2: [[_TT2:%.+]] = load double*, double** [[_TT1]],
+ // CK2: [[_CBP2:%.+]] = bitcast double*** [[CBP2]] to double**
+ // CK2: [[VAL2:%.+]] = load double*, double** [[_CBP2]],
+ // CK2: store double* [[VAL2]], double** [[PVT2:%.+]],
+ // CK2: store double** [[PVT2]], double*** [[_PVT2:%.+]],
+ // CK2: [[_CBP1:%.+]] = bitcast double*** [[CBP1]] to double**
+ // CK2: [[VAL1:%.+]] = load double*, double** [[_CBP1]],
+ // CK2: store double* [[VAL1]], double** [[PVT1:%.+]],
+ // CK2: store double** [[PVT1]], double*** [[_PVT1:%.+]],
+ // CK2: [[TT2:%.+]] = load double**, double*** [[_PVT2]],
+ // CK2: [[_TT2:%.+]] = load double*, double** [[TT2]],
// CK2: getelementptr inbounds double, double* [[_TT2]], i32 1
+ // CK2: [[TT1:%.+]] = load double**, double*** [[_PVT1]],
+ // CK2: [[_TT1:%.+]] = load double*, double** [[TT1]],
+ // CK2: getelementptr inbounds double, double* [[_TT1]], i32 1
#pragma omp target data map(b[:10]) use_device_ptr(a, b)
{
a++;
diff --git a/test/OpenMP/target_data_use_device_ptr_messages.cpp b/test/OpenMP/target_data_use_device_ptr_messages.cpp
index 1d8002c1ff60..87f23e2de77b 100644
--- a/test/OpenMP/target_data_use_device_ptr_messages.cpp
+++ b/test/OpenMP/target_data_use_device_ptr_messages.cpp
@@ -1,4 +1,6 @@
// RUN: %clang_cc1 -std=c++11 -verify -fopenmp -ferror-limit 200 %s
+
+// RUN: %clang_cc1 -std=c++11 -verify -fopenmp-simd -ferror-limit 200 %s
struct ST {
int *a;
};
diff --git a/test/OpenMP/target_defaultmap_messages.cpp b/test/OpenMP/target_defaultmap_messages.cpp
index 59348d42c525..27079c302811 100644
--- a/test/OpenMP/target_defaultmap_messages.cpp
+++ b/test/OpenMP/target_defaultmap_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_depend_codegen.cpp b/test/OpenMP/target_depend_codegen.cpp
new file mode 100644
index 000000000000..bd709e1def7d
--- /dev/null
+++ b/test/OpenMP/target_depend_codegen.cpp
@@ -0,0 +1,261 @@
+// Test host codegen.
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+// Test target codegen - host bc file has to be created first.
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+// CHECK-DAG: [[TT:%.+]] = type { i64, i8 }
+// CHECK-DAG: [[ENTTY:%.+]] = type { i8*, i8*, i[[SZ:32|64]], i32, i32 }
+// CHECK-DAG: [[DEVTY:%.+]] = type { i8*, i8*, [[ENTTY]]*, [[ENTTY]]* }
+// CHECK-DAG: [[DSCTY:%.+]] = type { i32, [[DEVTY]]*, [[ENTTY]]*, [[ENTTY]]* }
+
+// TCHECK: [[ENTTY:%.+]] = type { i8*, i8*, i{{32|64}}, i32, i32 }
+
+// CHECK-DAG: $[[REGFN:\.omp_offloading\..+]] = comdat
+
+// CHECK-DAG: [[SIZET:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 0, i[[SZ]] 4]
+// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 544, i64 800]
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = {{.*}}constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
+
+// Check if offloading descriptor is created.
+// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
+// CHECK: [[ENTEND:@.+]] = external constant [[ENTTY]]
+// CHECK: [[DEVBEGIN:@.+]] = external constant i8
+// CHECK: [[DEVEND:@.+]] = external constant i8
+// CHECK: [[IMAGES:@.+]] = internal unnamed_addr constant [1 x [[DEVTY]]] [{{.+}} { i8* [[DEVBEGIN]], i8* [[DEVEND]], [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }], comdat($[[REGFN]])
+// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
+
+// Check target registration is registered as a Ctor.
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
+
+
+template<typename tx, typename ty>
+struct TT{
+ tx X;
+ ty Y;
+};
+
+int global;
+extern int global;
+
+// CHECK: define {{.*}}[[FOO:@.+]](
+int foo(int n) {
+ int a = 0;
+ short aa = 0;
+ float b[10];
+ float bn[n];
+ double c[5][10];
+ double cn[5][n];
+ TT<long long, char> d;
+ static long *plocal;
+
+ // CHECK: [[ADD:%.+]] = add nsw i32
+ // CHECK: store i32 [[ADD]], i32* [[DEVICE_CAP:%.+]],
+ // CHECK: [[GEP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+ // CHECK: store i32 [[DEV]], i32* [[GEP]],
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* @0, i32 [[GTID:%.+]], i32 1, i[[SZ]] {{20|40}}, i[[SZ]] 4, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY0:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY0:%.+]]*
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 1
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 2
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 3
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call void @__kmpc_omp_wait_deps(%struct.ident_t* @0, i32 [[GTID]], i32 4, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: call void @__kmpc_omp_task_begin_if0(%struct.ident_t* @0, i32 [[GTID]], i8* [[TASK]])
+ // CHECK: call i32 [[TASK_ENTRY0]](i32 [[GTID]], [[TASK_TY0]]* [[BC_TASK]])
+ // CHECK: call void @__kmpc_omp_task_complete_if0(%struct.ident_t* @0, i32 [[GTID]], i8* [[TASK]])
+ #pragma omp target device(global + a) depend(in: global) depend(out: a, b, cn[4])
+ {
+ }
+
+ // CHECK: [[ADD:%.+]] = add nsw i32
+ // CHECK: store i32 [[ADD]], i32* [[DEVICE_CAP:%.+]],
+
+ // CHECK: [[BOOL:%.+]] = icmp ne i32 %{{.+}}, 0
+ // CHECK: br i1 [[BOOL]], label %[[THEN:.+]], label %[[ELSE:.+]]
+ // CHECK: [[THEN]]:
+ // CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP:%.+]], i32 0, i32 0
+ // CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P:%.+]], i32 0, i32 0
+ // CHECK-DAG: [[CBPADDR0:%.+]] = bitcast i8** [[BPADDR0]] to i[[SZ]]**
+ // CHECK-DAG: [[CPADDR0:%.+]] = bitcast i8** [[PADDR0]] to i[[SZ]]**
+ // CHECK-DAG: store i[[SZ]]* [[BP0:%[^,]+]], i[[SZ]]** [[CBPADDR0]]
+ // CHECK-DAG: store i[[SZ]]* [[BP0]], i[[SZ]]** [[CPADDR0]]
+
+ // CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 1
+ // CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P]], i32 0, i32 1
+ // CHECK-DAG: [[CBPADDR1:%.+]] = bitcast i8** [[BPADDR1]] to i[[SZ]]*
+ // CHECK-DAG: [[CPADDR1:%.+]] = bitcast i8** [[PADDR1]] to i[[SZ]]*
+ // CHECK-DAG: store i[[SZ]] [[BP1:%[^,]+]], i[[SZ]]* [[CBPADDR1]]
+ // CHECK-DAG: store i[[SZ]] [[BP1]], i[[SZ]]* [[CPADDR1]]
+ // CHECK-DAG: getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 0
+ // CHECK-DAG: getelementptr inbounds [2 x i8*], [2 x i8*]* [[P]], i32 0, i32 0
+ // CHECK: [[GEP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+ // CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+ // CHECK: store i32 [[DEV]], i32* [[GEP]],
+
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* @0, i32 [[GTID]], i32 1, i[[SZ]] {{104|52}}, i[[SZ]] {{16|12}}, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY1_:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY1_:%.+]]*
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 1
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 2
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call i32 @__kmpc_omp_task_with_deps(%struct.ident_t* @0, i32 [[GTID]], i8* [[TASK]], i32 3, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: br label %[[EXIT:.+]]
+
+ // CHECK: [[ELSE]]:
+ // CHECK-NOT: getelementptr inbounds [2 x i8*], [2 x i8*]*
+ // CHECK: [[GEP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+ // CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+ // CHECK: store i32 [[DEV]], i32* [[GEP]],
+
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* @0, i32 [[GTID]], i32 1, i[[SZ]] {{56|28}}, i[[SZ]] {{16|12}}, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY1__:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY1__:%.+]]*
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 1
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 2
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call i32 @__kmpc_omp_task_with_deps(%struct.ident_t* @0, i32 [[GTID]], i8* [[TASK]], i32 3, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: br label %[[EXIT:.+]]
+ // CHECK: [[EXIT]]:
+
+ #pragma omp target device(global + a) nowait depend(inout: global, a, bn) if(a)
+ {
+ static int local1;
+ *plocal = global;
+ local1 = global;
+ }
+
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* @0, i32 [[GTID]], i32 1, i[[SZ]] {{48|24}}, i[[SZ]] 4, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY2:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY2:%.+]]*
+ // CHECK: getelementptr inbounds [1 x %struct.kmp_depend_info], [1 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [1 x %struct.kmp_depend_info], [1 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call void @__kmpc_omp_wait_deps(%struct.ident_t* @0, i32 [[GTID]], i32 1, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: call void @__kmpc_omp_task_begin_if0(%struct.ident_t* @0, i32 [[GTID]], i8* [[TASK]])
+ // CHECK: call i32 [[TASK_ENTRY2]](i32 [[GTID]], [[TASK_TY2]]* [[BC_TASK]])
+ // CHECK: call void @__kmpc_omp_task_complete_if0(%struct.ident_t* @0, i32 [[GTID]], i8* [[TASK]])
+ #pragma omp target if(0) firstprivate(global) depend(out:global)
+ {
+ global += 1;
+ }
+
+ return a;
+}
+
+// Check that the offloading functions are emitted and that the arguments are
+// correct and loaded correctly for the target regions in foo().
+
+// CHECK: define internal void [[HVT0:@.+]]()
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY0]](i32{{.*}}, [[TASK_TY0]]* noalias)
+// CHECK: store void (i8*, ...)* null, void (i8*, ...)** %
+// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 0
+// CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+// CHECK: [[DEVICE:%.+]] = sext i32 [[DEV]] to i64
+// CHECK: [[RET:%.+]] = call i32 @__tgt_target(i64 [[DEVICE]], i8* @{{[^,]+}}, i32 0, i8** null, i8** null, i[[SZ]]* null, i64* null)
+// CHECK-NEXT: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
+// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
+// CHECK: [[FAIL]]
+// CHECK: call void [[HVT0]]()
+// CHECK-NEXT: br label %[[END]]
+// CHECK: [[END]]
+// CHECK: ret i32 0
+
+// CHECK: define internal void [[HVT1:@.+]](i[[SZ]]* %{{.+}}, i[[SZ]] %{{.+}})
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY1_]](i32{{.*}}, [[TASK_TY1_]]* noalias)
+// CHECK: call void (i8*, ...) %
+// CHECK: [[SZT:%.+]] = getelementptr inbounds [2 x i[[SZ]]], [2 x i[[SZ]]]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+// CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+// CHECK: [[DEVICE:%.+]] = sext i32 [[DEV]] to i64
+// CHECK: [[RET:%.+]] = call i32 @__tgt_target_nowait(i64 [[DEVICE]], i8* @{{[^,]+}}, i32 2, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SZT]], i64* getelementptr inbounds ([2 x i64], [2 x i64]* [[MAPT]], i32 0, i32 0)
+
+// CHECK: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
+// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
+// CHECK: [[FAIL]]
+// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
+// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
+// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
+// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
+// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
+// CHECK: [[BP1:%.+]] = load i[[SZ]], i[[SZ]]* [[BP1_PTR]],
+// CHECK: call void [[HVT1]](i[[SZ]]* [[BP0]], i[[SZ]] [[BP1]])
+// CHECK-NEXT: br label %[[END]]
+// CHECK: [[END]]
+// CHECK: ret i32 0
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY1__]](i32{{.*}}, [[TASK_TY1__]]* noalias)
+// CHECK: call void (i8*, ...) %
+// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
+// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
+// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
+// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
+// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
+// CHECK: [[BP1:%.+]] = load i[[SZ]], i[[SZ]]* [[BP1_PTR]],
+// CHECK: call void [[HVT1]](i[[SZ]]* [[BP0]], i[[SZ]] [[BP1]])
+// CHECK: ret i32 0
+
+// CHECK: define internal void [[HVT2:@.+]](i[[SZ]] %{{.+}})
+// Create stack storage and store argument in there.
+// CHECK: [[AA_ADDR:%.+]] = alloca i[[SZ]], align
+// CHECK: store i[[SZ]] %{{.+}}, i[[SZ]]* [[AA_ADDR]], align
+// CHECK-64: [[AA_CADDR:%.+]] = bitcast i[[SZ]]* [[AA_ADDR]] to i32*
+// CHECK-64: load i32, i32* [[AA_CADDR]], align
+// CHECK-32: load i32, i32* [[AA_ADDR]], align
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY2]](i32{{.*}}, [[TASK_TY2]]* noalias)
+// CHECK: call void (i8*, ...) %
+// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
+// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
+// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
+// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
+// CHECK: [[BP1:%.+]] = load i[[SZ]], i[[SZ]]* [[BP1_PTR]],
+// CHECK: call void [[HVT2]](i[[SZ]] [[BP1]])
+// CHECK: ret i32 0
+
+
+#endif
diff --git a/test/OpenMP/target_depend_messages.cpp b/test/OpenMP/target_depend_messages.cpp
index 3eb3af132d8f..5fdf37daf7dd 100644
--- a/test/OpenMP/target_depend_messages.cpp
+++ b/test/OpenMP/target_depend_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_device_messages.cpp b/test/OpenMP/target_device_messages.cpp
index 3befcd690810..8cf19b25970d 100644
--- a/test/OpenMP/target_device_messages.cpp
+++ b/test/OpenMP/target_device_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/target_enter_data_ast_print.cpp b/test/OpenMP/target_enter_data_ast_print.cpp
index 865cc7f1c17e..1df1f8e1d618 100644
--- a/test/OpenMP/target_enter_data_ast_print.cpp
+++ b/test/OpenMP/target_enter_data_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -65,7 +69,7 @@ T tmain(T argc, T *argv) {
// CHECK: template <typename T, int C> T tmain(T argc, T *argv) {
// CHECK-NEXT: T i, j, b, c, d, e, x[20];
// CHECK-NEXT: i = argc;
-// CHECK-NEXT: #pragma omp target enter data map(to: i)
+// CHECK-NEXT: #pragma omp target enter data map(to: i){{$}}
// CHECK-NEXT: #pragma omp target enter data map(to: i) if(target enter data: j > 0)
// CHECK-NEXT: #pragma omp target enter data map(to: i) if(b)
// CHECK-NEXT: #pragma omp target enter data map(to: c)
diff --git a/test/OpenMP/target_enter_data_codegen.cpp b/test/OpenMP/target_enter_data_codegen.cpp
index 08b6c7c2702e..b337fccb1c4c 100644
--- a/test/OpenMP/target_enter_data_codegen.cpp
+++ b/test/OpenMP/target_enter_data_codegen.cpp
@@ -9,6 +9,14 @@
// RUN: %clang_cc1 -DCK1 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
// RUN: %clang_cc1 -DCK1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
#ifdef CK1
// CK1: [[ST:%.+]] = type { i32, double* }
@@ -29,8 +37,9 @@ double gc[100];
// CK1: [[MTYPE03:@.+]] = {{.+}}constant [1 x i64] [i64 37]
-// CK1: [[SIZE04:@.+]] = {{.+}}constant [2 x i[[sz]]] [i[[sz]] {{8|4}}, i[[sz]] 24]
-// CK1: [[MTYPE04:@.+]] = {{.+}}constant [2 x i64] [i64 33, i64 17]
+// CK1-64: [[SIZE04:@.+]] = {{.+}}constant [2 x i64] [i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)), i64 24]
+// CK1-32: [[SIZE04:@.+]] = {{.+}}constant [2 x i32] [i32 trunc (i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)) to i32), i32 24]
+// CK1: [[MTYPE04:@.+]] = {{.+}}constant [2 x i64] [i64 32, i64 281474976710673]
// CK1-LABEL: _Z3fooi
void foo(int arg) {
@@ -145,6 +154,14 @@ void foo(int arg) {
// RUN: %clang_cc1 -DCK2 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
// RUN: %clang_cc1 -DCK2 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
#ifdef CK2
// CK2: [[ST:%.+]] = type { i32, double* }
@@ -161,8 +178,7 @@ struct ST {
}
};
-// CK2: [[SIZE00:@.+]] = {{.+}}constant [2 x i[[sz:64|32]]] [i{{64|32}} {{8|4}}, i{{64|32}} 24]
-// CK2: [[MTYPE00:@.+]] = {{.+}}constant [2 x i64] [i64 37, i64 21]
+// CK2: [[MTYPE00:@.+]] = {{.+}}constant [2 x i64] [i64 32, i64 281474976710677]
// CK2-LABEL: _Z3bari
int bar(int arg){
@@ -173,21 +189,23 @@ int bar(int arg){
// Region 00
// CK2: br i1 %{{[^,]+}}, label %[[IFTHEN:[^,]+]], label %[[IFELSE:[^,]+]]
// CK2: [[IFTHEN]]
-// CK2-DAG: call void @__tgt_target_data_begin(i64 [[DEV:%[^,]+]], i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[SIZE00]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE00]]{{.+}})
+// CK2-DAG: call void @__tgt_target_data_begin(i64 [[DEV:%[^,]+]], i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE00]]{{.+}})
// CK2-DAG: [[DEV]] = sext i32 [[DEVi32:%[^,]+]] to i64
// CK2-DAG: [[DEVi32]] = load i32, i32* %{{[^,]+}},
// CK2-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
// CK2-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
+// CK2-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
// CK2-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK2-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
+// CK2-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
// CK2-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]**
// CK2-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double***
// CK2-DAG: store [[ST]]* [[VAR0:%.+]], [[ST]]** [[CBP0]]
// CK2-DAG: store double** [[SEC0:%.+]], double*** [[CP0]]
+// CK2-DAG: store i[[sz]] {{%.+}}, i[[sz]]* [[S0]]
// CK2-DAG: [[SEC0]] = getelementptr inbounds {{.*}}[[ST]]* [[VAR0]], i32 0, i32 1
-
// CK2-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
// CK2-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
// CK2-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double***
@@ -213,6 +231,14 @@ int bar(int arg){
// RUN: %clang_cc1 -DCK3 -verify -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-32
// RUN: %clang_cc1 -DCK3 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-32
+
+// RUN: %clang_cc1 -DCK3 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// RUN: %clang_cc1 -DCK3 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// RUN: %clang_cc1 -DCK3 -verify -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// RUN: %clang_cc1 -DCK3 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// SIMD-ONLY2-NOT: {{__kmpc|__tgt}}
#ifdef CK3
// CK3-LABEL: no_target_devices
@@ -233,6 +259,14 @@ void no_target_devices(int arg) {
// RUN: %clang_cc1 -DCK4 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK4 --check-prefix CK4-32
+// RUN: %clang_cc1 -DCK4 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY3 %s
+// RUN: %clang_cc1 -DCK4 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY3 %s
+// RUN: %clang_cc1 -DCK4 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY3 %s
+// RUN: %clang_cc1 -DCK4 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY3 %s
+// SIMD-ONLY3-NOT: {{__kmpc|__tgt}}
+
// RUN: %clang_cc1 -DCK4 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
// RUN: %clang_cc1 -DCK4 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCK4 --check-prefix TCK4-64
// RUN: %clang_cc1 -DCK4 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
@@ -241,6 +275,16 @@ void no_target_devices(int arg) {
// RUN: %clang_cc1 -DCK4 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix TCK4 --check-prefix TCK4-32
// RUN: %clang_cc1 -DCK4 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCK4 --check-prefix TCK4-32
+
+// RUN: %clang_cc1 -DCK4 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -DCK4 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY4 %s
+// RUN: %clang_cc1 -DCK4 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY4 %s
+// RUN: %clang_cc1 -DCK4 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -DCK4 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY4 %s
+// RUN: %clang_cc1 -DCK4 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY4 %s
+// SIMD-ONLY4-NOT: {{__kmpc|__tgt}}
#ifdef CK4
// CK4-LABEL: device_side_scan
diff --git a/test/OpenMP/target_enter_data_depend_codegen.cpp b/test/OpenMP/target_enter_data_depend_codegen.cpp
index 469a161eb341..e17150d57677 100644
--- a/test/OpenMP/target_enter_data_depend_codegen.cpp
+++ b/test/OpenMP/target_enter_data_depend_codegen.cpp
@@ -5,6 +5,14 @@
// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
// CK1: [[ST:%.+]] = type { i32, double* }
// CK1: %struct.kmp_depend_info = type { i[[sz:64|32]],
@@ -29,8 +37,9 @@ double gc[100];
// CK1: [[MTYPE03:@.+]] = {{.+}}constant [1 x i64] [i64 32]
-// CK1: [[SIZE04:@.+]] = {{.+}}constant [2 x i[[sz]]] [i[[sz]] {{8|4}}, i[[sz]] 24]
-// CK1: [[MTYPE04:@.+]] = {{.+}}constant [2 x i64] [i64 33, i64 17]
+// CK1-64: [[SIZE04:@.+]] = {{.+}}constant [2 x i64] [i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)), i64 24]
+// CK1-32: [[SIZE04:@.+]] = {{.+}}constant [2 x i32] [i32 trunc (i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)) to i32), i32 24]
+// CK1: [[MTYPE04:@.+]] = {{.+}}constant [2 x i64] [i64 32, i64 281474976710673]
// CK1-LABEL: _Z3fooi
void foo(int arg) {
@@ -54,25 +63,25 @@ void foo(int arg) {
// CK1: [[CAP_DEVICE:%.+]] = getelementptr inbounds %struct.anon, %struct.anon* [[CAPTURES:%.+]], i32 0, i32 0
// CK1: [[DEVICE:%.+]] = load i32, i32* %{{.+}}
// CK1: store i32 [[DEVICE]], i32* [[CAP_DEVICE]],
- // CK1: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%ident_t* {{.+}}, i32 {{.+}}, i32 1, i[[sz]] [[sz]], i[[sz]] 4, i32 (i32, i8*)* bitcast (i32 (i32, %struct.kmp_task_t_with_privates*)* [[TASK_ENTRY0:@.+]] to i32 (i32, i8*)*))
+ // CK1: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* {{.+}}, i32 {{.+}}, i32 1, i[[sz]] [[sz]], i[[sz]] 4, i32 (i32, i8*)* bitcast (i32 (i32, %struct.kmp_task_t_with_privates*)* [[TASK_ENTRY0:@.+]] to i32 (i32, i8*)*))
// CK1: [[BC:%.+]] = bitcast i8* [[RES]] to %struct.kmp_task_t_with_privates*
// CK1: [[TASK_T:%.+]] = getelementptr inbounds %struct.kmp_task_t_with_privates, %struct.kmp_task_t_with_privates* [[BC]], i32 0, i32 0
// CK1: [[SHAREDS:%.+]] = getelementptr inbounds %struct.kmp_task_t, %struct.kmp_task_t* [[TASK_T]], i32 0, i32 0
// CK1: [[SHAREDS_REF:%.+]] = load i8*, i8** [[SHAREDS]],
// CK1: [[BC1:%.+]] = bitcast %struct.anon* [[CAPTURES]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[SHAREDS_REF]], i8* [[BC1]], i[[sz]] 4, i32 4, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align 4 [[SHAREDS_REF]], i8* align 4 [[BC1]], i[[sz]] 4, i1 false)
// CK1: [[PRIVS:%.+]] = getelementptr inbounds %struct.kmp_task_t_with_privates, %struct.kmp_task_t_with_privates* [[BC]], i32 0, i32 1
// CK1: [[PRIVS_BASEPTRS:%.+]] = getelementptr inbounds %struct..kmp_privates.t, %struct..kmp_privates.t* [[PRIVS]], i32 0, i32 0
// CK1: [[BC_PRIVS_BASEPTRS:%.+]] = bitcast [1 x i8*]* [[PRIVS_BASEPTRS]] to i8*
// CK1: [[BC_BASEPTRS:%.+]] = bitcast i8** [[GEPBP0]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_BASEPTRS]], i8* [[BC_BASEPTRS]], i[[sz]] {{8|4}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_BASEPTRS]], i8* align {{8|4}} [[BC_BASEPTRS]], i[[sz]] {{8|4}}, i1 false)
// CK1: [[PRIVS_PTRS:%.+]] = getelementptr inbounds %struct..kmp_privates.t, %struct..kmp_privates.t* [[PRIVS]], i32 0, i32 1
// CK1: [[BC_PRIVS_PTRS:%.+]] = bitcast [1 x i8*]* [[PRIVS_PTRS]] to i8*
// CK1: [[BC_PTRS:%.+]] = bitcast i8** [[GEPP0]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_PTRS]], i8* [[BC_PTRS]], i[[sz]] {{8|4}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_PTRS]], i8* align {{8|4}} [[BC_PTRS]], i[[sz]] {{8|4}}, i1 false)
// CK1: [[PRIVS_SIZES:%.+]] = getelementptr inbounds %struct..kmp_privates.t, %struct..kmp_privates.t* [[PRIVS]], i32 0, i32 2
// CK1: [[BC_PRIVS_SIZES:%.+]] = bitcast [1 x i[[sz]]]* [[PRIVS_SIZES]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_SIZES]], i8* bitcast ([1 x i[[sz]]]* [[SIZE00]] to i8*), i[[sz]] {{8|4}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_SIZES]], i8* align {{8|4}} bitcast ([1 x i[[sz]]]* [[SIZE00]] to i8*), i[[sz]] {{8|4}}, i1 false)
// CK1: [[DEP:%.+]] = getelementptr inbounds [1 x %struct.kmp_depend_info], [1 x %struct.kmp_depend_info]* [[MAIN_DEP:%.+]], i[[sz]] 0, i[[sz]] 0
// CK1: [[DEP_ADR:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[DEP]], i32 0, i32 0
// CK1: [[BC_ADR:%.+]] = ptrtoint i32* %{{.+}} to i[[sz]]
@@ -83,7 +92,7 @@ void foo(int arg) {
// CK1: store i8 1, i8* [[DEP_ATTRS]]
// CK1: [[DEP:%.+]] = getelementptr inbounds [1 x %struct.kmp_depend_info], [1 x %struct.kmp_depend_info]* [[MAIN_DEP]], i32 0, i32 0
// CK1: [[BC:%.+]] = bitcast %struct.kmp_depend_info* [[DEP]] to i8*
- // CK1: = call i32 @__kmpc_omp_task_with_deps(%ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]], i32 1, i8* [[BC]], i32 0, i8* null)
+ // CK1: = call i32 @__kmpc_omp_task_with_deps(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]], i32 1, i8* [[BC]], i32 0, i8* null)
// CK1: %{{.+}} = add nsw i32 %{{[^,]+}}, 1
#pragma omp target enter data if(1+3-5) device(arg) map(alloc:gc) nowait depend(in: arg)
@@ -110,25 +119,25 @@ void foo(int arg) {
// CK1: [[IF_BOOL:%.+]] = trunc i8 [[IF]] to i1
// CK1: [[IF:%.+]] = zext i1 [[IF_BOOL]] to i8
// CK1: store i8 [[IF]], i8* [[IF_DEVICE]],
- // CK1: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%ident_t* {{.+}}, i32 {{.+}}, i32 1, i[[sz]] [[sz]], i[[sz]] 1, i32 (i32, i8*)* bitcast (i32 (i32, %struct.kmp_task_t_with_privates{{.+}}*)* [[TASK_ENTRY2:@.+]] to i32 (i32, i8*)*))
+ // CK1: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* {{.+}}, i32 {{.+}}, i32 1, i[[sz]] [[sz]], i[[sz]] 1, i32 (i32, i8*)* bitcast (i32 (i32, %struct.kmp_task_t_with_privates{{.+}}*)* [[TASK_ENTRY2:@.+]] to i32 (i32, i8*)*))
// CK1: [[RES_BC:%.+]] = bitcast i8* [[RES]] to %struct.kmp_task_t_with_privates{{.+}}*
// CK1: [[TASK_T:%.+]] = getelementptr inbounds %struct.kmp_task_t_with_privates{{.+}}, %struct.kmp_task_t_with_privates{{.+}}* [[RES_BC]], i32 0, i32 0
// CK1: [[SHAREDS:%.+]] = getelementptr inbounds %struct.kmp_task_t, %struct.kmp_task_t* [[TASK_T]], i32 0, i32 0
// CK1: [[SHAREDS_REF:%.+]] = load i8*, i8** [[SHAREDS]],
// CK1: [[BC1:%.+]] = bitcast %struct.anon{{.+}}* [[CAPTURES]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[SHAREDS_REF]], i8* [[BC1]], i[[sz]] 1, i32 1, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align 1 [[SHAREDS_REF]], i8* align 1 [[BC1]], i[[sz]] 1, i1 false)
// CK1: [[PRIVS:%.+]] = getelementptr inbounds %struct.kmp_task_t_with_privates{{.+}}, %struct.kmp_task_t_with_privates{{.+}}* [[RES_BC]], i32 0, i32 1
// CK1: [[PRIVS_BASEPTRS:%.+]] = getelementptr inbounds %struct..kmp_privates.t{{.+}}, %struct..kmp_privates.t{{.+}}* [[PRIVS]], i32 0, i32 0
// CK1: [[BC_PRIVS_BASEPTRS:%.+]] = bitcast [1 x i8*]* [[PRIVS_BASEPTRS]] to i8*
// CK1: [[BC_BASEPTRS:%.+]] = bitcast i8** [[GEPBP0]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_BASEPTRS]], i8* [[BC_BASEPTRS]], i[[sz]] {{8|4}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_BASEPTRS]], i8* align {{8|4}} [[BC_BASEPTRS]], i[[sz]] {{8|4}}, i1 false)
// CK1: [[PRIVS_PTRS:%.+]] = getelementptr inbounds %struct..kmp_privates.t{{.+}}, %struct..kmp_privates.t{{.+}}* [[PRIVS]], i32 0, i32 1
// CK1: [[BC_PRIVS_PTRS:%.+]] = bitcast [1 x i8*]* [[PRIVS_PTRS]] to i8*
// CK1: [[BC_PTRS:%.+]] = bitcast i8** [[GEPP0]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_PTRS]], i8* [[BC_PTRS]], i[[sz]] {{8|4}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_PTRS]], i8* align {{8|4}} [[BC_PTRS]], i[[sz]] {{8|4}}, i1 false)
// CK1: [[PRIVS_SIZES:%.+]] = getelementptr inbounds %struct..kmp_privates.t{{.+}}, %struct..kmp_privates.t{{.+}}* [[PRIVS]], i32 0, i32 2
// CK1: [[BC_PRIVS_SIZES:%.+]] = bitcast [1 x i[[sz]]]* [[PRIVS_SIZES]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_SIZES]], i8* bitcast ([1 x i[[sz]]]* [[SIZE02]] to i8*), i[[sz]] {{8|4}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_SIZES]], i8* align {{8|4}} bitcast ([1 x i[[sz]]]* [[SIZE02]] to i8*), i[[sz]] {{8|4}}, i1 false)
// CK1: [[DEP:%.+]] = getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* [[MAIN_DEP:%.+]], i[[sz]] 0, i[[sz]] 0
// CK1: [[DEP_ADR:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[DEP]], i32 0, i32 0
// CK1: [[BC_ADR:%.+]] = ptrtoint i32* %{{.+}} to i[[sz]]
@@ -154,10 +163,10 @@ void foo(int arg) {
// CK1: store i8 3, i8* [[DEP_ATTRS]]
// CK1: [[DEP:%.+]] = getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* [[MAIN_DEP]], i32 0, i32 0
// CK1: [[BC:%.+]] = bitcast %struct.kmp_depend_info* [[DEP]] to i8*
- // CK1: call void @__kmpc_omp_wait_deps(%ident_t* @{{.+}}, i32 %{{.+}}, i32 3, i8* [[BC]], i32 0, i8* null)
- // CK1: call void @__kmpc_omp_task_begin_if0(%ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
+ // CK1: call void @__kmpc_omp_wait_deps(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i32 3, i8* [[BC]], i32 0, i8* null)
+ // CK1: call void @__kmpc_omp_task_begin_if0(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
// CK1: = call i32 [[TASK_ENTRY2]](i32 %{{.+}}, %struct.kmp_task_t_with_privates{{.+}}* [[RES_BC]])
- // CK1: call void @__kmpc_omp_task_complete_if0(%ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
+ // CK1: call void @__kmpc_omp_task_complete_if0(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
// CK1: br label %[[IFEND:[^,]+]]
@@ -183,22 +192,22 @@ void foo(int arg) {
// CK1: [[GEPBP0:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[BP]], i32 0, i32 0
// CK1: [[GEPP0:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[P]], i32 0, i32 0
// CK1: [[GEPS0:%.+]] = getelementptr inbounds [1 x i[[sz]]], [1 x i[[sz]]]* [[S]], i32 0, i32 0
- // CK1: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%ident_t* {{.+}}, i32 {{.+}}, i32 1, i[[sz]] [[sz]], i[[sz]] 1, i32 (i32, i8*)* bitcast (i32 (i32, %struct.kmp_task_t_with_privates{{.+}}*)* [[TASK_ENTRY3:@.+]] to i32 (i32, i8*)*))
+ // CK1: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* {{.+}}, i32 {{.+}}, i32 1, i[[sz]] [[sz]], i[[sz]] 1, i32 (i32, i8*)* bitcast (i32 (i32, %struct.kmp_task_t_with_privates{{.+}}*)* [[TASK_ENTRY3:@.+]] to i32 (i32, i8*)*))
// CK1: [[RES_BC:%.+]] = bitcast i8* [[RES]] to %struct.kmp_task_t_with_privates{{.+}}*
// CK1: [[TASK_T:%.+]] = getelementptr inbounds %struct.kmp_task_t_with_privates{{.+}}, %struct.kmp_task_t_with_privates{{.+}}* [[RES_BC]], i32 0, i32 0
// CK1: [[PRIVS:%.+]] = getelementptr inbounds %struct.kmp_task_t_with_privates{{.+}}, %struct.kmp_task_t_with_privates{{.+}}* [[RES_BC]], i32 0, i32 1
// CK1: [[PRIVS_BASEPTRS:%.+]] = getelementptr inbounds %struct..kmp_privates.t{{.+}}, %struct..kmp_privates.t{{.+}}* [[PRIVS]], i32 0, i32 0
// CK1: [[BC_PRIVS_BASEPTRS:%.+]] = bitcast [1 x i8*]* [[PRIVS_BASEPTRS]] to i8*
// CK1: [[BC_BASEPTRS:%.+]] = bitcast i8** [[GEPBP0]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_BASEPTRS]], i8* [[BC_BASEPTRS]], i[[sz]] {{8|4}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_BASEPTRS]], i8* align {{8|4}} [[BC_BASEPTRS]], i[[sz]] {{8|4}}, i1 false)
// CK1: [[PRIVS_PTRS:%.+]] = getelementptr inbounds %struct..kmp_privates.t{{.+}}, %struct..kmp_privates.t{{.+}}* [[PRIVS]], i32 0, i32 1
// CK1: [[BC_PRIVS_PTRS:%.+]] = bitcast [1 x i8*]* [[PRIVS_PTRS]] to i8*
// CK1: [[BC_PTRS:%.+]] = bitcast i8** [[GEPP0]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_PTRS]], i8* [[BC_PTRS]], i[[sz]] {{8|4}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_PTRS]], i8* align {{8|4}} [[BC_PTRS]], i[[sz]] {{8|4}}, i1 false)
// CK1: [[PRIVS_SIZES:%.+]] = getelementptr inbounds %struct..kmp_privates.t{{.+}}, %struct..kmp_privates.t{{.+}}* [[PRIVS]], i32 0, i32 2
// CK1: [[BC_PRIVS_SIZES:%.+]] = bitcast [1 x i[[sz]]]* [[PRIVS_SIZES]] to i8*
// CK1: [[BC_SIZES:%.+]] = bitcast i[[sz]]* [[GEPS0]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_SIZES]], i8* [[BC_SIZES]], i[[sz]] {{8|4}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_SIZES]], i8* align {{8|4}} [[BC_SIZES]], i[[sz]] {{8|4}}, i1 false)
// CK1: [[DEP:%.+]] = getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* [[MAIN_DEP:%.+]], i[[sz]] 0, i[[sz]] 0
// CK1: [[DEP_ADR:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[DEP]], i32 0, i32 0
// CK1: [[BC_ADR:%.+]] = ptrtoint float* %{{.+}} to i[[sz]]
@@ -232,10 +241,10 @@ void foo(int arg) {
// CK1: store i8 3, i8* [[DEP_ATTRS]]
// CK1: [[DEP:%.+]] = getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* [[MAIN_DEP]], i32 0, i32 0
// CK1: [[BC:%.+]] = bitcast %struct.kmp_depend_info* [[DEP]] to i8*
- // CK1: call void @__kmpc_omp_wait_deps(%ident_t* @{{.+}}, i32 %{{.+}}, i32 4, i8* [[BC]], i32 0, i8* null)
- // CK1: call void @__kmpc_omp_task_begin_if0(%ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
+ // CK1: call void @__kmpc_omp_wait_deps(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i32 4, i8* [[BC]], i32 0, i8* null)
+ // CK1: call void @__kmpc_omp_task_begin_if0(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
// CK1: = call i32 [[TASK_ENTRY3]](i32 %{{.+}}, %struct.kmp_task_t_with_privates{{.+}}* [[RES_BC]])
- // CK1: call void @__kmpc_omp_task_complete_if0(%ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
+ // CK1: call void @__kmpc_omp_task_complete_if0(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
#pragma omp target enter data map(alloc:lb) depend(out: lb, arg, la, gc)
{++arg;}
@@ -257,21 +266,21 @@ void foo(int arg) {
// CK1: store double* %{{.+}}, double** [[P1_BC]],
// CK1: [[GEPBP0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 0
// CK1: [[GEPP0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P]], i32 0, i32 0
- // CK1: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%ident_t* {{.+}}, i32 {{.+}}, i32 1, i[[sz]] {{88|44}}, i[[sz]] 1, i32 (i32, i8*)* bitcast (i32 (i32, %struct.kmp_task_t_with_privates{{.+}}*)* [[TASK_ENTRY4:@.+]] to i32 (i32, i8*)*))
+ // CK1: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* {{.+}}, i32 {{.+}}, i32 1, i[[sz]] {{88|44}}, i[[sz]] 1, i32 (i32, i8*)* bitcast (i32 (i32, %struct.kmp_task_t_with_privates{{.+}}*)* [[TASK_ENTRY4:@.+]] to i32 (i32, i8*)*))
// CK1: [[RES_BC:%.+]] = bitcast i8* [[RES]] to %struct.kmp_task_t_with_privates{{.+}}*
// CK1: [[TASK_T:%.+]] = getelementptr inbounds %struct.kmp_task_t_with_privates{{.+}}, %struct.kmp_task_t_with_privates{{.+}}* [[RES_BC]], i32 0, i32 0
// CK1: [[PRIVS:%.+]] = getelementptr inbounds %struct.kmp_task_t_with_privates{{.+}}, %struct.kmp_task_t_with_privates{{.+}}* [[RES_BC]], i32 0, i32 1
// CK1: [[PRIVS_BASEPTRS:%.+]] = getelementptr inbounds %struct..kmp_privates.t{{.+}}, %struct..kmp_privates.t{{.+}}* [[PRIVS]], i32 0, i32 0
// CK1: [[BC_PRIVS_BASEPTRS:%.+]] = bitcast [2 x i8*]* [[PRIVS_BASEPTRS]] to i8*
// CK1: [[BC_BASEPTRS:%.+]] = bitcast i8** [[GEPBP0]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_BASEPTRS]], i8* [[BC_BASEPTRS]], i[[sz]] {{16|8}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_BASEPTRS]], i8* align {{8|4}} [[BC_BASEPTRS]], i[[sz]] {{16|8}}, i1 false)
// CK1: [[PRIVS_PTRS:%.+]] = getelementptr inbounds %struct..kmp_privates.t{{.+}}, %struct..kmp_privates.t{{.+}}* [[PRIVS]], i32 0, i32 1
// CK1: [[BC_PRIVS_PTRS:%.+]] = bitcast [2 x i8*]* [[PRIVS_PTRS]] to i8*
// CK1: [[BC_PTRS:%.+]] = bitcast i8** [[GEPP0]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_PTRS]], i8* [[BC_PTRS]], i[[sz]] {{16|8}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_PTRS]], i8* align {{8|4}} [[BC_PTRS]], i[[sz]] {{16|8}}, i1 false)
// CK1: [[PRIVS_SIZES:%.+]] = getelementptr inbounds %struct..kmp_privates.t{{.+}}, %struct..kmp_privates.t{{.+}}* [[PRIVS]], i32 0, i32 2
// CK1: [[BC_PRIVS_SIZES:%.+]] = bitcast [2 x i[[sz]]]* [[PRIVS_SIZES]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_SIZES]], i8* bitcast ([2 x i[[sz]]]* [[SIZE04]] to i8*), i[[sz]] {{16|8}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_SIZES]], i8* align {{8|4}} bitcast ([2 x i[[sz]]]* [[SIZE04]] to i8*), i[[sz]] {{16|8}}, i1 false)
// CK1: [[DEP:%.+]] = getelementptr inbounds [5 x %struct.kmp_depend_info], [5 x %struct.kmp_depend_info]* [[MAIN_DEP:%.+]], i[[sz]] 0, i[[sz]] 0
// CK1: [[DEP_ADR:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[DEP]], i32 0, i32 0
// CK1: [[BC_ADR:%.+]] = ptrtoint double* %{{.+}} to i[[sz]]
@@ -313,10 +322,10 @@ void foo(int arg) {
// CK1: store i8 1, i8* [[DEP_ATTRS]]
// CK1: [[DEP:%.+]] = getelementptr inbounds [5 x %struct.kmp_depend_info], [5 x %struct.kmp_depend_info]* [[MAIN_DEP]], i32 0, i32 0
// CK1: [[BC:%.+]] = bitcast %struct.kmp_depend_info* [[DEP]] to i8*
- // CK1: call void @__kmpc_omp_wait_deps(%ident_t* @{{.+}}, i32 %{{.+}}, i32 5, i8* [[BC]], i32 0, i8* null)
- // CK1: call void @__kmpc_omp_task_begin_if0(%ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
+ // CK1: call void @__kmpc_omp_wait_deps(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i32 5, i8* [[BC]], i32 0, i8* null)
+ // CK1: call void @__kmpc_omp_task_begin_if0(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
// CK1: = call i32 [[TASK_ENTRY4]](i32 %{{.+}}, %struct.kmp_task_t_with_privates{{.+}}* [[RES_BC]])
- // CK1: call void @__kmpc_omp_task_complete_if0(%ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
+ // CK1: call void @__kmpc_omp_task_complete_if0(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
#pragma omp target enter data map(to:gb.b[:3]) depend(in: gb.b[:3], la, lb, gc, arg)
{++arg;}
}
@@ -328,9 +337,9 @@ void foo(int arg) {
// CK1-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
// CK1-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
// CK1-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
-// CK1-DAG: [[BP]] = load [1 x i8*]*, [1 x i8*]** [[BP_PRIV:%.+]],
-// CK1-DAG: [[P]] = load [1 x i8*]*, [1 x i8*]** [[P_PRIV:%.+]],
-// CK1-DAG: [[S]] = load [1 x i[[sz]]]*, [1 x i[[sz]]]** [[S_PRIV:%.+]],
+// CK1-DAG: [[BP]] = load [1 x i8*]*, [1 x i8*]** [[BP_PRIV:%[^,]+]],
+// CK1-DAG: [[P]] = load [1 x i8*]*, [1 x i8*]** [[P_PRIV:%[^,]+]],
+// CK1-DAG: [[S]] = load [1 x i[[sz]]]*, [1 x i[[sz]]]** [[S_PRIV:%[^,]+]],
// CK1-DAG: call void (i8*, ...) %{{.+}}(i8* %{{[^,]+}}, [1 x i8*]** [[BP_PRIV]], [1 x i8*]** [[P_PRIV]], [1 x i[[sz]]]** [[S_PRIV]])
// CK1: ret i32 0
// CK1: }
@@ -340,9 +349,9 @@ void foo(int arg) {
// CK1-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
// CK1-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
// CK1-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
-// CK1-DAG: [[BP]] = load [1 x i8*]*, [1 x i8*]** [[BP_PRIV:%.+]],
-// CK1-DAG: [[P]] = load [1 x i8*]*, [1 x i8*]** [[P_PRIV:%.+]],
-// CK1-DAG: [[S]] = load [1 x i[[sz]]]*, [1 x i[[sz]]]** [[S_PRIV:%.+]],
+// CK1-DAG: [[BP]] = load [1 x i8*]*, [1 x i8*]** [[BP_PRIV:%[^,]+]],
+// CK1-DAG: [[P]] = load [1 x i8*]*, [1 x i8*]** [[P_PRIV:%[^,]+]],
+// CK1-DAG: [[S]] = load [1 x i[[sz]]]*, [1 x i[[sz]]]** [[S_PRIV:%[^,]+]],
// CK1-DAG: call void (i8*, ...) %{{.+}}(i8* %{{[^,]+}}, [1 x i8*]** [[BP_PRIV]], [1 x i8*]** [[P_PRIV]], [1 x i[[sz]]]** [[S_PRIV]])
// CK1: ret i32 0
// CK1: }
@@ -353,9 +362,9 @@ void foo(int arg) {
// CK1-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
// CK1-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
-// CK1-DAG: [[BP]] = load [1 x i8*]*, [1 x i8*]** [[BP_PRIV:%.+]],
-// CK1-DAG: [[P]] = load [1 x i8*]*, [1 x i8*]** [[P_PRIV:%.+]],
-// CK1-DAG: [[S]] = load [1 x i[[sz]]]*, [1 x i[[sz]]]** [[S_PRIV:%.+]],
+// CK1-DAG: [[BP]] = load [1 x i8*]*, [1 x i8*]** [[BP_PRIV:%[^,]+]],
+// CK1-DAG: [[P]] = load [1 x i8*]*, [1 x i8*]** [[P_PRIV:%[^,]+]],
+// CK1-DAG: [[S]] = load [1 x i[[sz]]]*, [1 x i[[sz]]]** [[S_PRIV:%[^,]+]],
// CK1-DAG: call void (i8*, ...) %{{.+}}(i8* %{{[^,]+}}, [1 x i8*]** [[BP_PRIV]], [1 x i8*]** [[P_PRIV]], [1 x i[[sz]]]** [[S_PRIV]])
// CK1-NOT: __tgt_target_data_end
// CK1: ret i32 0
@@ -367,9 +376,9 @@ void foo(int arg) {
// CK1-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
// CK1-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
-// CK1-DAG: [[BP]] = load [2 x i8*]*, [2 x i8*]** [[BP_PRIV:%.+]],
-// CK1-DAG: [[P]] = load [2 x i8*]*, [2 x i8*]** [[P_PRIV:%.+]],
-// CK1-DAG: [[S]] = load [2 x i[[sz]]]*, [2 x i[[sz]]]** [[S_PRIV:%.+]],
+// CK1-DAG: [[BP]] = load [2 x i8*]*, [2 x i8*]** [[BP_PRIV:%[^,]+]],
+// CK1-DAG: [[P]] = load [2 x i8*]*, [2 x i8*]** [[P_PRIV:%[^,]+]],
+// CK1-DAG: [[S]] = load [2 x i[[sz]]]*, [2 x i[[sz]]]** [[S_PRIV:%[^,]+]],
// CK1-DAG: call void (i8*, ...) %{{.+}}(i8* %{{[^,]+}}, [2 x i8*]** [[BP_PRIV]], [2 x i8*]** [[P_PRIV]], [2 x i[[sz]]]** [[S_PRIV]])
// CK1-NOT: __tgt_target_data_end
// CK1: ret i32 0
diff --git a/test/OpenMP/target_enter_data_depend_messages.cpp b/test/OpenMP/target_enter_data_depend_messages.cpp
index 77e7039e8e20..ccc29ea49a26 100644
--- a/test/OpenMP/target_enter_data_depend_messages.cpp
+++ b/test/OpenMP/target_enter_data_depend_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_enter_data_device_messages.cpp b/test/OpenMP/target_enter_data_device_messages.cpp
index d954eca319dd..de8405b4a62f 100644
--- a/test/OpenMP/target_enter_data_device_messages.cpp
+++ b/test/OpenMP/target_enter_data_device_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/target_enter_data_if_messages.cpp b/test/OpenMP/target_enter_data_if_messages.cpp
index 137ff9751617..26404a5d97a7 100644
--- a/test/OpenMP/target_enter_data_if_messages.cpp
+++ b/test/OpenMP/target_enter_data_if_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -fopenmp-version=45 -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -fopenmp-version=45 -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/target_enter_data_map_messages.c b/test/OpenMP/target_enter_data_map_messages.c
index 8a7de3b96eff..381c94bf3986 100644
--- a/test/OpenMP/target_enter_data_map_messages.c
+++ b/test/OpenMP/target_enter_data_map_messages.c
@@ -1,6 +1,9 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - -x c++ %s
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -ferror-limit 100 -o - -x c++ %s
+
int main(int argc, char **argv) {
int r;
diff --git a/test/OpenMP/target_enter_data_nowait_messages.cpp b/test/OpenMP/target_enter_data_nowait_messages.cpp
index 508b1b254906..6f59c5ceb7b7 100644
--- a/test/OpenMP/target_enter_data_nowait_messages.cpp
+++ b/test/OpenMP/target_enter_data_nowait_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
int main(int argc, char **argv) {
int i;
diff --git a/test/OpenMP/target_exit_data_ast_print.cpp b/test/OpenMP/target_exit_data_ast_print.cpp
index a2f5d641f3cc..1408023b0637 100644
--- a/test/OpenMP/target_exit_data_ast_print.cpp
+++ b/test/OpenMP/target_exit_data_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -69,7 +73,7 @@ T tmain(T argc, T *argv) {
// CHECK: template <typename T, int C> T tmain(T argc, T *argv) {
// CHECK-NEXT: T i, j, b, c, d, e, x[20];
// CHECK-NEXT: i = argc;
-// CHECK-NEXT: #pragma omp target exit data map(from: i)
+// CHECK-NEXT: #pragma omp target exit data map(from: i){{$}}
// CHECK-NEXT: #pragma omp target exit data map(from: i) if(target exit data: j > 0)
// CHECK-NEXT: #pragma omp target exit data map(from: i) if(b)
// CHECK-NEXT: #pragma omp target exit data map(from: c)
diff --git a/test/OpenMP/target_exit_data_codegen.cpp b/test/OpenMP/target_exit_data_codegen.cpp
index 9359e3be451b..ff84303bb0ee 100644
--- a/test/OpenMP/target_exit_data_codegen.cpp
+++ b/test/OpenMP/target_exit_data_codegen.cpp
@@ -9,6 +9,14 @@
// RUN: %clang_cc1 -DCK1 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
// RUN: %clang_cc1 -DCK1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
#ifdef CK1
// CK1: [[ST:%.+]] = type { i32, double* }
@@ -29,8 +37,9 @@ double gc[100];
// CK1: [[MTYPE03:@.+]] = {{.+}}constant [1 x i64] [i64 38]
-// CK1: [[SIZE04:@.+]] = {{.+}}constant [2 x i[[sz]]] [i[[sz]] {{8|4}}, i[[sz]] 24]
-// CK1: [[MTYPE04:@.+]] = {{.+}}constant [2 x i64] [i64 32, i64 16]
+// CK1-64: [[SIZE04:@.+]] = {{.+}}constant [2 x i64] [i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)), i64 24]
+// CK1-32: [[SIZE04:@.+]] = {{.+}}constant [2 x i32] [i32 trunc (i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)) to i32), i32 24]
+// CK1: [[MTYPE04:@.+]] = {{.+}}constant [2 x i64] [i64 32, i64 281474976710672]
// CK1-LABEL: _Z3fooi
void foo(int arg) {
@@ -145,6 +154,14 @@ void foo(int arg) {
// RUN: %clang_cc1 -DCK2 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
// RUN: %clang_cc1 -DCK2 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
#ifdef CK2
// CK2: [[ST:%.+]] = type { i32, double* }
@@ -161,8 +178,7 @@ struct ST {
}
};
-// CK2: [[SIZE00:@.+]] = {{.+}}constant [2 x i[[sz:64|32]]] [i{{64|32}} {{8|4}}, i{{64|32}} 24]
-// CK2: [[MTYPE00:@.+]] = {{.+}}constant [2 x i64] [i64 36, i64 20]
+// CK2: [[MTYPE00:@.+]] = {{.+}}constant [2 x i64] [i64 32, i64 281474976710676]
// CK2-LABEL: _Z3bari
int bar(int arg){
@@ -174,21 +190,23 @@ int bar(int arg){
// CK2-NOT: __tgt_target_data_begin
// CK2: br i1 %{{[^,]+}}, label %[[IFTHEN:[^,]+]], label %[[IFELSE:[^,]+]]
// CK2: [[IFTHEN]]
-// CK2-DAG: call void @__tgt_target_data_end(i64 [[DEV:%[^,]+]], i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[SIZE00]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE00]]{{.+}})
+// CK2-DAG: call void @__tgt_target_data_end(i64 [[DEV:%[^,]+]], i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:.+]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE00]]{{.+}})
// CK2-DAG: [[DEV]] = sext i32 [[DEVi32:%[^,]+]] to i64
// CK2-DAG: [[DEVi32]] = load i32, i32* %{{[^,]+}},
// CK2-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
// CK2-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
+// CK2-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
// CK2-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK2-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
+// CK2-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
// CK2-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]**
// CK2-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double***
// CK2-DAG: store [[ST]]* [[VAR0:%[^,]+]], [[ST]]** [[CBP0]]
// CK2-DAG: store double** [[SEC0:%[^,]+]], double*** [[CP0]]
+// CK2-DAG: store i[[sz]] [[CSVAL0:%[^,]+]], i[[sz]]* [[S0]]
// CK2-DAG: [[SEC0]] = getelementptr inbounds {{.*}}[[ST]]* [[VAR0]], i32 0, i32 1
-
// CK2-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
// CK2-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
// CK2-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double***
@@ -213,6 +231,14 @@ int bar(int arg){
// RUN: %clang_cc1 -DCK3 -verify -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-32
// RUN: %clang_cc1 -DCK3 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-32
+
+// RUN: %clang_cc1 -DCK3 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// RUN: %clang_cc1 -DCK3 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// RUN: %clang_cc1 -DCK3 -verify -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// RUN: %clang_cc1 -DCK3 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// SIMD-ONLY2-NOT: {{__kmpc|__tgt}}
#ifdef CK3
// CK3-LABEL: no_target_devices
diff --git a/test/OpenMP/target_exit_data_depend_codegen.cpp b/test/OpenMP/target_exit_data_depend_codegen.cpp
index 6f7fba23db00..fec750dde237 100644
--- a/test/OpenMP/target_exit_data_depend_codegen.cpp
+++ b/test/OpenMP/target_exit_data_depend_codegen.cpp
@@ -5,6 +5,14 @@
// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
// CK1: [[ST:%.+]] = type { i32, double* }
// CK1: %struct.kmp_depend_info = type { i[[sz:64|32]],
@@ -29,8 +37,9 @@ double gc[100];
// CK1: [[MTYPE03:@.+]] = {{.+}}constant [1 x i64] [i64 34]
-// CK1: [[SIZE04:@.+]] = {{.+}}constant [2 x i[[sz]]] [i[[sz]] {{8|4}}, i[[sz]] 24]
-// CK1: [[MTYPE04:@.+]] = {{.+}}constant [2 x i64] [i64 34, i64 18]
+// CK1-64: [[SIZE04:@.+]] = {{.+}}constant [2 x i64] [i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)), i64 24]
+// CK1-32: [[SIZE04:@.+]] = {{.+}}constant [2 x i32] [i32 trunc (i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)) to i32), i32 24]
+// CK1: [[MTYPE04:@.+]] = {{.+}}constant [2 x i64] [i64 32, i64 281474976710674]
// CK1-LABEL: _Z3fooi
void foo(int arg) {
@@ -54,25 +63,25 @@ void foo(int arg) {
// CK1: [[CAP_DEVICE:%.+]] = getelementptr inbounds %struct.anon, %struct.anon* [[CAPTURES:%.+]], i32 0, i32 0
// CK1: [[DEVICE:%.+]] = load i32, i32* %{{.+}}
// CK1: store i32 [[DEVICE]], i32* [[CAP_DEVICE]],
- // CK1: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%ident_t* {{.+}}, i32 {{.+}}, i32 1, i[[sz]] [[sz]], i[[sz]] 4, i32 (i32, i8*)* bitcast (i32 (i32, %struct.kmp_task_t_with_privates*)* [[TASK_ENTRY0:@.+]] to i32 (i32, i8*)*))
+ // CK1: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* {{.+}}, i32 {{.+}}, i32 1, i[[sz]] [[sz]], i[[sz]] 4, i32 (i32, i8*)* bitcast (i32 (i32, %struct.kmp_task_t_with_privates*)* [[TASK_ENTRY0:@.+]] to i32 (i32, i8*)*))
// CK1: [[BC:%.+]] = bitcast i8* [[RES]] to %struct.kmp_task_t_with_privates*
// CK1: [[TASK_T:%.+]] = getelementptr inbounds %struct.kmp_task_t_with_privates, %struct.kmp_task_t_with_privates* [[BC]], i32 0, i32 0
// CK1: [[SHAREDS:%.+]] = getelementptr inbounds %struct.kmp_task_t, %struct.kmp_task_t* [[TASK_T]], i32 0, i32 0
// CK1: [[SHAREDS_REF:%.+]] = load i8*, i8** [[SHAREDS]],
// CK1: [[BC1:%.+]] = bitcast %struct.anon* [[CAPTURES]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[SHAREDS_REF]], i8* [[BC1]], i[[sz]] 4, i32 4, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align 4 [[SHAREDS_REF]], i8* align 4 [[BC1]], i[[sz]] 4, i1 false)
// CK1: [[PRIVS:%.+]] = getelementptr inbounds %struct.kmp_task_t_with_privates, %struct.kmp_task_t_with_privates* [[BC]], i32 0, i32 1
// CK1: [[PRIVS_BASEPTRS:%.+]] = getelementptr inbounds %struct..kmp_privates.t, %struct..kmp_privates.t* [[PRIVS]], i32 0, i32 0
// CK1: [[BC_PRIVS_BASEPTRS:%.+]] = bitcast [1 x i8*]* [[PRIVS_BASEPTRS]] to i8*
// CK1: [[BC_BASEPTRS:%.+]] = bitcast i8** [[GEPBP0]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_BASEPTRS]], i8* [[BC_BASEPTRS]], i[[sz]] {{8|4}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_BASEPTRS]], i8* align {{8|4}} [[BC_BASEPTRS]], i[[sz]] {{8|4}}, i1 false)
// CK1: [[PRIVS_PTRS:%.+]] = getelementptr inbounds %struct..kmp_privates.t, %struct..kmp_privates.t* [[PRIVS]], i32 0, i32 1
// CK1: [[BC_PRIVS_PTRS:%.+]] = bitcast [1 x i8*]* [[PRIVS_PTRS]] to i8*
// CK1: [[BC_PTRS:%.+]] = bitcast i8** [[GEPP0]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_PTRS]], i8* [[BC_PTRS]], i[[sz]] {{8|4}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_PTRS]], i8* align {{8|4}} [[BC_PTRS]], i[[sz]] {{8|4}}, i1 false)
// CK1: [[PRIVS_SIZES:%.+]] = getelementptr inbounds %struct..kmp_privates.t, %struct..kmp_privates.t* [[PRIVS]], i32 0, i32 2
// CK1: [[BC_PRIVS_SIZES:%.+]] = bitcast [1 x i[[sz]]]* [[PRIVS_SIZES]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_SIZES]], i8* bitcast ([1 x i[[sz]]]* [[SIZE00]] to i8*), i[[sz]] {{8|4}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_SIZES]], i8* align {{8|4}} bitcast ([1 x i[[sz]]]* [[SIZE00]] to i8*), i[[sz]] {{8|4}}, i1 false)
// CK1: [[DEP:%.+]] = getelementptr inbounds [1 x %struct.kmp_depend_info], [1 x %struct.kmp_depend_info]* [[MAIN_DEP:%.+]], i[[sz]] 0, i[[sz]] 0
// CK1: [[DEP_ADR:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[DEP]], i32 0, i32 0
// CK1: [[BC_ADR:%.+]] = ptrtoint i32* %{{.+}} to i[[sz]]
@@ -83,7 +92,7 @@ void foo(int arg) {
// CK1: store i8 1, i8* [[DEP_ATTRS]]
// CK1: [[DEP:%.+]] = getelementptr inbounds [1 x %struct.kmp_depend_info], [1 x %struct.kmp_depend_info]* [[MAIN_DEP]], i32 0, i32 0
// CK1: [[BC:%.+]] = bitcast %struct.kmp_depend_info* [[DEP]] to i8*
- // CK1: = call i32 @__kmpc_omp_task_with_deps(%ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]], i32 1, i8* [[BC]], i32 0, i8* null)
+ // CK1: = call i32 @__kmpc_omp_task_with_deps(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]], i32 1, i8* [[BC]], i32 0, i8* null)
// CK1: %{{.+}} = add nsw i32 %{{[^,]+}}, 1
#pragma omp target exit data if(1+3-5) device(arg) map(from:gc) nowait depend(in: arg)
@@ -110,25 +119,25 @@ void foo(int arg) {
// CK1: [[IF_BOOL:%.+]] = trunc i8 [[IF]] to i1
// CK1: [[IF:%.+]] = zext i1 [[IF_BOOL]] to i8
// CK1: store i8 [[IF]], i8* [[IF_DEVICE]],
- // CK1: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%ident_t* {{.+}}, i32 {{.+}}, i32 1, i[[sz]] [[sz]], i[[sz]] 1, i32 (i32, i8*)* bitcast (i32 (i32, %struct.kmp_task_t_with_privates{{.+}}*)* [[TASK_ENTRY2:@.+]] to i32 (i32, i8*)*))
+ // CK1: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* {{.+}}, i32 {{.+}}, i32 1, i[[sz]] [[sz]], i[[sz]] 1, i32 (i32, i8*)* bitcast (i32 (i32, %struct.kmp_task_t_with_privates{{.+}}*)* [[TASK_ENTRY2:@.+]] to i32 (i32, i8*)*))
// CK1: [[RES_BC:%.+]] = bitcast i8* [[RES]] to %struct.kmp_task_t_with_privates{{.+}}*
// CK1: [[TASK_T:%.+]] = getelementptr inbounds %struct.kmp_task_t_with_privates{{.+}}, %struct.kmp_task_t_with_privates{{.+}}* [[RES_BC]], i32 0, i32 0
// CK1: [[SHAREDS:%.+]] = getelementptr inbounds %struct.kmp_task_t, %struct.kmp_task_t* [[TASK_T]], i32 0, i32 0
// CK1: [[SHAREDS_REF:%.+]] = load i8*, i8** [[SHAREDS]],
// CK1: [[BC1:%.+]] = bitcast %struct.anon{{.+}}* [[CAPTURES]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[SHAREDS_REF]], i8* [[BC1]], i[[sz]] 1, i32 1, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align 1 [[SHAREDS_REF]], i8* align 1 [[BC1]], i[[sz]] 1, i1 false)
// CK1: [[PRIVS:%.+]] = getelementptr inbounds %struct.kmp_task_t_with_privates{{.+}}, %struct.kmp_task_t_with_privates{{.+}}* [[RES_BC]], i32 0, i32 1
// CK1: [[PRIVS_BASEPTRS:%.+]] = getelementptr inbounds %struct..kmp_privates.t{{.+}}, %struct..kmp_privates.t{{.+}}* [[PRIVS]], i32 0, i32 0
// CK1: [[BC_PRIVS_BASEPTRS:%.+]] = bitcast [1 x i8*]* [[PRIVS_BASEPTRS]] to i8*
// CK1: [[BC_BASEPTRS:%.+]] = bitcast i8** [[GEPBP0]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_BASEPTRS]], i8* [[BC_BASEPTRS]], i[[sz]] {{8|4}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_BASEPTRS]], i8* align {{8|4}} [[BC_BASEPTRS]], i[[sz]] {{8|4}}, i1 false)
// CK1: [[PRIVS_PTRS:%.+]] = getelementptr inbounds %struct..kmp_privates.t{{.+}}, %struct..kmp_privates.t{{.+}}* [[PRIVS]], i32 0, i32 1
// CK1: [[BC_PRIVS_PTRS:%.+]] = bitcast [1 x i8*]* [[PRIVS_PTRS]] to i8*
// CK1: [[BC_PTRS:%.+]] = bitcast i8** [[GEPP0]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_PTRS]], i8* [[BC_PTRS]], i[[sz]] {{8|4}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_PTRS]], i8* align {{8|4}} [[BC_PTRS]], i[[sz]] {{8|4}}, i1 false)
// CK1: [[PRIVS_SIZES:%.+]] = getelementptr inbounds %struct..kmp_privates.t{{.+}}, %struct..kmp_privates.t{{.+}}* [[PRIVS]], i32 0, i32 2
// CK1: [[BC_PRIVS_SIZES:%.+]] = bitcast [1 x i[[sz]]]* [[PRIVS_SIZES]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_SIZES]], i8* bitcast ([1 x i[[sz]]]* [[SIZE02]] to i8*), i[[sz]] {{8|4}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_SIZES]], i8* align {{8|4}} bitcast ([1 x i[[sz]]]* [[SIZE02]] to i8*), i[[sz]] {{8|4}}, i1 false)
// CK1: [[DEP:%.+]] = getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* [[MAIN_DEP:%.+]], i[[sz]] 0, i[[sz]] 0
// CK1: [[DEP_ADR:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[DEP]], i32 0, i32 0
// CK1: [[BC_ADR:%.+]] = ptrtoint i32* %{{.+}} to i[[sz]]
@@ -154,10 +163,10 @@ void foo(int arg) {
// CK1: store i8 3, i8* [[DEP_ATTRS]]
// CK1: [[DEP:%.+]] = getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* [[MAIN_DEP]], i32 0, i32 0
// CK1: [[BC:%.+]] = bitcast %struct.kmp_depend_info* [[DEP]] to i8*
- // CK1: call void @__kmpc_omp_wait_deps(%ident_t* @{{.+}}, i32 %{{.+}}, i32 3, i8* [[BC]], i32 0, i8* null)
- // CK1: call void @__kmpc_omp_task_begin_if0(%ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
+ // CK1: call void @__kmpc_omp_wait_deps(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i32 3, i8* [[BC]], i32 0, i8* null)
+ // CK1: call void @__kmpc_omp_task_begin_if0(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
// CK1: = call i32 [[TASK_ENTRY2]](i32 %{{.+}}, %struct.kmp_task_t_with_privates{{.+}}* [[RES_BC]])
- // CK1: call void @__kmpc_omp_task_complete_if0(%ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
+ // CK1: call void @__kmpc_omp_task_complete_if0(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
// CK1: br label %[[IFEND:[^,]+]]
@@ -183,22 +192,22 @@ void foo(int arg) {
// CK1: [[GEPBP0:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[BP]], i32 0, i32 0
// CK1: [[GEPP0:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[P]], i32 0, i32 0
// CK1: [[GEPS0:%.+]] = getelementptr inbounds [1 x i[[sz]]], [1 x i[[sz]]]* [[S]], i32 0, i32 0
- // CK1: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%ident_t* {{.+}}, i32 {{.+}}, i32 1, i[[sz]] [[sz]], i[[sz]] 1, i32 (i32, i8*)* bitcast (i32 (i32, %struct.kmp_task_t_with_privates{{.+}}*)* [[TASK_ENTRY3:@.+]] to i32 (i32, i8*)*))
+ // CK1: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* {{.+}}, i32 {{.+}}, i32 1, i[[sz]] [[sz]], i[[sz]] 1, i32 (i32, i8*)* bitcast (i32 (i32, %struct.kmp_task_t_with_privates{{.+}}*)* [[TASK_ENTRY3:@.+]] to i32 (i32, i8*)*))
// CK1: [[RES_BC:%.+]] = bitcast i8* [[RES]] to %struct.kmp_task_t_with_privates{{.+}}*
// CK1: [[TASK_T:%.+]] = getelementptr inbounds %struct.kmp_task_t_with_privates{{.+}}, %struct.kmp_task_t_with_privates{{.+}}* [[RES_BC]], i32 0, i32 0
// CK1: [[PRIVS:%.+]] = getelementptr inbounds %struct.kmp_task_t_with_privates{{.+}}, %struct.kmp_task_t_with_privates{{.+}}* [[RES_BC]], i32 0, i32 1
// CK1: [[PRIVS_BASEPTRS:%.+]] = getelementptr inbounds %struct..kmp_privates.t{{.+}}, %struct..kmp_privates.t{{.+}}* [[PRIVS]], i32 0, i32 0
// CK1: [[BC_PRIVS_BASEPTRS:%.+]] = bitcast [1 x i8*]* [[PRIVS_BASEPTRS]] to i8*
// CK1: [[BC_BASEPTRS:%.+]] = bitcast i8** [[GEPBP0]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_BASEPTRS]], i8* [[BC_BASEPTRS]], i[[sz]] {{8|4}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_BASEPTRS]], i8* align {{8|4}} [[BC_BASEPTRS]], i[[sz]] {{8|4}}, i1 false)
// CK1: [[PRIVS_PTRS:%.+]] = getelementptr inbounds %struct..kmp_privates.t{{.+}}, %struct..kmp_privates.t{{.+}}* [[PRIVS]], i32 0, i32 1
// CK1: [[BC_PRIVS_PTRS:%.+]] = bitcast [1 x i8*]* [[PRIVS_PTRS]] to i8*
// CK1: [[BC_PTRS:%.+]] = bitcast i8** [[GEPP0]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_PTRS]], i8* [[BC_PTRS]], i[[sz]] {{8|4}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_PTRS]], i8* align {{8|4}} [[BC_PTRS]], i[[sz]] {{8|4}}, i1 false)
// CK1: [[PRIVS_SIZES:%.+]] = getelementptr inbounds %struct..kmp_privates.t{{.+}}, %struct..kmp_privates.t{{.+}}* [[PRIVS]], i32 0, i32 2
// CK1: [[BC_PRIVS_SIZES:%.+]] = bitcast [1 x i[[sz]]]* [[PRIVS_SIZES]] to i8*
// CK1: [[BC_SIZES:%.+]] = bitcast i[[sz]]* [[GEPS0]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_SIZES]], i8* [[BC_SIZES]], i[[sz]] {{8|4}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_SIZES]], i8* align {{8|4}} [[BC_SIZES]], i[[sz]] {{8|4}}, i1 false)
// CK1: [[DEP:%.+]] = getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* [[MAIN_DEP:%.+]], i[[sz]] 0, i[[sz]] 0
// CK1: [[DEP_ADR:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[DEP]], i32 0, i32 0
// CK1: [[BC_ADR:%.+]] = ptrtoint float* %{{.+}} to i[[sz]]
@@ -232,10 +241,10 @@ void foo(int arg) {
// CK1: store i8 3, i8* [[DEP_ATTRS]]
// CK1: [[DEP:%.+]] = getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* [[MAIN_DEP]], i32 0, i32 0
// CK1: [[BC:%.+]] = bitcast %struct.kmp_depend_info* [[DEP]] to i8*
- // CK1: call void @__kmpc_omp_wait_deps(%ident_t* @{{.+}}, i32 %{{.+}}, i32 4, i8* [[BC]], i32 0, i8* null)
- // CK1: call void @__kmpc_omp_task_begin_if0(%ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
+ // CK1: call void @__kmpc_omp_wait_deps(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i32 4, i8* [[BC]], i32 0, i8* null)
+ // CK1: call void @__kmpc_omp_task_begin_if0(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
// CK1: = call i32 [[TASK_ENTRY3]](i32 %{{.+}}, %struct.kmp_task_t_with_privates{{.+}}* [[RES_BC]])
- // CK1: call void @__kmpc_omp_task_complete_if0(%ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
+ // CK1: call void @__kmpc_omp_task_complete_if0(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
#pragma omp target exit data map(from:lb) depend(out: lb, arg, la, gc)
{++arg;}
@@ -257,21 +266,21 @@ void foo(int arg) {
// CK1: store double* %{{.+}}, double** [[P1_BC]],
// CK1: [[GEPBP0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 0
// CK1: [[GEPP0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P]], i32 0, i32 0
- // CK1: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%ident_t* {{.+}}, i32 {{.+}}, i32 1, i[[sz]] {{88|44}}, i[[sz]] 1, i32 (i32, i8*)* bitcast (i32 (i32, %struct.kmp_task_t_with_privates{{.+}}*)* [[TASK_ENTRY4:@.+]] to i32 (i32, i8*)*))
+ // CK1: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* {{.+}}, i32 {{.+}}, i32 1, i[[sz]] {{88|44}}, i[[sz]] 1, i32 (i32, i8*)* bitcast (i32 (i32, %struct.kmp_task_t_with_privates{{.+}}*)* [[TASK_ENTRY4:@.+]] to i32 (i32, i8*)*))
// CK1: [[RES_BC:%.+]] = bitcast i8* [[RES]] to %struct.kmp_task_t_with_privates{{.+}}*
// CK1: [[TASK_T:%.+]] = getelementptr inbounds %struct.kmp_task_t_with_privates{{.+}}, %struct.kmp_task_t_with_privates{{.+}}* [[RES_BC]], i32 0, i32 0
// CK1: [[PRIVS:%.+]] = getelementptr inbounds %struct.kmp_task_t_with_privates{{.+}}, %struct.kmp_task_t_with_privates{{.+}}* [[RES_BC]], i32 0, i32 1
// CK1: [[PRIVS_BASEPTRS:%.+]] = getelementptr inbounds %struct..kmp_privates.t{{.+}}, %struct..kmp_privates.t{{.+}}* [[PRIVS]], i32 0, i32 0
// CK1: [[BC_PRIVS_BASEPTRS:%.+]] = bitcast [2 x i8*]* [[PRIVS_BASEPTRS]] to i8*
// CK1: [[BC_BASEPTRS:%.+]] = bitcast i8** [[GEPBP0]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_BASEPTRS]], i8* [[BC_BASEPTRS]], i[[sz]] {{16|8}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_BASEPTRS]], i8* align {{8|4}} [[BC_BASEPTRS]], i[[sz]] {{16|8}}, i1 false)
// CK1: [[PRIVS_PTRS:%.+]] = getelementptr inbounds %struct..kmp_privates.t{{.+}}, %struct..kmp_privates.t{{.+}}* [[PRIVS]], i32 0, i32 1
// CK1: [[BC_PRIVS_PTRS:%.+]] = bitcast [2 x i8*]* [[PRIVS_PTRS]] to i8*
// CK1: [[BC_PTRS:%.+]] = bitcast i8** [[GEPP0]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_PTRS]], i8* [[BC_PTRS]], i[[sz]] {{16|8}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_PTRS]], i8* align {{8|4}} [[BC_PTRS]], i[[sz]] {{16|8}}, i1 false)
// CK1: [[PRIVS_SIZES:%.+]] = getelementptr inbounds %struct..kmp_privates.t{{.+}}, %struct..kmp_privates.t{{.+}}* [[PRIVS]], i32 0, i32 2
// CK1: [[BC_PRIVS_SIZES:%.+]] = bitcast [2 x i[[sz]]]* [[PRIVS_SIZES]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_SIZES]], i8* bitcast ([2 x i[[sz]]]* [[SIZE04]] to i8*), i[[sz]] {{16|8}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_SIZES]], i8* align {{8|4}} bitcast ([2 x i[[sz]]]* [[SIZE04]] to i8*), i[[sz]] {{16|8}}, i1 false)
// CK1: [[DEP:%.+]] = getelementptr inbounds [5 x %struct.kmp_depend_info], [5 x %struct.kmp_depend_info]* [[MAIN_DEP:%.+]], i[[sz]] 0, i[[sz]] 0
// CK1: [[DEP_ADR:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[DEP]], i32 0, i32 0
// CK1: [[BC_ADR:%.+]] = ptrtoint double* %{{.+}} to i[[sz]]
@@ -313,10 +322,10 @@ void foo(int arg) {
// CK1: store i8 1, i8* [[DEP_ATTRS]]
// CK1: [[DEP:%.+]] = getelementptr inbounds [5 x %struct.kmp_depend_info], [5 x %struct.kmp_depend_info]* [[MAIN_DEP]], i32 0, i32 0
// CK1: [[BC:%.+]] = bitcast %struct.kmp_depend_info* [[DEP]] to i8*
- // CK1: call void @__kmpc_omp_wait_deps(%ident_t* @{{.+}}, i32 %{{.+}}, i32 5, i8* [[BC]], i32 0, i8* null)
- // CK1: call void @__kmpc_omp_task_begin_if0(%ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
+ // CK1: call void @__kmpc_omp_wait_deps(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i32 5, i8* [[BC]], i32 0, i8* null)
+ // CK1: call void @__kmpc_omp_task_begin_if0(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
// CK1: = call i32 [[TASK_ENTRY4]](i32 %{{.+}}, %struct.kmp_task_t_with_privates{{.+}}* [[RES_BC]])
- // CK1: call void @__kmpc_omp_task_complete_if0(%ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
+ // CK1: call void @__kmpc_omp_task_complete_if0(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
#pragma omp target exit data map(from:gb.b[:3]) depend(in: gb.b[:3], la, lb, gc, arg)
{++arg;}
}
@@ -328,9 +337,9 @@ void foo(int arg) {
// CK1-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
// CK1-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
// CK1-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
-// CK1-DAG: [[BP]] = load [1 x i8*]*, [1 x i8*]** [[BP_PRIV:%.+]],
-// CK1-DAG: [[P]] = load [1 x i8*]*, [1 x i8*]** [[P_PRIV:%.+]],
-// CK1-DAG: [[S]] = load [1 x i[[sz]]]*, [1 x i[[sz]]]** [[S_PRIV:%.+]],
+// CK1-DAG: [[BP]] = load [1 x i8*]*, [1 x i8*]** [[BP_PRIV:%[^,]+]],
+// CK1-DAG: [[P]] = load [1 x i8*]*, [1 x i8*]** [[P_PRIV:%[^,]+]],
+// CK1-DAG: [[S]] = load [1 x i[[sz]]]*, [1 x i[[sz]]]** [[S_PRIV:%[^,]+]],
// CK1-DAG: call void (i8*, ...) %{{.+}}(i8* %{{[^,]+}}, [1 x i8*]** [[BP_PRIV]], [1 x i8*]** [[P_PRIV]], [1 x i[[sz]]]** [[S_PRIV]])
// CK1: ret i32 0
// CK1: }
@@ -340,9 +349,9 @@ void foo(int arg) {
// CK1-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
// CK1-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
// CK1-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
-// CK1-DAG: [[BP]] = load [1 x i8*]*, [1 x i8*]** [[BP_PRIV:%.+]],
-// CK1-DAG: [[P]] = load [1 x i8*]*, [1 x i8*]** [[P_PRIV:%.+]],
-// CK1-DAG: [[S]] = load [1 x i[[sz]]]*, [1 x i[[sz]]]** [[S_PRIV:%.+]],
+// CK1-DAG: [[BP]] = load [1 x i8*]*, [1 x i8*]** [[BP_PRIV:%[^,]+]],
+// CK1-DAG: [[P]] = load [1 x i8*]*, [1 x i8*]** [[P_PRIV:%[^,]+]],
+// CK1-DAG: [[S]] = load [1 x i[[sz]]]*, [1 x i[[sz]]]** [[S_PRIV:%[^,]+]],
// CK1-DAG: call void (i8*, ...) %{{.+}}(i8* %{{[^,]+}}, [1 x i8*]** [[BP_PRIV]], [1 x i8*]** [[P_PRIV]], [1 x i[[sz]]]** [[S_PRIV]])
// CK1: ret i32 0
// CK1: }
@@ -353,9 +362,9 @@ void foo(int arg) {
// CK1-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
// CK1-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
-// CK1-DAG: [[BP]] = load [1 x i8*]*, [1 x i8*]** [[BP_PRIV:%.+]],
-// CK1-DAG: [[P]] = load [1 x i8*]*, [1 x i8*]** [[P_PRIV:%.+]],
-// CK1-DAG: [[S]] = load [1 x i[[sz]]]*, [1 x i[[sz]]]** [[S_PRIV:%.+]],
+// CK1-DAG: [[BP]] = load [1 x i8*]*, [1 x i8*]** [[BP_PRIV:%[^,]+]],
+// CK1-DAG: [[P]] = load [1 x i8*]*, [1 x i8*]** [[P_PRIV:%[^,]+]],
+// CK1-DAG: [[S]] = load [1 x i[[sz]]]*, [1 x i[[sz]]]** [[S_PRIV:%[^,]+]],
// CK1-DAG: call void (i8*, ...) %{{.+}}(i8* %{{[^,]+}}, [1 x i8*]** [[BP_PRIV]], [1 x i8*]** [[P_PRIV]], [1 x i[[sz]]]** [[S_PRIV]])
// CK1-NOT: __tgt_target_data_end
// CK1: ret i32 0
@@ -367,9 +376,9 @@ void foo(int arg) {
// CK1-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
// CK1-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
-// CK1-DAG: [[BP]] = load [2 x i8*]*, [2 x i8*]** [[BP_PRIV:%.+]],
-// CK1-DAG: [[P]] = load [2 x i8*]*, [2 x i8*]** [[P_PRIV:%.+]],
-// CK1-DAG: [[S]] = load [2 x i[[sz]]]*, [2 x i[[sz]]]** [[S_PRIV:%.+]],
+// CK1-DAG: [[BP]] = load [2 x i8*]*, [2 x i8*]** [[BP_PRIV:%[^,]+]],
+// CK1-DAG: [[P]] = load [2 x i8*]*, [2 x i8*]** [[P_PRIV:%[^,]+]],
+// CK1-DAG: [[S]] = load [2 x i[[sz]]]*, [2 x i[[sz]]]** [[S_PRIV:%[^,]+]],
// CK1-DAG: call void (i8*, ...) %{{.+}}(i8* %{{[^,]+}}, [2 x i8*]** [[BP_PRIV]], [2 x i8*]** [[P_PRIV]], [2 x i[[sz]]]** [[S_PRIV]])
// CK1-NOT: __tgt_target_data_end
// CK1: ret i32 0
diff --git a/test/OpenMP/target_exit_data_depend_messages.cpp b/test/OpenMP/target_exit_data_depend_messages.cpp
index ce8d237f75e9..7334cd751f14 100644
--- a/test/OpenMP/target_exit_data_depend_messages.cpp
+++ b/test/OpenMP/target_exit_data_depend_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_exit_data_device_messages.cpp b/test/OpenMP/target_exit_data_device_messages.cpp
index d9ce0ddd7ea0..ad27e8a50dd8 100644
--- a/test/OpenMP/target_exit_data_device_messages.cpp
+++ b/test/OpenMP/target_exit_data_device_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/target_exit_data_if_messages.cpp b/test/OpenMP/target_exit_data_if_messages.cpp
index 6d5ada14e9da..9341fe81794b 100644
--- a/test/OpenMP/target_exit_data_if_messages.cpp
+++ b/test/OpenMP/target_exit_data_if_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -fopenmp-version=45 -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -fopenmp-version=45 -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/target_exit_data_map_messages.c b/test/OpenMP/target_exit_data_map_messages.c
index 84bd7e79fd03..1c15aac2e5d9 100644
--- a/test/OpenMP/target_exit_data_map_messages.c
+++ b/test/OpenMP/target_exit_data_map_messages.c
@@ -1,6 +1,9 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - -x c++ %s
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -ferror-limit 100 -o - -x c++ %s
+
int main(int argc, char **argv) {
int r;
diff --git a/test/OpenMP/target_exit_data_nowait_messages.cpp b/test/OpenMP/target_exit_data_nowait_messages.cpp
index d0286031f362..02eded5a66df 100644
--- a/test/OpenMP/target_exit_data_nowait_messages.cpp
+++ b/test/OpenMP/target_exit_data_nowait_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
int main(int argc, char **argv) {
int i;
diff --git a/test/OpenMP/target_firstprivate_codegen.cpp b/test/OpenMP/target_firstprivate_codegen.cpp
index c2909c6f18b8..4a2837b3c83c 100644
--- a/test/OpenMP/target_firstprivate_codegen.cpp
+++ b/test/OpenMP/target_firstprivate_codegen.cpp
@@ -6,6 +6,14 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// Test target codegen - host bc file has to be created first.
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
@@ -16,6 +24,16 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -33,15 +51,15 @@ struct TT{
// TCHECK: [[S1:%.+]] = type { double }
// CHECK-DAG: [[SIZET:@.+]] = private unnamed_addr constant [1 x i{{32|64}}] [i[[SZ:32|64]] 4]
-// CHECK: [[MAPT:@.+]] = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [9 x i64] [i64 288, i64 161, i64 288, i64 161, i64 161, i64 288, i64 288, i64 161, i64 161]
+// CHECK: [[MAPT:@.+]] = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [9 x i64] [i64 800, i64 673, i64 288, i64 673, i64 673, i64 288, i64 288, i64 673, i64 673]
// CHECK-DAG: [[SIZET3:@.+]] = private unnamed_addr constant [1 x i{{32|64}}] zeroinitializer
-// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [1 x i64] [i64 32]
-// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [5 x i64] [i64 547, i64 288, i64 288, i64 288, i64 161]
+// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [1 x i64] [i64 544]
+// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [6 x i64] [i64 32, i64 281474976711171, i64 800, i64 288, i64 288, i64 673]
// CHECK-DAG: [[SIZET5:@.+]] = private unnamed_addr constant [3 x i{{32|64}}] [i[[SZ]] 4, i[[SZ]] 1, i[[SZ]] 40]
-// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [3 x i64] [i64 288, i64 288, i64 161]
+// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [3 x i64] [i64 800, i64 800, i64 673]
// CHECK-DAG: [[SIZET6:@.+]] = private unnamed_addr constant [2 x i{{32|64}}] [i[[SZ]] 4, i[[SZ]] 40]
-// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [2 x i64] [i64 288, i64 161]
+// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [2 x i64] [i64 800, i64 673]
// CHECK: define {{.*}}[[FOO:@.+]](
@@ -102,7 +120,7 @@ int foo(int n, double *ptr) {
// CHECK: [[PTR_GEP_ARG:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[PTR_ARR]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: {{.+}} = call i32 @__tgt_target(i64 -1, {{.+}}, i32 1, i8** [[BASE_PTR_GEP_ARG]], i8** [[PTR_GEP_ARG]], i[[SZ]]* getelementptr inbounds ([1 x i[[SZ]]], [1 x i[[SZ]]]* [[SIZET]], i32 0, i32 0), i64* getelementptr inbounds ([1 x i64], [1 x i64]* [[MAPT]], i32 0, i32 0))
- // TCHECK: define void @__omp_offloading_{{.+}}(i{{[0-9]+}} [[A_IN:%.+]])
+ // TCHECK: define weak void @__omp_offloading_{{.+}}(i{{[0-9]+}} [[A_IN:%.+]])
// TCHECK: [[A_ADDR:%.+]] = alloca i{{[0-9]+}},
// TCHECK-NOT: alloca i{{[0-9]+}},
// TCHECK: store i{{[0-9]+}} [[A_IN]], i{{[0-9]+}}* [[A_ADDR]],
@@ -263,7 +281,7 @@ int foo(int n, double *ptr) {
// firstprivate(b): memcpy(b_priv,b_in)
// TCHECK: [[B_PRIV_BCAST:%.+]] = bitcast [10 x float]* [[B_PRIV]] to i8*
// TCHECK: [[B_ADDR_REF_BCAST:%.+]] = bitcast [10 x float]* [[B_ADDR_REF]] to i8*
- // TCHECK: call void @llvm.memcpy.{{.+}}(i8* [[B_PRIV_BCAST]], i8* [[B_ADDR_REF_BCAST]], {{.+}})
+ // TCHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[B_PRIV_BCAST]], i8* align {{[0-9]+}} [[B_ADDR_REF_BCAST]], {{.+}})
// TCHECK: [[RET_STACK:%.+]] = call i8* @llvm.stacksave()
// TCHECK: store i8* [[RET_STACK]], i8** [[SSTACK]],
@@ -273,12 +291,12 @@ int foo(int n, double *ptr) {
// TCHECK: [[BN_COPY_SZ:%.+]] = mul{{.+}} i{{[0-9]+}} [[BN_SZ_VAL]], 4
// TCHECK: [[BN_PRIV__BCAST:%.+]] = bitcast float* [[BN_PRIV]] to i8*
// TCHECK: [[BN_REF_IN_BCAST:%.+]] = bitcast float* [[BN_ADDR_REF]] to i8*
- // TCHECK: call void @llvm.memcpy.{{.+}}(i8* [[BN_PRIV__BCAST]], i8* [[BN_REF_IN_BCAST]], i{{[0-9]+}} [[BN_COPY_SZ]],{{.+}})
+ // TCHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[BN_PRIV__BCAST]], i8* align {{[0-9]+}} [[BN_REF_IN_BCAST]], i{{[0-9]+}} [[BN_COPY_SZ]],{{.+}})
// firstprivate(c)
// TCHECK: [[C_PRIV_BCAST:%.+]] = bitcast [5 x [10 x double]]* [[C_PRIV]] to i8*
// TCHECK: [[C_IN_BCAST:%.+]] = bitcast [5 x [10 x double]]* [[C_ADDR_REF]] to i8*
- // TCHECK: call void @llvm.memcpy.{{.+}}(i8* [[C_PRIV_BCAST]], i8* [[C_IN_BCAST]],{{.+}})
+ // TCHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[C_PRIV_BCAST]], i8* align {{[0-9]+}} [[C_IN_BCAST]],{{.+}})
// firstprivate(cn)
// TCHECK: [[CN_SZ:%.+]] = mul{{.+}} i{{[0-9]+}} [[CN_SZ1_VAL]], [[CN_SZ2_VAL]]
@@ -287,12 +305,12 @@ int foo(int n, double *ptr) {
// TCHECK: [[CN_SZ2_CPY:%.+]] = mul{{.+}} i{{[0-9]+}} [[CN_SZ2]], 8
// TCHECK: [[CN_PRIV_BCAST:%.+]] = bitcast double* [[CN_PRIV]] to i8*
// TCHECK: [[CN_IN_BCAST:%.+]] = bitcast double* [[CN_ADDR_REF]] to i8*
- // TCHECK: call void @llvm.memcpy.{{.+}}(i8* [[CN_PRIV_BCAST]], i8* [[CN_IN_BCAST]], i{{[0-9]+}} [[CN_SZ2_CPY]],{{.+}})
+ // TCHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[CN_PRIV_BCAST]], i8* align {{[0-9]+}} [[CN_IN_BCAST]], i{{[0-9]+}} [[CN_SZ2_CPY]],{{.+}})
// firstprivate(d)
// TCHECK: [[D_PRIV_BCAST:%.+]] = bitcast [[TT]]* [[D_PRIV]] to i8*
// TCHECK: [[D_IN_BCAST:%.+]] = bitcast [[TT]]* [[D_ADDR_REF]] to i8*
- // TCHECK: call void @llvm.memcpy.{{.+}}(i8* [[D_PRIV_BCAST]], i8* [[D_IN_BCAST]],{{.+}})
+ // TCHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[D_PRIV_BCAST]], i8* align {{[0-9]+}} [[D_IN_BCAST]],{{.+}})
#pragma omp target firstprivate(ptr)
@@ -312,7 +330,7 @@ int foo(int n, double *ptr) {
// CHECK: [[PTR_GEP_ARG3:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[PTR_ARR3]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: {{.+}} = call i32 @__tgt_target(i64 -1, {{.+}}, i32 1, i8** [[BASE_PTR_GEP_ARG3]], i8** [[PTR_GEP_ARG3]], i[[SZ]]* getelementptr inbounds ([1 x i[[SZ]]], [1 x i[[SZ]]]* [[SIZET3]], i32 0, i32 0), i64* getelementptr inbounds ([1 x i64], [1 x i64]* [[MAPT3]], i32 0, i32 0))
- // TCHECK: define void @__omp_offloading_{{.+}}(double* [[PTR_IN:%.+]])
+ // TCHECK: define weak void @__omp_offloading_{{.+}}(double* [[PTR_IN:%.+]])
// TCHECK: [[PTR_ADDR:%.+]] = alloca double*,
// TCHECK-NOT: alloca double*,
// TCHECK: store double* [[PTR_IN]], double** [[PTR_ADDR]],
@@ -352,7 +370,7 @@ int fstatic(int n) {
return a;
}
-// TCHECK: define void @__omp_offloading_{{.+}}(i{{[0-9]+}} [[A_IN:%.+]], i{{[0-9]+}} [[A3_IN:%.+]], [10 x i{{[0-9]+}}]*{{.+}} [[B_IN:%.+]])
+// TCHECK: define weak void @__omp_offloading_{{.+}}(i{{[0-9]+}} [[A_IN:%.+]], i{{[0-9]+}} [[A3_IN:%.+]], [10 x i{{[0-9]+}}]*{{.+}} [[B_IN:%.+]])
// TCHECK: [[A_ADDR:%.+]] = alloca i{{[0-9]+}},
// TCHECK: [[A3_ADDR:%.+]] = alloca i{{[0-9]+}},
// TCHECK: [[B_ADDR:%.+]] = alloca [10 x i{{[0-9]+}}]*,
@@ -373,7 +391,7 @@ int fstatic(int n) {
// firstprivate(b)
// TCHECK: [[B_PRIV_BCAST:%.+]] = bitcast [10 x i{{[0-9]+}}]* [[B_PRIV]] to i8*
// TCHECK: [[B_IN_BCAST:%.+]] = bitcast [10 x i{{[0-9]+}}]* [[B_ADDR_REF]] to i8*
-// TCHECK: call void @llvm.memcpy.{{.+}}(i8* [[B_PRIV_BCAST]], i8* [[B_IN_BCAST]],{{.+}})
+// TCHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[B_PRIV_BCAST]], i8* align {{[0-9]+}} [[B_IN_BCAST]],{{.+}})
// TCHECK: ret void
@@ -395,60 +413,71 @@ struct S1 {
// on the host side, we first generate r1, then the static function and the template above
// CHECK: define{{.+}} i32 {{.+}}([[S1]]* {{.+}}, i{{[0-9]+}} {{.+}})
- // CHECK: [[BASE_PTRS4:%.+]] = alloca [5 x i8*],
- // CHECK: [[PTRS4:%.+]] = alloca [5 x i8*],
- // CHECK: [[SIZET4:%.+]] = alloca [5 x i{{[0-9]+}}],
+ // CHECK: [[BASE_PTRS4:%.+]] = alloca [6 x i8*],
+ // CHECK: [[PTRS4:%.+]] = alloca [6 x i8*],
+ // CHECK: [[SIZET4:%.+]] = alloca [6 x i{{[0-9]+}}],
// map(this: this ptr is implicitly captured (not firstprivate matter)
- // CHECK: {{.+}} = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BASE_PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
- // CHECK: store {{.+}}, {{.+}},
- // CHECK: {{.+}} = getelementptr inbounds [5 x i8*], [5 x i8*]* [[PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
- // CHECK: store {{.+}}, {{.+}},
- // CHECK: {{.+}} getelementptr inbounds [5 x i{{[0-9]+}}], [5 x i{{[0-9]+}}]* [[SIZET4]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
- // CHECK: store {{.+}}, {{.+}}
+ // CHECK: [[BP0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BASE_PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
+ // CHECK: [[CBP0:%.+]] = bitcast i8** [[BP0]] to %struct.S1**
+ // CHECK: store %struct.S1* [[THIS:%.+]], %struct.S1** [[CBP0]],
+ // CHECK: [[P0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
+ // CHECK: [[CP0:%.+]] = bitcast i8** [[P0]] to double**
+ // CHECK: store double* [[A:%.+]], double** [[CP0]],
+ // CHECK: [[SZ0:%.+]] = getelementptr inbounds [6 x i{{[0-9]+}}], [6 x i{{[0-9]+}}]* [[SIZET4]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
+ // CHECK: store i{{[0-9]+}} %{{.+}}, i{{[0-9]+}}* [[SZ0]],
+
+ // CHECK: [[BP1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BASE_PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 1
+ // CHECK: [[CBP1:%.+]] = bitcast i8** [[BP1]] to %struct.S1**
+ // CHECK: store %struct.S1* [[THIS]], %struct.S1** [[CBP1]],
+ // CHECK: [[P1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 1
+ // CHECK: [[CP1:%.+]] = bitcast i8** [[P1]] to double**
+ // CHECK: store double* [[A]], double** [[CP1]],
+ // CHECK: [[SZ1:%.+]] = getelementptr inbounds [6 x i{{[0-9]+}}], [6 x i{{[0-9]+}}]* [[SIZET4]], i{{[0-9]+}} 0, i{{[0-9]+}} 1
+ // CHECK: store i{{[0-9]+}} 8, i{{[0-9]+}}* [[SZ1]],
// firstprivate(b): base_ptr = b, ptr = b, size = 4 (pass by-value)
- // CHECK: [[BASE_PTRS_GEP4_1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BASE_PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 1
+ // CHECK: [[BASE_PTRS_GEP4_1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BASE_PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 2
// CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTRS_GEP4_1]] to i{{[0-9]+}}*
// CHECK: store i{{[0-9]+}} [[B_CAST:%.+]], i{{[0-9]+}}* [[BCAST_TOPTR]],
- // CHECK: [[PTRS_GEP4_1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 1
+ // CHECK: [[PTRS_GEP4_1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 2
// CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[PTRS_GEP4_1]] to i{{[0-9]+}}*
// CHECK: store i{{[0-9]+}} [[B_CAST]], i{{[0-9]+}}* [[BCAST_TOPTR]],
- // CHECK: [[SIZES_GEP4_1:%.+]] = getelementptr inbounds [5 x i{{[0-9]+}}], [5 x i{{[0-9]+}}]* [[SIZET4]], i{{[0-9]+}} 0, i{{[0-9]+}} 1
+ // CHECK: [[SIZES_GEP4_1:%.+]] = getelementptr inbounds [6 x i{{[0-9]+}}], [6 x i{{[0-9]+}}]* [[SIZET4]], i{{[0-9]+}} 0, i{{[0-9]+}} 2
// CHECK: store i{{[0-9]+}} 4, i{{[0-9]+}}* [[SIZES_GEP4_1]],
// firstprivate(c), 3 entries: 2, n, c
- // CHECK: [[BASE_PTRS_GEP4_2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BASE_PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 2
+ // CHECK: [[BASE_PTRS_GEP4_2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BASE_PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 3
// CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTRS_GEP4_2]] to i{{[0-9]+}}*
// CHECK: store i{{[0-9]+}} 2, i{{[0-9]+}}* [[BCAST_TOPTR]],
- // CHECK: [[PTRS_GEP4_2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 2
+ // CHECK: [[PTRS_GEP4_2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 3
// CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[PTRS_GEP4_2]] to i{{[0-9]+}}*
// CHECK: store i{{[0-9]+}} 2, i{{[0-9]+}}* [[BCAST_TOPTR]],
- // CHECK: [[SIZES_GEP4_2:%.+]] = getelementptr inbounds [5 x i{{[0-9]+}}], [5 x i{{[0-9]+}}]* [[SIZET4]], i{{[0-9]+}} 0, i{{[0-9]+}} 2
+ // CHECK: [[SIZES_GEP4_2:%.+]] = getelementptr inbounds [6 x i{{[0-9]+}}], [6 x i{{[0-9]+}}]* [[SIZET4]], i{{[0-9]+}} 0, i{{[0-9]+}} 3
// CHECK-64: store i{{[0-9]+}} 8, i{{[0-9]+}}* [[SIZES_GEP4_2]],
// CHECK-32: store i{{[0-9]+}} 4, i{{[0-9]+}}* [[SIZES_GEP4_2]],
- // CHECK: [[BASE_PTRS_GEP4_3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BASE_PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 3
+ // CHECK: [[BASE_PTRS_GEP4_3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BASE_PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 4
// CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTRS_GEP4_3]] to i{{[0-9]+}}*
// CHECK: store i{{[0-9]+}} [[N:%.+]], i{{[0-9]+}}* [[BCAST_TOPTR]],
- // CHECK: [[PTRS_GEP4_3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 3
+ // CHECK: [[PTRS_GEP4_3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 4
// CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[PTRS_GEP4_3]] to i{{[0-9]+}}*
// CHECK: store i{{[0-9]+}} [[N]], i{{[0-9]+}}* [[BCAST_TOPTR]],
- // CHECK: [[SIZES_GEP4_3:%.+]] = getelementptr inbounds [5 x i{{[0-9]+}}], [5 x i{{[0-9]+}}]* [[SIZET4]], i{{[0-9]+}} 0, i{{[0-9]+}} 3
+ // CHECK: [[SIZES_GEP4_3:%.+]] = getelementptr inbounds [6 x i{{[0-9]+}}], [6 x i{{[0-9]+}}]* [[SIZET4]], i{{[0-9]+}} 0, i{{[0-9]+}} 4
// CHECK-64: store i{{[0-9]+}} 8, i{{[0-9]+}}* [[SIZES_GEP4_3]],
// CHECK-32: store i{{[0-9]+}} 4, i{{[0-9]+}}* [[SIZES_GEP4_3]],
- // CHECK: [[BASE_PTRS_GEP4_4:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BASE_PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 4
+ // CHECK: [[BASE_PTRS_GEP4_4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BASE_PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 5
// CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTRS_GEP4_4]] to i{{[0-9]+}}**
// CHECK: store i{{[0-9]+}}* [[B:%.+]], i{{[0-9]+}}** [[BCAST_TOPTR]],
- // CHECK: [[PTRS_GEP4_4:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 4
+ // CHECK: [[PTRS_GEP4_4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 5
// CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[PTRS_GEP4_4]] to i{{[0-9]+}}**
// CHECK: store i{{[0-9]+}}* [[B]], i{{[0-9]+}}** [[BCAST_TOPTR]],
- // CHECK: [[SIZES_GEP4_4:%.+]] = getelementptr inbounds [5 x i{{[0-9]+}}], [5 x i{{[0-9]+}}]* [[SIZET4]], i{{[0-9]+}} 0, i{{[0-9]+}} 4
+ // CHECK: [[SIZES_GEP4_4:%.+]] = getelementptr inbounds [6 x i{{[0-9]+}}], [6 x i{{[0-9]+}}]* [[SIZET4]], i{{[0-9]+}} 0, i{{[0-9]+}} 5
// CHECK: store i{{[0-9]+}} [[B_SIZE:%.+]], i{{[0-9]+}}* [[SIZES_GEP4_4]],
// only check that we use the map types stored in the global variable
- // CHECK: call i32 @__tgt_target(i64 -1, {{.+}}, i32 5, i8** {{.+}}, i8** {{.+}}, i{{[0-9]+}}* {{.+}}, i64* getelementptr inbounds ([5 x i64], [5 x i64]* [[MAPT4]], i32 0, i32 0))
-
- // TCHECK: define void @__omp_offloading_{{.+}}([[S1]]* [[TH:%.+]], i{{[0-9]+}} [[B_IN:%.+]], i{{[0-9]+}} [[VLA:%.+]], i{{[0-9]+}} [[VLA1:%.+]], i{{[0-9]+}}{{.+}} [[C_IN:%.+]])
+ // CHECK: call i32 @__tgt_target(i64 -1, {{.+}}, i32 6, i8** {{.+}}, i8** {{.+}}, i{{[0-9]+}}* {{.+}}, i64* getelementptr inbounds ([6 x i64], [6 x i64]* [[MAPT4]], i32 0, i32 0))
+
+ // TCHECK: define weak void @__omp_offloading_{{.+}}([[S1]]* [[TH:%.+]], i{{[0-9]+}} [[B_IN:%.+]], i{{[0-9]+}} [[VLA:%.+]], i{{[0-9]+}} [[VLA1:%.+]], i{{[0-9]+}}{{.+}} [[C_IN:%.+]])
// TCHECK: [[TH_ADDR:%.+]] = alloca [[S1]]*,
// TCHECK: [[B_ADDR:%.+]] = alloca i{{[0-9]+}},
// TCHECK: [[VLA_ADDR:%.+]] = alloca i{{[0-9]+}},
@@ -481,7 +510,7 @@ struct S1 {
// TCHECK: [[C_SZ_CPY:%.+]] = mul{{.+}} i{{[0-9]+}} [[C_SZ2]], 2
// TCHECK: [[C_PRIV_BCAST:%.+]] = bitcast i{{[0-9]+}}* [[C_PRIV]] to i8*
// TCHECK: [[C_IN_BCAST:%.+]] = bitcast i{{[0-9]+}}* [[C_ADDR_REF]] to i8*
- // TCHECK: call void @llvm.memcpy.{{.+}}(i8* [[C_PRIV_BCAST]], i8* [[C_IN_BCAST]],{{.+}})
+ // TCHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[C_PRIV_BCAST]], i8* align {{[0-9]+}} [[C_IN_BCAST]],{{.+}})
// finish
// TCHECK: [[RELOAD_SSTACK:%.+]] = load i8*, i8** [[SSTACK]],
@@ -559,8 +588,7 @@ int bar(int n, double *ptr){
// CHECK: call i32 @__tgt_target(i64 -1, {{.+}}, i32 2, i8** {{.+}}, i8** {{.+}}, i[[SZ]]* getelementptr inbounds ([2 x i[[SZ]]], [2 x i[[SZ]]]* [[SIZET6]], i32 0, i32 0), i64* getelementptr inbounds ([2 x i64], [2 x i64]* [[MAPT6]], i32 0, i32 0))
-
-// TCHECK: define void @__omp_offloading_{{.+}}(i{{[0-9]+}} [[A_IN:%.+]], [10 x i{{[0-9]+}}]*{{.+}} [[B_IN:%.+]])
+// TCHECK: define weak void @__omp_offloading_{{.+}}(i{{[0-9]+}} [[A_IN:%.+]], [10 x i{{[0-9]+}}]*{{.+}} [[B_IN:%.+]])
// TCHECK: [[A_ADDR:%.+]] = alloca i{{[0-9]+}},
// TCHECK: [[B_ADDR:%.+]] = alloca [10 x i{{[0-9]+}}]*,
// TCHECK-NOT: alloca i{{[0-9]+}},
@@ -576,7 +604,7 @@ int bar(int n, double *ptr){
// firstprivate(b)
// TCHECK: [[B_PRIV_BCAST:%.+]] = bitcast [10 x i{{[0-9]+}}]* [[B_PRIV]] to i8*
// TCHECK: [[B_IN_BCAST:%.+]] = bitcast [10 x i{{[0-9]+}}]* [[B_ADDR_REF]] to i8*
-// TCHECK: call void @llvm.memcpy.{{.+}}(i8* [[B_PRIV_BCAST]], i8* [[B_IN_BCAST]],{{.+}})
+// TCHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[B_PRIV_BCAST]], i8* align {{[0-9]+}} [[B_IN_BCAST]],{{.+}})
// TCHECK: ret void
diff --git a/test/OpenMP/target_firstprivate_messages.cpp b/test/OpenMP/target_firstprivate_messages.cpp
index 6dbad671de7c..4f82c96e564c 100644
--- a/test/OpenMP/target_firstprivate_messages.cpp
+++ b/test/OpenMP/target_firstprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
struct S1; // expected-note 2 {{declared here}} expected-note 2 {{forward declaration of 'S1'}}
extern S1 a;
class S2 {
@@ -36,7 +38,7 @@ public:
S5(int v) : a(v) {}
S5 &operator=(S5 &s) {
#pragma omp target firstprivate(a) firstprivate(this->a) firstprivate(s.a) // expected-error {{expected variable name or data member of current class}}
- for (int k = 0; k < s.a; ++k)
+ for (int k = 0; k < s.a; ++k) // expected-warning {{Non-trivial type 'S5' is mapped, only trivial types are guaranteed to be mapped correctly}}
++s.a;
return *this;
}
diff --git a/test/OpenMP/target_if_messages.cpp b/test/OpenMP/target_if_messages.cpp
index 14b6a5fbf938..982fd4b0c028 100644
--- a/test/OpenMP/target_if_messages.cpp
+++ b/test/OpenMP/target_if_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_is_device_ptr_ast_print.cpp b/test/OpenMP/target_is_device_ptr_ast_print.cpp
index 8e56aa24d9bd..4e8bf8143542 100644
--- a/test/OpenMP/target_is_device_ptr_ast_print.cpp
+++ b/test/OpenMP/target_is_device_ptr_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -50,7 +54,7 @@ struct SA {
// CHECK-NEXT: int aa[10];
// CHECK-NEXT: arr &raa = this->aa;
// CHECK-NEXT: func(
-// CHECK-NEXT: #pragma omp target is_device_ptr(this->k)
+// CHECK-NEXT: #pragma omp target is_device_ptr(this->k){{$}}
// CHECK-NEXT: {
// CHECK-NEXT: }
// CHECK-NEXT: #pragma omp target is_device_ptr(this->z)
diff --git a/test/OpenMP/target_is_device_ptr_codegen.cpp b/test/OpenMP/target_is_device_ptr_codegen.cpp
index 1491f41a787f..90514acadf81 100644
--- a/test/OpenMP/target_is_device_ptr_codegen.cpp
+++ b/test/OpenMP/target_is_device_ptr_codegen.cpp
@@ -9,6 +9,14 @@
// RUN: %clang_cc1 -DCK1 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
// RUN: %clang_cc1 -DCK1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
#ifdef CK1
double *g;
@@ -35,7 +43,7 @@ double *g;
// CK1: [[SIZES06:@.+]] = {{.+}}constant [2 x i[[sz]]] [i[[sz]] {{8|4}}, i[[sz]] {{8|4}}]
// CK1: [[TYPES06:@.+]] = {{.+}}constant [2 x i64] [i64 288, i64 288]
-// CK1-LABEL: @_Z3foo
+// CK1-LABEL: @_Z3foo{{.*}}(
template<typename T>
void foo(float *&lr, T *&tr) {
float *l;
@@ -186,18 +194,32 @@ void bar(float *&a, int *&b) {
// RUN: %clang_cc1 -DCK2 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
// RUN: %clang_cc1 -DCK2 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
#ifdef CK2
// CK2: [[ST:%.+]] = type { double*, double** }
+// CK2-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l244.region_id = weak constant i8 0
+
// CK2: [[SIZE00:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} {{8|4}}]
-// CK2: [[MTYPE00:@.+]] = {{.+}}constant [1 x i64] [i64 33]
+// CK2: [[MTYPE00:@.+]] = {{.+}}constant [1 x i64] [i64 288]
+
+// CK2-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l259.region_id = weak constant i8 0
-// CK2: [[SIZE01:@.+]] = {{.+}}constant [2 x i[[sz]]] [i[[sz]] {{8|4}}, i[[sz]] {{8|4}}]
-// CK2: [[MTYPE01:@.+]] = {{.+}}constant [2 x i64] [i64 32, i64 17]
+// CK2: [[SIZE01:@.+]] = {{.+}}constant [1 x i[[sz]]] [i[[sz]] {{8|4}}]
+// CK2: [[MTYPE01:@.+]] = {{.+}}constant [1 x i64] [i64 288]
-// CK2: [[SIZE02:@.+]] = {{.+}}constant [3 x i[[sz]]] [i[[sz]] {{8|4}}, i[[sz]] {{8|4}}, i[[sz]] {{8|4}}]
-// CK2: [[MTYPE02:@.+]] = {{.+}}constant [3 x i64] [i64 33, i64 0, i64 17]
+// CK2-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l274.region_id = weak constant i8 0
+
+// CK2: [[SIZE02:@.+]] = {{.+}}constant [1 x i[[sz]]] [i[[sz]] {{8|4}}]
+// CK2: [[MTYPE02:@.+]] = {{.+}}constant [1 x i64] [i64 288]
template <typename T>
struct ST {
@@ -216,66 +238,39 @@ struct ST {
// CK2-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK2-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
// CK2-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]**
- // CK2-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double***
+ // CK2-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[ST]]**
// CK2-DAG: store [[ST]]* [[VAR0:%.+]], [[ST]]** [[CBP0]]
- // CK2-DAG: store double** [[SEC0:%.+]], double*** [[CP0]]
- // CK2-DAG: [[SEC0]] = getelementptr {{.*}}[[ST]]* [[VAR0]], i{{.+}} 0, i{{.+}} 0
+ // CK2-DAG: store [[ST]]* [[VAR0]], [[ST]]** [[CP0]]
#pragma omp target is_device_ptr(a)
{
a++;
}
- // CK2-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[SIZE01]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE01]]{{.+}})
+ // CK2-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 1, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[SIZE01]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[MTYPE01]]{{.+}})
// CK2-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
// CK2-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
// CK2-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK2-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
// CK2-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]**
- // CK2-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double****
+ // CK2-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[ST]]**
// CK2-DAG: store [[ST]]* [[VAR0:%.+]], [[ST]]** [[CBP0]]
- // CK2-DAG: store double*** [[SEC0:%.+]], double**** [[CP0]]
- // CK2-DAG: [[SEC0]] = getelementptr {{.*}}[[ST]]* [[VAR0]], i{{.+}} 0, i{{.+}} 1
-
- // CK2-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
- // CK2-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
- // CK2-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double****
- // CK2-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double***
- // CK2-DAG: store double*** [[SEC0]], double**** [[CBP1]]
- // CK2-DAG: store double** [[SEC1:%.+]], double*** [[CP1]]
- // CK2-DAG: [[SEC1]] = load double**, double*** [[SEC0]]
+ // CK2-DAG: store [[ST]]* [[VAR0]], [[ST]]** [[CP0]]
#pragma omp target is_device_ptr(b)
{
b++;
}
- // CK2-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 3, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[3 x i{{.+}}]* [[SIZE02]], {{.+}}getelementptr {{.+}}[3 x i{{.+}}]* [[MTYPE02]]{{.+}})
+ // CK2-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 1, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[SIZE02]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[MTYPE02]]{{.+}})
// CK2-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
// CK2-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
- // CK2-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
- // CK2-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+ // CK2-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
+ // CK2-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
// CK2-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]**
- // CK2-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double****
+ // CK2-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[ST]]**
// CK2-DAG: store [[ST]]* [[VAR0:%.+]], [[ST]]** [[CBP0]]
- // CK2-DAG: store double*** [[SEC0:%.+]], double**** [[CP0]]
- // CK2-DAG: [[SEC0]] = getelementptr {{.*}}[[ST]]* [[VAR0]], i{{.+}} 0, i{{.+}} 1
-
- // CK2-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2
- // CK2-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2
- // CK2-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double****
- // CK2-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double***
- // CK2-DAG: store double*** [[SEC0]], double**** [[CBP1]]
- // CK2-DAG: store double** [[SEC1:%.+]], double*** [[CP1]]
- // CK2-DAG: [[SEC1]] = load double**, double*** [[SEC0]]
-
- // CK2-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
- // CK2-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
- // CK2-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [[ST]]**
- // CK2-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to double***
- // CK2-DAG: store [[ST]]* [[VAR2:%.+]], [[ST]]** [[CBP2]]
- // CK2-DAG: store double** [[SEC2:%.+]], double*** [[CP2]]
- // CK2-DAG: [[SEC2]] = getelementptr {{.*}}[[ST]]* [[VAR2]], i{{.+}} 0, i{{.+}} 0
+ // CK2-DAG: store [[ST]]* [[VAR0]], [[ST]]** [[CP0]]
#pragma omp target is_device_ptr(a, b)
{
a++;
diff --git a/test/OpenMP/target_is_device_ptr_messages.cpp b/test/OpenMP/target_is_device_ptr_messages.cpp
index 8cd1426081ab..6f218e20f98c 100644
--- a/test/OpenMP/target_is_device_ptr_messages.cpp
+++ b/test/OpenMP/target_is_device_ptr_messages.cpp
@@ -1,4 +1,6 @@
// RUN: %clang_cc1 -std=c++11 -verify -fopenmp -ferror-limit 200 %s
+
+// RUN: %clang_cc1 -std=c++11 -verify -fopenmp-simd -ferror-limit 200 %s
struct ST {
int *a;
};
diff --git a/test/OpenMP/target_map_codegen.cpp b/test/OpenMP/target_map_codegen.cpp
index 34b239504462..ec99e8ed396d 100644
--- a/test/OpenMP/target_map_codegen.cpp
+++ b/test/OpenMP/target_map_codegen.cpp
@@ -7,12 +7,20 @@
///
///==========================================================================///
-// RUN: %clang_cc1 -DCK1 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-64
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK1 --check-prefix CK1-64
// RUN: %clang_cc1 -DCK1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-64
-// RUN: %clang_cc1 -DCK1 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK1 --check-prefix CK1-64
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK1 --check-prefix CK1-32
// RUN: %clang_cc1 -DCK1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK1 --check-prefix CK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
#ifdef CK1
class B {
@@ -31,11 +39,13 @@ public:
};
double B::VAR = 1.0;
+// CK1-LABEL: @.__omp_offloading_{{.*}}implicit_maps_integer{{.*}}_l68.region_id = weak constant i8 0
+
// CK1-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 4]
-// Map types: OMP_MAP_PRIVATE_VAL | OMP_MAP_IS_FIRST = 288
-// CK1-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 288]
+// Map types: OMP_MAP_PRIVATE_VAL | OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 800
+// CK1-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 800]
-// CK1-LABEL: implicit_maps_integer
+// CK1-LABEL: implicit_maps_integer{{.*}}(
void implicit_maps_integer (int a){
// CK1: call void{{.*}}modify
B::modify(a);
@@ -69,23 +79,36 @@ void implicit_maps_integer (int a){
// CK1-32: {{.+}} = load i32, i32* [[ADDR]],
#endif
+
+
///==========================================================================///
-// RUN: %clang_cc1 -DCK2 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-64
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK2 --check-prefix CK2-64
// RUN: %clang_cc1 -DCK2 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-64
-// RUN: %clang_cc1 -DCK2 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK2 --check-prefix CK2-64
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK2 --check-prefix CK2-32
// RUN: %clang_cc1 -DCK2 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK2 --check-prefix CK2-32
+
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
#ifdef CK2
+// CK2-LABEL: @.__omp_offloading_{{.*}}implicit_maps_reference{{.*}}_l128.region_id = weak constant i8 0
+
// CK2: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 4]
-// Map types: OMP_MAP_PRIVATE_VAL | OMP_MAP_IS_FIRST = 288
-// CK2: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 288]
+// Map types: OMP_MAP_PRIVATE_VAL | OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 800
+// CK2: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 800]
+// CK2-LABEL: @.__omp_offloading_{{.*}}implicit_maps_reference{{.*}}_l147.region_id = weak constant i8 0
// CK2: [[SIZES2:@.+]] = {{.+}}constant [1 x i[[sz]]] zeroinitializer
-// Map types: OMP_MAP_IS_PTR = 32
-// CK2: [[TYPES2:@.+]] = {{.+}}constant [1 x i64] [i64 32]
+// Map types: OMP_MAP_IS_PTR | OMP_MAP_IMPLICIT = 544
+// CK2: [[TYPES2:@.+]] = {{.+}}constant [1 x i64] [i64 544]
-// CK2-LABEL: implicit_maps_reference
+// CK2-LABEL: implicit_maps_reference{{.*}}(
void implicit_maps_reference (int a, int *b){
int &i = a;
// CK2-DAG: call i32 @__tgt_target(i64 {{.+}}, i8* {{.+}}, i32 1, i8** [[BPGEP:%[0-9]+]], i8** [[PGEP:%[0-9]+]], {{.+}}[[SIZES]]{{.+}}, {{.+}}[[TYPES]]{{.+}})
@@ -149,19 +172,29 @@ void implicit_maps_reference (int a, int *b){
// CK2: getelementptr inbounds i32, i32* [[TT]], i32 1
#endif
///==========================================================================///
-// RUN: %clang_cc1 -DCK3 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-64
+// RUN: %clang_cc1 -DCK3 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK3 --check-prefix CK3-64
// RUN: %clang_cc1 -DCK3 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-64
-// RUN: %clang_cc1 -DCK3 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK3 --check-prefix CK3-64
+// RUN: %clang_cc1 -DCK3 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK3 --check-prefix CK3-32
// RUN: %clang_cc1 -DCK3 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK3 --check-prefix CK3-32
+
+// RUN: %clang_cc1 -DCK3 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY2 %s
+// RUN: %clang_cc1 -DCK3 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY2 %s
+// RUN: %clang_cc1 -DCK3 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY2 %s
+// RUN: %clang_cc1 -DCK3 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY2 %s
+// SIMD-ONLY2-NOT: {{__kmpc|__tgt}}
#ifdef CK3
+// CK3-LABEL: @.__omp_offloading_{{.*}}implicit_maps_parameter{{.*}}_l214.region_id = weak constant i8 0
+
// CK3-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 4]
-// Map types: OMP_MAP_PRIVATE_VAL | OMP_MAP_IS_FIRST = 288
-// CK3-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 288]
+// Map types: OMP_MAP_PRIVATE_VAL | OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 800
+// CK3-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 800]
-// CK3-LABEL: implicit_maps_parameter
+// CK3-LABEL: implicit_maps_parameter{{.*}}(
void implicit_maps_parameter (int a){
// CK3-DAG: call i32 @__tgt_target(i64 {{.+}}, i8* {{.+}}, i32 1, i8** [[BPGEP:%[0-9]+]], i8** [[PGEP:%[0-9]+]], {{.+}}[[SIZES]]{{.+}}, {{.+}}[[TYPES]]{{.+}})
@@ -193,19 +226,29 @@ void implicit_maps_parameter (int a){
#endif
///==========================================================================///
-// RUN: %clang_cc1 -DCK4 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK4 --check-prefix CK4-64
+// RUN: %clang_cc1 -DCK4 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK4 --check-prefix CK4-64
// RUN: %clang_cc1 -DCK4 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK4 --check-prefix CK4-64
-// RUN: %clang_cc1 -DCK4 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK4 --check-prefix CK4-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK4 --check-prefix CK4-64
+// RUN: %clang_cc1 -DCK4 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK4 --check-prefix CK4-32
// RUN: %clang_cc1 -DCK4 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK4 --check-prefix CK4-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK4 --check-prefix CK4-32
+
+// RUN: %clang_cc1 -DCK4 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY3 %s
+// RUN: %clang_cc1 -DCK4 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY3 %s
+// RUN: %clang_cc1 -DCK4 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY3 %s
+// RUN: %clang_cc1 -DCK4 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY3 %s
+// SIMD-ONLY3-NOT: {{__kmpc|__tgt}}
#ifdef CK4
+// CK4-LABEL: @.__omp_offloading_{{.*}}implicit_maps_nested_integer{{.*}}_l276.region_id = weak constant i8 0
+
// CK4-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 4]
-// Map types: OMP_MAP_PRIVATE_VAL | OMP_MAP_IS_FIRST = 288
-// CK4-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 288]
+// Map types: OMP_MAP_PRIVATE_VAL | OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 800
+// CK4-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 800]
-// CK4-LABEL: implicit_maps_nested_integer
+// CK4-LABEL: implicit_maps_nested_integer{{.*}}(
void implicit_maps_nested_integer (int a){
int i = a;
@@ -249,19 +292,29 @@ void implicit_maps_nested_integer (int a){
// CK4: define internal void [[KERNELP2]](i32* {{[^,]+}}, i32* {{[^,]+}}, i32* {{[^,]+}})
#endif
///==========================================================================///
-// RUN: %clang_cc1 -DCK5 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK5 --check-prefix CK5-64
+// RUN: %clang_cc1 -DCK5 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK5 --check-prefix CK5-64
// RUN: %clang_cc1 -DCK5 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK5 --check-prefix CK5-64
-// RUN: %clang_cc1 -DCK5 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK5 --check-prefix CK5-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK5 --check-prefix CK5-64
+// RUN: %clang_cc1 -DCK5 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK5 --check-prefix CK5-32
// RUN: %clang_cc1 -DCK5 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK5 --check-prefix CK5-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK5 --check-prefix CK5-32
+
+// RUN: %clang_cc1 -DCK5 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY4 %s
+// RUN: %clang_cc1 -DCK5 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY4 %s
+// RUN: %clang_cc1 -DCK5 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY4 %s
+// RUN: %clang_cc1 -DCK5 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY4 %s
+// SIMD-ONLY4-NOT: {{__kmpc|__tgt}}
#ifdef CK5
+// CK5-LABEL: @.__omp_offloading_{{.*}}implicit_maps_nested_integer_and_enum{{.*}}_l340.region_id = weak constant i8 0
+
// CK5-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 4]
-// Map types: OMP_MAP_PRIVATE_VAL | OMP_MAP_IS_FIRST = 288
-// CK5-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 288]
+// Map types: OMP_MAP_PRIVATE_VAL | OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 800
+// CK5-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 800]
-// CK5-LABEL: implicit_maps_nested_integer_and_enum
+// CK5-LABEL: implicit_maps_nested_integer_and_enum{{.*}}(
void implicit_maps_nested_integer_and_enum (int a){
enum Bla {
SomeEnum = 0x09
@@ -300,19 +353,29 @@ void implicit_maps_nested_integer_and_enum (int a){
#endif
///==========================================================================///
-// RUN: %clang_cc1 -DCK6 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK6 --check-prefix CK6-64
+// RUN: %clang_cc1 -DCK6 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK6 --check-prefix CK6-64
// RUN: %clang_cc1 -DCK6 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK6 --check-prefix CK6-64
-// RUN: %clang_cc1 -DCK6 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK6 --check-prefix CK6-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK6 --check-prefix CK6-64
+// RUN: %clang_cc1 -DCK6 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK6 --check-prefix CK6-32
// RUN: %clang_cc1 -DCK6 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK6 --check-prefix CK6-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK6 --check-prefix CK6-32
+
+// RUN: %clang_cc1 -DCK6 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY5 %s
+// RUN: %clang_cc1 -DCK6 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY5 %s
+// RUN: %clang_cc1 -DCK6 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY5 %s
+// RUN: %clang_cc1 -DCK6 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY5 %s
+// SIMD-ONLY5-NOT: {{__kmpc|__tgt}}
#ifdef CK6
+// CK6-LABEL: @.__omp_offloading_{{.*}}implicit_maps_host_global{{.*}}_l397.region_id = weak constant i8 0
+
// CK6-DAG: [[GBL:@Gi]] = global i32 0
// CK6-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 4]
-// Map types: OMP_MAP_PRIVATE_VAL | OMP_MAP_IS_FIRST = 288
-// CK6-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 288]
+// Map types: OMP_MAP_PRIVATE_VAL | OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 800
+// CK6-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 800]
-// CK6-LABEL: implicit_maps_host_global
+// CK6-LABEL: implicit_maps_host_global{{.*}}(
int Gi;
void implicit_maps_host_global (int a){
// CK6-DAG: call i32 @__tgt_target(i64 {{.+}}, i8* {{.+}}, i32 1, i8** [[BPGEP:%[0-9]+]], i8** [[PGEP:%[0-9]+]], {{.+}}[[SIZES]]{{.+}}, {{.+}}[[TYPES]]{{.+}})
@@ -346,24 +409,34 @@ void implicit_maps_host_global (int a){
#endif
///==========================================================================///
-// RUN: %clang_cc1 -DCK7 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK7 --check-prefix CK7-64
+// RUN: %clang_cc1 -DCK7 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK7 --check-prefix CK7-64
// RUN: %clang_cc1 -DCK7 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK7 --check-prefix CK7-64
-// RUN: %clang_cc1 -DCK7 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK7 --check-prefix CK7-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK7 --check-prefix CK7-64
+// RUN: %clang_cc1 -DCK7 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK7 --check-prefix CK7-32
// RUN: %clang_cc1 -DCK7 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK7 --check-prefix CK7-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK7 --check-prefix CK7-32
+
+// RUN: %clang_cc1 -DCK7 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY6 %s
+// RUN: %clang_cc1 -DCK7 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY6 %s
+// RUN: %clang_cc1 -DCK7 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY6 %s
+// RUN: %clang_cc1 -DCK7 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY6 %s
+// SIMD-ONLY6-NOT: {{__kmpc|__tgt}}
#ifdef CK7
// For a 32-bit targets, the value doesn't fit the size of the pointer,
// therefore it is passed by reference with a map 'to' specification.
+// CK7-LABEL: @.__omp_offloading_{{.*}}implicit_maps_double{{.*}}_l464.region_id = weak constant i8 0
+
// CK7-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 8]
-// Map types: OMP_MAP_PRIVATE_VAL | OMP_MAP_IS_FIRST = 288
-// CK7-64-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 288]
-// Map types: OMP_MAP_TO | OMP_MAP_PRIVATE_PTR | OMP_MAP_FIRST_REF = 161
-// CK7-32-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 161]
+// Map types: OMP_MAP_PRIVATE_VAL | OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 800
+// CK7-64-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 800]
+// Map types: OMP_MAP_TO | OMP_MAP_PRIVATE | OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 673
+// CK7-32-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 673]
-// CK7-LABEL: implicit_maps_double
+// CK7-LABEL: implicit_maps_double{{.*}}(
void implicit_maps_double (int a){
double d = (double)a;
@@ -408,19 +481,29 @@ void implicit_maps_double (int a){
#endif
///==========================================================================///
-// RUN: %clang_cc1 -DCK8 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK8
+// RUN: %clang_cc1 -DCK8 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK8
// RUN: %clang_cc1 -DCK8 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK8
-// RUN: %clang_cc1 -DCK8 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK8
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK8
+// RUN: %clang_cc1 -DCK8 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK8
// RUN: %clang_cc1 -DCK8 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK8
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK8
+
+// RUN: %clang_cc1 -DCK8 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY7 %s
+// RUN: %clang_cc1 -DCK8 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY7 %s
+// RUN: %clang_cc1 -DCK8 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY7 %s
+// RUN: %clang_cc1 -DCK8 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY7 %s
+// SIMD-ONLY7-NOT: {{__kmpc|__tgt}}
#ifdef CK8
+// CK8-LABEL: @.__omp_offloading_{{.*}}implicit_maps_float{{.*}}_l524.region_id = weak constant i8 0
+
// CK8-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 4]
-// Map types: OMP_MAP_PRIVATE_VAL | OMP_MAP_IS_FIRST = 288
-// CK8-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 288]
+// Map types: OMP_MAP_PRIVATE_VAL | OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 800
+// CK8-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 800]
-// CK8-LABEL: implicit_maps_float
+// CK8-LABEL: implicit_maps_float{{.*}}(
void implicit_maps_float (int a){
float f = (float)a;
@@ -452,19 +535,29 @@ void implicit_maps_float (int a){
#endif
///==========================================================================///
-// RUN: %clang_cc1 -DCK9 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK9
+// RUN: %clang_cc1 -DCK9 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK9
// RUN: %clang_cc1 -DCK9 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK9
-// RUN: %clang_cc1 -DCK9 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK9
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK9
+// RUN: %clang_cc1 -DCK9 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK9
// RUN: %clang_cc1 -DCK9 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK9
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK9
+
+// RUN: %clang_cc1 -DCK9 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY8 %s
+// RUN: %clang_cc1 -DCK9 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY8 %s
+// RUN: %clang_cc1 -DCK9 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY8 %s
+// RUN: %clang_cc1 -DCK9 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY8 %s
+// SIMD-ONLY8-NOT: {{__kmpc|__tgt}}
#ifdef CK9
+// CK9-LABEL: @.__omp_offloading_{{.*}}implicit_maps_array{{.*}}_l575.region_id = weak constant i8 0
+
// CK9-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 16]
-// Map types: OMP_MAP_TO + OMP_MAP_FROM + OMP_MAP_IS_FIRST + OMP_MAP_IMPLICIT = 547
+// Map types: OMP_MAP_TO + OMP_MAP_FROM + OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 547
// CK9-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 547]
-// CK9-LABEL: implicit_maps_array
+// CK9-LABEL: implicit_maps_array{{.*}}(
void implicit_maps_array (int a){
double darr[2] = {(double)a, (double)a};
@@ -493,19 +586,29 @@ void implicit_maps_array (int a){
// CK9: {{.+}} = getelementptr inbounds [2 x double], [2 x double]* [[REF]], i[[sz]] 0, i[[sz]] 0
#endif
///==========================================================================///
-// RUN: %clang_cc1 -DCK10 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK10
+// RUN: %clang_cc1 -DCK10 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK10
// RUN: %clang_cc1 -DCK10 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK10
-// RUN: %clang_cc1 -DCK10 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK10
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK10
+// RUN: %clang_cc1 -DCK10 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK10
// RUN: %clang_cc1 -DCK10 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK10
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK10
+
+// RUN: %clang_cc1 -DCK10 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY9 %s
+// RUN: %clang_cc1 -DCK10 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY9 %s
+// RUN: %clang_cc1 -DCK10 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY9 %s
+// RUN: %clang_cc1 -DCK10 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY9 %s
+// SIMD-ONLY9-NOT: {{__kmpc|__tgt}}
#ifdef CK10
+// CK10-LABEL: @.__omp_offloading_{{.*}}implicit_maps_pointer{{.*}}_l626.region_id = weak constant i8 0
+
// CK10-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] zeroinitializer
-// Map types: OMP_MAP_IS_FIRST = 32
-// CK10-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 32]
+// Map types: OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 544
+// CK10-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 544]
-// CK10-LABEL: implicit_maps_pointer
+// CK10-LABEL: implicit_maps_pointer{{.*}}(
void implicit_maps_pointer (){
double *ddyn;
@@ -535,19 +638,29 @@ void implicit_maps_pointer (){
#endif
///==========================================================================///
-// RUN: %clang_cc1 -DCK11 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK11
+// RUN: %clang_cc1 -DCK11 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK11
// RUN: %clang_cc1 -DCK11 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK11
-// RUN: %clang_cc1 -DCK11 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK11
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK11
+// RUN: %clang_cc1 -DCK11 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK11
// RUN: %clang_cc1 -DCK11 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK11
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK11
+
+// RUN: %clang_cc1 -DCK11 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY10 %s
+// RUN: %clang_cc1 -DCK11 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY10 %s
+// RUN: %clang_cc1 -DCK11 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY10 %s
+// RUN: %clang_cc1 -DCK11 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY10 %s
+// SIMD-ONLY10-NOT: {{__kmpc|__tgt}}
#ifdef CK11
+// CK11-LABEL: @.__omp_offloading_{{.*}}implicit_maps_double_complex{{.*}}_l678.region_id = weak constant i8 0
+
// CK11-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 16]
-// Map types: OMP_MAP_TO + OMP_MAP_FROM + OMP_MAP_IS_FIRST + OMP_MAP_IMPLICIT = 547
+// Map types: OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 547
// CK11-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 547]
-// CK11-LABEL: implicit_maps_double_complex
+// CK11-LABEL: implicit_maps_double_complex{{.*}}(
void implicit_maps_double_complex (int a){
double _Complex dc = (double)a;
@@ -575,24 +688,34 @@ void implicit_maps_double_complex (int a){
// CK11: {{.+}} = getelementptr inbounds { double, double }, { double, double }* [[REF]], i32 0, i32 0
#endif
///==========================================================================///
-// RUN: %clang_cc1 -DCK12 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK12 --check-prefix CK12-64
+// RUN: %clang_cc1 -DCK12 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK12 --check-prefix CK12-64
// RUN: %clang_cc1 -DCK12 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK12 --check-prefix CK12-64
-// RUN: %clang_cc1 -DCK12 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK12 --check-prefix CK12-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK12 --check-prefix CK12-64
+// RUN: %clang_cc1 -DCK12 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK12 --check-prefix CK12-32
// RUN: %clang_cc1 -DCK12 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK12 --check-prefix CK12-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK12 --check-prefix CK12-32
+
+// RUN: %clang_cc1 -DCK12 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY11 %s
+// RUN: %clang_cc1 -DCK12 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY11 %s
+// RUN: %clang_cc1 -DCK12 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY11 %s
+// RUN: %clang_cc1 -DCK12 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY11 %s
+// SIMD-ONLY11-NOT: {{__kmpc|__tgt}}
#ifdef CK12
// For a 32-bit targets, the value doesn't fit the size of the pointer,
// therefore it is passed by reference with a map 'to' specification.
+// CK12-LABEL: @.__omp_offloading_{{.*}}implicit_maps_float_complex{{.*}}_l743.region_id = weak constant i8 0
+
// CK12-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 8]
-// Map types: OMP_MAP_PRIVATE_VAL + OMP_MAP_IS_FIRST = 288
-// CK12-64-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 288]
-// Map types: OMP_MAP_TO | OMP_MAP_PRIVATE_PTR | OMP_MAP_FIRST_REF = 161
-// CK12-32-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 161]
+// Map types: OMP_MAP_PRIVATE_VAL + OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 800
+// CK12-64-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 800]
+// Map types: OMP_MAP_TO | OMP_MAP_PRIVATE | OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 673
+// CK12-32-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 673]
-// CK12-LABEL: implicit_maps_float_complex
+// CK12-LABEL: implicit_maps_float_complex{{.*}}(
void implicit_maps_float_complex (int a){
float _Complex fc = (float)a;
@@ -636,22 +759,32 @@ void implicit_maps_float_complex (int a){
// CK12-32: {{.+}} = getelementptr inbounds { float, float }, { float, float }* [[REF]], i32 0, i32 0
#endif
///==========================================================================///
-// RUN: %clang_cc1 -DCK13 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK13
+// RUN: %clang_cc1 -DCK13 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK13
// RUN: %clang_cc1 -DCK13 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK13
-// RUN: %clang_cc1 -DCK13 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK13
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK13
+// RUN: %clang_cc1 -DCK13 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK13
// RUN: %clang_cc1 -DCK13 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK13
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK13
+
+// RUN: %clang_cc1 -DCK13 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY12 %s
+// RUN: %clang_cc1 -DCK13 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY12 %s
+// RUN: %clang_cc1 -DCK13 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY12 %s
+// RUN: %clang_cc1 -DCK13 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY12 %s
+// SIMD-ONLY12-NOT: {{__kmpc|__tgt}}
#ifdef CK13
+// CK13-LABEL: @.__omp_offloading_{{.*}}implicit_maps_variable_length_array{{.*}}_l825.region_id = weak constant i8 0
+
// We don't have a constant map size for VLAs.
// Map types:
-// - OMP_MAP_PRIVATE_VAL + OMP_MAP_IS_FIRST = 288 (vla size)
-// - OMP_MAP_PRIVATE_VAL + OMP_MAP_IS_FIRST = 288 (vla size)
-// - OMP_MAP_TO + OMP_MAP_FROM + OMP_MAP_IS_FIRST + OMP_IMPICIT_MAP = 547
+// - OMP_MAP_PRIVATE_VAL + OMP_MAP_TARGET_PARAM = 288 (vla size)
+// - OMP_MAP_PRIVATE_VAL + OMP_MAP_TARGET_PARAM = 288 (vla size)
+// - OMP_MAP_TO + OMP_MAP_FROM + OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 547
// CK13-DAG: [[TYPES:@.+]] = {{.+}}constant [3 x i64] [i64 288, i64 288, i64 547]
-// CK13-LABEL: implicit_maps_variable_length_array
+// CK13-LABEL: implicit_maps_variable_length_array{{.*}}(
void implicit_maps_variable_length_array (int a){
double vla[2][a];
@@ -708,21 +841,32 @@ void implicit_maps_variable_length_array (int a){
// CK13: {{.+}} = getelementptr inbounds double, double* [[REF]], i[[sz]] %{{.+}}
#endif
///==========================================================================///
-// RUN: %clang_cc1 -DCK14 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK14 --check-prefix CK14-64
+// RUN: %clang_cc1 -DCK14 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK14 --check-prefix CK14-64
// RUN: %clang_cc1 -DCK14 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK14 --check-prefix CK14-64
-// RUN: %clang_cc1 -DCK14 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK14 --check-prefix CK14-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK14 --check-prefix CK14-64
+// RUN: %clang_cc1 -DCK14 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK14 --check-prefix CK14-32
// RUN: %clang_cc1 -DCK14 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK14 --check-prefix CK14-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK14 --check-prefix CK14-32
+
+// RUN: %clang_cc1 -DCK14 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY13 %s
+// RUN: %clang_cc1 -DCK14 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY13 %s
+// RUN: %clang_cc1 -DCK14 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY13 %s
+// RUN: %clang_cc1 -DCK14 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY13 %s
+// SIMD-ONLY13-NOT: {{__kmpc|__tgt}}
#ifdef CK14
// CK14-DAG: [[ST:%.+]] = type { i32, double }
-// CK14-DAG: [[SIZES:@.+]] = {{.+}}constant [3 x i[[sz:64|32]]] [i{{64|32}} 4, i{{64|32}} 8, i{{64|32}} 4]
+
+// CK14-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l877.region_id = weak constant i8 0
+
+
// Map types:
-// - OMP_MAP_TO + OMP_MAP_FROM + OMP_MAP_IS_FIRST + OMP_IMPLICIT_MAP = 547
-// - OMP_MAP_TO + OMP_MAP_FROM + OMP_IMPLICIT_MAP = 515
-// - OMP_MAP_PRIVATE_VAL + OMP_MAP_IS_FIRST = 288
-// CK14-DAG: [[TYPES:@.+]] = {{.+}}constant [3 x i64] [i64 547, i64 515, i64 288]
+// - OMP_MAP_TARGET_PARAM = 32
+// - OMP_MAP_TO + OMP_MAP_FROM | OMP_MAP_IMPLICIT | OMP_MAP_MEMBER_OF = 281474976711171
+// - OMP_MAP_PRIVATE_VAL + OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 800
+// CK14-DAG: [[TYPES:@.+]] = {{.+}}constant [4 x i64] [i64 32, i64 281474976711171, i64 281474976711171, i64 800]
class SSS {
public:
@@ -740,35 +884,51 @@ public:
SSS(int a, double b) : a(a), b(b) {}
};
-// CK14-LABEL: implicit_maps_class
+// CK14-LABEL: implicit_maps_class{{.*}}(
void implicit_maps_class (int a){
SSS sss(a, (double)a);
// CK14: define {{.*}}void @{{.+}}foo{{.+}}([[ST]]* {{[^,]+}}, i32 {{[^,]+}})
- // CK14-DAG: call i32 @__tgt_target(i64 {{.+}}, i8* {{.+}}, i32 3, i8** [[BPGEP:%[0-9]+]], i8** [[PGEP:%[0-9]+]], {{.+}}[[SIZES]]{{.+}}, {{.+}}[[TYPES]]{{.+}})
+ // CK14-DAG: call i32 @__tgt_target(i64 {{.+}}, i8* {{.+}}, i32 4, i8** [[BPGEP:%[0-9]+]], i8** [[PGEP:%[0-9]+]], i[[sz:64|32]]* [[SIZES:%[^,]+]], {{.+}}[[TYPES]]{{.+}})
// CK14-DAG: [[BPGEP]] = getelementptr inbounds {{.+}}[[BPS:%[^,]+]], i32 0, i32 0
// CK14-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0
+ // CK14-DAG: [[SIZES]] = getelementptr inbounds {{.+}}[[S:%[^,]+]], i32 0, i32 0
// CK14-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0
// CK14-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0
+ // CK14-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i32 0, i32 0
// CK14-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]**
// CK14-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32**
// CK14-DAG: store [[ST]]* [[DECL:%.+]], [[ST]]** [[CBP0]]
- // CK14-DAG: store i32* %{{.+}}, i32** [[CP0]]
+ // CK14-DAG: store i32* [[A:%.+]], i32** [[CP0]]
+ // CK14-DAG: store i[[sz]] %{{.+}}, i[[sz]]* [[S0]]
// CK14-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 1
// CK14-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 1
+ // CK14-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i32 0, i32 1
// CK14-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[ST]]**
- // CK14-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double**
+ // CK14-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32**
// CK14-DAG: store [[ST]]* [[DECL]], [[ST]]** [[CBP1]]
- // CK14-DAG: store double* %{{.+}}, double** [[CP1]]
-
- // CK14-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 2
- // CK14-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 2
- // CK14-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[sz]]*
- // CK14-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[sz]]*
- // CK14-DAG: store i[[sz]] [[VAL:%.+]], i[[sz]]* [[CBP1]]
- // CK14-DAG: store i[[sz]] [[VAL]], i[[sz]]* [[CP1]]
+ // CK14-DAG: store i32* [[A]], i32** [[CP1]]
+ // CK14-DAG: store i[[sz]] 4, i[[sz]]* [[S1]]
+
+ // CK14-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 2
+ // CK14-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 2
+ // CK14-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i32 0, i32 2
+ // CK14-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [[ST]]**
+ // CK14-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to double**
+ // CK14-DAG: store [[ST]]* [[DECL]], [[ST]]** [[CBP2]]
+ // CK14-DAG: store double* %{{.+}}, double** [[CP2]]
+ // CK14-DAG: store i[[sz]] 8, i[[sz]]* [[S2]]
+
+ // CK14-DAG: [[BP3:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 3
+ // CK14-DAG: [[P3:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 3
+ // CK14-DAG: [[S3:%.+]] = getelementptr inbounds {{.+}}[[S]], i32 0, i32 3
+ // CK14-DAG: [[CBP3:%.+]] = bitcast i8** [[BP3]] to i[[sz]]*
+ // CK14-DAG: [[CP3:%.+]] = bitcast i8** [[P3]] to i[[sz]]*
+ // CK14-DAG: store i[[sz]] [[VAL:%.+]], i[[sz]]* [[CBP3]]
+ // CK14-DAG: store i[[sz]] [[VAL]], i[[sz]]* [[CP3]]
+ // CK14-DAG: store i[[sz]] 4, i[[sz]]* [[S3]]
// CK14-DAG: [[VAL]] = load i[[sz]], i[[sz]]* [[ADDR:%.+]],
// CK14-64-DAG: [[CADDR:%.+]] = bitcast i[[sz]]* [[ADDR]] to i32*
// CK14-64-DAG: store i32 {{.+}}, i32* [[CADDR]],
@@ -790,40 +950,46 @@ void implicit_maps_class (int a){
#endif
///==========================================================================///
-// RUN: %clang_cc1 -DCK15 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK15 --check-prefix CK15-64
+// RUN: %clang_cc1 -DCK15 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK15 --check-prefix CK15-64
// RUN: %clang_cc1 -DCK15 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK15 --check-prefix CK15-64
-// RUN: %clang_cc1 -DCK15 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK15 --check-prefix CK15-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK15 --check-prefix CK15-64
+// RUN: %clang_cc1 -DCK15 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK15 --check-prefix CK15-32
// RUN: %clang_cc1 -DCK15 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK15 --check-prefix CK15-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK15 --check-prefix CK15-32
+
+// RUN: %clang_cc1 -DCK15 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY14 %s
+// RUN: %clang_cc1 -DCK15 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY14 %s
+// RUN: %clang_cc1 -DCK15 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY14 %s
+// RUN: %clang_cc1 -DCK15 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY14 %s
+// SIMD-ONLY14-NOT: {{__kmpc|__tgt}}
#ifdef CK15
-// CK15: [[ST:%.+]] = type { i32, double, i32* }
-// CK15: [[SIZES:@.+]] = {{.+}}constant [5 x i[[sz:64|32]]] [i{{64|32}} 4, i{{64|32}} 8, i{{64|32}} {{8|4}}, i{{64|32}} 4, i{{64|32}} 4]
+// CK15: [[ST:%.+]] = type { i32, double }
// Map types:
-// - OMP_MAP_TO + OMP_MAP_FROM + OMP_MAP_IS_FIRST + OMP_MAP_IMPLICIT = 547
-// - OMP_MAP_PRIVATE_VAL + OMP_MAP_IS_FIRST = 288
-// CK15: [[TYPES:@.+]] = {{.+}}constant [5 x i64] [i64 547, i64 515, i64 512, i64 531, i64 288]
+// - OMP_MAP_TARGET_PARAM = 32
+// - OMP_MAP_TO + OMP_MAP_FROM | OMP_MAP_IMPLICIT | OMP_MAP_MEMBER_OF = 281474976711171
+// - OMP_MAP_PRIVATE_VAL + OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 800
+// CK15: [[TYPES:@.+]] = {{.+}}constant [4 x i64] [i64 32, i64 281474976711171, i64 281474976711171, i64 800]
-// CK15: [[SIZES2:@.+]] = {{.+}}constant [5 x i[[sz]]] [i{{64|32}} 4, i{{64|32}} 8, i{{64|32}} {{8|4}}, i{{64|32}} 4, i{{64|32}} 4]
// Map types:
-// - OMP_MAP_TO + OMP_MAP_FROM + OMP_MAP_IS_FIRST = 35
-// - OMP_MAP_PRIVATE_VAL + OMP_MAP_IS_FIRST = 288
-// CK15: [[TYPES2:@.+]] = {{.+}}constant [5 x i64] [i64 547, i64 515, i64 512, i64 531, i64 288]
+// - OMP_MAP_TARGET_PARAM = 32
+// - OMP_MAP_TO + OMP_MAP_FROM | OMP_MAP_IMPLICIT | OMP_MAP_MEMBER_OF = 281474976711171
+// - OMP_MAP_PRIVATE_VAL + OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 800
+// CK15: [[TYPES2:@.+]] = {{.+}}constant [4 x i64] [i64 32, i64 281474976711171, i64 281474976711171, i64 800]
template<int x>
class SSST {
public:
int a;
double b;
- int &r;
void foo(int c) {
#pragma omp target
{
a += c + x;
b += (double)(c + x);
- r += x;
}
}
template<int y>
@@ -832,56 +998,57 @@ public:
{
a += c + x + y;
b += (double)(c + x + y);
- r += x + y;
}
}
- SSST(int a, double b, int &r) : a(a), b(b), r(r) {}
+ SSST(int a, double b) : a(a), b(b) {}
};
-// CK15-LABEL: implicit_maps_templated_class
+// CK15-LABEL: implicit_maps_templated_class{{.*}}(
void implicit_maps_templated_class (int a){
- SSST<123> ssst(a, (double)a, a);
+ SSST<123> ssst(a, (double)a);
// CK15: define {{.*}}void @{{.+}}foo{{.+}}([[ST]]* {{[^,]+}}, i32 {{[^,]+}})
- // CK15-DAG: call i32 @__tgt_target(i64 {{.+}}, i8* {{.+}}, i32 5, i8** [[BPGEP:%[0-9]+]], i8** [[PGEP:%[0-9]+]], {{.+}}[[SIZES]]{{.+}}, {{.+}}[[TYPES]]{{.+}})
+ // CK15-DAG: call i32 @__tgt_target(i64 {{.+}}, i8* {{.+}}, i32 4, i8** [[BPGEP:%[0-9]+]], i8** [[PGEP:%[0-9]+]], i[[sz:64|32]]* [[SIZES:%[^,]+]], {{.+}}[[TYPES]]{{.+}})
// CK15-DAG: [[BPGEP]] = getelementptr inbounds {{.+}}[[BPS:%[^,]+]], i32 0, i32 0
// CK15-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0
+ // CK15-DAG: [[SIZES]] = getelementptr inbounds {{.+}}[[S:%[^,]+]], i32 0, i32 0
// CK15-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0
// CK15-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0
+ // CK15-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i32 0, i32 0
// CK15-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]**
// CK15-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32**
// CK15-DAG: store [[ST]]* [[DECL:%.+]], [[ST]]** [[CBP0]]
- // CK15-DAG: store i32* %{{.+}}, i32** [[CP0]]
+ // CK15-DAG: store i32* [[A:%.+]], i32** [[CP0]]
+ // CK15-DAG: store i[[sz]] %{{.+}}, i[[sz]]* [[S0]]
// CK15-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 1
// CK15-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 1
+ // CK15-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i32 0, i32 1
// CK15-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[ST]]**
- // CK15-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double**
+ // CK15-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32**
// CK15-DAG: store [[ST]]* [[DECL]], [[ST]]** [[CBP1]]
- // CK15-DAG: store double* %{{.+}}, double** [[CP1]]
+ // CK15-DAG: store i32* [[A]], i32** [[CP1]]
+ // CK15-DAG: store i[[sz]] 4, i[[sz]]* [[S1]]
// CK15-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 2
// CK15-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 2
+ // CK15-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i32 0, i32 2
// CK15-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [[ST]]**
- // CK15-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to i32***
+ // CK15-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to double**
// CK15-DAG: store [[ST]]* [[DECL]], [[ST]]** [[CBP2]]
- // CK15-DAG: store i32** %{{.+}}, i32*** [[CP2]]
+ // CK15-DAG: store double* %{{.+}}, double** [[CP2]]
+ // CK15-DAG: store i[[sz]] 8, i[[sz]]* [[S2]]
// CK15-DAG: [[BP3:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 3
// CK15-DAG: [[P3:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 3
- // CK15-DAG: [[CBP3:%.+]] = bitcast i8** [[BP3]] to i32***
- // CK15-DAG: [[CP3:%.+]] = bitcast i8** [[P3]] to i32**
- // CK15-DAG: store i32** %{{.+}}, i32*** [[CBP3]]
- // CK15-DAG: store i32* %{{.+}}, i32** [[CP3]]
-
- // CK15-DAG: [[BP4:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 4
- // CK15-DAG: [[P4:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 4
- // CK15-DAG: [[CBP4:%.+]] = bitcast i8** [[BP4]] to i[[sz]]*
- // CK15-DAG: [[CP4:%.+]] = bitcast i8** [[P4]] to i[[sz]]*
- // CK15-DAG: store i[[sz]] [[VAL:%.+]], i[[sz]]* [[CBP4]]
- // CK15-DAG: store i[[sz]] [[VAL]], i[[sz]]* [[CP4]]
+ // CK15-DAG: [[S3:%.+]] = getelementptr inbounds {{.+}}[[S]], i32 0, i32 3
+ // CK15-DAG: [[CBP3:%.+]] = bitcast i8** [[BP3]] to i[[sz]]*
+ // CK15-DAG: [[CP3:%.+]] = bitcast i8** [[P3]] to i[[sz]]*
+ // CK15-DAG: store i[[sz]] [[VAL:%.+]], i[[sz]]* [[CBP3]]
+ // CK15-DAG: store i[[sz]] [[VAL]], i[[sz]]* [[CP3]]
+ // CK15-DAG: store i[[sz]] 4, i[[sz]]* [[S3]]
// CK15-DAG: [[VAL]] = load i[[sz]], i[[sz]]* [[ADDR:%.+]],
// CK15-64-DAG: [[CADDR:%.+]] = bitcast i[[sz]]* [[ADDR]] to i32*
// CK15-64-DAG: store i32 {{.+}}, i32* [[CADDR]],
@@ -890,44 +1057,46 @@ void implicit_maps_templated_class (int a){
ssst.foo(456);
// CK15: define {{.*}}void @{{.+}}bar{{.+}}([[ST]]* {{[^,]+}}, i32 {{[^,]+}})
- // CK15-DAG: call i32 @__tgt_target(i64 {{.+}}, i8* {{.+}}, i32 5, i8** [[BPGEP:%[0-9]+]], i8** [[PGEP:%[0-9]+]], {{.+}}[[SIZES2]]{{.+}}, {{.+}}[[TYPES2]]{{.+}})
+ // CK15-DAG: call i32 @__tgt_target(i64 {{.+}}, i8* {{.+}}, i32 4, i8** [[BPGEP:%[0-9]+]], i8** [[PGEP:%[0-9]+]], i[[sz]]* [[SIZES:[^,]+]], {{.+}}[[TYPES2]]{{.+}})
// CK15-DAG: [[BPGEP]] = getelementptr inbounds {{.+}}[[BPS:%[^,]+]], i32 0, i32 0
// CK15-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0
+ // CK15-DAG: [[SIZES]] = getelementptr inbounds {{.+}}[[S:%[^,]+]], i32 0, i32 0
// CK15-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0
// CK15-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0
+ // CK15-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i32 0, i32 0
// CK15-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]**
// CK15-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32**
- // CK15-DAG: store [[ST]]* [[DECL]], [[ST]]** [[CBP0]]
- // CK15-DAG: store i32* %{{.+}}, i32** [[CP0]]
+ // CK15-DAG: store [[ST]]* [[DECL:%.+]], [[ST]]** [[CBP0]]
+ // CK15-DAG: store i32* [[A:%.+]], i32** [[CP0]]
+ // CK15-DAG: store i[[sz]] %{{.+}}, i[[sz]]* [[S0]]
// CK15-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 1
// CK15-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 1
+ // CK15-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i32 0, i32 1
// CK15-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[ST]]**
- // CK15-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double**
+ // CK15-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32**
// CK15-DAG: store [[ST]]* [[DECL]], [[ST]]** [[CBP1]]
- // CK15-DAG: store double* %{{.+}}, double** [[CP1]]
+ // CK15-DAG: store i32* [[A]], i32** [[CP1]]
+ // CK15-DAG: store i[[sz]] 4, i[[sz]]* [[S1]]
// CK15-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 2
// CK15-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 2
+ // CK15-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i32 0, i32 2
// CK15-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [[ST]]**
- // CK15-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to i32***
+ // CK15-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to double**
// CK15-DAG: store [[ST]]* [[DECL]], [[ST]]** [[CBP2]]
- // CK15-DAG: store i32** %{{.+}}, i32*** [[CP2]]
+ // CK15-DAG: store double* %{{.+}}, double** [[CP2]]
+ // CK15-DAG: store i[[sz]] 8, i[[sz]]* [[S2]]
// CK15-DAG: [[BP3:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 3
// CK15-DAG: [[P3:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 3
- // CK15-DAG: [[CBP3:%.+]] = bitcast i8** [[BP3]] to i32***
- // CK15-DAG: [[CP3:%.+]] = bitcast i8** [[P3]] to i32**
- // CK15-DAG: store i32** %{{.+}}, i32*** [[CBP3]]
- // CK15-DAG: store i32* %{{.+}}, i32** [[CP3]]
-
- // CK15-DAG: [[BP4:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 4
- // CK15-DAG: [[P4:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 4
- // CK15-DAG: [[CBP4:%.+]] = bitcast i8** [[BP4]] to i[[sz]]*
- // CK15-DAG: [[CP4:%.+]] = bitcast i8** [[P4]] to i[[sz]]*
- // CK15-DAG: store i[[sz]] [[VAL:%.+]], i[[sz]]* [[CBP4]]
- // CK15-DAG: store i[[sz]] [[VAL]], i[[sz]]* [[CP4]]
+ // CK15-DAG: [[S3:%.+]] = getelementptr inbounds {{.+}}[[S]], i32 0, i32 3
+ // CK15-DAG: [[CBP3:%.+]] = bitcast i8** [[BP3]] to i[[sz]]*
+ // CK15-DAG: [[CP3:%.+]] = bitcast i8** [[P3]] to i[[sz]]*
+ // CK15-DAG: store i[[sz]] [[VAL:%.+]], i[[sz]]* [[CBP3]]
+ // CK15-DAG: store i[[sz]] [[VAL]], i[[sz]]* [[CP3]]
+ // CK15-DAG: store i[[sz]] 4, i[[sz]]* [[S3]]
// CK15-DAG: [[VAL]] = load i[[sz]], i[[sz]]* [[ADDR:%.+]],
// CK15-64-DAG: [[CADDR:%.+]] = bitcast i[[sz]]* [[ADDR]] to i32*
// CK15-64-DAG: store i32 {{.+}}, i32* [[CADDR]],
@@ -960,18 +1129,26 @@ void implicit_maps_templated_class (int a){
#endif
///==========================================================================///
-// RUN: %clang_cc1 -DCK16 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK16 --check-prefix CK16-64
+// RUN: %clang_cc1 -DCK16 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK16 --check-prefix CK16-64
// RUN: %clang_cc1 -DCK16 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK16 --check-prefix CK16-64
-// RUN: %clang_cc1 -DCK16 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK16 --check-prefix CK16-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK16 --check-prefix CK16-64
+// RUN: %clang_cc1 -DCK16 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK16 --check-prefix CK16-32
// RUN: %clang_cc1 -DCK16 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK16 --check-prefix CK16-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK16 --check-prefix CK16-32
+
+// RUN: %clang_cc1 -DCK16 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY15 %s
+// RUN: %clang_cc1 -DCK16 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY15 %s
+// RUN: %clang_cc1 -DCK16 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY15 %s
+// RUN: %clang_cc1 -DCK16 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY15 %s
+// SIMD-ONLY15-NOT: {{__kmpc|__tgt}}
#ifdef CK16
// CK16-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 4]
// Map types:
-// - OMP_MAP_PRIVATE_VAL + OMP_MAP_IS_FIRST = 288
-// CK16-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 288]
+// - OMP_MAP_PRIVATE_VAL + OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 800
+// CK16-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 800]
template<int y>
int foo(int d) {
@@ -982,7 +1159,7 @@ int foo(int d) {
}
return res;
}
-// CK16-LABEL: implicit_maps_templated_function
+// CK16-LABEL: implicit_maps_templated_function{{.*}}(
void implicit_maps_templated_function (int a){
int i = a;
@@ -1013,17 +1190,26 @@ void implicit_maps_templated_function (int a){
#endif
///==========================================================================///
-// RUN: %clang_cc1 -DCK17 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK17
+// RUN: %clang_cc1 -DCK17 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK17
// RUN: %clang_cc1 -DCK17 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK17
-// RUN: %clang_cc1 -DCK17 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK17
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK17
+// RUN: %clang_cc1 -DCK17 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK17
// RUN: %clang_cc1 -DCK17 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK17
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK17
+
+// RUN: %clang_cc1 -DCK17 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY16 %s
+// RUN: %clang_cc1 -DCK17 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY16 %s
+// RUN: %clang_cc1 -DCK17 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY16 %s
+// RUN: %clang_cc1 -DCK17 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY16 %s
+// SIMD-ONLY16-NOT: {{__kmpc|__tgt}}
#ifdef CK17
// CK17-DAG: [[ST:%.+]] = type { i32, double }
+// CK17-LABEL: @.__omp_offloading_{{.*}}implicit_maps_struct{{.*}}_l1236.region_id = weak constant i8 0
// CK17-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} {{16|12}}]
-// Map types: OMP_MAP_TO + OMP_MAP_FROM + OMP_MAP_IS_FIRST + OMP_MAP_IMPLICIT = 547
+// Map types: OMP_MAP_TO + OMP_MAP_FROM + OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 547
// CK17-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 547]
class SSS {
@@ -1032,7 +1218,7 @@ public:
double b;
};
-// CK17-LABEL: implicit_maps_struct
+// CK17-LABEL: implicit_maps_struct{{.*}}(
void implicit_maps_struct (int a){
SSS s = {a, (double)a};
@@ -1061,18 +1247,26 @@ void implicit_maps_struct (int a){
// CK17: {{.+}} = getelementptr inbounds [[ST]], [[ST]]* [[REF]], i32 0, i32 0
#endif
///==========================================================================///
-// RUN: %clang_cc1 -DCK18 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK18 --check-prefix CK18-64
+// RUN: %clang_cc1 -DCK18 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK18 --check-prefix CK18-64
// RUN: %clang_cc1 -DCK18 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK18 --check-prefix CK18-64
-// RUN: %clang_cc1 -DCK18 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK18 --check-prefix CK18-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK18 --check-prefix CK18-64
+// RUN: %clang_cc1 -DCK18 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK18 --check-prefix CK18-32
// RUN: %clang_cc1 -DCK18 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK18 --check-prefix CK18-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK18 --check-prefix CK18-32
+
+// RUN: %clang_cc1 -DCK18 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY17 %s
+// RUN: %clang_cc1 -DCK18 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY17 %s
+// RUN: %clang_cc1 -DCK18 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY17 %s
+// RUN: %clang_cc1 -DCK18 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY17 %s
+// SIMD-ONLY17-NOT: {{__kmpc|__tgt}}
#ifdef CK18
// CK18-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 4]
// Map types:
-// - OMP_MAP_PRIVATE_VAL + OMP_MAP_IS_FIRST = 288
-// CK18-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 288]
+// - OMP_MAP_PRIVATE_VAL + OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 800
+// CK18-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 800]
template<typename T>
int foo(T d) {
@@ -1082,7 +1276,7 @@ int foo(T d) {
}
return d;
}
-// CK18-LABEL: implicit_maps_template_type_capture
+// CK18-LABEL: implicit_maps_template_type_capture{{.*}}(
void implicit_maps_template_type_capture (int a){
int i = a;
@@ -1113,136 +1307,189 @@ void implicit_maps_template_type_capture (int a){
#endif
///==========================================================================///
-// RUN: %clang_cc1 -DCK19 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK19 --check-prefix CK19-64
+// RUN: %clang_cc1 -DCK19 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK19 --check-prefix CK19-64
// RUN: %clang_cc1 -DCK19 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK19 --check-prefix CK19-64
-// RUN: %clang_cc1 -DCK19 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK19 --check-prefix CK19-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK19 --check-prefix CK19-64
+// RUN: %clang_cc1 -DCK19 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK19 --check-prefix CK19-32
// RUN: %clang_cc1 -DCK19 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK19 --check-prefix CK19-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK19 --check-prefix CK19-32
+
+// RUN: %clang_cc1 -DCK19 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY18 %s
+// RUN: %clang_cc1 -DCK19 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY18 %s
+// RUN: %clang_cc1 -DCK19 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY18 %s
+// RUN: %clang_cc1 -DCK19 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY18 %s
+// SIMD-ONLY18-NOT: {{__kmpc|__tgt}}
#ifdef CK19
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1510.region_id = weak constant i8 0
// CK19: [[SIZE00:@.+]] = private {{.*}}constant [1 x i[[Z:64|32]]] [i[[Z:64|32]] 4]
// CK19: [[MTYPE00:@.+]] = private {{.*}}constant [1 x i64] [i64 32]
-// CK19: [[SIZE00n:@.+]] = private {{.*}}constant [1 x i[[Z:64|32]]] [i[[Z:64|32]] 4]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1531.region_id = weak constant i8 0
+// CK19: [[SIZE00n:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 4]
// CK19: [[MTYPE00n:@.+]] = private {{.*}}constant [1 x i64] [i64 32]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1553.region_id = weak constant i8 0
// CK19: [[SIZE01:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 400]
// CK19: [[MTYPE01:@.+]] = private {{.*}}constant [1 x i64] [i64 33]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1572.region_id = weak constant i8 0
// CK19: [[SIZE02:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 240]
// CK19: [[MTYPE02:@.+]] = private {{.*}}constant [1 x i64] [i64 34]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1591.region_id = weak constant i8 0
// CK19: [[SIZE03:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 240]
// CK19: [[MTYPE03:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1610.region_id = weak constant i8 0
// CK19: [[SIZE04:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 400]
// CK19: [[MTYPE04:@.+]] = private {{.*}}constant [1 x i64] [i64 32]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1629.region_id = weak constant i8 0
// CK19: [[SIZE05:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 4]
// CK19: [[MTYPE05:@.+]] = private {{.*}}constant [1 x i64] [i64 33]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1652.region_id = weak constant i8 0
// CK19: [[MTYPE06:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1675.region_id = weak constant i8 0
// CK19: [[MTYPE07:@.+]] = private {{.*}}constant [1 x i64] [i64 32]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1694.region_id = weak constant i8 0
// CK19: [[SIZE08:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 4]
// CK19: [[MTYPE08:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1715.region_id = weak constant i8 0
// CK19: [[SIZE09:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] {{8|4}}]
// CK19: [[MTYPE09:@.+]] = private {{.*}}constant [1 x i64] [i64 34]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1736.region_id = weak constant i8 0
// CK19: [[SIZE10:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 240]
// CK19: [[MTYPE10:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1757.region_id = weak constant i8 0
// CK19: [[SIZE11:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 240]
// CK19: [[MTYPE11:@.+]] = private {{.*}}constant [1 x i64] [i64 32]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1778.region_id = weak constant i8 0
// CK19: [[SIZE12:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 4]
// CK19: [[MTYPE12:@.+]] = private {{.*}}constant [1 x i64] [i64 33]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1803.region_id = weak constant i8 0
// CK19: [[MTYPE13:@.+]] = private {{.*}}constant [1 x i64] [i64 32]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1828.region_id = weak constant i8 0
// CK19: [[MTYPE14:@.+]] = private {{.*}}constant [1 x i64] [i64 33]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1849.region_id = weak constant i8 0
// CK19: [[SIZE15:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 4]
// CK19: [[MTYPE15:@.+]] = private {{.*}}constant [1 x i64] [i64 34]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1883.region_id = weak constant i8 0
// CK19: [[MTYPE16:@.+]] = private {{.*}}constant [2 x i64] [i64 288, i64 33]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1909.region_id = weak constant i8 0
// CK19: [[SIZE17:@.+]] = private {{.*}}constant [2 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] 240]
// CK19: [[MTYPE17:@.+]] = private {{.*}}constant [2 x i64] [i64 288, i64 34]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1935.region_id = weak constant i8 0
// CK19: [[SIZE18:@.+]] = private {{.*}}constant [2 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] 240]
// CK19: [[MTYPE18:@.+]] = private {{.*}}constant [2 x i64] [i64 288, i64 35]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1967.region_id = weak constant i8 0
// CK19: [[MTYPE19:@.+]] = private {{.*}}constant [2 x i64] [i64 288, i64 32]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1993.region_id = weak constant i8 0
// CK19: [[SIZE20:@.+]] = private {{.*}}constant [2 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] 4]
// CK19: [[MTYPE20:@.+]] = private {{.*}}constant [2 x i64] [i64 288, i64 33]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2025.region_id = weak constant i8 0
// CK19: [[MTYPE21:@.+]] = private {{.*}}constant [2 x i64] [i64 288, i64 35]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2051.region_id = weak constant i8 0
// CK19: [[SIZE22:@.+]] = private {{.*}}constant [2 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] 4]
// CK19: [[MTYPE22:@.+]] = private {{.*}}constant [2 x i64] [i64 288, i64 35]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2070.region_id = weak constant i8 0
// CK19: [[SIZE23:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 4]
// CK19: [[MTYPE23:@.+]] = private {{.*}}constant [1 x i64] [i64 39]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2092.region_id = weak constant i8 0
// CK19: [[SIZE24:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 480]
// CK19: [[MTYPE24:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2113.region_id = weak constant i8 0
// CK19: [[SIZE25:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 16]
// CK19: [[MTYPE25:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2134.region_id = weak constant i8 0
// CK19: [[SIZE26:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 24]
// CK19: [[MTYPE26:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2155.region_id = weak constant i8 0
// CK19: [[SIZE27:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 4]
// CK19: [[MTYPE27:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2200.region_id = weak constant i8 0
// CK19: [[SIZE28:@.+]] = private {{.*}}constant [3 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] {{8|4}}, i[[Z]] 16]
-// CK19: [[MTYPE28:@.+]] = private {{.*}}constant [3 x i64] [i64 35, i64 19, i64 19]
+// CK19: [[MTYPE28:@.+]] = private {{.*}}constant [3 x i64] [i64 35, i64 16, i64 19]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2245.region_id = weak constant i8 0
// CK19: [[SIZE29:@.+]] = private {{.*}}constant [3 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] {{8|4}}, i[[Z]] 4]
-// CK19: [[MTYPE29:@.+]] = private {{.*}}constant [3 x i64] [i64 35, i64 19, i64 19]
+// CK19: [[MTYPE29:@.+]] = private {{.*}}constant [3 x i64] [i64 35, i64 16, i64 19]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2301.region_id = weak constant i8 0
// CK19: [[MTYPE30:@.+]] = private {{.*}}constant [4 x i64] [i64 288, i64 288, i64 288, i64 35]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2345.region_id = weak constant i8 0
// CK19: [[SIZE31:@.+]] = private {{.*}}constant [4 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] {{8|4}}, i[[Z]] {{8|4}}, i[[Z]] 40]
// CK19: [[MTYPE31:@.+]] = private {{.*}}constant [4 x i64] [i64 288, i64 288, i64 288, i64 35]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2368.region_id = weak constant i8 0
// CK19: [[SIZE32:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 13728]
// CK19: [[MTYPE32:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2387.region_id = weak constant i8 0
// CK19: [[SIZE33:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 13728]
// CK19: [[MTYPE33:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2406.region_id = weak constant i8 0
// CK19: [[SIZE34:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 13728]
// CK19: [[MTYPE34:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2431.region_id = weak constant i8 0
// CK19: [[MTYPE35:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2452.region_id = weak constant i8 0
// CK19: [[SIZE36:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 208]
// CK19: [[MTYPE36:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2492.region_id = weak constant i8 0
// CK19: [[MTYPE37:@.+]] = private {{.*}}constant [3 x i64] [i64 288, i64 288, i64 35]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2534.region_id = weak constant i8 0
// CK19: [[MTYPE38:@.+]] = private {{.*}}constant [3 x i64] [i64 288, i64 288, i64 35]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2576.region_id = weak constant i8 0
// CK19: [[MTYPE39:@.+]] = private {{.*}}constant [3 x i64] [i64 288, i64 288, i64 35]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2618.region_id = weak constant i8 0
// CK19: [[MTYPE40:@.+]] = private {{.*}}constant [3 x i64] [i64 288, i64 288, i64 35]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2653.region_id = weak constant i8 0
// CK19: [[SIZE41:@.+]] = private {{.*}}constant [3 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] {{8|4}}, i[[Z]] 208]
// CK19: [[MTYPE41:@.+]] = private {{.*}}constant [3 x i64] [i64 288, i64 288, i64 35]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2698.region_id = weak constant i8 0
// CK19: [[SIZE42:@.+]] = private {{.*}}constant [3 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] {{8|4}}, i[[Z]] 104]
-// CK19: [[MTYPE42:@.+]] = private {{.*}}constant [3 x i64] [i64 35, i64 19, i64 19]
+// CK19: [[MTYPE42:@.+]] = private {{.*}}constant [3 x i64] [i64 35, i64 16, i64 19]
+// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2723.region_id = weak constant i8 0
// CK19: [[MTYPE43:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
-// CK19-LABEL: explicit_maps_single
+// CK19-LABEL: explicit_maps_single{{.*}}(
void explicit_maps_single (int ii){
// Map of a scalar.
int a = ii;
@@ -2481,7 +2728,6 @@ void explicit_maps_single (int ii){
}
// CK19: define {{.+}}[[CALL00]]
-// CK19: define {{.+}}[[CALL00n]]
// CK19: define {{.+}}[[CALL01]]
// CK19: define {{.+}}[[CALL02]]
// CK19: define {{.+}}[[CALL03]]
@@ -2528,27 +2774,39 @@ void explicit_maps_single (int ii){
#endif
///==========================================================================///
-// RUN: %clang_cc1 -DCK20 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK20 --check-prefix CK20-64
+// RUN: %clang_cc1 -DCK20 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK20 --check-prefix CK20-64
// RUN: %clang_cc1 -DCK20 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK20 --check-prefix CK20-64
-// RUN: %clang_cc1 -DCK20 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK20 --check-prefix CK20-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK20 --check-prefix CK20-64
+// RUN: %clang_cc1 -DCK20 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK20 --check-prefix CK20-32
// RUN: %clang_cc1 -DCK20 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK20 --check-prefix CK20-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK20 --check-prefix CK20-32
+
+// RUN: %clang_cc1 -DCK20 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY19 %s
+// RUN: %clang_cc1 -DCK20 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY19 %s
+// RUN: %clang_cc1 -DCK20 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY19 %s
+// RUN: %clang_cc1 -DCK20 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY19 %s
+// SIMD-ONLY19-NOT: {{__kmpc|__tgt}}
#ifdef CK20
+// CK20-LABEL: @.__omp_offloading_{{.*}}explicit_maps_references_and_function_args{{.*}}_l2832.region_id = weak constant i8 0
// CK20: [[SIZE00:@.+]] = private {{.*}}constant [1 x i[[Z:64|32]]] [i[[Z:64|32]] 4]
// CK20: [[MTYPE00:@.+]] = private {{.*}}constant [1 x i64] [i64 33]
+// CK20-LABEL: @.__omp_offloading_{{.*}}explicit_maps_references_and_function_args{{.*}}_l2853.region_id = weak constant i8 0
// CK20: [[SIZE01:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 20]
// CK20: [[MTYPE01:@.+]] = private {{.*}}constant [1 x i64] [i64 33]
+// CK20-LABEL: @.__omp_offloading_{{.*}}explicit_maps_references_and_function_args{{.*}}_l2871.region_id = weak constant i8 0
// CK20: [[SIZE02:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 4]
// CK20: [[MTYPE02:@.+]] = private {{.*}}constant [1 x i64] [i64 34]
+// CK20-LABEL: @.__omp_offloading_{{.*}}explicit_maps_references_and_function_args{{.*}}_l2892.region_id = weak constant i8 0
// CK20: [[SIZE03:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 12]
// CK20: [[MTYPE03:@.+]] = private {{.*}}constant [1 x i64] [i64 34]
-// CK20-LABEL: explicit_maps_references_and_function_args
+// CK20-LABEL: explicit_maps_references_and_function_args{{.*}}(
void explicit_maps_references_and_function_args (int a, float b, int (&c)[10], float *d){
int &aa = a;
@@ -2644,34 +2902,45 @@ void explicit_maps_references_and_function_args (int a, float b, int (&c)[10], f
#endif
///==========================================================================///
-// RUN: %clang_cc1 -DCK21 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK21 --check-prefix CK21-64
+// RUN: %clang_cc1 -DCK21 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK21 --check-prefix CK21-64
// RUN: %clang_cc1 -DCK21 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK21 --check-prefix CK21-64
-// RUN: %clang_cc1 -DCK21 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK21 --check-prefix CK21-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK21 --check-prefix CK21-64
+// RUN: %clang_cc1 -DCK21 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK21 --check-prefix CK21-32
// RUN: %clang_cc1 -DCK21 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK21 --check-prefix CK21-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK21 --check-prefix CK21-32
+
+// RUN: %clang_cc1 -DCK21 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY20 %s
+// RUN: %clang_cc1 -DCK21 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY20 %s
+// RUN: %clang_cc1 -DCK21 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY20 %s
+// RUN: %clang_cc1 -DCK21 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY20 %s
+// SIMD-ONLY20-NOT: {{__kmpc|__tgt}}
#ifdef CK21
// CK21: [[ST:%.+]] = type { i32, i32, float* }
-// CK21: [[SIZE00:@.+]] = private {{.*}}constant [1 x i[[Z:64|32]]] [i[[Z:64|32]] 4]
-// CK21: [[MTYPE00:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK21-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
+// CK21: [[MTYPE00:@.+]] = private {{.*}}constant [2 x i64] [i64 32, i64 281474976710659]
-// CK21: [[SIZE01:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 492]
+// CK21-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
+// CK21: [[SIZE01:@.+]] = private {{.*}}constant [1 x i[[Z:64|32]]] [i[[Z:64|32]] 492]
// CK21: [[MTYPE01:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
-// CK21: [[SIZE02:@.+]] = private {{.*}}constant [2 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] 500]
-// CK21: [[MTYPE02:@.+]] = private {{.*}}constant [2 x i64] [i64 34, i64 18]
+// CK21-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
+// CK21: [[MTYPE02:@.+]] = private {{.*}}constant [2 x i64] [i64 32, i64 281474976710674]
+// CK21-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK21: [[SIZE03:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 492]
// CK21: [[MTYPE03:@.+]] = private {{.*}}constant [1 x i64] [i64 34]
+// CK21-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK21: [[SIZE04:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 4]
// CK21: [[MTYPE04:@.+]] = private {{.*}}constant [1 x i64] [i64 34]
-// CK21: [[SIZE05:@.+]] = private {{.*}}constant [2 x i[[Z]]] [i[[Z]] 4, i[[Z]] 4]
-// CK21: [[MTYPE05:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 3]
+// CK21-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
+// CK21: [[MTYPE05:@.+]] = private {{.*}}constant [3 x i64] [i64 32, i64 281474976710659, i64 281474976710659]
-// CK21-LABEL: explicit_maps_template_args_and_members
+// CK21-LABEL: explicit_maps_template_args_and_members{{.*}}(
template <int X, typename T>
struct CC {
@@ -2684,18 +2953,31 @@ struct CC {
T *lb;
// Region 00
- // CK21-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 1, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[SIZE00]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[MTYPE00]]{{.+}})
+ // CK21-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[Z]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE00]]{{.+}})
// CK21-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
// CK21-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
+ // CK21-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
// CK21-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK21-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
+ // CK21-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
// CK21-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]**
// CK21-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32**
// CK21-DAG: store [[ST]]* [[VAR0:%.+]], [[ST]]** [[CBP0]]
// CK21-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]]
+ // CK21-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[S0]]
// CK21-DAG: [[SEC0]] = getelementptr {{.*}}[[ST]]* [[VAR0:%.+]], i{{.+}} 0, i{{.+}} 0
+ // CK21-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
+ // CK21-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+ // CK21-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1
+ // CK21-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[ST]]**
+ // CK21-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32**
+ // CK21-DAG: store [[ST]]* [[VAR1:%.+]], [[ST]]** [[CBP1]]
+ // CK21-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]]
+ // CK21-DAG: store i[[Z]] {{.+}}, i[[Z]]* [[S1]]
+ // CK21-DAG: [[SEC1]] = getelementptr {{.*}}[[ST]]* [[VAR1:%.+]], i{{.+}} 0, i{{.+}} 0
+
// CK21: call void [[CALL00:@.+]]([[ST]]* {{[^,]+}})
#pragma omp target map(A)
{
@@ -2724,24 +3006,29 @@ struct CC {
}
// Region 02
- // CK21-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[SIZE02]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE02]]{{.+}})
+ // CK21-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[Z]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE02]]{{.+}})
// CK21-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
// CK21-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
+ // CK21-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
// CK21-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK21-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
+ // CK21-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
// CK21-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]**
// CK21-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to float***
// CK21-DAG: store [[ST]]* [[VAR0:%.+]], [[ST]]** [[CBP0]]
// CK21-DAG: store float** [[SEC0:%.+]], float*** [[CP0]]
+ // CK21-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[S0]]
// CK21-DAG: [[SEC0]] = getelementptr {{.*}}[[ST]]* [[VAR0]], i{{.+}} 0, i{{.+}} 2
// CK21-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
// CK21-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+ // CK21-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1
// CK21-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to float***
// CK21-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to float**
// CK21-DAG: store float** [[SEC0]], float*** [[CBP1]]
// CK21-DAG: store float* [[SEC1:%.+]], float** [[CP1]]
+ // CK21-DAG: store i[[Z]] {{.+}}, i[[Z]]* [[S1]]
// CK21-DAG: [[SEC1]] = getelementptr {{.*}}float* [[RVAR1:%[^,]+]], i{{.+}} 123
// CK21-DAG: [[RVAR1]] = load float*, float** [[SEC1_:%[^,]+]]
// CK21-DAG: [[SEC1_]] = getelementptr {{.*}}[[ST]]* [[VAR0]], i{{.+}} 0, i{{.+}} 2
@@ -2790,25 +3077,39 @@ struct CC {
// Make sure the extra flag is passed to the second map.
// Region 05
- // CK21-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[SIZE05]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE05]]{{.+}})
+ // CK21-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 3, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[Z]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[3 x i{{.+}}]* [[MTYPE05]]{{.+}})
// CK21-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
// CK21-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
+ // CK21-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
// CK21-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK21-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
+ // CK21-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
// CK21-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]**
// CK21-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32**
// CK21-DAG: store [[ST]]* [[VAR0:%.+]], [[ST]]** [[CBP0]]
// CK21-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]]
+ // CK21-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[S0]]
// CK21-DAG: [[SEC0]] = getelementptr {{.*}}[[ST]]* [[VAR0]], i{{.+}} 0, i{{.+}} 0
// CK21-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
// CK21-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+ // CK21-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1
// CK21-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[ST]]**
// CK21-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32**
- // CK21-DAG: store [[ST]]* [[VAR1:%.+]], [[ST]]** [[CBP1]]
- // CK21-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]]
- // CK21-DAG: [[SEC1]] = getelementptr {{.*}}[[ST]]* [[VAR0]], i{{.+}} 0, i{{.+}} 1
+ // CK21-DAG: store [[ST]]* [[VAR0]], [[ST]]** [[CBP1]]
+ // CK21-DAG: store i32* [[SEC0]], i32** [[CP1]]
+ // CK21-DAG: store i[[Z]] {{.+}}, i[[Z]]* [[S1]]
+
+ // CK21-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2
+ // CK21-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2
+ // CK21-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 2
+ // CK21-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [[ST]]**
+ // CK21-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to i32**
+ // CK21-DAG: store [[ST]]* [[VAR2:%.+]], [[ST]]** [[CBP2]]
+ // CK21-DAG: store i32* [[SEC2:%.+]], i32** [[CP2]]
+ // CK21-DAG: store i[[Z]] {{.+}}, i[[Z]]* [[S2]]
+ // CK21-DAG: [[SEC2]] = getelementptr {{.*}}[[ST]]* [[VAR2]], i{{.+}} 0, i{{.+}} 1
// CK21: call void [[CALL05:@.+]]([[ST]]* {{[^,]+}})
#pragma omp target map(A, A2)
@@ -2833,59 +3134,82 @@ int explicit_maps_template_args_and_members(int a){
// CK21: define {{.+}}[[CALL05]]
#endif
///==========================================================================///
-// RUN: %clang_cc1 -DCK22 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK22 --check-prefix CK22-64
+// RUN: %clang_cc1 -DCK22 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK22 --check-prefix CK22-64
// RUN: %clang_cc1 -DCK22 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK22 --check-prefix CK22-64
-// RUN: %clang_cc1 -DCK22 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK22 --check-prefix CK22-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK22 --check-prefix CK22-64
+// RUN: %clang_cc1 -DCK22 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK22 --check-prefix CK22-32
// RUN: %clang_cc1 -DCK22 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK22 --check-prefix CK22-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK22 --check-prefix CK22-32
+
+// RUN: %clang_cc1 -DCK22 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY21 %s
+// RUN: %clang_cc1 -DCK22 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY21 %s
+// RUN: %clang_cc1 -DCK22 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY21 %s
+// RUN: %clang_cc1 -DCK22 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY21 %s
+// SIMD-ONLY21-NOT: {{__kmpc|__tgt}}
#ifdef CK22
// CK22-DAG: [[ST:%.+]] = type { float }
// CK22-DAG: [[STT:%.+]] = type { i32 }
+// CK22-LABEL: @.__omp_offloading_{{.*}}explicit_maps_globals{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK22: [[SIZE00:@.+]] = private {{.*}}constant [1 x i[[Z:64|32]]] [i[[Z:64|32]] 4]
// CK22: [[MTYPE00:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK22-LABEL: @.__omp_offloading_{{.*}}explicit_maps_globals{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK22: [[SIZE01:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 400]
// CK22: [[MTYPE01:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK22-LABEL: @.__omp_offloading_{{.*}}explicit_maps_globals{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK22: [[SIZE02:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] {{8|4}}]
// CK22: [[MTYPE02:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK22-LABEL: @.__omp_offloading_{{.*}}explicit_maps_globals{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK22: [[SIZE03:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 16]
// CK22: [[MTYPE03:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK22-LABEL: @.__omp_offloading_{{.*}}explicit_maps_globals{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK22: [[SIZE04:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 20]
// CK22: [[MTYPE04:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK22-LABEL: @.__omp_offloading_{{.*}}explicit_maps_globals{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK22: [[SIZE05:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 4]
// CK22: [[MTYPE05:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK22-LABEL: @.__omp_offloading_{{.*}}explicit_maps_globals{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK22: [[SIZE06:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 400]
// CK22: [[MTYPE06:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK22-LABEL: @.__omp_offloading_{{.*}}explicit_maps_globals{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK22: [[SIZE07:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] {{8|4}}]
// CK22: [[MTYPE07:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK22-LABEL: @.__omp_offloading_{{.*}}explicit_maps_globals{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK22: [[SIZE08:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 16]
// CK22: [[MTYPE08:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK22-LABEL: @.__omp_offloading_{{.*}}explicit_maps_globals{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK22: [[SIZE09:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 20]
// CK22: [[MTYPE09:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK22-LABEL: @.__omp_offloading_{{.*}}explicit_maps_globals{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK22: [[SIZE10:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 4]
// CK22: [[MTYPE10:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK22-LABEL: @.__omp_offloading_{{.*}}explicit_maps_globals{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK22: [[SIZE11:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 400]
// CK22: [[MTYPE11:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK22-LABEL: @.__omp_offloading_{{.*}}explicit_maps_globals{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK22: [[SIZE12:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] {{8|4}}]
// CK22: [[MTYPE12:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK22-LABEL: @.__omp_offloading_{{.*}}explicit_maps_globals{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK22: [[SIZE13:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 16]
// CK22: [[MTYPE13:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK22-LABEL: @.__omp_offloading_{{.*}}explicit_maps_globals{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK22: [[SIZE14:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 20]
// CK22: [[MTYPE14:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
@@ -2910,7 +3234,7 @@ STT<int> sta ;
STT<int> stc[100];
STT<int> *std;
-// CK22-LABEL: explicit_maps_globals
+// CK22-LABEL: explicit_maps_globals{{.*}}(
int explicit_maps_globals(void){
// Region 00
// CK22-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 1, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[SIZE00]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[MTYPE00]]{{.+}})
@@ -3180,33 +3504,47 @@ int explicit_maps_globals(void){
// CK22: define {{.+}}[[CALL14]]
#endif
///==========================================================================///
-// RUN: %clang_cc1 -std=c++11 -DCK23 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK23 --check-prefix CK23-64
+// RUN: %clang_cc1 -std=c++11 -DCK23 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK23 --check-prefix CK23-64
// RUN: %clang_cc1 -std=c++11 -DCK23 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -std=c++11 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK23 --check-prefix CK23-64
-// RUN: %clang_cc1 -std=c++11 -DCK23 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK23 --check-prefix CK23-32
+// RUN: %clang_cc1 -std=c++11 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK23 --check-prefix CK23-64
+// RUN: %clang_cc1 -std=c++11 -DCK23 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK23 --check-prefix CK23-32
// RUN: %clang_cc1 -std=c++11 -DCK23 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -std=c++11 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK23 --check-prefix CK23-32
+// RUN: %clang_cc1 -std=c++11 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK23 --check-prefix CK23-32
+
+// RUN: %clang_cc1 -std=c++11 -DCK23 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY22 %s
+// RUN: %clang_cc1 -std=c++11 -DCK23 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -std=c++11 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY22 %s
+// RUN: %clang_cc1 -std=c++11 -DCK23 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY22 %s
+// RUN: %clang_cc1 -std=c++11 -DCK23 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -std=c++11 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY22 %s
+// SIMD-ONLY22-NOT: {{__kmpc|__tgt}}
#ifdef CK23
+// CK23-LABEL: @.__omp_offloading_{{.*}}explicit_maps_inside_captured{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK23: [[SIZE00:@.+]] = private {{.*}}constant [1 x i[[Z:64|32]]] [i[[Z:64|32]] 4]
// CK23: [[MTYPE00:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK23-LABEL: @.__omp_offloading_{{.*}}explicit_maps_inside_captured{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK23: [[SIZE01:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 4]
// CK23: [[MTYPE01:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK23-LABEL: @.__omp_offloading_{{.*}}explicit_maps_inside_captured{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK23: [[SIZE02:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 400]
// CK23: [[MTYPE02:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK23-LABEL: @.__omp_offloading_{{.*}}explicit_maps_inside_captured{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK23: [[SIZE03:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] {{8|4}}]
// CK23: [[MTYPE03:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK23-LABEL: @.__omp_offloading_{{.*}}explicit_maps_inside_captured{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK23: [[SIZE04:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 16]
// CK23: [[MTYPE04:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK23-LABEL: @.__omp_offloading_{{.*}}explicit_maps_inside_captured{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK23: [[SIZE05:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 16]
// CK23: [[MTYPE05:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
-// CK23-LABEL: explicit_maps_inside_captured
+// CK23-LABEL: explicit_maps_inside_captured{{.*}}(
int explicit_maps_inside_captured(int a){
float b;
float c[100];
@@ -3347,12 +3685,20 @@ int explicit_maps_inside_captured(int a){
// CK23: define {{.+}}[[CALL05]]
#endif
///==========================================================================///
-// RUN: %clang_cc1 -DCK24 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK24 --check-prefix CK24-64
+// RUN: %clang_cc1 -DCK24 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK24 --check-prefix CK24-64
// RUN: %clang_cc1 -DCK24 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK24 --check-prefix CK24-64
-// RUN: %clang_cc1 -DCK24 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK24 --check-prefix CK24-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK24 --check-prefix CK24-64
+// RUN: %clang_cc1 -DCK24 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK24 --check-prefix CK24-32
// RUN: %clang_cc1 -DCK24 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK24 --check-prefix CK24-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK24 --check-prefix CK24-32
+
+// RUN: %clang_cc1 -DCK24 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY23 %s
+// RUN: %clang_cc1 -DCK24 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY23 %s
+// RUN: %clang_cc1 -DCK24 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY23 %s
+// RUN: %clang_cc1 -DCK24 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY23 %s
+// SIMD-ONLY23-NOT: {{__kmpc|__tgt}}
#ifdef CK24
// CK24-DAG: [[SC:%.+]] = type { i32, [[SB:%.+]], [[SB:%.+]]*, [10 x i32] }
@@ -3378,44 +3724,44 @@ struct SC{
int b[10];
};
-// CK24: [[SIZE01:@.+]] = private {{.*}}constant [1 x i[[Z:64|32]]] [i[[Z:64|32]] 4]
-// CK24: [[MTYPE01:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
+// CK24: [[MTYPE01:@.+]] = private {{.*}}constant [2 x i64] [i64 32, i64 281474976710659]
-// CK24: [[SIZE13:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 4]
-// CK24: [[MTYPE13:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
+// CK24: [[MTYPE13:@.+]] = private {{.*}}constant [2 x i64] [i64 32, i64 281474976710659]
-// CK24: [[SIZE14:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] {{56|48}}]
-// CK24: [[MTYPE14:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
+// CK24: [[MTYPE14:@.+]] = private {{.*}}constant [2 x i64] [i64 32, i64 281474976710659]
-// CK24: [[SIZE15:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 4]
-// CK24: [[MTYPE15:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
+// CK24: [[MTYPE15:@.+]] = private {{.*}}constant [2 x i64] [i64 32, i64 281474976710659]
-// CK24: [[SIZE16:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 20]
-// CK24: [[MTYPE16:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
+// CK24: [[MTYPE16:@.+]] = private {{.*}}constant [2 x i64] [i64 32, i64 281474976710659]
-// CK24: [[SIZE17:@.+]] = private {{.*}}constant [2 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] {{3560|2880}}]
-// CK24: [[MTYPE17:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 19]
+// CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
+// CK24: [[MTYPE17:@.+]] = private {{.*}}constant [2 x i64] [i64 32, i64 281474976710675]
-// CK24: [[SIZE18:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 4]
-// CK24: [[MTYPE18:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
+// CK24: [[MTYPE18:@.+]] = private {{.*}}constant [2 x i64] [i64 32, i64 281474976710659]
-// CK24: [[SIZE19:@.+]] = private {{.*}}constant [2 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] 4]
-// CK24: [[MTYPE19:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 19]
+// CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
+// CK24: [[MTYPE19:@.+]] = private {{.*}}constant [3 x i64] [i64 32, i64 281474976710659, i64 281474976710675]
-// CK24: [[SIZE20:@.+]] = private {{.*}}constant [2 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] 4]
-// CK24: [[MTYPE20:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 19]
+// CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
+// CK24: [[MTYPE20:@.+]] = private {{.*}}constant [2 x i64] [i64 32, i64 281474976710675]
-// CK24: [[SIZE21:@.+]] = private {{.*}}constant [2 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] 4]
-// CK24: [[MTYPE21:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 19]
+// CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
+// CK24: [[MTYPE21:@.+]] = private {{.*}}constant [3 x i64] [i64 32, i64 281474976710659, i64 281474976710675]
-// CK24: [[SIZE22:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] {{8|4}}]
-// CK24: [[MTYPE22:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
+// CK24: [[MTYPE22:@.+]] = private {{.*}}constant [2 x i64] [i64 32, i64 281474976710659]
-// CK24: [[SIZE23:@.+]] = private {{.*}}constant [2 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] {{8|4}}]
-// CK24: [[MTYPE23:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 19]
+// CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
+// CK24: [[MTYPE23:@.+]] = private {{.*}}constant [3 x i64] [i64 32, i64 281474976710659, i64 281474976710675]
-// CK24: [[SIZE24:@.+]] = private {{.*}}constant [4 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] {{8|4}}, i[[Z]] {{8|4}}, i[[Z]] 4]
-// CK24: [[MTYPE24:@.+]] = private {{.*}}constant [4 x i64] [i64 35, i64 19, i64 19, i64 19]
+// CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
+// CK24: [[MTYPE24:@.+]] = private {{.*}}constant [4 x i64] [i64 32, i64 281474976710672, i64 16, i64 19]
// CK24-LABEL: explicit_maps_struct_fields
int explicit_maps_struct_fields(int a){
@@ -3423,81 +3769,129 @@ int explicit_maps_struct_fields(int a){
SC *p;
// Region 01
-// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 1, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[SIZE01]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[MTYPE01]]{{.+}})
+// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE01]]{{.+}})
// CK24-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
// CK24-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
+// CK24-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
// CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
+// CK24-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]**
// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32**
// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]]
// CK24-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]]
+// CK24-DAG: store i[[sz]] {{%.+}}, i[[sz]]* [[S0]]
// CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SC]]* [[VAR0]], i{{.+}} 0, i{{.+}} 0
+// CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SC]]**
+// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32**
+// CK24-DAG: store [[SC]]* [[VAR0]], [[SC]]** [[CBP1]]
+// CK24-DAG: store i32* [[SEC0]], i32** [[CP1]]
+// CK24-DAG: store i[[sz]] {{.+}}, i[[sz]]* [[S1]]
+
// CK24: call void [[CALL01:@.+]]([[SC]]* {{[^,]+}})
#pragma omp target map(s.a)
{ s.a++; }
-
+
//
// Same thing but starting from a pointer.
//
// Region 13
-// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 1, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[SIZE13]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[MTYPE13]]{{.+}})
+// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE13]]{{.+}})
// CK24-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
// CK24-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
+// CK24-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
// CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
+// CK24-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]**
// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32**
// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]]
// CK24-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]]
+// CK24-DAG: store i[[sz]] {{%.+}}, i[[sz]]* [[S0]]
// CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 0
+// CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SC]]**
+// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32**
+// CK24-DAG: store [[SC]]* [[VAR0]], [[SC]]** [[CBP1]]
+// CK24-DAG: store i32* [[SEC0]], i32** [[CP1]]
+// CK24-DAG: store i[[sz]] {{.+}}, i[[sz]]* [[S1]]
+
// CK24-DAG: [[VAR0]] = load [[SC]]*, [[SC]]** %{{.+}}
// CK24-DAG: [[VAR00]] = load [[SC]]*, [[SC]]** %{{.+}}
// CK24: call void [[CALL13:@.+]]([[SC]]* {{[^,]+}})
#pragma omp target map(p->a)
{ p->a++; }
-
+
// Region 14
-// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 1, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[SIZE14]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[MTYPE14]]{{.+}})
+// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE14]]{{.+}})
// CK24-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
// CK24-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
+// CK24-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
// CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
+// CK24-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]**
// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SA]]**
// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]]
// CK24-DAG: store [[SA]]* [[SEC0:%.+]], [[SA]]** [[CP0]]
+// CK24-DAG: store i[[sz]] {{%.+}}, i[[sz]]* [[S0]]
// CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SB]]* [[SEC00:%[^,]+]], i{{.+}} 0, i{{.+}} 1
// CK24-DAG: [[SEC00]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SC]]**
+// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to [[SA]]**
+// CK24-DAG: store [[SC]]* [[VAR0]], [[SC]]** [[CBP1]]
+// CK24-DAG: store [[SA]]* [[SEC0]], [[SA]]** [[CP1]]
+// CK24-DAG: store i[[sz]] {{.+}}, i[[sz]]* [[S1]]
+
// CK24-DAG: [[VAR0]] = load [[SC]]*, [[SC]]** %{{.+}}
// CK24-DAG: [[VAR00]] = load [[SC]]*, [[SC]]** %{{.+}}
// CK24: call void [[CALL14:@.+]]([[SC]]* {{[^,]+}})
#pragma omp target map(p->s.s)
{ p->a++; }
-
+
// Region 15
-// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 1, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[SIZE15]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[MTYPE15]]{{.+}})
+// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE15]]{{.+}})
// CK24-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
// CK24-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
+// CK24-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
// CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
+// CK24-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]**
// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32**
// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]]
// CK24-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]]
+// CK24-DAG: store i[[sz]] {{%.+}}, i[[sz]]* [[S0]]
// CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SA]]* [[SEC00:%[^,]+]], i{{.+}} 0, i{{.+}} 0
// CK24-DAG: [[SEC00]] = getelementptr {{.*}}[[SB]]* [[SEC000:%[^,]+]], i{{.+}} 0, i{{.+}} 1
// CK24-DAG: [[SEC000]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SC]]**
+// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32**
+// CK24-DAG: store [[SC]]* [[VAR0]], [[SC]]** [[CBP1]]
+// CK24-DAG: store i32* [[SEC0]], i32** [[CP1]]
+// CK24-DAG: store i[[sz]] {{.+}}, i[[sz]]* [[S1]]
+
// CK24-DAG: [[VAR0]] = load [[SC]]*, [[SC]]** %{{.+}}
// CK24-DAG: [[VAR00]] = load [[SC]]*, [[SC]]** %{{.+}}
@@ -3506,19 +3900,31 @@ int explicit_maps_struct_fields(int a){
{ p->a++; }
// Region 16
-// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 1, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[SIZE16]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[MTYPE16]]{{.+}})
+// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE16]]{{.+}})
// CK24-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
// CK24-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
+// CK24-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
// CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
+// CK24-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]**
// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32**
// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]]
// CK24-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]]
+// CK24-DAG: store i[[sz]] {{%.+}}, i[[sz]]* [[S0]]
// CK24-DAG: [[SEC0]] = getelementptr {{.*}}[10 x i32]* [[SEC00:%[^,]+]], i{{.+}} 0, i{{.+}} 0
// CK24-DAG: [[SEC00]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 3
+// CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SC]]**
+// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32**
+// CK24-DAG: store [[SC]]* [[VAR0]], [[SC]]** [[CBP1]]
+// CK24-DAG: store i32* [[SEC0]], i32** [[CP1]]
+// CK24-DAG: store i[[sz]] {{.+}}, i[[sz]]* [[S1]]
+
// CK24-DAG: [[VAR0]] = load [[SC]]*, [[SC]]** %{{.+}}
// CK24-DAG: [[VAR00]] = load [[SC]]*, [[SC]]** %{{.+}}
@@ -3527,24 +3933,29 @@ int explicit_maps_struct_fields(int a){
{ p->a++; }
// Region 17
-// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[SIZE17]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE17]]{{.+}})
+// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE17]]{{.+}})
// CK24-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
// CK24-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
+// CK24-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
// CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
+// CK24-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]**
// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SB]]***
// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]]
// CK24-DAG: store [[SB]]** [[SEC0:%.+]], [[SB]]*** [[CP0]]
+// CK24-DAG: store i[[sz]] {{%.+}}, i[[sz]]* [[S0]]
// CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 2
// CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
// CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1
// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SB]]***
// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to [[SB]]**
// CK24-DAG: store [[SB]]** [[SEC0]], [[SB]]*** [[CBP1]]
// CK24-DAG: store [[SB]]* [[SEC1:%.+]], [[SB]]** [[CP1]]
+// CK24-DAG: store i[[sz]] {{.+}}, i[[sz]]* [[S1]]
// CK24-DAG: [[SEC1]] = getelementptr {{.*}}[[SB]]* [[SEC11:%[^,]+]], i{{.+}} 0
// CK24-DAG: [[SEC11]] = load [[SB]]*, [[SB]]** [[SEC111:%[^,]+]],
// CK24-DAG: [[SEC111]] = getelementptr {{.*}}[[SC]]* [[VAR000:%.+]], i{{.+}} 0, i{{.+}} 2
@@ -3558,21 +3969,33 @@ int explicit_maps_struct_fields(int a){
{ p->a++; }
// Region 18
-// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 1, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[SIZE18]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[MTYPE18]]{{.+}})
+// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE18]]{{.+}})
// CK24-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
// CK24-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
+// CK24-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
// CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
+// CK24-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]**
// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32**
// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]]
// CK24-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]]
+// CK24-DAG: store i[[sz]] {{%.+}}, i[[sz]]* [[S0]]
// CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SA]]* [[SEC00:%[^,]+]], i{{.+}} 0, i{{.+}} 0
// CK24-DAG: [[SEC00]] = getelementptr {{.*}}[10 x [[SA]]]* [[SEC000:%[^,]+]], i{{.+}} 0, i{{.+}} 3
// CK24-DAG: [[SEC000]] = getelementptr {{.*}}[[SB]]* [[SEC0000:%[^,]+]], i{{.+}} 0, i{{.+}} 2
// CK24-DAG: [[SEC0000]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SC]]**
+// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32**
+// CK24-DAG: store [[SC]]* [[VAR0]], [[SC]]** [[CBP1]]
+// CK24-DAG: store i32* [[SEC0]], i32** [[CP1]]
+// CK24-DAG: store i[[sz]] {{.+}}, i[[sz]]* [[S1]]
+
// CK24-DAG: [[VAR0]] = load [[SC]]*, [[SC]]** %{{.+}}
// CK24-DAG: [[VAR00]] = load [[SC]]*, [[SC]]** %{{.+}}
@@ -3581,26 +4004,38 @@ int explicit_maps_struct_fields(int a){
{ p->a++; }
// Region 19
-// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[SIZE19]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE19]]{{.+}})
+// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 3, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[3 x i{{.+}}]* [[MTYPE19]]{{.+}})
// CK24-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
// CK24-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
+// CK24-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
// CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
+// CK24-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]**
// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SA]]***
// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]]
// CK24-DAG: store [[SA]]** [[SEC0:%.+]], [[SA]]*** [[CP0]]
+// CK24-DAG: store i[[sz]] {{%.+}}, i[[sz]]* [[S0]]
// CK24-DAG: [[SEC0]] = getelementptr {{.*}}[10 x [[SA]]*]* [[SEC00:%[^,]+]], i{{.+}} 0, i{{.+}} 3
// CK24-DAG: [[SEC00]] = getelementptr {{.*}}[[SB]]* [[SEC000:%[^,]+]], i{{.+}} 0, i{{.+}} 3
// CK24-DAG: [[SEC000]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 1
// CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
// CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
-// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SA]]***
-// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32**
-// CK24-DAG: store [[SA]]** [[SEC0]], [[SA]]*** [[CBP1]]
-// CK24-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]]
+// CK24-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SC]]**
+// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to [[SA]]***
+// CK24-DAG: store [[SC]]* [[VAR0]], [[SC]]** [[CBP1]]
+// CK24-DAG: store [[SA]]** [[SEC0]], [[SA]]*** [[CP1]]
+// CK24-DAG: store i[[sz]] {{.+}}, i[[sz]]* [[S1]]
+
+// CK24-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2
+// CK24-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2
+// CK24-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [[SA]]***
+// CK24-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to i32**
+// CK24-DAG: store [[SA]]** [[SEC0]], [[SA]]*** [[CBP2]]
+// CK24-DAG: store i32* [[SEC1:%.+]], i32** [[CP2]]
// CK24-DAG: [[SEC1]] = getelementptr {{.*}}[[SA]]* [[SEC11:%[^,]+]], i{{.+}} 0, i{{.+}} 0
// CK24-DAG: [[SEC11]] = load [[SA]]*, [[SA]]** [[SEC111:%[^,]+]],
// CK24-DAG: [[SEC111]] = getelementptr {{.*}}[10 x [[SA]]*]* [[SEC1111:%[^,]+]], i{{.+}} 0, i{{.+}} 3
@@ -3616,16 +4051,19 @@ int explicit_maps_struct_fields(int a){
{ p->a++; }
// Region 20
-// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[SIZE20]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE20]]{{.+}})
+// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE20]]{{.+}})
// CK24-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
// CK24-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
+// CK24-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
// CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
+// CK24-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]**
// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SB]]***
// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]]
// CK24-DAG: store [[SB]]** [[SEC0:%.+]], [[SB]]*** [[CP0]]
+// CK24-DAG: store i[[sz]] {{%.+}}, i[[sz]]* [[S0]]
// CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 2
// CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
@@ -3647,25 +4085,39 @@ int explicit_maps_struct_fields(int a){
{ p->a++; }
// Region 21
-// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[SIZE21]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE21]]{{.+}})
+// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 3, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[3 x i{{.+}}]* [[MTYPE21]]{{.+}})
// CK24-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
// CK24-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
+// CK24-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
// CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
+// CK24-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]**
// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SA]]***
// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]]
// CK24-DAG: store [[SA]]** [[SEC0:%.+]], [[SA]]*** [[CP0]]
+// CK24-DAG: store i[[sz]] {{%.+}}, i[[sz]]* [[S0]]
// CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SB]]* [[SEC00:[^,]+]], i{{.+}} 0, i{{.+}} 4
// CK24-DAG: [[SEC00]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 1
// CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
// CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
-// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SA]]***
-// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32**
-// CK24-DAG: store [[SA]]** [[SEC0]], [[SA]]*** [[CBP1]]
-// CK24-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]]
+// CK24-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SC]]**
+// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to [[SA]]***
+// CK24-DAG: store [[SC]]* [[VAR0]], [[SC]]** [[CBP1]]
+// CK24-DAG: store [[SA]]** [[SEC0]], [[SA]]*** [[CP1]]
+// CK24-DAG: store i[[sz]] {{.+}}, i[[sz]]* [[S1]]
+
+// CK24-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2
+// CK24-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2
+// CK24-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 2
+// CK24-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [[SA]]***
+// CK24-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to i32**
+// CK24-DAG: store [[SA]]** [[SEC0]], [[SA]]*** [[CBP2]]
+// CK24-DAG: store i32* [[SEC1:%.+]], i32** [[CP2]]
+// CK24-DAG: store i[[sz]] {{.+}}, i[[sz]]* [[S2]]
// CK24-DAG: [[SEC1]] = getelementptr {{.*}}[[SA]]* [[SEC11:%[^,]+]], i{{.+}} 0
// CK24-DAG: [[SEC11]] = load [[SA]]*, [[SA]]** [[SEC111:%[^,]+]],
// CK24-DAG: [[SEC111]] = getelementptr {{.*}}[[SB]]* [[SEC1111:[^,]+]], i{{.+}} 0, i{{.+}} 4
@@ -3680,21 +4132,33 @@ int explicit_maps_struct_fields(int a){
{ p->a++; }
// Region 22
-// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 1, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[SIZE22]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[MTYPE22]]{{.+}})
+// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE22]]{{.+}})
// CK24-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
// CK24-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
+// CK24-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
// CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
+// CK24-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]**
// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32**
// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]]
// CK24-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]]
+// CK24-DAG: store i[[sz]] {{%.+}}, i[[sz]]* [[S0]]
// CK24-DAG: [[SEC0]] = getelementptr {{.*}}[10 x i32]* [[SEC00:%[^,]+]], i{{.+}} 0, i{{.+}} 0
// CK24-DAG: [[SEC00]] = getelementptr {{.*}}[[SA]]* [[SEC000:%[^,]+]], i{{.+}} 0, i{{.+}} 2
// CK24-DAG: [[SEC000]] = getelementptr {{.*}}[[SB]]* [[SEC0000:%[^,]+]], i{{.+}} 0, i{{.+}} 1
// CK24-DAG: [[SEC0000]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SC]]**
+// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32**
+// CK24-DAG: store [[SC]]* [[VAR0]], [[SC]]** [[CBP1]]
+// CK24-DAG: store i32* [[SEC0]], i32** [[CP1]]
+// CK24-DAG: store i[[sz]] {{.+}}, i[[sz]]* [[S1]]
+
// CK24-DAG: [[VAR0]] = load [[SC]]*, [[SC]]** %{{.+}}
// CK24-DAG: [[VAR00]] = load [[SC]]*, [[SC]]** %{{.+}}
@@ -3703,25 +4167,39 @@ int explicit_maps_struct_fields(int a){
{ p->a++; }
// Region 23
-// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[SIZE23]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE23]]{{.+}})
+// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 3, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[3 x i{{.+}}]* [[MTYPE23]]{{.+}})
// CK24-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
// CK24-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
+// CK24-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
// CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
+// CK24-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]**
// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SA]]***
// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]]
// CK24-DAG: store [[SA]]** [[SEC0:%.+]], [[SA]]*** [[CP0]]
+// CK24-DAG: store i[[sz]] {{%.+}}, i[[sz]]* [[S0]]
// CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SB]]* [[SEC00:%[^,]+]], i{{.+}} 0, i{{.+}} 4
// CK24-DAG: [[SEC00]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 1
// CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
// CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
-// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SA]]***
-// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32**
-// CK24-DAG: store [[SA]]** [[SEC0]], [[SA]]*** [[CBP1]]
-// CK24-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]]
+// CK24-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SC]]**
+// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to [[SA]]***
+// CK24-DAG: store [[SC]]* [[VAR0]], [[SC]]** [[CBP1]]
+// CK24-DAG: store [[SA]]** [[SEC0]], [[SA]]*** [[CP1]]
+// CK24-DAG: store i[[sz]] {{.+}}, i[[sz]]* [[S1]]
+
+// CK24-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2
+// CK24-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2
+// CK24-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 2
+// CK24-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [[SA]]***
+// CK24-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to i32**
+// CK24-DAG: store [[SA]]** [[SEC0]], [[SA]]*** [[CBP2]]
+// CK24-DAG: store i32* [[SEC1:%.+]], i32** [[CP2]]
+// CK24-DAG: store i[[sz]] {{.+}}, i[[sz]]* [[S2]]
// CK24-DAG: [[SEC1]] = getelementptr {{.*}}[10 x i32]* [[SEC11:%[^,]+]], i{{.+}} 0, i{{.+}} 0
// CK24-DAG: [[SEC11]] = getelementptr {{.*}}[[SA]]* [[SEC111:%[^,]+]], i{{.+}} 0, i{{.+}} 2
// CK24-DAG: [[SEC111]] = load [[SA]]*, [[SA]]** [[SEC1111:%[^,]+]],
@@ -3737,34 +4215,41 @@ int explicit_maps_struct_fields(int a){
{ p->a++; }
// Region 24
-// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 4, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[4 x i{{.+}}]* [[SIZE24]], {{.+}}getelementptr {{.+}}[4 x i{{.+}}]* [[MTYPE24]]{{.+}})
+// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 4, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[4 x i{{.+}}]* [[MTYPE24]]{{.+}})
// CK24-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
// CK24-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
+// CK24-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
// CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
+// CK24-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]**
// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SB]]***
// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]]
// CK24-DAG: store [[SB]]** [[SEC0:%.+]], [[SB]]*** [[CP0]]
+// CK24-DAG: store i[[sz]] {{%.+}}, i[[sz]]* [[S0]]
// CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 2
// CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
// CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1
// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SB]]***
// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to [[SA]]***
// CK24-DAG: store [[SB]]** [[SEC0]], [[SB]]*** [[CBP1]]
// CK24-DAG: store [[SA]]** [[SEC1:%.+]], [[SA]]*** [[CP1]]
+// CK24-DAG: store i[[sz]] {{.+}}, i[[sz]]* [[S1]]
// CK24-DAG: [[SEC1]] = getelementptr {{.*}}[[SB]]* [[SEC11:%[^,]+]], i{{.+}} 0, i{{.+}} 4
// CK24-DAG: [[SEC11]] = load [[SB]]*, [[SB]]** [[SEC111:%[^,]+]],
// CK24-DAG: [[SEC111]] = getelementptr {{.*}}[[SC]]* [[VAR000:%.+]], i{{.+}} 0, i{{.+}} 2
// CK24-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2
// CK24-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2
+// CK24-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 2
// CK24-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [[SA]]***
// CK24-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to [[SA]]***
// CK24-DAG: store [[SA]]** [[SEC1]], [[SA]]*** [[CBP2]]
// CK24-DAG: store [[SA]]** [[SEC2:%.+]], [[SA]]*** [[CP2]]
+// CK24-DAG: store i[[sz]] {{.+}}, i[[sz]]* [[S2]]
// CK24-DAG: [[SEC2]] = getelementptr {{.*}}[[SA]]* [[SEC22:%[^,]+]], i{{.+}} 0, i{{.+}} 1
// CK24-DAG: [[SEC22]] = load [[SA]]*, [[SA]]** [[SEC222:%[^,]+]],
// CK24-DAG: [[SEC222]] = getelementptr {{.*}}[[SB]]* [[SEC2222:%[^,]+]], i{{.+}} 0, i{{.+}} 4
@@ -3773,10 +4258,12 @@ int explicit_maps_struct_fields(int a){
// CK24-DAG: [[BP3:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 3
// CK24-DAG: [[P3:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 3
+// CK24-DAG: [[S3:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 3
// CK24-DAG: [[CBP3:%.+]] = bitcast i8** [[BP3]] to [[SA]]***
// CK24-DAG: [[CP3:%.+]] = bitcast i8** [[P3]] to i32**
// CK24-DAG: store [[SA]]** [[SEC2]], [[SA]]*** [[CBP3]]
// CK24-DAG: store i32* [[SEC3:%.+]], i32** [[CP3]]
+// CK24-DAG: store i[[sz]] {{.+}}, i[[sz]]* [[S3]]
// CK24-DAG: [[SEC3]] = getelementptr {{.*}}[[SA]]* [[SEC33:%[^,]+]], i{{.+}} 0, i{{.+}} 0
// CK24-DAG: [[SEC33]] = load [[SA]]*, [[SA]]** [[SEC333:%[^,]+]],
// CK24-DAG: [[SEC333]] = getelementptr {{.*}}[[SA]]* [[SEC3333:%[^,]+]], i{{.+}} 0, i{{.+}} 1
@@ -3813,24 +4300,33 @@ int explicit_maps_struct_fields(int a){
// CK24: define {{.+}}[[CALL24]]
#endif
///==========================================================================///
-// RUN: %clang_cc1 -DCK25 -std=c++11 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK25 --check-prefix CK25-64
+// RUN: %clang_cc1 -DCK25 -std=c++11 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK25 --check-prefix CK25-64
// RUN: %clang_cc1 -DCK25 -std=c++11 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -std=c++11 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK25 --check-prefix CK25-64
-// RUN: %clang_cc1 -DCK25 -std=c++11 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK25 --check-prefix CK25-32
+// RUN: %clang_cc1 -fopenmp -std=c++11 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK25 --check-prefix CK25-64
+// RUN: %clang_cc1 -DCK25 -std=c++11 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK25 --check-prefix CK25-32
// RUN: %clang_cc1 -DCK25 -std=c++11 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -std=c++11 -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK25 --check-prefix CK25-32
+// RUN: %clang_cc1 -fopenmp -std=c++11 -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK25 --check-prefix CK25-32
+
+// RUN: %clang_cc1 -DCK25 -std=c++11 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY24 %s
+// RUN: %clang_cc1 -DCK25 -std=c++11 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY24 %s
+// RUN: %clang_cc1 -DCK25 -std=c++11 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY24 %s
+// RUN: %clang_cc1 -DCK25 -std=c++11 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY24 %s
+// SIMD-ONLY24-NOT: {{__kmpc|__tgt}}
#ifdef CK25
// CK25: [[ST:%.+]] = type { i32, float }
// CK25: [[CA00:%.+]] = type { [[ST]]* }
// CK25: [[CA01:%.+]] = type { i32* }
-// CK25: [[SIZE00:@.+]] = private {{.*}}constant [1 x i[[Z:64|32]]] [i[[Z:64|32]] 4]
-// CK25: [[MTYPE00:@.+]] = private {{.*}}constant [1 x i64] [i64 33]
+// CK25-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
+// CK25: [[MTYPE00:@.+]] = private {{.*}}constant [2 x i64] [i64 32, i64 281474976710657]
-// CK25: [[SIZE01:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 4]
+// CK25-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
+// CK25: [[SIZE01:@.+]] = private {{.*}}constant [1 x i[[Z:64|32]]] [i[[Z:64|32]] 4]
// CK25: [[MTYPE01:@.+]] = private {{.*}}constant [1 x i64] [i64 33]
-// CK25-LABEL: explicit_maps_with_inner_lambda
+// CK25-LABEL: explicit_maps_with_inner_lambda{{.*}}(
template <int X, typename T>
struct CC {
@@ -3839,18 +4335,30 @@ struct CC {
int foo(T arg) {
// Region 00
- // CK25-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 1, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[SIZE00]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[MTYPE00]]{{.+}})
+ // CK25-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[Z]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE00]]{{.+}})
// CK25-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
// CK25-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
+ // CK25-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
// CK25-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK25-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
+ // CK25-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
// CK25-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]**
// CK25-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32**
// CK25-DAG: store [[ST]]* [[VAR0:%.+]], [[ST]]** [[CBP0]]
// CK25-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]]
+ // CK25-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[S0]]
// CK25-DAG: [[SEC0]] = getelementptr {{.*}}[[ST]]* [[VAR0:%.+]], i{{.+}} 0, i{{.+}} 0
+ // CK25-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
+ // CK25-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+ // CK25-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1
+ // CK25-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[ST]]**
+ // CK25-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32**
+ // CK25-DAG: store [[ST]]* [[VAR0]], [[ST]]** [[CBP1]]
+ // CK25-DAG: store i32* [[SEC0]], i32** [[CP1]]
+ // CK25-DAG: store i[[Z]] {{.+}}, i[[Z]]* [[S1]]
+
// CK25: call void [[CALL00:@.+]]([[ST]]* {{[^,]+}})
#pragma omp target map(to:A)
{
@@ -3907,28 +4415,40 @@ int explicit_maps_with_inner_lambda(int a){
// CK25: define {{.+}}[[LAMBDA2]]
#endif
///==========================================================================///
-// RUN: %clang_cc1 -DCK26 -std=c++11 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK26 --check-prefix CK26-64
+// RUN: %clang_cc1 -DCK26 -std=c++11 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK26 --check-prefix CK26-64
// RUN: %clang_cc1 -DCK26 -std=c++11 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -std=c++11 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK26 --check-prefix CK26-64
-// RUN: %clang_cc1 -DCK26 -std=c++11 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK26 --check-prefix CK26-32
+// RUN: %clang_cc1 -fopenmp -std=c++11 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK26 --check-prefix CK26-64
+// RUN: %clang_cc1 -DCK26 -std=c++11 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK26 --check-prefix CK26-32
// RUN: %clang_cc1 -DCK26 -std=c++11 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -std=c++11 -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK26 --check-prefix CK26-32
+// RUN: %clang_cc1 -fopenmp -std=c++11 -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK26 --check-prefix CK26-32
+
+// RUN: %clang_cc1 -DCK26 -std=c++11 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY25 %s
+// RUN: %clang_cc1 -DCK26 -std=c++11 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY25 %s
+// RUN: %clang_cc1 -DCK26 -std=c++11 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY25 %s
+// RUN: %clang_cc1 -DCK26 -std=c++11 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY25 %s
+// SIMD-ONLY25-NOT: {{__kmpc|__tgt}}
#ifdef CK26
// CK26: [[ST:%.+]] = type { i32, float*, i32, float* }
+// CK26-LABEL: @.__omp_offloading_{{.*}}CC{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK26: [[SIZE00:@.+]] = private {{.*}}constant [2 x i[[Z:64|32]]] [i[[Z:64|32]] {{32|16}}, i[[Z:64|32]] 4]
-// CK26: [[MTYPE00:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 35]
+// CK26: [[MTYPE00:@.+]] = private {{.*}}constant [2 x i64] [i64 547, i64 35]
+// CK26-LABEL: @.__omp_offloading_{{.*}}CC{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK26: [[SIZE01:@.+]] = private {{.*}}constant [2 x i[[Z]]] [i[[Z]] {{32|16}}, i[[Z]] 4]
-// CK26: [[MTYPE01:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 35]
+// CK26: [[MTYPE01:@.+]] = private {{.*}}constant [2 x i64] [i64 547, i64 35]
+// CK26-LABEL: @.__omp_offloading_{{.*}}CC{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK26: [[SIZE02:@.+]] = private {{.*}}constant [2 x i[[Z]]] [i[[Z]] {{32|16}}, i[[Z]] 4]
-// CK26: [[MTYPE02:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 35]
+// CK26: [[MTYPE02:@.+]] = private {{.*}}constant [2 x i64] [i64 547, i64 35]
+// CK26-LABEL: @.__omp_offloading_{{.*}}CC{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK26: [[SIZE03:@.+]] = private {{.*}}constant [2 x i[[Z]]] [i[[Z]] {{32|16}}, i[[Z]] 4]
-// CK26: [[MTYPE03:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 35]
+// CK26: [[MTYPE03:@.+]] = private {{.*}}constant [2 x i64] [i64 547, i64 35]
-// CK26-LABEL: explicit_maps_with_private_class_members
+// CK26-LABEL: explicit_maps_with_private_class_members{{.*}}(
struct CC {
int fA;
@@ -4091,36 +4611,54 @@ int explicit_maps_with_private_class_members(){
}
#endif
///==========================================================================///
-// RUN: %clang_cc1 -DCK27 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK27 --check-prefix CK27-64
+// RUN: %clang_cc1 -DCK27 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK27 --check-prefix CK27-64
// RUN: %clang_cc1 -DCK27 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK27 --check-prefix CK27-64
-// RUN: %clang_cc1 -DCK27 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK27 --check-prefix CK27-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK27 --check-prefix CK27-64
+// RUN: %clang_cc1 -DCK27 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK27 --check-prefix CK27-32
// RUN: %clang_cc1 -DCK27 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK27 --check-prefix CK27-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK27 --check-prefix CK27-32
+
+// RUN: %clang_cc1 -DCK27 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY26 %s
+// RUN: %clang_cc1 -DCK27 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY26 %s
+// RUN: %clang_cc1 -DCK27 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY26 %s
+// RUN: %clang_cc1 -DCK27 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY26 %s
+// SIMD-ONLY26-NOT: {{__kmpc|__tgt}}
#ifdef CK27
+// CK27-LABEL: @.__omp_offloading_{{.*}}zero_size_section_and_private_maps{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK27: [[SIZE00:@.+]] = private {{.*}}constant [1 x i[[Z:64|32]]] zeroinitializer
-// CK27: [[MTYPE00:@.+]] = private {{.*}}constant [1 x i64] [i64 32]
+// CK27: [[MTYPE00:@.+]] = private {{.*}}constant [1 x i64] [i64 544]
+// CK27-LABEL: @.__omp_offloading_{{.*}}zero_size_section_and_private_maps{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK27: [[SIZE01:@.+]] = private {{.*}}constant [1 x i[[Z]]] zeroinitializer
// CK27: [[MTYPE01:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK27-LABEL: @.__omp_offloading_{{.*}}zero_size_section_and_private_maps{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK27: [[SIZE02:@.+]] = private {{.*}}constant [1 x i[[Z]]] zeroinitializer
// CK27: [[MTYPE02:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK27-LABEL: @.__omp_offloading_{{.*}}zero_size_section_and_private_maps{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK27: [[SIZE03:@.+]] = private {{.*}}constant [1 x i[[Z]]] zeroinitializer
// CK27: [[MTYPE03:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK27-LABEL: @.__omp_offloading_{{.*}}zero_size_section_and_private_maps{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
+// CK27-LABEL: @.__omp_offloading_{{.*}}zero_size_section_and_private_maps{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK27: [[SIZE05:@.+]] = private {{.*}}constant [1 x i[[Z]]] zeroinitializer
-// CK27: [[MTYPE05:@.+]] = private {{.*}}constant [1 x i64] [i64 32]
+// CK27: [[MTYPE05:@.+]] = private {{.*}}constant [1 x i64] [i64 544]
+// CK27-LABEL: @.__omp_offloading_{{.*}}zero_size_section_and_private_maps{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
+// CK27-LABEL: @.__omp_offloading_{{.*}}zero_size_section_and_private_maps{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK27: [[SIZE07:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 4]
-// CK27: [[MTYPE07:@.+]] = private {{.*}}constant [1 x i64] [i64 288]
+// CK27: [[MTYPE07:@.+]] = private {{.*}}constant [1 x i64] [i64 800]
+// CK27-LABEL: @.__omp_offloading_{{.*}}zero_size_section_and_private_maps{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
+// CK27-LABEL: @.__omp_offloading_{{.*}}zero_size_section_and_private_maps{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK27: [[SIZE09:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 40]
-// CK27: [[MTYPE09:@.+]] = private {{.*}}constant [1 x i64] [i64 161]
+// CK27: [[MTYPE09:@.+]] = private {{.*}}constant [1 x i64] [i64 673]
-// CK27-LABEL: zero_size_section_and_private_maps
+// CK27-LABEL: zero_size_section_and_private_maps{{.*}}(
void zero_size_section_and_private_maps (int ii){
// Map of a pointer.
@@ -4302,21 +4840,31 @@ void zero_size_section_and_private_maps (int ii){
// CK27: define {{.+}}[[CALL07]]
#endif
///==========================================================================///
-// RUN: %clang_cc1 -DCK28 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK28 --check-prefix CK28-64
+// RUN: %clang_cc1 -DCK28 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK28 --check-prefix CK28-64
// RUN: %clang_cc1 -DCK28 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK28 --check-prefix CK28-64
-// RUN: %clang_cc1 -DCK28 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK28 --check-prefix CK28-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK28 --check-prefix CK28-64
+// RUN: %clang_cc1 -DCK28 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK28 --check-prefix CK28-32
// RUN: %clang_cc1 -DCK28 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK28 --check-prefix CK28-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK28 --check-prefix CK28-32
+
+// RUN: %clang_cc1 -DCK28 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY27 %s
+// RUN: %clang_cc1 -DCK28 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY27 %s
+// RUN: %clang_cc1 -DCK28 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY27 %s
+// RUN: %clang_cc1 -DCK28 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY27 %s
+// SIMD-ONLY27-NOT: {{__kmpc|__tgt}}
#ifdef CK28
+// CK28-LABEL: @.__omp_offloading_{{.*}}explicit_maps_pointer_references{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK28: [[SIZE00:@.+]] = private {{.*}}constant [1 x i[[Z:64|32]]] [i[[Z:64|32]] {{8|4}}]
// CK28: [[MTYPE00:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK28-LABEL: @.__omp_offloading_{{.*}}explicit_maps_pointer_references{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
// CK28: [[SIZE01:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 400]
// CK28: [[MTYPE01:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
-// CK28-LABEL: explicit_maps_pointer_references
+// CK28-LABEL: explicit_maps_pointer_references{{.*}}(
void explicit_maps_pointer_references (int *p){
int *&a = p;
@@ -4365,25 +4913,33 @@ void explicit_maps_pointer_references (int *p){
}
#endif
///==========================================================================///
-// RUN: %clang_cc1 -DCK29 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK29 --check-prefix CK29-64
+// RUN: %clang_cc1 -DCK29 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK29 --check-prefix CK29-64
// RUN: %clang_cc1 -DCK29 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK29 --check-prefix CK29-64
-// RUN: %clang_cc1 -DCK29 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK29 --check-prefix CK29-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK29 --check-prefix CK29-64
+// RUN: %clang_cc1 -DCK29 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK29 --check-prefix CK29-32
// RUN: %clang_cc1 -DCK29 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK29 --check-prefix CK29-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK29 --check-prefix CK29-32
+
+// RUN: %clang_cc1 -DCK29 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY28 %s
+// RUN: %clang_cc1 -DCK29 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY28 %s
+// RUN: %clang_cc1 -DCK29 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY28 %s
+// RUN: %clang_cc1 -DCK29 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY28 %s
+// SIMD-ONLY28-NOT: {{__kmpc|__tgt}}
#ifdef CK29
// CK29: [[SSA:%.+]] = type { double*, double** }
// CK29: [[SSB:%.+]] = type { [[SSA]]*, [[SSA]]** }
-// CK29: [[SIZE00:@.+]] = private {{.*}}constant [4 x i[[Z:64|32]]] [i[[Z:64|32]] {{8|4}}, i[[Z:64|32]] {{8|4}}, i[[Z:64|32]] {{8|4}}, i[[Z:64|32]] 80]
-// CK29: [[MTYPE00:@.+]] = private {{.*}}constant [4 x i64] [i64 35, i64 16, i64 19, i64 19]
+// CK29-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
+// CK29: [[MTYPE00:@.+]] = private {{.*}}constant [3 x i64] [i64 32, i64 281474976710672, i64 19]
-// CK29: [[SIZE01:@.+]] = private {{.*}}constant [4 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] {{8|4}}, i[[Z]] {{8|4}}, i[[Z]] 80]
-// CK29: [[MTYPE01:@.+]] = private {{.*}}constant [4 x i64] [i64 32, i64 19, i64 19, i64 19]
+// CK29-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
+// CK29: [[MTYPE01:@.+]] = private {{.*}}constant [3 x i64] [i64 32, i64 281474976710672, i64 19]
-// CK29: [[SIZE02:@.+]] = private {{.*}}constant [5 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] {{8|4}}, i[[Z]] {{8|4}}, i[[Z]] {{8|4}}, i[[Z]] 80]
-// CK29: [[MTYPE02:@.+]] = private {{.*}}constant [5 x i64] [i64 32, i64 19, i64 16, i64 19, i64 19]
+// CK29-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
+// CK29: [[MTYPE02:@.+]] = private {{.*}}constant [3 x i64] [i64 32, i64 281474976710672, i64 19]
struct SSA{
double *p;
@@ -4400,45 +4956,44 @@ struct SSB{
void foo() {
// Region 00
- // CK29-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 4, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[4 x i{{.+}}]* [[SIZE00]], {{.+}}getelementptr {{.+}}[4 x i{{.+}}]* [[MTYPE00]]{{.+}})
+ // CK29-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 3, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[Z:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[3 x i{{.+}}]* [[MTYPE00]]{{.+}})
// CK29-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
// CK29-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
+ // CK29-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
// CK29-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK29-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
+ // CK29-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
// CK29-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SSB]]**
// CK29-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SSA]]**
// CK29-DAG: store [[SSB]]* [[VAR0:%.+]], [[SSB]]** [[CBP0]]
// CK29-DAG: store [[SSA]]** [[VAR00:%.+]], [[SSA]]*** [[CP0]]
+ // CK29-DAG: store i[[Z]] %{{.+}}, i[[Z]]* [[S0]]
// CK29-DAG: [[VAR0]] = load [[SSB]]*, [[SSB]]** %
// CK29-DAG: [[VAR00]] = getelementptr inbounds [[SSB]], [[SSB]]* [[VAR0]], i32 0, i32 0
// CK29-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
// CK29-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+ // CK29-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1
// CK29-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SSA]]***
- // CK29-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double****
+ // CK29-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double***
// CK29-DAG: store [[SSA]]** [[VAR00]], [[SSA]]*** [[CBP1]]
- // CK29-DAG: store double*** [[VAR1:%.+]], double**** [[CP1]]
- // CK29-DAG: [[VAR1]] = getelementptr inbounds [[SSA]], [[SSA]]* %{{.+}}, i32 0, i32 1
+ // CK29-DAG: store double** [[VAR1:%.+]], double*** [[CP1]]
+ // CK29-DAG: store i[[Z]] {{8|4}}, i[[Z]]* [[S1]]
+ // CK29-DAG: [[VAR1]] = load double**, double*** [[VAR1_REF:%.+]],
+ // CK29-DAG: [[VAR1_REF]] = getelementptr inbounds [[SSA]], [[SSA]]* %{{.+}}, i32 0, i32 1
// CK29-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2
// CK29-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2
- // CK29-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to double****
- // CK29-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to double***
- // CK29-DAG: store double*** [[VAR1]], double**** [[CBP2]]
- // CK29-DAG: store double** [[VAR2:%.+]], double*** [[CP2]]
- // CK29-DAG: [[VAR2]] = load double**, double*** [[VAR22:%.+]],
- // CK29-DAG: [[VAR22]] = getelementptr inbounds [[SSA]], [[SSA]]* %{{.+}}, i32 0, i32 1
-
- // CK29-DAG: [[BP3:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 3
- // CK29-DAG: [[P3:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 3
- // CK29-DAG: [[CBP3:%.+]] = bitcast i8** [[BP3]] to double***
- // CK29-DAG: [[CP3:%.+]] = bitcast i8** [[P3]] to double**
- // CK29-DAG: store double** [[VAR2]], double*** [[CBP3]]
- // CK29-DAG: store double* [[VAR3:%.+]], double** [[CP3]]
- // CK29-DAG: [[VAR3]] = getelementptr inbounds double, double* [[VAR33:%.+]], i{{.+}} 0
- // CK29-DAG: [[VAR33]] = load double*, double** %{{.+}},
+ // CK29-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 2
+ // CK29-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to double***
+ // CK29-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to double**
+ // CK29-DAG: store double** [[VAR1]], double*** [[CBP2]]
+ // CK29-DAG: store double* [[VAR2:%.+]], double** [[CP2]]
+ // CK29-DAG: store i[[Z]] 80, i[[Z]]* [[S2]]
+ // CK29-DAG: [[VAR2]] = getelementptr inbounds double, double* [[VAR22:%.+]], i{{.+}} 0
+ // CK29-DAG: [[VAR22]] = load double*, double** %{{.+}},
// CK29: call void [[CALL00:@.+]]([[SSB]]* {{[^,]+}})
#pragma omp target map(p->pr[:10])
@@ -4447,43 +5002,43 @@ struct SSB{
}
// Region 01
- // CK29-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 4, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[4 x i{{.+}}]* [[SIZE01]], {{.+}}getelementptr {{.+}}[4 x i{{.+}}]* [[MTYPE01]]{{.+}})
+ // CK29-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 3, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[Z]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[3 x i{{.+}}]* [[MTYPE01]]{{.+}})
// CK29-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
// CK29-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
+ // CK29-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
// CK29-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK29-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
+ // CK29-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
// CK29-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SSB]]**
- // CK29-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SSA]]****
- // CK29-DAG: store [[SSB]]* [[VAR0:%.+]], [[SSB]]** [[CBP0]]
- // CK29-DAG: store [[SSA]]*** [[VAR00:%.+]], [[SSA]]**** [[CP0]]
- // CK29-DAG: [[VAR00]] = getelementptr inbounds [[SSB]], [[SSB]]* [[VAR0]], i32 0, i32 1
+ // CK29-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SSA]]**
+ // CK29-DAG: store [[SSB]]* [[VAR0]], [[SSB]]** [[CBP0]]
+ // CK29-DAG: store [[SSA]]** [[VAR00:%.+]], [[SSA]]*** [[CP0]]
+ // CK29-DAG: store i[[Z]] %{{.+}}, i[[Z]]* [[S0]]
+ // CK29-DAG: [[VAR00]] = load [[SSA]]**, [[SSA]]*** [[VAR000:%.+]],
+ // CK29-DAG: [[VAR000]] = getelementptr inbounds [[SSB]], [[SSB]]* [[VAR0]], i32 0, i32 1
// CK29-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
// CK29-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
- // CK29-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SSA]]****
- // CK29-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to [[SSA]]***
- // CK29-DAG: store [[SSA]]*** [[VAR00]], [[SSA]]**** [[CBP1]]
- // CK29-DAG: store [[SSA]]** [[VAR1:%.+]], [[SSA]]*** [[CP1]]
- // CK29-DAG: [[VAR1]] = load [[SSA]]**, [[SSA]]*** [[VAR00]],
+ // CK29-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1
+ // CK29-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SSA]]***
+ // CK29-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double***
+ // CK29-DAG: store [[SSA]]** [[VAR00]], [[SSA]]*** [[CBP1]]
+ // CK29-DAG: store double** [[VAR1:%.+]], double*** [[CP1]]
+ // CK29-DAG: store i[[Z]] {{8|4}}, i[[Z]]* [[S1]]
+ // CK29-DAG: [[VAR1]] = getelementptr inbounds [[SSA]], [[SSA]]* %{{.+}}, i32 0, i32 0
// CK29-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2
// CK29-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2
- // CK29-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [[SSA]]***
- // CK29-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to double***
- // CK29-DAG: store [[SSA]]** [[VAR1]], [[SSA]]*** [[CBP2]]
- // CK29-DAG: store double** [[VAR2:%.+]], double*** [[CP2]]
- // CK29-DAG: [[VAR2]] = getelementptr inbounds [[SSA]], [[SSA]]* %{{.+}}, i32 0, i32 0
-
- // CK29-DAG: [[BP3:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 3
- // CK29-DAG: [[P3:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 3
- // CK29-DAG: [[CBP3:%.+]] = bitcast i8** [[BP3]] to double***
- // CK29-DAG: [[CP3:%.+]] = bitcast i8** [[P3]] to double**
- // CK29-DAG: store double** [[VAR2]], double*** [[CBP3]]
- // CK29-DAG: store double* [[VAR3:%.+]], double** [[CP3]]
- // CK29-DAG: [[VAR3]] = getelementptr inbounds double, double* [[VAR33:%.+]], i{{.+}} 0
- // CK29-DAG: [[VAR33]] = load double*, double** %{{.+}},
+ // CK29-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 2
+ // CK29-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to double***
+ // CK29-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to double**
+ // CK29-DAG: store double** [[VAR1]], double*** [[CBP2]]
+ // CK29-DAG: store double* [[VAR2:%.+]], double** [[CP2]]
+ // CK29-DAG: store i[[Z]] 80, i[[Z]]* [[S2]]
+ // CK29-DAG: [[VAR2]] = getelementptr inbounds double, double* [[VAR22:%.+]], i{{.+}} 0
+ // CK29-DAG: [[VAR22]] = load double*, double** %{{.+}},
// CK29: call void [[CALL00:@.+]]([[SSB]]* {{[^,]+}})
#pragma omp target map(pr->p[:10])
@@ -4492,51 +5047,44 @@ struct SSB{
}
// Region 02
- // CK29-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 5, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[5 x i{{.+}}]* [[SIZE02]], {{.+}}getelementptr {{.+}}[5 x i{{.+}}]* [[MTYPE02]]{{.+}})
+ // CK29-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 3, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[Z]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[3 x i{{.+}}]* [[MTYPE02]]{{.+}})
// CK29-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
// CK29-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
+ // CK29-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
// CK29-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK29-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
+ // CK29-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
// CK29-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SSB]]**
- // CK29-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SSA]]****
- // CK29-DAG: store [[SSB]]* [[VAR0:%.+]], [[SSB]]** [[CBP0]]
- // CK29-DAG: store [[SSA]]*** [[VAR00:%.+]], [[SSA]]**** [[CP0]]
- // CK29-DAG: [[VAR00]] = getelementptr inbounds [[SSB]], [[SSB]]* [[VAR0]], i32 0, i32 1
+ // CK29-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SSA]]**
+ // CK29-DAG: store [[SSB]]* [[VAR0]], [[SSB]]** [[CBP0]]
+ // CK29-DAG: store [[SSA]]** [[VAR00:%.+]], [[SSA]]*** [[CP0]]
+ // CK29-DAG: store i[[Z]] %{{.+}}, i[[Z]]* [[S0]]
+ // CK29-DAG: [[VAR00]] = load [[SSA]]**, [[SSA]]*** [[VAR000:%.+]],
+ // CK29-DAG: [[VAR000]] = getelementptr inbounds [[SSB]], [[SSB]]* [[VAR0]], i32 0, i32 1
// CK29-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
// CK29-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
- // CK29-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SSA]]****
- // CK29-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to [[SSA]]***
- // CK29-DAG: store [[SSA]]*** [[VAR00]], [[SSA]]**** [[CBP1]]
- // CK29-DAG: store [[SSA]]** [[VAR1:%.+]], [[SSA]]*** [[CP1]]
- // CK29-DAG: [[VAR1]] = load [[SSA]]**, [[SSA]]*** [[VAR00]],
+ // CK29-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1
+ // CK29-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SSA]]***
+ // CK29-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double***
+ // CK29-DAG: store [[SSA]]** [[VAR00]], [[SSA]]*** [[CBP1]]
+ // CK29-DAG: store double** [[VAR1:%.+]], double*** [[CP1]]
+ // CK29-DAG: store i[[Z]] {{8|4}}, i[[Z]]* [[S1]]
+ // CK29-DAG: [[VAR1]] = load double**, double*** [[VAR1_REF:%.+]],
+ // CK29-DAG: [[VAR1_REF]] = getelementptr inbounds [[SSA]], [[SSA]]* %{{.+}}, i32 0, i32 1
// CK29-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2
// CK29-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2
- // CK29-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [[SSA]]***
- // CK29-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to double****
- // CK29-DAG: store [[SSA]]** [[VAR1]], [[SSA]]*** [[CBP2]]
- // CK29-DAG: store double*** [[VAR2:%.+]], double**** [[CP2]]
- // CK29-DAG: [[VAR2]] = getelementptr inbounds [[SSA]], [[SSA]]* %{{.+}}, i32 0, i32 1
-
- // CK29-DAG: [[BP3:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 3
- // CK29-DAG: [[P3:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 3
- // CK29-DAG: [[CBP3:%.+]] = bitcast i8** [[BP3]] to double****
- // CK29-DAG: [[CP3:%.+]] = bitcast i8** [[P3]] to double***
- // CK29-DAG: store double*** [[VAR2]], double**** [[CBP3]]
- // CK29-DAG: store double** [[VAR3:%.+]], double*** [[CP3]]
- // CK29-DAG: [[VAR3]] = load double**, double*** [[VAR2]],
-
- // CK29-DAG: [[BP4:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 4
- // CK29-DAG: [[P4:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 4
- // CK29-DAG: [[CBP4:%.+]] = bitcast i8** [[BP4]] to double***
- // CK29-DAG: [[CP4:%.+]] = bitcast i8** [[P4]] to double**
- // CK29-DAG: store double** [[VAR3]], double*** [[CBP4]]
- // CK29-DAG: store double* [[VAR4:%.+]], double** [[CP4]]
- // CK29-DAG: [[VAR4]] = getelementptr inbounds double, double* [[VAR44:%.+]], i{{.+}} 0
- // CK29-DAG: [[VAR44]] = load double*, double**
+ // CK29-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 2
+ // CK29-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to double***
+ // CK29-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to double**
+ // CK29-DAG: store double** [[VAR1]], double*** [[CBP2]]
+ // CK29-DAG: store double* [[VAR2:%.+]], double** [[CP2]]
+ // CK29-DAG: store i[[Z]] 80, i[[Z]]* [[S2]]
+ // CK29-DAG: [[VAR2]] = getelementptr inbounds double, double* [[VAR22:%.+]], i{{.+}} 0
+ // CK29-DAG: [[VAR22]] = load double*, double** %{{.+}},
// CK29: call void [[CALL00:@.+]]([[SSB]]* {{[^,]+}})
#pragma omp target map(pr->pr[:10])
diff --git a/test/OpenMP/target_map_messages.cpp b/test/OpenMP/target_map_messages.cpp
index 9ffbec472572..03a81ee575b6 100644
--- a/test/OpenMP/target_map_messages.cpp
+++ b/test/OpenMP/target_map_messages.cpp
@@ -1,5 +1,8 @@
-// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 200 %s
-// RUN: %clang_cc1 -DCCODE -verify -fopenmp -ferror-limit 200 -x c %s
+// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 200 %s -Wno-openmp-target
+// RUN: %clang_cc1 -DCCODE -verify -fopenmp -ferror-limit 200 -x c %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 200 %s -Wno-openmp-target
+// RUN: %clang_cc1 -DCCODE -verify -fopenmp-simd -ferror-limit 200 -x c %s -Wno-openmp-target
#ifdef CCODE
void foo(int arg) {
const int n = 0;
@@ -16,6 +19,13 @@ void foo(int arg) {
{}
}
#else
+
+struct SREF {
+ int &a;
+ int b;
+ SREF(int &a) : a(a) {}
+};
+
template <typename T, int I>
struct SA {
static int ss;
@@ -28,13 +38,14 @@ struct SA {
T *f;
int bf : 20;
void func(int arg) {
+ SREF sref(arg);
#pragma omp target
{
a = 0.0;
func(arg);
bf = 20;
}
- #pragma omp target map(arg,a,d)
+ #pragma omp target map(arg,a,d,sref.b)
{}
#pragma omp target map(arg[2:2],a,d) // expected-error {{subscripted value is not an array or pointer}}
{}
@@ -232,9 +243,17 @@ void SAclient(int arg) {
{}
#pragma omp target map(r.ArrS[0].A, t.ArrS[1].A)
{}
- #pragma omp target map(r.PtrS[0], r.PtrS->B) // expected-error {{same pointer derreferenced in multiple different ways in map clause expressions}} expected-note {{used here}}
+ #pragma omp target map(r.PtrS[0], r.PtrS->B) // expected-error {{same pointer dereferenced in multiple different ways in map clause expressions}} expected-note {{used here}}
+ {}
+ #pragma omp target map(r.PtrS, r.PtrS->B) // expected-error {{pointer cannot be mapped along with a section derived from itself}} expected-note {{used here}}
+ {}
+ #pragma omp target map(r.PtrS->A, r.PtrS->B)
+ {}
+ #pragma omp target map(r.RPtrS[0], r.RPtrS->B) // expected-error {{same pointer dereferenced in multiple different ways in map clause expressions}} expected-note {{used here}}
+ {}
+ #pragma omp target map(r.RPtrS, r.RPtrS->B) // expected-error {{pointer cannot be mapped along with a section derived from itself}} expected-note {{used here}}
{}
- #pragma omp target map(r.RPtrS[0], r.RPtrS->B) // expected-error {{same pointer derreferenced in multiple different ways in map clause expressions}} expected-note {{used here}}
+ #pragma omp target map(r.RPtrS->A, r.RPtrS->B)
{}
#pragma omp target map(r.S.Arr[:12])
{}
diff --git a/test/OpenMP/target_messages.cpp b/test/OpenMP/target_messages.cpp
index 77d808493789..c9dc80aca44c 100644
--- a/test/OpenMP/target_messages.cpp
+++ b/test/OpenMP/target_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -o - %s
// RUN: not %clang_cc1 -fopenmp -std=c++11 -fopenmp-targets=aaa-bbb-ccc-ddd -o - %s 2>&1 | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -o - %s
// CHECK: error: OpenMP target is invalid: 'aaa-bbb-ccc-ddd'
// RUN: not %clang_cc1 -fopenmp -std=c++11 -triple nvptx64-nvidia-cuda -o - %s 2>&1 | FileCheck --check-prefix CHECK-UNSUPPORTED-HOST-TARGET %s
// RUN: not %clang_cc1 -fopenmp -std=c++11 -triple nvptx-nvidia-cuda -o - %s 2>&1 | FileCheck --check-prefix CHECK-UNSUPPORTED-HOST-TARGET %s
@@ -7,6 +9,25 @@
// RUN: not %clang_cc1 -fopenmp -std=c++11 -fopenmp-targets=hexagon-linux-gnu -o - %s 2>&1 | FileCheck --check-prefix CHECK-UNSUPPORTED-DEVICE-TARGET %s
// CHECK-UNSUPPORTED-DEVICE-TARGET: OpenMP target is invalid: 'hexagon-linux-gnu'
+// RUN: not %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path 1111.bc -o - 2>&1 | FileCheck --check-prefix NO-HOST-BC %s
+// NO-HOST-BC: The provided host compiler IR file '1111.bc' is required to generate code for OpenMP target regions but cannot be found.
+
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc -DREGION_HOST
+// RUN: not %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - -DREGION_DEVICE 2>&1 | FileCheck %s --check-prefix NO-REGION
+// NO-REGION: Offloading entry for target region is incorrect: either the address or the ID is invalid.
+
+#if defined(REGION_HOST) || defined(REGION_DEVICE)
+void foo() {
+#ifdef REGION_HOST
+#pragma omp target
+ ;
+#endif
+#ifdef REGION_DEVICE
+#pragma omp target
+ ;
+#endif
+}
+#else
void foo() {
}
@@ -69,4 +90,4 @@ int main(int argc, char **argv) {
return 0;
}
-
+#endif
diff --git a/test/OpenMP/target_nowait_messages.cpp b/test/OpenMP/target_nowait_messages.cpp
index 7531c81c0f6a..1f982dd67403 100644
--- a/test/OpenMP/target_nowait_messages.cpp
+++ b/test/OpenMP/target_nowait_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_ast_print.cpp b/test/OpenMP/target_parallel_ast_print.cpp
index 82c9203f030f..1b61f1533044 100644
--- a/test/OpenMP/target_parallel_ast_print.cpp
+++ b/test/OpenMP/target_parallel_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -70,7 +74,7 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: S<T> s;
// CHECK-NEXT: T arr[C][10], arr1[C];
// CHECK-NEXT: T i, j, a[20]
-// CHECK-NEXT: #pragma omp target parallel
+// CHECK-NEXT: #pragma omp target parallel{{$}}
// CHECK-NEXT: h = 2;
// CHECK-NEXT: #pragma omp target parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(C) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:C][0:10])
// CHECK-NEXT: foo()
diff --git a/test/OpenMP/target_parallel_codegen.cpp b/test/OpenMP/target_parallel_codegen.cpp
index b9d00da02f45..f1a511a6bb45 100644
--- a/test/OpenMP/target_parallel_codegen.cpp
+++ b/test/OpenMP/target_parallel_codegen.cpp
@@ -1,28 +1,46 @@
// Test host codegen.
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// Test target codegen - host bc file has to be created first.
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-64
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-64
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-32
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
-// CHECK-DAG: %ident_t = type { i32, i32, i32, i32, i8* }
+// CHECK-DAG: %struct.ident_t = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr constant %ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
// CHECK-DAG: [[TT:%.+]] = type { i64, i8 }
// CHECK-DAG: [[S1:%.+]] = type { double }
@@ -34,36 +52,35 @@
// CHECK-DAG: $[[REGFN:\.omp_offloading\..+]] = comdat
-// We have 8 target regions, but only 7 that actually will generate offloading
-// code, only 6 will have mapped arguments, and only 4 have all-constant map
-// sizes.
+// We have 8 target regions, but only 6 that actually will generate offloading
+// code and have mapped arguments, and only 4 have all-constant map sizes.
-// CHECK-DAG: [[SIZET2:@.+]] = private unnamed_addr constant [1 x i{{32|64}}] [i[[SZ:32|64]] 2]
-// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [1 x i64] [i64 288]
+// CHECK-DAG: [[SIZET2:@.+]] = private unnamed_addr constant [1 x i{{32|64}}] [i[[SZ]] 2]
+// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [1 x i64] [i64 800]
// CHECK-DAG: [[SIZET3:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2]
-// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [2 x i64] [i64 288, i64 288]
-// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [9 x i64] [i64 288, i64 547, i64 288, i64 547, i64 547, i64 288, i64 288, i64 547, i64 547]
+// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [2 x i64] [i64 800, i64 800]
+// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [9 x i64] [i64 800, i64 547, i64 288, i64 547, i64 547, i64 288, i64 288, i64 547, i64 547]
// CHECK-DAG: [[SIZET5:@.+]] = private unnamed_addr constant [3 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2, i[[SZ]] 40]
-// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [3 x i64] [i64 288, i64 288, i64 547]
+// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [3 x i64] [i64 800, i64 800, i64 547]
// CHECK-DAG: [[SIZET6:@.+]] = private unnamed_addr constant [4 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2, i[[SZ]] 1, i[[SZ]] 40]
-// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [4 x i64] [i64 288, i64 288, i64 288, i64 547]
-// CHECK-DAG: [[MAPT7:@.+]] = private unnamed_addr constant [5 x i64] [i64 547, i64 288, i64 288, i64 288, i64 547]
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK-NOT: @{{.+}} = constant [[ENTTY]]
+// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [4 x i64] [i64 800, i64 800, i64 800, i64 547]
+// CHECK-DAG: [[MAPT7:@.+]] = private unnamed_addr constant [6 x i64] [i64 32, i64 281474976711171, i64 800, i64 288, i64 288, i64 547]
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -74,7 +91,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx, typename ty>
@@ -179,13 +196,13 @@ int foo(int n) {
// CHECK-32: store i32 [[A_VAL]], i32* [[A_CADDR:%.+]],
// CHECK-32: [[A_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[A_CADDR]],
+ // CHECK: [[IF:%.+]] = icmp sgt i32 {{[^,]+}}, 20
+ // CHECK: br i1 [[IF]], label %[[TRY:[^,]+]], label %[[FAIL:[^,]+]]
+ // CHECK: [[TRY]]
// CHECK: [[BNSIZE:%.+]] = mul nuw i[[SZ]] [[VLA0:%.+]], 4
// CHECK: [[CNELEMSIZE2:%.+]] = mul nuw i[[SZ]] 5, [[VLA1:%.+]]
// CHECK: [[CNSIZE:%.+]] = mul nuw i[[SZ]] [[CNELEMSIZE2]], 8
- // CHECK: [[IF:%.+]] = icmp sgt i32 {{[^,]+}}, 20
- // CHECK: br i1 [[IF]], label %[[TRY:[^,]+]], label %[[FAIL:[^,]+]]
- // CHECK: [[TRY]]
// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 9, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([9 x i64], [9 x i64]* [[MAPT4]], i32 0, i32 0), i32 1, i32 0)
// CHECK-DAG: [[BPR]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BP:%[^,]+]], i32 0, i32 0
// CHECK-DAG: [[PR]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P:%[^,]+]], i32 0, i32 0
@@ -300,7 +317,7 @@ int foo(int n) {
// correct and loaded correctly for the target regions in foo().
// CHECK: define internal void [[HVT0]]()
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* [[OMP_OUTLINED:@.+]] to void (i32*, i32*, ...)*))
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* [[OMP_OUTLINED:@.+]] to void (i32*, i32*, ...)*))
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED]](i32* noalias %.global_tid., i32* noalias %.bound_tid.)
@@ -320,7 +337,7 @@ int foo(int n) {
// CHECK-64: store i32 [[AA]], i32* [[AA_C]], align
// CHECK-32: store i32 [[AA]], i32* [[AA_CASTED]], align
// CHECK: [[PARAM:%.+]] = load i[[SZ]], i[[SZ]]* [[AA_CASTED]], align
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]])* [[OMP_OUTLINED1:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]])* [[OMP_OUTLINED1:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED1]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}})
@@ -342,7 +359,7 @@ int foo(int n) {
// CHECK: [[AA_C:%.+]] = bitcast i[[SZ]]* [[AA_CASTED]] to i16*
// CHECK: store i16 [[AA]], i16* [[AA_C]], align
// CHECK: [[PARAM:%.+]] = load i[[SZ]], i[[SZ]]* [[AA_CASTED]], align
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]])* [[OMP_OUTLINED2:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]])* [[OMP_OUTLINED2:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED2]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}})
@@ -373,7 +390,7 @@ int foo(int n) {
// CHECK-DAG: store i16 [[AA]], i16* [[AA_C]], align
// CHECK-DAG: [[PARAM1:%.+]] = load i[[SZ]], i[[SZ]]* [[A_CASTED]], align
// CHECK-DAG: [[PARAM2:%.+]] = load i[[SZ]], i[[SZ]]* [[AA_CASTED]], align
-// CHECK-DAG: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 2, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]])* [[OMP_OUTLINED3:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM1]], i[[SZ]] [[PARAM2]])
+// CHECK-DAG: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 2, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]])* [[OMP_OUTLINED3:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM1]], i[[SZ]] [[PARAM2]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED3]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}})
@@ -425,7 +442,7 @@ int foo(int n) {
// CHECK-32-DAG:store i32 [[LOCAL_AV]], i32* [[LOCAL_A_CASTED]], align
// CHECK-DAG: [[REF_A:%.+]] = load i[[SZ]], i[[SZ]]* [[LOCAL_A_CASTED]],
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 9, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], [10 x float]*, i[[SZ]], float*, [5 x [10 x double]]*, i[[SZ]], i[[SZ]], double*, [[TT]]*)* [[OMP_OUTLINED4:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], [10 x float]* [[REF_B]], i[[SZ]] [[VAL_VLA1]], float* [[REF_BN]], [5 x [10 x double]]* [[REF_C]], i[[SZ]] [[VAL_VLA2]], i[[SZ]] [[VAL_VLA3]], double* [[REF_CN]], [[TT]]* [[REF_D]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 9, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], [10 x float]*, i[[SZ]], float*, [5 x [10 x double]]*, i[[SZ]], i[[SZ]], double*, [[TT]]*)* [[OMP_OUTLINED4:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], [10 x float]* [[REF_B]], i[[SZ]] [[VAL_VLA1]], float* [[REF_BN]], [5 x [10 x double]]* [[REF_C]], i[[SZ]] [[VAL_VLA2]], i[[SZ]] [[VAL_VLA3]], double* [[REF_CN]], [[TT]]* [[REF_D]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED4]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}}, [10 x float]* {{.+}}, i[[SZ]] %{{.+}}, float* {{.+}}, [5 x [10 x double]]* {{.+}}, i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, double* {{.+}}, [[TT]]* {{.+}})
@@ -510,32 +527,36 @@ int bar(int n){
// CHECK-64: store i32 %{{.+}}, i32* [[B_ADDR]],
// CHECK-64: [[B_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[B_CADDR]],
+// CHECK-32: store i32 %{{.+}}, i32* %__vla_expr
// CHECK-32: store i32 %{{.+}}, i32* [[B_ADDR:%.+]],
// CHECK-32: [[B_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[B_ADDR]],
+// CHECK: [[IF:%.+]] = icmp sgt i32 {{[^,]+}}, 60
+// CHECK: br i1 [[IF]], label %[[TRY:[^,]+]], label %[[FAIL:[^,]+]]
+// CHECK: [[TRY]]
// We capture 2 VLA sizes in this target region
// CHECK: [[CELEMSIZE2:%.+]] = mul nuw i[[SZ]] 2, [[VLA0:%.+]]
// CHECK: [[CSIZE:%.+]] = mul nuw i[[SZ]] [[CELEMSIZE2]], 2
-// CHECK: [[IF:%.+]] = icmp sgt i32 {{[^,]+}}, 60
-// CHECK: br i1 [[IF]], label %[[TRY:[^,]+]], label %[[FAIL:[^,]+]]
-// CHECK: [[TRY]]
-// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 5, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([5 x i64], [5 x i64]* [[MAPT7]], i32 0, i32 0), i32 1, i32 0)
-// CHECK-DAG: [[BPR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP:%.+]], i32 0, i32 0
-// CHECK-DAG: [[PR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P:%.+]], i32 0, i32 0
-// CHECK-DAG: [[SR]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0
-// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX0:[0-9]+]]
-// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX0]]
-// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX0]]
-// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX1:[0-9]+]]
-// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX1]]
-// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX1]]
-// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX2:[0-9]+]]
-// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX2]]
-// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX2]]
-// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]]
-// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX3]]
-// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX3]]
+// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 6, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([6 x i64], [6 x i64]* [[MAPT7]], i32 0, i32 0), i32 1, i32 0)
+// CHECK-DAG: [[BPR]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP:%.+]], i32 0, i32 0
+// CHECK-DAG: [[PR]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P:%.+]], i32 0, i32 0
+// CHECK-DAG: [[SR]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0
+// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX0:[0-9]+]]
+// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX0]]
+// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX0]]
+// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX1:[0-9]+]]
+// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX1]]
+// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX1]]
+// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX2:[0-9]+]]
+// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX2]]
+// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX2]]
+// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]]
+// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX3]]
+// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX3]]
+// CHECK-DAG: [[SADDR4:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX4:[0-9]+]]
+// CHECK-DAG: [[BPADDR4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX4]]
+// CHECK-DAG: [[PADDR4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX4]]
// The names below are not necessarily consistent with the names used for the
// addresses above as some are repeated.
@@ -561,12 +582,18 @@ int bar(int n){
// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CPADDR3:%.+]],
// CHECK-DAG: [[CBPADDR3]] = bitcast i8** {{%[^,]+}} to [[S1]]**
// CHECK-DAG: [[CPADDR3]] = bitcast i8** {{%[^,]+}} to [[S1]]**
+// CHECK-DAG: store i[[SZ]] %{{.+}}, i[[SZ]]* {{%[^,]+}}
+
+// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CBPADDR4:%.+]],
+// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CPADDR4:%.+]],
+// CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to [[S1]]**
+// CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to [[S1]]**
// CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* {{%[^,]+}}
-// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR4:%.+]],
-// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR4:%.+]],
-// CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to i16**
-// CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to i16**
+// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR5:%.+]],
+// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR5:%.+]],
+// CHECK-DAG: [[CBPADDR5]] = bitcast i8** {{%[^,]+}} to i16**
+// CHECK-DAG: [[CPADDR5]] = bitcast i8** {{%[^,]+}} to i16**
// CHECK-DAG: store i[[SZ]] [[CSIZE]], i[[SZ]]* {{%[^,]+}}
// CHECK-NEXT: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
@@ -700,7 +727,7 @@ int bar(int n){
// CHECK-32-DAG:store i32 [[LOCAL_BV]], i32* [[LOCAL_B_CASTED]], align
// CHECK-DAG: [[REF_B:%.+]] = load i[[SZ]], i[[SZ]]* [[LOCAL_B_CASTED]],
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 5, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, [[S1]]*, i[[SZ]], i[[SZ]], i[[SZ]], i16*)* [[OMP_OUTLINED5:@.+]] to void (i32*, i32*, ...)*), [[S1]]* [[REF_THIS]], i[[SZ]] [[REF_B]], i[[SZ]] [[VAL_VLA1]], i[[SZ]] [[VAL_VLA2]], i16* [[REF_C]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 5, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, [[S1]]*, i[[SZ]], i[[SZ]], i[[SZ]], i16*)* [[OMP_OUTLINED5:@.+]] to void (i32*, i32*, ...)*), [[S1]]* [[REF_THIS]], i[[SZ]] [[REF_B]], i[[SZ]] [[VAL_VLA1]], i[[SZ]] [[VAL_VLA2]], i16* [[REF_C]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED5]](i32* noalias %.global_tid., i32* noalias %.bound_tid., [[S1]]* %{{.+}}, i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, i16* {{.+}})
@@ -743,7 +770,7 @@ int bar(int n){
// CHECK-DAG: store i8 [[CONV_AAA]], i8* [[CONV]], align
// CHECK-DAG: [[REF_AAA:%.+]] = load i[[SZ]], i[[SZ]]* [[LOCAL_AAA_CASTED]],
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 4, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]], i[[SZ]], [10 x i32]*)* [[OMP_OUTLINED6:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], i[[SZ]] [[REF_AA]], i[[SZ]] [[REF_AAA]], [10 x i32]* [[REF_B]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 4, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]], i[[SZ]], [10 x i32]*)* [[OMP_OUTLINED6:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], i[[SZ]] [[REF_AA]], i[[SZ]] [[REF_AAA]], [10 x i32]* [[REF_B]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED6]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, [10 x i32]* {{.+}})
@@ -776,7 +803,7 @@ int bar(int n){
// CHECK-DAG: store i16 [[CONV_AA]], i16* [[CONV]], align
// CHECK-DAG: [[REF_AA:%.+]] = load i[[SZ]], i[[SZ]]* [[LOCAL_AA_CASTED]],
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]], [10 x i32]*)* [[OMP_OUTLINED7:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], i[[SZ]] [[REF_AA]], [10 x i32]* [[REF_B]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]], [10 x i32]*)* [[OMP_OUTLINED7:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], i[[SZ]] [[REF_AA]], [10 x i32]* [[REF_B]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED7]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, [10 x i32]* {{.+}})
diff --git a/test/OpenMP/target_parallel_codegen_registration.cpp b/test/OpenMP/target_parallel_codegen_registration.cpp
index d2cb1ec6f778..c9892eae36d6 100644
--- a/test/OpenMP/target_parallel_codegen_registration.cpp
+++ b/test/OpenMP/target_parallel_codegen_registration.cpp
@@ -6,6 +6,14 @@
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// Test target parallel codegen - host bc file has to be created first.
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s -check-prefix=TCHECK
@@ -16,9 +24,22 @@
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s -check-prefix=TCHECK
-// Check that no target code is emmitted if no omptests flag was provided.
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
+// Check that no target code is emitted if no omptests flag was provided.
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s -check-prefix=CHECK-NTARGET
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// SIMD-ONLY2-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -60,96 +81,96 @@
// We have 7 target regions
-// CHECK-DAG: {{@.+}} = private constant i8 0
-// TCHECK-NOT: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = weak constant i8 0
+// TCHECK-NOT: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
-// CHECK-NTARGET-NOT: private constant i8 0
+// CHECK-NTARGET-NOT: weak constant i8 0
// CHECK-NTARGET-NOT: private unnamed_addr constant [1 x i
// CHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// CHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY1:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// CHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY2:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// CHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY3:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// CHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY4:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// CHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY5:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// CHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY6:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// CHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY7:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// CHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY8:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// CHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY9:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// CHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY10:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// CHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY11:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// CHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY12:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// TCHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY1:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// TCHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY2:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// TCHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY3:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// TCHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY4:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// TCHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY5:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// TCHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY6:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// TCHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY7:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// TCHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY8:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// TCHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY9:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// TCHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY10:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// TCHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY11:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// TCHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY12:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
// CHECK: [[ENTEND:@.+]] = external constant [[ENTTY]]
@@ -163,7 +184,7 @@
// CHECK-SAME: { i32, void ()*, i8* } { i32 500, void ()* [[P500:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 501, void ()* [[P501:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 65535, void ()* [[PMAX:@[^,]+]], i8* null },
-// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
// CHECK-NTARGET: @llvm.global_ctors = appending global [3 x { i32, void ()*, i8* }] [
@@ -319,18 +340,18 @@ struct ST {
//CHECK-DAG: define internal void @[[NAME12]](
//CHECK-DAG: call void @[[NAME12]](
-//TCHECK-DAG: define void @[[NAME1]](
-//TCHECK-DAG: define void @[[NAME2]](
-//TCHECK-DAG: define void @[[NAME3]](
-//TCHECK-DAG: define void @[[NAME4]](
-//TCHECK-DAG: define void @[[NAME5]](
-//TCHECK-DAG: define void @[[NAME6]](
-//TCHECK-DAG: define void @[[NAME7]](
-//TCHECK-DAG: define void @[[NAME8]](
-//TCHECK-DAG: define void @[[NAME9]](
-//TCHECK-DAG: define void @[[NAME10]](
-//TCHECK-DAG: define void @[[NAME11]](
-//TCHECK-DAG: define void @[[NAME12]](
+//TCHECK-DAG: define weak void @[[NAME1]](
+//TCHECK-DAG: define weak void @[[NAME2]](
+//TCHECK-DAG: define weak void @[[NAME3]](
+//TCHECK-DAG: define weak void @[[NAME4]](
+//TCHECK-DAG: define weak void @[[NAME5]](
+//TCHECK-DAG: define weak void @[[NAME6]](
+//TCHECK-DAG: define weak void @[[NAME7]](
+//TCHECK-DAG: define weak void @[[NAME8]](
+//TCHECK-DAG: define weak void @[[NAME9]](
+//TCHECK-DAG: define weak void @[[NAME10]](
+//TCHECK-DAG: define weak void @[[NAME11]](
+//TCHECK-DAG: define weak void @[[NAME12]](
// CHECK-NTARGET-NOT: __tgt_target
// CHECK-NTARGET-NOT: __tgt_register_lib
@@ -372,7 +393,7 @@ struct ST {
//CHECK: ret void
//CHECK: declare i32 @__tgt_unregister_lib([[DSCTY]]*)
-//CHECK: define linkonce hidden void @[[REGFN]](i8*)
+//CHECK: define linkonce hidden void @[[REGFN]]()
//CHECK-SAME: comdat {
//CHECK: call i32 @__tgt_register_lib([[DSCTY]]* [[DESC]])
//CHECK: call i32 @__cxa_atexit(void (i8*)* @[[UNREGFN]], i8* bitcast ([[DSCTY]]* [[DESC]] to i8*),
@@ -411,31 +432,31 @@ int bar(int a){
// Check metadata is properly generated:
// CHECK: !omp_offload.info = !{!{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 195, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 245, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 261, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 267, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 278, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 284, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 406, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 290, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 284, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 290, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 278, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 220, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 216, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 266, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 282, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 288, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 299, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 305, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 427, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 311, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 305, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 311, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 299, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 241, i32 {{[0-9]+}}}
// TCHECK: !omp_offload.info = !{!{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 195, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 245, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 261, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 267, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 278, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 284, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 406, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 290, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 284, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 290, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 278, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 220, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 216, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 266, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 282, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 288, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 299, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 305, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 427, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 311, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 305, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 311, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 299, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 241, i32 {{[0-9]+}}}
#endif
diff --git a/test/OpenMP/target_parallel_codegen_registration_naming.cpp b/test/OpenMP/target_parallel_codegen_registration_naming.cpp
index 4b7940290d07..d2b88dc0729e 100644
--- a/test/OpenMP/target_parallel_codegen_registration_naming.cpp
+++ b/test/OpenMP/target_parallel_codegen_registration_naming.cpp
@@ -6,6 +6,14 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// Test target parallel codegen - host bc file has to be created first.
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s -check-prefix=TCHECK
@@ -16,6 +24,16 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s -check-prefix=TCHECK
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/target_parallel_debug_codegen.cpp b/test/OpenMP/target_parallel_debug_codegen.cpp
index 385f7a29cb8f..ebd761fb9699 100644
--- a/test/OpenMP/target_parallel_debug_codegen.cpp
+++ b/test/OpenMP/target_parallel_debug_codegen.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
-// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - -debug-info-kind=limited | FileCheck %s
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -fopenmp-cuda-mode -emit-llvm-bc %s -o %t-ppc-host.bc -fopenmp-version=45
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -fopenmp-cuda-mode -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - -debug-info-kind=limited -fopenmp-version=45 | FileCheck %s
// expected-no-diagnostics
int main() {
@@ -11,7 +11,7 @@ int main() {
int c[10][10][10];
#pragma omp target parallel firstprivate(a, b) map(tofrom \
: c) map(tofrom \
- : bb) if (a)
+ : bb) if (target:a)
{
int &f = c[1][1][1];
int &g = a;
@@ -54,7 +54,7 @@ int main() {
return 0;
}
-// CHECK: define internal void @__omp_offloading{{[^(]+}}([10 x [10 x [10 x i32]]] addrspace(1)* {{[^,]+}}, i32 {{[^,]+}}, [10 x [10 x i32]]* {{[^,]+}}, i8 addrspace(1)* noalias{{[^,]+}}, i1 {{[^)]+}})
+// CHECK: define internal void @__omp_offloading{{[^(]+}}([10 x [10 x [10 x i32]]] addrspace(1)* {{[^,]+}}, i32 {{[^,]+}}, [10 x [10 x i32]]* {{[^,]+}}, i8 addrspace(1)* noalias{{[^,]+}})
// CHECK: addrspacecast [10 x [10 x [10 x i32]]] addrspace(1)* %{{.+}} to [10 x [10 x [10 x i32]]]*
// CHECK: call void [[NONDEBUG_WRAPPER:.+]](i32* {{[^,]+}}, i32* {{[^,]+}}, [10 x [10 x [10 x i32]]]* {{[^,]+}}, i64 {{[^,]+}}, [10 x [10 x i32]]* {{[^,]+}}, i8* {{[^)]+}})
@@ -65,7 +65,7 @@ int main() {
// CHECK: addrspacecast [10 x [10 x [10 x i32]]]* %{{.+}} to [10 x [10 x [10 x i32]]] addrspace(1)*
// CHECK: call void [[DEBUG_PARALLEL]](i32* {{[^,]+}}, i32* {{[^,]+}}, [10 x [10 x [10 x i32]]] addrspace(1)* {{[^,]+}}, i32 {{[^,]+}}, [10 x [10 x i32]]* {{[^,]+}}, i8 addrspace(1)* {{[^)]+}})
-// CHECK: define void @__omp_offloading_{{[^(]+}}([10 x [10 x [10 x i32]]]* dereferenceable{{[^,]+}}, i64 {{[^,]+}}, [10 x [10 x i32]]* dereferenceable{{[^,]+}}, i8* dereferenceable{{[^)]+}})
+// CHECK: define weak void @__omp_offloading_{{[^(]+}}([10 x [10 x [10 x i32]]]* dereferenceable{{[^,]+}}, i64 {{[^,]+}}, [10 x [10 x i32]]* dereferenceable{{[^,]+}}, i8* dereferenceable{{[^)]+}})
// CHECK: addrspacecast [10 x [10 x [10 x i32]]]* %{{.+}} to [10 x [10 x [10 x i32]]] addrspace(1)*
// CHECK: call void @__omp_offloading_{{[^(]+}}([10 x [10 x [10 x i32]]] addrspace(1)* {{[^,]+}}, i32 {{[^,]+}}, [10 x [10 x i32]]* {{[^,]+}}, i8 addrspace(1)* {{[^)]+}})
@@ -83,7 +83,7 @@ int main() {
// CHECK: addrspacecast [10 x [10 x i32]]* %{{.+}} to [10 x [10 x i32]] addrspace(1)*
// CHECK: call void [[DEBUG_PARALLEL]](i32* {{[^,]+}}, i32* {{[^,]+}}, [10 x [10 x [10 x i32]]] addrspace(1)* {{[^,]+}}, i32 {{[^,]+}}, [10 x [10 x i32]] addrspace(1)* {{[^,]+}}, i8 addrspace(1)* {{[^)]+}})
-// CHECK: define void @__omp_offloading_{{[^(]+}}([10 x [10 x [10 x i32]]]* dereferenceable{{[^,]+}}, i64 {{[^,]+}}, [10 x [10 x i32]]* dereferenceable{{[^,]+}}, i8* dereferenceable{{[^)]+}})
+// CHECK: define weak void @__omp_offloading_{{[^(]+}}([10 x [10 x [10 x i32]]]* dereferenceable{{[^,]+}}, i64 {{[^,]+}}, [10 x [10 x i32]]* dereferenceable{{[^,]+}}, i8* dereferenceable{{[^)]+}})
// CHECK: addrspacecast [10 x [10 x [10 x i32]]]* %{{.+}} to [10 x [10 x [10 x i32]]] addrspace(1)*
// CHECK: addrspacecast [10 x [10 x i32]]* %{{.+}} to [10 x [10 x i32]] addrspace(1)*
// CHECK: call void @__omp_offloading_{{[^(]+}}([10 x [10 x [10 x i32]]] addrspace(1)* {{[^,]+}}, i32 {{[^,]+}}, [10 x [10 x i32]] addrspace(1)* {{[^,]+}}, i8 addrspace(1)* {{[^)]+}})
@@ -92,20 +92,20 @@ int main() {
// CHECK: addrspacecast [10 x [10 x [10 x i32]]] addrspace(1)* %{{.+}} to [10 x [10 x [10 x i32]]]*
// CHECK: addrspacecast i32 addrspace(1)* %{{.+}} to i32*
// CHECK: addrspacecast [10 x [10 x i32]] addrspace(1)* %{{.+}} to [10 x [10 x i32]]*
-// CHECK: call void [[NONDEBUG_WRAPPER:@.+]](i32* {{[^,]+}}, i32* {{[^,]+}}, [10 x [10 x [10 x i32]]]* {{[^,]+}}, i32* {{[^,]+}}, [10 x [10 x i32]]* {{[^,]+}}, i8* {{[^)]+}})
+// CHECK: call void @[[NONDEBUG_WRAPPER:.+]](i32* {{[^,]+}}, i32* {{[^,]+}}, [10 x [10 x [10 x i32]]]* {{[^,]+}}, i32* {{[^,]+}}, [10 x [10 x i32]]* {{[^,]+}}, i8* {{[^)]+}})
-// CHECK: define internal void [[DEBUG_PARALLEL:@.+]](i32* {{[^,]+}}, i32* {{[^,]+}}, [10 x [10 x [10 x i32]]] addrspace(1)* noalias{{[^,]+}}, i32 addrspace(1)* noalias{{[^,]+}}, [10 x [10 x i32]] addrspace(1)* noalias{{[^,]+}}, i8 addrspace(1)* noalias{{[^)]+}})
+// CHECK: define internal void @[[DEBUG_PARALLEL:.+]](i32* {{[^,]+}}, i32* {{[^,]+}}, [10 x [10 x [10 x i32]]] addrspace(1)* noalias{{[^,]+}}, i32 addrspace(1)* noalias{{[^,]+}}, [10 x [10 x i32]] addrspace(1)* noalias{{[^,]+}}, i8 addrspace(1)* noalias{{[^)]+}})
// CHECK: addrspacecast [10 x [10 x [10 x i32]]] addrspace(1)* %{{.+}} to [10 x [10 x [10 x i32]]]*
// CHECK: addrspacecast i32 addrspace(1)* %{{.+}} to i32*
// CHECK: addrspacecast [10 x [10 x i32]] addrspace(1)* %{{.+}} to [10 x [10 x i32]]*
-// CHECK: define internal void [[NONDEBUG_WRAPPER]](i32* {{[^,]+}}, i32* {{[^,]+}}, [10 x [10 x [10 x i32]]]* dereferenceable{{[^,]+}}, i32* dereferenceable{{[^,]+}}, [10 x [10 x i32]]* dereferenceable{{[^,]+}}, i8* dereferenceable{{[^)]+}})
+// CHECK: define internal void @[[NONDEBUG_WRAPPER]](i32* {{[^,]+}}, i32* {{[^,]+}}, [10 x [10 x [10 x i32]]]* dereferenceable{{[^,]+}}, i32* dereferenceable{{[^,]+}}, [10 x [10 x i32]]* dereferenceable{{[^,]+}}, i8* dereferenceable{{[^)]+}})
// CHECK: addrspacecast [10 x [10 x [10 x i32]]]* %{{.+}} to [10 x [10 x [10 x i32]]] addrspace(1)*
// CHECK: addrspacecast i32* %{{.+}} to i32 addrspace(1)*
// CHECK: addrspacecast [10 x [10 x i32]]* %{{.+}} to [10 x [10 x i32]] addrspace(1)*
-// CHECK: call void [[DEBUG_PARALLEL]](i32* {{[^,]+}}, i32* {{[^,]+}}, [10 x [10 x [10 x i32]]] addrspace(1)* {{[^,]+}}, i32 addrspace(1)* {{[^,]+}}, [10 x [10 x i32]] addrspace(1)* {{[^,]+}}, i8 addrspace(1)* {{[^)]+}})
+// CHECK: call void @[[DEBUG_PARALLEL]](i32* {{[^,]+}}, i32* {{[^,]+}}, [10 x [10 x [10 x i32]]] addrspace(1)* {{[^,]+}}, i32 addrspace(1)* {{[^,]+}}, [10 x [10 x i32]] addrspace(1)* {{[^,]+}}, i8 addrspace(1)* {{[^)]+}})
-// CHECK: define void @__omp_offloading_{{[^(]+}}([10 x [10 x [10 x i32]]]* dereferenceable{{[^,]+}}, i32* dereferenceable{{[^,]+}}, [10 x [10 x i32]]* dereferenceable{{[^,]+}}, i8* dereferenceable{{[^)]+}})
+// CHECK: define weak void @__omp_offloading_{{[^(]+}}([10 x [10 x [10 x i32]]]* dereferenceable{{[^,]+}}, i32* dereferenceable{{[^,]+}}, [10 x [10 x i32]]* dereferenceable{{[^,]+}}, i8* dereferenceable{{[^)]+}})
// CHECK: addrspacecast [10 x [10 x [10 x i32]]]* %{{.+}} to [10 x [10 x [10 x i32]]] addrspace(1)*
// CHECK: addrspacecast i32* %{{.+}} to i32 addrspace(1)*
// CHECK: addrspacecast [10 x [10 x i32]]* %{{.+}} to [10 x [10 x i32]] addrspace(1)*
@@ -116,8 +116,11 @@ int main() {
// CHECK: !DILocalVariable(name: ".bound_tid.",
// CHECK-SAME: DIFlagArtificial
// CHECK: !DILocalVariable(name: "c",
-// CHECK-SAMEi-NOT: DIFlagArtificial
+// CHECK-SAME: line: 11
// CHECK: !DILocalVariable(name: "a",
-// CHECK-SAMEi-NOT: DIFlagArtificial
+// CHECK-SAME: line: 9
// CHECK: !DILocalVariable(name: "b",
-// CHECK-SAMEi-NOT: DIFlagArtificial
+// CHECK-SAME: line: 10
+
+// CHECK-DAG: distinct !DISubprogram(name: "[[NONDEBUG_WRAPPER]]",
+// CHECK-DAG: distinct !DISubprogram(name: "[[DEBUG_PARALLEL]]",
diff --git a/test/OpenMP/target_parallel_default_messages.cpp b/test/OpenMP/target_parallel_default_messages.cpp
index cf497937f3e0..143a94c55326 100644
--- a/test/OpenMP/target_parallel_default_messages.cpp
+++ b/test/OpenMP/target_parallel_default_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo();
int main(int argc, char **argv) {
diff --git a/test/OpenMP/target_parallel_defaultmap_messages.cpp b/test/OpenMP/target_parallel_defaultmap_messages.cpp
index 49e7c30a7d15..33078a2ea7e8 100644
--- a/test/OpenMP/target_parallel_defaultmap_messages.cpp
+++ b/test/OpenMP/target_parallel_defaultmap_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_depend_codegen.cpp b/test/OpenMP/target_parallel_depend_codegen.cpp
new file mode 100644
index 000000000000..52d13a34d85a
--- /dev/null
+++ b/test/OpenMP/target_parallel_depend_codegen.cpp
@@ -0,0 +1,261 @@
+// Test host codegen.
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+// Test target codegen - host bc file has to be created first.
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+// CHECK-DAG: [[TT:%.+]] = type { i64, i8 }
+// CHECK-DAG: [[ENTTY:%.+]] = type { i8*, i8*, i[[SZ:32|64]], i32, i32 }
+// CHECK-DAG: [[DEVTY:%.+]] = type { i8*, i8*, [[ENTTY]]*, [[ENTTY]]* }
+// CHECK-DAG: [[DSCTY:%.+]] = type { i32, [[DEVTY]]*, [[ENTTY]]*, [[ENTTY]]* }
+
+// TCHECK: [[ENTTY:%.+]] = type { i8*, i8*, i{{32|64}}, i32, i32 }
+
+// CHECK-DAG: $[[REGFN:\.omp_offloading\..+]] = comdat
+
+// CHECK-DAG: [[SIZET:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 0, i[[SZ]] 4]
+// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 544, i64 800]
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = {{.*}}constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
+
+// Check if offloading descriptor is created.
+// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
+// CHECK: [[ENTEND:@.+]] = external constant [[ENTTY]]
+// CHECK: [[DEVBEGIN:@.+]] = external constant i8
+// CHECK: [[DEVEND:@.+]] = external constant i8
+// CHECK: [[IMAGES:@.+]] = internal unnamed_addr constant [1 x [[DEVTY]]] [{{.+}} { i8* [[DEVBEGIN]], i8* [[DEVEND]], [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }], comdat($[[REGFN]])
+// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
+
+// Check target registration is registered as a Ctor.
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
+
+
+template<typename tx, typename ty>
+struct TT{
+ tx X;
+ ty Y;
+};
+
+int global;
+extern int global;
+
+// CHECK: define {{.*}}[[FOO:@.+]](
+int foo(int n) {
+ int a = 0;
+ short aa = 0;
+ float b[10];
+ float bn[n];
+ double c[5][10];
+ double cn[5][n];
+ TT<long long, char> d;
+ static long *plocal;
+
+ // CHECK: [[ADD:%.+]] = add nsw i32
+ // CHECK: store i32 [[ADD]], i32* [[DEVICE_CAP:%.+]],
+ // CHECK: [[GEP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+ // CHECK: store i32 [[DEV]], i32* [[GEP]],
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* @0, i32 [[GTID:%.+]], i32 1, i[[SZ]] {{20|40}}, i[[SZ]] 4, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY0:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY0:%.+]]*
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 1
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 2
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 3
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call void @__kmpc_omp_wait_deps(%struct.ident_t* @0, i32 [[GTID]], i32 4, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: call void @__kmpc_omp_task_begin_if0(%struct.ident_t* @0, i32 [[GTID]], i8* [[TASK]])
+ // CHECK: call i32 [[TASK_ENTRY0]](i32 [[GTID]], [[TASK_TY0]]* [[BC_TASK]])
+ // CHECK: call void @__kmpc_omp_task_complete_if0(%struct.ident_t* @0, i32 [[GTID]], i8* [[TASK]])
+ #pragma omp target parallel device(global + a) depend(in: global) depend(out: a, b, cn[4])
+ {
+ }
+
+ // CHECK: [[ADD:%.+]] = add nsw i32
+ // CHECK: store i32 [[ADD]], i32* [[DEVICE_CAP:%.+]],
+
+ // CHECK: [[BOOL:%.+]] = icmp ne i32 %{{.+}}, 0
+ // CHECK: br i1 [[BOOL]], label %[[THEN:.+]], label %[[ELSE:.+]]
+ // CHECK: [[THEN]]:
+ // CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP:%.+]], i32 0, i32 0
+ // CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P:%.+]], i32 0, i32 0
+ // CHECK-DAG: [[CBPADDR0:%.+]] = bitcast i8** [[BPADDR0]] to i[[SZ]]**
+ // CHECK-DAG: [[CPADDR0:%.+]] = bitcast i8** [[PADDR0]] to i[[SZ]]**
+ // CHECK-DAG: store i[[SZ]]* [[BP0:%[^,]+]], i[[SZ]]** [[CBPADDR0]]
+ // CHECK-DAG: store i[[SZ]]* [[BP0]], i[[SZ]]** [[CPADDR0]]
+
+ // CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 1
+ // CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P]], i32 0, i32 1
+ // CHECK-DAG: [[CBPADDR1:%.+]] = bitcast i8** [[BPADDR1]] to i[[SZ]]*
+ // CHECK-DAG: [[CPADDR1:%.+]] = bitcast i8** [[PADDR1]] to i[[SZ]]*
+ // CHECK-DAG: store i[[SZ]] [[BP1:%[^,]+]], i[[SZ]]* [[CBPADDR1]]
+ // CHECK-DAG: store i[[SZ]] [[BP1]], i[[SZ]]* [[CPADDR1]]
+ // CHECK-DAG: getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 0
+ // CHECK-DAG: getelementptr inbounds [2 x i8*], [2 x i8*]* [[P]], i32 0, i32 0
+ // CHECK: [[GEP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+ // CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+ // CHECK: store i32 [[DEV]], i32* [[GEP]],
+
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* @0, i32 [[GTID]], i32 1, i[[SZ]] {{104|52}}, i[[SZ]] {{16|12}}, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY1_:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY1_:%.+]]*
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 1
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 2
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call i32 @__kmpc_omp_task_with_deps(%struct.ident_t* @0, i32 [[GTID]], i8* [[TASK]], i32 3, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: br label %[[EXIT:.+]]
+
+ // CHECK: [[ELSE]]:
+ // CHECK-NOT: getelementptr inbounds [2 x i8*], [2 x i8*]*
+ // CHECK: [[GEP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+ // CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+ // CHECK: store i32 [[DEV]], i32* [[GEP]],
+
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* @0, i32 [[GTID]], i32 1, i[[SZ]] {{56|28}}, i[[SZ]] {{16|12}}, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY1__:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY1__:%.+]]*
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 1
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 2
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call i32 @__kmpc_omp_task_with_deps(%struct.ident_t* @0, i32 [[GTID]], i8* [[TASK]], i32 3, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: br label %[[EXIT:.+]]
+ // CHECK: [[EXIT]]:
+
+ #pragma omp target parallel device(global + a) nowait depend(inout: global, a, bn) if(target:a)
+ {
+ static int local1;
+ *plocal = global;
+ local1 = global;
+ }
+
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* @0, i32 [[GTID]], i32 1, i[[SZ]] {{48|24}}, i[[SZ]] 4, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY2:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY2:%.+]]*
+ // CHECK: getelementptr inbounds [1 x %struct.kmp_depend_info], [1 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [1 x %struct.kmp_depend_info], [1 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call void @__kmpc_omp_wait_deps(%struct.ident_t* @0, i32 [[GTID]], i32 1, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: call void @__kmpc_omp_task_begin_if0(%struct.ident_t* @0, i32 [[GTID]], i8* [[TASK]])
+ // CHECK: call i32 [[TASK_ENTRY2]](i32 [[GTID]], [[TASK_TY2]]* [[BC_TASK]])
+ // CHECK: call void @__kmpc_omp_task_complete_if0(%struct.ident_t* @0, i32 [[GTID]], i8* [[TASK]])
+ #pragma omp target parallel if(0) firstprivate(global) depend(out:global)
+ {
+ global += 1;
+ }
+
+ return a;
+}
+
+// Check that the offloading functions are emitted and that the arguments are
+// correct and loaded correctly for the target regions in foo().
+
+// CHECK: define internal void [[HVT0:@.+]]()
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY0]](i32{{.*}}, [[TASK_TY0]]* noalias)
+// CHECK: store void (i8*, ...)* null, void (i8*, ...)** %
+// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 0
+// CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+// CHECK: [[DEVICE:%.+]] = sext i32 [[DEV]] to i64
+// CHECK: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 [[DEVICE]], i8* @{{[^,]+}}, i32 0, i8** null, i8** null, i[[SZ]]* null, i64* null, i32 1, i32 0)
+// CHECK-NEXT: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
+// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
+// CHECK: [[FAIL]]
+// CHECK: call void [[HVT0]]()
+// CHECK-NEXT: br label %[[END]]
+// CHECK: [[END]]
+// CHECK: ret i32 0
+
+// CHECK: define internal void [[HVT1:@.+]](i[[SZ]]* %{{.+}}, i[[SZ]] %{{.+}})
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY1_]](i32{{.*}}, [[TASK_TY1_]]* noalias)
+// CHECK: call void (i8*, ...) %
+// CHECK: [[SZT:%.+]] = getelementptr inbounds [2 x i[[SZ]]], [2 x i[[SZ]]]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+// CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+// CHECK: [[DEVICE:%.+]] = sext i32 [[DEV]] to i64
+// CHECK: [[RET:%.+]] = call i32 @__tgt_target_teams_nowait(i64 [[DEVICE]], i8* @{{[^,]+}}, i32 2, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SZT]], i64* getelementptr inbounds ([2 x i64], [2 x i64]* [[MAPT]], i32 0, i32 0), i32 1, i32 0)
+
+// CHECK: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
+// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
+// CHECK: [[FAIL]]
+// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
+// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
+// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
+// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
+// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
+// CHECK: [[BP1:%.+]] = load i[[SZ]], i[[SZ]]* [[BP1_PTR]],
+// CHECK: call void [[HVT1]](i[[SZ]]* [[BP0]], i[[SZ]] [[BP1]])
+// CHECK-NEXT: br label %[[END]]
+// CHECK: [[END]]
+// CHECK: ret i32 0
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY1__]](i32{{.*}}, [[TASK_TY1__]]* noalias)
+// CHECK: call void (i8*, ...) %
+// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
+// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
+// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
+// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
+// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
+// CHECK: [[BP1:%.+]] = load i[[SZ]], i[[SZ]]* [[BP1_PTR]],
+// CHECK: call void [[HVT1]](i[[SZ]]* [[BP0]], i[[SZ]] [[BP1]])
+// CHECK: ret i32 0
+
+// CHECK: define internal void [[HVT2:@.+]](i[[SZ]] %{{.+}})
+// Create stack storage and store argument in there.
+// CHECK: [[AA_ADDR:%.+]] = alloca i[[SZ]], align
+// CHECK: store i[[SZ]] %{{.+}}, i[[SZ]]* [[AA_ADDR]], align
+// CHECK-64: [[AA_CADDR:%.+]] = bitcast i[[SZ]]* [[AA_ADDR]] to i32*
+// CHECK-64: load i32, i32* [[AA_CADDR]], align
+// CHECK-32: load i32, i32* [[AA_ADDR]], align
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY2]](i32{{.*}}, [[TASK_TY2]]* noalias)
+// CHECK: call void (i8*, ...) %
+// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
+// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
+// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
+// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
+// CHECK: [[BP1:%.+]] = load i[[SZ]], i[[SZ]]* [[BP1_PTR]],
+// CHECK: call void [[HVT2]](i[[SZ]] [[BP1]])
+// CHECK: ret i32 0
+
+
+#endif
diff --git a/test/OpenMP/target_parallel_depend_messages.cpp b/test/OpenMP/target_parallel_depend_messages.cpp
index 24c69e95cc0a..746c2237066e 100644
--- a/test/OpenMP/target_parallel_depend_messages.cpp
+++ b/test/OpenMP/target_parallel_depend_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_device_messages.cpp b/test/OpenMP/target_parallel_device_messages.cpp
index 6c8d4c2e43ab..cc2525375316 100644
--- a/test/OpenMP/target_parallel_device_messages.cpp
+++ b/test/OpenMP/target_parallel_device_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_firstprivate_messages.cpp b/test/OpenMP/target_parallel_firstprivate_messages.cpp
index dd6825aa251f..02186e737b75 100644
--- a/test/OpenMP/target_parallel_firstprivate_messages.cpp
+++ b/test/OpenMP/target_parallel_firstprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_for_ast_print.cpp b/test/OpenMP/target_parallel_for_ast_print.cpp
index d5aa055842a7..c6c46c0031b1 100644
--- a/test/OpenMP/target_parallel_for_ast_print.cpp
+++ b/test/OpenMP/target_parallel_for_ast_print.cpp
@@ -1,6 +1,10 @@
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ast-print %s | FileCheck %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ast-print %s -Wno-openmp-target | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-target | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ast-print %s -Wno-openmp-target | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-target | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -35,7 +39,7 @@ public:
}
};
-// CHECK: #pragma omp target parallel for private(this->a) private(this->a) private(T::a)
+// CHECK: #pragma omp target parallel for private(this->a) private(this->a) private(T::a){{$}}
// CHECK: #pragma omp target parallel for private(this->a) private(this->a)
// CHECK: #pragma omp target parallel for private(this->a) private(this->a) private(this->S::a)
diff --git a/test/OpenMP/target_parallel_for_codegen.cpp b/test/OpenMP/target_parallel_for_codegen.cpp
index 58ac10bf9b2c..d541d14670a5 100644
--- a/test/OpenMP/target_parallel_for_codegen.cpp
+++ b/test/OpenMP/target_parallel_for_codegen.cpp
@@ -1,28 +1,46 @@
// Test host codegen.
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// Test target codegen - host bc file has to be created first.
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-64
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-64
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-32
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
-// CHECK-DAG: %ident_t = type { i32, i32, i32, i32, i8* }
+// CHECK-DAG: %struct.ident_t = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr constant %ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
// CHECK-DAG: [[TT:%.+]] = type { i64, i8 }
// CHECK-DAG: [[S1:%.+]] = type { double }
@@ -39,31 +57,31 @@
// sizes.
// CHECK-DAG: [[SIZET2:@.+]] = private unnamed_addr constant [3 x i[[SZ]]] [i[[SZ]] 2, i[[SZ]] 4, i[[SZ]] 4]
-// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [3 x i64] [i64 288, i64 288, i64 288]
+// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [3 x i64] [i64 800, i64 800, i64 800]
// CHECK-DAG: [[SIZET3:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2]
-// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [2 x i64] [i64 288, i64 288]
-// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [10 x i64] [i64 288, i64 547, i64 288, i64 547, i64 547, i64 288, i64 288, i64 547, i64 547, i64 288]
+// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [2 x i64] [i64 800, i64 800]
+// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [10 x i64] [i64 800, i64 547, i64 288, i64 547, i64 547, i64 288, i64 288, i64 547, i64 547, i64 800]
// CHECK-DAG: [[SIZET5:@.+]] = private unnamed_addr constant [3 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2, i[[SZ]] 40]
-// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [3 x i64] [i64 288, i64 288, i64 547]
+// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [3 x i64] [i64 800, i64 800, i64 547]
// CHECK-DAG: [[SIZET6:@.+]] = private unnamed_addr constant [4 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2, i[[SZ]] 1, i[[SZ]] 40]
-// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [4 x i64] [i64 288, i64 288, i64 288, i64 547]
-// CHECK-DAG: [[MAPT7:@.+]] = private unnamed_addr constant [5 x i64] [i64 547, i64 288, i64 288, i64 288, i64 547]
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK-NOT: @{{.+}} = constant [[ENTTY]]
+// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [4 x i64] [i64 800, i64 800, i64 800, i64 547]
+// CHECK-DAG: [[MAPT7:@.+]] = private unnamed_addr constant [6 x i64] [i64 32, i64 281474976711171, i64 800, i64 288, i64 288, i64 547]
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -74,7 +92,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx, typename ty>
@@ -200,13 +218,13 @@ int foo(int n) {
// CHECK-32: store i32 [[A_VAL]], i32* [[A_CADDR:%.+]],
// CHECK-32: [[A_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[A_CADDR]],
+ // CHECK: [[IF:%.+]] = icmp sgt i32 {{[^,]+}}, 20
+ // CHECK: br i1 [[IF]], label %[[TRY:[^,]+]], label %[[FAIL:[^,]+]]
+ // CHECK: [[TRY]]
// CHECK: [[BNSIZE:%.+]] = mul nuw i[[SZ]] [[VLA0:%.+]], 4
// CHECK: [[CNELEMSIZE2:%.+]] = mul nuw i[[SZ]] 5, [[VLA1:%.+]]
// CHECK: [[CNSIZE:%.+]] = mul nuw i[[SZ]] [[CNELEMSIZE2]], 8
- // CHECK: [[IF:%.+]] = icmp sgt i32 {{[^,]+}}, 20
- // CHECK: br i1 [[IF]], label %[[TRY:[^,]+]], label %[[FAIL:[^,]+]]
- // CHECK: [[TRY]]
// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 10, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([10 x i64], [10 x i64]* [[MAPT4]], i32 0, i32 0), i32 1, i32 0)
// CHECK-DAG: [[BPR]] = getelementptr inbounds [10 x i8*], [10 x i8*]* [[BP:%[^,]+]], i32 0, i32 0
// CHECK-DAG: [[PR]] = getelementptr inbounds [10 x i8*], [10 x i8*]* [[P:%[^,]+]], i32 0, i32 0
@@ -321,12 +339,12 @@ int foo(int n) {
// correct and loaded correctly for the target regions in foo().
// CHECK: define internal void [[HVT0]]()
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* [[OMP_OUTLINED:@.+]] to void (i32*, i32*, ...)*))
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* [[OMP_OUTLINED:@.+]] to void (i32*, i32*, ...)*))
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED]](i32* noalias %.global_tid., i32* noalias %.bound_tid.)
-// CHECK: call i32 @__kmpc_cancel(%ident_t* @
-// CHECK: call i32 @__kmpc_cancellationpoint(%ident_t* @
+// CHECK: call i32 @__kmpc_cancel(%struct.ident_t* @
+// CHECK: call i32 @__kmpc_cancellationpoint(%struct.ident_t* @
// CHECK: ret void
// CHECK: }
@@ -344,7 +362,7 @@ int foo(int n) {
// CHECK-64: store i32 [[AA]], i32* [[AA_C]], align
// CHECK-32: store i32 [[AA]], i32* [[AA_CASTED]], align
// CHECK: [[PARAM:%.+]] = load i[[SZ]], i[[SZ]]* [[AA_CASTED]], align
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 2, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i{{32|64}}{{[*]*}})* [[OMP_OUTLINED1:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM]], i{{32|64}}{{[*]*}} %{{.+}})
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 2, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i{{32|64}}{{[*]*}})* [[OMP_OUTLINED1:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM]], i{{32|64}}{{[*]*}} %{{.+}})
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED1]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}})
@@ -368,7 +386,7 @@ int foo(int n) {
// CHECK: [[AA_C:%.+]] = bitcast i[[SZ]]* [[AA_CASTED]] to i16*
// CHECK: store i16 [[AA]], i16* [[AA_C]], align
// CHECK: [[PARAM:%.+]] = load i[[SZ]], i[[SZ]]* [[AA_CASTED]], align
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]], i[[SZ]])* [[OMP_OUTLINED2:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM]], i[[SZ]] {{.+}}, i[[SZ]] {{.+}})
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]], i[[SZ]])* [[OMP_OUTLINED2:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM]], i[[SZ]] {{.+}}, i[[SZ]] {{.+}})
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED2]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}})
@@ -399,7 +417,7 @@ int foo(int n) {
// CHECK-DAG: store i16 [[AA]], i16* [[AA_C]], align
// CHECK-DAG: [[PARAM1:%.+]] = load i[[SZ]], i[[SZ]]* [[A_CASTED]], align
// CHECK-DAG: [[PARAM2:%.+]] = load i[[SZ]], i[[SZ]]* [[AA_CASTED]], align
-// CHECK-DAG: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 2, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]])* [[OMP_OUTLINED3:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM1]], i[[SZ]] [[PARAM2]])
+// CHECK-DAG: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 2, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]])* [[OMP_OUTLINED3:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM1]], i[[SZ]] [[PARAM2]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED3]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}})
@@ -452,7 +470,7 @@ int foo(int n) {
// CHECK-32-DAG:store i32 [[LOCAL_AV]], i32* [[LOCAL_A_CASTED]], align
// CHECK-DAG: [[REF_A:%.+]] = load i[[SZ]], i[[SZ]]* [[LOCAL_A_CASTED]],
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 10, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], [10 x float]*, i[[SZ]], float*, [5 x [10 x double]]*, i[[SZ]], i[[SZ]], double*, [[TT]]*, i[[SZ]])* [[OMP_OUTLINED4:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], [10 x float]* [[REF_B]], i[[SZ]] [[VAL_VLA1]], float* [[REF_BN]], [5 x [10 x double]]* [[REF_C]], i[[SZ]] [[VAL_VLA2]], i[[SZ]] [[VAL_VLA3]], double* [[REF_CN]], [[TT]]* [[REF_D]], i[[SZ]] %{{.+}})
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 10, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], [10 x float]*, i[[SZ]], float*, [5 x [10 x double]]*, i[[SZ]], i[[SZ]], double*, [[TT]]*, i[[SZ]])* [[OMP_OUTLINED4:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], [10 x float]* [[REF_B]], i[[SZ]] [[VAL_VLA1]], float* [[REF_BN]], [5 x [10 x double]]* [[REF_C]], i[[SZ]] [[VAL_VLA2]], i[[SZ]] [[VAL_VLA3]], double* [[REF_CN]], [[TT]]* [[REF_D]], i[[SZ]] %{{.+}})
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED4]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}}, [10 x float]* {{.+}}, i[[SZ]] %{{.+}}, float* {{.+}}, [5 x [10 x double]]* {{.+}}, i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, double* {{.+}}, [[TT]]* {{.+}})
@@ -537,32 +555,39 @@ int bar(int n){
// CHECK-64: store i32 %{{.+}}, i32* [[B_ADDR]],
// CHECK-64: [[B_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[B_CADDR]],
+// CHECK-32: store i32 %{{.+}}, i32* %__vla_expr
// CHECK-32: store i32 %{{.+}}, i32* [[B_ADDR:%.+]],
// CHECK-32: [[B_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[B_ADDR]],
+// CHECK: [[IF:%.+]] = icmp sgt i32 {{[^,]+}}, 60
+// CHECK: br i1 [[IF]], label %[[TRY:[^,]+]], label %[[FAIL:[^,]+]]
+// CHECK: [[TRY]]
// We capture 2 VLA sizes in this target region
// CHECK: [[CELEMSIZE2:%.+]] = mul nuw i[[SZ]] 2, [[VLA0:%.+]]
// CHECK: [[CSIZE:%.+]] = mul nuw i[[SZ]] [[CELEMSIZE2]], 2
-// CHECK: [[IF:%.+]] = icmp sgt i32 {{[^,]+}}, 60
-// CHECK: br i1 [[IF]], label %[[TRY:[^,]+]], label %[[FAIL:[^,]+]]
-// CHECK: [[TRY]]
-// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 5, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([5 x i64], [5 x i64]* [[MAPT7]], i32 0, i32 0), i32 1, i32 0)
-// CHECK-DAG: [[BPR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP:%.+]], i32 0, i32 0
-// CHECK-DAG: [[PR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P:%.+]], i32 0, i32 0
-// CHECK-DAG: [[SR]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0
-// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX0:[0-9]+]]
-// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX0]]
-// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX0]]
-// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX1:[0-9]+]]
-// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX1]]
-// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX1]]
-// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX2:[0-9]+]]
-// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX2]]
-// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX2]]
-// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]]
-// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX3]]
-// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX3]]
+// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 6, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([6 x i64], [6 x i64]* [[MAPT7]], i32 0, i32 0), i32 1, i32 0)
+// CHECK-DAG: [[BPR]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP:%.+]], i32 0, i32 0
+// CHECK-DAG: [[PR]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P:%.+]], i32 0, i32 0
+// CHECK-DAG: [[SR]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0
+// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX0:[0-9]+]]
+// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX0]]
+// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX0]]
+// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX1:[0-9]+]]
+// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX1]]
+// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX1]]
+// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX2:[0-9]+]]
+// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX2]]
+// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX2]]
+// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]]
+// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX3]]
+// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX3]]
+// CHECK-DAG: [[SADDR4:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX4:[0-9]+]]
+// CHECK-DAG: [[BPADDR4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX4]]
+// CHECK-DAG: [[PADDR4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX4]]
+// CHECK-DAG: [[SADDR5:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX5:[0-9]+]]
+// CHECK-DAG: [[BPADDR5:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX5]]
+// CHECK-DAG: [[PADDR5:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX5]]
// The names below are not necessarily consistent with the names used for the
// addresses above as some are repeated.
@@ -585,15 +610,21 @@ int bar(int n){
// CHECK-DAG: store i[[SZ]] 4, i[[SZ]]* {{%[^,]+}}
// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CBPADDR3:%.+]],
-// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CPADDR3:%.+]],
+// CHECK-DAG: store double* %{{.+}}, double** [[CPADDR3:%.+]],
// CHECK-DAG: [[CBPADDR3]] = bitcast i8** {{%[^,]+}} to [[S1]]**
-// CHECK-DAG: [[CPADDR3]] = bitcast i8** {{%[^,]+}} to [[S1]]**
+// CHECK-DAG: [[CPADDR3]] = bitcast i8** {{%[^,]+}} to double**
+// CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* {{%[^,]+}}
+
+// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CBPADDR4:%.+]],
+// CHECK-DAG: store double* %{{.+}}, double** [[CPADDR4:%.+]],
+// CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to [[S1]]**
+// CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to double**
// CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* {{%[^,]+}}
-// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR4:%.+]],
-// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR4:%.+]],
-// CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to i16**
-// CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to i16**
+// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR5:%.+]],
+// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR5:%.+]],
+// CHECK-DAG: [[CBPADDR5]] = bitcast i8** {{%[^,]+}} to i16**
+// CHECK-DAG: [[CPADDR5]] = bitcast i8** {{%[^,]+}} to i16**
// CHECK-DAG: store i[[SZ]] [[CSIZE]], i[[SZ]]* {{%[^,]+}}
// CHECK-NEXT: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
@@ -727,7 +758,7 @@ int bar(int n){
// CHECK-32-DAG:store i32 [[LOCAL_BV]], i32* [[LOCAL_B_CASTED]], align
// CHECK-DAG: [[REF_B:%.+]] = load i[[SZ]], i[[SZ]]* [[LOCAL_B_CASTED]],
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 5, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, [[S1]]*, i[[SZ]], i[[SZ]], i[[SZ]], i16*)* [[OMP_OUTLINED5:@.+]] to void (i32*, i32*, ...)*), [[S1]]* [[REF_THIS]], i[[SZ]] [[REF_B]], i[[SZ]] [[VAL_VLA1]], i[[SZ]] [[VAL_VLA2]], i16* [[REF_C]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 5, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, [[S1]]*, i[[SZ]], i[[SZ]], i[[SZ]], i16*)* [[OMP_OUTLINED5:@.+]] to void (i32*, i32*, ...)*), [[S1]]* [[REF_THIS]], i[[SZ]] [[REF_B]], i[[SZ]] [[VAL_VLA1]], i[[SZ]] [[VAL_VLA2]], i16* [[REF_C]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED5]](i32* noalias %.global_tid., i32* noalias %.bound_tid., [[S1]]* %{{.+}}, i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, i16* {{.+}})
@@ -770,7 +801,7 @@ int bar(int n){
// CHECK-DAG: store i8 [[CONV_AAA]], i8* [[CONV]], align
// CHECK-DAG: [[REF_AAA:%.+]] = load i[[SZ]], i[[SZ]]* [[LOCAL_AAA_CASTED]],
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 4, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]], i[[SZ]], [10 x i32]*)* [[OMP_OUTLINED6:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], i[[SZ]] [[REF_AA]], i[[SZ]] [[REF_AAA]], [10 x i32]* [[REF_B]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 4, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]], i[[SZ]], [10 x i32]*)* [[OMP_OUTLINED6:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], i[[SZ]] [[REF_AA]], i[[SZ]] [[REF_AAA]], [10 x i32]* [[REF_B]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED6]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, [10 x i32]* {{.+}})
@@ -803,7 +834,7 @@ int bar(int n){
// CHECK-DAG: store i16 [[CONV_AA]], i16* [[CONV]], align
// CHECK-DAG: [[REF_AA:%.+]] = load i[[SZ]], i[[SZ]]* [[LOCAL_AA_CASTED]],
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]], [10 x i32]*)* [[OMP_OUTLINED7:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], i[[SZ]] [[REF_AA]], [10 x i32]* [[REF_B]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]], [10 x i32]*)* [[OMP_OUTLINED7:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], i[[SZ]] [[REF_AA]], [10 x i32]* [[REF_B]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED7]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, [10 x i32]* {{.+}})
diff --git a/test/OpenMP/target_parallel_for_codegen_registration.cpp b/test/OpenMP/target_parallel_for_codegen_registration.cpp
index 24f0c06771ec..9a69ea994efc 100644
--- a/test/OpenMP/target_parallel_for_codegen_registration.cpp
+++ b/test/OpenMP/target_parallel_for_codegen_registration.cpp
@@ -6,6 +6,14 @@
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// Test target parallel for codegen - host bc file has to be created first.
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s -check-prefix=TCHECK
@@ -16,9 +24,22 @@
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s -check-prefix=TCHECK
-// Check that no target code is emmitted if no omptests flag was provided.
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
+// Check that no target code is emitted if no omptests flag was provided.
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s -check-prefix=CHECK-NTARGET
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// SIMD-ONLY2-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -60,96 +81,96 @@
// We have 7 target regions
-// CHECK-DAG: {{@.+}} = private constant i8 0
-// TCHECK-NOT: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = weak constant i8 0
+// TCHECK-NOT: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
-// CHECK-NTARGET-NOT: private constant i8 0
+// CHECK-NTARGET-NOT: weak constant i8 0
// CHECK-NTARGET-NOT: private unnamed_addr constant [1 x i
// CHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// CHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY1:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// CHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY2:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// CHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY3:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// CHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY4:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// CHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY5:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// CHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY6:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// CHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY7:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// CHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY8:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// CHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY9:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// CHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY10:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// CHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY11:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// CHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY12:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// TCHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY1:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// TCHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY2:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// TCHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY3:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// TCHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY4:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// TCHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY5:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// TCHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY6:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// TCHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY7:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// TCHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY8:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// TCHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY9:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// TCHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY10:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// TCHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY11:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// TCHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY12:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
// CHECK: [[ENTEND:@.+]] = external constant [[ENTTY]]
@@ -163,7 +184,7 @@
// CHECK-SAME: { i32, void ()*, i8* } { i32 500, void ()* [[P500:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 501, void ()* [[P501:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 65535, void ()* [[PMAX:@[^,]+]], i8* null },
-// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
// CHECK-NTARGET: @llvm.global_ctors = appending global [3 x { i32, void ()*, i8* }] [
@@ -328,18 +349,18 @@ struct ST {
//CHECK-DAG: define internal void @[[NAME12]](
//CHECK-DAG: call void @[[NAME12]](
-//TCHECK-DAG: define void @[[NAME1]](
-//TCHECK-DAG: define void @[[NAME2]](
-//TCHECK-DAG: define void @[[NAME3]](
-//TCHECK-DAG: define void @[[NAME4]](
-//TCHECK-DAG: define void @[[NAME5]](
-//TCHECK-DAG: define void @[[NAME6]](
-//TCHECK-DAG: define void @[[NAME7]](
-//TCHECK-DAG: define void @[[NAME8]](
-//TCHECK-DAG: define void @[[NAME9]](
-//TCHECK-DAG: define void @[[NAME10]](
-//TCHECK-DAG: define void @[[NAME11]](
-//TCHECK-DAG: define void @[[NAME12]](
+//TCHECK-DAG: define weak void @[[NAME1]](
+//TCHECK-DAG: define weak void @[[NAME2]](
+//TCHECK-DAG: define weak void @[[NAME3]](
+//TCHECK-DAG: define weak void @[[NAME4]](
+//TCHECK-DAG: define weak void @[[NAME5]](
+//TCHECK-DAG: define weak void @[[NAME6]](
+//TCHECK-DAG: define weak void @[[NAME7]](
+//TCHECK-DAG: define weak void @[[NAME8]](
+//TCHECK-DAG: define weak void @[[NAME9]](
+//TCHECK-DAG: define weak void @[[NAME10]](
+//TCHECK-DAG: define weak void @[[NAME11]](
+//TCHECK-DAG: define weak void @[[NAME12]](
// CHECK-NTARGET-NOT: __tgt_target
// CHECK-NTARGET-NOT: __tgt_register_lib
@@ -381,7 +402,7 @@ struct ST {
//CHECK: ret void
//CHECK: declare i32 @__tgt_unregister_lib([[DSCTY]]*)
-//CHECK: define linkonce hidden void @[[REGFN]](i8*)
+//CHECK: define linkonce hidden void @[[REGFN]]()
//CHECK-SAME: comdat {
//CHECK: call i32 @__tgt_register_lib([[DSCTY]]* [[DESC]])
//CHECK: call i32 @__cxa_atexit(void (i8*)* @[[UNREGFN]], i8* bitcast ([[DSCTY]]* [[DESC]] to i8*),
@@ -421,31 +442,31 @@ int bar(int a){
// Check metadata is properly generated:
// CHECK: !omp_offload.info = !{!{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 195, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 247, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 265, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 272, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 284, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 291, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 415, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 298, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 291, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 298, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 284, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 221, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 216, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 268, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 286, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 293, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 305, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 312, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 436, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 319, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 312, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 319, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 305, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 242, i32 {{[0-9]+}}}
// TCHECK: !omp_offload.info = !{!{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 195, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 247, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 265, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 272, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 284, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 291, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 415, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 298, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 291, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 298, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 284, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 221, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 216, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 268, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 286, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 293, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 305, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 312, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 436, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 319, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 312, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 319, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 305, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 242, i32 {{[0-9]+}}}
#endif
diff --git a/test/OpenMP/target_parallel_for_codegen_registration_naming.cpp b/test/OpenMP/target_parallel_for_codegen_registration_naming.cpp
index b42b5b55a505..db7f9ec392ff 100644
--- a/test/OpenMP/target_parallel_for_codegen_registration_naming.cpp
+++ b/test/OpenMP/target_parallel_for_codegen_registration_naming.cpp
@@ -6,6 +6,14 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// Test target parallel for codegen - host bc file has to be created first.
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s -check-prefix=TCHECK
@@ -16,6 +24,16 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s -check-prefix=TCHECK
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/target_parallel_for_collapse_messages.cpp b/test/OpenMP/target_parallel_for_collapse_messages.cpp
index 6163b52fd21c..d8ebdda81aa6 100644
--- a/test/OpenMP/target_parallel_for_collapse_messages.cpp
+++ b/test/OpenMP/target_parallel_for_collapse_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_for_debug_codegen.cpp b/test/OpenMP/target_parallel_for_debug_codegen.cpp
index 0e0bb7e85306..55671f4d0d03 100644
--- a/test/OpenMP/target_parallel_for_debug_codegen.cpp
+++ b/test/OpenMP/target_parallel_for_debug_codegen.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
-// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - -debug-info-kind=limited | FileCheck %s
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -fopenmp-cuda-mode -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -fopenmp-cuda-mode -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - -debug-info-kind=limited | FileCheck %s
// expected-no-diagnostics
int main() {
@@ -58,14 +58,14 @@ int main() {
// CHECK: addrspacecast [10 x [10 x [10 x i32]]] addrspace(1)* %{{.+}} to [10 x [10 x [10 x i32]]]*
// CHECK: call void [[NONDEBUG_WRAPPER:.+]](i32* {{[^,]+}}, i32* {{[^,]+}}, [10 x [10 x [10 x i32]]]* {{[^,]+}}, i64 {{[^,]+}}, [10 x [10 x i32]]* {{[^,]+}}, i8* {{[^)]+}})
-// CHECK: define internal void [[DEBUG_PARALLEL:@.+]](i32* {{[^,]+}}, i32* {{[^,]+}}, [10 x [10 x [10 x i32]]] addrspace(1)* noalias{{[^,]+}}, i32 {{[^,]+}}, [10 x [10 x i32]]* noalias{{[^,]+}}, i8 addrspace(1)* noalias{{[^)]+}})
+// CHECK: define internal void [[DEBUG_PARALLEL:.+]](i32* {{[^,]+}}, i32* {{[^,]+}}, [10 x [10 x [10 x i32]]] addrspace(1)* noalias{{[^,]+}}, i32 {{[^,]+}}, [10 x [10 x i32]]* noalias{{[^,]+}}, i8 addrspace(1)* noalias{{[^)]+}})
// CHECK: addrspacecast [10 x [10 x [10 x i32]]] addrspace(1)* %{{.+}} to [10 x [10 x [10 x i32]]]*
// CHECK: define internal void [[NONDEBUG_WRAPPER]](i32* {{[^,]+}}, i32* {{[^,]+}}, [10 x [10 x [10 x i32]]]* dereferenceable{{[^,]+}}, i64 {{[^,]+}}, [10 x [10 x i32]]* dereferenceable{{[^,]+}}, i8* dereferenceable{{[^)]+}})
// CHECK: addrspacecast [10 x [10 x [10 x i32]]]* %{{.+}} to [10 x [10 x [10 x i32]]] addrspace(1)*
// CHECK: call void [[DEBUG_PARALLEL]](i32* {{[^,]+}}, i32* {{[^,]+}}, [10 x [10 x [10 x i32]]] addrspace(1)* {{[^,]+}}, i32 {{[^,]+}}, [10 x [10 x i32]]* {{[^,]+}}, i8 addrspace(1)* {{[^)]+}})
-// CHECK: define void @__omp_offloading_{{[^(]+}}([10 x [10 x [10 x i32]]]* dereferenceable{{[^,]+}}, i64 {{[^,]+}}, [10 x [10 x i32]]* dereferenceable{{[^,]+}}, i8* dereferenceable{{[^)]+}})
+// CHECK: define weak void @__omp_offloading_{{[^(]+}}([10 x [10 x [10 x i32]]]* dereferenceable{{[^,]+}}, i64 {{[^,]+}}, [10 x [10 x i32]]* dereferenceable{{[^,]+}}, i8* dereferenceable{{[^)]+}})
// CHECK: addrspacecast [10 x [10 x [10 x i32]]]* %{{.+}} to [10 x [10 x [10 x i32]]] addrspace(1)*
// CHECK: call void @__omp_offloading_{{[^(]+}}([10 x [10 x [10 x i32]]] addrspace(1)* {{[^,]+}}, i32 {{[^,]+}}, [10 x [10 x i32]]* {{[^,]+}}, i8 addrspace(1)* {{[^)]+}})
@@ -83,7 +83,7 @@ int main() {
// CHECK: addrspacecast [10 x [10 x i32]]* %{{.+}} to [10 x [10 x i32]] addrspace(1)*
// CHECK: call void [[DEBUG_PARALLEL]](i32* {{[^,]+}}, i32* {{[^,]+}}, [10 x [10 x [10 x i32]]] addrspace(1)* {{[^,]+}}, i32 {{[^,]+}}, [10 x [10 x i32]] addrspace(1)* {{[^,]+}}, i8 addrspace(1)* {{[^)]+}})
-// CHECK: define void @__omp_offloading_{{[^(]+}}([10 x [10 x [10 x i32]]]* dereferenceable{{[^,]+}}, i64 {{[^,]+}}, [10 x [10 x i32]]* dereferenceable{{[^,]+}}, i8* dereferenceable{{[^)]+}})
+// CHECK: define weak void @__omp_offloading_{{[^(]+}}([10 x [10 x [10 x i32]]]* dereferenceable{{[^,]+}}, i64 {{[^,]+}}, [10 x [10 x i32]]* dereferenceable{{[^,]+}}, i8* dereferenceable{{[^)]+}})
// CHECK: addrspacecast [10 x [10 x [10 x i32]]]* %{{.+}} to [10 x [10 x [10 x i32]]] addrspace(1)*
// CHECK: addrspacecast [10 x [10 x i32]]* %{{.+}} to [10 x [10 x i32]] addrspace(1)*
// CHECK: call void @__omp_offloading_{{[^(]+}}([10 x [10 x [10 x i32]]] addrspace(1)* {{[^,]+}}, i32 {{[^,]+}}, [10 x [10 x i32]] addrspace(1)* {{[^,]+}}, i8 addrspace(1)* {{[^)]+}})
@@ -92,22 +92,24 @@ int main() {
// CHECK: addrspacecast [10 x [10 x [10 x i32]]] addrspace(1)* %{{.+}} to [10 x [10 x [10 x i32]]]*
// CHECK: addrspacecast i32 addrspace(1)* %{{.+}} to i32*
// CHECK: addrspacecast [10 x [10 x i32]] addrspace(1)* %{{.+}} to [10 x [10 x i32]]*
-// CHECK: call void [[NONDEBUG_WRAPPER:@.+]](i32* {{[^,]+}}, i32* {{[^,]+}}, [10 x [10 x [10 x i32]]]* {{[^,]+}}, i32* {{[^,]+}}, [10 x [10 x i32]]* {{[^,]+}}, i8* {{[^)]+}})
+// CHECK: call void @[[NONDEBUG_WRAPPER:.+]](i32* {{[^,]+}}, i32* {{[^,]+}}, [10 x [10 x [10 x i32]]]* {{[^,]+}}, i32* {{[^,]+}}, [10 x [10 x i32]]* {{[^,]+}}, i8* {{[^)]+}})
-// CHECK: define internal void [[DEBUG_PARALLEL:@.+]](i32* {{[^,]+}}, i32* {{[^,]+}}, [10 x [10 x [10 x i32]]] addrspace(1)* noalias{{[^,]+}}, i32 addrspace(1)* noalias{{[^,]+}}, [10 x [10 x i32]] addrspace(1)* noalias{{[^,]+}}, i8 addrspace(1)* noalias{{[^)]+}})
+// CHECK: define internal void @[[DEBUG_PARALLEL:.+]](i32* {{[^,]+}}, i32* {{[^,]+}}, [10 x [10 x [10 x i32]]] addrspace(1)* noalias{{[^,]+}}, i32 addrspace(1)* noalias{{[^,]+}}, [10 x [10 x i32]] addrspace(1)* noalias{{[^,]+}}, i8 addrspace(1)* noalias{{[^)]+}})
// CHECK: addrspacecast [10 x [10 x [10 x i32]]] addrspace(1)* %{{.+}} to [10 x [10 x [10 x i32]]]*
// CHECK: addrspacecast i32 addrspace(1)* %{{.+}} to i32*
// CHECK: addrspacecast [10 x [10 x i32]] addrspace(1)* %{{.+}} to [10 x [10 x i32]]*
-// CHECK: define internal void [[NONDEBUG_WRAPPER]](i32* {{[^,]+}}, i32* {{[^,]+}}, [10 x [10 x [10 x i32]]]* dereferenceable{{[^,]+}}, i32* dereferenceable{{[^,]+}}, [10 x [10 x i32]]* dereferenceable{{[^,]+}}, i8* dereferenceable{{[^)]+}})
+// CHECK: define internal void @[[NONDEBUG_WRAPPER]](i32* {{[^,]+}}, i32* {{[^,]+}}, [10 x [10 x [10 x i32]]]* dereferenceable{{[^,]+}}, i32* dereferenceable{{[^,]+}}, [10 x [10 x i32]]* dereferenceable{{[^,]+}}, i8* dereferenceable{{[^)]+}})
// CHECK: addrspacecast [10 x [10 x [10 x i32]]]* %{{.+}} to [10 x [10 x [10 x i32]]] addrspace(1)*
// CHECK: addrspacecast i32* %{{.+}} to i32 addrspace(1)*
// CHECK: addrspacecast [10 x [10 x i32]]* %{{.+}} to [10 x [10 x i32]] addrspace(1)*
-// CHECK: call void [[DEBUG_PARALLEL]](i32* {{[^,]+}}, i32* {{[^,]+}}, [10 x [10 x [10 x i32]]] addrspace(1)* {{[^,]+}}, i32 addrspace(1)* {{[^,]+}}, [10 x [10 x i32]] addrspace(1)* {{[^,]+}}, i8 addrspace(1)* {{[^)]+}})
+// CHECK: call void @[[DEBUG_PARALLEL]](i32* {{[^,]+}}, i32* {{[^,]+}}, [10 x [10 x [10 x i32]]] addrspace(1)* {{[^,]+}}, i32 addrspace(1)* {{[^,]+}}, [10 x [10 x i32]] addrspace(1)* {{[^,]+}}, i8 addrspace(1)* {{[^)]+}})
-// CHECK: define void @__omp_offloading_{{[^(]+}}([10 x [10 x [10 x i32]]]* dereferenceable{{[^,]+}}, i32* dereferenceable{{[^,]+}}, [10 x [10 x i32]]* dereferenceable{{[^,]+}}, i8* dereferenceable{{[^)]+}})
+// CHECK: define weak void @__omp_offloading_{{[^(]+}}([10 x [10 x [10 x i32]]]* dereferenceable{{[^,]+}}, i32* dereferenceable{{[^,]+}}, [10 x [10 x i32]]* dereferenceable{{[^,]+}}, i8* dereferenceable{{[^)]+}})
// CHECK: addrspacecast [10 x [10 x [10 x i32]]]* %{{.+}} to [10 x [10 x [10 x i32]]] addrspace(1)*
// CHECK: addrspacecast i32* %{{.+}} to i32 addrspace(1)*
// CHECK: addrspacecast [10 x [10 x i32]]* %{{.+}} to [10 x [10 x i32]] addrspace(1)*
// CHECK: call void @__omp_offloading_{{[^(]+}}([10 x [10 x [10 x i32]]] addrspace(1)* {{[^,]+}}, i32 addrspace(1)* {{[^,]+}}, [10 x [10 x i32]] addrspace(1)* {{[^,]+}}, i8 addrspace(1)* {{[^)]+}})
+// CHECK-DAG: distinct !DISubprogram(name: "[[NONDEBUG_WRAPPER]]",
+// CHECK-DAG: distinct !DISubprogram(name: "[[DEBUG_PARALLEL]]",
diff --git a/test/OpenMP/target_parallel_for_default_messages.cpp b/test/OpenMP/target_parallel_for_default_messages.cpp
index c1f04f4f6e40..94049cd37baf 100644
--- a/test/OpenMP/target_parallel_for_default_messages.cpp
+++ b/test/OpenMP/target_parallel_for_default_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo();
int main(int argc, char **argv) {
diff --git a/test/OpenMP/target_parallel_for_defaultmap_messages.cpp b/test/OpenMP/target_parallel_for_defaultmap_messages.cpp
index 24973edd2bda..9f97b60ff41c 100644
--- a/test/OpenMP/target_parallel_for_defaultmap_messages.cpp
+++ b/test/OpenMP/target_parallel_for_defaultmap_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_for_depend_codegen.cpp b/test/OpenMP/target_parallel_for_depend_codegen.cpp
new file mode 100644
index 000000000000..c6e71375f18c
--- /dev/null
+++ b/test/OpenMP/target_parallel_for_depend_codegen.cpp
@@ -0,0 +1,261 @@
+// Test host codegen.
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+// Test target codegen - host bc file has to be created first.
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+// CHECK-DAG: [[TT:%.+]] = type { i64, i8 }
+// CHECK-DAG: [[ENTTY:%.+]] = type { i8*, i8*, i[[SZ:32|64]], i32, i32 }
+// CHECK-DAG: [[DEVTY:%.+]] = type { i8*, i8*, [[ENTTY]]*, [[ENTTY]]* }
+// CHECK-DAG: [[DSCTY:%.+]] = type { i32, [[DEVTY]]*, [[ENTTY]]*, [[ENTTY]]* }
+
+// TCHECK: [[ENTTY:%.+]] = type { i8*, i8*, i{{32|64}}, i32, i32 }
+
+// CHECK-DAG: $[[REGFN:\.omp_offloading\..+]] = comdat
+
+// CHECK-DAG: [[SIZET:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 0, i[[SZ]] 4]
+// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 544, i64 800]
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = {{.*}}constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
+
+// Check if offloading descriptor is created.
+// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
+// CHECK: [[ENTEND:@.+]] = external constant [[ENTTY]]
+// CHECK: [[DEVBEGIN:@.+]] = external constant i8
+// CHECK: [[DEVEND:@.+]] = external constant i8
+// CHECK: [[IMAGES:@.+]] = internal unnamed_addr constant [1 x [[DEVTY]]] [{{.+}} { i8* [[DEVBEGIN]], i8* [[DEVEND]], [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }], comdat($[[REGFN]])
+// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
+
+// Check target registration is registered as a Ctor.
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
+
+
+template<typename tx, typename ty>
+struct TT{
+ tx X;
+ ty Y;
+};
+
+int global;
+extern int global;
+
+// CHECK: define {{.*}}[[FOO:@.+]](
+int foo(int n) {
+ int a = 0;
+ short aa = 0;
+ float b[10];
+ float bn[n];
+ double c[5][10];
+ double cn[5][n];
+ TT<long long, char> d;
+ static long *plocal;
+
+ // CHECK: [[ADD:%.+]] = add nsw i32
+ // CHECK: store i32 [[ADD]], i32* [[DEVICE_CAP:%.+]],
+ // CHECK: [[GEP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+ // CHECK: store i32 [[DEV]], i32* [[GEP]],
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[IN:@.+]], i32 [[GTID:%.+]], i32 1, i[[SZ]] {{20|40}}, i[[SZ]] 4, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY0:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY0:%.+]]*
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 1
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 2
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 3
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call void @__kmpc_omp_wait_deps(%struct.ident_t* [[IN]], i32 [[GTID]], i32 4, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: call void @__kmpc_omp_task_begin_if0(%struct.ident_t* [[IN]], i32 [[GTID]], i8* [[TASK]])
+ // CHECK: call i32 [[TASK_ENTRY0]](i32 [[GTID]], [[TASK_TY0]]* [[BC_TASK]])
+ // CHECK: call void @__kmpc_omp_task_complete_if0(%struct.ident_t* [[IN]], i32 [[GTID]], i8* [[TASK]])
+ #pragma omp target parallel for device(global + a) depend(in: global) depend(out: a, b, cn[4])
+ for (int i = 0; i < 10; ++i) {
+ }
+
+ // CHECK: [[ADD:%.+]] = add nsw i32
+ // CHECK: store i32 [[ADD]], i32* [[DEVICE_CAP:%.+]],
+
+ // CHECK: [[BOOL:%.+]] = icmp ne i32 %{{.+}}, 0
+ // CHECK: br i1 [[BOOL]], label %[[THEN:.+]], label %[[ELSE:.+]]
+ // CHECK: [[THEN]]:
+ // CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP:%.+]], i32 0, i32 0
+ // CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P:%.+]], i32 0, i32 0
+ // CHECK-DAG: [[CBPADDR0:%.+]] = bitcast i8** [[BPADDR0]] to i[[SZ]]**
+ // CHECK-DAG: [[CPADDR0:%.+]] = bitcast i8** [[PADDR0]] to i[[SZ]]**
+ // CHECK-DAG: store i[[SZ]]* [[BP0:%[^,]+]], i[[SZ]]** [[CBPADDR0]]
+ // CHECK-DAG: store i[[SZ]]* [[BP0]], i[[SZ]]** [[CPADDR0]]
+
+ // CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 1
+ // CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P]], i32 0, i32 1
+ // CHECK-DAG: [[CBPADDR1:%.+]] = bitcast i8** [[BPADDR1]] to i[[SZ]]*
+ // CHECK-DAG: [[CPADDR1:%.+]] = bitcast i8** [[PADDR1]] to i[[SZ]]*
+ // CHECK-DAG: store i[[SZ]] [[BP1:%[^,]+]], i[[SZ]]* [[CBPADDR1]]
+ // CHECK-DAG: store i[[SZ]] [[BP1]], i[[SZ]]* [[CPADDR1]]
+ // CHECK-DAG: getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 0
+ // CHECK-DAG: getelementptr inbounds [2 x i8*], [2 x i8*]* [[P]], i32 0, i32 0
+ // CHECK: [[GEP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+ // CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+ // CHECK: store i32 [[DEV]], i32* [[GEP]],
+
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[IN]], i32 [[GTID]], i32 1, i[[SZ]] {{104|52}}, i[[SZ]] {{16|12}}, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY1_:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY1_:%.+]]*
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 1
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 2
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call i32 @__kmpc_omp_task_with_deps(%struct.ident_t* [[IN]], i32 [[GTID]], i8* [[TASK]], i32 3, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: br label %[[EXIT:.+]]
+
+ // CHECK: [[ELSE]]:
+ // CHECK-NOT: getelementptr inbounds [2 x i8*], [2 x i8*]*
+ // CHECK: [[GEP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+ // CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+ // CHECK: store i32 [[DEV]], i32* [[GEP]],
+
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[IN]], i32 [[GTID]], i32 1, i[[SZ]] {{56|28}}, i[[SZ]] {{16|12}}, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY1__:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY1__:%.+]]*
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 1
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 2
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call i32 @__kmpc_omp_task_with_deps(%struct.ident_t* [[IN]], i32 [[GTID]], i8* [[TASK]], i32 3, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: br label %[[EXIT:.+]]
+ // CHECK: [[EXIT]]:
+
+ #pragma omp target parallel for device(global + a) nowait depend(inout: global, a, bn) if(target:a)
+ for (int i = 0; i < *plocal; ++i) {
+ static int local1;
+ *plocal = global;
+ local1 = global;
+ }
+
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[IN]], i32 [[GTID]], i32 1, i[[SZ]] {{48|24}}, i[[SZ]] 4, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY2:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY2:%.+]]*
+ // CHECK: getelementptr inbounds [1 x %struct.kmp_depend_info], [1 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [1 x %struct.kmp_depend_info], [1 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call void @__kmpc_omp_wait_deps(%struct.ident_t* [[IN]], i32 [[GTID]], i32 1, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: call void @__kmpc_omp_task_begin_if0(%struct.ident_t* [[IN]], i32 [[GTID]], i8* [[TASK]])
+ // CHECK: call i32 [[TASK_ENTRY2]](i32 [[GTID]], [[TASK_TY2]]* [[BC_TASK]])
+ // CHECK: call void @__kmpc_omp_task_complete_if0(%struct.ident_t* [[IN]], i32 [[GTID]], i8* [[TASK]])
+ #pragma omp target parallel for if(0) firstprivate(global) depend(out:global)
+ for (int i = 0; i < global; ++i) {
+ global += 1;
+ }
+
+ return a;
+}
+
+// Check that the offloading functions are emitted and that the arguments are
+// correct and loaded correctly for the target regions in foo().
+
+// CHECK: define internal void [[HVT0:@.+]]()
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY0]](i32{{.*}}, [[TASK_TY0]]* noalias)
+// CHECK: store void (i8*, ...)* null, void (i8*, ...)** %
+// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 0
+// CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+// CHECK: [[DEVICE:%.+]] = sext i32 [[DEV]] to i64
+// CHECK: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 [[DEVICE]], i8* @{{[^,]+}}, i32 0, i8** null, i8** null, i[[SZ]]* null, i64* null, i32 1, i32 0)
+// CHECK-NEXT: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
+// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
+// CHECK: [[FAIL]]
+// CHECK: call void [[HVT0]]()
+// CHECK-NEXT: br label %[[END]]
+// CHECK: [[END]]
+// CHECK: ret i32 0
+
+// CHECK: define internal void [[HVT1:@.+]](i[[SZ]]* %{{.+}}, i[[SZ]] %{{.+}})
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY1_]](i32{{.*}}, [[TASK_TY1_]]* noalias)
+// CHECK: call void (i8*, ...) %
+// CHECK: [[SZT:%.+]] = getelementptr inbounds [2 x i[[SZ]]], [2 x i[[SZ]]]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+// CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+// CHECK: [[DEVICE:%.+]] = sext i32 [[DEV]] to i64
+// CHECK: [[RET:%.+]] = call i32 @__tgt_target_teams_nowait(i64 [[DEVICE]], i8* @{{[^,]+}}, i32 2, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SZT]], i64* getelementptr inbounds ([2 x i64], [2 x i64]* [[MAPT]], i32 0, i32 0), i32 1, i32 0)
+
+// CHECK: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
+// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
+// CHECK: [[FAIL]]
+// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
+// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
+// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
+// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
+// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
+// CHECK: [[BP1:%.+]] = load i[[SZ]], i[[SZ]]* [[BP1_PTR]],
+// CHECK: call void [[HVT1]](i[[SZ]]* [[BP0]], i[[SZ]] [[BP1]])
+// CHECK-NEXT: br label %[[END]]
+// CHECK: [[END]]
+// CHECK: ret i32 0
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY1__]](i32{{.*}}, [[TASK_TY1__]]* noalias)
+// CHECK: call void (i8*, ...) %
+// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
+// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
+// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
+// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
+// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
+// CHECK: [[BP1:%.+]] = load i[[SZ]], i[[SZ]]* [[BP1_PTR]],
+// CHECK: call void [[HVT1]](i[[SZ]]* [[BP0]], i[[SZ]] [[BP1]])
+// CHECK: ret i32 0
+
+// CHECK: define internal void [[HVT2:@.+]](i[[SZ]] %{{.+}})
+// Create stack storage and store argument in there.
+// CHECK: [[AA_ADDR:%.+]] = alloca i[[SZ]], align
+// CHECK: store i[[SZ]] %{{.+}}, i[[SZ]]* [[AA_ADDR]], align
+// CHECK-64: [[AA_CADDR:%.+]] = bitcast i[[SZ]]* [[AA_ADDR]] to i32*
+// CHECK-64: load i32, i32* [[AA_CADDR]], align
+// CHECK-32: load i32, i32* [[AA_ADDR]], align
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY2]](i32{{.*}}, [[TASK_TY2]]* noalias)
+// CHECK: call void (i8*, ...) %
+// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
+// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
+// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
+// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
+// CHECK: [[BP1:%.+]] = load i[[SZ]], i[[SZ]]* [[BP1_PTR]],
+// CHECK: call void [[HVT2]](i[[SZ]] [[BP1]])
+// CHECK: ret i32 0
+
+
+#endif
diff --git a/test/OpenMP/target_parallel_for_depend_messages.cpp b/test/OpenMP/target_parallel_for_depend_messages.cpp
index 19872566161a..d644711b5e27 100644
--- a/test/OpenMP/target_parallel_for_depend_messages.cpp
+++ b/test/OpenMP/target_parallel_for_depend_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_for_device_messages.cpp b/test/OpenMP/target_parallel_for_device_messages.cpp
index 16a21ba4d662..bacf57d99ccc 100644
--- a/test/OpenMP/target_parallel_for_device_messages.cpp
+++ b/test/OpenMP/target_parallel_for_device_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_for_firstprivate_messages.cpp b/test/OpenMP/target_parallel_for_firstprivate_messages.cpp
index 36bfe25e9468..350bb89108b8 100644
--- a/test/OpenMP/target_parallel_for_firstprivate_messages.cpp
+++ b/test/OpenMP/target_parallel_for_firstprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_for_if_messages.cpp b/test/OpenMP/target_parallel_for_if_messages.cpp
index 4acf4b8d4a77..2bc433cf421d 100644
--- a/test/OpenMP/target_parallel_for_if_messages.cpp
+++ b/test/OpenMP/target_parallel_for_if_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_for_is_device_ptr_ast_print.cpp b/test/OpenMP/target_parallel_for_is_device_ptr_ast_print.cpp
index eaa0941a388e..fe600101b8ff 100644
--- a/test/OpenMP/target_parallel_for_is_device_ptr_ast_print.cpp
+++ b/test/OpenMP/target_parallel_for_is_device_ptr_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -59,7 +63,7 @@ struct SA {
// CHECK-NEXT: int aa[10];
// CHECK-NEXT: arr &raa = this->aa;
// CHECK-NEXT: func(
-// CHECK-NEXT: #pragma omp target parallel for is_device_ptr(this->k)
+// CHECK-NEXT: #pragma omp target parallel for is_device_ptr(this->k){{$}}
// CHECK-NEXT: for (int i = 0; i < 100; i++)
// CHECK-NEXT: foo();
// CHECK-NEXT: #pragma omp target parallel for is_device_ptr(this->z)
diff --git a/test/OpenMP/target_parallel_for_is_device_ptr_messages.cpp b/test/OpenMP/target_parallel_for_is_device_ptr_messages.cpp
index b3b33bf91ed0..3e675ead2acc 100644
--- a/test/OpenMP/target_parallel_for_is_device_ptr_messages.cpp
+++ b/test/OpenMP/target_parallel_for_is_device_ptr_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -std=c++11 -verify -fopenmp %s
+// RUN: %clang_cc1 -std=c++11 -verify -fopenmp-simd %s
+
struct ST {
int *a;
};
diff --git a/test/OpenMP/target_parallel_for_lastprivate_messages.cpp b/test/OpenMP/target_parallel_for_lastprivate_messages.cpp
index ee703a1ce32e..0ff2c722f7de 100644
--- a/test/OpenMP/target_parallel_for_lastprivate_messages.cpp
+++ b/test/OpenMP/target_parallel_for_lastprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_for_linear_messages.cpp b/test/OpenMP/target_parallel_for_linear_messages.cpp
index 36e897d5946e..b7224b538f4c 100644
--- a/test/OpenMP/target_parallel_for_linear_messages.cpp
+++ b/test/OpenMP/target_parallel_for_linear_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
namespace X {
int x;
};
diff --git a/test/OpenMP/target_parallel_for_loop_messages.cpp b/test/OpenMP/target_parallel_for_loop_messages.cpp
index d7c189116bf0..416cbfa1f3c3 100644
--- a/test/OpenMP/target_parallel_for_loop_messages.cpp
+++ b/test/OpenMP/target_parallel_for_loop_messages.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s -Wno-openmp-target
class S {
int a;
diff --git a/test/OpenMP/target_parallel_for_map_messages.cpp b/test/OpenMP/target_parallel_for_map_messages.cpp
index f3e1c616b406..f4f98dfc4915 100644
--- a/test/OpenMP/target_parallel_for_map_messages.cpp
+++ b/test/OpenMP/target_parallel_for_map_messages.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s -Wno-openmp-target
void foo() {
}
diff --git a/test/OpenMP/target_parallel_for_messages.cpp b/test/OpenMP/target_parallel_for_messages.cpp
index 173025c01ce7..6bf4ac280764 100644
--- a/test/OpenMP/target_parallel_for_messages.cpp
+++ b/test/OpenMP/target_parallel_for_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -std=c++11 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -std=c++11 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_for_misc_messages.c b/test/OpenMP/target_parallel_for_misc_messages.c
index cfe83f130107..44629e10c0c0 100644
--- a/test/OpenMP/target_parallel_for_misc_messages.c
+++ b/test/OpenMP/target_parallel_for_misc_messages.c
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -verify %s
+
// expected-error@+1 {{unexpected OpenMP directive '#pragma omp target parallel for'}}
#pragma omp target parallel for
diff --git a/test/OpenMP/target_parallel_for_nowait_messages.cpp b/test/OpenMP/target_parallel_for_nowait_messages.cpp
index 06d22969c4a4..2fb875b9de9f 100644
--- a/test/OpenMP/target_parallel_for_nowait_messages.cpp
+++ b/test/OpenMP/target_parallel_for_nowait_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_for_num_threads_messages.cpp b/test/OpenMP/target_parallel_for_num_threads_messages.cpp
index 915cfb1dfc9e..b47c96b82b55 100644
--- a/test/OpenMP/target_parallel_for_num_threads_messages.cpp
+++ b/test/OpenMP/target_parallel_for_num_threads_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_for_ordered_messages.cpp b/test/OpenMP/target_parallel_for_ordered_messages.cpp
index 72bb6e34912d..002e8e9a5c74 100644
--- a/test/OpenMP/target_parallel_for_ordered_messages.cpp
+++ b/test/OpenMP/target_parallel_for_ordered_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_for_private_messages.cpp b/test/OpenMP/target_parallel_for_private_messages.cpp
index 1d6381a1d5d3..dae4f17cccb8 100644
--- a/test/OpenMP/target_parallel_for_private_messages.cpp
+++ b/test/OpenMP/target_parallel_for_private_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
@@ -43,7 +45,7 @@ public:
S5(int v) : a(v) {}
S5 &operator=(S5 &s) {
#pragma omp target parallel for private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}}
- for (int k = 0; k < s.a; ++k)
+ for (int k = 0; k < s.a; ++k) // expected-warning {{Non-trivial type 'S5' is mapped, only trivial types are guaranteed to be mapped correctly}}
++s.a;
return *this;
}
diff --git a/test/OpenMP/target_parallel_for_proc_bind_messages.cpp b/test/OpenMP/target_parallel_for_proc_bind_messages.cpp
index eeb232aeca81..60d5b74fdc00 100644
--- a/test/OpenMP/target_parallel_for_proc_bind_messages.cpp
+++ b/test/OpenMP/target_parallel_for_proc_bind_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo();
int main(int argc, char **argv) {
diff --git a/test/OpenMP/target_parallel_for_reduction_messages.cpp b/test/OpenMP/target_parallel_for_reduction_messages.cpp
index 9f1f68f25f83..5cc40e9b9924 100644
--- a/test/OpenMP/target_parallel_for_reduction_messages.cpp
+++ b/test/OpenMP/target_parallel_for_reduction_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 150 -o - %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 150 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_for_schedule_messages.cpp b/test/OpenMP/target_parallel_for_schedule_messages.cpp
index 075e1df7827c..544ace25e408 100644
--- a/test/OpenMP/target_parallel_for_schedule_messages.cpp
+++ b/test/OpenMP/target_parallel_for_schedule_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_for_simd_aligned_messages.cpp b/test/OpenMP/target_parallel_for_simd_aligned_messages.cpp
index 655f90642f5b..54a6a9e8de26 100644
--- a/test/OpenMP/target_parallel_for_simd_aligned_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_aligned_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -x c++ -std=c++11 -verify -fopenmp %s
+// RUN: %clang_cc1 -x c++ -std=c++11 -verify -fopenmp-simd %s
+
struct B {
static int ib[20]; // expected-note 0 {{'B::ib' declared here}}
static constexpr int bfoo() { return 8; }
diff --git a/test/OpenMP/target_parallel_for_simd_ast_print.cpp b/test/OpenMP/target_parallel_for_simd_ast_print.cpp
index 8f0ed97d5cd9..de7fb12ab9cc 100644
--- a/test/OpenMP/target_parallel_for_simd_ast_print.cpp
+++ b/test/OpenMP/target_parallel_for_simd_ast_print.cpp
@@ -1,6 +1,10 @@
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ast-print %s | FileCheck %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ast-print %s -Wno-openmp-target | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-target | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ast-print %s -Wno-openmp-target | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-target | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -35,7 +39,7 @@ public:
}
};
-// CHECK: #pragma omp target parallel for simd private(this->a) private(this->a) private(T::a)
+// CHECK: #pragma omp target parallel for simd private(this->a) private(this->a) private(T::a){{$}}
// CHECK: #pragma omp target parallel for simd private(this->a) private(this->a)
// CHECK: #pragma omp target parallel for simd private(this->a) private(this->a) private(this->S::a)
diff --git a/test/OpenMP/target_parallel_for_simd_codegen.cpp b/test/OpenMP/target_parallel_for_simd_codegen.cpp
index d168214df35f..012b2f86be48 100644
--- a/test/OpenMP/target_parallel_for_simd_codegen.cpp
+++ b/test/OpenMP/target_parallel_for_simd_codegen.cpp
@@ -1,27 +1,45 @@
// Test host codegen.
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// Test target codegen - host bc file has to be created first.
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-64
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-64
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-32
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
-// CHECK-DAG: %ident_t = type { i32, i32, i32, i32, i8* }
+// CHECK-DAG: %struct.ident_t = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr constant %ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
// CHECK-DAG: [[TT:%.+]] = type { i64, i8 }
// CHECK-DAG: [[S1:%.+]] = type { double }
@@ -38,31 +56,31 @@
// sizes.
// CHECK-DAG: [[SIZET2:@.+]] = private unnamed_addr constant [3 x i[[SZ]]] [i[[SZ]] 2, i[[SZ]] 4, i[[SZ]] 4]
-// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [3 x i64] [i64 288, i64 288, i64 288]
+// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [3 x i64] [i64 800, i64 800, i64 800]
// CHECK-DAG: [[SIZET3:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2]
-// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [2 x i64] [i64 288, i64 288]
-// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [10 x i64] [i64 288, i64 547, i64 288, i64 547, i64 547, i64 288, i64 288, i64 547, i64 547, i64 288]
+// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [2 x i64] [i64 800, i64 800]
+// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [10 x i64] [i64 800, i64 547, i64 288, i64 547, i64 547, i64 288, i64 288, i64 547, i64 547, i64 800]
// CHECK-DAG: [[SIZET5:@.+]] = private unnamed_addr constant [3 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2, i[[SZ]] 40]
-// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [3 x i64] [i64 288, i64 288, i64 547]
+// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [3 x i64] [i64 800, i64 800, i64 547]
// CHECK-DAG: [[SIZET6:@.+]] = private unnamed_addr constant [4 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2, i[[SZ]] 1, i[[SZ]] 40]
-// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [4 x i64] [i64 288, i64 288, i64 288, i64 547]
-// CHECK-DAG: [[MAPT7:@.+]] = private unnamed_addr constant [5 x i64] [i64 547, i64 288, i64 288, i64 288, i64 547]
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK-NOT: @{{.+}} = constant [[ENTTY]]
+// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [4 x i64] [i64 800, i64 800, i64 800, i64 547]
+// CHECK-DAG: [[MAPT7:@.+]] = private unnamed_addr constant [6 x i64] [i64 32, i64 281474976711171, i64 800, i64 288, i64 288, i64 547]
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -73,7 +91,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx, typename ty>
@@ -197,13 +215,13 @@ int foo(int n) {
// CHECK-32: store i32 [[A_VAL]], i32* [[A_CADDR:%.+]],
// CHECK-32: [[A_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[A_CADDR]],
+ // CHECK: [[IF:%.+]] = icmp sgt i32 {{[^,]+}}, 20
+ // CHECK: br i1 [[IF]], label %[[TRY:[^,]+]], label %[[FAIL:[^,]+]]
+ // CHECK: [[TRY]]
// CHECK: [[BNSIZE:%.+]] = mul nuw i[[SZ]] [[VLA0:%.+]], 4
// CHECK: [[CNELEMSIZE2:%.+]] = mul nuw i[[SZ]] 5, [[VLA1:%.+]]
// CHECK: [[CNSIZE:%.+]] = mul nuw i[[SZ]] [[CNELEMSIZE2]], 8
- // CHECK: [[IF:%.+]] = icmp sgt i32 {{[^,]+}}, 20
- // CHECK: br i1 [[IF]], label %[[TRY:[^,]+]], label %[[FAIL:[^,]+]]
- // CHECK: [[TRY]]
// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 10, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([10 x i64], [10 x i64]* [[MAPT4]], i32 0, i32 0), i32 1, i32 0)
// CHECK-DAG: [[BPR]] = getelementptr inbounds [10 x i8*], [10 x i8*]* [[BP:%[^,]+]], i32 0, i32 0
// CHECK-DAG: [[PR]] = getelementptr inbounds [10 x i8*], [10 x i8*]* [[P:%[^,]+]], i32 0, i32 0
@@ -318,7 +336,7 @@ int foo(int n) {
// correct and loaded correctly for the target regions in foo().
// CHECK: define internal void [[HVT0]]()
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* [[OMP_OUTLINED:@.+]] to void (i32*, i32*, ...)*))
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* [[OMP_OUTLINED:@.+]] to void (i32*, i32*, ...)*))
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED]](i32* noalias %.global_tid., i32* noalias %.bound_tid.)
@@ -340,7 +358,7 @@ int foo(int n) {
// CHECK-64: store i32 [[AA]], i32* [[AA_C]], align
// CHECK-32: store i32 [[AA]], i32* [[AA_CASTED]], align
// CHECK: [[PARAM:%.+]] = load i[[SZ]], i[[SZ]]* [[AA_CASTED]], align
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 2, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i{{32|64}}{{[*]*}})* [[OMP_OUTLINED1:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM]], i{{32|64}}{{[*]*}} %{{.+}})
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 2, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i{{32|64}}{{[*]*}})* [[OMP_OUTLINED1:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM]], i{{32|64}}{{[*]*}} %{{.+}})
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED1]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}})
@@ -366,7 +384,7 @@ int foo(int n) {
// CHECK: [[AA_C:%.+]] = bitcast i[[SZ]]* [[AA_CASTED]] to i16*
// CHECK: store i16 [[AA]], i16* [[AA_C]], align
// CHECK: [[PARAM:%.+]] = load i[[SZ]], i[[SZ]]* [[AA_CASTED]], align
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]], i[[SZ]])* [[OMP_OUTLINED2:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM]], i[[SZ]] {{.+}}, i[[SZ]] {{.+}})
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]], i[[SZ]])* [[OMP_OUTLINED2:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM]], i[[SZ]] {{.+}}, i[[SZ]] {{.+}})
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED2]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}})
@@ -398,7 +416,7 @@ int foo(int n) {
// CHECK-DAG: store i16 [[AA]], i16* [[AA_C]], align
// CHECK-DAG: [[PARAM1:%.+]] = load i[[SZ]], i[[SZ]]* [[A_CASTED]], align
// CHECK-DAG: [[PARAM2:%.+]] = load i[[SZ]], i[[SZ]]* [[AA_CASTED]], align
-// CHECK-DAG: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 2, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]])* [[OMP_OUTLINED3:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM1]], i[[SZ]] [[PARAM2]])
+// CHECK-DAG: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 2, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]])* [[OMP_OUTLINED3:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM1]], i[[SZ]] [[PARAM2]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED3]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}})
@@ -452,7 +470,7 @@ int foo(int n) {
// CHECK-32-DAG:store i32 [[LOCAL_AV]], i32* [[LOCAL_A_CASTED]], align
// CHECK-DAG: [[REF_A:%.+]] = load i[[SZ]], i[[SZ]]* [[LOCAL_A_CASTED]],
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 10, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], [10 x float]*, i[[SZ]], float*, [5 x [10 x double]]*, i[[SZ]], i[[SZ]], double*, [[TT]]*, i[[SZ]])* [[OMP_OUTLINED4:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], [10 x float]* [[REF_B]], i[[SZ]] [[VAL_VLA1]], float* [[REF_BN]], [5 x [10 x double]]* [[REF_C]], i[[SZ]] [[VAL_VLA2]], i[[SZ]] [[VAL_VLA3]], double* [[REF_CN]], [[TT]]* [[REF_D]], i[[SZ]] %{{.+}})
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 10, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], [10 x float]*, i[[SZ]], float*, [5 x [10 x double]]*, i[[SZ]], i[[SZ]], double*, [[TT]]*, i[[SZ]])* [[OMP_OUTLINED4:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], [10 x float]* [[REF_B]], i[[SZ]] [[VAL_VLA1]], float* [[REF_BN]], [5 x [10 x double]]* [[REF_C]], i[[SZ]] [[VAL_VLA2]], i[[SZ]] [[VAL_VLA3]], double* [[REF_CN]], [[TT]]* [[REF_D]], i[[SZ]] %{{.+}})
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED4]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}}, [10 x float]* {{.+}}, i[[SZ]] %{{.+}}, float* {{.+}}, [5 x [10 x double]]* {{.+}}, i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, double* {{.+}}, [[TT]]* {{.+}})
@@ -537,32 +555,39 @@ int bar(int n){
// CHECK-64: store i32 %{{.+}}, i32* [[B_ADDR]],
// CHECK-64: [[B_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[B_CADDR]],
+// CHECK-32: store i32 %{{.+}}, i32* %__vla_expr
// CHECK-32: store i32 %{{.+}}, i32* [[B_ADDR:%.+]],
// CHECK-32: [[B_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[B_ADDR]],
+// CHECK: [[IF:%.+]] = icmp sgt i32 {{[^,]+}}, 60
+// CHECK: br i1 [[IF]], label %[[TRY:[^,]+]], label %[[FAIL:[^,]+]]
+// CHECK: [[TRY]]
// We capture 2 VLA sizes in this target region
// CHECK: [[CELEMSIZE2:%.+]] = mul nuw i[[SZ]] 2, [[VLA0:%.+]]
// CHECK: [[CSIZE:%.+]] = mul nuw i[[SZ]] [[CELEMSIZE2]], 2
-// CHECK: [[IF:%.+]] = icmp sgt i32 {{[^,]+}}, 60
-// CHECK: br i1 [[IF]], label %[[TRY:[^,]+]], label %[[FAIL:[^,]+]]
-// CHECK: [[TRY]]
-// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 5, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([5 x i64], [5 x i64]* [[MAPT7]], i32 0, i32 0), i32 1, i32 0)
-// CHECK-DAG: [[BPR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP:%.+]], i32 0, i32 0
-// CHECK-DAG: [[PR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P:%.+]], i32 0, i32 0
-// CHECK-DAG: [[SR]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0
-// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX0:[0-9]+]]
-// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX0]]
-// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX0]]
-// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX1:[0-9]+]]
-// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX1]]
-// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX1]]
-// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX2:[0-9]+]]
-// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX2]]
-// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX2]]
-// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]]
-// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX3]]
-// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX3]]
+// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 6, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([6 x i64], [6 x i64]* [[MAPT7]], i32 0, i32 0), i32 1, i32 0)
+// CHECK-DAG: [[BPR]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP:%.+]], i32 0, i32 0
+// CHECK-DAG: [[PR]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P:%.+]], i32 0, i32 0
+// CHECK-DAG: [[SR]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0
+// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX0:[0-9]+]]
+// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX0]]
+// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX0]]
+// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX1:[0-9]+]]
+// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX1]]
+// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX1]]
+// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX2:[0-9]+]]
+// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX2]]
+// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX2]]
+// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]]
+// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX3]]
+// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX3]]
+// CHECK-DAG: [[SADDR4:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX4:[0-9]+]]
+// CHECK-DAG: [[BPADDR4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX4]]
+// CHECK-DAG: [[PADDR4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX4]]
+// CHECK-DAG: [[SADDR5:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX5:[0-9]+]]
+// CHECK-DAG: [[BPADDR5:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX5]]
+// CHECK-DAG: [[PADDR5:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX5]]
// The names below are not necessarily consistent with the names used for the
// addresses above as some are repeated.
@@ -585,15 +610,21 @@ int bar(int n){
// CHECK-DAG: store i[[SZ]] 4, i[[SZ]]* {{%[^,]+}}
// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CBPADDR3:%.+]],
-// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CPADDR3:%.+]],
+// CHECK-DAG: store double* %{{.+}}, double** [[CPADDR3:%.+]],
// CHECK-DAG: [[CBPADDR3]] = bitcast i8** {{%[^,]+}} to [[S1]]**
-// CHECK-DAG: [[CPADDR3]] = bitcast i8** {{%[^,]+}} to [[S1]]**
+// CHECK-DAG: [[CPADDR3]] = bitcast i8** {{%[^,]+}} to double**
+// CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* {{%[^,]+}}
+
+// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CBPADDR4:%.+]],
+// CHECK-DAG: store double* %{{.+}}, double** [[CPADDR4:%.+]],
+// CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to [[S1]]**
+// CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to double**
// CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* {{%[^,]+}}
-// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR4:%.+]],
-// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR4:%.+]],
-// CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to i16**
-// CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to i16**
+// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR5:%.+]],
+// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR5:%.+]],
+// CHECK-DAG: [[CBPADDR5]] = bitcast i8** {{%[^,]+}} to i16**
+// CHECK-DAG: [[CPADDR5]] = bitcast i8** {{%[^,]+}} to i16**
// CHECK-DAG: store i[[SZ]] [[CSIZE]], i[[SZ]]* {{%[^,]+}}
// CHECK-NEXT: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
@@ -727,7 +758,7 @@ int bar(int n){
// CHECK-32-DAG:store i32 [[LOCAL_BV]], i32* [[LOCAL_B_CASTED]], align
// CHECK-DAG: [[REF_B:%.+]] = load i[[SZ]], i[[SZ]]* [[LOCAL_B_CASTED]],
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 5, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, [[S1]]*, i[[SZ]], i[[SZ]], i[[SZ]], i16*)* [[OMP_OUTLINED5:@.+]] to void (i32*, i32*, ...)*), [[S1]]* [[REF_THIS]], i[[SZ]] [[REF_B]], i[[SZ]] [[VAL_VLA1]], i[[SZ]] [[VAL_VLA2]], i16* [[REF_C]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 5, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, [[S1]]*, i[[SZ]], i[[SZ]], i[[SZ]], i16*)* [[OMP_OUTLINED5:@.+]] to void (i32*, i32*, ...)*), [[S1]]* [[REF_THIS]], i[[SZ]] [[REF_B]], i[[SZ]] [[VAL_VLA1]], i[[SZ]] [[VAL_VLA2]], i16* [[REF_C]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED5]](i32* noalias %.global_tid., i32* noalias %.bound_tid., [[S1]]* %{{.+}}, i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, i16* {{.+}})
@@ -770,7 +801,7 @@ int bar(int n){
// CHECK-DAG: store i8 [[CONV_AAA]], i8* [[CONV]], align
// CHECK-DAG: [[REF_AAA:%.+]] = load i[[SZ]], i[[SZ]]* [[LOCAL_AAA_CASTED]],
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 4, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]], i[[SZ]], [10 x i32]*)* [[OMP_OUTLINED6:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], i[[SZ]] [[REF_AA]], i[[SZ]] [[REF_AAA]], [10 x i32]* [[REF_B]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 4, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]], i[[SZ]], [10 x i32]*)* [[OMP_OUTLINED6:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], i[[SZ]] [[REF_AA]], i[[SZ]] [[REF_AAA]], [10 x i32]* [[REF_B]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED6]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, [10 x i32]* {{.+}})
@@ -803,7 +834,7 @@ int bar(int n){
// CHECK-DAG: store i16 [[CONV_AA]], i16* [[CONV]], align
// CHECK-DAG: [[REF_AA:%.+]] = load i[[SZ]], i[[SZ]]* [[LOCAL_AA_CASTED]],
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]], [10 x i32]*)* [[OMP_OUTLINED7:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], i[[SZ]] [[REF_AA]], [10 x i32]* [[REF_B]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]], [10 x i32]*)* [[OMP_OUTLINED7:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], i[[SZ]] [[REF_AA]], [10 x i32]* [[REF_B]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED7]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, [10 x i32]* {{.+}})
diff --git a/test/OpenMP/target_parallel_for_simd_codegen_registration.cpp b/test/OpenMP/target_parallel_for_simd_codegen_registration.cpp
index 5cc9d7015cbd..5973c8d182f1 100644
--- a/test/OpenMP/target_parallel_for_simd_codegen_registration.cpp
+++ b/test/OpenMP/target_parallel_for_simd_codegen_registration.cpp
@@ -6,6 +6,14 @@
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// Test target parallel for simd codegen - host bc file has to be created first.
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s -check-prefix=TCHECK
@@ -16,9 +24,22 @@
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s -check-prefix=TCHECK
-// Check that no target code is emmitted if no omptests flag was provided.
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
+// Check that no target code is emitted if no omptests flag was provided.
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s -check-prefix=CHECK-NTARGET
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// SIMD-ONLY2-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -60,96 +81,96 @@
// We have 7 target regions
-// CHECK-DAG: {{@.+}} = private constant i8 0
-// TCHECK-NOT: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = weak constant i8 0
+// TCHECK-NOT: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
-// CHECK-NTARGET-NOT: private constant i8 0
+// CHECK-NTARGET-NOT: weak constant i8 0
// CHECK-NTARGET-NOT: private unnamed_addr constant [1 x i
// CHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// CHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY1:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// CHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY2:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// CHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY3:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// CHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY4:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// CHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY5:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// CHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY6:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// CHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY7:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// CHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY8:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// CHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY9:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// CHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY10:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// CHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY11:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// CHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY12:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// TCHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY1:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// TCHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY2:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// TCHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY3:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// TCHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY4:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// TCHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY5:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// TCHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY6:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// TCHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY7:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// TCHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY8:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// TCHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY9:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// TCHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY10:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// TCHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY11:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// TCHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY12:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
// CHECK: [[ENTEND:@.+]] = external constant [[ENTTY]]
@@ -163,7 +184,7 @@
// CHECK-SAME: { i32, void ()*, i8* } { i32 500, void ()* [[P500:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 501, void ()* [[P501:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 65535, void ()* [[PMAX:@[^,]+]], i8* null },
-// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
// CHECK-NTARGET: @llvm.global_ctors = appending global [3 x { i32, void ()*, i8* }] [
@@ -328,18 +349,18 @@ struct ST {
//CHECK-DAG: define internal void @[[NAME12]](
//CHECK-DAG: call void @[[NAME12]](
-//TCHECK-DAG: define void @[[NAME1]](
-//TCHECK-DAG: define void @[[NAME2]](
-//TCHECK-DAG: define void @[[NAME3]](
-//TCHECK-DAG: define void @[[NAME4]](
-//TCHECK-DAG: define void @[[NAME5]](
-//TCHECK-DAG: define void @[[NAME6]](
-//TCHECK-DAG: define void @[[NAME7]](
-//TCHECK-DAG: define void @[[NAME8]](
-//TCHECK-DAG: define void @[[NAME9]](
-//TCHECK-DAG: define void @[[NAME10]](
-//TCHECK-DAG: define void @[[NAME11]](
-//TCHECK-DAG: define void @[[NAME12]](
+//TCHECK-DAG: define weak void @[[NAME1]](
+//TCHECK-DAG: define weak void @[[NAME2]](
+//TCHECK-DAG: define weak void @[[NAME3]](
+//TCHECK-DAG: define weak void @[[NAME4]](
+//TCHECK-DAG: define weak void @[[NAME5]](
+//TCHECK-DAG: define weak void @[[NAME6]](
+//TCHECK-DAG: define weak void @[[NAME7]](
+//TCHECK-DAG: define weak void @[[NAME8]](
+//TCHECK-DAG: define weak void @[[NAME9]](
+//TCHECK-DAG: define weak void @[[NAME10]](
+//TCHECK-DAG: define weak void @[[NAME11]](
+//TCHECK-DAG: define weak void @[[NAME12]](
// CHECK-NTARGET-NOT: __tgt_target
// CHECK-NTARGET-NOT: __tgt_register_lib
@@ -381,7 +402,7 @@ struct ST {
//CHECK: ret void
//CHECK: declare i32 @__tgt_unregister_lib([[DSCTY]]*)
-//CHECK: define linkonce hidden void @[[REGFN]](i8*)
+//CHECK: define linkonce hidden void @[[REGFN]]()
//CHECK-SAME: comdat {
//CHECK: call i32 @__tgt_register_lib([[DSCTY]]* [[DESC]])
//CHECK: call i32 @__cxa_atexit(void (i8*)* @[[UNREGFN]], i8* bitcast ([[DSCTY]]* [[DESC]] to i8*),
@@ -421,31 +442,31 @@ int bar(int a){
// Check metadata is properly generated:
// CHECK: !omp_offload.info = !{!{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 195, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 247, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 265, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 272, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 284, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 291, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 415, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 298, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 291, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 298, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 284, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 221, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 216, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 268, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 286, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 293, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 305, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 312, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 436, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 319, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 312, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 319, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 305, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 242, i32 {{[0-9]+}}}
// TCHECK: !omp_offload.info = !{!{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 195, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 247, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 265, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 272, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 284, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 291, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 415, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 298, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 291, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 298, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 284, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 221, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 216, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 268, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 286, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 293, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 305, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 312, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 436, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 319, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 312, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 319, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 305, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 242, i32 {{[0-9]+}}}
#endif
diff --git a/test/OpenMP/target_parallel_for_simd_codegen_registration_naming.cpp b/test/OpenMP/target_parallel_for_simd_codegen_registration_naming.cpp
index bdfa38669859..6c8e06a45510 100644
--- a/test/OpenMP/target_parallel_for_simd_codegen_registration_naming.cpp
+++ b/test/OpenMP/target_parallel_for_simd_codegen_registration_naming.cpp
@@ -6,6 +6,14 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// Test target parallel for simd codegen - host bc file has to be created first.
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s -check-prefix=TCHECK
@@ -16,6 +24,16 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s -check-prefix=TCHECK
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/target_parallel_for_simd_collapse_messages.cpp b/test/OpenMP/target_parallel_for_simd_collapse_messages.cpp
index ecf2d6e7889e..f3f2aa9ace56 100644
--- a/test/OpenMP/target_parallel_for_simd_collapse_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_collapse_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_for_simd_default_messages.cpp b/test/OpenMP/target_parallel_for_simd_default_messages.cpp
index 5d41cbcb457e..b67bfc52e75b 100644
--- a/test/OpenMP/target_parallel_for_simd_default_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_default_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo();
int main(int argc, char **argv) {
diff --git a/test/OpenMP/target_parallel_for_simd_defaultmap_messages.cpp b/test/OpenMP/target_parallel_for_simd_defaultmap_messages.cpp
index e922e0a000b4..c019c37c39d3 100644
--- a/test/OpenMP/target_parallel_for_simd_defaultmap_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_defaultmap_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_for_simd_depend_codegen.cpp b/test/OpenMP/target_parallel_for_simd_depend_codegen.cpp
new file mode 100644
index 000000000000..6fc71a787559
--- /dev/null
+++ b/test/OpenMP/target_parallel_for_simd_depend_codegen.cpp
@@ -0,0 +1,261 @@
+// Test host codegen.
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+// Test target codegen - host bc file has to be created first.
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+// CHECK-DAG: [[TT:%.+]] = type { i64, i8 }
+// CHECK-DAG: [[ENTTY:%.+]] = type { i8*, i8*, i[[SZ:32|64]], i32, i32 }
+// CHECK-DAG: [[DEVTY:%.+]] = type { i8*, i8*, [[ENTTY]]*, [[ENTTY]]* }
+// CHECK-DAG: [[DSCTY:%.+]] = type { i32, [[DEVTY]]*, [[ENTTY]]*, [[ENTTY]]* }
+
+// TCHECK: [[ENTTY:%.+]] = type { i8*, i8*, i{{32|64}}, i32, i32 }
+
+// CHECK-DAG: $[[REGFN:\.omp_offloading\..+]] = comdat
+
+// CHECK-DAG: [[SIZET:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 0, i[[SZ]] 4]
+// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 544, i64 800]
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = {{.*}}constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
+
+// Check if offloading descriptor is created.
+// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
+// CHECK: [[ENTEND:@.+]] = external constant [[ENTTY]]
+// CHECK: [[DEVBEGIN:@.+]] = external constant i8
+// CHECK: [[DEVEND:@.+]] = external constant i8
+// CHECK: [[IMAGES:@.+]] = internal unnamed_addr constant [1 x [[DEVTY]]] [{{.+}} { i8* [[DEVBEGIN]], i8* [[DEVEND]], [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }], comdat($[[REGFN]])
+// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
+
+// Check target registration is registered as a Ctor.
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
+
+
+template<typename tx, typename ty>
+struct TT{
+ tx X;
+ ty Y;
+};
+
+int global;
+extern int global;
+
+// CHECK: define {{.*}}[[FOO:@.+]](
+int foo(int n) {
+ int a = 0;
+ short aa = 0;
+ float b[10];
+ float bn[n];
+ double c[5][10];
+ double cn[5][n];
+ TT<long long, char> d;
+ static long *plocal;
+
+ // CHECK: [[ADD:%.+]] = add nsw i32
+ // CHECK: store i32 [[ADD]], i32* [[DEVICE_CAP:%.+]],
+ // CHECK: [[GEP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+ // CHECK: store i32 [[DEV]], i32* [[GEP]],
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[IN:@.+]], i32 [[GTID:%.+]], i32 1, i[[SZ]] {{20|40}}, i[[SZ]] 4, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY0:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY0:%.+]]*
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 1
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 2
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 3
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call void @__kmpc_omp_wait_deps(%struct.ident_t* [[IN]], i32 [[GTID]], i32 4, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: call void @__kmpc_omp_task_begin_if0(%struct.ident_t* [[IN]], i32 [[GTID]], i8* [[TASK]])
+ // CHECK: call i32 [[TASK_ENTRY0]](i32 [[GTID]], [[TASK_TY0]]* [[BC_TASK]])
+ // CHECK: call void @__kmpc_omp_task_complete_if0(%struct.ident_t* [[IN]], i32 [[GTID]], i8* [[TASK]])
+ #pragma omp target parallel for simd device(global + a) depend(in: global) depend(out: a, b, cn[4])
+ for (int i = 0; i < 10; ++i) {
+ }
+
+ // CHECK: [[ADD:%.+]] = add nsw i32
+ // CHECK: store i32 [[ADD]], i32* [[DEVICE_CAP:%.+]],
+
+ // CHECK: [[BOOL:%.+]] = icmp ne i32 %{{.+}}, 0
+ // CHECK: br i1 [[BOOL]], label %[[THEN:.+]], label %[[ELSE:.+]]
+ // CHECK: [[THEN]]:
+ // CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP:%.+]], i32 0, i32 0
+ // CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P:%.+]], i32 0, i32 0
+ // CHECK-DAG: [[CBPADDR0:%.+]] = bitcast i8** [[BPADDR0]] to i[[SZ]]**
+ // CHECK-DAG: [[CPADDR0:%.+]] = bitcast i8** [[PADDR0]] to i[[SZ]]**
+ // CHECK-DAG: store i[[SZ]]* [[BP0:%[^,]+]], i[[SZ]]** [[CBPADDR0]]
+ // CHECK-DAG: store i[[SZ]]* [[BP0]], i[[SZ]]** [[CPADDR0]]
+
+ // CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 1
+ // CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P]], i32 0, i32 1
+ // CHECK-DAG: [[CBPADDR1:%.+]] = bitcast i8** [[BPADDR1]] to i[[SZ]]*
+ // CHECK-DAG: [[CPADDR1:%.+]] = bitcast i8** [[PADDR1]] to i[[SZ]]*
+ // CHECK-DAG: store i[[SZ]] [[BP1:%[^,]+]], i[[SZ]]* [[CBPADDR1]]
+ // CHECK-DAG: store i[[SZ]] [[BP1]], i[[SZ]]* [[CPADDR1]]
+ // CHECK-DAG: getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 0
+ // CHECK-DAG: getelementptr inbounds [2 x i8*], [2 x i8*]* [[P]], i32 0, i32 0
+ // CHECK: [[GEP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+ // CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+ // CHECK: store i32 [[DEV]], i32* [[GEP]],
+
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[IN]], i32 [[GTID]], i32 1, i[[SZ]] {{104|52}}, i[[SZ]] {{16|12}}, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY1_:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY1_:%.+]]*
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 1
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 2
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call i32 @__kmpc_omp_task_with_deps(%struct.ident_t* [[IN]], i32 [[GTID]], i8* [[TASK]], i32 3, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: br label %[[EXIT:.+]]
+
+ // CHECK: [[ELSE]]:
+ // CHECK-NOT: getelementptr inbounds [2 x i8*], [2 x i8*]*
+ // CHECK: [[GEP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+ // CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+ // CHECK: store i32 [[DEV]], i32* [[GEP]],
+
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[IN]], i32 [[GTID]], i32 1, i[[SZ]] {{56|28}}, i[[SZ]] {{16|12}}, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY1__:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY1__:%.+]]*
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 1
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 2
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call i32 @__kmpc_omp_task_with_deps(%struct.ident_t* [[IN]], i32 [[GTID]], i8* [[TASK]], i32 3, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: br label %[[EXIT:.+]]
+ // CHECK: [[EXIT]]:
+
+ #pragma omp target parallel for simd device(global + a) nowait depend(inout: global, a, bn) if(target:a)
+ for (int i = 0; i < *plocal; ++i) {
+ static int local1;
+ *plocal = global;
+ local1 = global;
+ }
+
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[IN]], i32 [[GTID]], i32 1, i[[SZ]] {{48|24}}, i[[SZ]] 4, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY2:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY2:%.+]]*
+ // CHECK: getelementptr inbounds [1 x %struct.kmp_depend_info], [1 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [1 x %struct.kmp_depend_info], [1 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call void @__kmpc_omp_wait_deps(%struct.ident_t* [[IN]], i32 [[GTID]], i32 1, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: call void @__kmpc_omp_task_begin_if0(%struct.ident_t* [[IN]], i32 [[GTID]], i8* [[TASK]])
+ // CHECK: call i32 [[TASK_ENTRY2]](i32 [[GTID]], [[TASK_TY2]]* [[BC_TASK]])
+ // CHECK: call void @__kmpc_omp_task_complete_if0(%struct.ident_t* [[IN]], i32 [[GTID]], i8* [[TASK]])
+ #pragma omp target parallel for simd if(0) firstprivate(global) depend(out:global)
+ for (int i = 0; i < global; ++i) {
+ global += 1;
+ }
+
+ return a;
+}
+
+// Check that the offloading functions are emitted and that the arguments are
+// correct and loaded correctly for the target regions in foo().
+
+// CHECK: define internal void [[HVT0:@.+]]()
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY0]](i32{{.*}}, [[TASK_TY0]]* noalias)
+// CHECK: store void (i8*, ...)* null, void (i8*, ...)** %
+// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 0
+// CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+// CHECK: [[DEVICE:%.+]] = sext i32 [[DEV]] to i64
+// CHECK: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 [[DEVICE]], i8* @{{[^,]+}}, i32 0, i8** null, i8** null, i[[SZ]]* null, i64* null, i32 1, i32 0)
+// CHECK-NEXT: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
+// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
+// CHECK: [[FAIL]]
+// CHECK: call void [[HVT0]]()
+// CHECK-NEXT: br label %[[END]]
+// CHECK: [[END]]
+// CHECK: ret i32 0
+
+// CHECK: define internal void [[HVT1:@.+]](i[[SZ]]* %{{.+}}, i[[SZ]] %{{.+}})
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY1_]](i32{{.*}}, [[TASK_TY1_]]* noalias)
+// CHECK: call void (i8*, ...) %
+// CHECK: [[SZT:%.+]] = getelementptr inbounds [2 x i[[SZ]]], [2 x i[[SZ]]]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+// CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+// CHECK: [[DEVICE:%.+]] = sext i32 [[DEV]] to i64
+// CHECK: [[RET:%.+]] = call i32 @__tgt_target_teams_nowait(i64 [[DEVICE]], i8* @{{[^,]+}}, i32 2, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SZT]], i64* getelementptr inbounds ([2 x i64], [2 x i64]* [[MAPT]], i32 0, i32 0), i32 1, i32 0)
+
+// CHECK: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
+// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
+// CHECK: [[FAIL]]
+// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
+// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
+// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
+// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
+// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
+// CHECK: [[BP1:%.+]] = load i[[SZ]], i[[SZ]]* [[BP1_PTR]],
+// CHECK: call void [[HVT1]](i[[SZ]]* [[BP0]], i[[SZ]] [[BP1]])
+// CHECK-NEXT: br label %[[END]]
+// CHECK: [[END]]
+// CHECK: ret i32 0
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY1__]](i32{{.*}}, [[TASK_TY1__]]* noalias)
+// CHECK: call void (i8*, ...) %
+// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
+// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
+// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
+// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
+// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
+// CHECK: [[BP1:%.+]] = load i[[SZ]], i[[SZ]]* [[BP1_PTR]],
+// CHECK: call void [[HVT1]](i[[SZ]]* [[BP0]], i[[SZ]] [[BP1]])
+// CHECK: ret i32 0
+
+// CHECK: define internal void [[HVT2:@.+]](i[[SZ]] %{{.+}})
+// Create stack storage and store argument in there.
+// CHECK: [[AA_ADDR:%.+]] = alloca i[[SZ]], align
+// CHECK: store i[[SZ]] %{{.+}}, i[[SZ]]* [[AA_ADDR]], align
+// CHECK-64: [[AA_CADDR:%.+]] = bitcast i[[SZ]]* [[AA_ADDR]] to i32*
+// CHECK-64: load i32, i32* [[AA_CADDR]], align
+// CHECK-32: load i32, i32* [[AA_ADDR]], align
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY2]](i32{{.*}}, [[TASK_TY2]]* noalias)
+// CHECK: call void (i8*, ...) %
+// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
+// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
+// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
+// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
+// CHECK: [[BP1:%.+]] = load i[[SZ]], i[[SZ]]* [[BP1_PTR]],
+// CHECK: call void [[HVT2]](i[[SZ]] [[BP1]])
+// CHECK: ret i32 0
+
+
+#endif
diff --git a/test/OpenMP/target_parallel_for_simd_depend_messages.cpp b/test/OpenMP/target_parallel_for_simd_depend_messages.cpp
index 4375941036cf..5a735fc77afe 100644
--- a/test/OpenMP/target_parallel_for_simd_depend_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_depend_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_for_simd_device_messages.cpp b/test/OpenMP/target_parallel_for_simd_device_messages.cpp
index 2c9d43f07b25..8d2719571aba 100644
--- a/test/OpenMP/target_parallel_for_simd_device_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_device_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_for_simd_firstprivate_messages.cpp b/test/OpenMP/target_parallel_for_simd_firstprivate_messages.cpp
index 9ad255f033e4..8a32c6ffc28a 100644
--- a/test/OpenMP/target_parallel_for_simd_firstprivate_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_firstprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_for_simd_if_messages.cpp b/test/OpenMP/target_parallel_for_simd_if_messages.cpp
index 640e24c1eae4..fea1ad9778f5 100644
--- a/test/OpenMP/target_parallel_for_simd_if_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_if_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_for_simd_is_device_ptr_ast_print.cpp b/test/OpenMP/target_parallel_for_simd_is_device_ptr_ast_print.cpp
index af98f99ada95..feeaa1ef72ac 100644
--- a/test/OpenMP/target_parallel_for_simd_is_device_ptr_ast_print.cpp
+++ b/test/OpenMP/target_parallel_for_simd_is_device_ptr_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -56,7 +60,7 @@ struct SA {
// CHECK-NEXT: int aa[10];
// CHECK-NEXT: arr &raa = this->aa;
// CHECK-NEXT: func(
-// CHECK-NEXT: #pragma omp target parallel for simd is_device_ptr(this->k)
+// CHECK-NEXT: #pragma omp target parallel for simd is_device_ptr(this->k){{$}}
// CHECK-NEXT: for (int i = 0; i < 100; i++)
// CHECK-NEXT: ;
// CHECK-NEXT: #pragma omp target parallel for simd is_device_ptr(this->z)
diff --git a/test/OpenMP/target_parallel_for_simd_is_device_ptr_messages.cpp b/test/OpenMP/target_parallel_for_simd_is_device_ptr_messages.cpp
index 435b9a95e9e6..1079bf3cbb84 100644
--- a/test/OpenMP/target_parallel_for_simd_is_device_ptr_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_is_device_ptr_messages.cpp
@@ -1,4 +1,6 @@
// RUN: %clang_cc1 -std=c++11 -verify -fopenmp %s
+
+// RUN: %clang_cc1 -std=c++11 -verify -fopenmp-simd %s
struct ST {
int *a;
};
diff --git a/test/OpenMP/target_parallel_for_simd_lastprivate_messages.cpp b/test/OpenMP/target_parallel_for_simd_lastprivate_messages.cpp
index 313192dbb5f6..7c2c23f9d70d 100644
--- a/test/OpenMP/target_parallel_for_simd_lastprivate_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_lastprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_for_simd_linear_messages.cpp b/test/OpenMP/target_parallel_for_simd_linear_messages.cpp
index e17f15550e65..40fd052df2e3 100644
--- a/test/OpenMP/target_parallel_for_simd_linear_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_linear_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
namespace X {
int x;
};
diff --git a/test/OpenMP/target_parallel_for_simd_loop_messages.cpp b/test/OpenMP/target_parallel_for_simd_loop_messages.cpp
index f07f19e2a690..fabf389150d0 100644
--- a/test/OpenMP/target_parallel_for_simd_loop_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_loop_messages.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s -Wno-openmp-target
class S {
int a;
diff --git a/test/OpenMP/target_parallel_for_simd_map_messages.cpp b/test/OpenMP/target_parallel_for_simd_map_messages.cpp
index 7e95e10ae5ca..1cab5988396f 100644
--- a/test/OpenMP/target_parallel_for_simd_map_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_map_messages.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wno-openmp-target
void foo() {
}
diff --git a/test/OpenMP/target_parallel_for_simd_messages.cpp b/test/OpenMP/target_parallel_for_simd_messages.cpp
index 0e1a0fea7e61..c0e03289d750 100644
--- a/test/OpenMP/target_parallel_for_simd_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_for_simd_misc_messages.c b/test/OpenMP/target_parallel_for_simd_misc_messages.c
index f2574a35472d..8886ddd4a1e0 100644
--- a/test/OpenMP/target_parallel_for_simd_misc_messages.c
+++ b/test/OpenMP/target_parallel_for_simd_misc_messages.c
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -verify %s
+
// expected-error@+1 {{unexpected OpenMP directive '#pragma omp target parallel for simd'}}
#pragma omp target parallel for simd
diff --git a/test/OpenMP/target_parallel_for_simd_nowait_messages.cpp b/test/OpenMP/target_parallel_for_simd_nowait_messages.cpp
index 3c4b51204817..5e1e13168d5b 100644
--- a/test/OpenMP/target_parallel_for_simd_nowait_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_nowait_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_for_simd_num_threads_messages.cpp b/test/OpenMP/target_parallel_for_simd_num_threads_messages.cpp
index 1076b86ea5e6..b3323f67728f 100644
--- a/test/OpenMP/target_parallel_for_simd_num_threads_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_num_threads_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_for_simd_ordered_messages.cpp b/test/OpenMP/target_parallel_for_simd_ordered_messages.cpp
index 065d81517f83..3e3f6c26c343 100644
--- a/test/OpenMP/target_parallel_for_simd_ordered_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_ordered_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_for_simd_private_messages.cpp b/test/OpenMP/target_parallel_for_simd_private_messages.cpp
index 57262a58598c..51f1d9b8be9e 100644
--- a/test/OpenMP/target_parallel_for_simd_private_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_private_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
@@ -43,7 +45,7 @@ public:
S5(int v) : a(v) {}
S5 &operator=(S5 &s) {
#pragma omp target parallel for simd private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}}
- for (int k = 0; k < s.a; ++k)
+ for (int k = 0; k < s.a; ++k) // expected-warning {{Non-trivial type 'S5' is mapped, only trivial types are guaranteed to be mapped correctly}}
++s.a;
return *this;
}
diff --git a/test/OpenMP/target_parallel_for_simd_proc_bind_messages.cpp b/test/OpenMP/target_parallel_for_simd_proc_bind_messages.cpp
index 5bb6d92cd7e9..83b4efad15bd 100644
--- a/test/OpenMP/target_parallel_for_simd_proc_bind_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_proc_bind_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo();
int main(int argc, char **argv) {
diff --git a/test/OpenMP/target_parallel_for_simd_reduction_messages.cpp b/test/OpenMP/target_parallel_for_simd_reduction_messages.cpp
index 72e2130f3df4..30aaf832d6fe 100644
--- a/test/OpenMP/target_parallel_for_simd_reduction_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_reduction_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 150 -o - %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 150 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_for_simd_safelen_messages.cpp b/test/OpenMP/target_parallel_for_simd_safelen_messages.cpp
index f99010179dc3..74b1a7374f0f 100644
--- a/test/OpenMP/target_parallel_for_simd_safelen_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_safelen_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_for_simd_schedule_messages.cpp b/test/OpenMP/target_parallel_for_simd_schedule_messages.cpp
index f0d86e952de6..6f26e7aac433 100644
--- a/test/OpenMP/target_parallel_for_simd_schedule_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_schedule_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_for_simd_simdlen_messages.cpp b/test/OpenMP/target_parallel_for_simd_simdlen_messages.cpp
index e51e67b6b45f..f8b375ef1c6c 100644
--- a/test/OpenMP/target_parallel_for_simd_simdlen_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_simdlen_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_if_codegen.cpp b/test/OpenMP/target_parallel_if_codegen.cpp
index c155bf7c051a..aab1a14a5eb5 100644
--- a/test/OpenMP/target_parallel_if_codegen.cpp
+++ b/test/OpenMP/target_parallel_if_codegen.cpp
@@ -6,6 +6,14 @@
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// Test target codegen - host bc file has to be created first.
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
@@ -16,13 +24,23 @@
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
-// CHECK-DAG: %ident_t = type { i32, i32, i32, i32, i8* }
+// CHECK-DAG: %struct.ident_t = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr constant %ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
// CHECK-DAG: [[S1:%.+]] = type { double }
// CHECK-DAG: [[ENTTY:%.+]] = type { i8*, i8*, i[[SZ:32|64]], i32, i32 }
@@ -35,19 +53,19 @@
// We have 6 target regions
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -58,7 +76,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx>
@@ -145,7 +163,7 @@ int bar(int n){
// CHECK: store i8 [[FB]], i8* [[CONV]], align
// CHECK: [[ARG:%.+]] = load i[[SZ]], i[[SZ]]* [[CAPEC_ADDR]], align
//
-// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 3, {{.*}}, i32 1, i32 0)
+// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 4, {{.*}}, i32 1, i32 0)
// CHECK: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
// CHECK: br i1 [[ERROR]], label %[[FAIL:.+]], label %[[END:[^,]+]]
//
@@ -171,7 +189,7 @@ int bar(int n){
// CHECK: br i1 [[CMP]], label {{%?}}[[IF_THEN:.+]], label {{%?}}[[IF_ELSE:.+]]
//
// CHECK: [[IF_THEN]]
-// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 2, {{.*}}, i32 1, i32 0)
+// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 3, {{.*}}, i32 1, i32 0)
// CHECK: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:.+]], label %[[END:[^,]+]]
// CHECK: [[FAIL]]
@@ -291,7 +309,7 @@ int bar(int n){
// CHECK: br i1 [[TB]], label {{%?}}[[IF_THEN:.+]], label {{%?}}[[IF_ELSE:.+]]
//
// CHECK: [[IF_THEN]]
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 2, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, [[S1]]*, i[[SZ]])* [[OMP_OUTLINED3:@.+]] to void (i32*, i32*, ...)*), [[S1]]* {{.+}}, i[[SZ]] [[ARG]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 2, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, [[S1]]*, i[[SZ]])* [[OMP_OUTLINED3:@.+]] to void (i32*, i32*, ...)*), [[S1]]* {{.+}}, i[[SZ]] [[ARG]])
// CHECK: br label {{%?}}[[END:.+]]
//
// CHECK: [[IF_ELSE]]
@@ -313,7 +331,7 @@ int bar(int n){
// CHECK: br i1 [[TB]], label {{%?}}[[IF_THEN:.+]], label {{%?}}[[IF_ELSE:.+]]
//
// CHECK: [[IF_THEN]]
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, [[S1]]*)* [[OMP_OUTLINED4:@.+]] to void (i32*, i32*, ...)*), [[S1]]* {{.+}})
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, [[S1]]*)* [[OMP_OUTLINED4:@.+]] to void (i32*, i32*, ...)*), [[S1]]* {{.+}})
// CHECK: br label {{%?}}[[END:.+]]
//
// CHECK: [[IF_ELSE]]
@@ -341,7 +359,7 @@ int bar(int n){
// CHECK: br i1 [[TB]], label {{%?}}[[IF_THEN:.+]], label {{%?}}[[IF_ELSE:.+]]
//
// CHECK: [[IF_THEN]]
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* [[OMP_OUTLINED1:@.+]] to void (i32*, i32*, ...)*))
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* [[OMP_OUTLINED1:@.+]] to void (i32*, i32*, ...)*))
// CHECK: br label {{%?}}[[END:.+]]
//
// CHECK: [[IF_ELSE]]
@@ -354,7 +372,7 @@ int bar(int n){
//
//
// CHECK: define internal void [[HVT4]]()
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* [[OMP_OUTLINED2:@.+]] to void (i32*, i32*, ...)*))
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* [[OMP_OUTLINED2:@.+]] to void (i32*, i32*, ...)*))
// CHECK-NEXT: ret
//
//
@@ -377,7 +395,7 @@ int bar(int n){
// CHECK-NOT: call void @__kmpc_serialized_parallel(
// CHECK-NOT: call void [[OMP_OUTLINED5:@.+]](i32* {{%.+}}, i32* {{%.+}}, i[[SZ]] {{.+}})
// CHECK-NOT: call void @__kmpc_end_serialized_parallel(
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 2, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]])* [[OMP_OUTLINED5:@.+]] to void (i32*, i32*, ...)*),
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 2, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]])* [[OMP_OUTLINED5:@.+]] to void (i32*, i32*, ...)*),
// CHECK: ret
//
//
diff --git a/test/OpenMP/target_parallel_if_messages.cpp b/test/OpenMP/target_parallel_if_messages.cpp
index 06b7a59b7e59..d59b4ab5074b 100644
--- a/test/OpenMP/target_parallel_if_messages.cpp
+++ b/test/OpenMP/target_parallel_if_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_is_device_ptr_ast_print.cpp b/test/OpenMP/target_parallel_is_device_ptr_ast_print.cpp
index 7fbddd8622ae..16cc188e872e 100644
--- a/test/OpenMP/target_parallel_is_device_ptr_ast_print.cpp
+++ b/test/OpenMP/target_parallel_is_device_ptr_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -50,7 +54,7 @@ struct SA {
// CHECK-NEXT: int aa[10];
// CHECK-NEXT: arr &raa = this->aa;
// CHECK-NEXT: func(
-// CHECK-NEXT: #pragma omp target parallel is_device_ptr(this->k)
+// CHECK-NEXT: #pragma omp target parallel is_device_ptr(this->k){{$}}
// CHECK-NEXT: {
// CHECK-NEXT: }
// CHECK-NEXT: #pragma omp target parallel is_device_ptr(this->z)
diff --git a/test/OpenMP/target_parallel_is_device_ptr_messages.cpp b/test/OpenMP/target_parallel_is_device_ptr_messages.cpp
index d9c3ee907b61..b46fd713ff63 100644
--- a/test/OpenMP/target_parallel_is_device_ptr_messages.cpp
+++ b/test/OpenMP/target_parallel_is_device_ptr_messages.cpp
@@ -1,4 +1,6 @@
// RUN: %clang_cc1 -std=c++11 -verify -fopenmp -ferror-limit 200 %s
+
+// RUN: %clang_cc1 -std=c++11 -verify -fopenmp-simd -ferror-limit 200 %s
struct ST {
int *a;
};
@@ -38,7 +40,7 @@ struct SA {
#pragma omp target parallel is_device_ptr(aa) // OK
{}
#pragma omp target parallel is_device_ptr(raa) // OK
- {}
+ {}
#pragma omp target parallel is_device_ptr(e) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
{}
#pragma omp target parallel is_device_ptr(g) // OK
diff --git a/test/OpenMP/target_parallel_map_messages.cpp b/test/OpenMP/target_parallel_map_messages.cpp
index d3cc742decd5..4bb14ea52f03 100644
--- a/test/OpenMP/target_parallel_map_messages.cpp
+++ b/test/OpenMP/target_parallel_map_messages.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s -Wno-openmp-target
void foo() {
}
diff --git a/test/OpenMP/target_parallel_messages.cpp b/test/OpenMP/target_parallel_messages.cpp
index b6763d8f09e0..a7dfbf91ca53 100644
--- a/test/OpenMP/target_parallel_messages.cpp
+++ b/test/OpenMP/target_parallel_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -o - %s
// RUN: not %clang_cc1 -fopenmp -std=c++11 -fopenmp-targets=aaa-bbb-ccc-ddd -o - %s 2>&1 | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -o - %s
// CHECK: error: OpenMP target is invalid: 'aaa-bbb-ccc-ddd'
void foo() {
diff --git a/test/OpenMP/target_parallel_nowait_messages.cpp b/test/OpenMP/target_parallel_nowait_messages.cpp
index 91e26f20819f..8da03e4756ab 100644
--- a/test/OpenMP/target_parallel_nowait_messages.cpp
+++ b/test/OpenMP/target_parallel_nowait_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_num_threads_codegen.cpp b/test/OpenMP/target_parallel_num_threads_codegen.cpp
index 836a92d9a5db..e6b93113c557 100644
--- a/test/OpenMP/target_parallel_num_threads_codegen.cpp
+++ b/test/OpenMP/target_parallel_num_threads_codegen.cpp
@@ -6,6 +6,14 @@
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// Test target codegen - host bc file has to be created first.
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
@@ -16,13 +24,23 @@
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
-// CHECK-DAG: %ident_t = type { i32, i32, i32, i32, i8* }
+// CHECK-DAG: %struct.ident_t = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr constant %ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
// CHECK-DAG: [[S1:%.+]] = type { double }
// CHECK-DAG: [[ENTTY:%.+]] = type { i8*, i8*, i[[SZ:32|64]], i32, i32 }
@@ -35,19 +53,19 @@
// We have 6 target regions
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -58,7 +76,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx>
@@ -147,7 +165,7 @@ int bar(int n){
// CHECK: [[ARG:%.+]] = load i[[SZ]], i[[SZ]]* [[CAPEC_ADDR]], align
// CHECK: [[THREADS:%.+]] = load i32, i32* [[CAPE_ADDR]], align
//
-// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 3, {{.*}}, i32 1, i32 [[THREADS]])
+// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 4, {{.*}}, i32 1, i32 [[THREADS]])
// CHECK: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
// CHECK: br i1 [[ERROR]], label %[[FAIL:.+]], label %[[END:[^,]+]]
//
@@ -158,7 +176,7 @@ int bar(int n){
//
//
//
-// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 1, {{.+}}, i32 1, i32 1024)
+// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 2, {{.+}}, i32 1, i32 1024)
// CHECK: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
// CHECK: br i1 [[ERROR]], label %[[FAIL:.+]], label %[[END:[^,]+]]
//
@@ -270,15 +288,15 @@ int bar(int n){
// CHECK-64: [[CONV:%.+]] = bitcast i[[SZ]]* [[CAPE_ADDR]] to i32*
// CHECK-64: [[NT:%.+]] = load i32, i32* [[CONV]], align
// CHECK-32: [[NT:%.+]] = load i32, i32* [[CAPE_ADDR]], align
-// CHECK: call void @__kmpc_push_num_threads(%ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 [[NT]])
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 2,
+// CHECK: call void @__kmpc_push_num_threads(%struct.ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 [[NT]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 2,
//
//
// CHECK: define internal void [[HVT2]]([[S1]]* {{%.+}})
-// CHECK: call void @__kmpc_push_num_threads(%ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 1024)
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 1,
+// CHECK: call void @__kmpc_push_num_threads(%struct.ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 1024)
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 1,
//
//
@@ -294,8 +312,8 @@ int bar(int n){
// CHECK-64: [[CONV:%.+]] = bitcast i[[SZ]]* [[CAPE_ADDR]] to i32*
// CHECK-64: [[NT:%.+]] = load i32, i32* [[CONV]], align
// CHECK-32: [[NT:%.+]] = load i32, i32* [[CAPE_ADDR]], align
-// CHECK: call void @__kmpc_push_num_threads(%ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 [[NT]])
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 0,
+// CHECK: call void @__kmpc_push_num_threads(%struct.ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 [[NT]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 0,
//
//
// CHECK: define internal void [[HVT4]](i[[SZ]] [[PARM:%.+]])
@@ -303,8 +321,8 @@ int bar(int n){
// CHECK-64: [[CONV:%.+]] = bitcast i[[SZ]]* [[CAPE_ADDR]] to i32*
// CHECK-64: [[NT:%.+]] = load i32, i32* [[CONV]], align
// CHECK-32: [[NT:%.+]] = load i32, i32* [[CAPE_ADDR]], align
-// CHECK: call void @__kmpc_push_num_threads(%ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 [[NT]])
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 0,
+// CHECK: call void @__kmpc_push_num_threads(%struct.ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 [[NT]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 0,
//
//
@@ -313,8 +331,8 @@ int bar(int n){
// CHECK: define internal void [[HVT5]](
-// CHECK: call void @__kmpc_push_num_threads(%ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 20)
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 0,
+// CHECK: call void @__kmpc_push_num_threads(%struct.ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 20)
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 0,
//
//
@@ -324,8 +342,8 @@ int bar(int n){
// CHECK: [[CONV:%.+]] = bitcast i[[SZ]]* [[CAPE_ADDR]] to i16*
// CHECK: [[T:%.+]] = load i16, i16* [[CONV]], align
// CHECK: [[NT:%.+]] = sext i16 [[T]] to i32
-// CHECK: call void @__kmpc_push_num_threads(%ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 [[NT]])
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* [[DEF_LOC]], i32 2,
+// CHECK: call void @__kmpc_push_num_threads(%struct.ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 [[NT]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC]], i32 2,
//
//
diff --git a/test/OpenMP/target_parallel_num_threads_messages.cpp b/test/OpenMP/target_parallel_num_threads_messages.cpp
index 95797caf2962..efc1d1327f5a 100644
--- a/test/OpenMP/target_parallel_num_threads_messages.cpp
+++ b/test/OpenMP/target_parallel_num_threads_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_private_messages.cpp b/test/OpenMP/target_parallel_private_messages.cpp
index fabd37d4b395..34652d6cb3ce 100644
--- a/test/OpenMP/target_parallel_private_messages.cpp
+++ b/test/OpenMP/target_parallel_private_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_proc_bind_messages.cpp b/test/OpenMP/target_parallel_proc_bind_messages.cpp
index 56292ad43703..a01b63d7fef0 100644
--- a/test/OpenMP/target_parallel_proc_bind_messages.cpp
+++ b/test/OpenMP/target_parallel_proc_bind_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo();
int main(int argc, char **argv) {
diff --git a/test/OpenMP/target_parallel_reduction_messages.cpp b/test/OpenMP/target_parallel_reduction_messages.cpp
index 038f099c5a6c..6ea08848d513 100644
--- a/test/OpenMP/target_parallel_reduction_messages.cpp
+++ b/test/OpenMP/target_parallel_reduction_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 150 -o - %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 150 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/target_parallel_shared_messages.cpp b/test/OpenMP/target_parallel_shared_messages.cpp
index 302a09239d34..2ade722dd3a2 100644
--- a/test/OpenMP/target_parallel_shared_messages.cpp
+++ b/test/OpenMP/target_parallel_shared_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_private_codegen.cpp b/test/OpenMP/target_private_codegen.cpp
index 5c738ee5930f..213a20fec3aa 100644
--- a/test/OpenMP/target_private_codegen.cpp
+++ b/test/OpenMP/target_private_codegen.cpp
@@ -9,6 +9,16 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -35,28 +45,28 @@ int foo(int n) {
{
}
- // TCHECK: define void @__omp_offloading_{{.+}}()
+ // TCHECK: define weak void @__omp_offloading_{{.+}}()
// TCHECK: [[A:%.+]] = alloca i{{[0-9]+}},
// TCHECK-NOT: store {{.+}}, {{.+}} [[A]],
- // TCHECK: ret void
+ // TCHECK: ret void
#pragma omp target private(a)
{
a = 1;
}
- // TCHECK: define void @__omp_offloading_{{.+}}()
+ // TCHECK: define weak void @__omp_offloading_{{.+}}()
// TCHECK: [[A:%.+]] = alloca i{{[0-9]+}},
// TCHECK: store i{{[0-9]+}} 1, i{{[0-9]+}}* [[A]],
// TCHECK: ret void
-
- #pragma omp target private(a, aa)
+
+#pragma omp target private(a, aa)
{
a = 1;
aa = 1;
}
- // TCHECK: define void @__omp_offloading_{{.+}}()
+ // TCHECK: define weak void @__omp_offloading_{{.+}}()
// TCHECK: [[A:%.+]] = alloca i{{[0-9]+}},
// TCHECK: [[A2:%.+]] = alloca i{{[0-9]+}},
// TCHECK: store i{{[0-9]+}} 1, i{{[0-9]+}}* [[A]],
@@ -75,7 +85,7 @@ int foo(int n) {
}
// make sure that private variables are generated in all cases and that we use those instances for operations inside the
// target region
- // TCHECK: define void @__omp_offloading_{{.+}}(i{{[0-9]+}} [[VLA:%.+]], i{{[0-9]+}} [[VLA1:%.+]], i{{[0-9]+}} [[VLA3:%.+]])
+ // TCHECK: define weak void @__omp_offloading_{{.+}}(i{{[0-9]+}} [[VLA:%.+]], i{{[0-9]+}} [[VLA1:%.+]], i{{[0-9]+}} [[VLA3:%.+]])
// TCHECK: [[VLA_ADDR:%.+]] = alloca i{{[0-9]+}},
// TCHECK: [[VLA_ADDR2:%.+]] = alloca i{{[0-9]+}},
// TCHECK: [[VLA_ADDR4:%.+]] = alloca i{{[0-9]+}},
@@ -102,7 +112,7 @@ int foo(int n) {
// b[2] = 1.0
// TCHECK: [[B_GEP:%.+]] = getelementptr inbounds [10 x float], [10 x float]* [[B]], i{{[0-9]+}} 0, i{{[0-9]+}} 2
// TCHECK: store float 1.0{{.*}}, float* [[B_GEP]],
-
+
// bn[3] = 1.0
// TCHECK: [[BN_GEP:%.+]] = getelementptr inbounds float, float* [[VLA5]], i{{[0-9]+}} 3
// TCHECK: store float 1.0{{.*}}, float* [[BN_GEP]],
@@ -121,7 +131,7 @@ int foo(int n) {
// d.X = 1
// [[X_FIELD:%.+]] = getelementptr inbounds [[TT]] [[TT]]* [[D]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// store i{{[0-9]+}} 1, i{{[0-9]+}}* [[X_FIELD]],
-
+
// d.Y = 1
// [[Y_FIELD:%.+]] = getelementptr inbounds [[TT]] [[TT]]* [[D]], i{{[0-9]+}} 0, i{{[0-9]+}} 1
// store i{{[0-9]+}} 1, i{{[0-9]+}}* [[Y_FIELD]],
@@ -169,7 +179,7 @@ int fstatic(int n) {
return a;
}
-// TCHECK: define void @__omp_offloading_{{.+}}()
+// TCHECK: define weak void @__omp_offloading_{{.+}}()
// TCHECK: [[A:%.+]] = alloca i{{[0-9]+}},
// TCHECK: [[A2:%.+]] = alloca i{{[0-9]+}},
// TCHECK: [[A3:%.+]] = alloca i{{[0-9]+}},
@@ -197,7 +207,7 @@ struct S1 {
return c[1][1] + (int)b;
}
- // TCHECK: define void @__omp_offloading_{{.+}}([[S1]]* [[TH:%.+]], i{{[0-9]+}} [[VLA:%.+]], i{{[0-9]+}} [[VLA1:%.+]])
+ // TCHECK: define weak void @__omp_offloading_{{.+}}([[S1]]* [[TH:%.+]], i{{[0-9]+}} [[VLA:%.+]], i{{[0-9]+}} [[VLA1:%.+]])
// TCHECK: [[TH_ADDR:%.+]] = alloca [[S1]]*,
// TCHECK: [[VLA_ADDR:%.+]] = alloca i{{[0-9]+}},
// TCHECK: [[VLA_ADDR2:%.+]] = alloca i{{[0-9]+}},
@@ -251,7 +261,7 @@ int bar(int n){
}
// template
-// TCHECK: define void @__omp_offloading_{{.+}}()
+// TCHECK: define weak void @__omp_offloading_{{.+}}()
// TCHECK: [[A:%.+]] = alloca i{{[0-9]+}},
// TCHECK: [[A2:%.+]] = alloca i{{[0-9]+}},
// TCHECK: [[B:%.+]] = alloca [10 x i{{[0-9]+}}],
diff --git a/test/OpenMP/target_private_messages.cpp b/test/OpenMP/target_private_messages.cpp
index a093a8705627..49ee3fed3e94 100644
--- a/test/OpenMP/target_private_messages.cpp
+++ b/test/OpenMP/target_private_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
struct S1; // expected-note 2 {{declared here}} expected-note 2 {{forward declaration of 'S1'}}
extern S1 a;
class S2 {
@@ -36,7 +38,7 @@ public:
S5(int v) : a(v) {}
S5 &operator=(S5 &s) {
#pragma omp target private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}}
- for (int k = 0; k < s.a; ++k)
+ for (int k = 0; k < s.a; ++k) // expected-warning {{Non-trivial type 'S5' is mapped, only trivial types are guaranteed to be mapped correctly}}
++s.a;
return *this;
}
diff --git a/test/OpenMP/target_reduction_codegen.cpp b/test/OpenMP/target_reduction_codegen.cpp
index f86719b55fa1..38508006872e 100644
--- a/test/OpenMP/target_reduction_codegen.cpp
+++ b/test/OpenMP/target_reduction_codegen.cpp
@@ -9,6 +9,16 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -35,7 +45,7 @@ int foo(int n) {
{
}
- // TCHECK: define void @__omp_offloading_{{.+}}(i32*{{.+}} %{{.+}})
+ // TCHECK: define weak void @__omp_offloading_{{.+}}(i32*{{.+}} %{{.+}})
// TCHECK: [[A:%.+]] = alloca i{{[0-9]+}}*,
// TCHECK: store {{.+}}, {{.+}} [[A]],
// TCHECK: load i32*, i32** [[A]],
@@ -46,7 +56,7 @@ int foo(int n) {
a = 1;
}
- // TCHECK: define void @__omp_offloading_{{.+}}(i32*{{.+}} %{{.+}})
+ // TCHECK: define weak void @__omp_offloading_{{.+}}(i32*{{.+}} %{{.+}})
// TCHECK: [[A:%.+]] = alloca i{{[0-9]+}}*,
// TCHECK: store {{.+}}, {{.+}} [[A]],
// TCHECK: [[REF:%.+]] = load i32*, i32** [[A]],
@@ -59,7 +69,7 @@ int foo(int n) {
aa = 1;
}
- // TCHECK: define void @__omp_offloading_{{.+}}(i32*{{.+}} [[A:%.+]], i16*{{.+}} [[AA:%.+]])
+ // TCHECK: define weak void @__omp_offloading_{{.+}}(i32*{{.+}} [[A:%.+]], i16*{{.+}} [[AA:%.+]])
// TCHECK: [[A:%.+]] = alloca i{{[0-9]+}}*,
// TCHECK: [[AA:%.+]] = alloca i{{[0-9]+}}*,
// TCHECK: store {{.+}}, {{.+}} [[A]],
@@ -108,7 +118,7 @@ int fstatic(int n) {
return a;
}
-// TCHECK: define void @__omp_offloading_{{.+}}(i32*{{.+}}, i16*{{.+}}, i8*{{.+}}, [10 x i32]*{{.+}})
+// TCHECK: define weak void @__omp_offloading_{{.+}}(i32*{{.+}}, i16*{{.+}}, i8*{{.+}}, [10 x i32]*{{.+}})
// TCHECK: [[A:%.+]] = alloca i{{[0-9]+}}*,
// TCHECK: [[A2:%.+]] = alloca i{{[0-9]+}}*,
// TCHECK: [[A3:%.+]] = alloca i{{[0-9]+}}*,
@@ -144,7 +154,7 @@ struct S1 {
return c[1][1] + (int)b;
}
- // TCHECK: define void @__omp_offloading_{{.+}}([[S1]]* [[TH:%.+]], i32*{{.+}}, i{{[0-9]+}} [[VLA:%.+]], i{{[0-9]+}} [[VLA1:%.+]], i16*{{.+}})
+ // TCHECK: define weak void @__omp_offloading_{{.+}}([[S1]]* [[TH:%.+]], i32*{{.+}}, i{{[0-9]+}} [[VLA:%.+]], i{{[0-9]+}} [[VLA1:%.+]], i16*{{.+}})
// TCHECK: [[TH_ADDR:%.+]] = alloca [[S1]]*,
// TCHECK: [[B_ADDR:%.+]] = alloca i{{[0-9]+}}*,
// TCHECK: [[VLA_ADDR:%.+]] = alloca i{{[0-9]+}},
@@ -196,7 +206,7 @@ int bar(int n){
}
// template
-// TCHECK: define void @__omp_offloading_{{.+}}(i{{[0-9]+}}*{{.+}}, i{{[0-9]+}}*{{.+}}, [10 x i32]*{{.+}})
+// TCHECK: define weak void @__omp_offloading_{{.+}}(i{{[0-9]+}}*{{.+}}, i{{[0-9]+}}*{{.+}}, [10 x i32]*{{.+}})
// TCHECK: [[A:%.+]] = alloca i{{[0-9]+}}*,
// TCHECK: [[A2:%.+]] = alloca i{{[0-9]+}}*,
// TCHECK: [[B:%.+]] = alloca [10 x i{{[0-9]+}}]*,
diff --git a/test/OpenMP/target_reduction_messages.cpp b/test/OpenMP/target_reduction_messages.cpp
index 8cf79f9a5d99..ff936b8c1950 100644
--- a/test/OpenMP/target_reduction_messages.cpp
+++ b/test/OpenMP/target_reduction_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 150 -o - %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 150 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/target_simd_aligned_messages.cpp b/test/OpenMP/target_simd_aligned_messages.cpp
index 76a37f64984d..d2628b435796 100644
--- a/test/OpenMP/target_simd_aligned_messages.cpp
+++ b/test/OpenMP/target_simd_aligned_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -x c++ -std=c++11 -verify -fopenmp %s
+// RUN: %clang_cc1 -x c++ -std=c++11 -verify -fopenmp-simd %s
+
struct B {
static int ib[20]; // expected-note 0 {{'B::ib' declared here}}
static constexpr int bfoo() { return 8; }
diff --git a/test/OpenMP/target_simd_ast_print.cpp b/test/OpenMP/target_simd_ast_print.cpp
index 01ce1d21cfbc..7d3daa36f30c 100644
--- a/test/OpenMP/target_simd_ast_print.cpp
+++ b/test/OpenMP/target_simd_ast_print.cpp
@@ -1,6 +1,10 @@
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ast-print %s | FileCheck %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ast-print %s -Wno-openmp-target | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-target | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ast-print %s -Wno-openmp-target | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-target | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -35,7 +39,7 @@ public:
}
};
-// CHECK: #pragma omp target simd private(this->a) private(this->a) private(T::a)
+// CHECK: #pragma omp target simd private(this->a) private(this->a) private(T::a){{$}}
// CHECK: #pragma omp target simd private(this->a) private(this->a)
// CHECK: #pragma omp target simd private(this->a) private(this->a) private(this->S::a)
diff --git a/test/OpenMP/target_simd_codegen.cpp b/test/OpenMP/target_simd_codegen.cpp
index d57e3818559a..a2ec51c4e22f 100644
--- a/test/OpenMP/target_simd_codegen.cpp
+++ b/test/OpenMP/target_simd_codegen.cpp
@@ -1,20 +1,38 @@
// Test host codegen.
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// Test target codegen - host bc file has to be created first.
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-64
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-64
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-32
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
@@ -35,31 +53,31 @@
// sizes.
// CHECK-DAG: [[SIZET2:@.+]] = private unnamed_addr constant [3 x i[[SZ]]] [i[[SZ]] 2, i[[SZ]] 4, i[[SZ]] 4]
-// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [3 x i64] [i64 288, i64 288, i64 288]
+// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [3 x i64] [i64 800, i64 800, i64 800]
// CHECK-DAG: [[SIZET3:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2]
-// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [2 x i64] [i64 288, i64 288]
-// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [9 x i64] [i64 288, i64 547, i64 288, i64 547, i64 547, i64 288, i64 288, i64 547, i64 547]
+// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [2 x i64] [i64 800, i64 800]
+// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [9 x i64] [i64 800, i64 547, i64 288, i64 547, i64 547, i64 288, i64 288, i64 547, i64 547]
// CHECK-DAG: [[SIZET5:@.+]] = private unnamed_addr constant [3 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2, i[[SZ]] 40]
-// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [3 x i64] [i64 288, i64 288, i64 547]
+// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [3 x i64] [i64 800, i64 800, i64 547]
// CHECK-DAG: [[SIZET6:@.+]] = private unnamed_addr constant [4 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2, i[[SZ]] 1, i[[SZ]] 40]
-// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [4 x i64] [i64 288, i64 288, i64 288, i64 547]
-// CHECK-DAG: [[MAPT7:@.+]] = private unnamed_addr constant [5 x i64] [i64 547, i64 288, i64 288, i64 288, i64 547]
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK-NOT: @{{.+}} = constant [[ENTTY]]
+// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [4 x i64] [i64 800, i64 800, i64 800, i64 547]
+// CHECK-DAG: [[MAPT7:@.+]] = private unnamed_addr constant [6 x i64] [i64 32, i64 281474976711171, i64 800, i64 288, i64 288, i64 547]
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -70,7 +88,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx, typename ty>
@@ -192,13 +210,13 @@ int foo(int n) {
// CHECK-32: store i32 [[A_VAL]], i32* [[A_CADDR:%.+]],
// CHECK-32: [[A_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[A_CADDR]],
+ // CHECK: [[IF:%.+]] = icmp sgt i32 {{[^,]+}}, 20
+ // CHECK: br i1 [[IF]], label %[[TRY:[^,]+]], label %[[FAIL:[^,]+]]
+ // CHECK: [[TRY]]
// CHECK: [[BNSIZE:%.+]] = mul nuw i[[SZ]] [[VLA0:%.+]], 4
// CHECK: [[CNELEMSIZE2:%.+]] = mul nuw i[[SZ]] 5, [[VLA1:%.+]]
// CHECK: [[CNSIZE:%.+]] = mul nuw i[[SZ]] [[CNELEMSIZE2]], 8
- // CHECK: [[IF:%.+]] = icmp sgt i32 {{[^,]+}}, 20
- // CHECK: br i1 [[IF]], label %[[TRY:[^,]+]], label %[[FAIL:[^,]+]]
- // CHECK: [[TRY]]
// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target(i64 -1, i8* @{{[^,]+}}, i32 9, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([9 x i64], [9 x i64]* [[MAPT4]], i32 0, i32 0))
// CHECK-DAG: [[BPR]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BP:%[^,]+]], i32 0, i32 0
// CHECK-DAG: [[PR]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P:%[^,]+]], i32 0, i32 0
@@ -460,32 +478,39 @@ int bar(int n){
// CHECK-64: store i32 %{{.+}}, i32* [[B_ADDR]],
// CHECK-64: [[B_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[B_CADDR]],
+// CHECK-32: store i32 %{{.+}}, i32* %__vla_expr
// CHECK-32: store i32 %{{.+}}, i32* [[B_ADDR:%.+]],
// CHECK-32: [[B_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[B_ADDR]],
+// CHECK: [[IF:%.+]] = icmp sgt i32 {{[^,]+}}, 60
+// CHECK: br i1 [[IF]], label %[[TRY:[^,]+]], label %[[FAIL:[^,]+]]
+// CHECK: [[TRY]]
// We capture 2 VLA sizes in this target region
// CHECK: [[CELEMSIZE2:%.+]] = mul nuw i[[SZ]] 2, [[VLA0:%.+]]
// CHECK: [[CSIZE:%.+]] = mul nuw i[[SZ]] [[CELEMSIZE2]], 2
-// CHECK: [[IF:%.+]] = icmp sgt i32 {{[^,]+}}, 60
-// CHECK: br i1 [[IF]], label %[[TRY:[^,]+]], label %[[FAIL:[^,]+]]
-// CHECK: [[TRY]]
-// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target(i64 -1, i8* @{{[^,]+}}, i32 5, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([5 x i64], [5 x i64]* [[MAPT7]], i32 0, i32 0))
-// CHECK-DAG: [[BPR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP:%.+]], i32 0, i32 0
-// CHECK-DAG: [[PR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P:%.+]], i32 0, i32 0
-// CHECK-DAG: [[SR]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0
-// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX0:[0-9]+]]
-// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX0]]
-// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX0]]
-// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX1:[0-9]+]]
-// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX1]]
-// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX1]]
-// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX2:[0-9]+]]
-// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX2]]
-// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX2]]
-// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]]
-// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX3]]
-// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX3]]
+// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target(i64 -1, i8* @{{[^,]+}}, i32 6, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([6 x i64], [6 x i64]* [[MAPT7]], i32 0, i32 0))
+// CHECK-DAG: [[BPR]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP:%.+]], i32 0, i32 0
+// CHECK-DAG: [[PR]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P:%.+]], i32 0, i32 0
+// CHECK-DAG: [[SR]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0
+// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX0:[0-9]+]]
+// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX0]]
+// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX0]]
+// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX1:[0-9]+]]
+// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX1]]
+// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX1]]
+// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX2:[0-9]+]]
+// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX2]]
+// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX2]]
+// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]]
+// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX3]]
+// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX3]]
+// CHECK-DAG: [[SADDR4:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX4:[0-9]+]]
+// CHECK-DAG: [[BPADDR4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX4]]
+// CHECK-DAG: [[PADDR4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX4]]
+// CHECK-DAG: [[SADDR5:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX5:[0-9]+]]
+// CHECK-DAG: [[BPADDR5:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX5]]
+// CHECK-DAG: [[PADDR5:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX5]]
// The names below are not necessarily consistent with the names used for the
// addresses above as some are repeated.
@@ -508,15 +533,21 @@ int bar(int n){
// CHECK-DAG: store i[[SZ]] 4, i[[SZ]]* {{%[^,]+}}
// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CBPADDR3:%.+]],
-// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CPADDR3:%.+]],
+// CHECK-DAG: store double* %{{.+}}, double** [[CPADDR3:%.+]],
// CHECK-DAG: [[CBPADDR3]] = bitcast i8** {{%[^,]+}} to [[S1]]**
-// CHECK-DAG: [[CPADDR3]] = bitcast i8** {{%[^,]+}} to [[S1]]**
+// CHECK-DAG: [[CPADDR3]] = bitcast i8** {{%[^,]+}} to double**
+// CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* {{%[^,]+}}
+
+// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CBPADDR4:%.+]],
+// CHECK-DAG: store double* %{{.+}}, double** [[CPADDR4:%.+]],
+// CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to [[S1]]**
+// CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to double**
// CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* {{%[^,]+}}
-// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR4:%.+]],
-// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR4:%.+]],
-// CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to i16**
-// CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to i16**
+// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR5:%.+]],
+// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR5:%.+]],
+// CHECK-DAG: [[CBPADDR5]] = bitcast i8** {{%[^,]+}} to i16**
+// CHECK-DAG: [[CPADDR5]] = bitcast i8** {{%[^,]+}} to i16**
// CHECK-DAG: store i[[SZ]] [[CSIZE]], i[[SZ]]* {{%[^,]+}}
// CHECK-NEXT: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
diff --git a/test/OpenMP/target_simd_codegen_registration.cpp b/test/OpenMP/target_simd_codegen_registration.cpp
index a6e6e9b38565..39e930a5d554 100644
--- a/test/OpenMP/target_simd_codegen_registration.cpp
+++ b/test/OpenMP/target_simd_codegen_registration.cpp
@@ -6,6 +6,14 @@
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// Test target simd codegen - host bc file has to be created first.
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s -check-prefix=TCHECK
@@ -16,9 +24,22 @@
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s -check-prefix=TCHECK
-// Check that no target code is emmitted if no omptests flag was provided.
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
+// Check that no target code is emitted if no omptests flag was provided.
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s -check-prefix=CHECK-NTARGET
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// SIMD-ONLY2-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -60,96 +81,96 @@
// We have 7 target regions
-// CHECK-DAG: {{@.+}} = private constant i8 0
-// TCHECK-NOT: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = weak constant i8 0
+// TCHECK-NOT: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
-// CHECK-NTARGET-NOT: private constant i8 0
+// CHECK-NTARGET-NOT: weak constant i8 0
// CHECK-NTARGET-NOT: private unnamed_addr constant [1 x i
// CHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// CHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY1:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// CHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY2:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// CHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY3:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// CHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY4:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// CHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY5:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// CHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY6:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// CHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY7:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// CHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY8:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// CHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY9:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// CHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY10:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// CHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY11:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// CHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY12:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// TCHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY1:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// TCHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY2:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// TCHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY3:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// TCHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY4:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// TCHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY5:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// TCHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY6:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// TCHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY7:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// TCHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY8:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// TCHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY9:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// TCHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY10:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// TCHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY11:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// TCHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY12:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
// CHECK: [[ENTEND:@.+]] = external constant [[ENTTY]]
@@ -163,7 +184,7 @@
// CHECK-SAME: { i32, void ()*, i8* } { i32 500, void ()* [[P500:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 501, void ()* [[P501:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 65535, void ()* [[PMAX:@[^,]+]], i8* null },
-// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
// CHECK-NTARGET: @llvm.global_ctors = appending global [3 x { i32, void ()*, i8* }] [
@@ -328,18 +349,18 @@ struct ST {
//CHECK-DAG: define internal void @[[NAME12]](
//CHECK-DAG: call void @[[NAME12]](
-//TCHECK-DAG: define void @[[NAME1]](
-//TCHECK-DAG: define void @[[NAME2]](
-//TCHECK-DAG: define void @[[NAME3]](
-//TCHECK-DAG: define void @[[NAME4]](
-//TCHECK-DAG: define void @[[NAME5]](
-//TCHECK-DAG: define void @[[NAME6]](
-//TCHECK-DAG: define void @[[NAME7]](
-//TCHECK-DAG: define void @[[NAME8]](
-//TCHECK-DAG: define void @[[NAME9]](
-//TCHECK-DAG: define void @[[NAME10]](
-//TCHECK-DAG: define void @[[NAME11]](
-//TCHECK-DAG: define void @[[NAME12]](
+//TCHECK-DAG: define weak void @[[NAME1]](
+//TCHECK-DAG: define weak void @[[NAME2]](
+//TCHECK-DAG: define weak void @[[NAME3]](
+//TCHECK-DAG: define weak void @[[NAME4]](
+//TCHECK-DAG: define weak void @[[NAME5]](
+//TCHECK-DAG: define weak void @[[NAME6]](
+//TCHECK-DAG: define weak void @[[NAME7]](
+//TCHECK-DAG: define weak void @[[NAME8]](
+//TCHECK-DAG: define weak void @[[NAME9]](
+//TCHECK-DAG: define weak void @[[NAME10]](
+//TCHECK-DAG: define weak void @[[NAME11]](
+//TCHECK-DAG: define weak void @[[NAME12]](
// CHECK-NTARGET-NOT: __tgt_target
// CHECK-NTARGET-NOT: __tgt_register_lib
@@ -381,7 +402,7 @@ struct ST {
//CHECK: ret void
//CHECK: declare i32 @__tgt_unregister_lib([[DSCTY]]*)
-//CHECK: define linkonce hidden void @[[REGFN]](i8*)
+//CHECK: define linkonce hidden void @[[REGFN]]()
//CHECK-SAME: comdat {
//CHECK: call i32 @__tgt_register_lib([[DSCTY]]* [[DESC]])
//CHECK: call i32 @__cxa_atexit(void (i8*)* @[[UNREGFN]], i8* bitcast ([[DSCTY]]* [[DESC]] to i8*),
@@ -421,31 +442,31 @@ int bar(int a){
// Check metadata is properly generated:
// CHECK: !omp_offload.info = !{!{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 195, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 247, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 265, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 272, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 284, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 291, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 415, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 298, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 291, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 298, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 284, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 221, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 216, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 268, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 286, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 293, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 305, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 312, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 436, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 319, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 312, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 319, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 305, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 242, i32 {{[0-9]+}}}
// TCHECK: !omp_offload.info = !{!{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 195, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 247, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 265, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 272, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 284, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 291, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 415, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 298, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 291, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 298, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 284, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 221, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 216, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 268, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 286, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 293, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 305, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 312, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 436, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 319, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 312, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 319, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 305, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 242, i32 {{[0-9]+}}}
#endif
diff --git a/test/OpenMP/target_simd_codegen_registration_naming.cpp b/test/OpenMP/target_simd_codegen_registration_naming.cpp
index 2ed74da4f05b..2de806ddeaf8 100644
--- a/test/OpenMP/target_simd_codegen_registration_naming.cpp
+++ b/test/OpenMP/target_simd_codegen_registration_naming.cpp
@@ -6,6 +6,14 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// Test target simd codegen - host bc file has to be created first.
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s -check-prefix=TCHECK
@@ -16,6 +24,16 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s -check-prefix=TCHECK
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/target_simd_collapse_messages.cpp b/test/OpenMP/target_simd_collapse_messages.cpp
index ce42273cd259..400844152b44 100644
--- a/test/OpenMP/target_simd_collapse_messages.cpp
+++ b/test/OpenMP/target_simd_collapse_messages.cpp
@@ -1,6 +1,9 @@
// RUN: %clang_cc1 -verify -fopenmp %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_simd_defaultmap_messages.cpp b/test/OpenMP/target_simd_defaultmap_messages.cpp
index 4f622136b13e..33e12c1e0e84 100644
--- a/test/OpenMP/target_simd_defaultmap_messages.cpp
+++ b/test/OpenMP/target_simd_defaultmap_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_simd_depend_codegen.cpp b/test/OpenMP/target_simd_depend_codegen.cpp
new file mode 100644
index 000000000000..ed34dd12dfb6
--- /dev/null
+++ b/test/OpenMP/target_simd_depend_codegen.cpp
@@ -0,0 +1,261 @@
+// Test host codegen.
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+// Test target codegen - host bc file has to be created first.
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+// CHECK-DAG: [[TT:%.+]] = type { i64, i8 }
+// CHECK-DAG: [[ENTTY:%.+]] = type { i8*, i8*, i[[SZ:32|64]], i32, i32 }
+// CHECK-DAG: [[DEVTY:%.+]] = type { i8*, i8*, [[ENTTY]]*, [[ENTTY]]* }
+// CHECK-DAG: [[DSCTY:%.+]] = type { i32, [[DEVTY]]*, [[ENTTY]]*, [[ENTTY]]* }
+
+// TCHECK: [[ENTTY:%.+]] = type { i8*, i8*, i{{32|64}}, i32, i32 }
+
+// CHECK-DAG: $[[REGFN:\.omp_offloading\..+]] = comdat
+
+// CHECK-DAG: [[SIZET:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 0, i[[SZ]] 4]
+// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 544, i64 800]
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = {{.*}}constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
+
+// Check if offloading descriptor is created.
+// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
+// CHECK: [[ENTEND:@.+]] = external constant [[ENTTY]]
+// CHECK: [[DEVBEGIN:@.+]] = external constant i8
+// CHECK: [[DEVEND:@.+]] = external constant i8
+// CHECK: [[IMAGES:@.+]] = internal unnamed_addr constant [1 x [[DEVTY]]] [{{.+}} { i8* [[DEVBEGIN]], i8* [[DEVEND]], [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }], comdat($[[REGFN]])
+// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
+
+// Check target registration is registered as a Ctor.
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
+
+
+template<typename tx, typename ty>
+struct TT{
+ tx X;
+ ty Y;
+};
+
+int global;
+extern int global;
+
+// CHECK: define {{.*}}[[FOO:@.+]](
+int foo(int n) {
+ int a = 0;
+ short aa = 0;
+ float b[10];
+ float bn[n];
+ double c[5][10];
+ double cn[5][n];
+ TT<long long, char> d;
+ static long *plocal;
+
+ // CHECK: [[ADD:%.+]] = add nsw i32
+ // CHECK: store i32 [[ADD]], i32* [[DEVICE_CAP:%.+]],
+ // CHECK: [[GEP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+ // CHECK: store i32 [[DEV]], i32* [[GEP]],
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* @0, i32 [[GTID:%.+]], i32 1, i[[SZ]] {{20|40}}, i[[SZ]] 4, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY0:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY0:%.+]]*
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 1
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 2
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 3
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call void @__kmpc_omp_wait_deps(%struct.ident_t* @0, i32 [[GTID]], i32 4, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: call void @__kmpc_omp_task_begin_if0(%struct.ident_t* @0, i32 [[GTID]], i8* [[TASK]])
+ // CHECK: call i32 [[TASK_ENTRY0]](i32 [[GTID]], [[TASK_TY0]]* [[BC_TASK]])
+ // CHECK: call void @__kmpc_omp_task_complete_if0(%struct.ident_t* @0, i32 [[GTID]], i8* [[TASK]])
+ #pragma omp target simd device(global + a) depend(in: global) depend(out: a, b, cn[4])
+ for (int i = 0; i < 10; ++i) {
+ }
+
+ // CHECK: [[ADD:%.+]] = add nsw i32
+ // CHECK: store i32 [[ADD]], i32* [[DEVICE_CAP:%.+]],
+
+ // CHECK: [[BOOL:%.+]] = icmp ne i32 %{{.+}}, 0
+ // CHECK: br i1 [[BOOL]], label %[[THEN:.+]], label %[[ELSE:.+]]
+ // CHECK: [[THEN]]:
+ // CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP:%.+]], i32 0, i32 0
+ // CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P:%.+]], i32 0, i32 0
+ // CHECK-DAG: [[CBPADDR0:%.+]] = bitcast i8** [[BPADDR0]] to i[[SZ]]**
+ // CHECK-DAG: [[CPADDR0:%.+]] = bitcast i8** [[PADDR0]] to i[[SZ]]**
+ // CHECK-DAG: store i[[SZ]]* [[BP0:%[^,]+]], i[[SZ]]** [[CBPADDR0]]
+ // CHECK-DAG: store i[[SZ]]* [[BP0]], i[[SZ]]** [[CPADDR0]]
+
+ // CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 1
+ // CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P]], i32 0, i32 1
+ // CHECK-DAG: [[CBPADDR1:%.+]] = bitcast i8** [[BPADDR1]] to i[[SZ]]*
+ // CHECK-DAG: [[CPADDR1:%.+]] = bitcast i8** [[PADDR1]] to i[[SZ]]*
+ // CHECK-DAG: store i[[SZ]] [[BP1:%[^,]+]], i[[SZ]]* [[CBPADDR1]]
+ // CHECK-DAG: store i[[SZ]] [[BP1]], i[[SZ]]* [[CPADDR1]]
+ // CHECK-DAG: getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 0
+ // CHECK-DAG: getelementptr inbounds [2 x i8*], [2 x i8*]* [[P]], i32 0, i32 0
+ // CHECK: [[GEP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+ // CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+ // CHECK: store i32 [[DEV]], i32* [[GEP]],
+
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* @0, i32 [[GTID]], i32 1, i[[SZ]] {{104|52}}, i[[SZ]] {{16|12}}, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY1_:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY1_:%.+]]*
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 1
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 2
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call i32 @__kmpc_omp_task_with_deps(%struct.ident_t* @0, i32 [[GTID]], i8* [[TASK]], i32 3, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: br label %[[EXIT:.+]]
+
+ // CHECK: [[ELSE]]:
+ // CHECK-NOT: getelementptr inbounds [2 x i8*], [2 x i8*]*
+ // CHECK: [[GEP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+ // CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+ // CHECK: store i32 [[DEV]], i32* [[GEP]],
+
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* @0, i32 [[GTID]], i32 1, i[[SZ]] {{56|28}}, i[[SZ]] {{16|12}}, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY1__:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY1__:%.+]]*
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 1
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 2
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call i32 @__kmpc_omp_task_with_deps(%struct.ident_t* @0, i32 [[GTID]], i8* [[TASK]], i32 3, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: br label %[[EXIT:.+]]
+ // CHECK: [[EXIT]]:
+
+ #pragma omp target simd device(global + a) nowait depend(inout: global, a, bn) if(a)
+ for (int i = 0; i < *plocal; ++i) {
+ static int local1;
+ *plocal = global;
+ local1 = global;
+ }
+
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* @0, i32 [[GTID]], i32 1, i[[SZ]] {{48|24}}, i[[SZ]] 4, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY2:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY2:%.+]]*
+ // CHECK: getelementptr inbounds [1 x %struct.kmp_depend_info], [1 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [1 x %struct.kmp_depend_info], [1 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call void @__kmpc_omp_wait_deps(%struct.ident_t* @0, i32 [[GTID]], i32 1, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: call void @__kmpc_omp_task_begin_if0(%struct.ident_t* @0, i32 [[GTID]], i8* [[TASK]])
+ // CHECK: call i32 [[TASK_ENTRY2]](i32 [[GTID]], [[TASK_TY2]]* [[BC_TASK]])
+ // CHECK: call void @__kmpc_omp_task_complete_if0(%struct.ident_t* @0, i32 [[GTID]], i8* [[TASK]])
+ #pragma omp target simd if(0) firstprivate(global) depend(out:global)
+ for (int i = 0; i < global; ++i) {
+ global += 1;
+ }
+
+ return a;
+}
+
+// Check that the offloading functions are emitted and that the arguments are
+// correct and loaded correctly for the target regions in foo().
+
+// CHECK: define internal void [[HVT0:@.+]]()
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY0]](i32{{.*}}, [[TASK_TY0]]* noalias)
+// CHECK: store void (i8*, ...)* null, void (i8*, ...)** %
+// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 0
+// CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+// CHECK: [[DEVICE:%.+]] = sext i32 [[DEV]] to i64
+// CHECK: [[RET:%.+]] = call i32 @__tgt_target(i64 [[DEVICE]], i8* @{{[^,]+}}, i32 0, i8** null, i8** null, i[[SZ]]* null, i64* null)
+// CHECK-NEXT: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
+// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
+// CHECK: [[FAIL]]
+// CHECK: call void [[HVT0]]()
+// CHECK-NEXT: br label %[[END]]
+// CHECK: [[END]]
+// CHECK: ret i32 0
+
+// CHECK: define internal void [[HVT1:@.+]](i[[SZ]]* %{{.+}}, i[[SZ]] %{{.+}})
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY1_]](i32{{.*}}, [[TASK_TY1_]]* noalias)
+// CHECK: call void (i8*, ...) %
+// CHECK: [[SZT:%.+]] = getelementptr inbounds [2 x i[[SZ]]], [2 x i[[SZ]]]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+// CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+// CHECK: [[DEVICE:%.+]] = sext i32 [[DEV]] to i64
+// CHECK: [[RET:%.+]] = call i32 @__tgt_target_nowait(i64 [[DEVICE]], i8* @{{[^,]+}}, i32 2, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SZT]], i64* getelementptr inbounds ([2 x i64], [2 x i64]* [[MAPT]], i32 0, i32 0)
+
+// CHECK: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
+// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
+// CHECK: [[FAIL]]
+// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
+// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
+// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
+// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
+// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
+// CHECK: [[BP1:%.+]] = load i[[SZ]], i[[SZ]]* [[BP1_PTR]],
+// CHECK: call void [[HVT1]](i[[SZ]]* [[BP0]], i[[SZ]] [[BP1]])
+// CHECK-NEXT: br label %[[END]]
+// CHECK: [[END]]
+// CHECK: ret i32 0
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY1__]](i32{{.*}}, [[TASK_TY1__]]* noalias)
+// CHECK: call void (i8*, ...) %
+// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
+// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
+// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
+// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
+// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
+// CHECK: [[BP1:%.+]] = load i[[SZ]], i[[SZ]]* [[BP1_PTR]],
+// CHECK: call void [[HVT1]](i[[SZ]]* [[BP0]], i[[SZ]] [[BP1]])
+// CHECK: ret i32 0
+
+// CHECK: define internal void [[HVT2:@.+]](i[[SZ]] %{{.+}})
+// Create stack storage and store argument in there.
+// CHECK: [[AA_ADDR:%.+]] = alloca i[[SZ]], align
+// CHECK: store i[[SZ]] %{{.+}}, i[[SZ]]* [[AA_ADDR]], align
+// CHECK-64: [[AA_CADDR:%.+]] = bitcast i[[SZ]]* [[AA_ADDR]] to i32*
+// CHECK-64: load i32, i32* [[AA_CADDR]], align
+// CHECK-32: load i32, i32* [[AA_ADDR]], align
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY2]](i32{{.*}}, [[TASK_TY2]]* noalias)
+// CHECK: call void (i8*, ...) %
+// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
+// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
+// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
+// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
+// CHECK: [[BP1:%.+]] = load i[[SZ]], i[[SZ]]* [[BP1_PTR]],
+// CHECK: call void [[HVT2]](i[[SZ]] [[BP1]])
+// CHECK: ret i32 0
+
+
+#endif
diff --git a/test/OpenMP/target_simd_depend_messages.cpp b/test/OpenMP/target_simd_depend_messages.cpp
index 89184f25d7a1..80f988d7a0e7 100644
--- a/test/OpenMP/target_simd_depend_messages.cpp
+++ b/test/OpenMP/target_simd_depend_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_simd_device_messages.cpp b/test/OpenMP/target_simd_device_messages.cpp
index 1e9afc3bb179..d705f6140285 100644
--- a/test/OpenMP/target_simd_device_messages.cpp
+++ b/test/OpenMP/target_simd_device_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_simd_firstprivate_messages.cpp b/test/OpenMP/target_simd_firstprivate_messages.cpp
index 5bfd951ff81e..85b216b4cbf6 100644
--- a/test/OpenMP/target_simd_firstprivate_messages.cpp
+++ b/test/OpenMP/target_simd_firstprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_simd_if_messages.cpp b/test/OpenMP/target_simd_if_messages.cpp
index ff68f6f21602..60dee37ac543 100644
--- a/test/OpenMP/target_simd_if_messages.cpp
+++ b/test/OpenMP/target_simd_if_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_simd_is_device_ptr_messages.cpp b/test/OpenMP/target_simd_is_device_ptr_messages.cpp
index 02e2b326c742..6d6bc247c806 100644
--- a/test/OpenMP/target_simd_is_device_ptr_messages.cpp
+++ b/test/OpenMP/target_simd_is_device_ptr_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -std=c++11 -verify -fopenmp %s
+// RUN: %clang_cc1 -std=c++11 -verify -fopenmp-simd %s
+
struct ST {
int *a;
};
diff --git a/test/OpenMP/target_simd_lastprivate_messages.cpp b/test/OpenMP/target_simd_lastprivate_messages.cpp
index 9a6eb241728b..ae8bd0af7b5f 100644
--- a/test/OpenMP/target_simd_lastprivate_messages.cpp
+++ b/test/OpenMP/target_simd_lastprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_simd_linear_messages.cpp b/test/OpenMP/target_simd_linear_messages.cpp
index 6319e31b3fb2..6a094b865185 100644
--- a/test/OpenMP/target_simd_linear_messages.cpp
+++ b/test/OpenMP/target_simd_linear_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
namespace X {
int x;
};
diff --git a/test/OpenMP/target_simd_loop_messages.cpp b/test/OpenMP/target_simd_loop_messages.cpp
index d33f1f4cdc65..760bfe0496c2 100644
--- a/test/OpenMP/target_simd_loop_messages.cpp
+++ b/test/OpenMP/target_simd_loop_messages.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s -Wno-openmp-target
class S {
int a;
diff --git a/test/OpenMP/target_simd_map_messages.cpp b/test/OpenMP/target_simd_map_messages.cpp
index 2473bbb49bea..3722ecb95ad1 100644
--- a/test/OpenMP/target_simd_map_messages.cpp
+++ b/test/OpenMP/target_simd_map_messages.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wno-openmp-target
void foo() {
}
diff --git a/test/OpenMP/target_simd_messages.cpp b/test/OpenMP/target_simd_messages.cpp
index d1b06e3b9030..aa259c069663 100644
--- a/test/OpenMP/target_simd_messages.cpp
+++ b/test/OpenMP/target_simd_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_simd_misc_messages.c b/test/OpenMP/target_simd_misc_messages.c
index debe38713826..3965d28af577 100644
--- a/test/OpenMP/target_simd_misc_messages.c
+++ b/test/OpenMP/target_simd_misc_messages.c
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -verify %s
+
// expected-error@+1 {{unexpected OpenMP directive '#pragma omp target simd'}}
#pragma omp target simd
diff --git a/test/OpenMP/target_simd_nowait_messages.cpp b/test/OpenMP/target_simd_nowait_messages.cpp
index 3635ce25956b..c7ab302cb0f9 100644
--- a/test/OpenMP/target_simd_nowait_messages.cpp
+++ b/test/OpenMP/target_simd_nowait_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_simd_private_messages.cpp b/test/OpenMP/target_simd_private_messages.cpp
index b20ff0a426a7..1b7d864c7c1f 100644
--- a/test/OpenMP/target_simd_private_messages.cpp
+++ b/test/OpenMP/target_simd_private_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
@@ -43,7 +45,7 @@ public:
S5(int v) : a(v) {}
S5 &operator=(S5 &s) {
#pragma omp target simd private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}}
- for (int k = 0; k < s.a; ++k)
+ for (int k = 0; k < s.a; ++k) // expected-warning {{Non-trivial type 'S5' is mapped, only trivial types are guaranteed to be mapped correctly}}
++s.a;
return *this;
}
diff --git a/test/OpenMP/target_simd_reduction_messages.cpp b/test/OpenMP/target_simd_reduction_messages.cpp
index 9e1bb0521d71..299c81315abe 100644
--- a/test/OpenMP/target_simd_reduction_messages.cpp
+++ b/test/OpenMP/target_simd_reduction_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_simd_safelen_messages.cpp b/test/OpenMP/target_simd_safelen_messages.cpp
index 79bee763498e..69ceab1a6836 100644
--- a/test/OpenMP/target_simd_safelen_messages.cpp
+++ b/test/OpenMP/target_simd_safelen_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_simd_simdlen_messages.cpp b/test/OpenMP/target_simd_simdlen_messages.cpp
index 8a9a3dc9f9b3..c65fe20d3a24 100644
--- a/test/OpenMP/target_simd_simdlen_messages.cpp
+++ b/test/OpenMP/target_simd_simdlen_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_ast_print.cpp b/test/OpenMP/target_teams_ast_print.cpp
index a80b8d7dac83..a0cb63535d68 100644
--- a/test/OpenMP/target_teams_ast_print.cpp
+++ b/test/OpenMP/target_teams_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -46,7 +50,7 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: T b = argc, c, d, e, f, g;
// CHECK-NEXT: static T a;
// CHECK-NEXT: S<T> s;
-// CHECK-NEXT: #pragma omp target teams
+// CHECK-NEXT: #pragma omp target teams{{$}}
// CHECK-NEXT: a = 2;
// CHECK-NEXT: #pragma omp target teams default(none) private(argc,b) firstprivate(argv) shared(d) reduction(+: c) reduction(max: e) num_teams(C) thread_limit(d * C)
// CHECK-NEXT: foo()
diff --git a/test/OpenMP/target_teams_codegen.cpp b/test/OpenMP/target_teams_codegen.cpp
index e6c250178d06..5c18a0cba3bb 100644
--- a/test/OpenMP/target_teams_codegen.cpp
+++ b/test/OpenMP/target_teams_codegen.cpp
@@ -1,28 +1,46 @@
// Test host codegen.
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// Test target codegen - host bc file has to be created first.
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-64
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-64
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-32
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
-// CHECK-DAG: %ident_t = type { i32, i32, i32, i32, i8* }
+// CHECK-DAG: %struct.ident_t = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr constant %ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
// CHECK-DAG: [[TT:%.+]] = type { i64, i8 }
// CHECK-DAG: [[S1:%.+]] = type { double }
@@ -34,38 +52,37 @@
// CHECK-DAG: $[[REGFN:\.omp_offloading\..+]] = comdat
-// We have 8 target regions, but only 7 that actually will generate offloading
-// code, only 6 will have mapped arguments, and only 4 have all-constant map
-// sizes.
+// We have 8 target regions, but only 6 that actually will generate offloading
+// code and have mapped arguments, and only 4 have all-constant map sizes.
// CHECK-DAG: [[SIZET:@.+]] = private unnamed_addr constant [3 x i[[SZ]]] [i[[SZ]] 2, i[[SZ]] 4, i[[SZ]] 4]
-// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [3 x i64] [i64 288, i64 288, i64 288]
-// CHECK-DAG: [[SIZET2:@.+]] = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 2]
-// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [1 x i64] [i64 288]
+// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [3 x i64] [i64 800, i64 800, i64 800]
+// CHECK-DAG: [[SIZET2:@.+]] = private unnamed_addr constant [1 x i{{32|64}}] [i[[SZ]] 2]
+// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [1 x i64] [i64 800]
// CHECK-DAG: [[SIZET3:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2]
-// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [2 x i64] [i64 288, i64 288]
-// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [9 x i64] [i64 288, i64 547, i64 288, i64 547, i64 547, i64 288, i64 288, i64 547, i64 547]
+// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [2 x i64] [i64 800, i64 800]
+// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [9 x i64] [i64 800, i64 547, i64 288, i64 547, i64 547, i64 288, i64 288, i64 547, i64 547]
// CHECK-DAG: [[SIZET5:@.+]] = private unnamed_addr constant [3 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2, i[[SZ]] 40]
-// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [3 x i64] [i64 288, i64 288, i64 547]
+// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [3 x i64] [i64 800, i64 800, i64 547]
// CHECK-DAG: [[SIZET6:@.+]] = private unnamed_addr constant [4 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2, i[[SZ]] 1, i[[SZ]] 40]
-// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [4 x i64] [i64 288, i64 288, i64 288, i64 547]
-// CHECK-DAG: [[MAPT7:@.+]] = private unnamed_addr constant [5 x i64] [i64 547, i64 288, i64 288, i64 288, i64 547]
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK-NOT: @{{.+}} = constant [[ENTTY]]
+// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [4 x i64] [i64 800, i64 800, i64 800, i64 547]
+// CHECK-DAG: [[MAPT7:@.+]] = private unnamed_addr constant [6 x i64] [i64 32, i64 281474976711171, i64 800, i64 288, i64 288, i64 547]
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -76,7 +93,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx, typename ty>
@@ -202,13 +219,13 @@ int foo(int n) {
// CHECK-32: store i32 [[A_VAL]], i32* [[A_CADDR:%.+]],
// CHECK-32: [[A_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[A_CADDR]],
+ // CHECK: [[IF:%.+]] = icmp sgt i32 {{[^,]+}}, 20
+ // CHECK: br i1 [[IF]], label %[[TRY:[^,]+]], label %[[FAIL:[^,]+]]
+ // CHECK: [[TRY]]
// CHECK: [[BNSIZE:%.+]] = mul nuw i[[SZ]] [[VLA0:%.+]], 4
// CHECK: [[CNELEMSIZE2:%.+]] = mul nuw i[[SZ]] 5, [[VLA1:%.+]]
// CHECK: [[CNSIZE:%.+]] = mul nuw i[[SZ]] [[CNELEMSIZE2]], 8
- // CHECK: [[IF:%.+]] = icmp sgt i32 {{[^,]+}}, 20
- // CHECK: br i1 [[IF]], label %[[TRY:[^,]+]], label %[[FAIL:[^,]+]]
- // CHECK: [[TRY]]
// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 9, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([9 x i64], [9 x i64]* [[MAPT4]], i32 0, i32 0), i32 0, i32 0)
// CHECK-DAG: [[BPR]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BP:%[^,]+]], i32 0, i32 0
// CHECK-DAG: [[PR]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P:%[^,]+]], i32 0, i32 0
@@ -323,11 +340,12 @@ int foo(int n) {
// correct and loaded correctly for the target regions in foo().
// CHECK: define internal void [[HVT0]](i[[SZ]] {{[^,]+}}, i[[SZ]] {{[^,]+}}, i[[SZ]] {{[^)]+}})
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]])* [[OMP_OUTLINED:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] {{[^)]+}})
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]])* [[OMP_OUTLINED:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] {{[^)]+}})
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] {{[^)]+}})
-// CHECK: alloca i16,
+// CHECK: alloca i[[SZ]],
+// CHECK: bitcast i[[SZ]]* {{.+}} to i16*
// CHECK: ret void
// CHECK-NEXT: }
@@ -344,7 +362,7 @@ int foo(int n) {
// CHECK-64: store i32 [[AA]], i32* [[AA_C]], align
// CHECK-32: store i32 [[AA]], i32* [[AA_CASTED]], align
// CHECK: [[PARAM:%.+]] = load i[[SZ]], i[[SZ]]* [[AA_CASTED]], align
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]])* [[OMP_OUTLINED1:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]])* [[OMP_OUTLINED1:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED1]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}})
@@ -366,7 +384,7 @@ int foo(int n) {
// CHECK: [[AA_C:%.+]] = bitcast i[[SZ]]* [[AA_CASTED]] to i16*
// CHECK: store i16 [[AA]], i16* [[AA_C]], align
// CHECK: [[PARAM:%.+]] = load i[[SZ]], i[[SZ]]* [[AA_CASTED]], align
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]])* [[OMP_OUTLINED2:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]])* [[OMP_OUTLINED2:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED2]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}})
@@ -397,7 +415,7 @@ int foo(int n) {
// CHECK-DAG: store i16 [[AA]], i16* [[AA_C]], align
// CHECK-DAG: [[PARAM1:%.+]] = load i[[SZ]], i[[SZ]]* [[A_CASTED]], align
// CHECK-DAG: [[PARAM2:%.+]] = load i[[SZ]], i[[SZ]]* [[AA_CASTED]], align
-// CHECK-DAG: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 2, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]])* [[OMP_OUTLINED3:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM1]], i[[SZ]] [[PARAM2]])
+// CHECK-DAG: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 2, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]])* [[OMP_OUTLINED3:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM1]], i[[SZ]] [[PARAM2]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED3]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}})
@@ -449,7 +467,7 @@ int foo(int n) {
// CHECK-32-DAG:store i32 [[LOCAL_AV]], i32* [[LOCAL_A_CASTED]], align
// CHECK-DAG: [[REF_A:%.+]] = load i[[SZ]], i[[SZ]]* [[LOCAL_A_CASTED]],
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 9, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], [10 x float]*, i[[SZ]], float*, [5 x [10 x double]]*, i[[SZ]], i[[SZ]], double*, [[TT]]*)* [[OMP_OUTLINED4:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], [10 x float]* [[REF_B]], i[[SZ]] [[VAL_VLA1]], float* [[REF_BN]], [5 x [10 x double]]* [[REF_C]], i[[SZ]] [[VAL_VLA2]], i[[SZ]] [[VAL_VLA3]], double* [[REF_CN]], [[TT]]* [[REF_D]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 9, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], [10 x float]*, i[[SZ]], float*, [5 x [10 x double]]*, i[[SZ]], i[[SZ]], double*, [[TT]]*)* [[OMP_OUTLINED4:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], [10 x float]* [[REF_B]], i[[SZ]] [[VAL_VLA1]], float* [[REF_BN]], [5 x [10 x double]]* [[REF_C]], i[[SZ]] [[VAL_VLA2]], i[[SZ]] [[VAL_VLA3]], double* [[REF_CN]], [[TT]]* [[REF_D]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED4]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}}, [10 x float]* {{.+}}, i[[SZ]] %{{.+}}, float* {{.+}}, [5 x [10 x double]]* {{.+}}, i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, double* {{.+}}, [[TT]]* {{.+}})
@@ -534,32 +552,36 @@ int bar(int n){
// CHECK-64: store i32 %{{.+}}, i32* [[B_ADDR]],
// CHECK-64: [[B_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[B_CADDR]],
+// CHECK-32: store i32 %{{.+}}, i32* %__vla_expr
// CHECK-32: store i32 %{{.+}}, i32* [[B_ADDR:%.+]],
// CHECK-32: [[B_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[B_ADDR]],
+// CHECK: [[IF:%.+]] = icmp sgt i32 {{[^,]+}}, 60
+// CHECK: br i1 [[IF]], label %[[TRY:[^,]+]], label %[[FAIL:[^,]+]]
+// CHECK: [[TRY]]
// We capture 2 VLA sizes in this target region
// CHECK: [[CELEMSIZE2:%.+]] = mul nuw i[[SZ]] 2, [[VLA0:%.+]]
// CHECK: [[CSIZE:%.+]] = mul nuw i[[SZ]] [[CELEMSIZE2]], 2
-// CHECK: [[IF:%.+]] = icmp sgt i32 {{[^,]+}}, 60
-// CHECK: br i1 [[IF]], label %[[TRY:[^,]+]], label %[[FAIL:[^,]+]]
-// CHECK: [[TRY]]
-// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 5, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([5 x i64], [5 x i64]* [[MAPT7]], i32 0, i32 0), i32 0, i32 0)
-// CHECK-DAG: [[BPR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP:%.+]], i32 0, i32 0
-// CHECK-DAG: [[PR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P:%.+]], i32 0, i32 0
-// CHECK-DAG: [[SR]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0
-// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX0:[0-9]+]]
-// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX0]]
-// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX0]]
-// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX1:[0-9]+]]
-// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX1]]
-// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX1]]
-// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX2:[0-9]+]]
-// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX2]]
-// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX2]]
-// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]]
-// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX3]]
-// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX3]]
+// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 6, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([6 x i64], [6 x i64]* [[MAPT7]], i32 0, i32 0), i32 0, i32 0)
+// CHECK-DAG: [[BPR]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP:%.+]], i32 0, i32 0
+// CHECK-DAG: [[PR]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P:%.+]], i32 0, i32 0
+// CHECK-DAG: [[SR]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0
+// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX0:[0-9]+]]
+// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX0]]
+// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX0]]
+// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX1:[0-9]+]]
+// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX1]]
+// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX1]]
+// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX2:[0-9]+]]
+// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX2]]
+// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX2]]
+// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]]
+// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX3]]
+// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX3]]
+// CHECK-DAG: [[SADDR4:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX4:[0-9]+]]
+// CHECK-DAG: [[BPADDR4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX4]]
+// CHECK-DAG: [[PADDR4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX4]]
// The names below are not necessarily consistent with the names used for the
// addresses above as some are repeated.
@@ -587,10 +609,16 @@ int bar(int n){
// CHECK-DAG: [[CPADDR3]] = bitcast i8** {{%[^,]+}} to [[S1]]**
// CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* {{%[^,]+}}
-// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR4:%.+]],
-// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR4:%.+]],
-// CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to i16**
-// CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to i16**
+// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CBPADDR4:%.+]],
+// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CPADDR4:%.+]],
+// CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to [[S1]]**
+// CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to [[S1]]**
+// CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* {{%[^,]+}}
+
+// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR5:%.+]],
+// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR5:%.+]],
+// CHECK-DAG: [[CBPADDR5]] = bitcast i8** {{%[^,]+}} to i16**
+// CHECK-DAG: [[CPADDR5]] = bitcast i8** {{%[^,]+}} to i16**
// CHECK-DAG: store i[[SZ]] [[CSIZE]], i[[SZ]]* {{%[^,]+}}
// CHECK-NEXT: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
@@ -726,7 +754,7 @@ int bar(int n){
// CHECK-32-DAG:store i32 [[LOCAL_BV]], i32* [[LOCAL_B_CASTED]], align
// CHECK-DAG: [[REF_B:%.+]] = load i[[SZ]], i[[SZ]]* [[LOCAL_B_CASTED]],
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 5, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, [[S1]]*, i[[SZ]], i[[SZ]], i[[SZ]], i16*)* [[OMP_OUTLINED5:@.+]] to void (i32*, i32*, ...)*), [[S1]]* [[REF_THIS]], i[[SZ]] [[REF_B]], i[[SZ]] [[VAL_VLA1]], i[[SZ]] [[VAL_VLA2]], i16* [[REF_C]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 5, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, [[S1]]*, i[[SZ]], i[[SZ]], i[[SZ]], i16*)* [[OMP_OUTLINED5:@.+]] to void (i32*, i32*, ...)*), [[S1]]* [[REF_THIS]], i[[SZ]] [[REF_B]], i[[SZ]] [[VAL_VLA1]], i[[SZ]] [[VAL_VLA2]], i16* [[REF_C]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED5]](i32* noalias %.global_tid., i32* noalias %.bound_tid., [[S1]]* %{{.+}}, i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, i16* {{.+}})
@@ -769,7 +797,7 @@ int bar(int n){
// CHECK-DAG: store i8 [[CONV_AAA]], i8* [[CONV]], align
// CHECK-DAG: [[REF_AAA:%.+]] = load i[[SZ]], i[[SZ]]* [[LOCAL_AAA_CASTED]],
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 4, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]], i[[SZ]], [10 x i32]*)* [[OMP_OUTLINED6:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], i[[SZ]] [[REF_AA]], i[[SZ]] [[REF_AAA]], [10 x i32]* [[REF_B]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 4, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]], i[[SZ]], [10 x i32]*)* [[OMP_OUTLINED6:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], i[[SZ]] [[REF_AA]], i[[SZ]] [[REF_AAA]], [10 x i32]* [[REF_B]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED6]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, [10 x i32]* {{.+}})
@@ -802,7 +830,7 @@ int bar(int n){
// CHECK-DAG: store i16 [[CONV_AA]], i16* [[CONV]], align
// CHECK-DAG: [[REF_AA:%.+]] = load i[[SZ]], i[[SZ]]* [[LOCAL_AA_CASTED]],
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]], [10 x i32]*)* [[OMP_OUTLINED7:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], i[[SZ]] [[REF_AA]], [10 x i32]* [[REF_B]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]], [10 x i32]*)* [[OMP_OUTLINED7:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], i[[SZ]] [[REF_AA]], [10 x i32]* [[REF_B]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED7]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, [10 x i32]* {{.+}})
diff --git a/test/OpenMP/target_teams_codegen_registration.cpp b/test/OpenMP/target_teams_codegen_registration.cpp
index 38668a46b161..e62be6813460 100644
--- a/test/OpenMP/target_teams_codegen_registration.cpp
+++ b/test/OpenMP/target_teams_codegen_registration.cpp
@@ -6,6 +6,14 @@
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// Test target teams codegen - host bc file has to be created first.
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s -check-prefix=TCHECK
@@ -16,9 +24,22 @@
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s -check-prefix=TCHECK
-// Check that no target code is emmitted if no omptests flag was provided.
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
+// Check that no target code is emitted if no omptests flag was provided.
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s -check-prefix=CHECK-NTARGET
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// SIMD-ONLY2-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -60,96 +81,96 @@
// We have 7 target regions
-// CHECK-DAG: {{@.+}} = private constant i8 0
-// TCHECK-NOT: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = weak constant i8 0
+// TCHECK-NOT: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
-// CHECK-NTARGET-NOT: private constant i8 0
+// CHECK-NTARGET-NOT: weak constant i8 0
// CHECK-NTARGET-NOT: private unnamed_addr constant [1 x i
// CHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// CHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY1:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// CHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY2:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// CHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY3:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// CHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY4:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// CHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY5:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// CHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY6:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// CHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY7:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// CHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY8:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// CHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY9:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// CHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY10:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// CHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY11:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// CHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY12:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// TCHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY1:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// TCHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY2:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// TCHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY3:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// TCHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY4:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// TCHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY5:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// TCHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY6:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// TCHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY7:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// TCHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY8:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// TCHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY9:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// TCHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY10:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// TCHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY11:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// TCHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY12:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
// CHECK: [[ENTEND:@.+]] = external constant [[ENTTY]]
@@ -163,7 +184,7 @@
// CHECK-SAME: { i32, void ()*, i8* } { i32 500, void ()* [[P500:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 501, void ()* [[P501:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 65535, void ()* [[PMAX:@[^,]+]], i8* null },
-// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
// CHECK-NTARGET: @llvm.global_ctors = appending global [3 x { i32, void ()*, i8* }] [
@@ -319,18 +340,18 @@ struct ST {
//CHECK-DAG: define internal void @[[NAME12]](
//CHECK-DAG: call void @[[NAME12]](
-//TCHECK-DAG: define void @[[NAME1]](
-//TCHECK-DAG: define void @[[NAME2]](
-//TCHECK-DAG: define void @[[NAME3]](
-//TCHECK-DAG: define void @[[NAME4]](
-//TCHECK-DAG: define void @[[NAME5]](
-//TCHECK-DAG: define void @[[NAME6]](
-//TCHECK-DAG: define void @[[NAME7]](
-//TCHECK-DAG: define void @[[NAME8]](
-//TCHECK-DAG: define void @[[NAME9]](
-//TCHECK-DAG: define void @[[NAME10]](
-//TCHECK-DAG: define void @[[NAME11]](
-//TCHECK-DAG: define void @[[NAME12]](
+//TCHECK-DAG: define weak void @[[NAME1]](
+//TCHECK-DAG: define weak void @[[NAME2]](
+//TCHECK-DAG: define weak void @[[NAME3]](
+//TCHECK-DAG: define weak void @[[NAME4]](
+//TCHECK-DAG: define weak void @[[NAME5]](
+//TCHECK-DAG: define weak void @[[NAME6]](
+//TCHECK-DAG: define weak void @[[NAME7]](
+//TCHECK-DAG: define weak void @[[NAME8]](
+//TCHECK-DAG: define weak void @[[NAME9]](
+//TCHECK-DAG: define weak void @[[NAME10]](
+//TCHECK-DAG: define weak void @[[NAME11]](
+//TCHECK-DAG: define weak void @[[NAME12]](
// CHECK-NTARGET-NOT: __tgt_target
// CHECK-NTARGET-NOT: __tgt_register_lib
@@ -372,7 +393,7 @@ struct ST {
//CHECK: ret void
//CHECK: declare i32 @__tgt_unregister_lib([[DSCTY]]*)
-//CHECK: define linkonce hidden void @[[REGFN]](i8*)
+//CHECK: define linkonce hidden void @[[REGFN]]()
//CHECK-SAME: comdat {
//CHECK: call i32 @__tgt_register_lib([[DSCTY]]* [[DESC]])
//CHECK: call i32 @__cxa_atexit(void (i8*)* @[[UNREGFN]], i8* bitcast ([[DSCTY]]* [[DESC]] to i8*),
@@ -411,31 +432,31 @@ int bar(int a){
// Check metadata is properly generated:
// CHECK: !omp_offload.info = !{!{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 195, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 245, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 261, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 267, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 278, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 284, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 406, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 290, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 284, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 290, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 278, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 220, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 216, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 266, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 282, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 288, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 299, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 305, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 427, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 311, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 305, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 311, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 299, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 241, i32 {{[0-9]+}}}
// TCHECK: !omp_offload.info = !{!{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 195, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 245, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 261, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 267, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 278, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 284, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 406, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 290, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 284, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 290, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 278, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 220, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 216, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 266, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 282, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 288, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 299, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 305, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 427, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 311, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 305, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 311, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 299, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 241, i32 {{[0-9]+}}}
#endif
diff --git a/test/OpenMP/target_teams_codegen_registration_naming.cpp b/test/OpenMP/target_teams_codegen_registration_naming.cpp
index fb4232897282..c09442d61d97 100644
--- a/test/OpenMP/target_teams_codegen_registration_naming.cpp
+++ b/test/OpenMP/target_teams_codegen_registration_naming.cpp
@@ -6,6 +6,14 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// Test target teams codegen - host bc file has to be created first.
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s -check-prefix=TCHECK
@@ -16,6 +24,16 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s -check-prefix=TCHECK
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/target_teams_default_messages.cpp b/test/OpenMP/target_teams_default_messages.cpp
index 053463749b5a..fa54416e6774 100644
--- a/test/OpenMP/target_teams_default_messages.cpp
+++ b/test/OpenMP/target_teams_default_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -o - %s
+
void foo();
int main(int argc, char **argv) {
diff --git a/test/OpenMP/target_teams_defaultmap_messages.cpp b/test/OpenMP/target_teams_defaultmap_messages.cpp
index f2d30fdc87e2..b1b2bdd38962 100644
--- a/test/OpenMP/target_teams_defaultmap_messages.cpp
+++ b/test/OpenMP/target_teams_defaultmap_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_depend_codegen.cpp b/test/OpenMP/target_teams_depend_codegen.cpp
new file mode 100644
index 000000000000..a5fbc5afc163
--- /dev/null
+++ b/test/OpenMP/target_teams_depend_codegen.cpp
@@ -0,0 +1,261 @@
+// Test host codegen.
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+// Test target codegen - host bc file has to be created first.
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+// CHECK-DAG: [[TT:%.+]] = type { i64, i8 }
+// CHECK-DAG: [[ENTTY:%.+]] = type { i8*, i8*, i[[SZ:32|64]], i32, i32 }
+// CHECK-DAG: [[DEVTY:%.+]] = type { i8*, i8*, [[ENTTY]]*, [[ENTTY]]* }
+// CHECK-DAG: [[DSCTY:%.+]] = type { i32, [[DEVTY]]*, [[ENTTY]]*, [[ENTTY]]* }
+
+// TCHECK: [[ENTTY:%.+]] = type { i8*, i8*, i{{32|64}}, i32, i32 }
+
+// CHECK-DAG: $[[REGFN:\.omp_offloading\..+]] = comdat
+
+// CHECK-DAG: [[SIZET:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 0, i[[SZ]] 4]
+// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 544, i64 800]
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = {{.*}}constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
+
+// Check if offloading descriptor is created.
+// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
+// CHECK: [[ENTEND:@.+]] = external constant [[ENTTY]]
+// CHECK: [[DEVBEGIN:@.+]] = external constant i8
+// CHECK: [[DEVEND:@.+]] = external constant i8
+// CHECK: [[IMAGES:@.+]] = internal unnamed_addr constant [1 x [[DEVTY]]] [{{.+}} { i8* [[DEVBEGIN]], i8* [[DEVEND]], [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }], comdat($[[REGFN]])
+// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
+
+// Check target registration is registered as a Ctor.
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
+
+
+template<typename tx, typename ty>
+struct TT{
+ tx X;
+ ty Y;
+};
+
+int global;
+extern int global;
+
+// CHECK: define {{.*}}[[FOO:@.+]](
+int foo(int n) {
+ int a = 0;
+ short aa = 0;
+ float b[10];
+ float bn[n];
+ double c[5][10];
+ double cn[5][n];
+ TT<long long, char> d;
+ static long *plocal;
+
+ // CHECK: [[ADD:%.+]] = add nsw i32
+ // CHECK: store i32 [[ADD]], i32* [[DEVICE_CAP:%.+]],
+ // CHECK: [[GEP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+ // CHECK: store i32 [[DEV]], i32* [[GEP]],
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* @0, i32 [[GTID:%.+]], i32 1, i[[SZ]] {{20|40}}, i[[SZ]] 4, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY0:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY0:%.+]]*
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 1
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 2
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 3
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call void @__kmpc_omp_wait_deps(%struct.ident_t* @0, i32 [[GTID]], i32 4, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: call void @__kmpc_omp_task_begin_if0(%struct.ident_t* @0, i32 [[GTID]], i8* [[TASK]])
+ // CHECK: call i32 [[TASK_ENTRY0]](i32 [[GTID]], [[TASK_TY0]]* [[BC_TASK]])
+ // CHECK: call void @__kmpc_omp_task_complete_if0(%struct.ident_t* @0, i32 [[GTID]], i8* [[TASK]])
+ #pragma omp target teams device(global + a) depend(in: global) depend(out: a, b, cn[4])
+ {
+ }
+
+ // CHECK: [[ADD:%.+]] = add nsw i32
+ // CHECK: store i32 [[ADD]], i32* [[DEVICE_CAP:%.+]],
+
+ // CHECK: [[BOOL:%.+]] = icmp ne i32 %{{.+}}, 0
+ // CHECK: br i1 [[BOOL]], label %[[THEN:.+]], label %[[ELSE:.+]]
+ // CHECK: [[THEN]]:
+ // CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP:%.+]], i32 0, i32 0
+ // CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P:%.+]], i32 0, i32 0
+ // CHECK-DAG: [[CBPADDR0:%.+]] = bitcast i8** [[BPADDR0]] to i[[SZ]]**
+ // CHECK-DAG: [[CPADDR0:%.+]] = bitcast i8** [[PADDR0]] to i[[SZ]]**
+ // CHECK-DAG: store i[[SZ]]* [[BP0:%[^,]+]], i[[SZ]]** [[CBPADDR0]]
+ // CHECK-DAG: store i[[SZ]]* [[BP0]], i[[SZ]]** [[CPADDR0]]
+
+ // CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 1
+ // CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P]], i32 0, i32 1
+ // CHECK-DAG: [[CBPADDR1:%.+]] = bitcast i8** [[BPADDR1]] to i[[SZ]]*
+ // CHECK-DAG: [[CPADDR1:%.+]] = bitcast i8** [[PADDR1]] to i[[SZ]]*
+ // CHECK-DAG: store i[[SZ]] [[BP1:%[^,]+]], i[[SZ]]* [[CBPADDR1]]
+ // CHECK-DAG: store i[[SZ]] [[BP1]], i[[SZ]]* [[CPADDR1]]
+ // CHECK-DAG: getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 0
+ // CHECK-DAG: getelementptr inbounds [2 x i8*], [2 x i8*]* [[P]], i32 0, i32 0
+ // CHECK: [[GEP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+ // CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+ // CHECK: store i32 [[DEV]], i32* [[GEP]],
+
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* @0, i32 [[GTID]], i32 1, i[[SZ]] {{104|52}}, i[[SZ]] {{16|12}}, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY1_:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY1_:%.+]]*
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 1
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 2
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call i32 @__kmpc_omp_task_with_deps(%struct.ident_t* @0, i32 [[GTID]], i8* [[TASK]], i32 3, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: br label %[[EXIT:.+]]
+
+ // CHECK: [[ELSE]]:
+ // CHECK-NOT: getelementptr inbounds [2 x i8*], [2 x i8*]*
+ // CHECK: [[GEP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+ // CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+ // CHECK: store i32 [[DEV]], i32* [[GEP]],
+
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* @0, i32 [[GTID]], i32 1, i[[SZ]] {{56|28}}, i[[SZ]] {{16|12}}, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY1__:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY1__:%.+]]*
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 1
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 2
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call i32 @__kmpc_omp_task_with_deps(%struct.ident_t* @0, i32 [[GTID]], i8* [[TASK]], i32 3, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: br label %[[EXIT:.+]]
+ // CHECK: [[EXIT]]:
+
+ #pragma omp target teams device(global + a) nowait depend(inout: global, a, bn) if(a)
+ {
+ static int local1;
+ *plocal = global;
+ local1 = global;
+ }
+
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* @0, i32 [[GTID]], i32 1, i[[SZ]] {{48|24}}, i[[SZ]] 4, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY2:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY2:%.+]]*
+ // CHECK: getelementptr inbounds [1 x %struct.kmp_depend_info], [1 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [1 x %struct.kmp_depend_info], [1 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call void @__kmpc_omp_wait_deps(%struct.ident_t* @0, i32 [[GTID]], i32 1, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: call void @__kmpc_omp_task_begin_if0(%struct.ident_t* @0, i32 [[GTID]], i8* [[TASK]])
+ // CHECK: call i32 [[TASK_ENTRY2]](i32 [[GTID]], [[TASK_TY2]]* [[BC_TASK]])
+ // CHECK: call void @__kmpc_omp_task_complete_if0(%struct.ident_t* @0, i32 [[GTID]], i8* [[TASK]])
+ #pragma omp target teams if(0) firstprivate(global) depend(out:global)
+ {
+ global += 1;
+ }
+
+ return a;
+}
+
+// Check that the offloading functions are emitted and that the arguments are
+// correct and loaded correctly for the target regions in foo().
+
+// CHECK: define internal void [[HVT0:@.+]]()
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY0]](i32{{.*}}, [[TASK_TY0]]* noalias)
+// CHECK: store void (i8*, ...)* null, void (i8*, ...)** %
+// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 0
+// CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+// CHECK: [[DEVICE:%.+]] = sext i32 [[DEV]] to i64
+// CHECK: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 [[DEVICE]], i8* @{{[^,]+}}, i32 0, i8** null, i8** null, i[[SZ]]* null, i64* null, i32 0, i32 0)
+// CHECK-NEXT: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
+// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
+// CHECK: [[FAIL]]
+// CHECK: call void [[HVT0]]()
+// CHECK-NEXT: br label %[[END]]
+// CHECK: [[END]]
+// CHECK: ret i32 0
+
+// CHECK: define internal void [[HVT1:@.+]](i[[SZ]]* %{{.+}}, i[[SZ]] %{{.+}})
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY1_]](i32{{.*}}, [[TASK_TY1_]]* noalias)
+// CHECK: call void (i8*, ...) %
+// CHECK: [[SZT:%.+]] = getelementptr inbounds [2 x i[[SZ]]], [2 x i[[SZ]]]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+// CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+// CHECK: [[DEVICE:%.+]] = sext i32 [[DEV]] to i64
+// CHECK: [[RET:%.+]] = call i32 @__tgt_target_teams_nowait(i64 [[DEVICE]], i8* @{{[^,]+}}, i32 2, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SZT]], i64* getelementptr inbounds ([2 x i64], [2 x i64]* [[MAPT]], i32 0, i32 0), i32 0, i32 0)
+
+// CHECK: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
+// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
+// CHECK: [[FAIL]]
+// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
+// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
+// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
+// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
+// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
+// CHECK: [[BP1:%.+]] = load i[[SZ]], i[[SZ]]* [[BP1_PTR]],
+// CHECK: call void [[HVT1]](i[[SZ]]* [[BP0]], i[[SZ]] [[BP1]])
+// CHECK-NEXT: br label %[[END]]
+// CHECK: [[END]]
+// CHECK: ret i32 0
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY1__]](i32{{.*}}, [[TASK_TY1__]]* noalias)
+// CHECK: call void (i8*, ...) %
+// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
+// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
+// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
+// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
+// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
+// CHECK: [[BP1:%.+]] = load i[[SZ]], i[[SZ]]* [[BP1_PTR]],
+// CHECK: call void [[HVT1]](i[[SZ]]* [[BP0]], i[[SZ]] [[BP1]])
+// CHECK: ret i32 0
+
+// CHECK: define internal void [[HVT2:@.+]](i[[SZ]] %{{.+}})
+// Create stack storage and store argument in there.
+// CHECK: [[AA_ADDR:%.+]] = alloca i[[SZ]], align
+// CHECK: store i[[SZ]] %{{.+}}, i[[SZ]]* [[AA_ADDR]], align
+// CHECK-64: [[AA_CADDR:%.+]] = bitcast i[[SZ]]* [[AA_ADDR]] to i32*
+// CHECK-64: load i32, i32* [[AA_CADDR]], align
+// CHECK-32: load i32, i32* [[AA_ADDR]], align
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY2]](i32{{.*}}, [[TASK_TY2]]* noalias)
+// CHECK: call void (i8*, ...) %
+// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
+// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
+// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
+// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
+// CHECK: [[BP1:%.+]] = load i[[SZ]], i[[SZ]]* [[BP1_PTR]],
+// CHECK: call void [[HVT2]](i[[SZ]] [[BP1]])
+// CHECK: ret i32 0
+
+
+#endif
diff --git a/test/OpenMP/target_teams_depend_messages.cpp b/test/OpenMP/target_teams_depend_messages.cpp
index 57983eec8882..235ce98ee945 100644
--- a/test/OpenMP/target_teams_depend_messages.cpp
+++ b/test/OpenMP/target_teams_depend_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_device_messages.cpp b/test/OpenMP/target_teams_device_messages.cpp
index bd75da835158..da56c470fb6e 100644
--- a/test/OpenMP/target_teams_device_messages.cpp
+++ b/test/OpenMP/target_teams_device_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_ast_print.cpp b/test/OpenMP/target_teams_distribute_ast_print.cpp
index ae50366aabb3..4484451c4907 100644
--- a/test/OpenMP/target_teams_distribute_ast_print.cpp
+++ b/test/OpenMP/target_teams_distribute_ast_print.cpp
@@ -1,6 +1,10 @@
-// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -ast-print %s -Wno-openmp-target | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-target | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s -Wno-openmp-target | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-target | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -81,7 +85,7 @@ T tmain(T argc) {
#pragma omp target teams distribute
for (int i=0; i < 2; ++i)
a = 2;
-// CHECK: #pragma omp target teams distribute
+// CHECK: #pragma omp target teams distribute{{$}}
// CHECK-NEXT: for (int i = 0; i < 2; ++i)
// CHECK-NEXT: a = 2;
#pragma omp target teams distribute private(argc, b), firstprivate(c, d), collapse(2)
diff --git a/test/OpenMP/target_teams_distribute_codegen.cpp b/test/OpenMP/target_teams_distribute_codegen.cpp
index 17baa603d12b..f9500a73ef79 100644
--- a/test/OpenMP/target_teams_distribute_codegen.cpp
+++ b/test/OpenMP/target_teams_distribute_codegen.cpp
@@ -1,28 +1,46 @@
// Test host codegen.
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// Test target codegen - host bc file has to be created first.
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-64
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-64
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-32
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
-// CHECK-DAG: %ident_t = type { i32, i32, i32, i32, i8* }
+// CHECK-DAG: %struct.ident_t = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr constant %ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
// CHECK-DAG: [[TT:%.+]] = type { i64, i8 }
// CHECK-DAG: [[S1:%.+]] = type { double }
@@ -39,33 +57,33 @@
// sizes.
// CHECK-DAG: [[SIZET:@.+]] = private unnamed_addr constant [3 x i[[SZ]]] [i[[SZ]] 2, i[[SZ]] 4, i[[SZ]] 4]
-// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [3 x i64] [i64 288, i64 288, i64 288]
+// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [3 x i64] [i64 800, i64 800, i64 800]
// CHECK-DAG: [[SIZET2:@.+]] = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 2]
-// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [1 x i64] [i64 288]
+// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [1 x i64] [i64 800]
// CHECK-DAG: [[SIZET3:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2]
-// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [2 x i64] [i64 288, i64 288]
-// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [9 x i64] [i64 288, i64 547, i64 288, i64 547, i64 547, i64 288, i64 288, i64 547, i64 547]
-// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [5 x i64] [i64 547, i64 288, i64 288, i64 288, i64 547]
+// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [2 x i64] [i64 800, i64 800]
+// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [10 x i64] [i64 800, i64 547, i64 288, i64 547, i64 547, i64 288, i64 288, i64 547, i64 547, i64 800]
+// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [6 x i64] [i64 32, i64 281474976711171, i64 800, i64 288, i64 288, i64 547]
// CHECK-DAG: [[SIZET6:@.+]] = private unnamed_addr constant [5 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 4, i[[SZ]] 2, i[[SZ]] 1, i[[SZ]] 40]
-// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [5 x i64] [i64 288, i64 288, i64 288, i64 288, i64 547]
+// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [5 x i64] [i64 800, i64 800, i64 800, i64 800, i64 547]
// CHECK-DAG: [[SIZET7:@.+]] = private unnamed_addr constant [3 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2, i[[SZ]] 40]
-// CHECK-DAG: [[MAPT7:@.+]] = private unnamed_addr constant [3 x i64] [i64 288, i64 288, i64 547]
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK-NOT: @{{.+}} = constant [[ENTTY]]
+// CHECK-DAG: [[MAPT7:@.+]] = private unnamed_addr constant [3 x i64] [i64 800, i64 800, i64 547]
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -76,7 +94,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx, typename ty>
@@ -193,6 +211,7 @@ int foo(int n) {
}
// We capture 3 VLA sizes in this target region
+ // CHECK: load i32, i32* %
// CHECK-64: [[A_VAL:%.+]] = load i32, i32* %{{.+}},
// CHECK-64: [[A_ADDR:%.+]] = bitcast i[[SZ]]* [[A_CADDR:%.+]] to i32*
// CHECK-64: store i32 [[A_VAL]], i32* [[A_ADDR]],
@@ -202,45 +221,48 @@ int foo(int n) {
// CHECK-32: store i32 [[A_VAL]], i32* [[A_CADDR:%.+]],
// CHECK-32: [[A_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[A_CADDR]],
+ // CHECK: [[IF:%.+]] = icmp sgt i32 {{[^,]+}}, 20
+ // CHECK: br i1 [[IF]], label %[[TRY:[^,]+]], label %[[FAIL:[^,]+]]
+ // CHECK: [[TRY]]
// CHECK: [[BNSIZE:%.+]] = mul nuw i[[SZ]] [[VLA0:%.+]], 4
// CHECK: [[CNELEMSIZE2:%.+]] = mul nuw i[[SZ]] 5, [[VLA1:%.+]]
// CHECK: [[CNSIZE:%.+]] = mul nuw i[[SZ]] [[CNELEMSIZE2]], 8
- // CHECK: [[IF:%.+]] = icmp sgt i32 {{[^,]+}}, 20
- // CHECK: br i1 [[IF]], label %[[TRY:[^,]+]], label %[[FAIL:[^,]+]]
- // CHECK: [[TRY]]
- // CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 9, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([9 x i64], [9 x i64]* [[MAPT4]], i32 0, i32 0), i32 0, i32 0)
- // CHECK-DAG: [[BPR]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BP:%[^,]+]], i32 0, i32 0
- // CHECK-DAG: [[PR]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P:%[^,]+]], i32 0, i32 0
- // CHECK-DAG: [[SR]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S:%[^,]+]], i32 0, i32 0
-
- // CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX0:[0-9]+]]
- // CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BP]], i32 0, i32 [[IDX0]]
- // CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P]], i32 0, i32 [[IDX0]]
- // CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX1:[0-9]+]]
- // CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BP]], i32 0, i32 [[IDX1]]
- // CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P]], i32 0, i32 [[IDX1]]
- // CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX2:[0-9]+]]
- // CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BP]], i32 0, i32 [[IDX2]]
- // CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P]], i32 0, i32 [[IDX2]]
- // CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX3:[0-9]+]]
- // CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BP]], i32 0, i32 [[IDX3]]
- // CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P]], i32 0, i32 [[IDX3]]
- // CHECK-DAG: [[SADDR4:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX4:[0-9]+]]
- // CHECK-DAG: [[BPADDR4:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BP]], i32 0, i32 [[IDX4]]
- // CHECK-DAG: [[PADDR4:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P]], i32 0, i32 [[IDX4]]
- // CHECK-DAG: [[SADDR5:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX5:[0-9]+]]
- // CHECK-DAG: [[BPADDR5:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BP]], i32 0, i32 [[IDX5]]
- // CHECK-DAG: [[PADDR5:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P]], i32 0, i32 [[IDX5]]
- // CHECK-DAG: [[SADDR6:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX6:[0-9]+]]
- // CHECK-DAG: [[BPADDR6:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BP]], i32 0, i32 [[IDX6]]
- // CHECK-DAG: [[PADDR6:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P]], i32 0, i32 [[IDX6]]
- // CHECK-DAG: [[SADDR7:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX7:[0-9]+]]
- // CHECK-DAG: [[BPADDR7:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BP]], i32 0, i32 [[IDX7]]
- // CHECK-DAG: [[PADDR7:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P]], i32 0, i32 [[IDX7]]
- // CHECK-DAG: [[SADDR8:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX8:[0-9]+]]
- // CHECK-DAG: [[BPADDR8:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BP]], i32 0, i32 [[IDX8]]
- // CHECK-DAG: [[PADDR8:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P]], i32 0, i32 [[IDX8]]
+ // CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 10, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([10 x i64], [10 x i64]* [[MAPT4]], i32 0, i32 0), i32 0, i32 0)
+ // CHECK-DAG: [[BPR]] = getelementptr inbounds [10 x i8*], [10 x i8*]* [[BP:%[^,]+]], i32 0, i32 0
+ // CHECK-DAG: [[PR]] = getelementptr inbounds [10 x i8*], [10 x i8*]* [[P:%[^,]+]], i32 0, i32 0
+ // CHECK-DAG: [[SR]] = getelementptr inbounds [10 x i[[SZ]]], [10 x i[[SZ]]]* [[S:%[^,]+]], i32 0, i32 0
+
+ // CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [10 x i[[SZ]]], [10 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX0:[0-9]+]]
+ // CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [10 x i8*], [10 x i8*]* [[BP]], i32 0, i32 [[IDX0]]
+ // CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [10 x i8*], [10 x i8*]* [[P]], i32 0, i32 [[IDX0]]
+ // CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [10 x i[[SZ]]], [10 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX1:[0-9]+]]
+ // CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [10 x i8*], [10 x i8*]* [[BP]], i32 0, i32 [[IDX1]]
+ // CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [10 x i8*], [10 x i8*]* [[P]], i32 0, i32 [[IDX1]]
+ // CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [10 x i[[SZ]]], [10 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX2:[0-9]+]]
+ // CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [10 x i8*], [10 x i8*]* [[BP]], i32 0, i32 [[IDX2]]
+ // CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [10 x i8*], [10 x i8*]* [[P]], i32 0, i32 [[IDX2]]
+ // CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [10 x i[[SZ]]], [10 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX3:[0-9]+]]
+ // CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [10 x i8*], [10 x i8*]* [[BP]], i32 0, i32 [[IDX3]]
+ // CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [10 x i8*], [10 x i8*]* [[P]], i32 0, i32 [[IDX3]]
+ // CHECK-DAG: [[SADDR4:%.+]] = getelementptr inbounds [10 x i[[SZ]]], [10 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX4:[0-9]+]]
+ // CHECK-DAG: [[BPADDR4:%.+]] = getelementptr inbounds [10 x i8*], [10 x i8*]* [[BP]], i32 0, i32 [[IDX4]]
+ // CHECK-DAG: [[PADDR4:%.+]] = getelementptr inbounds [10 x i8*], [10 x i8*]* [[P]], i32 0, i32 [[IDX4]]
+ // CHECK-DAG: [[SADDR5:%.+]] = getelementptr inbounds [10 x i[[SZ]]], [10 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX5:[0-9]+]]
+ // CHECK-DAG: [[BPADDR5:%.+]] = getelementptr inbounds [10 x i8*], [10 x i8*]* [[BP]], i32 0, i32 [[IDX5]]
+ // CHECK-DAG: [[PADDR5:%.+]] = getelementptr inbounds [10 x i8*], [10 x i8*]* [[P]], i32 0, i32 [[IDX5]]
+ // CHECK-DAG: [[SADDR6:%.+]] = getelementptr inbounds [10 x i[[SZ]]], [10 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX6:[0-9]+]]
+ // CHECK-DAG: [[BPADDR6:%.+]] = getelementptr inbounds [10 x i8*], [10 x i8*]* [[BP]], i32 0, i32 [[IDX6]]
+ // CHECK-DAG: [[PADDR6:%.+]] = getelementptr inbounds [10 x i8*], [10 x i8*]* [[P]], i32 0, i32 [[IDX6]]
+ // CHECK-DAG: [[SADDR7:%.+]] = getelementptr inbounds [10 x i[[SZ]]], [10 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX7:[0-9]+]]
+ // CHECK-DAG: [[BPADDR7:%.+]] = getelementptr inbounds [10 x i8*], [10 x i8*]* [[BP]], i32 0, i32 [[IDX7]]
+ // CHECK-DAG: [[PADDR7:%.+]] = getelementptr inbounds [10 x i8*], [10 x i8*]* [[P]], i32 0, i32 [[IDX7]]
+ // CHECK-DAG: [[SADDR8:%.+]] = getelementptr inbounds [10 x i[[SZ]]], [10 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX8:[0-9]+]]
+ // CHECK-DAG: [[BPADDR8:%.+]] = getelementptr inbounds [10 x i8*], [10 x i8*]* [[BP]], i32 0, i32 [[IDX8]]
+ // CHECK-DAG: [[PADDR8:%.+]] = getelementptr inbounds [10 x i8*], [10 x i8*]* [[P]], i32 0, i32 [[IDX8]]
+ // CHECK-DAG: [[SADDR9:%.+]] = getelementptr inbounds [10 x i[[SZ]]], [10 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX9:[0-9]+]]
+ // CHECK-DAG: [[BPADDR9:%.+]] = getelementptr inbounds [10 x i8*], [10 x i8*]* [[BP]], i32 0, i32 [[IDX9]]
+ // CHECK-DAG: [[PADDR9:%.+]] = getelementptr inbounds [10 x i8*], [10 x i8*]* [[P]], i32 0, i32 [[IDX9]]
// The names below are not necessarily consistent with the names used for the
// addresses above as some are repeated.
@@ -298,14 +320,20 @@ int foo(int n) {
// CHECK-DAG: [[CPADDR8]] = bitcast i8** {{%[^,]+}} to [[TT]]**
// CHECK-DAG: store i[[SZ]] {{12|16}}, i[[SZ]]* {{%[^,]+}}
+ // CHECK-DAG: store i[[SZ]] %{{.+}}, i[[SZ]]* [[CBPADDR9:%.+]],
+ // CHECK-DAG: store i[[SZ]] %{{.+}}, i[[SZ]]* [[CPADDR9:%.+]],
+ // CHECK-DAG: [[CBPADDR9]] = bitcast i8** {{%[^,]+}} to i[[SZ]]*
+ // CHECK-DAG: [[CPADDR9]] = bitcast i8** {{%[^,]+}} to i[[SZ]]*
+ // CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* {{%[^,]+}}
+
// CHECK-NEXT: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
// CHECK: [[FAIL]]
- // CHECK: call void [[HVT4:@.+]]({{[^,]+}}, {{[^,]+}}, {{[^,]+}}, {{[^,]+}}, {{[^,]+}}, {{[^,]+}}, {{[^,]+}}, {{[^,]+}}, {{[^,]+}})
+ // CHECK: call void [[HVT4:@.+]]({{[^,]+}}, {{[^,]+}}, {{[^,]+}}, {{[^,]+}}, {{[^,]+}}, {{[^,]+}}, {{[^,]+}}, {{[^,]+}}, {{[^,]+}}, {{[^,]+}})
// CHECK-NEXT: br label %[[END]]
// CHECK: [[END]]
- #pragma omp target teams distribute if(target: n>20)
+ #pragma omp target teams distribute if(target: n>20) dist_schedule(static, n)
for (int i = 0; i < 10; ++i) {
a += 1;
b[2] += 1.0;
@@ -323,11 +351,12 @@ int foo(int n) {
// correct and loaded correctly for the target regions in foo().
// CHECK: define internal void [[HVT0]](i[[SZ]] {{[^,]+}}, i[[SZ]] {{[^,]+}}, i[[SZ]] {{[^)]+}})
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]])* [[OMP_OUTLINED:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] {{[^)]+}})
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]])* [[OMP_OUTLINED:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] {{[^)]+}})
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] {{[^)]+}})
-// CHECK: alloca i16,
+// CHECK: alloca i[[SZ]],
+// CHECK: bitcast i[[SZ]]* {{.+}} to i16*
// CHECK: ret void
// CHECK-NEXT: }
@@ -344,7 +373,7 @@ int foo(int n) {
// CHECK-64: store i32 [[AA]], i32* [[AA_C]], align
// CHECK-32: store i32 [[AA]], i32* [[AA_CASTED]], align
// CHECK: [[PARAM:%.+]] = load i[[SZ]], i[[SZ]]* [[AA_CASTED]], align
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]])* [[OMP_OUTLINED1:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]])* [[OMP_OUTLINED1:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED1]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}})
@@ -366,7 +395,7 @@ int foo(int n) {
// CHECK: [[AA_C:%.+]] = bitcast i[[SZ]]* [[AA_CASTED]] to i16*
// CHECK: store i16 [[AA]], i16* [[AA_C]], align
// CHECK: [[PARAM:%.+]] = load i[[SZ]], i[[SZ]]* [[AA_CASTED]], align
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]])* [[OMP_OUTLINED2:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]])* [[OMP_OUTLINED2:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED2]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}})
@@ -397,7 +426,7 @@ int foo(int n) {
// CHECK-DAG: store i16 [[AA]], i16* [[AA_C]], align
// CHECK-DAG: [[PARAM1:%.+]] = load i[[SZ]], i[[SZ]]* [[A_CASTED]], align
// CHECK-DAG: [[PARAM2:%.+]] = load i[[SZ]], i[[SZ]]* [[AA_CASTED]], align
-// CHECK-DAG: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 2, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]])* [[OMP_OUTLINED3:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM1]], i[[SZ]] [[PARAM2]])
+// CHECK-DAG: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 2, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]])* [[OMP_OUTLINED3:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM1]], i[[SZ]] [[PARAM2]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED3]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}})
@@ -421,6 +450,7 @@ int foo(int n) {
// CHECK: [[LOCAL_VLA3:%.+]] = alloca i[[SZ]]
// CHECK: [[LOCAL_CN:%.+]] = alloca double*
// CHECK: [[LOCAL_D:%.+]] = alloca [[TT]]*
+// CHECK: alloca i[[SZ]],
// CHECK: [[LOCAL_A_CASTED:%.+]] = alloca i[[SZ]]
// CHECK-DAG: store i[[SZ]] [[ARG_A:%.+]], i[[SZ]]* [[LOCAL_A]]
// CHECK-DAG: store [10 x float]* [[ARG_B:%.+]], [10 x float]** [[LOCAL_B]]
@@ -449,7 +479,7 @@ int foo(int n) {
// CHECK-32-DAG:store i32 [[LOCAL_AV]], i32* [[LOCAL_A_CASTED]], align
// CHECK-DAG: [[REF_A:%.+]] = load i[[SZ]], i[[SZ]]* [[LOCAL_A_CASTED]],
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 9, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], [10 x float]*, i[[SZ]], float*, [5 x [10 x double]]*, i[[SZ]], i[[SZ]], double*, [[TT]]*)* [[OMP_OUTLINED4:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], [10 x float]* [[REF_B]], i[[SZ]] [[VAL_VLA1]], float* [[REF_BN]], [5 x [10 x double]]* [[REF_C]], i[[SZ]] [[VAL_VLA2]], i[[SZ]] [[VAL_VLA3]], double* [[REF_CN]], [[TT]]* [[REF_D]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 10, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], [10 x float]*, i[[SZ]], float*, [5 x [10 x double]]*, i[[SZ]], i[[SZ]], double*, [[TT]]*, i[[SZ]])* [[OMP_OUTLINED4:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], [10 x float]* [[REF_B]], i[[SZ]] [[VAL_VLA1]], float* [[REF_BN]], [5 x [10 x double]]* [[REF_C]], i[[SZ]] [[VAL_VLA2]], i[[SZ]] [[VAL_VLA3]], double* [[REF_CN]], [[TT]]* [[REF_D]], i[[SZ]] %{{.+}})
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED4]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}}, [10 x float]* {{.+}}, i[[SZ]] %{{.+}}, float* {{.+}}, [5 x [10 x double]]* {{.+}}, i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, double* {{.+}}, [[TT]]* {{.+}})
@@ -534,32 +564,39 @@ int bar(int n){
// CHECK-64: store i32 %{{.+}}, i32* [[B_ADDR]],
// CHECK-64: [[B_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[B_CADDR]],
+// CHECK-32: store i32 %{{.+}}, i32* %__vla_expr
// CHECK-32: store i32 %{{.+}}, i32* [[B_ADDR:%.+]],
// CHECK-32: [[B_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[B_ADDR]],
+// CHECK: [[IF:%.+]] = icmp sgt i32 {{[^,]+}}, 60
+// CHECK: br i1 [[IF]], label %[[TRY:[^,]+]], label %[[FAIL:[^,]+]]
+// CHECK: [[TRY]]
// We capture 2 VLA sizes in this target region
// CHECK: [[CELEMSIZE2:%.+]] = mul nuw i[[SZ]] 2, [[VLA0:%.+]]
// CHECK: [[CSIZE:%.+]] = mul nuw i[[SZ]] [[CELEMSIZE2]], 2
-// CHECK: [[IF:%.+]] = icmp sgt i32 {{[^,]+}}, 60
-// CHECK: br i1 [[IF]], label %[[TRY:[^,]+]], label %[[FAIL:[^,]+]]
-// CHECK: [[TRY]]
-// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 5, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([5 x i64], [5 x i64]* [[MAPT5]], i32 0, i32 0), i32 0, i32 0)
-// CHECK-DAG: [[BPR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP:%.+]], i32 0, i32 0
-// CHECK-DAG: [[PR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P:%.+]], i32 0, i32 0
-// CHECK-DAG: [[SR]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0
-// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX0:[0-9]+]]
-// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX0]]
-// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX0]]
-// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX1:[0-9]+]]
-// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX1]]
-// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX1]]
-// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX2:[0-9]+]]
-// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX2]]
-// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX2]]
-// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]]
-// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX3]]
-// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX3]]
+// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 6, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([6 x i64], [6 x i64]* [[MAPT5]], i32 0, i32 0), i32 0, i32 0)
+// CHECK-DAG: [[BPR]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP:%.+]], i32 0, i32 0
+// CHECK-DAG: [[PR]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P:%.+]], i32 0, i32 0
+// CHECK-DAG: [[SR]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0
+// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX0:[0-9]+]]
+// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX0]]
+// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX0]]
+// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX1:[0-9]+]]
+// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX1]]
+// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX1]]
+// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX2:[0-9]+]]
+// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX2]]
+// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX2]]
+// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]]
+// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX3]]
+// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX3]]
+// CHECK-DAG: [[SADDR4:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]]
+// CHECK-DAG: [[BPADDR4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX3]]
+// CHECK-DAG: [[PADDR4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX3]]
+// CHECK-DAG: [[SADDR5:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]]
+// CHECK-DAG: [[BPADDR5:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX3]]
+// CHECK-DAG: [[PADDR5:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX3]]
// The names below are not necessarily consistent with the names used for the
// addresses above as some are repeated.
@@ -582,15 +619,21 @@ int bar(int n){
// CHECK-DAG: store i[[SZ]] 4, i[[SZ]]* {{%[^,]+}}
// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CBPADDR3:%.+]],
-// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CPADDR3:%.+]],
+// CHECK-DAG: store double* %{{.+}}, double** [[CPADDR3:%.+]],
// CHECK-DAG: [[CBPADDR3]] = bitcast i8** {{%[^,]+}} to [[S1]]**
-// CHECK-DAG: [[CPADDR3]] = bitcast i8** {{%[^,]+}} to [[S1]]**
+// CHECK-DAG: [[CPADDR3]] = bitcast i8** {{%[^,]+}} to double**
+// CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* {{%[^,]+}}
+
+// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CBPADDR4:%.+]],
+// CHECK-DAG: store double* %{{.+}}, double** [[CPADDR4:%.+]],
+// CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to [[S1]]**
+// CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to double**
// CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* {{%[^,]+}}
-// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR4:%.+]],
-// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR4:%.+]],
-// CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to i16**
-// CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to i16**
+// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR5:%.+]],
+// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR5:%.+]],
+// CHECK-DAG: [[CBPADDR5]] = bitcast i8** {{%[^,]+}} to i16**
+// CHECK-DAG: [[CPADDR5]] = bitcast i8** {{%[^,]+}} to i16**
// CHECK-DAG: store i[[SZ]] [[CSIZE]], i[[SZ]]* {{%[^,]+}}
// CHECK-NEXT: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
@@ -733,7 +776,7 @@ int bar(int n){
// CHECK-32-DAG:store i32 [[LOCAL_BV]], i32* [[LOCAL_B_CASTED]], align
// CHECK-DAG: [[REF_B:%.+]] = load i[[SZ]], i[[SZ]]* [[LOCAL_B_CASTED]],
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 5, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, [[S1]]*, i[[SZ]], i[[SZ]], i[[SZ]], i16*)* [[OMP_OUTLINED5:@.+]] to void (i32*, i32*, ...)*), [[S1]]* [[REF_THIS]], i[[SZ]] [[REF_B]], i[[SZ]] [[VAL_VLA1]], i[[SZ]] [[VAL_VLA2]], i16* [[REF_C]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 5, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, [[S1]]*, i[[SZ]], i[[SZ]], i[[SZ]], i16*)* [[OMP_OUTLINED5:@.+]] to void (i32*, i32*, ...)*), [[S1]]* [[REF_THIS]], i[[SZ]] [[REF_B]], i[[SZ]] [[VAL_VLA1]], i[[SZ]] [[VAL_VLA2]], i16* [[REF_C]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED5]](i32* noalias %.global_tid., i32* noalias %.bound_tid., [[S1]]* %{{.+}}, i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, i16* {{.+}})
@@ -778,7 +821,7 @@ int bar(int n){
// CHECK-DAG: store i8 [[CONV_AAA]], i8* [[CONV]], align
// CHECK-DAG: [[REF_AAA:%.+]] = load i[[SZ]], i[[SZ]]* [[LOCAL_AAA_CASTED]],
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 5, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]], i[[SZ]], i[[SZ]], [10 x i32]*)* [[OMP_OUTLINED6:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], i[[SZ]] {{.+}}, i[[SZ]] [[REF_AA]], i[[SZ]] [[REF_AAA]], [10 x i32]* [[REF_B]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 5, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]], i[[SZ]], i[[SZ]], [10 x i32]*)* [[OMP_OUTLINED6:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], i[[SZ]] {{.+}}, i[[SZ]] [[REF_AA]], i[[SZ]] [[REF_AAA]], [10 x i32]* [[REF_B]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED6]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, [10 x i32]* {{.+}})
@@ -811,7 +854,7 @@ int bar(int n){
// CHECK-DAG: store i16 [[CONV_AA]], i16* [[CONV]], align
// CHECK-DAG: [[REF_AA:%.+]] = load i[[SZ]], i[[SZ]]* [[LOCAL_AA_CASTED]],
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]], [10 x i32]*)* [[OMP_OUTLINED7:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], i[[SZ]] [[REF_AA]], [10 x i32]* [[REF_B]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]], [10 x i32]*)* [[OMP_OUTLINED7:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], i[[SZ]] [[REF_AA]], [10 x i32]* [[REF_B]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED7]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, [10 x i32]* {{.+}})
diff --git a/test/OpenMP/target_teams_distribute_codegen_registration.cpp b/test/OpenMP/target_teams_distribute_codegen_registration.cpp
index c031731c8065..e45e040b1fcd 100644
--- a/test/OpenMP/target_teams_distribute_codegen_registration.cpp
+++ b/test/OpenMP/target_teams_distribute_codegen_registration.cpp
@@ -6,6 +6,14 @@
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// Test target teams distribute codegen - host bc file has to be created first.
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s -check-prefix=TCHECK
@@ -16,9 +24,22 @@
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s -check-prefix=TCHECK
-// Check that no target code is emmitted if no omptests flag was provided.
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
+// Check that no target code is emitted if no omptests flag was provided.
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s -check-prefix=CHECK-NTARGET
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// SIMD-ONLY2-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -60,96 +81,96 @@
// We have 7 target regions
-// CHECK-DAG: {{@.+}} = private constant i8 0
-// TCHECK-NOT: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = weak constant i8 0
+// TCHECK-NOT: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
-// CHECK-NTARGET-NOT: private constant i8 0
+// CHECK-NTARGET-NOT: weak constant i8 0
// CHECK-NTARGET-NOT: private unnamed_addr constant [1 x i
// CHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// CHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY1:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// CHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY2:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// CHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY3:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// CHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY4:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// CHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY5:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// CHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY6:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// CHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY7:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// CHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY8:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// CHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY9:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// CHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY10:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// CHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY11:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// CHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY12:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// TCHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY1:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// TCHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY2:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// TCHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY3:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// TCHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY4:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// TCHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY5:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// TCHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY6:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// TCHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY7:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// TCHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY8:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// TCHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY9:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// TCHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY10:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// TCHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY11:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// TCHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY12:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
// CHECK: [[ENTEND:@.+]] = external constant [[ENTTY]]
@@ -163,7 +184,7 @@
// CHECK-SAME: { i32, void ()*, i8* } { i32 500, void ()* [[P500:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 501, void ()* [[P501:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 65535, void ()* [[PMAX:@[^,]+]], i8* null },
-// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
// CHECK-NTARGET: @llvm.global_ctors = appending global [3 x { i32, void ()*, i8* }] [
@@ -328,18 +349,18 @@ struct ST {
//CHECK-DAG: define internal void @[[NAME12]](
//CHECK-DAG: call void @[[NAME12]](
-//TCHECK-DAG: define void @[[NAME1]](
-//TCHECK-DAG: define void @[[NAME2]](
-//TCHECK-DAG: define void @[[NAME3]](
-//TCHECK-DAG: define void @[[NAME4]](
-//TCHECK-DAG: define void @[[NAME5]](
-//TCHECK-DAG: define void @[[NAME6]](
-//TCHECK-DAG: define void @[[NAME7]](
-//TCHECK-DAG: define void @[[NAME8]](
-//TCHECK-DAG: define void @[[NAME9]](
-//TCHECK-DAG: define void @[[NAME10]](
-//TCHECK-DAG: define void @[[NAME11]](
-//TCHECK-DAG: define void @[[NAME12]](
+//TCHECK-DAG: define weak void @[[NAME1]](
+//TCHECK-DAG: define weak void @[[NAME2]](
+//TCHECK-DAG: define weak void @[[NAME3]](
+//TCHECK-DAG: define weak void @[[NAME4]](
+//TCHECK-DAG: define weak void @[[NAME5]](
+//TCHECK-DAG: define weak void @[[NAME6]](
+//TCHECK-DAG: define weak void @[[NAME7]](
+//TCHECK-DAG: define weak void @[[NAME8]](
+//TCHECK-DAG: define weak void @[[NAME9]](
+//TCHECK-DAG: define weak void @[[NAME10]](
+//TCHECK-DAG: define weak void @[[NAME11]](
+//TCHECK-DAG: define weak void @[[NAME12]](
// CHECK-NTARGET-NOT: __tgt_target
// CHECK-NTARGET-NOT: __tgt_register_lib
@@ -381,7 +402,7 @@ struct ST {
//CHECK: ret void
//CHECK: declare i32 @__tgt_unregister_lib([[DSCTY]]*)
-//CHECK: define linkonce hidden void @[[REGFN]](i8*)
+//CHECK: define linkonce hidden void @[[REGFN]]()
//CHECK-SAME: comdat {
//CHECK: call i32 @__tgt_register_lib([[DSCTY]]* [[DESC]])
//CHECK: call i32 @__cxa_atexit(void (i8*)* @[[UNREGFN]], i8* bitcast ([[DSCTY]]* [[DESC]] to i8*),
@@ -421,31 +442,31 @@ int bar(int a){
// Check metadata is properly generated:
// CHECK: !omp_offload.info = !{!{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 195, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 247, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 265, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 272, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 284, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 291, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 415, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 298, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 291, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 298, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 284, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 221, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 216, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 268, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 286, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 293, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 305, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 312, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 436, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 319, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 312, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 319, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 305, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 242, i32 {{[0-9]+}}}
// TCHECK: !omp_offload.info = !{!{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 195, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 247, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 265, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 272, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 284, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 291, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 415, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 298, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 291, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 298, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 284, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 221, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 216, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 268, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 286, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 293, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 305, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 312, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 436, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 319, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 312, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 319, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 305, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 242, i32 {{[0-9]+}}}
#endif
diff --git a/test/OpenMP/target_teams_distribute_codegen_registration_naming.cpp b/test/OpenMP/target_teams_distribute_codegen_registration_naming.cpp
index c03466a52646..c2195acf3e7e 100644
--- a/test/OpenMP/target_teams_distribute_codegen_registration_naming.cpp
+++ b/test/OpenMP/target_teams_distribute_codegen_registration_naming.cpp
@@ -6,6 +6,14 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// Test target teams distribute codegen - host bc file has to be created first.
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s -check-prefix=TCHECK
@@ -16,6 +24,16 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s -check-prefix=TCHECK
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/target_teams_distribute_collapse_codegen.cpp b/test/OpenMP/target_teams_distribute_collapse_codegen.cpp
index be99186e4681..62fc58980a7c 100644
--- a/test/OpenMP/target_teams_distribute_collapse_codegen.cpp
+++ b/test/OpenMP/target_teams_distribute_collapse_codegen.cpp
@@ -9,6 +9,14 @@
// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
#ifdef CK1
template <typename T, int X, long long Y>
@@ -60,6 +68,14 @@ int teams_template_struct(void) {
// RUN: %clang_cc1 -DCK2 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
#ifdef CK2
template <typename T, int n, int m>
diff --git a/test/OpenMP/target_teams_distribute_collapse_messages.cpp b/test/OpenMP/target_teams_distribute_collapse_messages.cpp
index 4bc4a7b79ccf..4010c5a9a9c9 100644
--- a/test/OpenMP/target_teams_distribute_collapse_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_collapse_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_default_messages.cpp b/test/OpenMP/target_teams_distribute_default_messages.cpp
index 1bd106769784..2a3229dde5ec 100644
--- a/test/OpenMP/target_teams_distribute_default_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_default_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo();
int main(int argc, char **argv) {
diff --git a/test/OpenMP/target_teams_distribute_defaultmap_messages.cpp b/test/OpenMP/target_teams_distribute_defaultmap_messages.cpp
index 6608cee3de58..a31015255ccf 100644
--- a/test/OpenMP/target_teams_distribute_defaultmap_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_defaultmap_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_depend_codegen.cpp b/test/OpenMP/target_teams_distribute_depend_codegen.cpp
new file mode 100644
index 000000000000..f066574e8768
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_depend_codegen.cpp
@@ -0,0 +1,261 @@
+// Test host codegen.
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+// Test target codegen - host bc file has to be created first.
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+// CHECK-DAG: [[TT:%.+]] = type { i64, i8 }
+// CHECK-DAG: [[ENTTY:%.+]] = type { i8*, i8*, i[[SZ:32|64]], i32, i32 }
+// CHECK-DAG: [[DEVTY:%.+]] = type { i8*, i8*, [[ENTTY]]*, [[ENTTY]]* }
+// CHECK-DAG: [[DSCTY:%.+]] = type { i32, [[DEVTY]]*, [[ENTTY]]*, [[ENTTY]]* }
+
+// TCHECK: [[ENTTY:%.+]] = type { i8*, i8*, i{{32|64}}, i32, i32 }
+
+// CHECK-DAG: $[[REGFN:\.omp_offloading\..+]] = comdat
+
+// CHECK-DAG: [[SIZET:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 0, i[[SZ]] 4]
+// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 544, i64 800]
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = {{.*}}constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
+
+// Check if offloading descriptor is created.
+// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
+// CHECK: [[ENTEND:@.+]] = external constant [[ENTTY]]
+// CHECK: [[DEVBEGIN:@.+]] = external constant i8
+// CHECK: [[DEVEND:@.+]] = external constant i8
+// CHECK: [[IMAGES:@.+]] = internal unnamed_addr constant [1 x [[DEVTY]]] [{{.+}} { i8* [[DEVBEGIN]], i8* [[DEVEND]], [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }], comdat($[[REGFN]])
+// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
+
+// Check target registration is registered as a Ctor.
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
+
+
+template<typename tx, typename ty>
+struct TT{
+ tx X;
+ ty Y;
+};
+
+int global;
+extern int global;
+
+// CHECK: define {{.*}}[[FOO:@.+]](
+int foo(int n) {
+ int a = 0;
+ short aa = 0;
+ float b[10];
+ float bn[n];
+ double c[5][10];
+ double cn[5][n];
+ TT<long long, char> d;
+ static long *plocal;
+
+ // CHECK: [[ADD:%.+]] = add nsw i32
+ // CHECK: store i32 [[ADD]], i32* [[DEVICE_CAP:%.+]],
+ // CHECK: [[GEP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+ // CHECK: store i32 [[DEV]], i32* [[GEP]],
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[ID:@.+]], i32 [[GTID:%.+]], i32 1, i[[SZ]] {{20|40}}, i[[SZ]] 4, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY0:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY0:%.+]]*
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 1
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 2
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 3
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call void @__kmpc_omp_wait_deps(%struct.ident_t* [[ID]], i32 [[GTID]], i32 4, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: call void @__kmpc_omp_task_begin_if0(%struct.ident_t* [[ID]], i32 [[GTID]], i8* [[TASK]])
+ // CHECK: call i32 [[TASK_ENTRY0]](i32 [[GTID]], [[TASK_TY0]]* [[BC_TASK]])
+ // CHECK: call void @__kmpc_omp_task_complete_if0(%struct.ident_t* [[ID]], i32 [[GTID]], i8* [[TASK]])
+ #pragma omp target teams distribute device(global + a) depend(in: global) depend(out: a, b, cn[4])
+ for (int i = 0; i < 10; ++i) {
+ }
+
+ // CHECK: [[ADD:%.+]] = add nsw i32
+ // CHECK: store i32 [[ADD]], i32* [[DEVICE_CAP:%.+]],
+
+ // CHECK: [[BOOL:%.+]] = icmp ne i32 %{{.+}}, 0
+ // CHECK: br i1 [[BOOL]], label %[[THEN:.+]], label %[[ELSE:.+]]
+ // CHECK: [[THEN]]:
+ // CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP:%.+]], i32 0, i32 0
+ // CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P:%.+]], i32 0, i32 0
+ // CHECK-DAG: [[CBPADDR0:%.+]] = bitcast i8** [[BPADDR0]] to i[[SZ]]**
+ // CHECK-DAG: [[CPADDR0:%.+]] = bitcast i8** [[PADDR0]] to i[[SZ]]**
+ // CHECK-DAG: store i[[SZ]]* [[BP0:%[^,]+]], i[[SZ]]** [[CBPADDR0]]
+ // CHECK-DAG: store i[[SZ]]* [[BP0]], i[[SZ]]** [[CPADDR0]]
+
+ // CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 1
+ // CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P]], i32 0, i32 1
+ // CHECK-DAG: [[CBPADDR1:%.+]] = bitcast i8** [[BPADDR1]] to i[[SZ]]*
+ // CHECK-DAG: [[CPADDR1:%.+]] = bitcast i8** [[PADDR1]] to i[[SZ]]*
+ // CHECK-DAG: store i[[SZ]] [[BP1:%[^,]+]], i[[SZ]]* [[CBPADDR1]]
+ // CHECK-DAG: store i[[SZ]] [[BP1]], i[[SZ]]* [[CPADDR1]]
+ // CHECK-DAG: getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 0
+ // CHECK-DAG: getelementptr inbounds [2 x i8*], [2 x i8*]* [[P]], i32 0, i32 0
+ // CHECK: [[GEP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+ // CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+ // CHECK: store i32 [[DEV]], i32* [[GEP]],
+
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[ID]], i32 [[GTID]], i32 1, i[[SZ]] {{104|52}}, i[[SZ]] {{16|12}}, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY1_:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY1_:%.+]]*
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 1
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 2
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call i32 @__kmpc_omp_task_with_deps(%struct.ident_t* [[ID]], i32 [[GTID]], i8* [[TASK]], i32 3, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: br label %[[EXIT:.+]]
+
+ // CHECK: [[ELSE]]:
+ // CHECK-NOT: getelementptr inbounds [2 x i8*], [2 x i8*]*
+ // CHECK: [[GEP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+ // CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+ // CHECK: store i32 [[DEV]], i32* [[GEP]],
+
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[ID]], i32 [[GTID]], i32 1, i[[SZ]] {{56|28}}, i[[SZ]] {{16|12}}, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY1__:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY1__:%.+]]*
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 1
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 2
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call i32 @__kmpc_omp_task_with_deps(%struct.ident_t* [[ID]], i32 [[GTID]], i8* [[TASK]], i32 3, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: br label %[[EXIT:.+]]
+ // CHECK: [[EXIT]]:
+
+ #pragma omp target teams distribute device(global + a) nowait depend(inout: global, a, bn) if(a)
+ for (int i = 0; i < *plocal; ++i) {
+ static int local1;
+ *plocal = global;
+ local1 = global;
+ }
+
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[ID]], i32 [[GTID]], i32 1, i[[SZ]] {{48|24}}, i[[SZ]] 4, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY2:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY2:%.+]]*
+ // CHECK: getelementptr inbounds [1 x %struct.kmp_depend_info], [1 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [1 x %struct.kmp_depend_info], [1 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call void @__kmpc_omp_wait_deps(%struct.ident_t* [[ID]], i32 [[GTID]], i32 1, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: call void @__kmpc_omp_task_begin_if0(%struct.ident_t* [[ID]], i32 [[GTID]], i8* [[TASK]])
+ // CHECK: call i32 [[TASK_ENTRY2]](i32 [[GTID]], [[TASK_TY2]]* [[BC_TASK]])
+ // CHECK: call void @__kmpc_omp_task_complete_if0(%struct.ident_t* [[ID]], i32 [[GTID]], i8* [[TASK]])
+ #pragma omp target teams distribute if(0) firstprivate(global) depend(out:global)
+ for (int i = 0; i < global; ++i) {
+ global += 1;
+ }
+
+ return a;
+}
+
+// Check that the offloading functions are emitted and that the arguments are
+// correct and loaded correctly for the target regions in foo().
+
+// CHECK: define internal void [[HVT0:@.+]]()
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY0]](i32{{.*}}, [[TASK_TY0]]* noalias)
+// CHECK: store void (i8*, ...)* null, void (i8*, ...)** %
+// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 0
+// CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+// CHECK: [[DEVICE:%.+]] = sext i32 [[DEV]] to i64
+// CHECK: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 [[DEVICE]], i8* @{{[^,]+}}, i32 0, i8** null, i8** null, i[[SZ]]* null, i64* null, i32 0, i32 0)
+// CHECK-NEXT: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
+// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
+// CHECK: [[FAIL]]
+// CHECK: call void [[HVT0]]()
+// CHECK-NEXT: br label %[[END]]
+// CHECK: [[END]]
+// CHECK: ret i32 0
+
+// CHECK: define internal void [[HVT1:@.+]](i[[SZ]]* %{{.+}}, i[[SZ]] %{{.+}})
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY1_]](i32{{.*}}, [[TASK_TY1_]]* noalias)
+// CHECK: call void (i8*, ...) %
+// CHECK: [[SZT:%.+]] = getelementptr inbounds [2 x i[[SZ]]], [2 x i[[SZ]]]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+// CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+// CHECK: [[DEVICE:%.+]] = sext i32 [[DEV]] to i64
+// CHECK: [[RET:%.+]] = call i32 @__tgt_target_teams_nowait(i64 [[DEVICE]], i8* @{{[^,]+}}, i32 2, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SZT]], i64* getelementptr inbounds ([2 x i64], [2 x i64]* [[MAPT]], i32 0, i32 0), i32 0, i32 0)
+
+// CHECK: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
+// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
+// CHECK: [[FAIL]]
+// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
+// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
+// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
+// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
+// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
+// CHECK: [[BP1:%.+]] = load i[[SZ]], i[[SZ]]* [[BP1_PTR]],
+// CHECK: call void [[HVT1]](i[[SZ]]* [[BP0]], i[[SZ]] [[BP1]])
+// CHECK-NEXT: br label %[[END]]
+// CHECK: [[END]]
+// CHECK: ret i32 0
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY1__]](i32{{.*}}, [[TASK_TY1__]]* noalias)
+// CHECK: call void (i8*, ...) %
+// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
+// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
+// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
+// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
+// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
+// CHECK: [[BP1:%.+]] = load i[[SZ]], i[[SZ]]* [[BP1_PTR]],
+// CHECK: call void [[HVT1]](i[[SZ]]* [[BP0]], i[[SZ]] [[BP1]])
+// CHECK: ret i32 0
+
+// CHECK: define internal void [[HVT2:@.+]](i[[SZ]] %{{.+}})
+// Create stack storage and store argument in there.
+// CHECK: [[AA_ADDR:%.+]] = alloca i[[SZ]], align
+// CHECK: store i[[SZ]] %{{.+}}, i[[SZ]]* [[AA_ADDR]], align
+// CHECK-64: [[AA_CADDR:%.+]] = bitcast i[[SZ]]* [[AA_ADDR]] to i32*
+// CHECK-64: load i32, i32* [[AA_CADDR]], align
+// CHECK-32: load i32, i32* [[AA_ADDR]], align
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY2]](i32{{.*}}, [[TASK_TY2]]* noalias)
+// CHECK: call void (i8*, ...) %
+// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
+// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
+// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
+// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
+// CHECK: [[BP1:%.+]] = load i[[SZ]], i[[SZ]]* [[BP1_PTR]],
+// CHECK: call void [[HVT2]](i[[SZ]] [[BP1]])
+// CHECK: ret i32 0
+
+
+#endif
diff --git a/test/OpenMP/target_teams_distribute_depend_messages.cpp b/test/OpenMP/target_teams_distribute_depend_messages.cpp
index fbdd49590f87..9daba670203e 100644
--- a/test/OpenMP/target_teams_distribute_depend_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_depend_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_device_messages.cpp b/test/OpenMP/target_teams_distribute_device_messages.cpp
index b35d0befce21..aa62e0997168 100644
--- a/test/OpenMP/target_teams_distribute_device_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_device_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_dist_schedule_codegen.cpp b/test/OpenMP/target_teams_distribute_dist_schedule_codegen.cpp
index 0c9b2387debf..3eb153173006 100644
--- a/test/OpenMP/target_teams_distribute_dist_schedule_codegen.cpp
+++ b/test/OpenMP/target_teams_distribute_dist_schedule_codegen.cpp
@@ -9,6 +9,14 @@
// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
#ifdef CK1
template <typename T, int X, long long Y>
@@ -81,6 +89,14 @@ int teams_template_struct(void) {
// RUN: %clang_cc1 -DCK2 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
#ifdef CK2
template <typename T, int n>
diff --git a/test/OpenMP/target_teams_distribute_dist_schedule_messages.cpp b/test/OpenMP/target_teams_distribute_dist_schedule_messages.cpp
index 87708706a69e..2544b1b9abbc 100644
--- a/test/OpenMP/target_teams_distribute_dist_schedule_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_dist_schedule_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_firstprivate_codegen.cpp b/test/OpenMP/target_teams_distribute_firstprivate_codegen.cpp
index 35abffa92600..5487fa86e8f0 100644
--- a/test/OpenMP/target_teams_distribute_firstprivate_codegen.cpp
+++ b/test/OpenMP/target_teams_distribute_firstprivate_codegen.cpp
@@ -1,13 +1,26 @@
-// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
@@ -97,16 +110,7 @@ int main() {
// LAMBDA: [[G_ADDR:%.+]] = alloca i{{[0-9]+}},
// LAMBDA: [[G1_ADDR:%.+]] = alloca i{{[0-9]+}},
// LAMBDA: [[SIVAR_ADDR:%.+]] = alloca i{{[0-9]+}},
- // LAMBDA: {{%.+}} = alloca i{{[0-9]+}},
- // LAMBDA: {{%.+}} = alloca i{{[0-9]+}},
- // LAMBDA: {{%.+}} = alloca i{{[0-9]+}},
- // LAMBDA: {{%.+}} = alloca i{{[0-9]+}},
- // LAMBDA: {{%.+}} = alloca i{{[0-9]+}},
- // LAMBDA: {{%.+}} = alloca i{{[0-9]+}},
- // LAMBDA: [[G_PRIV_ADDR:%.+]] = alloca i{{[0-9]+}},
- // LAMBDA: [[G1_PRIV_ADDR:%.+]] = alloca i{{[0-9]+}},
// LAMBDA: [[G1_TMP:%.+]] = alloca i32*,
- // LAMBDA: [[SIVAR_PRIV_ADDR:%.+]] = alloca i{{[0-9]+}},
// skip loop vars
// LAMBDA-DAG: store {{.+}}, {{.+}} [[G_ADDR]],
// LAMBDA-DAG: store {{.+}}, {{.+}} [[G1_ADDR]],
@@ -114,15 +118,15 @@ int main() {
// LAMBDA-DAG: [[G_CONV:%.+]] = bitcast {{.+}} [[G_ADDR]] to
// LAMBDA-DAG: [[G1_CONV:%.+]] = bitcast {{.+}} [[G1_ADDR]] to
// LAMBDA-DAG: [[SIVAR_CONV:%.+]] = bitcast {{.+}} [[SIVAR_ADDR]] to
- // LAMBDA-DAG: store{{.+}} [[G1_PRIV_ADDR]], {{.+}} [[G1_TMP]],
+ // LAMBDA-DAG: store{{.+}} [[G1_CONV]], {{.+}} [[G1_TMP]],
g = 1;
g1 = 1;
sivar = 2;
// LAMBDA: call void @__kmpc_for_static_init_4(
- // LAMBDA-DAG: store{{.+}} 1, {{.+}} [[G_PRIV_ADDR]],
+ // LAMBDA-DAG: store{{.+}} 1, {{.+}} [[G_CONV]],
// LAMBDA-DAG: [[G1:%.+]] = load{{.+}}, {{.+}}* [[G1_TMP]]
// LAMBDA-DAG: store{{.+}} 1, {{.+}} [[G1]],
- // LAMBDA-DAG: store{{.+}} 2, {{.+}} [[SIVAR_PRIV_ADDR]],
+ // LAMBDA-DAG: store{{.+}} 2, {{.+}} [[SIVAR_CONV]],
// LAMBDA-DAG: [[G1_REF:%.+]] = load{{.+}}, {{.+}} [[G1_TMP]],
// LAMBDA-DAG: store{{.+}} 1, {{.+}} [[G1_REF]],
// LAMBDA: call void [[INNER_LAMBDA:@.+]](
@@ -212,8 +216,8 @@ int main() {
// CHECK: store i{{[0-9]+}} {{.+}}, i{{[0-9]+}}* [[SIVAR_ADDR]],
// T_VAR and SIVAR
-// CHECK-DAG-64: [[CONV_TVAR:%.+]] = bitcast i64* [[T_VAR_ADDR]] to i32*
-// CHECK-DAG-64: [[CONV_SIVAR:%.+]] = bitcast i64* [[SIVAR_ADDR]] to i32*
+// CHECK-64-DAG: [[CONV_TVAR:%.+]] = bitcast i64* [[T_VAR_ADDR]] to i32*
+// CHECK-64-DAG: [[CONV_SIVAR:%.+]] = bitcast i64* [[SIVAR_ADDR]] to i32*
// preparation vars
// CHECK-DAG: [[VEC_ADDR_VAL:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]],
@@ -223,7 +227,7 @@ int main() {
// firstprivate vec(vec): copy from *_addr into priv1 and then from priv1 into priv2
// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VEC_DEST_PRIV]], i8* [[VEC_SRC]], {{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST_PRIV]], i8* align {{[0-9]+}} [[VEC_SRC]], {{.+}})
// firstprivate(s_arr)
// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]],
@@ -243,13 +247,13 @@ int main() {
// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]])
// CHECK: call void @__kmpc_for_static_init_4(
-// CHECK-DAG-32: {{.+}} = {{.+}} [[T_VAR_ADDR]]
-// CHECK-DAG-64: {{.+}} = {{.+}} [[CONV_TVAR]]
+// CHECK-32-DAG: {{.+}} = {{.+}} [[T_VAR_ADDR]]
+// CHECK-64-DAG: {{.+}} = {{.+}} [[CONV_TVAR]]
// CHECK-DAG: {{.+}} = {{.+}} [[VEC_PRIV]]
// CHECK-DAG: {{.+}} = {{.+}} [[S_ARR_PRIV]]
// CHECK-DAG: {{.+}} = {{.+}} [[VAR_PRIV]]
-// CHECK-DAG-32: {{.+}} = {{.+}} [[SIVAR_ADDR]]
-// CHECK-DAG-64: {{.+}} = {{.+}} [[CONV_SIVAR]]
+// CHECK-32-DAG: {{.+}} = {{.+}} [[SIVAR_ADDR]]
+// CHECK-64-DAG: {{.+}} = {{.+}} [[CONV_SIVAR]]
// CHECK: call void @__kmpc_for_static_fini(
// CHECK: ret void
@@ -309,7 +313,7 @@ int main() {
// firstprivate vec(vec): copy from *_addr into priv1 and then from priv1 into priv2
// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VEC_DEST_PRIV]], i8* [[VEC_SRC]], {{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST_PRIV]], i8* align {{[0-9]+}} [[VEC_SRC]], {{.+}})
// firstprivate(s_arr)
// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_PRIV]],
@@ -331,8 +335,8 @@ int main() {
// CHECK-DAG: store [[S_INT_TY]]* [[VAR_PRIV]], [[S_INT_TY]]** [[TMP]],
// CHECK: call void @__kmpc_for_static_init_4(
-// CHECK-DAG-32: {{.+}} = {{.+}} [[T_VAR_ADDR]]
-// CHECK-DAG-64: {{.+}} = {{.+}} [[CONV_TVAR]]
+// CHECK-32-DAG: {{.+}} = {{.+}} [[T_VAR_ADDR]]
+// CHECK-64-DAG: {{.+}} = {{.+}} [[CONV_TVAR]]
// CHECK-DAG: {{.+}} = {{.+}} [[VEC_PRIV]]
// CHECK-DAG: {{.+}} = {{.+}} [[TMP]]
// CHECK-DAG: {{.+}} = {{.+}} [[S_ARR_PRIV]]
diff --git a/test/OpenMP/target_teams_distribute_firstprivate_messages.cpp b/test/OpenMP/target_teams_distribute_firstprivate_messages.cpp
index 934149e7c139..01c1a2818f82 100644
--- a/test/OpenMP/target_teams_distribute_firstprivate_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_firstprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_if_messages.cpp b/test/OpenMP/target_teams_distribute_if_messages.cpp
index c9ef03a61ba0..94d82ab5ae65 100644
--- a/test/OpenMP/target_teams_distribute_if_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_if_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_lastprivate_codegen.cpp b/test/OpenMP/target_teams_distribute_lastprivate_codegen.cpp
index b41a6016079b..26a7c0d61da8 100644
--- a/test/OpenMP/target_teams_distribute_lastprivate_codegen.cpp
+++ b/test/OpenMP/target_teams_distribute_lastprivate_codegen.cpp
@@ -5,12 +5,28 @@
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -243,7 +259,7 @@ int main() {
// CHECK-DAG: [[TMP_VAL:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP_PRIV]],
// CHECK-DAG: [[S_ARR_PTR_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_PTR]] to i8*
// CHECK-DAG: [[TMP_VAL_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_VAL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_PTR_BCAST]], i8* [[TMP_VAL_BCAST]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_PTR_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL_BCAST]],
// CHECK: call void @__kmpc_for_static_fini(
// lastprivates
@@ -257,7 +273,7 @@ int main() {
// CHECK-32: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_ADDR]],
// CHECK: [[BCAST_VEC_ADDR_REF:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_REF]] to i8*
// CHECK: [[BCAST_VEC_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[BCAST_VEC_ADDR_REF]], i8* [[BCAST_VEC_PRIV]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[BCAST_VEC_ADDR_REF]], i8* align {{[0-9]+}} [[BCAST_VEC_PRIV]],
// CHECK: [[S_ARR_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_ADDR_REF]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[S_ARR_PRIV_BCAST:%.+]] = bitcast [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]] to [[S_FLOAT_TY]]*
// CHECK: [[S_ARR_BEGIN_GEP:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[S_ARR_BEGIN]], i{{[0-9]+}} 2
@@ -268,7 +284,7 @@ int main() {
// CHECK: [[S_ARR_DST_EL:%.+]] = phi [[S_FLOAT_TY]]*{{.+}}
// CHECK: [[S_ARR_DST_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_DST_EL]] to i8*
// CHECK: [[S_ARR_SRC_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_SRC_EL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_DST_BCAST]], i8* [[S_ARR_SRC_BCAST]]{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_DST_BCAST]], i8* align {{[0-9]+}} [[S_ARR_SRC_BCAST]]{{.+}})
// CHECK: [[S_ARR_DST_NEXT:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[S_ARR_DST_EL]], i{{[0-9]+}} 1
// CHECK: [[S_ARR_SRC_NEXT:%.+]] = getelementptr{{.+}}
// CHECK: [[CPY_IS_FINISHED:%.+]] = icmp eq [[S_FLOAT_TY]]* [[S_ARR_DST_NEXT]], [[S_ARR_BEGIN_GEP]]
@@ -277,7 +293,7 @@ int main() {
// CHECK: [[TMP_VAL1:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP_PRIV]],
// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[VAR_ADDR_REF]] to i8*
// CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VAR_ADDR_REF_BCAST]], i8* [[TMP_VAL1_BCAST]],{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}})
// CHECK: [[SVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[S_VAR_PRIV]],
// CHECK-64: store i{{[0-9]+}} [[SVAR_VAL]], i{{[0-9]+}}* [[SVAR_ADDR_REF]],
// CHECK-32: store i{{[0-9]+}} [[SVAR_VAL]], i{{[0-9]+}}* [[SVAR_ADDR]],
@@ -345,7 +361,7 @@ int main() {
// CHECK-DAG: [[TMP_VAL1:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP_PRIV1]],
// CHECK-DAG: [[S_ARR_PTR_BCAST1:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_PTR1]] to i8*
// CHECK-DAG: [[TMP_VAL_BCAST1:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_PTR_BCAST1]], i8* [[TMP_VAL_BCAST1]],
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_PTR_BCAST1]], i8* align {{[0-9]+}} [[TMP_VAL_BCAST1]],
// CHECK: call void @__kmpc_for_static_fini(
// lastprivates
@@ -359,7 +375,7 @@ int main() {
// CHECK-32: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_ADDR1]],
// CHECK: [[BCAST_VEC_ADDR_REF:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_REF1]] to i8*
// CHECK: [[BCAST_VEC_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[BCAST_VEC_ADDR_REF]], i8* [[BCAST_VEC_PRIV]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[BCAST_VEC_ADDR_REF]], i8* align {{[0-9]+}} [[BCAST_VEC_PRIV]],
// CHECK: [[S_ARR_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_ADDR_REF]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[S_ARR_PRIV_BCAST:%.+]] = bitcast [2 x [[S_INT_TY]]]* [[S_ARR_PRIV1]] to [[S_INT_TY]]*
// CHECK: [[S_ARR_BEGIN_GEP:%.+]] = getelementptr [[S_INT_TY]], [[S_INT_TY]]* [[S_ARR_BEGIN]], i{{[0-9]+}} 2
@@ -370,7 +386,7 @@ int main() {
// CHECK: [[S_ARR_DST_EL:%.+]] = phi [[S_INT_TY]]*{{.+}}
// CHECK: [[S_ARR_DST_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_DST_EL]] to i8*
// CHECK: [[S_ARR_SRC_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_SRC_EL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_DST_BCAST]], i8* [[S_ARR_SRC_BCAST]]{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_DST_BCAST]], i8* align {{[0-9]+}} [[S_ARR_SRC_BCAST]]{{.+}})
// CHECK: [[S_ARR_DST_NEXT:%.+]] = getelementptr [[S_INT_TY]], [[S_INT_TY]]* [[S_ARR_DST_EL]], i{{[0-9]+}} 1
// CHECK: [[S_ARR_SRC_NEXT:%.+]] = getelementptr{{.+}}
// CHECK: [[CPY_IS_FINISHED:%.+]] = icmp eq [[S_INT_TY]]* [[S_ARR_DST_NEXT]], [[S_ARR_BEGIN_GEP]]
@@ -379,6 +395,6 @@ int main() {
// CHECK: [[TMP_VAL1:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP_PRIV1]],
// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[VAR_ADDR1_REF]] to i8*
// CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VAR_ADDR_REF_BCAST]], i8* [[TMP_VAL1_BCAST]],{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}})
// CHECK: ret void
#endif
diff --git a/test/OpenMP/target_teams_distribute_lastprivate_messages.cpp b/test/OpenMP/target_teams_distribute_lastprivate_messages.cpp
index 898291833d20..0739846cee0a 100644
--- a/test/OpenMP/target_teams_distribute_lastprivate_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_lastprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_loop_messages.cpp b/test/OpenMP/target_teams_distribute_loop_messages.cpp
index 0a825ab1e609..b090c288a201 100644
--- a/test/OpenMP/target_teams_distribute_loop_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_loop_messages.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s -Wno-openmp-target
class S {
int a;
diff --git a/test/OpenMP/target_teams_distribute_map_messages.cpp b/test/OpenMP/target_teams_distribute_map_messages.cpp
index eafdccb66bc9..826a09dd76d5 100644
--- a/test/OpenMP/target_teams_distribute_map_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_map_messages.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s -Wno-openmp-target
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_messages.cpp b/test/OpenMP/target_teams_distribute_messages.cpp
index 91f3c76a4a09..d3be0f632be3 100644
--- a/test/OpenMP/target_teams_distribute_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -std=c++11 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -std=c++11 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_misc_messages.c b/test/OpenMP/target_teams_distribute_misc_messages.c
index 33496a70d140..6d17b512619a 100644
--- a/test/OpenMP/target_teams_distribute_misc_messages.c
+++ b/test/OpenMP/target_teams_distribute_misc_messages.c
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -verify %s
+
// expected-error@+1 {{unexpected OpenMP directive '#pragma omp target teams distribute'}}
#pragma omp target teams distribute
diff --git a/test/OpenMP/target_teams_distribute_nowait_messages.cpp b/test/OpenMP/target_teams_distribute_nowait_messages.cpp
index 17aa1dcac36e..b7a9a2548be5 100644
--- a/test/OpenMP/target_teams_distribute_nowait_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_nowait_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_num_teams_messages.cpp b/test/OpenMP/target_teams_distribute_num_teams_messages.cpp
index 9b36e9c581f0..8b351dc8fb4a 100644
--- a/test/OpenMP/target_teams_distribute_num_teams_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_num_teams_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_ast_print.cpp b/test/OpenMP/target_teams_distribute_parallel_for_ast_print.cpp
index f51c4fe60d7f..a22b561320fa 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_ast_print.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_ast_print.cpp
@@ -1,6 +1,10 @@
-// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -ast-print %s -Wno-openmp-target | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-target | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s -Wno-openmp-target | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-target | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -89,7 +93,7 @@ T tmain(T argc) {
#pragma omp target teams distribute parallel for
for (int i=0; i < 2; ++i)
a = 2;
-// CHECK: #pragma omp target teams distribute parallel for
+// CHECK: #pragma omp target teams distribute parallel for{{$}}
// CHECK-NEXT: for (int i = 0; i < 2; ++i)
// CHECK-NEXT: a = 2;
#pragma omp target teams distribute parallel for private(argc, b), firstprivate(c, d), collapse(2)
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_codegen.cpp
new file mode 100644
index 000000000000..4d263cf69f02
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_codegen.cpp
@@ -0,0 +1,118 @@
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+// Test host codegen.
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-64 --check-prefix HCK1 --check-prefix HCK1-64
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-64 --check-prefix HCK1 --check-prefix HCK1-64
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32 --check-prefix HCK1 --check-prefix HCK1-64
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32 --check-prefix HCK1 --check-prefix HCK1-64
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY1
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY1
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY1
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY1
+
+// Test target codegen - host bc file has to be created first. (no significant differences with host version of target region)
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-64 --check-prefix TCK1 --check-prefix TCK1-64
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-64 --check-prefix TCK1 --check-prefix TCK1-64
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32 --check-prefix TCK1 --check-prefix TCK1-32
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32 --check-prefix TCK1 --check-prefix TCK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix SIMD-ONLY1
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY1
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix SIMD-ONLY1
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY1
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
+#ifdef CK1
+
+// HCK1: define{{.*}} i32 @{{.+}}target_teams_fun{{.*}}(
+int target_teams_fun(int *g){
+ int n = 1000;
+ int a[1000];
+ int te = n / 128;
+ int th = 128;
+ // discard n_addr
+ // HCK1: alloca i32,
+ // HCK1: [[TE:%.+]] alloca i32,
+ // HCK1: [[TH:%.+]] = alloca i32,
+ // discard capture expressions for te and th
+ // HCK1: = alloca i32,
+ // HCK1: = alloca i32,
+ // HCK1: [[N_CAST:%.+]] = alloca i{{32|64}},
+ // HCK1: [[TE_CAST:%.+]] = alloca i{{32|64}},
+ // HCK1: [[TH_CAST:%.+]] = alloca i{{32|64}},
+ // HCK1: [[N_PAR:%.+]] = load{{.+}}, {{.+}} [[N_CAST]],
+ // HCK1: [[TE_PAR:%.+]] = load{{.+}}, {{.+}} [[TE_CAST]],
+ // HCK1: [[TH_PAR:%.+]] = load{{.+}}, {{.+}} [[TH_CAST]],
+ // HCK1: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 4, i8** %{{[^,]+}}, i8** %{{[^,]+}},
+
+ // HCK1: call void @[[OFFL1:.+]](i{{32|64}} [[N_PAR]], {{.+}}, i{{32|64}} [[TE_PAR]], i{{32|64}} [[TH_PAR]])
+ #pragma omp target teams distribute parallel for num_teams(te), thread_limit(th)
+ for(int i = 0; i < n; i++) {
+ a[i] = 0;
+ #pragma omp cancel for
+ }
+
+ // HCK1: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 3, i8** %{{[^,]+}}, i8** %{{[^,]+}}, i{{64|32}}* {{.+}}@{{[^,]+}}, i32 0, i32 0), i64* {{.+}}@{{[^,]+}}, i32 0, i32 0),
+ // HCK1: call void @[[OFFL2:.+]](i{{64|32}} %{{.+}})
+ {{{
+ #pragma omp target teams distribute parallel for is_device_ptr(g)
+ for(int i = 0; i < n; i++) {
+ a[i] = g[0];
+ }
+ }}}
+
+ // outlined target regions
+ // HCK1: define internal void @[[OFFL1]](i{{32|64}} [[N_ARG:%.+]], i{{32|64}} [[TE_ARG:%.+]], i{{32|64}} [[TH_ARG:%.+]])
+ // TCK1: define weak void @{{.+}}target_teams_fun{{.*}}(i{{32|64}} [[N_ARG:%.+]], {{.+}}, i{{32|64}} [[TE_ARG:%.+]], i{{32|64}} [[TH_ARG:%.+]])
+ // CK1: [[N_ADDR:%.+]] = alloca i{{32|64}},
+ // CK1: [[TE_ADDR:%.+]] = alloca i{{32|64}},
+ // CK1: [[TH_ADDR:%.+]] = alloca i{{32|64}},
+ // TCK1: store {{.+}} [[N_ARG]], {{.+}} [[N_ADDR]],
+ // CK1: store{{.+}} [[TE_ARG]], {{.+}} [[TE_ADDR]],
+ // CK1: store{{.+}} [[TH_ARG]], {{.+}} [[TH_ADDR]],
+ // CK1-64: [[TE_CONV:%.+]] = bitcast{{.+}} [[TE_ADDR]] to
+ // CK1-64: [[TH_CONV:%.+]] = bitcast{{.+}} [[TH_ADDR]] to
+ // CK1-64: [[TE_VAL:%.+]] = load i32, i32* [[TE_CONV]],
+ // CK1-64: [[TH_VAL:%.+]] = load i32, i32* [[TH_CONV]],
+ // CK1-32: [[TE_VAL:%.+]] = load i32, i32* [[TE_ADDR]],
+ // CK1-32: [[TH_VAL:%.+]] = load i32, i32* [[TH_ADDR]],
+ // CK1: {{%.+}} = call i32 @__kmpc_push_num_teams({{.+}}, {{.+}}, i32 [[TE_VAL]], i32 [[TH_VAL]])
+ // CK1: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 2, {{.+}} @[[OUTL1:.+]] to {{.+}}, {{.+}}, {{.+}})
+ // CK1: ret void
+
+ // CK1: define internal void @[[OUTL1]]({{.+}})
+ // CK1: call void @__kmpc_for_static_init_4(
+ // CK1: call void {{.+}} @__kmpc_fork_call(
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ // HCK1: define internal void @[[OFFL2]](
+ // TCK1: define weak void @{{.+}}target_teams_fun{{.+}}(
+ // CK1: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 3, {{.+}} @[[OUTL2:.+]] to {{.+}}, {{.+}}, {{.+}})
+ // CK1: ret void
+
+ // CK1: define internal void @[[OUTL2]]({{.+}})
+ // CK1: call void @__kmpc_for_static_init_4(
+ // CK1: call void {{.+}} @__kmpc_fork_call(
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ return a[0];
+}
+
+#endif // CK1
+#endif // HEADER
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_collapse_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_collapse_codegen.cpp
new file mode 100644
index 000000000000..80e38925b39e
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_collapse_codegen.cpp
@@ -0,0 +1,157 @@
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+// Test host codegen.
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-64
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-64
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// SIMD-ONLY-NOT: {{__kmpc|__tgt}}
+#ifdef CK1
+
+template <typename T, int X, long long Y>
+struct SS{
+ T a[X][Y];
+
+ // CK1: define {{.*}}i32 @{{.+}}foo{{.+}}(
+ int foo(void) {
+
+ // CK1: call i32 @__tgt_target_teams(
+ // CK1: call void @[[OFFL1:.+]](
+ #pragma omp target teams distribute parallel for collapse(2)
+ for(int i = 0; i < X; i++) {
+ for(int j = 0; j < Y; j++) {
+ a[i][j] = (T)0;
+ }
+ }
+ // CK1: define internal void @[[OFFL1]](
+ // CK1: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[OUTL1:.+]] to {{.+}},
+ // CK1: ret void
+
+ // CK1: define internal void @[[OUTL1]]({{.+}})
+ // discard loop variables not needed here
+ // CK1: [[OMP_UB:%.omp.comb.ub]] = alloca i32,
+ // CK1: store i32 56087, i32* [[OMP_UB]],
+ // CK1: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 92, {{.+}}, {{.+}}, i32* [[OMP_UB]],
+ // CK1: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL1:.+]] to
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ // CK1: define internal void @[[PAR_OUTL1]]({{.+}})
+ // CK1: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 34, {{.+}}, {{.+}},
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ return a[0][0];
+ }
+};
+
+int teams_template_struct(void) {
+ SS<int, 123, 456> V;
+ return V.foo();
+
+}
+#endif // CK1
+
+// Test host codegen.
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-64
+// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-64
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// SIMD-ONLY-NOT: {{__kmpc|__tgt}}
+#ifdef CK2
+
+template <typename T, int n, int m>
+int tmain(T argc) {
+ T a[n][m];
+ #pragma omp target teams distribute parallel for collapse(2)
+ for(int i = 0; i < n; i++) {
+ for(int j = 0; j < m; j++) {
+ a[i][j] = (T)0;
+ }
+ }
+ return 0;
+}
+
+int main (int argc, char **argv) {
+ int n = 100;
+ int m = 2;
+ int a[n][m];
+ #pragma omp target teams distribute parallel for collapse(2)
+ for(int i = 0; i < n; i++) {
+ for(int j = 0; j < m; j++) {
+ a[i][j] = 0;
+ }
+ }
+ return tmain<int, 10, 2>(argc);
+}
+
+// CK2: define {{.*}}i32 @{{[^,]+}}(i{{.+}}{{.+}} %[[ARGC:.+]], {{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFL1:.+]]({{.+}})
+// CK2: {{%.+}} = call{{.*}} i32 @[[TMAIN:.+]]({{.+}})
+// CK2: ret
+
+// CK2: define {{.*}}void @[[OFFL1]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 5, {{.+}} @[[OUTL1:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTL1]]({{.+}})
+// CK2: [[OMP_UB:%.omp.comb.ub]] = alloca i64,
+// CK2: store i64 {{.+}}, i64* [[OMP_UB]],
+// CK2: call void @__kmpc_for_static_init_8({{.+}}, {{.+}}, i32 92, {{.+}}, {{.+}}, i64* [[OMP_UB]],
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL1:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTL1]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_{{[4|8]}}({{.+}}, {{.+}}, i32 34, {{.+}}, {{.+}},
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+
+// CK2: define {{.*}}i32 @[[TMAIN]]({{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFLT1:.+]]({{.+}})
+// CK2: ret
+// CK2-NEXT: }
+
+// CK2: define {{.*}}void @[[OFFLT1]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[OUTLT1:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTLT1]]({{.+}})
+// discard loop variables not needed here
+// CK2: [[OMP_UB:%.omp.comb.ub]] = alloca i32,
+// CK2: store i32 {{.+}}, i32* [[OMP_UB]],
+// CK2: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 92, {{.+}}, {{.+}}, i32* [[OMP_UB]],
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[TPAR_OUTL1:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[TPAR_OUTL1]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 34, {{.+}}, {{.+}},
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+#endif // CK2
+#endif // #ifndef HEADER
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_collapse_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_collapse_messages.cpp
index bd94ba5205ae..61e76cde020e 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_collapse_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_collapse_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp %s -std=c++98
// RUN: %clang_cc1 -verify -fopenmp %s -std=c++11
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -std=c++98
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -std=c++11
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_default_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_default_messages.cpp
index db47e68a8a32..d7c3fbaa9c75 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_default_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_default_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo();
int main(int argc, char **argv) {
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_defaultmap_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_defaultmap_messages.cpp
index ad0295d461c4..8de99aeb214b 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_defaultmap_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_defaultmap_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_depend_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_depend_codegen.cpp
new file mode 100644
index 000000000000..5cfa2cca51b5
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_depend_codegen.cpp
@@ -0,0 +1,261 @@
+// Test host codegen.
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+// Test target codegen - host bc file has to be created first.
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+// CHECK-DAG: [[TT:%.+]] = type { i64, i8 }
+// CHECK-DAG: [[ENTTY:%.+]] = type { i8*, i8*, i[[SZ:32|64]], i32, i32 }
+// CHECK-DAG: [[DEVTY:%.+]] = type { i8*, i8*, [[ENTTY]]*, [[ENTTY]]* }
+// CHECK-DAG: [[DSCTY:%.+]] = type { i32, [[DEVTY]]*, [[ENTTY]]*, [[ENTTY]]* }
+
+// TCHECK: [[ENTTY:%.+]] = type { i8*, i8*, i{{32|64}}, i32, i32 }
+
+// CHECK-DAG: $[[REGFN:\.omp_offloading\..+]] = comdat
+
+// CHECK-DAG: [[SIZET:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 0, i[[SZ]] 4]
+// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 544, i64 800]
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = {{.*}}constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
+
+// Check if offloading descriptor is created.
+// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
+// CHECK: [[ENTEND:@.+]] = external constant [[ENTTY]]
+// CHECK: [[DEVBEGIN:@.+]] = external constant i8
+// CHECK: [[DEVEND:@.+]] = external constant i8
+// CHECK: [[IMAGES:@.+]] = internal unnamed_addr constant [1 x [[DEVTY]]] [{{.+}} { i8* [[DEVBEGIN]], i8* [[DEVEND]], [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }], comdat($[[REGFN]])
+// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
+
+// Check target registration is registered as a Ctor.
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
+
+
+template<typename tx, typename ty>
+struct TT{
+ tx X;
+ ty Y;
+};
+
+int global;
+extern int global;
+
+// CHECK: define {{.*}}[[FOO:@.+]](
+int foo(int n) {
+ int a = 0;
+ short aa = 0;
+ float b[10];
+ float bn[n];
+ double c[5][10];
+ double cn[5][n];
+ TT<long long, char> d;
+ static long *plocal;
+
+ // CHECK: [[ADD:%.+]] = add nsw i32
+ // CHECK: store i32 [[ADD]], i32* [[DEVICE_CAP:%.+]],
+ // CHECK: [[GEP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+ // CHECK: store i32 [[DEV]], i32* [[GEP]],
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[ID:@.+]], i32 [[GTID:%.+]], i32 1, i[[SZ]] {{20|40}}, i[[SZ]] 4, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY0:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY0:%.+]]*
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 1
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 2
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 3
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call void @__kmpc_omp_wait_deps(%struct.ident_t* [[ID]], i32 [[GTID]], i32 4, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: call void @__kmpc_omp_task_begin_if0(%struct.ident_t* [[ID]], i32 [[GTID]], i8* [[TASK]])
+ // CHECK: call i32 [[TASK_ENTRY0]](i32 [[GTID]], [[TASK_TY0]]* [[BC_TASK]])
+ // CHECK: call void @__kmpc_omp_task_complete_if0(%struct.ident_t* [[ID]], i32 [[GTID]], i8* [[TASK]])
+ #pragma omp target teams distribute parallel for device(global + a) depend(in: global) depend(out: a, b, cn[4])
+ for (int i = 0; i < 10; ++i) {
+ }
+
+ // CHECK: [[ADD:%.+]] = add nsw i32
+ // CHECK: store i32 [[ADD]], i32* [[DEVICE_CAP:%.+]],
+
+ // CHECK: [[BOOL:%.+]] = icmp ne i32 %{{.+}}, 0
+ // CHECK: br i1 [[BOOL]], label %[[THEN:.+]], label %[[ELSE:.+]]
+ // CHECK: [[THEN]]:
+ // CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP:%.+]], i32 0, i32 0
+ // CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P:%.+]], i32 0, i32 0
+ // CHECK-DAG: [[CBPADDR0:%.+]] = bitcast i8** [[BPADDR0]] to i[[SZ]]**
+ // CHECK-DAG: [[CPADDR0:%.+]] = bitcast i8** [[PADDR0]] to i[[SZ]]**
+ // CHECK-DAG: store i[[SZ]]* [[BP0:%[^,]+]], i[[SZ]]** [[CBPADDR0]]
+ // CHECK-DAG: store i[[SZ]]* [[BP0]], i[[SZ]]** [[CPADDR0]]
+
+ // CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 1
+ // CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P]], i32 0, i32 1
+ // CHECK-DAG: [[CBPADDR1:%.+]] = bitcast i8** [[BPADDR1]] to i[[SZ]]*
+ // CHECK-DAG: [[CPADDR1:%.+]] = bitcast i8** [[PADDR1]] to i[[SZ]]*
+ // CHECK-DAG: store i[[SZ]] [[BP1:%[^,]+]], i[[SZ]]* [[CBPADDR1]]
+ // CHECK-DAG: store i[[SZ]] [[BP1]], i[[SZ]]* [[CPADDR1]]
+ // CHECK-DAG: getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 0
+ // CHECK-DAG: getelementptr inbounds [2 x i8*], [2 x i8*]* [[P]], i32 0, i32 0
+ // CHECK: [[GEP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+ // CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+ // CHECK: store i32 [[DEV]], i32* [[GEP]],
+
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[ID]], i32 [[GTID]], i32 1, i[[SZ]] {{104|52}}, i[[SZ]] {{16|12}}, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY1_:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY1_:%.+]]*
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 1
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 2
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call i32 @__kmpc_omp_task_with_deps(%struct.ident_t* [[ID]], i32 [[GTID]], i8* [[TASK]], i32 3, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: br label %[[EXIT:.+]]
+
+ // CHECK: [[ELSE]]:
+ // CHECK-NOT: getelementptr inbounds [2 x i8*], [2 x i8*]*
+ // CHECK: [[GEP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+ // CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+ // CHECK: store i32 [[DEV]], i32* [[GEP]],
+
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[ID]], i32 [[GTID]], i32 1, i[[SZ]] {{56|28}}, i[[SZ]] {{16|12}}, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY1__:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY1__:%.+]]*
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 1
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 2
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call i32 @__kmpc_omp_task_with_deps(%struct.ident_t* [[ID]], i32 [[GTID]], i8* [[TASK]], i32 3, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: br label %[[EXIT:.+]]
+ // CHECK: [[EXIT]]:
+
+ #pragma omp target teams distribute parallel for device(global + a) nowait depend(inout: global, a, bn) if(target:a)
+ for (int i = 0; i < *plocal; ++i) {
+ static int local1;
+ *plocal = global;
+ local1 = global;
+ }
+
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[ID]], i32 [[GTID]], i32 1, i[[SZ]] {{48|24}}, i[[SZ]] 4, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY2:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY2:%.+]]*
+ // CHECK: getelementptr inbounds [1 x %struct.kmp_depend_info], [1 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [1 x %struct.kmp_depend_info], [1 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call void @__kmpc_omp_wait_deps(%struct.ident_t* [[ID]], i32 [[GTID]], i32 1, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: call void @__kmpc_omp_task_begin_if0(%struct.ident_t* [[ID]], i32 [[GTID]], i8* [[TASK]])
+ // CHECK: call i32 [[TASK_ENTRY2]](i32 [[GTID]], [[TASK_TY2]]* [[BC_TASK]])
+ // CHECK: call void @__kmpc_omp_task_complete_if0(%struct.ident_t* [[ID]], i32 [[GTID]], i8* [[TASK]])
+ #pragma omp target teams distribute parallel for if(0) firstprivate(global) depend(out:global)
+ for (int i = 0; i < global; ++i) {
+ global += 1;
+ }
+
+ return a;
+}
+
+// Check that the offloading functions are emitted and that the arguments are
+// correct and loaded correctly for the target regions in foo().
+
+// CHECK: define internal void [[HVT0:@.+]]()
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY0]](i32{{.*}}, [[TASK_TY0]]* noalias)
+// CHECK: store void (i8*, ...)* null, void (i8*, ...)** %
+// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 0
+// CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+// CHECK: [[DEVICE:%.+]] = sext i32 [[DEV]] to i64
+// CHECK: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 [[DEVICE]], i8* @{{[^,]+}}, i32 0, i8** null, i8** null, i[[SZ]]* null, i64* null, i32 0, i32 0)
+// CHECK-NEXT: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
+// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
+// CHECK: [[FAIL]]
+// CHECK: call void [[HVT0]]()
+// CHECK-NEXT: br label %[[END]]
+// CHECK: [[END]]
+// CHECK: ret i32 0
+
+// CHECK: define internal void [[HVT1:@.+]](i[[SZ]]* %{{.+}}, i[[SZ]] %{{.+}})
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY1_]](i32{{.*}}, [[TASK_TY1_]]* noalias)
+// CHECK: call void (i8*, ...) %
+// CHECK: [[SZT:%.+]] = getelementptr inbounds [2 x i[[SZ]]], [2 x i[[SZ]]]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+// CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+// CHECK: [[DEVICE:%.+]] = sext i32 [[DEV]] to i64
+// CHECK: [[RET:%.+]] = call i32 @__tgt_target_teams_nowait(i64 [[DEVICE]], i8* @{{[^,]+}}, i32 2, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SZT]], i64* getelementptr inbounds ([2 x i64], [2 x i64]* [[MAPT]], i32 0, i32 0), i32 0, i32 0)
+
+// CHECK: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
+// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
+// CHECK: [[FAIL]]
+// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
+// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
+// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
+// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
+// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
+// CHECK: [[BP1:%.+]] = load i[[SZ]], i[[SZ]]* [[BP1_PTR]],
+// CHECK: call void [[HVT1]](i[[SZ]]* [[BP0]], i[[SZ]] [[BP1]])
+// CHECK-NEXT: br label %[[END]]
+// CHECK: [[END]]
+// CHECK: ret i32 0
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY1__]](i32{{.*}}, [[TASK_TY1__]]* noalias)
+// CHECK: call void (i8*, ...) %
+// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
+// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
+// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
+// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
+// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
+// CHECK: [[BP1:%.+]] = load i[[SZ]], i[[SZ]]* [[BP1_PTR]],
+// CHECK: call void [[HVT1]](i[[SZ]]* [[BP0]], i[[SZ]] [[BP1]])
+// CHECK: ret i32 0
+
+// CHECK: define internal void [[HVT2:@.+]](i[[SZ]] %{{.+}})
+// Create stack storage and store argument in there.
+// CHECK: [[AA_ADDR:%.+]] = alloca i[[SZ]], align
+// CHECK: store i[[SZ]] %{{.+}}, i[[SZ]]* [[AA_ADDR]], align
+// CHECK-64: [[AA_CADDR:%.+]] = bitcast i[[SZ]]* [[AA_ADDR]] to i32*
+// CHECK-64: load i32, i32* [[AA_CADDR]], align
+// CHECK-32: load i32, i32* [[AA_ADDR]], align
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY2]](i32{{.*}}, [[TASK_TY2]]* noalias)
+// CHECK: call void (i8*, ...) %
+// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
+// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
+// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
+// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
+// CHECK: [[BP1:%.+]] = load i[[SZ]], i[[SZ]]* [[BP1_PTR]],
+// CHECK: call void [[HVT2]](i[[SZ]] [[BP1]])
+// CHECK: ret i32 0
+
+
+#endif
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_depend_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_depend_messages.cpp
index c4688958e554..253e139b82a6 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_depend_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_depend_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_device_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_device_messages.cpp
index b1b86cd4080b..64b682a601b3 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_device_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_device_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_dist_schedule_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_dist_schedule_codegen.cpp
new file mode 100644
index 000000000000..28619f883f9d
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_dist_schedule_codegen.cpp
@@ -0,0 +1,270 @@
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+// Test host codegen.
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-64
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-64
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// SIMD-ONLY-NOT: {{__kmpc|__tgt}}
+#ifdef CK1
+
+template <typename T, int X, long long Y>
+struct SS{
+ T a[X];
+ float b;
+ // CK1: define {{.*}}i32 @{{.+}}foo{{.+}}(
+ int foo(void) {
+
+ // CK1: call i32 @__tgt_target_teams(
+ // CK1: call void @[[OFFL1:.+]](
+ #pragma omp target teams distribute parallel for
+ for(int i = 0; i < X; i++) {
+ a[i] = (T)0;
+ }
+ // CK1: call i32 @__tgt_target_teams(
+ // CK1: call void @[[OFFL2:.+]](
+ #pragma omp target teams distribute parallel for dist_schedule(static)
+ for(int i = 0; i < X; i++) {
+ a[i] = (T)0;
+ }
+ // CK1: call i32 @__tgt_target_teams(
+ // CK1: call void @[[OFFL3:.+]](
+ #pragma omp target teams distribute parallel for dist_schedule(static, X/2)
+ for(int i = 0; i < X; i++) {
+ a[i] = (T)0;
+ }
+ // CK1: define internal void @[[OFFL1]](
+ // CK1: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[OUTL1:.+]] to {{.+}},
+ // CK1: ret void
+
+ // CK1: define internal void @[[OUTL1]]({{.+}})
+ // CK1: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 92
+ // CK1: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL1:.+]] to
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ // CK1: define internal void @[[PAR_OUTL1]]({{.+}})
+ // CK1: call void @__kmpc_for_static_init_4(
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ // CK1: define internal void @[[OFFL2]](
+ // CK1: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[OUTL2:.+]] to {{.+}},
+ // CK1: ret void
+
+ // CK1: define internal void @[[OUTL2]]({{.+}})
+ // CK1: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 92
+ // CK1: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL2:.+]] to
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ // CK1: define internal void @[[PAR_OUTL2]]({{.+}})
+ // CK1: call void @__kmpc_for_static_init_4(
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+
+ // CK1: define internal void @[[OFFL3]](
+ // CK1: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[OUTL3:.+]] to {{.+}},
+ // CK1: ret void
+
+ // CK1: define internal void @[[OUTL3]]({{.+}})
+ // CK1: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 91
+ // CK1: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL3:.+]] to
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ // CK1: define internal void @[[PAR_OUTL3]]({{.+}})
+ // CK1: call void @__kmpc_for_static_init_4(
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ return a[0];
+ }
+};
+
+int teams_template_struct(void) {
+ SS<int, 123, 456> V;
+ return V.foo();
+
+}
+#endif // CK1
+
+// Test host codegen.
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-64
+// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-64
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// SIMD-ONLY-NOT: {{__kmpc|__tgt}}
+#ifdef CK2
+
+template <typename T, int n>
+int tmain(T argc) {
+ T a[n];
+ int m = 10;
+#pragma omp target teams distribute parallel for
+ for(int i = 0; i < n; i++) {
+ a[i] = (T)0;
+ }
+#pragma omp target teams distribute parallel for dist_schedule(static)
+ for(int i = 0; i < n; i++) {
+ a[i] = (T)0;
+ }
+#pragma omp target teams distribute parallel for dist_schedule(static, m)
+ for(int i = 0; i < n; i++) {
+ a[i] = (T)0;
+ }
+ return 0;
+}
+
+int main (int argc, char **argv) {
+ int n = 100;
+ int a[n];
+ int m = 10;
+#pragma omp target teams distribute parallel for
+ for(int i = 0; i < n; i++) {
+ a[i] = 0;
+ }
+#pragma omp target teams distribute parallel for dist_schedule(static)
+ for(int i = 0; i < n; i++) {
+ a[i] = 0;
+ }
+#pragma omp target teams distribute parallel for dist_schedule(static, m)
+ for(int i = 0; i < n; i++) {
+ a[i] = 0;
+ }
+ return tmain<int, 10>(argc);
+}
+
+// CK2: define {{.*}}i32 @{{[^,]+}}(i{{.+}}{{.+}} %[[ARGC:.+]], {{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFL1:.+]]({{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFL2:.+]]({{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFL3:.+]]({{.+}})
+// CK2: {{%.+}} = call{{.*}} i32 @[[TMAIN:.+]]({{.+}})
+// CK2: ret
+
+// CK2: define {{.*}}void @[[OFFL1]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 3, {{.+}} @[[OUTL1:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTL1]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 92
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL1:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTL1]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4(
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define {{.*}}void @[[OFFL2]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 3, {{.+}} @[[OUTL2:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTL2]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 92
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL2:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTL2]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4(
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define {{.*}}void @[[OFFL3]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 4, {{.+}} @[[OUTL3:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTL3]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 91
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL3:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTL3]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4(
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define {{.*}}i32 @[[TMAIN]]({{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFLT1:.+]]({{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFLT2:.+]]({{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFLT3:.+]]({{.+}})
+// CK2: ret
+// CK2-NEXT: }
+
+// CK2: define {{.*}}void @[[OFFLT1]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[OUTLT1:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTLT1]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 92
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTLT1:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTLT1]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4(
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define {{.*}}void @[[OFFLT2]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[OUTLT2:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTLT2]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 92
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTLT2:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTLT2]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4(
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define {{.*}}void @[[OFFLT3]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 {{.+}}, {{.+}} @[[OUTLT3:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTLT3]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 91
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTLT3:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTLT3]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4(
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+#endif // CK2
+#endif // #ifndef HEADER
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_dist_schedule_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_dist_schedule_messages.cpp
index d9913bc96212..a8abaffb464a 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_dist_schedule_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_dist_schedule_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_firstprivate_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_firstprivate_codegen.cpp
new file mode 100644
index 000000000000..843b667316a5
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_firstprivate_codegen.cpp
@@ -0,0 +1,523 @@
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 --check-prefix HCHECK --check-prefix HCHECK-64
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 --check-prefix HCHECK --check-prefix HCHECK-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix HCHECK --check-prefix HCHECK-32
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix HCHECK --check-prefix HCHECK-32
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64 --check-prefix HLAMBDA --check-prefix HLAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64 --check-prefix HLAMBDA --check-prefix HLAMBDA-64
+
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+
+// Test target codegen - host bc file has to be created first. (no significant differences with host version of target region)
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix TCHECK --check-prefix TCHECK-32
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64 --check-prefix TLAMBDA --check-prefix TLAMBDA-64
+
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix SIMD-ONLY
+// SIMD-ONLY-NOT: {{__kmpc|__tgt}}
+
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+struct St {
+ int a, b;
+ St() : a(0), b(0) {}
+ St(const St &st) : a(st.a + st.b), b(0) {}
+ ~St() {}
+};
+
+volatile int g = 1212;
+volatile int &g1 = g;
+
+template <class T>
+struct S {
+ T f;
+ S(T a) : f(a + g) {}
+ S() : f(g) {}
+ S(const S &s, St t = St()) : f(s.f + t.a) {}
+ operator T() { return T(); }
+ ~S() {}
+};
+
+// CHECK-DAG: [[S_FLOAT_TY:%.+]] = type { float }
+// CHECK-DAG: [[S_INT_TY:%.+]] = type { i{{[0-9]+}} }
+// CHECK-DAG: [[ST_TY:%.+]] = type { i{{[0-9]+}}, i{{[0-9]+}} }
+
+template <typename T>
+T tmain() {
+ S<T> test;
+ T t_var = T();
+ T vec[] = {1, 2};
+ S<T> s_arr[] = {1, 2};
+ S<T> &var = test;
+#pragma omp target teams distribute parallel for firstprivate(t_var, vec, s_arr, var)
+ for (int i = 0; i < 2; ++i) {
+ vec[i] = t_var;
+ s_arr[i] = var;
+ }
+ return T();
+}
+
+// HCHECK-DAG: [[TEST:@.+]] = global [[S_FLOAT_TY]] zeroinitializer,
+S<float> test;
+// HCHECK-DAG: [[T_VAR:@.+]] = global i{{[0-9]+}} 333,
+int t_var = 333;
+// HCHECK-DAG: [[VEC:@.+]] = global [2 x i{{[0-9]+}}] [i{{[0-9]+}} 1, i{{[0-9]+}} 2],
+int vec[] = {1, 2};
+// HCHECK-DAG: [[S_ARR:@.+]] = global [2 x [[S_FLOAT_TY]]] zeroinitializer,
+S<float> s_arr[] = {1, 2};
+// HCHECK-DAG: [[VAR:@.+]] = global [[S_FLOAT_TY]] zeroinitializer,
+S<float> var(3);
+// HCHECK-DAG: [[SIVAR:@.+]] = internal global i{{[0-9]+}} 0,
+
+int main() {
+ static int sivar;
+#ifdef LAMBDA
+ // HLAMBDA: [[G:@.+]] = global i{{[0-9]+}} 1212,
+ // HLAMBDA-LABEL: @main
+ // HLAMBDA: call void [[OUTER_LAMBDA:@.+]](
+ [&]() {
+ // HLAMBDA: define{{.*}} internal{{.*}} void [[OUTER_LAMBDA]](
+ // HLAMBDA: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 3, i8** %{{[^,]+}}, i8** %{{[^,]+}}, i{{64|32}}* {{.+}}@{{[^,]+}}, i32 0, i32 0), i64* {{.+}}@{{[^,]+}}, i32 0, i32 0), i32 0, i32 0)
+ // HLAMBDA: call void @[[LOFFL1:.+]](i{{64|32}} %{{.+}})
+ // HLAMBDA: ret
+#pragma omp target teams distribute parallel for firstprivate(g, g1, sivar)
+ for (int i = 0; i < 2; ++i) {
+ // HLAMBDA: define{{.*}} internal{{.*}} void @[[LOFFL1]](i{{64|32}} {{%.+}}, i{{64|32}} {{%.+}})
+ // TLAMBDA: define weak void @[[LOFFL1:.+]](i{{64|32}} {{%.+}}, i{{64|32}} {{%.+}})
+ // LAMBDA: {{%.+}} = alloca i{{[0-9]+}},
+ // LAMBDA: {{%.+}} = alloca i{{[0-9]+}},
+ // LAMBDA: {{%.+}} = alloca i{{[0-9]+}},
+ // LAMBDA: [[G_CAST:%.+]] = alloca i{{[0-9]+}},
+ // LAMBDA: [[G1_CAST:%.+]] = alloca i{{[0-9]+}},
+ // LAMBDA: [[SIVAR_CAST:%.+]] = alloca i{{[0-9]+}},
+ // LAMBDA-DAG: [[G_CAST_VAL:%.+]] = load{{.+}} [[G_CAST]],
+ // LAMBDA-DAG: [[G1_CAST_VAL:%.+]] = load{{.+}} [[G1_CAST]],
+ // LAMBDA-DAG: [[SIVAR_CAST_VAL:%.+]] = load{{.+}} [[SIVAR_CAST]],
+ // LAMBDA: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 3, {{.+}} @[[LOUTL1:.+]] to {{.+}}, {{.+}} [[G_CAST_VAL]], {{.+}} [[G1_CAST_VAL]], {{.+}} [[SIVAR_CAST_VAL]])
+ // LAMBDA: ret void
+
+ // LAMBDA: define internal void @[[LOUTL1]]({{.+}})
+ // Skip global and bound tid vars
+ // LAMBDA: {{.+}} = alloca i32*,
+ // LAMBDA: {{.+}} = alloca i32*,
+ // LAMBDA: [[G_ADDR:%.+]] = alloca i{{[0-9]+}},
+ // LAMBDA: [[G1_ADDR:%.+]] = alloca i{{[0-9]+}},
+ // LAMBDA: [[SIVAR_ADDR:%.+]] = alloca i{{[0-9]+}},
+ // LAMBDA: [[G1_TMP:%.+]] = alloca i32*,
+ // skip loop vars
+ // LAMBDA-DAG: store {{.+}}, {{.+}} [[G_ADDR]],
+ // LAMBDA-DAG: store {{.+}}, {{.+}} [[G1_ADDR]],
+ // LAMBDA-DAG: store {{.+}}, {{.+}} [[SIVAR_ADDR]],
+ // LAMBDA-DAG: [[G_CONV:%.+]] = bitcast {{.+}} [[G_ADDR]] to
+ // LAMBDA-DAG: [[G1_CONV:%.+]] = bitcast {{.+}} [[G1_ADDR]] to
+ // LAMBDA-DAG: [[SIVAR_CONV:%.+]] = bitcast {{.+}} [[SIVAR_ADDR]] to
+ // LAMBDA-DAG: store{{.+}} [[G1_CONV]], {{.+}} [[G1_TMP]],
+ g = 1;
+ g1 = 1;
+ sivar = 2;
+ // LAMBDA: call void @__kmpc_for_static_init_4(
+ // LAMBDA: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[LPAR_OUTL:.+]] to
+ // LAMBDA: call void @__kmpc_for_static_fini(
+ // LAMBDA: ret void
+
+ // LAMBDA: define internal void @[[LPAR_OUTL]]({{.+}})
+ // Skip global and bound tid vars, and prev lb and ub vars
+ // LAMBDA: {{.+}} = alloca i32*,
+ // LAMBDA: {{.+}} = alloca i32*,
+ // LAMBDA: {{.+}} = alloca i{{[0-9]+}},
+ // LAMBDA: {{.+}} = alloca i{{[0-9]+}},
+ // LAMBDA: [[G_ADDR:%.+]] = alloca i{{[0-9]+}},
+ // LAMBDA: [[G1_ADDR:%.+]] = alloca i{{[0-9]+}},
+ // LAMBDA: [[SIVAR_ADDR:%.+]] = alloca i{{[0-9]+}},
+ // LAMBDA: [[G1_TMP:%.+]] = alloca i32*,
+ // skip loop vars
+ // LAMBDA-DAG: store {{.+}}, {{.+}} [[G_ADDR]],
+ // LAMBDA-DAG: store {{.+}}, {{.+}} [[G1_ADDR]],
+ // LAMBDA-DAG: store {{.+}}, {{.+}} [[SIVAR_ADDR]],
+ // LAMBDA-DAG: [[G_CONV:%.+]] = bitcast {{.+}} [[G_ADDR]] to
+ // LAMBDA-DAG: [[G1_CONV:%.+]] = bitcast {{.+}} [[G1_ADDR]] to
+ // LAMBDA-DAG: [[SIVAR_CONV:%.+]] = bitcast {{.+}} [[SIVAR_ADDR]] to
+ // LAMBDA-DAG: store{{.+}} [[G1_CONV]], {{.+}} [[G1_TMP]],
+
+ // use of private vars
+ // LAMBDA-DAG: store{{.+}} 1, {{.+}} [[G_CONV]],
+ // LAMBDA-DAG: [[G1:%.+]] = load{{.+}}, {{.+}}* [[G1_TMP]]
+ // LAMBDA-DAG: store{{.+}} 1, {{.+}} [[G1]],
+ // LAMBDA-DAG: store{{.+}} 2, {{.+}} [[SIVAR_CONV]],
+ // LAMBDA-DAG: [[G1_REF:%.+]] = load{{.+}}, {{.+}} [[G1_TMP]],
+ // LAMBDA: call void [[INNER_LAMBDA:@.+]](
+ // LAMBDA: call void @__kmpc_for_static_fini(
+ // LAMBDA: ret void
+ [&]() {
+ // LAMBDA: define {{.+}} void [[INNER_LAMBDA]](%{{.+}}* [[ARG_PTR:%.+]])
+ // LAMBDA: store %{{.+}}* [[ARG_PTR]], %{{.+}}** [[ARG_PTR_REF:%.+]],
+ g = 2;
+ g1 = 2;
+ sivar = 4;
+ // LAMBDA: [[ARG_PTR:%.+]] = load %{{.+}}*, %{{.+}}** [[ARG_PTR_REF]]
+
+ // LAMBDA: [[G_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
+ // LAMBDA: [[G_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[G_PTR_REF]]
+ // LAMBDA: store i{{[0-9]+}} 2, i{{[0-9]+}}* [[G_REF]]
+ // LAMBDA: [[G1_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 1
+ // LAMBDA: [[G1_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[G1_PTR_REF]]
+ // LAMBDA: store i{{[0-9]+}} 2, i{{[0-9]+}}* [[G1_REF]]
+ // LAMBDA: [[SIVAR_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 2
+ // LAMBDA: [[SIVAR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SIVAR_PTR_REF]]
+ // LAMBDA: store i{{[0-9]+}} 4, i{{[0-9]+}}* [[SIVAR_REF]]
+ }();
+ }
+ }();
+ return 0;
+#else
+#pragma omp target teams distribute parallel for firstprivate(t_var, vec, s_arr, var, sivar)
+ for (int i = 0; i < 2; ++i) {
+ vec[i] = t_var;
+ s_arr[i] = var;
+ sivar += i;
+ }
+ return tmain<int>();
+#endif
+}
+
+// HCHECK: define {{.*}}i{{[0-9]+}} @main()
+// HCHECK: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 5,
+// HCHECK: call void @[[OFFL1:.+]](
+// HCHECK: {{%.+}} = call{{.*}} i32 @[[TMAIN_INT:.+]]()
+// HCHECK: ret
+
+// HCHECK: define{{.*}} void @[[OFFL1]](
+// TCHECK: define{{.*}} void @[[OFFL1:.+]](
+// CHECK-DAG: [[T_VAR_PRIV:%.+]] = alloca i{{[0-9]+}},
+// CHECK-DAG: [[VEC_PRIV:%.+]] = alloca [2 x i{{[0-9]+}}]*,
+// CHECK-DAG: [[S_ARR_PRIV:%.+]] = alloca [2 x [[S_FLOAT_TY]]]*,
+// CHECK-DAG: [[VAR_PRIV:%.+]] = alloca [[S_FLOAT_TY]]*,
+// CHECK: [[SIVAR_PRIV:%.+]] = alloca i{{[0-9]+}},
+// CHECK: [[T_VAR_CAST:%.+]] = alloca i{{[0-9]+}},
+// CHECK: [[SIVAR_CAST:%.+]] = alloca i{{[0-9]+}},
+
+// CHECK-DAG: [[VEC_TE_PAR:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_PRIV]],
+// CHECK-DAG: [[T_VAR_TE_PAR:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[T_VAR_CAST]],
+// CHECK-DAG: [[S_ARR_TE_PAR:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[S_ARR_PRIV]],
+// CHECK-DAG: [[VAR_TE_PAR:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[VAR_PRIV]],
+// CHECK-DAG: [[SIVAR_TE_PAR:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SIVAR_CAST]],
+
+// CHECK: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 5, {{.+}} @[[OUTL1:.+]] to {{.+}}, [2 x i{{[0-9]+}}]* [[VEC_TE_PAR]], i{{[0-9]+}} [[T_VAR_TE_PAR]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_TE_PAR]], [[S_FLOAT_TY]]* [[VAR_TE_PAR]], i{{[0-9]+}} [[SIVAR_TE_PAR]])
+// CHECK: ret void
+
+// CHECK: define internal void @[[OUTL1]]({{.+}})
+// Skip global and bound tid vars
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: [[VEC_ADDR:%.+]] = alloca [2 x i{{[0-9]+}}]*,
+// CHECK: [[T_VAR_ADDR:%.+]] = alloca i{{[0-9]+}},
+// CHECK: [[S_ARR_ADDR:%.+]] = alloca [2 x [[S_FLOAT_TY]]]*,
+// CHECK: [[VAR_ADDR:%.+]] = alloca [[S_FLOAT_TY]]*,
+// CHECK: [[SIVAR_ADDR:%.+]] = alloca i{{[0-9]+}},
+// Skip temp vars for loop
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: [[VEC_PRIV:%.+]] = alloca [2 x i{{[0-9]+}}],
+// CHECK: [[S_ARR_PRIV:%.+]] = alloca [2 x [[S_FLOAT_TY]]],
+// CHECK: [[AGG_TMP1:%.+]] = alloca [[ST_TY]],
+// CHECK: [[VAR_PRIV:%.+]] = alloca [[S_FLOAT_TY]],
+// CHECK: [[AGG_TMP2:%.+]] = alloca [[ST_TY]],
+
+// param copy
+// CHECK: store [2 x i{{[0-9]+}}]* {{.+}}, [2 x i{{[0-9]+}}]** [[VEC_ADDR]],
+// CHECK: store i{{[0-9]+}} {{.+}}, i{{[0-9]+}}* [[T_VAR_ADDR]],
+// CHECK: store [2 x [[S_FLOAT_TY]]]* {{.+}}, [2 x [[S_FLOAT_TY]]]** [[S_ARR_ADDR]],
+// CHECK: store [[S_FLOAT_TY]]* {{.+}}, [[S_FLOAT_TY]]** [[VAR_ADDR]],
+// CHECK: store i{{[0-9]+}} {{.+}}, i{{[0-9]+}}* [[SIVAR_ADDR]],
+
+// T_VAR and SIVAR
+// CHECK-64-DAG: [[CONV_TVAR:%.+]] = bitcast i64* [[T_VAR_ADDR]] to i32*
+// CHECK-64-DAG: [[CONV_SIVAR:%.+]] = bitcast i64* [[SIVAR_ADDR]] to i32*
+
+// preparation vars
+// CHECK-DAG: [[VEC_ADDR_VAL:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]],
+// CHECK-DAG: [[S_ARR_ADDR_REF:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[S_ARR_ADDR]],
+// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load{{.+}} [[VAR_ADDR]],
+
+// firstprivate vec(vec): copy from *_addr into priv1 and then from priv1 into priv2
+// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
+// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8*
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST_PRIV]], i8* align {{[0-9]+}} [[VEC_SRC]], {{.+}})
+
+// firstprivate(s_arr)
+// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]],
+// CHECK-DAG: [[S_ARR_ADDR_BGN:%.+]] = bitcast [2 x [[S_FLOAT_TY]]]* [[S_ARR_ADDR_REF]] to
+// CHECK-DAG: [[S_ARR_FIN:%.+]] = icmp{{.+}} [[S_ARR_PRIV_BGN]],
+// CHECK-DAG: [[S_ARR_SRC_COPY:%.+]] = phi{{.+}} [ [[S_ARR_ADDR_BGN]], {{.+}} ], [ [[S_ARR_SRC:%.+]], {{.+}} ]
+// CHECK-DAG: [[S_ARR_DST_COPY:%.+]] = phi{{.+}} [ [[S_ARR_PRIV_BGN]], {{.+}}], [ [[S_ARR_DST:%.+]], {{.+}} ]
+// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP1]])
+// CHECK-DAG: call void @{{.+}}({{.+}} [[S_ARR_DST_COPY]], {{.+}} [[S_ARR_SRC_COPY]], {{.+}} [[AGG_TMP1]])
+// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP1]])
+// CHECK-DAG: [[S_ARR_DST]] = getelementptr {{.+}} [[S_ARR_DST_COPY]],
+// CHECK-DAG: [[S_ARR_SRC]] = getelementptr {{.+}} [[S_ARR_SRC_COPY]],
+
+// firstprivate(var)
+// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]])
+// CHECK-DAG: call void @{{.+}}({{.+}} [[VAR_PRIV]], {{.+}} [[VAR_ADDR_REF]], {{.+}} [[AGG_TMP2]])
+// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]])
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL:.+]] to
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: ret void
+
+// CHECK: define internal void @[[PAR_OUTL]]({{.+}})
+// Skip global and bound tid vars, and prev lb ub vars
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: [[VEC_ADDR:%.+]] = alloca [2 x i{{[0-9]+}}]*,
+// CHECK: [[T_VAR_ADDR:%.+]] = alloca i{{[0-9]+}},
+// CHECK: [[S_ARR_ADDR:%.+]] = alloca [2 x [[S_FLOAT_TY]]]*,
+// CHECK: [[VAR_ADDR:%.+]] = alloca [[S_FLOAT_TY]]*,
+// CHECK: [[SIVAR_ADDR:%.+]] = alloca i{{[0-9]+}},
+// Skip temp vars for loop
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: [[VEC_PRIV:%.+]] = alloca [2 x i{{[0-9]+}}],
+// CHECK: [[S_ARR_PRIV:%.+]] = alloca [2 x [[S_FLOAT_TY]]],
+// CHECK: [[AGG_TMP1:%.+]] = alloca [[ST_TY]],
+// CHECK: [[VAR_PRIV:%.+]] = alloca [[S_FLOAT_TY]],
+// CHECK: [[AGG_TMP2:%.+]] = alloca [[ST_TY]],
+
+// param copy
+// CHECK: store [2 x i{{[0-9]+}}]* {{.+}}, [2 x i{{[0-9]+}}]** [[VEC_ADDR]],
+// CHECK: store i{{[0-9]+}} {{.+}}, i{{[0-9]+}}* [[T_VAR_ADDR]],
+// CHECK: store [2 x [[S_FLOAT_TY]]]* {{.+}}, [2 x [[S_FLOAT_TY]]]** [[S_ARR_ADDR]],
+// CHECK: store [[S_FLOAT_TY]]* {{.+}}, [[S_FLOAT_TY]]** [[VAR_ADDR]],
+// CHECK: store i{{[0-9]+}} {{.+}}, i{{[0-9]+}}* [[SIVAR_ADDR]],
+
+// T_VAR and SIVAR
+// CHECK-64-DAG: [[CONV_TVAR:%.+]] = bitcast i64* [[T_VAR_ADDR]] to i32*
+// CHECK-64-DAG: [[CONV_SIVAR:%.+]] = bitcast i64* [[SIVAR_ADDR]] to i32*
+
+// preparation vars
+// CHECK-DAG: [[VEC_ADDR_VAL:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]],
+// CHECK-DAG: [[S_ARR_ADDR_REF:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[S_ARR_ADDR]],
+// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load{{.+}} [[VAR_ADDR]],
+
+// firstprivate vec(vec): copy from *_addr into priv1 and then from priv1 into priv2
+// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
+// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8*
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST_PRIV]], i8* align {{[0-9]+}} [[VEC_SRC]], {{.+}})
+
+// firstprivate(s_arr)
+// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]],
+// CHECK-DAG: [[S_ARR_ADDR_BGN:%.+]] = bitcast [2 x [[S_FLOAT_TY]]]* [[S_ARR_ADDR_REF]] to
+// CHECK-DAG: [[S_ARR_FIN:%.+]] = icmp{{.+}} [[S_ARR_PRIV_BGN]],
+// CHECK-DAG: [[S_ARR_SRC_COPY:%.+]] = phi{{.+}} [ [[S_ARR_ADDR_BGN]], {{.+}} ], [ [[S_ARR_SRC:%.+]], {{.+}} ]
+// CHECK-DAG: [[S_ARR_DST_COPY:%.+]] = phi{{.+}} [ [[S_ARR_PRIV_BGN]], {{.+}}], [ [[S_ARR_DST:%.+]], {{.+}} ]
+// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP1]])
+// CHECK-DAG: call void @{{.+}}({{.+}} [[S_ARR_DST_COPY]], {{.+}} [[S_ARR_SRC_COPY]], {{.+}} [[AGG_TMP1]])
+// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP1]])
+// CHECK-DAG: [[S_ARR_DST]] = getelementptr {{.+}} [[S_ARR_DST_COPY]],
+// CHECK-DAG: [[S_ARR_SRC]] = getelementptr {{.+}} [[S_ARR_SRC_COPY]],
+
+// firstprivate(var)
+// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]])
+// CHECK-DAG: call void @{{.+}}({{.+}} [[VAR_PRIV]], {{.+}} [[VAR_ADDR_REF]], {{.+}} [[AGG_TMP2]])
+// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]])
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK-32-DAG: {{.+}} = {{.+}} [[T_VAR_ADDR]]
+// CHECK-64-DAG: {{.+}} = {{.+}} [[CONV_TVAR]]
+// CHECK-DAG: {{.+}} = {{.+}} [[VEC_PRIV]]
+// CHECK-DAG: {{.+}} = {{.+}} [[S_ARR_PRIV]]
+// CHECK-DAG: {{.+}} = {{.+}} [[VAR_PRIV]]
+// CHECK-32-DAG: {{.+}} = {{.+}} [[SIVAR_ADDR]]
+// CHECK-64-DAG: {{.+}} = {{.+}} [[CONV_SIVAR]]
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: ret void
+
+// HCHECK: define{{.*}} i{{[0-9]+}} @[[TMAIN_INT]]()
+// HCHECK: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 4, i8** %{{[^,]+}}, i8** %{{[^,]+}}, i{{64|32}}* {{.+}}@{{[^,]+}}, i32 0, i32 0), i64* {{.+}}@{{[^,]+}}, i32 0, i32 0), i32 0, i32 0)
+// HCHECK: call void @[[TOFFL1:.+]](
+// HCHECK: ret
+
+// HCHECK: define {{.*}}void @[[TOFFL1]]({{.+}})
+// TCHECK: define {{.*}}void @[[TOFFL1:.+]]({{.+}})
+// CHECK-DAG: [[TT_VAR_PRIV:%.+]] = alloca i{{[0-9]+}},
+// CHECK-DAG: [[TVEC_PRIV:%.+]] = alloca [2 x i{{[0-9]+}}]*,
+// CHECK-DAG: [[TS_ARR_PRIV:%.+]] = alloca [2 x [[S_INT_TY]]]*,
+// CHECK-DAG: [[TVAR_PRIV:%.+]] = alloca [[S_INT_TY]]*,
+// CHECK: [[TT_VAR_CAST:%.+]] = alloca i{{[0-9]+}},
+
+// CHECK-DAG: [[TVEC_TE_PAR:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[TVEC_PRIV]],
+// CHECK-DAG: [[TT_VAR_TE_PAR:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[TT_VAR_CAST]],
+// CHECK-DAG: [[TS_ARR_TE_PAR:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[TS_ARR_PRIV]],
+// CHECK-DAG: [[TVAR_TE_PAR:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TVAR_PRIV]],
+
+// CHECK: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 4, {{.+}} @[[TOUTL1:.+]] to {{.+}}, [2 x i{{[0-9]+}}]* [[TVEC_TE_PAR]], i{{[0-9]+}} [[TT_VAR_TE_PAR]], [2 x [[S_INT_TY]]]* [[TS_ARR_TE_PAR]], [[S_INT_TY]]* [[TVAR_TE_PAR]])
+// CHECK: ret void
+
+// CHECK: define internal void @[[TOUTL1]]({{.+}})
+// Skip global and bound tid vars
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: [[VEC_ADDR:%.+]] = alloca [2 x i{{[0-9]+}}]*,
+// CHECK: [[T_VAR_ADDR:%.+]] = alloca i{{[0-9]+}},
+// CHECK: [[S_ARR_ADDR:%.+]] = alloca [2 x [[S_INT_TY]]]*,
+// CHECK: [[VAR_ADDR:%.+]] = alloca [[S_INT_TY]]*,
+// Skip temp vars for loop
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: [[VEC_PRIV:%.+]] = alloca [2 x i{{[0-9]+}}],
+// CHECK: [[S_ARR_PRIV:%.+]] = alloca [2 x [[S_INT_TY]]],
+// CHECK: [[AGG_TMP1:%.+]] = alloca [[ST_TY]],
+// CHECK: [[VAR_PRIV:%.+]] = alloca [[S_INT_TY]],
+// CHECK: [[AGG_TMP2:%.+]] = alloca [[ST_TY]],
+// CHECK: [[TMP:%.+]] = alloca [[S_INT_TY]]*,
+
+// param copy
+// CHECK: store [2 x i{{[0-9]+}}]* {{.+}}, [2 x i{{[0-9]+}}]** [[VEC_ADDR]],
+// CHECK: store i{{[0-9]+}} {{.+}}, i{{[0-9]+}}* [[T_VAR_ADDR]],
+// CHECK: store [2 x [[S_INT_TY]]]* {{.+}}, [2 x [[S_INT_TY]]]** [[S_ARR_ADDR]],
+// CHECK: store [[S_INT_TY]]* {{.+}}, [[S_INT_TY]]** [[VAR_ADDR]],
+
+// T_VAR and preparation variables
+// CHECK: [[VEC_ADDR_VAL:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]],
+// CHECK-64: [[CONV_TVAR:%.+]] = bitcast i64* [[T_VAR_ADDR]] to i32*
+// CHECK: [[S_ARR_ADDR_REF:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[S_ARR_ADDR]],
+
+// firstprivate vec(vec): copy from *_addr into priv1 and then from priv1 into priv2
+// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
+// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8*
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST_PRIV]], i8* align {{[0-9]+}} [[VEC_SRC]], {{.+}})
+
+// firstprivate(s_arr)
+// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_PRIV]],
+// CHECK-DAG: [[S_ARR_ADDR_BGN:%.+]] = bitcast [2 x [[S_INT_TY]]]* [[S_ARR_ADDR_REF]] to
+// CHECK-DAG: [[S_ARR_FIN:%.+]] = icmp{{.+}} [[S_ARR_PRIV_BGN]],
+// CHECK-DAG: [[S_ARR_SRC_COPY:%.+]] = phi{{.+}} [ [[S_ARR_ADDR_BGN]], {{.+}} ], [ [[S_ARR_SRC:%.+]], {{.+}} ]
+// CHECK-DAG: [[S_ARR_DST_COPY:%.+]] = phi{{.+}} [ [[S_ARR_PRIV_BGN]], {{.+}} ], [ [[S_ARR_DST:%.+]], {{.+}} ]
+// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP1]])
+// CHECK-DAG: call void @{{.+}}({{.+}} [[S_ARR_DST_COPY]], {{.+}} [[S_ARR_SRC_COPY]], {{.+}} [[AGG_TMP1]])
+// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP1]])
+// CHECK-DAG: [[S_ARR_DST]] = getelementptr {{.+}} [[S_ARR_DST_COPY]],
+// CHECK-DAG: [[S_ARR_SRC]] = getelementptr {{.+}} [[S_ARR_SRC_COPY]],
+
+// firstprivate(var)
+// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load{{.+}} [[VAR_ADDR]],
+// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]])
+// CHECK-DAG: call void @{{.+}}({{.+}} [[VAR_PRIV]], {{.+}} [[VAR_ADDR_REF]], {{.+}} [[AGG_TMP2]])
+// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]])
+// CHECK-DAG: store [[S_INT_TY]]* [[VAR_PRIV]], [[S_INT_TY]]** [[TMP]],
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[TPAR_OUTL:.+]] to
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: ret void
+
+// CHECK: define internal void @[[TPAR_OUTL]]({{.+}})
+// Skip global and bound tid vars
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: [[VEC_ADDR:%.+]] = alloca [2 x i{{[0-9]+}}]*,
+// CHECK: [[T_VAR_ADDR:%.+]] = alloca i{{[0-9]+}},
+// CHECK: [[S_ARR_ADDR:%.+]] = alloca [2 x [[S_INT_TY]]]*,
+// CHECK: [[VAR_ADDR:%.+]] = alloca [[S_INT_TY]]*,
+// Skip temp vars for loop
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: [[VEC_PRIV:%.+]] = alloca [2 x i{{[0-9]+}}],
+// CHECK: [[S_ARR_PRIV:%.+]] = alloca [2 x [[S_INT_TY]]],
+// CHECK: [[AGG_TMP1:%.+]] = alloca [[ST_TY]],
+// CHECK: [[VAR_PRIV:%.+]] = alloca [[S_INT_TY]],
+// CHECK: [[AGG_TMP2:%.+]] = alloca [[ST_TY]],
+// CHECK: [[TMP:%.+]] = alloca [[S_INT_TY]]*,
+
+// param copy
+// CHECK: store [2 x i{{[0-9]+}}]* {{.+}}, [2 x i{{[0-9]+}}]** [[VEC_ADDR]],
+// CHECK: store i{{[0-9]+}} {{.+}}, i{{[0-9]+}}* [[T_VAR_ADDR]],
+// CHECK: store [2 x [[S_INT_TY]]]* {{.+}}, [2 x [[S_INT_TY]]]** [[S_ARR_ADDR]],
+// CHECK: store [[S_INT_TY]]* {{.+}}, [[S_INT_TY]]** [[VAR_ADDR]],
+
+// T_VAR and preparation variables
+// CHECK: [[VEC_ADDR_VAL:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]],
+// CHECK-64: [[CONV_TVAR:%.+]] = bitcast i64* [[T_VAR_ADDR]] to i32*
+// CHECK: [[S_ARR_ADDR_REF:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[S_ARR_ADDR]],
+
+// firstprivate vec(vec): copy from *_addr into priv1 and then from priv1 into priv2
+// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
+// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8*
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST_PRIV]], i8* align {{[0-9]+}} [[VEC_SRC]], {{.+}})
+
+// firstprivate(s_arr)
+// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_PRIV]],
+// CHECK-DAG: [[S_ARR_ADDR_BGN:%.+]] = bitcast [2 x [[S_INT_TY]]]* [[S_ARR_ADDR_REF]] to
+// CHECK-DAG: [[S_ARR_FIN:%.+]] = icmp{{.+}} [[S_ARR_PRIV_BGN]],
+// CHECK-DAG: [[S_ARR_SRC_COPY:%.+]] = phi{{.+}} [ [[S_ARR_ADDR_BGN]], {{.+}} ], [ [[S_ARR_SRC:%.+]], {{.+}} ]
+// CHECK-DAG: [[S_ARR_DST_COPY:%.+]] = phi{{.+}} [ [[S_ARR_PRIV_BGN]], {{.+}} ], [ [[S_ARR_DST:%.+]], {{.+}} ]
+// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP1]])
+// CHECK-DAG: call void @{{.+}}({{.+}} [[S_ARR_DST_COPY]], {{.+}} [[S_ARR_SRC_COPY]], {{.+}} [[AGG_TMP1]])
+// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP1]])
+// CHECK-DAG: [[S_ARR_DST]] = getelementptr {{.+}} [[S_ARR_DST_COPY]],
+// CHECK-DAG: [[S_ARR_SRC]] = getelementptr {{.+}} [[S_ARR_SRC_COPY]],
+
+// firstprivate(var)
+// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load{{.+}} [[VAR_ADDR]],
+// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]])
+// CHECK-DAG: call void @{{.+}}({{.+}} [[VAR_PRIV]], {{.+}} [[VAR_ADDR_REF]], {{.+}} [[AGG_TMP2]])
+// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]])
+// CHECK-DAG: store [[S_INT_TY]]* [[VAR_PRIV]], [[S_INT_TY]]** [[TMP]],
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK-32-DAG: {{.+}} = {{.+}} [[T_VAR_ADDR]]
+// CHECK-64-DAG: {{.+}} = {{.+}} [[CONV_TVAR]]
+// CHECK-DAG: {{.+}} = {{.+}} [[VEC_PRIV]]
+// CHECK-DAG: {{.+}} = {{.+}} [[TMP]]
+// CHECK-DAG: {{.+}} = {{.+}} [[S_ARR_PRIV]]
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: ret void
+
+#endif
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_firstprivate_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_firstprivate_messages.cpp
index 0d8355047830..a278e9f89acd 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_firstprivate_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_firstprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_if_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_if_codegen.cpp
new file mode 100644
index 000000000000..8cd90a610b5c
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_if_codegen.cpp
@@ -0,0 +1,181 @@
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple %itanium_abi_triple -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple %itanium_abi_triple -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple %itanium_abi_triple -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple %itanium_abi_triple -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// SIMD-ONLY-NOT: {{__kmpc|__tgt}}
+
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+void fn1();
+void fn2();
+void fn3();
+void fn4();
+void fn5();
+void fn6();
+
+int Arg;
+
+// CHECK-LABEL: define {{.*}}void @{{.+}}gtid_test
+void gtid_test() {
+// CHECK: call i{{[0-9]+}} @__tgt_target_teams(
+// CHECK: call void [[OFFLOADING_FUN_0:@.+]](
+// CHECK: call i{{[0-9]+}} @__tgt_target_teams(
+// CHECK: call void [[OFFLOADING_FUN_1:@.+]](
+#pragma omp target teams distribute parallel for
+ for(int i = 0 ; i < 100; i++) {}
+ // CHECK: define internal void [[OFFLOADING_FUN_0]](
+ // CHECK: call {{.*}}void {{.+}} @__kmpc_fork_teams({{.+}}, i32 0, {{.+}}* [[OMP_TEAMS_OUTLINED_0:@.+]] to {{.+}})
+ // CHECK: define{{.+}} void [[OMP_TEAMS_OUTLINED_0]](
+ // CHECK: call void @__kmpc_for_static_init_4(
+ // CHECK: call void {{.+}} @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{.+}} 2, {{.+}}* [[OMP_OUTLINED_0:@.+]] to void
+ // CHECK: call void @__kmpc_for_static_fini(
+
+ // CHECK: define{{.+}} void [[OMP_OUTLINED_0]](
+ // CHECK: call void @__kmpc_for_static_init_4(
+ // CHECK: call void @__kmpc_for_static_fini(
+ // CHECK: ret
+#pragma omp target teams distribute parallel for if (parallel: false)
+ for(int i = 0 ; i < 100; i++) {
+ // CHECK: define internal void [[OFFLOADING_FUN_1]](
+ // CHECK: call {{.*}}void {{.+}} @__kmpc_fork_teams({{.+}}, i32 0, {{.+}}* [[OMP_TEAMS_OUTLINED_1:@.+]] to {{.+}})
+ // CHECK: define{{.+}} void [[OMP_TEAMS_OUTLINED_1]](
+ // CHECK: call void @__kmpc_for_static_init_4(
+ // CHECK: call void @__kmpc_serialized_parallel(
+ // CHECK: call void [[OMP_OUTLINED_1:@.+]](
+ // CHECK: call void @__kmpc_end_serialized_parallel(
+ // CHECK: call void @__kmpc_for_static_fini(
+ // CHECK: define{{.+}} void [[OMP_OUTLINED_1]](
+ // CHECK: call void @__kmpc_for_static_init_4(
+ // CHECK: call void @{{.+}}gtid_test
+ // CHECK: call void @__kmpc_for_static_fini(
+ // CHECK: ret
+ gtid_test();
+ }
+}
+
+
+template <typename T>
+int tmain(T Arg) {
+#pragma omp target teams distribute parallel for if (true)
+ for(int i = 0 ; i < 100; i++) {
+ fn1();
+ }
+#pragma omp target teams distribute parallel for if (false)
+ for(int i = 0 ; i < 100; i++) {
+ fn2();
+ }
+#pragma omp target teams distribute parallel for if (parallel: Arg)
+ for(int i = 0 ; i < 100; i++) {
+ fn3();
+ }
+ return 0;
+}
+
+// CHECK-LABEL: define {{.*}}i{{[0-9]+}} @main()
+int main() {
+// CHECK: call i{{[0-9]+}} @__tgt_target_teams(
+// CHECK: call void [[OFFLOADING_FUN_0:@.+]](
+// CHECK: call void [[OFFLOADING_FUN_1:@.+]](
+// CHECK: call i{{[0-9]+}} @__tgt_target_teams(
+// CHECK: call void [[OFFLOADING_FUN_2:@.+]](
+// CHECK: = call {{.*}}i{{.+}} @{{.+}}tmain
+#pragma omp target teams distribute parallel for if (true)
+ for(int i = 0 ; i < 100; i++) {
+ // CHECK: define internal void [[OFFLOADING_FUN_0]](
+ // CHECK: call {{.*}}void {{.+}} @__kmpc_fork_teams({{.+}}, i32 0, {{.+}}* [[OMP_TEAMS_OUTLINED_0:@.+]] to {{.+}})
+ // CHECK: define{{.+}} void [[OMP_TEAMS_OUTLINED_0]](
+
+ // CHECK: call void @__kmpc_for_static_init_4(
+ // CHECK: call void {{.+}} @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{.+}} 2, {{.+}}* [[OMP_OUTLINED_2:@.+]] to void
+ // CHECK: call void @__kmpc_for_static_fini(
+ // CHECK: define{{.+}} void [[OMP_OUTLINED_2]](
+ // CHECK: call void @__kmpc_for_static_init_4(
+ // CHECK: call {{.*}}void @{{.+}}fn4
+ // CHECK: call void @__kmpc_for_static_fini(
+
+ fn4();
+ }
+
+#pragma omp target teams distribute parallel for if (false)
+ for(int i = 0 ; i < 100; i++) {
+ // CHECK: define internal void [[OFFLOADING_FUN_1]](
+ // CHECK: call {{.*}}void {{.+}} @__kmpc_fork_teams({{.+}}, i32 0, {{.+}}* [[OMP_TEAMS_OUTLINED_1:@.+]] to {{.+}})
+ // CHECK: define{{.+}} void [[OMP_TEAMS_OUTLINED_1]](
+
+ // CHECK: call void @__kmpc_for_static_init_4(
+ // CHECK: call void @__kmpc_serialized_parallel(
+ // CHECK: call void [[OMP_OUTLINED_3:@.+]](
+ // CHECK: call void @__kmpc_end_serialized_parallel(
+ // CHECK: call void @__kmpc_for_static_fini(
+
+ // CHECK: define{{.+}} void [[OMP_OUTLINED_3]](
+ // CHECK: call void @__kmpc_for_static_init_4(
+ // CHECK: call {{.*}}void @{{.+}}fn5
+ // CHECK: call void @__kmpc_for_static_fini(
+ fn5();
+ }
+
+#pragma omp target teams distribute parallel for if (Arg)
+ for(int i = 0 ; i < 100; i++) {
+ // CHECK: define internal void [[OFFLOADING_FUN_2]](
+ // CHECK: call {{.*}}void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}}* [[OMP_TEAMS_OUTLINED_2:@.+]] to {{.+}})
+ // CHECK: define{{.+}} void [[OMP_TEAMS_OUTLINED_2]](
+
+ // CHECK: call void @__kmpc_for_static_init_4(
+ // CHECK: call void {{.+}} @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{.+}} 2, {{.+}}* [[OMP_OUTLINED_4:@.+]] to void
+ // CHECK: call void @__kmpc_serialized_parallel(
+ // CHECK: call void [[OMP_OUTLINED_4:@.+]](
+ // CHECK: call void @__kmpc_end_serialized_parallel(
+ // CHECK: call void @__kmpc_for_static_fini(
+
+ // CHECK: define{{.+}} void [[OMP_OUTLINED_4]](
+ // CHECK: call void @__kmpc_for_static_init_4(
+ // CHECK: call {{.*}}void @{{.+}}fn6
+ // CHECK: call void @__kmpc_for_static_fini(
+ fn6();
+ }
+
+ return tmain(Arg);
+}
+
+// CHECK-LABEL: define {{.+}} @{{.+}}tmain
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call {{.*}}void {{.+}} @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{.+}} 2, void {{.+}}* [[T_OUTLINE_FUN_1:@.+]] to void
+// CHECK: call void @__kmpc_for_static_fini(
+
+// CHECK: define internal {{.*}}void [[T_OUTLINE_FUN_1]]
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call {{.*}}void @{{.+}}fn1
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: ret void
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call {{.*}}void @__kmpc_serialized_parallel(
+// CHECK: call void [[T_OUTLINE_FUN_2:@.+]](
+// CHECK: call {{.*}}void @__kmpc_end_serialized_parallel(
+// CHECK: call void @__kmpc_for_static_fini(
+
+// CHECK: define internal {{.*}}void [[T_OUTLINE_FUN_2]]
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call {{.*}}void @{{.+}}fn2
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: ret void
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call {{.*}}void {{.+}} @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{.+}} 2, void {{.+}}* [[T_OUTLINE_FUN_3:@.+]] to void
+// CHECK: call {{.*}}void @__kmpc_serialized_parallel(
+// call void [[T_OUTLINE_FUN_3:@.+]](
+// CHECK: call {{.*}}void @__kmpc_end_serialized_parallel(
+
+// CHECK: define internal {{.*}}void [[T_OUTLINE_FUN_3]]
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call {{.*}}void @{{.+}}fn3
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: ret void
+#endif
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_if_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_if_messages.cpp
index 82d39ac4ca8c..6f990f7bd28e 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_if_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_if_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_is_device_ptr_ast_print.cpp b/test/OpenMP/target_teams_distribute_parallel_for_is_device_ptr_ast_print.cpp
index c566319df42d..b3944bc19530 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_is_device_ptr_ast_print.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_is_device_ptr_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -56,7 +60,7 @@ struct SA {
// CHECK-NEXT: int aa[10];
// CHECK-NEXT: arr &raa = this->aa;
// CHECK-NEXT: func(
-// CHECK-NEXT: #pragma omp target teams distribute parallel for is_device_ptr(this->k)
+// CHECK-NEXT: #pragma omp target teams distribute parallel for is_device_ptr(this->k){{$}}
// CHECK-NEXT: for (int i = 0; i < 100; i++)
// CHECK-NEXT: ;
// CHECK-NEXT: #pragma omp target teams distribute parallel for is_device_ptr(this->z)
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_is_device_ptr_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_is_device_ptr_messages.cpp
index eaa3190a47f6..e19e46c57b71 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_is_device_ptr_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_is_device_ptr_messages.cpp
@@ -1,4 +1,6 @@
// RUN: %clang_cc1 -std=c++11 -verify -fopenmp %s
+
+// RUN: %clang_cc1 -std=c++11 -verify -fopenmp-simd %s
struct ST {
int *a;
};
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_codegen.cpp
new file mode 100644
index 000000000000..acb1c0b636ec
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_codegen.cpp
@@ -0,0 +1,454 @@
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// SIMD-ONLY-NOT: {{__kmpc|__tgt}}
+
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+template <class T>
+struct S {
+ T f;
+ S(T a) : f(a) {}
+ S() : f() {}
+ operator T() { return T(); }
+ ~S() {}
+};
+
+// CHECK: [[S_FLOAT_TY:%.+]] = type { float }
+// CHECK: [[S_INT_TY:%.+]] = type { i{{[0-9]+}} }
+template <typename T>
+T tmain() {
+ S<T> test;
+ T t_var = T();
+ T vec[] = {1, 2};
+ S<T> s_arr[] = {1, 2};
+ S<T> &var = test;
+ #pragma omp target teams distribute parallel for lastprivate(t_var, vec, s_arr, s_arr, var, var)
+ for (int i = 0; i < 2; ++i) {
+ vec[i] = t_var;
+ s_arr[i] = var;
+ }
+ return T();
+}
+
+int main() {
+ static int svar;
+ volatile double g;
+ volatile double &g1 = g;
+
+ #ifdef LAMBDA
+ // LAMBDA-LABEL: @main
+ // LAMBDA: call{{.*}} void [[OUTER_LAMBDA:@.+]](
+ [&]() {
+ static float sfvar;
+ // LAMBDA: define{{.*}} internal{{.*}} void [[OUTER_LAMBDA]](
+ // LAMBDA: call i{{[0-9]+}} @__tgt_target_teams(
+ // LAMBDA: call void [[OFFLOADING_FUN:@.+]](
+
+ // LAMBDA: define{{.+}} void [[OFFLOADING_FUN]](
+ // LAMBDA: call {{.*}}void {{.+}} @__kmpc_fork_teams({{.+}}, i32 4, {{.+}}* [[OMP_OUTLINED:@.+]] to {{.+}})
+ #pragma omp target teams distribute parallel for lastprivate(g, g1, svar, sfvar)
+ for (int i = 0; i < 2; ++i) {
+ // LAMBDA: define{{.*}} internal{{.*}} void [[OMP_OUTLINED]](i32* {{.+}}, i32* {{.+}}, {{.+}} [[G1_IN:%.+]], {{.+}} [[SVAR_IN:%.+]], {{.+}} [[SFVAR_IN:%.+]], {{.+}} [[G_IN:%.+]])
+ // skip gbl and bound tid
+ // LAMBDA: alloca
+ // LAMBDA: alloca
+ // LAMBDA: [[G1_ADDR:%.+]] = alloca {{.+}},
+ // LAMBDA: [[SVAR_ADDR:%.+]] = alloca {{.+}},
+ // LAMBDA: [[SFVAR_ADDR:%.+]] = alloca {{.+}},
+ // LAMBDA: [[G_ADDR:%.+]] = alloca {{.+}},
+ // LAMBDA-64: [[G1_REF:%.+]] = alloca double*,
+ // loop variables
+ // LAMBDA: {{.+}} = alloca i{{[0-9]+}},
+ // LAMBDA: {{.+}} = alloca i{{[0-9]+}},
+ // LAMBDA: {{.+}} = alloca i{{[0-9]+}},
+ // LAMBDA: {{.+}} = alloca i{{[0-9]+}},
+ // LAMBDA: {{.+}} = alloca i{{[0-9]+}},
+ // LAMBDA: [[OMP_IS_LAST:%.+]] = alloca i{{[0-9]+}},
+
+ // LAMBDA-DAG: store {{.+}} [[G_IN]], {{.+}} [[G_ADDR]],
+ // LAMBDA-DAG: store {{.+}} [[G1_IN]], {{.+}} [[G1_ADDR]],
+ // LAMBDA-DAG: store {{.+}} [[SVAR_IN]], {{.+}} [[SVAR_ADDR]],
+ // LAMBDA-DAG: store {{.+}} [[SFVAR_IN]], {{.+}} [[SFVAR_ADDR]],
+
+ // LAMBDA-64-DAG: [[G_TGT:%.+]] = bitcast {{.+}} [[G_ADDR]] to
+ // LAMBDA-32-DAG: [[G_TGT:%.+]] = load {{.+}}, {{.+}} [[G_ADDR]],
+ // LAMBDA-64-DAG: [[G1_TGT:%.+]] = load {{.+}}, {{.+}} [[G1_REF]],
+ // LAMBDA-32-DAG: [[G1_TGT:%.+]] = load {{.+}}, {{.+}} [[G1_ADDR]],
+ // LAMBDA-64-DAG: [[SVAR_TGT:%.+]] = bitcast {{.+}} [[SVAR_ADDR]] to
+ // LAMBDA-DAG: [[SFVAR_TGT:%.+]] = bitcast {{.+}} [[SFVAR_ADDR]] to
+
+ g1 = 1;
+ svar = 3;
+ sfvar = 4.0;
+ // LAMBDA: call {{.*}}void @__kmpc_for_static_init_4(
+ // LAMBDA: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[LPAR_OUTL:.+]] to
+ // LAMBDA: call {{.*}}void @__kmpc_for_static_fini(
+
+ // LAMBDA: [[OMP_IS_LAST_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[OMP_IS_LAST]],
+ // LAMBDA: [[IS_LAST_IT:%.+]] = icmp ne i{{[0-9]+}} [[OMP_IS_LAST_VAL]], 0
+ // LAMBDA: br i1 [[IS_LAST_IT]], label %[[OMP_LASTPRIV_BLOCK:.+]], label %[[OMP_LASTPRIV_DONE:.+]]
+
+ // LAMBDA: [[OMP_LASTPRIV_BLOCK]]:
+ // LAMBDA-DAG: store {{.+}}, {{.+}} [[G_TGT]],
+ // LAMBDA-DAG: store {{.+}}, {{.+}} [[G1_TGT]],
+ // LAMBDA-64-DAG: store {{.+}}, {{.+}} [[SVAR_TGT]],
+ // LAMBDA-32-DAG: store {{.+}}, {{.+}} [[SVAR_ADDR]],
+ // LAMBDA-DAG: store {{.+}}, {{.+}} [[SFVAR_TGT]],
+ // LAMBDA: br label %[[OMP_LASTPRIV_DONE]]
+ // LAMBDA: [[OMP_LASTPRIV_DONE]]:
+ // LAMBDA: ret
+
+ // LAMBDA: define{{.*}} internal{{.*}} void @[[LPAR_OUTL]](i32* noalias %{{.+}}, i32* noalias %{{.+}}, {{.+}}, {{.+}}, {{.+}} [[G1_IN:%.+]], {{.+}} [[SVAR_IN:%.+]], {{.+}} [[SFVAR_IN:%.+]], {{.+}} [[G_IN:%.+]])
+ // skip tid and prev variables
+ // LAMBDA: alloca
+ // LAMBDA: alloca
+ // LAMBDA: alloca
+ // LAMBDA: alloca
+ // LAMBDA: [[G1_ADDR:%.+]] = alloca {{.+}},
+ // LAMBDA: [[SVAR_ADDR:%.+]] = alloca {{.+}},
+ // LAMBDA: [[SFVAR_ADDR:%.+]] = alloca {{.+}},
+ // LAMBDA: [[G_ADDR:%.+]] = alloca {{.+}},
+ // LAMBDA-64: [[G1_REF:%.+]] = alloca double*,
+ // loop variables
+ // LAMBDA: {{.+}} = alloca i{{[0-9]+}},
+ // LAMBDA: {{.+}} = alloca i{{[0-9]+}},
+ // LAMBDA: {{.+}} = alloca i{{[0-9]+}},
+ // LAMBDA: {{.+}} = alloca i{{[0-9]+}},
+ // LAMBDA: {{.+}} = alloca i{{[0-9]+}},
+ // LAMBDA: [[OMP_IS_LAST:%.+]] = alloca i{{[0-9]+}},
+
+ // LAMBDA-DAG: store {{.+}} [[G_IN]], {{.+}} [[G_ADDR]],
+ // LAMBDA-DAG: store {{.+}} [[G1_IN]], {{.+}} [[G1_ADDR]],
+ // LAMBDA-DAG: store {{.+}} [[SVAR_IN]], {{.+}} [[SVAR_ADDR]],
+ // LAMBDA-DAG: store {{.+}} [[SFVAR_IN]], {{.+}} [[SFVAR_ADDR]],
+
+ // LAMBDA-64-DAG: [[G_TGT:%.+]] = bitcast {{.+}} [[G_ADDR]] to
+ // LAMBDA-32-DAG: [[G_TGT:%.+]] = load {{.+}}, {{.+}} [[G_ADDR]],
+ // LAMBDA-64-DAG: [[G1_TGT:%.+]] = load {{.+}}, {{.+}} [[G1_REF]],
+ // LAMBDA-32-DAG: [[G1_TGT:%.+]] = load {{.+}}, {{.+}} [[G1_ADDR]],
+ // LAMBDA-64-DAG: [[SVAR_TGT:%.+]] = bitcast {{.+}} [[SVAR_ADDR]] to
+ // LAMBDA-DAG: [[SFVAR_TGT:%.+]] = bitcast {{.+}} [[SFVAR_ADDR]] to
+
+
+ // LAMBDA: call {{.*}}void @__kmpc_for_static_init_4(
+ // LAMBDA: call{{.*}} void [[INNER_LAMBDA:@.+]](
+ // LAMBDA: call {{.*}}void @__kmpc_for_static_fini(
+
+ // LAMBDA: [[OMP_IS_LAST_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[OMP_IS_LAST]],
+ // LAMBDA: [[IS_LAST_IT:%.+]] = icmp ne i{{[0-9]+}} [[OMP_IS_LAST_VAL]], 0
+ // LAMBDA: br i1 [[IS_LAST_IT]], label %[[OMP_LASTPRIV_BLOCK:.+]], label %[[OMP_LASTPRIV_DONE:.+]]
+
+ // LAMBDA: [[OMP_LASTPRIV_BLOCK]]:
+ // LAMBDA-DAG: store {{.+}}, {{.+}} [[G_TGT]],
+ // LAMBDA-DAG: store {{.+}}, {{.+}} [[G1_TGT]],
+ // LAMBDA-64-DAG: store {{.+}}, {{.+}} [[SVAR_TGT]],
+ // LAMBDA-32-DAG: store {{.+}}, {{.+}} [[SVAR_ADDR]],
+ // LAMBDA-DAG: store {{.+}}, {{.+}} [[SFVAR_TGT]],
+ // LAMBDA: br label %[[OMP_LASTPRIV_DONE]]
+ // LAMBDA: [[OMP_LASTPRIV_DONE]]:
+ // LAMBDA: ret
+
+ [&]() {
+ // LAMBDA: define {{.+}} void [[INNER_LAMBDA]](%{{.+}}* [[ARG_PTR:%.+]])
+ // LAMBDA: store %{{.+}}* [[ARG_PTR]], %{{.+}}** [[ARG_PTR_REF:%.+]],
+ g = 2;
+ g1 = 2;
+ svar = 4;
+ sfvar = 8.0;
+ // LAMBDA: [[ARG_PTR:%.+]] = load %{{.+}}*, %{{.+}}** [[ARG_PTR_REF]]
+ // LAMBDA: [[G_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
+ // LAMBDA: [[G_REF:%.+]] = load double*, double** [[G_PTR_REF]]
+ // LAMBDA: store double 2.0{{.+}}, double* [[G_REF]]
+
+ // LAMBDA: [[TMP_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 1
+ // LAMBDA: [[G1_REF:%.+]] = load double*, double** [[TMP_PTR_REF]]
+ // LAMBDA: store double 2.0{{.+}}, double* [[G1_REF]],
+ // LAMBDA: [[SVAR_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 2
+ // LAMBDA: [[SVAR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SVAR_PTR_REF]]
+ // LAMBDA: store i{{[0-9]+}} 4, i{{[0-9]+}}* [[SVAR_REF]]
+ // LAMBDA: [[SFVAR_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 3
+ // LAMBDA: [[SFVAR_REF:%.+]] = load float*, float** [[SFVAR_PTR_REF]]
+ // LAMBDA: store float 8.0{{.+}}, float* [[SFVAR_REF]]
+ }();
+ }
+ }();
+ return 0;
+ #else
+ S<float> test;
+ int t_var = 0;
+ int vec[] = {1, 2};
+ S<float> s_arr[] = {1, 2};
+ S<float> &var = test;
+
+ #pragma omp target teams distribute parallel for lastprivate(t_var, vec, s_arr, s_arr, var, var, svar)
+ for (int i = 0; i < 2; ++i) {
+ vec[i] = t_var;
+ s_arr[i] = var;
+ }
+ int i;
+
+ return tmain<int>();
+ #endif
+}
+
+// CHECK: define{{.*}} i{{[0-9]+}} @main()
+// CHECK: [[TEST:%.+]] = alloca [[S_FLOAT_TY]],
+// CHECK: call {{.*}} [[S_FLOAT_TY_DEF_CONSTR:@.+]]([[S_FLOAT_TY]]* [[TEST]])
+// CHECK: call i{{[0-9]+}} @__tgt_target_teams(
+// CHECK: call void [[OFFLOAD_FUN:@.+]](
+// CHECK: ret
+
+// CHECK: define{{.+}} [[OFFLOAD_FUN]](
+// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_teams(
+// CHECK: ret
+//
+// CHECK: define internal void [[OMP_OUTLINED:@.+]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [2 x i{{[0-9]+}}]*{{.+}} [[VEC_IN:%.+]], i{{[0-9]+}}{{.+}} [[T_VAR_IN:%.+]], [2 x [[S_FLOAT_TY]]]*{{.+}} [[S_ARR_IN:%.+]], [[S_FLOAT_TY]]*{{.+}} [[VAR_IN:%.+]], i{{[0-9]+}}{{.*}} [[S_VAR_IN:%.+]])
+// CHECK: {{.+}} = alloca i{{[0-9]+}}*,
+// CHECK: {{.+}} = alloca i{{[0-9]+}}*,
+// CHECK: [[VEC_ADDR:%.+]] = alloca [2 x i{{[0-9]+}}]*,
+// CHECK: [[T_VAR_ADDR:%.+]] = alloca i{{[0-9]+}},
+// CHECK: [[S_ARR_ADDR:%.+]] = alloca [2 x [[S_FLOAT_TY]]]*,
+// CHECK: [[VAR_ADDR:%.+]] = alloca [[S_FLOAT_TY]]*,
+// CHECK: [[SVAR_ADDR:%.+]] = alloca i{{[0-9]+}},
+// skip loop variables
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: [[OMP_IS_LAST:%.+]] = alloca i{{[0-9]+}},
+
+// copy from parameters to local address variables
+// CHECK: store {{.+}} [[VEC_IN]], {{.+}} [[VEC_ADDR]],
+// CHECK: store {{.+}} [[T_VAR_IN]], {{.+}} [[T_VAR_ADDR]],
+// CHECK: store {{.+}} [[S_ARR_IN]], {{.+}} [[S_ARR_ADDR]],
+// CHECK: store {{.+}} [[VAR_IN]], {{.+}} [[VAR_ADDR]],
+// CHECK: store {{.+}} [[S_VAR_IN]], {{.+}} [[SVAR_ADDR]],
+
+// prepare lastprivate targets
+// CHECK-64-DAG: [[TVAR_TGT:%.+]] = bitcast {{.+}} [[T_VAR_ADDR]] to
+// CHECK-DAG: [[VEC_TGT:%.+]] = load {{.+}}, {{.+}} [[VEC_ADDR]],
+// CHECK-DAG: [[S_ARR_TGT:%.+]] = load {{.+}}, {{.+}} [[S_ARR_ADDR]],
+// CHECK-DAG: [[VAR_TGT:%.+]] = load {{.+}}, {{.+}} [[VAR_ADDR]],
+// CHECK-64-DAG: [[SVAR_TGT:%.+]] = bitcast {{.+}} [[SVAR_ADDR]] to
+
+// the distribute loop
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL:.+]] to
+// CHECK: call void @__kmpc_for_static_fini(
+
+// lastprivates
+// CHECK: [[OMP_IS_LAST_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[OMP_IS_LAST]],
+// CHECK: [[IS_LAST_IT:%.+]] = icmp ne i{{[0-9]+}} [[OMP_IS_LAST_VAL]], 0
+// CHECK: br i1 [[IS_LAST_IT]], label %[[OMP_LASTPRIV_BLOCK:.+]], label %[[OMP_LASTPRIV_DONE:.+]]
+
+// CHECK: [[OMP_LASTPRIV_BLOCK]]:
+// CHECK-64-DAG: store {{.+}}, {{.+}} [[TVAR_TGT]],
+// CHECK-32-DAG: store {{.+}}, {{.+}} [[T_VAR_ADDR]],
+// CHECK-DAG: [[VEC_TGT_REF:%.+]] = bitcast {{.+}} [[VEC_TGT]] to
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_TGT_REF]],
+// CHECK-DAG: [[S_ARR_BEGIN:%.+]] = getelementptr {{.+}} [[S_ARR_TGT]],
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}(
+// CHECK-DAG: [[VAR_TGT_BCAST:%.+]] = bitcast {{.+}} [[VAR_TGT]] to
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_TGT_BCAST]],
+// CHECK-64-DAG: store {{.+}}, {{.+}} [[SVAR_TGT]],
+// CHECK-32-DAG: store {{.+}}, {{.+}} [[SVAR_ADDR]],
+// CHECK: ret void
+
+// CHECK: define internal void [[OMP_OUTLINED:@.+]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, {{.+}}, {{.+}}, [2 x i{{[0-9]+}}]*{{.+}} [[VEC_IN:%.+]], i{{[0-9]+}}{{.+}} [[T_VAR_IN:%.+]], [2 x [[S_FLOAT_TY]]]*{{.+}} [[S_ARR_IN:%.+]], [[S_FLOAT_TY]]*{{.+}} [[VAR_IN:%.+]], i{{[0-9]+}}{{.*}} [[S_VAR_IN:%.+]])
+
+// gbl and bound tid vars, prev lb and ub vars
+// CHECK: {{.+}} = alloca i{{[0-9]+}}*,
+// CHECK: {{.+}} = alloca i{{[0-9]+}}*,
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+
+// CHECK: [[VEC_ADDR:%.+]] = alloca [2 x i{{[0-9]+}}]*,
+// CHECK: [[T_VAR_ADDR:%.+]] = alloca i{{[0-9]+}},
+// CHECK: [[S_ARR_ADDR:%.+]] = alloca [2 x [[S_FLOAT_TY]]]*,
+// CHECK: [[VAR_ADDR:%.+]] = alloca [[S_FLOAT_TY]]*,
+// CHECK: [[SVAR_ADDR:%.+]] = alloca i{{[0-9]+}},
+// skip loop variables
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: [[OMP_IS_LAST:%.+]] = alloca i{{[0-9]+}},
+
+// copy from parameters to local address variables
+// CHECK: store {{.+}} [[VEC_IN]], {{.+}} [[VEC_ADDR]],
+// CHECK: store {{.+}} [[T_VAR_IN]], {{.+}} [[T_VAR_ADDR]],
+// CHECK: store {{.+}} [[S_ARR_IN]], {{.+}} [[S_ARR_ADDR]],
+// CHECK: store {{.+}} [[VAR_IN]], {{.+}} [[VAR_ADDR]],
+// CHECK: store {{.+}} [[S_VAR_IN]], {{.+}} [[SVAR_ADDR]],
+
+// prepare lastprivate targets
+// CHECK-64-DAG: [[TVAR_TGT:%.+]] = bitcast {{.+}} [[T_VAR_ADDR]] to
+// CHECK-DAG: [[VEC_TGT:%.+]] = load {{.+}}, {{.+}} [[VEC_ADDR]],
+// CHECK-DAG: [[S_ARR_TGT:%.+]] = load {{.+}}, {{.+}} [[S_ARR_ADDR]],
+// CHECK-DAG: [[VAR_TGT:%.+]] = load {{.+}}, {{.+}} [[VAR_ADDR]],
+// CHECK-64-DAG: [[SVAR_TGT:%.+]] = bitcast {{.+}} [[SVAR_ADDR]] to
+
+// the distribute loop
+// CHECK: call void @__kmpc_for_static_init_4(
+// skip body: code generation routine is same as distribute parallel for lastprivate
+// CHECK: call void @__kmpc_for_static_fini(
+
+// lastprivates
+// CHECK: [[OMP_IS_LAST_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[OMP_IS_LAST]],
+// CHECK: [[IS_LAST_IT:%.+]] = icmp ne i{{[0-9]+}} [[OMP_IS_LAST_VAL]], 0
+// CHECK: br i1 [[IS_LAST_IT]], label %[[OMP_LASTPRIV_BLOCK:.+]], label %[[OMP_LASTPRIV_DONE:.+]]
+
+// CHECK: [[OMP_LASTPRIV_BLOCK]]:
+// CHECK-64-DAG: store {{.+}}, {{.+}} [[TVAR_TGT]],
+// CHECK-32-DAG: store {{.+}}, {{.+}} [[T_VAR_ADDR]],
+// CHECK-DAG: [[VEC_TGT_REF:%.+]] = bitcast {{.+}} [[VEC_TGT]] to
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_TGT_REF]],
+// CHECK-DAG: [[S_ARR_BEGIN:%.+]] = getelementptr {{.+}} [[S_ARR_TGT]],
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}(
+// CHECK-DAG: [[VAR_TGT_BCAST:%.+]] = bitcast {{.+}} [[VAR_TGT]] to
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_TGT_BCAST]],
+// CHECK-64-DAG: store {{.+}}, {{.+}} [[SVAR_TGT]],
+// CHECK-32-DAG: store {{.+}}, {{.+}} [[SVAR_ADDR]],
+// CHECK: ret void
+
+// template tmain
+// CHECK: define{{.*}} i{{[0-9]+}} [[TMAIN_INT:@.+]]()
+// CHECK: [[TEST:%.+]] = alloca [[S_INT_TY]],
+// CHECK: call {{.*}} [[S_INT_TY_DEF_CONSTR:@.+]]([[S_INT_TY]]* [[TEST]])
+// CHECK: call i{{[0-9]+}} @__tgt_target_teams(
+// CHECK: call void [[OFFLOAD_FUN_1:@.+]](
+// CHECK: ret
+
+// CHECK: define internal void [[OFFLOAD_FUN_1]](
+// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_teams(%{{.+}}* @{{.+}}, i{{[0-9]+}} 4,
+// CHECK: ret
+
+// CHECK: define internal void [[OMP_OUTLINED_1:@.+]](i{{[0-9]+}}* noalias [[GTID_ADDR1:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [2 x i{{[0-9]+}}]*{{.+}} [[VEC_IN1:%.+]], i{{[0-9]+}}{{.+}} [[T_VAR_IN1:%.+]], [2 x [[S_INT_TY]]]*{{.+}} [[S_ARR_IN1:%.+]], [[S_INT_TY]]*{{.+}} [[VAR_IN1:%.+]])
+// skip alloca of global_tid and bound_tid
+// CHECK: {{.+}} = alloca i{{[0-9]+}}*,
+// CHECK: {{.+}} = alloca i{{[0-9]+}}*,
+// CHECK: [[VEC_ADDR1:%.+]] = alloca [2 x i{{[0-9]+}}]*,
+// CHECK: [[T_VAR_ADDR1:%.+]] = alloca i{{[0-9]+}},
+// CHECK: [[S_ARR_ADDR1:%.+]] = alloca [2 x [[S_INT_TY]]]*,
+// CHECK: [[VAR_ADDR1:%.+]] = alloca [[S_INT_TY]]*,
+// skip loop variables
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: [[OMP_IS_LAST1:%.+]] = alloca i{{[0-9]+}},
+
+// copy from parameters to local address variables
+// CHECK: store {{.+}} [[VEC_IN1]], {{.+}} [[VEC_ADDR1]],
+// CHECK: store {{.+}} [[T_VAR_IN1]], {{.+}} [[T_VAR_ADDR1]],
+// CHECK: store {{.+}} [[S_ARR_IN1]], {{.+}} [[S_ARR_ADDR1]],
+// CHECK: store {{.+}} [[VAR_IN1]], {{.+}} [[VAR_ADDR1]],
+
+// prepare lastprivate targets
+// CHECK-64-DAG: [[T_VAR_TGT:%.+]] = bitcast {{.+}} [[T_VAR_ADDR1]] to
+// CHECK-DAG: [[VEC_TGT:%.+]] = load {{.+}}, {{.+}} [[VEC_ADDR1]],
+// CHECK-DAG: [[S_ARR_TGT:%.+]] = load {{.+}}, {{.+}} [[S_ARR_ADDR1]],
+// CHECK-DAG: [[VAR_TGT:%.+]] = load {{.+}}, {{.+}} [[VAR_ADDR1]],
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[TPAR_OUTL:.+]] to
+// CHECK: call void @__kmpc_for_static_fini(
+
+// lastprivates
+// CHECK: [[OMP_IS_LAST_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[OMP_IS_LAST1]],
+// CHECK: [[IS_LAST_IT:%.+]] = icmp ne i{{[0-9]+}} [[OMP_IS_LAST_VAL]], 0
+// CHECK: br i1 [[IS_LAST_IT]], label %[[OMP_LASTPRIV_BLOCK:.+]], label %[[OMP_LASTPRIV_DONE:.+]]
+
+// CHECK: [[OMP_LASTPRIV_BLOCK]]:
+// CHECK-64-DAG: store {{.+}}, {{.+}} [[T_VAR_TGT]],
+// CHECK-32-DAG: store {{.+}}, {{.+}} [[T_VAR_ADDR1]],
+// CHECK-DAG: [[VEC_TGT_BCAST:%.+]] = bitcast {{.+}} [[VEC_TGT]] to
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_TGT_BCAST]],
+// CHECK-DAG: {{.+}} = getelementptr {{.+}} [[S_ARR_TGT]],
+// CHECK: call void @llvm.memcpy.{{.+}}(
+// CHECK-DAG: [[VAR_ADDR_BCAST:%.+]] = bitcast {{.+}} [[VAR_TGT]] to
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_BCAST]],
+// CHECK: ret void
+
+// CHECK: define internal void [[TPAR_OUTL:@.+]](i{{[0-9]+}}* noalias [[GTID_ADDR1:%.+]], i{{[0-9]+}}* noalias %{{.+}}, {{.+}}, {{.+}}, [2 x i{{[0-9]+}}]*{{.+}} [[VEC_IN1:%.+]], i{{[0-9]+}}{{.+}} [[T_VAR_IN1:%.+]], [2 x [[S_INT_TY]]]*{{.+}} [[S_ARR_IN1:%.+]], [[S_INT_TY]]*{{.+}} [[VAR_IN1:%.+]])
+// skip alloca of global_tid and bound_tid, and prev lb and ub vars
+// CHECK: {{.+}} = alloca i{{[0-9]+}}*,
+// CHECK: {{.+}} = alloca i{{[0-9]+}}*,
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+
+// CHECK: [[VEC_ADDR1:%.+]] = alloca [2 x i{{[0-9]+}}]*,
+// CHECK: [[T_VAR_ADDR1:%.+]] = alloca i{{[0-9]+}},
+// CHECK: [[S_ARR_ADDR1:%.+]] = alloca [2 x [[S_INT_TY]]]*,
+// CHECK: [[VAR_ADDR1:%.+]] = alloca [[S_INT_TY]]*,
+// skip loop variables
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: [[OMP_IS_LAST1:%.+]] = alloca i{{[0-9]+}},
+
+// copy from parameters to local address variables
+// CHECK: store {{.+}} [[VEC_IN1]], {{.+}} [[VEC_ADDR1]],
+// CHECK: store {{.+}} [[T_VAR_IN1]], {{.+}} [[T_VAR_ADDR1]],
+// CHECK: store {{.+}} [[S_ARR_IN1]], {{.+}} [[S_ARR_ADDR1]],
+// CHECK: store {{.+}} [[VAR_IN1]], {{.+}} [[VAR_ADDR1]],
+
+// prepare lastprivate targets
+// CHECK-64-DAG: [[T_VAR_TGT:%.+]] = bitcast {{.+}} [[T_VAR_ADDR1]] to
+// CHECK-DAG: [[VEC_TGT:%.+]] = load {{.+}}, {{.+}} [[VEC_ADDR1]],
+// CHECK-DAG: [[S_ARR_TGT:%.+]] = load {{.+}}, {{.+}} [[S_ARR_ADDR1]],
+// CHECK-DAG: [[VAR_TGT:%.+]] = load {{.+}}, {{.+}} [[VAR_ADDR1]],
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// skip body: code generation routine is same as distribute parallel for lastprivate
+// CHECK: call void @__kmpc_for_static_fini(
+
+// lastprivates
+// CHECK: [[OMP_IS_LAST_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[OMP_IS_LAST1]],
+// CHECK: [[IS_LAST_IT:%.+]] = icmp ne i{{[0-9]+}} [[OMP_IS_LAST_VAL]], 0
+// CHECK: br i1 [[IS_LAST_IT]], label %[[OMP_LASTPRIV_BLOCK:.+]], label %[[OMP_LASTPRIV_DONE:.+]]
+
+// CHECK: [[OMP_LASTPRIV_BLOCK]]:
+// CHECK-64-DAG: store {{.+}}, {{.+}} [[T_VAR_TGT]],
+// CHECK-32-DAG: store {{.+}}, {{.+}} [[T_VAR_ADDR1]],
+// CHECK-DAG: [[VEC_TGT_BCAST:%.+]] = bitcast {{.+}} [[VEC_TGT]] to
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_TGT_BCAST]],
+// CHECK-DAG: {{.+}} = getelementptr {{.+}} [[S_ARR_TGT]],
+// CHECK: call void @llvm.memcpy.{{.+}}(
+// CHECK-DAG: [[VAR_ADDR_BCAST:%.+]] = bitcast {{.+}} [[VAR_TGT]] to
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_BCAST]],
+// CHECK: ret void
+
+#endif
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_messages.cpp
index 84a6df28174d..b21b9118f913 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_loop_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_loop_messages.cpp
index 57ab273c4601..01bf38deb97c 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_loop_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_loop_messages.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s -Wno-openmp-target
class S {
int a;
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_map_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_map_messages.cpp
index 1fb466ee5518..5cba1e732d3f 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_map_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_map_messages.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s -Wno-openmp-target
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_messages.cpp
index 15135838e981..551acd2e8f0f 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_misc_messages.c b/test/OpenMP/target_teams_distribute_parallel_for_misc_messages.c
index c48a2dfa9e68..820eb11189a3 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_misc_messages.c
+++ b/test/OpenMP/target_teams_distribute_parallel_for_misc_messages.c
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -verify %s
+
// expected-error@+1 {{unexpected OpenMP directive '#pragma omp target teams distribute parallel for'}}
#pragma omp target teams distribute parallel for
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_nowait_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_nowait_messages.cpp
index 30a622439dbf..d0e679936e6c 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_nowait_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_nowait_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -verify -fopenmp %s
+// RUN: %clang_cc1 -fsyntax-only -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_num_teams_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_num_teams_messages.cpp
index fdc2d9c25918..ceb4fa567c69 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_num_teams_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_num_teams_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_num_threads_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_num_threads_messages.cpp
index afd8c367a0dc..f558936afae6 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_num_threads_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_num_threads_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_private_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_private_codegen.cpp
new file mode 100644
index 000000000000..87a149968930
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_private_codegen.cpp
@@ -0,0 +1,369 @@
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 --check-prefix HHECK --check-prefix HCHECK-64
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 --check-prefix HHECK --check-prefix HCHECK-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix HHECK --check-prefix HCHECK-64
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix HHECK --check-prefix HCHECK-64
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64 --check-prefix HLAMBDA --check-prefix HLAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64 --check-prefix HLAMBDA --check-prefix HLAMBDA-64
+
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0
+
+// Test target codegen - host bc file has to be created first. (no significant differences with host version of target region)
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix TCHECK --check-prefix TCHECK-32
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64 --check-prefix TLAMBDA --check-prefix TLAMBDA-64
+
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0
+//
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+struct St {
+ int a, b;
+ St() : a(0), b(0) {}
+ St(const St &st) : a(st.a + st.b), b(0) {}
+ ~St() {}
+};
+
+volatile int g = 1212;
+volatile int &g1 = g;
+
+template <class T>
+struct S {
+ T f;
+ S(T a) : f(a + g) {}
+ S() : f(g) {}
+ S(const S &s, St t = St()) : f(s.f + t.a) {}
+ operator T() { return T(); }
+ ~S() {}
+};
+
+// CHECK-DAG: [[S_FLOAT_TY:%.+]] = type { float }
+// CHECK-DAG: [[S_INT_TY:%.+]] = type { i{{[0-9]+}} }
+
+template <typename T>
+T tmain() {
+ S<T> test;
+ T t_var = T();
+ T vec[] = {1, 2};
+ S<T> s_arr[] = {1, 2};
+ S<T> &var = test;
+#pragma omp target teams distribute parallel for private(t_var, vec, s_arr, var)
+ for (int i = 0; i < 2; ++i) {
+ vec[i] = t_var;
+ s_arr[i] = var;
+ }
+ return T();
+}
+
+// HCHECK-DAG: [[TEST:@.+]] ={{.*}} global [[S_FLOAT_TY]] zeroinitializer,
+S<float> test;
+// HCHECK-DAG: [[T_VAR:@.+]] ={{.+}} global i{{[0-9]+}} 333,
+int t_var = 333;
+// HCHECK-DAG: [[VEC:@.+]] ={{.+}} global [2 x i{{[0-9]+}}] [i{{[0-9]+}} 1, i{{[0-9]+}} 2],
+int vec[] = {1, 2};
+// HCHECK-DAG: [[S_ARR:@.+]] ={{.+}} global [2 x [[S_FLOAT_TY]]] zeroinitializer,
+S<float> s_arr[] = {1, 2};
+// HCHECK-DAG: [[VAR:@.+]] ={{.+}} global [[S_FLOAT_TY]] zeroinitializer,
+S<float> var(3);
+// HCHECK-DAG: [[SIVAR:@.+]] = internal global i{{[0-9]+}} 0,
+
+int main() {
+ static int sivar;
+#ifdef LAMBDA
+ // HLAMBDA: [[G:@.+]] = global i{{[0-9]+}} 1212,
+ // HLAMBDA-LABEL: @main
+ // HLAMBDA: call void [[OUTER_LAMBDA:@.+]](
+ [&]() {
+ // HLAMBDA: define{{.*}} internal{{.*}} void [[OUTER_LAMBDA]](
+ // HLAMBDA: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 0,
+ // HLAMBDA: call void @[[LOFFL1:.+]](
+ // HLAMBDA: ret
+#pragma omp target teams distribute parallel for private(g, g1, sivar)
+ for (int i = 0; i < 2; ++i) {
+ // HLAMBDA: define{{.*}} internal{{.*}} void @[[LOFFL1]]()
+ // TLAMBDA: define{{.*}} void @[[LOFFL1:.+]]()
+ // LAMBDA: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 0, {{.+}} @[[LOUTL1:.+]] to {{.+}})
+ // LAMBDA: ret void
+
+ // LAMBDA: define internal void @[[LOUTL1]]({{.+}})
+ // Skip global, bound tid and loop vars
+ // LAMBDA: {{.+}} = alloca i32*,
+ // LAMBDA: {{.+}} = alloca i32*,
+ // LAMBDA: alloca i32,
+ // LAMBDA: alloca i32,
+ // LAMBDA: alloca i32,
+ // LAMBDA: alloca i32,
+ // LAMBDA: alloca i32,
+ // LAMBDA: alloca i32,
+ // LAMBDA: [[G_PRIV:%.+]] = alloca i{{[0-9]+}},
+ // LAMBDA: [[G1_PRIV:%.+]] = alloca i{{[0-9]+}}
+ // LAMBDA: [[TMP:%.+]] = alloca i{{[0-9]+}}*,
+ // LAMBDA: [[SIVAR_PRIV:%.+]] = alloca i{{[0-9]+}},
+ // LAMBDA: store{{.+}} [[G1_PRIV]], {{.+}} [[TMP]],
+
+ g = 1;
+ g1 = 1;
+ sivar = 2;
+ // LAMBDA: call void @__kmpc_for_static_init_4(
+ // LAMBDA: call void {{.+}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[LPAR_OUTL:.+]] to
+ // LAMBDA: call void @__kmpc_for_static_fini(
+ // LAMBDA: ret void
+
+ // LAMBDA: define internal void @[[LPAR_OUTL]]({{.+}})
+ // Skip global, bound tid and loop vars
+ // LAMBDA: {{.+}} = alloca i32*,
+ // LAMBDA: {{.+}} = alloca i32*,
+ // LAMBDA: alloca i{{[0-9]+}},
+ // LAMBDA: alloca i{{[0-9]+}},
+ // LAMBDA: alloca i32,
+ // LAMBDA: alloca i32,
+ // LAMBDA: alloca i32,
+ // LAMBDA: alloca i32,
+ // LAMBDA: alloca i32,
+ // LAMBDA: alloca i32,
+ // LAMBDA: [[G_PRIV:%.+]] = alloca i{{[0-9]+}},
+ // LAMBDA: [[G1_PRIV:%.+]] = alloca i{{[0-9]+}}
+ // LAMBDA: [[TMP:%.+]] = alloca i{{[0-9]+}}*,
+ // LAMBDA: [[SIVAR_PRIV:%.+]] = alloca i{{[0-9]+}},
+ // LAMBDA: store{{.+}} [[G1_PRIV]], {{.+}} [[TMP]],
+ // LAMBDA-DAG: store{{.+}} 1, {{.+}} [[G_PRIV]],
+ // LAMBDA-DAG: store{{.+}} 2, {{.+}} [[SIVAR_PRIV]],
+ // LAMBDA-DAG: [[G1_REF:%.+]] = load{{.+}}, {{.+}} [[TMP]],
+ // LAMBDA-DAG: store{{.+}} 1, {{.+}} [[G1_REF]],
+ // LAMBDA: call void [[INNER_LAMBDA:@.+]](
+ // LAMBDA: call void @__kmpc_for_static_fini(
+ // LAMBDA: ret void
+ [&]() {
+ // LAMBDA: define {{.+}} void [[INNER_LAMBDA]](%{{.+}}* [[ARG_PTR:%.+]])
+ // LAMBDA: store %{{.+}}* [[ARG_PTR]], %{{.+}}** [[ARG_PTR_REF:%.+]],
+ g = 2;
+ g1 = 2;
+ sivar = 4;
+ // LAMBDA: [[ARG_PTR:%.+]] = load %{{.+}}*, %{{.+}}** [[ARG_PTR_REF]]
+
+ // LAMBDA: [[G_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
+ // LAMBDA: [[G_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[G_PTR_REF]]
+ // LAMBDA: store i{{[0-9]+}} 2, i{{[0-9]+}}* [[G_REF]]
+ // LAMBDA: [[G1_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 1
+ // LAMBDA: [[G1_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[G1_PTR_REF]]
+ // LAMBDA: store i{{[0-9]+}} 2, i{{[0-9]+}}* [[G1_REF]]
+ // LAMBDA: [[SIVAR_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 2
+ // LAMBDA: [[SIVAR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SIVAR_PTR_REF]]
+ // LAMBDA: store i{{[0-9]+}} 4, i{{[0-9]+}}* [[SIVAR_REF]]
+ }();
+ }
+ }();
+ return 0;
+#else
+#pragma omp target teams distribute parallel for private(t_var, vec, s_arr, var, sivar)
+ for (int i = 0; i < 2; ++i) {
+ vec[i] = t_var;
+ s_arr[i] = var;
+ sivar += i;
+ }
+ return tmain<int>();
+#endif
+}
+
+// HCHECK: define {{.*}}i{{[0-9]+}} @main()
+// HCHECK: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 0, i8** null, i8** null, {{.+}} null, {{.+}} null, i32 0, i32 0)
+// HCHECK: call void @[[OFFL1:.+]]()
+// HCHECK: {{%.+}} = call{{.*}} i32 @[[TMAIN_INT:.+]]()
+// HCHECK: ret
+
+// HCHECK: define{{.*}} void @[[OFFL1]]()
+// TCHECK: define{{.*}} void @[[OFFL1:.+]]()
+// CHECK: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 0, {{.+}} @[[OUTL1:.+]] to {{.+}})
+// CHECK: ret void
+
+// CHECK: define internal void @[[OUTL1]]({{.+}})
+// Skip global, bound tid and loop vars
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: {{.+}} = alloca i32,
+// CHECK: {{.+}} = alloca i32,
+// CHECK: {{.+}} = alloca i32,
+// CHECK: {{.+}} = alloca i32,
+// CHECK: {{.+}} = alloca i32,
+// CHECK-DAG: [[T_VAR_PRIV:%.+]] = alloca i{{[0-9]+}},
+// CHECK-DAG: [[VEC_PRIV:%.+]] = alloca [2 x i{{[0-9]+}}],
+// CHECK-DAG: [[S_ARR_PRIV:%.+]] = alloca [2 x [[S_FLOAT_TY]]],
+// CHECK-DAG: [[VAR_PRIV:%.+]] = alloca [[S_FLOAT_TY]],
+// CHECK-DAG: [[SIVAR_PRIV:%.+]] = alloca i{{[0-9]+}},
+// CHECK: alloca i32,
+
+// private(s_arr)
+// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]],
+// CHECK-DAG: [[S_ARR_PTR_ALLOC:%.+]] = phi{{.+}} [ [[S_ARR_PRIV_BGN]], {{.+}} ], [ [[S_ARR_NEXT:%.+]], {{.+}} ]
+// CHECK-DAG: call void @{{.+}}({{.+}} [[S_ARR_PTR_ALLOC]])
+// CHECK-DAG: [[S_ARR_NEXT]] = getelementptr {{.+}} [[S_ARR_PTR_ALLOC]],
+
+// private(var)
+// CHECK-DAG: call void @{{.+}}({{.+}} [[VAR_PRIV]])
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call void {{.+}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL1:.+]] to
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: ret void
+
+// CHECK: define internal void @[[PAR_OUTL1]]({{.+}})
+// Skip global, bound tid and loop vars
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i32,
+// CHECK: {{.+}} = alloca i32,
+// CHECK: {{.+}} = alloca i32,
+// CHECK: {{.+}} = alloca i32,
+// CHECK: {{.+}} = alloca i32,
+// CHECK: {{.+}} = alloca i32,
+// CHECK-DAG: [[T_VAR_PRIV:%.+]] = alloca i{{[0-9]+}},
+// CHECK-DAG: [[VEC_PRIV:%.+]] = alloca [2 x i{{[0-9]+}}],
+// CHECK-DAG: [[S_ARR_PRIV:%.+]] = alloca [2 x [[S_FLOAT_TY]]],
+// CHECK-DAG: [[VAR_PRIV:%.+]] = alloca [[S_FLOAT_TY]],
+// CHECK-DAG: [[SIVAR_PRIV:%.+]] = alloca i{{[0-9]+}},
+// CHECK: alloca i32,
+
+// private(s_arr)
+// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]],
+// CHECK-DAG: [[S_ARR_PTR_ALLOC:%.+]] = phi{{.+}} [ [[S_ARR_PRIV_BGN]], {{.+}} ], [ [[S_ARR_NEXT:%.+]], {{.+}} ]
+// CHECK-DAG: call void @{{.+}}({{.+}} [[S_ARR_PTR_ALLOC]])
+// CHECK-DAG: [[S_ARR_NEXT]] = getelementptr {{.+}} [[S_ARR_PTR_ALLOC]],
+
+// private(var)
+// CHECK-DAG: call void @{{.+}}({{.+}} [[VAR_PRIV]])
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK-DAG: {{.+}} = {{.+}} [[T_VAR_PRIV]]
+// CHECK-DAG: {{.+}} = {{.+}} [[VEC_PRIV]]
+// CHECK-DAG: {{.+}} = {{.+}} [[S_ARR_PRIV]]
+// CHECK-DAG: {{.+}} = {{.+}} [[VAR_PRIV]]
+// CHECK-DAG: {{.+}} = {{.+}} [[SIVAR_PRIV]]
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: ret void
+
+// HCHECK: define{{.*}} i{{[0-9]+}} @[[TMAIN_INT]]()
+// HCHECK: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 0,
+// HCHECK: call void @[[TOFFL1:.+]]()
+// HCHECK: ret
+
+// HCHECK: define {{.*}}void @[[TOFFL1]]()
+// TCHECK: define weak void @[[TOFFL1:.+]]()
+// CHECK: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 0, {{.+}} @[[TOUTL1:.+]] to {{.+}})
+// CHECK: ret void
+
+// CHECK: define internal void @[[TOUTL1]]({{.+}})
+// Skip global, bound tid and loop vars
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i32,
+// CHECK: [[T_VAR_PRIV:%.+]] = alloca i{{[0-9]+}},
+// CHECK: [[VEC_PRIV:%.+]] = alloca [2 x i{{[0-9]+}}],
+// CHECK: [[S_ARR_PRIV:%.+]] = alloca [2 x [[S_INT_TY]]],
+// CHECK: [[VAR_PRIV:%.+]] = alloca [[S_INT_TY]],
+// CHECK: [[TMP:%.+]] = alloca [[S_INT_TY]]*,
+
+// private(s_arr)
+// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_PRIV]],
+// CHECK-DAG: [[S_ARR_PTR_ALLOC:%.+]] = phi{{.+}} [ [[S_ARR_PRIV_BGN]], {{.+}} ], [ [[S_ARR_NEXT:%.+]], {{.+}} ]
+// CHECK-DAG: call void @{{.+}}({{.+}} [[S_ARR_PTR_ALLOC]])
+// CHECK-DAG: [[S_ARR_NEXT]] = getelementptr {{.+}} [[S_ARR_PTR_ALLOC]],
+
+// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_PRIV]],
+// CHECK-DAG: [[S_ARR_PTR_ALLOC:%.+]] = phi{{.+}} [ [[S_ARR_PRIV_BGN]], {{.+}} ], [ [[S_ARR_NEXT:%.+]], {{.+}} ]
+// CHECK-DAG: call void @{{.+}}({{.+}} [[S_ARR_PTR_ALLOC]])
+// CHECK-DAG: [[S_ARR_NEXT]] = getelementptr {{.+}} [[S_ARR_PTR_ALLOC]],
+
+// private(var)
+// CHECK-DAG: call void @{{.+}}({{.+}} [[VAR_PRIV]])
+// CHECK-DAG: store{{.+}} [[VAR_PRIV]], {{.+}} [[TMP]]
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call void {{.+}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[TPAR_OUTL1:.+]] to
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: ret void
+
+// CHECK: define internal void @[[TPAR_OUTL1]]({{.+}})
+// Skip global, bound tid and loop vars
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: {{.+}} = alloca i32*,
+// prev lb and ub
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// iter variables
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i32,
+// CHECK: [[T_VAR_PRIV:%.+]] = alloca i{{[0-9]+}},
+// CHECK: [[VEC_PRIV:%.+]] = alloca [2 x i{{[0-9]+}}],
+// CHECK: [[S_ARR_PRIV:%.+]] = alloca [2 x [[S_INT_TY]]],
+// CHECK: [[VAR_PRIV:%.+]] = alloca [[S_INT_TY]],
+// CHECK: [[TMP:%.+]] = alloca [[S_INT_TY]]*,
+
+// private(s_arr)
+// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_PRIV]],
+// CHECK-DAG: [[S_ARR_PTR_ALLOC:%.+]] = phi{{.+}} [ [[S_ARR_PRIV_BGN]], {{.+}} ], [ [[S_ARR_NEXT:%.+]], {{.+}} ]
+// CHECK-DAG: call void @{{.+}}({{.+}} [[S_ARR_PTR_ALLOC]])
+// CHECK-DAG: [[S_ARR_NEXT]] = getelementptr {{.+}} [[S_ARR_PTR_ALLOC]],
+
+// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_PRIV]],
+// CHECK-DAG: [[S_ARR_PTR_ALLOC:%.+]] = phi{{.+}} [ [[S_ARR_PRIV_BGN]], {{.+}} ], [ [[S_ARR_NEXT:%.+]], {{.+}} ]
+// CHECK-DAG: call void @{{.+}}({{.+}} [[S_ARR_PTR_ALLOC]])
+// CHECK-DAG: [[S_ARR_NEXT]] = getelementptr {{.+}} [[S_ARR_PTR_ALLOC]],
+
+// private(var)
+// CHECK-DAG: call void @{{.+}}({{.+}} [[VAR_PRIV]])
+// CHECK-DAG: store{{.+}} [[VAR_PRIV]], {{.+}} [[TMP]]
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK-DAG: {{.+}} = {{.+}} [[T_VAR_PRIV]]
+// CHECK-DAG: {{.+}} = {{.+}} [[VEC_PRIV]]
+// CHECK-DAG: {{.+}} = {{.+}} [[S_ARR_PRIV]]
+// CHECK-DAG: {{.+}} = {{.+}} [[TMP]]
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: ret void
+
+
+#endif
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_private_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_private_messages.cpp
index d89cb1aa846d..7750238e70b5 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_private_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_private_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_proc_bind_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_proc_bind_codegen.cpp
new file mode 100644
index 000000000000..9107c218a436
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_proc_bind_codegen.cpp
@@ -0,0 +1,93 @@
+// add -fopenmp-targets
+
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// SIMD-ONLY-NOT: {{__kmpc|__tgt}}
+
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+typedef __INTPTR_TYPE__ intptr_t;
+
+// CHECK-DAG: [[IDENT_T_TY:%.+]] = type { i32, i32, i32, i32, i8* }
+// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
+// CHECK-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr constant [[IDENT_T_TY]] { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+
+void foo();
+
+struct S {
+ intptr_t a, b, c;
+ S(intptr_t a) : a(a) {}
+ operator char() { return a; }
+ ~S() {}
+};
+
+template <typename T>
+T tmain() {
+#pragma omp target teams distribute parallel for proc_bind(master)
+ for(int i = 0; i < 1000; i++) {}
+ return T();
+}
+
+int main() {
+ // CHECK-LABEL: @main
+#pragma omp target teams distribute parallel for proc_bind(spread)
+ for(int i = 0; i < 1000; i++) {}
+#pragma omp target teams distribute parallel for proc_bind(close)
+ for(int i = 0; i < 1000; i++) {}
+ return tmain<int>();
+}
+
+// CHECK: call {{.*}}@__tgt_target_teams({{.+}})
+// CHECK: call void [[OFFL1:@.+]]()
+// CHECK: call {{.*}}@__tgt_target_teams({{.+}})
+// CHECK: call void [[OFFL2:@.+]]()
+// CHECK: [[CALL_RET:%.+]] = call{{.+}} i32 [[TMAIN:@.+]]()
+// CHECK: ret i32 [[CALL_RET]]
+
+// CHECK: define{{.+}} void [[OFFL1]](
+// CHECK: call {{.*}}void {{.+}} @__kmpc_fork_teams({{.+}}, {{.+}}, {{.+}}* [[OMP_OUTLINED_1:@.+]] to {{.+}})
+
+// CHECK: define{{.+}} [[OMP_OUTLINED_1]](i32* {{.+}} [[GTID_IN:%.+]],
+// CHECK: [[GTID_ADDR:%.+]] = alloca i32*,
+// CHECK: store i32* [[GTID_IN]], i32** [[GTID_ADDR]],
+// CHECK: [[GTID_REF:%.+]] = load i32*, i32** [[GTID_ADDR]],
+// CHECK: [[GTID_VAL:%.+]] = load i32, i32* [[GTID_REF]],
+// CHECK: call {{.*}}void @__kmpc_push_proc_bind([[IDENT_T_TY]]* [[DEF_LOC_2]], i32 [[GTID_VAL]], i32 4)
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: ret void
+
+// CHECK: define{{.+}} [[OFFL2]]()
+// CHECK: call {{.*}}void {{.+}} @__kmpc_fork_teams({{.+}}, {{.+}}, {{.+}}* [[OMP_OUTLINED_1:@.+]] to {{.+}})
+
+// CHECK: define{{.+}} [[OMP_OUTLINED_1]](i32* {{.+}} [[GTID_IN:%.+]],
+// CHECK: [[GTID_ADDR:%.+]] = alloca i32*,
+// CHECK: store i32* [[GTID_IN]], i32** [[GTID_ADDR]],
+// CHECK: [[GTID_REF:%.+]] = load i32*, i32** [[GTID_ADDR]],
+// CHECK: [[GTID_VAL:%.+]] = load i32, i32* [[GTID_REF]],
+// CHECK: call {{.*}}void @__kmpc_push_proc_bind([[IDENT_T_TY]]* [[DEF_LOC_2]], i32 [[GTID_VAL]], i32 3)
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: ret void
+
+// CHECK: define{{.+}} [[TMAIN]]()
+// CHECK: call {{.*}}@__tgt_target_teams({{.+}})
+// CHECK: call void [[OFFL3:@.+]]()
+
+// CHECK: define{{.+}} [[OFFL3]]()
+// CHECK: call {{.*}}void {{.+}} @__kmpc_fork_teams({{.+}}, {{.+}}, {{.+}}* [[OMP_OUTLINED_3:@.+]] to {{.+}})
+
+// CHECK: define{{.+}} [[OMP_OUTLINED_3]](i32* {{.+}} [[GTID_IN:%.+]],
+// CHECK: [[GTID_ADDR:%.+]] = alloca i32*,
+// CHECK: store i32* [[GTID_IN]], i32** [[GTID_ADDR]],
+// CHECK: [[GTID_REF:%.+]] = load i32*, i32** [[GTID_ADDR]],
+// CHECK: [[GTID_VAL:%.+]] = load i32, i32* [[GTID_REF]],
+// CHECK: call {{.*}}void @__kmpc_push_proc_bind([[IDENT_T_TY]]* [[DEF_LOC_2]], i32 [[GTID_VAL]], i32 2)
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: ret void
+#endif
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_proc_bind_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_proc_bind_messages.cpp
index b2bbfa8bb337..659684e6f1e3 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_proc_bind_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_proc_bind_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo();
template <class T, typename S, int N>
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_reduction_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_reduction_codegen.cpp
new file mode 100644
index 000000000000..6575659637a5
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_reduction_codegen.cpp
@@ -0,0 +1,353 @@
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// SIMD-ONLY-NOT: {{__kmpc|__tgt}}
+
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+template <typename T>
+T tmain() {
+ T t_var = T();
+ T vec[] = {1, 2};
+#pragma omp target teams distribute parallel for reduction(+: t_var)
+ for (int i = 0; i < 2; ++i) {
+ t_var += (T) i;
+ }
+ return T();
+}
+
+int main() {
+ static int sivar;
+#ifdef LAMBDA
+ // LAMBDA: [[RED_VAR:@.+]] = common global [8 x {{.+}}] zeroinitializer
+
+ // LAMBDA-LABEL: @main
+ // LAMBDA: call void [[OUTER_LAMBDA:@.+]](
+ [&]() {
+ // LAMBDA: define{{.*}} internal{{.*}} void [[OUTER_LAMBDA]](
+ // LAMBDA: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 1, i8** %{{[^,]+}}, i8** %{{[^,]+}}, i{{64|32}}* {{.+}}@{{[^,]+}}, i32 0, i32 0), i64* {{.+}}@{{[^,]+}}, i32 0, i32 0), i32 0, i32 0)
+ // LAMBDA: call void @[[LOFFL1:.+]](
+ // LAMBDA: ret
+#pragma omp target teams distribute parallel for reduction(+: sivar)
+ for (int i = 0; i < 2; ++i) {
+ // LAMBDA: define{{.*}} internal{{.*}} void @[[LOFFL1]](i{{64|32}}*{{.*}} [[SIVAR_ARG:%.+]])
+ // LAMBDA: [[SIVAR_ADDR:%.+]] = alloca i{{.+}},
+ // LAMBDA: store{{.+}} [[SIVAR_ARG]], {{.+}} [[SIVAR_ADDR]],
+ // LAMBDA: [[SIVAR_PAR:%.+]] = load{{.+}}, {{.+}} [[SIVAR_ADDR]],
+ // LAMBDA: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[LOUTL1:.+]] to {{.+}}, {{.+}} [[SIVAR_PAR]])
+ // LAMBDA: ret void
+
+ // LAMBDA: define internal void @[[LOUTL1]]({{.+}}, {{.+}}, {{.+}} [[SIVAR_ARG:%.+]])
+ // Skip global and bound tid vars
+ // LAMBDA: {{.+}} = alloca i32*,
+ // LAMBDA: {{.+}} = alloca i32*,
+ // LAMBDA: [[SIVAR_ADDR:%.+]] = alloca i{{.+}},
+ // LAMBDA: [[SIVAR_PRIV:%.+]] = alloca i{{.+}},
+ // LAMBDA: [[RED_LIST:%.+]] = alloca [1 x {{.+}}],
+ // LAMBDA: store{{.+}} [[SIVAR_ARG]], {{.+}} [[SIVAR_ADDR]],
+ // LAMBDA: [[SIVAR_REF:%.+]] = load{{.+}}, {{.+}} [[SIVAR_ADDR]]
+ // LAMBDA: store{{.+}} 0, {{.+}} [[SIVAR_PRIV]],
+
+ // LAMBDA: call void @__kmpc_for_static_init_4(
+ // LAMBDA: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[LPAR_OUTL:.+]] to
+ // LAMBDA: call void @__kmpc_for_static_fini(
+ // LAMBDA: [[RED_LIST_GEP:%.+]] = getelementptr{{.+}} [[RED_LIST]],
+ // LAMBDA: [[SIVAR_PRIV_CAST:%.+]] = bitcast{{.+}} [[SIVAR_PRIV]] to
+ // LAMBDA: store{{.+}} [[SIVAR_PRIV_CAST]], {{.+}} [[RED_LIST_GEP]],
+ // LAMBDA: [[RED_LIST_BCAST:%.+]] = bitcast{{.+}} [[RED_LIST]] to
+ // LAMBDA: [[K_RED_RET:%.+]] = call{{.+}} @__kmpc_reduce_nowait({{.+}}, {{.+}}, {{.+}}, {{.+}}, {{.+}} [[RED_LIST_BCAST]], {{.+}} [[RED_FUN:@.+]], {{.+}} [[RED_VAR]])
+ // LAMBDA: switch{{.+}} [[K_RED_RET]], label{{.+}} [
+ // LAMBDA: {{.+}}, label %[[CASE1:.+]]
+ // LAMBDA: {{.+}}, label %[[CASE2:.+]]
+ // LAMBDA: ]
+ // LAMBDA: [[CASE1]]:
+ // LAMBDA-DAG: [[SIVAR_VAL:%.+]] = load{{.+}}, {{.+}} [[SIVAR_REF]],
+ // LAMBDA-DAG: [[SIVAR_PRIV_VAL:%.+]] = load{{.+}}, {{.+}} [[SIVAR_PRIV]],
+ // LAMBDA-DAG: [[SIVAR_INC:%.+]] = add{{.+}} [[SIVAR_VAL]], [[SIVAR_PRIV_VAL]]
+ // LAMBDA: store{{.+}} [[SIVAR_INC]], {{.+}} [[SIVAR_REF]],
+ // LAMBDA: call void @__kmpc_end_reduce_nowait({{.+}}, {{.+}}, {{.+}} [[RED_VAR]])
+ // LAMBDA: br
+ // LAMBDA: [[CASE2]]:
+ // LAMBDA-DAG: [[SIVAR_PRIV_VAL:%.+]] = load{{.+}}, {{.+}} [[SIVAR_PRIV]],
+ // LAMBDA-DAG: [[ATOMIC_RES:%.+]] = atomicrmw add{{.+}} [[SIVAR_REF]], {{.+}} [[SIVAR_PRIV_VAL]]
+ // LAMBDA: br
+
+ // LAMBDA: define internal void @[[LPAR_OUTL]]({{.+}}, {{.+}}, {{.+}}, {{.+}}, {{.+}} [[SIVAR_ARG:%.+]])
+
+ // Skip global and bound tid vars, and prev lb and ub vars
+ // LAMBDA: {{.+}} = alloca i32*,
+ // LAMBDA: {{.+}} = alloca i32*,
+ // LAMBDA: alloca i{{[0-9]+}},
+ // LAMBDA: alloca i{{[0-9]+}},
+ // LAMBDA: [[SIVAR_ADDR:%.+]] = alloca i{{.+}},
+ // skip loop vars
+ // LAMBDA: alloca i32,
+ // LAMBDA: alloca i32,
+ // LAMBDA: alloca i32,
+ // LAMBDA: alloca i32,
+ // LAMBDA: alloca i32,
+ // LAMBDA: alloca i32,
+ // LAMBDA: [[SIVAR_PRIV:%.+]] = alloca i{{.+}},
+ // LAMBDA: [[RED_LIST:%.+]] = alloca [1 x {{.+}}],
+ // LAMBDA: store{{.+}} [[SIVAR_ARG]], {{.+}} [[SIVAR_ADDR]],
+ // LAMBDA: [[SIVAR_REF:%.+]] = load {{.+}} [[SIVAR_ADDR]]
+ // LAMBDA: store{{.+}} 0, {{.+}} [[SIVAR_PRIV]],
+
+ // LAMBDA: call void @__kmpc_for_static_init_4(
+ // LAMBDA: store{{.+}}, {{.+}} [[SIVAR_PRIV]],
+ // LAMBDA: call void [[INNER_LAMBDA:@.+]](
+ // LAMBDA: call void @__kmpc_for_static_fini(
+ // LAMBDA: [[RED_LIST_GEP:%.+]] = getelementptr{{.+}} [[RED_LIST]],
+ // LAMBDA: [[SIVAR_PRIV_CAST:%.+]] = bitcast{{.+}} [[SIVAR_PRIV]] to
+ // LAMBDA: store{{.+}} [[SIVAR_PRIV_CAST]], {{.+}} [[RED_LIST_GEP]],
+ // LAMBDA: [[RED_LIST_BCAST:%.+]] = bitcast{{.+}} [[RED_LIST]] to
+ // LAMBDA: [[K_RED_RET:%.+]] = call{{.+}} @__kmpc_reduce_nowait({{.+}}, {{.+}}, {{.+}}, {{.+}}, {{.+}} [[RED_LIST_BCAST]], {{.+}} [[RED_FUN:@.+]], {{.+}} [[RED_VAR]])
+ // LAMBDA: switch{{.+}} [[K_RED_RET]], label{{.+}} [
+ // LAMBDA: {{.+}}, label %[[CASE1:.+]]
+ // LAMBDA: {{.+}}, label %[[CASE2:.+]]
+ // LAMBDA: ]
+ // LAMBDA: [[CASE1]]:
+ // LAMBDA-64-DAG: [[SIVAR_VAL:%.+]] = load{{.+}}, {{.+}} [[SIVAR_REF]],
+ // LAMBDA-32-DAG: [[SIVAR_VAL:%.+]] = load{{.+}}, {{.+}} [[SIVAR_ADDR]],
+ // LAMBDA-DAG: [[SIVAR_PRIV_VAL:%.+]] = load{{.+}}, {{.+}} [[SIVAR_PRIV]],
+ // LAMBDA-DAG: [[SIVAR_INC:%.+]] = add{{.+}} [[SIVAR_VAL]], [[SIVAR_PRIV_VAL]]
+ // LAMBDA: store{{.+}} [[SIVAR_INC]], {{.+}} [[SIVAR_REF]],
+ // LAMBDA: call void @__kmpc_end_reduce_nowait({{.+}}, {{.+}}, {{.+}} [[RED_VAR]])
+ // LAMBDA: br
+ // LAMBDA: [[CASE2]]:
+ // LAMBDA-DAG: [[SIVAR_PRIV_VAL:%.+]] = load{{.+}}, {{.+}} [[SIVAR_PRIV]],
+ // LAMBDA-DAG: [[ATOMIC_RES:%.+]] = atomicrmw add{{.+}} [[SIVAR_REF]], {{.+}} [[SIVAR_PRIV_VAL]]
+ // LAMBDA: br
+
+ sivar += i;
+
+ [&]() {
+ // LAMBDA: define {{.+}} void [[INNER_LAMBDA]](%{{.+}}* [[ARG_PTR:%.+]])
+ // LAMBDA: store %{{.+}}* [[ARG_PTR]], %{{.+}}** [[ARG_PTR_REF:%.+]],
+
+ sivar += 4;
+ // LAMBDA: [[ARG_PTR:%.+]] = load %{{.+}}*, %{{.+}}** [[ARG_PTR_REF]]
+
+ // LAMBDA: [[SIVAR_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
+ // LAMBDA: [[SIVAR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SIVAR_PTR_REF]]
+ // LAMBDA: [[SIVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SIVAR_REF]]
+ // LAMBDA: [[SIVAR_INC:%.+]] = add{{.+}} [[SIVAR_VAL]], 4
+ // LAMBDA: store i{{[0-9]+}} [[SIVAR_INC]], i{{[0-9]+}}* [[SIVAR_REF]]
+ }();
+ }
+ }();
+ return 0;
+#else
+#pragma omp target teams distribute parallel for reduction(+: sivar)
+ for (int i = 0; i < 2; ++i) {
+ sivar += i;
+ }
+ return tmain<int>();
+#endif
+}
+
+// CHECK: [[RED_VAR:@.+]] = common global [8 x {{.+}}] zeroinitializer
+
+// CHECK: define {{.*}}i{{[0-9]+}} @main()
+// CHECK: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 1, i8** %{{[^,]+}}, i8** %{{[^,]+}}, i{{64|32}}* {{.+}}@{{[^,]+}}, i32 0, i32 0), i64* {{.+}}@{{[^,]+}}, i32 0, i32 0), i32 0, i32 0)
+// CHECK: call void @[[OFFL1:.+]](i{{64|32}}* @{{.+}})
+// CHECK: {{%.+}} = call{{.*}} i32 @[[TMAIN_INT:.+]]()
+// CHECK: ret
+
+// CHECK: define{{.*}} void @[[OFFL1]](i{{64|32}}*{{.*}} [[SIVAR_ARG:%.+]])
+// CHECK: [[SIVAR_ADDR:%.+]] = alloca i{{.+}},
+// CHECK: store{{.+}} [[SIVAR_ARG]], {{.+}} [[SIVAR_ADDR]],
+// CHECK: [[SIVAR_VAL:%.+]] = load{{.+}}, {{.+}} [[SIVAR_ADDR]]
+// CHECK: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[OUTL1:.+]] to {{.+}}, {{.+}} [[SIVAR_VAL]])
+// CHECK: ret void
+
+// CHECK: define internal void @[[OUTL1]]({{.+}}, {{.+}}, {{.+}} [[SIVAR_ARG:%.+]])
+// Skip global and bound tid vars
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: [[SIVAR_ADDR:%.+]] = alloca i{{.+}},
+// CHECK: [[SIVAR_PRIV:%.+]] = alloca i{{.+}},
+// CHECK: [[RED_LIST:%.+]] = alloca [1 x {{.+}}],
+// CHECK: store{{.+}} [[SIVAR_ARG]], {{.+}} [[SIVAR_ADDR]],
+// CHECK: [[SIVAR_REF:%.+]] = load{{.+}} [[SIVAR_ADDR]],
+// CHECK: store{{.+}} 0, {{.+}} [[SIVAR_PRIV]],
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL:.+]] to
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: [[RED_LIST_GEP:%.+]] = getelementptr{{.+}} [[RED_LIST]],
+// CHECK: [[SIVAR_PRIV_CAST:%.+]] = bitcast{{.+}} [[SIVAR_PRIV]] to
+// CHECK: store{{.+}} [[SIVAR_PRIV_CAST]], {{.+}} [[RED_LIST_GEP]],
+// CHECK: [[RED_LIST_BCAST:%.+]] = bitcast{{.+}} [[RED_LIST]] to
+// CHECK: [[K_RED_RET:%.+]] = call{{.+}} @__kmpc_reduce_nowait({{.+}}, {{.+}}, {{.+}}, {{.+}}, {{.+}} [[RED_LIST_BCAST]], {{.+}} [[RED_FUN:@.+]], {{.+}} [[RED_VAR]])
+// CHECK: switch{{.+}} [[K_RED_RET]], label{{.+}} [
+// CHECK: {{.+}}, label %[[CASE1:.+]]
+// CHECK: {{.+}}, label %[[CASE2:.+]]
+// CHECK: ]
+// CHECK: [[CASE1]]:
+// CHECK-DAG: [[SIVAR_VAL:%.+]] = load{{.+}}, {{.+}} [[SIVAR_REF]],
+// CHECK-DAG: [[SIVAR_PRIV_VAL:%.+]] = load{{.+}}, {{.+}} [[SIVAR_PRIV]],
+// CHECK-DAG: [[SIVAR_INC:%.+]] = add{{.+}} [[SIVAR_VAL]], [[SIVAR_PRIV_VAL]]
+// CHECK: store{{.+}} [[SIVAR_INC]], {{.+}} [[SIVAR_REF]],
+// CHECK: call void @__kmpc_end_reduce_nowait({{.+}}, {{.+}}, {{.+}} [[RED_VAR]])
+// CHECK: br
+// CHECK: [[CASE2]]:
+// CHECK-DAG: [[SIVAR_PRIV_VAL:%.+]] = load{{.+}}, {{.+}} [[SIVAR_PRIV]],
+// CHECK-DAG: [[ATOMIC_RES:%.+]] = atomicrmw add{{.+}} [[SIVAR_REF]], {{.+}} [[SIVAR_PRIV_VAL]]
+// CHECK: br
+
+// CHECK: define internal void @[[PAR_OUTL]]({{.+}}, {{.+}}, {{.+}}, {{.+}}, {{.+}} [[SIVAR_ARG:%.+]])
+// Skip global and bound tid vars, and prev lb and ub
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: [[SIVAR_ADDR:%.+]] = alloca i{{.+}},
+// skip loop vars
+// CHECK: alloca i32,
+// CHECK: alloca i32,
+// CHECK: alloca i32,
+// CHECK: alloca i32,
+// CHECK: alloca i32,
+// CHECK: alloca i32,
+// CHECK: [[SIVAR_PRIV:%.+]] = alloca i{{.+}},
+// CHECK: [[RED_LIST:%.+]] = alloca [1 x {{.+}}],
+// CHECK: store{{.+}} [[SIVAR_ARG]], {{.+}} [[SIVAR_ADDR]],
+// CHECK-64: [[SIVAR_REF:%.+]] = load {{.+}} [[SIVAR_ADDR]],
+// CHECK: store{{.+}} 0, {{.+}} [[SIVAR_PRIV]],
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: store{{.+}}, {{.+}} [[SIVAR_PRIV]],
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: [[RED_LIST_GEP:%.+]] = getelementptr{{.+}} [[RED_LIST]],
+// CHECK: [[SIVAR_PRIV_CAST:%.+]] = bitcast{{.+}} [[SIVAR_PRIV]] to
+// CHECK: store{{.+}} [[SIVAR_PRIV_CAST]], {{.+}} [[RED_LIST_GEP]],
+// CHECK: [[RED_LIST_BCAST:%.+]] = bitcast{{.+}} [[RED_LIST]] to
+// CHECK: [[K_RED_RET:%.+]] = call{{.+}} @__kmpc_reduce_nowait({{.+}}, {{.+}}, {{.+}}, {{.+}}, {{.+}} [[RED_LIST_BCAST]], {{.+}} [[RED_FUN:@.+]], {{.+}} [[RED_VAR]])
+// CHECK: switch{{.+}} [[K_RED_RET]], label{{.+}} [
+// CHECK: {{.+}}, label %[[CASE1:.+]]
+// CHECK: {{.+}}, label %[[CASE2:.+]]
+// CHECK: ]
+// CHECK: [[CASE1]]:
+// CHECK-DAG: [[SIVAR_VAL:%.+]] = load{{.+}}, {{.+}} [[SIVAR_REF]],
+// CHECK-DAG: [[SIVAR_PRIV_VAL:%.+]] = load{{.+}}, {{.+}} [[SIVAR_PRIV]],
+// CHECK-DAG: [[SIVAR_INC:%.+]] = add{{.+}} [[SIVAR_VAL]], [[SIVAR_PRIV_VAL]]
+// CHECK: store{{.+}} [[SIVAR_INC]], {{.+}} [[SIVAR_REF]],
+// CHECK: call void @__kmpc_end_reduce_nowait({{.+}}, {{.+}}, {{.+}} [[RED_VAR]])
+// CHECK: br
+// CHECK: [[CASE2]]:
+// CHECK-DAG: [[SIVAR_PRIV_VAL:%.+]] = load{{.+}}, {{.+}} [[SIVAR_PRIV]],
+// CHECK-DAG: [[ATOMIC_RES:%.+]] = atomicrmw add{{.+}} [[SIVAR_REF]], {{.+}} [[SIVAR_PRIV_VAL]]
+// CHECK: br
+
+// CHECK: define{{.*}} i{{[0-9]+}} @[[TMAIN_INT]]()
+// CHECK: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 1,
+// CHECK: call void @[[TOFFL1:.+]]({{.+}})
+// CHECK: ret
+
+// CHECK: define{{.*}} void @[[TOFFL1]](i{{64|32}}*{{.*}} [[TVAR_ARG:%.+]])
+// CHECK: [[TVAR_ADDR:%.+]] = alloca i{{.+}},
+// CHECK: store{{.+}} [[TVAR_ARG]], {{.+}} [[TVAR_ADDR]],
+// CHECK: [[TVAR_VAL:%.+]] = load{{.+}}, {{.+}} [[TVAR_ADDR]]
+// CHECK: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[TOUTL1:.+]] to {{.+}}, {{.+}} [[TVAR_VAL]])
+// CHECK: ret void
+
+// CHECK: define internal void @[[TOUTL1]]({{.+}}, {{.+}}, {{.+}} [[TVAR_ARG:%.+]])
+// Skip global and bound tid vars
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: [[TVAR_ADDR:%.+]] = alloca i{{.+}},
+// CHECK: [[TVAR_PRIV:%.+]] = alloca i{{.+}},
+// CHECK: [[RED_LIST:%.+]] = alloca [1 x {{.+}}],
+// CHECK: store{{.+}} [[TVAR_ARG]], {{.+}} [[TVAR_ADDR]],
+// CHECK: [[TVAR_REF:%.+]] = load {{.+}} [[TVAR_ADDR]],
+// CHECK: store{{.+}} 0, {{.+}} [[TVAR_PRIV]],
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[TPAR_OUTL:.+]] to
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: [[RED_LIST_GEP:%.+]] = getelementptr{{.+}} [[RED_LIST]],
+// CHECK: [[TVAR_PRIV_CAST:%.+]] = bitcast{{.+}} [[TVAR_PRIV]] to
+// CHECK: store{{.+}} [[TVAR_PRIV_CAST]], {{.+}} [[RED_LIST_GEP]],
+// CHECK: [[RED_LIST_BCAST:%.+]] = bitcast{{.+}} [[RED_LIST]] to
+// CHECK: [[K_RED_RET:%.+]] = call{{.+}} @__kmpc_reduce_nowait({{.+}}, {{.+}}, {{.+}}, {{.+}}, {{.+}} [[RED_LIST_BCAST]], {{.+}} [[RED_FUN:@.+]], {{.+}} [[RED_VAR]])
+// CHECK: switch{{.+}} [[K_RED_RET]], label{{.+}} [
+// CHECK: {{.+}}, label %[[CASE1:.+]]
+// CHECK: {{.+}}, label %[[CASE2:.+]]
+// CHECK: ]
+// CHECK: [[CASE1]]:
+// CHECK-DAG: [[TVAR_VAL:%.+]] = load{{.+}}, {{.+}} [[TVAR_REF]],
+// CHECK-DAG: [[TVAR_PRIV_VAL:%.+]] = load{{.+}}, {{.+}} [[TVAR_PRIV]],
+// CHECK-DAG: [[TVAR_INC:%.+]] = add{{.+}} [[TVAR_VAL]], [[TVAR_PRIV_VAL]]
+// CHECK: store{{.+}} [[TVAR_INC]], {{.+}} [[TVAR_REF]],
+// CHECK: call void @__kmpc_end_reduce_nowait({{.+}}, {{.+}}, {{.+}} [[RED_VAR]])
+// CHECK: br
+// CHECK: [[CASE2]]:
+// CHECK-DAG: [[TVAR_PRIV_VAL:%.+]] = load{{.+}}, {{.+}} [[TVAR_PRIV]],
+// CHECK-DAG: [[ATOMIC_RES:%.+]] = atomicrmw add{{.+}} [[TVAR_REF]], {{.+}} [[TVAR_PRIV_VAL]]
+// CHECK: br
+
+// CHECK: define internal void @[[TPAR_OUTL]]({{.+}}, {{.+}}, {{.+}}, {{.+}}, {{.+}} [[TVAR_ARG:%.+]])
+// Skip global and bound tid vars, and prev lb and ub vars
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: [[TVAR_ADDR:%.+]] = alloca i{{.+}},
+// skip loop vars
+// CHECK: alloca i32,
+// CHECK: alloca i32,
+// CHECK: alloca i32,
+// CHECK: alloca i32,
+// CHECK: alloca i32,
+// CHECK: alloca i32,
+// CHECK: [[TVAR_PRIV:%.+]] = alloca i{{.+}},
+// CHECK: [[RED_LIST:%.+]] = alloca [1 x {{.+}}],
+// CHECK: store{{.+}} [[TVAR_ARG]], {{.+}} [[TVAR_ADDR]],
+// CHECK: [[TVAR_REF:%.+]] = load {{.+}} [[TVAR_ADDR]],
+// CHECK: store{{.+}} 0, {{.+}} [[TVAR_PRIV]],
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: store{{.+}}, {{.+}} [[TVAR_PRIV]],
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: [[RED_LIST_GEP:%.+]] = getelementptr{{.+}} [[RED_LIST]],
+// CHECK: [[TVAR_PRIV_CAST:%.+]] = bitcast{{.+}} [[TVAR_PRIV]] to
+// CHECK: store{{.+}} [[TVAR_PRIV_CAST]], {{.+}} [[RED_LIST_GEP]],
+// CHECK: [[RED_LIST_BCAST:%.+]] = bitcast{{.+}} [[RED_LIST]] to
+// CHECK: [[K_RED_RET:%.+]] = call{{.+}} @__kmpc_reduce_nowait({{.+}}, {{.+}}, {{.+}}, {{.+}}, {{.+}} [[RED_LIST_BCAST]], {{.+}} [[RED_FUN:@.+]], {{.+}} [[RED_VAR]])
+// CHECK: switch{{.+}} [[K_RED_RET]], label{{.+}} [
+// CHECK: {{.+}}, label %[[CASE1:.+]]
+// CHECK: {{.+}}, label %[[CASE2:.+]]
+// CHECK: ]
+// CHECK: [[CASE1]]:
+// CHECK-DAG: [[TVAR_VAL:%.+]] = load{{.+}}, {{.+}} [[TVAR_REF]],
+// CHECK-DAG: [[TVAR_PRIV_VAL:%.+]] = load{{.+}}, {{.+}} [[TVAR_PRIV]],
+// CHECK-DAG: [[TVAR_INC:%.+]] = add{{.+}} [[TVAR_VAL]], [[TVAR_PRIV_VAL]]
+// CHECK: store{{.+}} [[TVAR_INC]], {{.+}} [[TVAR_REF]],
+// CHECK: call void @__kmpc_end_reduce_nowait({{.+}}, {{.+}}, {{.+}} [[RED_VAR]])
+// CHECK: br
+// CHECK: [[CASE2]]:
+// CHECK-DAG: [[TVAR_PRIV_VAL:%.+]] = load{{.+}}, {{.+}} [[TVAR_PRIV]],
+// CHECK-DAG: [[ATOMIC_RES:%.+]] = atomicrmw add{{.+}} [[TVAR_REF]], {{.+}} [[TVAR_PRIV_VAL]]
+// CHECK: br
+#endif
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_reduction_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_reduction_messages.cpp
index 59b35417d401..53c41b6bb062 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_reduction_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_reduction_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_schedule_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_schedule_codegen.cpp
new file mode 100644
index 000000000000..8eb6c443ca2d
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_schedule_codegen.cpp
@@ -0,0 +1,400 @@
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+// Test host codegen.
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-64
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-64
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// SIMD-ONLY-NOT: {{__kmpc|__tgt}}
+
+#ifdef CK1
+
+template <typename T, int X, long long Y>
+struct SS{
+ T a[X];
+ float b;
+ // CK1: define {{.*}}i32 @{{.+}}foo{{.+}}(
+ int foo(void) {
+
+ // CK1: call i32 @__tgt_target_teams(
+ // CK1: call void @[[OFFL1:.+]](
+ #pragma omp target teams distribute parallel for
+ for(int i = 0; i < X; i++) {
+ a[i] = (T)0;
+ }
+ // CK1: call i32 @__tgt_target_teams(
+ // CK1: call void @[[OFFL2:.+]](
+ #pragma omp target teams distribute parallel for schedule(static)
+ for(int i = 0; i < X; i++) {
+ a[i] = (T)0;
+ }
+ // CK1: call i32 @__tgt_target_teams(
+ // CK1: call void @[[OFFL3:.+]](
+ #pragma omp target teams distribute parallel for schedule(static, X/2)
+ for(int i = 0; i < X; i++) {
+ a[i] = (T)0;
+ }
+
+ // CK1: call i32 @__tgt_target_teams(
+ // CK1: call void @[[OFFL4:.+]](
+ #pragma omp target teams distribute parallel for schedule(dynamic)
+ for(int i = 0; i < X; i++) {
+ a[i] = (T)0;
+ }
+
+ // CK1: call i32 @__tgt_target_teams(
+ // CK1: call void @[[OFFL5:.+]](
+ #pragma omp target teams distribute parallel for schedule(dynamic, X/2)
+ for(int i = 0; i < X; i++) {
+ a[i] = (T)0;
+ }
+
+ // CK1: define internal void @[[OFFL1]](
+ // CK1: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[OUTL1:.+]] to {{.+}},
+ // CK1: ret void
+
+ // CK1: define internal void @[[OUTL1]]({{.+}})
+ // CK1: call void @__kmpc_for_static_init_4(
+ // CK1: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL1:.+]] to
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ // CK1: define internal void @[[PAR_OUTL1]]({{.+}})
+ // CK1: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 34,
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ // CK1: define internal void @[[OFFL2]](
+ // CK1: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[OUTL2:.+]] to {{.+}},
+ // CK1: ret void
+
+ // CK1: define internal void @[[OUTL2]]({{.+}})
+ // CK1: call void @__kmpc_for_static_init_4(
+ // CK1: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL2:.+]] to
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ // CK1: define internal void @[[PAR_OUTL2]]({{.+}})
+ // CK1: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 34,
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ // CK1: define internal void @[[OFFL3]](
+ // CK1: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[OUTL3:.+]] to {{.+}},
+ // CK1: ret void
+
+ // CK1: define internal void @[[OUTL3]]({{.+}})
+ // CK1: call void @__kmpc_for_static_init_4(
+ // CK1: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL3:.+]] to
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ // CK1: define internal void @[[PAR_OUTL3]]({{.+}})
+ // CK1: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 33,
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ // CK1: define internal void @[[OFFL4]](
+ // CK1: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[OUTL4:.+]] to {{.+}},
+ // CK1: ret void
+
+ // CK1: define internal void @[[OUTL4]]({{.+}})
+ // CK1: call void @__kmpc_for_static_init_4(
+ // CK1: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL4:.+]] to
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ // CK1: define internal void @[[PAR_OUTL4]]({{.+}})
+ // CK1: call void @__kmpc_dispatch_init_4({{.+}}, {{.+}}, i32 35,
+ // CK1: call {{.+}} @__kmpc_dispatch_next_4(
+ // CK1: ret void
+
+ // CK1: define internal void @[[OFFL5]](
+ // CK1: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[OUTL5:.+]] to {{.+}},
+ // CK1: ret void
+
+ // CK1: define internal void @[[OUTL5]]({{.+}})
+ // CK1: call void @__kmpc_for_static_init_4(
+ // CK1: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL5:.+]] to
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ // CK1: define internal void @[[PAR_OUTL5]]({{.+}})
+ // CK1: call void @__kmpc_dispatch_init_4({{.+}}, {{.+}}, i32 35,
+ // CK1: call {{.+}} @__kmpc_dispatch_next_4(
+ // CK1: ret void
+
+ return a[0];
+ }
+};
+
+int teams_template_struct(void) {
+ SS<int, 123, 456> V;
+ return V.foo();
+
+}
+#endif // CK1
+
+// Test host codegen.
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-64
+// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-64
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// SIMD-ONLY-NOT: {{__kmpc|__tgt}}
+#ifdef CK2
+
+template <typename T, int n>
+int tmain(T argc) {
+ T a[n];
+ int m = 10;
+#pragma omp target teams distribute parallel for
+ for(int i = 0; i < n; i++) {
+ a[i] = (T)0;
+ }
+#pragma omp target teams distribute parallel for schedule(static)
+ for(int i = 0; i < n; i++) {
+ a[i] = (T)0;
+ }
+#pragma omp target teams distribute parallel for schedule(static, m)
+ for(int i = 0; i < n; i++) {
+ a[i] = (T)0;
+ }
+#pragma omp target teams distribute parallel for schedule(dynamic)
+ for(int i = 0; i < n; i++) {
+ a[i] = (T)0;
+ }
+#pragma omp target teams distribute parallel for schedule(dynamic, m)
+ for(int i = 0; i < n; i++) {
+ a[i] = (T)0;
+ }
+ return 0;
+}
+
+int main (int argc, char **argv) {
+ int n = 100;
+ int a[n];
+ int m = 10;
+#pragma omp target teams distribute parallel for
+ for(int i = 0; i < n; i++) {
+ a[i] = 0;
+ }
+#pragma omp target teams distribute parallel for dist_schedule(static)
+ for(int i = 0; i < n; i++) {
+ a[i] = 0;
+ }
+#pragma omp target teams distribute parallel for dist_schedule(static, m)
+ for(int i = 0; i < n; i++) {
+ a[i] = 0;
+ }
+#pragma omp target teams distribute parallel for schedule(dynamic)
+ for(int i = 0; i < n; i++) {
+ a[i] = 0;
+ }
+#pragma omp target teams distribute parallel for schedule(dynamic, m)
+ for(int i = 0; i < n; i++) {
+ a[i] = 0;
+ }
+ return tmain<int, 10>(argc);
+}
+
+// CK2: define {{.*}}i32 @{{[^,]+}}(i{{.+}}{{.+}} %[[ARGC:.+]], {{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFL1:.+]]({{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFL2:.+]]({{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFL3:.+]]({{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFL4:.+]]({{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFL5:.+]]({{.+}})
+// CK2: {{%.+}} = call{{.*}} i32 @[[TMAIN:.+]]({{.+}})
+// CK2: ret
+
+// CK2: define {{.*}}void @[[OFFL1]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 3, {{.+}} @[[OUTL1:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTL1]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4(
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL1:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTL1]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 34,
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define {{.*}}void @[[OFFL2]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 3, {{.+}} @[[OUTL2:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTL2]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4(
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL2:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTL2]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 34,
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define {{.*}}void @[[OFFL3]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 4, {{.+}} @[[OUTL3:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTL3]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4(
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL3:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTL3]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 34
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define {{.*}}void @[[OFFL4]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 {{.+}}, {{.+}} @[[OUTL4:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTL4]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4(
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL4:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTL4]]({{.+}})
+// CK2: call void @__kmpc_dispatch_init_4({{.+}}, {{.+}}, i32 35,
+// CK2: call {{.+}} @__kmpc_dispatch_next_4(
+// CK2: ret void
+
+
+// CK2: define {{.*}}void @[[OFFL5]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 {{.+}}, {{.+}} @[[OUTL5:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTL5]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4(
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL5:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTL5]]({{.+}})
+// CK2: call void @__kmpc_dispatch_init_4({{.+}}, {{.+}}, i32 35,
+// CK2: call {{.+}} @__kmpc_dispatch_next_4(
+// CK2: ret void
+
+// CK2: define {{.*}}i32 @[[TMAIN]]({{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFLT1:.+]]({{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFLT2:.+]]({{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFLT3:.+]]({{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFLT4:.+]]({{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFLT5:.+]]({{.+}})
+// CK2: ret
+// CK2-NEXT: }
+
+// CK2: define {{.*}}void @[[OFFLT1]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[OUTLT1:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTLT1]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4(
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTLT1:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTLT1]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 34,
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define {{.*}}void @[[OFFLT2]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[OUTLT2:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTLT2]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4(
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTLT2:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTLT2]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 34,
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define {{.*}}void @[[OFFLT3]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 {{.+}}, {{.+}} @[[OUTLT3:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTLT3]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4(
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTLT3:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTLT3]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 33,
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define {{.*}}void @[[OFFLT4]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 {{.+}}, {{.+}} @[[OUTLT4:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTLT4]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4(
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTLT4:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTLT4]]({{.+}})
+// CK2: call void @__kmpc_dispatch_init_4({{.+}}, {{.+}}, i32 35,
+// CK2: call {{.+}} @__kmpc_dispatch_next_4(
+// CK2: ret void
+
+// CK2: define {{.*}}void @[[OFFLT5]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 {{.+}}, {{.+}} @[[OUTLT5:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTLT5]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4(
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTLT5:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTLT5]]({{.+}})
+// CK2: call void @__kmpc_dispatch_init_4({{.+}}, {{.+}}, i32 35,
+// CK2: call {{.+}} @__kmpc_dispatch_next_4(
+// CK2: ret void
+
+#endif // CK2
+#endif // #ifndef HEADER
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_schedule_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_schedule_messages.cpp
index 54e302010992..1f4f5f12e87b 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_schedule_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_schedule_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_shared_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_shared_messages.cpp
index 4f9000079630..f90a533edfee 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_shared_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_shared_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_aligned_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_aligned_messages.cpp
index f121512733af..18685d2b30ed 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_aligned_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_aligned_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -x c++ -std=c++11 -verify -fopenmp %s
+// RUN: %clang_cc1 -x c++ -std=c++11 -verify -fopenmp-simd %s
+
struct B {
static int ib[20]; // expected-note 0 {{'B::ib' declared here}}
static constexpr int bfoo() { return 8; }
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_ast_print.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_ast_print.cpp
index af588f1b81d9..5de2d4b195dd 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_ast_print.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_ast_print.cpp
@@ -1,6 +1,10 @@
-// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -ast-print %s -Wno-openmp-target | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-target | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s -Wno-openmp-target | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-target | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -109,7 +113,7 @@ T tmain(T argc) {
#pragma omp target teams distribute parallel for simd
for (int i=0; i < 2; ++i)
a = 2;
-// CHECK: #pragma omp target teams distribute parallel for simd
+// CHECK: #pragma omp target teams distribute parallel for simd{{$}}
// CHECK-NEXT: for (int i = 0; i < 2; ++i)
// CHECK-NEXT: a = 2;
#pragma omp target teams distribute parallel for simd private(argc, b), firstprivate(c, d), collapse(2)
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen.cpp
new file mode 100644
index 000000000000..0329d7e2789e
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen.cpp
@@ -0,0 +1,131 @@
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+// Test host codegen.
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-64 --check-prefix HCK1 --check-prefix HCK1-64
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-64 --check-prefix HCK1 --check-prefix HCK1-64
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32 --check-prefix HCK1 --check-prefix HCK1-64
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32 --check-prefix HCK1 --check-prefix HCK1-64
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY1
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY1
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY1
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY1
+
+// Test target codegen - host bc file has to be created first. (no significant differences with host version of target region)
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-64 --check-prefix TCK1 --check-prefix TCK1-64
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-64 --check-prefix TCK1 --check-prefix TCK1-64
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32 --check-prefix TCK1 --check-prefix TCK1-32
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32 --check-prefix TCK1 --check-prefix TCK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix SIMD-ONLY1
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY1
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix SIMD-ONLY1
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY1
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
+#ifdef CK1
+
+// HCK1: define{{.*}} i32 @{{.+}}target_teams_fun{{.*}}(
+int target_teams_fun(int *g){
+ int n = 1000;
+ int a[1000];
+ int te = n / 128;
+ int th = 128;
+// discard n_addr
+// HCK1: alloca i32,
+// HCK1: [[TE:%.+]] alloca i32,
+// HCK1: [[TH:%.+]] = alloca i32,
+// HCK1: [[I:%.+]] = alloca i32,
+// discard capture expressions for te and th
+// HCK1: = alloca i32,
+// HCK1: = alloca i32,
+// HCK1: [[I_CAST:%.+]] = alloca i{{32|64}},
+// HCK1: [[N_CAST:%.+]] = alloca i{{32|64}},
+// HCK1: [[TE_CAST:%.+]] = alloca i{{32|64}},
+// HCK1: [[TH_CAST:%.+]] = alloca i{{32|64}},
+// HCK1: [[I_PAR:%.+]] = load{{.+}}, {{.+}} [[I_CAST]],
+// HCK1: [[N_PAR:%.+]] = load{{.+}}, {{.+}} [[N_CAST]],
+// HCK1: [[TE_PAR:%.+]] = load{{.+}}, {{.+}} [[TE_CAST]],
+// HCK1: [[TH_PAR:%.+]] = load{{.+}}, {{.+}} [[TH_CAST]],
+// HCK1: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 5, i8** %{{[^,]+}}, i8** %{{[^,]+}},
+
+// HCK1: call void @[[OFFL1:.+]](i{{32|64}} [[I_PAR]], i{{32|64}} [[N_PAR]], {{.+}}, i{{32|64}} [[TE_PAR]], i{{32|64}} [[TH_PAR]])
+ int i;
+#pragma omp target teams distribute parallel for simd num_teams(te), thread_limit(th) aligned(a : 8) safelen(16) simdlen(4) linear(i : n)
+ for(i = 0; i < n; i++) {
+ a[i] = 0;
+ }
+
+ // HCK1: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 3, i8** %{{[^,]+}}, i8** %{{[^,]+}}, i{{64|32}}* {{.+}}@{{[^,]+}}, i32 0, i32 0), i64* {{.+}}@{{[^,]+}}, i32 0, i32 0),
+ // HCK1: call void @[[OFFL2:.+]](i{{64|32}} %{{.+}})
+ {{{
+ #pragma omp target teams distribute parallel for simd is_device_ptr(g) simdlen(8)
+ for(int i = 0; i < n; i++) {
+ a[i] = g[0];
+ }
+ }}}
+
+ // outlined target regions
+ // HCK1: define internal void @[[OFFL1]](i{{32|64}} [[I_ARG:%.+]], i{{32|64}} [[N_ARG:%.+]], {{.+}}, i{{32|64}} [[TE_ARG:%.+]], i{{32|64}} [[TH_ARG:%.+]])
+ // TCK1: define weak void @{{.+}}target_teams_fun{{.*}}(i{{32|64}} [[I_ARG:%.+]], i{{32|64}} [[N_ARG:%.+]], {{.+}}, i{{32|64}} [[TE_ARG:%.+]], i{{32|64}} [[TH_ARG:%.+]])
+ // CK1: [[I_ADDR:%.+]] = alloca i{{32|64}},
+ // CK1: [[N_ADDR:%.+]] = alloca i{{32|64}},
+ // CK1: [[TE_ADDR:%.+]] = alloca i{{32|64}},
+ // CK1: [[TH_ADDR:%.+]] = alloca i{{32|64}},
+ // TCK1: store {{.+}} [[N_ARG]], {{.+}} [[N_ADDR]],
+ // CK1: store{{.+}} [[TE_ARG]], {{.+}} [[TE_ADDR]],
+ // CK1: store{{.+}} [[TH_ARG]], {{.+}} [[TH_ADDR]],
+ // CK1-64: [[TE_CONV:%.+]] = bitcast{{.+}} [[TE_ADDR]] to
+ // CK1-64: [[TH_CONV:%.+]] = bitcast{{.+}} [[TH_ADDR]] to
+ // CK1-64: [[TE_VAL:%.+]] = load i32, i32* [[TE_CONV]],
+ // CK1-64: [[TH_VAL:%.+]] = load i32, i32* [[TH_CONV]],
+ // CK1-32: [[TE_VAL:%.+]] = load i32, i32* [[TE_ADDR]],
+ // CK1-32: [[TH_VAL:%.+]] = load i32, i32* [[TH_ADDR]],
+ // CK1: {{%.+}} = call i32 @__kmpc_push_num_teams({{.+}}, {{.+}}, i32 [[TE_VAL]], i32 [[TH_VAL]])
+ // CK1: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 3, {{.+}} @[[OUTL1:.+]] to {{.+}}, {{.+}}, {{.+}})
+ // CK1: ret void
+
+ // CK1: define internal void @[[OUTL1]]({{.+}})
+ // CK1: [[ARRDECAY:%.+]] = getelementptr inbounds [1000 x i32], [1000 x i32]* %{{.+}}, i32 0, i32 0
+ // CK1: [[ARR_CAST:%.+]] = ptrtoint i32* [[ARRDECAY]] to i{{32|64}}
+ // CK1: [[MASKED_PTR:%.+]] = and i{{32|64}} [[ARR_CAST]], 7
+ // CK1: [[COND:%.+]] = icmp eq i{{32|64}} [[MASKED_PTR]], 0
+ // CK1: call void @llvm.assume(i1 [[COND]])
+ // CK1: call void @__kmpc_for_static_init_4(
+ // CK1: call void {{.+}} @__kmpc_fork_call(
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ // HCK1: define internal void @[[OFFL2]](
+ // TCK1: define weak void @{{.+}}target_teams_fun{{.+}}(
+ // CK1: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 3, {{.+}} @[[OUTL2:.+]] to {{.+}}, {{.+}}, {{.+}})
+ // CK1: ret void
+
+ // CK1: define internal void @[[OUTL2]]({{.+}})
+ // CK1: call void @__kmpc_for_static_init_4(
+ // CK1: call void {{.+}} @__kmpc_fork_call(
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ return a[0];
+}
+
+// CK1-DAG: !{!"llvm.loop.vectorize.width", i32 4}
+// CK1-DAG: !{!"llvm.loop.vectorize.enable", i1 true}
+// CK1-DAG: !{!"llvm.loop.vectorize.width", i32 8}
+
+#endif // CK1
+#endif // HEADER
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen_registration.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen_registration.cpp
new file mode 100644
index 000000000000..76a7b4d0bd86
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen_registration.cpp
@@ -0,0 +1,472 @@
+// Test host codegen.
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+// Test target teams distribute parallel for simd codegen - host bc file has to be created first.
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s -check-prefix=TCHECK
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s -check-prefix=TCHECK
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s -check-prefix=TCHECK
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s -check-prefix=TCHECK
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
+// Check that no target code is emitted if no omptests flag was provided.
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s -check-prefix=CHECK-NTARGET
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// SIMD-ONLY2-NOT: {{__kmpc|__tgt}}
+
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+// CHECK-DAG: [[SA:%.+]] = type { [4 x i32] }
+// CHECK-DAG: [[SB:%.+]] = type { [8 x i32] }
+// CHECK-DAG: [[SC:%.+]] = type { [16 x i32] }
+// CHECK-DAG: [[SD:%.+]] = type { [32 x i32] }
+// CHECK-DAG: [[SE:%.+]] = type { [64 x i32] }
+// CHECK-DAG: [[ST1:%.+]] = type { [228 x i32] }
+// CHECK-DAG: [[ST2:%.+]] = type { [1128 x i32] }
+// CHECK-DAG: [[ENTTY:%.+]] = type { i8*, i8*, i[[SZ:32|64]], i32, i32 }
+// CHECK-DAG: [[DEVTY:%.+]] = type { i8*, i8*, [[ENTTY]]*, [[ENTTY]]* }
+// CHECK-DAG: [[DSCTY:%.+]] = type { i32, [[DEVTY]]*, [[ENTTY]]*, [[ENTTY]]* }
+
+// TCHECK: [[ENTTY:%.+]] = type { i8*, i8*, i[[SZ:32|64]], i32, i32 }
+
+// CHECK-DAG: $[[REGFN:\.omp_offloading\..+]] = comdat
+
+// CHECK-DAG: [[A1:@.+]] = internal global [[SA]]
+// CHECK-DAG: [[A2:@.+]] = global [[SA]]
+// CHECK-DAG: [[B1:@.+]] = global [[SB]]
+// CHECK-DAG: [[B2:@.+]] = global [[SB]]
+// CHECK-DAG: [[C1:@.+]] = internal global [[SC]]
+// CHECK-DAG: [[D1:@.+]] = global [[SD]]
+// CHECK-DAG: [[E1:@.+]] = global [[SE]]
+// CHECK-DAG: [[T1:@.+]] = global [[ST1]]
+// CHECK-DAG: [[T2:@.+]] = global [[ST2]]
+
+// CHECK-NTARGET-DAG: [[SA:%.+]] = type { [4 x i32] }
+// CHECK-NTARGET-DAG: [[SB:%.+]] = type { [8 x i32] }
+// CHECK-NTARGET-DAG: [[SC:%.+]] = type { [16 x i32] }
+// CHECK-NTARGET-DAG: [[SD:%.+]] = type { [32 x i32] }
+// CHECK-NTARGET-DAG: [[SE:%.+]] = type { [64 x i32] }
+// CHECK-NTARGET-DAG: [[ST1:%.+]] = type { [228 x i32] }
+// CHECK-NTARGET-DAG: [[ST2:%.+]] = type { [1128 x i32] }
+// CHECK-NTARGET-NOT: type { i8*, i8*, %
+// CHECK-NTARGET-NOT: type { i32, %
+
+// We have 7 target regions
+
+// CHECK-DAG: {{@.+}} = weak constant i8 0
+// TCHECK-NOT: {{@.+}} = weak constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+
+// CHECK-NTARGET-NOT: weak constant i8 0
+// CHECK-NTARGET-NOT: private unnamed_addr constant [1 x i
+
+// CHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
+// CHECK-DAG: [[ENTRY1:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
+// CHECK-DAG: [[ENTRY2:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
+// CHECK-DAG: [[ENTRY3:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
+// CHECK-DAG: [[ENTRY4:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
+// CHECK-DAG: [[ENTRY5:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
+// CHECK-DAG: [[ENTRY6:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
+// CHECK-DAG: [[ENTRY7:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
+// CHECK-DAG: [[ENTRY8:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
+// CHECK-DAG: [[ENTRY9:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
+// CHECK-DAG: [[ENTRY10:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
+// CHECK-DAG: [[ENTRY11:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
+// CHECK-DAG: [[ENTRY12:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+
+// TCHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
+// TCHECK-DAG: [[ENTRY1:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
+// TCHECK-DAG: [[ENTRY2:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
+// TCHECK-DAG: [[ENTRY3:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
+// TCHECK-DAG: [[ENTRY4:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
+// TCHECK-DAG: [[ENTRY5:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
+// TCHECK-DAG: [[ENTRY6:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
+// TCHECK-DAG: [[ENTRY7:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
+// TCHECK-DAG: [[ENTRY8:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
+// TCHECK-DAG: [[ENTRY9:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
+// TCHECK-DAG: [[ENTRY10:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
+// TCHECK-DAG: [[ENTRY11:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
+// TCHECK-DAG: [[ENTRY12:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+
+// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
+// CHECK: [[ENTEND:@.+]] = external constant [[ENTTY]]
+// CHECK: [[DEVBEGIN:@.+]] = external constant i8
+// CHECK: [[DEVEND:@.+]] = external constant i8
+// CHECK: [[IMAGES:@.+]] = internal unnamed_addr constant [1 x [[DEVTY]]] [{{.+}} { i8* [[DEVBEGIN]], i8* [[DEVEND]], [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }], comdat($[[REGFN]])
+// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
+
+// We have 4 initializers, one for the 500 priority, another one for 501, or more for the default priority, and the last one for the offloading registration function.
+// CHECK: @llvm.global_ctors = appending global [4 x { i32, void ()*, i8* }] [
+// CHECK-SAME: { i32, void ()*, i8* } { i32 500, void ()* [[P500:@[^,]+]], i8* null },
+// CHECK-SAME: { i32, void ()*, i8* } { i32 501, void ()* [[P501:@[^,]+]], i8* null },
+// CHECK-SAME: { i32, void ()*, i8* } { i32 65535, void ()* [[PMAX:@[^,]+]], i8* null },
+// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
+
+// CHECK-NTARGET: @llvm.global_ctors = appending global [3 x { i32, void ()*, i8* }] [
+
+extern int *R;
+
+struct SA {
+ int arr[4];
+ void foo() {
+ int a = *R;
+ a += 1;
+ *R = a;
+ }
+ SA() {
+ int a = *R;
+ a += 2;
+ *R = a;
+ }
+ ~SA() {
+ int a = *R;
+ a += 3;
+ *R = a;
+ }
+};
+
+struct SB {
+ int arr[8];
+ void foo() {
+ int a = *R;
+ #pragma omp target teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i)
+ a += 4;
+ *R = a;
+ }
+ SB() {
+ int a = *R;
+ a += 5;
+ *R = a;
+ }
+ ~SB() {
+ int a = *R;
+ a += 6;
+ *R = a;
+ }
+};
+
+struct SC {
+ int arr[16];
+ void foo() {
+ int a = *R;
+ a += 7;
+ *R = a;
+ }
+ SC() {
+ int a = *R;
+ #pragma omp target teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i)
+ a += 8;
+ *R = a;
+ }
+ ~SC() {
+ int a = *R;
+ a += 9;
+ *R = a;
+ }
+};
+
+struct SD {
+ int arr[32];
+ void foo() {
+ int a = *R;
+ a += 10;
+ *R = a;
+ }
+ SD() {
+ int a = *R;
+ a += 11;
+ *R = a;
+ }
+ ~SD() {
+ int a = *R;
+ #pragma omp target teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i)
+ a += 12;
+ *R = a;
+ }
+};
+
+struct SE {
+ int arr[64];
+ void foo() {
+ int a = *R;
+ #pragma omp target teams distribute parallel for simd if(target: 0)
+ for (int i = 0; i < 10; ++i)
+ a += 13;
+ *R = a;
+ }
+ SE() {
+ int a = *R;
+ #pragma omp target teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i)
+ a += 14;
+ *R = a;
+ }
+ ~SE() {
+ int a = *R;
+ #pragma omp target teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i)
+ a += 15;
+ *R = a;
+ }
+};
+
+template <int x>
+struct ST {
+ int arr[128 + x];
+ void foo() {
+ int a = *R;
+ #pragma omp target teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i)
+ a += 16 + x;
+ *R = a;
+ }
+ ST() {
+ int a = *R;
+ #pragma omp target teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i)
+ a += 17 + x;
+ *R = a;
+ }
+ ~ST() {
+ int a = *R;
+ #pragma omp target teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i)
+ a += 18 + x;
+ *R = a;
+ }
+};
+
+// We have to make sure we us all the target regions:
+//CHECK-DAG: define internal void @[[NAME1]](
+//CHECK-DAG: call void @[[NAME1]](
+//CHECK-DAG: define internal void @[[NAME2]](
+//CHECK-DAG: call void @[[NAME2]](
+//CHECK-DAG: define internal void @[[NAME3]](
+//CHECK-DAG: call void @[[NAME3]](
+//CHECK-DAG: define internal void @[[NAME4]](
+//CHECK-DAG: call void @[[NAME4]](
+//CHECK-DAG: define internal void @[[NAME5]](
+//CHECK-DAG: call void @[[NAME5]](
+//CHECK-DAG: define internal void @[[NAME6]](
+//CHECK-DAG: call void @[[NAME6]](
+//CHECK-DAG: define internal void @[[NAME7]](
+//CHECK-DAG: call void @[[NAME7]](
+//CHECK-DAG: define internal void @[[NAME8]](
+//CHECK-DAG: call void @[[NAME8]](
+//CHECK-DAG: define internal void @[[NAME9]](
+//CHECK-DAG: call void @[[NAME9]](
+//CHECK-DAG: define internal void @[[NAME10]](
+//CHECK-DAG: call void @[[NAME10]](
+//CHECK-DAG: define internal void @[[NAME11]](
+//CHECK-DAG: call void @[[NAME11]](
+//CHECK-DAG: define internal void @[[NAME12]](
+//CHECK-DAG: call void @[[NAME12]](
+
+//TCHECK-DAG: define weak void @[[NAME1]](
+//TCHECK-DAG: define weak void @[[NAME2]](
+//TCHECK-DAG: define weak void @[[NAME3]](
+//TCHECK-DAG: define weak void @[[NAME4]](
+//TCHECK-DAG: define weak void @[[NAME5]](
+//TCHECK-DAG: define weak void @[[NAME6]](
+//TCHECK-DAG: define weak void @[[NAME7]](
+//TCHECK-DAG: define weak void @[[NAME8]](
+//TCHECK-DAG: define weak void @[[NAME9]](
+//TCHECK-DAG: define weak void @[[NAME10]](
+//TCHECK-DAG: define weak void @[[NAME11]](
+//TCHECK-DAG: define weak void @[[NAME12]](
+
+// CHECK-NTARGET-NOT: __tgt_target
+// CHECK-NTARGET-NOT: __tgt_register_lib
+// CHECK-NTARGET-NOT: __tgt_unregister_lib
+
+// TCHECK-NOT: __tgt_target
+// TCHECK-NOT: __tgt_register_lib
+// TCHECK-NOT: __tgt_unregister_lib
+
+// We have 2 initializers with priority 500
+//CHECK: define internal void [[P500]](
+//CHECK: call void @{{.+}}()
+//CHECK: call void @{{.+}}()
+//CHECK-NOT: call void @{{.+}}()
+//CHECK: ret void
+
+// We have 1 initializers with priority 501
+//CHECK: define internal void [[P501]](
+//CHECK: call void @{{.+}}()
+//CHECK-NOT: call void @{{.+}}()
+//CHECK: ret void
+
+// We have 6 initializers with default priority
+//CHECK: define internal void [[PMAX]](
+//CHECK: call void @{{.+}}()
+//CHECK: call void @{{.+}}()
+//CHECK: call void @{{.+}}()
+//CHECK: call void @{{.+}}()
+//CHECK: call void @{{.+}}()
+//CHECK: call void @{{.+}}()
+//CHECK-NOT: call void @{{.+}}()
+//CHECK: ret void
+
+// Check registration and unregistration
+
+//CHECK: define internal void @[[UNREGFN:.+]](i8*)
+//CHECK-SAME: comdat($[[REGFN]]) {
+//CHECK: call i32 @__tgt_unregister_lib([[DSCTY]]* [[DESC]])
+//CHECK: ret void
+//CHECK: declare i32 @__tgt_unregister_lib([[DSCTY]]*)
+
+//CHECK: define linkonce hidden void @[[REGFN]]()
+//CHECK-SAME: comdat {
+//CHECK: call i32 @__tgt_register_lib([[DSCTY]]* [[DESC]])
+//CHECK: call i32 @__cxa_atexit(void (i8*)* @[[UNREGFN]], i8* bitcast ([[DSCTY]]* [[DESC]] to i8*),
+//CHECK: ret void
+//CHECK: declare i32 @__tgt_register_lib([[DSCTY]]*)
+
+static __attribute__((init_priority(500))) SA a1;
+SA a2;
+SB __attribute__((init_priority(500))) b1;
+SB __attribute__((init_priority(501))) b2;
+static SC c1;
+SD d1;
+SE e1;
+ST<100> t1;
+ST<1000> t2;
+
+
+int bar(int a){
+ int r = a;
+
+ a1.foo();
+ a2.foo();
+ b1.foo();
+ b2.foo();
+ c1.foo();
+ d1.foo();
+ e1.foo();
+ t1.foo();
+ t2.foo();
+
+ #pragma omp target teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i)
+ ++r;
+
+ return r + *R;
+}
+
+// Check metadata is properly generated:
+// CHECK: !omp_offload.info = !{!{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 216, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 268, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 286, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 293, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 305, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 312, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 436, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 319, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 312, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 319, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 305, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 242, i32 {{[0-9]+}}}
+
+// TCHECK: !omp_offload.info = !{!{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 216, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 268, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 286, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 293, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 305, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 312, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 436, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 319, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 312, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 319, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 305, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 242, i32 {{[0-9]+}}}
+
+#endif
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen_registration_naming.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen_registration_naming.cpp
new file mode 100644
index 000000000000..faeaeb949018
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen_registration_naming.cpp
@@ -0,0 +1,86 @@
+// Test host codegen.
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+// Test target teams distribute parallel for simd codegen - host bc file has to be created first.
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s -check-prefix=TCHECK
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s -check-prefix=TCHECK
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s -check-prefix=TCHECK
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s -check-prefix=TCHECK
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+// CHECK: [[CA:%.+]] = type { i32* }
+
+// CHECK: define {{.*}}i32 @[[NNAME:.+]](i32 {{.*}}%{{.+}})
+int nested(int a){
+ // CHECK: call void @__omp_offloading_[[FILEID:[0-9a-f]+_[0-9a-f]+]]_[[NNAME]]_l[[T1L:[0-9]+]](
+ #pragma omp target teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i)
+ ++a;
+
+ // CHECK: call void @"[[LNAME:.+]]"([[CA]]*
+ auto F = [&](){
+ #pragma omp parallel
+ {
+ #pragma omp target teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+ };
+
+ F();
+
+ return a;
+}
+
+// CHECK: define {{.*}}void @__omp_offloading_[[FILEID]]_[[NNAME]]_l[[T1L]](
+// TCHECK: define {{.*}}void @__omp_offloading_[[FILEID:[0-9a-f]+_[0-9a-f]+]]_[[NNAME:.+]]_l[[T1L:[0-9]+]](
+
+// CHECK: define {{.*}}void @"[[LNAME]]"(
+// CHECK: call void {{.*}}@__kmpc_fork_call{{.+}}[[PNAME:@.+]] to
+
+// CHECK: define {{.*}}void [[PNAME]](
+// CHECK: call void @__omp_offloading_[[FILEID]]_[[NNAME]]_l[[T2L:[0-9]+]](
+
+// CHECK: define {{.*}}void @__omp_offloading_[[FILEID]]_[[NNAME]]_l[[T2L]](
+// TCHECK: define {{.*}}void @__omp_offloading_[[FILEID]]_[[NNAME:.+]]_l[[T2L:[0-9]+]](
+
+
+// Check metadata is properly generated:
+// CHECK: !omp_offload.info = !{!{{[0-9]+}}, !{{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 {{-?[0-9]+}}, i32 {{-?[0-9]+}}, !"[[NNAME]]", i32 [[T1L]], i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 {{-?[0-9]+}}, i32 {{-?[0-9]+}}, !"[[NNAME]]", i32 [[T2L]], i32 {{[0-9]+}}}
+
+// TCHECK: !omp_offload.info = !{!{{[0-9]+}}, !{{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 {{-?[0-9]+}}, i32 {{-?[0-9]+}}, !"[[NNAME]]", i32 [[T1L]], i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 {{-?[0-9]+}}, i32 {{-?[0-9]+}}, !"[[NNAME]]", i32 [[T2L]], i32 {{[0-9]+}}}
+#endif
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_collapse_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_collapse_codegen.cpp
new file mode 100644
index 000000000000..3aca29165cd8
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_collapse_codegen.cpp
@@ -0,0 +1,157 @@
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+// Test host codegen.
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-64
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-64
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// SIMD-ONLY-NOT: {{__kmpc|__tgt}}
+#ifdef CK1
+
+template <typename T, int X, long long Y>
+struct SS{
+ T a[X][Y];
+
+ // CK1: define {{.*}}i32 @{{.+}}foo{{.+}}(
+ int foo(void) {
+
+ // CK1: call i32 @__tgt_target_teams(
+ // CK1: call void @[[OFFL1:.+]](
+ #pragma omp target teams distribute parallel for simd collapse(2)
+ for(int i = 0; i < X; i++) {
+ for(int j = 0; j < Y; j++) {
+ a[i][j] = (T)0;
+ }
+ }
+ // CK1: define internal void @[[OFFL1]](
+ // CK1: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[OUTL1:.+]] to {{.+}},
+ // CK1: ret void
+
+ // CK1: define internal void @[[OUTL1]]({{.+}})
+ // discard loop variables not needed here
+ // CK1: [[OMP_UB:%.omp.comb.ub]] = alloca i32,
+ // CK1: store i32 56087, i32* [[OMP_UB]],
+ // CK1: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 92, {{.+}}, {{.+}}, i32* [[OMP_UB]],
+ // CK1: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL1:.+]] to
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ // CK1: define internal void @[[PAR_OUTL1]]({{.+}})
+ // CK1: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 34, {{.+}}, {{.+}},
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ return a[0][0];
+ }
+};
+
+int teams_template_struct(void) {
+ SS<int, 123, 456> V;
+ return V.foo();
+
+}
+#endif // CK1
+
+// Test host codegen.
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-64
+// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-64
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// SIMD-ONLY-NOT: {{__kmpc|__tgt}}
+#ifdef CK2
+
+template <typename T, int n, int m>
+int tmain(T argc) {
+ T a[n][m];
+ #pragma omp target teams distribute parallel for simd collapse(2)
+ for(int i = 0; i < n; i++) {
+ for(int j = 0; j < m; j++) {
+ a[i][j] = (T)0;
+ }
+ }
+ return 0;
+}
+
+int main (int argc, char **argv) {
+ int n = 100;
+ int m = 2;
+ int a[n][m];
+ #pragma omp target teams distribute parallel for simd collapse(2)
+ for(int i = 0; i < n; i++) {
+ for(int j = 0; j < m; j++) {
+ a[i][j] = 0;
+ }
+ }
+ return tmain<int, 10, 2>(argc);
+}
+
+// CK2: define {{.*}}i32 @{{[^,]+}}(i{{.+}}{{.+}} %[[ARGC:.+]], {{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFL1:.+]]({{.+}})
+// CK2: {{%.+}} = call{{.*}} i32 @[[TMAIN:.+]]({{.+}})
+// CK2: ret
+
+// CK2: define {{.*}}void @[[OFFL1]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 5, {{.+}} @[[OUTL1:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTL1]]({{.+}})
+// CK2: [[OMP_UB:%.omp.comb.ub]] = alloca i64,
+// CK2: store i64 {{.+}}, i64* [[OMP_UB]],
+// CK2: call void @__kmpc_for_static_init_8({{.+}}, {{.+}}, i32 92, {{.+}}, {{.+}}, i64* [[OMP_UB]],
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL1:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTL1]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_{{[4|8]}}({{.+}}, {{.+}}, i32 34, {{.+}}, {{.+}},
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+
+// CK2: define {{.*}}i32 @[[TMAIN]]({{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFLT1:.+]]({{.+}})
+// CK2: ret
+// CK2-NEXT: }
+
+// CK2: define {{.*}}void @[[OFFLT1]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[OUTLT1:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTLT1]]({{.+}})
+// discard loop variables not needed here
+// CK2: [[OMP_UB:%.omp.comb.ub]] = alloca i32,
+// CK2: store i32 {{.+}}, i32* [[OMP_UB]],
+// CK2: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 92, {{.+}}, {{.+}}, i32* [[OMP_UB]],
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[TPAR_OUTL1:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[TPAR_OUTL1]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 34, {{.+}}, {{.+}},
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+#endif // CK2
+#endif // #ifndef HEADER
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_collapse_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_collapse_messages.cpp
index d0c8a5823cdd..069ea65ad29d 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_collapse_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_collapse_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp %s -std=c++98
// RUN: %clang_cc1 -verify -fopenmp %s -std=c++11
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -std=c++98
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -std=c++11
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_default_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_default_messages.cpp
index 7d07280d089d..a81aacea4af0 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_default_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_default_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo();
int main(int argc, char **argv) {
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_defaultmap_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_defaultmap_messages.cpp
index 6f0ea7e62fe8..c2c0e7be2130 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_defaultmap_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_defaultmap_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_depend_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_depend_codegen.cpp
new file mode 100644
index 000000000000..2a10ae872375
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_depend_codegen.cpp
@@ -0,0 +1,261 @@
+// Test host codegen.
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+// Test target codegen - host bc file has to be created first.
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+// CHECK-DAG: [[TT:%.+]] = type { i64, i8 }
+// CHECK-DAG: [[ENTTY:%.+]] = type { i8*, i8*, i[[SZ:32|64]], i32, i32 }
+// CHECK-DAG: [[DEVTY:%.+]] = type { i8*, i8*, [[ENTTY]]*, [[ENTTY]]* }
+// CHECK-DAG: [[DSCTY:%.+]] = type { i32, [[DEVTY]]*, [[ENTTY]]*, [[ENTTY]]* }
+
+// TCHECK: [[ENTTY:%.+]] = type { i8*, i8*, i{{32|64}}, i32, i32 }
+
+// CHECK-DAG: $[[REGFN:\.omp_offloading\..+]] = comdat
+
+// CHECK-DAG: [[SIZET:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 0, i[[SZ]] 4]
+// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 544, i64 800]
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = {{.*}}constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
+
+// Check if offloading descriptor is created.
+// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
+// CHECK: [[ENTEND:@.+]] = external constant [[ENTTY]]
+// CHECK: [[DEVBEGIN:@.+]] = external constant i8
+// CHECK: [[DEVEND:@.+]] = external constant i8
+// CHECK: [[IMAGES:@.+]] = internal unnamed_addr constant [1 x [[DEVTY]]] [{{.+}} { i8* [[DEVBEGIN]], i8* [[DEVEND]], [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }], comdat($[[REGFN]])
+// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
+
+// Check target registration is registered as a Ctor.
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
+
+
+template<typename tx, typename ty>
+struct TT{
+ tx X;
+ ty Y;
+};
+
+int global;
+extern int global;
+
+// CHECK: define {{.*}}[[FOO:@.+]](
+int foo(int n) {
+ int a = 0;
+ short aa = 0;
+ float b[10];
+ float bn[n];
+ double c[5][10];
+ double cn[5][n];
+ TT<long long, char> d;
+ static long *plocal;
+
+ // CHECK: [[ADD:%.+]] = add nsw i32
+ // CHECK: store i32 [[ADD]], i32* [[DEVICE_CAP:%.+]],
+ // CHECK: [[GEP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+ // CHECK: store i32 [[DEV]], i32* [[GEP]],
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[ID:@.+]], i32 [[GTID:%.+]], i32 1, i[[SZ]] {{20|40}}, i[[SZ]] 4, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY0:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY0:%.+]]*
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 1
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 2
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 3
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call void @__kmpc_omp_wait_deps(%struct.ident_t* [[ID]], i32 [[GTID]], i32 4, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: call void @__kmpc_omp_task_begin_if0(%struct.ident_t* [[ID]], i32 [[GTID]], i8* [[TASK]])
+ // CHECK: call i32 [[TASK_ENTRY0]](i32 [[GTID]], [[TASK_TY0]]* [[BC_TASK]])
+ // CHECK: call void @__kmpc_omp_task_complete_if0(%struct.ident_t* [[ID]], i32 [[GTID]], i8* [[TASK]])
+ #pragma omp target teams distribute parallel for simd device(global + a) depend(in: global) depend(out: a, b, cn[4])
+ for (int i = 0; i < 10; ++i) {
+ }
+
+ // CHECK: [[ADD:%.+]] = add nsw i32
+ // CHECK: store i32 [[ADD]], i32* [[DEVICE_CAP:%.+]],
+
+ // CHECK: [[BOOL:%.+]] = icmp ne i32 %{{.+}}, 0
+ // CHECK: br i1 [[BOOL]], label %[[THEN:.+]], label %[[ELSE:.+]]
+ // CHECK: [[THEN]]:
+ // CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP:%.+]], i32 0, i32 0
+ // CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P:%.+]], i32 0, i32 0
+ // CHECK-DAG: [[CBPADDR0:%.+]] = bitcast i8** [[BPADDR0]] to i[[SZ]]**
+ // CHECK-DAG: [[CPADDR0:%.+]] = bitcast i8** [[PADDR0]] to i[[SZ]]**
+ // CHECK-DAG: store i[[SZ]]* [[BP0:%[^,]+]], i[[SZ]]** [[CBPADDR0]]
+ // CHECK-DAG: store i[[SZ]]* [[BP0]], i[[SZ]]** [[CPADDR0]]
+
+ // CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 1
+ // CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P]], i32 0, i32 1
+ // CHECK-DAG: [[CBPADDR1:%.+]] = bitcast i8** [[BPADDR1]] to i[[SZ]]*
+ // CHECK-DAG: [[CPADDR1:%.+]] = bitcast i8** [[PADDR1]] to i[[SZ]]*
+ // CHECK-DAG: store i[[SZ]] [[BP1:%[^,]+]], i[[SZ]]* [[CBPADDR1]]
+ // CHECK-DAG: store i[[SZ]] [[BP1]], i[[SZ]]* [[CPADDR1]]
+ // CHECK-DAG: getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 0
+ // CHECK-DAG: getelementptr inbounds [2 x i8*], [2 x i8*]* [[P]], i32 0, i32 0
+ // CHECK: [[GEP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+ // CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+ // CHECK: store i32 [[DEV]], i32* [[GEP]],
+
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[ID]], i32 [[GTID]], i32 1, i[[SZ]] {{104|52}}, i[[SZ]] {{16|12}}, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY1_:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY1_:%.+]]*
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 1
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 2
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call i32 @__kmpc_omp_task_with_deps(%struct.ident_t* [[ID]], i32 [[GTID]], i8* [[TASK]], i32 3, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: br label %[[EXIT:.+]]
+
+ // CHECK: [[ELSE]]:
+ // CHECK-NOT: getelementptr inbounds [2 x i8*], [2 x i8*]*
+ // CHECK: [[GEP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+ // CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+ // CHECK: store i32 [[DEV]], i32* [[GEP]],
+
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[ID]], i32 [[GTID]], i32 1, i[[SZ]] {{56|28}}, i[[SZ]] {{16|12}}, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY1__:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY1__:%.+]]*
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 1
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 2
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call i32 @__kmpc_omp_task_with_deps(%struct.ident_t* [[ID]], i32 [[GTID]], i8* [[TASK]], i32 3, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: br label %[[EXIT:.+]]
+ // CHECK: [[EXIT]]:
+
+ #pragma omp target teams distribute parallel for simd device(global + a) nowait depend(inout: global, a, bn) if(target:a)
+ for (int i = 0; i < *plocal; ++i) {
+ static int local1;
+ *plocal = global;
+ local1 = global;
+ }
+
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[ID]], i32 [[GTID]], i32 1, i[[SZ]] {{48|24}}, i[[SZ]] 4, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY2:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY2:%.+]]*
+ // CHECK: getelementptr inbounds [1 x %struct.kmp_depend_info], [1 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [1 x %struct.kmp_depend_info], [1 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call void @__kmpc_omp_wait_deps(%struct.ident_t* [[ID]], i32 [[GTID]], i32 1, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: call void @__kmpc_omp_task_begin_if0(%struct.ident_t* [[ID]], i32 [[GTID]], i8* [[TASK]])
+ // CHECK: call i32 [[TASK_ENTRY2]](i32 [[GTID]], [[TASK_TY2]]* [[BC_TASK]])
+ // CHECK: call void @__kmpc_omp_task_complete_if0(%struct.ident_t* [[ID]], i32 [[GTID]], i8* [[TASK]])
+ #pragma omp target teams distribute parallel for simd if(0) firstprivate(global) depend(out:global)
+ for (int i = 0; i < global; ++i) {
+ global += 1;
+ }
+
+ return a;
+}
+
+// Check that the offloading functions are emitted and that the arguments are
+// correct and loaded correctly for the target regions in foo().
+
+// CHECK: define internal void [[HVT0:@.+]]()
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY0]](i32{{.*}}, [[TASK_TY0]]* noalias)
+// CHECK: store void (i8*, ...)* null, void (i8*, ...)** %
+// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 0
+// CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+// CHECK: [[DEVICE:%.+]] = sext i32 [[DEV]] to i64
+// CHECK: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 [[DEVICE]], i8* @{{[^,]+}}, i32 0, i8** null, i8** null, i[[SZ]]* null, i64* null, i32 0, i32 0)
+// CHECK-NEXT: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
+// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
+// CHECK: [[FAIL]]
+// CHECK: call void [[HVT0]]()
+// CHECK-NEXT: br label %[[END]]
+// CHECK: [[END]]
+// CHECK: ret i32 0
+
+// CHECK: define internal void [[HVT1:@.+]](i[[SZ]]* %{{.+}}, i[[SZ]] %{{.+}})
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY1_]](i32{{.*}}, [[TASK_TY1_]]* noalias)
+// CHECK: call void (i8*, ...) %
+// CHECK: [[SZT:%.+]] = getelementptr inbounds [2 x i[[SZ]]], [2 x i[[SZ]]]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+// CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+// CHECK: [[DEVICE:%.+]] = sext i32 [[DEV]] to i64
+// CHECK: [[RET:%.+]] = call i32 @__tgt_target_teams_nowait(i64 [[DEVICE]], i8* @{{[^,]+}}, i32 2, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SZT]], i64* getelementptr inbounds ([2 x i64], [2 x i64]* [[MAPT]], i32 0, i32 0), i32 0, i32 0)
+
+// CHECK: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
+// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
+// CHECK: [[FAIL]]
+// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
+// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
+// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
+// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
+// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
+// CHECK: [[BP1:%.+]] = load i[[SZ]], i[[SZ]]* [[BP1_PTR]],
+// CHECK: call void [[HVT1]](i[[SZ]]* [[BP0]], i[[SZ]] [[BP1]])
+// CHECK-NEXT: br label %[[END]]
+// CHECK: [[END]]
+// CHECK: ret i32 0
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY1__]](i32{{.*}}, [[TASK_TY1__]]* noalias)
+// CHECK: call void (i8*, ...) %
+// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
+// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
+// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
+// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
+// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
+// CHECK: [[BP1:%.+]] = load i[[SZ]], i[[SZ]]* [[BP1_PTR]],
+// CHECK: call void [[HVT1]](i[[SZ]]* [[BP0]], i[[SZ]] [[BP1]])
+// CHECK: ret i32 0
+
+// CHECK: define internal void [[HVT2:@.+]](i[[SZ]] %{{.+}})
+// Create stack storage and store argument in there.
+// CHECK: [[AA_ADDR:%.+]] = alloca i[[SZ]], align
+// CHECK: store i[[SZ]] %{{.+}}, i[[SZ]]* [[AA_ADDR]], align
+// CHECK-64: [[AA_CADDR:%.+]] = bitcast i[[SZ]]* [[AA_ADDR]] to i32*
+// CHECK-64: load i32, i32* [[AA_CADDR]], align
+// CHECK-32: load i32, i32* [[AA_ADDR]], align
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY2]](i32{{.*}}, [[TASK_TY2]]* noalias)
+// CHECK: call void (i8*, ...) %
+// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
+// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
+// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
+// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
+// CHECK: [[BP1:%.+]] = load i[[SZ]], i[[SZ]]* [[BP1_PTR]],
+// CHECK: call void [[HVT2]](i[[SZ]] [[BP1]])
+// CHECK: ret i32 0
+
+
+#endif
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_depend_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_depend_messages.cpp
index 4a9bf01e40bf..7cc0d412341a 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_depend_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_depend_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_device_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_device_messages.cpp
index 6a725797af6e..c7b3bc9098db 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_device_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_device_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_dist_schedule_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_dist_schedule_codegen.cpp
new file mode 100644
index 000000000000..281a8d742534
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_dist_schedule_codegen.cpp
@@ -0,0 +1,270 @@
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+// Test host codegen.
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-64
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-64
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// SIMD-ONLY-NOT: {{__kmpc|__tgt}}
+#ifdef CK1
+
+template <typename T, int X, long long Y>
+struct SS{
+ T a[X];
+ float b;
+ // CK1: define {{.*}}i32 @{{.+}}foo{{.+}}(
+ int foo(void) {
+
+ // CK1: call i32 @__tgt_target_teams(
+ // CK1: call void @[[OFFL1:.+]](
+ #pragma omp target teams distribute parallel for simd
+ for(int i = 0; i < X; i++) {
+ a[i] = (T)0;
+ }
+ // CK1: call i32 @__tgt_target_teams(
+ // CK1: call void @[[OFFL2:.+]](
+ #pragma omp target teams distribute parallel for simd dist_schedule(static)
+ for(int i = 0; i < X; i++) {
+ a[i] = (T)0;
+ }
+ // CK1: call i32 @__tgt_target_teams(
+ // CK1: call void @[[OFFL3:.+]](
+ #pragma omp target teams distribute parallel for simd dist_schedule(static, X/2)
+ for(int i = 0; i < X; i++) {
+ a[i] = (T)0;
+ }
+ // CK1: define internal void @[[OFFL1]](
+ // CK1: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[OUTL1:.+]] to {{.+}},
+ // CK1: ret void
+
+ // CK1: define internal void @[[OUTL1]]({{.+}})
+ // CK1: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 92
+ // CK1: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL1:.+]] to
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ // CK1: define internal void @[[PAR_OUTL1]]({{.+}})
+ // CK1: call void @__kmpc_for_static_init_4(
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ // CK1: define internal void @[[OFFL2]](
+ // CK1: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[OUTL2:.+]] to {{.+}},
+ // CK1: ret void
+
+ // CK1: define internal void @[[OUTL2]]({{.+}})
+ // CK1: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 92
+ // CK1: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL2:.+]] to
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ // CK1: define internal void @[[PAR_OUTL2]]({{.+}})
+ // CK1: call void @__kmpc_for_static_init_4(
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+
+ // CK1: define internal void @[[OFFL3]](
+ // CK1: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[OUTL3:.+]] to {{.+}},
+ // CK1: ret void
+
+ // CK1: define internal void @[[OUTL3]]({{.+}})
+ // CK1: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 91
+ // CK1: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL3:.+]] to
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ // CK1: define internal void @[[PAR_OUTL3]]({{.+}})
+ // CK1: call void @__kmpc_for_static_init_4(
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ return a[0];
+ }
+};
+
+int teams_template_struct(void) {
+ SS<int, 123, 456> V;
+ return V.foo();
+
+}
+#endif // CK1
+
+// Test host codegen.
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-64
+// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-64
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// SIMD-ONLY-NOT: {{__kmpc|__tgt}}
+#ifdef CK2
+
+template <typename T, int n>
+int tmain(T argc) {
+ T a[n];
+ int m = 10;
+#pragma omp target teams distribute parallel for simd
+ for(int i = 0; i < n; i++) {
+ a[i] = (T)0;
+ }
+#pragma omp target teams distribute parallel for simd dist_schedule(static)
+ for(int i = 0; i < n; i++) {
+ a[i] = (T)0;
+ }
+#pragma omp target teams distribute parallel for simd dist_schedule(static, m)
+ for(int i = 0; i < n; i++) {
+ a[i] = (T)0;
+ }
+ return 0;
+}
+
+int main (int argc, char **argv) {
+ int n = 100;
+ int a[n];
+ int m = 10;
+#pragma omp target teams distribute parallel for simd
+ for(int i = 0; i < n; i++) {
+ a[i] = 0;
+ }
+#pragma omp target teams distribute parallel for simd dist_schedule(static)
+ for(int i = 0; i < n; i++) {
+ a[i] = 0;
+ }
+#pragma omp target teams distribute parallel for simd dist_schedule(static, m)
+ for(int i = 0; i < n; i++) {
+ a[i] = 0;
+ }
+ return tmain<int, 10>(argc);
+}
+
+// CK2: define {{.*}}i32 @{{[^,]+}}(i{{.+}}{{.+}} %[[ARGC:.+]], {{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFL1:.+]]({{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFL2:.+]]({{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFL3:.+]]({{.+}})
+// CK2: {{%.+}} = call{{.*}} i32 @[[TMAIN:.+]]({{.+}})
+// CK2: ret
+
+// CK2: define {{.*}}void @[[OFFL1]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 3, {{.+}} @[[OUTL1:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTL1]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 92
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL1:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTL1]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4(
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define {{.*}}void @[[OFFL2]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 3, {{.+}} @[[OUTL2:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTL2]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 92
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL2:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTL2]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4(
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define {{.*}}void @[[OFFL3]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 4, {{.+}} @[[OUTL3:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTL3]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 91
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL3:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTL3]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4(
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define {{.*}}i32 @[[TMAIN]]({{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFLT1:.+]]({{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFLT2:.+]]({{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFLT3:.+]]({{.+}})
+// CK2: ret
+// CK2-NEXT: }
+
+// CK2: define {{.*}}void @[[OFFLT1]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[OUTLT1:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTLT1]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 92
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTLT1:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTLT1]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4(
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define {{.*}}void @[[OFFLT2]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[OUTLT2:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTLT2]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 92
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTLT2:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTLT2]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4(
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define {{.*}}void @[[OFFLT3]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 {{.+}}, {{.+}} @[[OUTLT3:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTLT3]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 91
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTLT3:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTLT3]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4(
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+#endif // CK2
+#endif // #ifndef HEADER
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_dist_schedule_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_dist_schedule_messages.cpp
index 4fb37532f095..079aaf69f556 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_dist_schedule_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_dist_schedule_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_firstprivate_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_firstprivate_codegen.cpp
new file mode 100644
index 000000000000..0b09cc6c4027
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_firstprivate_codegen.cpp
@@ -0,0 +1,523 @@
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 --check-prefix HCHECK --check-prefix HCHECK-64
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 --check-prefix HCHECK --check-prefix HCHECK-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix HCHECK --check-prefix HCHECK-32
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix HCHECK --check-prefix HCHECK-32
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64 --check-prefix HLAMBDA --check-prefix HLAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64 --check-prefix HLAMBDA --check-prefix HLAMBDA-64
+
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+
+// Test target codegen - host bc file has to be created first. (no significant differences with host version of target region)
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix TCHECK --check-prefix TCHECK-32
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64 --check-prefix TLAMBDA --check-prefix TLAMBDA-64
+
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix SIMD-ONLY
+// SIMD-ONLY-NOT: {{__kmpc|__tgt}}
+
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+struct St {
+ int a, b;
+ St() : a(0), b(0) {}
+ St(const St &st) : a(st.a + st.b), b(0) {}
+ ~St() {}
+};
+
+volatile int g = 1212;
+volatile int &g1 = g;
+
+template <class T>
+struct S {
+ T f;
+ S(T a) : f(a + g) {}
+ S() : f(g) {}
+ S(const S &s, St t = St()) : f(s.f + t.a) {}
+ operator T() { return T(); }
+ ~S() {}
+};
+
+// CHECK-DAG: [[S_FLOAT_TY:%.+]] = type { float }
+// CHECK-DAG: [[S_INT_TY:%.+]] = type { i{{[0-9]+}} }
+// CHECK-DAG: [[ST_TY:%.+]] = type { i{{[0-9]+}}, i{{[0-9]+}} }
+
+template <typename T>
+T tmain() {
+ S<T> test;
+ T t_var = T();
+ T vec[] = {1, 2};
+ S<T> s_arr[] = {1, 2};
+ S<T> &var = test;
+#pragma omp target teams distribute parallel for simd firstprivate(t_var, vec, s_arr, var)
+ for (int i = 0; i < 2; ++i) {
+ vec[i] = t_var;
+ s_arr[i] = var;
+ }
+ return T();
+}
+
+// HCHECK-DAG: [[TEST:@.+]] = global [[S_FLOAT_TY]] zeroinitializer,
+S<float> test;
+// HCHECK-DAG: [[T_VAR:@.+]] = global i{{[0-9]+}} 333,
+int t_var = 333;
+// HCHECK-DAG: [[VEC:@.+]] = global [2 x i{{[0-9]+}}] [i{{[0-9]+}} 1, i{{[0-9]+}} 2],
+int vec[] = {1, 2};
+// HCHECK-DAG: [[S_ARR:@.+]] = global [2 x [[S_FLOAT_TY]]] zeroinitializer,
+S<float> s_arr[] = {1, 2};
+// HCHECK-DAG: [[VAR:@.+]] = global [[S_FLOAT_TY]] zeroinitializer,
+S<float> var(3);
+// HCHECK-DAG: [[SIVAR:@.+]] = internal global i{{[0-9]+}} 0,
+
+int main() {
+ static int sivar;
+#ifdef LAMBDA
+ // HLAMBDA: [[G:@.+]] = global i{{[0-9]+}} 1212,
+ // HLAMBDA-LABEL: @main
+ // HLAMBDA: call void [[OUTER_LAMBDA:@.+]](
+ [&]() {
+ // HLAMBDA: define{{.*}} internal{{.*}} void [[OUTER_LAMBDA]](
+ // HLAMBDA: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 3, i8** %{{[^,]+}}, i8** %{{[^,]+}}, i{{64|32}}* {{.+}}@{{[^,]+}}, i32 0, i32 0), i64* {{.+}}@{{[^,]+}}, i32 0, i32 0), i32 0, i32 0)
+ // HLAMBDA: call void @[[LOFFL1:.+]](i{{64|32}} %{{.+}})
+ // HLAMBDA: ret
+#pragma omp target teams distribute parallel for simd firstprivate(g, g1, sivar)
+ for (int i = 0; i < 2; ++i) {
+ // HLAMBDA: define{{.*}} internal{{.*}} void @[[LOFFL1]](i{{64|32}} {{%.+}}, i{{64|32}} {{%.+}})
+ // TLAMBDA: define weak void @[[LOFFL1:.+]](i{{64|32}} {{%.+}}, i{{64|32}} {{%.+}})
+ // LAMBDA: {{%.+}} = alloca i{{[0-9]+}},
+ // LAMBDA: {{%.+}} = alloca i{{[0-9]+}},
+ // LAMBDA: {{%.+}} = alloca i{{[0-9]+}},
+ // LAMBDA: [[G_CAST:%.+]] = alloca i{{[0-9]+}},
+ // LAMBDA: [[G1_CAST:%.+]] = alloca i{{[0-9]+}},
+ // LAMBDA: [[SIVAR_CAST:%.+]] = alloca i{{[0-9]+}},
+ // LAMBDA-DAG: [[G_CAST_VAL:%.+]] = load{{.+}} [[G_CAST]],
+ // LAMBDA-DAG: [[G1_CAST_VAL:%.+]] = load{{.+}} [[G1_CAST]],
+ // LAMBDA-DAG: [[SIVAR_CAST_VAL:%.+]] = load{{.+}} [[SIVAR_CAST]],
+ // LAMBDA: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 3, {{.+}} @[[LOUTL1:.+]] to {{.+}}, {{.+}} [[G_CAST_VAL]], {{.+}} [[G1_CAST_VAL]], {{.+}} [[SIVAR_CAST_VAL]])
+ // LAMBDA: ret void
+
+ // LAMBDA: define internal void @[[LOUTL1]]({{.+}})
+ // Skip global and bound tid vars
+ // LAMBDA: {{.+}} = alloca i32*,
+ // LAMBDA: {{.+}} = alloca i32*,
+ // LAMBDA: [[G_ADDR:%.+]] = alloca i{{[0-9]+}},
+ // LAMBDA: [[G1_ADDR:%.+]] = alloca i{{[0-9]+}},
+ // LAMBDA: [[SIVAR_ADDR:%.+]] = alloca i{{[0-9]+}},
+ // LAMBDA: [[G1_TMP:%.+]] = alloca i32*,
+ // skip loop vars
+ // LAMBDA-DAG: store {{.+}}, {{.+}} [[G_ADDR]],
+ // LAMBDA-DAG: store {{.+}}, {{.+}} [[G1_ADDR]],
+ // LAMBDA-DAG: store {{.+}}, {{.+}} [[SIVAR_ADDR]],
+ // LAMBDA-DAG: [[G_CONV:%.+]] = bitcast {{.+}} [[G_ADDR]] to
+ // LAMBDA-DAG: [[G1_CONV:%.+]] = bitcast {{.+}} [[G1_ADDR]] to
+ // LAMBDA-DAG: [[SIVAR_CONV:%.+]] = bitcast {{.+}} [[SIVAR_ADDR]] to
+ // LAMBDA-DAG: store{{.+}} [[G1_CONV]], {{.+}} [[G1_TMP]],
+ g = 1;
+ g1 = 1;
+ sivar = 2;
+ // LAMBDA: call void @__kmpc_for_static_init_4(
+ // LAMBDA: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[LPAR_OUTL:.+]] to
+ // LAMBDA: call void @__kmpc_for_static_fini(
+ // LAMBDA: ret void
+
+ // LAMBDA: define internal void @[[LPAR_OUTL]]({{.+}})
+ // Skip global and bound tid vars, and prev lb and ub vars
+ // LAMBDA: {{.+}} = alloca i32*,
+ // LAMBDA: {{.+}} = alloca i32*,
+ // LAMBDA: {{.+}} = alloca i{{[0-9]+}},
+ // LAMBDA: {{.+}} = alloca i{{[0-9]+}},
+ // LAMBDA: [[G_ADDR:%.+]] = alloca i{{[0-9]+}},
+ // LAMBDA: [[G1_ADDR:%.+]] = alloca i{{[0-9]+}},
+ // LAMBDA: [[SIVAR_ADDR:%.+]] = alloca i{{[0-9]+}},
+ // LAMBDA: [[G1_TMP:%.+]] = alloca i32*,
+ // skip loop vars
+ // LAMBDA-DAG: store {{.+}}, {{.+}} [[G_ADDR]],
+ // LAMBDA-DAG: store {{.+}}, {{.+}} [[G1_ADDR]],
+ // LAMBDA-DAG: store {{.+}}, {{.+}} [[SIVAR_ADDR]],
+ // LAMBDA-DAG: [[G_CONV:%.+]] = bitcast {{.+}} [[G_ADDR]] to
+ // LAMBDA-DAG: [[G1_CONV:%.+]] = bitcast {{.+}} [[G1_ADDR]] to
+ // LAMBDA-DAG: [[SIVAR_CONV:%.+]] = bitcast {{.+}} [[SIVAR_ADDR]] to
+ // LAMBDA-DAG: store{{.+}} [[G1_CONV]], {{.+}} [[G1_TMP]],
+
+ // use of private vars
+ // LAMBDA-DAG: store{{.+}} 1, {{.+}} [[G_CONV]],
+ // LAMBDA-DAG: [[G1:%.+]] = load{{.+}}, {{.+}}* [[G1_TMP]]
+ // LAMBDA-DAG: store{{.+}} 1, {{.+}} [[G1]],
+ // LAMBDA-DAG: store{{.+}} 2, {{.+}} [[SIVAR_CONV]],
+ // LAMBDA-DAG: [[G1_REF:%.+]] = load{{.+}}, {{.+}} [[G1_TMP]],
+ // LAMBDA: call void [[INNER_LAMBDA:@.+]](
+ // LAMBDA: call void @__kmpc_for_static_fini(
+ // LAMBDA: ret void
+ [&]() {
+ // LAMBDA: define {{.+}} void [[INNER_LAMBDA]](%{{.+}}* [[ARG_PTR:%.+]])
+ // LAMBDA: store %{{.+}}* [[ARG_PTR]], %{{.+}}** [[ARG_PTR_REF:%.+]],
+ g = 2;
+ g1 = 2;
+ sivar = 4;
+ // LAMBDA: [[ARG_PTR:%.+]] = load %{{.+}}*, %{{.+}}** [[ARG_PTR_REF]]
+
+ // LAMBDA: [[G_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
+ // LAMBDA: [[G_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[G_PTR_REF]]
+ // LAMBDA: store i{{[0-9]+}} 2, i{{[0-9]+}}* [[G_REF]]
+ // LAMBDA: [[G1_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 1
+ // LAMBDA: [[G1_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[G1_PTR_REF]]
+ // LAMBDA: store i{{[0-9]+}} 2, i{{[0-9]+}}* [[G1_REF]]
+ // LAMBDA: [[SIVAR_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 2
+ // LAMBDA: [[SIVAR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SIVAR_PTR_REF]]
+ // LAMBDA: store i{{[0-9]+}} 4, i{{[0-9]+}}* [[SIVAR_REF]]
+ }();
+ }
+ }();
+ return 0;
+#else
+#pragma omp target teams distribute parallel for simd firstprivate(t_var, vec, s_arr, var, sivar)
+ for (int i = 0; i < 2; ++i) {
+ vec[i] = t_var;
+ s_arr[i] = var;
+ sivar += i;
+ }
+ return tmain<int>();
+#endif
+}
+
+// HCHECK: define {{.*}}i{{[0-9]+}} @main()
+// HCHECK: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 5,
+// HCHECK: call void @[[OFFL1:.+]](
+// HCHECK: {{%.+}} = call{{.*}} i32 @[[TMAIN_INT:.+]]()
+// HCHECK: ret
+
+// HCHECK: define{{.*}} void @[[OFFL1]](
+// TCHECK: define{{.*}} void @[[OFFL1:.+]](
+// CHECK-DAG: [[T_VAR_PRIV:%.+]] = alloca i{{[0-9]+}},
+// CHECK-DAG: [[VEC_PRIV:%.+]] = alloca [2 x i{{[0-9]+}}]*,
+// CHECK-DAG: [[S_ARR_PRIV:%.+]] = alloca [2 x [[S_FLOAT_TY]]]*,
+// CHECK-DAG: [[VAR_PRIV:%.+]] = alloca [[S_FLOAT_TY]]*,
+// CHECK: [[SIVAR_PRIV:%.+]] = alloca i{{[0-9]+}},
+// CHECK: [[T_VAR_CAST:%.+]] = alloca i{{[0-9]+}},
+// CHECK: [[SIVAR_CAST:%.+]] = alloca i{{[0-9]+}},
+
+// CHECK-DAG: [[VEC_TE_PAR:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_PRIV]],
+// CHECK-DAG: [[T_VAR_TE_PAR:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[T_VAR_CAST]],
+// CHECK-DAG: [[S_ARR_TE_PAR:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[S_ARR_PRIV]],
+// CHECK-DAG: [[VAR_TE_PAR:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[VAR_PRIV]],
+// CHECK-DAG: [[SIVAR_TE_PAR:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SIVAR_CAST]],
+
+// CHECK: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 5, {{.+}} @[[OUTL1:.+]] to {{.+}}, [2 x i{{[0-9]+}}]* [[VEC_TE_PAR]], i{{[0-9]+}} [[T_VAR_TE_PAR]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_TE_PAR]], [[S_FLOAT_TY]]* [[VAR_TE_PAR]], i{{[0-9]+}} [[SIVAR_TE_PAR]])
+// CHECK: ret void
+
+// CHECK: define internal void @[[OUTL1]]({{.+}})
+// Skip global and bound tid vars
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: [[VEC_ADDR:%.+]] = alloca [2 x i{{[0-9]+}}]*,
+// CHECK: [[T_VAR_ADDR:%.+]] = alloca i{{[0-9]+}},
+// CHECK: [[S_ARR_ADDR:%.+]] = alloca [2 x [[S_FLOAT_TY]]]*,
+// CHECK: [[VAR_ADDR:%.+]] = alloca [[S_FLOAT_TY]]*,
+// CHECK: [[SIVAR_ADDR:%.+]] = alloca i{{[0-9]+}},
+// Skip temp vars for loop
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: [[VEC_PRIV:%.+]] = alloca [2 x i{{[0-9]+}}],
+// CHECK: [[S_ARR_PRIV:%.+]] = alloca [2 x [[S_FLOAT_TY]]],
+// CHECK: [[AGG_TMP1:%.+]] = alloca [[ST_TY]],
+// CHECK: [[VAR_PRIV:%.+]] = alloca [[S_FLOAT_TY]],
+// CHECK: [[AGG_TMP2:%.+]] = alloca [[ST_TY]],
+
+// param copy
+// CHECK: store [2 x i{{[0-9]+}}]* {{.+}}, [2 x i{{[0-9]+}}]** [[VEC_ADDR]],
+// CHECK: store i{{[0-9]+}} {{.+}}, i{{[0-9]+}}* [[T_VAR_ADDR]],
+// CHECK: store [2 x [[S_FLOAT_TY]]]* {{.+}}, [2 x [[S_FLOAT_TY]]]** [[S_ARR_ADDR]],
+// CHECK: store [[S_FLOAT_TY]]* {{.+}}, [[S_FLOAT_TY]]** [[VAR_ADDR]],
+// CHECK: store i{{[0-9]+}} {{.+}}, i{{[0-9]+}}* [[SIVAR_ADDR]],
+
+// T_VAR and SIVAR
+// CHECK-64-DAG: [[CONV_TVAR:%.+]] = bitcast i64* [[T_VAR_ADDR]] to i32*
+// CHECK-64-DAG: [[CONV_SIVAR:%.+]] = bitcast i64* [[SIVAR_ADDR]] to i32*
+
+// preparation vars
+// CHECK-DAG: [[VEC_ADDR_VAL:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]],
+// CHECK-DAG: [[S_ARR_ADDR_REF:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[S_ARR_ADDR]],
+// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load{{.+}} [[VAR_ADDR]],
+
+// firstprivate vec(vec): copy from *_addr into priv1 and then from priv1 into priv2
+// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
+// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8*
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST_PRIV]], i8* align {{[0-9]+}} [[VEC_SRC]], {{.+}})
+
+// firstprivate(s_arr)
+// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]],
+// CHECK-DAG: [[S_ARR_ADDR_BGN:%.+]] = bitcast [2 x [[S_FLOAT_TY]]]* [[S_ARR_ADDR_REF]] to
+// CHECK-DAG: [[S_ARR_FIN:%.+]] = icmp{{.+}} [[S_ARR_PRIV_BGN]],
+// CHECK-DAG: [[S_ARR_SRC_COPY:%.+]] = phi{{.+}} [ [[S_ARR_ADDR_BGN]], {{.+}} ], [ [[S_ARR_SRC:%.+]], {{.+}} ]
+// CHECK-DAG: [[S_ARR_DST_COPY:%.+]] = phi{{.+}} [ [[S_ARR_PRIV_BGN]], {{.+}}], [ [[S_ARR_DST:%.+]], {{.+}} ]
+// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP1]])
+// CHECK-DAG: call void @{{.+}}({{.+}} [[S_ARR_DST_COPY]], {{.+}} [[S_ARR_SRC_COPY]], {{.+}} [[AGG_TMP1]])
+// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP1]])
+// CHECK-DAG: [[S_ARR_DST]] = getelementptr {{.+}} [[S_ARR_DST_COPY]],
+// CHECK-DAG: [[S_ARR_SRC]] = getelementptr {{.+}} [[S_ARR_SRC_COPY]],
+
+// firstprivate(var)
+// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]])
+// CHECK-DAG: call void @{{.+}}({{.+}} [[VAR_PRIV]], {{.+}} [[VAR_ADDR_REF]], {{.+}} [[AGG_TMP2]])
+// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]])
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL:.+]] to
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: ret void
+
+// CHECK: define internal void @[[PAR_OUTL]]({{.+}})
+// Skip global and bound tid vars, and prev lb ub vars
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: [[VEC_ADDR:%.+]] = alloca [2 x i{{[0-9]+}}]*,
+// CHECK: [[T_VAR_ADDR:%.+]] = alloca i{{[0-9]+}},
+// CHECK: [[S_ARR_ADDR:%.+]] = alloca [2 x [[S_FLOAT_TY]]]*,
+// CHECK: [[VAR_ADDR:%.+]] = alloca [[S_FLOAT_TY]]*,
+// CHECK: [[SIVAR_ADDR:%.+]] = alloca i{{[0-9]+}},
+// Skip temp vars for loop
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: [[VEC_PRIV:%.+]] = alloca [2 x i{{[0-9]+}}],
+// CHECK: [[S_ARR_PRIV:%.+]] = alloca [2 x [[S_FLOAT_TY]]],
+// CHECK: [[AGG_TMP1:%.+]] = alloca [[ST_TY]],
+// CHECK: [[VAR_PRIV:%.+]] = alloca [[S_FLOAT_TY]],
+// CHECK: [[AGG_TMP2:%.+]] = alloca [[ST_TY]],
+
+// param copy
+// CHECK: store [2 x i{{[0-9]+}}]* {{.+}}, [2 x i{{[0-9]+}}]** [[VEC_ADDR]],
+// CHECK: store i{{[0-9]+}} {{.+}}, i{{[0-9]+}}* [[T_VAR_ADDR]],
+// CHECK: store [2 x [[S_FLOAT_TY]]]* {{.+}}, [2 x [[S_FLOAT_TY]]]** [[S_ARR_ADDR]],
+// CHECK: store [[S_FLOAT_TY]]* {{.+}}, [[S_FLOAT_TY]]** [[VAR_ADDR]],
+// CHECK: store i{{[0-9]+}} {{.+}}, i{{[0-9]+}}* [[SIVAR_ADDR]],
+
+// T_VAR and SIVAR
+// CHECK-64-DAG: [[CONV_TVAR:%.+]] = bitcast i64* [[T_VAR_ADDR]] to i32*
+// CHECK-64-DAG: [[CONV_SIVAR:%.+]] = bitcast i64* [[SIVAR_ADDR]] to i32*
+
+// preparation vars
+// CHECK-DAG: [[VEC_ADDR_VAL:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]],
+// CHECK-DAG: [[S_ARR_ADDR_REF:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[S_ARR_ADDR]],
+// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load{{.+}} [[VAR_ADDR]],
+
+// firstprivate vec(vec): copy from *_addr into priv1 and then from priv1 into priv2
+// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
+// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8*
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST_PRIV]], i8* align {{[0-9]+}} [[VEC_SRC]], {{.+}})
+
+// firstprivate(s_arr)
+// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]],
+// CHECK-DAG: [[S_ARR_ADDR_BGN:%.+]] = bitcast [2 x [[S_FLOAT_TY]]]* [[S_ARR_ADDR_REF]] to
+// CHECK-DAG: [[S_ARR_FIN:%.+]] = icmp{{.+}} [[S_ARR_PRIV_BGN]],
+// CHECK-DAG: [[S_ARR_SRC_COPY:%.+]] = phi{{.+}} [ [[S_ARR_ADDR_BGN]], {{.+}} ], [ [[S_ARR_SRC:%.+]], {{.+}} ]
+// CHECK-DAG: [[S_ARR_DST_COPY:%.+]] = phi{{.+}} [ [[S_ARR_PRIV_BGN]], {{.+}}], [ [[S_ARR_DST:%.+]], {{.+}} ]
+// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP1]])
+// CHECK-DAG: call void @{{.+}}({{.+}} [[S_ARR_DST_COPY]], {{.+}} [[S_ARR_SRC_COPY]], {{.+}} [[AGG_TMP1]])
+// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP1]])
+// CHECK-DAG: [[S_ARR_DST]] = getelementptr {{.+}} [[S_ARR_DST_COPY]],
+// CHECK-DAG: [[S_ARR_SRC]] = getelementptr {{.+}} [[S_ARR_SRC_COPY]],
+
+// firstprivate(var)
+// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]])
+// CHECK-DAG: call void @{{.+}}({{.+}} [[VAR_PRIV]], {{.+}} [[VAR_ADDR_REF]], {{.+}} [[AGG_TMP2]])
+// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]])
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK-32-DAG: {{.+}} = {{.+}} [[T_VAR_ADDR]]
+// CHECK-64-DAG: {{.+}} = {{.+}} [[CONV_TVAR]]
+// CHECK-DAG: {{.+}} = {{.+}} [[VEC_PRIV]]
+// CHECK-DAG: {{.+}} = {{.+}} [[S_ARR_PRIV]]
+// CHECK-DAG: {{.+}} = {{.+}} [[VAR_PRIV]]
+// CHECK-32-DAG: {{.+}} = {{.+}} [[SIVAR_ADDR]]
+// CHECK-64-DAG: {{.+}} = {{.+}} [[CONV_SIVAR]]
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: ret void
+
+// HCHECK: define{{.*}} i{{[0-9]+}} @[[TMAIN_INT]]()
+// HCHECK: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 4, i8** %{{[^,]+}}, i8** %{{[^,]+}}, i{{64|32}}* {{.+}}@{{[^,]+}}, i32 0, i32 0), i64* {{.+}}@{{[^,]+}}, i32 0, i32 0), i32 0, i32 0)
+// HCHECK: call void @[[TOFFL1:.+]](
+// HCHECK: ret
+
+// HCHECK: define {{.*}}void @[[TOFFL1]]({{.+}})
+// TCHECK: define {{.*}}void @[[TOFFL1:.+]]({{.+}})
+// CHECK-DAG: [[TT_VAR_PRIV:%.+]] = alloca i{{[0-9]+}},
+// CHECK-DAG: [[TVEC_PRIV:%.+]] = alloca [2 x i{{[0-9]+}}]*,
+// CHECK-DAG: [[TS_ARR_PRIV:%.+]] = alloca [2 x [[S_INT_TY]]]*,
+// CHECK-DAG: [[TVAR_PRIV:%.+]] = alloca [[S_INT_TY]]*,
+// CHECK: [[TT_VAR_CAST:%.+]] = alloca i{{[0-9]+}},
+
+// CHECK-DAG: [[TVEC_TE_PAR:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[TVEC_PRIV]],
+// CHECK-DAG: [[TT_VAR_TE_PAR:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[TT_VAR_CAST]],
+// CHECK-DAG: [[TS_ARR_TE_PAR:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[TS_ARR_PRIV]],
+// CHECK-DAG: [[TVAR_TE_PAR:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TVAR_PRIV]],
+
+// CHECK: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 4, {{.+}} @[[TOUTL1:.+]] to {{.+}}, [2 x i{{[0-9]+}}]* [[TVEC_TE_PAR]], i{{[0-9]+}} [[TT_VAR_TE_PAR]], [2 x [[S_INT_TY]]]* [[TS_ARR_TE_PAR]], [[S_INT_TY]]* [[TVAR_TE_PAR]])
+// CHECK: ret void
+
+// CHECK: define internal void @[[TOUTL1]]({{.+}})
+// Skip global and bound tid vars
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: [[VEC_ADDR:%.+]] = alloca [2 x i{{[0-9]+}}]*,
+// CHECK: [[T_VAR_ADDR:%.+]] = alloca i{{[0-9]+}},
+// CHECK: [[S_ARR_ADDR:%.+]] = alloca [2 x [[S_INT_TY]]]*,
+// CHECK: [[VAR_ADDR:%.+]] = alloca [[S_INT_TY]]*,
+// Skip temp vars for loop
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: [[VEC_PRIV:%.+]] = alloca [2 x i{{[0-9]+}}],
+// CHECK: [[S_ARR_PRIV:%.+]] = alloca [2 x [[S_INT_TY]]],
+// CHECK: [[AGG_TMP1:%.+]] = alloca [[ST_TY]],
+// CHECK: [[VAR_PRIV:%.+]] = alloca [[S_INT_TY]],
+// CHECK: [[AGG_TMP2:%.+]] = alloca [[ST_TY]],
+// CHECK: [[TMP:%.+]] = alloca [[S_INT_TY]]*,
+
+// param copy
+// CHECK: store [2 x i{{[0-9]+}}]* {{.+}}, [2 x i{{[0-9]+}}]** [[VEC_ADDR]],
+// CHECK: store i{{[0-9]+}} {{.+}}, i{{[0-9]+}}* [[T_VAR_ADDR]],
+// CHECK: store [2 x [[S_INT_TY]]]* {{.+}}, [2 x [[S_INT_TY]]]** [[S_ARR_ADDR]],
+// CHECK: store [[S_INT_TY]]* {{.+}}, [[S_INT_TY]]** [[VAR_ADDR]],
+
+// T_VAR and preparation variables
+// CHECK: [[VEC_ADDR_VAL:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]],
+// CHECK-64: [[CONV_TVAR:%.+]] = bitcast i64* [[T_VAR_ADDR]] to i32*
+// CHECK: [[S_ARR_ADDR_REF:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[S_ARR_ADDR]],
+
+// firstprivate vec(vec): copy from *_addr into priv1 and then from priv1 into priv2
+// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
+// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8*
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST_PRIV]], i8* align {{[0-9]+}} [[VEC_SRC]], {{.+}})
+
+// firstprivate(s_arr)
+// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_PRIV]],
+// CHECK-DAG: [[S_ARR_ADDR_BGN:%.+]] = bitcast [2 x [[S_INT_TY]]]* [[S_ARR_ADDR_REF]] to
+// CHECK-DAG: [[S_ARR_FIN:%.+]] = icmp{{.+}} [[S_ARR_PRIV_BGN]],
+// CHECK-DAG: [[S_ARR_SRC_COPY:%.+]] = phi{{.+}} [ [[S_ARR_ADDR_BGN]], {{.+}} ], [ [[S_ARR_SRC:%.+]], {{.+}} ]
+// CHECK-DAG: [[S_ARR_DST_COPY:%.+]] = phi{{.+}} [ [[S_ARR_PRIV_BGN]], {{.+}} ], [ [[S_ARR_DST:%.+]], {{.+}} ]
+// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP1]])
+// CHECK-DAG: call void @{{.+}}({{.+}} [[S_ARR_DST_COPY]], {{.+}} [[S_ARR_SRC_COPY]], {{.+}} [[AGG_TMP1]])
+// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP1]])
+// CHECK-DAG: [[S_ARR_DST]] = getelementptr {{.+}} [[S_ARR_DST_COPY]],
+// CHECK-DAG: [[S_ARR_SRC]] = getelementptr {{.+}} [[S_ARR_SRC_COPY]],
+
+// firstprivate(var)
+// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load{{.+}} [[VAR_ADDR]],
+// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]])
+// CHECK-DAG: call void @{{.+}}({{.+}} [[VAR_PRIV]], {{.+}} [[VAR_ADDR_REF]], {{.+}} [[AGG_TMP2]])
+// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]])
+// CHECK-DAG: store [[S_INT_TY]]* [[VAR_PRIV]], [[S_INT_TY]]** [[TMP]],
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[TPAR_OUTL:.+]] to
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: ret void
+
+// CHECK: define internal void @[[TPAR_OUTL]]({{.+}})
+// Skip global and bound tid vars
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: [[VEC_ADDR:%.+]] = alloca [2 x i{{[0-9]+}}]*,
+// CHECK: [[T_VAR_ADDR:%.+]] = alloca i{{[0-9]+}},
+// CHECK: [[S_ARR_ADDR:%.+]] = alloca [2 x [[S_INT_TY]]]*,
+// CHECK: [[VAR_ADDR:%.+]] = alloca [[S_INT_TY]]*,
+// Skip temp vars for loop
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: [[VEC_PRIV:%.+]] = alloca [2 x i{{[0-9]+}}],
+// CHECK: [[S_ARR_PRIV:%.+]] = alloca [2 x [[S_INT_TY]]],
+// CHECK: [[AGG_TMP1:%.+]] = alloca [[ST_TY]],
+// CHECK: [[VAR_PRIV:%.+]] = alloca [[S_INT_TY]],
+// CHECK: [[AGG_TMP2:%.+]] = alloca [[ST_TY]],
+// CHECK: [[TMP:%.+]] = alloca [[S_INT_TY]]*,
+
+// param copy
+// CHECK: store [2 x i{{[0-9]+}}]* {{.+}}, [2 x i{{[0-9]+}}]** [[VEC_ADDR]],
+// CHECK: store i{{[0-9]+}} {{.+}}, i{{[0-9]+}}* [[T_VAR_ADDR]],
+// CHECK: store [2 x [[S_INT_TY]]]* {{.+}}, [2 x [[S_INT_TY]]]** [[S_ARR_ADDR]],
+// CHECK: store [[S_INT_TY]]* {{.+}}, [[S_INT_TY]]** [[VAR_ADDR]],
+
+// T_VAR and preparation variables
+// CHECK: [[VEC_ADDR_VAL:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]],
+// CHECK-64: [[CONV_TVAR:%.+]] = bitcast i64* [[T_VAR_ADDR]] to i32*
+// CHECK: [[S_ARR_ADDR_REF:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[S_ARR_ADDR]],
+
+// firstprivate vec(vec): copy from *_addr into priv1 and then from priv1 into priv2
+// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
+// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8*
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST_PRIV]], i8* align {{[0-9]+}} [[VEC_SRC]], {{.+}})
+
+// firstprivate(s_arr)
+// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_PRIV]],
+// CHECK-DAG: [[S_ARR_ADDR_BGN:%.+]] = bitcast [2 x [[S_INT_TY]]]* [[S_ARR_ADDR_REF]] to
+// CHECK-DAG: [[S_ARR_FIN:%.+]] = icmp{{.+}} [[S_ARR_PRIV_BGN]],
+// CHECK-DAG: [[S_ARR_SRC_COPY:%.+]] = phi{{.+}} [ [[S_ARR_ADDR_BGN]], {{.+}} ], [ [[S_ARR_SRC:%.+]], {{.+}} ]
+// CHECK-DAG: [[S_ARR_DST_COPY:%.+]] = phi{{.+}} [ [[S_ARR_PRIV_BGN]], {{.+}} ], [ [[S_ARR_DST:%.+]], {{.+}} ]
+// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP1]])
+// CHECK-DAG: call void @{{.+}}({{.+}} [[S_ARR_DST_COPY]], {{.+}} [[S_ARR_SRC_COPY]], {{.+}} [[AGG_TMP1]])
+// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP1]])
+// CHECK-DAG: [[S_ARR_DST]] = getelementptr {{.+}} [[S_ARR_DST_COPY]],
+// CHECK-DAG: [[S_ARR_SRC]] = getelementptr {{.+}} [[S_ARR_SRC_COPY]],
+
+// firstprivate(var)
+// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load{{.+}} [[VAR_ADDR]],
+// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]])
+// CHECK-DAG: call void @{{.+}}({{.+}} [[VAR_PRIV]], {{.+}} [[VAR_ADDR_REF]], {{.+}} [[AGG_TMP2]])
+// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]])
+// CHECK-DAG: store [[S_INT_TY]]* [[VAR_PRIV]], [[S_INT_TY]]** [[TMP]],
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK-32-DAG: {{.+}} = {{.+}} [[T_VAR_ADDR]]
+// CHECK-64-DAG: {{.+}} = {{.+}} [[CONV_TVAR]]
+// CHECK-DAG: {{.+}} = {{.+}} [[VEC_PRIV]]
+// CHECK-DAG: {{.+}} = {{.+}} [[TMP]]
+// CHECK-DAG: {{.+}} = {{.+}} [[S_ARR_PRIV]]
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: ret void
+
+#endif
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_firstprivate_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_firstprivate_messages.cpp
index 4790b4bffdaf..69292a7c6183 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_firstprivate_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_firstprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_if_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_if_codegen.cpp
new file mode 100644
index 000000000000..a3a14fbf1e68
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_if_codegen.cpp
@@ -0,0 +1,181 @@
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple %itanium_abi_triple -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple %itanium_abi_triple -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple %itanium_abi_triple -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple %itanium_abi_triple -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// SIMD-ONLY-NOT: {{__kmpc|__tgt}}
+
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+void fn1();
+void fn2();
+void fn3();
+void fn4();
+void fn5();
+void fn6();
+
+int Arg;
+
+// CHECK-LABEL: define {{.*}}void @{{.+}}gtid_test
+void gtid_test() {
+// CHECK: call i{{[0-9]+}} @__tgt_target_teams(
+// CHECK: call void [[OFFLOADING_FUN_0:@.+]](
+// CHECK: call i{{[0-9]+}} @__tgt_target_teams(
+// CHECK: call void [[OFFLOADING_FUN_1:@.+]](
+#pragma omp target teams distribute parallel for simd
+ for(int i = 0 ; i < 100; i++) {}
+ // CHECK: define internal void [[OFFLOADING_FUN_0]](
+ // CHECK: call {{.*}}void {{.+}} @__kmpc_fork_teams({{.+}}, i32 0, {{.+}}* [[OMP_TEAMS_OUTLINED_0:@.+]] to {{.+}})
+ // CHECK: define{{.+}} void [[OMP_TEAMS_OUTLINED_0]](
+ // CHECK: call void @__kmpc_for_static_init_4(
+ // CHECK: call void {{.+}} @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{.+}} 2, {{.+}}* [[OMP_OUTLINED_0:@.+]] to void
+ // CHECK: call void @__kmpc_for_static_fini(
+
+ // CHECK: define{{.+}} void [[OMP_OUTLINED_0]](
+ // CHECK: call void @__kmpc_for_static_init_4(
+ // CHECK: call void @__kmpc_for_static_fini(
+ // CHECK: ret
+#pragma omp target teams distribute parallel for simd if (parallel: false)
+ for(int i = 0 ; i < 100; i++) {
+ // CHECK: define internal void [[OFFLOADING_FUN_1]](
+ // CHECK: call {{.*}}void {{.+}} @__kmpc_fork_teams({{.+}}, i32 0, {{.+}}* [[OMP_TEAMS_OUTLINED_1:@.+]] to {{.+}})
+ // CHECK: define{{.+}} void [[OMP_TEAMS_OUTLINED_1]](
+ // CHECK: call void @__kmpc_for_static_init_4(
+ // CHECK: call void @__kmpc_serialized_parallel(
+ // CHECK: call void [[OMP_OUTLINED_1:@.+]](
+ // CHECK: call void @__kmpc_end_serialized_parallel(
+ // CHECK: call void @__kmpc_for_static_fini(
+ // CHECK: define{{.+}} void [[OMP_OUTLINED_1]](
+ // CHECK: call void @__kmpc_for_static_init_4(
+ // CHECK: call void @{{.+}}gtid_test
+ // CHECK: call void @__kmpc_for_static_fini(
+ // CHECK: ret
+ gtid_test();
+ }
+}
+
+
+template <typename T>
+int tmain(T Arg) {
+#pragma omp target teams distribute parallel for simd if (true)
+ for(int i = 0 ; i < 100; i++) {
+ fn1();
+ }
+#pragma omp target teams distribute parallel for simd if (false)
+ for(int i = 0 ; i < 100; i++) {
+ fn2();
+ }
+#pragma omp target teams distribute parallel for simd if (parallel: Arg)
+ for(int i = 0 ; i < 100; i++) {
+ fn3();
+ }
+ return 0;
+}
+
+// CHECK-LABEL: define {{.*}}i{{[0-9]+}} @main()
+int main() {
+// CHECK: call i{{[0-9]+}} @__tgt_target_teams(
+// CHECK: call void [[OFFLOADING_FUN_0:@.+]](
+// CHECK: call void [[OFFLOADING_FUN_1:@.+]](
+// CHECK: call i{{[0-9]+}} @__tgt_target_teams(
+// CHECK: call void [[OFFLOADING_FUN_2:@.+]](
+// CHECK: = call {{.*}}i{{.+}} @{{.+}}tmain
+#pragma omp target teams distribute parallel for simd if (true)
+ for(int i = 0 ; i < 100; i++) {
+ // CHECK: define internal void [[OFFLOADING_FUN_0]](
+ // CHECK: call {{.*}}void {{.+}} @__kmpc_fork_teams({{.+}}, i32 0, {{.+}}* [[OMP_TEAMS_OUTLINED_0:@.+]] to {{.+}})
+ // CHECK: define{{.+}} void [[OMP_TEAMS_OUTLINED_0]](
+
+ // CHECK: call void @__kmpc_for_static_init_4(
+ // CHECK: call void {{.+}} @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{.+}} 2, {{.+}}* [[OMP_OUTLINED_2:@.+]] to void
+ // CHECK: call void @__kmpc_for_static_fini(
+ // CHECK: define{{.+}} void [[OMP_OUTLINED_2]](
+ // CHECK: call void @__kmpc_for_static_init_4(
+ // CHECK: call {{.*}}void @{{.+}}fn4
+ // CHECK: call void @__kmpc_for_static_fini(
+
+ fn4();
+ }
+
+#pragma omp target teams distribute parallel for simd if (false)
+ for(int i = 0 ; i < 100; i++) {
+ // CHECK: define internal void [[OFFLOADING_FUN_1]](
+ // CHECK: call {{.*}}void {{.+}} @__kmpc_fork_teams({{.+}}, i32 0, {{.+}}* [[OMP_TEAMS_OUTLINED_1:@.+]] to {{.+}})
+ // CHECK: define{{.+}} void [[OMP_TEAMS_OUTLINED_1]](
+
+ // CHECK: call void @__kmpc_for_static_init_4(
+ // CHECK: call void @__kmpc_serialized_parallel(
+ // CHECK: call void [[OMP_OUTLINED_3:@.+]](
+ // CHECK: call void @__kmpc_end_serialized_parallel(
+ // CHECK: call void @__kmpc_for_static_fini(
+
+ // CHECK: define{{.+}} void [[OMP_OUTLINED_3]](
+ // CHECK: call void @__kmpc_for_static_init_4(
+ // CHECK: call {{.*}}void @{{.+}}fn5
+ // CHECK: call void @__kmpc_for_static_fini(
+ fn5();
+ }
+
+#pragma omp target teams distribute parallel for simd if (Arg)
+ for(int i = 0 ; i < 100; i++) {
+ // CHECK: define internal void [[OFFLOADING_FUN_2]](
+ // CHECK: call {{.*}}void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}}* [[OMP_TEAMS_OUTLINED_2:@.+]] to {{.+}})
+ // CHECK: define{{.+}} void [[OMP_TEAMS_OUTLINED_2]](
+
+ // CHECK: call void @__kmpc_for_static_init_4(
+ // CHECK: call void {{.+}} @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{.+}} 2, {{.+}}* [[OMP_OUTLINED_4:@.+]] to void
+ // CHECK: call void @__kmpc_serialized_parallel(
+ // CHECK: call void [[OMP_OUTLINED_4:@.+]](
+ // CHECK: call void @__kmpc_end_serialized_parallel(
+ // CHECK: call void @__kmpc_for_static_fini(
+
+ // CHECK: define{{.+}} void [[OMP_OUTLINED_4]](
+ // CHECK: call void @__kmpc_for_static_init_4(
+ // CHECK: call {{.*}}void @{{.+}}fn6
+ // CHECK: call void @__kmpc_for_static_fini(
+ fn6();
+ }
+
+ return tmain(Arg);
+}
+
+// CHECK-LABEL: define {{.+}} @{{.+}}tmain
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call {{.*}}void {{.+}} @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{.+}} 2, void {{.+}}* [[T_OUTLINE_FUN_1:@.+]] to void
+// CHECK: call void @__kmpc_for_static_fini(
+
+// CHECK: define internal {{.*}}void [[T_OUTLINE_FUN_1]]
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call {{.*}}void @{{.+}}fn1
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: ret void
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call {{.*}}void @__kmpc_serialized_parallel(
+// CHECK: call void [[T_OUTLINE_FUN_2:@.+]](
+// CHECK: call {{.*}}void @__kmpc_end_serialized_parallel(
+// CHECK: call void @__kmpc_for_static_fini(
+
+// CHECK: define internal {{.*}}void [[T_OUTLINE_FUN_2]]
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call {{.*}}void @{{.+}}fn2
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: ret void
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call {{.*}}void {{.+}} @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{.+}} 2, void {{.+}}* [[T_OUTLINE_FUN_3:@.+]] to void
+// CHECK: call {{.*}}void @__kmpc_serialized_parallel(
+// call void [[T_OUTLINE_FUN_3:@.+]](
+// CHECK: call {{.*}}void @__kmpc_end_serialized_parallel(
+
+// CHECK: define internal {{.*}}void [[T_OUTLINE_FUN_3]]
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call {{.*}}void @{{.+}}fn3
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: ret void
+#endif
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_if_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_if_messages.cpp
index 96db02eea7a3..7554e5bc0590 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_if_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_if_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_is_device_ptr_ast_print.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_is_device_ptr_ast_print.cpp
index e73f40ef1ccf..510751967230 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_is_device_ptr_ast_print.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_is_device_ptr_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -56,7 +60,7 @@ struct SA {
// CHECK-NEXT: int aa[10];
// CHECK-NEXT: arr &raa = this->aa;
// CHECK-NEXT: func(
-// CHECK-NEXT: #pragma omp target teams distribute parallel for simd is_device_ptr(this->k)
+// CHECK-NEXT: #pragma omp target teams distribute parallel for simd is_device_ptr(this->k){{$}}
// CHECK-NEXT: for (int i = 0; i < 100; i++)
// CHECK-NEXT: ;
// CHECK-NEXT: #pragma omp target teams distribute parallel for simd is_device_ptr(this->z)
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_is_device_ptr_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_is_device_ptr_messages.cpp
index 520f746efdd5..57abff3fb48e 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_is_device_ptr_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_is_device_ptr_messages.cpp
@@ -1,4 +1,6 @@
// RUN: %clang_cc1 -std=c++11 -verify -fopenmp %s
+
+// RUN: %clang_cc1 -std=c++11 -verify -fopenmp-simd %s
struct ST {
int *a;
};
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_codegen.cpp
new file mode 100644
index 000000000000..c3d38612d63d
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_codegen.cpp
@@ -0,0 +1,456 @@
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// SIMD-ONLY-NOT: {{__kmpc|__tgt}}
+
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+template <class T>
+struct S {
+ T f;
+ S(T a) : f(a) {}
+ S() : f() {}
+ operator T() { return T(); }
+ ~S() {}
+};
+
+// CHECK: [[S_FLOAT_TY:%.+]] = type { float }
+// CHECK: [[S_INT_TY:%.+]] = type { i{{[0-9]+}} }
+template <typename T>
+T tmain() {
+ S<T> test;
+ T t_var = T();
+ T vec[] = {1, 2};
+ S<T> s_arr[] = {1, 2};
+ S<T> &var = test;
+ #pragma omp target teams distribute parallel for simd lastprivate(t_var, vec, s_arr, s_arr, var, var)
+ for (int i = 0; i < 2; ++i) {
+ vec[i] = t_var;
+ s_arr[i] = var;
+ }
+ return T();
+}
+
+int main() {
+ static int svar;
+ volatile double g;
+ volatile double &g1 = g;
+
+ #ifdef LAMBDA
+ // LAMBDA-LABEL: @main
+ // LAMBDA: call{{.*}} void [[OUTER_LAMBDA:@.+]](
+ [&]() {
+ static float sfvar;
+ // LAMBDA: define{{.*}} internal{{.*}} void [[OUTER_LAMBDA]](
+ // LAMBDA: call i{{[0-9]+}} @__tgt_target_teams(
+ // LAMBDA: call void [[OFFLOADING_FUN:@.+]](
+
+ // LAMBDA: define{{.+}} void [[OFFLOADING_FUN]](
+ // LAMBDA: call {{.*}}void {{.+}} @__kmpc_fork_teams({{.+}}, i32 4, {{.+}}* [[OMP_OUTLINED:@.+]] to {{.+}})
+ #pragma omp target teams distribute parallel for simd lastprivate(g, g1, svar, sfvar)
+ for (int i = 0; i < 2; ++i) {
+ // LAMBDA: define{{.*}} internal{{.*}} void [[OMP_OUTLINED]](i32* {{.+}}, i32* {{.+}}, {{.+}} [[G1_IN:%.+]], {{.+}} [[SVAR_IN:%.+]], {{.+}} [[SFVAR_IN:%.+]], {{.+}} [[G_IN:%.+]])
+ // skip gbl and bound tid
+ // LAMBDA: alloca
+ // LAMBDA: alloca
+ // LAMBDA: [[G1_ADDR:%.+]] = alloca {{.+}},
+ // LAMBDA: [[SVAR_ADDR:%.+]] = alloca {{.+}},
+ // LAMBDA: [[SFVAR_ADDR:%.+]] = alloca {{.+}},
+ // LAMBDA: [[G_ADDR:%.+]] = alloca {{.+}},
+ // LAMBDA-64: [[G1_REF:%.+]] = alloca double*,
+ // loop variables
+ // LAMBDA: {{.+}} = alloca i{{[0-9]+}},
+ // LAMBDA: {{.+}} = alloca i{{[0-9]+}},
+ // LAMBDA: {{.+}} = alloca i{{[0-9]+}},
+ // LAMBDA: {{.+}} = alloca i{{[0-9]+}},
+ // LAMBDA: {{.+}} = alloca i{{[0-9]+}},
+ // LAMBDA: [[OMP_IS_LAST:%.+]] = alloca i{{[0-9]+}},
+
+ // LAMBDA-DAG: store {{.+}} [[G_IN]], {{.+}} [[G_ADDR]],
+ // LAMBDA-DAG: store {{.+}} [[G1_IN]], {{.+}} [[G1_ADDR]],
+ // LAMBDA-DAG: store {{.+}} [[SVAR_IN]], {{.+}} [[SVAR_ADDR]],
+ // LAMBDA-DAG: store {{.+}} [[SFVAR_IN]], {{.+}} [[SFVAR_ADDR]],
+
+ // LAMBDA-64-DAG: [[G_TGT:%.+]] = bitcast {{.+}} [[G_ADDR]] to
+ // LAMBDA-32-DAG: [[G_TGT:%.+]] = load {{.+}}, {{.+}} [[G_ADDR]],
+ // LAMBDA-64-DAG: [[G1_TGT:%.+]] = load {{.+}}, {{.+}} [[G1_REF]],
+ // LAMBDA-32-DAG: [[G1_TGT:%.+]] = load {{.+}}, {{.+}} [[G1_ADDR]],
+ // LAMBDA-64-DAG: [[SVAR_TGT:%.+]] = bitcast {{.+}} [[SVAR_ADDR]] to
+ // LAMBDA-DAG: [[SFVAR_TGT:%.+]] = bitcast {{.+}} [[SFVAR_ADDR]] to
+
+ g1 = 1;
+ svar = 3;
+ sfvar = 4.0;
+ // LAMBDA: call {{.*}}void @__kmpc_for_static_init_4(
+ // LAMBDA: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[LPAR_OUTL:.+]] to
+ // LAMBDA: call {{.*}}void @__kmpc_for_static_fini(
+
+ // LAMBDA: store i32 2, i32* %
+ // LAMBDA: [[OMP_IS_LAST_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[OMP_IS_LAST]],
+ // LAMBDA: [[IS_LAST_IT:%.+]] = icmp ne i{{[0-9]+}} [[OMP_IS_LAST_VAL]], 0
+ // LAMBDA: br i1 [[IS_LAST_IT]], label %[[OMP_LASTPRIV_BLOCK:.+]], label %[[OMP_LASTPRIV_DONE:.+]]
+
+ // LAMBDA: [[OMP_LASTPRIV_BLOCK]]:
+ // LAMBDA-DAG: store {{.+}}, {{.+}} [[G_TGT]],
+ // LAMBDA-DAG: store {{.+}}, {{.+}} [[G1_TGT]],
+ // LAMBDA-64-DAG: store {{.+}}, {{.+}} [[SVAR_TGT]],
+ // LAMBDA-32-DAG: store {{.+}}, {{.+}} [[SVAR_ADDR]],
+ // LAMBDA-DAG: store {{.+}}, {{.+}} [[SFVAR_TGT]],
+ // LAMBDA: br label %[[OMP_LASTPRIV_DONE]]
+ // LAMBDA: [[OMP_LASTPRIV_DONE]]:
+ // LAMBDA: ret
+
+ // LAMBDA: define{{.*}} internal{{.*}} void @[[LPAR_OUTL]](i32* noalias %{{.+}}, i32* noalias %{{.+}}, {{.+}}, {{.+}}, {{.+}} [[G1_IN:%.+]], {{.+}} [[SVAR_IN:%.+]], {{.+}} [[SFVAR_IN:%.+]], {{.+}} [[G_IN:%.+]])
+ // skip tid and prev variables
+ // LAMBDA: alloca
+ // LAMBDA: alloca
+ // LAMBDA: alloca
+ // LAMBDA: alloca
+ // LAMBDA: [[G1_ADDR:%.+]] = alloca {{.+}},
+ // LAMBDA: [[SVAR_ADDR:%.+]] = alloca {{.+}},
+ // LAMBDA: [[SFVAR_ADDR:%.+]] = alloca {{.+}},
+ // LAMBDA: [[G_ADDR:%.+]] = alloca {{.+}},
+ // LAMBDA-64: [[G1_REF:%.+]] = alloca double*,
+ // loop variables
+ // LAMBDA: {{.+}} = alloca i{{[0-9]+}},
+ // LAMBDA: {{.+}} = alloca i{{[0-9]+}},
+ // LAMBDA: {{.+}} = alloca i{{[0-9]+}},
+ // LAMBDA: {{.+}} = alloca i{{[0-9]+}},
+ // LAMBDA: {{.+}} = alloca i{{[0-9]+}},
+ // LAMBDA: [[OMP_IS_LAST:%.+]] = alloca i{{[0-9]+}},
+
+ // LAMBDA-DAG: store {{.+}} [[G_IN]], {{.+}} [[G_ADDR]],
+ // LAMBDA-DAG: store {{.+}} [[G1_IN]], {{.+}} [[G1_ADDR]],
+ // LAMBDA-DAG: store {{.+}} [[SVAR_IN]], {{.+}} [[SVAR_ADDR]],
+ // LAMBDA-DAG: store {{.+}} [[SFVAR_IN]], {{.+}} [[SFVAR_ADDR]],
+
+ // LAMBDA-64-DAG: [[G_TGT:%.+]] = bitcast {{.+}} [[G_ADDR]] to
+ // LAMBDA-32-DAG: [[G_TGT:%.+]] = load {{.+}}, {{.+}} [[G_ADDR]],
+ // LAMBDA-64-DAG: [[G1_TGT:%.+]] = load {{.+}}, {{.+}} [[G1_REF]],
+ // LAMBDA-32-DAG: [[G1_TGT:%.+]] = load {{.+}}, {{.+}} [[G1_ADDR]],
+ // LAMBDA-64-DAG: [[SVAR_TGT:%.+]] = bitcast {{.+}} [[SVAR_ADDR]] to
+ // LAMBDA-DAG: [[SFVAR_TGT:%.+]] = bitcast {{.+}} [[SFVAR_ADDR]] to
+
+
+ // LAMBDA: call {{.*}}void @__kmpc_for_static_init_4(
+ // LAMBDA: call{{.*}} void [[INNER_LAMBDA:@.+]](
+ // LAMBDA: call {{.*}}void @__kmpc_for_static_fini(
+
+ // LAMBDA: store i32 2, i32* %
+ // LAMBDA: [[OMP_IS_LAST_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[OMP_IS_LAST]],
+ // LAMBDA: [[IS_LAST_IT:%.+]] = icmp ne i{{[0-9]+}} [[OMP_IS_LAST_VAL]], 0
+ // LAMBDA: br i1 [[IS_LAST_IT]], label %[[OMP_LASTPRIV_BLOCK:.+]], label %[[OMP_LASTPRIV_DONE:.+]]
+
+ // LAMBDA: [[OMP_LASTPRIV_BLOCK]]:
+ // LAMBDA-DAG: store {{.+}}, {{.+}} [[G_TGT]],
+ // LAMBDA-DAG: store {{.+}}, {{.+}} [[G1_TGT]],
+ // LAMBDA-64-DAG: store {{.+}}, {{.+}} [[SVAR_TGT]],
+ // LAMBDA-32-DAG: store {{.+}}, {{.+}} [[SVAR_ADDR]],
+ // LAMBDA-DAG: store {{.+}}, {{.+}} [[SFVAR_TGT]],
+ // LAMBDA: br label %[[OMP_LASTPRIV_DONE]]
+ // LAMBDA: [[OMP_LASTPRIV_DONE]]:
+ // LAMBDA: ret
+
+ [&]() {
+ // LAMBDA: define {{.+}} void [[INNER_LAMBDA]](%{{.+}}* [[ARG_PTR:%.+]])
+ // LAMBDA: store %{{.+}}* [[ARG_PTR]], %{{.+}}** [[ARG_PTR_REF:%.+]],
+ g = 2;
+ g1 = 2;
+ svar = 4;
+ sfvar = 8.0;
+ // LAMBDA: [[ARG_PTR:%.+]] = load %{{.+}}*, %{{.+}}** [[ARG_PTR_REF]]
+ // LAMBDA: [[G_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
+ // LAMBDA: [[G_REF:%.+]] = load double*, double** [[G_PTR_REF]]
+ // LAMBDA: store double 2.0{{.+}}, double* [[G_REF]]
+
+ // LAMBDA: [[TMP_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 1
+ // LAMBDA: [[G1_REF:%.+]] = load double*, double** [[TMP_PTR_REF]]
+ // LAMBDA: store double 2.0{{.+}}, double* [[G1_REF]],
+ // LAMBDA: [[SVAR_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 2
+ // LAMBDA: [[SVAR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SVAR_PTR_REF]]
+ // LAMBDA: store i{{[0-9]+}} 4, i{{[0-9]+}}* [[SVAR_REF]]
+ // LAMBDA: [[SFVAR_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 3
+ // LAMBDA: [[SFVAR_REF:%.+]] = load float*, float** [[SFVAR_PTR_REF]]
+ // LAMBDA: store float 8.0{{.+}}, float* [[SFVAR_REF]]
+ }();
+ }
+ }();
+ return 0;
+ #else
+ S<float> test;
+ int t_var = 0;
+ int vec[] = {1, 2};
+ S<float> s_arr[] = {1, 2};
+ S<float> &var = test;
+
+ #pragma omp target teams distribute parallel for simd lastprivate(t_var, vec, s_arr, s_arr, var, var, svar)
+ for (int i = 0; i < 2; ++i) {
+ vec[i] = t_var;
+ s_arr[i] = var;
+ }
+ int i;
+
+ return tmain<int>();
+ #endif
+}
+
+// CHECK: define{{.*}} i{{[0-9]+}} @main()
+// CHECK: [[TEST:%.+]] = alloca [[S_FLOAT_TY]],
+// CHECK: call {{.*}} [[S_FLOAT_TY_DEF_CONSTR:@.+]]([[S_FLOAT_TY]]* [[TEST]])
+// CHECK: call i{{[0-9]+}} @__tgt_target_teams(
+// CHECK: call void [[OFFLOAD_FUN:@.+]](
+// CHECK: ret
+
+// CHECK: define{{.+}} [[OFFLOAD_FUN]](
+// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_teams(
+// CHECK: ret
+//
+// CHECK: define internal void [[OMP_OUTLINED:@.+]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [2 x i{{[0-9]+}}]*{{.+}} [[VEC_IN:%.+]], i{{[0-9]+}}{{.+}} [[T_VAR_IN:%.+]], [2 x [[S_FLOAT_TY]]]*{{.+}} [[S_ARR_IN:%.+]], [[S_FLOAT_TY]]*{{.+}} [[VAR_IN:%.+]], i{{[0-9]+}}{{.*}} [[S_VAR_IN:%.+]])
+// CHECK: {{.+}} = alloca i{{[0-9]+}}*,
+// CHECK: {{.+}} = alloca i{{[0-9]+}}*,
+// CHECK: [[VEC_ADDR:%.+]] = alloca [2 x i{{[0-9]+}}]*,
+// CHECK: [[T_VAR_ADDR:%.+]] = alloca i{{[0-9]+}},
+// CHECK: [[S_ARR_ADDR:%.+]] = alloca [2 x [[S_FLOAT_TY]]]*,
+// CHECK: [[VAR_ADDR:%.+]] = alloca [[S_FLOAT_TY]]*,
+// CHECK: [[SVAR_ADDR:%.+]] = alloca i{{[0-9]+}},
+// skip loop variables
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: [[OMP_IS_LAST:%.+]] = alloca i{{[0-9]+}},
+
+// copy from parameters to local address variables
+// CHECK: store {{.+}} [[VEC_IN]], {{.+}} [[VEC_ADDR]],
+// CHECK: store {{.+}} [[T_VAR_IN]], {{.+}} [[T_VAR_ADDR]],
+// CHECK: store {{.+}} [[S_ARR_IN]], {{.+}} [[S_ARR_ADDR]],
+// CHECK: store {{.+}} [[VAR_IN]], {{.+}} [[VAR_ADDR]],
+// CHECK: store {{.+}} [[S_VAR_IN]], {{.+}} [[SVAR_ADDR]],
+
+// prepare lastprivate targets
+// CHECK-64-DAG: [[TVAR_TGT:%.+]] = bitcast {{.+}} [[T_VAR_ADDR]] to
+// CHECK-DAG: [[VEC_TGT:%.+]] = load {{.+}}, {{.+}} [[VEC_ADDR]],
+// CHECK-DAG: [[S_ARR_TGT:%.+]] = load {{.+}}, {{.+}} [[S_ARR_ADDR]],
+// CHECK-DAG: [[VAR_TGT:%.+]] = load {{.+}}, {{.+}} [[VAR_ADDR]],
+// CHECK-64-DAG: [[SVAR_TGT:%.+]] = bitcast {{.+}} [[SVAR_ADDR]] to
+
+// the distribute loop
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL:.+]] to
+// CHECK: call void @__kmpc_for_static_fini(
+
+// lastprivates
+// CHECK: [[OMP_IS_LAST_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[OMP_IS_LAST]],
+// CHECK: [[IS_LAST_IT:%.+]] = icmp ne i{{[0-9]+}} [[OMP_IS_LAST_VAL]], 0
+// CHECK: br i1 [[IS_LAST_IT]], label %[[OMP_LASTPRIV_BLOCK:.+]], label %[[OMP_LASTPRIV_DONE:.+]]
+
+// CHECK: [[OMP_LASTPRIV_BLOCK]]:
+// CHECK-64-DAG: store {{.+}}, {{.+}} [[TVAR_TGT]],
+// CHECK-32-DAG: store {{.+}}, {{.+}} [[T_VAR_ADDR]],
+// CHECK-DAG: [[VEC_TGT_REF:%.+]] = bitcast {{.+}} [[VEC_TGT]] to
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_TGT_REF]],
+// CHECK-DAG: [[S_ARR_BEGIN:%.+]] = getelementptr {{.+}} [[S_ARR_TGT]],
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}(
+// CHECK-DAG: [[VAR_TGT_BCAST:%.+]] = bitcast {{.+}} [[VAR_TGT]] to
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_TGT_BCAST]],
+// CHECK-64-DAG: store {{.+}}, {{.+}} [[SVAR_TGT]],
+// CHECK-32-DAG: store {{.+}}, {{.+}} [[SVAR_ADDR]],
+// CHECK: ret void
+
+// CHECK: define internal void [[OMP_OUTLINED:@.+]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, {{.+}}, {{.+}}, [2 x i{{[0-9]+}}]*{{.+}} [[VEC_IN:%.+]], i{{[0-9]+}}{{.+}} [[T_VAR_IN:%.+]], [2 x [[S_FLOAT_TY]]]*{{.+}} [[S_ARR_IN:%.+]], [[S_FLOAT_TY]]*{{.+}} [[VAR_IN:%.+]], i{{[0-9]+}}{{.*}} [[S_VAR_IN:%.+]])
+
+// gbl and bound tid vars, prev lb and ub vars
+// CHECK: {{.+}} = alloca i{{[0-9]+}}*,
+// CHECK: {{.+}} = alloca i{{[0-9]+}}*,
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+
+// CHECK: [[VEC_ADDR:%.+]] = alloca [2 x i{{[0-9]+}}]*,
+// CHECK: [[T_VAR_ADDR:%.+]] = alloca i{{[0-9]+}},
+// CHECK: [[S_ARR_ADDR:%.+]] = alloca [2 x [[S_FLOAT_TY]]]*,
+// CHECK: [[VAR_ADDR:%.+]] = alloca [[S_FLOAT_TY]]*,
+// CHECK: [[SVAR_ADDR:%.+]] = alloca i{{[0-9]+}},
+// skip loop variables
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: [[OMP_IS_LAST:%.+]] = alloca i{{[0-9]+}},
+
+// copy from parameters to local address variables
+// CHECK: store {{.+}} [[VEC_IN]], {{.+}} [[VEC_ADDR]],
+// CHECK: store {{.+}} [[T_VAR_IN]], {{.+}} [[T_VAR_ADDR]],
+// CHECK: store {{.+}} [[S_ARR_IN]], {{.+}} [[S_ARR_ADDR]],
+// CHECK: store {{.+}} [[VAR_IN]], {{.+}} [[VAR_ADDR]],
+// CHECK: store {{.+}} [[S_VAR_IN]], {{.+}} [[SVAR_ADDR]],
+
+// prepare lastprivate targets
+// CHECK-64-DAG: [[TVAR_TGT:%.+]] = bitcast {{.+}} [[T_VAR_ADDR]] to
+// CHECK-DAG: [[VEC_TGT:%.+]] = load {{.+}}, {{.+}} [[VEC_ADDR]],
+// CHECK-DAG: [[S_ARR_TGT:%.+]] = load {{.+}}, {{.+}} [[S_ARR_ADDR]],
+// CHECK-DAG: [[VAR_TGT:%.+]] = load {{.+}}, {{.+}} [[VAR_ADDR]],
+// CHECK-64-DAG: [[SVAR_TGT:%.+]] = bitcast {{.+}} [[SVAR_ADDR]] to
+
+// the distribute loop
+// CHECK: call void @__kmpc_for_static_init_4(
+// skip body: code generation routine is same as distribute parallel for lastprivate
+// CHECK: call void @__kmpc_for_static_fini(
+
+// lastprivates
+// CHECK: [[OMP_IS_LAST_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[OMP_IS_LAST]],
+// CHECK: [[IS_LAST_IT:%.+]] = icmp ne i{{[0-9]+}} [[OMP_IS_LAST_VAL]], 0
+// CHECK: br i1 [[IS_LAST_IT]], label %[[OMP_LASTPRIV_BLOCK:.+]], label %[[OMP_LASTPRIV_DONE:.+]]
+
+// CHECK: [[OMP_LASTPRIV_BLOCK]]:
+// CHECK-64-DAG: store {{.+}}, {{.+}} [[TVAR_TGT]],
+// CHECK-32-DAG: store {{.+}}, {{.+}} [[T_VAR_ADDR]],
+// CHECK-DAG: [[VEC_TGT_REF:%.+]] = bitcast {{.+}} [[VEC_TGT]] to
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_TGT_REF]],
+// CHECK-DAG: [[S_ARR_BEGIN:%.+]] = getelementptr {{.+}} [[S_ARR_TGT]],
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}(
+// CHECK-DAG: [[VAR_TGT_BCAST:%.+]] = bitcast {{.+}} [[VAR_TGT]] to
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_TGT_BCAST]],
+// CHECK-64-DAG: store {{.+}}, {{.+}} [[SVAR_TGT]],
+// CHECK-32-DAG: store {{.+}}, {{.+}} [[SVAR_ADDR]],
+// CHECK: ret void
+
+// template tmain
+// CHECK: define{{.*}} i{{[0-9]+}} [[TMAIN_INT:@.+]]()
+// CHECK: [[TEST:%.+]] = alloca [[S_INT_TY]],
+// CHECK: call {{.*}} [[S_INT_TY_DEF_CONSTR:@.+]]([[S_INT_TY]]* [[TEST]])
+// CHECK: call i{{[0-9]+}} @__tgt_target_teams(
+// CHECK: call void [[OFFLOAD_FUN_1:@.+]](
+// CHECK: ret
+
+// CHECK: define internal void [[OFFLOAD_FUN_1]](
+// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_teams(%{{.+}}* @{{.+}}, i{{[0-9]+}} 4,
+// CHECK: ret
+
+// CHECK: define internal void [[OMP_OUTLINED_1:@.+]](i{{[0-9]+}}* noalias [[GTID_ADDR1:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [2 x i{{[0-9]+}}]*{{.+}} [[VEC_IN1:%.+]], i{{[0-9]+}}{{.+}} [[T_VAR_IN1:%.+]], [2 x [[S_INT_TY]]]*{{.+}} [[S_ARR_IN1:%.+]], [[S_INT_TY]]*{{.+}} [[VAR_IN1:%.+]])
+// skip alloca of global_tid and bound_tid
+// CHECK: {{.+}} = alloca i{{[0-9]+}}*,
+// CHECK: {{.+}} = alloca i{{[0-9]+}}*,
+// CHECK: [[VEC_ADDR1:%.+]] = alloca [2 x i{{[0-9]+}}]*,
+// CHECK: [[T_VAR_ADDR1:%.+]] = alloca i{{[0-9]+}},
+// CHECK: [[S_ARR_ADDR1:%.+]] = alloca [2 x [[S_INT_TY]]]*,
+// CHECK: [[VAR_ADDR1:%.+]] = alloca [[S_INT_TY]]*,
+// skip loop variables
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: [[OMP_IS_LAST1:%.+]] = alloca i{{[0-9]+}},
+
+// copy from parameters to local address variables
+// CHECK: store {{.+}} [[VEC_IN1]], {{.+}} [[VEC_ADDR1]],
+// CHECK: store {{.+}} [[T_VAR_IN1]], {{.+}} [[T_VAR_ADDR1]],
+// CHECK: store {{.+}} [[S_ARR_IN1]], {{.+}} [[S_ARR_ADDR1]],
+// CHECK: store {{.+}} [[VAR_IN1]], {{.+}} [[VAR_ADDR1]],
+
+// prepare lastprivate targets
+// CHECK-64-DAG: [[T_VAR_TGT:%.+]] = bitcast {{.+}} [[T_VAR_ADDR1]] to
+// CHECK-DAG: [[VEC_TGT:%.+]] = load {{.+}}, {{.+}} [[VEC_ADDR1]],
+// CHECK-DAG: [[S_ARR_TGT:%.+]] = load {{.+}}, {{.+}} [[S_ARR_ADDR1]],
+// CHECK-DAG: [[VAR_TGT:%.+]] = load {{.+}}, {{.+}} [[VAR_ADDR1]],
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[TPAR_OUTL:.+]] to
+// CHECK: call void @__kmpc_for_static_fini(
+
+// lastprivates
+// CHECK: [[OMP_IS_LAST_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[OMP_IS_LAST1]],
+// CHECK: [[IS_LAST_IT:%.+]] = icmp ne i{{[0-9]+}} [[OMP_IS_LAST_VAL]], 0
+// CHECK: br i1 [[IS_LAST_IT]], label %[[OMP_LASTPRIV_BLOCK:.+]], label %[[OMP_LASTPRIV_DONE:.+]]
+
+// CHECK: [[OMP_LASTPRIV_BLOCK]]:
+// CHECK-64-DAG: store {{.+}}, {{.+}} [[T_VAR_TGT]],
+// CHECK-32-DAG: store {{.+}}, {{.+}} [[T_VAR_ADDR1]],
+// CHECK-DAG: [[VEC_TGT_BCAST:%.+]] = bitcast {{.+}} [[VEC_TGT]] to
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_TGT_BCAST]],
+// CHECK-DAG: {{.+}} = getelementptr {{.+}} [[S_ARR_TGT]],
+// CHECK: call void @llvm.memcpy.{{.+}}(
+// CHECK-DAG: [[VAR_ADDR_BCAST:%.+]] = bitcast {{.+}} [[VAR_TGT]] to
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_BCAST]],
+// CHECK: ret void
+
+// CHECK: define internal void [[TPAR_OUTL:@.+]](i{{[0-9]+}}* noalias [[GTID_ADDR1:%.+]], i{{[0-9]+}}* noalias %{{.+}}, {{.+}}, {{.+}}, [2 x i{{[0-9]+}}]*{{.+}} [[VEC_IN1:%.+]], i{{[0-9]+}}{{.+}} [[T_VAR_IN1:%.+]], [2 x [[S_INT_TY]]]*{{.+}} [[S_ARR_IN1:%.+]], [[S_INT_TY]]*{{.+}} [[VAR_IN1:%.+]])
+// skip alloca of global_tid and bound_tid, and prev lb and ub vars
+// CHECK: {{.+}} = alloca i{{[0-9]+}}*,
+// CHECK: {{.+}} = alloca i{{[0-9]+}}*,
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+
+// CHECK: [[VEC_ADDR1:%.+]] = alloca [2 x i{{[0-9]+}}]*,
+// CHECK: [[T_VAR_ADDR1:%.+]] = alloca i{{[0-9]+}},
+// CHECK: [[S_ARR_ADDR1:%.+]] = alloca [2 x [[S_INT_TY]]]*,
+// CHECK: [[VAR_ADDR1:%.+]] = alloca [[S_INT_TY]]*,
+// skip loop variables
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: [[OMP_IS_LAST1:%.+]] = alloca i{{[0-9]+}},
+
+// copy from parameters to local address variables
+// CHECK: store {{.+}} [[VEC_IN1]], {{.+}} [[VEC_ADDR1]],
+// CHECK: store {{.+}} [[T_VAR_IN1]], {{.+}} [[T_VAR_ADDR1]],
+// CHECK: store {{.+}} [[S_ARR_IN1]], {{.+}} [[S_ARR_ADDR1]],
+// CHECK: store {{.+}} [[VAR_IN1]], {{.+}} [[VAR_ADDR1]],
+
+// prepare lastprivate targets
+// CHECK-64-DAG: [[T_VAR_TGT:%.+]] = bitcast {{.+}} [[T_VAR_ADDR1]] to
+// CHECK-DAG: [[VEC_TGT:%.+]] = load {{.+}}, {{.+}} [[VEC_ADDR1]],
+// CHECK-DAG: [[S_ARR_TGT:%.+]] = load {{.+}}, {{.+}} [[S_ARR_ADDR1]],
+// CHECK-DAG: [[VAR_TGT:%.+]] = load {{.+}}, {{.+}} [[VAR_ADDR1]],
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// skip body: code generation routine is same as distribute parallel for lastprivate
+// CHECK: call void @__kmpc_for_static_fini(
+
+// lastprivates
+// CHECK: [[OMP_IS_LAST_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[OMP_IS_LAST1]],
+// CHECK: [[IS_LAST_IT:%.+]] = icmp ne i{{[0-9]+}} [[OMP_IS_LAST_VAL]], 0
+// CHECK: br i1 [[IS_LAST_IT]], label %[[OMP_LASTPRIV_BLOCK:.+]], label %[[OMP_LASTPRIV_DONE:.+]]
+
+// CHECK: [[OMP_LASTPRIV_BLOCK]]:
+// CHECK-64-DAG: store {{.+}}, {{.+}} [[T_VAR_TGT]],
+// CHECK-32-DAG: store {{.+}}, {{.+}} [[T_VAR_ADDR1]],
+// CHECK-DAG: [[VEC_TGT_BCAST:%.+]] = bitcast {{.+}} [[VEC_TGT]] to
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_TGT_BCAST]],
+// CHECK-DAG: {{.+}} = getelementptr {{.+}} [[S_ARR_TGT]],
+// CHECK: call void @llvm.memcpy.{{.+}}(
+// CHECK-DAG: [[VAR_ADDR_BCAST:%.+]] = bitcast {{.+}} [[VAR_TGT]] to
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_BCAST]],
+// CHECK: ret void
+
+#endif
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_messages.cpp
index 156f1a66c191..b65c22ba8a40 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_linear_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_linear_messages.cpp
index 257244ede444..3013480d6ea9 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_linear_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_linear_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
namespace X {
int x;
};
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_loop_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_loop_messages.cpp
index a16dec190dd2..1378ea4eb65c 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_loop_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_loop_messages.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s -Wno-openmp-target
class S {
int a;
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_map_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_map_messages.cpp
index b230d9ab24fe..63d85ebc37b9 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_map_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_map_messages.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s -Wno-openmp-target
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_messages.cpp
index 7e16c794f01f..58e88623473f 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_misc_messages.c b/test/OpenMP/target_teams_distribute_parallel_for_simd_misc_messages.c
index 1ea02f6d2b57..7005c7b027a8 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_misc_messages.c
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_misc_messages.c
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -verify %s
+
// expected-error@+1 {{unexpected OpenMP directive '#pragma omp target teams distribute parallel for simd'}}
#pragma omp target teams distribute parallel for simd
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_nowait_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_nowait_messages.cpp
index 4c65130b9d91..458eaf72c340 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_nowait_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_nowait_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -verify -fopenmp %s
+// RUN: %clang_cc1 -fsyntax-only -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_num_teams_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_num_teams_messages.cpp
index 240d7d7b66b8..6564f104a126 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_num_teams_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_num_teams_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_num_threads_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_num_threads_messages.cpp
index 9032996dc28d..58fab1e8df63 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_num_threads_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_num_threads_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_private_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_private_codegen.cpp
new file mode 100644
index 000000000000..88169197d1c6
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_private_codegen.cpp
@@ -0,0 +1,369 @@
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 --check-prefix HHECK --check-prefix HCHECK-64
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 --check-prefix HHECK --check-prefix HCHECK-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix HHECK --check-prefix HCHECK-64
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix HHECK --check-prefix HCHECK-64
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64 --check-prefix HLAMBDA --check-prefix HLAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64 --check-prefix HLAMBDA --check-prefix HLAMBDA-64
+
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0
+
+// Test target codegen - host bc file has to be created first. (no significant differences with host version of target region)
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix TCHECK --check-prefix TCHECK-32
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64 --check-prefix TLAMBDA --check-prefix TLAMBDA-64
+
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0
+//
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+struct St {
+ int a, b;
+ St() : a(0), b(0) {}
+ St(const St &st) : a(st.a + st.b), b(0) {}
+ ~St() {}
+};
+
+volatile int g = 1212;
+volatile int &g1 = g;
+
+template <class T>
+struct S {
+ T f;
+ S(T a) : f(a + g) {}
+ S() : f(g) {}
+ S(const S &s, St t = St()) : f(s.f + t.a) {}
+ operator T() { return T(); }
+ ~S() {}
+};
+
+// CHECK-DAG: [[S_FLOAT_TY:%.+]] = type { float }
+// CHECK-DAG: [[S_INT_TY:%.+]] = type { i{{[0-9]+}} }
+
+template <typename T>
+T tmain() {
+ S<T> test;
+ T t_var = T();
+ T vec[] = {1, 2};
+ S<T> s_arr[] = {1, 2};
+ S<T> &var = test;
+#pragma omp target teams distribute parallel for simd private(t_var, vec, s_arr, var)
+ for (int i = 0; i < 2; ++i) {
+ vec[i] = t_var;
+ s_arr[i] = var;
+ }
+ return T();
+}
+
+// HCHECK-DAG: [[TEST:@.+]] ={{.*}} global [[S_FLOAT_TY]] zeroinitializer,
+S<float> test;
+// HCHECK-DAG: [[T_VAR:@.+]] ={{.+}} global i{{[0-9]+}} 333,
+int t_var = 333;
+// HCHECK-DAG: [[VEC:@.+]] ={{.+}} global [2 x i{{[0-9]+}}] [i{{[0-9]+}} 1, i{{[0-9]+}} 2],
+int vec[] = {1, 2};
+// HCHECK-DAG: [[S_ARR:@.+]] ={{.+}} global [2 x [[S_FLOAT_TY]]] zeroinitializer,
+S<float> s_arr[] = {1, 2};
+// HCHECK-DAG: [[VAR:@.+]] ={{.+}} global [[S_FLOAT_TY]] zeroinitializer,
+S<float> var(3);
+// HCHECK-DAG: [[SIVAR:@.+]] = internal global i{{[0-9]+}} 0,
+
+int main() {
+ static int sivar;
+#ifdef LAMBDA
+ // HLAMBDA: [[G:@.+]] = global i{{[0-9]+}} 1212,
+ // HLAMBDA-LABEL: @main
+ // HLAMBDA: call void [[OUTER_LAMBDA:@.+]](
+ [&]() {
+ // HLAMBDA: define{{.*}} internal{{.*}} void [[OUTER_LAMBDA]](
+ // HLAMBDA: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 0,
+ // HLAMBDA: call void @[[LOFFL1:.+]](
+ // HLAMBDA: ret
+#pragma omp target teams distribute parallel for simd private(g, g1, sivar)
+ for (int i = 0; i < 2; ++i) {
+ // HLAMBDA: define{{.*}} internal{{.*}} void @[[LOFFL1]]()
+ // TLAMBDA: define{{.*}} void @[[LOFFL1:.+]]()
+ // LAMBDA: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 0, {{.+}} @[[LOUTL1:.+]] to {{.+}})
+ // LAMBDA: ret void
+
+ // LAMBDA: define internal void @[[LOUTL1]]({{.+}})
+ // Skip global, bound tid and loop vars
+ // LAMBDA: {{.+}} = alloca i32*,
+ // LAMBDA: {{.+}} = alloca i32*,
+ // LAMBDA: alloca i32,
+ // LAMBDA: alloca i32,
+ // LAMBDA: alloca i32,
+ // LAMBDA: alloca i32,
+ // LAMBDA: alloca i32,
+ // LAMBDA: alloca i32,
+ // LAMBDA: [[G_PRIV:%.+]] = alloca i{{[0-9]+}},
+ // LAMBDA: [[G1_PRIV:%.+]] = alloca i{{[0-9]+}}
+ // LAMBDA: [[TMP:%.+]] = alloca i{{[0-9]+}}*,
+ // LAMBDA: [[SIVAR_PRIV:%.+]] = alloca i{{[0-9]+}},
+ // LAMBDA: store{{.+}} [[G1_PRIV]], {{.+}} [[TMP]],
+
+ g = 1;
+ g1 = 1;
+ sivar = 2;
+ // LAMBDA: call void @__kmpc_for_static_init_4(
+ // LAMBDA: call void {{.+}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[LPAR_OUTL:.+]] to
+ // LAMBDA: call void @__kmpc_for_static_fini(
+ // LAMBDA: ret void
+
+ // LAMBDA: define internal void @[[LPAR_OUTL]]({{.+}})
+ // Skip global, bound tid and loop vars
+ // LAMBDA: {{.+}} = alloca i32*,
+ // LAMBDA: {{.+}} = alloca i32*,
+ // LAMBDA: alloca i{{[0-9]+}},
+ // LAMBDA: alloca i{{[0-9]+}},
+ // LAMBDA: alloca i32,
+ // LAMBDA: alloca i32,
+ // LAMBDA: alloca i32,
+ // LAMBDA: alloca i32,
+ // LAMBDA: alloca i32,
+ // LAMBDA: alloca i32,
+ // LAMBDA: [[G_PRIV:%.+]] = alloca i{{[0-9]+}},
+ // LAMBDA: [[G1_PRIV:%.+]] = alloca i{{[0-9]+}}
+ // LAMBDA: [[TMP:%.+]] = alloca i{{[0-9]+}}*,
+ // LAMBDA: [[SIVAR_PRIV:%.+]] = alloca i{{[0-9]+}},
+ // LAMBDA: store{{.+}} [[G1_PRIV]], {{.+}} [[TMP]],
+ // LAMBDA-DAG: store{{.+}} 1, {{.+}} [[G_PRIV]],
+ // LAMBDA-DAG: store{{.+}} 2, {{.+}} [[SIVAR_PRIV]],
+ // LAMBDA-DAG: [[G1_REF:%.+]] = load{{.+}}, {{.+}} [[TMP]],
+ // LAMBDA-DAG: store{{.+}} 1, {{.+}} [[G1_REF]],
+ // LAMBDA: call void [[INNER_LAMBDA:@.+]](
+ // LAMBDA: call void @__kmpc_for_static_fini(
+ // LAMBDA: ret void
+ [&]() {
+ // LAMBDA: define {{.+}} void [[INNER_LAMBDA]](%{{.+}}* [[ARG_PTR:%.+]])
+ // LAMBDA: store %{{.+}}* [[ARG_PTR]], %{{.+}}** [[ARG_PTR_REF:%.+]],
+ g = 2;
+ g1 = 2;
+ sivar = 4;
+ // LAMBDA: [[ARG_PTR:%.+]] = load %{{.+}}*, %{{.+}}** [[ARG_PTR_REF]]
+
+ // LAMBDA: [[G_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
+ // LAMBDA: [[G_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[G_PTR_REF]]
+ // LAMBDA: store i{{[0-9]+}} 2, i{{[0-9]+}}* [[G_REF]]
+ // LAMBDA: [[G1_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 1
+ // LAMBDA: [[G1_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[G1_PTR_REF]]
+ // LAMBDA: store i{{[0-9]+}} 2, i{{[0-9]+}}* [[G1_REF]]
+ // LAMBDA: [[SIVAR_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 2
+ // LAMBDA: [[SIVAR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SIVAR_PTR_REF]]
+ // LAMBDA: store i{{[0-9]+}} 4, i{{[0-9]+}}* [[SIVAR_REF]]
+ }();
+ }
+ }();
+ return 0;
+#else
+#pragma omp target teams distribute parallel for simd private(t_var, vec, s_arr, var, sivar)
+ for (int i = 0; i < 2; ++i) {
+ vec[i] = t_var;
+ s_arr[i] = var;
+ sivar += i;
+ }
+ return tmain<int>();
+#endif
+}
+
+// HCHECK: define {{.*}}i{{[0-9]+}} @main()
+// HCHECK: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 0, i8** null, i8** null, {{.+}} null, {{.+}} null, i32 0, i32 0)
+// HCHECK: call void @[[OFFL1:.+]]()
+// HCHECK: {{%.+}} = call{{.*}} i32 @[[TMAIN_INT:.+]]()
+// HCHECK: ret
+
+// HCHECK: define{{.*}} void @[[OFFL1]]()
+// TCHECK: define{{.*}} void @[[OFFL1:.+]]()
+// CHECK: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 0, {{.+}} @[[OUTL1:.+]] to {{.+}})
+// CHECK: ret void
+
+// CHECK: define internal void @[[OUTL1]]({{.+}})
+// Skip global, bound tid and loop vars
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: {{.+}} = alloca i32,
+// CHECK: {{.+}} = alloca i32,
+// CHECK: {{.+}} = alloca i32,
+// CHECK: {{.+}} = alloca i32,
+// CHECK: {{.+}} = alloca i32,
+// CHECK-DAG: [[T_VAR_PRIV:%.+]] = alloca i{{[0-9]+}},
+// CHECK-DAG: [[VEC_PRIV:%.+]] = alloca [2 x i{{[0-9]+}}],
+// CHECK-DAG: [[S_ARR_PRIV:%.+]] = alloca [2 x [[S_FLOAT_TY]]],
+// CHECK-DAG: [[VAR_PRIV:%.+]] = alloca [[S_FLOAT_TY]],
+// CHECK-DAG: [[SIVAR_PRIV:%.+]] = alloca i{{[0-9]+}},
+// CHECK: alloca i32,
+
+// private(s_arr)
+// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]],
+// CHECK-DAG: [[S_ARR_PTR_ALLOC:%.+]] = phi{{.+}} [ [[S_ARR_PRIV_BGN]], {{.+}} ], [ [[S_ARR_NEXT:%.+]], {{.+}} ]
+// CHECK-DAG: call void @{{.+}}({{.+}} [[S_ARR_PTR_ALLOC]])
+// CHECK-DAG: [[S_ARR_NEXT]] = getelementptr {{.+}} [[S_ARR_PTR_ALLOC]],
+
+// private(var)
+// CHECK-DAG: call void @{{.+}}({{.+}} [[VAR_PRIV]])
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call void {{.+}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL1:.+]] to
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: ret void
+
+// CHECK: define internal void @[[PAR_OUTL1]]({{.+}})
+// Skip global, bound tid and loop vars
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i{{[0-9]+}},
+// CHECK: {{.+}} = alloca i32,
+// CHECK: {{.+}} = alloca i32,
+// CHECK: {{.+}} = alloca i32,
+// CHECK: {{.+}} = alloca i32,
+// CHECK: {{.+}} = alloca i32,
+// CHECK: {{.+}} = alloca i32,
+// CHECK-DAG: [[T_VAR_PRIV:%.+]] = alloca i{{[0-9]+}},
+// CHECK-DAG: [[VEC_PRIV:%.+]] = alloca [2 x i{{[0-9]+}}],
+// CHECK-DAG: [[S_ARR_PRIV:%.+]] = alloca [2 x [[S_FLOAT_TY]]],
+// CHECK-DAG: [[VAR_PRIV:%.+]] = alloca [[S_FLOAT_TY]],
+// CHECK-DAG: [[SIVAR_PRIV:%.+]] = alloca i{{[0-9]+}},
+// CHECK: alloca i32,
+
+// private(s_arr)
+// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]],
+// CHECK-DAG: [[S_ARR_PTR_ALLOC:%.+]] = phi{{.+}} [ [[S_ARR_PRIV_BGN]], {{.+}} ], [ [[S_ARR_NEXT:%.+]], {{.+}} ]
+// CHECK-DAG: call void @{{.+}}({{.+}} [[S_ARR_PTR_ALLOC]])
+// CHECK-DAG: [[S_ARR_NEXT]] = getelementptr {{.+}} [[S_ARR_PTR_ALLOC]],
+
+// private(var)
+// CHECK-DAG: call void @{{.+}}({{.+}} [[VAR_PRIV]])
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK-DAG: {{.+}} = {{.+}} [[T_VAR_PRIV]]
+// CHECK-DAG: {{.+}} = {{.+}} [[VEC_PRIV]]
+// CHECK-DAG: {{.+}} = {{.+}} [[S_ARR_PRIV]]
+// CHECK-DAG: {{.+}} = {{.+}} [[VAR_PRIV]]
+// CHECK-DAG: {{.+}} = {{.+}} [[SIVAR_PRIV]]
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: ret void
+
+// HCHECK: define{{.*}} i{{[0-9]+}} @[[TMAIN_INT]]()
+// HCHECK: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 0,
+// HCHECK: call void @[[TOFFL1:.+]]()
+// HCHECK: ret
+
+// HCHECK: define {{.*}}void @[[TOFFL1]]()
+// TCHECK: define weak void @[[TOFFL1:.+]]()
+// CHECK: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 0, {{.+}} @[[TOUTL1:.+]] to {{.+}})
+// CHECK: ret void
+
+// CHECK: define internal void @[[TOUTL1]]({{.+}})
+// Skip global, bound tid and loop vars
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i32,
+// CHECK: [[T_VAR_PRIV:%.+]] = alloca i{{[0-9]+}},
+// CHECK: [[VEC_PRIV:%.+]] = alloca [2 x i{{[0-9]+}}],
+// CHECK: [[S_ARR_PRIV:%.+]] = alloca [2 x [[S_INT_TY]]],
+// CHECK: [[VAR_PRIV:%.+]] = alloca [[S_INT_TY]],
+// CHECK: [[TMP:%.+]] = alloca [[S_INT_TY]]*,
+
+// private(s_arr)
+// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_PRIV]],
+// CHECK-DAG: [[S_ARR_PTR_ALLOC:%.+]] = phi{{.+}} [ [[S_ARR_PRIV_BGN]], {{.+}} ], [ [[S_ARR_NEXT:%.+]], {{.+}} ]
+// CHECK-DAG: call void @{{.+}}({{.+}} [[S_ARR_PTR_ALLOC]])
+// CHECK-DAG: [[S_ARR_NEXT]] = getelementptr {{.+}} [[S_ARR_PTR_ALLOC]],
+
+// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_PRIV]],
+// CHECK-DAG: [[S_ARR_PTR_ALLOC:%.+]] = phi{{.+}} [ [[S_ARR_PRIV_BGN]], {{.+}} ], [ [[S_ARR_NEXT:%.+]], {{.+}} ]
+// CHECK-DAG: call void @{{.+}}({{.+}} [[S_ARR_PTR_ALLOC]])
+// CHECK-DAG: [[S_ARR_NEXT]] = getelementptr {{.+}} [[S_ARR_PTR_ALLOC]],
+
+// private(var)
+// CHECK-DAG: call void @{{.+}}({{.+}} [[VAR_PRIV]])
+// CHECK-DAG: store{{.+}} [[VAR_PRIV]], {{.+}} [[TMP]]
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call void {{.+}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[TPAR_OUTL1:.+]] to
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: ret void
+
+// CHECK: define internal void @[[TPAR_OUTL1]]({{.+}})
+// Skip global, bound tid and loop vars
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: {{.+}} = alloca i32*,
+// prev lb and ub
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// iter variables
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i32,
+// CHECK: [[T_VAR_PRIV:%.+]] = alloca i{{[0-9]+}},
+// CHECK: [[VEC_PRIV:%.+]] = alloca [2 x i{{[0-9]+}}],
+// CHECK: [[S_ARR_PRIV:%.+]] = alloca [2 x [[S_INT_TY]]],
+// CHECK: [[VAR_PRIV:%.+]] = alloca [[S_INT_TY]],
+// CHECK: [[TMP:%.+]] = alloca [[S_INT_TY]]*,
+
+// private(s_arr)
+// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_PRIV]],
+// CHECK-DAG: [[S_ARR_PTR_ALLOC:%.+]] = phi{{.+}} [ [[S_ARR_PRIV_BGN]], {{.+}} ], [ [[S_ARR_NEXT:%.+]], {{.+}} ]
+// CHECK-DAG: call void @{{.+}}({{.+}} [[S_ARR_PTR_ALLOC]])
+// CHECK-DAG: [[S_ARR_NEXT]] = getelementptr {{.+}} [[S_ARR_PTR_ALLOC]],
+
+// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_PRIV]],
+// CHECK-DAG: [[S_ARR_PTR_ALLOC:%.+]] = phi{{.+}} [ [[S_ARR_PRIV_BGN]], {{.+}} ], [ [[S_ARR_NEXT:%.+]], {{.+}} ]
+// CHECK-DAG: call void @{{.+}}({{.+}} [[S_ARR_PTR_ALLOC]])
+// CHECK-DAG: [[S_ARR_NEXT]] = getelementptr {{.+}} [[S_ARR_PTR_ALLOC]],
+
+// private(var)
+// CHECK-DAG: call void @{{.+}}({{.+}} [[VAR_PRIV]])
+// CHECK-DAG: store{{.+}} [[VAR_PRIV]], {{.+}} [[TMP]]
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK-DAG: {{.+}} = {{.+}} [[T_VAR_PRIV]]
+// CHECK-DAG: {{.+}} = {{.+}} [[VEC_PRIV]]
+// CHECK-DAG: {{.+}} = {{.+}} [[S_ARR_PRIV]]
+// CHECK-DAG: {{.+}} = {{.+}} [[TMP]]
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: ret void
+
+
+#endif
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_private_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_private_messages.cpp
index 20e185003ba0..f1a8e0bfc7c3 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_private_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_private_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_proc_bind_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_proc_bind_codegen.cpp
new file mode 100644
index 000000000000..40bf51f34028
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_proc_bind_codegen.cpp
@@ -0,0 +1,93 @@
+// add -fopenmp-targets
+
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// SIMD-ONLY-NOT: {{__kmpc|__tgt}}
+
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+typedef __INTPTR_TYPE__ intptr_t;
+
+// CHECK-DAG: [[IDENT_T_TY:%.+]] = type { i32, i32, i32, i32, i8* }
+// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
+// CHECK-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr constant [[IDENT_T_TY]] { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+
+void foo();
+
+struct S {
+ intptr_t a, b, c;
+ S(intptr_t a) : a(a) {}
+ operator char() { return a; }
+ ~S() {}
+};
+
+template <typename T>
+T tmain() {
+#pragma omp target teams distribute parallel for simd proc_bind(master)
+ for(int i = 0; i < 1000; i++) {}
+ return T();
+}
+
+int main() {
+ // CHECK-LABEL: @main
+#pragma omp target teams distribute parallel for simd proc_bind(spread)
+ for(int i = 0; i < 1000; i++) {}
+#pragma omp target teams distribute parallel for simd proc_bind(close)
+ for(int i = 0; i < 1000; i++) {}
+ return tmain<int>();
+}
+
+// CHECK: call {{.*}}@__tgt_target_teams({{.+}})
+// CHECK: call void [[OFFL1:@.+]]()
+// CHECK: call {{.*}}@__tgt_target_teams({{.+}})
+// CHECK: call void [[OFFL2:@.+]]()
+// CHECK: [[CALL_RET:%.+]] = call{{.+}} i32 [[TMAIN:@.+]]()
+// CHECK: ret i32 [[CALL_RET]]
+
+// CHECK: define{{.+}} void [[OFFL1]](
+// CHECK: call {{.*}}void {{.+}} @__kmpc_fork_teams({{.+}}, {{.+}}, {{.+}}* [[OMP_OUTLINED_1:@.+]] to {{.+}})
+
+// CHECK: define{{.+}} [[OMP_OUTLINED_1]](i32* {{.+}} [[GTID_IN:%.+]],
+// CHECK: [[GTID_ADDR:%.+]] = alloca i32*,
+// CHECK: store i32* [[GTID_IN]], i32** [[GTID_ADDR]],
+// CHECK: [[GTID_REF:%.+]] = load i32*, i32** [[GTID_ADDR]],
+// CHECK: [[GTID_VAL:%.+]] = load i32, i32* [[GTID_REF]],
+// CHECK: call {{.*}}void @__kmpc_push_proc_bind([[IDENT_T_TY]]* [[DEF_LOC_2]], i32 [[GTID_VAL]], i32 4)
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: ret void
+
+// CHECK: define{{.+}} [[OFFL2]]()
+// CHECK: call {{.*}}void {{.+}} @__kmpc_fork_teams({{.+}}, {{.+}}, {{.+}}* [[OMP_OUTLINED_1:@.+]] to {{.+}})
+
+// CHECK: define{{.+}} [[OMP_OUTLINED_1]](i32* {{.+}} [[GTID_IN:%.+]],
+// CHECK: [[GTID_ADDR:%.+]] = alloca i32*,
+// CHECK: store i32* [[GTID_IN]], i32** [[GTID_ADDR]],
+// CHECK: [[GTID_REF:%.+]] = load i32*, i32** [[GTID_ADDR]],
+// CHECK: [[GTID_VAL:%.+]] = load i32, i32* [[GTID_REF]],
+// CHECK: call {{.*}}void @__kmpc_push_proc_bind([[IDENT_T_TY]]* [[DEF_LOC_2]], i32 [[GTID_VAL]], i32 3)
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: ret void
+
+// CHECK: define{{.+}} [[TMAIN]]()
+// CHECK: call {{.*}}@__tgt_target_teams({{.+}})
+// CHECK: call void [[OFFL3:@.+]]()
+
+// CHECK: define{{.+}} [[OFFL3]]()
+// CHECK: call {{.*}}void {{.+}} @__kmpc_fork_teams({{.+}}, {{.+}}, {{.+}}* [[OMP_OUTLINED_3:@.+]] to {{.+}})
+
+// CHECK: define{{.+}} [[OMP_OUTLINED_3]](i32* {{.+}} [[GTID_IN:%.+]],
+// CHECK: [[GTID_ADDR:%.+]] = alloca i32*,
+// CHECK: store i32* [[GTID_IN]], i32** [[GTID_ADDR]],
+// CHECK: [[GTID_REF:%.+]] = load i32*, i32** [[GTID_ADDR]],
+// CHECK: [[GTID_VAL:%.+]] = load i32, i32* [[GTID_REF]],
+// CHECK: call {{.*}}void @__kmpc_push_proc_bind([[IDENT_T_TY]]* [[DEF_LOC_2]], i32 [[GTID_VAL]], i32 2)
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: ret void
+#endif
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_proc_bind_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_proc_bind_messages.cpp
index 14714124bc4e..3ae5268667d3 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_proc_bind_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_proc_bind_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -o - %s
+
void foo();
template <class T, typename S, int N>
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_reduction_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_reduction_codegen.cpp
new file mode 100644
index 000000000000..e938a7746313
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_reduction_codegen.cpp
@@ -0,0 +1,353 @@
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// SIMD-ONLY-NOT: {{__kmpc|__tgt}}
+
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+template <typename T>
+T tmain() {
+ T t_var = T();
+ T vec[] = {1, 2};
+#pragma omp target teams distribute parallel for simd reduction(+: t_var)
+ for (int i = 0; i < 2; ++i) {
+ t_var += (T) i;
+ }
+ return T();
+}
+
+int main() {
+ static int sivar;
+#ifdef LAMBDA
+ // LAMBDA: [[RED_VAR:@.+]] = common global [8 x {{.+}}] zeroinitializer
+
+ // LAMBDA-LABEL: @main
+ // LAMBDA: call void [[OUTER_LAMBDA:@.+]](
+ [&]() {
+ // LAMBDA: define{{.*}} internal{{.*}} void [[OUTER_LAMBDA]](
+ // LAMBDA: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 1, i8** %{{[^,]+}}, i8** %{{[^,]+}}, i{{64|32}}* {{.+}}@{{[^,]+}}, i32 0, i32 0), i64* {{.+}}@{{[^,]+}}, i32 0, i32 0), i32 0, i32 0)
+ // LAMBDA: call void @[[LOFFL1:.+]](
+ // LAMBDA: ret
+#pragma omp target teams distribute parallel for simd reduction(+: sivar)
+ for (int i = 0; i < 2; ++i) {
+ // LAMBDA: define{{.*}} internal{{.*}} void @[[LOFFL1]](i{{64|32}}*{{.*}} [[SIVAR_ARG:%.+]])
+ // LAMBDA: [[SIVAR_ADDR:%.+]] = alloca i{{.+}},
+ // LAMBDA: store{{.+}} [[SIVAR_ARG]], {{.+}} [[SIVAR_ADDR]],
+ // LAMBDA: [[SIVAR_PAR:%.+]] = load{{.+}}, {{.+}} [[SIVAR_ADDR]],
+ // LAMBDA: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[LOUTL1:.+]] to {{.+}}, {{.+}} [[SIVAR_PAR]])
+ // LAMBDA: ret void
+
+ // LAMBDA: define internal void @[[LOUTL1]]({{.+}}, {{.+}}, {{.+}} [[SIVAR_ARG:%.+]])
+ // Skip global and bound tid vars
+ // LAMBDA: {{.+}} = alloca i32*,
+ // LAMBDA: {{.+}} = alloca i32*,
+ // LAMBDA: [[SIVAR_ADDR:%.+]] = alloca i{{.+}},
+ // LAMBDA: [[SIVAR_PRIV:%.+]] = alloca i{{.+}},
+ // LAMBDA: [[RED_LIST:%.+]] = alloca [1 x {{.+}}],
+ // LAMBDA: store{{.+}} [[SIVAR_ARG]], {{.+}} [[SIVAR_ADDR]],
+ // LAMBDA: [[SIVAR_REF:%.+]] = load{{.+}}, {{.+}} [[SIVAR_ADDR]]
+ // LAMBDA: store{{.+}} 0, {{.+}} [[SIVAR_PRIV]],
+
+ // LAMBDA: call void @__kmpc_for_static_init_4(
+ // LAMBDA: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[LPAR_OUTL:.+]] to
+ // LAMBDA: call void @__kmpc_for_static_fini(
+ // LAMBDA: [[RED_LIST_GEP:%.+]] = getelementptr{{.+}} [[RED_LIST]],
+ // LAMBDA: [[SIVAR_PRIV_CAST:%.+]] = bitcast{{.+}} [[SIVAR_PRIV]] to
+ // LAMBDA: store{{.+}} [[SIVAR_PRIV_CAST]], {{.+}} [[RED_LIST_GEP]],
+ // LAMBDA: [[RED_LIST_BCAST:%.+]] = bitcast{{.+}} [[RED_LIST]] to
+ // LAMBDA: [[K_RED_RET:%.+]] = call{{.+}} @__kmpc_reduce_nowait({{.+}}, {{.+}}, {{.+}}, {{.+}}, {{.+}} [[RED_LIST_BCAST]], {{.+}} [[RED_FUN:@.+]], {{.+}} [[RED_VAR]])
+ // LAMBDA: switch{{.+}} [[K_RED_RET]], label{{.+}} [
+ // LAMBDA: {{.+}}, label %[[CASE1:.+]]
+ // LAMBDA: {{.+}}, label %[[CASE2:.+]]
+ // LAMBDA: ]
+ // LAMBDA: [[CASE1]]:
+ // LAMBDA-DAG: [[SIVAR_VAL:%.+]] = load{{.+}}, {{.+}} [[SIVAR_REF]],
+ // LAMBDA-DAG: [[SIVAR_PRIV_VAL:%.+]] = load{{.+}}, {{.+}} [[SIVAR_PRIV]],
+ // LAMBDA-DAG: [[SIVAR_INC:%.+]] = add{{.+}} [[SIVAR_VAL]], [[SIVAR_PRIV_VAL]]
+ // LAMBDA: store{{.+}} [[SIVAR_INC]], {{.+}} [[SIVAR_REF]],
+ // LAMBDA: call void @__kmpc_end_reduce_nowait({{.+}}, {{.+}}, {{.+}} [[RED_VAR]])
+ // LAMBDA: br
+ // LAMBDA: [[CASE2]]:
+ // LAMBDA-DAG: [[SIVAR_PRIV_VAL:%.+]] = load{{.+}}, {{.+}} [[SIVAR_PRIV]],
+ // LAMBDA-DAG: [[ATOMIC_RES:%.+]] = atomicrmw add{{.+}} [[SIVAR_REF]], {{.+}} [[SIVAR_PRIV_VAL]]
+ // LAMBDA: br
+
+ // LAMBDA: define internal void @[[LPAR_OUTL]]({{.+}}, {{.+}}, {{.+}}, {{.+}}, {{.+}} [[SIVAR_ARG:%.+]])
+
+ // Skip global and bound tid vars, and prev lb and ub vars
+ // LAMBDA: {{.+}} = alloca i32*,
+ // LAMBDA: {{.+}} = alloca i32*,
+ // LAMBDA: alloca i{{[0-9]+}},
+ // LAMBDA: alloca i{{[0-9]+}},
+ // LAMBDA: [[SIVAR_ADDR:%.+]] = alloca i{{.+}},
+ // skip loop vars
+ // LAMBDA: alloca i32,
+ // LAMBDA: alloca i32,
+ // LAMBDA: alloca i32,
+ // LAMBDA: alloca i32,
+ // LAMBDA: alloca i32,
+ // LAMBDA: alloca i32,
+ // LAMBDA: [[SIVAR_PRIV:%.+]] = alloca i{{.+}},
+ // LAMBDA: [[RED_LIST:%.+]] = alloca [1 x {{.+}}],
+ // LAMBDA: store{{.+}} [[SIVAR_ARG]], {{.+}} [[SIVAR_ADDR]],
+ // LAMBDA: [[SIVAR_REF:%.+]] = load {{.+}} [[SIVAR_ADDR]]
+ // LAMBDA: store{{.+}} 0, {{.+}} [[SIVAR_PRIV]],
+
+ // LAMBDA: call void @__kmpc_for_static_init_4(
+ // LAMBDA: store{{.+}}, {{.+}} [[SIVAR_PRIV]],
+ // LAMBDA: call void [[INNER_LAMBDA:@.+]](
+ // LAMBDA: call void @__kmpc_for_static_fini(
+ // LAMBDA: [[RED_LIST_GEP:%.+]] = getelementptr{{.+}} [[RED_LIST]],
+ // LAMBDA: [[SIVAR_PRIV_CAST:%.+]] = bitcast{{.+}} [[SIVAR_PRIV]] to
+ // LAMBDA: store{{.+}} [[SIVAR_PRIV_CAST]], {{.+}} [[RED_LIST_GEP]],
+ // LAMBDA: [[RED_LIST_BCAST:%.+]] = bitcast{{.+}} [[RED_LIST]] to
+ // LAMBDA: [[K_RED_RET:%.+]] = call{{.+}} @__kmpc_reduce_nowait({{.+}}, {{.+}}, {{.+}}, {{.+}}, {{.+}} [[RED_LIST_BCAST]], {{.+}} [[RED_FUN:@.+]], {{.+}} [[RED_VAR]])
+ // LAMBDA: switch{{.+}} [[K_RED_RET]], label{{.+}} [
+ // LAMBDA: {{.+}}, label %[[CASE1:.+]]
+ // LAMBDA: {{.+}}, label %[[CASE2:.+]]
+ // LAMBDA: ]
+ // LAMBDA: [[CASE1]]:
+ // LAMBDA-64-DAG: [[SIVAR_VAL:%.+]] = load{{.+}}, {{.+}} [[SIVAR_REF]],
+ // LAMBDA-32-DAG: [[SIVAR_VAL:%.+]] = load{{.+}}, {{.+}} [[SIVAR_ADDR]],
+ // LAMBDA-DAG: [[SIVAR_PRIV_VAL:%.+]] = load{{.+}}, {{.+}} [[SIVAR_PRIV]],
+ // LAMBDA-DAG: [[SIVAR_INC:%.+]] = add{{.+}} [[SIVAR_VAL]], [[SIVAR_PRIV_VAL]]
+ // LAMBDA: store{{.+}} [[SIVAR_INC]], {{.+}} [[SIVAR_REF]],
+ // LAMBDA: call void @__kmpc_end_reduce_nowait({{.+}}, {{.+}}, {{.+}} [[RED_VAR]])
+ // LAMBDA: br
+ // LAMBDA: [[CASE2]]:
+ // LAMBDA-DAG: [[SIVAR_PRIV_VAL:%.+]] = load{{.+}}, {{.+}} [[SIVAR_PRIV]],
+ // LAMBDA-DAG: [[ATOMIC_RES:%.+]] = atomicrmw add{{.+}} [[SIVAR_REF]], {{.+}} [[SIVAR_PRIV_VAL]]
+ // LAMBDA: br
+
+ sivar += i;
+
+ [&]() {
+ // LAMBDA: define {{.+}} void [[INNER_LAMBDA]](%{{.+}}* [[ARG_PTR:%.+]])
+ // LAMBDA: store %{{.+}}* [[ARG_PTR]], %{{.+}}** [[ARG_PTR_REF:%.+]],
+
+ sivar += 4;
+ // LAMBDA: [[ARG_PTR:%.+]] = load %{{.+}}*, %{{.+}}** [[ARG_PTR_REF]]
+
+ // LAMBDA: [[SIVAR_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
+ // LAMBDA: [[SIVAR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SIVAR_PTR_REF]]
+ // LAMBDA: [[SIVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SIVAR_REF]]
+ // LAMBDA: [[SIVAR_INC:%.+]] = add{{.+}} [[SIVAR_VAL]], 4
+ // LAMBDA: store i{{[0-9]+}} [[SIVAR_INC]], i{{[0-9]+}}* [[SIVAR_REF]]
+ }();
+ }
+ }();
+ return 0;
+#else
+#pragma omp target teams distribute parallel for simd reduction(+: sivar)
+ for (int i = 0; i < 2; ++i) {
+ sivar += i;
+ }
+ return tmain<int>();
+#endif
+}
+
+// CHECK: [[RED_VAR:@.+]] = common global [8 x {{.+}}] zeroinitializer
+
+// CHECK: define {{.*}}i{{[0-9]+}} @main()
+// CHECK: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 1, i8** %{{[^,]+}}, i8** %{{[^,]+}}, i{{64|32}}* {{.+}}@{{[^,]+}}, i32 0, i32 0), i64* {{.+}}@{{[^,]+}}, i32 0, i32 0), i32 0, i32 0)
+// CHECK: call void @[[OFFL1:.+]](i{{64|32}}* @{{.+}})
+// CHECK: {{%.+}} = call{{.*}} i32 @[[TMAIN_INT:.+]]()
+// CHECK: ret
+
+// CHECK: define{{.*}} void @[[OFFL1]](i{{64|32}}*{{.*}} [[SIVAR_ARG:%.+]])
+// CHECK: [[SIVAR_ADDR:%.+]] = alloca i{{.+}},
+// CHECK: store{{.+}} [[SIVAR_ARG]], {{.+}} [[SIVAR_ADDR]],
+// CHECK: [[SIVAR_VAL:%.+]] = load{{.+}}, {{.+}} [[SIVAR_ADDR]]
+// CHECK: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[OUTL1:.+]] to {{.+}}, {{.+}} [[SIVAR_VAL]])
+// CHECK: ret void
+
+// CHECK: define internal void @[[OUTL1]]({{.+}}, {{.+}}, {{.+}} [[SIVAR_ARG:%.+]])
+// Skip global and bound tid vars
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: [[SIVAR_ADDR:%.+]] = alloca i{{.+}},
+// CHECK: [[SIVAR_PRIV:%.+]] = alloca i{{.+}},
+// CHECK: [[RED_LIST:%.+]] = alloca [1 x {{.+}}],
+// CHECK: store{{.+}} [[SIVAR_ARG]], {{.+}} [[SIVAR_ADDR]],
+// CHECK: [[SIVAR_REF:%.+]] = load{{.+}} [[SIVAR_ADDR]],
+// CHECK: store{{.+}} 0, {{.+}} [[SIVAR_PRIV]],
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL:.+]] to
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: [[RED_LIST_GEP:%.+]] = getelementptr{{.+}} [[RED_LIST]],
+// CHECK: [[SIVAR_PRIV_CAST:%.+]] = bitcast{{.+}} [[SIVAR_PRIV]] to
+// CHECK: store{{.+}} [[SIVAR_PRIV_CAST]], {{.+}} [[RED_LIST_GEP]],
+// CHECK: [[RED_LIST_BCAST:%.+]] = bitcast{{.+}} [[RED_LIST]] to
+// CHECK: [[K_RED_RET:%.+]] = call{{.+}} @__kmpc_reduce_nowait({{.+}}, {{.+}}, {{.+}}, {{.+}}, {{.+}} [[RED_LIST_BCAST]], {{.+}} [[RED_FUN:@.+]], {{.+}} [[RED_VAR]])
+// CHECK: switch{{.+}} [[K_RED_RET]], label{{.+}} [
+// CHECK: {{.+}}, label %[[CASE1:.+]]
+// CHECK: {{.+}}, label %[[CASE2:.+]]
+// CHECK: ]
+// CHECK: [[CASE1]]:
+// CHECK-DAG: [[SIVAR_VAL:%.+]] = load{{.+}}, {{.+}} [[SIVAR_REF]],
+// CHECK-DAG: [[SIVAR_PRIV_VAL:%.+]] = load{{.+}}, {{.+}} [[SIVAR_PRIV]],
+// CHECK-DAG: [[SIVAR_INC:%.+]] = add{{.+}} [[SIVAR_VAL]], [[SIVAR_PRIV_VAL]]
+// CHECK: store{{.+}} [[SIVAR_INC]], {{.+}} [[SIVAR_REF]],
+// CHECK: call void @__kmpc_end_reduce_nowait({{.+}}, {{.+}}, {{.+}} [[RED_VAR]])
+// CHECK: br
+// CHECK: [[CASE2]]:
+// CHECK-DAG: [[SIVAR_PRIV_VAL:%.+]] = load{{.+}}, {{.+}} [[SIVAR_PRIV]],
+// CHECK-DAG: [[ATOMIC_RES:%.+]] = atomicrmw add{{.+}} [[SIVAR_REF]], {{.+}} [[SIVAR_PRIV_VAL]]
+// CHECK: br
+
+// CHECK: define internal void @[[PAR_OUTL]]({{.+}}, {{.+}}, {{.+}}, {{.+}}, {{.+}} [[SIVAR_ARG:%.+]])
+// Skip global and bound tid vars, and prev lb and ub
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: [[SIVAR_ADDR:%.+]] = alloca i{{.+}},
+// skip loop vars
+// CHECK: alloca i32,
+// CHECK: alloca i32,
+// CHECK: alloca i32,
+// CHECK: alloca i32,
+// CHECK: alloca i32,
+// CHECK: alloca i32,
+// CHECK: [[SIVAR_PRIV:%.+]] = alloca i{{.+}},
+// CHECK: [[RED_LIST:%.+]] = alloca [1 x {{.+}}],
+// CHECK: store{{.+}} [[SIVAR_ARG]], {{.+}} [[SIVAR_ADDR]],
+// CHECK-64: [[SIVAR_REF:%.+]] = load {{.+}} [[SIVAR_ADDR]],
+// CHECK: store{{.+}} 0, {{.+}} [[SIVAR_PRIV]],
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: store{{.+}}, {{.+}} [[SIVAR_PRIV]],
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: [[RED_LIST_GEP:%.+]] = getelementptr{{.+}} [[RED_LIST]],
+// CHECK: [[SIVAR_PRIV_CAST:%.+]] = bitcast{{.+}} [[SIVAR_PRIV]] to
+// CHECK: store{{.+}} [[SIVAR_PRIV_CAST]], {{.+}} [[RED_LIST_GEP]],
+// CHECK: [[RED_LIST_BCAST:%.+]] = bitcast{{.+}} [[RED_LIST]] to
+// CHECK: [[K_RED_RET:%.+]] = call{{.+}} @__kmpc_reduce_nowait({{.+}}, {{.+}}, {{.+}}, {{.+}}, {{.+}} [[RED_LIST_BCAST]], {{.+}} [[RED_FUN:@.+]], {{.+}} [[RED_VAR]])
+// CHECK: switch{{.+}} [[K_RED_RET]], label{{.+}} [
+// CHECK: {{.+}}, label %[[CASE1:.+]]
+// CHECK: {{.+}}, label %[[CASE2:.+]]
+// CHECK: ]
+// CHECK: [[CASE1]]:
+// CHECK-DAG: [[SIVAR_VAL:%.+]] = load{{.+}}, {{.+}} [[SIVAR_REF]],
+// CHECK-DAG: [[SIVAR_PRIV_VAL:%.+]] = load{{.+}}, {{.+}} [[SIVAR_PRIV]],
+// CHECK-DAG: [[SIVAR_INC:%.+]] = add{{.+}} [[SIVAR_VAL]], [[SIVAR_PRIV_VAL]]
+// CHECK: store{{.+}} [[SIVAR_INC]], {{.+}} [[SIVAR_REF]],
+// CHECK: call void @__kmpc_end_reduce_nowait({{.+}}, {{.+}}, {{.+}} [[RED_VAR]])
+// CHECK: br
+// CHECK: [[CASE2]]:
+// CHECK-DAG: [[SIVAR_PRIV_VAL:%.+]] = load{{.+}}, {{.+}} [[SIVAR_PRIV]],
+// CHECK-DAG: [[ATOMIC_RES:%.+]] = atomicrmw add{{.+}} [[SIVAR_REF]], {{.+}} [[SIVAR_PRIV_VAL]]
+// CHECK: br
+
+// CHECK: define{{.*}} i{{[0-9]+}} @[[TMAIN_INT]]()
+// CHECK: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 1,
+// CHECK: call void @[[TOFFL1:.+]]({{.+}})
+// CHECK: ret
+
+// CHECK: define{{.*}} void @[[TOFFL1]](i{{64|32}}*{{.*}} [[TVAR_ARG:%.+]])
+// CHECK: [[TVAR_ADDR:%.+]] = alloca i{{.+}},
+// CHECK: store{{.+}} [[TVAR_ARG]], {{.+}} [[TVAR_ADDR]],
+// CHECK: [[TVAR_VAL:%.+]] = load{{.+}}, {{.+}} [[TVAR_ADDR]]
+// CHECK: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[TOUTL1:.+]] to {{.+}}, {{.+}} [[TVAR_VAL]])
+// CHECK: ret void
+
+// CHECK: define internal void @[[TOUTL1]]({{.+}}, {{.+}}, {{.+}} [[TVAR_ARG:%.+]])
+// Skip global and bound tid vars
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: [[TVAR_ADDR:%.+]] = alloca i{{.+}},
+// CHECK: [[TVAR_PRIV:%.+]] = alloca i{{.+}},
+// CHECK: [[RED_LIST:%.+]] = alloca [1 x {{.+}}],
+// CHECK: store{{.+}} [[TVAR_ARG]], {{.+}} [[TVAR_ADDR]],
+// CHECK: [[TVAR_REF:%.+]] = load {{.+}} [[TVAR_ADDR]],
+// CHECK: store{{.+}} 0, {{.+}} [[TVAR_PRIV]],
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[TPAR_OUTL:.+]] to
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: [[RED_LIST_GEP:%.+]] = getelementptr{{.+}} [[RED_LIST]],
+// CHECK: [[TVAR_PRIV_CAST:%.+]] = bitcast{{.+}} [[TVAR_PRIV]] to
+// CHECK: store{{.+}} [[TVAR_PRIV_CAST]], {{.+}} [[RED_LIST_GEP]],
+// CHECK: [[RED_LIST_BCAST:%.+]] = bitcast{{.+}} [[RED_LIST]] to
+// CHECK: [[K_RED_RET:%.+]] = call{{.+}} @__kmpc_reduce_nowait({{.+}}, {{.+}}, {{.+}}, {{.+}}, {{.+}} [[RED_LIST_BCAST]], {{.+}} [[RED_FUN:@.+]], {{.+}} [[RED_VAR]])
+// CHECK: switch{{.+}} [[K_RED_RET]], label{{.+}} [
+// CHECK: {{.+}}, label %[[CASE1:.+]]
+// CHECK: {{.+}}, label %[[CASE2:.+]]
+// CHECK: ]
+// CHECK: [[CASE1]]:
+// CHECK-DAG: [[TVAR_VAL:%.+]] = load{{.+}}, {{.+}} [[TVAR_REF]],
+// CHECK-DAG: [[TVAR_PRIV_VAL:%.+]] = load{{.+}}, {{.+}} [[TVAR_PRIV]],
+// CHECK-DAG: [[TVAR_INC:%.+]] = add{{.+}} [[TVAR_VAL]], [[TVAR_PRIV_VAL]]
+// CHECK: store{{.+}} [[TVAR_INC]], {{.+}} [[TVAR_REF]],
+// CHECK: call void @__kmpc_end_reduce_nowait({{.+}}, {{.+}}, {{.+}} [[RED_VAR]])
+// CHECK: br
+// CHECK: [[CASE2]]:
+// CHECK-DAG: [[TVAR_PRIV_VAL:%.+]] = load{{.+}}, {{.+}} [[TVAR_PRIV]],
+// CHECK-DAG: [[ATOMIC_RES:%.+]] = atomicrmw add{{.+}} [[TVAR_REF]], {{.+}} [[TVAR_PRIV_VAL]]
+// CHECK: br
+
+// CHECK: define internal void @[[TPAR_OUTL]]({{.+}}, {{.+}}, {{.+}}, {{.+}}, {{.+}} [[TVAR_ARG:%.+]])
+// Skip global and bound tid vars, and prev lb and ub vars
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: {{.+}} = alloca i32*,
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: [[TVAR_ADDR:%.+]] = alloca i{{.+}},
+// skip loop vars
+// CHECK: alloca i32,
+// CHECK: alloca i32,
+// CHECK: alloca i32,
+// CHECK: alloca i32,
+// CHECK: alloca i32,
+// CHECK: alloca i32,
+// CHECK: [[TVAR_PRIV:%.+]] = alloca i{{.+}},
+// CHECK: [[RED_LIST:%.+]] = alloca [1 x {{.+}}],
+// CHECK: store{{.+}} [[TVAR_ARG]], {{.+}} [[TVAR_ADDR]],
+// CHECK: [[TVAR_REF:%.+]] = load {{.+}} [[TVAR_ADDR]],
+// CHECK: store{{.+}} 0, {{.+}} [[TVAR_PRIV]],
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: store{{.+}}, {{.+}} [[TVAR_PRIV]],
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: [[RED_LIST_GEP:%.+]] = getelementptr{{.+}} [[RED_LIST]],
+// CHECK: [[TVAR_PRIV_CAST:%.+]] = bitcast{{.+}} [[TVAR_PRIV]] to
+// CHECK: store{{.+}} [[TVAR_PRIV_CAST]], {{.+}} [[RED_LIST_GEP]],
+// CHECK: [[RED_LIST_BCAST:%.+]] = bitcast{{.+}} [[RED_LIST]] to
+// CHECK: [[K_RED_RET:%.+]] = call{{.+}} @__kmpc_reduce_nowait({{.+}}, {{.+}}, {{.+}}, {{.+}}, {{.+}} [[RED_LIST_BCAST]], {{.+}} [[RED_FUN:@.+]], {{.+}} [[RED_VAR]])
+// CHECK: switch{{.+}} [[K_RED_RET]], label{{.+}} [
+// CHECK: {{.+}}, label %[[CASE1:.+]]
+// CHECK: {{.+}}, label %[[CASE2:.+]]
+// CHECK: ]
+// CHECK: [[CASE1]]:
+// CHECK-DAG: [[TVAR_VAL:%.+]] = load{{.+}}, {{.+}} [[TVAR_REF]],
+// CHECK-DAG: [[TVAR_PRIV_VAL:%.+]] = load{{.+}}, {{.+}} [[TVAR_PRIV]],
+// CHECK-DAG: [[TVAR_INC:%.+]] = add{{.+}} [[TVAR_VAL]], [[TVAR_PRIV_VAL]]
+// CHECK: store{{.+}} [[TVAR_INC]], {{.+}} [[TVAR_REF]],
+// CHECK: call void @__kmpc_end_reduce_nowait({{.+}}, {{.+}}, {{.+}} [[RED_VAR]])
+// CHECK: br
+// CHECK: [[CASE2]]:
+// CHECK-DAG: [[TVAR_PRIV_VAL:%.+]] = load{{.+}}, {{.+}} [[TVAR_PRIV]],
+// CHECK-DAG: [[ATOMIC_RES:%.+]] = atomicrmw add{{.+}} [[TVAR_REF]], {{.+}} [[TVAR_PRIV_VAL]]
+// CHECK: br
+#endif
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_reduction_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_reduction_messages.cpp
index 63744c77fb3a..8cd4acd878d0 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_reduction_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_reduction_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_safelen_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_safelen_messages.cpp
index beb3c1e84580..f068e6b2e475 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_safelen_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_safelen_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_schedule_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_schedule_codegen.cpp
new file mode 100644
index 000000000000..799769739d97
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_schedule_codegen.cpp
@@ -0,0 +1,400 @@
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+// Test host codegen.
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-64
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-64
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// SIMD-ONLY-NOT: {{__kmpc|__tgt}}
+
+#ifdef CK1
+
+template <typename T, int X, long long Y>
+struct SS{
+ T a[X];
+ float b;
+ // CK1: define {{.*}}i32 @{{.+}}foo{{.+}}(
+ int foo(void) {
+
+ // CK1: call i32 @__tgt_target_teams(
+ // CK1: call void @[[OFFL1:.+]](
+ #pragma omp target teams distribute parallel for simd
+ for(int i = 0; i < X; i++) {
+ a[i] = (T)0;
+ }
+ // CK1: call i32 @__tgt_target_teams(
+ // CK1: call void @[[OFFL2:.+]](
+ #pragma omp target teams distribute parallel for simd schedule(static)
+ for(int i = 0; i < X; i++) {
+ a[i] = (T)0;
+ }
+ // CK1: call i32 @__tgt_target_teams(
+ // CK1: call void @[[OFFL3:.+]](
+ #pragma omp target teams distribute parallel for simd schedule(static, X/2)
+ for(int i = 0; i < X; i++) {
+ a[i] = (T)0;
+ }
+
+ // CK1: call i32 @__tgt_target_teams(
+ // CK1: call void @[[OFFL4:.+]](
+ #pragma omp target teams distribute parallel for simd schedule(dynamic)
+ for(int i = 0; i < X; i++) {
+ a[i] = (T)0;
+ }
+
+ // CK1: call i32 @__tgt_target_teams(
+ // CK1: call void @[[OFFL5:.+]](
+ #pragma omp target teams distribute parallel for simd schedule(dynamic, X/2)
+ for(int i = 0; i < X; i++) {
+ a[i] = (T)0;
+ }
+
+ // CK1: define internal void @[[OFFL1]](
+ // CK1: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[OUTL1:.+]] to {{.+}},
+ // CK1: ret void
+
+ // CK1: define internal void @[[OUTL1]]({{.+}})
+ // CK1: call void @__kmpc_for_static_init_4(
+ // CK1: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL1:.+]] to
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ // CK1: define internal void @[[PAR_OUTL1]]({{.+}})
+ // CK1: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 34,
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ // CK1: define internal void @[[OFFL2]](
+ // CK1: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[OUTL2:.+]] to {{.+}},
+ // CK1: ret void
+
+ // CK1: define internal void @[[OUTL2]]({{.+}})
+ // CK1: call void @__kmpc_for_static_init_4(
+ // CK1: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL2:.+]] to
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ // CK1: define internal void @[[PAR_OUTL2]]({{.+}})
+ // CK1: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 34,
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ // CK1: define internal void @[[OFFL3]](
+ // CK1: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[OUTL3:.+]] to {{.+}},
+ // CK1: ret void
+
+ // CK1: define internal void @[[OUTL3]]({{.+}})
+ // CK1: call void @__kmpc_for_static_init_4(
+ // CK1: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL3:.+]] to
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ // CK1: define internal void @[[PAR_OUTL3]]({{.+}})
+ // CK1: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 33,
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ // CK1: define internal void @[[OFFL4]](
+ // CK1: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[OUTL4:.+]] to {{.+}},
+ // CK1: ret void
+
+ // CK1: define internal void @[[OUTL4]]({{.+}})
+ // CK1: call void @__kmpc_for_static_init_4(
+ // CK1: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL4:.+]] to
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ // CK1: define internal void @[[PAR_OUTL4]]({{.+}})
+ // CK1: call void @__kmpc_dispatch_init_4({{.+}}, {{.+}}, i32 35,
+ // CK1: call {{.+}} @__kmpc_dispatch_next_4(
+ // CK1: ret void
+
+ // CK1: define internal void @[[OFFL5]](
+ // CK1: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[OUTL5:.+]] to {{.+}},
+ // CK1: ret void
+
+ // CK1: define internal void @[[OUTL5]]({{.+}})
+ // CK1: call void @__kmpc_for_static_init_4(
+ // CK1: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL5:.+]] to
+ // CK1: call void @__kmpc_for_static_fini(
+ // CK1: ret void
+
+ // CK1: define internal void @[[PAR_OUTL5]]({{.+}})
+ // CK1: call void @__kmpc_dispatch_init_4({{.+}}, {{.+}}, i32 35,
+ // CK1: call {{.+}} @__kmpc_dispatch_next_4(
+ // CK1: ret void
+
+ return a[0];
+ }
+};
+
+int teams_template_struct(void) {
+ SS<int, 123, 456> V;
+ return V.foo();
+
+}
+#endif // CK1
+
+// Test host codegen.
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-64
+// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-64
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY
+// SIMD-ONLY-NOT: {{__kmpc|__tgt}}
+#ifdef CK2
+
+template <typename T, int n>
+int tmain(T argc) {
+ T a[n];
+ int m = 10;
+#pragma omp target teams distribute parallel for simd
+ for(int i = 0; i < n; i++) {
+ a[i] = (T)0;
+ }
+#pragma omp target teams distribute parallel for simd schedule(static)
+ for(int i = 0; i < n; i++) {
+ a[i] = (T)0;
+ }
+#pragma omp target teams distribute parallel for simd schedule(static, m)
+ for(int i = 0; i < n; i++) {
+ a[i] = (T)0;
+ }
+#pragma omp target teams distribute parallel for simd schedule(dynamic)
+ for(int i = 0; i < n; i++) {
+ a[i] = (T)0;
+ }
+#pragma omp target teams distribute parallel for simd schedule(dynamic, m)
+ for(int i = 0; i < n; i++) {
+ a[i] = (T)0;
+ }
+ return 0;
+}
+
+int main (int argc, char **argv) {
+ int n = 100;
+ int a[n];
+ int m = 10;
+#pragma omp target teams distribute parallel for simd
+ for(int i = 0; i < n; i++) {
+ a[i] = 0;
+ }
+#pragma omp target teams distribute parallel for simd dist_schedule(static)
+ for(int i = 0; i < n; i++) {
+ a[i] = 0;
+ }
+#pragma omp target teams distribute parallel for simd dist_schedule(static, m)
+ for(int i = 0; i < n; i++) {
+ a[i] = 0;
+ }
+#pragma omp target teams distribute parallel for simd schedule(dynamic)
+ for(int i = 0; i < n; i++) {
+ a[i] = 0;
+ }
+#pragma omp target teams distribute parallel for simd schedule(dynamic, m)
+ for(int i = 0; i < n; i++) {
+ a[i] = 0;
+ }
+ return tmain<int, 10>(argc);
+}
+
+// CK2: define {{.*}}i32 @{{[^,]+}}(i{{.+}}{{.+}} %[[ARGC:.+]], {{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFL1:.+]]({{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFL2:.+]]({{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFL3:.+]]({{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFL4:.+]]({{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFL5:.+]]({{.+}})
+// CK2: {{%.+}} = call{{.*}} i32 @[[TMAIN:.+]]({{.+}})
+// CK2: ret
+
+// CK2: define {{.*}}void @[[OFFL1]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 3, {{.+}} @[[OUTL1:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTL1]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4(
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL1:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTL1]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 34,
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define {{.*}}void @[[OFFL2]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 3, {{.+}} @[[OUTL2:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTL2]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4(
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL2:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTL2]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 34,
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define {{.*}}void @[[OFFL3]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 4, {{.+}} @[[OUTL3:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTL3]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4(
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL3:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTL3]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 34
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define {{.*}}void @[[OFFL4]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 {{.+}}, {{.+}} @[[OUTL4:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTL4]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4(
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL4:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTL4]]({{.+}})
+// CK2: call void @__kmpc_dispatch_init_4({{.+}}, {{.+}}, i32 35,
+// CK2: call {{.+}} @__kmpc_dispatch_next_4(
+// CK2: ret void
+
+
+// CK2: define {{.*}}void @[[OFFL5]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 {{.+}}, {{.+}} @[[OUTL5:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTL5]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4(
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL5:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTL5]]({{.+}})
+// CK2: call void @__kmpc_dispatch_init_4({{.+}}, {{.+}}, i32 35,
+// CK2: call {{.+}} @__kmpc_dispatch_next_4(
+// CK2: ret void
+
+// CK2: define {{.*}}i32 @[[TMAIN]]({{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFLT1:.+]]({{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFLT2:.+]]({{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFLT3:.+]]({{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFLT4:.+]]({{.+}})
+// CK2: call i32 @__tgt_target_teams(
+// CK2: call void @[[OFFLT5:.+]]({{.+}})
+// CK2: ret
+// CK2-NEXT: }
+
+// CK2: define {{.*}}void @[[OFFLT1]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[OUTLT1:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTLT1]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4(
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTLT1:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTLT1]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 34,
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define {{.*}}void @[[OFFLT2]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 1, {{.+}} @[[OUTLT2:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTLT2]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4(
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTLT2:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTLT2]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 34,
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define {{.*}}void @[[OFFLT3]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 {{.+}}, {{.+}} @[[OUTLT3:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTLT3]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4(
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTLT3:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTLT3]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 33,
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define {{.*}}void @[[OFFLT4]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 {{.+}}, {{.+}} @[[OUTLT4:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTLT4]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4(
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTLT4:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTLT4]]({{.+}})
+// CK2: call void @__kmpc_dispatch_init_4({{.+}}, {{.+}}, i32 35,
+// CK2: call {{.+}} @__kmpc_dispatch_next_4(
+// CK2: ret void
+
+// CK2: define {{.*}}void @[[OFFLT5]]({{.+}})
+// CK2: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 {{.+}}, {{.+}} @[[OUTLT5:.+]] to {{.+}},
+// CK2: ret void
+
+// CK2: define internal void @[[OUTLT5]]({{.+}})
+// CK2: call void @__kmpc_for_static_init_4(
+// CK2: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTLT5:.+]] to
+// CK2: call void @__kmpc_for_static_fini(
+// CK2: ret void
+
+// CK2: define internal void @[[PAR_OUTLT5]]({{.+}})
+// CK2: call void @__kmpc_dispatch_init_4({{.+}}, {{.+}}, i32 35,
+// CK2: call {{.+}} @__kmpc_dispatch_next_4(
+// CK2: ret void
+
+#endif // CK2
+#endif // #ifndef HEADER
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_schedule_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_schedule_messages.cpp
index 773a148f9bba..c24a54318428 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_schedule_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_schedule_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_shared_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_shared_messages.cpp
index cbef07a4d069..f59ecbd58378 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_shared_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_shared_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_simdlen_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_simdlen_messages.cpp
index c2a82d5bfc28..d5f714c9c308 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_simdlen_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_simdlen_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_thread_limit_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_thread_limit_messages.cpp
index 159d1b0f518d..ea8b1a77513e 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_thread_limit_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_thread_limit_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_thread_limit_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_thread_limit_messages.cpp
index 1db07262931e..bd04e934a245 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_thread_limit_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_thread_limit_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_private_codegen.cpp b/test/OpenMP/target_teams_distribute_private_codegen.cpp
index 7c88c01c4ab3..f52d3b040f04 100644
--- a/test/OpenMP/target_teams_distribute_private_codegen.cpp
+++ b/test/OpenMP/target_teams_distribute_private_codegen.cpp
@@ -1,13 +1,26 @@
-// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
diff --git a/test/OpenMP/target_teams_distribute_private_messages.cpp b/test/OpenMP/target_teams_distribute_private_messages.cpp
index fcbd4f87162a..df7b68919ca5 100644
--- a/test/OpenMP/target_teams_distribute_private_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_private_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_reduction_codegen.cpp b/test/OpenMP/target_teams_distribute_reduction_codegen.cpp
index 188b75306453..704bf0012016 100644
--- a/test/OpenMP/target_teams_distribute_reduction_codegen.cpp
+++ b/test/OpenMP/target_teams_distribute_reduction_codegen.cpp
@@ -5,10 +5,23 @@
// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/target_teams_distribute_reduction_messages.cpp b/test/OpenMP/target_teams_distribute_reduction_messages.cpp
index 3cfb08651a61..38878fc74c74 100644
--- a/test/OpenMP/target_teams_distribute_reduction_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_reduction_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_shared_messages.cpp b/test/OpenMP/target_teams_distribute_shared_messages.cpp
index 13f4d471f1d1..37e0aa1b5b6e 100644
--- a/test/OpenMP/target_teams_distribute_shared_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_shared_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_simd_aligned_messages.cpp b/test/OpenMP/target_teams_distribute_simd_aligned_messages.cpp
index d91cfa9b54ae..2ec53ee99e09 100644
--- a/test/OpenMP/target_teams_distribute_simd_aligned_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_aligned_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -x c++ -std=c++11 -verify -fopenmp %s
+// RUN: %clang_cc1 -x c++ -std=c++11 -verify -fopenmp-simd %s
+
struct B {
static int ib[20]; // expected-note 0 {{'B::ib' declared here}}
static constexpr int bfoo() { return 8; }
diff --git a/test/OpenMP/target_teams_distribute_simd_ast_print.cpp b/test/OpenMP/target_teams_distribute_simd_ast_print.cpp
index 31b9ad0c5fc1..a96863572a0f 100644
--- a/test/OpenMP/target_teams_distribute_simd_ast_print.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_ast_print.cpp
@@ -1,6 +1,10 @@
-// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -ast-print %s -Wno-openmp-target | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-target | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s -Wno-openmp-target | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-target | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -103,7 +107,7 @@ T tmain(T argc) {
#pragma omp target teams distribute simd
for (int i=0; i < 2; ++i)
a = 2;
-// CHECK: #pragma omp target teams distribute simd
+// CHECK: #pragma omp target teams distribute simd{{$}}
// CHECK-NEXT: for (int i = 0; i < 2; ++i)
// CHECK-NEXT: a = 2;
#pragma omp target teams distribute simd private(argc, b), firstprivate(c, d), collapse(2)
diff --git a/test/OpenMP/target_teams_distribute_simd_codegen.cpp b/test/OpenMP/target_teams_distribute_simd_codegen.cpp
index 7fb76d9198db..c400e0867154 100644
--- a/test/OpenMP/target_teams_distribute_simd_codegen.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_codegen.cpp
@@ -1,28 +1,46 @@
// Test host codegen.
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// Test target codegen - host bc file has to be created first.
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-64
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-64
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-32
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
-// CHECK-DAG: %ident_t = type { i32, i32, i32, i32, i8* }
+// CHECK-DAG: %struct.ident_t = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr constant %ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
// CHECK-DAG: [[TT:%.+]] = type { i64, i8 }
// CHECK-DAG: [[S1:%.+]] = type { double }
@@ -39,33 +57,33 @@
// sizes.
// CHECK-DAG: [[SIZET:@.+]] = private unnamed_addr constant [3 x i[[SZ]]] [i[[SZ]] 2, i[[SZ]] 4, i[[SZ]] 4]
-// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [3 x i64] [i64 288, i64 288, i64 288]
+// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [3 x i64] [i64 800, i64 800, i64 800]
// CHECK-DAG: [[SIZET2:@.+]] = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 2]
-// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [1 x i64] [i64 288]
+// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [1 x i64] [i64 800]
// CHECK-DAG: [[SIZET3:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2]
-// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [2 x i64] [i64 288, i64 288]
-// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [9 x i64] [i64 288, i64 547, i64 288, i64 547, i64 547, i64 288, i64 288, i64 547, i64 547]
-// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [5 x i64] [i64 547, i64 288, i64 288, i64 288, i64 547]
+// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [2 x i64] [i64 800, i64 800]
+// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [9 x i64] [i64 800, i64 547, i64 288, i64 547, i64 547, i64 288, i64 288, i64 547, i64 547]
+// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [6 x i64] [i64 32, i64 281474976711171, i64 800, i64 288, i64 288, i64 547]
// CHECK-DAG: [[SIZET6:@.+]] = private unnamed_addr constant [5 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 4, i[[SZ]] 2, i[[SZ]] 1, i[[SZ]] 40]
-// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [5 x i64] [i64 288, i64 288, i64 288, i64 288, i64 547]
+// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [5 x i64] [i64 800, i64 800, i64 800, i64 800, i64 547]
// CHECK-DAG: [[SIZET7:@.+]] = private unnamed_addr constant [3 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2, i[[SZ]] 40]
-// CHECK-DAG: [[MAPT7:@.+]] = private unnamed_addr constant [3 x i64] [i64 288, i64 288, i64 547]
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK-NOT: @{{.+}} = constant [[ENTTY]]
+// CHECK-DAG: [[MAPT7:@.+]] = private unnamed_addr constant [3 x i64] [i64 800, i64 800, i64 547]
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -76,7 +94,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx, typename ty>
@@ -202,13 +220,13 @@ int foo(int n) {
// CHECK-32: store i32 [[A_VAL]], i32* [[A_CADDR:%.+]],
// CHECK-32: [[A_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[A_CADDR]],
+ // CHECK: [[IF:%.+]] = icmp sgt i32 {{[^,]+}}, 20
+ // CHECK: br i1 [[IF]], label %[[TRY:[^,]+]], label %[[FAIL:[^,]+]]
+ // CHECK: [[TRY]]
// CHECK: [[BNSIZE:%.+]] = mul nuw i[[SZ]] [[VLA0:%.+]], 4
// CHECK: [[CNELEMSIZE2:%.+]] = mul nuw i[[SZ]] 5, [[VLA1:%.+]]
// CHECK: [[CNSIZE:%.+]] = mul nuw i[[SZ]] [[CNELEMSIZE2]], 8
- // CHECK: [[IF:%.+]] = icmp sgt i32 {{[^,]+}}, 20
- // CHECK: br i1 [[IF]], label %[[TRY:[^,]+]], label %[[FAIL:[^,]+]]
- // CHECK: [[TRY]]
// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 9, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([9 x i64], [9 x i64]* [[MAPT4]], i32 0, i32 0), i32 0, i32 0)
// CHECK-DAG: [[BPR]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BP:%[^,]+]], i32 0, i32 0
// CHECK-DAG: [[PR]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P:%[^,]+]], i32 0, i32 0
@@ -323,11 +341,12 @@ int foo(int n) {
// correct and loaded correctly for the target regions in foo().
// CHECK: define internal void [[HVT0]](i[[SZ]] {{[^,]+}}, i[[SZ]] {{[^,]+}}, i[[SZ]] {{[^)]+}})
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]])* [[OMP_OUTLINED:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] {{[^)]+}})
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]])* [[OMP_OUTLINED:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] {{[^)]+}})
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] {{[^)]+}})
-// CHECK: alloca i16,
+// CHECK: alloca i[[SZ]],
+// CHECK: bitcast i[[SZ]]* {{.+}} to i16*
// CHECK: ret void
// CHECK-NEXT: }
@@ -344,7 +363,7 @@ int foo(int n) {
// CHECK-64: store i32 [[AA]], i32* [[AA_C]], align
// CHECK-32: store i32 [[AA]], i32* [[AA_CASTED]], align
// CHECK: [[PARAM:%.+]] = load i[[SZ]], i[[SZ]]* [[AA_CASTED]], align
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]])* [[OMP_OUTLINED1:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]])* [[OMP_OUTLINED1:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED1]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}})
@@ -366,7 +385,7 @@ int foo(int n) {
// CHECK: [[AA_C:%.+]] = bitcast i[[SZ]]* [[AA_CASTED]] to i16*
// CHECK: store i16 [[AA]], i16* [[AA_C]], align
// CHECK: [[PARAM:%.+]] = load i[[SZ]], i[[SZ]]* [[AA_CASTED]], align
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]])* [[OMP_OUTLINED2:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]])* [[OMP_OUTLINED2:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED2]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}})
@@ -397,7 +416,7 @@ int foo(int n) {
// CHECK-DAG: store i16 [[AA]], i16* [[AA_C]], align
// CHECK-DAG: [[PARAM1:%.+]] = load i[[SZ]], i[[SZ]]* [[A_CASTED]], align
// CHECK-DAG: [[PARAM2:%.+]] = load i[[SZ]], i[[SZ]]* [[AA_CASTED]], align
-// CHECK-DAG: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 2, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]])* [[OMP_OUTLINED3:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM1]], i[[SZ]] [[PARAM2]])
+// CHECK-DAG: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 2, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]])* [[OMP_OUTLINED3:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[PARAM1]], i[[SZ]] [[PARAM2]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED3]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}})
@@ -449,7 +468,7 @@ int foo(int n) {
// CHECK-32-DAG:store i32 [[LOCAL_AV]], i32* [[LOCAL_A_CASTED]], align
// CHECK-DAG: [[REF_A:%.+]] = load i[[SZ]], i[[SZ]]* [[LOCAL_A_CASTED]],
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 9, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], [10 x float]*, i[[SZ]], float*, [5 x [10 x double]]*, i[[SZ]], i[[SZ]], double*, [[TT]]*)* [[OMP_OUTLINED4:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], [10 x float]* [[REF_B]], i[[SZ]] [[VAL_VLA1]], float* [[REF_BN]], [5 x [10 x double]]* [[REF_C]], i[[SZ]] [[VAL_VLA2]], i[[SZ]] [[VAL_VLA3]], double* [[REF_CN]], [[TT]]* [[REF_D]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 9, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], [10 x float]*, i[[SZ]], float*, [5 x [10 x double]]*, i[[SZ]], i[[SZ]], double*, [[TT]]*)* [[OMP_OUTLINED4:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], [10 x float]* [[REF_B]], i[[SZ]] [[VAL_VLA1]], float* [[REF_BN]], [5 x [10 x double]]* [[REF_C]], i[[SZ]] [[VAL_VLA2]], i[[SZ]] [[VAL_VLA3]], double* [[REF_CN]], [[TT]]* [[REF_D]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED4]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}}, [10 x float]* {{.+}}, i[[SZ]] %{{.+}}, float* {{.+}}, [5 x [10 x double]]* {{.+}}, i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, double* {{.+}}, [[TT]]* {{.+}})
@@ -534,32 +553,39 @@ int bar(int n){
// CHECK-64: store i32 %{{.+}}, i32* [[B_ADDR]],
// CHECK-64: [[B_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[B_CADDR]],
+// CHECK-32: store i32 %{{.+}}, i32* %__vla_expr
// CHECK-32: store i32 %{{.+}}, i32* [[B_ADDR:%.+]],
// CHECK-32: [[B_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[B_ADDR]],
+// CHECK: [[IF:%.+]] = icmp sgt i32 {{[^,]+}}, 60
+// CHECK: br i1 [[IF]], label %[[TRY:[^,]+]], label %[[FAIL:[^,]+]]
+// CHECK: [[TRY]]
// We capture 2 VLA sizes in this target region
// CHECK: [[CELEMSIZE2:%.+]] = mul nuw i[[SZ]] 2, [[VLA0:%.+]]
// CHECK: [[CSIZE:%.+]] = mul nuw i[[SZ]] [[CELEMSIZE2]], 2
-// CHECK: [[IF:%.+]] = icmp sgt i32 {{[^,]+}}, 60
-// CHECK: br i1 [[IF]], label %[[TRY:[^,]+]], label %[[FAIL:[^,]+]]
-// CHECK: [[TRY]]
-// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 5, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([5 x i64], [5 x i64]* [[MAPT5]], i32 0, i32 0), i32 0, i32 0)
-// CHECK-DAG: [[BPR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP:%.+]], i32 0, i32 0
-// CHECK-DAG: [[PR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P:%.+]], i32 0, i32 0
-// CHECK-DAG: [[SR]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0
-// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX0:[0-9]+]]
-// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX0]]
-// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX0]]
-// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX1:[0-9]+]]
-// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX1]]
-// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX1]]
-// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX2:[0-9]+]]
-// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX2]]
-// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX2]]
-// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]]
-// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX3]]
-// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX3]]
+// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 6, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([6 x i64], [6 x i64]* [[MAPT5]], i32 0, i32 0), i32 0, i32 0)
+// CHECK-DAG: [[BPR]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP:%.+]], i32 0, i32 0
+// CHECK-DAG: [[PR]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P:%.+]], i32 0, i32 0
+// CHECK-DAG: [[SR]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0
+// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX0:[0-9]+]]
+// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX0]]
+// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX0]]
+// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX1:[0-9]+]]
+// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX1]]
+// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX1]]
+// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX2:[0-9]+]]
+// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX2]]
+// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX2]]
+// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]]
+// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX3]]
+// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX3]]
+// CHECK-DAG: [[SADDR4:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]]
+// CHECK-DAG: [[BPADDR4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX3]]
+// CHECK-DAG: [[PADDR4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX3]]
+// CHECK-DAG: [[SADDR5:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]]
+// CHECK-DAG: [[BPADDR5:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX3]]
+// CHECK-DAG: [[PADDR5:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX3]]
// The names below are not necessarily consistent with the names used for the
// addresses above as some are repeated.
@@ -582,15 +608,21 @@ int bar(int n){
// CHECK-DAG: store i[[SZ]] 4, i[[SZ]]* {{%[^,]+}}
// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CBPADDR3:%.+]],
-// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CPADDR3:%.+]],
+// CHECK-DAG: store double* %{{.+}}, double** [[CPADDR3:%.+]],
// CHECK-DAG: [[CBPADDR3]] = bitcast i8** {{%[^,]+}} to [[S1]]**
-// CHECK-DAG: [[CPADDR3]] = bitcast i8** {{%[^,]+}} to [[S1]]**
+// CHECK-DAG: [[CPADDR3]] = bitcast i8** {{%[^,]+}} to double**
+// CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* {{%[^,]+}}
+
+// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CBPADDR4:%.+]],
+// CHECK-DAG: store double* %{{.+}}, double** [[CPADDR4:%.+]],
+// CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to [[S1]]**
+// CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to double**
// CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* {{%[^,]+}}
-// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR4:%.+]],
-// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR4:%.+]],
-// CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to i16**
-// CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to i16**
+// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR5:%.+]],
+// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR5:%.+]],
+// CHECK-DAG: [[CBPADDR5]] = bitcast i8** {{%[^,]+}} to i16**
+// CHECK-DAG: [[CPADDR5]] = bitcast i8** {{%[^,]+}} to i16**
// CHECK-DAG: store i[[SZ]] [[CSIZE]], i[[SZ]]* {{%[^,]+}}
// CHECK-NEXT: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
@@ -733,7 +765,7 @@ int bar(int n){
// CHECK-32-DAG:store i32 [[LOCAL_BV]], i32* [[LOCAL_B_CASTED]], align
// CHECK-DAG: [[REF_B:%.+]] = load i[[SZ]], i[[SZ]]* [[LOCAL_B_CASTED]],
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 5, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, [[S1]]*, i[[SZ]], i[[SZ]], i[[SZ]], i16*)* [[OMP_OUTLINED5:@.+]] to void (i32*, i32*, ...)*), [[S1]]* [[REF_THIS]], i[[SZ]] [[REF_B]], i[[SZ]] [[VAL_VLA1]], i[[SZ]] [[VAL_VLA2]], i16* [[REF_C]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 5, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, [[S1]]*, i[[SZ]], i[[SZ]], i[[SZ]], i16*)* [[OMP_OUTLINED5:@.+]] to void (i32*, i32*, ...)*), [[S1]]* [[REF_THIS]], i[[SZ]] [[REF_B]], i[[SZ]] [[VAL_VLA1]], i[[SZ]] [[VAL_VLA2]], i16* [[REF_C]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED5]](i32* noalias %.global_tid., i32* noalias %.bound_tid., [[S1]]* %{{.+}}, i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, i16* {{.+}})
@@ -778,7 +810,7 @@ int bar(int n){
// CHECK-DAG: store i8 [[CONV_AAA]], i8* [[CONV]], align
// CHECK-DAG: [[REF_AAA:%.+]] = load i[[SZ]], i[[SZ]]* [[LOCAL_AAA_CASTED]],
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 5, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]], i[[SZ]], i[[SZ]], [10 x i32]*)* [[OMP_OUTLINED6:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], i[[SZ]] {{.+}}, i[[SZ]] [[REF_AA]], i[[SZ]] [[REF_AAA]], [10 x i32]* [[REF_B]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 5, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]], i[[SZ]], i[[SZ]], [10 x i32]*)* [[OMP_OUTLINED6:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], i[[SZ]] {{.+}}, i[[SZ]] [[REF_AA]], i[[SZ]] [[REF_AAA]], [10 x i32]* [[REF_B]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED6]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, [10 x i32]* {{.+}})
@@ -811,7 +843,7 @@ int bar(int n){
// CHECK-DAG: store i16 [[CONV_AA]], i16* [[CONV]], align
// CHECK-DAG: [[REF_AA:%.+]] = load i[[SZ]], i[[SZ]]* [[LOCAL_AA_CASTED]],
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]], [10 x i32]*)* [[OMP_OUTLINED7:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], i[[SZ]] [[REF_AA]], [10 x i32]* [[REF_B]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i[[SZ]], i[[SZ]], [10 x i32]*)* [[OMP_OUTLINED7:@.+]] to void (i32*, i32*, ...)*), i[[SZ]] [[REF_A]], i[[SZ]] [[REF_AA]], [10 x i32]* [[REF_B]])
//
//
// CHECK: define internal {{.*}}void [[OMP_OUTLINED7]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, [10 x i32]* {{.+}})
diff --git a/test/OpenMP/target_teams_distribute_simd_codegen_registration.cpp b/test/OpenMP/target_teams_distribute_simd_codegen_registration.cpp
index d138114633ea..5020bcc87aaf 100644
--- a/test/OpenMP/target_teams_distribute_simd_codegen_registration.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_codegen_registration.cpp
@@ -6,6 +6,14 @@
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// Test target teams distribute simd codegen - host bc file has to be created first.
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s -check-prefix=TCHECK
@@ -16,9 +24,22 @@
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s -check-prefix=TCHECK
-// Check that no target code is emmitted if no omptests flag was provided.
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
+// Check that no target code is emitted if no omptests flag was provided.
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s -check-prefix=CHECK-NTARGET
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// SIMD-ONLY2-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -60,96 +81,96 @@
// We have 7 target regions
-// CHECK-DAG: {{@.+}} = private constant i8 0
-// TCHECK-NOT: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = weak constant i8 0
+// TCHECK-NOT: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
-// CHECK-DAG: {{@.+}} = private constant i8 0
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
+// CHECK-DAG: {{@.+}} = weak constant i8 0
// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4]
-// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288]
+// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800]
-// CHECK-NTARGET-NOT: private constant i8 0
+// CHECK-NTARGET-NOT: weak constant i8 0
// CHECK-NTARGET-NOT: private unnamed_addr constant [1 x i
// CHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// CHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY1:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// CHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY2:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// CHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY3:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// CHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY4:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// CHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY5:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// CHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY6:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// CHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY7:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// CHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY8:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// CHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY9:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// CHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY10:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// CHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY11:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// CHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY12:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// TCHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY1:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// TCHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY2:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// TCHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY3:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// TCHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY4:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// TCHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY5:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// TCHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY6:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// TCHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY7:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// TCHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY8:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// TCHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY9:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// TCHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY10:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// TCHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY11:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// TCHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY12:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
// CHECK: [[ENTEND:@.+]] = external constant [[ENTTY]]
@@ -163,7 +184,7 @@
// CHECK-SAME: { i32, void ()*, i8* } { i32 500, void ()* [[P500:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 501, void ()* [[P501:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 65535, void ()* [[PMAX:@[^,]+]], i8* null },
-// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
// CHECK-NTARGET: @llvm.global_ctors = appending global [3 x { i32, void ()*, i8* }] [
@@ -328,18 +349,18 @@ struct ST {
//CHECK-DAG: define internal void @[[NAME12]](
//CHECK-DAG: call void @[[NAME12]](
-//TCHECK-DAG: define void @[[NAME1]](
-//TCHECK-DAG: define void @[[NAME2]](
-//TCHECK-DAG: define void @[[NAME3]](
-//TCHECK-DAG: define void @[[NAME4]](
-//TCHECK-DAG: define void @[[NAME5]](
-//TCHECK-DAG: define void @[[NAME6]](
-//TCHECK-DAG: define void @[[NAME7]](
-//TCHECK-DAG: define void @[[NAME8]](
-//TCHECK-DAG: define void @[[NAME9]](
-//TCHECK-DAG: define void @[[NAME10]](
-//TCHECK-DAG: define void @[[NAME11]](
-//TCHECK-DAG: define void @[[NAME12]](
+//TCHECK-DAG: define weak void @[[NAME1]](
+//TCHECK-DAG: define weak void @[[NAME2]](
+//TCHECK-DAG: define weak void @[[NAME3]](
+//TCHECK-DAG: define weak void @[[NAME4]](
+//TCHECK-DAG: define weak void @[[NAME5]](
+//TCHECK-DAG: define weak void @[[NAME6]](
+//TCHECK-DAG: define weak void @[[NAME7]](
+//TCHECK-DAG: define weak void @[[NAME8]](
+//TCHECK-DAG: define weak void @[[NAME9]](
+//TCHECK-DAG: define weak void @[[NAME10]](
+//TCHECK-DAG: define weak void @[[NAME11]](
+//TCHECK-DAG: define weak void @[[NAME12]](
// CHECK-NTARGET-NOT: __tgt_target
// CHECK-NTARGET-NOT: __tgt_register_lib
@@ -381,7 +402,7 @@ struct ST {
//CHECK: ret void
//CHECK: declare i32 @__tgt_unregister_lib([[DSCTY]]*)
-//CHECK: define linkonce hidden void @[[REGFN]](i8*)
+//CHECK: define linkonce hidden void @[[REGFN]]()
//CHECK-SAME: comdat {
//CHECK: call i32 @__tgt_register_lib([[DSCTY]]* [[DESC]])
//CHECK: call i32 @__cxa_atexit(void (i8*)* @[[UNREGFN]], i8* bitcast ([[DSCTY]]* [[DESC]] to i8*),
@@ -421,32 +442,32 @@ int bar(int a){
// Check metadata is properly generated:
// CHECK: !omp_offload.info = !{!{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 195, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 247, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 265, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 272, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 284, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 291, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 415, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 298, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 291, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 298, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 284, i32 {{[0-9]+}}}
-// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 221, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 216, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 268, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 286, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 293, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 305, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 312, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 436, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 319, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 312, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 319, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 305, i32 {{[0-9]+}}}
+// CHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 242, i32 {{[0-9]+}}}
// TCHECK: !omp_offload.info = !{!{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 195, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 247, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 265, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 272, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 284, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 291, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 415, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 298, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 291, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 298, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 284, i32 {{[0-9]+}}}
-// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 221, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID:-?[0-9]+]], i32 [[FILEID:-?[0-9]+]], !"_ZN2SB3fooEv", i32 216, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SDD1Ev", i32 268, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SEC1Ev", i32 286, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SED1Ev", i32 293, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EE3fooEv", i32 305, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EEC1Ev", i32 312, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_Z3bari", i32 436, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EED1Ev", i32 319, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EEC1Ev", i32 312, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi1000EED1Ev", i32 319, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2STILi100EE3fooEv", i32 305, i32 {{[0-9]+}}}
+// TCHECK-DAG: = !{i32 0, i32 [[DEVID]], i32 [[FILEID]], !"_ZN2SCC1Ev", i32 242, i32 {{[0-9]+}}}
// TCHECK-DAG: !{!"llvm.loop.vectorize.enable", i1 true}
// CHECK-DAG: !{!"llvm.loop.vectorize.enable", i1 true}
diff --git a/test/OpenMP/target_teams_distribute_simd_codegen_registration_naming.cpp b/test/OpenMP/target_teams_distribute_simd_codegen_registration_naming.cpp
index 76618accbd68..856664b4c0e2 100644
--- a/test/OpenMP/target_teams_distribute_simd_codegen_registration_naming.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_codegen_registration_naming.cpp
@@ -6,6 +6,14 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// Test target teams distribute simd codegen - host bc file has to be created first.
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s -check-prefix=TCHECK
@@ -16,6 +24,16 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s -check-prefix=TCHECK
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/target_teams_distribute_simd_collapse_codegen.cpp b/test/OpenMP/target_teams_distribute_simd_collapse_codegen.cpp
index 703136f0652e..8a80774ef187 100644
--- a/test/OpenMP/target_teams_distribute_simd_collapse_codegen.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_collapse_codegen.cpp
@@ -9,6 +9,14 @@
// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
#ifdef CK1
template <typename T, int X, long long Y>
@@ -60,6 +68,14 @@ int teams_template_struct(void) {
// RUN: %clang_cc1 -DCK2 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
#ifdef CK2
template <typename T, int n, int m>
diff --git a/test/OpenMP/target_teams_distribute_simd_collapse_messages.cpp b/test/OpenMP/target_teams_distribute_simd_collapse_messages.cpp
index 39937f90fb34..a2d3bde44afb 100644
--- a/test/OpenMP/target_teams_distribute_simd_collapse_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_collapse_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_simd_defaultmap_messages.cpp b/test/OpenMP/target_teams_distribute_simd_defaultmap_messages.cpp
index 3bea411540a2..b8ac8aee672a 100644
--- a/test/OpenMP/target_teams_distribute_simd_defaultmap_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_defaultmap_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_simd_depend_codegen.cpp b/test/OpenMP/target_teams_distribute_simd_depend_codegen.cpp
new file mode 100644
index 000000000000..0c1c13e1e908
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_simd_depend_codegen.cpp
@@ -0,0 +1,261 @@
+// Test host codegen.
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+// Test target codegen - host bc file has to be created first.
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+// CHECK-DAG: [[TT:%.+]] = type { i64, i8 }
+// CHECK-DAG: [[ENTTY:%.+]] = type { i8*, i8*, i[[SZ:32|64]], i32, i32 }
+// CHECK-DAG: [[DEVTY:%.+]] = type { i8*, i8*, [[ENTTY]]*, [[ENTTY]]* }
+// CHECK-DAG: [[DSCTY:%.+]] = type { i32, [[DEVTY]]*, [[ENTTY]]*, [[ENTTY]]* }
+
+// TCHECK: [[ENTTY:%.+]] = type { i8*, i8*, i{{32|64}}, i32, i32 }
+
+// CHECK-DAG: $[[REGFN:\.omp_offloading\..+]] = comdat
+
+// CHECK-DAG: [[SIZET:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 0, i[[SZ]] 4]
+// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 544, i64 800]
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = {{.*}}constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
+
+// Check if offloading descriptor is created.
+// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
+// CHECK: [[ENTEND:@.+]] = external constant [[ENTTY]]
+// CHECK: [[DEVBEGIN:@.+]] = external constant i8
+// CHECK: [[DEVEND:@.+]] = external constant i8
+// CHECK: [[IMAGES:@.+]] = internal unnamed_addr constant [1 x [[DEVTY]]] [{{.+}} { i8* [[DEVBEGIN]], i8* [[DEVEND]], [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }], comdat($[[REGFN]])
+// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
+
+// Check target registration is registered as a Ctor.
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
+
+
+template<typename tx, typename ty>
+struct TT{
+ tx X;
+ ty Y;
+};
+
+int global;
+extern int global;
+
+// CHECK: define {{.*}}[[FOO:@.+]](
+int foo(int n) {
+ int a = 0;
+ short aa = 0;
+ float b[10];
+ float bn[n];
+ double c[5][10];
+ double cn[5][n];
+ TT<long long, char> d;
+ static long *plocal;
+
+ // CHECK: [[ADD:%.+]] = add nsw i32
+ // CHECK: store i32 [[ADD]], i32* [[DEVICE_CAP:%.+]],
+ // CHECK: [[GEP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+ // CHECK: store i32 [[DEV]], i32* [[GEP]],
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[ID:@.+]], i32 [[GTID:%.+]], i32 1, i[[SZ]] {{20|40}}, i[[SZ]] 4, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY0:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY0:%.+]]*
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 1
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 2
+ // CHECK: getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 3
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call void @__kmpc_omp_wait_deps(%struct.ident_t* [[ID]], i32 [[GTID]], i32 4, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: call void @__kmpc_omp_task_begin_if0(%struct.ident_t* [[ID]], i32 [[GTID]], i8* [[TASK]])
+ // CHECK: call i32 [[TASK_ENTRY0]](i32 [[GTID]], [[TASK_TY0]]* [[BC_TASK]])
+ // CHECK: call void @__kmpc_omp_task_complete_if0(%struct.ident_t* [[ID]], i32 [[GTID]], i8* [[TASK]])
+ #pragma omp target teams distribute simd device(global + a) depend(in: global) depend(out: a, b, cn[4])
+ for (int i = 0; i < 10; ++i) {
+ }
+
+ // CHECK: [[ADD:%.+]] = add nsw i32
+ // CHECK: store i32 [[ADD]], i32* [[DEVICE_CAP:%.+]],
+
+ // CHECK: [[BOOL:%.+]] = icmp ne i32 %{{.+}}, 0
+ // CHECK: br i1 [[BOOL]], label %[[THEN:.+]], label %[[ELSE:.+]]
+ // CHECK: [[THEN]]:
+ // CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP:%.+]], i32 0, i32 0
+ // CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P:%.+]], i32 0, i32 0
+ // CHECK-DAG: [[CBPADDR0:%.+]] = bitcast i8** [[BPADDR0]] to i[[SZ]]**
+ // CHECK-DAG: [[CPADDR0:%.+]] = bitcast i8** [[PADDR0]] to i[[SZ]]**
+ // CHECK-DAG: store i[[SZ]]* [[BP0:%[^,]+]], i[[SZ]]** [[CBPADDR0]]
+ // CHECK-DAG: store i[[SZ]]* [[BP0]], i[[SZ]]** [[CPADDR0]]
+
+ // CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 1
+ // CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P]], i32 0, i32 1
+ // CHECK-DAG: [[CBPADDR1:%.+]] = bitcast i8** [[BPADDR1]] to i[[SZ]]*
+ // CHECK-DAG: [[CPADDR1:%.+]] = bitcast i8** [[PADDR1]] to i[[SZ]]*
+ // CHECK-DAG: store i[[SZ]] [[BP1:%[^,]+]], i[[SZ]]* [[CBPADDR1]]
+ // CHECK-DAG: store i[[SZ]] [[BP1]], i[[SZ]]* [[CPADDR1]]
+ // CHECK-DAG: getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 0
+ // CHECK-DAG: getelementptr inbounds [2 x i8*], [2 x i8*]* [[P]], i32 0, i32 0
+ // CHECK: [[GEP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+ // CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+ // CHECK: store i32 [[DEV]], i32* [[GEP]],
+
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[ID]], i32 [[GTID]], i32 1, i[[SZ]] {{104|52}}, i[[SZ]] {{16|12}}, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY1_:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY1_:%.+]]*
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 1
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 2
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call i32 @__kmpc_omp_task_with_deps(%struct.ident_t* [[ID]], i32 [[GTID]], i8* [[TASK]], i32 3, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: br label %[[EXIT:.+]]
+
+ // CHECK: [[ELSE]]:
+ // CHECK-NOT: getelementptr inbounds [2 x i8*], [2 x i8*]*
+ // CHECK: [[GEP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+ // CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+ // CHECK: store i32 [[DEV]], i32* [[GEP]],
+
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[ID]], i32 [[GTID]], i32 1, i[[SZ]] {{56|28}}, i[[SZ]] {{16|12}}, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY1__:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY1__:%.+]]*
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 1
+ // CHECK: getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 2
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call i32 @__kmpc_omp_task_with_deps(%struct.ident_t* [[ID]], i32 [[GTID]], i8* [[TASK]], i32 3, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: br label %[[EXIT:.+]]
+ // CHECK: [[EXIT]]:
+
+ #pragma omp target teams distribute simd device(global + a) nowait depend(inout: global, a, bn) if(a)
+ for (int i = 0; i < *plocal; ++i) {
+ static int local1;
+ *plocal = global;
+ local1 = global;
+ }
+
+ // CHECK: [[TASK:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[ID]], i32 [[GTID]], i32 1, i[[SZ]] {{48|24}}, i[[SZ]] 4, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* [[TASK_ENTRY2:@.+]] to i32 (i32, i8*)*))
+ // CHECK: [[BC_TASK:%.+]] = bitcast i8* [[TASK]] to [[TASK_TY2:%.+]]*
+ // CHECK: getelementptr inbounds [1 x %struct.kmp_depend_info], [1 x %struct.kmp_depend_info]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: [[DEP_START:%.+]] = getelementptr inbounds [1 x %struct.kmp_depend_info], [1 x %struct.kmp_depend_info]* %{{.+}}, i32 0, i32 0
+ // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[DEP_START]] to i8*
+ // CHECK: call void @__kmpc_omp_wait_deps(%struct.ident_t* [[ID]], i32 [[GTID]], i32 1, i8* [[DEP]], i32 0, i8* null)
+ // CHECK: call void @__kmpc_omp_task_begin_if0(%struct.ident_t* [[ID]], i32 [[GTID]], i8* [[TASK]])
+ // CHECK: call i32 [[TASK_ENTRY2]](i32 [[GTID]], [[TASK_TY2]]* [[BC_TASK]])
+ // CHECK: call void @__kmpc_omp_task_complete_if0(%struct.ident_t* [[ID]], i32 [[GTID]], i8* [[TASK]])
+ #pragma omp target teams distribute simd if(0) firstprivate(global) depend(out:global)
+ for (int i = 0; i < global; ++i) {
+ global += 1;
+ }
+
+ return a;
+}
+
+// Check that the offloading functions are emitted and that the arguments are
+// correct and loaded correctly for the target regions in foo().
+
+// CHECK: define internal void [[HVT0:@.+]]()
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY0]](i32{{.*}}, [[TASK_TY0]]* noalias)
+// CHECK: store void (i8*, ...)* null, void (i8*, ...)** %
+// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 0
+// CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+// CHECK: [[DEVICE:%.+]] = sext i32 [[DEV]] to i64
+// CHECK: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 [[DEVICE]], i8* @{{[^,]+}}, i32 0, i8** null, i8** null, i[[SZ]]* null, i64* null, i32 0, i32 0)
+// CHECK-NEXT: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
+// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
+// CHECK: [[FAIL]]
+// CHECK: call void [[HVT0]]()
+// CHECK-NEXT: br label %[[END]]
+// CHECK: [[END]]
+// CHECK: ret i32 0
+
+// CHECK: define internal void [[HVT1:@.+]](i[[SZ]]* %{{.+}}, i[[SZ]] %{{.+}})
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY1_]](i32{{.*}}, [[TASK_TY1_]]* noalias)
+// CHECK: call void (i8*, ...) %
+// CHECK: [[SZT:%.+]] = getelementptr inbounds [2 x i[[SZ]]], [2 x i[[SZ]]]* %{{.+}}, i[[SZ]] 0, i[[SZ]] 0
+// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+// CHECK: [[DEV:%.+]] = load i32, i32* [[DEVICE_CAP]],
+// CHECK: [[DEVICE:%.+]] = sext i32 [[DEV]] to i64
+// CHECK: [[RET:%.+]] = call i32 @__tgt_target_teams_nowait(i64 [[DEVICE]], i8* @{{[^,]+}}, i32 2, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SZT]], i64* getelementptr inbounds ([2 x i64], [2 x i64]* [[MAPT]], i32 0, i32 0), i32 0, i32 0)
+
+// CHECK: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
+// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
+// CHECK: [[FAIL]]
+// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
+// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
+// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
+// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
+// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
+// CHECK: [[BP1:%.+]] = load i[[SZ]], i[[SZ]]* [[BP1_PTR]],
+// CHECK: call void [[HVT1]](i[[SZ]]* [[BP0]], i[[SZ]] [[BP1]])
+// CHECK-NEXT: br label %[[END]]
+// CHECK: [[END]]
+// CHECK: ret i32 0
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY1__]](i32{{.*}}, [[TASK_TY1__]]* noalias)
+// CHECK: call void (i8*, ...) %
+// CHECK: [[DEVICE_CAP:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 2
+// CHECK: [[BP0:%.+]] = load i[[SZ]]*, i[[SZ]]** %
+// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
+// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
+// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
+// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
+// CHECK: [[BP1:%.+]] = load i[[SZ]], i[[SZ]]* [[BP1_PTR]],
+// CHECK: call void [[HVT1]](i[[SZ]]* [[BP0]], i[[SZ]] [[BP1]])
+// CHECK: ret i32 0
+
+// CHECK: define internal void [[HVT2:@.+]](i[[SZ]] %{{.+}})
+// Create stack storage and store argument in there.
+// CHECK: [[AA_ADDR:%.+]] = alloca i[[SZ]], align
+// CHECK: store i[[SZ]] %{{.+}}, i[[SZ]]* [[AA_ADDR]], align
+// CHECK-64: [[AA_CADDR:%.+]] = bitcast i[[SZ]]* [[AA_ADDR]] to i32*
+// CHECK-64: load i32, i32* [[AA_CADDR]], align
+// CHECK-32: load i32, i32* [[AA_ADDR]], align
+
+// CHECK: define internal{{.*}} i32 [[TASK_ENTRY2]](i32{{.*}}, [[TASK_TY2]]* noalias)
+// CHECK: call void (i8*, ...) %
+// CHECK: [[BP1_I32:%.+]] = load i32, i32* %
+// CHECK-64: [[BP1_CAST:%.+]] = bitcast i[[SZ]]* [[BP1_PTR:%.+]] to i32*
+// CHECK-64: store i32 [[BP1_I32]], i32* [[BP1_CAST]],
+// CHECK-32: store i32 [[BP1_I32]], i32* [[BP1_PTR:%.+]],
+// CHECK: [[BP1:%.+]] = load i[[SZ]], i[[SZ]]* [[BP1_PTR]],
+// CHECK: call void [[HVT2]](i[[SZ]] [[BP1]])
+// CHECK: ret i32 0
+
+
+#endif
diff --git a/test/OpenMP/target_teams_distribute_simd_depend_messages.cpp b/test/OpenMP/target_teams_distribute_simd_depend_messages.cpp
index c24c7438b0b5..9c70d051d7b3 100644
--- a/test/OpenMP/target_teams_distribute_simd_depend_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_depend_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_simd_device_messages.cpp b/test/OpenMP/target_teams_distribute_simd_device_messages.cpp
index e9246cb29def..1f47d1c72636 100644
--- a/test/OpenMP/target_teams_distribute_simd_device_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_device_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_simd_dist_schedule_codegen.cpp b/test/OpenMP/target_teams_distribute_simd_dist_schedule_codegen.cpp
index d096da329abc..874d4fc92c66 100644
--- a/test/OpenMP/target_teams_distribute_simd_dist_schedule_codegen.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_dist_schedule_codegen.cpp
@@ -9,6 +9,14 @@
// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
#ifdef CK1
template <typename T, int X, long long Y>
@@ -81,6 +89,14 @@ int teams_template_struct(void) {
// RUN: %clang_cc1 -DCK2 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
#ifdef CK2
template <typename T, int n>
diff --git a/test/OpenMP/target_teams_distribute_simd_dist_schedule_messages.cpp b/test/OpenMP/target_teams_distribute_simd_dist_schedule_messages.cpp
index 9b9239d64e9d..b9fdc18a0ec0 100644
--- a/test/OpenMP/target_teams_distribute_simd_dist_schedule_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_dist_schedule_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_simd_firstprivate_codegen.cpp b/test/OpenMP/target_teams_distribute_simd_firstprivate_codegen.cpp
index f2871f811833..b2b911e888f9 100644
--- a/test/OpenMP/target_teams_distribute_simd_firstprivate_codegen.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_firstprivate_codegen.cpp
@@ -1,13 +1,26 @@
-// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
@@ -97,16 +110,7 @@ int main() {
// LAMBDA: [[G_ADDR:%.+]] = alloca i{{[0-9]+}},
// LAMBDA: [[G1_ADDR:%.+]] = alloca i{{[0-9]+}},
// LAMBDA: [[SIVAR_ADDR:%.+]] = alloca i{{[0-9]+}},
- // LAMBDA: {{%.+}} = alloca i{{[0-9]+}},
- // LAMBDA: {{%.+}} = alloca i{{[0-9]+}},
- // LAMBDA: {{%.+}} = alloca i{{[0-9]+}},
- // LAMBDA: {{%.+}} = alloca i{{[0-9]+}},
- // LAMBDA: {{%.+}} = alloca i{{[0-9]+}},
- // LAMBDA: {{%.+}} = alloca i{{[0-9]+}},
- // LAMBDA: [[G_PRIV_ADDR:%.+]] = alloca i{{[0-9]+}},
- // LAMBDA: [[G1_PRIV_ADDR:%.+]] = alloca i{{[0-9]+}},
// LAMBDA: [[G1_TMP:%.+]] = alloca i32*,
- // LAMBDA: [[SIVAR_PRIV_ADDR:%.+]] = alloca i{{[0-9]+}},
// skip loop vars
// LAMBDA-DAG: store {{.+}}, {{.+}} [[G_ADDR]],
// LAMBDA-DAG: store {{.+}}, {{.+}} [[G1_ADDR]],
@@ -114,15 +118,15 @@ int main() {
// LAMBDA-DAG: [[G_CONV:%.+]] = bitcast {{.+}} [[G_ADDR]] to
// LAMBDA-DAG: [[G1_CONV:%.+]] = bitcast {{.+}} [[G1_ADDR]] to
// LAMBDA-DAG: [[SIVAR_CONV:%.+]] = bitcast {{.+}} [[SIVAR_ADDR]] to
- // LAMBDA-DAG: store{{.+}} [[G1_PRIV_ADDR]], {{.+}} [[G1_TMP]],
+ // LAMBDA-DAG: store{{.+}} [[G1_CONV]], {{.+}} [[G1_TMP]],
g = 1;
g1 = 1;
sivar = 2;
// LAMBDA: call void @__kmpc_for_static_init_4(
- // LAMBDA-DAG: store{{.+}} 1, {{.+}} [[G_PRIV_ADDR]],
+ // LAMBDA-DAG: store{{.+}} 1, {{.+}} [[G_CONV]],
// LAMBDA-DAG: [[G1:%.+]] = load{{.+}}, {{.+}}* [[G1_TMP]]
// LAMBDA-DAG: store{{.+}} 1, {{.+}} [[G1]],
- // LAMBDA-DAG: store{{.+}} 2, {{.+}} [[SIVAR_PRIV_ADDR]],
+ // LAMBDA-DAG: store{{.+}} 2, {{.+}} [[SIVAR_CONV]],
// LAMBDA-DAG: [[G1_REF:%.+]] = load{{.+}}, {{.+}} [[G1_TMP]],
// LAMBDA-DAG: store{{.+}} 1, {{.+}} [[G1_REF]],
// LAMBDA: call void [[INNER_LAMBDA:@.+]](
@@ -212,8 +216,8 @@ int main() {
// CHECK: store i{{[0-9]+}} {{.+}}, i{{[0-9]+}}* [[SIVAR_ADDR]],
// T_VAR and SIVAR
-// CHECK-DAG-64: [[CONV_TVAR:%.+]] = bitcast i64* [[T_VAR_ADDR]] to i32*
-// CHECK-DAG-64: [[CONV_SIVAR:%.+]] = bitcast i64* [[SIVAR_ADDR]] to i32*
+// CHECK-64-DAG: [[CONV_TVAR:%.+]] = bitcast i64* [[T_VAR_ADDR]] to i32*
+// CHECK-64-DAG: [[CONV_SIVAR:%.+]] = bitcast i64* [[SIVAR_ADDR]] to i32*
// preparation vars
// CHECK-DAG: [[VEC_ADDR_VAL:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]],
@@ -223,7 +227,7 @@ int main() {
// firstprivate vec(vec): copy from *_addr into priv1 and then from priv1 into priv2
// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VEC_DEST_PRIV]], i8* [[VEC_SRC]], {{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST_PRIV]], i8* align {{[0-9]+}} [[VEC_SRC]], {{.+}})
// firstprivate(s_arr)
// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]],
@@ -243,13 +247,13 @@ int main() {
// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]])
// CHECK: call void @__kmpc_for_static_init_4(
-// CHECK-DAG-32: {{.+}} = {{.+}} [[T_VAR_ADDR]]
-// CHECK-DAG-64: {{.+}} = {{.+}} [[CONV_TVAR]]
+// CHECK-32-DAG: {{.+}} = {{.+}} [[T_VAR_ADDR]]
+// CHECK-64-DAG: {{.+}} = {{.+}} [[CONV_TVAR]]
// CHECK-DAG: {{.+}} = {{.+}} [[VEC_PRIV]]
// CHECK-DAG: {{.+}} = {{.+}} [[S_ARR_PRIV]]
// CHECK-DAG: {{.+}} = {{.+}} [[VAR_PRIV]]
-// CHECK-DAG-32: {{.+}} = {{.+}} [[SIVAR_ADDR]]
-// CHECK-DAG-64: {{.+}} = {{.+}} [[CONV_SIVAR]]
+// CHECK-32-DAG: {{.+}} = {{.+}} [[SIVAR_ADDR]]
+// CHECK-64-DAG: {{.+}} = {{.+}} [[CONV_SIVAR]]
// CHECK: call void @__kmpc_for_static_fini(
// CHECK: ret void
@@ -309,7 +313,7 @@ int main() {
// firstprivate vec(vec): copy from *_addr into priv1 and then from priv1 into priv2
// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VEC_DEST_PRIV]], i8* [[VEC_SRC]], {{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST_PRIV]], i8* align {{[0-9]+}} [[VEC_SRC]], {{.+}})
// firstprivate(s_arr)
// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_PRIV]],
@@ -331,8 +335,8 @@ int main() {
// CHECK-DAG: store [[S_INT_TY]]* [[VAR_PRIV]], [[S_INT_TY]]** [[TMP]],
// CHECK: call void @__kmpc_for_static_init_4(
-// CHECK-DAG-32: {{.+}} = {{.+}} [[T_VAR_ADDR]]
-// CHECK-DAG-64: {{.+}} = {{.+}} [[CONV_TVAR]]
+// CHECK-32-DAG: {{.+}} = {{.+}} [[T_VAR_ADDR]]
+// CHECK-64-DAG: {{.+}} = {{.+}} [[CONV_TVAR]]
// CHECK-DAG: {{.+}} = {{.+}} [[VEC_PRIV]]
// CHECK-DAG: {{.+}} = {{.+}} [[TMP]]
// CHECK-DAG: {{.+}} = {{.+}} [[S_ARR_PRIV]]
diff --git a/test/OpenMP/target_teams_distribute_simd_firstprivate_messages.cpp b/test/OpenMP/target_teams_distribute_simd_firstprivate_messages.cpp
index 235533b49d16..a4aaba7f8373 100644
--- a/test/OpenMP/target_teams_distribute_simd_firstprivate_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_firstprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_simd_if_messages.cpp b/test/OpenMP/target_teams_distribute_simd_if_messages.cpp
index 6cb2ad44aa11..43d8957f0065 100644
--- a/test/OpenMP/target_teams_distribute_simd_if_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_if_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_simd_is_device_ptr_ast_print.cpp b/test/OpenMP/target_teams_distribute_simd_is_device_ptr_ast_print.cpp
index 61aede4cb9e6..eb5347d61d65 100644
--- a/test/OpenMP/target_teams_distribute_simd_is_device_ptr_ast_print.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_is_device_ptr_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -56,7 +60,7 @@ struct SA {
// CHECK-NEXT: int aa[10];
// CHECK-NEXT: arr &raa = this->aa;
// CHECK-NEXT: func(
-// CHECK-NEXT: #pragma omp target teams distribute simd is_device_ptr(this->k)
+// CHECK-NEXT: #pragma omp target teams distribute simd is_device_ptr(this->k){{$}}
// CHECK-NEXT: for (int i = 0; i < 100; i++)
// CHECK-NEXT: ;
// CHECK-NEXT: #pragma omp target teams distribute simd is_device_ptr(this->z)
diff --git a/test/OpenMP/target_teams_distribute_simd_is_device_ptr_messages.cpp b/test/OpenMP/target_teams_distribute_simd_is_device_ptr_messages.cpp
index 013b703a91e9..340830569263 100644
--- a/test/OpenMP/target_teams_distribute_simd_is_device_ptr_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_is_device_ptr_messages.cpp
@@ -1,4 +1,6 @@
// RUN: %clang_cc1 -std=c++11 -verify -fopenmp %s
+
+// RUN: %clang_cc1 -std=c++11 -verify -fopenmp-simd %s
struct ST {
int *a;
};
diff --git a/test/OpenMP/target_teams_distribute_simd_lastprivate_codegen.cpp b/test/OpenMP/target_teams_distribute_simd_lastprivate_codegen.cpp
index 8a978a221954..fdf6d2f3a7dc 100644
--- a/test/OpenMP/target_teams_distribute_simd_lastprivate_codegen.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_lastprivate_codegen.cpp
@@ -5,12 +5,28 @@
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -244,7 +260,7 @@ int main() {
// CHECK-DAG: [[TMP_VAL:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP_PRIV]],
// CHECK-DAG: [[S_ARR_PTR_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_PTR]] to i8*
// CHECK-DAG: [[TMP_VAL_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_VAL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_PTR_BCAST]], i8* [[TMP_VAL_BCAST]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_PTR_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL_BCAST]],
// CHECK: call void @__kmpc_for_static_fini(
// lastprivates
@@ -258,7 +274,7 @@ int main() {
// CHECK-32: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_ADDR]],
// CHECK: [[BCAST_VEC_ADDR_REF:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_REF]] to i8*
// CHECK: [[BCAST_VEC_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[BCAST_VEC_ADDR_REF]], i8* [[BCAST_VEC_PRIV]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[BCAST_VEC_ADDR_REF]], i8* align {{[0-9]+}} [[BCAST_VEC_PRIV]],
// CHECK: [[S_ARR_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_ADDR_REF]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[S_ARR_PRIV_BCAST:%.+]] = bitcast [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]] to [[S_FLOAT_TY]]*
// CHECK: [[S_ARR_BEGIN_GEP:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[S_ARR_BEGIN]], i{{[0-9]+}} 2
@@ -269,7 +285,7 @@ int main() {
// CHECK: [[S_ARR_DST_EL:%.+]] = phi [[S_FLOAT_TY]]*{{.+}}
// CHECK: [[S_ARR_DST_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_DST_EL]] to i8*
// CHECK: [[S_ARR_SRC_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_SRC_EL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_DST_BCAST]], i8* [[S_ARR_SRC_BCAST]]{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_DST_BCAST]], i8* align {{[0-9]+}} [[S_ARR_SRC_BCAST]]{{.+}})
// CHECK: [[S_ARR_DST_NEXT:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[S_ARR_DST_EL]], i{{[0-9]+}} 1
// CHECK: [[S_ARR_SRC_NEXT:%.+]] = getelementptr{{.+}}
// CHECK: [[CPY_IS_FINISHED:%.+]] = icmp eq [[S_FLOAT_TY]]* [[S_ARR_DST_NEXT]], [[S_ARR_BEGIN_GEP]]
@@ -278,7 +294,7 @@ int main() {
// CHECK: [[TMP_VAL1:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP_PRIV]],
// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[VAR_ADDR_REF]] to i8*
// CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VAR_ADDR_REF_BCAST]], i8* [[TMP_VAL1_BCAST]],{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}})
// CHECK: [[SVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[S_VAR_PRIV]],
// CHECK-64: store i{{[0-9]+}} [[SVAR_VAL]], i{{[0-9]+}}* [[SVAR_ADDR_REF]],
// CHECK-32: store i{{[0-9]+}} [[SVAR_VAL]], i{{[0-9]+}}* [[SVAR_ADDR]],
@@ -346,7 +362,7 @@ int main() {
// CHECK-DAG: [[TMP_VAL1:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP_PRIV1]],
// CHECK-DAG: [[S_ARR_PTR_BCAST1:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_PTR1]] to i8*
// CHECK-DAG: [[TMP_VAL_BCAST1:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_PTR_BCAST1]], i8* [[TMP_VAL_BCAST1]],
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_PTR_BCAST1]], i8* align {{[0-9]+}} [[TMP_VAL_BCAST1]],
// CHECK: call void @__kmpc_for_static_fini(
// lastprivates
@@ -360,7 +376,7 @@ int main() {
// CHECK-32: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_ADDR1]],
// CHECK: [[BCAST_VEC_ADDR_REF:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_REF1]] to i8*
// CHECK: [[BCAST_VEC_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[BCAST_VEC_ADDR_REF]], i8* [[BCAST_VEC_PRIV]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[BCAST_VEC_ADDR_REF]], i8* align {{[0-9]+}} [[BCAST_VEC_PRIV]],
// CHECK: [[S_ARR_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_ADDR_REF]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[S_ARR_PRIV_BCAST:%.+]] = bitcast [2 x [[S_INT_TY]]]* [[S_ARR_PRIV1]] to [[S_INT_TY]]*
// CHECK: [[S_ARR_BEGIN_GEP:%.+]] = getelementptr [[S_INT_TY]], [[S_INT_TY]]* [[S_ARR_BEGIN]], i{{[0-9]+}} 2
@@ -371,7 +387,7 @@ int main() {
// CHECK: [[S_ARR_DST_EL:%.+]] = phi [[S_INT_TY]]*{{.+}}
// CHECK: [[S_ARR_DST_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_DST_EL]] to i8*
// CHECK: [[S_ARR_SRC_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_SRC_EL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_DST_BCAST]], i8* [[S_ARR_SRC_BCAST]]{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_DST_BCAST]], i8* align {{[0-9]+}} [[S_ARR_SRC_BCAST]]{{.+}})
// CHECK: [[S_ARR_DST_NEXT:%.+]] = getelementptr [[S_INT_TY]], [[S_INT_TY]]* [[S_ARR_DST_EL]], i{{[0-9]+}} 1
// CHECK: [[S_ARR_SRC_NEXT:%.+]] = getelementptr{{.+}}
// CHECK: [[CPY_IS_FINISHED:%.+]] = icmp eq [[S_INT_TY]]* [[S_ARR_DST_NEXT]], [[S_ARR_BEGIN_GEP]]
@@ -380,6 +396,6 @@ int main() {
// CHECK: [[TMP_VAL1:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP_PRIV1]],
// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[VAR_ADDR1_REF]] to i8*
// CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VAR_ADDR_REF_BCAST]], i8* [[TMP_VAL1_BCAST]],{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}})
// CHECK: ret void
#endif
diff --git a/test/OpenMP/target_teams_distribute_simd_lastprivate_messages.cpp b/test/OpenMP/target_teams_distribute_simd_lastprivate_messages.cpp
index a143dc2fd883..3a9abfb24a1a 100644
--- a/test/OpenMP/target_teams_distribute_simd_lastprivate_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_lastprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_simd_linear_messages.cpp b/test/OpenMP/target_teams_distribute_simd_linear_messages.cpp
index 2be792bbda74..5bcd77da9e58 100644
--- a/test/OpenMP/target_teams_distribute_simd_linear_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_linear_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
namespace X {
int x;
};
diff --git a/test/OpenMP/target_teams_distribute_simd_loop_messages.cpp b/test/OpenMP/target_teams_distribute_simd_loop_messages.cpp
index 09aa548bd5c6..463c88df2c3e 100644
--- a/test/OpenMP/target_teams_distribute_simd_loop_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_loop_messages.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s -Wno-openmp-target
class S {
int a;
diff --git a/test/OpenMP/target_teams_distribute_simd_map_messages.cpp b/test/OpenMP/target_teams_distribute_simd_map_messages.cpp
index 29d48d958a3d..73671d728443 100644
--- a/test/OpenMP/target_teams_distribute_simd_map_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_map_messages.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s -Wno-openmp-target
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_simd_messages.cpp b/test/OpenMP/target_teams_distribute_simd_messages.cpp
index aa82c947010f..6ee8073357f4 100644
--- a/test/OpenMP/target_teams_distribute_simd_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
@@ -62,7 +64,7 @@ L1:
// expected-error@+1 {{unexpected OpenMP clause 'default' in directive '#pragma omp target teams distribute simd'}}
#pragma omp target teams distribute simd default(none)
for (int i = 0; i < 10; ++i)
- ++argc; // expected-error {{ariable 'argc' must have explicitly specified data sharing attributes}}
+ ++argc;
goto L2; // expected-error {{use of undeclared label 'L2'}}
#pragma omp target teams distribute simd
diff --git a/test/OpenMP/target_teams_distribute_simd_misc_messages.c b/test/OpenMP/target_teams_distribute_simd_misc_messages.c
index 70ec508f6798..397795ff6e0a 100644
--- a/test/OpenMP/target_teams_distribute_simd_misc_messages.c
+++ b/test/OpenMP/target_teams_distribute_simd_misc_messages.c
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -verify %s
+
// expected-error@+1 {{unexpected OpenMP directive '#pragma omp target teams distribute simd'}}
#pragma omp target teams distribute simd
diff --git a/test/OpenMP/target_teams_distribute_simd_nowait_messages.cpp b/test/OpenMP/target_teams_distribute_simd_nowait_messages.cpp
index 6c2c2a50ab55..25daa81eb744 100644
--- a/test/OpenMP/target_teams_distribute_simd_nowait_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_nowait_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -verify -fopenmp %s
+// RUN: %clang_cc1 -fsyntax-only -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_simd_num_teams_messages.cpp b/test/OpenMP/target_teams_distribute_simd_num_teams_messages.cpp
index 63926bcfcbe9..cdc5244fe1ef 100644
--- a/test/OpenMP/target_teams_distribute_simd_num_teams_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_num_teams_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_simd_private_codegen.cpp b/test/OpenMP/target_teams_distribute_simd_private_codegen.cpp
index c8883e18d7d9..4fa4d04c706b 100644
--- a/test/OpenMP/target_teams_distribute_simd_private_codegen.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_private_codegen.cpp
@@ -1,13 +1,26 @@
-// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
diff --git a/test/OpenMP/target_teams_distribute_simd_private_messages.cpp b/test/OpenMP/target_teams_distribute_simd_private_messages.cpp
index 3d351bdc7d82..743ac160ce5d 100644
--- a/test/OpenMP/target_teams_distribute_simd_private_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_private_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_simd_reduction_codegen.cpp b/test/OpenMP/target_teams_distribute_simd_reduction_codegen.cpp
index 76a1299981cb..c533bb30f813 100644
--- a/test/OpenMP/target_teams_distribute_simd_reduction_codegen.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_reduction_codegen.cpp
@@ -5,10 +5,23 @@
// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/target_teams_distribute_simd_reduction_messages.cpp b/test/OpenMP/target_teams_distribute_simd_reduction_messages.cpp
index 35d4e12dc339..b77082b44a9e 100644
--- a/test/OpenMP/target_teams_distribute_simd_reduction_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_reduction_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_simd_safelen_messages.cpp b/test/OpenMP/target_teams_distribute_simd_safelen_messages.cpp
index 1f41c537ced6..67b22216b97d 100644
--- a/test/OpenMP/target_teams_distribute_simd_safelen_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_safelen_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_simd_shared_messages.cpp b/test/OpenMP/target_teams_distribute_simd_shared_messages.cpp
index 9f98ab9c80b6..3147baedae8f 100644
--- a/test/OpenMP/target_teams_distribute_simd_shared_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_shared_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_simd_simdlen_messages.cpp b/test/OpenMP/target_teams_distribute_simd_simdlen_messages.cpp
index 1b7ad66af69e..6fea25a57ab6 100644
--- a/test/OpenMP/target_teams_distribute_simd_simdlen_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_simdlen_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_distribute_simd_thread_limit_messages.cpp b/test/OpenMP/target_teams_distribute_simd_thread_limit_messages.cpp
index 357f5dde313b..593650b38cc7 100644
--- a/test/OpenMP/target_teams_distribute_simd_thread_limit_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_thread_limit_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_firstprivate_messages.cpp b/test/OpenMP/target_teams_firstprivate_messages.cpp
index 84fc4ab1063a..492796981adf 100644
--- a/test/OpenMP/target_teams_firstprivate_messages.cpp
+++ b/test/OpenMP/target_teams_firstprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_if_messages.cpp b/test/OpenMP/target_teams_if_messages.cpp
index 0ab8fc3c94e8..84c900a41ab3 100644
--- a/test/OpenMP/target_teams_if_messages.cpp
+++ b/test/OpenMP/target_teams_if_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_is_device_ptr_ast_print.cpp b/test/OpenMP/target_teams_is_device_ptr_ast_print.cpp
index 3a9cee5eee19..19fe955ee76b 100644
--- a/test/OpenMP/target_teams_is_device_ptr_ast_print.cpp
+++ b/test/OpenMP/target_teams_is_device_ptr_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -49,7 +53,7 @@ struct SA {
// CHECK-NEXT: int aa[10];
// CHECK-NEXT: arr &raa = this->aa;
// CHECK-NEXT: func(
-// CHECK-NEXT: #pragma omp target teams is_device_ptr(this->k)
+// CHECK-NEXT: #pragma omp target teams is_device_ptr(this->k){{$}}
// CHECK-NEXT: {
// CHECK-NEXT: }
// CHECK-NEXT: #pragma omp target teams is_device_ptr(this->z)
diff --git a/test/OpenMP/target_teams_is_device_ptr_messages.cpp b/test/OpenMP/target_teams_is_device_ptr_messages.cpp
index 0f5be43aaee7..8ae6d7fed0e1 100644
--- a/test/OpenMP/target_teams_is_device_ptr_messages.cpp
+++ b/test/OpenMP/target_teams_is_device_ptr_messages.cpp
@@ -1,4 +1,6 @@
// RUN: %clang_cc1 -std=c++11 -verify -fopenmp -ferror-limit 200 %s
+
+// RUN: %clang_cc1 -std=c++11 -verify -fopenmp-simd -ferror-limit 200 %s
struct ST {
int *a;
};
diff --git a/test/OpenMP/target_teams_map_messages.cpp b/test/OpenMP/target_teams_map_messages.cpp
index 7874c2e105cf..57d9396394c7 100644
--- a/test/OpenMP/target_teams_map_messages.cpp
+++ b/test/OpenMP/target_teams_map_messages.cpp
@@ -1,5 +1,7 @@
-// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 200 %s
-// rUN: %clang_cc1 -DCCODE -verify -fopenmp -ferror-limit 200 -x c %s
+// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 200 %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 200 %s -Wno-openmp-target
+// RUN: %clang_cc1 -DCCODE -verify -fopenmp -ferror-limit 200 -x c %s -Wno-openmp-target
#ifdef CCODE
void foo(int arg) {
const int n = 0;
@@ -223,9 +225,17 @@ void SAclient(int arg) {
{}
#pragma omp target teams map(r.ArrS[0].A, t.ArrS[1].A)
{}
- #pragma omp target teams map(r.PtrS[0], r.PtrS->B) // expected-error {{same pointer derreferenced in multiple different ways in map clause expressions}} expected-note {{used here}}
+ #pragma omp target teams map(r.PtrS[0], r.PtrS->B) // expected-error {{same pointer dereferenced in multiple different ways in map clause expressions}} expected-note {{used here}}
+ {}
+ #pragma omp target teams map(r.PtrS, r.PtrS->B) // expected-error {{pointer cannot be mapped along with a section derived from itself}} expected-note {{used here}}
+ {}
+ #pragma omp target teams map(r.PtrS->A, r.PtrS->B)
+ {}
+ #pragma omp target teams map(r.RPtrS[0], r.RPtrS->B) // expected-error {{same pointer dereferenced in multiple different ways in map clause expressions}} expected-note {{used here}}
+ {}
+ #pragma omp target teams map(r.RPtrS, r.RPtrS->B) // expected-error {{pointer cannot be mapped along with a section derived from itself}} expected-note {{used here}}
{}
- #pragma omp target teams map(r.RPtrS[0], r.RPtrS->B) // expected-error {{same pointer derreferenced in multiple different ways in map clause expressions}} expected-note {{used here}}
+ #pragma omp target teams map(r.RPtrS->A, r.RPtrS->B)
{}
#pragma omp target teams map(r.S.Arr[:12])
{}
diff --git a/test/OpenMP/target_teams_messages.cpp b/test/OpenMP/target_teams_messages.cpp
index 7fc7d1f1aab0..3a367bfc7e4e 100644
--- a/test/OpenMP/target_teams_messages.cpp
+++ b/test/OpenMP/target_teams_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_nowait_messages.cpp b/test/OpenMP/target_teams_nowait_messages.cpp
index 9cf8cc34ca06..aeb182940315 100644
--- a/test/OpenMP/target_teams_nowait_messages.cpp
+++ b/test/OpenMP/target_teams_nowait_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_num_teams_codegen.cpp b/test/OpenMP/target_teams_num_teams_codegen.cpp
index 91288458c5aa..0961c03e30f0 100644
--- a/test/OpenMP/target_teams_num_teams_codegen.cpp
+++ b/test/OpenMP/target_teams_num_teams_codegen.cpp
@@ -6,6 +6,14 @@
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// Test target codegen - host bc file has to be created first.
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
@@ -16,13 +24,23 @@
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
-// CHECK-DAG: %ident_t = type { i32, i32, i32, i32, i8* }
+// CHECK-DAG: %struct.ident_t = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr constant %ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
// CHECK-DAG: [[S1:%.+]] = type { double }
// CHECK-DAG: [[ENTTY:%.+]] = type { i8*, i8*, i[[SZ:32|64]], i32, i32 }
@@ -35,19 +53,19 @@
// We have 6 target regions
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -58,7 +76,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx>
@@ -147,7 +165,7 @@ int bar(int n){
// CHECK: [[ARG:%.+]] = load i[[SZ]], i[[SZ]]* [[CAPEC_ADDR]], align
// CHECK: [[TEAMS:%.+]] = load i32, i32* [[CAPE_ADDR]], align
//
-// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 3, {{.*}}, i32 [[TEAMS]], i32 0)
+// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 4, {{.*}}, i32 [[TEAMS]], i32 0)
// CHECK: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
// CHECK: br i1 [[ERROR]], label %[[FAIL:.+]], label %[[END:[^,]+]]
//
@@ -158,7 +176,7 @@ int bar(int n){
//
//
//
-// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 1, {{.+}}, i32 1024, i32 0)
+// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 2, {{.+}}, i32 1024, i32 0)
// CHECK: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
// CHECK: br i1 [[ERROR]], label %[[FAIL:.+]], label %[[END:[^,]+]]
//
@@ -270,15 +288,15 @@ int bar(int n){
// CHECK-64: [[CONV:%.+]] = bitcast i[[SZ]]* [[CAPE_ADDR]] to i32*
// CHECK-64: [[NT:%.+]] = load i32, i32* [[CONV]], align
// CHECK-32: [[NT:%.+]] = load i32, i32* [[CAPE_ADDR]], align
-// CHECK: call i32 @__kmpc_push_num_teams(%ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 [[NT]], i32 0)
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 2,
+// CHECK: call i32 @__kmpc_push_num_teams(%struct.ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 [[NT]], i32 0)
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 2,
//
//
// CHECK: define internal void [[HVT2]]([[S1]]* {{%.+}})
-// CHECK: call i32 @__kmpc_push_num_teams(%ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 1024, i32 0)
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 1,
+// CHECK: call i32 @__kmpc_push_num_teams(%struct.ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 1024, i32 0)
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 1,
//
//
@@ -294,8 +312,8 @@ int bar(int n){
// CHECK-64: [[CONV:%.+]] = bitcast i[[SZ]]* [[CAPE_ADDR]] to i32*
// CHECK-64: [[NT:%.+]] = load i32, i32* [[CONV]], align
// CHECK-32: [[NT:%.+]] = load i32, i32* [[CAPE_ADDR]], align
-// CHECK: call i32 @__kmpc_push_num_teams(%ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 [[NT]], i32 0)
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 0,
+// CHECK: call i32 @__kmpc_push_num_teams(%struct.ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 [[NT]], i32 0)
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 0,
//
//
// CHECK: define internal void [[HVT4]](i[[SZ]] [[PARM:%.+]])
@@ -303,8 +321,8 @@ int bar(int n){
// CHECK-64: [[CONV:%.+]] = bitcast i[[SZ]]* [[CAPE_ADDR]] to i32*
// CHECK-64: [[NT:%.+]] = load i32, i32* [[CONV]], align
// CHECK-32: [[NT:%.+]] = load i32, i32* [[CAPE_ADDR]], align
-// CHECK: call i32 @__kmpc_push_num_teams(%ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 [[NT]], i32 0)
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 0,
+// CHECK: call i32 @__kmpc_push_num_teams(%struct.ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 [[NT]], i32 0)
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 0,
//
//
@@ -313,8 +331,8 @@ int bar(int n){
// CHECK: define internal void [[HVT5]](
-// CHECK: call i32 @__kmpc_push_num_teams(%ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 20, i32 0)
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 0,
+// CHECK: call i32 @__kmpc_push_num_teams(%struct.ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 20, i32 0)
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 0,
//
//
@@ -324,8 +342,8 @@ int bar(int n){
// CHECK: [[CONV:%.+]] = bitcast i[[SZ]]* [[CAPE_ADDR]] to i16*
// CHECK: [[T:%.+]] = load i16, i16* [[CONV]], align
// CHECK: [[NT:%.+]] = sext i16 [[T]] to i32
-// CHECK: call i32 @__kmpc_push_num_teams(%ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 [[NT]], i32 0)
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 2,
+// CHECK: call i32 @__kmpc_push_num_teams(%struct.ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 [[NT]], i32 0)
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 2,
//
//
diff --git a/test/OpenMP/target_teams_num_teams_messages.cpp b/test/OpenMP/target_teams_num_teams_messages.cpp
index e220fb67477d..9134af640c90 100644
--- a/test/OpenMP/target_teams_num_teams_messages.cpp
+++ b/test/OpenMP/target_teams_num_teams_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_private_messages.cpp b/test/OpenMP/target_teams_private_messages.cpp
index 69551ff96cc0..7ee509c8acaa 100644
--- a/test/OpenMP/target_teams_private_messages.cpp
+++ b/test/OpenMP/target_teams_private_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_reduction_messages.cpp b/test/OpenMP/target_teams_reduction_messages.cpp
index b5876b108508..c62f2c58440b 100644
--- a/test/OpenMP/target_teams_reduction_messages.cpp
+++ b/test/OpenMP/target_teams_reduction_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -o - %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_shared_messages.cpp b/test/OpenMP/target_teams_shared_messages.cpp
index 84e412eb4c4b..3fb84967b9d9 100644
--- a/test/OpenMP/target_teams_shared_messages.cpp
+++ b/test/OpenMP/target_teams_shared_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/target_teams_thread_limit_codegen.cpp b/test/OpenMP/target_teams_thread_limit_codegen.cpp
index 5d93c1de77fe..21c9c5a68e70 100644
--- a/test/OpenMP/target_teams_thread_limit_codegen.cpp
+++ b/test/OpenMP/target_teams_thread_limit_codegen.cpp
@@ -6,6 +6,14 @@
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// Test target codegen - host bc file has to be created first.
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
@@ -16,13 +24,23 @@
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
-// CHECK-DAG: %ident_t = type { i32, i32, i32, i32, i8* }
+// CHECK-DAG: %struct.ident_t = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr constant %ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
// CHECK-DAG: [[S1:%.+]] = type { double }
// CHECK-DAG: [[ENTTY:%.+]] = type { i8*, i8*, i[[SZ:32|64]], i32, i32 }
@@ -35,19 +53,19 @@
// We have 6 target regions
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
-// CHECK-DAG: @{{.*}} = private constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -58,7 +76,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx>
@@ -147,7 +165,7 @@ int bar(int n){
// CHECK: [[ARG:%.+]] = load i[[SZ]], i[[SZ]]* [[CAPEC_ADDR]], align
// CHECK: [[TL:%.+]] = load i32, i32* [[CAPE_ADDR]], align
//
-// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 3, {{.*}}, i32 0, i32 [[TL]])
+// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 4, {{.*}}, i32 0, i32 [[TL]])
// CHECK: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
// CHECK: br i1 [[ERROR]], label %[[FAIL:.+]], label %[[END:[^,]+]]
//
@@ -158,7 +176,7 @@ int bar(int n){
//
//
//
-// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 1, {{.+}}, i32 0, i32 1024)
+// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 2, {{.+}}, i32 0, i32 1024)
// CHECK: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
// CHECK: br i1 [[ERROR]], label %[[FAIL:.+]], label %[[END:[^,]+]]
//
@@ -279,15 +297,15 @@ int bar(int n){
// CHECK-64: [[CONV:%.+]] = bitcast i[[SZ]]* [[CAPE_ADDR]] to i32*
// CHECK-64: [[TL:%.+]] = load i32, i32* [[CONV]], align
// CHECK-32: [[TL:%.+]] = load i32, i32* [[CAPE_ADDR]], align
-// CHECK: call i32 @__kmpc_push_num_teams(%ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 0, i32 [[TL]])
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 2,
+// CHECK: call i32 @__kmpc_push_num_teams(%struct.ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 0, i32 [[TL]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 2,
//
//
// CHECK: define internal void [[HVT2]]([[S1]]* {{%.+}})
-// CHECK: call i32 @__kmpc_push_num_teams(%ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 0, i32 1024)
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 1,
+// CHECK: call i32 @__kmpc_push_num_teams(%struct.ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 0, i32 1024)
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 1,
//
//
@@ -307,8 +325,8 @@ int bar(int n){
// CHECK-64: [[TL:%.+]] = load i32, i32* [[CONV2]], align
// CHECK-32: [[NT:%.+]] = load i32, i32* [[CAPE_ADDR1]], align
// CHECK-32: [[TL:%.+]] = load i32, i32* [[CAPE_ADDR2]], align
-// CHECK: call i32 @__kmpc_push_num_teams(%ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 [[NT]], i32 [[TL]])
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 0,
+// CHECK: call i32 @__kmpc_push_num_teams(%struct.ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 [[NT]], i32 [[TL]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 0,
//
//
// CHECK: define internal void [[HVT4]](i[[SZ]] [[PARM:%.+]])
@@ -316,8 +334,8 @@ int bar(int n){
// CHECK-64: [[CONV:%.+]] = bitcast i[[SZ]]* [[CAPE_ADDR]] to i32*
// CHECK-64: [[TL:%.+]] = load i32, i32* [[CONV]], align
// CHECK-32: [[TL:%.+]] = load i32, i32* [[CAPE_ADDR]], align
-// CHECK: call i32 @__kmpc_push_num_teams(%ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 0, i32 [[TL]])
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 0,
+// CHECK: call i32 @__kmpc_push_num_teams(%struct.ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 0, i32 [[TL]])
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 0,
//
//
@@ -326,8 +344,8 @@ int bar(int n){
// CHECK: define internal void [[HVT5]](
-// CHECK: call i32 @__kmpc_push_num_teams(%ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 0, i32 20)
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 0,
+// CHECK: call i32 @__kmpc_push_num_teams(%struct.ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 0, i32 20)
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 0,
//
//
@@ -337,8 +355,8 @@ int bar(int n){
// CHECK: [[CONV:%.+]] = bitcast i[[SZ]]* [[CAPE_ADDR]] to i16*
// CHECK: [[T:%.+]] = load i16, i16* [[CONV]], align
// CHECK: [[NT:%.+]] = sext i16 [[T]] to i32
-// CHECK: call i32 @__kmpc_push_num_teams(%ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 [[NT]], i32 1024)
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC]], i32 2,
+// CHECK: call i32 @__kmpc_push_num_teams(%struct.ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 [[NT]], i32 1024)
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC]], i32 2,
//
//
diff --git a/test/OpenMP/target_teams_thread_limit_messages.cpp b/test/OpenMP/target_teams_thread_limit_messages.cpp
index 2685f242196c..4b0a4b05c828 100644
--- a/test/OpenMP/target_teams_thread_limit_messages.cpp
+++ b/test/OpenMP/target_teams_thread_limit_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/target_update_ast_print.cpp b/test/OpenMP/target_update_ast_print.cpp
index cbff907acaee..e60e081b3210 100644
--- a/test/OpenMP/target_update_ast_print.cpp
+++ b/test/OpenMP/target_update_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -21,7 +25,7 @@ T foo(T targ, U uarg) {
// CHECK: static T a;
// CHECK-NEXT: U b;
// CHECK-NEXT: int l;
-// CHECK-NEXT: #pragma omp target update to(a) if(l > 5) device(l) nowait depend(inout : l)
+// CHECK-NEXT: #pragma omp target update to(a) if(l > 5) device(l) nowait depend(inout : l){{$}}
// CHECK-NEXT: #pragma omp target update from(b) if(l < 5) device(l - 1) nowait depend(inout : l)
// CHECK: static int a;
// CHECK-NEXT: float b;
diff --git a/test/OpenMP/target_update_codegen.cpp b/test/OpenMP/target_update_codegen.cpp
index 7f45c313a8a1..5beb853a2f6d 100644
--- a/test/OpenMP/target_update_codegen.cpp
+++ b/test/OpenMP/target_update_codegen.cpp
@@ -9,6 +9,14 @@
// RUN: %clang_cc1 -DCK1 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
// RUN: %clang_cc1 -DCK1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
#ifdef CK1
// CK1: [[ST:%.+]] = type { i32, double* }
@@ -29,8 +37,9 @@ double gc[100];
// CK1: [[MTYPE03:@.+]] = {{.+}}constant [1 x i64] [i64 34]
-// CK1: [[SIZE04:@.+]] = {{.+}}constant [2 x i[[sz]]] [i[[sz]] {{8|4}}, i[[sz]] 24]
-// CK1: [[MTYPE04:@.+]] = {{.+}}constant [2 x i64] [i64 33, i64 17]
+// CK1-64: [[SIZE04:@.+]] = {{.+}}constant [2 x i64] [i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)), i64 24]
+// CK1-32: [[SIZE04:@.+]] = {{.+}}constant [2 x i32] [i32 trunc (i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)) to i32), i32 24]
+// CK1: [[MTYPE04:@.+]] = {{.+}}constant [2 x i64] [i64 32, i64 281474976710673]
// CK1-LABEL: _Z3fooi
void foo(int arg) {
@@ -143,6 +152,14 @@ void foo(int arg) {
// RUN: %clang_cc1 -DCK2 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
// RUN: %clang_cc1 -DCK2 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
#ifdef CK2
// CK2: [[ST:%.+]] = type { i32, double* }
@@ -159,8 +176,7 @@ struct ST {
}
};
-// CK2: [[SIZE00:@.+]] = {{.+}}constant [2 x i[[sz:64|32]]] [i{{64|32}} {{8|4}}, i{{64|32}} 24]
-// CK2: [[MTYPE00:@.+]] = {{.+}}constant [2 x i64] [i64 34, i64 18]
+// CK2: [[MTYPE00:@.+]] = {{.+}}constant [2 x i64] [i64 32, i64 281474976710674]
// CK2-LABEL: _Z3bari
int bar(int arg){
@@ -171,18 +187,21 @@ int bar(int arg){
// Region 00
// CK2: br i1 %{{[^,]+}}, label %[[IFTHEN:[^,]+]], label %[[IFELSE:[^,]+]]
// CK2: [[IFTHEN]]
-// CK2-DAG: call void @__tgt_target_data_update(i64 [[DEV:%[^,]+]], i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[SIZE00]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE00]]{{.+}})
+// CK2-DAG: call void @__tgt_target_data_update(i64 [[DEV:%[^,]+]], i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE00]]{{.+}})
// CK2-DAG: [[DEV]] = sext i32 [[DEVi32:%[^,]+]] to i64
// CK2-DAG: [[DEVi32]] = load i32, i32* %{{[^,]+}},
// CK2-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
// CK2-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
+// CK2-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
// CK2-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
// CK2-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
+// CK2-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
// CK2-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]**
// CK2-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double***
// CK2-DAG: store [[ST]]* [[VAR0:%[^,]+]], [[ST]]** [[CBP0]]
// CK2-DAG: store double** [[SEC0:%[^,]+]], double*** [[CP0]]
+// CK2-DAG: store i[[sz]] {{%.+}}, i[[sz]]* [[S0]]
// CK2-DAG: [[SEC0]] = getelementptr inbounds {{.*}}[[ST]]* [[VAR0]], i32 0, i32 1
@@ -210,6 +229,14 @@ int bar(int arg){
// RUN: %clang_cc1 -DCK3 -verify -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-32
// RUN: %clang_cc1 -DCK3 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-32
+
+// RUN: %clang_cc1 -DCK3 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// RUN: %clang_cc1 -DCK3 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// RUN: %clang_cc1 -DCK3 -verify -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// RUN: %clang_cc1 -DCK3 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// SIMD-ONLY2-NOT: {{__kmpc|__tgt}}
#ifdef CK3
// CK3-LABEL: no_target_devices
@@ -229,6 +256,14 @@ void no_target_devices(int arg) {
// RUN: %clang_cc1 -DCK4 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK4 --check-prefix CK4-32
+// RUN: %clang_cc1 -DCK4 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY3 %s
+// RUN: %clang_cc1 -DCK4 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY3 %s
+// RUN: %clang_cc1 -DCK4 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY3 %s
+// RUN: %clang_cc1 -DCK4 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY3 %s
+// SIMD-ONLY3-NOT: {{__kmpc|__tgt}}
+
// RUN: %clang_cc1 -DCK4 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
// RUN: %clang_cc1 -DCK4 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCK4 --check-prefix TCK4-64
// RUN: %clang_cc1 -DCK4 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
@@ -237,6 +272,16 @@ void no_target_devices(int arg) {
// RUN: %clang_cc1 -DCK4 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix TCK4 --check-prefix TCK4-32
// RUN: %clang_cc1 -DCK4 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCK4 --check-prefix TCK4-32
+
+// RUN: %clang_cc1 -DCK4 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -DCK4 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY4 %s
+// RUN: %clang_cc1 -DCK4 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY4 %s
+// RUN: %clang_cc1 -DCK4 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -DCK4 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY4 %s
+// RUN: %clang_cc1 -DCK4 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY4 %s
+// SIMD-ONLY4-NOT: {{__kmpc|__tgt}}
#ifdef CK4
// CK4-LABEL: device_side_scan
diff --git a/test/OpenMP/target_update_depend_codegen.cpp b/test/OpenMP/target_update_depend_codegen.cpp
index 6542aa1958d3..ee1b0bfceeee 100644
--- a/test/OpenMP/target_update_depend_codegen.cpp
+++ b/test/OpenMP/target_update_depend_codegen.cpp
@@ -5,6 +5,14 @@
// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
// CK1: [[ST:%.+]] = type { i32, double* }
// CK1: %struct.kmp_depend_info = type { i[[sz:64|32]],
@@ -29,8 +37,9 @@ double gc[100];
// CK1: [[MTYPE03:@.+]] = {{.+}}constant [1 x i64] [i64 34]
-// CK1: [[SIZE04:@.+]] = {{.+}}constant [2 x i[[sz]]] [i[[sz]] {{8|4}}, i[[sz]] 24]
-// CK1: [[MTYPE04:@.+]] = {{.+}}constant [2 x i64] [i64 33, i64 17]
+// CK1-64: [[SIZE04:@.+]] = {{.+}}constant [2 x i64] [i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)), i64 24]
+// CK1-32: [[SIZE04:@.+]] = {{.+}}constant [2 x i32] [i32 trunc (i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)) to i32), i32 24]
+// CK1: [[MTYPE04:@.+]] = {{.+}}constant [2 x i64] [i64 32, i64 281474976710673]
// CK1-LABEL: _Z3fooi
void foo(int arg) {
@@ -54,25 +63,25 @@ void foo(int arg) {
// CK1: [[CAP_DEVICE:%.+]] = getelementptr inbounds %struct.anon, %struct.anon* [[CAPTURES:%.+]], i32 0, i32 0
// CK1: [[DEVICE:%.+]] = load i32, i32* %{{.+}}
// CK1: store i32 [[DEVICE]], i32* [[CAP_DEVICE]],
- // CK1: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%ident_t* {{.+}}, i32 {{.+}}, i32 1, i[[sz]] [[sz]], i[[sz]] 4, i32 (i32, i8*)* bitcast (i32 (i32, %struct.kmp_task_t_with_privates*)* [[TASK_ENTRY0:@.+]] to i32 (i32, i8*)*))
+ // CK1: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* {{.+}}, i32 {{.+}}, i32 1, i[[sz]] [[sz]], i[[sz]] 4, i32 (i32, i8*)* bitcast (i32 (i32, %struct.kmp_task_t_with_privates*)* [[TASK_ENTRY0:@.+]] to i32 (i32, i8*)*))
// CK1: [[BC:%.+]] = bitcast i8* [[RES]] to %struct.kmp_task_t_with_privates*
// CK1: [[TASK_T:%.+]] = getelementptr inbounds %struct.kmp_task_t_with_privates, %struct.kmp_task_t_with_privates* [[BC]], i32 0, i32 0
// CK1: [[SHAREDS:%.+]] = getelementptr inbounds %struct.kmp_task_t, %struct.kmp_task_t* [[TASK_T]], i32 0, i32 0
// CK1: [[SHAREDS_REF:%.+]] = load i8*, i8** [[SHAREDS]],
// CK1: [[BC1:%.+]] = bitcast %struct.anon* [[CAPTURES]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[SHAREDS_REF]], i8* [[BC1]], i[[sz]] 4, i32 4, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align 4 [[SHAREDS_REF]], i8* align 4 [[BC1]], i[[sz]] 4, i1 false)
// CK1: [[PRIVS:%.+]] = getelementptr inbounds %struct.kmp_task_t_with_privates, %struct.kmp_task_t_with_privates* [[BC]], i32 0, i32 1
// CK1: [[PRIVS_BASEPTRS:%.+]] = getelementptr inbounds %struct..kmp_privates.t, %struct..kmp_privates.t* [[PRIVS]], i32 0, i32 0
// CK1: [[BC_PRIVS_BASEPTRS:%.+]] = bitcast [1 x i8*]* [[PRIVS_BASEPTRS]] to i8*
// CK1: [[BC_BASEPTRS:%.+]] = bitcast i8** [[GEPBP0]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_BASEPTRS]], i8* [[BC_BASEPTRS]], i[[sz]] {{8|4}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_BASEPTRS]], i8* align {{8|4}} [[BC_BASEPTRS]], i[[sz]] {{8|4}}, i1 false)
// CK1: [[PRIVS_PTRS:%.+]] = getelementptr inbounds %struct..kmp_privates.t, %struct..kmp_privates.t* [[PRIVS]], i32 0, i32 1
// CK1: [[BC_PRIVS_PTRS:%.+]] = bitcast [1 x i8*]* [[PRIVS_PTRS]] to i8*
// CK1: [[BC_PTRS:%.+]] = bitcast i8** [[GEPP0]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_PTRS]], i8* [[BC_PTRS]], i[[sz]] {{8|4}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_PTRS]], i8* align {{8|4}} [[BC_PTRS]], i[[sz]] {{8|4}}, i1 false)
// CK1: [[PRIVS_SIZES:%.+]] = getelementptr inbounds %struct..kmp_privates.t, %struct..kmp_privates.t* [[PRIVS]], i32 0, i32 2
// CK1: [[BC_PRIVS_SIZES:%.+]] = bitcast [1 x i[[sz]]]* [[PRIVS_SIZES]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_SIZES]], i8* bitcast ([1 x i[[sz]]]* [[SIZE00]] to i8*), i[[sz]] {{8|4}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_SIZES]], i8* align {{8|4}} bitcast ([1 x i[[sz]]]* [[SIZE00]] to i8*), i[[sz]] {{8|4}}, i1 false)
// CK1: [[DEP:%.+]] = getelementptr inbounds [1 x %struct.kmp_depend_info], [1 x %struct.kmp_depend_info]* [[MAIN_DEP:%.+]], i[[sz]] 0, i[[sz]] 0
// CK1: [[DEP_ADR:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[DEP]], i32 0, i32 0
// CK1: [[BC_ADR:%.+]] = ptrtoint i32* %{{.+}} to i[[sz]]
@@ -83,7 +92,7 @@ void foo(int arg) {
// CK1: store i8 1, i8* [[DEP_ATTRS]]
// CK1: [[DEP:%.+]] = getelementptr inbounds [1 x %struct.kmp_depend_info], [1 x %struct.kmp_depend_info]* [[MAIN_DEP]], i32 0, i32 0
// CK1: [[BC:%.+]] = bitcast %struct.kmp_depend_info* [[DEP]] to i8*
- // CK1: = call i32 @__kmpc_omp_task_with_deps(%ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]], i32 1, i8* [[BC]], i32 0, i8* null)
+ // CK1: = call i32 @__kmpc_omp_task_with_deps(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]], i32 1, i8* [[BC]], i32 0, i8* null)
// CK1: %{{.+}} = add nsw i32 %{{[^,]+}}, 1
#pragma omp target update if(1+3-5) device(arg) from(gc) nowait depend(in: arg)
@@ -110,25 +119,25 @@ void foo(int arg) {
// CK1: [[IF_BOOL:%.+]] = trunc i8 [[IF]] to i1
// CK1: [[IF:%.+]] = zext i1 [[IF_BOOL]] to i8
// CK1: store i8 [[IF]], i8* [[IF_DEVICE]],
- // CK1: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%ident_t* {{.+}}, i32 {{.+}}, i32 1, i[[sz]] [[sz]], i[[sz]] 1, i32 (i32, i8*)* bitcast (i32 (i32, %struct.kmp_task_t_with_privates{{.+}}*)* [[TASK_ENTRY2:@.+]] to i32 (i32, i8*)*))
+ // CK1: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* {{.+}}, i32 {{.+}}, i32 1, i[[sz]] [[sz]], i[[sz]] 1, i32 (i32, i8*)* bitcast (i32 (i32, %struct.kmp_task_t_with_privates{{.+}}*)* [[TASK_ENTRY2:@.+]] to i32 (i32, i8*)*))
// CK1: [[RES_BC:%.+]] = bitcast i8* [[RES]] to %struct.kmp_task_t_with_privates{{.+}}*
// CK1: [[TASK_T:%.+]] = getelementptr inbounds %struct.kmp_task_t_with_privates{{.+}}, %struct.kmp_task_t_with_privates{{.+}}* [[RES_BC]], i32 0, i32 0
// CK1: [[SHAREDS:%.+]] = getelementptr inbounds %struct.kmp_task_t, %struct.kmp_task_t* [[TASK_T]], i32 0, i32 0
// CK1: [[SHAREDS_REF:%.+]] = load i8*, i8** [[SHAREDS]],
// CK1: [[BC1:%.+]] = bitcast %struct.anon{{.+}}* [[CAPTURES]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[SHAREDS_REF]], i8* [[BC1]], i[[sz]] 1, i32 1, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align 1 [[SHAREDS_REF]], i8* align 1 [[BC1]], i[[sz]] 1, i1 false)
// CK1: [[PRIVS:%.+]] = getelementptr inbounds %struct.kmp_task_t_with_privates{{.+}}, %struct.kmp_task_t_with_privates{{.+}}* [[RES_BC]], i32 0, i32 1
// CK1: [[PRIVS_BASEPTRS:%.+]] = getelementptr inbounds %struct..kmp_privates.t{{.+}}, %struct..kmp_privates.t{{.+}}* [[PRIVS]], i32 0, i32 0
// CK1: [[BC_PRIVS_BASEPTRS:%.+]] = bitcast [1 x i8*]* [[PRIVS_BASEPTRS]] to i8*
// CK1: [[BC_BASEPTRS:%.+]] = bitcast i8** [[GEPBP0]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_BASEPTRS]], i8* [[BC_BASEPTRS]], i[[sz]] {{8|4}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_BASEPTRS]], i8* align {{8|4}} [[BC_BASEPTRS]], i[[sz]] {{8|4}}, i1 false)
// CK1: [[PRIVS_PTRS:%.+]] = getelementptr inbounds %struct..kmp_privates.t{{.+}}, %struct..kmp_privates.t{{.+}}* [[PRIVS]], i32 0, i32 1
// CK1: [[BC_PRIVS_PTRS:%.+]] = bitcast [1 x i8*]* [[PRIVS_PTRS]] to i8*
// CK1: [[BC_PTRS:%.+]] = bitcast i8** [[GEPP0]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_PTRS]], i8* [[BC_PTRS]], i[[sz]] {{8|4}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_PTRS]], i8* align {{8|4}} [[BC_PTRS]], i[[sz]] {{8|4}}, i1 false)
// CK1: [[PRIVS_SIZES:%.+]] = getelementptr inbounds %struct..kmp_privates.t{{.+}}, %struct..kmp_privates.t{{.+}}* [[PRIVS]], i32 0, i32 2
// CK1: [[BC_PRIVS_SIZES:%.+]] = bitcast [1 x i[[sz]]]* [[PRIVS_SIZES]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_SIZES]], i8* bitcast ([1 x i[[sz]]]* [[SIZE02]] to i8*), i[[sz]] {{8|4}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_SIZES]], i8* align {{8|4}} bitcast ([1 x i[[sz]]]* [[SIZE02]] to i8*), i[[sz]] {{8|4}}, i1 false)
// CK1: [[DEP:%.+]] = getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* [[MAIN_DEP:%.+]], i[[sz]] 0, i[[sz]] 0
// CK1: [[DEP_ADR:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[DEP]], i32 0, i32 0
// CK1: [[BC_ADR:%.+]] = ptrtoint i32* %{{.+}} to i[[sz]]
@@ -154,10 +163,10 @@ void foo(int arg) {
// CK1: store i8 3, i8* [[DEP_ATTRS]]
// CK1: [[DEP:%.+]] = getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* [[MAIN_DEP]], i32 0, i32 0
// CK1: [[BC:%.+]] = bitcast %struct.kmp_depend_info* [[DEP]] to i8*
- // CK1: call void @__kmpc_omp_wait_deps(%ident_t* @{{.+}}, i32 %{{.+}}, i32 3, i8* [[BC]], i32 0, i8* null)
- // CK1: call void @__kmpc_omp_task_begin_if0(%ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
+ // CK1: call void @__kmpc_omp_wait_deps(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i32 3, i8* [[BC]], i32 0, i8* null)
+ // CK1: call void @__kmpc_omp_task_begin_if0(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
// CK1: = call i32 [[TASK_ENTRY2]](i32 %{{.+}}, %struct.kmp_task_t_with_privates{{.+}}* [[RES_BC]])
- // CK1: call void @__kmpc_omp_task_complete_if0(%ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
+ // CK1: call void @__kmpc_omp_task_complete_if0(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
// CK1: br label %[[IFEND:[^,]+]]
@@ -183,22 +192,22 @@ void foo(int arg) {
// CK1: [[GEPBP0:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[BP]], i32 0, i32 0
// CK1: [[GEPP0:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[P]], i32 0, i32 0
// CK1: [[GEPS0:%.+]] = getelementptr inbounds [1 x i[[sz]]], [1 x i[[sz]]]* [[S]], i32 0, i32 0
- // CK1: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%ident_t* {{.+}}, i32 {{.+}}, i32 1, i[[sz]] [[sz]], i[[sz]] 1, i32 (i32, i8*)* bitcast (i32 (i32, %struct.kmp_task_t_with_privates{{.+}}*)* [[TASK_ENTRY3:@.+]] to i32 (i32, i8*)*))
+ // CK1: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* {{.+}}, i32 {{.+}}, i32 1, i[[sz]] [[sz]], i[[sz]] 1, i32 (i32, i8*)* bitcast (i32 (i32, %struct.kmp_task_t_with_privates{{.+}}*)* [[TASK_ENTRY3:@.+]] to i32 (i32, i8*)*))
// CK1: [[RES_BC:%.+]] = bitcast i8* [[RES]] to %struct.kmp_task_t_with_privates{{.+}}*
// CK1: [[TASK_T:%.+]] = getelementptr inbounds %struct.kmp_task_t_with_privates{{.+}}, %struct.kmp_task_t_with_privates{{.+}}* [[RES_BC]], i32 0, i32 0
// CK1: [[PRIVS:%.+]] = getelementptr inbounds %struct.kmp_task_t_with_privates{{.+}}, %struct.kmp_task_t_with_privates{{.+}}* [[RES_BC]], i32 0, i32 1
// CK1: [[PRIVS_BASEPTRS:%.+]] = getelementptr inbounds %struct..kmp_privates.t{{.+}}, %struct..kmp_privates.t{{.+}}* [[PRIVS]], i32 0, i32 0
// CK1: [[BC_PRIVS_BASEPTRS:%.+]] = bitcast [1 x i8*]* [[PRIVS_BASEPTRS]] to i8*
// CK1: [[BC_BASEPTRS:%.+]] = bitcast i8** [[GEPBP0]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_BASEPTRS]], i8* [[BC_BASEPTRS]], i[[sz]] {{8|4}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_BASEPTRS]], i8* align {{8|4}} [[BC_BASEPTRS]], i[[sz]] {{8|4}}, i1 false)
// CK1: [[PRIVS_PTRS:%.+]] = getelementptr inbounds %struct..kmp_privates.t{{.+}}, %struct..kmp_privates.t{{.+}}* [[PRIVS]], i32 0, i32 1
// CK1: [[BC_PRIVS_PTRS:%.+]] = bitcast [1 x i8*]* [[PRIVS_PTRS]] to i8*
// CK1: [[BC_PTRS:%.+]] = bitcast i8** [[GEPP0]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_PTRS]], i8* [[BC_PTRS]], i[[sz]] {{8|4}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_PTRS]], i8* align {{8|4}} [[BC_PTRS]], i[[sz]] {{8|4}}, i1 false)
// CK1: [[PRIVS_SIZES:%.+]] = getelementptr inbounds %struct..kmp_privates.t{{.+}}, %struct..kmp_privates.t{{.+}}* [[PRIVS]], i32 0, i32 2
// CK1: [[BC_PRIVS_SIZES:%.+]] = bitcast [1 x i[[sz]]]* [[PRIVS_SIZES]] to i8*
// CK1: [[BC_SIZES:%.+]] = bitcast i[[sz]]* [[GEPS0]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_SIZES]], i8* [[BC_SIZES]], i[[sz]] {{8|4}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_SIZES]], i8* align {{8|4}} [[BC_SIZES]], i[[sz]] {{8|4}}, i1 false)
// CK1: [[DEP:%.+]] = getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* [[MAIN_DEP:%.+]], i[[sz]] 0, i[[sz]] 0
// CK1: [[DEP_ADR:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[DEP]], i32 0, i32 0
// CK1: [[BC_ADR:%.+]] = ptrtoint float* %{{.+}} to i[[sz]]
@@ -232,10 +241,10 @@ void foo(int arg) {
// CK1: store i8 3, i8* [[DEP_ATTRS]]
// CK1: [[DEP:%.+]] = getelementptr inbounds [4 x %struct.kmp_depend_info], [4 x %struct.kmp_depend_info]* [[MAIN_DEP]], i32 0, i32 0
// CK1: [[BC:%.+]] = bitcast %struct.kmp_depend_info* [[DEP]] to i8*
- // CK1: call void @__kmpc_omp_wait_deps(%ident_t* @{{.+}}, i32 %{{.+}}, i32 4, i8* [[BC]], i32 0, i8* null)
- // CK1: call void @__kmpc_omp_task_begin_if0(%ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
+ // CK1: call void @__kmpc_omp_wait_deps(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i32 4, i8* [[BC]], i32 0, i8* null)
+ // CK1: call void @__kmpc_omp_task_begin_if0(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
// CK1: = call i32 [[TASK_ENTRY3]](i32 %{{.+}}, %struct.kmp_task_t_with_privates{{.+}}* [[RES_BC]])
- // CK1: call void @__kmpc_omp_task_complete_if0(%ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
+ // CK1: call void @__kmpc_omp_task_complete_if0(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
#pragma omp target update from(lb) depend(out: lb, arg, la, gc)
{++arg;}
@@ -257,21 +266,21 @@ void foo(int arg) {
// CK1: store double* %{{.+}}, double** [[P1_BC]],
// CK1: [[GEPBP0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 0
// CK1: [[GEPP0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P]], i32 0, i32 0
- // CK1: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%ident_t* {{.+}}, i32 {{.+}}, i32 1, i[[sz]] {{88|44}}, i[[sz]] 1, i32 (i32, i8*)* bitcast (i32 (i32, %struct.kmp_task_t_with_privates{{.+}}*)* [[TASK_ENTRY4:@.+]] to i32 (i32, i8*)*))
+ // CK1: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* {{.+}}, i32 {{.+}}, i32 1, i[[sz]] {{88|44}}, i[[sz]] 1, i32 (i32, i8*)* bitcast (i32 (i32, %struct.kmp_task_t_with_privates{{.+}}*)* [[TASK_ENTRY4:@.+]] to i32 (i32, i8*)*))
// CK1: [[RES_BC:%.+]] = bitcast i8* [[RES]] to %struct.kmp_task_t_with_privates{{.+}}*
// CK1: [[TASK_T:%.+]] = getelementptr inbounds %struct.kmp_task_t_with_privates{{.+}}, %struct.kmp_task_t_with_privates{{.+}}* [[RES_BC]], i32 0, i32 0
// CK1: [[PRIVS:%.+]] = getelementptr inbounds %struct.kmp_task_t_with_privates{{.+}}, %struct.kmp_task_t_with_privates{{.+}}* [[RES_BC]], i32 0, i32 1
// CK1: [[PRIVS_BASEPTRS:%.+]] = getelementptr inbounds %struct..kmp_privates.t{{.+}}, %struct..kmp_privates.t{{.+}}* [[PRIVS]], i32 0, i32 0
// CK1: [[BC_PRIVS_BASEPTRS:%.+]] = bitcast [2 x i8*]* [[PRIVS_BASEPTRS]] to i8*
// CK1: [[BC_BASEPTRS:%.+]] = bitcast i8** [[GEPBP0]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_BASEPTRS]], i8* [[BC_BASEPTRS]], i[[sz]] {{16|8}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_BASEPTRS]], i8* align {{8|4}} [[BC_BASEPTRS]], i[[sz]] {{16|8}}, i1 false)
// CK1: [[PRIVS_PTRS:%.+]] = getelementptr inbounds %struct..kmp_privates.t{{.+}}, %struct..kmp_privates.t{{.+}}* [[PRIVS]], i32 0, i32 1
// CK1: [[BC_PRIVS_PTRS:%.+]] = bitcast [2 x i8*]* [[PRIVS_PTRS]] to i8*
// CK1: [[BC_PTRS:%.+]] = bitcast i8** [[GEPP0]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_PTRS]], i8* [[BC_PTRS]], i[[sz]] {{16|8}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_PTRS]], i8* align {{8|4}} [[BC_PTRS]], i[[sz]] {{16|8}}, i1 false)
// CK1: [[PRIVS_SIZES:%.+]] = getelementptr inbounds %struct..kmp_privates.t{{.+}}, %struct..kmp_privates.t{{.+}}* [[PRIVS]], i32 0, i32 2
// CK1: [[BC_PRIVS_SIZES:%.+]] = bitcast [2 x i[[sz]]]* [[PRIVS_SIZES]] to i8*
- // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* [[BC_PRIVS_SIZES]], i8* bitcast ([2 x i[[sz]]]* [[SIZE04]] to i8*), i[[sz]] {{16|8}}, i32 {{8|4}}, i1 false)
+ // CK1: call void @llvm.memcpy.p0i8.p0i8.i[[sz]](i8* align {{8|4}} [[BC_PRIVS_SIZES]], i8* align {{8|4}} bitcast ([2 x i[[sz]]]* [[SIZE04]] to i8*), i[[sz]] {{16|8}}, i1 false)
// CK1: [[DEP:%.+]] = getelementptr inbounds [5 x %struct.kmp_depend_info], [5 x %struct.kmp_depend_info]* [[MAIN_DEP:%.+]], i[[sz]] 0, i[[sz]] 0
// CK1: [[DEP_ADR:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[DEP]], i32 0, i32 0
// CK1: [[BC_ADR:%.+]] = ptrtoint double* %{{.+}} to i[[sz]]
@@ -313,10 +322,10 @@ void foo(int arg) {
// CK1: store i8 1, i8* [[DEP_ATTRS]]
// CK1: [[DEP:%.+]] = getelementptr inbounds [5 x %struct.kmp_depend_info], [5 x %struct.kmp_depend_info]* [[MAIN_DEP]], i32 0, i32 0
// CK1: [[BC:%.+]] = bitcast %struct.kmp_depend_info* [[DEP]] to i8*
- // CK1: call void @__kmpc_omp_wait_deps(%ident_t* @{{.+}}, i32 %{{.+}}, i32 5, i8* [[BC]], i32 0, i8* null)
- // CK1: call void @__kmpc_omp_task_begin_if0(%ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
+ // CK1: call void @__kmpc_omp_wait_deps(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i32 5, i8* [[BC]], i32 0, i8* null)
+ // CK1: call void @__kmpc_omp_task_begin_if0(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
// CK1: = call i32 [[TASK_ENTRY4]](i32 %{{.+}}, %struct.kmp_task_t_with_privates{{.+}}* [[RES_BC]])
- // CK1: call void @__kmpc_omp_task_complete_if0(%ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
+ // CK1: call void @__kmpc_omp_task_complete_if0(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i8* [[RES]])
#pragma omp target update to(gb.b[:3]) depend(in: gb.b[:3], la, lb, gc, arg)
{++arg;}
}
@@ -328,9 +337,9 @@ void foo(int arg) {
// CK1-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
// CK1-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
// CK1-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
-// CK1-DAG: [[BP]] = load [1 x i8*]*, [1 x i8*]** [[BP_PRIV:%.+]],
-// CK1-DAG: [[P]] = load [1 x i8*]*, [1 x i8*]** [[P_PRIV:%.+]],
-// CK1-DAG: [[S]] = load [1 x i[[sz]]]*, [1 x i[[sz]]]** [[S_PRIV:%.+]],
+// CK1-DAG: [[BP]] = load [1 x i8*]*, [1 x i8*]** [[BP_PRIV:%[^,]+]],
+// CK1-DAG: [[P]] = load [1 x i8*]*, [1 x i8*]** [[P_PRIV:%[^,]+]],
+// CK1-DAG: [[S]] = load [1 x i[[sz]]]*, [1 x i[[sz]]]** [[S_PRIV:%[^,]+]],
// CK1-DAG: call void (i8*, ...) %{{.+}}(i8* %{{[^,]+}}, [1 x i8*]** [[BP_PRIV]], [1 x i8*]** [[P_PRIV]], [1 x i[[sz]]]** [[S_PRIV]])
// CK1: ret i32 0
// CK1: }
@@ -340,9 +349,9 @@ void foo(int arg) {
// CK1-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
// CK1-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
// CK1-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
-// CK1-DAG: [[BP]] = load [1 x i8*]*, [1 x i8*]** [[BP_PRIV:%.+]],
-// CK1-DAG: [[P]] = load [1 x i8*]*, [1 x i8*]** [[P_PRIV:%.+]],
-// CK1-DAG: [[S]] = load [1 x i[[sz]]]*, [1 x i[[sz]]]** [[S_PRIV:%.+]],
+// CK1-DAG: [[BP]] = load [1 x i8*]*, [1 x i8*]** [[BP_PRIV:%[^,]+]],
+// CK1-DAG: [[P]] = load [1 x i8*]*, [1 x i8*]** [[P_PRIV:%[^,]+]],
+// CK1-DAG: [[S]] = load [1 x i[[sz]]]*, [1 x i[[sz]]]** [[S_PRIV:%[^,]+]],
// CK1-DAG: call void (i8*, ...) %{{.+}}(i8* %{{[^,]+}}, [1 x i8*]** [[BP_PRIV]], [1 x i8*]** [[P_PRIV]], [1 x i[[sz]]]** [[S_PRIV]])
// CK1: ret i32 0
// CK1: }
@@ -353,9 +362,9 @@ void foo(int arg) {
// CK1-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
// CK1-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
-// CK1-DAG: [[BP]] = load [1 x i8*]*, [1 x i8*]** [[BP_PRIV:%.+]],
-// CK1-DAG: [[P]] = load [1 x i8*]*, [1 x i8*]** [[P_PRIV:%.+]],
-// CK1-DAG: [[S]] = load [1 x i[[sz]]]*, [1 x i[[sz]]]** [[S_PRIV:%.+]],
+// CK1-DAG: [[BP]] = load [1 x i8*]*, [1 x i8*]** [[BP_PRIV:%[^,]+]],
+// CK1-DAG: [[P]] = load [1 x i8*]*, [1 x i8*]** [[P_PRIV:%[^,]+]],
+// CK1-DAG: [[S]] = load [1 x i[[sz]]]*, [1 x i[[sz]]]** [[S_PRIV:%[^,]+]],
// CK1-DAG: call void (i8*, ...) %{{.+}}(i8* %{{[^,]+}}, [1 x i8*]** [[BP_PRIV]], [1 x i8*]** [[P_PRIV]], [1 x i[[sz]]]** [[S_PRIV]])
// CK1-NOT: __tgt_target_data_end
// CK1: ret i32 0
@@ -367,9 +376,9 @@ void foo(int arg) {
// CK1-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
// CK1-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
-// CK1-DAG: [[BP]] = load [2 x i8*]*, [2 x i8*]** [[BP_PRIV:%.+]],
-// CK1-DAG: [[P]] = load [2 x i8*]*, [2 x i8*]** [[P_PRIV:%.+]],
-// CK1-DAG: [[S]] = load [2 x i[[sz]]]*, [2 x i[[sz]]]** [[S_PRIV:%.+]],
+// CK1-DAG: [[BP]] = load [2 x i8*]*, [2 x i8*]** [[BP_PRIV:%[^,]+]],
+// CK1-DAG: [[P]] = load [2 x i8*]*, [2 x i8*]** [[P_PRIV:%[^,]+]],
+// CK1-DAG: [[S]] = load [2 x i[[sz]]]*, [2 x i[[sz]]]** [[S_PRIV:%[^,]+]],
// CK1-DAG: call void (i8*, ...) %{{.+}}(i8* %{{[^,]+}}, [2 x i8*]** [[BP_PRIV]], [2 x i8*]** [[P_PRIV]], [2 x i[[sz]]]** [[S_PRIV]])
// CK1-NOT: __tgt_target_data_end
// CK1: ret i32 0
diff --git a/test/OpenMP/target_update_depend_messages.cpp b/test/OpenMP/target_update_depend_messages.cpp
index 59e159e99fdb..d52f56684431 100644
--- a/test/OpenMP/target_update_depend_messages.cpp
+++ b/test/OpenMP/target_update_depend_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_update_device_messages.cpp b/test/OpenMP/target_update_device_messages.cpp
index 37112755805c..228b4a800a04 100644
--- a/test/OpenMP/target_update_device_messages.cpp
+++ b/test/OpenMP/target_update_device_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_update_from_messages.cpp b/test/OpenMP/target_update_from_messages.cpp
index c42bd12f75b8..e5a1f045e230 100644
--- a/test/OpenMP/target_update_from_messages.cpp
+++ b/test/OpenMP/target_update_from_messages.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s -Wno-openmp-target
void foo() {
}
diff --git a/test/OpenMP/target_update_if_messages.cpp b/test/OpenMP/target_update_if_messages.cpp
index 3d076a6389d1..4f229a768c7e 100644
--- a/test/OpenMP/target_update_if_messages.cpp
+++ b/test/OpenMP/target_update_if_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_update_messages.cpp b/test/OpenMP/target_update_messages.cpp
index 73f1eeca8efe..da71ff6a5a99 100644
--- a/test/OpenMP/target_update_messages.cpp
+++ b/test/OpenMP/target_update_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/target_update_nowait_messages.cpp b/test/OpenMP/target_update_nowait_messages.cpp
index 19bc58ea467e..fb3d035af9d3 100644
--- a/test/OpenMP/target_update_nowait_messages.cpp
+++ b/test/OpenMP/target_update_nowait_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
int main(int argc, char **argv) {
int i;
diff --git a/test/OpenMP/target_update_to_messages.cpp b/test/OpenMP/target_update_to_messages.cpp
index 9bde51e9839b..58f6aee234b3 100644
--- a/test/OpenMP/target_update_to_messages.cpp
+++ b/test/OpenMP/target_update_to_messages.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s -Wno-openmp-target
void foo() {
}
diff --git a/test/OpenMP/target_vla_messages.cpp b/test/OpenMP/target_vla_messages.cpp
index c970d0def661..b744081e9837 100644
--- a/test/OpenMP/target_vla_messages.cpp
+++ b/test/OpenMP/target_vla_messages.cpp
@@ -2,10 +2,15 @@
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-unknown-unknown -emit-llvm-bc %s -o %t-ppc-host-ppc.bc
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-unknown-unknown -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host-ppc.bc -o %t-ppc-device.ll
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-unknown-unknown -emit-llvm-bc %s -o %t-ppc-host-ppc.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-unknown-unknown -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host-ppc.bc -o %t-ppc-device.ll
+
// Nvidia GPUs don't support VLAs.
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host-nvptx.bc
// RUN: %clang_cc1 -verify -DNO_VLA -fopenmp -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host-nvptx.bc -o %t-nvptx-device.ll
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host-nvptx.bc
+
#ifndef NO_VLA
// expected-no-diagnostics
#endif
@@ -38,7 +43,7 @@ void declare_parallel_reduction(int arg) {
#pragma omp end declare target
template <typename T>
-void target_template(int arg) {
+void target_template(int arg) {
#pragma omp target
{
#ifdef NO_VLA
@@ -86,7 +91,7 @@ void teams_reduction(int arg) {
#pragma omp target map(vla)
#pragma omp teams reduction(+: vla)
{ }
-
+
#pragma omp target map(a[0:2])
#pragma omp teams reduction(+: a[0:2])
{ }
diff --git a/test/OpenMP/task_ast_print.cpp b/test/OpenMP/task_ast_print.cpp
index 54c05d8ed410..01ffda9f8760 100644
--- a/test/OpenMP/task_ast_print.cpp
+++ b/test/OpenMP/task_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -38,7 +42,7 @@ public:
};
// CHECK: #pragma omp taskgroup task_reduction(+: this->b)
-// CHECK: #pragma omp task private(this->a) private(this->a) private(T::a) in_reduction(+: this->b)
+// CHECK: #pragma omp task private(this->a) private(this->a) private(T::a) in_reduction(+: this->b){{$}}
// CHECK: #pragma omp task private(this->a) private(this->a)
// CHECK: #pragma omp task private(this->a) private(this->a) private(this->S1::a)
diff --git a/test/OpenMP/task_codegen.c b/test/OpenMP/task_codegen.c
index 579a6f1b9229..6669c7e73616 100644
--- a/test/OpenMP/task_codegen.c
+++ b/test/OpenMP/task_codegen.c
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -x c -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c -triple x86_64-apple-darwin10 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c -triple x86_64-apple-darwin10 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -x c -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c -triple x86_64-apple-darwin10 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/task_codegen.cpp b/test/OpenMP/task_codegen.cpp
index 4743ca3dc13c..fefe8b4329c2 100644
--- a/test/OpenMP/task_codegen.cpp
+++ b/test/OpenMP/task_codegen.cpp
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -x c++ -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -x c++ -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -33,7 +38,7 @@ int main() {
// CHECK: [[SHAREDS_REF_PTR:%.+]] = getelementptr inbounds [[KMP_TASK_T]], [[KMP_TASK_T]]* [[TASK_PTR:%.+]], i32 0, i32 0
// CHECK: [[SHAREDS_REF:%.+]] = load i8*, i8** [[SHAREDS_REF_PTR]]
// CHECK: [[BITCAST:%.+]] = bitcast [[STRUCT_SHAREDS]]* [[CAPTURES]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[SHAREDS_REF]], i8* [[BITCAST]], i64 16, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[SHAREDS_REF]], i8* align 8 [[BITCAST]], i64 16, i1 false)
// CHECK: [[PRIORITY_REF_PTR:%.+]] = getelementptr inbounds [[KMP_TASK_T]], [[KMP_TASK_T]]* [[TASK_PTR]], i32 0, i32 4
// CHECK: [[PRIORITY:%.+]] = bitcast %union{{.+}}* [[PRIORITY_REF_PTR]] to i32*
// CHECK: store i32 {{.+}}, i32* [[PRIORITY]]
@@ -50,7 +55,7 @@ int main() {
// CHECK: [[SHAREDS_REF_PTR:%.+]] = getelementptr inbounds [[KMP_TASK_T]], [[KMP_TASK_T]]* [[TASK_PTR:%.+]], i32 0, i32 0
// CHECK: [[SHAREDS_REF:%.+]] = load i8*, i8** [[SHAREDS_REF_PTR]]
// CHECK: [[BITCAST:%.+]] = bitcast [[STRUCT_SHAREDS1]]* [[CAPTURES]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[SHAREDS_REF]], i8* [[BITCAST]], i64 8, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[SHAREDS_REF]], i8* align 8 [[BITCAST]], i64 8, i1 false)
// CHECK: [[DEP:%.*]] = getelementptr inbounds [4 x [[KMP_DEPEND_INFO]]], [4 x [[KMP_DEPEND_INFO]]]* [[DEPENDENCIES:%.*]], i64 0, i64 0
// CHECK: [[T0:%.*]] = getelementptr inbounds [[KMP_DEPEND_INFO]], [[KMP_DEPEND_INFO]]* [[DEP]], i32 0, i32 0
// CHECK: store i64 ptrtoint (i32* @{{.+}} to i64), i64* [[T0]]
diff --git a/test/OpenMP/task_default_messages.cpp b/test/OpenMP/task_default_messages.cpp
index b3df295a8fa2..45bd8df82151 100644
--- a/test/OpenMP/task_default_messages.cpp
+++ b/test/OpenMP/task_default_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo();
int main(int argc, char **argv) {
diff --git a/test/OpenMP/task_depend_messages.cpp b/test/OpenMP/task_depend_messages.cpp
index 1e51b479dd96..469785e97cae 100644
--- a/test/OpenMP/task_depend_messages.cpp
+++ b/test/OpenMP/task_depend_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/task_final_messages.cpp b/test/OpenMP/task_final_messages.cpp
index a217ea2ef30e..49b9bfe204fd 100644
--- a/test/OpenMP/task_final_messages.cpp
+++ b/test/OpenMP/task_final_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/task_firstprivate_codegen.cpp b/test/OpenMP/task_firstprivate_codegen.cpp
index 7c15a18e7d40..09b1deabde40 100644
--- a/test/OpenMP/task_firstprivate_codegen.cpp
+++ b/test/OpenMP/task_firstprivate_codegen.cpp
@@ -4,6 +4,14 @@
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=ARRAY %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
// It doesn't pass on win32.
// REQUIRES: shell
@@ -199,7 +207,7 @@ int main() {
// CHECK: [[SHAREDS_REF_ADDR:%.+]] = getelementptr inbounds [[KMP_TASK_T_TY]], [[KMP_TASK_T_TY]]* [[TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[SHAREDS_REF:%.+]] = load i8*, i8** [[SHAREDS_REF_ADDR]],
// CHECK: [[CAPTURES_ADDR:%.+]] = bitcast [[CAP_MAIN_TY]]* %{{.+}} to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[SHAREDS_REF]], i8* [[CAPTURES_ADDR]], i64 40, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[SHAREDS_REF]], i8* align 8 [[CAPTURES_ADDR]], i64 40, i1 false)
// Initialize kmp_task_t->privates with default values (no init for simple types, default constructors for classes).
// Also copy address of private copy to the corresponding shareds reference.
@@ -353,7 +361,7 @@ int main() {
// CHECK: [[SHAREDS_REF_ADDR:%.+]] = getelementptr inbounds [[KMP_TASK_T_TY]], [[KMP_TASK_T_TY]]* [[TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[SHAREDS_REF:%.+]] = load i8*, i8** [[SHAREDS_REF_ADDR]],
// CHECK: [[CAPTURES_ADDR:%.+]] = bitcast [[CAP_TMAIN_TY]]* %{{.+}} to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[SHAREDS_REF]], i8* [[CAPTURES_ADDR]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[SHAREDS_REF]], i8* align 8 [[CAPTURES_ADDR]], i64 32, i1 false)
// Initialize kmp_task_t->privates with default values (no init for simple types, default constructors for classes).
// CHECK: [[PRIVATES:%.+]] = getelementptr inbounds [[KMP_TASK_TMAIN_TY]], [[KMP_TASK_TMAIN_TY]]* [[RES_KMP_TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 2
diff --git a/test/OpenMP/task_firstprivate_messages.cpp b/test/OpenMP/task_firstprivate_messages.cpp
index 11d8c5789879..1a64f2abf3c6 100644
--- a/test/OpenMP/task_firstprivate_messages.cpp
+++ b/test/OpenMP/task_firstprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/task_if_codegen.cpp b/test/OpenMP/task_if_codegen.cpp
index 5952085b6ec1..6f02942905b4 100644
--- a/test/OpenMP/task_if_codegen.cpp
+++ b/test/OpenMP/task_if_codegen.cpp
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/task_if_messages.cpp b/test/OpenMP/task_if_messages.cpp
index 89b10f71d3d9..fca57bb05d0d 100644
--- a/test/OpenMP/task_if_messages.cpp
+++ b/test/OpenMP/task_if_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/task_in_reduction_codegen.cpp b/test/OpenMP/task_in_reduction_codegen.cpp
index 2ad013a14a57..e96d12689fb1 100644
--- a/test/OpenMP/task_in_reduction_codegen.cpp
+++ b/test/OpenMP/task_in_reduction_codegen.cpp
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -x c++ -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -x c++ -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -33,18 +38,18 @@ int main(int argc, char **argv) {
}
// CHECK-LABEL: @main
-// CHECK: void @__kmpc_taskgroup(%ident_t* @0, i32 [[GTID:%.+]])
+// CHECK: void @__kmpc_taskgroup(%struct.ident_t* @0, i32 [[GTID:%.+]])
// CHECK: [[TD1:%.+]] = call i8* @__kmpc_task_reduction_init(i32 [[GTID]], i32 3, i8* %
// CHECK-NEXT: store i8* [[TD1]], i8** [[TD1_ADDR:%[^,]+]],
-// CHECK-NEXT: call void @__kmpc_taskgroup(%ident_t* @0, i32 [[GTID]])
+// CHECK-NEXT: call void @__kmpc_taskgroup(%struct.ident_t* @0, i32 [[GTID]])
// CHECK: [[TD2:%.+]] = call i8* @__kmpc_task_reduction_init(i32 [[GTID]], i32 2, i8* %
// CHECK-NEXT: store i8* [[TD2]], i8** [[TD2_ADDR:%[^,]+]],
-// CHECK-NEXT: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* @0, i32 5, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, i64, i16*, i8**, i8**)* [[OMP_PARALLEL:@.+]] to void (i32*, i32*, ...)*), i32* %{{.+}}, i64 %{{.+}}, i16* %{{.+}}, i8** [[TD1_ADDR]], i8** [[TD2_ADDR]])
-// CHECK-NEXT: call void @__kmpc_end_taskgroup(%ident_t* @0, i32 [[GTID]])
-// CHECK-NEXT: call void @__kmpc_end_taskgroup(%ident_t* @0, i32 [[GTID]])
+// CHECK-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @0, i32 5, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, i64, i16*, i8**, i8**)* [[OMP_PARALLEL:@.+]] to void (i32*, i32*, ...)*), i32* %{{.+}}, i64 %{{.+}}, i16* %{{.+}}, i8** [[TD1_ADDR]], i8** [[TD2_ADDR]])
+// CHECK-NEXT: call void @__kmpc_end_taskgroup(%struct.ident_t* @0, i32 [[GTID]])
+// CHECK-NEXT: call void @__kmpc_end_taskgroup(%struct.ident_t* @0, i32 [[GTID]])
// CHECK: define internal void [[OMP_PARALLEL]](
-// CHECK: [[TASK_T:%.+]] = call i8* @__kmpc_omp_task_alloc(%ident_t* @0, i32 [[GTID:%.+]], i32 1, i64 56, i64 40, i32 (i32, i8*)* bitcast (i32 (i32, [[T:%.+]]*)* [[OMP_TASK:@.+]] to i32 (i32, i8*)*))
+// CHECK: [[TASK_T:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* @0, i32 [[GTID:%.+]], i32 1, i64 56, i64 40, i32 (i32, i8*)* bitcast (i32 (i32, [[T:%.+]]*)* [[OMP_TASK:@.+]] to i32 (i32, i8*)*))
// CHECK-NEXT: [[TASK_T_WITH_PRIVS:%.+]] = bitcast i8* [[TASK_T]] to [[T]]*
// CHECK: [[PRIVS:%.+]] = getelementptr inbounds [[T]], [[T]]* [[TASK_T_WITH_PRIVS]], i32 0, i32 1
// CHECK: [[TD1_REF:%.+]] = getelementptr inbounds [[PRIVATES]], [[PRIVATES]]* [[PRIVS]], i32 0, i32 0
@@ -57,7 +62,7 @@ int main(int argc, char **argv) {
// CHECK-NEXT: [[TD2_ADDR:%.+]] = load i8**, i8*** [[TD2_SHAR]],
// CHECK-NEXT: [[TD2:%.+]] = load i8*, i8** [[TD2_ADDR]],
// CHECK-NEXT: store i8* [[TD2]], i8** [[TD2_REF]],
-// CHECK-NEXT: call i32 @__kmpc_omp_task(%ident_t* @0, i32 [[GTID]], i8* [[TASK_T]])
+// CHECK-NEXT: call i32 @__kmpc_omp_task(%struct.ident_t* @0, i32 [[GTID]], i8* [[TASK_T]])
// CHECK-NEXT: ret void
// CHECK-NEXT: }
@@ -73,9 +78,11 @@ int main(int argc, char **argv) {
// CHECK-NEXT: call i8* @__kmpc_task_reduction_get_th_data(i32 [[GTID]], i8* [[TD1]], i8* [[A_PTR]])
// CHECK: [[D_REF:%.+]] = getelementptr inbounds %
// CHECK-NEXT: [[D_ADDR:%.+]] = load i16*, i16** [[D_REF]],
+// CHECK: call i8* @__kmpc_threadprivate_cached(
// CHECK: [[TD2:%.+]] = load i8*, i8** [[TD2_ADDR]],
// CHECK-NEXT: [[D_PTR:%.+]] = bitcast i16* [[D_ADDR]] to i8*
// CHECK-NEXT: call i8* @__kmpc_task_reduction_get_th_data(i32 [[GTID]], i8* [[TD2]], i8* [[D_PTR]])
// CHECK: add nsw i32
// CHECK: store i32 %
+// CHECK-NOT: call i8* @__kmpc_threadprivate_cached(
#endif
diff --git a/test/OpenMP/task_in_reduction_message.cpp b/test/OpenMP/task_in_reduction_message.cpp
index e176dc9305b3..d99d2e42d762 100644
--- a/test/OpenMP/task_in_reduction_message.cpp
+++ b/test/OpenMP/task_in_reduction_message.cpp
@@ -2,6 +2,11 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 150 -o - %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 150 -o - %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
void foo() {
}
diff --git a/test/OpenMP/task_messages.cpp b/test/OpenMP/task_messages.cpp
index f42a37ae1daa..832d8fa57d67 100644
--- a/test/OpenMP/task_messages.cpp
+++ b/test/OpenMP/task_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -std=c++11 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -std=c++11 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/task_priority_messages.cpp b/test/OpenMP/task_priority_messages.cpp
index 8a5553eb08c5..2e184ce1a911 100644
--- a/test/OpenMP/task_priority_messages.cpp
+++ b/test/OpenMP/task_priority_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/task_private_codegen.cpp b/test/OpenMP/task_private_codegen.cpp
index 021749912a05..1484c6f7e376 100644
--- a/test/OpenMP/task_private_codegen.cpp
+++ b/test/OpenMP/task_private_codegen.cpp
@@ -4,6 +4,14 @@
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=ARRAY %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
// It doesn't pass on win32. Investigating.
// REQUIRES: shell
diff --git a/test/OpenMP/task_private_messages.cpp b/test/OpenMP/task_private_messages.cpp
index 6bce1352b13e..5663a436e43f 100644
--- a/test/OpenMP/task_private_messages.cpp
+++ b/test/OpenMP/task_private_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/task_shared_messages.cpp b/test/OpenMP/task_shared_messages.cpp
index bf3b8ba28373..bdd46ab42825 100644
--- a/test/OpenMP/task_shared_messages.cpp
+++ b/test/OpenMP/task_shared_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/taskgroup_ast_print.cpp b/test/OpenMP/taskgroup_ast_print.cpp
index 4292eedfb56e..a15600cb779b 100644
--- a/test/OpenMP/taskgroup_ast_print.cpp
+++ b/test/OpenMP/taskgroup_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -70,7 +74,7 @@ int main (int argc, char **argv) {
// CHECK: static int a;
#pragma omp taskgroup
a=2;
-// CHECK-NEXT: #pragma omp taskgroup
+// CHECK-NEXT: #pragma omp taskgroup{{$}}
// CHECK-NEXT: a = 2;
// CHECK-NEXT: ++a;
++a;
diff --git a/test/OpenMP/taskgroup_codegen.cpp b/test/OpenMP/taskgroup_codegen.cpp
index 4b7d89e70391..f672ab17fd59 100644
--- a/test/OpenMP/taskgroup_codegen.cpp
+++ b/test/OpenMP/taskgroup_codegen.cpp
@@ -2,6 +2,12 @@
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck %s --check-prefix=TERM_DEBUG
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/taskgroup_messages.cpp b/test/OpenMP/taskgroup_messages.cpp
index 23820734a551..dfb4725280bb 100644
--- a/test/OpenMP/taskgroup_messages.cpp
+++ b/test/OpenMP/taskgroup_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
int foo();
int main() {
diff --git a/test/OpenMP/taskgroup_task_reduction_codegen.cpp b/test/OpenMP/taskgroup_task_reduction_codegen.cpp
index 63e015182420..90b03c653ef0 100644
--- a/test/OpenMP/taskgroup_task_reduction_codegen.cpp
+++ b/test/OpenMP/taskgroup_task_reduction_codegen.cpp
@@ -2,10 +2,19 @@
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ %s -verify -debug-info-kind=limited -emit-llvm -o - -triple x86_64-apple-darwin10 | FileCheck %s --check-prefix=CHECK --check-prefix=DEBUG
+
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -x c++ -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ %s -verify -debug-info-kind=limited -emit-llvm -o - -triple x86_64-apple-darwin10 | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
+// CHECK-DAG: @reduction_size.[[ID:.+]]_[[CID:[0-9]+]].artificial.
+// CHECK-DAG: @reduction_size.[[ID]]_[[CID]].artificial..cache.
+
struct S {
int a;
S() : a(0) {}
@@ -15,7 +24,6 @@ struct S {
friend S operator+(const S&a, const S&b) {return a;}
};
-
int main(int argc, char **argv) {
int a;
float b;
@@ -35,7 +43,7 @@ int main(int argc, char **argv) {
// CHECK: [[A:%.+]] = alloca i32,
// CHECK: [[B:%.+]] = alloca float,
// CHECK: [[C:%.+]] = alloca [5 x %struct.S],
-// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num(%ident_t*
+// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num(%struct.ident_t*
// CHECK: [[RD_IN1:%.+]] = alloca [3 x [[T1:%[^,]+]]],
// CHECK: [[TD1:%.+]] = alloca i8*,
// CHECK: [[RD_IN2:%.+]] = alloca [2 x [[T2:%[^,]+]]],
@@ -43,7 +51,7 @@ int main(int argc, char **argv) {
// CHECK: [[VLA:%.+]] = alloca i16, i64 [[VLA_SIZE:%[^,]+]],
-// CHECK: call void @__kmpc_taskgroup(%ident_t* {{[^,]+}}, i32 [[GTID]])
+// CHECK: call void @__kmpc_taskgroup(%struct.ident_t* {{[^,]+}}, i32 [[GTID]])
// CHECK-DAG: [[BC_A:%.+]] = bitcast i32* [[A]] to i8*
// CHECK-DAG: store i8* [[BC_A]], i8** [[A_REF:[^,]+]],
// CHECK-DAG: [[A_REF]] = getelementptr inbounds [[T1]], [[T1]]* [[GEPA:%[^,]+]], i32 0, i32 0
@@ -51,14 +59,14 @@ int main(int argc, char **argv) {
// CHECK-DAG: [[TMP6:%.+]] = getelementptr inbounds [[T1]], [[T1]]* [[GEPA]], i32 0, i32 1
// CHECK-DAG: store i64 4, i64* [[TMP6]],
// CHECK-DAG: [[TMP7:%.+]] = getelementptr inbounds [[T1]], [[T1]]* [[GEPA]], i32 0, i32 2
-// CHECK-DAG: store i8* bitcast (void (i8*)* [[AINIT:@.+]] to i8*), i8** [[TMP7]],
+// CHECK-DAG: store i8* bitcast (void (i8*)* @[[AINIT:.+]] to i8*), i8** [[TMP7]],
// CHECK-DAG: [[TMP8:%.+]] = getelementptr inbounds [[T1]], [[T1]]* [[GEPA]], i32 0, i32 3
// CHECK-DAG: store i8* null, i8** [[TMP8]],
// CHECK-DAG: [[TMP9:%.+]] = getelementptr inbounds [[T1]], [[T1]]* [[GEPA]], i32 0, i32 4
-// CHECK-DAG: store i8* bitcast (void (i8*, i8*)* [[ACOMB:@.+]] to i8*), i8** [[TMP9]],
+// CHECK-DAG: store i8* bitcast (void (i8*, i8*)* @[[ACOMB:.+]] to i8*), i8** [[TMP9]],
// CHECK-DAG: [[TMP10:%.+]] = getelementptr inbounds [[T1]], [[T1]]* [[GEPA]], i32 0, i32 5
// CHECK-DAG: [[TMP11:%.+]] = bitcast i32* [[TMP10]] to i8*
-// CHECK-DAG: call void @llvm.memset.p0i8.i64(i8* [[TMP11]], i8 0, i64 4, i32 8, i1 false)
+// CHECK-DAG: call void @llvm.memset.p0i8.i64(i8* align 8 [[TMP11]], i8 0, i64 4, i1 false)
// CHECK-DAG: [[TMP13:%.+]] = bitcast float* [[B]] to i8*
// CHECK-DAG: store i8* [[TMP13]], i8** [[TMP12:%[^,]+]],
// CHECK-DAG: [[TMP12]] = getelementptr inbounds [[T1]], [[T1]]* [[GEPB:%[^,]+]], i32 0, i32 0
@@ -66,14 +74,14 @@ int main(int argc, char **argv) {
// CHECK-DAG: [[TMP14:%.+]] = getelementptr inbounds [[T1]], [[T1]]* [[GEPB]], i32 0, i32 1
// CHECK-DAG: store i64 4, i64* [[TMP14]],
// CHECK-DAG: [[TMP15:%.+]] = getelementptr inbounds [[T1]], [[T1]]* [[GEPB]], i32 0, i32 2
-// CHECK-DAG: store i8* bitcast (void (i8*)* [[BINIT:@.+]] to i8*), i8** [[TMP15]],
+// CHECK-DAG: store i8* bitcast (void (i8*)* @[[BINIT:.+]] to i8*), i8** [[TMP15]],
// CHECK-DAG: [[TMP16:%.+]] = getelementptr inbounds [[T1]], [[T1]]* [[GEPB]], i32 0, i32 3
// CHECK-DAG: store i8* null, i8** [[TMP16]],
// CHECK-DAG: [[TMP17:%.+]] = getelementptr inbounds [[T1]], [[T1]]* [[GEPB]], i32 0, i32 4
-// CHECK-DAG: store i8* bitcast (void (i8*, i8*)* [[BCOMB:@.+]] to i8*), i8** [[TMP17]],
+// CHECK-DAG: store i8* bitcast (void (i8*, i8*)* @[[BCOMB:.+]] to i8*), i8** [[TMP17]],
// CHECK-DAG: [[TMP18:%.+]] = getelementptr inbounds [[T1]], [[T1]]* [[GEPB]], i32 0, i32 5
// CHECK-DAG: [[TMP19:%.+]] = bitcast i32* [[TMP18]] to i8*
-// CHECK-DAG: call void @llvm.memset.p0i8.i64(i8* [[TMP19]], i8 0, i64 4, i32 8, i1 false)
+// CHECK-DAG: call void @llvm.memset.p0i8.i64(i8* align 8 [[TMP19]], i8 0, i64 4, i1 false)
// CHECK-DAG: [[TMP21:%.+]] = bitcast i32* [[ARGC_ADDR]] to i8*
// CHECK-DAG: store i8* [[TMP21]], i8** [[TMP20:%[^,]+]],
// CHECK-DAG: [[TMP20]] = getelementptr inbounds [[T1]], [[T1]]* [[GEPARGC:%[^,]+]], i32 0, i32 0
@@ -81,19 +89,19 @@ int main(int argc, char **argv) {
// CHECK-DAG: [[TMP22:%.+]] = getelementptr inbounds [[T1]], [[T1]]* [[GEPARGC]], i32 0, i32 1
// CHECK-DAG: store i64 4, i64* [[TMP22]],
// CHECK-DAG: [[TMP23:%.+]] = getelementptr inbounds [[T1]], [[T1]]* [[GEPARGC]], i32 0, i32 2
-// CHECK-DAG: store i8* bitcast (void (i8*)* [[ARGCINIT:@.+]] to i8*), i8** [[TMP23]],
+// CHECK-DAG: store i8* bitcast (void (i8*)* @[[ARGCINIT:.+]] to i8*), i8** [[TMP23]],
// CHECK-DAG: [[TMP24:%.+]] = getelementptr inbounds [[T1]], [[T1]]* [[GEPARGC]], i32 0, i32 3
// CHECK-DAG: store i8* null, i8** [[TMP24]],
// CHECK-DAG: [[TMP25:%.+]] = getelementptr inbounds [[T1]], [[T1]]* [[GEPARGC]], i32 0, i32 4
-// CHECK-DAG: store i8* bitcast (void (i8*, i8*)* [[ARGCCOMB:@.+]] to i8*), i8** [[TMP25]],
+// CHECK-DAG: store i8* bitcast (void (i8*, i8*)* @[[ARGCCOMB:.+]] to i8*), i8** [[TMP25]],
// CHECK-DAG: [[TMP26:%.+]] = getelementptr inbounds [[T1]], [[T1]]* [[GEPARGC]], i32 0, i32 5
// CHECK-DAG: [[TMP27:%.+]] = bitcast i32* [[TMP26]] to i8*
-// CHECK-DAG: call void @llvm.memset.p0i8.i64(i8* [[TMP27]], i8 0, i64 4, i32 8, i1 false)
+// CHECK-DAG: call void @llvm.memset.p0i8.i64(i8* align 8 [[TMP27]], i8 0, i64 4, i1 false)
// CHECK-DAG: [[TMP28:%.+]] = bitcast [3 x [[T1]]]* [[RD_IN1]] to i8*
// CHECK-DAG: [[TMP29:%.+]] = call i8* @__kmpc_task_reduction_init(i32 [[GTID]], i32 3, i8* [[TMP28]])
// DEBUG-DAG: call void @llvm.dbg.declare(metadata i8** [[TD1]],
// CHECK-DAG: store i8* [[TMP29]], i8** [[TD1]],
-// CHECK-DAG: call void @__kmpc_taskgroup(%ident_t* {{[^,]+}}, i32 [[GTID]])
+// CHECK-DAG: call void @__kmpc_taskgroup(%struct.ident_t* {{[^,]+}}, i32 [[GTID]])
// CHECK-DAG: [[TMP31:%.+]] = bitcast [5 x %struct.S]* [[C]] to i8*
// CHECK-DAG: store i8* [[TMP31]], i8** [[TMP30:%[^,]+]],
// CHECK-DAG: [[TMP30]] = getelementptr inbounds [[T2]], [[T2]]* [[GEPC:%[^,]+]], i32 0, i32 0
@@ -101,14 +109,14 @@ int main(int argc, char **argv) {
// CHECK-DAG: [[TMP32:%.+]] = getelementptr inbounds [[T2]], [[T2]]* [[GEPC]], i32 0, i32 1
// CHECK-DAG: store i64 20, i64* [[TMP32]],
// CHECK-DAG: [[TMP33:%.+]] = getelementptr inbounds [[T2]], [[T2]]* [[GEPC]], i32 0, i32 2
-// CHECK-DAG: store i8* bitcast (void (i8*)* [[CINIT:@.+]] to i8*), i8** [[TMP33]],
+// CHECK-DAG: store i8* bitcast (void (i8*)* @[[CINIT:.+]] to i8*), i8** [[TMP33]],
// CHECK-DAG: [[TMP34:%.+]] = getelementptr inbounds [[T2]], [[T2]]* [[GEPC]], i32 0, i32 3
-// CHECK-DAG: store i8* bitcast (void (i8*)* [[CFINI:@.+]] to i8*), i8** [[TMP34]],
+// CHECK-DAG: store i8* bitcast (void (i8*)* @[[CFINI:.+]] to i8*), i8** [[TMP34]],
// CHECK-DAG: [[TMP35:%.+]] = getelementptr inbounds [[T2]], [[T2]]* [[GEPC]], i32 0, i32 4
-// CHECK-DAG: store i8* bitcast (void (i8*, i8*)* [[CCOMB:@.+]] to i8*), i8** [[TMP35]],
+// CHECK-DAG: store i8* bitcast (void (i8*, i8*)* @[[CCOMB:.+]] to i8*), i8** [[TMP35]],
// CHECK-DAG: [[TMP36:%.+]] = getelementptr inbounds [[T2]], [[T2]]* [[GEPC]], i32 0, i32 5
// CHECK-DAG: [[TMP37:%.+]] = bitcast i32* [[TMP36]] to i8*
-// CHECK-DAG: call void @llvm.memset.p0i8.i64(i8* [[TMP37]], i8 0, i64 4, i32 8, i1 false)
+// CHECK-DAG: call void @llvm.memset.p0i8.i64(i8* align 8 [[TMP37]], i8 0, i64 4, i1 false)
// CHECK-DAG: [[TMP39:%.+]] = bitcast i16* [[VLA]] to i8*
// CHECK-DAG: store i8* [[TMP39]], i8** [[TMP38:%[^,]+]],
// CHECK-DAG: [[TMP38]] = getelementptr inbounds [[T2]], [[T2]]* [[GEPVLA:%[^,]+]], i32 0, i32 0
@@ -118,67 +126,67 @@ int main(int argc, char **argv) {
// CHECK-DAG: [[TMP42:%.+]] = getelementptr inbounds [[T2]], [[T2]]* [[GEPVLA]], i32 0, i32 1
// CHECK-DAG: store i64 [[TMP40]], i64* [[TMP42]],
// CHECK-DAG: [[TMP43:%.+]] = getelementptr inbounds [[T2]], [[T2]]* [[GEPVLA]], i32 0, i32 2
-// CHECK-DAG: store i8* bitcast (void (i8*)* [[VLAINIT:@.+]] to i8*), i8** [[TMP43]],
+// CHECK-DAG: store i8* bitcast (void (i8*)* @[[VLAINIT:.+]] to i8*), i8** [[TMP43]],
// CHECK-DAG: [[TMP44:%.+]] = getelementptr inbounds [[T2]], [[T2]]* [[GEPVLA]], i32 0, i32 3
// CHECK-DAG: store i8* null, i8** [[TMP44]],
// CHECK-DAG: [[TMP45:%.+]] = getelementptr inbounds [[T2]], [[T2]]* [[GEPVLA]], i32 0, i32 4
-// CHECK-DAG: store i8* bitcast (void (i8*, i8*)* [[VLACOMB:@.+]] to i8*), i8** [[TMP45]],
+// CHECK-DAG: store i8* bitcast (void (i8*, i8*)* @[[VLACOMB:.+]] to i8*), i8** [[TMP45]],
// CHECK-DAG: [[TMP46:%.+]] = getelementptr inbounds [[T2]], [[T2]]* [[GEPVLA]], i32 0, i32 5
// CHECK-DAG: store i32 1, i32* [[TMP46]],
// CHECK: [[TMP47:%.+]] = bitcast [2 x [[T2]]]* [[RD_IN2]] to i8*
// CHECK: [[TMP48:%.+]] = call i8* @__kmpc_task_reduction_init(i32 [[GTID]], i32 2, i8* [[TMP47]])
// CHECK: store i8* [[TMP48]], i8** [[TD2]],
-// CHECK: call void @__kmpc_end_taskgroup(%ident_t* {{[^,]+}}, i32 [[GTID]])
-// CHECK: call void @__kmpc_end_taskgroup(%ident_t* {{[^,]+}}, i32 [[GTID]])
+// CHECK: call void @__kmpc_end_taskgroup(%struct.ident_t* {{[^,]+}}, i32 [[GTID]])
+// CHECK: call void @__kmpc_end_taskgroup(%struct.ident_t* {{[^,]+}}, i32 [[GTID]])
-// CHECK-DAG: define internal void [[AINIT]](i8*)
+// CHECK-DAG: define internal void @[[AINIT]](i8*)
// CHECK-DAG: store i32 0, i32* %
// CHECK-DAG: ret void
// CHECK-DAG: }
-// CHECK-DAG: define internal void [[ACOMB]](i8*, i8*)
+// CHECK-DAG: define internal void @[[ACOMB]](i8*, i8*)
// CHECK-DAG: add nsw i32 %
// CHECK-DAG: store i32 %
// CHECK-DAG: ret void
// CHECK-DAG: }
-// CHECK-DAG: define internal void [[BINIT]](i8*)
+// CHECK-DAG: define internal void @[[BINIT]](i8*)
// CHECK-DAG: store float 0.000000e+00, float* %
// CHECK-DAG: ret void
// CHECK-DAG: }
-// CHECK-DAG: define internal void [[BCOMB]](i8*, i8*)
+// CHECK-DAG: define internal void @[[BCOMB]](i8*, i8*)
// CHECK-DAG: fadd float %
// CHECK-DAG: store float %
// CHECK-DAG: ret void
// CHECK-DAG: }
-// CHECK-DAG: define internal void [[ARGCINIT]](i8*)
+// CHECK-DAG: define internal void @[[ARGCINIT]](i8*)
// CHECK-DAG: store i32 0, i32* %
// CHECK-DAG: ret void
// CHECK-DAG: }
-// CHECK-DAG: define internal void [[ARGCCOMB]](i8*, i8*)
+// CHECK-DAG: define internal void @[[ARGCCOMB]](i8*, i8*)
// CHECK-DAG: add nsw i32 %
// CHECK-DAG: store i32 %
// CHECK-DAG: ret void
// CHECK-DAG: }
-// CHECK-DAG: define internal void [[CINIT]](i8*)
+// CHECK-DAG: define internal void @[[CINIT]](i8*)
// CHECK-DAG: phi %struct.S* [
// CHECK-DAG: call {{.+}}(%struct.S* {{.+}})
// CHECK-DAG: br i1 %
// CHECK-DAG: ret void
// CHECK-DAG: }
-// CHECK-DAG: define internal void [[CFINI]](i8*)
+// CHECK-DAG: define internal void @[[CFINI]](i8*)
// CHECK-DAG: phi %struct.S* [
// CHECK-DAG: call {{.+}}(%struct.S* {{.+}})
// CHECK-DAG: br i1 %
// CHECK-DAG: ret void
// CHECK-DAG: }
-// CHECK-DAG: define internal void [[CCOMB]](i8*, i8*)
+// CHECK-DAG: define internal void @[[CCOMB]](i8*, i8*)
// CHECK-DAG: phi %struct.S* [
// CHECK-DAG: phi %struct.S* [
// CHECK-DAG: call {{.+}}(%struct.S* {{.+}}, %struct.S* {{.+}}, %struct.S* {{.+}})
@@ -188,18 +196,18 @@ int main(int argc, char **argv) {
// CHECK-DAG: ret void
// CHECK_DAG: }
-// CHECK-DAG: define internal void [[VLAINIT]](i8*)
-// CHECK-DAG: call i32 @__kmpc_global_thread_num(%ident_t* {{[^,]+}})
-// CHECK-DAG: call i8* @__kmpc_threadprivate_cached(%ident_t*
+// CHECK-DAG: define internal void @[[VLAINIT]](i8*)
+// CHECK-DAG: call i32 @__kmpc_global_thread_num(%struct.ident_t* {{[^,]+}})
+// CHECK-DAG: call i8* @__kmpc_threadprivate_cached(%struct.ident_t*
// CHECK-DAG: phi i16* [
// CHECK-DAG: store i16 0, i16* %
// CHECK-DAG: br i1 %
// CHECK-DAG: ret void
// CHECK-DAG: }
-// CHECK-DAG: define internal void [[VLACOMB]](i8*, i8*)
-// CHECK-DAG: call i32 @__kmpc_global_thread_num(%ident_t* {{[^,]+}})
-// CHECK-DAG: call i8* @__kmpc_threadprivate_cached(%ident_t*
+// CHECK-DAG: define internal void @[[VLACOMB]](i8*, i8*)
+// CHECK-DAG: call i32 @__kmpc_global_thread_num(%struct.ident_t* {{[^,]+}})
+// CHECK-DAG: call i8* @__kmpc_threadprivate_cached(%struct.ident_t*
// CHECK-DAG: phi i16* [
// CHECK-DAG: phi i16* [
// CHECK-DAG: sext i16 %{{.+}} to i32
@@ -210,3 +218,16 @@ int main(int argc, char **argv) {
// CHECK-DAG: ret void
// CHECK-DAG: }
#endif
+
+// DEBUG-LABEL: distinct !DICompileUnit
+// DEBUG-DAG: distinct !DISubprogram(linkageName: "[[AINIT]]",
+// DEBUG-DAG: distinct !DISubprogram(linkageName: "[[ACOMB]]",
+// DEBUG-DAG: distinct !DISubprogram(linkageName: "[[BINIT]]",
+// DEBUG-DAG: distinct !DISubprogram(linkageName: "[[BCOMB]]",
+// DEBUG-DAG: distinct !DISubprogram(linkageName: "[[ARGCINIT]]",
+// DEBUG-DAG: distinct !DISubprogram(linkageName: "[[ARGCCOMB]]",
+// DEBUG-DAG: distinct !DISubprogram(linkageName: "[[CINIT]]",
+// DEBUG-DAG: distinct !DISubprogram(linkageName: "[[CFINI]]",
+// DEBUG-DAG: distinct !DISubprogram(linkageName: "[[CCOMB]]",
+// DEBUG-DAG: distinct !DISubprogram(linkageName: "[[VLAINIT]]",
+// DEBUG-DAG: distinct !DISubprogram(linkageName: "[[VLACOMB]]",
diff --git a/test/OpenMP/taskgroup_task_reduction_messages.cpp b/test/OpenMP/taskgroup_task_reduction_messages.cpp
index 819dc5bdaf68..59ff2190bb9e 100644
--- a/test/OpenMP/taskgroup_task_reduction_messages.cpp
+++ b/test/OpenMP/taskgroup_task_reduction_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 150 -o - %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 150 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/taskloop_ast_print.cpp b/test/OpenMP/taskloop_ast_print.cpp
index 891b31dce4db..97f797b7c986 100644
--- a/test/OpenMP/taskloop_ast_print.cpp
+++ b/test/OpenMP/taskloop_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -16,7 +20,7 @@ T tmain(T argc) {
#pragma omp taskgroup task_reduction(+: d)
#pragma omp taskloop if(taskloop: argc > N) default(shared) untied priority(N) grainsize(N) reduction(+:g) in_reduction(+: d)
// CHECK-NEXT: #pragma omp taskgroup task_reduction(+: d)
- // CHECK-NEXT: #pragma omp taskloop if(taskloop: argc > N) default(shared) untied priority(N) grainsize(N) reduction(+: g) in_reduction(+: d)
+ // CHECK-NEXT: #pragma omp taskloop if(taskloop: argc > N) default(shared) untied priority(N) grainsize(N) reduction(+: g) in_reduction(+: d){{$}}
for (int i = 0; i < 2; ++i)
a = 2;
// CHECK-NEXT: for (int i = 0; i < 2; ++i)
diff --git a/test/OpenMP/taskloop_codegen.cpp b/test/OpenMP/taskloop_codegen.cpp
index 94cf5365d872..82b8e1b292bd 100644
--- a/test/OpenMP/taskloop_codegen.cpp
+++ b/test/OpenMP/taskloop_codegen.cpp
@@ -1,19 +1,24 @@
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -x c++ -emit-llvm %s -o - -femit-all-decls | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -include-pch %t -verify %s -emit-llvm -o - -femit-all-decls | FileCheck %s
+
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -x c++ -emit-llvm %s -o - -femit-all-decls | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -include-pch %t -verify %s -emit-llvm -o - -femit-all-decls | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
// CHECK-LABEL: @main
int main(int argc, char **argv) {
-// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num(%ident_t* [[DEFLOC:@.+]])
-// CHECK: call i8* @__kmpc_omp_task_alloc(%ident_t* [[DEFLOC]], i32 [[GTID]],
-// CHECK: call i32 @__kmpc_omp_task(%ident_t* [[DEFLOC]], i32 [[GTID]],
+// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[DEFLOC:@.+]])
+// CHECK: call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[DEFLOC]], i32 [[GTID]],
+// CHECK: call i32 @__kmpc_omp_task(%struct.ident_t* [[DEFLOC]], i32 [[GTID]],
#pragma omp task
;
-// CHECK: call void @__kmpc_taskgroup(%ident_t* [[DEFLOC]], i32 [[GTID]])
-// CHECK: [[TASKV:%.+]] = call i8* @__kmpc_omp_task_alloc(%ident_t* [[DEFLOC]], i32 [[GTID]], i32 33, i64 80, i64 1, i32 (i32, i8*)* bitcast (i32 (i32, [[TDP_TY:%.+]]*)* [[TASK1:@.+]] to i32 (i32, i8*)*))
+// CHECK: call void @__kmpc_taskgroup(%struct.ident_t* [[DEFLOC]], i32 [[GTID]])
+// CHECK: [[TASKV:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i32 33, i64 80, i64 1, i32 (i32, i8*)* bitcast (i32 (i32, [[TDP_TY:%.+]]*)* [[TASK1:@.+]] to i32 (i32, i8*)*))
// CHECK: [[TASK:%.+]] = bitcast i8* [[TASKV]] to [[TDP_TY]]*
// CHECK: [[TASK_DATA:%.+]] = getelementptr inbounds [[TDP_TY]], [[TDP_TY]]* [[TASK]], i32 0, i32 0
// CHECK: [[DOWN:%.+]] = getelementptr inbounds [[TD_TY:%.+]], [[TD_TY]]* [[TASK_DATA]], i32 0, i32 5
@@ -23,12 +28,12 @@ int main(int argc, char **argv) {
// CHECK: [[ST:%.+]] = getelementptr inbounds [[TD_TY]], [[TD_TY]]* [[TASK_DATA]], i32 0, i32 7
// CHECK: store i64 1, i64* [[ST]],
// CHECK: [[ST_VAL:%.+]] = load i64, i64* [[ST]],
-// CHECK: call void @__kmpc_taskloop(%ident_t* [[DEFLOC]], i32 [[GTID]], i8* [[TASKV]], i32 1, i64* [[DOWN]], i64* [[UP]], i64 [[ST_VAL]], i32 0, i32 0, i64 0, i8* null)
-// CHECK: call void @__kmpc_end_taskgroup(%ident_t* [[DEFLOC]], i32 [[GTID]])
+// CHECK: call void @__kmpc_taskloop(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i8* [[TASKV]], i32 1, i64* [[DOWN]], i64* [[UP]], i64 [[ST_VAL]], i32 0, i32 0, i64 0, i8* null)
+// CHECK: call void @__kmpc_end_taskgroup(%struct.ident_t* [[DEFLOC]], i32 [[GTID]])
#pragma omp taskloop priority(argc)
for (int i = 0; i < 10; ++i)
;
-// CHECK: [[TASKV:%.+]] = call i8* @__kmpc_omp_task_alloc(%ident_t* [[DEFLOC]], i32 [[GTID]], i32 1, i64 80, i64 1, i32 (i32, i8*)* bitcast (i32 (i32, [[TDP_TY:%.+]]*)* [[TASK2:@.+]] to i32 (i32, i8*)*))
+// CHECK: [[TASKV:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i32 1, i64 80, i64 1, i32 (i32, i8*)* bitcast (i32 (i32, [[TDP_TY:%.+]]*)* [[TASK2:@.+]] to i32 (i32, i8*)*))
// CHECK: [[TASK:%.+]] = bitcast i8* [[TASKV]] to [[TDP_TY]]*
// CHECK: [[TASK_DATA:%.+]] = getelementptr inbounds [[TDP_TY]], [[TDP_TY]]* [[TASK]], i32 0, i32 0
// CHECK: [[DOWN:%.+]] = getelementptr inbounds [[TD_TY:%.+]], [[TD_TY]]* [[TASK_DATA]], i32 0, i32 5
@@ -39,12 +44,12 @@ int main(int argc, char **argv) {
// CHECK: store i64 1, i64* [[ST]],
// CHECK: [[ST_VAL:%.+]] = load i64, i64* [[ST]],
// CHECK: [[GRAINSIZE:%.+]] = zext i32 %{{.+}} to i64
-// CHECK: call void @__kmpc_taskloop(%ident_t* [[DEFLOC]], i32 [[GTID]], i8* [[TASKV]], i32 1, i64* [[DOWN]], i64* [[UP]], i64 [[ST_VAL]], i32 0, i32 1, i64 [[GRAINSIZE]], i8* null)
+// CHECK: call void @__kmpc_taskloop(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i8* [[TASKV]], i32 1, i64* [[DOWN]], i64* [[UP]], i64 [[ST_VAL]], i32 0, i32 1, i64 [[GRAINSIZE]], i8* null)
#pragma omp taskloop nogroup grainsize(argc)
for (int i = 0; i < 10; ++i)
;
-// CHECK: call void @__kmpc_taskgroup(%ident_t* [[DEFLOC]], i32 [[GTID]])
-// CHECK: [[TASKV:%.+]] = call i8* @__kmpc_omp_task_alloc(%ident_t* [[DEFLOC]], i32 [[GTID]], i32 1, i64 80, i64 24, i32 (i32, i8*)* bitcast (i32 (i32, [[TDP_TY:%.+]]*)* [[TASK3:@.+]] to i32 (i32, i8*)*))
+// CHECK: call void @__kmpc_taskgroup(%struct.ident_t* [[DEFLOC]], i32 [[GTID]])
+// CHECK: [[TASKV:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i32 1, i64 80, i64 24, i32 (i32, i8*)* bitcast (i32 (i32, [[TDP_TY:%.+]]*)* [[TASK3:@.+]] to i32 (i32, i8*)*))
// CHECK: [[TASK:%.+]] = bitcast i8* [[TASKV]] to [[TDP_TY]]*
// CHECK: [[TASK_DATA:%.+]] = getelementptr inbounds [[TDP_TY]], [[TDP_TY]]* [[TASK]], i32 0, i32 0
// CHECK: [[IF:%.+]] = icmp ne i32 %{{.+}}, 0
@@ -56,8 +61,8 @@ int main(int argc, char **argv) {
// CHECK: [[ST:%.+]] = getelementptr inbounds [[TD_TY]], [[TD_TY]]* [[TASK_DATA]], i32 0, i32 7
// CHECK: store i64 1, i64* [[ST]],
// CHECK: [[ST_VAL:%.+]] = load i64, i64* [[ST]],
-// CHECK: call void @__kmpc_taskloop(%ident_t* [[DEFLOC]], i32 [[GTID]], i8* [[TASKV]], i32 [[IF_INT]], i64* [[DOWN]], i64* [[UP]], i64 [[ST_VAL]], i32 0, i32 2, i64 4, i8* null)
-// CHECK: call void @__kmpc_end_taskgroup(%ident_t* [[DEFLOC]], i32 [[GTID]])
+// CHECK: call void @__kmpc_taskloop(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i8* [[TASKV]], i32 [[IF_INT]], i64* [[DOWN]], i64* [[UP]], i64 [[ST_VAL]], i32 0, i32 2, i64 4, i8* null)
+// CHECK: call void @__kmpc_end_taskgroup(%struct.ident_t* [[DEFLOC]], i32 [[GTID]])
int i;
#pragma omp taskloop if(argc) shared(argc, argv) collapse(2) num_tasks(4)
for (i = 0; i < argc; ++i)
@@ -147,8 +152,8 @@ int main(int argc, char **argv) {
struct S {
int a;
S(int c) {
-// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num(%ident_t* [[DEFLOC:@.+]])
-// CHECK: [[TASKV:%.+]] = call i8* @__kmpc_omp_task_alloc(%ident_t* [[DEFLOC]], i32 [[GTID]], i32 1, i64 80, i64 16, i32 (i32, i8*)* bitcast (i32 (i32, [[TDP_TY:%.+]]*)* [[TASK4:@.+]] to i32 (i32, i8*)*))
+// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[DEFLOC:@.+]])
+// CHECK: [[TASKV:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i32 1, i64 80, i64 16, i32 (i32, i8*)* bitcast (i32 (i32, [[TDP_TY:%.+]]*)* [[TASK4:@.+]] to i32 (i32, i8*)*))
// CHECK: [[TASK:%.+]] = bitcast i8* [[TASKV]] to [[TDP_TY]]*
// CHECK: [[TASK_DATA:%.+]] = getelementptr inbounds [[TDP_TY]], [[TDP_TY]]* [[TASK]], i32 0, i32 0
// CHECK: [[DOWN:%.+]] = getelementptr inbounds [[TD_TY:%.+]], [[TD_TY]]* [[TASK_DATA]], i32 0, i32 5
@@ -159,7 +164,7 @@ struct S {
// CHECK: store i64 1, i64* [[ST]],
// CHECK: [[ST_VAL:%.+]] = load i64, i64* [[ST]],
// CHECK: [[NUM_TASKS:%.+]] = zext i32 %{{.+}} to i64
-// CHECK: call void @__kmpc_taskloop(%ident_t* [[DEFLOC]], i32 [[GTID]], i8* [[TASKV]], i32 1, i64* [[DOWN]], i64* [[UP]], i64 [[ST_VAL]], i32 0, i32 2, i64 [[NUM_TASKS]], i8* null)
+// CHECK: call void @__kmpc_taskloop(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i8* [[TASKV]], i32 1, i64* [[DOWN]], i64* [[UP]], i64 [[ST_VAL]], i32 0, i32 2, i64 [[NUM_TASKS]], i8* null)
#pragma omp taskloop shared(c) num_tasks(a)
for (a = 0; a < c; ++a)
;
diff --git a/test/OpenMP/taskloop_collapse_messages.cpp b/test/OpenMP/taskloop_collapse_messages.cpp
index 1a5620e77db0..4de0f38dae8b 100644
--- a/test/OpenMP/taskloop_collapse_messages.cpp
+++ b/test/OpenMP/taskloop_collapse_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/taskloop_final_messages.cpp b/test/OpenMP/taskloop_final_messages.cpp
index a2d7cdae9673..d53b12322e93 100644
--- a/test/OpenMP/taskloop_final_messages.cpp
+++ b/test/OpenMP/taskloop_final_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/taskloop_firstprivate_codegen.cpp b/test/OpenMP/taskloop_firstprivate_codegen.cpp
index 6e8453050987..d617835299cc 100644
--- a/test/OpenMP/taskloop_firstprivate_codegen.cpp
+++ b/test/OpenMP/taskloop_firstprivate_codegen.cpp
@@ -4,6 +4,14 @@
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=ARRAY %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
// It doesn't pass on win32.
// REQUIRES: shell
@@ -198,7 +206,7 @@ int main() {
// CHECK: [[SHAREDS_REF_ADDR:%.+]] = getelementptr inbounds [[KMP_TASK_T_TY]], [[KMP_TASK_T_TY]]* [[TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[SHAREDS_REF:%.+]] = load i8*, i8** [[SHAREDS_REF_ADDR]],
// CHECK: [[CAPTURES_ADDR:%.+]] = bitcast [[CAP_MAIN_TY]]* %{{.+}} to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[SHAREDS_REF]], i8* [[CAPTURES_ADDR]], i64 40, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[SHAREDS_REF]], i8* align 8 [[CAPTURES_ADDR]], i64 40, i1 false)
// Initialize kmp_task_t->privates with default values (no init for simple types, default constructors for classes).
// Also copy address of private copy to the corresponding shareds reference.
@@ -368,7 +376,7 @@ int main() {
// CHECK: [[SHAREDS_REF_ADDR:%.+]] = getelementptr inbounds [[KMP_TASK_T_TY]], [[KMP_TASK_T_TY]]* [[TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[SHAREDS_REF:%.+]] = load i8*, i8** [[SHAREDS_REF_ADDR]],
// CHECK: [[CAPTURES_ADDR:%.+]] = bitcast [[CAP_TMAIN_TY]]* %{{.+}} to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[SHAREDS_REF]], i8* [[CAPTURES_ADDR]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[SHAREDS_REF]], i8* align 8 [[CAPTURES_ADDR]], i64 32, i1 false)
// Initialize kmp_task_t->privates with default values (no init for simple types, default constructors for classes).
// CHECK: [[PRIVATES:%.+]] = getelementptr inbounds [[KMP_TASK_TMAIN_TY]], [[KMP_TASK_TMAIN_TY]]* [[RES_KMP_TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 2
diff --git a/test/OpenMP/taskloop_firstprivate_messages.cpp b/test/OpenMP/taskloop_firstprivate_messages.cpp
index e63d6a678b8d..7e1b818800da 100644
--- a/test/OpenMP/taskloop_firstprivate_messages.cpp
+++ b/test/OpenMP/taskloop_firstprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/taskloop_grainsize_messages.cpp b/test/OpenMP/taskloop_grainsize_messages.cpp
index 047f925b8250..a1cfea474c97 100644
--- a/test/OpenMP/taskloop_grainsize_messages.cpp
+++ b/test/OpenMP/taskloop_grainsize_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/taskloop_in_reduction_codegen.cpp b/test/OpenMP/taskloop_in_reduction_codegen.cpp
index e9ee9a32b97b..93f15932d7da 100644
--- a/test/OpenMP/taskloop_in_reduction_codegen.cpp
+++ b/test/OpenMP/taskloop_in_reduction_codegen.cpp
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -x c++ -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -x c++ -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -34,18 +39,18 @@ int main(int argc, char **argv) {
}
// CHECK-LABEL: @main
-// CHECK: void @__kmpc_taskgroup(%ident_t* @0, i32 [[GTID:%.+]])
+// CHECK: void @__kmpc_taskgroup(%struct.ident_t* @0, i32 [[GTID:%.+]])
// CHECK: [[TD1:%.+]] = call i8* @__kmpc_task_reduction_init(i32 [[GTID]], i32 3, i8* %
// CHECK-NEXT: store i8* [[TD1]], i8** [[TD1_ADDR:%[^,]+]],
-// CHECK-NEXT: call void @__kmpc_taskgroup(%ident_t* @0, i32 [[GTID]])
+// CHECK-NEXT: call void @__kmpc_taskgroup(%struct.ident_t* @0, i32 [[GTID]])
// CHECK: [[TD2:%.+]] = call i8* @__kmpc_task_reduction_init(i32 [[GTID]], i32 2, i8* %
// CHECK-NEXT: store i8* [[TD2]], i8** [[TD2_ADDR:%[^,]+]],
-// CHECK-NEXT: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* @0, i32 5, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, i64, i16*, i8**, i8**)* [[OMP_PARALLEL:@.+]] to void (i32*, i32*, ...)*), i32* %{{.+}}, i64 %{{.+}}, i16* %{{.+}}, i8** [[TD1_ADDR]], i8** [[TD2_ADDR]])
-// CHECK-NEXT: call void @__kmpc_end_taskgroup(%ident_t* @0, i32 [[GTID]])
-// CHECK-NEXT: call void @__kmpc_end_taskgroup(%ident_t* @0, i32 [[GTID]])
+// CHECK-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @0, i32 5, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, i64, i16*, i8**, i8**)* [[OMP_PARALLEL:@.+]] to void (i32*, i32*, ...)*), i32* %{{.+}}, i64 %{{.+}}, i16* %{{.+}}, i8** [[TD1_ADDR]], i8** [[TD2_ADDR]])
+// CHECK-NEXT: call void @__kmpc_end_taskgroup(%struct.ident_t* @0, i32 [[GTID]])
+// CHECK-NEXT: call void @__kmpc_end_taskgroup(%struct.ident_t* @0, i32 [[GTID]])
// CHECK: define internal void [[OMP_PARALLEL]](
-// CHECK: [[TASK_T:%.+]] = call i8* @__kmpc_omp_task_alloc(%ident_t* @0, i32 [[GTID:%.+]], i32 1, i64 96, i64 40, i32 (i32, i8*)* bitcast (i32 (i32, [[T:%.+]]*)* [[OMP_TASK:@.+]] to i32 (i32, i8*)*))
+// CHECK: [[TASK_T:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* @0, i32 [[GTID:%.+]], i32 1, i64 96, i64 40, i32 (i32, i8*)* bitcast (i32 (i32, [[T:%.+]]*)* [[OMP_TASK:@.+]] to i32 (i32, i8*)*))
// CHECK-NEXT: [[TASK_T_WITH_PRIVS:%.+]] = bitcast i8* [[TASK_T]] to [[T]]*
// CHECK: [[PRIVS:%.+]] = getelementptr inbounds [[T]], [[T]]* [[TASK_T_WITH_PRIVS]], i32 0, i32 1
// CHECK: [[TD1_REF:%.+]] = getelementptr inbounds [[PRIVATES]], [[PRIVATES]]* [[PRIVS]], i32 0, i32 0
@@ -58,7 +63,7 @@ int main(int argc, char **argv) {
// CHECK-NEXT: [[TD2_ADDR:%.+]] = load i8**, i8*** [[TD2_SHAR]],
// CHECK-NEXT: [[TD2:%.+]] = load i8*, i8** [[TD2_ADDR]],
// CHECK-NEXT: store i8* [[TD2]], i8** [[TD2_REF]],
-// CHECK: call void @__kmpc_taskloop(%ident_t* @0, i32 [[GTID]], i8* [[TASK_T]], i32 1,
+// CHECK: call void @__kmpc_taskloop(%struct.ident_t* @0, i32 [[GTID]], i8* [[TASK_T]], i32 1,
// CHECK: ret void
// CHECK-NEXT: }
diff --git a/test/OpenMP/taskloop_in_reduction_messages.cpp b/test/OpenMP/taskloop_in_reduction_messages.cpp
index 409975565a91..dc19bac907d5 100644
--- a/test/OpenMP/taskloop_in_reduction_messages.cpp
+++ b/test/OpenMP/taskloop_in_reduction_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 150 -o - %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 150 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/taskloop_lastprivate_codegen.cpp b/test/OpenMP/taskloop_lastprivate_codegen.cpp
index 837977eb57c0..a6f7abcc338b 100644
--- a/test/OpenMP/taskloop_lastprivate_codegen.cpp
+++ b/test/OpenMP/taskloop_lastprivate_codegen.cpp
@@ -4,6 +4,14 @@
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=ARRAY %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
// It doesn't pass on win32.
// REQUIRES: shell
@@ -190,7 +198,7 @@ int main() {
// CHECK: [[SHAREDS_REF_ADDR:%.+]] = getelementptr inbounds [[KMP_TASK_T_TY]], [[KMP_TASK_T_TY]]* [[TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[SHAREDS_REF:%.+]] = load i8*, i8** [[SHAREDS_REF_ADDR]],
// CHECK: [[CAPTURES_ADDR:%.+]] = bitcast [[CAP_MAIN_TY]]* %{{.+}} to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[SHAREDS_REF]], i8* [[CAPTURES_ADDR]], i64 40, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[SHAREDS_REF]], i8* align 8 [[CAPTURES_ADDR]], i64 40, i1 false)
// Initialize kmp_task_t->privates with default values (no init for simple types, default constructors for classes).
// Also copy address of private copy to the corresponding shareds reference.
@@ -279,18 +287,18 @@ int main() {
// CHECK-NEXT: br i1
// CHECK: bitcast [[S_DOUBLE_TY]]* %{{.+}} to i8*
// CHECK: bitcast [[S_DOUBLE_TY]]* %{{.+}} to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align {{[0-9]+}} %
// CHECK: load i32, i32* %
// CHECK: store i32 %{{.+}}, i32* %
// CHECK: getelementptr inbounds [2 x [[S_DOUBLE_TY]]], [2 x [[S_DOUBLE_TY]]]* %
// CHECK: phi [[S_DOUBLE_TY]]*
// CHECK: phi [[S_DOUBLE_TY]]*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align {{[0-9]+}} %
// CHECK: icmp eq [[S_DOUBLE_TY]]* %
// CHECK-NEXT: br i1
// CHECK: bitcast [2 x i32]* %{{.+}} to i8*
// CHECK: bitcast [2 x i32]* %{{.+}} to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align {{[0-9]+}} %
// CHECK: load i32, i32* %
// CHECK: store i32 %{{.+}}, i32* %
// CHECK: br label
@@ -364,7 +372,7 @@ int main() {
// CHECK: [[SHAREDS_REF_ADDR:%.+]] = getelementptr inbounds [[KMP_TASK_T_TY]], [[KMP_TASK_T_TY]]* [[TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[SHAREDS_REF:%.+]] = load i8*, i8** [[SHAREDS_REF_ADDR]],
// CHECK: [[CAPTURES_ADDR:%.+]] = bitcast [[CAP_TMAIN_TY]]* %{{.+}} to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[SHAREDS_REF]], i8* [[CAPTURES_ADDR]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[SHAREDS_REF]], i8* align 8 [[CAPTURES_ADDR]], i64 32, i1 false)
// Initialize kmp_task_t->privates with default values (no init for simple types, default constructors for classes).
// CHECK: [[PRIVATES:%.+]] = getelementptr inbounds [[KMP_TASK_TMAIN_TY]], [[KMP_TASK_TMAIN_TY]]* [[RES_KMP_TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 2
@@ -445,16 +453,16 @@ int main() {
// CHECK: store i32 %{{.+}}, i32* %
// CHECK: bitcast [2 x i32]* %{{.+}} to i8*
// CHECK: bitcast [2 x i32]* %{{.+}} to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align {{[0-9]+}} %
// CHECK: getelementptr inbounds [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* %
// CHECK: phi [[S_INT_TY]]*
// CHECK: phi [[S_INT_TY]]*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align {{[0-9]+}} %
// CHECK: icmp eq [[S_INT_TY]]* %
// CHECK-NEXT: br i1
// CHECK: bitcast [[S_INT_TY]]* %{{.+}} to i8*
// CHECK: bitcast [[S_INT_TY]]* %{{.+}} to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align {{[0-9]+}} %
// CHECK: br label
// CHECK: ret
diff --git a/test/OpenMP/taskloop_lastprivate_messages.cpp b/test/OpenMP/taskloop_lastprivate_messages.cpp
index 1d238ea083e6..85aaa00c8189 100644
--- a/test/OpenMP/taskloop_lastprivate_messages.cpp
+++ b/test/OpenMP/taskloop_lastprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/taskloop_loop_messages.cpp b/test/OpenMP/taskloop_loop_messages.cpp
index edfc2a8dcde5..4ce83b4ae1ae 100644
--- a/test/OpenMP/taskloop_loop_messages.cpp
+++ b/test/OpenMP/taskloop_loop_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+
class S {
int a;
S() : a(0) {}
@@ -292,10 +294,8 @@ int test_iteration_spaces() {
c[ii] = a[ii];
#pragma omp parallel
-// expected-error@+2 {{unexpected OpenMP clause 'linear' in directive '#pragma omp taskloop'}}
-// expected-note@+1 {{defined as linear}}
+// expected-error@+1 {{unexpected OpenMP clause 'linear' in directive '#pragma omp taskloop'}}
#pragma omp taskloop linear(ii)
-// expected-error@+1 {{loop iteration variable in the associated loop of 'omp taskloop' directive may not be linear, predetermined as private}}
for (ii = 0; ii < 10; ii++)
c[ii] = a[ii];
diff --git a/test/OpenMP/taskloop_misc_messages.c b/test/OpenMP/taskloop_misc_messages.c
index f9e084e0edd1..4e2ac0aab7c6 100644
--- a/test/OpenMP/taskloop_misc_messages.c
+++ b/test/OpenMP/taskloop_misc_messages.c
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -triple x86_64-unknown-unknown -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -triple x86_64-unknown-unknown -verify %s
+
// expected-error@+1 {{unexpected OpenMP directive '#pragma omp taskloop'}}
#pragma omp taskloop
diff --git a/test/OpenMP/taskloop_num_tasks_messages.cpp b/test/OpenMP/taskloop_num_tasks_messages.cpp
index 94d74eb41eb0..cf506ff5df92 100644
--- a/test/OpenMP/taskloop_num_tasks_messages.cpp
+++ b/test/OpenMP/taskloop_num_tasks_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/taskloop_priority_messages.cpp b/test/OpenMP/taskloop_priority_messages.cpp
index 6c1584570eb9..cbfd2579f587 100644
--- a/test/OpenMP/taskloop_priority_messages.cpp
+++ b/test/OpenMP/taskloop_priority_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/taskloop_private_codegen.cpp b/test/OpenMP/taskloop_private_codegen.cpp
index 6ca7c402a12b..21ffcba97d9e 100644
--- a/test/OpenMP/taskloop_private_codegen.cpp
+++ b/test/OpenMP/taskloop_private_codegen.cpp
@@ -4,6 +4,14 @@
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=ARRAY %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
// It doesn't pass on win32. Investigating.
// REQUIRES: shell
diff --git a/test/OpenMP/taskloop_private_messages.cpp b/test/OpenMP/taskloop_private_messages.cpp
index 367d59da6959..ffe731d2c7ef 100644
--- a/test/OpenMP/taskloop_private_messages.cpp
+++ b/test/OpenMP/taskloop_private_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/taskloop_reduction_codegen.cpp b/test/OpenMP/taskloop_reduction_codegen.cpp
index 6af067642fea..65bc50a4d255 100644
--- a/test/OpenMP/taskloop_reduction_codegen.cpp
+++ b/test/OpenMP/taskloop_reduction_codegen.cpp
@@ -1,4 +1,7 @@
// RUN: %clang_cc1 -fopenmp -x c++ %s -verify -debug-info-kind=limited -emit-llvm -o - -triple powerpc64le-unknown-linux-gnu -std=c++98 | FileCheck %s
+
+// RUN: %clang_cc1 -fopenmp-simd -x c++ %s -verify -debug-info-kind=limited -emit-llvm -o - -triple powerpc64le-unknown-linux-gnu -std=c++98 | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
struct S {
@@ -49,7 +52,7 @@ sum = 0.0;
// CHECK: [[C:%.*]] = alloca [100 x %struct.S],
// CHECK: [[D:%.*]] = alloca float*,
// CHECK: [[AGG_CAPTURED:%.*]] = alloca [[STRUCT_ANON:%.*]],
-// CHECK: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(%ident_t*
+// CHECK: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t*
// CHECK: [[DOTRD_INPUT_:%.*]] = alloca [4 x %struct.kmp_task_red_input_t],
// CHECK: alloca i32,
// CHECK: [[DOTCAPTURE_EXPR_:%.*]] = alloca i32,
@@ -62,21 +65,21 @@ sum = 0.0;
// CHECK: [[TMP2:%.*]] = zext i32 [[ADD]] to i64
// CHECK: [[VLA:%.+]] = alloca float, i64 %
-// CHECK: call void @__kmpc_taskgroup(%ident_t*
+// CHECK: call void @__kmpc_taskgroup(%struct.ident_t*
// CHECK-DAG: [[TMP21:%.*]] = bitcast float* [[SUM]] to i8*
// CHECK-DAG: store i8* [[TMP21]], i8** [[TMP20:%[^,]+]],
// CHECK-DAG: [[TMP20]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T:%.+]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_:%.+]], i32 0, i32 0
// CHECK-DAG: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_]], i32 0, i32 1
// CHECK-DAG: store i64 4, i64* [[TMP22]],
// CHECK-DAG: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_]], i32 0, i32 2
-// CHECK-DAG: store i8* bitcast (void (i8*)* [[RED_INIT1:@.+]] to i8*), i8** [[TMP23]],
+// CHECK-DAG: store i8* bitcast (void (i8*)* @[[RED_INIT1:.+]] to i8*), i8** [[TMP23]],
// CHECK-DAG: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_]], i32 0, i32 3
// CHECK-DAG: store i8* null, i8** [[TMP24]],
// CHECK-DAG: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_]], i32 0, i32 4
-// CHECK-DAG: store i8* bitcast (void (i8*, i8*)* [[RED_COMB1:@.+]] to i8*), i8** [[TMP25]],
+// CHECK-DAG: store i8* bitcast (void (i8*, i8*)* @[[RED_COMB1:.+]] to i8*), i8** [[TMP25]],
// CHECK-DAG: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_]], i32 0, i32 5
// CHECK-DAG: [[TMP27:%.*]] = bitcast i32* [[TMP26]] to i8*
-// CHECK-DAG: call void @llvm.memset.p0i8.i64(i8* [[TMP27]], i8 0, i64 4, i32 8, i1 false)
+// CHECK-DAG: call void @llvm.memset.p0i8.i64(i8* align 8 [[TMP27]], i8 0, i64 4, i1 false)
// CHECK-DAG: [[ARRAYIDX5:%.*]] = getelementptr inbounds [100 x %struct.S], [100 x %struct.S]* [[C]], i64 0, i64 0
// CHECK-DAG: [[LB_ADD_LEN:%.*]] = add nsw i64 -1, %
// CHECK-DAG: [[ARRAYIDX6:%.*]] = getelementptr inbounds [100 x %struct.S], [100 x %struct.S]* [[C]], i64 0, i64 [[LB_ADD_LEN]]
@@ -92,11 +95,11 @@ sum = 0.0;
// CHECK-DAG: store i64 [[TMP37]], i64* [[TMP38:%[^,]+]],
// CHECK-DAG: [[TMP38]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_4]], i32 0, i32 1
// CHECK-DAG: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_4]], i32 0, i32 2
-// CHECK-DAG: store i8* bitcast (void (i8*)* [[RED_INIT2:@.+]] to i8*), i8** [[TMP39]],
+// CHECK-DAG: store i8* bitcast (void (i8*)* @[[RED_INIT2:.+]] to i8*), i8** [[TMP39]],
// CHECK-DAG: [[TMP40:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_4]], i32 0, i32 3
-// CHECK-DAG: store i8* bitcast (void (i8*)* [[RED_FINI2:@.+]] to i8*), i8** [[TMP40]],
+// CHECK-DAG: store i8* bitcast (void (i8*)* @[[RED_FINI2:.+]] to i8*), i8** [[TMP40]],
// CHECK-DAG: [[TMP41:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_4]], i32 0, i32 4
-// CHECK-DAG: store i8* bitcast (void (i8*, i8*)* [[RED_COMB2:@.+]] to i8*), i8** [[TMP41]],
+// CHECK-DAG: store i8* bitcast (void (i8*, i8*)* @[[RED_COMB2:.+]] to i8*), i8** [[TMP41]],
// CHECK-DAG: [[TMP42:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_4]], i32 0, i32 5
// CHECK-DAG: store i32 1, i32* [[TMP42]],
// CHECK-DAG: [[TMP44:%.*]] = load float*, float** [[D]],
@@ -106,14 +109,14 @@ sum = 0.0;
// CHECK-DAG: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_7]], i32 0, i32 1
// CHECK-DAG: store i64 4, i64* [[TMP46]],
// CHECK-DAG: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_7]], i32 0, i32 2
-// CHECK-DAG: store i8* bitcast (void (i8*)* [[RED_INIT3:@.+]] to i8*), i8** [[TMP47]],
+// CHECK-DAG: store i8* bitcast (void (i8*)* @[[RED_INIT3:.+]] to i8*), i8** [[TMP47]],
// CHECK-DAG: [[TMP48:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_7]], i32 0, i32 3
// CHECK-DAG: store i8* null, i8** [[TMP48]],
// CHECK-DAG: [[TMP49:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_7]], i32 0, i32 4
-// CHECK-DAG: store i8* bitcast (void (i8*, i8*)* [[RED_COMB3:@.+]] to i8*), i8** [[TMP49]],
+// CHECK-DAG: store i8* bitcast (void (i8*, i8*)* @[[RED_COMB3:.+]] to i8*), i8** [[TMP49]],
// CHECK-DAG: [[TMP50:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_7]], i32 0, i32 5
// CHECK-DAG: [[TMP51:%.*]] = bitcast i32* [[TMP50]] to i8*
-// CHECK-DAG: call void @llvm.memset.p0i8.i64(i8* [[TMP51]], i8 0, i64 4, i32 8, i1 false)
+// CHECK-DAG: call void @llvm.memset.p0i8.i64(i8* align 8 [[TMP51]], i8 0, i64 4, i1 false)
// CHECK-DAG: [[TMP53:%.*]] = bitcast float* [[VLA]] to i8*
// CHECK-DAG: store i8* [[TMP53]], i8** [[TMP52:%[^,]+]],
// CHECK-DAG: [[TMP52]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_8:%.+]], i32 0, i32 0
@@ -122,11 +125,11 @@ sum = 0.0;
// CHECK-DAG: store i64 [[TMP54]], i64* [[TMP56:%[^,]+]],
// CHECK-DAG: [[TMP56]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_8]], i32 0, i32 1
// CHECK-DAG: [[TMP57:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_8]], i32 0, i32 2
-// CHECK-DAG: store i8* bitcast (void (i8*)* [[RED_INIT4:@.+]] to i8*), i8** [[TMP57]],
+// CHECK-DAG: store i8* bitcast (void (i8*)* @[[RED_INIT4:.+]] to i8*), i8** [[TMP57]],
// CHECK-DAG: [[TMP58:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_8]], i32 0, i32 3
// CHECK-DAG: store i8* null, i8** [[TMP58]],
// CHECK-DAG: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_8]], i32 0, i32 4
-// CHECK-DAG: store i8* bitcast (void (i8*, i8*)* [[RED_COMB4:@.+]] to i8*), i8** [[TMP59]],
+// CHECK-DAG: store i8* bitcast (void (i8*, i8*)* @[[RED_COMB4:.+]] to i8*), i8** [[TMP59]],
// CHECK-DAG: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_8]], i32 0, i32 5
// CHECK-DAG: store i32 1, i32* [[TMP60]],
// CHECK-DAG: [[DOTRD_INPUT_GEP_]] = getelementptr inbounds [4 x %struct.kmp_task_red_input_t], [4 x %struct.kmp_task_red_input_t]* [[DOTRD_INPUT_]], i64 0, i64
@@ -144,56 +147,78 @@ sum = 0.0;
// CHECK: [[DIV:%.*]] = sdiv i32 [[ADD11]], 1
// CHECK: [[SUB12:%.*]] = sub nsw i32 [[DIV]], 1
// CHECK: store i32 [[SUB12]], i32* [[DOTCAPTURE_EXPR_9]],
-// CHECK: [[TMP65:%.*]] = call i8* @__kmpc_omp_task_alloc(%ident_t* %{{.+}}, i32 [[TMP0]], i32 1, i64 888, i64 72, i32 (i32, i8*)* bitcast (i32 (i32, %struct.kmp_task_t_with_privates*)* @[[TASK:.+]] to i32 (i32, i8*)*))
-// CHECK: call void @__kmpc_taskloop(%ident_t* %{{.+}}, i32 [[TMP0]], i8* [[TMP65]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 0, i32 0, i64 0, i8* null)
-// CHECK: call void @__kmpc_end_taskgroup(%ident_t*
+// CHECK: [[TMP65:%.*]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* %{{.+}}, i32 [[TMP0]], i32 1, i64 888, i64 72, i32 (i32, i8*)* bitcast (i32 (i32, %struct.kmp_task_t_with_privates*)* @[[TASK:.+]] to i32 (i32, i8*)*))
+// CHECK: call void @__kmpc_taskloop(%struct.ident_t* %{{.+}}, i32 [[TMP0]], i8* [[TMP65]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 0, i32 0, i64 0, i8* null)
+// CHECK: call void @__kmpc_end_taskgroup(%struct.ident_t*
// CHECK: ret i32
-// CHECK: define internal void [[RED_INIT1]](i8*)
+// CHECK: define internal void @[[RED_INIT1]](i8*)
// CHECK: store float 0.000000e+00, float* %
// CHECK: ret void
-// CHECK: define internal void [[RED_COMB1]](i8*, i8*)
+// CHECK: define internal void @[[RED_COMB1]](i8*, i8*)
// CHECK: fadd float %
// CHECK: store float %{{.+}}, float* %
// CHECK: ret void
-// CHECK: define internal void [[RED_INIT2]](i8*)
-// CHECK: call i8* @__kmpc_threadprivate_cached(
+// CHECK: define internal void @[[RED_INIT2]](i8*)
// CHECK: call i8* @__kmpc_threadprivate_cached(
+// CHECK: [[ORIG_PTR_ADDR:%.+]] = call i8* @__kmpc_threadprivate_cached(
+// CHECK: [[ORIG_PTR_REF:%.+]] = bitcast i8* [[ORIG_PTR_ADDR]] to i8**
+// CHECK: load i8*, i8** [[ORIG_PTR_REF]],
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(
// CHECK: ret void
-// CHECK: define internal void [[RED_FINI2]](i8*)
+// CHECK: define internal void @[[RED_FINI2]](i8*)
// CHECK: call i8* @__kmpc_threadprivate_cached(
// CHECK: call void @
// CHECK: ret void
-// CHECK: define internal void [[RED_COMB2]](i8*, i8*)
+// CHECK: define internal void @[[RED_COMB2]](i8*, i8*)
// CHECK: call i8* @__kmpc_threadprivate_cached(
// CHECK: fadd float %
// CHECK: store float %{{.+}}, float* %
// CHECK: ret void
-// CHECK: define internal void [[RED_INIT3]](i8*)
+// CHECK: define internal void @[[RED_INIT3]](i8*)
// CHECK: store float 0.000000e+00, float* %
// CHECK: ret void
-// CHECK: define internal void [[RED_COMB3]](i8*, i8*)
+// CHECK: define internal void @[[RED_COMB3]](i8*, i8*)
// CHECK: fadd float %
// CHECK: store float %{{.+}}, float* %
// CHECK: ret void
-// CHECK: define internal void [[RED_INIT4]](i8*)
+// CHECK: define internal void @[[RED_INIT4]](i8*)
// CHECK: call i8* @__kmpc_threadprivate_cached(
// CHECK: store float 0.000000e+00, float* %
// CHECK: ret void
-// CHECK: define internal void [[RED_COMB4]](i8*, i8*)
+// CHECK: define internal void @[[RED_COMB4]](i8*, i8*)
// CHECK: call i8* @__kmpc_threadprivate_cached(
// CHECK: fadd float %
// CHECK: store float %{{.+}}, float* %
// CHECK: ret void
-// CHECK: distinct !DISubprogram(linkageName: "[[TASK]]", scope: !
+// CHECK-NOT: call i8* @__kmpc_threadprivate_cached(
+// CHECK: call i8* @__kmpc_task_reduction_get_th_data(
+// CHECK: call i8* @__kmpc_threadprivate_cached(
+// CHECK: call i8* @__kmpc_threadprivate_cached(
+// CHECK: call i8* @__kmpc_task_reduction_get_th_data(
+// CHECK-NOT: call i8* @__kmpc_threadprivate_cached(
+// CHECK: call i8* @__kmpc_task_reduction_get_th_data(
+// CHECK: call i8* @__kmpc_threadprivate_cached(
+// CHECK: call i8* @__kmpc_task_reduction_get_th_data(
+// CHECK-NOT: call i8* @__kmpc_threadprivate_cached(
+
+// CHECK-DAG: distinct !DISubprogram(linkageName: "[[TASK]]", scope: !
+// CHECK-DAG: !DISubprogram(linkageName: "[[RED_INIT1]]"
+// CHECK-DAG: !DISubprogram(linkageName: "[[RED_COMB1]]"
+// CHECK-DAG: !DISubprogram(linkageName: "[[RED_INIT2]]"
+// CHECK-DAG: !DISubprogram(linkageName: "[[RED_FINI2]]"
+// CHECK-DAG: !DISubprogram(linkageName: "[[RED_COMB2]]"
+// CHECK-DAG: !DISubprogram(linkageName: "[[RED_INIT3]]"
+// CHECK-DAG: !DISubprogram(linkageName: "[[RED_COMB3]]"
+// CHECK-DAG: !DISubprogram(linkageName: "[[RED_INIT4]]"
+// CHECK-DAG: !DISubprogram(linkageName: "[[RED_COMB4]]"
diff --git a/test/OpenMP/taskloop_reduction_messages.cpp b/test/OpenMP/taskloop_reduction_messages.cpp
index 23f70b568525..c83a8b30c52c 100644
--- a/test/OpenMP/taskloop_reduction_messages.cpp
+++ b/test/OpenMP/taskloop_reduction_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 150 -o - %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 150 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/taskloop_simd_aligned_messages.cpp b/test/OpenMP/taskloop_simd_aligned_messages.cpp
index c4c41ebbafe4..24cdd00e6b34 100644
--- a/test/OpenMP/taskloop_simd_aligned_messages.cpp
+++ b/test/OpenMP/taskloop_simd_aligned_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -x c++ -std=c++11 -verify -fopenmp %s
+// RUN: %clang_cc1 -x c++ -std=c++11 -verify -fopenmp-simd %s
+
struct B {
static int ib[20]; // expected-note 0 {{'B::ib' declared here}}
static constexpr int bfoo() { return 8; }
diff --git a/test/OpenMP/taskloop_simd_ast_print.cpp b/test/OpenMP/taskloop_simd_ast_print.cpp
index 6f13c7e0baa5..0a847f8fad06 100644
--- a/test/OpenMP/taskloop_simd_ast_print.cpp
+++ b/test/OpenMP/taskloop_simd_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -17,7 +21,7 @@ T tmain(T argc) {
#pragma omp taskgroup task_reduction(+: d)
#pragma omp taskloop simd if(taskloop: argc > N) default(shared) untied priority(N) safelen(N) linear(c) aligned(ptr) grainsize(N) reduction(+:g) in_reduction(+: d)
// CHECK-NEXT: #pragma omp taskgroup task_reduction(+: d)
- // CHECK-NEXT: #pragma omp taskloop simd if(taskloop: argc > N) default(shared) untied priority(N) safelen(N) linear(c) aligned(ptr) grainsize(N) reduction(+: g) in_reduction(+: d)
+ // CHECK-NEXT: #pragma omp taskloop simd if(taskloop: argc > N) default(shared) untied priority(N) safelen(N) linear(c) aligned(ptr) grainsize(N) reduction(+: g) in_reduction(+: d){{$}}
for (int i = 0; i < 2; ++i)
a = 2;
// CHECK-NEXT: for (int i = 0; i < 2; ++i)
diff --git a/test/OpenMP/taskloop_simd_codegen.cpp b/test/OpenMP/taskloop_simd_codegen.cpp
index 006fd59af3fa..d3efec5ee441 100644
--- a/test/OpenMP/taskloop_simd_codegen.cpp
+++ b/test/OpenMP/taskloop_simd_codegen.cpp
@@ -1,15 +1,20 @@
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -x c++ -emit-llvm %s -o - -femit-all-decls | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -include-pch %t -verify %s -emit-llvm -o - -femit-all-decls | FileCheck %s
+
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -x c++ -emit-llvm %s -o - -femit-all-decls | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -include-pch %t -verify %s -emit-llvm -o - -femit-all-decls | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
// CHECK-LABEL: @main
int main(int argc, char **argv) {
-// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num(%ident_t* [[DEFLOC:@.+]])
-// CHECK: call void @__kmpc_taskgroup(%ident_t* [[DEFLOC]], i32 [[GTID]])
-// CHECK: [[TASKV:%.+]] = call i8* @__kmpc_omp_task_alloc(%ident_t* [[DEFLOC]], i32 [[GTID]], i32 33, i64 80, i64 1, i32 (i32, i8*)* bitcast (i32 (i32, [[TDP_TY:%.+]]*)* [[TASK1:@.+]] to i32 (i32, i8*)*))
+// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[DEFLOC:@.+]])
+// CHECK: call void @__kmpc_taskgroup(%struct.ident_t* [[DEFLOC]], i32 [[GTID]])
+// CHECK: [[TASKV:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i32 33, i64 80, i64 1, i32 (i32, i8*)* bitcast (i32 (i32, [[TDP_TY:%.+]]*)* [[TASK1:@.+]] to i32 (i32, i8*)*))
// CHECK: [[TASK:%.+]] = bitcast i8* [[TASKV]] to [[TDP_TY]]*
// CHECK: [[TASK_DATA:%.+]] = getelementptr inbounds [[TDP_TY]], [[TDP_TY]]* [[TASK]], i32 0, i32 0
// CHECK: [[DOWN:%.+]] = getelementptr inbounds [[TD_TY:%.+]], [[TD_TY]]* [[TASK_DATA]], i32 0, i32 5
@@ -19,12 +24,12 @@ int main(int argc, char **argv) {
// CHECK: [[ST:%.+]] = getelementptr inbounds [[TD_TY]], [[TD_TY]]* [[TASK_DATA]], i32 0, i32 7
// CHECK: store i64 1, i64* [[ST]],
// CHECK: [[ST_VAL:%.+]] = load i64, i64* [[ST]],
-// CHECK: call void @__kmpc_taskloop(%ident_t* [[DEFLOC]], i32 [[GTID]], i8* [[TASKV]], i32 1, i64* [[DOWN]], i64* [[UP]], i64 [[ST_VAL]], i32 0, i32 0, i64 0, i8* null)
-// CHECK: call void @__kmpc_end_taskgroup(%ident_t* [[DEFLOC]], i32 [[GTID]])
+// CHECK: call void @__kmpc_taskloop(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i8* [[TASKV]], i32 1, i64* [[DOWN]], i64* [[UP]], i64 [[ST_VAL]], i32 0, i32 0, i64 0, i8* null)
+// CHECK: call void @__kmpc_end_taskgroup(%struct.ident_t* [[DEFLOC]], i32 [[GTID]])
#pragma omp taskloop simd priority(argc)
for (int i = 0; i < 10; ++i)
;
-// CHECK: [[TASKV:%.+]] = call i8* @__kmpc_omp_task_alloc(%ident_t* [[DEFLOC]], i32 [[GTID]], i32 1, i64 80, i64 1, i32 (i32, i8*)* bitcast (i32 (i32, [[TDP_TY:%.+]]*)* [[TASK2:@.+]] to i32 (i32, i8*)*))
+// CHECK: [[TASKV:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i32 1, i64 80, i64 1, i32 (i32, i8*)* bitcast (i32 (i32, [[TDP_TY:%.+]]*)* [[TASK2:@.+]] to i32 (i32, i8*)*))
// CHECK: [[TASK:%.+]] = bitcast i8* [[TASKV]] to [[TDP_TY]]*
// CHECK: [[TASK_DATA:%.+]] = getelementptr inbounds [[TDP_TY]], [[TDP_TY]]* [[TASK]], i32 0, i32 0
// CHECK: [[DOWN:%.+]] = getelementptr inbounds [[TD_TY:%.+]], [[TD_TY]]* [[TASK_DATA]], i32 0, i32 5
@@ -35,12 +40,12 @@ int main(int argc, char **argv) {
// CHECK: store i64 1, i64* [[ST]],
// CHECK: [[ST_VAL:%.+]] = load i64, i64* [[ST]],
// CHECK: [[GRAINSIZE:%.+]] = zext i32 %{{.+}} to i64
-// CHECK: call void @__kmpc_taskloop(%ident_t* [[DEFLOC]], i32 [[GTID]], i8* [[TASKV]], i32 1, i64* [[DOWN]], i64* [[UP]], i64 [[ST_VAL]], i32 0, i32 1, i64 [[GRAINSIZE]], i8* null)
+// CHECK: call void @__kmpc_taskloop(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i8* [[TASKV]], i32 1, i64* [[DOWN]], i64* [[UP]], i64 [[ST_VAL]], i32 0, i32 1, i64 [[GRAINSIZE]], i8* null)
#pragma omp taskloop simd nogroup grainsize(argc) simdlen(4)
for (int i = 0; i < 10; ++i)
;
-// CHECK: call void @__kmpc_taskgroup(%ident_t* [[DEFLOC]], i32 [[GTID]])
-// CHECK: [[TASKV:%.+]] = call i8* @__kmpc_omp_task_alloc(%ident_t* [[DEFLOC]], i32 [[GTID]], i32 1, i64 80, i64 24, i32 (i32, i8*)* bitcast (i32 (i32, [[TDP_TY:%.+]]*)* [[TASK3:@.+]] to i32 (i32, i8*)*))
+// CHECK: call void @__kmpc_taskgroup(%struct.ident_t* [[DEFLOC]], i32 [[GTID]])
+// CHECK: [[TASKV:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i32 1, i64 80, i64 24, i32 (i32, i8*)* bitcast (i32 (i32, [[TDP_TY:%.+]]*)* [[TASK3:@.+]] to i32 (i32, i8*)*))
// CHECK: [[TASK:%.+]] = bitcast i8* [[TASKV]] to [[TDP_TY]]*
// CHECK: [[TASK_DATA:%.+]] = getelementptr inbounds [[TDP_TY]], [[TDP_TY]]* [[TASK]], i32 0, i32 0
// CHECK: [[IF:%.+]] = icmp ne i32 %{{.+}}, 0
@@ -52,8 +57,8 @@ int main(int argc, char **argv) {
// CHECK: [[ST:%.+]] = getelementptr inbounds [[TD_TY]], [[TD_TY]]* [[TASK_DATA]], i32 0, i32 7
// CHECK: store i64 1, i64* [[ST]],
// CHECK: [[ST_VAL:%.+]] = load i64, i64* [[ST]],
-// CHECK: call void @__kmpc_taskloop(%ident_t* [[DEFLOC]], i32 [[GTID]], i8* [[TASKV]], i32 [[IF_INT]], i64* [[DOWN]], i64* [[UP]], i64 [[ST_VAL]], i32 0, i32 2, i64 4, i8* null)
-// CHECK: call void @__kmpc_end_taskgroup(%ident_t* [[DEFLOC]], i32 [[GTID]])
+// CHECK: call void @__kmpc_taskloop(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i8* [[TASKV]], i32 [[IF_INT]], i64* [[DOWN]], i64* [[UP]], i64 [[ST_VAL]], i32 0, i32 2, i64 4, i8* null)
+// CHECK: call void @__kmpc_end_taskgroup(%struct.ident_t* [[DEFLOC]], i32 [[GTID]])
int i;
#pragma omp taskloop simd if(argc) shared(argc, argv) collapse(2) num_tasks(4) safelen(32)
for (i = 0; i < argc; ++i)
@@ -145,8 +150,8 @@ int main(int argc, char **argv) {
struct S {
int a;
S(int c) {
-// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num(%ident_t* [[DEFLOC:@.+]])
-// CHECK: [[TASKV:%.+]] = call i8* @__kmpc_omp_task_alloc(%ident_t* [[DEFLOC]], i32 [[GTID]], i32 1, i64 80, i64 16, i32 (i32, i8*)* bitcast (i32 (i32, [[TDP_TY:%.+]]*)* [[TASK4:@.+]] to i32 (i32, i8*)*))
+// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[DEFLOC:@.+]])
+// CHECK: [[TASKV:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i32 1, i64 80, i64 16, i32 (i32, i8*)* bitcast (i32 (i32, [[TDP_TY:%.+]]*)* [[TASK4:@.+]] to i32 (i32, i8*)*))
// CHECK: [[TASK:%.+]] = bitcast i8* [[TASKV]] to [[TDP_TY]]*
// CHECK: [[TASK_DATA:%.+]] = getelementptr inbounds [[TDP_TY]], [[TDP_TY]]* [[TASK]], i32 0, i32 0
// CHECK: [[DOWN:%.+]] = getelementptr inbounds [[TD_TY:%.+]], [[TD_TY]]* [[TASK_DATA]], i32 0, i32 5
@@ -157,7 +162,7 @@ struct S {
// CHECK: store i64 1, i64* [[ST]],
// CHECK: [[ST_VAL:%.+]] = load i64, i64* [[ST]],
// CHECK: [[NUM_TASKS:%.+]] = zext i32 %{{.+}} to i64
-// CHECK: call void @__kmpc_taskloop(%ident_t* [[DEFLOC]], i32 [[GTID]], i8* [[TASKV]], i32 1, i64* [[DOWN]], i64* [[UP]], i64 [[ST_VAL]], i32 0, i32 2, i64 [[NUM_TASKS]], i8* null)
+// CHECK: call void @__kmpc_taskloop(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i8* [[TASKV]], i32 1, i64* [[DOWN]], i64* [[UP]], i64 [[ST_VAL]], i32 0, i32 2, i64 [[NUM_TASKS]], i8* null)
#pragma omp taskloop simd shared(c) num_tasks(a) simdlen(8) safelen(64)
for (a = 0; a < c; ++a)
;
diff --git a/test/OpenMP/taskloop_simd_collapse_messages.cpp b/test/OpenMP/taskloop_simd_collapse_messages.cpp
index e4ce0c1df41a..3f7e66a27702 100644
--- a/test/OpenMP/taskloop_simd_collapse_messages.cpp
+++ b/test/OpenMP/taskloop_simd_collapse_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/taskloop_simd_final_messages.cpp b/test/OpenMP/taskloop_simd_final_messages.cpp
index c6580fbaa9b4..b7393661c940 100644
--- a/test/OpenMP/taskloop_simd_final_messages.cpp
+++ b/test/OpenMP/taskloop_simd_final_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/taskloop_simd_firstprivate_codegen.cpp b/test/OpenMP/taskloop_simd_firstprivate_codegen.cpp
index 9e268d8a1739..4f406b2a583a 100644
--- a/test/OpenMP/taskloop_simd_firstprivate_codegen.cpp
+++ b/test/OpenMP/taskloop_simd_firstprivate_codegen.cpp
@@ -4,6 +4,14 @@
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=ARRAY %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
// It doesn't pass on win32.
// REQUIRES: shell
@@ -198,7 +206,7 @@ int main() {
// CHECK: [[SHAREDS_REF_ADDR:%.+]] = getelementptr inbounds [[KMP_TASK_T_TY]], [[KMP_TASK_T_TY]]* [[TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[SHAREDS_REF:%.+]] = load i8*, i8** [[SHAREDS_REF_ADDR]],
// CHECK: [[CAPTURES_ADDR:%.+]] = bitcast [[CAP_MAIN_TY]]* %{{.+}} to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[SHAREDS_REF]], i8* [[CAPTURES_ADDR]], i64 40, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[SHAREDS_REF]], i8* align 8 [[CAPTURES_ADDR]], i64 40, i1 false)
// Initialize kmp_task_t->privates with default values (no init for simple types, default constructors for classes).
// Also copy address of private copy to the corresponding shareds reference.
@@ -368,7 +376,7 @@ int main() {
// CHECK: [[SHAREDS_REF_ADDR:%.+]] = getelementptr inbounds [[KMP_TASK_T_TY]], [[KMP_TASK_T_TY]]* [[TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[SHAREDS_REF:%.+]] = load i8*, i8** [[SHAREDS_REF_ADDR]],
// CHECK: [[CAPTURES_ADDR:%.+]] = bitcast [[CAP_TMAIN_TY]]* %{{.+}} to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[SHAREDS_REF]], i8* [[CAPTURES_ADDR]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[SHAREDS_REF]], i8* align 8 [[CAPTURES_ADDR]], i64 32, i1 false)
// Initialize kmp_task_t->privates with default values (no init for simple types, default constructors for classes).
// CHECK: [[PRIVATES:%.+]] = getelementptr inbounds [[KMP_TASK_TMAIN_TY]], [[KMP_TASK_TMAIN_TY]]* [[RES_KMP_TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 2
diff --git a/test/OpenMP/taskloop_simd_firstprivate_messages.cpp b/test/OpenMP/taskloop_simd_firstprivate_messages.cpp
index 176dcd7f8f9c..66c9e7a2f8ff 100644
--- a/test/OpenMP/taskloop_simd_firstprivate_messages.cpp
+++ b/test/OpenMP/taskloop_simd_firstprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/taskloop_simd_grainsize_messages.cpp b/test/OpenMP/taskloop_simd_grainsize_messages.cpp
index 45ccb31824fa..3441e59e56d0 100644
--- a/test/OpenMP/taskloop_simd_grainsize_messages.cpp
+++ b/test/OpenMP/taskloop_simd_grainsize_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/taskloop_simd_in_reduction_codegen.cpp b/test/OpenMP/taskloop_simd_in_reduction_codegen.cpp
index d894943cc359..a197b4613e88 100644
--- a/test/OpenMP/taskloop_simd_in_reduction_codegen.cpp
+++ b/test/OpenMP/taskloop_simd_in_reduction_codegen.cpp
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -x c++ -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -x c++ -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -34,18 +39,18 @@ int main(int argc, char **argv) {
}
// CHECK-LABEL: @main
-// CHECK: void @__kmpc_taskgroup(%ident_t* @0, i32 [[GTID:%.+]])
+// CHECK: void @__kmpc_taskgroup(%struct.ident_t* @0, i32 [[GTID:%.+]])
// CHECK: [[TD1:%.+]] = call i8* @__kmpc_task_reduction_init(i32 [[GTID]], i32 3, i8* %
// CHECK-NEXT: store i8* [[TD1]], i8** [[TD1_ADDR:%[^,]+]],
-// CHECK-NEXT: call void @__kmpc_taskgroup(%ident_t* @0, i32 [[GTID]])
+// CHECK-NEXT: call void @__kmpc_taskgroup(%struct.ident_t* @0, i32 [[GTID]])
// CHECK: [[TD2:%.+]] = call i8* @__kmpc_task_reduction_init(i32 [[GTID]], i32 2, i8* %
// CHECK-NEXT: store i8* [[TD2]], i8** [[TD2_ADDR:%[^,]+]],
-// CHECK-NEXT: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* @0, i32 5, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, i64, i16*, i8**, i8**)* [[OMP_PARALLEL:@.+]] to void (i32*, i32*, ...)*), i32* %{{.+}}, i64 %{{.+}}, i16* %{{.+}}, i8** [[TD1_ADDR]], i8** [[TD2_ADDR]])
-// CHECK-NEXT: call void @__kmpc_end_taskgroup(%ident_t* @0, i32 [[GTID]])
-// CHECK-NEXT: call void @__kmpc_end_taskgroup(%ident_t* @0, i32 [[GTID]])
+// CHECK-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @0, i32 5, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, i64, i16*, i8**, i8**)* [[OMP_PARALLEL:@.+]] to void (i32*, i32*, ...)*), i32* %{{.+}}, i64 %{{.+}}, i16* %{{.+}}, i8** [[TD1_ADDR]], i8** [[TD2_ADDR]])
+// CHECK-NEXT: call void @__kmpc_end_taskgroup(%struct.ident_t* @0, i32 [[GTID]])
+// CHECK-NEXT: call void @__kmpc_end_taskgroup(%struct.ident_t* @0, i32 [[GTID]])
// CHECK: define internal void [[OMP_PARALLEL]](
-// CHECK: [[TASK_T:%.+]] = call i8* @__kmpc_omp_task_alloc(%ident_t* @0, i32 [[GTID:%.+]], i32 1, i64 96, i64 40, i32 (i32, i8*)* bitcast (i32 (i32, [[T:%.+]]*)* [[OMP_TASK:@.+]] to i32 (i32, i8*)*))
+// CHECK: [[TASK_T:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* @0, i32 [[GTID:%.+]], i32 1, i64 96, i64 40, i32 (i32, i8*)* bitcast (i32 (i32, [[T:%.+]]*)* [[OMP_TASK:@.+]] to i32 (i32, i8*)*))
// CHECK-NEXT: [[TASK_T_WITH_PRIVS:%.+]] = bitcast i8* [[TASK_T]] to [[T]]*
// CHECK: [[PRIVS:%.+]] = getelementptr inbounds [[T]], [[T]]* [[TASK_T_WITH_PRIVS]], i32 0, i32 1
// CHECK: [[TD1_REF:%.+]] = getelementptr inbounds [[PRIVATES]], [[PRIVATES]]* [[PRIVS]], i32 0, i32 0
@@ -58,7 +63,7 @@ int main(int argc, char **argv) {
// CHECK-NEXT: [[TD2_ADDR:%.+]] = load i8**, i8*** [[TD2_SHAR]],
// CHECK-NEXT: [[TD2:%.+]] = load i8*, i8** [[TD2_ADDR]],
// CHECK-NEXT: store i8* [[TD2]], i8** [[TD2_REF]],
-// CHECK: call void @__kmpc_taskloop(%ident_t* @0, i32 [[GTID]], i8* [[TASK_T]], i32 1,
+// CHECK: call void @__kmpc_taskloop(%struct.ident_t* @0, i32 [[GTID]], i8* [[TASK_T]], i32 1,
// CHECK: ret void
// CHECK-NEXT: }
diff --git a/test/OpenMP/taskloop_simd_in_reduction_messages.cpp b/test/OpenMP/taskloop_simd_in_reduction_messages.cpp
index f3b1a855e320..ee3d09376610 100644
--- a/test/OpenMP/taskloop_simd_in_reduction_messages.cpp
+++ b/test/OpenMP/taskloop_simd_in_reduction_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 150 -o - %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 150 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/taskloop_simd_lastprivate_codegen.cpp b/test/OpenMP/taskloop_simd_lastprivate_codegen.cpp
index 8d5ebb216808..be484465e3ae 100644
--- a/test/OpenMP/taskloop_simd_lastprivate_codegen.cpp
+++ b/test/OpenMP/taskloop_simd_lastprivate_codegen.cpp
@@ -4,6 +4,14 @@
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=ARRAY %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
// It doesn't pass on win32.
// REQUIRES: shell
@@ -190,7 +198,7 @@ int main() {
// CHECK: [[SHAREDS_REF_ADDR:%.+]] = getelementptr inbounds [[KMP_TASK_T_TY]], [[KMP_TASK_T_TY]]* [[TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[SHAREDS_REF:%.+]] = load i8*, i8** [[SHAREDS_REF_ADDR]],
// CHECK: [[CAPTURES_ADDR:%.+]] = bitcast [[CAP_MAIN_TY]]* %{{.+}} to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[SHAREDS_REF]], i8* [[CAPTURES_ADDR]], i64 40, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[SHAREDS_REF]], i8* align 8 [[CAPTURES_ADDR]], i64 40, i1 false)
// Initialize kmp_task_t->privates with default values (no init for simple types, default constructors for classes).
// Also copy address of private copy to the corresponding shareds reference.
@@ -279,18 +287,18 @@ int main() {
// CHECK-NEXT: br i1
// CHECK: bitcast [[S_DOUBLE_TY]]* %{{.+}} to i8*
// CHECK: bitcast [[S_DOUBLE_TY]]* %{{.+}} to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align {{[0-9]+}} %
// CHECK: load i32, i32* %
// CHECK: store i32 %{{.+}}, i32* %
// CHECK: getelementptr inbounds [2 x [[S_DOUBLE_TY]]], [2 x [[S_DOUBLE_TY]]]* %
// CHECK: phi [[S_DOUBLE_TY]]*
// CHECK: phi [[S_DOUBLE_TY]]*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align {{[0-9]+}} %
// CHECK: icmp eq [[S_DOUBLE_TY]]* %
// CHECK-NEXT: br i1
// CHECK: bitcast [2 x i32]* %{{.+}} to i8*
// CHECK: bitcast [2 x i32]* %{{.+}} to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align {{[0-9]+}} %
// CHECK: load i32, i32* %
// CHECK: store i32 %{{.+}}, i32* %
// CHECK: br label
@@ -364,7 +372,7 @@ int main() {
// CHECK: [[SHAREDS_REF_ADDR:%.+]] = getelementptr inbounds [[KMP_TASK_T_TY]], [[KMP_TASK_T_TY]]* [[TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[SHAREDS_REF:%.+]] = load i8*, i8** [[SHAREDS_REF_ADDR]],
// CHECK: [[CAPTURES_ADDR:%.+]] = bitcast [[CAP_TMAIN_TY]]* %{{.+}} to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[SHAREDS_REF]], i8* [[CAPTURES_ADDR]], i64 32, i32 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[SHAREDS_REF]], i8* align 8 [[CAPTURES_ADDR]], i64 32, i1 false)
// Initialize kmp_task_t->privates with default values (no init for simple types, default constructors for classes).
// CHECK: [[PRIVATES:%.+]] = getelementptr inbounds [[KMP_TASK_TMAIN_TY]], [[KMP_TASK_TMAIN_TY]]* [[RES_KMP_TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 2
@@ -445,16 +453,16 @@ int main() {
// CHECK: store i32 %{{.+}}, i32* %
// CHECK: bitcast [2 x i32]* %{{.+}} to i8*
// CHECK: bitcast [2 x i32]* %{{.+}} to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align {{[0-9]+}} %
// CHECK: getelementptr inbounds [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* %
// CHECK: phi [[S_INT_TY]]*
// CHECK: phi [[S_INT_TY]]*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align {{[0-9]+}} %
// CHECK: icmp eq [[S_INT_TY]]* %
// CHECK-NEXT: br i1
// CHECK: bitcast [[S_INT_TY]]* %{{.+}} to i8*
// CHECK: bitcast [[S_INT_TY]]* %{{.+}} to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align {{[0-9]+}} %
// CHECK: br label
// CHECK: ret
diff --git a/test/OpenMP/taskloop_simd_lastprivate_messages.cpp b/test/OpenMP/taskloop_simd_lastprivate_messages.cpp
index e5cba6c64b6b..8f418ff3b883 100644
--- a/test/OpenMP/taskloop_simd_lastprivate_messages.cpp
+++ b/test/OpenMP/taskloop_simd_lastprivate_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/taskloop_simd_linear_messages.cpp b/test/OpenMP/taskloop_simd_linear_messages.cpp
index c9a82b9dc148..2aea6a041fce 100644
--- a/test/OpenMP/taskloop_simd_linear_messages.cpp
+++ b/test/OpenMP/taskloop_simd_linear_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
namespace X {
int x;
};
diff --git a/test/OpenMP/taskloop_simd_loop_messages.cpp b/test/OpenMP/taskloop_simd_loop_messages.cpp
index 502224629a56..71aa9dfe1143 100644
--- a/test/OpenMP/taskloop_simd_loop_messages.cpp
+++ b/test/OpenMP/taskloop_simd_loop_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+
class S {
int a;
S() : a(0) {}
diff --git a/test/OpenMP/taskloop_simd_misc_messages.c b/test/OpenMP/taskloop_simd_misc_messages.c
index 35cc62cad585..bb4b2dfbb85e 100644
--- a/test/OpenMP/taskloop_simd_misc_messages.c
+++ b/test/OpenMP/taskloop_simd_misc_messages.c
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -triple x86_64-unknown-unknown -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -triple x86_64-unknown-unknown -verify %s
+
// expected-error@+1 {{unexpected OpenMP directive '#pragma omp taskloop simd'}}
#pragma omp taskloop simd
diff --git a/test/OpenMP/taskloop_simd_num_tasks_messages.cpp b/test/OpenMP/taskloop_simd_num_tasks_messages.cpp
index f26ee79a8740..3267d294b756 100644
--- a/test/OpenMP/taskloop_simd_num_tasks_messages.cpp
+++ b/test/OpenMP/taskloop_simd_num_tasks_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/taskloop_simd_priority_messages.cpp b/test/OpenMP/taskloop_simd_priority_messages.cpp
index a94798f821a6..44e0b57a00d3 100644
--- a/test/OpenMP/taskloop_simd_priority_messages.cpp
+++ b/test/OpenMP/taskloop_simd_priority_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/taskloop_simd_private_codegen.cpp b/test/OpenMP/taskloop_simd_private_codegen.cpp
index 3833b5ea9fb3..fd0820ad84a6 100644
--- a/test/OpenMP/taskloop_simd_private_codegen.cpp
+++ b/test/OpenMP/taskloop_simd_private_codegen.cpp
@@ -4,6 +4,14 @@
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=ARRAY %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
// It doesn't pass on win32. Investigating.
// REQUIRES: shell
diff --git a/test/OpenMP/taskloop_simd_private_messages.cpp b/test/OpenMP/taskloop_simd_private_messages.cpp
index ba9e8da17e20..68e536525122 100644
--- a/test/OpenMP/taskloop_simd_private_messages.cpp
+++ b/test/OpenMP/taskloop_simd_private_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/taskloop_simd_reduction_codegen.cpp b/test/OpenMP/taskloop_simd_reduction_codegen.cpp
index 7e8d54a2a1da..6c34e34ca584 100644
--- a/test/OpenMP/taskloop_simd_reduction_codegen.cpp
+++ b/test/OpenMP/taskloop_simd_reduction_codegen.cpp
@@ -1,4 +1,7 @@
// RUN: %clang_cc1 -fopenmp -x c++ %s -verify -debug-info-kind=limited -emit-llvm -o - -triple powerpc64le-unknown-linux-gnu -std=c++98 | FileCheck %s
+
+// RUN: %clang_cc1 -fopenmp-simd -x c++ %s -verify -debug-info-kind=limited -emit-llvm -o - -triple powerpc64le-unknown-linux-gnu -std=c++98 | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
struct S {
@@ -49,7 +52,7 @@ sum = 0.0;
// CHECK: [[C:%.*]] = alloca [100 x %struct.S],
// CHECK: [[D:%.*]] = alloca float*,
// CHECK: [[AGG_CAPTURED:%.*]] = alloca [[STRUCT_ANON:%.*]],
-// CHECK: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(%ident_t*
+// CHECK: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t*
// CHECK: [[DOTRD_INPUT_:%.*]] = alloca [4 x %struct.kmp_task_red_input_t],
// CHECK: alloca i32,
// CHECK: [[DOTCAPTURE_EXPR_:%.*]] = alloca i32,
@@ -62,21 +65,21 @@ sum = 0.0;
// CHECK: [[TMP2:%.*]] = zext i32 [[ADD]] to i64
// CHECK: [[VLA:%.+]] = alloca float, i64 %
-// CHECK: call void @__kmpc_taskgroup(%ident_t*
+// CHECK: call void @__kmpc_taskgroup(%struct.ident_t*
// CHECK-DAG: [[TMP21:%.*]] = bitcast float* [[SUM]] to i8*
// CHECK-DAG: store i8* [[TMP21]], i8** [[TMP20:%[^,]+]],
// CHECK-DAG: [[TMP20]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T:%.+]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_:%.+]], i32 0, i32 0
// CHECK-DAG: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_]], i32 0, i32 1
// CHECK-DAG: store i64 4, i64* [[TMP22]],
// CHECK-DAG: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_]], i32 0, i32 2
-// CHECK-DAG: store i8* bitcast (void (i8*)* [[RED_INIT1:@.+]] to i8*), i8** [[TMP23]],
+// CHECK-DAG: store i8* bitcast (void (i8*)* @[[RED_INIT1:.+]] to i8*), i8** [[TMP23]],
// CHECK-DAG: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_]], i32 0, i32 3
// CHECK-DAG: store i8* null, i8** [[TMP24]],
// CHECK-DAG: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_]], i32 0, i32 4
-// CHECK-DAG: store i8* bitcast (void (i8*, i8*)* [[RED_COMB1:@.+]] to i8*), i8** [[TMP25]],
+// CHECK-DAG: store i8* bitcast (void (i8*, i8*)* @[[RED_COMB1:.+]] to i8*), i8** [[TMP25]],
// CHECK-DAG: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_]], i32 0, i32 5
// CHECK-DAG: [[TMP27:%.*]] = bitcast i32* [[TMP26]] to i8*
-// CHECK-DAG: call void @llvm.memset.p0i8.i64(i8* [[TMP27]], i8 0, i64 4, i32 8, i1 false)
+// CHECK-DAG: call void @llvm.memset.p0i8.i64(i8* align 8 [[TMP27]], i8 0, i64 4, i1 false)
// CHECK-DAG: [[ARRAYIDX5:%.*]] = getelementptr inbounds [100 x %struct.S], [100 x %struct.S]* [[C]], i64 0, i64 0
// CHECK-DAG: [[LB_ADD_LEN:%.*]] = add nsw i64 -1, %
// CHECK-DAG: [[ARRAYIDX6:%.*]] = getelementptr inbounds [100 x %struct.S], [100 x %struct.S]* [[C]], i64 0, i64 [[LB_ADD_LEN]]
@@ -92,11 +95,11 @@ sum = 0.0;
// CHECK-DAG: store i64 [[TMP37]], i64* [[TMP38:%[^,]+]],
// CHECK-DAG: [[TMP38]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_4]], i32 0, i32 1
// CHECK-DAG: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_4]], i32 0, i32 2
-// CHECK-DAG: store i8* bitcast (void (i8*)* [[RED_INIT2:@.+]] to i8*), i8** [[TMP39]],
+// CHECK-DAG: store i8* bitcast (void (i8*)* @[[RED_INIT2:.+]] to i8*), i8** [[TMP39]],
// CHECK-DAG: [[TMP40:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_4]], i32 0, i32 3
-// CHECK-DAG: store i8* bitcast (void (i8*)* [[RED_FINI2:@.+]] to i8*), i8** [[TMP40]],
+// CHECK-DAG: store i8* bitcast (void (i8*)* @[[RED_FINI2:.+]] to i8*), i8** [[TMP40]],
// CHECK-DAG: [[TMP41:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_4]], i32 0, i32 4
-// CHECK-DAG: store i8* bitcast (void (i8*, i8*)* [[RED_COMB2:@.+]] to i8*), i8** [[TMP41]],
+// CHECK-DAG: store i8* bitcast (void (i8*, i8*)* @[[RED_COMB2:.+]] to i8*), i8** [[TMP41]],
// CHECK-DAG: [[TMP42:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_4]], i32 0, i32 5
// CHECK-DAG: store i32 1, i32* [[TMP42]],
// CHECK-DAG: [[TMP44:%.*]] = load float*, float** [[D]],
@@ -106,14 +109,14 @@ sum = 0.0;
// CHECK-DAG: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_7]], i32 0, i32 1
// CHECK-DAG: store i64 4, i64* [[TMP46]],
// CHECK-DAG: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_7]], i32 0, i32 2
-// CHECK-DAG: store i8* bitcast (void (i8*)* [[RED_INIT3:@.+]] to i8*), i8** [[TMP47]],
+// CHECK-DAG: store i8* bitcast (void (i8*)* @[[RED_INIT3:.+]] to i8*), i8** [[TMP47]],
// CHECK-DAG: [[TMP48:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_7]], i32 0, i32 3
// CHECK-DAG: store i8* null, i8** [[TMP48]],
// CHECK-DAG: [[TMP49:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_7]], i32 0, i32 4
-// CHECK-DAG: store i8* bitcast (void (i8*, i8*)* [[RED_COMB3:@.+]] to i8*), i8** [[TMP49]],
+// CHECK-DAG: store i8* bitcast (void (i8*, i8*)* @[[RED_COMB3:.+]] to i8*), i8** [[TMP49]],
// CHECK-DAG: [[TMP50:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_7]], i32 0, i32 5
// CHECK-DAG: [[TMP51:%.*]] = bitcast i32* [[TMP50]] to i8*
-// CHECK-DAG: call void @llvm.memset.p0i8.i64(i8* [[TMP51]], i8 0, i64 4, i32 8, i1 false)
+// CHECK-DAG: call void @llvm.memset.p0i8.i64(i8* align 8 [[TMP51]], i8 0, i64 4, i1 false)
// CHECK-DAG: [[TMP53:%.*]] = bitcast float* [[VLA]] to i8*
// CHECK-DAG: store i8* [[TMP53]], i8** [[TMP52:%[^,]+]],
// CHECK-DAG: [[TMP52]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_8:%.+]], i32 0, i32 0
@@ -122,11 +125,11 @@ sum = 0.0;
// CHECK-DAG: store i64 [[TMP54]], i64* [[TMP56:%[^,]+]],
// CHECK-DAG: [[TMP56]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_8]], i32 0, i32 1
// CHECK-DAG: [[TMP57:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_8]], i32 0, i32 2
-// CHECK-DAG: store i8* bitcast (void (i8*)* [[RED_INIT4:@.+]] to i8*), i8** [[TMP57]],
+// CHECK-DAG: store i8* bitcast (void (i8*)* @[[RED_INIT4:.+]] to i8*), i8** [[TMP57]],
// CHECK-DAG: [[TMP58:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_8]], i32 0, i32 3
// CHECK-DAG: store i8* null, i8** [[TMP58]],
// CHECK-DAG: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_8]], i32 0, i32 4
-// CHECK-DAG: store i8* bitcast (void (i8*, i8*)* [[RED_COMB4:@.+]] to i8*), i8** [[TMP59]],
+// CHECK-DAG: store i8* bitcast (void (i8*, i8*)* @[[RED_COMB4:.+]] to i8*), i8** [[TMP59]],
// CHECK-DAG: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_RED_INPUT_T]], %struct.kmp_task_red_input_t* [[DOTRD_INPUT_GEP_8]], i32 0, i32 5
// CHECK-DAG: store i32 1, i32* [[TMP60]],
// CHECK-DAG: [[DOTRD_INPUT_GEP_]] = getelementptr inbounds [4 x %struct.kmp_task_red_input_t], [4 x %struct.kmp_task_red_input_t]* [[DOTRD_INPUT_]], i64 0, i64
@@ -144,55 +147,64 @@ sum = 0.0;
// CHECK: [[DIV:%.*]] = sdiv i32 [[ADD11]], 1
// CHECK: [[SUB12:%.*]] = sub nsw i32 [[DIV]], 1
// CHECK: store i32 [[SUB12]], i32* [[DOTCAPTURE_EXPR_9]],
-// CHECK: [[TMP65:%.*]] = call i8* @__kmpc_omp_task_alloc(%ident_t* %{{.+}}, i32 [[TMP0]], i32 1, i64 888, i64 72, i32 (i32, i8*)* bitcast (i32 (i32, %struct.kmp_task_t_with_privates*)* @{{.+}} to i32 (i32, i8*)*))
-// CHECK: call void @__kmpc_taskloop(%ident_t* %{{.+}}, i32 [[TMP0]], i8* [[TMP65]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 0, i32 0, i64 0, i8* null)
-// CHECK: call void @__kmpc_end_taskgroup(%ident_t*
+// CHECK: [[TMP65:%.*]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* %{{.+}}, i32 [[TMP0]], i32 1, i64 888, i64 72, i32 (i32, i8*)* bitcast (i32 (i32, %struct.kmp_task_t_with_privates*)* @{{.+}} to i32 (i32, i8*)*))
+// CHECK: call void @__kmpc_taskloop(%struct.ident_t* %{{.+}}, i32 [[TMP0]], i8* [[TMP65]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 0, i32 0, i64 0, i8* null)
+// CHECK: call void @__kmpc_end_taskgroup(%struct.ident_t*
// CHECK: ret i32
-// CHECK: define internal void [[RED_INIT1]](i8*)
+// CHECK: define internal void @[[RED_INIT1]](i8*)
// CHECK: store float 0.000000e+00, float* %
// CHECK: ret void
-// CHECK: define internal void [[RED_COMB1]](i8*, i8*)
+// CHECK: define internal void @[[RED_COMB1]](i8*, i8*)
// CHECK: fadd float %
// CHECK: store float %{{.+}}, float* %
// CHECK: ret void
-// CHECK: define internal void [[RED_INIT2]](i8*)
+// CHECK: define internal void @[[RED_INIT2]](i8*)
// CHECK: call i8* @__kmpc_threadprivate_cached(
// CHECK: call i8* @__kmpc_threadprivate_cached(
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(
// CHECK: ret void
-// CHECK: define internal void [[RED_FINI2]](i8*)
+// CHECK: define internal void @[[RED_FINI2]](i8*)
// CHECK: call i8* @__kmpc_threadprivate_cached(
// CHECK: call void @
// CHECK: ret void
-// CHECK: define internal void [[RED_COMB2]](i8*, i8*)
+// CHECK: define internal void @[[RED_COMB2]](i8*, i8*)
// CHECK: call i8* @__kmpc_threadprivate_cached(
// CHECK: fadd float %
// CHECK: store float %{{.+}}, float* %
// CHECK: ret void
-// CHECK: define internal void [[RED_INIT3]](i8*)
+// CHECK: define internal void @[[RED_INIT3]](i8*)
// CHECK: store float 0.000000e+00, float* %
// CHECK: ret void
-// CHECK: define internal void [[RED_COMB3]](i8*, i8*)
+// CHECK: define internal void @[[RED_COMB3]](i8*, i8*)
// CHECK: fadd float %
// CHECK: store float %{{.+}}, float* %
// CHECK: ret void
-// CHECK: define internal void [[RED_INIT4]](i8*)
+// CHECK: define internal void @[[RED_INIT4]](i8*)
// CHECK: call i8* @__kmpc_threadprivate_cached(
// CHECK: store float 0.000000e+00, float* %
// CHECK: ret void
-// CHECK: define internal void [[RED_COMB4]](i8*, i8*)
+// CHECK: define internal void @[[RED_COMB4]](i8*, i8*)
// CHECK: call i8* @__kmpc_threadprivate_cached(
// CHECK: fadd float %
// CHECK: store float %{{.+}}, float* %
// CHECK: ret void
+// CHECK-DAG: !DISubprogram(linkageName: "[[RED_INIT1]]"
+// CHECK-DAG: !DISubprogram(linkageName: "[[RED_COMB1]]"
+// CHECK-DAG: !DISubprogram(linkageName: "[[RED_INIT2]]"
+// CHECK-DAG: !DISubprogram(linkageName: "[[RED_FINI2]]"
+// CHECK-DAG: !DISubprogram(linkageName: "[[RED_COMB2]]"
+// CHECK-DAG: !DISubprogram(linkageName: "[[RED_INIT3]]"
+// CHECK-DAG: !DISubprogram(linkageName: "[[RED_COMB3]]"
+// CHECK-DAG: !DISubprogram(linkageName: "[[RED_INIT4]]"
+// CHECK-DAG: !DISubprogram(linkageName: "[[RED_COMB4]]"
diff --git a/test/OpenMP/taskloop_simd_reduction_messages.cpp b/test/OpenMP/taskloop_simd_reduction_messages.cpp
index 886b685f6325..10ee5ce8c83c 100644
--- a/test/OpenMP/taskloop_simd_reduction_messages.cpp
+++ b/test/OpenMP/taskloop_simd_reduction_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 150 -o - %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 150 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/taskloop_simd_safelen_messages.cpp b/test/OpenMP/taskloop_simd_safelen_messages.cpp
index 729f31407bfa..87c4fe07ab02 100644
--- a/test/OpenMP/taskloop_simd_safelen_messages.cpp
+++ b/test/OpenMP/taskloop_simd_safelen_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/taskloop_simd_simdlen_messages.cpp b/test/OpenMP/taskloop_simd_simdlen_messages.cpp
index 79655ba9c275..4170d012dd5d 100644
--- a/test/OpenMP/taskloop_simd_simdlen_messages.cpp
+++ b/test/OpenMP/taskloop_simd_simdlen_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/taskwait_ast_print.cpp b/test/OpenMP/taskwait_ast_print.cpp
index 1a69b58a37ba..9cbc46ef29f9 100644
--- a/test/OpenMP/taskwait_ast_print.cpp
+++ b/test/OpenMP/taskwait_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -15,7 +19,7 @@ T tmain(T argc) {
return a + argc;
}
// CHECK: static T a;
-// CHECK-NEXT: #pragma omp taskwait
+// CHECK-NEXT: #pragma omp taskwait{{$}}
// CHECK: static int a;
// CHECK-NEXT: #pragma omp taskwait
// CHECK: static char a;
diff --git a/test/OpenMP/taskwait_codegen.cpp b/test/OpenMP/taskwait_codegen.cpp
index 492786eb8058..22f381b35199 100644
--- a/test/OpenMP/taskwait_codegen.cpp
+++ b/test/OpenMP/taskwait_codegen.cpp
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -x c++ -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -x c++ -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/taskwait_messages.cpp b/test/OpenMP/taskwait_messages.cpp
index 06e8e6b8bdf2..46efff5972e8 100644
--- a/test/OpenMP/taskwait_messages.cpp
+++ b/test/OpenMP/taskwait_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
template <class T>
T tmain(T argc) {
#pragma omp taskwait
diff --git a/test/OpenMP/taskyield_ast_print.cpp b/test/OpenMP/taskyield_ast_print.cpp
index 1fd9b9c14d4e..7acf53dd6afe 100644
--- a/test/OpenMP/taskyield_ast_print.cpp
+++ b/test/OpenMP/taskyield_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -15,7 +19,7 @@ T tmain(T argc) {
return a + argc;
}
// CHECK: static T a;
-// CHECK-NEXT: #pragma omp taskyield
+// CHECK-NEXT: #pragma omp taskyield{{$}}
// CHECK: static int a;
// CHECK-NEXT: #pragma omp taskyield
// CHECK: static char a;
diff --git a/test/OpenMP/taskyield_codegen.cpp b/test/OpenMP/taskyield_codegen.cpp
index 80b65bff5e49..d57071f48aa8 100644
--- a/test/OpenMP/taskyield_codegen.cpp
+++ b/test/OpenMP/taskyield_codegen.cpp
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-unknown -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/taskyield_messages.cpp b/test/OpenMP/taskyield_messages.cpp
index cfeaa63815b3..fd98a8786f18 100644
--- a/test/OpenMP/taskyield_messages.cpp
+++ b/test/OpenMP/taskyield_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
template <class T>
T tmain(T argc) {
#pragma omp taskyield
diff --git a/test/OpenMP/teams_ast_print.cpp b/test/OpenMP/teams_ast_print.cpp
index 861b25da34a3..80300bfd4f10 100644
--- a/test/OpenMP/teams_ast_print.cpp
+++ b/test/OpenMP/teams_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -50,7 +54,7 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: static T a;
// CHECK-NEXT: S<T> s;
// CHECK-NEXT: #pragma omp target
-// CHECK-NEXT: #pragma omp teams
+// CHECK-NEXT: #pragma omp teams{{$}}
// CHECK-NEXT: a = 2;
// CHECK-NEXT: #pragma omp target
// CHECK-NEXT: #pragma omp teams default(none) private(argc,b) firstprivate(argv) shared(d) reduction(+: c) reduction(max: e) num_teams(C) thread_limit(d * C)
diff --git a/test/OpenMP/teams_codegen.cpp b/test/OpenMP/teams_codegen.cpp
index 28f6ca0714d4..057c55788319 100644
--- a/test/OpenMP/teams_codegen.cpp
+++ b/test/OpenMP/teams_codegen.cpp
@@ -8,6 +8,14 @@
// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
#ifdef CK1
int Gbla;
@@ -105,6 +113,14 @@ int teams_argument_global_local(int a){
// RUN: %clang_cc1 -DCK2 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
#ifdef CK2
// CK2-DAG: [[SSI:%.+]] = type { i32, float }
@@ -168,6 +184,14 @@ int teams_template_arg(void) {
// RUN: %clang_cc1 -DCK3 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-32
// RUN: %clang_cc1 -DCK3 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK3 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-32
+
+// RUN: %clang_cc1 -DCK3 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// RUN: %clang_cc1 -DCK3 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK3 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// RUN: %clang_cc1 -DCK3 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// RUN: %clang_cc1 -DCK3 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK3 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// SIMD-ONLY2-NOT: {{__kmpc|__tgt}}
#ifdef CK3
// CK3: [[SSI:%.+]] = type { i32, float }
@@ -181,7 +205,7 @@ struct SS{
int foo(void) {
int comp = 1;
- // CK3-DAG: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 2, i8** %{{[^,]+}}, i8** %{{[^,]+}}, i{{64|32}}* {{.+}}@{{[^,]+}}, i32 0, i32 0), i64* {{.+}}@{{[^,]+}}, i32 0, i32 0), i32 [[NT:%[^,]+]], i32 123)
+ // CK3-DAG: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 3, i8** %{{[^,]+}}, i8** %{{[^,]+}}, i{{64|32}}* %{{[^,]+}}, i64* {{.+}}@{{[^,]+}}, i32 0, i32 0), i32 [[NT:%[^,]+]], i32 123)
// CK3-DAG: [[NT]] = load i32, i32* [[NTA:%[^,]+]],
// CK3-DAG: [[NTA]] = getelementptr inbounds [[SSI]], [[SSI]]* [[NTB:%[^,]+]], i32 0, i32 0
@@ -194,7 +218,7 @@ struct SS{
++comp;
}
- // CK3-DAG: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 2, i8** %{{[^,]+}}, i8** %{{[^,]+}}, i{{64|32}}* {{.+}}@{{[^,]+}}, i32 0, i32 0), i64* {{.+}}@{{[^,]+}}, i32 0, i32 0), i32 456, i32 [[TL:%[^,]+]])
+ // CK3-DAG: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 3, i8** %{{[^,]+}}, i8** %{{[^,]+}}, i{{64|32}}* %{{[^,]+}}, i64* {{.+}}@{{[^,]+}}, i32 0, i32 0), i32 456, i32 [[TL:%[^,]+]])
// CK3-DAG: [[TL]] = add nsw i32 [[TLA:%[^,]+]], 123
// CK3-DAG: [[TLA]] = fptosi float [[TLB:%[^,]+]] to i32
@@ -228,11 +252,21 @@ int teams_template_struct(void) {
// RUN: %clang_cc1 -DCK4 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
// RUN: %clang_cc1 -DCK4 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK4 --check-prefix CK4-32
+// RUN: %clang_cc1 -DCK4 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -DCK4 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY3 %s
+// RUN: %clang_cc1 -DCK4 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -DCK4 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY3 %s
+// RUN: %clang_cc1 -DCK4 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -DCK4 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY3 %s
+// RUN: %clang_cc1 -DCK4 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -DCK4 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY3 %s
+// SIMD-ONLY3-NOT: {{__kmpc|__tgt}}
+
#ifdef CK4
-// CK4-DAG: %ident_t = type { i32, i32, i32, i32, i8* }
+// CK4-DAG: %struct.ident_t = type { i32, i32, i32, i32, i8* }
// CK4-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CK4-DAG: [[DEF_LOC_0:@.+]] = private unnamed_addr constant %ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CK4-DAG: [[DEF_LOC_0:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
// CK4-DEBUG-DAG: [[LOC1:@.+]] = private unnamed_addr constant [{{.+}} x i8] c";{{.*}}teams_codegen.cpp;main;[[@LINE+14]];9;;\00"
// CK4-DEBUG-DAG: [[LOC2:@.+]] = private unnamed_addr constant [{{.+}} x i8] c";{{.*}}teams_codegen.cpp;tmain;[[@LINE+7]];9;;\00"
@@ -255,15 +289,15 @@ int main (int argc, char **argv) {
// CK4: [[ARGCADDR:%.+]] = alloca i{{.+}}
// CK4: store i{{.+}} %[[ARGC]], i{{.+}}* [[ARGCADDR]]
// CK4-64: [[CONV:%.+]] = bitcast i64* [[ARGCADDR]] to i32*
-// CK4-64: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC_0]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*)* {{.+}} to void (i32*, i32*, ...)*), i32* [[CONV]])
-// CK4-32: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC_0]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*)* {{.+}} to void (i32*, i32*, ...)*), i32* [[ARGCADDR]])
+// CK4-64: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC_0]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*)* {{.+}} to void (i32*, i32*, ...)*), i32* [[CONV]])
+// CK4-32: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC_0]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*)* {{.+}} to void (i32*, i32*, ...)*), i32* [[ARGCADDR]])
// CK4: ret void
// CK4-NEXT: }
// CK4: define {{.*}}void @{{[^,]+}}(i8** [[ARGC1:%.+]])
// CK4: [[ARGCADDR1:%.+]] = alloca i8**
// CK4: store i8** [[ARGC1]], i8*** [[ARGCADDR1]]
-// CK4: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC_0]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i8***)* {{.+}} to void (i32*, i32*, ...)*), i8*** [[ARGCADDR1]])
+// CK4: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC_0]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i8***)* {{.+}} to void (i32*, i32*, ...)*), i8*** [[ARGCADDR1]])
#endif // CK4
@@ -278,12 +312,22 @@ int main (int argc, char **argv) {
// RUN: %clang_cc1 -DCK5 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
// RUN: %clang_cc1 -DCK5 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK5 --check-prefix CK5-32
+// RUN: %clang_cc1 -DCK5 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -DCK5 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY4 %s
+// RUN: %clang_cc1 -DCK5 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
+// RUN: %clang_cc1 -DCK5 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY4 %s
+// RUN: %clang_cc1 -DCK5 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -DCK5 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY4 %s
+// RUN: %clang_cc1 -DCK5 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
+// RUN: %clang_cc1 -DCK5 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY4 %s
+// SIMD-ONLY4-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifdef CK5
-// CK5-DAG: %ident_t = type { i32, i32, i32, i32, i8* }
+// CK5-DAG: %struct.ident_t = type { i32, i32, i32, i32, i8* }
// CK5-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CK5-DAG: [[DEF_LOC_0:@.+]] = private unnamed_addr constant %ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CK5-DAG: [[DEF_LOC_0:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
// CK5-DEBUG-DAG: [[LOC1:@.+]] = private unnamed_addr constant [{{.+}} x i8] c";{{.*}}teams_codegen.cpp;main;[[@LINE+14]];9;;\00"
// CK5-DEBUG-DAG: [[LOC2:@.+]] = private unnamed_addr constant [{{.+}} x i8] c";{{.*}}teams_codegen.cpp;tmain;[[@LINE+7]];9;;\00"
@@ -314,7 +358,7 @@ int main (int argc, char **argv) {
// CK5: [[AADDR:%.+]] = alloca i{{.+}}
// CK5: [[BADDR:%.+]] = alloca i{{.+}}
// CK5: [[ARGCADDR:%.+]] = alloca i{{.+}}
-// CK5: [[GBL_TH_NUM:%.+]] = call i32 @__kmpc_global_thread_num(%ident_t* [[DEF_LOC_0]])
+// CK5: [[GBL_TH_NUM:%.+]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[DEF_LOC_0]])
// CK5: store i{{.+}} [[AP]], i{{.+}}* [[AADDR]]
// CK5: store i{{.+}} [[BP]], i{{.+}}* [[BADDR]]
// CK5: store i{{.+}} [[ARGC]], i{{.+}}* [[ARGCADDR]]
@@ -325,15 +369,15 @@ int main (int argc, char **argv) {
// CK5-64: [[BCONVVAL:%.+]] = load i32, i32* [[BCONV]]
// CK5-32: [[ACONVVAL:%.+]] = load i32, i32* [[AADDR]]
// CK5-32: [[BCONVVAL:%.+]] = load i32, i32* [[BADDR]]
-// CK5: {{.+}} = call i32 @__kmpc_push_num_teams(%ident_t* [[DEF_LOC_0]], i32 [[GBL_TH_NUM]], i32 [[ACONVVAL]], i32 [[BCONVVAL]])
-// CK5-64: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC_0]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*)* @.omp_outlined. to void (i32*, i32*, ...)*), i32* [[CONV]])
-// CK5-32: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC_0]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*)* @.omp_outlined. to void (i32*, i32*, ...)*), i32* [[ARGCADDR]])
+// CK5: {{.+}} = call i32 @__kmpc_push_num_teams(%struct.ident_t* [[DEF_LOC_0]], i32 [[GBL_TH_NUM]], i32 [[ACONVVAL]], i32 [[BCONVVAL]])
+// CK5-64: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC_0]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*)* @.omp_outlined. to void (i32*, i32*, ...)*), i32* [[CONV]])
+// CK5-32: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC_0]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*)* @.omp_outlined. to void (i32*, i32*, ...)*), i32* [[ARGCADDR]])
// CK5: define {{.*}}void @{{[^,]+}}(i{{.+}} [[AP:%.+]], i{{.+}} [[BP:%.+]], i{{.+}}** [[ARGC:%.+]])
// CK5: [[AADDR:%.+]] = alloca i{{.+}}
// CK5: [[BADDR:%.+]] = alloca i{{.+}}
// CK5: [[ARGCADDR:%.+]] = alloca i{{.+}}**
-// CK5: [[GBL_TH_NUM:%.+]] = call i32 @__kmpc_global_thread_num(%ident_t* [[DEF_LOC_0]])
+// CK5: [[GBL_TH_NUM:%.+]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[DEF_LOC_0]])
// CK5: store i{{.+}} [[AP]], i{{.+}}* [[AADDR]]
// CK5: store i{{.+}} [[BP]], i{{.+}}* [[BADDR]]
// CK5: store i{{.+}}** [[ARGC]], i{{.+}}*** [[ARGCADDR]]
@@ -341,11 +385,11 @@ int main (int argc, char **argv) {
// CK5-64: [[BCONV:%.+]] = bitcast i64* [[BADDR]] to i32*
// CK5-64: [[ACONVVAL:%.+]] = load i32, i32* [[ACONV]]
// CK5-64: [[BCONVVAL:%.+]] = load i32, i32* [[BCONV]]
-// CK5-64: {{.+}} = call i32 @__kmpc_push_num_teams(%ident_t* [[DEF_LOC_0]], i32 [[GBL_TH_NUM]], i32 [[ACONVVAL]], i32 [[BCONVVAL]])
+// CK5-64: {{.+}} = call i32 @__kmpc_push_num_teams(%struct.ident_t* [[DEF_LOC_0]], i32 [[GBL_TH_NUM]], i32 [[ACONVVAL]], i32 [[BCONVVAL]])
// CK5-32: [[A_VAL:%.+]] = load i32, i32* [[AADDR]]
// CK5-32: [[B_VAL:%.+]] = load i32, i32* [[BADDR]]
-// CK5-32: {{.+}} = call i32 @__kmpc_push_num_teams(%ident_t* [[DEF_LOC_0]], i32 [[GBL_TH_NUM]], i32 [[A_VAL]], i32 [[B_VAL]])
-// CK5: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%ident_t* [[DEF_LOC_0]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i{{.+}})* @.omp_outlined.{{.+}} to void (i32*, i32*, ...)*), i{{.+}}*** [[ARGCADDR]])
+// CK5-32: {{.+}} = call i32 @__kmpc_push_num_teams(%struct.ident_t* [[DEF_LOC_0]], i32 [[GBL_TH_NUM]], i32 [[A_VAL]], i32 [[B_VAL]])
+// CK5: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(%struct.ident_t* [[DEF_LOC_0]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i{{.+}})* @.omp_outlined.{{.+}} to void (i32*, i32*, ...)*), i{{.+}}*** [[ARGCADDR]])
// CK5: ret void
// CK5-NEXT: }
diff --git a/test/OpenMP/teams_default_messages.cpp b/test/OpenMP/teams_default_messages.cpp
index 83909ccfe051..daf48ae56204 100644
--- a/test/OpenMP/teams_default_messages.cpp
+++ b/test/OpenMP/teams_default_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -o - %s
+
void foo();
int main(int argc, char **argv) {
diff --git a/test/OpenMP/teams_distribute_ast_print.cpp b/test/OpenMP/teams_distribute_ast_print.cpp
index f465c3f8e30b..ef07d51b5a9d 100644
--- a/test/OpenMP/teams_distribute_ast_print.cpp
+++ b/test/OpenMP/teams_distribute_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -96,7 +100,7 @@ T tmain(T argc) {
for (int i=0; i < 2; ++i)
a = 2;
// CHECK: #pragma omp target
-// CHECK-NEXT: #pragma omp teams distribute
+// CHECK-NEXT: #pragma omp teams distribute{{$}}
// CHECK-NEXT: for (int i = 0; i < 2; ++i)
// CHECK-NEXT: a = 2;
#pragma omp target
diff --git a/test/OpenMP/teams_distribute_codegen.cpp b/test/OpenMP/teams_distribute_codegen.cpp
index 8a2afbd4341d..0f6b5f2f25e1 100644
--- a/test/OpenMP/teams_distribute_codegen.cpp
+++ b/test/OpenMP/teams_distribute_codegen.cpp
@@ -8,6 +8,14 @@
// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
#ifdef CK1
int a[100];
@@ -86,6 +94,14 @@ int teams_argument_global(int n){
// RUN: %clang_cc1 -DCK2 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
#ifdef CK2
// CK2: define {{.*}}i32 @{{.+}}teams_local_argv(
@@ -122,6 +138,14 @@ int teams_local_arg(void) {
// RUN: %clang_cc1 -DCK3 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-32
// RUN: %clang_cc1 -DCK3 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK3 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-32
+
+// RUN: %clang_cc1 -DCK3 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// RUN: %clang_cc1 -DCK3 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK3 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// RUN: %clang_cc1 -DCK3 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// RUN: %clang_cc1 -DCK3 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK3 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// SIMD-ONLY2-NOT: {{__kmpc|__tgt}}
#ifdef CK3
// CK3: [[SSI:%.+]] = type { [{{.+}} x i32], float }
@@ -170,6 +194,14 @@ int teams_template_struct(void) {
// RUN: %clang_cc1 -DCK4 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK4 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK4 --check-prefix CK4-32
+// RUN: %clang_cc1 -DCK4 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY3 %s
+// RUN: %clang_cc1 -DCK4 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK4 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY3 %s
+// RUN: %clang_cc1 -DCK4 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY3 %s
+// RUN: %clang_cc1 -DCK4 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK4 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY3 %s
+// SIMD-ONLY3-NOT: {{__kmpc|__tgt}}
+
#ifdef CK4
template <typename T, int n>
diff --git a/test/OpenMP/teams_distribute_collapse_codegen.cpp b/test/OpenMP/teams_distribute_collapse_codegen.cpp
index a65c0a2e63f7..716e76692913 100644
--- a/test/OpenMP/teams_distribute_collapse_codegen.cpp
+++ b/test/OpenMP/teams_distribute_collapse_codegen.cpp
@@ -9,6 +9,14 @@
// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
#ifdef CK1
template <typename T, int X, long long Y>
@@ -61,6 +69,14 @@ int teams_template_struct(void) {
// RUN: %clang_cc1 -DCK2 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
#ifdef CK2
template <typename T, int n, int m>
diff --git a/test/OpenMP/teams_distribute_collapse_messages.cpp b/test/OpenMP/teams_distribute_collapse_messages.cpp
index 37c10e5986bf..bcbd774e8ea1 100644
--- a/test/OpenMP/teams_distribute_collapse_messages.cpp
+++ b/test/OpenMP/teams_distribute_collapse_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp %s -std=c++98
// RUN: %clang_cc1 -verify -fopenmp %s -std=c++11
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -std=c++98
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -std=c++11
+
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_default_messages.cpp b/test/OpenMP/teams_distribute_default_messages.cpp
index bf62930825d9..5e8702a99d97 100644
--- a/test/OpenMP/teams_distribute_default_messages.cpp
+++ b/test/OpenMP/teams_distribute_default_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo();
int main(int argc, char **argv) {
diff --git a/test/OpenMP/teams_distribute_dist_schedule_codegen.cpp b/test/OpenMP/teams_distribute_dist_schedule_codegen.cpp
index 8bd8825e00c4..97ae3871111d 100644
--- a/test/OpenMP/teams_distribute_dist_schedule_codegen.cpp
+++ b/test/OpenMP/teams_distribute_dist_schedule_codegen.cpp
@@ -9,6 +9,14 @@
// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
#ifdef CK1
template <typename T, int X, long long Y>
@@ -84,6 +92,14 @@ int teams_template_struct(void) {
// RUN: %clang_cc1 -DCK2 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
#ifdef CK2
template <typename T, int n>
diff --git a/test/OpenMP/teams_distribute_dist_schedule_messages.cpp b/test/OpenMP/teams_distribute_dist_schedule_messages.cpp
index d86722dd277d..a86a87a9ef51 100644
--- a/test/OpenMP/teams_distribute_dist_schedule_messages.cpp
+++ b/test/OpenMP/teams_distribute_dist_schedule_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_firstprivate_codegen.cpp b/test/OpenMP/teams_distribute_firstprivate_codegen.cpp
index a126b1d16b77..562e986df034 100644
--- a/test/OpenMP/teams_distribute_firstprivate_codegen.cpp
+++ b/test/OpenMP/teams_distribute_firstprivate_codegen.cpp
@@ -1,13 +1,26 @@
-// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
-// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
-
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
@@ -206,8 +219,8 @@ int main() {
// CHECK: store i{{[0-9]+}} {{.+}}, i{{[0-9]+}}* [[SIVAR_ADDR]],
// T_VAR and SIVAR
-// CHECK-DAG-64: [[CONV_TVAR:%.+]] = bitcast i64* [[T_VAR_ADDR]] to i32*
-// CHECK-DAG-64: [[CONV_SIVAR:%.+]] = bitcast i64* [[SIVAR_ADDR]] to i32*
+// CHECK-64-DAG: [[CONV_TVAR:%.+]] = bitcast i64* [[T_VAR_ADDR]] to i32*
+// CHECK-64-DAG: [[CONV_SIVAR:%.+]] = bitcast i64* [[SIVAR_ADDR]] to i32*
// preparation vars
// CHECK-DAG: [[VEC_ADDR_VAL:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]],
@@ -217,7 +230,7 @@ int main() {
// firstprivate vec(vec): copy from *_addr into priv1 and then from priv1 into priv2
// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VEC_DEST_PRIV]], i8* [[VEC_SRC]], {{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST_PRIV]], i8* align {{[0-9]+}} [[VEC_SRC]], {{.+}})
// firstprivate(s_arr)
// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]],
@@ -237,13 +250,13 @@ int main() {
// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]])
// CHECK: call void @__kmpc_for_static_init_4(
-// CHECK-DAG-32: {{.+}} = {{.+}} [[T_VAR_ADDR]]
-// CHECK-DAG-64: {{.+}} = {{.+}} [[CONV_TVAR]]
+// CHECK-32-DAG: {{.+}} = {{.+}} [[T_VAR_ADDR]]
+// CHECK-64-DAG: {{.+}} = {{.+}} [[CONV_TVAR]]
// CHECK-DAG: {{.+}} = {{.+}} [[VEC_PRIV]]
// CHECK-DAG: {{.+}} = {{.+}} [[S_ARR_PRIV]]
// CHECK-DAG: {{.+}} = {{.+}} [[VAR_PRIV]]
-// CHECK-DAG-32: {{.+}} = {{.+}} [[SIVAR_ADDR]]
-// CHECK-DAG-64: {{.+}} = {{.+}} [[CONV_SIVAR]]
+// CHECK-32-DAG: {{.+}} = {{.+}} [[SIVAR_ADDR]]
+// CHECK-64-DAG: {{.+}} = {{.+}} [[CONV_SIVAR]]
// CHECK: call void @__kmpc_for_static_fini(
// CHECK: ret void
@@ -303,7 +316,7 @@ int main() {
// firstprivate vec(vec): copy from *_addr into priv1 and then from priv1 into priv2
// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VEC_DEST_PRIV]], i8* [[VEC_SRC]], {{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST_PRIV]], i8* align {{[0-9]+}} [[VEC_SRC]], {{.+}})
// firstprivate(s_arr)
// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_PRIV]],
@@ -325,8 +338,8 @@ int main() {
// CHECK-DAG: store [[S_INT_TY]]* [[VAR_PRIV]], [[S_INT_TY]]** [[TMP]],
// CHECK: call void @__kmpc_for_static_init_4(
-// CHECK-DAG-32: {{.+}} = {{.+}} [[T_VAR_ADDR]]
-// CHECK-DAG-64: {{.+}} = {{.+}} [[CONV_TVAR]]
+// CHECK-32-DAG: {{.+}} = {{.+}} [[T_VAR_ADDR]]
+// CHECK-64-DAG: {{.+}} = {{.+}} [[CONV_TVAR]]
// CHECK-DAG: {{.+}} = {{.+}} [[VEC_PRIV]]
// CHECK-DAG: {{.+}} = {{.+}} [[TMP]]
// CHECK-DAG: {{.+}} = {{.+}} [[S_ARR_PRIV]]
diff --git a/test/OpenMP/teams_distribute_firstprivate_messages.cpp b/test/OpenMP/teams_distribute_firstprivate_messages.cpp
index 1a2b5f3782f9..e373a3a87005 100644
--- a/test/OpenMP/teams_distribute_firstprivate_messages.cpp
+++ b/test/OpenMP/teams_distribute_firstprivate_messages.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wno-openmp-target
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_lastprivate_codegen.cpp b/test/OpenMP/teams_distribute_lastprivate_codegen.cpp
index 2eab60b9dd3c..883234185aae 100644
--- a/test/OpenMP/teams_distribute_lastprivate_codegen.cpp
+++ b/test/OpenMP/teams_distribute_lastprivate_codegen.cpp
@@ -1,16 +1,32 @@
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -231,7 +247,7 @@ int main() {
// CHECK-DAG: [[TMP_VAL:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP_PRIV]],
// CHECK-DAG: [[S_ARR_PTR_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_PTR]] to i8*
// CHECK-DAG: [[TMP_VAL_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_VAL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_PTR_BCAST]], i8* [[TMP_VAL_BCAST]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_PTR_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL_BCAST]],
// CHECK: call void @__kmpc_for_static_fini(
// lastprivates
@@ -244,7 +260,7 @@ int main() {
// CHECK: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_ADDR_REF]],
// CHECK: [[BCAST_VEC_ADDR_REF:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_REF]] to i8*
// CHECK: [[BCAST_VEC_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[BCAST_VEC_ADDR_REF]], i8* [[BCAST_VEC_PRIV]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[BCAST_VEC_ADDR_REF]], i8* align {{[0-9]+}} [[BCAST_VEC_PRIV]],
// CHECK: [[S_ARR_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_ADDR_REF]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[S_ARR_PRIV_BCAST:%.+]] = bitcast [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]] to [[S_FLOAT_TY]]*
// CHECK: [[S_ARR_BEGIN_GEP:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[S_ARR_BEGIN]], i{{[0-9]+}} 2
@@ -255,7 +271,7 @@ int main() {
// CHECK: [[S_ARR_DST_EL:%.+]] = phi [[S_FLOAT_TY]]*{{.+}}
// CHECK: [[S_ARR_DST_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_DST_EL]] to i8*
// CHECK: [[S_ARR_SRC_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_SRC_EL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_DST_BCAST]], i8* [[S_ARR_SRC_BCAST]]{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_DST_BCAST]], i8* align {{[0-9]+}} [[S_ARR_SRC_BCAST]]{{.+}})
// CHECK: [[S_ARR_DST_NEXT:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[S_ARR_DST_EL]], i{{[0-9]+}} 1
// CHECK: [[S_ARR_SRC_NEXT:%.+]] = getelementptr{{.+}}
// CHECK: [[CPY_IS_FINISHED:%.+]] = icmp eq [[S_FLOAT_TY]]* [[S_ARR_DST_NEXT]], [[S_ARR_BEGIN_GEP]]
@@ -264,7 +280,7 @@ int main() {
// CHECK: [[TMP_VAL1:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP_PRIV]],
// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[VAR_ADDR_REF]] to i8*
// CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VAR_ADDR_REF_BCAST]], i8* [[TMP_VAL1_BCAST]],{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}})
// CHECK: [[SVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[S_VAR_PRIV]],
// CHECK: store i{{[0-9]+}} [[SVAR_VAL]], i{{[0-9]+}}* [[SVAR_ADDR_REF]],
// CHECK: ret void
@@ -331,7 +347,7 @@ int main() {
// CHECK-DAG: [[TMP_VAL1:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP_PRIV1]],
// CHECK-DAG: [[S_ARR_PTR_BCAST1:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_PTR1]] to i8*
// CHECK-DAG: [[TMP_VAL_BCAST1:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_PTR_BCAST1]], i8* [[TMP_VAL_BCAST1]],
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_PTR_BCAST1]], i8* align {{[0-9]+}} [[TMP_VAL_BCAST1]],
// CHECK: call void @__kmpc_for_static_fini(
// lastprivates
@@ -344,7 +360,7 @@ int main() {
// CHECK: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_ADDR_REF1]],
// CHECK: [[BCAST_VEC_ADDR_REF:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_REF1]] to i8*
// CHECK: [[BCAST_VEC_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[BCAST_VEC_ADDR_REF]], i8* [[BCAST_VEC_PRIV]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[BCAST_VEC_ADDR_REF]], i8* align {{[0-9]+}} [[BCAST_VEC_PRIV]],
// CHECK: [[S_ARR_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_ADDR_REF]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[S_ARR_PRIV_BCAST:%.+]] = bitcast [2 x [[S_INT_TY]]]* [[S_ARR_PRIV1]] to [[S_INT_TY]]*
// CHECK: [[S_ARR_BEGIN_GEP:%.+]] = getelementptr [[S_INT_TY]], [[S_INT_TY]]* [[S_ARR_BEGIN]], i{{[0-9]+}} 2
@@ -355,7 +371,7 @@ int main() {
// CHECK: [[S_ARR_DST_EL:%.+]] = phi [[S_INT_TY]]*{{.+}}
// CHECK: [[S_ARR_DST_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_DST_EL]] to i8*
// CHECK: [[S_ARR_SRC_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_SRC_EL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_DST_BCAST]], i8* [[S_ARR_SRC_BCAST]]{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_DST_BCAST]], i8* align {{[0-9]+}} [[S_ARR_SRC_BCAST]]{{.+}})
// CHECK: [[S_ARR_DST_NEXT:%.+]] = getelementptr [[S_INT_TY]], [[S_INT_TY]]* [[S_ARR_DST_EL]], i{{[0-9]+}} 1
// CHECK: [[S_ARR_SRC_NEXT:%.+]] = getelementptr{{.+}}
// CHECK: [[CPY_IS_FINISHED:%.+]] = icmp eq [[S_INT_TY]]* [[S_ARR_DST_NEXT]], [[S_ARR_BEGIN_GEP]]
@@ -364,6 +380,6 @@ int main() {
// CHECK: [[TMP_VAL1:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP_PRIV1]],
// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[VAR_ADDR1_REF]] to i8*
// CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VAR_ADDR_REF_BCAST]], i8* [[TMP_VAL1_BCAST]],{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}})
// CHECK: ret void
#endif
diff --git a/test/OpenMP/teams_distribute_lastprivate_messages.cpp b/test/OpenMP/teams_distribute_lastprivate_messages.cpp
index 392607ea14ba..d5e1a1c94cd0 100644
--- a/test/OpenMP/teams_distribute_lastprivate_messages.cpp
+++ b/test/OpenMP/teams_distribute_lastprivate_messages.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wno-openmp-target
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_loop_messages.cpp b/test/OpenMP/teams_distribute_loop_messages.cpp
index acab1f76a2d4..13f39d100aa5 100644
--- a/test/OpenMP/teams_distribute_loop_messages.cpp
+++ b/test/OpenMP/teams_distribute_loop_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+
class S {
int a;
S() : a(0) {} // expected-note {{implicitly declared private here}}
@@ -698,7 +700,7 @@ void test_loop_firstprivate_lastprivate() {
S s(4);
// expected-error@+2 {{lastprivate variable cannot be firstprivate}} expected-note@+2 {{defined as lastprivate}}
#pragma omp target
-#pragma omp teams distribute lastprivate(s) firstprivate(s) // expected-error {{calling a private constructor of class 'S'}}
+#pragma omp teams distribute lastprivate(s) firstprivate(s) // expected-error {{calling a private constructor of class 'S'}} expected-warning {{Non-trivial type 'S' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (int i = 0; i < 16; ++i)
;
}
diff --git a/test/OpenMP/teams_distribute_num_teams_messages.cpp b/test/OpenMP/teams_distribute_num_teams_messages.cpp
index 6086abd9200a..103a6d26fd4c 100644
--- a/test/OpenMP/teams_distribute_num_teams_messages.cpp
+++ b/test/OpenMP/teams_distribute_num_teams_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_parallel_for_ast_print.cpp b/test/OpenMP/teams_distribute_parallel_for_ast_print.cpp
index 68bd424ade01..246382daff4f 100644
--- a/test/OpenMP/teams_distribute_parallel_for_ast_print.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -104,7 +108,7 @@ T tmain(T argc) {
for (int i=0; i < 2; ++i)
a = 2;
// CHECK: #pragma omp target
-// CHECK-NEXT: #pragma omp teams distribute parallel for
+// CHECK-NEXT: #pragma omp teams distribute parallel for{{$}}
// CHECK-NEXT: for (int i = 0; i < 2; ++i)
// CHECK-NEXT: a = 2;
#pragma omp target
diff --git a/test/OpenMP/teams_distribute_parallel_for_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_codegen.cpp
index 5711ede87c86..865ea129f979 100644
--- a/test/OpenMP/teams_distribute_parallel_for_codegen.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_codegen.cpp
@@ -8,6 +8,14 @@
// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
#ifdef CK1
int a[100];
@@ -88,6 +96,14 @@ int teams_argument_global(int n){
// RUN: %clang_cc1 -DCK2 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
#ifdef CK2
// CK2: define {{.*}}i32 @{{.+}}teams_local_argv(
@@ -125,6 +141,14 @@ int teams_local_arg(void) {
// RUN: %clang_cc1 -DCK3 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-32
// RUN: %clang_cc1 -DCK3 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK3 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-32
+
+// RUN: %clang_cc1 -DCK3 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// RUN: %clang_cc1 -DCK3 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK3 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// RUN: %clang_cc1 -DCK3 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// RUN: %clang_cc1 -DCK3 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK3 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// SIMD-ONLY2-NOT: {{__kmpc|__tgt}}
#ifdef CK3
// CK3: [[SSI:%.+]] = type { [{{.+}} x i32], float }
@@ -174,6 +198,14 @@ int teams_template_struct(void) {
// RUN: %clang_cc1 -DCK4 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK4 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK4 --check-prefix CK4-32
+// RUN: %clang_cc1 -DCK4 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY3 %s
+// RUN: %clang_cc1 -DCK4 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK4 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY3 %s
+// RUN: %clang_cc1 -DCK4 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY3 %s
+// RUN: %clang_cc1 -DCK4 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK4 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY3 %s
+// SIMD-ONLY3-NOT: {{__kmpc|__tgt}}
+
#ifdef CK4
template <typename T, int n>
diff --git a/test/OpenMP/teams_distribute_parallel_for_collapse_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_collapse_codegen.cpp
index 7522288f75e2..11a97868ef72 100644
--- a/test/OpenMP/teams_distribute_parallel_for_collapse_codegen.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_collapse_codegen.cpp
@@ -9,6 +9,14 @@
// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
#ifdef CK1
template <typename T, int X, long long Y>
@@ -63,6 +71,14 @@ int teams_template_struct(void) {
// RUN: %clang_cc1 -DCK2 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
#ifdef CK2
template <typename T, int n, int m>
diff --git a/test/OpenMP/teams_distribute_parallel_for_collapse_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_collapse_messages.cpp
index ea4455dcc5f2..2e83a37bc95e 100644
--- a/test/OpenMP/teams_distribute_parallel_for_collapse_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_collapse_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp %s -std=c++98
// RUN: %clang_cc1 -verify -fopenmp %s -std=c++11
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -std=c++98
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -std=c++11
+
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_parallel_for_copyin_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_copyin_codegen.cpp
index 0202a40002b5..399025d8a4f1 100644
--- a/test/OpenMP/teams_distribute_parallel_for_copyin_codegen.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_copyin_codegen.cpp
@@ -5,10 +5,23 @@
// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/teams_distribute_parallel_for_copyin_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_copyin_messages.cpp
index 30f3e75bf635..2664b9df9534 100644
--- a/test/OpenMP/teams_distribute_parallel_for_copyin_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_copyin_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_parallel_for_default_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_default_messages.cpp
index 4cd7e65510b1..e5b333152039 100644
--- a/test/OpenMP/teams_distribute_parallel_for_default_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_default_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo();
int main(int argc, char **argv) {
diff --git a/test/OpenMP/teams_distribute_parallel_for_dist_schedule_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_dist_schedule_codegen.cpp
index dc48f166b4c0..03276e4b5ecb 100644
--- a/test/OpenMP/teams_distribute_parallel_for_dist_schedule_codegen.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_dist_schedule_codegen.cpp
@@ -9,6 +9,14 @@
// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
#ifdef CK1
template <typename T, int X, long long Y>
@@ -103,6 +111,14 @@ int teams_template_struct(void) {
// RUN: %clang_cc1 -DCK2 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
#ifdef CK2
template <typename T, int n>
diff --git a/test/OpenMP/teams_distribute_parallel_for_dist_schedule_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_dist_schedule_messages.cpp
index 098abb74870b..e0abe1114fb1 100644
--- a/test/OpenMP/teams_distribute_parallel_for_dist_schedule_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_dist_schedule_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_parallel_for_firstprivate_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_firstprivate_codegen.cpp
index fa99f9cfcf1b..7e161b1d2a62 100644
--- a/test/OpenMP/teams_distribute_parallel_for_firstprivate_codegen.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_firstprivate_codegen.cpp
@@ -1,13 +1,26 @@
-// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
-// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
-
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
@@ -127,16 +140,6 @@ int main() {
// LAMBDA: [[SIVAR_ADDR:%.+]] = alloca i{{[0-9]+}},
// LAMBDA: [[G1_TMP:%.+]] = alloca i32*,
// skip loop vars
- // LAMBDA: alloca i32,
- // LAMBDA: alloca i32,
- // LAMBDA: alloca i32,
- // LAMBDA: alloca i32,
- // LAMBDA: alloca i32,
- // LAMBDA: alloca i32,
- // LAMBDA: [[G_PRIV:%.+]] = alloca i{{[0-9]+}},
- // LAMBDA: [[G1_PRIV:%.+]] = alloca i{{[0-9]+}},
- // LAMBDA: [[G1_TMP_PRIV:%.+]] = alloca i{{[0-9]+}}*,
- // LAMBDA: [[SIVAR_PRIV:%.+]] = alloca i{{[0-9]+}},
// LAMBDA-DAG: store {{.+}}, {{.+}} [[G_ADDR]],
// LAMBDA-DAG: store {{.+}}, {{.+}} [[G1_ADDR]],
// LAMBDA-DAG: store {{.+}}, {{.+}} [[SIVAR_ADDR]],
@@ -146,10 +149,10 @@ int main() {
// LAMBDA-DAG: store{{.+}} [[G1_CONV]], {{.+}} [[G1_TMP]],
// use of private vars
- // LAMBDA-DAG: store{{.+}} 1, {{.+}} [[G_PRIV]],
- // LAMBDA-DAG: [[G1:%.+]] = load{{.+}}, {{.+}}* [[G1_TMP_PRIV]]
+ // LAMBDA-DAG: store{{.+}} 1, {{.+}} [[G_CONV]],
+ // LAMBDA-DAG: [[G1:%.+]] = load{{.+}}, {{.+}}* [[G1_TMP]]
// LAMBDA-DAG: store{{.+}} 1, {{.+}} [[G1]],
- // LAMBDA-DAG: store{{.+}} 2, {{.+}} [[SIVAR_PRIV]],
+ // LAMBDA-DAG: store{{.+}} 2, {{.+}} [[SIVAR_CONV]],
// LAMBDA-DAG: [[G1_REF:%.+]] = load{{.+}}, {{.+}} [[G1_TMP]],
// LAMBDA: call void [[INNER_LAMBDA:@.+]](
// LAMBDA: call void @__kmpc_for_static_fini(
@@ -240,8 +243,8 @@ int main() {
// CHECK: store i{{[0-9]+}} {{.+}}, i{{[0-9]+}}* [[SIVAR_ADDR]],
// T_VAR and SIVAR
-// CHECK-DAG-64: [[CONV_TVAR:%.+]] = bitcast i64* [[T_VAR_ADDR]] to i32*
-// CHECK-DAG-64: [[CONV_SIVAR:%.+]] = bitcast i64* [[SIVAR_ADDR]] to i32*
+// CHECK-64-DAG: [[CONV_TVAR:%.+]] = bitcast i64* [[T_VAR_ADDR]] to i32*
+// CHECK-64-DAG: [[CONV_SIVAR:%.+]] = bitcast i64* [[SIVAR_ADDR]] to i32*
// preparation vars
// CHECK-DAG: [[VEC_ADDR_VAL:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]],
@@ -251,7 +254,7 @@ int main() {
// firstprivate vec(vec): copy from *_addr into priv1 and then from priv1 into priv2
// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VEC_DEST_PRIV]], i8* [[VEC_SRC]], {{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST_PRIV]], i8* align {{[0-9]+}} [[VEC_SRC]], {{.+}})
// firstprivate(s_arr)
// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]],
@@ -306,8 +309,8 @@ int main() {
// CHECK: store i{{[0-9]+}} {{.+}}, i{{[0-9]+}}* [[SIVAR_ADDR]],
// T_VAR and SIVAR
-// CHECK-DAG-64: [[CONV_TVAR:%.+]] = bitcast i64* [[T_VAR_ADDR]] to i32*
-// CHECK-DAG-64: [[CONV_SIVAR:%.+]] = bitcast i64* [[SIVAR_ADDR]] to i32*
+// CHECK-64-DAG: [[CONV_TVAR:%.+]] = bitcast i64* [[T_VAR_ADDR]] to i32*
+// CHECK-64-DAG: [[CONV_SIVAR:%.+]] = bitcast i64* [[SIVAR_ADDR]] to i32*
// preparation vars
// CHECK-DAG: [[VEC_ADDR_VAL:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]],
@@ -317,7 +320,7 @@ int main() {
// firstprivate vec(vec): copy from *_addr into priv1 and then from priv1 into priv2
// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VEC_DEST_PRIV]], i8* [[VEC_SRC]], {{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST_PRIV]], i8* align {{[0-9]+}} [[VEC_SRC]], {{.+}})
// firstprivate(s_arr)
// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]],
@@ -337,13 +340,13 @@ int main() {
// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]])
// CHECK: call void @__kmpc_for_static_init_4(
-// CHECK-DAG-32: {{.+}} = {{.+}} [[T_VAR_ADDR]]
-// CHECK-DAG-64: {{.+}} = {{.+}} [[CONV_TVAR]]
+// CHECK-32-DAG: {{.+}} = {{.+}} [[T_VAR_ADDR]]
+// CHECK-64-DAG: {{.+}} = {{.+}} [[CONV_TVAR]]
// CHECK-DAG: {{.+}} = {{.+}} [[VEC_PRIV]]
// CHECK-DAG: {{.+}} = {{.+}} [[S_ARR_PRIV]]
// CHECK-DAG: {{.+}} = {{.+}} [[VAR_PRIV]]
-// CHECK-DAG-32: {{.+}} = {{.+}} [[SIVAR_ADDR]]
-// CHECK-DAG-64: {{.+}} = {{.+}} [[CONV_SIVAR]]
+// CHECK-32-DAG: {{.+}} = {{.+}} [[SIVAR_ADDR]]
+// CHECK-64-DAG: {{.+}} = {{.+}} [[CONV_SIVAR]]
// CHECK: call void @__kmpc_for_static_fini(
// CHECK: ret void
@@ -402,7 +405,7 @@ int main() {
// firstprivate vec(vec): copy from *_addr into priv1 and then from priv1 into priv2
// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VEC_DEST_PRIV]], i8* [[VEC_SRC]], {{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST_PRIV]], i8* align {{[0-9]+}} [[VEC_SRC]], {{.+}})
// firstprivate(s_arr)
// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_PRIV]],
@@ -463,7 +466,7 @@ int main() {
// firstprivate vec(vec): copy from *_addr into priv1 and then from priv1 into priv2
// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VEC_DEST_PRIV]], i8* [[VEC_SRC]], {{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST_PRIV]], i8* align {{[0-9]+}} [[VEC_SRC]], {{.+}})
// firstprivate(s_arr)
// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_PRIV]],
@@ -485,8 +488,8 @@ int main() {
// CHECK-DAG: store [[S_INT_TY]]* [[VAR_PRIV]], [[S_INT_TY]]** [[TMP]],
// CHECK: call void @__kmpc_for_static_init_4(
-// CHECK-DAG-32: {{.+}} = {{.+}} [[T_VAR_ADDR]]
-// CHECK-DAG-64: {{.+}} = {{.+}} [[CONV_TVAR]]
+// CHECK-32-DAG: {{.+}} = {{.+}} [[T_VAR_ADDR]]
+// CHECK-64-DAG: {{.+}} = {{.+}} [[CONV_TVAR]]
// CHECK-DAG: {{.+}} = {{.+}} [[VEC_PRIV]]
// CHECK-DAG: {{.+}} = {{.+}} [[TMP]]
// CHECK-DAG: {{.+}} = {{.+}} [[S_ARR_PRIV]]
diff --git a/test/OpenMP/teams_distribute_parallel_for_firstprivate_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_firstprivate_messages.cpp
index 90e78defc5e2..f4955887546e 100644
--- a/test/OpenMP/teams_distribute_parallel_for_firstprivate_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_firstprivate_messages.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wno-openmp-target
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_parallel_for_if_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_if_codegen.cpp
index bc40dca83fbe..f4119fc47d3b 100644
--- a/test/OpenMP/teams_distribute_parallel_for_if_codegen.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_if_codegen.cpp
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple %itanium_abi_triple -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple %itanium_abi_triple -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple %itanium_abi_triple -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple %itanium_abi_triple -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/teams_distribute_parallel_for_if_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_if_messages.cpp
index 14253b89f63e..e92dc65c60a8 100644
--- a/test/OpenMP/teams_distribute_parallel_for_if_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_if_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_parallel_for_lastprivate_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_lastprivate_codegen.cpp
index 501abb725b31..451dc0579cd3 100644
--- a/test/OpenMP/teams_distribute_parallel_for_lastprivate_codegen.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_lastprivate_codegen.cpp
@@ -1,16 +1,32 @@
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
-
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -288,7 +304,7 @@ int main() {
// CHECK: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_ADDR_REF]],
// CHECK: [[BCAST_VEC_ADDR_REF:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_REF]] to i8*
// CHECK: [[BCAST_VEC_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[BCAST_VEC_ADDR_REF]], i8* [[BCAST_VEC_PRIV]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[BCAST_VEC_ADDR_REF]], i8* align {{[0-9]+}} [[BCAST_VEC_PRIV]],
// CHECK: [[S_ARR_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_ADDR_REF]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[S_ARR_PRIV_BCAST:%.+]] = bitcast [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]] to [[S_FLOAT_TY]]*
// CHECK: [[S_ARR_BEGIN_GEP:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[S_ARR_BEGIN]], i{{[0-9]+}} 2
@@ -299,7 +315,7 @@ int main() {
// CHECK: [[S_ARR_DST_EL:%.+]] = phi [[S_FLOAT_TY]]*{{.+}}
// CHECK: [[S_ARR_DST_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_DST_EL]] to i8*
// CHECK: [[S_ARR_SRC_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_SRC_EL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_DST_BCAST]], i8* [[S_ARR_SRC_BCAST]]{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_DST_BCAST]], i8* align {{[0-9]+}} [[S_ARR_SRC_BCAST]]{{.+}})
// CHECK: [[S_ARR_DST_NEXT:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[S_ARR_DST_EL]], i{{[0-9]+}} 1
// CHECK: [[S_ARR_SRC_NEXT:%.+]] = getelementptr{{.+}}
// CHECK: [[CPY_IS_FINISHED:%.+]] = icmp eq [[S_FLOAT_TY]]* [[S_ARR_DST_NEXT]], [[S_ARR_BEGIN_GEP]]
@@ -308,7 +324,7 @@ int main() {
// CHECK: [[TMP_VAL1:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP_PRIV]],
// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[VAR_ADDR_REF]] to i8*
// CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VAR_ADDR_REF_BCAST]], i8* [[TMP_VAL1_BCAST]],{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}})
// CHECK: [[SVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[S_VAR_PRIV]],
// CHECK: store i{{[0-9]+}} [[SVAR_VAL]], i{{[0-9]+}}* [[SVAR_ADDR_REF]],
// CHECK: ret void
@@ -365,7 +381,7 @@ int main() {
// CHECK-DAG: [[TMP_VAL:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP_PRIV]],
// CHECK-DAG: [[S_ARR_PTR_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_PTR]] to i8*
// CHECK-DAG: [[TMP_VAL_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_VAL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_PTR_BCAST]], i8* [[TMP_VAL_BCAST]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_PTR_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL_BCAST]],
// CHECK: call void @__kmpc_for_static_fini(
@@ -379,7 +395,7 @@ int main() {
// CHECK: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_ADDR_REF]],
// CHECK: [[BCAST_VEC_ADDR_REF:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_REF]] to i8*
// CHECK: [[BCAST_VEC_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[BCAST_VEC_ADDR_REF]], i8* [[BCAST_VEC_PRIV]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[BCAST_VEC_ADDR_REF]], i8* align {{[0-9]+}} [[BCAST_VEC_PRIV]],
// CHECK: [[S_ARR_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_ADDR_REF]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[S_ARR_PRIV_BCAST:%.+]] = bitcast [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]] to [[S_FLOAT_TY]]*
// CHECK: [[S_ARR_BEGIN_GEP:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[S_ARR_BEGIN]], i{{[0-9]+}} 2
@@ -390,7 +406,7 @@ int main() {
// CHECK: [[S_ARR_DST_EL:%.+]] = phi [[S_FLOAT_TY]]*{{.+}}
// CHECK: [[S_ARR_DST_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_DST_EL]] to i8*
// CHECK: [[S_ARR_SRC_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_SRC_EL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_DST_BCAST]], i8* [[S_ARR_SRC_BCAST]]{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_DST_BCAST]], i8* align {{[0-9]+}} [[S_ARR_SRC_BCAST]]{{.+}})
// CHECK: [[S_ARR_DST_NEXT:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[S_ARR_DST_EL]], i{{[0-9]+}} 1
// CHECK: [[S_ARR_SRC_NEXT:%.+]] = getelementptr{{.+}}
// CHECK: [[CPY_IS_FINISHED:%.+]] = icmp eq [[S_FLOAT_TY]]* [[S_ARR_DST_NEXT]], [[S_ARR_BEGIN_GEP]]
@@ -399,7 +415,7 @@ int main() {
// CHECK: [[TMP_VAL1:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP_PRIV]],
// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[VAR_ADDR_REF]] to i8*
// CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VAR_ADDR_REF_BCAST]], i8* [[TMP_VAL1_BCAST]],{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}})
// CHECK: [[SVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[S_VAR_PRIV]],
// CHECK: store i{{[0-9]+}} [[SVAR_VAL]], i{{[0-9]+}}* [[SVAR_ADDR_REF]],
// CHECK: ret void
@@ -468,7 +484,7 @@ int main() {
// CHECK: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_ADDR_REF1]],
// CHECK: [[BCAST_VEC_ADDR_REF:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_REF1]] to i8*
// CHECK: [[BCAST_VEC_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[BCAST_VEC_ADDR_REF]], i8* [[BCAST_VEC_PRIV]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[BCAST_VEC_ADDR_REF]], i8* align {{[0-9]+}} [[BCAST_VEC_PRIV]],
// CHECK: [[S_ARR_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_ADDR_REF]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[S_ARR_PRIV_BCAST:%.+]] = bitcast [2 x [[S_INT_TY]]]* [[S_ARR_PRIV1]] to [[S_INT_TY]]*
// CHECK: [[S_ARR_BEGIN_GEP:%.+]] = getelementptr [[S_INT_TY]], [[S_INT_TY]]* [[S_ARR_BEGIN]], i{{[0-9]+}} 2
@@ -479,7 +495,7 @@ int main() {
// CHECK: [[S_ARR_DST_EL:%.+]] = phi [[S_INT_TY]]*{{.+}}
// CHECK: [[S_ARR_DST_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_DST_EL]] to i8*
// CHECK: [[S_ARR_SRC_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_SRC_EL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_DST_BCAST]], i8* [[S_ARR_SRC_BCAST]]{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_DST_BCAST]], i8* align {{[0-9]+}} [[S_ARR_SRC_BCAST]]{{.+}})
// CHECK: [[S_ARR_DST_NEXT:%.+]] = getelementptr [[S_INT_TY]], [[S_INT_TY]]* [[S_ARR_DST_EL]], i{{[0-9]+}} 1
// CHECK: [[S_ARR_SRC_NEXT:%.+]] = getelementptr{{.+}}
// CHECK: [[CPY_IS_FINISHED:%.+]] = icmp eq [[S_INT_TY]]* [[S_ARR_DST_NEXT]], [[S_ARR_BEGIN_GEP]]
@@ -488,7 +504,7 @@ int main() {
// CHECK: [[TMP_VAL1:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP_PRIV1]],
// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[VAR_ADDR1_REF]] to i8*
// CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VAR_ADDR_REF_BCAST]], i8* [[TMP_VAL1_BCAST]],{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}})
// CHECK: ret void
// CHECK: define internal void [[TPAR_OUTL:@.+]](i{{[0-9]+}}* noalias [[GTID_ADDR1:%.+]], i{{[0-9]+}}* noalias %{{.+}}, {{.+}}, {{.+}}, [2 x i{{[0-9]+}}]*{{.+}} [[VEC_IN1:%.+]], i{{[0-9]+}}*{{.+}} [[T_VAR_IN1:%.+]], [2 x [[S_INT_TY]]]*{{.+}} [[S_ARR_IN1:%.+]], [[S_INT_TY]]*{{.+}} [[VAR_IN1:%.+]])
@@ -544,7 +560,7 @@ int main() {
// CHECK-DAG: [[TMP_VAL1:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP_PRIV1]],
// CHECK-DAG: [[S_ARR_PTR_BCAST1:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_PTR1]] to i8*
// CHECK-DAG: [[TMP_VAL_BCAST1:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_PTR_BCAST1]], i8* [[TMP_VAL_BCAST1]],
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_PTR_BCAST1]], i8* align {{[0-9]+}} [[TMP_VAL_BCAST1]],
// CHECK: call void @__kmpc_for_static_fini(
@@ -558,7 +574,7 @@ int main() {
// CHECK: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_ADDR_REF1]],
// CHECK: [[BCAST_VEC_ADDR_REF:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_REF1]] to i8*
// CHECK: [[BCAST_VEC_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[BCAST_VEC_ADDR_REF]], i8* [[BCAST_VEC_PRIV]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[BCAST_VEC_ADDR_REF]], i8* align {{[0-9]+}} [[BCAST_VEC_PRIV]],
// CHECK: [[S_ARR_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_ADDR_REF]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[S_ARR_PRIV_BCAST:%.+]] = bitcast [2 x [[S_INT_TY]]]* [[S_ARR_PRIV1]] to [[S_INT_TY]]*
// CHECK: [[S_ARR_BEGIN_GEP:%.+]] = getelementptr [[S_INT_TY]], [[S_INT_TY]]* [[S_ARR_BEGIN]], i{{[0-9]+}} 2
@@ -569,7 +585,7 @@ int main() {
// CHECK: [[S_ARR_DST_EL:%.+]] = phi [[S_INT_TY]]*{{.+}}
// CHECK: [[S_ARR_DST_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_DST_EL]] to i8*
// CHECK: [[S_ARR_SRC_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_SRC_EL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_DST_BCAST]], i8* [[S_ARR_SRC_BCAST]]{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_DST_BCAST]], i8* align {{[0-9]+}} [[S_ARR_SRC_BCAST]]{{.+}})
// CHECK: [[S_ARR_DST_NEXT:%.+]] = getelementptr [[S_INT_TY]], [[S_INT_TY]]* [[S_ARR_DST_EL]], i{{[0-9]+}} 1
// CHECK: [[S_ARR_SRC_NEXT:%.+]] = getelementptr{{.+}}
// CHECK: [[CPY_IS_FINISHED:%.+]] = icmp eq [[S_INT_TY]]* [[S_ARR_DST_NEXT]], [[S_ARR_BEGIN_GEP]]
@@ -578,7 +594,7 @@ int main() {
// CHECK: [[TMP_VAL1:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP_PRIV1]],
// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[VAR_ADDR1_REF]] to i8*
// CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VAR_ADDR_REF_BCAST]], i8* [[TMP_VAL1_BCAST]],{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}})
// CHECK: ret void
#endif
diff --git a/test/OpenMP/teams_distribute_parallel_for_lastprivate_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_lastprivate_messages.cpp
index b58bac4fdfc3..97e9e4f822f0 100644
--- a/test/OpenMP/teams_distribute_parallel_for_lastprivate_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_lastprivate_messages.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wno-openmp-target
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_parallel_for_loop_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_loop_messages.cpp
index a2f6f679d325..0fd3fa263ad2 100644
--- a/test/OpenMP/teams_distribute_parallel_for_loop_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_loop_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+
class S {
int a;
S() : a(0) {} // expected-note {{implicitly declared private here}}
@@ -693,7 +695,7 @@ void test_loop_firstprivate_lastprivate() {
S s(4);
// expected-error@+2 {{lastprivate variable cannot be firstprivate}} expected-note@+2 {{defined as lastprivate}}
#pragma omp target
-#pragma omp teams distribute parallel for lastprivate(s) firstprivate(s) // expected-error {{calling a private constructor of class 'S'}}
+#pragma omp teams distribute parallel for lastprivate(s) firstprivate(s) // expected-error {{calling a private constructor of class 'S'}} expected-warning {{Non-trivial type 'S' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (int i = 0; i < 16; ++i)
;
}
diff --git a/test/OpenMP/teams_distribute_parallel_for_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_messages.cpp
index 9843b442e5b4..57ad66638028 100644
--- a/test/OpenMP/teams_distribute_parallel_for_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_parallel_for_num_teams_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_num_teams_messages.cpp
index 63bc91e8ec00..cc6f1c8e6405 100644
--- a/test/OpenMP/teams_distribute_parallel_for_num_teams_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_num_teams_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_parallel_for_num_threads_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_num_threads_codegen.cpp
index 5aed5b172af6..ea4afa1418cb 100644
--- a/test/OpenMP/teams_distribute_parallel_for_num_threads_codegen.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_num_threads_codegen.cpp
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-ibm-linux-gnu -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-ibm-linux-gnu -fexceptions -fcxx-exceptions -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-ibm-linux-gnu -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-ibm-linux-gnu -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-ibm-linux-gnu -fexceptions -fcxx-exceptions -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-ibm-linux-gnu -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/teams_distribute_parallel_for_private_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_private_codegen.cpp
index 80a12738cab4..5fc7ee12eb0a 100644
--- a/test/OpenMP/teams_distribute_parallel_for_private_codegen.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_private_codegen.cpp
@@ -1,13 +1,26 @@
-// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
diff --git a/test/OpenMP/teams_distribute_parallel_for_private_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_private_messages.cpp
index 6e72905d754a..5fda1a96e41e 100644
--- a/test/OpenMP/teams_distribute_parallel_for_private_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_private_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_parallel_for_proc_bind_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_proc_bind_codegen.cpp
index 71e92bd5a555..0c242f851b7d 100644
--- a/test/OpenMP/teams_distribute_parallel_for_proc_bind_codegen.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_proc_bind_codegen.cpp
@@ -3,6 +3,11 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -57,7 +62,7 @@ int main() {
// CHECK: [[GTID_REF:%.+]] = load i32*, i32** [[GTID_ADDR]],
// CHECK: [[GTID_VAL:%.+]] = load i32, i32* [[GTID_REF]],
// CHECK: call {{.*}}void @__kmpc_push_proc_bind([[IDENT_T_TY]]* [[DEF_LOC_2]], i32 [[GTID_VAL]], i32 4)
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
// CHECK: ret void
// CHECK: define{{.+}} [[OFFL2]]()
@@ -69,7 +74,7 @@ int main() {
// CHECK: [[GTID_REF:%.+]] = load i32*, i32** [[GTID_ADDR]],
// CHECK: [[GTID_VAL:%.+]] = load i32, i32* [[GTID_REF]],
// CHECK: call {{.*}}void @__kmpc_push_proc_bind([[IDENT_T_TY]]* [[DEF_LOC_2]], i32 [[GTID_VAL]], i32 3)
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
// CHECK: ret void
// CHECK: define{{.+}} [[TMAIN]]()
@@ -85,6 +90,6 @@ int main() {
// CHECK: [[GTID_REF:%.+]] = load i32*, i32** [[GTID_ADDR]],
// CHECK: [[GTID_VAL:%.+]] = load i32, i32* [[GTID_REF]],
// CHECK: call {{.*}}void @__kmpc_push_proc_bind([[IDENT_T_TY]]* [[DEF_LOC_2]], i32 [[GTID_VAL]], i32 2)
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
// CHECK: ret void
#endif
diff --git a/test/OpenMP/teams_distribute_parallel_for_proc_bind_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_proc_bind_messages.cpp
index 2a7074a0bcd4..33e9c39be900 100644
--- a/test/OpenMP/teams_distribute_parallel_for_proc_bind_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_proc_bind_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo();
template <class T, typename S, int N>
diff --git a/test/OpenMP/teams_distribute_parallel_for_reduction_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_reduction_codegen.cpp
index 55ccfff99a3c..34cc2874f6f3 100644
--- a/test/OpenMP/teams_distribute_parallel_for_reduction_codegen.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_reduction_codegen.cpp
@@ -5,10 +5,23 @@
// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/teams_distribute_parallel_for_reduction_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_reduction_messages.cpp
index 889efd76cc3c..31a91a862f69 100644
--- a/test/OpenMP/teams_distribute_parallel_for_reduction_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_reduction_messages.cpp
@@ -1,6 +1,10 @@
-// RUN: %clang_cc1 -verify -fopenmp %s
-// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
-// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp %s -Wno-openmp-target
+// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s -Wno-openmp-target
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wno-openmp-target
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s -Wno-openmp-target
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s -Wno-openmp-target
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_parallel_for_schedule_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_schedule_codegen.cpp
index 201a170ccd4a..f7b11a719194 100644
--- a/test/OpenMP/teams_distribute_parallel_for_schedule_codegen.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_schedule_codegen.cpp
@@ -9,6 +9,14 @@
// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
#ifdef CK1
template <typename T, int X, long long Y>
@@ -149,6 +157,14 @@ int teams_template_struct(void) {
// RUN: %clang_cc1 -DCK2 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
#ifdef CK2
template <typename T, int n>
diff --git a/test/OpenMP/teams_distribute_parallel_for_schedule_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_schedule_messages.cpp
index 477d1a0f7d34..e8cda672c096 100644
--- a/test/OpenMP/teams_distribute_parallel_for_schedule_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_schedule_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_parallel_for_shared_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_shared_messages.cpp
index 1a1af09aa205..90edfb1b11f0 100644
--- a/test/OpenMP/teams_distribute_parallel_for_shared_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_shared_messages.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wno-openmp-target
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_aligned_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_aligned_messages.cpp
index 97b200bb1641..8fc21a086f81 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_aligned_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_aligned_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -x c++ -std=c++11 -verify -fopenmp %s
+// RUN: %clang_cc1 -x c++ -std=c++11 -verify -fopenmp-simd %s
+
struct B {
static int ib[20]; // expected-note 0 {{'B::ib' declared here}}
static constexpr int bfoo() { return 8; }
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_ast_print.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_ast_print.cpp
index 7573fdeafa31..c7a0a358f60d 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_ast_print.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -128,7 +132,7 @@ T tmain(T argc) {
for (int i=0; i < 2; ++i)
a = 2;
// CHECK: #pragma omp target
-// CHECK-NEXT: #pragma omp teams distribute parallel for simd
+// CHECK-NEXT: #pragma omp teams distribute parallel for simd{{$}}
// CHECK-NEXT: for (int i = 0; i < 2; ++i)
// CHECK-NEXT: a = 2;
#pragma omp target
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp
index 00f2844735c9..784deeef7cd2 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp
@@ -8,6 +8,14 @@
// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
#ifdef CK1
int a[100];
@@ -92,6 +100,14 @@ int teams_argument_global(int n){
// RUN: %clang_cc1 -DCK2 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
#ifdef CK2
// CK2: define {{.*}}i32 @{{.+}}teams_local_argv(
@@ -133,6 +149,14 @@ int teams_local_arg(void) {
// RUN: %clang_cc1 -DCK3 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-32
// RUN: %clang_cc1 -DCK3 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK3 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-32
+
+// RUN: %clang_cc1 -DCK3 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// RUN: %clang_cc1 -DCK3 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK3 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// RUN: %clang_cc1 -DCK3 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// RUN: %clang_cc1 -DCK3 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK3 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// SIMD-ONLY2-NOT: {{__kmpc|__tgt}}
#ifdef CK3
// CK3: [[SSI:%.+]] = type { [{{.+}} x i32], float }
@@ -144,7 +168,7 @@ struct SS{
// CK3: define {{.*}}i32 @{{.+}}foo{{.+}}(
int foo(void) {
int i;
- // CK3: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 2, i8** %{{[^,]+}}, i8** %{{[^,]+}}, i{{64|32}}* {{.+}}@{{[^,]+}}, i32 0, i32 0), i64* {{.+}}@{{[^,]+}}, i32 0, i32 0)
+ // CK3: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 3, i8** %{{[^,]+}}, i8** %{{[^,]+}}, i{{64|32}}* %{{[^,]+}}, i64* {{.+}}@{{[^,]+}}, i32 0, i32 0)
// CK3: call void @[[OFFL1:.+]]([[SSI]]* %{{.+}})
#pragma omp target
#pragma omp teams distribute parallel for simd safelen(4) aligned(a) linear(i)
@@ -185,6 +209,14 @@ int teams_template_struct(void) {
// RUN: %clang_cc1 -DCK4 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK4 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK4 --check-prefix CK4-32
+// RUN: %clang_cc1 -DCK4 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY3 %s
+// RUN: %clang_cc1 -DCK4 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK4 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY3 %s
+// RUN: %clang_cc1 -DCK4 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY3 %s
+// RUN: %clang_cc1 -DCK4 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK4 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY3 %s
+// SIMD-ONLY3-NOT: {{__kmpc|__tgt}}
+
#ifdef CK4
template <typename T, int n>
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_collapse_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_collapse_codegen.cpp
index 91c451d49a08..24bd31e07ba6 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_collapse_codegen.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_collapse_codegen.cpp
@@ -9,6 +9,14 @@
// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
#ifdef CK1
template <typename T, int X, long long Y>
@@ -66,6 +74,14 @@ int teams_template_struct(void) {
// RUN: %clang_cc1 -DCK2 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
#ifdef CK2
template <typename T, int n, int m>
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_collapse_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_collapse_messages.cpp
index 197c5f1ad341..a287da7a36c2 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_collapse_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_collapse_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp %s -std=c++98
// RUN: %clang_cc1 -verify -fopenmp %s -std=c++11
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -std=c++98
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -std=c++11
+
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_default_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_default_messages.cpp
index dc69acbe0b3c..8db9d668fd34 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_default_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_default_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo();
int main(int argc, char **argv) {
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_codegen.cpp
index 5c1f73066cd4..4f11dc67437b 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_codegen.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_codegen.cpp
@@ -9,6 +9,14 @@
// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
#ifdef CK1
template <typename T, int X, long long Y>
@@ -106,6 +114,14 @@ int teams_template_struct(void) {
// RUN: %clang_cc1 -DCK2 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
#ifdef CK2
template <typename T, int n>
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_messages.cpp
index b879de749dfa..d53fa578b5c5 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_firstprivate_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_firstprivate_codegen.cpp
index 1219742c752d..68b0016a9746 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_firstprivate_codegen.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_firstprivate_codegen.cpp
@@ -1,13 +1,26 @@
-// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
-// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
-
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
@@ -127,16 +140,6 @@ int main() {
// LAMBDA: [[SIVAR_ADDR:%.+]] = alloca i{{[0-9]+}},
// LAMBDA: [[G1_TMP:%.+]] = alloca i32*,
// skip loop vars
- // LAMBDA: alloca i32,
- // LAMBDA: alloca i32,
- // LAMBDA: alloca i32,
- // LAMBDA: alloca i32,
- // LAMBDA: alloca i32,
- // LAMBDA: alloca i32,
- // LAMBDA: [[G_PRIV:%.+]] = alloca i{{[0-9]+}},
- // LAMBDA: [[G1_PRIV:%.+]] = alloca i{{[0-9]+}},
- // LAMBDA: [[G1_TMP_PRIV:%.+]] = alloca i{{[0-9]+}}*,
- // LAMBDA: [[SIVAR_PRIV:%.+]] = alloca i{{[0-9]+}},
// LAMBDA-DAG: store {{.+}}, {{.+}} [[G_ADDR]],
// LAMBDA-DAG: store {{.+}}, {{.+}} [[G1_ADDR]],
// LAMBDA-DAG: store {{.+}}, {{.+}} [[SIVAR_ADDR]],
@@ -146,10 +149,10 @@ int main() {
// LAMBDA-DAG: store{{.+}} [[G1_CONV]], {{.+}} [[G1_TMP]],
// use of private vars
- // LAMBDA-DAG: store{{.+}} 1, {{.+}} [[G_PRIV]],
- // LAMBDA-DAG: [[G1:%.+]] = load{{.+}}, {{.+}}* [[G1_TMP_PRIV]]
+ // LAMBDA-DAG: store{{.+}} 1, {{.+}} [[G_CONV]],
+ // LAMBDA-DAG: [[G1:%.+]] = load{{.+}}, {{.+}}* [[G1_TMP]]
// LAMBDA-DAG: store{{.+}} 1, {{.+}} [[G1]],
- // LAMBDA-DAG: store{{.+}} 2, {{.+}} [[SIVAR_PRIV]],
+ // LAMBDA-DAG: store{{.+}} 2, {{.+}} [[SIVAR_CONV]],
// LAMBDA-DAG: [[G1_REF:%.+]] = load{{.+}}, {{.+}} [[G1_TMP]],
// LAMBDA: call void [[INNER_LAMBDA:@.+]](
// LAMBDA: call void @__kmpc_for_static_fini(
@@ -243,8 +246,8 @@ int main() {
// CHECK: store i{{[0-9]+}} {{.+}}, i{{[0-9]+}}* [[SIVAR_ADDR]],
// T_VAR and SIVAR
-// CHECK-DAG-64: [[CONV_TVAR:%.+]] = bitcast i64* [[T_VAR_ADDR]] to i32*
-// CHECK-DAG-64: [[CONV_SIVAR:%.+]] = bitcast i64* [[SIVAR_ADDR]] to i32*
+// CHECK-64-DAG: [[CONV_TVAR:%.+]] = bitcast i64* [[T_VAR_ADDR]] to i32*
+// CHECK-64-DAG: [[CONV_SIVAR:%.+]] = bitcast i64* [[SIVAR_ADDR]] to i32*
// preparation vars
// CHECK-DAG: [[VEC_ADDR_VAL:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]],
@@ -254,7 +257,7 @@ int main() {
// firstprivate vec(vec): copy from *_addr into priv1 and then from priv1 into priv2
// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VEC_DEST_PRIV]], i8* [[VEC_SRC]], {{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST_PRIV]], i8* align {{[0-9]+}} [[VEC_SRC]], {{.+}})
// firstprivate(s_arr)
// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]],
@@ -309,8 +312,8 @@ int main() {
// CHECK: store i{{[0-9]+}} {{.+}}, i{{[0-9]+}}* [[SIVAR_ADDR]],
// T_VAR and SIVAR
-// CHECK-DAG-64: [[CONV_TVAR:%.+]] = bitcast i64* [[T_VAR_ADDR]] to i32*
-// CHECK-DAG-64: [[CONV_SIVAR:%.+]] = bitcast i64* [[SIVAR_ADDR]] to i32*
+// CHECK-64-DAG: [[CONV_TVAR:%.+]] = bitcast i64* [[T_VAR_ADDR]] to i32*
+// CHECK-64-DAG: [[CONV_SIVAR:%.+]] = bitcast i64* [[SIVAR_ADDR]] to i32*
// preparation vars
// CHECK-DAG: [[VEC_ADDR_VAL:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]],
@@ -320,7 +323,7 @@ int main() {
// firstprivate vec(vec): copy from *_addr into priv1 and then from priv1 into priv2
// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VEC_DEST_PRIV]], i8* [[VEC_SRC]], {{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST_PRIV]], i8* align {{[0-9]+}} [[VEC_SRC]], {{.+}})
// firstprivate(s_arr)
// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]],
@@ -340,13 +343,13 @@ int main() {
// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]])
// CHECK: call void @__kmpc_for_static_init_4(
-// CHECK-DAG-32: {{.+}} = {{.+}} [[T_VAR_ADDR]]
-// CHECK-DAG-64: {{.+}} = {{.+}} [[CONV_TVAR]]
+// CHECK-32-DAG: {{.+}} = {{.+}} [[T_VAR_ADDR]]
+// CHECK-64-DAG: {{.+}} = {{.+}} [[CONV_TVAR]]
// CHECK-DAG: {{.+}} = {{.+}} [[VEC_PRIV]]
// CHECK-DAG: {{.+}} = {{.+}} [[S_ARR_PRIV]]
// CHECK-DAG: {{.+}} = {{.+}} [[VAR_PRIV]]
-// CHECK-DAG-32: {{.+}} = {{.+}} [[SIVAR_ADDR]]
-// CHECK-DAG-64: {{.+}} = {{.+}} [[CONV_SIVAR]]
+// CHECK-32-DAG: {{.+}} = {{.+}} [[SIVAR_ADDR]]
+// CHECK-64-DAG: {{.+}} = {{.+}} [[CONV_SIVAR]]
// CHECK: call void @__kmpc_for_static_fini(
// CHECK: ret void
@@ -405,7 +408,7 @@ int main() {
// firstprivate vec(vec): copy from *_addr into priv1 and then from priv1 into priv2
// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VEC_DEST_PRIV]], i8* [[VEC_SRC]], {{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST_PRIV]], i8* align {{[0-9]+}} [[VEC_SRC]], {{.+}})
// firstprivate(s_arr)
// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_PRIV]],
@@ -466,7 +469,7 @@ int main() {
// firstprivate vec(vec): copy from *_addr into priv1 and then from priv1 into priv2
// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VEC_DEST_PRIV]], i8* [[VEC_SRC]], {{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST_PRIV]], i8* align {{[0-9]+}} [[VEC_SRC]], {{.+}})
// firstprivate(s_arr)
// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_PRIV]],
@@ -488,8 +491,8 @@ int main() {
// CHECK-DAG: store [[S_INT_TY]]* [[VAR_PRIV]], [[S_INT_TY]]** [[TMP]],
// CHECK: call void @__kmpc_for_static_init_4(
-// CHECK-DAG-32: {{.+}} = {{.+}} [[T_VAR_ADDR]]
-// CHECK-DAG-64: {{.+}} = {{.+}} [[CONV_TVAR]]
+// CHECK-32-DAG: {{.+}} = {{.+}} [[T_VAR_ADDR]]
+// CHECK-64-DAG: {{.+}} = {{.+}} [[CONV_TVAR]]
// CHECK-DAG: {{.+}} = {{.+}} [[VEC_PRIV]]
// CHECK-DAG: {{.+}} = {{.+}} [[TMP]]
// CHECK-DAG: {{.+}} = {{.+}} [[S_ARR_PRIV]]
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_firstprivate_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_firstprivate_messages.cpp
index 668337db454b..036f20123093 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_firstprivate_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_firstprivate_messages.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wno-openmp-target
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_if_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_if_codegen.cpp
index 6f2cef88cbbc..66794132a9ed 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_if_codegen.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_if_codegen.cpp
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple %itanium_abi_triple -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple %itanium_abi_triple -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple %itanium_abi_triple -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple %itanium_abi_triple -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_if_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_if_messages.cpp
index 01978d722226..d8a642300d71 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_if_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_if_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_codegen.cpp
index 5df893d525f4..c9141b01494f 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_codegen.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_codegen.cpp
@@ -1,16 +1,32 @@
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
-
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -295,7 +311,7 @@ int main() {
// CHECK: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_ADDR_REF]],
// CHECK: [[BCAST_VEC_ADDR_REF:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_REF]] to i8*
// CHECK: [[BCAST_VEC_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[BCAST_VEC_ADDR_REF]], i8* [[BCAST_VEC_PRIV]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[BCAST_VEC_ADDR_REF]], i8* align {{[0-9]+}} [[BCAST_VEC_PRIV]],
// CHECK: [[S_ARR_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_ADDR_REF]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[S_ARR_PRIV_BCAST:%.+]] = bitcast [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]] to [[S_FLOAT_TY]]*
// CHECK: [[S_ARR_BEGIN_GEP:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[S_ARR_BEGIN]], i{{[0-9]+}} 2
@@ -306,7 +322,7 @@ int main() {
// CHECK: [[S_ARR_DST_EL:%.+]] = phi [[S_FLOAT_TY]]*{{.+}}
// CHECK: [[S_ARR_DST_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_DST_EL]] to i8*
// CHECK: [[S_ARR_SRC_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_SRC_EL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_DST_BCAST]], i8* [[S_ARR_SRC_BCAST]]{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_DST_BCAST]], i8* align {{[0-9]+}} [[S_ARR_SRC_BCAST]]{{.+}})
// CHECK: [[S_ARR_DST_NEXT:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[S_ARR_DST_EL]], i{{[0-9]+}} 1
// CHECK: [[S_ARR_SRC_NEXT:%.+]] = getelementptr{{.+}}
// CHECK: [[CPY_IS_FINISHED:%.+]] = icmp eq [[S_FLOAT_TY]]* [[S_ARR_DST_NEXT]], [[S_ARR_BEGIN_GEP]]
@@ -315,7 +331,7 @@ int main() {
// CHECK: [[TMP_VAL1:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP_PRIV]],
// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[VAR_ADDR_REF]] to i8*
// CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VAR_ADDR_REF_BCAST]], i8* [[TMP_VAL1_BCAST]],{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}})
// CHECK: [[SVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[S_VAR_PRIV]],
// CHECK: store i{{[0-9]+}} [[SVAR_VAL]], i{{[0-9]+}}* [[SVAR_ADDR_REF]],
// CHECK: ret void
@@ -372,7 +388,7 @@ int main() {
// CHECK-DAG: [[TMP_VAL:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP_PRIV]],
// CHECK-DAG: [[S_ARR_PTR_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_PTR]] to i8*
// CHECK-DAG: [[TMP_VAL_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_VAL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_PTR_BCAST]], i8* [[TMP_VAL_BCAST]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_PTR_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL_BCAST]],
// CHECK: call void @__kmpc_for_static_fini(
@@ -389,7 +405,7 @@ int main() {
// CHECK: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_ADDR_REF]],
// CHECK: [[BCAST_VEC_ADDR_REF:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_REF]] to i8*
// CHECK: [[BCAST_VEC_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[BCAST_VEC_ADDR_REF]], i8* [[BCAST_VEC_PRIV]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[BCAST_VEC_ADDR_REF]], i8* align {{[0-9]+}} [[BCAST_VEC_PRIV]],
// CHECK: [[S_ARR_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_ADDR_REF]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[S_ARR_PRIV_BCAST:%.+]] = bitcast [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]] to [[S_FLOAT_TY]]*
// CHECK: [[S_ARR_BEGIN_GEP:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[S_ARR_BEGIN]], i{{[0-9]+}} 2
@@ -400,7 +416,7 @@ int main() {
// CHECK: [[S_ARR_DST_EL:%.+]] = phi [[S_FLOAT_TY]]*{{.+}}
// CHECK: [[S_ARR_DST_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_DST_EL]] to i8*
// CHECK: [[S_ARR_SRC_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_SRC_EL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_DST_BCAST]], i8* [[S_ARR_SRC_BCAST]]{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_DST_BCAST]], i8* align {{[0-9]+}} [[S_ARR_SRC_BCAST]]{{.+}})
// CHECK: [[S_ARR_DST_NEXT:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[S_ARR_DST_EL]], i{{[0-9]+}} 1
// CHECK: [[S_ARR_SRC_NEXT:%.+]] = getelementptr{{.+}}
// CHECK: [[CPY_IS_FINISHED:%.+]] = icmp eq [[S_FLOAT_TY]]* [[S_ARR_DST_NEXT]], [[S_ARR_BEGIN_GEP]]
@@ -409,7 +425,7 @@ int main() {
// CHECK: [[TMP_VAL1:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP_PRIV]],
// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[VAR_ADDR_REF]] to i8*
// CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VAR_ADDR_REF_BCAST]], i8* [[TMP_VAL1_BCAST]],{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}})
// CHECK: [[SVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[S_VAR_PRIV]],
// CHECK: store i{{[0-9]+}} [[SVAR_VAL]], i{{[0-9]+}}* [[SVAR_ADDR_REF]],
// CHECK: ret void
@@ -478,7 +494,7 @@ int main() {
// CHECK: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_ADDR_REF1]],
// CHECK: [[BCAST_VEC_ADDR_REF:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_REF1]] to i8*
// CHECK: [[BCAST_VEC_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[BCAST_VEC_ADDR_REF]], i8* [[BCAST_VEC_PRIV]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[BCAST_VEC_ADDR_REF]], i8* align {{[0-9]+}} [[BCAST_VEC_PRIV]],
// CHECK: [[S_ARR_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_ADDR_REF]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[S_ARR_PRIV_BCAST:%.+]] = bitcast [2 x [[S_INT_TY]]]* [[S_ARR_PRIV1]] to [[S_INT_TY]]*
// CHECK: [[S_ARR_BEGIN_GEP:%.+]] = getelementptr [[S_INT_TY]], [[S_INT_TY]]* [[S_ARR_BEGIN]], i{{[0-9]+}} 2
@@ -489,7 +505,7 @@ int main() {
// CHECK: [[S_ARR_DST_EL:%.+]] = phi [[S_INT_TY]]*{{.+}}
// CHECK: [[S_ARR_DST_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_DST_EL]] to i8*
// CHECK: [[S_ARR_SRC_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_SRC_EL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_DST_BCAST]], i8* [[S_ARR_SRC_BCAST]]{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_DST_BCAST]], i8* align {{[0-9]+}} [[S_ARR_SRC_BCAST]]{{.+}})
// CHECK: [[S_ARR_DST_NEXT:%.+]] = getelementptr [[S_INT_TY]], [[S_INT_TY]]* [[S_ARR_DST_EL]], i{{[0-9]+}} 1
// CHECK: [[S_ARR_SRC_NEXT:%.+]] = getelementptr{{.+}}
// CHECK: [[CPY_IS_FINISHED:%.+]] = icmp eq [[S_INT_TY]]* [[S_ARR_DST_NEXT]], [[S_ARR_BEGIN_GEP]]
@@ -498,7 +514,7 @@ int main() {
// CHECK: [[TMP_VAL1:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP_PRIV1]],
// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[VAR_ADDR1_REF]] to i8*
// CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VAR_ADDR_REF_BCAST]], i8* [[TMP_VAL1_BCAST]],{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}})
// CHECK: ret void
// CHECK: define internal void [[TPAR_OUTL:@.+]](i{{[0-9]+}}* noalias [[GTID_ADDR1:%.+]], i{{[0-9]+}}* noalias %{{.+}}, {{.+}}, {{.+}}, [2 x i{{[0-9]+}}]*{{.+}} [[VEC_IN1:%.+]], i{{[0-9]+}}*{{.+}} [[T_VAR_IN1:%.+]], [2 x [[S_INT_TY]]]*{{.+}} [[S_ARR_IN1:%.+]], [[S_INT_TY]]*{{.+}} [[VAR_IN1:%.+]])
@@ -554,7 +570,7 @@ int main() {
// CHECK-DAG: [[TMP_VAL1:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP_PRIV1]],
// CHECK-DAG: [[S_ARR_PTR_BCAST1:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_PTR1]] to i8*
// CHECK-DAG: [[TMP_VAL_BCAST1:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_PTR_BCAST1]], i8* [[TMP_VAL_BCAST1]],
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_PTR_BCAST1]], i8* align {{[0-9]+}} [[TMP_VAL_BCAST1]],
// CHECK: call void @__kmpc_for_static_fini(
@@ -571,7 +587,7 @@ int main() {
// CHECK: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_ADDR_REF1]],
// CHECK: [[BCAST_VEC_ADDR_REF:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_REF1]] to i8*
// CHECK: [[BCAST_VEC_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[BCAST_VEC_ADDR_REF]], i8* [[BCAST_VEC_PRIV]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[BCAST_VEC_ADDR_REF]], i8* align {{[0-9]+}} [[BCAST_VEC_PRIV]],
// CHECK: [[S_ARR_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_ADDR_REF]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[S_ARR_PRIV_BCAST:%.+]] = bitcast [2 x [[S_INT_TY]]]* [[S_ARR_PRIV1]] to [[S_INT_TY]]*
// CHECK: [[S_ARR_BEGIN_GEP:%.+]] = getelementptr [[S_INT_TY]], [[S_INT_TY]]* [[S_ARR_BEGIN]], i{{[0-9]+}} 2
@@ -582,7 +598,7 @@ int main() {
// CHECK: [[S_ARR_DST_EL:%.+]] = phi [[S_INT_TY]]*{{.+}}
// CHECK: [[S_ARR_DST_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_DST_EL]] to i8*
// CHECK: [[S_ARR_SRC_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_SRC_EL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_DST_BCAST]], i8* [[S_ARR_SRC_BCAST]]{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_DST_BCAST]], i8* align {{[0-9]+}} [[S_ARR_SRC_BCAST]]{{.+}})
// CHECK: [[S_ARR_DST_NEXT:%.+]] = getelementptr [[S_INT_TY]], [[S_INT_TY]]* [[S_ARR_DST_EL]], i{{[0-9]+}} 1
// CHECK: [[S_ARR_SRC_NEXT:%.+]] = getelementptr{{.+}}
// CHECK: [[CPY_IS_FINISHED:%.+]] = icmp eq [[S_INT_TY]]* [[S_ARR_DST_NEXT]], [[S_ARR_BEGIN_GEP]]
@@ -591,7 +607,7 @@ int main() {
// CHECK: [[TMP_VAL1:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP_PRIV1]],
// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[VAR_ADDR1_REF]] to i8*
// CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VAR_ADDR_REF_BCAST]], i8* [[TMP_VAL1_BCAST]],{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}})
// CHECK: ret void
// CHECK: !{!"llvm.loop.vectorize.enable", i1 true}
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_messages.cpp
index 204be4c95e91..416d409acc13 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_messages.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wno-openmp-target
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_linear_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_linear_messages.cpp
index c0a9baf916dd..e60f2c9dbc68 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_linear_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_linear_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
namespace X {
int x;
};
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_loop_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_loop_messages.cpp
index 66361b64eb84..9980a1d11a7e 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_loop_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_loop_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+
class S {
int a;
S() : a(0) {} // expected-note {{implicitly declared private here}}
@@ -695,7 +697,7 @@ void test_loop_firstprivate_lastprivate() {
S s(4);
// expected-error@+2 {{lastprivate variable cannot be firstprivate}} expected-note@+2 {{defined as lastprivate}}
#pragma omp target
-#pragma omp teams distribute parallel for simd lastprivate(s) firstprivate(s) // expected-error {{calling a private constructor of class 'S'}}
+#pragma omp teams distribute parallel for simd lastprivate(s) firstprivate(s) // expected-error {{calling a private constructor of class 'S'}} expected-warning {{Non-trivial type 'S' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (int i = 0; i < 16; ++i)
;
}
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_messages.cpp
index 12ac8f9a9479..d27e156161f8 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_num_teams_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_num_teams_messages.cpp
index 7affd607b9d0..5e4ce0c86471 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_num_teams_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_num_teams_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_codegen.cpp
index aa7b9331da12..8c0c8208ab80 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_codegen.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_codegen.cpp
@@ -1,6 +1,11 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-ibm-linux-gnu -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-ibm-linux-gnu -fexceptions -fcxx-exceptions -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-ibm-linux-gnu -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-ibm-linux-gnu -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-ibm-linux-gnu -fexceptions -fcxx-exceptions -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-ibm-linux-gnu -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_messages.cpp
index fc71569e65ac..1f9b61e46437 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_private_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_private_codegen.cpp
index a6dbd29a5b96..b2c8c22b84d8 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_private_codegen.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_private_codegen.cpp
@@ -1,13 +1,26 @@
-// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_private_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_private_messages.cpp
index dc1ef5794206..50bf034891d9 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_private_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_private_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_proc_bind_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_proc_bind_codegen.cpp
index 7f95a877ab85..08b3cd3a47ba 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_proc_bind_codegen.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_proc_bind_codegen.cpp
@@ -3,6 +3,11 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -57,7 +62,7 @@ int main() {
// CHECK: [[GTID_REF:%.+]] = load i32*, i32** [[GTID_ADDR]],
// CHECK: [[GTID_VAL:%.+]] = load i32, i32* [[GTID_REF]],
// CHECK: call {{.*}}void @__kmpc_push_proc_bind([[IDENT_T_TY]]* [[DEF_LOC_2]], i32 [[GTID_VAL]], i32 4)
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
// CHECK: ret void
// CHECK: define{{.+}} [[OFFL2]]()
@@ -69,7 +74,7 @@ int main() {
// CHECK: [[GTID_REF:%.+]] = load i32*, i32** [[GTID_ADDR]],
// CHECK: [[GTID_VAL:%.+]] = load i32, i32* [[GTID_REF]],
// CHECK: call {{.*}}void @__kmpc_push_proc_bind([[IDENT_T_TY]]* [[DEF_LOC_2]], i32 [[GTID_VAL]], i32 3)
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
// CHECK: ret void
// CHECK: define{{.+}} [[TMAIN]]()
@@ -85,7 +90,7 @@ int main() {
// CHECK: [[GTID_REF:%.+]] = load i32*, i32** [[GTID_ADDR]],
// CHECK: [[GTID_VAL:%.+]] = load i32, i32* [[GTID_REF]],
// CHECK: call {{.*}}void @__kmpc_push_proc_bind([[IDENT_T_TY]]* [[DEF_LOC_2]], i32 [[GTID_VAL]], i32 2)
-// CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+// CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
// CHECK: ret void
// CHECK: !{!"llvm.loop.vectorize.enable", i1 true}
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_proc_bind_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_proc_bind_messages.cpp
index fd904299cd6d..459f40f494c2 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_proc_bind_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_proc_bind_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+
void foo();
template <class T, typename S, int N>
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_reduction_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_reduction_codegen.cpp
index 384ac4b5f32a..f97f0a050c34 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_reduction_codegen.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_reduction_codegen.cpp
@@ -5,10 +5,23 @@
// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_reduction_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_reduction_messages.cpp
index b0522e8f69d2..a17ffe392b87 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_reduction_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_reduction_messages.cpp
@@ -1,6 +1,10 @@
-// RUN: %clang_cc1 -verify -fopenmp %s
-// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
-// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp %s -Wno-openmp-target
+// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s -Wno-openmp-target
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wno-openmp-target
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s -Wno-openmp-target
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s -Wno-openmp-target
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_safelen_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_safelen_messages.cpp
index 82fd4b0da837..e673bb382af6 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_safelen_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_safelen_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_schedule_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_schedule_codegen.cpp
index 71e8ee8e8110..ea99cc7b569d 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_schedule_codegen.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_schedule_codegen.cpp
@@ -9,6 +9,14 @@
// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
#ifdef CK1
template <typename T, int X, long long Y>
@@ -151,6 +159,14 @@ int teams_template_struct(void) {
// RUN: %clang_cc1 -DCK2 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
#ifdef CK2
template <typename T, int n>
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_shared_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_shared_messages.cpp
index 1089555889f0..90f3cf46b90d 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_shared_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_shared_messages.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wno-openmp-target
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_simdlen_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_simdlen_messages.cpp
index 82fd4b0da837..e673bb382af6 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_simdlen_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_simdlen_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_thread_limit_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_thread_limit_messages.cpp
index 81ed9475d356..b5a95760eb0d 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_thread_limit_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_thread_limit_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_parallel_for_thread_limit_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_thread_limit_messages.cpp
index 4018f3f07d0f..ad37b5389c63 100644
--- a/test/OpenMP/teams_distribute_parallel_for_thread_limit_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_thread_limit_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_private_codegen.cpp b/test/OpenMP/teams_distribute_private_codegen.cpp
index 8e4a61cd7cb1..8880e2f51769 100644
--- a/test/OpenMP/teams_distribute_private_codegen.cpp
+++ b/test/OpenMP/teams_distribute_private_codegen.cpp
@@ -1,13 +1,26 @@
-// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
diff --git a/test/OpenMP/teams_distribute_private_messages.cpp b/test/OpenMP/teams_distribute_private_messages.cpp
index aff1f539894d..5fa002aadaaa 100644
--- a/test/OpenMP/teams_distribute_private_messages.cpp
+++ b/test/OpenMP/teams_distribute_private_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_reduction_codegen.cpp b/test/OpenMP/teams_distribute_reduction_codegen.cpp
index 961891da98d0..019306c6106d 100644
--- a/test/OpenMP/teams_distribute_reduction_codegen.cpp
+++ b/test/OpenMP/teams_distribute_reduction_codegen.cpp
@@ -5,10 +5,23 @@
// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/teams_distribute_reduction_messages.cpp b/test/OpenMP/teams_distribute_reduction_messages.cpp
index f11236f0ce27..4b9d6e51b2cc 100644
--- a/test/OpenMP/teams_distribute_reduction_messages.cpp
+++ b/test/OpenMP/teams_distribute_reduction_messages.cpp
@@ -1,6 +1,10 @@
-// RUN: %clang_cc1 -verify -fopenmp %s
-// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
-// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp %s -Wno-openmp-target
+// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s -Wno-openmp-target
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wno-openmp-target
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s -Wno-openmp-target
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s -Wno-openmp-target
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_shared_messages.cpp b/test/OpenMP/teams_distribute_shared_messages.cpp
index ecf6f2e03673..b1828eb43c42 100644
--- a/test/OpenMP/teams_distribute_shared_messages.cpp
+++ b/test/OpenMP/teams_distribute_shared_messages.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wno-openmp-target
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_simd_aligned_messages.cpp b/test/OpenMP/teams_distribute_simd_aligned_messages.cpp
index 885432bb9a1e..34227c659a3e 100644
--- a/test/OpenMP/teams_distribute_simd_aligned_messages.cpp
+++ b/test/OpenMP/teams_distribute_simd_aligned_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -x c++ -std=c++11 -verify -fopenmp %s
+// RUN: %clang_cc1 -x c++ -std=c++11 -verify -fopenmp-simd %s
+
struct B {
static int ib[20]; // expected-note 0 {{'B::ib' declared here}}
static constexpr int bfoo() { return 8; }
diff --git a/test/OpenMP/teams_distribute_simd_ast_print.cpp b/test/OpenMP/teams_distribute_simd_ast_print.cpp
index e751413c4232..b3d8ce436d4a 100644
--- a/test/OpenMP/teams_distribute_simd_ast_print.cpp
+++ b/test/OpenMP/teams_distribute_simd_ast_print.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -122,7 +126,7 @@ T tmain(T argc) {
for (int i=0; i < 2; ++i)
a = 2;
// CHECK: #pragma omp target
-// CHECK-NEXT: #pragma omp teams distribute simd
+// CHECK-NEXT: #pragma omp teams distribute simd{{$}}
// CHECK-NEXT: for (int i = 0; i < 2; ++i)
// CHECK-NEXT: a = 2;
#pragma omp target
diff --git a/test/OpenMP/teams_distribute_simd_codegen.cpp b/test/OpenMP/teams_distribute_simd_codegen.cpp
index cad5854a2f1e..813d3912c398 100644
--- a/test/OpenMP/teams_distribute_simd_codegen.cpp
+++ b/test/OpenMP/teams_distribute_simd_codegen.cpp
@@ -8,6 +8,14 @@
// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
#ifdef CK1
int a[100];
@@ -92,6 +100,14 @@ int teams_argument_global(int n) {
// RUN: %clang_cc1 -DCK2 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
#ifdef CK2
// CK2: define {{.*}}i32 @{{.+}}teams_local_argv(
@@ -129,6 +145,14 @@ int teams_local_arg(void) {
// RUN: %clang_cc1 -DCK3 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-32
// RUN: %clang_cc1 -DCK3 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK3 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-32
+
+// RUN: %clang_cc1 -DCK3 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// RUN: %clang_cc1 -DCK3 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK3 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// RUN: %clang_cc1 -DCK3 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// RUN: %clang_cc1 -DCK3 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK3 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY2 %s
+// SIMD-ONLY2-NOT: {{__kmpc|__tgt}}
#ifdef CK3
// CK3: [[SSI:%.+]] = type { [{{.+}} x i32], float }
@@ -178,6 +202,14 @@ int teams_template_struct(void) {
// RUN: %clang_cc1 -DCK4 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK4 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK4 --check-prefix CK4-32
+// RUN: %clang_cc1 -DCK4 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY3 %s
+// RUN: %clang_cc1 -DCK4 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK4 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY3 %s
+// RUN: %clang_cc1 -DCK4 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY3 %s
+// RUN: %clang_cc1 -DCK4 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK4 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY3 %s
+// SIMD-ONLY3-NOT: {{__kmpc|__tgt}}
+
#ifdef CK4
template <typename T, int n>
diff --git a/test/OpenMP/teams_distribute_simd_collapse_codegen.cpp b/test/OpenMP/teams_distribute_simd_collapse_codegen.cpp
index 071d1672fad1..41c494a562d7 100644
--- a/test/OpenMP/teams_distribute_simd_collapse_codegen.cpp
+++ b/test/OpenMP/teams_distribute_simd_collapse_codegen.cpp
@@ -9,6 +9,14 @@
// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
#ifdef CK1
template <typename T, int X, long long Y>
@@ -63,6 +71,14 @@ int teams_template_struct(void) {
// RUN: %clang_cc1 -DCK2 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
#ifdef CK2
template <typename T, int n, int m>
diff --git a/test/OpenMP/teams_distribute_simd_collapse_messages.cpp b/test/OpenMP/teams_distribute_simd_collapse_messages.cpp
index 0f62be2861d1..d0b2f814bf8b 100644
--- a/test/OpenMP/teams_distribute_simd_collapse_messages.cpp
+++ b/test/OpenMP/teams_distribute_simd_collapse_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_simd_default_messages.cpp b/test/OpenMP/teams_distribute_simd_default_messages.cpp
index a6685b9202ea..af176f46cbfc 100644
--- a/test/OpenMP/teams_distribute_simd_default_messages.cpp
+++ b/test/OpenMP/teams_distribute_simd_default_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo();
int main(int argc, char **argv) {
diff --git a/test/OpenMP/teams_distribute_simd_dist_schedule_codegen.cpp b/test/OpenMP/teams_distribute_simd_dist_schedule_codegen.cpp
index 599e18f58a16..8937a44f89e8 100644
--- a/test/OpenMP/teams_distribute_simd_dist_schedule_codegen.cpp
+++ b/test/OpenMP/teams_distribute_simd_dist_schedule_codegen.cpp
@@ -9,6 +9,14 @@
// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK1 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32
+
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK1 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
#ifdef CK1
template <typename T, int X, long long Y>
@@ -85,6 +93,14 @@ int teams_template_struct(void) {
// RUN: %clang_cc1 -DCK2 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCK2 -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32
+
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK2 -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
#ifdef CK2
template <typename T, int n>
diff --git a/test/OpenMP/teams_distribute_simd_dist_schedule_messages.cpp b/test/OpenMP/teams_distribute_simd_dist_schedule_messages.cpp
index 5274204b1ac6..3eb0db923b81 100644
--- a/test/OpenMP/teams_distribute_simd_dist_schedule_messages.cpp
+++ b/test/OpenMP/teams_distribute_simd_dist_schedule_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_simd_firstprivate_codegen.cpp b/test/OpenMP/teams_distribute_simd_firstprivate_codegen.cpp
index e503f5267f19..27320191faef 100644
--- a/test/OpenMP/teams_distribute_simd_firstprivate_codegen.cpp
+++ b/test/OpenMP/teams_distribute_simd_firstprivate_codegen.cpp
@@ -1,13 +1,26 @@
-// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
-// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
-
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
@@ -206,8 +219,8 @@ int main() {
// CHECK: store i{{[0-9]+}} {{.+}}, i{{[0-9]+}}* [[SIVAR_ADDR]],
// T_VAR and SIVAR
-// CHECK-DAG-64: [[CONV_TVAR:%.+]] = bitcast i64* [[T_VAR_ADDR]] to i32*
-// CHECK-DAG-64: [[CONV_SIVAR:%.+]] = bitcast i64* [[SIVAR_ADDR]] to i32*
+// CHECK-64-DAG: [[CONV_TVAR:%.+]] = bitcast i64* [[T_VAR_ADDR]] to i32*
+// CHECK-64-DAG: [[CONV_SIVAR:%.+]] = bitcast i64* [[SIVAR_ADDR]] to i32*
// preparation vars
// CHECK-DAG: [[VEC_ADDR_VAL:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]],
@@ -217,7 +230,7 @@ int main() {
// firstprivate vec(vec): copy from *_addr into priv1 and then from priv1 into priv2
// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VEC_DEST_PRIV]], i8* [[VEC_SRC]], {{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST_PRIV]], i8* align {{[0-9]+}} [[VEC_SRC]], {{.+}})
// firstprivate(s_arr)
// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]],
@@ -237,13 +250,13 @@ int main() {
// CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]])
// CHECK: call void @__kmpc_for_static_init_4(
-// CHECK-DAG-32: {{.+}} = {{.+}} [[T_VAR_ADDR]]
-// CHECK-DAG-64: {{.+}} = {{.+}} [[CONV_TVAR]]
+// CHECK-32-DAG: {{.+}} = {{.+}} [[T_VAR_ADDR]]
+// CHECK-64-DAG: {{.+}} = {{.+}} [[CONV_TVAR]]
// CHECK-DAG: {{.+}} = {{.+}} [[VEC_PRIV]]
// CHECK-DAG: {{.+}} = {{.+}} [[S_ARR_PRIV]]
// CHECK-DAG: {{.+}} = {{.+}} [[VAR_PRIV]]
-// CHECK-DAG-32: {{.+}} = {{.+}} [[SIVAR_ADDR]]
-// CHECK-DAG-64: {{.+}} = {{.+}} [[CONV_SIVAR]]
+// CHECK-32-DAG: {{.+}} = {{.+}} [[SIVAR_ADDR]]
+// CHECK-64-DAG: {{.+}} = {{.+}} [[CONV_SIVAR]]
// CHECK: call void @__kmpc_for_static_fini(
// CHECK: ret void
@@ -303,7 +316,7 @@ int main() {
// firstprivate vec(vec): copy from *_addr into priv1 and then from priv1 into priv2
// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VEC_DEST_PRIV]], i8* [[VEC_SRC]], {{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST_PRIV]], i8* align {{[0-9]+}} [[VEC_SRC]], {{.+}})
// firstprivate(s_arr)
// CHECK-DAG: [[S_ARR_PRIV_BGN:%.+]] = getelementptr{{.*}} [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_PRIV]],
@@ -325,8 +338,8 @@ int main() {
// CHECK-DAG: store [[S_INT_TY]]* [[VAR_PRIV]], [[S_INT_TY]]** [[TMP]],
// CHECK: call void @__kmpc_for_static_init_4(
-// CHECK-DAG-32: {{.+}} = {{.+}} [[T_VAR_ADDR]]
-// CHECK-DAG-64: {{.+}} = {{.+}} [[CONV_TVAR]]
+// CHECK-32-DAG: {{.+}} = {{.+}} [[T_VAR_ADDR]]
+// CHECK-64-DAG: {{.+}} = {{.+}} [[CONV_TVAR]]
// CHECK-DAG: {{.+}} = {{.+}} [[VEC_PRIV]]
// CHECK-DAG: {{.+}} = {{.+}} [[TMP]]
// CHECK-DAG: {{.+}} = {{.+}} [[S_ARR_PRIV]]
diff --git a/test/OpenMP/teams_distribute_simd_firstprivate_messages.cpp b/test/OpenMP/teams_distribute_simd_firstprivate_messages.cpp
index bcc0e351c66e..5b074c4cda10 100644
--- a/test/OpenMP/teams_distribute_simd_firstprivate_messages.cpp
+++ b/test/OpenMP/teams_distribute_simd_firstprivate_messages.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wno-openmp-target
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_simd_lastprivate_codegen.cpp b/test/OpenMP/teams_distribute_simd_lastprivate_codegen.cpp
index 3a18b75cf405..86cfd00f8c7a 100644
--- a/test/OpenMP/teams_distribute_simd_lastprivate_codegen.cpp
+++ b/test/OpenMP/teams_distribute_simd_lastprivate_codegen.cpp
@@ -1,16 +1,32 @@
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target| FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -232,7 +248,7 @@ int main() {
// CHECK-DAG: [[TMP_VAL:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP_PRIV]],
// CHECK-DAG: [[S_ARR_PTR_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_PTR]] to i8*
// CHECK-DAG: [[TMP_VAL_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_VAL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_PTR_BCAST]], i8* [[TMP_VAL_BCAST]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_PTR_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL_BCAST]],
// CHECK: call void @__kmpc_for_static_fini(
// lastprivates
@@ -245,7 +261,7 @@ int main() {
// CHECK: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_ADDR_REF]],
// CHECK: [[BCAST_VEC_ADDR_REF:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_REF]] to i8*
// CHECK: [[BCAST_VEC_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[BCAST_VEC_ADDR_REF]], i8* [[BCAST_VEC_PRIV]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[BCAST_VEC_ADDR_REF]], i8* align {{[0-9]+}} [[BCAST_VEC_PRIV]],
// CHECK: [[S_ARR_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_ADDR_REF]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[S_ARR_PRIV_BCAST:%.+]] = bitcast [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]] to [[S_FLOAT_TY]]*
// CHECK: [[S_ARR_BEGIN_GEP:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[S_ARR_BEGIN]], i{{[0-9]+}} 2
@@ -256,7 +272,7 @@ int main() {
// CHECK: [[S_ARR_DST_EL:%.+]] = phi [[S_FLOAT_TY]]*{{.+}}
// CHECK: [[S_ARR_DST_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_DST_EL]] to i8*
// CHECK: [[S_ARR_SRC_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[S_ARR_SRC_EL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_DST_BCAST]], i8* [[S_ARR_SRC_BCAST]]{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_DST_BCAST]], i8* align {{[0-9]+}} [[S_ARR_SRC_BCAST]]{{.+}})
// CHECK: [[S_ARR_DST_NEXT:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[S_ARR_DST_EL]], i{{[0-9]+}} 1
// CHECK: [[S_ARR_SRC_NEXT:%.+]] = getelementptr{{.+}}
// CHECK: [[CPY_IS_FINISHED:%.+]] = icmp eq [[S_FLOAT_TY]]* [[S_ARR_DST_NEXT]], [[S_ARR_BEGIN_GEP]]
@@ -265,7 +281,7 @@ int main() {
// CHECK: [[TMP_VAL1:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP_PRIV]],
// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[VAR_ADDR_REF]] to i8*
// CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VAR_ADDR_REF_BCAST]], i8* [[TMP_VAL1_BCAST]],{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}})
// CHECK: [[SVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[S_VAR_PRIV]],
// CHECK: store i{{[0-9]+}} [[SVAR_VAL]], i{{[0-9]+}}* [[SVAR_ADDR_REF]],
// CHECK: ret void
@@ -332,7 +348,7 @@ int main() {
// CHECK-DAG: [[TMP_VAL1:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP_PRIV1]],
// CHECK-DAG: [[S_ARR_PTR_BCAST1:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_PTR1]] to i8*
// CHECK-DAG: [[TMP_VAL_BCAST1:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_PTR_BCAST1]], i8* [[TMP_VAL_BCAST1]],
+// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_PTR_BCAST1]], i8* align {{[0-9]+}} [[TMP_VAL_BCAST1]],
// CHECK: call void @__kmpc_for_static_fini(
// lastprivates
@@ -345,7 +361,7 @@ int main() {
// CHECK: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_ADDR_REF1]],
// CHECK: [[BCAST_VEC_ADDR_REF:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_REF1]] to i8*
// CHECK: [[BCAST_VEC_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[BCAST_VEC_ADDR_REF]], i8* [[BCAST_VEC_PRIV]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[BCAST_VEC_ADDR_REF]], i8* align {{[0-9]+}} [[BCAST_VEC_PRIV]],
// CHECK: [[S_ARR_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_ADDR_REF]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[S_ARR_PRIV_BCAST:%.+]] = bitcast [2 x [[S_INT_TY]]]* [[S_ARR_PRIV1]] to [[S_INT_TY]]*
// CHECK: [[S_ARR_BEGIN_GEP:%.+]] = getelementptr [[S_INT_TY]], [[S_INT_TY]]* [[S_ARR_BEGIN]], i{{[0-9]+}} 2
@@ -356,7 +372,7 @@ int main() {
// CHECK: [[S_ARR_DST_EL:%.+]] = phi [[S_INT_TY]]*{{.+}}
// CHECK: [[S_ARR_DST_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_DST_EL]] to i8*
// CHECK: [[S_ARR_SRC_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[S_ARR_SRC_EL]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[S_ARR_DST_BCAST]], i8* [[S_ARR_SRC_BCAST]]{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[S_ARR_DST_BCAST]], i8* align {{[0-9]+}} [[S_ARR_SRC_BCAST]]{{.+}})
// CHECK: [[S_ARR_DST_NEXT:%.+]] = getelementptr [[S_INT_TY]], [[S_INT_TY]]* [[S_ARR_DST_EL]], i{{[0-9]+}} 1
// CHECK: [[S_ARR_SRC_NEXT:%.+]] = getelementptr{{.+}}
// CHECK: [[CPY_IS_FINISHED:%.+]] = icmp eq [[S_INT_TY]]* [[S_ARR_DST_NEXT]], [[S_ARR_BEGIN_GEP]]
@@ -365,7 +381,7 @@ int main() {
// CHECK: [[TMP_VAL1:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP_PRIV1]],
// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[VAR_ADDR1_REF]] to i8*
// CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL1]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VAR_ADDR_REF_BCAST]], i8* [[TMP_VAL1_BCAST]],{{.+}})
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}})
// CHECK: ret void
// CHECK: !{!"llvm.loop.vectorize.enable", i1 true}
#endif
diff --git a/test/OpenMP/teams_distribute_simd_lastprivate_messages.cpp b/test/OpenMP/teams_distribute_simd_lastprivate_messages.cpp
index 51dbfef22933..08605912d8e4 100644
--- a/test/OpenMP/teams_distribute_simd_lastprivate_messages.cpp
+++ b/test/OpenMP/teams_distribute_simd_lastprivate_messages.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wno-openmp-target
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_simd_linear_messages.cpp b/test/OpenMP/teams_distribute_simd_linear_messages.cpp
index a53f0e62dda2..a3984b98da82 100644
--- a/test/OpenMP/teams_distribute_simd_linear_messages.cpp
+++ b/test/OpenMP/teams_distribute_simd_linear_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
namespace X {
int x;
};
diff --git a/test/OpenMP/teams_distribute_simd_loop_messages.cpp b/test/OpenMP/teams_distribute_simd_loop_messages.cpp
index 60e07a3db596..8721dc50795f 100644
--- a/test/OpenMP/teams_distribute_simd_loop_messages.cpp
+++ b/test/OpenMP/teams_distribute_simd_loop_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+
class S {
int a;
S() : a(0) {} // expected-note {{implicitly declared private here}}
@@ -695,7 +697,7 @@ void test_loop_firstprivate_lastprivate() {
S s(4);
// expected-error@+2 {{lastprivate variable cannot be firstprivate}} expected-note@+2 {{defined as lastprivate}}
#pragma omp target
-#pragma omp teams distribute simd lastprivate(s) firstprivate(s) // expected-error {{calling a private constructor of class 'S'}}
+#pragma omp teams distribute simd lastprivate(s) firstprivate(s) // expected-error {{calling a private constructor of class 'S'}} expected-warning {{Non-trivial type 'S' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (int i = 0; i < 16; ++i)
;
}
diff --git a/test/OpenMP/teams_distribute_simd_messages.cpp b/test/OpenMP/teams_distribute_simd_messages.cpp
index b00de796b0ed..79128706bc94 100644
--- a/test/OpenMP/teams_distribute_simd_messages.cpp
+++ b/test/OpenMP/teams_distribute_simd_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_simd_num_teams_messages.cpp b/test/OpenMP/teams_distribute_simd_num_teams_messages.cpp
index e65025a317ee..86164642b82f 100644
--- a/test/OpenMP/teams_distribute_simd_num_teams_messages.cpp
+++ b/test/OpenMP/teams_distribute_simd_num_teams_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_simd_private_codegen.cpp b/test/OpenMP/teams_distribute_simd_private_codegen.cpp
index ca9a673e2441..fc7000a6996c 100644
--- a/test/OpenMP/teams_distribute_simd_private_codegen.cpp
+++ b/test/OpenMP/teams_distribute_simd_private_codegen.cpp
@@ -1,13 +1,26 @@
-// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
diff --git a/test/OpenMP/teams_distribute_simd_private_messages.cpp b/test/OpenMP/teams_distribute_simd_private_messages.cpp
index 90442130d263..94fb9098a7d1 100644
--- a/test/OpenMP/teams_distribute_simd_private_messages.cpp
+++ b/test/OpenMP/teams_distribute_simd_private_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_simd_reduction_codegen.cpp b/test/OpenMP/teams_distribute_simd_reduction_codegen.cpp
index 3153cce3a923..10901dea12f9 100644
--- a/test/OpenMP/teams_distribute_simd_reduction_codegen.cpp
+++ b/test/OpenMP/teams_distribute_simd_reduction_codegen.cpp
@@ -5,10 +5,23 @@
// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/teams_distribute_simd_reduction_messages.cpp b/test/OpenMP/teams_distribute_simd_reduction_messages.cpp
index 09d22bd4bd81..49b45b7bc6fb 100644
--- a/test/OpenMP/teams_distribute_simd_reduction_messages.cpp
+++ b/test/OpenMP/teams_distribute_simd_reduction_messages.cpp
@@ -1,6 +1,10 @@
-// RUN: %clang_cc1 -verify -fopenmp %s
-// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
-// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp %s -Wno-openmp-target
+// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s -Wno-openmp-target
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wno-openmp-target
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s -Wno-openmp-target
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s -Wno-openmp-target
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_simd_safelen_messages.cpp b/test/OpenMP/teams_distribute_simd_safelen_messages.cpp
index a323c0883c5b..7be581a96b96 100644
--- a/test/OpenMP/teams_distribute_simd_safelen_messages.cpp
+++ b/test/OpenMP/teams_distribute_simd_safelen_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_simd_shared_messages.cpp b/test/OpenMP/teams_distribute_simd_shared_messages.cpp
index 6b06f5b6f203..b29e2bb8557e 100644
--- a/test/OpenMP/teams_distribute_simd_shared_messages.cpp
+++ b/test/OpenMP/teams_distribute_simd_shared_messages.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wno-openmp-target
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_simd_simdlen_messages.cpp b/test/OpenMP/teams_distribute_simd_simdlen_messages.cpp
index a323c0883c5b..7be581a96b96 100644
--- a/test/OpenMP/teams_distribute_simd_simdlen_messages.cpp
+++ b/test/OpenMP/teams_distribute_simd_simdlen_messages.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_simd_thread_limit_messages.cpp b/test/OpenMP/teams_distribute_simd_thread_limit_messages.cpp
index b9c8ac3e3615..732bb3447355 100644
--- a/test/OpenMP/teams_distribute_simd_thread_limit_messages.cpp
+++ b/test/OpenMP/teams_distribute_simd_thread_limit_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/teams_distribute_thread_limit_messages.cpp b/test/OpenMP/teams_distribute_thread_limit_messages.cpp
index ec4ca7a05f27..d22cc25b5b59 100644
--- a/test/OpenMP/teams_distribute_thread_limit_messages.cpp
+++ b/test/OpenMP/teams_distribute_thread_limit_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 %s
+
void foo() {
}
diff --git a/test/OpenMP/teams_firstprivate_codegen.cpp b/test/OpenMP/teams_firstprivate_codegen.cpp
index 3248bfeebd91..a2b41440f38c 100644
--- a/test/OpenMP/teams_firstprivate_codegen.cpp
+++ b/test/OpenMP/teams_firstprivate_codegen.cpp
@@ -1,24 +1,48 @@
// Test host codegen.
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
-// RUN: %clang_cc1 -DARRAY -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix ARRAY --check-prefix ARRAY-64
-// RUN: %clang_cc1 -DARRAY -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DARRAY -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix ARRAY --check-prefix ARRAY-64
-// RUN: %clang_cc1 -DARRAY -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix ARRAY --check-prefix ARRAY-32
-// RUN: %clang_cc1 -DARRAY -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DARRAY -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix ARRAY --check-prefix ARRAY-32
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
+// RUN: %clang_cc1 -DARRAY -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix ARRAY --check-prefix ARRAY-64
+// RUN: %clang_cc1 -DARRAY -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DARRAY -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix ARRAY --check-prefix ARRAY-64
+// RUN: %clang_cc1 -DARRAY -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix ARRAY --check-prefix ARRAY-32
+// RUN: %clang_cc1 -DARRAY -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DARRAY -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix ARRAY --check-prefix ARRAY-32
+
+// RUN: %clang_cc1 -DARRAY -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY2 %s
+// RUN: %clang_cc1 -DARRAY -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DARRAY -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY2 %s
+// RUN: %clang_cc1 -DARRAY -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY2 %s
+// RUN: %clang_cc1 -DARRAY -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target
+// RUN: %clang_cc1 -DARRAY -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY2 %s
+// SIMD-ONLY2-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -148,7 +172,7 @@ int main() {
// CHECK-64: [[SIVAR7_CONV:%.+]] = bitcast i64* [[SIVAR7_PRIV]] to i32*
// CHECK: [[VEC_DEST:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
// CHECK: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_REF]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VEC_DEST]], i8* [[VEC_SRC]],
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST]], i8* align {{[0-9]+}} [[VEC_SRC]],
// CHECK: [[S_ARR_PRIV_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[S_ARR_BEGIN:%.+]] = bitcast [2 x [[S_FLOAT_TY]]]* [[S_ARR_REF]] to [[S_FLOAT_TY]]*
// CHECK: [[S_ARR_PRIV_END:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[S_ARR_PRIV_BEGIN]], i{{[0-9]+}} 2
@@ -200,7 +224,7 @@ int main() {
// CHECK: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_PRIV]], align 128
// CHECK: [[VEC_DEST:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
// CHECK: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_REF]] to i8*
-// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VEC_DEST]], i8* [[VEC_SRC]], i{{[0-9]+}} {{[0-9]+}}, i{{[0-9]+}} 128,
+// CHECK: call void @llvm.memcpy.{{.+}}(i8* align 128 [[VEC_DEST]], i8* align 128 [[VEC_SRC]], i{{[0-9]+}} {{[0-9]+}},
// CHECK: [[S_ARR_PRIV_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_PRIV]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[S_ARR_BEGIN:%.+]] = bitcast [2 x [[S_INT_TY]]]* [[S_ARR_REF]] to [[S_INT_TY]]*
// CHECK: [[S_ARR_PRIV_END:%.+]] = getelementptr [[S_INT_TY]], [[S_INT_TY]]* [[S_ARR_PRIV_BEGIN]], i{{[0-9]+}} 2
@@ -260,7 +284,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) {
// ARRAY-DAG: store double* %{{.+}}, double** [[PRIV_VLA2]],
// ARRAY: call i8* @llvm.stacksave()
// ARRAY: [[SIZE:%.+]] = mul nuw i{{[0-9]+}} %{{.+}}, 8
-// ARRAY: call void @llvm.memcpy.p0i8.p0i8.i{{[0-9]+}}(i8* %{{.+}}, i8* %{{.+}}, i{{[0-9]+}} [[SIZE]], i32 128, i1 false)
+// ARRAY: call void @llvm.memcpy.p0i8.p0i8.i{{[0-9]+}}(i8* align 128 %{{.+}}, i8* align 128 %{{.+}}, i{{[0-9]+}} [[SIZE]], i1 false)
#pragma omp target
#pragma omp teams firstprivate(a, s, vla1, vla2)
s[0].St_func(s, n, vla1);
@@ -278,6 +302,6 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) {
// ARRAY-DAG: store double* %{{.+}}, double** [[PRIV_VLA2]],
// ARRAY: call i8* @llvm.stacksave()
// ARRAY: [[SIZE:%.+]] = mul nuw i{{[0-9]+}} %{{.+}}, 8
-// ARRAY: call void @llvm.memcpy.p0i8.p0i8.i{{[0-9]+}}(i8* %{{.+}}, i8* %{{.+}}, i{{[0-9]+}} [[SIZE]], i32 128, i1 false)
+// ARRAY: call void @llvm.memcpy.p0i8.p0i8.i{{[0-9]+}}(i8* align 128 %{{.+}}, i8* align 128 %{{.+}}, i{{[0-9]+}} [[SIZE]], i1 false)
#endif
#endif
diff --git a/test/OpenMP/teams_firstprivate_messages.cpp b/test/OpenMP/teams_firstprivate_messages.cpp
index ba12fde86b5c..d29a2e3960f6 100644
--- a/test/OpenMP/teams_firstprivate_messages.cpp
+++ b/test/OpenMP/teams_firstprivate_messages.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wno-openmp-target
void foo() {
}
diff --git a/test/OpenMP/teams_messages.cpp b/test/OpenMP/teams_messages.cpp
index 642fe73cac75..6ed3be9da58d 100644
--- a/test/OpenMP/teams_messages.cpp
+++ b/test/OpenMP/teams_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/teams_num_teams_messages.cpp b/test/OpenMP/teams_num_teams_messages.cpp
index 01871127bda5..47b2b4eafe34 100644
--- a/test/OpenMP/teams_num_teams_messages.cpp
+++ b/test/OpenMP/teams_num_teams_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/teams_private_codegen.cpp b/test/OpenMP/teams_private_codegen.cpp
index 7ddf39c9b0ea..0df111c3eb42 100644
--- a/test/OpenMP/teams_private_codegen.cpp
+++ b/test/OpenMP/teams_private_codegen.cpp
@@ -5,12 +5,28 @@
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/teams_private_messages.cpp b/test/OpenMP/teams_private_messages.cpp
index 344ef8daf996..30c7a0abd68f 100644
--- a/test/OpenMP/teams_private_messages.cpp
+++ b/test/OpenMP/teams_private_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+
void foo() {
}
diff --git a/test/OpenMP/teams_reduction_messages.cpp b/test/OpenMP/teams_reduction_messages.cpp
index 7aef97730d9e..94a47436c123 100644
--- a/test/OpenMP/teams_reduction_messages.cpp
+++ b/test/OpenMP/teams_reduction_messages.cpp
@@ -1,6 +1,10 @@
-// RUN: %clang_cc1 -verify -fopenmp -o - %s
-// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -o - %s
-// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp -o - %s -Wno-openmp-target
+// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -o - %s -Wno-openmp-target
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -o - %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -o - %s -Wno-openmp-target
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 -o - %s -Wno-openmp-target
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -o - %s -Wno-openmp-target
void foo() {
}
diff --git a/test/OpenMP/teams_shared_messages.cpp b/test/OpenMP/teams_shared_messages.cpp
index 6b013d099dce..a83b82f37f33 100644
--- a/test/OpenMP/teams_shared_messages.cpp
+++ b/test/OpenMP/teams_shared_messages.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp %s -Wno-openmp-target
+
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wno-openmp-target
void foo() {
}
diff --git a/test/OpenMP/teams_thread_limit_messages.cpp b/test/OpenMP/teams_thread_limit_messages.cpp
index 1cb147c60781..0c5a22cf3031 100644
--- a/test/OpenMP/teams_thread_limit_messages.cpp
+++ b/test/OpenMP/teams_thread_limit_messages.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 100 -o - %s
+
void foo() {
}
diff --git a/test/OpenMP/threadprivate_ast_print.cpp b/test/OpenMP/threadprivate_ast_print.cpp
index 5502c62134b5..a1482031f5bf 100644
--- a/test/OpenMP/threadprivate_ast_print.cpp
+++ b/test/OpenMP/threadprivate_ast_print.cpp
@@ -4,6 +4,13 @@
// RUN: %clang_cc1 -verify -fopenmp -triple x86_64-unknown-linux-gnu -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -fnoopenmp-use-tls -triple x86_64-unknown-linux-gnu -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fnoopenmp-use-tls -triple x86_64-unknown-linux-gnu -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -triple x86_64-apple-darwin10.6.0 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -triple x86_64-apple-darwin10.6.0 -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -triple x86_64-apple-darwin10.6.0 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print
+// RUN: %clang_cc1 -verify -fopenmp-simd -triple x86_64-unknown-linux-gnu -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -fnoopenmp-use-tls -triple x86_64-unknown-linux-gnu -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fnoopenmp-use-tls -triple x86_64-unknown-linux-gnu -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print
// expected-no-diagnostics
#ifndef HEADER
@@ -18,7 +25,7 @@ struct St1{
static int b;
// CHECK: static int b;
#pragma omp threadprivate(b)
-// CHECK-NEXT: #pragma omp threadprivate(St1::b)
+// CHECK-NEXT: #pragma omp threadprivate(St1::b){{$}}
} d;
int a, b;
diff --git a/test/OpenMP/threadprivate_codegen.cpp b/test/OpenMP/threadprivate_codegen.cpp
index 3785b70c19ba..1f403111e7e2 100644
--- a/test/OpenMP/threadprivate_codegen.cpp
+++ b/test/OpenMP/threadprivate_codegen.cpp
@@ -2,10 +2,20 @@
// RUN: %clang_cc1 -fopenmp -fnoopenmp-use-tls -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fnoopenmp-use-tls -DBODY -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -debug-info-kind=limited -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix=CHECK-DEBUG %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fnoopenmp-use-tls -DBODY -triple x86_64-unknown-unknown -x c++ -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fnoopenmp-use-tls -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fnoopenmp-use-tls -DBODY -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -debug-info-kind=limited -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
// RUN: %clang_cc1 -verify -fopenmp -DBODY -triple x86_64-unknown-unknown -x c++ -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s --check-prefix=CHECK-TLS
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -DBODY -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -debug-info-kind=limited -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix=CHECK-TLS %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -DBODY -triple x86_64-unknown-unknown -x c++ -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -DBODY -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -debug-info-kind=limited -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
+
// expected-no-diagnostics
//
#ifndef HEADER
@@ -144,26 +154,26 @@ struct S5 {
// CHECK-DEBUG-DAG: [[ST_INT_ST:@.+]] = linkonce_odr global i32 23
// CHECK-DEBUG-DAG: [[ST_FLOAT_ST:@.+]] = linkonce_odr global float 2.300000e+01
// CHECK-DEBUG-DAG: [[ST_S4_ST:@.+]] = linkonce_odr global %struct.S4 zeroinitializer
-// CHECK-DEBUG-DAG: [[LOC1:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;;192;9;;\00"
-// CHECK-DEBUG-DAG: [[LOC2:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;;247;9;;\00"
-// CHECK-DEBUG-DAG: [[LOC3:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;;334;19;;\00"
-// CHECK-DEBUG-DAG: [[LOC4:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;main;371;9;;\00"
-// CHECK-DEBUG-DAG: [[LOC5:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;main;388;9;;\00"
-// CHECK-DEBUG-DAG: [[LOC6:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;main;410;10;;\00"
-// CHECK-DEBUG-DAG: [[LOC7:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;main;433;10;;\00"
-// CHECK-DEBUG-DAG: [[LOC8:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;main;469;10;;\00"
-// CHECK-DEBUG-DAG: [[LOC9:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;main;498;10;;\00"
-// CHECK-DEBUG-DAG: [[LOC10:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;main;518;10;;\00"
-// CHECK-DEBUG-DAG: [[LOC11:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;main;541;27;;\00"
-// CHECK-DEBUG-DAG: [[LOC12:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;main;564;10;;\00"
-// CHECK-DEBUG-DAG: [[LOC13:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;foobar;684;9;;\00"
-// CHECK-DEBUG-DAG: [[LOC14:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;foobar;707;10;;\00"
-// CHECK-DEBUG-DAG: [[LOC15:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;foobar;743;10;;\00"
-// CHECK-DEBUG-DAG: [[LOC16:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;foobar;772;10;;\00"
-// CHECK-DEBUG-DAG: [[LOC17:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;foobar;792;10;;\00"
-// CHECK-DEBUG-DAG: [[LOC18:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;foobar;815;27;;\00"
-// CHECK-DEBUG-DAG: [[LOC19:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;foobar;838;10;;\00"
-// CHECK-DEBUG-DAG: [[LOC20:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;;306;9;;\00"
+// CHECK-DEBUG-DAG: [[LOC1:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;;201;9;;\00"
+// CHECK-DEBUG-DAG: [[LOC2:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;;256;9;;\00"
+// CHECK-DEBUG-DAG: [[LOC3:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;;343;19;;\00"
+// CHECK-DEBUG-DAG: [[LOC4:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;main;380;9;;\00"
+// CHECK-DEBUG-DAG: [[LOC5:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;main;397;9;;\00"
+// CHECK-DEBUG-DAG: [[LOC6:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;main;419;10;;\00"
+// CHECK-DEBUG-DAG: [[LOC7:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;main;442;10;;\00"
+// CHECK-DEBUG-DAG: [[LOC8:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;main;478;10;;\00"
+// CHECK-DEBUG-DAG: [[LOC9:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;main;507;10;;\00"
+// CHECK-DEBUG-DAG: [[LOC10:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;main;527;10;;\00"
+// CHECK-DEBUG-DAG: [[LOC11:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;main;550;27;;\00"
+// CHECK-DEBUG-DAG: [[LOC12:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;main;573;10;;\00"
+// CHECK-DEBUG-DAG: [[LOC13:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;foobar;693;9;;\00"
+// CHECK-DEBUG-DAG: [[LOC14:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;foobar;716;10;;\00"
+// CHECK-DEBUG-DAG: [[LOC15:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;foobar;752;10;;\00"
+// CHECK-DEBUG-DAG: [[LOC16:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;foobar;781;10;;\00"
+// CHECK-DEBUG-DAG: [[LOC17:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;foobar;801;10;;\00"
+// CHECK-DEBUG-DAG: [[LOC18:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;foobar;824;27;;\00"
+// CHECK-DEBUG-DAG: [[LOC19:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;foobar;847;10;;\00"
+// CHECK-DEBUG-DAG: [[LOC20:@.*]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";{{.*}}threadprivate_codegen.cpp;;315;9;;\00"
// CHECK-TLS-DAG: [[GS1:@.+]] = internal thread_local global [[S1]] zeroinitializer
// CHECK-TLS-DAG: [[GS2:@.+]] = internal global [[S2]] zeroinitializer
// CHECK-TLS-DAG: [[ARR_X:@.+]] = thread_local global [2 x [3 x [[S1]]]] zeroinitializer
@@ -180,7 +190,6 @@ struct S5 {
// CHECK-TLS-DAG: [[GS1_TLS_INIT:@_ZTHL3gs1]] = internal alias void (), void ()* @__tls_init
// CHECK-TLS-DAG: [[ARR_X_TLS_INIT:@_ZTH5arr_x]] = alias void (), void ()* @__tls_init
-
// CHECK-TLS-DAG: [[ST_S4_ST_TLS_INIT:@_ZTHN2STI2S4E2stE]] = linkonce_odr alias void (), void ()* [[ST_S4_ST_CXX_INIT:@[^, ]*]]
struct Static {
diff --git a/test/OpenMP/threadprivate_messages.cpp b/test/OpenMP/threadprivate_messages.cpp
index 9775bfa458f4..62ddfd1e639c 100644
--- a/test/OpenMP/threadprivate_messages.cpp
+++ b/test/OpenMP/threadprivate_messages.cpp
@@ -1,6 +1,9 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -fnoopenmp-use-tls -ferror-limit 100 -emit-llvm -o - %s
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -emit-llvm -o - %s
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -fnoopenmp-use-tls -ferror-limit 100 -emit-llvm -o - %s
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -ferror-limit 100 -emit-llvm -o - %s
+
#pragma omp threadprivate // expected-error {{expected '(' after 'threadprivate'}}
#pragma omp threadprivate( // expected-error {{expected identifier}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp threadprivate() // expected-error {{expected identifier}}
diff --git a/test/OpenMP/varargs.cpp b/test/OpenMP/varargs.cpp
index 7738f83fab24..4730c1025d32 100644
--- a/test/OpenMP/varargs.cpp
+++ b/test/OpenMP/varargs.cpp
@@ -1,4 +1,7 @@
// RUN: %clang_cc1 -verify -fopenmp %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
void f(int a, ...) {
#pragma omp parallel for
for (int i = 0; i < 100; ++i) {
diff --git a/test/OpenMP/vla_crash.c b/test/OpenMP/vla_crash.c
index 0dcba5503e4c..00cada4a6453 100644
--- a/test/OpenMP/vla_crash.c
+++ b/test/OpenMP/vla_crash.c
@@ -1,5 +1,8 @@
// RUN: %clang_cc1 -verify -triple powerpc64le-unknown-linux-gnu -fopenmp -x c -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -triple powerpc64le-unknown-linux-gnu -fopenmp-simd -x c -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
int a;
// CHECK-LABEL: foo
diff --git a/test/PCH/Inputs/pch-through-use0.cpp b/test/PCH/Inputs/pch-through-use0.cpp
new file mode 100644
index 000000000000..a39080144fbb
--- /dev/null
+++ b/test/PCH/Inputs/pch-through-use0.cpp
@@ -0,0 +1,2 @@
+void foo() {
+}
diff --git a/test/PCH/Inputs/pch-through-use1.cpp b/test/PCH/Inputs/pch-through-use1.cpp
new file mode 100644
index 000000000000..4eda7cecc951
--- /dev/null
+++ b/test/PCH/Inputs/pch-through-use1.cpp
@@ -0,0 +1,5 @@
+#include "Inputs/pch-through1.h"
+#include "Inputs/pch-through3.h"
+void foo() {
+ through2(0);
+}
diff --git a/test/PCH/Inputs/pch-through-use2.cpp b/test/PCH/Inputs/pch-through-use2.cpp
new file mode 100644
index 000000000000..217803ba398c
--- /dev/null
+++ b/test/PCH/Inputs/pch-through-use2.cpp
@@ -0,0 +1,3 @@
+void foo() {
+ through4(0);
+}
diff --git a/test/PCH/Inputs/pch-through-use3a.cpp b/test/PCH/Inputs/pch-through-use3a.cpp
new file mode 100644
index 000000000000..dfd1d11071c0
--- /dev/null
+++ b/test/PCH/Inputs/pch-through-use3a.cpp
@@ -0,0 +1,2 @@
+#define AFOO 0
+#include "Inputs/pch-through1.h"
diff --git a/test/PCH/Inputs/pch-through-use3b.cpp b/test/PCH/Inputs/pch-through-use3b.cpp
new file mode 100644
index 000000000000..5b547647d85b
--- /dev/null
+++ b/test/PCH/Inputs/pch-through-use3b.cpp
@@ -0,0 +1,3 @@
+#define AFOO 1
+#define BFOO 2
+#include "Inputs/pch-through1.h"
diff --git a/test/PCH/Inputs/pch-through1.h b/test/PCH/Inputs/pch-through1.h
new file mode 100644
index 000000000000..7ebfa7d5df28
--- /dev/null
+++ b/test/PCH/Inputs/pch-through1.h
@@ -0,0 +1,2 @@
+#define THROUGH1
+int through1(int);
diff --git a/test/PCH/Inputs/pch-through2.h b/test/PCH/Inputs/pch-through2.h
new file mode 100644
index 000000000000..4c1f2981f932
--- /dev/null
+++ b/test/PCH/Inputs/pch-through2.h
@@ -0,0 +1,2 @@
+#define THROUGH2
+int through2(int);
diff --git a/test/PCH/Inputs/pch-through3.h b/test/PCH/Inputs/pch-through3.h
new file mode 100644
index 000000000000..28368655004d
--- /dev/null
+++ b/test/PCH/Inputs/pch-through3.h
@@ -0,0 +1,2 @@
+#define THROUGH3
+int through3(int);
diff --git a/test/PCH/Inputs/pch-through4.h b/test/PCH/Inputs/pch-through4.h
new file mode 100644
index 000000000000..95860edd196b
--- /dev/null
+++ b/test/PCH/Inputs/pch-through4.h
@@ -0,0 +1,2 @@
+#define THROUGH4
+int through4(int);
diff --git a/test/PCH/Inputs/std-compare.h b/test/PCH/Inputs/std-compare.h
new file mode 100644
index 000000000000..a6ab605bb527
--- /dev/null
+++ b/test/PCH/Inputs/std-compare.h
@@ -0,0 +1,437 @@
+#ifndef STD_COMPARE_H
+#define STD_COMPARE_H
+
+namespace std {
+inline namespace __1 {
+
+// exposition only
+enum class _EqResult : unsigned char {
+ __zero = 0,
+ __equal = __zero,
+ __equiv = __equal,
+ __nonequal = 1,
+ __nonequiv = __nonequal
+};
+
+enum class _OrdResult : signed char {
+ __less = -1,
+ __greater = 1
+};
+
+enum class _NCmpResult : signed char {
+ __unordered = -127
+};
+
+struct _CmpUnspecifiedType;
+using _CmpUnspecifiedParam = void (_CmpUnspecifiedType::*)();
+
+class weak_equality {
+ constexpr explicit weak_equality(_EqResult __val) noexcept : __value_(__val) {}
+
+public:
+ static const weak_equality equivalent;
+ static const weak_equality nonequivalent;
+
+ friend constexpr bool operator==(weak_equality __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator==(_CmpUnspecifiedParam, weak_equality __v) noexcept;
+ friend constexpr bool operator!=(weak_equality __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator!=(_CmpUnspecifiedParam, weak_equality __v) noexcept;
+ friend constexpr weak_equality operator<=>(weak_equality __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr weak_equality operator<=>(_CmpUnspecifiedParam, weak_equality __v) noexcept;
+
+ // test helper
+ constexpr bool test_eq(weak_equality const &other) const noexcept {
+ return __value_ == other.__value_;
+ }
+
+private:
+ _EqResult __value_;
+};
+
+inline constexpr weak_equality weak_equality::equivalent(_EqResult::__equiv);
+inline constexpr weak_equality weak_equality::nonequivalent(_EqResult::__nonequiv);
+inline constexpr bool operator==(weak_equality __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ == _EqResult::__zero;
+}
+inline constexpr bool operator==(_CmpUnspecifiedParam, weak_equality __v) noexcept {
+ return __v.__value_ == _EqResult::__zero;
+}
+inline constexpr bool operator!=(weak_equality __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ != _EqResult::__zero;
+}
+inline constexpr bool operator!=(_CmpUnspecifiedParam, weak_equality __v) noexcept {
+ return __v.__value_ != _EqResult::__zero;
+}
+
+inline constexpr weak_equality operator<=>(weak_equality __v, _CmpUnspecifiedParam) noexcept {
+ return __v;
+}
+inline constexpr weak_equality operator<=>(_CmpUnspecifiedParam, weak_equality __v) noexcept {
+ return __v;
+}
+
+class strong_equality {
+ explicit constexpr strong_equality(_EqResult __val) noexcept : __value_(__val) {}
+
+public:
+ static const strong_equality equal;
+ static const strong_equality nonequal;
+ static const strong_equality equivalent;
+ static const strong_equality nonequivalent;
+
+ // conversion
+ constexpr operator weak_equality() const noexcept {
+ return __value_ == _EqResult::__zero ? weak_equality::equivalent
+ : weak_equality::nonequivalent;
+ }
+
+ // comparisons
+ friend constexpr bool operator==(strong_equality __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator!=(strong_equality __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator==(_CmpUnspecifiedParam, strong_equality __v) noexcept;
+ friend constexpr bool operator!=(_CmpUnspecifiedParam, strong_equality __v) noexcept;
+
+ friend constexpr strong_equality operator<=>(strong_equality __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr strong_equality operator<=>(_CmpUnspecifiedParam, strong_equality __v) noexcept;
+
+ // test helper
+ constexpr bool test_eq(strong_equality const &other) const noexcept {
+ return __value_ == other.__value_;
+ }
+
+private:
+ _EqResult __value_;
+};
+
+inline constexpr strong_equality strong_equality::equal(_EqResult::__equal);
+inline constexpr strong_equality strong_equality::nonequal(_EqResult::__nonequal);
+inline constexpr strong_equality strong_equality::equivalent(_EqResult::__equiv);
+inline constexpr strong_equality strong_equality::nonequivalent(_EqResult::__nonequiv);
+constexpr bool operator==(strong_equality __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ == _EqResult::__zero;
+}
+constexpr bool operator==(_CmpUnspecifiedParam, strong_equality __v) noexcept {
+ return __v.__value_ == _EqResult::__zero;
+}
+constexpr bool operator!=(strong_equality __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ != _EqResult::__zero;
+}
+constexpr bool operator!=(_CmpUnspecifiedParam, strong_equality __v) noexcept {
+ return __v.__value_ != _EqResult::__zero;
+}
+
+constexpr strong_equality operator<=>(strong_equality __v, _CmpUnspecifiedParam) noexcept {
+ return __v;
+}
+constexpr strong_equality operator<=>(_CmpUnspecifiedParam, strong_equality __v) noexcept {
+ return __v;
+}
+
+class partial_ordering {
+ using _ValueT = signed char;
+ explicit constexpr partial_ordering(_EqResult __v) noexcept
+ : __value_(_ValueT(__v)) {}
+ explicit constexpr partial_ordering(_OrdResult __v) noexcept
+ : __value_(_ValueT(__v)) {}
+ explicit constexpr partial_ordering(_NCmpResult __v) noexcept
+ : __value_(_ValueT(__v)) {}
+
+ constexpr bool __is_ordered() const noexcept {
+ return __value_ != _ValueT(_NCmpResult::__unordered);
+ }
+
+public:
+ // valid values
+ static const partial_ordering less;
+ static const partial_ordering equivalent;
+ static const partial_ordering greater;
+ static const partial_ordering unordered;
+
+ // conversion
+ constexpr operator weak_equality() const noexcept {
+ return __value_ == 0 ? weak_equality::equivalent : weak_equality::nonequivalent;
+ }
+
+ // comparisons
+ friend constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator!=(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator<(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator>(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator==(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
+ friend constexpr bool operator!=(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
+ friend constexpr bool operator<(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
+ friend constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
+ friend constexpr bool operator>(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
+ friend constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
+
+ friend constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
+
+ // test helper
+ constexpr bool test_eq(partial_ordering const &other) const noexcept {
+ return __value_ == other.__value_;
+ }
+
+private:
+ _ValueT __value_;
+};
+
+inline constexpr partial_ordering partial_ordering::less(_OrdResult::__less);
+inline constexpr partial_ordering partial_ordering::equivalent(_EqResult::__equiv);
+inline constexpr partial_ordering partial_ordering::greater(_OrdResult::__greater);
+inline constexpr partial_ordering partial_ordering::unordered(_NCmpResult ::__unordered);
+constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__is_ordered() && __v.__value_ == 0;
+}
+constexpr bool operator<(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__is_ordered() && __v.__value_ < 0;
+}
+constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__is_ordered() && __v.__value_ <= 0;
+}
+constexpr bool operator>(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__is_ordered() && __v.__value_ > 0;
+}
+constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__is_ordered() && __v.__value_ >= 0;
+}
+constexpr bool operator==(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
+ return __v.__is_ordered() && 0 == __v.__value_;
+}
+constexpr bool operator<(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
+ return __v.__is_ordered() && 0 < __v.__value_;
+}
+constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
+ return __v.__is_ordered() && 0 <= __v.__value_;
+}
+constexpr bool operator>(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
+ return __v.__is_ordered() && 0 > __v.__value_;
+}
+constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
+ return __v.__is_ordered() && 0 >= __v.__value_;
+}
+constexpr bool operator!=(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return !__v.__is_ordered() || __v.__value_ != 0;
+}
+constexpr bool operator!=(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
+ return !__v.__is_ordered() || __v.__value_ != 0;
+}
+
+constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v;
+}
+constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
+ return __v < 0 ? partial_ordering::greater : (__v > 0 ? partial_ordering::less : __v);
+}
+
+class weak_ordering {
+ using _ValueT = signed char;
+ explicit constexpr weak_ordering(_EqResult __v) noexcept : __value_(_ValueT(__v)) {}
+ explicit constexpr weak_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {}
+
+public:
+ static const weak_ordering less;
+ static const weak_ordering equivalent;
+ static const weak_ordering greater;
+
+ // conversions
+ constexpr operator weak_equality() const noexcept {
+ return __value_ == 0 ? weak_equality::equivalent
+ : weak_equality::nonequivalent;
+ }
+ constexpr operator partial_ordering() const noexcept {
+ return __value_ == 0 ? partial_ordering::equivalent
+ : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater);
+ }
+
+ // comparisons
+ friend constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator!=(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator<(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator>(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator==(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
+ friend constexpr bool operator!=(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
+ friend constexpr bool operator<(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
+ friend constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
+ friend constexpr bool operator>(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
+ friend constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
+
+ friend constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
+
+ // test helper
+ constexpr bool test_eq(weak_ordering const &other) const noexcept {
+ return __value_ == other.__value_;
+ }
+
+private:
+ _ValueT __value_;
+};
+
+inline constexpr weak_ordering weak_ordering::less(_OrdResult::__less);
+inline constexpr weak_ordering weak_ordering::equivalent(_EqResult::__equiv);
+inline constexpr weak_ordering weak_ordering::greater(_OrdResult::__greater);
+constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ == 0;
+}
+constexpr bool operator!=(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ != 0;
+}
+constexpr bool operator<(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ < 0;
+}
+constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ <= 0;
+}
+constexpr bool operator>(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ > 0;
+}
+constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ >= 0;
+}
+constexpr bool operator==(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
+ return 0 == __v.__value_;
+}
+constexpr bool operator!=(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
+ return 0 != __v.__value_;
+}
+constexpr bool operator<(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
+ return 0 < __v.__value_;
+}
+constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
+ return 0 <= __v.__value_;
+}
+constexpr bool operator>(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
+ return 0 > __v.__value_;
+}
+constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
+ return 0 >= __v.__value_;
+}
+
+constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v;
+}
+constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
+ return __v < 0 ? weak_ordering::greater : (__v > 0 ? weak_ordering::less : __v);
+}
+
+class strong_ordering {
+ using _ValueT = signed char;
+ explicit constexpr strong_ordering(_EqResult __v) noexcept : __value_(static_cast<signed char>(__v)) {}
+ explicit constexpr strong_ordering(_OrdResult __v) noexcept : __value_(static_cast<signed char>(__v)) {}
+
+public:
+ static const strong_ordering less;
+ static const strong_ordering equal;
+ static const strong_ordering equivalent;
+ static const strong_ordering greater;
+
+ // conversions
+ constexpr operator weak_equality() const noexcept {
+ return __value_ == 0 ? weak_equality::equivalent
+ : weak_equality::nonequivalent;
+ }
+ constexpr operator strong_equality() const noexcept {
+ return __value_ == 0 ? strong_equality::equal
+ : strong_equality::nonequal;
+ }
+ constexpr operator partial_ordering() const noexcept {
+ return __value_ == 0 ? partial_ordering::equivalent
+ : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater);
+ }
+ constexpr operator weak_ordering() const noexcept {
+ return __value_ == 0 ? weak_ordering::equivalent
+ : (__value_ < 0 ? weak_ordering::less : weak_ordering::greater);
+ }
+
+ // comparisons
+ friend constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator!=(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator<(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator>(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator==(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
+ friend constexpr bool operator!=(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
+ friend constexpr bool operator<(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
+ friend constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
+ friend constexpr bool operator>(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
+ friend constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
+
+ friend constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
+
+ // test helper
+ constexpr bool test_eq(strong_ordering const &other) const noexcept {
+ return __value_ == other.__value_;
+ }
+
+private:
+ _ValueT __value_;
+};
+
+inline constexpr strong_ordering strong_ordering::less(_OrdResult::__less);
+inline constexpr strong_ordering strong_ordering::equal(_EqResult::__equal);
+inline constexpr strong_ordering strong_ordering::equivalent(_EqResult::__equiv);
+inline constexpr strong_ordering strong_ordering::greater(_OrdResult::__greater);
+
+constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ == 0;
+}
+constexpr bool operator!=(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ != 0;
+}
+constexpr bool operator<(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ < 0;
+}
+constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ <= 0;
+}
+constexpr bool operator>(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ > 0;
+}
+constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ >= 0;
+}
+constexpr bool operator==(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
+ return 0 == __v.__value_;
+}
+constexpr bool operator!=(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
+ return 0 != __v.__value_;
+}
+constexpr bool operator<(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
+ return 0 < __v.__value_;
+}
+constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
+ return 0 <= __v.__value_;
+}
+constexpr bool operator>(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
+ return 0 > __v.__value_;
+}
+constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
+ return 0 >= __v.__value_;
+}
+
+constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v;
+}
+constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
+ return __v < 0 ? strong_ordering::greater : (__v > 0 ? strong_ordering::less : __v);
+}
+
+// named comparison functions
+constexpr bool is_eq(weak_equality __cmp) noexcept { return __cmp == 0; }
+constexpr bool is_neq(weak_equality __cmp) noexcept { return __cmp != 0; }
+constexpr bool is_lt(partial_ordering __cmp) noexcept { return __cmp < 0; }
+constexpr bool is_lteq(partial_ordering __cmp) noexcept { return __cmp <= 0; }
+constexpr bool is_gt(partial_ordering __cmp) noexcept { return __cmp > 0; }
+constexpr bool is_gteq(partial_ordering __cmp) noexcept { return __cmp >= 0; }
+
+} // namespace __1
+} // end namespace std
+
+#endif // STD_COMPARE_H
diff --git a/test/PCH/chain-openmp-threadprivate.cpp b/test/PCH/chain-openmp-threadprivate.cpp
index c7f0f4195967..d719d4d2949c 100644
--- a/test/PCH/chain-openmp-threadprivate.cpp
+++ b/test/PCH/chain-openmp-threadprivate.cpp
@@ -23,7 +23,7 @@ int *a = malloc(20);
#else
// CHECK: call {{.*}} @__kmpc_threadprivate_register(
-// CHECK-TLS-1: @{{a|\"\\01\?a@@3PE?AHE?A\"}} = {{.*}}thread_local {{.*}}global {{.*}}i32*
+// CHECK-TLS-1: @{{a|\"\?a@@3PE?AHE?A\"}} = {{.*}}thread_local {{.*}}global {{.*}}i32*
// CHECK-LABEL: foo
// CHECK-TLS-LABEL: foo
@@ -31,9 +31,9 @@ int foo() {
return *a;
// CHECK: call {{.*}} @__kmpc_global_thread_num(
// CHECK: call {{.*}} @__kmpc_threadprivate_cached(
- // CHECK-TLS-1: call {{.*}} @{{_ZTW1a|\"\\01\?\?__Ea@@YAXXZ\"}}()
+ // CHECK-TLS-1: call {{.*}} @{{_ZTW1a|\"\?\?__Ea@@YAXXZ\"}}()
}
-// CHECK-TLS-2: define {{.*}} @{{_ZTW1a|\"\\01\?\?__Ea@@YAXXZ\"}}()
+// CHECK-TLS-2: define {{.*}} @{{_ZTW1a|\"\?\?__Ea@@YAXXZ\"}}()
#endif
diff --git a/test/PCH/cxx-required-decls.cpp b/test/PCH/cxx-required-decls.cpp
index c2f8e2fd68fe..132af6c95200 100644
--- a/test/PCH/cxx-required-decls.cpp
+++ b/test/PCH/cxx-required-decls.cpp
@@ -7,4 +7,4 @@
// CHECK: @_ZL5globS = internal global %struct.S zeroinitializer
// CHECK: @_ZL3bar = internal global i32 0, align 4
-// CHECK: @glob_var = global i32 0
+// CHECK: @glob_var = {{(dso_local )?}}global i32 0
diff --git a/test/PCH/cxx2a-compare.cpp b/test/PCH/cxx2a-compare.cpp
new file mode 100644
index 000000000000..9ad368d88fd9
--- /dev/null
+++ b/test/PCH/cxx2a-compare.cpp
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -pedantic-errors -std=c++2a -emit-pch %s -o %t
+// RUN: %clang_cc1 -pedantic-errors -std=c++2a -include-pch %t -verify %s
+// RUN: %clang_cc1 -pedantic-errors -std=c++2a -include-pch %t -emit-llvm %s -o -
+
+
+#ifndef HEADER
+#define HEADER
+
+#include "Inputs/std-compare.h"
+constexpr auto foo() {
+ return (42 <=> 101);
+}
+
+inline auto bar(int x) {
+ return (1 <=> x);
+}
+
+#else
+
+// expected-no-diagnostics
+
+static_assert(foo() < 0);
+
+auto bar2(int x) {
+ return bar(x);
+}
+
+#endif
diff --git a/test/PCH/cxx_exprs.cpp b/test/PCH/cxx_exprs.cpp
index 0fb7590c68b5..928a21125db0 100644
--- a/test/PCH/cxx_exprs.cpp
+++ b/test/PCH/cxx_exprs.cpp
@@ -1,9 +1,9 @@
// Test this without pch.
-// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -include %S/cxx_exprs.h -std=c++11 -fsyntax-only -verify %s -ast-dump
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -include %S/cxx_exprs.h -std=c++11 -fsyntax-only -verify %s -ast-dump | FileCheck %s
// Test with pch. Use '-ast-dump' to force deserialization of function bodies.
// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -x c++-header -std=c++11 -emit-pch -o %t %S/cxx_exprs.h
-// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-dump
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-dump-all | FileCheck %s
// expected-no-diagnostics
@@ -14,19 +14,49 @@ bool boolean;
// CXXStaticCastExpr
static_cast_result void_ptr = &integer;
+// CHECK: TypedefDecl {{.*}} <{{.*}}, col:{{.*}}> col:{{.*}}{{(imported)?}} referenced static_cast_result 'typeof (static_cast<void *>(0))':'void *'{{$}}
+// CHECK-NEXT: TypeOfExprType {{.*}} 'typeof (static_cast<void *>(0))' sugar{{( imported)?}}{{$}}
+// CHECK-NEXT: ParenExpr {{.*}} <col:{{.*}}, col:{{.*}}> 'void *'{{$}}
+// CHECK-NEXT: CXXStaticCastExpr {{.*}} <col:{{.*}}, col:{{.*}}> 'void *' static_cast<void *> <NoOp>{{$}}
+// CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'void *' <NullToPointer> part_of_explicit_cast{{$}}
+// CHECK-NEXT: IntegerLiteral {{.*}} <col:{{.*}}> 'int' 0{{$}}
// CXXDynamicCastExpr
Derived *d;
dynamic_cast_result derived_ptr = d;
+// CHECK: TypedefDecl {{.*}} <{{.*}}, col:{{.*}}> col:{{.*}} referenced dynamic_cast_result 'typeof (dynamic_cast<Derived *>(base_ptr))':'Derived *'{{$}}
+// CHECK-NEXT: TypeOfExprType {{.*}} 'typeof (dynamic_cast<Derived *>(base_ptr))' sugar{{( imported)?}}{{$}}
+// CHECK-NEXT: ParenExpr {{.*}} <col:{{.*}}, col:{{.*}}> 'Derived *'{{$}}
+// CHECK-NEXT: CXXDynamicCastExpr {{.*}} <col:{{.*}}, col:{{.*}}> 'Derived *' dynamic_cast<struct Derived *> <Dynamic>{{$}}
+// CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'Base *' <LValueToRValue> part_of_explicit_cast{{$}}
+// CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'Base *' lvalue Var {{.*}} 'base_ptr' 'Base *'{{$}}
// CXXReinterpretCastExpr
reinterpret_cast_result void_ptr2 = &integer;
+// CHECK: TypedefDecl {{.*}} <{{.*}}, col:{{.*}}> col:{{.*}} referenced reinterpret_cast_result 'typeof (reinterpret_cast<void *>(0))':'void *'{{$}}
+// CHECK-NEXT: TypeOfExprType {{.*}} 'typeof (reinterpret_cast<void *>(0))' sugar{{( imported)?}}{{$}}
+// CHECK-NEXT: ParenExpr {{.*}} <col:{{.*}}, col:{{.*}}> 'void *'{{$}}
+// CHECK-NEXT: CXXReinterpretCastExpr {{.*}} <col:{{.*}}, col:{{.*}}> 'void *' reinterpret_cast<void *> <IntegralToPointer>{{$}}
+// CHECK-NEXT: IntegerLiteral {{.*}} <col:{{.*}}> 'int' 0{{$}}
// CXXConstCastExpr
const_cast_result char_ptr = &character;
+// CHECK: TypedefDecl {{.*}} <{{.*}}, col:{{.*}}> col:{{.*}} referenced const_cast_result 'typeof (const_cast<char *>(const_char_ptr_value))':'char *'{{$}}
+// CHECK-NEXT: TypeOfExprType {{.*}} 'typeof (const_cast<char *>(const_char_ptr_value))' sugar{{( imported)?}}{{$}}
+// CHECK-NEXT: ParenExpr {{.*}} <col:{{.*}}, col:{{.*}}> 'char *'{{$}}
+// CHECK-NEXT: CXXConstCastExpr {{.*}} <col:{{.*}}, col:{{.*}}> 'char *' const_cast<char *> <NoOp>{{$}}
+// CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'const char *' <LValueToRValue> part_of_explicit_cast{{$}}
+// CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'const char *' lvalue Var {{.*}} 'const_char_ptr_value' 'const char *'{{$}}
// CXXFunctionalCastExpr
functional_cast_result *double_ptr = &floating;
+// CHECK: TypedefDecl {{.*}} <{{.*}}, col:{{.*}}> col:{{.*}} referenced functional_cast_result 'typeof (double(int_value))':'double'{{$}}
+// CHECK-NEXT: TypeOfExprType {{.*}} 'typeof (double(int_value))' sugar{{( imported)?}}{{$}}
+// CHECK-NEXT: ParenExpr {{.*}} <col:{{.*}}, col:{{.*}}> 'double'{{$}}
+// CHECK-NEXT: CXXFunctionalCastExpr {{.*}} <col:{{.*}}, col:{{.*}}> 'double' functional cast to double <NoOp>{{$}}
+// CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'double' <IntegralToFloating> part_of_explicit_cast{{$}}
+// CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'int' <LValueToRValue> part_of_explicit_cast{{$}}
+// CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'int' lvalue Var {{.*}} 'int_value' 'int'{{$}}
// CXXBoolLiteralExpr
bool_literal_result *bool_ptr = &boolean;
diff --git a/test/PCH/dllexport-default-arg-closure.cpp b/test/PCH/dllexport-default-arg-closure.cpp
index 892f1eb9bff8..32e0a721c775 100644
--- a/test/PCH/dllexport-default-arg-closure.cpp
+++ b/test/PCH/dllexport-default-arg-closure.cpp
@@ -17,8 +17,8 @@ struct __declspec(dllexport) Foo {
// Demangles as:
// void Foo::`default constructor closure'(void)
-// CHECK: define weak_odr dllexport void @"\01??_FFoo@@QEAAXXZ"(%struct.Foo*{{.*}})
-// CHECK: call %struct.Foo* @"\01??0Foo@@QEAA@W4E@0@@Z"(%struct.Foo* {{.*}}, i32 0)
+// CHECK: define weak_odr dso_local dllexport void @"??_FFoo@@QEAAXXZ"(%struct.Foo*{{.*}})
+// CHECK: call %struct.Foo* @"??0Foo@@QEAA@W4E@0@@Z"(%struct.Foo* {{.*}}, i32 0)
#else
diff --git a/test/PCH/include-stream-type.cpp b/test/PCH/include-stream-type.cpp
new file mode 100644
index 000000000000..30e2586b0bf0
--- /dev/null
+++ b/test/PCH/include-stream-type.cpp
@@ -0,0 +1,10 @@
+// Test that llvm-bcanalyzer recognizes the stream type of a PCH file.
+
+// RUN: mkdir -p %t-dir
+// Copying files allow for read-only checkouts to run this test.
+// RUN: cp %S/Inputs/pragma-once2-pch.h %t-dir
+// RUN: cp %S/Inputs/pragma-once2.h %t-dir
+// RUN: %clang_cc1 -x c++-header -emit-pch -fmodule-format=raw -o %t %t-dir/pragma-once2-pch.h
+// RUN: llvm-bcanalyzer -dump %t | FileCheck %s
+//
+// CHECK: Stream type: Clang Serialized AST
diff --git a/test/PCH/late-parsed-instantiations.cpp b/test/PCH/late-parsed-instantiations.cpp
new file mode 100644
index 000000000000..f1fe8bb06a51
--- /dev/null
+++ b/test/PCH/late-parsed-instantiations.cpp
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -fdelayed-template-parsing -std=c++14 -emit-pch %s -o %t.pch -verify
+// RUN: %clang_cc1 -fdelayed-template-parsing -std=c++14 -include-pch %t.pch %s -verify
+
+#ifndef HEADER_INCLUDED
+
+#define HEADER_INCLUDED
+
+// pr33561
+class ArrayBuffer;
+template <typename T> class Trans_NS_WTF_RefPtr {
+public:
+ ArrayBuffer *operator->() { return nullptr; }
+};
+Trans_NS_WTF_RefPtr<ArrayBuffer> get();
+template <typename _Visitor>
+constexpr void visit(_Visitor __visitor) {
+ __visitor(get()); // expected-note {{in instantiation}}
+}
+class ArrayBuffer {
+ char data() {
+ visit([](auto buffer) -> char { // expected-note {{in instantiation}}
+ buffer->data();
+ }); // expected-warning {{control reaches end of non-void lambda}}
+ } // expected-warning {{control reaches end of non-void function}}
+};
+
+#else
+
+// expected-no-diagnostics
+
+#endif
diff --git a/test/PCH/modified-header-crash.c b/test/PCH/modified-header-crash.c
index 4c21a8c2b825..39b2530a32f2 100644
--- a/test/PCH/modified-header-crash.c
+++ b/test/PCH/modified-header-crash.c
@@ -1,6 +1,6 @@
// Don't crash.
-// RUN: cp %S/modified-header-crash.h %t.h
+// RUN: cat %S/modified-header-crash.h > %t.h
// RUN: %clang_cc1 -DCAKE -x c-header %t.h -emit-pch -o %t
// RUN: echo 'int foobar;' >> %t.h
// RUN: not %clang_cc1 %s -include-pch %t -fsyntax-only
diff --git a/test/PCH/objc_stmts.m b/test/PCH/objc_stmts.m
index 8deb14a81545..ee7b780731a9 100644
--- a/test/PCH/objc_stmts.m
+++ b/test/PCH/objc_stmts.m
@@ -1,11 +1,11 @@
// Test this without pch.
-// RUN: %clang_cc1 -include %S/objc_stmts.h -emit-llvm -fobjc-exceptions -o - %s
-// RUN: %clang_cc1 -include %S/objc_stmts.h -ast-print -fobjc-exceptions -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.10 -include %S/objc_stmts.h -emit-llvm -fobjc-exceptions -o - %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.10 -include %S/objc_stmts.h -ast-print -fobjc-exceptions -o - %s | FileCheck %s
// Test with pch.
-// RUN: %clang_cc1 -x objective-c -emit-pch -fobjc-exceptions -o %t %S/objc_stmts.h
-// RUN: %clang_cc1 -include-pch %t -emit-llvm -fobjc-exceptions -o - %s
-// RUN: %clang_cc1 -include-pch %t -ast-print -fobjc-exceptions -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.10 -x objective-c -emit-pch -fobjc-exceptions -o %t %S/objc_stmts.h
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.10 -include-pch %t -emit-llvm -fobjc-exceptions -o - %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.10 -include-pch %t -ast-print -fobjc-exceptions -o - %s | FileCheck %s
// CHECK: @catch(A *a)
// CHECK: @catch(B *b)
diff --git a/test/PCH/pch-through1.cpp b/test/PCH/pch-through1.cpp
new file mode 100644
index 000000000000..b7e7fa82a19a
--- /dev/null
+++ b/test/PCH/pch-through1.cpp
@@ -0,0 +1,34 @@
+// Through header not found (anywhere)
+// RUN: not %clang_cc1 -emit-pch \
+// RUN: -pch-through-header=Inputs/pch-does-not-exist.h -o %t %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-TEST0A %s
+// CHECK-TEST0A: fatal error:{{.*}} 'Inputs/pch-does-not-exist.h'
+// CHECK-TEST0A-SAME: required for precompiled header not found
+
+// Through header not found in search path
+// RUN: not %clang_cc1 -emit-pch \
+// RUN: -pch-through-header=Inputs/pch-through2.h -o %t \
+// RUN: %S/Inputs/pch-through-use0.cpp 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-TEST0B %s
+// CHECK-TEST0B: fatal error:{{.*}}'Inputs/pch-through2.h'
+// CHECK-TEST0B-SAME: required for precompiled header not found
+
+// No #include of through header during pch create
+// RUN: not %clang_cc1 -I %S -emit-pch \
+// RUN: -pch-through-header=Inputs/pch-through2.h -o %t %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-TEST1A %s
+// CHECK-TEST1A: fatal error:{{.*}} #include of
+// CHECK-TEST1A-SAME: 'Inputs/pch-through2.h' not seen while attempting to
+// CHECK-TEST1A-SAME: create precompiled header
+
+// checks for through headers that are also -includes
+// RUN: %clang_cc1 -I %S -include Inputs/pch-through1.h \
+// RUN: -pch-through-header=Inputs/pch-through1.h -emit-pch -o %t.s3t1 %s
+// RUN: %clang_cc1 -I %S -include Inputs/pch-through1.h \
+// RUN: -include Inputs/pch-through2.h -include Inputs/pch-through3.h \
+// RUN: -pch-through-header=Inputs/pch-through2.h -emit-pch -o %t.s3t2 %s
+// Use through header from -includes
+// RUN: %clang_cc1 -I %S -include Inputs/pch-through1.h \
+// RUN: -include Inputs/pch-through2.h -include Inputs/pch-through4.h \
+// RUN: -pch-through-header=Inputs/pch-through2.h -include-pch %t.s3t2 \
+// RUN: %S/Inputs/pch-through-use2.cpp -o %t.out
diff --git a/test/PCH/pch-through2.cpp b/test/PCH/pch-through2.cpp
new file mode 100644
index 000000000000..6bf7a29d9a08
--- /dev/null
+++ b/test/PCH/pch-through2.cpp
@@ -0,0 +1,28 @@
+// Create
+// RUN: %clang_cc1 -I %S -emit-pch \
+// RUN: -pch-through-header=Inputs/pch-through2.h -o %t.1 %s
+
+// Use
+// RUN: %clang_cc1 -I %S -include-pch %t.1 \
+// RUN: -pch-through-header=Inputs/pch-through2.h %s
+
+// No #include of through header during pch use
+// RUN: not %clang_cc1 -I %S -include-pch %t.1 \
+// RUN: -pch-through-header=Inputs/pch-through2.h \
+// RUN: %S/Inputs/pch-through-use1.cpp 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-TEST2A %s
+// CHECK-TEST2A: fatal error:{{.*}} #include of
+// CHECK-TEST2A-SAME: 'Inputs/pch-through2.h' not seen while attempting to
+// CHECK-TEST2A-SAME: use precompiled header
+
+// check that pch only contains code before the through header.
+// RUN: %clang_cc1 -I %S -emit-pch \
+// RUN: -pch-through-header=Inputs/pch-through1.h -o %t.2 %s
+// RUN: not %clang_cc1 -I %S -include-pch %t.2 \
+// RUN: -pch-through-header=Inputs/pch-through1.h \
+// RUN: %S/Inputs/pch-through-use1.cpp 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-TEST3 %s
+// CHECK-TEST3: error: use of undeclared identifier 'through2'
+
+#include "Inputs/pch-through1.h"
+#include "Inputs/pch-through2.h"
diff --git a/test/PCH/pch-through3a.cpp b/test/PCH/pch-through3a.cpp
new file mode 100644
index 000000000000..3a134e9310bc
--- /dev/null
+++ b/test/PCH/pch-through3a.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -verify -I %S -emit-pch \
+// RUN: -pch-through-header=Inputs/pch-through1.h -o %t.s3at1 %s
+
+// RUN: %clang_cc1 -I %S -include-pch %t.s3at1 \
+// RUN: -pch-through-header=Inputs/pch-through1.h \
+// RUN: %S/Inputs/pch-through-use3a.cpp
+//expected-no-diagnostics
+
+#define AFOO 0
+#include "Inputs/pch-through1.h"
diff --git a/test/PCH/pch-through3b.cpp b/test/PCH/pch-through3b.cpp
new file mode 100644
index 000000000000..2a7695a7098a
--- /dev/null
+++ b/test/PCH/pch-through3b.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -I %S -emit-pch \
+// RUN: -pch-through-header=Inputs/pch-through1.h -o %t.s3bt1 %s
+
+// RUN: %clang_cc1 -I %S -include-pch %t.s3bt1 \
+// RUN: -pch-through-header=Inputs/pch-through1.h \
+// RUN: %S/Inputs/pch-through-use3b.cpp 2>&1 | FileCheck %s
+
+//CHECK: warning: definition of macro 'AFOO' does not match definition in
+//CHECK-SAME: precompiled header
+//CHECK: warning: definition of macro 'BFOO' does not match definition in
+//CHECK-SAME: precompiled header
+
+#define AFOO 0
+#include "Inputs/pch-through1.h"
diff --git a/test/PCH/pragma-loop.cpp b/test/PCH/pragma-loop.cpp
index 5975816f69a6..7f443ddb034e 100644
--- a/test/PCH/pragma-loop.cpp
+++ b/test/PCH/pragma-loop.cpp
@@ -4,7 +4,7 @@
// FIXME: A bug in ParsedAttributes causes the order of the attributes to be
// reversed. The checks are consequently in the reverse order below.
-// CHECK: #pragma clang loop unroll_count(16)
+// CHECK: #pragma clang loop unroll_count(16){{$}}
// CHECK: #pragma clang loop interleave_count(8)
// CHECK: #pragma clang loop vectorize_width(4)
// CHECK: #pragma clang loop distribute(enable)
@@ -15,9 +15,10 @@
// CHECK: #pragma clang loop unroll(full)
// CHECK: #pragma clang loop interleave(enable)
// CHECK: #pragma clang loop vectorize(disable)
-// CHECK: #pragma unroll
-// CHECK: #pragma unroll (32)
-// CHECK: #pragma nounroll
+// FIXME: "#pragma unroll (enable)" is invalid and is not the input source.
+// CHECK: #pragma unroll (enable){{$}}
+// CHECK: #pragma unroll (32){{$}}
+// CHECK: #pragma nounroll{{$}}
// CHECK: #pragma clang loop interleave_count(I)
// CHECK: #pragma clang loop vectorize_width(V)
diff --git a/test/PCH/pragma-weak.c b/test/PCH/pragma-weak.c
index 1a8724c35cd7..4a4819764025 100644
--- a/test/PCH/pragma-weak.c
+++ b/test/PCH/pragma-weak.c
@@ -5,6 +5,6 @@
// RUN: %clang_cc1 -x c-header -emit-pch -o %t %S/pragma-weak.h
// RUN: not %clang_cc1 -include-pch %t %s -verify -emit-llvm -o - | FileCheck %s
-// CHECK: @weakvar = weak global i32 0
+// CHECK: @weakvar = weak {{(dso_local )?}}global i32 0
int weakvar;
// expected-warning {{weak identifier 'undeclaredvar' never declared}}
diff --git a/test/PCH/uses-seh.cpp b/test/PCH/uses-seh.cpp
index 6fbfc9766c48..53ca1ef154ff 100644
--- a/test/PCH/uses-seh.cpp
+++ b/test/PCH/uses-seh.cpp
@@ -19,8 +19,8 @@ inline int f() {
}
int x = f();
-// CHECK: define linkonce_odr i32 @"\01?f@@YAHXZ"()
-// CHECK: define internal i32 @"\01?filt$0@0@f@@"({{.*}})
+// CHECK: define linkonce_odr dso_local i32 @"?f@@YAHXZ"()
+// CHECK: define internal i32 @"?filt$0@0@f@@"({{.*}})
#else
diff --git a/test/PCH/verify_pch.m b/test/PCH/verify_pch.m
index e905f2537c7f..d50e23456e35 100644
--- a/test/PCH/verify_pch.m
+++ b/test/PCH/verify_pch.m
@@ -2,7 +2,7 @@
// RUN: rm -rf %t
// RUN: mkdir -p %t/usr/include
// RUN: echo '// empty' > %t/usr/include/sys_header.h
-// RUN: cp %s %t.h
+// RUN: cat %s > %t.h
//
// Precompile
// RUN: %clang_cc1 -isystem %t/usr/include -x objective-c-header -emit-pch -o %t.pch %t.h
diff --git a/test/Parser/MicrosoftExtensions.cpp b/test/Parser/MicrosoftExtensions.cpp
index 21635f0ee12f..8799f49df6c4 100644
--- a/test/Parser/MicrosoftExtensions.cpp
+++ b/test/Parser/MicrosoftExtensions.cpp
@@ -424,3 +424,10 @@ struct S {
S(T);
} f([] {});
}
+
+namespace pr36638 {
+// Make sure we accept __unaligned method qualifiers on member function
+// pointers.
+struct A;
+void (A::*mp1)(int) __unaligned;
+}
diff --git a/test/Parser/brackets.c b/test/Parser/brackets.c
index a1003f399da9..4ce38bd1ce33 100644
--- a/test/Parser/brackets.c
+++ b/test/Parser/brackets.c
@@ -15,10 +15,10 @@ void test1() {
// CHECK: fix-it:{{.*}}:{[[@LINE-6]]:10-[[@LINE-6]]:10}:"[]"
int c = a[0];
- int d = b[0]; // No undeclared identifer error here.
+ int d = b[0]; // No undeclared identifier error here.
int *e = a;
- int *f = b; // No undeclared identifer error here.
+ int *f = b; // No undeclared identifier error here.
}
struct S {
diff --git a/test/Parser/brackets.cpp b/test/Parser/brackets.cpp
index 6963a75ab399..415cbdda83f5 100644
--- a/test/Parser/brackets.cpp
+++ b/test/Parser/brackets.cpp
@@ -15,10 +15,10 @@ void test1() {
// CHECK: fix-it:{{.*}}:{[[@LINE-6]]:10-[[@LINE-6]]:10}:"[]"
int c = a[0];
- int d = b[0]; // No undeclared identifer error here.
+ int d = b[0]; // No undeclared identifier error here.
int *e = a;
- int *f = b; // No undeclared identifer error here.
+ int *f = b; // No undeclared identifier error here.
int[1] g[2];
// expected-error@-1{{brackets are not allowed here; to declare an array, place the brackets after the name}}
diff --git a/test/Parser/cxx-ambig-decl-expr.cpp b/test/Parser/cxx-ambig-decl-expr.cpp
index feb185fbe3f2..7bf08b02c4f5 100644
--- a/test/Parser/cxx-ambig-decl-expr.cpp
+++ b/test/Parser/cxx-ambig-decl-expr.cpp
@@ -11,3 +11,7 @@ void f() {
unknown *p = 0; // expected-error {{unknown type name 'unknown'}}
unknown * p + 0; // expected-error {{undeclared identifier 'unknown'}}
}
+
+auto (*p)() -> int(nullptr);
+auto (*q)() -> int(*)(unknown); // expected-error {{unknown type name 'unknown'}}
+auto (*r)() -> int(*)(unknown + 1); // expected-error {{undeclared identifier 'unknown'}}
diff --git a/test/Parser/cxx-decl.cpp b/test/Parser/cxx-decl.cpp
index 1a24520b8f55..c60e42f28eef 100644
--- a/test/Parser/cxx-decl.cpp
+++ b/test/Parser/cxx-decl.cpp
@@ -237,10 +237,11 @@ namespace PR5066 {
namespace PR17255 {
void foo() {
typename A::template B<>; // expected-error {{use of undeclared identifier 'A'}}
+ // expected-error@-1 {{'template' keyword not permitted here}}
#if __cplusplus <= 199711L
- // expected-error@-2 {{'template' keyword outside of a template}}
+ // expected-error@-3 {{'template' keyword outside of a template}}
#endif
- // expected-error@-4 {{expected a qualified name after 'typename'}}
+ // expected-error@-5 {{expected a qualified name after 'typename'}}
}
}
@@ -298,6 +299,11 @@ inline namespace ParensAroundFriend { // expected-error 0-1{{C++11}}
}
}
+namespace rdar37099386 {
+ class A typename A; // expected-error {{expected a qualified name after 'typename'}}
+ // expected-error@-1 {{cannot combine with previous 'class' declaration specifier}}
+}
+
// PR8380
extern "" // expected-error {{unknown linkage language}}
test6a { ;// expected-error {{C++ requires a type specifier for all declarations}}
diff --git a/test/Parser/cxx-extra-semi.cpp b/test/Parser/cxx-extra-semi.cpp
index 2aa18dfcc0e4..de14bc0354d8 100644
--- a/test/Parser/cxx-extra-semi.cpp
+++ b/test/Parser/cxx-extra-semi.cpp
@@ -38,4 +38,7 @@ union B {
#if __cplusplus < 201103L
// expected-warning@-3{{extra ';' outside of a function is a C++11 extension}}
// expected-warning@-3{{extra ';' outside of a function is a C++11 extension}}
+#elif !defined(PEDANTIC)
+// expected-warning@-6{{extra ';' outside of a function is incompatible with C++98}}
+// expected-warning@-6{{extra ';' outside of a function is incompatible with C++98}}
#endif
diff --git a/test/Parser/cxx0x-decl.cpp b/test/Parser/cxx0x-decl.cpp
index 2b253c019c97..7bd82e8220be 100644
--- a/test/Parser/cxx0x-decl.cpp
+++ b/test/Parser/cxx0x-decl.cpp
@@ -79,7 +79,7 @@ enum E
namespace PR5066 {
using T = int (*f)(); // expected-error {{type-id cannot have a name}}
template<typename T> using U = int (*f)(); // expected-error {{type-id cannot have a name}}
- auto f() -> int (*f)(); // expected-error {{type-id cannot have a name}}
+ auto f() -> int (*f)(); // expected-error {{only variables can be initialized}} expected-error {{expected ';'}}
auto g = []() -> int (*f)() {}; // expected-error {{type-id cannot have a name}}
}
@@ -130,15 +130,18 @@ namespace AliasDeclEndLocation {
using B = AliasDeclEndLocation::A<int
> // expected-error {{expected ';' after alias declaration}}
+;
- // FIXME: After splitting this >> into two > tokens, we incorrectly determine
- // the end of the template-id to be after the *second* '>'.
- // Perhaps we could synthesize an expansion FileID containing '> >' to fix this?
using C = AliasDeclEndLocation::A<int
>\
> // expected-error {{expected ';' after alias declaration}}
;
using D = AliasDeclEndLocation::A<int
> // expected-error {{expected ';' after alias declaration}}
+ // FIXME: After splitting this >> into two > tokens, we incorrectly determine
+ // the end of the template-id to be after the *second* '>'.
+ using E = AliasDeclEndLocation::A<int>>;
+#define GGG >>>
+ using F = AliasDeclEndLocation::A<int GGG;
+ // expected-error@-1 {{expected ';' after alias declaration}}
B something_else;
}
diff --git a/test/Parser/cxx11-brace-initializers.cpp b/test/Parser/cxx11-brace-initializers.cpp
index 7926320fd021..820344c57836 100644
--- a/test/Parser/cxx11-brace-initializers.cpp
+++ b/test/Parser/cxx11-brace-initializers.cpp
@@ -1,5 +1,4 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
-// expected-no-diagnostics
struct S {
S(int, int) {}
@@ -25,3 +24,6 @@ namespace PR14948 {
template<typename T> T Q<T>::x {};
}
+
+int conditional1 = 1 ? {} : 0; // expected-error {{initializer list cannot be used on the right hand side of operator '?'}}
+int conditional2 = 1 ? 0 : {}; // expected-error {{initializer list cannot be used on the right hand side of operator ':'}}
diff --git a/test/Parser/cxx1z-class-template-argument-deduction.cpp b/test/Parser/cxx1z-class-template-argument-deduction.cpp
index b8f5a82d461b..532c893f2132 100644
--- a/test/Parser/cxx1z-class-template-argument-deduction.cpp
+++ b/test/Parser/cxx1z-class-template-argument-deduction.cpp
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -verify %s
-template <typename T> struct A { // expected-note 35{{declared here}}
+template <typename T> struct A { // expected-note 38{{declared here}}
constexpr A() {}
constexpr A(int) {}
constexpr operator int() { return 0; }
@@ -17,6 +17,12 @@ namespace template_template_arg {
Y<A> ya; // expected-error {{requires template arguments}}
X<::A> xcca;
Y<::A> ycca; // expected-error {{requires template arguments}}
+ X<A*> xap; // expected-error {{requires template arguments}}
+ X<const A> xca; // expected-error {{requires template arguments}}
+ X<A const> xac; // expected-error {{requires template arguments}}
+ // FIXME: This should not parse as a template template argument due to the
+ // trailing attributes.
+ X<A [[]]> xa_attr;
template<template<typename> typename = A> struct XD {};
template<typename = A> struct YD {}; // expected-error {{requires template arguments}}
@@ -28,6 +34,23 @@ namespace template_template_arg {
template<typename T = A> struct G { }; // expected-error {{requires template arguments}}
}
+namespace template_template_arg_pack {
+ template<template<typename> typename...> struct XP {};
+ template<typename...> struct YP {};
+
+ struct Z { template<typename T> struct Q {}; }; // expected-note 2{{here}}
+
+ template<typename T> using ZId = Z;
+
+ template<typename ...Ts> struct A {
+ XP<ZId<Ts>::Q...> xe;
+ YP<ZId<Ts>::Q...> ye; // expected-error {{requires template arguments}}
+
+ XP<ZId<Ts>::Q> xp; // expected-error {{unexpanded parameter pack}}
+ YP<ZId<Ts>::Q> yp; // expected-error {{requires template arguments}}
+ };
+}
+
namespace injected_class_name {
template<typename T> struct A {
A(T);
@@ -114,7 +137,6 @@ namespace expr {
(void)A{n};
(void)new A(n);
(void)new A{n};
- // FIXME: We should diagnose the lack of an initializer here.
(void)new A;
}
}
@@ -127,7 +149,7 @@ namespace decl {
auto k() -> A; // expected-error{{requires template arguments}}
- A a; // expected-error {{declaration of variable 'a' with deduced type 'A' requires an initializer}}
+ A a;
A b = 0;
const A c = 0;
A (parens) = 0; // expected-error {{cannot use parentheses when declaring variable with deduced class template specialization type}}
@@ -193,3 +215,18 @@ namespace typename_specifier {
template<typename T> void g(typename T::A = 0); // expected-note {{refers to class template member}}
void h() { g<X>(); } // expected-error {{no matching function}}
}
+
+namespace parenthesized {
+ template<typename T> struct X { X(T); };
+ auto n = (X([]{}));
+}
+
+namespace within_template_arg_list {
+ template<typename T> struct X { constexpr X(T v) : v(v) {} T v; };
+ template<int N = X(1).v> struct Y {};
+ using T = Y<>;
+ using T = Y<X(1).v>;
+ using T = Y<within_template_arg_list::X(1).v>;
+
+ template<int ...N> struct Z { Y<X(N)...> y; };
+}
diff --git a/test/Parser/decomposed-condition.cpp b/test/Parser/decomposed-condition.cpp
index c41c82292e8d..4c635c4735db 100644
--- a/test/Parser/decomposed-condition.cpp
+++ b/test/Parser/decomposed-condition.cpp
@@ -1,5 +1,20 @@
// RUN: %clang_cc1 -std=c++1z %s -verify
+namespace std {
+ template<typename> struct tuple_size;
+ template<int, typename> struct tuple_element;
+}
+
+struct Get {
+ template<int> int get() { return 0; }
+ operator bool() { return true; }
+};
+
+namespace std {
+ template<> struct tuple_size<Get> { static constexpr int value = 1; };
+ template<> struct tuple_element<0, Get> { using type = int; };
+}
+
struct Na {
bool flag;
float data;
@@ -17,29 +32,35 @@ Rst f();
Na g();
namespace CondInIf {
-void h() {
+int h() {
if (auto [ok, d] = f()) // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}}
;
if (auto [ok, d] = g()) // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}} expected-error {{value of type 'Na' is not contextually convertible to 'bool'}}
;
+ if (auto [value] = Get()) // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}}
+ return value;
}
} // namespace CondInIf
namespace CondInWhile {
-void h() {
+int h() {
while (auto [ok, d] = f()) // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}}
;
while (auto [ok, d] = g()) // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}} expected-error {{value of type 'Na' is not contextually convertible to 'bool'}}
;
+ while (auto [value] = Get()) // expected-warning{{ISO C++17 does not permit structured binding declaration in a condition}}
+ return value;
}
} // namespace CondInWhile
namespace CondInFor {
-void h() {
+int h() {
for (; auto [ok, d] = f();) // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}}
;
for (; auto [ok, d] = g();) // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}} expected-error {{value of type 'Na' is not contextually convertible to 'bool'}}
;
+ for (; auto [value] = Get();) // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}}
+ return value;
}
} // namespace CondInFor
@@ -52,10 +73,15 @@ struct IntegerLike {
};
namespace CondInSwitch {
-void h(IntegerLike x) {
+int h(IntegerLike x) {
switch (auto [ok, d] = x) // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}}
;
switch (auto [ok, d] = g()) // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}} expected-error {{statement requires expression of integer type ('Na' invalid)}}
;
+ switch (auto [value] = Get()) {// expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}}
+ // expected-warning@-1{{switch condition has boolean value}}
+ case 1:
+ return value;
+ }
}
} // namespace CondInSwitch
diff --git a/test/Parser/gcc-for-loop-init-compatibility.c b/test/Parser/gcc-for-loop-init-compatibility.c
new file mode 100644
index 000000000000..dc88f083955d
--- /dev/null
+++ b/test/Parser/gcc-for-loop-init-compatibility.c
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -std=c89 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=gnu89 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c99 -fsyntax-only -verify %s -DC99
+
+#ifdef C99
+// expected-no-diagnostics
+#endif
+
+void foo() {
+#ifndef C99
+ // expected-warning@+2{{GCC does not allow variable declarations in for loop initializers before C99}}
+#endif
+ for (int i = 0; i < 10; i++)
+ ;
+}
diff --git a/test/Parser/objc-attr.m b/test/Parser/objc-attr.m
new file mode 100644
index 000000000000..7e65eff745da
--- /dev/null
+++ b/test/Parser/objc-attr.m
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -fsyntax-only -fdouble-square-bracket-attributes -triple x86_64-apple-macosx10.10.0 -verify %s
+// expected-no-diagnostics
+
+@interface NSObject
+@end
+
+[[clang::objc_exception]]
+@interface Foo {
+ [[clang::iboutlet]] NSObject *h;
+}
+@property (readonly) [[clang::objc_returns_inner_pointer]] void *i, *j;
+@property (readonly) [[clang::iboutlet]] NSObject *k;
+@end
+
+[[clang::objc_runtime_name("name")]] @protocol Bar;
+
+[[clang::objc_protocol_requires_explicit_implementation]]
+@protocol Baz
+@end
+
+@interface Quux
+-(void)g1 [[clang::ns_consumes_self]];
+-(void)g2 __attribute__((ns_consumes_self));
+-(void)h1: (int)x [[clang::ns_consumes_self]];
+-(void)h2: (int)x __attribute__((ns_consumes_self));
+-(void) [[clang::ns_consumes_self]] i1;
+-(void) __attribute__((ns_consumes_self)) i2;
+@end
diff --git a/test/Parser/objc-try-catch-1.m b/test/Parser/objc-try-catch-1.m
index a3220ebc6477..3a60148c8be9 100644
--- a/test/Parser/objc-try-catch-1.m
+++ b/test/Parser/objc-try-catch-1.m
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -fobjc-exceptions %s
-// RUN: %clang_cc1 -fsyntax-only -verify -fobjc-exceptions -x objective-c++ %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.10 -fsyntax-only -verify -fobjc-exceptions %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.10 -fsyntax-only -verify -fobjc-exceptions -x objective-c++ %s
void * proc();
@interface NSConstantString
diff --git a/test/Parser/opencl-cl20.cl b/test/Parser/opencl-cl20.cl
index b14ad10153df..be9695025477 100644
--- a/test/Parser/opencl-cl20.cl
+++ b/test/Parser/opencl-cl20.cl
@@ -10,9 +10,9 @@ __generic int * __generic_test(__generic int *arg) {
return var;
}
#ifndef CL20
-// expected-error@-5 {{OpenCL version 1.0 does not support the '__generic' type qualifier}}
-// expected-error@-6 {{OpenCL version 1.0 does not support the '__generic' type qualifier}}
-// expected-error@-6 {{OpenCL version 1.0 does not support the '__generic' type qualifier}}
+// expected-error@-5 {{OpenCL C version 1.0 does not support the '__generic' type qualifier}}
+// expected-error@-6 {{OpenCL C version 1.0 does not support the '__generic' type qualifier}}
+// expected-error@-6 {{OpenCL C version 1.0 does not support the '__generic' type qualifier}}
#endif
generic int * generic_test(generic int *arg) {
@@ -20,7 +20,7 @@ generic int * generic_test(generic int *arg) {
return var;
}
#ifndef CL20
-// expected-error@-5 {{OpenCL version 1.0 does not support the 'generic' type qualifier}}
-// expected-error@-6 {{OpenCL version 1.0 does not support the 'generic' type qualifier}}
-// expected-error@-6 {{OpenCL version 1.0 does not support the 'generic' type qualifier}}
+// expected-error@-5 {{OpenCL C version 1.0 does not support the 'generic' type qualifier}}
+// expected-error@-6 {{OpenCL C version 1.0 does not support the 'generic' type qualifier}}
+// expected-error@-6 {{OpenCL C version 1.0 does not support the 'generic' type qualifier}}
#endif
diff --git a/test/Parser/opencl-cxx-keywords.cl b/test/Parser/opencl-cxx-keywords.cl
new file mode 100644
index 000000000000..791da9361d31
--- /dev/null
+++ b/test/Parser/opencl-cxx-keywords.cl
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -verify -fsyntax-only
+// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -verify -fsyntax-only -fexceptions -fcxx-exceptions
+
+// This test checks that various C++ and OpenCL C keywords are not available
+// in OpenCL C++, according to OpenCL C++ 1.0 Specification Section 2.9.
+
+// Test that exceptions are disabled despite passing -fcxx-exceptions.
+kernel void test_exceptions() {
+ int x;
+ try {
+ // expected-error@-1 {{cannot use 'try' with exceptions disabled}}
+ throw 0;
+ // expected-error@-1 {{cannot use 'throw' with exceptions disabled}}
+ } catch (int i) {
+ x = 41;
+ }
+}
+
+// Test that only __-prefixed address space qualifiers are accepted.
+struct test_address_space_qualifiers {
+ global int *g;
+ // expected-error@-1 {{unknown type name 'global'}}
+ // expected-error@-2 {{expected member name or ';' after declaration specifiers}}
+ __global int *uug;
+ int global; // should be fine in OpenCL C++
+
+ local int *l;
+ // expected-error@-1 {{unknown type name 'local'}}
+ // expected-error@-2 {{expected member name or ';' after declaration specifiers}}
+ __local int *uul;
+ int local; // should be fine in OpenCL C++
+
+ private int *p;
+ // expected-error@-1 {{expected ':'}}
+ __private int *uup;
+ int private; // 'private' is a keyword in C++14 and thus in OpenCL C++
+ // expected-error@-1 {{expected member name or ';' after declaration specifiers}}
+
+ constant int *c;
+ // expected-error@-1 {{unknown type name 'constant'}}
+ // expected-error@-2 {{expected member name or ';' after declaration specifiers}}
+ __constant int *uuc;
+ int constant; // should be fine in OpenCL C++
+
+ generic int *ge;
+ // expected-error@-1 {{unknown type name 'generic'}}
+ // expected-error@-2 {{expected member name or ';' after declaration specifiers}}
+ __generic int *uuge;
+ int generic; // should be fine in OpenCL C++
+};
diff --git a/test/Parser/opencl-cxx-virtual.cl b/test/Parser/opencl-cxx-virtual.cl
new file mode 100644
index 000000000000..da08bfde957b
--- /dev/null
+++ b/test/Parser/opencl-cxx-virtual.cl
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -fsyntax-only -verify
+
+// Test that virtual functions and abstract classes are rejected.
+class virtual_functions {
+ virtual void bad1() {}
+ //expected-error@-1 {{virtual functions are not supported in OpenCL C++}}
+
+ virtual void bad2() = 0;
+ //expected-error@-1 {{virtual functions are not supported in OpenCL C++}}
+ //expected-error@-2 {{'bad2' is not virtual and cannot be declared pure}}
+};
+
+template <typename T>
+class X {
+ virtual T f();
+ //expected-error@-1 {{virtual functions are not supported in OpenCL C++}}
+};
+
+// Test that virtual base classes are allowed.
+struct A {
+ int a;
+ void foo();
+};
+
+struct B : virtual A {
+ int b;
+};
+
+struct C : public virtual A {
+ int c;
+};
+
+struct D : B, C {
+ int d;
+};
+
+kernel void virtual_inheritance() {
+ D d;
+
+ d.foo();
+ d.a = 11;
+ d.b = 22;
+ d.c = 33;
+ d.d = 44;
+}
diff --git a/test/Parser/opencl-storage-class.cl b/test/Parser/opencl-storage-class.cl
index a8ebc1af3999..a33c6e88401a 100644
--- a/test/Parser/opencl-storage-class.cl
+++ b/test/Parser/opencl-storage-class.cl
@@ -2,10 +2,10 @@
void test_storage_class_specs()
{
- static int a; // expected-error {{OpenCL version 1.0 does not support the 'static' storage class specifier}}
- register int b; // expected-error {{OpenCL version 1.0 does not support the 'register' storage class specifier}}
- extern int c; // expected-error {{OpenCL version 1.0 does not support the 'extern' storage class specifier}}
- auto int d; // expected-error {{OpenCL version 1.0 does not support the 'auto' storage class specifier}}
+ static int a; // expected-error {{OpenCL C version 1.0 does not support the 'static' storage class specifier}}
+ register int b; // expected-error {{OpenCL C version 1.0 does not support the 'register' storage class specifier}}
+ extern int c; // expected-error {{OpenCL C version 1.0 does not support the 'extern' storage class specifier}}
+ auto int d; // expected-error {{OpenCL C version 1.0 does not support the 'auto' storage class specifier}}
#pragma OPENCL EXTENSION cl_clang_storage_class_specifiers : enable
static int e; // expected-error {{static local variable must reside in constant address space}}
diff --git a/test/Parser/pointer_promotion.c b/test/Parser/pointer_promotion.c
index 30589d01326f..8b718ad565ce 100644
--- a/test/Parser/pointer_promotion.c
+++ b/test/Parser/pointer_promotion.c
@@ -12,6 +12,6 @@ void test() {
if (cp < fp) {} // expected-warning {{comparison of distinct pointer types ('char *' and 'struct foo *')}}
if (fp < bp) {} // expected-warning {{comparison of distinct pointer types ('struct foo *' and 'struct bar *')}}
if (ip < 7) {} // expected-warning {{comparison between pointer and integer ('int *' and 'int')}}
- if (sint < ip) {} // expected-warning {{comparison between pointer and integer ('int' and 'int *')}}
+ if (sint < ip) {} // expected-warning {{comparison between pointer and integer ('short' and 'int *')}}
if (ip == cp) {} // expected-warning {{comparison of distinct pointer types ('int *' and 'char *')}}
}
diff --git a/test/Parser/skip-function-bodies.h b/test/Parser/skip-function-bodies.h
new file mode 100644
index 000000000000..2d1a4c009ca2
--- /dev/null
+++ b/test/Parser/skip-function-bodies.h
@@ -0,0 +1,3 @@
+int header1(int t) {
+ return t;
+}
diff --git a/test/Parser/skip-function-bodies.mm b/test/Parser/skip-function-bodies.mm
index e5b7b2adf838..646730ee6c71 100644
--- a/test/Parser/skip-function-bodies.mm
+++ b/test/Parser/skip-function-bodies.mm
@@ -1,4 +1,4 @@
-// RUN: env CINDEXTEST_SKIP_FUNCTION_BODIES=1 c-index-test -test-load-source all %s | FileCheck %s
+#include "skip-function-bodies.h"
class A {
class B {};
@@ -27,6 +27,7 @@ void J() {
class K {};
}
+// RUN: env CINDEXTEST_SKIP_FUNCTION_BODIES=1 c-index-test -test-load-source all %s | FileCheck %s
// CHECK: skip-function-bodies.mm:3:7: ClassDecl=A:3:7 (Definition) Extent=[3:1 - 14:2]
// CHECK: skip-function-bodies.mm:4:9: ClassDecl=B:4:9 (Definition) Extent=[4:3 - 4:13]
// CHECK: skip-function-bodies.mm:6:1: CXXAccessSpecifier=:6:1 (Definition) Extent=[6:1 - 6:8]
@@ -43,3 +44,13 @@ void J() {
// CHECK-NOT: skip-function-bodies.mm:21:11: TypeRef=class A:3:7 Extent=[21:11 - 21:12]
// CHECK: skip-function-bodies.mm:26:6: FunctionDecl=J:26:6 Extent=[26:1 - 26:9]
// CHECK-NOT: skip-function-bodies.mm:27:9: ClassDecl=K:27:9 (Definition) Extent=[27:3 - 27:13]
+
+// RUN: env CINDEXTEST_EDITING=1 \
+// RUN: CINDEXTEST_CREATE_PREAMBLE_ON_FIRST_PARSE=1 \
+// RUN: CINDEXTEST_SKIP_FUNCTION_BODIES=1 \
+// RUN: CINDEXTEST_LIMIT_SKIP_FUNCTION_BODIES_TO_PREAMBLE=1 \
+// RUN: c-index-test -test-load-source all %s | FileCheck -check-prefix=CHECK-PREAMBLE %s
+// CHECK-PREAMBLE: skip-function-bodies.h:1:5: FunctionDecl=header1:1:5 Extent=[1:1 - 1:19]
+// CHECK-PREAMBLE-NOT: skip-function-bodies.h:2:3: ReturnStmt= Extent=[2:3 - 2:11]
+// CHECK-PREAMBLE: skip-function-bodies.mm:8:12: StructDecl=C:8:12 (Definition) Extent=[8:5 - 10:6]
+// CHECK-PREAMBLE: skip-function-bodies.mm:9:12: CXXMethod=d:9:12 (Definition) Extent=[9:7 - 9:18]
diff --git a/test/Parser/switch-recovery.cpp b/test/Parser/switch-recovery.cpp
index 4b06d55ba594..a3a0178cd10b 100644
--- a/test/Parser/switch-recovery.cpp
+++ b/test/Parser/switch-recovery.cpp
@@ -185,8 +185,9 @@ void pr19022_1a(int x) {
void pr19022_1b(int x) {
switch(x) {
- case v // expected-error{{use of undeclared identifier 'v'}}
- }
+ case v // expected-error{{use of undeclared identifier 'v'}} \
+ // expected-error{{expected ':' after 'case'}}
+ } // expected-error{{expected statement}}
}
void pr19022_2() {
@@ -209,7 +210,8 @@ int pr19022_4(int x) {
void pr19022_5(int x) {
switch(x) {
- case 1: case
+ case 1: case // expected-error{{expected ':' after 'case'}} \
+ // expected-error{{expected statement}}
} // expected-error{{expected expression}}
}
diff --git a/test/Preprocessor/Inputs/cycle/a.h b/test/Preprocessor/Inputs/cycle/a.h
new file mode 100644
index 000000000000..dd3ef35d61fc
--- /dev/null
+++ b/test/Preprocessor/Inputs/cycle/a.h
@@ -0,0 +1,8 @@
+// Presence of 2 inclusion cycles
+// b.h -> a.h -> b.h -> ...
+// c.h -> a.h -> c.h -> ...
+// makes it unfeasible to reach max inclusion depth in all possible ways. Need
+// to stop earlier.
+
+#include "b.h"
+#include "c.h"
diff --git a/test/Preprocessor/Inputs/cycle/b.h b/test/Preprocessor/Inputs/cycle/b.h
new file mode 100644
index 000000000000..2243de1baf9a
--- /dev/null
+++ b/test/Preprocessor/Inputs/cycle/b.h
@@ -0,0 +1 @@
+#include "a.h"
diff --git a/test/Preprocessor/Inputs/cycle/c.h b/test/Preprocessor/Inputs/cycle/c.h
new file mode 100644
index 000000000000..2243de1baf9a
--- /dev/null
+++ b/test/Preprocessor/Inputs/cycle/c.h
@@ -0,0 +1 @@
+#include "a.h"
diff --git a/test/Preprocessor/Inputs/headermap-rel/foo.hmap b/test/Preprocessor/Inputs/headermap-rel/foo.hmap
deleted file mode 100644
index 783c64e67bb8..000000000000
--- a/test/Preprocessor/Inputs/headermap-rel/foo.hmap
+++ /dev/null
Binary files differ
diff --git a/test/Preprocessor/Inputs/headermap-rel/foo.hmap.json b/test/Preprocessor/Inputs/headermap-rel/foo.hmap.json
new file mode 100644
index 000000000000..ccfd911f0f7f
--- /dev/null
+++ b/test/Preprocessor/Inputs/headermap-rel/foo.hmap.json
@@ -0,0 +1,6 @@
+{
+ "mappings" :
+ {
+ "Foo.h" : "Foo/Foo.h"
+ }
+}
diff --git a/test/Preprocessor/Inputs/headermap-rel2/project-headers.hmap b/test/Preprocessor/Inputs/headermap-rel2/project-headers.hmap
deleted file mode 100644
index a0770fb25124..000000000000
--- a/test/Preprocessor/Inputs/headermap-rel2/project-headers.hmap
+++ /dev/null
Binary files differ
diff --git a/test/Preprocessor/Inputs/headermap-rel2/project-headers.hmap.json b/test/Preprocessor/Inputs/headermap-rel2/project-headers.hmap.json
new file mode 100644
index 000000000000..e03703b1bb06
--- /dev/null
+++ b/test/Preprocessor/Inputs/headermap-rel2/project-headers.hmap.json
@@ -0,0 +1,6 @@
+{
+ "mappings" :
+ {
+ "someheader.h" : "Product/someheader.h"
+ }
+}
diff --git a/test/Preprocessor/Inputs/nonportable-hmaps/foo.hmap b/test/Preprocessor/Inputs/nonportable-hmaps/foo.hmap
deleted file mode 100644
index 9036f208711c..000000000000
--- a/test/Preprocessor/Inputs/nonportable-hmaps/foo.hmap
+++ /dev/null
Binary files differ
diff --git a/test/Preprocessor/Inputs/nonportable-hmaps/foo.hmap.json b/test/Preprocessor/Inputs/nonportable-hmaps/foo.hmap.json
new file mode 100644
index 000000000000..c69f1df77253
--- /dev/null
+++ b/test/Preprocessor/Inputs/nonportable-hmaps/foo.hmap.json
@@ -0,0 +1,6 @@
+{
+ "mappings" :
+ {
+ "Foo/Foo.h" : "headers/foo/Foo.h"
+ }
+}
diff --git a/test/Preprocessor/aarch64-target-features.c b/test/Preprocessor/aarch64-target-features.c
index 836d29866efe..92df0004e906 100644
--- a/test/Preprocessor/aarch64-target-features.c
+++ b/test/Preprocessor/aarch64-target-features.c
@@ -38,6 +38,7 @@
// CHECK-NOT: __ARM_SIZEOF_MINIMAL_ENUM 1
// CHECK-NOT: __ARM_SIZEOF_WCHAR_T 2
// CHECK-NOT: __ARM_FEATURE_SVE
+// CHECK-NOT: __ARM_FEATURE_DOTPROD
// RUN: %clang -target aarch64_be-eabi -x c -E -dM %s -o - | FileCheck %s -check-prefix CHECK-BIGENDIAN
// CHECK-BIGENDIAN: __ARM_BIG_ENDIAN 1
@@ -89,6 +90,21 @@
// RUN: %clang -target aarch64-none-linux-gnu -march=armv8-a+sve -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SVE %s
// CHECK-SVE: __ARM_FEATURE_SVE 1
+// RUN: %clang -target aarch64-none-linux-gnu -march=armv8.2a+dotprod -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-DOTPROD %s
+// CHECK-DOTPROD: __ARM_FEATURE_DOTPROD 1
+
+// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.2a+fp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s
+// CHECK-FULLFP16-VECTOR-SCALAR: #define __ARM_FEATURE_FP16_SCALAR_ARITHMETIC 1
+// CHECK-FULLFP16-VECTOR-SCALAR: #define __ARM_FEATURE_FP16_VECTOR_ARITHMETIC 1
+// CHECK-FULLFP16-VECTOR-SCALAR: #define __ARM_FP 0xE
+// CHECK-FULLFP16-VECTOR-SCALAR: #define __ARM_FP16_FORMAT_IEEE 1
+
+// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.2a+fp16+nosimd -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-SCALAR %s
+// CHECK-FULLFP16-SCALAR: #define __ARM_FEATURE_FP16_SCALAR_ARITHMETIC 1
+// CHECK-FULLFP16-SCALAR-NOT: #define __ARM_FEATURE_FP16_VECTOR_ARITHMETIC 1
+// CHECK-FULLFP16-SCALAR: #define __ARM_FP 0xE
+// CHECK-FULLFP16-SCALAR: #define __ARM_FP16_FORMAT_IEEE 1
+
// ================== Check whether -mtune accepts mixed-case features.
// RUN: %clang -target aarch64 -mtune=CYCLONE -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MTUNE-CYCLONE %s
// CHECK-MTUNE-CYCLONE: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+neon" "-target-feature" "+zcm" "-target-feature" "+zcz"
@@ -102,6 +118,7 @@
// RUN: %clang -target aarch64 -mcpu=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-M1 %s
// RUN: %clang -target aarch64 -mcpu=exynos-m2 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-M1 %s
// RUN: %clang -target aarch64 -mcpu=exynos-m3 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-M1 %s
+// RUN: %clang -target aarch64 -mcpu=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-M1 %s
// RUN: %clang -target aarch64 -mcpu=kryo -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-KRYO %s
// RUN: %clang -target aarch64 -mcpu=thunderx2t99 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-THUNDERX2T99 %s
// CHECK-MCPU-CYCLONE: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+neon" "-target-feature" "+crypto" "-target-feature" "+zcm" "-target-feature" "+zcz"
diff --git a/test/Preprocessor/arm-target-features.c b/test/Preprocessor/arm-target-features.c
index 43c9c7c65ff5..a982d8085028 100644
--- a/test/Preprocessor/arm-target-features.c
+++ b/test/Preprocessor/arm-target-features.c
@@ -5,9 +5,36 @@
// CHECK-V8A: #define __ARM_FEATURE_CRC32 1
// CHECK-V8A: #define __ARM_FEATURE_DIRECTED_ROUNDING 1
// CHECK-V8A: #define __ARM_FEATURE_NUMERIC_MAXMIN 1
-// CHECK-V8A: #define __ARM_FP 0xe
-// CHECK-V8A: #define __ARM_FP16_ARGS 1
-// CHECK-V8A: #define __ARM_FP16_FORMAT_IEEE 1
+// CHECK-V8A-NOT: #define __ARM_FP 0x
+// CHECK-V8A-NOT: #define __ARM_FEATURE_DOTPROD
+
+// RUN: %clang -target armv8a-none-linux-gnueabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V8A-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv8a-none-linux-gnueabihf -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V8A-ALLOW-FP-INSTR %s
+// CHECK-V8A-ALLOW-FP-INSTR: #define __ARMEL__ 1
+// CHECK-V8A-ALLOW-FP-INSTR: #define __ARM_ARCH 8
+// CHECK-V8A-ALLOW-FP-INSTR: #define __ARM_ARCH_8A__ 1
+// CHECK-V8A-ALLOW-FP-INSTR: #define __ARM_FEATURE_CRC32 1
+// CHECK-V8A-ALLOW-FP-INSTR: #define __ARM_FEATURE_DIRECTED_ROUNDING 1
+// CHECK-V8A-ALLOW-FP-INSTR: #define __ARM_FEATURE_NUMERIC_MAXMIN 1
+// CHECK-V8A-ALLOW-FP-INSTR: #define __ARM_FP 0xe
+// CHECK-V8A-ALLOW-FP-INSTR: #define __ARM_FP16_ARGS 1
+// CHECK-V8A-ALLOW-FP-INSTR: #define __ARM_FP16_FORMAT_IEEE 1
+// CHECK-V8A-ALLOW-FP-INSTR-V8A-NOT: #define __ARM_FEATURE_DOTPROD
+
+// RUN: %clang -target arm-none-linux-gnueabi -march=armv8.2a+fp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s
+// CHECK-FULLFP16-VECTOR-SCALAR: #define __ARM_FEATURE_FP16_SCALAR_ARITHMETIC 1
+// CHECK-FULLFP16-VECTOR-SCALAR: #define __ARM_FEATURE_FP16_VECTOR_ARITHMETIC 1
+// CHECK-FULLFP16-VECTOR-SCALAR: #define __ARM_FP 0xe
+// CHECK-FULLFP16-VECTOR-SCALAR: #define __ARM_FP16_FORMAT_IEEE 1
+
+// RUN: %clang -target arm-none-linux-gnueabi -march=armv8.2a+fp16 -mfpu=vfp4 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-SCALAR %s
+// CHECK-FULLFP16-SCALAR: #define __ARM_FEATURE_FP16_SCALAR_ARITHMETIC 1
+// CHECK-FULLFP16-SCALAR-NOT: #define __ARM_FEATURE_FP16_VECTOR_ARITHMETIC 1
+// CHECK-FULLFP16-SCALAR: #define __ARM_FP 0xe
+// CHECK-FULLFP16-SCALAR: #define __ARM_FP16_FORMAT_IEEE 1
+//
+// RUN: %clang -target arm-none-linux-gnueabi -march=armv8.2a+dotprod -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-DOTPROD %s
+// CHECK-DOTPROD: #define __ARM_FEATURE_DOTPROD 1
// RUN: %clang -target armv8r-none-linux-gnu -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V8R %s
// CHECK-V8R: #define __ARMEL__ 1
@@ -16,7 +43,17 @@
// CHECK-V8R: #define __ARM_FEATURE_CRC32 1
// CHECK-V8R: #define __ARM_FEATURE_DIRECTED_ROUNDING 1
// CHECK-V8R: #define __ARM_FEATURE_NUMERIC_MAXMIN 1
-// CHECK-V8R: #define __ARM_FP 0xe
+// CHECK-V8R-NOT: #define __ARM_FP 0x
+
+// RUN: %clang -target armv8r-none-linux-gnueabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V8R-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv8r-none-linux-gnueabihf -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V8R-ALLOW-FP-INSTR %s
+// CHECK-V8R-ALLOW-FP-INSTR: #define __ARMEL__ 1
+// CHECK-V8R-ALLOW-FP-INSTR: #define __ARM_ARCH 8
+// CHECK-V8R-ALLOW-FP-INSTR: #define __ARM_ARCH_8R__ 1
+// CHECK-V8R-ALLOW-FP-INSTR: #define __ARM_FEATURE_CRC32 1
+// CHECK-V8R-ALLOW-FP-INSTR: #define __ARM_FEATURE_DIRECTED_ROUNDING 1
+// CHECK-V8R-ALLOW-FP-INSTR: #define __ARM_FEATURE_NUMERIC_MAXMIN 1
+// CHECK-V8R-ALLOW-FP-INSTR: #define __ARM_FP 0xe
// RUN: %clang -target armv7a-none-linux-gnu -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V7 %s
// CHECK-V7: #define __ARMEL__ 1
@@ -25,14 +62,32 @@
// CHECK-V7-NOT: __ARM_FEATURE_CRC32
// CHECK-V7-NOT: __ARM_FEATURE_NUMERIC_MAXMIN
// CHECK-V7-NOT: __ARM_FEATURE_DIRECTED_ROUNDING
-// CHECK-V7: #define __ARM_FP 0xc
+// CHECK-V7-NOT: #define __ARM_FP 0x
+
+// RUN: %clang -target armv7a-none-linux-gnueabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V7-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv7a-none-linux-gnueabihf -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V7-ALLOW-FP-INSTR %s
+// CHECK-V7-ALLOW-FP-INSTR: #define __ARMEL__ 1
+// CHECK-V7-ALLOW-FP-INSTR: #define __ARM_ARCH 7
+// CHECK-V7-ALLOW-FP-INSTR: #define __ARM_ARCH_7A__ 1
+// CHECK-V7-ALLOW-FP-INSTR-NOT: __ARM_FEATURE_CRC32
+// CHECK-V7-ALLOW-FP-INSTR-NOT: __ARM_FEATURE_NUMERIC_MAXMIN
+// CHECK-V7-ALLOW-FP-INSTR-NOT: __ARM_FEATURE_DIRECTED_ROUNDING
+// CHECK-V7-ALLOW-FP-INSTR: #define __ARM_FP 0xc
// RUN: %clang -target armv7ve-none-linux-gnu -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V7VE %s
// CHECK-V7VE: #define __ARMEL__ 1
// CHECK-V7VE: #define __ARM_ARCH 7
// CHECK-V7VE: #define __ARM_ARCH_7VE__ 1
// CHECK-V7VE: #define __ARM_ARCH_EXT_IDIV__ 1
-// CHECK-V7VE: #define __ARM_FP 0xc
+// CHECK-V7VE-NOT: #define __ARM_FP 0x
+
+// RUN: %clang -target armv7ve-none-linux-gnueabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V7VE-DEFAULT-ABI-SOFT %s
+// RUN: %clang -target armv7ve-none-linux-gnueabihf -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V7VE-DEFAULT-ABI-SOFT %s
+// CHECK-V7VE-DEFAULT-ABI-SOFT: #define __ARMEL__ 1
+// CHECK-V7VE-DEFAULT-ABI-SOFT: #define __ARM_ARCH 7
+// CHECK-V7VE-DEFAULT-ABI-SOFT: #define __ARM_ARCH_7VE__ 1
+// CHECK-V7VE-DEFAULT-ABI-SOFT: #define __ARM_ARCH_EXT_IDIV__ 1
+// CHECK-V7VE-DEFAULT-ABI-SOFT: #define __ARM_FP 0xc
// RUN: %clang -target x86_64-apple-macosx10.10 -arch armv7s -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V7S %s
// CHECK-V7S: #define __ARMEL__ 1
@@ -85,10 +140,15 @@
// RUN: %clang -target armv8a -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=V8A %s
// RUN: %clang -target armv8a -mthumb -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=V8A %s
-// RUN: %clang -target armv8a-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=V8A %s
-// RUN: %clang -target armv8a-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=V8A %s
// V8A:#define __ARM_ARCH_EXT_IDIV__ 1
-// V8A:#define __ARM_FP 0xe
+// V8A-NOT:#define __ARM_FP 0x
+
+// RUN: %clang -target armv8a-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=V8A-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv8a-eabi -mthumb -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=V8A-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv8a-eabihf -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=V8A-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv8a-eabihf -mthumb -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=V8A-ALLOW-FP-INSTR %s
+// V8A-ALLOW-FP-INSTR:#define __ARM_ARCH_EXT_IDIV__ 1
+// V8A-ALLOW-FP-INSTR:#define __ARM_FP 0xe
// RUN: %clang -target armv8m.base-none-linux-gnu -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=V8M_BASELINE %s
// V8M_BASELINE: #define __ARM_ARCH 8
@@ -111,9 +171,22 @@
// V8M_MAINLINE: #define __ARM_ARCH_PROFILE 'M'
// V8M_MAINLINE-NOT: __ARM_FEATURE_CRC32
// V8M_MAINLINE-NOT: __ARM_FEATURE_DSP
-// V8M_MAINLINE: #define __ARM_FP 0xe
+// V8M_MAINLINE-NOT: #define __ARM_FP 0x
// V8M_MAINLINE: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
+// RUN: %clang -target armv8m.main-none-linux-gnueabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=V8M-MAINLINE-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv8m.main-none-linux-gnueabihf -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=V8M-MAINLINE-ALLOW-FP-INSTR %s
+// V8M-MAINLINE-ALLOW-FP-INSTR: #define __ARM_ARCH 8
+// V8M-MAINLINE-ALLOW-FP-INSTR: #define __ARM_ARCH_8M_MAIN__ 1
+// V8M-MAINLINE-ALLOW-FP-INSTR: #define __ARM_ARCH_EXT_IDIV__ 1
+// V8M-MAINLINE-ALLOW-FP-INSTR-NOT: __ARM_ARCH_ISA_ARM
+// V8M-MAINLINE-ALLOW-FP-INSTR: #define __ARM_ARCH_ISA_THUMB 2
+// V8M-MAINLINE-ALLOW-FP-INSTR: #define __ARM_ARCH_PROFILE 'M'
+// V8M-MAINLINE-ALLOW-FP-INSTR-NOT: __ARM_FEATURE_CRC32
+// V8M-MAINLINE-ALLOW-FP-INSTR-NOT: __ARM_FEATURE_DSP
+// V8M-MAINLINE-ALLOW-FP-INSTR: #define __ARM_FP 0xe
+// V8M-MAINLINE-ALLOW-FP-INSTR: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
+
// RUN: %clang -target arm-none-linux-gnu -march=armv8-m.main+dsp -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=V8M_MAINLINE_DSP %s
// V8M_MAINLINE_DSP: #define __ARM_ARCH 8
// V8M_MAINLINE_DSP: #define __ARM_ARCH_8M_MAIN__ 1
@@ -123,9 +196,21 @@
// V8M_MAINLINE_DSP: #define __ARM_ARCH_PROFILE 'M'
// V8M_MAINLINE_DSP-NOT: __ARM_FEATURE_CRC32
// V8M_MAINLINE_DSP: #define __ARM_FEATURE_DSP 1
-// V8M_MAINLINE_DSP: #define __ARM_FP 0xe
+// V8M_MAINLINE_DSP-NOT: #define __ARM_FP 0x
// V8M_MAINLINE_DSP: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
+// RUN: %clang -target arm-none-linux-gnueabi -march=armv8-m.main+dsp -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=V8M-MAINLINE-DSP-ALLOW-FP-INSTR %s
+// V8M-MAINLINE-DSP-ALLOW-FP-INSTR: #define __ARM_ARCH 8
+// V8M-MAINLINE-DSP-ALLOW-FP-INSTR: #define __ARM_ARCH_8M_MAIN__ 1
+// V8M-MAINLINE-DSP-ALLOW-FP-INSTR: #define __ARM_ARCH_EXT_IDIV__ 1
+// V8M-MAINLINE-DSP-ALLOW-FP-INSTR-NOT: __ARM_ARCH_ISA_ARM
+// V8M-MAINLINE-DSP-ALLOW-FP-INSTR: #define __ARM_ARCH_ISA_THUMB 2
+// V8M-MAINLINE-DSP-ALLOW-FP-INSTR: #define __ARM_ARCH_PROFILE 'M'
+// V8M-MAINLINE-DSP-ALLOW-FP-INSTR-NOT: __ARM_FEATURE_CRC32
+// V8M-MAINLINE-DSP-ALLOW-FP-INSTR: #define __ARM_FEATURE_DSP 1
+// V8M-MAINLINE-DSP-ALLOW-FP-INSTR: #define __ARM_FP 0xe
+// V8M-MAINLINE-DSP-ALLOW-FP-INSTR: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
+
// RUN: %clang -target arm-none-linux-gnu -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-DEFS %s
// CHECK-DEFS:#define __ARM_PCS 1
// CHECK-DEFS:#define __ARM_SIZEOF_MINIMAL_ENUM 4
@@ -161,6 +246,8 @@
// Check that -mfpu works properly for Cortex-A7 (enabled by default).
// RUN: %clang -target armv7-none-linux-gnueabi -mcpu=cortex-a7 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=DEFAULTFPU-A7 %s
// RUN: %clang -target armv7-none-linux-gnueabi -mthumb -mcpu=cortex-a7 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=DEFAULTFPU-A7 %s
+// RUN: %clang -target armv7-none-linux-gnueabihf -mcpu=cortex-a7 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=DEFAULTFPU-A7 %s
+// RUN: %clang -target armv7-none-linux-gnueabihf -mthumb -mcpu=cortex-a7 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=DEFAULTFPU-A7 %s
// DEFAULTFPU-A7:#define __ARM_FP 0xe
// DEFAULTFPU-A7:#define __ARM_NEON__ 1
// DEFAULTFPU-A7:#define __ARM_VFPV4__ 1
@@ -207,7 +294,7 @@
// A5T-NOT:#define __ARM_FEATURE_DSP
// A5T-NOT:#define __ARM_FP 0x{{.*}}
-// Test whether predefines are as expected when targeting cortex-a5.
+// Test whether predefines are as expected when targeting cortex-a5i (soft FP ABI as default).
// RUN: %clang -target armv7 -mcpu=cortex-a5 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=A5 %s
// RUN: %clang -target armv7 -mthumb -mcpu=cortex-a5 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=A5 %s
// A5:#define __ARM_ARCH 7
@@ -218,9 +305,21 @@
// A5-NOT: #define __ARM_FEATURE_DIRECTED_ROUNDING
// A5:#define __ARM_FEATURE_DSP 1
// A5-NOT: #define __ARM_FEATURE_NUMERIC_MAXMIN
-// A5:#define __ARM_FP 0xe
-
-// Test whether predefines are as expected when targeting cortex-a7.
+// A5-NOT:#define __ARM_FP 0x
+
+// Test whether predefines are as expected when targeting cortex-a5 (softfp FP ABI as default).
+// RUN: %clang -target armv7-eabi -mcpu=cortex-a5 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=A5-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv7-eabi -mthumb -mcpu=cortex-a5 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=A5-ALLOW-FP-INSTR %s
+// A5-ALLOW-FP-INSTR:#define __ARM_ARCH 7
+// A5-ALLOW-FP-INSTR:#define __ARM_ARCH_7A__ 1
+// A5-ALLOW-FP-INSTR-NOT:#define __ARM_ARCH_EXT_IDIV__
+// A5-ALLOW-FP-INSTR:#define __ARM_ARCH_PROFILE 'A'
+// A5-ALLOW-FP-INSTR-NOT: #define __ARM_FEATURE_DIRECTED_ROUNDING
+// A5-ALLOW-FP-INSTR:#define __ARM_FEATURE_DSP 1
+// A5-ALLOW-FP-INSTR-NOT: #define __ARM_FEATURE_NUMERIC_MAXMIN
+// A5-ALLOW-FP-INSTR:#define __ARM_FP 0xe
+
+// Test whether predefines are as expected when targeting cortex-a7 (soft FP ABI as default).
// RUN: %clang -target armv7k -mcpu=cortex-a7 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=A7 %s
// RUN: %clang -target armv7k -mthumb -mcpu=cortex-a7 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=A7 %s
// A7:#define __ARM_ARCH 7
@@ -228,7 +327,16 @@
// A7:#define __ARM_ARCH_PROFILE 'A'
// A7-NOT:#define __ARM_DWARF_EH__ 1
// A7:#define __ARM_FEATURE_DSP 1
-// A7:#define __ARM_FP 0xe
+// A7-NOT:#define __ARM_FP 0x
+
+// Test whether predefines are as expected when targeting cortex-a7 (softfp FP ABI as default).
+// RUN: %clang -target armv7k-eabi -mcpu=cortex-a7 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=A7-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv7k-eabi -mthumb -mcpu=cortex-a7 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=A7-ALLOW-FP-INSTR %s
+// A7-ALLOW-FP-INSTR:#define __ARM_ARCH 7
+// A7-ALLOW-FP-INSTR:#define __ARM_ARCH_EXT_IDIV__ 1
+// A7-ALLOW-FP-INSTR:#define __ARM_ARCH_PROFILE 'A'
+// A7-ALLOW-FP-INSTR:#define __ARM_FEATURE_DSP 1
+// A7-ALLOW-FP-INSTR:#define __ARM_FP 0xe
// Test whether predefines are as expected when targeting cortex-a7.
// RUN: %clang -target x86_64-apple-darwin -arch armv7k -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV7K %s
@@ -241,19 +349,33 @@
// ARMV7K:#define __ARM_PCS_VFP 1
-// Test whether predefines are as expected when targeting cortex-a8.
+// Test whether predefines are as expected when targeting cortex-a8 (soft FP ABI as default).
// RUN: %clang -target armv7 -mcpu=cortex-a8 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=A8 %s
// RUN: %clang -target armv7 -mthumb -mcpu=cortex-a8 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=A8 %s
// A8-NOT:#define __ARM_ARCH_EXT_IDIV__
// A8:#define __ARM_FEATURE_DSP 1
-// A8:#define __ARM_FP 0xc
+// A8-NOT:#define __ARM_FP 0x
+
+// Test whether predefines are as expected when targeting cortex-a8 (softfp FP ABI as default).
+// RUN: %clang -target armv7-eabi -mcpu=cortex-a8 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=A8-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv7-eabi -mthumb -mcpu=cortex-a8 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=A8-ALLOW-FP-INSTR %s
+// A8-ALLOW-FP-INSTR-NOT:#define __ARM_ARCH_EXT_IDIV__
+// A8-ALLOW-FP-INSTR:#define __ARM_FEATURE_DSP 1
+// A8-ALLOW-FP-INSTR:#define __ARM_FP 0xc
-// Test whether predefines are as expected when targeting cortex-a9.
+// Test whether predefines are as expected when targeting cortex-a9 (soft FP as default).
// RUN: %clang -target armv7 -mcpu=cortex-a9 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=A9 %s
// RUN: %clang -target armv7 -mthumb -mcpu=cortex-a9 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=A9 %s
// A9-NOT:#define __ARM_ARCH_EXT_IDIV__
// A9:#define __ARM_FEATURE_DSP 1
-// A9:#define __ARM_FP 0xe
+// A9-NOT:#define __ARM_FP 0x
+
+// Test whether predefines are as expected when targeting cortex-a9 (softfp FP as default).
+// RUN: %clang -target armv7-eabi -mcpu=cortex-a9 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=A9-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv7-eabi -mthumb -mcpu=cortex-a9 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=A9-ALLOW-FP-INSTR %s
+// A9-ALLOW-FP-INSTR-NOT:#define __ARM_ARCH_EXT_IDIV__
+// A9-ALLOW-FP-INSTR:#define __ARM_FEATURE_DSP 1
+// A9-ALLOW-FP-INSTR:#define __ARM_FP 0xe
// Check that -mfpu works properly for Cortex-A12 (enabled by default).
@@ -269,7 +391,7 @@
// FPUNONE-A12-NOT:#define __ARM_NEON__ 1
// FPUNONE-A12-NOT:#define __ARM_VFPV4__ 1
-// Test whether predefines are as expected when targeting cortex-a12.
+// Test whether predefines are as expected when targeting cortex-a12 (soft FP ABI as default).
// RUN: %clang -target armv7 -mcpu=cortex-a12 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=A12 %s
// RUN: %clang -target armv7 -mthumb -mcpu=cortex-a12 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=A12 %s
// A12:#define __ARM_ARCH 7
@@ -277,14 +399,31 @@
// A12:#define __ARM_ARCH_EXT_IDIV__ 1
// A12:#define __ARM_ARCH_PROFILE 'A'
// A12:#define __ARM_FEATURE_DSP 1
-// A12:#define __ARM_FP 0xe
-
-// Test whether predefines are as expected when targeting cortex-a15.
+// A12-NOT:#define __ARM_FP 0x
+
+// Test whether predefines are as expected when targeting cortex-a12 (soft FP ABI as default).
+// RUN: %clang -target armv7-eabi -mcpu=cortex-a12 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=A12-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv7-eabi -mthumb -mcpu=cortex-a12 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=A12-ALLOW-FP-INSTR %s
+// A12-ALLOW-FP-INSTR:#define __ARM_ARCH 7
+// A12-ALLOW-FP-INSTR:#define __ARM_ARCH_7A__ 1
+// A12-ALLOW-FP-INSTR:#define __ARM_ARCH_EXT_IDIV__ 1
+// A12-ALLOW-FP-INSTR:#define __ARM_ARCH_PROFILE 'A'
+// A12-ALLOW-FP-INSTR:#define __ARM_FEATURE_DSP 1
+// A12-ALLOW-FP-INSTR:#define __ARM_FP 0xe
+
+// Test whether predefines are as expected when targeting cortex-a15 (soft FP ABI as default).
// RUN: %clang -target armv7 -mcpu=cortex-a15 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=A15 %s
// RUN: %clang -target armv7 -mthumb -mcpu=cortex-a15 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=A15 %s
// A15:#define __ARM_ARCH_EXT_IDIV__ 1
// A15:#define __ARM_FEATURE_DSP 1
-// A15:#define __ARM_FP 0xe
+// A15-NOT:#define __ARM_FP 0x
+
+// Test whether predefines are as expected when targeting cortex-a15 (softfp ABI as default).
+// RUN: %clang -target armv7-eabi -mcpu=cortex-a15 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=A15-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv7-eabi -mthumb -mcpu=cortex-a15 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=A15-ALLOW-FP-INSTR %s
+// A15-ALLOW-FP-INSTR:#define __ARM_ARCH_EXT_IDIV__ 1
+// A15-ALLOW-FP-INSTR:#define __ARM_FEATURE_DSP 1
+// A15-ALLOW-FP-INSTR:#define __ARM_FP 0xe
// Check that -mfpu works properly for Cortex-A17 (enabled by default).
// RUN: %clang -target armv7-none-linux-gnueabi -mcpu=cortex-a17 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=DEFAULTFPU-A17 %s
@@ -299,7 +438,7 @@
// FPUNONE-A17-NOT:#define __ARM_NEON__ 1
// FPUNONE-A17-NOT:#define __ARM_VFPV4__ 1
-// Test whether predefines are as expected when targeting cortex-a17.
+// Test whether predefines are as expected when targeting cortex-a17 (soft FP ABI as default).
// RUN: %clang -target armv7 -mcpu=cortex-a17 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=A17 %s
// RUN: %clang -target armv7 -mthumb -mcpu=cortex-a17 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=A17 %s
// A17:#define __ARM_ARCH 7
@@ -307,16 +446,33 @@
// A17:#define __ARM_ARCH_EXT_IDIV__ 1
// A17:#define __ARM_ARCH_PROFILE 'A'
// A17:#define __ARM_FEATURE_DSP 1
-// A17:#define __ARM_FP 0xe
-
-// Test whether predefines are as expected when targeting swift.
+// A17-NOT:#define __ARM_FP 0x
+
+// Test whether predefines are as expected when targeting cortex-a17 (softfp FP ABI as default).
+// RUN: %clang -target armv7-eabi -mcpu=cortex-a17 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=A17-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv7-eabi -mthumb -mcpu=cortex-a17 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=A17-ALLOW-FP-INSTR %s
+// A17-ALLOW-FP-INSTR:#define __ARM_ARCH 7
+// A17-ALLOW-FP-INSTR:#define __ARM_ARCH_7A__ 1
+// A17-ALLOW-FP-INSTR:#define __ARM_ARCH_EXT_IDIV__ 1
+// A17-ALLOW-FP-INSTR:#define __ARM_ARCH_PROFILE 'A'
+// A17-ALLOW-FP-INSTR:#define __ARM_FEATURE_DSP 1
+// A17-ALLOW-FP-INSTR:#define __ARM_FP 0xe
+
+// Test whether predefines are as expected when targeting swift (soft FP ABI as default).
// RUN: %clang -target armv7s -mcpu=swift -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=SWIFT %s
// RUN: %clang -target armv7s -mthumb -mcpu=swift -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=SWIFT %s
// SWIFT:#define __ARM_ARCH_EXT_IDIV__ 1
// SWIFT:#define __ARM_FEATURE_DSP 1
-// SWIFT:#define __ARM_FP 0xe
+// SWIFT-NOT:#define __ARM_FP 0xxE
+
+// Test whether predefines are as expected when targeting swift (softfp FP ABI as default).
+// RUN: %clang -target armv7s-eabi -mcpu=swift -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=SWIFT-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv7s-eabi -mthumb -mcpu=swift -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=SWIFT-ALLOW-FP-INSTR %s
+// SWIFT-ALLOW-FP-INSTR:#define __ARM_ARCH_EXT_IDIV__ 1
+// SWIFT-ALLOW-FP-INSTR:#define __ARM_FEATURE_DSP 1
+// SWIFT-ALLOW-FP-INSTR:#define __ARM_FP 0xe
-// Test whether predefines are as expected when targeting ARMv8-A Cortex implementations
+// Test whether predefines are as expected when targeting ARMv8-A Cortex implementations (soft FP ABI as default)
// RUN: %clang -target armv8 -mcpu=cortex-a32 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8 %s
// RUN: %clang -target armv8 -mthumb -mcpu=cortex-a32 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8 %s
// RUN: %clang -target armv8 -mcpu=cortex-a35 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8 %s
@@ -329,9 +485,44 @@
// RUN: %clang -target armv8 -mthumb -mcpu=cortex-a72 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8 %s
// RUN: %clang -target armv8 -mcpu=cortex-a73 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8 %s
// RUN: %clang -target armv8 -mthumb -mcpu=cortex-a73 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8 %s
+//
+// RUN: %clang -target armv8 -mcpu=exynos-m1 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8 %s
+// RUN: %clang -target armv8 -mthumb -mcpu=exynos-m1 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8 %s
+// RUN: %clang -target armv8 -mcpu=exynos-m2 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8 %s
+// RUN: %clang -target armv8 -mthumb -mcpu=exynos-m2 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8 %s
+// RUN: %clang -target armv8 -mcpu=exynos-m3 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8 %s
+// RUN: %clang -target armv8 -mthumb -mcpu=exynos-m3 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8 %s
+// RUN: %clang -target armv8 -mcpu=exynos-m4 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8 %s
+// RUN: %clang -target armv8 -mthumb -mcpu=exynos-m4 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8 %s
// ARMV8:#define __ARM_ARCH_EXT_IDIV__ 1
// ARMV8:#define __ARM_FEATURE_DSP 1
-// ARMV8:#define __ARM_FP 0xe
+// ARMV8-NOT:#define __ARM_FP 0x
+
+// Test whether predefines are as expected when targeting ARMv8-A Cortex implementations (softfp FP ABI as default)
+// RUN: %clang -target armv8-eabi -mcpu=cortex-a32 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv8-eabi -mthumb -mcpu=cortex-a32 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv8-eabi -mcpu=cortex-a35 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv8-eabi -mthumb -mcpu=cortex-a35 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv8-eabi -mcpu=cortex-a53 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv8-eabi -mthumb -mcpu=cortex-a53 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv8-eabi -mcpu=cortex-a57 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv8-eabi -mthumb -mcpu=cortex-a57 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv8-eabi -mcpu=cortex-a72 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv8-eabi -mthumb -mcpu=cortex-a72 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv8-eabi -mcpu=cortex-a73 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv8-eabi -mthumb -mcpu=cortex-a73 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8-ALLOW-FP-INSTR %s
+//
+// RUN: %clang -target armv8-eabi -mcpu=exynos-m1 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv8-eabi -mthumb -mcpu=exynos-m1 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv8-eabi -mcpu=exynos-m2 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv8-eabi -mthumb -mcpu=exynos-m2 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv8-eabi -mcpu=exynos-m3 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv8-eabi -mthumb -mcpu=exynos-m3 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv8-eabi -mcpu=exynos-m4 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv8-eabi -mthumb -mcpu=exynos-m4 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8-ALLOW-FP-INSTR %s
+// ARMV8-ALLOW-FP-INSTR:#define __ARM_ARCH_EXT_IDIV__ 1
+// ARMV8-ALLOW-FP-INSTR:#define __ARM_FEATURE_DSP 1
+// ARMV8-ALLOW-FP-INSTR:#define __ARM_FP 0xe
// Test whether predefines are as expected when targeting cortex-r4.
// RUN: %clang -target armv7 -mcpu=cortex-r4 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=R4-ARM %s
@@ -344,32 +535,59 @@
// R4-THUMB:#define __ARM_FEATURE_DSP 1
// R4-THUMB-NOT:#define __ARM_FP 0x{{.*}}
-// Test whether predefines are as expected when targeting cortex-r4f.
+// Test whether predefines are as expected when targeting cortex-r4f (soft FP ABI as default).
// RUN: %clang -target armv7 -mcpu=cortex-r4f -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=R4F-ARM %s
// R4F-ARM-NOT:#define __ARM_ARCH_EXT_IDIV__
// R4F-ARM:#define __ARM_FEATURE_DSP 1
-// R4F-ARM:#define __ARM_FP 0xc
+// R4F-ARM-NOT:#define __ARM_FP 0x
+
+// Test whether predefines are as expected when targeting cortex-r4f (softfp FP ABI as default).
+// RUN: %clang -target armv7-eabi -mcpu=cortex-r4f -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=R4F-ARM-ALLOW-FP-INSTR %s
+// R4F-ARM-ALLOW-FP-INSTR-NOT:#define __ARM_ARCH_EXT_IDIV__
+// R4F-ARM-ALLOW-FP-INSTR:#define __ARM_FEATURE_DSP 1
+// R4F-ARM-ALLOW-FP-INSTR:#define __ARM_FP 0xc
// RUN: %clang -target armv7 -mthumb -mcpu=cortex-r4f -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=R4F-THUMB %s
// R4F-THUMB:#define __ARM_ARCH_EXT_IDIV__ 1
// R4F-THUMB:#define __ARM_FEATURE_DSP 1
-// R4F-THUMB:#define __ARM_FP 0xc
+// R4F-THUMB-NOT:#define __ARM_FP 0x
+
+// RUN: %clang -target armv7-eabi -mthumb -mcpu=cortex-r4f -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=R4F-THUMB-ALLOW-FP-INSTR %s
+// R4F-THUMB-ALLOW-FP-INSTR:#define __ARM_ARCH_EXT_IDIV__ 1
+// R4F-THUMB-ALLOW-FP-INSTR:#define __ARM_FEATURE_DSP 1
+// R4F-THUMB-ALLOW-FP-INSTR:#define __ARM_FP 0xc
-// Test whether predefines are as expected when targeting cortex-r5.
+// Test whether predefines are as expected when targeting cortex-r5 (soft FP ABI as default).
// RUN: %clang -target armv7 -mcpu=cortex-r5 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=R5 %s
// RUN: %clang -target armv7 -mthumb -mcpu=cortex-r5 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=R5 %s
// R5:#define __ARM_ARCH_EXT_IDIV__ 1
// R5:#define __ARM_FEATURE_DSP 1
-// R5:#define __ARM_FP 0xc
+// R5-NOT:#define __ARM_FP 0x
-// Test whether predefines are as expected when targeting cortex-r7 and cortex-r8.
+// Test whether predefines are as expected when targeting cortex-r5 (softfp FP ABI as default).
+// RUN: %clang -target armv7-eabi -mcpu=cortex-r5 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=R5-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv7-eabi -mthumb -mcpu=cortex-r5 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=R5-ALLOW-FP-INSTR %s
+// R5-ALLOW-FP-INSTR:#define __ARM_ARCH_EXT_IDIV__ 1
+// R5-ALLOW-FP-INSTR:#define __ARM_FEATURE_DSP 1
+// R5-ALLOW-FP-INSTR:#define __ARM_FP 0xc
+
+// Test whether predefines are as expected when targeting cortex-r7 and cortex-r8 (soft FP ABI as default).
// RUN: %clang -target armv7 -mcpu=cortex-r7 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=R7-R8 %s
// RUN: %clang -target armv7 -mthumb -mcpu=cortex-r7 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=R7-R8 %s
// RUN: %clang -target armv7 -mcpu=cortex-r8 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=R7-R8 %s
// RUN: %clang -target armv7 -mthumb -mcpu=cortex-r8 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=R7-R8 %s
// R7-R8:#define __ARM_ARCH_EXT_IDIV__ 1
// R7-R8:#define __ARM_FEATURE_DSP 1
-// R7-R8:#define __ARM_FP 0xe
+// R7-R8-NOT:#define __ARM_FP 0x
+
+// Test whether predefines are as expected when targeting cortex-r7 and cortex-r8 (softfp FP ABI as default).
+// RUN: %clang -target armv7-eabi -mcpu=cortex-r7 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=R7-R8-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv7-eabi -mthumb -mcpu=cortex-r7 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=R7-R8-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv7-eabi -mcpu=cortex-r8 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=R7-R8-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv7-eabi -mthumb -mcpu=cortex-r8 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=R7-R8-ALLOW-FP-INSTR %s
+// R7-R8-ALLOW-FP-INSTR:#define __ARM_ARCH_EXT_IDIV__ 1
+// R7-R8-ALLOW-FP-INSTR:#define __ARM_FEATURE_DSP 1
+// R7-R8-ALLOW-FP-INSTR:#define __ARM_FP 0xe
// Test whether predefines are as expected when targeting cortex-m0.
// RUN: %clang -target armv7 -mthumb -mcpu=cortex-m0 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=M0-THUMB %s
@@ -387,18 +605,31 @@
// M3-THUMB-NOT:#define __ARM_FEATURE_DSP
// M3-THUMB-NOT:#define __ARM_FP 0x{{.*}}
-// Test whether predefines are as expected when targeting cortex-m4.
+// Test whether predefines are as expected when targeting cortex-m4 (soft FP ABI as default).
// RUN: %clang -target armv7 -mthumb -mcpu=cortex-m4 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=M4-THUMB %s
// M4-THUMB:#define __ARM_ARCH_EXT_IDIV__ 1
// M4-THUMB:#define __ARM_FEATURE_DSP 1
-// M4-THUMB:#define __ARM_FP 0x6
+// M4-THUMB-NOT:#define __ARM_FP 0x
-// Test whether predefines are as expected when targeting cortex-m7.
+// Test whether predefines are as expected when targeting cortex-m4 (softfp ABI as default).
+// RUN: %clang -target armv7-eabi -mthumb -mcpu=cortex-m4 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=M4-THUMB-ALLOW-FP-INSTR %s
+// M4-THUMB-ALLOW-FP-INSTR:#define __ARM_ARCH_EXT_IDIV__ 1
+// M4-THUMB-ALLOW-FP-INSTR:#define __ARM_FEATURE_DSP 1
+// M4-THUMB-ALLOW-FP-INSTR:#define __ARM_FP 0x6
+
+// Test whether predefines are as expected when targeting cortex-m7 (soft FP ABI as default).
// RUN: %clang -target armv7 -mthumb -mcpu=cortex-m7 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=M7-THUMB %s
// M7-THUMB:#define __ARM_ARCH_EXT_IDIV__ 1
// M7-THUMB:#define __ARM_FEATURE_DSP 1
-// M7-THUMB:#define __ARM_FP 0xe
-// M7-THUMB:#define __ARM_FPV5__ 1
+// M7-THUMB-NOT:#define __ARM_FP 0x
+// M7-THUMB-NOT:#define __ARM_FPV5__
+
+// Test whether predefines are as expected when targeting cortex-m7 (softfp FP ABI as default).
+// RUN: %clang -target armv7-eabi -mthumb -mcpu=cortex-m7 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=M7-THUMB-ALLOW-FP-INSTR %s
+// M7-THUMB-ALLOW-FP-INSTR:#define __ARM_ARCH_EXT_IDIV__ 1
+// M7-THUMB-ALLOW-FP-INSTR:#define __ARM_FEATURE_DSP 1
+// M7-THUMB-ALLOW-FP-INSTR:#define __ARM_FP 0xe
+// M7-THUMB-ALLOW-FP-INSTR:#define __ARM_FPV5__ 1
// Test whether predefines are as expected when targeting v8m cores
// RUN: %clang -target arm -mcpu=cortex-m23 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=M23 %s
@@ -413,6 +644,7 @@
// M23-NOT: __ARM_FP 0x{{.*}}
// M23-NOT: __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
+// Test whether predefines are as expected when targeting m33 (soft FP ABI as default).
// RUN: %clang -target arm -mcpu=cortex-m33 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=M33 %s
// M33: #define __ARM_ARCH 8
// M33: #define __ARM_ARCH_8M_MAIN__ 1
@@ -422,15 +654,35 @@
// M33: #define __ARM_ARCH_PROFILE 'M'
// M33-NOT: __ARM_FEATURE_CRC32
// M33: #define __ARM_FEATURE_DSP 1
-// M33: #define __ARM_FP 0x6
+// M33-NOT: #define __ARM_FP 0x
// M33: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
-// Test whether predefines are as expected when targeting krait.
+// Test whether predefines are as expected when targeting m33 (softfp FP ABI as default).
+// RUN: %clang -target arm-eabi -mcpu=cortex-m33 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=M33-ALLOW-FP-INSTR %s
+// M33-ALLOW-FP-INSTR: #define __ARM_ARCH 8
+// M33-ALLOW-FP-INSTR: #define __ARM_ARCH_8M_MAIN__ 1
+// M33-ALLOW-FP-INSTR: #define __ARM_ARCH_EXT_IDIV__ 1
+// M33-ALLOW-FP-INSTR-NOT: __ARM_ARCH_ISA_ARM
+// M33-ALLOW-FP-INSTR: #define __ARM_ARCH_ISA_THUMB 2
+// M33-ALLOW-FP-INSTR: #define __ARM_ARCH_PROFILE 'M'
+// M33-ALLOW-FP-INSTR-NOT: __ARM_FEATURE_CRC32
+// M33-ALLOW-FP-INSTR: #define __ARM_FEATURE_DSP 1
+// M33-ALLOW-FP-INSTR: #define __ARM_FP 0x6
+// M33-ALLOW-FP-INSTR: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
+
+// Test whether predefines are as expected when targeting krait (soft FP as default).
// RUN: %clang -target armv7 -mcpu=krait -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=KRAIT %s
// RUN: %clang -target armv7 -mthumb -mcpu=krait -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=KRAIT %s
// KRAIT:#define __ARM_ARCH_EXT_IDIV__ 1
// KRAIT:#define __ARM_FEATURE_DSP 1
-// KRAIT:#define __ARM_VFPV4__ 1
+// KRAIT-NOT:#define __ARM_VFPV4__
+
+// Test whether predefines are as expected when targeting krait (softfp FP as default).
+// RUN: %clang -target armv7-eabi -mcpu=krait -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=KRAIT-ALLOW-FP-INSTR %s
+// RUN: %clang -target armv7-eabi -mthumb -mcpu=krait -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=KRAIT-ALLOW-FP-INSTR %s
+// KRAIT-ALLOW-FP-INSTR:#define __ARM_ARCH_EXT_IDIV__ 1
+// KRAIT-ALLOW-FP-INSTR:#define __ARM_FEATURE_DSP 1
+// KRAIT-ALLOW-FP-INSTR:#define __ARM_VFPV4__ 1
// RUN: %clang -target armv8.1a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V81A %s
// CHECK-V81A: #define __ARM_ARCH 8
diff --git a/test/Preprocessor/cuda-types.cu b/test/Preprocessor/cuda-types.cu
index 9e96f6a15e6e..4ad3e4d97aa2 100644
--- a/test/Preprocessor/cuda-types.cu
+++ b/test/Preprocessor/cuda-types.cu
@@ -9,40 +9,40 @@
// RUN: %clang --cuda-host-only -nocudainc -target i386-unknown-linux-gnu -x cuda -E -dM -o - /dev/null \
// RUN: | grep 'define __[^ ]*\(TYPE\|MAX\|SIZEOF|WIDTH\)\|define __GCC_ATOMIC' \
-// RUN: | grep -v '__FLT128\|__LDBL\|_LONG_DOUBLE' > %t/i386-host-defines-filtered
+// RUN: | grep -v '__LDBL\|_LONG_DOUBLE' > %t/i386-host-defines-filtered
// RUN: %clang --cuda-device-only -nocudainc -nocudalib -target i386-unknown-linux-gnu -x cuda -E -dM -o - /dev/null \
// RUN: | grep 'define __[^ ]*\(TYPE\|MAX\|SIZEOF|WIDTH\)\|define __GCC_ATOMIC' \
-// RUN: | grep -v '__FLT128\|__LDBL\|_LONG_DOUBLE' > %t/i386-device-defines-filtered
+// RUN: | grep -v '__LDBL\|_LONG_DOUBLE' > %t/i386-device-defines-filtered
// RUN: diff %t/i386-host-defines-filtered %t/i386-device-defines-filtered
// RUN: %clang --cuda-host-only -nocudainc -target x86_64-unknown-linux-gnu -x cuda -E -dM -o - /dev/null \
// RUN: | grep 'define __[^ ]*\(TYPE\|MAX\|SIZEOF|WIDTH\)\|define __GCC_ATOMIC' \
-// RUN: | grep -v '__FLT128\|__LDBL\|_LONG_DOUBLE' > %t/x86_64-host-defines-filtered
+// RUN: | grep -v '__LDBL\|_LONG_DOUBLE' > %t/x86_64-host-defines-filtered
// RUN: %clang --cuda-device-only -nocudainc -nocudalib -target x86_64-unknown-linux-gnu -x cuda -E -dM -o - /dev/null \
// RUN: | grep 'define __[^ ]*\(TYPE\|MAX\|SIZEOF|WIDTH\)\|define __GCC_ATOMIC' \
-// RUN: | grep -v '__FLT128\|__LDBL\|_LONG_DOUBLE' > %t/x86_64-device-defines-filtered
+// RUN: | grep -v '__LDBL\|_LONG_DOUBLE' > %t/x86_64-device-defines-filtered
// RUN: diff %t/x86_64-host-defines-filtered %t/x86_64-device-defines-filtered
// RUN: %clang --cuda-host-only -nocudainc -target powerpc64-unknown-linux-gnu -x cuda -E -dM -o - /dev/null \
// RUN: | grep 'define __[^ ]*\(TYPE\|MAX\|SIZEOF|WIDTH\)\|define __GCC_ATOMIC' \
-// RUN: | grep -v '__FLT128\|__LDBL\|_LONG_DOUBLE' > %t/powerpc64-host-defines-filtered
+// RUN: | grep -v '__LDBL\|_LONG_DOUBLE' > %t/powerpc64-host-defines-filtered
// RUN: %clang --cuda-device-only -nocudainc -nocudalib -target powerpc64-unknown-linux-gnu -x cuda -E -dM -o - /dev/null \
// RUN: | grep 'define __[^ ]*\(TYPE\|MAX\|SIZEOF|WIDTH\)\|define __GCC_ATOMIC' \
-// RUN: | grep -v '__FLT128\|__LDBL\|_LONG_DOUBLE' > %t/powerpc64-device-defines-filtered
+// RUN: | grep -v '__LDBL\|_LONG_DOUBLE' > %t/powerpc64-device-defines-filtered
// RUN: diff %t/powerpc64-host-defines-filtered %t/powerpc64-device-defines-filtered
// RUN: %clang --cuda-host-only -nocudainc -target i386-windows-msvc -x cuda -E -dM -o - /dev/null \
// RUN: | grep 'define __[^ ]*\(TYPE\|MAX\|SIZEOF|WIDTH\)\|define __GCC_ATOMIC' \
-// RUN: | grep -v '__FLT128\|__LDBL\|_LONG_DOUBLE' > %t/i386-msvc-host-defines-filtered
+// RUN: | grep -v '__LDBL\|_LONG_DOUBLE' > %t/i386-msvc-host-defines-filtered
// RUN: %clang --cuda-device-only -nocudainc -nocudalib -target i386-windows-msvc -x cuda -E -dM -o - /dev/null \
// RUN: | grep 'define __[^ ]*\(TYPE\|MAX\|SIZEOF|WIDTH\)\|define __GCC_ATOMIC' \
-// RUN: | grep -v '__FLT128\|__LDBL\|_LONG_DOUBLE' > %t/i386-msvc-device-defines-filtered
+// RUN: | grep -v '__LDBL\|_LONG_DOUBLE' > %t/i386-msvc-device-defines-filtered
// RUN: diff %t/i386-msvc-host-defines-filtered %t/i386-msvc-device-defines-filtered
// RUN: %clang --cuda-host-only -nocudainc -target x86_64-windows-msvc -x cuda -E -dM -o - /dev/null \
// RUN: | grep 'define __[^ ]*\(TYPE\|MAX\|SIZEOF|WIDTH\)\|define __GCC_ATOMIC' \
-// RUN: | grep -v '__FLT128\|__LDBL\|_LONG_DOUBLE' > %t/x86_64-msvc-host-defines-filtered
+// RUN: | grep -v '__LDBL\|_LONG_DOUBLE' > %t/x86_64-msvc-host-defines-filtered
// RUN: %clang --cuda-device-only -nocudainc -nocudalib -target x86_64-windows-msvc -x cuda -E -dM -o - /dev/null \
// RUN: | grep 'define __[^ ]*\(TYPE\|MAX\|SIZEOF|WIDTH\)\|define __GCC_ATOMIC' \
-// RUN: | grep -v '__FLT128\|__LDBL\|_LONG_DOUBLE' > %t/x86_64-msvc-device-defines-filtered
+// RUN: | grep -v '__LDBL\|_LONG_DOUBLE' > %t/x86_64-msvc-device-defines-filtered
// RUN: diff %t/x86_64-msvc-host-defines-filtered %t/x86_64-msvc-device-defines-filtered
diff --git a/test/Preprocessor/has_include.c b/test/Preprocessor/has_include.c
index ad7329390ef6..af1f6b8414e1 100644
--- a/test/Preprocessor/has_include.c
+++ b/test/Preprocessor/has_include.c
@@ -93,19 +93,19 @@
// Try as non-preprocessor directives
void foo( void ) {
- __has_include_next("stdint.h") // expected-warning {{#include_next in primary source file}} expected-error {{__has_include_next must be used within a preprocessing directive}}
- __has_include("stdint.h") // expected-error {{__has_include must be used within a preprocessing directive}}
+ __has_include_next("stdint.h") // expected-warning {{#include_next in primary source file}} expected-error {{'__has_include_next' must be used within a preprocessing directive}}
+ __has_include("stdint.h") // expected-error {{'__has_include' must be used within a preprocessing directive}}
}
-MACRO1 // expected-error {{__has_include must be used within a preprocessing directive}}
+MACRO1 // expected-error {{'__has_include' must be used within a preprocessing directive}}
#if 1
-MACRO1 // expected-error {{__has_include must be used within a preprocessing directive}}
+MACRO1 // expected-error {{'__has_include' must be used within a preprocessing directive}}
#endif
#if 0
#elif 1
-MACRO1 // expected-error {{__has_include must be used within a preprocessing directive}}
+MACRO1 // expected-error {{'__has_include' must be used within a preprocessing directive}}
#endif
#if 0
@@ -148,7 +148,7 @@ MACRO1 // This should be fine because it is never actually reached
#if __has_include(stdint.h>)
#endif
-// expected-error@+1 {{__has_include must be used within a preprocessing directive}}
+// expected-error@+1 {{'__has_include' must be used within a preprocessing directive}}
__has_include
// expected-error@+1 {{missing ')' after '__has_include'}} // expected-error@+1 {{expected value in expression}} // expected-note@+1 {{to match this '('}}
diff --git a/test/Preprocessor/headermap-rel.c b/test/Preprocessor/headermap-rel.c
index 38500a70f697..db57534c1c7f 100644
--- a/test/Preprocessor/headermap-rel.c
+++ b/test/Preprocessor/headermap-rel.c
@@ -1,8 +1,6 @@
-
-// This uses a headermap with this entry:
-// Foo.h -> Foo/Foo.h
-
-// RUN: %clang_cc1 -E %s -o %t.i -I %S/Inputs/headermap-rel/foo.hmap -F %S/Inputs/headermap-rel
+// RUN: rm -f %t.hmap
+// RUN: %hmaptool write %S/Inputs/headermap-rel/foo.hmap.json %t.hmap
+// RUN: %clang_cc1 -E %s -o %t.i -I %t.hmap -F %S/Inputs/headermap-rel
// RUN: FileCheck %s -input-file %t.i
// CHECK: Foo.h is parsed
diff --git a/test/Preprocessor/headermap-rel2.c b/test/Preprocessor/headermap-rel2.c
index d61f3385b22d..83e89f0a492e 100644
--- a/test/Preprocessor/headermap-rel2.c
+++ b/test/Preprocessor/headermap-rel2.c
@@ -1,8 +1,7 @@
-// This uses a headermap with this entry:
-// someheader.h -> Product/someheader.h
-
-// RUN: %clang_cc1 -v -fsyntax-only %s -iquote %S/Inputs/headermap-rel2/project-headers.hmap -isystem %S/Inputs/headermap-rel2/system/usr/include -I %S/Inputs/headermap-rel2 -H
-// RUN: %clang_cc1 -fsyntax-only %s -iquote %S/Inputs/headermap-rel2/project-headers.hmap -isystem %S/Inputs/headermap-rel2/system/usr/include -I %S/Inputs/headermap-rel2 -H 2> %t.out
+// RUN: rm -f %t.hmap
+// RUN: %hmaptool write %S/Inputs/headermap-rel2/project-headers.hmap.json %t.hmap
+// RUN: %clang_cc1 -v -fsyntax-only %s -iquote %t.hmap -isystem %S/Inputs/headermap-rel2/system/usr/include -I %S/Inputs/headermap-rel2 -H
+// RUN: %clang_cc1 -fsyntax-only %s -iquote %t.hmap -isystem %S/Inputs/headermap-rel2/system/usr/include -I %S/Inputs/headermap-rel2 -H 2> %t.out
// RUN: FileCheck %s -input-file %t.out
// CHECK: Product/someheader.h
diff --git a/test/Preprocessor/include-cycle.c b/test/Preprocessor/include-cycle.c
new file mode 100644
index 000000000000..52fcfbd27ad8
--- /dev/null
+++ b/test/Preprocessor/include-cycle.c
@@ -0,0 +1,5 @@
+// RUN: not %clang_cc1 -E -I%S/Inputs -ferror-limit 20 %s
+
+// Test that preprocessing terminates even if we have inclusion cycles.
+
+#include "cycle/a.h"
diff --git a/test/Preprocessor/init.c b/test/Preprocessor/init.c
index 51e1233456b8..68d057d87b08 100644
--- a/test/Preprocessor/init.c
+++ b/test/Preprocessor/init.c
@@ -724,21 +724,21 @@
// AARCH64-NETBSD:#define __INT32_FMTi__ "i"
// AARCH64-NETBSD:#define __INT32_MAX__ 2147483647
// AARCH64-NETBSD:#define __INT32_TYPE__ int
-// AARCH64-NETBSD:#define __INT64_C_SUFFIX__ LL
-// AARCH64-NETBSD:#define __INT64_FMTd__ "lld"
-// AARCH64-NETBSD:#define __INT64_FMTi__ "lli"
-// AARCH64-NETBSD:#define __INT64_MAX__ 9223372036854775807LL
-// AARCH64-NETBSD:#define __INT64_TYPE__ long long int
+// AARCH64-NETBSD:#define __INT64_C_SUFFIX__ L
+// AARCH64-NETBSD:#define __INT64_FMTd__ "ld"
+// AARCH64-NETBSD:#define __INT64_FMTi__ "li"
+// AARCH64-NETBSD:#define __INT64_MAX__ 9223372036854775807L
+// AARCH64-NETBSD:#define __INT64_TYPE__ long int
// AARCH64-NETBSD:#define __INT8_C_SUFFIX__
// AARCH64-NETBSD:#define __INT8_FMTd__ "hhd"
// AARCH64-NETBSD:#define __INT8_FMTi__ "hhi"
// AARCH64-NETBSD:#define __INT8_MAX__ 127
// AARCH64-NETBSD:#define __INT8_TYPE__ signed char
-// AARCH64-NETBSD:#define __INTMAX_C_SUFFIX__ LL
-// AARCH64-NETBSD:#define __INTMAX_FMTd__ "lld"
-// AARCH64-NETBSD:#define __INTMAX_FMTi__ "lli"
-// AARCH64-NETBSD:#define __INTMAX_MAX__ 9223372036854775807LL
-// AARCH64-NETBSD:#define __INTMAX_TYPE__ long long int
+// AARCH64-NETBSD:#define __INTMAX_C_SUFFIX__ L
+// AARCH64-NETBSD:#define __INTMAX_FMTd__ "ld"
+// AARCH64-NETBSD:#define __INTMAX_FMTi__ "li"
+// AARCH64-NETBSD:#define __INTMAX_MAX__ 9223372036854775807L
+// AARCH64-NETBSD:#define __INTMAX_TYPE__ long int
// AARCH64-NETBSD:#define __INTMAX_WIDTH__ 64
// AARCH64-NETBSD:#define __INTPTR_FMTd__ "ld"
// AARCH64-NETBSD:#define __INTPTR_FMTi__ "li"
@@ -824,15 +824,15 @@
// AARCH64-NETBSD:#define __UINT32_C_SUFFIX__ U
// AARCH64-NETBSD:#define __UINT32_MAX__ 4294967295U
// AARCH64-NETBSD:#define __UINT32_TYPE__ unsigned int
-// AARCH64-NETBSD:#define __UINT64_C_SUFFIX__ ULL
-// AARCH64-NETBSD:#define __UINT64_MAX__ 18446744073709551615ULL
-// AARCH64-NETBSD:#define __UINT64_TYPE__ long long unsigned int
+// AARCH64-NETBSD:#define __UINT64_C_SUFFIX__ UL
+// AARCH64-NETBSD:#define __UINT64_MAX__ 18446744073709551615UL
+// AARCH64-NETBSD:#define __UINT64_TYPE__ long unsigned int
// AARCH64-NETBSD:#define __UINT8_C_SUFFIX__
// AARCH64-NETBSD:#define __UINT8_MAX__ 255
// AARCH64-NETBSD:#define __UINT8_TYPE__ unsigned char
-// AARCH64-NETBSD:#define __UINTMAX_C_SUFFIX__ ULL
-// AARCH64-NETBSD:#define __UINTMAX_MAX__ 18446744073709551615ULL
-// AARCH64-NETBSD:#define __UINTMAX_TYPE__ long long unsigned int
+// AARCH64-NETBSD:#define __UINTMAX_C_SUFFIX__ UL
+// AARCH64-NETBSD:#define __UINTMAX_MAX__ 18446744073709551615UL
+// AARCH64-NETBSD:#define __UINTMAX_TYPE__ long unsigned int
// AARCH64-NETBSD:#define __UINTMAX_WIDTH__ 64
// AARCH64-NETBSD:#define __UINTPTR_MAX__ 18446744073709551615UL
// AARCH64-NETBSD:#define __UINTPTR_TYPE__ long unsigned int
@@ -2652,7 +2652,7 @@
// Thumbebv7: #define __THUMB_INTERWORK__ 1
// Thumbebv7: #define __thumb2__ 1
-// RUN: %clang -E -dM -ffreestanding -target thumbv7-pc-mingw32 %s -o - | FileCheck -match-full-lines -check-prefix THUMB-MINGW %s
+// RUN: %clang_cc1 -E -dM -ffreestanding -triple=thumbv7-pc-windows-gnu -fdwarf-exceptions %s -o - | FileCheck -match-full-lines -check-prefix THUMB-MINGW %s
// THUMB-MINGW:#define __ARM_DWARF_EH__ 1
@@ -6370,7 +6370,7 @@
// PPCPOWER9:#define _ARCH_PWR7 1
// PPCPOWER9:#define _ARCH_PWR9 1
//
-// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-feature +float128 -target-cpu power8 -fno-signed-char < /dev/null | FileCheck -check-prefix PPC-FLOAT128 %s
+// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-feature +float128 -target-cpu power9 -fno-signed-char < /dev/null | FileCheck -check-prefix PPC-FLOAT128 %s
// PPC-FLOAT128:#define __FLOAT128__ 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-unknown-linux-gnu -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPC64-LINUX %s
@@ -8965,6 +8965,9 @@
// PS4:#define __x86_64__ 1
// PS4:#define unix 1
//
+// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=x86_64-scei-ps4 < /dev/null | FileCheck -match-full-lines -check-prefix PS4-CXX %s
+// PS4-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 32UL
+//
// RUN: %clang_cc1 -E -dM -triple=x86_64-pc-mingw32 < /dev/null | FileCheck -match-full-lines -check-prefix X86-64-DECLSPEC %s
// RUN: %clang_cc1 -E -dM -fms-extensions -triple=x86_64-unknown-mingw32 < /dev/null | FileCheck -match-full-lines -check-prefix X86-64-DECLSPEC %s
// X86-64-DECLSPEC: #define __declspec{{.*}}
@@ -8999,6 +9002,13 @@
// RUN: %clang_cc1 -x c++ -triple sparc-rtems-elf -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GNUSOURCE %s
// GNUSOURCE:#define _GNU_SOURCE 1
//
+// Check that the GNUstep Objective-C ABI defines exist and are clamped at the
+// highest supported version.
+// RUN: %clang_cc1 -x objective-c -triple i386-unknown-freebsd -fobjc-runtime=gnustep-1.9 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GNUSTEP1 %s
+// GNUSTEP1:#define __OBJC_GNUSTEP_RUNTIME_ABI__ 18
+// RUN: %clang_cc1 -x objective-c -triple i386-unknown-freebsd -fobjc-runtime=gnustep-2.5 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GNUSTEP2 %s
+// GNUSTEP2:#define __OBJC_GNUSTEP_RUNTIME_ABI__ 20
+//
// RUN: %clang_cc1 -x c++ -std=c++98 -fno-rtti -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix NORTTI %s
// NORTTI: #define __GXX_ABI_VERSION {{.*}}
// NORTTI-NOT:#define __GXX_RTTI
@@ -9161,10 +9171,10 @@
// WEBASSEMBLY32-NEXT:#define __INTMAX_MAX__ 9223372036854775807LL
// WEBASSEMBLY32-NEXT:#define __INTMAX_TYPE__ long long int
// WEBASSEMBLY32-NEXT:#define __INTMAX_WIDTH__ 64
-// WEBASSEMBLY32-NEXT:#define __INTPTR_FMTd__ "d"
-// WEBASSEMBLY32-NEXT:#define __INTPTR_FMTi__ "i"
-// WEBASSEMBLY32-NEXT:#define __INTPTR_MAX__ 2147483647
-// WEBASSEMBLY32-NEXT:#define __INTPTR_TYPE__ int
+// WEBASSEMBLY32-NEXT:#define __INTPTR_FMTd__ "ld"
+// WEBASSEMBLY32-NEXT:#define __INTPTR_FMTi__ "li"
+// WEBASSEMBLY32-NEXT:#define __INTPTR_MAX__ 2147483647L
+// WEBASSEMBLY32-NEXT:#define __INTPTR_TYPE__ long int
// WEBASSEMBLY32-NEXT:#define __INTPTR_WIDTH__ 32
// WEBASSEMBLY32-NEXT:#define __INT_FAST16_FMTd__ "hd"
// WEBASSEMBLY32-NEXT:#define __INT_FAST16_FMTi__ "hi"
@@ -9229,10 +9239,10 @@
// WEBASSEMBLY32-NEXT:#define __ORDER_PDP_ENDIAN__ 3412
// WEBASSEMBLY32-NEXT:#define __POINTER_WIDTH__ 32
// WEBASSEMBLY32-NEXT:#define __PRAGMA_REDEFINE_EXTNAME 1
-// WEBASSEMBLY32-NEXT:#define __PTRDIFF_FMTd__ "d"
-// WEBASSEMBLY32-NEXT:#define __PTRDIFF_FMTi__ "i"
-// WEBASSEMBLY32-NEXT:#define __PTRDIFF_MAX__ 2147483647
-// WEBASSEMBLY32-NEXT:#define __PTRDIFF_TYPE__ int
+// WEBASSEMBLY32-NEXT:#define __PTRDIFF_FMTd__ "ld"
+// WEBASSEMBLY32-NEXT:#define __PTRDIFF_FMTi__ "li"
+// WEBASSEMBLY32-NEXT:#define __PTRDIFF_MAX__ 2147483647L
+// WEBASSEMBLY32-NEXT:#define __PTRDIFF_TYPE__ long int
// WEBASSEMBLY32-NEXT:#define __PTRDIFF_WIDTH__ 32
// WEBASSEMBLY32-NOT:#define __REGISTER_PREFIX__
// WEBASSEMBLY32-NEXT:#define __SCHAR_MAX__ 127
@@ -9252,12 +9262,12 @@
// WEBASSEMBLY32-NEXT:#define __SIZEOF_SIZE_T__ 4
// WEBASSEMBLY32-NEXT:#define __SIZEOF_WCHAR_T__ 4
// WEBASSEMBLY32-NEXT:#define __SIZEOF_WINT_T__ 4
-// WEBASSEMBLY32-NEXT:#define __SIZE_FMTX__ "X"
-// WEBASSEMBLY32-NEXT:#define __SIZE_FMTo__ "o"
-// WEBASSEMBLY32-NEXT:#define __SIZE_FMTu__ "u"
-// WEBASSEMBLY32-NEXT:#define __SIZE_FMTx__ "x"
-// WEBASSEMBLY32-NEXT:#define __SIZE_MAX__ 4294967295U
-// WEBASSEMBLY32-NEXT:#define __SIZE_TYPE__ unsigned int
+// WEBASSEMBLY32-NEXT:#define __SIZE_FMTX__ "lX"
+// WEBASSEMBLY32-NEXT:#define __SIZE_FMTo__ "lo"
+// WEBASSEMBLY32-NEXT:#define __SIZE_FMTu__ "lu"
+// WEBASSEMBLY32-NEXT:#define __SIZE_FMTx__ "lx"
+// WEBASSEMBLY32-NEXT:#define __SIZE_MAX__ 4294967295UL
+// WEBASSEMBLY32-NEXT:#define __SIZE_TYPE__ long unsigned int
// WEBASSEMBLY32-NEXT:#define __SIZE_WIDTH__ 32
// WEBASSEMBLY32-NEXT:#define __STDC_HOSTED__ 0
// WEBASSEMBLY32-NOT:#define __STDC_MB_MIGHT_NEQ_WC__
@@ -9305,12 +9315,12 @@
// WEBASSEMBLY32-NEXT:#define __UINTMAX_MAX__ 18446744073709551615ULL
// WEBASSEMBLY32-NEXT:#define __UINTMAX_TYPE__ long long unsigned int
// WEBASSEMBLY32-NEXT:#define __UINTMAX_WIDTH__ 64
-// WEBASSEMBLY32-NEXT:#define __UINTPTR_FMTX__ "X"
-// WEBASSEMBLY32-NEXT:#define __UINTPTR_FMTo__ "o"
-// WEBASSEMBLY32-NEXT:#define __UINTPTR_FMTu__ "u"
-// WEBASSEMBLY32-NEXT:#define __UINTPTR_FMTx__ "x"
-// WEBASSEMBLY32-NEXT:#define __UINTPTR_MAX__ 4294967295U
-// WEBASSEMBLY32-NEXT:#define __UINTPTR_TYPE__ unsigned int
+// WEBASSEMBLY32-NEXT:#define __UINTPTR_FMTX__ "lX"
+// WEBASSEMBLY32-NEXT:#define __UINTPTR_FMTo__ "lo"
+// WEBASSEMBLY32-NEXT:#define __UINTPTR_FMTu__ "lu"
+// WEBASSEMBLY32-NEXT:#define __UINTPTR_FMTx__ "lx"
+// WEBASSEMBLY32-NEXT:#define __UINTPTR_MAX__ 4294967295UL
+// WEBASSEMBLY32-NEXT:#define __UINTPTR_TYPE__ long unsigned int
// WEBASSEMBLY32-NEXT:#define __UINTPTR_WIDTH__ 32
// WEBASSEMBLY32-NEXT:#define __UINT_FAST16_FMTX__ "hX"
// WEBASSEMBLY32-NEXT:#define __UINT_FAST16_FMTo__ "ho"
@@ -10003,3 +10013,420 @@
// ARM-DARWIN-BAREMETAL-64: #define __PTRDIFF_TYPE__ long int
// ARM-DARWIN-BAREMETAL-64: #define __SIZE_TYPE__ long unsigned int
+// RUN: %clang_cc1 -E -dM -ffreestanding -triple=riscv32 < /dev/null \
+// RUN: | FileCheck -match-full-lines -check-prefix=RISCV32 %s
+// RUN: %clang_cc1 -E -dM -ffreestanding -triple=riscv32-unknown-linux < /dev/null \
+// RUN: | FileCheck -match-full-lines -check-prefixes=RISCV32,RISCV32-LINUX %s
+// RUN: %clang_cc1 -E -dM -ffreestanding -triple=riscv32 \
+// RUN: -fforce-enable-int128 < /dev/null | FileCheck -match-full-lines \
+// RUN: -check-prefixes=RISCV32,RISCV32-INT128 %s
+// RISCV32: #define _ILP32 1
+// RISCV32: #define __ATOMIC_ACQUIRE 2
+// RISCV32: #define __ATOMIC_ACQ_REL 4
+// RISCV32: #define __ATOMIC_CONSUME 1
+// RISCV32: #define __ATOMIC_RELAXED 0
+// RISCV32: #define __ATOMIC_RELEASE 3
+// RISCV32: #define __ATOMIC_SEQ_CST 5
+// RISCV32: #define __BIGGEST_ALIGNMENT__ 16
+// RISCV32: #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
+// RISCV32: #define __CHAR16_TYPE__ unsigned short
+// RISCV32: #define __CHAR32_TYPE__ unsigned int
+// RISCV32: #define __CHAR_BIT__ 8
+// RISCV32: #define __DBL_DECIMAL_DIG__ 17
+// RISCV32: #define __DBL_DENORM_MIN__ 4.9406564584124654e-324
+// RISCV32: #define __DBL_DIG__ 15
+// RISCV32: #define __DBL_EPSILON__ 2.2204460492503131e-16
+// RISCV32: #define __DBL_HAS_DENORM__ 1
+// RISCV32: #define __DBL_HAS_INFINITY__ 1
+// RISCV32: #define __DBL_HAS_QUIET_NAN__ 1
+// RISCV32: #define __DBL_MANT_DIG__ 53
+// RISCV32: #define __DBL_MAX_10_EXP__ 308
+// RISCV32: #define __DBL_MAX_EXP__ 1024
+// RISCV32: #define __DBL_MAX__ 1.7976931348623157e+308
+// RISCV32: #define __DBL_MIN_10_EXP__ (-307)
+// RISCV32: #define __DBL_MIN_EXP__ (-1021)
+// RISCV32: #define __DBL_MIN__ 2.2250738585072014e-308
+// RISCV32: #define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
+// RISCV32: #define __ELF__ 1
+// RISCV32: #define __FINITE_MATH_ONLY__ 0
+// RISCV32: #define __FLT_DECIMAL_DIG__ 9
+// RISCV32: #define __FLT_DENORM_MIN__ 1.40129846e-45F
+// RISCV32: #define __FLT_DIG__ 6
+// RISCV32: #define __FLT_EPSILON__ 1.19209290e-7F
+// RISCV32: #define __FLT_EVAL_METHOD__ 0
+// RISCV32: #define __FLT_HAS_DENORM__ 1
+// RISCV32: #define __FLT_HAS_INFINITY__ 1
+// RISCV32: #define __FLT_HAS_QUIET_NAN__ 1
+// RISCV32: #define __FLT_MANT_DIG__ 24
+// RISCV32: #define __FLT_MAX_10_EXP__ 38
+// RISCV32: #define __FLT_MAX_EXP__ 128
+// RISCV32: #define __FLT_MAX__ 3.40282347e+38F
+// RISCV32: #define __FLT_MIN_10_EXP__ (-37)
+// RISCV32: #define __FLT_MIN_EXP__ (-125)
+// RISCV32: #define __FLT_MIN__ 1.17549435e-38F
+// RISCV32: #define __FLT_RADIX__ 2
+// RISCV32: #define __GCC_ATOMIC_BOOL_LOCK_FREE 1
+// RISCV32: #define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 1
+// RISCV32: #define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 1
+// RISCV32: #define __GCC_ATOMIC_CHAR_LOCK_FREE 1
+// RISCV32: #define __GCC_ATOMIC_INT_LOCK_FREE 1
+// RISCV32: #define __GCC_ATOMIC_LLONG_LOCK_FREE 1
+// RISCV32: #define __GCC_ATOMIC_LONG_LOCK_FREE 1
+// RISCV32: #define __GCC_ATOMIC_POINTER_LOCK_FREE 1
+// RISCV32: #define __GCC_ATOMIC_SHORT_LOCK_FREE 1
+// RISCV32: #define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
+// RISCV32: #define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 1
+// RISCV32: #define __GNUC_MINOR__ {{.*}}
+// RISCV32: #define __GNUC_PATCHLEVEL__ {{.*}}
+// RISCV32: #define __GNUC_STDC_INLINE__ 1
+// RISCV32: #define __GNUC__ {{.*}}
+// RISCV32: #define __GXX_ABI_VERSION {{.*}}
+// RISCV32: #define __ILP32__ 1
+// RISCV32: #define __INT16_C_SUFFIX__
+// RISCV32: #define __INT16_MAX__ 32767
+// RISCV32: #define __INT16_TYPE__ short
+// RISCV32: #define __INT32_C_SUFFIX__
+// RISCV32: #define __INT32_MAX__ 2147483647
+// RISCV32: #define __INT32_TYPE__ int
+// RISCV32: #define __INT64_C_SUFFIX__ LL
+// RISCV32: #define __INT64_MAX__ 9223372036854775807LL
+// RISCV32: #define __INT64_TYPE__ long long int
+// RISCV32: #define __INT8_C_SUFFIX__
+// RISCV32: #define __INT8_MAX__ 127
+// RISCV32: #define __INT8_TYPE__ signed char
+// RISCV32: #define __INTMAX_C_SUFFIX__ LL
+// RISCV32: #define __INTMAX_MAX__ 9223372036854775807LL
+// RISCV32: #define __INTMAX_TYPE__ long long int
+// RISCV32: #define __INTMAX_WIDTH__ 64
+// RISCV32: #define __INTPTR_MAX__ 2147483647
+// RISCV32: #define __INTPTR_TYPE__ int
+// RISCV32: #define __INTPTR_WIDTH__ 32
+// TODO: RISC-V GCC defines INT_FAST16 as int
+// RISCV32: #define __INT_FAST16_MAX__ 32767
+// RISCV32: #define __INT_FAST16_TYPE__ short
+// RISCV32: #define __INT_FAST32_MAX__ 2147483647
+// RISCV32: #define __INT_FAST32_TYPE__ int
+// RISCV32: #define __INT_FAST64_MAX__ 9223372036854775807LL
+// RISCV32: #define __INT_FAST64_TYPE__ long long int
+// TODO: RISC-V GCC defines INT_FAST8 as int
+// RISCV32: #define __INT_FAST8_MAX__ 127
+// RISCV32: #define __INT_FAST8_TYPE__ signed char
+// RISCV32: #define __INT_LEAST16_MAX__ 32767
+// RISCV32: #define __INT_LEAST16_TYPE__ short
+// RISCV32: #define __INT_LEAST32_MAX__ 2147483647
+// RISCV32: #define __INT_LEAST32_TYPE__ int
+// RISCV32: #define __INT_LEAST64_MAX__ 9223372036854775807LL
+// RISCV32: #define __INT_LEAST64_TYPE__ long long int
+// RISCV32: #define __INT_LEAST8_MAX__ 127
+// RISCV32: #define __INT_LEAST8_TYPE__ signed char
+// RISCV32: #define __INT_MAX__ 2147483647
+// RISCV32: #define __LDBL_DECIMAL_DIG__ 36
+// RISCV32: #define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L
+// RISCV32: #define __LDBL_DIG__ 33
+// RISCV32: #define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L
+// RISCV32: #define __LDBL_HAS_DENORM__ 1
+// RISCV32: #define __LDBL_HAS_INFINITY__ 1
+// RISCV32: #define __LDBL_HAS_QUIET_NAN__ 1
+// RISCV32: #define __LDBL_MANT_DIG__ 113
+// RISCV32: #define __LDBL_MAX_10_EXP__ 4932
+// RISCV32: #define __LDBL_MAX_EXP__ 16384
+// RISCV32: #define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L
+// RISCV32: #define __LDBL_MIN_10_EXP__ (-4931)
+// RISCV32: #define __LDBL_MIN_EXP__ (-16381)
+// RISCV32: #define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
+// RISCV32: #define __LITTLE_ENDIAN__ 1
+// RISCV32: #define __LONG_LONG_MAX__ 9223372036854775807LL
+// RISCV32: #define __LONG_MAX__ 2147483647L
+// RISCV32: #define __NO_INLINE__ 1
+// RISCV32: #define __POINTER_WIDTH__ 32
+// RISCV32: #define __PRAGMA_REDEFINE_EXTNAME 1
+// RISCV32: #define __PTRDIFF_MAX__ 2147483647
+// RISCV32: #define __PTRDIFF_TYPE__ int
+// RISCV32: #define __PTRDIFF_WIDTH__ 32
+// RISCV32: #define __SCHAR_MAX__ 127
+// RISCV32: #define __SHRT_MAX__ 32767
+// RISCV32: #define __SIG_ATOMIC_MAX__ 2147483647
+// RISCV32: #define __SIG_ATOMIC_WIDTH__ 32
+// RISCV32: #define __SIZEOF_DOUBLE__ 8
+// RISCV32: #define __SIZEOF_FLOAT__ 4
+// RISCV32-INT128: #define __SIZEOF_INT128__ 16
+// RISCV32: #define __SIZEOF_INT__ 4
+// RISCV32: #define __SIZEOF_LONG_DOUBLE__ 16
+// RISCV32: #define __SIZEOF_LONG_LONG__ 8
+// RISCV32: #define __SIZEOF_LONG__ 4
+// RISCV32: #define __SIZEOF_POINTER__ 4
+// RISCV32: #define __SIZEOF_PTRDIFF_T__ 4
+// RISCV32: #define __SIZEOF_SHORT__ 2
+// RISCV32: #define __SIZEOF_SIZE_T__ 4
+// RISCV32: #define __SIZEOF_WCHAR_T__ 4
+// RISCV32: #define __SIZEOF_WINT_T__ 4
+// RISCV32: #define __SIZE_MAX__ 4294967295U
+// RISCV32: #define __SIZE_TYPE__ unsigned int
+// RISCV32: #define __SIZE_WIDTH__ 32
+// RISCV32: #define __STDC_HOSTED__ 0
+// RISCV32: #define __STDC_UTF_16__ 1
+// RISCV32: #define __STDC_UTF_32__ 1
+// RISCV32: #define __STDC_VERSION__ 201112L
+// RISCV32: #define __STDC__ 1
+// RISCV32: #define __UINT16_C_SUFFIX__
+// RISCV32: #define __UINT16_MAX__ 65535
+// RISCV32: #define __UINT16_TYPE__ unsigned short
+// RISCV32: #define __UINT32_C_SUFFIX__ U
+// RISCV32: #define __UINT32_MAX__ 4294967295U
+// RISCV32: #define __UINT32_TYPE__ unsigned int
+// RISCV32: #define __UINT64_C_SUFFIX__ ULL
+// RISCV32: #define __UINT64_MAX__ 18446744073709551615ULL
+// RISCV32: #define __UINT64_TYPE__ long long unsigned int
+// RISCV32: #define __UINT8_C_SUFFIX__
+// RISCV32: #define __UINT8_MAX__ 255
+// RISCV32: #define __UINT8_TYPE__ unsigned char
+// RISCV32: #define __UINTMAX_C_SUFFIX__ ULL
+// RISCV32: #define __UINTMAX_MAX__ 18446744073709551615ULL
+// RISCV32: #define __UINTMAX_TYPE__ long long unsigned int
+// RISCV32: #define __UINTMAX_WIDTH__ 64
+// RISCV32: #define __UINTPTR_MAX__ 4294967295U
+// RISCV32: #define __UINTPTR_TYPE__ unsigned int
+// RISCV32: #define __UINTPTR_WIDTH__ 32
+// TODO: RISC-V GCC defines UINT_FAST16 to be unsigned int
+// RISCV32: #define __UINT_FAST16_MAX__ 65535
+// RISCV32: #define __UINT_FAST16_TYPE__ unsigned short
+// RISCV32: #define __UINT_FAST32_MAX__ 4294967295U
+// RISCV32: #define __UINT_FAST32_TYPE__ unsigned int
+// RISCV32: #define __UINT_FAST64_MAX__ 18446744073709551615ULL
+// RISCV32: #define __UINT_FAST64_TYPE__ long long unsigned int
+// TODO: RISC-V GCC defines UINT_FAST8 to be unsigned int
+// RISCV32: #define __UINT_FAST8_MAX__ 255
+// RISCV32: #define __UINT_FAST8_TYPE__ unsigned char
+// RISCV32: #define __UINT_LEAST16_MAX__ 65535
+// RISCV32: #define __UINT_LEAST16_TYPE__ unsigned short
+// RISCV32: #define __UINT_LEAST32_MAX__ 4294967295U
+// RISCV32: #define __UINT_LEAST32_TYPE__ unsigned int
+// RISCV32: #define __UINT_LEAST64_MAX__ 18446744073709551615ULL
+// RISCV32: #define __UINT_LEAST64_TYPE__ long long unsigned int
+// RISCV32: #define __UINT_LEAST8_MAX__ 255
+// RISCV32: #define __UINT_LEAST8_TYPE__ unsigned char
+// RISCV32: #define __USER_LABEL_PREFIX__
+// RISCV32: #define __WCHAR_MAX__ 2147483647
+// RISCV32: #define __WCHAR_TYPE__ int
+// RISCV32: #define __WCHAR_WIDTH__ 32
+// RISCV32: #define __WINT_TYPE__ unsigned int
+// RISCV32: #define __WINT_UNSIGNED__ 1
+// RISCV32: #define __WINT_WIDTH__ 32
+// RISCV32-LINUX: #define __gnu_linux__ 1
+// RISCV32-LINUX: #define __linux 1
+// RISCV32-LINUX: #define __linux__ 1
+// RISCV32: #define __riscv 1
+// RISCV32: #define __riscv_cmodel_medlow 1
+// RISCV32: #define __riscv_float_abi_soft 1
+// RISCV32: #define __riscv_xlen 32
+// RISCV32-LINUX: #define __unix 1
+// RISCV32-LINUX: #define __unix__ 1
+// RISCV32-LINUX: #define linux 1
+// RISCV32-LINUX: #define unix 1
+
+// RUN: %clang_cc1 -E -dM -ffreestanding -triple=riscv64 < /dev/null \
+// RUN: | FileCheck -match-full-lines -check-prefix=RISCV64 %s
+// RUN: %clang_cc1 -E -dM -ffreestanding -triple=riscv64-unknown-linux < /dev/null \
+// RUN: | FileCheck -match-full-lines -check-prefixes=RISCV64,RISCV64-LINUX %s
+// RISCV64: #define _LP64 1
+// RISCV64: #define __ATOMIC_ACQUIRE 2
+// RISCV64: #define __ATOMIC_ACQ_REL 4
+// RISCV64: #define __ATOMIC_CONSUME 1
+// RISCV64: #define __ATOMIC_RELAXED 0
+// RISCV64: #define __ATOMIC_RELEASE 3
+// RISCV64: #define __ATOMIC_SEQ_CST 5
+// RISCV64: #define __BIGGEST_ALIGNMENT__ 16
+// RISCV64: #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
+// RISCV64: #define __CHAR16_TYPE__ unsigned short
+// RISCV64: #define __CHAR32_TYPE__ unsigned int
+// RISCV64: #define __CHAR_BIT__ 8
+// RISCV64: #define __DBL_DECIMAL_DIG__ 17
+// RISCV64: #define __DBL_DENORM_MIN__ 4.9406564584124654e-324
+// RISCV64: #define __DBL_DIG__ 15
+// RISCV64: #define __DBL_EPSILON__ 2.2204460492503131e-16
+// RISCV64: #define __DBL_HAS_DENORM__ 1
+// RISCV64: #define __DBL_HAS_INFINITY__ 1
+// RISCV64: #define __DBL_HAS_QUIET_NAN__ 1
+// RISCV64: #define __DBL_MANT_DIG__ 53
+// RISCV64: #define __DBL_MAX_10_EXP__ 308
+// RISCV64: #define __DBL_MAX_EXP__ 1024
+// RISCV64: #define __DBL_MAX__ 1.7976931348623157e+308
+// RISCV64: #define __DBL_MIN_10_EXP__ (-307)
+// RISCV64: #define __DBL_MIN_EXP__ (-1021)
+// RISCV64: #define __DBL_MIN__ 2.2250738585072014e-308
+// RISCV64: #define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
+// RISCV64: #define __ELF__ 1
+// RISCV64: #define __FINITE_MATH_ONLY__ 0
+// RISCV64: #define __FLT_DECIMAL_DIG__ 9
+// RISCV64: #define __FLT_DENORM_MIN__ 1.40129846e-45F
+// RISCV64: #define __FLT_DIG__ 6
+// RISCV64: #define __FLT_EPSILON__ 1.19209290e-7F
+// RISCV64: #define __FLT_EVAL_METHOD__ 0
+// RISCV64: #define __FLT_HAS_DENORM__ 1
+// RISCV64: #define __FLT_HAS_INFINITY__ 1
+// RISCV64: #define __FLT_HAS_QUIET_NAN__ 1
+// RISCV64: #define __FLT_MANT_DIG__ 24
+// RISCV64: #define __FLT_MAX_10_EXP__ 38
+// RISCV64: #define __FLT_MAX_EXP__ 128
+// RISCV64: #define __FLT_MAX__ 3.40282347e+38F
+// RISCV64: #define __FLT_MIN_10_EXP__ (-37)
+// RISCV64: #define __FLT_MIN_EXP__ (-125)
+// RISCV64: #define __FLT_MIN__ 1.17549435e-38F
+// RISCV64: #define __FLT_RADIX__ 2
+// RISCV64: #define __GCC_ATOMIC_BOOL_LOCK_FREE 1
+// RISCV64: #define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 1
+// RISCV64: #define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 1
+// RISCV64: #define __GCC_ATOMIC_CHAR_LOCK_FREE 1
+// RISCV64: #define __GCC_ATOMIC_INT_LOCK_FREE 1
+// RISCV64: #define __GCC_ATOMIC_LLONG_LOCK_FREE 1
+// RISCV64: #define __GCC_ATOMIC_LONG_LOCK_FREE 1
+// RISCV64: #define __GCC_ATOMIC_POINTER_LOCK_FREE 1
+// RISCV64: #define __GCC_ATOMIC_SHORT_LOCK_FREE 1
+// RISCV64: #define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
+// RISCV64: #define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 1
+// RISCV64: #define __GNUC_MINOR__ {{.*}}
+// RISCV64: #define __GNUC_PATCHLEVEL__ {{.*}}
+// RISCV64: #define __GNUC_STDC_INLINE__ 1
+// RISCV64: #define __GNUC__ {{.*}}
+// RISCV64: #define __GXX_ABI_VERSION {{.*}}
+// RISCV64: #define __INT16_C_SUFFIX__
+// RISCV64: #define __INT16_MAX__ 32767
+// RISCV64: #define __INT16_TYPE__ short
+// RISCV64: #define __INT32_C_SUFFIX__
+// RISCV64: #define __INT32_MAX__ 2147483647
+// RISCV64: #define __INT32_TYPE__ int
+// RISCV64: #define __INT64_C_SUFFIX__ L
+// RISCV64: #define __INT64_MAX__ 9223372036854775807L
+// RISCV64: #define __INT64_TYPE__ long int
+// RISCV64: #define __INT8_C_SUFFIX__
+// RISCV64: #define __INT8_MAX__ 127
+// RISCV64: #define __INT8_TYPE__ signed char
+// RISCV64: #define __INTMAX_C_SUFFIX__ L
+// RISCV64: #define __INTMAX_MAX__ 9223372036854775807L
+// RISCV64: #define __INTMAX_TYPE__ long int
+// RISCV64: #define __INTMAX_WIDTH__ 64
+// RISCV64: #define __INTPTR_MAX__ 9223372036854775807L
+// RISCV64: #define __INTPTR_TYPE__ long int
+// RISCV64: #define __INTPTR_WIDTH__ 64
+// TODO: RISC-V GCC defines INT_FAST16 as int
+// RISCV64: #define __INT_FAST16_MAX__ 32767
+// RISCV64: #define __INT_FAST16_TYPE__ short
+// RISCV64: #define __INT_FAST32_MAX__ 2147483647
+// RISCV64: #define __INT_FAST32_TYPE__ int
+// RISCV64: #define __INT_FAST64_MAX__ 9223372036854775807L
+// RISCV64: #define __INT_FAST64_TYPE__ long int
+// TODO: RISC-V GCC defines INT_FAST8 as int
+// RISCV64: #define __INT_FAST8_MAX__ 127
+// RISCV64: #define __INT_FAST8_TYPE__ signed char
+// RISCV64: #define __INT_LEAST16_MAX__ 32767
+// RISCV64: #define __INT_LEAST16_TYPE__ short
+// RISCV64: #define __INT_LEAST32_MAX__ 2147483647
+// RISCV64: #define __INT_LEAST32_TYPE__ int
+// RISCV64: #define __INT_LEAST64_MAX__ 9223372036854775807L
+// RISCV64: #define __INT_LEAST64_TYPE__ long int
+// RISCV64: #define __INT_LEAST8_MAX__ 127
+// RISCV64: #define __INT_LEAST8_TYPE__ signed char
+// RISCV64: #define __INT_MAX__ 2147483647
+// RISCV64: #define __LDBL_DECIMAL_DIG__ 36
+// RISCV64: #define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L
+// RISCV64: #define __LDBL_DIG__ 33
+// RISCV64: #define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L
+// RISCV64: #define __LDBL_HAS_DENORM__ 1
+// RISCV64: #define __LDBL_HAS_INFINITY__ 1
+// RISCV64: #define __LDBL_HAS_QUIET_NAN__ 1
+// RISCV64: #define __LDBL_MANT_DIG__ 113
+// RISCV64: #define __LDBL_MAX_10_EXP__ 4932
+// RISCV64: #define __LDBL_MAX_EXP__ 16384
+// RISCV64: #define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L
+// RISCV64: #define __LDBL_MIN_10_EXP__ (-4931)
+// RISCV64: #define __LDBL_MIN_EXP__ (-16381)
+// RISCV64: #define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
+// RISCV64: #define __LITTLE_ENDIAN__ 1
+// RISCV64: #define __LONG_LONG_MAX__ 9223372036854775807LL
+// RISCV64: #define __LONG_MAX__ 9223372036854775807L
+// RISCV64: #define __LP64__ 1
+// RISCV64: #define __NO_INLINE__ 1
+// RISCV64: #define __POINTER_WIDTH__ 64
+// RISCV64: #define __PRAGMA_REDEFINE_EXTNAME 1
+// RISCV64: #define __PTRDIFF_MAX__ 9223372036854775807L
+// RISCV64: #define __PTRDIFF_TYPE__ long int
+// RISCV64: #define __PTRDIFF_WIDTH__ 64
+// RISCV64: #define __SCHAR_MAX__ 127
+// RISCV64: #define __SHRT_MAX__ 32767
+// RISCV64: #define __SIG_ATOMIC_MAX__ 2147483647
+// RISCV64: #define __SIG_ATOMIC_WIDTH__ 32
+// RISCV64: #define __SIZEOF_DOUBLE__ 8
+// RISCV64: #define __SIZEOF_FLOAT__ 4
+// RISCV64: #define __SIZEOF_INT__ 4
+// RISCV64: #define __SIZEOF_LONG_DOUBLE__ 16
+// RISCV64: #define __SIZEOF_LONG_LONG__ 8
+// RISCV64: #define __SIZEOF_LONG__ 8
+// RISCV64: #define __SIZEOF_POINTER__ 8
+// RISCV64: #define __SIZEOF_PTRDIFF_T__ 8
+// RISCV64: #define __SIZEOF_SHORT__ 2
+// RISCV64: #define __SIZEOF_SIZE_T__ 8
+// RISCV64: #define __SIZEOF_WCHAR_T__ 4
+// RISCV64: #define __SIZEOF_WINT_T__ 4
+// RISCV64: #define __SIZE_MAX__ 18446744073709551615UL
+// RISCV64: #define __SIZE_TYPE__ long unsigned int
+// RISCV64: #define __SIZE_WIDTH__ 64
+// RISCV64: #define __STDC_HOSTED__ 0
+// RISCV64: #define __STDC_UTF_16__ 1
+// RISCV64: #define __STDC_UTF_32__ 1
+// RISCV64: #define __STDC_VERSION__ 201112L
+// RISCV64: #define __STDC__ 1
+// RISCV64: #define __UINT16_C_SUFFIX__
+// RISCV64: #define __UINT16_MAX__ 65535
+// RISCV64: #define __UINT16_TYPE__ unsigned short
+// RISCV64: #define __UINT32_C_SUFFIX__ U
+// RISCV64: #define __UINT32_MAX__ 4294967295U
+// RISCV64: #define __UINT32_TYPE__ unsigned int
+// RISCV64: #define __UINT64_C_SUFFIX__ UL
+// RISCV64: #define __UINT64_MAX__ 18446744073709551615UL
+// RISCV64: #define __UINT64_TYPE__ long unsigned int
+// RISCV64: #define __UINT8_C_SUFFIX__
+// RISCV64: #define __UINT8_MAX__ 255
+// RISCV64: #define __UINT8_TYPE__ unsigned char
+// RISCV64: #define __UINTMAX_C_SUFFIX__ UL
+// RISCV64: #define __UINTMAX_MAX__ 18446744073709551615UL
+// RISCV64: #define __UINTMAX_TYPE__ long unsigned int
+// RISCV64: #define __UINTMAX_WIDTH__ 64
+// RISCV64: #define __UINTPTR_MAX__ 18446744073709551615UL
+// RISCV64: #define __UINTPTR_TYPE__ long unsigned int
+// RISCV64: #define __UINTPTR_WIDTH__ 64
+// TODO: RISC-V GCC defines UINT_FAST16 to be unsigned int
+// RISCV64: #define __UINT_FAST16_MAX__ 65535
+// RISCV64: #define __UINT_FAST16_TYPE__ unsigned short
+// RISCV64: #define __UINT_FAST32_MAX__ 4294967295U
+// RISCV64: #define __UINT_FAST32_TYPE__ unsigned int
+// RISCV64: #define __UINT_FAST64_MAX__ 18446744073709551615UL
+// RISCV64: #define __UINT_FAST64_TYPE__ long unsigned int
+// TODO: RISC-V GCC defines UINT_FAST8 to be unsigned int
+// RISCV64: #define __UINT_FAST8_MAX__ 255
+// RISCV64: #define __UINT_FAST8_TYPE__ unsigned char
+// RISCV64: #define __UINT_LEAST16_MAX__ 65535
+// RISCV64: #define __UINT_LEAST16_TYPE__ unsigned short
+// RISCV64: #define __UINT_LEAST32_MAX__ 4294967295U
+// RISCV64: #define __UINT_LEAST32_TYPE__ unsigned int
+// RISCV64: #define __UINT_LEAST64_MAX__ 18446744073709551615UL
+// RISCV64: #define __UINT_LEAST64_TYPE__ long unsigned int
+// RISCV64: #define __UINT_LEAST8_MAX__ 255
+// RISCV64: #define __UINT_LEAST8_TYPE__ unsigned char
+// RISCV64: #define __USER_LABEL_PREFIX__
+// RISCV64: #define __WCHAR_MAX__ 2147483647
+// RISCV64: #define __WCHAR_TYPE__ int
+// RISCV64: #define __WCHAR_WIDTH__ 32
+// RISCV64: #define __WINT_TYPE__ unsigned int
+// RISCV64: #define __WINT_UNSIGNED__ 1
+// RISCV64: #define __WINT_WIDTH__ 32
+// RISCV64-LINUX: #define __gnu_linux__ 1
+// RISCV64-LINUX: #define __linux 1
+// RISCV64-LINUX: #define __linux__ 1
+// RISCV64: #define __riscv 1
+// RISCV64: #define __riscv_cmodel_medlow 1
+// RISCV64: #define __riscv_float_abi_soft 1
+// RISCV64: #define __riscv_xlen 64
+// RISCV64-LINUX: #define __unix 1
+// RISCV64-LINUX: #define __unix__ 1
+// RISCV64-LINUX: #define linux 1
+// RISCV64-LINUX: #define unix 1
diff --git a/test/Preprocessor/macro-multiline.c b/test/Preprocessor/macro-multiline.c
index 72a5d20e523f..664c37cd02a4 100644
--- a/test/Preprocessor/macro-multiline.c
+++ b/test/Preprocessor/macro-multiline.c
@@ -1,4 +1,4 @@
-// RUN: printf -- "-DX=A\nTHIS_SHOULD_NOT_EXIST_IN_THE_OUTPUT" | xargs -0 %clang -E %s | FileCheck -strict-whitespace %s
+// RUN: printf -- "-DX=A\\\\\nTHIS_SHOULD_NOT_EXIST_IN_THE_OUTPUT\n" | xargs %clang -E %s | FileCheck -strict-whitespace %s
// Per GCC -D semantics, \n and anything that follows is ignored.
diff --git a/test/Preprocessor/macro_paste_commaext.c b/test/Preprocessor/macro_paste_commaext.c
index 60418effe7c3..f3e6f9d40942 100644
--- a/test/Preprocessor/macro_paste_commaext.c
+++ b/test/Preprocessor/macro_paste_commaext.c
@@ -1,9 +1,9 @@
// RUN: %clang_cc1 %s -E | FileCheck --strict-whitespace --match-full-lines %s
// In the following tests, note that the output is sensitive to the
-// whitespace *preceeding* the varargs argument, as well as to
+// whitespace *preceding* the varargs argument, as well as to
// interior whitespace. AFAIK, this is the only case where whitespace
-// preceeding an argument matters, and might be considered a bug in
+// preceding an argument matters, and might be considered a bug in
// GCC. Nevertheless, since this feature is a GCC extension in the
// first place, we'll follow along.
diff --git a/test/Preprocessor/nonportable-include-with-hmap.c b/test/Preprocessor/nonportable-include-with-hmap.c
index fc958e7e5e3f..bbbd669a0f39 100644
--- a/test/Preprocessor/nonportable-include-with-hmap.c
+++ b/test/Preprocessor/nonportable-include-with-hmap.c
@@ -1,5 +1,7 @@
+// RUN: rm -f %t.hmap
+// RUN: %hmaptool write %S/Inputs/nonportable-hmaps/foo.hmap.json %t.hmap
// RUN: %clang_cc1 -Eonly \
-// RUN: -I%S/Inputs/nonportable-hmaps/foo.hmap \
+// RUN: -I%t.hmap \
// RUN: -I%S/Inputs/nonportable-hmaps \
// RUN: %s -verify
//
diff --git a/test/Preprocessor/pragma-comment-linux.c b/test/Preprocessor/pragma-comment-linux.c
new file mode 100644
index 000000000000..fcac049f46e8
--- /dev/null
+++ b/test/Preprocessor/pragma-comment-linux.c
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fsyntax-only -verify %s -Wunknown-pragmas
+
+#pragma comment(linker, "")
+// expected-warning@-1 {{'#pragma comment linker' ignored}}
+
diff --git a/test/Preprocessor/pragma_microsoft.c b/test/Preprocessor/pragma_microsoft.c
index b256b2bee6cf..4105e41af44b 100644
--- a/test/Preprocessor/pragma_microsoft.c
+++ b/test/Preprocessor/pragma_microsoft.c
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 %s -fsyntax-only -verify -fms-extensions -Wunknown-pragmas
-// RUN: not %clang_cc1 %s -fms-extensions -E | FileCheck %s
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc %s -fsyntax-only -verify -fms-extensions -Wunknown-pragmas
+// RUN: not %clang_cc1 -triple i686-unknown-windows-msvc %s -fms-extensions -E | FileCheck %s
// REQUIRES: non-ps4-sdk
// rdar://6495941
@@ -190,3 +190,11 @@ void g() {}
#pragma intrinsic(asdf) // no-warning
#pragma clang diagnostic pop
#pragma intrinsic(asdf) // expected-warning {{'asdf' is not a recognized builtin; consider including <intrin.h>}}
+
+#pragma optimize // expected-warning{{missing '(' after '#pragma optimize'}}
+#pragma optimize( // expected-warning{{expected string literal in '#pragma optimize'}}
+#pragma optimize(a // expected-warning{{expected string literal in '#pragma optimize'}}
+#pragma optimize("g" // expected-warning{{expected ',' in '#pragma optimize'}}
+#pragma optimize("g", // expected-warning{{missing argument to '#pragma optimize'; expected 'on' or 'off'}}
+#pragma optimize("g",xyz // expected-warning{{unexpected argument 'xyz' to '#pragma optimize'; expected 'on' or 'off'}}
+#pragma optimize("g",on) // expected-warning{{#pragma optimize' is not supported}}
diff --git a/test/Preprocessor/pragma_unknown.c b/test/Preprocessor/pragma_unknown.c
index 5578ce5b7502..81fe88cd3855 100644
--- a/test/Preprocessor/pragma_unknown.c
+++ b/test/Preprocessor/pragma_unknown.c
@@ -1,29 +1,45 @@
// RUN: %clang_cc1 -fsyntax-only -Wunknown-pragmas -verify %s
-// RUN: %clang_cc1 -E %s | FileCheck --strict-whitespace %s
+// RUN: %clang_cc1 -E %s 2>&1 | FileCheck --strict-whitespace %s
// GCC doesn't expand macro args for unrecognized pragmas.
#define bar xX
#pragma foo bar // expected-warning {{unknown pragma ignored}}
+// CHECK-NOT: unknown pragma in STDC namespace
// CHECK: {{^}}#pragma foo bar{{$}}
#pragma STDC FP_CONTRACT ON
#pragma STDC FP_CONTRACT OFF
#pragma STDC FP_CONTRACT DEFAULT
#pragma STDC FP_CONTRACT IN_BETWEEN // expected-warning {{expected 'ON' or 'OFF' or 'DEFAULT' in pragma}}
+// CHECK: {{^}}#pragma STDC FP_CONTRACT ON{{$}}
+// CHECK: {{^}}#pragma STDC FP_CONTRACT OFF{{$}}
+// CHECK: {{^}}#pragma STDC FP_CONTRACT DEFAULT{{$}}
+// CHECK: {{^}}#pragma STDC FP_CONTRACT IN_BETWEEN{{$}}
#pragma STDC FENV_ACCESS ON // expected-warning {{pragma STDC FENV_ACCESS ON is not supported, ignoring pragma}}
#pragma STDC FENV_ACCESS OFF
#pragma STDC FENV_ACCESS DEFAULT
#pragma STDC FENV_ACCESS IN_BETWEEN // expected-warning {{expected 'ON' or 'OFF' or 'DEFAULT' in pragma}}
+// CHECK: {{^}}#pragma STDC FENV_ACCESS ON{{$}}
+// CHECK: {{^}}#pragma STDC FENV_ACCESS OFF{{$}}
+// CHECK: {{^}}#pragma STDC FENV_ACCESS DEFAULT{{$}}
+// CHECK: {{^}}#pragma STDC FENV_ACCESS IN_BETWEEN{{$}}
#pragma STDC CX_LIMITED_RANGE ON
#pragma STDC CX_LIMITED_RANGE OFF
#pragma STDC CX_LIMITED_RANGE DEFAULT
#pragma STDC CX_LIMITED_RANGE IN_BETWEEN // expected-warning {{expected 'ON' or 'OFF' or 'DEFAULT' in pragma}}
+// CHECK: {{^}}#pragma STDC CX_LIMITED_RANGE ON{{$}}
+// CHECK: {{^}}#pragma STDC CX_LIMITED_RANGE OFF{{$}}
+// CHECK: {{^}}#pragma STDC CX_LIMITED_RANGE DEFAULT{{$}}
+// CHECK: {{^}}#pragma STDC CX_LIMITED_RANGE IN_BETWEEN{{$}}
#pragma STDC CX_LIMITED_RANGE // expected-warning {{expected 'ON' or 'OFF' or 'DEFAULT' in pragma}}
#pragma STDC CX_LIMITED_RANGE ON FULL POWER // expected-warning {{expected end of directive in pragma}}
+// CHECK: {{^}}#pragma STDC CX_LIMITED_RANGE{{$}}
+// CHECK: {{^}}#pragma STDC CX_LIMITED_RANGE ON FULL POWER{{$}}
#pragma STDC SO_GREAT // expected-warning {{unknown pragma in STDC namespace}}
#pragma STDC // expected-warning {{unknown pragma in STDC namespace}}
-
+// CHECK: {{^}}#pragma STDC SO_GREAT{{$}}
+// CHECK: {{^}}#pragma STDC{{$}}
diff --git a/test/Preprocessor/predefined-arch-macros.c b/test/Preprocessor/predefined-arch-macros.c
index dac137c57536..281e6780cbf5 100644
--- a/test/Preprocessor/predefined-arch-macros.c
+++ b/test/Preprocessor/predefined-arch-macros.c
@@ -1,5 +1,5 @@
// Begin X86/GCC/Linux tests ----------------
-//
+
// RUN: %clang -march=i386 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_I386_M32
@@ -11,7 +11,7 @@
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_I386_M64
// CHECK_I386_M64: error: {{.*}}
-//
+
// RUN: %clang -march=i486 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_I486_M32
@@ -25,7 +25,7 @@
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_I486_M64
// CHECK_I486_M64: error: {{.*}}
-//
+
// RUN: %clang -march=i586 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_I586_M32
@@ -42,7 +42,7 @@
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_I586_M64
// CHECK_I586_M64: error: {{.*}}
-//
+
// RUN: %clang -march=pentium -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_PENTIUM_M32
@@ -59,7 +59,7 @@
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_PENTIUM_M64
// CHECK_PENTIUM_M64: error: {{.*}}
-//
+
// RUN: %clang -march=pentium-mmx -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_PENTIUM_MMX_M32
@@ -79,7 +79,7 @@
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_PENTIUM_MMX_M64
// CHECK_PENTIUM_MMX_M64: error: {{.*}}
-//
+
// RUN: %clang -march=winchip-c6 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_WINCHIP_C6_M32
@@ -94,7 +94,7 @@
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_WINCHIP_C6_M64
// CHECK_WINCHIP_C6_M64: error: {{.*}}
-//
+
// RUN: %clang -march=winchip2 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_WINCHIP2_M32
@@ -110,7 +110,7 @@
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_WINCHIP2_M64
// CHECK_WINCHIP2_M64: error: {{.*}}
-//
+
// RUN: %clang -march=c3 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_C3_M32
@@ -126,7 +126,7 @@
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_C3_M64
// CHECK_C3_M64: error: {{.*}}
-//
+
// RUN: %clang -march=c3-2 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_C3_2_M32
@@ -146,7 +146,7 @@
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_C3_2_M64
// CHECK_C3_2_M64: error: {{.*}}
-//
+
// RUN: %clang -march=i686 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_I686_M32
@@ -163,7 +163,7 @@
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_I686_M64
// CHECK_I686_M64: error: {{.*}}
-//
+
// RUN: %clang -march=pentiumpro -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_PENTIUMPRO_M32
@@ -180,7 +180,7 @@
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_PENTIUMPRO_M64
// CHECK_PENTIUMPRO_M64: error: {{.*}}
-//
+
// RUN: %clang -march=pentium2 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_PENTIUM2_M32
@@ -199,7 +199,7 @@
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_PENTIUM2_M64
// CHECK_PENTIUM2_M64: error: {{.*}}
-//
+
// RUN: %clang -march=pentium3 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_PENTIUM3_M32
@@ -220,7 +220,7 @@
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_PENTIUM3_M64
// CHECK_PENTIUM3_M64: error: {{.*}}
-//
+
// RUN: %clang -march=pentium3m -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_PENTIUM3M_M32
@@ -239,7 +239,7 @@
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_PENTIUM3M_M64
// CHECK_PENTIUM3M_M64: error: {{.*}}
-//
+
// RUN: %clang -march=pentium-m -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_PENTIUM_M_M32
@@ -259,7 +259,7 @@
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_PENTIUM_M_M64
// CHECK_PENTIUM_M_M64: error: {{.*}}
-//
+
// RUN: %clang -march=pentium4 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_PENTIUM4_M32
@@ -276,7 +276,7 @@
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_PENTIUM4_M64
// CHECK_PENTIUM4_M64: error: {{.*}}
-//
+
// RUN: %clang -march=pentium4m -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_PENTIUM4M_M32
@@ -293,7 +293,7 @@
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_PENTIUM4M_M64
// CHECK_PENTIUM4M_M64: error: {{.*}}
-//
+
// RUN: %clang -march=prescott -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_PRESCOTT_M32
@@ -311,7 +311,7 @@
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_PRESCOTT_M64
// CHECK_PRESCOTT_M64: error: {{.*}}
-//
+
// RUN: %clang -march=nocona -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_NOCONA_M32
@@ -341,7 +341,7 @@
// CHECK_NOCONA_M64: #define __tune_nocona__ 1
// CHECK_NOCONA_M64: #define __x86_64 1
// CHECK_NOCONA_M64: #define __x86_64__ 1
-//
+
// RUN: %clang -march=core2 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_CORE2_M32
@@ -356,6 +356,7 @@
// CHECK_CORE2_M32: #define __i386__ 1
// CHECK_CORE2_M32: #define __tune_core2__ 1
// CHECK_CORE2_M32: #define i386 1
+
// RUN: %clang -march=core2 -m64 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_CORE2_M64
@@ -373,7 +374,7 @@
// CHECK_CORE2_M64: #define __tune_core2__ 1
// CHECK_CORE2_M64: #define __x86_64 1
// CHECK_CORE2_M64: #define __x86_64__ 1
-//
+
// RUN: %clang -march=corei7 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_COREI7_M32
@@ -391,6 +392,7 @@
// CHECK_COREI7_M32: #define __i386__ 1
// CHECK_COREI7_M32: #define __tune_corei7__ 1
// CHECK_COREI7_M32: #define i386 1
+
// RUN: %clang -march=corei7 -m64 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_COREI7_M64
@@ -411,7 +413,7 @@
// CHECK_COREI7_M64: #define __tune_corei7__ 1
// CHECK_COREI7_M64: #define __x86_64 1
// CHECK_COREI7_M64: #define __x86_64__ 1
-//
+
// RUN: %clang -march=corei7-avx -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_COREI7_AVX_M32
@@ -435,6 +437,7 @@
// CHECK_COREI7_AVX_M32: #define __i386__ 1
// CHECK_COREI7_AVX_M32: #define __tune_corei7__ 1
// CHECK_COREI7_AVX_M32: #define i386 1
+
// RUN: %clang -march=corei7-avx -m64 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_COREI7_AVX_M64
@@ -461,7 +464,7 @@
// CHECK_COREI7_AVX_M64: #define __tune_corei7__ 1
// CHECK_COREI7_AVX_M64: #define __x86_64 1
// CHECK_COREI7_AVX_M64: #define __x86_64__ 1
-//
+
// RUN: %clang -march=core-avx-i -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_CORE_AVX_I_M32
@@ -485,6 +488,7 @@
// CHECK_CORE_AVX_I_M32: #define __i386__ 1
// CHECK_CORE_AVX_I_M32: #define __tune_corei7__ 1
// CHECK_CORE_AVX_I_M32: #define i386 1
+
// RUN: %clang -march=core-avx-i -m64 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_CORE_AVX_I_M64
@@ -511,7 +515,7 @@
// CHECK_CORE_AVX_I_M64: #define __tune_corei7__ 1
// CHECK_CORE_AVX_I_M64: #define __x86_64 1
// CHECK_CORE_AVX_I_M64: #define __x86_64__ 1
-//
+
// RUN: %clang -march=core-avx2 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_CORE_AVX2_M32
@@ -522,6 +526,7 @@
// CHECK_CORE_AVX2_M32: #define __BMI__ 1
// CHECK_CORE_AVX2_M32: #define __F16C__ 1
// CHECK_CORE_AVX2_M32: #define __FMA__ 1
+// CHECK_CORE_AVX2_M32: #define __INVPCID__ 1
// CHECK_CORE_AVX2_M32: #define __LZCNT__ 1
// CHECK_CORE_AVX2_M32: #define __MMX__ 1
// CHECK_CORE_AVX2_M32: #define __PCLMUL__ 1
@@ -541,6 +546,7 @@
// CHECK_CORE_AVX2_M32: #define __i386__ 1
// CHECK_CORE_AVX2_M32: #define __tune_corei7__ 1
// CHECK_CORE_AVX2_M32: #define i386 1
+
// RUN: %clang -march=core-avx2 -m64 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_CORE_AVX2_M64
@@ -551,6 +557,7 @@
// CHECK_CORE_AVX2_M64: #define __BMI__ 1
// CHECK_CORE_AVX2_M64: #define __F16C__ 1
// CHECK_CORE_AVX2_M64: #define __FMA__ 1
+// CHECK_CORE_AVX2_M64: #define __INVPCID__ 1
// CHECK_CORE_AVX2_M64: #define __LZCNT__ 1
// CHECK_CORE_AVX2_M64: #define __MMX__ 1
// CHECK_CORE_AVX2_M64: #define __PCLMUL__ 1
@@ -573,7 +580,7 @@
// CHECK_CORE_AVX2_M64: #define __tune_corei7__ 1
// CHECK_CORE_AVX2_M64: #define __x86_64 1
// CHECK_CORE_AVX2_M64: #define __x86_64__ 1
-//
+
// RUN: %clang -march=broadwell -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_BROADWELL_M32
@@ -585,6 +592,7 @@
// CHECK_BROADWELL_M32: #define __BMI__ 1
// CHECK_BROADWELL_M32: #define __F16C__ 1
// CHECK_BROADWELL_M32: #define __FMA__ 1
+// CHECK_BROADWELL_M32: #define __INVPCID__ 1
// CHECK_BROADWELL_M32: #define __LZCNT__ 1
// CHECK_BROADWELL_M32: #define __MMX__ 1
// CHECK_BROADWELL_M32: #define __PCLMUL__ 1
@@ -606,6 +614,7 @@
// CHECK_BROADWELL_M32: #define __i386__ 1
// CHECK_BROADWELL_M32: #define __tune_corei7__ 1
// CHECK_BROADWELL_M32: #define i386 1
+
// RUN: %clang -march=broadwell -m64 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_BROADWELL_M64
@@ -617,6 +626,7 @@
// CHECK_BROADWELL_M64: #define __BMI__ 1
// CHECK_BROADWELL_M64: #define __F16C__ 1
// CHECK_BROADWELL_M64: #define __FMA__ 1
+// CHECK_BROADWELL_M64: #define __INVPCID__ 1
// CHECK_BROADWELL_M64: #define __LZCNT__ 1
// CHECK_BROADWELL_M64: #define __MMX__ 1
// CHECK_BROADWELL_M64: #define __PCLMUL__ 1
@@ -641,7 +651,7 @@
// CHECK_BROADWELL_M64: #define __tune_corei7__ 1
// CHECK_BROADWELL_M64: #define __x86_64 1
// CHECK_BROADWELL_M64: #define __x86_64__ 1
-//
+
// RUN: %clang -march=skylake -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SKL_M32
@@ -654,6 +664,7 @@
// CHECK_SKL_M32: #define __CLFLUSHOPT__ 1
// CHECK_SKL_M32: #define __F16C__ 1
// CHECK_SKL_M32: #define __FMA__ 1
+// CHECK_SKL_M32: #define __INVPCID__ 1
// CHECK_SKL_M32: #define __LZCNT__ 1
// CHECK_SKL_M32: #define __MMX__ 1
// CHECK_SKL_M32: #define __MPX__ 1
@@ -688,6 +699,7 @@
// CHECK_SKL_M64: #define __CLFLUSHOPT__ 1
// CHECK_SKL_M64: #define __F16C__ 1
// CHECK_SKL_M64: #define __FMA__ 1
+// CHECK_SKL_M64: #define __INVPCID__ 1
// CHECK_SKL_M64: #define __LZCNT__ 1
// CHECK_SKL_M64: #define __MMX__ 1
// CHECK_SKL_M64: #define __MPX__ 1
@@ -864,7 +876,7 @@
// CHECK_KNM_M64: #define __amd64__ 1
// CHECK_KNM_M64: #define __x86_64 1
// CHECK_KNM_M64: #define __x86_64__ 1
-//
+
// RUN: %clang -march=skylake-avx512 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SKX_M32
@@ -882,6 +894,7 @@
// CHECK_SKX_M32: #define __CLWB__ 1
// CHECK_SKX_M32: #define __F16C__ 1
// CHECK_SKX_M32: #define __FMA__ 1
+// CHECK_SKX_M32: #define __INVPCID__ 1
// CHECK_SKX_M32: #define __LZCNT__ 1
// CHECK_SKX_M32: #define __MMX__ 1
// CHECK_SKX_M32: #define __MPX__ 1
@@ -890,8 +903,9 @@
// CHECK_SKX_M32: #define __POPCNT__ 1
// CHECK_SKX_M32: #define __PRFCHW__ 1
// CHECK_SKX_M32: #define __RDRND__ 1
+// CHECK_SKX_M32: #define __RDSEED__ 1
// CHECK_SKX_M32: #define __RTM__ 1
-// CHECK_SKX_M32: #define __SGX__ 1
+// CHECK_SKX_M32-NOT: #define __SGX__ 1
// CHECK_SKX_M32: #define __SSE2__ 1
// CHECK_SKX_M32: #define __SSE3__ 1
// CHECK_SKX_M32: #define __SSE4_1__ 1
@@ -926,6 +940,7 @@
// CHECK_SKX_M64: #define __CLWB__ 1
// CHECK_SKX_M64: #define __F16C__ 1
// CHECK_SKX_M64: #define __FMA__ 1
+// CHECK_SKX_M64: #define __INVPCID__ 1
// CHECK_SKX_M64: #define __LZCNT__ 1
// CHECK_SKX_M64: #define __MMX__ 1
// CHECK_SKX_M64: #define __MPX__ 1
@@ -934,8 +949,9 @@
// CHECK_SKX_M64: #define __POPCNT__ 1
// CHECK_SKX_M64: #define __PRFCHW__ 1
// CHECK_SKX_M64: #define __RDRND__ 1
+// CHECK_SKX_M64: #define __RDSEED__ 1
// CHECK_SKX_M64: #define __RTM__ 1
-// CHECK_SKX_M64: #define __SGX__ 1
+// CHECK_SKX_M64-NOT: #define __SGX__ 1
// CHECK_SKX_M64: #define __SSE2_MATH__ 1
// CHECK_SKX_M64: #define __SSE2__ 1
// CHECK_SKX_M64: #define __SSE3__ 1
@@ -955,7 +971,7 @@
// CHECK_SKX_M64: #define __tune_corei7__ 1
// CHECK_SKX_M64: #define __x86_64 1
// CHECK_SKX_M64: #define __x86_64__ 1
-//
+
// RUN: %clang -march=cannonlake -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_CNL_M32
@@ -975,14 +991,16 @@
// CHECK_CNL_M32-NOT: #define __CLWB__ 1
// CHECK_CNL_M32: #define __F16C__ 1
// CHECK_CNL_M32: #define __FMA__ 1
+// CHECK_CNL_M32: #define __INVPCID__ 1
// CHECK_CNL_M32: #define __LZCNT__ 1
// CHECK_CNL_M32: #define __MMX__ 1
// CHECK_CNL_M32: #define __MPX__ 1
// CHECK_CNL_M32: #define __PCLMUL__ 1
-// CHECK_CNL_M32-NOT: #define __PKU__ 1
+// CHECK_CNL_M32: #define __PKU__ 1
// CHECK_CNL_M32: #define __POPCNT__ 1
// CHECK_CNL_M32: #define __PRFCHW__ 1
// CHECK_CNL_M32: #define __RDRND__ 1
+// CHECK_CNL_M32: #define __RDSEED__ 1
// CHECK_CNL_M32: #define __RTM__ 1
// CHECK_CNL_M32: #define __SGX__ 1
// CHECK_CNL_M32: #define __SHA__ 1
@@ -1002,7 +1020,7 @@
// CHECK_CNL_M32: #define __i386__ 1
// CHECK_CNL_M32: #define __tune_corei7__ 1
// CHECK_CNL_M32: #define i386 1
-//
+
// RUN: %clang -march=cannonlake -m64 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_CNL_M64
@@ -1022,14 +1040,16 @@
// CHECK_CNL_M64-NOT: #define __CLWB__ 1
// CHECK_CNL_M64: #define __F16C__ 1
// CHECK_CNL_M64: #define __FMA__ 1
+// CHECK_CNL_M64: #define __INVPCID__ 1
// CHECK_CNL_M64: #define __LZCNT__ 1
// CHECK_CNL_M64: #define __MMX__ 1
// CHECK_CNL_M64: #define __MPX__ 1
// CHECK_CNL_M64: #define __PCLMUL__ 1
-// CHECK_CNL_M64-NOT: #define __PKU__ 1
+// CHECK_CNL_M64: #define __PKU__ 1
// CHECK_CNL_M64: #define __POPCNT__ 1
// CHECK_CNL_M64: #define __PRFCHW__ 1
// CHECK_CNL_M64: #define __RDRND__ 1
+// CHECK_CNL_M64: #define __RDSEED__ 1
// CHECK_CNL_M64: #define __RTM__ 1
// CHECK_CNL_M64: #define __SGX__ 1
// CHECK_CNL_M64: #define __SHA__ 1
@@ -1051,7 +1071,7 @@
// CHECK_CNL_M64: #define __x86_64 1
// CHECK_CNL_M64: #define __x86_64__ 1
-// RUN: %clang -march=icelake -m32 -E -dM %s -o - 2>&1 \
+// RUN: %clang -march=icelake-client -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_ICL_M32
// CHECK_ICL_M32: #define __AES__ 1
@@ -1075,14 +1095,17 @@
// CHECK_ICL_M32: #define __F16C__ 1
// CHECK_ICL_M32: #define __FMA__ 1
// CHECK_ICL_M32: #define __GFNI__ 1
+// CHECK_ICL_M32: #define __INVPCID__ 1
// CHECK_ICL_M32: #define __LZCNT__ 1
// CHECK_ICL_M32: #define __MMX__ 1
// CHECK_ICL_M32: #define __MPX__ 1
// CHECK_ICL_M32: #define __PCLMUL__ 1
-// CHECK_ICL_M32-NOT: #define __PKU__ 1
+// CHECK_ICL_M32: #define __PKU__ 1
// CHECK_ICL_M32: #define __POPCNT__ 1
// CHECK_ICL_M32: #define __PRFCHW__ 1
+// CHECK_ICL_M32: #define __RDPID__ 1
// CHECK_ICL_M32: #define __RDRND__ 1
+// CHECK_ICL_M32: #define __RDSEED__ 1
// CHECK_ICL_M32: #define __RTM__ 1
// CHECK_ICL_M32: #define __SGX__ 1
// CHECK_ICL_M32: #define __SHA__ 1
@@ -1094,6 +1117,7 @@
// CHECK_ICL_M32: #define __SSSE3__ 1
// CHECK_ICL_M32: #define __VAES__ 1
// CHECK_ICL_M32: #define __VPCLMULQDQ__ 1
+// CHECK_ICL_M32-NOT: #define __WBNOINVD__ 1
// CHECK_ICL_M32: #define __XSAVEC__ 1
// CHECK_ICL_M32: #define __XSAVEOPT__ 1
// CHECK_ICL_M32: #define __XSAVES__ 1
@@ -1104,8 +1128,8 @@
// CHECK_ICL_M32: #define __i386__ 1
// CHECK_ICL_M32: #define __tune_corei7__ 1
// CHECK_ICL_M32: #define i386 1
-//
-// RUN: %clang -march=icelake -m64 -E -dM %s -o - 2>&1 \
+
+// RUN: %clang -march=icelake-client -m64 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_ICL_M64
// CHECK_ICL_M64: #define __AES__ 1
@@ -1129,14 +1153,17 @@
// CHECK_ICL_M64: #define __F16C__ 1
// CHECK_ICL_M64: #define __FMA__ 1
// CHECK_ICL_M64: #define __GFNI__ 1
+// CHECK_ICL_M64: #define __INVPCID__ 1
// CHECK_ICL_M64: #define __LZCNT__ 1
// CHECK_ICL_M64: #define __MMX__ 1
// CHECK_ICL_M64: #define __MPX__ 1
// CHECK_ICL_M64: #define __PCLMUL__ 1
-// CHECK_ICL_M64-NOT: #define __PKU__ 1
+// CHECK_ICL_M64: #define __PKU__ 1
// CHECK_ICL_M64: #define __POPCNT__ 1
// CHECK_ICL_M64: #define __PRFCHW__ 1
+// CHECK_ICL_M64: #define __RDPID__ 1
// CHECK_ICL_M64: #define __RDRND__ 1
+// CHECK_ICL_M64: #define __RDSEED__ 1
// CHECK_ICL_M64: #define __RTM__ 1
// CHECK_ICL_M64: #define __SGX__ 1
// CHECK_ICL_M64: #define __SHA__ 1
@@ -1148,6 +1175,7 @@
// CHECK_ICL_M64: #define __SSSE3__ 1
// CHECK_ICL_M64: #define __VAES__ 1
// CHECK_ICL_M64: #define __VPCLMULQDQ__ 1
+// CHECK_ICL_M64-NOT: #define __WBNOINVD__ 1
// CHECK_ICL_M64: #define __XSAVEC__ 1
// CHECK_ICL_M64: #define __XSAVEOPT__ 1
// CHECK_ICL_M64: #define __XSAVES__ 1
@@ -1160,6 +1188,125 @@
// CHECK_ICL_M64: #define __x86_64 1
// CHECK_ICL_M64: #define __x86_64__ 1
+// RUN: %clang -march=icelake-server -m32 -E -dM %s -o - 2>&1 \
+// RUN: -target i386-unknown-linux \
+// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_ICX_M32
+// CHECK_ICX_M32: #define __AES__ 1
+// CHECK_ICX_M32: #define __AVX2__ 1
+// CHECK_ICX_M32: #define __AVX512BITALG__ 1
+// CHECK_ICX_M32: #define __AVX512BW__ 1
+// CHECK_ICX_M32: #define __AVX512CD__ 1
+// CHECK_ICX_M32: #define __AVX512DQ__ 1
+// CHECK_ICX_M32: #define __AVX512F__ 1
+// CHECK_ICX_M32: #define __AVX512IFMA__ 1
+// CHECK_ICX_M32: #define __AVX512VBMI2__ 1
+// CHECK_ICX_M32: #define __AVX512VBMI__ 1
+// CHECK_ICX_M32: #define __AVX512VL__ 1
+// CHECK_ICX_M32: #define __AVX512VNNI__ 1
+// CHECK_ICX_M32: #define __AVX512VPOPCNTDQ__ 1
+// CHECK_ICX_M32: #define __AVX__ 1
+// CHECK_ICX_M32: #define __BMI2__ 1
+// CHECK_ICX_M32: #define __BMI__ 1
+// CHECK_ICX_M32: #define __CLFLUSHOPT__ 1
+// CHECK_ICX_M32: #define __CLWB__ 1
+// CHECK_ICX_M32: #define __F16C__ 1
+// CHECK_ICX_M32: #define __FMA__ 1
+// CHECK_ICX_M32: #define __GFNI__ 1
+// CHECK_ICX_M32: #define __INVPCID__ 1
+// CHECK_ICX_M32: #define __LZCNT__ 1
+// CHECK_ICX_M32: #define __MMX__ 1
+// CHECK_ICX_M32: #define __MPX__ 1
+// CHECK_ICX_M32: #define __PCLMUL__ 1
+// CHECK_ICX_M32: #define __PCONFIG__ 1
+// CHECK_ICX_M32: #define __PKU__ 1
+// CHECK_ICX_M32: #define __POPCNT__ 1
+// CHECK_ICX_M32: #define __PRFCHW__ 1
+// CHECK_ICX_M32: #define __RDPID__ 1
+// CHECK_ICX_M32: #define __RDRND__ 1
+// CHECK_ICX_M32: #define __RDSEED__ 1
+// CHECK_ICX_M32: #define __RTM__ 1
+// CHECK_ICX_M32: #define __SGX__ 1
+// CHECK_ICX_M32: #define __SHA__ 1
+// CHECK_ICX_M32: #define __SSE2__ 1
+// CHECK_ICX_M32: #define __SSE3__ 1
+// CHECK_ICX_M32: #define __SSE4_1__ 1
+// CHECK_ICX_M32: #define __SSE4_2__ 1
+// CHECK_ICX_M32: #define __SSE__ 1
+// CHECK_ICX_M32: #define __SSSE3__ 1
+// CHECK_ICX_M32: #define __VAES__ 1
+// CHECK_ICX_M32: #define __VPCLMULQDQ__ 1
+// CHECK_ICX_M32: #define __WBNOINVD__ 1
+// CHECK_ICX_M32: #define __XSAVEC__ 1
+// CHECK_ICX_M32: #define __XSAVEOPT__ 1
+// CHECK_ICX_M32: #define __XSAVES__ 1
+// CHECK_ICX_M32: #define __XSAVE__ 1
+// CHECK_ICX_M32: #define __corei7 1
+// CHECK_ICX_M32: #define __corei7__ 1
+// CHECK_ICX_M32: #define __i386 1
+// CHECK_ICX_M32: #define __i386__ 1
+// CHECK_ICX_M32: #define __tune_corei7__ 1
+// CHECK_ICX_M32: #define i386 1
+
+// RUN: %clang -march=icelake-server -m64 -E -dM %s -o - 2>&1 \
+// RUN: -target i386-unknown-linux \
+// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_ICX_M64
+// CHECK_ICX_M64: #define __AES__ 1
+// CHECK_ICX_M64: #define __AVX2__ 1
+// CHECK_ICX_M64: #define __AVX512BITALG__ 1
+// CHECK_ICX_M64: #define __AVX512BW__ 1
+// CHECK_ICX_M64: #define __AVX512CD__ 1
+// CHECK_ICX_M64: #define __AVX512DQ__ 1
+// CHECK_ICX_M64: #define __AVX512F__ 1
+// CHECK_ICX_M64: #define __AVX512IFMA__ 1
+// CHECK_ICX_M64: #define __AVX512VBMI2__ 1
+// CHECK_ICX_M64: #define __AVX512VBMI__ 1
+// CHECK_ICX_M64: #define __AVX512VL__ 1
+// CHECK_ICX_M64: #define __AVX512VNNI__ 1
+// CHECK_ICX_M64: #define __AVX512VPOPCNTDQ__ 1
+// CHECK_ICX_M64: #define __AVX__ 1
+// CHECK_ICX_M64: #define __BMI2__ 1
+// CHECK_ICX_M64: #define __BMI__ 1
+// CHECK_ICX_M64: #define __CLFLUSHOPT__ 1
+// CHECK_ICX_M64: #define __CLWB__ 1
+// CHECK_ICX_M64: #define __F16C__ 1
+// CHECK_ICX_M64: #define __FMA__ 1
+// CHECK_ICX_M64: #define __GFNI__ 1
+// CHECK_ICX_M64: #define __INVPCID__ 1
+// CHECK_ICX_M64: #define __LZCNT__ 1
+// CHECK_ICX_M64: #define __MMX__ 1
+// CHECK_ICX_M64: #define __MPX__ 1
+// CHECK_ICX_M64: #define __PCLMUL__ 1
+// CHECK_ICX_M64: #define __PCONFIG__ 1
+// CHECK_ICX_M64: #define __PKU__ 1
+// CHECK_ICX_M64: #define __POPCNT__ 1
+// CHECK_ICX_M64: #define __PRFCHW__ 1
+// CHECK_ICX_M64: #define __RDPID__ 1
+// CHECK_ICX_M64: #define __RDRND__ 1
+// CHECK_ICX_M64: #define __RDSEED__ 1
+// CHECK_ICX_M64: #define __RTM__ 1
+// CHECK_ICX_M64: #define __SGX__ 1
+// CHECK_ICX_M64: #define __SHA__ 1
+// CHECK_ICX_M64: #define __SSE2__ 1
+// CHECK_ICX_M64: #define __SSE3__ 1
+// CHECK_ICX_M64: #define __SSE4_1__ 1
+// CHECK_ICX_M64: #define __SSE4_2__ 1
+// CHECK_ICX_M64: #define __SSE__ 1
+// CHECK_ICX_M64: #define __SSSE3__ 1
+// CHECK_ICX_M64: #define __VAES__ 1
+// CHECK_ICX_M64: #define __VPCLMULQDQ__ 1
+// CHECK_ICX_M64: #define __WBNOINVD__ 1
+// CHECK_ICX_M64: #define __XSAVEC__ 1
+// CHECK_ICX_M64: #define __XSAVEOPT__ 1
+// CHECK_ICX_M64: #define __XSAVES__ 1
+// CHECK_ICX_M64: #define __XSAVE__ 1
+// CHECK_ICX_M64: #define __amd64 1
+// CHECK_ICX_M64: #define __amd64__ 1
+// CHECK_ICX_M64: #define __corei7 1
+// CHECK_ICX_M64: #define __corei7__ 1
+// CHECK_ICX_M64: #define __tune_corei7__ 1
+// CHECK_ICX_M64: #define __x86_64 1
+// CHECK_ICX_M64: #define __x86_64__ 1
+
// RUN: %clang -march=atom -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_ATOM_M32
@@ -1174,6 +1321,7 @@
// CHECK_ATOM_M32: #define __i386__ 1
// CHECK_ATOM_M32: #define __tune_atom__ 1
// CHECK_ATOM_M32: #define i386 1
+
// RUN: %clang -march=atom -m64 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_ATOM_M64
@@ -1191,7 +1339,7 @@
// CHECK_ATOM_M64: #define __tune_atom__ 1
// CHECK_ATOM_M64: #define __x86_64 1
// CHECK_ATOM_M64: #define __x86_64__ 1
-//
+
// RUN: %clang -march=goldmont -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck %s -check-prefix=CHECK_GLM_M32
@@ -1224,7 +1372,7 @@
// CHECK_GLM_M32: #define __i386__ 1
// CHECK_GLM_M32: #define __tune_goldmont__ 1
// CHECK_GLM_M32: #define i386 1
-//
+
// RUN: %clang -march=goldmont -m64 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck %s -check-prefix=CHECK_GLM_M64
@@ -1239,6 +1387,7 @@
// CHECK_GLM_M64: #define __PRFCHW__ 1
// CHECK_GLM_M64: #define __RDRND__ 1
// CHECK_GLM_M64: #define __RDSEED__ 1
+// CHECK_GLM_M64: #define __SHA__ 1
// CHECK_GLM_M64: #define __SSE2__ 1
// CHECK_GLM_M64: #define __SSE3__ 1
// CHECK_GLM_M64: #define __SSE4_1__ 1
@@ -1254,7 +1403,157 @@
// CHECK_GLM_M64: #define __tune_goldmont__ 1
// CHECK_GLM_M64: #define __x86_64 1
// CHECK_GLM_M64: #define __x86_64__ 1
-//
+
+// RUN: %clang -march=goldmont-plus -m32 -E -dM %s -o - 2>&1 \
+// RUN: -target i386-unknown-linux \
+// RUN: | FileCheck %s -check-prefix=CHECK_GLMP_M32
+// CHECK_GLMP_M32: #define __AES__ 1
+// CHECK_GLMP_M32: #define __CLFLUSHOPT__ 1
+// CHECK_GLMP_M32: #define __FSGSBASE__ 1
+// CHECK_GLMP_M32: #define __FXSR__ 1
+// CHECK_GLMP_M32: #define __MMX__ 1
+// CHECK_GLMP_M32: #define __MPX__ 1
+// CHECK_GLMP_M32: #define __PCLMUL__ 1
+// CHECK_GLMP_M32: #define __POPCNT__ 1
+// CHECK_GLMP_M32: #define __PRFCHW__ 1
+// CHECK_GLMP_M32: #define __PTWRITE__ 1
+// CHECK_GLMP_M32: #define __RDPID__ 1
+// CHECK_GLMP_M32: #define __RDRND__ 1
+// CHECK_GLMP_M32: #define __RDSEED__ 1
+// CHECK_GLMP_M32: #define __SGX__ 1
+// CHECK_GLMP_M32: #define __SHA__ 1
+// CHECK_GLMP_M32: #define __SSE2__ 1
+// CHECK_GLMP_M32: #define __SSE3__ 1
+// CHECK_GLMP_M32: #define __SSE4_1__ 1
+// CHECK_GLMP_M32: #define __SSE4_2__ 1
+// CHECK_GLMP_M32: #define __SSE_MATH__ 1
+// CHECK_GLMP_M32: #define __SSE__ 1
+// CHECK_GLMP_M32: #define __SSSE3__ 1
+// CHECK_GLMP_M32: #define __XSAVEC__ 1
+// CHECK_GLMP_M32: #define __XSAVEOPT__ 1
+// CHECK_GLMP_M32: #define __XSAVES__ 1
+// CHECK_GLMP_M32: #define __XSAVE__ 1
+// CHECK_GLMP_M32: #define __goldmont_plus 1
+// CHECK_GLMP_M32: #define __goldmont_plus__ 1
+// CHECK_GLMP_M32: #define __i386 1
+// CHECK_GLMP_M32: #define __i386__ 1
+// CHECK_GLMP_M32: #define __tune_goldmont_plus__ 1
+// CHECK_GLMP_M32: #define i386 1
+
+// RUN: %clang -march=goldmont-plus -m64 -E -dM %s -o - 2>&1 \
+// RUN: -target i386-unknown-linux \
+// RUN: | FileCheck %s -check-prefix=CHECK_GLMP_M64
+// CHECK_GLMP_M64: #define __AES__ 1
+// CHECK_GLMP_M64: #define __CLFLUSHOPT__ 1
+// CHECK_GLMP_M64: #define __FSGSBASE__ 1
+// CHECK_GLMP_M64: #define __FXSR__ 1
+// CHECK_GLMP_M64: #define __MMX__ 1
+// CHECK_GLMP_M64: #define __MPX__ 1
+// CHECK_GLMP_M64: #define __PCLMUL__ 1
+// CHECK_GLMP_M64: #define __POPCNT__ 1
+// CHECK_GLMP_M64: #define __PRFCHW__ 1
+// CHECK_GLMP_M64: #define __PTWRITE__ 1
+// CHECK_GLMP_M64: #define __RDPID__ 1
+// CHECK_GLMP_M64: #define __RDRND__ 1
+// CHECK_GLMP_M64: #define __RDSEED__ 1
+// CHECK_GLMP_M64: #define __SGX__ 1
+// CHECK_GLMP_M64: #define __SHA__ 1
+// CHECK_GLMP_M64: #define __SSE2__ 1
+// CHECK_GLMP_M64: #define __SSE3__ 1
+// CHECK_GLMP_M64: #define __SSE4_1__ 1
+// CHECK_GLMP_M64: #define __SSE4_2__ 1
+// CHECK_GLMP_M64: #define __SSE__ 1
+// CHECK_GLMP_M64: #define __SSSE3__ 1
+// CHECK_GLMP_M64: #define __XSAVEC__ 1
+// CHECK_GLMP_M64: #define __XSAVEOPT__ 1
+// CHECK_GLMP_M64: #define __XSAVES__ 1
+// CHECK_GLMP_M64: #define __XSAVE__ 1
+// CHECK_GLMP_M64: #define __goldmont_plus 1
+// CHECK_GLMP_M64: #define __goldmont_plus__ 1
+// CHECK_GLMP_M64: #define __tune_goldmont_plus__ 1
+// CHECK_GLMP_M64: #define __x86_64 1
+// CHECK_GLMP_M64: #define __x86_64__ 1
+
+// RUN: %clang -march=tremont -m32 -E -dM %s -o - 2>&1 \
+// RUN: -target i386-unknown-linux \
+// RUN: | FileCheck %s -check-prefix=CHECK_TRM_M32
+// CHECK_TRM_M32: #define __AES__ 1
+// CHECK_TRM_M32: #define __CLDEMOTE__ 1
+// CHECK_TRM_M32: #define __CLFLUSHOPT__ 1
+// CHECK_TRM_M32: #define __FSGSBASE__ 1
+// CHECK_TRM_M32: #define __FXSR__ 1
+// CHECK_TRM_M32: #define __GFNI__ 1
+// CHECK_TRM_M32: #define __MMX__ 1
+// CHECK_TRM_M32: #define __MOVDIR64B__ 1
+// CHECK_TRM_M32: #define __MOVDIRI__ 1
+// CHECK_TRM_M32: #define __MPX__ 1
+// CHECK_TRM_M32: #define __PCLMUL__ 1
+// CHECK_TRM_M32: #define __POPCNT__ 1
+// CHECK_TRM_M32: #define __PRFCHW__ 1
+// CHECK_TRM_M32: #define __PTWRITE__ 1
+// CHECK_TRM_M32: #define __RDPID__ 1
+// CHECK_TRM_M32: #define __RDRND__ 1
+// CHECK_TRM_M32: #define __RDSEED__ 1
+// CHECK_TRM_M32: #define __SGX__ 1
+// CHECK_TRM_M32: #define __SHA__ 1
+// CHECK_TRM_M32: #define __SSE2__ 1
+// CHECK_TRM_M32: #define __SSE3__ 1
+// CHECK_TRM_M32: #define __SSE4_1__ 1
+// CHECK_TRM_M32: #define __SSE4_2__ 1
+// CHECK_TRM_M32: #define __SSE_MATH__ 1
+// CHECK_TRM_M32: #define __SSE__ 1
+// CHECK_TRM_M32: #define __SSSE3__ 1
+// CHECK_TRM_M32: #define __WAITPKG__ 1
+// CHECK_TRM_M32: #define __XSAVEC__ 1
+// CHECK_TRM_M32: #define __XSAVEOPT__ 1
+// CHECK_TRM_M32: #define __XSAVES__ 1
+// CHECK_TRM_M32: #define __XSAVE__ 1
+// CHECK_TRM_M32: #define __i386 1
+// CHECK_TRM_M32: #define __i386__ 1
+// CHECK_TRM_M32: #define __tremont 1
+// CHECK_TRM_M32: #define __tremont__ 1
+// CHECK_TRM_M32: #define __tune_tremont__ 1
+// CHECK_TRM_M32: #define i386 1
+
+// RUN: %clang -march=tremont -m64 -E -dM %s -o - 2>&1 \
+// RUN: -target i386-unknown-linux \
+// RUN: | FileCheck %s -check-prefix=CHECK_TRM_M64
+// CHECK_TRM_M64: #define __AES__ 1
+// CHECK_TRM_M64: #define __CLDEMOTE__ 1
+// CHECK_TRM_M64: #define __CLFLUSHOPT__ 1
+// CHECK_TRM_M64: #define __FSGSBASE__ 1
+// CHECK_TRM_M64: #define __FXSR__ 1
+// CHECK_TRM_M64: #define __GFNI__ 1
+// CHECK_TRM_M64: #define __MMX__ 1
+// CHECK_TRM_M64: #define __MOVDIR64B__ 1
+// CHECK_TRM_M64: #define __MOVDIRI__ 1
+// CHECK_TRM_M64: #define __MPX__ 1
+// CHECK_TRM_M64: #define __PCLMUL__ 1
+// CHECK_TRM_M64: #define __POPCNT__ 1
+// CHECK_TRM_M64: #define __PRFCHW__ 1
+// CHECK_TRM_M64: #define __PTWRITE__ 1
+// CHECK_TRM_M64: #define __RDPID__ 1
+// CHECK_TRM_M64: #define __RDRND__ 1
+// CHECK_TRM_M64: #define __RDSEED__ 1
+// CHECK_TRM_M64: #define __SGX__ 1
+// CHECK_TRM_M64: #define __SHA__ 1
+// CHECK_TRM_M64: #define __SSE2__ 1
+// CHECK_TRM_M64: #define __SSE3__ 1
+// CHECK_TRM_M64: #define __SSE4_1__ 1
+// CHECK_TRM_M64: #define __SSE4_2__ 1
+// CHECK_TRM_M64: #define __SSE__ 1
+// CHECK_TRM_M64: #define __SSSE3__ 1
+// CHECK_TRM_M64: #define __WAITPKG__ 1
+// CHECK_TRM_M64: #define __XSAVEC__ 1
+// CHECK_TRM_M64: #define __XSAVEOPT__ 1
+// CHECK_TRM_M64: #define __XSAVES__ 1
+// CHECK_TRM_M64: #define __XSAVE__ 1
+// CHECK_TRM_M64: #define __tremont 1
+// CHECK_TRM_M64: #define __tremont__ 1
+// CHECK_TRM_M64: #define __tune_tremont__ 1
+// CHECK_TRM_M64: #define __x86_64 1
+// CHECK_TRM_M64: #define __x86_64__ 1
+
// RUN: %clang -march=slm -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SLM_M32
@@ -1264,6 +1563,7 @@
// CHECK_SLM_M32: #define __PCLMUL__ 1
// CHECK_SLM_M32: #define __POPCNT__ 1
// CHECK_SLM_M32: #define __PRFCHW__ 1
+// CHECK_SLM_M32: #define __RDRND__ 1
// CHECK_SLM_M32: #define __SSE2__ 1
// CHECK_SLM_M32: #define __SSE3__ 1
// CHECK_SLM_M32: #define __SSE4_1__ 1
@@ -1276,6 +1576,7 @@
// CHECK_SLM_M32: #define __slm__ 1
// CHECK_SLM_M32: #define __tune_slm__ 1
// CHECK_SLM_M32: #define i386 1
+
// RUN: %clang -march=slm -m64 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SLM_M64
@@ -1285,6 +1586,7 @@
// CHECK_SLM_M64: #define __PCLMUL__ 1
// CHECK_SLM_M64: #define __POPCNT__ 1
// CHECK_SLM_M64: #define __PRFCHW__ 1
+// CHECK_SLM_M64: #define __RDRND__ 1
// CHECK_SLM_M64: #define __SSE2_MATH__ 1
// CHECK_SLM_M64: #define __SSE2__ 1
// CHECK_SLM_M64: #define __SSE3__ 1
@@ -1300,7 +1602,7 @@
// CHECK_SLM_M64: #define __tune_slm__ 1
// CHECK_SLM_M64: #define __x86_64 1
// CHECK_SLM_M64: #define __x86_64__ 1
-//
+
// RUN: %clang -march=lakemont -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck %s -check-prefix=CHECK_LAKEMONT_M32
@@ -1316,7 +1618,7 @@
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck %s -check-prefix=CHECK_LAKEMONT_M64
// CHECK_LAKEMONT_M64: error:
-//
+
// RUN: %clang -march=geode -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_GEODE_M32
@@ -1333,7 +1635,7 @@
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_GEODE_M64
// CHECK_GEODE_M64: error: {{.*}}
-//
+
// RUN: %clang -march=k6 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_K6_M32
@@ -1348,7 +1650,7 @@
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_K6_M64
// CHECK_K6_M64: error: {{.*}}
-//
+
// RUN: %clang -march=k6-2 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_K6_2_M32
@@ -1366,7 +1668,7 @@
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_K6_2_M64
// CHECK_K6_2_M64: error: {{.*}}
-//
+
// RUN: %clang -march=k6-3 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_K6_3_M32
@@ -1384,7 +1686,7 @@
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_K6_3_M64
// CHECK_K6_3_M64: error: {{.*}}
-//
+
// RUN: %clang -march=athlon -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_ATHLON_M32
@@ -1401,7 +1703,7 @@
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_ATHLON_M64
// CHECK_ATHLON_M64: error: {{.*}}
-//
+
// RUN: %clang -march=athlon-tbird -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_ATHLON_TBIRD_M32
@@ -1418,7 +1720,7 @@
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_ATHLON_TBIRD_M64
// CHECK_ATHLON_TBIRD_M64: error: {{.*}}
-//
+
// RUN: %clang -march=athlon-4 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_ATHLON_4_M32
@@ -1438,7 +1740,7 @@
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_ATHLON_4_M64
// CHECK_ATHLON_4_M64: error: {{.*}}
-//
+
// RUN: %clang -march=athlon-xp -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_ATHLON_XP_M32
@@ -1458,7 +1760,7 @@
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_ATHLON_XP_M64
// CHECK_ATHLON_XP_M64: error: {{.*}}
-//
+
// RUN: %clang -march=athlon-mp -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_ATHLON_MP_M32
@@ -1478,7 +1780,7 @@
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_ATHLON_MP_M64
// CHECK_ATHLON_MP_M64: error: {{.*}}
-//
+
// RUN: %clang -march=x86-64 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_X86_64_M32
@@ -1490,6 +1792,7 @@
// CHECK_X86_64_M32: #define __k8 1
// CHECK_X86_64_M32: #define __k8__ 1
// CHECK_X86_64_M32: #define i386 1
+
// RUN: %clang -march=x86-64 -m64 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_X86_64_M64
@@ -1504,7 +1807,7 @@
// CHECK_X86_64_M64: #define __k8__ 1
// CHECK_X86_64_M64: #define __x86_64 1
// CHECK_X86_64_M64: #define __x86_64__ 1
-//
+
// RUN: %clang -march=k8 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_K8_M32
@@ -1519,6 +1822,7 @@
// CHECK_K8_M32: #define __k8__ 1
// CHECK_K8_M32: #define __tune_k8__ 1
// CHECK_K8_M32: #define i386 1
+
// RUN: %clang -march=k8 -m64 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_K8_M64
@@ -1536,7 +1840,7 @@
// CHECK_K8_M64: #define __tune_k8__ 1
// CHECK_K8_M64: #define __x86_64 1
// CHECK_K8_M64: #define __x86_64__ 1
-//
+
// RUN: %clang -march=k8-sse3 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_K8_SSE3_M32
@@ -1552,6 +1856,7 @@
// CHECK_K8_SSE3_M32: #define __k8__ 1
// CHECK_K8_SSE3_M32: #define __tune_k8__ 1
// CHECK_K8_SSE3_M32: #define i386 1
+
// RUN: %clang -march=k8-sse3 -m64 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_K8_SSE3_M64
@@ -1570,7 +1875,7 @@
// CHECK_K8_SSE3_M64: #define __tune_k8__ 1
// CHECK_K8_SSE3_M64: #define __x86_64 1
// CHECK_K8_SSE3_M64: #define __x86_64__ 1
-//
+
// RUN: %clang -march=opteron -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_OPTERON_M32
@@ -1585,6 +1890,7 @@
// CHECK_OPTERON_M32: #define __k8__ 1
// CHECK_OPTERON_M32: #define __tune_k8__ 1
// CHECK_OPTERON_M32: #define i386 1
+
// RUN: %clang -march=opteron -m64 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_OPTERON_M64
@@ -1602,7 +1908,7 @@
// CHECK_OPTERON_M64: #define __tune_k8__ 1
// CHECK_OPTERON_M64: #define __x86_64 1
// CHECK_OPTERON_M64: #define __x86_64__ 1
-//
+
// RUN: %clang -march=opteron-sse3 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_OPTERON_SSE3_M32
@@ -1618,6 +1924,7 @@
// CHECK_OPTERON_SSE3_M32: #define __k8__ 1
// CHECK_OPTERON_SSE3_M32: #define __tune_k8__ 1
// CHECK_OPTERON_SSE3_M32: #define i386 1
+
// RUN: %clang -march=opteron-sse3 -m64 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_OPTERON_SSE3_M64
@@ -1636,7 +1943,7 @@
// CHECK_OPTERON_SSE3_M64: #define __tune_k8__ 1
// CHECK_OPTERON_SSE3_M64: #define __x86_64 1
// CHECK_OPTERON_SSE3_M64: #define __x86_64__ 1
-//
+
// RUN: %clang -march=athlon64 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_ATHLON64_M32
@@ -1651,6 +1958,7 @@
// CHECK_ATHLON64_M32: #define __k8__ 1
// CHECK_ATHLON64_M32: #define __tune_k8__ 1
// CHECK_ATHLON64_M32: #define i386 1
+
// RUN: %clang -march=athlon64 -m64 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_ATHLON64_M64
@@ -1668,7 +1976,7 @@
// CHECK_ATHLON64_M64: #define __tune_k8__ 1
// CHECK_ATHLON64_M64: #define __x86_64 1
// CHECK_ATHLON64_M64: #define __x86_64__ 1
-//
+
// RUN: %clang -march=athlon64-sse3 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_ATHLON64_SSE3_M32
@@ -1684,6 +1992,7 @@
// CHECK_ATHLON64_SSE3_M32: #define __k8__ 1
// CHECK_ATHLON64_SSE3_M32: #define __tune_k8__ 1
// CHECK_ATHLON64_SSE3_M32: #define i386 1
+
// RUN: %clang -march=athlon64-sse3 -m64 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_ATHLON64_SSE3_M64
@@ -1702,7 +2011,7 @@
// CHECK_ATHLON64_SSE3_M64: #define __tune_k8__ 1
// CHECK_ATHLON64_SSE3_M64: #define __x86_64 1
// CHECK_ATHLON64_SSE3_M64: #define __x86_64__ 1
-//
+
// RUN: %clang -march=athlon-fx -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_ATHLON_FX_M32
@@ -1717,6 +2026,7 @@
// CHECK_ATHLON_FX_M32: #define __k8__ 1
// CHECK_ATHLON_FX_M32: #define __tune_k8__ 1
// CHECK_ATHLON_FX_M32: #define i386 1
+
// RUN: %clang -march=athlon-fx -m64 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_ATHLON_FX_M64
@@ -1734,6 +2044,7 @@
// CHECK_ATHLON_FX_M64: #define __tune_k8__ 1
// CHECK_ATHLON_FX_M64: #define __x86_64 1
// CHECK_ATHLON_FX_M64: #define __x86_64__ 1
+
// RUN: %clang -march=amdfam10 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_AMDFAM10_M32
@@ -1753,6 +2064,7 @@
// CHECK_AMDFAM10_M32: #define __i386 1
// CHECK_AMDFAM10_M32: #define __i386__ 1
// CHECK_AMDFAM10_M32: #define __tune_amdfam10__ 1
+
// RUN: %clang -march=amdfam10 -m64 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_AMDFAM10_M64
@@ -1774,6 +2086,7 @@
// CHECK_AMDFAM10_M64: #define __tune_amdfam10__ 1
// CHECK_AMDFAM10_M64: #define __x86_64 1
// CHECK_AMDFAM10_M64: #define __x86_64__ 1
+
// RUN: %clang -march=btver1 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_BTVER1_M32
@@ -1795,6 +2108,7 @@
// CHECK_BTVER1_M32: #define __i386 1
// CHECK_BTVER1_M32: #define __i386__ 1
// CHECK_BTVER1_M32: #define __tune_btver1__ 1
+
// RUN: %clang -march=btver1 -m64 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_BTVER1_M64
@@ -1818,6 +2132,7 @@
// CHECK_BTVER1_M64: #define __tune_btver1__ 1
// CHECK_BTVER1_M64: #define __x86_64 1
// CHECK_BTVER1_M64: #define __x86_64__ 1
+
// RUN: %clang -march=btver2 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_BTVER2_M32
@@ -1846,6 +2161,7 @@
// CHECK_BTVER2_M32: #define __i386 1
// CHECK_BTVER2_M32: #define __i386__ 1
// CHECK_BTVER2_M32: #define __tune_btver2__ 1
+
// RUN: %clang -march=btver2 -m64 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_BTVER2_M64
@@ -1876,6 +2192,7 @@
// CHECK_BTVER2_M64: #define __tune_btver2__ 1
// CHECK_BTVER2_M64: #define __x86_64 1
// CHECK_BTVER2_M64: #define __x86_64__ 1
+
// RUN: %clang -march=bdver1 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_BDVER1_M32
@@ -1906,6 +2223,7 @@
// CHECK_BDVER1_M32: #define __i386 1
// CHECK_BDVER1_M32: #define __i386__ 1
// CHECK_BDVER1_M32: #define __tune_bdver1__ 1
+
// RUN: %clang -march=bdver1 -m64 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_BDVER1_M64
@@ -1938,6 +2256,7 @@
// CHECK_BDVER1_M64: #define __tune_bdver1__ 1
// CHECK_BDVER1_M64: #define __x86_64 1
// CHECK_BDVER1_M64: #define __x86_64__ 1
+
// RUN: %clang -march=bdver2 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_BDVER2_M32
@@ -1972,6 +2291,7 @@
// CHECK_BDVER2_M32: #define __i386 1
// CHECK_BDVER2_M32: #define __i386__ 1
// CHECK_BDVER2_M32: #define __tune_bdver2__ 1
+
// RUN: %clang -march=bdver2 -m64 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_BDVER2_M64
@@ -2008,6 +2328,7 @@
// CHECK_BDVER2_M64: #define __tune_bdver2__ 1
// CHECK_BDVER2_M64: #define __x86_64 1
// CHECK_BDVER2_M64: #define __x86_64__ 1
+
// RUN: %clang -march=bdver3 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_BDVER3_M32
@@ -2044,6 +2365,7 @@
// CHECK_BDVER3_M32: #define __i386 1
// CHECK_BDVER3_M32: #define __i386__ 1
// CHECK_BDVER3_M32: #define __tune_bdver3__ 1
+
// RUN: %clang -march=bdver3 -m64 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_BDVER3_M64
@@ -2082,6 +2404,7 @@
// CHECK_BDVER3_M64: #define __tune_bdver3__ 1
// CHECK_BDVER3_M64: #define __x86_64 1
// CHECK_BDVER3_M64: #define __x86_64__ 1
+
// RUN: %clang -march=bdver4 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_BDVER4_M32
@@ -2119,6 +2442,7 @@
// CHECK_BDVER4_M32: #define __i386 1
// CHECK_BDVER4_M32: #define __i386__ 1
// CHECK_BDVER4_M32: #define __tune_bdver4__ 1
+
// RUN: %clang -march=bdver4 -m64 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_BDVER4_M64
@@ -2158,6 +2482,7 @@
// CHECK_BDVER4_M64: #define __tune_bdver4__ 1
// CHECK_BDVER4_M64: #define __x86_64 1
// CHECK_BDVER4_M64: #define __x86_64__ 1
+
// RUN: %clang -march=znver1 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_ZNVER1_M32
@@ -2200,6 +2525,7 @@
// CHECK_ZNVER1_M32: #define __tune_znver1__ 1
// CHECK_ZNVER1_M32: #define __znver1 1
// CHECK_ZNVER1_M32: #define __znver1__ 1
+
// RUN: %clang -march=znver1 -m64 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_ZNVER1_M64
@@ -2244,7 +2570,7 @@
// CHECK_ZNVER1_M64: #define __x86_64__ 1
// CHECK_ZNVER1_M64: #define __znver1 1
// CHECK_ZNVER1_M64: #define __znver1__ 1
-//
+
// End X86/GCC/Linux tests ------------------
// Begin PPC/GCC/Linux tests ----------------
@@ -2252,32 +2578,27 @@
// RUN: %clang -mvsx -E -dM %s -o - 2>&1 \
// RUN: -target powerpc-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_PPC_VSX_M32
-//
// CHECK_PPC_VSX_M32: #define __ALTIVEC__ 1
// CHECK_PPC_VSX_M32: #define __VSX__ 1
-//
+
// RUN: %clang -mvsx -E -dM %s -o - 2>&1 \
// RUN: -target powerpc64-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_PPC_VSX_M64
-//
// CHECK_PPC_VSX_M64: #define __VSX__ 1
-//
+
// RUN: %clang -mpower8-vector -E -dM %s -o - 2>&1 \
// RUN: -target powerpc64-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_PPC_POWER8_VECTOR_M64
-//
// CHECK_PPC_POWER8_VECTOR_M64: #define __POWER8_VECTOR__ 1
-//
+
// RUN: %clang -mpower9-vector -E -dM %s -o - 2>&1 \
// RUN: -target powerpc64-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_PPC_POWER9_VECTOR_M64
-//
// CHECK_PPC_POWER9_VECTOR_M64: #define __POWER9_VECTOR__ 1
-//
+
// RUN: %clang -mcrypto -E -dM %s -o - 2>&1 \
// RUN: -target powerpc64-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_PPC_CRYPTO_M64
-//
// CHECK_PPC_CRYPTO_M64: #define __CRYPTO__ 1
// HTM is available on power8 or later which includes all of powerpc64le as an
@@ -2294,10 +2615,8 @@
// RUN: %clang -mcpu=pwr9 -E -dM %s -o - 2>&1 \
// RUN: -target powerpc64-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_PPC_HTM
-//
// CHECK_PPC_HTM: #define __HTM__ 1
-//
// RUN: %clang -mcpu=ppc64 -E -dM %s -o - 2>&1 \
// RUN: -target powerpc64-unknown-unknown \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_PPC_GCC_ATOMICS
@@ -2307,23 +2626,18 @@
// RUN: %clang -E -dM %s -o - 2>&1 \
// RUN: -target powerpc64le-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_PPC_GCC_ATOMICS
-//
// CHECK_PPC_GCC_ATOMICS: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
// CHECK_PPC_GCC_ATOMICS: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
// CHECK_PPC_GCC_ATOMICS: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1
// CHECK_PPC_GCC_ATOMICS: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1
-//
+
// End PPC/GCC/Linux tests ------------------
// Begin Sparc/GCC/Linux tests ----------------
-//
+
// RUN: %clang -E -dM %s -o - 2>&1 \
// RUN: -target sparc-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SPARC
-// RUN: %clang -mcpu=v9 -E -dM %s -o - 2>&1 \
-// RUN: -target sparc-unknown-linux \
-// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SPARC-V9
-//
// CHECK_SPARC: #define __BIG_ENDIAN__ 1
// CHECK_SPARC: #define __sparc 1
// CHECK_SPARC: #define __sparc__ 1
@@ -2333,12 +2647,14 @@
// CHECK_SPARC-NOT: #define __sparcv9 1
// CHECK_SPARC-NOT: #define __sparcv9__ 1
+// RUN: %clang -mcpu=v9 -E -dM %s -o - 2>&1 \
+// RUN: -target sparc-unknown-linux \
+// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SPARC-V9
// CHECK_SPARC-V9-NOT: #define __sparcv8 1
// CHECK_SPARC-V9: #define __sparc_v9__ 1
// CHECK_SPARC-V9: #define __sparcv9 1
// CHECK_SPARC-V9-NOT: #define __sparcv8 1
-//
// RUN: %clang -E -dM %s -o - 2>&1 \
// RUN: -target sparcel-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SPARCEL
@@ -2391,19 +2707,22 @@
// CHECK_MYRIAD2: #define __leon__ 1
// CHECK_MYRIAD2-1: #define __myriad2 1
// CHECK_MYRIAD2-1: #define __myriad2__ 1
+// CHECK_MYRIAD2-2: #define __ma2x5x 1
+// CHECK_MYRIAD2-2: #define __ma2x5x__ 1
// CHECK_MYRIAD2-2: #define __myriad2 2
// CHECK_MYRIAD2-2: #define __myriad2__ 2
+// CHECK_MYRIAD2-3: #define __ma2x8x 1
+// CHECK_MYRIAD2-3: #define __ma2x8x__ 1
// CHECK_MYRIAD2-3: #define __myriad2 3
// CHECK_MYRIAD2-3: #define __myriad2__ 3
// CHECK_SPARCEL: #define __sparc 1
// CHECK_SPARCEL: #define __sparc__ 1
// CHECK_MYRIAD2: #define __sparc_v8__ 1
// CHECK_SPARCEL: #define __sparcv8 1
-//
+
// RUN: %clang -E -dM %s -o - 2>&1 \
// RUN: -target sparcv9-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SPARCV9
-//
// CHECK_SPARCV9: #define __BIG_ENDIAN__ 1
// CHECK_SPARCV9: #define __sparc 1
// CHECK_SPARCV9: #define __sparc64__ 1
@@ -2413,14 +2732,13 @@
// CHECK_SPARCV9: #define __sparcv9__ 1
// Begin SystemZ/GCC/Linux tests ----------------
-//
+
// RUN: %clang -march=arch8 -E -dM %s -o - 2>&1 \
// RUN: -target s390x-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SYSTEMZ_ARCH8
// RUN: %clang -march=z10 -E -dM %s -o - 2>&1 \
// RUN: -target s390x-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SYSTEMZ_ARCH8
-//
// CHECK_SYSTEMZ_ARCH8: #define __ARCH__ 8
// CHECK_SYSTEMZ_ARCH8: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
// CHECK_SYSTEMZ_ARCH8: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
@@ -2430,14 +2748,13 @@
// CHECK_SYSTEMZ_ARCH8: #define __s390__ 1
// CHECK_SYSTEMZ_ARCH8: #define __s390x__ 1
// CHECK_SYSTEMZ_ARCH8: #define __zarch__ 1
-//
+
// RUN: %clang -march=arch9 -E -dM %s -o - 2>&1 \
// RUN: -target s390x-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SYSTEMZ_ARCH9
// RUN: %clang -march=z196 -E -dM %s -o - 2>&1 \
// RUN: -target s390x-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SYSTEMZ_ARCH9
-//
// CHECK_SYSTEMZ_ARCH9: #define __ARCH__ 9
// CHECK_SYSTEMZ_ARCH9: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
// CHECK_SYSTEMZ_ARCH9: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
@@ -2447,14 +2764,13 @@
// CHECK_SYSTEMZ_ARCH9: #define __s390__ 1
// CHECK_SYSTEMZ_ARCH9: #define __s390x__ 1
// CHECK_SYSTEMZ_ARCH9: #define __zarch__ 1
-//
+
// RUN: %clang -march=arch10 -E -dM %s -o - 2>&1 \
// RUN: -target s390x-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SYSTEMZ_ARCH10
// RUN: %clang -march=zEC12 -E -dM %s -o - 2>&1 \
// RUN: -target s390x-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SYSTEMZ_ARCH10
-//
// CHECK_SYSTEMZ_ARCH10: #define __ARCH__ 10
// CHECK_SYSTEMZ_ARCH10: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
// CHECK_SYSTEMZ_ARCH10: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
@@ -2465,14 +2781,13 @@
// CHECK_SYSTEMZ_ARCH10: #define __s390__ 1
// CHECK_SYSTEMZ_ARCH10: #define __s390x__ 1
// CHECK_SYSTEMZ_ARCH10: #define __zarch__ 1
-//
+
// RUN: %clang -march=arch11 -E -dM %s -o - 2>&1 \
// RUN: -target s390x-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SYSTEMZ_ARCH11
// RUN: %clang -march=z13 -E -dM %s -o - 2>&1 \
// RUN: -target s390x-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SYSTEMZ_ARCH11
-//
// CHECK_SYSTEMZ_ARCH11: #define __ARCH__ 11
// CHECK_SYSTEMZ_ARCH11: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
// CHECK_SYSTEMZ_ARCH11: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
@@ -2484,14 +2799,13 @@
// CHECK_SYSTEMZ_ARCH11: #define __s390__ 1
// CHECK_SYSTEMZ_ARCH11: #define __s390x__ 1
// CHECK_SYSTEMZ_ARCH11: #define __zarch__ 1
-//
+
// RUN: %clang -march=arch12 -E -dM %s -o - 2>&1 \
// RUN: -target s390x-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SYSTEMZ_ARCH12
// RUN: %clang -march=z14 -E -dM %s -o - 2>&1 \
// RUN: -target s390x-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SYSTEMZ_ARCH12
-//
// CHECK_SYSTEMZ_ARCH12: #define __ARCH__ 12
// CHECK_SYSTEMZ_ARCH12: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
// CHECK_SYSTEMZ_ARCH12: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
@@ -2503,30 +2817,27 @@
// CHECK_SYSTEMZ_ARCH12: #define __s390__ 1
// CHECK_SYSTEMZ_ARCH12: #define __s390x__ 1
// CHECK_SYSTEMZ_ARCH12: #define __zarch__ 1
-//
+
// RUN: %clang -mhtm -E -dM %s -o - 2>&1 \
// RUN: -target s390x-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SYSTEMZ_HTM
-//
// CHECK_SYSTEMZ_HTM: #define __HTM__ 1
-//
+
// RUN: %clang -mvx -E -dM %s -o - 2>&1 \
// RUN: -target s390x-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SYSTEMZ_VX
-//
// CHECK_SYSTEMZ_VX: #define __VX__ 1
-//
+
// RUN: %clang -fzvector -E -dM %s -o - 2>&1 \
// RUN: -target s390x-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SYSTEMZ_ZVECTOR
// RUN: %clang -mzvector -E -dM %s -o - 2>&1 \
// RUN: -target s390x-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SYSTEMZ_ZVECTOR
-//
// CHECK_SYSTEMZ_ZVECTOR: #define __VEC__ 10302
// Begin amdgcn tests ----------------
-//
+
// RUN: %clang -march=amdgcn -E -dM %s -o - 2>&1 \
// RUN: -target amdgcn-unknown-unknown \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_AMDGCN
@@ -2536,7 +2847,7 @@
// CHECK_AMDGCN: #define __HAS_LDEXPF__ 1
// Begin r600 tests ----------------
-//
+
// RUN: %clang -march=amdgcn -E -dM %s -o - 2>&1 \
// RUN: -target r600-unknown-unknown \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_R600
diff --git a/test/Preprocessor/predefined-macros.c b/test/Preprocessor/predefined-macros.c
index def1ef90f55d..9296b1cf5a50 100644
--- a/test/Preprocessor/predefined-macros.c
+++ b/test/Preprocessor/predefined-macros.c
@@ -1,33 +1,5 @@
// This test verifies that the correct macros are predefined.
//
-// RUN: %clang_cc1 %s -x c++ -E -dM -triple i686-pc-win32 -fms-extensions -fms-compatibility \
-// RUN: -fms-compatibility-version=19.00 -std=c++1z -o - | FileCheck -match-full-lines %s --check-prefix=CHECK-MS
-// CHECK-MS: #define _INTEGRAL_MAX_BITS 64
-// CHECK-MS: #define _MSC_EXTENSIONS 1
-// CHECK-MS: #define _MSC_VER 1900
-// CHECK-MS: #define _MSVC_LANG 201403L
-// CHECK-MS: #define _M_IX86 600
-// CHECK-MS: #define _M_IX86_FP 0
-// CHECK-MS: #define _WIN32 1
-// CHECK-MS-NOT: #define __STRICT_ANSI__
-// CHECK-MS-NOT: GCC
-// CHECK-MS-NOT: GNU
-// CHECK-MS-NOT: GXX
-//
-// RUN: %clang_cc1 %s -x c++ -E -dM -triple x86_64-pc-win32 -fms-extensions -fms-compatibility \
-// RUN: -fms-compatibility-version=19.00 -std=c++14 -o - | FileCheck -match-full-lines %s --check-prefix=CHECK-MS64
-// CHECK-MS64: #define _INTEGRAL_MAX_BITS 64
-// CHECK-MS64: #define _MSC_EXTENSIONS 1
-// CHECK-MS64: #define _MSC_VER 1900
-// CHECK-MS64: #define _MSVC_LANG 201402L
-// CHECK-MS64: #define _M_AMD64 100
-// CHECK-MS64: #define _M_X64 100
-// CHECK-MS64: #define _WIN64 1
-// CHECK-MS64-NOT: #define __STRICT_ANSI__
-// CHECK-MS64-NOT: GCC
-// CHECK-MS64-NOT: GNU
-// CHECK-MS64-NOT: GXX
-//
// RUN: %clang_cc1 %s -E -dM -triple i686-pc-win32 -fms-compatibility \
// RUN: -o - | FileCheck -match-full-lines %s --check-prefix=CHECK-MS-STDINT
// CHECK-MS-STDINT:#define __INT16_MAX__ 32767
@@ -159,6 +131,8 @@
// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-CL20
// RUN: %clang_cc1 %s -E -dM -o - -x cl -cl-fast-relaxed-math \
// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-FRM
+// RUN: %clang_cc1 %s -E -dM -o - -x cl -cl-std=c++ \
+// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-CLCPP10
// CHECK-CL10: #define CL_VERSION_1_0 100
// CHECK-CL10: #define CL_VERSION_1_1 110
// CHECK-CL10: #define CL_VERSION_1_2 120
@@ -184,6 +158,10 @@
// CHECK-CL20: #define __OPENCL_C_VERSION__ 200
// CHECK-CL20-NOT: #define __FAST_RELAXED_MATH__ 1
// CHECK-FRM: #define __FAST_RELAXED_MATH__ 1
+// CHECK-CLCPP10: #define __CL_CPP_VERSION_1_0__ 100
+// CHECK-CLCPP10: #define __OPENCL_CPP_VERSION__ 100
+// CHECK-CLCPP10-NOT: #define __FAST_RELAXED_MATH__ 1
+// CHECK-CLCPP10-NOT: #define __ENDIAN_LITTLE__ 1
// RUN: %clang_cc1 %s -E -dM -o - -x cl \
// RUN: | FileCheck %s --check-prefix=MSCOPE
@@ -193,81 +171,21 @@
// MSCOPE:#define __OPENCL_MEMORY_SCOPE_WORK_GROUP 1
// MSCOPE:#define __OPENCL_MEMORY_SCOPE_WORK_ITEM 0
-// RUN: %clang_cc1 -triple i386-windows %s -E -dM -o - \
-// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-X86-WIN
-
-// CHECK-X86-WIN-NOT: #define WIN32 1
-// CHECK-X86-WIN-NOT: #define WIN64 1
-// CHECK-X86-WIN-NOT: #define WINNT 1
-// CHECK-X86-WIN: #define _WIN32 1
-// CHECK-X86-WIN-NOT: #define _WIN64 1
-
-// RUN: %clang_cc1 -triple thumbv7-windows %s -E -dM -o - \
-// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-ARM-WIN
-
-// CHECK-ARM-WIN-NOT: #define WIN32 1
-// CHECK-ARM-WIN-NOT: #define WIN64 1
-// CHECK-ARM-WIN-NOT: #define WINNT 1
-// CHECK-ARM-WIN: #define _WIN32 1
-// CHECK-ARM-WIN-NOT: #define _WIN64 1
-
-// RUN: %clang_cc1 -triple x86_64-windows %s -E -dM -o - \
-// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-AMD64-WIN
-
-// CHECK-AMD64-WIN-NOT: #define WIN32 1
-// CHECK-AMD64-WIN-NOT: #define WIN64 1
-// CHECK-AMD64-WIN-NOT: #define WINNT 1
-// CHECK-AMD64-WIN: #define _WIN32 1
-// CHECK-AMD64-WIN: #define _WIN64 1
-
-// RUN: %clang_cc1 -triple aarch64-windows %s -E -dM -o - \
-// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-ARM64-WIN
-
-// CHECK-ARM64-WIN-NOT: #define WIN32 1
-// CHECK-ARM64-WIN-NOT: #define WIN64 1
-// CHECK-ARM64-WIN-NOT: #define WINNT 1
-// CHECK-ARM64-WIN: #define _M_ARM64 1
-// CHECK-ARM64-WIN: #define _WIN32 1
-// CHECK-ARM64-WIN: #define _WIN64 1
-
-// RUN: %clang_cc1 -triple i686-windows-gnu %s -E -dM -o - \
-// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-X86-MINGW
-
-// CHECK-X86-MINGW: #define WIN32 1
-// CHECK-X86-MINGW-NOT: #define WIN64 1
-// CHECK-X86-MINGW: #define WINNT 1
-// CHECK-X86-MINGW: #define _WIN32 1
-// CHECK-X86-MINGW-NOT: #define _WIN64 1
-
-// RUN: %clang_cc1 -triple thumbv7-windows-gnu %s -E -dM -o - \
-// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-ARM-MINGW
-
-// CHECK-ARM-MINGW: #define WIN32 1
-// CHECK-ARM-MINGW-NOT: #define WIN64 1
-// CHECK-ARM-MINGW: #define WINNT 1
-// CHECK-ARM-MINGW: #define _WIN32 1
-// CHECK-ARM-MINGW-NOT: #define _WIN64 1
-
-// RUN: %clang_cc1 -triple x86_64-windows-gnu %s -E -dM -o - \
-// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-AMD64-MINGW
-
-// CHECK-AMD64-MINGW: #define WIN32 1
-// CHECK-AMD64-MINGW: #define WIN64 1
-// CHECK-AMD64-MINGW: #define WINNT 1
-// CHECK-AMD64-MINGW: #define _WIN32 1
-// CHECK-AMD64-MINGW: #define _WIN64 1
-
-// RUN: %clang_cc1 -triple aarch64-windows-gnu %s -E -dM -o - \
-// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-ARM64-MINGW
-
-// CHECK-ARM64-MINGW-NOT: #define _M_ARM64 1
-// CHECK-ARM64-MINGW: #define WIN32 1
-// CHECK-ARM64-MINGW: #define WIN64 1
-// CHECK-ARM64-MINGW: #define WINNT 1
-// CHECK-ARM64-MINGW: #define _WIN32 1
-// CHECK-ARM64-MINGW: #define _WIN64 1
-// CHECK-ARM64-MINGW: #define __aarch64__ 1
-
// RUN: %clang_cc1 %s -E -dM -o - -x cl -triple spir-unknown-unknown \
// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-SPIR
// CHECK-SPIR: #define __IMAGE_SUPPORT__ 1
+
+// RUN: %clang_cc1 %s -E -dM -o - -x hip -triple amdgcn-amd-amdhsa \
+// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-HIP
+// CHECK-HIP-NOT: #define __CUDA_ARCH__
+// CHECK-HIP: #define __HIPCC__ 1
+// CHECK-HIP-NOT: #define __HIP_DEVICE_COMPILE__ 1
+// CHECK-HIP: #define __HIP__ 1
+
+// RUN: %clang_cc1 %s -E -dM -o - -x hip -triple amdgcn-amd-amdhsa \
+// RUN: -fcuda-is-device \
+// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-HIP-DEV
+// CHECK-HIP-DEV-NOT: #define __CUDA_ARCH__
+// CHECK-HIP-DEV: #define __HIPCC__ 1
+// CHECK-HIP-DEV: #define __HIP_DEVICE_COMPILE__ 1
+// CHECK-HIP-DEV: #define __HIP__ 1
diff --git a/test/Preprocessor/predefined-win-macros.c b/test/Preprocessor/predefined-win-macros.c
new file mode 100644
index 000000000000..0979e34860cf
--- /dev/null
+++ b/test/Preprocessor/predefined-win-macros.c
@@ -0,0 +1,110 @@
+// This test verifies that the correct macros are predefined.
+//
+// RUN: %clang_cc1 %s -x c++ -E -dM -triple x86_64-pc-win32 -fms-extensions -fms-compatibility \
+// RUN: -fms-compatibility-version=19.00 -std=c++14 -o - | FileCheck -match-full-lines %s --check-prefix=CHECK-MS64
+// CHECK-MS64: #define _INTEGRAL_MAX_BITS 64
+// CHECK-MS64: #define _MSC_EXTENSIONS 1
+// CHECK-MS64: #define _MSC_VER 1900
+// CHECK-MS64: #define _MSVC_LANG 201402L
+// CHECK-MS64: #define _M_AMD64 100
+// CHECK-MS64: #define _M_X64 100
+// CHECK-MS64: #define _WIN64 1
+// CHECK-MS64-NOT: #define __STRICT_ANSI__
+// CHECK-MS64-NOT: GCC
+// CHECK-MS64-NOT: GNU
+// CHECK-MS64-NOT: GXX
+
+// RUN: %clang_cc1 %s -x c++ -E -dM -triple i686-pc-win32 -fms-extensions -fms-compatibility \
+// RUN: -fms-compatibility-version=19.00 -std=c++17 -o - | FileCheck -match-full-lines %s --check-prefix=CHECK-MS
+// CHECK-MS: #define _INTEGRAL_MAX_BITS 64
+// CHECK-MS: #define _MSC_EXTENSIONS 1
+// CHECK-MS: #define _MSC_VER 1900
+// CHECK-MS: #define _MSVC_LANG 201703L
+// CHECK-MS: #define _M_IX86 600
+// CHECK-MS: #define _M_IX86_FP 0
+// CHECK-MS: #define _WIN32 1
+// CHECK-MS-NOT: #define __STRICT_ANSI__
+// CHECK-MS-NOT: GCC
+// CHECK-MS-NOT: GNU
+// CHECK-MS-NOT: GXX
+
+// RUN: %clang_cc1 %s -x c++ -E -dM -triple i686-pc-win32 -fms-extensions -fms-compatibility \
+// RUN: -fms-compatibility-version=19.00 -std=c++2a -o - | FileCheck -match-full-lines %s --check-prefix=CHECK-MS-CPP2A
+// CHECK-MS-CPP2A: #define _MSC_VER 1900
+// CHECK-MS-CPP2A: #define _MSVC_LANG 201704L
+
+// RUN: %clang_cc1 -triple i386-windows %s -E -dM -o - \
+// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-X86-WIN
+
+// CHECK-X86-WIN-NOT: #define WIN32 1
+// CHECK-X86-WIN-NOT: #define WIN64 1
+// CHECK-X86-WIN-NOT: #define WINNT 1
+// CHECK-X86-WIN: #define _WIN32 1
+// CHECK-X86-WIN-NOT: #define _WIN64 1
+
+// RUN: %clang_cc1 -triple thumbv7-windows %s -E -dM -o - \
+// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-ARM-WIN
+
+// CHECK-ARM-WIN-NOT: #define WIN32 1
+// CHECK-ARM-WIN-NOT: #define WIN64 1
+// CHECK-ARM-WIN-NOT: #define WINNT 1
+// CHECK-ARM-WIN: #define _WIN32 1
+// CHECK-ARM-WIN-NOT: #define _WIN64 1
+
+// RUN: %clang_cc1 -triple x86_64-windows %s -E -dM -o - \
+// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-AMD64-WIN
+
+// CHECK-AMD64-WIN-NOT: #define WIN32 1
+// CHECK-AMD64-WIN-NOT: #define WIN64 1
+// CHECK-AMD64-WIN-NOT: #define WINNT 1
+// CHECK-AMD64-WIN: #define _WIN32 1
+// CHECK-AMD64-WIN: #define _WIN64 1
+
+// RUN: %clang_cc1 -triple aarch64-windows %s -E -dM -o - \
+// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-ARM64-WIN
+
+// CHECK-ARM64-WIN-NOT: #define WIN32 1
+// CHECK-ARM64-WIN-NOT: #define WIN64 1
+// CHECK-ARM64-WIN-NOT: #define WINNT 1
+// CHECK-ARM64-WIN: #define _M_ARM64 1
+// CHECK-ARM64-WIN: #define _WIN32 1
+// CHECK-ARM64-WIN: #define _WIN64 1
+
+// RUN: %clang_cc1 -triple i686-windows-gnu %s -E -dM -o - \
+// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-X86-MINGW
+
+// CHECK-X86-MINGW: #define WIN32 1
+// CHECK-X86-MINGW-NOT: #define WIN64 1
+// CHECK-X86-MINGW: #define WINNT 1
+// CHECK-X86-MINGW: #define _WIN32 1
+// CHECK-X86-MINGW-NOT: #define _WIN64 1
+
+// RUN: %clang_cc1 -triple thumbv7-windows-gnu %s -E -dM -o - \
+// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-ARM-MINGW
+
+// CHECK-ARM-MINGW: #define WIN32 1
+// CHECK-ARM-MINGW-NOT: #define WIN64 1
+// CHECK-ARM-MINGW: #define WINNT 1
+// CHECK-ARM-MINGW: #define _WIN32 1
+// CHECK-ARM-MINGW-NOT: #define _WIN64 1
+
+// RUN: %clang_cc1 -triple x86_64-windows-gnu %s -E -dM -o - \
+// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-AMD64-MINGW
+
+// CHECK-AMD64-MINGW: #define WIN32 1
+// CHECK-AMD64-MINGW: #define WIN64 1
+// CHECK-AMD64-MINGW: #define WINNT 1
+// CHECK-AMD64-MINGW: #define _WIN32 1
+// CHECK-AMD64-MINGW: #define _WIN64 1
+
+// RUN: %clang_cc1 -triple aarch64-windows-gnu %s -E -dM -o - \
+// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-ARM64-MINGW
+
+// CHECK-ARM64-MINGW-NOT: #define _M_ARM64 1
+// CHECK-ARM64-MINGW: #define WIN32 1
+// CHECK-ARM64-MINGW: #define WIN64 1
+// CHECK-ARM64-MINGW: #define WINNT 1
+// CHECK-ARM64-MINGW: #define _WIN32 1
+// CHECK-ARM64-MINGW: #define _WIN64 1
+// CHECK-ARM64-MINGW: #define __aarch64__ 1
+
diff --git a/test/Preprocessor/riscv-target-features.c b/test/Preprocessor/riscv-target-features.c
new file mode 100644
index 000000000000..2c63e0fa29df
--- /dev/null
+++ b/test/Preprocessor/riscv-target-features.c
@@ -0,0 +1,49 @@
+// RUN: %clang -target riscv32-unknown-linux-gnu -march=rv32i -x c -E -dM %s \
+// RUN: -o - | FileCheck %s
+// RUN: %clang -target riscv64-unknown-linux-gnu -march=rv64i -x c -E -dM %s \
+// RUN: -o - | FileCheck %s
+
+// CHECK-NOT: __riscv_div
+// CHECK-NOT: __riscv_mul
+// CHECK-NOT: __riscv_muldiv
+// CHECK-NOT: __riscv_compressed
+// CHECK-NOT: __riscv_flen
+// CHECK-NOT: __riscv_fdiv
+// CHECK-NOT: __riscv_fsqrt
+// CHECK-NOT: __riscv_atomic
+
+// RUN: %clang -target riscv32-unknown-linux-gnu -march=rv32im -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-M-EXT %s
+// RUN: %clang -target riscv64-unknown-linux-gnu -march=rv64im -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-M-EXT %s
+// CHECK-M-EXT: __riscv_div 1
+// CHECK-M-EXT: __riscv_mul 1
+// CHECK-M-EXT: __riscv_muldiv 1
+
+// RUN: %clang -target riscv32-unknown-linux-gnu -march=rv32ia -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-A-EXT %s
+// RUN: %clang -target riscv64-unknown-linux-gnu -march=rv64ia -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-A-EXT %s
+// CHECK-A-EXT: __riscv_atomic 1
+
+// RUN: %clang -target riscv32-unknown-linux-gnu -march=rv32if -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-F-EXT %s
+// RUN: %clang -target riscv64-unknown-linux-gnu -march=rv64if -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-F-EXT %s
+// CHECK-F-EXT: __riscv_fdiv 1
+// CHECK-F-EXT: __riscv_flen 32
+// CHECK-F-EXT: __riscv_fsqrt 1
+
+// RUN: %clang -target riscv32-unknown-linux-gnu -march=rv32ifd -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-D-EXT %s
+// RUN: %clang -target riscv64-unknown-linux-gnu -march=rv64ifd -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-D-EXT %s
+// CHECK-D-EXT: __riscv_fdiv 1
+// CHECK-D-EXT: __riscv_flen 64
+// CHECK-D-EXT: __riscv_fsqrt 1
+
+// RUN: %clang -target riscv32-unknown-linux-gnu -march=rv32ic -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-C-EXT %s
+// RUN: %clang -target riscv64-unknown-linux-gnu -march=rv64ic -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-C-EXT %s
+// CHECK-C-EXT: __riscv_compressed 1
diff --git a/test/Preprocessor/stdint.c b/test/Preprocessor/stdint.c
index 3b32346d5edc..fc179b4ba538 100644
--- a/test/Preprocessor/stdint.c
+++ b/test/Preprocessor/stdint.c
@@ -636,8 +636,8 @@
//
// RUN: %clang_cc1 -E -ffreestanding -triple=powerpc64-none-netbsd %s | FileCheck -check-prefix PPC64-NETBSD %s
//
-// PPC64-NETBSD:typedef long long int int64_t;
-// PPC64-NETBSD:typedef long long unsigned int uint64_t;
+// PPC64-NETBSD:typedef long int int64_t;
+// PPC64-NETBSD:typedef long unsigned int uint64_t;
// PPC64-NETBSD:typedef int64_t int_least64_t;
// PPC64-NETBSD:typedef uint64_t uint_least64_t;
// PPC64-NETBSD:typedef int64_t int_fast64_t;
@@ -667,8 +667,8 @@
// PPC64-NETBSD:typedef long int intptr_t;
// PPC64-NETBSD:typedef long unsigned int uintptr_t;
//
-// PPC64-NETBSD:typedef long long int intmax_t;
-// PPC64-NETBSD:typedef long long unsigned int uintmax_t;
+// PPC64-NETBSD:typedef long int intmax_t;
+// PPC64-NETBSD:typedef long unsigned int uintmax_t;
//
// PPC64-NETBSD:INT8_MAX_ 127
// PPC64-NETBSD:INT8_MIN_ (-127 -1)
@@ -700,15 +700,15 @@
// PPC64-NETBSD:INT_FAST32_MAX_ 2147483647
// PPC64-NETBSD:UINT_FAST32_MAX_ 4294967295U
//
-// PPC64-NETBSD:INT64_MAX_ 9223372036854775807LL
-// PPC64-NETBSD:INT64_MIN_ (-9223372036854775807LL -1)
-// PPC64-NETBSD:UINT64_MAX_ 18446744073709551615ULL
-// PPC64-NETBSD:INT_LEAST64_MIN_ (-9223372036854775807LL -1)
-// PPC64-NETBSD:INT_LEAST64_MAX_ 9223372036854775807LL
-// PPC64-NETBSD:UINT_LEAST64_MAX_ 18446744073709551615ULL
-// PPC64-NETBSD:INT_FAST64_MIN_ (-9223372036854775807LL -1)
-// PPC64-NETBSD:INT_FAST64_MAX_ 9223372036854775807LL
-// PPC64-NETBSD:UINT_FAST64_MAX_ 18446744073709551615ULL
+// PPC64-NETBSD:INT64_MAX_ 9223372036854775807L
+// PPC64-NETBSD:INT64_MIN_ (-9223372036854775807L -1)
+// PPC64-NETBSD:UINT64_MAX_ 18446744073709551615UL
+// PPC64-NETBSD:INT_LEAST64_MIN_ (-9223372036854775807L -1)
+// PPC64-NETBSD:INT_LEAST64_MAX_ 9223372036854775807L
+// PPC64-NETBSD:UINT_LEAST64_MAX_ 18446744073709551615UL
+// PPC64-NETBSD:INT_FAST64_MIN_ (-9223372036854775807L -1)
+// PPC64-NETBSD:INT_FAST64_MAX_ 9223372036854775807L
+// PPC64-NETBSD:UINT_FAST64_MAX_ 18446744073709551615UL
//
// PPC64-NETBSD:INTPTR_MIN_ (-9223372036854775807L -1)
// PPC64-NETBSD:INTPTR_MAX_ 9223372036854775807L
@@ -717,9 +717,9 @@
// PPC64-NETBSD:PTRDIFF_MAX_ 9223372036854775807L
// PPC64-NETBSD:SIZE_MAX_ 18446744073709551615UL
//
-// PPC64-NETBSD:INTMAX_MIN_ (-9223372036854775807LL -1)
-// PPC64-NETBSD:INTMAX_MAX_ 9223372036854775807LL
-// PPC64-NETBSD:UINTMAX_MAX_ 18446744073709551615ULL
+// PPC64-NETBSD:INTMAX_MIN_ (-9223372036854775807L -1)
+// PPC64-NETBSD:INTMAX_MAX_ 9223372036854775807L
+// PPC64-NETBSD:UINTMAX_MAX_ 18446744073709551615UL
//
// PPC64-NETBSD:SIG_ATOMIC_MIN_ (-2147483647 -1)
// PPC64-NETBSD:SIG_ATOMIC_MAX_ 2147483647
@@ -735,11 +735,11 @@
// PPC64-NETBSD:UINT16_C_(0) 0U
// PPC64-NETBSD:INT32_C_(0) 0
// PPC64-NETBSD:UINT32_C_(0) 0U
-// PPC64-NETBSD:INT64_C_(0) 0LL
-// PPC64-NETBSD:UINT64_C_(0) 0ULL
+// PPC64-NETBSD:INT64_C_(0) 0L
+// PPC64-NETBSD:UINT64_C_(0) 0UL
//
-// PPC64-NETBSD:INTMAX_C_(0) 0LL
-// PPC64-NETBSD:UINTMAX_C_(0) 0ULL
+// PPC64-NETBSD:INTMAX_C_(0) 0L
+// PPC64-NETBSD:UINTMAX_C_(0) 0UL
//
// RUN: %clang_cc1 -E -ffreestanding -triple=powerpc-none-none %s | FileCheck -check-prefix PPC %s
//
diff --git a/test/Preprocessor/x86_target_features.c b/test/Preprocessor/x86_target_features.c
index 542328aca047..2d5369faede0 100644
--- a/test/Preprocessor/x86_target_features.c
+++ b/test/Preprocessor/x86_target_features.c
@@ -376,9 +376,9 @@
// ADX: #define __ADX__ 1
-// RUN: %clang -target i386-unknown-unknown -mshstk -x c -E -dM -o - %s | FileCheck -match-full-lines --check-prefix=CETSS %s
+// RUN: %clang -target i386-unknown-unknown -mshstk -x c -E -dM -o - %s | FileCheck -match-full-lines --check-prefix=SHSTK %s
-// CETSS: #define __SHSTK__ 1
+// SHSTK: #define __SHSTK__ 1
// RUN: %clang -target i386-unknown-unknown -march=atom -mrdseed -x c -E -dM -o - %s | FileCheck -match-full-lines --check-prefix=RDSEED %s
@@ -436,3 +436,6 @@
// VPCLMULQDQNOPCLMUL-NOT: #define __PCLMUL__ 1
// VPCLMULQDQNOPCLMUL-NOT: #define __VPCLMULQDQ__ 1
+// RUN: %clang -target i386-unknown-unknown -march=atom -mrdpid -x c -E -dM -o - %s | FileCheck -match-full-lines --check-prefix=RDPID %s
+
+// RDPID: #define __RDPID__ 1
diff --git a/test/Profile/c-captured.c b/test/Profile/c-captured.c
index bae2dcb6ef77..0e265a722917 100644
--- a/test/Profile/c-captured.c
+++ b/test/Profile/c-captured.c
@@ -1,7 +1,7 @@
-// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-captured.c %s -o - -emit-llvm -fprofile-instrument=clang | FileCheck -check-prefix=PGOGEN -check-prefix=PGOALL %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-captured.c %s -o - -emit-llvm -fprofile-instrument=clang | FileCheck -allow-deprecated-dag-overlap -check-prefix=PGOGEN -check-prefix=PGOALL %s
// RUN: llvm-profdata merge %S/Inputs/c-captured.proftext -o %t.profdata
-// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-captured.c %s -o - -emit-llvm -fprofile-instrument-use-path=%t.profdata | FileCheck -check-prefix=PGOUSE -check-prefix=PGOALL %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-captured.c %s -o - -emit-llvm -fprofile-instrument-use-path=%t.profdata | FileCheck -allow-deprecated-dag-overlap -check-prefix=PGOUSE -check-prefix=PGOALL %s
// PGOGEN: @[[DCC:__profc_debug_captured]] = private global [3 x i64] zeroinitializer
// PGOGEN: @[[CSC:__profc_c_captured.c___captured_stmt]] = private global [2 x i64] zeroinitializer
diff --git a/test/Profile/c-general.c b/test/Profile/c-general.c
index da3b7f25522c..22b4288a5fd6 100644
--- a/test/Profile/c-general.c
+++ b/test/Profile/c-general.c
@@ -1,12 +1,12 @@
// Test instrumentation of general constructs in C.
-// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-general.c %s -o - -emit-llvm -fprofile-instrument=clang | FileCheck -check-prefix=PGOGEN %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-general.c %s -o - -emit-llvm -fprofile-instrument=clang | FileCheck -allow-deprecated-dag-overlap -check-prefix=PGOGEN %s
// RUN: llvm-profdata merge %S/Inputs/c-general.proftext -o %t.profdata
-// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-general.c %s -o - -emit-llvm -fprofile-instrument-use-path=%t.profdata | FileCheck -check-prefix=PGOUSE %s
-// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-general.c %s -o - -emit-llvm -fprofile-instrument-use-path=%S/Inputs/c-general.profdata.v3 | FileCheck -check-prefix=PGOUSE %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-general.c %s -o - -emit-llvm -fprofile-instrument-use-path=%t.profdata | FileCheck -allow-deprecated-dag-overlap -check-prefix=PGOUSE %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-general.c %s -o - -emit-llvm -fprofile-instrument-use-path=%S/Inputs/c-general.profdata.v3 | FileCheck -allow-deprecated-dag-overlap -check-prefix=PGOUSE %s
// Also check compatibility with older profiles.
-// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-general.c %s -o - -emit-llvm -fprofile-instrument-use-path=%S/Inputs/c-general.profdata.v1 | FileCheck -check-prefix=PGOUSE %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-general.c %s -o - -emit-llvm -fprofile-instrument-use-path=%S/Inputs/c-general.profdata.v1 | FileCheck -allow-deprecated-dag-overlap -check-prefix=PGOUSE %s
// PGOGEN: @[[SLC:__profc_simple_loops]] = private global [4 x i64] zeroinitializer
// PGOGEN: @[[IFC:__profc_conditionals]] = private global [11 x i64] zeroinitializer
diff --git a/test/Profile/cxx-lambda.cpp b/test/Profile/cxx-lambda.cpp
index 2b422912f45b..645f1603e019 100644
--- a/test/Profile/cxx-lambda.cpp
+++ b/test/Profile/cxx-lambda.cpp
@@ -1,13 +1,13 @@
// Tests for instrumentation of C++11 lambdas
// RUN: %clang_cc1 -x c++ %s -triple %itanium_abi_triple -main-file-name cxx-lambda.cpp -std=c++11 -o - -emit-llvm -fprofile-instrument=clang > %tgen
-// RUN: FileCheck --input-file=%tgen -check-prefix=PGOGEN %s
-// RUN: FileCheck --input-file=%tgen -check-prefix=LMBGEN %s
+// RUN: FileCheck -allow-deprecated-dag-overlap --input-file=%tgen -check-prefix=PGOGEN %s
+// RUN: FileCheck -allow-deprecated-dag-overlap --input-file=%tgen -check-prefix=LMBGEN %s
// RUN: llvm-profdata merge %S/Inputs/cxx-lambda.proftext -o %t.profdata
// RUN: %clang_cc1 -x c++ %s -triple %itanium_abi_triple -main-file-name cxx-lambda.cpp -std=c++11 -o - -emit-llvm -fprofile-instrument-use-path=%t.profdata > %tuse
-// RUN: FileCheck --input-file=%tuse -check-prefix=PGOUSE %s
-// RUN: FileCheck --input-file=%tuse -check-prefix=LMBUSE %s
+// RUN: FileCheck -allow-deprecated-dag-overlap --input-file=%tuse -check-prefix=PGOUSE %s
+// RUN: FileCheck -allow-deprecated-dag-overlap --input-file=%tuse -check-prefix=LMBUSE %s
// PGOGEN: @[[LWC:__profc__Z7lambdasv]] = private global [4 x i64] zeroinitializer
// PGOGEN: @[[MAC:__profc_main]] = private global [1 x i64] zeroinitializer
diff --git a/test/Rewriter/rewrite-modern-try-finally.m b/test/Rewriter/rewrite-modern-try-finally.m
index 500133b86142..41737e95f0cd 100644
--- a/test/Rewriter/rewrite-modern-try-finally.m
+++ b/test/Rewriter/rewrite-modern-try-finally.m
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -x objective-c -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp
-// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -fexceptions -Wno-address-of-temporary -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.10 -x objective-c -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.10 -fsyntax-only -fcxx-exceptions -fexceptions -Wno-address-of-temporary -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
typedef struct objc_class *Class;
typedef struct objc_object {
diff --git a/test/Sema/Inputs/pragma-align-no-header-change-warning.h b/test/Sema/Inputs/pragma-align-no-header-change-warning.h
new file mode 100644
index 000000000000..6cd4e7d7ed1b
--- /dev/null
+++ b/test/Sema/Inputs/pragma-align-no-header-change-warning.h
@@ -0,0 +1,5 @@
+#pragma options align=mac68k
+
+struct S { int x; };
+
+#pragma options align=reset
diff --git a/test/Sema/_Float128.c b/test/Sema/_Float128.c
deleted file mode 100644
index f0c3c6d555ef..000000000000
--- a/test/Sema/_Float128.c
+++ /dev/null
@@ -1,22 +0,0 @@
-// RUN: %clang_cc1 -verify %s
-// RUN: %clang_cc1 -triple powerpc64-linux -verify %s
-// RUN: %clang_cc1 -triple i686-windows-gnu -verify %s
-// RUN: %clang_cc1 -triple x86_64-windows-gnu -verify %s
-// RUN: %clang_cc1 -triple x86_64-windows-msvc -verify %s
-
-#if defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__)
-_Float128 f;
-_Float128 tiny = __FLT128_EPSILON__;
-int g(int x, _Float128 *y) {
- return x + *y;
-}
-
-// expected-no-diagnostics
-#else
-_Float128 f; // expected-error {{__float128 is not supported on this target}}
-float tiny = __FLT128_EPSILON__; // expected-error{{use of undeclared identifier}}
-int g(int x, _Float128 *y) { // expected-error {{__float128 is not supported on this target}}
- return x + *y;
-}
-
-#endif // defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__)
diff --git a/test/Sema/aarch64-neon-fp16-ranges.c b/test/Sema/aarch64-neon-fp16-ranges.c
new file mode 100644
index 000000000000..60190525e042
--- /dev/null
+++ b/test/Sema/aarch64-neon-fp16-ranges.c
@@ -0,0 +1,64 @@
+// RUN: %clang_cc1 -triple arm64-linux-gnu -fallow-half-arguments-and-returns -target-feature +neon -target-feature +fullfp16 -ffreestanding -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple aarch64-linux-gnu -fallow-half-arguments-and-returns -target-feature +fullfp16 -target-feature +neon -ffreestanding -fsyntax-only -verify %s
+
+#include <arm_neon.h>
+#include <arm_fp16.h>
+
+void test_vcvt_f16_16(int16_t a){
+ vcvth_n_f16_s16(a, 1);
+ vcvth_n_f16_s16(a, 16);
+ vcvth_n_f16_s16(a, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vcvth_n_f16_s16(a, 17); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+
+ vcvth_n_f16_u16(a, 1);
+ vcvth_n_f16_u16(a, 16);
+ vcvth_n_f16_u16(a, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vcvth_n_f16_u16(a, 17); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+}
+
+void test_vcvt_f16_32(int32_t a){
+ vcvth_n_f16_u32(a, 1);
+ vcvth_n_f16_u32(a, 16);
+ vcvth_n_f16_u32(a, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vcvth_n_f16_u32(a, 17); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+
+ vcvth_n_f16_s32(a, 1);
+ vcvth_n_f16_s32(a, 16);
+ vcvth_n_f16_s32(a, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vcvth_n_f16_s32(a, 17); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+}
+
+void test_vcvt_f16_64(int64_t a){
+ vcvth_n_f16_s64(a, 1);
+ vcvth_n_f16_s64(a, 16);
+ vcvth_n_f16_s64(a, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vcvth_n_f16_s64(a, 17); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+}
+
+
+void test_vcvt_su_f(float16_t a){
+ vcvth_n_s16_f16(a, 1);
+ vcvth_n_s16_f16(a, 16);
+ vcvth_n_s16_f16(a, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vcvth_n_s16_f16(a, 17); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+
+ vcvth_n_s32_f16(a, 1);
+ vcvth_n_s32_f16(a, 16);
+ vcvth_n_s32_f16(a, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vcvth_n_s32_f16(a, 17); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+
+ vcvth_n_s64_f16(a, 1);
+ vcvth_n_s64_f16(a, 16);
+ vcvth_n_s64_f16(a, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vcvth_n_s64_f16(a, 17); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+
+ vcvth_n_u16_f16(a, 1);
+ vcvth_n_u16_f16(a, 16);
+ vcvth_n_u16_f16(a, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vcvth_n_u16_f16(a, 17); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+
+ vcvth_n_u32_f16(a, 1);
+ vcvth_n_u32_f16(a, 16);
+ vcvth_n_u32_f16(a, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vcvth_n_u32_f16(a, 17); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+}
diff --git a/test/Sema/aarch64-neon-ranges.c b/test/Sema/aarch64-neon-ranges.c
index 3a170b8f4cb9..f9b652fc9bf5 100644
--- a/test/Sema/aarch64-neon-ranges.c
+++ b/test/Sema/aarch64-neon-ranges.c
@@ -11,12 +11,12 @@ void test_vext_8bit(int8x8_t small, int8x16_t big) {
vextq_u8(big, big, 15);
vextq_p8(big, big, 15);
- vext_s8(small, small, 8); // expected-error {{argument should be a value from 0 to 7}}
- vext_u8(small, small, 8); // expected-error {{argument should be a value from 0 to 7}}
- vext_p8(small, small, 8); // expected-error {{argument should be a value from 0 to 7}}
- vextq_s8(big, big, 16); // expected-error {{argument should be a value from 0 to 15}}
- vextq_u8(big, big, 16); // expected-error {{argument should be a value from 0 to 15}}
- vextq_p8(big, big, 16); // expected-error {{argument should be a value from 0 to 15}}
+ vext_s8(small, small, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vext_u8(small, small, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vext_p8(small, small, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vextq_s8(big, big, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vextq_u8(big, big, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vextq_p8(big, big, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
}
void test_mul_lane_f64(float64x1_t small, float64x2_t big, float64x2_t rhs) {
@@ -29,11 +29,11 @@ void test_mul_lane_f64(float64x1_t small, float64x2_t big, float64x2_t rhs) {
vfmaq_lane_f64(big, big, small, 0);
vfmaq_laneq_f64(big, big, big, 1);
- vmul_lane_f64(small, small, 1); // expected-error {{argument should be a value from 0 to 0}}
- vmul_laneq_f64(small, big, 2); // expected-error {{argument should be a value from 0 to 1}}
- vfma_lane_f64(small, small, small, 1); // expected-error {{argument should be a value from 0 to 0}}
- vfma_laneq_f64(small, small, big, 2); // expected-error {{argument should be a value from 0 to 1}}
- vfmaq_laneq_f64(big, big, big, 2); // expected-error {{argument should be a value from 0 to 1}}
+ vmul_lane_f64(small, small, 1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vmul_laneq_f64(small, big, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vfma_lane_f64(small, small, small, 1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vfma_laneq_f64(small, small, big, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vfmaq_laneq_f64(big, big, big, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}}
}
void test_ld1st1(int8x8_t small, int8x16_t big, void *addr) {
@@ -47,15 +47,15 @@ void test_ld1st1(int8x8_t small, int8x16_t big, void *addr) {
vld1q_lane_s32(addr, big, 3);
vld1q_lane_s64(addr, big, 1);
- vld1_lane_s8(addr, small, 8); // expected-error {{argument should be a value from 0 to 7}}
- vld1_lane_s16(addr, small, 4); // expected-error {{argument should be a value from 0 to 3}}
- vld1_lane_s32(addr, small, 2); // expected-error {{argument should be a value from 0 to 1}}
- vld1_lane_s64(addr, small, 1); // expected-error {{argument should be a value from 0 to 0}}
+ vld1_lane_s8(addr, small, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vld1_lane_s16(addr, small, 4); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vld1_lane_s32(addr, small, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vld1_lane_s64(addr, small, 1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
- vld1q_lane_s8(addr, big, 16); // expected-error {{argument should be a value from 0 to 15}}
- vld1q_lane_s16(addr, big, 8); // expected-error {{argument should be a value from 0 to 7}}
- vld1q_lane_s32(addr, big, 4); // expected-error {{argument should be a value from 0 to 3}}
- vld1q_lane_s64(addr, big, 2); // expected-error {{argument should be a value from 0 to 1}}
+ vld1q_lane_s8(addr, big, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vld1q_lane_s16(addr, big, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vld1q_lane_s32(addr, big, 4); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vld1q_lane_s64(addr, big, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}}
vst1_lane_s8(addr, small, 7);
vst1_lane_s16(addr, small, 3);
@@ -67,15 +67,15 @@ void test_ld1st1(int8x8_t small, int8x16_t big, void *addr) {
vst1q_lane_s32(addr, big, 3);
vst1q_lane_s64(addr, big, 1);
- vst1_lane_s8(addr, small, 8); // expected-error {{argument should be a value from 0 to 7}}
- vst1_lane_s16(addr, small, 4); // expected-error {{argument should be a value from 0 to 3}}
- vst1_lane_s32(addr, small, 2); // expected-error {{argument should be a value from 0 to 1}}
- vst1_lane_s64(addr, small, 1); // expected-error {{argument should be a value from 0 to 0}}
+ vst1_lane_s8(addr, small, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vst1_lane_s16(addr, small, 4); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vst1_lane_s32(addr, small, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vst1_lane_s64(addr, small, 1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
- vst1q_lane_s8(addr, big, 16); // expected-error {{argument should be a value from 0 to 15}}
- vst1q_lane_s16(addr, big, 8); // expected-error {{argument should be a value from 0 to 7}}
- vst1q_lane_s32(addr, big, 4); // expected-error {{argument should be a value from 0 to 3}}
- vst1q_lane_s64(addr, big, 2); // expected-error {{argument should be a value from 0 to 1}}
+ vst1q_lane_s8(addr, big, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vst1q_lane_s16(addr, big, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vst1q_lane_s32(addr, big, 4); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vst1q_lane_s64(addr, big, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}}
}
void test_ld2st2(int8x8x2_t small8, int8x16x2_t big8,
@@ -93,15 +93,15 @@ void test_ld2st2(int8x8x2_t small8, int8x16x2_t big8,
vld2q_lane_s32(addr, big32, 3);
vld2q_lane_s64(addr, big64, 1);
- vld2_lane_s8(addr, small8, 8); // expected-error {{argument should be a value from 0 to 7}}
- vld2_lane_s16(addr, small16, 4); // expected-error {{argument should be a value from 0 to 3}}
- vld2_lane_s32(addr, small32, 2); // expected-error {{argument should be a value from 0 to 1}}
- vld2_lane_s64(addr, small64, 1); // expected-error {{argument should be a value from 0 to 0}}
+ vld2_lane_s8(addr, small8, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vld2_lane_s16(addr, small16, 4); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vld2_lane_s32(addr, small32, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vld2_lane_s64(addr, small64, 1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
- vld2q_lane_s8(addr, big8, 16); // expected-error {{argument should be a value from 0 to 15}}
- vld2q_lane_s16(addr, big16, 8); // expected-error {{argument should be a value from 0 to 7}}
- vld2q_lane_s32(addr, big32, 4); // expected-error {{argument should be a value from 0 to 3}}
- vld2q_lane_s64(addr, big64, 2); // expected-error {{argument should be a value from 0 to 1}}
+ vld2q_lane_s8(addr, big8, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vld2q_lane_s16(addr, big16, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vld2q_lane_s32(addr, big32, 4); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vld2q_lane_s64(addr, big64, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}}
vst2_lane_s8(addr, small8, 7);
vst2_lane_s16(addr, small16, 3);
@@ -113,15 +113,15 @@ void test_ld2st2(int8x8x2_t small8, int8x16x2_t big8,
vst2q_lane_s32(addr, big32, 3);
vst2q_lane_s64(addr, big64, 1);
- vst2_lane_s8(addr, small8, 8); // expected-error {{argument should be a value from 0 to 7}}
- vst2_lane_s16(addr, small16, 4); // expected-error {{argument should be a value from 0 to 3}}
- vst2_lane_s32(addr, small32, 2); // expected-error {{argument should be a value from 0 to 1}}
- vst2_lane_s64(addr, small64, 1); // expected-error {{argument should be a value from 0 to 0}}
+ vst2_lane_s8(addr, small8, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vst2_lane_s16(addr, small16, 4); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vst2_lane_s32(addr, small32, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vst2_lane_s64(addr, small64, 1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
- vst2q_lane_s8(addr, big8, 16); // expected-error {{argument should be a value from 0 to 15}}
- vst2q_lane_s16(addr, big16, 8); // expected-error {{argument should be a value from 0 to 7}}
- vst2q_lane_s32(addr, big32, 4); // expected-error {{argument should be a value from 0 to 3}}
- vst2q_lane_s64(addr, big64, 2); // expected-error {{argument should be a value from 0 to 1}}
+ vst2q_lane_s8(addr, big8, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vst2q_lane_s16(addr, big16, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vst2q_lane_s32(addr, big32, 4); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vst2q_lane_s64(addr, big64, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}}
}
void test_ld3st3(int8x8x3_t small8, int8x16x3_t big8,
@@ -139,15 +139,15 @@ void test_ld3st3(int8x8x3_t small8, int8x16x3_t big8,
vld3q_lane_s32(addr, big32, 3);
vld3q_lane_s64(addr, big64, 1);
- vld3_lane_s8(addr, small8, 8); // expected-error {{argument should be a value from 0 to 7}}
- vld3_lane_s16(addr, small16, 4); // expected-error {{argument should be a value from 0 to 3}}
- vld3_lane_s32(addr, small32, 2); // expected-error {{argument should be a value from 0 to 1}}
- vld3_lane_s64(addr, small64, 1); // expected-error {{argument should be a value from 0 to 0}}
+ vld3_lane_s8(addr, small8, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vld3_lane_s16(addr, small16, 4); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vld3_lane_s32(addr, small32, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vld3_lane_s64(addr, small64, 1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
- vld3q_lane_s8(addr, big8, 16); // expected-error {{argument should be a value from 0 to 15}}
- vld3q_lane_s16(addr, big16, 8); // expected-error {{argument should be a value from 0 to 7}}
- vld3q_lane_s32(addr, big32, 4); // expected-error {{argument should be a value from 0 to 3}}
- vld3q_lane_s64(addr, big64, 2); // expected-error {{argument should be a value from 0 to 1}}
+ vld3q_lane_s8(addr, big8, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vld3q_lane_s16(addr, big16, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vld3q_lane_s32(addr, big32, 4); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vld3q_lane_s64(addr, big64, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}}
vst3_lane_s8(addr, small8, 7);
vst3_lane_s16(addr, small16, 3);
@@ -159,15 +159,15 @@ void test_ld3st3(int8x8x3_t small8, int8x16x3_t big8,
vst3q_lane_s32(addr, big32, 3);
vst3q_lane_s64(addr, big64, 1);
- vst3_lane_s8(addr, small8, 8); // expected-error {{argument should be a value from 0 to 7}}
- vst3_lane_s16(addr, small16, 4); // expected-error {{argument should be a value from 0 to 3}}
- vst3_lane_s32(addr, small32, 2); // expected-error {{argument should be a value from 0 to 1}}
- vst3_lane_s64(addr, small64, 1); // expected-error {{argument should be a value from 0 to 0}}
+ vst3_lane_s8(addr, small8, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vst3_lane_s16(addr, small16, 4); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vst3_lane_s32(addr, small32, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vst3_lane_s64(addr, small64, 1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
- vst3q_lane_s8(addr, big8, 16); // expected-error {{argument should be a value from 0 to 15}}
- vst3q_lane_s16(addr, big16, 8); // expected-error {{argument should be a value from 0 to 7}}
- vst3q_lane_s32(addr, big32, 4); // expected-error {{argument should be a value from 0 to 3}}
- vst3q_lane_s64(addr, big64, 2); // expected-error {{argument should be a value from 0 to 1}}
+ vst3q_lane_s8(addr, big8, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vst3q_lane_s16(addr, big16, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vst3q_lane_s32(addr, big32, 4); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vst3q_lane_s64(addr, big64, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}}
}
void test_ld4st4(int8x8x4_t small8, int8x16x4_t big8,
@@ -185,15 +185,15 @@ void test_ld4st4(int8x8x4_t small8, int8x16x4_t big8,
vld4q_lane_s32(addr, big32, 3);
vld4q_lane_s64(addr, big64, 1);
- vld4_lane_s8(addr, small8, 8); // expected-error {{argument should be a value from 0 to 7}}
- vld4_lane_s16(addr, small16, 4); // expected-error {{argument should be a value from 0 to 3}}
- vld4_lane_s32(addr, small32, 2); // expected-error {{argument should be a value from 0 to 1}}
- vld4_lane_s64(addr, small64, 1); // expected-error {{argument should be a value from 0 to 0}}
+ vld4_lane_s8(addr, small8, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vld4_lane_s16(addr, small16, 4); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vld4_lane_s32(addr, small32, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vld4_lane_s64(addr, small64, 1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
- vld4q_lane_s8(addr, big8, 16); // expected-error {{argument should be a value from 0 to 15}}
- vld4q_lane_s16(addr, big16, 8); // expected-error {{argument should be a value from 0 to 7}}
- vld4q_lane_s32(addr, big32, 4); // expected-error {{argument should be a value from 0 to 3}}
- vld4q_lane_s64(addr, big64, 2); // expected-error {{argument should be a value from 0 to 1}}
+ vld4q_lane_s8(addr, big8, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vld4q_lane_s16(addr, big16, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vld4q_lane_s32(addr, big32, 4); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vld4q_lane_s64(addr, big64, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}}
vst4_lane_s8(addr, small8, 7);
vst4_lane_s16(addr, small16, 3);
@@ -205,14 +205,14 @@ void test_ld4st4(int8x8x4_t small8, int8x16x4_t big8,
vst4q_lane_s32(addr, big32, 3);
vst4q_lane_s64(addr, big64, 1);
- vst4_lane_s8(addr, small8, 8); // expected-error {{argument should be a value from 0 to 7}}
- vst4_lane_s16(addr, small16, 4); // expected-error {{argument should be a value from 0 to 3}}
- vst4_lane_s32(addr, small32, 2); // expected-error {{argument should be a value from 0 to 1}}
- vst4_lane_s64(addr, small64, 1); // expected-error {{argument should be a value from 0 to 0}}
+ vst4_lane_s8(addr, small8, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vst4_lane_s16(addr, small16, 4); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vst4_lane_s32(addr, small32, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vst4_lane_s64(addr, small64, 1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
- vst4q_lane_s8(addr, big8, 16); // expected-error {{argument should be a value from 0 to 15}}
- vst4q_lane_s16(addr, big16, 8); // expected-error {{argument should be a value from 0 to 7}}
- vst4q_lane_s32(addr, big32, 4); // expected-error {{argument should be a value from 0 to 3}}
- vst4q_lane_s64(addr, big64, 2); // expected-error {{argument should be a value from 0 to 1}}
+ vst4q_lane_s8(addr, big8, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vst4q_lane_s16(addr, big16, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vst4q_lane_s32(addr, big32, 4); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vst4q_lane_s64(addr, big64, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}}
}
diff --git a/test/Sema/address_spaces.c b/test/Sema/address_spaces.c
index 018a8521bfc5..87707d7deb0d 100644
--- a/test/Sema/address_spaces.c
+++ b/test/Sema/address_spaces.c
@@ -14,6 +14,7 @@ void foo(_AS3 float *a,
int _AS1 _AS2 *Y; // expected-error {{multiple address spaces specified for type}}
int *_AS1 _AS2 *Z; // expected-error {{multiple address spaces specified for type}}
+ int *_AS1 _AS1 *M; // expected-warning {{multiple identical address spaces specified for type}}
_AS1 int local; // expected-error {{automatic variable qualified with an address space}}
_AS1 int array[5]; // expected-error {{automatic variable qualified with an address space}}
diff --git a/test/Sema/alloc-size.c b/test/Sema/alloc-size.c
index 7004a5a7d7f6..56181511a194 100644
--- a/test/Sema/alloc-size.c
+++ b/test/Sema/alloc-size.c
@@ -3,14 +3,14 @@
void *fail1(int a) __attribute__((alloc_size)); //expected-error{{'alloc_size' attribute takes at least 1 argument}}
void *fail2(int a) __attribute__((alloc_size())); //expected-error{{'alloc_size' attribute takes at least 1 argument}}
-void *fail3(int a) __attribute__((alloc_size(0))); //expected-error{{'alloc_size' attribute parameter 0 is out of bounds}}
-void *fail4(int a) __attribute__((alloc_size(2))); //expected-error{{'alloc_size' attribute parameter 2 is out of bounds}}
+void *fail3(int a) __attribute__((alloc_size(0))); //expected-error{{'alloc_size' attribute parameter 1 is out of bounds}}
+void *fail4(int a) __attribute__((alloc_size(2))); //expected-error{{'alloc_size' attribute parameter 1 is out of bounds}}
-void *fail5(int a, int b) __attribute__((alloc_size(0, 1))); //expected-error{{'alloc_size' attribute parameter 0 is out of bounds}}
-void *fail6(int a, int b) __attribute__((alloc_size(3, 1))); //expected-error{{'alloc_size' attribute parameter 3 is out of bounds}}
+void *fail5(int a, int b) __attribute__((alloc_size(0, 1))); //expected-error{{'alloc_size' attribute parameter 1 is out of bounds}}
+void *fail6(int a, int b) __attribute__((alloc_size(3, 1))); //expected-error{{'alloc_size' attribute parameter 1 is out of bounds}}
-void *fail7(int a, int b) __attribute__((alloc_size(1, 0))); //expected-error{{'alloc_size' attribute parameter 0 is out of bounds}}
-void *fail8(int a, int b) __attribute__((alloc_size(1, 3))); //expected-error{{'alloc_size' attribute parameter 3 is out of bounds}}
+void *fail7(int a, int b) __attribute__((alloc_size(1, 0))); //expected-error{{'alloc_size' attribute parameter 2 is out of bounds}}
+void *fail8(int a, int b) __attribute__((alloc_size(1, 3))); //expected-error{{'alloc_size' attribute parameter 2 is out of bounds}}
int fail9(int a) __attribute__((alloc_size(1))); //expected-warning{{'alloc_size' attribute only applies to return values that are pointers}}
diff --git a/test/Sema/annotate.c b/test/Sema/annotate.c
index 4a786d0a0163..0d1a1c29a310 100644
--- a/test/Sema/annotate.c
+++ b/test/Sema/annotate.c
@@ -1,9 +1,13 @@
-// RUN: %clang_cc1 %s -fsyntax-only -verify
+// RUN: %clang_cc1 %s -fsyntax-only -fdouble-square-bracket-attributes -verify
void __attribute__((annotate("foo"))) foo(float *a) {
__attribute__((annotate("bar"))) int x;
+ [[clang::annotate("bar")]] int x2;
__attribute__((annotate(1))) int y; // expected-error {{'annotate' attribute requires a string}}
+ [[clang::annotate(1)]] int y2; // expected-error {{'annotate' attribute requires a string}}
__attribute__((annotate("bar", 1))) int z; // expected-error {{'annotate' attribute takes one argument}}
+ [[clang::annotate("bar", 1)]] int z2; // expected-error {{'annotate' attribute takes one argument}}
+
int u = __builtin_annotation(z, (char*) 0); // expected-error {{second argument to __builtin_annotation must be a non-wide string constant}}
int v = __builtin_annotation(z, (char*) L"bar"); // expected-error {{second argument to __builtin_annotation must be a non-wide string constant}}
int w = __builtin_annotation(z, "foo");
diff --git a/test/Sema/arm-asm.c b/test/Sema/arm-asm.c
index e48718b0a2ac..24fb5a7ecd82 100644
--- a/test/Sema/arm-asm.c
+++ b/test/Sema/arm-asm.c
@@ -10,3 +10,10 @@ void test_64bit_r(void) {
long long foo = 0, bar = 0;
asm volatile("INST %0, %1" : "=r"(foo) : "r"(bar));
}
+
+void test_clobber_conflict(void) {
+ register int x asm("r1");
+ asm volatile("nop" :: "r"(x) : "%r1"); // expected-error {{conflicts with asm clobber list}}
+ asm volatile("nop" :: "l"(x) : "%r1"); // expected-error {{conflicts with asm clobber list}}
+ asm volatile("nop" : "=r"(x) :: "%r1"); // expected-error {{conflicts with asm clobber list}}
+}
diff --git a/test/Sema/arm-neon-types.c b/test/Sema/arm-neon-types.c
index a5ee708b5034..989f20ab20ec 100644
--- a/test/Sema/arm-neon-types.c
+++ b/test/Sema/arm-neon-types.c
@@ -17,7 +17,7 @@ float32x2_t test2(uint32x2_t x) {
float32x2_t test3(uint32x2_t x) {
// FIXME: The "incompatible result type" error is due to pr10112 and should be
// removed when that is fixed.
- return vcvt_n_f32_u32(x, 0); // expected-error {{argument should be a value from 1 to 32}}
+ return vcvt_n_f32_u32(x, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}}
}
typedef signed int vSInt32 __attribute__((__vector_size__(16)));
diff --git a/test/Sema/arm-no-fp16.c b/test/Sema/arm-no-fp16.c
index 6443d83198ce..2a23270e92d8 100644
--- a/test/Sema/arm-no-fp16.c
+++ b/test/Sema/arm-no-fp16.c
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -triple thumbv7-none-eabi %s -target-feature +neon -target-feature -fp16 -fsyntax-only -verify
+// RUN: %clang_cc1 -triple thumbv7-none-eabi %s -target-feature +neon \
+// RUN: -fallow-half-arguments-and-returns -target-feature -fp16 \
+// RUN: -fsyntax-only -verify
#include <arm_neon.h>
@@ -9,3 +11,75 @@ float16x4_t test_vcvt_f16_f32(float32x4_t a) {
float32x4_t test_vcvt_f32_f16(float16x4_t a) {
return vcvt_f32_f16(a); // expected-warning{{implicit declaration of function 'vcvt_f32_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float32x4_t'}}
}
+
+float16x4_t test_vrnda_f16(float16x4_t a) {
+ return vrnda_f16(a); // expected-warning{{implicit declaration of function 'vrnda_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x4_t'}}
+}
+
+float16x8_t test_vrndaq_f16(float16x8_t a) {
+ return vrndaq_f16(a); // expected-warning{{implicit declaration of function 'vrndaq_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8_t'}}
+}
+
+float16x4_t test_vrnd_f16(float16x4_t a) {
+ return vrnd_f16(a); // expected-warning{{implicit declaration of function 'vrnd_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x4_t'}}
+}
+
+float16x8_t test_vrndq_f16(float16x8_t a) {
+ return vrndq_f16(a); // expected-warning{{implicit declaration of function 'vrndq_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8_t'}}
+}
+
+float16x4_t test_vrndi_f16(float16x4_t a) {
+ return vrndi_f16(a); // expected-warning{{implicit declaration of function 'vrndi_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x4_t'}}
+}
+
+float16x8_t test_vrndiq_f16(float16x8_t a) {
+ return vrndiq_f16(a); // expected-warning{{implicit declaration of function 'vrndiq_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8_t'}}
+}
+
+float16x4_t test_vrndm_f16(float16x4_t a) {
+ return vrndm_f16(a); // expected-warning{{implicit declaration of function 'vrndm_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x4_t'}}
+}
+
+float16x8_t test_vrndmq_f16(float16x8_t a) {
+ return vrndmq_f16(a); // expected-warning{{implicit declaration of function 'vrndmq_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8_t'}}
+}
+
+float16x4_t test_vrndn_f16(float16x4_t a) {
+ return vrndn_f16(a); // expected-warning{{implicit declaration of function 'vrndn_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x4_t'}}
+}
+
+float16x8_t test_vrndnq_f16(float16x8_t a) {
+ return vrndnq_f16(a); // expected-warning{{implicit declaration of function 'vrndnq_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8_t'}}
+}
+
+float16x4_t test_vrndp_f16(float16x4_t a) {
+ return vrndp_f16(a); // expected-warning{{implicit declaration of function 'vrndp_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x4_t'}}
+}
+
+float16x8_t test_vrndpq_f16(float16x8_t a) {
+ return vrndpq_f16(a); // expected-warning{{implicit declaration of function 'vrndpq_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8_t'}}
+}
+
+float16x4_t test_vrndx_f16(float16x4_t a) {
+ return vrndx_f16(a); // expected-warning{{implicit declaration of function 'vrndx_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x4_t'}}
+}
+
+float16x8_t test_vrndxq_f16(float16x8_t a) {
+ return vrndxq_f16(a); // expected-warning{{implicit declaration of function 'vrndxq_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8_t'}}
+}
+
+float16x4_t test_vmaxnm_f16(float16x4_t a, float16x4_t b) {
+ return vmaxnm_f16(a, b); // expected-warning{{implicit declaration of function 'vmaxnm_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x4_t'}}
+}
+
+float16x8_t test_vmaxnmq_f16(float16x8_t a, float16x8_t b) {
+ return vmaxnmq_f16(a, b); // expected-warning{{implicit declaration of function 'vmaxnmq_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8_t'}}
+}
+
+float16x4_t test_vminnm_f16(float16x4_t a, float16x4_t b) {
+ return vminnm_f16(a, b); // expected-warning{{implicit declaration of function 'vminnm_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x4_t'}}
+}
+
+float16x8_t test_vminnmq_f16(float16x8_t a, float16x8_t b) {
+ return vminnmq_f16(a, b); // expected-warning{{implicit declaration of function 'vminnmq_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8_t'}}
+}
diff --git a/test/Sema/arm64-inline-asm.c b/test/Sema/arm64-inline-asm.c
index d8e16a6872cc..541c190e6116 100644
--- a/test/Sema/arm64-inline-asm.c
+++ b/test/Sema/arm64-inline-asm.c
@@ -7,3 +7,9 @@ void foo() {
asm volatile("USE(%0)" :: "z"(0)); // expected-warning {{value size does not match register size specified by the constraint and modifier}} expected-note {{use constraint modifier "w"}}
}
+
+void test_clobber_conflict(void) {
+ register long x asm("x1");
+ asm volatile("nop" :: "r"(x) : "%x1"); // expected-error {{conflicts with asm clobber list}}
+ asm volatile("nop" : "=r"(x) :: "%x1"); // expected-error {{conflicts with asm clobber list}}
+}
diff --git a/test/Sema/artificial.c b/test/Sema/artificial.c
new file mode 100644
index 000000000000..076a61ca0fef
--- /dev/null
+++ b/test/Sema/artificial.c
@@ -0,0 +1,4 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+inline void __attribute__((artificial)) foo() {}
+void __attribute__((artificial)) bar() {} // expected-warning {{'artificial' attribute only applies to inline functions}}
diff --git a/test/Sema/assign.c b/test/Sema/assign.c
index 5bdfa9a3a5df..28d7b9f3bbdf 100644
--- a/test/Sema/assign.c
+++ b/test/Sema/assign.c
@@ -11,10 +11,10 @@ void test2 (const struct {int a;} *x) {
typedef int arr[10];
void test3() {
- const arr b;
- const int b2[10];
- b[4] = 1; // expected-error {{read-only variable is not assignable}}
- b2[4] = 1; // expected-error {{read-only variable is not assignable}}
+ const arr b; // expected-note {{variable 'b' declared const here}}
+ const int b2[10]; // expected-note {{variable 'b2' declared const here}}
+ b[4] = 1; // expected-error {{cannot assign to variable 'b' with const-qualified type 'const arr' (aka 'int const[10]')}}
+ b2[4] = 1; // expected-error {{cannot assign to variable 'b2' with const-qualified type 'const int [10]'}}
}
typedef struct I {
diff --git a/test/Sema/ast-print.c b/test/Sema/ast-print.c
index f701b1220953..7f675206e58b 100644
--- a/test/Sema/ast-print.c
+++ b/test/Sema/ast-print.c
@@ -1,5 +1,14 @@
-// RUN: %clang_cc1 %s -ast-print | FileCheck %s
-// RUN: %clang_cc1 %s -ast-print | %clang_cc1 -fsyntax-only -
+// RUN: %clang_cc1 %s -ast-print -verify > %t.c
+// RUN: FileCheck %s --input-file %t.c
+//
+// RUN: echo >> %t.c "// expected""-warning@* {{use of GNU old-style field designator extension}}"
+// RUN: echo >> %t.c "// expected""-warning@* {{'EnumWithAttributes' is deprecated}}"
+// RUN: echo >> %t.c "// expected""-note@* {{'EnumWithAttributes' has been explicitly marked deprecated here}}"
+// RUN: echo >> %t.c "// expected""-warning@* {{'EnumWithAttributes2' is deprecated}}"
+// RUN: echo >> %t.c "// expected""-note@* {{'EnumWithAttributes2' has been explicitly marked deprecated here}}"
+// RUN: echo >> %t.c "// expected""-warning@* {{'EnumWithAttributes3' is deprecated}}"
+// RUN: echo >> %t.c "// expected""-note@* {{'EnumWithAttributes3' has been explicitly marked deprecated here}}"
+// RUN: %clang_cc1 -fsyntax-only %t.c -verify
typedef void func_typedef();
func_typedef xxx;
@@ -15,6 +24,10 @@ struct blah {
};
};
+// This used to crash clang.
+struct {
+}(s1);
+
int foo(const struct blah *b) {
// CHECK: return b->b;
return b->b;
@@ -54,7 +67,7 @@ struct pair_t {
};
// CHECK: struct pair_t p = {a: 3, .b = 4};
-struct pair_t p = {a: 3, .b = 4};
+struct pair_t p = {a: 3, .b = 4}; // expected-warning {{use of GNU old-style field designator extension}}
void initializers() {
// CHECK: int *x = ((void *)0), *y = ((void *)0);
@@ -66,11 +79,28 @@ void initializers() {
} z = {(struct Z){}};
}
-// CHECK-LABEL: enum EnumWithAttributes {
-enum EnumWithAttributes {
+// CHECK-LABEL: enum __attribute__((deprecated(""))) EnumWithAttributes {
+enum EnumWithAttributes { // expected-warning {{'EnumWithAttributes' is deprecated}}
// CHECK-NEXT: EnumWithAttributesFoo __attribute__((deprecated(""))),
EnumWithAttributesFoo __attribute__((deprecated)),
// CHECK-NEXT: EnumWithAttributesBar __attribute__((unavailable(""))) = 50
EnumWithAttributesBar __attribute__((unavailable)) = 50
- // CHECK-NEXT: } __attribute__((deprecated("")))
-} __attribute__((deprecated));
+ // CHECK-NEXT: } *EnumWithAttributesPtr;
+} __attribute__((deprecated)) *EnumWithAttributesPtr; // expected-note {{'EnumWithAttributes' has been explicitly marked deprecated here}}
+
+// CHECK-LABEL: enum __attribute__((deprecated(""))) EnumWithAttributes2 *EnumWithAttributes2Ptr;
+// expected-warning@+2 {{'EnumWithAttributes2' is deprecated}}
+// expected-note@+1 {{'EnumWithAttributes2' has been explicitly marked deprecated here}}
+enum __attribute__((deprecated)) EnumWithAttributes2 *EnumWithAttributes2Ptr;
+
+// CHECK-LABEL: EnumWithAttributes3Fn
+void EnumWithAttributes3Fn() {
+ // CHECK-NEXT: enum __attribute__((deprecated(""))) EnumWithAttributes3 *EnumWithAttributes3Ptr;
+ // expected-warning@+2 {{'EnumWithAttributes3' is deprecated}}
+ // expected-note@+1 {{'EnumWithAttributes3' has been explicitly marked deprecated here}}
+ enum __attribute__((deprecated)) EnumWithAttributes3 *EnumWithAttributes3Ptr;
+ // Printing must not put the attribute after the tag where it would apply to
+ // the variable instead of the type, and then our deprecation warning would
+ // move to this use of the variable.
+ void *p = EnumWithAttributes3Ptr;
+}
diff --git a/test/Sema/atomic-ops.c b/test/Sema/atomic-ops.c
index eee1cda8635e..49310bf45b68 100644
--- a/test/Sema/atomic-ops.c
+++ b/test/Sema/atomic-ops.c
@@ -173,6 +173,9 @@ void f(_Atomic(int) *i, const _Atomic(int) *ci,
__atomic_fetch_sub(P, 3, memory_order_seq_cst);
__atomic_fetch_sub(D, 3, memory_order_seq_cst); // expected-error {{must be a pointer to integer or pointer}}
__atomic_fetch_sub(s1, 3, memory_order_seq_cst); // expected-error {{must be a pointer to integer or pointer}}
+ __atomic_fetch_min(D, 3, memory_order_seq_cst); // expected-error {{must be a pointer to signed or unsigned 32-bit integer}}
+ __atomic_fetch_max(P, 3, memory_order_seq_cst); // expected-error {{must be a pointer to signed or unsigned 32-bit integer}}
+ __atomic_fetch_max(p, 3); // expected-error {{too few arguments to function call, expected 3, have 2}}
__c11_atomic_fetch_and(i, 1, memory_order_seq_cst);
__c11_atomic_fetch_and(p, 1, memory_order_seq_cst); // expected-error {{must be a pointer to atomic integer}}
@@ -456,6 +459,20 @@ void memory_checks(_Atomic(int) *Ap, int *p, int val) {
(void)__atomic_fetch_nand(p, val, memory_order_acq_rel);
(void)__atomic_fetch_nand(p, val, memory_order_seq_cst);
+ (void)__atomic_fetch_min(p, val, memory_order_relaxed);
+ (void)__atomic_fetch_min(p, val, memory_order_acquire);
+ (void)__atomic_fetch_min(p, val, memory_order_consume);
+ (void)__atomic_fetch_min(p, val, memory_order_release);
+ (void)__atomic_fetch_min(p, val, memory_order_acq_rel);
+ (void)__atomic_fetch_min(p, val, memory_order_seq_cst);
+
+ (void)__atomic_fetch_max(p, val, memory_order_relaxed);
+ (void)__atomic_fetch_max(p, val, memory_order_acquire);
+ (void)__atomic_fetch_max(p, val, memory_order_consume);
+ (void)__atomic_fetch_max(p, val, memory_order_release);
+ (void)__atomic_fetch_max(p, val, memory_order_acq_rel);
+ (void)__atomic_fetch_max(p, val, memory_order_seq_cst);
+
(void)__atomic_and_fetch(p, val, memory_order_relaxed);
(void)__atomic_and_fetch(p, val, memory_order_acquire);
(void)__atomic_and_fetch(p, val, memory_order_consume);
@@ -513,9 +530,146 @@ void memory_checks(_Atomic(int) *Ap, int *p, int val) {
(void)__atomic_compare_exchange_n(p, p, val, 0, memory_order_seq_cst, memory_order_relaxed);
}
-void nullPointerWarning(_Atomic(int) *Ap, int *p, int val) {
- // The 'expected' pointer shouldn't be NULL.
- (void)__c11_atomic_compare_exchange_strong(Ap, NULL, val, memory_order_relaxed, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
- (void)atomic_compare_exchange_weak(Ap, ((void*)0), val); // expected-warning {{null passed to a callee that requires a non-null argument}}
- (void)__atomic_compare_exchange_n(p, NULL, val, 0, memory_order_relaxed, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+void nullPointerWarning() {
+ volatile _Atomic(int) vai;
+ _Atomic(int) ai;
+ volatile int vi = 42;
+ int i = 42;
+ volatile _Atomic(int*) vap;
+ _Atomic(int*) ap;
+ volatile int* vp = NULL;
+ int* p = NULL;
+
+ __c11_atomic_init((volatile _Atomic(int)*)0, 42); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ __c11_atomic_init((_Atomic(int)*)0, 42); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ __c11_atomic_store((volatile _Atomic(int)*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ __c11_atomic_store((_Atomic(int)*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__c11_atomic_load((volatile _Atomic(int)*)0, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__c11_atomic_load((_Atomic(int)*)0, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__c11_atomic_exchange((volatile _Atomic(int)*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__c11_atomic_exchange((_Atomic(int)*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__c11_atomic_compare_exchange_weak((volatile _Atomic(int)*)0, &i, 42, memory_order_relaxed, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__c11_atomic_compare_exchange_weak((_Atomic(int)*)0, &i, 42, memory_order_relaxed, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__c11_atomic_compare_exchange_weak(&vai, (int*)0, 42, memory_order_relaxed, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__c11_atomic_compare_exchange_weak(&ai, (int*)0, 42, memory_order_relaxed, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__c11_atomic_compare_exchange_strong((volatile _Atomic(int)*)0, &i, 42, memory_order_relaxed, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__c11_atomic_compare_exchange_strong((_Atomic(int)*)0, &i, 42, memory_order_relaxed, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__c11_atomic_compare_exchange_strong(&vai, (int*)0, 42, memory_order_relaxed, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__c11_atomic_compare_exchange_strong(&ai, (int*)0, 42, memory_order_relaxed, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__c11_atomic_fetch_add((volatile _Atomic(int)*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__c11_atomic_fetch_add((_Atomic(int)*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__c11_atomic_fetch_sub((volatile _Atomic(int)*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__c11_atomic_fetch_sub((_Atomic(int)*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__c11_atomic_fetch_and((volatile _Atomic(int)*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__c11_atomic_fetch_and((_Atomic(int)*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__c11_atomic_fetch_or((volatile _Atomic(int)*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__c11_atomic_fetch_or((_Atomic(int)*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__c11_atomic_fetch_xor((volatile _Atomic(int)*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__c11_atomic_fetch_xor((_Atomic(int)*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+
+ __atomic_store_n((volatile int*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ __atomic_store_n((int*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ __atomic_store((volatile int*)0, &i, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ __atomic_store((int*)0, &i, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ __atomic_store(&vi, (int*)0, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ __atomic_store(&i, (int*)0, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_load_n((volatile int*)0, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_load_n((int*)0, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ __atomic_load((volatile int*)0, &i, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ __atomic_load((int*)0, &i, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ __atomic_load(&vi, (int*)0, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ __atomic_load(&i, (int*)0, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_exchange_n((volatile int*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_exchange_n((int*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ __atomic_exchange((volatile int*)0, &i, &i, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ __atomic_exchange((int*)0, &i, &i, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ __atomic_exchange(&vi, (int*)0, &i, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ __atomic_exchange(&i, (int*)0, &i, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ __atomic_exchange(&vi, &i, (int*)0, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ __atomic_exchange(&i, &i, (int*)0, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_compare_exchange_n((volatile int*)0, &i, 42, /*weak=*/0, memory_order_relaxed, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_compare_exchange_n((int*)0, &i, 42, /*weak=*/0, memory_order_relaxed, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_compare_exchange_n(&vi, (int*)0, 42, /*weak=*/0, memory_order_relaxed, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_compare_exchange_n(&i, (int*)0, 42, /*weak=*/0, memory_order_relaxed, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_compare_exchange((volatile int*)0, &i, &i, /*weak=*/0, memory_order_relaxed, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_compare_exchange((int*)0, &i, &i, /*weak=*/0, memory_order_relaxed, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_compare_exchange(&vi, (int*)0, &i, /*weak=*/0, memory_order_relaxed, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_compare_exchange(&i, (int*)0, &i, /*weak=*/0, memory_order_relaxed, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_compare_exchange(&vi, &i, (int*)0, /*weak=*/0, memory_order_relaxed, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_compare_exchange(&i, &i, (int*)0, /*weak=*/0, memory_order_relaxed, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_fetch_add((volatile int*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_fetch_add((int*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_fetch_sub((volatile int*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_fetch_sub((int*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_fetch_and((volatile int*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_fetch_and((int*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_fetch_or((volatile int*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_fetch_or((int*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_fetch_xor((volatile int*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_fetch_xor((int*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_fetch_min((volatile int*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_fetch_min((int*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_fetch_max((volatile int*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_fetch_max((int*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+
+ // These don't warn: the "desired" parameter is passed by value. Even for
+ // atomic pointers the "desired" result can be NULL.
+ __c11_atomic_init(&vai, 0);
+ __c11_atomic_init(&ai, 0);
+ __c11_atomic_init(&vap, NULL);
+ __c11_atomic_init(&ap, NULL);
+ __c11_atomic_store(&vai, 0, memory_order_relaxed);
+ __c11_atomic_store(&ai, 0, memory_order_relaxed);
+ __c11_atomic_store(&vap, NULL, memory_order_relaxed);
+ __c11_atomic_store(&ap, NULL, memory_order_relaxed);
+ (void)__c11_atomic_exchange(&vai, 0, memory_order_relaxed);
+ (void)__c11_atomic_exchange(&ai, 0, memory_order_relaxed);
+ (void)__c11_atomic_exchange(&vap, NULL, memory_order_relaxed);
+ (void)__c11_atomic_exchange(&ap, NULL, memory_order_relaxed);
+ (void)__c11_atomic_compare_exchange_weak(&vai, &i, 0, memory_order_relaxed, memory_order_relaxed);
+ (void)__c11_atomic_compare_exchange_weak(&ai, &i, 0, memory_order_relaxed, memory_order_relaxed);
+ (void)__c11_atomic_compare_exchange_weak(&vap, &p, NULL, memory_order_relaxed, memory_order_relaxed);
+ (void)__c11_atomic_compare_exchange_weak(&ap, &p, NULL, memory_order_relaxed, memory_order_relaxed);
+ (void)__c11_atomic_compare_exchange_strong(&vai, &i, 0, memory_order_relaxed, memory_order_relaxed);
+ (void)__c11_atomic_compare_exchange_strong(&ai, &i, 0, memory_order_relaxed, memory_order_relaxed);
+ (void)__c11_atomic_compare_exchange_strong(&vap, &p, NULL, memory_order_relaxed, memory_order_relaxed);
+ (void)__c11_atomic_compare_exchange_strong(&ap, &p, NULL, memory_order_relaxed, memory_order_relaxed);
+ (void)__c11_atomic_fetch_add(&vai, 0, memory_order_relaxed);
+ (void)__c11_atomic_fetch_add(&ai, 0, memory_order_relaxed);
+ (void)__c11_atomic_fetch_sub(&vai, 0, memory_order_relaxed);
+ (void)__c11_atomic_fetch_sub(&ai, 0, memory_order_relaxed);
+ (void)__c11_atomic_fetch_and(&vai, 0, memory_order_relaxed);
+ (void)__c11_atomic_fetch_and(&ai, 0, memory_order_relaxed);
+ (void)__c11_atomic_fetch_or(&vai, 0, memory_order_relaxed);
+ (void)__c11_atomic_fetch_or(&ai, 0, memory_order_relaxed);
+ (void)__c11_atomic_fetch_xor(&vai, 0, memory_order_relaxed);
+ (void)__c11_atomic_fetch_xor(&ai, 0, memory_order_relaxed);
+
+ // Ditto.
+ __atomic_store_n(&vi, 0, memory_order_relaxed);
+ __atomic_store_n(&i, 0, memory_order_relaxed);
+ __atomic_store_n(&vp, NULL, memory_order_relaxed);
+ __atomic_store_n(&p, NULL, memory_order_relaxed);
+ (void)__atomic_exchange_n(&vi, 0, memory_order_relaxed);
+ (void)__atomic_exchange_n(&i, 0, memory_order_relaxed);
+ (void)__atomic_exchange_n(&vp, NULL, memory_order_relaxed);
+ (void)__atomic_exchange_n(&p, NULL, memory_order_relaxed);
+ (void)__atomic_compare_exchange_n(&vi, &i, 0, /*weak=*/0, memory_order_relaxed, memory_order_relaxed);
+ (void)__atomic_compare_exchange_n(&i, &i, 0, /*weak=*/0, memory_order_relaxed, memory_order_relaxed);
+ (void)__atomic_compare_exchange_n(&vp, &vp, NULL, /*weak=*/0, memory_order_relaxed, memory_order_relaxed);
+ (void)__atomic_compare_exchange_n(&p, &p, NULL, /*weak=*/0, memory_order_relaxed, memory_order_relaxed);
+ (void)__atomic_fetch_add(&vi, 0, memory_order_relaxed);
+ (void)__atomic_fetch_add(&i, 0, memory_order_relaxed);
+ (void)__atomic_fetch_sub(&vi, 0, memory_order_relaxed);
+ (void)__atomic_fetch_sub(&i, 0, memory_order_relaxed);
+ (void)__atomic_fetch_and(&vi, 0, memory_order_relaxed);
+ (void)__atomic_fetch_and(&i, 0, memory_order_relaxed);
+ (void)__atomic_fetch_or(&vi, 0, memory_order_relaxed);
+ (void)__atomic_fetch_or(&i, 0, memory_order_relaxed);
+ (void)__atomic_fetch_xor(&vi, 0, memory_order_relaxed);
+ (void)__atomic_fetch_xor(&i, 0, memory_order_relaxed);
+ (void)__atomic_fetch_min(&vi, 0, memory_order_relaxed);
+ (void)__atomic_fetch_min(&i, 0, memory_order_relaxed);
+ (void)__atomic_fetch_max(&vi, 0, memory_order_relaxed);
+ (void)__atomic_fetch_max(&i, 0, memory_order_relaxed);
}
diff --git a/test/Sema/attr-availability-square-brackets.c b/test/Sema/attr-availability-square-brackets.c
new file mode 100644
index 000000000000..13dbf0abb17f
--- /dev/null
+++ b/test/Sema/attr-availability-square-brackets.c
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fsyntax-only -fdouble-square-bracket-attributes -verify %s
+
+void f0() [[clang::availability(macosx,introduced=10.4,deprecated=10.2)]]; // expected-warning{{feature cannot be deprecated in macOS version 10.2 before it was introduced in version 10.4; attribute ignored}}
+void f1() [[clang::availability(ios,obsoleted=2.1,deprecated=3.0)]]; // expected-warning{{feature cannot be obsoleted in iOS version 2.1 before it was deprecated in version 3.0; attribute ignored}}
+void f2() [[clang::availability(ios,introduced=2.1,deprecated=2.1)]];
+
+extern void
+ATSFontGetName(const char *oName) [[clang::availability(macosx,introduced=8.0,deprecated=9.0, message="use CTFontCopyFullName")]]; // expected-note {{'ATSFontGetName' has been explicitly marked deprecated here}}
+
+void test_10095131() {
+ ATSFontGetName("Hello"); // expected-warning {{'ATSFontGetName' is deprecated: first deprecated in macOS 9.0 - use CTFontCopyFullName}}
+}
+
+enum
+[[clang::availability(macos, unavailable)]]
+{
+ NSDataWritingFileProtectionWriteOnly = 0x30000000,
+ NSDataWritingFileProtectionCompleteUntilUserAuthentication = 0x40000000,
+};
+
+extern int x [[clang::availability(macosx,introduced=10.5)]];
+extern int x;
+
+int i [[clang::availability(this, should = 1.0)]]; // expected-error {{'should' is not an availability stage; use 'introduced', 'deprecated', or 'obsoleted'}} \
+ // expected-warning {{unknown platform 'this' in availability macro}}
diff --git a/test/Sema/attr-availability-tvos.c b/test/Sema/attr-availability-tvos.c
index d53d6ac8edc4..68337e49ce44 100644
--- a/test/Sema/attr-availability-tvos.c
+++ b/test/Sema/attr-availability-tvos.c
@@ -53,7 +53,7 @@ void test_tvos() {
f3_tvos(0);
f4_tvos(0); // expected-error{{'f4_tvos' is unavailable: obsoleted in tvOS 3.0}}
// We get no warning here because any explicit 'tvos' availability causes
- // the ios availablity to not implicitly become 'tvos' availability. Otherwise we'd get
+ // the ios availability to not implicitly become 'tvos' availability. Otherwise we'd get
// a deprecated warning.
f5_tvos(0); // no-warning
f5_attr_reversed_tvos(0); // no-warning
diff --git a/test/Sema/attr-availability-watchos.c b/test/Sema/attr-availability-watchos.c
index ec7f3a7d3afd..59233986ee46 100644
--- a/test/Sema/attr-availability-watchos.c
+++ b/test/Sema/attr-availability-watchos.c
@@ -42,7 +42,7 @@ void test_watchos() {
f3_watchos(0);
f4_watchos(0); // expected-error{{'f4_watchos' is unavailable: obsoleted in watchOS 3.0}}
// We get no warning here because any explicit 'watchos' availability causes
- // the ios availablity to not implicitly become 'watchos' availability. Otherwise we'd get
+ // the ios availability to not implicitly become 'watchos' availability. Otherwise we'd get
// a deprecated warning.
f5_watchos(0); // no-warning
f5_attr_reversed_watchos(0); // no-warning
diff --git a/test/Sema/attr-cpuspecific.c b/test/Sema/attr-cpuspecific.c
new file mode 100644
index 000000000000..91063c1c5b8a
--- /dev/null
+++ b/test/Sema/attr-cpuspecific.c
@@ -0,0 +1,96 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -verify %s
+
+void __attribute__((cpu_specific(ivybridge))) no_default(void);
+void __attribute__((cpu_specific(sandybridge))) no_default(void);
+
+void use1(void){
+ // Should be OK, default not a problem.
+ no_default();
+}
+
+int __attribute__((cpu_specific(atom))) addr_of(void);
+int __attribute__((cpu_specific(ivybridge))) addr_of(void);
+int __attribute__((cpu_specific(ivybridge))) addr_of2(void);
+
+void use2(void){
+ addr_of();
+ addr_of2();
+ // expected-error@+1{{reference to multiversioned function could not be resolved; did you mean to call it with no arguments?}}
+ (void)+addr_of;
+ // expected-error@+1{{reference to multiversioned function could not be resolved; did you mean to call it with no arguments?}}
+ (void)+addr_of2;
+ // expected-error@+1{{reference to multiversioned function could not be resolved; did you mean to call it with no arguments?}}
+ (void)&addr_of;
+ // expected-error@+1{{reference to multiversioned function could not be resolved; did you mean to call it with no arguments?}}
+ (void)&addr_of2;
+}
+
+// expected-error@+1 {{multiversioned function must have a prototype}}
+int __attribute__((cpu_specific(atom))) no_proto();
+
+int __attribute__((cpu_specific(atom))) redecl1(void);
+int __attribute__((cpu_specific(atom))) redecl1(void) { return 1; }
+
+int __attribute__((cpu_dispatch(atom))) redecl2(void);
+int __attribute__((cpu_dispatch(atom))) redecl2(void) { }
+// expected-error@+2 {{redefinition of 'redecl2'}}
+// expected-note@-2 {{previous definition is here}}
+int __attribute__((cpu_dispatch(atom))) redecl2(void) { }
+
+int redecl3(void);
+// expected-error@-1 {{function declaration is missing 'cpu_specific' or 'cpu_dispatch' attribute in a multiversioned function}}
+// expected-note@+1 {{function multiversioning caused by this declaration}}
+int __attribute__((cpu_dispatch(atom))) redecl3(void) {}
+
+int __attribute__((cpu_specific(atom))) redecl4(void);
+// expected-error@+1 {{function declaration is missing 'cpu_specific' or 'cpu_dispatch' attribute in a multiversioned function}}
+int redecl4(void);
+
+// expected-warning@+1 {{CPU list contains duplicate entries; attribute ignored}}
+int __attribute__((cpu_specific(atom, atom))) dup_procs(void);
+
+int __attribute__((cpu_specific(ivybridge, atom))) dup_procs2(void);
+// expected-error@+2 {{multiple 'cpu_specific' functions cannot specify the same CPU: 'atom'}}
+// expected-note@-2 {{previous declaration is here}}
+int __attribute__((cpu_specific(atom))) dup_procs2(void);
+
+int __attribute__((cpu_specific(ivybridge, atom))) dup_procs3(void);
+// expected-error@+2 {{multiple 'cpu_specific' functions cannot specify the same CPU: 'ivybridge'}}
+// expected-note@-2 {{previous declaration is here}}
+int __attribute__((cpu_specific(atom, ivybridge))) dup_procs3(void);
+
+int __attribute__((cpu_specific(atom))) redef(void) { return 1; }
+// expected-error@+2 {{redefinition of 'redef'}}
+// expected-note@-2 {{previous definition is here}}
+int __attribute__((cpu_specific(atom))) redef(void) { return 2; }
+
+int __attribute((cpu_dispatch(atom))) mult_dispatch(void) {}
+// expected-error@+2 {{'cpu_dispatch' function redeclared with different CPUs}}
+// expected-note@-2 {{previous declaration is here}}
+int __attribute((cpu_dispatch(ivybridge))) mult_dispatch(void) {}
+
+// expected-error@+1 {{'cpu_dispatch' attribute takes at least 1 argument}}
+int __attribute((cpu_dispatch())) no_dispatch(void) {}
+// expected-error@+1 {{'cpu_specific' attribute takes at least 1 argument}}
+int __attribute((cpu_specific())) no_specific(void) {}
+
+//expected-error@+1 {{attribute 'cpu_specific' multiversioning cannot be combined}}
+void __attribute__((used,cpu_specific(sandybridge))) addtl_attrs(void);
+
+void __attribute__((target("default"))) addtl_attrs2(void);
+// expected-error@+2 {{multiversioning attributes cannot be combined}}
+// expected-note@-2 {{previous declaration is here}}
+void __attribute__((cpu_specific(sandybridge))) addtl_attrs2(void);
+
+// expected-error@+2 {{multiversioning attributes cannot be combined}}
+void __attribute((cpu_specific(sandybridge), cpu_dispatch(atom, sandybridge)))
+combine_attrs(void);
+
+int __attribute__((cpu_dispatch(ivybridge))) diff_cc(void){}
+// expected-error@+1 {{multiversioned function declaration has a different calling convention}}
+__vectorcall int __attribute__((cpu_specific(sandybridge))) diff_cc(void);
+
+// expected-warning@+2 {{body of cpu_dispatch function will be ignored}}
+int __attribute__((cpu_dispatch(atom))) disp_with_body(void) {
+ return 5;
+}
diff --git a/test/Sema/attr-cx2.c b/test/Sema/attr-cx2.c
new file mode 100644
index 000000000000..5b537625c129
--- /dev/null
+++ b/test/Sema/attr-cx2.c
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -fdouble-square-bracket-attributes %s
+
+struct S {};
+struct S * [[clang::address_space(1)]] Foo;
+
+enum [[clang::enum_extensibility(open)]] EnumOpen {
+ C0 = 1, C1 = 10
+};
+
+enum [[clang::flag_enum]] EnumFlag {
+ D0 = 1, D1 = 8
+};
+
+void foo(void *c) [[clang::overloadable]];
+void foo(char *c) [[clang::overloadable]];
+
+void context_okay(void *context [[clang::swift_context]]) [[clang::swiftcall]];
+void context_okay2(void *context [[clang::swift_context]], void *selfType, char **selfWitnessTable) [[clang::swiftcall]];
+
+void *f1(void) [[clang::ownership_returns(foo)]];
+void *f2() [[clang::ownership_returns(foo)]]; // expected-warning {{'ownership_returns' attribute only applies to non-K&R-style functions}}
+
+void foo2(void) [[clang::unavailable("not available - replaced")]]; // expected-note {{'foo2' has been explicitly marked unavailable here}}
+void bar(void) {
+ foo2(); // expected-error {{'foo2' is unavailable: not available - replaced}}
+}
diff --git a/test/Sema/attr-external-source-symbol.c b/test/Sema/attr-external-source-symbol.c
index af6e6bc79e7b..dfed609c8e87 100644
--- a/test/Sema/attr-external-source-symbol.c
+++ b/test/Sema/attr-external-source-symbol.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -fblocks -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fblocks -verify -fdouble-square-bracket-attributes %s
void threeClauses() __attribute__((external_source_symbol(language="Swift", defined_in="module", generated_declaration)));
@@ -17,3 +17,15 @@ void namedDeclsOnly() {
return 1;
};
}
+
+void threeClauses2() [[clang::external_source_symbol(language="Swift", defined_in="module", generated_declaration)]];
+
+void twoClauses2() [[clang::external_source_symbol(language="Swift", defined_in="module")]];
+
+void fourClauses2()
+[[clang::external_source_symbol(language="Swift", defined_in="module", generated_declaration, generated_declaration)]]; // expected-error {{duplicate 'generated_declaration' clause in an 'external_source_symbol' attribute}}
+
+void oneClause2() [[clang::external_source_symbol(generated_declaration)]];
+
+void noArguments2()
+[[clang::external_source_symbol]]; // expected-error {{'external_source_symbol' attribute takes at least 1 argument}}
diff --git a/test/Sema/attr-format_arg.c b/test/Sema/attr-format_arg.c
index 64a23878317c..e041c5acbffa 100644
--- a/test/Sema/attr-format_arg.c
+++ b/test/Sema/attr-format_arg.c
@@ -4,10 +4,27 @@ int printf(const char *, ...);
const char* f(const char *s) __attribute__((format_arg(1)));
+const char *h(const char *msg1, const char *msg2)
+ __attribute__((__format_arg__(1))) __attribute__((__format_arg__(2)));
+
void g(const char *s) {
printf("%d", 123);
printf("%d %d", 123); // expected-warning{{more '%' conversions than data arguments}}
printf(f("%d"), 123);
printf(f("%d %d"), 123); // expected-warning{{more '%' conversions than data arguments}}
+
+ printf(h(
+ "", // expected-warning {{format string is empty}}
+ "" // expected-warning {{format string is empty}}
+ ), 123);
+ printf(h(
+ "%d",
+ "" // expected-warning {{format string is empty}}
+ ), 123);
+ printf(h(
+ "", // expected-warning {{format string is empty}}
+ "%d"
+ ), 123);
+ printf(h("%d", "%d"), 123);
}
diff --git a/test/Sema/attr-ifunc.c b/test/Sema/attr-ifunc.c
index 16fd0dfc9820..af7a7e33da09 100644
--- a/test/Sema/attr-ifunc.c
+++ b/test/Sema/attr-ifunc.c
@@ -36,7 +36,7 @@ void f1a() __asm("f1");
void f1a() {}
//expected-note@-1 {{previous definition is here}}
void f1() __attribute__((ifunc("f1_ifunc")));
-//expected-error@-1 {{definition with same mangled name as another definition}}
+//expected-error@-1 {{definition with same mangled name 'f1' as another definition}}
void* f1_ifunc() { return 0; }
void* f6_ifunc(int i);
diff --git a/test/Sema/attr-min-vector-width.c b/test/Sema/attr-min-vector-width.c
new file mode 100644
index 000000000000..0e6f84a672f2
--- /dev/null
+++ b/test/Sema/attr-min-vector-width.c
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify %s
+
+int i;
+void f(void) __attribute__((__min_vector_width__(i))); /* expected-error {{'__min_vector_width__' attribute requires an integer constant}} */
+
+void f2(void) __attribute__((__min_vector_width__(128)));
+
+void f3(void) __attribute__((__min_vector_width__(128), __min_vector_width__(256))); /* expected-warning {{attribute '__min_vector_width__' is already applied with different parameters}} */
+
+void f4(void) __attribute__((__min_vector_width__())); /* expected-error {{'__min_vector_width__' attribute takes one argument}} */
+
+void f5(void) __attribute__((__min_vector_width__(128, 256))); /* expected-error {{'__min_vector_width__' attribute takes one argument}} */
+
+void f6(void) {
+ int x __attribute__((__min_vector_width__(128))) = 0; /* expected-error {{'__min_vector_width__' attribute only applies to functions}} */
+}
diff --git a/test/Sema/attr-nocf_check.c b/test/Sema/attr-nocf_check.c
new file mode 100644
index 000000000000..9ca1bb173439
--- /dev/null
+++ b/test/Sema/attr-nocf_check.c
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -triple=x86_64-unknown-unknown -verify -fcf-protection=branch -fsyntax-only %s
+
+// Function pointer definition.
+typedef void (*FuncPointerWithNoCfCheck)(void) __attribute__((nocf_check)); // no-warning
+typedef void (*FuncPointer)(void);
+
+// Dont allow function declaration and definition mismatch.
+void __attribute__((nocf_check)) testNoCfCheck(); // expected-note {{previous declaration is here}}
+void testNoCfCheck(){}; // expected-error {{conflicting types for 'testNoCfCheck'}}
+
+// No variable or parameter declaration
+__attribute__((nocf_check)) int i; // expected-warning {{'nocf_check' attribute only applies to function}}
+void testNoCfCheckImpl(double __attribute__((nocf_check)) i) {} // expected-warning {{'nocf_check' attribute only applies to function}}
+
+// Allow attributed function pointers as well as casting between attributed
+// and non-attributed function pointers.
+void testNoCfCheckMismatch(FuncPointer f) {
+ FuncPointerWithNoCfCheck fNoCfCheck = f; // expected-warning {{incompatible function pointer types}}
+ (*fNoCfCheck)(); // no-warning
+}
+
+// 'nocf_check' Attribute has no parameters.
+int testNoCfCheckParams() __attribute__((nocf_check(1))); // expected-error {{'nocf_check' attribute takes no arguments}}
diff --git a/test/Sema/attr-nocf_check.cpp b/test/Sema/attr-nocf_check.cpp
new file mode 100644
index 000000000000..e306c8ef79cd
--- /dev/null
+++ b/test/Sema/attr-nocf_check.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -triple=i386-unknown-unknown -verify -fcf-protection=branch -std=c++11 -fsyntax-only %s
+
+// Function pointer definition.
+[[gnu::nocf_check]] typedef void (*FuncPointerWithNoCfCheck)(void); // no-warning
+typedef void (*FuncPointer)(void);
+
+// Dont allow function declaration and definition mismatch.
+[[gnu::nocf_check]] void testNoCfCheck(); // expected-note {{previous declaration is here}}
+void testNoCfCheck(){}; // expected-error {{conflicting types for 'testNoCfCheck'}}
+
+// No variable or parameter declaration
+int [[gnu::nocf_check]] i; // expected-error {{'nocf_check' attribute cannot be applied to types}}
+void testNoCfCheckImpl(double i [[gnu::nocf_check]]) {} // expected-warning {{'nocf_check' attribute only applies to functions and function pointers}}
+
+// Allow attributed function pointers as well as casting between attributed
+// and non-attributed function pointers.
+void testNoCfCheckMismatch(FuncPointer f) {
+ FuncPointerWithNoCfCheck fNoCfCheck = f; // expected-error {{cannot initialize a variable of type}}
+ (*fNoCfCheck)(); // no-warning
+}
+
+// 'nocf_check' Attribute has no parameters.
+[[gnu::nocf_check(1)]] int testNoCfCheckParams(); // expected-error {{'nocf_check' attribute takes no arguments}}
diff --git a/test/Sema/attr-objc-bridge-related.m b/test/Sema/attr-objc-bridge-related.m
new file mode 100644
index 000000000000..bf059ba01860
--- /dev/null
+++ b/test/Sema/attr-objc-bridge-related.m
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -verify -fsyntax-only -fdouble-square-bracket-attributes %s
+
+struct [[clang::objc_bridge_related(NSParagraphStyle,,)]] TestBridgedRef;
+
+struct [[clang::objc_bridge_related(NSColor,colorWithCGColor:,CGColor)]] CGColorRefOk;
+struct [[clang::objc_bridge_related(,colorWithCGColor:,CGColor)]] CGColorRef1NotOk; // expected-error {{expected a related ObjectiveC class name, e.g., 'NSColor'}}
+struct [[clang::objc_bridge_related(NSColor,colorWithCGColor::,CGColor)]] CGColorRef3NotOk; // expected-error {{expected a class method selector with single argument, e.g., 'colorWithCGColor:'}}
diff --git a/test/Sema/attr-ownership.c b/test/Sema/attr-ownership.c
index fa21b0319b42..ff6c7197df8d 100644
--- a/test/Sema/attr-ownership.c
+++ b/test/Sema/attr-ownership.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -verify
+// RUN: %clang_cc1 %s -verify -fsyntax-only
void f1(void) __attribute__((ownership_takes("foo"))); // expected-error {{'ownership_takes' attribute requires parameter 1 to be an identifier}}
void *f2(void) __attribute__((ownership_returns(foo, 1, 2))); // expected-error {{'ownership_returns' attribute takes no more than 1 argument}}
diff --git a/test/Sema/attr-ownership.cpp b/test/Sema/attr-ownership.cpp
new file mode 100644
index 000000000000..cde195ff0aa8
--- /dev/null
+++ b/test/Sema/attr-ownership.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 %s -verify -fsyntax-only
+
+class C {
+ void f(int, int)
+ __attribute__((ownership_returns(foo, 2))) // expected-note {{declared with index 2 here}}
+ __attribute__((ownership_returns(foo, 3))); // expected-error {{'ownership_returns' attribute index does not match; here it is 3}}
+};
diff --git a/test/Sema/attr-print.c b/test/Sema/attr-print.c
index 7ffbbb800d51..16b440d5d73a 100644
--- a/test/Sema/attr-print.c
+++ b/test/Sema/attr-print.c
@@ -7,6 +7,9 @@ int x __attribute__((aligned(4)));
// CHECK: int y __declspec(align(4));
__declspec(align(4)) int y;
+// CHECK: short arr[3] __attribute__((aligned));
+short arr[3] __attribute__((aligned));
+
// CHECK: void foo() __attribute__((const));
void foo() __attribute__((const));
diff --git a/test/Sema/attr-target-ast.c b/test/Sema/attr-target-ast.c
new file mode 100644
index 000000000000..6e8497ea9c8d
--- /dev/null
+++ b/test/Sema/attr-target-ast.c
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -ast-dump %s | FileCheck %s
+
+int __attribute__((target("arch=hiss,arch=woof"))) pine_tree() { return 4; }
+// CHECK-NOT: arch=hiss
+// CHECK-NOT: arch=woof
diff --git a/test/Sema/attr-target-mv-bad-target.c b/test/Sema/attr-target-mv-bad-target.c
new file mode 100644
index 000000000000..9cf3c5e10a6b
--- /dev/null
+++ b/test/Sema/attr-target-mv-bad-target.c
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -triple x86_64-windows-pc -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple arm-none-eabi -fsyntax-only -verify %s
+
+int __attribute__((target("sse4.2"))) redecl1(void) { return 1; }
+//expected-error@+2 {{function multiversioning is not supported on the current target}}
+//expected-note@-2 {{previous declaration is here}}
+int __attribute__((target("avx"))) redecl1(void) { return 2; }
+
+//expected-error@+1 {{function multiversioning is not supported on the current target}}
+int __attribute__((target("default"))) with_def(void) { return 1;}
diff --git a/test/Sema/attr-target-mv.c b/test/Sema/attr-target-mv.c
new file mode 100644
index 000000000000..671adff5b042
--- /dev/null
+++ b/test/Sema/attr-target-mv.c
@@ -0,0 +1,103 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -verify %s
+
+void __attribute__((target("sse4.2"))) no_default(void);
+void __attribute__((target("arch=sandybridge"))) no_default(void);
+
+void use1(void){
+ // expected-error@+1 {{no matching function for call to 'no_default'}}
+ no_default();
+}
+
+void __attribute__((target("sse4.2"))) has_def(void);
+void __attribute__((target("default"))) has_def(void);
+
+void use2(void){
+ // expected-error@+2 {{reference to overloaded function could not be resolved; did you mean to call it?}}
+ // expected-note@-4 {{possible target for call}}
+ +has_def;
+}
+
+int __attribute__((target("sse4.2"))) no_proto();
+// expected-error@-1 {{multiversioned function must have a prototype}}
+// expected-note@+1 {{function multiversioning caused by this declaration}}
+int __attribute__((target("arch=sandybridge"))) no_proto();
+
+// The following should all be legal, since they are just redeclarations.
+int __attribute__((target("sse4.2"))) redecl1(void);
+int __attribute__((target("sse4.2"))) redecl1(void) { return 1; }
+int __attribute__((target("arch=sandybridge"))) redecl1(void) { return 2; }
+
+int __attribute__((target("sse4.2"))) redecl2(void) { return 1; }
+int __attribute__((target("sse4.2"))) redecl2(void);
+int __attribute__((target("arch=sandybridge"))) redecl2(void) { return 2; }
+
+int __attribute__((target("sse4.2"))) redecl3(void) { return 0; }
+int __attribute__((target("arch=ivybridge"))) redecl3(void) { return 1; }
+int __attribute__((target("arch=sandybridge"))) redecl3(void);
+int __attribute__((target("arch=sandybridge"))) redecl3(void) { return 2; }
+
+int __attribute__((target("sse4.2"))) redecl4(void) { return 1; }
+int __attribute__((target("arch=sandybridge"))) redecl4(void) { return 2; }
+int __attribute__((target("arch=sandybridge"))) redecl4(void);
+
+int __attribute__((target("sse4.2"))) redef(void) { return 1; }
+int __attribute__((target("arch=ivybridge"))) redef(void) { return 1; }
+int __attribute__((target("arch=sandybridge"))) redef(void) { return 2; }
+// expected-error@+2 {{redefinition of 'redef'}}
+// expected-note@-2 {{previous definition is here}}
+int __attribute__((target("arch=sandybridge"))) redef(void) { return 2; }
+
+int __attribute__((target("default"))) redef2(void) { return 1;}
+// expected-error@+2 {{redefinition of 'redef2'}}
+// expected-note@-2 {{previous definition is here}}
+int __attribute__((target("default"))) redef2(void) { return 1;}
+
+int __attribute__((target("sse4.2"))) mv_after_use(void) { return 1; }
+int use3(void) {
+ return mv_after_use();
+}
+
+// expected-error@+1 {{function declaration cannot become a multiversioned function after first usage}}
+int __attribute__((target("arch=sandybridge"))) mv_after_use(void) { return 2; }
+
+int __attribute__((target("sse4.2,arch=sandybridge"))) mangle(void) { return 1; }
+//expected-error@+2 {{multiversioned function redeclarations require identical target attributes}}
+//expected-note@-2 {{previous declaration is here}}
+int __attribute__((target("arch=sandybridge,sse4.2"))) mangle(void) { return 2; }
+
+int prev_no_target(void);
+int __attribute__((target("arch=sandybridge"))) prev_no_target(void) { return 2; }
+// expected-error@-2 {{function declaration is missing 'target' attribute in a multiversioned function}}
+// expected-note@+1 {{function multiversioning caused by this declaration}}
+int __attribute__((target("arch=ivybridge"))) prev_no_target(void) { return 2; }
+
+int __attribute__((target("arch=sandybridge"))) prev_no_target2(void);
+int prev_no_target2(void);
+// expected-error@-1 {{function declaration is missing 'target' attribute in a multiversioned function}}
+// expected-note@+1 {{function multiversioning caused by this declaration}}
+int __attribute__((target("arch=ivybridge"))) prev_no_target2(void);
+
+void __attribute__((target("sse4.2"))) addtl_attrs(void);
+//expected-error@+1 {{attribute 'target' multiversioning cannot be combined}}
+void __attribute__((used,target("arch=sandybridge"))) addtl_attrs(void);
+
+//expected-error@+1 {{attribute 'target' multiversioning cannot be combined}}
+void __attribute__((target("default"), used)) addtl_attrs2(void);
+
+//expected-error@+2 {{attribute 'target' multiversioning cannot be combined}}
+//expected-note@+2 {{function multiversioning caused by this declaration}}
+void __attribute__((used,target("sse4.2"))) addtl_attrs3(void);
+void __attribute__((target("arch=sandybridge"))) addtl_attrs3(void);
+
+void __attribute__((target("sse4.2"))) addtl_attrs4(void);
+void __attribute__((target("arch=sandybridge"))) addtl_attrs4(void);
+//expected-error@+1 {{attribute 'target' multiversioning cannot be combined}}
+void __attribute__((used,target("arch=ivybridge"))) addtl_attrs4(void);
+
+int __attribute__((target("sse4.2"))) diff_cc(void);
+// expected-error@+1 {{multiversioned function declaration has a different calling convention}}
+__vectorcall int __attribute__((target("arch=sandybridge"))) diff_cc(void);
+
+int __attribute__((target("sse4.2"))) diff_ret(void);
+// expected-error@+1 {{multiversioned function declaration has a different return type}}
+short __attribute__((target("arch=sandybridge"))) diff_ret(void);
diff --git a/test/Sema/attr-target-unsupported.c b/test/Sema/attr-target-unsupported.c
new file mode 100644
index 000000000000..8e23fcc17ebd
--- /dev/null
+++ b/test/Sema/attr-target-unsupported.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -triple mips-linux-gnu -fsyntax-only -verify %s
+
+void __attribute__((target("arch=mips1")))
+foo(void) {}
+// expected-error@+3 {{function multiversioning is not supported on the current target}}
+// expected-note@-2 {{previous declaration is here}}
+void __attribute__((target("arch=mips2")))
+foo(void) {}
+
+// expected-error@+2 {{function multiversioning is not supported on the current target}}
+void __attribute__((target("default")))
+bar(void){}
diff --git a/test/Sema/attr-target.c b/test/Sema/attr-target.c
index 058bfc421a19..644d7cb1604e 100644
--- a/test/Sema/attr-target.c
+++ b/test/Sema/attr-target.c
@@ -1,14 +1,21 @@
// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -verify %s
int __attribute__((target("avx,sse4.2,arch=ivybridge"))) foo() { return 4; }
-int __attribute__((target())) bar() { return 4; } //expected-error {{'target' attribute takes one argument}}
-int __attribute__((target("tune=sandybridge"))) baz() { return 4; } //expected-warning {{ignoring unsupported 'tune=' in the target attribute string}}
-int __attribute__((target("fpmath=387"))) walrus() { return 4; } //expected-warning {{ignoring unsupported 'fpmath=' in the target attribute string}}
-int __attribute__((target("avx,sse4.2,arch=hiss"))) meow() { return 4; }//expected-warning {{ignoring unsupported architecture 'hiss' in the target attribute string}}
-int __attribute__((target("woof"))) bark() { return 4; }//expected-warning {{ignoring unsupported 'woof' in the target attribute string}}
-int __attribute__((target("arch="))) turtle() { return 4; } // no warning, same as saying 'nothing'.
-int __attribute__((target("arch=hiss,arch=woof"))) pine_tree() { return 4; } //expected-warning {{ignoring unsupported architecture 'hiss' in the target attribute string}}
-int __attribute__((target("arch=ivybridge,arch=haswell"))) oak_tree() { return 4; } //expected-warning {{ignoring duplicate 'arch=' in the target attribute string}}
-
+//expected-error@+1 {{'target' attribute takes one argument}}
+int __attribute__((target())) bar() { return 4; }
+//expected-warning@+1 {{unsupported 'tune=' in the 'target' attribute string; 'target' attribute ignored}}
+int __attribute__((target("tune=sandybridge"))) baz() { return 4; }
+//expected-warning@+1 {{unsupported 'fpmath=' in the 'target' attribute string; 'target' attribute ignored}}
+int __attribute__((target("fpmath=387"))) walrus() { return 4; }
+//expected-warning@+1 {{unsupported architecture 'hiss' in the 'target' attribute string; 'target' attribute ignored}}
+int __attribute__((target("avx,sse4.2,arch=hiss"))) meow() { return 4; }
+//expected-warning@+1 {{unsupported 'woof' in the 'target' attribute string; 'target' attribute ignored}}
+int __attribute__((target("woof"))) bark() { return 4; }
+// no warning, same as saying 'nothing'.
+int __attribute__((target("arch="))) turtle() { return 4; }
+//expected-warning@+1 {{unsupported architecture 'hiss' in the 'target' attribute string; 'target' attribute ignored}}
+int __attribute__((target("arch=hiss,arch=woof"))) pine_tree() { return 4; }
+//expected-warning@+1 {{duplicate 'arch=' in the 'target' attribute string; 'target' attribute ignored}}
+int __attribute__((target("arch=ivybridge,arch=haswell"))) oak_tree() { return 4; }
diff --git a/test/Sema/attr-type-safety.c b/test/Sema/attr-type-safety.c
new file mode 100644
index 000000000000..d7dab5d30760
--- /dev/null
+++ b/test/Sema/attr-type-safety.c
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -fsyntax-only -fdouble-square-bracket-attributes -verify %s
+
+struct A {};
+
+typedef struct A *MPI_Datatype;
+
+extern struct A datatype_wrong1 [[clang::type_tag_for_datatype]]; // expected-error {{'type_tag_for_datatype' attribute requires parameter 1 to be an identifier}}
+
+extern struct A datatype_wrong2 [[clang::type_tag_for_datatype(mpi,1,2)]]; // expected-error {{expected a type}}
+
+extern struct A datatype_wrong3 [[clang::type_tag_for_datatype(mpi,not_a_type)]]; // expected-error {{unknown type name 'not_a_type'}}
+
+extern struct A datatype_wrong4 [[clang::type_tag_for_datatype(mpi,int,int)]]; // expected-error {{expected identifier}}
+
+extern struct A datatype_wrong5 [[clang::type_tag_for_datatype(mpi,int,not_a_flag)]]; // expected-error {{invalid comparison flag 'not_a_flag'}}
+
+extern struct A datatype_wrong6 [[clang::type_tag_for_datatype(mpi,int,layout_compatible,not_a_flag)]]; // expected-error {{invalid comparison flag 'not_a_flag'}}
+
+extern struct A A_tag [[clang::type_tag_for_datatype(a,int)]];
+extern struct A B_tag [[clang::type_tag_for_datatype(b,int)]];
+
+static const int C_tag [[clang::type_tag_for_datatype(c,int)]] = 10;
+static const int D_tag [[clang::type_tag_for_datatype(d,int)]] = 20;
+
+[[clang::pointer_with_type_tag]] // expected-error {{'pointer_with_type_tag' attribute requires exactly 3 arguments}}
+int wrong1(void *buf, MPI_Datatype datatype);
+
+[[clang::pointer_with_type_tag(mpi,0,7)]] // expected-error {{attribute parameter 2 is out of bounds}}
+int wrong2(void *buf, MPI_Datatype datatype);
+
+[[clang::pointer_with_type_tag(mpi,3,7)]] // expected-error {{attribute parameter 2 is out of bounds}}
+int wrong3(void *buf, MPI_Datatype datatype);
+
+[[clang::pointer_with_type_tag(mpi,1,0)]] // expected-error {{attribute parameter 3 is out of bounds}}
+int wrong4(void *buf, MPI_Datatype datatype);
+
+[[clang::pointer_with_type_tag(mpi,1,3)]] // expected-error {{attribute parameter 3 is out of bounds}}
+int wrong5(void *buf, MPI_Datatype datatype);
+
+[[clang::pointer_with_type_tag(mpi,0x8000000000000001ULL,1)]] // expected-error {{attribute parameter 2 is out of bounds}}
+int wrong6(void *buf, MPI_Datatype datatype);
+
+[[clang::pointer_with_type_tag(a,1,2)]] void A_func(void *ptr, void *tag);
+[[clang::pointer_with_type_tag(c,1,2)]] void C_func(void *ptr, int tag);
+
diff --git a/test/Sema/attr-used.c b/test/Sema/attr-used.c
index 4e3bda7609bb..c13d57c95e61 100644
--- a/test/Sema/attr-used.c
+++ b/test/Sema/attr-used.c
@@ -3,7 +3,7 @@
extern int l0 __attribute__((used)); // expected-warning {{'used' attribute ignored}}
__private_extern__ int l1 __attribute__((used)); // expected-warning {{'used' attribute ignored}}
-struct __attribute__((used)) s { // expected-warning {{'used' attribute only applies to variables and functions}}
+struct __attribute__((used)) s { // expected-warning {{'used' attribute only applies to variables with non-local storage, functions, and Objective-C methods}}
int x;
};
@@ -14,7 +14,7 @@ static void __attribute__((used)) f0(void) {
void f1() {
static int a __attribute__((used));
- int b __attribute__((used)); // expected-warning {{'used' attribute ignored}}
+ int b __attribute__((used)); // expected-warning {{'used' attribute only applies to variables with non-local storage, functions, and Objective-C methods}}
}
static void __attribute__((used)) f0(void);
diff --git a/test/Sema/attr-weak.c b/test/Sema/attr-weak.c
index e3610caba584..6f0c3d5523b3 100644
--- a/test/Sema/attr-weak.c
+++ b/test/Sema/attr-weak.c
@@ -1,7 +1,9 @@
// RUN: %clang_cc1 -verify -fsyntax-only %s
+extern int f0() __attribute__((weak));
extern int g0 __attribute__((weak));
extern int g1 __attribute__((weak_import));
+int f2() __attribute__((weak));
int g2 __attribute__((weak));
int g3 __attribute__((weak_import)); // expected-warning {{'weak_import' attribute cannot be specified on a definition}}
int __attribute__((weak_import)) g4(void);
@@ -11,6 +13,7 @@ void __attribute__((weak_import)) g5(void) {
struct __attribute__((weak)) s0 {}; // expected-warning {{'weak' attribute only applies to variables, functions, and classes}}
struct __attribute__((weak_import)) s1 {}; // expected-warning {{'weak_import' attribute only applies to variables and functions}}
+static int f() __attribute__((weak)); // expected-error {{weak declaration cannot have internal linkage}}
static int x __attribute__((weak)); // expected-error {{weak declaration cannot have internal linkage}}
// rdar://9538608
diff --git a/test/Sema/availability-guard-format.mm b/test/Sema/availability-guard-format.mm
new file mode 100644
index 000000000000..910de49ffc81
--- /dev/null
+++ b/test/Sema/availability-guard-format.mm
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -triple x86_64-apple-macosx-10.11 -Wunguarded-availability -fdiagnostics-parseable-fixits -fsyntax-only -verify %s
+
+// Testing that even for source code using '_' as a delimiter in availability version tuple '.' is actually used in diagnostic output as a delimiter.
+
+@interface foo
+- (void) method_bar __attribute__((availability(macosx, introduced = 10_12))); // expected-note {{'method_bar' has been explicitly marked partial here}}
+@end
+
+int main() {
+ [foo method_bar]; // \
+ // expected-warning {{'method_bar' is only available on macOS 10.12 or newer}} \
+ // expected-note {{enclose 'method_bar' in an @available check to silence this warning}} \
+ // CHECK: "fix-it:.*if (@available(macOS 10.12, *))"
+ return 0;
+}
diff --git a/test/Sema/bitfield.c b/test/Sema/bitfield.c
index d625366e4e1f..13e9480a378b 100644
--- a/test/Sema/bitfield.c
+++ b/test/Sema/bitfield.c
@@ -82,3 +82,7 @@ typedef __typeof__(+(t5.n--)) Unsigned; // also act like compound-assignment.
struct Test6 {
: 0.0; // expected-error{{type name requires a specifier or qualifier}}
};
+
+struct PR36157 {
+ int n : 1 ? 1 : implicitly_declare_function(); // expected-warning {{invalid in C99}}
+};
diff --git a/test/Sema/bittest-intrinsics.c b/test/Sema/bittest-intrinsics.c
new file mode 100644
index 000000000000..536c1eb066c7
--- /dev/null
+++ b/test/Sema/bittest-intrinsics.c
@@ -0,0 +1,84 @@
+// RUN: %clang_cc1 -ffreestanding -fms-compatibility -fms-compatibility-version=19 -verify %s -triple i686-windows-msvc -fms-extensions -DTEST_X86
+// RUN: %clang_cc1 -ffreestanding -fms-compatibility -fms-compatibility-version=19 -verify %s -triple x86_64-windows-msvc -fms-extensions -DTEST_X64
+// RUN: %clang_cc1 -ffreestanding -fms-compatibility -fms-compatibility-version=19 -verify %s -triple arm-windows-msvc -fms-extensions -DTEST_ARM
+// RUN: %clang_cc1 -ffreestanding -fms-compatibility -fms-compatibility-version=19 -verify %s -triple thumbv7-windows-msvc -fms-extensions -DTEST_ARM
+// RUN: %clang_cc1 -ffreestanding -fms-compatibility -fms-compatibility-version=19 -verify %s -triple aarch64-windows-msvc -fms-extensions -DTEST_ARM
+
+#include <intrin.h>
+extern unsigned char sink;
+
+#ifdef TEST_X86
+void x86(long *bits, __int64 *bits64, long bitidx) {
+ sink = _bittest(bits, bitidx);
+ sink = _bittestandcomplement(bits, bitidx);
+ sink = _bittestandreset(bits, bitidx);
+ sink = _bittestandset(bits, bitidx);
+ sink = _interlockedbittestandreset(bits, bitidx);
+ sink = _interlockedbittestandset(bits, bitidx);
+
+ sink = _bittest64(bits64, bitidx); // expected-error {{builtin is not supported on this target}}
+ sink = _bittestandcomplement64(bits64, bitidx); // expected-error {{builtin is not supported on this target}}
+ sink = _bittestandreset64(bits64, bitidx); // expected-error {{builtin is not supported on this target}}
+ sink = _bittestandset64(bits64, bitidx); // expected-error {{builtin is not supported on this target}}
+ sink = _interlockedbittestandreset64(bits64, bitidx); // expected-error {{builtin is not supported on this target}}
+ sink = _interlockedbittestandset64(bits64, bitidx); // expected-error {{builtin is not supported on this target}}
+
+ sink = _interlockedbittestandreset_acq(bits, bitidx); // expected-error {{builtin is not supported on this target}}
+ sink = _interlockedbittestandreset_rel(bits, bitidx); // expected-error {{builtin is not supported on this target}}
+ sink = _interlockedbittestandreset_nf(bits, bitidx); // expected-error {{builtin is not supported on this target}}
+ sink = _interlockedbittestandset_acq(bits, bitidx); // expected-error {{builtin is not supported on this target}}
+ sink = _interlockedbittestandset_rel(bits, bitidx); // expected-error {{builtin is not supported on this target}}
+ sink = _interlockedbittestandset_nf(bits, bitidx); // expected-error {{builtin is not supported on this target}}
+}
+#endif
+
+#ifdef TEST_X64
+void x64(long *bits, __int64 *bits64, long bitidx) {
+ sink = _bittest(bits, bitidx);
+ sink = _bittestandcomplement(bits, bitidx);
+ sink = _bittestandreset(bits, bitidx);
+ sink = _bittestandset(bits, bitidx);
+ sink = _interlockedbittestandreset(bits, bitidx);
+ sink = _interlockedbittestandset(bits, bitidx);
+
+ sink = _bittest64(bits64, bitidx);
+ sink = _bittestandcomplement64(bits64, bitidx);
+ sink = _bittestandreset64(bits64, bitidx);
+ sink = _bittestandset64(bits64, bitidx);
+ sink = _interlockedbittestandreset64(bits64, bitidx);
+ sink = _interlockedbittestandset64(bits64, bitidx);
+
+ sink = _interlockedbittestandreset_acq(bits, bitidx); // expected-error {{builtin is not supported on this target}}
+ sink = _interlockedbittestandreset_rel(bits, bitidx); // expected-error {{builtin is not supported on this target}}
+ sink = _interlockedbittestandreset_nf(bits, bitidx); // expected-error {{builtin is not supported on this target}}
+ sink = _interlockedbittestandset_acq(bits, bitidx); // expected-error {{builtin is not supported on this target}}
+ sink = _interlockedbittestandset_rel(bits, bitidx); // expected-error {{builtin is not supported on this target}}
+ sink = _interlockedbittestandset_nf(bits, bitidx); // expected-error {{builtin is not supported on this target}}
+}
+#endif
+
+#ifdef TEST_ARM
+// expected-no-diagnostics
+void arm(long *bits, __int64 *bits64, long bitidx) {
+ sink = _bittest(bits, bitidx);
+ sink = _bittestandcomplement(bits, bitidx);
+ sink = _bittestandreset(bits, bitidx);
+ sink = _bittestandset(bits, bitidx);
+ sink = _interlockedbittestandreset(bits, bitidx);
+ sink = _interlockedbittestandset(bits, bitidx);
+
+ sink = _bittest64(bits64, bitidx);
+ sink = _bittestandcomplement64(bits64, bitidx);
+ sink = _bittestandreset64(bits64, bitidx);
+ sink = _bittestandset64(bits64, bitidx);
+ sink = _interlockedbittestandreset64(bits64, bitidx);
+ sink = _interlockedbittestandset64(bits64, bitidx);
+
+ sink = _interlockedbittestandreset_acq(bits, bitidx);
+ sink = _interlockedbittestandreset_rel(bits, bitidx);
+ sink = _interlockedbittestandreset_nf(bits, bitidx);
+ sink = _interlockedbittestandset_acq(bits, bitidx);
+ sink = _interlockedbittestandset_rel(bits, bitidx);
+ sink = _interlockedbittestandset_nf(bits, bitidx);
+}
+#endif
diff --git a/test/Sema/builtin-classify-type.c b/test/Sema/builtin-classify-type.c
index 376e73d1118c..814c1aeec627 100644
--- a/test/Sema/builtin-classify-type.c
+++ b/test/Sema/builtin-classify-type.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify %s -fblocks
// expected-no-diagnostics
@@ -25,6 +25,14 @@ void foo() {
struct { int a; float b; } s_obj;
union { int a; float b; } u_obj;
int arr[10];
+ int (^block)();
+ __attribute__((vector_size(16))) int vec;
+ typedef __attribute__((ext_vector_type(4))) int evec_t;
+ evec_t evec;
+ _Atomic int atomic_i;
+ _Atomic double atomic_d;
+ _Complex int complex_i;
+ _Complex double complex_d;
int a1[__builtin_classify_type(f()) == void_type_class ? 1 : -1];
int a2[__builtin_classify_type(i) == integer_type_class ? 1 : -1];
@@ -38,5 +46,14 @@ void foo() {
int a10[__builtin_classify_type(u_obj) == union_type_class ? 1 : -1];
int a11[__builtin_classify_type(arr) == pointer_type_class ? 1 : -1];
int a12[__builtin_classify_type("abc") == pointer_type_class ? 1 : -1];
+ int a13[__builtin_classify_type(block) == no_type_class ? 1 : -1];
+ int a14[__builtin_classify_type(vec) == no_type_class ? 1 : -1];
+ int a15[__builtin_classify_type(evec) == no_type_class ? 1 : -1];
+ int a16[__builtin_classify_type(atomic_i) == integer_type_class ? 1 : -1];
+ int a17[__builtin_classify_type(atomic_d) == real_type_class ? 1 : -1];
+ int a18[__builtin_classify_type(complex_i) == complex_type_class ? 1 : -1];
+ int a19[__builtin_classify_type(complex_d) == complex_type_class ? 1 : -1];
}
+extern int (^p)();
+int n = __builtin_classify_type(p);
diff --git a/test/Sema/builtin-dump-struct.c b/test/Sema/builtin-dump-struct.c
new file mode 100644
index 000000000000..ec82ad15b644
--- /dev/null
+++ b/test/Sema/builtin-dump-struct.c
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -triple i386-unknown-unknown -fsyntax-only -fno-spell-checking -verify %s
+
+void invalid_uses() {
+ struct A {
+ };
+ struct A a;
+ void *b;
+ int (*goodfunc)(const char *, ...);
+ int (*badfunc1)(const char *);
+ int (*badfunc2)(int, ...);
+ void (*badfunc3)(const char *, ...);
+ int (*badfunc4)(char *, ...);
+ int (*badfunc5)(void);
+
+ __builtin_dump_struct(); // expected-error {{too few arguments to function call, expected 2, have 0}}
+ __builtin_dump_struct(1); // expected-error {{too few arguments to function call, expected 2, have 1}}
+ __builtin_dump_struct(1, 2); // expected-error {{passing 'int' to parameter of incompatible type structure pointer: type mismatch at 1st parameter ('int' vs structure pointer)}}
+ __builtin_dump_struct(&a, 2); // expected-error {{passing 'int' to parameter of incompatible type 'int (*)(const char *, ...)': type mismatch at 2nd parameter ('int' vs 'int (*)(const char *, ...)')}}
+ __builtin_dump_struct(b, goodfunc); // expected-error {{passing 'void *' to parameter of incompatible type structure pointer: type mismatch at 1st parameter ('void *' vs structure pointer)}}
+ __builtin_dump_struct(&a, badfunc1); // expected-error {{passing 'int (*)(const char *)' to parameter of incompatible type 'int (*)(const char *, ...)': type mismatch at 2nd parameter ('int (*)(const char *)' vs 'int (*)(const char *, ...)')}}
+ __builtin_dump_struct(&a, badfunc2); // expected-error {{passing 'int (*)(int, ...)' to parameter of incompatible type 'int (*)(const char *, ...)': type mismatch at 2nd parameter ('int (*)(int, ...)' vs 'int (*)(const char *, ...)')}}
+ __builtin_dump_struct(&a, badfunc3); // expected-error {{passing 'void (*)(const char *, ...)' to parameter of incompatible type 'int (*)(const char *, ...)': type mismatch at 2nd parameter ('void (*)(const char *, ...)' vs 'int (*)(const char *, ...)')}}
+ __builtin_dump_struct(&a, badfunc4); // expected-error {{passing 'int (*)(char *, ...)' to parameter of incompatible type 'int (*)(const char *, ...)': type mismatch at 2nd parameter ('int (*)(char *, ...)' vs 'int (*)(const char *, ...)')}}
+ __builtin_dump_struct(&a, badfunc5); // expected-error {{passing 'int (*)(void)' to parameter of incompatible type 'int (*)(const char *, ...)': type mismatch at 2nd parameter ('int (*)(void)' vs 'int (*)(const char *, ...)')}}
+ __builtin_dump_struct(a, goodfunc); // expected-error {{passing 'struct A' to parameter of incompatible type structure pointer: type mismatch at 1st parameter ('struct A' vs structure pointer)}}
+}
+
+void valid_uses() {
+ struct A {
+ };
+ union B {
+ };
+
+ int (*goodfunc)(const char *, ...);
+ int (*goodfunc2)();
+ struct A a;
+ union B b;
+
+ __builtin_dump_struct(&a, goodfunc);
+ __builtin_dump_struct(&b, goodfunc);
+ __builtin_dump_struct(&a, goodfunc2);
+}
diff --git a/test/Sema/builtin-object-size.c b/test/Sema/builtin-object-size.c
index 096882a088c0..436e99d9ab88 100644
--- a/test/Sema/builtin-object-size.c
+++ b/test/Sema/builtin-object-size.c
@@ -13,10 +13,10 @@ int f1() {
__builtin_object_size(&a, 3));
}
int f2() {
- return __builtin_object_size(&a, -1); // expected-error {{argument should be a value from 0 to 3}}
+ return __builtin_object_size(&a, -1); // expected-error {{argument value -1 is outside the valid range [0, 3]}}
}
int f3() {
- return __builtin_object_size(&a, 4); // expected-error {{argument should be a value from 0 to 3}}
+ return __builtin_object_size(&a, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}}
}
@@ -41,7 +41,7 @@ void f5(void)
char buf[10];
memset((void *)0x100000000ULL, 0, 0x1000);
memcpy((char *)NULL + 0x10000, buf, 0x10);
- memcpy1((char *)NULL + 0x10000, buf, 0x10); // expected-error {{argument should be a value from 0 to 3}}
+ memcpy1((char *)NULL + 0x10000, buf, 0x10); // expected-error {{argument value 4 is outside the valid range [0, 3]}}
}
// rdar://18431336
diff --git a/test/Sema/builtin-prefetch.c b/test/Sema/builtin-prefetch.c
index c5fa792a5663..478c85b75687 100644
--- a/test/Sema/builtin-prefetch.c
+++ b/test/Sema/builtin-prefetch.c
@@ -8,7 +8,7 @@ void foo() {
__builtin_prefetch(&a, 1, 9, 3); // expected-error{{too many arguments to function}}
__builtin_prefetch(&a, "hello", 2); // expected-error{{argument to '__builtin_prefetch' must be a constant integer}}
__builtin_prefetch(&a, a, 2); // expected-error{{argument to '__builtin_prefetch' must be a constant integer}}
- __builtin_prefetch(&a, 2); // expected-error{{argument should be a value from 0 to 1}}
- __builtin_prefetch(&a, 0, 4); // expected-error{{argument should be a value from 0 to 3}}
- __builtin_prefetch(&a, -1, 4); // expected-error{{argument should be a value from 0 to 1}}
+ __builtin_prefetch(&a, 2); // expected-error{{argument value 2 is outside the valid range [0, 1]}}
+ __builtin_prefetch(&a, 0, 4); // expected-error{{argument value 4 is outside the valid range [0, 3]}}
+ __builtin_prefetch(&a, -1, 4); // expected-error{{argument value -1 is outside the valid range [0, 1]}}
}
diff --git a/test/Sema/builtin-redecl.cpp b/test/Sema/builtin-redecl.cpp
new file mode 100644
index 000000000000..9d1a7fff0232
--- /dev/null
+++ b/test/Sema/builtin-redecl.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 %s -fsyntax-only -verify
+// RUN: %clang_cc1 %s -fsyntax-only -verify -x c
+// RUN: %clang_cc1 %s -fsyntax-only -verify -fms-compatibility
+
+// Redeclaring library builtins is OK.
+void exit(int);
+
+// expected-error@+2 {{cannot redeclare builtin function '__builtin_va_copy'}}
+// expected-note@+1 {{'__builtin_va_copy' is a builtin with type}}
+void __builtin_va_copy(double d);
+
+// expected-error@+2 {{cannot redeclare builtin function '__builtin_va_end'}}
+// expected-note@+1 {{'__builtin_va_end' is a builtin with type}}
+void __builtin_va_end(__builtin_va_list);
+// RUN: %clang_cc1 %s -fsyntax-only -verify
+// RUN: %clang_cc1 %s -fsyntax-only -verify -x c
+
+void __va_start(__builtin_va_list*, ...);
diff --git a/test/Sema/builtins-arm.c b/test/Sema/builtins-arm.c
index 373bbae31e7f..f34499123c40 100644
--- a/test/Sema/builtins-arm.c
+++ b/test/Sema/builtins-arm.c
@@ -35,18 +35,18 @@ void test2() {
#endif
void test3() {
- __builtin_arm_dsb(16); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_arm_dmb(17); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_arm_isb(18); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_arm_dsb(16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_arm_dmb(17); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_arm_isb(18); // expected-error-re {{argument value {{.*}} is outside the valid range}}
}
void test4() {
- __builtin_arm_prefetch(0, 2, 0); // expected-error {{argument should be a value from 0 to 1}}
- __builtin_arm_prefetch(0, 0, 2); // expected-error {{argument should be a value from 0 to 1}}
+ __builtin_arm_prefetch(0, 2, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_arm_prefetch(0, 0, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}}
}
void test5() {
- __builtin_arm_dbg(16); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_arm_dbg(16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
}
void test6(int a, int b, int c) {
@@ -168,14 +168,14 @@ void test_9_4_1_width_specified_saturation(int a, int b) {
s = __builtin_arm_ssat(8, 2);
s = __builtin_arm_ssat(a, 1);
s = __builtin_arm_ssat(a, 32);
- s = __builtin_arm_ssat(a, 0); // expected-error {{argument should be a value from 1 to 32}}
- s = __builtin_arm_ssat(a, 33); // expected-error {{argument should be a value from 1 to 32}}
+ s = __builtin_arm_ssat(a, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ s = __builtin_arm_ssat(a, 33); // expected-error-re {{argument value {{.*}} is outside the valid range}}
s = __builtin_arm_ssat(a, b); // expected-error {{argument to '__builtin_arm_ssat' must be a constant integer}}
u = __builtin_arm_usat(8, 2);
u = __builtin_arm_usat(a, 0);
u = __builtin_arm_usat(a, 31);
- u = __builtin_arm_usat(a, 32); // expected-error {{argument should be a value from 0 to 31}}
+ u = __builtin_arm_usat(a, 32); // expected-error-re {{argument value {{.*}} is outside the valid range}}
u = __builtin_arm_usat(a, b); // expected-error {{argument to '__builtin_arm_usat' must be a constant integer}}
}
@@ -215,12 +215,12 @@ void test_9_5_4_parallel_16bit_saturation(int16x2_t a) {
s = __builtin_arm_ssat16(a, 1);
s = __builtin_arm_ssat16(a, 16);
- s = __builtin_arm_ssat16(a, 0); // expected-error {{argument should be a value from 1 to 16}}
- s = __builtin_arm_ssat16(a, 17); // expected-error {{argument should be a value from 1 to 16}}
+ s = __builtin_arm_ssat16(a, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ s = __builtin_arm_ssat16(a, 17); // expected-error-re {{argument value {{.*}} is outside the valid range}}
u = __builtin_arm_usat16(a, 0);
u = __builtin_arm_usat16(a, 15);
- u = __builtin_arm_usat16(a, 16); // expected-error {{argument should be a value from 0 to 15}}
+ u = __builtin_arm_usat16(a, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
}
void test_9_5_5_packing_and_unpacking(int16x2_t a, int8x4_t b, uint16x2_t c, uint8x4_t d) {
@@ -320,3 +320,18 @@ void test_9_5_10_parallel_16bit_multiplication(int16x2_t a, int16x2_t b,
x = __builtin_arm_smusd(a, b);
x = __builtin_arm_smusdx(a, b);
}
+
+void test_VFP(float f, double d) {
+ float fr;
+ double dr;
+
+ fr = __builtin_arm_vcvtr_f(f, 0);
+ fr = __builtin_arm_vcvtr_f(f, 1);
+ fr = __builtin_arm_vcvtr_f(f, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ fr = __builtin_arm_vcvtr_f(f, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+
+ dr = __builtin_arm_vcvtr_f(d, 0);
+ dr = __builtin_arm_vcvtr_f(d, 1);
+ dr = __builtin_arm_vcvtr_f(d, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ dr = __builtin_arm_vcvtr_f(d, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+}
diff --git a/test/Sema/builtins-arm64.c b/test/Sema/builtins-arm64.c
index 2779984680f4..27144a18cdeb 100644
--- a/test/Sema/builtins-arm64.c
+++ b/test/Sema/builtins-arm64.c
@@ -18,14 +18,14 @@ void test_clear_cache_no_args() {
}
void test_memory_barriers() {
- __builtin_arm_dmb(16); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_arm_dsb(17); // expected-error {{argument should be a value from 0 to 15}}
- __builtin_arm_isb(18); // expected-error {{argument should be a value from 0 to 15}}
+ __builtin_arm_dmb(16); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_arm_dsb(17); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_arm_isb(18); // expected-error-re {{argument value {{.*}} is outside the valid range}}
}
void test_prefetch() {
- __builtin_arm_prefetch(0, 2, 0, 0, 0); // expected-error {{argument should be a value from 0 to 1}}
- __builtin_arm_prefetch(0, 0, 3, 0, 0); // expected-error {{argument should be a value from 0 to 2}}
- __builtin_arm_prefetch(0, 0, 0, 2, 0); // expected-error {{argument should be a value from 0 to 1}}
- __builtin_arm_prefetch(0, 0, 0, 0, 2); // expected-error {{argument should be a value from 0 to 1}}
+ __builtin_arm_prefetch(0, 2, 0, 0, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_arm_prefetch(0, 0, 3, 0, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_arm_prefetch(0, 0, 0, 2, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_arm_prefetch(0, 0, 0, 0, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}}
}
diff --git a/test/Sema/builtins-hexagon-v55.c b/test/Sema/builtins-hexagon-v55.c
new file mode 100644
index 000000000000..e5e233d1f1e8
--- /dev/null
+++ b/test/Sema/builtins-hexagon-v55.c
@@ -0,0 +1,17 @@
+// REQUIRES: hexagon-registered-target
+// RUN: %clang_cc1 %s -triple hexagon -fsyntax-only -verify -target-cpu hexagonv55
+
+unsigned builtin_needs_v60(unsigned Rs) {
+ // expected-error@+1 {{builtin is not supported on this CPU}}
+ return __builtin_HEXAGON_S6_rol_i_r(Rs, 3);
+}
+
+unsigned long long builtin_needs_v62(unsigned Rs) {
+ // expected-error@+1 {{builtin is not supported on this CPU}}
+ return __builtin_HEXAGON_S6_vsplatrbp(Rs);
+}
+
+unsigned builtin_needs_v65(unsigned long long Rss, unsigned long long Rtt) {
+ // expected-error@+1 {{builtin is not supported on this CPU}}
+ return __builtin_HEXAGON_A6_vcmpbeq_notany(Rss, Rtt);
+}
diff --git a/test/Sema/builtins-hexagon-v60.c b/test/Sema/builtins-hexagon-v60.c
new file mode 100644
index 000000000000..d4f081bf66ae
--- /dev/null
+++ b/test/Sema/builtins-hexagon-v60.c
@@ -0,0 +1,16 @@
+// REQUIRES: hexagon-registered-target
+// RUN: %clang_cc1 %s -triple hexagon -fsyntax-only -verify -target-cpu hexagonv60
+
+unsigned builtin_needs_v60(unsigned Rs) {
+ return __builtin_HEXAGON_S6_rol_i_r(Rs, 3);
+}
+
+unsigned long long builtin_needs_v62(unsigned Rs) {
+ // expected-error@+1 {{builtin is not supported on this CPU}}
+ return __builtin_HEXAGON_S6_vsplatrbp(Rs);
+}
+
+unsigned builtin_needs_v65(unsigned long long Rss, unsigned long long Rtt) {
+ // expected-error@+1 {{builtin is not supported on this CPU}}
+ return __builtin_HEXAGON_A6_vcmpbeq_notany(Rss, Rtt);
+}
diff --git a/test/Sema/builtins-hexagon-v62.c b/test/Sema/builtins-hexagon-v62.c
new file mode 100644
index 000000000000..ed3907bc8271
--- /dev/null
+++ b/test/Sema/builtins-hexagon-v62.c
@@ -0,0 +1,15 @@
+// REQUIRES: hexagon-registered-target
+// RUN: %clang_cc1 %s -triple hexagon -fsyntax-only -verify -target-cpu hexagonv62
+
+unsigned builtin_needs_v60(unsigned Rs) {
+ return __builtin_HEXAGON_S6_rol_i_r(Rs, 3);
+}
+
+unsigned long long builtin_needs_v62(unsigned Rs) {
+ return __builtin_HEXAGON_S6_vsplatrbp(Rs);
+}
+
+unsigned builtin_needs_v65(unsigned long long Rss, unsigned long long Rtt) {
+ // expected-error@+1 {{builtin is not supported on this CPU}}
+ return __builtin_HEXAGON_A6_vcmpbeq_notany(Rss, Rtt);
+}
diff --git a/test/Sema/builtins-hexagon-v65.c b/test/Sema/builtins-hexagon-v65.c
new file mode 100644
index 000000000000..bb8a1ce5e167
--- /dev/null
+++ b/test/Sema/builtins-hexagon-v65.c
@@ -0,0 +1,15 @@
+// REQUIRES: hexagon-registered-target
+// RUN: %clang_cc1 %s -triple hexagon -fsyntax-only -verify -target-cpu hexagonv65
+
+// expected-no-diagnostics
+unsigned builtin_needs_v60(unsigned Rs) {
+ return __builtin_HEXAGON_S6_rol_i_r(Rs, 3);
+}
+
+unsigned long long builtin_needs_v62(unsigned Rs) {
+ return __builtin_HEXAGON_S6_vsplatrbp(Rs);
+}
+
+unsigned builtin_needs_v65(unsigned long long Rss, unsigned long long Rtt) {
+ return __builtin_HEXAGON_A6_vcmpbeq_notany(Rss, Rtt);
+}
diff --git a/test/Sema/builtins-hvx-none.c b/test/Sema/builtins-hvx-none.c
new file mode 100644
index 000000000000..c43b34f1c57b
--- /dev/null
+++ b/test/Sema/builtins-hvx-none.c
@@ -0,0 +1,26 @@
+// REQUIRES: hexagon-registered-target
+// RUN: %clang_cc1 -triple hexagon %s -fsyntax-only -verify
+
+typedef long Vect1024 __attribute__((__vector_size__(128)))
+ __attribute__((aligned(128)));
+typedef long Vect2048 __attribute__((__vector_size__(256)))
+ __attribute__((aligned(128)));
+
+typedef Vect1024 HVX_Vector;
+typedef Vect2048 HVX_VectorPair;
+
+
+HVX_Vector builtin_needs_v60(HVX_VectorPair a) {
+ // expected-error@+1 {{builtin requires HVX}}
+ return __builtin_HEXAGON_V6_hi_128B(a);
+}
+
+HVX_Vector builtin_needs_v62(char a) {
+ // expected-error@+1 {{builtin requires HVX}}
+ return __builtin_HEXAGON_V6_lvsplatb_128B(a);
+}
+
+HVX_VectorPair builtin_needs_v65() {
+ // expected-error@+1 {{builtin requires HVX}}
+ return __builtin_HEXAGON_V6_vdd0_128B();
+}
diff --git a/test/Sema/builtins-hvx-v60.c b/test/Sema/builtins-hvx-v60.c
new file mode 100644
index 000000000000..7d298e989ea2
--- /dev/null
+++ b/test/Sema/builtins-hvx-v60.c
@@ -0,0 +1,25 @@
+// REQUIRES: hexagon-registered-target
+// RUN: %clang_cc1 -triple hexagon %s -target-feature +hvx-length128b -target-feature +hvxv60 -target-cpu hexagonv60 -fsyntax-only -verify
+
+typedef long Vect1024 __attribute__((__vector_size__(128)))
+ __attribute__((aligned(128)));
+typedef long Vect2048 __attribute__((__vector_size__(256)))
+ __attribute__((aligned(128)));
+
+typedef Vect1024 HVX_Vector;
+typedef Vect2048 HVX_VectorPair;
+
+
+HVX_Vector builtin_needs_v60(HVX_VectorPair a) {
+ return __builtin_HEXAGON_V6_hi_128B(a);
+}
+
+HVX_Vector builtin_needs_v62(char a) {
+ // expected-error@+1 {{builtin is not supported on this version of HVX}}
+ return __builtin_HEXAGON_V6_lvsplatb_128B(a);
+}
+
+HVX_VectorPair builtin_needs_v65() {
+ // expected-error@+1 {{builtin is not supported on this version of HVX}}
+ return __builtin_HEXAGON_V6_vdd0_128B();
+}
diff --git a/test/Sema/builtins-hvx-v62.c b/test/Sema/builtins-hvx-v62.c
new file mode 100644
index 000000000000..b73af963766d
--- /dev/null
+++ b/test/Sema/builtins-hvx-v62.c
@@ -0,0 +1,24 @@
+// REQUIRES: hexagon-registered-target
+// RUN: %clang_cc1 -triple hexagon %s -target-feature +hvx-length128b -target-feature +hvxv62 -target-cpu hexagonv62 -fsyntax-only -verify
+
+typedef long Vect1024 __attribute__((__vector_size__(128)))
+ __attribute__((aligned(128)));
+typedef long Vect2048 __attribute__((__vector_size__(256)))
+ __attribute__((aligned(128)));
+
+typedef Vect1024 HVX_Vector;
+typedef Vect2048 HVX_VectorPair;
+
+
+HVX_Vector builtin_needs_v60(HVX_VectorPair a) {
+ return __builtin_HEXAGON_V6_hi_128B(a);
+}
+
+HVX_Vector builtin_needs_v62(char a) {
+ return __builtin_HEXAGON_V6_lvsplatb_128B(a);
+}
+
+HVX_VectorPair builtin_needs_v65() {
+ // expected-error@+1 {{builtin is not supported on this version of HVX}}
+ return __builtin_HEXAGON_V6_vdd0_128B();
+}
diff --git a/test/Sema/builtins-hvx-v65.c b/test/Sema/builtins-hvx-v65.c
new file mode 100644
index 000000000000..be6b7b0955d5
--- /dev/null
+++ b/test/Sema/builtins-hvx-v65.c
@@ -0,0 +1,23 @@
+// REQUIRES: hexagon-registered-target
+// RUN: %clang_cc1 -triple hexagon %s -target-feature +hvx-length128b -target-feature +hvxv65 -target-cpu hexagonv65 -fsyntax-only -verify
+
+typedef long Vect1024 __attribute__((__vector_size__(128)))
+ __attribute__((aligned(128)));
+typedef long Vect2048 __attribute__((__vector_size__(256)))
+ __attribute__((aligned(128)));
+
+typedef Vect1024 HVX_Vector;
+typedef Vect2048 HVX_VectorPair;
+
+// expected-no-diagnostics
+HVX_Vector builtin_needs_v60(HVX_VectorPair a) {
+ return __builtin_HEXAGON_V6_hi_128B(a);
+}
+
+HVX_Vector builtin_needs_v62(char a) {
+ return __builtin_HEXAGON_V6_lvsplatb_128B(a);
+}
+
+HVX_VectorPair builtin_needs_v65() {
+ return __builtin_HEXAGON_V6_vdd0_128B();
+}
diff --git a/test/Sema/builtins-ppc.c b/test/Sema/builtins-ppc.c
index 5c45d02b414c..aa6e9843f657 100644
--- a/test/Sema/builtins-ppc.c
+++ b/test/Sema/builtins-ppc.c
@@ -9,15 +9,15 @@
#ifdef TEST_HTM
void test_htm() {
- __builtin_tbegin(4); // expected-error {{argument should be a value from 0 to 1}}
- __builtin_tend(-1); // expected-error {{argument should be a value from 0 to 1}}
- __builtin_tsr(55); // expected-error {{argument should be a value from 0 to 7}}
- __builtin_tabortwc(-5, 2, 3); // expected-error {{argument should be a value from 0 to 31}}
- __builtin_tabortdc(55, 2, 3); // expected-error {{argument should be a value from 0 to 31}}
- __builtin_tabortwci(-5, 2, 5); // expected-error {{argument should be a value from 0 to 31}}
- __builtin_tabortwci(5, 2, 55); // expected-error {{argument should be a value from 0 to 31}}
- __builtin_tabortdci(-5, 2, 5); // expected-error {{argument should be a value from 0 to 31}}
- __builtin_tabortdci(5, 2, 55); // expected-error {{argument should be a value from 0 to 31}}
+ __builtin_tbegin(4); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_tend(-1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_tsr(55); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_tabortwc(-5, 2, 3); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_tabortdc(55, 2, 3); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_tabortwci(-5, 2, 5); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_tabortwci(5, 2, 55); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_tabortdci(-5, 2, 5); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __builtin_tabortdci(5, 2, 55); // expected-error-re {{argument value {{.*}} is outside the valid range}}
}
#endif
@@ -30,20 +30,20 @@ void test_htm() {
vector unsigned int test_vshasigmaw_or(void)
{
vector unsigned int a = W_INIT
- vector unsigned int b = __builtin_crypto_vshasigmaw(a, 2, 15); // expected-error {{argument should be a value from 0 to 1}}
- vector unsigned int c = __builtin_crypto_vshasigmaw(a, -1, 15); // expected-error {{argument should be a value from 0 to 1}}
- vector unsigned int d = __builtin_crypto_vshasigmaw(a, 0, 85); // expected-error {{argument should be a value from 0 to 15}}
- vector unsigned int e = __builtin_crypto_vshasigmaw(a, 1, -15); // expected-error {{argument should be a value from 0 to 15}}
+ vector unsigned int b = __builtin_crypto_vshasigmaw(a, 2, 15); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vector unsigned int c = __builtin_crypto_vshasigmaw(a, -1, 15); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vector unsigned int d = __builtin_crypto_vshasigmaw(a, 0, 85); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vector unsigned int e = __builtin_crypto_vshasigmaw(a, 1, -15); // expected-error-re {{argument value {{.*}} is outside the valid range}}
return __builtin_crypto_vshasigmaw(a, 1, 15);
}
vector unsigned long long test_vshasigmad_or(void)
{
vector unsigned long long a = D_INIT
- vector unsigned long long b = __builtin_crypto_vshasigmad(a, 2, 15); // expected-error {{argument should be a value from 0 to 1}}
- vector unsigned long long c = __builtin_crypto_vshasigmad(a, -1, 15); // expected-error {{argument should be a value from 0 to 1}}
- vector unsigned long long d = __builtin_crypto_vshasigmad(a, 0, 85); // expected-error {{argument should be a value from 0 to 1}}
- vector unsigned long long e = __builtin_crypto_vshasigmad(a, 1, -15); // expected-error {{argument should be a value from 0 to 1}}
+ vector unsigned long long b = __builtin_crypto_vshasigmad(a, 2, 15); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vector unsigned long long c = __builtin_crypto_vshasigmad(a, -1, 15); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vector unsigned long long d = __builtin_crypto_vshasigmad(a, 0, 85); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ vector unsigned long long e = __builtin_crypto_vshasigmad(a, 1, -15); // expected-error-re {{argument value {{.*}} is outside the valid range}}
return __builtin_crypto_vshasigmad(a, 0, 15);
}
diff --git a/test/Sema/builtins-x86.c b/test/Sema/builtins-x86.c
index 074efe16ade6..9872a64f1874 100644
--- a/test/Sema/builtins-x86.c
+++ b/test/Sema/builtins-x86.c
@@ -4,82 +4,163 @@ typedef long long __m128i __attribute__((__vector_size__(16)));
typedef float __m128 __attribute__((__vector_size__(16)));
typedef double __m128d __attribute__((__vector_size__(16)));
+typedef long long __m256i __attribute__((__vector_size__(32)));
+typedef float __m256 __attribute__((__vector_size__(32)));
+typedef double __m256d __attribute__((__vector_size__(32)));
+
typedef long long __m512i __attribute__((__vector_size__(64)));
typedef float __m512 __attribute__((__vector_size__(64)));
typedef double __m512d __attribute__((__vector_size__(64)));
typedef unsigned char __mmask8;
typedef unsigned short __mmask16;
+typedef unsigned int __mmask32;
+
+void call_x86_32_builtins(void) {
+ (void)__builtin_ia32_readeflags_u32(); // expected-error{{this builtin is only available on 32-bit targets}}
+ (void)__builtin_ia32_writeeflags_u32(4); // expected-error{{this builtin is only available on 32-bit targets}}
+}
__m128 test__builtin_ia32_cmpps(__m128 __a, __m128 __b) {
- __builtin_ia32_cmpps(__a, __b, 32); // expected-error {{argument should be a value from 0 to 31}}
+ return __builtin_ia32_cmpps(__a, __b, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
}
__m128d test__builtin_ia32_cmppd(__m128d __a, __m128d __b) {
- __builtin_ia32_cmppd(__a, __b, 32); // expected-error {{argument should be a value from 0 to 31}}
+ return __builtin_ia32_cmppd(__a, __b, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
}
__m128 test__builtin_ia32_cmpss(__m128 __a, __m128 __b) {
- __builtin_ia32_cmpss(__a, __b, 32); // expected-error {{argument should be a value from 0 to 31}}
+ return __builtin_ia32_cmpss(__a, __b, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
}
__m128d test__builtin_ia32_cmpsd(__m128d __a, __m128d __b) {
- __builtin_ia32_cmpsd(__a, __b, 32); // expected-error {{argument should be a value from 0 to 31}}
+ return __builtin_ia32_cmpsd(__a, __b, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
}
__mmask16 test__builtin_ia32_cmpps512_mask(__m512d __a, __m512d __b) {
- __builtin_ia32_cmpps512_mask(__a, __b, 32, -1, 4); // expected-error {{argument should be a value from 0 to 31}}
+ return __builtin_ia32_cmpps512_mask(__a, __b, 32, -1, 4); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
}
__mmask8 test__builtin_ia32_cmppd512_mask(__m512d __a, __m512d __b) {
- __builtin_ia32_cmppd512_mask(__a, __b, 32, -1, 4); // expected-error {{argument should be a value from 0 to 31}}
+ return __builtin_ia32_cmppd512_mask(__a, __b, 32, -1, 4); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
}
__m128i test__builtin_ia32_vpcomub(__m128i __a, __m128i __b) {
- __builtin_ia32_vpcomub(__a, __b, 8); // expected-error {{argument should be a value from 0 to 7}}
+ return __builtin_ia32_vpcomub(__a, __b, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}}
}
__m128i test__builtin_ia32_vpcomuw(__m128i __a, __m128i __b) {
- __builtin_ia32_vpcomuw(__a, __b, 8); // expected-error {{argument should be a value from 0 to 7}}
+ return __builtin_ia32_vpcomuw(__a, __b, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}}
}
__m128i test__builtin_ia32_vpcomud(__m128i __a, __m128i __b) {
- __builtin_ia32_vpcomud(__a, __b, 8); // expected-error {{argument should be a value from 0 to 7}}
+ return __builtin_ia32_vpcomud(__a, __b, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}}
}
__m128i test__builtin_ia32_vpcomuq(__m128i __a, __m128i __b) {
- __builtin_ia32_vpcomuq(__a, __b, 8); // expected-error {{argument should be a value from 0 to 7}}
+ return __builtin_ia32_vpcomuq(__a, __b, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}}
}
__m128i test__builtin_ia32_vpcomb(__m128i __a, __m128i __b) {
- __builtin_ia32_vpcomub(__a, __b, 8); // expected-error {{argument should be a value from 0 to 7}}
+ return __builtin_ia32_vpcomub(__a, __b, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}}
}
__m128i test__builtin_ia32_vpcomw(__m128i __a, __m128i __b) {
- __builtin_ia32_vpcomuw(__a, __b, 8); // expected-error {{argument should be a value from 0 to 7}}
+ return __builtin_ia32_vpcomuw(__a, __b, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}}
}
__m128i test__builtin_ia32_vpcomd(__m128i __a, __m128i __b) {
- __builtin_ia32_vpcomud(__a, __b, 8); // expected-error {{argument should be a value from 0 to 7}}
+ return __builtin_ia32_vpcomud(__a, __b, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}}
}
__m128i test__builtin_ia32_vpcomq(__m128i __a, __m128i __b) {
- __builtin_ia32_vpcomuq(__a, __b, 8); // expected-error {{argument should be a value from 0 to 7}}
+ return __builtin_ia32_vpcomuq(__a, __b, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}}
}
__mmask16 test__builtin_ia32_cmpps512_mask_rounding(__m512 __a, __m512 __b, __mmask16 __u) {
- __builtin_ia32_cmpps512_mask(__a, __b, 0, __u, 0); // expected-error {{invalid rounding argument}}
+ return __builtin_ia32_cmpps512_mask(__a, __b, 0, __u, 0); // expected-error {{invalid rounding argument}}
}
__m128i test_mm_mask_i32gather_epi32(__m128i a, int const *b, __m128i c, __m128i mask) {
return __builtin_ia32_gatherd_d(a, b, c, mask, 5); // expected-error {{scale argument must be 1, 2, 4, or 8}}
}
-__m512i _mm512_mask_prefetch_i32gather_ps(__m512i index, __mmask16 mask, int const *addr) {
- return __builtin_ia32_gatherpfdps(mask, index, addr, 5, 1); // expected-error {{scale argument must be 1, 2, 4, or 8}}
+void _mm512_mask_prefetch_i32gather_ps(__m512i index, __mmask16 mask, int const *addr) {
+ __builtin_ia32_gatherpfdps(mask, index, addr, 5, 1); // expected-error {{scale argument must be 1, 2, 4, or 8}}
+}
+
+void _mm512_mask_prefetch_i32gather_ps_2(__m512i index, __mmask16 mask, int const *addr) {
+ __builtin_ia32_gatherpfdps(mask, index, addr, 1, 1); // expected-error {{argument value 1 is outside the valid range [2, 3]}}
+}
+
+__m512i test_mm512_shldi_epi64(__m512i __A, __m512i __B) {
+ return __builtin_ia32_vpshldq512(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}}
+}
+
+__m512i test_mm512_shldi_epi32(__m512i __A, __m512i __B) {
+ return __builtin_ia32_vpshldd512(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}}
+}
+
+__m512i test_mm512_shldi_epi16(__m512i __A, __m512i __B) {
+ return __builtin_ia32_vpshldw512(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}}
+}
+
+__m512i test_mm512_shrdi_epi64(__m512i __A, __m512i __B) {
+ return __builtin_ia32_vpshrdq512(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}}
+}
+
+__m512i test_mm512_shrdi_epi32(__m512i __A, __m512i __B) {
+ return __builtin_ia32_vpshrdd512(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}}
+}
+
+__m512i test_mm512_shrdi_epi16(__m512i __A, __m512i __B) {
+ return __builtin_ia32_vpshrdw512(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}}
+}
+
+__m256i test_mm256_shldi_epi64(__m256i __A, __m256i __B) {
+ return __builtin_ia32_vpshldq256(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}}
}
-__m512 _mm512_mask_prefetch_i32gather_ps_2(__m512i index, __mmask16 mask, int const *addr) {
- return __builtin_ia32_gatherpfdps(mask, index, addr, 1, 1); // expected-error {{argument should be a value from 2 to 3}}
+__m128i test_mm128_shldi_epi64( __m128i __A, __m128i __B) {
+ return __builtin_ia32_vpshldq128(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}}
}
+__m256i test_mm256_shldi_epi32(__m256i __A, __m256i __B) {
+ return __builtin_ia32_vpshldd256(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}}
+}
+
+__m128i test_mm128_shldi_epi32(__m128i __A, __m128i __B) {
+ return __builtin_ia32_vpshldd128(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}}
+}
+
+__m256i test_mm256_shldi_epi16( __m256i __A, __m256i __B) {
+ return __builtin_ia32_vpshldw256(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}}
+}
+
+__m128i test_mm128_shldi_epi16(__m128i __A, __m128i __B) {
+ return __builtin_ia32_vpshldw128(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}}
+}
+
+__m256i test_mm256_shrdi_epi64(__m256i __A, __m256i __B) {
+ return __builtin_ia32_vpshrdq256(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}}
+}
+
+__m128i test_mm128_shrdi_epi64(__m128i __A, __m128i __B) {
+ return __builtin_ia32_vpshrdq128(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}}
+}
+
+__m256i test_mm256_shrdi_epi32(__m256i __A, __m256i __B) {
+ return __builtin_ia32_vpshrdd256(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}}
+}
+
+__m128i test_mm128_shrdi_epi32(__m128i __A, __m128i __B) {
+ return __builtin_ia32_vpshrdd128(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}}
+}
+
+__m256i test_mm256_shrdi_epi16(__m256i __A, __m256i __B) {
+ return __builtin_ia32_vpshrdw256(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}}
+}
+
+__m128i test_mm128_shrdi_epi16(__m128i __A, __m128i __B) {
+ return __builtin_ia32_vpshrdw128(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}}
+}
diff --git a/test/Sema/builtins-x86.cpp b/test/Sema/builtins-x86.cpp
new file mode 100644
index 000000000000..0f37f4a34649
--- /dev/null
+++ b/test/Sema/builtins-x86.cpp
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -triple=x86_64-apple-darwin -fsyntax-only -verify %s
+//
+// Ensure that when we use builtins in C++ code with templates that compute the
+// valid immediate, the dead code with the invalid immediate doesn't error.
+// expected-no-diagnostics
+
+typedef short __v8hi __attribute__((__vector_size__(16)));
+
+template <int Imm>
+__v8hi test(__v8hi a) {
+ if (Imm < 4)
+ return __builtin_ia32_pshuflw(a, 0x55 * Imm);
+ else
+ return __builtin_ia32_pshuflw(a, 0x55 * (Imm - 4));
+}
+
+template __v8hi test<0>(__v8hi);
+template __v8hi test<1>(__v8hi);
+template __v8hi test<2>(__v8hi);
+template __v8hi test<3>(__v8hi);
+template __v8hi test<4>(__v8hi);
+template __v8hi test<5>(__v8hi);
+template __v8hi test<6>(__v8hi);
+template __v8hi test<7>(__v8hi);
diff --git a/test/Sema/builtins.c b/test/Sema/builtins.c
index 0e2925e0748d..a831d030ef11 100644
--- a/test/Sema/builtins.c
+++ b/test/Sema/builtins.c
@@ -248,3 +248,31 @@ char * Test20(char *p, const char *in, unsigned n)
return buf;
}
+
+void test21(const int *ptr) {
+ __sync_fetch_and_add(ptr, 1); // expected-error{{address argument to atomic builtin cannot be const-qualified ('const int *' invalid)}}
+ __atomic_fetch_add(ptr, 1, 0); // expected-error {{address argument to atomic operation must be a pointer to non-const type ('const int *' invalid)}}
+}
+
+void test22(void) {
+ (void)__builtin_signbit(); // expected-error{{too few arguments to function call, expected 1, have 0}}
+ (void)__builtin_signbit(1.0, 2.0, 3.0); // expected-error{{too many arguments to function call, expected 1, have 3}}
+ (void)__builtin_signbit(1); // expected-error {{floating point classification requires argument of floating point type (passed in 'int')}}
+ (void)__builtin_signbit(1.0);
+ (void)__builtin_signbit(1.0f);
+ (void)__builtin_signbit(1.0L);
+
+ (void)__builtin_signbitf(); // expected-error{{too few arguments to function call, expected 1, have 0}}
+ (void)__builtin_signbitf(1.0, 2.0, 3.0); // expected-error{{too many arguments to function call, expected 1, have 3}}
+ (void)__builtin_signbitf(1);
+ (void)__builtin_signbitf(1.0);
+ (void)__builtin_signbitf(1.0f);
+ (void)__builtin_signbitf(1.0L);
+
+ (void)__builtin_signbitl(); // expected-error{{too few arguments to function call, expected 1, have 0}}
+ (void)__builtin_signbitl(1.0, 2.0, 3.0); // expected-error{{too many arguments to function call, expected 1, have 3}}
+ (void)__builtin_signbitl(1);
+ (void)__builtin_signbitl(1.0);
+ (void)__builtin_signbitl(1.0f);
+ (void)__builtin_signbitl(1.0L);
+}
diff --git a/test/Sema/compare.c b/test/Sema/compare.c
index 97586a7cc05e..b2b486f59f87 100644
--- a/test/Sema/compare.c
+++ b/test/Sema/compare.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -pedantic -verify -Wsign-compare %s -Wno-unreachable-code
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -pedantic -verify -Wsign-compare -Wtautological-constant-in-range-compare %s -Wno-unreachable-code
int test(char *C) { // nothing here should warn.
return C != ((void*)0);
@@ -391,3 +391,16 @@ typedef char two_chars[2];
void test12(unsigned a) {
if (0 && -1 > a) { }
}
+
+// PR36008
+
+enum PR36008EnumTest {
+ kPR36008Value = 0,
+};
+
+void pr36008(enum PR36008EnumTest lhs) {
+ __typeof__(lhs) x = lhs;
+ __typeof__(kPR36008Value) y = (kPR36008Value);
+ if (x == y) x = y; // no warning
+ if (y == x) y = x; // no warning
+}
diff --git a/test/Sema/complex-int.c b/test/Sema/complex-int.c
index 2b797e5a14ad..52ea44dd77fb 100644
--- a/test/Sema/complex-int.c
+++ b/test/Sema/complex-int.c
@@ -18,6 +18,10 @@ result = arr*brr;
result = xx*yy;
switch (arr) { // expected-error{{statement requires expression of integer type ('_Complex int' invalid)}}
+ case brr: ;
+ case xx: ;
+}
+switch (ii) {
case brr: ; // expected-error{{expression is not an integer constant expression}}
case xx: ; // expected-error{{expression is not an integer constant expression}}
}
diff --git a/test/Sema/constant-builtins-2.c b/test/Sema/constant-builtins-2.c
index a4baecb61558..40cfce1f4a00 100644
--- a/test/Sema/constant-builtins-2.c
+++ b/test/Sema/constant-builtins-2.c
@@ -5,24 +5,35 @@
double g0 = __builtin_huge_val();
float g1 = __builtin_huge_valf();
long double g2 = __builtin_huge_vall();
+#if defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__)
+__float128 g2_2 = __builtin_huge_valf128();
+#endif
double g3 = __builtin_inf();
float g4 = __builtin_inff();
long double g5 = __builtin_infl();
+#if defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__)
+__float128 g5_2 = __builtin_inff128();
+#endif
double g6 = __builtin_nan("");
float g7 = __builtin_nanf("");
long double g8 = __builtin_nanl("");
+#if defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__)
+__float128 g8_2 = __builtin_nanf128("");
+#endif
// GCC constant folds these too (via native strtol):
//double g6_1 = __builtin_nan("1");
//float g7_1 = __builtin_nanf("1");
//long double g8_1 = __builtin_nanl("1");
-// APFloat doesn't have signalling NaN functions.
-//double g9 = __builtin_nans("");
-//float g10 = __builtin_nansf("");
-//long double g11 = __builtin_nansl("");
+double g9 = __builtin_nans("");
+float g10 = __builtin_nansf("");
+long double g11 = __builtin_nansl("");
+#if defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__)
+__float128 g11_2 = __builtin_nansf128("");
+#endif
//int g12 = __builtin_abs(-12);
@@ -32,10 +43,16 @@ double g13_1 = __builtin_fabs(-__builtin_inf());
float g14 = __builtin_fabsf(-12.f);
// GCC doesn't eat this one.
//long double g15 = __builtin_fabsfl(-12.0L);
+#if defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__)
+__float128 g15_2 = __builtin_fabsf128(-12.q);
+#endif
float g16 = __builtin_copysign(1.0, -1.0);
double g17 = __builtin_copysignf(1.0f, -1.0f);
long double g18 = __builtin_copysignl(1.0L, -1.0L);
+#if defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__)
+__float128 g18_2 = __builtin_copysignf128(1.0q, -1.0q);
+#endif
char classify_nan [__builtin_fpclassify(+1, -1, -1, -1, -1, __builtin_nan(""))];
char classify_snan [__builtin_fpclassify(+1, -1, -1, -1, -1, __builtin_nans(""))];
diff --git a/test/Sema/conversion.c b/test/Sema/conversion.c
index 89c34c6a224c..aa591c9fa60d 100644
--- a/test/Sema/conversion.c
+++ b/test/Sema/conversion.c
@@ -429,3 +429,22 @@ void test27(ushort16 constants) {
ushort16 crCbScale = pairedConstants.s4; // expected-warning {{implicit conversion loses integer precision: 'uint32_t' (aka 'unsigned int') to 'ushort16'}}
ushort16 brBias = pairedConstants.s6; // expected-warning {{implicit conversion loses integer precision: 'uint32_t' (aka 'unsigned int') to 'ushort16'}}
}
+
+
+float double2float_test1(double a) {
+ return a; // expected-warning {{implicit conversion loses floating-point precision: 'double' to 'float'}}
+}
+
+void double2float_test2(double a, float *b) {
+ *b += a; // expected-warning {{implicit conversion when assigning computation result loses floating-point precision: 'double' to 'float'}}
+}
+
+float sinf (float x);
+double double2float_test3(double a) {
+ return sinf(a); // expected-warning {{implicit conversion loses floating-point precision: 'double' to 'float'}}
+}
+
+float double2float_test4(double a, float b) {
+ b -= a; // expected-warning {{implicit conversion when assigning computation result loses floating-point precision: 'double' to 'float'}}
+ return b;
+}
diff --git a/test/Sema/cxx-as-c.c b/test/Sema/cxx-as-c.c
new file mode 100644
index 000000000000..41d7350d1f15
--- /dev/null
+++ b/test/Sema/cxx-as-c.c
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 %s -verify
+
+// PR36157
+struct Foo {
+ Foo(int n) : n_(n) {} // expected-error 1+{{}} expected-warning 1+{{}}
+private:
+ int n;
+};
+int main() { Foo f; } // expected-error 1+{{}}
diff --git a/test/Sema/darwin-tls.c b/test/Sema/darwin-tls.c
index 0fcf096d92ba..6279e0b7e412 100644
--- a/test/Sema/darwin-tls.c
+++ b/test/Sema/darwin-tls.c
@@ -1,12 +1,18 @@
// RUN: not %clang_cc1 -fsyntax-only -triple x86_64-apple-macosx10.6 %s 2>&1 | FileCheck %s --check-prefix NO-TLS
// RUN: %clang_cc1 -fsyntax-only -triple x86_64-apple-macosx10.7 %s 2>&1 | FileCheck %s --check-prefix TLS
+
// RUN: not %clang_cc1 -fsyntax-only -triple arm64-apple-ios7.1 %s 2>&1 | FileCheck %s --check-prefix NO-TLS
// RUN: %clang_cc1 -fsyntax-only -triple arm64-apple-ios8.0 %s 2>&1 | FileCheck %s --check-prefix TLS
// RUN: not %clang_cc1 -fsyntax-only -triple thumbv7s-apple-ios8.3 %s 2>&1 | FileCheck %s --check-prefix NO-TLS
// RUN: %clang_cc1 -fsyntax-only -triple thumbv7s-apple-ios9.0 %s 2>&1 | FileCheck %s --check-prefix TLS
// RUN: %clang_cc1 -fsyntax-only -triple armv7-apple-ios9.0 %s 2>&1 | FileCheck %s --check-prefix TLS
+// RUN: not %clang_cc1 -fsyntax-only -triple i386-apple-ios9.0-simulator %s 2>&1 | FileCheck %s --check-prefix NO-TLS
+// RUN: %clang_cc1 -fsyntax-only -triple i386-apple-ios10.0-simulator %s 2>&1 | FileCheck %s --check-prefix TLS
+
// RUN: not %clang_cc1 -fsyntax-only -triple thumbv7k-apple-watchos1.0 %s 2>&1 | FileCheck %s --check-prefix NO-TLS
// RUN: %clang_cc1 -fsyntax-only -triple thumbv7k-apple-watchos2.0 %s 2>&1 | FileCheck %s --check-prefix TLS
+// RUN: not %clang_cc1 -fsyntax-only -triple i386-apple-watchos2.0-simulator %s 2>&1 | FileCheck %s --check-prefix NO-TLS
+// RUN: %clang_cc1 -fsyntax-only -triple i386-apple-watchos3.0-simulator %s 2>&1 | FileCheck %s --check-prefix TLS
__thread int a;
diff --git a/test/Sema/diagnose_if.c b/test/Sema/diagnose_if.c
index 38a3307d924a..00bb4770f053 100644
--- a/test/Sema/diagnose_if.c
+++ b/test/Sema/diagnose_if.c
@@ -157,3 +157,13 @@ void runAlwaysWarnWithArg(int a) {
// Bug: we would complain about `a` being undeclared if this was spelled
// __diagnose_if__.
void underbarName(int a) __attribute__((__diagnose_if__(a, "", "warning")));
+
+// PR38095
+void constCharStar(const char *str) __attribute__((__diagnose_if__(!str[0], "empty string not allowed", "error"))); // expected-note {{from}}
+void charStar(char *str) __attribute__((__diagnose_if__(!str[0], "empty string not allowed", "error"))); // expected-note {{from}}
+void runConstCharStar() {
+ constCharStar("foo");
+ charStar("bar");
+ constCharStar(""); // expected-error {{empty string not allowed}}
+ charStar(""); // expected-error {{empty string not allowed}}
+}
diff --git a/test/Sema/error-type-safety.cpp b/test/Sema/error-type-safety.cpp
index 223645de0f71..c5aa48fd1e81 100644
--- a/test/Sema/error-type-safety.cpp
+++ b/test/Sema/error-type-safety.cpp
@@ -3,21 +3,50 @@
#define INT_TAG 42
static const int test_in
- __attribute__((type_tag_for_datatype(test, int))) = INT_TAG;
+ __attribute__((type_tag_for_datatype(test, int))) = INT_TAG;
// Argument index: 1, Type tag index: 2
void test_bounds_index(...)
- __attribute__((argument_with_type_tag(test, 1, 2)));
+ __attribute__((argument_with_type_tag(test, 1, 2)));
+
+// Argument index: 1, Type tag index: 2
+void test_bounds_index_ptr(void *, ...)
+ __attribute__((pointer_with_type_tag(test, 1, 2)));
// Argument index: 3, Type tag index: 1
void test_bounds_arg_index(...)
- __attribute__((argument_with_type_tag(test, 3, 1)));
+ __attribute__((argument_with_type_tag(test, 3, 1)));
+
+class C {
+public:
+ // Argument index: 2, Type tag index: 3
+ void test_bounds_index(...)
+ __attribute__((argument_with_type_tag(test, 2, 3)));
+
+ // Argument index: 2, Type tag index: 3
+ void test_bounds_index_ptr(void *, ...)
+ __attribute__((pointer_with_type_tag(test, 2, 3)));
+
+ // Argument index: 4, Type tag index: 2
+ void test_bounds_arg_index(...)
+ __attribute__((argument_with_type_tag(test, 4, 2)));
+};
void test_bounds()
{
+ C c;
+
// Test the boundary edges (ensure no off-by-one) with argument indexing.
test_bounds_index(1, INT_TAG);
+ c.test_bounds_index(1, INT_TAG);
+ test_bounds_index_ptr(0, INT_TAG);
+ c.test_bounds_index_ptr(0, INT_TAG);
+
+ test_bounds_index(1); // expected-error {{type tag index 2 is greater than the number of arguments specified}}
+ c.test_bounds_index(1); // expected-error {{type tag index 3 is greater than the number of arguments specified}}
+ test_bounds_index_ptr(0); // expected-error {{type tag index 2 is greater than the number of arguments specified}}
+ c.test_bounds_index_ptr(0); // expected-error {{type tag index 3 is greater than the number of arguments specified}}
- test_bounds_index(1); // expected-error {{type tag index 2 is greater than the number of arguments specified}}
- test_bounds_arg_index(INT_TAG, 1); // expected-error {{argument index 3 is greater than the number of arguments specified}}
+ test_bounds_arg_index(INT_TAG, 1); // expected-error {{argument index 3 is greater than the number of arguments specified}}
+ c.test_bounds_arg_index(INT_TAG, 1); // expected-error {{argument index 4 is greater than the number of arguments specified}}
}
diff --git a/test/Sema/ext_vector_comparisons.c b/test/Sema/ext_vector_comparisons.c
index 605ba6c55e33..4c632a412f44 100644
--- a/test/Sema/ext_vector_comparisons.c
+++ b/test/Sema/ext_vector_comparisons.c
@@ -6,12 +6,12 @@ static int4 test1() {
int4 vec, rv;
// comparisons to self...
- return vec == vec; // expected-warning{{self-comparison always evaluates to a constant}}
- return vec != vec; // expected-warning{{self-comparison always evaluates to a constant}}
- return vec < vec; // expected-warning{{self-comparison always evaluates to a constant}}
- return vec <= vec; // expected-warning{{self-comparison always evaluates to a constant}}
- return vec > vec; // expected-warning{{self-comparison always evaluates to a constant}}
- return vec >= vec; // expected-warning{{self-comparison always evaluates to a constant}}
+ return vec == vec; // expected-warning{{self-comparison always evaluates to true}}
+ return vec != vec; // expected-warning{{self-comparison always evaluates to false}}
+ return vec < vec; // expected-warning{{self-comparison always evaluates to false}}
+ return vec <= vec; // expected-warning{{self-comparison always evaluates to true}}
+ return vec > vec; // expected-warning{{self-comparison always evaluates to false}}
+ return vec >= vec; // expected-warning{{self-comparison always evaluates to true}}
}
diff --git a/test/Sema/float128-ld-incompatibility.cpp b/test/Sema/float128-ld-incompatibility.cpp
index d993ed7b081c..369b14a87e32 100644
--- a/test/Sema/float128-ld-incompatibility.cpp
+++ b/test/Sema/float128-ld-incompatibility.cpp
@@ -1,10 +1,12 @@
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 \
-// RUN: -triple powerpc64le-unknown-linux-gnu -target-cpu pwr8 \
+// RUN: -triple powerpc64le-unknown-linux-gnu -target-cpu pwr9 \
// RUN: -target-feature +float128 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -triple x86_64-unknown-linux-gnu -Wno-unused-value -Wno-parentheses %s
__float128 qf();
long double ldf();
+#ifdef __PPC__
// FIXME: once operations between long double and __float128 are implemented for
// targets where the types are different, these next two will change
long double ld{qf()}; // expected-error {{cannot initialize a variable of type 'long double' with an rvalue of type '__float128'}}
@@ -17,6 +19,7 @@ auto test1(__float128 q, long double ld) -> decltype(q + ld) { // expected-error
auto test2(long double a, __float128 b) -> decltype(a + b) { // expected-error {{invalid operands to binary expression ('long double' and '__float128')}}
return a + b; // expected-error {{invalid operands to binary expression ('long double' and '__float128')}}
}
+#endif
void test3(bool b) {
long double ld;
diff --git a/test/Sema/inline-asm-validate-amdgpu.cl b/test/Sema/inline-asm-validate-amdgpu.cl
index bc2580c5738b..51009ecb3f1e 100644
--- a/test/Sema/inline-asm-validate-amdgpu.cl
+++ b/test/Sema/inline-asm-validate-amdgpu.cl
@@ -74,3 +74,8 @@ test_double(const __global double *a, const __global double *b, __global double
c[i] = ci;
}
+
+void test_long(int arg0) {
+ long v15_16;
+ __asm volatile("v_lshlrev_b64 v[15:16], 0, %0" : "={v[15:16]}"(v15_16) : "v"(arg0));
+}
diff --git a/test/Sema/integer-overflow.c b/test/Sema/integer-overflow.c
index 44c2629ebf7b..d66ce7ff1647 100644
--- a/test/Sema/integer-overflow.c
+++ b/test/Sema/integer-overflow.c
@@ -158,6 +158,21 @@ uint64_t check_integer_overflows(int i) {
return ((4608 * 1024 * 1024) + ((uint64_t)(4608 * 1024 * 1024)));
}
+void check_integer_overflows_in_function_calls() {
+// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+ (void)f0(4608 * 1024 * 1024);
+
+// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+ uint64_t x = f0(4608 * 1024 * 1024);
+
+// expected-warning@+2 {{overflow in expression; result is 536870912 with type 'int'}}
+ uint64_t (*f0_ptr)(uint64_t) = &f0;
+ (void)(*f0_ptr)(4608 * 1024 * 1024);
+
+// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+ (void)f2(0, f0(4608 * 1024 * 1024));
+}
+
struct s {
unsigned x;
unsigned y;
diff --git a/test/Sema/internal_linkage.c b/test/Sema/internal_linkage.c
index 37090a333315..57315d826e24 100644
--- a/test/Sema/internal_linkage.c
+++ b/test/Sema/internal_linkage.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -fdouble-square-bracket-attributes %s
int var __attribute__((internal_linkage));
int var2 __attribute__((internal_linkage,common)); // expected-error{{'internal_linkage' and 'common' attributes are not compatible}} \
@@ -19,3 +19,9 @@ struct __attribute__((internal_linkage)) S { // expected-warning{{'internal_link
};
__attribute__((internal_linkage("foo"))) int g() {} // expected-error{{'internal_linkage' attribute takes no arguments}}
+
+int var6 [[clang::internal_linkage]];
+int var7 [[clang::internal_linkage]] __attribute__((common)); // expected-error{{'internal_linkage' and 'common' attributes are not compatible}} \
+ // expected-note{{conflicting attribute is here}}
+__attribute__((common)) int var8 [[clang::internal_linkage]]; // expected-error{{'internal_linkage' and 'common' attributes are not compatible}} \
+ // expected-note{{conflicting attribute is here}}
diff --git a/test/Sema/mms-bitfields.c b/test/Sema/mms-bitfields.c
index d238a7a10d0d..cee5b0669d25 100644
--- a/test/Sema/mms-bitfields.c
+++ b/test/Sema/mms-bitfields.c
@@ -11,3 +11,18 @@ struct
// MS pads out bitfields between different types.
static int arr[(sizeof(t) == 8) ? 1 : -1];
+
+#pragma pack (push,1)
+
+typedef unsigned int UINT32;
+
+struct Inner {
+ UINT32 A : 1;
+ UINT32 B : 1;
+ UINT32 C : 1;
+ UINT32 D : 30;
+} Inner;
+
+#pragma pack (pop)
+
+static int arr2[(sizeof(Inner) == 8) ? 1 : -1];
diff --git a/test/Sema/ms_wide_predefined_expr.cpp b/test/Sema/ms_wide_predefined_expr.cpp
index d56d1576cd0c..eb6efa5cdbef 100644
--- a/test/Sema/ms_wide_predefined_expr.cpp
+++ b/test/Sema/ms_wide_predefined_expr.cpp
@@ -7,6 +7,8 @@
void abcdefghi12(void) {
const wchar_t (*ss)[12] = &STR2WSTR(__FUNCTION__);
static int arr[sizeof(STR2WSTR(__FUNCTION__))==12*sizeof(wchar_t) ? 1 : -1];
+ const wchar_t (*ss2)[31] = &STR2WSTR(__FUNCSIG__);
+ static int arr2[sizeof(STR2WSTR(__FUNCSIG__))==31*sizeof(wchar_t) ? 1 : -1];
}
namespace PR13206 {
diff --git a/test/Sema/multistep-explicit-cast.c b/test/Sema/multistep-explicit-cast.c
new file mode 100644
index 000000000000..aeb591961812
--- /dev/null
+++ b/test/Sema/multistep-explicit-cast.c
@@ -0,0 +1,70 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -ast-dump %s | FileCheck %s
+
+// We are checking that implicit casts don't get marked with 'part_of_explicit_cast',
+// while in explicit casts, the implicitly-inserted implicit casts are marked with 'part_of_explicit_cast'
+
+unsigned char implicitcast_0(unsigned int x) {
+ // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} implicitcast_0 'unsigned char (unsigned int)'{{$}}
+ // CHECK: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned char' <IntegralCast>{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned int' <LValueToRValue>{{$}}
+ // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}}
+ return x;
+}
+
+signed char implicitcast_1(unsigned int x) {
+ // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} implicitcast_1 'signed char (unsigned int)'{{$}}
+ // CHECK: ImplicitCastExpr {{.*}} <col:{{.*}}> 'signed char' <IntegralCast>{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned int' <LValueToRValue>{{$}}
+ // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}}
+ return x;
+}
+
+unsigned char implicitcast_2(signed int x) {
+ // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} implicitcast_2 'unsigned char (int)'{{$}}
+ // CHECK: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned char' <IntegralCast>{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'int' <LValueToRValue>{{$}}
+ // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}}
+ return x;
+}
+
+signed char implicitcast_3(signed int x) {
+ // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} implicitcast_3 'signed char (int)'{{$}}
+ // CHECK: ImplicitCastExpr {{.*}} <col:{{.*}}> 'signed char' <IntegralCast>{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'int' <LValueToRValue>{{$}}
+ // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}}
+ return x;
+}
+
+//----------------------------------------------------------------------------//
+
+unsigned char cstylecast_0(unsigned int x) {
+ // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cstylecast_0 'unsigned char (unsigned int)'{{$}}
+ // CHECK: CStyleCastExpr {{.*}} <col:{{.*}}> 'unsigned char' <IntegralCast>{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned int' <LValueToRValue> part_of_explicit_cast{{$}}
+ // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}}
+ return (unsigned char)x;
+}
+
+signed char cstylecast_1(unsigned int x) {
+ // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cstylecast_1 'signed char (unsigned int)'{{$}}
+ // CHECK: CStyleCastExpr {{.*}} <col:{{.*}}> 'signed char' <IntegralCast>{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned int' <LValueToRValue> part_of_explicit_cast{{$}}
+ // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}}
+ return (signed char)x;
+}
+
+unsigned char cstylecast_2(signed int x) {
+ // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cstylecast_2 'unsigned char (int)'{{$}}
+ // CHECK: CStyleCastExpr {{.*}} <col:{{.*}}> 'unsigned char' <IntegralCast>{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'int' <LValueToRValue> part_of_explicit_cast{{$}}
+ // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}}
+ return (unsigned char)x;
+}
+
+signed char cstylecast_3(signed int x) {
+ // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cstylecast_3 'signed char (int)'{{$}}
+ // CHECK: CStyleCastExpr {{.*}} <col:{{.*}}> 'signed char' <IntegralCast>{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'int' <LValueToRValue> part_of_explicit_cast{{$}}
+ // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}}
+ return (signed char)x;
+}
diff --git a/test/Sema/no_stack_protector.c b/test/Sema/no_stack_protector.c
new file mode 100644
index 000000000000..8e52f0982f52
--- /dev/null
+++ b/test/Sema/no_stack_protector.c
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+void __attribute__((no_stack_protector)) foo() {}
+int __attribute__((no_stack_protector)) var; // expected-warning {{'no_stack_protector' attribute only applies to functions}}
+void __attribute__((no_stack_protector(2))) bar() {} // expected-error {{'no_stack_protector' attribute takes no arguments}}
diff --git a/test/Sema/nocf_check_attr_not_allowed.c b/test/Sema/nocf_check_attr_not_allowed.c
new file mode 100644
index 000000000000..2ba71d4aa4c7
--- /dev/null
+++ b/test/Sema/nocf_check_attr_not_allowed.c
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu -fsyntax-only -verify -fcf-protection=branch %s
+// RUN: %clang_cc1 -triple arm-unknown-linux-gnu -fsyntax-only -verify -fcf-protection=branch %s
+// RUN: %clang_cc1 -triple arm-unknown-linux-gnu -fsyntax-only -verify %s
+
+void __attribute__((nocf_check)) foo(); // expected-warning-re{{{{((unknown attribute 'nocf_check' ignored)|('nocf_check' attribute ignored; use -fcf-protection to enable the attribute))}}}}
diff --git a/test/Sema/nonnull.c b/test/Sema/nonnull.c
index b589bb3d1ffd..3410d36ddfbc 100644
--- a/test/Sema/nonnull.c
+++ b/test/Sema/nonnull.c
@@ -1,5 +1,9 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// rdar://9584012
+//
+// Verify All warnings are still issued with the option -fno-delete-null-pointer-checks
+// if nullptr is passed to function with nonnull attribute.
+// RUN: %clang_cc1 -fsyntax-only -fno-delete-null-pointer-checks -verify %s
typedef struct {
char *str;
diff --git a/test/Sema/pr30372.c b/test/Sema/pr30372.c
index e10fa2c84130..87c1c1bc9342 100644
--- a/test/Sema/pr30372.c
+++ b/test/Sema/pr30372.c
@@ -1,7 +1,7 @@
// REQUIRES: x86-registered-target
// RUN: %clang_cc1 %s -triple i386-pc-windows-msvc18.0.0 -disable-free -fms-volatile -fms-extensions -fms-compatibility -fms-compatibility-version=18 -std=c++11 -x c++
-// Check that the parser catching an 'error' from forward declaration of "location" does not lexer out it's subsequent declation.
+// Check that the parser catching an 'error' from forward declaration of "location" does not lexer out it's subsequent declaration.
void foo() {
__asm {
diff --git a/test/Sema/pragma-align-no-header-change-warning.c b/test/Sema/pragma-align-no-header-change-warning.c
new file mode 100644
index 000000000000..dcd61d070567
--- /dev/null
+++ b/test/Sema/pragma-align-no-header-change-warning.c
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -triple i686-apple-darwin9 -fsyntax-only -Wpragma-pack -I %S/Inputs -verify %s
+// expected-no-diagnostics
+
+#include "pragma-align-no-header-change-warning.h"
+
diff --git a/test/Sema/preserve-call-conv.c b/test/Sema/preserve-call-conv.c
index 6bd049ffdca2..6add3095c667 100644
--- a/test/Sema/preserve-call-conv.c
+++ b/test/Sema/preserve-call-conv.c
@@ -2,6 +2,7 @@
// RUN: %clang_cc1 %s -fsyntax-only -triple arm64-unknown-unknown -verify
// RUN: %clang_cc1 %s -fsyntax-only -triple x86_64-unknown-windows-msvc -verify
// RUN: %clang_cc1 %s -fsyntax-only -triple aarch64-unknown-windows-msvc -verify
+// RUN: %clang_cc1 %s -fsyntax-only -triple thumbv7-unknown-windows-msvc -verify
typedef void typedef_fun_t(int);
diff --git a/test/Sema/redefine_extname.c b/test/Sema/redefine_extname.c
index 8202176c9f7b..b1e8dab9244f 100644
--- a/test/Sema/redefine_extname.c
+++ b/test/Sema/redefine_extname.c
@@ -4,3 +4,4 @@
#pragma redefine_extname foo_static bar_static
static int foo_static() { return 1; } // expected-warning {{#pragma redefine_extname is applicable to external C declarations only; not applied to function 'foo_static'}}
+unsigned __int128_t; // expected-error {{redefinition of '__int128_t' as different kind of symbol}}
diff --git a/test/Sema/return.c b/test/Sema/return.c
index 2a58a6ef9e47..debf5ab55f5b 100644
--- a/test/Sema/return.c
+++ b/test/Sema/return.c
@@ -283,6 +283,18 @@ lbl:
goto lbl;
}
+int test36a(int b) {
+ if (b)
+ return 43;
+ __builtin_unreachable();
+}
+
+int test36b(int b) {
+ if (b)
+ return 43;
+ __builtin_assume(0);
+}
+
// PR19074.
void abort(void) __attribute__((noreturn));
#define av_assert0(cond) do {\
diff --git a/test/Sema/riscv-interrupt-attr.c b/test/Sema/riscv-interrupt-attr.c
new file mode 100644
index 000000000000..55f0863c1f53
--- /dev/null
+++ b/test/Sema/riscv-interrupt-attr.c
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -triple riscv32-unknown-elf -emit-llvm -DCHECK_IR < %s| FileCheck %s
+// RUN: %clang_cc1 -triple riscv64-unknown-elf -emit-llvm -DCHECK_IR < %s| FileCheck %s
+// RUN: %clang_cc1 %s -triple riscv32-unknown-elf -verify -fsyntax-only
+// RUN: %clang_cc1 %s -triple riscv64-unknown-elf -verify -fsyntax-only
+
+#if defined(CHECK_IR)
+// CHECK-LABEL: @foo_user() #0
+// CHECK: ret void
+__attribute__((interrupt("user"))) void foo_user(void) {}
+// CHECK-LABEL: @foo_supervisor() #1
+// CHECK: ret void
+__attribute__((interrupt("supervisor"))) void foo_supervisor(void) {}
+// CHECK-LABEL: @foo_machine() #2
+// CHECK: ret void
+__attribute__((interrupt("machine"))) void foo_machine(void) {}
+// CHECK-LABEL: @foo_default() #2
+// CHECK: ret void
+__attribute__((interrupt())) void foo_default(void) {}
+// CHECK-LABEL: @foo_default2() #2
+// CHECK: ret void
+__attribute__((interrupt())) void foo_default2(void) {}
+// CHECK: attributes #0
+// CHECK: "interrupt"="user"
+// CHECK: attributes #1
+// CHECK: "interrupt"="supervisor"
+// CHECK: attributes #2
+// CHECK: "interrupt"="machine"
+#else
+struct a { int b; };
+
+struct a test __attribute__((interrupt)); // expected-warning {{'interrupt' attribute only applies to functions}}
+
+__attribute__((interrupt("USER"))) void foo1(void) {} // expected-warning {{'interrupt' attribute argument not supported: USER}}
+
+__attribute__((interrupt("user", 1))) void foo2(void) {} // expected-error {{'interrupt' attribute takes no more than 1 argument}}
+
+__attribute__((interrupt)) int foo3(void) {return 0;} // expected-warning {{RISC-V 'interrupt' attribute only applies to functions that have a 'void' return type}}
+
+__attribute__((interrupt())) void foo4();
+__attribute__((interrupt())) void foo4() {};
+
+__attribute__((interrupt())) void foo5(int a) {} // expected-warning {{RISC-V 'interrupt' attribute only applies to functions that have no parameters}}
+
+__attribute__((interrupt("user"), interrupt("supervisor"))) void foo6(void) {} // expected-warning {{repeated RISC-V 'interrupt' attribute}} \
+ // expected-note {{repeated RISC-V 'interrupt' attribute is here}}
+
+__attribute__((interrupt, interrupt)) void foo7(void) {} // expected-warning {{repeated RISC-V 'interrupt' attribute}} \
+ // expected-note {{repeated RISC-V 'interrupt' attribute is here}}
+
+__attribute__((interrupt(""))) void foo8(void) {} // expected-warning {{'interrupt' attribute argument not supported}}
+
+__attribute__((interrupt("user"))) void foo9(void);
+__attribute__((interrupt("supervisor"))) void foo9(void);
+__attribute__((interrupt("machine"))) void foo9(void);
+
+__attribute__((interrupt("user"))) void foo10(void) {}
+__attribute__((interrupt("supervisor"))) void foo11(void) {}
+__attribute__((interrupt("machine"))) void foo12(void) {}
+__attribute__((interrupt())) void foo13(void) {}
+__attribute__((interrupt)) void foo14(void) {}
+#endif
+
diff --git a/test/Sema/riscv-interrupt-attr.cpp b/test/Sema/riscv-interrupt-attr.cpp
new file mode 100644
index 000000000000..a01999b3a107
--- /dev/null
+++ b/test/Sema/riscv-interrupt-attr.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -x c++ -triple riscv32-unknown-elf -emit-llvm -DCHECK_IR < %s | FileCheck %s
+// RUN: %clang_cc1 -x c++ -triple riscv64-unknown-elf -emit-llvm -DCHECK_IR < %s | FileCheck %s
+// RUN: %clang_cc1 %s -triple riscv32-unknown-elf -verify -fsyntax-only
+// RUN: %clang_cc1 %s -triple riscv64-unknown-elf -verify -fsyntax-only
+
+#if defined(CHECK_IR)
+// CHECK-LABEL: @_Z11foo_defaultv() #0
+// CHECK: ret void
+[[gnu::interrupt]] void foo_default() {}
+// CHECK: attributes #0
+// CHECK: "interrupt"="machine"
+#else
+[[gnu::interrupt]] [[gnu::interrupt]] void foo1() {} // expected-warning {{repeated RISC-V 'interrupt' attribute}} \
+ // expected-note {{repeated RISC-V 'interrupt' attribute is here}}
+[[gnu::interrupt]] void foo2() {}
+#endif
diff --git a/test/Sema/self-comparison.c b/test/Sema/self-comparison.c
index edb3a6a4c8a5..4c848f030e13 100644
--- a/test/Sema/self-comparison.c
+++ b/test/Sema/self-comparison.c
@@ -60,7 +60,7 @@ int array_comparisons() {
return array1 >= array1; // expected-warning{{self-comparison always evaluates to true}}
//
- // compare differrent arrays
+ // compare different arrays
//
return array1 == array2; // expected-warning{{array comparison always evaluates to false}}
return array1 != array2; // expected-warning{{array comparison always evaluates to true}}
@@ -86,3 +86,8 @@ int R8435950(int i) {
return 1;
}
+__attribute__((weak)) int weak_1[3];
+__attribute__((weak)) int weak_2[3];
+_Bool compare_weak() {
+ return weak_1 == weak_2;
+}
diff --git a/test/Sema/sign-compare-enum.c b/test/Sema/sign-compare-enum.c
index 8661bd502fe5..fb67e323f1d1 100644
--- a/test/Sema/sign-compare-enum.c
+++ b/test/Sema/sign-compare-enum.c
@@ -1,24 +1,77 @@
-// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -fsyntax-only -DUNSIGNED -verify -Wsign-compare %s
-// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fsyntax-only -DSIGNED -verify -Wsign-compare %s
-// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -fsyntax-only -DUNSIGNED -DSILENCE -verify %s
-// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fsyntax-only -DSIGNED -DSILENCE -verify %s
+// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -fsyntax-only -verify -Wsign-compare %s
+// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fsyntax-only -verify -Wsign-compare %s
+// RUN: %clang_cc1 -x c++ -triple=x86_64-pc-linux-gnu -fsyntax-only -verify -Wsign-compare %s
+// RUN: %clang_cc1 -x c++ -triple=x86_64-pc-win32 -fsyntax-only -verify -Wsign-compare %s
-int main() {
- enum A { A_a = 0, A_b = 1 };
- static const int message[] = {0, 1};
- enum A a;
+// Check that -Wsign-compare is off by default.
+// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -fsyntax-only -verify -DSILENCE %s
+#ifdef SILENCE
+// expected-no-diagnostics
+#endif
+
+enum PosEnum {
+ A_a = 0,
+ A_b = 1,
+ A_c = 10
+};
+
+static const int message[] = {0, 1};
+
+int test_pos(enum PosEnum a) {
if (a < 2)
return 0;
-#if defined(SIGNED) && !defined(SILENCE)
- if (a < sizeof(message)/sizeof(message[0])) // expected-warning {{comparison of integers of different signs: 'enum A' and 'unsigned long long'}}
- return 0;
-#else
- // expected-no-diagnostics
+ // No warning, except in Windows C mode, where PosEnum is 'int' and it can
+ // take on any value according to the C standard.
+#if !defined(SILENCE) && defined(_WIN32) && !defined(__cplusplus)
+ // expected-warning@+2 {{comparison of integers of different signs}}
+#endif
if (a < 2U)
return 0;
+
+ unsigned uv = 2;
+#if !defined(SILENCE) && defined(_WIN32) && !defined(__cplusplus)
+ // expected-warning@+2 {{comparison of integers of different signs}}
+#endif
+ if (a < uv)
+ return 1;
+
+#if !defined(SILENCE) && defined(_WIN32) && !defined(__cplusplus)
+ // expected-warning@+2 {{comparison of integers of different signs}}
+#endif
if (a < sizeof(message)/sizeof(message[0]))
return 0;
+ return 4;
+}
+
+enum NegEnum {
+ NE_a = -1,
+ NE_b = 0,
+ NE_c = 10
+};
+
+int test_neg(enum NegEnum a) {
+ if (a < 2)
+ return 0;
+
+#ifndef SILENCE
+ // expected-warning@+2 {{comparison of integers of different signs}}
+#endif
+ if (a < 2U)
+ return 0;
+
+ unsigned uv = 2;
+#ifndef SILENCE
+ // expected-warning@+2 {{comparison of integers of different signs}}
+#endif
+ if (a < uv)
+ return 1;
+
+#ifndef SILENCE
+ // expected-warning@+2 {{comparison of integers of different signs}}
#endif
+ if (a < sizeof(message)/sizeof(message[0]))
+ return 0;
+ return 4;
}
diff --git a/test/Sema/switch.c b/test/Sema/switch.c
index a33300b41f54..638fd997679a 100644
--- a/test/Sema/switch.c
+++ b/test/Sema/switch.c
@@ -372,7 +372,7 @@ void switch_on_ExtendedEnum1(enum ExtendedEnum1 e) {
case EE1_b: break;
case EE1_c: break; // no-warning
case EE1_d: break; // expected-warning {{case value not in enumerated type 'enum ExtendedEnum1'}}
- // expected-warning@-1 {{comparison of two values with different enumeration types in switch statement ('enum ExtendedEnum1' and 'const enum ExtendedEnum1_unrelated')}}
+ // expected-warning@-1 {{comparison of two values with different enumeration types in switch statement ('enum ExtendedEnum1' and 'enum ExtendedEnum1_unrelated')}}
}
}
diff --git a/test/Sema/tautological-constant-compare.c b/test/Sema/tautological-constant-compare.c
index c48aa9944453..b242f35dc6cf 100644
--- a/test/Sema/tautological-constant-compare.c
+++ b/test/Sema/tautological-constant-compare.c
@@ -1,7 +1,13 @@
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -DTEST -verify %s
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -Wno-tautological-constant-compare -verify %s
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -DTEST -verify -x c++ %s
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -Wno-tautological-constant-compare -verify -x c++ %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -Wtautological-constant-in-range-compare -DTEST -verify %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -Wtautological-constant-in-range-compare -DTEST -verify -x c++ %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -Wtautological-type-limit-compare -DTEST -verify %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -Wtautological-type-limit-compare -DTEST -verify -x c++ %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -Wextra -Wno-sign-compare -verify %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -Wextra -Wno-sign-compare -verify -x c++ %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -Wall -verify %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -Wall -verify -x c++ %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -verify -x c++ %s
int value(void);
@@ -122,32 +128,6 @@ int main()
if (32767UL >= s)
return 0;
- if (s == 0UL)
- return 0;
- if (s != 0UL)
- return 0;
- if (s < 0UL) // expected-warning {{comparison of unsigned expression < 0 is always false}}
- return 0;
- if (s <= 0UL)
- return 0;
- if (s > 0UL)
- return 0;
- if (s >= 0UL) // expected-warning {{comparison of unsigned expression >= 0 is always true}}
- return 0;
-
- if (0UL == s)
- return 0;
- if (0UL != s)
- return 0;
- if (0UL < s)
- return 0;
- if (0UL <= s) // expected-warning {{comparison of 0 <= unsigned expression is always true}}
- return 0;
- if (0UL > s) // expected-warning {{comparison of 0 > unsigned expression is always false}}
- return 0;
- if (0UL >= s)
- return 0;
-
enum { ULONG_MAX = (2UL * (unsigned long)__LONG_MAX__ + 1UL) };
if (s == 2UL * (unsigned long)__LONG_MAX__ + 1UL)
return 0;
@@ -498,7 +478,7 @@ int main()
return 0;
#if __SIZEOF_INT128__
- __int128 i128;
+ __int128 i128 = value();
if (i128 == -1) // used to crash
return 0;
#endif
@@ -509,7 +489,7 @@ int main()
no,
maybe
};
- enum E e;
+ enum E e = (enum E)value();
if (e == yes)
return 0;
diff --git a/test/Sema/tautological-constant-enum-compare.c b/test/Sema/tautological-constant-enum-compare.c
index 539439b817dc..99481c7adb33 100644
--- a/test/Sema/tautological-constant-enum-compare.c
+++ b/test/Sema/tautological-constant-enum-compare.c
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -fsyntax-only -DUNSIGNED -verify %s
-// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fsyntax-only -DSIGNED -verify %s
+// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -fsyntax-only -DUNSIGNED -Wtautological-constant-in-range-compare -verify %s
+// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fsyntax-only -DSIGNED -Wtautological-constant-in-range-compare -verify %s
// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -fsyntax-only -DUNSIGNED -DSILENCE -Wno-tautological-constant-compare -verify %s
// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fsyntax-only -DSIGNED -DSILENCE -Wno-tautological-constant-compare -verify %s
diff --git a/test/Sema/tautological-unsigned-enum-zero-compare.c b/test/Sema/tautological-unsigned-enum-zero-compare.c
index a32cfcd8329f..87a56aa40bc3 100644
--- a/test/Sema/tautological-unsigned-enum-zero-compare.c
+++ b/test/Sema/tautological-unsigned-enum-zero-compare.c
@@ -1,9 +1,10 @@
// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -fsyntax-only \
+// RUN: -Wtautological-unsigned-enum-zero-compare \
// RUN: -verify=unsigned,unsigned-signed %s
// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fsyntax-only \
+// RUN: -Wtautological-unsigned-enum-zero-compare \
// RUN: -verify=unsigned-signed %s
// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fsyntax-only \
-// RUN: -Wno-tautological-unsigned-enum-zero-compare \
// RUN: -verify=silence %s
// Okay, this is where it gets complicated.
diff --git a/test/Sema/tautological-unsigned-enum-zero-compare.cpp b/test/Sema/tautological-unsigned-enum-zero-compare.cpp
index a733b6edfc03..0b66c68197d9 100644
--- a/test/Sema/tautological-unsigned-enum-zero-compare.cpp
+++ b/test/Sema/tautological-unsigned-enum-zero-compare.cpp
@@ -1,9 +1,10 @@
// RUN: %clang_cc1 -std=c++11 -triple=x86_64-pc-linux-gnu -fsyntax-only \
+// RUN: -Wtautological-unsigned-enum-zero-compare \
// RUN: -verify=unsigned,unsigned-signed %s
// RUN: %clang_cc1 -std=c++11 -triple=x86_64-pc-win32 -fsyntax-only \
+// RUN: -Wtautological-unsigned-enum-zero-compare \
// RUN: -verify=unsigned-signed %s
// RUN: %clang_cc1 -std=c++11 -triple=x86_64-pc-win32 -fsyntax-only \
-// RUN: -Wno-tautological-unsigned-enum-zero-compare \
// RUN: -verify=silence %s
// silence-no-diagnostics
diff --git a/test/Sema/tautological-unsigned-zero-compare.c b/test/Sema/tautological-unsigned-zero-compare.c
index b9ea02a731a3..4c9394e213c4 100644
--- a/test/Sema/tautological-unsigned-zero-compare.c
+++ b/test/Sema/tautological-unsigned-zero-compare.c
@@ -1,7 +1,13 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
-// RUN: %clang_cc1 -fsyntax-only -Wno-tautological-unsigned-zero-compare -verify=silence %s
-// RUN: %clang_cc1 -fsyntax-only -verify -x c++ %s
-// RUN: %clang_cc1 -fsyntax-only -Wno-tautological-unsigned-zero-compare -verify=silence -x c++ %s
+// RUN: %clang_cc1 -fsyntax-only \
+// RUN: -Wtautological-unsigned-zero-compare \
+// RUN: -verify %s
+// RUN: %clang_cc1 -fsyntax-only \
+// RUN: -verify=silence %s
+// RUN: %clang_cc1 -fsyntax-only \
+// RUN: -Wtautological-unsigned-zero-compare \
+// RUN: -verify -x c++ %s
+// RUN: %clang_cc1 -fsyntax-only \
+// RUN: -verify=silence -x c++ %s
unsigned uvalue(void);
signed int svalue(void);
@@ -32,10 +38,39 @@ int main()
TFunc<unsigned short>();
#endif
+ short s = svalue();
+
unsigned un = uvalue();
// silence-no-diagnostics
+ // Note: both sides are promoted to unsigned long prior to the comparison.
+ if (s == 0UL)
+ return 0;
+ if (s != 0UL)
+ return 0;
+ if (s < 0UL) // expected-warning {{comparison of unsigned expression < 0 is always false}}
+ return 0;
+ if (s <= 0UL)
+ return 0;
+ if (s > 0UL)
+ return 0;
+ if (s >= 0UL) // expected-warning {{comparison of unsigned expression >= 0 is always true}}
+ return 0;
+
+ if (0UL == s)
+ return 0;
+ if (0UL != s)
+ return 0;
+ if (0UL < s)
+ return 0;
+ if (0UL <= s) // expected-warning {{comparison of 0 <= unsigned expression is always true}}
+ return 0;
+ if (0UL > s) // expected-warning {{comparison of 0 > unsigned expression is always false}}
+ return 0;
+ if (0UL >= s)
+ return 0;
+
if (un == 0)
return 0;
if (un != 0)
diff --git a/test/Sema/tls.c b/test/Sema/tls.c
index 38bd3f202246..e4d0656d1dd6 100644
--- a/test/Sema/tls.c
+++ b/test/Sema/tls.c
@@ -12,11 +12,11 @@
// RUN: %clang_cc1 -triple x86_64-pc-win32 -fsyntax-only %s
// RUN: %clang_cc1 -triple i386-pc-win32 -fsyntax-only %s
-// OpenBSD suppports TLS.
+// OpenBSD supports TLS.
// RUN: %clang_cc1 -triple x86_64-pc-openbsd -fsyntax-only %s
// RUN: %clang_cc1 -triple i386-pc-openbsd -fsyntax-only %s
-// Haiku does not suppport TLS.
+// Haiku does not support TLS.
// RUN: not %clang_cc1 -triple i586-pc-haiku -fsyntax-only %s
__thread int x;
diff --git a/test/Sema/transparent-union.c b/test/Sema/transparent-union.c
index 048112767480..7967535db8c1 100644
--- a/test/Sema/transparent-union.c
+++ b/test/Sema/transparent-union.c
@@ -43,6 +43,35 @@ void fi(int i) {} // expected-error{{conflicting types}}
void fvpp(TU); // expected-note{{previous declaration is here}}
void fvpp(void **v) {} // expected-error{{conflicting types}}
+/* Test redeclaring a function taking a transparent_union arg more than twice.
+ Merging different declarations depends on their order, vary order too. */
+
+void f_triple0(TU tu) {}
+void f_triple0(int *); // expected-note{{previous declaration is here}}
+void f_triple0(float *f); // expected-error{{conflicting types}}
+
+void f_triple1(int *);
+void f_triple1(TU tu) {} // expected-note{{previous definition is here}}
+void f_triple1(float *f); // expected-error{{conflicting types}}
+
+void f_triple2(int *); // expected-note{{previous declaration is here}}
+void f_triple2(float *f); // expected-error{{conflicting types}}
+void f_triple2(TU tu) {}
+
+/* Test calling redeclared function taking a transparent_union arg. */
+
+void f_callee(TU);
+void f_callee(int *i) {} // expected-note{{passing argument to parameter 'i' here}}
+
+void caller(void) {
+ TU tu;
+ f_callee(tu); // expected-error{{passing 'TU' to parameter of incompatible type 'int *'}}
+
+ int *i;
+ f_callee(i);
+}
+
+
/* FIXME: we'd like to just use an "int" here and align it differently
from the normal "int", but if we do so we lose the alignment
information from the typedef within the compiler. */
diff --git a/test/Sema/transpose-memset.c b/test/Sema/transpose-memset.c
new file mode 100644
index 000000000000..6112fde34066
--- /dev/null
+++ b/test/Sema/transpose-memset.c
@@ -0,0 +1,61 @@
+// RUN: %clang_cc1 -Wmemset-transposed-args -verify %s
+// RUN: %clang_cc1 -xc++ -Wmemset-transposed-args -verify %s
+
+#define memset(...) __builtin_memset(__VA_ARGS__)
+#define bzero(x,y) __builtin_memset(x, 0, y)
+#define real_bzero(x,y) __builtin_bzero(x,y)
+
+int array[10];
+int *ptr;
+
+int main() {
+ memset(array, sizeof(array), 0); // expected-warning{{'size' argument to memset is '0'; did you mean to transpose the last two arguments?}} expected-note{{parenthesize the third argument to silence}}
+ memset(array, sizeof(array), 0xff); // expected-warning{{setting buffer to a 'sizeof' expression; did you mean to transpose the last two arguments?}} expected-note{{cast the second argument to 'int' to silence}}
+ memset(ptr, sizeof(ptr), 0); // expected-warning{{'size' argument to memset is '0'; did you mean to transpose the last two arguments?}} expected-note{{parenthesize the third argument to silence}}
+ memset(ptr, sizeof(*ptr) * 10, 1); // expected-warning{{setting buffer to a 'sizeof' expression; did you mean to transpose the last two arguments?}} expected-note{{cast the second argument to 'int' to silence}}
+ memset(ptr, 10 * sizeof(int *), 1); // expected-warning{{setting buffer to a 'sizeof' expression; did you mean to transpose the last two arguments?}} expected-note{{cast the second argument to 'int' to silence}}
+ memset(ptr, 10 * sizeof(int *) + 10, 0xff); // expected-warning{{setting buffer to a 'sizeof' expression; did you mean to transpose the last two arguments?}} expected-note{{cast the second argument to 'int' to silence}}
+ memset(ptr, sizeof(char) * sizeof(int *), 0xff); // expected-warning{{setting buffer to a 'sizeof' expression; did you mean to transpose the last two arguments?}} expected-note{{cast the second argument to 'int' to silence}}
+ memset(array, sizeof(array), sizeof(array)); // Uh... fine I guess.
+ memset(array, 0, sizeof(array));
+ memset(ptr, 0, sizeof(int *) * 10);
+ memset(array, (int)sizeof(array), (0)); // no warning
+ memset(array, (int)sizeof(array), 32); // no warning
+ memset(array, 32, (0)); // no warning
+ memset(array, 0, 0); // no warning
+
+ bzero(ptr, 0); // expected-warning{{'size' argument to bzero is '0'}} expected-note{{parenthesize the second argument to silence}}
+ real_bzero(ptr, 0); // expected-warning{{'size' argument to bzero is '0'}} expected-note{{parenthesize the second argument to silence}}
+}
+
+void macros() {
+#define ZERO 0
+ int array[10];
+ memset(array, 0xff, ZERO); // no warning
+ // Still emit a diagnostic for memsetting a sizeof expression:
+ memset(array, sizeof(array), ZERO); // expected-warning{{'sizeof'}} expected-note{{cast}}
+ bzero(array, ZERO); // no warning
+ real_bzero(array, ZERO); // no warning
+#define NESTED_DONT_DIAG \
+ memset(array, 0xff, ZERO); \
+ real_bzero(array, ZERO);
+
+ NESTED_DONT_DIAG;
+
+#define NESTED_DO_DIAG \
+ memset(array, 0xff, 0); \
+ real_bzero(array, 0)
+
+ NESTED_DO_DIAG; // expected-warning{{'size' argument to memset}} expected-warning{{'size' argument to bzero}} expected-note2{{parenthesize}}
+
+#define FN_MACRO(p) \
+ memset(array, 0xff, p)
+
+ FN_MACRO(ZERO);
+ FN_MACRO(0); // FIXME: should we diagnose this?
+
+ __builtin_memset(array, 0, ZERO); // no warning
+ __builtin_bzero(array, ZERO);
+ __builtin_memset(array, 1, 0); // expected-warning{{'size' argument to memset}} // expected-note{{parenthesize}}
+ __builtin_bzero(array, 0); // expected-warning{{'size' argument to bzero}} // expected-note{{parenthesize}}
+}
diff --git a/test/Sema/typedef-retain.c b/test/Sema/typedef-retain.c
index d216466360b7..3d784ce60a75 100644
--- a/test/Sema/typedef-retain.c
+++ b/test/Sema/typedef-retain.c
@@ -16,8 +16,8 @@ void test2(float4 a, int4p result, int i) {
typedef int a[5];
void test3() {
typedef const a b;
- b r;
- r[0]=10; // expected-error {{read-only variable is not assignable}}
+ b r; // expected-note {{variable 'r' declared const here}}
+ r[0] = 10; // expected-error {{cannot assign to variable 'r' with const-qualified type 'b' (aka 'int const[5]')}}
}
int test4(const a y) {
diff --git a/test/Sema/typo-correction.c b/test/Sema/typo-correction.c
index 78007015dcae..e7992ac90bb3 100644
--- a/test/Sema/typo-correction.c
+++ b/test/Sema/typo-correction.c
@@ -87,3 +87,16 @@ __attribute__((overloadable)) void func_overloadable(float);
void overloadable_callexpr(int arg) {
func_overloadable(ar); //expected-error{{use of undeclared identifier}}
}
+
+// rdar://problem/38642201
+struct rdar38642201 {
+ int fieldName;
+};
+
+void rdar38642201_callee(int x, int y);
+void rdar38642201_caller() {
+ struct rdar38642201 structVar;
+ rdar38642201_callee(
+ structVar1.fieldName1.member1, //expected-error{{use of undeclared identifier 'structVar1'}}
+ structVar2.fieldName2.member2); //expected-error{{use of undeclared identifier 'structVar2'}}
+}
diff --git a/test/Sema/uninit-variables.c b/test/Sema/uninit-variables.c
index 9e3dd9d2875b..89ea190cbc61 100644
--- a/test/Sema/uninit-variables.c
+++ b/test/Sema/uninit-variables.c
@@ -111,7 +111,7 @@ void test15() {
int test15b() {
// Warn here with the self-init, since it does result in a use of
- // an unintialized variable and this is the root cause.
+ // an uninitialized variable and this is the root cause.
int x = x; // expected-warning {{variable 'x' is uninitialized when used within its own initialization}}
return x;
}
diff --git a/test/Sema/varargs.c b/test/Sema/varargs.c
index 0ade0cf0aaf9..3fa429163ff5 100644
--- a/test/Sema/varargs.c
+++ b/test/Sema/varargs.c
@@ -112,3 +112,12 @@ void f13(enum E1 e, ...) {
#endif
__builtin_va_end(va);
}
+
+void f14(int e, ...) {
+ // expected-warning@+3 {{implicitly declaring library function 'va_start'}}
+ // expected-note@+2 {{include the header <stdarg.h>}}
+ // expected-error@+1 {{too few arguments to function call}}
+ va_start();
+ __builtin_va_list va;
+ va_start(va, e);
+}
diff --git a/test/Sema/vector-gcc-compat.c b/test/Sema/vector-gcc-compat.c
index 9eb0569b25f0..73b56347f1b1 100644
--- a/test/Sema/vector-gcc-compat.c
+++ b/test/Sema/vector-gcc-compat.c
@@ -114,7 +114,7 @@ void logicTest(void) {
v2i64_a >>= 1;
}
-// For operations with floating point types, we check that interger constants
+// For operations with floating point types, we check that integer constants
// can be respresented, or failing that checking based on the integer types.
void floatTestConstant(void) {
// Test that constants added to floats must be expressible as floating point
diff --git a/test/Sema/vector-gcc-compat.cpp b/test/Sema/vector-gcc-compat.cpp
index 12da314c325f..71497d95eb60 100644
--- a/test/Sema/vector-gcc-compat.cpp
+++ b/test/Sema/vector-gcc-compat.cpp
@@ -112,7 +112,7 @@ void logicTest(void) {
v2i64_a >>= 1;
}
-// For operations with floating point types, we check that interger constants
+// For operations with floating point types, we check that integer constants
// can be respresented, or failing that checking based on the integer types.
void floatTestConstant(void) {
// Test that constants added to floats must be expressible as floating point
diff --git a/test/Sema/vla.c b/test/Sema/vla.c
index b9576bf8cfd6..8d83100b9d68 100644
--- a/test/Sema/vla.c
+++ b/test/Sema/vla.c
@@ -68,3 +68,24 @@ void pr23151(int (*p1)[*]) // expected-error {{variable length array must be bou
int TransformBug(int a) {
return sizeof(*(int(*)[({ goto v; v: a;})]) 0); // expected-warning {{use of GNU statement expression extension}}
}
+
+// PR36157
+struct {
+ int a[ // expected-error {{variable length array in struct}}
+ implicitly_declared() // expected-warning {{implicit declaration}}
+ ];
+};
+int (*use_implicitly_declared)() = implicitly_declared; // ok, was implicitly declared at file scope
+
+void VLAPtrAssign(int size) {
+ int array[1][2][3][size][4][5];
+ // This is well formed
+ int (*p)[2][3][size][4][5] = array;
+ // Last array dimension too large
+ int (*p2)[2][3][size][4][6] = array; // expected-warning {{incompatible pointer types}}
+ // Second array dimension too large
+ int (*p3)[20][3][size][4][5] = array; // expected-warning {{incompatible pointer types}}
+
+ // Not illegal in C, program _might_ be well formed if size == 3.
+ int (*p4)[2][size][3][4][5] = array;
+}
diff --git a/test/Sema/warn-cast-qual.c b/test/Sema/warn-cast-qual.c
index a682cad75ed6..789bde15b13c 100644
--- a/test/Sema/warn-cast-qual.c
+++ b/test/Sema/warn-cast-qual.c
@@ -4,11 +4,15 @@
#include <stdint.h>
void foo() {
- const char * const ptr = 0;
- const char * const *ptrptr = 0;
+ const char *const ptr = 0;
+ const char *const *ptrptr = 0;
+ char *const *ptrcptr = 0;
+ char **ptrptr2 = 0;
char *y = (char *)ptr; // expected-warning {{cast from 'const char *' to 'char *' drops const qualifier}}
- char **y1 = (char **)ptrptr; // expected-warning {{cast from 'const char *const' to 'char *' drops const qualifier}}
+ char **y1 = (char **)ptrptr; // expected-warning {{cast from 'const char *const *' to 'char **' drops const qualifier}}
const char **y2 = (const char **)ptrptr; // expected-warning {{cast from 'const char *const *' to 'const char **' drops const qualifier}}
+ char *const *y3 = (char *const *)ptrptr; // expected-warning {{cast from 'const char *const' to 'char *const' drops const qualifier}}
+ const char **y4 = (const char **)ptrcptr; // expected-warning {{cast from 'char *const *' to 'const char **' drops const qualifier}}
char *z = (char *)(uintptr_t)(const void *)ptr; // no warning
char *z1 = (char *)(const void *)ptr; // expected-warning {{cast from 'const void *' to 'char *' drops const qualifier}}
diff --git a/test/Sema/warn-documentation.m b/test/Sema/warn-documentation.m
index 18ab5bd9e096..0b75bcf80d5f 100644
--- a/test/Sema/warn-documentation.m
+++ b/test/Sema/warn-documentation.m
@@ -218,13 +218,13 @@ int FooBar();
// rdar://14124644
@interface test_vararg1
-/// @param[in] arg somthing
+/// @param[in] arg something
/// @param[in] ... This is vararg
- (void) VarArgMeth : (id)arg, ...;
@end
@implementation test_vararg1
-/// @param[in] arg somthing
+/// @param[in] arg something
/// @param[in] ... This is vararg
- (void) VarArgMeth : (id)arg, ... {}
@end
diff --git a/test/Sema/warn-duplicate-enum.c b/test/Sema/warn-duplicate-enum.c
index f108b3aa6c32..84fdeb4f8fd4 100644
--- a/test/Sema/warn-duplicate-enum.c
+++ b/test/Sema/warn-duplicate-enum.c
@@ -1,29 +1,29 @@
// RUN: %clang_cc1 %s -fsyntax-only -verify -Wduplicate-enum
// RUN: %clang_cc1 %s -x c++ -fsyntax-only -verify -Wduplicate-enum
enum A {
- A1 = 0, // expected-note {{element A1 also has value 0}}
+ A1 = 0, // expected-note {{element 'A1' also has value 0}}
A2 = -1,
- A3, // expected-warning {{element A3 has been implicitly assigned 0 which another element has been assigned}}
+ A3, // expected-warning {{element 'A3' has been implicitly assigned 0 which another element has been assigned}}
A4};
enum B {
- B1 = -1, // expected-note {{element B1 also has value -1}}
- B2, // expected-warning {{element B2 has been implicitly assigned 0 which another element has been assigned}}
+ B1 = -1, // expected-note {{element 'B1' also has value -1}}
+ B2, // expected-warning {{element 'B2' has been implicitly assigned 0 which another element has been assigned}}
B3,
B4 = -2,
- B5, // expected-warning {{element B5 has been implicitly assigned -1 which another element has been assigned}}
- B6 // expected-note {{element B6 also has value 0}}
+ B5, // expected-warning {{element 'B5' has been implicitly assigned -1 which another element has been assigned}}
+ B6 // expected-note {{element 'B6' also has value 0}}
};
-enum C { C1, C2 = -1, C3 }; // expected-warning{{element C1 has been implicitly assigned 0 which another element has been assigned}} \
- // expected-note {{element C3 also has value 0}}
+enum C { C1, C2 = -1, C3 }; // expected-warning{{element 'C1' has been implicitly assigned 0 which another element has been assigned}} \
+ // expected-note {{element 'C3' also has value 0}}
enum D {
D1,
D2,
- D3, // expected-warning{{element D3 has been implicitly assigned 2 which another element has been assigned}}
+ D3, // expected-warning{{element 'D3' has been implicitly assigned 2 which another element has been assigned}}
D4 = D2, // no warning
- D5 = 2 // expected-note {{element D5 also has value 2}}
+ D5 = 2 // expected-note {{element 'D5' also has value 2}}
};
enum E {
diff --git a/test/Sema/warn-strict-prototypes.c b/test/Sema/warn-strict-prototypes.c
index a28f57d48c84..0c23b3b2c245 100644
--- a/test/Sema/warn-strict-prototypes.c
+++ b/test/Sema/warn-strict-prototypes.c
@@ -65,3 +65,9 @@ void foo11(p, p2) int p; int p2; {}
void __attribute__((cdecl)) foo12(d) // expected-warning {{this old-style function definition is not preceded by a prototype}}
short d;
{}
+
+// No warnings for variadic functions. Overloadable attribute is required
+// to avoid err_ellipsis_first_param error.
+// rdar://problem/33251668
+void foo13(...) __attribute__((overloadable));
+void foo13(...) __attribute__((overloadable)) {}
diff --git a/test/Sema/warn-string-conversion.c b/test/Sema/warn-string-conversion.c
index 28dfc1b67dd5..fbbc264f8f9a 100644
--- a/test/Sema/warn-string-conversion.c
+++ b/test/Sema/warn-string-conversion.c
@@ -12,7 +12,7 @@ void assert_error();
#define assert2(expr) \
((expr) ? do_nothing() : assert_error())
-// Expection for common assert form.
+// Exception for common assert form.
void test1() {
assert1(0 && "foo");
assert1("foo" && 0);
diff --git a/test/Sema/warn-type-safety.c b/test/Sema/warn-type-safety.c
index 04313865a8b8..da914730d3aa 100644
--- a/test/Sema/warn-type-safety.c
+++ b/test/Sema/warn-type-safety.c
@@ -7,7 +7,7 @@ struct A {};
typedef struct A *MPI_Datatype;
int wrong1(void *buf, MPI_Datatype datatype)
- __attribute__(( pointer_with_type_tag )); // expected-error {{'pointer_with_type_tag' attribute requires parameter 1 to be an identifier}}
+ __attribute__(( pointer_with_type_tag )); // expected-error {{'pointer_with_type_tag' attribute requires exactly 3 arguments}}
int wrong2(void *buf, MPI_Datatype datatype)
__attribute__(( pointer_with_type_tag(mpi,0,7) )); // expected-error {{attribute parameter 2 is out of bounds}}
@@ -32,11 +32,15 @@ int wrong7(void *buf, MPI_Datatype datatype)
int wrong8(void *buf, MPI_Datatype datatype)
__attribute__(( pointer_with_type_tag(mpi,1,x) )); // expected-error {{attribute requires parameter 3 to be an integer constant}}
-int wrong9 __attribute__(( pointer_with_type_tag(mpi,1,2) )); // expected-error {{attribute only applies to functions and methods}}
+int wrong9 __attribute__(( pointer_with_type_tag(mpi,1,2) )); // expected-error {{'pointer_with_type_tag' attribute only applies to non-K&R-style functions}}
int wrong10(double buf, MPI_Datatype type)
__attribute__(( pointer_with_type_tag(mpi,1,2) )); // expected-error {{'pointer_with_type_tag' attribute only applies to pointer arguments}}
+int ok11(void *, ...)
+ __attribute__(( pointer_with_type_tag(mpi,1,2) ));
+int wrong11(void *, ...)
+ __attribute__(( pointer_with_type_tag(mpi,2,3) )); // expected-error {{'pointer_with_type_tag' attribute only applies to pointer arguments}}
extern struct A datatype_wrong1
__attribute__(( type_tag_for_datatype )); // expected-error {{'type_tag_for_datatype' attribute requires parameter 1 to be an identifier}}
diff --git a/test/Sema/warn-unreachable.c b/test/Sema/warn-unreachable.c
index 440aa0a5a174..aec3b070213c 100644
--- a/test/Sema/warn-unreachable.c
+++ b/test/Sema/warn-unreachable.c
@@ -468,6 +468,7 @@ int pr13910_foo(int x) {
else
return x;
__builtin_unreachable(); // expected no warning
+ __builtin_assume(0); // expected no warning
}
int pr13910_bar(int x) {
@@ -485,16 +486,19 @@ int pr13910_bar2(int x) {
return x;
pr13910_foo(x); // expected-warning {{code will never be executed}}
__builtin_unreachable(); // expected no warning
+ __builtin_assume(0); // expected no warning
pr13910_foo(x); // expected-warning {{code will never be executed}}
}
void pr13910_noreturn() {
raze();
__builtin_unreachable(); // expected no warning
+ __builtin_assume(0); // expected no warning
}
void pr13910_assert() {
myassert(0 && "unreachable");
return;
__builtin_unreachable(); // expected no warning
+ __builtin_assume(0); // expected no warning
}
diff --git a/test/Sema/x86-builtin-palignr.c b/test/Sema/x86-builtin-palignr.c
index f7e70b9c3c45..e055cbb70e9e 100644
--- a/test/Sema/x86-builtin-palignr.c
+++ b/test/Sema/x86-builtin-palignr.c
@@ -4,7 +4,5 @@
#include <tmmintrin.h>
__m64 test1(__m64 a, __m64 b, int c) {
- // FIXME: The "incompatible result type" error is due to pr10112 and should
- // be removed when that is fixed.
- return _mm_alignr_pi8(a, b, c); // expected-error {{argument to '__builtin_ia32_palignr' must be a constant integer}} expected-error {{incompatible result type}}
+ return _mm_alignr_pi8(a, b, c); // expected-error {{argument to '__builtin_ia32_palignr' must be a constant integer}}
}
diff --git a/test/SemaCUDA/amdgpu-attrs.cu b/test/SemaCUDA/amdgpu-attrs.cu
index 87559726869b..63abda9eea37 100644
--- a/test/SemaCUDA/amdgpu-attrs.cu
+++ b/test/SemaCUDA/amdgpu-attrs.cu
@@ -1,110 +1,80 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
-
#include "Inputs/cuda.h"
-// expected-error@+2 {{'amdgpu_flat_work_group_size' attribute only applies to kernel functions}}
__attribute__((amdgpu_flat_work_group_size(32, 64)))
__global__ void flat_work_group_size_32_64() {}
-// expected-error@+2 {{'amdgpu_waves_per_eu' attribute only applies to kernel functions}}
__attribute__((amdgpu_waves_per_eu(2)))
__global__ void waves_per_eu_2() {}
-// expected-error@+2 {{'amdgpu_waves_per_eu' attribute only applies to kernel functions}}
__attribute__((amdgpu_waves_per_eu(2, 4)))
__global__ void waves_per_eu_2_4() {}
-// expected-error@+2 {{'amdgpu_num_sgpr' attribute only applies to kernel functions}}
__attribute__((amdgpu_num_sgpr(32)))
__global__ void num_sgpr_32() {}
-// expected-error@+2 {{'amdgpu_num_vgpr' attribute only applies to kernel functions}}
__attribute__((amdgpu_num_vgpr(64)))
__global__ void num_vgpr_64() {}
-// expected-error@+3 {{'amdgpu_flat_work_group_size' attribute only applies to kernel functions}}
-// fixme-expected-error@+2 {{'amdgpu_waves_per_eu' attribute only applies to kernel functions}}
__attribute__((amdgpu_flat_work_group_size(32, 64), amdgpu_waves_per_eu(2)))
__global__ void flat_work_group_size_32_64_waves_per_eu_2() {}
-// expected-error@+3 {{'amdgpu_flat_work_group_size' attribute only applies to kernel functions}}
-// fixme-expected-error@+2 {{'amdgpu_waves_per_eu' attribute only applies to kernel functions}}
__attribute__((amdgpu_flat_work_group_size(32, 64), amdgpu_waves_per_eu(2, 4)))
__global__ void flat_work_group_size_32_64_waves_per_eu_2_4() {}
-// expected-error@+3 {{'amdgpu_flat_work_group_size' attribute only applies to kernel functions}}
-// fixme-expected-error@+2 {{'amdgpu_num_sgpr' attribute only applies to kernel functions}}
__attribute__((amdgpu_flat_work_group_size(32, 64), amdgpu_num_sgpr(32)))
__global__ void flat_work_group_size_32_64_num_sgpr_32() {}
-// expected-error@+3 {{'amdgpu_flat_work_group_size' attribute only applies to kernel functions}}
-// fixme-expected-error@+2 {{'amdgpu_num_vgpr' attribute only applies to kernel functions}}
__attribute__((amdgpu_flat_work_group_size(32, 64), amdgpu_num_vgpr(64)))
__global__ void flat_work_group_size_32_64_num_vgpr_64() {}
-// expected-error@+3 {{'amdgpu_waves_per_eu' attribute only applies to kernel functions}}
-// fixme-expected-error@+2 {{'amdgpu_num_sgpr' attribute only applies to kernel functions}}
__attribute__((amdgpu_waves_per_eu(2), amdgpu_num_sgpr(32)))
__global__ void waves_per_eu_2_num_sgpr_32() {}
-// expected-error@+3 {{'amdgpu_waves_per_eu' attribute only applies to kernel functions}}
-// fixme-expected-error@+2 {{'amdgpu_num_vgpr' attribute only applies to kernel functions}}
__attribute__((amdgpu_waves_per_eu(2), amdgpu_num_vgpr(64)))
__global__ void waves_per_eu_2_num_vgpr_64() {}
-// expected-error@+3 {{'amdgpu_waves_per_eu' attribute only applies to kernel functions}}
-// fixme-expected-error@+2 {{'amdgpu_num_sgpr' attribute only applies to kernel functions}}
__attribute__((amdgpu_waves_per_eu(2, 4), amdgpu_num_sgpr(32)))
__global__ void waves_per_eu_2_4_num_sgpr_32() {}
-// expected-error@+3 {{'amdgpu_waves_per_eu' attribute only applies to kernel functions}}
-// fixme-expected-error@+2 {{'amdgpu_num_vgpr' attribute only applies to kernel functions}}
__attribute__((amdgpu_waves_per_eu(2, 4), amdgpu_num_vgpr(64)))
__global__ void waves_per_eu_2_4_num_vgpr_64() {}
-// expected-error@+3 {{'amdgpu_num_sgpr' attribute only applies to kernel functions}}
-// fixme-expected-error@+2 {{'amdgpu_num_vgpr' attribute only applies to kernel functions}}
__attribute__((amdgpu_num_sgpr(32), amdgpu_num_vgpr(64)))
__global__ void num_sgpr_32_num_vgpr_64() {}
-
-// expected-error@+4 {{'amdgpu_flat_work_group_size' attribute only applies to kernel functions}}
-// fixme-expected-error@+3 {{'amdgpu_waves_per_eu' attribute only applies to kernel functions}}
-// fixme-expected-error@+2 {{'amdgpu_num_sgpr' attribute only applies to kernel functions}}
__attribute__((amdgpu_flat_work_group_size(32, 64), amdgpu_waves_per_eu(2), amdgpu_num_sgpr(32)))
__global__ void flat_work_group_size_32_64_waves_per_eu_2_num_sgpr_32() {}
-// expected-error@+4 {{'amdgpu_flat_work_group_size' attribute only applies to kernel functions}}
-// fixme-expected-error@+3 {{'amdgpu_waves_per_eu' attribute only applies to kernel functions}}
-// fixme-expected-error@+2 {{'amdgpu_num_vgpr' attribute only applies to kernel functions}}
__attribute__((amdgpu_flat_work_group_size(32, 64), amdgpu_waves_per_eu(2), amdgpu_num_vgpr(64)))
__global__ void flat_work_group_size_32_64_waves_per_eu_2_num_vgpr_64() {}
-// expected-error@+4 {{'amdgpu_flat_work_group_size' attribute only applies to kernel functions}}
-// fixme-expected-error@+3 {{'amdgpu_waves_per_eu' attribute only applies to kernel functions}}
-// fixme-expected-error@+2 {{'amdgpu_num_sgpr' attribute only applies to kernel functions}}
__attribute__((amdgpu_flat_work_group_size(32, 64), amdgpu_waves_per_eu(2, 4), amdgpu_num_sgpr(32)))
__global__ void flat_work_group_size_32_64_waves_per_eu_2_4_num_sgpr_32() {}
-// expected-error@+4 {{'amdgpu_flat_work_group_size' attribute only applies to kernel functions}}
-// fixme-expected-error@+3 {{'amdgpu_waves_per_eu' attribute only applies to kernel functions}}
-// fixme-expected-error@+2 {{'amdgpu_num_vgpr' attribute only applies to kernel functions}}
__attribute__((amdgpu_flat_work_group_size(32, 64), amdgpu_waves_per_eu(2, 4), amdgpu_num_vgpr(64)))
__global__ void flat_work_group_size_32_64_waves_per_eu_2_4_num_vgpr_64() {}
-
-// expected-error@+5 {{'amdgpu_flat_work_group_size' attribute only applies to kernel functions}}
-// fixme-expected-error@+4 {{'amdgpu_waves_per_eu' attribute only applies to kernel functions}}
-// fixme-expected-error@+3 {{'amdgpu_num_sgpr' attribute only applies to kernel functions}}
-// fixme-expected-error@+2 {{'amdgpu_num_vgpr' attribute only applies to kernel functions}}
__attribute__((amdgpu_flat_work_group_size(32, 64), amdgpu_waves_per_eu(2), amdgpu_num_sgpr(32), amdgpu_num_vgpr(64)))
__global__ void flat_work_group_size_32_64_waves_per_eu_2_num_sgpr_32_num_vgpr_64() {}
-// expected-error@+5 {{'amdgpu_flat_work_group_size' attribute only applies to kernel functions}}
-// fixme-expected-error@+4 {{'amdgpu_waves_per_eu' attribute only applies to kernel functions}}
-// fixme-expected-error@+3 {{'amdgpu_num_sgpr' attribute only applies to kernel functions}}
-// fixme-expected-error@+2 {{'amdgpu_num_vgpr' attribute only applies to kernel functions}}
__attribute__((amdgpu_flat_work_group_size(32, 64), amdgpu_waves_per_eu(2, 4), amdgpu_num_sgpr(32), amdgpu_num_vgpr(64)))
__global__ void flat_work_group_size_32_64_waves_per_eu_2_4_num_sgpr_32_num_vgpr_64() {}
+
+// expected-error@+2{{attribute 'reqd_work_group_size' can only be applied to an OpenCL kernel function}}
+__attribute__((reqd_work_group_size(32, 64, 64)))
+__global__ void reqd_work_group_size_32_64_64() {}
+
+// expected-error@+2{{attribute 'work_group_size_hint' can only be applied to an OpenCL kernel function}}
+__attribute__((work_group_size_hint(2, 2, 2)))
+__global__ void work_group_size_hint_2_2_2() {}
+
+// expected-error@+2{{attribute 'vec_type_hint' can only be applied to an OpenCL kernel function}}
+__attribute__((vec_type_hint(int)))
+__global__ void vec_type_hint_int() {}
+
+// expected-error@+2{{attribute 'intel_reqd_sub_group_size' can only be applied to an OpenCL kernel function}}
+__attribute__((intel_reqd_sub_group_size(64)))
+__global__ void intel_reqd_sub_group_size_64() {}
diff --git a/test/SemaCUDA/call-device-fn-from-host.cu b/test/SemaCUDA/call-device-fn-from-host.cu
index 3ea013f3a742..26215d581d25 100644
--- a/test/SemaCUDA/call-device-fn-from-host.cu
+++ b/test/SemaCUDA/call-device-fn-from-host.cu
@@ -83,3 +83,10 @@ template <typename T>
__host__ __device__ void fn_ptr_template() {
auto* ptr = &device_fn; // Not an error because the template isn't instantiated.
}
+
+// Launching a kernel from a host function does not result in code generation
+// for it, so calling HD function which calls a D function should not trigger
+// errors.
+static __host__ __device__ void hd_func() { device_fn(); }
+__global__ void kernel() { hd_func(); }
+void host_func(void) { kernel<<<1, 1>>>(); }
diff --git a/test/SemaCUDA/device-var-init.cu b/test/SemaCUDA/device-var-init.cu
index 71f2352843b2..46cb90da2ecf 100644
--- a/test/SemaCUDA/device-var-init.cu
+++ b/test/SemaCUDA/device-var-init.cu
@@ -225,3 +225,20 @@ inline __host__ __device__ void hd_emitted_host_only() {
static int x = 42; // no error on device because this is never codegen'ed there.
}
void call_hd_emitted_host_only() { hd_emitted_host_only(); }
+
+// Verify that we also check field initializers in instantiated structs.
+struct NontrivialInitializer {
+ __host__ __device__ NontrivialInitializer() : x(43) {}
+ int x;
+};
+
+template <typename T>
+__global__ void bar() {
+ __shared__ T bad;
+// expected-error@-1 {{initialization is not supported for __shared__ variables.}}
+}
+
+void instantiate() {
+ bar<NontrivialInitializer><<<1, 1>>>();
+// expected-note@-1 {{in instantiation of function template specialization 'bar<NontrivialInitializer>' requested here}}
+}
diff --git a/test/SemaCUDA/extern-shared.cu b/test/SemaCUDA/extern-shared.cu
index 9fd7bbba593c..ec6f31695052 100644
--- a/test/SemaCUDA/extern-shared.cu
+++ b/test/SemaCUDA/extern-shared.cu
@@ -1,5 +1,10 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
-// RUN: %clang_cc1 -fsyntax-only -fcuda-is-device -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wundefined-internal -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wundefined-internal -fcuda-is-device -verify %s
+
+// RUN: %clang_cc1 -fsyntax-only -Wundefined-internal -fcuda-rdc -verify=rdc %s
+// RUN: %clang_cc1 -fsyntax-only -Wundefined-internal -fcuda-is-device -fcuda-rdc -verify=rdc %s
+
+// Most of these declarations are fine in separate compilation mode.
#include "Inputs/cuda.h"
@@ -21,3 +26,18 @@ __host__ __device__ void bar() {
extern __shared__ int global; // expected-error {{__shared__ variable 'global' cannot be 'extern'}}
extern __shared__ int global_arr[]; // ok
extern __shared__ int global_arr1[1]; // expected-error {{__shared__ variable 'global_arr1' cannot be 'extern'}}
+
+// Check that, iff we're not in rdc mode, extern __shared__ can appear in an
+// anonymous namespace / in a static function without generating a warning
+// about a variable with internal linkage but no definition
+// (-Wundefined-internal).
+namespace {
+extern __shared__ int global_arr[]; // rdc-warning {{has internal linkage but is not defined}}
+__global__ void in_anon_ns() {
+ extern __shared__ int local_arr[]; // rdc-warning {{has internal linkage but is not defined}}
+
+ // Touch arrays to generate the warning.
+ local_arr[0] = 0; // rdc-note {{used here}}
+ global_arr[0] = 0; // rdc-note {{used here}}
+}
+} // namespace
diff --git a/test/SemaCUDA/function-overload.cu b/test/SemaCUDA/function-overload.cu
index adf488b5eea3..1d78636a7089 100644
--- a/test/SemaCUDA/function-overload.cu
+++ b/test/SemaCUDA/function-overload.cu
@@ -119,7 +119,7 @@ __host__ void hostf() {
HostReturnTy ret_cdh = cdh();
GlobalFnPtr fp_g = g;
- g(); // expected-error {{call to global function g not configured}}
+ g(); // expected-error {{call to global function 'g' not configured}}
g<<<0, 0>>>();
}
@@ -202,7 +202,7 @@ __host__ __device__ void hostdevicef() {
#if defined (__CUDA_ARCH__)
// expected-error@-2 {{reference to __global__ function 'g' in __host__ __device__ function}}
#else
- // expected-error@-4 {{call to global function g not configured}}
+ // expected-error@-4 {{call to global function 'g' not configured}}
#endif
g<<<0,0>>>();
diff --git a/test/SemaCUDA/function-template-overload.cu b/test/SemaCUDA/function-template-overload.cu
index 56bba653958c..5d75d60d0674 100644
--- a/test/SemaCUDA/function-template-overload.cu
+++ b/test/SemaCUDA/function-template-overload.cu
@@ -41,7 +41,7 @@ template <typename T> __device__ HDType overload_hd(T a);
__device__ HDType overload_hd(int a); // OK.
// Verify that target attributes are taken into account when we
-// explicitly specialize or instantiate function tempaltes.
+// explicitly specialize or instantiate function templates.
template <> __host__ HType overload_hd(int a);
// expected-error@-1 {{no function template matches function template specialization 'overload_hd'}}
template __host__ HType overload_hd(long a);
diff --git a/test/SemaCUDA/kernel-call.cu b/test/SemaCUDA/kernel-call.cu
index 47d7762f59ea..b2433c956e25 100644
--- a/test/SemaCUDA/kernel-call.cu
+++ b/test/SemaCUDA/kernel-call.cu
@@ -13,13 +13,13 @@ int h2(int x) { return 1; }
int main(void) {
g1<<<1, 1>>>(42);
- g1(42); // expected-error {{call to global function g1 not configured}}
+ g1(42); // expected-error {{call to global function 'g1' not configured}}
g1<<<1>>>(42); // expected-error {{too few execution configuration arguments to kernel function call}}
g1<<<1, 1, 0, 0, 0>>>(42); // expected-error {{too many execution configuration arguments to kernel function call}}
t1(1);
- h1<<<1, 1>>>(42); // expected-error {{kernel call to non-global function h1}}
+ h1<<<1, 1>>>(42); // expected-error {{kernel call to non-global function 'h1'}}
int (*fp)(int) = h2;
fp<<<1, 1>>>(42); // expected-error {{must have void return type}}
diff --git a/test/SemaCXX/Inputs/std-compare.h b/test/SemaCXX/Inputs/std-compare.h
new file mode 100644
index 000000000000..a6ab605bb527
--- /dev/null
+++ b/test/SemaCXX/Inputs/std-compare.h
@@ -0,0 +1,437 @@
+#ifndef STD_COMPARE_H
+#define STD_COMPARE_H
+
+namespace std {
+inline namespace __1 {
+
+// exposition only
+enum class _EqResult : unsigned char {
+ __zero = 0,
+ __equal = __zero,
+ __equiv = __equal,
+ __nonequal = 1,
+ __nonequiv = __nonequal
+};
+
+enum class _OrdResult : signed char {
+ __less = -1,
+ __greater = 1
+};
+
+enum class _NCmpResult : signed char {
+ __unordered = -127
+};
+
+struct _CmpUnspecifiedType;
+using _CmpUnspecifiedParam = void (_CmpUnspecifiedType::*)();
+
+class weak_equality {
+ constexpr explicit weak_equality(_EqResult __val) noexcept : __value_(__val) {}
+
+public:
+ static const weak_equality equivalent;
+ static const weak_equality nonequivalent;
+
+ friend constexpr bool operator==(weak_equality __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator==(_CmpUnspecifiedParam, weak_equality __v) noexcept;
+ friend constexpr bool operator!=(weak_equality __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator!=(_CmpUnspecifiedParam, weak_equality __v) noexcept;
+ friend constexpr weak_equality operator<=>(weak_equality __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr weak_equality operator<=>(_CmpUnspecifiedParam, weak_equality __v) noexcept;
+
+ // test helper
+ constexpr bool test_eq(weak_equality const &other) const noexcept {
+ return __value_ == other.__value_;
+ }
+
+private:
+ _EqResult __value_;
+};
+
+inline constexpr weak_equality weak_equality::equivalent(_EqResult::__equiv);
+inline constexpr weak_equality weak_equality::nonequivalent(_EqResult::__nonequiv);
+inline constexpr bool operator==(weak_equality __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ == _EqResult::__zero;
+}
+inline constexpr bool operator==(_CmpUnspecifiedParam, weak_equality __v) noexcept {
+ return __v.__value_ == _EqResult::__zero;
+}
+inline constexpr bool operator!=(weak_equality __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ != _EqResult::__zero;
+}
+inline constexpr bool operator!=(_CmpUnspecifiedParam, weak_equality __v) noexcept {
+ return __v.__value_ != _EqResult::__zero;
+}
+
+inline constexpr weak_equality operator<=>(weak_equality __v, _CmpUnspecifiedParam) noexcept {
+ return __v;
+}
+inline constexpr weak_equality operator<=>(_CmpUnspecifiedParam, weak_equality __v) noexcept {
+ return __v;
+}
+
+class strong_equality {
+ explicit constexpr strong_equality(_EqResult __val) noexcept : __value_(__val) {}
+
+public:
+ static const strong_equality equal;
+ static const strong_equality nonequal;
+ static const strong_equality equivalent;
+ static const strong_equality nonequivalent;
+
+ // conversion
+ constexpr operator weak_equality() const noexcept {
+ return __value_ == _EqResult::__zero ? weak_equality::equivalent
+ : weak_equality::nonequivalent;
+ }
+
+ // comparisons
+ friend constexpr bool operator==(strong_equality __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator!=(strong_equality __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator==(_CmpUnspecifiedParam, strong_equality __v) noexcept;
+ friend constexpr bool operator!=(_CmpUnspecifiedParam, strong_equality __v) noexcept;
+
+ friend constexpr strong_equality operator<=>(strong_equality __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr strong_equality operator<=>(_CmpUnspecifiedParam, strong_equality __v) noexcept;
+
+ // test helper
+ constexpr bool test_eq(strong_equality const &other) const noexcept {
+ return __value_ == other.__value_;
+ }
+
+private:
+ _EqResult __value_;
+};
+
+inline constexpr strong_equality strong_equality::equal(_EqResult::__equal);
+inline constexpr strong_equality strong_equality::nonequal(_EqResult::__nonequal);
+inline constexpr strong_equality strong_equality::equivalent(_EqResult::__equiv);
+inline constexpr strong_equality strong_equality::nonequivalent(_EqResult::__nonequiv);
+constexpr bool operator==(strong_equality __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ == _EqResult::__zero;
+}
+constexpr bool operator==(_CmpUnspecifiedParam, strong_equality __v) noexcept {
+ return __v.__value_ == _EqResult::__zero;
+}
+constexpr bool operator!=(strong_equality __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ != _EqResult::__zero;
+}
+constexpr bool operator!=(_CmpUnspecifiedParam, strong_equality __v) noexcept {
+ return __v.__value_ != _EqResult::__zero;
+}
+
+constexpr strong_equality operator<=>(strong_equality __v, _CmpUnspecifiedParam) noexcept {
+ return __v;
+}
+constexpr strong_equality operator<=>(_CmpUnspecifiedParam, strong_equality __v) noexcept {
+ return __v;
+}
+
+class partial_ordering {
+ using _ValueT = signed char;
+ explicit constexpr partial_ordering(_EqResult __v) noexcept
+ : __value_(_ValueT(__v)) {}
+ explicit constexpr partial_ordering(_OrdResult __v) noexcept
+ : __value_(_ValueT(__v)) {}
+ explicit constexpr partial_ordering(_NCmpResult __v) noexcept
+ : __value_(_ValueT(__v)) {}
+
+ constexpr bool __is_ordered() const noexcept {
+ return __value_ != _ValueT(_NCmpResult::__unordered);
+ }
+
+public:
+ // valid values
+ static const partial_ordering less;
+ static const partial_ordering equivalent;
+ static const partial_ordering greater;
+ static const partial_ordering unordered;
+
+ // conversion
+ constexpr operator weak_equality() const noexcept {
+ return __value_ == 0 ? weak_equality::equivalent : weak_equality::nonequivalent;
+ }
+
+ // comparisons
+ friend constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator!=(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator<(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator>(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator==(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
+ friend constexpr bool operator!=(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
+ friend constexpr bool operator<(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
+ friend constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
+ friend constexpr bool operator>(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
+ friend constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
+
+ friend constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
+
+ // test helper
+ constexpr bool test_eq(partial_ordering const &other) const noexcept {
+ return __value_ == other.__value_;
+ }
+
+private:
+ _ValueT __value_;
+};
+
+inline constexpr partial_ordering partial_ordering::less(_OrdResult::__less);
+inline constexpr partial_ordering partial_ordering::equivalent(_EqResult::__equiv);
+inline constexpr partial_ordering partial_ordering::greater(_OrdResult::__greater);
+inline constexpr partial_ordering partial_ordering::unordered(_NCmpResult ::__unordered);
+constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__is_ordered() && __v.__value_ == 0;
+}
+constexpr bool operator<(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__is_ordered() && __v.__value_ < 0;
+}
+constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__is_ordered() && __v.__value_ <= 0;
+}
+constexpr bool operator>(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__is_ordered() && __v.__value_ > 0;
+}
+constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__is_ordered() && __v.__value_ >= 0;
+}
+constexpr bool operator==(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
+ return __v.__is_ordered() && 0 == __v.__value_;
+}
+constexpr bool operator<(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
+ return __v.__is_ordered() && 0 < __v.__value_;
+}
+constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
+ return __v.__is_ordered() && 0 <= __v.__value_;
+}
+constexpr bool operator>(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
+ return __v.__is_ordered() && 0 > __v.__value_;
+}
+constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
+ return __v.__is_ordered() && 0 >= __v.__value_;
+}
+constexpr bool operator!=(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return !__v.__is_ordered() || __v.__value_ != 0;
+}
+constexpr bool operator!=(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
+ return !__v.__is_ordered() || __v.__value_ != 0;
+}
+
+constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v;
+}
+constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
+ return __v < 0 ? partial_ordering::greater : (__v > 0 ? partial_ordering::less : __v);
+}
+
+class weak_ordering {
+ using _ValueT = signed char;
+ explicit constexpr weak_ordering(_EqResult __v) noexcept : __value_(_ValueT(__v)) {}
+ explicit constexpr weak_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {}
+
+public:
+ static const weak_ordering less;
+ static const weak_ordering equivalent;
+ static const weak_ordering greater;
+
+ // conversions
+ constexpr operator weak_equality() const noexcept {
+ return __value_ == 0 ? weak_equality::equivalent
+ : weak_equality::nonequivalent;
+ }
+ constexpr operator partial_ordering() const noexcept {
+ return __value_ == 0 ? partial_ordering::equivalent
+ : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater);
+ }
+
+ // comparisons
+ friend constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator!=(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator<(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator>(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator==(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
+ friend constexpr bool operator!=(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
+ friend constexpr bool operator<(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
+ friend constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
+ friend constexpr bool operator>(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
+ friend constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
+
+ friend constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
+
+ // test helper
+ constexpr bool test_eq(weak_ordering const &other) const noexcept {
+ return __value_ == other.__value_;
+ }
+
+private:
+ _ValueT __value_;
+};
+
+inline constexpr weak_ordering weak_ordering::less(_OrdResult::__less);
+inline constexpr weak_ordering weak_ordering::equivalent(_EqResult::__equiv);
+inline constexpr weak_ordering weak_ordering::greater(_OrdResult::__greater);
+constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ == 0;
+}
+constexpr bool operator!=(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ != 0;
+}
+constexpr bool operator<(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ < 0;
+}
+constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ <= 0;
+}
+constexpr bool operator>(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ > 0;
+}
+constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ >= 0;
+}
+constexpr bool operator==(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
+ return 0 == __v.__value_;
+}
+constexpr bool operator!=(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
+ return 0 != __v.__value_;
+}
+constexpr bool operator<(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
+ return 0 < __v.__value_;
+}
+constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
+ return 0 <= __v.__value_;
+}
+constexpr bool operator>(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
+ return 0 > __v.__value_;
+}
+constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
+ return 0 >= __v.__value_;
+}
+
+constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v;
+}
+constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
+ return __v < 0 ? weak_ordering::greater : (__v > 0 ? weak_ordering::less : __v);
+}
+
+class strong_ordering {
+ using _ValueT = signed char;
+ explicit constexpr strong_ordering(_EqResult __v) noexcept : __value_(static_cast<signed char>(__v)) {}
+ explicit constexpr strong_ordering(_OrdResult __v) noexcept : __value_(static_cast<signed char>(__v)) {}
+
+public:
+ static const strong_ordering less;
+ static const strong_ordering equal;
+ static const strong_ordering equivalent;
+ static const strong_ordering greater;
+
+ // conversions
+ constexpr operator weak_equality() const noexcept {
+ return __value_ == 0 ? weak_equality::equivalent
+ : weak_equality::nonequivalent;
+ }
+ constexpr operator strong_equality() const noexcept {
+ return __value_ == 0 ? strong_equality::equal
+ : strong_equality::nonequal;
+ }
+ constexpr operator partial_ordering() const noexcept {
+ return __value_ == 0 ? partial_ordering::equivalent
+ : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater);
+ }
+ constexpr operator weak_ordering() const noexcept {
+ return __value_ == 0 ? weak_ordering::equivalent
+ : (__value_ < 0 ? weak_ordering::less : weak_ordering::greater);
+ }
+
+ // comparisons
+ friend constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator!=(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator<(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator>(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr bool operator==(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
+ friend constexpr bool operator!=(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
+ friend constexpr bool operator<(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
+ friend constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
+ friend constexpr bool operator>(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
+ friend constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
+
+ friend constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
+ friend constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
+
+ // test helper
+ constexpr bool test_eq(strong_ordering const &other) const noexcept {
+ return __value_ == other.__value_;
+ }
+
+private:
+ _ValueT __value_;
+};
+
+inline constexpr strong_ordering strong_ordering::less(_OrdResult::__less);
+inline constexpr strong_ordering strong_ordering::equal(_EqResult::__equal);
+inline constexpr strong_ordering strong_ordering::equivalent(_EqResult::__equiv);
+inline constexpr strong_ordering strong_ordering::greater(_OrdResult::__greater);
+
+constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ == 0;
+}
+constexpr bool operator!=(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ != 0;
+}
+constexpr bool operator<(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ < 0;
+}
+constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ <= 0;
+}
+constexpr bool operator>(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ > 0;
+}
+constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v.__value_ >= 0;
+}
+constexpr bool operator==(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
+ return 0 == __v.__value_;
+}
+constexpr bool operator!=(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
+ return 0 != __v.__value_;
+}
+constexpr bool operator<(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
+ return 0 < __v.__value_;
+}
+constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
+ return 0 <= __v.__value_;
+}
+constexpr bool operator>(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
+ return 0 > __v.__value_;
+}
+constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
+ return 0 >= __v.__value_;
+}
+
+constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
+ return __v;
+}
+constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
+ return __v < 0 ? strong_ordering::greater : (__v > 0 ? strong_ordering::less : __v);
+}
+
+// named comparison functions
+constexpr bool is_eq(weak_equality __cmp) noexcept { return __cmp == 0; }
+constexpr bool is_neq(weak_equality __cmp) noexcept { return __cmp != 0; }
+constexpr bool is_lt(partial_ordering __cmp) noexcept { return __cmp < 0; }
+constexpr bool is_lteq(partial_ordering __cmp) noexcept { return __cmp <= 0; }
+constexpr bool is_gt(partial_ordering __cmp) noexcept { return __cmp > 0; }
+constexpr bool is_gteq(partial_ordering __cmp) noexcept { return __cmp >= 0; }
+
+} // namespace __1
+} // end namespace std
+
+#endif // STD_COMPARE_H
diff --git a/test/SemaCXX/MicrosoftCompatibility.cpp b/test/SemaCXX/MicrosoftCompatibility.cpp
index d095f6edc617..203a81011142 100644
--- a/test/SemaCXX/MicrosoftCompatibility.cpp
+++ b/test/SemaCXX/MicrosoftCompatibility.cpp
@@ -239,6 +239,15 @@ enum ENUM2 {
ENUM2_c = 0x100000000 // expected-warning {{enumerator value is not representable in the underlying type 'int'}}
};
+namespace NsEnumForwardDecl {
+ enum E *p; // expected-warning {{forward references to 'enum' types are a Microsoft extension}}
+ extern E e;
+}
+// Clang used to complain that NsEnumForwardDecl::E was undeclared below.
+NsEnumForwardDecl::E NsEnumForwardDecl_e;
+namespace NsEnumForwardDecl {
+ extern E e;
+}
namespace PR11791 {
template<class _Ty>
diff --git a/test/SemaCXX/MicrosoftExtensions.cpp b/test/SemaCXX/MicrosoftExtensions.cpp
index c605dcb912f6..55adb68d2e4f 100644
--- a/test/SemaCXX/MicrosoftExtensions.cpp
+++ b/test/SemaCXX/MicrosoftExtensions.cpp
@@ -489,7 +489,6 @@ void AfterClassBody() {
namespace PR24246 {
template <typename TX> struct A {
template <bool> struct largest_type_select;
- // expected-warning@+1 {{explicit specialization of 'largest_type_select' within class scope is a Microsoft extension}}
template <> struct largest_type_select<false> {
blah x; // expected-error {{unknown type name 'blah'}}
};
diff --git a/test/SemaCXX/PR22637.cpp b/test/SemaCXX/PR22637.cpp
new file mode 100644
index 000000000000..1a9bf1df43c5
--- /dev/null
+++ b/test/SemaCXX/PR22637.cpp
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// expected-no-diagnostics
+
+void check(int&) = delete;
+void check(int const&) { }
+
+template <typename>
+struct A {
+ union {
+ int b;
+ };
+ struct {
+ int c;
+ };
+ union {
+ struct {
+ union {
+ struct {
+ struct {
+ int d;
+ };
+ };
+ };
+ };
+ };
+ int e;
+ void foo() const {
+ check(b);
+ check(c);
+ check(d);
+ check(d);
+ check(e);
+ }
+};
+
+int main(){
+ A<int> a;
+ a.foo();
+}
diff --git a/test/SemaCXX/PR35832.cpp b/test/SemaCXX/PR35832.cpp
new file mode 100644
index 000000000000..fd47cd6a5eee
--- /dev/null
+++ b/test/SemaCXX/PR35832.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// expected-no-diagnostics
+
+class B {
+public:
+ int i;
+ struct { struct { union { int j; }; }; };
+ union { int k; };
+};
+
+class X : public B { };
+class Y : public B { };
+
+class Z : public X, public Y {
+public:
+ int a() { return X::i; }
+ int b() { return X::j; }
+ int c() { return X::k; }
+ int d() { return this->X::j; }
+};
diff --git a/test/SemaCXX/PR38235.cpp b/test/SemaCXX/PR38235.cpp
new file mode 100644
index 000000000000..c3fd38ab04d6
--- /dev/null
+++ b/test/SemaCXX/PR38235.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -pedantic %s
+
+enum class E { Foo, Bar = 97119 };
+
+void f() __attribute__((constructor(E::Foo))); // expected-error{{'constructor' attribute requires an integer constant}}
+void f2() __attribute__((constructor(E::Bar)));// expected-error{{'constructor' attribute requires an integer constant}}
+
+void switch_me(E e) {
+ switch (e) {
+ case E::Foo:
+ case E::Bar:
+ break;
+ }
+}
+
+enum class E2;
+
+struct S {
+ static const E e = E::Foo;
+};
diff --git a/test/SemaCXX/access.cpp b/test/SemaCXX/access.cpp
index 29a58a1388ac..74c5f27751b9 100644
--- a/test/SemaCXX/access.cpp
+++ b/test/SemaCXX/access.cpp
@@ -169,3 +169,50 @@ namespace ThisLambdaIsNotMyFriend {
}
void bar() { foo<void>(); }
}
+
+namespace OverloadedMemberFunctionPointer {
+ template<class T, void(T::*pMethod)()>
+ void func0() {}
+
+ template<class T, void(T::*pMethod)(int)>
+ void func1() {}
+
+ template<class T>
+ void func2(void(*fn)()) {} // expected-note 2 {{candidate function template not viable: no overload of 'func}}
+
+ class C {
+ private:
+ friend void friendFunc();
+ void overloadedMethod();
+ protected:
+ void overloadedMethod(int);
+ public:
+ void overloadedMethod(int, int);
+ void method() {
+ func2<int>(&func0<C, &C::overloadedMethod>);
+ func2<int>(&func1<C, &C::overloadedMethod>);
+ }
+ };
+
+ void friendFunc() {
+ func2<int>(&func0<C, &C::overloadedMethod>);
+ func2<int>(&func1<C, &C::overloadedMethod>);
+ }
+
+ void nonFriendFunc() {
+ func2<int>(&func0<C, &C::overloadedMethod>); // expected-error {{no matching function for call to 'func2'}}
+ func2<int>(&func1<C, &C::overloadedMethod>); // expected-error {{no matching function for call to 'func2'}}
+ }
+
+ // r325321 caused an assertion failure when the following code was compiled.
+ class A {
+ template <typename Type> static bool foo1() { return true; }
+
+ public:
+ void init(bool c) {
+ if (c) {
+ auto f = foo1<int>;
+ }
+ }
+ };
+}
diff --git a/test/SemaCXX/address-of-temporary.cpp b/test/SemaCXX/address-of-temporary.cpp
index 5eef1c5521c4..eb0ca3c4a7f1 100644
--- a/test/SemaCXX/address-of-temporary.cpp
+++ b/test/SemaCXX/address-of-temporary.cpp
@@ -26,11 +26,12 @@ namespace PointerToArrayDecay {
template<typename T> void consume(T);
struct S { int *p; };
- void g0() { int *p = Y().a; } // expected-warning{{pointer is initialized by a temporary array}}
- void g1() { int *p = Y{}.a; } // expected-warning{{pointer is initialized by a temporary array}}
- void g2() { int *p = A{}; } // expected-warning{{pointer is initialized by a temporary array}}
- void g3() { int *p = (A){}; } // expected-warning{{pointer is initialized by a temporary array}}
- void g4() { Z *p = AZ{}; } // expected-warning{{pointer is initialized by a temporary array}}
+ void g0() { int *p = Y().a; } // expected-warning{{will be destroyed at the end of the full-expression}}
+ void g1() { int *p = Y{}.a; } // expected-warning{{will be destroyed at the end of the full-expression}}
+ void g2() { int *p = A{}; } // expected-warning{{will be destroyed at the end of the full-expression}}
+ void g3() { int *p = (A){}; } // expected-warning{{will be destroyed at the end of the full-expression}}
+ void g4() { Z *p = AZ{}; } // expected-warning{{will be destroyed at the end of the full-expression}}
+ void g5() { Z *p = &(Z&)(AZ{}[0]); } // expected-warning{{will be destroyed at the end of the full-expression}}
void h0() { consume(Y().a); }
void h1() { consume(Y{}.a); }
@@ -38,10 +39,10 @@ namespace PointerToArrayDecay {
void h3() { consume((A){}); }
void h4() { consume(AZ{}); }
- void i0() { S s = { Y().a }; } // expected-warning{{pointer is initialized by a temporary array}}
- void i1() { S s = { Y{}.a }; } // expected-warning{{pointer is initialized by a temporary array}}
- void i2() { S s = { A{} }; } // expected-warning{{pointer is initialized by a temporary array}}
- void i3() { S s = { (A){} }; } // expected-warning{{pointer is initialized by a temporary array}}
+ void i0() { S s = { Y().a }; } // expected-warning{{will be destroyed at the end of the full-expression}}
+ void i1() { S s = { Y{}.a }; } // expected-warning{{will be destroyed at the end of the full-expression}}
+ void i2() { S s = { A{} }; } // expected-warning{{will be destroyed at the end of the full-expression}}
+ void i3() { S s = { (A){} }; } // expected-warning{{will be destroyed at the end of the full-expression}}
void j0() { (void)S { Y().a }; }
void j1() { (void)S { Y{}.a }; }
diff --git a/test/SemaCXX/address-space-references.cpp b/test/SemaCXX/address-space-references.cpp
index f5a63d24a968..5c297e76c41a 100644
--- a/test/SemaCXX/address-space-references.cpp
+++ b/test/SemaCXX/address-space-references.cpp
@@ -3,10 +3,10 @@
typedef int __attribute__((address_space(1))) int_1;
typedef int __attribute__((address_space(2))) int_2;
-void f0(int_1 &); // expected-note{{candidate function not viable: 1st argument ('int') is in address space 0, but parameter must be in address space 1}} \
-// expected-note{{candidate function not viable: 1st argument ('int_2' (aka '__attribute__((address_space(2))) int')) is in address space 2, but parameter must be in address space 1}}
-void f0(const int_1 &); // expected-note{{candidate function not viable: 1st argument ('int') is in address space 0, but parameter must be in address space 1}} \
-// expected-note{{candidate function not viable: 1st argument ('int_2' (aka '__attribute__((address_space(2))) int')) is in address space 2, but parameter must be in address space 1}}
+void f0(int_1 &); // expected-note{{candidate function not viable: address space mismatch in 1st argument ('int'), parameter type must be 'int_1 &' (aka '__attribute__((address_space(1))) int &')}} \
+// expected-note{{candidate function not viable: address space mismatch in 1st argument ('int_2' (aka '__attribute__((address_space(2))) int')), parameter type must be 'int_1 &' (aka '__attribute__((address_space(1))) int &')}}
+void f0(const int_1 &); // expected-note{{candidate function not viable: address space mismatch in 1st argument ('int'), parameter type must be 'const int_1 &' (aka 'const __attribute__((address_space(1))) int &')}} \
+// expected-note{{candidate function not viable: address space mismatch in 1st argument ('int_2' (aka '__attribute__((address_space(2))) int')), parameter type must be 'const int_1 &' (aka 'const __attribute__((address_space(1))) int &')}}
void test_f0() {
int i;
diff --git a/test/SemaCXX/aggregate-initialization.cpp b/test/SemaCXX/aggregate-initialization.cpp
index 514473f9bcb1..0dfb61333ec2 100644
--- a/test/SemaCXX/aggregate-initialization.cpp
+++ b/test/SemaCXX/aggregate-initialization.cpp
@@ -180,3 +180,9 @@ namespace IdiomaticStdArrayInitDoesNotWarn {
#pragma clang diagnostic pop
}
+
+namespace HugeArraysUseArrayFiller {
+ // All we're checking here is that initialization completes in a reasonable
+ // amount of time.
+ struct A { int n; int arr[1000 * 1000 * 1000]; } a = {1, {2}};
+}
diff --git a/test/SemaCXX/anonymous-struct.cpp b/test/SemaCXX/anonymous-struct.cpp
index bb7e6eb92da3..f89d19959b8f 100644
--- a/test/SemaCXX/anonymous-struct.cpp
+++ b/test/SemaCXX/anonymous-struct.cpp
@@ -16,7 +16,7 @@ struct E {
struct {
S x;
#if __cplusplus <= 199711L
- // expected-error@-2 {{anonymous struct member 'x' has a non-trivial constructor}}
+ // expected-error@-2 {{anonymous struct member 'x' has a non-trivial default constructor}}
#endif
};
static struct {
diff --git a/test/SemaCXX/anonymous-union-export.cpp b/test/SemaCXX/anonymous-union-export.cpp
new file mode 100644
index 000000000000..1d83d809f520
--- /dev/null
+++ b/test/SemaCXX/anonymous-union-export.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -std=c++17 -fmodules-ts -emit-obj -verify -o %t.pcm %s
+
+export module M;
+export {
+ union { bool a; }; // expected-error{{anonymous unions at namespace or global scope must be declared 'static'}}
+}
diff --git a/test/SemaCXX/anonymous-union.cpp b/test/SemaCXX/anonymous-union.cpp
index 0b654266f75f..5538ea470335 100644
--- a/test/SemaCXX/anonymous-union.cpp
+++ b/test/SemaCXX/anonymous-union.cpp
@@ -80,6 +80,10 @@ union { // expected-error{{anonymous unions at namespace or global scope must be
float float_val;
};
+extern "C++" {
+union { }; // expected-error{{anonymous unions at namespace or global scope must be declared 'static'}}
+}
+
static union {
int int_val2; // expected-note{{previous definition is here}}
float float_val2;
diff --git a/test/SemaCXX/array-bounds.cpp b/test/SemaCXX/array-bounds.cpp
index 8ae92e761301..a97f8e312a05 100644
--- a/test/SemaCXX/array-bounds.cpp
+++ b/test/SemaCXX/array-bounds.cpp
@@ -269,3 +269,18 @@ int test_operator_overload_struct_array_index() {
struct P x[10] = {0}; // expected-note {{array 'x' declared here}}
return x[1] + x[11]; // expected-warning {{array index 11 is past the end of the array (which contains 10 elements)}}
}
+
+int multi[2][2][2]; // expected-note 3 {{array 'multi' declared here}}
+int test_multiarray() {
+ return multi[2][0][0] + // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}}
+ multi[0][2][0] + // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}}
+ multi[0][0][2]; // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}}
+}
+
+struct multi_s {
+ int arr[4];
+};
+struct multi_s multi2[4]; // expected-note {{array 'multi2' declared here}}
+int test_struct_multiarray() {
+ return multi2[4].arr[0]; // expected-warning {{array index 4 is past the end of the array (which contains 4 elements)}}
+}
diff --git a/test/SemaCXX/ast-print-crash.cpp b/test/SemaCXX/ast-print-crash.cpp
new file mode 100644
index 000000000000..c108f666d7e3
--- /dev/null
+++ b/test/SemaCXX/ast-print-crash.cpp
@@ -0,0 +1,12 @@
+// RUN: not %clang_cc1 -triple %ms_abi_triple -ast-print %s -std=gnu++11 \
+// RUN: | FileCheck %s
+
+// The test compiles a file with a syntax error which used to cause a crash with
+// -ast-print. Compilation fails due to the syntax error, but compiler should
+// not crash and print out whatever it manager to parse.
+
+// CHECK: struct {
+// CHECK-NEXT: } dont_crash_on_syntax_error;
+// CHECK-NEXT: decltype(nullptr) p;
+struct {
+} dont_crash_on_syntax_error /* missing ; */ decltype(nullptr) p;
diff --git a/test/SemaCXX/ast-print.cpp b/test/SemaCXX/ast-print.cpp
index 408af35c2951..fd1d3fe84fac 100644
--- a/test/SemaCXX/ast-print.cpp
+++ b/test/SemaCXX/ast-print.cpp
@@ -214,10 +214,13 @@ namespace {
struct [[gnu::visibility("hidden")]] S;
}
-// CHECK: struct CXXFunctionalCastExprPrint fce = CXXFunctionalCastExprPrint{};
+// CHECK: struct CXXFunctionalCastExprPrint {
+// CHECK-NEXT: } fce = CXXFunctionalCastExprPrint{};
struct CXXFunctionalCastExprPrint {} fce = CXXFunctionalCastExprPrint{};
-// CHECK: struct CXXTemporaryObjectExprPrint toe = CXXTemporaryObjectExprPrint{};
+// CHECK: struct CXXTemporaryObjectExprPrint {
+// CHECK-NEXT: CXXTemporaryObjectExprPrint();
+// CHECK-NEXT: } toe = CXXTemporaryObjectExprPrint{};
struct CXXTemporaryObjectExprPrint { CXXTemporaryObjectExprPrint(); } toe = CXXTemporaryObjectExprPrint{};
namespace PR24872 {
diff --git a/test/SemaCXX/attr-cpuspecific.cpp b/test/SemaCXX/attr-cpuspecific.cpp
new file mode 100644
index 000000000000..a881b6c4e2ba
--- /dev/null
+++ b/test/SemaCXX/attr-cpuspecific.cpp
@@ -0,0 +1,111 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -verify -fexceptions -fcxx-exceptions %s -std=c++14
+
+// expected-error@+1{{invalid option 'invalid' for cpu_dispatch}}
+void __attribute__((cpu_dispatch(atom, invalid))) invalid_cpu();
+
+void __attribute__((cpu_specific(atom))) no_default(void);
+void __attribute__((cpu_specific(sandybridge))) no_default(void);
+
+struct MVReference {
+ int __attribute__((cpu_specific(sandybridge))) bar(void);
+ int __attribute__((cpu_specific(ivybridge))) bar(void);
+ int __attribute__((cpu_specific(sandybridge))) foo(void);
+};
+
+void use1(void){
+ // OK, will fail in the linker, unless another TU provides the cpu_dispatch.
+ no_default();
+
+ // expected-error@+1 {{call to non-static member function without an object argument}}
+ +MVReference::bar;
+ // expected-error@+1 {{call to non-static member function without an object argument}}
+ +MVReference::foo;
+ // expected-error@+1 {{reference to multiversioned function could not be resolved; did you mean to call it?}}
+ &MVReference::bar;
+ // expected-error@+1 {{reference to multiversioned function could not be resolved; did you mean to call it?}}
+ &MVReference::foo;
+}
+
+//expected-error@+1 {{attribute 'cpu_specific' multiversioned functions do not yet support constexpr functions}}
+constexpr int __attribute__((cpu_specific(sandybridge))) foo(void);
+
+int __attribute__((cpu_specific(sandybridge))) foo2(void);
+//expected-error@+1 {{attribute 'cpu_specific' multiversioned functions do not yet support constexpr functions}}
+constexpr int __attribute__((cpu_specific(ivybridge))) foo2(void);
+
+static int __attribute__((cpu_specific(sandybridge))) bar(void);
+//expected-error@+1 {{multiversioned function declaration has a different storage class}}
+int __attribute__((cpu_dispatch(ivybridge))) bar(void) {}
+
+inline int __attribute__((cpu_specific(sandybridge))) baz(void);
+//expected-error@+1 {{multiversioned function declaration has a different inline specification}}
+int __attribute__((cpu_specific(ivybridge))) baz(void) {return 1;}
+
+void __attribute__((cpu_specific(atom))) diff_return(void);
+//expected-error@+1 {{multiversioned function declaration has a different return type}}
+int __attribute__((cpu_specific(sandybridge))) diff_return(void);
+
+int __attribute__((cpu_specific(atom))) diff_noexcept(void) noexcept(true);
+//expected-error@+2 {{exception specification in declaration does not match previous declaration}}
+//expected-note@-2 {{previous declaration is here}}
+int __attribute__((cpu_specific(sandybridge))) diff_noexcept(void) noexcept(false);
+
+// FIXME: Add support for templates and virtual functions!
+// expected-error@+2 {{multiversioned functions do not yet support function templates}}
+template<typename T>
+int __attribute__((cpu_specific(atom))) foo(T) { return 0; }
+// expected-error@+2 {{multiversioned functions do not yet support function templates}}
+template<typename T>
+int __attribute__((cpu_specific(sandybridge))) foo2(T);
+
+struct S {
+ // expected-error@+2 {{multiversioned functions do not yet support function templates}}
+ template<typename T>
+ int __attribute__((cpu_specific(atom))) foo(T) { return 0; }
+
+ // expected-error@+2 {{multiversioned functions do not yet support function templates}}
+ template<typename T>
+ int __attribute__((cpu_dispatch(ivybridge))) foo2(T) {}
+
+ // expected-error@+1 {{multiversioned functions do not yet support virtual functions}}
+ virtual void __attribute__((cpu_specific(atom))) virt();
+};
+
+extern "C" {
+int __attribute__((cpu_specific(atom))) diff_mangle(void) { return 0; }
+}
+//expected-error@+1 {{multiversioned function declaration has a different linkage}}
+int __attribute__((cpu_specific(sandybridge))) diff_mangle(void) { return 0; }
+
+__attribute__((cpu_specific(atom))) void DiffDecl();
+namespace N {
+using ::DiffDecl;
+// expected-error@+3 {{declaration conflicts with target of using declaration already in scope}}
+// expected-note@-4 {{target of using declaration}}
+// expected-note@-3 {{using declaration}}
+__attribute__((cpu_dispatch(atom))) void DiffDecl();
+} // namespace N
+
+struct SpecialFuncs {
+ // expected-error@+1 {{multiversioned functions do not yet support constructors}}
+ __attribute__((cpu_specific(atom))) SpecialFuncs();
+ // expected-error@+1 {{multiversioned functions do not yet support destructors}}
+ __attribute__((cpu_specific(atom))) ~SpecialFuncs();
+
+ // expected-error@+1 {{multiversioned functions do not yet support defaulted functions}}
+ SpecialFuncs& __attribute__((cpu_specific(atom))) operator=(const SpecialFuncs&) = default;
+ // expected-error@+1 {{multiversioned functions do not yet support deleted functions}}
+ SpecialFuncs& __attribute__((cpu_specific(atom))) operator=(SpecialFuncs&&) = delete;
+};
+
+struct BadOutOfLine {
+ int __attribute__((cpu_specific(atom, ivybridge))) foo(int);
+};
+
+int __attribute__((cpu_specific(atom, ivybridge))) BadOutOfLine::foo(int) { return 0; }
+// expected-error@+2 {{out-of-line definition of 'foo' does not match any declaration in 'BadOutOfLine'}}
+// expected-note@-2 {{member declaration nearly matches}}
+int __attribute__((cpu_specific(sandybridge))) BadOutOfLine::foo(int) { return 1; }
+
+// Ensure Cpp Spelling works.
+[[clang::cpu_specific(ivybridge,atom)]] int CppSpelling(){}
diff --git a/test/SemaCXX/attr-noreturn.cpp b/test/SemaCXX/attr-noreturn.cpp
index 24598e132113..5e7875f08345 100644
--- a/test/SemaCXX/attr-noreturn.cpp
+++ b/test/SemaCXX/attr-noreturn.cpp
@@ -244,11 +244,11 @@ namespace PR15291 {
template <typename T>
void qux(T) {}
- // expected-note@+5 {{candidate function not viable: no overload of 'baz' matching 'void (*)(int) __attribute__((noreturn))' for 1st argument}}
- // expected-note@+4 {{candidate function not viable: no overload of 'qux' matching 'void (*)(int) __attribute__((noreturn))' for 1st argument}}
- // expected-note@+3 {{candidate function not viable: no overload of 'bar' matching 'void (*)(int) __attribute__((noreturn))' for 1st argument}}
- // expected-note@+2 {{candidate function not viable: no overload of 'bar' matching 'void (*)(int)' for 1st argument}}
- // expected-note@+1 {{candidate function not viable: no overload of 'bar' matching 'void (*)(int)' for 1st argument}}
+ // expected-note@+5 {{candidate function template not viable: no overload of 'baz' matching 'void (*)(int) __attribute__((noreturn))' for 1st argument}}
+ // expected-note@+4 {{candidate function template not viable: no overload of 'qux' matching 'void (*)(int) __attribute__((noreturn))' for 1st argument}}
+ // expected-note@+3 {{candidate function template not viable: no overload of 'bar' matching 'void (*)(int) __attribute__((noreturn))' for 1st argument}}
+ // expected-note@+2 {{candidate function template not viable: no overload of 'bar' matching 'void (*)(int)' for 1st argument}}
+ // expected-note@+1 {{candidate function template not viable: no overload of 'bar' matching 'void (*)(int)' for 1st argument}}
template <typename T> void accept_T(T) {}
// expected-note@+1 {{candidate function not viable: no overload of 'bar' matching 'void (*)(int)' for 1st argument}}
diff --git a/test/SemaCXX/attr-print.cpp b/test/SemaCXX/attr-print.cpp
index f40d803e94cb..960050bc7106 100644
--- a/test/SemaCXX/attr-print.cpp
+++ b/test/SemaCXX/attr-print.cpp
@@ -34,3 +34,12 @@ class __attribute__((consumable(unknown))) AttrTester1 {
// CHECK: void callableWhen() __attribute__((callable_when("unconsumed", "consumed")));
void callableWhen() __attribute__((callable_when("unconsumed", "consumed")));
};
+
+// CHECK: class __single_inheritance SingleInheritance;
+class __single_inheritance SingleInheritance;
+
+// CHECK: class __multiple_inheritance MultipleInheritance;
+class __multiple_inheritance MultipleInheritance;
+
+// CHECK: class __virtual_inheritance VirtualInheritance;
+class __virtual_inheritance VirtualInheritance;
diff --git a/test/SemaCXX/attr-section.cpp b/test/SemaCXX/attr-section.cpp
new file mode 100644
index 000000000000..cc80989d22bf
--- /dev/null
+++ b/test/SemaCXX/attr-section.cpp
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -verify -fsyntax-only -triple x86_64-linux-gnu %s
+
+int x __attribute__((section(
+ 42))); // expected-error {{'section' attribute requires a string}}
+
+
+// PR6007
+void test() {
+ __attribute__((section("NEAR,x"))) int n1; // expected-error {{'section' attribute only applies to functions, global variables, Objective-C methods, and Objective-C properties}}
+ __attribute__((section("NEAR,x"))) static int n2; // ok.
+}
+
+// pr9356
+void __attribute__((section("foo"))) test2(); // expected-note {{previous attribute is here}}
+void __attribute__((section("bar"))) test2() {} // expected-warning {{section does not match previous declaration}}
+
+enum __attribute__((section("NEAR,x"))) e { one }; // expected-error {{'section' attribute only applies to}}
+
+extern int a; // expected-note {{previous declaration is here}}
+int *b = &a;
+extern int a __attribute__((section("foo,zed"))); // expected-warning {{section attribute is specified on redeclared variable}}
+
+// Not a warning.
+extern int c;
+int c __attribute__((section("foo,zed")));
+
+// Also OK.
+struct r_debug {};
+extern struct r_debug _r_debug;
+struct r_debug _r_debug __attribute__((nocommon, section(".r_debug,bar")));
+
+namespace override {
+ struct A {
+ __attribute__((section("foo"))) virtual void f(){};
+ };
+ struct B : A {
+ void f() {} // ok
+ };
+ struct C : A {
+ __attribute__((section("bar"))) void f(); // expected-note {{previous}}
+ };
+ __attribute__((section("baz"))) // expected-warning {{section does not match}}
+ void C::f() {}
+}
diff --git a/test/SemaCXX/attr-target-mv.cpp b/test/SemaCXX/attr-target-mv.cpp
new file mode 100644
index 000000000000..11f3a276c7c7
--- /dev/null
+++ b/test/SemaCXX/attr-target-mv.cpp
@@ -0,0 +1,185 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -verify -fexceptions -fcxx-exceptions %s -std=c++14
+void __attribute__((target("default"))) invalid_features(void);
+//expected-error@+2 {{function declaration is missing 'target' attribute in a multiversioned function}}
+//expected-warning@+1 {{unsupported 'hello_world' in the 'target' attribute string; 'target' attribute ignored}}
+void __attribute__((target("hello_world"))) invalid_features(void);
+//expected-error@+1 {{function multiversioning doesn't support feature 'no-sse4.2'}}
+void __attribute__((target("no-sse4.2"))) invalid_features(void);
+
+void __attribute__((target("sse4.2"))) no_default(void);
+void __attribute__((target("arch=sandybridge"))) no_default(void);
+
+void use1(void){
+ // expected-error@+1 {{no matching function for call to 'no_default'}}
+ no_default();
+}
+constexpr int __attribute__((target("sse4.2"))) foo(void) { return 0; }
+constexpr int __attribute__((target("arch=sandybridge"))) foo(void);
+//expected-error@+1 {{multiversioned function declaration has a different constexpr specification}}
+int __attribute__((target("arch=ivybridge"))) foo(void) {return 1;}
+constexpr int __attribute__((target("default"))) foo(void) { return 2; }
+
+int __attribute__((target("sse4.2"))) foo2(void) { return 0; }
+//expected-error@+1 {{multiversioned function declaration has a different constexpr specification}}
+constexpr int __attribute__((target("arch=sandybridge"))) foo2(void);
+int __attribute__((target("arch=ivybridge"))) foo2(void) {return 1;}
+int __attribute__((target("default"))) foo2(void) { return 2; }
+
+static int __attribute__((target("sse4.2"))) bar(void) { return 0; }
+static int __attribute__((target("arch=sandybridge"))) bar(void);
+//expected-error@+1 {{multiversioned function declaration has a different storage class}}
+int __attribute__((target("arch=ivybridge"))) bar(void) {return 1;}
+static int __attribute__((target("default"))) bar(void) { return 2; }
+
+int __attribute__((target("sse4.2"))) bar2(void) { return 0; }
+//expected-error@+1 {{multiversioned function declaration has a different storage class}}
+static int __attribute__((target("arch=sandybridge"))) bar2(void);
+int __attribute__((target("arch=ivybridge"))) bar2(void) {return 1;}
+int __attribute__((target("default"))) bar2(void) { return 2; }
+
+
+inline int __attribute__((target("sse4.2"))) baz(void) { return 0; }
+inline int __attribute__((target("arch=sandybridge"))) baz(void);
+//expected-error@+1 {{multiversioned function declaration has a different inline specification}}
+int __attribute__((target("arch=ivybridge"))) baz(void) {return 1;}
+inline int __attribute__((target("default"))) baz(void) { return 2; }
+
+int __attribute__((target("sse4.2"))) baz2(void) { return 0; }
+//expected-error@+1 {{multiversioned function declaration has a different inline specification}}
+inline int __attribute__((target("arch=sandybridge"))) baz2(void);
+int __attribute__((target("arch=ivybridge"))) baz2(void) {return 1;}
+int __attribute__((target("default"))) baz2(void) { return 2; }
+
+float __attribute__((target("sse4.2"))) bock(void) { return 0; }
+//expected-error@+1 {{multiversioned function declaration has a different return type}}
+int __attribute__((target("arch=sandybridge"))) bock(void);
+//expected-error@+1 {{multiversioned function declaration has a different return type}}
+int __attribute__((target("arch=ivybridge"))) bock(void) {return 1;}
+//expected-error@+1 {{multiversioned function declaration has a different return type}}
+int __attribute__((target("default"))) bock(void) { return 2; }
+
+int __attribute__((target("sse4.2"))) bock2(void) { return 0; }
+//expected-error@+1 {{multiversioned function declaration has a different return type}}
+float __attribute__((target("arch=sandybridge"))) bock2(void);
+int __attribute__((target("arch=ivybridge"))) bock2(void) {return 1;}
+int __attribute__((target("default"))) bock2(void) { return 2; }
+
+auto __attribute__((target("sse4.2"))) bock3(void) -> int { return 0; }
+//expected-error@+1 {{multiversioned function declaration has a different return type}}
+auto __attribute__((target("arch=sandybridge"))) bock3(void) -> short { return (short)0;}
+
+int __attribute__((target("sse4.2"))) bock4(void) noexcept(false) { return 0; }
+//expected-error@+2 {{exception specification in declaration does not match previous declaration}}
+//expected-note@-2 {{previous declaration is here}}
+int __attribute__((target("arch=sandybridge"))) bock4(void) noexcept(true) { return 1;}
+
+// FIXME: Add support for templates and virtual functions!
+template<typename T>
+int __attribute__((target("sse4.2"))) foo(T) { return 0; }
+// expected-error@+2 {{multiversioned functions do not yet support function templates}}
+template<typename T>
+int __attribute__((target("arch=sandybridge"))) foo(T);
+
+// expected-error@+2 {{multiversioned functions do not yet support function templates}}
+template<typename T>
+int __attribute__((target("default"))) foo(T) { return 2; }
+
+struct S {
+ template<typename T>
+ int __attribute__((target("sse4.2"))) foo(T) { return 0; }
+ // expected-error@+2 {{multiversioned functions do not yet support function templates}}
+ template<typename T>
+ int __attribute__((target("arch=sandybridge"))) foo(T);
+
+ // expected-error@+2 {{multiversioned functions do not yet support function templates}}
+ template<typename T>
+ int __attribute__((target("default"))) foo(T) { return 2; }
+
+ // expected-error@+1 {{multiversioned functions do not yet support virtual functions}}
+ virtual void __attribute__((target("default"))) virt();
+};
+
+extern "C" {
+int __attribute__((target("sse4.2"))) diff_mangle(void) { return 0; }
+}
+//expected-error@+1 {{multiversioned function declaration has a different linkage}}
+int __attribute__((target("arch=sandybridge"))) diff_mangle(void) { return 0; }
+
+// expected-error@+1 {{multiversioned functions do not yet support deduced return types}}
+auto __attribute__((target("default"))) deduced_return(void) { return 0; }
+// expected-error@-1 {{cannot initialize return object of type 'auto' with an rvalue of type 'int'}}
+
+auto __attribute__((target("default"))) trailing_return(void)-> int { return 0; }
+
+__attribute__((target("default"))) void DiffDecl();
+namespace N {
+using ::DiffDecl;
+// expected-error@+3 {{declaration conflicts with target of using declaration already in scope}}
+// expected-note@-4 {{target of using declaration}}
+// expected-note@-3 {{using declaration}}
+__attribute__((target("arch=sandybridge"))) void DiffDecl();
+} // namespace N
+
+struct SpecialFuncs {
+ // expected-error@+1 {{multiversioned functions do not yet support constructors}}
+ __attribute__((target("default"))) SpecialFuncs();
+ // expected-error@+1 {{multiversioned functions do not yet support destructors}}
+ __attribute__((target("default"))) ~SpecialFuncs();
+
+ // expected-error@+1 {{multiversioned functions do not yet support defaulted functions}}
+ SpecialFuncs& __attribute__((target("default"))) operator=(const SpecialFuncs&) = default;
+ // expected-error@+1 {{multiversioned functions do not yet support deleted functions}}
+ SpecialFuncs& __attribute__((target("default"))) operator=(SpecialFuncs&&) = delete;
+};
+
+class Secret {
+ int i = 0;
+ __attribute__((target("default")))
+ friend int SecretAccessor(Secret &s);
+ __attribute__((target("arch=sandybridge")))
+ friend int SecretAccessor(Secret &s);
+};
+
+__attribute__((target("default")))
+int SecretAccessor(Secret &s) {
+ return s.i;
+}
+
+__attribute__((target("arch=sandybridge")))
+int SecretAccessor(Secret &s) {
+ return s.i + 2;
+}
+
+__attribute__((target("arch=ivybridge")))
+int SecretAccessor(Secret &s) {
+ //expected-error@+2{{'i' is a private member of 'Secret'}}
+ //expected-note@-20{{implicitly declared private here}}
+ return s.i + 3;
+}
+
+constexpr int __attribute__((target("sse4.2"))) constexpr_foo(void) {
+ return 0;
+}
+constexpr int __attribute__((target("arch=sandybridge"))) constexpr_foo(void);
+constexpr int __attribute__((target("arch=ivybridge"))) constexpr_foo(void) {
+ return 1;
+}
+constexpr int __attribute__((target("default"))) constexpr_foo(void) {
+ return 2;
+}
+
+void constexpr_test() {
+ static_assert(foo() == 2, "Should call 'default' in a constexpr context");
+}
+
+struct BadOutOfLine {
+ int __attribute__((target("sse4.2"))) foo(int);
+ int __attribute__((target("default"))) foo(int);
+};
+
+int __attribute__((target("sse4.2"))) BadOutOfLine::foo(int) { return 0; }
+int __attribute__((target("default"))) BadOutOfLine::foo(int) { return 1; }
+// expected-error@+3 {{out-of-line definition of 'foo' does not match any declaration in 'BadOutOfLine'}}
+// expected-note@-3 {{member declaration nearly matches}}
+// expected-note@-3 {{member declaration nearly matches}}
+int __attribute__((target("arch=atom"))) BadOutOfLine::foo(int) { return 1; }
diff --git a/test/SemaCXX/base-class-ambiguity-check.cpp b/test/SemaCXX/base-class-ambiguity-check.cpp
new file mode 100644
index 000000000000..fc1c4c2cea5e
--- /dev/null
+++ b/test/SemaCXX/base-class-ambiguity-check.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+template <typename T> class Foo {
+ struct Base : T {};
+
+ // Test that this code no longer causes a crash in Sema. rdar://23291875
+ struct Derived : Base, T {};
+};
diff --git a/test/SemaCXX/builtin-classify-type.cpp b/test/SemaCXX/builtin-classify-type.cpp
index f700c1d5baa9..ebc81425e401 100644
--- a/test/SemaCXX/builtin-classify-type.cpp
+++ b/test/SemaCXX/builtin-classify-type.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s
// expected-no-diagnostics
@@ -34,6 +34,14 @@ void foo() {
cl cl_obj;
union { int a; float b; } u_obj;
int arr[10];
+ int (^block)();
+ __attribute__((vector_size(16))) int vec;
+ typedef __attribute__((ext_vector_type(4))) int evec_t;
+ evec_t evec;
+ _Atomic int atomic_i;
+ _Atomic double atomic_d;
+ _Complex int complex_i;
+ _Complex double complex_d;
int a1[__builtin_classify_type(f()) == void_type_class ? 1 : -1];
int a2[__builtin_classify_type(i) == integer_type_class ? 1 : -1];
@@ -44,11 +52,18 @@ void foo() {
int a7[__builtin_classify_type(r) == integer_type_class ? 1 : -1];
int a8[__builtin_classify_type(&cl::baz) == offset_type_class ? 1 : -1];
int a9[__builtin_classify_type(d) == real_type_class ? 1 : -1];
- int a10[__builtin_classify_type(f) == function_type_class ? 1 : -1];
- int a11[__builtin_classify_type(&cl::bar) == method_type_class ? 1 : -1];
+ int a10[__builtin_classify_type(f) == pointer_type_class ? 1 : -1];
+ int a11[__builtin_classify_type(&cl::bar) == record_type_class ? 1 : -1];
int a12[__builtin_classify_type(cl_obj) == record_type_class ? 1 : -1];
int a13[__builtin_classify_type(u_obj) == union_type_class ? 1 : -1];
- int a14[__builtin_classify_type(arr) == array_type_class ? 1 : -1];
- int a15[__builtin_classify_type("abc") == array_type_class ? 1 : -1];
+ int a14[__builtin_classify_type(arr) == pointer_type_class ? 1 : -1];
+ int a15[__builtin_classify_type("abc") == pointer_type_class ? 1 : -1];
+ int a16[__builtin_classify_type(block) == no_type_class ? 1 : -1];
+ int a17[__builtin_classify_type(vec) == no_type_class ? 1 : -1];
+ int a18[__builtin_classify_type(evec) == no_type_class ? 1 : -1];
+ int a19[__builtin_classify_type(atomic_i) == integer_type_class ? 1 : -1];
+ int a20[__builtin_classify_type(atomic_d) == real_type_class ? 1 : -1];
+ int a21[__builtin_classify_type(complex_i) == complex_type_class ? 1 : -1];
+ int a22[__builtin_classify_type(complex_d) == complex_type_class ? 1 : -1];
}
diff --git a/test/SemaCXX/builtin-operator-new-delete.cpp b/test/SemaCXX/builtin-operator-new-delete.cpp
new file mode 100644
index 000000000000..40d47329effb
--- /dev/null
+++ b/test/SemaCXX/builtin-operator-new-delete.cpp
@@ -0,0 +1,157 @@
+// RUN: %clang_cc1 -std=c++1z -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++03 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++03 -faligned-allocation -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -fsized-deallocation %s
+
+#if !__has_builtin(__builtin_operator_new) || !__has_builtin(__builtin_operator_delete)
+#error builtins should always be available
+#endif
+
+#if __has_builtin(__builtin_operator_new) != 201802L || \
+ __has_builtin(__builtin_operator_delete) != 201802L
+#error builtin should report updated value
+#endif
+
+typedef __SIZE_TYPE__ size_t;
+namespace std {
+ struct nothrow_t {};
+#if __cplusplus >= 201103L
+enum class align_val_t : size_t {};
+#else
+ enum align_val_t {
+ // We can't force an underlying type when targeting windows.
+# ifndef _WIN32
+ __zero = 0, __max = (size_t)-1
+# endif
+ };
+#endif
+}
+std::nothrow_t nothrow;
+
+void *operator new(size_t); // expected-note 1+ {{candidate function}}
+void operator delete(void *); // expected-note 1+ {{candidate function}}
+
+// Declare the reserved placement operators.
+void *operator new(size_t, void*) throw(); // expected-note 1+ {{candidate function}}
+void operator delete(void *, void *)throw(); // expected-note 1+ {{candidate function}}
+void *operator new[](size_t, void*) throw();
+void operator delete[](void*, void*) throw();
+
+// Declare the replaceable global allocation operators.
+void *operator new(size_t, const std::nothrow_t &) throw(); // expected-note 1+ {{candidate function}}
+void *operator new[](size_t, const std::nothrow_t &) throw();
+void operator delete(void *, const std::nothrow_t &)throw(); // expected-note 1+ {{candidate function}}
+void operator delete[](void *, const std::nothrow_t &) throw();
+
+// aligned allocation and deallocation functions.
+void* operator new ( size_t count, std::align_val_t al); // expected-note 1+ {{candidate function}}
+void operator delete(void *, std::align_val_t); // expected-note 1+ {{candidate}}
+#ifndef __cpp_aligned_new
+// expected-note@-3 1+ {{non-usual 'operator new' declared here}}
+// expected-note@-3 1+ {{non-usual 'operator delete' declared here}}
+#endif
+void *operator new[](size_t count, std::align_val_t al);
+void operator delete[](void*, std::align_val_t);
+
+void operator delete(void *, size_t); // expected-note 1+ {{candidate}}
+#ifndef __cpp_sized_deallocation
+// expected-note@-2 1+ {{non-usual 'operator delete' declared here}}
+#endif
+void operator delete[](void*, size_t);
+
+// Declare some other placemenet operators.
+void *operator new(size_t, void*, bool) throw(); // expected-note 1+ {{candidate function}}
+void *operator new[](size_t, void*, bool) throw();
+
+void *NP = 0;
+
+void test_typo_in_args() {
+ __builtin_operator_new(DNE); // expected-error {{undeclared identifier 'DNE'}}
+ __builtin_operator_new(DNE, DNE2); // expected-error {{undeclared identifier 'DNE'}} expected-error {{'DNE2'}}
+ __builtin_operator_delete(DNE); // expected-error {{'DNE'}}
+ __builtin_operator_delete(DNE, DNE2); // expected-error {{'DNE'}} expected-error {{'DNE2'}}
+}
+
+void test_arg_types() {
+ __builtin_operator_new(NP); // expected-error {{no matching function for call to 'operator new'}}
+ __builtin_operator_new(NP, std::align_val_t(0)); // expected-error {{no matching function for call to 'operator new'}}}
+}
+void test_return_type() {
+ int w = __builtin_operator_new(42); // expected-error {{cannot initialize a variable of type 'int' with an rvalue of type 'void *'}}
+ int y = __builtin_operator_delete(NP); // expected-error {{cannot initialize a variable of type 'int' with an rvalue of type 'void'}}
+}
+
+void test_aligned_new() {
+#ifdef __cpp_aligned_new
+ void *p = __builtin_operator_new(42, std::align_val_t(2));
+ __builtin_operator_delete(p, std::align_val_t(2));
+#else
+ // FIXME: We've manually declared the aligned new/delete overloads,
+ // but LangOpts::AlignedAllocation is false. Should our overloads be considered
+ // usual allocation/deallocation functions?
+ void *p = __builtin_operator_new(42, std::align_val_t(2)); // expected-error {{call to '__builtin_operator_new' selects non-usual allocation function}}
+ __builtin_operator_delete(p, std::align_val_t(2)); // expected-error {{call to '__builtin_operator_delete' selects non-usual deallocation function}}
+#endif
+}
+
+void test_sized_delete() {
+#ifdef __cpp_sized_deallocation
+ __builtin_operator_delete(NP, 4);
+#else
+ __builtin_operator_delete(NP, 4); // expected-error {{call to '__builtin_operator_delete' selects non-usual deallocation function}}
+#endif
+}
+
+void *operator new(size_t, bool); // expected-note 1+ {{candidate}}
+// expected-note@-1 {{non-usual 'operator new' declared here}}
+void operator delete(void *, bool); // expected-note 1+ {{candidate}}
+// expected-note@-1 {{non-usual 'operator delete' declared here}}
+
+void test_non_usual() {
+ __builtin_operator_new(42, true); // expected-error {{call to '__builtin_operator_new' selects non-usual allocation function}}
+ __builtin_operator_delete(NP, false); // expected-error {{call to '__builtin_operator_delete' selects non-usual deallocation function}}
+}
+
+template <int ID>
+struct Tag {};
+struct ConvertsToTypes {
+ operator std::align_val_t() const;
+ operator Tag<0>() const;
+};
+
+void *operator new(size_t, Tag<0>); // expected-note 0+ {{candidate}}
+void operator delete(void *, Tag<0>); // expected-note 0+ {{candidate}}
+
+void test_ambiguous() {
+#ifdef __cpp_aligned_new
+ ConvertsToTypes cvt;
+ __builtin_operator_new(42, cvt); // expected-error {{call to 'operator new' is ambiguous}}
+ __builtin_operator_delete(NP, cvt); // expected-error {{call to 'operator delete' is ambiguous}}
+#endif
+}
+
+void test_no_args() {
+ __builtin_operator_new(); // expected-error {{no matching function for call to 'operator new'}}
+ __builtin_operator_delete(); // expected-error {{no matching function for call to 'operator delete'}}
+}
+
+void test_no_matching_fn() {
+ Tag<1> tag;
+ __builtin_operator_new(42, tag); // expected-error {{no matching function for call to 'operator new'}}
+ __builtin_operator_delete(NP, tag); // expected-error {{no matching function for call to 'operator delete'}}
+}
+
+template <class Tp, class Up, class RetT>
+void test_dependent_call(Tp new_arg, Up delete_arg, RetT) {
+ RetT ret = __builtin_operator_new(new_arg);
+ __builtin_operator_delete(delete_arg);
+}
+template void test_dependent_call(int, int*, void*);
+
+void test_const_attribute() {
+ __builtin_operator_new(42); // expected-warning {{ignoring return value of function declared with const attribute}}
+#ifdef __cpp_aligned_new
+ __builtin_operator_new(42, std::align_val_t(8)); // expected-warning {{ignoring return value of function declared with const attribute}}
+#endif
+}
diff --git a/test/SemaCXX/builtins-overflow.cpp b/test/SemaCXX/builtins-overflow.cpp
new file mode 100644
index 000000000000..65733c0c154f
--- /dev/null
+++ b/test/SemaCXX/builtins-overflow.cpp
@@ -0,0 +1,93 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// expected-no-diagnostics
+
+#include <limits.h>
+
+int a() {
+ const int x = 3;
+ static int z;
+ constexpr int *y = &z;
+ return []() { return __builtin_sub_overflow((int)x, (int)x, (int *)y); }();
+}
+int a2() {
+ const int x = 3;
+ static int z;
+ constexpr int *y = &z;
+ return []() { return __builtin_sub_overflow(x, x, y); }();
+}
+
+template<typename T>
+struct Result {
+ bool B;
+ T Value;
+ constexpr bool operator==(const Result<T> &Other) {
+ return B == Other.B && Value == Other.Value;
+ }
+};
+
+
+template <typename RET, typename LHS, typename RHS>
+constexpr Result<RET> add(LHS &&lhs, RHS &&rhs) {
+ RET sum{};
+ return {__builtin_add_overflow(lhs, rhs, &sum), sum};
+}
+
+static_assert(add<short>(static_cast<char>(120), static_cast<char>(10)) == Result<short>{false, 130});
+static_assert(add<char>(static_cast<short>(120), static_cast<short>(10)) == Result<char>{true, -126});
+static_assert(add<unsigned int>(INT_MAX, INT_MAX) == Result<unsigned int>{false, static_cast<unsigned int>(INT_MAX) * 2u});
+static_assert(add<int>(static_cast<unsigned int>(INT_MAX), 1u) == Result<int>{true, INT_MIN});
+
+static_assert(add<int>(17, 22) == Result<int>{false, 39});
+static_assert(add<int>(INT_MAX - 22, 24) == Result<int>{true, INT_MIN + 1});
+static_assert(add<int>(INT_MIN + 22, -23) == Result<int>{true, INT_MAX});
+
+template <typename RET, typename LHS, typename RHS>
+constexpr Result<RET> sub(LHS &&lhs, RHS &&rhs) {
+ RET sum{};
+ return {__builtin_sub_overflow(lhs, rhs, &sum), sum};
+}
+
+static_assert(sub<unsigned char>(static_cast<char>(0),static_cast<char>(1)) == Result<unsigned char>{true, UCHAR_MAX});
+static_assert(sub<char>(static_cast<unsigned char>(0),static_cast<unsigned char>(1)) == Result<char>{false, -1});
+static_assert(sub<unsigned short>(static_cast<short>(0),static_cast<short>(1)) == Result<unsigned short>{true, USHRT_MAX});
+
+static_assert(sub<int>(17,22) == Result<int>{false, -5});
+static_assert(sub<int>(INT_MAX - 22, -23) == Result<int>{true, INT_MIN});
+static_assert(sub<int>(INT_MIN + 22, 23) == Result<int>{true, INT_MAX});
+
+template <typename RET, typename LHS, typename RHS>
+constexpr Result<RET> mul(LHS &&lhs, RHS &&rhs) {
+ RET sum{};
+ return {__builtin_mul_overflow(lhs, rhs, &sum), sum};
+}
+
+static_assert(mul<int>(17,22) == Result<int>{false, 374});
+static_assert(mul<int>(INT_MAX / 22, 23) == Result<int>{true, -2049870757});
+static_assert(mul<int>(INT_MIN / 22, -23) == Result<int>{true, -2049870757});
+
+constexpr Result<int> sadd(int lhs, int rhs) {
+ int sum{};
+ return {__builtin_sadd_overflow(lhs, rhs, &sum), sum};
+}
+
+static_assert(sadd(17,22) == Result<int>{false, 39});
+static_assert(sadd(INT_MAX - 22, 23) == Result<int>{true, INT_MIN});
+static_assert(sadd(INT_MIN + 22, -23) == Result<int>{true, INT_MAX});
+
+constexpr Result<int> ssub(int lhs, int rhs) {
+ int sum{};
+ return {__builtin_ssub_overflow(lhs, rhs, &sum), sum};
+}
+
+static_assert(ssub(17,22) == Result<int>{false, -5});
+static_assert(ssub(INT_MAX - 22, -23) == Result<int>{true, INT_MIN});
+static_assert(ssub(INT_MIN + 22, 23) == Result<int>{true, INT_MAX});
+
+constexpr Result<int> smul(int lhs, int rhs) {
+ int sum{};
+ return {__builtin_smul_overflow(lhs, rhs, &sum), sum};
+}
+
+static_assert(smul(17,22) == Result<int>{false, 374});
+static_assert(smul(INT_MAX / 22, 23) == Result<int>{true, -2049870757});
+static_assert(smul(INT_MIN / 22, -23) == Result<int>{true, -2049870757});
diff --git a/test/SemaCXX/char8_t.cpp b/test/SemaCXX/char8_t.cpp
new file mode 100644
index 000000000000..5eb3d7062d2c
--- /dev/null
+++ b/test/SemaCXX/char8_t.cpp
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -fchar8_t -std=c++2a -verify %s
+
+char8_t a = u8'a';
+char8_t b[] = u8"foo";
+char8_t c = 'a';
+char8_t d[] = "foo"; // expected-error {{initializing 'char8_t' array with plain string literal}} expected-note {{add 'u8' prefix}}
+
+char e = u8'a';
+char f[] = u8"foo"; // expected-error {{initialization of char array with UTF-8 string literal is not permitted by '-fchar8_t'}}
+char g = 'a';
+char h[] = "foo";
+
+void disambig() {
+ char8_t (a) = u8'x';
+}
+
+void operator""_a(char);
+void operator""_a(const char*, decltype(sizeof(0)));
+
+void test_udl1() {
+ int &x = u8'a'_a; // expected-error {{no matching literal operator}}
+ float &y = u8"a"_a; // expected-error {{no matching literal operator}}
+}
+
+int &operator""_a(char8_t);
+float &operator""_a(const char8_t*, decltype(sizeof(0)));
+
+void test_udl2() {
+ int &x = u8'a'_a;
+ float &y = u8"a"_a;
+}
+
+template<typename E, typename T> void check(T &&t) {
+ using Check = E;
+ using Check = T;
+}
+void check_deduction() {
+ check<char8_t>(u8'a');
+ check<const char8_t(&)[5]>(u8"a\u1000");
+}
+
+static_assert(sizeof(char8_t) == 1);
+static_assert(char8_t(-1) > 0);
+static_assert(u8"\u0080"[0] > 0);
diff --git a/test/SemaCXX/class-layout.cpp b/test/SemaCXX/class-layout.cpp
index 96552de1cbe2..5403bd6e6a6f 100644
--- a/test/SemaCXX/class-layout.cpp
+++ b/test/SemaCXX/class-layout.cpp
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++98 -Wno-inaccessible-base
// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=6 -DCLANG_ABI_COMPAT=6
// expected-no-diagnostics
#define SA(n, p) int a##n[(p) ? 1 : -1]
@@ -570,3 +571,36 @@ namespace test18 {
SA(0, sizeof(might_use_tail_padding) == 80);
}
} // namespace PR16537
+
+namespace PR37275 {
+ struct X { char c; };
+
+ struct A { int n; };
+ _Static_assert(_Alignof(A) == _Alignof(int), "");
+
+ // __attribute__((packed)) does not apply to base classes.
+ struct __attribute__((packed)) B : X, A {};
+#if defined(CLANG_ABI_COMPAT) && CLANG_ABI_COMPAT <= 6
+ _Static_assert(_Alignof(B) == 1, "");
+ _Static_assert(__builtin_offsetof(B, n) == 1, "");
+#else
+ _Static_assert(_Alignof(B) == _Alignof(int), "");
+ _Static_assert(__builtin_offsetof(B, n) == 4, "");
+#endif
+
+ // #pragma pack does, though.
+#pragma pack(push, 2)
+ struct C : X, A {};
+ _Static_assert(_Alignof(C) == 2, "");
+ _Static_assert(__builtin_offsetof(C, n) == 2, "");
+
+ struct __attribute__((packed)) D : X, A {};
+#if defined(CLANG_ABI_COMPAT) && CLANG_ABI_COMPAT <= 6
+ _Static_assert(_Alignof(D) == 1, "");
+ _Static_assert(__builtin_offsetof(D, n) == 1, "");
+#else
+ _Static_assert(_Alignof(D) == 2, "");
+ _Static_assert(__builtin_offsetof(D, n) == 2, "");
+#endif
+#pragma pack(pop)
+}
diff --git a/test/SemaCXX/code-seg.cpp b/test/SemaCXX/code-seg.cpp
new file mode 100644
index 000000000000..c4ce6613ba9d
--- /dev/null
+++ b/test/SemaCXX/code-seg.cpp
@@ -0,0 +1,105 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions %s -triple x86_64-pc-win32
+
+struct __declspec(code_seg("my_one")) FooOne {
+ int barC();
+};
+
+struct FooTwo {
+ int __declspec(code_seg("my_three")) barD();
+ int barE();
+};
+int __declspec(code_seg("my_four")) FooOne::barC() { return 10; }
+// expected-warning@-1 {{codeseg does not match previous declaration}}
+// expected-note@3{{previous attribute is here}}
+int __declspec(code_seg("my_five")) FooTwo::barD() { return 20; }
+// expected-warning@-1 {{codeseg does not match previous declaration}}
+// expected-note@8 {{previous attribute is here}}
+int __declspec(code_seg("my_six")) FooTwo::barE() { return 30; }
+// expected-warning@-1 {{codeseg does not match previous declaration}}
+// expected-note@9 {{previous declaration is here}}
+
+// Microsoft docs say:
+// If a base-class has a code_seg attribute, derived classes must have the
+// same attribute.
+struct __declspec(code_seg("my_base")) Base1 {};
+struct Base2 {};
+
+struct D1 : Base1 {};
+//expected-error@-1 {{derived class must specify the same code segment as its base classes}}
+// expected-note@24 {{base class 'Base1' specified here}}
+struct __declspec(code_seg("my_derived")) D2 : Base1 {};
+// expected-error@-1 {{derived class must specify the same code segment as its base classes}}
+// expected-note@24 {{base class 'Base1' specified here}}
+struct __declspec(code_seg("my_derived")) D3 : Base2 {};
+// expected-error@-1 {{derived class must specify the same code segment as its base classes}}
+// expected-note@25 {{base class 'Base2' specified here}}
+
+template <typename T> struct __declspec(code_seg("my_base")) MB : T { };
+template <typename T> struct __declspec(code_seg("my_derived")) MD : T { };
+MB<Base1> mb1; // ok
+MB<Base2> mb2;
+// expected-error@37 {{derived class must specify the same code segment as its base classes}}
+// expected-note@-2 {{in instantiation of template class}}
+// expected-note@25 {{base class 'Base2' specified here}}
+MD<Base1> md1;
+// expected-error@38 {{derived class must specify the same code segment as its base classes}}
+// expected-note@-2 {{in instantiation of template class}}
+// expected-note@24 {{base class 'Base1' specified here}}
+MD<Base2> md2;
+// expected-error@38 {{derived class must specify the same code segment as its base classes}}
+// expected-note@-2 {{in instantiation of template class}}
+// expected-note@25 {{base class 'Base2' specified here}}
+
+// Virtual overrides must have the same code_seg.
+struct __declspec(code_seg("my_one")) Base3 {
+ virtual int barA() { return 1; }
+ virtual int __declspec(code_seg("my_two")) barB() { return 2; }
+};
+struct __declspec(code_seg("my_one")) Derived3 : Base3 {
+ int barA() { return 4; } // ok
+ int barB() { return 6; }
+ // expected-error@-1 {{overriding virtual function must specify the same code segment as its overridden function}}
+ // expected-note@56 {{previous declaration is here}}
+};
+
+struct Base4 {
+ virtual int __declspec(code_seg("my_one")) barA() {return 1;}
+ virtual int barB() { return 2;}
+};
+struct Derived4 : Base4 {
+ virtual int barA() {return 1;}
+ // expected-error@-1 {{overriding virtual function must specify the same code segment as its overridden function}}
+ // expected-note@66 {{previous declaration is here}}
+ virtual int __declspec(code_seg("my_two")) barB() {return 1;}
+ // expected-error@-1 {{overriding virtual function must specify the same code segment as its overridden function}}
+ // expected-note@67 {{previous declaration is here}}
+};
+
+// MS gives an error when different code segments are used but a warning when a duplicate is used
+
+// Function
+int __declspec(code_seg("foo")) __declspec(code_seg("foo")) bar1() { return 1; }
+// expected-warning@-1 {{duplicate code segment specifiers}}
+int __declspec(code_seg("foo")) __declspec(code_seg("bar")) bar2() { return 1; }
+// expected-error@-1 {{conflicting code segment specifiers}}
+
+// Class
+struct __declspec(code_seg("foo")) __declspec(code_seg("foo")) Foo {
+ // expected-warning@-1 {{duplicate code segment specifiers}}
+ int bar3() {return 0;}
+};
+struct __declspec(code_seg("foo")) __declspec(code_seg("bar")) FooSix {
+ // expected-error@-1 {{conflicting code segment specifiers}}
+ int bar3() {return 0;}
+};
+
+//Class Members
+struct FooThree {
+ int __declspec(code_seg("foo")) __declspec(code_seg("foo")) bar1() { return 1; }
+ // expected-warning@-1 {{duplicate code segment specifiers}}
+ int __declspec(code_seg("foo")) __declspec(code_seg("bar")) bar2() { return 1; }
+ // expected-error@-1 {{conflicting code segment specifiers}}
+ int bar8();
+ int bar9() { return 9; }
+};
+
diff --git a/test/SemaCXX/code-seg1.cpp b/test/SemaCXX/code-seg1.cpp
new file mode 100644
index 000000000000..0537f9cab352
--- /dev/null
+++ b/test/SemaCXX/code-seg1.cpp
@@ -0,0 +1,97 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions %s -triple x86_64-pc-win32
+
+// Multiple inheritance is involved (code segmments all disagree between the bases and derived class)
+struct __declspec(code_seg("my_base")) Base1 {};
+struct Base2 {};
+
+struct D1 : Base1, Base2 {};
+// expected-error@-1 {{derived class must specify the same code segment as its base classes}}
+// expected-note@4 {{base class 'Base1' specified here}}
+
+struct __declspec(code_seg("my_derived")) D2 : Base2, Base1 {};
+// expected-error@-1 {{derived class must specify the same code segment as its base classes}}
+// expected-error@-2 {{derived class must specify the same code segment as its base classes}}
+// expected-note@5 {{base class 'Base2' specified here}}
+// expected-note@4 {{base class 'Base1' specified here}}
+
+// Multiple inheritance (code segments partially agree between the bases and the derived class)
+struct __declspec(code_seg("base_class")) BaseClass1 {};
+struct __declspec(code_seg("base_class")) BaseClass2 {};
+
+struct Derived1 : BaseClass1, BaseClass2 {};
+// expected-error@-1 {{derived class must specify the same code segment as its base classes}}
+// expected-error@-2 {{derived class must specify the same code segment as its base classes}}
+// expected-note@18 {{base class 'BaseClass1' specified here}}
+// expected-note@19 {{base class 'BaseClass2' specified here}}
+
+struct __declspec(code_seg("derived_class")) Derived2 : BaseClass2, BaseClass1 {};
+// expected-error@-1 {{derived class must specify the same code segment as its base classes}}
+// expected-error@-2 {{derived class must specify the same code segment as its base classes}}
+// expected-note@19 {{base class 'BaseClass2' specified here}}
+// expected-note@18 {{base class 'BaseClass1' specified here}}
+
+struct __declspec(code_seg("base_class")) Derived3 : BaseClass2, BaseClass1 {}; //OK
+struct __declspec(code_seg("base_class")) Derived4 : BaseClass1, BaseClass2 {}; //OK
+
+// Multiple inheritance is involved (code segmments all agree between the bases and derived class)
+struct __declspec(code_seg("foo_base")) B1 {};
+struct __declspec(code_seg("foo_base")) B2 {};
+struct __declspec(code_seg("foo_base")) Derived : B1, B2 {};
+
+// virtual Inheritance is involved (code segmments all disagree between the bases and derived class)
+struct __declspec(code_seg("my_one")) Base {
+ virtual int barA() { return 1; } ;
+};
+
+struct __declspec(code_seg("my_two")) Derived5 : virtual Base {
+ virtual int barB() { return 2; };
+};
+// expected-error@-3 {{derived class must specify the same code segment as its base classes}}
+// expected-note@42 {{base class 'Base' specified here}}
+
+struct __declspec(code_seg("my_three")) Derived6 : virtual Base {
+ virtual int barC() { return 3; };
+};
+// expected-error@-3 {{derived class must specify the same code segment as its base classes}}
+// expected-note@42 {{base class 'Base' specified here}}
+
+struct __declspec(code_seg("my_four")) Derived7 : Derived5, Derived6 {};
+// expected-error@-1 {{derived class must specify the same code segment as its base classes}}
+// expected-error@-2 {{derived class must specify the same code segment as its base classes}}
+// expected-note@46 {{base class 'Derived5' specified here}}
+// expected-note@52 {{base class 'Derived6' specified here}}
+
+// virtual Inheritance is involved (code segmments partially agree between the bases and derived class)
+struct __declspec(code_seg("my_class")) BaseClass {
+ virtual int barA() { return 1; } ;
+};
+
+struct __declspec(code_seg("my_class")) DerivedClass1 : virtual BaseClass { //OK
+ virtual int barB() { return 2; };
+};
+
+struct __declspec(code_seg("my_class")) DerivedClass2 : virtual BaseClass { //OK
+ virtual int barC() { return 3; };
+};
+
+struct __declspec(code_seg("my_derived_one")) DerivedClass3 : DerivedClass1, DerivedClass2 {};
+// expected-error@-1 {{derived class must specify the same code segment as its base classes}}
+// expected-error@-2 {{derived class must specify the same code segment as its base classes}}
+// expected-note@69 {{base class 'DerivedClass1' specified here}}
+// expected-note@73 {{base class 'DerivedClass2' specified here}}
+
+// virtual Inheritance is involved (code segmments all agree between the bases and derived class)
+struct __declspec(code_seg("foo_one")) Class {
+ virtual int foo1() { return 10; } ;
+};
+
+struct __declspec(code_seg("foo_one")) Derived_One: virtual Class { //OK
+ virtual int foo2() { return 20; };
+};
+
+struct __declspec(code_seg("foo_one")) Derived_Two : virtual Class { //OK
+ virtual int foo3() { return 30; };
+};
+
+struct __declspec(code_seg("foo_one")) Derived_Three : Derived_One, Derived_Two {}; //OK
+
diff --git a/test/SemaCXX/compare-cxx2a.cpp b/test/SemaCXX/compare-cxx2a.cpp
index 61d35021cc13..89597587d571 100644
--- a/test/SemaCXX/compare-cxx2a.cpp
+++ b/test/SemaCXX/compare-cxx2a.cpp
@@ -1,30 +1,42 @@
// Force x86-64 because some of our heuristics are actually based
// on integer sizes.
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -pedantic -verify -Wsign-compare -std=c++2a %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -fcxx-exceptions -fsyntax-only -pedantic -verify -Wsign-compare -std=c++2a %s
+
+#include "Inputs/std-compare.h"
+
+#define ASSERT_TYPE(...) static_assert(__is_same(__VA_ARGS__))
+#define ASSERT_EXPR_TYPE(Expr, Expect) static_assert(__is_same(decltype(Expr), Expect));
+
+void self_compare() {
+ int a;
+ int *b = nullptr;
+
+ (void)(a <=> a); // expected-warning {{self-comparison always evaluates to 'std::strong_ordering::equal'}}
+ (void)(b <=> b); // expected-warning {{self-comparison always evaluates to 'std::strong_ordering::equal'}}
+}
void test0(long a, unsigned long b) {
- enum EnumA {A};
+ enum EnumA : int {A};
enum EnumB {B};
enum EnumC {C = 0x10000};
- // (a,b)
- // FIXME: <=> should never produce -Wsign-compare warnings. All the possible error
- // cases involve narrowing conversions and so are ill-formed.
- (void)(a <=> (unsigned long) b); // expected-warning {{comparison of integers of different signs}}
+ (void)((short)a <=> (unsigned short)b);
+
+ // (a,b)
+ (void)(a <=> (unsigned long)b); // expected-error {{argument to 'operator<=>' cannot be narrowed}}
(void)(a <=> (unsigned int) b);
(void)(a <=> (unsigned short) b);
(void)(a <=> (unsigned char) b);
- (void)((long) a <=> b); // expected-warning {{comparison of integers of different signs}}
- (void)((int) a <=> b); // expected-warning {{comparison of integers of different signs}}
- (void)((short) a <=> b); // expected-warning {{comparison of integers of different signs}}
- (void)((signed char) a <=> b); // expected-warning {{comparison of integers of different signs}}
- (void)((long) a <=> (unsigned long) b); // expected-warning {{comparison of integers of different signs}}
- (void)((int) a <=> (unsigned int) b); // expected-warning {{comparison of integers of different signs}}
+ (void)((long)a <=> b); // expected-error {{argument to 'operator<=>' cannot be narrowed}}
+ (void)((int)a <=> b); // expected-error {{argument to 'operator<=>' cannot be narrowed}}
+ (void)((short)a <=> b); // expected-error {{argument to 'operator<=>' cannot be narrowed}}
+ (void)((signed char)a <=> b); // expected-error {{argument to 'operator<=>' cannot be narrowed}}
+ (void)((long)a <=> (unsigned long)b); // expected-error {{argument to 'operator<=>' cannot be narrowed}}
+ (void)((int)a <=> (unsigned int)b); // expected-error {{argument to 'operator<=>' cannot be narrowed}}
(void)((short) a <=> (unsigned short) b);
(void)((signed char) a <=> (unsigned char) b);
-#if 0
// (A,b)
(void)(A <=> (unsigned long) b);
(void)(A <=> (unsigned int) b);
@@ -40,7 +52,7 @@ void test0(long a, unsigned long b) {
(void)((signed char) A <=> (unsigned char) b);
// (a,B)
- (void)(a <=> (unsigned long) B);
+ (void)(a <=> (unsigned long) B); // expected-error {{argument to 'operator<=>' cannot be narrowed from type 'long' to 'unsigned long'}}
(void)(a <=> (unsigned int) B);
(void)(a <=> (unsigned short) B);
(void)(a <=> (unsigned char) B);
@@ -48,8 +60,8 @@ void test0(long a, unsigned long b) {
(void)((int) a <=> B);
(void)((short) a <=> B);
(void)((signed char) a <=> B);
- (void)((long) a <=> (unsigned long) B);
- (void)((int) a <=> (unsigned int) B);
+ (void)((long) a <=> (unsigned long) B); // expected-error {{argument to 'operator<=>' cannot be narrowed from type 'long' to 'unsigned long'}}
+ (void)((int) a <=> (unsigned int) B); // expected-error {{argument to 'operator<=>' cannot be narrowed from type 'int' to 'unsigned int'}}
(void)((short) a <=> (unsigned short) B);
(void)((signed char) a <=> (unsigned char) B);
@@ -68,7 +80,7 @@ void test0(long a, unsigned long b) {
(void)((signed char) C <=> (unsigned char) b);
// (a,C)
- (void)(a <=> (unsigned long) C);
+ (void)(a <=> (unsigned long) C); // expected-error {{argument to 'operator<=>' cannot be narrowed from type 'long' to 'unsigned long'}}
(void)(a <=> (unsigned int) C);
(void)(a <=> (unsigned short) C);
(void)(a <=> (unsigned char) C);
@@ -76,11 +88,10 @@ void test0(long a, unsigned long b) {
(void)((int) a <=> C);
(void)((short) a <=> C); // expected-warning {{comparison of constant 'C' (65536) with expression of type 'short' is always 'std::strong_ordering::less'}}
(void)((signed char) a <=> C); // expected-warning {{comparison of constant 'C' (65536) with expression of type 'signed char' is always 'std::strong_ordering::less'}}
- (void)((long) a <=> (unsigned long) C);
- (void)((int) a <=> (unsigned int) C);
+ (void)((long) a <=> (unsigned long) C); // expected-error {{argument to 'operator<=>' cannot be narrowed from type 'long' to 'unsigned long'}}
+ (void)((int) a <=> (unsigned int) C); // expected-error {{argument to 'operator<=>' cannot be narrowed from type 'int' to 'unsigned int'}}
(void)((short) a <=> (unsigned short) C);
(void)((signed char) a <=> (unsigned char) C);
-#endif
// (0x80000,b)
(void)(0x80000 <=> (unsigned long) b);
@@ -97,7 +108,7 @@ void test0(long a, unsigned long b) {
(void)((signed char) 0x80000 <=> (unsigned char) b);
// (a,0x80000)
- (void)(a <=> (unsigned long) 0x80000); // expected-warning {{comparison of integers of different signs}}
+ (void)(a <=> (unsigned long)0x80000); // expected-error {{argument to 'operator<=>' cannot be narrowed}}
(void)(a <=> (unsigned int) 0x80000);
(void)(a <=> (unsigned short) 0x80000);
(void)(a <=> (unsigned char) 0x80000);
@@ -105,19 +116,23 @@ void test0(long a, unsigned long b) {
(void)((int) a <=> 0x80000);
(void)((short) a <=> 0x80000); // expected-warning {{comparison of constant 524288 with expression of type 'short' is always 'std::strong_ordering::less'}}
(void)((signed char) a <=> 0x80000); // expected-warning {{comparison of constant 524288 with expression of type 'signed char' is always 'std::strong_ordering::less'}}
- (void)((long) a <=> (unsigned long) 0x80000); // expected-warning {{comparison of integers of different signs}}
- (void)((int) a <=> (unsigned int) 0x80000); // expected-warning {{comparison of integers of different signs}}
+ (void)((long)a <=> (unsigned long)0x80000); // expected-error {{argument to 'operator<=>' cannot be narrowed}}
+ (void)((int)a <=> (unsigned int)0x80000); // expected-error {{argument to 'operator<=>' cannot be narrowed}}
(void)((short) a <=> (unsigned short) 0x80000);
(void)((signed char) a <=> (unsigned char) 0x80000);
}
-void test5(bool b) {
- (void) (b <=> -10); // expected-warning{{comparison of constant -10 with expression of type 'bool' is always 'std::strong_ordering::greater'}}
- (void) (b <=> -1); // expected-warning{{comparison of constant -1 with expression of type 'bool' is always 'std::strong_ordering::greater'}}
- (void) (b <=> 0);
- (void) (b <=> 1);
- (void) (b <=> 2); // expected-warning{{comparison of constant 2 with expression of type 'bool' is always 'std::strong_ordering::less'}}
- (void) (b <=> 10); // expected-warning{{comparison of constant 10 with expression of type 'bool' is always 'std::strong_ordering::less'}}
+void test5(bool b, bool b2) {
+ enum EnumA { A };
+ (void)(b <=> b2); // OK
+ (void)(true <=> b); // OK
+ (void)(b <=> -10); // expected-error {{invalid operands to binary expression ('bool' and 'int')}}
+ (void)(b <=> char(1)); // expected-error {{invalid operands to binary expression ('bool' and 'char')}}
+ (void)(b <=> A); // expected-error {{invalid operands to binary expression ('bool' and 'EnumA')}}
+
+ // FIXME: Should this be accepted when narrowing doesn't occur?
+ (void)(b <=> 0); // expected-error {{invalid operands to binary expression ('bool' and 'int')}}
+ (void)(b <=> 1); // expected-error {{invalid operands to binary expression ('bool' and 'int')}}
}
void test6(signed char sc) {
@@ -134,13 +149,13 @@ void test7(unsigned long other) {
(void)((unsigned long)other <=> (unsigned)(0xffff'ffff));
// Common unsigned, other signed, constant unsigned
- (void)((int)other <=> (unsigned long)(0xffff'ffff'ffff'ffff)); // expected-warning{{different signs}}
- (void)((int)other <=> (unsigned long)(0x0000'0000'ffff'ffff)); // expected-warning{{different signs}}
- (void)((int)other <=> (unsigned long)(0x0000'0000'0fff'ffff)); // expected-warning{{different signs}}
- (void)((int)other <=> (unsigned)(0x8000'0000)); // expected-warning{{different signs}}
+ (void)((int)other <=> (unsigned long)(0xffff'ffff'ffff'ffff)); // expected-error {{argument to 'operator<=>' cannot be narrowed}}
+ (void)((int)other <=> (unsigned long)(0x0000'0000'ffff'ffff)); // expected-error {{argument to 'operator<=>' cannot be narrowed}}
+ (void)((int)other <=> (unsigned long)(0x0000'0000'0fff'ffff)); // expected-error {{argument to 'operator<=>' cannot be narrowed}}
+ (void)((int)other <=> (unsigned)(0x8000'0000)); // expected-error {{argument to 'operator<=>' cannot be narrowed}}
// Common unsigned, other unsigned, constant signed
- (void)((unsigned long)other <=> (int)(0xffff'ffff)); // expected-warning{{different signs}}
+ (void)((unsigned long)other <=> (int)(0xffff'ffff)); // expected-error {{argument to 'operator<=>' evaluates to -1, which cannot be narrowed to type 'unsigned long'}}
// Common unsigned, other signed, constant signed
// Should not be possible as the common type should also be signed.
@@ -164,3 +179,245 @@ void test7(unsigned long other) {
(void)((unsigned char)other <=> (unsigned short)(0x100)); // expected-warning{{less}}
(void)((unsigned short)other <=> (unsigned char)(0xff));
}
+
+void test8(void *vp, const void *cvp, int *ip) {
+ (void)(vp <=> cvp); // OK, void* comparisons are allowed.
+ (void)(vp <=> ip);
+ (void)(ip <=> cvp);
+}
+
+void test9(long double ld, double d, float f, int i, long long ll) {
+ (void)(f <=> ll); // OK, floating-point to integer is OK
+ (void)(d <=> ld);
+ (void)(i <=> f);
+}
+
+typedef int *INTPTR;
+void test_typedef_bug(int *x, INTPTR y) {
+ (void)(x <=> y);
+}
+
+using nullptr_t = decltype(nullptr);
+
+struct Class {};
+struct ClassB : Class {};
+struct Class2 {};
+using FnTy = void(int);
+using FnTy2 = long(int);
+using MemFnTy = void (Class::*)() const;
+using MemFnTyB = void (ClassB::*)() const;
+using MemFnTy2 = void (Class::*)();
+using MemFnTy3 = void (Class2::*)() const;
+using MemDataTy = long(Class::*);
+
+void test_nullptr(int *x, FnTy *fp, MemFnTy memp, MemDataTy memdp) {
+ auto r1 = (nullptr <=> nullptr);
+ ASSERT_EXPR_TYPE(r1, std::strong_equality);
+
+ auto r2 = (nullptr <=> x);
+ ASSERT_EXPR_TYPE(r2, std::strong_equality);
+
+ auto r3 = (fp <=> nullptr);
+ ASSERT_EXPR_TYPE(r3, std::strong_equality);
+
+ auto r4 = (0 <=> fp);
+ ASSERT_EXPR_TYPE(r4, std::strong_equality);
+
+ auto r5 = (nullptr <=> memp);
+ ASSERT_EXPR_TYPE(r5, std::strong_equality);
+
+ auto r6 = (0 <=> memdp);
+ ASSERT_EXPR_TYPE(r6, std::strong_equality);
+
+ auto r7 = (0 <=> nullptr);
+ ASSERT_EXPR_TYPE(r7, std::strong_equality);
+}
+
+void test_compatible_pointer(FnTy *f1, FnTy2 *f2, MemFnTy mf1, MemFnTyB mfb,
+ MemFnTy2 mf2, MemFnTy3 mf3) {
+ (void)(f1 <=> f2); // expected-error {{distinct pointer types}}
+
+ auto r1 = (mf1 <=> mfb); // OK
+ ASSERT_EXPR_TYPE(r1, std::strong_equality);
+ ASSERT_EXPR_TYPE((mf1 <=> mfb), std::strong_equality);
+
+ (void)(mf1 <=> mf2); // expected-error {{distinct pointer types}}
+ (void)(mf3 <=> mf1); // expected-error {{distinct pointer types}}
+}
+
+// Test that variable narrowing is deferred for value dependent expressions
+template <int Val>
+auto test_template_overflow() {
+ // expected-error@+1 {{argument to 'operator<=>' evaluates to -1, which cannot be narrowed to type 'unsigned long'}}
+ return (Val <=> (unsigned long)0);
+}
+template auto test_template_overflow<0>();
+template auto test_template_overflow<-1>(); // expected-note {{requested here}}
+
+void test_enum_integral_compare() {
+ enum EnumA : int {A, ANeg = -1, AMax = __INT_MAX__};
+ enum EnumB : unsigned {B, BMax = __UINT32_MAX__ };
+ enum EnumC : int {C = -1, C0 = 0};
+
+ (void)(A <=> C); // expected-error {{invalid operands to binary expression ('EnumA' and 'EnumC')}}
+
+ (void)(A <=> (unsigned)0);
+ (void)((unsigned)0 <=> A);
+ (void)(ANeg <=> (unsigned)0); // expected-error {{argument to 'operator<=>' evaluates to -1, which cannot be narrowed to type 'unsigned int'}}
+ (void)((unsigned)0 <=> ANeg); // expected-error {{cannot be narrowed}}
+
+ (void)(B <=> 42);
+ (void)(42 <=> B);
+ (void)(B <=> (unsigned long long)42);
+ (void)(B <=> -1); // expected-error {{argument to 'operator<=>' evaluates to -1, which cannot be narrowed to type 'unsigned int'}}
+ (void)(BMax <=> (unsigned long)-1);
+
+ (void)(C0 <=> (unsigned)42);
+ (void)(C <=> (unsigned)42); // expected-error {{argument to 'operator<=>' evaluates to -1, which cannot be narrowed to type 'unsigned int'}}
+}
+
+namespace EnumCompareTests {
+
+enum class EnumA { A, A2 };
+enum class EnumB { B };
+enum class EnumC : unsigned { C };
+
+void test_enum_enum_compare_no_builtin() {
+ auto r1 = (EnumA::A <=> EnumA::A2); // OK
+ ASSERT_EXPR_TYPE(r1, std::strong_ordering);
+ (void)(EnumA::A <=> EnumA::A); // expected-warning {{self-comparison always evaluates to 'std::strong_ordering::equal'}}
+ (void)(EnumA::A <=> EnumB::B); // expected-error {{invalid operands to binary expression ('EnumCompareTests::EnumA' and 'EnumCompareTests::EnumB')}}
+ (void)(EnumB::B <=> EnumA::A); // expected-error {{invalid operands}}
+}
+
+template <int>
+struct Tag {};
+// expected-note@+1 {{candidate}}
+Tag<0> operator<=>(EnumA, EnumA) {
+ return {};
+}
+Tag<1> operator<=>(EnumA, EnumB) {
+ return {};
+}
+
+void test_enum_ovl_provided() {
+ auto r1 = (EnumA::A <=> EnumA::A);
+ ASSERT_EXPR_TYPE(r1, Tag<0>);
+ auto r2 = (EnumA::A <=> EnumB::B);
+ ASSERT_EXPR_TYPE(r2, Tag<1>);
+ (void)(EnumB::B <=> EnumA::A); // expected-error {{invalid operands to binary expression ('EnumCompareTests::EnumB' and 'EnumCompareTests::EnumA')}}
+}
+
+void enum_float_test() {
+ enum EnumA { A };
+ (void)(A <=> (float)0); // expected-error {{invalid operands to binary expression ('EnumA' and 'float')}}
+ (void)((double)0 <=> A); // expected-error {{invalid operands to binary expression ('double' and 'EnumA')}}
+ (void)((long double)0 <=> A); // expected-error {{invalid operands to binary expression ('long double' and 'EnumA')}}
+}
+
+enum class Bool1 : bool { Zero,
+ One };
+enum Bool2 : bool { B2_Zero,
+ B2_One };
+
+void test_bool_enum(Bool1 A1, Bool1 A2, Bool2 B1, Bool2 B2) {
+ (void)(A1 <=> A2);
+ (void)(B1 <=> B2);
+}
+
+} // namespace EnumCompareTests
+
+namespace TestUserDefinedConvSeq {
+
+template <class T, T Val>
+struct Conv {
+ constexpr operator T() const { return Val; }
+ operator T() { return Val; }
+};
+
+void test_user_conv() {
+ {
+ using C = Conv<int, 0>;
+ C c;
+ const C cc;
+ (void)(0 <=> c);
+ (void)(c <=> -1);
+ (void)((unsigned)0 <=> cc);
+ (void)((unsigned)0 <=> c); // expected-error {{argument to 'operator<=>' cannot be narrowed from type 'int' to 'unsigned int'}}
+ }
+ {
+ using C = Conv<int, -1>;
+ C c;
+ const C cc;
+ (void)(c <=> 0);
+ (void)(cc <=> (unsigned)0); // expected-error {{argument to 'operator<=>' evaluates to -1, which cannot be narrowed to type 'unsigned int'}}
+ (void)(c <=> (unsigned)0); // expected-error {{cannot be narrowed from type 'int' to 'unsigned int'}}
+ }
+}
+
+} // namespace TestUserDefinedConvSeq
+
+void test_array_conv() {
+ int arr[5];
+ int *ap = arr + 2;
+ int arr2[3];
+ (void)(arr <=> arr); // expected-error {{invalid operands to binary expression ('int [5]' and 'int [5]')}}
+ (void)(+arr <=> arr);
+}
+
+void test_mixed_float_int(float f, double d, long double ld) {
+ extern int i;
+ extern unsigned u;
+ extern long l;
+ extern short s;
+ extern unsigned short us;
+ auto r1 = (f <=> i);
+ ASSERT_EXPR_TYPE(r1, std::partial_ordering);
+
+ auto r2 = (us <=> ld);
+ ASSERT_EXPR_TYPE(r2, std::partial_ordering);
+
+ auto r3 = (s <=> f);
+ ASSERT_EXPR_TYPE(r3, std::partial_ordering);
+
+ auto r4 = (0.0 <=> i);
+ ASSERT_EXPR_TYPE(r4, std::partial_ordering);
+}
+
+namespace NullptrTest {
+using nullptr_t = decltype(nullptr);
+void foo(nullptr_t x, nullptr_t y) {
+ auto r = x <=> y;
+ ASSERT_EXPR_TYPE(r, std::strong_equality);
+}
+} // namespace NullptrTest
+
+namespace ComplexTest {
+
+enum class StrongE {};
+enum WeakE { E_One,
+ E_Two };
+
+void test_diag(_Complex int ci, _Complex float cf, _Complex double cd, int i, float f, StrongE E1, WeakE E2, int *p) {
+ (void)(ci <=> (_Complex int &)ci);
+ (void)(ci <=> cf);
+ (void)(ci <=> i);
+ (void)(ci <=> f);
+ (void)(cf <=> i);
+ (void)(cf <=> f);
+ (void)(ci <=> p); // expected-error {{invalid operands}}
+ (void)(ci <=> E1); // expected-error {{invalid operands}}
+ (void)(E2 <=> cf); // expected-error {{invalid operands}}
+}
+
+void test_int(_Complex int x, _Complex int y) {
+ auto r = x <=> y;
+ ASSERT_EXPR_TYPE(r, std::strong_equality);
+}
+
+void test_double(_Complex double x, _Complex double y) {
+ auto r = x <=> y;
+ ASSERT_EXPR_TYPE(r, std::weak_equality);
+}
+
+} // namespace ComplexTest
diff --git a/test/SemaCXX/compare.cpp b/test/SemaCXX/compare.cpp
index d852180c0663..ee0fe01fd1d1 100644
--- a/test/SemaCXX/compare.cpp
+++ b/test/SemaCXX/compare.cpp
@@ -1,7 +1,7 @@
// Force x86-64 because some of our heuristics are actually based
// on integer sizes.
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -pedantic -verify -Wsign-compare -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -pedantic -verify -Wsign-compare -Wtautological-constant-in-range-compare -std=c++11 %s
int test0(long a, unsigned long b) {
enum EnumA {A};
diff --git a/test/SemaCXX/complete-member-pointers.cpp b/test/SemaCXX/complete-member-pointers.cpp
new file mode 100644
index 000000000000..942bb703a922
--- /dev/null
+++ b/test/SemaCXX/complete-member-pointers.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -verify -fsyntax-only -fcomplete-member-pointers %s
+
+struct S; // expected-note {{forward declaration of 'S'}}
+typedef int S::*t;
+t foo; // expected-error {{member pointer has incomplete base type 'S'}}
+
+struct S2 {
+ int S2::*foo;
+};
+int S2::*bar;
+
+template <typename T>
+struct S3 {
+ int T::*foo;
+};
diff --git a/test/SemaCXX/conditional-expr.cpp b/test/SemaCXX/conditional-expr.cpp
index 5025990cfd36..8d0555ea5068 100644
--- a/test/SemaCXX/conditional-expr.cpp
+++ b/test/SemaCXX/conditional-expr.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 -Wsign-conversion %s
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++17 -Wsign-conversion %s
// C++ rules for ?: are a lot stricter than C rules, and have to take into
// account more conversion options.
@@ -149,7 +150,7 @@ void test()
i1 = i1 ? i1 : I();
I i2(i1 ? I() : J());
I i3(i1 ? J() : I());
- // "the type [it] woud have if E2 were converted to an rvalue"
+ // "the type [it] would have if E2 were converted to an rvalue"
vfn pfn = i1 ? F() : test;
pfn = i1 ? test : F();
(void)(i1 ? A() : B()); // expected-error {{conversion from 'B' to 'A' is ambiguous}}
@@ -228,7 +229,7 @@ void test()
// be properly tested at runtime, though.
const Abstract &abstract1 = true ? static_cast<const Abstract&>(Derived1()) : Derived2(); // expected-error {{allocating an object of abstract class type 'const Abstract'}}
- const Abstract &abstract2 = true ? static_cast<const Abstract&>(Derived1()) : throw 3; // ok
+ const Abstract &abstract2 = true ? static_cast<const Abstract&>(Derived1()) : throw 3;
}
namespace PR6595 {
@@ -393,3 +394,18 @@ Derived d;
typedef decltype(true ? static_cast<Base&&>(b) : static_cast<Derived&&>(d)) x;
typedef Base &&x;
}
+
+namespace lifetime_extension {
+ struct A {};
+ struct B : A { B(); ~B(); };
+ struct C : A { C(); ~C(); };
+
+ void f(bool b) {
+ A &&r = b ? static_cast<A&&>(B()) : static_cast<A&&>(C());
+ }
+
+ struct D { A &&a; };
+ void f_indirect(bool b) {
+ D d = b ? D{B()} : D{C()};
+ }
+}
diff --git a/test/SemaCXX/const-cast.cpp b/test/SemaCXX/const-cast.cpp
index 87df61cbc7b2..a9268660f1ea 100644
--- a/test/SemaCXX/const-cast.cpp
+++ b/test/SemaCXX/const-cast.cpp
@@ -58,8 +58,14 @@ short *bad_const_cast_test(char const *volatile *const volatile *var)
// Non-pointer.
char v = const_cast<char>(**var2); // expected-error {{const_cast to 'char', which is not a reference, pointer-to-object, or pointer-to-data-member}}
const int *ar[100] = {0};
- // Not even lenient g++ accepts this.
- int *(*rar)[100] = const_cast<int *(*)[100]>(&ar); // expected-error {{const_cast from 'const int *(*)[100]' to 'int *(*)[100]' is not allowed}}
+ extern const int *aub[];
+ // const_cast looks through arrays as of DR330.
+ (void) const_cast<int *(*)[100]>(&ar); // ok
+ (void) const_cast<int *(*)[]>(&aub); // ok
+ // ... but the array bound must exactly match.
+ (void) const_cast<int *(*)[]>(&ar); // expected-error {{const_cast from 'const int *(*)[100]' to 'int *(*)[]' is not allowed}}
+ (void) const_cast<int *(*)[99]>(&ar); // expected-error {{const_cast from 'const int *(*)[100]' to 'int *(*)[99]' is not allowed}}
+ (void) const_cast<int *(*)[100]>(&aub); // expected-error {{const_cast from 'const int *(*)[]' to 'int *(*)[100]' is not allowed}}
f fp1 = 0;
// Function pointers.
f fp2 = const_cast<f>(fp1); // expected-error {{const_cast to 'f' (aka 'int (*)(int)'), which is not a reference, pointer-to-object, or pointer-to-data-member}}
diff --git a/test/SemaCXX/constant-conversion.cpp b/test/SemaCXX/constant-conversion.cpp
new file mode 100644
index 000000000000..80deabf79a46
--- /dev/null
+++ b/test/SemaCXX/constant-conversion.cpp
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-apple-darwin %s
+
+// This file tests -Wconstant-conversion, a subcategory of -Wconversion
+// which is on by default.
+
+constexpr int nines() { return 99999; }
+
+void too_big_for_char(int param) {
+ char warn1 = false ? 0 : 99999;
+ // expected-warning@-1 {{implicit conversion from 'int' to 'char' changes value from 99999 to -97}}
+ char warn2 = false ? 0 : nines();
+ // expected-warning@-1 {{implicit conversion from 'int' to 'char' changes value from 99999 to -97}}
+
+ char warn3 = param > 0 ? 0 : 99999;
+ // expected-warning@-1 {{implicit conversion from 'int' to 'char' changes value from 99999 to -97}}
+ char warn4 = param > 0 ? 0 : nines();
+ // expected-warning@-1 {{implicit conversion from 'int' to 'char' changes value from 99999 to -97}}
+
+ char ok1 = true ? 0 : 99999;
+ char ok2 = true ? 0 : nines();
+
+ char ok3 = true ? 0 : 99999 + 1;
+ char ok4 = true ? 0 : nines() + 1;
+}
diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp
index 51dd6199e63a..a64207583dd5 100644
--- a/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/test/SemaCXX/constant-expression-cxx11.cpp
@@ -528,7 +528,7 @@ constexpr int xs6 = p[3]; // expected-error {{constant expression}} expected-not
constexpr int xs0 = p[-3]; // ok
constexpr int xs_1 = p[-4]; // expected-error {{constant expression}} expected-note {{cannot refer to element -1}}
-constexpr int zs[2][2][2][2] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
+constexpr int zs[2][2][2][2] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; // expected-note {{array 'zs' declared here}}
static_assert(zs[0][0][0][0] == 1, "");
static_assert(zs[1][1][1][1] == 16, "");
static_assert(zs[0][0][0][2] == 3, ""); // expected-error {{constant expression}} expected-note {{read of dereferenced one-past-the-end pointer}}
@@ -536,7 +536,10 @@ static_assert((&zs[0][0][0][2])[-1] == 2, "");
static_assert(**(**(zs + 1) + 1) == 11, "");
static_assert(*(&(&(*(*&(&zs[2] - 1)[0] + 2 - 2))[2])[-1][-1] + 1) == 11, ""); // expected-error {{constant expression}} expected-note {{cannot refer to element -1 of array of 2 elements in a constant expression}}
static_assert(*(&(&(*(*&(&zs[2] - 1)[0] + 2 - 2))[2])[-1][2] - 2) == 11, "");
-constexpr int err_zs_1_2_0_0 = zs[1][2][0][0]; // expected-error {{constant expression}} expected-note {{cannot access array element of pointer past the end}}
+constexpr int err_zs_1_2_0_0 = zs[1][2][0][0]; // \
+expected-error {{constant expression}} \
+expected-note {{cannot access array element of pointer past the end}} \
+expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}}
constexpr int fail(const int &p) {
return (&p)[64]; // expected-note {{cannot refer to element 64 of array of 2 elements}}
@@ -629,6 +632,10 @@ namespace ArrayOfUnknownBound {
extern const int carr[]; // expected-note {{here}}
constexpr int n = carr[0]; // expected-error {{constant}} expected-note {{non-constexpr variable}}
+
+ constexpr int local_extern[] = {1, 2, 3};
+ void f() { extern const int local_extern[]; }
+ static_assert(local_extern[1] == 2, "");
}
namespace DependentValues {
@@ -1548,13 +1555,13 @@ namespace CompoundLiteral {
// Other kinds are not.
struct X { int a[2]; };
- constexpr int *n = (X){1, 2}.a; // expected-warning {{C99}} expected-warning {{temporary array}}
+ constexpr int *n = (X){1, 2}.a; // expected-warning {{C99}} expected-warning {{temporary}}
// expected-error@-1 {{constant expression}}
// expected-note@-2 {{pointer to subobject of temporary}}
// expected-note@-3 {{temporary created here}}
void f() {
- static constexpr int *p = (int*)(int[1]){3}; // expected-warning {{C99}}
+ static constexpr int *p = (int*)(int[1]){3}; // expected-warning {{C99}} expected-warning {{temporary}}
// expected-error@-1 {{constant expression}}
// expected-note@-2 {{pointer to subobject of temporary}}
// expected-note@-3 {{temporary created here}}
@@ -1885,14 +1892,15 @@ namespace Lifetime {
}
constexpr int &get(int &&n) { return n; }
+ constexpr int &&get_rv(int &&n) { return static_cast<int&&>(n); }
struct S {
- int &&r; // expected-note 2{{declared here}}
+ int &&r;
int &s;
int t;
- constexpr S() : r(0), s(get(0)), t(r) {} // expected-warning {{temporary}}
- constexpr S(int) : r(0), s(get(0)), t(s) {} // expected-warning {{temporary}} expected-note {{read of object outside its lifetime}}
+ constexpr S() : r(get_rv(0)), s(get(0)), t(r) {} // expected-note {{read of object outside its lifetime}}
+ constexpr S(int) : r(get_rv(0)), s(get(0)), t(s) {} // expected-note {{read of object outside its lifetime}}
};
- constexpr int k1 = S().t; // ok, int is lifetime-extended to end of constructor
+ constexpr int k1 = S().t; // expected-error {{constant expression}} expected-note {{in call}}
constexpr int k2 = S(0).t; // expected-error {{constant expression}} expected-note {{in call}}
}
diff --git a/test/SemaCXX/constant-expression-cxx1y.cpp b/test/SemaCXX/constant-expression-cxx1y.cpp
index 12fec0851691..00df2e5c77a4 100644
--- a/test/SemaCXX/constant-expression-cxx1y.cpp
+++ b/test/SemaCXX/constant-expression-cxx1y.cpp
@@ -852,7 +852,6 @@ namespace Lifetime {
static_assert(h(2) == 0, ""); // expected-error {{constant expression}} expected-note {{in call}}
static_assert(h(3) == 0, ""); // expected-error {{constant expression}} expected-note {{in call}}
- // FIXME: This function should be treated as non-constant.
constexpr void lifetime_versus_loops() {
int *p = 0;
for (int i = 0; i != 2; ++i) {
@@ -862,10 +861,10 @@ namespace Lifetime {
if (i)
// This modifies the 'n' from the previous iteration of the loop outside
// its lifetime.
- ++*q;
+ ++*q; // expected-note {{increment of object outside its lifetime}}
}
}
- static_assert((lifetime_versus_loops(), true), "");
+ static_assert((lifetime_versus_loops(), true), ""); // expected-error {{constant expression}} expected-note {{in call}}
}
namespace Bitfields {
@@ -1021,3 +1020,81 @@ constexpr bool evalNested() {
}
static_assert(evalNested(), "");
} // namespace PR19741
+
+namespace Mutable {
+ struct A { mutable int n; }; // expected-note 2{{here}}
+ constexpr int k = A{123}.n; // ok
+ static_assert(k == 123, "");
+
+ struct Q { A &&a; int b = a.n; };
+ constexpr Q q = { A{456} }; // expected-note {{temporary}}
+ static_assert(q.b == 456, "");
+ static_assert(q.a.n == 456, ""); // expected-error {{constant expression}} expected-note {{outside the expression that created the temporary}}
+
+ constexpr A a = {123};
+ constexpr int m = a.n; // expected-error {{constant expression}} expected-note {{mutable}}
+
+ constexpr Q r = { static_cast<A&&>(const_cast<A&>(a)) }; // expected-error {{constant expression}} expected-note@-8 {{mutable}}
+
+ struct B {
+ mutable int n; // expected-note {{here}}
+ int m;
+ constexpr B() : n(1), m(n) {} // ok
+ };
+ constexpr B b;
+ constexpr int p = b.n; // expected-error {{constant expression}} expected-note {{mutable}}
+}
+
+namespace IndirectFields {
+
+// Reference indirect field.
+struct A {
+ struct {
+ union {
+ int x = x = 3; // expected-note {{outside its lifetime}}
+ };
+ };
+ constexpr A() {}
+};
+static_assert(A().x == 3, ""); // expected-error{{not an integral constant expression}} expected-note{{in call to 'A()'}}
+
+// Reference another indirect field, with different 'this'.
+struct B {
+ struct {
+ union {
+ int x = 3;
+ };
+ int y = x;
+ };
+ constexpr B() {}
+};
+static_assert(B().y == 3, "");
+
+// Nested evaluation of indirect field initializers.
+struct C {
+ union {
+ int x = 1;
+ };
+};
+struct D {
+ struct {
+ C c;
+ int y = c.x + 1;
+ };
+};
+static_assert(D().y == 2, "");
+
+// Explicit 'this'.
+struct E {
+ int n = 0;
+ struct {
+ void *x = this;
+ };
+ void *y = this;
+};
+constexpr E e1 = E();
+static_assert(e1.x != e1.y, "");
+constexpr E e2 = E{0};
+static_assert(e2.x != e2.y, "");
+
+} // namespace IndirectFields
diff --git a/test/SemaCXX/constant-expression-cxx1z.cpp b/test/SemaCXX/constant-expression-cxx1z.cpp
index a48c9b11b886..2b366adf2e91 100644
--- a/test/SemaCXX/constant-expression-cxx1z.cpp
+++ b/test/SemaCXX/constant-expression-cxx1z.cpp
@@ -46,3 +46,16 @@ namespace Cxx17CD_NB_GB19 {
const int &r = 0;
constexpr int n = r;
}
+
+namespace PR37585 {
+template <class T> struct S { static constexpr bool value = true; };
+template <class T> constexpr bool f() { return true; }
+template <class T> constexpr bool v = true;
+
+void test() {
+ if constexpr (true) {}
+ else if constexpr (f<int>()) {}
+ else if constexpr (S<int>::value) {}
+ else if constexpr (v<int>) {}
+}
+}
diff --git a/test/SemaCXX/constant-expression-cxx2a.cpp b/test/SemaCXX/constant-expression-cxx2a.cpp
index 935cbefc7cb9..18c4a726fd00 100644
--- a/test/SemaCXX/constant-expression-cxx2a.cpp
+++ b/test/SemaCXX/constant-expression-cxx2a.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -std=c++2a -verify %s -fcxx-exceptions -triple=x86_64-linux-gnu
+#include "Inputs/std-compare.h"
+
namespace ThreeWayComparison {
struct A {
int n;
@@ -11,17 +13,194 @@ namespace ThreeWayComparison {
static_assert(A{2} <=> A{1} > 0);
static_assert(A{2} <=> A{2} == 0);
- // Note: not yet supported.
- static_assert(1 <=> 2 < 0); // expected-error {{invalid operands}}
- static_assert(2 <=> 1 > 0); // expected-error {{invalid operands}}
- static_assert(1 <=> 1 == 0); // expected-error {{invalid operands}}
+ static_assert(1 <=> 2 < 0);
+ static_assert(2 <=> 1 > 0);
+ static_assert(1 <=> 1 == 0);
constexpr int k = (1 <=> 1, 0);
- // expected-error@-1 {{constexpr variable 'k' must be initialized by a constant expression}}
- // expected-warning@-2 {{three-way comparison result unused}}
+ // expected-warning@-1 {{three-way comparison result unused}}
+
+ static_assert(std::strong_ordering::equal == 0);
+
+ constexpr void f() {
+ void(1 <=> 1);
+ }
+
+ struct MemPtr {
+ void foo() {}
+ void bar() {}
+ int data;
+ int data2;
+ long data3;
+ };
+
+ struct MemPtr2 {
+ void foo() {}
+ void bar() {}
+ int data;
+ int data2;
+ long data3;
+ };
+ using MemPtrT = void (MemPtr::*)();
+
+ using FnPtrT = void (*)();
+
+ void FnPtr1() {}
+ void FnPtr2() {}
+
+#define CHECK(...) ((__VA_ARGS__) ? void() : throw "error")
+#define CHECK_TYPE(...) static_assert(__is_same(__VA_ARGS__));
+
+constexpr bool test_constexpr_success = [] {
+ {
+ auto &EQ = std::strong_ordering::equal;
+ auto &LESS = std::strong_ordering::less;
+ auto &GREATER = std::strong_ordering::greater;
+ using SO = std::strong_ordering;
+ auto eq = (42 <=> 42);
+ CHECK_TYPE(decltype(eq), SO);
+ CHECK(eq.test_eq(EQ));
+
+ auto less = (-1 <=> 0);
+ CHECK_TYPE(decltype(less), SO);
+ CHECK(less.test_eq(LESS));
+
+ auto greater = (42l <=> 1u);
+ CHECK_TYPE(decltype(greater), SO);
+ CHECK(greater.test_eq(GREATER));
+ }
+ {
+ using PO = std::partial_ordering;
+ auto EQUIV = PO::equivalent;
+ auto LESS = PO::less;
+ auto GREATER = PO::greater;
+
+ auto eq = (42.0 <=> 42.0);
+ CHECK_TYPE(decltype(eq), PO);
+ CHECK(eq.test_eq(EQUIV));
+
+ auto less = (39.0 <=> 42.0);
+ CHECK_TYPE(decltype(less), PO);
+ CHECK(less.test_eq(LESS));
+
+ auto greater = (-10.123 <=> -101.1);
+ CHECK_TYPE(decltype(greater), PO);
+ CHECK(greater.test_eq(GREATER));
+ }
+ {
+ using SE = std::strong_equality;
+ auto EQ = SE::equal;
+ auto NEQ = SE::nonequal;
- constexpr void f() { // expected-error {{constant expression}}
- void(1 <=> 1); // expected-note {{constant expression}}
+ MemPtrT P1 = &MemPtr::foo;
+ MemPtrT P12 = &MemPtr::foo;
+ MemPtrT P2 = &MemPtr::bar;
+ MemPtrT P3 = nullptr;
+
+ auto eq = (P1 <=> P12);
+ CHECK_TYPE(decltype(eq), SE);
+ CHECK(eq.test_eq(EQ));
+
+ auto neq = (P1 <=> P2);
+ CHECK_TYPE(decltype(eq), SE);
+ CHECK(neq.test_eq(NEQ));
+
+ auto eq2 = (P3 <=> nullptr);
+ CHECK_TYPE(decltype(eq2), SE);
+ CHECK(eq2.test_eq(EQ));
+ }
+ {
+ using SE = std::strong_equality;
+ auto EQ = SE::equal;
+ auto NEQ = SE::nonequal;
+
+ FnPtrT F1 = &FnPtr1;
+ FnPtrT F12 = &FnPtr1;
+ FnPtrT F2 = &FnPtr2;
+ FnPtrT F3 = nullptr;
+
+ auto eq = (F1 <=> F12);
+ CHECK_TYPE(decltype(eq), SE);
+ CHECK(eq.test_eq(EQ));
+
+ auto neq = (F1 <=> F2);
+ CHECK_TYPE(decltype(neq), SE);
+ CHECK(neq.test_eq(NEQ));
+ }
+ { // mixed nullptr tests
+ using SO = std::strong_ordering;
+ using SE = std::strong_equality;
+
+ int x = 42;
+ int *xp = &x;
+
+ MemPtrT mf = nullptr;
+ MemPtrT mf2 = &MemPtr::foo;
+ auto r3 = (mf <=> nullptr);
+ CHECK_TYPE(decltype(r3), std::strong_equality);
+ CHECK(r3.test_eq(SE::equal));
}
- // TODO: defaulted operator <=>
+ return true;
+}();
+
+template <auto LHS, auto RHS, bool ExpectTrue = false>
+constexpr bool test_constexpr() {
+ using nullptr_t = decltype(nullptr);
+ using LHSTy = decltype(LHS);
+ using RHSTy = decltype(RHS);
+ // expected-note@+1 {{subexpression not valid in a constant expression}}
+ auto Res = (LHS <=> RHS);
+ if constexpr (__is_same(LHSTy, nullptr_t) || __is_same(RHSTy, nullptr_t)) {
+ CHECK_TYPE(decltype(Res), std::strong_equality);
+ }
+ if (ExpectTrue)
+ return Res == 0;
+ return Res != 0;
+}
+int dummy = 42;
+int dummy2 = 101;
+
+constexpr bool tc1 = test_constexpr<nullptr, &dummy>();
+constexpr bool tc2 = test_constexpr<&dummy, nullptr>();
+
+// OK, equality comparison only
+constexpr bool tc3 = test_constexpr<&MemPtr::foo, nullptr>();
+constexpr bool tc4 = test_constexpr<nullptr, &MemPtr::foo>();
+constexpr bool tc5 = test_constexpr<&MemPtr::foo, &MemPtr::bar>();
+
+constexpr bool tc6 = test_constexpr<&MemPtr::data, nullptr>();
+constexpr bool tc7 = test_constexpr<nullptr, &MemPtr::data>();
+constexpr bool tc8 = test_constexpr<&MemPtr::data, &MemPtr::data2>();
+
+// expected-error@+1 {{must be initialized by a constant expression}}
+constexpr bool tc9 = test_constexpr<&dummy, &dummy2>(); // expected-note {{in call}}
+
+template <class T, class R, class I>
+constexpr T makeComplex(R r, I i) {
+ T res{r, i};
+ return res;
+};
+
+template <class T, class ResultT>
+constexpr bool complex_test(T x, T y, ResultT Expect) {
+ auto res = x <=> y;
+ CHECK_TYPE(decltype(res), ResultT);
+ return res.test_eq(Expect);
}
+static_assert(complex_test(makeComplex<_Complex double>(0.0, 0.0),
+ makeComplex<_Complex double>(0.0, 0.0),
+ std::weak_equality::equivalent));
+static_assert(complex_test(makeComplex<_Complex double>(0.0, 0.0),
+ makeComplex<_Complex double>(1.0, 0.0),
+ std::weak_equality::nonequivalent));
+static_assert(complex_test(makeComplex<_Complex double>(0.0, 0.0),
+ makeComplex<_Complex double>(0.0, 1.0),
+ std::weak_equality::nonequivalent));
+static_assert(complex_test(makeComplex<_Complex int>(0, 0),
+ makeComplex<_Complex int>(0, 0),
+ std::strong_equality::equal));
+static_assert(complex_test(makeComplex<_Complex int>(0, 0),
+ makeComplex<_Complex int>(1, 0),
+ std::strong_equality::nonequal));
+// TODO: defaulted operator <=>
+} // namespace ThreeWayComparison
diff --git a/test/SemaCXX/constexpr-default-arg.cpp b/test/SemaCXX/constexpr-default-arg.cpp
new file mode 100644
index 000000000000..0cef4aa578af
--- /dev/null
+++ b/test/SemaCXX/constexpr-default-arg.cpp
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -std=c++1y -S -o - -emit-llvm -verify %s
+
+namespace default_arg_temporary {
+
+constexpr bool equals(const float& arg = 1.0f) {
+ return arg == 1.0f;
+}
+
+constexpr const int &x(const int &p = 0) {
+ return p;
+}
+
+struct S {
+ constexpr S(const int &a = 0) {}
+};
+
+void test_default_arg2() {
+ // This piece of code used to cause an assertion failure in
+ // CallStackFrame::createTemporary because the same MTE is used to initilize
+ // both elements of the array (see PR33140).
+ constexpr S s[2] = {};
+
+ // This piece of code used to cause an assertion failure in
+ // CallStackFrame::createTemporary because multiple CXXDefaultArgExpr share
+ // the same MTE (see PR33140).
+ static_assert(equals() && equals(), "");
+
+ // Test that constant expression evaluation produces distinct lvalues for
+ // each call.
+ static_assert(&x() != &x(), "");
+}
+
+// Check that multiple CXXDefaultInitExprs don't cause an assertion failure.
+struct A { int &&r = 0; }; // expected-note 2{{default member initializer}}
+struct B { A x, y; };
+B b = {}; // expected-warning 2{{not supported}}
+
+}
diff --git a/test/SemaCXX/constexpr-string.cpp b/test/SemaCXX/constexpr-string.cpp
index fba05e508ab7..2ed35fcc2bdd 100644
--- a/test/SemaCXX/constexpr-string.cpp
+++ b/test/SemaCXX/constexpr-string.cpp
@@ -53,6 +53,8 @@ namespace StrcmpEtc {
static_assert(__builtin_strcmp("abab", "abaa") == 1);
static_assert(__builtin_strcmp("ababa", "abab") == 1);
static_assert(__builtin_strcmp("abab", "ababa") == -1);
+ static_assert(__builtin_strcmp("a\203", "a") == 1);
+ static_assert(__builtin_strcmp("a\203", "a\003") == 1);
static_assert(__builtin_strcmp("abab\0banana", "abab") == 0);
static_assert(__builtin_strcmp("abab", "abab\0banana") == 0);
static_assert(__builtin_strcmp("abab\0banana", "abab\0canada") == 0);
@@ -78,6 +80,8 @@ namespace StrcmpEtc {
static_assert(__builtin_memcmp("abaa", "abba", 3) == -1);
static_assert(__builtin_memcmp("abaa", "abba", 2) == 0);
+ static_assert(__builtin_memcmp("a\203", "a", 2) == 1);
+ static_assert(__builtin_memcmp("a\203", "a\003", 2) == 1);
static_assert(__builtin_memcmp(0, 0, 0) == 0);
static_assert(__builtin_memcmp("abab\0banana", "abab\0banana", 100) == 0); // expected-error {{not an integral constant}} expected-note {{dereferenced one-past-the-end}}
static_assert(__builtin_memcmp("abab\0banana", "abab\0canada", 100) == -1); // FIXME: Should we reject this?
@@ -102,6 +106,9 @@ namespace WcscmpEtc {
static_assert(__builtin_wcscmp(L"abab\0banana", L"abab") == 0);
static_assert(__builtin_wcscmp(L"abab", L"abab\0banana") == 0);
static_assert(__builtin_wcscmp(L"abab\0banana", L"abab\0canada") == 0);
+#if __WCHAR_WIDTH__ == 32
+ static_assert(__builtin_wcscmp(L"a\x83838383", L"a") == (wchar_t)-1U >> 31);
+#endif
static_assert(__builtin_wcscmp(0, L"abab") == 0); // expected-error {{not an integral constant}} expected-note {{dereferenced null}}
static_assert(__builtin_wcscmp(L"abab", 0) == 0); // expected-error {{not an integral constant}} expected-note {{dereferenced null}}
@@ -116,6 +123,10 @@ namespace WcscmpEtc {
static_assert(__builtin_wcsncmp(L"abaa", L"abba", 0) == 0);
static_assert(__builtin_wcsncmp(0, 0, 0) == 0);
static_assert(__builtin_wcsncmp(L"abab\0banana", L"abab\0canada", 100) == 0);
+#if __WCHAR_WIDTH__ == 32
+ static_assert(__builtin_wcsncmp(L"a\x83838383", L"aa", 2) ==
+ (wchar_t)-1U >> 31);
+#endif
static_assert(__builtin_wcsncmp(kFoobar, kFoobazfoobar, 6) == -1);
static_assert(__builtin_wcsncmp(kFoobar, kFoobazfoobar, 7) == -1); // FIXME: Should we reject this?
@@ -125,6 +136,10 @@ namespace WcscmpEtc {
static_assert(__builtin_wmemcmp(L"abaa", L"abba", 3) == -1);
static_assert(__builtin_wmemcmp(L"abaa", L"abba", 2) == 0);
static_assert(__builtin_wmemcmp(0, 0, 0) == 0);
+#if __WCHAR_WIDTH__ == 32
+ static_assert(__builtin_wmemcmp(L"a\x83838383", L"aa", 2) ==
+ (wchar_t)-1U >> 31);
+#endif
static_assert(__builtin_wmemcmp(L"abab\0banana", L"abab\0banana", 100) == 0); // expected-error {{not an integral constant}} expected-note {{dereferenced one-past-the-end}}
static_assert(__builtin_wmemcmp(L"abab\0banana", L"abab\0canada", 100) == -1); // FIXME: Should we reject this?
static_assert(__builtin_wmemcmp(L"abab\0banana", L"abab\0canada", 7) == -1);
diff --git a/test/SemaCXX/conversion-function.cpp b/test/SemaCXX/conversion-function.cpp
index 531de818b680..1d3593d8ed1b 100644
--- a/test/SemaCXX/conversion-function.cpp
+++ b/test/SemaCXX/conversion-function.cpp
@@ -444,3 +444,13 @@ namespace PR18234 {
bool k1 = e == A::e; // expected-error {{no member named 'e'}}
bool k2 = e.n == 0;
}
+
+namespace PR30595 {
+struct S {
+ const operator int(); // expected-error {{cannot specify any part of a return type in the declaration of a conversion function; put the complete type after 'operator'}}
+ const operator int() const; // expected-error {{cannot specify any part of a return type}}
+ volatile const operator int(); // expected-error {{cannot specify any part of a return type}}
+
+ operator const int() const;
+};
+}
diff --git a/test/SemaCXX/copy-initialization.cpp b/test/SemaCXX/copy-initialization.cpp
index 4f6c65cf550c..cd7e5f07e140 100644
--- a/test/SemaCXX/copy-initialization.cpp
+++ b/test/SemaCXX/copy-initialization.cpp
@@ -26,7 +26,7 @@ struct foo {
};
// PR3600
-void test(const foo *P) { P->bar(); } // expected-error{{'bar' not viable: 'this' argument has type 'const foo', but function is not marked const}}
+void test(const foo *P) { P->bar(); } // expected-error{{'this' argument to member function 'bar' has type 'const foo', but function is not marked const}}
namespace PR6757 {
struct Foo {
diff --git a/test/SemaCXX/coroutine-source-location-crash.cpp b/test/SemaCXX/coroutine-source-location-crash.cpp
new file mode 100644
index 000000000000..04fb1d45c524
--- /dev/null
+++ b/test/SemaCXX/coroutine-source-location-crash.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++14 -fcoroutines-ts \
+// RUN: -fsyntax-only -ast-dump | FileCheck %s
+#include "Inputs/std-coroutine.h"
+
+using namespace std::experimental;
+
+struct A {
+ bool await_ready();
+ void await_resume();
+ template <typename F>
+ void await_suspend(F);
+};
+
+struct coro_t {
+ struct promise_type {
+ coro_t get_return_object();
+ suspend_never initial_suspend();
+ suspend_never final_suspend();
+ void return_void();
+ static void unhandled_exception();
+ };
+};
+
+// {{0x[0-9a-fA-F]+}} <line:[[@LINE+1]]:1, col:36>
+// CHECK-LABEL: FunctionDecl {{.*}} f 'coro_t (int)'
+coro_t f(int n) {
+ A a{};
+ // CHECK: CoawaitExpr {{0x[0-9a-fA-F]+}} <col:3, col:12>
+ // CHECK-NEXT: DeclRefExpr {{0x[0-9a-fA-F]+}} <col:12>
+ // CHECK-NEXT: CXXMemberCallExpr {{0x[0-9a-fA-F]+}} <col:12>
+ // CHECK-NEXT: MemberExpr {{0x[0-9a-fA-F]+}} <col:12>
+ co_await a;
+}
diff --git a/test/SemaCXX/coroutine-traits-undefined-template.cpp b/test/SemaCXX/coroutine-traits-undefined-template.cpp
new file mode 100644
index 000000000000..4687ed245ac8
--- /dev/null
+++ b/test/SemaCXX/coroutine-traits-undefined-template.cpp
@@ -0,0 +1,19 @@
+// This file contains references to sections of the Coroutines TS, which can be
+// found at http://wg21.link/coroutines.
+
+// RUN: %clang_cc1 -std=c++14 -fcoroutines-ts -verify %s -fcxx-exceptions -fexceptions -Wunused-result
+
+namespace std {
+namespace experimental {
+
+template<typename ...T>
+struct coroutine_traits {
+ struct promise_type {};
+};
+
+template<> struct coroutine_traits<void>; // expected-note {{forward declaration of 'std::experimental::coroutine_traits<void>'}}
+}} // namespace std::experimental
+
+void uses_forward_declaration() {
+ co_return; // expected-error {{this function cannot be a coroutine: missing definition of specialization 'coroutine_traits<void>'}}
+}
diff --git a/test/SemaCXX/coroutines.cpp b/test/SemaCXX/coroutines.cpp
index 65e17abb11fe..d58cedf414f8 100644
--- a/test/SemaCXX/coroutines.cpp
+++ b/test/SemaCXX/coroutines.cpp
@@ -1,4 +1,7 @@
-// RUN: %clang_cc1 -std=c++14 -fcoroutines-ts -verify %s -fcxx-exceptions -fexceptions
+// This file contains references to sections of the Coroutines TS, which can be
+// found at http://wg21.link/coroutines.
+
+// RUN: %clang_cc1 -std=c++14 -fcoroutines-ts -verify %s -fcxx-exceptions -fexceptions -Wunused-result
void no_coroutine_traits_bad_arg_await() {
co_await a; // expected-error {{include <experimental/coroutine>}}
@@ -157,7 +160,7 @@ struct coroutine_handle<void> {
void yield() {
co_yield 0;
co_yield {"foo", 1, 2};
- co_yield {1e100}; // expected-error {{cannot be narrowed}} expected-note {{explicit cast}} expected-warning {{changes value}} expected-warning {{braces around scalar}}
+ co_yield {1e100}; // expected-error {{cannot be narrowed}} expected-note {{explicit cast}} expected-warning {{implicit conversion}} expected-warning {{braces around scalar}}
co_yield {"foo", __LONG_LONG_MAX__}; // expected-error {{cannot be narrowed}} expected-note {{explicit cast}} expected-warning {{changes value}}
co_yield {"foo"};
co_yield "foo"; // expected-error {{no matching}}
@@ -320,6 +323,11 @@ void unevaluated() {
typeid(co_yield a); // expected-error {{cannot be used in an unevaluated context}}
}
+// [expr.await]p2: "An await-expression shall not appear in a default argument."
+// FIXME: A better diagnostic would explicitly state that default arguments are
+// not allowed. A user may not understand that this is "outside a function."
+void default_argument(int arg = co_await 0) {} // expected-error {{'co_await' cannot be used outside a function}}
+
constexpr auto constexpr_deduced_return_coroutine() {
co_yield 0; // expected-error {{'co_yield' cannot be used in a constexpr function}}
// expected-error@-1 {{'co_yield' cannot be used in a function with a deduced return type}}
@@ -510,8 +518,7 @@ coro<bad_promise_1> missing_get_return_object() { // expected-error {{no member
struct bad_promise_2 {
coro<bad_promise_2> get_return_object();
- // FIXME: We shouldn't offer a typo-correction here!
- suspend_always final_suspend(); // expected-note {{here}}
+ suspend_always final_suspend();
void unhandled_exception();
void return_void();
};
@@ -522,8 +529,7 @@ coro<bad_promise_2> missing_initial_suspend() { // expected-error {{no member na
struct bad_promise_3 {
coro<bad_promise_3> get_return_object();
- // FIXME: We shouldn't offer a typo-correction here!
- suspend_always initial_suspend(); // expected-note {{here}}
+ suspend_always initial_suspend();
void unhandled_exception();
void return_void();
};
@@ -781,6 +787,46 @@ coro<T> dependent_uses_nothrow_new(T) {
}
template coro<good_promise_13> dependent_uses_nothrow_new(good_promise_13);
+struct good_promise_custom_new_operator {
+ coro<good_promise_custom_new_operator> get_return_object();
+ suspend_always initial_suspend();
+ suspend_always final_suspend();
+ void return_void();
+ void unhandled_exception();
+ void *operator new(SizeT, double, float, int);
+};
+
+coro<good_promise_custom_new_operator>
+good_coroutine_calls_custom_new_operator(double, float, int) {
+ co_return;
+}
+
+struct coroutine_nonstatic_member_struct;
+
+struct good_promise_nonstatic_member_custom_new_operator {
+ coro<good_promise_nonstatic_member_custom_new_operator> get_return_object();
+ suspend_always initial_suspend();
+ suspend_always final_suspend();
+ void return_void();
+ void unhandled_exception();
+ void *operator new(SizeT, coroutine_nonstatic_member_struct &, double);
+};
+
+struct good_promise_noexcept_custom_new_operator {
+ static coro<good_promise_noexcept_custom_new_operator> get_return_object_on_allocation_failure();
+ coro<good_promise_noexcept_custom_new_operator> get_return_object();
+ suspend_always initial_suspend();
+ suspend_always final_suspend();
+ void return_void();
+ void unhandled_exception();
+ void *operator new(SizeT, double, float, int) noexcept;
+};
+
+coro<good_promise_noexcept_custom_new_operator>
+good_coroutine_calls_noexcept_custom_new_operator(double, float, int) {
+ co_return;
+}
+
struct mismatch_gro_type_tag1 {};
template<>
struct std::experimental::coroutine_traits<int, mismatch_gro_type_tag1> {
@@ -793,7 +839,7 @@ struct std::experimental::coroutine_traits<int, mismatch_gro_type_tag1> {
};
};
-extern "C" int f(mismatch_gro_type_tag1) {
+extern "C" int f(mismatch_gro_type_tag1) {
// expected-error@-1 {{cannot initialize return object of type 'int' with an rvalue of type 'void'}}
co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
}
@@ -810,7 +856,7 @@ struct std::experimental::coroutine_traits<int, mismatch_gro_type_tag2> {
};
};
-extern "C" int f(mismatch_gro_type_tag2) {
+extern "C" int f(mismatch_gro_type_tag2) {
// expected-error@-1 {{cannot initialize return object of type 'int' with an lvalue of type 'void *'}}
co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
}
@@ -828,7 +874,7 @@ struct std::experimental::coroutine_traits<int, mismatch_gro_type_tag3> {
};
};
-extern "C" int f(mismatch_gro_type_tag3) {
+extern "C" int f(mismatch_gro_type_tag3) {
// expected-error@-1 {{cannot initialize return object of type 'int' with an rvalue of type 'void'}}
co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
}
@@ -847,7 +893,7 @@ struct std::experimental::coroutine_traits<int, mismatch_gro_type_tag4> {
};
};
-extern "C" int f(mismatch_gro_type_tag4) {
+extern "C" int f(mismatch_gro_type_tag4) {
// expected-error@-1 {{cannot initialize return object of type 'int' with an rvalue of type 'char *'}}
co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
}
@@ -1171,4 +1217,155 @@ template CoroMemberTag DepTestType<int>::test_member_template(long, const char *
template CoroMemberTag DepTestType<int>::test_static_template<void>(const char *volatile &, unsigned);
+struct bad_promise_deleted_constructor {
+ // expected-note@+1 {{'bad_promise_deleted_constructor' has been explicitly marked deleted here}}
+ bad_promise_deleted_constructor() = delete;
+ coro<bad_promise_deleted_constructor> get_return_object();
+ suspend_always initial_suspend();
+ suspend_always final_suspend();
+ void return_void();
+ void unhandled_exception();
+};
+
+coro<bad_promise_deleted_constructor>
+bad_coroutine_calls_deleted_promise_constructor() {
+ // expected-error@-1 {{call to deleted constructor of 'std::experimental::coroutine_traits<coro<CoroHandleMemberFunctionTest::bad_promise_deleted_constructor>>::promise_type' (aka 'CoroHandleMemberFunctionTest::bad_promise_deleted_constructor')}}
+ co_return;
+}
+
+// Test that, when the promise type has a constructor whose signature matches
+// that of the coroutine function, that constructor is used. If no matching
+// constructor exists, the default constructor is used as a fallback. If no
+// matching constructors exist at all, an error is emitted. This is an
+// experimental feature that will be proposed for the Coroutines TS.
+
+struct good_promise_default_constructor {
+ good_promise_default_constructor(double, float, int);
+ good_promise_default_constructor() = default;
+ coro<good_promise_default_constructor> get_return_object();
+ suspend_always initial_suspend();
+ suspend_always final_suspend();
+ void return_void();
+ void unhandled_exception();
+};
+
+coro<good_promise_default_constructor>
+good_coroutine_calls_default_constructor() {
+ co_return;
+}
+
+struct some_class;
+
+struct good_promise_custom_constructor {
+ good_promise_custom_constructor(some_class&, float, int);
+ good_promise_custom_constructor(double, float, int);
+ good_promise_custom_constructor() = delete;
+ coro<good_promise_custom_constructor> get_return_object();
+ suspend_always initial_suspend();
+ suspend_always final_suspend();
+ void return_void();
+ void unhandled_exception();
+};
+
+coro<good_promise_custom_constructor>
+good_coroutine_calls_custom_constructor(double, float, int) {
+ co_return;
+}
+
+struct some_class {
+ coro<good_promise_custom_constructor>
+ good_coroutine_calls_custom_constructor(float, int) {
+ co_return;
+ }
+ coro<good_promise_custom_constructor>
+ static good_coroutine_calls_custom_constructor(double, float, int) {
+ co_return;
+ }
+};
+
+struct bad_promise_no_matching_constructor {
+ bad_promise_no_matching_constructor(int, int, int);
+ // expected-note@+1 2 {{'bad_promise_no_matching_constructor' has been explicitly marked deleted here}}
+ bad_promise_no_matching_constructor() = delete;
+ coro<bad_promise_no_matching_constructor> get_return_object();
+ suspend_always initial_suspend();
+ suspend_always final_suspend();
+ void return_void();
+ void unhandled_exception();
+};
+
+coro<bad_promise_no_matching_constructor>
+bad_coroutine_calls_with_no_matching_constructor(int, int) {
+ // expected-error@-1 {{call to deleted constructor of 'std::experimental::coroutine_traits<coro<CoroHandleMemberFunctionTest::bad_promise_no_matching_constructor>, int, int>::promise_type' (aka 'CoroHandleMemberFunctionTest::bad_promise_no_matching_constructor')}}
+ co_return;
+}
+
+struct some_class2 {
+coro<bad_promise_no_matching_constructor>
+bad_coroutine_calls_with_no_matching_constructor(int, int, int) {
+ // expected-error@-1 {{call to deleted constructor}}
+ co_return;
+}
+};
+
} // namespace CoroHandleMemberFunctionTest
+
+class awaitable_no_unused_warn {
+public:
+ using handle_type = std::experimental::coroutine_handle<>;
+ constexpr bool await_ready() { return false; }
+ void await_suspend(handle_type) noexcept {}
+ int await_resume() { return 1; }
+};
+
+
+class awaitable_unused_warn {
+public:
+ using handle_type = std::experimental::coroutine_handle<>;
+ constexpr bool await_ready() { return false; }
+ void await_suspend(handle_type) noexcept {}
+ [[nodiscard]]
+ int await_resume() { return 1; }
+};
+
+template <class Await>
+struct check_warning_promise {
+ coro<check_warning_promise> get_return_object();
+ Await initial_suspend();
+ Await final_suspend();
+ Await yield_value(int);
+ void return_void();
+ void unhandled_exception();
+};
+
+
+coro<check_warning_promise<awaitable_no_unused_warn>>
+test_no_unused_warning() {
+ co_await awaitable_no_unused_warn();
+ co_yield 42;
+}
+
+coro<check_warning_promise<awaitable_unused_warn>>
+test_unused_warning() {
+ co_await awaitable_unused_warn(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ co_yield 42; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+}
+
+struct missing_await_ready {
+ void await_suspend(std::experimental::coroutine_handle<>);
+ void await_resume();
+};
+struct missing_await_suspend {
+ bool await_ready();
+ void await_resume();
+};
+struct missing_await_resume {
+ bool await_ready();
+ void await_suspend(std::experimental::coroutine_handle<>);
+};
+
+void test_missing_awaitable_members() {
+ co_await missing_await_ready{}; // expected-error {{no member named 'await_ready' in 'missing_await_ready'}}
+ co_await missing_await_suspend{}; // expected-error {{no member named 'await_suspend' in 'missing_await_suspend'}}
+ co_await missing_await_resume{}; // expected-error {{no member named 'await_resume' in 'missing_await_resume'}}
+}
diff --git a/test/SemaCXX/cxx-deprecated.cpp b/test/SemaCXX/cxx-deprecated.cpp
index 47accd4ae1d5..aa4501d53197 100644
--- a/test/SemaCXX/cxx-deprecated.cpp
+++ b/test/SemaCXX/cxx-deprecated.cpp
@@ -24,3 +24,6 @@ void g() {
}
namespace M = N; // expected-warning {{'N' is deprecated}}
+
+// Shouldn't diag:
+[[nodiscard, deprecated("")]] int PR37935();
diff --git a/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp b/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
index 860a4aa6c6ff..f371891e5480 100644
--- a/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
+++ b/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
@@ -153,13 +153,14 @@ void dangle() {
}
struct haslist1 {
- std::initializer_list<int> il = {1, 2, 3}; // expected-warning{{at the end of the constructor}}
- std::initializer_list<int> jl{1, 2, 3}; // expected-warning{{at the end of the constructor}}
+ std::initializer_list<int> il // expected-note {{declared here}}
+ = {1, 2, 3}; // ok, unused
+ std::initializer_list<int> jl{1, 2, 3}; // expected-note {{default member init}}
haslist1();
};
-haslist1::haslist1()
-: il{1, 2, 3} // expected-warning{{at the end of the constructor}}
+haslist1::haslist1() // expected-error {{backing array for 'std::initializer_list' member 'jl' is a temporary object}}
+: il{1, 2, 3} // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}}
{}
namespace PR12119 {
diff --git a/test/SemaCXX/cxx0x-nontrivial-union.cpp b/test/SemaCXX/cxx0x-nontrivial-union.cpp
index db296bd57d71..f0927768f3fc 100644
--- a/test/SemaCXX/cxx0x-nontrivial-union.cpp
+++ b/test/SemaCXX/cxx0x-nontrivial-union.cpp
@@ -110,7 +110,7 @@ namespace optional {
}
explicit operator bool() const { return has; }
- T &operator*() const { return value; }
+ T &operator*() { return value; }
};
optional<non_trivial> o1;
diff --git a/test/SemaCXX/cxx11-gnu-attrs.cpp b/test/SemaCXX/cxx11-gnu-attrs.cpp
index 231be727714e..b020d2ae2939 100644
--- a/test/SemaCXX/cxx11-gnu-attrs.cpp
+++ b/test/SemaCXX/cxx11-gnu-attrs.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=c++11 -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=c++11 -Wno-gcc-compat -verify %s
// Error cases.
@@ -18,8 +18,7 @@ int *[[gnu::unused]] attr_on_ptr;
// expected-warning@-2 {{calling convention '__stdcall' ignored for this target}}
[[gnu::fastcall]] void pr17424_4() [[gnu::stdcall]];
// expected-warning@-1 {{calling convention 'fastcall' ignored for this target}}
-// expected-warning@-2 {{attribute 'stdcall' ignored, because it cannot be applied to a type}}
-// expected-warning@-3 {{calling convention 'stdcall' ignored for this target}}
+// expected-warning@-2 {{calling convention 'stdcall' ignored for this target}}
void pr17424_5 [[gnu::fastcall]]();
// expected-warning@-1 {{calling convention 'fastcall' ignored for this target}}
diff --git a/test/SemaCXX/cxx1y-contextual-conversion-tweaks.cpp b/test/SemaCXX/cxx1y-contextual-conversion-tweaks.cpp
index c7e6074a4437..7cb83c6f8876 100644
--- a/test/SemaCXX/cxx1y-contextual-conversion-tweaks.cpp
+++ b/test/SemaCXX/cxx1y-contextual-conversion-tweaks.cpp
@@ -96,8 +96,8 @@ namespace extended_examples {
//expected-error@81 {{statement requires expression of integer type ('extended_examples::A1' invalid)}}
//expected-error@85 {{statement requires expression of integer type ('extended_examples::B2' invalid)}}
#else
-//expected-error@81 {{cannot initialize object parameter of type 'extended_examples::A1' with an expression of type 'extended_examples::A1'}}
-//expected-error@85 {{cannot initialize object parameter of type 'extended_examples::B2' with an expression of type 'extended_examples::B2'}}
+//expected-error@81 {{'this' argument to member function 'operator int' is an lvalue, but function has rvalue ref-qualifier}} expected-note@54 {{'operator int' declared here}}
+//expected-error@85 {{'this' argument to member function 'operator int' is an lvalue, but function has rvalue ref-qualifier}} expected-note@75 {{'operator int' declared here}}
#endif
namespace extended_examples_cxx1y {
@@ -149,9 +149,9 @@ namespace extended_examples_cxx1y {
#ifdef CXX1Y
//expected-error@139 {{statement requires expression of integer type ('extended_examples_cxx1y::A2' invalid)}}
#else
-//expected-error@138 {{cannot initialize object parameter of type 'extended_examples_cxx1y::A1' with an expression of type 'extended_examples_cxx1y::A1'}}
-//expected-error@139 {{cannot initialize object parameter of type 'extended_examples_cxx1y::A2' with an expression of type 'extended_examples_cxx1y::A2'}}
-//expected-error@143 {{cannot initialize object parameter of type 'extended_examples_cxx1y::D' with an expression of type 'extended_examples_cxx1y::D'}}
+//expected-error@138 {{'this' argument to member function 'operator int' is an lvalue, but function has rvalue ref-qualifier}} expected-note@106 {{'operator int' declared here}}
+//expected-error@139 {{'this' argument to member function 'operator int' is an lvalue, but function has rvalue ref-qualifier}} expected-note@111 {{'operator int' declared here}}
+//expected-error@143 {{'this' argument to member function 'operator int' is an lvalue, but function has rvalue ref-qualifier}} expected-note@131 {{'operator int' declared here}}
#endif
namespace extended_examples_array_bounds {
diff --git a/test/SemaCXX/cxx1y-generic-lambdas.cpp b/test/SemaCXX/cxx1y-generic-lambdas.cpp
index 9f3c77591a86..7c3b970ae8f6 100644
--- a/test/SemaCXX/cxx1y-generic-lambdas.cpp
+++ b/test/SemaCXX/cxx1y-generic-lambdas.cpp
@@ -181,7 +181,7 @@ int test() {
int (*fp2)(int) = [](auto b) -> int { return b; };
int (*fp3)(char) = [](auto c) -> int { return c; };
char (*fp4)(int) = [](auto d) { return d; }; //expected-error{{no viable conversion}}\
- //expected-note{{candidate template ignored}}
+ //expected-note{{candidate function [with $0 = int]}}
char (*fp5)(char) = [](auto e) -> int { return e; }; //expected-error{{no viable conversion}}\
//expected-note{{candidate template ignored}}
@@ -207,12 +207,22 @@ int variadic_test() {
} // end ns
namespace conversion_operator {
-void test() {
- auto L = [](auto a) -> int { return a; };
+ void test() {
+ auto L = [](auto a) -> int { return a; }; // expected-error {{cannot initialize}}
int (*fp)(int) = L;
int (&fp2)(int) = [](auto a) { return a; }; // expected-error{{non-const lvalue}}
int (&&fp3)(int) = [](auto a) { return a; }; // expected-error{{no viable conversion}}\
//expected-note{{candidate}}
+
+ using F = int(int);
+ using G = int(void*);
+ L.operator F*();
+ L.operator G*(); // expected-note-re {{instantiation of function template specialization '{{.*}}::operator()<void *>'}}
+
+ // Here, the conversion function is named 'operator auto (*)(int)', and
+ // there is no way to write that name in valid C++.
+ auto M = [](auto a) -> auto { return a; };
+ M.operator F*(); // expected-error {{no member named 'operator int (*)(int)'}}
}
}
}
@@ -992,4 +1002,4 @@ namespace PR32638 {
void test() {
[](auto x) noexcept(noexcept(x)) { } (0);
}
-} \ No newline at end of file
+}
diff --git a/test/SemaCXX/cxx1y-variable-templates_in_class.cpp b/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
index 66f0f10f0f3d..b09305d7a0c1 100644
--- a/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
+++ b/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
@@ -15,8 +15,8 @@ class A {
template<typename T> static CONST T right<T,int> = 5;
template<typename T> CONST int right<int,T>; // expected-error {{member 'right' declared as a template}}
template<typename T> CONST float right<float,T> = 5; // expected-error {{member 'right' declared as a template}}
- template<> static CONST int right<int,int> = 7; // expected-error {{explicit specialization of 'right' in class scope}}
- template<> static CONST float right<float,int>; // expected-error {{explicit specialization of 'right' in class scope}}
+ template<> static CONST int right<int,int> = 7;
+ template<> static CONST float right<float,int>;
template static CONST int right<int,int>; // expected-error {{expected '<' after 'template'}}
};
@@ -163,8 +163,8 @@ namespace constexpred {
template<typename T> constexpr int right<int,T>; // expected-error {{member 'right' declared as a template}} \
// expected-error {{non-static data member cannot be constexpr; did you intend to make it const?}}
template<typename T> constexpr float right<float,T> = 5; // expected-error {{non-static data member cannot be constexpr; did you intend to make it static?}}
- template<> static constexpr int right<int,int> = 7; // expected-error {{explicit specialization of 'right' in class scope}}
- template<> static constexpr float right<float,int>; // expected-error {{explicit specialization of 'right' in class scope}}
+ template<> static constexpr int right<int,int> = 7;
+ template<> static constexpr float right<float,int>; // expected-error {{requires an initializer}}
template static constexpr int right<int,int>; // expected-error {{expected '<' after 'template'}}
};
}
@@ -296,17 +296,17 @@ namespace in_class_template {
};
template<typename T> void f() {
- typename T::template A<int> a; // expected-error {{template name refers to non-type template 'S::A'}}
+ typename T::template A<int> a; // expected-error {{template name refers to non-type template 'S::template A'}}
}
template<typename T> void g() {
- T::template A<int>::B = 0; // expected-error {{template name refers to non-type template 'S::A'}}
+ T::template A<int>::B = 0; // expected-error {{template name refers to non-type template 'S::template A'}}
}
template<typename T> void h() {
- class T::template A<int> c; // expected-error {{template name refers to non-type template 'S::A'}}
+ class T::template A<int> c; // expected-error {{template name refers to non-type template 'S::template A'}}
}
template<typename T>
- struct X : T::template A<int> {}; // expected-error {{template name refers to non-type template 'S::A'}}
+ struct X : T::template A<int> {}; // expected-error {{template name refers to non-type template 'S::template A'}}
template void f<S>(); // expected-note {{in instantiation of}}
template void g<S>(); // expected-note {{in instantiation of}}
@@ -380,3 +380,18 @@ int main() {
} // end ns PR24473
#endif // CPP1Y
+namespace dependent_static_var_template {
+ struct A {
+ template<int = 0> static int n; // expected-note 2{{here}}
+ };
+ int &r = A::template n; // expected-error {{use of variable template 'n' requires template arguments}}
+
+ template<typename T>
+ int &f() { return T::template n; } // expected-error {{use of variable template 'n' requires template arguments}}
+ int &s = f<A>(); // expected-note {{instantiation of}}
+
+ namespace B {
+ template<int = 0> static int n; // expected-note {{here}}
+ }
+ int &t = B::template n; // expected-error {{use of variable template 'n' requires template arguments}}
+}
diff --git a/test/SemaCXX/cxx1y-variable-templates_top_level.cpp b/test/SemaCXX/cxx1y-variable-templates_top_level.cpp
index a78548b6f128..ddc9c8a6b25b 100644
--- a/test/SemaCXX/cxx1y-variable-templates_top_level.cpp
+++ b/test/SemaCXX/cxx1y-variable-templates_top_level.cpp
@@ -30,8 +30,8 @@ namespace use_in_top_level_funcs {
void no_deduce() {
// template arguments are not deduced for uses of variable templates.
- int ipi = pi; // expected-error {{cannot refer to variable template 'pi' without a template argument list}}
- int icpi = cpi; // expected-error {{cannot refer to variable template 'cpi' without a template argument list}}
+ int ipi = pi; // expected-error {{use of variable template 'pi' requires template arguments}}
+ int icpi = cpi; // expected-error {{use of variable template 'cpi' requires template arguments}}
}
template<typename T>
@@ -409,7 +409,7 @@ namespace nested {
#endif
float f1 = pi1a<float>;
- template<> double pi1a<double> = 5.2; // expected-error {{variable template specialization of 'pi1a' must originally be declared in namespace 'n1'}}
+ template<> double pi1a<double> = 5.2; // expected-error {{not in a namespace enclosing 'n1'}}
double d1 = pi1a<double>;
}
@@ -422,8 +422,7 @@ namespace nested {
#endif
float f1 = n1::pi1b<float>;
- template<> double n1::pi1b<double> = 5.2; // expected-error {{cannot define or redeclare 'pi1b' here because namespace 'use_n1b' does not enclose namespace 'n1'}} \
- // expected-error {{variable template specialization of 'pi1b' must originally be declared in namespace 'n1'}}
+ template<> double n1::pi1b<double> = 5.2; // expected-error {{not in a namespace enclosing 'n1'}}
double d1 = n1::pi1b<double>;
}
}
@@ -466,5 +465,5 @@ auto variadic2 = Variadic<int, int>;
namespace VexingParse {
template <typename> int var; // expected-note {{declared here}}
- int x(var); // expected-error {{cannot refer to variable template 'var' without a template argument list}}
+ int x(var); // expected-error {{use of variable template 'var' requires template arguments}}
}
diff --git a/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp b/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
index 9080f67fe0e1..f72cb886d81a 100644
--- a/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
+++ b/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
@@ -309,6 +309,70 @@ namespace dependent {
template int New(int);
}
+namespace injected_class_name {
+ template<typename T = void> struct A {
+ A();
+ template<typename U> A(A<U>);
+ };
+ A<int> a;
+ A b = a;
+ using T = decltype(a);
+ using T = decltype(b);
+}
+
+namespace member_guides {
+ // PR34520
+ template<class>
+ struct Foo {
+ template <class T> struct Bar {
+ Bar(...) {}
+ };
+ Bar(int) -> Bar<int>;
+ };
+ Foo<int>::Bar b = 0;
+
+ struct A {
+ template<typename T> struct Public; // expected-note {{declared public}}
+ Public(float) -> Public<float>;
+ protected: // expected-note {{declared protected by intervening access specifier}}
+ template<typename T> struct Protected; // expected-note 2{{declared protected}}
+ Protected(float) -> Protected<float>;
+ Public(int) -> Public<int>; // expected-error {{different access}}
+ private: // expected-note {{declared private by intervening access specifier}}
+ template<typename T> struct Private; // expected-note {{declared private}}
+ Protected(int) -> Protected<int>; // expected-error {{different access}}
+ public: // expected-note 2{{declared public by intervening access specifier}}
+ template<typename T> Public(T) -> Public<T>;
+ template<typename T> Protected(T) -> Protected<T>; // expected-error {{different access}}
+ template<typename T> Private(T) -> Private<T>; // expected-error {{different access}}
+ };
+}
+
+namespace rdar41903969 {
+template <class T> struct A {};
+template <class T> struct B;
+template <class T> struct C {
+ C(A<T>&);
+ C(B<T>&);
+};
+
+void foo(A<int> &a, B<int> &b) {
+ (void)C{b};
+ (void)C{a};
+}
+
+template<typename T> struct X {
+ X(std::initializer_list<T>) = delete;
+ X(const X&);
+};
+
+template <class T> struct D : X<T> {};
+
+void bar(D<int>& d) {
+ (void)X{d};
+}
+}
+
#else
// expected-no-diagnostics
diff --git a/test/SemaCXX/cxx1z-constexpr-lambdas.cpp b/test/SemaCXX/cxx1z-constexpr-lambdas.cpp
index 4a98a1b06c87..bdf6847ec3dd 100644
--- a/test/SemaCXX/cxx1z-constexpr-lambdas.cpp
+++ b/test/SemaCXX/cxx1z-constexpr-lambdas.cpp
@@ -6,7 +6,7 @@
namespace test_lambda_is_literal {
#ifdef CPP14_AND_EARLIER
//expected-error@+4{{not a literal type}}
-//expected-note@+2{{not an aggregate and has no constexpr constructors}}
+//expected-note@+2{{lambda closure types are non-literal types before C++17}}
#endif
auto L = [] { };
constexpr int foo(decltype(L) l) { return 0; }
@@ -270,4 +270,37 @@ namespace ns1_test_lvalue_type {
} // end ns test_lambda_is_cce
+namespace PR36054 {
+constexpr int fn() {
+ int Capture = 42;
+ return [=]() constexpr { return Capture; }();
+}
+
+static_assert(fn() == 42, "");
+
+template <class T>
+constexpr int tfn() {
+ int Capture = 42;
+ return [=]() constexpr { return Capture; }();
+}
+
+static_assert(tfn<int>() == 42, "");
+
+constexpr int gfn() {
+ int Capture = 42;
+ return [=](auto P) constexpr { return Capture + P; }(58);
+}
+
+static_assert(gfn() == 100, "");
+
+constexpr bool OtherCaptures() {
+ int Capture = 42;
+ constexpr auto Outer = [](auto P) constexpr { return 42 + P; };
+ auto Inner = [&](auto O) constexpr { return O(58) + Capture; };
+ return Inner(Outer) == 142;
+}
+
+static_assert(OtherCaptures(), "");
+} // namespace PR36054
+
#endif // ndef CPP14_AND_EARLIER
diff --git a/test/SemaCXX/cxx1z-decomposition.cpp b/test/SemaCXX/cxx1z-decomposition.cpp
index 7a4221784ad3..3c9b181f1c8f 100644
--- a/test/SemaCXX/cxx1z-decomposition.cpp
+++ b/test/SemaCXX/cxx1z-decomposition.cpp
@@ -76,4 +76,9 @@ template <class T> void dependent_foreach(T t) {
a,b,c;
}
+struct PR37352 {
+ int n;
+ void f() { static auto [a] = *this; } // expected-error {{cannot be declared 'static'}}
+};
+
// FIXME: by-value array copies
diff --git a/test/SemaCXX/cxx1z-noexcept-function-type.cpp b/test/SemaCXX/cxx1z-noexcept-function-type.cpp
index 814b04c6e42f..82ed724e1bd9 100644
--- a/test/SemaCXX/cxx1z-noexcept-function-type.cpp
+++ b/test/SemaCXX/cxx1z-noexcept-function-type.cpp
@@ -10,7 +10,7 @@ template<typename T> void redecl1() noexcept(noexcept(T())); // ok, same type
template<typename T> void redecl1() noexcept(noexcept(T())) {} // expected-error {{redefinition}}
template<bool A, bool B> void redecl2() noexcept(A); // expected-note {{previous}}
-template<bool A, bool B> void redecl2() noexcept(B); // expected-error {{conflicting types}}
+template<bool A, bool B> void redecl2() noexcept(B); // expected-error {{does not match previous}}
// These have the same canonical type, but are still different.
template<typename A, typename B> void redecl3() throw(A); // expected-note {{previous}}
diff --git a/test/SemaCXX/cxx2a-lambda-equals-this.cpp b/test/SemaCXX/cxx2a-lambda-equals-this.cpp
index ce6916322e5d..652fb8da9b6d 100644
--- a/test/SemaCXX/cxx2a-lambda-equals-this.cpp
+++ b/test/SemaCXX/cxx2a-lambda-equals-this.cpp
@@ -1,5 +1,4 @@
-// RUN: %clang_cc1 -std=c++2a -verify %s
-// expected-no-diagnostics
+// RUN: %clang_cc1 -std=c++2a -verify %s -Wdeprecated
// This test does two things.
// Deleting the copy constructor ensures that an [=, this] capture doesn't copy the object.
@@ -13,3 +12,12 @@ class A {
L();
}
};
+
+struct B {
+ int i;
+ void f() {
+ (void) [=] { // expected-note {{add an explicit capture of 'this'}}
+ return i; // expected-warning {{implicit capture of 'this' with a capture default of '=' is deprecated}}
+ };
+ }
+};
diff --git a/test/SemaCXX/cxx2a-pointer-to-const-ref-member.cpp b/test/SemaCXX/cxx2a-pointer-to-const-ref-member.cpp
index e9cbb1a18532..7c709d905f78 100644
--- a/test/SemaCXX/cxx2a-pointer-to-const-ref-member.cpp
+++ b/test/SemaCXX/cxx2a-pointer-to-const-ref-member.cpp
@@ -1,14 +1,17 @@
// RUN: %clang_cc1 -std=c++2a %s -verify
struct X {
- void ref() & {}
+ void ref() & {} // expected-note{{'ref' declared here}}
void cref() const& {}
+ void cvref() const volatile & {} // expected-note{{'cvref' declared here}}
};
void test() {
- X{}.ref(); // expected-error{{cannot initialize object parameter of type 'X' with an expression of type 'X'}}
+ X{}.ref(); // expected-error{{'this' argument to member function 'ref' is an rvalue, but function has non-const lvalue ref-qualifier}}
X{}.cref(); // expected-no-error
+ X{}.cvref(); // expected-error{{'this' argument to member function 'cvref' is an rvalue, but function has non-const lvalue ref-qualifier}}
(X{}.*&X::ref)(); // expected-error-re{{pointer-to-member function type 'void (X::*)() {{.*}}&' can only be called on an lvalue}}
(X{}.*&X::cref)(); // expected-no-error
+ (X{}.*&X::cvref)(); // expected-error-re{{pointer-to-member function type 'void (X::*)() {{.*}}&' can only be called on an lvalue}}
}
diff --git a/test/SemaCXX/cxx2a-user-defined-literals.cpp b/test/SemaCXX/cxx2a-user-defined-literals.cpp
new file mode 100644
index 000000000000..d730eba741a8
--- /dev/null
+++ b/test/SemaCXX/cxx2a-user-defined-literals.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -std=c++2a %s -include %s -verify
+
+#ifndef INCLUDED
+#define INCLUDED
+
+#pragma clang system_header
+namespace std {
+ namespace chrono {
+ struct day{};
+ struct year{};
+ }
+ constexpr chrono::day operator"" d(unsigned long long d) noexcept;
+ constexpr chrono::year operator"" y(unsigned long long y) noexcept;
+}
+
+#else
+
+using namespace std;
+chrono::day dec_d = 5d;
+chrono::day oct_d = 05d;
+chrono::day bin_d = 0b011d;
+// expected-error@+3{{no viable conversion from 'int' to 'chrono::day'}}
+// expected-note@9{{candidate constructor (the implicit copy constructor)}}
+// expected-note@9{{candidate constructor (the implicit move constructor)}}
+chrono::day hex_d = 0x44d;
+chrono::year y = 10y;
+#endif
diff --git a/test/SemaCXX/cxx98-compat.cpp b/test/SemaCXX/cxx98-compat.cpp
index 4a9baf5100d6..f814a06f13be 100644
--- a/test/SemaCXX/cxx98-compat.cpp
+++ b/test/SemaCXX/cxx98-compat.cpp
@@ -47,6 +47,8 @@ namespace TemplateParsing {
void Lambda() {
[]{}(); // expected-warning {{lambda expressions are incompatible with C++98}}
+ // Don't warn about implicit "-> auto" here.
+ [](){}(); // expected-warning {{lambda expressions are incompatible with C++98}}
}
struct Ctor {
@@ -185,9 +187,9 @@ namespace RedundantParensInAddressTemplateParam {
}
namespace TemplateSpecOutOfScopeNs {
- template<typename T> struct S {}; // expected-note {{here}}
+ template<typename T> struct S {};
}
-template<> struct TemplateSpecOutOfScopeNs::S<char> {}; // expected-warning {{class template specialization of 'S' outside namespace 'TemplateSpecOutOfScopeNs' is incompatible with C++98}}
+template<> struct TemplateSpecOutOfScopeNs::S<char> {};
struct Typename {
template<typename T> struct Inner {};
@@ -239,13 +241,13 @@ namespace UnionOrAnonStructMembers {
~NonTrivDtor(); // expected-note 2{{user-provided destructor}}
};
union BadUnion {
- NonTrivCtor ntc; // expected-warning {{union member 'ntc' with a non-trivial constructor is incompatible with C++98}}
+ NonTrivCtor ntc; // expected-warning {{union member 'ntc' with a non-trivial default constructor is incompatible with C++98}}
NonTrivCopy ntcp; // expected-warning {{union member 'ntcp' with a non-trivial copy constructor is incompatible with C++98}}
NonTrivDtor ntd; // expected-warning {{union member 'ntd' with a non-trivial destructor is incompatible with C++98}}
};
struct Wrap {
struct {
- NonTrivCtor ntc; // expected-warning {{anonymous struct member 'ntc' with a non-trivial constructor is incompatible with C++98}}
+ NonTrivCtor ntc; // expected-warning {{anonymous struct member 'ntc' with a non-trivial default constructor is incompatible with C++98}}
NonTrivCopy ntcp; // expected-warning {{anonymous struct member 'ntcp' with a non-trivial copy constructor is incompatible with C++98}}
NonTrivDtor ntd; // expected-warning {{anonymous struct member 'ntd' with a non-trivial destructor is incompatible with C++98}}
};
@@ -346,7 +348,7 @@ namespace rdar11736429 {
};
union S {
- X x; // expected-warning{{union member 'x' with a non-trivial constructor is incompatible with C++98}}
+ X x; // expected-warning{{union member 'x' with a non-trivial default constructor is incompatible with C++98}}
};
}
diff --git a/test/SemaCXX/dllimport-constexpr.cpp b/test/SemaCXX/dllimport-constexpr.cpp
new file mode 100644
index 000000000000..95d75b906f96
--- /dev/null
+++ b/test/SemaCXX/dllimport-constexpr.cpp
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -std=c++14 %s -verify -fms-extensions -triple x86_64-windows-msvc
+// RUN: %clang_cc1 -std=c++17 %s -verify -fms-extensions -triple x86_64-windows-msvc
+
+__declspec(dllimport) void imported_func();
+__declspec(dllimport) int imported_int;
+struct Foo {
+ void __declspec(dllimport) imported_method();
+};
+
+// Instantiation is OK.
+template <void (*FP)()> struct TemplateFnPtr {
+ static void getit() { FP(); }
+};
+template <void (&FP)()> struct TemplateFnRef {
+ static void getit() { FP(); }
+};
+void instantiate1() {
+ TemplateFnPtr<&imported_func>::getit();
+ TemplateFnRef<imported_func>::getit();
+}
+
+// Check variable template instantiation.
+template <int *GI> struct TemplateIntPtr {
+ static int getit() { return *GI; }
+};
+template <int &GI> struct TemplateIntRef {
+ static int getit() { return GI; }
+};
+int instantiate2() {
+ int r = 0;
+ r += TemplateIntPtr<&imported_int>::getit();
+ r += TemplateIntRef<imported_int>::getit();
+ return r;
+}
+
+// Member pointer instantiation.
+template <void (Foo::*MP)()> struct TemplateMemPtr { };
+TemplateMemPtr<&Foo::imported_method> instantiate_mp;
+
+// constexpr initialization doesn't work for dllimport things.
+// expected-error@+1{{must be initialized by a constant expression}}
+constexpr void (*constexpr_import_func)() = &imported_func;
+// expected-error@+1{{must be initialized by a constant expression}}
+constexpr int *constexpr_import_int = &imported_int;
+// expected-error@+1{{must be initialized by a constant expression}}
+constexpr void (Foo::*constexpr_memptr)() = &Foo::imported_method;
+
+// We make dynamic initializers for 'const' globals, but not constexpr ones.
+void (*const const_import_func)() = &imported_func;
+int *const const_import_int = &imported_int;
+void (Foo::*const const_memptr)() = &Foo::imported_method;
+
+// Check that using a non-type template parameter for constexpr global
+// initialization is correctly diagnosed during template instantiation.
+template <void (*FP)()> struct StaticConstexpr {
+ // expected-error@+1{{must be initialized by a constant expression}}
+ static constexpr void (*g_fp)() = FP;
+};
+void instantiate3() {
+ // expected-note@+1 {{requested here}}
+ StaticConstexpr<imported_func>::g_fp();
+}
diff --git a/test/SemaCXX/dllimport-memptr.cpp b/test/SemaCXX/dllimport-memptr.cpp
index 35bf5b8610b5..937384e8234f 100644
--- a/test/SemaCXX/dllimport-memptr.cpp
+++ b/test/SemaCXX/dllimport-memptr.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-extensions -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-extensions -verify -std=c++17 %s
// expected-no-diagnostics
diff --git a/test/SemaCXX/err_typecheck_assign_const.cpp b/test/SemaCXX/err_typecheck_assign_const.cpp
index 7e2812565144..3725e58b422d 100644
--- a/test/SemaCXX/err_typecheck_assign_const.cpp
+++ b/test/SemaCXX/err_typecheck_assign_const.cpp
@@ -129,3 +129,23 @@ void test() {
Func &bar();
bar()() = 0; // expected-error {{read-only variable is not assignable}}
}
+
+typedef float float4 __attribute__((ext_vector_type(4)));
+struct OhNo {
+ float4 v;
+ void AssignMe() const { v.x = 1; } // expected-error {{cannot assign to non-static data member within const member function 'AssignMe'}} \
+ expected-note {{member function 'OhNo::AssignMe' is declared const here}}
+};
+
+typedef float float4_2 __attribute__((__vector_size__(16)));
+struct OhNo2 {
+ float4_2 v;
+ void AssignMe() const { v[0] = 1; } // expected-error {{cannot assign to non-static data member within const member function 'AssignMe'}} \
+ expected-note {{member function 'OhNo2::AssignMe' is declared const here}}
+};
+
+struct OhNo3 {
+ float v[4];
+ void AssignMe() const { v[0] = 1; } // expected-error {{cannot assign to non-static data member within const member function 'AssignMe'}} \
+ expected-note {{member function 'OhNo3::AssignMe' is declared const here}}
+};
diff --git a/test/SemaCXX/err_typecheck_assign_const_filecheck.cpp b/test/SemaCXX/err_typecheck_assign_const_filecheck.cpp
index 0d29b1e12f21..72ae40f0bdc5 100644
--- a/test/SemaCXX/err_typecheck_assign_const_filecheck.cpp
+++ b/test/SemaCXX/err_typecheck_assign_const_filecheck.cpp
@@ -220,7 +220,7 @@ void test4(const A Ca) {
// CHECK-NOT: note:
}
-// Only display notes for relavent cases.
+// Only display notes for relevant cases.
void test5(const A Ca) {
Ca.Mb.c.d.Ce.num = 5;
// CHECK-NOT: error:
diff --git a/test/SemaCXX/eval-crashes.cpp b/test/SemaCXX/eval-crashes.cpp
index 23946845d8ed..60c2deed4d34 100644
--- a/test/SemaCXX/eval-crashes.cpp
+++ b/test/SemaCXX/eval-crashes.cpp
@@ -26,10 +26,10 @@ namespace pr33140_0b {
namespace pr33140_2 {
// FIXME: The declaration of 'b' below should lifetime-extend two int
- // temporaries, invalidating this warning to some extent.
- struct A { int &&r = 0; }; // expected-warning {{binding reference member 'r' to a temporary}} expected-note {{here}}
+ // temporaries.
+ struct A { int &&r = 0; }; // expected-note 2{{initializing field 'r' with default member initializer}}
struct B { A x, y; };
- B b = {};
+ B b = {}; // expected-warning 2{{not supported}}
}
namespace pr33140_3 {
diff --git a/test/SemaCXX/extern-c.cpp b/test/SemaCXX/extern-c.cpp
index fa6c2b1990c0..1a32beec7baa 100644
--- a/test/SemaCXX/extern-c.cpp
+++ b/test/SemaCXX/extern-c.cpp
@@ -242,3 +242,20 @@ namespace tag_hiding {
ExternCStruct3 *q3 = p3;
ExternCStruct4 *q4 = p4; // expected-error {{ambiguous}}
}
+
+namespace PR35697 {
+ typedef struct {} *ReturnStruct;
+ extern "C" ReturnStruct PR35697_f();
+ extern "C" ReturnStruct PR35697_v;
+ ReturnStruct PR35697_f();
+ ReturnStruct PR35697_v;
+
+ namespace {
+ extern "C" ReturnStruct PR35697_f();
+ extern "C" ReturnStruct PR35697_v;
+ void q() {
+ extern ReturnStruct PR35697_f();
+ extern ReturnStruct PR35697_v;
+ }
+ }
+}
diff --git a/test/SemaCXX/extra-semi.cpp b/test/SemaCXX/extra-semi.cpp
new file mode 100644
index 000000000000..be7435a40681
--- /dev/null
+++ b/test/SemaCXX/extra-semi.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -verify -std=c++98 -Wextra-semi %s
+// RUN: %clang_cc1 -verify -std=c++03 -Wextra-semi %s
+// RUN: %clang_cc1 -verify -std=c++11 -Wextra-semi %s
+// RUN: %clang_cc1 -verify -std=c++17 -Wextra-semi %s
+// RUN: %clang_cc1 -verify -std=c++2a -Wextra-semi %s
+// RUN: %clang_cc1 -verify -Weverything -Wno-c++98-compat %s
+// RUN: %clang_cc1 -verify -Weverything -Wno-c++98-compat-pedantic -Wc++98-compat-extra-semi %s
+
+// Last RUN line checks that c++98-compat-extra-semi can still be re-enabled.
+
+void F();
+
+void F(){}
+;
+#if __cplusplus < 201103L
+// expected-warning@-2{{extra ';' outside of a function is a C++11 extension}}
+#else
+// expected-warning@-4{{extra ';' outside of a function is incompatible with C++98}}
+#endif
+
+namespace ns {
+class C {
+ void F() const;
+};
+}
+; // expected-warning {{extra ';' outside of a function is}}
+
+void ns::C::F() const {}
+; // expected-warning {{extra ';' outside of a function is}}
diff --git a/test/SemaCXX/for-range-examples.cpp b/test/SemaCXX/for-range-examples.cpp
index d6b527ff8a50..477789b56c14 100644
--- a/test/SemaCXX/for-range-examples.cpp
+++ b/test/SemaCXX/for-range-examples.cpp
@@ -221,11 +221,7 @@ namespace test7 {
for (c alignas(8) : arr) { // expected-error {{requires type for loop variable}}
static_assert(alignof(c) == 8, ""); // expected-warning {{extension}}
}
- // FIXME: The fix-it hint here is not sufficient to fix the error.
- // We fail to diagnose that d is underaligned for its type, because
- // we check the alignment attribute before we perform the auto
- // deduction.
- for (d alignas(1) : arr) {} // expected-error {{requires type for loop variable}}
+ for (d alignas(1) : arr) {} // expected-error {{requested alignment is less than minimum}} expected-error {{requires type for loop variable}}
for (e [[deprecated]] : arr) { e = 0; } // expected-warning {{deprecated}} expected-note {{here}} expected-error {{requires type for loop variable}}
}
}
@@ -274,4 +270,4 @@ int foo(int b) {
}();
return b;
}
-} \ No newline at end of file
+}
diff --git a/test/SemaCXX/friend2.cpp b/test/SemaCXX/friend2.cpp
index d1d4b628ba2d..8eacdeb19c62 100644
--- a/test/SemaCXX/friend2.cpp
+++ b/test/SemaCXX/friend2.cpp
@@ -101,6 +101,34 @@ template<typename T> class C12 {
friend void func_12(int x = 0); // expected-error{{friend declaration specifying a default argument must be the only declaration}}
};
+// Friend function with uninstantiated body is still a definition.
+
+template<typename T> struct C20 {
+ friend void func_20() {} // expected-note{{previous definition is here}}
+};
+C20<int> c20i;
+void func_20() {} // expected-error{{redefinition of 'func_20'}}
+
+template<typename T> struct C21a {
+ friend void func_21() {} // expected-note{{previous definition is here}}
+};
+template<typename T> struct C21b {
+ friend void func_21() {} // expected-error{{redefinition of 'func_21'}}
+};
+C21a<int> c21ai;
+C21b<int> c21bi; // expected-note{{in instantiation of template class 'C21b<int>' requested here}}
+
+template<typename T> struct C22a {
+ friend void func_22() {} // expected-note{{previous definition is here}}
+};
+template<typename T> struct C22b {
+ friend void func_22();
+};
+C22a<int> c22ai;
+C22b<int> c22bi;
+void func_22() {} // expected-error{{redefinition of 'func_22'}}
+
+
namespace pr22307 {
diff --git a/test/SemaCXX/i-c-e-cxx.cpp b/test/SemaCXX/i-c-e-cxx.cpp
index 9e01ccb6b336..2bfb67ffdf5b 100644
--- a/test/SemaCXX/i-c-e-cxx.cpp
+++ b/test/SemaCXX/i-c-e-cxx.cpp
@@ -23,10 +23,8 @@ int a() {
// expected-note@-2 {{read of object outside its lifetime}}
#endif
- switch(1) {
-#if __cplusplus <= 199711L
- // expected-warning@-2 {{no case matching constant switch condition '1'}}
-#endif
+ switch(1) { // do not warn that 1 is not a case value;
+ // 't' might have been expected to evalaute to 1
case t:; // expected-note {{initializer of 't' is not a constant expression}}
#if __cplusplus <= 199711L
// expected-error@-2 {{not an integral constant expression}}
diff --git a/test/SemaCXX/init-expr-crash.cpp b/test/SemaCXX/init-expr-crash.cpp
index 407da78e60b0..201ab03955cd 100644
--- a/test/SemaCXX/init-expr-crash.cpp
+++ b/test/SemaCXX/init-expr-crash.cpp
@@ -29,3 +29,11 @@ template <class T> struct B {
return 0;
}
};
+
+// This test checks for a crash that resulted from us miscomputing the
+// dependence of a nested initializer list.
+template<int> struct X {
+ static constexpr int n = 4;
+ static constexpr int a[1][1] = {n};
+};
+
diff --git a/test/SemaCXX/injected-class-name-crash.cpp b/test/SemaCXX/injected-class-name-crash.cpp
new file mode 100644
index 000000000000..2996a7cdb48c
--- /dev/null
+++ b/test/SemaCXX/injected-class-name-crash.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+template <class T>
+struct X : public Foo<Bar { // expected-error {{unknown template name 'Foo'}} expected-error {{use of undeclared identifier 'Bar'}}
+ X();
+}; // expected-error {{expected '{' after base class list}}
+
+
+template <class T>
+X<T>::X() {
+}
diff --git a/test/SemaCXX/instantiate-blocks.cpp b/test/SemaCXX/instantiate-blocks.cpp
index bb0f8d881d36..dbcef500b579 100644
--- a/test/SemaCXX/instantiate-blocks.cpp
+++ b/test/SemaCXX/instantiate-blocks.cpp
@@ -30,3 +30,12 @@ int main(void)
noret((float)0.0, double(0.0)); // expected-note {{in instantiation of function template specialization 'noret<float, double>' requested here}}
}
+namespace rdar41200624 {
+template <class T>
+struct S {
+ int (^p)() = ^{ return 0; };
+ T (^t)() = ^{ return T{}; };
+ T s = ^{ return T{}; }();
+};
+S<int> x;
+}
diff --git a/test/SemaCXX/integer-overflow.cpp b/test/SemaCXX/integer-overflow.cpp
index 6abc95614496..956ec157b3fa 100644
--- a/test/SemaCXX/integer-overflow.cpp
+++ b/test/SemaCXX/integer-overflow.cpp
@@ -169,3 +169,18 @@ uint64_t check_integer_overflows(int i) { //expected-note {{declared here}}
// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}}
return ((4608 * 1024 * 1024) + ((uint64_t)(4608 * 1024 * 1024)));
}
+
+void check_integer_overflows_in_function_calls() {
+// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+ (void)f0(4608 * 1024 * 1024);
+
+// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+ uint64_t x = f0(4608 * 1024 * 1024);
+
+// expected-warning@+2 {{overflow in expression; result is 536870912 with type 'int'}}
+ uint64_t (*f0_ptr)(uint64_t) = &f0;
+ (void)(*f0_ptr)(4608 * 1024 * 1024);
+
+// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+ (void)f2(0, f0(4608 * 1024 * 1024));
+}
diff --git a/test/SemaCXX/invalid-template-specifier.cpp b/test/SemaCXX/invalid-template-specifier.cpp
index bcd6da7f32f7..140ad00c9e6f 100644
--- a/test/SemaCXX/invalid-template-specifier.cpp
+++ b/test/SemaCXX/invalid-template-specifier.cpp
@@ -7,6 +7,6 @@ const template basic_istream<char>; // expected-error {{expected unqualified-id}
namespace S {}
template <class X> class Y {
- void x() { S::template y<char>(1); } // expected-error {{does not refer to a template}} \
+ void x() { S::template y<char>(1); } // expected-error {{no member named 'y' in namespace 'S'}} \
// expected-error {{unqualified-id}}
};
diff --git a/test/SemaCXX/lambda-expressions.cpp b/test/SemaCXX/lambda-expressions.cpp
index efbb47681ade..4565345fc665 100644
--- a/test/SemaCXX/lambda-expressions.cpp
+++ b/test/SemaCXX/lambda-expressions.cpp
@@ -583,3 +583,43 @@ namespace PR25627_dont_odr_use_local_consts {
(void) [] { X<N> x; };
}
}
+
+namespace ConversionOperatorDoesNotHaveDeducedReturnType {
+ auto x = [](int){};
+ auto y = [](auto) -> void {};
+ using T = decltype(x);
+ using U = decltype(y);
+ using ExpectedTypeT = void (*)(int);
+ template<typename T>
+ using ExpectedTypeU = void (*)(T);
+
+ struct X {
+ friend T::operator ExpectedTypeT() const;
+
+ // Formally, this is invalid, because the return type of the conversion
+ // function for a generic lambda expression is an unspecified decltype
+ // type, which this should not match. However, this declaration is
+ // functionally equivalent to that one, so we're permitted to choose to
+ // accept this.
+ template<typename T>
+ friend U::operator ExpectedTypeU<T>() const;
+ };
+
+ // This used to crash in return type deduction for the conversion opreator.
+ struct A { int n; void f() { +[](decltype(n)) {}; } };
+}
+
+namespace TypoCorrection {
+template <typename T> struct X {};
+// expected-note@-1 {{template parameter is declared here}}
+
+template <typename T>
+void Run(const int& points) {
+// expected-note@-1 {{'points' declared here}}
+ auto outer_lambda = []() {
+ auto inner_lambda = [](const X<Points>&) {};
+ // expected-error@-1 {{use of undeclared identifier 'Points'; did you mean 'points'?}}
+ // expected-error@-2 {{template argument for template type parameter must be a type}}
+ };
+}
+}
diff --git a/test/SemaCXX/large-array-init.cpp b/test/SemaCXX/large-array-init.cpp
new file mode 100644
index 000000000000..ba7342805978
--- /dev/null
+++ b/test/SemaCXX/large-array-init.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -S -o %t.ll -mllvm -debug-only=exprconstant %s 2>&1 | \
+// RUN: FileCheck %s
+// REQUIRES: asserts
+
+struct S { int i; };
+
+static struct S arr[100000000] = {{ 0 }};
+// CHECK: The number of elements to initialize: 1.
+
+struct S *foo() { return arr; }
diff --git a/test/SemaCXX/member-init.cpp b/test/SemaCXX/member-init.cpp
index 82750878e584..8a13eca2f177 100644
--- a/test/SemaCXX/member-init.cpp
+++ b/test/SemaCXX/member-init.cpp
@@ -86,9 +86,8 @@ namespace PR14838 {
};
struct thing {};
struct another {
- another() : r(thing()) {}
+ another() : r(thing()) {} // expected-error {{binds to a temporary object}}
// expected-error@-1 {{temporary of type 'PR14838::function' has private destructor}}
- // expected-warning@-2 {{binding reference member 'r' to a temporary value}}
const function &r; // expected-note {{reference member declared here}}
} af;
}
@@ -101,7 +100,7 @@ namespace rdar14084171 {
struct Sprite {
Point location = Point(0,0); // expected-error {{no matching constructor for initialization of 'rdar14084171::Point'}}
};
- void f(Sprite& x) { x = x; }
+ void f(Sprite& x) { x = x; } // expected-warning {{explicitly assigning value of variable}}
}
namespace PR18560 {
diff --git a/test/SemaCXX/ms-initlist-narrowing.cpp b/test/SemaCXX/ms-initlist-narrowing.cpp
new file mode 100644
index 000000000000..687a206d4974
--- /dev/null
+++ b/test/SemaCXX/ms-initlist-narrowing.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 %s -fsyntax-only -verify -fms-extensions -fms-compatibility-version=19.0 -std=c++11
+
+int ai[] = { 1, 2.0 }; // expected-error {{type 'double' cannot be narrowed to 'int' in initializer list}} expected-note {{silence}}
+
+template<typename T>
+struct Agg {
+ T t;
+};
+
+void f(int i) {
+ // Constant expression.
+ Agg<float> f8 = {1E50}; // expected-error {{constant expression evaluates to 1.000000e+50 which cannot be narrowed to type 'float'}} expected-note {{silence}}
+
+ // Non-constant expression.
+ double d = 1.0;
+ Agg<float> f2 = {d}; // expected-error {{non-constant-expression cannot be narrowed from type 'double' to 'float'}} expected-note {{silence}}
+}
diff --git a/test/SemaCXX/ms-interface.cpp b/test/SemaCXX/ms-interface.cpp
index 66ce376e2a94..c827f4c5703c 100644
--- a/test/SemaCXX/ms-interface.cpp
+++ b/test/SemaCXX/ms-interface.cpp
@@ -47,7 +47,7 @@ __interface I4 : I1, I2 {
void fn2() final;
};
-// expected-error@+1 {{interface type cannot inherit from non-public 'interface I1'}}
+// expected-error@+1 {{interface type cannot inherit from non-public interface 'I1'}}
__interface I5 : private I1 {
};
@@ -65,12 +65,12 @@ static_assert(!__is_interface_class(C), "oops");
static_assert(!__is_interface_class(I), "oops");
static_assert(!__is_interface_class(U), "oops");
-// expected-error@55 {{interface type cannot inherit from 'struct S'}}
+// expected-error@55 {{interface type cannot inherit from struct 'S'}}
// expected-note@+1 {{in instantiation of template class 'I6<S>' requested here}}
struct S1 : I6<S> {
};
-// expected-error@55 {{interface type cannot inherit from 'class C'}}
+// expected-error@55 {{interface type cannot inherit from class 'C'}}
// expected-note@+1 {{in instantiation of template class 'I6<C>' requested here}}
class C1 : I6<C> {
};
diff --git a/test/SemaCXX/ms-uuid.cpp b/test/SemaCXX/ms-uuid.cpp
index e29dda878e68..624ac0541db4 100644
--- a/test/SemaCXX/ms-uuid.cpp
+++ b/test/SemaCXX/ms-uuid.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions %s -Wno-deprecated-declarations
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify -fms-extensions %s -Wno-deprecated-declarations
typedef struct _GUID {
unsigned long Data1;
@@ -23,7 +24,7 @@ namespace {
// clang-cl implements the following simpler (but largely compatible) behavior
// instead:
// * [] and __declspec uuids have the same behavior.
-// * If there are several uuids on a a class (no matter if on the same decl or
+// * If there are several uuids on a class (no matter if on the same decl or
// on several decls), it is an error if they don't match.
// * Having several uuids that match is ok.
@@ -92,4 +93,16 @@ class __declspec(uuid("000000A0-0000-0000-C000-000000000049"))
// the previous case).
[uuid("000000A0-0000-0000-C000-000000000049"),
uuid("000000A0-0000-0000-C000-000000000049")] class C10;
+
+template <const GUID* p>
+void F1() {
+ // Regression test for PR24986. The given GUID should just work as a pointer.
+ const GUID* q = p;
+}
+
+void F2() {
+ // The UUID should work for a non-type template parameter.
+ F1<&__uuidof(C1)>();
+}
+
}
diff --git a/test/SemaCXX/multistep-explicit-cast.cpp b/test/SemaCXX/multistep-explicit-cast.cpp
new file mode 100644
index 000000000000..58466791354c
--- /dev/null
+++ b/test/SemaCXX/multistep-explicit-cast.cpp
@@ -0,0 +1,155 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -ast-dump %s | FileCheck %s
+
+// We are checking that implicit casts don't get marked with 'part_of_explicit_cast',
+// while in explicit casts, the implicitly-inserted implicit casts are marked with 'part_of_explicit_cast'
+
+unsigned char implicitcast_0(unsigned int x) {
+ // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} implicitcast_0 'unsigned char (unsigned int)'{{$}}
+ // CHECK: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned char' <IntegralCast>{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned int' <LValueToRValue>{{$}}
+ // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}}
+ return x;
+}
+
+signed char implicitcast_1(unsigned int x) {
+ // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} implicitcast_1 'signed char (unsigned int)'{{$}}
+ // CHECK: ImplicitCastExpr {{.*}} <col:{{.*}}> 'signed char' <IntegralCast>{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned int' <LValueToRValue>{{$}}
+ // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}}
+ return x;
+}
+
+unsigned char implicitcast_2(signed int x) {
+ // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} implicitcast_2 'unsigned char (int)'{{$}}
+ // CHECK: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned char' <IntegralCast>{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'int' <LValueToRValue>{{$}}
+ // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}}
+ return x;
+}
+
+signed char implicitcast_3(signed int x) {
+ // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} implicitcast_3 'signed char (int)'{{$}}
+ // CHECK: ImplicitCastExpr {{.*}} <col:{{.*}}> 'signed char' <IntegralCast>{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'int' <LValueToRValue>{{$}}
+ // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}}
+ return x;
+}
+
+//----------------------------------------------------------------------------//
+
+unsigned char cstylecast_0(unsigned int x) {
+ // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cstylecast_0 'unsigned char (unsigned int)'{{$}}
+ // CHECK: CStyleCastExpr {{.*}} <col:{{.*}}> 'unsigned char' <NoOp>{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned char' <IntegralCast> part_of_explicit_cast{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned int' <LValueToRValue> part_of_explicit_cast{{$}}
+ // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}}
+ return (unsigned char)x;
+}
+
+signed char cstylecast_1(unsigned int x) {
+ // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cstylecast_1 'signed char (unsigned int)'{{$}}
+ // CHECK: CStyleCastExpr {{.*}} <col:{{.*}}> 'signed char' <NoOp>{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'signed char' <IntegralCast> part_of_explicit_cast{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned int' <LValueToRValue> part_of_explicit_cast{{$}}
+ // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}}
+ return (signed char)x;
+}
+
+unsigned char cstylecast_2(signed int x) {
+ // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cstylecast_2 'unsigned char (int)'{{$}}
+ // CHECK: CStyleCastExpr {{.*}} <col:{{.*}}> 'unsigned char' <NoOp>{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned char' <IntegralCast> part_of_explicit_cast{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'int' <LValueToRValue> part_of_explicit_cast{{$}}
+ // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}}
+ return (unsigned char)x;
+}
+
+signed char cstylecast_3(signed int x) {
+ // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cstylecast_3 'signed char (int)'{{$}}
+ // CHECK: CStyleCastExpr {{.*}} <col:{{.*}}> 'signed char' <NoOp>{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'signed char' <IntegralCast> part_of_explicit_cast{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'int' <LValueToRValue> part_of_explicit_cast{{$}}
+ // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}}
+ return (signed char)x;
+}
+
+//----------------------------------------------------------------------------//
+
+unsigned char cxxstaticcast_0(unsigned int x) {
+ // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxstaticcast_0 'unsigned char (unsigned int)'{{$}}
+ // CHECK: CXXStaticCastExpr {{.*}} <col:{{.*}}> 'unsigned char' static_cast<unsigned char> <NoOp>{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned char' <IntegralCast> part_of_explicit_cast{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned int' <LValueToRValue> part_of_explicit_cast{{$}}
+ // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}}
+ return static_cast<unsigned char>(x);
+}
+
+signed char cxxstaticcast_1(unsigned int x) {
+ // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxstaticcast_1 'signed char (unsigned int)'{{$}}
+ // CHECK: CXXStaticCastExpr {{.*}} <col:{{.*}}> 'signed char' static_cast<signed char> <NoOp>{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'signed char' <IntegralCast> part_of_explicit_cast{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned int' <LValueToRValue> part_of_explicit_cast{{$}}
+ // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}}
+ return static_cast<signed char>(x);
+}
+
+unsigned char cxxstaticcast_2(signed int x) {
+ // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxstaticcast_2 'unsigned char (int)'{{$}}
+ // CHECK: CXXStaticCastExpr {{.*}} <col:{{.*}}> 'unsigned char' static_cast<unsigned char> <NoOp>{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned char' <IntegralCast> part_of_explicit_cast{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'int' <LValueToRValue> part_of_explicit_cast{{$}}
+ // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}}
+ return static_cast<unsigned char>(x);
+}
+
+signed char cxxstaticcast_3(signed int x) {
+ // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxstaticcast_3 'signed char (int)'{{$}}
+ // CHECK: CXXStaticCastExpr {{.*}} <col:{{.*}}> 'signed char' static_cast<signed char> <NoOp>{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'signed char' <IntegralCast> part_of_explicit_cast{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'int' <LValueToRValue> part_of_explicit_cast{{$}}
+ // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}}
+ return static_cast<signed char>(x);
+}
+
+//----------------------------------------------------------------------------//
+
+using UnsignedChar = unsigned char;
+using SignedChar = signed char;
+using UnsignedInt = unsigned int;
+using SignedInt = signed int;
+
+UnsignedChar cxxfunctionalcast_0(UnsignedInt x) {
+ // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxfunctionalcast_0 'UnsignedChar (UnsignedInt)'{{$}}
+ // CHECK: CXXFunctionalCastExpr {{.*}} <col:{{.*}}> 'UnsignedChar':'unsigned char' functional cast to UnsignedChar <NoOp>{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'UnsignedChar':'unsigned char' <IntegralCast> part_of_explicit_cast{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'UnsignedInt':'unsigned int' <LValueToRValue> part_of_explicit_cast{{$}}
+ // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'UnsignedInt':'unsigned int' lvalue ParmVar {{.*}} 'x' 'UnsignedInt':'unsigned int'{{$}}
+ return UnsignedChar(x);
+}
+
+SignedChar cxxfunctionalcast_1(UnsignedInt x) {
+ // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxfunctionalcast_1 'SignedChar (UnsignedInt)'{{$}}
+ // CHECK: CXXFunctionalCastExpr {{.*}} <col:{{.*}}> 'SignedChar':'signed char' functional cast to SignedChar <NoOp>{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'SignedChar':'signed char' <IntegralCast> part_of_explicit_cast{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'UnsignedInt':'unsigned int' <LValueToRValue> part_of_explicit_cast{{$}}
+ // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'UnsignedInt':'unsigned int' lvalue ParmVar {{.*}} 'x' 'UnsignedInt':'unsigned int'{{$}}
+ return SignedChar(x);
+}
+
+UnsignedChar cxxfunctionalcast_2(SignedInt x) {
+ // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxfunctionalcast_2 'UnsignedChar (SignedInt)'{{$}}
+ // CHECK: CXXFunctionalCastExpr {{.*}} <col:{{.*}}> 'UnsignedChar':'unsigned char' functional cast to UnsignedChar <NoOp>{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'UnsignedChar':'unsigned char' <IntegralCast> part_of_explicit_cast{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'SignedInt':'int' <LValueToRValue> part_of_explicit_cast{{$}}
+ // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'SignedInt':'int' lvalue ParmVar {{.*}} 'x' 'SignedInt':'int'{{$}}
+ return UnsignedChar(x);
+}
+
+SignedChar cxxfunctionalcast_3(SignedInt x) {
+ // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxfunctionalcast_3 'SignedChar (SignedInt)'{{$}}
+ // CHECK: CXXFunctionalCastExpr {{.*}} <col:{{.*}}> 'SignedChar':'signed char' functional cast to SignedChar <NoOp>{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'SignedChar':'signed char' <IntegralCast> part_of_explicit_cast{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'SignedInt':'int' <LValueToRValue> part_of_explicit_cast{{$}}
+ // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'SignedInt':'int' lvalue ParmVar {{.*}} 'x' 'SignedInt':'int'{{$}}
+ return SignedChar(x);
+}
diff --git a/test/SemaCXX/neon-vector-types.cpp b/test/SemaCXX/neon-vector-types.cpp
index c2953d713b2a..aaf4af18e24b 100644
--- a/test/SemaCXX/neon-vector-types.cpp
+++ b/test/SemaCXX/neon-vector-types.cpp
@@ -35,7 +35,7 @@ namespace rdar11688587 {
extern float32x4_t vec;
return __extension__ ({
float32x4_t __a = (vec);
- (float32_t)__builtin_neon_vgetq_lane_f32(__a, I); // expected-error{{argument should be a value from 0 to 3}}
+ (float32_t)__builtin_neon_vgetq_lane_f32(__a, I); // expected-error-re{{argument value {{.*}} is outside the valid range}}
});
}
diff --git a/test/SemaCXX/no-rtti.cpp b/test/SemaCXX/no-rtti.cpp
index a171b3cde2c3..e0b57153c24c 100644
--- a/test/SemaCXX/no-rtti.cpp
+++ b/test/SemaCXX/no-rtti.cpp
@@ -6,7 +6,7 @@ namespace std {
void f()
{
- (void)typeid(int); // expected-error {{cannot use typeid with -fno-rtti}}
+ (void)typeid(int); // expected-error {{use of typeid requires -frtti}}
}
namespace {
@@ -20,7 +20,7 @@ struct B : public A {
}
bool isa_B(A *a) {
- return dynamic_cast<B *>(a) != 0; // expected-error {{cannot use dynamic_cast with -fno-rtti}}
+ return dynamic_cast<B *>(a) != 0; // expected-error {{use of dynamic_cast requires -frtti}}
}
void* getMostDerived(A* a) {
diff --git a/test/SemaCXX/overload-call.cpp b/test/SemaCXX/overload-call.cpp
index 0c4bba5027f7..befa927f0677 100644
--- a/test/SemaCXX/overload-call.cpp
+++ b/test/SemaCXX/overload-call.cpp
@@ -338,22 +338,23 @@ namespace PR5756 {
// Tests the exact text used to note the candidates
namespace test1 {
- template <class T> void foo(T t, unsigned N); // expected-note {{candidate function not viable: no known conversion from 'const char [6]' to 'unsigned int' for 2nd argument}}
- void foo(int n, char N); // expected-note {{candidate function not viable: no known conversion from 'const char [6]' to 'char' for 2nd argument}}
- void foo(int n, const char *s, int t); // expected-note {{candidate function not viable: requires 3 arguments, but 2 were provided}}
- void foo(int n, const char *s, int t, ...); // expected-note {{candidate function not viable: requires at least 3 arguments, but 2 were provided}}
- void foo(int n, const char *s, int t, int u = 0); // expected-note {{candidate function not viable: requires at least 3 arguments, but 2 were provided}}
-
- // PR 11857
- void foo(int n); // expected-note {{candidate function not viable: requires single argument 'n', but 2 arguments were provided}}
- void foo(unsigned n = 10); // expected-note {{candidate function not viable: allows at most single argument 'n', but 2 arguments were provided}}
- void bar(int n, int u = 0); // expected-note {{candidate function not viable: requires at least argument 'n', but no arguments were provided}}
- void baz(int n = 0, int u = 0); // expected-note {{candidate function not viable: requires at most 2 arguments, but 3 were provided}}
-
- void test() {
- foo(4, "hello"); //expected-error {{no matching function for call to 'foo'}}
- bar(); //expected-error {{no matching function for call to 'bar'}}
- baz(3, 4, 5); // expected-error {{no matching function for call to 'baz'}}
+template <class T>
+void foo(T t, unsigned N); // expected-note {{candidate function template not viable: no known conversion from 'const char [6]' to 'unsigned int' for 2nd argument}}
+void foo(int n, char N); // expected-note {{candidate function not viable: no known conversion from 'const char [6]' to 'char' for 2nd argument}}
+void foo(int n, const char *s, int t); // expected-note {{candidate function not viable: requires 3 arguments, but 2 were provided}}
+void foo(int n, const char *s, int t, ...); // expected-note {{candidate function not viable: requires at least 3 arguments, but 2 were provided}}
+void foo(int n, const char *s, int t, int u = 0); // expected-note {{candidate function not viable: requires at least 3 arguments, but 2 were provided}}
+
+// PR 11857
+void foo(int n); // expected-note {{candidate function not viable: requires single argument 'n', but 2 arguments were provided}}
+void foo(unsigned n = 10); // expected-note {{candidate function not viable: allows at most single argument 'n', but 2 arguments were provided}}
+void bar(int n, int u = 0); // expected-note {{candidate function not viable: requires at least argument 'n', but no arguments were provided}}
+void baz(int n = 0, int u = 0); // expected-note {{candidate function not viable: requires at most 2 arguments, but 3 were provided}}
+
+void test() {
+ foo(4, "hello"); //expected-error {{no matching function for call to 'foo'}}
+ bar(); //expected-error {{no matching function for call to 'bar'}}
+ baz(3, 4, 5); // expected-error {{no matching function for call to 'baz'}}
}
}
@@ -666,3 +667,24 @@ namespace ProduceNotesAfterSFINAEFailure {
void f(void*, A); // expected-note {{candidate function not viable}}
void g() { f(1, 2); } // expected-error {{no matching function}}
}
+
+namespace PR19808 {
+ struct B {
+ int i;
+ void bar();
+ };
+ struct D : public B{};
+
+ void f(bool);
+ void f(int D::*);
+ void f(void (D::*)());
+
+ void Usage() {
+ int B::*pmem;
+ void (B::*pmf)();
+
+ // These should not be ambiguous.
+ f(pmem);
+ f(pmf);
+ }
+}
diff --git a/test/SemaCXX/overload-member-call.cpp b/test/SemaCXX/overload-member-call.cpp
index 6e64b25d6b53..2d017a499ad9 100644
--- a/test/SemaCXX/overload-member-call.cpp
+++ b/test/SemaCXX/overload-member-call.cpp
@@ -70,7 +70,8 @@ void test_X2(X2 *x2p, const X2 *cx2p) {
// Tests the exact text used to note the candidates
namespace test1 {
class A {
- template <class T> void foo(T t, unsigned N); // expected-note {{candidate function not viable: no known conversion from 'const char [6]' to 'unsigned int' for 2nd argument}}
+ template <class T>
+ void foo(T t, unsigned N); // expected-note {{candidate function template not viable: no known conversion from 'const char [6]' to 'unsigned int' for 2nd argument}}
void foo(int n, char N); // expected-note {{candidate function not viable: no known conversion from 'const char [6]' to 'char' for 2nd argument}}
void foo(int n, const char *s, int t); // expected-note {{candidate function not viable: requires 3 arguments, but 2 were provided}}
void foo(int n, const char *s, int t, ...); // expected-note {{candidate function not viable: requires at least 3 arguments, but 2 were provided}}
diff --git a/test/SemaCXX/overloaded-builtin-operators-cxx17.cpp b/test/SemaCXX/overloaded-builtin-operators-cxx17.cpp
new file mode 100644
index 000000000000..05f85f88ccd8
--- /dev/null
+++ b/test/SemaCXX/overloaded-builtin-operators-cxx17.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -fsyntax-only -fshow-overloads=best -verify -triple x86_64-linux-gnu -std=c++17 %s
+
+struct BoolRef {
+ operator bool&();
+};
+
+void foo(BoolRef br) {
+ // C++ [over.built]p3: Increment for bool was removed in C++17.
+ bool b = br++; // expected-error{{cannot increment value of type 'BoolRef'}}
+} \ No newline at end of file
diff --git a/test/SemaCXX/overloaded-builtin-operators.cpp b/test/SemaCXX/overloaded-builtin-operators.cpp
index 7a99a898e209..4fa376aed036 100644
--- a/test/SemaCXX/overloaded-builtin-operators.cpp
+++ b/test/SemaCXX/overloaded-builtin-operators.cpp
@@ -62,6 +62,10 @@ void f(Short s, Long l, Enum1 e1, Enum2 e2, Xpmf pmf) {
// FIXME: should pass (void)static_cast<no&>(islong(e1 % e2));
}
+struct BoolRef {
+ operator bool&();
+};
+
struct ShortRef { // expected-note{{candidate function (the implicit copy assignment operator) not viable}}
#if __cplusplus >= 201103L // C++11 or later
// expected-note@-2 {{candidate function (the implicit move assignment operator) not viable}}
@@ -73,6 +77,10 @@ struct LongRef {
operator volatile long&();
};
+struct FloatRef {
+ operator float&();
+};
+
struct XpmfRef { // expected-note{{candidate function (the implicit copy assignment operator) not viable}}
#if __cplusplus >= 201103L // C++11 or later
// expected-note@-2 {{candidate function (the implicit move assignment operator) not viable}}
@@ -84,13 +92,19 @@ struct E2Ref {
operator E2&();
};
-void g(ShortRef sr, LongRef lr, E2Ref e2_ref, XpmfRef pmf_ref) {
+void g(BoolRef br, ShortRef sr, LongRef lr, FloatRef fr, E2Ref e2_ref, XpmfRef pmf_ref) {
// C++ [over.built]p3
short s1 = sr++;
- // C++ [over.built]p3
+ // C++ [over.built]p4
long l1 = lr--;
+ // C++ [over.built]p4
+ float f1 = fr--;
+
+ // C++ [over.built]p4
+ bool b2 = br--; // expected-error{{cannot decrement value of type 'BoolRef'}}
+
// C++ [over.built]p18
short& sr1 = (sr *= lr);
volatile long& lr1 = (lr *= sr);
diff --git a/test/SemaCXX/overloaded-name.cpp b/test/SemaCXX/overloaded-name.cpp
index 6da035440095..8f1dc2f59c67 100644
--- a/test/SemaCXX/overloaded-name.cpp
+++ b/test/SemaCXX/overloaded-name.cpp
@@ -28,3 +28,11 @@ namespace rdar9623945 {
}
};
}
+
+namespace PR38077 {
+ template <class T> void bar() {} // expected-note {{possible target for call}}
+
+ int run() {
+ decltype(bar)::does_not_exist; // expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}}
+ }
+}
diff --git a/test/SemaCXX/pr36536.cpp b/test/SemaCXX/pr36536.cpp
new file mode 100644
index 000000000000..702b9ccb707e
--- /dev/null
+++ b/test/SemaCXX/pr36536.cpp
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -std=c++11 %s -verify -fno-spell-checking
+
+// These test cases are constructed to make clang call ActOnStartOfFunctionDef
+// with nullptr.
+
+struct ImplicitDefaultCtor1 {};
+struct Foo {
+ typedef int NameInClass;
+ void f();
+};
+namespace bar {
+// FIXME: Improved our recovery to make this a redeclaration of Foo::f,
+// even though this is in the wrong namespace. That will allow name lookup to
+// find NameInClass below. Users are likely to hit this when they forget to
+// close namespaces.
+// expected-error@+1 {{cannot define or redeclare 'f' here}}
+void Foo::f() {
+ switch (0) { case 0: ImplicitDefaultCtor1 o; }
+ // expected-error@+1 {{unknown type name 'NameInClass'}}
+ NameInClass var;
+}
+} // namespace bar
+
+struct ImplicitDefaultCtor2 {};
+template <typename T> class TFoo { void f(); };
+// expected-error@+1 {{nested name specifier 'decltype(TFoo<T>())::'}}
+template <typename T> void decltype(TFoo<T>())::f() {
+ switch (0) { case 0: ImplicitDefaultCtor1 o; }
+}
+
+namespace tpl2 {
+struct ImplicitDefaultCtor3 {};
+template <class T1> class A {
+ template <class T2> class B {
+ void mf2();
+ };
+};
+template <class Y>
+template <>
+// expected-error@+1 {{nested name specifier 'A<Y>::B<double>::'}}
+void A<Y>::B<double>::mf2() {
+ switch (0) { case 0: ImplicitDefaultCtor3 o; }
+}
+}
diff --git a/test/SemaCXX/pragma-optimize.cpp b/test/SemaCXX/pragma-optimize.cpp
index cda46c552a4e..132a59985fa0 100644
--- a/test/SemaCXX/pragma-optimize.cpp
+++ b/test/SemaCXX/pragma-optimize.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -I %S/Inputs -x c++ -std=c++11 -triple x86_64-unknown-linux -emit-llvm -O2 < %s | FileCheck %s
-// RUN: %clang_cc1 -I %S/Inputs -x c++ -std=c++11 -triple x86_64-unknown-linux -emit-llvm -Os < %s | FileCheck %s
-// RUN: %clang_cc1 -I %S/Inputs -x c++ -std=c++11 -triple x86_64-unknown-linux -emit-llvm -Oz < %s | FileCheck %s
+// RUN: %clang_cc1 -I %S/Inputs -x c++ -std=c++11 -triple x86_64-unknown-linux -emit-llvm -O2 < %s | FileCheck -allow-deprecated-dag-overlap %s
+// RUN: %clang_cc1 -I %S/Inputs -x c++ -std=c++11 -triple x86_64-unknown-linux -emit-llvm -Os < %s | FileCheck -allow-deprecated-dag-overlap %s
+// RUN: %clang_cc1 -I %S/Inputs -x c++ -std=c++11 -triple x86_64-unknown-linux -emit-llvm -Oz < %s | FileCheck -allow-deprecated-dag-overlap %s
#pragma clang optimize off
diff --git a/test/SemaCXX/references.cpp b/test/SemaCXX/references.cpp
index dc59d503ba80..e32f4a8b0b08 100644
--- a/test/SemaCXX/references.cpp
+++ b/test/SemaCXX/references.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
int g(int);
void f() {
@@ -55,6 +56,24 @@ void test5() {
// const double& rcd2 = 2; // rcd2 refers to temporary with value 2.0
const volatile int cvi = 1;
const int& r = cvi; // expected-error{{binding value of type 'const volatile int' to reference to type 'const int' drops 'volatile' qualifier}}
+
+#if __cplusplus >= 201103L
+ const int& r2{cvi}; // expected-error{{binding value of type 'const volatile int' to reference to type 'const int' drops 'volatile' qualifier}}
+
+ const int a = 2;
+ int& r3{a}; // expected-error{{binding value of type 'const int' to reference to type 'int' drops 'const'}}
+
+ const int&& r4{a}; // expected-error{{rvalue reference to type 'const int' cannot bind to lvalue of type 'const int'}}
+
+ void func();
+ void func(int);
+ int &ptr1 = {func}; // expected-error{{address of overloaded function 'func' does not match required type 'int'}}
+ int &&ptr2{func}; // expected-error{{address of overloaded function 'func' does not match required type 'int'}}
+ // expected-note@-4{{candidate function}}
+ // expected-note@-4{{candidate function}}
+ // expected-note@-6{{candidate function}}
+ // expected-note@-6{{candidate function}}
+#endif
}
// C++ [dcl.init.ref]p3
@@ -154,3 +173,31 @@ namespace ExplicitRefInit {
struct A { explicit A(int); };
const A &a(0); // expected-error {{reference to type 'const ExplicitRefInit::A' could not bind to an rvalue of type 'int'}}
}
+
+namespace RefCollapseTypePrinting {
+ template<typename T> void add_lref() {
+ using X = int(T); // expected-note 4{{previous}}
+ using X = const volatile T&;
+ // expected-error@-1 {{'int &' vs 'int (int &)'}}
+ // expected-error@-2 {{'int &' vs 'int (int &&)'}}
+ // expected-error@-3 {{'const int &' vs 'int (const int &)'}}
+ // expected-error@-4 {{'const int &' vs 'int (const int &&)'}}
+ }
+ template void add_lref<int&>(); // expected-note {{instantiation of}}
+ template void add_lref<int&&>(); // expected-note {{instantiation of}}
+ template void add_lref<const int&>(); // expected-note {{instantiation of}}
+ template void add_lref<const int&&>(); // expected-note {{instantiation of}}
+
+ template<typename T> void add_rref() {
+ using X = int(T); // expected-note 4{{previous}}
+ using X = const volatile T&&;
+ // expected-error@-1 {{'int &' vs 'int (int &)'}}
+ // expected-error@-2 {{'int &&' vs 'int (int &&)'}}
+ // expected-error@-3 {{'const int &' vs 'int (const int &)'}}
+ // expected-error@-4 {{'const int &&' vs 'int (const int &&)'}}
+ }
+ template void add_rref<int&>(); // expected-note {{instantiation of}}
+ template void add_rref<int&&>(); // expected-note {{instantiation of}}
+ template void add_rref<const int&>(); // expected-note {{instantiation of}}
+ template void add_rref<const int&&>(); // expected-note {{instantiation of}}
+}
diff --git a/test/SemaCXX/return-stack-addr-2.cpp b/test/SemaCXX/return-stack-addr-2.cpp
index 47b45957e94b..e848189bde78 100644
--- a/test/SemaCXX/return-stack-addr-2.cpp
+++ b/test/SemaCXX/return-stack-addr-2.cpp
@@ -65,7 +65,7 @@ const int *int6() {
const int *int7(int x) {
const int &x2 = x; // expected-note{{binding reference variable 'x2' here}}
- return &x2; // expected-warning{{address of stack memory associated with local variable 'x' returned}}
+ return &x2; // expected-warning{{address of stack memory associated with parameter 'x' returned}}
}
const int *int8(const int &x = 5) {
diff --git a/test/SemaCXX/return-stack-addr.cpp b/test/SemaCXX/return-stack-addr.cpp
index 7670798ecb9c..08aaa749b4e3 100644
--- a/test/SemaCXX/return-stack-addr.cpp
+++ b/test/SemaCXX/return-stack-addr.cpp
@@ -63,7 +63,8 @@ int& ret_local_field_ref() {
int* ret_conditional(bool cond) {
int x = 1;
int y = 2;
- return cond ? &x : &y; // expected-warning {{address of stack memory}}
+ return cond ? &x // expected-warning {{address of stack memory associated with local variable 'x' returned}}
+ : &y; // expected-warning {{address of stack memory associated with local variable 'y' returned}}
}
int* ret_conditional_rhs(int *x, bool cond) {
@@ -156,3 +157,9 @@ void ret_from_lambda() {
(void) [&]() -> int& { int &a = b; return a; };
(void) [=]() mutable -> int& { int &a = b; return a; };
}
+
+namespace mem_ptr {
+ struct X {};
+ int X::*f();
+ int &r(X *p) { return p->*f(); }
+}
diff --git a/test/SemaCXX/rval-references.cpp b/test/SemaCXX/rval-references.cpp
index 94b09ce2cb2a..838bf484fe28 100644
--- a/test/SemaCXX/rval-references.cpp
+++ b/test/SemaCXX/rval-references.cpp
@@ -65,10 +65,9 @@ void f() {
}
int&& should_warn(int i) {
- // FIXME: The stack address return test doesn't reason about casts.
- return static_cast<int&&>(i); // xpected-warning {{returning reference to temporary}}
+ return static_cast<int&&>(i); // expected-warning {{reference to stack memory associated with parameter 'i' returned}}
}
-int&& should_not_warn(int&& i) { // But GCC 4.4 does
+int&& should_not_warn(int&& i) {
return static_cast<int&&>(i);
}
diff --git a/test/SemaCXX/scope-check.cpp b/test/SemaCXX/scope-check.cpp
index 9e0033298527..518a1e9f2606 100644
--- a/test/SemaCXX/scope-check.cpp
+++ b/test/SemaCXX/scope-check.cpp
@@ -193,7 +193,8 @@ namespace PR10462 {
bool recurse() {
MyEnum K;
- switch (K) { // expected-warning {{enumeration value 'something_invalid' not handled in switch}}
+ switch (K) { // do not warn that 'something_invalid' is not listed;
+ // 'what_am_i_thinking' might have been intended to be that case.
case something_valid:
case what_am_i_thinking: // expected-error {{use of undeclared identifier}}
int *X = 0;
diff --git a/test/SemaCXX/self-comparison.cpp b/test/SemaCXX/self-comparison.cpp
index fb15ec843061..ac129b68a67a 100644
--- a/test/SemaCXX/self-comparison.cpp
+++ b/test/SemaCXX/self-comparison.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++2a
int foo(int x) {
return x == x; // expected-warning {{self-comparison always evaluates to true}}
@@ -21,3 +21,22 @@ struct A {
return a == c; // expected-warning {{array comparison always evaluates to false}}
}
};
+
+namespace NA { extern "C" int x[3]; }
+namespace NB { extern "C" int x[3]; }
+bool k = NA::x == NB::x; // expected-warning {{self-comparison always evaluates to true}}
+
+template<typename T> struct Y { static inline int n; };
+bool f() {
+ return
+ Y<int>::n == Y<int>::n || // expected-warning {{self-comparison always evaluates to true}}
+ Y<void>::n == Y<int>::n;
+}
+template<typename T, typename U>
+bool g() {
+ // FIXME: Ideally we'd produce a self-comparison warning on the first of these.
+ return
+ Y<T>::n == Y<T>::n ||
+ Y<T>::n == Y<U>::n;
+}
+template bool g<int, int>(); // should not produce any warnings
diff --git a/test/SemaCXX/sourceranges.cpp b/test/SemaCXX/sourceranges.cpp
index 287925f7ffd7..58772a063915 100644
--- a/test/SemaCXX/sourceranges.cpp
+++ b/test/SemaCXX/sourceranges.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -triple i686-mingw32 -ast-dump %s | FileCheck %s
+// RUN: %clang_cc1 -triple i686-mingw32 -std=c++1z -ast-dump %s | FileCheck %s -check-prefix=CHECK-1Z
template<class T>
class P {
@@ -12,7 +13,7 @@ enum B {};
typedef int C;
}
-// CHECK: VarDecl {{0x[0-9a-fA-F]+}} <line:16:1, col:36> col:15 ImplicitConstrArray 'foo::A [2]'
+// CHECK: VarDecl {{0x[0-9a-fA-F]+}} <line:[[@LINE+1]]:1, col:36> col:15 ImplicitConstrArray 'foo::A [2]'
static foo::A ImplicitConstrArray[2];
int main() {
@@ -50,3 +51,89 @@ void construct() {
D d = D(12);
// CHECK: CXXConstructExpr {{0x[0-9a-fA-F]+}} <col:9, col:13> 'D' 'void (int){{( __attribute__\(\(thiscall\)\))?}}'
}
+
+void abort() __attribute__((noreturn));
+
+namespace std {
+typedef decltype(sizeof(int)) size_t;
+
+template <typename E> struct initializer_list {
+ const E *p;
+ size_t n;
+ initializer_list(const E *p, size_t n) : p(p), n(n) {}
+};
+
+template <typename F, typename S> struct pair {
+ F f;
+ S s;
+ pair(const F &f, const S &s) : f(f), s(s) {}
+};
+
+struct string {
+ const char *str;
+ string() { abort(); }
+ string(const char *S) : str(S) {}
+ ~string() { abort(); }
+};
+
+template<typename K, typename V>
+struct map {
+ using T = pair<K, V>;
+ map(initializer_list<T> i, const string &s = string()) {}
+ ~map() { abort(); }
+};
+
+}; // namespace std
+
+#if __cplusplus >= 201703L
+// CHECK-1Z: FunctionDecl {{.*}} construct_with_init_list
+std::map<int, int> construct_with_init_list() {
+ // CHECK-1Z-NEXT: CompoundStmt
+ // CHECK-1Z-NEXT: ReturnStmt {{.*}} <line:[[@LINE+5]]:3, col:35
+ // CHECK-1Z-NEXT: ExprWithCleanups {{.*}} <col:10, col:35
+ // CHECK-1Z-NEXT: CXXBindTemporaryExpr {{.*}} <col:10, col:35
+ // CHECK-1Z-NEXT: CXXTemporaryObjectExpr {{.*}} <col:10, col:35
+ // CHECK-1Z-NEXT: CXXStdInitializerListExpr {{.*}} <col:28, col:35
+ return std::map<int, int>{{0, 0}};
+}
+
+// CHECK-1Z: NamespaceDecl {{.*}} in_class_init
+namespace in_class_init {
+ struct A {};
+
+ // CHECK-1Z: CXXRecordDecl {{.*}} struct B definition
+ struct B {
+ // CHECK-1Z: FieldDecl {{.*}} a 'in_class_init::A'
+ // CHECK-1Z-NEXT: InitListExpr {{.*}} <col:11, col:12
+ A a = {};
+ };
+}
+
+// CHECK-1Z: NamespaceDecl {{.*}} delegating_constructor_init
+namespace delegating_constructor_init {
+ struct A {};
+
+ struct B : A {
+ A a;
+ B(A a) : a(a) {}
+ };
+
+ // CHECK-1Z: CXXRecordDecl {{.*}} struct C definition
+ struct C : B {
+ // CHECK-1Z: CXXConstructorDecl {{.*}} C
+ // CHECK-1Z-NEXT: CXXCtorInitializer 'delegating_constructor_init::B'
+ // CHECK-1Z-NEXT: CXXConstructExpr {{.*}} <col:11, col:15
+ // CHECK-1Z-NEXT: InitListExpr {{.*}} <col:13, col:14
+ C() : B({}) {};
+ };
+}
+
+// CHECK-1Z: NamespaceDecl {{.*}} new_init
+namespace new_init {
+ void A() {
+ // CHECK-1Z: CXXNewExpr {{.*}} <line:[[@LINE+2]]:5, col:14
+ // CHECK-1Z-NEXT: InitListExpr {{.*}} <col:12, col:14
+ new int{0};
+ }
+}
+#endif
diff --git a/test/SemaCXX/std-compare-cxx2a.cpp b/test/SemaCXX/std-compare-cxx2a.cpp
new file mode 100644
index 000000000000..6746fb480e62
--- /dev/null
+++ b/test/SemaCXX/std-compare-cxx2a.cpp
@@ -0,0 +1,65 @@
+// Test diagnostics for ill-formed STL <compare> headers.
+
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -fcxx-exceptions -fsyntax-only -pedantic -verify -Wsign-compare -std=c++2a %s
+
+void compare_not_found_test() {
+ // expected-error@+1 {{cannot deduce return type of 'operator<=>' because type 'std::partial_ordering' was not found; include <compare>}}
+ (void)(0.0 <=> 42.123);
+}
+
+namespace std {
+inline namespace __1 {
+struct partial_ordering; // expected-note {{forward declaration}}
+}
+} // namespace std
+
+auto compare_incomplete_test() {
+ // expected-error@+1 {{incomplete type 'std::partial_ordering' where a complete type is required}}
+ return (-1.2 <=> 123.0);
+}
+
+namespace std {
+inline namespace __1 {
+struct partial_ordering {
+ unsigned value;
+};
+} // namespace __1
+} // namespace std
+
+auto missing_member_test() {
+ // expected-error@+1 {{standard library implementation of 'std::partial_ordering' is not supported; member 'equivalent' is missing}}
+ return (1.0 <=> 1.0);
+}
+
+namespace std {
+inline namespace __1 {
+struct strong_ordering {
+ long long value;
+ static const strong_ordering equivalent; // expected-note {{declared here}}
+};
+} // namespace __1
+} // namespace std
+
+auto test_non_constexpr_var() {
+ // expected-error@+1 {{standard library implementation of 'std::strong_ordering' is not supported; member 'equivalent' does not have expected form}}
+ return (1 <=> 0);
+}
+
+namespace std {
+inline namespace __1 {
+struct strong_equality {
+ char value = 0;
+ constexpr strong_equality() = default;
+ // non-trivial
+ constexpr strong_equality(strong_equality const &other) : value(other.value) {}
+};
+} // namespace __1
+} // namespace std
+
+struct Class {};
+using MemPtr = void (Class::*)(int);
+
+auto test_non_trivial(MemPtr LHS, MemPtr RHS) {
+ // expected-error@+1 {{standard library implementation of 'std::strong_equality' is not supported; the type is not trivially copyable}}
+ return LHS <=> RHS;
+}
diff --git a/test/SemaCXX/type-attrs.cpp b/test/SemaCXX/type-attrs.cpp
new file mode 100644
index 000000000000..ae77df614ea8
--- /dev/null
+++ b/test/SemaCXX/type-attrs.cpp
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -triple x86_64-pc-win32 -Wgcc-compat -std=c++11 -verify %s
+
+void f() [[gnu::cdecl]] {} // expected-warning {{GCC does not allow the 'cdecl' attribute to be written on a type}}
+void g() [[gnu::stdcall]] {} // expected-warning {{GCC does not allow the 'stdcall' attribute to be written on a type}}
+void i() [[gnu::fastcall]] {} // expected-warning {{GCC does not allow the 'fastcall' attribute to be written on a type}}
diff --git a/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp
index b334e507554f..1ab35dfc1a46 100644
--- a/test/SemaCXX/type-traits.cpp
+++ b/test/SemaCXX/type-traits.cpp
@@ -262,6 +262,7 @@ void is_pod()
typedef Empty EmptyAr[10];
struct Bit0 { int : 0; };
struct Bit0Cons { int : 0; Bit0Cons(); };
+struct AnonBitOnly { int : 3; };
struct BitOnly { int x : 3; };
struct DerivesVirt : virtual POD {};
@@ -287,6 +288,7 @@ void is_empty()
{ int arr[F(__is_empty(EmptyAr))]; }
{ int arr[F(__is_empty(HasRef))]; }
{ int arr[F(__is_empty(HasVirt))]; }
+ { int arr[F(__is_empty(AnonBitOnly))]; }
{ int arr[F(__is_empty(BitOnly))]; }
{ int arr[F(__is_empty(void))]; }
{ int arr[F(__is_empty(IntArNB))]; }
@@ -1353,6 +1355,59 @@ void is_standard_layout()
int t43[F(__is_standard_layout(AnIncompleteType[1]))]; // expected-error {{incomplete type}}
int t44[F(__is_standard_layout(void))];
int t45[F(__is_standard_layout(const volatile void))];
+
+ struct HasAnonEmptyBitfield { int : 0; };
+ struct HasAnonBitfield { int : 4; };
+ struct DerivesFromBitfield : HasAnonBitfield {};
+ struct DerivesFromBitfieldWithBitfield : HasAnonBitfield { int : 5; };
+ struct DerivesFromBitfieldTwice : DerivesFromBitfield, HasAnonEmptyBitfield {};
+
+ int t50[T(__is_standard_layout(HasAnonEmptyBitfield))];
+ int t51[T(__is_standard_layout(HasAnonBitfield))];
+ int t52[T(__is_standard_layout(DerivesFromBitfield))];
+ int t53[F(__is_standard_layout(DerivesFromBitfieldWithBitfield))];
+ int t54[F(__is_standard_layout(DerivesFromBitfieldTwice))];
+
+ struct Empty {};
+ struct HasEmptyBase : Empty {};
+ struct HoldsEmptyBase { Empty e; };
+ struct HasRepeatedEmptyBase : Empty, HasEmptyBase {}; // expected-warning {{inaccessible}}
+ struct HasEmptyBaseAsMember : Empty { Empty e; };
+ struct HasEmptyBaseAsSubobjectOfMember1 : Empty { HoldsEmptyBase e; };
+ struct HasEmptyBaseAsSubobjectOfMember2 : Empty { HasEmptyBase e; };
+ struct HasEmptyBaseAsSubobjectOfMember3 : Empty { HoldsEmptyBase e[2]; };
+ struct HasEmptyIndirectBaseAsMember : HasEmptyBase { Empty e; };
+ struct HasEmptyIndirectBaseAsSecondMember : HasEmptyBase { int n; Empty e; };
+ struct HasEmptyIndirectBaseAfterBitfield : HasEmptyBase { int : 4; Empty e; };
+
+ int t60[T(__is_standard_layout(Empty))];
+ int t61[T(__is_standard_layout(HasEmptyBase))];
+ int t62[F(__is_standard_layout(HasRepeatedEmptyBase))];
+ int t63[F(__is_standard_layout(HasEmptyBaseAsMember))];
+ int t64[F(__is_standard_layout(HasEmptyBaseAsSubobjectOfMember1))];
+ int t65[T(__is_standard_layout(HasEmptyBaseAsSubobjectOfMember2))]; // FIXME: standard bug?
+ int t66[F(__is_standard_layout(HasEmptyBaseAsSubobjectOfMember3))];
+ int t67[F(__is_standard_layout(HasEmptyIndirectBaseAsMember))];
+ int t68[T(__is_standard_layout(HasEmptyIndirectBaseAsSecondMember))];
+ int t69[F(__is_standard_layout(HasEmptyIndirectBaseAfterBitfield))]; // FIXME: standard bug?
+
+ struct StructWithEmptyFields {
+ int n;
+ HoldsEmptyBase e[3];
+ };
+ union UnionWithEmptyFields {
+ int n;
+ HoldsEmptyBase e[3];
+ };
+ struct HasEmptyIndirectBaseAsSecondStructMember : HasEmptyBase {
+ StructWithEmptyFields u;
+ };
+ struct HasEmptyIndirectBaseAsSecondUnionMember : HasEmptyBase {
+ UnionWithEmptyFields u;
+ };
+
+ int t70[T(__is_standard_layout(HasEmptyIndirectBaseAsSecondStructMember))];
+ int t71[F(__is_standard_layout(HasEmptyIndirectBaseAsSecondUnionMember))];
}
void is_signed()
@@ -2225,6 +2280,7 @@ void constructible_checks() {
// PR25513
{ int arr[F(__is_constructible(int(int)))]; }
+ { int arr[T(__is_constructible(int const &, long))]; }
{ int arr[T(__is_constructible(ACompleteType))]; }
{ int arr[T(__is_nothrow_constructible(ACompleteType))]; }
@@ -2275,6 +2331,47 @@ void is_trivially_constructible_test() {
{ int arr[F(__is_trivially_constructible(const volatile void))]; }
}
+template <class T, class RefType = T &>
+struct ConvertsToRef {
+ operator RefType() const { return static_cast<RefType>(obj); }
+ mutable T obj = 42;
+};
+
+void reference_binds_to_temporary_checks() {
+ { int arr[F((__reference_binds_to_temporary(int &, int &)))]; }
+ { int arr[F((__reference_binds_to_temporary(int &, int &&)))]; }
+
+ { int arr[F((__reference_binds_to_temporary(int const &, int &)))]; }
+ { int arr[F((__reference_binds_to_temporary(int const &, int const &)))]; }
+ { int arr[F((__reference_binds_to_temporary(int const &, int &&)))]; }
+
+ { int arr[F((__reference_binds_to_temporary(int &, long &)))]; } // doesn't construct
+ { int arr[T((__reference_binds_to_temporary(int const &, long &)))]; }
+ { int arr[T((__reference_binds_to_temporary(int const &, long &&)))]; }
+ { int arr[T((__reference_binds_to_temporary(int &&, long &)))]; }
+
+ using LRef = ConvertsToRef<int, int &>;
+ using RRef = ConvertsToRef<int, int &&>;
+ using CLRef = ConvertsToRef<int, const int &>;
+ using LongRef = ConvertsToRef<long, long &>;
+ { int arr[T((__is_constructible(int &, LRef)))]; }
+ { int arr[F((__reference_binds_to_temporary(int &, LRef)))]; }
+
+ { int arr[T((__is_constructible(int &&, RRef)))]; }
+ { int arr[F((__reference_binds_to_temporary(int &&, RRef)))]; }
+
+ { int arr[T((__is_constructible(int const &, CLRef)))]; }
+ { int arr[F((__reference_binds_to_temporary(int &&, CLRef)))]; }
+
+ { int arr[T((__is_constructible(int const &, LongRef)))]; }
+ { int arr[T((__reference_binds_to_temporary(int const &, LongRef)))]; }
+
+ // Test that it doesn't accept non-reference types as input.
+ { int arr[F((__reference_binds_to_temporary(int, long)))]; }
+
+ { int arr[T((__reference_binds_to_temporary(const int &, long)))]; }
+}
+
void array_rank() {
int t01[T(__array_rank(IntAr) == 1)];
int t02[T(__array_rank(ConstIntArAr) == 2)];
@@ -2440,7 +2537,7 @@ struct VirtuallyInheritsFromNoPadding : virtual NoPadding {
int d;
};
-static_assert(!has_unique_object_representations<VirtuallyInheritsFromNoPadding>::value, "No virtual inheritence");
+static_assert(!has_unique_object_representations<VirtuallyInheritsFromNoPadding>::value, "No virtual inheritance");
struct Padding {
char a;
@@ -2524,6 +2621,7 @@ static_assert(!has_unique_object_representations<const int &>::value, "No refere
static_assert(!has_unique_object_representations<volatile int &>::value, "No references!");
static_assert(!has_unique_object_representations<const volatile int &>::value, "No references!");
static_assert(!has_unique_object_representations<Empty>::value, "No empty types!");
+static_assert(!has_unique_object_representations<EmptyUnion>::value, "No empty types!");
class Compressed : Empty {
int x;
diff --git a/test/SemaCXX/typeid-ref.cpp b/test/SemaCXX/typeid-ref.cpp
index 7e5dbdd85ade..48c9fc285f78 100644
--- a/test/SemaCXX/typeid-ref.cpp
+++ b/test/SemaCXX/typeid-ref.cpp
@@ -6,7 +6,7 @@ namespace std {
struct X { };
void f() {
- // CHECK: @_ZTS1X = linkonce_odr constant
- // CHECK: @_ZTI1X = linkonce_odr constant
+ // CHECK: @_ZTS1X = linkonce_odr {{(dso_local )?}}constant
+ // CHECK: @_ZTI1X = linkonce_odr {{(dso_local )?}}constant
(void)typeid(X&);
}
diff --git a/test/SemaCXX/typo-correction-cxx17.cpp b/test/SemaCXX/typo-correction-cxx17.cpp
new file mode 100644
index 000000000000..f13749975342
--- /dev/null
+++ b/test/SemaCXX/typo-correction-cxx17.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -std=c++1z -fsyntax-only -verify %s
+
+namespace decomp_decl {
+void f() {
+ auto [this_is_a_typo] = this_is_a_typp(); // expected-error{{use of undeclared identifier 'this_is_a_typp'}}
+}
+}
diff --git a/test/SemaCXX/typo-correction.cpp b/test/SemaCXX/typo-correction.cpp
index 2d78f06c5d33..0b520e0af1d5 100644
--- a/test/SemaCXX/typo-correction.cpp
+++ b/test/SemaCXX/typo-correction.cpp
@@ -411,7 +411,7 @@ public:
void testAccess() {
Figure obj;
- switch (obj.type()) { // expected-warning {{enumeration values 'SQUARE', 'TRIANGLE', and 'CIRCLE' not handled in switch}}
+ switch (obj.type()) {
case SQUARE: // expected-error-re {{use of undeclared identifier 'SQUARE'{{$}}}}
case TRIANGLE: // expected-error-re {{use of undeclared identifier 'TRIANGLE'{{$}}}}
case CIRCE: // expected-error-re {{use of undeclared identifier 'CIRCE'{{$}}}}
@@ -647,7 +647,7 @@ namespace testArraySubscriptIndex {
namespace crash_has_include {
int has_include(int); // expected-note {{'has_include' declared here}}
-// expected-error@+1 {{__has_include must be used within a preprocessing directive}}
+// expected-error@+1 {{'__has_include' must be used within a preprocessing directive}}
int foo = __has_include(42); // expected-error {{use of undeclared identifier '__has_include'; did you mean 'has_include'?}}
}
diff --git a/test/SemaCXX/uninitialized.cpp b/test/SemaCXX/uninitialized.cpp
index 92f1c1472caf..f620e1014c34 100644
--- a/test/SemaCXX/uninitialized.cpp
+++ b/test/SemaCXX/uninitialized.cpp
@@ -26,7 +26,7 @@ int c = (c + c); // expected-warning 2 {{variable 'c' is uninitialized when used
int e = static_cast<long>(e) + 1; // expected-warning {{variable 'e' is uninitialized when used within its own initialization}}
int f = foo(f); // expected-warning {{variable 'f' is uninitialized when used within its own initialization}}
-// Thes don't warn as they don't require the value.
+// These don't warn as they don't require the value.
int g = sizeof(g);
void* ptr = &ptr;
int h = bar(&h);
@@ -60,7 +60,7 @@ void test_stuff () {
int e = static_cast<long>(e) + 1; // expected-warning {{variable 'e' is uninitialized when used within its own initialization}}
int f = foo(f); // expected-warning {{variable 'f' is uninitialized when used within its own initialization}}
- // Thes don't warn as they don't require the value.
+ // These don't warn as they don't require the value.
int g = sizeof(g);
void* ptr = &ptr;
int h = bar(&h);
@@ -94,7 +94,7 @@ void test_stuff () {
int e = static_cast<long>(e) + 1; // expected-warning {{variable 'e' is uninitialized when used within its own initialization}}
int f = foo(f); // expected-warning {{variable 'f' is uninitialized when used within its own initialization}}
- // Thes don't warn as they don't require the value.
+ // These don't warn as they don't require the value.
int g = sizeof(g);
void* ptr = &ptr;
int h = bar(&h);
@@ -704,7 +704,7 @@ namespace statics {
static int e = static_cast<long>(e) + 1; // expected-warning {{variable 'e' is uninitialized when used within its own initialization}}
static int f = foo(f); // expected-warning {{variable 'f' is uninitialized when used within its own initialization}}
- // Thes don't warn as they don't require the value.
+ // These don't warn as they don't require the value.
static int g = sizeof(g);
int gg = g; // Silence unneeded warning
static void* ptr = &ptr;
@@ -740,7 +740,7 @@ namespace statics {
static int e = static_cast<long>(e) + 1; // expected-warning {{static variable 'e' is suspiciously used within its own initialization}}
static int f = foo(f); // expected-warning {{static variable 'f' is suspiciously used within its own initialization}}
- // Thes don't warn as they don't require the value.
+ // These don't warn as they don't require the value.
static int g = sizeof(g);
static void* ptr = &ptr;
static int h = bar(&h);
@@ -774,7 +774,7 @@ namespace statics {
static int e = static_cast<long>(e) + 1; // expected-warning {{static variable 'e' is suspiciously used within its own initialization}}
static int f = foo(f); // expected-warning {{static variable 'f' is suspiciously used within its own initialization}}
- // Thes don't warn as they don't require the value.
+ // These don't warn as they don't require the value.
static int g = sizeof(g);
static void* ptr = &ptr;
static int h = bar(&h);
diff --git a/test/SemaCXX/vector.cpp b/test/SemaCXX/vector.cpp
index 9b272444a23f..56a8a6db5b68 100644
--- a/test/SemaCXX/vector.cpp
+++ b/test/SemaCXX/vector.cpp
@@ -190,7 +190,7 @@ void test_implicit_conversions(bool Cond, char16 c16, longlong16 ll16,
(void)(Cond? to_c16 : to_c16e);
(void)(Cond? to_ll16e : to_ll16);
- // These 2 are convertable with -flax-vector-conversions (default)
+ // These 2 are convertible with -flax-vector-conversions (default)
(void)(Cond? to_c16 : to_ll16);
(void)(Cond? to_c16e : to_ll16e);
}
@@ -291,3 +291,46 @@ const int &reference_to_vec_element = vi4(1).x;
// PR12649
typedef bool bad __attribute__((__vector_size__(16))); // expected-error {{invalid vector element type 'bool'}}
+
+namespace Templates {
+template <typename Elt, unsigned Size>
+struct TemplateVectorType {
+ typedef Elt __attribute__((__vector_size__(Size))) type;
+};
+
+template <int N, typename T>
+struct PR15730 {
+ typedef T __attribute__((vector_size(N * sizeof(T)))) type;
+ typedef T __attribute__((vector_size(8192))) type2;
+ typedef T __attribute__((vector_size(3))) type3;
+};
+
+void Init() {
+ const TemplateVectorType<float, 32>::type Works = {};
+ const TemplateVectorType<int, 32>::type Works2 = {};
+ // expected-error@298 {{invalid vector element type 'bool'}}
+ // expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType<bool, 32>' requested here}}
+ const TemplateVectorType<bool, 32>::type NoBool;
+ // expected-error@298 {{invalid vector element type 'int __attribute__((ext_vector_type(4)))' (vector of 4 'int' values)}}
+ // expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType<int __attribute__((ext_vector_type(4))), 32>' requested here}}
+ const TemplateVectorType<vi4, 32>::type NoComplex;
+ // expected-error@298 {{vector size not an integral multiple of component size}}
+ // expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType<int, 33>' requested here}}
+ const TemplateVectorType<int, 33>::type BadSize;
+ // expected-error@298 {{vector size too large}}
+ // expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType<int, 8192>' requested here}}
+ const TemplateVectorType<int, 8192>::type TooLarge;
+ // expected-error@298 {{zero vector size}}
+ // expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType<int, 0>' requested here}}
+ const TemplateVectorType<int, 0>::type Zero;
+
+ // expected-error@304 {{vector size too large}}
+ // expected-error@305 {{vector size not an integral multiple of component size}}
+ // expected-note@+1 {{in instantiation of template class 'Templates::PR15730<8, int>' requested here}}
+ const PR15730<8, int>::type PR15730_1 = {};
+ // expected-error@304 {{vector size too large}}
+ // expected-note@+1 {{in instantiation of template class 'Templates::PR15730<8, char>' requested here}}
+ const PR15730<8, char>::type2 PR15730_2 = {};
+}
+
+} // namespace Templates
diff --git a/test/SemaCXX/warn-dangling-field.cpp b/test/SemaCXX/warn-dangling-field.cpp
index eb65bd06692c..578f3df654d2 100644
--- a/test/SemaCXX/warn-dangling-field.cpp
+++ b/test/SemaCXX/warn-dangling-field.cpp
@@ -20,7 +20,7 @@ struct S {
struct S2 {
const X &x; // expected-note {{reference member declared here}}
- S2(int i) : x(i) {} // expected-warning {{binding reference member 'x' to a temporary}}
+ S2(int i) : x(i) {} // expected-error {{member 'x' binds to a temporary}}
};
struct S3 {
@@ -43,9 +43,14 @@ S5 s5 = { 0 }; // ok, lifetime-extended
struct S6 {
S5 s5; // expected-note {{here}}
- S6() : s5 { 0 } {} // expected-warning {{binding reference subobject of member 's5' to a temporary}}
+ S6() : s5 { 0 } {} // expected-error {{reference subobject of member 's5' binds to a temporary}}
};
struct S7 : S5 {
- S7() : S5 { 0 } {} // expected-warning {{binding reference member 'x' to a temporary}}
+ S7() : S5 { 0 } {} // expected-error {{reference member 'x' binds to a temporary}}
+};
+
+struct S8 {
+ int *p;
+ S8(int *a) : p(&a[0]) {}
};
diff --git a/test/SemaCXX/warn-dangling-local.cpp b/test/SemaCXX/warn-dangling-local.cpp
new file mode 100644
index 000000000000..19a722f84d16
--- /dev/null
+++ b/test/SemaCXX/warn-dangling-local.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -verify -std=c++11 %s
+
+using T = int[];
+
+void f() {
+ int *p = &(int&)(int&&)0; // expected-warning {{temporary whose address is used as value of local variable 'p' will be destroyed at the end of the full-expression}}
+
+ int *q = (int *const &)T{1, 2, 3}; // expected-warning {{temporary whose address is used as value of local variable 'q' will be destroyed at the end of the full-expression}}
+
+ // FIXME: We don't warn here because the 'int*' temporary is not const, but
+ // it also can't have actually changed since it was created, so we could
+ // still warn.
+ int *r = (int *&&)T{1, 2, 3};
+
+ // FIXME: The wording of this warning is not quite right. There are two
+ // temporaries here: an 'int* const' temporary that points to the array, and
+ // is lifetime-extended, and an array temporary that the pointer temporary
+ // points to, which doesn't live long enough.
+ int *const &s = (int *const &)T{1, 2, 3}; // expected-warning {{temporary bound to local reference 's' will be destroyed at the end of the full-expression}}
+}
diff --git a/test/SemaCXX/warn-float-conversion.cpp b/test/SemaCXX/warn-float-conversion.cpp
index fc221893aeee..a3d178622c7d 100644
--- a/test/SemaCXX/warn-float-conversion.cpp
+++ b/test/SemaCXX/warn-float-conversion.cpp
@@ -63,6 +63,9 @@ void TestConstantFloat() {
int b3 = five / 1.0; //expected-warning{{conversion}}
int b4 = five / 2.0; //expected-warning{{conversion}}
+
+ int f = 2147483646.5 + 1; // expected-warning{{implicit conversion from 'double' to 'int' changes value from 2147483647.5 to 2147483647}}
+ unsigned g = -.5 + .01; // expected-warning{{implicit conversion from 'double' to 'unsigned int' changes non-zero value from -0.49 to 0}}
}
#endif // FLOAT_CONVERSION
@@ -81,9 +84,43 @@ void TestOverflow() {
char b = -500.0; // caught by -Wliteral-conversion
const float LargeNumber = 1024;
- char c = LargeNumber; // expected-warning{{implicit conversion of out of range value from 'const float' to 'char' changes value from 1024 to 127}}
- char d = 400.0 + 400.0; // expected-warning{{implicit conversion of out of range value from 'double' to 'char' changes value from 800 to 127}}
+ char c = LargeNumber; // expected-warning{{implicit conversion of out of range value from 'const float' to 'char' is undefined}}
+ char d = 400.0 + 400.0; // expected-warning{{implicit conversion of out of range value from 'double' to 'char' is undefined}}
+
+ char e = 1.0 / 0.0; // expected-warning{{implicit conversion of out of range value from 'double' to 'char' is undefined}}
+}
+
+
+template <typename T>
+class Check {
+ public:
+ static constexpr bool Safe();
+};
+
+template<>
+constexpr bool Check<char>::Safe() { return false; }
- char e = 1.0 / 0.0; // expected-warning{{implicit conversion of out of range value from 'double' to 'char' changes value from +Inf to 127}}
+template<>
+constexpr bool Check<float>::Safe() { return true; }
+
+template <typename T>
+T run1(T t) {
+ const float ret = 800;
+ return ret; // expected-warning {{implicit conversion of out of range value from 'const float' to 'char' is undefined}}
+}
+
+template <typename T>
+T run2(T t) {
+ const float ret = 800;
+ if (Check<T>::Safe())
+ return ret;
+ else
+ return t;
}
+
+void test() {
+ float a = run1(a) + run2(a);
+ char b = run1(b) + run2(b); // expected-note {{in instantiation of function template specialization 'run1<char>' requested here}}
+}
+
#endif // OVERFLOW
diff --git a/test/SemaCXX/warn-infinite-recursion.cpp b/test/SemaCXX/warn-infinite-recursion.cpp
index e1b7c5412e1f..bbeff92a657b 100644
--- a/test/SemaCXX/warn-infinite-recursion.cpp
+++ b/test/SemaCXX/warn-infinite-recursion.cpp
@@ -29,8 +29,7 @@ void f();
void e() { f(); }
void f() { e(); }
-// Don't warn on infinite loops
-void g() {
+void g() { // expected-warning{{call itself}}
while (true)
g();
@@ -54,6 +53,19 @@ int j() { // expected-warning{{call itself}}
return 5 + j();
}
+void k() { // expected-warning{{call itself}}
+ while(true) {
+ k();
+ }
+}
+
+// Don't warn on infinite loops
+void l() {
+ while (true) {}
+
+ l();
+}
+
class S {
static void a();
void b();
diff --git a/test/SemaCXX/warn-literal-conversion.cpp b/test/SemaCXX/warn-literal-conversion.cpp
index 875aa1dec5ef..b607bd8c76c4 100644
--- a/test/SemaCXX/warn-literal-conversion.cpp
+++ b/test/SemaCXX/warn-literal-conversion.cpp
@@ -48,4 +48,15 @@ void test1() {
// values.
bool b3 = 0.0f;
bool b4 = 0.0;
+
+ // These all warn because they overflow the target type.
+ short s = 32768.0; // expected-warning{{implicit conversion of out of range value from 'double' to 'short' is undefined}}
+ unsigned short us = 65536.0; // expected-warning{{implicit conversion of out of range value from 'double' to 'unsigned short' is undefined}}
+
+ short s2 = -32769.0; // expected-warning{{implicit conversion of out of range value from 'double' to 'short' is undefined}}
+ unsigned short us2 = -65537.0; // expected-warning{{implicit conversion of out of range value from 'double' to 'unsigned short' is undefined}}
}
+
+int a() { return 2147483647.5; } // expected-warning{{implicit conversion from 'double' to 'int' changes value from 2147483647.5 to 2147483647}}
+unsigned b() { return -.5; } // expected-warning{{implicit conversion from 'double' to 'unsigned int' changes value from -0.5 to 0}}
+
diff --git a/test/SemaCXX/warn-missing-variable-declarations.cpp b/test/SemaCXX/warn-missing-variable-declarations.cpp
index 5b882845f3c6..5b71f38c811f 100644
--- a/test/SemaCXX/warn-missing-variable-declarations.cpp
+++ b/test/SemaCXX/warn-missing-variable-declarations.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang -Wmissing-variable-declarations -fsyntax-only -Xclang -verify %s
+// RUN: %clang -Wmissing-variable-declarations -fsyntax-only -Xclang -verify -std=c++17 %s
// Variable declarations that should trigger a warning.
int vbad1; // expected-warning{{no previous extern declaration for non-static variable 'vbad1'}}
@@ -52,3 +52,24 @@ class C {
namespace {
int vgood4;
}
+
+inline int inline_var = 0;
+const int const_var = 0;
+constexpr int constexpr_var = 0;
+inline constexpr int inline_constexpr_var = 0;
+extern const int extern_const_var = 0; // expected-warning {{no previous extern declaration}}
+extern constexpr int extern_constexpr_var = 0; // expected-warning {{no previous extern declaration}}
+
+template<typename> int var_template = 0;
+template<typename> constexpr int const_var_template = 0;
+template<typename> static int static_var_template = 0;
+
+template int var_template<int[1]>;
+int use_var_template() { return var_template<int[2]>; }
+template int var_template<int[3]>;
+extern template int var_template<int[4]>;
+template<> int var_template<int[5]>; // expected-warning {{no previous extern declaration}}
+
+// FIXME: We give this specialization internal linkage rather than inheriting
+// the linkage from the template! We should not warn here.
+template<> int static_var_template<int[5]>; // expected-warning {{no previous extern declaration}}
diff --git a/test/SemaCXX/warn-return-std-move.cpp b/test/SemaCXX/warn-return-std-move.cpp
new file mode 100644
index 000000000000..48542f467f21
--- /dev/null
+++ b/test/SemaCXX/warn-return-std-move.cpp
@@ -0,0 +1,334 @@
+// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -Wreturn-std-move -Wreturn-std-move-in-c++11 -std=c++14 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -Wreturn-std-move -Wreturn-std-move-in-c++11 -std=c++14 -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+
+// definitions for std::move
+namespace std {
+inline namespace foo {
+template <class T> struct remove_reference { typedef T type; };
+template <class T> struct remove_reference<T&> { typedef T type; };
+template <class T> struct remove_reference<T&&> { typedef T type; };
+
+template <class T> typename remove_reference<T>::type &&move(T &&t);
+} // namespace foo
+} // namespace std
+
+struct Instrument {
+ Instrument() {}
+ Instrument(Instrument&&) { /* MOVE */ }
+ Instrument(const Instrument&) { /* COPY */ }
+};
+struct ConvertFromBase { Instrument i; };
+struct ConvertFromDerived { Instrument i; };
+struct Base {
+ Instrument i;
+ operator ConvertFromBase() const& { return ConvertFromBase{i}; }
+ operator ConvertFromBase() && { return ConvertFromBase{std::move(i)}; }
+};
+struct Derived : public Base {
+ operator ConvertFromDerived() const& { return ConvertFromDerived{i}; }
+ operator ConvertFromDerived() && { return ConvertFromDerived{std::move(i)}; }
+};
+struct ConstructFromBase {
+ Instrument i;
+ ConstructFromBase(const Base& b): i(b.i) {}
+ ConstructFromBase(Base&& b): i(std::move(b.i)) {}
+};
+struct ConstructFromDerived {
+ Instrument i;
+ ConstructFromDerived(const Derived& d): i(d.i) {}
+ ConstructFromDerived(Derived&& d): i(std::move(d.i)) {}
+};
+
+struct TrivialInstrument {
+ int i = 42;
+};
+struct ConvertFromTrivialBase { TrivialInstrument i; };
+struct ConvertFromTrivialDerived { TrivialInstrument i; };
+struct TrivialBase {
+ TrivialInstrument i;
+ operator ConvertFromTrivialBase() const& { return ConvertFromTrivialBase{i}; }
+ operator ConvertFromTrivialBase() && { return ConvertFromTrivialBase{std::move(i)}; }
+};
+struct TrivialDerived : public TrivialBase {
+ operator ConvertFromTrivialDerived() const& { return ConvertFromTrivialDerived{i}; }
+ operator ConvertFromTrivialDerived() && { return ConvertFromTrivialDerived{std::move(i)}; }
+};
+struct ConstructFromTrivialBase {
+ TrivialInstrument i;
+ ConstructFromTrivialBase(const TrivialBase& b): i(b.i) {}
+ ConstructFromTrivialBase(TrivialBase&& b): i(std::move(b.i)) {}
+};
+struct ConstructFromTrivialDerived {
+ TrivialInstrument i;
+ ConstructFromTrivialDerived(const TrivialDerived& d): i(d.i) {}
+ ConstructFromTrivialDerived(TrivialDerived&& d): i(std::move(d.i)) {}
+};
+
+Derived test1() {
+ Derived d1;
+ return d1; // ok
+}
+Base test2() {
+ Derived d2;
+ return d2; // e1
+ // expected-warning@-1{{will be copied despite being returned by name}}
+ // expected-note@-2{{to avoid copying}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:14}:"std::move(d2)"
+}
+ConstructFromDerived test3() {
+ Derived d3;
+ return d3; // e2-cxx11
+ // expected-warning@-1{{would have been copied despite being returned by name}}
+ // expected-note@-2{{to avoid copying on older compilers}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:14}:"std::move(d3)"
+}
+ConstructFromBase test4() {
+ Derived d4;
+ return d4; // e3
+ // expected-warning@-1{{will be copied despite being returned by name}}
+ // expected-note@-2{{to avoid copying}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:14}:"std::move(d4)"
+}
+ConvertFromDerived test5() {
+ Derived d5;
+ return d5; // e4
+ // expected-warning@-1{{will be copied despite being returned by name}}
+ // expected-note@-2{{to avoid copying}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:14}:"std::move(d5)"
+}
+ConvertFromBase test6() {
+ Derived d6;
+ return d6; // e5
+ // expected-warning@-1{{will be copied despite being returned by name}}
+ // expected-note@-2{{to avoid copying}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:14}:"std::move(d6)"
+}
+
+// These test cases should not produce the warning.
+Derived ok1() { Derived d; return d; }
+Base ok2() { Derived d; return static_cast<Derived&&>(d); }
+ConstructFromDerived ok3() { Derived d; return static_cast<Derived&&>(d); }
+ConstructFromBase ok4() { Derived d; return static_cast<Derived&&>(d); }
+ConvertFromDerived ok5() { Derived d; return static_cast<Derived&&>(d); }
+ConvertFromBase ok6() { Derived d; return static_cast<Derived&&>(d); }
+
+// If the target is an lvalue reference, assume it's not safe to move from.
+Derived ok_plvalue1(Derived& d) { return d; }
+Base ok_plvalue2(Derived& d) { return d; }
+ConstructFromDerived ok_plvalue3(const Derived& d) { return d; }
+ConstructFromBase ok_plvalue4(Derived& d) { return d; }
+ConvertFromDerived ok_plvalue5(Derived& d) { return d; }
+ConvertFromBase ok_plvalue6(Derived& d) { return d; }
+
+Derived ok_lvalue1(Derived *p) { Derived& d = *p; return d; }
+Base ok_lvalue2(Derived *p) { Derived& d = *p; return d; }
+ConstructFromDerived ok_lvalue3(Derived *p) { const Derived& d = *p; return d; }
+ConstructFromBase ok_lvalue4(Derived *p) { Derived& d = *p; return d; }
+ConvertFromDerived ok_lvalue5(Derived *p) { Derived& d = *p; return d; }
+ConvertFromBase ok_lvalue6(Derived *p) { Derived& d = *p; return d; }
+
+// If the target is a global, assume it's not safe to move from.
+static Derived global_d;
+Derived ok_global1() { return global_d; }
+Base ok_global2() { return global_d; }
+ConstructFromDerived ok_global3() { return global_d; }
+ConstructFromBase ok_global4() { return global_d; }
+ConvertFromDerived ok_global5() { return global_d; }
+ConvertFromBase ok_global6() { return global_d; }
+
+// If the target's copy constructor is trivial, assume the programmer doesn't care.
+TrivialDerived ok_trivial1(TrivialDerived d) { return d; }
+TrivialBase ok_trivial2(TrivialDerived d) { return d; }
+ConstructFromTrivialDerived ok_trivial3(TrivialDerived d) { return d; }
+ConstructFromTrivialBase ok_trivial4(TrivialDerived d) { return d; }
+ConvertFromTrivialDerived ok_trivial5(TrivialDerived d) { return d; }
+ConvertFromTrivialBase ok_trivial6(TrivialDerived d) { return d; }
+
+// If the target is a parameter, do apply the diagnostic.
+Derived testParam1(Derived d) { return d; }
+Base testParam2(Derived d) {
+ return d; // e6
+ // expected-warning@-1{{will be copied despite being returned by name}}
+ // expected-note@-2{{to avoid copying}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:13}:"std::move(d)"
+}
+ConstructFromDerived testParam3(Derived d) {
+ return d; // e7-cxx11
+ // expected-warning@-1{{would have been copied despite being returned by name}}
+ // expected-note@-2{{to avoid copying on older compilers}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:13}:"std::move(d)"
+}
+ConstructFromBase testParam4(Derived d) {
+ return d; // e8
+ // expected-warning@-1{{will be copied despite being returned by name}}
+ // expected-note@-2{{to avoid copying}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:13}:"std::move(d)"
+}
+ConvertFromDerived testParam5(Derived d) {
+ return d; // e9
+ // expected-warning@-1{{will be copied despite being returned by name}}
+ // expected-note@-2{{to avoid copying}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:13}:"std::move(d)"
+}
+ConvertFromBase testParam6(Derived d) {
+ return d; // e10
+ // expected-warning@-1{{will be copied despite being returned by name}}
+ // expected-note@-2{{to avoid copying}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:13}:"std::move(d)"
+}
+
+// If the target is an rvalue reference parameter, do apply the diagnostic.
+Derived testRParam1(Derived&& d) {
+ return d; // e11
+ // expected-warning@-1{{will be copied despite being returned by name}}
+ // expected-note@-2{{to avoid copying}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:13}:"std::move(d)"
+}
+Base testRParam2(Derived&& d) {
+ return d; // e12
+ // expected-warning@-1{{will be copied despite being returned by name}}
+ // expected-note@-2{{to avoid copying}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:13}:"std::move(d)"
+}
+ConstructFromDerived testRParam3(Derived&& d) {
+ return d; // e13
+ // expected-warning@-1{{will be copied despite being returned by name}}
+ // expected-note@-2{{to avoid copying}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:13}:"std::move(d)"
+}
+ConstructFromBase testRParam4(Derived&& d) {
+ return d; // e14
+ // expected-warning@-1{{will be copied despite being returned by name}}
+ // expected-note@-2{{to avoid copying}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:13}:"std::move(d)"
+}
+ConvertFromDerived testRParam5(Derived&& d) {
+ return d; // e15
+ // expected-warning@-1{{will be copied despite being returned by name}}
+ // expected-note@-2{{to avoid copying}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:13}:"std::move(d)"
+}
+ConvertFromBase testRParam6(Derived&& d) {
+ return d; // e16
+ // expected-warning@-1{{will be copied despite being returned by name}}
+ // expected-note@-2{{to avoid copying}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:13}:"std::move(d)"
+}
+
+// But if the return type is a reference type, then moving would be wrong.
+Derived& testRetRef1(Derived&& d) { return d; }
+Base& testRetRef2(Derived&& d) { return d; }
+auto&& testRetRef3(Derived&& d) { return d; }
+decltype(auto) testRetRef4(Derived&& d) { return (d); }
+
+// As long as we're checking parentheses, make sure parentheses don't disable the warning.
+Base testParens1() {
+ Derived d;
+ return (d); // e17
+ // expected-warning@-1{{will be copied despite being returned by name}}
+ // expected-note@-2{{to avoid copying}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:15}:"std::move(d)"
+}
+ConstructFromDerived testParens2() {
+ Derived d;
+ return (d); // e18-cxx11
+ // expected-warning@-1{{would have been copied despite being returned by name}}
+ // expected-note@-2{{to avoid copying}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:15}:"std::move(d)"
+}
+
+
+// If the target is a catch-handler parameter, do apply the diagnostic.
+void throw_derived();
+Derived testEParam1() {
+ try { throw_derived(); } catch (Derived d) { return d; } // e19
+ // expected-warning@-1{{will be copied despite being returned by name}}
+ // expected-note@-2{{to avoid copying}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:57-[[@LINE-3]]:58}:"std::move(d)"
+ __builtin_unreachable();
+}
+Base testEParam2() {
+ try { throw_derived(); } catch (Derived d) { return d; } // e20
+ // expected-warning@-1{{will be copied despite being returned by name}}
+ // expected-note@-2{{to avoid copying}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:57-[[@LINE-3]]:58}:"std::move(d)"
+ __builtin_unreachable();
+}
+ConstructFromDerived testEParam3() {
+ try { throw_derived(); } catch (Derived d) { return d; } // e21
+ // expected-warning@-1{{will be copied despite being returned by name}}
+ // expected-note@-2{{to avoid copying}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:57-[[@LINE-3]]:58}:"std::move(d)"
+ __builtin_unreachable();
+}
+ConstructFromBase testEParam4() {
+ try { throw_derived(); } catch (Derived d) { return d; } // e22
+ // expected-warning@-1{{will be copied despite being returned by name}}
+ // expected-note@-2{{to avoid copying}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:57-[[@LINE-3]]:58}:"std::move(d)"
+ __builtin_unreachable();
+}
+ConvertFromDerived testEParam5() {
+ try { throw_derived(); } catch (Derived d) { return d; } // e23
+ // expected-warning@-1{{will be copied despite being returned by name}}
+ // expected-note@-2{{to avoid copying}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:57-[[@LINE-3]]:58}:"std::move(d)"
+ __builtin_unreachable();
+}
+ConvertFromBase testEParam6() {
+ try { throw_derived(); } catch (Derived d) { return d; } // e24
+ // expected-warning@-1{{will be copied despite being returned by name}}
+ // expected-note@-2{{to avoid copying}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:57-[[@LINE-3]]:58}:"std::move(d)"
+ __builtin_unreachable();
+}
+
+// If the exception variable is an lvalue reference, we cannot be sure
+// that we own it; it is extremely contrived, but possible, for this to
+// be a reference to an exception object that was thrown via
+// `std::rethrow_exception(xp)` in Thread A, and meanwhile somebody else
+// has got a copy of `xp` in Thread B, so that moving out of this object
+// in Thread A would be observable (and racy) with respect to Thread B.
+// Therefore assume it's not safe to move from.
+Derived ok_REParam1() { try { throw_derived(); } catch (Derived& d) { return d; } __builtin_unreachable(); }
+Base ok_REParam2() { try { throw_derived(); } catch (Derived& d) { return d; } __builtin_unreachable(); }
+ConstructFromDerived ok_REParam3() { try { throw_derived(); } catch (Derived& d) { return d; } __builtin_unreachable(); }
+ConstructFromBase ok_REParam4() { try { throw_derived(); } catch (Derived& d) { return d; } __builtin_unreachable(); }
+ConvertFromDerived ok_REParam5() { try { throw_derived(); } catch (Derived& d) { return d; } __builtin_unreachable(); }
+ConvertFromBase ok_REParam6() { try { throw_derived(); } catch (Derived& d) { return d; } __builtin_unreachable(); }
+
+Derived ok_CEParam1() { try { throw_derived(); } catch (const Derived& d) { return d; } __builtin_unreachable(); }
+Base ok_CEParam2() { try { throw_derived(); } catch (const Derived& d) { return d; } __builtin_unreachable(); }
+ConstructFromDerived ok_CEParam3() { try { throw_derived(); } catch (const Derived& d) { return d; } __builtin_unreachable(); }
+ConstructFromBase ok_CEParam4() { try { throw_derived(); } catch (const Derived& d) { return d; } __builtin_unreachable(); }
+ConvertFromDerived ok_CEParam5() { try { throw_derived(); } catch (const Derived& d) { return d; } __builtin_unreachable(); }
+ConvertFromBase ok_CEParam6() { try { throw_derived(); } catch (const Derived& d) { return d; } __builtin_unreachable(); }
+
+// If rvalue overload resolution would find a copy constructor anyway,
+// or if the copy constructor actually selected is trivial, then don't warn.
+struct TriviallyCopyable {};
+struct OnlyCopyable {
+ OnlyCopyable() = default;
+ OnlyCopyable(const OnlyCopyable&) {}
+};
+
+TriviallyCopyable ok_copy1() { TriviallyCopyable c; return c; }
+OnlyCopyable ok_copy2() { OnlyCopyable c; return c; }
+TriviallyCopyable ok_copyparam1(TriviallyCopyable c) { return c; }
+OnlyCopyable ok_copyparam2(OnlyCopyable c) { return c; }
+
+void test_throw1(Derived&& d) {
+ throw d; // e25
+ // expected-warning@-1{{will be copied despite being thrown by name}}
+ // expected-note@-2{{to avoid copying}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:11-[[@LINE-3]]:12}:"std::move(d)"
+}
+
+void ok_throw1() { Derived d; throw d; }
+void ok_throw2(Derived d) { throw d; }
+void ok_throw3(Derived& d) { throw d; }
+void ok_throw4(Derived d) { throw std::move(d); }
+void ok_throw5(Derived& d) { throw std::move(d); }
+void ok_throw6(Derived& d) { throw static_cast<Derived&&>(d); }
+void ok_throw7(TriviallyCopyable d) { throw d; }
+void ok_throw8(OnlyCopyable d) { throw d; }
diff --git a/test/SemaCXX/warn-self-assign-builtin.cpp b/test/SemaCXX/warn-self-assign-builtin.cpp
new file mode 100644
index 000000000000..212fc241e3e7
--- /dev/null
+++ b/test/SemaCXX/warn-self-assign-builtin.cpp
@@ -0,0 +1,67 @@
+// RUN: %clang_cc1 -fsyntax-only -Wself-assign -verify %s
+
+void f() {
+ int a = 42, b = 42;
+ a = a; // expected-warning{{explicitly assigning}}
+ b = b; // expected-warning{{explicitly assigning}}
+ a = b;
+ b = a = b;
+ a = a = a; // expected-warning{{explicitly assigning}}
+ a = b = b = a;
+
+ a *= a;
+ a /= a;
+ a %= a;
+ a += a;
+ a -= a;
+ a <<= a;
+ a >>= a;
+ a &= a; // expected-warning {{explicitly assigning}}
+ a |= a; // expected-warning {{explicitly assigning}}
+ a ^= a;
+}
+
+// Dummy type.
+struct S {};
+
+void false_positives() {
+#define OP =
+#define LHS a
+#define RHS a
+ int a = 42;
+ // These shouldn't warn due to the use of the preprocessor.
+ a OP a;
+ LHS = a;
+ a = RHS;
+ LHS OP RHS;
+#undef OP
+#undef LHS
+#undef RHS
+
+ // A way to silence the warning.
+ a = (int &)a;
+
+ // Volatile stores aren't side-effect free.
+ volatile int vol_a;
+ vol_a = vol_a;
+ volatile int &vol_a_ref = vol_a;
+ vol_a_ref = vol_a_ref;
+}
+
+// Do not diagnose self-assigment in an unevaluated context
+void false_positives_unevaluated_ctx(int a) noexcept(noexcept(a = a)) // expected-warning {{expression with side effects has no effect in an unevaluated context}}
+{
+ decltype(a = a) b = a; // expected-warning {{expression with side effects has no effect in an unevaluated context}}
+ static_assert(noexcept(a = a), ""); // expected-warning {{expression with side effects has no effect in an unevaluated context}}
+ static_assert(sizeof(a = a), ""); // expected-warning {{expression with side effects has no effect in an unevaluated context}}
+}
+
+template <typename T>
+void g() {
+ T a;
+ a = a; // expected-warning{{explicitly assigning}}
+}
+void instantiate() {
+ g<int>();
+ g<S>();
+}
diff --git a/test/SemaCXX/warn-self-assign-field-builtin.cpp b/test/SemaCXX/warn-self-assign-field-builtin.cpp
new file mode 100644
index 000000000000..7ae07e7de672
--- /dev/null
+++ b/test/SemaCXX/warn-self-assign-field-builtin.cpp
@@ -0,0 +1,117 @@
+// RUN: %clang_cc1 -fsyntax-only -Wself-assign-field -verify %s
+
+struct C {
+ int a;
+ int b;
+
+ void f() {
+ a = a; // expected-warning {{assigning field to itself}}
+ b = b; // expected-warning {{assigning field to itself}}
+ a = b;
+
+ this->a = a; // expected-warning {{assigning field to itself}}
+ this->b = b; // expected-warning {{assigning field to itself}}
+ a = this->a; // expected-warning {{assigning field to itself}}
+ b = this->b; // expected-warning {{assigning field to itself}}
+ this->a = this->a; // expected-warning {{assigning field to itself}}
+ this->b = this->b; // expected-warning {{assigning field to itself}}
+
+ a = b;
+ a = this->b;
+ this->a = b;
+ this->a = this->b;
+
+ a *= a;
+ a /= a;
+ a %= a;
+ a += a;
+ a -= a;
+ a <<= a;
+ a >>= a;
+ a &= a;
+ a |= a;
+ a ^= a;
+ }
+
+ void false_positives() {
+#define OP =
+#define LHS a
+#define RHS a
+ // These shouldn't warn due to the use of the preprocessor.
+ a OP a;
+ LHS = a;
+ a = RHS;
+ LHS OP RHS;
+#undef OP
+#undef LHS
+#undef RHS
+
+ // A way to silence the warning.
+ a = (int &)a;
+ }
+
+ // Do not diagnose self-assigment in an unevaluated context
+ void false_positives_unevaluated_ctx() noexcept(noexcept(a = a)) // expected-warning {{expression with side effects has no effect in an unevaluated context}}
+ {
+ decltype(a = a) b = a; // expected-warning {{expression with side effects has no effect in an unevaluated context}}
+ static_assert(noexcept(a = a), ""); // expected-warning {{expression with side effects has no effect in an unevaluated context}}
+ static_assert(sizeof(a = a), ""); // expected-warning {{expression with side effects has no effect in an unevaluated context}}
+ }
+
+ volatile int vol_a;
+ void vol_test() {
+ // Volatile stores aren't side-effect free.
+ vol_a = vol_a;
+ volatile int &vol_a_ref = vol_a;
+ vol_a_ref = vol_a_ref;
+ }
+};
+
+// Dummy type.
+struct Dummy {};
+
+template <typename T>
+struct TemplateClass {
+ T var;
+ void f() {
+ var = var; // expected-warning {{assigning field to itself}}
+ }
+};
+void instantiate() {
+ {
+ TemplateClass<int> c;
+ c.f();
+ }
+ {
+ TemplateClass<Dummy> c;
+ c.f();
+ }
+}
+
+// It may make sense not to warn on the rest of the tests.
+// It may be a valid use-case to self-assign to tell the compiler that
+// it is ok to vectorize the store.
+
+void f0(C *s, C *t) {
+ s->a = s->a;
+ t->a = s->a;
+}
+
+void f1(C &s, C &t) {
+ s.a = s.a;
+ t.a = s.a;
+}
+
+struct T {
+ C *s;
+};
+
+void f2(T *t, T *t2) {
+ t->s->a = t->s->a;
+ t2->s->a = t->s->a;
+}
+
+void f3(T &t, T &t2) {
+ t.s->a = t.s->a;
+ t2.s->a = t.s->a;
+}
diff --git a/test/SemaCXX/warn-self-assign-field-overloaded.cpp b/test/SemaCXX/warn-self-assign-field-overloaded.cpp
new file mode 100644
index 000000000000..c9cec8e406fc
--- /dev/null
+++ b/test/SemaCXX/warn-self-assign-field-overloaded.cpp
@@ -0,0 +1,162 @@
+// RUN: %clang_cc1 -fsyntax-only -Wself-assign-field -DDUMMY -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wself-assign-field -DV0 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wself-assign-field -DV1 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wself-assign-field -DV2 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wself-assign-field -DV3 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wself-assign-field -DV4 -verify %s
+
+#ifdef DUMMY
+struct S {};
+#else
+struct S {
+#if defined(V0)
+ S() = default;
+#elif defined(V1)
+ S &operator=(const S &) = default;
+#elif defined(V2)
+ S &operator=(S &) = default;
+#elif defined(V3)
+ S &operator=(const S &);
+#elif defined(V4)
+ S &operator=(S &);
+#else
+#error Define something!
+#endif
+ S &operator*=(const S &);
+ S &operator/=(const S &);
+ S &operator%=(const S &);
+ S &operator+=(const S &);
+ S &operator-=(const S &);
+ S &operator<<=(const S &);
+ S &operator>>=(const S &);
+ S &operator&=(const S &);
+ S &operator|=(const S &);
+ S &operator^=(const S &);
+ S &operator=(const volatile S &) volatile;
+};
+#endif
+struct C {
+ S a;
+ S b;
+
+ void f() {
+ a = a; // expected-warning {{assigning field to itself}}
+ b = b; // expected-warning {{assigning field to itself}}
+ a = b;
+
+ this->a = a; // expected-warning {{assigning field to itself}}
+ this->b = b; // expected-warning {{assigning field to itself}}
+ a = this->a; // expected-warning {{assigning field to itself}}
+ b = this->b; // expected-warning {{assigning field to itself}}
+ this->a = this->a; // expected-warning {{assigning field to itself}}
+ this->b = this->b; // expected-warning {{assigning field to itself}}
+
+ a = b;
+ a = this->b;
+ this->a = b;
+ this->a = this->b;
+
+#ifndef DUMMY
+ a *= a;
+ a /= a; // expected-warning {{assigning field to itself}}
+ a %= a; // expected-warning {{assigning field to itself}}
+ a += a;
+ a -= a; // expected-warning {{assigning field to itself}}
+ a <<= a;
+ a >>= a;
+ a &= a; // expected-warning {{assigning field to itself}}
+ a |= a; // expected-warning {{assigning field to itself}}
+ a ^= a; // expected-warning {{assigning field to itself}}
+#endif
+ }
+
+ void false_positives() {
+#define OP =
+#define LHS a
+#define RHS a
+ // These shouldn't warn due to the use of the preprocessor.
+ a OP a;
+ LHS = a;
+ a = RHS;
+ LHS OP RHS;
+#undef OP
+#undef LHS
+#undef RHS
+
+ // Ways to silence the warning.
+ a = *&a;
+ a = (S &)a;
+ a = static_cast<decltype(a) &>(a);
+ }
+
+#ifndef DUMMY
+ volatile S vol_a;
+ void vol_test() {
+ // Volatile stores aren't side-effect free.
+ vol_a = vol_a;
+ volatile S &vol_a_ref = vol_a;
+ vol_a_ref = vol_a_ref;
+ }
+#endif
+};
+
+// Do not diagnose self-assigment in an unevaluated context
+struct SNoExcept {
+ SNoExcept() = default;
+ SNoExcept &operator=(const SNoExcept &) noexcept;
+};
+struct false_positives_unevaluated_ctx_class {
+ SNoExcept a;
+
+ void false_positives_unevaluated_ctx(SNoExcept a) noexcept(noexcept(a = a)) {
+ decltype(a = a) b = a;
+ static_assert(noexcept(a = a), "");
+ static_assert(sizeof(a = a), "");
+ }
+};
+
+template <typename T>
+struct TemplateClass {
+ T var;
+ void f() {
+ var = var; // expected-warning {{assigning field to itself}}
+ }
+};
+void instantiate() {
+ {
+ TemplateClass<int> c;
+ c.f();
+ }
+ {
+ TemplateClass<S> c;
+ c.f();
+ }
+}
+
+// It may make sense not to warn on the rest of the tests.
+// It may be a valid use-case to self-assign to tell the compiler that
+// it is ok to vectorize the store.
+
+void f0(C *s, C *t) {
+ s->a = s->a;
+ t->a = s->a;
+}
+
+void f1(C &s, C &t) {
+ s.a = s.a;
+ t.a = s.a;
+}
+
+struct T {
+ C *s;
+};
+
+void f2(T *t, T *t2) {
+ t->s->a = t->s->a;
+ t2->s->a = t->s->a;
+}
+
+void f3(T &t, T &t2) {
+ t.s->a = t.s->a;
+ t2.s->a = t.s->a;
+}
diff --git a/test/SemaCXX/warn-self-assign-overloaded-disable.cpp b/test/SemaCXX/warn-self-assign-overloaded-disable.cpp
new file mode 100644
index 000000000000..703fcc47b56c
--- /dev/null
+++ b/test/SemaCXX/warn-self-assign-overloaded-disable.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -fsyntax-only -Wall -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wself-assign -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wself-assign-overloaded -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wall -Wno-self-assign-overloaded -DSILENCE -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wself-assign -Wno-self-assign-overloaded -DSILENCE -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wself-assign-overloaded -Wno-self-assign-overloaded -DSILENCE -verify %s
+
+struct S {};
+
+void f() {
+ S a;
+#ifndef SILENCE
+ a = a; // expected-warning{{explicitly assigning}}
+#else
+ // expected-no-diagnostics
+ a = a;
+#endif
+}
diff --git a/test/SemaCXX/warn-self-assign-overloaded.cpp b/test/SemaCXX/warn-self-assign-overloaded.cpp
new file mode 100644
index 000000000000..b27f4c857aa7
--- /dev/null
+++ b/test/SemaCXX/warn-self-assign-overloaded.cpp
@@ -0,0 +1,115 @@
+// RUN: %clang_cc1 -fsyntax-only -Wself-assign -DDUMMY -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wself-assign -DV0 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wself-assign -DV1 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wself-assign -DV2 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wself-assign -DV3 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wself-assign -DV4 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wno-self-assign -Wself-assign-overloaded -DDUMMY -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wno-self-assign -Wself-assign-overloaded -DV0 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wno-self-assign -Wself-assign-overloaded -DV1 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wno-self-assign -Wself-assign-overloaded -DV2 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wno-self-assign -Wself-assign-overloaded -DV3 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wno-self-assign -Wself-assign-overloaded -DV4 -verify %s
+
+#ifdef DUMMY
+struct S {};
+#else
+struct S {
+#if defined(V0)
+ S() = default;
+#elif defined(V1)
+ S &operator=(const S &) = default;
+#elif defined(V2)
+ S &operator=(S &) = default;
+#elif defined(V3)
+ S &operator=(const S &);
+#elif defined(V4)
+ S &operator=(S &);
+#else
+#error Define something!
+#endif
+ S &operator*=(const S &);
+ S &operator/=(const S &);
+ S &operator%=(const S &);
+ S &operator+=(const S &);
+ S &operator-=(const S &);
+ S &operator<<=(const S &);
+ S &operator>>=(const S &);
+ S &operator&=(const S &);
+ S &operator|=(const S &);
+ S &operator^=(const S &);
+ S &operator=(const volatile S &) volatile;
+};
+#endif
+
+void f() {
+ S a, b;
+ a = a; // expected-warning{{explicitly assigning}}
+ b = b; // expected-warning{{explicitly assigning}}
+ a = b;
+ b = a = b;
+ a = a = a; // expected-warning{{explicitly assigning}}
+ a = b = b = a;
+
+#ifndef DUMMY
+ a *= a;
+ a /= a; // expected-warning {{explicitly assigning}}
+ a %= a; // expected-warning {{explicitly assigning}}
+ a += a;
+ a -= a; // expected-warning {{explicitly assigning}}
+ a <<= a;
+ a >>= a;
+ a &= a; // expected-warning {{explicitly assigning}}
+ a |= a; // expected-warning {{explicitly assigning}}
+ a ^= a; // expected-warning {{explicitly assigning}}
+#endif
+}
+
+void false_positives() {
+#define OP =
+#define LHS a
+#define RHS a
+ S a;
+ // These shouldn't warn due to the use of the preprocessor.
+ a OP a;
+ LHS = a;
+ a = RHS;
+ LHS OP RHS;
+#undef OP
+#undef LHS
+#undef RHS
+
+ // Ways to silence the warning.
+ a = *&a;
+ a = (S &)a;
+ a = static_cast<decltype(a) &>(a);
+
+#ifndef DUMMY
+ // Volatile stores aren't side-effect free.
+ volatile S vol_a;
+ vol_a = vol_a;
+ volatile S &vol_a_ref = vol_a;
+ vol_a_ref = vol_a_ref;
+#endif
+}
+
+// Do not diagnose self-assigment in an unevaluated context
+struct SNoExcept {
+ SNoExcept() = default;
+ SNoExcept &operator=(const SNoExcept &) noexcept;
+};
+void false_positives_unevaluated_ctx(SNoExcept a) noexcept(noexcept(a = a)) {
+ decltype(a = a) b = a;
+ static_assert(noexcept(a = a), "");
+ static_assert(sizeof(a = a), "");
+}
+
+template <typename T>
+void g() {
+ T a;
+ a = a; // expected-warning{{explicitly assigning}}
+}
+void instantiate() {
+ g<int>();
+ g<S>();
+}
diff --git a/test/SemaCXX/warn-self-assign.cpp b/test/SemaCXX/warn-self-assign.cpp
deleted file mode 100644
index 7d558c6a073e..000000000000
--- a/test/SemaCXX/warn-self-assign.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-// RUN: %clang_cc1 -fsyntax-only -Wself-assign -verify %s
-
-void f() {
- int a = 42, b = 42;
- a = a; // expected-warning{{explicitly assigning}}
- b = b; // expected-warning{{explicitly assigning}}
- a = b;
- b = a = b;
- a = a = a; // expected-warning{{explicitly assigning}}
- a = b = b = a;
- a &= a; // expected-warning{{explicitly assigning}}
- a |= a; // expected-warning{{explicitly assigning}}
- a ^= a;
-}
-
-// Dummy type.
-struct S {};
-
-void false_positives() {
-#define OP =
-#define LHS a
-#define RHS a
- int a = 42;
- // These shouldn't warn due to the use of the preprocessor.
- a OP a;
- LHS = a;
- a = RHS;
- LHS OP RHS;
-#undef OP
-#undef LHS
-#undef RHS
-
- S s;
- s = s; // Not a builtin assignment operator, no warning.
-
- // Volatile stores aren't side-effect free.
- volatile int vol_a;
- vol_a = vol_a;
- volatile int &vol_a_ref = vol_a;
- vol_a_ref = vol_a_ref;
-}
-
-template <typename T> void g() {
- T a;
- a = a; // May or may not be a builtin assignment operator, no warning.
-}
-void instantiate() {
- g<int>();
- g<S>();
-}
diff --git a/test/SemaCXX/warn-thread-safety-analysis.cpp b/test/SemaCXX/warn-thread-safety-analysis.cpp
index fc1ea5e9e996..51535be97d97 100644
--- a/test/SemaCXX/warn-thread-safety-analysis.cpp
+++ b/test/SemaCXX/warn-thread-safety-analysis.cpp
@@ -1,10 +1,11 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_ASSERT_CAPABILITY=0 %s
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_ASSERT_CAPABILITY=1 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=0 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=1 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=0 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=1 %s
// FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety -std=c++11 -Wc++98-compat %s
// FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety %s
-#define LOCKABLE __attribute__((lockable))
#define SCOPED_LOCKABLE __attribute__((scoped_lockable))
#define GUARDED_BY(x) __attribute__((guarded_by(x)))
#define GUARDED_VAR __attribute__((guarded_var))
@@ -12,37 +13,49 @@
#define PT_GUARDED_VAR __attribute__((pt_guarded_var))
#define ACQUIRED_AFTER(...) __attribute__((acquired_after(__VA_ARGS__)))
#define ACQUIRED_BEFORE(...) __attribute__((acquired_before(__VA_ARGS__)))
-#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__((exclusive_lock_function(__VA_ARGS__)))
-#define SHARED_LOCK_FUNCTION(...) __attribute__((shared_lock_function(__VA_ARGS__)))
-#if USE_ASSERT_CAPABILITY
+#if USE_CAPABILITY
+#define LOCKABLE __attribute__((capability("mutex")))
#define ASSERT_EXCLUSIVE_LOCK(...) __attribute__((assert_capability(__VA_ARGS__)))
#define ASSERT_SHARED_LOCK(...) __attribute__((assert_shared_capability(__VA_ARGS__)))
+#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__((acquire_capability(__VA_ARGS__)))
+#define SHARED_LOCK_FUNCTION(...) __attribute__((acquire_shared_capability(__VA_ARGS__)))
+#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__((try_acquire_capability(__VA_ARGS__)))
+#define SHARED_TRYLOCK_FUNCTION(...) __attribute__((try_acquire_shared_capability(__VA_ARGS__)))
+#define EXCLUSIVE_LOCKS_REQUIRED(...) __attribute__((requires_capability(__VA_ARGS__)))
+#define SHARED_LOCKS_REQUIRED(...) __attribute__((requires_shared_capability(__VA_ARGS__)))
#else
+#define LOCKABLE __attribute__((lockable))
#define ASSERT_EXCLUSIVE_LOCK(...) __attribute__((assert_exclusive_lock(__VA_ARGS__)))
#define ASSERT_SHARED_LOCK(...) __attribute__((assert_shared_lock(__VA_ARGS__)))
-#endif
-
+#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__((exclusive_lock_function(__VA_ARGS__)))
+#define SHARED_LOCK_FUNCTION(...) __attribute__((shared_lock_function(__VA_ARGS__)))
#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__((exclusive_trylock_function(__VA_ARGS__)))
#define SHARED_TRYLOCK_FUNCTION(...) __attribute__((shared_trylock_function(__VA_ARGS__)))
-#define UNLOCK_FUNCTION(...) __attribute__((unlock_function(__VA_ARGS__)))
+#define EXCLUSIVE_LOCKS_REQUIRED(...) __attribute__((exclusive_locks_required(__VA_ARGS__)))
+#define SHARED_LOCKS_REQUIRED(...) __attribute__((shared_locks_required(__VA_ARGS__)))
+#endif
#define EXCLUSIVE_UNLOCK_FUNCTION(...) __attribute__((release_capability(__VA_ARGS__)))
#define SHARED_UNLOCK_FUNCTION(...) __attribute__((release_shared_capability(__VA_ARGS__)))
+#define UNLOCK_FUNCTION(...) __attribute__((unlock_function(__VA_ARGS__)))
#define LOCK_RETURNED(x) __attribute__((lock_returned(x)))
#define LOCKS_EXCLUDED(...) __attribute__((locks_excluded(__VA_ARGS__)))
-#define EXCLUSIVE_LOCKS_REQUIRED(...) __attribute__((exclusive_locks_required(__VA_ARGS__)))
-#define SHARED_LOCKS_REQUIRED(...) __attribute__((shared_locks_required(__VA_ARGS__)))
#define NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis))
class LOCKABLE Mutex {
public:
- void Lock() __attribute__((exclusive_lock_function));
- void ReaderLock() __attribute__((shared_lock_function));
- void Unlock() __attribute__((unlock_function));
- bool TryLock() __attribute__((exclusive_trylock_function(true)));
- bool ReaderTryLock() __attribute__((shared_trylock_function(true)));
- void LockWhen(const int &cond) __attribute__((exclusive_lock_function));
+ void Lock() EXCLUSIVE_LOCK_FUNCTION();
+ void ReaderLock() SHARED_LOCK_FUNCTION();
+ void Unlock() UNLOCK_FUNCTION();
+ void ExclusiveUnlock() EXCLUSIVE_UNLOCK_FUNCTION();
+ void ReaderUnlock() SHARED_UNLOCK_FUNCTION();
+ bool TryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true);
+ bool ReaderTryLock() SHARED_TRYLOCK_FUNCTION(true);
+ void LockWhen(const int &cond) EXCLUSIVE_LOCK_FUNCTION();
+
+ void PromoteShared() SHARED_UNLOCK_FUNCTION() EXCLUSIVE_LOCK_FUNCTION();
+ void DemoteExclusive() EXCLUSIVE_UNLOCK_FUNCTION() SHARED_LOCK_FUNCTION();
// for negative capabilities
const Mutex& operator!() const { return *this; }
@@ -73,11 +86,10 @@ class SCOPED_LOCKABLE ReleasableMutexLock {
void Release() UNLOCK_FUNCTION();
};
-class __attribute__((scoped_lockable)) DoubleMutexLock {
+class SCOPED_LOCKABLE DoubleMutexLock {
public:
- DoubleMutexLock(Mutex *mu1, Mutex *mu2)
- __attribute__((exclusive_lock_function(mu1, mu2)));
- ~DoubleMutexLock() __attribute__((unlock_function));
+ DoubleMutexLock(Mutex *mu1, Mutex *mu2) EXCLUSIVE_LOCK_FUNCTION(mu1, mu2);
+ ~DoubleMutexLock() UNLOCK_FUNCTION();
};
// The universal lock, written "*", allows checking to be selectively turned
@@ -158,7 +170,7 @@ class MutexWrapper {
public:
Mutex mu;
int x __attribute__((guarded_by(mu)));
- void MyLock() __attribute__((exclusive_lock_function(mu)));
+ void MyLock() EXCLUSIVE_LOCK_FUNCTION(mu);
};
MutexWrapper sls_mw;
@@ -371,8 +383,8 @@ Mutex aa_mu;
class GlobalLocker {
public:
- void globalLock() __attribute__((exclusive_lock_function(aa_mu)));
- void globalUnlock() __attribute__((unlock_function(aa_mu)));
+ void globalLock() EXCLUSIVE_LOCK_FUNCTION(aa_mu);
+ void globalUnlock() UNLOCK_FUNCTION(aa_mu);
};
GlobalLocker glock;
@@ -455,7 +467,7 @@ class GBFoo {
// expected-warning {{writing variable 'gb_field' requires holding mutex 'sls_mu' exclusively}}
}
- void testNoAnal() __attribute__((no_thread_safety_analysis)) {
+ void testNoAnal() NO_THREAD_SAFETY_ANALYSIS {
gb_field = 0;
}
};
@@ -549,7 +561,7 @@ public:
int a __attribute__((guarded_by(mu)));
int b;
- void foo() __attribute__((exclusive_locks_required(mu))) { }
+ void foo() EXCLUSIVE_LOCKS_REQUIRED(mu) { }
void test() {
a = 0; // \
@@ -695,6 +707,26 @@ void shared_fun_8() {
sls_mu.Unlock();
}
+void shared_fun_9() {
+ sls_mu.Lock();
+ sls_mu.ExclusiveUnlock();
+
+ sls_mu.ReaderLock();
+ sls_mu.ReaderUnlock();
+}
+
+void shared_fun_10() {
+ sls_mu.Lock();
+ sls_mu.DemoteExclusive();
+ sls_mu.ReaderUnlock();
+}
+
+void shared_fun_11() {
+ sls_mu.ReaderLock();
+ sls_mu.PromoteShared();
+ sls_mu.Unlock();
+}
+
void shared_bad_0() {
sls_mu.Lock(); // \
// expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}
@@ -728,21 +760,47 @@ void shared_bad_2() {
sls_mu.Unlock();
}
+void shared_bad_3() {
+ sls_mu.Lock();
+ sls_mu.ReaderUnlock(); // \
+ // expected-warning {{releasing mutex 'sls_mu' using shared access, expected exclusive access}}
+}
+
+void shared_bad_4() {
+ sls_mu.ReaderLock();
+ sls_mu.ExclusiveUnlock(); // \
+ // expected-warning {{releasing mutex 'sls_mu' using exclusive access, expected shared access}}
+}
+
+void shared_bad_5() {
+ sls_mu.Lock();
+ sls_mu.PromoteShared(); // \
+ // expected-warning {{releasing mutex 'sls_mu' using shared access, expected exclusive access}}
+ sls_mu.ExclusiveUnlock();
+}
+
+void shared_bad_6() {
+ sls_mu.ReaderLock();
+ sls_mu.DemoteExclusive(); // \
+ // expected-warning {{releasing mutex 'sls_mu' using exclusive access, expected shared access}}
+ sls_mu.ReaderUnlock();
+}
+
// FIXME: Add support for functions (not only methods)
class LRBar {
public:
- void aa_elr_fun() __attribute__((exclusive_locks_required(aa_mu)));
- void aa_elr_fun_s() __attribute__((shared_locks_required(aa_mu)));
+ void aa_elr_fun() EXCLUSIVE_LOCKS_REQUIRED(aa_mu);
+ void aa_elr_fun_s() SHARED_LOCKS_REQUIRED(aa_mu);
void le_fun() __attribute__((locks_excluded(sls_mu)));
};
class LRFoo {
public:
- void test() __attribute__((exclusive_locks_required(sls_mu)));
- void testShared() __attribute__((shared_locks_required(sls_mu2)));
+ void test() EXCLUSIVE_LOCKS_REQUIRED(sls_mu);
+ void testShared() SHARED_LOCKS_REQUIRED(sls_mu2);
};
-void elr_fun() __attribute__((exclusive_locks_required(sls_mu)));
+void elr_fun() EXCLUSIVE_LOCKS_REQUIRED(sls_mu);
void elr_fun() {}
LRFoo MyLRFoo;
@@ -794,18 +852,18 @@ void es_fun_7() {
sls_mu.Unlock();
}
-void es_fun_8() __attribute__((no_thread_safety_analysis));
+void es_fun_8() NO_THREAD_SAFETY_ANALYSIS;
void es_fun_8() {
Bar.aa_elr_fun_s();
}
-void es_fun_9() __attribute__((shared_locks_required(aa_mu)));
+void es_fun_9() SHARED_LOCKS_REQUIRED(aa_mu);
void es_fun_9() {
Bar.aa_elr_fun_s();
}
-void es_fun_10() __attribute__((exclusive_locks_required(aa_mu)));
+void es_fun_10() EXCLUSIVE_LOCKS_REQUIRED(aa_mu);
void es_fun_10() {
Bar.aa_elr_fun_s();
}
@@ -1047,7 +1105,7 @@ void main() {
namespace thread_annot_lock_61_modified {
// Modified to fix the compiler errors
// Test the fix for a bug introduced by the support of pass-by-reference
- // paramters.
+ // parameters.
struct Foo { Foo &operator<< (bool) {return *this;} };
Foo &getFoo();
struct Bar { Foo &func () {return getFoo();} };
@@ -1531,23 +1589,23 @@ namespace substitution_test {
public:
Mutex mu;
- void lockData() __attribute__((exclusive_lock_function(mu)));
- void unlockData() __attribute__((unlock_function(mu)));
+ void lockData() EXCLUSIVE_LOCK_FUNCTION(mu);
+ void unlockData() UNLOCK_FUNCTION(mu);
- void doSomething() __attribute__((exclusive_locks_required(mu))) { }
+ void doSomething() EXCLUSIVE_LOCKS_REQUIRED(mu) { }
};
class DataLocker {
public:
- void lockData (MyData *d) __attribute__((exclusive_lock_function(d->mu)));
- void unlockData(MyData *d) __attribute__((unlock_function(d->mu)));
+ void lockData (MyData *d) EXCLUSIVE_LOCK_FUNCTION(d->mu);
+ void unlockData(MyData *d) UNLOCK_FUNCTION(d->mu);
};
class Foo {
public:
- void foo(MyData* d) __attribute__((exclusive_locks_required(d->mu))) { }
+ void foo(MyData* d) EXCLUSIVE_LOCKS_REQUIRED(d->mu) { }
void bar1(MyData* d) {
d->lockData();
@@ -1588,8 +1646,8 @@ namespace constructor_destructor_tests {
class Foo {
public:
- Foo() __attribute__((exclusive_lock_function(fooMu))) { }
- ~Foo() __attribute__((unlock_function(fooMu))) { }
+ Foo() EXCLUSIVE_LOCK_FUNCTION(fooMu) { }
+ ~Foo() UNLOCK_FUNCTION(fooMu) { }
};
void fooTest() {
@@ -1803,7 +1861,7 @@ struct TestTryLock {
bool b = mu.TryLock();
while (cond) {
- if (b) { // b should be uknown at this point b/c of the loop
+ if (b) { // b should be unknown at this point b/c of the loop
a = 10; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
}
b = !b;
@@ -1932,7 +1990,7 @@ void test() {
f1.mu_.Unlock();
bt.barTD(&f1); // \
- // expected-warning {{calling function 'barTD' requires holding mutex 'f1.mu_' exclusively}} \
+ // expected-warning {{calling function 'barTD<TestTemplateAttributeInstantiation::Foo1>' requires holding mutex 'f1.mu_' exclusively}} \
// expected-note {{found near match 'bt.fooBase.mu_'}}
bt.fooBase.mu_.Unlock();
@@ -2020,9 +2078,9 @@ void test() {
namespace GoingNative {
- struct __attribute__((lockable)) mutex {
- void lock() __attribute__((exclusive_lock_function));
- void unlock() __attribute__((unlock_function));
+ struct LOCKABLE mutex {
+ void lock() EXCLUSIVE_LOCK_FUNCTION();
+ void unlock() UNLOCK_FUNCTION();
// ...
};
bool foo();
@@ -2129,10 +2187,10 @@ void test() {
myFoo.foo3(&myFoo); // \
// expected-warning {{calling function 'foo3' requires holding mutex 'myFoo.mu_' exclusively}}
myFoo.fooT1(dummy); // \
- // expected-warning {{calling function 'fooT1' requires holding mutex 'myFoo.mu_' exclusively}}
+ // expected-warning {{calling function 'fooT1<int>' requires holding mutex 'myFoo.mu_' exclusively}}
myFoo.fooT2(dummy); // \
- // expected-warning {{calling function 'fooT2' requires holding mutex 'myFoo.mu_' exclusively}}
+ // expected-warning {{calling function 'fooT2<int>' requires holding mutex 'myFoo.mu_' exclusively}}
fooF1(&myFoo); // \
// expected-warning {{calling function 'fooF1' requires holding mutex 'myFoo.mu_' exclusively}}
@@ -3553,7 +3611,7 @@ struct Cell {
class Foo {
public:
template <class T>
- void elr(Cell<T>* c) __attribute__((exclusive_locks_required(c->mu_)));
+ void elr(Cell<T>* c) EXCLUSIVE_LOCKS_REQUIRED(c->mu_);
void test();
};
@@ -3564,12 +3622,12 @@ void Foo::elr(Cell<T>* c1) { }
void Foo::test() {
Cell<int> cell;
elr(&cell); // \
- // expected-warning {{calling function 'elr' requires holding mutex 'cell.mu_' exclusively}}
+ // expected-warning {{calling function 'elr<int>' requires holding mutex 'cell.mu_' exclusively}}
}
template<class T>
-void globalELR(Cell<T>* c) __attribute__((exclusive_locks_required(c->mu_)));
+void globalELR(Cell<T>* c) EXCLUSIVE_LOCKS_REQUIRED(c->mu_);
template<class T>
void globalELR(Cell<T>* c1) { }
@@ -3577,12 +3635,12 @@ void globalELR(Cell<T>* c1) { }
void globalTest() {
Cell<int> cell;
globalELR(&cell); // \
- // expected-warning {{calling function 'globalELR' requires holding mutex 'cell.mu_' exclusively}}
+ // expected-warning {{calling function 'globalELR<int>' requires holding mutex 'cell.mu_' exclusively}}
}
template<class T>
-void globalELR2(Cell<T>* c) __attribute__((exclusive_locks_required(c->mu_)));
+void globalELR2(Cell<T>* c) EXCLUSIVE_LOCKS_REQUIRED(c->mu_);
// second declaration
template<class T>
@@ -3598,14 +3656,14 @@ void globalELR2(Cell<T>* c4);
void globalTest2() {
Cell<int> cell;
globalELR2(&cell); // \
- // expected-warning {{calling function 'globalELR2' requires holding mutex 'cell.mu_' exclusively}}
+ // expected-warning {{calling function 'globalELR2<int>' requires holding mutex 'cell.mu_' exclusively}}
}
template<class T>
class FooT {
public:
- void elr(Cell<T>* c) __attribute__((exclusive_locks_required(c->mu_)));
+ void elr(Cell<T>* c) EXCLUSIVE_LOCKS_REQUIRED(c->mu_);
};
template<class T>
@@ -4415,7 +4473,7 @@ class A {
(RunHelper)(); // expected-warning {{calling function 'RunHelper' requires holding mutex 'M' exclusively}}
}
- void RunHelper() __attribute__((exclusive_locks_required(M)));
+ void RunHelper() EXCLUSIVE_LOCKS_REQUIRED(M);
Mutex M;
};
@@ -4642,8 +4700,8 @@ namespace NegativeThreadRoles {
typedef int __attribute__((capability("role"))) ThreadRole;
-void acquire(ThreadRole R) __attribute__((exclusive_lock_function(R))) __attribute__((no_thread_safety_analysis)) {}
-void release(ThreadRole R) __attribute__((unlock_function(R))) __attribute__((no_thread_safety_analysis)) {}
+void acquire(ThreadRole R) EXCLUSIVE_LOCK_FUNCTION(R) NO_THREAD_SAFETY_ANALYSIS {}
+void release(ThreadRole R) UNLOCK_FUNCTION(R) NO_THREAD_SAFETY_ANALYSIS {}
ThreadRole FlightControl, Logger;
@@ -5248,3 +5306,28 @@ struct C {
C c;
void f() { c[A()]->g(); }
} // namespace PR34800
+
+namespace ReturnScopedLockable {
+ template<typename Object> class SCOPED_LOCKABLE ReadLockedPtr {
+ public:
+ ReadLockedPtr(Object *ptr) SHARED_LOCK_FUNCTION((*this)->mutex);
+ ReadLockedPtr(ReadLockedPtr &&) SHARED_LOCK_FUNCTION((*this)->mutex);
+ ~ReadLockedPtr() UNLOCK_FUNCTION();
+
+ Object *operator->() const { return object; }
+
+ private:
+ Object *object;
+ };
+
+ struct Object {
+ int f() SHARED_LOCKS_REQUIRED(mutex);
+ Mutex mutex;
+ };
+
+ ReadLockedPtr<Object> get();
+ int use() {
+ auto ptr = get();
+ return ptr->f();
+ }
+}
diff --git a/test/SemaCXX/warn-throw-out-noexcept-func.cpp b/test/SemaCXX/warn-throw-out-noexcept-func.cpp
index a6c23ddc6c8f..646cea446c2c 100644
--- a/test/SemaCXX/warn-throw-out-noexcept-func.cpp
+++ b/test/SemaCXX/warn-throw-out-noexcept-func.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -fdelayed-template-parsing -fcxx-exceptions -fsyntax-only -Wexceptions -verify -fdeclspec -std=c++11
+// RUN: %clang_cc1 %s -fdelayed-template-parsing -fcxx-exceptions -fsyntax-only -Wexceptions -verify -fdeclspec -std=c++17
struct A_ShouldDiag {
~A_ShouldDiag(); // implicitly noexcept(true)
};
@@ -248,9 +248,11 @@ void o_ShouldNotDiag() noexcept {
}
}
-void p_ShouldDiag() noexcept { //expected-note {{function declared non-throwing here}}
+void p_ShouldNotDiag() noexcept {
+ // Don't warn here: it's possible that the user arranges to only call this
+ // when the active exception is of type 'int'.
try {
- throw; //expected-warning {{has a non-throwing exception specification but}}
+ throw;
} catch (int){
}
}
@@ -325,3 +327,138 @@ int main() {
ShouldDiagnose obj;
ShouldNotDiagnose obj1;
}
+
+namespace ExceptionInNamespace {
+ namespace N {
+ struct E {};
+ }
+ void run() throw() {
+ try {
+ throw N::E();
+ } catch (const N::E &e) {
+ }
+ }
+}
+
+namespace HandlerSpecialCases {
+ struct A {};
+ using CA = const A;
+
+ struct B : A {};
+ using CB = const B;
+
+ struct AmbigBase {};
+ struct AmbigMiddle : AmbigBase {};
+ struct AmbigDerived : AmbigBase, AmbigMiddle {}; // expected-warning {{inaccessible}}
+
+ struct PrivateBase {};
+ struct PrivateDerived : private PrivateBase { friend void bad3() throw(); };
+
+ void good() throw() {
+ try { throw CA(); } catch (volatile A&) {}
+ try { throw B(); } catch (A&) {}
+ try { throw B(); } catch (const volatile A&) {}
+ try { throw CB(); } catch (A&) {}
+ try { throw (int*)0; } catch (void* const volatile) {}
+ try { throw (int*)0; } catch (void* const &) {}
+ try { throw (B*)0; } catch (A*) {}
+ try { throw (B*)0; } catch (A* const &) {}
+ try { throw (void(*)() noexcept)0; } catch (void (*)()) {}
+ try { throw (void(*)() noexcept)0; } catch (void (*const &)()) {}
+ try { throw (int**)0; } catch (const int * const*) {}
+ try { throw (int**)0; } catch (const int * const* const&) {}
+ try { throw nullptr; } catch (int*) {}
+ try { throw nullptr; } catch (int* const&) {}
+ }
+
+ void bad1() throw() { // expected-note {{here}}
+ try { throw A(); } catch (const B&) {} // expected-warning {{still throw}}
+ }
+ void bad2() throw() { // expected-note {{here}}
+ try { throw AmbigDerived(); } catch (const AmbigBase&) {} // expected-warning {{still throw}}
+ }
+ void bad3() throw() { // expected-note {{here}}
+ try { throw PrivateDerived(); } catch (const PrivateBase&) {} // expected-warning {{still throw}}
+ }
+ void bad4() throw() { // expected-note {{here}}
+ try { throw (int*)0; } catch (void* &) {} // expected-warning {{still throw}}
+ }
+ void bad5() throw() { // expected-note {{here}}
+ try { throw (int*)0; } catch (void* const volatile &) {} // expected-warning {{still throw}}
+ }
+ void bad6() throw() { // expected-note {{here}}
+ try { throw (int* volatile)0; } catch (void* const volatile &) {} // expected-warning {{still throw}}
+ }
+ void bad7() throw() { // expected-note {{here}}
+ try { throw (AmbigDerived*)0; } catch (AmbigBase*) {} // expected-warning {{still throw}}
+ }
+ void bad8() throw() { // expected-note {{here}}
+ try { throw (PrivateDerived*)0; } catch (PrivateBase*) {} // expected-warning {{still throw}}
+ }
+ void bad9() throw() { // expected-note {{here}}
+ try { throw (B*)0; } catch (A* &) {} // expected-warning {{still throw}}
+ }
+ void bad10() throw() { // expected-note {{here}}
+ try { throw (void(*)())0; } catch (void (*)() noexcept) {} // expected-warning {{still throw}}
+ }
+ void bad11() throw() { // expected-note {{here}}
+ try { throw (int**)0; } catch (const int **) {} // expected-warning {{still throw}}
+ }
+ void bad12() throw() { // expected-note {{here}}
+ try { throw nullptr; } catch (int) {} // expected-warning {{still throw}}
+ }
+}
+
+namespace NestedTry {
+ void f() noexcept {
+ try {
+ try {
+ throw 0;
+ } catch (float) {}
+ } catch (int) {}
+ }
+
+ struct A { [[noreturn]] ~A(); };
+
+ void g() noexcept { // expected-note {{here}}
+ try {
+ try {
+ throw 0; // expected-warning {{still throw}}
+ } catch (float) {}
+ } catch (const char*) {}
+ }
+
+ void h() noexcept { // expected-note {{here}}
+ try {
+ try {
+ throw 0;
+ } catch (float) {}
+ } catch (int) {
+ throw; // expected-warning {{still throw}}
+ }
+ }
+
+ // FIXME: Ideally, this should still warn; we can track which types are
+ // potentially thrown by the rethrow.
+ void i() noexcept {
+ try {
+ try {
+ throw 0;
+ } catch (int) {
+ throw;
+ }
+ } catch (float) {}
+ }
+
+ // FIXME: Ideally, this should not warn: the second catch block is
+ // unreachable.
+ void j() noexcept { // expected-note {{here}}
+ try {
+ try {
+ throw 0;
+ } catch (int) {}
+ } catch (float) {
+ throw; // expected-warning {{still throw}}
+ }
+ }
+}
diff --git a/test/SemaCXX/warn-unreachable.cpp b/test/SemaCXX/warn-unreachable.cpp
index 08118147b751..a14e4226861c 100644
--- a/test/SemaCXX/warn-unreachable.cpp
+++ b/test/SemaCXX/warn-unreachable.cpp
@@ -102,7 +102,7 @@ void test_unreachable_templates_harness() {
test_unreachable_templates<TestUnreachableB>();
}
-// Do warn about explict template specializations, as they represent
+// Do warn about explicit template specializations, as they represent
// actual concrete functions that somebody wrote.
template <typename T> void funcToSpecialize() {}
diff --git a/test/SemaObjC/Inputs/module.map b/test/SemaObjC/Inputs/module.map
new file mode 100644
index 000000000000..492d4c368eb8
--- /dev/null
+++ b/test/SemaObjC/Inputs/module.map
@@ -0,0 +1,3 @@
+module empty {
+ header "empty.h"
+}
diff --git a/test/SemaObjC/arc-decls.m b/test/SemaObjC/arc-decls.m
index c1c319d95e3c..c728f00c7e5c 100644
--- a/test/SemaObjC/arc-decls.m
+++ b/test/SemaObjC/arc-decls.m
@@ -3,7 +3,7 @@
// rdar://8843524
struct A {
- id x; // expected-error {{ARC forbids Objective-C objects in struct}}
+ id x;
};
union u {
@@ -13,7 +13,7 @@ union u {
@interface I {
struct A a;
struct B {
- id y[10][20]; // expected-error {{ARC forbids Objective-C objects in struct}}
+ id y[10][20];
id z;
} b;
@@ -23,7 +23,7 @@ union u {
// rdar://10260525
struct r10260525 {
- id (^block) (); // expected-error {{ARC forbids blocks in struct}}
+ id (^block) ();
};
struct S {
@@ -154,3 +154,25 @@ struct __attribute__((objc_ownership(none))) S2 {}; // expected-error {{'objc_ow
@property (readwrite, weak) ControllerClass *weak_controller;
@end
+
+@interface I3
+@end
+
+@interface D3 : I3
+@end
+
+@interface D3 (Cat1)
+- (id)method;
+@end
+
+@interface I3 (Cat2)
+// FIXME: clang should diagnose mismatch between methods in D3(Cat1) and
+// I3(Cat2).
+- (id)method __attribute__((ns_returns_retained));
+@end
+
+@implementation D3
+- (id)method {
+ return (id)0;
+}
+@end
diff --git a/test/SemaObjC/arc-peformselector.m b/test/SemaObjC/arc-peformselector.m
index a7e5d3e8239e..ec385af58211 100644
--- a/test/SemaObjC/arc-peformselector.m
+++ b/test/SemaObjC/arc-peformselector.m
@@ -36,7 +36,7 @@
return [self performSelector : @selector(PlusZero)];
return [self performSelector : @selector(PlusOne)]; // expected-error {{performSelector names a selector which retains the object}}
- // Avoid the unkown selector warning for more complicated performSelector
+ // Avoid the unknown selector warning for more complicated performSelector
// variations because it produces too many false positives.
[self performSelector: sel1 withObject:0 afterDelay:0 inModes:0];
diff --git a/test/SemaObjC/arc-property-decl-attrs.m b/test/SemaObjC/arc-property-decl-attrs.m
index 7393f58199f9..6638054bef88 100644
--- a/test/SemaObjC/arc-property-decl-attrs.m
+++ b/test/SemaObjC/arc-property-decl-attrs.m
@@ -252,3 +252,38 @@ __attribute__((objc_root_class))
@synthesize prop = _prop;
@end
+
+// rdar://39024725
+// Allow strong readwrite property and a readonly one.
+@protocol StrongCollision
+
+@property(strong) NSObject *p;
+@property(copy) NSObject *p2;
+
+// expected-error@+1 {{property with attribute 'retain (or strong)' was selected for synthesis}}
+@property(strong, readwrite) NSObject *collision;
+
+@end
+
+@protocol ReadonlyCollision
+
+@property(readonly) NSObject *p;
+@property(readonly) NSObject *p2;
+
+// expected-note@+1 {{it could also be property without attribute 'retain (or strong)' declared here}}
+@property(readonly, weak) NSObject *collision;
+
+@end
+
+@interface StrongReadonlyCollision : NSObject <StrongCollision, ReadonlyCollision>
+@end
+
+@implementation StrongReadonlyCollision
+
+// no error
+@synthesize p = _p;
+@synthesize p2 = _p2;
+
+@synthesize collision = _collision; // expected-note {{property synthesized here}}
+
+@end
diff --git a/test/SemaObjC/arc-repeated-weak.mm b/test/SemaObjC/arc-repeated-weak.mm
index 37b2123ec1c4..d153eb9a52eb 100644
--- a/test/SemaObjC/arc-repeated-weak.mm
+++ b/test/SemaObjC/arc-repeated-weak.mm
@@ -479,3 +479,6 @@ void foo1() {
// expected-error@-2{{cast of 'E' to 'INTFPtrTy' (aka 'INTF *') is disallowed with ARC}}
#endif
}
+
+@class NSString;
+static NSString* const kGlobal = @"";
diff --git a/test/SemaObjC/arc-system-header.m b/test/SemaObjC/arc-system-header.m
index 68230e74b2d5..f3b72363c57b 100644
--- a/test/SemaObjC/arc-system-header.m
+++ b/test/SemaObjC/arc-system-header.m
@@ -23,8 +23,7 @@ void test4(Test4 *p) {
}
void test5(struct Test5 *p) {
- p->field = 0; // expected-error {{'field' is unavailable in ARC}}
- // expected-note@arc-system-header.h:25 {{field has non-trivial ownership qualification}}
+ p->field = 0;
}
id test6() {
@@ -49,8 +48,7 @@ void test7(Test7 *p) {
extern void doSomething(Test9 arg);
void test9() {
- Test9 foo2 = {0, 0}; // expected-error {{'field' is unavailable in ARC}}
- // expected-note@arc-system-header.h:56 {{field has non-trivial ownership qualification}}
+ Test9 foo2 = {0, 0};
doSomething(foo2);
}
#endif
diff --git a/test/SemaObjC/arc.m b/test/SemaObjC/arc.m
index e90d0a87e311..fcac798ff2d1 100644
--- a/test/SemaObjC/arc.m
+++ b/test/SemaObjC/arc.m
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fsyntax-only -fobjc-arc -fblocks -verify -Wno-objc-root-class %s
-// RUN: not %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fsyntax-only -fobjc-arc -fblocks -Wno-objc-root-class -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+// RUN: not %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fsyntax-only -fobjc-arc -fblocks -Wno-objc-root-class -fdiagnostics-parseable-fixits %s 2>&1
typedef unsigned long NSUInteger;
typedef const void * CFTypeRef;
@@ -811,23 +811,17 @@ int garf() {
}
void block_capture_autoreleasing(A * __autoreleasing *a,
- A **b, // expected-note {{declare the parameter __autoreleasing explicitly to suppress this warning}} expected-note {{declare the parameter __strong or capture a __block __strong variable to keep values alive across autorelease pools}}
- A * _Nullable *c, // expected-note {{declare the parameter __autoreleasing explicitly to suppress this warning}} expected-note {{declare the parameter __strong or capture a __block __strong variable to keep values alive across autorelease pools}}
+ A **b, // expected-note {{declare the parameter __strong or capture a __block __strong variable to keep values alive across autorelease pools}}
+ A * _Nullable *c, // expected-note {{declare the parameter __strong or capture a __block __strong variable to keep values alive across autorelease pools}}
A * _Nullable __autoreleasing *d,
- A ** _Nullable e, // expected-note {{declare the parameter __autoreleasing explicitly to suppress this warning}} expected-note {{declare the parameter __strong or capture a __block __strong variable to keep values alive across autorelease pools}}
+ A ** _Nullable e, // expected-note {{declare the parameter __strong or capture a __block __strong variable to keep values alive across autorelease pools}}
A * __autoreleasing * _Nullable f,
id __autoreleasing *g,
- id *h, // expected-note {{declare the parameter __autoreleasing explicitly to suppress this warning}} expected-note {{declare the parameter __strong or capture a __block __strong variable to keep values alive across autorelease pools}}
- id _Nullable *i, // expected-note {{declare the parameter __autoreleasing explicitly to suppress this warning}} expected-note {{declare the parameter __strong or capture a __block __strong variable to keep values alive across autorelease pools}}
+ id *h, // expected-note {{declare the parameter __strong or capture a __block __strong variable to keep values alive across autorelease pools}}
+ id _Nullable *i, // expected-note {{declare the parameter __strong or capture a __block __strong variable to keep values alive across autorelease pools}}
id _Nullable __autoreleasing *j,
- id * _Nullable k, // expected-note {{declare the parameter __autoreleasing explicitly to suppress this warning}} expected-note {{declare the parameter __strong or capture a __block __strong variable to keep values alive across autorelease pools}}
+ id * _Nullable k, // expected-note {{declare the parameter __strong or capture a __block __strong variable to keep values alive across autorelease pools}}
id __autoreleasing * _Nullable l) {
- // CHECK: fix-it:"{{.*}}":{[[@LINE-11]]:37-[[@LINE-11]]:37}:" __autoreleasing "
- // CHECK: fix-it:"{{.*}}":{[[@LINE-11]]:47-[[@LINE-11]]:47}:" __autoreleasing"
- // CHECK: fix-it:"{{.*}}":{[[@LINE-10]]:37-[[@LINE-10]]:37}:" __autoreleasing "
- // CHECK: fix-it:"{{.*}}":{[[@LINE-8]]:36-[[@LINE-8]]:36}:" __autoreleasing"
- // CHECK: fix-it:"{{.*}}":{[[@LINE-8]]:46-[[@LINE-8]]:46}:" __autoreleasing"
- // CHECK: fix-it:"{{.*}}":{[[@LINE-7]]:36-[[@LINE-7]]:36}:" __autoreleasing"
^{
(void)*a;
(void)*b; // expected-warning {{block captures an autoreleasing out-parameter, which may result in use-after-free bugs}}
diff --git a/test/SemaObjC/attr-availability-1.m b/test/SemaObjC/attr-availability-1.m
index d3d400037853..cd7968fc7294 100644
--- a/test/SemaObjC/attr-availability-1.m
+++ b/test/SemaObjC/attr-availability-1.m
@@ -25,10 +25,10 @@
// rdar://11475360
@interface B : A
- (void)method; // NOTE: we expect 'method' to *not* inherit availability.
-- (void)overridden __attribute__((availability(macosx,introduced=10_4))); // expected-warning{{overriding method introduced after overridden method on macOS (10_4 vs. 10_3)}}
+- (void)overridden __attribute__((availability(macosx,introduced=10_4))); // expected-warning{{overriding method introduced after overridden method on macOS (10.4 vs. 10.3)}}
- (void)overridden2 __attribute__((availability(macosx,introduced=10_2)));
- (void)overridden3 __attribute__((availability(macosx,deprecated=10_4)));
-- (void)overridden4 __attribute__((availability(macosx,deprecated=10_2))); // expected-warning{{overriding method deprecated before overridden method on macOS (10_3 vs. 10_2)}}
+- (void)overridden4 __attribute__((availability(macosx,deprecated=10_2))); // expected-warning{{overriding method deprecated before overridden method on macOS (10.3 vs. 10.2)}}
- (void)overridden5 __attribute__((availability(macosx,introduced=10_3)));
- (void)overridden6 __attribute__((availability(macosx,unavailable))); // expected-warning{{overriding method cannot be unavailable on macOS when its overridden method is available}}
@end
diff --git a/test/SemaObjC/attr-deprecated-replacement-fixit.m b/test/SemaObjC/attr-deprecated-replacement-fixit.m
new file mode 100644
index 000000000000..9d0fcf91a2e0
--- /dev/null
+++ b/test/SemaObjC/attr-deprecated-replacement-fixit.m
@@ -0,0 +1,177 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -verify -fsyntax-only %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck --implicit-check-not fix-it: %s
+// RUN: cp %s %t
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -DIGNORE_UNSUCCESSFUL_RENAMES -fixit -x objective-c %t
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -DIGNORE_UNSUCCESSFUL_RENAMES -Werror -x objective-c %t
+
+#if !__has_feature(attribute_deprecated_with_replacement)
+#error "Missing __has_feature"
+#endif
+
+#if !__has_feature(attribute_availability_with_replacement)
+#error "Missing __has_feature"
+#endif
+
+#define DEPRECATED(replacement) __attribute__((deprecated("message", replacement)))
+
+@protocol SuccessfulMultiParameterRenames
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)multi:(int)param1 parameter:(int)param2 replacement:(int)param3 DEPRECATED("multi_new:parameter_new:replace_new_ment:");
+- (void)multi_new:(int)param1 parameter_new:(int)param2 replace_new_ment:(int)param3;
+
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)varArgs:(int)params, ... DEPRECATED("renameVarArgs:");
+- (void)renameVarArgs:(int)params, ...;
+
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)leadingMinus:(int)param DEPRECATED("-leadingMinusRenamed:");
+- (void)leadingMinusRenamed:(int)param;
+
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)leadingPlus:(int)param DEPRECATED("+leadingPlusRenamed:");
+- (void)leadingPlusRenamed:(int)param;
+
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)sourceEmptyName:(int)param1 :(int)param2 DEPRECATED("renameEmptyName:toNonEmpty:");
+- (void)renameEmptyName:(int)param1 toNonEmpty:(int)param2;
+
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)target:(int)param1 willBecomeEmpty:(int)param2 emptyName:(int)param3 DEPRECATED("target::emptyName:");
+- (void)target:(int)param1 :(int)param2 emptyName:(int)param3;
+
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)extra:(int)param1 whiteSpace:(int)param2 DEPRECATED("renameExtra:whiteSpace:");
+- (void)renameExtra:(int)param1 whiteSpace:(int)param2;
+
+// Test renaming that was producing valid code earlier is still producing valid
+// code. The difference is that now we detect different number of parameters.
+//
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)singleArgumentRegression:(int)param DEPRECATED("renameSingleArgument");
+- (void)renameSingleArgument:(int)param;
+@end
+
+void successfulRenames(id<SuccessfulMultiParameterRenames> object) {
+ [object multi:0 parameter:1 replacement:2]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:16}:"multi_new"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:19-[[@LINE-2]]:28}:"parameter_new"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:31-[[@LINE-3]]:42}:"replace_new_ment"
+
+ [object varArgs:1, 2, 3, 0]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:18}:"renameVarArgs"
+
+ [object leadingMinus:0]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:23}:"leadingMinusRenamed"
+
+ [object leadingPlus:0]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:22}:"leadingPlusRenamed"
+
+ [object sourceEmptyName:0 :1]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:26}:"renameEmptyName"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:29-[[@LINE-2]]:29}:"toNonEmpty"
+
+ [object target:0 willBecomeEmpty:1 emptyName:2]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:17}:"target"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:20-[[@LINE-2]]:35}:""
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:38-[[@LINE-3]]:47}:"emptyName"
+
+ [object extra: 0 whiteSpace: 1]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:16}:"renameExtra"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:23-[[@LINE-2]]:33}:"whiteSpace"
+
+ [object singleArgumentRegression:0]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:35}:"renameSingleArgument"
+}
+
+#ifndef IGNORE_UNSUCCESSFUL_RENAMES
+@protocol UnsuccessfulMultiParameterRenames
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)differentNumberOfParameters:(int)param DEPRECATED("rename:hasMoreParameters:");
+
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)differentNumber:(int)param1 ofParameters:(int)param2 DEPRECATED("renameHasLessParameters:");
+
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)methodLike:(int)param1 replacement:(int)param2 DEPRECATED("noColon:atTheEnd");
+
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)freeFormText DEPRECATED("Use something else");
+
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)freeFormTextReplacementStartsAsMethod DEPRECATED("-Use something different");
+
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)replacementHasSingleSkipCharacter DEPRECATED("-");
+
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)replacementHasInvalid:(int)param1 slotName:(int)param2 DEPRECATED("renameWith:1nonIdentifier:");
+@end
+
+void unsuccessfulRenames(id<UnsuccessfulMultiParameterRenames> object) {
+ [object differentNumberOfParameters:0]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:38}:"rename:hasMoreParameters:"
+
+ [object differentNumber:0 ofParameters:1]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:26}:"renameHasLessParameters:"
+
+ [object methodLike:0 replacement:1]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:21}:"noColon:atTheEnd"
+
+ [object freeFormText]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:23}:"Use something else"
+
+ [object freeFormTextReplacementStartsAsMethod]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:48}:"-Use something different"
+
+ [object replacementHasSingleSkipCharacter]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:44}:"-"
+
+ [object replacementHasInvalid:0 slotName:1]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:32}:"renameWith:1nonIdentifier:"
+}
+#endif // IGNORE_UNSUCCESSFUL_RENAMES
+
+// Make sure classes are treated the same way as protocols.
+__attribute__((objc_root_class))
+@interface Interface
+// expected-note@+1 {{has been explicitly marked deprecated here}}
++ (void)classMethod:(int)param1 replacement:(int)param2 DEPRECATED("renameClassMethod:replace_new_ment:");
++ (void)renameClassMethod:(int)param1 replace_new_ment:(int)param2;
+
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)multi:(int)param1 parameter:(int)param2 replacement:(int)param3 DEPRECATED("multi_new:parameter_new:replace_new_ment:");
+- (void)multi_new:(int)param1 parameter_new:(int)param2 replace_new_ment:(int)param3;
+@end
+
+@implementation Interface
++ (void)classMethod:(int)param1 replacement:(int)param2 {}
++ (void)renameClassMethod:(int)param1 replace_new_ment:(int)param2 {}
+
+- (void)multi:(int)param1 parameter:(int)param2 replacement:(int)param3 {}
+- (void)multi_new:(int)param1 parameter_new:(int)param2 replace_new_ment:(int)param3 {}
+
+- (void)usage {
+ [Interface classMethod:0 replacement:1]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:14-[[@LINE-1]]:25}:"renameClassMethod"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:28-[[@LINE-2]]:39}:"replace_new_ment"
+
+ [self multi:0 parameter:1 replacement:2]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:14}:"multi_new"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:17-[[@LINE-2]]:26}:"parameter_new"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:29-[[@LINE-3]]:40}:"replace_new_ment"
+}
+@end
+
+// Make sure availability attribute is handled the same way as deprecation attribute.
+@protocol AvailabilityAttributeRenames
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)multi:(int)param1 parameter:(int)param2 replacement:(int)param3 __attribute__((availability(macosx,deprecated=9.0,replacement="multi_new:parameter_new:replace_new_ment:")));
+- (void)multi_new:(int)param1 parameter_new:(int)param2 replace_new_ment:(int)param3;
+@end
+
+void availabilityAttributeRenames(id<AvailabilityAttributeRenames> object) {
+ [object multi:0 parameter:1 replacement:2]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:16}:"multi_new"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:19-[[@LINE-2]]:28}:"parameter_new"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:31-[[@LINE-3]]:42}:"replace_new_ment"
+}
diff --git a/test/SemaObjC/avoid-unavailable-implementation-warning-in-app-extension.m b/test/SemaObjC/avoid-unavailable-implementation-warning-in-app-extension.m
new file mode 100644
index 000000000000..06872a9cab36
--- /dev/null
+++ b/test/SemaObjC/avoid-unavailable-implementation-warning-in-app-extension.m
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -fapplication-extension -Wdeprecated-implementations -verify -Wno-objc-root-class %s
+// RUN: %clang_cc1 -triple arm64-apple-tvos11 -fapplication-extension -Wdeprecated-implementations -verify -Wno-objc-root-class %s
+// Declarations marked as 'unavailable' in an app extension should not generate a
+// warning on implementation.
+
+@interface Parent
+- (void)ok __attribute__((availability(ios_app_extension,unavailable,message="not available")));
+- (void)reallyUnavail __attribute__((availability(ios,unavailable))); // expected-note {{method 'reallyUnavail' declared here}}
+- (void)reallyUnavail2 __attribute__((unavailable)); // expected-note {{method 'reallyUnavail2' declared here}}
+@end
+
+@interface Child : Parent
+@end
+
+@implementation Child
+
+- (void)ok { // no warning.
+}
+- (void)reallyUnavail { // expected-warning {{implementing unavailable method}}
+}
+- (void)reallyUnavail2 { // expected-warning {{implementing unavailable method}}
+}
+
+@end
diff --git a/test/SemaObjC/block-compare.mm b/test/SemaObjC/block-compare.mm
new file mode 100644
index 000000000000..c63f484a80aa
--- /dev/null
+++ b/test/SemaObjC/block-compare.mm
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1 -S -o - -triple i686-windows -verify -fblocks \
+// RUN: -Wno-unused-comparison %s
+
+#pragma clang diagnostic ignored "-Wunused-comparison"
+
+#define nil ((id)nullptr)
+
+@protocol NSObject
+@end
+
+@protocol NSCopying
+@end
+
+@protocol OtherProtocol
+@end
+
+__attribute__((objc_root_class))
+@interface NSObject <NSObject, NSCopying>
+@end
+
+__attribute__((objc_root_class))
+@interface Test
+@end
+
+int main() {
+ void (^block)() = ^{};
+ NSObject *object;
+ id<NSObject, NSCopying> qualifiedId;
+
+ id<OtherProtocol> poorlyQualified1;
+ Test *objectOfWrongType;
+
+ block == nil;
+ block == object;
+ block == qualifiedId;
+
+ nil == block;
+ object == block;
+ qualifiedId == block;
+
+ // these are still not valid: blocks must be compared with id, NSObject*, or a protocol-qualified id
+ // conforming to NSCopying or NSObject.
+
+ block == poorlyQualified1; // expected-error {{invalid operands to binary expression ('void (^)()' and 'id<OtherProtocol>')}}
+ block == objectOfWrongType; // expected-error {{invalid operands to binary expression ('void (^)()' and 'Test *')}}
+
+ poorlyQualified1 == block; // expected-error {{invalid operands to binary expression ('id<OtherProtocol>' and 'void (^)()')}}
+ objectOfWrongType == block; // expected-error {{invalid operands to binary expression ('Test *' and 'void (^)()')}}
+
+ return 0;
+}
diff --git a/test/SemaObjC/catch-invalid.m b/test/SemaObjC/catch-invalid.m
new file mode 100644
index 000000000000..352b2fbaa8ed
--- /dev/null
+++ b/test/SemaObjC/catch-invalid.m
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -triple thumbv7-unknown-windows-msvc -fobjc-exceptions -fobjc-runtime=ios -verify %s
+
+extern void g(void);
+void f() {
+ @try {
+ g();
+ } @catch (Class c) { // expected-error{{@catch parameter is not a pointer to an interface type}}
+ }
+}
diff --git a/test/SemaObjC/class-unavail-warning.m b/test/SemaObjC/class-unavail-warning.m
index f7d8f569ca67..30ebf7939edf 100644
--- a/test/SemaObjC/class-unavail-warning.m
+++ b/test/SemaObjC/class-unavail-warning.m
@@ -115,9 +115,9 @@ UNAVAILABLE __attribute__((objc_root_class))
}
@end
-typedef int unavailable_int UNAVAILABLE;
+typedef int unavailable_int UNAVAILABLE; // expected-note {{'unavailable_int' has been explicitly marked unavailable here}}
UNAVAILABLE
@interface A
-extern unavailable_int global_unavailable; // FIXME: this should be an error!
+extern unavailable_int global_unavailable; // expected-error {{'unavailable_int' is unavailable: not available}}
@end
diff --git a/test/SemaObjC/compare-qualified-class.m b/test/SemaObjC/compare-qualified-class.m
index a52561521444..c7d4a2ec1a39 100644
--- a/test/SemaObjC/compare-qualified-class.m
+++ b/test/SemaObjC/compare-qualified-class.m
@@ -53,7 +53,7 @@ int main () {
@implementation OtherClass
- (ClassA<ProtocolY> *)aMethod {
// This does not work, even though ClassB subclasses from A and conforms to Y
- // because the property type explicity adds ProtocolX conformance
+ // because the property type explicitly adds ProtocolX conformance
// even though ClassB already conforms to ProtocolX
return self.aProperty;
}
diff --git a/test/SemaObjC/comptypes-legal.m b/test/SemaObjC/comptypes-legal.m
index 05f18977cc4e..7ac4e143338a 100644
--- a/test/SemaObjC/comptypes-legal.m
+++ b/test/SemaObjC/comptypes-legal.m
@@ -42,7 +42,7 @@ void foo(void)
- (void) Meth : (id <NSCopying>)aKey; // expected-note {{passing argument to parameter 'aKey' here}}
@end
-@class ForwarClass; // expected-note 3 {{conformance of forward class ForwarClass to protocol NSCopying can not be confirmed}}
+@class ForwarClass; // expected-note 3 {{conformance of forward class 'ForwarClass' to protocol 'NSCopying' can not be confirmed}}
ForwarClass *Test10751015 (I* pi, ForwarClass *ns_forward) {
diff --git a/test/SemaObjC/finally-msvc.m b/test/SemaObjC/finally-msvc.m
new file mode 100644
index 000000000000..5db08a7f7100
--- /dev/null
+++ b/test/SemaObjC/finally-msvc.m
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -triple i686--windows-msvc -fexceptions -fobjc-exceptions -ast-dump %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64--windows-msvc -fexceptions -fobjc-exceptions -ast-dump %s 2>&1 | FileCheck %s
+
+void f() {
+ @try {
+ } @finally {
+ }
+}
+
+// CHECK: ObjCAtFinallyStmt
+// CHECK-NEXT: CapturedStmt
+// CHECK-NEXT: CapturedDecl
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ImplicitParamDecl
diff --git a/test/SemaObjC/foreachtemplatized.mm b/test/SemaObjC/foreachtemplatized.mm
new file mode 100644
index 000000000000..ab2770a7cefb
--- /dev/null
+++ b/test/SemaObjC/foreachtemplatized.mm
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -fobjc-arc -Wno-objc-root-class -std=c++11 -ast-dump %s | FileCheck %s
+
+// CHECK-NOT: ImplicitValueInitExpr
+
+@interface I
+@end
+
+template <typename T>
+void decode(I *p) {
+ for (I *k in p) {}
+}
+
+void decode(I *p) {
+ decode<int>(p);
+}
diff --git a/test/SemaObjC/format-size-spec-nsinteger.m b/test/SemaObjC/format-size-spec-nsinteger.m
new file mode 100644
index 000000000000..e7c0a0dd1011
--- /dev/null
+++ b/test/SemaObjC/format-size-spec-nsinteger.m
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -triple thumbv7-apple-ios -Wno-objc-root-class -fsyntax-only -verify -Wformat %s
+// RUN: %clang_cc1 -triple thumbv7-apple-ios -Wno-objc-root-class -fsyntax-only -verify -Wformat-pedantic -DPEDANTIC %s
+// RUN: %clang_cc1 -triple thumbv7k-apple-watchos2.0.0 -fsyntax-only -fblocks -verify %s
+// RUN: %clang_cc1 -triple thumbv7k-apple-watchos2.0.0 -fsyntax-only -fblocks -verify -Wformat-pedantic -DPEDANTIC %s
+
+#if !defined(PEDANTIC)
+// expected-no-diagnostics
+#endif
+
+#if __LP64__
+typedef unsigned long NSUInteger;
+typedef long NSInteger;
+typedef long ptrdiff_t;
+#else
+typedef unsigned int NSUInteger;
+typedef int NSInteger;
+#if __is_target_os(watchos)
+ // Watch ABI uses long for ptrdiff_t.
+ typedef long ptrdiff_t;
+#else
+ typedef int ptrdiff_t;
+#endif
+#endif
+
+@class NSString;
+
+extern void NSLog(NSString *format, ...);
+
+void testSizeSpecifier() {
+ NSInteger i = 0;
+ NSUInteger j = 0;
+ NSLog(@"max NSInteger = %zi", i);
+ NSLog(@"max NSUinteger = %zu", j);
+
+#if defined(PEDANTIC)
+ // expected-warning@-4 {{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}}
+ // expected-warning@-4 {{values of type 'NSUInteger' should not be used as format arguments; add an explicit cast to 'unsigned long' instead}}
+#endif
+}
+
+void testPtrdiffSpecifier(ptrdiff_t x) {
+ NSInteger i = 0;
+ NSUInteger j = 0;
+
+ NSLog(@"ptrdiff_t NSUinteger: %tu", j);
+ NSLog(@"ptrdiff_t NSInteger: %td", i);
+ NSLog(@"ptrdiff_t %tu, %td", x, x);
+#if __is_target_os(watchos) && defined(PEDANTIC)
+ // expected-warning@-4 {{values of type 'NSUInteger' should not be used as format arguments; add an explicit cast to 'unsigned long' instead}}
+ // expected-warning@-4 {{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}}
+#endif
+}
diff --git a/test/SemaObjC/incomplete-implementation.m b/test/SemaObjC/incomplete-implementation.m
index 74dea2aa86b9..910cda5f07d1 100644
--- a/test/SemaObjC/incomplete-implementation.m
+++ b/test/SemaObjC/incomplete-implementation.m
@@ -13,6 +13,13 @@
- Meth {return 0;} // expected-warning {{category is implementing a method which will also be implemented by its primary class}}
@end
+// rdar://40634455
+@interface MyClass
+-(void)mymeth __attribute__((availability(macos, introduced=100))); // expected-note{{here}}
+@end
+@implementation MyClass // expected-warning{{'mymeth' not found}}
+@end
+
#pragma GCC diagnostic ignored "-Wincomplete-implementation"
@interface I2
- Meth; // expected-note{{method 'Meth' declared here}}
diff --git a/test/SemaObjC/integer-overflow.m b/test/SemaObjC/integer-overflow.m
new file mode 100644
index 000000000000..6d82e2951c1e
--- /dev/null
+++ b/test/SemaObjC/integer-overflow.m
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -Wno-objc-root-class -fsyntax-only -verify %s
+
+@interface Foo
+@end
+
+@implementation Foo
+- (int)add:(int)a with:(int)b {
+ return a + b;
+}
+
+- (void)testIntegerOverflows {
+// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+ (void)[self add:0 with:4608 * 1024 * 1024];
+
+// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+ (void)[self add:0 with:[self add:4608 * 1024 * 1024 with:0]];
+}
+@end
diff --git a/test/SemaObjC/ns-consumed-error-not-warning.m b/test/SemaObjC/ns-consumed-error-not-warning.m
new file mode 100644
index 000000000000..f44cc8f0f60b
--- /dev/null
+++ b/test/SemaObjC/ns-consumed-error-not-warning.m
@@ -0,0 +1,13 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fsyntax-only -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs -fobjc-arc -verify -fblocks -triple x86_64-apple-darwin10.0.0 -DOBJCARC %s
+// rdar://36265651
+
+@interface A
+-(void) m:(id)p; // expected-note {{parameter declared here}}
+@end
+
+@interface B : A
+-(void) m:(__attribute__((ns_consumed)) id)p; // expected-error {{overriding method has mismatched ns_consumed attribute on its parameter}}
+@end
+
+@import empty;
diff --git a/test/SemaObjC/nullability.m b/test/SemaObjC/nullability.m
index cbfe132d143e..93f4d1d4994a 100644
--- a/test/SemaObjC/nullability.m
+++ b/test/SemaObjC/nullability.m
@@ -279,3 +279,14 @@ void test(ArraysInMethods *obj) {
[obj simpleSugar:0]; // expected-warning {{null passed to a callee that requires a non-null argument}}
[obj sugarWithTypedef:0]; // expected-warning {{null passed to a callee that requires a non-null argument}}
}
+
+// Check that we don't propagate the nullability specifier on the receiver to
+// the result type of a message send if the result type cannot have a
+// nullability specifier.
+@interface C0
+-(int) count;
+@end
+
+void testMessageSendResultType(C0 * _Nullable c0) {
+ int *p = [c0 count]; // expected-warning {{incompatible integer to pointer conversion initializing 'int *' with an expression of type 'int'}}
+}
diff --git a/test/SemaObjC/property-10.m b/test/SemaObjC/property-10.m
index b2aaf2b1a180..7bd0d3be0803 100644
--- a/test/SemaObjC/property-10.m
+++ b/test/SemaObjC/property-10.m
@@ -24,7 +24,7 @@
@property(unsafe_unretained, copy, retain) id p4_3; // expected-error {{property attributes 'unsafe_unretained' and 'copy' are mutually exclusive}}, expected-error {{property attributes 'unsafe_unretained' and 'retain' are mutually exclusive}}
@property(unsafe_unretained, copy, strong) id s4_3; // expected-error {{property attributes 'unsafe_unretained' and 'copy' are mutually exclusive}}, expected-error {{property attributes 'unsafe_unretained' and 'strong' are mutually exclusive}}
-@property id p4; // expected-warning {{no 'assign', 'retain', or 'copy' attribute is specified - 'assign' is assumed}}, expected-warning {{default property attribute 'assign' not appropriate for non-GC object}}
+@property id p4; // expected-warning {{no 'assign', 'retain', or 'copy' attribute is specified - 'assign' is assumed}}, expected-warning {{default property attribute 'assign' not appropriate for object}}
@property(nonatomic,copy) int (^includeMailboxCondition)();
@property(nonatomic,copy) int (*includeMailboxCondition2)(); // expected-error {{property with 'copy' attribute must be of object type}}
diff --git a/test/SemaObjC/property-deprecated-warning.m b/test/SemaObjC/property-deprecated-warning.m
index 8cf4f9731bc4..0591c78fba4a 100644
--- a/test/SemaObjC/property-deprecated-warning.m
+++ b/test/SemaObjC/property-deprecated-warning.m
@@ -167,3 +167,14 @@ void testUserAccessorAttributes(Foo *foo) {
foo.x = foo.x; // expected-error {{property access is using 'x' method which is unavailable}} \
// expected-warning {{property access is using 'setX:' method which is deprecated}}
}
+
+// test implicit property does not emit duplicated warning.
+@protocol Foo
+- (int)size __attribute__((availability(ios,deprecated=3.0))); // expected-note {{'size' has been explicitly marked deprecated here}}
+- (void)setSize: (int)x __attribute__((availability(ios,deprecated=2.0))); // expected-note {{'setSize:' has been explicitly marked deprecated here}}
+@end
+
+void testImplicitProperty(id<Foo> object) {
+ object.size = object.size; // expected-warning {{'size' is deprecated: first deprecated in iOS 3.0}} \
+ // expected-warning {{'setSize:' is deprecated: first deprecated in iOS 2.0}}
+}
diff --git a/test/SemaObjC/property-ivar-mismatch.m b/test/SemaObjC/property-ivar-mismatch.m
index 148fa8ebb27f..3e2ae7eba122 100644
--- a/test/SemaObjC/property-ivar-mismatch.m
+++ b/test/SemaObjC/property-ivar-mismatch.m
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -verify -Wno-objc-root-class %s
-// Test that arithmatic types on property and its ivar have exact match.
+// Test that arithmetic types on property and its ivar have exact match.
@interface Test4
{
diff --git a/test/SemaObjC/property.m b/test/SemaObjC/property.m
index 748544717386..b67ac37b85e6 100644
--- a/test/SemaObjC/property.m
+++ b/test/SemaObjC/property.m
@@ -6,7 +6,7 @@
int name;
}
@property int d1;
-@property id prop_id; // expected-warning {{no 'assign', 'retain', or 'copy' attribute is specified - 'assign' is assumed}}, expected-warning {{default property attribute 'assign' not appropriate for non-GC object}}
+@property id prop_id; // expected-warning {{no 'assign', 'retain', or 'copy' attribute is specified - 'assign' is assumed}}, expected-warning {{default property attribute 'assign' not appropriate for object}}
@property int name;
@end
diff --git a/test/SemaObjC/protocol-expr-neg-1.m b/test/SemaObjC/protocol-expr-neg-1.m
index aed56c016b08..26cdac70ae8d 100644
--- a/test/SemaObjC/protocol-expr-neg-1.m
+++ b/test/SemaObjC/protocol-expr-neg-1.m
@@ -12,7 +12,7 @@
int main()
{
Protocol *proto = @protocol(p1);
- Protocol *fproto = @protocol(fproto); // expected-warning {{@protocol is using a forward protocol declaration of fproto}}
+ Protocol *fproto = @protocol(fproto); // expected-warning {{@protocol is using a forward protocol declaration of 'fproto'}}
Protocol *pp = @protocol(i); // expected-error {{cannot find protocol declaration for 'i'}}
Protocol *p1p = @protocol(cl); // expected-error {{cannot find protocol declaration for 'cl'}}
}
@@ -26,9 +26,9 @@ int main()
@end
int doesConform(id foo) {
- return [foo conformsToProtocol:@protocol(TestProtocol)]; // expected-warning {{@protocol is using a forward protocol declaration of TestProtocol}}
+ return [foo conformsToProtocol:@protocol(TestProtocol)]; // expected-warning {{@protocol is using a forward protocol declaration of 'TestProtocol'}}
}
int doesConformSuper(id foo) {
- return [foo conformsToProtocol:@protocol(SuperProtocol)]; // expected-warning {{@protocol is using a forward protocol declaration of SuperProtocol}}
+ return [foo conformsToProtocol:@protocol(SuperProtocol)]; // expected-warning {{@protocol is using a forward protocol declaration of 'SuperProtocol'}}
}
diff --git a/test/SemaObjC/scope-check.m b/test/SemaObjC/scope-check.m
index b52e7a06ffc2..b23edd1240f9 100644
--- a/test/SemaObjC/scope-check.m
+++ b/test/SemaObjC/scope-check.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -fobjc-exceptions -Wno-objc-root-class %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.10 -fsyntax-only -verify -fobjc-exceptions -Wno-objc-root-class %s
@class A, B, C;
diff --git a/test/SemaObjC/strong-in-c-struct.m b/test/SemaObjC/strong-in-c-struct.m
new file mode 100644
index 000000000000..5dd5f94af830
--- /dev/null
+++ b/test/SemaObjC/strong-in-c-struct.m
@@ -0,0 +1,56 @@
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -fsyntax-only -verify %s
+
+typedef struct {
+ id a;
+} Strong;
+
+void callee_variadic(const char *, ...);
+
+void test_variadic(void) {
+ Strong t;
+ callee_variadic("s", t); // expected-error {{cannot pass non-trivial C object of type 'Strong' by value to variadic function}}
+}
+
+void test_jump0(int cond) {
+ switch (cond) {
+ case 0:
+ ;
+ Strong x; // expected-note {{jump bypasses initialization of variable of non-trivial C struct type}}
+ break;
+ case 1: // expected-error {{cannot jump from switch statement to this case label}}
+ x.a = 0;
+ break;
+ }
+}
+
+void test_jump1(void) {
+ static void *ips[] = { &&L0 };
+L0: // expected-note {{possible target of indirect goto}}
+ ;
+ Strong x; // expected-note {{jump exits scope of variable with non-trivial destructor}}
+ goto *ips; // expected-error {{cannot jump}}
+}
+
+typedef void (^BlockTy)(void);
+void func(BlockTy);
+void func2(Strong);
+
+void test_block_scope0(int cond) {
+ Strong x; // expected-note {{jump enters lifetime of block which captures a C struct that is non-trivial to destroy}}
+ switch (cond) {
+ case 0:
+ func(^{ func2(x); });
+ break;
+ default: // expected-error {{cannot jump from switch statement to this case label}}
+ break;
+ }
+}
+
+void test_block_scope1(void) {
+ static void *ips[] = { &&L0 };
+L0: // expected-note {{possible target of indirect goto}}
+ ;
+ Strong x; // expected-note {{jump exits scope of variable with non-trivial destructor}} expected-note {{jump exits lifetime of block which captures a C struct that is non-trivial to destroy}}
+ func(^{ func2(x); });
+ goto *ips; // expected-error {{cannot jump}}
+}
diff --git a/test/SemaObjC/undef-class-property-error.m b/test/SemaObjC/undef-class-property-error.m
new file mode 100644
index 000000000000..e7e5db41efbe
--- /dev/null
+++ b/test/SemaObjC/undef-class-property-error.m
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+@implementation I (C) // expected-error {{cannot find interface declaration for 'I'}}
+
++ (void)f {
+ self.m; // expected-error {{member reference base type 'Class' is not a structure or union}}
+}
+
+@end
diff --git a/test/SemaObjC/unguarded-availability-category-protocol-use.m b/test/SemaObjC/unguarded-availability-category-protocol-use.m
new file mode 100644
index 000000000000..d2eb9f4841be
--- /dev/null
+++ b/test/SemaObjC/unguarded-availability-category-protocol-use.m
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple arm64-apple-ios10 -Wunguarded-availability -fblocks -fsyntax-only -verify %s
+
+__attribute__((availability(ios,unavailable)))
+@protocol Prot // expected-note {{here}}
+
+@end
+
+@interface A
+@end
+
+__attribute__((availability(ios,unavailable)))
+@interface A (Cat) <Prot> // No error.
+@end
+
+__attribute__((availability(tvos,unavailable)))
+@interface B @end
+@interface B (Cat) <Prot> // expected-error {{'Prot' is unavailable: not available on iOS}}
+@end
diff --git a/test/SemaObjC/unguarded-availability.m b/test/SemaObjC/unguarded-availability.m
index b34cd0f9822c..39c631097985 100644
--- a/test/SemaObjC/unguarded-availability.m
+++ b/test/SemaObjC/unguarded-availability.m
@@ -7,7 +7,7 @@
typedef int AVAILABLE_10_12 new_int; // expected-note + {{marked partial here}}
-int func_10_11() AVAILABLE_10_11; // expected-note 4 {{'func_10_11' has been explicitly marked partial here}}
+int func_10_11() AVAILABLE_10_11; // expected-note 8 {{'func_10_11' has been explicitly marked partial here}}
#ifdef OBJCPP
// expected-note@+2 6 {{marked partial here}}
@@ -311,3 +311,45 @@ void switchAnimals(Animals a) {
(void)AK_Cat; // no warning
(void)AK_CyborgCat; // expected-warning{{'AK_CyborgCat' is only available on macOS 10.12 or newer}} expected-note {{@available}}
}
+
+
+// test static initializers has the same availability as the deployment target and it cannot be overwritten.
+@interface HasStaticInitializer : BaseClass
++ (void)load AVAILABLE_10_11; // expected-warning{{ignoring availability attribute on '+load' method}}
+@end
+
+@implementation HasStaticInitializer
++ (void)load {
+ func_10_11(); // expected-warning{{'func_10_11' is only available on macOS 10.11 or newer}} expected-note{{enclose 'func_10_11' in an @available check to silence this warning}}
+}
+@end
+
+// test availability from interface is ignored when checking the unguarded availability in +load method.
+AVAILABLE_10_11
+@interface HasStaticInitializer1 : BaseClass
++ (void)load;
++ (void)load: (int)x; // no warning.
+@end
+
+@implementation HasStaticInitializer1
++ (void)load {
+ func_10_11(); // expected-warning{{'func_10_11' is only available on macOS 10.11 or newer}} expected-note{{enclose 'func_10_11' in an @available check to silence this warning}}
+}
++ (void)load: (int)x {
+ func_10_11(); // no warning.
+}
+@end
+
+__attribute__((constructor))
+void is_constructor();
+
+AVAILABLE_10_11 // expected-warning{{ignoring availability attribute with constructor attribute}}
+void is_constructor() {
+ func_10_11(); // expected-warning{{'func_10_11' is only available on macOS 10.11 or newer}} expected-note{{enclose 'func_10_11' in an @available check to silence this warning}}
+}
+
+AVAILABLE_10_11 // expected-warning{{ignoring availability attribute with destructor attribute}}
+__attribute__((destructor))
+void is_destructor() {
+ func_10_11(); // expected-warning{{'func_10_11' is only available on macOS 10.11 or newer}} expected-note{{enclose 'func_10_11' in an @available check to silence this warning}}
+}
diff --git a/test/SemaObjC/warn-nontrivial-struct-memaccess.m b/test/SemaObjC/warn-nontrivial-struct-memaccess.m
new file mode 100644
index 000000000000..a6eb485ceabe
--- /dev/null
+++ b/test/SemaObjC/warn-nontrivial-struct-memaccess.m
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-runtime-has-weak -x objective-c -fobjc-arc -verify %s
+
+void *memset(void *, int, __SIZE_TYPE__);
+void bzero(void *, __SIZE_TYPE__);
+void *memcpy(void *, const void *, __SIZE_TYPE__);
+void *memmove(void *, const void *, __SIZE_TYPE__);
+
+struct Trivial {
+ int f0;
+ volatile int f1;
+};
+
+struct NonTrivial0 {
+ int f0;
+ __weak id f1; // expected-note 2 {{non-trivial to default-initialize}} expected-note 2 {{non-trivial to copy}}
+ volatile int f2;
+ id f3[10]; // expected-note 2 {{non-trivial to default-initialize}} expected-note 2 {{non-trivial to copy}}
+};
+
+struct NonTrivial1 {
+ id f0; // expected-note 2 {{non-trivial to default-initialize}} expected-note 2 {{non-trivial to copy}}
+ int f1;
+ struct NonTrivial0 f2;
+};
+
+void testTrivial(struct Trivial *d, struct Trivial *s) {
+ memset(d, 0, sizeof(struct Trivial));
+ bzero(d, sizeof(struct Trivial));
+ memcpy(d, s, sizeof(struct Trivial));
+ memmove(d, s, sizeof(struct Trivial));
+}
+
+void testNonTrivial1(struct NonTrivial1 *d, struct NonTrivial1 *s) {
+ memset(d, 0, sizeof(struct NonTrivial1)); // expected-warning {{that is not trivial to primitive-default-initialize}} expected-note {{explicitly cast the pointer to silence}}
+ memset((void *)d, 0, sizeof(struct NonTrivial1));
+ bzero(d, sizeof(struct NonTrivial1)); // expected-warning {{that is not trivial to primitive-default-initialize}} expected-note {{explicitly cast the pointer to silence}}
+ memcpy(d, s, sizeof(struct NonTrivial1)); // expected-warning {{that is not trivial to primitive-copy}} expected-note {{explicitly cast the pointer to silence}}
+ memmove(d, s, sizeof(struct NonTrivial1)); // expected-warning {{that is not trivial to primitive-copy}} expected-note {{explicitly cast the pointer to silence}}
+}
diff --git a/test/SemaObjCXX/attr-trivial-abi.mm b/test/SemaObjCXX/attr-trivial-abi.mm
new file mode 100644
index 000000000000..fe8baee473e9
--- /dev/null
+++ b/test/SemaObjCXX/attr-trivial-abi.mm
@@ -0,0 +1,97 @@
+// RUN: %clang_cc1 -std=c++11 -fobjc-runtime-has-weak -fobjc-weak -fobjc-arc -fsyntax-only -verify %s
+
+void __attribute__((trivial_abi)) foo(); // expected-warning {{'trivial_abi' attribute only applies to classes}}
+
+struct [[clang::trivial_abi]] S0 {
+ int a;
+};
+
+struct __attribute__((trivial_abi)) S1 {
+ int a;
+};
+
+struct __attribute__((trivial_abi)) S2 { // expected-warning {{'trivial_abi' cannot be applied to 'S2'}}
+ __weak id a;
+};
+
+struct __attribute__((trivial_abi)) S3 { // expected-warning {{'trivial_abi' cannot be applied to 'S3'}}
+ virtual void m();
+};
+
+struct S3_2 {
+ virtual void m();
+} __attribute__((trivial_abi)); // expected-warning {{'trivial_abi' cannot be applied to 'S3_2'}}
+
+struct S4 {
+ int a;
+};
+
+struct __attribute__((trivial_abi)) S5 : public virtual S4 { // expected-warning {{'trivial_abi' cannot be applied to 'S5'}}
+};
+
+struct __attribute__((trivial_abi)) S9 : public S4 {
+};
+
+struct S6 {
+ __weak id a;
+};
+
+struct __attribute__((trivial_abi)) S12 { // expected-warning {{'trivial_abi' cannot be applied to 'S12'}}
+ __weak id a;
+};
+
+struct __attribute__((trivial_abi)) S13 { // expected-warning {{'trivial_abi' cannot be applied to 'S13'}}
+ __weak id a[2];
+};
+
+struct __attribute__((trivial_abi)) S7 { // expected-warning {{'trivial_abi' cannot be applied to 'S7'}}
+ S6 a;
+};
+
+struct __attribute__((trivial_abi)) S11 { // expected-warning {{'trivial_abi' cannot be applied to 'S11'}}
+ S6 a[2];
+};
+
+struct __attribute__((trivial_abi(1))) S8 { // expected-error {{'trivial_abi' attribute takes no arguments}}
+ int a;
+};
+
+// Do not warn when 'trivial_abi' is used to annotate a template class.
+template<class T>
+struct __attribute__((trivial_abi)) S10 {
+ T p;
+};
+
+S10<int *> p1;
+S10<__weak id> p2;
+
+template<>
+struct __attribute__((trivial_abi)) S10<id> { // expected-warning {{'trivial_abi' cannot be applied to 'S10<id>'}}
+ __weak id a;
+};
+
+template<class T>
+struct S14 {
+ T a;
+ __weak id b;
+};
+
+template<class T>
+struct __attribute__((trivial_abi)) S15 : S14<T> {
+};
+
+S15<int> s15;
+
+template<class T>
+struct __attribute__((trivial_abi)) S16 {
+ S14<T> a;
+};
+
+S16<int> s16;
+
+template<class T>
+struct __attribute__((trivial_abi)) S17 { // expected-warning {{'trivial_abi' cannot be applied to 'S17'}}
+ __weak id a;
+};
+
+S17<int> s17;
diff --git a/test/SemaObjCXX/instantiate-method-return.mm b/test/SemaObjCXX/instantiate-method-return.mm
index 9fad82feaeb7..74faa7f58257 100644
--- a/test/SemaObjCXX/instantiate-method-return.mm
+++ b/test/SemaObjCXX/instantiate-method-return.mm
@@ -1,14 +1,14 @@
// RUN: %clang_cc1 -fsyntax-only -verify -Wno-objc-root-class %s
-// expected-no-diagnostics
// PR7386
@class NSObject;
-class A;
-template<class T> class V {};
+class A; // expected-note {{forward declaration of 'A'}}
+template<class T> class V { T x; }; // expected-error {{field has incomplete type 'A'}}
@protocol Protocol
- (V<A*>)protocolMethod;
+- (V<A>)method2;
@end
@@ -24,4 +24,6 @@ template<class T> class V {};
- (V<A*>)protocolMethod {
V<A*> va; return va;
}
+- (V<A>)method2 { // expected-note {{in instantiation of}}
+}
@end
diff --git a/test/SemaObjCXX/parameterized_classes_subst.mm b/test/SemaObjCXX/parameterized_classes_subst.mm
index f342ac0224ce..88d001274b1c 100644
--- a/test/SemaObjCXX/parameterized_classes_subst.mm
+++ b/test/SemaObjCXX/parameterized_classes_subst.mm
@@ -419,7 +419,7 @@ struct DependentTemplate {
};
struct NSMutableDictionaryBuilder {
- typedef NSMutableDictionary apply;
+ typedef NSMutableDictionary apply; // expected-note 2{{declared as a non-template here}}
};
typedef DependentTemplate<NSMutableDictionaryBuilder>::type DependentTemplateFail1; // expected-note{{in instantiation of template class}}
diff --git a/test/SemaOpenCL/address-spaces.cl b/test/SemaOpenCL/address-spaces.cl
index 97dd1f4f90b3..52c891e16b73 100644
--- a/test/SemaOpenCL/address-spaces.cl
+++ b/test/SemaOpenCL/address-spaces.cl
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only
// RUN: %clang_cc1 %s -cl-std=CL2.0 -verify -pedantic -fsyntax-only
+// RUN: %clang_cc1 %s -cl-std=c++ -verify -pedantic -fsyntax-only
__constant int ci = 1;
@@ -8,6 +9,8 @@ __kernel void foo(__global int *gip) {
__local int lj = 2; // expected-error {{'__local' variable cannot have an initializer}}
int *ip;
+// FIXME: Temporarily disable part of the test that doesn't work for C++ yet.
+#if !__OPENCL_CPP_VERSION__
#if __OPENCL_C_VERSION__ < 200
ip = gip; // expected-error {{assigning '__global int *' to 'int *' changes address space of pointer}}
ip = &li; // expected-error {{assigning '__local int *' to 'int *' changes address space of pointer}}
@@ -62,4 +65,7 @@ void func_multiple_addr(void) {
__local __private int *var2; // expected-error {{multiple address spaces specified for type}}
__local private_int_t var3; // expected-error {{multiple address spaces specified for type}}
__local private_int_t *var4; // expected-error {{multiple address spaces specified for type}}
+ __private private_int_t var5; // expected-warning {{multiple identical address spaces specified for type}}
+ __private private_int_t *var6;// expected-warning {{multiple identical address spaces specified for type}}
+#endif // !__OPENCL_CXX_VERSION__
}
diff --git a/test/SemaOpenCL/builtins-amdgcn-error.cl b/test/SemaOpenCL/builtins-amdgcn-error.cl
index 2639bf27752f..67c416feacf7 100644
--- a/test/SemaOpenCL/builtins-amdgcn-error.cl
+++ b/test/SemaOpenCL/builtins-amdgcn-error.cl
@@ -102,3 +102,20 @@ void test_mov_dpp2(global int* out, int a, int b, int c, int d, bool e)
*out = __builtin_amdgcn_mov_dpp(a, 0, 0, 0, e); // expected-error {{argument to '__builtin_amdgcn_mov_dpp' must be a constant integer}}
}
+void test_ds_faddf(local float *out, float src, int a) {
+ *out = __builtin_amdgcn_ds_faddf(out, src, a, 0, false); // expected-error {{argument to '__builtin_amdgcn_ds_faddf' must be a constant integer}}
+ *out = __builtin_amdgcn_ds_faddf(out, src, 0, a, false); // expected-error {{argument to '__builtin_amdgcn_ds_faddf' must be a constant integer}}
+ *out = __builtin_amdgcn_ds_faddf(out, src, 0, 0, a); // expected-error {{argument to '__builtin_amdgcn_ds_faddf' must be a constant integer}}
+}
+
+void test_ds_fminf(local float *out, float src, int a) {
+ *out = __builtin_amdgcn_ds_fminf(out, src, a, 0, false); // expected-error {{argument to '__builtin_amdgcn_ds_fminf' must be a constant integer}}
+ *out = __builtin_amdgcn_ds_fminf(out, src, 0, a, false); // expected-error {{argument to '__builtin_amdgcn_ds_fminf' must be a constant integer}}
+ *out = __builtin_amdgcn_ds_fminf(out, src, 0, 0, a); // expected-error {{argument to '__builtin_amdgcn_ds_fminf' must be a constant integer}}
+}
+
+void test_ds_fmaxf(local float *out, float src, int a) {
+ *out = __builtin_amdgcn_ds_fmaxf(out, src, a, 0, false); // expected-error {{argument to '__builtin_amdgcn_ds_fmaxf' must be a constant integer}}
+ *out = __builtin_amdgcn_ds_fmaxf(out, src, 0, a, false); // expected-error {{argument to '__builtin_amdgcn_ds_fmaxf' must be a constant integer}}
+ *out = __builtin_amdgcn_ds_fmaxf(out, src, 0, 0, a); // expected-error {{argument to '__builtin_amdgcn_ds_fmaxf' must be a constant integer}}
+}
diff --git a/test/SemaOpenCL/extension-version.cl b/test/SemaOpenCL/extension-version.cl
index e56027604651..714e4c210861 100644
--- a/test/SemaOpenCL/extension-version.cl
+++ b/test/SemaOpenCL/extension-version.cl
@@ -131,6 +131,15 @@
#endif
#pragma OPENCL EXTENSION cl_khr_d3d10_sharing: enable
+#if (__OPENCL_C_VERSION__ >= 110)
+#ifndef cles_khr_int64
+#error "Missing cles_khr_int64 define"
+#endif
+#else
+// expected-warning@+2{{unsupported OpenCL extension 'cles_khr_int64' - ignoring}}
+#endif
+#pragma OPENCL EXTENSION cles_khr_int64: enable
+
#if (__OPENCL_C_VERSION__ >= 120)
#ifndef cl_khr_context_abort
#error "Missing cl_context_abort define"
diff --git a/test/SemaOpenCL/invalid-kernel-attrs.cl b/test/SemaOpenCL/invalid-kernel-attrs.cl
index 1f1359cceead..a19a989f41bb 100644
--- a/test/SemaOpenCL/invalid-kernel-attrs.cl
+++ b/test/SemaOpenCL/invalid-kernel-attrs.cl
@@ -14,11 +14,11 @@ kernel __attribute__((work_group_size_hint(8,16,32,4))) void kernel6() {} //expe
kernel __attribute__((work_group_size_hint(1,2,3))) __attribute__((work_group_size_hint(3,2,1))) void kernel7() {} //expected-warning{{attribute 'work_group_size_hint' is already applied with different parameters}}
-__attribute__((reqd_work_group_size(8,16,32))) void kernel8(){} // expected-error {{attribute 'reqd_work_group_size' can only be applied to a kernel}}
+__attribute__((reqd_work_group_size(8,16,32))) void kernel8(){} // expected-error {{attribute 'reqd_work_group_size' can only be applied to an OpenCL kernel}}
-__attribute__((work_group_size_hint(8,16,32))) void kernel9(){} // expected-error {{attribute 'work_group_size_hint' can only be applied to a kernel}}
+__attribute__((work_group_size_hint(8,16,32))) void kernel9(){} // expected-error {{attribute 'work_group_size_hint' can only be applied to an OpenCL kernel}}
-__attribute__((vec_type_hint(char))) void kernel10(){} // expected-error {{attribute 'vec_type_hint' can only be applied to a kernel}}
+__attribute__((vec_type_hint(char))) void kernel10(){} // expected-error {{attribute 'vec_type_hint' can only be applied to an OpenCL kernel}}
constant int foo1 __attribute__((reqd_work_group_size(8,16,32))) = 0; // expected-error {{'reqd_work_group_size' attribute only applies to functions}}
@@ -34,6 +34,6 @@ kernel __attribute__((reqd_work_group_size(1,2,0))) void kernel11(){} // expecte
kernel __attribute__((reqd_work_group_size(1,0,2))) void kernel12(){} // expected-error {{'reqd_work_group_size' attribute must be greater than 0}}
kernel __attribute__((reqd_work_group_size(0,1,2))) void kernel13(){} // expected-error {{'reqd_work_group_size' attribute must be greater than 0}}
-__attribute__((intel_reqd_sub_group_size(8))) void kernel14(){} // expected-error {{attribute 'intel_reqd_sub_group_size' can only be applied to a kernel}}
+__attribute__((intel_reqd_sub_group_size(8))) void kernel14(){} // expected-error {{attribute 'intel_reqd_sub_group_size' can only be applied to an OpenCL kernel}}
kernel __attribute__((intel_reqd_sub_group_size(0))) void kernel15(){} // expected-error {{'intel_reqd_sub_group_size' attribute must be greater than 0}}
kernel __attribute__((intel_reqd_sub_group_size(8))) __attribute__((intel_reqd_sub_group_size(16))) void kernel16() {} //expected-warning{{attribute 'intel_reqd_sub_group_size' is already applied with different parameters}}
diff --git a/test/SemaOpenCL/logical-ops.cl b/test/SemaOpenCL/logical-ops.cl
index 42501b14413e..f6972c46e2ad 100644
--- a/test/SemaOpenCL/logical-ops.cl
+++ b/test/SemaOpenCL/logical-ops.cl
@@ -29,7 +29,7 @@ kernel void float_ops() {
#if __OPENCL_C_VERSION__ < 120
// expected-error@-2{{invalid operands}}
#endif
- float ibaf = 0 & 0.0f; // expected-error {{invalid operands}}
+ float ibaf = 0 & 0.0f; // expected-error {{invalid operands to binary expression ('int' and 'float')}}
float ibof = 0 | 0.0f; // expected-error {{invalid operands}}
float bnf = ~0.0f;// expected-error {{invalid argument type}}
float lnf = !0.0f;
diff --git a/test/SemaOpenCL/multistep-explicit-cast.cl b/test/SemaOpenCL/multistep-explicit-cast.cl
new file mode 100644
index 000000000000..5e3d12a0e449
--- /dev/null
+++ b/test/SemaOpenCL/multistep-explicit-cast.cl
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -ast-dump %s | FileCheck %s
+// expected-no-diagnostics
+
+typedef __attribute__((ext_vector_type(2))) char char2;
+
+void vectorIncrementDecrementOps() {
+ // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} vectorIncrementDecrementOps 'void (void)'{{$}}
+ // CHECK: CStyleCastExpr {{.*}} <col:{{.*}}> 'char2':'char __attribute__((ext_vector_type(2)))' <VectorSplat>{{$}}
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'char' <IntegralCast> part_of_explicit_cast{{$}}
+ // CHECK-NEXT: IntegerLiteral {{.*}} <col:{{.*}}> 'int' 1{{$}}
+ char2 A = (char2)(1);
+ A++;
+}
diff --git a/test/SemaOpenCL/predefined-expr.cl b/test/SemaOpenCL/predefined-expr.cl
new file mode 100644
index 000000000000..419e7a925c5c
--- /dev/null
+++ b/test/SemaOpenCL/predefined-expr.cl
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 %s -verify
+// RUN: %clang_cc1 %s -verify -cl-std=CL2.0
+
+void f() {
+ char *f1 = __func__; //expected-error-re{{initializing '{{__generic char|char}} *' with an expression of type 'const __constant char *' changes address space of pointer}}
+ constant char *f2 = __func__; //expected-warning{{initializing '__constant char *' with an expression of type 'const __constant char [2]' discards qualifiers}}
+ constant const char *f3 = __func__;
+}
diff --git a/test/SemaOpenCL/storageclass.cl b/test/SemaOpenCL/storageclass.cl
index cbcb94509b32..f35ab9c2e08c 100644
--- a/test/SemaOpenCL/storageclass.cl
+++ b/test/SemaOpenCL/storageclass.cl
@@ -10,14 +10,14 @@ static constant float g_constant_static_var = 0;
static global float g_global_static_var = 0; // expected-error {{program scope variable must reside in constant address space}}
static local float g_local_static_var = 0; // expected-error {{program scope variable must reside in constant address space}}
static private float g_private_static_var = 0; // expected-error {{program scope variable must reside in constant address space}}
-static generic float g_generic_static_var = 0; // expected-error{{OpenCL version 1.2 does not support the 'generic' type qualifier}} // expected-error {{program scope variable must reside in constant address space}}
+static generic float g_generic_static_var = 0; // expected-error{{OpenCL C version 1.2 does not support the 'generic' type qualifier}} // expected-error {{program scope variable must reside in constant address space}}
extern float g_implicit_extern_var; // expected-error {{extern variable must reside in constant address space}}
extern constant float g_constant_extern_var;
extern global float g_global_extern_var; // expected-error {{extern variable must reside in constant address space}}
extern local float g_local_extern_var; // expected-error {{extern variable must reside in constant address space}}
extern private float g_private_extern_var; // expected-error {{extern variable must reside in constant address space}}
-extern generic float g_generic_extern_var; // expected-error{{OpenCL version 1.2 does not support the 'generic' type qualifier}} // expected-error {{extern variable must reside in constant address space}}
+extern generic float g_generic_extern_var; // expected-error{{OpenCL C version 1.2 does not support the 'generic' type qualifier}} // expected-error {{extern variable must reside in constant address space}}
void kernel foo(int x) {
// static is not allowed at local scope before CL2.0
@@ -32,7 +32,7 @@ void kernel foo(int x) {
constant int L1 = 42; // expected-error {{variables in the constant address space can only be declared in the outermost scope of a kernel function}}
}
- auto int L3 = 7; // expected-error{{OpenCL version 1.2 does not support the 'auto' storage class specifier}}
+ auto int L3 = 7; // expected-error{{OpenCL C version 1.2 does not support the 'auto' storage class specifier}}
global int L4; // expected-error{{function scope variable cannot be declared in global address space}}
__attribute__((address_space(100))) int L5; // expected-error{{automatic variable qualified with an invalid address space}}
@@ -64,12 +64,12 @@ void f() {
static global float l_global_static_var = 0; // expected-error {{variables in function scope cannot be declared static}}
static local float l_local_static_var = 0; // expected-error {{variables in function scope cannot be declared static}}
static private float l_private_static_var = 0; // expected-error {{variables in function scope cannot be declared static}}
- static generic float l_generic_static_var = 0; // expected-error{{OpenCL version 1.2 does not support the 'generic' type qualifier}} // expected-error {{variables in function scope cannot be declared static}}
+ static generic float l_generic_static_var = 0; // expected-error{{OpenCL C version 1.2 does not support the 'generic' type qualifier}} // expected-error {{variables in function scope cannot be declared static}}
extern float l_implicit_extern_var; // expected-error {{extern variable must reside in constant address space}}
extern constant float l_constant_extern_var;
extern global float l_global_extern_var; // expected-error {{extern variable must reside in constant address space}}
extern local float l_local_extern_var; // expected-error {{extern variable must reside in constant address space}}
extern private float l_private_extern_var; // expected-error {{extern variable must reside in constant address space}}
- extern generic float l_generic_extern_var; // expected-error{{OpenCL version 1.2 does not support the 'generic' type qualifier}} // expected-error {{extern variable must reside in constant address space}}
+ extern generic float l_generic_extern_var; // expected-error{{OpenCL C version 1.2 does not support the 'generic' type qualifier}} // expected-error {{extern variable must reside in constant address space}}
}
diff --git a/test/SemaOpenCLCXX/newdelete.cl b/test/SemaOpenCLCXX/newdelete.cl
new file mode 100644
index 000000000000..ce6273f3be77
--- /dev/null
+++ b/test/SemaOpenCLCXX/newdelete.cl
@@ -0,0 +1,55 @@
+// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -pedantic -verify -fsyntax-only
+
+class A {
+ public:
+ A() : x(21) {}
+ int x;
+};
+
+typedef __SIZE_TYPE__ size_t;
+
+class B {
+ public:
+ B() : bx(42) {}
+ void *operator new(size_t);
+ void operator delete(void *ptr);
+ int bx;
+};
+
+// There are no global user-defined new operators at this point. Test that clang
+// rejects these gracefully.
+void test_default_new_delete(void *buffer, A **pa) {
+ A *a = new A; // expected-error {{'default new' is not supported in OpenCL C++}}
+ delete a; // expected-error {{'default delete' is not supported in OpenCL C++}}
+ *pa = new (buffer) A; // expected-error {{'default new' is not supported in OpenCL C++}}
+}
+
+// expected-note@+1 {{candidate function not viable: requires 2 arguments, but 1 was provided}}
+void *operator new(size_t _s, void *ptr) noexcept {
+ return ptr;
+}
+
+// expected-note@+1 {{candidate function not viable: requires 2 arguments, but 1 was provided}}
+void *operator new[](size_t _s, void *ptr) noexcept {
+ return ptr;
+}
+
+void test_new_delete(void *buffer, A **a, B **b) {
+ *a = new A; // expected-error {{no matching function for call to 'operator new'}}
+ delete a; // expected-error {{'default delete' is not supported in OpenCL C++}}
+
+ *a = new A[20]; // expected-error {{no matching function for call to 'operator new[]'}}
+ delete[] *a; // expected-error {{'default delete' is not supported in OpenCL C++}}
+
+ // User-defined placement new is supported.
+ *a = new (buffer) A;
+
+ // User-defined placement new[] is supported.
+ *a = new (buffer) A[30];
+
+ // User-defined new is supported.
+ *b = new B;
+
+ // User-defined delete is supported.
+ delete *b;
+}
diff --git a/test/SemaOpenCLCXX/restricted.cl b/test/SemaOpenCLCXX/restricted.cl
new file mode 100644
index 000000000000..c0dfbd645d0c
--- /dev/null
+++ b/test/SemaOpenCLCXX/restricted.cl
@@ -0,0 +1,63 @@
+// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -pedantic -verify -fsyntax-only
+
+// This test checks that various C/C++/OpenCL C constructs are not available in
+// OpenCL C++, according to OpenCL C++ 1.0 Specification Section 2.9.
+
+// Test that typeid is not available in OpenCL C++.
+namespace std {
+ // Provide a dummy std::type_info so that we can use typeid.
+ class type_info {
+ int a;
+ };
+}
+__constant std::type_info int_ti = typeid(int);
+// expected-error@-1 {{'typeid' is not supported in OpenCL C++}}
+
+// Test that dynamic_cast is not available in OpenCL C++.
+class A {
+public:
+ int a;
+};
+
+class B : public A {
+ int b;
+};
+
+B *test_dynamic_cast(B *p) {
+ return dynamic_cast<B *>(p);
+ // expected-error@-1 {{'dynamic_cast' is not supported in OpenCL C++}}
+}
+
+// Test storage class qualifiers.
+__constant _Thread_local int a = 1;
+// expected-error@-1 {{OpenCL C++ version 1.0 does not support the '_Thread_local' storage class specifier}}
+__constant __thread int b = 2;
+// expected-error@-1 {{OpenCL C++ version 1.0 does not support the '__thread' storage class specifier}}
+kernel void test_storage_classes() {
+ register int x;
+ // expected-error@-1 {{OpenCL C++ version 1.0 does not support the 'register' storage class specifier}}
+ thread_local int y;
+ // expected-error@-1 {{OpenCL C++ version 1.0 does not support the 'thread_local' storage class specifier}}
+}
+
+// Test that access qualifiers are reserved keywords.
+kernel void test_access_qualifiers() {
+ int read_only;
+ // expected-error@-1 {{'read_only' is a reserved keyword in OpenCL C++}}
+ // expected-warning@-2 {{declaration does not declare anything}}
+ int __read_only;
+ // expected-error@-1 {{'__read_only' is a reserved keyword in OpenCL C++}}
+ // expected-warning@-2 {{declaration does not declare anything}}
+ int write_only;
+ // expected-error@-1 {{'write_only' is a reserved keyword in OpenCL C++}}
+ // expected-warning@-2 {{declaration does not declare anything}}
+ int __write_only;
+ // expected-error@-1 {{'__write_only' is a reserved keyword in OpenCL C++}}
+ // expected-warning@-2 {{declaration does not declare anything}}
+ int read_write;
+ // expected-error@-1 {{'read_write' is a reserved keyword in OpenCL C++}}
+ // expected-warning@-2 {{declaration does not declare anything}}
+ int __read_write;
+ // expected-error@-1 {{'__read_write' is a reserved keyword in OpenCL C++}}
+ // expected-warning@-2 {{declaration does not declare anything}}
+}
diff --git a/test/SemaTemplate/alias-templates.cpp b/test/SemaTemplate/alias-templates.cpp
index 3b7548d169b0..240a6eeff2e7 100644
--- a/test/SemaTemplate/alias-templates.cpp
+++ b/test/SemaTemplate/alias-templates.cpp
@@ -256,12 +256,14 @@ namespace PR31514 {
}
namespace an_alias_template_is_not_a_class_template {
- template<typename T> using Foo = int; // expected-note 2{{here}}
+ template<typename T> using Foo = int; // expected-note 3{{here}}
Foo x; // expected-error {{use of alias template 'Foo' requires template arguments}}
Foo<> y; // expected-error {{too few template arguments for alias template 'Foo'}}
+ int z = Foo(); // expected-error {{use of alias template 'Foo' requires template arguments}}
- template<template<typename> class Bar> void f() { // expected-note 2{{here}}
+ template<template<typename> class Bar> void f() { // expected-note 3{{here}}
Bar x; // expected-error {{use of template template parameter 'Bar' requires template arguments}}
Bar<> y; // expected-error {{too few template arguments for template template parameter 'Bar'}}
+ int z = Bar(); // expected-error {{use of template template parameter 'Bar' requires template arguments}}
}
}
diff --git a/test/SemaTemplate/alignas.cpp b/test/SemaTemplate/alignas.cpp
index 8a1f96e5bdec..680f07b32998 100644
--- a/test/SemaTemplate/alignas.cpp
+++ b/test/SemaTemplate/alignas.cpp
@@ -21,3 +21,14 @@ struct C { char a[16]; };
static_assert(sizeof(my_union<A, B, C>) == 16, "");
static_assert(alignof(my_union<A, B, C>) == 8, "");
+
+namespace PR35028 {
+ template<class X, int Alignment> struct alignas(X) alignas(long long) alignas(long double) alignas(Alignment) Aligned {
+ union {
+ long long align1;
+ long double align2;
+ char data[sizeof(X)];
+ };
+ };
+ Aligned<int, 1> a;
+}
diff --git a/test/SemaTemplate/argument-dependent-lookup.cpp b/test/SemaTemplate/argument-dependent-lookup.cpp
new file mode 100644
index 000000000000..d1603d56b960
--- /dev/null
+++ b/test/SemaTemplate/argument-dependent-lookup.cpp
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -verify %s
+// RUN: %clang_cc1 -verify %s -DHAVE_UNQUALIFIED_LOOKUP_RESULTS
+// expected-no-diagnostics
+
+namespace address_of {
+#ifdef HAVE_UNQUALIFIED_LOOKUP_RESULTS
+ struct Q {};
+ void operator&(Q);
+#endif
+
+ template<typename T> struct A {
+ static constexpr auto x = &T::value;
+ };
+
+ template<typename T> struct B {
+ constexpr int operator&() { return 123; }
+ };
+
+ template<typename T> struct C {
+ static_assert(sizeof(T) == 123, "");
+ };
+
+ struct X1 {
+ static B<X1> value;
+ };
+ struct X2 : B<X2> {
+ enum E { value };
+ friend constexpr int operator&(E) { return 123; }
+ };
+
+ struct Y1 {
+ C<int> *value;
+ };
+ struct Y2 {
+ C<int> value();
+ };
+
+ // ok, uses ADL to find operator&:
+ static_assert(A<X1>::x == 123, "");
+ static_assert(A<X2>::x == 123, "");
+
+ // ok, does not use ADL so does not instantiate C<T>:
+ static_assert(A<Y1>::x == &Y1::value, "");
+ static_assert(A<Y2>::x == &Y2::value, "");
+}
diff --git a/test/SemaTemplate/attributes.cpp b/test/SemaTemplate/attributes.cpp
index 1d46058b0191..7634b937c906 100644
--- a/test/SemaTemplate/attributes.cpp
+++ b/test/SemaTemplate/attributes.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -std=gnu++11 -fsyntax-only -verify %s
+// RUN: not %clang_cc1 -std=gnu++11 -ast-dump %s | FileCheck %s
namespace attribute_aligned {
template<int N>
@@ -52,3 +53,13 @@ namespace PR9049 {
template<typename T>
inline void WBCFRelease(__attribute__((cf_consumed)) T aValue) { if(aValue) CFRelease(aValue); }
}
+
+// CHECK: FunctionTemplateDecl {{.*}} HasAnnotations
+// CHECK: AnnotateAttr {{.*}} "ANNOTATE_BAR"
+// CHECK: AnnotateAttr {{.*}} "ANNOTATE_FOO"
+// CHECK: FunctionDecl {{.*}} HasAnnotations
+// CHECK: TemplateArgument type 'int'
+// CHECK: AnnotateAttr {{.*}} "ANNOTATE_BAR"
+// CHECK: AnnotateAttr {{.*}} "ANNOTATE_FOO"
+template<typename T> [[clang::annotate("ANNOTATE_FOO"), clang::annotate("ANNOTATE_BAR")]] void HasAnnotations();
+void UseAnnotations() { HasAnnotations<int>(); }
diff --git a/test/SemaTemplate/class-template-spec.cpp b/test/SemaTemplate/class-template-spec.cpp
index 00e03ef61eb0..d763944371cc 100644
--- a/test/SemaTemplate/class-template-spec.cpp
+++ b/test/SemaTemplate/class-template-spec.cpp
@@ -78,9 +78,6 @@ template<> struct ::A<double>;
namespace N {
template<typename T> struct B; // expected-note {{explicitly specialized}}
-#if __cplusplus <= 199711L
- // expected-note@-2 {{explicitly specialized}}
-#endif
template<> struct ::N::B<char>; // okay
template<> struct ::N::B<short>; // okay
@@ -92,9 +89,6 @@ namespace N {
template<> struct N::B<int> { }; // okay
template<> struct N::B<float> { };
-#if __cplusplus <= 199711L
-// expected-warning@-2 {{first declaration of class template specialization of 'B' outside namespace 'N' is a C++11 extension}}
-#endif
namespace M {
@@ -121,9 +115,9 @@ class Wibble<int> { }; // expected-error{{cannot specialize a template template
namespace rdar9676205 {
template<typename T>
- struct X {
+ struct X { // expected-note {{here}}
template<typename U>
- struct X<U*> { // expected-error{{explicit specialization of 'X' in class scope}}
+ struct X<U*> { // expected-error{{partial specialization of 'X' not in a namespace enclosing}}
};
};
diff --git a/test/SemaTemplate/cxx17-inline-variables.cpp b/test/SemaTemplate/cxx17-inline-variables.cpp
index 9e6761ee57aa..7fc0aa8eeeb0 100644
--- a/test/SemaTemplate/cxx17-inline-variables.cpp
+++ b/test/SemaTemplate/cxx17-inline-variables.cpp
@@ -16,3 +16,14 @@ namespace CompleteType {
constexpr int n = X<true>::value;
}
+
+template <typename T> struct A {
+ static const int n;
+ static const int m;
+ constexpr int f() { return n; }
+ constexpr int g() { return n; }
+};
+template <typename T> constexpr int A<T>::n = sizeof(A) + sizeof(T);
+template <typename T> inline constexpr int A<T>::m = sizeof(A) + sizeof(T);
+static_assert(A<int>().f() == 5);
+static_assert(A<int>().g() == 5);
diff --git a/test/SemaTemplate/dependent-base-classes.cpp b/test/SemaTemplate/dependent-base-classes.cpp
index 1853511bfc8f..6d342f984d53 100644
--- a/test/SemaTemplate/dependent-base-classes.cpp
+++ b/test/SemaTemplate/dependent-base-classes.cpp
@@ -55,7 +55,7 @@ namespace PR6031 {
struct NoDepBase {
int foo() {
class NoDepBase::Nested nested; // expected-error{{no class named 'Nested' in 'NoDepBase<T>'}}
- typedef typename NoDepBase::template MemberTemplate<T>::type type; // expected-error{{'MemberTemplate' following the 'template' keyword does not refer to a template}} \
+ typedef typename NoDepBase::template MemberTemplate<T>::type type; // expected-error{{no member named 'MemberTemplate' in 'NoDepBase<T>'}} \
// FIXME: expected-error{{unqualified-id}}
return NoDepBase::a; // expected-error{{no member named 'a' in 'NoDepBase<T>'}}
}
@@ -103,7 +103,7 @@ namespace PR6081 {
template< class X >
void f0(const X & k)
{
- this->template f1<int>()(k); // expected-error{{'f1' following the 'template' keyword does not refer to a template}} \
+ this->template f1<int>()(k); // expected-error{{no member named 'f1' in 'C<T>'}} \
// FIXME: expected-error{{unqualified-id}} \
// expected-error{{function-style cast or type construction}} \
// expected-error{{expected expression}}
diff --git a/test/SemaTemplate/dependent-names.cpp b/test/SemaTemplate/dependent-names.cpp
index d5c9d66c4526..67ef238083f0 100644
--- a/test/SemaTemplate/dependent-names.cpp
+++ b/test/SemaTemplate/dependent-names.cpp
@@ -419,3 +419,43 @@ template <typename> struct CT2 {
template <class U> struct X;
};
template <typename T> int CT2<int>::X<>; // expected-error {{template parameter list matching the non-templated nested type 'CT2<int>' should be empty}}
+
+namespace DependentTemplateIdWithNoArgs {
+ template<typename T> void f() { T::template f(); }
+ struct X {
+ template<int = 0> static void f();
+ };
+ void g() { f<X>(); }
+}
+
+namespace DependentUnresolvedUsingTemplate {
+ template<typename T>
+ struct X : T {
+ using T::foo;
+ void f() { this->template foo(); } // expected-error {{does not refer to a template}}
+ void g() { this->template foo<>(); } // expected-error {{does not refer to a template}}
+ void h() { this->template foo<int>(); } // expected-error {{does not refer to a template}}
+ };
+ struct A { template<typename = int> int foo(); };
+ struct B { int foo(); }; // expected-note 3{{non-template here}}
+ void test(X<A> xa, X<B> xb) {
+ xa.f();
+ xa.g();
+ xa.h();
+ xb.f(); // expected-note {{instantiation of}}
+ xb.g(); // expected-note {{instantiation of}}
+ xb.h(); // expected-note {{instantiation of}}
+ }
+}
+
+namespace PR37680 {
+ template <class a> struct b : a {
+ using a::add;
+ template<int> int add() { return this->template add(0); }
+ };
+ struct a {
+ template<typename T = void> int add(...);
+ void add(int);
+ };
+ int f(b<a> ba) { return ba.add<0>(); }
+}
diff --git a/test/SemaTemplate/dependent-template-recover.cpp b/test/SemaTemplate/dependent-template-recover.cpp
index ac1623041719..37a8faa705f7 100644
--- a/test/SemaTemplate/dependent-template-recover.cpp
+++ b/test/SemaTemplate/dependent-template-recover.cpp
@@ -5,18 +5,69 @@ struct X {
t->f0<U>(); // expected-error{{use 'template' keyword to treat 'f0' as a dependent template name}}
t->f0<int>(); // expected-error{{use 'template' keyword to treat 'f0' as a dependent template name}}
- t->operator+<U const, 1>(); // expected-error{{use 'template' keyword to treat 'operator +' as a dependent template name}}
- t->f1<int const, 2>(); // expected-error{{use 'template' keyword to treat 'f1' as a dependent template name}}
+ t->operator+<U const, 1>(1); // expected-error{{use 'template' keyword to treat 'operator +' as a dependent template name}}
+ t->f1<int const, 2>(1); // expected-error{{use 'template' keyword to treat 'f1' as a dependent template name}}
+ t->f1<3, int const>(1); // expected-error{{missing 'template' keyword prior to dependent template name 'f1'}}
T::getAs<U>(); // expected-error{{use 'template' keyword to treat 'getAs' as a dependent template name}}
t->T::getAs<U>(); // expected-error{{use 'template' keyword to treat 'getAs' as a dependent template name}}
- // FIXME: We can't recover from these yet
- (*t).f2<N>(); // expected-error{{expected expression}}
- (*t).f2<0>(); // expected-error{{expected expression}}
+ (*t).f2<N>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f2'}}
+ (*t).f2<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f2'}}
+ T::f2<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f2'}}
+ T::f2<0, int>(0); // expected-error{{missing 'template' keyword prior to dependent template name 'f2'}}
+
+ T::foo<N < 2 || N >= 4>(); // expected-error{{missing 'template' keyword prior to dependent template name 'foo'}}
+
+ // If there are multiple potential template names, pick the one where there
+ // is no whitespace between the name and the '<'.
+ T::foo<T::bar < 1>(); // expected-error{{missing 'template' keyword prior to dependent template name 'foo'}}
+ T::foo < T::bar<1>(); // expected-error{{missing 'template' keyword prior to dependent template name 'bar'}}
+
+ // Prefer to diagonse a missing 'template' keyword rather than finding a non-template name.
+ xyz < T::foo < 1 > (); // expected-error{{missing 'template' keyword prior to dependent template name 'foo'}}
+ T::foo < xyz < 1 > (); // expected-error{{missing 'template' keyword prior to dependent template name 'foo'}}
+
+ // ... even if the whitespace suggests the other name is the template name.
+ // FIXME: Is this the right heuristic?
+ xyz<T::foo < 1>(); // expected-error{{missing 'template' keyword prior to dependent template name 'foo'}}
+ T::foo < xyz<1>(); // expected-error{{missing 'template' keyword prior to dependent template name 'foo'}}
+
+ sizeof T::foo < 123 > (); // expected-error{{missing 'template' keyword prior to dependent template name 'foo'}}
+ f(t->foo<1, 2>(), // expected-error{{missing 'template' keyword prior to dependent template name 'foo'}}
+ t->bar<3, 4>()); // expected-error{{missing 'template' keyword prior to dependent template name 'bar'}}
+
+ int arr[] = {
+ t->baz<1, 2>(1 + 1), // ok, two comparisons
+ t->foo<1, 2>(), // expected-error{{missing 'template' keyword prior to dependent template name 'foo'}}
+ t->bar<3, 4>() // FIXME: we don't recover from the previous error so don't diagnose this
+ };
}
+
+ int xyz;
};
+template <typename T> void not_missing_template(T t) {
+ (T::n < 0) > (
+ ) // expected-error {{expected expression}}
+ ;
+
+ int a = T::x < 3;
+ int b = T::y > (); // expected-error {{expected expression}}
+
+ void c(int = T::x < 3);
+ void d(int = T::y > ()); // expected-error {{expected expression}}
+
+ for (int x = t < 3 ? 1 : 2; t > (); ++t) { // expected-error {{expected expression}}
+ }
+
+ // FIXME: We shouldn't treat 'T::t' as a potential template-name here,
+ // because that would leave a '?' with no matching ':'.
+ // We should probably generally treat '?' ... ':' as a bracket-like
+ // construct.
+ bool k = T::t < 3 ? 1 > () : false; // expected-error {{missing 'template' keyword}} expected-error +{{}} expected-note +{{}}
+}
+
struct MrsBadcrumble {
friend MrsBadcrumble operator<(void (*)(int), MrsBadcrumble);
friend void operator>(MrsBadcrumble, int);
@@ -30,6 +81,9 @@ template<int N, typename T> void f(T t) {
// Note: no diagnostic here, this is actually valid as a comparison between
// the decayed pointer to Y::g<> and mb!
T::g<mb>(0);
+
+ // ... but this one must be a template-id.
+ T::g<mb, int>(0); // expected-error {{missing 'template' keyword prior to dependent template name 'g'}}
}
struct Y {
diff --git a/test/SemaTemplate/ext_ms_template_spec.cpp b/test/SemaTemplate/ext_ms_template_spec.cpp
index fc2ed16f9f8a..cb303217ea90 100644
--- a/test/SemaTemplate/ext_ms_template_spec.cpp
+++ b/test/SemaTemplate/ext_ms_template_spec.cpp
@@ -18,16 +18,16 @@ template <typename T> struct X {
namespace B {
template <>
-class A::ClassTemplate<int>; // expected-warning {{class template specialization of 'ClassTemplate' outside namespace enclosing 'A' is a Microsoft extension}}
+class A::ClassTemplate<int>; // expected-warning {{class template specialization of 'ClassTemplate' not in a namespace enclosing 'A' is a Microsoft extension}}
template <class T1>
-class A::ClassTemplatePartial<T1, T1 *> {}; // expected-warning {{class template partial specialization of 'ClassTemplatePartial' outside namespace enclosing 'A' is a Microsoft extension}}
+class A::ClassTemplatePartial<T1, T1 *> {}; // expected-warning {{class template partial specialization of 'ClassTemplatePartial' not in a namespace enclosing 'A' is a Microsoft extension}}
template <>
-struct A::X<int>::MemberClass; // expected-warning {{member class specialization of 'MemberClass' outside namespace enclosing 'A' is a Microsoft extension}}
+struct A::X<int>::MemberClass; // expected-warning {{member class specialization of 'MemberClass' not in class 'X' or an enclosing namespace is a Microsoft extension}}
template <>
-enum A::X<int>::MemberEnumeration; // expected-warning {{member enumeration specialization of 'MemberEnumeration' outside namespace enclosing 'A' is a Microsoft extension}} // expected-error {{ISO C++ forbids forward references to 'enum' types}}
+enum A::X<int>::MemberEnumeration; // expected-warning {{member enumeration specialization of 'MemberEnumeration' not in class 'X' or an enclosing namespace is a Microsoft extension}} // expected-error {{ISO C++ forbids forward references to 'enum' types}}
}
diff --git a/test/SemaTemplate/function-pointer-qualifier.cpp b/test/SemaTemplate/function-pointer-qualifier.cpp
new file mode 100644
index 000000000000..97d160738a28
--- /dev/null
+++ b/test/SemaTemplate/function-pointer-qualifier.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+template<class _Ty> inline
+ void testparam(_Ty **, _Ty **)
+ {
+ }
+
+template<class _Ty> inline
+ void testparam(_Ty *const *, _Ty **)
+ {
+ }
+
+template<class _Ty> inline
+ void testparam(_Ty **, const _Ty **)
+ {
+ }
+
+template<class _Ty> inline
+ void testparam(_Ty *const *, const _Ty **)
+ {
+ }
+
+void case0()
+{
+ void (**p1)();
+ void (**p2)();
+ testparam(p1, p2);
+}
diff --git a/test/SemaTemplate/function-template-specialization.cpp b/test/SemaTemplate/function-template-specialization.cpp
index 6327ff64c336..a3669fd7fdda 100644
--- a/test/SemaTemplate/function-template-specialization.cpp
+++ b/test/SemaTemplate/function-template-specialization.cpp
@@ -54,5 +54,5 @@ class Foo {
// Don't crash here.
template<>
- static void Bar(const long& input) {} // expected-error{{explicit specialization of 'Bar' in class scope}}
+ static void Bar(const long& input) {} // expected-warning{{explicit specialization cannot have a storage class}}
};
diff --git a/test/SemaTemplate/instantiate-after-fatal-cxx17.cpp b/test/SemaTemplate/instantiate-after-fatal-cxx17.cpp
new file mode 100644
index 000000000000..3e0ddf1ae60f
--- /dev/null
+++ b/test/SemaTemplate/instantiate-after-fatal-cxx17.cpp
@@ -0,0 +1,16 @@
+// RUN: not %clang_cc1 -std=c++17 -fsyntax-only -ferror-limit 1 %s 2>&1 | FileCheck %s
+
+#error Error 1
+#error Error 2
+// CHECK: fatal error: too many errors emitted, stopping now
+
+namespace rdar39051732 {
+
+ template<class T> struct A {
+ template <class U> A(T&, ...);
+ };
+ // Deduction guide triggers constructor instantiation.
+ template<class T> A(const T&, const T&) -> A<T&>;
+
+}
+
diff --git a/test/SemaTemplate/instantiate-init.cpp b/test/SemaTemplate/instantiate-init.cpp
index 244e94f6d605..51fa6955d0c0 100644
--- a/test/SemaTemplate/instantiate-init.cpp
+++ b/test/SemaTemplate/instantiate-init.cpp
@@ -142,3 +142,17 @@ namespace ReturnStmtIsInitialization {
template<typename T> X f() { return {}; }
auto &&x = f<void>();
}
+
+namespace InitListUpdate {
+ struct A { int n; };
+ using AA = A[1];
+
+ // Check that an init list update doesn't "lose" the pack-ness of an expression.
+ template <int... N> void f() {
+ g(AA{0, [0].n = N} ...); // expected-warning 3{{overrides prior init}} expected-note 3{{previous init}}
+ g(AA{N, [0].n = 0} ...); // expected-warning 3{{overrides prior init}} expected-note 3{{previous init}}
+ };
+
+ void g(AA, AA);
+ void h() { f<1, 2>(); } // expected-note {{instantiation of}}
+}
diff --git a/test/SemaTemplate/instantiate-method.cpp b/test/SemaTemplate/instantiate-method.cpp
index 961884417b54..9cd668dacf5c 100644
--- a/test/SemaTemplate/instantiate-method.cpp
+++ b/test/SemaTemplate/instantiate-method.cpp
@@ -185,7 +185,7 @@ namespace SameSignatureAfterInstantiation {
namespace PR22040 {
template <typename T> struct Foobar {
- template <> void bazqux(typename T::type) {} // expected-error {{cannot specialize a function 'bazqux' within class scope}} expected-error 2{{cannot be used prior to '::' because it has no members}}
+ template <> void bazqux(typename T::type) {} // expected-error 2{{cannot be used prior to '::' because it has no members}}
};
void test() {
diff --git a/test/SemaTemplate/late-parsing-eager-instantiation.cpp b/test/SemaTemplate/late-parsing-eager-instantiation.cpp
new file mode 100644
index 000000000000..412f0265a46a
--- /dev/null
+++ b/test/SemaTemplate/late-parsing-eager-instantiation.cpp
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -std=c++14 -verify %s
+
+// pr33561
+class ArrayBuffer;
+template <typename T> class Trans_NS_WTF_RefPtr {
+public:
+ ArrayBuffer *operator->() { return nullptr; }
+};
+Trans_NS_WTF_RefPtr<ArrayBuffer> get();
+template <typename _Visitor>
+constexpr void visit(_Visitor __visitor) {
+ __visitor(get()); // expected-note {{in instantiation}}
+}
+class ArrayBuffer {
+ char data() {
+ visit([](auto buffer) -> char { // expected-note {{in instantiation}}
+ buffer->data();
+ }); // expected-warning {{control reaches end of non-void lambda}}
+ } // expected-warning {{control reaches end of non-void function}}
+};
+
+// pr34185
+template <typename Promise> struct coroutine_handle {
+ Promise &promise() const { return
+ *static_cast<Promise *>(nullptr); // expected-warning {{binding dereferenced null}}
+ }
+};
+
+template <typename Promise> auto GetCurrenPromise() {
+ struct Awaiter { // expected-note {{in instantiation}}
+ void await_suspend(coroutine_handle<Promise> h) {
+ h.promise(); // expected-note {{in instantiation}}
+ }
+ };
+ return Awaiter{};
+}
+
+void foo() {
+ auto &&p = GetCurrenPromise<int>(); // expected-note {{in instantiation}}
+}
diff --git a/test/SemaTemplate/metafun-apply.cpp b/test/SemaTemplate/metafun-apply.cpp
index 3a7408e28025..55f6194a5103 100644
--- a/test/SemaTemplate/metafun-apply.cpp
+++ b/test/SemaTemplate/metafun-apply.cpp
@@ -15,7 +15,7 @@ struct add_reference {
};
struct bogus {
- struct apply {
+ struct apply { // expected-note{{declared as a non-template here}}
typedef int type;
};
};
diff --git a/test/SemaTemplate/ms-function-specialization-class-scope.cpp b/test/SemaTemplate/ms-function-specialization-class-scope.cpp
index 3c7111d05838..dcab9bfaeabc 100644
--- a/test/SemaTemplate/ms-function-specialization-class-scope.cpp
+++ b/test/SemaTemplate/ms-function-specialization-class-scope.cpp
@@ -1,18 +1,15 @@
// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify %s
// RUN: %clang_cc1 -fms-extensions -fdelayed-template-parsing -fsyntax-only -verify %s
+// expected-no-diagnostics
class A {
public:
template<class U> A(U p) {}
- template<> A(int p) {
- // expected-warning@-1 {{explicit specialization of 'A' within class scope is a Microsoft extension}}
- }
+ template<> A(int p) {}
template<class U> void f(U p) {}
- template<> void f(int p) {
- // expected-warning@-1 {{explicit specialization of 'f' within class scope is a Microsoft extension}}
- }
+ template<> void f(int p) {}
void f(int p) {}
};
@@ -28,14 +25,11 @@ void test1() {
template<class T> class B {
public:
template<class U> B(U p) {}
- template<> B(int p) {
- // expected-warning@-1 {{explicit specialization of 'B<T>' within class scope is a Microsoft extension}}
- }
+ template<> B(int p) {}
template<class U> void f(U p) { T y = 9; }
template<> void f(int p) {
- // expected-warning@-1 {{explicit specialization of 'f' within class scope is a Microsoft extension}}
T a = 3;
}
@@ -56,9 +50,7 @@ namespace PR12709 {
template<bool b> void specialized_member_template() {}
- template<> void specialized_member_template<false>() {
- // expected-warning@-1 {{explicit specialization of 'specialized_member_template' within class scope is a Microsoft extension}}
- }
+ template<> void specialized_member_template<false>() {}
};
void f() { TemplateClass<int> t; }
@@ -67,8 +59,8 @@ namespace PR12709 {
namespace Duplicates {
template<typename T> struct A {
template<typename U> void f();
- template<> void f<int>() {} // expected-warning {{Microsoft extension}}
- template<> void f<T>() {} // expected-warning {{Microsoft extension}}
+ template<> void f<int>() {}
+ template<> void f<T>() {}
};
// FIXME: We should diagnose the duplicate explicit specialization definitions
@@ -81,6 +73,6 @@ struct S {
template <int>
int f(int = 0);
template <>
- int f<0>(int); // expected-warning {{Microsoft extension}}
+ int f<0>(int);
};
}
diff --git a/test/SemaTemplate/nested-name-spec-template.cpp b/test/SemaTemplate/nested-name-spec-template.cpp
index 78d09d13deea..e9d0eb202033 100644
--- a/test/SemaTemplate/nested-name-spec-template.cpp
+++ b/test/SemaTemplate/nested-name-spec-template.cpp
@@ -49,7 +49,7 @@ namespace N {
struct X;
};
- struct B;
+ struct B; // expected-note{{declared as a non-template here}}
}
struct ::N::A<int>::X {
@@ -131,7 +131,7 @@ namespace PR9226 {
template<typename T, typename U>
struct Y {
- typedef typename T::template f<U> type; // expected-error{{template name refers to non-type template 'X::f'}}
+ typedef typename T::template f<U> type; // expected-error{{template name refers to non-type template 'X::template f'}}
};
Y<X, int> yxi; // expected-note{{in instantiation of template class 'PR9226::Y<PR9226::X, int>' requested here}}
@@ -144,7 +144,7 @@ namespace PR9449 {
template <typename T>
void f() {
int s<T>::template n<T>::* f; // expected-error{{implicit instantiation of undefined template 'PR9449::s<int>'}} \
- // expected-error{{following the 'template' keyword}}
+ // expected-error{{no member named 'n'}}
}
template void f<int>(); // expected-note{{in instantiation of}}
diff --git a/test/SemaTemplate/nested-template.cpp b/test/SemaTemplate/nested-template.cpp
index 44cb82e95bbf..efbde2076b9f 100644
--- a/test/SemaTemplate/nested-template.cpp
+++ b/test/SemaTemplate/nested-template.cpp
@@ -161,3 +161,10 @@ class Outer1 {
template <typename T> struct X;
template <typename T> int X<T>::func() {} // expected-error{{out-of-line definition of 'func' from class 'X<T>' without definition}}
};
+
+namespace RefPack {
+ template<const int &...N> struct A { template<typename ...T> void f(T (&...t)[N]); };
+ constexpr int k = 10;
+ int arr[10];
+ void g() { A<k>().f(arr); }
+}
diff --git a/test/SemaTemplate/pack-deduction.cpp b/test/SemaTemplate/pack-deduction.cpp
index 84eefa63d215..f9309d52111e 100644
--- a/test/SemaTemplate/pack-deduction.cpp
+++ b/test/SemaTemplate/pack-deduction.cpp
@@ -65,3 +65,104 @@ namespace PR14615 {
void f() { check<char>(1, 2); } // expected-error {{no matching function}}
}
}
+
+namespace fully_expanded_packs {
+ template<typename ...T> struct A {
+ template<T ...X> static constexpr int f() {
+ // expected-note@-1 1+{{deduced too few arguments for expanded pack 'X'}}
+ // expected-note@-2 1+{{too many template arguments}}
+ return (X + ... + 0); // expected-warning {{extension}}
+ }
+
+ template<T ...X, int Y> static constexpr int g() {
+ // expected-note@-1 1+{{deduced too few arguments for expanded pack 'X'}}
+ // expected-note@-2 1+{{couldn't infer template argument 'Y'}}
+ // expected-note@-3 1+{{too many template arguments}}
+ return (X + ... + (1000 * Y)); // expected-warning {{extension}}
+ }
+
+ template<T ...X, int Y, T ...Z> static constexpr int h() {
+ // expected-note@-1 1+{{deduced too few arguments for expanded pack 'X'}}
+ // expected-note@-2 1+{{couldn't infer template argument 'Y'}}
+ // expected-note@-3 1+{{deduced too few arguments for expanded pack 'Z'}}
+ // expected-note@-4 1+{{too many template arguments}}
+ return (X + ... + (1000 * Y)) + 1000000 * (Z + ... + 0); // expected-warning 2{{extension}}
+ }
+
+ template<T ...X, int ...Z> static constexpr int i() {
+ return (X + ... + 0) + 1000 * (Z + ... + 0); // expected-warning 2{{extension}}
+ }
+
+ template<T ...X, int Y, int ...Z> static constexpr int j() {
+ return (X + ... + (1000 * Y)) + 1000000 * (Z + ... + 0); // expected-warning 2{{extension}}
+ }
+ };
+
+ void check_invalid_calls() {
+ A<int, int>::f(); // expected-error {{no matching function}}
+ A<int, int>::f<>(); // expected-error {{no matching function}}
+ A<int, int>::f<0>(); // expected-error {{no matching function}}
+ A<int, int>::g(); // expected-error {{no matching function}}
+ A<int, int>::g<>(); // expected-error {{no matching function}}
+ A<int, int>::g<0>(); // expected-error {{no matching function}}
+ A<int, int>::g<0, 0>(); // expected-error {{no matching function}}
+ A<>::f<0>(); // expected-error {{no matching function}}
+ A<>::g(); // expected-error {{no matching function}}
+ A<>::g<>(); // expected-error {{no matching function}}
+ A<>::g<0, 0>(); // expected-error {{no matching function}}
+ A<>::h<>(); // expected-error {{no matching function}}
+ A<int>::h<>(); // expected-error {{no matching function}}
+ A<int>::h<0, 0>(); // expected-error {{no matching function}}
+ A<>::h<0, 0>(); // expected-error {{no matching function}}
+ }
+
+ static_assert(A<>::f() == 0, "");
+ static_assert(A<int>::f<1>() == 1, "");
+ static_assert(A<>::g<1>() == 1000, "");
+ static_assert(A<int>::g<1, 2>() == 2001, "");
+ static_assert(A<>::h<1>() == 1000, "");
+ static_assert(A<int>::h<1, 2, 3>() == 3002001, "");
+ static_assert(A<int, int>::h<1, 20, 3, 4, 50>() == 54003021, "");
+ static_assert(A<>::i<1>() == 1000, "");
+ static_assert(A<int>::i<1>() == 1, "");
+ static_assert(A<>::j<1, 2, 30>() == 32001000, "");
+ static_assert(A<int>::j<1, 2, 3, 40>() == 43002001, "");
+}
+
+namespace partial_full_mix {
+ template<typename T, typename U> struct pair {};
+ template<typename ...T> struct tuple {};
+ template<typename ...T> struct A {
+ template<typename ...U> static pair<tuple<T...>, tuple<U...>> f(pair<T, U> ...p);
+ // expected-note@-1 {{[with U = <char, double, long>]: pack expansion contains parameter pack 'U' that has a different length (2 vs. 3) from outer parameter packs}}
+ // expected-note@-2 {{[with U = <char, double, void>]: pack expansion contains parameter pack 'U' that has a different length (at least 3 vs. 2) from outer parameter packs}}
+
+ template<typename ...U> static pair<tuple<T...>, tuple<U...>> g(pair<T, U> ...p, ...);
+ // expected-note@-1 {{[with U = <char, double, long>]: pack expansion contains parameter pack 'U' that has a different length (2 vs. 3) from outer parameter packs}}
+
+ template<typename ...U> static tuple<U...> h(tuple<pair<T, U>..., pair<int, int>>);
+ // expected-note@-1 {{[with U = <int [2]>]: pack expansion contains parameter pack 'U' that has a different length (2 vs. 1) from outer parameter packs}}
+ };
+
+ pair<tuple<int, float>, tuple<char, double>> k1 = A<int, float>().f<char>(pair<int, char>(), pair<float, double>());
+ pair<tuple<int, float>, tuple<char, double>> k2 = A<int, float>().f<char>(pair<int, char>(), pair<float, double>(), pair<void, long>()); // expected-error {{no match}}
+ pair<tuple<int, float>, tuple<char, double>> k3 = A<int, float>().f<char, double, void>(pair<int, char>(), pair<float, double>()); // expected-error {{no match}}
+
+ // FIXME: We should accept this by treating the pack 'p' as having a fixed length of 2 here.
+ pair<tuple<int, float>, tuple<char, double>> k4 = A<int, float>().g<char>(pair<int, char>(), pair<float, double>(), pair<void, long>()); // expected-error {{no match}}
+
+ // FIXME: We should accept this by treating the pack of pairs as having a fixed length of 2 here.
+ tuple<int[2], int[4]> k5 = A<int[1], int[3]>::h<int[2]>(tuple<pair<int[1], int[2]>, pair<int[3], int[4]>, pair<int, int>>()); // expected-error {{no match}}
+}
+
+namespace substitution_vs_function_deduction {
+ template <typename... T> struct A {
+ template <typename... U> void f(void(*...)(T, U)); // expected-warning {{ISO C++11 requires a parenthesized pack declaration to have a name}}
+ template <typename... U> void g(void...(T, U)); // expected-note {{could not match 'void (T, U)' against 'void (*)(int, int)'}}
+ };
+ void f(int, int) {
+ A<int>().f(f);
+ // FIXME: We fail to decay the parameter to a pointer type.
+ A<int>().g(f); // expected-error {{no match}}
+ }
+}
diff --git a/test/SemaTemplate/partial-spec-instantiate.cpp b/test/SemaTemplate/partial-spec-instantiate.cpp
index d5ecd8c1e3bf..2fc0517ae3d3 100644
--- a/test/SemaTemplate/partial-spec-instantiate.cpp
+++ b/test/SemaTemplate/partial-spec-instantiate.cpp
@@ -55,3 +55,46 @@ namespace rdar9169404 {
// expected-no-diagnostics
#endif
}
+
+// rdar://problem/39524996
+namespace rdar39524996 {
+ template <typename T, typename U>
+ struct enable_if_not_same
+ {
+ typedef void type;
+ };
+ template <typename T>
+ struct enable_if_not_same<T, T>;
+
+ template <typename T>
+ struct Wrapper {
+ // Assertion triggered on trying to set twice the same partial specialization
+ // enable_if_not_same<int, int>
+ template <class U>
+ Wrapper(const Wrapper<U>& other,
+ typename enable_if_not_same<U, T>::type* = 0) {}
+
+ explicit Wrapper(int i) {}
+ };
+
+ template <class T>
+ struct Container {
+ // It is important that the struct has implicit copy and move constructors.
+ Container() : x() {}
+
+ template <class U>
+ Container(const Container<U>& other) : x(static_cast<T>(other.x)) {}
+
+ // Implicit constructors are member-wise, so the field triggers instantiation
+ // of T constructors and we instantiate all of them for overloading purposes.
+ T x;
+ };
+
+ void takesWrapperInContainer(const Container< Wrapper<int> >& c);
+ void test() {
+ // Type mismatch triggers initialization with conversion which requires
+ // implicit constructors to be instantiated.
+ Container<int> c;
+ takesWrapperInContainer(c);
+ }
+}
diff --git a/test/SemaTemplate/sizeof-pack.cpp b/test/SemaTemplate/sizeof-pack.cpp
new file mode 100644
index 000000000000..4b0c883a24ac
--- /dev/null
+++ b/test/SemaTemplate/sizeof-pack.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -std=c++11 -verify %s
+// expected-no-diagnostics
+
+template<int &...Ns> int f() {
+ return sizeof...(Ns);
+}
+template int f<>();
diff --git a/test/SemaTemplate/stmt-expr.cpp b/test/SemaTemplate/stmt-expr.cpp
new file mode 100644
index 000000000000..2516a5220c1a
--- /dev/null
+++ b/test/SemaTemplate/stmt-expr.cpp
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -verify %s
+
+// FIXME: We could in principle support cases like this (particularly, cases
+// where the statement-expression contains no labels).
+template <typename... T> void f1() {
+ int arr[] = {
+ ({
+ T(); // expected-error {{unexpanded parameter pack}}
+ }) ... // expected-error {{does not contain any unexpanded parameter packs}}
+ };
+}
+
+// FIXME: The error for this isn't ideal; it'd be preferable to say that pack
+// expansion of a statement expression is not permitted.
+template <typename... T> void f2() {
+ [] {
+ int arr[] = {
+ T() + ({
+ foo:
+ T t; // expected-error {{unexpanded parameter pack}}
+ goto foo;
+ 0;
+ }) ...
+ };
+ };
+}
+
+template <typename... T> void f3() {
+ ({
+ int arr[] = {
+ [] {
+ foo:
+ T t; // OK, expanded within compound statement
+ goto foo;
+ return 0;
+ } ...
+ };
+ });
+}
diff --git a/test/SemaTemplate/temp-param-subst-linear.cpp b/test/SemaTemplate/temp-param-subst-linear.cpp
new file mode 100644
index 000000000000..fd93aa568553
--- /dev/null
+++ b/test/SemaTemplate/temp-param-subst-linear.cpp
@@ -0,0 +1,56 @@
+// RUN: %clang_cc1 -std=c++17 %s -verify
+// expected-no-diagnostics
+
+// This test attempts to ensure that the below template parameter pack
+// splitting technique executes in linear time in the number of template
+// parameters. The size of the list below is selected so as to execute
+// relatively quickly on a "good" compiler and to time out otherwise.
+
+template<typename...> struct TypeList;
+
+namespace detail {
+template<unsigned> using Unsigned = unsigned;
+template<typename T, T ...N> using ListOfNUnsignedsImpl = TypeList<Unsigned<N>...>;
+template<unsigned N> using ListOfNUnsigneds =
+ __make_integer_seq<ListOfNUnsignedsImpl, unsigned, N>;
+
+template<typename T> struct TypeWrapper {
+ template<unsigned> using AsTemplate = T;
+};
+
+template<typename ...N> struct Splitter {
+ template<template<N> class ...L,
+ template<unsigned> class ...R> struct Split {
+ using Left = TypeList<L<0>...>;
+ using Right = TypeList<R<0>...>;
+ };
+};
+}
+
+template<typename TypeList, unsigned N, typename = detail::ListOfNUnsigneds<N>>
+struct SplitAtIndex;
+
+template<typename ...T, unsigned N, typename ...NUnsigneds>
+struct SplitAtIndex<TypeList<T...>, N, TypeList<NUnsigneds...>> :
+ detail::Splitter<NUnsigneds...>::
+ template Split<detail::TypeWrapper<T>::template AsTemplate...> {};
+
+template<typename T, int N> struct Rep : Rep<typename Rep<T, N-1>::type, 1> {};
+template<typename ...T> struct Rep<TypeList<T...>, 1> { typedef TypeList<T..., T...> type; };
+
+using Ints = Rep<TypeList<int>, 14>::type;
+
+template<typename T> extern int Size;
+template<typename ...T> constexpr int Size<TypeList<T...>> = sizeof...(T);
+
+using Left = SplitAtIndex<Ints, Size<Ints> / 2>::Left;
+using Right = SplitAtIndex<Ints, Size<Ints> / 2>::Right;
+static_assert(Size<Left> == 8192);
+static_assert(Size<Right> == 8192);
+
+template<typename L, typename R> struct Concat;
+template<typename ...L, typename ...R> struct Concat<TypeList<L...>, TypeList<R...>> {
+ using type = TypeList<L..., R...>;
+};
+
+using Ints = Concat<Left, Right>::type;
diff --git a/test/SemaTemplate/temp_arg_nontype_cxx11.cpp b/test/SemaTemplate/temp_arg_nontype_cxx11.cpp
index 0b8f0eed1601..313114e2cb8e 100644
--- a/test/SemaTemplate/temp_arg_nontype_cxx11.cpp
+++ b/test/SemaTemplate/temp_arg_nontype_cxx11.cpp
@@ -36,3 +36,15 @@ namespace check_conversion_early {
struct Y { constexpr operator int() const { return 0; } };
template<Y &y> struct A<y> {}; // expected-error {{cannot be deduced}} expected-note {{'y'}}
}
+
+namespace ReportCorrectParam {
+template <int a, unsigned b, int c>
+void TempFunc() {}
+
+void Useage() {
+ //expected-error@+2 {{no matching function}}
+ //expected-note@-4 {{candidate template ignored: invalid explicitly-specified argument for template parameter 'b'}}
+ TempFunc<1, -1, 1>();
+}
+}
+
diff --git a/test/SemaTemplate/temp_arg_pack.cpp b/test/SemaTemplate/temp_arg_pack.cpp
new file mode 100644
index 000000000000..b79dca78bced
--- /dev/null
+++ b/test/SemaTemplate/temp_arg_pack.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -verify %s
+
+namespace deduce_pack_non_pack {
+ template <typename...> class A;
+ template <typename> struct C {};
+ template <typename T> void g(C<A<T>>); // expected-note {{candidate template ignored: deduced type 'C<A<[...], (no argument)>>' of 1st parameter does not match adjusted type 'C<A<[...], int>>' of argument [with T = bool]}}
+ void h(C<A<bool, int>> &x) { g(x); } // expected-error {{no matching function}}
+}
diff --git a/test/SemaTemplate/temp_class_spec_neg.cpp b/test/SemaTemplate/temp_class_spec_neg.cpp
index 6366a528ff53..7465e5e8caaa 100644
--- a/test/SemaTemplate/temp_class_spec_neg.cpp
+++ b/test/SemaTemplate/temp_class_spec_neg.cpp
@@ -7,17 +7,11 @@ template<typename T> struct vector;
namespace N {
namespace M {
template<typename T> struct A;
-#if __cplusplus <= 199711L // C++03 or earlier modes
- // expected-note@-2{{explicitly specialized declaration is here}}
-#endif
}
}
template<typename T>
struct N::M::A<T*> { };
-#if __cplusplus <= 199711L
-// expected-warning@-2{{first declaration of class template partial specialization of 'A' outside namespace 'M' is a C++11 extension}}
-#endif
// C++ [temp.class.spec]p9
// bullet 1, as amended by DR1315
diff --git a/test/SemaTemplate/template-id-expr.cpp b/test/SemaTemplate/template-id-expr.cpp
index 4e6e22479b3f..0555d8b94504 100644
--- a/test/SemaTemplate/template-id-expr.cpp
+++ b/test/SemaTemplate/template-id-expr.cpp
@@ -56,7 +56,7 @@ struct Y0 {
template<typename U>
static void f2(U);
- void f3(int);
+ void f3(int); // expected-note 2{{declared as a non-template here}}
static int f4(int);
template<typename U>
@@ -85,10 +85,85 @@ struct Y0 {
}
};
+template<typename U> void Y0
+ ::template // expected-error {{expected unqualified-id}}
+ f1(U) {}
+
+// FIXME: error recovery is awful without this.
+ ;
+
+template<typename T>
+struct Y1 {
+ template<typename U>
+ void f1(U);
+
+ template<typename U>
+ static void f2(U);
+
+ void f3(int); // expected-note 4{{declared as a non-template here}}
+
+ static int f4(int);
+ template<typename U>
+ static void f4(U);
+
+ template<typename U>
+ void f() {
+ Y1::template f1<U>(0);
+ Y1::template f1(0);
+ this->template f1(0);
+
+ Y1::template f2<U>(0);
+ Y1::template f2(0);
+
+ Y1::template f3(0); // expected-error {{'f3' following the 'template' keyword does not refer to a template}}
+ Y1::template f3(); // expected-error {{'f3' following the 'template' keyword does not refer to a template}}
+
+ int x;
+ x = Y1::f4(0);
+ x = Y1::f4<int>(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
+ x = Y1::template f4(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
+
+ x = this->f4(0);
+ x = this->f4<int>(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
+ x = this->template f4(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
+ }
+};
+
+void use_Y1(Y1<int> y1) { y1.f<int>(); } // expected-note {{in instantiation of}}
+
+template<typename T>
+struct Y2 : Y1<T> {
+ typedef ::Y1<T> Y1;
+
+ template<typename U>
+ void f(Y1 *p) {
+ Y1::template f1<U>(0);
+ Y1::template f1(0);
+ p->template f1(0);
+
+ Y1::template f2<U>(0);
+ Y1::template f2(0);
+
+ Y1::template f3(0); // expected-error {{'f3' following the 'template' keyword does not refer to a template}}
+ Y1::template f3(); // expected-error {{'f3' following the 'template' keyword does not refer to a template}}
+
+ int x;
+ x = Y1::f4(0);
+ x = Y1::f4<int>(0); // expected-error {{use 'template'}} expected-error {{assigning to 'int' from incompatible type 'void'}}
+ x = Y1::template f4(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
+
+ x = p->f4(0);
+ x = p->f4<int>(0); // expected-error {{assigning to 'int' from incompatible type 'void'}} expected-error {{use 'template'}}
+ x = p->template f4(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
+ }
+};
+
+void use_Y2(Y2<int> y2) { y2.f<int>(0); } // expected-note {{in instantiation of}}
+
struct A {
template<int I>
struct B {
- static void b1();
+ static void b1(); // expected-note {{declared as a non-template here}}
};
};
diff --git a/test/SemaTemplate/typo-dependent-name.cpp b/test/SemaTemplate/typo-dependent-name.cpp
index 78cedd0c98ca..0231740f6c2e 100644
--- a/test/SemaTemplate/typo-dependent-name.cpp
+++ b/test/SemaTemplate/typo-dependent-name.cpp
@@ -1,18 +1,45 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
-// expected-no-diagnostics
+
+using nullptr_t = decltype(nullptr);
template<typename T>
struct Base {
T inner;
};
+int z;
+
template<typename T>
-struct X {
- template<typename U>
+struct X : Base<T> {
+ static int z;
+
+ template<int U>
struct Inner {
};
bool f(T other) {
- return this->inner < other;
+ // A pair of comparisons; 'inner' is a dependent name so can't be assumed
+ // to be a template.
+ return this->inner < other > ::z;
}
};
+
+void use_x(X<int> x) { x.f(0); }
+
+template<typename T>
+struct Y {
+ static int z;
+
+ template<int U>
+ struct Inner : Y { // expected-note {{declared here}}
+ };
+
+ bool f(T other) {
+ // We can determine that 'inner' does not exist at parse time, so can
+ // perform typo correction in this case.
+ return this->inner<other>::z; // expected-error {{no template named 'inner' in 'Y<T>'; did you mean 'Inner'?}}
+ }
+};
+
+struct Q { constexpr operator int() { return 0; } };
+void use_y(Y<Q> x) { x.f(Q()); }
diff --git a/test/SemaTemplate/undefined-template.cpp b/test/SemaTemplate/undefined-template.cpp
index 7dfe2fde94b0..52530e2e3909 100644
--- a/test/SemaTemplate/undefined-template.cpp
+++ b/test/SemaTemplate/undefined-template.cpp
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++14 -Wundefined-func-template %s
+#if !defined(INCLUDE)
template <class T> struct C1 {
static char s_var_1; // expected-note{{forward declaration of template entity is here}}
static char s_var_2; // expected-note{{forward declaration of template entity is here}}
@@ -142,6 +143,16 @@ namespace test_24 {
void h(X<int> x) { g(x); } // no warning for use of 'g' despite the declaration having been instantiated from a template
}
+#define INCLUDE
+#include "undefined-template.cpp"
+void func_25(SystemHeader<char> *x) {
+ x->meth();
+}
+
int main() {
return 0;
}
+#else
+#pragma clang system_header
+template <typename T> struct SystemHeader { T meth(); };
+#endif
diff --git a/test/SemaTemplate/warn-thread-safety-analysis.cpp b/test/SemaTemplate/warn-thread-safety-analysis.cpp
new file mode 100644
index 000000000000..710f424c17dc
--- /dev/null
+++ b/test/SemaTemplate/warn-thread-safety-analysis.cpp
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -std=c++11 %s -verify -Wthread-safety-analysis
+
+class Mutex {
+public:
+ void Lock() __attribute__((exclusive_lock_function()));
+ void Unlock() __attribute__((unlock_function()));
+};
+
+class A {
+public:
+ Mutex mu1, mu2;
+
+ void foo() __attribute__((exclusive_locks_required(mu1))) __attribute__((exclusive_locks_required(mu2))) {}
+
+ template <class T> void bar() __attribute__((exclusive_locks_required(mu1))) __attribute__((exclusive_locks_required(mu2))) {
+ foo();
+ }
+};
+
+void f() {
+ A a;
+ a.mu1.Lock();
+ a.mu2.Lock();
+ a.bar<int>();
+ a.mu2.Unlock();
+ a.bar<int>(); // expected-warning {{calling function 'bar<int>' requires holding mutex 'a.mu2' exclusively}}
+ a.mu1.Unlock();
+ a.bar<int>(); // expected-warning {{calling function 'bar<int>' requires holding mutex 'a.mu1' exclusively}} \
+ expected-warning {{calling function 'bar<int>' requires holding mutex 'a.mu2' exclusively}}
+}
diff --git a/test/TableGen/DiagnosticBase.inc b/test/TableGen/DiagnosticBase.inc
index afa85f538b2d..e9a8b9761155 100644
--- a/test/TableGen/DiagnosticBase.inc
+++ b/test/TableGen/DiagnosticBase.inc
@@ -1,35 +1,130 @@
-// Define the diagnostic mappings.
-class DiagMapping;
-def MAP_IGNORE : DiagMapping;
-def MAP_WARNING : DiagMapping;
-def MAP_ERROR : DiagMapping;
-def MAP_FATAL : DiagMapping;
+//===--- DiagnosticBase.inc - A test file mimicking Diagnostic.td ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the TableGen core definitions for the diagnostics
+// and diagnostic control.
+//
+//===----------------------------------------------------------------------===//
+
+// See the Internals Manual, section The Diagnostics Subsystem for an overview.
+
+// Define the diagnostic severities.
+class Severity<string N> {
+ string Name = N;
+}
+def SEV_Ignored : Severity<"Ignored">;
+def SEV_Remark : Severity<"Remark">;
+def SEV_Warning : Severity<"Warning">;
+def SEV_Error : Severity<"Error">;
+def SEV_Fatal : Severity<"Fatal">;
// Define the diagnostic classes.
class DiagClass;
def CLASS_NOTE : DiagClass;
+def CLASS_REMARK : DiagClass;
def CLASS_WARNING : DiagClass;
def CLASS_EXTENSION : DiagClass;
def CLASS_ERROR : DiagClass;
+// Responses to a diagnostic in a SFINAE context.
+class SFINAEResponse;
+def SFINAE_SubstitutionFailure : SFINAEResponse;
+def SFINAE_Suppress : SFINAEResponse;
+def SFINAE_Report : SFINAEResponse;
+def SFINAE_AccessControl : SFINAEResponse;
+
+// 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> {
+ string CategoryName = Name;
+}
+
+// Diagnostic Groups.
class DiagGroup<string Name, list<DiagGroup> subgroups = []> {
string GroupName = Name;
list<DiagGroup> SubGroups = subgroups;
string CategoryName = "";
+ code Documentation = [{}];
}
class InGroup<DiagGroup G> { DiagGroup Group = G; }
+//class IsGroup<string Name> { DiagGroup Group = DiagGroup<Name>; }
+
+include "DiagnosticDocs.inc"
// All diagnostics emitted by the compiler are an indirect subclass of this.
-class Diagnostic<string text, DiagClass DC, DiagMapping defaultmapping> {
- string Text = text;
- DiagClass Class = DC;
- DiagMapping DefaultMapping = defaultmapping;
- DiagGroup Group;
- string CategoryName = "";
-}
-
-class Error<string str> : Diagnostic<str, CLASS_ERROR, MAP_ERROR>;
-class Warning<string str> : Diagnostic<str, CLASS_WARNING, MAP_WARNING>;
-class Extension<string str> : Diagnostic<str, CLASS_EXTENSION, MAP_IGNORE>;
-class ExtWarn<string str> : Diagnostic<str, CLASS_EXTENSION, MAP_WARNING>;
-class Note<string str> : Diagnostic<str, CLASS_NOTE, MAP_FATAL/*ignored*/>;
+class Diagnostic<string text, DiagClass DC, Severity defaultmapping> {
+ /// Component is specified by the file with a big let directive.
+ string Component = ?;
+ string Text = text;
+ DiagClass Class = DC;
+ SFINAEResponse SFINAE = SFINAE_Suppress;
+ bit AccessControl = 0;
+ bit WarningNoWerror = 0;
+ bit ShowInSystemHeader = 0;
+ Severity DefaultSeverity = defaultmapping;
+ DiagGroup Group;
+ string CategoryName = "";
+}
+
+class SFINAEFailure {
+ SFINAEResponse SFINAE = SFINAE_SubstitutionFailure;
+}
+class NoSFINAE {
+ SFINAEResponse SFINAE = SFINAE_Report;
+}
+class AccessControl {
+ SFINAEResponse SFINAE = SFINAE_AccessControl;
+}
+
+class ShowInSystemHeader {
+ bit ShowInSystemHeader = 1;
+}
+
+class SuppressInSystemHeader {
+ bit ShowInSystemHeader = 0;
+}
+
+// FIXME: ExtWarn and Extension should also be SFINAEFailure by default.
+class Error<string str> : Diagnostic<str, CLASS_ERROR, SEV_Error>, SFINAEFailure {
+ bit ShowInSystemHeader = 1;
+}
+// Warnings default to on (but can be default-off'd with DefaultIgnore).
+// This is used for warnings about questionable code; warnings about
+// accepted language extensions should use Extension or ExtWarn below instead.
+class Warning<string str> : Diagnostic<str, CLASS_WARNING, SEV_Warning>;
+// Remarks can be turned on with -R flags and provide commentary, e.g. on
+// optimizer decisions.
+class Remark<string str> : Diagnostic<str, CLASS_REMARK, SEV_Ignored>;
+// Extensions are warnings about accepted language extensions.
+// Extension warnings are default-off but enabled by -pedantic.
+class Extension<string str> : Diagnostic<str, CLASS_EXTENSION, SEV_Ignored>;
+// ExtWarns are warnings about accepted language extensions.
+// ExtWarn warnings are default-on.
+class ExtWarn<string str> : Diagnostic<str, CLASS_EXTENSION, SEV_Warning>;
+// Notes can provide supplementary information on errors, warnings, and remarks.
+class Note<string str> : Diagnostic<str, CLASS_NOTE, SEV_Fatal/*ignored*/>;
+
+
+class DefaultIgnore { Severity DefaultSeverity = SEV_Ignored; }
+class DefaultWarn { Severity DefaultSeverity = SEV_Warning; }
+class DefaultError { Severity DefaultSeverity = SEV_Error; }
+class DefaultFatal { Severity DefaultSeverity = SEV_Fatal; }
+class DefaultWarnNoWerror {
+ bit WarningNoWerror = 1;
+}
+class DefaultRemark { Severity DefaultSeverity = SEV_Remark; }
diff --git a/test/TableGen/DiagnosticDocs.inc b/test/TableGen/DiagnosticDocs.inc
new file mode 100644
index 000000000000..4b114059382f
--- /dev/null
+++ b/test/TableGen/DiagnosticDocs.inc
@@ -0,0 +1,75 @@
+
+def GlobalDocumentation {
+ code Intro =[{..
+ -------------------------------------------------------------------
+ NOTE: This file is automatically generated by running clang-tblgen
+ -gen-diag-docs. Do not edit this file by hand!!
+ -------------------------------------------------------------------
+
+.. Add custom CSS to output. FIXME: This should be put into <head> rather
+ than the start of <body>.
+.. raw:: html
+
+ <style>
+ table.docutils {
+ width: 1px;
+ }
+ table.docutils td {
+ border: none;
+ padding: 0 0 0 0.2em;
+ vertical-align: middle;
+ white-space: nowrap;
+ width: 1px;
+ font-family: monospace;
+ }
+ table.docutils tr + tr {
+ border-top: 0.2em solid #aaa;
+ }
+ .error {
+ font-family: monospace;
+ font-weight: bold;
+ color: #c00;
+ }
+ .warning {
+ font-family: monospace;
+ font-weight: bold;
+ color: #80a;
+ }
+ .remark {
+ font-family: monospace;
+ font-weight: bold;
+ color: #00c;
+ }
+ .diagtext {
+ font-family: monospace;
+ font-weight: bold;
+ }
+ </style>
+
+.. FIXME: rST doesn't support formatting this, so we format all <td> elements
+ as monospace font face instead.
+.. |nbsp| unicode:: 0xA0
+ :trim:
+
+.. Roles generated by clang-tblgen.
+.. role:: error
+.. role:: warning
+.. role:: remark
+.. role:: diagtext
+.. role:: placeholder(emphasis)
+
+=========================
+Diagnostic flags in Clang
+=========================
+.. contents::
+ :local:
+
+Introduction
+============
+
+This page lists the diagnostic flags currently supported by Clang.
+
+Diagnostic flags
+================
+}];
+}
diff --git a/test/TableGen/anonymous-groups.td b/test/TableGen/anonymous-groups.td
index acc0a211b661..9e8dc398bb24 100644
--- a/test/TableGen/anonymous-groups.td
+++ b/test/TableGen/anonymous-groups.td
@@ -7,21 +7,17 @@ def NamedGroup : DiagGroup<"name">;
def InNamedGroup : Warning<"">, InGroup<DiagGroup<"name">>;
-// CHECK: anonymous-groups.td:[[@LINE-1]]:41: error: group 'name' is referred to anonymously
+// CHECK: anonymous-groups.td:[[@LINE-1]]:1: error: group 'name' is referred to anonymously
// CHECK-NEXT: {{^def InNamedGroup : Warning<"">, InGroup<DiagGroup<"name">>;}}
-// CHECK-NEXT: {{^ ~~~~~~~~\^~~~~~~~~~~~~~~~~~}}
-// CHECK-NEXT: {{^ InGroup<NamedGroup>}}
-// CHECK-NEXT: anonymous-groups.td:6:1: note: group defined here
+// CHECK: anonymous-groups.td:6:1: note: group defined here
// CHECK-NEXT: def NamedGroup : DiagGroup<"name">;
// CHECK-NEXT: ^
def AlsoInNamedGroup : Warning<"">, InGroup < DiagGroup<"name"> >;
-// CHECK: anonymous-groups.td:[[@LINE-1]]:48: error: group 'name' is referred to anonymously
+// CHECK: anonymous-groups.td:[[@LINE-1]]:1: error: group 'name' is referred to anonymously
// CHECK-NEXT: {{^def AlsoInNamedGroup : Warning<"">, InGroup < DiagGroup<"name"> >;}}
-// CHECK-NEXT: {{^ ~~~~~~~~~~~\^~~~~~~~~~~~~~~~~~~}}
-// CHECK-NEXT: {{^ InGroup<NamedGroup>}}
-// CHECK-NEXT: anonymous-groups.td:6:1: note: group defined here
+// CHECK: anonymous-groups.td:6:1: note: group defined here
// CHECK-NEXT: def NamedGroup : DiagGroup<"name">;
// CHECK-NEXT: ^
@@ -31,12 +27,8 @@ def AlsoAnonymousGroup : Warning<"">, InGroup<DiagGroup<"anonymous">>;
def AnonymousGroupAgain : Warning<"">,
InGroup<DiagGroup<"anonymous">>;
-// CHECK: anonymous-groups.td:[[@LINE-5]]:43: error: group 'anonymous' is referred to anonymously
+// CHECK: anonymous-groups.td:[[@LINE-5]]:1: error: group 'anonymous' is referred to anonymously
// CHECK-NEXT: {{^def AnonymousGroup : Warning<"">, InGroup<DiagGroup<"anonymous">>;}}
-// CHECK-NEXT: {{^ ~~~~~~~~\^~~~~~~~~~~~~~~~~~~~~~~}}
-// CHECK-NEXT: anonymous-groups.td:[[@LINE-7]]:47: note: also referenced here
+// CHECK: anonymous-groups.td:[[@LINE-6]]:1: note: also referenced here
// CHECK-NEXT: {{^def AlsoAnonymousGroup : Warning<"">, InGroup<DiagGroup<"anonymous">>;}}
-// CHECK-NEXT: {{^ ~~~~~~~~\^~~~~~~~~~~~~~~~~~~~~~~}}
-// CHECK-NEXT: anonymous-groups.td:[[@LINE-8]]:11: note: also referenced here
-// CHECK-NEXT: {{^ InGroup<DiagGroup<"anonymous">>;}}
-// CHECK-NEXT: {{^ ~~~~~~~~\^~~~~~~~~~~~~~~~~~~~~~~}}
+// CHECK: anonymous-groups.td:[[@LINE-7]]:1: note: also referenced here
diff --git a/test/TableGen/emit-diag-docs.td b/test/TableGen/emit-diag-docs.td
new file mode 100644
index 000000000000..b2ecba727f4f
--- /dev/null
+++ b/test/TableGen/emit-diag-docs.td
@@ -0,0 +1,78 @@
+// RUN: clang-tblgen -gen-diag-docs -I%S %s -o - 2>&1 | \
+// RUN: FileCheck --strict-whitespace %s
+include "DiagnosticBase.inc"
+
+def MyGroup : DiagGroup<"MyGroupName">;
+
+def MyKinds : TextSubstitution<"%select{food|forests}0">;
+def MyGoodBad : TextSubstitution<"%select{good|bad}0">;
+def MySubNested : TextSubstitution<"%sub{MyGoodBad}1 %sub{MyKinds}2 are %sub{MyGoodBad}1 according to %0">;
+
+// CHECK: -WMyGroupName
+// CHECK: **Diagnostic text:**
+
+let Group = MyGroup in {
+
+// CHECK: |:warning:`warning:` |nbsp| :diagtext:`this is my diff text`|
+// CHECK-NEXT: +-----------------------------------------------------------+
+def CheckDiff : Warning<"%diff{$ is not $|this is my diff text}0,1">;
+
+
+// CHECK: |:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is my modifier test` |nbsp| :placeholder:`B`|
+// CHECK-NEXT: +----------------------------------------------------------------------------------------------------------+
+def CheckModifier : Warning<"%0 is my modifier test %1">;
+
+
+// CHECK: |:warning:`warning:` |nbsp| :diagtext:`This is the` |nbsp| :placeholder:`A` |nbsp| :diagtext:`test I've written`|
+// CHECK-NEXT: +---------------------------------------------------------------------------------------------------------------+
+def CheckOrdinal : Warning<"This is the %ordinal0 test I've written">;
+
+// CHECK: |:warning:`warning:` |nbsp| :diagtext:`I wrote` |nbsp| |+----------------+| |nbsp| :diagtext:`tests`|
+// CHECK-NEXT: | ||:diagtext:`no` || |
+// CHECK-NEXT: | |+----------------+| |
+// CHECK-NEXT: | ||:diagtext:`one` || |
+// CHECK-NEXT: | |+----------------+| |
+// CHECK-NEXT: | ||:placeholder:`A`|| |
+// CHECK-NEXT: | |+----------------+| |
+// CHECK-NEXT: +------------------------------------------------------+------------------+-------------------------+
+def CheckPlural : Warning<"I wrote %plural{0:no|1:one|:%0}0 tests">;
+
+
+// CHECK: |:warning:`warning:` |nbsp| :diagtext:`bad type` |nbsp| :placeholder:`A`|
+// CHECK-NEXT: +-----------------------------------------------------------------------+
+def CheckQ : Warning<"bad type %q0">;
+
+
+// CHECK: |:warning:`warning:` |nbsp| :diagtext:`My test`|+-------------+| |nbsp| :diagtext:`are the best!`|
+// CHECK-NEXT: | || || |
+// CHECK-NEXT: | |+-------------+| |
+// CHECK-NEXT: | ||:diagtext:`s`|| |
+// CHECK-NEXT: | |+-------------+| |
+// CHECK-NEXT: +----------------------------------------------+---------------+---------------------------------+
+def CheckS : Warning<"My test%s0 are the best!">;
+
+
+// CHECK: |:warning:`warning:` |nbsp| :diagtext:`this is my select test:` |nbsp| |+---------------+|
+// CHECK-NEXT: | ||:diagtext:`one`||
+// CHECK-NEXT: | |+---------------+|
+// CHECK-NEXT: | ||:diagtext:`two`||
+// CHECK-NEXT: | |+---------------+|
+// CHECK-NEXT: +----------------------------------------------------------------------+-----------------+
+def CheckSelect : Warning<"this is my select test: %select{one|two}0 and it is %select{good|bad}1">;
+
+
+// CHECK: +-------------------------------------------------------+------------------+--------+---------------------+-------------------------------+------------------+--------------------------------------------------------+
+// CHECK-NEXT: |:warning:`warning:` |nbsp| :diagtext:`They say` |nbsp| |+----------------+| |nbsp| |+-------------------+| |nbsp| :diagtext:`are` |nbsp| |+----------------+| |nbsp| :diagtext:`according to` |nbsp| :placeholder:`D`|
+// CHECK-NEXT: | ||:diagtext:`good`|| ||:diagtext:`food` || ||:diagtext:`good`|| |
+// CHECK-NEXT: | |+----------------+| |+-------------------+| |+----------------+| |
+// CHECK-NEXT: | ||:diagtext:`bad` || ||:diagtext:`forests`|| ||:diagtext:`bad` || |
+// CHECK-NEXT: | |+----------------+| |+-------------------+| |+----------------+| |
+// CHECK-NEXT: +-------------------------------------------------------+------------------+--------+---------------------+-------------------------------+------------------+--------------------------------------------------------+
+def CheckSubstitution : Warning<"They say %sub{MySubNested}3,1,0">;
+
+
+// CHECK: |:warning:`warning:` |nbsp| :diagtext:`this is my warning text`|
+// CHECK-NEXT: +--------------------------------------------------------------+
+def CheckText : Warning<"this is my warning text">;
+
+}
diff --git a/test/TableGen/text-substitution.td b/test/TableGen/text-substitution.td
new file mode 100644
index 000000000000..aafdbe48c43b
--- /dev/null
+++ b/test/TableGen/text-substitution.td
@@ -0,0 +1,38 @@
+// RUN: clang-tblgen -gen-clang-diags-defs -I%S %s -o - 2>&1 | \
+// RUN: FileCheck --strict-whitespace %s
+include "DiagnosticBase.inc"
+
+def yes_no : TextSubstitution<"%select{yes|no}0">;
+def says_yes : TextSubstitution<"%1 says %sub{yes_no}0">;
+
+
+def sub_test_rewrite : TextSubstitution<
+ "SELECT! %select{one|two}3. "
+ "DIFF! %diff{$ is $|or not}0,1. "
+ "PLURAL! %plural{0:zero items|[1,2]:one or two item|:multiple items}2. "
+ "ORDINAL! %ordinal1. "
+ "S! item%s2. "
+ "Q! %q4. "
+ "PLACEHOLDER! %5."
+ "OBJCCLASS! %objcclass0. "
+ "OBJCINSTANCE! %objcinstance1. ">;
+
+// CHECK: DIAG(test_rewrite,
+// CHECK-SAME: SELECT! %select{one|two}2.
+// CHECK-SAME: DIFF! %diff{$ is $|or not}5,4.
+// CHECK-SAME: PLURAL! %plural{0:zero items|[1,2]:one or two item|:multiple items}3.
+// CHECK-SAME: ORDINAL! %ordinal4.
+// CHECK-SAME: S! item%s3.
+// CHECK-SAME: Q! %q1.
+// CHECK-SAME: PLACEHOLDER! %0.OBJCCLASS!
+// CHECK-SAME: %objcclass5. OBJCINSTANCE!
+// CHECK-SAME: %objcinstance4. DONE!",
+def test_rewrite: Error<"%sub{sub_test_rewrite}5,4,3,2,1,0 DONE!">;
+
+def test_sub_basic : Error<"%sub{yes_no}0">;
+// CHECK: test_sub_basic
+// CHECK-SAME: "%select{yes|no}0",
+
+def test_sub_nested : Error<"%sub{says_yes}2,4">;
+// CHECK: test_sub_nested
+// CHECK-SAME: "%4 says %select{yes|no}2",
diff --git a/test/TableGen/tg-fixits.td b/test/TableGen/tg-fixits.td
index d04a6a67e48b..f0f62ef9a4be 100644
--- a/test/TableGen/tg-fixits.td
+++ b/test/TableGen/tg-fixits.td
@@ -4,38 +4,22 @@ include "DiagnosticBase.inc"
def NamedGroup : DiagGroup<"name">;
def InNamedGroup : Warning<"">, InGroup<DiagGroup<"name">>;
-// CHECK: tg-fixits.td:[[@LINE-1]]:41: error: group 'name' is referred to anonymously
+// CHECK: tg-fixits.td:[[@LINE-1]]:1: error: group 'name' is referred to anonymously
// CHECK-NEXT: {{^def InNamedGroup : Warning<"">, InGroup<DiagGroup<"name">>;}}
-// CHECK-NEXT: {{^ ~~~~~~~~\^~~~~~~~~~~~~~~~~~}}
-// CHECK-NEXT: {{^ InGroup<NamedGroup>}}
def Wrapped : Warning<"">, InGroup<DiagGroup<
"name">>;
-// CHECK: tg-fixits.td:[[@LINE-2]]:36: error: group 'name' is referred to anonymously
+// CHECK: tg-fixits.td:[[@LINE-2]]:1: error: group 'name' is referred to anonymously
// CHECK-NEXT: {{^def Wrapped : Warning<"">, InGroup<DiagGroup<}}
-// CHECK-NEXT: {{^ ~~~~~~~~\^~~~~~~~~~}}
-// CHECK-NEXT: {{^ InGroup<NamedGroup>}}
def AlsoWrapped : Warning<"">, InGroup<
DiagGroup<"name">>;
-// CHECK: tg-fixits.td:[[@LINE-1]]:3: error: group 'name' is referred to anonymously
-// CHECK-NEXT: {{^ DiagGroup<"name">>;}}
-// CHECK-NEXT: {{^~~\^~~~~~~~~~~~~~~~~~}}
-// CHECK-NEXT: {{^InGroup<NamedGroup>}}
-
-// The following lines contain hard tabs (\t); do not change this!
-def HardTabs : Warning<"">,
- InGroup< DiagGroup<"name"> >;
-// CHECK: tg-fixits.td:[[@LINE-1]]:11: error: group 'name' is referred to anonymously
-// CHECK-NEXT: {{^ InGroup< DiagGroup<"name"> >;}}
-// CHECK-NEXT: {{^ ~~~~~~~~~~~~~~~~\^~~~~~~~~~~~~~~~~~~~~~~~~}}
-// CHECK-NEXT: {{^ InGroup<NamedGrop>}}
+// CHECK: tg-fixits.td:[[@LINE-2]]:1: error: group 'name' is referred to anonymously
// The following line has Unicode characters in it; do not change them!
// FIXME: For now, we just give up on printing carets/ranges/fixits for
// lines with Unicode in them, because SMDiagnostic don't keep a byte<->column
// map around to line things up like Clang does.
def Unicode : Warning<"ユニコード">, InGroup<DiagGroup<"name">>;
-// CHECK: tg-fixits.td:[[@LINE-1]]:51: error: group 'name' is referred to anonymously
+// CHECK: tg-fixits.td:[[@LINE-1]]:1: error: group 'name' is referred to anonymously
// CHECK-NEXT: def Unicode : Warning<"{{[^"]+}}">, InGroup<DiagGroup<"name">>;
-// CHECK-NEXT: note:
diff --git a/test/Templight/templight-deduced-func.cpp b/test/Templight/templight-deduced-func.cpp
new file mode 100644
index 000000000000..779fb5f45228
--- /dev/null
+++ b/test/Templight/templight-deduced-func.cpp
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -templight-dump %s 2>&1 | FileCheck %s
+
+template <class T>
+int foo(T){return 0;}
+
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+foo$}}
+// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-deduced-func.cpp:4:5'}}
+// CHECK: {{^poi:[ ]+'.*templight-deduced-func.cpp:44:12'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+foo$}}
+// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-deduced-func.cpp:4:5'}}
+// CHECK: {{^poi:[ ]+'.*templight-deduced-func.cpp:44:12'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-deduced-func.cpp:4:5'}}
+// CHECK: {{^poi:[ ]+'.*templight-deduced-func.cpp:44:12'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-deduced-func.cpp:4:5'}}
+// CHECK: {{^poi:[ ]+'.*templight-deduced-func.cpp:44:12'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-deduced-func.cpp:4:5'}}
+// CHECK: {{^poi:[ ]+'.*templight-deduced-func.cpp:44:12'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-deduced-func.cpp:4:5'}}
+// CHECK: {{^poi:[ ]+'.*templight-deduced-func.cpp:44:12'$}}
+int gvar = foo(0);
diff --git a/test/Templight/templight-default-arg-inst.cpp b/test/Templight/templight-default-arg-inst.cpp
new file mode 100644
index 000000000000..fe2bab3a837e
--- /dev/null
+++ b/test/Templight/templight-default-arg-inst.cpp
@@ -0,0 +1,82 @@
+// RUN: %clang_cc1 -templight-dump %s 2>&1 | FileCheck %s
+template<class T, class U = T>
+class A {};
+
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A::U'$}}
+// CHECK: {{^kind:[ ]+DefaultTemplateArgumentInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-arg-inst.cpp:2:25'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-arg-inst.cpp:82:1'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A::U'$}}
+// CHECK: {{^kind:[ ]+DefaultTemplateArgumentInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-arg-inst.cpp:2:25'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-arg-inst.cpp:82:1'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A::U'$}}
+// CHECK: {{^kind:[ ]+DefaultTemplateArgumentChecking$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-arg-inst.cpp:2:25'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-arg-inst.cpp:82:6'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A::U'$}}
+// CHECK: {{^kind:[ ]+DefaultTemplateArgumentChecking$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-arg-inst.cpp:2:25'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-arg-inst.cpp:82:6'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A<int, int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-arg-inst.cpp:3:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-arg-inst.cpp:82:8'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A<int, int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-arg-inst.cpp:3:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-arg-inst.cpp:82:8'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A<int, int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-arg-inst.cpp:3:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-arg-inst.cpp:82:8'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A<int, int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-arg-inst.cpp:3:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-arg-inst.cpp:82:8'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A<int, int>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-arg-inst.cpp:3:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-arg-inst.cpp:82:8'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A<int, int>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-arg-inst.cpp:3:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-arg-inst.cpp:82:8'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A<int, int>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-arg-inst.cpp:3:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-arg-inst.cpp:82:8'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A<int, int>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-arg-inst.cpp:3:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-arg-inst.cpp:82:8'$}}
+A<int> a;
diff --git a/test/Templight/templight-default-func-arg.cpp b/test/Templight/templight-default-func-arg.cpp
new file mode 100644
index 000000000000..19e603937972
--- /dev/null
+++ b/test/Templight/templight-default-func-arg.cpp
@@ -0,0 +1,73 @@
+// RUN: %clang_cc1 -std=c++14 -templight-dump %s 2>&1 | FileCheck %s
+template <class T>
+void foo(T b = 0) {};
+
+int main()
+{
+
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+foo$}}
+// CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-func-arg.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:72:3'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+foo$}}
+// CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-func-arg.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:72:3'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+foo$}}
+// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-func-arg.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:72:3'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+foo$}}
+// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-func-arg.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:72:3'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-func-arg.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:72:3'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-func-arg.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:72:3'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+b$}}
+// CHECK: {{^kind:[ ]+DefaultFunctionArgumentInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-func-arg.cpp:3:12'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:72:3'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+b$}}
+// CHECK: {{^kind:[ ]+DefaultFunctionArgumentInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-func-arg.cpp:3:12'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:72:3'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-func-arg.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:72:3'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-func-arg.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:72:3'$}}
+ foo<int>();
+}
diff --git a/test/Templight/templight-default-template-arg.cpp b/test/Templight/templight-default-template-arg.cpp
new file mode 100644
index 000000000000..5d2ccb4e4088
--- /dev/null
+++ b/test/Templight/templight-default-template-arg.cpp
@@ -0,0 +1,69 @@
+// RUN: %clang_cc1 -templight-dump %s 2>&1 | FileCheck %s
+template <class T = int>
+class A {};
+
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A::T'$}}
+// CHECK: {{^kind:[ ]+DefaultTemplateArgumentChecking$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-template-arg.cpp:2:17'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-template-arg.cpp:69:3'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A::T'$}}
+// CHECK: {{^kind:[ ]+DefaultTemplateArgumentChecking$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-template-arg.cpp:2:17'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-template-arg.cpp:69:3'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-template-arg.cpp:3:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-template-arg.cpp:69:5'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-template-arg.cpp:3:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-template-arg.cpp:69:5'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-template-arg.cpp:3:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-template-arg.cpp:69:5'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-template-arg.cpp:3:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-template-arg.cpp:69:5'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A<int>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-template-arg.cpp:3:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-template-arg.cpp:69:5'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A<int>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-template-arg.cpp:3:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-template-arg.cpp:69:5'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A<int>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-template-arg.cpp:3:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-template-arg.cpp:69:5'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'A<int>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-default-template-arg.cpp:3:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-default-template-arg.cpp:69:5'$}}
+A<> a;
diff --git a/test/Templight/templight-exception-spec-func.cpp b/test/Templight/templight-exception-spec-func.cpp
new file mode 100644
index 000000000000..39a66d0ecdd2
--- /dev/null
+++ b/test/Templight/templight-exception-spec-func.cpp
@@ -0,0 +1,73 @@
+// RUN: %clang_cc1 -templight-dump -std=c++14 %s 2>&1 | FileCheck %s
+template <bool B>
+void f() noexcept(B) {}
+
+int main()
+{
+
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+f$}}
+// CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-exception-spec-func.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-exception-spec-func.cpp:72:3'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+f$}}
+// CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-exception-spec-func.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-exception-spec-func.cpp:72:3'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+f$}}
+// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-exception-spec-func.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-exception-spec-func.cpp:72:3'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+f$}}
+// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-exception-spec-func.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-exception-spec-func.cpp:72:3'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'f<false>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-exception-spec-func.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-exception-spec-func.cpp:72:3'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'f<false>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-exception-spec-func.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-exception-spec-func.cpp:72:3'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'f<false>'$}}
+// CHECK: {{^kind:[ ]+ExceptionSpecInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-exception-spec-func.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-exception-spec-func.cpp:72:3'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'f<false>'$}}
+// CHECK: {{^kind:[ ]+ExceptionSpecInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-exception-spec-func.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-exception-spec-func.cpp:72:3'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'f<false>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-exception-spec-func.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-exception-spec-func.cpp:72:3'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'f<false>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-exception-spec-func.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-exception-spec-func.cpp:72:3'$}}
+ f<false>();
+}
diff --git a/test/Templight/templight-explicit-template-arg.cpp b/test/Templight/templight-explicit-template-arg.cpp
new file mode 100644
index 000000000000..678cba28cdc0
--- /dev/null
+++ b/test/Templight/templight-explicit-template-arg.cpp
@@ -0,0 +1,59 @@
+// RUN: %clang_cc1 -templight-dump %s 2>&1 | FileCheck %s
+template <class T>
+void f(){}
+
+int main()
+{
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+f$}}
+// CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-explicit-template-arg.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-explicit-template-arg.cpp:58:3'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+f$}}
+// CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-explicit-template-arg.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-explicit-template-arg.cpp:58:3'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+f$}}
+// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-explicit-template-arg.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-explicit-template-arg.cpp:58:3'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+f$}}
+// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-explicit-template-arg.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-explicit-template-arg.cpp:58:3'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'f<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-explicit-template-arg.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-explicit-template-arg.cpp:58:3'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'f<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-explicit-template-arg.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-explicit-template-arg.cpp:58:3'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'f<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-explicit-template-arg.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-explicit-template-arg.cpp:58:3'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'f<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-explicit-template-arg.cpp:3:6'}}
+// CHECK: {{^poi:[ ]+'.*templight-explicit-template-arg.cpp:58:3'$}}
+ f<int>();
+}
diff --git a/test/Templight/templight-memoization.cpp b/test/Templight/templight-memoization.cpp
new file mode 100644
index 000000000000..ddf2447834fd
--- /dev/null
+++ b/test/Templight/templight-memoization.cpp
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -templight-dump %s 2>&1 | FileCheck %s
+
+template <class T>
+struct foo {};
+
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-memoization.cpp:18:10'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-memoization.cpp:18:10'$}}
+foo<int> x;
+
+// CHECK-LABEL: {{^---$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK-LABEL: {{^---$}}
+
+// CHECK: {{^name:[ ]+'foo<int>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-memoization.cpp:41:10'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<int>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-memoization.cpp:41:10'$}}
+foo<int> y;
+
diff --git a/test/Templight/templight-nested-memoization.cpp b/test/Templight/templight-nested-memoization.cpp
new file mode 100644
index 000000000000..37e8483f5381
--- /dev/null
+++ b/test/Templight/templight-nested-memoization.cpp
@@ -0,0 +1,174 @@
+// RUN: %clang_cc1 -templight-dump %s 2>&1 | FileCheck %s
+
+template <int N>
+struct fib
+{
+ static const int value = fib<N-1>::value + fib<N-2>::value;
+};
+
+template <>
+struct fib<0>
+{
+ static const int value = 1;
+};
+
+template <>
+struct fib<1>
+{
+ static const int value = 1;
+};
+
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<4>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:173:8'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<4>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:173:8'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<4>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:173:8'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<3>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:28'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<3>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:28'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<3>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:28'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<2>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:28'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<2>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:28'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<2>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:28'$}}
+
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<1>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:16:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:28'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<1>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:16:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:28'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<0>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:10:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:46'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<0>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:10:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:46'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<2>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:28'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<2>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:28'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<2>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:28'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<1>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:16:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:46'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<1>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:16:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:46'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<3>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:28'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<3>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:28'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<3>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:28'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<2>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:46'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'fib<2>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:6:46'$}}
+// CHECK-LABEL: {{^---$}}
+//
+// CHECK: {{^name:[ ]+'fib<4>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-memoization.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-memoization.cpp:173:8'$}}
+fib<4> x;
+
diff --git a/test/Templight/templight-nested-template-instantiation.cpp b/test/Templight/templight-nested-template-instantiation.cpp
new file mode 100644
index 000000000000..a064c16d5918
--- /dev/null
+++ b/test/Templight/templight-nested-template-instantiation.cpp
@@ -0,0 +1,84 @@
+// RUN: %clang_cc1 -templight-dump %s 2>&1 | FileCheck %s
+
+template <int N>
+struct foo : foo<N - 1> {};
+
+template <>
+struct foo<0> {};
+
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<2>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-template-instantiation.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-template-instantiation.cpp:84:8'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<2>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-template-instantiation.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-template-instantiation.cpp:84:8'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<2>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-template-instantiation.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-template-instantiation.cpp:84:8'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<1>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-template-instantiation.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-template-instantiation.cpp:4:14'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<1>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-template-instantiation.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-template-instantiation.cpp:4:14'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<1>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-template-instantiation.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-template-instantiation.cpp:4:14'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<0>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-template-instantiation.cpp:7:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-template-instantiation.cpp:4:14'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<0>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-template-instantiation.cpp:7:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-template-instantiation.cpp:4:14'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<1>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-template-instantiation.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-template-instantiation.cpp:4:14'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<1>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-template-instantiation.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-template-instantiation.cpp:4:14'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<1>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-template-instantiation.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-template-instantiation.cpp:4:14'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<2>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-nested-template-instantiation.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-nested-template-instantiation.cpp:84:8'$}}
+foo<2> x;
diff --git a/test/Templight/templight-one-instantiation.cpp b/test/Templight/templight-one-instantiation.cpp
new file mode 100644
index 000000000000..e865ef3a4ba9
--- /dev/null
+++ b/test/Templight/templight-one-instantiation.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -templight-dump %s 2>&1 | FileCheck %s
+
+template <class T>
+struct foo {};
+
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-one-instantiation.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-one-instantiation.cpp:18:10'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'foo<int>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-one-instantiation.cpp:4:8'}}
+// CHECK: {{^poi:[ ]+'.*templight-one-instantiation.cpp:18:10'$}}
+foo<int> x;
diff --git a/test/Templight/templight-prior-template-arg.cpp b/test/Templight/templight-prior-template-arg.cpp
new file mode 100644
index 000000000000..e9b1dd47bb60
--- /dev/null
+++ b/test/Templight/templight-prior-template-arg.cpp
@@ -0,0 +1,72 @@
+// RUN: %clang_cc1 -templight-dump %s 2>&1 | FileCheck %s
+template<class T>
+class A {};
+
+template <template <class Inner> class Outer>
+class B {};
+
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'B::Outer'$}}
+// CHECK: {{^kind:[ ]+PriorTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-prior-template-arg.cpp:5:40'}}
+// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:72:1'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'B::Outer'$}}
+// CHECK: {{^kind:[ ]+PriorTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-prior-template-arg.cpp:5:40'}}
+// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:72:1'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'B<A>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-prior-template-arg.cpp:6:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:72:6'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'B<A>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-prior-template-arg.cpp:6:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:72:6'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'B<A>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-prior-template-arg.cpp:6:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:72:6'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'B<A>'$}}
+// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-prior-template-arg.cpp:6:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:72:6'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'B<A>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-prior-template-arg.cpp:6:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:72:6'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'B<A>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-prior-template-arg.cpp:6:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:72:6'$}}
+//
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'B<A>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-prior-template-arg.cpp:6:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:72:6'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+'B<A>'$}}
+// CHECK: {{^kind:[ ]+Memoization$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-prior-template-arg.cpp:6:7'}}
+// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:72:6'$}}
+B<A> b;
diff --git a/test/Tooling/clang-diff-json.cpp b/test/Tooling/clang-diff-json.cpp
index 9aac6fa8b15b..20c808cb0f19 100644
--- a/test/Tooling/clang-diff-json.cpp
+++ b/test/Tooling/clang-diff-json.cpp
@@ -1,10 +1,10 @@
// RUN: clang-diff -ast-dump-json %s -- \
-// RUN: | %python -c 'import json, sys; json.dump(json.loads(sys.stdin.read()), sys.stdout, sort_keys=True, indent=2)' \
+// RUN: | '%python' -c 'import json, sys; json.dump(json.loads(sys.stdin.read()), sys.stdout, sort_keys=True, indent=2)' \
// RUN: | FileCheck %s
-// CHECK: "begin": 299,
+// CHECK: "begin": 301,
// CHECK: "type": "FieldDecl",
-// CHECK: "end": 319,
+// CHECK: "end": 321,
// CHECK: "type": "CXXRecordDecl",
class A {
int x;
diff --git a/test/VFS/Inputs/MissingVFS/a.h b/test/VFS/Inputs/MissingVFS/a.h
new file mode 100644
index 000000000000..892d837b10b6
--- /dev/null
+++ b/test/VFS/Inputs/MissingVFS/a.h
@@ -0,0 +1 @@
+// void funcA(void);
diff --git a/test/VFS/Inputs/MissingVFS/module.modulemap b/test/VFS/Inputs/MissingVFS/module.modulemap
new file mode 100644
index 000000000000..bbd9d674c946
--- /dev/null
+++ b/test/VFS/Inputs/MissingVFS/module.modulemap
@@ -0,0 +1,3 @@
+module A {
+ header "a.h"
+}
diff --git a/test/VFS/Inputs/MissingVFS/vfsoverlay.yaml b/test/VFS/Inputs/MissingVFS/vfsoverlay.yaml
new file mode 100644
index 000000000000..49517a159080
--- /dev/null
+++ b/test/VFS/Inputs/MissingVFS/vfsoverlay.yaml
@@ -0,0 +1,13 @@
+{
+ 'version': 0,
+ 'ignore-non-existent-contents': false,
+ 'roots': [
+ { 'name': 'INPUT_DIR', 'type': 'directory',
+ 'contents': [
+ { 'name': 'a.h', 'type': 'file',
+ 'external-contents': 'OUT_DIR/a.h'
+ }
+ ]
+ }
+ ]
+}
diff --git a/test/VFS/module_missing_vfs.m b/test/VFS/module_missing_vfs.m
new file mode 100644
index 000000000000..4c4ee4dd8967
--- /dev/null
+++ b/test/VFS/module_missing_vfs.m
@@ -0,0 +1,16 @@
+// REQUIRES: shell
+// RUN: rm -rf %t && mkdir -p %t
+// RUN: echo "void funcA(void);" >> %t/a.h
+
+// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/mcp -I %S/Inputs/MissingVFS %s -fsyntax-only -ivfsoverlay %t/vfs.yaml 2>&1 | FileCheck %s -check-prefix=ERROR
+// ERROR: virtual filesystem overlay file '{{.*}}' not found
+// RUN: find %t/mcp -name "A-*.pcm" | count 1
+
+// RUN: sed -e "s:INPUT_DIR:%S/Inputs:g" -e "s:OUT_DIR:%t:g" %S/Inputs/MissingVFS/vfsoverlay.yaml > %t/vfs.yaml
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/mcp -I %S/Inputs/MissingVFS %s -fsyntax-only -ivfsoverlay %t/vfs.yaml
+// RUN: find %t/mcp -name "A-*.pcm" | count 1
+
+@import A;
+void test(void) {
+ funcA();
+}
diff --git a/test/VFS/real-path-found-first.m b/test/VFS/real-path-found-first.m
index 5838aa36c452..cc5a0024ea80 100644
--- a/test/VFS/real-path-found-first.m
+++ b/test/VFS/real-path-found-first.m
@@ -7,7 +7,7 @@
// REQUIRES: shell
// RUN: rm -rf %t %t-cache %t.pch
// RUN: mkdir -p %t/SomeFramework.framework/Modules
-// RUN: cp %S/Inputs/some_frame_module.map %t/SomeFramework.framework/Modules/module.modulemap
+// RUN: cat %S/Inputs/some_frame_module.map > %t/SomeFramework.framework/Modules/module.modulemap
// RUN: sed -e "s:INPUT_DIR:%S/Inputs:g" -e "s:OUT_DIR:%t:g" %S/Inputs/vfsoverlay.yaml > %t.yaml
// Build
diff --git a/test/VFS/umbrella-framework-import-skipnonexist.m b/test/VFS/umbrella-framework-import-skipnonexist.m
index 5c7cd6d9db13..129f475fe774 100644
--- a/test/VFS/umbrella-framework-import-skipnonexist.m
+++ b/test/VFS/umbrella-framework-import-skipnonexist.m
@@ -5,7 +5,7 @@
// RUN: rm -rf %t
// RUN: mkdir -p %t/vdir %t/outdir %t/cache
-// RUN: cp -a %S/Inputs/Bar.framework %t/outdir/
+// RUN: cp -R %S/Inputs/Bar.framework %t/outdir/
//
// RUN: sed -e "s:VDIR:%t/vdir:g" -e "s:OUT_DIR:%t/outdir:g" %S/Inputs/bar-headers.yaml > %t/vdir/bar-headers.yaml
// RUN: rm -f %t/outdir/Bar.framework/Headers/B.h
diff --git a/test/VFS/umbrella-mismatch.m b/test/VFS/umbrella-mismatch.m
index fc5180241619..8167a21f485b 100644
--- a/test/VFS/umbrella-mismatch.m
+++ b/test/VFS/umbrella-mismatch.m
@@ -1,7 +1,7 @@
// RUN: rm -rf %t
// RUN: sed -e "s;INPUT_DIR;%/S/Inputs;g" -e "s;OUT_DIR;%/S/Inputs;g" %S/Inputs/vfsoverlay.yaml > %t.yaml
-// RUN: %clang_cc1 -Werror -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -ivfsoverlay %t.yaml -F %S/Inputs -fsyntax-only %s -verify
-// RUN: %clang_cc1 -Werror -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs -fsyntax-only %s -verify
+// RUN: %clang_cc1 -Werror -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -ivfsoverlay %t.yaml -F %S/Inputs -fsyntax-only %s -Wno-atimport-in-framework-header -verify
+// RUN: %clang_cc1 -Werror -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs -fsyntax-only %s -Wno-atimport-in-framework-header -verify
// expected-no-diagnostics
@import UsesFoo;
diff --git a/test/lit.cfg.py b/test/lit.cfg.py
index 5323cfe73550..ad30988c1796 100644
--- a/test/lit.cfg.py
+++ b/test/lit.cfg.py
@@ -57,16 +57,22 @@ config.substitutions.append(('%PATH%', config.environment['PATH']))
tool_dirs = [config.clang_tools_dir, config.llvm_tools_dir]
tools = [
- 'c-index-test', 'clang-check', 'clang-diff', 'clang-format', 'opt',
+ 'c-index-test', 'clang-check', 'clang-diff', 'clang-format', 'clang-tblgen',
+ 'opt',
ToolSubst('%clang_func_map', command=FindTool(
'clang-func-mapping'), unresolved='ignore'),
]
if config.clang_examples:
+ config.available_features.add('examples')
tools.append('clang-interpreter')
llvm_config.add_tool_substitutions(tools, tool_dirs)
+config.substitutions.append(
+ ('%hmaptool', "'%s' %s" % (config.python_executable,
+ os.path.join(config.llvm_tools_dir, 'hmaptool'))))
+
# Plugins (loadable modules)
# TODO: This should be supplied by Makefile or autoconf.
if sys.platform in ['win32', 'cygwin']:
diff --git a/test/lit.site.cfg.py.in b/test/lit.site.cfg.py.in
index 9d2b4c591879..361d4e44d679 100644
--- a/test/lit.site.cfg.py.in
+++ b/test/lit.site.cfg.py.in
@@ -25,7 +25,6 @@ config.clang_examples = @CLANG_BUILD_EXAMPLES@
config.enable_shared = @ENABLE_SHARED@
config.enable_backtrace = @ENABLE_BACKTRACES@
config.host_arch = "@HOST_ARCH@"
-config.enable_abi_breaking_checks = "@LLVM_ENABLE_ABI_BREAKING_CHECKS@"
config.python_executable = "@PYTHON_EXECUTABLE@"
# Support substitution of the tools and libs dirs with user parameters. This is
diff --git a/tools/c-index-test/CMakeLists.txt b/tools/c-index-test/CMakeLists.txt
index d38c7bb28709..53e3421f1b35 100644
--- a/tools/c-index-test/CMakeLists.txt
+++ b/tools/c-index-test/CMakeLists.txt
@@ -40,7 +40,11 @@ set_target_properties(c-index-test
# If libxml2 is available, make it available for c-index-test.
if (CLANG_HAVE_LIBXML)
- include_directories(SYSTEM ${LIBXML2_INCLUDE_DIR})
+ if ((CMAKE_OSX_SYSROOT) AND (EXISTS ${CMAKE_OSX_SYSROOT}/${LIBXML2_INCLUDE_DIR}))
+ include_directories(SYSTEM ${CMAKE_OSX_SYSROOT}/${LIBXML2_INCLUDE_DIR})
+ else()
+ include_directories(SYSTEM ${LIBXML2_INCLUDE_DIR})
+ endif()
target_link_libraries(c-index-test PRIVATE ${LIBXML2_LIBRARIES})
endif()
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c
index 99f05669b64c..70ab11866edd 100644
--- a/tools/c-index-test/c-index-test.c
+++ b/tools/c-index-test/c-index-test.c
@@ -64,7 +64,7 @@ extern char *basename(const char *);
extern char *dirname(char *);
#endif
-/** \brief Return the default parsing options. */
+/** Return the default parsing options. */
static unsigned getDefaultParsingOptions() {
unsigned options = CXTranslationUnit_DetailedPreprocessingRecord;
@@ -82,11 +82,76 @@ static unsigned getDefaultParsingOptions() {
options |= CXTranslationUnit_CreatePreambleOnFirstParse;
if (getenv("CINDEXTEST_KEEP_GOING"))
options |= CXTranslationUnit_KeepGoing;
+ if (getenv("CINDEXTEST_LIMIT_SKIP_FUNCTION_BODIES_TO_PREAMBLE"))
+ options |= CXTranslationUnit_LimitSkipFunctionBodiesToPreamble;
return options;
}
-/** \brief Returns 0 in case of success, non-zero in case of a failure. */
+static void ModifyPrintingPolicyAccordingToEnv(CXPrintingPolicy Policy) {
+ struct Mapping {
+ const char *name;
+ enum CXPrintingPolicyProperty property;
+ };
+ struct Mapping mappings[] = {
+ {"CINDEXTEST_PRINTINGPOLICY_INDENTATION", CXPrintingPolicy_Indentation},
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSSPECIFIERS",
+ CXPrintingPolicy_SuppressSpecifiers},
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSTAGKEYWORD",
+ CXPrintingPolicy_SuppressTagKeyword},
+ {"CINDEXTEST_PRINTINGPOLICY_INCLUDETAGDEFINITION",
+ CXPrintingPolicy_IncludeTagDefinition},
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSSCOPE",
+ CXPrintingPolicy_SuppressScope},
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSUNWRITTENSCOPE",
+ CXPrintingPolicy_SuppressUnwrittenScope},
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSINITIALIZERS",
+ CXPrintingPolicy_SuppressInitializers},
+ {"CINDEXTEST_PRINTINGPOLICY_CONSTANTARRAYSIZEASWRITTEN",
+ CXPrintingPolicy_ConstantArraySizeAsWritten},
+ {"CINDEXTEST_PRINTINGPOLICY_ANONYMOUSTAGLOCATIONS",
+ CXPrintingPolicy_AnonymousTagLocations},
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSSTRONGLIFETIME",
+ CXPrintingPolicy_SuppressStrongLifetime},
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSLIFETIMEQUALIFIERS",
+ CXPrintingPolicy_SuppressLifetimeQualifiers},
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSTEMPLATEARGSINCXXCONSTRUCTORS",
+ CXPrintingPolicy_SuppressTemplateArgsInCXXConstructors},
+ {"CINDEXTEST_PRINTINGPOLICY_BOOL", CXPrintingPolicy_Bool},
+ {"CINDEXTEST_PRINTINGPOLICY_RESTRICT", CXPrintingPolicy_Restrict},
+ {"CINDEXTEST_PRINTINGPOLICY_ALIGNOF", CXPrintingPolicy_Alignof},
+ {"CINDEXTEST_PRINTINGPOLICY_UNDERSCOREALIGNOF",
+ CXPrintingPolicy_UnderscoreAlignof},
+ {"CINDEXTEST_PRINTINGPOLICY_USEVOIDFORZEROPARAMS",
+ CXPrintingPolicy_UseVoidForZeroParams},
+ {"CINDEXTEST_PRINTINGPOLICY_TERSEOUTPUT", CXPrintingPolicy_TerseOutput},
+ {"CINDEXTEST_PRINTINGPOLICY_POLISHFORDECLARATION",
+ CXPrintingPolicy_PolishForDeclaration},
+ {"CINDEXTEST_PRINTINGPOLICY_HALF", CXPrintingPolicy_Half},
+ {"CINDEXTEST_PRINTINGPOLICY_MSWCHAR", CXPrintingPolicy_MSWChar},
+ {"CINDEXTEST_PRINTINGPOLICY_INCLUDENEWLINES",
+ CXPrintingPolicy_IncludeNewlines},
+ {"CINDEXTEST_PRINTINGPOLICY_MSVCFORMATTING",
+ CXPrintingPolicy_MSVCFormatting},
+ {"CINDEXTEST_PRINTINGPOLICY_CONSTANTSASWRITTEN",
+ CXPrintingPolicy_ConstantsAsWritten},
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSIMPLICITBASE",
+ CXPrintingPolicy_SuppressImplicitBase},
+ {"CINDEXTEST_PRINTINGPOLICY_FULLYQUALIFIEDNAME",
+ CXPrintingPolicy_FullyQualifiedName},
+ };
+
+ unsigned i;
+ for (i = 0; i < sizeof(mappings) / sizeof(struct Mapping); i++) {
+ char *value = getenv(mappings[i].name);
+ if (value) {
+ clang_PrintingPolicy_setProperty(Policy, mappings[i].property,
+ (unsigned)strtoul(value, 0L, 10));
+ }
+ }
+}
+
+/** Returns 0 in case of success, non-zero in case of a failure. */
static int checkForErrors(CXTranslationUnit TU);
static void describeLibclangFailure(enum CXErrorCode Err) {
@@ -169,6 +234,7 @@ static int parse_remapped_files_with_opt(const char *opt_name,
*unsaved_files
= (struct CXUnsavedFile *)malloc(sizeof(struct CXUnsavedFile) *
*num_unsaved_files);
+ assert(*unsaved_files);
for (i = 0; i != *num_unsaved_files; ++i) {
struct CXUnsavedFile *unsaved = *unsaved_files + i;
const char *arg_string = argv[arg_indices[i]] + prefix_len;
@@ -204,6 +270,7 @@ static int parse_remapped_files_with_opt(const char *opt_name,
/* Read the contents of the file we're remapping to. */
contents = (char *)malloc(unsaved->Length + 1);
+ assert(contents);
if (fread(contents, 1, unsaved->Length, to_file) != unsaved->Length) {
fprintf(stderr, "error: unexpected %s reading 'to' file %s\n",
(feof(to_file) ? "EOF" : "error"), sep + 1);
@@ -223,6 +290,7 @@ static int parse_remapped_files_with_opt(const char *opt_name,
/* Copy the file name that we're remapping from. */
filename_len = sep - arg_string;
filename = (char *)malloc(filename_len + 1);
+ assert(filename);
memcpy(filename, arg_string, filename_len);
filename[filename_len] = 0;
unsaved->Filename = filename;
@@ -277,6 +345,7 @@ static int parse_remapped_files_with_try(int try_idx,
= (struct CXUnsavedFile *)realloc(unsaved_files_no_try_idx,
sizeof(struct CXUnsavedFile) *
*num_unsaved_files);
+ assert(*unsaved_files);
memcpy(*unsaved_files + num_unsaved_files_no_try_idx,
unsaved_files_try_idx, sizeof(struct CXUnsavedFile) *
num_unsaved_files_try_idx);
@@ -356,7 +425,11 @@ static void PrintRange(CXSourceRange R, const char *str) {
PrintExtent(stdout, begin_line, begin_column, end_line, end_column);
}
-int want_display_name = 0;
+static enum DisplayType {
+ DisplayType_Spelling,
+ DisplayType_DisplayName,
+ DisplayType_Pretty
+} wanted_display_type = DisplayType_Spelling;
static void printVersion(const char *Prefix, CXVersion Version) {
if (Version.Major < 0)
@@ -591,7 +664,7 @@ static void ValidateCommentXML(const char *Str, const char *CommentSchemaFile) {
printf(" CommentXMLValid");
else if (status > 0) {
xmlErrorPtr Error = xmlGetLastError();
- printf(" CommentXMLInvalid [not vaild XML: %s]", Error->message);
+ printf(" CommentXMLInvalid [not valid XML: %s]", Error->message);
} else
printf(" libXMLError");
@@ -656,6 +729,28 @@ static int lineCol_cmp(const void *p1, const void *p2) {
return (int)lhs->col - (int)rhs->col;
}
+static CXString CursorToText(CXCursor Cursor) {
+ CXString text;
+ switch (wanted_display_type) {
+ case DisplayType_Spelling:
+ return clang_getCursorSpelling(Cursor);
+ case DisplayType_DisplayName:
+ return clang_getCursorDisplayName(Cursor);
+ case DisplayType_Pretty: {
+ CXPrintingPolicy Policy = clang_getCursorPrintingPolicy(Cursor);
+ ModifyPrintingPolicyAccordingToEnv(Policy);
+ text = clang_getCursorPrettyPrinted(Cursor, Policy);
+ clang_PrintingPolicy_dispose(Policy);
+ return text;
+ }
+ }
+ assert(0 && "unknown display type"); /* no llvm_unreachable in C. */
+ /* Set to NULL to prevent uninitialized variable warnings. */
+ text.data = NULL;
+ text.private_flags = 0;
+ return text;
+}
+
static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) {
CXTranslationUnit TU = clang_Cursor_getTranslationUnit(Cursor);
if (clang_isInvalid(Cursor.kind)) {
@@ -682,8 +777,7 @@ static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) {
int I;
ks = clang_getCursorKindSpelling(Cursor.kind);
- string = want_display_name? clang_getCursorDisplayName(Cursor)
- : clang_getCursorSpelling(Cursor);
+ string = CursorToText(Cursor);
printf("%s=%s", clang_getCString(ks),
clang_getCString(string));
clang_disposeString(ks);
@@ -812,6 +906,8 @@ static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) {
printf(" (variadic)");
if (clang_Cursor_isObjCOptional(Cursor))
printf(" (@optional)");
+ if (clang_isInvalidDeclaration(Cursor))
+ printf(" (invalid)");
switch (clang_getCursorExceptionSpecificationType(Cursor))
{
@@ -1038,6 +1134,13 @@ static const char* GetCursorSource(CXCursor Cursor) {
}
}
+static CXString createCXString(const char *CS) {
+ CXString Str;
+ Str.data = (const void *) CS;
+ Str.private_flags = 0;
+ return Str;
+}
+
/******************************************************************************/
/* Callbacks. */
/******************************************************************************/
@@ -1684,7 +1787,12 @@ static int perform_test_load(CXIndex Idx, CXTranslationUnit TU,
else if (!strcmp(filter, "all-display") ||
!strcmp(filter, "local-display")) {
ck = NULL;
- want_display_name = 1;
+ wanted_display_type = DisplayType_DisplayName;
+ }
+ else if (!strcmp(filter, "all-pretty") ||
+ !strcmp(filter, "local-pretty")) {
+ ck = NULL;
+ wanted_display_type = DisplayType_Pretty;
}
else if (!strcmp(filter, "none")) K = (enum CXCursorKind) ~0;
else if (!strcmp(filter, "category")) K = CXCursor_ObjCCategoryDecl;
@@ -1752,8 +1860,11 @@ int perform_test_load_source(int argc, const char **argv,
const char *InvocationPath;
Idx = clang_createIndex(/* excludeDeclsFromPCH */
- (!strcmp(filter, "local") ||
- !strcmp(filter, "local-display"))? 1 : 0,
+ (!strcmp(filter, "local") ||
+ !strcmp(filter, "local-display") ||
+ !strcmp(filter, "local-pretty"))
+ ? 1
+ : 0,
/* displayDiagnostics=*/1);
InvocationPath = getenv("CINDEXTEST_INVOCATION_EMISSION_PATH");
if (InvocationPath)
@@ -2064,6 +2175,7 @@ int parse_file_line_column(const char *input, char **filename, unsigned *line,
/* Copy the file name. */
*filename = (char*)malloc(last_colon - input + 1);
+ assert(*filename);
memcpy(*filename, input, last_colon - input);
(*filename)[last_colon - input] = 0;
return 0;
@@ -2158,8 +2270,33 @@ static void print_completion_string(CXCompletionString completion_string,
}
-static void print_completion_result(CXCompletionResult *completion_result,
+static void print_line_column(CXSourceLocation location, FILE *file) {
+ unsigned line, column;
+ clang_getExpansionLocation(location, NULL, &line, &column, NULL);
+ fprintf(file, "%d:%d", line, column);
+}
+
+static void print_token_range(CXTranslationUnit translation_unit,
+ CXSourceLocation start, FILE *file) {
+ CXToken *token = clang_getToken(translation_unit, start);
+
+ fprintf(file, "{");
+ if (token != NULL) {
+ CXSourceRange token_range = clang_getTokenExtent(translation_unit, *token);
+ print_line_column(clang_getRangeStart(token_range), file);
+ fprintf(file, "-");
+ print_line_column(clang_getRangeEnd(token_range), file);
+ clang_disposeTokens(translation_unit, token, 1);
+ }
+
+ fprintf(file, "}");
+}
+
+static void print_completion_result(CXTranslationUnit translation_unit,
+ CXCodeCompleteResults *completion_results,
+ unsigned index,
FILE *file) {
+ CXCompletionResult *completion_result = completion_results->Results + index;
CXString ks = clang_getCursorKindSpelling(completion_result->CursorKind);
unsigned annotationCount;
enum CXCursorKind ParentKind;
@@ -2167,6 +2304,7 @@ static void print_completion_result(CXCompletionResult *completion_result,
CXString BriefComment;
CXString Annotation;
const char *BriefCommentCString;
+ unsigned i;
fprintf(file, "%s:", clang_getCString(ks));
clang_disposeString(ks);
@@ -2227,7 +2365,19 @@ static void print_completion_result(CXCompletionResult *completion_result,
fprintf(file, "(brief comment: %s)", BriefCommentCString);
}
clang_disposeString(BriefComment);
-
+
+ for (i = 0; i < clang_getCompletionNumFixIts(completion_results, index);
+ ++i) {
+ CXSourceRange correction_range;
+ CXString FixIt = clang_getCompletionFixIt(completion_results, index, i,
+ &correction_range);
+ fprintf(file, " (requires fix-it: ");
+ print_token_range(translation_unit, clang_getRangeStart(correction_range),
+ file);
+ fprintf(file, " to \"%s\")", clang_getCString(FixIt));
+ clang_disposeString(FixIt);
+ }
+
fprintf(file, "\n");
}
@@ -2324,6 +2474,10 @@ int perform_code_completion(int argc, const char **argv, int timing_only) {
completionOptions |= CXCodeComplete_IncludeCodePatterns;
if (getenv("CINDEXTEST_COMPLETION_BRIEF_COMMENTS"))
completionOptions |= CXCodeComplete_IncludeBriefComments;
+ if (getenv("CINDEXTEST_COMPLETION_SKIP_PREAMBLE"))
+ completionOptions |= CXCodeComplete_SkipPreamble;
+ if (getenv("CINDEXTEST_COMPLETION_INCLUDE_FIXITS"))
+ completionOptions |= CXCodeComplete_IncludeCompletionsWithFixIts;
if (timing_only)
input += strlen("-code-completion-timing=");
@@ -2388,7 +2542,7 @@ int perform_code_completion(int argc, const char **argv, int timing_only) {
clang_sortCodeCompletionResults(results->Results, results->NumResults);
for (i = 0; i != n; ++i)
- print_completion_result(results->Results + i, stdout);
+ print_completion_result(TU, results, i, stdout);
}
n = clang_codeCompleteGetNumDiagnostics(results);
for (i = 0; i != n; ++i) {
@@ -2471,6 +2625,7 @@ static int inspect_cursor_at(int argc, const char **argv,
assert(NumLocations > 0 && "Unable to count locations?");
Locations = (CursorSourceLocation *)malloc(
NumLocations * sizeof(CursorSourceLocation));
+ assert(Locations);
for (Loc = 0; Loc < NumLocations; ++Loc) {
const char *input = argv[Loc + 1] + strlen(locations_flag);
if ((errorCode = parse_file_line_column(input, &Locations[Loc].filename,
@@ -2764,6 +2919,7 @@ static int find_file_refs_at(int argc, const char **argv) {
assert(NumLocations > 0 && "Unable to count locations?");
Locations = (CursorSourceLocation *)malloc(
NumLocations * sizeof(CursorSourceLocation));
+ assert(Locations);
for (Loc = 0; Loc < NumLocations; ++Loc) {
const char *input = argv[Loc + 1] + strlen("-file-refs-at=");
if ((errorCode = parse_file_line_column(input, &Locations[Loc].filename,
@@ -2871,6 +3027,7 @@ static int find_file_includes_in(int argc, const char **argv) {
/* Parse the locations. */
assert(NumFilenames > 0 && "Unable to count filenames?");
Filenames = (const char **)malloc(NumFilenames * sizeof(const char *));
+ assert(Filenames);
for (I = 0; I < NumFilenames; ++I) {
const char *input = argv[I + 1] + strlen("-file-includes-in=");
/* Copy the file name. */
@@ -2954,7 +3111,9 @@ typedef struct {
static ImportedASTFilesData *importedASTs_create() {
ImportedASTFilesData *p;
p = malloc(sizeof(ImportedASTFilesData));
+ assert(p);
p->filenames = malloc(MAX_IMPORTED_ASTFILES * sizeof(const char *));
+ assert(p->filenames);
p->num_files = 0;
return p;
}
@@ -2990,7 +3149,7 @@ typedef struct {
int first_check_printed;
int fail_for_error;
int abort;
- const char *main_filename;
+ CXString main_filename;
ImportedASTFilesData *importedASTs;
IndexDataStringList *strings;
CXTranslationUnit TU;
@@ -3029,6 +3188,7 @@ static void printCXIndexLoc(CXIdxLoc loc, CXClientData client_data) {
const char *cname;
CXIdxClientFile file;
unsigned line, column;
+ const char *main_filename;
int isMainFile;
index_data = (IndexData *)client_data;
@@ -3043,7 +3203,8 @@ static void printCXIndexLoc(CXIdxLoc loc, CXClientData client_data) {
}
filename = clang_getFileName((CXFile)file);
cname = clang_getCString(filename);
- if (strcmp(cname, index_data->main_filename) == 0)
+ main_filename = clang_getCString(index_data->main_filename);
+ if (strcmp(cname, main_filename) == 0)
isMainFile = 1;
else
isMainFile = 0;
@@ -3085,6 +3246,7 @@ static CXIdxClientContainer makeClientContainer(CXClientData *client_data,
node =
(IndexDataStringList *)malloc(sizeof(IndexDataStringList) + strlen(name) +
digitCount(line) + digitCount(column) + 2);
+ assert(node);
newStr = node->data;
sprintf(newStr, "%s:%d:%d", name, line, column);
@@ -3217,6 +3379,27 @@ static void printProtocolList(const CXIdxObjCProtocolRefListInfo *ProtoInfo,
}
}
+static void printSymbolRole(CXSymbolRole role) {
+ if (role & CXSymbolRole_Declaration)
+ printf(" decl");
+ if (role & CXSymbolRole_Definition)
+ printf(" def");
+ if (role & CXSymbolRole_Reference)
+ printf(" ref");
+ if (role & CXSymbolRole_Read)
+ printf(" read");
+ if (role & CXSymbolRole_Write)
+ printf(" write");
+ if (role & CXSymbolRole_Call)
+ printf(" call");
+ if (role & CXSymbolRole_Dynamic)
+ printf(" dyn");
+ if (role & CXSymbolRole_AddressOf)
+ printf(" addr");
+ if (role & CXSymbolRole_Implicit)
+ printf(" implicit");
+}
+
static void index_diagnostic(CXClientData client_data,
CXDiagnosticSet diagSet, void *reserved) {
CXString str;
@@ -3245,14 +3428,11 @@ static void index_diagnostic(CXClientData client_data,
static CXIdxClientFile index_enteredMainFile(CXClientData client_data,
CXFile file, void *reserved) {
IndexData *index_data;
- CXString filename;
index_data = (IndexData *)client_data;
printCheck(index_data);
- filename = clang_getFileName(file);
- index_data->main_filename = clang_getCString(filename);
- clang_disposeString(filename);
+ index_data->main_filename = clang_getFileName(file);
printf("[enteredMainFile]: ");
printCXIndexFile((CXIdxClientFile)file);
@@ -3438,9 +3618,11 @@ static void index_indexEntityReference(CXClientData client_data,
printCXIndexContainer(info->container);
printf(" | refkind: ");
switch (info->kind) {
- case CXIdxEntityRef_Direct: printf("direct"); break;
- case CXIdxEntityRef_Implicit: printf("implicit"); break;
+ case CXIdxEntityRef_Direct: printf("direct"); break;
+ case CXIdxEntityRef_Implicit: printf("implicit"); break;
}
+ printf(" | role:");
+ printSymbolRole(info->role);
printf("\n");
}
@@ -3470,6 +3652,8 @@ static unsigned getIndexOptions(void) {
index_opts |= CXIndexOpt_IndexFunctionLocalSymbols;
if (!getenv("CINDEXTEST_DISABLE_SKIPPARSEDBODIES"))
index_opts |= CXIndexOpt_SkipParsedBodiesInSession;
+ if (getenv("CINDEXTEST_INDEXIMPLICITTEMPLATEINSTANTIATIONS"))
+ index_opts |= CXIndexOpt_IndexImplicitTemplateInstantiations;
return index_opts;
}
@@ -3491,7 +3675,7 @@ static int index_compile_args(int num_args, const char **args,
index_data.first_check_printed = 0;
index_data.fail_for_error = 0;
index_data.abort = 0;
- index_data.main_filename = "";
+ index_data.main_filename = createCXString("");
index_data.importedASTs = importedASTs;
index_data.strings = NULL;
index_data.TU = NULL;
@@ -3507,6 +3691,7 @@ static int index_compile_args(int num_args, const char **args,
if (index_data.fail_for_error)
result = -1;
+ clang_disposeString(index_data.main_filename);
free_client_data(&index_data);
return result;
}
@@ -3528,7 +3713,7 @@ static int index_ast_file(const char *ast_file,
index_data.first_check_printed = 0;
index_data.fail_for_error = 0;
index_data.abort = 0;
- index_data.main_filename = "";
+ index_data.main_filename = createCXString("");
index_data.importedASTs = importedASTs;
index_data.strings = NULL;
index_data.TU = TU;
@@ -3541,6 +3726,7 @@ static int index_ast_file(const char *ast_file,
result = -1;
clang_disposeTranslationUnit(TU);
+ clang_disposeString(index_data.main_filename);
free_client_data(&index_data);
return result;
}
@@ -3664,6 +3850,7 @@ static int index_compile_db(int argc, const char **argv) {
len = strlen(database);
tmp = (char *) malloc(len+1);
+ assert(tmp);
memcpy(tmp, database, len+1);
buildDir = dirname(tmp);
@@ -3845,6 +4032,7 @@ int perform_token_annotation(int argc, const char **argv) {
}
cursors = (CXCursor *)malloc(num_tokens * sizeof(CXCursor));
+ assert(cursors);
clang_annotateTokens(TU, tokens, num_tokens, cursors);
if (checkForErrors(TU) != 0) {
@@ -3919,6 +4107,7 @@ perform_test_compilation_db(const char *database, int argc, const char **argv) {
len = strlen(database);
tmp = (char *) malloc(len+1);
+ assert(tmp);
memcpy(tmp, database, len+1);
buildDir = dirname(tmp);
@@ -4033,9 +4222,7 @@ int print_usrs(const char **I, const char **E) {
if (!isUSR(I[2]))
return not_usr("<class USR>", I[2]);
else {
- CXString x;
- x.data = (void*) I[2];
- x.private_flags = 0;
+ CXString x = createCXString(I[2]);
print_usr(clang_constructUSR_ObjCIvar(I[1], x));
}
@@ -4060,9 +4247,7 @@ int print_usrs(const char **I, const char **E) {
if (!isUSR(I[3]))
return not_usr("<class USR>", I[3]);
else {
- CXString x;
- x.data = (void*) I[3];
- x.private_flags = 0;
+ CXString x = createCXString(I[3]);
print_usr(clang_constructUSR_ObjCMethod(I[1], atoi(I[2]), x));
}
I += 4;
@@ -4090,9 +4275,7 @@ int print_usrs(const char **I, const char **E) {
if (!isUSR(I[2]))
return not_usr("<class USR>", I[2]);
else {
- CXString x;
- x.data = (void*) I[2];
- x.private_flags = 0;
+ CXString x = createCXString(I[2]);
print_usr(clang_constructUSR_ObjCProperty(I[1], x));
}
I += 3;
@@ -4261,10 +4444,10 @@ static void printLocation(CXSourceLocation L) {
CXFile File;
CXString FileName;
unsigned line, column, offset;
-
+
clang_getExpansionLocation(L, &File, &line, &column, &offset);
FileName = clang_getFileName(File);
-
+
fprintf(stderr, "%s:%d:%d", clang_getCString(FileName), line, column);
clang_disposeString(FileName);
}
diff --git a/tools/c-index-test/core_main.cpp b/tools/c-index-test/core_main.cpp
index c255f54ba68c..a7732c09d5b0 100644
--- a/tools/c-index-test/core_main.cpp
+++ b/tools/c-index-test/core_main.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/Basic/LangOptions.h"
#include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
@@ -16,6 +17,7 @@
#include "clang/Index/IndexDataConsumer.h"
#include "clang/Index/USRGeneration.h"
#include "clang/Index/CodegenNameGenerator.h"
+#include "clang/Lex/Preprocessor.h"
#include "clang/Serialization/ASTReader.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Signals.h"
@@ -77,6 +79,7 @@ namespace {
class PrintIndexDataConsumer : public IndexDataConsumer {
raw_ostream &OS;
std::unique_ptr<CodegenNameGenerator> CGNameGen;
+ std::shared_ptr<Preprocessor> PP;
public:
PrintIndexDataConsumer(raw_ostream &OS) : OS(OS) {
@@ -86,15 +89,20 @@ public:
CGNameGen.reset(new CodegenNameGenerator(Ctx));
}
+ void setPreprocessor(std::shared_ptr<Preprocessor> PP) override {
+ this->PP = std::move(PP);
+ }
+
bool handleDeclOccurence(const Decl *D, SymbolRoleSet Roles,
ArrayRef<SymbolRelation> Relations,
- FileID FID, unsigned Offset,
- ASTNodeInfo ASTNode) override {
+ SourceLocation Loc, ASTNodeInfo ASTNode) override {
ASTContext &Ctx = D->getASTContext();
SourceManager &SM = Ctx.getSourceManager();
- unsigned Line = SM.getLineNumber(FID, Offset);
- unsigned Col = SM.getColumnNumber(FID, Offset);
+ Loc = SM.getFileLoc(Loc);
+ FileID FID = SM.getFileID(Loc);
+ unsigned Line = SM.getLineNumber(FID, SM.getFileOffset(Loc));
+ unsigned Col = SM.getColumnNumber(FID, SM.getFileOffset(Loc));
OS << Line << ':' << Col << " | ";
printSymbolInfo(getSymbolInfo(D), OS);
@@ -124,12 +132,14 @@ public:
}
bool handleModuleOccurence(const ImportDecl *ImportD, SymbolRoleSet Roles,
- FileID FID, unsigned Offset) override {
+ SourceLocation Loc) override {
ASTContext &Ctx = ImportD->getASTContext();
SourceManager &SM = Ctx.getSourceManager();
- unsigned Line = SM.getLineNumber(FID, Offset);
- unsigned Col = SM.getColumnNumber(FID, Offset);
+ Loc = SM.getFileLoc(Loc);
+ FileID FID = SM.getFileID(Loc);
+ unsigned Line = SM.getLineNumber(FID, SM.getFileOffset(Loc));
+ unsigned Col = SM.getColumnNumber(FID, SM.getFileOffset(Loc));
OS << Line << ':' << Col << " | ";
printSymbolInfo(getSymbolInfo(ImportD), OS);
@@ -142,6 +152,37 @@ public:
return true;
}
+
+ bool handleMacroOccurence(const IdentifierInfo *Name, const MacroInfo *MI,
+ SymbolRoleSet Roles, SourceLocation Loc) override {
+ assert(PP);
+ SourceManager &SM = PP->getSourceManager();
+
+ Loc = SM.getFileLoc(Loc);
+ FileID FID = SM.getFileID(Loc);
+ unsigned Line = SM.getLineNumber(FID, SM.getFileOffset(Loc));
+ unsigned Col = SM.getColumnNumber(FID, SM.getFileOffset(Loc));
+ OS << Line << ':' << Col << " | ";
+
+ printSymbolInfo(getSymbolInfoForMacro(*MI), OS);
+ OS << " | ";
+
+ OS << Name->getName();
+ OS << " | ";
+
+ SmallString<256> USRBuf;
+ if (generateUSRForMacro(Name->getName(), MI->getDefinitionLoc(), SM,
+ USRBuf)) {
+ OS << "<no-usr>";
+ } else {
+ OS << USRBuf;
+ }
+ OS << " | ";
+
+ printSymbolRoles(Roles, OS);
+ OS << " |\n";
+ return true;
+ }
};
} // anonymous namespace
@@ -192,7 +233,7 @@ static bool printSourceSymbols(ArrayRef<const char *> Args,
if (auto Reader = Unit->getASTReader()) {
Reader->getModuleManager().visit([&](serialization::ModuleFile &Mod) -> bool {
OS << "==== Module " << Mod.ModuleName << " ====\n";
- indexModuleFile(Mod, *Reader, DataConsumer, IndexOpts);
+ indexModuleFile(Mod, *Reader, *DataConsumer, IndexOpts);
dumpModuleFileInputs(Mod, *Reader, OS);
return true; // skip module dependencies.
});
@@ -228,7 +269,7 @@ static bool printSourceSymbolsFromModule(StringRef modulePath,
return true;
}
- auto DataConsumer = std::make_shared<PrintIndexDataConsumer>(outs());
+ PrintIndexDataConsumer DataConsumer(outs());
IndexingOptions IndexOpts;
indexASTUnit(*AU, DataConsumer, IndexOpts);
diff --git a/tools/clang-check/ClangCheck.cpp b/tools/clang-check/ClangCheck.cpp
index e190c0721afb..f00e9a3df0ad 100644
--- a/tools/clang-check/ClangCheck.cpp
+++ b/tools/clang-check/ClangCheck.cpp
@@ -103,7 +103,7 @@ public:
}
};
-/// \brief Subclasses \c clang::FixItRewriter to not count fixed errors/warnings
+/// Subclasses \c clang::FixItRewriter to not count fixed errors/warnings
/// in the final error counts.
///
/// This has the side-effect that clang-check -fixit exits with code 0 on
@@ -120,7 +120,7 @@ public:
bool IncludeInDiagnosticCounts() const override { return false; }
};
-/// \brief Subclasses \c clang::FixItAction so that we can install the custom
+/// Subclasses \c clang::FixItAction so that we can install the custom
/// \c FixItRewriter.
class FixItAction : public clang::FixItAction {
public:
@@ -138,7 +138,9 @@ public:
if (ASTList)
return clang::CreateASTDeclNodeLister();
if (ASTDump)
- return clang::CreateASTDumper(ASTDumpFilter, /*DumpDecls=*/true,
+ return clang::CreateASTDumper(nullptr /*Dump to stdout.*/,
+ ASTDumpFilter,
+ /*DumpDecls=*/true,
/*Deserialize=*/false,
/*DumpLookups=*/false);
if (ASTPrint)
diff --git a/tools/clang-format-vs/ClangFormat/ClangFormatPackage.cs b/tools/clang-format-vs/ClangFormat/ClangFormatPackage.cs
index efb2147f2b43..1071b680aea0 100644
--- a/tools/clang-format-vs/ClangFormat/ClangFormatPackage.cs
+++ b/tools/clang-format-vs/ClangFormat/ClangFormatPackage.cs
@@ -38,7 +38,7 @@ namespace LLVM.ClangFormat
private string style = "file";
private bool formatOnSave = false;
private string formatOnSaveFileExtensions =
- ".c;.cpp;.cxx;.cc;.tli;.tlh;.h;.hh;.hpp;.hxx;.hh;.inl" +
+ ".c;.cpp;.cxx;.cc;.tli;.tlh;.h;.hh;.hpp;.hxx;.hh;.inl;" +
".java;.js;.ts;.m;.mm;.proto;.protodevel;.td";
public OptionPageGrid Clone()
diff --git a/tools/clang-format-vs/ClangFormat/license.txt b/tools/clang-format-vs/ClangFormat/license.txt
index 9966c8123f5b..76aa2afdf81e 100644
--- a/tools/clang-format-vs/ClangFormat/license.txt
+++ b/tools/clang-format-vs/ClangFormat/license.txt
@@ -4,7 +4,7 @@ LLVM Release License
University of Illinois/NCSA
Open Source License
-Copyright (c) 2007-2017 University of Illinois at Urbana-Champaign.
+Copyright (c) 2007-2018 University of Illinois at Urbana-Champaign.
All rights reserved.
Developed by:
diff --git a/tools/clang-format/ClangFormat.cpp b/tools/clang-format/ClangFormat.cpp
index b7179ffd6416..de2f9d7fe76e 100644
--- a/tools/clang-format/ClangFormat.cpp
+++ b/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/tools/clang-format/clang-format.el b/tools/clang-format/clang-format.el
index 6c626e0b83d1..4f11daf15fa9 100644
--- a/tools/clang-format/clang-format.el
+++ b/tools/clang-format/clang-format.el
@@ -153,7 +153,7 @@ uses the function `buffer-file-name'."
nil nil clang-format-executable
nil `(,temp-buffer ,temp-file) nil
`("-output-replacements-xml"
- ;; Gaurd against a nil assume-file-name.
+ ;; Guard against a nil assume-file-name.
;; If the clang-format option -assume-filename
;; is given a blank string it will crash as per
;; the following bug report
diff --git a/tools/clang-format/fuzzer/ClangFormatFuzzer.cpp b/tools/clang-format/fuzzer/ClangFormatFuzzer.cpp
index d440a6124b67..0c9ae848d59b 100644
--- a/tools/clang-format/fuzzer/ClangFormatFuzzer.cpp
+++ b/tools/clang-format/fuzzer/ClangFormatFuzzer.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file implements a function that runs Clang format on a single
+/// This file implements a function that runs Clang format on a single
/// input. This function is then linked into the Fuzzer library.
///
//===----------------------------------------------------------------------===//
diff --git a/tools/clang-format/git-clang-format b/tools/clang-format/git-clang-format
index 60cd4fb25b63..0b2103962a31 100755
--- a/tools/clang-format/git-clang-format
+++ b/tools/clang-format/git-clang-format
@@ -79,6 +79,7 @@ def main():
'm', # ObjC
'mm', # ObjC++
'cc', 'cp', 'cpp', 'c++', 'cxx', 'hpp', # C++
+ 'cu', # CUDA
# Other languages that clang-format supports
'proto', 'protodevel', # Protocol Buffers
'java', # Java
diff --git a/tools/clang-fuzzer/CMakeLists.txt b/tools/clang-fuzzer/CMakeLists.txt
index b351ec51652d..5f07e66fe675 100644
--- a/tools/clang-fuzzer/CMakeLists.txt
+++ b/tools/clang-fuzzer/CMakeLists.txt
@@ -9,12 +9,13 @@ elseif(LLVM_USE_SANITIZE_COVERAGE)
unset(DUMMY_MAIN)
endif()
-# Hack to bypass LLVM's cmake sources check and allow multiple libraries and
-# executables from this directory.
+# Needed by LLVM's CMake checks because this file defines multiple targets.
set(LLVM_OPTIONAL_SOURCES
ClangFuzzer.cpp
DummyClangFuzzer.cpp
ExampleClangProtoFuzzer.cpp
+ ExampleClangLoopProtoFuzzer.cpp
+ ExampleClangLLVMProtoFuzzer.cpp
)
if(CLANG_ENABLE_PROTO_FUZZER)
@@ -25,6 +26,7 @@ if(CLANG_ENABLE_PROTO_FUZZER)
include_directories(${PROTOBUF_INCLUDE_DIRS})
include_directories(${CMAKE_CURRENT_BINARY_DIR})
protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS cxx_proto.proto)
+ protobuf_generate_cpp(LOOP_PROTO_SRCS LOOP_PROTO_HDRS cxx_loop_proto.proto)
set(LLVM_OPTIONAL_SOURCES ${LLVM_OPTIONAL_SOURCES} ${PROTO_SRCS})
add_clang_library(clangCXXProto
${PROTO_SRCS}
@@ -34,6 +36,14 @@ if(CLANG_ENABLE_PROTO_FUZZER)
${PROTOBUF_LIBRARIES}
)
+ add_clang_library(clangCXXLoopProto
+ ${LOOP_PROTO_SRCS}
+ ${LOOP_PROTO_HDRS}
+
+ LINK_LIBS
+ ${PROTOBUF_LIBRARIES}
+ )
+
# Build and include libprotobuf-mutator
include(ProtobufMutator)
include_directories(${ProtobufMutator_INCLUDE_DIRS})
@@ -41,24 +51,63 @@ if(CLANG_ENABLE_PROTO_FUZZER)
# Build the protobuf->C++ translation library and driver.
add_clang_subdirectory(proto-to-cxx)
+ # Build the protobuf->LLVM IR translation library and driver.
+ add_clang_subdirectory(proto-to-llvm)
+
+ # Build the fuzzer initialization library.
+ add_clang_subdirectory(fuzzer-initialize)
+
# Build the protobuf fuzzer
add_clang_executable(clang-proto-fuzzer
${DUMMY_MAIN}
ExampleClangProtoFuzzer.cpp
)
- target_link_libraries(clang-proto-fuzzer
- PRIVATE
+ # Build the loop protobuf fuzzer
+ add_clang_executable(clang-loop-proto-fuzzer
+ ${DUMMY_MAIN}
+ ExampleClangLoopProtoFuzzer.cpp
+ )
+
+ # Build the llvm protobuf fuzzer
+ add_clang_executable(clang-llvm-proto-fuzzer
+ ${DUMMY_MAIN}
+ ExampleClangLLVMProtoFuzzer.cpp
+ )
+
+ set(COMMON_PROTO_FUZZ_LIBRARIES
${ProtobufMutator_LIBRARIES}
${PROTOBUF_LIBRARIES}
${LLVM_LIB_FUZZING_ENGINE}
- clangCXXProto
+ clangFuzzerInitialize
+ )
+
+ target_link_libraries(clang-proto-fuzzer
+ PRIVATE
+ ${COMMON_PROTO_FUZZ_LIBRARIES}
clangHandleCXX
+ clangCXXProto
clangProtoToCXX
)
+ target_link_libraries(clang-loop-proto-fuzzer
+ PRIVATE
+ ${COMMON_PROTO_FUZZ_LIBRARIES}
+ clangHandleCXX
+ clangCXXLoopProto
+ clangLoopProtoToCXX
+ )
+ target_link_libraries(clang-llvm-proto-fuzzer
+ PRIVATE
+ ${COMMON_PROTO_FUZZ_LIBRARIES}
+ clangHandleLLVM
+ clangCXXLoopProto
+ clangLoopProtoToLLVM
+ )
+
endif()
add_clang_subdirectory(handle-cxx)
+add_clang_subdirectory(handle-llvm)
add_clang_executable(clang-fuzzer
EXCLUDE_FROM_ALL
diff --git a/tools/clang-fuzzer/ClangFuzzer.cpp b/tools/clang-fuzzer/ClangFuzzer.cpp
index 2d35fb7735f9..f169f58a39b6 100644
--- a/tools/clang-fuzzer/ClangFuzzer.cpp
+++ b/tools/clang-fuzzer/ClangFuzzer.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file implements a function that runs Clang on a single
+/// This file implements a function that runs Clang on a single
/// input. This function is then linked into the Fuzzer library.
///
//===----------------------------------------------------------------------===//
diff --git a/tools/clang-fuzzer/ExampleClangLLVMProtoFuzzer.cpp b/tools/clang-fuzzer/ExampleClangLLVMProtoFuzzer.cpp
new file mode 100644
index 000000000000..347ba1c320df
--- /dev/null
+++ b/tools/clang-fuzzer/ExampleClangLLVMProtoFuzzer.cpp
@@ -0,0 +1,28 @@
+//===-- ExampleClangLLVMProtoFuzzer.cpp - Fuzz Clang ----------------------===//
+//
+// 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 function that compiles a single LLVM IR string as
+/// input and uses libprotobuf-mutator to find new inputs. This function is
+/// then linked into the Fuzzer library.
+///
+//===----------------------------------------------------------------------===//
+
+#include "cxx_loop_proto.pb.h"
+#include "fuzzer-initialize/fuzzer_initialize.h"
+#include "handle-llvm/handle_llvm.h"
+#include "proto-to-llvm/loop_proto_to_llvm.h"
+#include "src/libfuzzer/libfuzzer_macro.h"
+
+using namespace clang_fuzzer;
+
+DEFINE_BINARY_PROTO_FUZZER(const LoopFunction &input) {
+ auto S = LoopFunctionToLLVMString(input);
+ HandleLLVM(S, GetCLArgs());
+}
diff --git a/tools/clang-fuzzer/ExampleClangLoopProtoFuzzer.cpp b/tools/clang-fuzzer/ExampleClangLoopProtoFuzzer.cpp
new file mode 100644
index 000000000000..3640be13fafd
--- /dev/null
+++ b/tools/clang-fuzzer/ExampleClangLoopProtoFuzzer.cpp
@@ -0,0 +1,30 @@
+//===-- ExampleClangLoopProtoFuzzer.cpp - Fuzz Clang ----------------------===//
+//
+// 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 function that runs Clang on a single
+/// input and uses libprotobuf-mutator to find new inputs. This function is
+/// then linked into the Fuzzer library. This file differs from
+/// ExampleClangProtoFuzzer in that it uses a different protobuf that includes
+/// C++ code with a single for loop.
+///
+//===----------------------------------------------------------------------===//
+
+#include "cxx_loop_proto.pb.h"
+#include "fuzzer-initialize/fuzzer_initialize.h"
+#include "handle-cxx/handle_cxx.h"
+#include "proto-to-cxx/proto_to_cxx.h"
+#include "src/libfuzzer/libfuzzer_macro.h"
+
+using namespace clang_fuzzer;
+
+DEFINE_BINARY_PROTO_FUZZER(const LoopFunction &input) {
+ auto S = LoopFunctionToString(input);
+ HandleCXX(S, GetCLArgs());
+}
diff --git a/tools/clang-fuzzer/ExampleClangProtoFuzzer.cpp b/tools/clang-fuzzer/ExampleClangProtoFuzzer.cpp
index ab734e85b857..159ded3ca185 100644
--- a/tools/clang-fuzzer/ExampleClangProtoFuzzer.cpp
+++ b/tools/clang-fuzzer/ExampleClangProtoFuzzer.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file implements a function that runs Clang on a single
+/// This file implements a function that runs Clang on a single
/// input and uses libprotobuf-mutator to find new inputs. This function is
/// then linked into the Fuzzer library.
///
@@ -17,28 +17,12 @@
#include "cxx_proto.pb.h"
#include "handle-cxx/handle_cxx.h"
#include "proto-to-cxx/proto_to_cxx.h"
-
+#include "fuzzer-initialize/fuzzer_initialize.h"
#include "src/libfuzzer/libfuzzer_macro.h"
-#include <cstring>
-
using namespace clang_fuzzer;
-static std::vector<const char *> CLArgs;
-
-extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
- CLArgs.push_back("-O2");
- for (int I = 1; I < *argc; I++) {
- if (strcmp((*argv)[I], "-ignore_remaining_args=1") == 0) {
- for (I++; I < *argc; I++)
- CLArgs.push_back((*argv)[I]);
- break;
- }
- }
- return 0;
-}
-
DEFINE_BINARY_PROTO_FUZZER(const Function& input) {
auto S = FunctionToString(input);
- HandleCXX(S, CLArgs);
+ HandleCXX(S, GetCLArgs());
}
diff --git a/tools/clang-fuzzer/cxx_loop_proto.proto b/tools/clang-fuzzer/cxx_loop_proto.proto
new file mode 100644
index 000000000000..f2b47ed43d89
--- /dev/null
+++ b/tools/clang-fuzzer/cxx_loop_proto.proto
@@ -0,0 +1,80 @@
+//===-- cxx_loop_proto.proto - Protobuf description of C++ with for loops -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file describes a subset of C++ as a protobuf. It is used to
+/// more easily find interesting inputs for fuzzing Clang. This subset
+/// differs from the one defined in cxx_proto.proto by eliminating while
+/// loops and conditionals. The goal is that the C++ code generated will be
+/// more likely to stress the LLVM loop vectorizer.
+///
+//===----------------------------------------------------------------------===//
+
+syntax = "proto2";
+
+message Const {
+ required int32 val = 1;
+}
+
+message VarRef {
+ // Add an enum for each array in function signature
+ enum Arr {
+ ARR_A = 0;
+ ARR_B = 1;
+ ARR_C = 2;
+ };
+ required Arr arr = 1;
+}
+
+message BinaryOp {
+ enum Op {
+ PLUS = 0;
+ MINUS = 1;
+ MUL = 2;
+ XOR = 3;
+ AND = 4;
+ OR = 5;
+ EQ = 6;
+ NE = 7;
+ LE = 8;
+ GE = 9;
+ LT = 10;
+ GT = 11;
+ };
+ required Op op = 1;
+ required Rvalue left = 2;
+ required Rvalue right = 3;
+}
+
+message Rvalue {
+ oneof rvalue_oneof {
+ Const cons = 1;
+ BinaryOp binop = 2;
+ VarRef varref = 3;
+ }
+}
+
+message AssignmentStatement {
+ required VarRef varref = 1;
+ required Rvalue rvalue = 2;
+}
+
+message Statement {
+ required AssignmentStatement assignment = 1;
+}
+
+message StatementSeq {
+ repeated Statement statements = 1;
+}
+
+message LoopFunction {
+ required StatementSeq statements = 1;
+}
+
+package clang_fuzzer;
diff --git a/tools/clang-fuzzer/cxx_proto.proto b/tools/clang-fuzzer/cxx_proto.proto
index 714a29861e6a..499101fc0fbd 100644
--- a/tools/clang-fuzzer/cxx_proto.proto
+++ b/tools/clang-fuzzer/cxx_proto.proto
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file describes a subset of C++ as a protobuf. It is used to
+/// This file describes a subset of C++ as a protobuf. It is used to
/// more easily find interesting inputs for fuzzing Clang.
///
//===----------------------------------------------------------------------===//
diff --git a/tools/clang-fuzzer/fuzzer-initialize/CMakeLists.txt b/tools/clang-fuzzer/fuzzer-initialize/CMakeLists.txt
new file mode 100644
index 000000000000..c149fb3d4b36
--- /dev/null
+++ b/tools/clang-fuzzer/fuzzer-initialize/CMakeLists.txt
@@ -0,0 +1,3 @@
+set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} Support)
+
+add_clang_library(clangFuzzerInitialize fuzzer_initialize.cpp)
diff --git a/tools/clang-fuzzer/fuzzer-initialize/fuzzer_initialize.cpp b/tools/clang-fuzzer/fuzzer-initialize/fuzzer_initialize.cpp
new file mode 100644
index 000000000000..75bf22803bce
--- /dev/null
+++ b/tools/clang-fuzzer/fuzzer-initialize/fuzzer_initialize.cpp
@@ -0,0 +1,65 @@
+//===-- fuzzer_initialize.cpp - Fuzz Clang --------------------------------===//
+//
+// 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 two functions: one that returns the command line
+/// arguments for a given call to the fuzz target and one that initializes
+/// the fuzzer with the correct command line arguments.
+///
+//===----------------------------------------------------------------------===//
+
+#include "fuzzer_initialize.h"
+
+#include "llvm/InitializePasses.h"
+#include "llvm/PassRegistry.h"
+#include "llvm/Support/TargetSelect.h"
+#include <cstring>
+
+using namespace clang_fuzzer;
+using namespace llvm;
+
+
+namespace clang_fuzzer {
+
+static std::vector<const char *> CLArgs;
+
+const std::vector<const char *>& GetCLArgs() {
+ return CLArgs;
+}
+
+}
+
+extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
+ InitializeAllTargets();
+ InitializeAllTargetMCs();
+ InitializeAllAsmPrinters();
+ InitializeAllAsmParsers();
+
+ PassRegistry &Registry = *PassRegistry::getPassRegistry();
+ initializeCore(Registry);
+ initializeScalarOpts(Registry);
+ initializeVectorization(Registry);
+ initializeIPO(Registry);
+ initializeAnalysis(Registry);
+ initializeTransformUtils(Registry);
+ initializeInstCombine(Registry);
+ initializeAggressiveInstCombine(Registry);
+ initializeInstrumentation(Registry);
+ initializeTarget(Registry);
+
+ CLArgs.push_back("-O2");
+ for (int I = 1; I < *argc; I++) {
+ if (strcmp((*argv)[I], "-ignore_remaining_args=1") == 0) {
+ for (I++; I < *argc; I++)
+ CLArgs.push_back((*argv)[I]);
+ break;
+ }
+ }
+ return 0;
+}
diff --git a/tools/clang-fuzzer/fuzzer-initialize/fuzzer_initialize.h b/tools/clang-fuzzer/fuzzer-initialize/fuzzer_initialize.h
new file mode 100644
index 000000000000..83a5cf9dc571
--- /dev/null
+++ b/tools/clang-fuzzer/fuzzer-initialize/fuzzer_initialize.h
@@ -0,0 +1,19 @@
+//==-- fuzzer_initialize.h - Fuzz Clang ------------------------------------==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines a function that returns the command line arguments for a specific
+// call to the fuzz target.
+//
+//===----------------------------------------------------------------------===//
+
+#include <vector>
+
+namespace clang_fuzzer {
+const std::vector<const char *>& GetCLArgs();
+}
diff --git a/tools/clang-fuzzer/handle-cxx/handle_cxx.cpp b/tools/clang-fuzzer/handle-cxx/handle_cxx.cpp
index 312ab91e5fe2..4985fedbe118 100644
--- a/tools/clang-fuzzer/handle-cxx/handle_cxx.cpp
+++ b/tools/clang-fuzzer/handle-cxx/handle_cxx.cpp
@@ -18,17 +18,11 @@
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/Option/Option.h"
-#include "llvm/Support/TargetSelect.h"
using namespace clang;
void clang_fuzzer::HandleCXX(const std::string &S,
const std::vector<const char *> &ExtraArgs) {
- llvm::InitializeAllTargets();
- llvm::InitializeAllTargetMCs();
- llvm::InitializeAllAsmPrinters();
- llvm::InitializeAllAsmParsers();
-
llvm::opt::ArgStringList CC1Args;
CC1Args.push_back("-cc1");
for (auto &A : ExtraArgs)
diff --git a/tools/clang-fuzzer/handle-llvm/CMakeLists.txt b/tools/clang-fuzzer/handle-llvm/CMakeLists.txt
new file mode 100644
index 000000000000..47f9fdf68f40
--- /dev/null
+++ b/tools/clang-fuzzer/handle-llvm/CMakeLists.txt
@@ -0,0 +1,30 @@
+set(LLVM_LINK_COMPONENTS
+ Analysis
+ CodeGen
+ Core
+ ExecutionEngine
+ IPO
+ IRReader
+ MC
+ MCJIT
+ Object
+ RuntimeDyld
+ SelectionDAG
+ Support
+ Target
+ TransformUtils
+ native
+)
+
+# Depend on LLVM IR intrinsic generation.
+set(handle_llvm_deps intrinsics_gen)
+if (CLANG_BUILT_STANDALONE)
+ set(handle_llvm_deps)
+endif()
+
+add_clang_library(clangHandleLLVM
+ handle_llvm.cpp
+
+ DEPENDS
+ ${handle_llvm_deps}
+ )
diff --git a/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp b/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp
new file mode 100644
index 000000000000..ef544ae711ab
--- /dev/null
+++ b/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp
@@ -0,0 +1,178 @@
+//==-- handle_llvm.cpp - Helper function for Clang fuzzers -----------------==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implements HandleLLVM for use by the Clang fuzzers. First runs a loop
+// vectorizer optimization pass over the given IR code. Then mimics lli on both
+// versions to JIT the generated code and execute it. Currently, functions are
+// executed on dummy inputs.
+//
+//===----------------------------------------------------------------------===//
+
+#include "handle_llvm.h"
+
+#include "llvm/ADT/Triple.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
+#include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/CodeGen/CommandFlags.inc"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/TargetPassConfig.h"
+#include "llvm/ExecutionEngine/JITEventListener.h"
+#include "llvm/ExecutionEngine/JITSymbol.h"
+#include "llvm/ExecutionEngine/MCJIT.h"
+#include "llvm/ExecutionEngine/ObjectCache.h"
+#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
+#include "llvm/ExecutionEngine/SectionMemoryManager.h"
+#include "llvm/IR/IRPrintingPasses.h"
+#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/IR/LegacyPassNameParser.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Verifier.h"
+#include "llvm/IRReader/IRReader.h"
+#include "llvm/Pass.h"
+#include "llvm/PassRegistry.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#include "llvm/Transforms/IPO.h"
+#include "llvm/Transforms/Vectorize.h"
+
+using namespace llvm;
+
+// Helper function to parse command line args and find the optimization level
+static void getOptLevel(const std::vector<const char *> &ExtraArgs,
+ CodeGenOpt::Level &OLvl) {
+ // Find the optimization level from the command line args
+ OLvl = CodeGenOpt::Default;
+ for (auto &A : ExtraArgs) {
+ if (A[0] == '-' && A[1] == 'O') {
+ switch(A[2]) {
+ case '0': OLvl = CodeGenOpt::None; break;
+ case '1': OLvl = CodeGenOpt::Less; break;
+ case '2': OLvl = CodeGenOpt::Default; break;
+ case '3': OLvl = CodeGenOpt::Aggressive; break;
+ default:
+ errs() << "error: opt level must be between 0 and 3.\n";
+ std::exit(1);
+ }
+ }
+ }
+}
+
+void ErrorAndExit(std::string message) {
+ errs()<< "ERROR: " << message << "\n";
+ std::exit(1);
+}
+
+// Helper function to add optimization passes to the TargetMachine at the
+// specified optimization level, OptLevel
+static void AddOptimizationPasses(legacy::PassManagerBase &MPM,
+ CodeGenOpt::Level OptLevel,
+ unsigned SizeLevel) {
+ // Create and initialize a PassManagerBuilder
+ PassManagerBuilder Builder;
+ Builder.OptLevel = OptLevel;
+ Builder.SizeLevel = SizeLevel;
+ Builder.Inliner = createFunctionInliningPass(OptLevel, SizeLevel, false);
+ Builder.LoopVectorize = true;
+ Builder.populateModulePassManager(MPM);
+}
+
+// Mimics the opt tool to run an optimization pass over the provided IR
+std::string OptLLVM(const std::string &IR, CodeGenOpt::Level OLvl) {
+ // Create a module that will run the optimization passes
+ SMDiagnostic Err;
+ LLVMContext Context;
+ std::unique_ptr<Module> M = parseIR(MemoryBufferRef(IR, "IR"), Err, Context);
+ if (!M || verifyModule(*M, &errs()))
+ ErrorAndExit("Could not parse IR");
+
+ setFunctionAttributes(getCPUStr(), getFeaturesStr(), *M);
+
+ legacy::PassManager Passes;
+ Triple ModuleTriple(M->getTargetTriple());
+
+ Passes.add(new TargetLibraryInfoWrapperPass(ModuleTriple));
+ Passes.add(createTargetTransformInfoWrapperPass(TargetIRAnalysis()));
+ Passes.add(createVerifierPass());
+
+ AddOptimizationPasses(Passes, OLvl, 0);
+
+ // Add a pass that writes the optimized IR to an output stream
+ std::string outString;
+ raw_string_ostream OS(outString);
+ Passes.add(createPrintModulePass(OS, "", false));
+
+ Passes.run(*M);
+
+ return OS.str();
+}
+
+void CreateAndRunJITFun(const std::string &IR, CodeGenOpt::Level OLvl) {
+ SMDiagnostic Err;
+ LLVMContext Context;
+ std::unique_ptr<Module> M = parseIR(MemoryBufferRef(IR, "IR"), Err,
+ Context);
+ if (!M)
+ ErrorAndExit("Could not parse IR");
+
+ Function *EntryFunc = M->getFunction("foo");
+ if (!EntryFunc)
+ ErrorAndExit("Function not found in module");
+
+ std::string ErrorMsg;
+ EngineBuilder builder(std::move(M));
+ builder.setMArch(MArch);
+ builder.setMCPU(getCPUStr());
+ builder.setMAttrs(getFeatureList());
+ builder.setErrorStr(&ErrorMsg);
+ builder.setEngineKind(EngineKind::JIT);
+ builder.setUseOrcMCJITReplacement(false);
+ builder.setMCJITMemoryManager(make_unique<SectionMemoryManager>());
+ builder.setOptLevel(OLvl);
+ builder.setTargetOptions(InitTargetOptionsFromCodeGenFlags());
+
+ std::unique_ptr<ExecutionEngine> EE(builder.create());
+ if (!EE)
+ ErrorAndExit("Could not create execution engine");
+
+ EE->finalizeObject();
+ EE->runStaticConstructorsDestructors(false);
+
+ typedef void (*func)(int*, int*, int*, int);
+ func f = reinterpret_cast<func>(EE->getPointerToFunction(EntryFunc));
+
+ // Define some dummy arrays to use an input for now
+ int a[] = {1};
+ int b[] = {1};
+ int c[] = {1};
+ f(a, b, c, 1);
+
+ EE->runStaticConstructorsDestructors(true);
+}
+
+// Main fuzz target called by ExampleClangLLVMProtoFuzzer.cpp
+// Mimics the lli tool to JIT the LLVM IR code and execute it
+void clang_fuzzer::HandleLLVM(const std::string &IR,
+ const std::vector<const char *> &ExtraArgs) {
+ // Parse ExtraArgs to set the optimization level
+ CodeGenOpt::Level OLvl;
+ getOptLevel(ExtraArgs, OLvl);
+
+ // First we optimize the IR by running a loop vectorizer pass
+ std::string OptIR = OptLLVM(IR, OLvl);
+
+ CreateAndRunJITFun(OptIR, OLvl);
+ CreateAndRunJITFun(IR, CodeGenOpt::None);
+
+ return;
+}
diff --git a/tools/clang-fuzzer/handle-llvm/handle_llvm.h b/tools/clang-fuzzer/handle-llvm/handle_llvm.h
new file mode 100644
index 000000000000..38aec6799490
--- /dev/null
+++ b/tools/clang-fuzzer/handle-llvm/handle_llvm.h
@@ -0,0 +1,25 @@
+//==-- handle_llvm.h - Helper function for Clang fuzzers -------------------==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines HandleLLVM for use by the Clang fuzzers.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_CLANG_FUZZER_HANDLE_LLVM_HANDLELLVM_H
+#define LLVM_CLANG_TOOLS_CLANG_FUZZER_HANDLE_LLVM_HANDLELLVM_H
+
+#include <string>
+#include <vector>
+
+namespace clang_fuzzer {
+void HandleLLVM(const std::string &S,
+ const std::vector<const char *> &ExtraArgs);
+} // namespace clang_fuzzer
+
+#endif
diff --git a/tools/clang-fuzzer/proto-to-cxx/CMakeLists.txt b/tools/clang-fuzzer/proto-to-cxx/CMakeLists.txt
index 910b793e0e0d..339959b81af0 100644
--- a/tools/clang-fuzzer/proto-to-cxx/CMakeLists.txt
+++ b/tools/clang-fuzzer/proto-to-cxx/CMakeLists.txt
@@ -1,14 +1,22 @@
set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD})
set(CMAKE_CXX_FLAGS ${CXX_FLAGS_NOFUZZ})
-# Hack to bypass LLVM's CMake source checks so we can have both a library and
-# an executable built from this directory.
-set(LLVM_OPTIONAL_SOURCES proto_to_cxx.cpp proto_to_cxx_main.cpp)
+# Needed by LLVM's CMake checks because this file defines multiple targets.
+set(LLVM_OPTIONAL_SOURCES proto_to_cxx.cpp proto_to_cxx_main.cpp
+ loop_proto_to_cxx.cpp loop_proto_to_cxx_main.cpp)
add_clang_library(clangProtoToCXX proto_to_cxx.cpp
DEPENDS clangCXXProto
LINK_LIBS clangCXXProto ${PROTOBUF_LIBRARIES}
)
+add_clang_library(clangLoopProtoToCXX loop_proto_to_cxx.cpp
+ DEPENDS clangCXXLoopProto
+ LINK_LIBS clangCXXLoopProto ${PROTOBUF_LIBRARIES}
+ )
+
add_clang_executable(clang-proto-to-cxx proto_to_cxx_main.cpp)
+add_clang_executable(clang-loop-proto-to-cxx loop_proto_to_cxx_main.cpp)
+
target_link_libraries(clang-proto-to-cxx PRIVATE clangProtoToCXX)
+target_link_libraries(clang-loop-proto-to-cxx PRIVATE clangLoopProtoToCXX)
diff --git a/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx.cpp b/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx.cpp
new file mode 100644
index 000000000000..7d8f6650aadb
--- /dev/null
+++ b/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx.cpp
@@ -0,0 +1,131 @@
+//==-- loop_proto_to_cxx.cpp - Protobuf-C++ conversion ---------------------==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implements functions for converting between protobufs and C++. Differs from
+// proto_to_cxx.cpp by wrapping all the generated C++ code in a single for
+// loop. Also coutputs a different function signature that includes a
+// size_t parameter for the loop to use. The C++ code generated is meant to
+// stress the LLVM loop vectorizer.
+//
+// Still a work in progress.
+//
+//===----------------------------------------------------------------------===//
+
+#include "cxx_loop_proto.pb.h"
+#include "proto_to_cxx.h"
+
+// The following is needed to convert protos in human-readable form
+#include <google/protobuf/text_format.h>
+
+#include <ostream>
+#include <sstream>
+
+namespace clang_fuzzer {
+
+// Forward decls.
+std::ostream &operator<<(std::ostream &os, const BinaryOp &x);
+std::ostream &operator<<(std::ostream &os, const StatementSeq &x);
+
+// Proto to C++.
+std::ostream &operator<<(std::ostream &os, const Const &x) {
+ return os << "(" << x.val() << ")";
+}
+std::ostream &operator<<(std::ostream &os, const VarRef &x) {
+ switch (x.arr()) {
+ case VarRef::ARR_A:
+ return os << "a[i]";
+ case VarRef::ARR_B:
+ return os << "b[i]";
+ case VarRef::ARR_C:
+ return os << "c[i]";
+ }
+}
+std::ostream &operator<<(std::ostream &os, const Rvalue &x) {
+ if (x.has_cons())
+ return os << x.cons();
+ if (x.has_binop())
+ return os << x.binop();
+ if (x.has_varref())
+ return os << x.varref();
+ return os << "1";
+}
+std::ostream &operator<<(std::ostream &os, const BinaryOp &x) {
+ os << "(" << x.left();
+ switch (x.op()) {
+ case BinaryOp::PLUS:
+ os << "+";
+ break;
+ case BinaryOp::MINUS:
+ os << "-";
+ break;
+ case BinaryOp::MUL:
+ os << "*";
+ break;
+ case BinaryOp::XOR:
+ os << "^";
+ break;
+ case BinaryOp::AND:
+ os << "&";
+ break;
+ case BinaryOp::OR:
+ os << "|";
+ break;
+ case BinaryOp::EQ:
+ os << "==";
+ break;
+ case BinaryOp::NE:
+ os << "!=";
+ break;
+ case BinaryOp::LE:
+ os << "<=";
+ break;
+ case BinaryOp::GE:
+ os << ">=";
+ break;
+ case BinaryOp::LT:
+ os << "<";
+ break;
+ case BinaryOp::GT:
+ os << ">";
+ break;
+ }
+ return os << x.right() << ")";
+}
+std::ostream &operator<<(std::ostream &os, const AssignmentStatement &x) {
+ return os << x.varref() << "=" << x.rvalue() << ";\n";
+}
+std::ostream &operator<<(std::ostream &os, const Statement &x) {
+ return os << x.assignment();
+}
+std::ostream &operator<<(std::ostream &os, const StatementSeq &x) {
+ for (auto &st : x.statements())
+ os << st;
+ return os;
+}
+std::ostream &operator<<(std::ostream &os, const LoopFunction &x) {
+ return os << "void foo(int *a, int *b, int *__restrict__ c, size_t s) {\n"
+ << "for (int i=0; i<s; i++){\n"
+ << x.statements() << "}\n}\n";
+}
+
+// ---------------------------------
+
+std::string LoopFunctionToString(const LoopFunction &input) {
+ std::ostringstream os;
+ os << input;
+ return os.str();
+}
+std::string LoopProtoToCxx(const uint8_t *data, size_t size) {
+ LoopFunction message;
+ if (!message.ParsePartialFromArray(data, size))
+ return "#error invalid proto\n";
+ return LoopFunctionToString(message);
+}
+
+} // namespace clang_fuzzer
diff --git a/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx_main.cpp b/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx_main.cpp
new file mode 100644
index 000000000000..a4b8e58c1273
--- /dev/null
+++ b/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx_main.cpp
@@ -0,0 +1,31 @@
+//==-- loop_proto_to_cxx_main.cpp - Driver for protobuf-C++ conversion -----==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implements a simple driver to print a C++ program from a protobuf with loops.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include <fstream>
+#include <iostream>
+#include <streambuf>
+#include <string>
+
+#include "proto_to_cxx.h"
+
+int main(int argc, char **argv) {
+ for (int i = 1; i < argc; i++) {
+ std::fstream in(argv[i]);
+ std::string str((std::istreambuf_iterator<char>(in)),
+ std::istreambuf_iterator<char>());
+ std::cout << "// " << argv[i] << std::endl;
+ std::cout << clang_fuzzer::LoopProtoToCxx(
+ reinterpret_cast<const uint8_t *>(str.data()), str.size());
+ }
+}
diff --git a/tools/clang-fuzzer/proto-to-cxx/proto_to_cxx.cpp b/tools/clang-fuzzer/proto-to-cxx/proto_to_cxx.cpp
index cd75e0c99c47..4a86515f5598 100644
--- a/tools/clang-fuzzer/proto-to-cxx/proto_to_cxx.cpp
+++ b/tools/clang-fuzzer/proto-to-cxx/proto_to_cxx.cpp
@@ -94,7 +94,7 @@ std::string FunctionToString(const Function &input) {
}
std::string ProtoToCxx(const uint8_t *data, size_t size) {
Function message;
- if (!message.ParseFromArray(data, size))
+ if (!message.ParsePartialFromArray(data, size))
return "#error invalid proto\n";
return FunctionToString(message);
}
diff --git a/tools/clang-fuzzer/proto-to-cxx/proto_to_cxx.h b/tools/clang-fuzzer/proto-to-cxx/proto_to_cxx.h
index 1985e91ba2cd..8d2e2e6f0081 100644
--- a/tools/clang-fuzzer/proto-to-cxx/proto_to_cxx.h
+++ b/tools/clang-fuzzer/proto-to-cxx/proto_to_cxx.h
@@ -17,6 +17,10 @@
namespace clang_fuzzer {
class Function;
+class LoopFunction;
+
std::string FunctionToString(const Function &input);
std::string ProtoToCxx(const uint8_t *data, size_t size);
+std::string LoopFunctionToString(const LoopFunction &input);
+std::string LoopProtoToCxx(const uint8_t *data, size_t size);
}
diff --git a/tools/clang-fuzzer/proto-to-llvm/CMakeLists.txt b/tools/clang-fuzzer/proto-to-llvm/CMakeLists.txt
new file mode 100644
index 000000000000..ae58523f2274
--- /dev/null
+++ b/tools/clang-fuzzer/proto-to-llvm/CMakeLists.txt
@@ -0,0 +1,14 @@
+set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD})
+set(CMAKE_CXX_FLAGS ${CXX_FLAGS_NOFUZZ})
+
+# Needed by LLVM's CMake checks because this file defines multiple targets.
+set(LLVM_OPTIONAL_SOURCES loop_proto_to_llvm.cpp loop_proto_to_llvm_main.cpp)
+
+add_clang_library(clangLoopProtoToLLVM loop_proto_to_llvm.cpp
+ DEPENDS clangCXXLoopProto
+ LINK_LIBS clangCXXLoopProto ${PROTOBUF_LIBRARIES}
+ )
+
+add_clang_executable(clang-loop-proto-to-llvm loop_proto_to_llvm_main.cpp)
+
+target_link_libraries(clang-loop-proto-to-llvm PRIVATE clangLoopProtoToLLVM)
diff --git a/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.cpp b/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.cpp
new file mode 100644
index 000000000000..16dbcb7b49b2
--- /dev/null
+++ b/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.cpp
@@ -0,0 +1,156 @@
+//==-- loop_proto_to_llvm.cpp - Protobuf-C++ conversion
+//---------------------==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implements functions for converting between protobufs and LLVM IR.
+//
+//
+//===----------------------------------------------------------------------===//
+
+#include "loop_proto_to_llvm.h"
+#include "cxx_loop_proto.pb.h"
+
+// The following is needed to convert protos in human-readable form
+#include <google/protobuf/text_format.h>
+
+#include <ostream>
+#include <sstream>
+
+namespace clang_fuzzer {
+
+// Forward decls
+std::string BinopToString(std::ostream &os, const BinaryOp &x);
+std::string StateSeqToString(std::ostream &os, const StatementSeq &x);
+
+// Counter variable to generate new LLVM IR variable names and wrapper function
+std::string get_var() {
+ static int ctr = 0;
+ return "%var" + std::to_string(ctr++);
+}
+
+// Proto to LLVM.
+
+std::string ConstToString(const Const &x) {
+ return std::to_string(x.val());
+}
+std::string VarRefToString(std::ostream &os, const VarRef &x) {
+ std::string arr;
+ switch(x.arr()) {
+ case VarRef::ARR_A:
+ arr = "%a";
+ break;
+ case VarRef::ARR_B:
+ arr = "%b";
+ break;
+ case VarRef::ARR_C:
+ arr = "%c";
+ break;
+ }
+ std::string ptr_var = get_var();
+ os << ptr_var << " = getelementptr i32, i32* " << arr << ", i64 %ct\n";
+ return ptr_var;
+}
+std::string RvalueToString(std::ostream &os, const Rvalue &x) {
+ if(x.has_cons())
+ return ConstToString(x.cons());
+ if(x.has_binop())
+ return BinopToString(os, x.binop());
+ if(x.has_varref()) {
+ std::string var_ref = VarRefToString(os, x.varref());
+ std::string val_var = get_var();
+ os << val_var << " = load i32, i32* " << var_ref << "\n";
+ return val_var;
+ }
+ return "1";
+
+}
+std::string BinopToString(std::ostream &os, const BinaryOp &x) {
+ std::string left = RvalueToString(os, x.left());
+ std::string right = RvalueToString(os, x.right());
+ std::string op;
+ switch (x.op()) {
+ case BinaryOp::PLUS:
+ op = "add";
+ break;
+ case BinaryOp::MINUS:
+ op = "sub";
+ break;
+ case BinaryOp::MUL:
+ op = "mul";
+ break;
+ case BinaryOp::XOR:
+ op = "xor";
+ break;
+ case BinaryOp::AND:
+ op = "and";
+ break;
+ case BinaryOp::OR:
+ op = "or";
+ break;
+ // Support for Boolean operators will be added later
+ case BinaryOp::EQ:
+ case BinaryOp::NE:
+ case BinaryOp::LE:
+ case BinaryOp::GE:
+ case BinaryOp::LT:
+ case BinaryOp::GT:
+ op = "add";
+ break;
+ }
+ std::string val_var = get_var();
+ os << val_var << " = " << op << " i32 " << left << ", " << right << "\n";
+ return val_var;
+}
+std::ostream &operator<<(std::ostream &os, const AssignmentStatement &x) {
+ std::string rvalue = RvalueToString(os, x.rvalue());
+ std::string var_ref = VarRefToString(os, x.varref());
+ return os << "store i32 " << rvalue << ", i32* " << var_ref << "\n";
+}
+std::ostream &operator<<(std::ostream &os, const Statement &x) {
+ return os << x.assignment();
+}
+std::ostream &operator<<(std::ostream &os, const StatementSeq &x) {
+ for (auto &st : x.statements()) {
+ os << st;
+ }
+ return os;
+}
+std::ostream &operator<<(std::ostream &os, const LoopFunction &x) {
+ return os << "define void @foo(i32* %a, i32* %b, i32* noalias %c, i64 %s) {\n"
+ << "%i = alloca i64\n"
+ << "store i64 0, i64* %i\n"
+ << "br label %loop\n\n"
+ << "loop:\n"
+ << "%ct = load i64, i64* %i\n"
+ << "%comp = icmp eq i64 %ct, %s\n"
+ << "br i1 %comp, label %endloop, label %body\n\n"
+ << "body:\n"
+ << x.statements()
+ << "%z = add i64 1, %ct\n"
+ << "store i64 %z, i64* %i\n"
+ << "br label %loop\n\n"
+ << "endloop:\n"
+ << "ret void\n}\n";
+}
+
+// ---------------------------------
+
+std::string LoopFunctionToLLVMString(const LoopFunction &input) {
+ std::ostringstream os;
+ os << input;
+ return os.str();
+}
+std::string LoopProtoToLLVM(const uint8_t *data, size_t size) {
+ LoopFunction message;
+ if (!message.ParsePartialFromArray(data, size))
+ return "#error invalid proto\n";
+ return LoopFunctionToLLVMString(message);
+}
+
+} // namespace clang_fuzzer
diff --git a/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.h b/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.h
new file mode 100644
index 000000000000..51660fcb710b
--- /dev/null
+++ b/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.h
@@ -0,0 +1,23 @@
+//==-- loop_proto_to_llvm.h - Protobuf-C++ conversion ----------------------------==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines functions for converting between protobufs and LLVM IR.
+//
+//===----------------------------------------------------------------------===//
+
+#include <cstdint>
+#include <cstddef>
+#include <string>
+
+namespace clang_fuzzer {
+class LoopFunction;
+
+std::string LoopFunctionToLLVMString(const LoopFunction &input);
+std::string LoopProtoToLLVM(const uint8_t *data, size_t size);
+}
diff --git a/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm_main.cpp b/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm_main.cpp
new file mode 100644
index 000000000000..17ca15ec27f5
--- /dev/null
+++ b/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm_main.cpp
@@ -0,0 +1,31 @@
+//==-- loop_proto_to_llvm_main.cpp - Driver for protobuf-LLVM conversion----==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implements a simple driver to print a LLVM program from a protobuf with loops
+//
+//===----------------------------------------------------------------------===//
+
+
+#include <fstream>
+#include <iostream>
+#include <streambuf>
+#include <string>
+
+#include "loop_proto_to_llvm.h"
+
+int main(int argc, char **argv) {
+ for (int i = 1; i < argc; i++) {
+ std::fstream in(argv[i]);
+ std::string str((std::istreambuf_iterator<char>(in)),
+ std::istreambuf_iterator<char>());
+ std::cout << ";; " << argv[i] << std::endl;
+ std::cout << clang_fuzzer::LoopProtoToLLVM(
+ reinterpret_cast<const uint8_t *>(str.data()), str.size());
+ }
+}
diff --git a/tools/clang-import-test/CMakeLists.txt b/tools/clang-import-test/CMakeLists.txt
index 836efac8ac3e..dfccfe2304bd 100644
--- a/tools/clang-import-test/CMakeLists.txt
+++ b/tools/clang-import-test/CMakeLists.txt
@@ -1,7 +1,7 @@
set(LLVM_LINK_COMPONENTS
- core
- support
-)
+ Core
+ Support
+ )
if(NOT CLANG_BUILT_STANDALONE)
set(tablegen_deps intrinsics_gen)
diff --git a/tools/clang-import-test/clang-import-test.cpp b/tools/clang-import-test/clang-import-test.cpp
index 1ea7ee3611df..106f3d1d150d 100644
--- a/tools/clang-import-test/clang-import-test.cpp
+++ b/tools/clang-import-test/clang-import-test.cpp
@@ -50,9 +50,10 @@ static llvm::cl::opt<bool>
Direct("direct", llvm::cl::Optional,
llvm::cl::desc("Use the parsed declarations without indirection"));
-static llvm::cl::opt<bool>
- UseOrigins("use-origins", llvm::cl::Optional,
- llvm::cl::desc("Use DeclContext origin information for more accurate lookups"));
+static llvm::cl::opt<bool> UseOrigins(
+ "use-origins", llvm::cl::Optional,
+ llvm::cl::desc(
+ "Use DeclContext origin information for more accurate lookups"));
static llvm::cl::list<std::string>
ClangArgs("Xcc", llvm::cl::ZeroOrMore,
@@ -225,7 +226,7 @@ std::unique_ptr<CodeGenerator> BuildCodeGen(CompilerInstance &CI,
CI.getDiagnostics(), ModuleName, CI.getHeaderSearchOpts(),
CI.getPreprocessorOpts(), CI.getCodeGenOpts(), LLVMCtx));
}
-} // end namespace
+} // namespace init_convenience
namespace {
@@ -244,7 +245,7 @@ struct CIAndOrigins {
ASTContext &getASTContext() { return CI->getASTContext(); }
FileManager &getFileManager() { return CI->getFileManager(); }
const OriginMap &getOriginMap() {
- static const OriginMap EmptyOriginMap;
+ static const OriginMap EmptyOriginMap{};
if (ExternalASTSource *Source = CI->getASTContext().getExternalSource())
return static_cast<ExternalASTMerger *>(Source)->GetOrigins();
return EmptyOriginMap;
@@ -261,8 +262,8 @@ void AddExternalSource(CIAndOrigins &CI,
{CI.getASTContext(), CI.getFileManager()});
llvm::SmallVector<ExternalASTMerger::ImporterSource, 3> Sources;
for (CIAndOrigins &Import : Imports)
- Sources.push_back(
- {Import.getASTContext(), Import.getFileManager(), Import.getOriginMap()});
+ Sources.push_back({Import.getASTContext(), Import.getFileManager(),
+ Import.getOriginMap()});
auto ES = llvm::make_unique<ExternalASTMerger>(Target, Sources);
CI.getASTContext().setExternalSource(ES.release());
CI.getASTContext().getTranslationUnitDecl()->setHasExternalVisibleStorage();
@@ -312,7 +313,8 @@ llvm::Expected<CIAndOrigins> Parse(const std::string &Path,
auto &CG = *static_cast<CodeGenerator *>(ASTConsumers.back().get());
if (ShouldDumpAST)
- ASTConsumers.push_back(CreateASTDumper("", true, false, false));
+ ASTConsumers.push_back(CreateASTDumper(nullptr /*Dump to stdout.*/,
+ "", true, false, false));
CI.getDiagnosticClient().BeginSourceFile(
CI.getCompilerInstance().getLangOpts(),
@@ -327,15 +329,15 @@ llvm::Expected<CIAndOrigins> Parse(const std::string &Path,
CG.GetModule()->print(llvm::outs(), nullptr);
if (CI.getDiagnosticClient().getNumErrors())
return llvm::make_error<llvm::StringError>(
- "Errors occured while parsing the expression.", std::error_code());
+ "Errors occurred while parsing the expression.", std::error_code());
return std::move(CI);
}
void Forget(CIAndOrigins &CI, llvm::MutableArrayRef<CIAndOrigins> Imports) {
llvm::SmallVector<ExternalASTMerger::ImporterSource, 3> Sources;
for (CIAndOrigins &Import : Imports)
- Sources.push_back(
- {Import.getASTContext(), Import.getFileManager(), Import.getOriginMap()});
+ Sources.push_back({Import.getASTContext(), Import.getFileManager(),
+ Import.getOriginMap()});
ExternalASTSource *Source = CI.CI->getASTContext().getExternalSource();
auto *Merger = static_cast<ExternalASTMerger *>(Source);
Merger->RemoveSources(Sources);
diff --git a/tools/clang-offload-bundler/ClangOffloadBundler.cpp b/tools/clang-offload-bundler/ClangOffloadBundler.cpp
index 6ff4becb5030..29cd9848d111 100644
--- a/tools/clang-offload-bundler/ClangOffloadBundler.cpp
+++ b/tools/clang-offload-bundler/ClangOffloadBundler.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file implements a clang-offload-bundler that bundles different
+/// This file implements a clang-offload-bundler that bundles different
/// files that relate with the same source code but different targets into a
/// single one. Also the implements the opposite functionality, i.e. unbundle
/// files previous created by this tool.
@@ -412,7 +412,7 @@ class ObjectFileHandler final : public FileHandler {
/// read from the buffers.
unsigned NumberOfProcessedInputs = 0;
- /// LLVM context used to to create the auxiliary modules.
+ /// LLVM context used to create the auxiliary modules.
LLVMContext VMContext;
/// LLVM module used to create an object with all the bundle
@@ -536,23 +536,22 @@ public:
// close it and use the name to pass down to clang.
OS.close();
SmallString<128> TargetName = getTriple(TargetNames[HostInputIndex]);
- const char *ClangArgs[] = {"clang",
- "-r",
- "-target",
- TargetName.c_str(),
- "-o",
- OutputFileNames.front().c_str(),
- InputFileNames[HostInputIndex].c_str(),
- BitcodeFileName.c_str(),
- "-nostdlib",
- nullptr};
+ std::vector<StringRef> ClangArgs = {"clang",
+ "-r",
+ "-target",
+ TargetName.c_str(),
+ "-o",
+ OutputFileNames.front().c_str(),
+ InputFileNames[HostInputIndex].c_str(),
+ BitcodeFileName.c_str(),
+ "-nostdlib"};
// If the user asked for the commands to be printed out, we do that instead
// of executing it.
if (PrintExternalCommands) {
errs() << "\"" << ClangBinary.get() << "\"";
- for (unsigned I = 1; ClangArgs[I]; ++I)
- errs() << " \"" << ClangArgs[I] << "\"";
+ for (StringRef Arg : ClangArgs)
+ errs() << " \"" << Arg << "\"";
errs() << "\n";
} else {
// Write the bitcode contents to the temporary file.
@@ -563,7 +562,7 @@ public:
errs() << "error: unable to open temporary file.\n";
return true;
}
- WriteBitcodeToFile(AuxModule.get(), BitcodeFile);
+ WriteBitcodeToFile(*AuxModule, BitcodeFile);
}
bool Failed = sys::ExecuteAndWait(ClangBinary.get(), ClangArgs);
@@ -969,11 +968,11 @@ int main(int argc, const char **argv) {
getOffloadKindAndTriple(Target, Kind, Triple);
bool KindIsValid = !Kind.empty();
- KindIsValid = KindIsValid &&
- StringSwitch<bool>(Kind)
- .Case("host", true)
- .Case("openmp", true)
- .Default(false);
+ KindIsValid = KindIsValid && StringSwitch<bool>(Kind)
+ .Case("host", true)
+ .Case("openmp", true)
+ .Case("hip", true)
+ .Default(false);
bool TripleIsValid = !Triple.empty();
llvm::Triple T(Triple);
diff --git a/tools/clang-refactor/CMakeLists.txt b/tools/clang-refactor/CMakeLists.txt
index d2029066b9b7..b435744ca4bd 100644
--- a/tools/clang-refactor/CMakeLists.txt
+++ b/tools/clang-refactor/CMakeLists.txt
@@ -20,5 +20,3 @@ target_link_libraries(clang-refactor
clangToolingCore
clangToolingRefactor
)
-
-install(TARGETS clang-refactor RUNTIME DESTINATION bin)
diff --git a/tools/clang-refactor/ClangRefactor.cpp b/tools/clang-refactor/ClangRefactor.cpp
index 950b80062cd9..e64f325be242 100644
--- a/tools/clang-refactor/ClangRefactor.cpp
+++ b/tools/clang-refactor/ClangRefactor.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file implements a clang-refactor tool that performs various
+/// This file implements a clang-refactor tool that performs various
/// source transformations.
///
//===----------------------------------------------------------------------===//
diff --git a/tools/clang-refactor/TestSupport.cpp b/tools/clang-refactor/TestSupport.cpp
index 9331dfd92eb4..f81f4a8bc8fb 100644
--- a/tools/clang-refactor/TestSupport.cpp
+++ b/tools/clang-refactor/TestSupport.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file implements routines that provide refactoring testing
+/// This file implements routines that provide refactoring testing
/// utilities.
///
//===----------------------------------------------------------------------===//
diff --git a/tools/clang-refactor/TestSupport.h b/tools/clang-refactor/TestSupport.h
index 101f35bd94f3..61aa660733fb 100644
--- a/tools/clang-refactor/TestSupport.h
+++ b/tools/clang-refactor/TestSupport.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Declares datatypes and routines that are used by test-specific code
+/// Declares datatypes and routines that are used by test-specific code
/// in clang-refactor.
///
//===----------------------------------------------------------------------===//
diff --git a/tools/clang-rename/CMakeLists.txt b/tools/clang-rename/CMakeLists.txt
index 9689e1c6804d..3b3ab1540a80 100644
--- a/tools/clang-rename/CMakeLists.txt
+++ b/tools/clang-rename/CMakeLists.txt
@@ -3,7 +3,9 @@ set(LLVM_LINK_COMPONENTS
Support
)
-add_clang_tool(clang-rename ClangRename.cpp)
+add_clang_tool(clang-rename
+ ClangRename.cpp
+ )
target_link_libraries(clang-rename
PRIVATE
diff --git a/tools/clang-rename/ClangRename.cpp b/tools/clang-rename/ClangRename.cpp
index 2c14b69ee547..d58f44e4d44e 100644
--- a/tools/clang-rename/ClangRename.cpp
+++ b/tools/clang-rename/ClangRename.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file implements a clang-rename tool that automatically finds and
+/// This file implements a clang-rename tool that automatically finds and
/// renames symbols in C++ code.
///
//===----------------------------------------------------------------------===//
@@ -39,7 +39,7 @@
using namespace llvm;
using namespace clang;
-/// \brief An oldname -> newname rename.
+/// An oldname -> newname rename.
struct RenameAllInfo {
unsigned Offset = 0;
std::string QualifiedName;
@@ -51,7 +51,7 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(RenameAllInfo)
namespace llvm {
namespace yaml {
-/// \brief Specialized MappingTraits to describe how a RenameAllInfo is
+/// Specialized MappingTraits to describe how a RenameAllInfo is
/// (de)serialized.
template <> struct MappingTraits<RenameAllInfo> {
static void mapping(IO &IO, RenameAllInfo &Info) {
diff --git a/tools/diagtool/CMakeLists.txt b/tools/diagtool/CMakeLists.txt
index beb6c35457c4..96d1c390249c 100644
--- a/tools/diagtool/CMakeLists.txt
+++ b/tools/diagtool/CMakeLists.txt
@@ -18,8 +18,14 @@ target_link_libraries(diagtool
clangFrontend
)
-if(UNIX)
- set(CLANGXX_LINK_OR_COPY create_symlink)
-else()
- set(CLANGXX_LINK_OR_COPY copy)
+if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
+ install(TARGETS diagtool
+ COMPONENT diagtool
+ RUNTIME DESTINATION bin)
+
+ if (NOT CMAKE_CONFIGURATION_TYPES)
+ add_llvm_install_targets(install-diagtool
+ DEPENDS diagtool
+ COMPONENT diagtool)
+ endif()
endif()
diff --git a/tools/diagtool/DiagTool.cpp b/tools/diagtool/DiagTool.cpp
index 7582d51ae4f5..d9086af8e989 100644
--- a/tools/diagtool/DiagTool.cpp
+++ b/tools/diagtool/DiagTool.cpp
@@ -48,7 +48,7 @@ void DiagTools::printCommands(llvm::raw_ostream &out) {
if (len > maxName)
maxName = len;
}
- std::sort(toolNames.begin(), toolNames.end());
+ llvm::sort(toolNames.begin(), toolNames.end());
for (std::vector<llvm::StringRef>::iterator it = toolNames.begin(),
ei = toolNames.end(); it != ei; ++it) {
diff --git a/tools/diagtool/DiagnosticNames.h b/tools/diagtool/DiagnosticNames.h
index 598ae6a0ba65..fba59095948c 100644
--- a/tools/diagtool/DiagnosticNames.h
+++ b/tools/diagtool/DiagnosticNames.h
@@ -30,10 +30,10 @@ namespace diagtool {
}
};
- /// \brief Get every diagnostic in the system, sorted by name.
+ /// Get every diagnostic in the system, sorted by name.
llvm::ArrayRef<DiagnosticRecord> getBuiltinDiagnosticsByName();
- /// \brief Get a diagnostic by its ID.
+ /// Get a diagnostic by its ID.
const DiagnosticRecord &getDiagnosticForID(short DiagID);
@@ -101,7 +101,7 @@ namespace diagtool {
}
};
- /// \brief Get every diagnostic group in the system, sorted by name.
+ /// Get every diagnostic group in the system, sorted by name.
llvm::ArrayRef<GroupRecord> getDiagnosticGroups();
template<>
diff --git a/tools/driver/CMakeLists.txt b/tools/driver/CMakeLists.txt
index 22a498422aef..15b0519e4111 100644
--- a/tools/driver/CMakeLists.txt
+++ b/tools/driver/CMakeLists.txt
@@ -4,6 +4,7 @@ set( LLVM_LINK_COMPONENTS
CodeGen
Core
IPO
+ AggressiveInstCombine
InstCombine
Instrumentation
MC
@@ -32,6 +33,7 @@ add_clang_tool(clang
driver.cpp
cc1_main.cpp
cc1as_main.cpp
+ cc1gen_reproducer_main.cpp
DEPENDS
${tablegen_deps}
@@ -61,10 +63,6 @@ add_dependencies(clang clang-headers)
if(NOT CLANG_LINKS_TO_CREATE)
set(CLANG_LINKS_TO_CREATE clang++ clang-cl clang-cpp)
-
- if (MSVC)
- list(APPEND CLANG_LINKS_TO_CREATE ../msbuild-bin/cl)
- endif()
endif()
foreach(link ${CLANG_LINKS_TO_CREATE})
@@ -96,20 +94,16 @@ if (APPLE)
set(TOOL_INFO_BUILD_VERSION)
endif()
-if(CLANG_ORDER_FILE AND (LD64_EXECUTABLE OR GOLD_EXECUTABLE))
- include(CMakePushCheckState)
-
- function(check_linker_flag flag out_var)
- cmake_push_check_state()
- set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${flag}")
- check_cxx_compiler_flag("" ${out_var})
- cmake_pop_check_state()
- endfunction()
+if(CLANG_ORDER_FILE AND
+ (LLVM_LINKER_IS_LD64 OR LLVM_LINKER_IS_GOLD OR LLVM_LINKER_IS_LLD))
+ include(CheckLinkerFlag)
- if (LD64_EXECUTABLE)
+ if (LLVM_LINKER_IS_LD64)
set(LINKER_ORDER_FILE_OPTION "-Wl,-order_file,${CLANG_ORDER_FILE}")
- elseif (GOLD_EXECUTABLE)
+ elseif (LLVM_LINKER_IS_GOLD)
set(LINKER_ORDER_FILE_OPTION "-Wl,--section-ordering-file,${CLANG_ORDER_FILE}")
+ elseif (LLVM_LINKER_IS_LLD)
+ set(LINKER_ORDER_FILE_OPTION "-Wl,--symbol-ordering-file,${CLANG_ORDER_FILE}")
endif()
# This is a test to ensure the actual order file works with the linker.
diff --git a/tools/driver/cc1_main.cpp b/tools/driver/cc1_main.cpp
index 1a16746d589d..ef5a191bda0a 100644
--- a/tools/driver/cc1_main.cpp
+++ b/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/tools/driver/cc1as_main.cpp b/tools/driver/cc1as_main.cpp
index 9b90562af903..09db014019bf 100644
--- a/tools/driver/cc1as_main.cpp
+++ b/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(*MRI, Opts.Triple, Opts.CPU, 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,18 +432,26 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts,
Out = BOS.get();
}
- MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx);
- MCTargetOptions Options;
- MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*MRI, Opts.Triple,
- Opts.CPU, 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(
@@ -461,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/tools/driver/cc1gen_reproducer_main.cpp b/tools/driver/cc1gen_reproducer_main.cpp
new file mode 100644
index 000000000000..a4c034d8d357
--- /dev/null
+++ b/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/tools/driver/driver.cpp b/tools/driver/driver.cpp
index fa757da9535c..0455ba029c65 100644
--- a/tools/driver/driver.cpp
+++ b/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,
@@ -212,20 +212,21 @@ static void insertTargetAndModeArgs(const ParsedClangName &NameParts,
// Put target and mode arguments at the start of argument list so that
// arguments specified in command line could override them. Avoid putting
// them at index 0, as an option like '-cc1' must remain the first.
- auto InsertionPoint = ArgVector.begin();
- if (InsertionPoint != ArgVector.end())
+ int InsertionPoint = 0;
+ if (ArgVector.size() > 0)
++InsertionPoint;
if (NameParts.DriverMode) {
// Add the mode flag to the arguments.
- ArgVector.insert(InsertionPoint,
+ ArgVector.insert(ArgVector.begin() + InsertionPoint,
GetStableCStr(SavedStrings, NameParts.DriverMode));
}
if (NameParts.TargetIsValid) {
const char *arr[] = {"-target", GetStableCStr(SavedStrings,
NameParts.TargetPrefix)};
- ArgVector.insert(InsertionPoint, std::begin(arr), std::end(arr));
+ ArgVector.insert(ArgVector.begin() + InsertionPoint,
+ std::begin(arr), std::end(arr));
}
}
@@ -309,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]);
@@ -490,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) {
@@ -506,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/tools/libclang/BuildSystem.cpp b/tools/libclang/BuildSystem.cpp
index 99aa5b6f2ff0..79fa69c40bae 100644
--- a/tools/libclang/BuildSystem.cpp
+++ b/tools/libclang/BuildSystem.cpp
@@ -17,6 +17,7 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/CBindingWrapping.h"
#include "llvm/Support/Chrono.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
@@ -78,7 +79,7 @@ clang_VirtualFileOverlay_writeToBuffer(CXVirtualFileOverlay VFO, unsigned,
unwrap(VFO)->write(OS);
StringRef Data = OS.str();
- *out_buffer_ptr = (char*)malloc(Data.size());
+ *out_buffer_ptr = static_cast<char*>(llvm::safe_malloc(Data.size()));
*out_buffer_size = Data.size();
memcpy(*out_buffer_ptr, Data.data(), Data.size());
return CXError_Success;
@@ -140,7 +141,7 @@ clang_ModuleMapDescriptor_writeToBuffer(CXModuleMapDescriptor MMD, unsigned,
OS << "}\n";
StringRef Data = OS.str();
- *out_buffer_ptr = (char*)malloc(Data.size());
+ *out_buffer_ptr = static_cast<char*>(llvm::safe_malloc(Data.size()));
*out_buffer_size = Data.size();
memcpy(*out_buffer_ptr, Data.data(), Data.size());
return CXError_Success;
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index f4d347108c9f..499d9abf9a8e 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -26,6 +26,7 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticCategories.h"
#include "clang/Basic/DiagnosticIDs.h"
+#include "clang/Basic/Stack.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Version.h"
#include "clang/Frontend/ASTUnit.h"
@@ -103,7 +104,7 @@ cxtu::CXTUOwner::~CXTUOwner() {
clang_disposeTranslationUnit(TU);
}
-/// \brief Compare two source ranges to determine their relative position in
+/// Compare two source ranges to determine their relative position in
/// the translation unit.
static RangeComparisonResult RangeCompare(SourceManager &SM,
SourceRange R1,
@@ -119,7 +120,7 @@ static RangeComparisonResult RangeCompare(SourceManager &SM,
return RangeOverlap;
}
-/// \brief Determine if a source location falls within, before, or after a
+/// Determine if a source location falls within, before, or after a
/// a given source range.
static RangeComparisonResult LocationCompare(SourceManager &SM,
SourceLocation L, SourceRange R) {
@@ -134,7 +135,7 @@ static RangeComparisonResult LocationCompare(SourceManager &SM,
return RangeOverlap;
}
-/// \brief Translate a Clang source range into a CIndex source range.
+/// Translate a Clang source range into a CIndex source range.
///
/// Clang internally represents ranges where the end location points to the
/// start of the token at the end. However, for external clients it is more
@@ -146,9 +147,13 @@ CXSourceRange cxloc::translateSourceRange(const SourceManager &SM,
// We want the last character in this location, so we will adjust the
// location accordingly.
SourceLocation EndLoc = R.getEnd();
- if (EndLoc.isValid() && EndLoc.isMacroID() && !SM.isMacroArgExpansion(EndLoc))
- EndLoc = SM.getExpansionRange(EndLoc).second;
- if (R.isTokenRange() && EndLoc.isValid()) {
+ bool IsTokenRange = R.isTokenRange();
+ if (EndLoc.isValid() && EndLoc.isMacroID() && !SM.isMacroArgExpansion(EndLoc)) {
+ CharSourceRange Expansion = SM.getExpansionRange(EndLoc);
+ EndLoc = Expansion.getEnd();
+ IsTokenRange = Expansion.isTokenRange();
+ }
+ if (IsTokenRange && EndLoc.isValid()) {
unsigned Length = Lexer::MeasureTokenLength(SM.getSpellingLoc(EndLoc),
SM, LangOpts);
EndLoc = EndLoc.getLocWithOffset(Length);
@@ -174,7 +179,7 @@ RangeComparisonResult CursorVisitor::CompareRegionOfInterest(SourceRange R) {
return RangeCompare(AU->getSourceManager(), R, RegionOfInterest);
}
-/// \brief Visit the given cursor and, if requested by the visitor,
+/// Visit the given cursor and, if requested by the visitor,
/// its children.
///
/// \param Cursor the cursor to visit.
@@ -478,7 +483,7 @@ bool CursorVisitor::visitPreprocessedEntities(InputIterator First,
return false;
}
-/// \brief Visit the children of the given cursor.
+/// Visit the children of the given cursor.
///
/// \returns true if the visitation should be aborted, false if it
/// should continue.
@@ -785,7 +790,17 @@ bool CursorVisitor::VisitDeclaratorDecl(DeclaratorDecl *DD) {
return false;
}
-/// \brief Compare two base or member initializers based on their source order.
+static bool HasTrailingReturnType(FunctionDecl *ND) {
+ const QualType Ty = ND->getType();
+ if (const FunctionType *AFT = Ty->getAs<FunctionType>()) {
+ if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(AFT))
+ return FT->hasTrailingReturn();
+ }
+
+ return false;
+}
+
+/// Compare two base or member initializers based on their source order.
static int CompareCXXCtorInitializers(CXXCtorInitializer *const *X,
CXXCtorInitializer *const *Y) {
return (*X)->getSourceOrder() - (*Y)->getSourceOrder();
@@ -804,14 +819,16 @@ bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) {
// written. This requires a bit of work.
TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens();
FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>();
+ const bool HasTrailingRT = HasTrailingReturnType(ND);
// If we have a function declared directly (without the use of a typedef),
// visit just the return type. Otherwise, just visit the function's type
// now.
- if ((FTL && !isa<CXXConversionDecl>(ND) && Visit(FTL.getReturnLoc())) ||
+ if ((FTL && !isa<CXXConversionDecl>(ND) && !HasTrailingRT &&
+ Visit(FTL.getReturnLoc())) ||
(!FTL && Visit(TL)))
return true;
-
+
// Visit the nested-name-specifier, if present.
if (NestedNameSpecifierLoc QualifierLoc = ND->getQualifierLoc())
if (VisitNestedNameSpecifierLoc(QualifierLoc))
@@ -827,7 +844,11 @@ bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) {
// Visit the function parameters, if we have a function type.
if (FTL && VisitFunctionTypeLoc(FTL, true))
return true;
-
+
+ // Visit the function's trailing return type.
+ if (FTL && HasTrailingRT && Visit(FTL.getReturnLoc()))
+ return true;
+
// FIXME: Attributes?
}
@@ -1023,8 +1044,8 @@ bool CursorVisitor::VisitObjCContainerDecl(ObjCContainerDecl *D) {
}
// Now sort the Decls so that they appear in lexical order.
- std::sort(DeclsInContainer.begin(), DeclsInContainer.end(),
- [&SM](Decl *A, Decl *B) {
+ llvm::sort(DeclsInContainer.begin(), DeclsInContainer.end(),
+ [&SM](Decl *A, Decl *B) {
SourceLocation L_A = A->getLocStart();
SourceLocation L_B = B->getLocStart();
return L_A != L_B ?
@@ -1751,6 +1772,7 @@ DEFAULT_TYPELOC_IMPL(IncompleteArray, ArrayType)
DEFAULT_TYPELOC_IMPL(VariableArray, ArrayType)
DEFAULT_TYPELOC_IMPL(DependentSizedArray, ArrayType)
DEFAULT_TYPELOC_IMPL(DependentAddressSpace, Type)
+DEFAULT_TYPELOC_IMPL(DependentVector, Type)
DEFAULT_TYPELOC_IMPL(DependentSizedExtVector, Type)
DEFAULT_TYPELOC_IMPL(Vector, Type)
DEFAULT_TYPELOC_IMPL(ExtVector, VectorType)
@@ -1780,7 +1802,7 @@ bool CursorVisitor::VisitCXXRecordDecl(CXXRecordDecl *D) {
bool CursorVisitor::VisitAttributes(Decl *D) {
for (const auto *I : D->attrs())
- if (Visit(MakeCXCursor(I, D, TU)))
+ if (!I->isImplicit() && Visit(MakeCXCursor(I, D, TU)))
return true;
return false;
@@ -2099,7 +2121,7 @@ void EnqueueVisitor::EnqueueChildren(const Stmt *S) {
namespace {
class OMPClauseEnqueue : public ConstOMPClauseVisitor<OMPClauseEnqueue> {
EnqueueVisitor *Visitor;
- /// \brief Process clauses with list of variables.
+ /// Process clauses with list of variables.
template <typename T>
void VisitOMPClauseList(T *Node);
public:
@@ -2577,7 +2599,7 @@ void EnqueueVisitor::VisitMemberExpr(const MemberExpr *M) {
return;
// Ignore base anonymous struct/union fields, otherwise they will shadow the
- // real field that that we are interested in.
+ // real field that we are interested in.
if (auto *SubME = dyn_cast<MemberExpr>(M->getBase())) {
if (auto *FD = dyn_cast_or_null<FieldDecl>(SubME->getMemberDecl())) {
if (FD->isAnonymousStructOrUnion()) {
@@ -3360,9 +3382,15 @@ clang_parseTranslationUnit_Impl(CXIndex CIdx, const char *source_filename,
= options & CXTranslationUnit_CacheCompletionResults;
bool IncludeBriefCommentsInCodeCompletion
= options & CXTranslationUnit_IncludeBriefCommentsInCodeCompletion;
- bool SkipFunctionBodies = options & CXTranslationUnit_SkipFunctionBodies;
bool SingleFileParse = options & CXTranslationUnit_SingleFileParse;
bool ForSerialization = options & CXTranslationUnit_ForSerialization;
+ SkipFunctionBodiesScope SkipFunctionBodies = SkipFunctionBodiesScope::None;
+ if (options & CXTranslationUnit_SkipFunctionBodies) {
+ SkipFunctionBodies =
+ (options & CXTranslationUnit_LimitSkipFunctionBodiesToPreamble)
+ ? SkipFunctionBodiesScope::Preamble
+ : SkipFunctionBodiesScope::PreambleAndMainFile;
+ }
// Configure the diagnostics.
IntrusiveRefCntPtr<DiagnosticsEngine>
@@ -4233,6 +4261,14 @@ int clang_File_isEqual(CXFile file1, CXFile file2) {
return FEnt1->getUniqueID() == FEnt2->getUniqueID();
}
+CXString clang_File_tryGetRealPathName(CXFile SFile) {
+ if (!SFile)
+ return cxstring::createNull();
+
+ FileEntry *FEnt = static_cast<FileEntry *>(SFile);
+ return cxstring::createRef(FEnt->tryGetRealPathName());
+}
+
//===----------------------------------------------------------------------===//
// CXCursor Operations.
//===----------------------------------------------------------------------===//
@@ -4690,6 +4726,195 @@ CXStringSet *clang_Cursor_getObjCManglings(CXCursor C) {
return cxstring::createSet(Manglings);
}
+CXPrintingPolicy clang_getCursorPrintingPolicy(CXCursor C) {
+ if (clang_Cursor_isNull(C))
+ return 0;
+ return new PrintingPolicy(getCursorContext(C).getPrintingPolicy());
+}
+
+void clang_PrintingPolicy_dispose(CXPrintingPolicy Policy) {
+ if (Policy)
+ delete static_cast<PrintingPolicy *>(Policy);
+}
+
+unsigned
+clang_PrintingPolicy_getProperty(CXPrintingPolicy Policy,
+ enum CXPrintingPolicyProperty Property) {
+ if (!Policy)
+ return 0;
+
+ PrintingPolicy *P = static_cast<PrintingPolicy *>(Policy);
+ switch (Property) {
+ case CXPrintingPolicy_Indentation:
+ return P->Indentation;
+ case CXPrintingPolicy_SuppressSpecifiers:
+ return P->SuppressSpecifiers;
+ case CXPrintingPolicy_SuppressTagKeyword:
+ return P->SuppressTagKeyword;
+ case CXPrintingPolicy_IncludeTagDefinition:
+ return P->IncludeTagDefinition;
+ case CXPrintingPolicy_SuppressScope:
+ return P->SuppressScope;
+ case CXPrintingPolicy_SuppressUnwrittenScope:
+ return P->SuppressUnwrittenScope;
+ case CXPrintingPolicy_SuppressInitializers:
+ return P->SuppressInitializers;
+ case CXPrintingPolicy_ConstantArraySizeAsWritten:
+ return P->ConstantArraySizeAsWritten;
+ case CXPrintingPolicy_AnonymousTagLocations:
+ return P->AnonymousTagLocations;
+ case CXPrintingPolicy_SuppressStrongLifetime:
+ return P->SuppressStrongLifetime;
+ case CXPrintingPolicy_SuppressLifetimeQualifiers:
+ return P->SuppressLifetimeQualifiers;
+ case CXPrintingPolicy_SuppressTemplateArgsInCXXConstructors:
+ return P->SuppressTemplateArgsInCXXConstructors;
+ case CXPrintingPolicy_Bool:
+ return P->Bool;
+ case CXPrintingPolicy_Restrict:
+ return P->Restrict;
+ case CXPrintingPolicy_Alignof:
+ return P->Alignof;
+ case CXPrintingPolicy_UnderscoreAlignof:
+ return P->UnderscoreAlignof;
+ case CXPrintingPolicy_UseVoidForZeroParams:
+ return P->UseVoidForZeroParams;
+ case CXPrintingPolicy_TerseOutput:
+ return P->TerseOutput;
+ case CXPrintingPolicy_PolishForDeclaration:
+ return P->PolishForDeclaration;
+ case CXPrintingPolicy_Half:
+ return P->Half;
+ case CXPrintingPolicy_MSWChar:
+ return P->MSWChar;
+ case CXPrintingPolicy_IncludeNewlines:
+ return P->IncludeNewlines;
+ case CXPrintingPolicy_MSVCFormatting:
+ return P->MSVCFormatting;
+ case CXPrintingPolicy_ConstantsAsWritten:
+ return P->ConstantsAsWritten;
+ case CXPrintingPolicy_SuppressImplicitBase:
+ return P->SuppressImplicitBase;
+ case CXPrintingPolicy_FullyQualifiedName:
+ return P->FullyQualifiedName;
+ }
+
+ assert(false && "Invalid CXPrintingPolicyProperty");
+ return 0;
+}
+
+void clang_PrintingPolicy_setProperty(CXPrintingPolicy Policy,
+ enum CXPrintingPolicyProperty Property,
+ unsigned Value) {
+ if (!Policy)
+ return;
+
+ PrintingPolicy *P = static_cast<PrintingPolicy *>(Policy);
+ switch (Property) {
+ case CXPrintingPolicy_Indentation:
+ P->Indentation = Value;
+ return;
+ case CXPrintingPolicy_SuppressSpecifiers:
+ P->SuppressSpecifiers = Value;
+ return;
+ case CXPrintingPolicy_SuppressTagKeyword:
+ P->SuppressTagKeyword = Value;
+ return;
+ case CXPrintingPolicy_IncludeTagDefinition:
+ P->IncludeTagDefinition = Value;
+ return;
+ case CXPrintingPolicy_SuppressScope:
+ P->SuppressScope = Value;
+ return;
+ case CXPrintingPolicy_SuppressUnwrittenScope:
+ P->SuppressUnwrittenScope = Value;
+ return;
+ case CXPrintingPolicy_SuppressInitializers:
+ P->SuppressInitializers = Value;
+ return;
+ case CXPrintingPolicy_ConstantArraySizeAsWritten:
+ P->ConstantArraySizeAsWritten = Value;
+ return;
+ case CXPrintingPolicy_AnonymousTagLocations:
+ P->AnonymousTagLocations = Value;
+ return;
+ case CXPrintingPolicy_SuppressStrongLifetime:
+ P->SuppressStrongLifetime = Value;
+ return;
+ case CXPrintingPolicy_SuppressLifetimeQualifiers:
+ P->SuppressLifetimeQualifiers = Value;
+ return;
+ case CXPrintingPolicy_SuppressTemplateArgsInCXXConstructors:
+ P->SuppressTemplateArgsInCXXConstructors = Value;
+ return;
+ case CXPrintingPolicy_Bool:
+ P->Bool = Value;
+ return;
+ case CXPrintingPolicy_Restrict:
+ P->Restrict = Value;
+ return;
+ case CXPrintingPolicy_Alignof:
+ P->Alignof = Value;
+ return;
+ case CXPrintingPolicy_UnderscoreAlignof:
+ P->UnderscoreAlignof = Value;
+ return;
+ case CXPrintingPolicy_UseVoidForZeroParams:
+ P->UseVoidForZeroParams = Value;
+ return;
+ case CXPrintingPolicy_TerseOutput:
+ P->TerseOutput = Value;
+ return;
+ case CXPrintingPolicy_PolishForDeclaration:
+ P->PolishForDeclaration = Value;
+ return;
+ case CXPrintingPolicy_Half:
+ P->Half = Value;
+ return;
+ case CXPrintingPolicy_MSWChar:
+ P->MSWChar = Value;
+ return;
+ case CXPrintingPolicy_IncludeNewlines:
+ P->IncludeNewlines = Value;
+ return;
+ case CXPrintingPolicy_MSVCFormatting:
+ P->MSVCFormatting = Value;
+ return;
+ case CXPrintingPolicy_ConstantsAsWritten:
+ P->ConstantsAsWritten = Value;
+ return;
+ case CXPrintingPolicy_SuppressImplicitBase:
+ P->SuppressImplicitBase = Value;
+ return;
+ case CXPrintingPolicy_FullyQualifiedName:
+ P->FullyQualifiedName = Value;
+ return;
+ }
+
+ assert(false && "Invalid CXPrintingPolicyProperty");
+}
+
+CXString clang_getCursorPrettyPrinted(CXCursor C, CXPrintingPolicy cxPolicy) {
+ if (clang_Cursor_isNull(C))
+ return cxstring::createEmpty();
+
+ if (clang_isDeclaration(C.kind)) {
+ const Decl *D = getCursorDecl(C);
+ if (!D)
+ return cxstring::createEmpty();
+
+ SmallString<128> Str;
+ llvm::raw_svector_ostream OS(Str);
+ PrintingPolicy *UserPolicy = static_cast<PrintingPolicy *>(cxPolicy);
+ D->print(OS, UserPolicy ? *UserPolicy
+ : getCursorContext(C).getPrintingPolicy());
+
+ return cxstring::createDup(OS.str());
+ }
+
+ return cxstring::createEmpty();
+}
+
CXString clang_getCursorDisplayName(CXCursor C) {
if (!clang_isDeclaration(C.kind))
return clang_getCursorSpelling(C);
@@ -4838,6 +5063,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
return cxstring::createRef("VariableRef");
case CXCursor_IntegerLiteral:
return cxstring::createRef("IntegerLiteral");
+ case CXCursor_FixedPointLiteral:
+ return cxstring::createRef("FixedPointLiteral");
case CXCursor_FloatingLiteral:
return cxstring::createRef("FloatingLiteral");
case CXCursor_ImaginaryLiteral:
@@ -5421,6 +5648,15 @@ unsigned clang_isDeclaration(enum CXCursorKind K) {
(K >= CXCursor_FirstExtraDecl && K <= CXCursor_LastExtraDecl);
}
+unsigned clang_isInvalidDeclaration(CXCursor C) {
+ if (clang_isDeclaration(C.kind)) {
+ if (const Decl *D = getCursorDecl(C))
+ return D->isInvalidDecl();
+ }
+
+ return 0;
+}
+
unsigned clang_isReference(enum CXCursorKind K) {
return K >= CXCursor_FirstRef && K <= CXCursor_LastRef;
}
@@ -5727,7 +5963,7 @@ static SourceRange getRawCursorExtent(CXCursor C) {
return SourceRange();
}
-/// \brief Retrieves the "raw" cursor extent, which is then extended to include
+/// Retrieves the "raw" cursor extent, which is then extended to include
/// the decl-specifier-seq for declarations.
static SourceRange getFullCursorExtent(CXCursor C, SourceManager &SrcMgr) {
if (clang_isDeclaration(C.kind)) {
@@ -6420,6 +6656,42 @@ static void getTokens(ASTUnit *CXXUnit, SourceRange Range,
} while (Lex.getBufferLocation() < EffectiveBufferEnd);
}
+CXToken *clang_getToken(CXTranslationUnit TU, CXSourceLocation Location) {
+ LOG_FUNC_SECTION {
+ *Log << TU << ' ' << Location;
+ }
+
+ if (isNotUsableTU(TU)) {
+ LOG_BAD_TU(TU);
+ return NULL;
+ }
+
+ ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
+ if (!CXXUnit)
+ return NULL;
+
+ SourceLocation Begin = cxloc::translateSourceLocation(Location);
+ if (Begin.isInvalid())
+ return NULL;
+ SourceManager &SM = CXXUnit->getSourceManager();
+ std::pair<FileID, unsigned> DecomposedEnd = SM.getDecomposedLoc(Begin);
+ DecomposedEnd.second += Lexer::MeasureTokenLength(Begin, SM, CXXUnit->getLangOpts());
+
+ SourceLocation End = SM.getComposedLoc(DecomposedEnd.first, DecomposedEnd.second);
+
+ SmallVector<CXToken, 32> CXTokens;
+ getTokens(CXXUnit, SourceRange(Begin, End), CXTokens);
+
+ if (CXTokens.empty())
+ return NULL;
+
+ CXTokens.resize(1);
+ CXToken *Token = static_cast<CXToken *>(llvm::safe_malloc(sizeof(CXToken)));
+
+ memmove(Token, CXTokens.data(), sizeof(CXToken));
+ return Token;
+}
+
void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range,
CXToken **Tokens, unsigned *NumTokens) {
LOG_FUNC_SECTION {
@@ -6452,7 +6724,8 @@ void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range,
if (CXTokens.empty())
return;
- *Tokens = (CXToken *)malloc(sizeof(CXToken) * CXTokens.size());
+ *Tokens = static_cast<CXToken *>(
+ llvm::safe_malloc(sizeof(CXToken) * CXTokens.size()));
memmove(*Tokens, CXTokens.data(), sizeof(CXToken) * CXTokens.size());
*NumTokens = CXTokens.size();
}
@@ -6536,7 +6809,7 @@ public:
bool postVisitChildren(CXCursor cursor);
void AnnotateTokens();
- /// \brief Determine whether the annotator saw any cursors that have
+ /// Determine whether the annotator saw any cursors that have
/// context-sensitive keywords.
bool hasContextSensitiveKeywords() const {
return HasContextSensitiveKeywords;
@@ -6561,7 +6834,7 @@ static inline void updateCursorAnnotation(CXCursor &Cursor,
Cursor = updateC;
}
-/// \brief It annotates and advances tokens with a cursor until the comparison
+/// It annotates and advances tokens with a cursor until the comparison
//// between the cursor location and the source range is the same as
/// \arg compResult.
///
@@ -6586,7 +6859,7 @@ void AnnotateTokensWorker::annotateAndAdvanceTokens(CXCursor updateC,
}
}
-/// \brief Special annotation handling for macro argument tokens.
+/// Special annotation handling for macro argument tokens.
/// \returns true if it advanced beyond all macro tokens, false otherwise.
bool AnnotateTokensWorker::annotateAndAdvanceFunctionMacroTokens(
CXCursor updateC,
@@ -6830,7 +7103,7 @@ static bool AnnotateTokensPostChildrenVisitor(CXCursor cursor,
namespace {
-/// \brief Uses the macro expansions in the preprocessing record to find
+/// Uses the macro expansions in the preprocessing record to find
/// and mark tokens that are macro arguments. This info is used by the
/// AnnotateTokensWorker.
class MarkMacroArgTokensVisitor {
@@ -6905,7 +7178,7 @@ MarkMacroArgTokensVisitorDelegate(CXCursor cursor, CXCursor parent,
parent);
}
-/// \brief Used by \c annotatePreprocessorTokens.
+/// Used by \c annotatePreprocessorTokens.
/// \returns true if lexing was finished, false otherwise.
static bool lexNext(Lexer &Lex, Token &Tok,
unsigned &NextIdx, unsigned NumTokens) {
@@ -7358,10 +7631,10 @@ static void getCursorPlatformAvailabilityForDecl(
if (AvailabilityAttrs.empty())
return;
- std::sort(AvailabilityAttrs.begin(), AvailabilityAttrs.end(),
- [](AvailabilityAttr *LHS, AvailabilityAttr *RHS) {
- return LHS->getPlatform()->getName() <
- RHS->getPlatform()->getName();
+ llvm::sort(AvailabilityAttrs.begin(), AvailabilityAttrs.end(),
+ [](AvailabilityAttr *LHS, AvailabilityAttr *RHS) {
+ return LHS->getPlatform()->getName() <
+ RHS->getPlatform()->getName();
});
ASTContext &Ctx = D->getASTContext();
auto It = std::unique(
@@ -7479,8 +7752,8 @@ CXTLSKind clang_getCursorTLSKind(CXCursor cursor) {
return CXTLS_None;
}
- /// \brief If the given cursor is the "templated" declaration
- /// descibing a class or function template, return the class or
+ /// If the given cursor is the "templated" declaration
+ /// describing a class or function template, return the class or
/// function template.
static const Decl *maybeGetTemplateCursor(const Decl *D) {
if (!D)
@@ -8135,6 +8408,7 @@ CXSourceRangeList *clang_getSkippedRanges(CXTranslationUnit TU, CXFile file) {
SourceManager &sm = Ctx.getSourceManager();
FileEntry *fileEntry = static_cast<FileEntry *>(file);
FileID wantedFileID = sm.translateFile(fileEntry);
+ bool isMainFile = wantedFileID == sm.getMainFileID();
const std::vector<SourceRange> &SkippedRanges = ppRec->getSkippedRanges();
std::vector<SourceRange> wantedRanges;
@@ -8142,6 +8416,8 @@ CXSourceRangeList *clang_getSkippedRanges(CXTranslationUnit TU, CXFile file) {
i != ei; ++i) {
if (sm.getFileID(i->getBegin()) == wantedFileID || sm.getFileID(i->getEnd()) == wantedFileID)
wantedRanges.push_back(*i);
+ else if (isMainFile && (astUnit->isInPreambleFileID(i->getBegin()) || astUnit->isInPreambleFileID(i->getEnd())))
+ wantedRanges.push_back(*i);
}
skipped->count = wantedRanges.size();
@@ -8200,8 +8476,8 @@ void clang::PrintLibclangResourceUsage(CXTranslationUnit TU) {
// Misc. utility functions.
//===----------------------------------------------------------------------===//
-/// Default to using an 8 MB stack size on "safety" threads.
-static unsigned SafetyStackThreadSize = 8 << 20;
+/// Default to using our desired 8 MB stack size on "safety" threads.
+static unsigned SafetyStackThreadSize = DesiredStackSize;
namespace clang {
@@ -8246,7 +8522,7 @@ void cxindex::printDiagsToStderr(ASTUnit *Unit) {
fprintf(stderr, "%s\n", clang_getCString(Msg));
clang_disposeString(Msg);
}
-#ifdef LLVM_ON_WIN32
+#ifdef _WIN32
// On Windows, force a flush, since there may be multiple copies of
// stderr and stdout in the file system, all with different buffers
// but writing to the same device.
diff --git a/tools/libclang/CIndexCodeCompletion.cpp b/tools/libclang/CIndexCodeCompletion.cpp
index d4af0870c0b6..f49f9763c362 100644
--- a/tools/libclang/CIndexCodeCompletion.cpp
+++ b/tools/libclang/CIndexCodeCompletion.cpp
@@ -16,6 +16,7 @@
#include "CIndexDiagnostic.h"
#include "CLog.h"
#include "CXCursor.h"
+#include "CXSourceLocation.h"
#include "CXString.h"
#include "CXTranslationUnit.h"
#include "clang/AST/Decl.h"
@@ -240,7 +241,7 @@ clang_getCompletionBriefComment(CXCompletionString completion_string) {
namespace {
-/// \brief The CXCodeCompleteResults structure we allocate internally;
+/// The CXCodeCompleteResults structure we allocate internally;
/// the client only sees the initial CXCodeCompleteResults structure.
///
/// Normally, clients of CXString shouldn't care whether or not a CXString is
@@ -251,62 +252,105 @@ struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {
AllocatedCXCodeCompleteResults(IntrusiveRefCntPtr<FileManager> FileMgr);
~AllocatedCXCodeCompleteResults();
- /// \brief Diagnostics produced while performing code completion.
+ /// Diagnostics produced while performing code completion.
SmallVector<StoredDiagnostic, 8> Diagnostics;
- /// \brief Allocated API-exposed wrappters for Diagnostics.
+ /// Allocated API-exposed wrappters for Diagnostics.
SmallVector<CXStoredDiagnostic *, 8> DiagnosticsWrappers;
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
- /// \brief Diag object
+ /// Diag object
IntrusiveRefCntPtr<DiagnosticsEngine> Diag;
- /// \brief Language options used to adjust source locations.
+ /// Language options used to adjust source locations.
LangOptions LangOpts;
- /// \brief File manager, used for diagnostics.
+ /// File manager, used for diagnostics.
IntrusiveRefCntPtr<FileManager> FileMgr;
- /// \brief Source manager, used for diagnostics.
+ /// Source manager, used for diagnostics.
IntrusiveRefCntPtr<SourceManager> SourceMgr;
- /// \brief Temporary buffers that will be deleted once we have finished with
+ /// Temporary buffers that will be deleted once we have finished with
/// the code-completion results.
SmallVector<const llvm::MemoryBuffer *, 1> TemporaryBuffers;
- /// \brief Allocator used to store globally cached code-completion results.
+ /// Allocator used to store globally cached code-completion results.
std::shared_ptr<clang::GlobalCodeCompletionAllocator>
CachedCompletionAllocator;
- /// \brief Allocator used to store code completion results.
+ /// Allocator used to store code completion results.
std::shared_ptr<clang::GlobalCodeCompletionAllocator> CodeCompletionAllocator;
- /// \brief Context under which completion occurred.
+ /// Context under which completion occurred.
enum clang::CodeCompletionContext::Kind ContextKind;
- /// \brief A bitfield representing the acceptable completions for the
+ /// A bitfield representing the acceptable completions for the
/// current context.
unsigned long long Contexts;
- /// \brief The kind of the container for the current context for completions.
+ /// The kind of the container for the current context for completions.
enum CXCursorKind ContainerKind;
- /// \brief The USR of the container for the current context for completions.
+ /// The USR of the container for the current context for completions.
std::string ContainerUSR;
- /// \brief a boolean value indicating whether there is complete information
+ /// a boolean value indicating whether there is complete information
/// about the container
unsigned ContainerIsIncomplete;
- /// \brief A string containing the Objective-C selector entered thus far for a
+ /// A string containing the Objective-C selector entered thus far for a
/// message send.
std::string Selector;
+
+ /// Vector of fix-its for each completion result that *must* be applied
+ /// before that result for the corresponding completion item.
+ std::vector<std::vector<FixItHint>> FixItsVector;
};
} // end anonymous namespace
-/// \brief Tracks the number of code-completion result objects that are
+unsigned clang_getCompletionNumFixIts(CXCodeCompleteResults *results,
+ unsigned completion_index) {
+ AllocatedCXCodeCompleteResults *allocated_results = (AllocatedCXCodeCompleteResults *)results;
+
+ if (!allocated_results || allocated_results->FixItsVector.size() <= completion_index)
+ return 0;
+
+ return static_cast<unsigned>(allocated_results->FixItsVector[completion_index].size());
+}
+
+CXString clang_getCompletionFixIt(CXCodeCompleteResults *results,
+ unsigned completion_index,
+ unsigned fixit_index,
+ CXSourceRange *replacement_range) {
+ AllocatedCXCodeCompleteResults *allocated_results = (AllocatedCXCodeCompleteResults *)results;
+
+ if (!allocated_results || allocated_results->FixItsVector.size() <= completion_index) {
+ if (replacement_range)
+ *replacement_range = clang_getNullRange();
+ return cxstring::createNull();
+ }
+
+ ArrayRef<FixItHint> FixIts = allocated_results->FixItsVector[completion_index];
+ if (FixIts.size() <= fixit_index) {
+ if (replacement_range)
+ *replacement_range = clang_getNullRange();
+ return cxstring::createNull();
+ }
+
+ const FixItHint &FixIt = FixIts[fixit_index];
+ if (replacement_range) {
+ *replacement_range = cxloc::translateSourceRange(
+ *allocated_results->SourceMgr, allocated_results->LangOpts,
+ FixIt.RemoveRange);
+ }
+
+ return cxstring::createRef(FixIt.CodeToInsert.c_str());
+}
+
+/// Tracks the number of code-completion result objects that are
/// currently active.
///
/// Used for debugging purposes only.
@@ -531,8 +575,10 @@ namespace {
CodeCompletionResult *Results,
unsigned NumResults) override {
StoredResults.reserve(StoredResults.size() + NumResults);
+ if (includeFixIts())
+ AllocatedResults.FixItsVector.reserve(NumResults);
for (unsigned I = 0; I != NumResults; ++I) {
- CodeCompletionString *StoredCompletion
+ CodeCompletionString *StoredCompletion
= Results[I].CreateCodeCompletionString(S, Context, getAllocator(),
getCodeCompletionTUInfo(),
includeBriefComments());
@@ -541,8 +587,10 @@ namespace {
R.CursorKind = Results[I].CursorKind;
R.CompletionString = StoredCompletion;
StoredResults.push_back(R);
+ if (includeFixIts())
+ AllocatedResults.FixItsVector.emplace_back(std::move(Results[I].FixIts));
}
-
+
enum CodeCompletionContext::Kind contextKind = Context.getKind();
AllocatedResults.ContextKind = contextKind;
@@ -643,13 +691,14 @@ clang_codeCompleteAt_Impl(CXTranslationUnit TU, const char *complete_filename,
ArrayRef<CXUnsavedFile> unsaved_files,
unsigned options) {
bool IncludeBriefComments = options & CXCodeComplete_IncludeBriefComments;
+ bool SkipPreamble = options & CXCodeComplete_SkipPreamble;
+ bool IncludeFixIts = options & CXCodeComplete_IncludeCompletionsWithFixIts;
#ifdef UDP_CODE_COMPLETION_LOGGER
#ifdef UDP_CODE_COMPLETION_LOGGER_PORT
const llvm::TimeRecord &StartTime = llvm::TimeRecord::getCurrentTime();
#endif
#endif
-
bool EnableLogging = getenv("LIBCLANG_CODE_COMPLETION_LOGGING") != nullptr;
if (cxtu::isNotUsableTU(TU)) {
@@ -689,6 +738,8 @@ clang_codeCompleteAt_Impl(CXTranslationUnit TU, const char *complete_filename,
// Create a code-completion consumer to capture the results.
CodeCompleteOptions Opts;
Opts.IncludeBriefComments = IncludeBriefComments;
+ Opts.LoadExternal = !SkipPreamble;
+ Opts.IncludeFixIts = IncludeFixIts;
CaptureCompletionResults Capture(Opts, *Results, &TU);
// Perform completion.
@@ -911,7 +962,7 @@ CXString clang_codeCompleteGetObjCSelector(CXCodeCompleteResults *ResultsIn) {
return cxstring::createDup(Results->Selector);
}
-/// \brief Simple utility function that appends a \p New string to the given
+/// Simple utility function that appends a \p New string to the given
/// \p Old string, using the \p Buffer for storage.
///
/// \param Old The string to which we are appending. This parameter will be
@@ -935,7 +986,7 @@ static void AppendToString(StringRef &Old, StringRef New,
Old = Buffer.str();
}
-/// \brief Get the typed-text blocks from the given code-completion string
+/// Get the typed-text blocks from the given code-completion string
/// and return them as a single string.
///
/// \param String The code-completion string whose typed-text blocks will be
@@ -962,7 +1013,7 @@ namespace {
= (CodeCompletionString *)XR.CompletionString;
CodeCompletionString *Y
= (CodeCompletionString *)YR.CompletionString;
-
+
SmallString<256> XBuffer;
StringRef XText = GetTypedName(X, XBuffer);
SmallString<256> YBuffer;
diff --git a/tools/libclang/CIndexDiagnostic.h b/tools/libclang/CIndexDiagnostic.h
index 9f406987ebf1..e865df0894a6 100644
--- a/tools/libclang/CIndexDiagnostic.h
+++ b/tools/libclang/CIndexDiagnostic.h
@@ -58,34 +58,34 @@ public:
virtual ~CXDiagnosticImpl();
- /// \brief Return the severity of the diagnostic.
+ /// Return the severity of the diagnostic.
virtual CXDiagnosticSeverity getSeverity() const = 0;
- /// \brief Return the location of the diagnostic.
+ /// Return the location of the diagnostic.
virtual CXSourceLocation getLocation() const = 0;
- /// \brief Return the spelling of the diagnostic.
+ /// Return the spelling of the diagnostic.
virtual CXString getSpelling() const = 0;
- /// \brief Return the text for the diagnostic option.
+ /// Return the text for the diagnostic option.
virtual CXString getDiagnosticOption(CXString *Disable) const = 0;
- /// \brief Return the category of the diagnostic.
+ /// Return the category of the diagnostic.
virtual unsigned getCategory() const = 0;
- /// \brief Return the category string of the diagnostic.
+ /// Return the category string of the diagnostic.
virtual CXString getCategoryText() const = 0;
- /// \brief Return the number of source ranges for the diagnostic.
+ /// Return the number of source ranges for the diagnostic.
virtual unsigned getNumRanges() const = 0;
- /// \brief Return the source ranges for the diagnostic.
+ /// Return the source ranges for the diagnostic.
virtual CXSourceRange getRange(unsigned Range) const = 0;
- /// \brief Return the number of FixIts.
+ /// Return the number of FixIts.
virtual unsigned getNumFixIts() const = 0;
- /// \brief Return the FixIt information (source range and inserted text).
+ /// Return the FixIt information (source range and inserted text).
virtual CXString getFixIt(unsigned FixIt,
CXSourceRange *ReplacementRange) const = 0;
@@ -107,7 +107,7 @@ private:
Kind K;
};
-/// \brief The storage behind a CXDiagnostic
+/// The storage behind a CXDiagnostic
struct CXStoredDiagnostic : public CXDiagnosticImpl {
const StoredDiagnostic &Diag;
const LangOptions &LangOpts;
@@ -119,34 +119,34 @@ struct CXStoredDiagnostic : public CXDiagnosticImpl {
~CXStoredDiagnostic() override {}
- /// \brief Return the severity of the diagnostic.
+ /// Return the severity of the diagnostic.
CXDiagnosticSeverity getSeverity() const override;
- /// \brief Return the location of the diagnostic.
+ /// Return the location of the diagnostic.
CXSourceLocation getLocation() const override;
- /// \brief Return the spelling of the diagnostic.
+ /// Return the spelling of the diagnostic.
CXString getSpelling() const override;
- /// \brief Return the text for the diagnostic option.
+ /// Return the text for the diagnostic option.
CXString getDiagnosticOption(CXString *Disable) const override;
- /// \brief Return the category of the diagnostic.
+ /// Return the category of the diagnostic.
unsigned getCategory() const override;
- /// \brief Return the category string of the diagnostic.
+ /// Return the category string of the diagnostic.
CXString getCategoryText() const override;
- /// \brief Return the number of source ranges for the diagnostic.
+ /// Return the number of source ranges for the diagnostic.
unsigned getNumRanges() const override;
- /// \brief Return the source ranges for the diagnostic.
+ /// Return the source ranges for the diagnostic.
CXSourceRange getRange(unsigned Range) const override;
- /// \brief Return the number of FixIts.
+ /// Return the number of FixIts.
unsigned getNumFixIts() const override;
- /// \brief Return the FixIt information (source range and inserted text).
+ /// Return the FixIt information (source range and inserted text).
CXString getFixIt(unsigned FixIt,
CXSourceRange *ReplacementRange) const override;
diff --git a/tools/libclang/CIndexHigh.cpp b/tools/libclang/CIndexHigh.cpp
index d4666c2288c9..a9cd2cac42ec 100644
--- a/tools/libclang/CIndexHigh.cpp
+++ b/tools/libclang/CIndexHigh.cpp
@@ -65,7 +65,7 @@ struct FindFileIdRefVisitData {
return cxtu::getASTUnit(TU)->getASTContext();
}
- /// \brief We are looking to find all semantically relevant identifiers,
+ /// We are looking to find all semantically relevant identifiers,
/// so the definition of "canonical" here is different than in the AST, e.g.
///
/// \code
@@ -129,7 +129,7 @@ private:
} // end anonymous namespace.
-/// \brief For a macro \arg Loc, returns the file spelling location and sets
+/// For a macro \arg Loc, returns the file spelling location and sets
/// to \arg isMacroArg whether the spelling resides inside a macro definition or
/// a macro argument.
static SourceLocation getFileSpellingLoc(SourceManager &SM,
diff --git a/tools/libclang/CIndexer.cpp b/tools/libclang/CIndexer.cpp
index 62ea88172069..3c6e1530f198 100644
--- a/tools/libclang/CIndexer.cpp
+++ b/tools/libclang/CIndexer.cpp
@@ -17,20 +17,20 @@
#include "clang/Basic/Version.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/Config/llvm-config.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/MutexGuard.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
+#include "llvm/Support/YAMLParser.h"
#include <cstdio>
#ifdef __CYGWIN__
#include <cygwin/version.h>
#include <sys/cygwin.h>
-#define LLVM_ON_WIN32 1
+#define _WIN32 1
#endif
-#ifdef LLVM_ON_WIN32
+#ifdef _WIN32
#include <windows.h>
#else
#include <dlfcn.h>
@@ -46,7 +46,7 @@ const std::string &CIndexer::getClangResourcesPath() {
SmallString<128> LibClangPath;
// Find the location where this library lives (libclang.dylib).
-#ifdef LLVM_ON_WIN32
+#ifdef _WIN32
MEMORY_BASIC_INFORMATION mbi;
char path[MAX_PATH];
VirtualQuery((void *)(uintptr_t)clang_createTranslationUnit, &mbi,
@@ -112,7 +112,7 @@ LibclangInvocationReporter::LibclangInvocationReporter(
// Write out the information about the invocation to it.
auto WriteStringKey = [&OS](StringRef Key, StringRef Value) {
OS << R"(")" << Key << R"(":")";
- OS << Value << '"';
+ OS << llvm::yaml::escape(Value) << '"';
};
OS << '{';
WriteStringKey("toolchain", Idx.getClangToolchainPath());
@@ -126,14 +126,14 @@ LibclangInvocationReporter::LibclangInvocationReporter(
for (const auto &I : llvm::enumerate(Args)) {
if (I.index())
OS << ',';
- OS << '"' << I.value() << '"';
+ OS << '"' << llvm::yaml::escape(I.value()) << '"';
}
if (!InvocationArgs.empty()) {
OS << R"(],"invocation-args":[)";
for (const auto &I : llvm::enumerate(InvocationArgs)) {
if (I.index())
OS << ',';
- OS << '"' << I.value() << '"';
+ OS << '"' << llvm::yaml::escape(I.value()) << '"';
}
}
if (!UnsavedFiles.empty()) {
diff --git a/tools/libclang/CIndexer.h b/tools/libclang/CIndexer.h
index 6c46eed4fb98..3ba35d6db601 100644
--- a/tools/libclang/CIndexer.h
+++ b/tools/libclang/CIndexer.h
@@ -52,7 +52,7 @@ public:
Options(CXGlobalOpt_None), PCHContainerOps(std::move(PCHContainerOps)) {
}
- /// \brief Whether we only want to see "local" declarations (that did not
+ /// Whether we only want to see "local" declarations (that did not
/// come from a previous precompiled header). If false, we want to see all
/// declarations.
bool getOnlyLocalDecls() const { return OnlyLocalDecls; }
@@ -74,7 +74,7 @@ public:
return Options & opt;
}
- /// \brief Get the path of the clang resource files.
+ /// Get the path of the clang resource files.
const std::string &getClangResourcesPath();
StringRef getClangToolchainPath();
@@ -103,47 +103,47 @@ private:
std::string File;
};
- /// \brief Return the current size to request for "safety".
+ /// Return the current size to request for "safety".
unsigned GetSafetyThreadStackSize();
- /// \brief Set the current size to request for "safety" (or 0, if safety
+ /// Set the current size to request for "safety" (or 0, if safety
/// threads should not be used).
void SetSafetyThreadStackSize(unsigned Value);
- /// \brief Execution the given code "safely", using crash recovery or safety
+ /// Execution the given code "safely", using crash recovery or safety
/// threads when possible.
///
/// \return False if a crash was detected.
bool RunSafely(llvm::CrashRecoveryContext &CRC, llvm::function_ref<void()> Fn,
unsigned Size = 0);
- /// \brief Set the thread priority to background.
+ /// Set the thread priority to background.
/// FIXME: Move to llvm/Support.
void setThreadBackgroundPriority();
- /// \brief Print libclang's resource usage to standard error.
+ /// Print libclang's resource usage to standard error.
void PrintLibclangResourceUsage(CXTranslationUnit TU);
namespace cxindex {
void printDiagsToStderr(ASTUnit *Unit);
- /// \brief If \c MacroDefLoc points at a macro definition with \c II as
+ /// If \c MacroDefLoc points at a macro definition with \c II as
/// its name, this retrieves its MacroInfo.
MacroInfo *getMacroInfo(const IdentifierInfo &II,
SourceLocation MacroDefLoc, CXTranslationUnit TU);
- /// \brief Retrieves the corresponding MacroInfo of a MacroDefinitionRecord.
+ /// Retrieves the corresponding MacroInfo of a MacroDefinitionRecord.
const MacroInfo *getMacroInfo(const MacroDefinitionRecord *MacroDef,
CXTranslationUnit TU);
- /// \brief If \c Loc resides inside the definition of \c MI and it points at
+ /// If \c Loc resides inside the definition of \c MI and it points at
/// an identifier that has ever been a macro name, this returns the latest
/// MacroDefinitionRecord for that name, otherwise it returns NULL.
MacroDefinitionRecord *checkForMacroInMacroDefinition(const MacroInfo *MI,
SourceLocation Loc,
CXTranslationUnit TU);
- /// \brief If \c Tok resides inside the definition of \c MI and it points at
+ /// If \c Tok resides inside the definition of \c MI and it points at
/// an identifier that has ever been a macro name, this returns the latest
/// MacroDefinitionRecord for that name, otherwise it returns NULL.
MacroDefinitionRecord *checkForMacroInMacroDefinition(const MacroInfo *MI,
diff --git a/tools/libclang/CLog.h b/tools/libclang/CLog.h
index e1d6a57e4a01..a935995a1135 100644
--- a/tools/libclang/CLog.h
+++ b/tools/libclang/CLog.h
@@ -31,7 +31,7 @@ namespace cxindex {
class Logger;
typedef IntrusiveRefCntPtr<Logger> LogRef;
-/// \brief Collects logging output and writes it to stderr when it's destructed.
+/// Collects logging output and writes it to stderr when it's destructed.
/// Common use case:
/// \code
/// if (LogRef Log = Logger::make(__func__)) {
@@ -90,7 +90,7 @@ public:
}
}
-/// \brief Macros to automate common uses of Logger. Like this:
+/// Macros to automate common uses of Logger. Like this:
/// \code
/// LOG_FUNC_SECTION {
/// *Log << "blah";
diff --git a/tools/libclang/CMakeLists.txt b/tools/libclang/CMakeLists.txt
index 44406378207b..e539c8308e75 100644
--- a/tools/libclang/CMakeLists.txt
+++ b/tools/libclang/CMakeLists.txt
@@ -67,7 +67,7 @@ option(LIBCLANG_BUILD_STATIC
set(LLVM_EXPORTED_SYMBOL_FILE ${CMAKE_CURRENT_SOURCE_DIR}/libclang.exports)
if(MSVC)
- # Avoid LNK4197 not to spceify libclang.def here.
+ # Avoid LNK4197 by not specifying libclang.exports here.
# Each functions is exported as "dllexport" in include/clang-c.
# KB835326
set(LLVM_EXPORTED_SYMBOL_FILE)
diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp
index fb61249a778f..b4ad0595cc53 100644
--- a/tools/libclang/CXCursor.cpp
+++ b/tools/libclang/CXCursor.cpp
@@ -305,6 +305,10 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
K = CXCursor_IntegerLiteral;
break;
+ case Stmt::FixedPointLiteralClass:
+ K = CXCursor_FixedPointLiteral;
+ break;
+
case Stmt::FloatingLiteralClass:
K = CXCursor_FloatingLiteral;
break;
@@ -1196,19 +1200,19 @@ int clang_Cursor_getNumTemplateArguments(CXCursor C) {
}
enum CXGetTemplateArgumentStatus {
- /** \brief The operation completed successfully */
+ /** The operation completed successfully */
CXGetTemplateArgumentStatus_Success = 0,
- /** \brief The specified cursor did not represent a FunctionDecl. */
+ /** The specified cursor did not represent a FunctionDecl. */
CXGetTemplateArgumentStatus_CursorNotFunctionDecl = -1,
- /** \brief The specified cursor was not castable to a FunctionDecl. */
+ /** The specified cursor was not castable to a FunctionDecl. */
CXGetTemplateArgumentStatus_BadFunctionDeclCast = -2,
- /** \brief A NULL FunctionTemplateSpecializationInfo was retrieved. */
+ /** A NULL FunctionTemplateSpecializationInfo was retrieved. */
CXGetTemplateArgumentStatus_NullTemplSpecInfo = -3,
- /** \brief An invalid (OOB) argument index was specified */
+ /** An invalid (OOB) argument index was specified */
CXGetTemplateArgumentStatus_InvalidIndex = -4
};
@@ -1469,17 +1473,17 @@ void clang_getOverriddenCursors(CXCursor cursor,
assert(cxcursor::getCursorTU(backRefCursor) == TU);
Vec->push_back(backRefCursor);
- // Get the overriden cursors.
+ // Get the overridden cursors.
cxcursor::getOverriddenCursors(cursor, *Vec);
- // Did we get any overriden cursors? If not, return Vec to the pool
+ // Did we get any overridden cursors? If not, return Vec to the pool
// of available cursor vectors.
if (Vec->size() == 1) {
pool.AvailableCursors.push_back(Vec);
return;
}
- // Now tell the caller about the overriden cursors.
+ // Now tell the caller about the overridden cursors.
assert(Vec->size() > 1);
*overridden = &((*Vec)[1]);
*num_overridden = Vec->size() - 1;
diff --git a/tools/libclang/CXCursor.h b/tools/libclang/CXCursor.h
index 083b86934d16..a5d9fff2a55a 100644
--- a/tools/libclang/CXCursor.h
+++ b/tools/libclang/CXCursor.h
@@ -58,109 +58,109 @@ CXCursor MakeCXCursor(const clang::Stmt *S, const clang::Decl *Parent,
SourceRange RegionOfInterest = SourceRange());
CXCursor MakeCXCursorInvalid(CXCursorKind K, CXTranslationUnit TU = nullptr);
-/// \brief Create an Objective-C superclass reference at the given location.
+/// Create an Objective-C superclass reference at the given location.
CXCursor MakeCursorObjCSuperClassRef(ObjCInterfaceDecl *Super,
SourceLocation Loc,
CXTranslationUnit TU);
-/// \brief Unpack an ObjCSuperClassRef cursor into the interface it references
+/// Unpack an ObjCSuperClassRef cursor into the interface it references
/// and optionally the location where the reference occurred.
std::pair<const ObjCInterfaceDecl *, SourceLocation>
getCursorObjCSuperClassRef(CXCursor C);
-/// \brief Create an Objective-C protocol reference at the given location.
+/// Create an Objective-C protocol reference at the given location.
CXCursor MakeCursorObjCProtocolRef(const ObjCProtocolDecl *Proto,
SourceLocation Loc,
CXTranslationUnit TU);
-/// \brief Unpack an ObjCProtocolRef cursor into the protocol it references
+/// Unpack an ObjCProtocolRef cursor into the protocol it references
/// and optionally the location where the reference occurred.
std::pair<const ObjCProtocolDecl *, SourceLocation>
getCursorObjCProtocolRef(CXCursor C);
-/// \brief Create an Objective-C class reference at the given location.
+/// Create an Objective-C class reference at the given location.
CXCursor MakeCursorObjCClassRef(const ObjCInterfaceDecl *Class,
SourceLocation Loc,
CXTranslationUnit TU);
-/// \brief Unpack an ObjCClassRef cursor into the class it references
+/// Unpack an ObjCClassRef cursor into the class it references
/// and optionally the location where the reference occurred.
std::pair<const ObjCInterfaceDecl *, SourceLocation>
getCursorObjCClassRef(CXCursor C);
-/// \brief Create a type reference at the given location.
+/// Create a type reference at the given location.
CXCursor MakeCursorTypeRef(const TypeDecl *Type, SourceLocation Loc,
CXTranslationUnit TU);
-/// \brief Unpack a TypeRef cursor into the class it references
+/// Unpack a TypeRef cursor into the class it references
/// and optionally the location where the reference occurred.
std::pair<const TypeDecl *, SourceLocation> getCursorTypeRef(CXCursor C);
-/// \brief Create a reference to a template at the given location.
+/// Create a reference to a template at the given location.
CXCursor MakeCursorTemplateRef(const TemplateDecl *Template, SourceLocation Loc,
CXTranslationUnit TU);
-/// \brief Unpack a TemplateRef cursor into the template it references and
+/// Unpack a TemplateRef cursor into the template it references and
/// the location where the reference occurred.
std::pair<const TemplateDecl *, SourceLocation>
getCursorTemplateRef(CXCursor C);
-/// \brief Create a reference to a namespace or namespace alias at the given
+/// Create a reference to a namespace or namespace alias at the given
/// location.
CXCursor MakeCursorNamespaceRef(const NamedDecl *NS, SourceLocation Loc,
CXTranslationUnit TU);
-/// \brief Unpack a NamespaceRef cursor into the namespace or namespace alias
+/// Unpack a NamespaceRef cursor into the namespace or namespace alias
/// it references and the location where the reference occurred.
std::pair<const NamedDecl *, SourceLocation> getCursorNamespaceRef(CXCursor C);
-/// \brief Create a reference to a variable at the given location.
+/// Create a reference to a variable at the given location.
CXCursor MakeCursorVariableRef(const VarDecl *Var, SourceLocation Loc,
CXTranslationUnit TU);
-/// \brief Unpack a VariableRef cursor into the variable it references and the
+/// Unpack a VariableRef cursor into the variable it references and the
/// location where the where the reference occurred.
std::pair<const VarDecl *, SourceLocation> getCursorVariableRef(CXCursor C);
-/// \brief Create a reference to a field at the given location.
+/// Create a reference to a field at the given location.
CXCursor MakeCursorMemberRef(const FieldDecl *Field, SourceLocation Loc,
CXTranslationUnit TU);
-/// \brief Unpack a MemberRef cursor into the field it references and the
+/// Unpack a MemberRef cursor into the field it references and the
/// location where the reference occurred.
std::pair<const FieldDecl *, SourceLocation> getCursorMemberRef(CXCursor C);
-/// \brief Create a CXX base specifier cursor.
+/// Create a CXX base specifier cursor.
CXCursor MakeCursorCXXBaseSpecifier(const CXXBaseSpecifier *B,
CXTranslationUnit TU);
-/// \brief Unpack a CXXBaseSpecifier cursor into a CXXBaseSpecifier.
+/// Unpack a CXXBaseSpecifier cursor into a CXXBaseSpecifier.
const CXXBaseSpecifier *getCursorCXXBaseSpecifier(CXCursor C);
-/// \brief Create a preprocessing directive cursor.
+/// Create a preprocessing directive cursor.
CXCursor MakePreprocessingDirectiveCursor(SourceRange Range,
CXTranslationUnit TU);
-/// \brief Unpack a given preprocessing directive to retrieve its source range.
+/// Unpack a given preprocessing directive to retrieve its source range.
SourceRange getCursorPreprocessingDirective(CXCursor C);
-/// \brief Create a macro definition cursor.
+/// Create a macro definition cursor.
CXCursor MakeMacroDefinitionCursor(const MacroDefinitionRecord *,
CXTranslationUnit TU);
-/// \brief Unpack a given macro definition cursor to retrieve its
+/// Unpack a given macro definition cursor to retrieve its
/// source range.
const MacroDefinitionRecord *getCursorMacroDefinition(CXCursor C);
-/// \brief Create a macro expansion cursor.
+/// Create a macro expansion cursor.
CXCursor MakeMacroExpansionCursor(MacroExpansion *, CXTranslationUnit TU);
-/// \brief Create a "pseudo" macro expansion cursor, using a macro definition
+/// Create a "pseudo" macro expansion cursor, using a macro definition
/// and a source location.
CXCursor MakeMacroExpansionCursor(MacroDefinitionRecord *, SourceLocation Loc,
CXTranslationUnit TU);
-/// \brief Wraps a macro expansion cursor and provides a common interface
+/// Wraps a macro expansion cursor and provides a common interface
/// for a normal macro expansion cursor or a "pseudo" one.
///
/// "Pseudo" macro expansion cursors (essentially a macro definition along with
@@ -194,46 +194,46 @@ public:
SourceRange getSourceRange() const;
};
-/// \brief Unpack a given macro expansion cursor to retrieve its info.
+/// Unpack a given macro expansion cursor to retrieve its info.
static inline MacroExpansionCursor getCursorMacroExpansion(CXCursor C) {
return C;
}
-/// \brief Create an inclusion directive cursor.
+/// Create an inclusion directive cursor.
CXCursor MakeInclusionDirectiveCursor(InclusionDirective *,
CXTranslationUnit TU);
-/// \brief Unpack a given inclusion directive cursor to retrieve its
+/// Unpack a given inclusion directive cursor to retrieve its
/// source range.
const InclusionDirective *getCursorInclusionDirective(CXCursor C);
-/// \brief Create a label reference at the given location.
+/// Create a label reference at the given location.
CXCursor MakeCursorLabelRef(LabelStmt *Label, SourceLocation Loc,
CXTranslationUnit TU);
-/// \brief Unpack a label reference into the label statement it refers to and
+/// Unpack a label reference into the label statement it refers to and
/// the location of the reference.
std::pair<const LabelStmt *, SourceLocation> getCursorLabelRef(CXCursor C);
-/// \brief Create a overloaded declaration reference cursor for an expression.
+/// Create a overloaded declaration reference cursor for an expression.
CXCursor MakeCursorOverloadedDeclRef(const OverloadExpr *E,
CXTranslationUnit TU);
-/// \brief Create a overloaded declaration reference cursor for a declaration.
+/// Create a overloaded declaration reference cursor for a declaration.
CXCursor MakeCursorOverloadedDeclRef(const Decl *D, SourceLocation Location,
CXTranslationUnit TU);
-/// \brief Create a overloaded declaration reference cursor for a template name.
+/// Create a overloaded declaration reference cursor for a template name.
CXCursor MakeCursorOverloadedDeclRef(TemplateName Template,
SourceLocation Location,
CXTranslationUnit TU);
-/// \brief Internal storage for an overloaded declaration reference cursor;
+/// Internal storage for an overloaded declaration reference cursor;
typedef llvm::PointerUnion3<const OverloadExpr *, const Decl *,
OverloadedTemplateStorage *>
OverloadedDeclRefStorage;
-/// \brief Unpack an overloaded declaration reference into an expression,
+/// Unpack an overloaded declaration reference into an expression,
/// declaration, or template name along with the source location.
std::pair<OverloadedDeclRefStorage, SourceLocation>
getCursorOverloadedDeclRef(CXCursor C);
@@ -251,14 +251,14 @@ CXTranslationUnit getCursorTU(CXCursor Cursor);
void getOverriddenCursors(CXCursor cursor,
SmallVectorImpl<CXCursor> &overridden);
-/// \brief Create an opaque pool used for fast generation of overriden
+/// Create an opaque pool used for fast generation of overridden
/// CXCursor arrays.
void *createOverridenCXCursorsPool();
-/// \brief Dispose of the overriden CXCursors pool.
+/// Dispose of the overridden CXCursors pool.
void disposeOverridenCXCursorsPool(void *pool);
-/// \brief Returns a index/location pair for a selector identifier if the cursor
+/// Returns a index/location pair for a selector identifier if the cursor
/// points to one.
std::pair<int, SourceLocation> getSelectorIdentifierIndexAndLoc(CXCursor);
static inline int getSelectorIdentifierIndex(CXCursor cursor) {
@@ -279,7 +279,7 @@ static inline CXCursor getTypeRefedCallExprCursor(CXCursor cursor) {
CXCursor getTypeRefCursor(CXCursor cursor);
-/// \brief Generate a USR for \arg D and put it in \arg Buf.
+/// Generate a USR for \arg D and put it in \arg Buf.
/// \returns true if no USR was computed or the result should be ignored,
/// false otherwise.
bool getDeclCursorUSR(const Decl *D, SmallVectorImpl<char> &Buf);
@@ -290,7 +290,7 @@ inline bool operator!=(CXCursor X, CXCursor Y) {
return !(X == Y);
}
-/// \brief Return true if the cursor represents a declaration that is the
+/// Return true if the cursor represents a declaration that is the
/// first in a declaration group.
bool isFirstInDeclGroup(CXCursor C);
diff --git a/tools/libclang/CXIndexDataConsumer.cpp b/tools/libclang/CXIndexDataConsumer.cpp
index 89ac23be7344..616a0797f52b 100644
--- a/tools/libclang/CXIndexDataConsumer.cpp
+++ b/tools/libclang/CXIndexDataConsumer.cpp
@@ -148,15 +148,17 @@ public:
return true;
}
};
+
+CXSymbolRole getSymbolRole(SymbolRoleSet Role) {
+ // CXSymbolRole mirrors low 9 bits of clang::index::SymbolRole.
+ return CXSymbolRole(static_cast<uint32_t>(Role) & ((1 << 9) - 1));
+}
}
-bool CXIndexDataConsumer::handleDeclOccurence(const Decl *D,
- SymbolRoleSet Roles,
- ArrayRef<SymbolRelation> Relations,
- FileID FID, unsigned Offset,
- ASTNodeInfo ASTNode) {
- SourceLocation Loc = getASTContext().getSourceManager()
- .getLocForStartOfFile(FID).getLocWithOffset(Offset);
+bool CXIndexDataConsumer::handleDeclOccurence(
+ const Decl *D, SymbolRoleSet Roles, ArrayRef<SymbolRelation> Relations,
+ SourceLocation Loc, ASTNodeInfo ASTNode) {
+ Loc = getASTContext().getSourceManager().getFileLoc(Loc);
if (Roles & (unsigned)SymbolRole::Reference) {
const NamedDecl *ND = dyn_cast<NamedDecl>(D);
@@ -184,6 +186,7 @@ bool CXIndexDataConsumer::handleDeclOccurence(const Decl *D,
if (Roles & (unsigned)SymbolRole::Implicit) {
Kind = CXIdxEntityRef_Implicit;
}
+ CXSymbolRole CXRole = getSymbolRole(Roles);
CXCursor Cursor;
if (ASTNode.OrigE) {
@@ -202,7 +205,7 @@ bool CXIndexDataConsumer::handleDeclOccurence(const Decl *D,
}
handleReference(ND, Loc, Cursor,
dyn_cast_or_null<NamedDecl>(ASTNode.Parent),
- ASTNode.ContainerDC, ASTNode.OrigE, Kind);
+ ASTNode.ContainerDC, ASTNode.OrigE, Kind, CXRole);
} else {
const DeclContext *LexicalDC = ASTNode.ContainerDC;
@@ -220,8 +223,7 @@ bool CXIndexDataConsumer::handleDeclOccurence(const Decl *D,
bool CXIndexDataConsumer::handleModuleOccurence(const ImportDecl *ImportD,
SymbolRoleSet Roles,
- FileID FID,
- unsigned Offset) {
+ SourceLocation Loc) {
IndexingDeclVisitor(*this, SourceLocation(), nullptr).Visit(ImportD);
return !shouldAbort();
}
@@ -889,13 +891,14 @@ bool CXIndexDataConsumer::handleReference(const NamedDecl *D, SourceLocation Loc
const NamedDecl *Parent,
const DeclContext *DC,
const Expr *E,
- CXIdxEntityRefKind Kind) {
- if (!D)
+ CXIdxEntityRefKind Kind,
+ CXSymbolRole Role) {
+ if (!D || !DC)
return false;
CXCursor Cursor = E ? MakeCXCursor(E, cast<Decl>(DC), CXTU)
: getRefCursor(D, Loc);
- return handleReference(D, Loc, Cursor, Parent, DC, E, Kind);
+ return handleReference(D, Loc, Cursor, Parent, DC, E, Kind, Role);
}
bool CXIndexDataConsumer::handleReference(const NamedDecl *D, SourceLocation Loc,
@@ -903,11 +906,12 @@ bool CXIndexDataConsumer::handleReference(const NamedDecl *D, SourceLocation Loc
const NamedDecl *Parent,
const DeclContext *DC,
const Expr *E,
- CXIdxEntityRefKind Kind) {
+ CXIdxEntityRefKind Kind,
+ CXSymbolRole Role) {
if (!CB.indexEntityReference)
return false;
- if (!D)
+ if (!D || !DC)
return false;
if (Loc.isInvalid())
return false;
@@ -939,7 +943,8 @@ bool CXIndexDataConsumer::handleReference(const NamedDecl *D, SourceLocation Loc
getIndexLoc(Loc),
&RefEntity,
Parent ? &ParentEntity : nullptr,
- &Container };
+ &Container,
+ Role };
CB.indexEntityReference(ClientData, &Info);
return true;
}
diff --git a/tools/libclang/CXIndexDataConsumer.h b/tools/libclang/CXIndexDataConsumer.h
index a54baadd0774..19e39b281ab0 100644
--- a/tools/libclang/CXIndexDataConsumer.h
+++ b/tools/libclang/CXIndexDataConsumer.h
@@ -260,7 +260,7 @@ public:
}
unsigned getNumAttrs() const { return (unsigned)CXAttrs.size(); }
- /// \brief Retain/Release only useful when we allocate a AttrListInfo from the
+ /// Retain/Release only useful when we allocate a AttrListInfo from the
/// BumpPtrAllocator, and not from the stack; so that we keep a pointer
// in the EntityInfo
void Retain() { ++ref_cnt; }
@@ -436,13 +436,15 @@ public:
const NamedDecl *Parent,
const DeclContext *DC,
const Expr *E = nullptr,
- CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct);
+ CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct,
+ CXSymbolRole Role = CXSymbolRole_None);
bool handleReference(const NamedDecl *D, SourceLocation Loc,
const NamedDecl *Parent,
const DeclContext *DC,
const Expr *E = nullptr,
- CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct);
+ CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct,
+ CXSymbolRole Role = CXSymbolRole_None);
bool isNotFromSourceFile(SourceLocation Loc) const;
@@ -463,12 +465,11 @@ public:
private:
bool handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles,
ArrayRef<index::SymbolRelation> Relations,
- FileID FID, unsigned Offset,
- ASTNodeInfo ASTNode) override;
+ SourceLocation Loc, ASTNodeInfo ASTNode) override;
bool handleModuleOccurence(const ImportDecl *ImportD,
index::SymbolRoleSet Roles,
- FileID FID, unsigned Offset) override;
+ SourceLocation Loc) override;
void finish() override;
diff --git a/tools/libclang/CXLoadedDiagnostic.cpp b/tools/libclang/CXLoadedDiagnostic.cpp
index 36c3dcabb924..fd6881e03ab0 100644
--- a/tools/libclang/CXLoadedDiagnostic.cpp
+++ b/tools/libclang/CXLoadedDiagnostic.cpp
@@ -47,7 +47,7 @@ public:
FileManager FakeFiles;
llvm::DenseMap<unsigned, const FileEntry *> Files;
- /// \brief Copy the string into our own allocator.
+ /// Copy the string into our own allocator.
const char *copyString(StringRef Blob) {
char *mem = Alloc.Allocate<char>(Blob.size() + 1);
memcpy(mem, Blob.data(), Blob.size());
diff --git a/tools/libclang/CXLoadedDiagnostic.h b/tools/libclang/CXLoadedDiagnostic.h
index 1209d76669f8..521ebd84bf13 100644
--- a/tools/libclang/CXLoadedDiagnostic.h
+++ b/tools/libclang/CXLoadedDiagnostic.h
@@ -27,34 +27,34 @@ public:
~CXLoadedDiagnostic() override;
- /// \brief Return the severity of the diagnostic.
+ /// Return the severity of the diagnostic.
CXDiagnosticSeverity getSeverity() const override;
- /// \brief Return the location of the diagnostic.
+ /// Return the location of the diagnostic.
CXSourceLocation getLocation() const override;
- /// \brief Return the spelling of the diagnostic.
+ /// Return the spelling of the diagnostic.
CXString getSpelling() const override;
- /// \brief Return the text for the diagnostic option.
+ /// Return the text for the diagnostic option.
CXString getDiagnosticOption(CXString *Disable) const override;
- /// \brief Return the category of the diagnostic.
+ /// Return the category of the diagnostic.
unsigned getCategory() const override;
- /// \brief Return the category string of the diagnostic.
+ /// Return the category string of the diagnostic.
CXString getCategoryText() const override;
- /// \brief Return the number of source ranges for the diagnostic.
+ /// Return the number of source ranges for the diagnostic.
unsigned getNumRanges() const override;
- /// \brief Return the source ranges for the diagnostic.
+ /// Return the source ranges for the diagnostic.
CXSourceRange getRange(unsigned Range) const override;
- /// \brief Return the number of FixIts.
+ /// Return the number of FixIts.
unsigned getNumFixIts() const override;
- /// \brief Return the FixIt information (source range and inserted text).
+ /// Return the FixIt information (source range and inserted text).
CXString getFixIt(unsigned FixIt,
CXSourceRange *ReplacementRange) const override;
@@ -62,7 +62,7 @@ public:
return D->getKind() == LoadedDiagnosticKind;
}
- /// \brief Decode the CXSourceLocation into file, line, column, and offset.
+ /// Decode the CXSourceLocation into file, line, column, and offset.
static void decodeLocation(CXSourceLocation location,
CXFile *file,
unsigned *line,
diff --git a/tools/libclang/CXSourceLocation.h b/tools/libclang/CXSourceLocation.h
index f0b3f4954919..dddc8475906c 100644
--- a/tools/libclang/CXSourceLocation.h
+++ b/tools/libclang/CXSourceLocation.h
@@ -25,7 +25,7 @@ class SourceManager;
namespace cxloc {
-/// \brief Translate a Clang source location into a CIndex source location.
+/// Translate a Clang source location into a CIndex source location.
static inline CXSourceLocation
translateSourceLocation(const SourceManager &SM, const LangOptions &LangOpts,
SourceLocation Loc) {
@@ -37,7 +37,7 @@ translateSourceLocation(const SourceManager &SM, const LangOptions &LangOpts,
return Result;
}
-/// \brief Translate a Clang source location into a CIndex source location.
+/// Translate a Clang source location into a CIndex source location.
static inline CXSourceLocation translateSourceLocation(ASTContext &Context,
SourceLocation Loc) {
return translateSourceLocation(Context.getSourceManager(),
@@ -45,7 +45,7 @@ static inline CXSourceLocation translateSourceLocation(ASTContext &Context,
Loc);
}
-/// \brief Translate a Clang source range into a CIndex source range.
+/// Translate a Clang source range into a CIndex source range.
///
/// Clang internally represents ranges where the end location points to the
/// start of the token at the end. However, for external clients it is more
@@ -55,7 +55,7 @@ CXSourceRange translateSourceRange(const SourceManager &SM,
const LangOptions &LangOpts,
const CharSourceRange &R);
-/// \brief Translate a Clang source range into a CIndex source range.
+/// Translate a Clang source range into a CIndex source range.
static inline CXSourceRange translateSourceRange(ASTContext &Context,
SourceRange R) {
return translateSourceRange(Context.getSourceManager(),
diff --git a/tools/libclang/CXString.cpp b/tools/libclang/CXString.cpp
index 448603179203..cef4e53a42c2 100644
--- a/tools/libclang/CXString.cpp
+++ b/tools/libclang/CXString.cpp
@@ -96,7 +96,7 @@ CXString createRef(StringRef String) {
CXString createDup(StringRef String) {
CXString Result;
- char *Spelling = static_cast<char *>(malloc(String.size() + 1));
+ char *Spelling = static_cast<char *>(llvm::safe_malloc(String.size() + 1));
memmove(Spelling, String.data(), String.size());
Spelling[String.size()] = 0;
Result.data = Spelling;
diff --git a/tools/libclang/CXString.h b/tools/libclang/CXString.h
index 6473eb2d7103..ed1926118701 100644
--- a/tools/libclang/CXString.h
+++ b/tools/libclang/CXString.h
@@ -27,33 +27,33 @@ namespace cxstring {
struct CXStringBuf;
-/// \brief Create a CXString object for an empty "" string.
+/// Create a CXString object for an empty "" string.
CXString createEmpty();
-/// \brief Create a CXString object for an NULL string.
+/// Create a CXString object for an NULL string.
///
/// A NULL string should be used as an "invalid" value in case of errors.
CXString createNull();
-/// \brief Create a CXString object from a nul-terminated C string. New
+/// Create a CXString object from a nul-terminated C string. New
/// CXString may contain a pointer to \p String.
///
/// \p String should not be changed by the caller afterwards.
CXString createRef(const char *String);
-/// \brief Create a CXString object from a nul-terminated C string. New
+/// Create a CXString object from a nul-terminated C string. New
/// CXString will contain a copy of \p String.
///
/// \p String can be changed or freed by the caller.
CXString createDup(const char *String);
-/// \brief Create a CXString object from a StringRef. New CXString may
+/// Create a CXString object from a StringRef. New CXString may
/// contain a pointer to the undrelying data of \p String.
///
/// \p String should not be changed by the caller afterwards.
CXString createRef(StringRef String);
-/// \brief Create a CXString object from a StringRef. New CXString will
+/// Create a CXString object from a StringRef. New CXString will
/// contain a copy of \p String.
///
/// \p String can be changed or freed by the caller.
@@ -65,12 +65,12 @@ CXString createDup(StringRef String);
// If you need to make a copy, call \c createDup(StringRef(String)).
CXString createRef(std::string String) = delete;
-/// \brief Create a CXString object that is backed by a string buffer.
+/// Create a CXString object that is backed by a string buffer.
CXString createCXString(CXStringBuf *buf);
CXStringSet *createSet(const std::vector<std::string> &Strings);
-/// \brief A string pool used for fast allocation/deallocation of strings.
+/// A string pool used for fast allocation/deallocation of strings.
class CXStringPool {
public:
~CXStringPool();
@@ -89,13 +89,13 @@ struct CXStringBuf {
CXStringBuf(CXTranslationUnit TU) : TU(TU) {}
- /// \brief Return this buffer to the pool.
+ /// Return this buffer to the pool.
void dispose();
};
CXStringBuf *getCXStringBuf(CXTranslationUnit TU);
-/// \brief Returns true if the CXString data is managed by a pool.
+/// Returns true if the CXString data is managed by a pool.
bool isManagedByPool(CXString str);
}
diff --git a/tools/libclang/CXType.cpp b/tools/libclang/CXType.cpp
index dfc015247768..7c0f307944a1 100644
--- a/tools/libclang/CXType.cpp
+++ b/tools/libclang/CXType.cpp
@@ -53,6 +53,12 @@ static CXTypeKind GetBuiltinTypeKind(const BuiltinType *BT) {
BTCASE(Float);
BTCASE(Double);
BTCASE(LongDouble);
+ BTCASE(ShortAccum);
+ BTCASE(Accum);
+ BTCASE(LongAccum);
+ BTCASE(UShortAccum);
+ BTCASE(UAccum);
+ BTCASE(ULongAccum);
BTCASE(Float16);
BTCASE(Float128);
BTCASE(NullPtr);
@@ -119,6 +125,10 @@ CXType cxtype::MakeCXType(QualType T, CXTranslationUnit TU) {
if (auto *ATT = T->getAs<AttributedType>()) {
return MakeCXType(ATT->getModifiedType(), TU);
}
+ // Handle paren types as the original type
+ if (auto *PTT = T->getAs<ParenType>()) {
+ return MakeCXType(PTT->getInnerType(), TU);
+ }
ASTContext &Ctx = cxtu::getASTUnit(TU)->getASTContext();
if (Ctx.getLangOpts().ObjC1) {
@@ -542,6 +552,12 @@ CXString clang_getTypeKindSpelling(enum CXTypeKind K) {
TKIND(Float);
TKIND(Double);
TKIND(LongDouble);
+ TKIND(ShortAccum);
+ TKIND(Accum);
+ TKIND(LongAccum);
+ TKIND(UShortAccum);
+ TKIND(UAccum);
+ TKIND(ULongAccum);
TKIND(Float16);
TKIND(Float128);
TKIND(NullPtr);
@@ -689,13 +705,41 @@ CXType clang_getCursorResultType(CXCursor C) {
return MakeCXType(QualType(), cxcursor::getCursorTU(C));
}
+// FIXME: We should expose the canThrow(...) result instead of the EST.
+static CXCursor_ExceptionSpecificationKind
+getExternalExceptionSpecificationKind(ExceptionSpecificationType EST) {
+ switch (EST) {
+ case EST_None:
+ return CXCursor_ExceptionSpecificationKind_None;
+ case EST_DynamicNone:
+ return CXCursor_ExceptionSpecificationKind_DynamicNone;
+ case EST_Dynamic:
+ return CXCursor_ExceptionSpecificationKind_Dynamic;
+ case EST_MSAny:
+ return CXCursor_ExceptionSpecificationKind_MSAny;
+ case EST_BasicNoexcept:
+ return CXCursor_ExceptionSpecificationKind_BasicNoexcept;
+ case EST_NoexceptFalse:
+ case EST_NoexceptTrue:
+ case EST_DependentNoexcept:
+ return CXCursor_ExceptionSpecificationKind_ComputedNoexcept;
+ case EST_Unevaluated:
+ return CXCursor_ExceptionSpecificationKind_Unevaluated;
+ case EST_Uninstantiated:
+ return CXCursor_ExceptionSpecificationKind_Uninstantiated;
+ case EST_Unparsed:
+ return CXCursor_ExceptionSpecificationKind_Unparsed;
+ }
+ llvm_unreachable("invalid EST value");
+}
+
int clang_getExceptionSpecificationType(CXType X) {
QualType T = GetQualType(X);
if (T.isNull())
return -1;
if (const auto *FD = T->getAs<FunctionProtoType>())
- return static_cast<int>(FD->getExceptionSpecType());
+ return getExternalExceptionSpecificationKind(FD->getExceptionSpecType());
return -1;
}
diff --git a/tools/libclang/CursorVisitor.h b/tools/libclang/CursorVisitor.h
index 82f251a348f0..f2fb68fab954 100644
--- a/tools/libclang/CursorVisitor.h
+++ b/tools/libclang/CursorVisitor.h
@@ -55,44 +55,44 @@ class CursorVisitor : public DeclVisitor<CursorVisitor, bool>,
public TypeLocVisitor<CursorVisitor, bool>
{
public:
- /// \brief Callback called after child nodes of a cursor have been visited.
+ /// Callback called after child nodes of a cursor have been visited.
/// Return true to break visitation or false to continue.
typedef bool (*PostChildrenVisitorTy)(CXCursor cursor,
CXClientData client_data);
private:
- /// \brief The translation unit we are traversing.
+ /// The translation unit we are traversing.
CXTranslationUnit TU;
ASTUnit *AU;
- /// \brief The parent cursor whose children we are traversing.
+ /// The parent cursor whose children we are traversing.
CXCursor Parent;
- /// \brief The declaration that serves at the parent of any statement or
+ /// The declaration that serves at the parent of any statement or
/// expression nodes.
const Decl *StmtParent;
- /// \brief The visitor function.
+ /// The visitor function.
CXCursorVisitor Visitor;
PostChildrenVisitorTy PostChildrenVisitor;
- /// \brief The opaque client data, to be passed along to the visitor.
+ /// The opaque client data, to be passed along to the visitor.
CXClientData ClientData;
- /// \brief Whether we should visit the preprocessing record entries last,
+ /// Whether we should visit the preprocessing record entries last,
/// after visiting other declarations.
bool VisitPreprocessorLast;
- /// \brief Whether we should visit declarations or preprocessing record
+ /// Whether we should visit declarations or preprocessing record
/// entries that are #included inside the \arg RegionOfInterest.
bool VisitIncludedEntities;
- /// \brief When valid, a source range to which the cursor should restrict
+ /// When valid, a source range to which the cursor should restrict
/// its search.
SourceRange RegionOfInterest;
- /// \brief Whether we should only visit declarations and not preprocessing
+ /// Whether we should only visit declarations and not preprocessing
/// record entries.
bool VisitDeclsOnly;
@@ -110,7 +110,7 @@ private:
using DeclVisitor<CursorVisitor, bool>::Visit;
using TypeLocVisitor<CursorVisitor, bool>::Visit;
- /// \brief Determine whether this particular source range comes before, comes
+ /// Determine whether this particular source range comes before, comes
/// after, or overlaps the region of interest.
///
/// \param R a half-open source range retrieved from the abstract syntax tree.
@@ -177,7 +177,7 @@ public:
bool Visit(CXCursor Cursor, bool CheckedRegionOfInterest = false);
- /// \brief Visit declarations and preprocessed entities for the file region
+ /// Visit declarations and preprocessed entities for the file region
/// designated by \see RegionOfInterest.
bool visitFileRegion();
diff --git a/tools/libclang/Index_Internal.h b/tools/libclang/Index_Internal.h
index 98f069c88738..fbe3cabf04c8 100644
--- a/tools/libclang/Index_Internal.h
+++ b/tools/libclang/Index_Internal.h
@@ -40,15 +40,15 @@ typedef struct _CXCursorAndRangeVisitorBlock {
#endif // !__has_feature(blocks)
-/// \brief The result of comparing two source ranges.
+/// The result of comparing two source ranges.
enum RangeComparisonResult {
- /// \brief Either the ranges overlap or one of the ranges is invalid.
+ /// Either the ranges overlap or one of the ranges is invalid.
RangeOverlap,
- /// \brief The first range ends before the second range starts.
+ /// The first range ends before the second range starts.
RangeBefore,
- /// \brief The first range starts after the second range ends.
+ /// The first range starts after the second range ends.
RangeAfter
};
diff --git a/tools/libclang/Indexing.cpp b/tools/libclang/Indexing.cpp
index 021ebcfcfe43..4da046b28233 100644
--- a/tools/libclang/Indexing.cpp
+++ b/tools/libclang/Indexing.cpp
@@ -45,7 +45,7 @@ namespace {
// Skip Parsed Bodies
//===----------------------------------------------------------------------===//
-/// \brief A "region" in source code identified by the file/offset of the
+/// A "region" in source code identified by the file/offset of the
/// preprocessor conditional directive that it belongs to.
/// Multiple, non-consecutive ranges can be parts of the same region.
///
@@ -249,7 +249,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 {
bool isImport = (IncludeTok.is(tok::identifier) &&
IncludeTok.getIdentifierInfo()->getPPKeywordID() == tok::pp_import);
DataConsumer.ppIncludedFile(HashLoc, FileName, File, isImport, IsAngled,
@@ -401,6 +402,8 @@ static IndexingOptions getIndexingOptionsFromCXOptions(unsigned index_options) {
IndexingOptions IdxOpts;
if (index_options & CXIndexOpt_IndexFunctionLocalSymbols)
IdxOpts.IndexFunctionLocals = true;
+ if (index_options & CXIndexOpt_IndexImplicitTemplateInstantiations)
+ IdxOpts.IndexImplicitInstantiation = true;
return IdxOpts;
}
@@ -659,8 +662,7 @@ static CXErrorCode clang_indexTranslationUnit_Impl(
? index_callbacks_size : sizeof(CB);
memcpy(&CB, client_index_callbacks, ClientCBSize);
- auto DataConsumer = std::make_shared<CXIndexDataConsumer>(client_data, CB,
- index_options, TU);
+ CXIndexDataConsumer DataConsumer(client_data, CB, index_options, TU);
ASTUnit *Unit = cxtu::getASTUnit(TU);
if (!Unit)
@@ -669,21 +671,22 @@ static CXErrorCode clang_indexTranslationUnit_Impl(
ASTUnit::ConcurrencyCheck Check(*Unit);
if (const FileEntry *PCHFile = Unit->getPCHFile())
- DataConsumer->importedPCH(PCHFile);
+ DataConsumer.importedPCH(PCHFile);
FileManager &FileMgr = Unit->getFileManager();
if (Unit->getOriginalSourceFileName().empty())
- DataConsumer->enteredMainFile(nullptr);
+ DataConsumer.enteredMainFile(nullptr);
else
- DataConsumer->enteredMainFile(FileMgr.getFile(Unit->getOriginalSourceFileName()));
+ DataConsumer.enteredMainFile(
+ FileMgr.getFile(Unit->getOriginalSourceFileName()));
- DataConsumer->setASTContext(Unit->getASTContext());
- DataConsumer->startedTranslationUnit();
+ DataConsumer.setASTContext(Unit->getASTContext());
+ DataConsumer.startedTranslationUnit();
- indexPreprocessingRecord(*Unit, *DataConsumer);
+ indexPreprocessingRecord(*Unit, DataConsumer);
indexASTUnit(*Unit, DataConsumer, getIndexingOptionsFromCXOptions(index_options));
- DataConsumer->indexDiagnostics();
+ DataConsumer.indexDiagnostics();
return CXError_Success;
}
diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports
index 4d3a029567d4..95a42712c4af 100644
--- a/tools/libclang/libclang.exports
+++ b/tools/libclang/libclang.exports
@@ -46,6 +46,7 @@ clang_Cursor_isVariadic
clang_Cursor_getModule
clang_Cursor_getStorageClass
clang_File_isEqual
+clang_File_tryGetRealPathName
clang_Module_getASTFile
clang_Module_getParent
clang_Module_getName
@@ -170,6 +171,8 @@ clang_getCompletionBriefComment
clang_getCompletionChunkCompletionString
clang_getCompletionChunkKind
clang_getCompletionChunkText
+clang_getCompletionNumFixIts
+clang_getCompletionFixIt
clang_getCompletionNumAnnotations
clang_getCompletionParent
clang_getCompletionPriority
@@ -178,6 +181,8 @@ clang_getCursorAvailability
clang_getCursorCompletionString
clang_getCursorDefinition
clang_getCursorDisplayName
+clang_getCursorPrintingPolicy
+clang_getCursorPrettyPrinted
clang_getCursorExtent
clang_getCursorExceptionSpecificationType
clang_getCursorKind
@@ -220,6 +225,7 @@ clang_getExceptionSpecificationType
clang_getFieldDeclBitWidth
clang_getExpansionLocation
clang_getFile
+clang_getFileContents
clang_getFileLocation
clang_getFileName
clang_getFileTime
@@ -256,6 +262,7 @@ clang_getSpecializedCursorTemplate
clang_getSpellingLocation
clang_getTUResourceUsageName
clang_getTemplateCursorKind
+clang_getToken
clang_getTokenExtent
clang_getTokenKind
clang_getTokenLocation
@@ -290,6 +297,7 @@ clang_isAttribute
clang_isConstQualifiedType
clang_isCursorDefinition
clang_isDeclaration
+clang_isInvalidDeclaration
clang_isExpression
clang_isFileMultipleIncludeGuarded
clang_isFunctionTypeVariadic
@@ -357,3 +365,6 @@ clang_EvalResult_isUnsignedInt
clang_EvalResult_getAsDouble
clang_EvalResult_getAsStr
clang_EvalResult_dispose
+clang_PrintingPolicy_getProperty
+clang_PrintingPolicy_setProperty
+clang_PrintingPolicy_dispose
diff --git a/tools/scan-build-py/README.md b/tools/scan-build-py/README.md
index 54bfc37ff76d..720bde1cf3b1 100644
--- a/tools/scan-build-py/README.md
+++ b/tools/scan-build-py/README.md
@@ -41,6 +41,32 @@ goes like this:
Use `--help` to know more about the commands.
+How to use the experimental Cross Translation Unit analysis
+-----------------------------------------------------------
+
+To run the CTU analysis, a compilation database file has to be created:
+
+ $ intercept-build <your build command>
+
+To run the Clang Static Analyzer against a compilation database
+with CTU analysis enabled, execute:
+
+ $ analyze-build --ctu
+
+For CTU analysis an additional (function-definition) collection-phase is required.
+For debugging purposes, it is possible to separately execute the collection
+and the analysis phase. By doing this, the intermediate files used for
+the analysis are kept on the disk in `./ctu-dir`.
+
+ # Collect and store the data required by the CTU analysis
+ $ analyze-build --ctu-collect-only
+
+ # Analyze using the previously collected data
+ $ analyze-build --ctu-analyze-only
+
+Use `--help` to get more information about the commands.
+
+
Limitations
-----------
@@ -58,11 +84,11 @@ tool has three distinct model to run the analyzer:
This is the default behaviour, can be enforced with `--override-compiler`
flag.
-2. Use special library to intercept compiler calls durring the build process.
+2. Use special library to intercept compiler calls during the build process.
The analyzer run against each modules after the build finished.
Use `--intercept-first` flag to get this model.
-3. Use compiler wrappers to intercept compiler calls durring the build process.
+3. Use compiler wrappers to intercept compiler calls during the build process.
The analyzer run against each modules after the build finished.
Use `--intercept-first` and `--override-compiler` flags together to get
this model.
@@ -79,7 +105,7 @@ process removes removes intermediate modules (generated sources) the analyzer
output still kept.
The 2. and 3. generate the compilation database first, and filters out those
-modules which are not exists. So, it's suitable for incremental analysis durring
+modules which are not exists. So, it's suitable for incremental analysis during
the development.
The 2. mode is available only on FreeBSD and Linux. Where library preload
diff --git a/tools/scan-build-py/libscanbuild/__init__.py b/tools/scan-build-py/libscanbuild/__init__.py
index 800926ebb6f2..e7b74879167e 100644
--- a/tools/scan-build-py/libscanbuild/__init__.py
+++ b/tools/scan-build-py/libscanbuild/__init__.py
@@ -19,6 +19,9 @@ ENVIRONMENT_KEY = 'INTERCEPT_BUILD'
Execution = collections.namedtuple('Execution', ['pid', 'cwd', 'cmd'])
+CtuConfig = collections.namedtuple('CtuConfig', ['collect', 'analyze', 'dir',
+ 'func_map_cmd'])
+
def duplicate_check(method):
""" Predicate to detect duplicated entries.
diff --git a/tools/scan-build-py/libscanbuild/analyze.py b/tools/scan-build-py/libscanbuild/analyze.py
index b5614b5b6da0..5a7cc20a517e 100644
--- a/tools/scan-build-py/libscanbuild/analyze.py
+++ b/tools/scan-build-py/libscanbuild/analyze.py
@@ -22,16 +22,19 @@ import functools
import subprocess
import contextlib
import datetime
+import shutil
+import glob
+from collections import defaultdict
from libscanbuild import command_entry_point, compiler_wrapper, \
- wrapper_environment, run_build, run_command
+ wrapper_environment, run_build, run_command, CtuConfig
from libscanbuild.arguments import parse_args_for_scan_build, \
parse_args_for_analyze_build
from libscanbuild.intercept import capture
from libscanbuild.report import document
from libscanbuild.compilation import split_command, classify_source, \
compiler_language
-from libscanbuild.clang import get_version, get_arguments
+from libscanbuild.clang import get_version, get_arguments, get_triple_arch
from libscanbuild.shell import decode
__all__ = ['scan_build', 'analyze_build', 'analyze_compiler_wrapper']
@@ -39,6 +42,9 @@ __all__ = ['scan_build', 'analyze_build', 'analyze_compiler_wrapper']
COMPILER_WRAPPER_CC = 'analyze-cc'
COMPILER_WRAPPER_CXX = 'analyze-c++'
+CTU_FUNCTION_MAP_FILENAME = 'externalFnMap.txt'
+CTU_TEMP_FNMAP_FOLDER = 'tmpExternalFnMaps'
+
@command_entry_point
def scan_build():
@@ -56,7 +62,7 @@ def scan_build():
exit_code = capture(args)
# Run the analyzer against the captured commands.
if need_analyzer(args.build):
- run_analyzer_parallel(args)
+ govern_analyzer_runs(args)
else:
# Run build command and analyzer with compiler wrappers.
environment = setup_environment(args)
@@ -75,7 +81,7 @@ def analyze_build():
# will re-assign the report directory as new output
with report_directory(args.output, args.keep_empty) as args.output:
# Run the analyzer against a compilation db.
- run_analyzer_parallel(args)
+ govern_analyzer_runs(args)
# Cover report generation and bug counting.
number_of_bugs = document(args)
# Set exit status as it was requested.
@@ -88,13 +94,115 @@ def need_analyzer(args):
When static analyzer run against project configure step, it should be
silent and no need to run the analyzer or generate report.
- To run `scan-build` against the configure step might be neccessary,
+ To run `scan-build` against the configure step might be necessary,
when compiler wrappers are used. That's the moment when build setup
check the compiler and capture the location for the build process. """
return len(args) and not re.search('configure|autogen', args[0])
+def prefix_with(constant, pieces):
+ """ From a sequence create another sequence where every second element
+ is from the original sequence and the odd elements are the prefix.
+
+ eg.: prefix_with(0, [1,2,3]) creates [0, 1, 0, 2, 0, 3] """
+
+ return [elem for piece in pieces for elem in [constant, piece]]
+
+
+def get_ctu_config_from_args(args):
+ """ CTU configuration is created from the chosen phases and dir. """
+
+ return (
+ CtuConfig(collect=args.ctu_phases.collect,
+ analyze=args.ctu_phases.analyze,
+ dir=args.ctu_dir,
+ func_map_cmd=args.func_map_cmd)
+ if hasattr(args, 'ctu_phases') and hasattr(args.ctu_phases, 'dir')
+ else CtuConfig(collect=False, analyze=False, dir='', func_map_cmd=''))
+
+
+def get_ctu_config_from_json(ctu_conf_json):
+ """ CTU configuration is created from the chosen phases and dir. """
+
+ ctu_config = json.loads(ctu_conf_json)
+ # Recover namedtuple from json when coming from analyze-cc or analyze-c++
+ return CtuConfig(collect=ctu_config[0],
+ analyze=ctu_config[1],
+ dir=ctu_config[2],
+ func_map_cmd=ctu_config[3])
+
+
+def create_global_ctu_function_map(func_map_lines):
+ """ Takes iterator of individual function maps and creates a global map
+ keeping only unique names. We leave conflicting names out of CTU.
+
+ :param func_map_lines: Contains the id of a function (mangled name) and
+ the originating source (the corresponding AST file) name.
+ :type func_map_lines: Iterator of str.
+ :returns: Mangled name - AST file pairs.
+ :rtype: List of (str, str) tuples.
+ """
+
+ mangled_to_asts = defaultdict(set)
+
+ for line in func_map_lines:
+ mangled_name, ast_file = line.strip().split(' ', 1)
+ mangled_to_asts[mangled_name].add(ast_file)
+
+ mangled_ast_pairs = []
+
+ for mangled_name, ast_files in mangled_to_asts.items():
+ if len(ast_files) == 1:
+ mangled_ast_pairs.append((mangled_name, next(iter(ast_files))))
+
+ return mangled_ast_pairs
+
+
+def merge_ctu_func_maps(ctudir):
+ """ Merge individual function maps into a global one.
+
+ As the collect phase runs parallel on multiple threads, all compilation
+ units are separately mapped into a temporary file in CTU_TEMP_FNMAP_FOLDER.
+ These function maps contain the mangled names of functions and the source
+ (AST generated from the source) which had them.
+ These files should be merged at the end into a global map file:
+ CTU_FUNCTION_MAP_FILENAME."""
+
+ def generate_func_map_lines(fnmap_dir):
+ """ Iterate over all lines of input files in a determined order. """
+
+ files = glob.glob(os.path.join(fnmap_dir, '*'))
+ files.sort()
+ for filename in files:
+ with open(filename, 'r') as in_file:
+ for line in in_file:
+ yield line
+
+ def write_global_map(arch, mangled_ast_pairs):
+ """ Write (mangled function name, ast file) pairs into final file. """
+
+ extern_fns_map_file = os.path.join(ctudir, arch,
+ CTU_FUNCTION_MAP_FILENAME)
+ with open(extern_fns_map_file, 'w') as out_file:
+ for mangled_name, ast_file in mangled_ast_pairs:
+ out_file.write('%s %s\n' % (mangled_name, ast_file))
+
+ triple_arches = glob.glob(os.path.join(ctudir, '*'))
+ for triple_path in triple_arches:
+ if os.path.isdir(triple_path):
+ triple_arch = os.path.basename(triple_path)
+ fnmap_dir = os.path.join(ctudir, triple_arch,
+ CTU_TEMP_FNMAP_FOLDER)
+
+ func_map_lines = generate_func_map_lines(fnmap_dir)
+ mangled_ast_pairs = create_global_ctu_function_map(func_map_lines)
+ write_global_map(triple_arch, mangled_ast_pairs)
+
+ # Remove all temporary files
+ shutil.rmtree(fnmap_dir, ignore_errors=True)
+
+
def run_analyzer_parallel(args):
""" Runs the analyzer against the given compilation database. """
@@ -109,7 +217,8 @@ def run_analyzer_parallel(args):
'output_format': args.output_format,
'output_failures': args.output_failures,
'direct_args': analyzer_params(args),
- 'force_debug': args.force_debug
+ 'force_debug': args.force_debug,
+ 'ctu': get_ctu_config_from_args(args)
}
logging.debug('run analyzer against compilation database')
@@ -127,6 +236,38 @@ def run_analyzer_parallel(args):
pool.join()
+def govern_analyzer_runs(args):
+ """ Governs multiple runs in CTU mode or runs once in normal mode. """
+
+ ctu_config = get_ctu_config_from_args(args)
+ # If we do a CTU collect (1st phase) we remove all previous collection
+ # data first.
+ if ctu_config.collect:
+ shutil.rmtree(ctu_config.dir, ignore_errors=True)
+
+ # If the user asked for a collect (1st) and analyze (2nd) phase, we do an
+ # all-in-one run where we deliberately remove collection data before and
+ # also after the run. If the user asks only for a single phase data is
+ # left so multiple analyze runs can use the same data gathered by a single
+ # collection run.
+ if ctu_config.collect and ctu_config.analyze:
+ # CTU strings are coming from args.ctu_dir and func_map_cmd,
+ # so we can leave it empty
+ args.ctu_phases = CtuConfig(collect=True, analyze=False,
+ dir='', func_map_cmd='')
+ run_analyzer_parallel(args)
+ merge_ctu_func_maps(ctu_config.dir)
+ args.ctu_phases = CtuConfig(collect=False, analyze=True,
+ dir='', func_map_cmd='')
+ run_analyzer_parallel(args)
+ shutil.rmtree(ctu_config.dir, ignore_errors=True)
+ else:
+ # Single runs (collect or analyze) are launched from here.
+ run_analyzer_parallel(args)
+ if ctu_config.collect:
+ merge_ctu_func_maps(ctu_config.dir)
+
+
def setup_environment(args):
""" Set up environment for build command to interpose compiler wrapper. """
@@ -140,7 +281,8 @@ def setup_environment(args):
'ANALYZE_BUILD_REPORT_FORMAT': args.output_format,
'ANALYZE_BUILD_REPORT_FAILURES': 'yes' if args.output_failures else '',
'ANALYZE_BUILD_PARAMETERS': ' '.join(analyzer_params(args)),
- 'ANALYZE_BUILD_FORCE_DEBUG': 'yes' if args.force_debug else ''
+ 'ANALYZE_BUILD_FORCE_DEBUG': 'yes' if args.force_debug else '',
+ 'ANALYZE_BUILD_CTU': json.dumps(get_ctu_config_from_args(args))
})
return environment
@@ -173,7 +315,8 @@ def analyze_compiler_wrapper_impl(result, execution):
'').split(' '),
'force_debug': os.getenv('ANALYZE_BUILD_FORCE_DEBUG'),
'directory': execution.cwd,
- 'command': [execution.cmd[0], '-c'] + compilation.flags
+ 'command': [execution.cmd[0], '-c'] + compilation.flags,
+ 'ctu': get_ctu_config_from_json(os.getenv('ANALYZE_BUILD_CTU'))
}
# call static analyzer against the compilation
for source in compilation.files:
@@ -223,14 +366,6 @@ def analyzer_params(args):
""" A group of command line arguments can mapped to command
line arguments of the analyzer. This method generates those. """
- def prefix_with(constant, pieces):
- """ From a sequence create another sequence where every second element
- is from the original sequence and the odd elements are the prefix.
-
- eg.: prefix_with(0, [1,2,3]) creates [0, 1, 0, 2, 0, 3] """
-
- return [elem for piece in pieces for elem in [constant, piece]]
-
result = []
if args.store_model:
@@ -294,14 +429,15 @@ def require(required):
'direct_args', # arguments from command line
'force_debug', # kill non debug macros
'output_dir', # where generated report files shall go
- 'output_format', # it's 'plist' or 'html' or both
- 'output_failures']) # generate crash reports or not
+ 'output_format', # it's 'plist', 'html', both or plist-multi-file
+ 'output_failures', # generate crash reports or not
+ 'ctu']) # ctu control options
def run(opts):
""" Entry point to run (or not) static analyzer against a single entry
of the compilation database.
This complex task is decomposed into smaller methods which are calling
- each other in chain. If the analyzis is not possibe the given method
+ each other in chain. If the analyzis is not possible the given method
just return and break the chain.
The passed parameter is a python dictionary. Each method first check
@@ -317,7 +453,7 @@ def run(opts):
return arch_check(opts)
except Exception:
- logging.error("Problem occured during analyzis.", exc_info=1)
+ logging.error("Problem occurred during analyzis.", exc_info=1)
return None
@@ -383,7 +519,10 @@ def run_analyzer(opts, continuation=report_failure):
def target():
""" Creates output file name for reports. """
- if opts['output_format'] in {'plist', 'plist-html'}:
+ if opts['output_format'] in {
+ 'plist',
+ 'plist-html',
+ 'plist-multi-file'}:
(handle, name) = tempfile.mkstemp(prefix='report-',
suffix='.plist',
dir=opts['output_dir'])
@@ -407,8 +546,109 @@ def run_analyzer(opts, continuation=report_failure):
return result
+def func_map_list_src_to_ast(func_src_list):
+ """ Turns textual function map list with source files into a
+ function map list with ast files. """
+
+ func_ast_list = []
+ for fn_src_txt in func_src_list:
+ mangled_name, path = fn_src_txt.split(" ", 1)
+ # Normalize path on windows as well
+ path = os.path.splitdrive(path)[1]
+ # Make relative path out of absolute
+ path = path[1:] if path[0] == os.sep else path
+ ast_path = os.path.join("ast", path + ".ast")
+ func_ast_list.append(mangled_name + " " + ast_path)
+ return func_ast_list
+
+
+@require(['clang', 'directory', 'flags', 'direct_args', 'file', 'ctu'])
+def ctu_collect_phase(opts):
+ """ Preprocess source by generating all data needed by CTU analysis. """
+
+ def generate_ast(triple_arch):
+ """ Generates ASTs for the current compilation command. """
+
+ args = opts['direct_args'] + opts['flags']
+ ast_joined_path = os.path.join(opts['ctu'].dir, triple_arch, 'ast',
+ os.path.realpath(opts['file'])[1:] +
+ '.ast')
+ ast_path = os.path.abspath(ast_joined_path)
+ ast_dir = os.path.dirname(ast_path)
+ if not os.path.isdir(ast_dir):
+ try:
+ os.makedirs(ast_dir)
+ except OSError:
+ # In case an other process already created it.
+ pass
+ ast_command = [opts['clang'], '-emit-ast']
+ ast_command.extend(args)
+ ast_command.append('-w')
+ ast_command.append(opts['file'])
+ ast_command.append('-o')
+ ast_command.append(ast_path)
+ logging.debug("Generating AST using '%s'", ast_command)
+ run_command(ast_command, cwd=opts['directory'])
+
+ def map_functions(triple_arch):
+ """ Generate function map file for the current source. """
+
+ args = opts['direct_args'] + opts['flags']
+ funcmap_command = [opts['ctu'].func_map_cmd]
+ funcmap_command.append(opts['file'])
+ funcmap_command.append('--')
+ funcmap_command.extend(args)
+ logging.debug("Generating function map using '%s'", funcmap_command)
+ func_src_list = run_command(funcmap_command, cwd=opts['directory'])
+ func_ast_list = func_map_list_src_to_ast(func_src_list)
+ extern_fns_map_folder = os.path.join(opts['ctu'].dir, triple_arch,
+ CTU_TEMP_FNMAP_FOLDER)
+ if not os.path.isdir(extern_fns_map_folder):
+ try:
+ os.makedirs(extern_fns_map_folder)
+ except OSError:
+ # In case an other process already created it.
+ pass
+ if func_ast_list:
+ with tempfile.NamedTemporaryFile(mode='w',
+ dir=extern_fns_map_folder,
+ delete=False) as out_file:
+ out_file.write("\n".join(func_ast_list) + "\n")
+
+ cwd = opts['directory']
+ cmd = [opts['clang'], '--analyze'] + opts['direct_args'] + opts['flags'] \
+ + [opts['file']]
+ triple_arch = get_triple_arch(cmd, cwd)
+ generate_ast(triple_arch)
+ map_functions(triple_arch)
+
+
+@require(['ctu'])
+def dispatch_ctu(opts, continuation=run_analyzer):
+ """ Execute only one phase of 2 phases of CTU if needed. """
+
+ ctu_config = opts['ctu']
+
+ if ctu_config.collect or ctu_config.analyze:
+ assert ctu_config.collect != ctu_config.analyze
+ if ctu_config.collect:
+ return ctu_collect_phase(opts)
+ if ctu_config.analyze:
+ cwd = opts['directory']
+ cmd = [opts['clang'], '--analyze'] + opts['direct_args'] \
+ + opts['flags'] + [opts['file']]
+ triarch = get_triple_arch(cmd, cwd)
+ ctu_options = ['ctu-dir=' + os.path.join(ctu_config.dir, triarch),
+ 'experimental-enable-naive-ctu-analysis=true']
+ analyzer_options = prefix_with('-analyzer-config', ctu_options)
+ direct_options = prefix_with('-Xanalyzer', analyzer_options)
+ opts['direct_args'].extend(direct_options)
+
+ return continuation(opts)
+
+
@require(['flags', 'force_debug'])
-def filter_debug_flags(opts, continuation=run_analyzer):
+def filter_debug_flags(opts, continuation=dispatch_ctu):
""" Filter out nondebug macros when requested. """
if opts.pop('force_debug'):
@@ -475,6 +715,7 @@ def arch_check(opts, continuation=language_check):
logging.debug('analysis, on default arch')
return continuation(opts)
+
# To have good results from static analyzer certain compiler options shall be
# omitted. The compiler flag filtering only affects the static analyzer run.
#
diff --git a/tools/scan-build-py/libscanbuild/arguments.py b/tools/scan-build-py/libscanbuild/arguments.py
index 2735123f9f16..a5d0c6bda661 100644
--- a/tools/scan-build-py/libscanbuild/arguments.py
+++ b/tools/scan-build-py/libscanbuild/arguments.py
@@ -18,8 +18,8 @@ import sys
import argparse
import logging
import tempfile
-from libscanbuild import reconfigure_logging
-from libscanbuild.clang import get_checkers
+from libscanbuild import reconfigure_logging, CtuConfig
+from libscanbuild.clang import get_checkers, is_ctu_capable
__all__ = ['parse_args_for_intercept_build', 'parse_args_for_analyze_build',
'parse_args_for_scan_build']
@@ -98,6 +98,11 @@ def normalize_args_for_analyze(args, from_build_command):
# add cdb parameter invisibly to make report module working.
args.cdb = 'compile_commands.json'
+ # Make ctu_dir an abspath as it is needed inside clang
+ if not from_build_command and hasattr(args, 'ctu_phases') \
+ and hasattr(args.ctu_phases, 'dir'):
+ args.ctu_dir = os.path.abspath(args.ctu_dir)
+
def validate_args_for_analyze(parser, args, from_build_command):
""" Command line parsing is done by the argparse module, but semantic
@@ -122,6 +127,18 @@ def validate_args_for_analyze(parser, args, from_build_command):
elif not from_build_command and not os.path.exists(args.cdb):
parser.error(message='compilation database is missing')
+ # If the user wants CTU mode
+ if not from_build_command and hasattr(args, 'ctu_phases') \
+ and hasattr(args.ctu_phases, 'dir'):
+ # If CTU analyze_only, the input directory should exist
+ if args.ctu_phases.analyze and not args.ctu_phases.collect \
+ and not os.path.exists(args.ctu_dir):
+ parser.error(message='missing CTU directory')
+ # Check CTU capability via checking clang-func-mapping
+ if not is_ctu_capable(args.func_map_cmd):
+ parser.error(message="""This version of clang does not support CTU
+ functionality or clang-func-mapping command not found.""")
+
def create_intercept_parser():
""" Creates a parser for command-line arguments to 'intercept'. """
@@ -218,7 +235,15 @@ def create_analyze_parser(from_build_command):
default='html',
action='store_const',
help="""Cause the results as a set of .html and .plist files.""")
- # TODO: implement '-view '
+ format_group.add_argument(
+ '--plist-multi-file',
+ '-plist-multi-file',
+ dest='output_format',
+ const='plist-multi-file',
+ default='html',
+ action='store_const',
+ help="""Cause the results as a set of .plist files with extra
+ information on related files.""")
advanced = parser.add_argument_group('advanced options')
advanced.add_argument(
@@ -256,7 +281,7 @@ def create_analyze_parser(from_build_command):
'-maxloop',
metavar='<loop count>',
type=int,
- help="""Specifiy the number of times a block can be visited before
+ help="""Specify the number of times a block can be visited before
giving up. Increase for more comprehensive coverage at a cost of
speed.""")
advanced.add_argument(
@@ -333,6 +358,51 @@ def create_analyze_parser(from_build_command):
if from_build_command:
parser.add_argument(
dest='build', nargs=argparse.REMAINDER, help="""Command to run.""")
+ else:
+ ctu = parser.add_argument_group('cross translation unit analysis')
+ ctu_mutex_group = ctu.add_mutually_exclusive_group()
+ ctu_mutex_group.add_argument(
+ '--ctu',
+ action='store_const',
+ const=CtuConfig(collect=True, analyze=True,
+ dir='', func_map_cmd=''),
+ dest='ctu_phases',
+ help="""Perform cross translation unit (ctu) analysis (both collect
+ and analyze phases) using default <ctu-dir> for temporary output.
+ At the end of the analysis, the temporary directory is removed.""")
+ ctu.add_argument(
+ '--ctu-dir',
+ metavar='<ctu-dir>',
+ dest='ctu_dir',
+ default='ctu-dir',
+ help="""Defines the temporary directory used between ctu
+ phases.""")
+ ctu_mutex_group.add_argument(
+ '--ctu-collect-only',
+ action='store_const',
+ const=CtuConfig(collect=True, analyze=False,
+ dir='', func_map_cmd=''),
+ dest='ctu_phases',
+ help="""Perform only the collect phase of ctu.
+ Keep <ctu-dir> for further use.""")
+ ctu_mutex_group.add_argument(
+ '--ctu-analyze-only',
+ action='store_const',
+ const=CtuConfig(collect=False, analyze=True,
+ dir='', func_map_cmd=''),
+ dest='ctu_phases',
+ help="""Perform only the analyze phase of ctu. <ctu-dir> should be
+ present and will not be removed after analysis.""")
+ ctu.add_argument(
+ '--use-func-map-cmd',
+ metavar='<path>',
+ dest='func_map_cmd',
+ default='clang-func-mapping',
+ help="""'%(prog)s' uses the 'clang-func-mapping' executable
+ relative to itself for generating function maps for static
+ analysis. One can override this behavior with this option by using
+ the 'clang-func-mapping' packaged with Xcode (on OS X) or from the
+ PATH.""")
return parser
diff --git a/tools/scan-build-py/libscanbuild/clang.py b/tools/scan-build-py/libscanbuild/clang.py
index 192e708782c1..ab422066cab1 100644
--- a/tools/scan-build-py/libscanbuild/clang.py
+++ b/tools/scan-build-py/libscanbuild/clang.py
@@ -8,11 +8,13 @@
Since Clang command line interface is so rich, but this project is using only
a subset of that, it makes sense to create a function specific wrapper. """
+import subprocess
import re
from libscanbuild import run_command
from libscanbuild.shell import decode
-__all__ = ['get_version', 'get_arguments', 'get_checkers']
+__all__ = ['get_version', 'get_arguments', 'get_checkers', 'is_ctu_capable',
+ 'get_triple_arch']
# regex for activated checker
ACTIVE_CHECKER_PATTERN = re.compile(r'^-analyzer-checker=(.*)$')
@@ -152,3 +154,26 @@ def get_checkers(clang, plugins):
raise Exception('Could not query Clang for available checkers.')
return checkers
+
+
+def is_ctu_capable(func_map_cmd):
+ """ Detects if the current (or given) clang and function mapping
+ executables are CTU compatible. """
+
+ try:
+ run_command([func_map_cmd, '-version'])
+ except (OSError, subprocess.CalledProcessError):
+ return False
+ return True
+
+
+def get_triple_arch(command, cwd):
+ """Returns the architecture part of the target triple for the given
+ compilation command. """
+
+ cmd = get_arguments(command, cwd)
+ try:
+ separator = cmd.index("-triple")
+ return cmd[separator + 1]
+ except (IndexError, ValueError):
+ return ""
diff --git a/tools/scan-build-py/libscanbuild/report.py b/tools/scan-build-py/libscanbuild/report.py
index 54b9695d927f..b3753c1d9d4e 100644
--- a/tools/scan-build-py/libscanbuild/report.py
+++ b/tools/scan-build-py/libscanbuild/report.py
@@ -13,7 +13,6 @@ import os
import os.path
import sys
import shutil
-import itertools
import plistlib
import glob
import json
@@ -255,24 +254,29 @@ def read_crashes(output_dir):
def read_bugs(output_dir, html):
+ # type: (str, bool) -> Generator[Dict[str, Any], None, None]
""" Generate a unique sequence of bugs from given output directory.
Duplicates can be in a project if the same module was compiled multiple
times with different compiler options. These would be better to show in
the final report (cover) only once. """
- parser = parse_bug_html if html else parse_bug_plist
- pattern = '*.html' if html else '*.plist'
+ def empty(file_name):
+ return os.stat(file_name).st_size == 0
duplicate = duplicate_check(
lambda bug: '{bug_line}.{bug_path_length}:{bug_file}'.format(**bug))
- bugs = itertools.chain.from_iterable(
- # parser creates a bug generator not the bug itself
- parser(filename)
- for filename in glob.iglob(os.path.join(output_dir, pattern)))
-
- return (bug for bug in bugs if not duplicate(bug))
+ # get the right parser for the job.
+ parser = parse_bug_html if html else parse_bug_plist
+ # get the input files, which are not empty.
+ pattern = os.path.join(output_dir, '*.html' if html else '*.plist')
+ bug_files = (file for file in glob.iglob(pattern) if not empty(file))
+
+ for bug_file in bug_files:
+ for bug in parser(bug_file):
+ if not duplicate(bug):
+ yield bug
def parse_bug_plist(filename):
diff --git a/tools/scan-build-py/tests/unit/test_analyze.py b/tools/scan-build-py/tests/unit/test_analyze.py
index a250ff22132c..9964a296b8dd 100644
--- a/tools/scan-build-py/tests/unit/test_analyze.py
+++ b/tools/scan-build-py/tests/unit/test_analyze.py
@@ -4,12 +4,12 @@
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
-import libear
-import libscanbuild.analyze as sut
import unittest
import re
import os
import os.path
+import libear
+import libscanbuild.analyze as sut
class ReportDirectoryTest(unittest.TestCase):
@@ -333,3 +333,83 @@ class RequireDecoratorTest(unittest.TestCase):
def test_method_exception_not_caught(self):
self.assertRaises(Exception, method_exception_from_inside, dict())
+
+
+class PrefixWithTest(unittest.TestCase):
+
+ def test_gives_empty_on_empty(self):
+ res = sut.prefix_with(0, [])
+ self.assertFalse(res)
+
+ def test_interleaves_prefix(self):
+ res = sut.prefix_with(0, [1, 2, 3])
+ self.assertListEqual([0, 1, 0, 2, 0, 3], res)
+
+
+class MergeCtuMapTest(unittest.TestCase):
+
+ def test_no_map_gives_empty(self):
+ pairs = sut.create_global_ctu_function_map([])
+ self.assertFalse(pairs)
+
+ def test_multiple_maps_merged(self):
+ concat_map = ['c:@F@fun1#I# ast/fun1.c.ast',
+ 'c:@F@fun2#I# ast/fun2.c.ast',
+ 'c:@F@fun3#I# ast/fun3.c.ast']
+ pairs = sut.create_global_ctu_function_map(concat_map)
+ self.assertTrue(('c:@F@fun1#I#', 'ast/fun1.c.ast') in pairs)
+ self.assertTrue(('c:@F@fun2#I#', 'ast/fun2.c.ast') in pairs)
+ self.assertTrue(('c:@F@fun3#I#', 'ast/fun3.c.ast') in pairs)
+ self.assertEqual(3, len(pairs))
+
+ def test_not_unique_func_left_out(self):
+ concat_map = ['c:@F@fun1#I# ast/fun1.c.ast',
+ 'c:@F@fun2#I# ast/fun2.c.ast',
+ 'c:@F@fun1#I# ast/fun7.c.ast']
+ pairs = sut.create_global_ctu_function_map(concat_map)
+ self.assertFalse(('c:@F@fun1#I#', 'ast/fun1.c.ast') in pairs)
+ self.assertFalse(('c:@F@fun1#I#', 'ast/fun7.c.ast') in pairs)
+ self.assertTrue(('c:@F@fun2#I#', 'ast/fun2.c.ast') in pairs)
+ self.assertEqual(1, len(pairs))
+
+ def test_duplicates_are_kept(self):
+ concat_map = ['c:@F@fun1#I# ast/fun1.c.ast',
+ 'c:@F@fun2#I# ast/fun2.c.ast',
+ 'c:@F@fun1#I# ast/fun1.c.ast']
+ pairs = sut.create_global_ctu_function_map(concat_map)
+ self.assertTrue(('c:@F@fun1#I#', 'ast/fun1.c.ast') in pairs)
+ self.assertTrue(('c:@F@fun2#I#', 'ast/fun2.c.ast') in pairs)
+ self.assertEqual(2, len(pairs))
+
+ def test_space_handled_in_source(self):
+ concat_map = ['c:@F@fun1#I# ast/f un.c.ast']
+ pairs = sut.create_global_ctu_function_map(concat_map)
+ self.assertTrue(('c:@F@fun1#I#', 'ast/f un.c.ast') in pairs)
+ self.assertEqual(1, len(pairs))
+
+
+class FuncMapSrcToAstTest(unittest.TestCase):
+
+ def test_empty_gives_empty(self):
+ fun_ast_lst = sut.func_map_list_src_to_ast([])
+ self.assertFalse(fun_ast_lst)
+
+ def test_sources_to_asts(self):
+ fun_src_lst = ['c:@F@f1#I# ' + os.path.join(os.sep + 'path', 'f1.c'),
+ 'c:@F@f2#I# ' + os.path.join(os.sep + 'path', 'f2.c')]
+ fun_ast_lst = sut.func_map_list_src_to_ast(fun_src_lst)
+ self.assertTrue('c:@F@f1#I# ' +
+ os.path.join('ast', 'path', 'f1.c.ast')
+ in fun_ast_lst)
+ self.assertTrue('c:@F@f2#I# ' +
+ os.path.join('ast', 'path', 'f2.c.ast')
+ in fun_ast_lst)
+ self.assertEqual(2, len(fun_ast_lst))
+
+ def test_spaces_handled(self):
+ fun_src_lst = ['c:@F@f1#I# ' + os.path.join(os.sep + 'path', 'f 1.c')]
+ fun_ast_lst = sut.func_map_list_src_to_ast(fun_src_lst)
+ self.assertTrue('c:@F@f1#I# ' +
+ os.path.join('ast', 'path', 'f 1.c.ast')
+ in fun_ast_lst)
+ self.assertEqual(1, len(fun_ast_lst))
diff --git a/tools/scan-build-py/tests/unit/test_clang.py b/tools/scan-build-py/tests/unit/test_clang.py
index eef8c26bbd19..07ac4d9fb806 100644
--- a/tools/scan-build-py/tests/unit/test_clang.py
+++ b/tools/scan-build-py/tests/unit/test_clang.py
@@ -92,3 +92,15 @@ class ClangGetCheckersTest(unittest.TestCase):
self.assertEqual('Checker One description', result.get('checker.one'))
self.assertTrue('checker.two' in result)
self.assertEqual('Checker Two description', result.get('checker.two'))
+
+
+class ClangIsCtuCapableTest(unittest.TestCase):
+ def test_ctu_not_found(self):
+ is_ctu = sut.is_ctu_capable('not-found-clang-func-mapping')
+ self.assertFalse(is_ctu)
+
+
+class ClangGetTripleArchTest(unittest.TestCase):
+ def test_arch_is_not_empty(self):
+ arch = sut.get_triple_arch(['clang', '-E', '-'], '.')
+ self.assertTrue(len(arch) > 0)
diff --git a/tools/scan-build/bin/scan-build b/tools/scan-build/bin/scan-build
index cbf3bf3d6f0b..c50f900cc45e 100755
--- a/tools/scan-build/bin/scan-build
+++ b/tools/scan-build/bin/scan-build
@@ -51,6 +51,7 @@ my %Options = (
OutputDir => undef, # Parent directory to store HTML files.
HtmlTitle => basename($CurrentDir)." - scan-build results",
IgnoreErrors => 0, # Ignore build errors.
+ KeepCC => 0, # Do not override CC and CXX make variables
ViewResults => 0, # View results when the build terminates.
ExitStatusFoundBugs => 0, # Exit status reflects whether bugs were found
ShowDescription => 0, # Display the description of the defect in the list
@@ -1012,7 +1013,7 @@ sub RunXcodebuild {
}
close(DETECT_XCODE);
- # If --override-compiler is explicitely requested, resort to the old
+ # If --override-compiler is explicitly requested, resort to the old
# behavior regardless of Xcode version.
if ($Options{OverrideCompiler}) {
$oldBehavior = 1;
@@ -1062,6 +1063,7 @@ sub RunXcodebuild {
sub RunBuildCommand {
my $Args = shift;
my $IgnoreErrors = shift;
+ my $KeepCC = shift;
my $Cmd = $Args->[0];
my $CCAnalyzer = shift;
my $CXXAnalyzer = shift;
@@ -1099,8 +1101,10 @@ sub RunBuildCommand {
unshift @$Args, $CXXAnalyzer;
}
elsif ($Cmd eq "make" or $Cmd eq "gmake" or $Cmd eq "mingw32-make") {
- AddIfNotPresent($Args, "CC=$CCAnalyzer");
- AddIfNotPresent($Args, "CXX=$CXXAnalyzer");
+ if (!$KeepCC) {
+ AddIfNotPresent($Args, "CC=$CCAnalyzer");
+ AddIfNotPresent($Args, "CXX=$CXXAnalyzer");
+ }
if ($IgnoreErrors) {
AddIfNotPresent($Args,"-k");
AddIfNotPresent($Args,"-i");
@@ -1158,6 +1162,12 @@ OPTIONS:
currently supports make and xcodebuild. This is a convenience option; one
can specify this behavior directly using build options.
+ --keep-cc
+
+ Do not override CC and CXX make variables. Useful when running make in
+ autoconf-based (and similar) projects where configure can add extra flags
+ to those variables.
+
--html-title [title]
--html-title=[title]
@@ -1236,7 +1246,7 @@ ADVANCED OPTIONS:
-maxloop <loop count>
- Specifiy the number of times a block can be visited before giving up.
+ Specify the number of times a block can be visited before giving up.
Default is 4. Increase for more comprehensive coverage at a cost of speed.
-internal-stats
@@ -1532,6 +1542,12 @@ sub ProcessArgs {
next;
}
+ if ($arg eq "--keep-cc") {
+ shift @$Args;
+ $Options{KeepCC} = 1;
+ next;
+ }
+
if ($arg =~ /^--use-cc(=(.+))?$/) {
shift @$Args;
my $cc;
@@ -1838,8 +1854,8 @@ my %EnvVars = (
);
# Run the build.
-my $ExitStatus = RunBuildCommand(\@ARGV, $Options{IgnoreErrors}, $Cmd, $CmdCXX,
- \%EnvVars);
+my $ExitStatus = RunBuildCommand(\@ARGV, $Options{IgnoreErrors}, $Options{KeepCC},
+ $Cmd, $CmdCXX, \%EnvVars);
if (defined $Options{OutputFormat}) {
if ($Options{OutputFormat} =~ /plist/) {
diff --git a/tools/scan-build/libexec/ccc-analyzer b/tools/scan-build/libexec/ccc-analyzer
index b0ec7e7e7487..73cd2ff3d915 100755
--- a/tools/scan-build/libexec/ccc-analyzer
+++ b/tools/scan-build/libexec/ccc-analyzer
@@ -419,7 +419,7 @@ my %LangMap = (
'cc' => 'c++',
'C' => 'c++',
'ii' => 'c++-cpp-output',
- 'i' => $IsCXX ? 'c++-cpp-output' : 'c-cpp-output',
+ 'i' => $IsCXX ? 'c++-cpp-output' : 'cpp-output',
'm' => 'objective-c',
'mi' => 'objective-c-cpp-output',
'mm' => 'objective-c++',
@@ -439,7 +439,7 @@ my %LangsAccepted = (
"c" => 1,
"c++" => 1,
"objective-c++" => 1,
- "c-cpp-output" => 1,
+ "cpp-output" => 1,
"objective-c-cpp-output" => 1,
"c++-cpp-output" => 1
);
diff --git a/tools/scan-build/man/scan-build.1 b/tools/scan-build/man/scan-build.1
index fd18d1f5c70a..3e3252e1b643 100644
--- a/tools/scan-build/man/scan-build.1
+++ b/tools/scan-build/man/scan-build.1
@@ -1,6 +1,6 @@
.\" This file is distributed under the University of Illinois Open Source
.\" License. See LICENSE.TXT for details.
-.\" $Id: scan-build.1 253074 2015-11-13 20:34:15Z jroelofs $
+.\" $Id: scan-build.1 329399 2018-04-06 15:14:32Z alexfh $
.Dd May 25, 2012
.Dt SCAN-BUILD 1
.Os "clang" "3.5"
@@ -116,7 +116,7 @@ model is used. Specifying
uses a simpler, less powerful constraint model used by checker-0.160
and earlier.
.It Fl maxloop Ar N
-Specifiy the number of times a block can be visited before giving
+Specify the number of times a block can be visited before giving
up. Default is 4. Increase for more comprehensive coverage at a
cost of speed.
.It Fl no-failure-reports
diff --git a/tools/scan-view/share/startfile.py b/tools/scan-view/share/startfile.py
index 673935909f82..f58dbeeaf817 100644
--- a/tools/scan-view/share/startfile.py
+++ b/tools/scan-view/share/startfile.py
@@ -62,7 +62,7 @@ class Controller(BaseController):
preexec_fn=setsid, startupinfo=startupinfo)
# It is assumed that this kind of tools (gnome-open, kfmclient,
- # exo-open, xdg-open and open for OSX) immediately exit after lauching
+ # exo-open, xdg-open and open for OSX) immediately exit after launching
# the specific application
returncode = pipe.wait()
if hasattr(self, 'fixreturncode'):
@@ -85,7 +85,7 @@ class Controller(BaseController):
if sys.platform[:3] == 'win':
class Start(BaseController):
- '''Controller for the win32 start progam through os.startfile.'''
+ '''Controller for the win32 start program through os.startfile.'''
def open(self, filename):
try:
@@ -201,6 +201,6 @@ else:
def open(filename):
- '''Open a file or an URL in the registered default application.'''
+ '''Open a file or a URL in the registered default application.'''
return _open(filename)
diff --git a/unittests/AST/ASTImporterTest.cpp b/unittests/AST/ASTImporterTest.cpp
index a6ec304ff1a1..21b76173c105 100644
--- a/unittests/AST/ASTImporterTest.cpp
+++ b/unittests/AST/ASTImporterTest.cpp
@@ -11,259 +11,604 @@
//
//===----------------------------------------------------------------------===//
+#include "MatchVerifier.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTImporter.h"
-#include "MatchVerifier.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Tooling/Tooling.h"
-#include "gtest/gtest.h"
+
+#include "DeclMatcher.h"
+#include "Language.h"
+#include "gmock/gmock.h"
+#include "llvm/ADT/StringMap.h"
namespace clang {
namespace ast_matchers {
-typedef std::vector<std::string> ArgVector;
-typedef std::vector<ArgVector> RunOptions;
-
-static bool isCXX(Language Lang) {
- return Lang == Lang_CXX || Lang == Lang_CXX11;
-}
-
-static RunOptions getRunOptionsForLanguage(Language Lang) {
- ArgVector BasicArgs;
- // Test with basic arguments.
- switch (Lang) {
- case Lang_C:
- BasicArgs = {"-x", "c", "-std=c99"};
- break;
- case Lang_C89:
- BasicArgs = {"-x", "c", "-std=c89"};
- break;
- case Lang_CXX:
- BasicArgs = {"-std=c++98"};
- break;
- case Lang_CXX11:
- BasicArgs = {"-std=c++11"};
- break;
- case Lang_OpenCL:
- case Lang_OBJCXX:
- llvm_unreachable("Not implemented yet!");
- }
-
- // For C++, test with "-fdelayed-template-parsing" enabled to handle MSVC
- // default behaviour.
- if (isCXX(Lang)) {
- ArgVector ArgsForDelayedTemplateParse = BasicArgs;
- ArgsForDelayedTemplateParse.emplace_back("-fdelayed-template-parsing");
- return {BasicArgs, ArgsForDelayedTemplateParse};
- }
-
- return {BasicArgs};
-}
-
-template<typename NodeType, typename MatcherType>
-testing::AssertionResult
-testImport(const std::string &FromCode, const ArgVector &FromArgs,
- const std::string &ToCode, const ArgVector &ToArgs,
- MatchVerifier<NodeType> &Verifier, const MatcherType &AMatcher) {
+using internal::Matcher;
+using internal::BindableMatcher;
+using llvm::StringMap;
+
+// Creates a virtual file and assigns that to the context of given AST. If the
+// file already exists then the file will not be created again as a duplicate.
+static void
+createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
+ std::unique_ptr<llvm::MemoryBuffer> &&Buffer) {
+ assert(ToAST);
+ ASTContext &ToCtx = ToAST->getASTContext();
+ auto *OFS = static_cast<vfs::OverlayFileSystem *>(
+ ToCtx.getSourceManager().getFileManager().getVirtualFileSystem().get());
+ auto *MFS =
+ static_cast<vfs::InMemoryFileSystem *>(OFS->overlays_begin()->get());
+ MFS->addFile(FileName, 0, std::move(Buffer));
+}
+
+static void createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
+ StringRef Code) {
+ return createVirtualFileIfNeeded(ToAST, FileName,
+ llvm::MemoryBuffer::getMemBuffer(Code));
+}
+
+const StringRef DeclToImportID = "declToImport";
+const StringRef DeclToVerifyID = "declToVerify";
+
+// Common base for the different families of ASTImporter tests that are
+// parameterized on the compiler options which may result a different AST. E.g.
+// -fms-compatibility or -fdelayed-template-parsing.
+struct ParameterizedTestsFixture : ::testing::TestWithParam<ArgVector> {
+
+ // Returns the argument vector used for a specific language option, this set
+ // can be tweaked by the test parameters.
+ ArgVector getArgVectorForLanguage(Language Lang) const {
+ ArgVector Args = getBasicRunOptionsForLanguage(Lang);
+ ArgVector ExtraArgs = GetParam();
+ for (const auto &Arg : ExtraArgs) {
+ Args.push_back(Arg);
+ }
+ return Args;
+ }
+
+};
+
+// Base class for those tests which use the family of `testImport` functions.
+class TestImportBase : public ParameterizedTestsFixture {
+
+ template <typename NodeType>
+ NodeType importNode(ASTUnit *From, ASTUnit *To, ASTImporter &Importer,
+ NodeType Node) {
+ ASTContext &ToCtx = To->getASTContext();
+
+ // Add 'From' file to virtual file system so importer can 'find' it
+ // while importing SourceLocations. It is safe to add same file multiple
+ // times - it just isn't replaced.
+ StringRef FromFileName = From->getMainFileName();
+ createVirtualFileIfNeeded(To, FromFileName,
+ From->getBufferForFile(FromFileName));
+
+ auto Imported = Importer.Import(Node);
+
+ // This should dump source locations and assert if some source locations
+ // were not imported.
+ SmallString<1024> ImportChecker;
+ llvm::raw_svector_ostream ToNothing(ImportChecker);
+ ToCtx.getTranslationUnitDecl()->print(ToNothing);
+
+ // This traverses the AST to catch certain bugs like poorly or not
+ // implemented subtrees.
+ Imported->dump(ToNothing);
+
+ return Imported;
+ }
+
+ template <typename NodeType>
+ testing::AssertionResult
+ testImport(const std::string &FromCode, const ArgVector &FromArgs,
+ const std::string &ToCode, const ArgVector &ToArgs,
+ MatchVerifier<NodeType> &Verifier,
+ const BindableMatcher<NodeType> &SearchMatcher,
+ const BindableMatcher<NodeType> &VerificationMatcher) {
+ const char *const InputFileName = "input.cc";
+ const char *const OutputFileName = "output.cc";
+
+ std::unique_ptr<ASTUnit> FromAST = tooling::buildASTFromCodeWithArgs(
+ FromCode, FromArgs, InputFileName),
+ ToAST = tooling::buildASTFromCodeWithArgs(
+ ToCode, ToArgs, OutputFileName);
+
+ ASTContext &FromCtx = FromAST->getASTContext(),
+ &ToCtx = ToAST->getASTContext();
+
+ ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx,
+ FromAST->getFileManager(), false);
+
+ auto FoundNodes = match(SearchMatcher, FromCtx);
+ if (FoundNodes.size() != 1)
+ return testing::AssertionFailure()
+ << "Multiple potential nodes were found!";
+
+ auto ToImport = selectFirst<NodeType>(DeclToImportID, FoundNodes);
+ if (!ToImport)
+ return testing::AssertionFailure() << "Node type mismatch!";
+
+ // Sanity check: the node being imported should match in the same way as
+ // the result node.
+ BindableMatcher<NodeType> WrapperMatcher(VerificationMatcher);
+ EXPECT_TRUE(Verifier.match(ToImport, WrapperMatcher));
+
+ auto Imported = importNode(FromAST.get(), ToAST.get(), Importer, ToImport);
+ if (!Imported)
+ return testing::AssertionFailure() << "Import failed, nullptr returned!";
+
+ return Verifier.match(Imported, WrapperMatcher);
+ }
+
+ template <typename NodeType>
+ testing::AssertionResult
+ testImport(const std::string &FromCode, const ArgVector &FromArgs,
+ const std::string &ToCode, const ArgVector &ToArgs,
+ MatchVerifier<NodeType> &Verifier,
+ const BindableMatcher<NodeType> &VerificationMatcher) {
+ return testImport(
+ FromCode, FromArgs, ToCode, ToArgs, Verifier,
+ translationUnitDecl(
+ has(namedDecl(hasName(DeclToImportID)).bind(DeclToImportID))),
+ VerificationMatcher);
+ }
+
+public:
+
+ /// Test how AST node named "declToImport" located in the translation unit
+ /// of "FromCode" virtual file is imported to "ToCode" virtual file.
+ /// The verification is done by running AMatcher over the imported node.
+ template <typename NodeType, typename MatcherType>
+ void testImport(const std::string &FromCode, Language FromLang,
+ const std::string &ToCode, Language ToLang,
+ MatchVerifier<NodeType> &Verifier,
+ const MatcherType &AMatcher) {
+ ArgVector FromArgs = getArgVectorForLanguage(FromLang),
+ ToArgs = getArgVectorForLanguage(ToLang);
+ EXPECT_TRUE(
+ testImport(FromCode, FromArgs, ToCode, ToArgs, Verifier, AMatcher));
+ }
+
+ struct ImportAction {
+ StringRef FromFilename;
+ StringRef ToFilename;
+ // FIXME: Generalize this to support other node kinds.
+ BindableMatcher<Decl> ImportPredicate;
+
+ ImportAction(StringRef FromFilename, StringRef ToFilename,
+ DeclarationMatcher ImportPredicate)
+ : FromFilename(FromFilename), ToFilename(ToFilename),
+ ImportPredicate(ImportPredicate) {}
+
+ ImportAction(StringRef FromFilename, StringRef ToFilename,
+ const std::string &DeclName)
+ : FromFilename(FromFilename), ToFilename(ToFilename),
+ ImportPredicate(namedDecl(hasName(DeclName))) {}
+ };
+
+ using SingleASTUnit = std::unique_ptr<ASTUnit>;
+ using AllASTUnits = StringMap<SingleASTUnit>;
+
+ struct CodeEntry {
+ std::string CodeSample;
+ Language Lang;
+ };
+
+ using CodeFiles = StringMap<CodeEntry>;
+
+ /// Builds an ASTUnit for one potential compile options set.
+ SingleASTUnit createASTUnit(StringRef FileName, const CodeEntry &CE) const {
+ ArgVector Args = getArgVectorForLanguage(CE.Lang);
+ auto AST = tooling::buildASTFromCodeWithArgs(CE.CodeSample, Args, FileName);
+ EXPECT_TRUE(AST.get());
+ return AST;
+ }
+
+ /// Test an arbitrary sequence of imports for a set of given in-memory files.
+ /// The verification is done by running VerificationMatcher against a
+ /// specified AST node inside of one of given files.
+ /// \param CodeSamples Map whose key is the file name and the value is the
+ /// file content.
+ /// \param ImportActions Sequence of imports. Each import in sequence
+ /// specifies "from file" and "to file" and a matcher that is used for
+ /// searching a declaration for import in "from file".
+ /// \param FileForFinalCheck Name of virtual file for which the final check is
+ /// applied.
+ /// \param FinalSelectPredicate Matcher that specifies the AST node in the
+ /// FileForFinalCheck for which the verification will be done.
+ /// \param VerificationMatcher Matcher that will be used for verification
+ /// after all imports in sequence are done.
+ void testImportSequence(const CodeFiles &CodeSamples,
+ const std::vector<ImportAction> &ImportActions,
+ StringRef FileForFinalCheck,
+ BindableMatcher<Decl> FinalSelectPredicate,
+ BindableMatcher<Decl> VerificationMatcher) {
+ AllASTUnits AllASTs;
+ using ImporterKey = std::pair<const ASTUnit *, const ASTUnit *>;
+ llvm::DenseMap<ImporterKey, std::unique_ptr<ASTImporter>> Importers;
+
+ auto GenASTsIfNeeded = [this, &AllASTs, &CodeSamples](StringRef Filename) {
+ if (!AllASTs.count(Filename)) {
+ auto Found = CodeSamples.find(Filename);
+ assert(Found != CodeSamples.end() && "Wrong file for import!");
+ AllASTs[Filename] = createASTUnit(Filename, Found->getValue());
+ }
+ };
+
+ for (const ImportAction &Action : ImportActions) {
+ StringRef FromFile = Action.FromFilename, ToFile = Action.ToFilename;
+ GenASTsIfNeeded(FromFile);
+ GenASTsIfNeeded(ToFile);
+
+ ASTUnit *From = AllASTs[FromFile].get();
+ ASTUnit *To = AllASTs[ToFile].get();
+
+ // Create a new importer if needed.
+ std::unique_ptr<ASTImporter> &ImporterRef = Importers[{From, To}];
+ if (!ImporterRef)
+ ImporterRef.reset(new ASTImporter(
+ To->getASTContext(), To->getFileManager(), From->getASTContext(),
+ From->getFileManager(), false));
+
+ // Find the declaration and import it.
+ auto FoundDecl = match(Action.ImportPredicate.bind(DeclToImportID),
+ From->getASTContext());
+ EXPECT_TRUE(FoundDecl.size() == 1);
+ const Decl *ToImport = selectFirst<Decl>(DeclToImportID, FoundDecl);
+ auto Imported = importNode(From, To, *ImporterRef, ToImport);
+ EXPECT_TRUE(Imported);
+ }
+
+ // Find the declaration and import it.
+ auto FoundDecl = match(FinalSelectPredicate.bind(DeclToVerifyID),
+ AllASTs[FileForFinalCheck]->getASTContext());
+ EXPECT_TRUE(FoundDecl.size() == 1);
+ const Decl *ToVerify = selectFirst<Decl>(DeclToVerifyID, FoundDecl);
+ MatchVerifier<Decl> Verifier;
+ EXPECT_TRUE(
+ Verifier.match(ToVerify, BindableMatcher<Decl>(VerificationMatcher)));
+ }
+};
+
+template <typename T> RecordDecl *getRecordDecl(T *D) {
+ auto *ET = cast<ElaboratedType>(D->getType().getTypePtr());
+ return cast<RecordType>(ET->getNamedType().getTypePtr())->getDecl();
+}
+
+// This class provides generic methods to write tests which can check internal
+// attributes of AST nodes like getPreviousDecl(), isVirtual(), etc. Also,
+// this fixture makes it possible to import from several "From" contexts.
+class ASTImporterTestBase : public ParameterizedTestsFixture {
+
const char *const InputFileName = "input.cc";
const char *const OutputFileName = "output.cc";
- std::unique_ptr<ASTUnit>
- FromAST = tooling::buildASTFromCodeWithArgs(
- FromCode, FromArgs, InputFileName),
- ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
-
- ASTContext &FromCtx = FromAST->getASTContext(),
- &ToCtx = ToAST->getASTContext();
-
- // Add input.cc to virtual file system so importer can 'find' it
- // while importing SourceLocations.
- vfs::OverlayFileSystem *OFS = static_cast<vfs::OverlayFileSystem *>(
- ToCtx.getSourceManager().getFileManager().getVirtualFileSystem().get());
- vfs::InMemoryFileSystem *MFS = static_cast<vfs::InMemoryFileSystem *>(
- OFS->overlays_begin()->get());
- MFS->addFile(InputFileName, 0, llvm::MemoryBuffer::getMemBuffer(FromCode));
-
- ASTImporter Importer(ToCtx, ToAST->getFileManager(),
- FromCtx, FromAST->getFileManager(), false);
-
- IdentifierInfo *ImportedII = &FromCtx.Idents.get("declToImport");
- assert(ImportedII && "Declaration with 'declToImport' name"
- "should be specified in test!");
- DeclarationName ImportDeclName(ImportedII);
- SmallVector<NamedDecl *, 4> FoundDecls;
- FromCtx.getTranslationUnitDecl()->localUncachedLookup(
- ImportDeclName, FoundDecls);
-
- if (FoundDecls.size() != 1)
- return testing::AssertionFailure() << "Multiple declarations were found!";
-
- auto Imported = Importer.Import(*FoundDecls.begin());
- if (!Imported)
- return testing::AssertionFailure() << "Import failed, nullptr returned!";
-
- // This should dump source locations and assert if some source locations
- // were not imported.
- SmallString<1024> ImportChecker;
- llvm::raw_svector_ostream ToNothing(ImportChecker);
- ToCtx.getTranslationUnitDecl()->print(ToNothing);
-
- // This traverses the AST to catch certain bugs like poorly or not
- // implemented subtrees.
- Imported->dump(ToNothing);
-
- return Verifier.match(Imported, AMatcher);
-}
-
-template<typename NodeType, typename MatcherType>
-void testImport(const std::string &FromCode, Language FromLang,
- const std::string &ToCode, Language ToLang,
- MatchVerifier<NodeType> &Verifier,
- const MatcherType &AMatcher) {
- auto RunOptsFrom = getRunOptionsForLanguage(FromLang);
- auto RunOptsTo = getRunOptionsForLanguage(ToLang);
- for (const auto &FromArgs : RunOptsFrom)
- for (const auto &ToArgs : RunOptsTo)
- EXPECT_TRUE(testImport(FromCode, FromArgs, ToCode, ToArgs,
- Verifier, AMatcher));
-}
-
-
-TEST(ImportExpr, ImportStringLiteral) {
- MatchVerifier<Decl> Verifier;
- testImport("void declToImport() { \"foo\"; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- stringLiteral(
- hasType(
- asString("const char [4]"))))))));
- testImport("void declToImport() { L\"foo\"; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- stringLiteral(
- hasType(
- asString("const wchar_t [4]"))))))));
- testImport("void declToImport() { \"foo\" \"bar\"; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- stringLiteral(
- hasType(
- asString("const char [7]"))))))));
-}
-
-TEST(ImportExpr, ImportGNUNullExpr) {
- MatchVerifier<Decl> Verifier;
- testImport("void declToImport() { __null; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- gnuNullExpr(
- hasType(isInteger())))))));
-}
-
-TEST(ImportExpr, ImportCXXNullPtrLiteralExpr) {
- MatchVerifier<Decl> Verifier;
- testImport("void declToImport() { nullptr; }",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- cxxNullPtrLiteralExpr())))));
+ // Buffer for the To context, must live in the test scope.
+ std::string ToCode;
+
+ // Represents a "From" translation unit and holds an importer object which we
+ // use to import from this translation unit.
+ struct TU {
+ // Buffer for the context, must live in the test scope.
+ std::string Code;
+ std::string FileName;
+ std::unique_ptr<ASTUnit> Unit;
+ TranslationUnitDecl *TUDecl = nullptr;
+ std::unique_ptr<ASTImporter> Importer;
+ TU(StringRef Code, StringRef FileName, ArgVector Args)
+ : Code(Code), FileName(FileName),
+ Unit(tooling::buildASTFromCodeWithArgs(this->Code, Args,
+ this->FileName)),
+ TUDecl(Unit->getASTContext().getTranslationUnitDecl()) {
+ Unit->enableSourceFileDiagnostics();
+ }
+
+ void lazyInitImporter(ASTUnit *ToAST) {
+ assert(ToAST);
+ if (!Importer) {
+ Importer.reset(new ASTImporter(
+ ToAST->getASTContext(), ToAST->getFileManager(),
+ Unit->getASTContext(), Unit->getFileManager(), false));
+ }
+ assert(&ToAST->getASTContext() == &Importer->getToContext());
+ createVirtualFileIfNeeded(ToAST, FileName, Code);
+ }
+
+ Decl *import(ASTUnit *ToAST, Decl *FromDecl) {
+ lazyInitImporter(ToAST);
+ return Importer->Import(FromDecl);
+ }
+
+ QualType import(ASTUnit *ToAST, QualType FromType) {
+ lazyInitImporter(ToAST);
+ return Importer->Import(FromType);
+ }
+ };
+
+ // We may have several From contexts and related translation units. In each
+ // AST, the buffers for the source are handled via references and are set
+ // during the creation of the AST. These references must point to a valid
+ // buffer until the AST is alive. Thus, we must use a list in order to avoid
+ // moving of the stored objects because that would mean breaking the
+ // references in the AST. By using a vector a move could happen when the
+ // vector is expanding, with the list we won't have these issues.
+ std::list<TU> FromTUs;
+
+ void lazyInitToAST(Language ToLang) {
+ if (ToAST)
+ return;
+ ArgVector ToArgs = getArgVectorForLanguage(ToLang);
+ // Build the AST from an empty file.
+ ToAST = tooling::buildASTFromCodeWithArgs(/*Code=*/"", ToArgs, "empty.cc");
+ ToAST->enableSourceFileDiagnostics();
+ }
+
+ TU *findFromTU(Decl *From) {
+ // Create a virtual file in the To Ctx which corresponds to the file from
+ // which we want to import the `From` Decl. Without this source locations
+ // will be invalid in the ToCtx.
+ auto It = std::find_if(FromTUs.begin(), FromTUs.end(), [From](const TU &E) {
+ return E.TUDecl == From->getTranslationUnitDecl();
+ });
+ assert(It != FromTUs.end());
+ return &*It;
+ }
+
+public:
+ // We may have several From context but only one To context.
+ std::unique_ptr<ASTUnit> ToAST;
+
+ // Creates an AST both for the From and To source code and imports the Decl
+ // of the identifier into the To context.
+ // Must not be called more than once within the same test.
+ std::tuple<Decl *, Decl *>
+ getImportedDecl(StringRef FromSrcCode, Language FromLang, StringRef ToSrcCode,
+ Language ToLang, StringRef Identifier = DeclToImportID) {
+ ArgVector FromArgs = getArgVectorForLanguage(FromLang),
+ ToArgs = getArgVectorForLanguage(ToLang);
+
+ FromTUs.emplace_back(FromSrcCode, InputFileName, FromArgs);
+ TU &FromTU = FromTUs.back();
+
+ ToCode = ToSrcCode;
+ assert(!ToAST);
+ ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
+ ToAST->enableSourceFileDiagnostics();
+
+ ASTContext &FromCtx = FromTU.Unit->getASTContext();
+
+ createVirtualFileIfNeeded(ToAST.get(), InputFileName, FromTU.Code);
+
+ IdentifierInfo *ImportedII = &FromCtx.Idents.get(Identifier);
+ assert(ImportedII && "Declaration with the given identifier "
+ "should be specified in test!");
+ DeclarationName ImportDeclName(ImportedII);
+ SmallVector<NamedDecl *, 4> FoundDecls;
+ FromCtx.getTranslationUnitDecl()->localUncachedLookup(ImportDeclName,
+ FoundDecls);
+
+ assert(FoundDecls.size() == 1);
+
+ Decl *Imported = FromTU.import(ToAST.get(), FoundDecls.front());
+
+ assert(Imported);
+ return std::make_tuple(*FoundDecls.begin(), Imported);
+ }
+
+ // Creates a TU decl for the given source code which can be used as a From
+ // context. May be called several times in a given test (with different file
+ // name).
+ TranslationUnitDecl *getTuDecl(StringRef SrcCode, Language Lang,
+ StringRef FileName = "input.cc") {
+ assert(
+ std::find_if(FromTUs.begin(), FromTUs.end(), [FileName](const TU &E) {
+ return E.FileName == FileName;
+ }) == FromTUs.end());
+
+ ArgVector Args = getArgVectorForLanguage(Lang);
+ FromTUs.emplace_back(SrcCode, FileName, Args);
+ TU &Tu = FromTUs.back();
+
+ return Tu.TUDecl;
+ }
+
+ // Creates the To context with the given source code and returns the TU decl.
+ TranslationUnitDecl *getToTuDecl(StringRef ToSrcCode, Language ToLang) {
+ ArgVector ToArgs = getArgVectorForLanguage(ToLang);
+ ToCode = ToSrcCode;
+ assert(!ToAST);
+ ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
+ ToAST->enableSourceFileDiagnostics();
+
+ return ToAST->getASTContext().getTranslationUnitDecl();
+ }
+
+ // Import the given Decl into the ToCtx.
+ // May be called several times in a given test.
+ // The different instances of the param From may have different ASTContext.
+ Decl *Import(Decl *From, Language ToLang) {
+ lazyInitToAST(ToLang);
+ TU *FromTU = findFromTU(From);
+ return FromTU->import(ToAST.get(), From);
+ }
+
+ QualType ImportType(QualType FromType, Decl *TUDecl, Language ToLang) {
+ lazyInitToAST(ToLang);
+ TU *FromTU = findFromTU(TUDecl);
+ return FromTU->import(ToAST.get(), FromType);
+ }
+
+ ~ASTImporterTestBase() {
+ if (!::testing::Test::HasFailure()) return;
+
+ for (auto &Tu : FromTUs) {
+ assert(Tu.Unit);
+ llvm::errs() << "FromAST:\n";
+ Tu.Unit->getASTContext().getTranslationUnitDecl()->dump();
+ llvm::errs() << "\n";
+ }
+ if (ToAST) {
+ llvm::errs() << "ToAST:\n";
+ ToAST->getASTContext().getTranslationUnitDecl()->dump();
+ }
+ }
+};
+
+struct ImportExpr : TestImportBase {};
+struct ImportType : TestImportBase {};
+struct ImportDecl : TestImportBase {};
+
+struct CanonicalRedeclChain : ASTImporterTestBase {};
+
+TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers) {
+ Decl *FromTU = getTuDecl("void f();", Lang_CXX);
+ auto Pattern = functionDecl(hasName("f"));
+ auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+
+ auto Redecls = getCanonicalForwardRedeclChain(D0);
+ ASSERT_EQ(Redecls.size(), 1u);
+ EXPECT_EQ(D0, Redecls[0]);
}
+TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers2) {
+ Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
+ auto Pattern = functionDecl(hasName("f"));
+ auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+ auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+ FunctionDecl *D1 = D2->getPreviousDecl();
-TEST(ImportExpr, ImportFloatinglLiteralExpr) {
+ auto Redecls = getCanonicalForwardRedeclChain(D0);
+ ASSERT_EQ(Redecls.size(), 3u);
+ EXPECT_EQ(D0, Redecls[0]);
+ EXPECT_EQ(D1, Redecls[1]);
+ EXPECT_EQ(D2, Redecls[2]);
+}
+
+TEST_P(CanonicalRedeclChain, ShouldBeSameForAllDeclInTheChain) {
+ Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
+ auto Pattern = functionDecl(hasName("f"));
+ auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+ auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+ FunctionDecl *D1 = D2->getPreviousDecl();
+
+ auto RedeclsD0 = getCanonicalForwardRedeclChain(D0);
+ auto RedeclsD1 = getCanonicalForwardRedeclChain(D1);
+ auto RedeclsD2 = getCanonicalForwardRedeclChain(D2);
+
+ EXPECT_THAT(RedeclsD0, ::testing::ContainerEq(RedeclsD1));
+ EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2));
+}
+
+
+TEST_P(ImportExpr, ImportStringLiteral) {
MatchVerifier<Decl> Verifier;
- testImport("void declToImport() { 1.0; }",
- Lang_C, "", Lang_C, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- floatLiteral(
- equals(1.0),
- hasType(asString("double"))))))));
- testImport("void declToImport() { 1.0e-5f; }",
- Lang_C, "", Lang_C, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- floatLiteral(
- equals(1.0e-5f),
- hasType(asString("float"))))))));
-}
-
-TEST(ImportExpr, ImportCompoundLiteralExpr) {
- MatchVerifier<Decl> Verifier;
- testImport("void declToImport() {"
- " struct s { int x; long y; unsigned z; }; "
- " (struct s){ 42, 0L, 1U }; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- compoundLiteralExpr(
- hasType(asString("struct s")),
- has(initListExpr(
- hasType(asString("struct s")),
- has(integerLiteral(
- equals(42), hasType(asString("int")))),
- has(integerLiteral(
- equals(0), hasType(asString("long")))),
- has(integerLiteral(
- equals(1),
- hasType(asString("unsigned int"))))
- ))))))));
-}
-
-TEST(ImportExpr, ImportCXXThisExpr) {
- MatchVerifier<Decl> Verifier;
- testImport("class declToImport { void f() { this; } };",
- Lang_CXX, "", Lang_CXX, Verifier,
- cxxRecordDecl(
- hasMethod(
- hasBody(
- compoundStmt(
- has(
- cxxThisExpr(
- hasType(
- asString("class declToImport *")))))))));
-}
-
-TEST(ImportExpr, ImportAtomicExpr) {
- MatchVerifier<Decl> Verifier;
- testImport("void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
- Lang_C, "", Lang_C, Verifier,
- functionDecl(hasBody(compoundStmt(has(atomicExpr(
- has(ignoringParenImpCasts(
- declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
- hasType(asString("int *"))))),
- has(integerLiteral(equals(1), hasType(asString("int"))))))))));
+ testImport(
+ "void declToImport() { (void)\"foo\"; }",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ functionDecl(hasDescendant(
+ stringLiteral(hasType(asString("const char [4]"))))));
+ testImport(
+ "void declToImport() { (void)L\"foo\"; }",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ functionDecl(hasDescendant(
+ stringLiteral(hasType(asString("const wchar_t [4]"))))));
+ testImport(
+ "void declToImport() { (void) \"foo\" \"bar\"; }",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ functionDecl(hasDescendant(
+ stringLiteral(hasType(asString("const char [7]"))))));
}
-TEST(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
+TEST_P(ImportExpr, ImportGNUNullExpr) {
MatchVerifier<Decl> Verifier;
testImport(
- "void declToImport() { loop: goto loop; &&loop; }", Lang_C, "", Lang_C,
- Verifier,
- functionDecl(hasBody(compoundStmt(
- has(labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
- has(addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))))));
+ "void declToImport() { (void)__null; }",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ functionDecl(hasDescendant(gnuNullExpr(hasType(isInteger())))));
+}
+
+TEST_P(ImportExpr, ImportCXXNullPtrLiteralExpr) {
+ MatchVerifier<Decl> Verifier;
+ testImport(
+ "void declToImport() { (void)nullptr; }",
+ Lang_CXX11, "", Lang_CXX11, Verifier,
+ functionDecl(hasDescendant(cxxNullPtrLiteralExpr())));
+}
+
+
+TEST_P(ImportExpr, ImportFloatinglLiteralExpr) {
+ MatchVerifier<Decl> Verifier;
+ testImport(
+ "void declToImport() { (void)1.0; }",
+ Lang_C, "", Lang_C, Verifier,
+ functionDecl(hasDescendant(
+ floatLiteral(equals(1.0), hasType(asString("double"))))));
+ testImport(
+ "void declToImport() { (void)1.0e-5f; }",
+ Lang_C, "", Lang_C, Verifier,
+ functionDecl(hasDescendant(
+ floatLiteral(equals(1.0e-5f), hasType(asString("float"))))));
+}
+
+TEST_P(ImportExpr, ImportCompoundLiteralExpr) {
+ MatchVerifier<Decl> Verifier;
+ testImport(
+ "void declToImport() {"
+ " struct s { int x; long y; unsigned z; }; "
+ " (void)(struct s){ 42, 0L, 1U }; }",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ functionDecl(hasDescendant(
+ compoundLiteralExpr(
+ hasType(asString("struct s")),
+ has(initListExpr(
+ hasType(asString("struct s")),
+ has(integerLiteral(
+ equals(42), hasType(asString("int")))),
+ has(integerLiteral(
+ equals(0), hasType(asString("long")))),
+ has(integerLiteral(
+ equals(1), hasType(asString("unsigned int"))))))))));
+}
+
+TEST_P(ImportExpr, ImportCXXThisExpr) {
+ MatchVerifier<Decl> Verifier;
+ testImport(
+ "class declToImport { void f() { (void)this; } };",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ cxxRecordDecl(
+ hasMethod(
+ hasDescendant(
+ cxxThisExpr(
+ hasType(
+ asString("class declToImport *")))))));
+}
+
+TEST_P(ImportExpr, ImportAtomicExpr) {
+ MatchVerifier<Decl> Verifier;
+ testImport(
+ "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
+ Lang_C, "", Lang_C, Verifier,
+ functionDecl(hasDescendant(
+ atomicExpr(
+ has(ignoringParenImpCasts(
+ declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
+ hasType(asString("int *"))))),
+ has(integerLiteral(equals(1), hasType(asString("int"))))))));
+}
+
+TEST_P(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
+ MatchVerifier<Decl> Verifier;
+ testImport(
+ "void declToImport() { loop: goto loop; (void)&&loop; }",
+ Lang_C, "", Lang_C, Verifier,
+ functionDecl(
+ hasDescendant(
+ labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
+ hasDescendant(
+ addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))));
}
AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
@@ -272,7 +617,7 @@ AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
return Template && InnerMatcher.matches(*Template, Finder, Builder);
}
-TEST(ImportExpr, ImportParenListExpr) {
+TEST_P(ImportExpr, ImportParenListExpr) {
MatchVerifier<Decl> Verifier;
testImport(
"template<typename T> class dummy { void f() { dummy X(*this); } };"
@@ -289,279 +634,290 @@ TEST(ImportExpr, ImportParenListExpr) {
hasUnaryOperand(cxxThisExpr())))))))))))))))))))))));
}
-TEST(ImportExpr, ImportSwitch) {
+TEST_P(ImportExpr, ImportSwitch) {
MatchVerifier<Decl> Verifier;
- testImport("void declToImport() { int b; switch (b) { case 1: break; } }",
- Lang_C, "", Lang_C, Verifier,
- functionDecl(hasBody(compoundStmt(
- has(switchStmt(has(compoundStmt(has(caseStmt())))))))));
+ testImport(
+ "void declToImport() { int b; switch (b) { case 1: break; } }",
+ Lang_C, "", Lang_C, Verifier,
+ functionDecl(hasDescendant(
+ switchStmt(has(compoundStmt(has(caseStmt())))))));
}
-TEST(ImportExpr, ImportStmtExpr) {
+TEST_P(ImportExpr, ImportStmtExpr) {
MatchVerifier<Decl> Verifier;
// NOTE: has() ignores implicit casts, using hasDescendant() to match it
testImport(
"void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
Lang_C, "", Lang_C, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- declStmt(
- hasSingleDecl(
- varDecl(
- hasName("C"),
- hasType(asString("int")),
- hasInitializer(
- stmtExpr(
- hasAnySubstatement(
- declStmt(
- hasSingleDecl(
- varDecl(
- hasName("X"),
- hasType(asString("int")),
- hasInitializer(
+ functionDecl(hasDescendant(
+ varDecl(
+ hasName("C"),
+ hasType(asString("int")),
+ hasInitializer(
+ stmtExpr(
+ hasAnySubstatement(declStmt(hasSingleDecl(
+ varDecl(
+ hasName("X"),
+ hasType(asString("int")),
+ hasInitializer(
integerLiteral(equals(4))))))),
- hasDescendant(
- implicitCastExpr()
- )))))))))));
+ hasDescendant(
+ implicitCastExpr())))))));
}
-TEST(ImportExpr, ImportConditionalOperator) {
+TEST_P(ImportExpr, ImportConditionalOperator) {
MatchVerifier<Decl> Verifier;
testImport(
- "void declToImport() { true ? 1 : -5; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- conditionalOperator(
+ "void declToImport() { (void)(true ? 1 : -5); }",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ functionDecl(hasDescendant(
+ conditionalOperator(
hasCondition(cxxBoolLiteral(equals(true))),
hasTrueExpression(integerLiteral(equals(1))),
hasFalseExpression(
- unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))
- )))))));
+ unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))))
+ )));
}
-TEST(ImportExpr, ImportBinaryConditionalOperator) {
+TEST_P(ImportExpr, ImportBinaryConditionalOperator) {
MatchVerifier<Decl> Verifier;
testImport(
- "void declToImport() { 1 ?: -5; }", Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- binaryConditionalOperator(
+ "void declToImport() { (void)(1 ?: -5); }",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ functionDecl(hasDescendant(
+ binaryConditionalOperator(
hasCondition(
- implicitCastExpr(
- hasSourceExpression(
- opaqueValueExpr(
- hasSourceExpression(integerLiteral(equals(1))))),
- hasType(booleanType()))),
+ implicitCastExpr(
+ hasSourceExpression(opaqueValueExpr(
+ hasSourceExpression(integerLiteral(equals(1))))),
+ hasType(booleanType()))),
hasTrueExpression(
- opaqueValueExpr(hasSourceExpression(
- integerLiteral(equals(1))))),
+ opaqueValueExpr(
+ hasSourceExpression(integerLiteral(equals(1))))),
hasFalseExpression(
- unaryOperator(hasOperatorName("-"),
- hasUnaryOperand(integerLiteral(equals(5)))))
- ))))));
+ unaryOperator(
+ hasOperatorName("-"),
+ hasUnaryOperand(integerLiteral(equals(5)))))))));
}
-TEST(ImportExpr, ImportDesignatedInitExpr) {
+TEST_P(ImportExpr, ImportDesignatedInitExpr) {
MatchVerifier<Decl> Verifier;
- testImport("void declToImport() {"
- " struct point { double x; double y; };"
- " struct point ptarray[10] = "
- "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
- Lang_C, "", Lang_C, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- declStmt(
- hasSingleDecl(
- varDecl(
- hasInitializer(
- initListExpr(
- hasSyntacticForm(
- initListExpr(
- has(
- designatedInitExpr(
- designatorCountIs(2),
- has(floatLiteral(
- equals(1.0))),
- has(integerLiteral(
- equals(2))))),
- has(
- designatedInitExpr(
- designatorCountIs(2),
- has(floatLiteral(
- equals(2.0))),
- has(integerLiteral(
- equals(2))))),
- has(
- designatedInitExpr(
- designatorCountIs(2),
- has(floatLiteral(
- equals(1.0))),
- has(integerLiteral(
- equals(0)))))
- ))))))))))));
-}
-
-
-TEST(ImportExpr, ImportPredefinedExpr) {
+ testImport(
+ "void declToImport() {"
+ " struct point { double x; double y; };"
+ " struct point ptarray[10] = "
+ "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
+ Lang_C, "", Lang_C, Verifier,
+ functionDecl(hasDescendant(
+ initListExpr(
+ has(designatedInitExpr(
+ designatorCountIs(2),
+ has(floatLiteral(equals(1.0))),
+ has(integerLiteral(equals(2))))),
+ has(designatedInitExpr(
+ designatorCountIs(2),
+ has(floatLiteral(equals(2.0))),
+ has(integerLiteral(equals(2))))),
+ has(designatedInitExpr(
+ designatorCountIs(2),
+ has(floatLiteral(equals(1.0))),
+ has(integerLiteral(equals(0)))))))));
+}
+
+
+TEST_P(ImportExpr, ImportPredefinedExpr) {
MatchVerifier<Decl> Verifier;
// __func__ expands as StringLiteral("declToImport")
- testImport("void declToImport() { __func__; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- predefinedExpr(
- hasType(
- asString("const char [13]")),
- has(
- stringLiteral(
- hasType(
- asString("const char [13]"))))))))));
-}
-
-TEST(ImportExpr, ImportInitListExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "void declToImport() {"
- " struct point { double x; double y; };"
- " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
- " [0].x = 1.0 }; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- declStmt(
- hasSingleDecl(
- varDecl(
- hasInitializer(
- initListExpr(
- has(
- cxxConstructExpr(
- requiresZeroInitialization())),
- has(
- initListExpr(
- hasType(asString("struct point")),
- has(floatLiteral(equals(1.0))),
- has(implicitValueInitExpr(
- hasType(asString("double")))))),
- has(
- initListExpr(
- hasType(asString("struct point")),
- has(floatLiteral(equals(2.0))),
- has(floatLiteral(equals(1.0)))))
- ))))))))));
+ testImport(
+ "void declToImport() { (void)__func__; }",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ functionDecl(hasDescendant(
+ predefinedExpr(
+ hasType(
+ asString("const char [13]")),
+ has(stringLiteral(hasType(
+ asString("const char [13]"))))))));
+}
+
+TEST_P(ImportExpr, ImportInitListExpr) {
+ MatchVerifier<Decl> Verifier;
+ testImport(
+ "void declToImport() {"
+ " struct point { double x; double y; };"
+ " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
+ " [0].x = 1.0 }; }",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ functionDecl(hasDescendant(
+ initListExpr(
+ has(
+ cxxConstructExpr(
+ requiresZeroInitialization())),
+ has(
+ initListExpr(
+ hasType(asString("struct point")),
+ has(floatLiteral(equals(1.0))),
+ has(implicitValueInitExpr(
+ hasType(asString("double")))))),
+ has(
+ initListExpr(
+ hasType(asString("struct point")),
+ has(floatLiteral(equals(2.0))),
+ has(floatLiteral(equals(1.0)))))))));
}
const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
-TEST(ImportExpr, ImportVAArgExpr) {
+TEST_P(ImportExpr, ImportVAArgExpr) {
MatchVerifier<Decl> Verifier;
- testImport("void declToImport(__builtin_va_list list, ...) {"
- " (void)__builtin_va_arg(list, int); }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- cStyleCastExpr(
- hasSourceExpression(
- vaArgExpr())))))));
+ testImport(
+ "void declToImport(__builtin_va_list list, ...) {"
+ " (void)__builtin_va_arg(list, int); }",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ functionDecl(hasDescendant(
+ cStyleCastExpr(hasSourceExpression(vaArgExpr())))));
}
+TEST_P(ImportExpr, CXXTemporaryObjectExpr) {
+ MatchVerifier<Decl> Verifier;
+ testImport(
+ "struct C {};"
+ "void declToImport() { C c = C(); }",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ functionDecl(hasDescendant(
+ exprWithCleanups(has(cxxConstructExpr(
+ has(materializeTemporaryExpr(has(implicitCastExpr(
+ has(cxxTemporaryObjectExpr())))))))))));
+}
-TEST(ImportType, ImportAtomicType) {
+TEST_P(ImportType, ImportAtomicType) {
MatchVerifier<Decl> Verifier;
- testImport("void declToImport() { typedef _Atomic(int) a_int; }",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- declStmt(
- has(
- typedefDecl(
- has(atomicType())))))))));
+ testImport(
+ "void declToImport() { typedef _Atomic(int) a_int; }",
+ Lang_CXX11, "", Lang_CXX11, Verifier,
+ functionDecl(hasDescendant(typedefDecl(has(atomicType())))));
}
-TEST(ImportDecl, ImportFunctionTemplateDecl) {
+TEST_P(ImportDecl, ImportFunctionTemplateDecl) {
MatchVerifier<Decl> Verifier;
- testImport("template <typename T> void declToImport() { };", Lang_CXX, "",
- Lang_CXX, Verifier, functionTemplateDecl());
+ testImport(
+ "template <typename T> void declToImport() { };",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ functionTemplateDecl());
}
const internal::VariadicDynCastAllOfMatcher<Expr, CXXDependentScopeMemberExpr>
cxxDependentScopeMemberExpr;
-TEST(ImportExpr, ImportCXXDependentScopeMemberExpr) {
+TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) {
MatchVerifier<Decl> Verifier;
- testImport("template <typename T> struct C { T t; };"
- "template <typename T> void declToImport() {"
- " C<T> d;"
- " d.t;"
- "}"
- "void instantiate() { declToImport<int>(); }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionTemplateDecl(has(functionDecl(
- has(compoundStmt(has(cxxDependentScopeMemberExpr())))))));
- testImport("template <typename T> struct C { T t; };"
- "template <typename T> void declToImport() {"
- " C<T> d;"
- " (&d)->t;"
- "}"
- "void instantiate() { declToImport<int>(); }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionTemplateDecl(has(functionDecl(
- has(compoundStmt(has(cxxDependentScopeMemberExpr())))))));
+ testImport(
+ "template <typename T> struct C { T t; };"
+ "template <typename T> void declToImport() {"
+ " C<T> d;"
+ " (void)d.t;"
+ "}"
+ "void instantiate() { declToImport<int>(); }",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ functionTemplateDecl(hasDescendant(
+ cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
+ testImport(
+ "template <typename T> struct C { T t; };"
+ "template <typename T> void declToImport() {"
+ " C<T> d;"
+ " (void)(&d)->t;"
+ "}"
+ "void instantiate() { declToImport<int>(); }",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ functionTemplateDecl(hasDescendant(
+ cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
}
-TEST(ImportType, ImportTypeAliasTemplate) {
+TEST_P(ImportType, ImportTypeAliasTemplate) {
MatchVerifier<Decl> Verifier;
- testImport("template <int K>"
- "struct dummy { static const int i = K; };"
- "template <int K> using dummy2 = dummy<K>;"
- "int declToImport() { return dummy2<3>::i; }",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- returnStmt(
- has(
- implicitCastExpr(
- has(
- declRefExpr())))))))));
-}
-
-TEST(ImportType, ImportPackExpansion) {
- MatchVerifier<Decl> Verifier;
- testImport("template <typename... Args>"
- "struct dummy {"
- " dummy(Args... args) {}"
- " static const int i = 4;"
- "};"
- "int declToImport() { return dummy<int>::i; }",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- returnStmt(
- has(
- implicitCastExpr(
- has(
- declRefExpr())))))))));
+ testImport(
+ "template <int K>"
+ "struct dummy { static const int i = K; };"
+ "template <int K> using dummy2 = dummy<K>;"
+ "int declToImport() { return dummy2<3>::i; }",
+ Lang_CXX11, "", Lang_CXX11, Verifier,
+ functionDecl(
+ hasDescendant(implicitCastExpr(has(declRefExpr()))),
+ unless(hasAncestor(translationUnitDecl(has(typeAliasDecl()))))));
+}
+
+const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl>
+ varTemplateSpecializationDecl;
+
+TEST_P(ImportDecl, ImportVarTemplate) {
+ MatchVerifier<Decl> Verifier;
+ testImport(
+ "template <typename T>"
+ "T pi = T(3.1415926535897932385L);"
+ "void declToImport() { (void)pi<int>; }",
+ Lang_CXX14, "", Lang_CXX14, Verifier,
+ functionDecl(
+ hasDescendant(declRefExpr(to(varTemplateSpecializationDecl()))),
+ unless(hasAncestor(translationUnitDecl(has(varDecl(
+ hasName("pi"), unless(varTemplateSpecializationDecl()))))))));
+}
+
+TEST_P(ImportType, ImportPackExpansion) {
+ MatchVerifier<Decl> Verifier;
+ testImport(
+ "template <typename... Args>"
+ "struct dummy {"
+ " dummy(Args... args) {}"
+ " static const int i = 4;"
+ "};"
+ "int declToImport() { return dummy<int>::i; }",
+ Lang_CXX11, "", Lang_CXX11, Verifier,
+ functionDecl(hasDescendant(
+ returnStmt(has(implicitCastExpr(has(declRefExpr())))))));
+}
+
+const internal::VariadicDynCastAllOfMatcher<Type,
+ DependentTemplateSpecializationType>
+ dependentTemplateSpecializationType;
+
+TEST_P(ImportType, ImportDependentTemplateSpecialization) {
+ MatchVerifier<Decl> Verifier;
+ testImport(
+ "template<typename T>"
+ "struct A;"
+ "template<typename T>"
+ "struct declToImport {"
+ " typename A<T>::template B<T> a;"
+ "};",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ classTemplateDecl(has(cxxRecordDecl(has(
+ fieldDecl(hasType(dependentTemplateSpecializationType())))))));
+}
+
+const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>
+ sizeOfPackExpr;
+
+TEST_P(ImportExpr, ImportSizeOfPackExpr) {
+ MatchVerifier<Decl> Verifier;
+ testImport(
+ "template <typename... Ts>"
+ "void declToImport() {"
+ " const int i = sizeof...(Ts);"
+ "};"
+ "void g() { declToImport<int>(); }",
+ Lang_CXX11, "", Lang_CXX11, Verifier,
+ functionTemplateDecl(hasDescendant(sizeOfPackExpr())));
+ testImport(
+ "template <typename... Ts>"
+ "using X = int[sizeof...(Ts)];"
+ "template <typename... Us>"
+ "struct Y {"
+ " X<Us..., int, double, int, Us...> f;"
+ "};"
+ "Y<float, int> declToImport;",
+ Lang_CXX11, "", Lang_CXX11, Verifier,
+ varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType(
+ hasUnqualifiedDesugaredType(constantArrayType(hasSize(7))))))))));
}
/// \brief Matches __builtin_types_compatible_p:
@@ -573,66 +929,108 @@ TEST(ImportType, ImportPackExpansion) {
// will generate TypeTraitExpr <...> 'int'
const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
-TEST(ImportExpr, ImportTypeTraitExpr) {
+TEST_P(ImportExpr, ImportTypeTraitExpr) {
+ MatchVerifier<Decl> Verifier;
+ testImport(
+ "void declToImport() { "
+ " (void)__builtin_types_compatible_p(int, int);"
+ "}",
+ Lang_C, "", Lang_C, Verifier,
+ functionDecl(hasDescendant(typeTraitExpr(hasType(asString("int"))))));
+}
+
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;
+
+TEST_P(ImportExpr, ImportCXXTypeidExpr) {
MatchVerifier<Decl> Verifier;
- testImport("void declToImport() { "
- " __builtin_types_compatible_p(int, int);"
+ testImport(
+ "namespace std { class type_info {}; }"
+ "void declToImport() {"
+ " int x;"
+ " auto a = typeid(int); auto b = typeid(x);"
+ "}",
+ Lang_CXX11, "", Lang_CXX11, Verifier,
+ functionDecl(
+ hasDescendant(varDecl(
+ hasName("a"), hasInitializer(hasDescendant(cxxTypeidExpr())))),
+ hasDescendant(varDecl(
+ hasName("b"), hasInitializer(hasDescendant(cxxTypeidExpr()))))));
+}
+
+TEST_P(ImportExpr, ImportTypeTraitExprValDep) {
+ MatchVerifier<Decl> Verifier;
+ testImport(
+ "template<typename T> struct declToImport {"
+ " void m() { (void)__is_pod(T); }"
+ "};"
+ "void f() { declToImport<int>().m(); }",
+ Lang_CXX11, "", Lang_CXX11, Verifier,
+ classTemplateDecl(has(cxxRecordDecl(has(
+ functionDecl(hasDescendant(
+ typeTraitExpr(hasType(booleanType())))))))));
+}
+
+TEST_P(ImportDecl, ImportRecordDeclInFunc) {
+ MatchVerifier<Decl> Verifier;
+ testImport("int declToImport() { "
+ " struct data_t {int a;int b;};"
+ " struct data_t d;"
+ " return 0;"
"}",
Lang_C, "", Lang_C, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- typeTraitExpr(hasType(asString("int"))))))));
+ functionDecl(hasBody(compoundStmt(
+ has(declStmt(hasSingleDecl(varDecl(hasName("d")))))))));
}
-TEST(ImportExpr, ImportTypeTraitExprValDep) {
- MatchVerifier<Decl> Verifier;
- testImport("template<typename T> struct declToImport {"
- " void m() { __is_pod(T); }"
- "};"
- "void f() { declToImport<int>().m(); }",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- classTemplateDecl(
- has(
- cxxRecordDecl(
- has(
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- typeTraitExpr(
- hasType(booleanType())
- ))))))))));
+TEST_P(ASTImporterTestBase, ImportRecordTypeInFunc) {
+ Decl *FromTU = getTuDecl("int declToImport() { "
+ " struct data_t {int a;int b;};"
+ " struct data_t d;"
+ " return 0;"
+ "}",
+ Lang_C, "input.c");
+ auto FromVar =
+ FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("d")));
+ ASSERT_TRUE(FromVar);
+ auto ToType =
+ ImportType(FromVar->getType().getCanonicalType(), FromVar, Lang_C);
+ EXPECT_FALSE(ToType.isNull());
+}
+
+TEST_P(ASTImporterTestBase, ImportRecordDeclInFuncParams) {
+ // This construct is not supported by ASTImporter.
+ Decl *FromTU =
+ getTuDecl("int declToImport(struct data_t{int a;int b;} *d){ return 0; }",
+ Lang_C, "input.c");
+ auto From = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
+ ASSERT_TRUE(From);
+ auto To = Import(From, Lang_C);
+ EXPECT_EQ(To, nullptr);
}
const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
cxxPseudoDestructorExpr;
-TEST(ImportExpr, ImportCXXPseudoDestructorExpr) {
+TEST_P(ImportExpr, ImportCXXPseudoDestructorExpr) {
MatchVerifier<Decl> Verifier;
- testImport("typedef int T;"
- "void declToImport(int *p) {"
- " T t;"
- " p->T::~T();"
- "}",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(has(compoundStmt(has(
- callExpr(has(cxxPseudoDestructorExpr())))))));
+ testImport(
+ "typedef int T;"
+ "void declToImport(int *p) {"
+ " T t;"
+ " p->T::~T();"
+ "}",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ functionDecl(hasDescendant(
+ callExpr(has(cxxPseudoDestructorExpr())))));
}
-TEST(ImportDecl, ImportUsingDecl) {
+TEST_P(ImportDecl, ImportUsingDecl) {
MatchVerifier<Decl> Verifier;
- testImport("namespace foo { int bar; }"
- "int declToImport(){ using foo::bar; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(
- has(
- compoundStmt(
- has(
- declStmt(
- has(
- usingDecl())))))));
+ testImport(
+ "namespace foo { int bar; }"
+ "void declToImport() { using foo::bar; }",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ functionDecl(hasDescendant(usingDecl())));
}
/// \brief Matches shadow declarations introduced into a scope by a
@@ -648,13 +1046,1950 @@ TEST(ImportDecl, ImportUsingDecl) {
const internal::VariadicDynCastAllOfMatcher<Decl,
UsingShadowDecl> usingShadowDecl;
-TEST(ImportDecl, ImportUsingShadowDecl) {
+TEST_P(ImportDecl, ImportUsingShadowDecl) {
+ MatchVerifier<Decl> Verifier;
+ testImport(
+ "namespace foo { int bar; }"
+ "namespace declToImport { using foo::bar; }",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ namespaceDecl(has(usingShadowDecl())));
+}
+
+TEST_P(ImportExpr, ImportUnresolvedLookupExpr) {
+ MatchVerifier<Decl> Verifier;
+ testImport(
+ "template<typename T> int foo();"
+ "template <typename T> void declToImport() {"
+ " (void)::foo<T>;"
+ " (void)::template foo<T>;"
+ "}"
+ "void instantiate() { declToImport<int>(); }",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ functionTemplateDecl(hasDescendant(unresolvedLookupExpr())));
+}
+
+TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) {
+ MatchVerifier<Decl> Verifier;
+ testImport(
+ "template <typename T> struct C { T t; };"
+ "template <typename T> void declToImport() {"
+ " C<T> d;"
+ " d.t = T();"
+ "}"
+ "void instantiate() { declToImport<int>(); }",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ functionTemplateDecl(hasDescendant(
+ binaryOperator(has(cxxUnresolvedConstructExpr())))));
+ testImport(
+ "template <typename T> struct C { T t; };"
+ "template <typename T> void declToImport() {"
+ " C<T> d;"
+ " (&d)->t = T();"
+ "}"
+ "void instantiate() { declToImport<int>(); }",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ functionTemplateDecl(hasDescendant(
+ binaryOperator(has(cxxUnresolvedConstructExpr())))));
+}
+
+/// Check that function "declToImport()" (which is the templated function
+/// for corresponding FunctionTemplateDecl) is not added into DeclContext.
+/// Same for class template declarations.
+TEST_P(ImportDecl, ImportTemplatedDeclForTemplate) {
+ MatchVerifier<Decl> Verifier;
+ testImport(
+ "template <typename T> void declToImport() { T a = 1; }"
+ "void instantiate() { declToImport<int>(); }",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ functionTemplateDecl(hasAncestor(translationUnitDecl(
+ unless(has(functionDecl(hasName("declToImport"))))))));
+ testImport(
+ "template <typename T> struct declToImport { T t; };"
+ "void instantiate() { declToImport<int>(); }",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ classTemplateDecl(hasAncestor(translationUnitDecl(
+ unless(has(cxxRecordDecl(hasName("declToImport"))))))));
+}
+
+TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) {
MatchVerifier<Decl> Verifier;
- testImport("namespace foo { int bar; }"
- "namespace declToImport { using foo::bar; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- namespaceDecl(has(usingShadowDecl())));
+ auto Code =
+ R"s(
+ struct declToImport {
+ template <typename T0> struct X;
+ template <typename T0> struct X<T0 *> {};
+ };
+ )s";
+ testImport(Code, Lang_CXX, "", Lang_CXX, Verifier,
+ recordDecl(has(classTemplateDecl()),
+ has(classTemplateSpecializationDecl())));
}
+TEST_P(ImportExpr, CXXOperatorCallExpr) {
+ MatchVerifier<Decl> Verifier;
+ testImport(
+ "class declToImport {"
+ " void f() { *this = declToImport(); }"
+ "};",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ cxxRecordDecl(has(cxxMethodDecl(hasDescendant(
+ cxxOperatorCallExpr())))));
+}
+
+TEST_P(ImportExpr, DependentSizedArrayType) {
+ MatchVerifier<Decl> Verifier;
+ testImport(
+ "template<typename T, int Size> class declToImport {"
+ " T data[Size];"
+ "};",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ classTemplateDecl(has(cxxRecordDecl(
+ has(fieldDecl(hasType(dependentSizedArrayType())))))));
+}
+
+TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfClassTemplateDecl) {
+ Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
+ auto From =
+ FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
+ ASSERT_TRUE(From);
+ auto To = cast<ClassTemplateDecl>(Import(From, Lang_CXX));
+ ASSERT_TRUE(To);
+ Decl *ToTemplated = To->getTemplatedDecl();
+ Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
+ EXPECT_TRUE(ToTemplated1);
+ EXPECT_EQ(ToTemplated1, ToTemplated);
+}
+
+TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfFunctionTemplateDecl) {
+ Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
+ auto From = FirstDeclMatcher<FunctionTemplateDecl>().match(
+ FromTU, functionTemplateDecl());
+ ASSERT_TRUE(From);
+ auto To = cast<FunctionTemplateDecl>(Import(From, Lang_CXX));
+ ASSERT_TRUE(To);
+ Decl *ToTemplated = To->getTemplatedDecl();
+ Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
+ EXPECT_TRUE(ToTemplated1);
+ EXPECT_EQ(ToTemplated1, ToTemplated);
+}
+
+TEST_P(ASTImporterTestBase,
+ ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) {
+ Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
+ auto FromFT =
+ FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
+ ASSERT_TRUE(FromFT);
+
+ auto ToTemplated =
+ cast<CXXRecordDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
+ EXPECT_TRUE(ToTemplated);
+ auto ToTU = ToTemplated->getTranslationUnitDecl();
+ auto ToFT =
+ FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, classTemplateDecl());
+ EXPECT_TRUE(ToFT);
+}
+
+TEST_P(ASTImporterTestBase,
+ ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) {
+ Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
+ auto FromFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
+ FromTU, functionTemplateDecl());
+ ASSERT_TRUE(FromFT);
+
+ auto ToTemplated =
+ cast<FunctionDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
+ EXPECT_TRUE(ToTemplated);
+ auto ToTU = ToTemplated->getTranslationUnitDecl();
+ auto ToFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
+ ToTU, functionTemplateDecl());
+ EXPECT_TRUE(ToFT);
+}
+
+TEST_P(ASTImporterTestBase, ImportCorrectTemplatedDecl) {
+ auto Code =
+ R"(
+ namespace x {
+ template<class X> struct S1{};
+ template<class X> struct S2{};
+ template<class X> struct S3{};
+ }
+ )";
+ Decl *FromTU = getTuDecl(Code, Lang_CXX);
+ auto FromNs =
+ FirstDeclMatcher<NamespaceDecl>().match(FromTU, namespaceDecl());
+ auto ToNs = cast<NamespaceDecl>(Import(FromNs, Lang_CXX));
+ ASSERT_TRUE(ToNs);
+ auto From =
+ FirstDeclMatcher<ClassTemplateDecl>().match(FromTU,
+ classTemplateDecl(
+ hasName("S2")));
+ auto To =
+ FirstDeclMatcher<ClassTemplateDecl>().match(ToNs,
+ classTemplateDecl(
+ hasName("S2")));
+ ASSERT_TRUE(From);
+ ASSERT_TRUE(To);
+ auto ToTemplated = To->getTemplatedDecl();
+ auto ToTemplated1 =
+ cast<CXXRecordDecl>(Import(From->getTemplatedDecl(), Lang_CXX));
+ EXPECT_TRUE(ToTemplated1);
+ ASSERT_EQ(ToTemplated1, ToTemplated);
+}
+
+TEST_P(ASTImporterTestBase, ImportFunctionWithBackReferringParameter) {
+ Decl *From, *To;
+ std::tie(From, To) = getImportedDecl(
+ R"(
+ template <typename T> struct X {};
+
+ void declToImport(int y, X<int> &x) {}
+
+ template <> struct X<int> {
+ void g() {
+ X<int> x;
+ declToImport(0, x);
+ }
+ };
+ )",
+ Lang_CXX, "", Lang_CXX);
+
+ MatchVerifier<Decl> Verifier;
+ auto Matcher = functionDecl(hasName("declToImport"),
+ parameterCountIs(2),
+ hasParameter(0, hasName("y")),
+ hasParameter(1, hasName("x")),
+ hasParameter(1, hasType(asString("X<int> &"))));
+ ASSERT_TRUE(Verifier.match(From, Matcher));
+ EXPECT_TRUE(Verifier.match(To, Matcher));
+}
+
+TEST_P(ASTImporterTestBase,
+ TUshouldNotContainTemplatedDeclOfFunctionTemplates) {
+ Decl *From, *To;
+ std::tie(From, To) =
+ getImportedDecl("template <typename T> void declToImport() { T a = 1; }"
+ "void instantiate() { declToImport<int>(); }",
+ Lang_CXX, "", Lang_CXX);
+
+ auto Check = [](Decl *D) -> bool {
+ auto TU = D->getTranslationUnitDecl();
+ for (auto Child : TU->decls()) {
+ if (auto *FD = dyn_cast<FunctionDecl>(Child)) {
+ if (FD->getNameAsString() == "declToImport") {
+ GTEST_NONFATAL_FAILURE_(
+ "TU should not contain any FunctionDecl with name declToImport");
+ return false;
+ }
+ }
+ }
+ return true;
+ };
+
+ ASSERT_TRUE(Check(From));
+ EXPECT_TRUE(Check(To));
+}
+
+TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfClassTemplates) {
+ Decl *From, *To;
+ std::tie(From, To) =
+ getImportedDecl("template <typename T> struct declToImport { T t; };"
+ "void instantiate() { declToImport<int>(); }",
+ Lang_CXX, "", Lang_CXX);
+
+ auto Check = [](Decl *D) -> bool {
+ auto TU = D->getTranslationUnitDecl();
+ for (auto Child : TU->decls()) {
+ if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) {
+ if (RD->getNameAsString() == "declToImport") {
+ GTEST_NONFATAL_FAILURE_(
+ "TU should not contain any CXXRecordDecl with name declToImport");
+ return false;
+ }
+ }
+ }
+ return true;
+ };
+
+ ASSERT_TRUE(Check(From));
+ EXPECT_TRUE(Check(To));
+}
+
+TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfTypeAlias) {
+ Decl *From, *To;
+ std::tie(From, To) =
+ getImportedDecl(
+ "template <typename T> struct X {};"
+ "template <typename T> using declToImport = X<T>;"
+ "void instantiate() { declToImport<int> a; }",
+ Lang_CXX11, "", Lang_CXX11);
+
+ auto Check = [](Decl *D) -> bool {
+ auto TU = D->getTranslationUnitDecl();
+ for (auto Child : TU->decls()) {
+ if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) {
+ if (AD->getNameAsString() == "declToImport") {
+ GTEST_NONFATAL_FAILURE_(
+ "TU should not contain any TypeAliasDecl with name declToImport");
+ return false;
+ }
+ }
+ }
+ return true;
+ };
+
+ ASSERT_TRUE(Check(From));
+ EXPECT_TRUE(Check(To));
+}
+
+TEST_P(
+ ASTImporterTestBase,
+ TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {
+
+ Decl *From, *To;
+ std::tie(From, To) = getImportedDecl(
+ R"(
+ template<class T>
+ class Base {};
+ class declToImport : public Base<declToImport> {};
+ )",
+ Lang_CXX, "", Lang_CXX);
+
+ // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.
+ auto Pattern =
+ translationUnitDecl(unless(has(classTemplateSpecializationDecl())));
+ ASSERT_TRUE(
+ MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
+ EXPECT_TRUE(
+ MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
+
+ // Check that the ClassTemplateSpecializationDecl is the child of the
+ // ClassTemplateDecl.
+ Pattern = translationUnitDecl(has(classTemplateDecl(
+ hasName("Base"), has(classTemplateSpecializationDecl()))));
+ ASSERT_TRUE(
+ MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
+ EXPECT_TRUE(
+ MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
+}
+
+AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {
+ size_t Index = 0;
+ for (FieldDecl *Field : Node.fields()) {
+ if (Index == Order.size())
+ return false;
+ if (Field->getName() != Order[Index])
+ return false;
+ ++Index;
+ }
+ return Index == Order.size();
+}
+
+TEST_P(ASTImporterTestBase,
+ TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
+ Decl *From, *To;
+ std::tie(From, To) = getImportedDecl(
+ R"(
+ namespace NS {
+ template<class T>
+ class X {};
+ template class X<int>;
+ }
+ )",
+ Lang_CXX, "", Lang_CXX, "NS");
+
+ // Check that the ClassTemplateSpecializationDecl is NOT the child of the
+ // ClassTemplateDecl.
+ auto Pattern = namespaceDecl(has(classTemplateDecl(
+ hasName("X"), unless(has(classTemplateSpecializationDecl())))));
+ ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
+ EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
+
+ // Check that the ClassTemplateSpecializationDecl is the child of the
+ // NamespaceDecl.
+ Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X"))));
+ ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
+ EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
+}
+
+TEST_P(ASTImporterTestBase, CXXRecordDeclFieldsShouldBeInCorrectOrder) {
+ Decl *From, *To;
+ std::tie(From, To) =
+ getImportedDecl(
+ "struct declToImport { int a; int b; };",
+ Lang_CXX11, "", Lang_CXX11);
+
+ MatchVerifier<Decl> Verifier;
+ ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
+ EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
+}
+
+TEST_P(ASTImporterTestBase,
+ DISABLED_CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
+ Decl *From, *To;
+ std::tie(From, To) = getImportedDecl(
+ // The original recursive algorithm of ASTImporter first imports 'c' then
+ // 'b' and lastly 'a'. Therefore we must restore the order somehow.
+ R"s(
+ struct declToImport {
+ int a = c + b;
+ int b = 1;
+ int c = 2;
+ };
+ )s",
+ Lang_CXX11, "", Lang_CXX11);
+
+ MatchVerifier<Decl> Verifier;
+ ASSERT_TRUE(
+ Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
+ EXPECT_TRUE(
+ Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
+}
+
+TEST_P(ASTImporterTestBase, ShouldImportImplicitCXXRecordDecl) {
+ Decl *From, *To;
+ std::tie(From, To) = getImportedDecl(
+ R"(
+ struct declToImport {
+ };
+ )",
+ Lang_CXX, "", Lang_CXX);
+
+ MatchVerifier<Decl> Verifier;
+ // Match the implicit Decl.
+ auto Matcher = cxxRecordDecl(has(cxxRecordDecl()));
+ ASSERT_TRUE(Verifier.match(From, Matcher));
+ EXPECT_TRUE(Verifier.match(To, Matcher));
+}
+
+TEST_P(ASTImporterTestBase, ShouldImportImplicitCXXRecordDeclOfClassTemplate) {
+ Decl *From, *To;
+ std::tie(From, To) = getImportedDecl(
+ R"(
+ template <typename U>
+ struct declToImport {
+ };
+ )",
+ Lang_CXX, "", Lang_CXX);
+
+ MatchVerifier<Decl> Verifier;
+ // Match the implicit Decl.
+ auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
+ ASSERT_TRUE(Verifier.match(From, Matcher));
+ EXPECT_TRUE(Verifier.match(To, Matcher));
+}
+
+TEST_P(
+ ASTImporterTestBase,
+ ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
+ Decl *From, *To;
+ std::tie(From, To) = getImportedDecl(
+ R"(
+ template<class T>
+ class Base {};
+ class declToImport : public Base<declToImport> {};
+ )",
+ Lang_CXX, "", Lang_CXX);
+
+ auto hasImplicitClass = has(cxxRecordDecl());
+ auto Pattern = translationUnitDecl(has(classTemplateDecl(
+ hasName("Base"),
+ has(classTemplateSpecializationDecl(hasImplicitClass)))));
+ ASSERT_TRUE(
+ MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
+ EXPECT_TRUE(
+ MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
+}
+
+TEST_P(ASTImporterTestBase, IDNSOrdinary) {
+ Decl *From, *To;
+ std::tie(From, To) =
+ getImportedDecl("void declToImport() {}", Lang_CXX, "", Lang_CXX);
+
+ MatchVerifier<Decl> Verifier;
+ auto Matcher = functionDecl();
+ ASSERT_TRUE(Verifier.match(From, Matcher));
+ EXPECT_TRUE(Verifier.match(To, Matcher));
+ EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
+}
+
+TEST_P(ASTImporterTestBase, IDNSOfNonmemberOperator) {
+ Decl *FromTU = getTuDecl(
+ R"(
+ struct X {};
+ void operator<<(int, X);
+ )",
+ Lang_CXX);
+ Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl());
+ const Decl *To = Import(From, Lang_CXX);
+ EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
+}
+
+TEST_P(ASTImporterTestBase,
+ ShouldImportMembersOfClassTemplateSpecializationDecl) {
+ Decl *From, *To;
+ std::tie(From, To) = getImportedDecl(
+ R"(
+ template<class T>
+ class Base { int a; };
+ class declToImport : Base<declToImport> {};
+ )",
+ Lang_CXX, "", Lang_CXX);
+
+ auto Pattern = translationUnitDecl(has(classTemplateDecl(
+ hasName("Base"),
+ has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a"))))))));
+ ASSERT_TRUE(
+ MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
+ EXPECT_TRUE(
+ MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
+}
+
+TEST_P(ASTImporterTestBase, ImportDefinitionOfClassTemplateAfterFwdDecl) {
+ {
+ Decl *FromTU = getTuDecl(
+ R"(
+ template <typename T>
+ struct B;
+ )",
+ Lang_CXX, "input0.cc");
+ auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
+ FromTU, classTemplateDecl(hasName("B")));
+
+ Import(FromD, Lang_CXX);
+ }
+
+ {
+ Decl *FromTU = getTuDecl(
+ R"(
+ template <typename T>
+ struct B {
+ void f();
+ };
+ )",
+ Lang_CXX, "input1.cc");
+ FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
+ FromTU, functionDecl(hasName("f")));
+ Import(FromD, Lang_CXX);
+ auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
+ FromTU, classTemplateDecl(hasName("B")));
+ auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
+ EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
+ }
+}
+
+TEST_P(ASTImporterTestBase,
+ ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {
+ Decl *ToTU = getToTuDecl(
+ R"(
+ template <typename T>
+ struct B {
+ void f();
+ };
+
+ template <typename T>
+ struct B;
+ )",
+ Lang_CXX);
+ ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
+ [](const ClassTemplateDecl *T) {
+ return T->isThisDeclarationADefinition();
+ })
+ .match(ToTU, classTemplateDecl()));
+
+ Decl *FromTU = getTuDecl(
+ R"(
+ template <typename T>
+ struct B {
+ void f();
+ };
+ )",
+ Lang_CXX, "input1.cc");
+ ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
+ FromTU, classTemplateDecl(hasName("B")));
+
+ Import(FromD, Lang_CXX);
+
+ // We should have only one definition.
+ EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
+ [](const ClassTemplateDecl *T) {
+ return T->isThisDeclarationADefinition();
+ })
+ .match(ToTU, classTemplateDecl()));
+}
+
+TEST_P(ASTImporterTestBase,
+ ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {
+ Decl *ToTU = getToTuDecl(
+ R"(
+ struct B {
+ void f();
+ };
+
+ struct B;
+ )",
+ Lang_CXX);
+ ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
+ ToTU, cxxRecordDecl(unless(isImplicit()))));
+
+ Decl *FromTU = getTuDecl(
+ R"(
+ struct B {
+ void f();
+ };
+ )",
+ Lang_CXX, "input1.cc");
+ auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
+ FromTU, cxxRecordDecl(hasName("B")));
+
+ Import(FromD, Lang_CXX);
+
+ EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
+ ToTU, cxxRecordDecl(unless(isImplicit()))));
+}
+
+static void CompareSourceLocs(FullSourceLoc Loc1, FullSourceLoc Loc2) {
+ EXPECT_EQ(Loc1.getExpansionLineNumber(), Loc2.getExpansionLineNumber());
+ EXPECT_EQ(Loc1.getExpansionColumnNumber(), Loc2.getExpansionColumnNumber());
+ EXPECT_EQ(Loc1.getSpellingLineNumber(), Loc2.getSpellingLineNumber());
+ EXPECT_EQ(Loc1.getSpellingColumnNumber(), Loc2.getSpellingColumnNumber());
+}
+static void CompareSourceRanges(SourceRange Range1, SourceRange Range2,
+ SourceManager &SM1, SourceManager &SM2) {
+ CompareSourceLocs(FullSourceLoc{ Range1.getBegin(), SM1 },
+ FullSourceLoc{ Range2.getBegin(), SM2 });
+ CompareSourceLocs(FullSourceLoc{ Range1.getEnd(), SM1 },
+ FullSourceLoc{ Range2.getEnd(), SM2 });
+}
+TEST_P(ASTImporterTestBase, ImportSourceLocs) {
+ Decl *FromTU = getTuDecl(
+ R"(
+ #define MFOO(arg) arg = arg + 1
+
+ void foo() {
+ int a = 5;
+ MFOO(a);
+ }
+ )",
+ Lang_CXX);
+ auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
+ auto ToD = Import(FromD, Lang_CXX);
+
+ auto ToLHS = LastDeclMatcher<DeclRefExpr>().match(ToD, declRefExpr());
+ auto FromLHS = LastDeclMatcher<DeclRefExpr>().match(FromTU, declRefExpr());
+ auto ToRHS = LastDeclMatcher<IntegerLiteral>().match(ToD, integerLiteral());
+ auto FromRHS =
+ LastDeclMatcher<IntegerLiteral>().match(FromTU, integerLiteral());
+
+ SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
+ SourceManager &FromSM = FromD->getASTContext().getSourceManager();
+ CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
+ FromSM);
+ CompareSourceRanges(ToLHS->getSourceRange(), FromLHS->getSourceRange(), ToSM,
+ FromSM);
+ CompareSourceRanges(ToRHS->getSourceRange(), FromRHS->getSourceRange(), ToSM,
+ FromSM);
+}
+
+TEST_P(ASTImporterTestBase, ImportNestedMacro) {
+ Decl *FromTU = getTuDecl(
+ R"(
+ #define FUNC_INT void declToImport
+ #define FUNC FUNC_INT
+ FUNC(int a);
+ )",
+ Lang_CXX);
+ auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
+ auto ToD = Import(FromD, Lang_CXX);
+
+ SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
+ SourceManager &FromSM = FromD->getASTContext().getSourceManager();
+ CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
+ FromSM);
+}
+
+TEST_P(
+ ASTImporterTestBase,
+ ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition)
+{
+ Decl *ToTU = getToTuDecl(
+ R"(
+ template <typename T>
+ struct B;
+
+ template <>
+ struct B<int> {};
+
+ template <>
+ struct B<int>;
+ )",
+ Lang_CXX);
+ // We should have only one definition.
+ ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
+ [](const ClassTemplateSpecializationDecl *T) {
+ return T->isThisDeclarationADefinition();
+ })
+ .match(ToTU, classTemplateSpecializationDecl()));
+
+ Decl *FromTU = getTuDecl(
+ R"(
+ template <typename T>
+ struct B;
+
+ template <>
+ struct B<int> {};
+ )",
+ Lang_CXX, "input1.cc");
+ auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
+ FromTU, classTemplateSpecializationDecl(hasName("B")));
+
+ Import(FromD, Lang_CXX);
+
+ // We should have only one definition.
+ EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
+ [](const ClassTemplateSpecializationDecl *T) {
+ return T->isThisDeclarationADefinition();
+ })
+ .match(ToTU, classTemplateSpecializationDecl()));
+}
+
+TEST_P(ASTImporterTestBase, ObjectsWithUnnamedStructType) {
+ Decl *FromTU = getTuDecl(
+ R"(
+ struct { int a; int b; } object0 = { 2, 3 };
+ struct { int x; int y; int z; } object1;
+ )",
+ Lang_CXX, "input0.cc");
+
+ auto *Obj0 =
+ FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object0")));
+ auto *From0 = getRecordDecl(Obj0);
+ auto *Obj1 =
+ FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object1")));
+ auto *From1 = getRecordDecl(Obj1);
+
+ auto *To0 = Import(From0, Lang_CXX);
+ auto *To1 = Import(From1, Lang_CXX);
+
+ EXPECT_TRUE(To0);
+ EXPECT_TRUE(To1);
+ EXPECT_NE(To0, To1);
+ EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());
+}
+
+TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag) {
+ auto Pattern = varDecl(hasName("x"));
+ VarDecl *Imported1;
+ {
+ Decl *FromTU = getTuDecl("extern int x;", Lang_CXX, "input0.cc");
+ auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
+ Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
+ }
+ VarDecl *Imported2;
+ {
+ Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input1.cc");
+ auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
+ Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
+ }
+ EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl());
+ EXPECT_FALSE(Imported2->isUsed(false));
+ {
+ Decl *FromTU =
+ getTuDecl("extern int x; int f() { return x; }", Lang_CXX, "input2.cc");
+ auto *FromD =
+ FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
+ Import(FromD, Lang_CXX);
+ }
+ EXPECT_TRUE(Imported2->isUsed(false));
+}
+
+TEST_P(ASTImporterTestBase, ReimportWithUsedFlag) {
+ auto Pattern = varDecl(hasName("x"));
+
+ Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input0.cc");
+ auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
+
+ auto *Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
+
+ ASSERT_FALSE(Imported1->isUsed(false));
+
+ FromD->setIsUsed();
+ auto *Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
+
+ EXPECT_EQ(Imported1, Imported2);
+ EXPECT_TRUE(Imported2->isUsed(false));
+}
+
+struct ImportFunctions : ASTImporterTestBase {};
+
+TEST_P(ImportFunctions,
+ DefinitionShouldBeImportedAsDefintionWhenThereIsAPrototype) {
+ Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX);
+ auto Pattern = functionDecl(hasName("f"));
+ FunctionDecl *FromD = // Definition
+ LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+
+ Decl *ImportedD = Import(FromD, Lang_CXX);
+ Decl *ToTU = ImportedD->getTranslationUnitDecl();
+
+ EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
+ EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
+}
+
+TEST_P(ImportFunctions, DefinitionShouldBeImportedAsADefinition) {
+ Decl *FromTU = getTuDecl("void f() {}", Lang_CXX);
+ auto Pattern = functionDecl(hasName("f"));
+ FunctionDecl *FromD =
+ FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+
+ Decl *ImportedD = Import(FromD, Lang_CXX);
+ Decl *ToTU = ImportedD->getTranslationUnitDecl();
+
+ EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
+ EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
+}
+
+TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {
+ Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
+ auto Pattern = functionDecl(hasName("f"));
+ auto *From =
+ FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto
+
+ Decl *ImportedD = Import(From, Lang_CXX);
+ Decl *ToTU = ImportedD->getTranslationUnitDecl();
+
+ EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
+ auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
+ auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
+ EXPECT_TRUE(ImportedD == To0);
+ EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
+ EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
+ EXPECT_EQ(To1->getPreviousDecl(), To0);
+}
+
+TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
+ Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
+ auto Pattern = functionDecl(hasName("f"));
+ auto *From =
+ LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def
+
+ Decl *ImportedD = Import(From, Lang_CXX);
+ Decl *ToTU = ImportedD->getTranslationUnitDecl();
+
+ EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
+ auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
+ auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
+ EXPECT_TRUE(ImportedD == To1);
+ EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
+ EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
+ EXPECT_EQ(To1->getPreviousDecl(), To0);
+}
+
+TEST_P(ImportFunctions, ImportPrototypes) {
+ auto Pattern = functionDecl(hasName("f"));
+
+ Decl *ImportedD;
+ {
+ Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
+ auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+
+ ImportedD = Import(FromD, Lang_CXX);
+ }
+ {
+ Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
+ auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+ Import(FromD, Lang_CXX);
+ }
+
+ Decl *ToTU = ImportedD->getTranslationUnitDecl();
+
+ EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
+ auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
+ auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
+ EXPECT_TRUE(ImportedD == To0);
+ EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
+ EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
+ EXPECT_EQ(To1->getPreviousDecl(), To0);
+}
+
+TEST_P(ImportFunctions, ImportDefinitions) {
+ auto Pattern = functionDecl(hasName("f"));
+
+ Decl *ImportedD;
+ {
+ Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
+ auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+ ImportedD = Import(FromD, Lang_CXX);
+ }
+ {
+ Decl *FromTU = getTuDecl("void f(){};", Lang_CXX, "input1.cc");
+ auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+ Import(FromD, Lang_CXX);
+ }
+
+ Decl *ToTU = ImportedD->getTranslationUnitDecl();
+
+ EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
+ auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
+ EXPECT_TRUE(ImportedD == To0);
+ EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
+}
+
+TEST_P(ImportFunctions, ImportDefinitionThenPrototype) {
+ auto Pattern = functionDecl(hasName("f"));
+
+ Decl *ImportedD;
+ {
+ Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
+ auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+ ImportedD = Import(FromD, Lang_CXX);
+ }
+ {
+ Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
+ auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+ Import(FromD, Lang_CXX);
+ }
+
+ Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+
+ EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
+ auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
+ auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
+ EXPECT_TRUE(ImportedD == To0);
+ EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
+ EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
+ EXPECT_EQ(To1->getPreviousDecl(), To0);
+}
+
+TEST_P(ImportFunctions, ImportPrototypeThenDefinition) {
+ auto Pattern = functionDecl(hasName("f"));
+
+ {
+ Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
+ FunctionDecl *FromD =
+ FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+
+ Import(FromD, Lang_CXX);
+ }
+ {
+ Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input1.cc");
+ FunctionDecl *FromD =
+ FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+ Import(FromD, Lang_CXX);
+ }
+
+ Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+ ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
+ FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
+ EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());
+ FunctionDecl *DefinitionD =
+ LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
+ EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
+ EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD);
+}
+
+TEST_P(ImportFunctions, ImportPrototypeThenProtoAndDefinition) {
+ auto Pattern = functionDecl(hasName("f"));
+
+ {
+ Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
+ auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+ Import(FromD, Lang_CXX);
+ }
+ {
+ Decl *FromTU = getTuDecl("void f(); void f(){}", Lang_CXX, "input1.cc");
+ auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+ Import(FromD, Lang_CXX);
+ }
+
+ Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+
+ ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 3u);
+ FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
+ EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());
+
+ FunctionDecl *DefinitionD =
+ LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
+ EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
+
+ EXPECT_TRUE(DefinitionD->getPreviousDecl());
+ EXPECT_FALSE(DefinitionD->getPreviousDecl()->doesThisDeclarationHaveABody());
+ EXPECT_EQ(DefinitionD->getPreviousDecl()->getPreviousDecl(), ProtoD);
+}
+
+TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
+ auto Code =
+ R"(
+ struct B { virtual void f(); };
+ void B::f() {}
+ struct D : B { void f(); };
+ )";
+ auto Pattern =
+ cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
+ Decl *FromTU = getTuDecl(Code, Lang_CXX);
+ CXXMethodDecl *Proto =
+ FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
+
+ ASSERT_EQ(Proto->size_overridden_methods(), 1u);
+ CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
+ EXPECT_EQ(To->size_overridden_methods(), 1u);
+}
+
+TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
+ auto Code =
+ R"(
+ struct B { virtual void f(); };
+ void B::f() {}
+ )";
+ auto Pattern =
+ cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
+ Decl *FromTU = getTuDecl(Code, Lang_CXX);
+ CXXMethodDecl *Proto =
+ FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
+ CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
+
+ ASSERT_TRUE(Proto->isVirtual());
+ ASSERT_TRUE(Def->isVirtual());
+ CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
+ EXPECT_TRUE(To->isVirtual());
+}
+
+TEST_P(ImportFunctions,
+ ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {
+ Decl *ToTU = getToTuDecl(
+ R"(
+ void f() {}
+ void f();
+ )",
+ Lang_CXX);
+ ASSERT_EQ(1u,
+ DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
+ return FD->doesThisDeclarationHaveABody();
+ }).match(ToTU, functionDecl()));
+
+ Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc");
+ auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
+
+ Import(FromD, Lang_CXX);
+
+ EXPECT_EQ(1u,
+ DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
+ return FD->doesThisDeclarationHaveABody();
+ }).match(ToTU, functionDecl()));
+}
+
+struct ImportFriendFunctions : ImportFunctions {};
+
+TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
+ auto Pattern = functionDecl(hasName("f"));
+
+ Decl *FromTU = getTuDecl("struct X { friend void f(); };"
+ "void f();",
+ Lang_CXX,
+ "input0.cc");
+ auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+
+ auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
+ Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+ ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
+ EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
+ auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
+ EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
+ EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
+}
+
+TEST_P(ImportFriendFunctions,
+ ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {
+ auto Pattern = functionDecl(hasName("f"));
+
+ Decl *FromTU = getTuDecl("void f();"
+ "struct X { friend void f(); };",
+ Lang_CXX, "input0.cc");
+ auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+
+ auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
+ Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+ ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
+ EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
+ auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
+ EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
+ EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
+}
+
+TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {
+ auto Pattern = functionDecl(hasName("f"));
+
+ Decl *FromTU = getTuDecl("struct X { friend void f(){} };"
+ "void f();",
+ Lang_CXX,
+ "input0.cc");
+ auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+
+ auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
+ Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+ ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
+ EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
+ auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
+ EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
+ EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
+}
+
+TEST_P(ImportFriendFunctions,
+ ImportFriendFunctionRedeclChainDef_OutOfClassDef) {
+ auto Pattern = functionDecl(hasName("f"));
+
+ Decl *FromTU = getTuDecl("struct X { friend void f(); };"
+ "void f(){}",
+ Lang_CXX, "input0.cc");
+ auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+
+ auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
+ Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+ ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
+ EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
+ auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
+ EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());
+ EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
+}
+
+// Disabled temporarily, because the new structural equivalence check
+// (https://reviews.llvm.org/D48628) breaks it.
+// PreviousDecl is not set because there is no structural match.
+// FIXME Enable!
+TEST_P(ImportFriendFunctions,
+ DISABLED_ImportFriendFunctionRedeclChainDefWithClass) {
+ auto Pattern = functionDecl(hasName("f"));
+
+ Decl *FromTU = getTuDecl(
+ R"(
+ class X;
+ void f(X *x){}
+ class X{
+ friend void f(X *x);
+ };
+ )",
+ Lang_CXX, "input0.cc");
+ auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+
+ auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
+ Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+ ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
+ EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
+ auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()
+ .match(ToTU, friendDecl())
+ ->getFriendDecl());
+ EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
+ EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
+ // The parameters must refer the same type
+ EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
+ (*ImportedD->param_begin())->getOriginalType());
+}
+
+// Disabled temporarily, because the new structural equivalence check
+// (https://reviews.llvm.org/D48628) breaks it.
+// PreviousDecl is not set because there is no structural match.
+// FIXME Enable!
+TEST_P(ImportFriendFunctions,
+ DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
+ auto Pattern = functionDecl(hasName("f"));
+
+ Decl *FromTU = getTuDecl(
+ R"(
+ class X;
+ void f(X *x){}
+ class X{
+ friend void f(X *x);
+ };
+ )",
+ Lang_CXX, "input0.cc");
+ auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+
+ auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
+ Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+ ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
+ EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
+ auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
+ ToTU, functionDecl(unless(hasParent(friendDecl()))));
+
+ EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
+ EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
+ // The parameters must refer the same type
+ EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
+ (*ImportedD->param_begin())->getOriginalType());
+}
+
+TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
+ auto Pattern = functionDecl(hasName("f"));
+
+ FunctionDecl *ImportedD;
+ {
+ Decl *FromTU =
+ getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc");
+ auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+ ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
+ }
+ FunctionDecl *ImportedD1;
+ {
+ Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
+ auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+ ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX));
+ }
+
+ Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+ ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
+ EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
+ EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
+ EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
+}
+
+AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
+ InnerMatcher) {
+ if (auto *Typedef = Node.getTypedefNameForAnonDecl())
+ return InnerMatcher.matches(*Typedef, Finder, Builder);
+ return false;
+}
+
+TEST_P(ImportDecl, ImportEnumSequential) {
+ CodeFiles Samples{{"main.c",
+ {"void foo();"
+ "void moo();"
+ "int main() { foo(); moo(); }",
+ Lang_C}},
+
+ {"foo.c",
+ {"typedef enum { THING_VALUE } thing_t;"
+ "void conflict(thing_t type);"
+ "void foo() { (void)THING_VALUE; }"
+ "void conflict(thing_t type) {}",
+ Lang_C}},
+
+ {"moo.c",
+ {"typedef enum { THING_VALUE } thing_t;"
+ "void conflict(thing_t type);"
+ "void moo() { conflict(THING_VALUE); }",
+ Lang_C}}};
+
+ auto VerificationMatcher =
+ enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
+ hasTypedefForAnonDecl(hasName("thing_t")));
+
+ ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
+ ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
+
+ testImportSequence(
+ Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
+ // Just check that there is only one enum decl in the result AST.
+ "main.c", enumDecl(), VerificationMatcher);
+
+ // For different import order, result should be the same.
+ testImportSequence(
+ Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
+ // Check that there is only one enum decl in the result AST.
+ "main.c", enumDecl(), VerificationMatcher);
+}
+
+const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
+ dependentScopeDeclRefExpr;
+
+TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
+ MatchVerifier<Decl> Verifier;
+ testImport("template <typename T> struct S { static T foo; };"
+ "template <typename T> void declToImport() {"
+ " (void) S<T>::foo;"
+ "}"
+ "void instantiate() { declToImport<int>(); }"
+ "template <typename T> T S<T>::foo;",
+ Lang_CXX11, "", Lang_CXX11, Verifier,
+ functionTemplateDecl(has(functionDecl(has(compoundStmt(
+ has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
+
+ testImport("template <typename T> struct S {"
+ "template<typename S> static void foo(){};"
+ "};"
+ "template <typename T> void declToImport() {"
+ " S<T>::template foo<T>();"
+ "}"
+ "void instantiate() { declToImport<int>(); }",
+ Lang_CXX11, "", Lang_CXX11, Verifier,
+ functionTemplateDecl(has(functionDecl(has(compoundStmt(
+ has(callExpr(has(dependentScopeDeclRefExpr())))))))));
+}
+
+const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
+ dependentNameType;
+
+TEST_P(ImportExpr, DependentNameType) {
+ MatchVerifier<Decl> Verifier;
+ testImport("template <typename T> struct declToImport {"
+ " typedef typename T::type dependent_name;"
+ "};",
+ Lang_CXX11, "", Lang_CXX11, Verifier,
+ classTemplateDecl(has(
+ cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
+}
+
+const internal::VariadicDynCastAllOfMatcher<Expr, UnresolvedMemberExpr>
+ unresolvedMemberExpr;
+
+TEST_P(ImportExpr, UnresolvedMemberExpr) {
+ MatchVerifier<Decl> Verifier;
+ testImport("struct S { template <typename T> void mem(); };"
+ "template <typename U> void declToImport() {"
+ " S s;"
+ " s.mem<U>();"
+ "}"
+ "void instantiate() { declToImport<int>(); }",
+ Lang_CXX11, "", Lang_CXX11, Verifier,
+ functionTemplateDecl(has(functionDecl(has(
+ compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
+}
+
+class ImportImplicitMethods : public ASTImporterTestBase {
+public:
+ static constexpr auto DefaultCode = R"(
+ struct A { int x; };
+ void f() {
+ A a;
+ A a1(a);
+ A a2(A{});
+ a = a1;
+ a = A{};
+ a.~A();
+ })";
+
+ template <typename MatcherType>
+ void testImportOf(
+ const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
+ test(MethodMatcher, Code, /*ExpectedCount=*/1u);
+ }
+
+ template <typename MatcherType>
+ void testNoImportOf(
+ const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
+ test(MethodMatcher, Code, /*ExpectedCount=*/0u);
+ }
+
+private:
+ template <typename MatcherType>
+ void test(const MatcherType &MethodMatcher,
+ const char *Code, unsigned int ExpectedCount) {
+ auto ClassMatcher = cxxRecordDecl(unless(isImplicit()));
+
+ Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
+ auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
+ ToTU, ClassMatcher);
+
+ ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 1u);
+
+ {
+ CXXMethodDecl *Method =
+ FirstDeclMatcher<CXXMethodDecl>().match(ToClass, MethodMatcher);
+ ToClass->removeDecl(Method);
+ }
+
+ ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 0u);
+
+ Decl *ImportedClass = nullptr;
+ {
+ Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input1.cc");
+ auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
+ FromTU, ClassMatcher);
+ ImportedClass = Import(FromClass, Lang_CXX11);
+ }
+
+ EXPECT_EQ(ToClass, ImportedClass);
+ EXPECT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher),
+ ExpectedCount);
+ }
+};
+
+TEST_P(ImportImplicitMethods, DefaultConstructor) {
+ testImportOf(cxxConstructorDecl(isDefaultConstructor()));
+}
+
+TEST_P(ImportImplicitMethods, CopyConstructor) {
+ testImportOf(cxxConstructorDecl(isCopyConstructor()));
+}
+
+TEST_P(ImportImplicitMethods, MoveConstructor) {
+ testImportOf(cxxConstructorDecl(isMoveConstructor()));
+}
+
+TEST_P(ImportImplicitMethods, Destructor) {
+ testImportOf(cxxDestructorDecl());
+}
+
+TEST_P(ImportImplicitMethods, CopyAssignment) {
+ testImportOf(cxxMethodDecl(isCopyAssignmentOperator()));
+}
+
+TEST_P(ImportImplicitMethods, MoveAssignment) {
+ testImportOf(cxxMethodDecl(isMoveAssignmentOperator()));
+}
+
+TEST_P(ImportImplicitMethods, DoNotImportUserProvided) {
+ auto Code = R"(
+ struct A { A() { int x; } };
+ )";
+ testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
+}
+
+TEST_P(ImportImplicitMethods, DoNotImportDefault) {
+ auto Code = R"(
+ struct A { A() = default; };
+ )";
+ testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
+}
+
+TEST_P(ImportImplicitMethods, DoNotImportDeleted) {
+ auto Code = R"(
+ struct A { A() = delete; };
+ )";
+ testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
+}
+
+TEST_P(ImportImplicitMethods, DoNotImportOtherMethod) {
+ auto Code = R"(
+ struct A { void f() { } };
+ )";
+ testNoImportOf(cxxMethodDecl(hasName("f")), Code);
+}
+
+TEST_P(ASTImporterTestBase, ImportOfEquivalentRecord) {
+ Decl *ToR1;
+ {
+ Decl *FromTU = getTuDecl(
+ "struct A { };", Lang_CXX, "input0.cc");
+ auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
+ FromTU, cxxRecordDecl(hasName("A")));
+
+ ToR1 = Import(FromR, Lang_CXX);
+ }
+
+ Decl *ToR2;
+ {
+ Decl *FromTU = getTuDecl(
+ "struct A { };", Lang_CXX, "input1.cc");
+ auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
+ FromTU, cxxRecordDecl(hasName("A")));
+
+ ToR2 = Import(FromR, Lang_CXX);
+ }
+
+ EXPECT_EQ(ToR1, ToR2);
+}
+
+TEST_P(ASTImporterTestBase, ImportOfNonEquivalentRecord) {
+ Decl *ToR1;
+ {
+ Decl *FromTU = getTuDecl(
+ "struct A { int x; };", Lang_CXX, "input0.cc");
+ auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
+ FromTU, cxxRecordDecl(hasName("A")));
+ ToR1 = Import(FromR, Lang_CXX);
+ }
+ Decl *ToR2;
+ {
+ Decl *FromTU = getTuDecl(
+ "struct A { unsigned x; };", Lang_CXX, "input1.cc");
+ auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
+ FromTU, cxxRecordDecl(hasName("A")));
+ ToR2 = Import(FromR, Lang_CXX);
+ }
+ EXPECT_NE(ToR1, ToR2);
+}
+
+TEST_P(ASTImporterTestBase, ImportOfEquivalentField) {
+ Decl *ToF1;
+ {
+ Decl *FromTU = getTuDecl(
+ "struct A { int x; };", Lang_CXX, "input0.cc");
+ auto *FromF = FirstDeclMatcher<FieldDecl>().match(
+ FromTU, fieldDecl(hasName("x")));
+ ToF1 = Import(FromF, Lang_CXX);
+ }
+ Decl *ToF2;
+ {
+ Decl *FromTU = getTuDecl(
+ "struct A { int x; };", Lang_CXX, "input1.cc");
+ auto *FromF = FirstDeclMatcher<FieldDecl>().match(
+ FromTU, fieldDecl(hasName("x")));
+ ToF2 = Import(FromF, Lang_CXX);
+ }
+ EXPECT_EQ(ToF1, ToF2);
+}
+
+TEST_P(ASTImporterTestBase, ImportOfNonEquivalentField) {
+ Decl *ToF1;
+ {
+ Decl *FromTU = getTuDecl(
+ "struct A { int x; };", Lang_CXX, "input0.cc");
+ auto *FromF = FirstDeclMatcher<FieldDecl>().match(
+ FromTU, fieldDecl(hasName("x")));
+ ToF1 = Import(FromF, Lang_CXX);
+ }
+ Decl *ToF2;
+ {
+ Decl *FromTU = getTuDecl(
+ "struct A { unsigned x; };", Lang_CXX, "input1.cc");
+ auto *FromF = FirstDeclMatcher<FieldDecl>().match(
+ FromTU, fieldDecl(hasName("x")));
+ ToF2 = Import(FromF, Lang_CXX);
+ }
+ EXPECT_NE(ToF1, ToF2);
+}
+
+TEST_P(ASTImporterTestBase, ImportOfEquivalentMethod) {
+ Decl *ToM1;
+ {
+ Decl *FromTU = getTuDecl(
+ "struct A { void x(); }; void A::x() { }", Lang_CXX, "input0.cc");
+ auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
+ FromTU, functionDecl(hasName("x"), isDefinition()));
+ ToM1 = Import(FromM, Lang_CXX);
+ }
+ Decl *ToM2;
+ {
+ Decl *FromTU = getTuDecl(
+ "struct A { void x(); }; void A::x() { }", Lang_CXX, "input1.cc");
+ auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
+ FromTU, functionDecl(hasName("x"), isDefinition()));
+ ToM2 = Import(FromM, Lang_CXX);
+ }
+ EXPECT_EQ(ToM1, ToM2);
+}
+
+TEST_P(ASTImporterTestBase, ImportOfNonEquivalentMethod) {
+ Decl *ToM1;
+ {
+ Decl *FromTU = getTuDecl(
+ "struct A { void x(); }; void A::x() { }",
+ Lang_CXX, "input0.cc");
+ auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
+ FromTU, functionDecl(hasName("x"), isDefinition()));
+ ToM1 = Import(FromM, Lang_CXX);
+ }
+ Decl *ToM2;
+ {
+ Decl *FromTU = getTuDecl(
+ "struct A { void x() const; }; void A::x() const { }",
+ Lang_CXX, "input1.cc");
+ auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
+ FromTU, functionDecl(hasName("x"), isDefinition()));
+ ToM2 = Import(FromM, Lang_CXX);
+ }
+ EXPECT_NE(ToM1, ToM2);
+}
+
+TEST_P(ASTImporterTestBase, ImportUnnamedStructsWithRecursingField) {
+ Decl *FromTU = getTuDecl(
+ R"(
+ struct A {
+ struct {
+ struct A *next;
+ } entry0;
+ struct {
+ struct A *next;
+ } entry1;
+ };
+ )",
+ Lang_C, "input0.cc");
+ auto *From =
+ FirstDeclMatcher<RecordDecl>().match(FromTU, recordDecl(hasName("A")));
+
+ Import(From, Lang_C);
+
+ auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+ auto *Entry0 =
+ FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));
+ auto *Entry1 =
+ FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry1")));
+ auto *R0 = getRecordDecl(Entry0);
+ auto *R1 = getRecordDecl(Entry1);
+ EXPECT_NE(R0, R1);
+ EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
+ R0, recordDecl(has(fieldDecl(hasName("next"))))));
+ EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
+ R1, recordDecl(has(fieldDecl(hasName("next"))))));
+}
+
+struct DeclContextTest : ASTImporterTestBase {};
+
+TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
+ Decl *TU = getTuDecl(
+ R"(
+ namespace NS {
+
+ template <typename T>
+ struct S {};
+ template struct S<int>;
+
+ inline namespace INS {
+ template <typename T>
+ struct S {};
+ template struct S<int>;
+ }
+
+ }
+ )", Lang_CXX11, "input0.cc");
+ auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
+ TU, namespaceDecl());
+ auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
+ TU, classTemplateSpecializationDecl());
+ ASSERT_TRUE(NS->containsDecl(Spec));
+
+ NS->removeDecl(Spec);
+ EXPECT_FALSE(NS->containsDecl(Spec));
+}
+
+struct ImportFunctionTemplateSpecializations : ASTImporterTestBase {};
+
+TEST_P(ImportFunctionTemplateSpecializations,
+ TUshouldNotContainFunctionTemplateImplicitInstantiation) {
+
+ Decl *FromTU = getTuDecl(
+ R"(
+ template<class T>
+ int f() { return 0; }
+ void foo() { f<int>(); }
+ )",
+ Lang_CXX, "input0.cc");
+
+ // Check that the function template instantiation is NOT the child of the TU.
+ auto Pattern = translationUnitDecl(
+ unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
+ ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
+
+ auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
+ FromTU, functionDecl(hasName("foo")));
+ ASSERT_TRUE(Import(Foo, Lang_CXX));
+
+ auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+ EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
+}
+
+TEST_P(ImportFunctionTemplateSpecializations,
+ TUshouldNotContainFunctionTemplateExplicitInstantiation) {
+
+ Decl *FromTU = getTuDecl(
+ R"(
+ template<class T>
+ int f() { return 0; }
+ template int f<int>();
+ )",
+ Lang_CXX, "input0.cc");
+
+ // Check that the function template instantiation is NOT the child of the TU.
+ auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
+ auto Pattern = translationUnitDecl(unless(has(Instantiation)));
+ ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
+
+ ASSERT_TRUE(
+ Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX));
+
+ auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+ EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
+}
+
+TEST_P(ImportFunctionTemplateSpecializations,
+ TUshouldContainFunctionTemplateSpecialization) {
+
+ Decl *FromTU = getTuDecl(
+ R"(
+ template<class T>
+ int f() { return 0; }
+ template <> int f<int>() { return 4; }
+ )",
+ Lang_CXX, "input0.cc");
+
+ // Check that the function template specialization is the child of the TU.
+ auto Specialization =
+ functionDecl(hasName("f"), isExplicitTemplateSpecialization());
+ auto Pattern = translationUnitDecl(has(Specialization));
+ ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
+
+ ASSERT_TRUE(
+ Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX));
+
+ auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+ EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
+}
+
+TEST_P(ImportFunctionTemplateSpecializations,
+ FunctionTemplateSpecializationRedeclChain) {
+
+ Decl *FromTU = getTuDecl(
+ R"(
+ template<class T>
+ int f() { return 0; }
+ template <> int f<int>() { return 4; }
+ )",
+ Lang_CXX, "input0.cc");
+
+ auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
+ hasParent(translationUnitDecl()));
+ auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
+ {
+ auto *TU = FromTU;
+ auto *SpecD = FromSpecD;
+ auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
+ TU, functionTemplateDecl());
+ auto *FirstSpecD = *(TemplateD->spec_begin());
+ ASSERT_EQ(SpecD, FirstSpecD);
+ ASSERT_TRUE(SpecD->getPreviousDecl());
+ ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
+ ->doesThisDeclarationHaveABody());
+ }
+
+ ASSERT_TRUE(Import(FromSpecD, Lang_CXX));
+
+ {
+ auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
+ auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
+ auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
+ TU, functionTemplateDecl());
+ auto *FirstSpecD = *(TemplateD->spec_begin());
+ EXPECT_EQ(SpecD, FirstSpecD);
+ ASSERT_TRUE(SpecD->getPreviousDecl());
+ EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
+ ->doesThisDeclarationHaveABody());
+ }
+}
+
+TEST_P(ImportFunctionTemplateSpecializations,
+ MatchNumberOfFunctionTemplateSpecializations) {
+
+ Decl *FromTU = getTuDecl(
+ R"(
+ template <typename T> constexpr int f() { return 0; }
+ template <> constexpr int f<int>() { return 4; }
+ void foo() {
+ static_assert(f<char>() == 0, "");
+ static_assert(f<int>() == 4, "");
+ }
+ )",
+ Lang_CXX11, "input0.cc");
+ auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
+ FromTU, functionDecl(hasName("foo")));
+
+ Import(FromD, Lang_CXX11);
+ auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+ EXPECT_EQ(
+ DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
+ DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
+}
+
+TEST_P(ImportFunctionTemplateSpecializations,
+ ImportPrototypes) {
+ auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
+ auto Code =
+ R"(
+ // Proto of the primary template.
+ template <class T>
+ void f();
+ // Proto of the specialization.
+ template <>
+ void f<int>();
+ )";
+
+ Decl *ImportedD;
+ {
+ Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
+ auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+
+ ImportedD = Import(FromD, Lang_CXX);
+ }
+ {
+ Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");
+ auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+ Import(FromD, Lang_CXX);
+ }
+
+ Decl *ToTU = ImportedD->getTranslationUnitDecl();
+
+ EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
+ auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
+ auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
+ EXPECT_TRUE(ImportedD == To0);
+ EXPECT_TRUE(ImportedD != To1);
+ EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
+ EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
+ // Check that they are part of the same redecl chain.
+ EXPECT_EQ(To1->getCanonicalDecl(), To0->getCanonicalDecl());
+}
+
+TEST_P(ImportFunctionTemplateSpecializations, ImportDefinitions) {
+ auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
+ auto Code =
+ R"(
+ // Proto of the primary template.
+ template <class T>
+ void f();
+ // Specialization and definition.
+ template <>
+ void f<int>() {}
+ )";
+
+ Decl *ImportedD;
+ {
+ Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
+ auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+ ImportedD = Import(FromD, Lang_CXX);
+ }
+ {
+ Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");
+ auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+ Import(FromD, Lang_CXX);
+ }
+
+ Decl *ToTU = ImportedD->getTranslationUnitDecl();
+
+ EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
+ auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
+ EXPECT_TRUE(ImportedD == To0);
+ EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
+
+ auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
+ ToTU, functionTemplateDecl());
+ auto *FirstSpecD = *(TemplateD->spec_begin());
+ EXPECT_EQ(FirstSpecD->getCanonicalDecl(), To0->getCanonicalDecl());
+}
+
+TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenPrototype) {
+ auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
+ auto Code =
+ R"(
+ // Proto of the primary template.
+ template <class T>
+ void f();
+ // Specialization proto.
+ template <>
+ void f<int>();
+ // Specialization proto.
+ template <>
+ void f<int>();
+ )";
+
+ Decl *ImportedD;
+ {
+ Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
+ auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+ ImportedD = Import(FromD, Lang_CXX);
+ }
+
+ Decl *ToTU = ImportedD->getTranslationUnitDecl();
+
+ EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
+ auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
+ auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
+ EXPECT_TRUE(ImportedD == To0);
+ EXPECT_TRUE(ImportedD != To1);
+ EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
+ EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
+ EXPECT_EQ(To1->getPreviousDecl(), To0);
+}
+
+TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenDefinition) {
+ auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
+ auto Code =
+ R"(
+ // Proto of the primary template.
+ template <class T>
+ void f();
+ // Specialization proto.
+ template <>
+ void f<int>();
+ // Specialization definition.
+ template <>
+ void f<int>() {}
+ )";
+
+ Decl *ImportedD;
+ {
+ Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
+ auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+ ImportedD = Import(FromD, Lang_CXX);
+ }
+
+ Decl *ToTU = ImportedD->getTranslationUnitDecl();
+
+ EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
+ auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
+ auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
+ EXPECT_TRUE(ImportedD == To0);
+ EXPECT_TRUE(ImportedD != To1);
+ EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
+ EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
+ EXPECT_EQ(To1->getPreviousDecl(), To0);
+}
+
+TEST_P(ImportFunctionTemplateSpecializations, DefinitionThenPrototype) {
+ auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
+ auto Code =
+ R"(
+ // Proto of the primary template.
+ template <class T>
+ void f();
+ // Specialization definition.
+ template <>
+ void f<int>() {}
+ // Specialization proto.
+ template <>
+ void f<int>();
+ )";
+
+ Decl *ImportedD;
+ {
+ Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
+ auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+ ImportedD = Import(FromD, Lang_CXX);
+ }
+
+ Decl *ToTU = ImportedD->getTranslationUnitDecl();
+
+ EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
+ auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
+ auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
+ EXPECT_TRUE(ImportedD == To0);
+ EXPECT_TRUE(ImportedD != To1);
+ EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
+ EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
+ EXPECT_EQ(To1->getPreviousDecl(), To0);
+}
+
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
+ ::testing::Values(ArgVector()), );
+
+INSTANTIATE_TEST_CASE_P(
+ ParameterizedTests, CanonicalRedeclChain,
+ ::testing::Values(ArgVector()),);
+
+auto DefaultTestValuesForRunOptions = ::testing::Values(
+ ArgVector(),
+ ArgVector{"-fdelayed-template-parsing"},
+ ArgVector{"-fms-compatibility"},
+ ArgVector{"-fdelayed-template-parsing", "-fms-compatibility"});
+
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
+ DefaultTestValuesForRunOptions, );
+
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType,
+ DefaultTestValuesForRunOptions, );
+
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
+ DefaultTestValuesForRunOptions, );
+
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterTestBase,
+ DefaultTestValuesForRunOptions, );
+
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
+ DefaultTestValuesForRunOptions, );
+
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
+ DefaultTestValuesForRunOptions, );
+
+INSTANTIATE_TEST_CASE_P(ParameterizedTests,
+ ImportFunctionTemplateSpecializations,
+ DefaultTestValuesForRunOptions, );
+
} // end namespace ast_matchers
} // end namespace clang
diff --git a/unittests/AST/CMakeLists.txt b/unittests/AST/CMakeLists.txt
index 9839cdb1f2ec..776e3dcf6df0 100644
--- a/unittests/AST/CMakeLists.txt
+++ b/unittests/AST/CMakeLists.txt
@@ -9,15 +9,17 @@ add_clang_unittest(ASTTests
ASTVectorTest.cpp
CommentLexer.cpp
CommentParser.cpp
+ CommentTextTest.cpp
DataCollectionTest.cpp
DeclPrinterTest.cpp
DeclTest.cpp
EvaluateAsRValueTest.cpp
ExternalASTSourceTest.cpp
+ Language.cpp
NamedDeclPrinterTest.cpp
- PostOrderASTVisitor.cpp
SourceLocationTest.cpp
StmtPrinterTest.cpp
+ StructuralEquivalenceTest.cpp
)
target_link_libraries(ASTTests
diff --git a/unittests/AST/CommentTextTest.cpp b/unittests/AST/CommentTextTest.cpp
new file mode 100644
index 000000000000..04475f1c1061
--- /dev/null
+++ b/unittests/AST/CommentTextTest.cpp
@@ -0,0 +1,128 @@
+//===- unittest/AST/CommentTextTest.cpp - Comment text extraction test ----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Tests for user-friendly output formatting of comments, i.e.
+// RawComment::getFormattedText().
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/RawCommentList.h"
+#include "clang/Basic/CommentOptions.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticIDs.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 "llvm/Support/MemoryBuffer.h"
+#include <gtest/gtest.h>
+
+namespace clang {
+
+class CommentTextTest : public ::testing::Test {
+protected:
+ std::string formatComment(llvm::StringRef CommentText) {
+ SourceManagerForFile FileSourceMgr("comment-test.cpp", CommentText);
+ SourceManager& SourceMgr = FileSourceMgr.get();
+
+ auto CommentStartOffset = CommentText.find("/");
+ assert(CommentStartOffset != llvm::StringRef::npos);
+ FileID File = SourceMgr.getMainFileID();
+
+ SourceRange CommentRange(
+ SourceMgr.getLocForStartOfFile(File).getLocWithOffset(
+ CommentStartOffset),
+ SourceMgr.getLocForEndOfFile(File));
+ CommentOptions EmptyOpts;
+ // FIXME: technically, merged that we set here is incorrect, but that
+ // shouldn't matter.
+ RawComment Comment(SourceMgr, CommentRange, EmptyOpts, /*Merged=*/true);
+ DiagnosticsEngine Diags(new DiagnosticIDs, new DiagnosticOptions);
+ return Comment.getFormattedText(SourceMgr, Diags);
+ }
+};
+
+TEST_F(CommentTextTest, FormattedText) {
+ // clang-format off
+ auto ExpectedOutput =
+R"(This function does this and that.
+For example,
+ Runnning it in that case will give you
+ this result.
+That's about it.)";
+ // Two-slash comments.
+ auto Formatted = formatComment(
+R"cpp(
+// This function does this and that.
+// For example,
+// Runnning it in that case will give you
+// this result.
+// That's about it.)cpp");
+ EXPECT_EQ(ExpectedOutput, Formatted);
+
+ // Three-slash comments.
+ Formatted = formatComment(
+R"cpp(
+/// This function does this and that.
+/// For example,
+/// Runnning it in that case will give you
+/// this result.
+/// That's about it.)cpp");
+ EXPECT_EQ(ExpectedOutput, Formatted);
+
+ // Block comments.
+ Formatted = formatComment(
+R"cpp(
+/* This function does this and that.
+ * For example,
+ * Runnning it in that case will give you
+ * this result.
+ * That's about it.*/)cpp");
+ EXPECT_EQ(ExpectedOutput, Formatted);
+
+ // Doxygen-style block comments.
+ Formatted = formatComment(
+R"cpp(
+/** This function does this and that.
+ * For example,
+ * Runnning it in that case will give you
+ * this result.
+ * That's about it.*/)cpp");
+ EXPECT_EQ(ExpectedOutput, Formatted);
+
+ // Weird indentation.
+ Formatted = formatComment(
+R"cpp(
+ // This function does this and that.
+ // For example,
+ // Runnning it in that case will give you
+ // this result.
+ // That's about it.)cpp");
+ EXPECT_EQ(ExpectedOutput, Formatted);
+ // clang-format on
+}
+
+TEST_F(CommentTextTest, KeepsDoxygenControlSeqs) {
+ // clang-format off
+ auto ExpectedOutput =
+R"(\brief This is the brief part of the comment.
+\param a something about a.
+@param b something about b.)";
+
+ auto Formatted = formatComment(
+R"cpp(
+/// \brief This is the brief part of the comment.
+/// \param a something about a.
+/// @param b something about b.)cpp");
+ EXPECT_EQ(ExpectedOutput, Formatted);
+ // clang-format on
+}
+
+} // namespace clang
diff --git a/unittests/AST/DeclMatcher.h b/unittests/AST/DeclMatcher.h
new file mode 100644
index 000000000000..602f8dff07fe
--- /dev/null
+++ b/unittests/AST/DeclMatcher.h
@@ -0,0 +1,79 @@
+//===- unittest/AST/DeclMatcher.h - AST unit test support ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_UNITTESTS_AST_DECLMATCHER_H
+#define LLVM_CLANG_UNITTESTS_AST_DECLMATCHER_H
+
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+namespace clang {
+namespace ast_matchers {
+
+enum class DeclMatcherKind { First, Last };
+
+// Matcher class to retrieve the first/last matched node under a given AST.
+template <typename NodeType, DeclMatcherKind MatcherKind>
+class DeclMatcher : public MatchFinder::MatchCallback {
+ NodeType *Node = nullptr;
+ void run(const MatchFinder::MatchResult &Result) override {
+ if ((MatcherKind == DeclMatcherKind::First && Node == nullptr) ||
+ MatcherKind == DeclMatcherKind::Last) {
+ Node = const_cast<NodeType *>(Result.Nodes.getNodeAs<NodeType>(""));
+ }
+ }
+public:
+ // Returns the first/last matched node under the tree rooted in `D`.
+ template <typename MatcherType>
+ NodeType *match(const Decl *D, const MatcherType &AMatcher) {
+ MatchFinder Finder;
+ Finder.addMatcher(AMatcher.bind(""), this);
+ Finder.matchAST(D->getASTContext());
+ assert(Node);
+ return Node;
+ }
+};
+template <typename NodeType>
+using LastDeclMatcher = DeclMatcher<NodeType, DeclMatcherKind::Last>;
+template <typename NodeType>
+using FirstDeclMatcher = DeclMatcher<NodeType, DeclMatcherKind::First>;
+
+template <typename NodeType>
+class DeclCounterWithPredicate : public MatchFinder::MatchCallback {
+ using UnaryPredicate = std::function<bool(const NodeType *)>;
+ UnaryPredicate Predicate;
+ unsigned Count = 0;
+ void run(const MatchFinder::MatchResult &Result) override {
+ if (auto N = Result.Nodes.getNodeAs<NodeType>("")) {
+ if (Predicate(N))
+ ++Count;
+ }
+ }
+
+public:
+ DeclCounterWithPredicate()
+ : Predicate([](const NodeType *) { return true; }) {}
+ DeclCounterWithPredicate(UnaryPredicate P) : Predicate(P) {}
+ // Returns the number of matched nodes which satisfy the predicate under the
+ // tree rooted in `D`.
+ template <typename MatcherType>
+ unsigned match(const Decl *D, const MatcherType &AMatcher) {
+ MatchFinder Finder;
+ Finder.addMatcher(AMatcher.bind(""), this);
+ Finder.matchAST(D->getASTContext());
+ return Count;
+ }
+};
+
+template <typename NodeType>
+using DeclCounter = DeclCounterWithPredicate<NodeType>;
+
+} // end namespace ast_matchers
+} // end namespace clang
+
+#endif
diff --git a/unittests/AST/Language.cpp b/unittests/AST/Language.cpp
new file mode 100644
index 000000000000..5d1664019c7d
--- /dev/null
+++ b/unittests/AST/Language.cpp
@@ -0,0 +1,46 @@
+//===------ unittest/AST/Language.cpp - AST unit test support -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines language options for AST unittests.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Language.h"
+
+namespace clang {
+namespace ast_matchers {
+
+ArgVector getBasicRunOptionsForLanguage(Language Lang) {
+ ArgVector BasicArgs;
+ // Test with basic arguments.
+ switch (Lang) {
+ case Lang_C:
+ BasicArgs = {"-x", "c", "-std=c99"};
+ break;
+ case Lang_C89:
+ BasicArgs = {"-x", "c", "-std=c89"};
+ break;
+ case Lang_CXX:
+ BasicArgs = {"-std=c++98", "-frtti"};
+ break;
+ case Lang_CXX11:
+ BasicArgs = {"-std=c++11", "-frtti"};
+ break;
+ case Lang_CXX14:
+ BasicArgs = {"-std=c++14", "-frtti"};
+ break;
+ case Lang_OpenCL:
+ case Lang_OBJCXX:
+ llvm_unreachable("Not implemented yet!");
+ }
+ return BasicArgs;
+}
+
+} // end namespace ast_matchers
+} // end namespace clang
diff --git a/unittests/AST/Language.h b/unittests/AST/Language.h
new file mode 100644
index 000000000000..0eb2fb2417ca
--- /dev/null
+++ b/unittests/AST/Language.h
@@ -0,0 +1,41 @@
+//===------ unittest/AST/Language.h - AST unit test support ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines language options for AST unittests.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_UNITTESTS_AST_LANGUAGE_H
+#define LLVM_CLANG_UNITTESTS_AST_LANGUAGE_H
+
+#include "llvm/Support/ErrorHandling.h"
+#include <vector>
+#include <string>
+
+namespace clang {
+namespace ast_matchers {
+
+typedef std::vector<std::string> ArgVector;
+
+enum Language {
+ Lang_C,
+ Lang_C89,
+ Lang_CXX,
+ Lang_CXX11,
+ Lang_CXX14,
+ Lang_OpenCL,
+ Lang_OBJCXX
+};
+
+ArgVector getBasicRunOptionsForLanguage(Language Lang);
+
+} // end namespace ast_matchers
+} // end namespace clang
+
+#endif
diff --git a/unittests/AST/MatchVerifier.h b/unittests/AST/MatchVerifier.h
index 74b9bdfbe7e6..3e94d539f76a 100644
--- a/unittests/AST/MatchVerifier.h
+++ b/unittests/AST/MatchVerifier.h
@@ -23,20 +23,12 @@
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Tooling/Tooling.h"
+#include "Language.h"
#include "gtest/gtest.h"
namespace clang {
namespace ast_matchers {
-enum Language {
- Lang_C,
- Lang_C89,
- Lang_CXX,
- Lang_CXX11,
- Lang_OpenCL,
- Lang_OBJCXX
-};
-
/// \brief Base class for verifying some property of nodes found by a matcher.
template <typename NodeType>
class MatchVerifier : public MatchFinder::MatchCallback {
@@ -113,6 +105,10 @@ testing::AssertionResult MatchVerifier<NodeType>::match(
Args.push_back("-std=c++11");
FileName = "input.cc";
break;
+ case Lang_CXX14:
+ Args.push_back("-std=c++14");
+ FileName = "input.cc";
+ break;
case Lang_OpenCL:
FileName = "input.cl";
break;
diff --git a/unittests/AST/NamedDeclPrinterTest.cpp b/unittests/AST/NamedDeclPrinterTest.cpp
index 002bb28f374d..5715a341d813 100644
--- a/unittests/AST/NamedDeclPrinterTest.cpp
+++ b/unittests/AST/NamedDeclPrinterTest.cpp
@@ -173,3 +173,10 @@ TEST(NamedDeclPrinter, TestClassWithScopedNamedEnum) {
"A",
"X::Y::A"));
}
+
+TEST(NamedDeclPrinter, TestLinkageInNamespace) {
+ ASSERT_TRUE(PrintedWrittenNamedDeclCXX11Matches(
+ "namespace X { extern \"C\" { int A; } }",
+ "A",
+ "X::A"));
+}
diff --git a/unittests/AST/PostOrderASTVisitor.cpp b/unittests/AST/PostOrderASTVisitor.cpp
deleted file mode 100644
index 2921f3ead50e..000000000000
--- a/unittests/AST/PostOrderASTVisitor.cpp
+++ /dev/null
@@ -1,128 +0,0 @@
-//===- unittests/AST/PostOrderASTVisitor.cpp - Declaration printer tests --===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains tests for the post-order traversing functionality
-// of RecursiveASTVisitor.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/AST/RecursiveASTVisitor.h"
-#include "clang/Tooling/Tooling.h"
-#include "gtest/gtest.h"
-
-using namespace clang;
-
-namespace {
-
- class RecordingVisitor
- : public RecursiveASTVisitor<RecordingVisitor> {
-
- bool VisitPostOrder;
- public:
- explicit RecordingVisitor(bool VisitPostOrder)
- : VisitPostOrder(VisitPostOrder) {
- }
-
- // List of visited nodes during traversal.
- std::vector<std::string> VisitedNodes;
-
- bool shouldTraversePostOrder() const { return VisitPostOrder; }
-
- bool VisitUnaryOperator(UnaryOperator *Op) {
- VisitedNodes.push_back(Op->getOpcodeStr(Op->getOpcode()));
- return true;
- }
-
- bool VisitBinaryOperator(BinaryOperator *Op) {
- VisitedNodes.push_back(Op->getOpcodeStr());
- return true;
- }
-
- bool VisitIntegerLiteral(IntegerLiteral *Lit) {
- VisitedNodes.push_back(Lit->getValue().toString(10, false));
- return true;
- }
-
- bool VisitVarDecl(VarDecl* D) {
- VisitedNodes.push_back(D->getNameAsString());
- return true;
- }
-
- bool VisitCXXMethodDecl(CXXMethodDecl *D) {
- VisitedNodes.push_back(D->getQualifiedNameAsString());
- return true;
- }
-
- bool VisitReturnStmt(ReturnStmt *S) {
- VisitedNodes.push_back("return");
- return true;
- }
-
- bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) {
- VisitedNodes.push_back(Declaration->getQualifiedNameAsString());
- return true;
- }
-
- bool VisitTemplateTypeParmType(TemplateTypeParmType *T) {
- VisitedNodes.push_back(T->getDecl()->getQualifiedNameAsString());
- return true;
- }
- };
-
-}
-
-TEST(RecursiveASTVisitor, PostOrderTraversal) {
- auto ASTUnit = tooling::buildASTFromCode(
- "class A {"
- " class B {"
- " int foo() { while(4) { int i = 9; int j = -5; } return (1 + 3) + 2; }"
- " };"
- "};"
- );
- auto TU = ASTUnit->getASTContext().getTranslationUnitDecl();
- // We traverse the translation unit and store all
- // visited nodes.
- RecordingVisitor Visitor(true);
- Visitor.TraverseTranslationUnitDecl(TU);
-
- std::vector<std::string> expected = {"4", "9", "i", "5", "-",
- "j", "1", "3", "+", "2",
- "+", "return", "A::B::foo", "A::B", "A"};
- // Compare the list of actually visited nodes
- // with the expected list of visited nodes.
- ASSERT_EQ(expected.size(), Visitor.VisitedNodes.size());
- for (std::size_t I = 0; I < expected.size(); I++) {
- ASSERT_EQ(expected[I], Visitor.VisitedNodes[I]);
- }
-}
-
-TEST(RecursiveASTVisitor, NoPostOrderTraversal) {
- auto ASTUnit = tooling::buildASTFromCode(
- "class A {"
- " class B {"
- " int foo() { return 1 + 2; }"
- " };"
- "};"
- );
- auto TU = ASTUnit->getASTContext().getTranslationUnitDecl();
- // We traverse the translation unit and store all
- // visited nodes.
- RecordingVisitor Visitor(false);
- Visitor.TraverseTranslationUnitDecl(TU);
-
- std::vector<std::string> expected = {
- "A", "A::B", "A::B::foo", "return", "+", "1", "2"
- };
- // Compare the list of actually visited nodes
- // with the expected list of visited nodes.
- ASSERT_EQ(expected.size(), Visitor.VisitedNodes.size());
- for (std::size_t I = 0; I < expected.size(); I++) {
- ASSERT_EQ(expected[I], Visitor.VisitedNodes[I]);
- }
-}
diff --git a/unittests/AST/StructuralEquivalenceTest.cpp b/unittests/AST/StructuralEquivalenceTest.cpp
new file mode 100644
index 000000000000..d5b529c6b674
--- /dev/null
+++ b/unittests/AST/StructuralEquivalenceTest.cpp
@@ -0,0 +1,631 @@
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/AST/ASTStructuralEquivalence.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Tooling/Tooling.h"
+
+#include "Language.h"
+#include "DeclMatcher.h"
+
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace ast_matchers {
+
+using std::get;
+
+struct StructuralEquivalenceTest : ::testing::Test {
+ std::unique_ptr<ASTUnit> AST0, AST1;
+ std::string Code0, Code1; // Buffers for SourceManager
+
+ // Get a pair of node pointers into the synthesized AST from the given code
+ // snippets. To determine the returned node, a separate matcher is specified
+ // for both snippets. The first matching node is returned.
+ template <typename NodeType, typename MatcherType>
+ std::tuple<NodeType *, NodeType *> makeDecls(
+ const std::string &SrcCode0, const std::string &SrcCode1, Language Lang,
+ const MatcherType &Matcher0, const MatcherType &Matcher1) {
+ this->Code0 = SrcCode0;
+ this->Code1 = SrcCode1;
+ ArgVector Args = getBasicRunOptionsForLanguage(Lang);
+
+ const char *const InputFileName = "input.cc";
+
+ AST0 = tooling::buildASTFromCodeWithArgs(Code0, Args, InputFileName);
+ AST1 = tooling::buildASTFromCodeWithArgs(Code1, Args, InputFileName);
+
+ NodeType *D0 = FirstDeclMatcher<NodeType>().match(
+ AST0->getASTContext().getTranslationUnitDecl(), Matcher0);
+ NodeType *D1 = FirstDeclMatcher<NodeType>().match(
+ AST1->getASTContext().getTranslationUnitDecl(), Matcher1);
+
+ return std::make_tuple(D0, D1);
+ }
+
+ std::tuple<TranslationUnitDecl *, TranslationUnitDecl *> makeTuDecls(
+ const std::string &SrcCode0, const std::string &SrcCode1, Language Lang) {
+ this->Code0 = SrcCode0;
+ this->Code1 = SrcCode1;
+ ArgVector Args = getBasicRunOptionsForLanguage(Lang);
+
+ const char *const InputFileName = "input.cc";
+
+ AST0 = tooling::buildASTFromCodeWithArgs(Code0, Args, InputFileName);
+ AST1 = tooling::buildASTFromCodeWithArgs(Code1, Args, InputFileName);
+
+ return std::make_tuple(AST0->getASTContext().getTranslationUnitDecl(),
+ AST1->getASTContext().getTranslationUnitDecl());
+ }
+
+ // Get a pair of node pointers into the synthesized AST from the given code
+ // snippets. The same matcher is used for both snippets.
+ template <typename NodeType, typename MatcherType>
+ std::tuple<NodeType *, NodeType *> makeDecls(
+ const std::string &SrcCode0, const std::string &SrcCode1, Language Lang,
+ const MatcherType &AMatcher) {
+ return makeDecls<NodeType, MatcherType>(
+ SrcCode0, SrcCode1, Lang, AMatcher, AMatcher);
+ }
+
+ // Get a pair of Decl pointers to the synthesized declarations from the given
+ // code snippets. We search for the first NamedDecl with given name in both
+ // snippets.
+ std::tuple<NamedDecl *, NamedDecl *> makeNamedDecls(
+ const std::string &SrcCode0, const std::string &SrcCode1,
+ Language Lang, const char *const Identifier = "foo") {
+ auto Matcher = namedDecl(hasName(Identifier));
+ return makeDecls<NamedDecl>(SrcCode0, SrcCode1, Lang, Matcher);
+ }
+
+ bool testStructuralMatch(Decl *D0, Decl *D1) {
+ llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls;
+ StructuralEquivalenceContext Ctx(
+ D0->getASTContext(), D1->getASTContext(), NonEquivalentDecls,
+ StructuralEquivalenceKind::Default, false, false);
+ return Ctx.IsEquivalent(D0, D1);
+ }
+
+ bool testStructuralMatch(std::tuple<Decl *, Decl *> t) {
+ return testStructuralMatch(get<0>(t), get<1>(t));
+ }
+};
+
+TEST_F(StructuralEquivalenceTest, Int) {
+ auto Decls = makeNamedDecls("int foo;", "int foo;", Lang_CXX);
+ EXPECT_TRUE(testStructuralMatch(Decls));
+}
+
+TEST_F(StructuralEquivalenceTest, IntVsSignedInt) {
+ auto Decls = makeNamedDecls("int foo;", "signed int foo;", Lang_CXX);
+ EXPECT_TRUE(testStructuralMatch(Decls));
+}
+
+TEST_F(StructuralEquivalenceTest, Char) {
+ auto Decls = makeNamedDecls("char foo;", "char foo;", Lang_CXX);
+ EXPECT_TRUE(testStructuralMatch(Decls));
+}
+
+// This test is disabled for now.
+// FIXME Whether this is equivalent is dependendant on the target.
+TEST_F(StructuralEquivalenceTest, DISABLED_CharVsSignedChar) {
+ auto Decls = makeNamedDecls("char foo;", "signed char foo;", Lang_CXX);
+ EXPECT_FALSE(testStructuralMatch(Decls));
+}
+
+TEST_F(StructuralEquivalenceTest, ForwardRecordDecl) {
+ auto Decls = makeNamedDecls("struct foo;", "struct foo;", Lang_CXX);
+ EXPECT_TRUE(testStructuralMatch(Decls));
+}
+
+TEST_F(StructuralEquivalenceTest, IntVsSignedIntInStruct) {
+ auto Decls = makeNamedDecls("struct foo { int x; };",
+ "struct foo { signed int x; };", Lang_CXX);
+ EXPECT_TRUE(testStructuralMatch(Decls));
+}
+
+TEST_F(StructuralEquivalenceTest, CharVsSignedCharInStruct) {
+ auto Decls = makeNamedDecls("struct foo { char x; };",
+ "struct foo { signed char x; };", Lang_CXX);
+ EXPECT_FALSE(testStructuralMatch(Decls));
+}
+
+TEST_F(StructuralEquivalenceTest, IntVsSignedIntTemplateSpec) {
+ auto Decls = makeDecls<ClassTemplateSpecializationDecl>(
+ R"(template <class T> struct foo; template<> struct foo<int>{};)",
+ R"(template <class T> struct foo; template<> struct foo<signed int>{};)",
+ Lang_CXX,
+ classTemplateSpecializationDecl());
+ auto Spec0 = get<0>(Decls);
+ auto Spec1 = get<1>(Decls);
+ EXPECT_TRUE(testStructuralMatch(Spec0, Spec1));
+}
+
+TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpec) {
+ auto Decls = makeDecls<ClassTemplateSpecializationDecl>(
+ R"(template <class T> struct foo; template<> struct foo<char>{};)",
+ R"(template <class T> struct foo; template<> struct foo<signed char>{};)",
+ Lang_CXX,
+ classTemplateSpecializationDecl());
+ auto Spec0 = get<0>(Decls);
+ auto Spec1 = get<1>(Decls);
+ EXPECT_FALSE(testStructuralMatch(Spec0, Spec1));
+}
+
+TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpecWithInheritance) {
+ auto Decls = makeDecls<ClassTemplateSpecializationDecl>(
+ R"(
+ struct true_type{};
+ template <class T> struct foo;
+ template<> struct foo<char> : true_type {};
+ )",
+ R"(
+ struct true_type{};
+ template <class T> struct foo;
+ template<> struct foo<signed char> : true_type {};
+ )",
+ Lang_CXX,
+ classTemplateSpecializationDecl());
+ EXPECT_FALSE(testStructuralMatch(Decls));
+}
+
+// This test is disabled for now.
+// FIXME Enable it, once the check is implemented.
+TEST_F(StructuralEquivalenceTest, DISABLED_WrongOrderInNamespace) {
+ auto Code =
+ R"(
+ namespace NS {
+ template <class T> class Base {
+ int a;
+ };
+ class Derived : Base<Derived> {
+ };
+ }
+ void foo(NS::Derived &);
+ )";
+ auto Decls = makeNamedDecls(Code, Code, Lang_CXX);
+
+ NamespaceDecl *NS =
+ LastDeclMatcher<NamespaceDecl>().match(get<1>(Decls), namespaceDecl());
+ ClassTemplateDecl *TD = LastDeclMatcher<ClassTemplateDecl>().match(
+ get<1>(Decls), classTemplateDecl(hasName("Base")));
+
+ // Reorder the decls, move the TD to the last place in the DC.
+ NS->removeDecl(TD);
+ NS->addDeclInternal(TD);
+
+ EXPECT_FALSE(testStructuralMatch(Decls));
+}
+
+TEST_F(StructuralEquivalenceTest, WrongOrderOfFieldsInClass) {
+ auto Code = "class X { int a; int b; };";
+ auto Decls = makeNamedDecls(Code, Code, Lang_CXX, "X");
+
+ CXXRecordDecl *RD = FirstDeclMatcher<CXXRecordDecl>().match(
+ get<1>(Decls), cxxRecordDecl(hasName("X")));
+ FieldDecl *FD =
+ FirstDeclMatcher<FieldDecl>().match(get<1>(Decls), fieldDecl(hasName("a")));
+
+ // Reorder the FieldDecls
+ RD->removeDecl(FD);
+ RD->addDeclInternal(FD);
+
+ EXPECT_FALSE(testStructuralMatch(Decls));
+}
+
+struct StructuralEquivalenceFunctionTest : StructuralEquivalenceTest {
+};
+
+TEST_F(StructuralEquivalenceFunctionTest, ParamConstWithRef) {
+ auto t = makeNamedDecls("void foo(int&);",
+ "void foo(const int&);", Lang_CXX);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceFunctionTest, ParamConstSimple) {
+ auto t = makeNamedDecls("void foo(int);",
+ "void foo(const int);", Lang_CXX);
+ EXPECT_TRUE(testStructuralMatch(t));
+ // consider this OK
+}
+
+TEST_F(StructuralEquivalenceFunctionTest, Throw) {
+ auto t = makeNamedDecls("void foo();",
+ "void foo() throw();", Lang_CXX);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceFunctionTest, Noexcept) {
+ auto t = makeNamedDecls("void foo();",
+ "void foo() noexcept;", Lang_CXX11);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexcept) {
+ auto t = makeNamedDecls("void foo() throw();",
+ "void foo() noexcept;", Lang_CXX11);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexceptFalse) {
+ auto t = makeNamedDecls("void foo() throw();",
+ "void foo() noexcept(false);", Lang_CXX11);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexceptTrue) {
+ auto t = makeNamedDecls("void foo() throw();",
+ "void foo() noexcept(true);", Lang_CXX11);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceFunctionTest, DISABLED_NoexceptNonMatch) {
+ // The expression is not checked yet.
+ auto t = makeNamedDecls("void foo() noexcept(false);",
+ "void foo() noexcept(true);", Lang_CXX11);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceFunctionTest, NoexceptMatch) {
+ auto t = makeNamedDecls("void foo() noexcept(false);",
+ "void foo() noexcept(false);", Lang_CXX11);
+ EXPECT_TRUE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceFunctionTest, NoexceptVsNoexceptFalse) {
+ auto t = makeNamedDecls("void foo() noexcept;",
+ "void foo() noexcept(false);", Lang_CXX11);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceFunctionTest, NoexceptVsNoexceptTrue) {
+ auto t = makeNamedDecls("void foo() noexcept;",
+ "void foo() noexcept(true);", Lang_CXX11);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceFunctionTest, ReturnType) {
+ auto t = makeNamedDecls("char foo();",
+ "int foo();", Lang_CXX);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceFunctionTest, ReturnConst) {
+ auto t = makeNamedDecls("char foo();",
+ "const char foo();", Lang_CXX);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceFunctionTest, ReturnRef) {
+ auto t = makeNamedDecls("char &foo();",
+ "char &&foo();", Lang_CXX11);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceFunctionTest, ParamCount) {
+ auto t = makeNamedDecls("void foo(int);",
+ "void foo(int, int);", Lang_CXX);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceFunctionTest, ParamType) {
+ auto t = makeNamedDecls("void foo(int);",
+ "void foo(char);", Lang_CXX);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceFunctionTest, ParamName) {
+ auto t = makeNamedDecls("void foo(int a);",
+ "void foo(int b);", Lang_CXX);
+ EXPECT_TRUE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceFunctionTest, Variadic) {
+ auto t = makeNamedDecls("void foo(int x...);",
+ "void foo(int x);", Lang_CXX);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceFunctionTest, ParamPtr) {
+ auto t = makeNamedDecls("void foo(int *);",
+ "void foo(int);", Lang_CXX);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceFunctionTest, NameInParen) {
+ auto t = makeNamedDecls(
+ "void ((foo))();",
+ "void foo();",
+ Lang_CXX);
+ EXPECT_TRUE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceFunctionTest, NameInParenWithExceptionSpec) {
+ auto t = makeNamedDecls(
+ "void (foo)() throw(int);",
+ "void (foo)() noexcept;",
+ Lang_CXX11);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceFunctionTest, NameInParenWithConst) {
+ auto t = makeNamedDecls(
+ "struct A { void (foo)() const; };",
+ "struct A { void (foo)(); };",
+ Lang_CXX11);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+struct StructuralEquivalenceCXXMethodTest : StructuralEquivalenceTest {
+};
+
+TEST_F(StructuralEquivalenceCXXMethodTest, Virtual) {
+ auto t = makeDecls<CXXMethodDecl>(
+ "struct X { void foo(); };",
+ "struct X { virtual void foo(); };", Lang_CXX,
+ cxxMethodDecl(hasName("foo")));
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceCXXMethodTest, Pure) {
+ auto t = makeNamedDecls("struct X { virtual void foo(); };",
+ "struct X { virtual void foo() = 0; };", Lang_CXX);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceCXXMethodTest, DISABLED_Final) {
+ // The final-ness is not checked yet.
+ auto t = makeNamedDecls("struct X { virtual void foo(); };",
+ "struct X { virtual void foo() final; };", Lang_CXX);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceCXXMethodTest, Const) {
+ auto t = makeNamedDecls("struct X { void foo(); };",
+ "struct X { void foo() const; };", Lang_CXX);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceCXXMethodTest, Static) {
+ auto t = makeNamedDecls("struct X { void foo(); };",
+ "struct X { static void foo(); };", Lang_CXX);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceCXXMethodTest, Ref1) {
+ auto t = makeNamedDecls("struct X { void foo(); };",
+ "struct X { void foo() &&; };", Lang_CXX11);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceCXXMethodTest, Ref2) {
+ auto t = makeNamedDecls("struct X { void foo() &; };",
+ "struct X { void foo() &&; };", Lang_CXX11);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceCXXMethodTest, AccessSpecifier) {
+ auto t = makeDecls<CXXMethodDecl>(
+ "struct X { public: void foo(); };",
+ "struct X { private: void foo(); };", Lang_CXX,
+ cxxMethodDecl(hasName("foo")));
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceCXXMethodTest, Delete) {
+ auto t = makeNamedDecls("struct X { void foo(); };",
+ "struct X { void foo() = delete; };", Lang_CXX11);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceCXXMethodTest, Constructor) {
+ auto t = makeDecls<FunctionDecl>(
+ "void foo();", "struct foo { foo(); };", Lang_CXX,
+ functionDecl(hasName("foo")), cxxConstructorDecl(hasName("foo")));
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorParam) {
+ auto t = makeDecls<CXXConstructorDecl>("struct X { X(); };",
+ "struct X { X(int); };", Lang_CXX,
+ cxxConstructorDecl(hasName("X")));
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorExplicit) {
+ auto t = makeDecls<CXXConstructorDecl>("struct X { X(int); };",
+ "struct X { explicit X(int); };",
+ Lang_CXX11,
+ cxxConstructorDecl(hasName("X")));
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorDefault) {
+ auto t = makeDecls<CXXConstructorDecl>("struct X { X(); };",
+ "struct X { X() = default; };",
+ Lang_CXX11,
+ cxxConstructorDecl(hasName("X")));
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceCXXMethodTest, Conversion) {
+ auto t = makeDecls<CXXConversionDecl>("struct X { operator bool(); };",
+ "struct X { operator char(); };",
+ Lang_CXX11,
+ cxxConversionDecl());
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceCXXMethodTest, Operator) {
+ auto t = makeDecls<FunctionDecl>(
+ "struct X { int operator +(int); };",
+ "struct X { int operator -(int); };", Lang_CXX,
+ functionDecl(hasOverloadedOperatorName("+")),
+ functionDecl(hasOverloadedOperatorName("-")));
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceCXXMethodTest, OutOfClass1) {
+ auto t = makeDecls<FunctionDecl>(
+ "struct X { virtual void f(); }; void X::f() { }",
+ "struct X { virtual void f() { }; };",
+ Lang_CXX,
+ functionDecl(allOf(hasName("f"), isDefinition())));
+ EXPECT_TRUE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceCXXMethodTest, OutOfClass2) {
+ auto t = makeDecls<FunctionDecl>(
+ "struct X { virtual void f(); }; void X::f() { }",
+ "struct X { void f(); }; void X::f() { }",
+ Lang_CXX,
+ functionDecl(allOf(hasName("f"), isDefinition())));
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+struct StructuralEquivalenceRecordTest : StructuralEquivalenceTest {
+ // FIXME Use a common getRecordDecl with ASTImporterTest.cpp!
+ RecordDecl *getRecordDecl(FieldDecl *FD) {
+ auto *ET = cast<ElaboratedType>(FD->getType().getTypePtr());
+ return cast<RecordType>(ET->getNamedType().getTypePtr())->getDecl();
+ };
+};
+
+TEST_F(StructuralEquivalenceRecordTest, Name) {
+ auto t = makeDecls<CXXRecordDecl>(
+ "struct A{ };",
+ "struct B{ };",
+ Lang_CXX,
+ cxxRecordDecl(hasName("A")),
+ cxxRecordDecl(hasName("B")));
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceRecordTest, Fields) {
+ auto t = makeNamedDecls(
+ "struct foo{ int x; };",
+ "struct foo{ char x; };",
+ Lang_CXX);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceRecordTest, DISABLED_Methods) {
+ // Currently, methods of a class are not checked at class equivalence.
+ auto t = makeNamedDecls(
+ "struct foo{ int x(); };",
+ "struct foo{ char x(); };",
+ Lang_CXX);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceRecordTest, Bases) {
+ auto t = makeNamedDecls(
+ "struct A{ }; struct foo: A { };",
+ "struct B{ }; struct foo: B { };",
+ Lang_CXX);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceRecordTest, InheritanceVirtual) {
+ auto t = makeNamedDecls(
+ "struct A{ }; struct foo: A { };",
+ "struct A{ }; struct foo: virtual A { };",
+ Lang_CXX);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceRecordTest, DISABLED_InheritanceType) {
+ // Access specifier in inheritance is not checked yet.
+ auto t = makeNamedDecls(
+ "struct A{ }; struct foo: public A { };",
+ "struct A{ }; struct foo: private A { };",
+ Lang_CXX);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceRecordTest, Match) {
+ auto Code = R"(
+ struct A{ };
+ struct B{ };
+ struct foo: A, virtual B {
+ void x();
+ int a;
+ };
+ )";
+ auto t = makeNamedDecls(Code, Code, Lang_CXX);
+ EXPECT_TRUE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceRecordTest, UnnamedRecordsShouldBeInequivalent) {
+ auto t = makeTuDecls(
+ R"(
+ struct A {
+ struct {
+ struct A *next;
+ } entry0;
+ struct {
+ struct A *next;
+ } entry1;
+ };
+ )",
+ "", Lang_C);
+ auto *TU = get<0>(t);
+ auto *Entry0 =
+ FirstDeclMatcher<FieldDecl>().match(TU, fieldDecl(hasName("entry0")));
+ auto *Entry1 =
+ FirstDeclMatcher<FieldDecl>().match(TU, fieldDecl(hasName("entry1")));
+ auto *R0 = getRecordDecl(Entry0);
+ auto *R1 = getRecordDecl(Entry1);
+
+ ASSERT_NE(R0, R1);
+ EXPECT_TRUE(testStructuralMatch(R0, R0));
+ EXPECT_TRUE(testStructuralMatch(R1, R1));
+ EXPECT_FALSE(testStructuralMatch(R0, R1));
+}
+
+TEST_F(StructuralEquivalenceRecordTest,
+ UnnamedRecordsShouldBeInequivalentEvenIfTheSecondIsBeingDefined) {
+ auto Code =
+ R"(
+ struct A {
+ struct {
+ struct A *next;
+ } entry0;
+ struct {
+ struct A *next;
+ } entry1;
+ };
+ )";
+ auto t = makeTuDecls(Code, Code, Lang_C);
+
+ auto *FromTU = get<0>(t);
+ auto *Entry1 =
+ FirstDeclMatcher<FieldDecl>().match(FromTU, fieldDecl(hasName("entry1")));
+
+ auto *ToTU = get<1>(t);
+ auto *Entry0 =
+ FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));
+ auto *A =
+ FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
+ A->startDefinition(); // Set isBeingDefined, getDefinition() will return a
+ // nullptr. This may be the case during ASTImport.
+
+ auto *R0 = getRecordDecl(Entry0);
+ auto *R1 = getRecordDecl(Entry1);
+
+ ASSERT_NE(R0, R1);
+ EXPECT_TRUE(testStructuralMatch(R0, R0));
+ EXPECT_TRUE(testStructuralMatch(R1, R1));
+ EXPECT_FALSE(testStructuralMatch(R0, R1));
+}
+
+
+TEST_F(StructuralEquivalenceTest, CompareSameDeclWithMultiple) {
+ auto t = makeNamedDecls(
+ "struct A{ }; struct B{ }; void foo(A a, A b);",
+ "struct A{ }; struct B{ }; void foo(A a, B b);",
+ Lang_CXX);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+} // end namespace ast_matchers
+} // end namespace clang
diff --git a/unittests/ASTMatchers/ASTMatchersInternalTest.cpp b/unittests/ASTMatchers/ASTMatchersInternalTest.cpp
index c12056f4440a..288fce08a8d9 100644
--- a/unittests/ASTMatchers/ASTMatchersInternalTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersInternalTest.cpp
@@ -189,7 +189,7 @@ TEST(IsInlineMatcher, IsInline) {
// FIXME: Figure out how to specify paths so the following tests pass on
// Windows.
-#ifndef LLVM_ON_WIN32
+#ifndef _WIN32
TEST(Matcher, IsExpansionInMainFileMatcher) {
EXPECT_TRUE(matches("class X {};",
@@ -234,7 +234,7 @@ TEST(Matcher, IsExpansionInFileMatching) {
"-isystem/", M));
}
-#endif // LLVM_ON_WIN32
+#endif // _WIN32
} // end namespace ast_matchers
} // end namespace clang
diff --git a/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
index 7e7d02707112..1e7b10e99e71 100644
--- a/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -894,6 +894,10 @@ TEST(isConstexpr, MatchesConstexprDeclarations) {
varDecl(hasName("foo"), isConstexpr())));
EXPECT_TRUE(matches("constexpr int bar();",
functionDecl(hasName("bar"), isConstexpr())));
+ EXPECT_TRUE(matchesConditionally("void baz() { if constexpr(1 > 0) {} }",
+ ifStmt(isConstexpr()), true, "-std=c++17"));
+ EXPECT_TRUE(matchesConditionally("void baz() { if (1 > 0) {} }",
+ ifStmt(isConstexpr()), false, "-std=c++17"));
}
TEST(TemplateArgumentCountIs, Matches) {
@@ -1350,6 +1354,16 @@ TEST(Matcher, HandlesNullQualTypes) {
))))));
}
+TEST(ObjCIvarRefExprMatcher, IvarExpr) {
+ std::string ObjCString =
+ "@interface A @end "
+ "@implementation A { A *x; } - (void) func { x = 0; } @end";
+ EXPECT_TRUE(matchesObjC(ObjCString, objcIvarRefExpr()));
+ EXPECT_TRUE(matchesObjC(ObjCString, objcIvarRefExpr(
+ hasDeclaration(namedDecl(hasName("x"))))));
+ EXPECT_FALSE(matchesObjC(ObjCString, objcIvarRefExpr(
+ hasDeclaration(namedDecl(hasName("y"))))));
+}
TEST(StatementCountIs, FindsNoStatementsInAnEmptyCompoundStatement) {
EXPECT_TRUE(matches("void f() { }",
@@ -1623,6 +1637,14 @@ TEST(IsTemplateInstantiation, MatchesExplicitClassTemplateInstantiation) {
"template class X<A>;",
cxxRecordDecl(isTemplateInstantiation(), hasDescendant(
fieldDecl(hasType(recordDecl(hasName("A"))))))));
+
+ // Make sure that we match the instantiation instead of the template
+ // definition by checking whether the member function is present.
+ EXPECT_TRUE(
+ matches("template <typename T> class X { void f() { T t; } };"
+ "extern template class X<int>;",
+ cxxRecordDecl(isTemplateInstantiation(),
+ unless(hasDescendant(varDecl(hasName("t")))))));
}
TEST(IsTemplateInstantiation,
@@ -1770,6 +1792,84 @@ TEST(IsExplicitTemplateSpecialization,
functionDecl(isExplicitTemplateSpecialization())));
}
+TEST(TypeMatching, MatchesNoReturn) {
+ EXPECT_TRUE(notMatches("void func();", functionDecl(isNoReturn())));
+ EXPECT_TRUE(notMatches("void func() {}", functionDecl(isNoReturn())));
+
+ EXPECT_TRUE(notMatchesC("void func();", functionDecl(isNoReturn())));
+ EXPECT_TRUE(notMatchesC("void func() {}", functionDecl(isNoReturn())));
+
+ EXPECT_TRUE(
+ notMatches("struct S { void func(); };", functionDecl(isNoReturn())));
+ EXPECT_TRUE(
+ notMatches("struct S { void func() {} };", functionDecl(isNoReturn())));
+
+ EXPECT_TRUE(notMatches("struct S { static void func(); };",
+ functionDecl(isNoReturn())));
+ EXPECT_TRUE(notMatches("struct S { static void func() {} };",
+ functionDecl(isNoReturn())));
+
+ EXPECT_TRUE(notMatches("struct S { S(); };", functionDecl(isNoReturn())));
+ EXPECT_TRUE(notMatches("struct S { S() {} };", functionDecl(isNoReturn())));
+
+ // ---
+
+ EXPECT_TRUE(matches("[[noreturn]] void func();", functionDecl(isNoReturn())));
+ EXPECT_TRUE(
+ matches("[[noreturn]] void func() {}", functionDecl(isNoReturn())));
+
+ EXPECT_TRUE(matches("struct S { [[noreturn]] void func(); };",
+ functionDecl(isNoReturn())));
+ EXPECT_TRUE(matches("struct S { [[noreturn]] void func() {} };",
+ functionDecl(isNoReturn())));
+
+ EXPECT_TRUE(matches("struct S { [[noreturn]] static void func(); };",
+ functionDecl(isNoReturn())));
+ EXPECT_TRUE(matches("struct S { [[noreturn]] static void func() {} };",
+ functionDecl(isNoReturn())));
+
+ EXPECT_TRUE(
+ matches("struct S { [[noreturn]] S(); };", functionDecl(isNoReturn())));
+ EXPECT_TRUE(matches("struct S { [[noreturn]] S() {} };",
+ functionDecl(isNoReturn())));
+
+ // ---
+
+ EXPECT_TRUE(matches("__attribute__((noreturn)) void func();",
+ functionDecl(isNoReturn())));
+ EXPECT_TRUE(matches("__attribute__((noreturn)) void func() {}",
+ functionDecl(isNoReturn())));
+
+ EXPECT_TRUE(matches("struct S { __attribute__((noreturn)) void func(); };",
+ functionDecl(isNoReturn())));
+ EXPECT_TRUE(matches("struct S { __attribute__((noreturn)) void func() {} };",
+ functionDecl(isNoReturn())));
+
+ EXPECT_TRUE(
+ matches("struct S { __attribute__((noreturn)) static void func(); };",
+ functionDecl(isNoReturn())));
+ EXPECT_TRUE(
+ matches("struct S { __attribute__((noreturn)) static void func() {} };",
+ functionDecl(isNoReturn())));
+
+ EXPECT_TRUE(matches("struct S { __attribute__((noreturn)) S(); };",
+ functionDecl(isNoReturn())));
+ EXPECT_TRUE(matches("struct S { __attribute__((noreturn)) S() {} };",
+ functionDecl(isNoReturn())));
+
+ // ---
+
+ EXPECT_TRUE(matchesC("__attribute__((noreturn)) void func();",
+ functionDecl(isNoReturn())));
+ EXPECT_TRUE(matchesC("__attribute__((noreturn)) void func() {}",
+ functionDecl(isNoReturn())));
+
+ EXPECT_TRUE(matchesC("_Noreturn void func();",
+ functionDecl(isNoReturn())));
+ EXPECT_TRUE(matchesC("_Noreturn void func() {}",
+ functionDecl(isNoReturn())));
+}
+
TEST(TypeMatching, MatchesBool) {
EXPECT_TRUE(matches("struct S { bool func(); };",
cxxMethodDecl(returns(booleanType()))));
@@ -2029,5 +2129,52 @@ TEST(HasDefinition, MatchesUnionDefinition) {
cxxRecordDecl(hasDefinition())));
}
+TEST(IsScopedEnum, MatchesScopedEnum) {
+ EXPECT_TRUE(matches("enum class X {};", enumDecl(isScoped())));
+ EXPECT_TRUE(notMatches("enum X {};", enumDecl(isScoped())));
+}
+
+TEST(HasTrailingReturn, MatchesTrailingReturn) {
+ EXPECT_TRUE(matches("auto Y() -> int { return 0; }",
+ functionDecl(hasTrailingReturn())));
+ EXPECT_TRUE(matches("auto X() -> int;", functionDecl(hasTrailingReturn())));
+ EXPECT_TRUE(notMatches("int X() { return 0; }",
+ functionDecl(hasTrailingReturn())));
+ EXPECT_TRUE(notMatches("int X();", functionDecl(hasTrailingReturn())));
+ EXPECT_TRUE(notMatchesC("void X();", functionDecl(hasTrailingReturn())));
+}
+
+TEST(HasTrailingReturn, MatchesLambdaTrailingReturn) {
+ EXPECT_TRUE(matches(
+ "auto lambda2 = [](double x, double y) -> double {return x + y;};",
+ functionDecl(hasTrailingReturn())));
+ EXPECT_TRUE(notMatches(
+ "auto lambda2 = [](double x, double y) {return x + y;};",
+ functionDecl(hasTrailingReturn())));
+}
+
+TEST(IsAssignmentOperator, Basic) {
+ StatementMatcher BinAsgmtOperator = binaryOperator(isAssignmentOperator());
+ StatementMatcher CXXAsgmtOperator =
+ cxxOperatorCallExpr(isAssignmentOperator());
+
+ EXPECT_TRUE(matches("void x() { int a; a += 1; }", BinAsgmtOperator));
+ EXPECT_TRUE(matches("void x() { int a; a = 2; }", BinAsgmtOperator));
+ EXPECT_TRUE(matches("void x() { int a; a &= 3; }", BinAsgmtOperator));
+ EXPECT_TRUE(matches("struct S { S& operator=(const S&); };"
+ "void x() { S s1, s2; s1 = s2; }",
+ CXXAsgmtOperator));
+ EXPECT_TRUE(
+ notMatches("void x() { int a; if(a == 0) return; }", BinAsgmtOperator));
+}
+
+TEST(Matcher, isMain) {
+ EXPECT_TRUE(
+ matches("int main() {}", functionDecl(isMain())));
+
+ EXPECT_TRUE(
+ notMatches("int main2() {}", functionDecl(isMain())));
+}
+
} // namespace ast_matchers
} // namespace clang
diff --git a/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
index 59fadadbedc7..e521940983b2 100644
--- a/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -160,6 +160,16 @@ TEST(ValueDecl, Matches) {
valueDecl(hasType(asString("void (void)")))));
}
+TEST(FriendDecl, Matches) {
+ EXPECT_TRUE(matches("class Y { friend class X; };",
+ friendDecl(hasType(asString("class X")))));
+ EXPECT_TRUE(matches("class Y { friend class X; };",
+ friendDecl(hasType(recordDecl(hasName("X"))))));
+
+ EXPECT_TRUE(matches("class Y { friend void f(); };",
+ functionDecl(hasName("f"), hasParent(friendDecl()))));
+}
+
TEST(Enum, DoesNotMatchClasses) {
EXPECT_TRUE(notMatches("class X {};", enumDecl(hasName("X"))));
}
@@ -1196,6 +1206,12 @@ TEST(TypeMatching, MatchesAutoTypes) {
// autoType(hasDeducedType(isInteger()))));
}
+TEST(TypeMatching, MatchesDeclTypes) {
+ EXPECT_TRUE(matches("decltype(1 + 1) sum = 1 + 1;", decltypeType()));
+ EXPECT_TRUE(matches("decltype(1 + 1) sum = 1 + 1;",
+ decltypeType(hasUnderlyingType(isInteger()))));
+}
+
TEST(TypeMatching, MatchesFunctionTypes) {
EXPECT_TRUE(matches("int (*f)(int);", functionType()));
EXPECT_TRUE(matches("void f(int i) {}", functionType()));
@@ -1450,6 +1466,10 @@ TEST(NNS, MatchesNestedNameSpecifierPrefixes) {
"struct A { struct B { struct C {}; }; }; A::B::C c;",
nestedNameSpecifierLoc(hasPrefix(
specifiesTypeLoc(loc(qualType(asString("struct A"))))))));
+ EXPECT_TRUE(matches(
+ "namespace N { struct A { struct B { struct C {}; }; }; } N::A::B::C c;",
+ nestedNameSpecifierLoc(hasPrefix(
+ specifiesTypeLoc(loc(qualType(asString("struct N::A"))))))));
}
@@ -1565,11 +1585,22 @@ TEST(ObjCMessageExprMatcher, SimpleExprs) {
EXPECT_TRUE(matchesObjC(
Objc1String,
objcMessageExpr(anything())));
+ EXPECT_TRUE(matchesObjC(Objc1String,
+ objcMessageExpr(hasAnySelector({
+ "contents", "meth:"}))
+
+ ));
EXPECT_TRUE(matchesObjC(
Objc1String,
objcMessageExpr(hasSelector("contents"))));
EXPECT_TRUE(matchesObjC(
Objc1String,
+ objcMessageExpr(hasAnySelector("contents", "contentsA"))));
+ EXPECT_FALSE(matchesObjC(
+ Objc1String,
+ objcMessageExpr(hasAnySelector("contentsB", "contentsC"))));
+ EXPECT_TRUE(matchesObjC(
+ Objc1String,
objcMessageExpr(matchesSelector("cont*"))));
EXPECT_FALSE(matchesObjC(
Objc1String,
@@ -1662,5 +1693,17 @@ TEST(ObjCStmtMatcher, ExceptionStmts) {
objcFinallyStmt()));
}
+TEST(ObjCAutoreleaseMatcher, AutoreleasePool) {
+ std::string ObjCString =
+ "void f() {"
+ "@autoreleasepool {"
+ " int x = 1;"
+ "}"
+ "}";
+ EXPECT_TRUE(matchesObjC(ObjCString, autoreleasePoolStmt()));
+ std::string ObjCStringNoPool = "void f() { int x = 1; }";
+ EXPECT_FALSE(matchesObjC(ObjCStringNoPool, autoreleasePoolStmt()));
+}
+
} // namespace ast_matchers
} // namespace clang
diff --git a/unittests/ASTMatchers/ASTMatchersTest.h b/unittests/ASTMatchers/ASTMatchersTest.h
index 7cfe5b9e3709..504668872f4f 100644
--- a/unittests/ASTMatchers/ASTMatchersTest.h
+++ b/unittests/ASTMatchers/ASTMatchersTest.h
@@ -132,7 +132,7 @@ testing::AssertionResult matchesObjC(const std::string &Code, const T &AMatcher,
bool ExpectMatch = true) {
return matchesConditionally(Code, AMatcher, ExpectMatch,
{"-fobjc-nonfragile-abi", "-Wno-objc-root-class",
- "-Wno-incomplete-implementation"},
+ "-fblocks", "-Wno-incomplete-implementation"},
FileContentMappings(), "input.m");
}
diff --git a/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
index e699e19262e2..3b8f362101a6 100644
--- a/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -403,11 +403,18 @@ TEST(Matcher, Argument) {
}
TEST(Matcher, AnyArgument) {
- StatementMatcher CallArgumentY = callExpr(
- hasAnyArgument(
- ignoringParenImpCasts(declRefExpr(to(varDecl(hasName("y")))))));
+ auto HasArgumentY = hasAnyArgument(
+ ignoringParenImpCasts(declRefExpr(to(varDecl(hasName("y"))))));
+ StatementMatcher CallArgumentY = callExpr(HasArgumentY);
+ StatementMatcher ObjCCallArgumentY = objcMessageExpr(HasArgumentY);
EXPECT_TRUE(matches("void x(int, int) { int y; x(1, y); }", CallArgumentY));
EXPECT_TRUE(matches("void x(int, int) { int y; x(y, 42); }", CallArgumentY));
+ EXPECT_TRUE(matchesObjC("@interface I -(void)f:(int) y; @end "
+ "void x(I* i) { int y; [i f:y]; }",
+ ObjCCallArgumentY));
+ EXPECT_FALSE(matchesObjC("@interface I -(void)f:(int) z; @end "
+ "void x(I* i) { int z; [i f:z]; }",
+ ObjCCallArgumentY));
EXPECT_TRUE(notMatches("void x(int, int) { x(1, 2); }", CallArgumentY));
StatementMatcher ImplicitCastedArgument = callExpr(
@@ -415,6 +422,35 @@ TEST(Matcher, AnyArgument) {
EXPECT_TRUE(matches("void x(long) { int y; x(y); }", ImplicitCastedArgument));
}
+TEST(Matcher, HasReceiver) {
+ EXPECT_TRUE(matchesObjC(
+ "@interface NSString @end "
+ "void f(NSString *x) {"
+ "[x containsString];"
+ "}",
+ objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x"))))))));
+
+ EXPECT_FALSE(matchesObjC(
+ "@interface NSString +(NSString *) stringWithFormat; @end "
+ "void f() { [NSString stringWithFormat]; }",
+ objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x"))))))));
+}
+
+TEST(Matcher, isInstanceMessage) {
+ EXPECT_TRUE(matchesObjC(
+ "@interface NSString @end "
+ "void f(NSString *x) {"
+ "[x containsString];"
+ "}",
+ objcMessageExpr(isInstanceMessage())));
+
+ EXPECT_FALSE(matchesObjC(
+ "@interface NSString +(NSString *) stringWithFormat; @end "
+ "void f() { [NSString stringWithFormat]; }",
+ objcMessageExpr(isInstanceMessage())));
+
+}
+
TEST(ForEachArgumentWithParam, ReportsNoFalsePositives) {
StatementMatcher ArgumentY =
declRefExpr(to(varDecl(hasName("y")))).bind("arg");
@@ -532,6 +568,10 @@ TEST(HasParameter, CallsInnerMatcher) {
cxxMethodDecl(hasParameter(0, varDecl()))));
EXPECT_TRUE(notMatches("class X { void x(int) {} };",
cxxMethodDecl(hasParameter(0, hasName("x")))));
+ EXPECT_TRUE(matchesObjC("@interface I -(void)f:(int) x; @end",
+ objcMethodDecl(hasParameter(0, hasName("x")))));
+ EXPECT_TRUE(matchesObjC("int main() { void (^b)(int) = ^(int p) {}; }",
+ blockDecl(hasParameter(0, hasName("p")))));
}
TEST(HasParameter, DoesNotMatchIfIndexOutOfBounds) {
@@ -561,6 +601,10 @@ TEST(HasAnyParameter, MatchesIndependentlyOfPosition) {
EXPECT_TRUE(matches(
"class Y {}; class X { void x(Y y, X x) {} };",
cxxMethodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
+ EXPECT_TRUE(matchesObjC("@interface I -(void)f:(int) x; @end",
+ objcMethodDecl(hasAnyParameter(hasName("x")))));
+ EXPECT_TRUE(matchesObjC("int main() { void (^b)(int) = ^(int p) {}; }",
+ blockDecl(hasAnyParameter(hasName("p")))));
}
TEST(Returns, MatchesReturnTypes) {
diff --git a/unittests/ASTMatchers/CMakeLists.txt b/unittests/ASTMatchers/CMakeLists.txt
index a876fc2d3360..ae1aecf503cc 100644
--- a/unittests/ASTMatchers/CMakeLists.txt
+++ b/unittests/ASTMatchers/CMakeLists.txt
@@ -15,7 +15,8 @@ add_clang_unittest(ASTMatchersTests
ASTMatchersInternalTest.cpp
ASTMatchersNodeTest.cpp
ASTMatchersNarrowingTest.cpp
- ASTMatchersTraversalTest.cpp)
+ ASTMatchersTraversalTest.cpp
+ )
target_link_libraries(ASTMatchersTests
PRIVATE
diff --git a/unittests/ASTMatchers/Dynamic/CMakeLists.txt b/unittests/ASTMatchers/Dynamic/CMakeLists.txt
index 848a820adead..0fd96e97cff0 100644
--- a/unittests/ASTMatchers/Dynamic/CMakeLists.txt
+++ b/unittests/ASTMatchers/Dynamic/CMakeLists.txt
@@ -5,7 +5,8 @@ set(LLVM_LINK_COMPONENTS
add_clang_unittest(DynamicASTMatchersTests
VariantValueTest.cpp
ParserTest.cpp
- RegistryTest.cpp)
+ RegistryTest.cpp
+ )
target_link_libraries(DynamicASTMatchersTests
PRIVATE
diff --git a/unittests/ASTMatchers/Dynamic/ParserTest.cpp b/unittests/ASTMatchers/Dynamic/ParserTest.cpp
index 0c4c7dfd7802..d670e3129b80 100644
--- a/unittests/ASTMatchers/Dynamic/ParserTest.cpp
+++ b/unittests/ASTMatchers/Dynamic/ParserTest.cpp
@@ -186,8 +186,8 @@ using ast_matchers::internal::Matcher;
Parser::NamedValueMap getTestNamedValues() {
Parser::NamedValueMap Values;
Values["nameX"] = llvm::StringRef("x");
- Values["hasParamA"] =
- VariantMatcher::SingleMatcher(hasParameter(0, hasName("a")));
+ Values["hasParamA"] = VariantMatcher::SingleMatcher(
+ functionDecl(hasParameter(0, hasName("a"))));
return Values;
}
@@ -236,6 +236,17 @@ TEST(ParserTest, FullParserTest) {
Error.toStringFull());
}
+TEST(ParserTest, VariadicMatchTest) {
+ Diagnostics Error;
+ llvm::Optional<DynTypedMatcher> OM(Parser::parseMatcherExpression(
+ "stmt(objcMessageExpr(hasAnySelector(\"methodA\", \"methodB:\")))",
+ &Error));
+ EXPECT_EQ("", Error.toStringFull());
+ auto M = OM->unconditionalConvertTo<Stmt>();
+ EXPECT_TRUE(matchesObjC("@interface I @end "
+ "void foo(I* i) { [i methodA]; }", M));
+}
+
std::string ParseWithError(StringRef Code) {
Diagnostics Error;
VariantValue Value;
@@ -329,16 +340,17 @@ TEST(ParserTest, CompletionNamedValues) {
EXPECT_LT(0u, Comps.size());
// Can complete names and registry together.
- Code = "cxxMethodDecl(hasP";
+ Code = "functionDecl(hasP";
Comps = Parser::completeExpression(Code, Code.size(), nullptr, &NamedValues);
ASSERT_EQ(3u, Comps.size());
- EXPECT_EQ("aramA", Comps[0].TypedText);
- EXPECT_EQ("Matcher<FunctionDecl> hasParamA", Comps[0].MatcherDecl);
- EXPECT_EQ("arameter(", Comps[1].TypedText);
+ EXPECT_EQ("arameter(", Comps[0].TypedText);
EXPECT_EQ(
"Matcher<FunctionDecl> hasParameter(unsigned, Matcher<ParmVarDecl>)",
- Comps[1].MatcherDecl);
+ Comps[0].MatcherDecl);
+
+ EXPECT_EQ("aramA", Comps[1].TypedText);
+ EXPECT_EQ("Matcher<Decl> hasParamA", Comps[1].MatcherDecl);
EXPECT_EQ("arent(", Comps[2].TypedText);
EXPECT_EQ(
diff --git a/unittests/Basic/CharInfoTest.cpp b/unittests/Basic/CharInfoTest.cpp
index 348e6ffe2b7d..7a9d17fce65d 100644
--- a/unittests/Basic/CharInfoTest.cpp
+++ b/unittests/Basic/CharInfoTest.cpp
@@ -432,6 +432,7 @@ TEST(CharInfoTest, isValidIdentifier) {
EXPECT_TRUE(isValidIdentifier("z"));
EXPECT_TRUE(isValidIdentifier("A"));
EXPECT_TRUE(isValidIdentifier("Z"));
+ EXPECT_TRUE(isValidIdentifier("$", /*AllowDollar=*/true));
// 2 characters, '_' suffix
EXPECT_FALSE(isValidIdentifier("._"));
@@ -448,6 +449,7 @@ TEST(CharInfoTest, isValidIdentifier) {
EXPECT_TRUE(isValidIdentifier("z_"));
EXPECT_TRUE(isValidIdentifier("A_"));
EXPECT_TRUE(isValidIdentifier("Z_"));
+ EXPECT_TRUE(isValidIdentifier("$_", /*AllowDollar=*/true));
// 2 characters, '_' prefix
EXPECT_FALSE(isValidIdentifier("_."));
@@ -464,6 +466,7 @@ TEST(CharInfoTest, isValidIdentifier) {
EXPECT_TRUE(isValidIdentifier("_z"));
EXPECT_TRUE(isValidIdentifier("_A"));
EXPECT_TRUE(isValidIdentifier("_Z"));
+ EXPECT_TRUE(isValidIdentifier("_$", /*AllowDollar=*/true));
// 3 characters, '__' prefix
EXPECT_FALSE(isValidIdentifier("__."));
@@ -480,6 +483,7 @@ TEST(CharInfoTest, isValidIdentifier) {
EXPECT_TRUE(isValidIdentifier("__z"));
EXPECT_TRUE(isValidIdentifier("__A"));
EXPECT_TRUE(isValidIdentifier("__Z"));
+ EXPECT_TRUE(isValidIdentifier("__$", /*AllowDollar=*/true));
// 3 characters, '_' prefix and suffix
EXPECT_FALSE(isValidIdentifier("_._"));
@@ -496,4 +500,5 @@ TEST(CharInfoTest, isValidIdentifier) {
EXPECT_TRUE(isValidIdentifier("_z_"));
EXPECT_TRUE(isValidIdentifier("_A_"));
EXPECT_TRUE(isValidIdentifier("_Z_"));
+ EXPECT_TRUE(isValidIdentifier("_$_", /*AllowDollar=*/true));
}
diff --git a/unittests/Basic/FileManagerTest.cpp b/unittests/Basic/FileManagerTest.cpp
index a2a6c6aebe4b..52cb5b2f0d65 100644
--- a/unittests/Basic/FileManagerTest.cpp
+++ b/unittests/Basic/FileManagerTest.cpp
@@ -12,7 +12,6 @@
#include "clang/Basic/FileSystemStatCache.h"
#include "clang/Basic/VirtualFileSystem.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/Config/llvm-config.h"
#include "llvm/Support/Path.h"
#include "gtest/gtest.h"
@@ -31,7 +30,7 @@ private:
llvm::StringMap<FileData, llvm::BumpPtrAllocator> StatCalls;
void InjectFileOrDirectory(const char *Path, ino_t INode, bool IsFile) {
-#ifndef LLVM_ON_WIN32
+#ifndef _WIN32
SmallString<128> NormalizedPath(Path);
llvm::sys::path::native(NormalizedPath);
Path = NormalizedPath.c_str();
@@ -63,7 +62,7 @@ public:
LookupResult getStat(StringRef Path, FileData &Data, bool isFile,
std::unique_ptr<vfs::File> *F,
vfs::FileSystem &FS) override {
-#ifndef LLVM_ON_WIN32
+#ifndef _WIN32
SmallString<128> NormalizedPath(Path);
llvm::sys::path::native(NormalizedPath);
Path = NormalizedPath.c_str();
@@ -143,7 +142,7 @@ TEST_F(FileManagerTest, getFileReturnsValidFileEntryForExistingRealFile) {
statCache->InjectDirectory("/tmp", 42);
statCache->InjectFile("/tmp/test", 43);
-#ifdef LLVM_ON_WIN32
+#ifdef _WIN32
const char *DirName = "C:.";
const char *FileName = "C:test";
statCache->InjectDirectory(DirName, 44);
@@ -161,7 +160,7 @@ TEST_F(FileManagerTest, getFileReturnsValidFileEntryForExistingRealFile) {
ASSERT_TRUE(dir != nullptr);
EXPECT_EQ("/tmp", dir->getName());
-#ifdef LLVM_ON_WIN32
+#ifdef _WIN32
file = manager.getFile(FileName);
ASSERT_TRUE(file != NULL);
@@ -225,7 +224,7 @@ TEST_F(FileManagerTest, getFileReturnsNULLForNonexistentFile) {
// The following tests apply to Unix-like system only.
-#ifndef LLVM_ON_WIN32
+#ifndef _WIN32
// getFile() returns the same FileEntry for real files that are aliases.
TEST_F(FileManagerTest, getFileReturnsSameFileEntryForAliasedRealFiles) {
@@ -267,7 +266,7 @@ TEST_F(FileManagerTest, addRemoveStatCache) {
// getFile() Should return the same entry as getVirtualFile if the file actually
// is a virtual file, even if the name is not exactly the same (but is after
// normalisation done by the file system, like on Windows). This can be checked
-// here by checkng the size.
+// here by checking the size.
TEST_F(FileManagerTest, getVirtualFileWithDifferentName) {
// Inject fake files into the file system.
auto statCache = llvm::make_unique<FakeStatCache>();
@@ -295,11 +294,11 @@ TEST_F(FileManagerTest, getVirtualFileWithDifferentName) {
EXPECT_EQ(123, file2->getSize());
}
-#endif // !LLVM_ON_WIN32
+#endif // !_WIN32
TEST_F(FileManagerTest, makeAbsoluteUsesVFS) {
SmallString<64> CustomWorkingDir;
-#ifdef LLVM_ON_WIN32
+#ifdef _WIN32
CustomWorkingDir = "C:";
#else
CustomWorkingDir = "/";
diff --git a/unittests/Basic/VirtualFileSystemTest.cpp b/unittests/Basic/VirtualFileSystemTest.cpp
index f9efbeaee565..c795be07acf1 100644
--- a/unittests/Basic/VirtualFileSystemTest.cpp
+++ b/unittests/Basic/VirtualFileSystemTest.cpp
@@ -9,6 +9,7 @@
#include "clang/Basic/VirtualFileSystem.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -66,6 +67,21 @@ public:
std::error_code setCurrentWorkingDirectory(const Twine &Path) override {
return std::error_code();
}
+ // Map any symlink to "/symlink".
+ std::error_code getRealPath(const Twine &Path,
+ SmallVectorImpl<char> &Output) const override {
+ auto I = FilesAndDirs.find(Path.str());
+ if (I == FilesAndDirs.end())
+ return make_error_code(llvm::errc::no_such_file_or_directory);
+ if (I->second.isSymlink()) {
+ Output.clear();
+ Twine("/symlink").toVector(Output);
+ return std::error_code();
+ }
+ Output.clear();
+ Path.toVector(Output);
+ return std::error_code();
+ }
struct DirIterImpl : public clang::vfs::detail::DirIterImpl {
std::map<std::string, vfs::Status> &FilesAndDirs;
@@ -195,6 +211,35 @@ TEST(VirtualFileSystemTest, BaseOnlyOverlay) {
EXPECT_TRUE(Status->equivalent(*Status2));
}
+TEST(VirtualFileSystemTest, GetRealPathInOverlay) {
+ IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
+ Lower->addRegularFile("/foo");
+ Lower->addSymlink("/lower_link");
+ IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
+
+ IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
+ new vfs::OverlayFileSystem(Lower));
+ O->pushOverlay(Upper);
+
+ // Regular file.
+ SmallString<16> RealPath;
+ EXPECT_FALSE(O->getRealPath("/foo", RealPath));
+ EXPECT_EQ(RealPath.str(), "/foo");
+
+ // Expect no error getting real path for symlink in lower overlay.
+ EXPECT_FALSE(O->getRealPath("/lower_link", RealPath));
+ EXPECT_EQ(RealPath.str(), "/symlink");
+
+ // Try a non-existing link.
+ EXPECT_EQ(O->getRealPath("/upper_link", RealPath),
+ errc::no_such_file_or_directory);
+
+ // Add a new symlink in upper.
+ Upper->addSymlink("/upper_link");
+ EXPECT_FALSE(O->getRealPath("/upper_link", RealPath));
+ EXPECT_EQ(RealPath.str(), "/symlink");
+}
+
TEST(VirtualFileSystemTest, OverlayFiles) {
IntrusiveRefCntPtr<DummyFileSystem> Base(new DummyFileSystem());
IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
@@ -442,16 +487,17 @@ TEST(VirtualFileSystemTest, BrokenSymlinkRealFSRecursiveIteration) {
ScopedDir _dd(TestDirectory + "/d/d");
ScopedDir _ddd(TestDirectory + "/d/d/d");
ScopedLink _e("no_such_file", TestDirectory + "/e");
- std::vector<StringRef> Expected = {_b, _bb, _d, _dd, _ddd};
- std::vector<std::string> Contents;
+ std::vector<StringRef> ExpectedBrokenSymlinks = {_a, _ba, _bc, _c, _e};
+ std::vector<StringRef> ExpectedNonBrokenSymlinks = {_b, _bb, _d, _dd, _ddd};
+ std::vector<std::string> VisitedBrokenSymlinks;
+ std::vector<std::string> VisitedNonBrokenSymlinks;
std::error_code EC;
for (vfs::recursive_directory_iterator I(*FS, Twine(TestDirectory), EC), E;
I != E; I.increment(EC)) {
- // Skip broken symlinks.
auto EC2 = std::make_error_code(std::errc::no_such_file_or_directory);
if (EC == EC2) {
- EC.clear();
+ VisitedBrokenSymlinks.push_back(I->getName());
continue;
}
// For bot debugging.
@@ -467,13 +513,20 @@ TEST(VirtualFileSystemTest, BrokenSymlinkRealFSRecursiveIteration) {
<< "EC message: " << EC2.message() << "\n";
}
ASSERT_FALSE(EC);
- Contents.push_back(I->getName());
+ VisitedNonBrokenSymlinks.push_back(I->getName());
}
- // Check sorted contents.
- std::sort(Contents.begin(), Contents.end());
- EXPECT_EQ(Expected.size(), Contents.size());
- EXPECT_TRUE(std::equal(Contents.begin(), Contents.end(), Expected.begin()));
+ // Check visited file names.
+ std::sort(VisitedBrokenSymlinks.begin(), VisitedBrokenSymlinks.end());
+ std::sort(VisitedNonBrokenSymlinks.begin(), VisitedNonBrokenSymlinks.end());
+ EXPECT_EQ(ExpectedBrokenSymlinks.size(), VisitedBrokenSymlinks.size());
+ EXPECT_TRUE(std::equal(VisitedBrokenSymlinks.begin(),
+ VisitedBrokenSymlinks.end(),
+ ExpectedBrokenSymlinks.begin()));
+ EXPECT_EQ(ExpectedNonBrokenSymlinks.size(), VisitedNonBrokenSymlinks.size());
+ EXPECT_TRUE(std::equal(VisitedNonBrokenSymlinks.begin(),
+ VisitedNonBrokenSymlinks.end(),
+ ExpectedNonBrokenSymlinks.begin()));
}
#endif
@@ -488,8 +541,8 @@ static void checkContents(DirIter I, ArrayRef<StringRef> ExpectedOut) {
for (DirIter E; !EC && I != E; I.increment(EC))
InputToCheck.push_back(I->getName());
- std::sort(InputToCheck.begin(), InputToCheck.end());
- std::sort(Expected.begin(), Expected.end());
+ llvm::sort(InputToCheck.begin(), InputToCheck.end());
+ llvm::sort(Expected.begin(), Expected.end());
EXPECT_EQ(InputToCheck.size(), Expected.size());
unsigned LastElt = std::min(InputToCheck.size(), Expected.size());
@@ -760,6 +813,30 @@ TEST_F(InMemoryFileSystemTest, WorkingDirectory) {
NormalizedFS.getCurrentWorkingDirectory().get()));
}
+#if !defined(_WIN32)
+TEST_F(InMemoryFileSystemTest, GetRealPath) {
+ SmallString<16> Path;
+ EXPECT_EQ(FS.getRealPath("b", Path), errc::operation_not_permitted);
+
+ auto GetRealPath = [this](StringRef P) {
+ SmallString<16> Output;
+ auto EC = FS.getRealPath(P, Output);
+ EXPECT_FALSE(EC);
+ return Output.str().str();
+ };
+
+ FS.setCurrentWorkingDirectory("a");
+ EXPECT_EQ(GetRealPath("b"), "a/b");
+ EXPECT_EQ(GetRealPath("../b"), "b");
+ EXPECT_EQ(GetRealPath("b/./c"), "a/b/c");
+
+ FS.setCurrentWorkingDirectory("/a");
+ EXPECT_EQ(GetRealPath("b"), "/a/b");
+ EXPECT_EQ(GetRealPath("../b"), "/b");
+ EXPECT_EQ(GetRealPath("b/./c"), "/a/b/c");
+}
+#endif // _WIN32
+
TEST_F(InMemoryFileSystemTest, AddFileWithUser) {
FS.addFile("/a/b/c", 0, MemoryBuffer::getMemBuffer("abc"), 0xFEEDFACE);
auto Stat = FS.status("/a");
diff --git a/unittests/CrossTU/CrossTranslationUnitTest.cpp b/unittests/CrossTU/CrossTranslationUnitTest.cpp
index 5fbf56ed43b8..dd82743ac6d5 100644
--- a/unittests/CrossTU/CrossTranslationUnitTest.cpp
+++ b/unittests/CrossTU/CrossTranslationUnitTest.cpp
@@ -11,7 +11,6 @@
#include "clang/AST/ASTConsumer.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Tooling/Tooling.h"
-#include "llvm/Config/llvm-config.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/ToolOutputFile.h"
diff --git a/unittests/Driver/CMakeLists.txt b/unittests/Driver/CMakeLists.txt
index b8c800f59eaf..82dc0ff4bd2a 100644
--- a/unittests/Driver/CMakeLists.txt
+++ b/unittests/Driver/CMakeLists.txt
@@ -7,6 +7,7 @@ set(LLVM_LINK_COMPONENTS
add_clang_unittest(ClangDriverTests
DistroTest.cpp
ToolChainTest.cpp
+ ModuleCacheTest.cpp
MultilibTest.cpp
)
diff --git a/unittests/Driver/ModuleCacheTest.cpp b/unittests/Driver/ModuleCacheTest.cpp
new file mode 100644
index 000000000000..7340889796b1
--- /dev/null
+++ b/unittests/Driver/ModuleCacheTest.cpp
@@ -0,0 +1,28 @@
+//===- unittests/Driver/ModuleCacheTest.cpp -------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Unit tests for the LLDB module cache API.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Driver.h"
+#include "gtest/gtest.h"
+using namespace clang;
+using namespace clang::driver;
+
+namespace {
+
+TEST(ModuleCacheTest, GetTargetAndMode) {
+ SmallString<128> Buf;
+ Driver::getDefaultModuleCachePath(Buf);
+ StringRef Path = Buf;
+ EXPECT_TRUE(Path.find("org.llvm.clang") != Path.npos);
+ EXPECT_TRUE(Path.endswith("ModuleCache"));
+}
+} // end anonymous namespace.
diff --git a/unittests/Driver/ToolChainTest.cpp b/unittests/Driver/ToolChainTest.cpp
index 93cf12b3c2be..d4198eaeb1cb 100644
--- a/unittests/Driver/ToolChainTest.cpp
+++ b/unittests/Driver/ToolChainTest.cpp
@@ -69,7 +69,7 @@ TEST(ToolChainTest, VFSGCCInstallation) {
llvm::raw_string_ostream OS(S);
C->getDefaultToolChain().printVerboseInfo(OS);
}
-#if LLVM_ON_WIN32
+#if _WIN32
std::replace(S.begin(), S.end(), '\\', '/');
#endif
EXPECT_EQ(
@@ -109,7 +109,7 @@ TEST(ToolChainTest, VFSGCCInstallationRelativeDir) {
llvm::raw_string_ostream OS(S);
C->getDefaultToolChain().printVerboseInfo(OS);
}
-#if LLVM_ON_WIN32
+#if _WIN32
std::replace(S.begin(), S.end(), '\\', '/');
#endif
EXPECT_EQ("Found candidate GCC installation: "
diff --git a/unittests/Format/CleanupTest.cpp b/unittests/Format/CleanupTest.cpp
index 708fdf896890..f4a36d8e1f71 100644
--- a/unittests/Format/CleanupTest.cpp
+++ b/unittests/Format/CleanupTest.cpp
@@ -358,156 +358,27 @@ TEST_F(CleanUpReplacementsTest, FixOnlyAffectedCodeAfterReplacements) {
EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
}
-TEST_F(CleanUpReplacementsTest, NoExistingIncludeWithoutDefine) {
- std::string Code = "int main() {}";
- std::string Expected = "#include \"a.h\"\n"
- "int main() {}";
- tooling::Replacements Replaces =
- toReplacements({createInsertion("#include \"a.h\"")});
- EXPECT_EQ(Expected, apply(Code, Replaces));
-}
-
-TEST_F(CleanUpReplacementsTest, NoExistingIncludeWithDefine) {
- std::string Code = "#ifndef A_H\n"
- "#define A_H\n"
- "class A {};\n"
- "#define MMM 123\n"
- "#endif";
- std::string Expected = "#ifndef A_H\n"
- "#define A_H\n"
- "#include \"b.h\"\n"
- "class A {};\n"
- "#define MMM 123\n"
- "#endif";
-
- tooling::Replacements Replaces =
- toReplacements({createInsertion("#include \"b.h\"")});
- EXPECT_EQ(Expected, apply(Code, Replaces));
-}
-
-TEST_F(CleanUpReplacementsTest, InsertBeforeCategoryWithLowerPriority) {
- std::string Code = "#ifndef A_H\n"
- "#define A_H\n"
- "\n"
- "\n"
- "\n"
- "#include <vector>\n"
- "class A {};\n"
- "#define MMM 123\n"
- "#endif";
- std::string Expected = "#ifndef A_H\n"
- "#define A_H\n"
- "\n"
- "\n"
- "\n"
- "#include \"a.h\"\n"
- "#include <vector>\n"
- "class A {};\n"
- "#define MMM 123\n"
- "#endif";
-
- tooling::Replacements Replaces =
- toReplacements({createInsertion("#include \"a.h\"")});
- EXPECT_EQ(Expected, apply(Code, Replaces));
-}
-
-TEST_F(CleanUpReplacementsTest, InsertAfterMainHeader) {
- std::string Code = "#include \"fix.h\"\n"
- "\n"
- "int main() {}";
- std::string Expected = "#include \"fix.h\"\n"
- "#include <a>\n"
- "\n"
- "int main() {}";
- tooling::Replacements Replaces =
- toReplacements({createInsertion("#include <a>")});
- Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp);
- EXPECT_EQ(Expected, apply(Code, Replaces));
-}
-
-TEST_F(CleanUpReplacementsTest, InsertBeforeSystemHeaderLLVM) {
- std::string Code = "#include <memory>\n"
- "\n"
- "int main() {}";
- std::string Expected = "#include \"z.h\"\n"
- "#include <memory>\n"
- "\n"
- "int main() {}";
- tooling::Replacements Replaces =
- toReplacements({createInsertion("#include \"z.h\"")});
- EXPECT_EQ(Expected, apply(Code, Replaces));
-}
-
-TEST_F(CleanUpReplacementsTest, InsertAfterSystemHeaderGoogle) {
- std::string Code = "#include <memory>\n"
- "\n"
- "int main() {}";
- std::string Expected = "#include <memory>\n"
- "#include \"z.h\"\n"
- "\n"
- "int main() {}";
- tooling::Replacements Replaces =
- toReplacements({createInsertion("#include \"z.h\"")});
- Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp);
- EXPECT_EQ(Expected, apply(Code, Replaces));
-}
-
-TEST_F(CleanUpReplacementsTest, InsertOneIncludeLLVMStyle) {
- std::string Code = "#include \"x/fix.h\"\n"
- "#include \"a.h\"\n"
- "#include \"b.h\"\n"
- "#include \"clang/Format/Format.h\"\n"
- "#include <memory>\n";
- std::string Expected = "#include \"x/fix.h\"\n"
- "#include \"a.h\"\n"
- "#include \"b.h\"\n"
- "#include \"d.h\"\n"
- "#include \"clang/Format/Format.h\"\n"
- "#include \"llvm/x/y.h\"\n"
- "#include <memory>\n";
- tooling::Replacements Replaces =
- toReplacements({createInsertion("#include \"d.h\""),
- createInsertion("#include \"llvm/x/y.h\"")});
- EXPECT_EQ(Expected, apply(Code, Replaces));
-}
-
TEST_F(CleanUpReplacementsTest, InsertMultipleIncludesLLVMStyle) {
std::string Code = "#include \"x/fix.h\"\n"
"#include \"a.h\"\n"
"#include \"b.h\"\n"
+ "#include \"z.h\"\n"
"#include \"clang/Format/Format.h\"\n"
"#include <memory>\n";
std::string Expected = "#include \"x/fix.h\"\n"
"#include \"a.h\"\n"
"#include \"b.h\"\n"
"#include \"new/new.h\"\n"
+ "#include \"z.h\"\n"
"#include \"clang/Format/Format.h\"\n"
- "#include <memory>\n"
- "#include <list>\n";
+ "#include <list>\n"
+ "#include <memory>\n";
tooling::Replacements Replaces =
toReplacements({createInsertion("#include <list>"),
createInsertion("#include \"new/new.h\"")});
EXPECT_EQ(Expected, apply(Code, Replaces));
}
-TEST_F(CleanUpReplacementsTest, InsertNewSystemIncludeGoogleStyle) {
- std::string Code = "#include \"x/fix.h\"\n"
- "\n"
- "#include \"y/a.h\"\n"
- "#include \"z/b.h\"\n";
- // FIXME: inserting after the empty line following the main header might be
- // prefered.
- std::string Expected = "#include \"x/fix.h\"\n"
- "#include <vector>\n"
- "\n"
- "#include \"y/a.h\"\n"
- "#include \"z/b.h\"\n";
- tooling::Replacements Replaces =
- toReplacements({createInsertion("#include <vector>")});
- Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp);
- EXPECT_EQ(Expected, apply(Code, Replaces));
-}
-
TEST_F(CleanUpReplacementsTest, InsertMultipleIncludesGoogleStyle) {
std::string Code = "#include \"x/fix.h\"\n"
"\n"
@@ -517,12 +388,12 @@ TEST_F(CleanUpReplacementsTest, InsertMultipleIncludesGoogleStyle) {
"#include \"z/b.h\"\n";
std::string Expected = "#include \"x/fix.h\"\n"
"\n"
- "#include <vector>\n"
"#include <list>\n"
+ "#include <vector>\n"
"\n"
+ "#include \"x/x.h\"\n"
"#include \"y/a.h\"\n"
- "#include \"z/b.h\"\n"
- "#include \"x/x.h\"\n";
+ "#include \"z/b.h\"\n";
tooling::Replacements Replaces =
toReplacements({createInsertion("#include <list>"),
createInsertion("#include \"x/x.h\"")});
@@ -565,6 +436,19 @@ TEST_F(CleanUpReplacementsTest, InsertMultipleNewHeadersAndSortGoogle) {
EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
}
+TEST_F(CleanUpReplacementsTest, NoNewLineAtTheEndOfCodeMultipleInsertions) {
+ std::string Code = "#include <map>";
+ // FIXME: a better behavior is to only append on newline to Code, but this
+ // case should be rare in practice.
+ std::string Expected =
+ "#include <map>\n#include <string>\n\n#include <vector>\n";
+ tooling::Replacements Replaces =
+ toReplacements({createInsertion("#include <string>"),
+ createInsertion("#include <vector>")});
+ EXPECT_EQ(Expected, apply(Code, Replaces));
+}
+
+
TEST_F(CleanUpReplacementsTest, FormatCorrectLineWhenHeadersAreInserted) {
std::string Code = "\n"
"int x;\n"
@@ -590,225 +474,6 @@ TEST_F(CleanUpReplacementsTest, FormatCorrectLineWhenHeadersAreInserted) {
EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
}
-TEST_F(CleanUpReplacementsTest, NotConfusedByDefine) {
- std::string Code = "void f() {}\n"
- "#define A \\\n"
- " int i;";
- std::string Expected = "#include <vector>\n"
- "void f() {}\n"
- "#define A \\\n"
- " int i;";
- tooling::Replacements Replaces =
- toReplacements({createInsertion("#include <vector>")});
- EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
-}
-
-TEST_F(CleanUpReplacementsTest, SkippedTopComment) {
- std::string Code = "// comment\n"
- "\n"
- " // comment\n";
- std::string Expected = "// comment\n"
- "\n"
- " // comment\n"
- "#include <vector>\n";
- tooling::Replacements Replaces =
- toReplacements({createInsertion("#include <vector>")});
- EXPECT_EQ(Expected, apply(Code, Replaces));
-}
-
-TEST_F(CleanUpReplacementsTest, SkippedMixedComments) {
- std::string Code = "// comment\n"
- "// comment \\\n"
- " comment continued\n"
- "/*\n"
- "* comment\n"
- "*/\n";
- std::string Expected = "// comment\n"
- "// comment \\\n"
- " comment continued\n"
- "/*\n"
- "* comment\n"
- "*/\n"
- "#include <vector>\n";
- tooling::Replacements Replaces =
- toReplacements({createInsertion("#include <vector>")});
- EXPECT_EQ(Expected, apply(Code, Replaces));
-}
-
-TEST_F(CleanUpReplacementsTest, MultipleBlockCommentsInOneLine) {
- std::string Code = "/*\n"
- "* comment\n"
- "*/ /* comment\n"
- "*/\n"
- "\n\n"
- "/* c1 */ /*c2 */\n";
- std::string Expected = "/*\n"
- "* comment\n"
- "*/ /* comment\n"
- "*/\n"
- "\n\n"
- "/* c1 */ /*c2 */\n"
- "#include <vector>\n";
- tooling::Replacements Replaces =
- toReplacements({createInsertion("#include <vector>")});
- EXPECT_EQ(Expected, apply(Code, Replaces));
-}
-
-TEST_F(CleanUpReplacementsTest, CodeAfterComments) {
- std::string Code = "/*\n"
- "* comment\n"
- "*/ /* comment\n"
- "*/\n"
- "\n\n"
- "/* c1 */ /*c2 */\n"
- "\n"
- "int x;\n";
- std::string Expected = "/*\n"
- "* comment\n"
- "*/ /* comment\n"
- "*/\n"
- "\n\n"
- "/* c1 */ /*c2 */\n"
- "\n"
- "#include <vector>\n"
- "int x;\n";
- tooling::Replacements Replaces =
- toReplacements({createInsertion("#include <vector>")});
- EXPECT_EQ(Expected, apply(Code, Replaces));
-}
-
-TEST_F(CleanUpReplacementsTest, FakeHeaderGuardIfDef) {
- std::string Code = "// comment \n"
- "#ifdef X\n"
- "#define X\n";
- std::string Expected = "// comment \n"
- "#include <vector>\n"
- "#ifdef X\n"
- "#define X\n";
- tooling::Replacements Replaces =
- toReplacements({createInsertion("#include <vector>")});
- EXPECT_EQ(Expected, apply(Code, Replaces));
-}
-
-TEST_F(CleanUpReplacementsTest, RealHeaderGuardAfterComments) {
- std::string Code = "// comment \n"
- "#ifndef X\n"
- "#define X\n"
- "int x;\n"
- "#define Y 1\n";
- std::string Expected = "// comment \n"
- "#ifndef X\n"
- "#define X\n"
- "#include <vector>\n"
- "int x;\n"
- "#define Y 1\n";
- tooling::Replacements Replaces =
- toReplacements({createInsertion("#include <vector>")});
- EXPECT_EQ(Expected, apply(Code, Replaces));
-}
-
-TEST_F(CleanUpReplacementsTest, IfNDefWithNoDefine) {
- std::string Code = "// comment \n"
- "#ifndef X\n"
- "int x;\n"
- "#define Y 1\n";
- std::string Expected = "// comment \n"
- "#include <vector>\n"
- "#ifndef X\n"
- "int x;\n"
- "#define Y 1\n";
- tooling::Replacements Replaces =
- toReplacements({createInsertion("#include <vector>")});
- EXPECT_EQ(Expected, apply(Code, Replaces));
-}
-
-TEST_F(CleanUpReplacementsTest, FakeHeaderGuard) {
- std::string Code = "// comment \n"
- "#ifndef X\n"
- "#define 1\n";
- std::string Expected = "// comment \n"
- "#include <vector>\n"
- "#ifndef X\n"
- "#define 1\n";
- tooling::Replacements Replaces =
- toReplacements({createInsertion("#include <vector>")});
- EXPECT_EQ(Expected, apply(Code, Replaces));
-}
-
-TEST_F(CleanUpReplacementsTest, HeaderGuardWithComment) {
- std::string Code = "// comment \n"
- "#ifndef X // comment\n"
- "// comment\n"
- "/* comment\n"
- "*/\n"
- "/* comment */ #define X\n"
- "int x;\n"
- "#define Y 1\n";
- std::string Expected = "// comment \n"
- "#ifndef X // comment\n"
- "// comment\n"
- "/* comment\n"
- "*/\n"
- "/* comment */ #define X\n"
- "#include <vector>\n"
- "int x;\n"
- "#define Y 1\n";
- tooling::Replacements Replaces =
- toReplacements({createInsertion("#include <vector>")});
- EXPECT_EQ(Expected, apply(Code, Replaces));
-}
-
-TEST_F(CleanUpReplacementsTest, EmptyCode) {
- std::string Code = "";
- std::string Expected = "#include <vector>\n";
- tooling::Replacements Replaces =
- toReplacements({createInsertion("#include <vector>")});
- EXPECT_EQ(Expected, apply(Code, Replaces));
-}
-
-TEST_F(CleanUpReplacementsTest, NoNewLineAtTheEndOfCode) {
- std::string Code = "#include <map>";
- std::string Expected = "#include <map>\n#include <vector>\n";
- tooling::Replacements Replaces =
- toReplacements({createInsertion("#include <vector>")});
- EXPECT_EQ(Expected, apply(Code, Replaces));
-}
-
-TEST_F(CleanUpReplacementsTest, NoNewLineAtTheEndOfCodeMultipleInsertions) {
- std::string Code = "#include <map>";
- std::string Expected =
- "#include <map>\n#include <string>\n#include <vector>\n";
- tooling::Replacements Replaces =
- toReplacements({createInsertion("#include <string>"),
- createInsertion("#include <vector>")});
- EXPECT_EQ(Expected, apply(Code, Replaces));
-}
-
-TEST_F(CleanUpReplacementsTest, SkipExistingHeaders) {
- std::string Code = "#include \"a.h\"\n"
- "#include <vector>\n";
- std::string Expected = "#include \"a.h\"\n"
- "#include <vector>\n";
- tooling::Replacements Replaces =
- toReplacements({createInsertion("#include <vector>"),
- createInsertion("#include \"a.h\"")});
- EXPECT_EQ(Expected, apply(Code, Replaces));
-}
-
-TEST_F(CleanUpReplacementsTest, AddIncludesWithDifferentForms) {
- std::string Code = "#include \"a.h\"\n"
- "#include <vector>\n";
- // FIXME: this might not be the best behavior.
- std::string Expected = "#include \"a.h\"\n"
- "#include \"vector\"\n"
- "#include <vector>\n"
- "#include <a.h>\n";
- tooling::Replacements Replaces =
- toReplacements({createInsertion("#include \"vector\""),
- createInsertion("#include <a.h>")});
- EXPECT_EQ(Expected, apply(Code, Replaces));
-}
-
TEST_F(CleanUpReplacementsTest, SimpleDeleteIncludes) {
std::string Code = "#include \"abc.h\"\n"
"#include \"xyz.h\" // comment\n"
@@ -821,33 +486,6 @@ TEST_F(CleanUpReplacementsTest, SimpleDeleteIncludes) {
EXPECT_EQ(Expected, apply(Code, Replaces));
}
-TEST_F(CleanUpReplacementsTest, DeleteAllCode) {
- std::string Code = "#include \"xyz.h\"\n"
- "#include <xyz.h>";
- std::string Expected = "";
- tooling::Replacements Replaces = toReplacements({createDeletion("xyz.h")});
- EXPECT_EQ(Expected, apply(Code, Replaces));
-}
-
-TEST_F(CleanUpReplacementsTest, DeleteAllIncludesWithSameNameIfNoType) {
- std::string Code = "#include \"xyz.h\"\n"
- "#include \"xyz\"\n"
- "#include <xyz.h>\n";
- std::string Expected = "#include \"xyz\"\n";
- tooling::Replacements Replaces = toReplacements({createDeletion("xyz.h")});
- EXPECT_EQ(Expected, apply(Code, Replaces));
-}
-
-TEST_F(CleanUpReplacementsTest, OnlyDeleteHeaderWithType) {
- std::string Code = "#include \"xyz.h\"\n"
- "#include \"xyz\"\n"
- "#include <xyz.h>";
- std::string Expected = "#include \"xyz.h\"\n"
- "#include \"xyz\"\n";
- tooling::Replacements Replaces = toReplacements({createDeletion("<xyz.h>")});
- EXPECT_EQ(Expected, apply(Code, Replaces));
-}
-
TEST_F(CleanUpReplacementsTest, InsertionAndDeleteHeader) {
std::string Code = "#include \"a.h\"\n"
"\n"
@@ -860,117 +498,6 @@ TEST_F(CleanUpReplacementsTest, InsertionAndDeleteHeader) {
EXPECT_EQ(Expected, apply(Code, Replaces));
}
-TEST_F(CleanUpReplacementsTest, NoInsertionAfterCode) {
- std::string Code = "#include \"a.h\"\n"
- "void f() {}\n"
- "#include \"b.h\"\n";
- std::string Expected = "#include \"a.h\"\n"
- "#include \"c.h\"\n"
- "void f() {}\n"
- "#include \"b.h\"\n";
- tooling::Replacements Replaces = toReplacements(
- {createInsertion("#include \"c.h\"")});
- EXPECT_EQ(Expected, apply(Code, Replaces));
-}
-
-TEST_F(CleanUpReplacementsTest, NoInsertionInStringLiteral) {
- std::string Code = "#include \"a.h\"\n"
- "const char[] = R\"(\n"
- "#include \"b.h\"\n"
- ")\";\n";
- std::string Expected = "#include \"a.h\"\n"
- "#include \"c.h\"\n"
- "const char[] = R\"(\n"
- "#include \"b.h\"\n"
- ")\";\n";
- tooling::Replacements Replaces =
- toReplacements({createInsertion("#include \"c.h\"")});
- EXPECT_EQ(Expected, apply(Code, Replaces));
-}
-
-TEST_F(CleanUpReplacementsTest, NoInsertionAfterOtherDirective) {
- std::string Code = "#include \"a.h\"\n"
- "#ifdef X\n"
- "#include \"b.h\"\n"
- "#endif\n";
- std::string Expected = "#include \"a.h\"\n"
- "#include \"c.h\"\n"
- "#ifdef X\n"
- "#include \"b.h\"\n"
- "#endif\n";
- tooling::Replacements Replaces = toReplacements(
- {createInsertion("#include \"c.h\"")});
- EXPECT_EQ(Expected, apply(Code, Replaces));
-}
-
-TEST_F(CleanUpReplacementsTest, CanInsertAfterLongSystemInclude) {
- std::string Code = "#include \"a.h\"\n"
- "// comment\n\n"
- "#include <a/b/c/d/e.h>\n";
- std::string Expected = "#include \"a.h\"\n"
- "// comment\n\n"
- "#include <a/b/c/d/e.h>\n"
- "#include <x.h>\n";
- tooling::Replacements Replaces =
- toReplacements({createInsertion("#include <x.h>")});
- EXPECT_EQ(Expected, apply(Code, Replaces));
-}
-
-TEST_F(CleanUpReplacementsTest, CanInsertAfterComment) {
- std::string Code = "#include \"a.h\"\n"
- "// Comment\n"
- "\n"
- "/* Comment */\n"
- "// Comment\n"
- "\n"
- "#include \"b.h\"\n";
- std::string Expected = "#include \"a.h\"\n"
- "// Comment\n"
- "\n"
- "/* Comment */\n"
- "// Comment\n"
- "\n"
- "#include \"b.h\"\n"
- "#include \"c.h\"\n";
- tooling::Replacements Replaces =
- toReplacements({createInsertion("#include \"c.h\"")});
- EXPECT_EQ(Expected, apply(Code, Replaces));
-}
-
-TEST_F(CleanUpReplacementsTest, LongCommentsInTheBeginningOfFile) {
- std::string Code = "// Loooooooooooooooooooooooooong comment\n"
- "// Loooooooooooooooooooooooooong comment\n"
- "// Loooooooooooooooooooooooooong comment\n"
- "#include <string>\n"
- "#include <vector>\n"
- "\n"
- "#include \"a.h\"\n"
- "#include \"b.h\"\n";
- std::string Expected = "// Loooooooooooooooooooooooooong comment\n"
- "// Loooooooooooooooooooooooooong comment\n"
- "// Loooooooooooooooooooooooooong comment\n"
- "#include <string>\n"
- "#include <vector>\n"
- "\n"
- "#include \"a.h\"\n"
- "#include \"b.h\"\n"
- "#include \"third.h\"\n";
- tooling::Replacements Replaces =
- toReplacements({createInsertion("#include \"third.h\"")});
- Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp);
- EXPECT_EQ(Expected, apply(Code, Replaces));
-}
-
-TEST_F(CleanUpReplacementsTest, CanDeleteAfterCode) {
- std::string Code = "#include \"a.h\"\n"
- "void f() {}\n"
- "#include \"b.h\"\n";
- std::string Expected = "#include \"a.h\"\n"
- "void f() {}\n";
- tooling::Replacements Replaces = toReplacements({createDeletion("\"b.h\"")});
- EXPECT_EQ(Expected, apply(Code, Replaces));
-}
-
} // end namespace
} // end namespace format
} // end namespace clang
diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp
index 2cae9dd0c547..f234e287cf17 100644
--- a/unittests/Format/FormatTest.cpp
+++ b/unittests/Format/FormatTest.cpp
@@ -39,8 +39,8 @@ protected:
std::string format(llvm::StringRef Code,
const FormatStyle &Style = getLLVMStyle(),
StatusCheck CheckComplete = SC_ExpectComplete) {
- DEBUG(llvm::errs() << "---\n");
- DEBUG(llvm::errs() << Code << "\n\n");
+ LLVM_DEBUG(llvm::errs() << "---\n");
+ LLVM_DEBUG(llvm::errs() << Code << "\n\n");
std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
FormattingAttemptStatus Status;
tooling::Replacements Replaces =
@@ -53,7 +53,7 @@ protected:
ReplacementCount = Replaces.size();
auto Result = applyAllReplacements(Code, Replaces);
EXPECT_TRUE(static_cast<bool>(Result));
- DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
+ LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
return *Result;
}
@@ -72,6 +72,8 @@ protected:
void verifyFormat(llvm::StringRef Expected, llvm::StringRef Code,
const FormatStyle &Style = getLLVMStyle()) {
+ EXPECT_EQ(Expected.str(), format(Expected, Style))
+ << "Expected code is not stable";
EXPECT_EQ(Expected.str(), format(Code, Style));
if (Style.Language == FormatStyle::LK_Cpp) {
// Objective-C++ is a superset of C++, so everything checked for C++
@@ -276,11 +278,12 @@ TEST_F(FormatTest, RemovesEmptyLines) {
"\n"
"}"));
- // FIXME: This is slightly inconsistent.
+ // Don't remove empty lines before namespace endings.
FormatStyle LLVMWithNoNamespaceFix = getLLVMStyle();
LLVMWithNoNamespaceFix.FixNamespaceComments = false;
EXPECT_EQ("namespace {\n"
"int i;\n"
+ "\n"
"}",
format("namespace {\n"
"int i;\n"
@@ -291,6 +294,27 @@ TEST_F(FormatTest, RemovesEmptyLines) {
"}",
format("namespace {\n"
"int i;\n"
+ "}", LLVMWithNoNamespaceFix));
+ EXPECT_EQ("namespace {\n"
+ "int i;\n"
+ "\n"
+ "};",
+ format("namespace {\n"
+ "int i;\n"
+ "\n"
+ "};", LLVMWithNoNamespaceFix));
+ EXPECT_EQ("namespace {\n"
+ "int i;\n"
+ "};",
+ format("namespace {\n"
+ "int i;\n"
+ "};", LLVMWithNoNamespaceFix));
+ EXPECT_EQ("namespace {\n"
+ "int i;\n"
+ "\n"
+ "}",
+ format("namespace {\n"
+ "int i;\n"
"\n"
"}"));
EXPECT_EQ("namespace {\n"
@@ -588,6 +612,23 @@ TEST_F(FormatTest, FormatShortBracedStatements) {
AllowSimpleBracedStatements);
}
+TEST_F(FormatTest, ShortBlocksInMacrosDontMergeWithCodeAfterMacro) {
+ FormatStyle Style = getLLVMStyleWithColumns(60);
+ Style.AllowShortBlocksOnASingleLine = true;
+ Style.AllowShortIfStatementsOnASingleLine = true;
+ Style.BreakBeforeBraces = FormatStyle::BS_Allman;
+ EXPECT_EQ("#define A \\\n"
+ " if (HANDLEwernufrnuLwrmviferuvnierv) \\\n"
+ " { RET_ERR1_ANUIREUINERUIFNIOAerwfwrvnuier; }\n"
+ "X;",
+ format("#define A \\\n"
+ " if (HANDLEwernufrnuLwrmviferuvnierv) { \\\n"
+ " RET_ERR1_ANUIREUINERUIFNIOAerwfwrvnuier; \\\n"
+ " }\n"
+ "X;",
+ Style));
+}
+
TEST_F(FormatTest, ParseIfElse) {
verifyFormat("if (true)\n"
" if (true)\n"
@@ -725,6 +766,12 @@ TEST_F(FormatTest, FormatsForLoop) {
" aaaaaaaaaaaaaaaaaaaaaaaaaaa != bbbbbbbbbbbbbbbbbbbbbbb;\n"
" ++aaaaaaaaaaaaaaaaaaaaaaaaaaa) {");
+ // These should not be formatted as Objective-C for-in loops.
+ verifyFormat("for (Foo *x = 0; x != in; x++) {\n}");
+ verifyFormat("Foo *x;\nfor (x = 0; x != in; x++) {\n}");
+ verifyFormat("Foo *x;\nfor (x in y) {\n}");
+ verifyFormat("for (const Foo<Bar> &baz = in.value(); !baz.at_end(); ++baz) {\n}");
+
FormatStyle NoBinPacking = getLLVMStyle();
NoBinPacking.BinPackParameters = false;
verifyFormat("for (int aaaaaaaaaaa = 1;\n"
@@ -1269,15 +1316,40 @@ TEST_F(FormatTest, FormatsClasses) {
verifyFormat("class ::A::B {};");
}
-TEST_F(FormatTest, BreakBeforeInheritanceComma) {
- FormatStyle StyleWithInheritanceBreak = getLLVMStyle();
- StyleWithInheritanceBreak.BreakBeforeInheritanceComma = true;
-
- verifyFormat("class MyClass : public X {};", StyleWithInheritanceBreak);
+TEST_F(FormatTest, BreakInheritanceStyle) {
+ FormatStyle StyleWithInheritanceBreakBeforeComma = getLLVMStyle();
+ StyleWithInheritanceBreakBeforeComma.BreakInheritanceList =
+ FormatStyle::BILS_BeforeComma;
+ verifyFormat("class MyClass : public X {};",
+ StyleWithInheritanceBreakBeforeComma);
verifyFormat("class MyClass\n"
" : public X\n"
" , public Y {};",
- StyleWithInheritanceBreak);
+ StyleWithInheritanceBreakBeforeComma);
+ verifyFormat("class AAAAAAAAAAAAAAAAAAAAAA\n"
+ " : public BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n"
+ " , public CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC {};",
+ StyleWithInheritanceBreakBeforeComma);
+ verifyFormat("struct aaaaaaaaaaaaa\n"
+ " : public aaaaaaaaaaaaaaaaaaa< // break\n"
+ " aaaaaaaaaaaaaaaa> {};",
+ StyleWithInheritanceBreakBeforeComma);
+
+ FormatStyle StyleWithInheritanceBreakAfterColon = getLLVMStyle();
+ StyleWithInheritanceBreakAfterColon.BreakInheritanceList =
+ FormatStyle::BILS_AfterColon;
+ verifyFormat("class MyClass : public X {};",
+ StyleWithInheritanceBreakAfterColon);
+ verifyFormat("class MyClass : public X, public Y {};",
+ StyleWithInheritanceBreakAfterColon);
+ verifyFormat("class AAAAAAAAAAAAAAAAAAAAAA :\n"
+ " public BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB,\n"
+ " public CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC {};",
+ StyleWithInheritanceBreakAfterColon);
+ verifyFormat("struct aaaaaaaaaaaaa :\n"
+ " public aaaaaaaaaaaaaaaaaaa< // break\n"
+ " aaaaaaaaaaaaaaaa> {};",
+ StyleWithInheritanceBreakAfterColon);
}
TEST_F(FormatTest, FormatsVariableDeclarationsAfterStructOrClass) {
@@ -2484,8 +2556,6 @@ TEST_F(FormatTest, IndentPreprocessorDirectives) {
"#endif",
Style);
// Test with include guards.
- // EXPECT_EQ is used because verifyFormat() calls messUp() which incorrectly
- // merges lines.
verifyFormat("#ifndef HEADER_H\n"
"#define HEADER_H\n"
"code();\n"
@@ -2532,6 +2602,20 @@ TEST_F(FormatTest, IndentPreprocessorDirectives) {
"#elif FOO\n"
"#endif",
Style);
+ // Non-identifier #define after potential include guard.
+ verifyFormat("#ifndef FOO\n"
+ "# define 1\n"
+ "#endif\n",
+ Style);
+ // #if closes past last non-preprocessor line.
+ verifyFormat("#ifndef FOO\n"
+ "#define FOO\n"
+ "#if 1\n"
+ "int i;\n"
+ "# define A 0\n"
+ "#endif\n"
+ "#endif\n",
+ Style);
// FIXME: This doesn't handle the case where there's code between the
// #ifndef and #define but all other conditions hold. This is because when
// the #define line is parsed, UnwrappedLineParser::Lines doesn't hold the
@@ -2580,21 +2664,85 @@ TEST_F(FormatTest, IndentPreprocessorDirectives) {
"code();\n"
"#endif",
Style));
- // FIXME: The comment indent corrector in TokenAnnotator gets thrown off by
- // preprocessor indentation.
- EXPECT_EQ("#if 1\n"
- " // comment\n"
- "# define A 0\n"
- "// comment\n"
- "# define B 0\n"
- "#endif",
- format("#if 1\n"
- "// comment\n"
- "# define A 0\n"
- " // comment\n"
- "# define B 0\n"
- "#endif",
- Style));
+ // Keep comments aligned with #, otherwise indent comments normally. These
+ // tests cannot use verifyFormat because messUp manipulates leading
+ // whitespace.
+ {
+ const char *Expected = ""
+ "void f() {\n"
+ "#if 1\n"
+ "// Preprocessor aligned.\n"
+ "# define A 0\n"
+ " // Code. Separated by blank line.\n"
+ "\n"
+ "# define B 0\n"
+ " // Code. Not aligned with #\n"
+ "# define C 0\n"
+ "#endif";
+ const char *ToFormat = ""
+ "void f() {\n"
+ "#if 1\n"
+ "// Preprocessor aligned.\n"
+ "# define A 0\n"
+ "// Code. Separated by blank line.\n"
+ "\n"
+ "# define B 0\n"
+ " // Code. Not aligned with #\n"
+ "# define C 0\n"
+ "#endif";
+ EXPECT_EQ(Expected, format(ToFormat, Style));
+ EXPECT_EQ(Expected, format(Expected, Style));
+ }
+ // Keep block quotes aligned.
+ {
+ const char *Expected = ""
+ "void f() {\n"
+ "#if 1\n"
+ "/* Preprocessor aligned. */\n"
+ "# define A 0\n"
+ " /* Code. Separated by blank line. */\n"
+ "\n"
+ "# define B 0\n"
+ " /* Code. Not aligned with # */\n"
+ "# define C 0\n"
+ "#endif";
+ const char *ToFormat = ""
+ "void f() {\n"
+ "#if 1\n"
+ "/* Preprocessor aligned. */\n"
+ "# define A 0\n"
+ "/* Code. Separated by blank line. */\n"
+ "\n"
+ "# define B 0\n"
+ " /* Code. Not aligned with # */\n"
+ "# define C 0\n"
+ "#endif";
+ EXPECT_EQ(Expected, format(ToFormat, Style));
+ EXPECT_EQ(Expected, format(Expected, Style));
+ }
+ // Keep comments aligned with un-indented directives.
+ {
+ const char *Expected = ""
+ "void f() {\n"
+ "// Preprocessor aligned.\n"
+ "#define A 0\n"
+ " // Code. Separated by blank line.\n"
+ "\n"
+ "#define B 0\n"
+ " // Code. Not aligned with #\n"
+ "#define C 0\n";
+ const char *ToFormat = ""
+ "void f() {\n"
+ "// Preprocessor aligned.\n"
+ "#define A 0\n"
+ "// Code. Separated by blank line.\n"
+ "\n"
+ "#define B 0\n"
+ " // Code. Not aligned with #\n"
+ "#define C 0\n";
+ EXPECT_EQ(Expected, format(ToFormat, Style));
+ EXPECT_EQ(Expected, format(Expected, Style));
+ }
// Test with tabs.
Style.UseTab = FormatStyle::UT_Always;
Style.IndentWidth = 8;
@@ -3603,6 +3751,23 @@ TEST_F(FormatTest, BreakConstructorInitializersAfterColon) {
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
" bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb {}",
Style);
+
+ // `ConstructorInitializerIndentWidth` actually applies to InheritanceList as well
+ Style.BreakInheritanceList = FormatStyle::BILS_BeforeColon;
+ verifyFormat("class SomeClass\n"
+ " : public aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
+ " public bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb {};",
+ Style);
+ Style.BreakInheritanceList = FormatStyle::BILS_BeforeComma;
+ verifyFormat("class SomeClass\n"
+ " : public aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " , public bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb {};",
+ Style);
+ Style.BreakInheritanceList = FormatStyle::BILS_AfterColon;
+ verifyFormat("class SomeClass :\n"
+ " public aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
+ " public bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb {};",
+ Style);
}
#ifndef EXPENSIVE_CHECKS
@@ -5352,7 +5517,7 @@ TEST_F(FormatTest, WrapsTemplateDeclarations) {
" const typename aaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaa);");
FormatStyle AlwaysBreak = getLLVMStyle();
- AlwaysBreak.AlwaysBreakTemplateDeclarations = true;
+ AlwaysBreak.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes;
verifyFormat("template <typename T>\nclass C {};", AlwaysBreak);
verifyFormat("template <typename T>\nvoid f();", AlwaysBreak);
verifyFormat("template <typename T>\nvoid f() {}", AlwaysBreak);
@@ -5370,6 +5535,83 @@ TEST_F(FormatTest, WrapsTemplateDeclarations) {
"public:\n"
" E *f();\n"
"};");
+
+ FormatStyle NeverBreak = getLLVMStyle();
+ NeverBreak.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_No;
+ verifyFormat("template <typename T> class C {};", NeverBreak);
+ verifyFormat("template <typename T> void f();", NeverBreak);
+ verifyFormat("template <typename T> void f() {}", NeverBreak);
+ verifyFormat("template <typename T>\nvoid foo(aaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbb) {}",
+ NeverBreak);
+ verifyFormat("void aaaaaaaaaaaaaaaaaaa<aaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
+ " bbbbbbbbbbbbbbbbbbbbbbbbbbbb>(\n"
+ " ccccccccccccccccccccccccccccccccccccccccccccccc);",
+ NeverBreak);
+ verifyFormat("template <template <typename> class Fooooooo,\n"
+ " template <typename> class Baaaaaaar>\n"
+ "struct C {};",
+ NeverBreak);
+ verifyFormat("template <typename T> // T can be A, B or C.\n"
+ "struct C {};",
+ NeverBreak);
+ verifyFormat("template <enum E> class A {\n"
+ "public:\n"
+ " E *f();\n"
+ "};", NeverBreak);
+ NeverBreak.PenaltyBreakTemplateDeclaration = 100;
+ verifyFormat("template <typename T> void\nfoo(aaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbb) {}",
+ NeverBreak);
+}
+
+TEST_F(FormatTest, WrapsTemplateDeclarationsWithComments) {
+ FormatStyle Style = getGoogleStyle(FormatStyle::LK_Cpp);
+ Style.ColumnLimit = 60;
+ EXPECT_EQ("// Baseline - no comments.\n"
+ "template <\n"
+ " typename aaaaaaaaaaaaaaaaaaaaaa<bbbbbbbbbbbb>::value>\n"
+ "void f() {}",
+ format("// Baseline - no comments.\n"
+ "template <\n"
+ " typename aaaaaaaaaaaaaaaaaaaaaa<bbbbbbbbbbbb>::value>\n"
+ "void f() {}",
+ Style));
+
+ EXPECT_EQ("template <\n"
+ " typename aaaaaaaaaa<bbbbbbbbbbbb>::value> // trailing\n"
+ "void f() {}",
+ format("template <\n"
+ " typename aaaaaaaaaa<bbbbbbbbbbbb>::value> // trailing\n"
+ "void f() {}",
+ Style));
+
+ EXPECT_EQ(
+ "template <\n"
+ " typename aaaaaaaaaa<bbbbbbbbbbbb>::value> /* line */\n"
+ "void f() {}",
+ format("template <typename aaaaaaaaaa<bbbbbbbbbbbb>::value> /* line */\n"
+ "void f() {}",
+ Style));
+
+ EXPECT_EQ(
+ "template <\n"
+ " typename aaaaaaaaaa<bbbbbbbbbbbb>::value> // trailing\n"
+ " // multiline\n"
+ "void f() {}",
+ format("template <\n"
+ " typename aaaaaaaaaa<bbbbbbbbbbbb>::value> // trailing\n"
+ " // multiline\n"
+ "void f() {}",
+ Style));
+
+ EXPECT_EQ(
+ "template <typename aaaaaaaaaa<\n"
+ " bbbbbbbbbbbb>::value> // trailing loooong\n"
+ "void f() {}",
+ format(
+ "template <\n"
+ " typename aaaaaaaaaa<bbbbbbbbbbbb>::value> // trailing loooong\n"
+ "void f() {}",
+ Style));
}
TEST_F(FormatTest, WrapsTemplateParameters) {
@@ -5562,6 +5804,8 @@ TEST_F(FormatTest, UnderstandsUnaryOperators) {
verifyFormat("(a->f())++;");
verifyFormat("a[42]++;");
verifyFormat("if (!(a->f())) {\n}");
+ verifyFormat("if (!+i) {\n}");
+ verifyFormat("~&a;");
verifyFormat("a-- > b;");
verifyFormat("b ? -a : c;");
@@ -5934,6 +6178,7 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) {
PointerMiddle.PointerAlignment = FormatStyle::PAS_Middle;
verifyFormat("delete *x;", PointerMiddle);
verifyFormat("int * x;", PointerMiddle);
+ verifyFormat("int *[] x;", PointerMiddle);
verifyFormat("template <int * y> f() {}", PointerMiddle);
verifyFormat("int * f(int * a) {}", PointerMiddle);
verifyFormat("int main(int argc, char ** argv) {}", PointerMiddle);
@@ -5941,7 +6186,7 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) {
verifyFormat("A<int *> a;", PointerMiddle);
verifyFormat("A<int **> a;", PointerMiddle);
verifyFormat("A<int *, int *> a;", PointerMiddle);
- verifyFormat("A<int * []> a;", PointerMiddle);
+ verifyFormat("A<int *[]> a;", PointerMiddle);
verifyFormat("A = new SomeType *[Length]();", PointerMiddle);
verifyFormat("A = new SomeType *[Length];", PointerMiddle);
verifyFormat("T ** t = new T *;", PointerMiddle);
@@ -5966,6 +6211,31 @@ TEST_F(FormatTest, UnderstandsAttributes) {
AfterType);
}
+TEST_F(FormatTest, UnderstandsSquareAttributes) {
+ verifyFormat("SomeType s [[unused]] (InitValue);");
+ verifyFormat("SomeType s [[gnu::unused]] (InitValue);");
+ verifyFormat("SomeType s [[using gnu: unused]] (InitValue);");
+ verifyFormat("[[gsl::suppress(\"clang-tidy-check-name\")]] void f() {}");
+ verifyFormat("void f() [[deprecated(\"so sorry\")]];");
+ verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " [[unused]] aaaaaaaaaaaaaaaaaaaaaaa(int i);");
+
+ // Make sure we do not mistake attributes for array subscripts.
+ verifyFormat("int a() {}\n"
+ "[[unused]] int b() {}\n");
+
+ // On the other hand, we still need to correctly find array subscripts.
+ verifyFormat("int a = std::vector<int>{1, 2, 3}[0];");
+
+ // Make sure we do not parse attributes as lambda introducers.
+ FormatStyle MultiLineFunctions = getLLVMStyle();
+ MultiLineFunctions.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
+ verifyFormat("[[unused]] int b() {\n"
+ " return 42;\n"
+ "}\n",
+ MultiLineFunctions);
+}
+
TEST_F(FormatTest, UnderstandsEllipsis) {
verifyFormat("int printf(const char *fmt, ...);");
verifyFormat("template <class... Ts> void Foo(Ts... ts) { Foo(ts...); }");
@@ -6451,6 +6721,18 @@ TEST_F(FormatTest, IncorrectCodeUnbalancedBraces) {
verifyNoCrash("(/**/[:!] ?[).");
}
+TEST_F(FormatTest, IncorrectUnbalancedBracesInMacrosWithUnicode) {
+ // Found by oss-fuzz:
+ // https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=8212
+ FormatStyle Style = getGoogleStyle(FormatStyle::LK_Cpp);
+ Style.ColumnLimit = 60;
+ verifyNoCrash(
+ "\x23\x47\xff\x20\x28\xff\x3c\xff\x3f\xff\x20\x2f\x7b\x7a\xff\x20"
+ "\xff\xff\xff\xca\xb5\xff\xff\xff\xff\x3a\x7b\x7d\xff\x20\xff\x20"
+ "\xff\x74\xff\x20\x7d\x7d\xff\x7b\x3a\xff\x20\x71\xff\x20\xff\x0a",
+ Style);
+}
+
TEST_F(FormatTest, IncorrectCodeDoNoWhile) {
verifyFormat("do {\n}");
verifyFormat("do {\n}\n"
@@ -6557,6 +6839,15 @@ TEST_F(FormatTest, LayoutCxx11BraceInitializers) {
"};");
verifyFormat("#define A {a, a},");
+ // Avoid breaking between equal sign and opening brace
+ FormatStyle AvoidBreakingFirstArgument = getLLVMStyle();
+ AvoidBreakingFirstArgument.PenaltyBreakBeforeFirstCallParameter = 200;
+ verifyFormat("const std::unordered_map<std::string, int> MyHashTable =\n"
+ " {{\"aaaaaaaaaaaaaaaaaaaaa\", 0},\n"
+ " {\"bbbbbbbbbbbbbbbbbbbbb\", 1},\n"
+ " {\"ccccccccccccccccccccc\", 2}};",
+ AvoidBreakingFirstArgument);
+
// Binpacking only if there is no trailing comma
verifyFormat("const Aaaaaa aaaaa = {aaaaaaaaaa, bbbbbbbbbb,\n"
" cccccccccc, dddddddddd};",
@@ -6713,6 +7004,26 @@ TEST_F(FormatTest, LayoutCxx11BraceInitializers) {
verifyFormat("vector<int> foo = { ::SomeGlobalFunction() };", ExtraSpaces);
verifyFormat("const struct A a = { .a = 1, .b = 2 };", ExtraSpaces);
verifyFormat("const struct A a = { [0] = 1, [1] = 2 };", ExtraSpaces);
+
+ // Avoid breaking between initializer/equal sign and opening brace
+ ExtraSpaces.PenaltyBreakBeforeFirstCallParameter = 200;
+ verifyFormat("const std::unordered_map<std::string, int> MyHashTable = {\n"
+ " { \"aaaaaaaaaaaaaaaaaaaaa\", 0 },\n"
+ " { \"bbbbbbbbbbbbbbbbbbbbb\", 1 },\n"
+ " { \"ccccccccccccccccccccc\", 2 }\n"
+ "};",
+ ExtraSpaces);
+ verifyFormat("const std::unordered_map<std::string, int> MyHashTable{\n"
+ " { \"aaaaaaaaaaaaaaaaaaaaa\", 0 },\n"
+ " { \"bbbbbbbbbbbbbbbbbbbbb\", 1 },\n"
+ " { \"ccccccccccccccccccccc\", 2 }\n"
+ "};",
+ ExtraSpaces);
+
+ FormatStyle SpaceBeforeBrace = getLLVMStyle();
+ SpaceBeforeBrace.SpaceBeforeCpp11BracedList = true;
+ verifyFormat("vector<int> x {1, 2, 3, 4};", SpaceBeforeBrace);
+ verifyFormat("f({}, {{}, {}}, MyMap[{k, v}]);", SpaceBeforeBrace);
}
TEST_F(FormatTest, FormatsBracedListsInColumnLayout) {
@@ -7549,16 +7860,18 @@ TEST_F(FormatTest, FormatForObjectiveCMethodDecls) {
// When the function name has to be wrapped.
FormatStyle Style = getLLVMStyle();
+ // ObjC ignores IndentWrappedFunctionNames when wrapping methods
+ // and always indents instead.
Style.IndentWrappedFunctionNames = false;
verifyFormat("- (SomeLooooooooooooooooooooongType *)\n"
- "veryLooooooooooongName:(NSString)aaaaaaaaaaaaaa\n"
- " anotherName:(NSString)bbbbbbbbbbbbbb {\n"
+ " veryLooooooooooongName:(NSString)aaaaaaaaaaaaaa\n"
+ " anotherName:(NSString)bbbbbbbbbbbbbb {\n"
"}",
Style);
Style.IndentWrappedFunctionNames = true;
verifyFormat("- (SomeLooooooooooooooooooooongType *)\n"
- " veryLooooooooooongName:(NSString)aaaaaaaaaaaaaa\n"
- " anotherName:(NSString)bbbbbbbbbbbbbb {\n"
+ " veryLooooooooooongName:(NSString)cccccccccccccc\n"
+ " anotherName:(NSString)dddddddddddddd {\n"
"}",
Style);
@@ -7983,6 +8296,9 @@ TEST_F(FormatTest, CountsCharactersInMultilineRawStringLiterals) {
"multiline raw string literal xxxxxxxxxxxxxx\n"
")x\" + bbbbbb);",
getGoogleStyleWithColumns(20)));
+ EXPECT_EQ("fffffffffff(R\"(single line raw string)\" + bbbbbb);",
+ format("fffffffffff(\n"
+ " R\"(single line raw string)\" + bbbbbb);"));
}
TEST_F(FormatTest, SkipsUnknownStringLiterals) {
@@ -8704,6 +9020,7 @@ TEST_F(FormatTest, ConfigurableSpacesInParentheses) {
FormatStyle Spaces = getLLVMStyle();
Spaces.SpacesInParentheses = true;
+ verifyFormat("do_something( ::globalVar );", Spaces);
verifyFormat("call( x, y, z );", Spaces);
verifyFormat("call();", Spaces);
verifyFormat("std::function<void( int, int )> callback;", Spaces);
@@ -8840,6 +9157,137 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeAssignmentOperators) {
verifyFormat("a or_eq 8;", Spaces);
}
+TEST_F(FormatTest, ConfigurableSpaceBeforeColon) {
+ verifyFormat("class Foo : public Bar {};");
+ verifyFormat("Foo::Foo() : foo(1) {}");
+ verifyFormat("for (auto a : b) {\n}");
+ verifyFormat("int x = a ? b : c;");
+ verifyFormat("{\n"
+ "label0:\n"
+ " int x = 0;\n"
+ "}");
+ verifyFormat("switch (x) {\n"
+ "case 1:\n"
+ "default:\n"
+ "}");
+
+ FormatStyle CtorInitializerStyle = getLLVMStyleWithColumns(30);
+ CtorInitializerStyle.SpaceBeforeCtorInitializerColon = false;
+ verifyFormat("class Foo : public Bar {};", CtorInitializerStyle);
+ verifyFormat("Foo::Foo(): foo(1) {}", CtorInitializerStyle);
+ verifyFormat("for (auto a : b) {\n}", CtorInitializerStyle);
+ verifyFormat("int x = a ? b : c;", CtorInitializerStyle);
+ verifyFormat("{\n"
+ "label1:\n"
+ " int x = 0;\n"
+ "}",
+ CtorInitializerStyle);
+ verifyFormat("switch (x) {\n"
+ "case 1:\n"
+ "default:\n"
+ "}",
+ CtorInitializerStyle);
+ CtorInitializerStyle.BreakConstructorInitializers =
+ FormatStyle::BCIS_AfterColon;
+ verifyFormat("Fooooooooooo::Fooooooooooo():\n"
+ " aaaaaaaaaaaaaaaa(1),\n"
+ " bbbbbbbbbbbbbbbb(2) {}",
+ CtorInitializerStyle);
+ CtorInitializerStyle.BreakConstructorInitializers =
+ FormatStyle::BCIS_BeforeComma;
+ verifyFormat("Fooooooooooo::Fooooooooooo()\n"
+ " : aaaaaaaaaaaaaaaa(1)\n"
+ " , bbbbbbbbbbbbbbbb(2) {}",
+ CtorInitializerStyle);
+ CtorInitializerStyle.BreakConstructorInitializers =
+ FormatStyle::BCIS_BeforeColon;
+ verifyFormat("Fooooooooooo::Fooooooooooo()\n"
+ " : aaaaaaaaaaaaaaaa(1),\n"
+ " bbbbbbbbbbbbbbbb(2) {}",
+ CtorInitializerStyle);
+ CtorInitializerStyle.ConstructorInitializerIndentWidth = 0;
+ verifyFormat("Fooooooooooo::Fooooooooooo()\n"
+ ": aaaaaaaaaaaaaaaa(1),\n"
+ " bbbbbbbbbbbbbbbb(2) {}",
+ CtorInitializerStyle);
+
+ FormatStyle InheritanceStyle = getLLVMStyleWithColumns(30);
+ InheritanceStyle.SpaceBeforeInheritanceColon = false;
+ verifyFormat("class Foo: public Bar {};", InheritanceStyle);
+ verifyFormat("Foo::Foo() : foo(1) {}", InheritanceStyle);
+ verifyFormat("for (auto a : b) {\n}", InheritanceStyle);
+ verifyFormat("int x = a ? b : c;", InheritanceStyle);
+ verifyFormat("{\n"
+ "label2:\n"
+ " int x = 0;\n"
+ "}",
+ InheritanceStyle);
+ verifyFormat("switch (x) {\n"
+ "case 1:\n"
+ "default:\n"
+ "}",
+ InheritanceStyle);
+ InheritanceStyle.BreakInheritanceList = FormatStyle::BILS_AfterColon;
+ verifyFormat("class Foooooooooooooooooooooo:\n"
+ " public aaaaaaaaaaaaaaaaaa,\n"
+ " public bbbbbbbbbbbbbbbbbb {\n"
+ "}",
+ InheritanceStyle);
+ InheritanceStyle.BreakInheritanceList = FormatStyle::BILS_BeforeComma;
+ verifyFormat("class Foooooooooooooooooooooo\n"
+ " : public aaaaaaaaaaaaaaaaaa\n"
+ " , public bbbbbbbbbbbbbbbbbb {\n"
+ "}",
+ InheritanceStyle);
+ InheritanceStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon;
+ verifyFormat("class Foooooooooooooooooooooo\n"
+ " : public aaaaaaaaaaaaaaaaaa,\n"
+ " public bbbbbbbbbbbbbbbbbb {\n"
+ "}",
+ InheritanceStyle);
+ InheritanceStyle.ConstructorInitializerIndentWidth = 0;
+ verifyFormat("class Foooooooooooooooooooooo\n"
+ ": public aaaaaaaaaaaaaaaaaa,\n"
+ " public bbbbbbbbbbbbbbbbbb {}",
+ InheritanceStyle);
+
+ FormatStyle ForLoopStyle = getLLVMStyle();
+ ForLoopStyle.SpaceBeforeRangeBasedForLoopColon = false;
+ verifyFormat("class Foo : public Bar {};", ForLoopStyle);
+ verifyFormat("Foo::Foo() : foo(1) {}", ForLoopStyle);
+ verifyFormat("for (auto a: b) {\n}", ForLoopStyle);
+ verifyFormat("int x = a ? b : c;", ForLoopStyle);
+ verifyFormat("{\n"
+ "label2:\n"
+ " int x = 0;\n"
+ "}",
+ ForLoopStyle);
+ verifyFormat("switch (x) {\n"
+ "case 1:\n"
+ "default:\n"
+ "}",
+ ForLoopStyle);
+
+ FormatStyle NoSpaceStyle = getLLVMStyle();
+ NoSpaceStyle.SpaceBeforeCtorInitializerColon = false;
+ NoSpaceStyle.SpaceBeforeInheritanceColon = false;
+ NoSpaceStyle.SpaceBeforeRangeBasedForLoopColon = false;
+ verifyFormat("class Foo: public Bar {};", NoSpaceStyle);
+ verifyFormat("Foo::Foo(): foo(1) {}", NoSpaceStyle);
+ verifyFormat("for (auto a: b) {\n}", NoSpaceStyle);
+ verifyFormat("int x = a ? b : c;", NoSpaceStyle);
+ verifyFormat("{\n"
+ "label3:\n"
+ " int x = 0;\n"
+ "}",
+ NoSpaceStyle);
+ verifyFormat("switch (x) {\n"
+ "case 1:\n"
+ "default:\n"
+ "}",
+ NoSpaceStyle);
+}
+
TEST_F(FormatTest, AlignConsecutiveAssignments) {
FormatStyle Alignment = getLLVMStyle();
Alignment.AlignConsecutiveAssignments = false;
@@ -10151,13 +10599,11 @@ TEST_F(FormatTest, ParsesConfigurationBools) {
CHECK_PARSE_BOOL(AllowShortCaseLabelsOnASingleLine);
CHECK_PARSE_BOOL(AllowShortIfStatementsOnASingleLine);
CHECK_PARSE_BOOL(AllowShortLoopsOnASingleLine);
- CHECK_PARSE_BOOL(AlwaysBreakTemplateDeclarations);
CHECK_PARSE_BOOL(BinPackArguments);
CHECK_PARSE_BOOL(BinPackParameters);
CHECK_PARSE_BOOL(BreakAfterJavaFieldAnnotations);
CHECK_PARSE_BOOL(BreakBeforeTernaryOperators);
CHECK_PARSE_BOOL(BreakStringLiterals);
- CHECK_PARSE_BOOL(BreakBeforeInheritanceComma)
CHECK_PARSE_BOOL(CompactNamespaces);
CHECK_PARSE_BOOL(ConstructorInitializerAllOnOneLineOrOnePerLine);
CHECK_PARSE_BOOL(DerivePointerAlignment);
@@ -10181,6 +10627,10 @@ TEST_F(FormatTest, ParsesConfigurationBools) {
CHECK_PARSE_BOOL(SpaceAfterCStyleCast);
CHECK_PARSE_BOOL(SpaceAfterTemplateKeyword);
CHECK_PARSE_BOOL(SpaceBeforeAssignmentOperators);
+ CHECK_PARSE_BOOL(SpaceBeforeCpp11BracedList);
+ CHECK_PARSE_BOOL(SpaceBeforeCtorInitializerColon);
+ CHECK_PARSE_BOOL(SpaceBeforeInheritanceColon);
+ CHECK_PARSE_BOOL(SpaceBeforeRangeBasedForLoopColon);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterClass);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterControlStatement);
@@ -10214,6 +10664,8 @@ TEST_F(FormatTest, ParsesConfiguration) {
PenaltyBreakAssignment, 1234u);
CHECK_PARSE("PenaltyBreakBeforeFirstCallParameter: 1234",
PenaltyBreakBeforeFirstCallParameter, 1234u);
+ CHECK_PARSE("PenaltyBreakTemplateDeclaration: 1234",
+ PenaltyBreakTemplateDeclaration, 1234u);
CHECK_PARSE("PenaltyExcessCharacter: 1234", PenaltyExcessCharacter, 1234u);
CHECK_PARSE("PenaltyReturnTypeOnItsOwnLine: 1234",
PenaltyReturnTypeOnItsOwnLine, 1234u);
@@ -10269,6 +10721,17 @@ TEST_F(FormatTest, ParsesConfiguration) {
CHECK_PARSE("BreakConstructorInitializersBeforeComma: true",
BreakConstructorInitializers, FormatStyle::BCIS_BeforeComma);
+ Style.BreakInheritanceList = FormatStyle::BILS_BeforeColon;
+ CHECK_PARSE("BreakInheritanceList: BeforeComma",
+ BreakInheritanceList, FormatStyle::BILS_BeforeComma);
+ CHECK_PARSE("BreakInheritanceList: AfterColon",
+ BreakInheritanceList, FormatStyle::BILS_AfterColon);
+ CHECK_PARSE("BreakInheritanceList: BeforeColon",
+ BreakInheritanceList, FormatStyle::BILS_BeforeColon);
+ // For backward compatibility:
+ CHECK_PARSE("BreakBeforeInheritanceComma: true",
+ BreakInheritanceList, FormatStyle::BILS_BeforeComma);
+
Style.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak;
CHECK_PARSE("AlignAfterOpenBracket: Align", AlignAfterOpenBracket,
FormatStyle::BAS_Align);
@@ -10368,6 +10831,18 @@ TEST_F(FormatTest, ParsesConfiguration) {
AlwaysBreakAfterReturnType,
FormatStyle::RTBS_TopLevelDefinitions);
+ Style.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes;
+ CHECK_PARSE("AlwaysBreakTemplateDeclarations: No", AlwaysBreakTemplateDeclarations,
+ FormatStyle::BTDS_No);
+ CHECK_PARSE("AlwaysBreakTemplateDeclarations: MultiLine", AlwaysBreakTemplateDeclarations,
+ FormatStyle::BTDS_MultiLine);
+ CHECK_PARSE("AlwaysBreakTemplateDeclarations: Yes", AlwaysBreakTemplateDeclarations,
+ FormatStyle::BTDS_Yes);
+ CHECK_PARSE("AlwaysBreakTemplateDeclarations: false", AlwaysBreakTemplateDeclarations,
+ FormatStyle::BTDS_MultiLine);
+ CHECK_PARSE("AlwaysBreakTemplateDeclarations: true", AlwaysBreakTemplateDeclarations,
+ FormatStyle::BTDS_Yes);
+
Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All;
CHECK_PARSE("AlwaysBreakAfterDefinitionReturnType: None",
AlwaysBreakAfterDefinitionReturnType, FormatStyle::DRTBS_None);
@@ -10397,29 +10872,52 @@ TEST_F(FormatTest, ParsesConfiguration) {
CHECK_PARSE("ForEachMacros: [BOOST_FOREACH, Q_FOREACH]", ForEachMacros,
BoostAndQForeach);
- Style.IncludeCategories.clear();
- std::vector<FormatStyle::IncludeCategory> ExpectedCategories = {{"abc/.*", 2},
- {".*", 1}};
+ Style.IncludeStyle.IncludeCategories.clear();
+ std::vector<tooling::IncludeStyle::IncludeCategory> ExpectedCategories = {
+ {"abc/.*", 2}, {".*", 1}};
CHECK_PARSE("IncludeCategories:\n"
" - Regex: abc/.*\n"
" Priority: 2\n"
" - Regex: .*\n"
" Priority: 1",
- IncludeCategories, ExpectedCategories);
- CHECK_PARSE("IncludeIsMainRegex: 'abc$'", IncludeIsMainRegex, "abc$");
+ IncludeStyle.IncludeCategories, ExpectedCategories);
+ CHECK_PARSE("IncludeIsMainRegex: 'abc$'", IncludeStyle.IncludeIsMainRegex,
+ "abc$");
Style.RawStringFormats.clear();
std::vector<FormatStyle::RawStringFormat> ExpectedRawStringFormats = {
- {"pb", FormatStyle::LK_TextProto, "llvm"},
- {"cpp", FormatStyle::LK_Cpp, "google"}};
+ {
+ FormatStyle::LK_TextProto,
+ {"pb", "proto"},
+ {"PARSE_TEXT_PROTO"},
+ /*CanonicalDelimiter=*/"",
+ "llvm",
+ },
+ {
+ FormatStyle::LK_Cpp,
+ {"cc", "cpp"},
+ {"C_CODEBLOCK", "CPPEVAL"},
+ /*CanonicalDelimiter=*/"cc",
+ /*BasedOnStyle=*/"",
+ },
+ };
CHECK_PARSE("RawStringFormats:\n"
- " - Delimiter: 'pb'\n"
- " Language: TextProto\n"
+ " - Language: TextProto\n"
+ " Delimiters:\n"
+ " - 'pb'\n"
+ " - 'proto'\n"
+ " EnclosingFunctions:\n"
+ " - 'PARSE_TEXT_PROTO'\n"
" BasedOnStyle: llvm\n"
- " - Delimiter: 'cpp'\n"
- " Language: Cpp\n"
- " BasedOnStyle: google",
+ " - Language: Cpp\n"
+ " Delimiters:\n"
+ " - 'cc'\n"
+ " - 'cpp'\n"
+ " EnclosingFunctions:\n"
+ " - 'C_CODEBLOCK'\n"
+ " - 'CPPEVAL'\n"
+ " CanonicalDelimiter: 'cc'",
RawStringFormats, ExpectedRawStringFormats);
}
@@ -11608,6 +12106,13 @@ TEST_F(FormatTest, NoSpaceAfterSuper) {
verifyFormat("__super::FooBar();");
}
+TEST(FormatStyle, GetStyleWithEmptyFileName) {
+ vfs::InMemoryFileSystem FS;
+ auto Style1 = getStyle("file", "", "Google", "", &FS);
+ ASSERT_TRUE((bool)Style1);
+ ASSERT_EQ(*Style1, getGoogleStyle());
+}
+
TEST(FormatStyle, GetStyleOfFile) {
vfs::InMemoryFileSystem FS;
// Test 1: format file in the same directory.
@@ -11837,6 +12342,90 @@ TEST_F(FormatTest, StructuredBindings) {
verifyFormat("auto const &[ a, b ] = f();", Spaces);
}
+TEST_F(FormatTest, FileAndCode) {
+ EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo.cc", ""));
+ EXPECT_EQ(FormatStyle::LK_ObjC, guessLanguage("foo.m", ""));
+ EXPECT_EQ(FormatStyle::LK_ObjC, guessLanguage("foo.mm", ""));
+ EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo.h", ""));
+ EXPECT_EQ(FormatStyle::LK_ObjC, guessLanguage("foo.h", "@interface Foo\n@end\n"));
+ EXPECT_EQ(
+ FormatStyle::LK_ObjC,
+ guessLanguage("foo.h", "#define TRY(x, y) @try { x; } @finally { y; }"));
+ EXPECT_EQ(FormatStyle::LK_ObjC,
+ guessLanguage("foo.h", "#define AVAIL(x) @available(x, *))"));
+ EXPECT_EQ(FormatStyle::LK_ObjC, guessLanguage("foo.h", "@class Foo;"));
+ EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo", ""));
+ EXPECT_EQ(FormatStyle::LK_ObjC, guessLanguage("foo", "@interface Foo\n@end\n"));
+ EXPECT_EQ(FormatStyle::LK_ObjC,
+ guessLanguage("foo.h", "int DoStuff(CGRect rect);\n"));
+ EXPECT_EQ(
+ FormatStyle::LK_ObjC,
+ guessLanguage("foo.h",
+ "#define MY_POINT_MAKE(x, y) CGPointMake((x), (y));\n"));
+ EXPECT_EQ(
+ FormatStyle::LK_Cpp,
+ guessLanguage("foo.h", "#define FOO(...) auto bar = [] __VA_ARGS__;"));
+}
+
+TEST_F(FormatTest, GuessLanguageWithCpp11AttributeSpecifiers) {
+ EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo.h", "[[noreturn]];"));
+ EXPECT_EQ(FormatStyle::LK_ObjC,
+ guessLanguage("foo.h", "array[[calculator getIndex]];"));
+ EXPECT_EQ(FormatStyle::LK_Cpp,
+ guessLanguage("foo.h", "[[noreturn, deprecated(\"so sorry\")]];"));
+ EXPECT_EQ(
+ FormatStyle::LK_Cpp,
+ guessLanguage("foo.h", "[[noreturn, deprecated(\"gone, sorry\")]];"));
+ EXPECT_EQ(FormatStyle::LK_ObjC,
+ guessLanguage("foo.h", "[[noreturn foo] bar];"));
+ EXPECT_EQ(FormatStyle::LK_Cpp,
+ guessLanguage("foo.h", "[[clang::fallthrough]];"));
+ EXPECT_EQ(FormatStyle::LK_ObjC,
+ guessLanguage("foo.h", "[[clang:fallthrough] foo];"));
+ EXPECT_EQ(FormatStyle::LK_Cpp,
+ guessLanguage("foo.h", "[[gsl::suppress(\"type\")]];"));
+ EXPECT_EQ(FormatStyle::LK_Cpp,
+ guessLanguage("foo.h", "[[using clang: fallthrough]];"));
+ EXPECT_EQ(FormatStyle::LK_ObjC,
+ guessLanguage("foo.h", "[[abusing clang:fallthrough] bar];"));
+ EXPECT_EQ(FormatStyle::LK_Cpp,
+ guessLanguage("foo.h", "[[using gsl: suppress(\"type\")]];"));
+ EXPECT_EQ(
+ FormatStyle::LK_Cpp,
+ guessLanguage("foo.h",
+ "[[clang::callable_when(\"unconsumed\", \"unknown\")]]"));
+ EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo.h", "[[foo::bar, ...]]"));
+}
+
+TEST_F(FormatTest, GuessLanguageWithCaret) {
+ EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo.h", "FOO(^);"));
+ EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo.h", "FOO(^, Bar);"));
+ EXPECT_EQ(FormatStyle::LK_ObjC,
+ guessLanguage("foo.h", "int(^)(char, float);"));
+ EXPECT_EQ(FormatStyle::LK_ObjC,
+ guessLanguage("foo.h", "int(^foo)(char, float);"));
+ EXPECT_EQ(FormatStyle::LK_ObjC,
+ guessLanguage("foo.h", "int(^foo[10])(char, float);"));
+ EXPECT_EQ(FormatStyle::LK_ObjC,
+ guessLanguage("foo.h", "int(^foo[kNumEntries])(char, float);"));
+ EXPECT_EQ(
+ FormatStyle::LK_ObjC,
+ guessLanguage("foo.h", "int(^foo[(kNumEntries + 10)])(char, float);"));
+}
+
+TEST_F(FormatTest, GuessLanguageWithChildLines) {
+ EXPECT_EQ(FormatStyle::LK_Cpp,
+ guessLanguage("foo.h", "#define FOO ({ std::string s; })"));
+ EXPECT_EQ(FormatStyle::LK_ObjC,
+ guessLanguage("foo.h", "#define FOO ({ NSString *s; })"));
+ EXPECT_EQ(
+ FormatStyle::LK_Cpp,
+ guessLanguage("foo.h", "#define FOO ({ foo(); ({ std::string s; }) })"));
+ EXPECT_EQ(
+ FormatStyle::LK_ObjC,
+ guessLanguage("foo.h", "#define FOO ({ foo(); ({ NSString *s; }) })"));
+}
+
} // end namespace
} // end namespace format
} // end namespace clang
diff --git a/unittests/Format/FormatTestComments.cpp b/unittests/Format/FormatTestComments.cpp
index ed11fbdb1fc0..cacd2024fef3 100644
--- a/unittests/Format/FormatTestComments.cpp
+++ b/unittests/Format/FormatTestComments.cpp
@@ -38,8 +38,8 @@ protected:
std::string format(llvm::StringRef Code,
const FormatStyle &Style = getLLVMStyle(),
StatusCheck CheckComplete = SC_ExpectComplete) {
- DEBUG(llvm::errs() << "---\n");
- DEBUG(llvm::errs() << Code << "\n\n");
+ LLVM_DEBUG(llvm::errs() << "---\n");
+ LLVM_DEBUG(llvm::errs() << Code << "\n\n");
std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
FormattingAttemptStatus Status;
tooling::Replacements Replaces =
@@ -52,7 +52,7 @@ protected:
ReplacementCount = Replaces.size();
auto Result = applyAllReplacements(Code, Replaces);
EXPECT_TRUE(static_cast<bool>(Result));
- DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
+ LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
return *Result;
}
@@ -70,6 +70,7 @@ protected:
void verifyFormat(llvm::StringRef Code,
const FormatStyle &Style = getLLVMStyle()) {
+ EXPECT_EQ(Code.str(), format(Code, Style)) << "Expected code is not stable";
EXPECT_EQ(Code.str(), format(test::messUp(Code), Style));
}
@@ -3089,6 +3090,21 @@ TEST_F(FormatTestComments, BreaksBeforeTrailingUnbreakableSequence) {
getLLVMStyleWithColumns(23));
}
+TEST_F(FormatTestComments, ReflowBackslashCrash) {
+// clang-format off
+ EXPECT_EQ(
+"// How to run:\n"
+"// bbbbb run \\\n"
+"// rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr\n"
+"// \\ <log_file> -- --output_directory=\"<output_directory>\"",
+ format(
+"// How to run:\n"
+"// bbbbb run \\\n"
+"// rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr \\\n"
+"// <log_file> -- --output_directory=\"<output_directory>\""));
+// clang-format on
+}
+
} // end namespace
} // end namespace format
} // end namespace clang
diff --git a/unittests/Format/FormatTestJS.cpp b/unittests/Format/FormatTestJS.cpp
index 2a929563f754..9975b7d31125 100644
--- a/unittests/Format/FormatTestJS.cpp
+++ b/unittests/Format/FormatTestJS.cpp
@@ -21,8 +21,8 @@ class FormatTestJS : public ::testing::Test {
protected:
static std::string format(llvm::StringRef Code, unsigned Offset,
unsigned Length, const FormatStyle &Style) {
- DEBUG(llvm::errs() << "---\n");
- DEBUG(llvm::errs() << Code << "\n\n");
+ LLVM_DEBUG(llvm::errs() << "---\n");
+ LLVM_DEBUG(llvm::errs() << Code << "\n\n");
std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));
FormattingAttemptStatus Status;
tooling::Replacements Replaces =
@@ -30,7 +30,7 @@ protected:
EXPECT_TRUE(Status.FormatComplete);
auto Result = applyAllReplacements(Code, Replaces);
EXPECT_TRUE(static_cast<bool>(Result));
- DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
+ LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
return *Result;
}
@@ -49,6 +49,8 @@ protected:
static void verifyFormat(
llvm::StringRef Code,
const FormatStyle &Style = getGoogleStyle(FormatStyle::LK_JavaScript)) {
+ EXPECT_EQ(Code.str(), format(Code, Style))
+ << "Expected code is not stable";
std::string Result = format(test::messUp(Code), Style);
EXPECT_EQ(Code.str(), Result) << "Formatted:\n" << Result;
}
@@ -57,6 +59,8 @@ protected:
llvm::StringRef Expected,
llvm::StringRef Code,
const FormatStyle &Style = getGoogleStyle(FormatStyle::LK_JavaScript)) {
+ EXPECT_EQ(Expected.str(), format(Expected, Style))
+ << "Expected code is not stable";
std::string Result = format(Code, Style);
EXPECT_EQ(Expected.str(), Result) << "Formatted:\n" << Result;
}
@@ -294,6 +298,7 @@ TEST_F(FormatTestJS, ReservedWords) {
verifyFormat("x.for = 1;");
verifyFormat("x.of();");
verifyFormat("of(null);");
+ verifyFormat("return of(null);");
verifyFormat("import {of} from 'x';");
verifyFormat("x.in();");
verifyFormat("x.let();");
@@ -1157,6 +1162,17 @@ TEST_F(FormatTestJS, WrapRespectsAutomaticSemicolonInsertion) {
"foo() {}",
getGoogleJSStyleWithColumns(10));
verifyFormat("await theReckoning;", getGoogleJSStyleWithColumns(10));
+ verifyFormat("some['a']['b']", getGoogleJSStyleWithColumns(10));
+ verifyFormat("x = (a['a']\n"
+ " ['b']);",
+ getGoogleJSStyleWithColumns(10));
+ verifyFormat("function f() {\n"
+ " return foo.bar(\n"
+ " (param): param is {\n"
+ " a: SomeType\n"
+ " }&ABC => 1)\n"
+ "}",
+ getGoogleJSStyleWithColumns(25));
}
TEST_F(FormatTestJS, AutomaticSemicolonInsertionHeuristic) {
@@ -1524,6 +1540,15 @@ TEST_F(FormatTestJS, ClassDeclarations) {
"}");
}
+TEST_F(FormatTestJS, StrictPropInitWrap) {
+ const FormatStyle &Style = getGoogleJSStyleWithColumns(22);
+ verifyFormat("class X {\n"
+ " strictPropInitField!:\n"
+ " string;\n"
+ "}",
+ Style);
+}
+
TEST_F(FormatTestJS, InterfaceDeclarations) {
verifyFormat("interface I {\n"
" x: string;\n"
@@ -2129,6 +2154,7 @@ TEST_F(FormatTestJS, NonNullAssertionOperator) {
verifyFormat("let x = foo!.bar();\n");
verifyFormat("let x = foo ? bar! : baz;\n");
verifyFormat("let x = !foo;\n");
+ verifyFormat("if (!+a) {\n}");
verifyFormat("let x = foo[0]!;\n");
verifyFormat("let x = (foo)!;\n");
verifyFormat("let x = x(foo!);\n");
diff --git a/unittests/Format/FormatTestJava.cpp b/unittests/Format/FormatTestJava.cpp
index 2f376f765d66..76e82612e0fe 100644
--- a/unittests/Format/FormatTestJava.cpp
+++ b/unittests/Format/FormatTestJava.cpp
@@ -21,13 +21,13 @@ class FormatTestJava : public ::testing::Test {
protected:
static std::string format(llvm::StringRef Code, unsigned Offset,
unsigned Length, const FormatStyle &Style) {
- DEBUG(llvm::errs() << "---\n");
- DEBUG(llvm::errs() << Code << "\n\n");
+ LLVM_DEBUG(llvm::errs() << "---\n");
+ LLVM_DEBUG(llvm::errs() << Code << "\n\n");
std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));
tooling::Replacements Replaces = reformat(Style, Code, Ranges);
auto Result = applyAllReplacements(Code, Replaces);
EXPECT_TRUE(static_cast<bool>(Result));
- DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
+ LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
return *Result;
}
@@ -46,6 +46,7 @@ protected:
static void verifyFormat(
llvm::StringRef Code,
const FormatStyle &Style = getGoogleStyle(FormatStyle::LK_Java)) {
+ EXPECT_EQ(Code.str(), format(Code, Style)) << "Expected code is not stable";
EXPECT_EQ(Code.str(), format(test::messUp(Code), Style));
}
};
@@ -144,6 +145,7 @@ TEST_F(FormatTestJava, ClassDeclarations) {
verifyFormat("public interface SomeInterface {\n"
" void doStuff(int theStuff);\n"
" void doMoreStuff(int moreStuff);\n"
+ " default void doStuffWithDefault() {}\n"
"}");
verifyFormat("@interface SomeInterface {\n"
" void doStuff(int theStuff);\n"
diff --git a/unittests/Format/FormatTestObjC.cpp b/unittests/Format/FormatTestObjC.cpp
index 4220b44b4c47..e56df6d130d2 100644
--- a/unittests/Format/FormatTestObjC.cpp
+++ b/unittests/Format/FormatTestObjC.cpp
@@ -40,8 +40,8 @@ protected:
std::string format(llvm::StringRef Code,
StatusCheck CheckComplete = SC_ExpectComplete) {
- DEBUG(llvm::errs() << "---\n");
- DEBUG(llvm::errs() << Code << "\n\n");
+ LLVM_DEBUG(llvm::errs() << "---\n");
+ LLVM_DEBUG(llvm::errs() << Code << "\n\n");
std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
FormattingAttemptStatus Status;
tooling::Replacements Replaces =
@@ -53,11 +53,12 @@ protected:
}
auto Result = applyAllReplacements(Code, Replaces);
EXPECT_TRUE(static_cast<bool>(Result));
- DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
+ LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
return *Result;
}
void verifyFormat(StringRef Code) {
+ EXPECT_EQ(Code.str(), format(Code)) << "Expected code is not stable";
EXPECT_EQ(Code.str(), format(test::messUp(Code)));
}
@@ -94,6 +95,75 @@ TEST(FormatTestObjCStyle, DetectsObjCInHeaders) {
Style = getStyle("LLVM", "a.h", "none", "void f() {}");
ASSERT_TRUE((bool)Style);
EXPECT_EQ(FormatStyle::LK_Cpp, Style->Language);
+
+ Style = getStyle("{}", "a.h", "none", "@interface Foo\n@end\n");
+ ASSERT_TRUE((bool)Style);
+ EXPECT_EQ(FormatStyle::LK_ObjC, Style->Language);
+
+ Style = getStyle("{}", "a.h", "none",
+ "const int interface = 1;\nconst int end = 2;\n");
+ ASSERT_TRUE((bool)Style);
+ EXPECT_EQ(FormatStyle::LK_Cpp, Style->Language);
+
+ Style = getStyle("{}", "a.h", "none", "@protocol Foo\n@end\n");
+ ASSERT_TRUE((bool)Style);
+ EXPECT_EQ(FormatStyle::LK_ObjC, Style->Language);
+
+ Style = getStyle("{}", "a.h", "none",
+ "const int protocol = 1;\nconst int end = 2;\n");
+ ASSERT_TRUE((bool)Style);
+ EXPECT_EQ(FormatStyle::LK_Cpp, Style->Language);
+
+ Style =
+ getStyle("{}", "a.h", "none", "typedef NS_ENUM(NSInteger, Foo) {};\n");
+ ASSERT_TRUE((bool)Style);
+ EXPECT_EQ(FormatStyle::LK_ObjC, Style->Language);
+
+ Style = getStyle("{}", "a.h", "none", "enum Foo {};");
+ ASSERT_TRUE((bool)Style);
+ EXPECT_EQ(FormatStyle::LK_Cpp, Style->Language);
+
+ Style =
+ getStyle("{}", "a.h", "none", "inline void Foo() { Log(@\"Foo\"); }\n");
+ ASSERT_TRUE((bool)Style);
+ EXPECT_EQ(FormatStyle::LK_ObjC, Style->Language);
+
+ Style =
+ getStyle("{}", "a.h", "none", "inline void Foo() { Log(\"Foo\"); }\n");
+ ASSERT_TRUE((bool)Style);
+ EXPECT_EQ(FormatStyle::LK_Cpp, Style->Language);
+
+ Style =
+ getStyle("{}", "a.h", "none", "inline void Foo() { id = @[1, 2, 3]; }\n");
+ ASSERT_TRUE((bool)Style);
+ EXPECT_EQ(FormatStyle::LK_ObjC, Style->Language);
+
+ Style = getStyle("{}", "a.h", "none",
+ "inline void Foo() { id foo = @{1: 2, 3: 4, 5: 6}; }\n");
+ ASSERT_TRUE((bool)Style);
+ EXPECT_EQ(FormatStyle::LK_ObjC, Style->Language);
+
+ Style = getStyle("{}", "a.h", "none",
+ "inline void Foo() { int foo[] = {1, 2, 3}; }\n");
+ ASSERT_TRUE((bool)Style);
+ EXPECT_EQ(FormatStyle::LK_Cpp, Style->Language);
+
+ // ObjC characteristic types.
+ Style = getStyle("{}", "a.h", "none", "extern NSString *kFoo;\n");
+ ASSERT_TRUE((bool)Style);
+ EXPECT_EQ(FormatStyle::LK_ObjC, Style->Language);
+
+ Style = getStyle("{}", "a.h", "none", "extern NSInteger Foo();\n");
+ ASSERT_TRUE((bool)Style);
+ EXPECT_EQ(FormatStyle::LK_ObjC, Style->Language);
+
+ Style = getStyle("{}", "a.h", "none", "NSObject *Foo();\n");
+ ASSERT_TRUE((bool)Style);
+ EXPECT_EQ(FormatStyle::LK_ObjC, Style->Language);
+
+ Style = getStyle("{}", "a.h", "none", "NSSet *Foo();\n");
+ ASSERT_TRUE((bool)Style);
+ EXPECT_EQ(FormatStyle::LK_ObjC, Style->Language);
}
TEST_F(FormatTestObjC, FormatObjCTryCatch) {
@@ -118,7 +188,8 @@ TEST_F(FormatTestObjC, FormatObjCAutoreleasepool) {
"@autoreleasepool {\n"
" f();\n"
"}\n");
- Style.BreakBeforeBraces = FormatStyle::BS_Allman;
+ Style.BreakBeforeBraces = FormatStyle::BS_Custom;
+ Style.BraceWrapping.AfterControlStatement = true;
verifyFormat("@autoreleasepool\n"
"{\n"
" f();\n"
@@ -129,6 +200,36 @@ TEST_F(FormatTestObjC, FormatObjCAutoreleasepool) {
"}\n");
}
+TEST_F(FormatTestObjC, FormatObjCGenerics) {
+ Style.ColumnLimit = 40;
+ verifyFormat("int aaaaaaaaaaaaaaaa(\n"
+ " NSArray<aaaaaaaaaaaaaaaaaa *>\n"
+ " aaaaaaaaaaaaaaaaa);\n");
+ verifyFormat("int aaaaaaaaaaaaaaaa(\n"
+ " NSArray<aaaaaaaaaaaaaaaaaaa<\n"
+ " aaaaaaaaaaaaaaaa *> *>\n"
+ " aaaaaaaaaaaaaaaaa);\n");
+}
+
+TEST_F(FormatTestObjC, FormatObjCSynchronized) {
+ verifyFormat("@synchronized(self) {\n"
+ " f();\n"
+ "}\n"
+ "@synchronized(self) {\n"
+ " f();\n"
+ "}\n");
+ Style.BreakBeforeBraces = FormatStyle::BS_Custom;
+ Style.BraceWrapping.AfterControlStatement = true;
+ verifyFormat("@synchronized(self)\n"
+ "{\n"
+ " f();\n"
+ "}\n"
+ "@synchronized(self)\n"
+ "{\n"
+ " f();\n"
+ "}\n");
+}
+
TEST_F(FormatTestObjC, FormatObjCInterface) {
verifyFormat("@interface Foo : NSObject <NSSomeDelegate> {\n"
"@public\n"
@@ -155,6 +256,12 @@ TEST_F(FormatTestObjC, FormatObjCInterface) {
"@end");
verifyFormat("@interface Foo : Bar\n"
+ "@property(assign, readwrite) NSInteger bar;\n"
+ "+ (id)init;\n"
+ "@end");
+
+ verifyFormat("FOUNDATION_EXPORT NS_AVAILABLE_IOS(10.0) @interface Foo : Bar\n"
+ "@property(assign, readwrite) NSInteger bar;\n"
"+ (id)init;\n"
"@end");
@@ -192,6 +299,18 @@ TEST_F(FormatTestObjC, FormatObjCInterface) {
"+ (id)init;\n"
"@end");
+ verifyFormat("@interface Foo<Baz : Blech> : Bar <Baz, Quux> {\n"
+ " int _i;\n"
+ "}\n"
+ "+ (id)init;\n"
+ "@end");
+
+ verifyFormat("@interface Foo<Bar : Baz <Blech>> : Xyzzy <Corge> {\n"
+ " int _i;\n"
+ "}\n"
+ "+ (id)init;\n"
+ "@end");
+
verifyFormat("@interface Foo (HackStuff) {\n"
" int _i;\n"
"}\n"
@@ -209,9 +328,46 @@ TEST_F(FormatTestObjC, FormatObjCInterface) {
"}\n"
"+ (id)init;\n"
"@end");
+ verifyFormat("@interface Foo\n"
+ "- (void)foo {\n"
+ "}\n"
+ "@end\n"
+ "@implementation Bar\n"
+ "- (void)bar {\n"
+ "}\n"
+ "@end");
+ Style.ColumnLimit = 40;
+ verifyFormat("@interface ccccccccccccc () <\n"
+ " ccccccccccccc, ccccccccccccc,\n"
+ " ccccccccccccc, ccccccccccccc> {\n"
+ "}");
+ verifyFormat("@interface ccccccccccccc (ccccccccccc) <\n"
+ " ccccccccccccc> {\n"
+ "}");
+ Style.ObjCBinPackProtocolList = FormatStyle::BPS_Never;
+ verifyFormat("@interface ddddddddddddd () <\n"
+ " ddddddddddddd,\n"
+ " ddddddddddddd,\n"
+ " ddddddddddddd,\n"
+ " ddddddddddddd> {\n"
+ "}");
+
+ Style.BinPackParameters = false;
+ Style.ObjCBinPackProtocolList = FormatStyle::BPS_Auto;
+ verifyFormat("@interface eeeeeeeeeeeee () <\n"
+ " eeeeeeeeeeeee,\n"
+ " eeeeeeeeeeeee,\n"
+ " eeeeeeeeeeeee,\n"
+ " eeeeeeeeeeeee> {\n"
+ "}");
+ Style.ObjCBinPackProtocolList = FormatStyle::BPS_Always;
+ verifyFormat("@interface fffffffffffff () <\n"
+ " fffffffffffff, fffffffffffff,\n"
+ " fffffffffffff, fffffffffffff> {\n"
+ "}");
Style = getGoogleStyle(FormatStyle::LK_ObjC);
- verifyFormat("@interface Foo : NSObject<NSSomeDelegate> {\n"
+ verifyFormat("@interface Foo : NSObject <NSSomeDelegate> {\n"
" @public\n"
" int field1;\n"
" @protected\n"
@@ -223,19 +379,22 @@ TEST_F(FormatTestObjC, FormatObjCInterface) {
"}\n"
"+ (id)init;\n"
"@end");
- verifyFormat("@interface Foo : Bar<Baz, Quux>\n"
+ verifyFormat("@interface Foo : Bar <Baz, Quux>\n"
"+ (id)init;\n"
"@end");
- verifyFormat("@interface Foo (HackStuff)<MyProtocol>\n"
+ verifyFormat("@interface Foo (HackStuff) <MyProtocol>\n"
"+ (id)init;\n"
"@end");
- Style.BinPackParameters = false;
- Style.ColumnLimit = 80;
- verifyFormat("@interface aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ()<\n"
- " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
- " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
- " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
- " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa> {\n"
+ Style.ColumnLimit = 40;
+ // BinPackParameters should be true by default.
+ verifyFormat("void eeeeeeee(int eeeee, int eeeee,\n"
+ " int eeeee, int eeeee);\n");
+ // ObjCBinPackProtocolList should be BPS_Never by default.
+ verifyFormat("@interface fffffffffffff () <\n"
+ " fffffffffffff,\n"
+ " fffffffffffff,\n"
+ " fffffffffffff,\n"
+ " fffffffffffff> {\n"
"}");
}
@@ -334,6 +493,10 @@ TEST_F(FormatTestObjC, FormatObjCProtocol) {
"@protocol Bar\n"
"@end");
+ verifyFormat("FOUNDATION_EXPORT NS_AVAILABLE_IOS(10.0) @protocol Foo\n"
+ "@property(assign, readwrite) NSInteger bar;\n"
+ "@end");
+
verifyFormat("@protocol myProtocol\n"
"- (void)mandatoryWithInt:(int)i;\n"
"@optional\n"
@@ -354,7 +517,7 @@ TEST_F(FormatTestObjC, FormatObjCProtocol) {
"@end");
Style = getGoogleStyle(FormatStyle::LK_ObjC);
- verifyFormat("@protocol MyProtocol<NSObject>\n"
+ verifyFormat("@protocol MyProtocol <NSObject>\n"
"- (NSUInteger)numberOfThings;\n"
"@end");
}
@@ -374,6 +537,7 @@ TEST_F(FormatTestObjC, FormatObjCMethodDeclarations) {
" evenLongerKeyword:(float)theInterval\n"
" error:(NSError **)theError {\n"
"}");
+ verifyFormat("+ (instancetype)new;\n");
Style.ColumnLimit = 60;
verifyFormat("- (instancetype)initXxxxxx:(id<x>)x\n"
" y:(id<yyyyyyyyyyyyyyyyyyyy>)y\n"
@@ -381,12 +545,26 @@ TEST_F(FormatTestObjC, FormatObjCMethodDeclarations) {
verifyFormat("- (void)drawRectOn:(id)surface\n"
" ofSize:(size_t)height\n"
" :(size_t)width;");
+ Style.ColumnLimit = 40;
+ // Make sure selectors with 0, 1, or more arguments are indented when wrapped.
+ verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaaa;\n");
+ verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a;\n");
+ verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a;\n");
+ verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a;\n");
+ verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a;\n");
// Continuation indent width should win over aligning colons if the function
// name is long.
Style = getGoogleStyle(FormatStyle::LK_ObjC);
Style.ColumnLimit = 40;
- Style.IndentWrappedFunctionNames = true;
verifyFormat("- (void)shortf:(GTMFoo *)theFoo\n"
" dontAlignNamef:(NSRect)theRect {\n"
"}");
@@ -478,6 +656,9 @@ TEST_F(FormatTestObjC, FormatObjCMethodExpr) {
verifyFormat("for (id foo in [self getStuffFor:bla]) {\n"
"}");
verifyFormat("[self aaaaa:MACRO(a, b:, c:)];");
+ verifyFormat("[self aaaaa:MACRO(a, b:c:, d:e:)];");
+ verifyFormat("[self aaaaa:MACRO(a, b:c:d:, e:f:g:)];");
+ verifyFormat("int XYMyFoo(int a, int b) NS_SWIFT_NAME(foo(self:scale:));");
verifyFormat("[self aaaaa:(1 + 2) bbbbb:3];");
verifyFormat("[self aaaaa:(Type)a bbbbb:3];");
@@ -497,6 +678,18 @@ TEST_F(FormatTestObjC, FormatObjCMethodExpr) {
verifyFormat("[(id)foo bar:(id) ? baz : quux];");
verifyFormat("4 > 4 ? (id)a : (id)baz;");
+ unsigned PreviousColumnLimit = Style.ColumnLimit;
+ Style.ColumnLimit = 50;
+ // Instead of:
+ // bool a =
+ // ([object a:42] == 0 || [object a:42
+ // b:42] == 0);
+ verifyFormat("bool a = ([object a:42] == 0 ||\n"
+ " [object a:42 b:42] == 0);");
+ Style.ColumnLimit = PreviousColumnLimit;
+ verifyFormat("bool a = ([aaaaaaaa aaaaa] == aaaaaaaaaaaaaaaaa ||\n"
+ " [aaaaaaaa aaaaa] == aaaaaaaaaaaaaaaaaaaa);");
+
// This tests that the formatter doesn't break after "backing" but before ":",
// which would be at 80 columns.
verifyFormat(
@@ -573,17 +766,101 @@ TEST_F(FormatTestObjC, FormatObjCMethodExpr) {
"[self aaaaaaaaaaaaa:aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa,\n"
" aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa,\n"
" aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa];");
+
verifyFormat("[self // break\n"
" a:a\n"
" aaa:aaa];");
- verifyFormat("bool a = ([aaaaaaaa aaaaa] == aaaaaaaaaaaaaaaaa ||\n"
- " [aaaaaaaa aaaaa] == aaaaaaaaaaaaaaaaaaaa);");
// Formats pair-parameters.
verifyFormat("[I drawRectOn:surface ofSize:aa:bbb atOrigin:cc:dd];");
verifyFormat("[I drawRectOn:surface //\n"
- " ofSize:aa:bbb\n"
- " atOrigin:cc:dd];");
+ " ofSize:aa:bbb\n"
+ " atOrigin:cc:dd];");
+
+ // Inline block as a first argument.
+ verifyFormat("[object justBlock:^{\n"
+ " a = 42;\n"
+ "}];");
+ verifyFormat("[object\n"
+ " justBlock:^{\n"
+ " a = 42;\n"
+ " }\n"
+ " notBlock:42\n"
+ " a:42];");
+ verifyFormat("[object\n"
+ " firstBlock:^{\n"
+ " a = 42;\n"
+ " }\n"
+ " blockWithLongerName:^{\n"
+ " a = 42;\n"
+ " }];");
+ verifyFormat("[object\n"
+ " blockWithLongerName:^{\n"
+ " a = 42;\n"
+ " }\n"
+ " secondBlock:^{\n"
+ " a = 42;\n"
+ " }];");
+ verifyFormat("[object\n"
+ " firstBlock:^{\n"
+ " a = 42;\n"
+ " }\n"
+ " notBlock:42\n"
+ " secondBlock:^{\n"
+ " a = 42;\n"
+ " }];");
+
+ // Space between cast rparen and selector name component.
+ verifyFormat("[((Foo *)foo) bar];");
+ verifyFormat("[((Foo *)foo) bar:1 blech:2];");
+
+ Style.ColumnLimit = 20;
+ verifyFormat("aaaaa = [a aa:aa\n"
+ " aa:aa];");
+ verifyFormat("aaaaaa = [aa aa:aa\n"
+ " aa:aa];");
+
+ // Message receiver taking multiple lines.
+ // Non-corner case.
+ verifyFormat("[[object block:^{\n"
+ " return 42;\n"
+ "}] a:42 b:42];");
+ // Arguments just fit into one line.
+ verifyFormat("[[object block:^{\n"
+ " return 42;\n"
+ "}] aaaaaaa:42 b:42];");
+ // Arguments just over a column limit.
+ verifyFormat("[[object block:^{\n"
+ " return 42;\n"
+ "}] aaaaaaa:42\n"
+ " bb:42];");
+ // Arguments just fit into one line.
+ Style.ColumnLimit = 23;
+ verifyFormat("[[obj a:42\n"
+ " b:42\n"
+ " c:42\n"
+ " d:42] e:42 f:42];");
+
+ // Arguments do not fit into one line with a receiver.
+ Style.ColumnLimit = 20;
+ verifyFormat("[[obj a:42] a:42\n"
+ " b:42];");
+ verifyFormat("[[obj a:42] a:42\n"
+ " b:42\n"
+ " c:42];");
+ verifyFormat("[[obj aaaaaa:42\n"
+ " b:42]\n"
+ " cc:42\n"
+ " d:42];");
+
+ // Avoid breaking receiver expression.
+ Style.ColumnLimit = 30;
+ verifyFormat("fooooooo =\n"
+ " [[obj fooo] aaa:42\n"
+ " aaa:42];");
+ verifyFormat("[[[obj foo] bar] aa:42\n"
+ " bb:42\n"
+ " cc:42];");
Style.ColumnLimit = 70;
verifyFormat(
@@ -616,6 +893,26 @@ TEST_F(FormatTestObjC, FormatObjCMethodExpr) {
" backing:NSBackingStoreBuffered\n"
" defer:NO]);\n"
"}");
+
+ // Respect continuation indent and colon alignment (e.g. when object name is
+ // short, and first selector is the longest one)
+ Style = getLLVMStyle();
+ Style.Language = FormatStyle::LK_ObjC;
+ Style.ContinuationIndentWidth = 8;
+ verifyFormat("[self performSelectorOnMainThread:@selector(loadAccessories)\n"
+ " withObject:nil\n"
+ " waitUntilDone:false];");
+ verifyFormat("[self performSelector:@selector(loadAccessories)\n"
+ " withObjectOnMainThread:nil\n"
+ " waitUntilDone:false];");
+ verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " performSelectorOnMainThread:@selector(loadAccessories)\n"
+ " withObject:nil\n"
+ " waitUntilDone:false];");
+ verifyFormat("[self // force wrapping\n"
+ " performSelectorOnMainThread:@selector(loadAccessories)\n"
+ " withObject:nil\n"
+ " waitUntilDone:false];");
}
TEST_F(FormatTestObjC, ObjCAt) {
@@ -652,6 +949,15 @@ TEST_F(FormatTestObjC, ObjCAt) {
verifyFormat("@ /*foo*/ interface");
}
+TEST_F(FormatTestObjC, ObjCBlockTypesAndVariables) {
+ verifyFormat("void DoStuffWithBlockType(int (^)(char));");
+ verifyFormat("int (^foo)(char, float);");
+ verifyFormat("int (^foo[10])(char, float);");
+ verifyFormat("int (^foo[kNumEntries])(char, float);");
+ verifyFormat("int (^foo[kNumEntries + 10])(char, float);");
+ verifyFormat("int (^foo[(kNumEntries + 10)])(char, float);");
+}
+
TEST_F(FormatTestObjC, ObjCSnippets) {
verifyFormat("@autoreleasepool {\n"
" foo();\n"
@@ -676,6 +982,14 @@ TEST_F(FormatTestObjC, ObjCSnippets) {
verifyFormat("@property(assign, nonatomic) CGFloat hoverAlpha;");
verifyFormat("@property(assign, getter=isEditable) BOOL editable;");
+ Style.ColumnLimit = 50;
+ verifyFormat("@interface Foo\n"
+ "- (void)doStuffWithFoo:(id)name\n"
+ " bar:(id)bar\n"
+ " baz:(id)baz\n"
+ " NS_SWIFT_NAME(doStuff(withFoo:bar:baz:));\n"
+ "@end");
+
Style = getMozillaStyle();
verifyFormat("@property (assign, getter=isEditable) BOOL editable;");
verifyFormat("@property BOOL editable;");
@@ -700,6 +1014,88 @@ TEST_F(FormatTestObjC, ObjCForIn) {
" foo(n);\n"
" }\n"
"}");
+ verifyFormat("for (Foo *x in bar) {\n}");
+ verifyFormat("for (Foo *x in [bar baz]) {\n}");
+ verifyFormat("for (Foo *x in [bar baz:blech]) {\n}");
+ verifyFormat("for (Foo *x in [bar baz:blech, 1, 2, 3, 0]) {\n}");
+ verifyFormat("for (Foo *x in [bar baz:^{\n"
+ " [uh oh];\n"
+ " }]) {\n}");
+}
+
+TEST_F(FormatTestObjC, ObjCCxxKeywords) {
+ verifyFormat("+ (instancetype)new {\n"
+ " return nil;\n"
+ "}\n");
+ verifyFormat("+ (instancetype)myNew {\n"
+ " return [self new];\n"
+ "}\n");
+ verifyFormat("SEL NewSelector(void) { return @selector(new); }\n");
+ verifyFormat("SEL MacroSelector(void) { return MACRO(new); }\n");
+ verifyFormat("+ (instancetype)delete {\n"
+ " return nil;\n"
+ "}\n");
+ verifyFormat("+ (instancetype)myDelete {\n"
+ " return [self delete];\n"
+ "}\n");
+ verifyFormat("SEL DeleteSelector(void) { return @selector(delete); }\n");
+ verifyFormat("SEL MacroSelector(void) { return MACRO(delete); }\n");
+ verifyFormat("MACRO(new:)\n");
+ verifyFormat("MACRO(delete:)\n");
+ verifyFormat("foo = @{MACRO(new:) : MACRO(delete:)}\n");
+ verifyFormat("@implementation Foo\n"
+ "// Testing\n"
+ "- (Class)class {\n"
+ "}\n"
+ "- (void)foo {\n"
+ "}\n"
+ "@end\n");
+ verifyFormat("@implementation Foo\n"
+ "- (Class)class {\n"
+ "}\n"
+ "- (void)foo {\n"
+ "}\n"
+ "@end");
+ verifyFormat("@implementation Foo\n"
+ "+ (Class)class {\n"
+ "}\n"
+ "- (void)foo {\n"
+ "}\n"
+ "@end");
+ verifyFormat("@implementation Foo\n"
+ "- (Class)class:(Class)klass {\n"
+ "}\n"
+ "- (void)foo {\n"
+ "}\n"
+ "@end");
+ verifyFormat("@implementation Foo\n"
+ "+ (Class)class:(Class)klass {\n"
+ "}\n"
+ "- (void)foo {\n"
+ "}\n"
+ "@end");
+
+ verifyFormat("@interface Foo\n"
+ "// Testing\n"
+ "- (Class)class;\n"
+ "- (void)foo;\n"
+ "@end\n");
+ verifyFormat("@interface Foo\n"
+ "- (Class)class;\n"
+ "- (void)foo;\n"
+ "@end");
+ verifyFormat("@interface Foo\n"
+ "+ (Class)class;\n"
+ "- (void)foo;\n"
+ "@end");
+ verifyFormat("@interface Foo\n"
+ "- (Class)class:(Class)klass;\n"
+ "- (void)foo;\n"
+ "@end");
+ verifyFormat("@interface Foo\n"
+ "+ (Class)class:(Class)klass;\n"
+ "- (void)foo;\n"
+ "@end");
}
TEST_F(FormatTestObjC, ObjCLiterals) {
@@ -776,6 +1172,30 @@ TEST_F(FormatTestObjC, ObjCDictLiterals) {
" (aaaaaaaa id)aaaaaaaaa : (aaaaaaaa id)aaaaaaaaaaaaaaaaaaaaaaaa,\n"
" (aaaaaaaa id)aaaaaaaaaaaaaa : (aaaaaaaa id)aaaaaaaaaaaaaa,\n"
"};");
+ Style.ColumnLimit = 40;
+ verifyFormat("int Foo() {\n"
+ " a12345 = @{a12345 : a12345};\n"
+ "}");
+ verifyFormat("int Foo() {\n"
+ " a12345 = @{a12345 : @(a12345)};\n"
+ "}");
+ verifyFormat("int Foo() {\n"
+ " a12345 = @{(Foo *)a12345 : @(a12345)};\n"
+ "}");
+ verifyFormat("int Foo() {\n"
+ " a12345 = @{@(a12345) : a12345};\n"
+ "}");
+ verifyFormat("int Foo() {\n"
+ " a12345 = @{@(a12345) : @YES};\n"
+ "}");
+ Style.SpacesInContainerLiterals = false;
+ verifyFormat("int Foo() {\n"
+ " b12345 = @{b12345: b12345};\n"
+ "}");
+ verifyFormat("int Foo() {\n"
+ " b12345 = @{(Foo *)b12345: @(b12345)};\n"
+ "}");
+ Style.SpacesInContainerLiterals = true;
Style = getGoogleStyle(FormatStyle::LK_ObjC);
verifyFormat(
@@ -831,7 +1251,60 @@ TEST_F(FormatTestObjC, ObjCArrayLiterals) {
verifyFormat("[someFunction someLooooooooooooongParameter:@[\n"
" NSBundle.mainBundle.infoDictionary[@\"a\"]\n"
"]];");
+ Style.ColumnLimit = 40;
+ verifyFormat("int Foo() {\n"
+ " a12345 = @[ a12345, a12345 ];\n"
+ "}");
+ verifyFormat("int Foo() {\n"
+ " a123 = @[ (Foo *)a12345, @(a12345) ];\n"
+ "}");
+ Style.SpacesInContainerLiterals = false;
+ verifyFormat("int Foo() {\n"
+ " b12345 = @[b12345, b12345];\n"
+ "}");
+ verifyFormat("int Foo() {\n"
+ " b12345 = @[(Foo *)b12345, @(b12345)];\n"
+ "}");
+ Style.SpacesInContainerLiterals = true;
+ Style.ColumnLimit = 20;
+ // We can't break string literals inside NSArray literals
+ // (that raises -Wobjc-string-concatenation).
+ verifyFormat("NSArray *foo = @[\n"
+ " @\"aaaaaaaaaaaaaaaaaaaaaaaaaa\"\n"
+ "];\n");
+}
+
+TEST_F(FormatTestObjC, BreaksCallStatementWhereSemiJustOverTheLimit) {
+ Style.ColumnLimit = 60;
+ // If the statement starting with 'a = ...' is put on a single line, the ';'
+ // is at line 61.
+ verifyFormat("int f(int a) {\n"
+ " a = [self aaaaaaaaaa:bbbbbbbbb\n"
+ " ccccccccc:dddddddd\n"
+ " ee:fddd];\n"
+ "}");
}
+
+TEST_F(FormatTestObjC, AlwaysBreakBeforeMultilineStrings) {
+ Style = getGoogleStyle(FormatStyle::LK_ObjC);
+ Style.ColumnLimit = 40;
+ verifyFormat("aaaa = @\"bbbb\"\n"
+ " @\"cccc\";");
+ verifyFormat("aaaa(@\"bbbb\"\n"
+ " @\"cccc\");");
+ verifyFormat("aaaa(qqq, @\"bbbb\"\n"
+ " @\"cccc\");");
+ verifyFormat("[aaaa qqqq:@\"bbbb\"\n"
+ " @\"cccc\"];");
+ verifyFormat("aaaa = [aaaa qqqq:@\"bbbb\"\n"
+ " @\"cccc\"];");
+ verifyFormat("[aaaa qqqq:@\"bbbb\"\n"
+ " @\"cccc\"\n"
+ " rr:42\n"
+ " ssssss:@\"ee\"\n"
+ " @\"fffff\"];");
+}
+
} // end namespace
} // end namespace format
} // end namespace clang
diff --git a/unittests/Format/FormatTestProto.cpp b/unittests/Format/FormatTestProto.cpp
index df94d8172730..d25aeb846a97 100644
--- a/unittests/Format/FormatTestProto.cpp
+++ b/unittests/Format/FormatTestProto.cpp
@@ -21,13 +21,13 @@ class FormatTestProto : public ::testing::Test {
protected:
static std::string format(llvm::StringRef Code, unsigned Offset,
unsigned Length, const FormatStyle &Style) {
- DEBUG(llvm::errs() << "---\n");
- DEBUG(llvm::errs() << Code << "\n\n");
+ LLVM_DEBUG(llvm::errs() << "---\n");
+ LLVM_DEBUG(llvm::errs() << Code << "\n\n");
std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));
tooling::Replacements Replaces = reformat(Style, Code, Ranges);
auto Result = applyAllReplacements(Code, Replaces);
EXPECT_TRUE(static_cast<bool>(Result));
- DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
+ LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
return *Result;
}
@@ -38,6 +38,7 @@ protected:
}
static void verifyFormat(llvm::StringRef Code) {
+ EXPECT_EQ(Code.str(), format(Code)) << "Expected code is not stable";
EXPECT_EQ(Code.str(), format(test::messUp(Code)));
}
};
@@ -97,7 +98,7 @@ TEST_F(FormatTestProto, FormatsEnums) {
" TYPE_B = 2;\n"
"};");
verifyFormat("enum Type {\n"
- " UNKNOWN = 0 [(some_options) = {a: aa, b: bb}];\n"
+ " UNKNOWN = 0 [(some_options) = { a: aa, b: bb }];\n"
"};");
verifyFormat("enum Type {\n"
" UNKNOWN = 0 [(some_options) = {\n"
@@ -121,7 +122,7 @@ TEST_F(FormatTestProto, MessageFieldAttributes) {
verifyFormat("optional LongMessageType long_proto_field = 1\n"
" [default = REALLY_REALLY_LONG_CONSTANT_VALUE];");
verifyFormat("repeated double value = 1\n"
- " [(aaaaaaa.aaaaaaaaa) = {aaaaaaaaaaaaaaaaa: AAAAAAAA}];");
+ " [(aaaaaaa.aaaaaaaaa) = { aaaaaaaaaaaaaaaaa: AAAAAAAA }];");
verifyFormat("repeated double value = 1 [(aaaaaaa.aaaaaaaaa) = {\n"
" aaaaaaaaaaaaaaaa: AAAAAAAAAA,\n"
" bbbbbbbbbbbbbbbb: BBBBBBBBBB\n"
@@ -158,9 +159,8 @@ TEST_F(FormatTestProto, MessageFieldAttributes) {
" key: 'a' //\n"
" }\n"
"];");
- verifyFormat("optional string test = 1 [default =\n"
- " \"test\"\n"
- " \"test\"];");
+ verifyFormat("optional string test = 1 [default = \"test\"\n"
+ " \"test\"];");
verifyFormat("optional Aaaaaaaa aaaaaaaa = 12 [\n"
" (aaa) = aaaa,\n"
" (bbbbbbbbbbbbbbbbbbbbbbbbbb) = {\n"
@@ -168,6 +168,16 @@ TEST_F(FormatTestProto, MessageFieldAttributes) {
" aaaaaaaaaaaaaaaa: true\n"
" }\n"
"];");
+ verifyFormat("extensions 20 [(proto2.type) = 'Aaaa.bbbb'];");
+ verifyFormat("extensions 20\n"
+ " [(proto3.type) = 'Aaaa.bbbb', (aaa.Aaa) = 'aaa.bbb'];");
+ verifyFormat("extensions 123 [\n"
+ " (aaa) = aaaa,\n"
+ " (bbbbbbbbbbbbbbbbbbbbbbbbbb) = {\n"
+ " aaaaaaaaaaaaaaaaa: true,\n"
+ " aaaaaaaaaaaaaaaa: true\n"
+ " }\n"
+ "];");
}
TEST_F(FormatTestProto, DoesntWrapFileOptions) {
@@ -183,27 +193,27 @@ TEST_F(FormatTestProto, FormatsOptions) {
" field_a: OK\n"
" field_b: \"OK\"\n"
" field_c: \"OK\"\n"
- " msg_field: {field_d: 123}\n"
+ " msg_field: { field_d: 123 }\n"
"};");
verifyFormat("option (MyProto.options) = {\n"
" field_a: OK\n"
" field_b: \"OK\"\n"
" field_c: \"OK\"\n"
- " msg_field: {field_d: 123 field_e: OK}\n"
+ " msg_field: { field_d: 123 field_e: OK }\n"
"};");
verifyFormat("option (MyProto.options) = {\n"
" field_a: OK // Comment\n"
" field_b: \"OK\"\n"
" field_c: \"OK\"\n"
- " msg_field: {field_d: 123}\n"
+ " msg_field: { field_d: 123 }\n"
"};");
verifyFormat("option (MyProto.options) = {\n"
" field_c: \"OK\"\n"
- " msg_field {field_d: 123}\n"
+ " msg_field { field_d: 123 }\n"
"};");
verifyFormat("option (MyProto.options) = {\n"
" field_a: OK\n"
- " field_b {field_c: OK}\n"
+ " field_b { field_c: OK }\n"
" field_d: OKOKOK\n"
" field_e: OK\n"
"}");
@@ -211,12 +221,14 @@ TEST_F(FormatTestProto, FormatsOptions) {
// Support syntax with <> instead of {}.
verifyFormat("option (MyProto.options) = {\n"
" field_c: \"OK\",\n"
- " msg_field: <field_d: 123>\n"
+ " msg_field: < field_d: 123 >\n"
+ " empty: <>\n"
+ " empty <>\n"
"};");
verifyFormat("option (MyProto.options) = {\n"
" field_a: OK\n"
- " field_b <field_c: OK>\n"
+ " field_b < field_c: OK >\n"
" field_d: OKOKOK\n"
" field_e: OK\n"
"}");
@@ -224,9 +236,9 @@ TEST_F(FormatTestProto, FormatsOptions) {
verifyFormat("option (MyProto.options) = {\n"
" msg_field: <>\n"
" field_c: \"OK\",\n"
- " msg_field: <field_d: 123>\n"
+ " msg_field: < field_d: 123 >\n"
" field_e: OK\n"
- " msg_field: <field_d: 12>\n"
+ " msg_field: < field_d: 12 >\n"
"};");
verifyFormat("option (MyProto.options) = <\n"
@@ -247,7 +259,7 @@ TEST_F(FormatTestProto, FormatsOptions) {
verifyFormat("option (MyProto.options) = <\n"
" field_a: \"OK\"\n"
- " msg_field: {field_b: OK}\n"
+ " msg_field: { field_b: OK }\n"
" field_g: OK\n"
" field_g: OK\n"
" field_g: OK\n"
@@ -350,7 +362,7 @@ TEST_F(FormatTestProto, FormatsOptions) {
" field_D: 4\n"
" field_E: 5\n"
" >\n"
- " msg_field <field_A: 1 field_B: 2 field_C: 3 field_D: 4>\n"
+ " msg_field < field_A: 1 field_B: 2 field_C: 3 f_D: 4 >\n"
" field_e: OK\n"
" field_f: OK\n"
" }\n"
@@ -358,21 +370,21 @@ TEST_F(FormatTestProto, FormatsOptions) {
">;");
verifyFormat("option (MyProto.options) = <\n"
- " data1 <key1: value1>\n"
- " data2 {key2: value2}\n"
+ " data1 < key1: value1 >\n"
+ " data2 { key2: value2 }\n"
">;");
verifyFormat("option (MyProto.options) = <\n"
" app_id: 'com.javax.swing.salsa.latino'\n"
" head_id: 1\n"
- " data <key: value>\n"
+ " data < key: value >\n"
">;");
verifyFormat("option (MyProto.options) = {\n"
" app_id: 'com.javax.swing.salsa.latino'\n"
" head_id: 1\n"
" headheadheadheadheadhead_id: 1\n"
- " product_data {product {1}}\n"
+ " product_data { product { 1 } }\n"
"};");
}
@@ -410,5 +422,236 @@ TEST_F(FormatTestProto, FormatsImports) {
"}");
}
+TEST_F(FormatTestProto, KeepsLongStringLiteralsOnSameLine) {
+ verifyFormat(
+ "option (MyProto.options) = {\n"
+ " foo: {\n"
+ " text: \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaasaaaaaaaa\"\n"
+ " }\n"
+ "}");
+}
+
+TEST_F(FormatTestProto, FormatsOptionsExtensions) {
+ verifyFormat("option (MyProto.options) = {\n"
+ " msg_field: { field_d: 123 }\n"
+ " [ext.t/u] { key: value }\n"
+ " key: value\n"
+ " [t.u/v] <\n"
+ " [ext] { key: value }\n"
+ " >\n"
+ "};");
+}
+
+TEST_F(FormatTestProto, SpacesAroundPercents) {
+ verifyFormat("option (MyProto.options) = {\n"
+ " key: %lld\n"
+ " key: 0x%04x\n"
+ " key: \"%d %d\"\n"
+ "};");
+}
+
+TEST_F(FormatTestProto, FormatsRepeatedListInitializersInOptions) {
+ verifyFormat("option (MyProto.options) = {\n"
+ " key: item\n"
+ " keys: [\n"
+ " 'ala',\n"
+ " 'bala',\n"
+ " 'porto',\n"
+ " 'kala',\n"
+ " 'too',\n"
+ " 'long',\n"
+ " 'long',\n"
+ " 'long'\n"
+ " ]\n"
+ " key: [ item ]\n"
+ " msg {\n"
+ " key: item\n"
+ " keys: [\n"
+ " 'ala',\n"
+ " 'bala',\n"
+ " 'porto',\n"
+ " 'kala',\n"
+ " 'too',\n"
+ " 'long',\n"
+ " 'long'\n"
+ " ]\n"
+ " }\n"
+ " key: value\n"
+ "};");
+}
+
+TEST_F(FormatTestProto, AcceptsOperatorAsKeyInOptions) {
+ verifyFormat("option (MyProto.options) = {\n"
+ " bbbbbbbbb: <\n"
+ " ccccccccccccccccccccccc: <\n"
+ " operator: 1\n"
+ " operator: 2\n"
+ " operator: 3\n"
+ " operator { key: value }\n"
+ " >\n"
+ " >\n"
+ "};");
+}
+
+TEST_F(FormatTestProto, BreaksEntriesOfSubmessagesContainingSubmessages) {
+ FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto);
+ Style.ColumnLimit = 60;
+ // The column limit allows for the keys submessage to be put on 1 line, but we
+ // break it since it contains a submessage an another entry.
+ verifyFormat("option (MyProto.options) = {\n"
+ " key: valueeeeeeee\n"
+ " keys: {\n"
+ " item: 'aaaaaaaaaaaaaaaa'\n"
+ " sub <>\n"
+ " }\n"
+ "}");
+ verifyFormat("option (MyProto.options) = {\n"
+ " key: valueeeeeeee\n"
+ " keys: {\n"
+ " item: 'aaaaaaaaaaaaaaaa'\n"
+ " sub {}\n"
+ " }\n"
+ "}");
+ verifyFormat("option (MyProto.options) = {\n"
+ " key: valueeeeeeee\n"
+ " keys: {\n"
+ " sub {}\n"
+ " sub: <>\n"
+ " sub: []\n"
+ " }\n"
+ "}");
+ verifyFormat("option (MyProto.options) = {\n"
+ " key: valueeeeeeee\n"
+ " keys: {\n"
+ " item: 'aaaaaaaaaaa'\n"
+ " sub { msg: 1 }\n"
+ " }\n"
+ "}");
+ verifyFormat("option (MyProto.options) = {\n"
+ " key: valueeeeeeee\n"
+ " keys: {\n"
+ " item: 'aaaaaaaaaaa'\n"
+ " sub: { msg: 1 }\n"
+ " }\n"
+ "}");
+ verifyFormat("option (MyProto.options) = {\n"
+ " key: valueeeeeeee\n"
+ " keys: {\n"
+ " item: 'aaaaaaaaaaa'\n"
+ " sub < msg: 1 >\n"
+ " }\n"
+ "}");
+ verifyFormat("option (MyProto.options) = {\n"
+ " key: valueeeeeeee\n"
+ " keys: {\n"
+ " item: 'aaaaaaaaaaa'\n"
+ " sub: [ msg: 1 ]\n"
+ " }\n"
+ "}");
+ verifyFormat("option (MyProto.options) = {\n"
+ " key: valueeeeeeee\n"
+ " keys: <\n"
+ " item: 'aaaaaaaaaaa'\n"
+ " sub: [ 1, 2 ]\n"
+ " >\n"
+ "}");
+ verifyFormat("option (MyProto.options) = {\n"
+ " key: valueeeeeeee\n"
+ " keys: {\n"
+ " sub {}\n"
+ " item: 'aaaaaaaaaaaaaaaa'\n"
+ " }\n"
+ "}");
+ verifyFormat("option (MyProto.options) = {\n"
+ " key: valueeeeeeee\n"
+ " keys: {\n"
+ " sub: []\n"
+ " item: 'aaaaaaaaaaaaaaaa'\n"
+ " }\n"
+ "}");
+ verifyFormat("option (MyProto.options) = {\n"
+ " key: valueeeeeeee\n"
+ " keys: {\n"
+ " sub <>\n"
+ " item: 'aaaaaaaaaaaaaaaa'\n"
+ " }\n"
+ "}");
+ verifyFormat("option (MyProto.options) = {\n"
+ " key: valueeeeeeee\n"
+ " keys: {\n"
+ " sub { key: value }\n"
+ " item: 'aaaaaaaaaaaaaaaa'\n"
+ " }\n"
+ "}");
+ verifyFormat("option (MyProto.options) = {\n"
+ " key: valueeeeeeee\n"
+ " keys: {\n"
+ " sub: [ 1, 2 ]\n"
+ " item: 'aaaaaaaaaaaaaaaa'\n"
+ " }\n"
+ "}");
+ verifyFormat("option (MyProto.options) = {\n"
+ " key: valueeeeeeee\n"
+ " keys: {\n"
+ " sub < sub_2: {} >\n"
+ " item: 'aaaaaaaaaaaaaaaa'\n"
+ " }\n"
+ "}");
+ verifyFormat("option (MyProto.options) = {\n"
+ " key: valueeeeeeee\n"
+ " keys: {\n"
+ " item: data\n"
+ " sub: [ 1, 2 ]\n"
+ " item: 'aaaaaaaaaaaaaaaa'\n"
+ " }\n"
+ "}");
+ verifyFormat("option (MyProto.options) = {\n"
+ " key: valueeeeeeee\n"
+ " keys: {\n"
+ " item: data\n"
+ " sub < sub_2: {} >\n"
+ " item: 'aaaaaaaaaaaaaaaa'\n"
+ " }\n"
+ "}");
+ verifyFormat("option (MyProto.options) = {\n"
+ " sub: {\n"
+ " key: valueeeeeeee\n"
+ " keys: {\n"
+ " sub: [ 1, 2 ]\n"
+ " item: 'aaaaaaaaaaaaaaaa'\n"
+ " }\n"
+ " }\n"
+ "}");
+}
+
+TEST_F(FormatTestProto, PreventBreaksBetweenKeyAndSubmessages) {
+ verifyFormat("option (MyProto.options) = {\n"
+ " submessage: {\n"
+ " key: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'\n"
+ " }\n"
+ "}");
+ verifyFormat("option (MyProto.options) = {\n"
+ " submessage {\n"
+ " key: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'\n"
+ " }\n"
+ "}");
+ verifyFormat("option (MyProto.options) = {\n"
+ " submessage: <\n"
+ " key: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'\n"
+ " >\n"
+ "}");
+ verifyFormat("option (MyProto.options) = {\n"
+ " submessage <\n"
+ " key: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'\n"
+ " >\n"
+ "}");
+ verifyFormat("option (MyProto.options) = {\n"
+ " repeatedd: [\n"
+ " 'eyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'\n"
+ " ]\n"
+ "}");
+}
+
+
} // end namespace tooling
} // end namespace clang
diff --git a/unittests/Format/FormatTestRawStrings.cpp b/unittests/Format/FormatTestRawStrings.cpp
index 6e7b7065875d..307394341d74 100644
--- a/unittests/Format/FormatTestRawStrings.cpp
+++ b/unittests/Format/FormatTestRawStrings.cpp
@@ -33,8 +33,8 @@ protected:
std::string format(llvm::StringRef Code,
const FormatStyle &Style = getLLVMStyle(),
StatusCheck CheckComplete = SC_ExpectComplete) {
- DEBUG(llvm::errs() << "---\n");
- DEBUG(llvm::errs() << Code << "\n\n");
+ LLVM_DEBUG(llvm::errs() << "---\n");
+ LLVM_DEBUG(llvm::errs() << Code << "\n\n");
std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
FormattingAttemptStatus Status;
tooling::Replacements Replaces =
@@ -47,7 +47,7 @@ protected:
ReplacementCount = Replaces.size();
auto Result = applyAllReplacements(Code, Replaces);
EXPECT_TRUE(static_cast<bool>(Result));
- DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
+ LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
return *Result;
}
@@ -65,23 +65,43 @@ protected:
FormatStyle getRawStringPbStyleWithColumns(unsigned ColumnLimit) {
FormatStyle Style = getLLVMStyle();
Style.ColumnLimit = ColumnLimit;
- Style.RawStringFormats = {{/*Delimiter=*/"pb",
- /*Kind=*/FormatStyle::LK_TextProto,
- /*BasedOnStyle=*/"google"}};
+ Style.RawStringFormats = {
+ {
+ /*Language=*/FormatStyle::LK_TextProto,
+ /*Delimiters=*/{"pb"},
+ /*EnclosingFunctions=*/{},
+ /*CanonicalDelimiter=*/"",
+ /*BasedOnStyle=*/"google",
+ },
+ };
return Style;
}
FormatStyle getRawStringLLVMCppStyleBasedOn(std::string BasedOnStyle) {
FormatStyle Style = getLLVMStyle();
- Style.RawStringFormats = {{/*Delimiter=*/"cpp",
- /*Kind=*/FormatStyle::LK_Cpp, BasedOnStyle}};
+ Style.RawStringFormats = {
+ {
+ /*Language=*/FormatStyle::LK_Cpp,
+ /*Delimiters=*/{"cpp"},
+ /*EnclosingFunctions=*/{},
+ /*CanonicalDelimiter=*/"",
+ BasedOnStyle,
+ },
+ };
return Style;
}
FormatStyle getRawStringGoogleCppStyleBasedOn(std::string BasedOnStyle) {
FormatStyle Style = getGoogleStyle(FormatStyle::LK_Cpp);
- Style.RawStringFormats = {{/*Delimiter=*/"cpp",
- /*Kind=*/FormatStyle::LK_Cpp, BasedOnStyle}};
+ Style.RawStringFormats = {
+ {
+ /*Language=*/FormatStyle::LK_Cpp,
+ /*Delimiters=*/{"cpp"},
+ /*EnclosingFunctions=*/{},
+ /*CanonicalDelimiter=*/"",
+ BasedOnStyle,
+ },
+ };
return Style;
}
@@ -112,6 +132,27 @@ TEST_F(FormatTestRawStrings, ReformatsAccordingToBaseStyle) {
getRawStringGoogleCppStyleBasedOn("llvm")));
}
+TEST_F(FormatTestRawStrings, UsesConfigurationOverBaseStyle) {
+ // llvm style puts '*' on the right.
+ // google style puts '*' on the left.
+
+ // Uses the configured google style inside raw strings even if BasedOnStyle in
+ // the raw string format is llvm.
+ FormatStyle Style = getGoogleStyle(FormatStyle::LK_Cpp);
+ EXPECT_EQ(0, parseConfiguration("---\n"
+ "Language: Cpp\n"
+ "BasedOnStyle: Google", &Style).value());
+ Style.RawStringFormats = {{
+ FormatStyle::LK_Cpp,
+ {"cpp"},
+ {},
+ /*CanonicalDelimiter=*/"",
+ /*BasedOnStyle=*/"llvm",
+ }};
+ expect_eq(R"test(int* i = R"cpp(int* j = 0;)cpp";)test",
+ format(R"test(int * i = R"cpp(int * j = 0;)cpp";)test", Style));
+}
+
TEST_F(FormatTestRawStrings, MatchesDelimitersCaseSensitively) {
// Don't touch the 'PB' raw string, format the 'pb' raw string.
expect_eq(R"test(
@@ -121,29 +162,20 @@ t = R"pb(item: 1)pb";)test",
s = R"PB(item:1)PB";
t = R"pb(item:1)pb";)test",
getRawStringPbStyleWithColumns(40)));
+}
- FormatStyle MixedStyle = getLLVMStyle();
- MixedStyle.RawStringFormats = {
- {/*Delimiter=*/"cpp", /*Kind=*/FormatStyle::LK_Cpp,
- /*BasedOnStyle=*/"llvm"},
- {/*Delimiter=*/"CPP", /*Kind=*/FormatStyle::LK_Cpp,
- /*BasedOnStyle=*/"google"}};
-
- // Format the 'cpp' raw string with '*' on the right.
- // Format the 'CPP' raw string with '*' on the left.
- // Do not format the 'Cpp' raw string.
- // Do not format non-raw strings.
- expect_eq(R"test(
-a = R"cpp(int *i = 0;)cpp";
-b = R"CPP(int* j = 0;)CPP";
-c = R"Cpp(int * k = 0;)Cpp";
-d = R"cpp(int * k = 0;)Cpp";)test",
- format(R"test(
-a = R"cpp(int * i = 0;)cpp";
-b = R"CPP(int * j = 0;)CPP";
-c = R"Cpp(int * k = 0;)Cpp";
-d = R"cpp(int * k = 0;)Cpp";)test",
- MixedStyle));
+TEST_F(FormatTestRawStrings, RespectsClangFormatOff) {
+ expect_eq(R"test(
+// clang-format off
+s = R"pb(item: 1)pb";
+// clang-format on
+t = R"pb(item: 1)pb";)test",
+ format(R"test(
+// clang-format off
+s = R"pb(item: 1)pb";
+// clang-format on
+t = R"pb(item: 1)pb";)test",
+ getRawStringPbStyleWithColumns(40)));
}
TEST_F(FormatTestRawStrings, ReformatsShortRawStringsOnSingleLine) {
@@ -167,12 +199,6 @@ TEST_F(FormatTestRawStrings, ReformatsShortRawStringsOnSingleLine) {
format(
R"test(P p = TP(R"pb(item_1:1 item_2:2)pb");)test",
getRawStringPbStyleWithColumns(40)));
- expect_eq(
- R"test(P p = TP(R"pb(item_1 <1> item_2: {2})pb");)test",
- format(
- R"test(P p = TP(R"pb(item_1<1> item_2:{2})pb");)test",
- getRawStringPbStyleWithColumns(40)));
-
// Merge two short lines into one.
expect_eq(R"test(
std::string s = R"pb(
@@ -188,6 +214,18 @@ std::string s = R"pb(
getRawStringPbStyleWithColumns(40)));
}
+TEST_F(FormatTestRawStrings, BreaksShortRawStringsWhenNeeded) {
+ // The raw string contains multiple submessage entries, so break for
+ // readability.
+ expect_eq(R"test(
+P p = TP(R"pb(item_1 < 1 >
+ item_2: { 2 })pb");)test",
+ format(
+ R"test(
+P p = TP(R"pb(item_1<1> item_2:{2})pb");)test",
+ getRawStringPbStyleWithColumns(40)));
+}
+
TEST_F(FormatTestRawStrings, BreaksRawStringsExceedingColumnLimit) {
expect_eq(R"test(
P p = TPPPPPPPPPPPPPPP(
@@ -207,8 +245,8 @@ P p = TPPPPPPPPPPPPPPP(R"pb(item_1: 1, item_2: 2, item_3: 3)pb");)test",
getRawStringPbStyleWithColumns(40)));
expect_eq(R"test(
-P p = TP(R"pb(item_1 <1>
- item_2: <2>
+P p = TP(R"pb(item_1 < 1 >
+ item_2: < 2 >
item_3 {})pb");)test",
format(R"test(
P p = TP(R"pb(item_1<1> item_2:<2> item_3{ })pb");)test",
@@ -227,10 +265,10 @@ P p = TP(R"pb(item_1: 1, item_2: 2, item_3: 3, item_4: 4)pb");)test",
expect_eq(R"test(
P p = TPPPPPPPPPPPPPPP(
- R"pb(item_1 <1>,
- item_2: {2},
- item_3: <3>,
- item_4: {4})pb");)test",
+ R"pb(item_1 < 1 >,
+ item_2: { 2 },
+ item_3: < 3 >,
+ item_4: { 4 })pb");)test",
format(R"test(
P p = TPPPPPPPPPPPPPPP(R"pb(item_1<1>, item_2: {2}, item_3: <3>, item_4:{4})pb");)test",
getRawStringPbStyleWithColumns(40)));
@@ -277,7 +315,7 @@ int f(string s) {
TEST_F(FormatTestRawStrings, FormatsRawStringArguments) {
expect_eq(R"test(
-P p = TP(R"pb(key {1})pb", param_2);)test",
+P p = TP(R"pb(key { 1 })pb", param_2);)test",
format(R"test(
P p = TP(R"pb(key{1})pb",param_2);)test",
getRawStringPbStyleWithColumns(40)));
@@ -290,9 +328,9 @@ PPPPPPPPPPPPP(R"pb(keykeyk)pb", param_2);)test",
getRawStringPbStyleWithColumns(40)));
expect_eq(R"test(
-P p =
- TP(R"pb(item: {i: 1, s: 's'}
- item: {i: 2, s: 't'})pb");)test",
+P p = TP(
+ R"pb(item: { i: 1, s: 's' }
+ item: { i: 2, s: 't' })pb");)test",
format(R"test(
P p = TP(R"pb(item: {i: 1, s: 's'} item: {i: 2, s: 't'})pb");)test",
getRawStringPbStyleWithColumns(40)));
@@ -663,15 +701,14 @@ int s() {
})test",
getRawStringPbStyleWithColumns(20)));
- // Align the suffix with the surrounding FirstIndent if the prefix is not on
+ // Align the suffix with the surrounding indent if the prefix is not on
// a line of its own.
expect_eq(R"test(
int s() {
- auto S = PTP(
- R"pb(
- item_1: 1,
- item_2: 2
- )pb");
+ auto S = PTP(R"pb(
+ item_1: 1,
+ item_2: 2
+ )pb");
})test",
format(R"test(
int s() {
@@ -728,6 +765,130 @@ TEST_F(FormatTestRawStrings, DontFormatNonRawStrings) {
getRawStringPbStyleWithColumns(20)));
}
+TEST_F(FormatTestRawStrings, FormatsRawStringsWithEnclosingFunctionName) {
+ FormatStyle Style = getRawStringPbStyleWithColumns(40);
+ Style.RawStringFormats[0].EnclosingFunctions.push_back(
+ "PARSE_TEXT_PROTO");
+ Style.RawStringFormats[0].EnclosingFunctions.push_back("ParseTextProto");
+ expect_eq(R"test(a = PARSE_TEXT_PROTO(R"(key: value)");)test",
+ format(R"test(a = PARSE_TEXT_PROTO(R"(key:value)");)test", Style));
+
+ expect_eq(R"test(
+a = PARSE_TEXT_PROTO /**/ (
+ /**/ R"(key: value)");)test",
+ format(R"test(
+a = PARSE_TEXT_PROTO/**/(/**/R"(key:value)");)test",
+ Style));
+
+ expect_eq(R"test(
+a = ParseTextProto<ProtoType>(
+ R"(key: value)");)test",
+ format(R"test(
+a = ParseTextProto<ProtoType>(R"(key:value)");)test",
+ Style));
+}
+
+TEST_F(FormatTestRawStrings, UpdatesToCanonicalDelimiters) {
+ FormatStyle Style = getRawStringPbStyleWithColumns(25);
+ Style.RawStringFormats[0].CanonicalDelimiter = "proto";
+ expect_eq(R"test(a = R"proto(key: value)proto";)test",
+ format(R"test(a = R"pb(key:value)pb";)test", Style));
+
+ // Don't update to canonical delimiter if it occurs as a raw string suffix in
+ // the raw string content.
+ expect_eq(R"test(a = R"pb(key: ")proto")pb";)test",
+ format(R"test(a = R"pb(key:")proto")pb";)test", Style));
+}
+
+TEST_F(FormatTestRawStrings, PenalizesPrefixExcessChars) {
+ FormatStyle Style = getRawStringPbStyleWithColumns(60);
+
+ // The '(' in R"pb is at column 60, no break.
+ expect_eq(R"test(
+xxxxxxxaaaaax wwwwwww = _Verxrrrrrrrr(PARSE_TEXT_PROTO(R"pb(
+ Category: aaaaaaaaaaaaaaaaaaaaaaaaaa
+)pb"));
+)test",
+ format(R"test(
+xxxxxxxaaaaax wwwwwww = _Verxrrrrrrrr(PARSE_TEXT_PROTO(R"pb(
+ Category: aaaaaaaaaaaaaaaaaaaaaaaaaa
+)pb"));
+)test", Style));
+ // The '(' in R"pb is at column 61, break.
+ expect_eq(R"test(
+xxxxxxxaaaaax wwwwwww =
+ _Verxrrrrrrrrr(PARSE_TEXT_PROTO(R"pb(
+ Category: aaaaaaaaaaaaaaaaaaaaaaaaaa
+ )pb"));
+)test",
+ format(R"test(
+xxxxxxxaaaaax wwwwwww = _Verxrrrrrrrrr(PARSE_TEXT_PROTO(R"pb(
+ Category: aaaaaaaaaaaaaaaaaaaaaaaaaa
+)pb"));
+)test", Style));
+}
+
+TEST_F(FormatTestRawStrings, KeepsRBraceFolloedByMoreLBracesOnSameLine) {
+ FormatStyle Style = getRawStringPbStyleWithColumns(80);
+
+ expect_eq(
+ R"test(
+int f() {
+ if (1) {
+ TTTTTTTTTTTTTTTTTTTTT s = PARSE_TEXT_PROTO(R"pb(
+ ttttttttt {
+ ppppppppppppp {
+ [cccccccccc.pppppppppppppp.TTTTTTTTTTTTTTTTTTTT] { field_1: "123_1" }
+ [cccccccccc.pppppppppppppp.TTTTTTTTTTTTTTTTTTTT] { field_2: "123_2" }
+ }
+ }
+ )pb");
+ }
+}
+)test",
+ format(
+ R"test(
+int f() {
+ if (1) {
+ TTTTTTTTTTTTTTTTTTTTT s = PARSE_TEXT_PROTO(R"pb(
+ ttttttttt {
+ ppppppppppppp {
+ [cccccccccc.pppppppppppppp.TTTTTTTTTTTTTTTTTTTT] { field_1: "123_1" }
+ [cccccccccc.pppppppppppppp.TTTTTTTTTTTTTTTTTTTT] { field_2: "123_2" }}}
+ )pb");
+ }
+}
+)test",
+ Style));
+}
+
+TEST_F(FormatTestRawStrings,
+ DoNotFormatUnrecognizedDelimitersInRecognizedFunctions) {
+ FormatStyle Style = getRawStringPbStyleWithColumns(60);
+ Style.RawStringFormats[0].EnclosingFunctions.push_back(
+ "EqualsProto");
+ // EqualsProto is a recognized function, but the Raw delimiter is
+ // unrecognized. Do not touch the string in this case, since it might be
+ // special.
+ expect_eq(R"test(
+void f() {
+ aaaaaaaaa(bbbbbbbbb, EqualsProto(R"Raw(
+item {
+ key: value
+}
+)Raw"));
+})test",
+ format(R"test(
+void f() {
+ aaaaaaaaa(bbbbbbbbb, EqualsProto(R"Raw(
+item {
+ key: value
+}
+)Raw"));
+})test",
+ Style));
+}
+
} // end namespace
} // end namespace format
} // end namespace clang
diff --git a/unittests/Format/FormatTestSelective.cpp b/unittests/Format/FormatTestSelective.cpp
index 182218fe96db..36d9089c6056 100644
--- a/unittests/Format/FormatTestSelective.cpp
+++ b/unittests/Format/FormatTestSelective.cpp
@@ -21,8 +21,8 @@ namespace {
class FormatTestSelective : public ::testing::Test {
protected:
std::string format(llvm::StringRef Code, unsigned Offset, unsigned Length) {
- DEBUG(llvm::errs() << "---\n");
- DEBUG(llvm::errs() << Code << "\n\n");
+ LLVM_DEBUG(llvm::errs() << "---\n");
+ LLVM_DEBUG(llvm::errs() << Code << "\n\n");
std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));
FormattingAttemptStatus Status;
tooling::Replacements Replaces =
@@ -30,7 +30,7 @@ protected:
EXPECT_TRUE(Status.FormatComplete) << Code << "\n\n";
auto Result = applyAllReplacements(Code, Replaces);
EXPECT_TRUE(static_cast<bool>(Result));
- DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
+ LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
return *Result;
}
@@ -177,6 +177,72 @@ TEST_F(FormatTestSelective, FormatsCommentsLocally) {
0, 0));
}
+TEST_F(FormatTestSelective, ContinueReindenting) {
+ // When we change an indent, we continue formatting as long as following
+ // lines are not indented correctly.
+ EXPECT_EQ("int i;\n"
+ "int b;\n"
+ "int c;\n"
+ "int d;\n"
+ "int e;\n"
+ " int f;\n",
+ format("int i;\n"
+ " int b;\n"
+ " int c;\n"
+ " int d;\n"
+ "int e;\n"
+ " int f;\n",
+ 11, 0));
+}
+
+TEST_F(FormatTestSelective, ReindentClosingBrace) {
+ EXPECT_EQ("int i;\n"
+ "int f() {\n"
+ " int a;\n"
+ " int b;\n"
+ "}\n"
+ " int c;\n",
+ format("int i;\n"
+ " int f(){\n"
+ "int a;\n"
+ "int b;\n"
+ " }\n"
+ " int c;\n",
+ 11, 0));
+ EXPECT_EQ("void f() {\n"
+ " if (foo) {\n"
+ " b();\n"
+ " } else {\n"
+ " c();\n"
+ " }\n"
+ "int d;\n"
+ "}\n",
+ format("void f() {\n"
+ " if (foo) {\n"
+ "b();\n"
+ "}else{\n"
+ "c();\n"
+ "}\n"
+ "int d;\n"
+ "}\n",
+ 13, 0));
+ EXPECT_EQ("int i = []() {\n"
+ " class C {\n"
+ " int a;\n"
+ " int b;\n"
+ " };\n"
+ " int c;\n"
+ "};\n",
+ format("int i = []() {\n"
+ " class C{\n"
+ "int a;\n"
+ "int b;\n"
+ "};\n"
+ "int c;\n"
+ " };\n",
+ 17, 0));
+}
+
TEST_F(FormatTestSelective, IndividualStatementsOfNestedBlocks) {
EXPECT_EQ("DEBUG({\n"
" int i;\n"
@@ -503,7 +569,7 @@ TEST_F(FormatTestSelective, StopFormattingWhenLeavingScope) {
" if (a) {\n"
" g();\n"
" h();\n"
- "}\n"
+ " }\n"
"\n"
"void g() {\n"
"}",
diff --git a/unittests/Format/FormatTestTextProto.cpp b/unittests/Format/FormatTestTextProto.cpp
index 0a7bcdd82362..0875bd8925d1 100644
--- a/unittests/Format/FormatTestTextProto.cpp
+++ b/unittests/Format/FormatTestTextProto.cpp
@@ -21,24 +21,29 @@ class FormatTestTextProto : public ::testing::Test {
protected:
static std::string format(llvm::StringRef Code, unsigned Offset,
unsigned Length, const FormatStyle &Style) {
- DEBUG(llvm::errs() << "---\n");
- DEBUG(llvm::errs() << Code << "\n\n");
+ LLVM_DEBUG(llvm::errs() << "---\n");
+ LLVM_DEBUG(llvm::errs() << Code << "\n\n");
std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));
tooling::Replacements Replaces = reformat(Style, Code, Ranges);
auto Result = applyAllReplacements(Code, Replaces);
EXPECT_TRUE(static_cast<bool>(Result));
- DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
+ LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
return *Result;
}
- static std::string format(llvm::StringRef Code) {
- FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto);
- Style.ColumnLimit = 60; // To make writing tests easier.
+ static std::string format(llvm::StringRef Code, const FormatStyle &Style) {
return format(Code, 0, Code.size(), Style);
}
+ static void verifyFormat(llvm::StringRef Code, const FormatStyle &Style) {
+ EXPECT_EQ(Code.str(), format(Code, Style)) << "Expected code is not stable";
+ EXPECT_EQ(Code.str(), format(test::messUp(Code), Style));
+ }
+
static void verifyFormat(llvm::StringRef Code) {
- EXPECT_EQ(Code.str(), format(test::messUp(Code)));
+ FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto);
+ Style.ColumnLimit = 60; // To make writing tests easier.
+ verifyFormat(Code, Style);
}
};
@@ -49,9 +54,9 @@ TEST_F(FormatTestTextProto, KeepsTopLevelEntriesFittingALine) {
TEST_F(FormatTestTextProto, SupportsMessageFields) {
verifyFormat("msg_field: {}");
- verifyFormat("msg_field: {field_a: A}");
+ verifyFormat("msg_field: { field_a: A }");
- verifyFormat("msg_field: {field_a: \"OK\" field_b: 123}");
+ verifyFormat("msg_field: { field_a: \"OK\" field_b: 123 }");
verifyFormat("msg_field: {\n"
" field_a: 1\n"
@@ -63,9 +68,9 @@ TEST_F(FormatTestTextProto, SupportsMessageFields) {
verifyFormat("msg_field {}");
- verifyFormat("msg_field {field_a: A}");
+ verifyFormat("msg_field { field_a: A }");
- verifyFormat("msg_field {field_a: \"OK\" field_b: 123}");
+ verifyFormat("msg_field { field_a: \"OK\" field_b: 123 }");
verifyFormat("msg_field {\n"
" field_a: 1\n"
@@ -78,11 +83,11 @@ TEST_F(FormatTestTextProto, SupportsMessageFields) {
" field_h: 1234.567e-89\n"
"}");
- verifyFormat("msg_field: {msg_field {field_a: 1}}");
+ verifyFormat("msg_field: { msg_field { field_a: 1 } }");
verifyFormat("id: \"ala.bala\"\n"
- "item {type: ITEM_A rank: 1 score: 90.0}\n"
- "item {type: ITEM_B rank: 2 score: 70.5}\n"
+ "item { type: ITEM_A rank: 1 score: 90.0 }\n"
+ "item { type: ITEM_B rank: 2 score: 70.5 }\n"
"item {\n"
" type: ITEM_A\n"
" rank: 3\n"
@@ -102,24 +107,24 @@ TEST_F(FormatTestTextProto, AvoidsTopLevelBinPacking) {
verifyFormat("field_a: OK\n"
"field_b: \"OK\"\n"
"field_c: \"OK\"\n"
- "msg_field: {field_d: 123}\n"
+ "msg_field: { field_d: 123 }\n"
"field_e: OK\n"
"field_f: OK");
verifyFormat("field_a: OK\n"
"field_b: \"OK\"\n"
"field_c: \"OK\"\n"
- "msg_field: {field_d: 123 field_e: OK}");
+ "msg_field: { field_d: 123 field_e: OK }");
verifyFormat("a: {\n"
" field_a: OK\n"
- " field_b {field_c: OK}\n"
+ " field_b { field_c: OK }\n"
" field_d: OKOKOK\n"
" field_e: OK\n"
"}");
verifyFormat("field_a: OK,\n"
- "field_b {field_c: OK},\n"
+ "field_b { field_c: OK },\n"
"field_d: OKOKOK,\n"
"field_e: OK");
}
@@ -139,29 +144,77 @@ TEST_F(FormatTestTextProto, AddsNewlinesAfterTrailingComments) {
"}");
}
+TEST_F(FormatTestTextProto, ImplicitStringLiteralConcatenation) {
+ verifyFormat("field_a: 'aaaaa'\n"
+ " 'bbbbb'");
+ verifyFormat("field_a: \"aaaaa\"\n"
+ " \"bbbbb\"");
+ FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto);
+ Style.AlwaysBreakBeforeMultilineStrings = true;
+ verifyFormat("field_a:\n"
+ " 'aaaaa'\n"
+ " 'bbbbb'",
+ Style);
+ verifyFormat("field_a:\n"
+ " \"aaaaa\"\n"
+ " \"bbbbb\"",
+ Style);
+}
+
TEST_F(FormatTestTextProto, SupportsAngleBracketMessageFields) {
// Single-line tests
verifyFormat("msg_field <>");
verifyFormat("msg_field: <>");
- verifyFormat("msg_field <field_a: OK>");
- verifyFormat("msg_field: <field_a: 123>");
- verifyFormat("msg_field <field_a <>>");
- verifyFormat("msg_field <field_a <field_b <>>>");
- verifyFormat("msg_field: <field_a <field_b: <>>>");
- verifyFormat("msg_field <field_a: OK, field_b: \"OK\">");
- verifyFormat("msg_field <field_a: OK field_b: <>, field_c: OK>");
- verifyFormat("msg_field <field_a {field_b: 1}, field_c: <field_d: 2>>");
- verifyFormat("msg_field: <field_a: OK, field_b: \"OK\">");
- verifyFormat("msg_field: <field_a: OK field_b: <>, field_c: OK>");
- verifyFormat("msg_field: <field_a {field_b: 1}, field_c: <field_d: 2>>");
- verifyFormat("field_a: \"OK\", msg_field: <field_b: 123>, field_c: {}");
- verifyFormat("field_a <field_b: 1>, msg_field: <field_b: 123>, field_c <>");
- verifyFormat("field_a <field_b: 1> msg_field: <field_b: 123> field_c <>");
- verifyFormat("field <field <field: <>>, field <>> field: <field: 1>");
-
+ verifyFormat("msg_field < field_a: OK >");
+ verifyFormat("msg_field: < field_a: 123 >");
+ verifyFormat("msg_field < field_a <> >");
+ verifyFormat("msg_field < field_a < field_b <> > >");
+ verifyFormat("msg_field: < field_a < field_b: <> > >");
+ verifyFormat("msg_field < field_a: OK, field_b: \"OK\" >");
+ verifyFormat("msg_field: < field_a: OK, field_b: \"OK\" >");
// Multiple lines tests
verifyFormat("msg_field <\n"
" field_a: OK\n"
+ " field_b: <>,\n"
+ " field_c: OK\n"
+ ">");
+
+ verifyFormat("msg_field <\n"
+ " field_a { field_b: 1 },\n"
+ " field_c: < f_d: 2 >\n"
+ ">");
+
+ verifyFormat("msg_field: <\n"
+ " field_a: OK\n"
+ " field_b: <>,\n"
+ " field_c: OK\n"
+ ">");
+
+ verifyFormat("msg_field: <\n"
+ " field_a { field_b: 1 },\n"
+ " field_c: < fd_d: 2 >\n"
+ ">");
+
+ verifyFormat("field_a: \"OK\",\n"
+ "msg_field: < field_b: 123 >,\n"
+ "field_c: {}");
+
+ verifyFormat("field_a < field_b: 1 >,\n"
+ "msg_fid: < fiel_b: 123 >,\n"
+ "field_c <>");
+
+ verifyFormat("field_a < field_b: 1 >\n"
+ "msg_fied: < field_b: 123 >\n"
+ "field_c <>");
+
+ verifyFormat("field <\n"
+ " field < field: <> >,\n"
+ " field <>\n"
+ ">\n"
+ "field: < field: 1 >");
+
+ verifyFormat("msg_field <\n"
+ " field_a: OK\n"
" field_b: \"OK\"\n"
" field_c: 1\n"
" field_d: 12.5\n"
@@ -170,37 +223,37 @@ TEST_F(FormatTestTextProto, SupportsAngleBracketMessageFields) {
verifyFormat("msg_field: <>\n"
"field_c: \"OK\",\n"
- "msg_field: <field_d: 123>\n"
+ "msg_field: < field_d: 123 >\n"
"field_e: OK\n"
- "msg_field: <field_d: 12>");
+ "msg_field: < field_d: 12 >");
verifyFormat("field_a: OK,\n"
- "field_b <field_c: OK>,\n"
- "field_d: <12.5>,\n"
+ "field_b < field_c: OK >,\n"
+ "field_d: < 12.5 >,\n"
"field_e: OK");
verifyFormat("field_a: OK\n"
- "field_b <field_c: OK>\n"
- "field_d: <12.5>\n"
+ "field_b < field_c: OK >\n"
+ "field_d: < 12.5 >\n"
"field_e: OKOKOK");
verifyFormat("msg_field <\n"
" field_a: OK,\n"
- " field_b <field_c: OK>,\n"
- " field_d: <12.5>,\n"
+ " field_b < field_c: OK >,\n"
+ " field_d: < 12.5 >,\n"
" field_e: OK\n"
">");
verifyFormat("msg_field <\n"
- " field_a: <field: OK>,\n"
- " field_b <field_c: OK>,\n"
- " field_d: <12.5>,\n"
+ " field_a: < field: OK >,\n"
+ " field_b < field_c: OK >,\n"
+ " field_d: < 12.5 >,\n"
" field_e: OK,\n"
">");
verifyFormat("msg_field: <\n"
" field_a: \"OK\"\n"
- " msg_field: {field_b: OK}\n"
+ " msg_field: { field_b: OK }\n"
" field_g: OK\n"
" field_g: OK\n"
" field_g: OK\n"
@@ -208,87 +261,479 @@ TEST_F(FormatTestTextProto, SupportsAngleBracketMessageFields) {
verifyFormat("field_a {\n"
" field_d: ok\n"
- " field_b: <field_c: 1>\n"
+ " field_b: < field_c: 1 >\n"
" field_d: ok\n"
" field_d: ok\n"
"}");
verifyFormat("field_a: {\n"
" field_d: ok\n"
- " field_b: <field_c: 1>\n"
+ " field_b: < field_c: 1 >\n"
" field_d: ok\n"
" field_d: ok\n"
"}");
- verifyFormat("field_a: <f1: 1, f2: <>>\n"
+ verifyFormat("field_a: <\n"
+ " f1: 1,\n"
+ " f2: <>\n"
+ ">\n"
"field_b <\n"
" field_b1: <>\n"
" field_b2: ok,\n"
" field_b3: <\n"
" field_x {} // Comment\n"
- " field_y: {field_z: 1}\n"
+ " field_y: { field_z: 1 }\n"
" field_w: ok\n"
" >\n"
" field {\n"
" field_x <> // Comment\n"
- " field_y: <field_z: 1>\n"
+ " field_y: < field_z: 1 >\n"
" field_w: ok\n"
" msg_field: <\n"
" field: <>\n"
- " field: <field: 1>\n"
- " field: <field: 2>\n"
- " field: <field: 3>\n"
- " field: <field: 4>\n"
+ " field: < field: 1 >\n"
+ " field: < field: 2 >\n"
+ " field: < field: 3 >\n"
+ " field: < field: 4 >\n"
" field: ok\n"
" >\n"
" }\n"
">\n"
"field: OK,\n"
- "field_c <field <field <>>>");
+ "field_c < field < field <> > >");
verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n"
"head_id: 1\n"
- "data <key: value>");
+ "data < key: value >");
verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n"
"head_id: 1\n"
- "data <key: value>\n"
+ "data < key: value >\n"
"tail_id: 2");
verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n"
"head_id: 1\n"
- "data <key: value>\n"
- "data {key: value}");
+ "data < key: value >\n"
+ "data { key: value }");
verifyFormat("app {\n"
" app_id: 'com.javax.swing.salsa.latino'\n"
" head_id: 1\n"
- " data <key: value>\n"
+ " data < key: value >\n"
"}");
verifyFormat("app: {\n"
" app_id: 'com.javax.swing.salsa.latino'\n"
" head_id: 1\n"
- " data <key: value>\n"
+ " data < key: value >\n"
"}");
verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n"
"headheadheadheadheadhead_id: 1\n"
- "product_data {product {1}}");
+ "product_data { product { 1 } }");
verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n"
"headheadheadheadheadhead_id: 1\n"
- "product_data <product {1}>");
+ "product_data < product { 1 } >");
verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n"
"headheadheadheadheadhead_id: 1\n"
- "product_data <product <1>>");
+ "product_data < product < 1 > >");
verifyFormat("app <\n"
" app_id: 'com.javax.swing.salsa.latino'\n"
" headheadheadheadheadhead_id: 1\n"
- " product_data <product {1}>\n"
+ " product_data < product { 1 } >\n"
">");
+
+ verifyFormat("dcccwrnfioeruvginerurneitinfo {\n"
+ " exte3nsionrnfvui { key: value }\n"
+ "}");
+}
+
+TEST_F(FormatTestTextProto, DiscardsUnbreakableTailIfCanBreakAfter) {
+ // The two closing braces count towards the string UnbreakableTailLength, but
+ // since we have broken after the corresponding opening braces, we don't
+ // consider that length for string breaking.
+ verifyFormat(
+ "foo: {\n"
+ " bar: {\n"
+ " text: \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"\n"
+ " }\n"
+ "}");
+}
+
+TEST_F(FormatTestTextProto, KeepsLongStringLiteralsOnSameLine) {
+ verifyFormat(
+ "foo: {\n"
+ " text: \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaasaaaaaaaaaa\"\n"
+ "}");
+}
+
+TEST_F(FormatTestTextProto, KeepsCommentsIndentedInList) {
+ verifyFormat("aaaaaaaaaa: 100\n"
+ "bbbbbbbbbbbbbbbbbbbbbbbbbbb: 200\n"
+ "# Single line comment for stuff here.\n"
+ "cccccccccccccccccccccccc: 3849\n"
+ "# Multiline comment for stuff here.\n"
+ "# Multiline comment for stuff here.\n"
+ "# Multiline comment for stuff here.\n"
+ "cccccccccccccccccccccccc: 3849");
+}
+
+TEST_F(FormatTestTextProto, UnderstandsHashHashComments) {
+ FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto);
+ Style.ColumnLimit = 60; // To make writing tests easier.
+ EXPECT_EQ("aaa: 100\n"
+ "##this is a double-hash comment.\n"
+ "bb: 100\n"
+ "## another double-hash comment.\n"
+ "### a triple-hash comment\n"
+ "cc: 200\n"
+ "#### a quadriple-hash comment\n"
+ "dd: 100\n",
+ format("aaa: 100\n"
+ "##this is a double-hash comment.\n"
+ "bb: 100\n"
+ "## another double-hash comment.\n"
+ "### a triple-hash comment\n"
+ "cc: 200\n"
+ "#### a quadriple-hash comment\n"
+ "dd: 100\n",
+ Style));
+}
+
+TEST_F(FormatTestTextProto, FormatsExtensions) {
+ verifyFormat("[type] { key: value }");
+ verifyFormat("[type] {\n"
+ " keyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: value\n"
+ "}");
+ verifyFormat("[type.type] { key: value }");
+ verifyFormat("[type.type] < key: value >");
+ verifyFormat("[type.type/type.type] { key: value }");
+ verifyFormat("msg {\n"
+ " [type.type] { key: value }\n"
+ "}");
+ verifyFormat("msg {\n"
+ " [type.type] {\n"
+ " keyyyyyyyyyyyyyy: valuuuuuuuuuuuuuuuuuuuuuuuuue\n"
+ " }\n"
+ "}");
+ verifyFormat("key: value\n"
+ "[a.b] { key: value }");
+ verifyFormat("msg: <\n"
+ " key: value\n"
+ " [a.b.c/d.e]: < key: value >\n"
+ " [f.g]: <\n"
+ " key: valueeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\n"
+ " key: {}\n"
+ " >\n"
+ " key {}\n"
+ " [h.i.j] < key: value >\n"
+ " [a]: {\n"
+ " [b.c]: {}\n"
+ " [d] <>\n"
+ " [e/f]: 1\n"
+ " }\n"
+ ">");
+ verifyFormat("[longg.long.long.long.long.long.long.long.long.long.long\n"
+ " .longg.longlong] { key: value }");
+ verifyFormat("[longg.long.long.long.long.long.long.long.long.long.long\n"
+ " .longg.longlong] {\n"
+ " key: value\n"
+ " key: value\n"
+ " key: value\n"
+ " key: value\n"
+ "}");
+ verifyFormat("[longg.long.long.long.long.long.long.long.long.long\n"
+ " .long/longg.longlong] { key: value }");
+ verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/\n"
+ " bbbbbbbbbbbbbb] { key: value }");
+ // These go over the column limit intentionally, since the alternative
+ // [aa..a\n] is worse.
+ verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] {\n"
+ " key: value\n"
+ "}");
+ verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] {\n"
+ " [type.type] {\n"
+ " keyyyyyyyyyyyyyy: valuuuuuuuuuuuuuuuuuuuuuuuuue\n"
+ " }\n"
+ "}");
+ verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/\n"
+ " bbbbbbb] {\n"
+ " [type.type] {\n"
+ " keyyyyyyyyyyyyyy: valuuuuuuuuuuuuuuuuuuuuuuuuue\n"
+ " }\n"
+ "}");
+ verifyFormat(
+ "aaaaaaaaaaaaaaa {\n"
+ " bbbbbb {\n"
+ " [a.b/cy] {\n"
+ " eeeeeeeeeeeee: \"The lazy coo cat jumps over the lazy hot dog\"\n"
+ " }\n"
+ " }\n"
+ "}");
}
+
+TEST_F(FormatTestTextProto, SpacesAroundPercents) {
+ verifyFormat("key: %d");
+ verifyFormat("key: 0x%04x");
+ verifyFormat("key: \"%d %d\"");
+}
+
+TEST_F(FormatTestTextProto, FormatsRepeatedListInitializers) {
+ verifyFormat("keys: []");
+ verifyFormat("keys: [ 1 ]");
+ verifyFormat("keys: [ 'ala', 'bala' ]");
+ verifyFormat("keys: [\n"
+ " 'ala',\n"
+ " 'bala',\n"
+ " 'porto',\n"
+ " 'kala',\n"
+ " 'too',\n"
+ " 'long',\n"
+ " 'ng'\n"
+ "]");
+ verifyFormat("key: item\n"
+ "keys: [\n"
+ " 'ala',\n"
+ " 'bala',\n"
+ " 'porto',\n"
+ " 'kala',\n"
+ " 'too',\n"
+ " 'long',\n"
+ " 'long',\n"
+ " 'long'\n"
+ "]\n"
+ "key: item\n"
+ "msg {\n"
+ " key: item\n"
+ " keys: [\n"
+ " 'ala',\n"
+ " 'bala',\n"
+ " 'porto',\n"
+ " 'kala',\n"
+ " 'too',\n"
+ " 'long',\n"
+ " 'long'\n"
+ " ]\n"
+ "}\n"
+ "key: value"
+ );
+ FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto);
+ Style.ColumnLimit = 60; // To make writing tests easier.
+ Style.Cpp11BracedListStyle = true;
+ verifyFormat("keys: [1]", Style);
+}
+
+TEST_F(FormatTestTextProto, AcceptsOperatorAsKey) {
+ verifyFormat("aaaaaaaaaaa: <\n"
+ " bbbbbbbbb: <\n"
+ " ccccccccccccccccccccccc: <\n"
+ " operator: 1\n"
+ " operator: 2\n"
+ " operator: 3\n"
+ " operator { key: value }\n"
+ " >\n"
+ " >\n"
+ ">");
+}
+
+TEST_F(FormatTestTextProto, BreaksConsecutiveStringLiterals) {
+ verifyFormat("ala: \"str1\"\n"
+ " \"str2\"\n");
+}
+
+TEST_F(FormatTestTextProto, PutsMultipleEntriesInExtensionsOnNewlines) {
+ FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto);
+ verifyFormat("pppppppppp: {\n"
+ " ssssss: \"http://example.com/blahblahblah\"\n"
+ " ppppppp: \"sssss/MMMMMMMMMMMM\"\n"
+ " [ns.sssss.eeeeeeeee.eeeeeeeeeeeeeee] { begin: 24 end: 252 }\n"
+ " [ns.sssss.eeeeeeeee.eeeeeeeeeeeeeee] {\n"
+ " begin: 24\n"
+ " end: 252\n"
+ " key: value\n"
+ " key: value\n"
+ " }\n"
+ "}", Style);
+}
+
+TEST_F(FormatTestTextProto, BreaksAfterBraceFollowedByClosingBraceOnNextLine) {
+ FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto);
+ Style.ColumnLimit = 60;
+ verifyFormat("keys: [\n"
+ " data: { item: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' }\n"
+ "]");
+ verifyFormat("keys: <\n"
+ " data: { item: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' }\n"
+ ">");
+}
+
+TEST_F(FormatTestTextProto, BreaksEntriesOfSubmessagesContainingSubmessages) {
+ FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto);
+ Style.ColumnLimit = 60;
+ // The column limit allows for the keys submessage to be put on 1 line, but we
+ // break it since it contains a submessage an another entry.
+ verifyFormat("key: valueeeeeeee\n"
+ "keys: {\n"
+ " item: 'aaaaaaaaaaaaaaaa'\n"
+ " sub <>\n"
+ "}");
+ verifyFormat("key: valueeeeeeee\n"
+ "keys: {\n"
+ " item: 'aaaaaaaaaaaaaaaa'\n"
+ " sub {}\n"
+ "}");
+ verifyFormat("key: valueeeeeeee\n"
+ "keys: {\n"
+ " sub {}\n"
+ " sub: <>\n"
+ " sub: []\n"
+ "}");
+ verifyFormat("key: valueeeeeeee\n"
+ "keys: {\n"
+ " item: 'aaaaaaaaaaa'\n"
+ " sub { msg: 1 }\n"
+ "}");
+ verifyFormat("key: valueeeeeeee\n"
+ "keys: {\n"
+ " item: 'aaaaaaaaaaa'\n"
+ " sub: { msg: 1 }\n"
+ "}");
+ verifyFormat("key: valueeeeeeee\n"
+ "keys: {\n"
+ " item: 'aaaaaaaaaaa'\n"
+ " sub < msg: 1 >\n"
+ "}");
+ verifyFormat("key: valueeeeeeee\n"
+ "keys: {\n"
+ " item: 'aaaaaaaaaaa'\n"
+ " sub: [ msg: 1 ]\n"
+ "}");
+ verifyFormat("key: valueeeeeeee\n"
+ "keys: <\n"
+ " item: 'aaaaaaaaaaa'\n"
+ " sub: [ 1, 2 ]\n"
+ ">");
+ verifyFormat("key: valueeeeeeee\n"
+ "keys: {\n"
+ " sub {}\n"
+ " item: 'aaaaaaaaaaaaaaaa'\n"
+ "}");
+ verifyFormat("key: valueeeeeeee\n"
+ "keys: {\n"
+ " sub: []\n"
+ " item: 'aaaaaaaaaaaaaaaa'\n"
+ "}");
+ verifyFormat("key: valueeeeeeee\n"
+ "keys: {\n"
+ " sub <>\n"
+ " item: 'aaaaaaaaaaaaaaaa'\n"
+ "}");
+ verifyFormat("key: valueeeeeeee\n"
+ "keys: {\n"
+ " sub { key: value }\n"
+ " item: 'aaaaaaaaaaaaaaaa'\n"
+ "}");
+ verifyFormat("key: valueeeeeeee\n"
+ "keys: {\n"
+ " sub: [ 1, 2 ]\n"
+ " item: 'aaaaaaaaaaaaaaaa'\n"
+ "}");
+ verifyFormat("key: valueeeeeeee\n"
+ "keys: {\n"
+ " sub < sub_2: {} >\n"
+ " item: 'aaaaaaaaaaaaaaaa'\n"
+ "}");
+ verifyFormat("key: valueeeeeeee\n"
+ "keys: {\n"
+ " item: data\n"
+ " sub: [ 1, 2 ]\n"
+ " item: 'aaaaaaaaaaaaaaaa'\n"
+ "}");
+ verifyFormat("key: valueeeeeeee\n"
+ "keys: {\n"
+ " item: data\n"
+ " sub < sub_2: {} >\n"
+ " item: 'aaaaaaaaaaaaaaaa'\n"
+ "}");
+ verifyFormat("sub: {\n"
+ " key: valueeeeeeee\n"
+ " keys: {\n"
+ " sub: [ 1, 2 ]\n"
+ " item: 'aaaaaaaaaaaaaaaa'\n"
+ " }\n"
+ "}");
+ verifyFormat("sub: {\n"
+ " key: 1\n"
+ " sub: {}\n"
+ "}\n"
+ "# comment\n");
+ verifyFormat("sub: {\n"
+ " key: 1\n"
+ " # comment\n"
+ " sub: {}\n"
+ "}");
+}
+
+TEST_F(FormatTestTextProto, PreventBreaksBetweenKeyAndSubmessages) {
+ verifyFormat("submessage: {\n"
+ " key: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'\n"
+ "}");
+ verifyFormat("submessage {\n"
+ " key: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'\n"
+ "}");
+ verifyFormat("submessage: <\n"
+ " key: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'\n"
+ ">");
+ verifyFormat("submessage <\n"
+ " key: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'\n"
+ ">");
+ verifyFormat("repeatedd: [\n"
+ " 'eyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'\n"
+ "]");
+ // "{" is going over the column limit.
+ verifyFormat(
+ "submessageeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee: {\n"
+ " key: 'aaaaa'\n"
+ "}");
+}
+
+TEST_F(FormatTestTextProto, FormatsCommentsAtEndOfFile) {
+ verifyFormat("key: value\n"
+ "# endfile comment");
+ verifyFormat("key: value\n"
+ "// endfile comment");
+ verifyFormat("key: value\n"
+ "// endfile comment 1\n"
+ "// endfile comment 2");
+ verifyFormat("submessage { key: value }\n"
+ "# endfile comment");
+ verifyFormat("submessage <\n"
+ " key: value\n"
+ " item {}\n"
+ ">\n"
+ "# endfile comment");
+}
+
+TEST_F(FormatTestTextProto, KeepsAmpersandsNextToKeys) {
+ verifyFormat("@tmpl { field: 1 }");
+ verifyFormat("@placeholder: 1");
+ verifyFormat("@name <>");
+ verifyFormat("submessage: @base { key: value }");
+ verifyFormat("submessage: @base {\n"
+ " key: value\n"
+ " item: {}\n"
+ "}");
+ verifyFormat("submessage: {\n"
+ " msg: @base {\n"
+ " yolo: {}\n"
+ " key: value\n"
+ " }\n"
+ " key: value\n"
+ "}");
+}
+
} // end namespace tooling
} // end namespace clang
diff --git a/unittests/Format/NamespaceEndCommentsFixerTest.cpp b/unittests/Format/NamespaceEndCommentsFixerTest.cpp
index fda8b4d69fe0..ee083b8ad14c 100644
--- a/unittests/Format/NamespaceEndCommentsFixerTest.cpp
+++ b/unittests/Format/NamespaceEndCommentsFixerTest.cpp
@@ -25,13 +25,13 @@ protected:
fixNamespaceEndComments(llvm::StringRef Code,
const std::vector<tooling::Range> &Ranges,
const FormatStyle &Style = getLLVMStyle()) {
- DEBUG(llvm::errs() << "---\n");
- DEBUG(llvm::errs() << Code << "\n\n");
+ LLVM_DEBUG(llvm::errs() << "---\n");
+ LLVM_DEBUG(llvm::errs() << Code << "\n\n");
tooling::Replacements Replaces =
clang::format::fixNamespaceEndComments(Style, Code, Ranges, "<stdin>");
auto Result = applyAllReplacements(Code, Replaces);
EXPECT_TRUE(static_cast<bool>(Result));
- DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
+ LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
return *Result;
}
diff --git a/unittests/Format/SortIncludesTest.cpp b/unittests/Format/SortIncludesTest.cpp
index 09fc0703d42e..dde88003784c 100644
--- a/unittests/Format/SortIncludesTest.cpp
+++ b/unittests/Format/SortIncludesTest.cpp
@@ -26,12 +26,12 @@ protected:
std::string sort(StringRef Code, std::vector<tooling::Range> Ranges,
StringRef FileName = "input.cc") {
- auto Replaces = sortIncludes(Style, Code, Ranges, FileName);
+ auto Replaces = sortIncludes(FmtStyle, Code, Ranges, FileName);
Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges);
auto Sorted = applyAllReplacements(Code, Replaces);
EXPECT_TRUE(static_cast<bool>(Sorted));
auto Result = applyAllReplacements(
- *Sorted, reformat(Style, *Sorted, Ranges, FileName));
+ *Sorted, reformat(FmtStyle, *Sorted, Ranges, FileName));
EXPECT_TRUE(static_cast<bool>(Result));
return *Result;
}
@@ -41,12 +41,12 @@ protected:
}
unsigned newCursor(llvm::StringRef Code, unsigned Cursor) {
- sortIncludes(Style, Code, GetCodeRange(Code), "input.cpp", &Cursor);
+ sortIncludes(FmtStyle, Code, GetCodeRange(Code), "input.cpp", &Cursor);
return Cursor;
}
- FormatStyle Style = getLLVMStyle();
-
+ FormatStyle FmtStyle = getLLVMStyle();
+ tooling::IncludeStyle &Style = FmtStyle.IncludeStyle;
};
TEST_F(SortIncludesTest, BasicSorting) {
@@ -74,11 +74,11 @@ TEST_F(SortIncludesTest, NoReplacementsForValidIncludes) {
"#include <d>\n"
"#include <e>\n"
"#include <f>\n";
- EXPECT_TRUE(sortIncludes(Style, Code, GetCodeRange(Code), "a.cc").empty());
+ EXPECT_TRUE(sortIncludes(FmtStyle, Code, GetCodeRange(Code), "a.cc").empty());
}
TEST_F(SortIncludesTest, SortedIncludesInMultipleBlocksAreMerged) {
- Style.IncludeBlocks = FormatStyle::IBS_Merge;
+ Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge;
EXPECT_EQ("#include \"a.h\"\n"
"#include \"b.h\"\n"
"#include \"c.h\"\n",
@@ -88,7 +88,7 @@ TEST_F(SortIncludesTest, SortedIncludesInMultipleBlocksAreMerged) {
"\n"
"#include \"b.h\"\n"));
- Style.IncludeBlocks = FormatStyle::IBS_Regroup;
+ Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
EXPECT_EQ("#include \"a.h\"\n"
"#include \"b.h\"\n"
"#include \"c.h\"\n",
@@ -119,7 +119,7 @@ TEST_F(SortIncludesTest, SupportClangFormatOff) {
}
TEST_F(SortIncludesTest, IncludeSortingCanBeDisabled) {
- Style.SortIncludes = false;
+ FmtStyle.SortIncludes = false;
EXPECT_EQ("#include \"a.h\"\n"
"#include \"c.h\"\n"
"#include \"b.h\"\n",
@@ -182,7 +182,7 @@ TEST_F(SortIncludesTest, SortsLocallyInEachBlock) {
}
TEST_F(SortIncludesTest, SortsAllBlocksWhenMerging) {
- Style.IncludeBlocks = FormatStyle::IBS_Merge;
+ Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge;
EXPECT_EQ("#include \"a.h\"\n"
"#include \"b.h\"\n"
"#include \"c.h\"\n",
@@ -202,7 +202,7 @@ TEST_F(SortIncludesTest, CommentsAlwaysSeparateGroups) {
"// comment\n"
"#include \"b.h\"\n"));
- Style.IncludeBlocks = FormatStyle::IBS_Merge;
+ Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge;
EXPECT_EQ("#include \"a.h\"\n"
"#include \"c.h\"\n"
"// comment\n"
@@ -212,7 +212,7 @@ TEST_F(SortIncludesTest, CommentsAlwaysSeparateGroups) {
"// comment\n"
"#include \"b.h\"\n"));
- Style.IncludeBlocks = FormatStyle::IBS_Regroup;
+ Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
EXPECT_EQ("#include \"a.h\"\n"
"#include \"c.h\"\n"
"// comment\n"
@@ -233,7 +233,7 @@ TEST_F(SortIncludesTest, HandlesAngledIncludesAsSeparateBlocks) {
"#include \"c.h\"\n"
"#include \"a.h\"\n"));
- Style = getGoogleStyle(FormatStyle::LK_Cpp);
+ FmtStyle = getGoogleStyle(FormatStyle::LK_Cpp);
EXPECT_EQ("#include <b.h>\n"
"#include <d.h>\n"
"#include \"a.h\"\n"
@@ -245,7 +245,7 @@ TEST_F(SortIncludesTest, HandlesAngledIncludesAsSeparateBlocks) {
}
TEST_F(SortIncludesTest, RegroupsAngledIncludesInSeparateBlocks) {
- Style.IncludeBlocks = FormatStyle::IBS_Regroup;
+ Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
EXPECT_EQ("#include \"a.h\"\n"
"#include \"c.h\"\n"
"\n"
@@ -345,7 +345,7 @@ TEST_F(SortIncludesTest, LeavesMainHeaderFirst) {
TEST_F(SortIncludesTest, RecognizeMainHeaderInAllGroups) {
Style.IncludeIsMainRegex = "([-_](test|unittest))?$";
- Style.IncludeBlocks = FormatStyle::IBS_Merge;
+ Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge;
EXPECT_EQ("#include \"c.h\"\n"
"#include \"a.h\"\n"
@@ -359,7 +359,7 @@ TEST_F(SortIncludesTest, RecognizeMainHeaderInAllGroups) {
TEST_F(SortIncludesTest, MainHeaderIsSeparatedWhenRegroupping) {
Style.IncludeIsMainRegex = "([-_](test|unittest))?$";
- Style.IncludeBlocks = FormatStyle::IBS_Regroup;
+ Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
EXPECT_EQ("#include \"a.h\"\n"
"\n"
@@ -417,7 +417,7 @@ TEST_F(SortIncludesTest, NegativePriorities) {
TEST_F(SortIncludesTest, PriorityGroupsAreSeparatedWhenRegroupping) {
Style.IncludeCategories = {{".*important_os_header.*", -1}, {".*", 1}};
- Style.IncludeBlocks = FormatStyle::IBS_Regroup;
+ Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
EXPECT_EQ("#include \"important_os_header.h\"\n"
"\n"
@@ -467,7 +467,7 @@ TEST_F(SortIncludesTest, DeduplicateIncludes) {
"#include <b>\n"
"#include <c>\n"));
- Style.IncludeBlocks = FormatStyle::IBS_Merge;
+ Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge;
EXPECT_EQ("#include <a>\n"
"#include <b>\n"
"#include <c>\n",
@@ -479,7 +479,7 @@ TEST_F(SortIncludesTest, DeduplicateIncludes) {
"#include <b>\n"
"#include <c>\n"));
- Style.IncludeBlocks = FormatStyle::IBS_Regroup;
+ Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
EXPECT_EQ("#include <a>\n"
"#include <b>\n"
"#include <c>\n",
@@ -503,7 +503,7 @@ TEST_F(SortIncludesTest, SortAndDeduplicateIncludes) {
"#include <c>\n"
"#include <b>\n"));
- Style.IncludeBlocks = FormatStyle::IBS_Merge;
+ Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge;
EXPECT_EQ("#include <a>\n"
"#include <b>\n"
"#include <c>\n",
@@ -515,7 +515,7 @@ TEST_F(SortIncludesTest, SortAndDeduplicateIncludes) {
"#include <c>\n"
"#include <b>\n"));
- Style.IncludeBlocks = FormatStyle::IBS_Regroup;
+ Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
EXPECT_EQ("#include <a>\n"
"#include <b>\n"
"#include <c>\n",
@@ -573,7 +573,7 @@ TEST_F(SortIncludesTest, ValidAffactedRangesAfterDeduplicatingIncludes) {
"\n"
" int x ;";
std::vector<tooling::Range> Ranges = {tooling::Range(0, 52)};
- auto Replaces = sortIncludes(Style, Code, Ranges, "input.cpp");
+ auto Replaces = sortIncludes(FmtStyle, Code, Ranges, "input.cpp");
Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges);
EXPECT_EQ(1u, Ranges.size());
EXPECT_EQ(0u, Ranges[0].getOffset());
diff --git a/unittests/Format/UsingDeclarationsSorterTest.cpp b/unittests/Format/UsingDeclarationsSorterTest.cpp
index c4d971367be9..2ba6520e057f 100644
--- a/unittests/Format/UsingDeclarationsSorterTest.cpp
+++ b/unittests/Format/UsingDeclarationsSorterTest.cpp
@@ -23,13 +23,13 @@ protected:
std::string sortUsingDeclarations(llvm::StringRef Code,
const std::vector<tooling::Range> &Ranges,
const FormatStyle &Style = getLLVMStyle()) {
- DEBUG(llvm::errs() << "---\n");
- DEBUG(llvm::errs() << Code << "\n\n");
+ LLVM_DEBUG(llvm::errs() << "---\n");
+ LLVM_DEBUG(llvm::errs() << Code << "\n\n");
tooling::Replacements Replaces =
clang::format::sortUsingDeclarations(Style, Code, Ranges, "<stdin>");
auto Result = applyAllReplacements(Code, Replaces);
EXPECT_TRUE(static_cast<bool>(Result));
- DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
+ LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
return *Result;
}
diff --git a/unittests/Frontend/ASTUnitTest.cpp b/unittests/Frontend/ASTUnitTest.cpp
index 4f529cf55de9..c60004e40bd7 100644
--- a/unittests/Frontend/ASTUnitTest.cpp
+++ b/unittests/Frontend/ASTUnitTest.cpp
@@ -23,7 +23,41 @@ using namespace clang;
namespace {
-TEST(ASTUnit, SaveLoadPreservesLangOptionsInPrintingPolicy) {
+class ASTUnitTest : public ::testing::Test {
+protected:
+ int FD;
+ llvm::SmallString<256> InputFileName;
+ std::unique_ptr<ToolOutputFile> input_file;
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags;
+ std::shared_ptr<CompilerInvocation> CInvok;
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps;
+
+ std::unique_ptr<ASTUnit> createASTUnit(bool isVolatile) {
+ EXPECT_FALSE(llvm::sys::fs::createTemporaryFile("ast-unit", "cpp", FD,
+ InputFileName));
+ input_file = llvm::make_unique<ToolOutputFile>(InputFileName, FD);
+ input_file->os() << "";
+
+ const char *Args[] = {"clang", "-xc++", InputFileName.c_str()};
+
+ Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions());
+
+ CInvok = createInvocationFromCommandLine(Args, Diags);
+
+ if (!CInvok)
+ return nullptr;
+
+ FileManager *FileMgr =
+ new FileManager(FileSystemOptions(), vfs::getRealFileSystem());
+ PCHContainerOps = std::make_shared<PCHContainerOperations>();
+
+ return ASTUnit::LoadFromCompilerInvocation(
+ CInvok, PCHContainerOps, Diags, FileMgr, false, false, 0, TU_Complete,
+ false, false, isVolatile);
+ }
+};
+
+TEST_F(ASTUnitTest, SaveLoadPreservesLangOptionsInPrintingPolicy) {
// Check that the printing policy is restored with the correct language
// options when loading an ASTUnit from a file. To this end, an ASTUnit
// for a C++ translation unit is set up and written to a temporary file.
@@ -38,29 +72,7 @@ TEST(ASTUnit, SaveLoadPreservesLangOptionsInPrintingPolicy) {
EXPECT_TRUE(PolicyWithDefaultLangOpt.UseVoidForZeroParams);
}
- int FD;
- llvm::SmallString<256> InputFileName;
- ASSERT_FALSE(llvm::sys::fs::createTemporaryFile("ast-unit", "cpp", FD, InputFileName));
- ToolOutputFile input_file(InputFileName, FD);
- input_file.os() << "";
-
- const char* Args[] = {"clang", "-xc++", InputFileName.c_str()};
-
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
- CompilerInstance::createDiagnostics(new DiagnosticOptions());
-
- std::shared_ptr<CompilerInvocation> CInvok =
- createInvocationFromCommandLine(Args, Diags);
-
- if (!CInvok)
- FAIL() << "could not create compiler invocation";
-
- FileManager *FileMgr =
- new FileManager(FileSystemOptions(), vfs::getRealFileSystem());
- auto PCHContainerOps = std::make_shared<PCHContainerOperations>();
-
- std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromCompilerInvocation(
- CInvok, PCHContainerOps, Diags, FileMgr);
+ std::unique_ptr<ASTUnit> AST = createASTUnit(false);
if (!AST)
FAIL() << "failed to create ASTUnit";
@@ -68,15 +80,17 @@ TEST(ASTUnit, SaveLoadPreservesLangOptionsInPrintingPolicy) {
EXPECT_FALSE(AST->getASTContext().getPrintingPolicy().UseVoidForZeroParams);
llvm::SmallString<256> ASTFileName;
- ASSERT_FALSE(llvm::sys::fs::createTemporaryFile("ast-unit", "ast", FD, ASTFileName));
+ ASSERT_FALSE(
+ llvm::sys::fs::createTemporaryFile("ast-unit", "ast", FD, ASTFileName));
ToolOutputFile ast_file(ASTFileName, FD);
AST->Save(ASTFileName.str());
EXPECT_TRUE(llvm::sys::fs::exists(ASTFileName));
std::unique_ptr<ASTUnit> AU = ASTUnit::LoadFromASTFile(
- ASTFileName.str(), PCHContainerOps->getRawReader(), ASTUnit::LoadEverything, Diags,
- FileSystemOptions(), /*UseDebugInfo=*/false);
+ ASTFileName.str(), PCHContainerOps->getRawReader(),
+ ASTUnit::LoadEverything, Diags, FileSystemOptions(),
+ /*UseDebugInfo=*/false);
if (!AU)
FAIL() << "failed to load ASTUnit";
@@ -84,4 +98,17 @@ TEST(ASTUnit, SaveLoadPreservesLangOptionsInPrintingPolicy) {
EXPECT_FALSE(AU->getASTContext().getPrintingPolicy().UseVoidForZeroParams);
}
+TEST_F(ASTUnitTest, GetBufferForFileMemoryMapping) {
+ std::unique_ptr<ASTUnit> AST = createASTUnit(true);
+
+ if (!AST)
+ FAIL() << "failed to create ASTUnit";
+
+ std::unique_ptr<llvm::MemoryBuffer> memoryBuffer =
+ AST->getBufferForFile(InputFileName);
+
+ EXPECT_NE(memoryBuffer->getBufferKind(),
+ llvm::MemoryBuffer::MemoryBuffer_MMap);
+}
+
} // anonymous namespace
diff --git a/unittests/Frontend/CMakeLists.txt b/unittests/Frontend/CMakeLists.txt
index f3c4336ea22f..c764fb9e2a0f 100644
--- a/unittests/Frontend/CMakeLists.txt
+++ b/unittests/Frontend/CMakeLists.txt
@@ -9,6 +9,7 @@ add_clang_unittest(FrontendTests
CodeGenActionTest.cpp
ParsedSourceLocationTest.cpp
PCHPreambleTest.cpp
+ OutputStreamTest.cpp
)
target_link_libraries(FrontendTests
PRIVATE
@@ -18,4 +19,5 @@ target_link_libraries(FrontendTests
clangLex
clangSema
clangCodeGen
+ clangFrontendTool
)
diff --git a/unittests/Frontend/OutputStreamTest.cpp b/unittests/Frontend/OutputStreamTest.cpp
new file mode 100644
index 000000000000..ff036500d8c8
--- /dev/null
+++ b/unittests/Frontend/OutputStreamTest.cpp
@@ -0,0 +1,46 @@
+//===- unittests/Frontend/OutputStreamTest.cpp --- FrontendAction tests --===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/CodeGen/BackendUtil.h"
+#include "clang/CodeGen/CodeGenAction.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/FrontendTool/Utils.h"
+#include "clang/Lex/PreprocessorOptions.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace clang;
+using namespace clang::frontend;
+
+namespace {
+
+TEST(FrontendOutputTests, TestOutputStream) {
+ auto Invocation = std::make_shared<CompilerInvocation>();
+ Invocation->getPreprocessorOpts().addRemappedFile(
+ "test.cc", MemoryBuffer::getMemBuffer("").release());
+ Invocation->getFrontendOpts().Inputs.push_back(
+ FrontendInputFile("test.cc", InputKind::CXX));
+ Invocation->getFrontendOpts().ProgramAction = EmitBC;
+ Invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu";
+ CompilerInstance Compiler;
+
+ SmallVector<char, 256> IRBuffer;
+ std::unique_ptr<raw_pwrite_stream> IRStream(
+ new raw_svector_ostream(IRBuffer));
+
+ Compiler.setOutputStream(std::move(IRStream));
+ Compiler.setInvocation(std::move(Invocation));
+ Compiler.createDiagnostics();
+
+ bool Success = ExecuteCompilerInvocation(&Compiler);
+ EXPECT_TRUE(Success);
+ EXPECT_TRUE(!IRBuffer.empty());
+ EXPECT_TRUE(StringRef(IRBuffer.data()).startswith("BC"));
+}
+}
diff --git a/unittests/Lex/CMakeLists.txt b/unittests/Lex/CMakeLists.txt
index ea6f9fd23402..bb0f66d86073 100644
--- a/unittests/Lex/CMakeLists.txt
+++ b/unittests/Lex/CMakeLists.txt
@@ -4,6 +4,7 @@ set(LLVM_LINK_COMPONENTS
add_clang_unittest(LexTests
HeaderMapTest.cpp
+ HeaderSearchTest.cpp
LexerTest.cpp
PPCallbacksTest.cpp
PPConditionalDirectiveRecordTest.cpp
diff --git a/unittests/Lex/HeaderSearchTest.cpp b/unittests/Lex/HeaderSearchTest.cpp
new file mode 100644
index 000000000000..c2794f5e9593
--- /dev/null
+++ b/unittests/Lex/HeaderSearchTest.cpp
@@ -0,0 +1,96 @@
+//===- unittests/Lex/HeaderSearchTest.cpp ------ HeaderSearch tests -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/MemoryBufferCache.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/HeaderSearchOptions.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace {
+
+// The test fixture.
+class HeaderSearchTest : public ::testing::Test {
+protected:
+ HeaderSearchTest()
+ : VFS(new vfs::InMemoryFileSystem), FileMgr(FileMgrOpts, VFS),
+ DiagID(new DiagnosticIDs()),
+ Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()),
+ SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions),
+ Search(std::make_shared<HeaderSearchOptions>(), SourceMgr, Diags,
+ LangOpts, Target.get()) {
+ TargetOpts->Triple = "x86_64-apple-darwin11.1.0";
+ Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
+ }
+
+ void addSearchDir(llvm::StringRef Dir) {
+ VFS->addFile(Dir, 0, llvm::MemoryBuffer::getMemBuffer(""), /*User=*/None,
+ /*Group=*/None, llvm::sys::fs::file_type::directory_file);
+ const DirectoryEntry *DE = FileMgr.getDirectory(Dir);
+ assert(DE);
+ auto DL = DirectoryLookup(DE, SrcMgr::C_User, /*isFramework=*/false);
+ Search.AddSearchPath(DL, /*isAngled=*/false);
+ }
+
+ IntrusiveRefCntPtr<vfs::InMemoryFileSystem> VFS;
+ FileSystemOptions FileMgrOpts;
+ FileManager FileMgr;
+ IntrusiveRefCntPtr<DiagnosticIDs> DiagID;
+ DiagnosticsEngine Diags;
+ SourceManager SourceMgr;
+ LangOptions LangOpts;
+ std::shared_ptr<TargetOptions> TargetOpts;
+ IntrusiveRefCntPtr<TargetInfo> Target;
+ HeaderSearch Search;
+};
+
+TEST_F(HeaderSearchTest, NoSearchDir) {
+ EXPECT_EQ(Search.search_dir_size(), 0u);
+ EXPECT_EQ(Search.suggestPathToFileForDiagnostics("/x/y/z", /*WorkingDir=*/""),
+ "/x/y/z");
+}
+
+TEST_F(HeaderSearchTest, SimpleShorten) {
+ addSearchDir("/x");
+ addSearchDir("/x/y");
+ EXPECT_EQ(Search.suggestPathToFileForDiagnostics("/x/y/z", /*WorkingDir=*/""),
+ "z");
+ addSearchDir("/a/b/");
+ EXPECT_EQ(Search.suggestPathToFileForDiagnostics("/a/b/c", /*WorkingDir=*/""),
+ "c");
+}
+
+TEST_F(HeaderSearchTest, ShortenWithWorkingDir) {
+ addSearchDir("x/y");
+ EXPECT_EQ(Search.suggestPathToFileForDiagnostics("/a/b/c/x/y/z",
+ /*WorkingDir=*/"/a/b/c"),
+ "z");
+}
+
+TEST_F(HeaderSearchTest, Dots) {
+ addSearchDir("/x/./y/");
+ EXPECT_EQ(Search.suggestPathToFileForDiagnostics("/x/y/./z",
+ /*WorkingDir=*/""),
+ "z");
+ addSearchDir("a/.././c/");
+ EXPECT_EQ(Search.suggestPathToFileForDiagnostics("/m/n/./c/z",
+ /*WorkingDir=*/"/m/n/"),
+ "z");
+}
+
+} // namespace
+} // namespace clang
diff --git a/unittests/Lex/LexerTest.cpp b/unittests/Lex/LexerTest.cpp
index d699a44b13fd..c913062a7abf 100644
--- a/unittests/Lex/LexerTest.cpp
+++ b/unittests/Lex/LexerTest.cpp
@@ -286,9 +286,7 @@ TEST_F(LexerTest, LexAPI) {
SourceLocation lsqrLoc = toks[0].getLocation();
SourceLocation idLoc = toks[1].getLocation();
SourceLocation rsqrLoc = toks[2].getLocation();
- std::pair<SourceLocation,SourceLocation>
- macroPair = SourceMgr.getExpansionRange(lsqrLoc);
- SourceRange macroRange = SourceRange(macroPair.first, macroPair.second);
+ CharSourceRange macroRange = SourceMgr.getExpansionRange(lsqrLoc);
SourceLocation Loc;
EXPECT_TRUE(Lexer::isAtStartOfMacroExpansion(lsqrLoc, SourceMgr, LangOpts, &Loc));
@@ -297,6 +295,7 @@ TEST_F(LexerTest, LexAPI) {
EXPECT_FALSE(Lexer::isAtEndOfMacroExpansion(idLoc, SourceMgr, LangOpts));
EXPECT_TRUE(Lexer::isAtEndOfMacroExpansion(rsqrLoc, SourceMgr, LangOpts, &Loc));
EXPECT_EQ(Loc, macroRange.getEnd());
+ EXPECT_TRUE(macroRange.isTokenRange());
CharSourceRange range = Lexer::makeFileCharRange(
CharSourceRange::getTokenRange(lsqrLoc, idLoc), SourceMgr, LangOpts);
@@ -334,11 +333,11 @@ TEST_F(LexerTest, LexAPI) {
EXPECT_EQ(SourceRange(fileIdLoc, fileRsqrLoc.getLocWithOffset(1)),
range.getAsRange());
- macroPair = SourceMgr.getExpansionRange(macroLsqrLoc);
+ macroRange = SourceMgr.getExpansionRange(macroLsqrLoc);
range = Lexer::makeFileCharRange(
CharSourceRange::getTokenRange(macroLsqrLoc, macroRsqrLoc),
SourceMgr, LangOpts);
- EXPECT_EQ(SourceRange(macroPair.first, macroPair.second.getLocWithOffset(1)),
+ EXPECT_EQ(SourceRange(macroRange.getBegin(), macroRange.getEnd().getLocWithOffset(1)),
range.getAsRange());
text = Lexer::getSourceText(
@@ -474,8 +473,9 @@ TEST_F(LexerTest, GetBeginningOfTokenWithEscapedNewLine) {
}
TEST_F(LexerTest, AvoidPastEndOfStringDereference) {
- std::vector<Token> LexedTokens = Lex(" // \\\n");
- EXPECT_TRUE(LexedTokens.empty());
+ EXPECT_TRUE(Lex(" // \\\n").empty());
+ EXPECT_TRUE(Lex("#include <\\\\").empty());
+ EXPECT_TRUE(Lex("#include <\\\\\n").empty());
}
TEST_F(LexerTest, StringizingRasString) {
diff --git a/unittests/Lex/PPCallbacksTest.cpp b/unittests/Lex/PPCallbacksTest.cpp
index 67b56a601c71..0fa6286cc048 100644
--- a/unittests/Lex/PPCallbacksTest.cpp
+++ b/unittests/Lex/PPCallbacksTest.cpp
@@ -39,16 +39,18 @@ public:
StringRef FileName, bool IsAngled,
CharSourceRange FilenameRange, const FileEntry *File,
StringRef SearchPath, StringRef RelativePath,
- const Module *Imported) override {
- this->HashLoc = HashLoc;
- this->IncludeTok = IncludeTok;
- this->FileName = FileName.str();
- this->IsAngled = IsAngled;
- this->FilenameRange = FilenameRange;
- this->File = File;
- this->SearchPath = SearchPath.str();
- this->RelativePath = RelativePath.str();
- this->Imported = Imported;
+ const Module *Imported,
+ SrcMgr::CharacteristicKind FileType) override {
+ this->HashLoc = HashLoc;
+ this->IncludeTok = IncludeTok;
+ this->FileName = FileName.str();
+ this->IsAngled = IsAngled;
+ this->FilenameRange = FilenameRange;
+ this->File = File;
+ this->SearchPath = SearchPath.str();
+ this->RelativePath = RelativePath.str();
+ this->Imported = Imported;
+ this->FileType = FileType;
}
SourceLocation HashLoc;
@@ -60,6 +62,7 @@ public:
SmallString<16> SearchPath;
SmallString<16> RelativePath;
const Module* Imported;
+ SrcMgr::CharacteristicKind FileType;
};
// Stub to collect data from PragmaOpenCLExtension callbacks.
@@ -153,6 +156,30 @@ protected:
SourceMgr, PCMCache, HeaderInfo, ModLoader,
/*IILookup =*/nullptr,
/*OwnsHeaderSearch =*/false);
+ return InclusionDirectiveCallback(PP)->FilenameRange;
+ }
+
+ SrcMgr::CharacteristicKind InclusionDirectiveCharacteristicKind(
+ const char *SourceText, const char *HeaderPath, bool SystemHeader) {
+ std::unique_ptr<llvm::MemoryBuffer> Buf =
+ llvm::MemoryBuffer::getMemBuffer(SourceText);
+ SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf)));
+
+ TrivialModuleLoader ModLoader;
+ MemoryBufferCache PCMCache;
+
+ HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr,
+ Diags, LangOpts, Target.get());
+ AddFakeHeader(HeaderInfo, HeaderPath, SystemHeader);
+
+ Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts,
+ SourceMgr, PCMCache, HeaderInfo, ModLoader,
+ /*IILookup =*/nullptr,
+ /*OwnsHeaderSearch =*/false);
+ return InclusionDirectiveCallback(PP)->FileType;
+ }
+
+ InclusionDirectiveCallbacks *InclusionDirectiveCallback(Preprocessor &PP) {
PP.Initialize(*Target);
InclusionDirectiveCallbacks* Callbacks = new InclusionDirectiveCallbacks;
PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Callbacks));
@@ -168,7 +195,7 @@ protected:
}
// Callbacks have been executed at this point -- return filename range.
- return Callbacks->FilenameRange;
+ return Callbacks;
}
PragmaOpenCLExtensionCallbacks::CallbackParameters
@@ -222,6 +249,15 @@ protected:
}
};
+TEST_F(PPCallbacksTest, UserFileCharacteristics) {
+ const char *Source = "#include \"quoted.h\"\n";
+
+ SrcMgr::CharacteristicKind Kind =
+ InclusionDirectiveCharacteristicKind(Source, "/quoted.h", false);
+
+ ASSERT_EQ(SrcMgr::CharacteristicKind::C_User, Kind);
+}
+
TEST_F(PPCallbacksTest, QuotedFilename) {
const char* Source =
"#include \"quoted.h\"\n";
diff --git a/unittests/Rename/RenameMemberTest.cpp b/unittests/Rename/RenameMemberTest.cpp
index 463f7c70def7..fb8d5580fb40 100644
--- a/unittests/Rename/RenameMemberTest.cpp
+++ b/unittests/Rename/RenameMemberTest.cpp
@@ -139,7 +139,7 @@ INSTANTIATE_TEST_CASE_P(
"void f() { auto p = &ns::C::SBar<int>; }", "ns::C::SFoo",
"ns::C::SBar"},
- // These methods are not declared or overrided in the subclass B, we
+ // These methods are not declared or overridden in the subclass B, we
// have to use the qualified name with parent class A to identify them.
{"void f() { auto p = &ns::B::Foo; }",
"void f() { auto p = &ns::B::Bar; }", "ns::A::Foo", "ns::B::Bar"},
diff --git a/unittests/Sema/CMakeLists.txt b/unittests/Sema/CMakeLists.txt
index 16fae820dfe4..45460f1e0f6c 100644
--- a/unittests/Sema/CMakeLists.txt
+++ b/unittests/Sema/CMakeLists.txt
@@ -4,6 +4,7 @@ set(LLVM_LINK_COMPONENTS
add_clang_unittest(SemaTests
ExternalSemaSourceTest.cpp
+ CodeCompleteTest.cpp
)
target_link_libraries(SemaTests
diff --git a/unittests/Sema/CodeCompleteTest.cpp b/unittests/Sema/CodeCompleteTest.cpp
new file mode 100644
index 000000000000..04cb14b971ec
--- /dev/null
+++ b/unittests/Sema/CodeCompleteTest.cpp
@@ -0,0 +1,145 @@
+//=== unittests/Sema/CodeCompleteTest.cpp - Code Complete tests ==============//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Parse/ParseAST.h"
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/SemaDiagnostic.h"
+#include "clang/Tooling/Tooling.h"
+#include "gtest/gtest.h"
+#include "gmock/gmock.h"
+
+namespace {
+
+using namespace clang;
+using namespace clang::tooling;
+using ::testing::UnorderedElementsAre;
+
+const char TestCCName[] = "test.cc";
+using VisitedContextResults = std::vector<std::string>;
+
+class VisitedContextFinder: public CodeCompleteConsumer {
+public:
+ VisitedContextFinder(VisitedContextResults &Results)
+ : CodeCompleteConsumer(/*CodeCompleteOpts=*/{},
+ /*CodeCompleteConsumer*/ false),
+ VCResults(Results),
+ CCTUInfo(std::make_shared<GlobalCodeCompletionAllocator>()) {}
+
+ void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context,
+ CodeCompletionResult *Results,
+ unsigned NumResults) override {
+ VisitedContexts = Context.getVisitedContexts();
+ VCResults = getVisitedNamespace();
+ }
+
+ CodeCompletionAllocator &getAllocator() override {
+ return CCTUInfo.getAllocator();
+ }
+
+ CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }
+
+ std::vector<std::string> getVisitedNamespace() const {
+ std::vector<std::string> NSNames;
+ for (const auto *Context : VisitedContexts)
+ if (const auto *NS = llvm::dyn_cast<NamespaceDecl>(Context))
+ NSNames.push_back(NS->getQualifiedNameAsString());
+ return NSNames;
+ }
+
+private:
+ VisitedContextResults& VCResults;
+ CodeCompletionTUInfo CCTUInfo;
+ CodeCompletionContext::VisitedContextSet VisitedContexts;
+};
+
+class CodeCompleteAction : public SyntaxOnlyAction {
+public:
+ CodeCompleteAction(ParsedSourceLocation P, VisitedContextResults &Results)
+ : CompletePosition(std::move(P)), VCResults(Results) {}
+
+ bool BeginInvocation(CompilerInstance &CI) override {
+ CI.getFrontendOpts().CodeCompletionAt = CompletePosition;
+ CI.setCodeCompletionConsumer(new VisitedContextFinder(VCResults));
+ return true;
+ }
+
+private:
+ // 1-based code complete position <Line, Col>;
+ ParsedSourceLocation CompletePosition;
+ VisitedContextResults& VCResults;
+};
+
+ParsedSourceLocation offsetToPosition(llvm::StringRef Code, size_t Offset) {
+ Offset = std::min(Code.size(), Offset);
+ StringRef Before = Code.substr(0, Offset);
+ int Lines = Before.count('\n');
+ size_t PrevNL = Before.rfind('\n');
+ size_t StartOfLine = (PrevNL == StringRef::npos) ? 0 : (PrevNL + 1);
+ return {TestCCName, static_cast<unsigned>(Lines + 1),
+ static_cast<unsigned>(Offset - StartOfLine + 1)};
+}
+
+VisitedContextResults runCodeCompleteOnCode(StringRef Code) {
+ VisitedContextResults Results;
+ auto TokenOffset = Code.find('^');
+ assert(TokenOffset != StringRef::npos &&
+ "Completion token ^ wasn't found in Code.");
+ std::string WithoutToken = Code.take_front(TokenOffset);
+ WithoutToken += Code.drop_front(WithoutToken.size() + 1);
+ assert(StringRef(WithoutToken).find('^') == StringRef::npos &&
+ "expected exactly one completion token ^ inside the code");
+
+ auto Action = llvm::make_unique<CodeCompleteAction>(
+ offsetToPosition(WithoutToken, TokenOffset), Results);
+ clang::tooling::runToolOnCodeWithArgs(Action.release(), Code, {"-std=c++11"},
+ TestCCName);
+ return Results;
+}
+
+TEST(SemaCodeCompleteTest, VisitedNSForValidQualifiedId) {
+ auto VisitedNS = runCodeCompleteOnCode(R"cpp(
+ namespace ns1 {}
+ namespace ns2 {}
+ namespace ns3 {}
+ namespace ns3 { namespace nns3 {} }
+
+ namespace foo {
+ using namespace ns1;
+ namespace ns4 {} // not visited
+ namespace { using namespace ns2; }
+ inline namespace bar { using namespace ns3::nns3; }
+ } // foo
+ namespace ns { foo::^ }
+ )cpp");
+ EXPECT_THAT(VisitedNS, UnorderedElementsAre("foo", "ns1", "ns2", "ns3::nns3",
+ "foo::(anonymous)"));
+}
+
+TEST(SemaCodeCompleteTest, VisitedNSForInvalideQualifiedId) {
+ auto VisitedNS = runCodeCompleteOnCode(R"cpp(
+ namespace ns { foo::^ }
+ )cpp");
+ EXPECT_TRUE(VisitedNS.empty());
+}
+
+TEST(SemaCodeCompleteTest, VisitedNSWithoutQualifier) {
+ auto VisitedNS = runCodeCompleteOnCode(R"cpp(
+ namespace n1 {
+ namespace n2 {
+ void f(^) {}
+ }
+ }
+ )cpp");
+ EXPECT_THAT(VisitedNS, UnorderedElementsAre("n1", "n1::n2"));
+}
+
+} // namespace
diff --git a/unittests/StaticAnalyzer/AnalyzerOptionsTest.cpp b/unittests/StaticAnalyzer/AnalyzerOptionsTest.cpp
index 891c88da302e..3d8332554fbc 100644
--- a/unittests/StaticAnalyzer/AnalyzerOptionsTest.cpp
+++ b/unittests/StaticAnalyzer/AnalyzerOptionsTest.cpp
@@ -1,4 +1,4 @@
-//===- unittest/Analysis/AnalyzerOptionsTest.cpp - SA Options test --------===//
+//===- unittest/StaticAnalyzer/AnalyzerOptionsTest.cpp - SA Options test --===//
//
// The LLVM Compiler Infrastructure
//
@@ -53,9 +53,9 @@ TEST(StaticAnalyzerOptions, SearchInParentPackageTests) {
// search mode.
CheckerOneMock CheckerOne;
EXPECT_TRUE(Opts.getBooleanOption("Option", false, &CheckerOne));
- // The package option is overriden with a checker option.
+ // The package option is overridden with a checker option.
EXPECT_TRUE(Opts.getBooleanOption("Option", false, &CheckerOne, true));
- // The Outer package option is overriden by the Inner package option. No
+ // The Outer package option is overridden by the Inner package option. No
// package option is specified.
EXPECT_TRUE(Opts.getBooleanOption("Option2", false, &CheckerOne, true));
// No package option is specified and search in packages is turned off. The
diff --git a/unittests/StaticAnalyzer/CMakeLists.txt b/unittests/StaticAnalyzer/CMakeLists.txt
index 4ca0be50e5c2..ff041452dfd4 100644
--- a/unittests/StaticAnalyzer/CMakeLists.txt
+++ b/unittests/StaticAnalyzer/CMakeLists.txt
@@ -4,11 +4,15 @@ set(LLVM_LINK_COMPONENTS
add_clang_unittest(StaticAnalysisTests
AnalyzerOptionsTest.cpp
+ RegisterCustomCheckersTest.cpp
)
target_link_libraries(StaticAnalysisTests
PRIVATE
clangBasic
clangAnalysis
- clangStaticAnalyzerCore
+ clangFrontend
+ clangStaticAnalyzerCore
+ clangStaticAnalyzerFrontend
+ clangTooling
)
diff --git a/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp b/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp
new file mode 100644
index 000000000000..dcd115e59631
--- /dev/null
+++ b/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp
@@ -0,0 +1,80 @@
+//===- unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/CompilerInstance.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/CheckerRegistry.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
+#include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h"
+#include "clang/Tooling/Tooling.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace ento {
+namespace {
+
+class CustomChecker : public Checker<check::ASTCodeBody> {
+public:
+ void checkASTCodeBody(const Decl *D, AnalysisManager &Mgr,
+ BugReporter &BR) const {
+ BR.EmitBasicReport(D, this, "Custom diagnostic", categories::LogicError,
+ "Custom diagnostic description",
+ PathDiagnosticLocation(D, Mgr.getSourceManager()), {});
+ }
+};
+
+class TestAction : public ASTFrontendAction {
+ class DiagConsumer : public PathDiagnosticConsumer {
+ llvm::raw_ostream &Output;
+
+ public:
+ DiagConsumer(llvm::raw_ostream &Output) : Output(Output) {}
+ void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
+ FilesMade *filesMade) override {
+ for (const auto *PD : Diags)
+ Output << PD->getCheckName() << ":" << PD->getShortDescription();
+ }
+
+ StringRef getName() const override { return "Test"; }
+ };
+
+ llvm::raw_ostream &DiagsOutput;
+
+public:
+ TestAction(llvm::raw_ostream &DiagsOutput) : DiagsOutput(DiagsOutput) {}
+
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler,
+ StringRef File) override {
+ std::unique_ptr<AnalysisASTConsumer> AnalysisConsumer =
+ CreateAnalysisConsumer(Compiler);
+ AnalysisConsumer->AddDiagnosticConsumer(new DiagConsumer(DiagsOutput));
+ Compiler.getAnalyzerOpts()->CheckersControlList = {
+ {"custom.CustomChecker", true}};
+ AnalysisConsumer->AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
+ Registry.addChecker<CustomChecker>("custom.CustomChecker", "Description");
+ });
+ return std::move(AnalysisConsumer);
+ }
+};
+
+
+TEST(RegisterCustomCheckers, RegisterChecker) {
+ std::string Diags;
+ {
+ llvm::raw_string_ostream OS(Diags);
+ EXPECT_TRUE(tooling::runToolOnCode(new TestAction(OS), "void f() {;}"));
+ }
+ EXPECT_EQ(Diags, "custom.CustomChecker:Custom diagnostic description");
+}
+
+}
+}
+}
diff --git a/unittests/Tooling/CMakeLists.txt b/unittests/Tooling/CMakeLists.txt
index 557d1007ae2c..e9910fb87aba 100644
--- a/unittests/Tooling/CMakeLists.txt
+++ b/unittests/Tooling/CMakeLists.txt
@@ -18,13 +18,30 @@ add_clang_unittest(ToolingTests
DiagnosticsYamlTest.cpp
ExecutionTest.cpp
FixItTest.cpp
+ HeaderIncludesTest.cpp
LexicallyOrderedRecursiveASTVisitorTest.cpp
LookupTest.cpp
QualTypeNamesTest.cpp
- RecursiveASTVisitorTest.cpp
- RecursiveASTVisitorTestCallVisitor.cpp
+ RecursiveASTVisitorTests/Attr.cpp
+ RecursiveASTVisitorTests/Class.cpp
+ RecursiveASTVisitorTests/ConstructExpr.cpp
+ RecursiveASTVisitorTests/CXXBoolLiteralExpr.cpp
+ RecursiveASTVisitorTests/CXXMemberCall.cpp
+ RecursiveASTVisitorTests/CXXOperatorCallExprTraverser.cpp
+ RecursiveASTVisitorTests/DeclRefExpr.cpp
+ RecursiveASTVisitorTests/ImplicitCtor.cpp
+ RecursiveASTVisitorTests/InitListExprPostOrder.cpp
+ RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp
+ RecursiveASTVisitorTests/InitListExprPreOrder.cpp
+ RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp
+ RecursiveASTVisitorTests/IntegerLiteral.cpp
+ RecursiveASTVisitorTests/LambdaDefaultCapture.cpp
+ RecursiveASTVisitorTests/LambdaExpr.cpp
+ RecursiveASTVisitorTests/NestedNameSpecifiers.cpp
+ RecursiveASTVisitorTests/ParenExpr.cpp
+ RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp
RecursiveASTVisitorTestDeclVisitor.cpp
- RecursiveASTVisitorTestExprVisitor.cpp
+ RecursiveASTVisitorTestPostOrderVisitor.cpp
RecursiveASTVisitorTestTypeLocVisitor.cpp
RefactoringActionRulesTest.cpp
RefactoringCallbacksTest.cpp
@@ -45,5 +62,6 @@ target_link_libraries(ToolingTests
clangRewrite
clangTooling
clangToolingCore
+ clangToolingInclusions
clangToolingRefactor
)
diff --git a/unittests/Tooling/CompilationDatabaseTest.cpp b/unittests/Tooling/CompilationDatabaseTest.cpp
index fd8afe6b7976..ffc1d5b3a4ac 100644
--- a/unittests/Tooling/CompilationDatabaseTest.cpp
+++ b/unittests/Tooling/CompilationDatabaseTest.cpp
@@ -626,5 +626,143 @@ TEST(ParseFixedCompilationDatabase, HandlesArgv0) {
EXPECT_EQ(2, Argc);
}
+struct MemCDB : public CompilationDatabase {
+ using EntryMap = llvm::StringMap<SmallVector<CompileCommand, 1>>;
+ EntryMap Entries;
+ MemCDB(const EntryMap &E) : Entries(E) {}
+
+ std::vector<CompileCommand> getCompileCommands(StringRef F) const override {
+ auto Ret = Entries.lookup(F);
+ return {Ret.begin(), Ret.end()};
+ }
+
+ std::vector<std::string> getAllFiles() const override {
+ std::vector<std::string> Result;
+ for (const auto &Entry : Entries)
+ Result.push_back(Entry.first());
+ return Result;
+ }
+};
+
+class InterpolateTest : public ::testing::Test {
+protected:
+ // Adds an entry to the underlying compilation database.
+ // A flag is injected: -D <File>, so the command used can be identified.
+ void add(llvm::StringRef File, llvm::StringRef Flags = "") {
+ llvm::SmallVector<StringRef, 8> Argv = {"clang", File, "-D", File};
+ llvm::SplitString(Flags, Argv);
+ llvm::SmallString<32> Dir;
+ llvm::sys::path::system_temp_directory(false, Dir);
+ Entries[path(File)].push_back(
+ {Dir, path(File), {Argv.begin(), Argv.end()}, "foo.o"});
+ }
+
+ // Turn a unix path fragment (foo/bar.h) into a native path (C:\tmp\foo\bar.h)
+ std::string path(llvm::SmallString<32> File) {
+ llvm::SmallString<32> Dir;
+ llvm::sys::path::system_temp_directory(false, Dir);
+ llvm::sys::path::native(File);
+ llvm::SmallString<64> Result;
+ llvm::sys::path::append(Result, Dir, File);
+ return Result.str();
+ }
+
+ // Look up the command from a relative path, and return it in string form.
+ // The input file is not included in the returned command.
+ std::string getCommand(llvm::StringRef F) {
+ auto Results =
+ inferMissingCompileCommands(llvm::make_unique<MemCDB>(Entries))
+ ->getCompileCommands(path(F));
+ if (Results.empty())
+ return "none";
+ // drop the input file argument, so tests don't have to deal with path().
+ EXPECT_EQ(Results[0].CommandLine.back(), path(F))
+ << "Last arg should be the file";
+ Results[0].CommandLine.pop_back();
+ return llvm::join(Results[0].CommandLine, " ");
+ }
+
+ MemCDB::EntryMap Entries;
+};
+
+TEST_F(InterpolateTest, Nearby) {
+ add("dir/foo.cpp");
+ add("dir/bar.cpp");
+ add("an/other/foo.cpp");
+
+ // great: dir and name both match (prefix or full, case insensitive)
+ EXPECT_EQ(getCommand("dir/f.cpp"), "clang -D dir/foo.cpp");
+ EXPECT_EQ(getCommand("dir/FOO.cpp"), "clang -D dir/foo.cpp");
+ // no name match. prefer matching dir, break ties by alpha
+ EXPECT_EQ(getCommand("dir/a.cpp"), "clang -D dir/bar.cpp");
+ // an exact name match beats one segment of directory match
+ EXPECT_EQ(getCommand("some/other/bar.h"),
+ "clang -D dir/bar.cpp -x c++-header");
+ // two segments of directory match beat a prefix name match
+ EXPECT_EQ(getCommand("an/other/b.cpp"), "clang -D an/other/foo.cpp");
+ // if nothing matches at all, we still get the closest alpha match
+ EXPECT_EQ(getCommand("below/some/obscure/path.cpp"),
+ "clang -D an/other/foo.cpp");
+}
+
+TEST_F(InterpolateTest, Language) {
+ add("dir/foo.cpp", "-std=c++17");
+ add("dir/baz.cee", "-x c");
+
+ // .h is ambiguous, so we add explicit language flags
+ EXPECT_EQ(getCommand("foo.h"),
+ "clang -D dir/foo.cpp -x c++-header -std=c++17");
+ // and don't add -x if the inferred language is correct.
+ EXPECT_EQ(getCommand("foo.hpp"), "clang -D dir/foo.cpp -std=c++17");
+ // respect -x if it's already there.
+ EXPECT_EQ(getCommand("baz.h"), "clang -D dir/baz.cee -x c-header");
+ // prefer a worse match with the right language
+ EXPECT_EQ(getCommand("foo.c"), "clang -D dir/baz.cee");
+ Entries.erase(path(StringRef("dir/baz.cee")));
+ // Now we transfer across languages, so drop -std too.
+ EXPECT_EQ(getCommand("foo.c"), "clang -D dir/foo.cpp");
+}
+
+TEST_F(InterpolateTest, Strip) {
+ add("dir/foo.cpp", "-o foo.o -Wall");
+ // the -o option and the input file are removed, but -Wall is preserved.
+ EXPECT_EQ(getCommand("dir/bar.cpp"), "clang -D dir/foo.cpp -Wall");
+}
+
+TEST_F(InterpolateTest, Case) {
+ add("FOO/BAR/BAZ/SHOUT.cc");
+ add("foo/bar/baz/quiet.cc");
+ // Case mismatches are completely ignored, so we choose the name match.
+ EXPECT_EQ(getCommand("foo/bar/baz/shout.C"), "clang -D FOO/BAR/BAZ/SHOUT.cc");
+}
+
+TEST(CompileCommandTest, EqualityOperator) {
+ CompileCommand CCRef("/foo/bar", "hello.c", {"a", "b"}, "hello.o");
+ CompileCommand CCTest = CCRef;
+
+ EXPECT_TRUE(CCRef == CCTest);
+ EXPECT_FALSE(CCRef != CCTest);
+
+ CCTest = CCRef;
+ CCTest.Directory = "/foo/baz";
+ EXPECT_FALSE(CCRef == CCTest);
+ EXPECT_TRUE(CCRef != CCTest);
+
+ CCTest = CCRef;
+ CCTest.Filename = "bonjour.c";
+ EXPECT_FALSE(CCRef == CCTest);
+ EXPECT_TRUE(CCRef != CCTest);
+
+ CCTest = CCRef;
+ CCTest.CommandLine.push_back("c");
+ EXPECT_FALSE(CCRef == CCTest);
+ EXPECT_TRUE(CCRef != CCTest);
+
+ CCTest = CCRef;
+ CCTest.Output = "bonjour.o";
+ EXPECT_FALSE(CCRef == CCTest);
+ EXPECT_TRUE(CCRef != CCTest);
+}
+
} // end namespace tooling
} // end namespace clang
diff --git a/unittests/Tooling/ExecutionTest.cpp b/unittests/Tooling/ExecutionTest.cpp
index b0c16d6cc5d2..26db8c6d0ea8 100644
--- a/unittests/Tooling/ExecutionTest.cpp
+++ b/unittests/Tooling/ExecutionTest.cpp
@@ -7,17 +7,19 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/Tooling/Execution.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/FrontendActions.h"
+#include "clang/Tooling/AllTUsExecution.h"
#include "clang/Tooling/CompilationDatabase.h"
-#include "clang/Tooling/Execution.h"
#include "clang/Tooling/StandaloneExecution.h"
#include "clang/Tooling/ToolExecutorPluginRegistry.h"
#include "clang/Tooling/Tooling.h"
+#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <algorithm>
#include <string>
@@ -44,7 +46,10 @@ public:
}
bool TraverseFunctionDecl(clang::FunctionDecl *Decl) {
- Context->reportResult(Decl->getNameAsString(), "1");
+ Context->reportResult(Decl->getNameAsString(),
+ Context->getRevision() + ":" + Context->getCorpus() +
+ ":" + Context->getCurrentCompilationUnit() +
+ "/1");
return ASTVisitor::TraverseFunctionDecl(Decl);
}
@@ -211,10 +216,77 @@ TEST(StandaloneToolTest, SimpleActionWithResult) {
auto KVs = Executor.getToolResults()->AllKVResults();
ASSERT_EQ(KVs.size(), 1u);
EXPECT_EQ("f", KVs[0].first);
- EXPECT_EQ("1", KVs[0].second);
+ // Currently the standlone executor returns empty corpus, revision, and
+ // compilation unit.
+ EXPECT_EQ("::/1", KVs[0].second);
+
+ Executor.getToolResults()->forEachResult(
+ [](StringRef, StringRef Value) { EXPECT_EQ("::/1", Value); });
+}
+
+class FixedCompilationDatabaseWithFiles : public CompilationDatabase {
+public:
+ FixedCompilationDatabaseWithFiles(Twine Directory,
+ ArrayRef<std::string> Files,
+ ArrayRef<std::string> CommandLine)
+ : FixedCompilations(Directory, CommandLine), Files(Files) {}
+
+ std::vector<CompileCommand>
+ getCompileCommands(StringRef FilePath) const override {
+ return FixedCompilations.getCompileCommands(FilePath);
+ }
+
+ std::vector<std::string> getAllFiles() const override { return Files; }
+
+private:
+ FixedCompilationDatabase FixedCompilations;
+ std::vector<std::string> Files;
+};
+
+MATCHER_P(Named, Name, "") { return arg.first == Name; }
+TEST(AllTUsToolTest, AFewFiles) {
+ FixedCompilationDatabaseWithFiles Compilations(".", {"a.cc", "b.cc", "c.cc"},
+ std::vector<std::string>());
+ AllTUsToolExecutor Executor(Compilations, /*ThreadCount=*/0);
+ Executor.mapVirtualFile("a.cc", "void x() {}");
+ Executor.mapVirtualFile("b.cc", "void y() {}");
+ Executor.mapVirtualFile("c.cc", "void z() {}");
+
+ auto Err = Executor.execute(std::unique_ptr<FrontendActionFactory>(
+ new ReportResultActionFactory(Executor.getExecutionContext())));
+ ASSERT_TRUE(!Err);
+ EXPECT_THAT(
+ Executor.getToolResults()->AllKVResults(),
+ ::testing::UnorderedElementsAre(Named("x"), Named("y"), Named("z")));
+}
+
+TEST(AllTUsToolTest, ManyFiles) {
+ unsigned NumFiles = 100;
+ std::vector<std::string> Files;
+ std::map<std::string, std::string> FileToContent;
+ std::vector<std::string> ExpectedSymbols;
+ for (unsigned i = 1; i <= NumFiles; ++i) {
+ std::string File = "f" + std::to_string(i) + ".cc";
+ std::string Symbol = "looong_function_name_" + std::to_string(i);
+ Files.push_back(File);
+ FileToContent[File] = "void " + Symbol + "() {}";
+ ExpectedSymbols.push_back(Symbol);
+ }
+ FixedCompilationDatabaseWithFiles Compilations(".", Files,
+ std::vector<std::string>());
+ AllTUsToolExecutor Executor(Compilations, /*ThreadCount=*/0);
+ for (const auto &FileAndContent : FileToContent) {
+ Executor.mapVirtualFile(FileAndContent.first, FileAndContent.second);
+ }
+
+ auto Err = Executor.execute(std::unique_ptr<FrontendActionFactory>(
+ new ReportResultActionFactory(Executor.getExecutionContext())));
+ ASSERT_TRUE(!Err);
+ std::vector<std::string> Results;
Executor.getToolResults()->forEachResult(
- [](StringRef, StringRef Value) { EXPECT_EQ("1", Value); });
+ [&](StringRef Name, StringRef) { Results.push_back(Name); });
+ EXPECT_THAT(ExpectedSymbols, ::testing::UnorderedElementsAreArray(Results));
}
} // end namespace tooling
diff --git a/unittests/Tooling/HeaderIncludesTest.cpp b/unittests/Tooling/HeaderIncludesTest.cpp
new file mode 100644
index 000000000000..ff68f75a6e82
--- /dev/null
+++ b/unittests/Tooling/HeaderIncludesTest.cpp
@@ -0,0 +1,527 @@
+//===- unittest/Tooling/CleanupTest.cpp - Include insertion/deletion tests ===//
+//
+// 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 "../Tooling/ReplacementTest.h"
+#include "../Tooling/RewriterTestContext.h"
+#include "clang/Format/Format.h"
+#include "clang/Tooling/Core/Replacement.h"
+
+#include "gtest/gtest.h"
+
+using clang::tooling::ReplacementTest;
+using clang::tooling::toReplacements;
+
+namespace clang {
+namespace tooling {
+namespace {
+
+class HeaderIncludesTest : public ::testing::Test {
+protected:
+ std::string insert(llvm::StringRef Code, llvm::StringRef Header) {
+ HeaderIncludes Includes(FileName, Code, Style);
+ assert(Header.startswith("\"") || Header.startswith("<"));
+ auto R = Includes.insert(Header.trim("\"<>"), Header.startswith("<"));
+ if (!R)
+ return Code;
+ auto Result = applyAllReplacements(Code, Replacements(*R));
+ EXPECT_TRUE(static_cast<bool>(Result));
+ return *Result;
+ }
+
+ std::string remove(llvm::StringRef Code, llvm::StringRef Header) {
+ HeaderIncludes Includes(FileName, Code, Style);
+ assert(Header.startswith("\"") || Header.startswith("<"));
+ auto Replaces = Includes.remove(Header.trim("\"<>"), Header.startswith("<"));
+ auto Result = applyAllReplacements(Code, Replaces);
+ EXPECT_TRUE(static_cast<bool>(Result));
+ return *Result;
+ }
+
+ const std::string FileName = "fix.cpp";
+ IncludeStyle Style = format::getLLVMStyle().IncludeStyle;
+};
+
+TEST_F(HeaderIncludesTest, NoExistingIncludeWithoutDefine) {
+ std::string Code = "int main() {}";
+ std::string Expected = "#include \"a.h\"\n"
+ "int main() {}";
+ EXPECT_EQ(Expected, insert(Code, "\"a.h\""));
+}
+
+TEST_F(HeaderIncludesTest, NoExistingIncludeWithDefine) {
+ std::string Code = "#ifndef A_H\n"
+ "#define A_H\n"
+ "class A {};\n"
+ "#define MMM 123\n"
+ "#endif";
+ std::string Expected = "#ifndef A_H\n"
+ "#define A_H\n"
+ "#include \"b.h\"\n"
+ "class A {};\n"
+ "#define MMM 123\n"
+ "#endif";
+
+ EXPECT_EQ(Expected, insert(Code, "\"b.h\""));
+}
+
+TEST_F(HeaderIncludesTest, InsertBeforeCategoryWithLowerPriority) {
+ std::string Code = "#ifndef A_H\n"
+ "#define A_H\n"
+ "\n"
+ "\n"
+ "\n"
+ "#include <vector>\n"
+ "class A {};\n"
+ "#define MMM 123\n"
+ "#endif";
+ std::string Expected = "#ifndef A_H\n"
+ "#define A_H\n"
+ "\n"
+ "\n"
+ "\n"
+ "#include \"a.h\"\n"
+ "#include <vector>\n"
+ "class A {};\n"
+ "#define MMM 123\n"
+ "#endif";
+
+ EXPECT_EQ(Expected, insert(Code, "\"a.h\""));
+}
+
+TEST_F(HeaderIncludesTest, InsertAfterMainHeader) {
+ std::string Code = "#include \"fix.h\"\n"
+ "\n"
+ "int main() {}";
+ std::string Expected = "#include \"fix.h\"\n"
+ "#include <a>\n"
+ "\n"
+ "int main() {}";
+ Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp)
+ .IncludeStyle;
+ EXPECT_EQ(Expected, insert(Code, "<a>"));
+}
+
+TEST_F(HeaderIncludesTest, InsertBeforeSystemHeaderLLVM) {
+ std::string Code = "#include <memory>\n"
+ "\n"
+ "int main() {}";
+ std::string Expected = "#include \"z.h\"\n"
+ "#include <memory>\n"
+ "\n"
+ "int main() {}";
+ EXPECT_EQ(Expected, insert(Code, "\"z.h\""));
+}
+
+TEST_F(HeaderIncludesTest, InsertAfterSystemHeaderGoogle) {
+ std::string Code = "#include <memory>\n"
+ "\n"
+ "int main() {}";
+ std::string Expected = "#include <memory>\n"
+ "#include \"z.h\"\n"
+ "\n"
+ "int main() {}";
+ Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp)
+ .IncludeStyle;
+ EXPECT_EQ(Expected, insert(Code, "\"z.h\""));
+}
+
+TEST_F(HeaderIncludesTest, InsertOneIncludeLLVMStyle) {
+ std::string Code = "#include \"x/fix.h\"\n"
+ "#include \"a.h\"\n"
+ "#include \"b.h\"\n"
+ "#include \"clang/Format/Format.h\"\n"
+ "#include <memory>\n";
+ std::string Expected = "#include \"x/fix.h\"\n"
+ "#include \"a.h\"\n"
+ "#include \"b.h\"\n"
+ "#include \"clang/Format/Format.h\"\n"
+ "#include \"llvm/x/y.h\"\n"
+ "#include <memory>\n";
+ EXPECT_EQ(Expected, insert(Code, "\"llvm/x/y.h\""));
+}
+
+TEST_F(HeaderIncludesTest, InsertIntoBlockSorted) {
+ std::string Code = "#include \"x/fix.h\"\n"
+ "#include \"a.h\"\n"
+ "#include \"c.h\"\n"
+ "#include <memory>\n";
+ std::string Expected = "#include \"x/fix.h\"\n"
+ "#include \"a.h\"\n"
+ "#include \"b.h\"\n"
+ "#include \"c.h\"\n"
+ "#include <memory>\n";
+ EXPECT_EQ(Expected, insert(Code, "\"b.h\""));
+}
+
+TEST_F(HeaderIncludesTest, InsertIntoFirstBlockOfSameKind) {
+ std::string Code = "#include \"x/fix.h\"\n"
+ "#include \"c.h\"\n"
+ "#include \"e.h\"\n"
+ "#include \"f.h\"\n"
+ "#include <memory>\n"
+ "#include <vector>\n"
+ "#include \"m.h\"\n"
+ "#include \"n.h\"\n";
+ std::string Expected = "#include \"x/fix.h\"\n"
+ "#include \"c.h\"\n"
+ "#include \"d.h\"\n"
+ "#include \"e.h\"\n"
+ "#include \"f.h\"\n"
+ "#include <memory>\n"
+ "#include <vector>\n"
+ "#include \"m.h\"\n"
+ "#include \"n.h\"\n";
+ EXPECT_EQ(Expected, insert(Code, "\"d.h\""));
+}
+
+TEST_F(HeaderIncludesTest, InsertIntoSystemBlockSorted) {
+ std::string Code = "#include \"x/fix.h\"\n"
+ "#include \"a.h\"\n"
+ "#include \"c.h\"\n"
+ "#include <a>\n"
+ "#include <z>\n";
+ std::string Expected = "#include \"x/fix.h\"\n"
+ "#include \"a.h\"\n"
+ "#include \"c.h\"\n"
+ "#include <a>\n"
+ "#include <vector>\n"
+ "#include <z>\n";
+ EXPECT_EQ(Expected, insert(Code, "<vector>"));
+}
+
+TEST_F(HeaderIncludesTest, InsertNewSystemIncludeGoogleStyle) {
+ std::string Code = "#include \"x/fix.h\"\n"
+ "\n"
+ "#include \"y/a.h\"\n"
+ "#include \"z/b.h\"\n";
+ // FIXME: inserting after the empty line following the main header might be
+ // preferred.
+ std::string Expected = "#include \"x/fix.h\"\n"
+ "#include <vector>\n"
+ "\n"
+ "#include \"y/a.h\"\n"
+ "#include \"z/b.h\"\n";
+ Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp)
+ .IncludeStyle;
+ EXPECT_EQ(Expected, insert(Code, "<vector>"));
+}
+
+TEST_F(HeaderIncludesTest, NotConfusedByDefine) {
+ std::string Code = "void f() {}\n"
+ "#define A \\\n"
+ " int i;";
+ std::string Expected = "#include <vector>\n"
+ "void f() {}\n"
+ "#define A \\\n"
+ " int i;";
+ EXPECT_EQ(Expected, insert(Code, "<vector>"));
+}
+
+TEST_F(HeaderIncludesTest, SkippedTopComment) {
+ std::string Code = "// comment\n"
+ "\n"
+ " // comment\n";
+ std::string Expected = "// comment\n"
+ "\n"
+ " // comment\n"
+ "#include <vector>\n";
+ EXPECT_EQ(Expected, insert(Code, "<vector>"));
+}
+
+TEST_F(HeaderIncludesTest, SkippedMixedComments) {
+ std::string Code = "// comment\n"
+ "// comment \\\n"
+ " comment continued\n"
+ "/*\n"
+ "* comment\n"
+ "*/\n";
+ std::string Expected = "// comment\n"
+ "// comment \\\n"
+ " comment continued\n"
+ "/*\n"
+ "* comment\n"
+ "*/\n"
+ "#include <vector>\n";
+ EXPECT_EQ(Expected, insert(Code, "<vector>"));
+}
+
+TEST_F(HeaderIncludesTest, MultipleBlockCommentsInOneLine) {
+ std::string Code = "/*\n"
+ "* comment\n"
+ "*/ /* comment\n"
+ "*/\n"
+ "\n\n"
+ "/* c1 */ /*c2 */\n";
+ std::string Expected = "/*\n"
+ "* comment\n"
+ "*/ /* comment\n"
+ "*/\n"
+ "\n\n"
+ "/* c1 */ /*c2 */\n"
+ "#include <vector>\n";
+ EXPECT_EQ(Expected, insert(Code, "<vector>"));
+}
+
+TEST_F(HeaderIncludesTest, CodeAfterComments) {
+ std::string Code = "/*\n"
+ "* comment\n"
+ "*/ /* comment\n"
+ "*/\n"
+ "\n\n"
+ "/* c1 */ /*c2 */\n"
+ "\n"
+ "int x;\n";
+ std::string Expected = "/*\n"
+ "* comment\n"
+ "*/ /* comment\n"
+ "*/\n"
+ "\n\n"
+ "/* c1 */ /*c2 */\n"
+ "\n"
+ "#include <vector>\n"
+ "int x;\n";
+ EXPECT_EQ(Expected, insert(Code, "<vector>"));
+}
+
+TEST_F(HeaderIncludesTest, FakeHeaderGuardIfDef) {
+ std::string Code = "// comment \n"
+ "#ifdef X\n"
+ "#define X\n";
+ std::string Expected = "// comment \n"
+ "#include <vector>\n"
+ "#ifdef X\n"
+ "#define X\n";
+ EXPECT_EQ(Expected, insert(Code, "<vector>"));
+}
+
+TEST_F(HeaderIncludesTest, RealHeaderGuardAfterComments) {
+ std::string Code = "// comment \n"
+ "#ifndef X\n"
+ "#define X\n"
+ "int x;\n"
+ "#define Y 1\n";
+ std::string Expected = "// comment \n"
+ "#ifndef X\n"
+ "#define X\n"
+ "#include <vector>\n"
+ "int x;\n"
+ "#define Y 1\n";
+ EXPECT_EQ(Expected, insert(Code, "<vector>"));
+}
+
+TEST_F(HeaderIncludesTest, IfNDefWithNoDefine) {
+ std::string Code = "// comment \n"
+ "#ifndef X\n"
+ "int x;\n"
+ "#define Y 1\n";
+ std::string Expected = "// comment \n"
+ "#include <vector>\n"
+ "#ifndef X\n"
+ "int x;\n"
+ "#define Y 1\n";
+ EXPECT_EQ(Expected, insert(Code, "<vector>"));
+}
+
+TEST_F(HeaderIncludesTest, FakeHeaderGuard) {
+ std::string Code = "// comment \n"
+ "#ifndef X\n"
+ "#define 1\n";
+ std::string Expected = "// comment \n"
+ "#include <vector>\n"
+ "#ifndef X\n"
+ "#define 1\n";
+ EXPECT_EQ(Expected, insert(Code, "<vector>"));
+}
+
+TEST_F(HeaderIncludesTest, HeaderGuardWithComment) {
+ std::string Code = "// comment \n"
+ "#ifndef X // comment\n"
+ "// comment\n"
+ "/* comment\n"
+ "*/\n"
+ "/* comment */ #define X\n"
+ "int x;\n"
+ "#define Y 1\n";
+ std::string Expected = "// comment \n"
+ "#ifndef X // comment\n"
+ "// comment\n"
+ "/* comment\n"
+ "*/\n"
+ "/* comment */ #define X\n"
+ "#include <vector>\n"
+ "int x;\n"
+ "#define Y 1\n";
+ EXPECT_EQ(Expected, insert(Code, "<vector>"));
+}
+
+TEST_F(HeaderIncludesTest, EmptyCode) {
+ std::string Code = "";
+ std::string Expected = "#include <vector>\n";
+ EXPECT_EQ(Expected, insert(Code, "<vector>"));
+}
+
+TEST_F(HeaderIncludesTest, NoNewLineAtTheEndOfCode) {
+ std::string Code = "#include <map>";
+ std::string Expected = "#include <map>\n#include <vector>\n";
+ EXPECT_EQ(Expected, insert(Code, "<vector>"));
+}
+
+TEST_F(HeaderIncludesTest, SkipExistingHeaders) {
+ std::string Code = "#include \"a.h\"\n"
+ "#include <vector>\n";
+ std::string Expected = "#include \"a.h\"\n"
+ "#include <vector>\n";
+ EXPECT_EQ(Expected, insert(Code, "<vector>"));
+ EXPECT_EQ(Expected, insert(Code, "\"a.h\""));
+}
+
+TEST_F(HeaderIncludesTest, AddIncludesWithDifferentForms) {
+ std::string Code = "#include <vector>\n";
+ // FIXME: this might not be the best behavior.
+ std::string Expected = "#include \"vector\"\n"
+ "#include <vector>\n";
+ EXPECT_EQ(Expected, insert(Code, "\"vector\""));
+}
+
+TEST_F(HeaderIncludesTest, NoInsertionAfterCode) {
+ std::string Code = "#include \"a.h\"\n"
+ "void f() {}\n"
+ "#include \"b.h\"\n";
+ std::string Expected = "#include \"a.h\"\n"
+ "#include \"c.h\"\n"
+ "void f() {}\n"
+ "#include \"b.h\"\n";
+ EXPECT_EQ(Expected, insert(Code, "\"c.h\""));
+}
+
+TEST_F(HeaderIncludesTest, NoInsertionInStringLiteral) {
+ std::string Code = "#include \"a.h\"\n"
+ "const char[] = R\"(\n"
+ "#include \"b.h\"\n"
+ ")\";\n";
+ std::string Expected = "#include \"a.h\"\n"
+ "#include \"c.h\"\n"
+ "const char[] = R\"(\n"
+ "#include \"b.h\"\n"
+ ")\";\n";
+ EXPECT_EQ(Expected, insert(Code, "\"c.h\""));
+}
+
+TEST_F(HeaderIncludesTest, NoInsertionAfterOtherDirective) {
+ std::string Code = "#include \"a.h\"\n"
+ "#ifdef X\n"
+ "#include \"b.h\"\n"
+ "#endif\n";
+ std::string Expected = "#include \"a.h\"\n"
+ "#include \"c.h\"\n"
+ "#ifdef X\n"
+ "#include \"b.h\"\n"
+ "#endif\n";
+ EXPECT_EQ(Expected, insert(Code, "\"c.h\""));
+}
+
+TEST_F(HeaderIncludesTest, CanInsertAfterLongSystemInclude) {
+ std::string Code = "#include \"a.h\"\n"
+ "// comment\n\n"
+ "#include <a/b/c/d/e.h>\n";
+ std::string Expected = "#include \"a.h\"\n"
+ "// comment\n\n"
+ "#include <a/b/c/d/e.h>\n"
+ "#include <x.h>\n";
+ EXPECT_EQ(Expected, insert(Code, "<x.h>"));
+}
+
+TEST_F(HeaderIncludesTest, CanInsertAfterComment) {
+ std::string Code = "#include \"a.h\"\n"
+ "// Comment\n"
+ "\n"
+ "/* Comment */\n"
+ "// Comment\n"
+ "\n"
+ "#include \"b.h\"\n";
+ std::string Expected = "#include \"a.h\"\n"
+ "// Comment\n"
+ "\n"
+ "/* Comment */\n"
+ "// Comment\n"
+ "\n"
+ "#include \"b.h\"\n"
+ "#include \"c.h\"\n";
+ EXPECT_EQ(Expected, insert(Code, "\"c.h\""));
+}
+
+TEST_F(HeaderIncludesTest, LongCommentsInTheBeginningOfFile) {
+ std::string Code = "// Loooooooooooooooooooooooooong comment\n"
+ "// Loooooooooooooooooooooooooong comment\n"
+ "// Loooooooooooooooooooooooooong comment\n"
+ "#include <string>\n"
+ "#include <vector>\n"
+ "\n"
+ "#include \"a.h\"\n"
+ "#include \"b.h\"\n";
+ std::string Expected = "// Loooooooooooooooooooooooooong comment\n"
+ "// Loooooooooooooooooooooooooong comment\n"
+ "// Loooooooooooooooooooooooooong comment\n"
+ "#include <string>\n"
+ "#include <vector>\n"
+ "\n"
+ "#include \"a.h\"\n"
+ "#include \"b.h\"\n"
+ "#include \"third.h\"\n";
+ Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp)
+ .IncludeStyle;
+ EXPECT_EQ(Expected, insert(Code, "\"third.h\""));
+}
+
+TEST_F(HeaderIncludesTest, SimpleDeleteInclude) {
+ std::string Code = "#include \"abc.h\"\n"
+ "#include \"xyz.h\" // comment\n"
+ "int x;\n";
+ std::string Expected = "#include \"abc.h\"\n"
+ "int x;\n";
+ EXPECT_EQ(Expected, remove(Code, "\"xyz.h\""));
+}
+
+TEST_F(HeaderIncludesTest, DeleteQuotedOnly) {
+ std::string Code = "#include \"abc.h\"\n"
+ "#include <abc.h>\n"
+ "int x;\n";
+ std::string Expected = "#include <abc.h>\n"
+ "int x;\n";
+ EXPECT_EQ(Expected, remove(Code, "\"abc.h\""));
+}
+
+TEST_F(HeaderIncludesTest, DeleteAllCode) {
+ std::string Code = "#include \"xyz.h\"\n";
+ std::string Expected = "";
+ EXPECT_EQ(Expected, remove(Code, "\"xyz.h\""));
+}
+
+TEST_F(HeaderIncludesTest, DeleteOnlyIncludesWithSameQuote) {
+ std::string Code = "#include \"xyz.h\"\n"
+ "#include \"xyz\"\n"
+ "#include <xyz.h>\n";
+ std::string Expected = "#include \"xyz.h\"\n"
+ "#include \"xyz\"\n";
+ EXPECT_EQ(Expected, remove(Code, "<xyz.h>"));
+}
+
+TEST_F(HeaderIncludesTest, CanDeleteAfterCode) {
+ std::string Code = "#include \"a.h\"\n"
+ "void f() {}\n"
+ "#include \"b.h\"\n";
+ std::string Expected = "#include \"a.h\"\n"
+ "void f() {}\n";
+ EXPECT_EQ(Expected, remove(Code, "\"b.h\""));
+}
+
+} // namespace
+} // namespace tooling
+} // namespace clang
diff --git a/unittests/Tooling/QualTypeNamesTest.cpp b/unittests/Tooling/QualTypeNamesTest.cpp
index dd48f3bf4595..b4c56f7bd5c1 100644
--- a/unittests/Tooling/QualTypeNamesTest.cpp
+++ b/unittests/Tooling/QualTypeNamesTest.cpp
@@ -26,9 +26,13 @@ struct TypeNameVisitor : TestVisitor<TypeNameVisitor> {
std::string ExpectedName =
ExpectedQualTypeNames.lookup(VD->getNameAsString());
if (ExpectedName != "") {
- std::string ActualName =
- TypeName::getFullyQualifiedName(VD->getType(), *Context,
- WithGlobalNsPrefix);
+ PrintingPolicy Policy(Context->getPrintingPolicy());
+ Policy.SuppressScope = false;
+ Policy.AnonymousTagLocations = true;
+ Policy.PolishForDeclaration = true;
+ Policy.SuppressUnwrittenScope = true;
+ std::string ActualName = TypeName::getFullyQualifiedName(
+ VD->getType(), *Context, Policy, WithGlobalNsPrefix);
if (ExpectedName != ActualName) {
// A custom message makes it much easier to see what declaration
// failed compared to EXPECT_EQ.
@@ -217,6 +221,26 @@ TEST(QualTypeNameTest, getFullyQualifiedName) {
" }\n"
"}\n"
);
+
+ TypeNameVisitor AnonStrucs;
+ AnonStrucs.ExpectedQualTypeNames["a"] = "short";
+ AnonStrucs.ExpectedQualTypeNames["un_in_st_1"] =
+ "union (anonymous struct at input.cc:1:1)::(anonymous union at "
+ "input.cc:2:27)";
+ AnonStrucs.ExpectedQualTypeNames["b"] = "short";
+ AnonStrucs.ExpectedQualTypeNames["un_in_st_2"] =
+ "union (anonymous struct at input.cc:1:1)::(anonymous union at "
+ "input.cc:5:27)";
+ AnonStrucs.ExpectedQualTypeNames["anon_st"] =
+ "struct (anonymous struct at input.cc:1:1)";
+ AnonStrucs.runOver(R"(struct {
+ union {
+ short a;
+ } un_in_st_1;
+ union {
+ short b;
+ } un_in_st_2;
+ } anon_st;)");
}
} // end anonymous namespace
diff --git a/unittests/Tooling/RecursiveASTVisitorTest.cpp b/unittests/Tooling/RecursiveASTVisitorTest.cpp
deleted file mode 100644
index 63dbd1475454..000000000000
--- a/unittests/Tooling/RecursiveASTVisitorTest.cpp
+++ /dev/null
@@ -1,305 +0,0 @@
-//===- unittest/Tooling/RecursiveASTVisitorTest.cpp -----------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "TestVisitor.h"
-#include <stack>
-
-using namespace clang;
-
-namespace {
-
-class LambdaExprVisitor : public ExpectedLocationVisitor<LambdaExprVisitor> {
-public:
- bool VisitLambdaExpr(LambdaExpr *Lambda) {
- PendingBodies.push(Lambda);
- Match("", Lambda->getIntroducerRange().getBegin());
- return true;
- }
- /// For each call to VisitLambdaExpr, we expect a subsequent call (with
- /// proper nesting) to TraverseLambdaBody.
- bool TraverseLambdaBody(LambdaExpr *Lambda) {
- EXPECT_FALSE(PendingBodies.empty());
- EXPECT_EQ(PendingBodies.top(), Lambda);
- PendingBodies.pop();
- return TraverseStmt(Lambda->getBody());
- }
- /// Determine whether TraverseLambdaBody has been called for every call to
- /// VisitLambdaExpr.
- bool allBodiesHaveBeenTraversed() const {
- return PendingBodies.empty();
- }
-private:
- std::stack<LambdaExpr *> PendingBodies;
-};
-
-TEST(RecursiveASTVisitor, VisitsLambdaExpr) {
- LambdaExprVisitor Visitor;
- Visitor.ExpectMatch("", 1, 12);
- EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }",
- LambdaExprVisitor::Lang_CXX11));
-}
-
-TEST(RecursiveASTVisitor, TraverseLambdaBodyCanBeOverridden) {
- LambdaExprVisitor Visitor;
- EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }",
- LambdaExprVisitor::Lang_CXX11));
- EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed());
-}
-
-TEST(RecursiveASTVisitor, VisitsAttributedLambdaExpr) {
- LambdaExprVisitor Visitor;
- Visitor.ExpectMatch("", 1, 12);
- EXPECT_TRUE(Visitor.runOver(
- "void f() { [] () __attribute__ (( fastcall )) { return; }(); }",
- LambdaExprVisitor::Lang_CXX14));
-}
-
-// Matches the (optional) capture-default of a lambda-introducer.
-class LambdaDefaultCaptureVisitor
- : public ExpectedLocationVisitor<LambdaDefaultCaptureVisitor> {
-public:
- bool VisitLambdaExpr(LambdaExpr *Lambda) {
- if (Lambda->getCaptureDefault() != LCD_None) {
- Match("", Lambda->getCaptureDefaultLoc());
- }
- return true;
- }
-};
-
-TEST(RecursiveASTVisitor, HasCaptureDefaultLoc) {
- LambdaDefaultCaptureVisitor Visitor;
- Visitor.ExpectMatch("", 1, 20);
- EXPECT_TRUE(Visitor.runOver("void f() { int a; [=]{a;}; }",
- LambdaDefaultCaptureVisitor::Lang_CXX11));
-}
-
-// Checks for lambda classes that are not marked as implicitly-generated.
-// (There should be none.)
-class ClassVisitor : public ExpectedLocationVisitor<ClassVisitor> {
-public:
- ClassVisitor() : SawNonImplicitLambdaClass(false) {}
- bool VisitCXXRecordDecl(CXXRecordDecl* record) {
- if (record->isLambda() && !record->isImplicit())
- SawNonImplicitLambdaClass = true;
- return true;
- }
-
- bool sawOnlyImplicitLambdaClasses() const {
- return !SawNonImplicitLambdaClass;
- }
-
-private:
- bool SawNonImplicitLambdaClass;
-};
-
-TEST(RecursiveASTVisitor, LambdaClosureTypesAreImplicit) {
- ClassVisitor Visitor;
- EXPECT_TRUE(Visitor.runOver("auto lambda = []{};", ClassVisitor::Lang_CXX11));
- EXPECT_TRUE(Visitor.sawOnlyImplicitLambdaClasses());
-}
-
-
-// Check to ensure that attributes and expressions within them are being
-// visited.
-class AttrVisitor : public ExpectedLocationVisitor<AttrVisitor> {
-public:
- bool VisitMemberExpr(MemberExpr *ME) {
- Match(ME->getMemberDecl()->getNameAsString(), ME->getLocStart());
- return true;
- }
- bool VisitAttr(Attr *A) {
- Match("Attr", A->getLocation());
- return true;
- }
- bool VisitGuardedByAttr(GuardedByAttr *A) {
- Match("guarded_by", A->getLocation());
- return true;
- }
-};
-
-
-TEST(RecursiveASTVisitor, AttributesAreVisited) {
- AttrVisitor Visitor;
- Visitor.ExpectMatch("Attr", 4, 24);
- Visitor.ExpectMatch("guarded_by", 4, 24);
- Visitor.ExpectMatch("mu1", 4, 35);
- Visitor.ExpectMatch("Attr", 5, 29);
- Visitor.ExpectMatch("mu1", 5, 54);
- Visitor.ExpectMatch("mu2", 5, 59);
- EXPECT_TRUE(Visitor.runOver(
- "class Foo {\n"
- " int mu1;\n"
- " int mu2;\n"
- " int a __attribute__((guarded_by(mu1)));\n"
- " void bar() __attribute__((exclusive_locks_required(mu1, mu2)));\n"
- "};\n"));
-}
-
-// Check to ensure that implicit default argument expressions are visited.
-class IntegerLiteralVisitor
- : public ExpectedLocationVisitor<IntegerLiteralVisitor> {
-public:
- bool VisitIntegerLiteral(const IntegerLiteral *IL) {
- Match("literal", IL->getLocation());
- return true;
- }
-};
-
-TEST(RecursiveASTVisitor, DefaultArgumentsAreVisited) {
- IntegerLiteralVisitor Visitor;
- Visitor.ExpectMatch("literal", 1, 15, 2);
- EXPECT_TRUE(Visitor.runOver("int f(int i = 1);\n"
- "static int k = f();\n"));
-}
-
-// Check to ensure that InitListExpr is visited twice, once each for the
-// syntactic and semantic form.
-class InitListExprPreOrderVisitor
- : public ExpectedLocationVisitor<InitListExprPreOrderVisitor> {
-public:
- bool VisitInitListExpr(InitListExpr *ILE) {
- Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart());
- return true;
- }
-};
-
-class InitListExprPostOrderVisitor
- : public ExpectedLocationVisitor<InitListExprPostOrderVisitor> {
-public:
- bool shouldTraversePostOrder() const { return true; }
-
- bool VisitInitListExpr(InitListExpr *ILE) {
- Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart());
- return true;
- }
-};
-
-class InitListExprPreOrderNoQueueVisitor
- : public ExpectedLocationVisitor<InitListExprPreOrderNoQueueVisitor> {
-public:
- bool TraverseInitListExpr(InitListExpr *ILE) {
- return ExpectedLocationVisitor::TraverseInitListExpr(ILE);
- }
-
- bool VisitInitListExpr(InitListExpr *ILE) {
- Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart());
- return true;
- }
-};
-
-class InitListExprPostOrderNoQueueVisitor
- : public ExpectedLocationVisitor<InitListExprPostOrderNoQueueVisitor> {
-public:
- bool shouldTraversePostOrder() const { return true; }
-
- bool TraverseInitListExpr(InitListExpr *ILE) {
- return ExpectedLocationVisitor::TraverseInitListExpr(ILE);
- }
-
- bool VisitInitListExpr(InitListExpr *ILE) {
- Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart());
- return true;
- }
-};
-
-TEST(RecursiveASTVisitor, InitListExprIsPreOrderVisitedTwice) {
- InitListExprPreOrderVisitor Visitor;
- Visitor.ExpectMatch("syntactic", 2, 21);
- Visitor.ExpectMatch("semantic", 2, 21);
- EXPECT_TRUE(Visitor.runOver("struct S { int x; };\n"
- "static struct S s = {.x = 0};\n",
- InitListExprPreOrderVisitor::Lang_C));
-}
-
-TEST(RecursiveASTVisitor, InitListExprIsPostOrderVisitedTwice) {
- InitListExprPostOrderVisitor Visitor;
- Visitor.ExpectMatch("syntactic", 2, 21);
- Visitor.ExpectMatch("semantic", 2, 21);
- EXPECT_TRUE(Visitor.runOver("struct S { int x; };\n"
- "static struct S s = {.x = 0};\n",
- InitListExprPostOrderVisitor::Lang_C));
-}
-
-TEST(RecursiveASTVisitor, InitListExprIsPreOrderNoQueueVisitedTwice) {
- InitListExprPreOrderNoQueueVisitor Visitor;
- Visitor.ExpectMatch("syntactic", 2, 21);
- Visitor.ExpectMatch("semantic", 2, 21);
- EXPECT_TRUE(Visitor.runOver("struct S { int x; };\n"
- "static struct S s = {.x = 0};\n",
- InitListExprPreOrderNoQueueVisitor::Lang_C));
-}
-
-TEST(RecursiveASTVisitor, InitListExprIsPostOrderNoQueueVisitedTwice) {
- InitListExprPostOrderNoQueueVisitor Visitor;
- Visitor.ExpectMatch("syntactic", 2, 21);
- Visitor.ExpectMatch("semantic", 2, 21);
- EXPECT_TRUE(Visitor.runOver("struct S { int x; };\n"
- "static struct S s = {.x = 0};\n",
- InitListExprPostOrderNoQueueVisitor::Lang_C));
-}
-
-// Check to ensure that nested name specifiers are visited.
-class NestedNameSpecifiersVisitor
- : public ExpectedLocationVisitor<NestedNameSpecifiersVisitor> {
-public:
- bool VisitRecordTypeLoc(RecordTypeLoc RTL) {
- if (!RTL)
- return true;
- Match(RTL.getDecl()->getName(), RTL.getNameLoc());
- return true;
- }
-
- bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
- if (!NNS)
- return true;
- if (const NamespaceDecl *ND =
- NNS.getNestedNameSpecifier()->getAsNamespace())
- Match(ND->getName(), NNS.getLocalBeginLoc());
- return ExpectedLocationVisitor::TraverseNestedNameSpecifierLoc(NNS);
- }
-};
-
-TEST(RecursiveASTVisitor,
- NestedNameSpecifiersForTemplateSpecializationsAreVisited) {
- StringRef Source = R"(
-namespace ns {
-struct Outer {
- template<typename T, typename U>
- struct Nested { };
-
- template<typename T>
- static T x;
-};
-}
-
-template<>
-struct ns::Outer::Nested<int, int>;
-
-template<>
-struct ns::Outer::Nested<int, int> { };
-
-template<typename T>
-struct ns::Outer::Nested<int, T> { };
-
-template<>
-int ns::Outer::x<int> = 0;
-)";
- NestedNameSpecifiersVisitor Visitor;
- Visitor.ExpectMatch("ns", 13, 8);
- Visitor.ExpectMatch("ns", 16, 8);
- Visitor.ExpectMatch("ns", 19, 8);
- Visitor.ExpectMatch("ns", 22, 5);
- Visitor.ExpectMatch("Outer", 13, 12);
- Visitor.ExpectMatch("Outer", 16, 12);
- Visitor.ExpectMatch("Outer", 19, 12);
- Visitor.ExpectMatch("Outer", 22, 9);
- EXPECT_TRUE(Visitor.runOver(Source, NestedNameSpecifiersVisitor::Lang_CXX14));
-}
-
-} // end anonymous namespace
diff --git a/unittests/Tooling/RecursiveASTVisitorTestExprVisitor.cpp b/unittests/Tooling/RecursiveASTVisitorTestExprVisitor.cpp
deleted file mode 100644
index 5f1dd65222ba..000000000000
--- a/unittests/Tooling/RecursiveASTVisitorTestExprVisitor.cpp
+++ /dev/null
@@ -1,271 +0,0 @@
-//===- unittest/Tooling/RecursiveASTVisitorTestExprVisitor.cpp ------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "TestVisitor.h"
-
-using namespace clang;
-
-namespace {
-
-class ParenExprVisitor : public ExpectedLocationVisitor<ParenExprVisitor> {
-public:
- bool VisitParenExpr(ParenExpr *Parens) {
- Match("", Parens->getExprLoc());
- return true;
- }
-};
-
-TEST(RecursiveASTVisitor, VisitsParensDuringDataRecursion) {
- ParenExprVisitor Visitor;
- Visitor.ExpectMatch("", 1, 9);
- EXPECT_TRUE(Visitor.runOver("int k = (4) + 9;\n"));
-}
-
-class TemplateArgumentLocTraverser
- : public ExpectedLocationVisitor<TemplateArgumentLocTraverser> {
-public:
- bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) {
- std::string ArgStr;
- llvm::raw_string_ostream Stream(ArgStr);
- const TemplateArgument &Arg = ArgLoc.getArgument();
-
- Arg.print(Context->getPrintingPolicy(), Stream);
- Match(Stream.str(), ArgLoc.getLocation());
- return ExpectedLocationVisitor<TemplateArgumentLocTraverser>::
- TraverseTemplateArgumentLoc(ArgLoc);
- }
-};
-
-TEST(RecursiveASTVisitor, VisitsClassTemplateTemplateParmDefaultArgument) {
- TemplateArgumentLocTraverser Visitor;
- Visitor.ExpectMatch("X", 2, 40);
- EXPECT_TRUE(Visitor.runOver(
- "template<typename T> class X;\n"
- "template<template <typename> class T = X> class Y;\n"
- "template<template <typename> class T> class Y {};\n"));
-}
-
-class CXXBoolLiteralExprVisitor
- : public ExpectedLocationVisitor<CXXBoolLiteralExprVisitor> {
-public:
- bool VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *BE) {
- if (BE->getValue())
- Match("true", BE->getLocation());
- else
- Match("false", BE->getLocation());
- return true;
- }
-};
-
-TEST(RecursiveASTVisitor, VisitsClassTemplateNonTypeParmDefaultArgument) {
- CXXBoolLiteralExprVisitor Visitor;
- Visitor.ExpectMatch("true", 2, 19);
- EXPECT_TRUE(Visitor.runOver(
- "template<bool B> class X;\n"
- "template<bool B = true> class Y;\n"
- "template<bool B> class Y {};\n"));
-}
-
-// A visitor that visits implicit declarations and matches constructors.
-class ImplicitCtorVisitor
- : public ExpectedLocationVisitor<ImplicitCtorVisitor> {
-public:
- bool shouldVisitImplicitCode() const { return true; }
-
- bool VisitCXXConstructorDecl(CXXConstructorDecl* Ctor) {
- if (Ctor->isImplicit()) { // Was not written in source code
- if (const CXXRecordDecl* Class = Ctor->getParent()) {
- Match(Class->getName(), Ctor->getLocation());
- }
- }
- return true;
- }
-};
-
-TEST(RecursiveASTVisitor, VisitsImplicitCopyConstructors) {
- ImplicitCtorVisitor Visitor;
- Visitor.ExpectMatch("Simple", 2, 8);
- // Note: Clang lazily instantiates implicit declarations, so we need
- // to use them in order to force them to appear in the AST.
- EXPECT_TRUE(Visitor.runOver(
- "struct WithCtor { WithCtor(); }; \n"
- "struct Simple { Simple(); WithCtor w; }; \n"
- "int main() { Simple s; Simple t(s); }\n"));
-}
-
-/// \brief A visitor that optionally includes implicit code and matches
-/// CXXConstructExpr.
-///
-/// The name recorded for the match is the name of the class whose constructor
-/// is invoked by the CXXConstructExpr, not the name of the class whose
-/// constructor the CXXConstructExpr is contained in.
-class ConstructExprVisitor
- : public ExpectedLocationVisitor<ConstructExprVisitor> {
-public:
- ConstructExprVisitor() : ShouldVisitImplicitCode(false) {}
-
- bool shouldVisitImplicitCode() const { return ShouldVisitImplicitCode; }
-
- void setShouldVisitImplicitCode(bool NewValue) {
- ShouldVisitImplicitCode = NewValue;
- }
-
- bool VisitCXXConstructExpr(CXXConstructExpr* Expr) {
- if (const CXXConstructorDecl* Ctor = Expr->getConstructor()) {
- if (const CXXRecordDecl* Class = Ctor->getParent()) {
- Match(Class->getName(), Expr->getLocation());
- }
- }
- return true;
- }
-
- private:
- bool ShouldVisitImplicitCode;
-};
-
-TEST(RecursiveASTVisitor, CanVisitImplicitMemberInitializations) {
- ConstructExprVisitor Visitor;
- Visitor.setShouldVisitImplicitCode(true);
- Visitor.ExpectMatch("WithCtor", 2, 8);
- // Simple has a constructor that implicitly initializes 'w'. Test
- // that a visitor that visits implicit code visits that initialization.
- // Note: Clang lazily instantiates implicit declarations, so we need
- // to use them in order to force them to appear in the AST.
- EXPECT_TRUE(Visitor.runOver(
- "struct WithCtor { WithCtor(); }; \n"
- "struct Simple { WithCtor w; }; \n"
- "int main() { Simple s; }\n"));
-}
-
-// The same as CanVisitImplicitMemberInitializations, but checking that the
-// visits are omitted when the visitor does not include implicit code.
-TEST(RecursiveASTVisitor, CanSkipImplicitMemberInitializations) {
- ConstructExprVisitor Visitor;
- Visitor.setShouldVisitImplicitCode(false);
- Visitor.DisallowMatch("WithCtor", 2, 8);
- // Simple has a constructor that implicitly initializes 'w'. Test
- // that a visitor that skips implicit code skips that initialization.
- // Note: Clang lazily instantiates implicit declarations, so we need
- // to use them in order to force them to appear in the AST.
- EXPECT_TRUE(Visitor.runOver(
- "struct WithCtor { WithCtor(); }; \n"
- "struct Simple { WithCtor w; }; \n"
- "int main() { Simple s; }\n"));
-}
-
-class DeclRefExprVisitor : public ExpectedLocationVisitor<DeclRefExprVisitor> {
-public:
- DeclRefExprVisitor() : ShouldVisitImplicitCode(false) {}
-
- bool shouldVisitImplicitCode() const { return ShouldVisitImplicitCode; }
-
- void setShouldVisitImplicitCode(bool NewValue) {
- ShouldVisitImplicitCode = NewValue;
- }
-
- bool VisitDeclRefExpr(DeclRefExpr *Reference) {
- Match(Reference->getNameInfo().getAsString(), Reference->getLocation());
- return true;
- }
-
-private:
- bool ShouldVisitImplicitCode;
-};
-
-TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArguments) {
- DeclRefExprVisitor Visitor;
- Visitor.ExpectMatch("x", 2, 3);
- EXPECT_TRUE(Visitor.runOver(
- "void x(); template <void (*T)()> class X {};\nX<x> y;"));
-}
-
-TEST(RecursiveASTVisitor, VisitsCXXForRangeStmtRange) {
- DeclRefExprVisitor Visitor;
- Visitor.ExpectMatch("x", 2, 25);
- Visitor.ExpectMatch("x", 2, 30);
- EXPECT_TRUE(Visitor.runOver(
- "int x[5];\n"
- "void f() { for (int i : x) { x[0] = 1; } }",
- DeclRefExprVisitor::Lang_CXX11));
-}
-
-TEST(RecursiveASTVisitor, VisitsCallExpr) {
- DeclRefExprVisitor Visitor;
- Visitor.ExpectMatch("x", 1, 22);
- EXPECT_TRUE(Visitor.runOver(
- "void x(); void y() { x(); }"));
-}
-
-TEST(RecursiveASTVisitor, VisitsExplicitLambdaCaptureInit) {
- DeclRefExprVisitor Visitor;
- Visitor.ExpectMatch("i", 1, 20);
- EXPECT_TRUE(Visitor.runOver(
- "void f() { int i; [i]{}; }",
- DeclRefExprVisitor::Lang_CXX11));
-}
-
-TEST(RecursiveASTVisitor, VisitsUseOfImplicitLambdaCapture) {
- DeclRefExprVisitor Visitor;
- Visitor.ExpectMatch("i", 1, 24);
- EXPECT_TRUE(Visitor.runOver(
- "void f() { int i; [=]{ i; }; }",
- DeclRefExprVisitor::Lang_CXX11));
-}
-
-TEST(RecursiveASTVisitor, VisitsImplicitLambdaCaptureInit) {
- DeclRefExprVisitor Visitor;
- Visitor.setShouldVisitImplicitCode(true);
- // We're expecting the "i" in the lambda to be visited twice:
- // - Once for the DeclRefExpr in the lambda capture initialization (whose
- // source code location is set to the first use of the variable).
- // - Once for the DeclRefExpr for the use of "i" inside the lambda.
- Visitor.ExpectMatch("i", 1, 24, /*Times=*/2);
- EXPECT_TRUE(Visitor.runOver(
- "void f() { int i; [=]{ i; }; }",
- DeclRefExprVisitor::Lang_CXX11));
-}
-
-TEST(RecursiveASTVisitor, VisitsLambdaInitCaptureInit) {
- DeclRefExprVisitor Visitor;
- Visitor.ExpectMatch("i", 1, 24);
- EXPECT_TRUE(Visitor.runOver(
- "void f() { int i; [a = i + 1]{}; }",
- DeclRefExprVisitor::Lang_CXX14));
-}
-
-/* FIXME: According to Richard Smith this is a bug in the AST.
-TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArgumentsInInstantiation) {
- DeclRefExprVisitor Visitor;
- Visitor.ExpectMatch("x", 3, 43);
- EXPECT_TRUE(Visitor.runOver(
- "template <typename T> void x();\n"
- "template <void (*T)()> class X {};\n"
- "template <typename T> class Y : public X< x<T> > {};\n"
- "Y<int> y;"));
-}
-*/
-
-TEST(RecursiveASTVisitor, VisitsExtension) {
- DeclRefExprVisitor Visitor;
- Visitor.ExpectMatch("s", 1, 24);
- EXPECT_TRUE(Visitor.runOver(
- "int s = __extension__ (s);\n"));
-}
-
-TEST(RecursiveASTVisitor, VisitsCopyExprOfBlockDeclCapture) {
- DeclRefExprVisitor Visitor;
- Visitor.ExpectMatch("x", 3, 24);
- EXPECT_TRUE(Visitor.runOver("void f(int(^)(int)); \n"
- "void g() { \n"
- " f([&](int x){ return x; }); \n"
- "}",
- DeclRefExprVisitor::Lang_OBJCXX11));
-}
-
-} // end anonymous namespace
diff --git a/unittests/Tooling/RecursiveASTVisitorTestPostOrderVisitor.cpp b/unittests/Tooling/RecursiveASTVisitorTestPostOrderVisitor.cpp
new file mode 100644
index 000000000000..2e7b398c3d1f
--- /dev/null
+++ b/unittests/Tooling/RecursiveASTVisitorTestPostOrderVisitor.cpp
@@ -0,0 +1,116 @@
+//===- unittests/Tooling/RecursiveASTVisitorPostOrderASTVisitor.cpp -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains tests for the post-order traversing functionality
+// of RecursiveASTVisitor.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestVisitor.h"
+
+using namespace clang;
+
+namespace {
+
+class RecordingVisitor : public TestVisitor<RecordingVisitor> {
+
+ bool VisitPostOrder;
+
+public:
+ explicit RecordingVisitor(bool VisitPostOrder)
+ : VisitPostOrder(VisitPostOrder) {}
+
+ // List of visited nodes during traversal.
+ std::vector<std::string> VisitedNodes;
+
+ bool shouldTraversePostOrder() const { return VisitPostOrder; }
+
+ bool VisitUnaryOperator(UnaryOperator *Op) {
+ VisitedNodes.push_back(Op->getOpcodeStr(Op->getOpcode()));
+ return true;
+ }
+
+ bool VisitBinaryOperator(BinaryOperator *Op) {
+ VisitedNodes.push_back(Op->getOpcodeStr());
+ return true;
+ }
+
+ bool VisitIntegerLiteral(IntegerLiteral *Lit) {
+ VisitedNodes.push_back(Lit->getValue().toString(10, false));
+ return true;
+ }
+
+ bool VisitVarDecl(VarDecl *D) {
+ VisitedNodes.push_back(D->getNameAsString());
+ return true;
+ }
+
+ bool VisitCXXMethodDecl(CXXMethodDecl *D) {
+ VisitedNodes.push_back(D->getQualifiedNameAsString());
+ return true;
+ }
+
+ bool VisitReturnStmt(ReturnStmt *S) {
+ VisitedNodes.push_back("return");
+ return true;
+ }
+
+ bool VisitCXXRecordDecl(CXXRecordDecl *D) {
+ if (!D->isImplicit())
+ VisitedNodes.push_back(D->getQualifiedNameAsString());
+ return true;
+ }
+
+ bool VisitTemplateTypeParmType(TemplateTypeParmType *T) {
+ VisitedNodes.push_back(T->getDecl()->getQualifiedNameAsString());
+ return true;
+ }
+};
+} // namespace
+
+TEST(RecursiveASTVisitor, PostOrderTraversal) {
+ // We traverse the translation unit and store all visited nodes.
+ RecordingVisitor Visitor(true);
+ Visitor.runOver("class A {\n"
+ " class B {\n"
+ " int foo() {\n"
+ " while(4) { int i = 9; int j = -5; }\n"
+ " return (1 + 3) + 2; }\n"
+ " };\n"
+ "};\n");
+
+ std::vector<std::string> expected = {"4", "9", "i", "5", "-",
+ "j", "1", "3", "+", "2",
+ "+", "return", "A::B::foo", "A::B", "A"};
+ // Compare the list of actually visited nodes with the expected list of
+ // visited nodes.
+ ASSERT_EQ(expected.size(), Visitor.VisitedNodes.size());
+ for (std::size_t I = 0; I < expected.size(); I++) {
+ ASSERT_EQ(expected[I], Visitor.VisitedNodes[I]);
+ }
+}
+
+TEST(RecursiveASTVisitor, NoPostOrderTraversal) {
+ // We traverse the translation unit and store all visited nodes.
+ RecordingVisitor Visitor(false);
+ Visitor.runOver("class A {\n"
+ " class B {\n"
+ " int foo() { return 1 + 2; }\n"
+ " };\n"
+ "};\n");
+
+ std::vector<std::string> expected = {"A", "A::B", "A::B::foo", "return",
+ "+", "1", "2"};
+ // Compare the list of actually visited nodes with the expected list of
+ // visited nodes.
+ ASSERT_EQ(expected.size(), Visitor.VisitedNodes.size());
+ for (std::size_t I = 0; I < expected.size(); I++) {
+ ASSERT_EQ(expected[I], Visitor.VisitedNodes[I]);
+ }
+}
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/Attr.cpp b/unittests/Tooling/RecursiveASTVisitorTests/Attr.cpp
new file mode 100644
index 000000000000..a6ba92ea03b5
--- /dev/null
+++ b/unittests/Tooling/RecursiveASTVisitorTests/Attr.cpp
@@ -0,0 +1,52 @@
+//===- unittest/Tooling/RecursiveASTVisitorTests/Attr.cpp -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestVisitor.h"
+
+using namespace clang;
+
+namespace {
+
+// Check to ensure that attributes and expressions within them are being
+// visited.
+class AttrVisitor : public ExpectedLocationVisitor<AttrVisitor> {
+public:
+ bool VisitMemberExpr(MemberExpr *ME) {
+ Match(ME->getMemberDecl()->getNameAsString(), ME->getLocStart());
+ return true;
+ }
+ bool VisitAttr(Attr *A) {
+ Match("Attr", A->getLocation());
+ return true;
+ }
+ bool VisitGuardedByAttr(GuardedByAttr *A) {
+ Match("guarded_by", A->getLocation());
+ return true;
+ }
+};
+
+
+TEST(RecursiveASTVisitor, AttributesAreVisited) {
+ AttrVisitor Visitor;
+ Visitor.ExpectMatch("Attr", 4, 24);
+ Visitor.ExpectMatch("guarded_by", 4, 24);
+ Visitor.ExpectMatch("mu1", 4, 35);
+ Visitor.ExpectMatch("Attr", 5, 29);
+ Visitor.ExpectMatch("mu1", 5, 54);
+ Visitor.ExpectMatch("mu2", 5, 59);
+ EXPECT_TRUE(Visitor.runOver(
+ "class Foo {\n"
+ " int mu1;\n"
+ " int mu2;\n"
+ " int a __attribute__((guarded_by(mu1)));\n"
+ " void bar() __attribute__((exclusive_locks_required(mu1, mu2)));\n"
+ "};\n"));
+}
+
+} // end anonymous namespace
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/CXXBoolLiteralExpr.cpp b/unittests/Tooling/RecursiveASTVisitorTests/CXXBoolLiteralExpr.cpp
new file mode 100644
index 000000000000..ca2e4a4691dc
--- /dev/null
+++ b/unittests/Tooling/RecursiveASTVisitorTests/CXXBoolLiteralExpr.cpp
@@ -0,0 +1,37 @@
+//===- unittest/Tooling/RecursiveASTVisitorTests/CXXBoolLiteralExpr.cpp ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestVisitor.h"
+
+using namespace clang;
+
+namespace {
+
+class CXXBoolLiteralExprVisitor
+ : public ExpectedLocationVisitor<CXXBoolLiteralExprVisitor> {
+public:
+ bool VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *BE) {
+ if (BE->getValue())
+ Match("true", BE->getLocation());
+ else
+ Match("false", BE->getLocation());
+ return true;
+ }
+};
+
+TEST(RecursiveASTVisitor, VisitsClassTemplateNonTypeParmDefaultArgument) {
+ CXXBoolLiteralExprVisitor Visitor;
+ Visitor.ExpectMatch("true", 2, 19);
+ EXPECT_TRUE(Visitor.runOver(
+ "template<bool B> class X;\n"
+ "template<bool B = true> class Y;\n"
+ "template<bool B> class Y {};\n"));
+}
+
+} // end anonymous namespace
diff --git a/unittests/Tooling/RecursiveASTVisitorTestCallVisitor.cpp b/unittests/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp
index b981585450e1..8a979204b847 100644
--- a/unittests/Tooling/RecursiveASTVisitorTestCallVisitor.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp
@@ -1,4 +1,4 @@
-//===- unittest/Tooling/RecursiveASTVisitorTestCallVisitor.cpp ------------===//
+//===- unittest/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp --------===//
//
// The LLVM Compiler Infrastructure
//
@@ -95,26 +95,4 @@ TEST(RecursiveASTVisitor, VisitsExplicitTemplateSpecialization) {
"template void A::g(const A& a) const;\n"));
}
-class CXXOperatorCallExprTraverser
- : public ExpectedLocationVisitor<CXXOperatorCallExprTraverser> {
-public:
- // Use Traverse, not Visit, to check that data recursion optimization isn't
- // bypassing the call of this function.
- bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *CE) {
- Match(getOperatorSpelling(CE->getOperator()), CE->getExprLoc());
- return ExpectedLocationVisitor<CXXOperatorCallExprTraverser>::
- TraverseCXXOperatorCallExpr(CE);
- }
-};
-
-TEST(RecursiveASTVisitor, TraversesOverloadedOperator) {
- CXXOperatorCallExprTraverser Visitor;
- Visitor.ExpectMatch("()", 4, 9);
- EXPECT_TRUE(Visitor.runOver(
- "struct A {\n"
- " int operator()();\n"
- "} a;\n"
- "int k = a();\n"));
-}
-
} // end anonymous namespace
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/CXXOperatorCallExprTraverser.cpp b/unittests/Tooling/RecursiveASTVisitorTests/CXXOperatorCallExprTraverser.cpp
new file mode 100644
index 000000000000..414b0f0174e1
--- /dev/null
+++ b/unittests/Tooling/RecursiveASTVisitorTests/CXXOperatorCallExprTraverser.cpp
@@ -0,0 +1,38 @@
+//===- unittest/Tooling/RecursiveASTVisitorTests/CXXOperatorCallExprTraverser.cpp -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestVisitor.h"
+
+using namespace clang;
+
+namespace {
+
+class CXXOperatorCallExprTraverser
+ : public ExpectedLocationVisitor<CXXOperatorCallExprTraverser> {
+public:
+ // Use Traverse, not Visit, to check that data recursion optimization isn't
+ // bypassing the call of this function.
+ bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *CE) {
+ Match(getOperatorSpelling(CE->getOperator()), CE->getExprLoc());
+ return ExpectedLocationVisitor<CXXOperatorCallExprTraverser>::
+ TraverseCXXOperatorCallExpr(CE);
+ }
+};
+
+TEST(RecursiveASTVisitor, TraversesOverloadedOperator) {
+ CXXOperatorCallExprTraverser Visitor;
+ Visitor.ExpectMatch("()", 4, 9);
+ EXPECT_TRUE(Visitor.runOver(
+ "struct A {\n"
+ " int operator()();\n"
+ "} a;\n"
+ "int k = a();\n"));
+}
+
+} // end anonymous namespace
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/Class.cpp b/unittests/Tooling/RecursiveASTVisitorTests/Class.cpp
new file mode 100644
index 000000000000..666c924d1acf
--- /dev/null
+++ b/unittests/Tooling/RecursiveASTVisitorTests/Class.cpp
@@ -0,0 +1,41 @@
+//===- unittest/Tooling/RecursiveASTVisitorTests/Class.cpp ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestVisitor.h"
+
+using namespace clang;
+
+namespace {
+
+// Checks for lambda classes that are not marked as implicitly-generated.
+// (There should be none.)
+class ClassVisitor : public ExpectedLocationVisitor<ClassVisitor> {
+public:
+ ClassVisitor() : SawNonImplicitLambdaClass(false) {}
+ bool VisitCXXRecordDecl(CXXRecordDecl* record) {
+ if (record->isLambda() && !record->isImplicit())
+ SawNonImplicitLambdaClass = true;
+ return true;
+ }
+
+ bool sawOnlyImplicitLambdaClasses() const {
+ return !SawNonImplicitLambdaClass;
+ }
+
+private:
+ bool SawNonImplicitLambdaClass;
+};
+
+TEST(RecursiveASTVisitor, LambdaClosureTypesAreImplicit) {
+ ClassVisitor Visitor;
+ EXPECT_TRUE(Visitor.runOver("auto lambda = []{};", ClassVisitor::Lang_CXX11));
+ EXPECT_TRUE(Visitor.sawOnlyImplicitLambdaClasses());
+}
+
+} // end anonymous namespace
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/ConstructExpr.cpp b/unittests/Tooling/RecursiveASTVisitorTests/ConstructExpr.cpp
new file mode 100644
index 000000000000..f775a31e59b2
--- /dev/null
+++ b/unittests/Tooling/RecursiveASTVisitorTests/ConstructExpr.cpp
@@ -0,0 +1,76 @@
+//===- unittest/Tooling/RecursiveASTVisitorTests/ConstructExpr.cpp --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestVisitor.h"
+
+using namespace clang;
+
+namespace {
+
+/// \brief A visitor that optionally includes implicit code and matches
+/// CXXConstructExpr.
+///
+/// The name recorded for the match is the name of the class whose constructor
+/// is invoked by the CXXConstructExpr, not the name of the class whose
+/// constructor the CXXConstructExpr is contained in.
+class ConstructExprVisitor
+ : public ExpectedLocationVisitor<ConstructExprVisitor> {
+public:
+ ConstructExprVisitor() : ShouldVisitImplicitCode(false) {}
+
+ bool shouldVisitImplicitCode() const { return ShouldVisitImplicitCode; }
+
+ void setShouldVisitImplicitCode(bool NewValue) {
+ ShouldVisitImplicitCode = NewValue;
+ }
+
+ bool VisitCXXConstructExpr(CXXConstructExpr* Expr) {
+ if (const CXXConstructorDecl* Ctor = Expr->getConstructor()) {
+ if (const CXXRecordDecl* Class = Ctor->getParent()) {
+ Match(Class->getName(), Expr->getLocation());
+ }
+ }
+ return true;
+ }
+
+ private:
+ bool ShouldVisitImplicitCode;
+};
+
+TEST(RecursiveASTVisitor, CanVisitImplicitMemberInitializations) {
+ ConstructExprVisitor Visitor;
+ Visitor.setShouldVisitImplicitCode(true);
+ Visitor.ExpectMatch("WithCtor", 2, 8);
+ // Simple has a constructor that implicitly initializes 'w'. Test
+ // that a visitor that visits implicit code visits that initialization.
+ // Note: Clang lazily instantiates implicit declarations, so we need
+ // to use them in order to force them to appear in the AST.
+ EXPECT_TRUE(Visitor.runOver(
+ "struct WithCtor { WithCtor(); }; \n"
+ "struct Simple { WithCtor w; }; \n"
+ "int main() { Simple s; }\n"));
+}
+
+// The same as CanVisitImplicitMemberInitializations, but checking that the
+// visits are omitted when the visitor does not include implicit code.
+TEST(RecursiveASTVisitor, CanSkipImplicitMemberInitializations) {
+ ConstructExprVisitor Visitor;
+ Visitor.setShouldVisitImplicitCode(false);
+ Visitor.DisallowMatch("WithCtor", 2, 8);
+ // Simple has a constructor that implicitly initializes 'w'. Test
+ // that a visitor that skips implicit code skips that initialization.
+ // Note: Clang lazily instantiates implicit declarations, so we need
+ // to use them in order to force them to appear in the AST.
+ EXPECT_TRUE(Visitor.runOver(
+ "struct WithCtor { WithCtor(); }; \n"
+ "struct Simple { WithCtor w; }; \n"
+ "int main() { Simple s; }\n"));
+}
+
+} // end anonymous namespace
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp b/unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp
new file mode 100644
index 000000000000..67640486efb6
--- /dev/null
+++ b/unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp
@@ -0,0 +1,125 @@
+//===- unittest/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestVisitor.h"
+
+using namespace clang;
+
+namespace {
+
+class DeclRefExprVisitor : public ExpectedLocationVisitor<DeclRefExprVisitor> {
+public:
+ DeclRefExprVisitor() : ShouldVisitImplicitCode(false) {}
+
+ bool shouldVisitImplicitCode() const { return ShouldVisitImplicitCode; }
+
+ void setShouldVisitImplicitCode(bool NewValue) {
+ ShouldVisitImplicitCode = NewValue;
+ }
+
+ bool VisitDeclRefExpr(DeclRefExpr *Reference) {
+ Match(Reference->getNameInfo().getAsString(), Reference->getLocation());
+ return true;
+ }
+
+private:
+ bool ShouldVisitImplicitCode;
+};
+
+TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArguments) {
+ DeclRefExprVisitor Visitor;
+ Visitor.ExpectMatch("x", 2, 3);
+ EXPECT_TRUE(Visitor.runOver(
+ "void x(); template <void (*T)()> class X {};\nX<x> y;"));
+}
+
+TEST(RecursiveASTVisitor, VisitsCXXForRangeStmtRange) {
+ DeclRefExprVisitor Visitor;
+ Visitor.ExpectMatch("x", 2, 25);
+ Visitor.ExpectMatch("x", 2, 30);
+ EXPECT_TRUE(Visitor.runOver(
+ "int x[5];\n"
+ "void f() { for (int i : x) { x[0] = 1; } }",
+ DeclRefExprVisitor::Lang_CXX11));
+}
+
+TEST(RecursiveASTVisitor, VisitsCallExpr) {
+ DeclRefExprVisitor Visitor;
+ Visitor.ExpectMatch("x", 1, 22);
+ EXPECT_TRUE(Visitor.runOver(
+ "void x(); void y() { x(); }"));
+}
+
+TEST(RecursiveASTVisitor, VisitsExplicitLambdaCaptureInit) {
+ DeclRefExprVisitor Visitor;
+ Visitor.ExpectMatch("i", 1, 20);
+ EXPECT_TRUE(Visitor.runOver(
+ "void f() { int i; [i]{}; }",
+ DeclRefExprVisitor::Lang_CXX11));
+}
+
+TEST(RecursiveASTVisitor, VisitsUseOfImplicitLambdaCapture) {
+ DeclRefExprVisitor Visitor;
+ Visitor.ExpectMatch("i", 1, 24);
+ EXPECT_TRUE(Visitor.runOver(
+ "void f() { int i; [=]{ i; }; }",
+ DeclRefExprVisitor::Lang_CXX11));
+}
+
+TEST(RecursiveASTVisitor, VisitsImplicitLambdaCaptureInit) {
+ DeclRefExprVisitor Visitor;
+ Visitor.setShouldVisitImplicitCode(true);
+ // We're expecting the "i" in the lambda to be visited twice:
+ // - Once for the DeclRefExpr in the lambda capture initialization (whose
+ // source code location is set to the first use of the variable).
+ // - Once for the DeclRefExpr for the use of "i" inside the lambda.
+ Visitor.ExpectMatch("i", 1, 24, /*Times=*/2);
+ EXPECT_TRUE(Visitor.runOver(
+ "void f() { int i; [=]{ i; }; }",
+ DeclRefExprVisitor::Lang_CXX11));
+}
+
+TEST(RecursiveASTVisitor, VisitsLambdaInitCaptureInit) {
+ DeclRefExprVisitor Visitor;
+ Visitor.ExpectMatch("i", 1, 24);
+ EXPECT_TRUE(Visitor.runOver(
+ "void f() { int i; [a = i + 1]{}; }",
+ DeclRefExprVisitor::Lang_CXX14));
+}
+
+/* FIXME: According to Richard Smith this is a bug in the AST.
+TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArgumentsInInstantiation) {
+ DeclRefExprVisitor Visitor;
+ Visitor.ExpectMatch("x", 3, 43);
+ EXPECT_TRUE(Visitor.runOver(
+ "template <typename T> void x();\n"
+ "template <void (*T)()> class X {};\n"
+ "template <typename T> class Y : public X< x<T> > {};\n"
+ "Y<int> y;"));
+}
+*/
+
+TEST(RecursiveASTVisitor, VisitsExtension) {
+ DeclRefExprVisitor Visitor;
+ Visitor.ExpectMatch("s", 1, 24);
+ EXPECT_TRUE(Visitor.runOver(
+ "int s = __extension__ (s);\n"));
+}
+
+TEST(RecursiveASTVisitor, VisitsCopyExprOfBlockDeclCapture) {
+ DeclRefExprVisitor Visitor;
+ Visitor.ExpectMatch("x", 3, 24);
+ EXPECT_TRUE(Visitor.runOver("void f(int(^)(int)); \n"
+ "void g() { \n"
+ " f([&](int x){ return x; }); \n"
+ "}",
+ DeclRefExprVisitor::Lang_OBJCXX11));
+}
+
+} // end anonymous namespace
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/ImplicitCtor.cpp b/unittests/Tooling/RecursiveASTVisitorTests/ImplicitCtor.cpp
new file mode 100644
index 000000000000..c2194ab2927d
--- /dev/null
+++ b/unittests/Tooling/RecursiveASTVisitorTests/ImplicitCtor.cpp
@@ -0,0 +1,43 @@
+//===- unittest/Tooling/RecursiveASTVisitorTests/ImplicitCtor.cpp ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestVisitor.h"
+
+using namespace clang;
+
+namespace {
+
+// A visitor that visits implicit declarations and matches constructors.
+class ImplicitCtorVisitor
+ : public ExpectedLocationVisitor<ImplicitCtorVisitor> {
+public:
+ bool shouldVisitImplicitCode() const { return true; }
+
+ bool VisitCXXConstructorDecl(CXXConstructorDecl* Ctor) {
+ if (Ctor->isImplicit()) { // Was not written in source code
+ if (const CXXRecordDecl* Class = Ctor->getParent()) {
+ Match(Class->getName(), Ctor->getLocation());
+ }
+ }
+ return true;
+ }
+};
+
+TEST(RecursiveASTVisitor, VisitsImplicitCopyConstructors) {
+ ImplicitCtorVisitor Visitor;
+ Visitor.ExpectMatch("Simple", 2, 8);
+ // Note: Clang lazily instantiates implicit declarations, so we need
+ // to use them in order to force them to appear in the AST.
+ EXPECT_TRUE(Visitor.runOver(
+ "struct WithCtor { WithCtor(); }; \n"
+ "struct Simple { Simple(); WithCtor w; }; \n"
+ "int main() { Simple s; Simple t(s); }\n"));
+}
+
+} // end anonymous namespace
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrder.cpp b/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrder.cpp
new file mode 100644
index 000000000000..420b49aa1b14
--- /dev/null
+++ b/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrder.cpp
@@ -0,0 +1,36 @@
+//===- unittest/Tooling/RecursiveASTVisitorTests/InitListExprPostOrder.cpp -==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestVisitor.h"
+
+using namespace clang;
+
+namespace {
+
+class InitListExprPostOrderVisitor
+ : public ExpectedLocationVisitor<InitListExprPostOrderVisitor> {
+public:
+ bool shouldTraversePostOrder() const { return true; }
+
+ bool VisitInitListExpr(InitListExpr *ILE) {
+ Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart());
+ return true;
+ }
+};
+
+TEST(RecursiveASTVisitor, InitListExprIsPostOrderVisitedTwice) {
+ InitListExprPostOrderVisitor Visitor;
+ Visitor.ExpectMatch("syntactic", 2, 21);
+ Visitor.ExpectMatch("semantic", 2, 21);
+ EXPECT_TRUE(Visitor.runOver("struct S { int x; };\n"
+ "static struct S s = {.x = 0};\n",
+ InitListExprPostOrderVisitor::Lang_C));
+}
+
+} // end anonymous namespace
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp b/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp
new file mode 100644
index 000000000000..f9d5ef69e098
--- /dev/null
+++ b/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp
@@ -0,0 +1,40 @@
+//===- unittest/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestVisitor.h"
+
+using namespace clang;
+
+namespace {
+
+class InitListExprPostOrderNoQueueVisitor
+ : public ExpectedLocationVisitor<InitListExprPostOrderNoQueueVisitor> {
+public:
+ bool shouldTraversePostOrder() const { return true; }
+
+ bool TraverseInitListExpr(InitListExpr *ILE) {
+ return ExpectedLocationVisitor::TraverseInitListExpr(ILE);
+ }
+
+ bool VisitInitListExpr(InitListExpr *ILE) {
+ Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart());
+ return true;
+ }
+};
+
+TEST(RecursiveASTVisitor, InitListExprIsPostOrderNoQueueVisitedTwice) {
+ InitListExprPostOrderNoQueueVisitor Visitor;
+ Visitor.ExpectMatch("syntactic", 2, 21);
+ Visitor.ExpectMatch("semantic", 2, 21);
+ EXPECT_TRUE(Visitor.runOver("struct S { int x; };\n"
+ "static struct S s = {.x = 0};\n",
+ InitListExprPostOrderNoQueueVisitor::Lang_C));
+}
+
+} // end anonymous namespace
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp b/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp
new file mode 100644
index 000000000000..f2036e232c01
--- /dev/null
+++ b/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp
@@ -0,0 +1,36 @@
+//===- unittest/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestVisitor.h"
+
+using namespace clang;
+
+namespace {
+
+// Check to ensure that InitListExpr is visited twice, once each for the
+// syntactic and semantic form.
+class InitListExprPreOrderVisitor
+ : public ExpectedLocationVisitor<InitListExprPreOrderVisitor> {
+public:
+ bool VisitInitListExpr(InitListExpr *ILE) {
+ Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart());
+ return true;
+ }
+};
+
+TEST(RecursiveASTVisitor, InitListExprIsPreOrderVisitedTwice) {
+ InitListExprPreOrderVisitor Visitor;
+ Visitor.ExpectMatch("syntactic", 2, 21);
+ Visitor.ExpectMatch("semantic", 2, 21);
+ EXPECT_TRUE(Visitor.runOver("struct S { int x; };\n"
+ "static struct S s = {.x = 0};\n",
+ InitListExprPreOrderVisitor::Lang_C));
+}
+
+} // end anonymous namespace
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp b/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp
new file mode 100644
index 000000000000..064cd74390b4
--- /dev/null
+++ b/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp
@@ -0,0 +1,38 @@
+//===- unittest/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestVisitor.h"
+
+using namespace clang;
+
+namespace {
+
+class InitListExprPreOrderNoQueueVisitor
+ : public ExpectedLocationVisitor<InitListExprPreOrderNoQueueVisitor> {
+public:
+ bool TraverseInitListExpr(InitListExpr *ILE) {
+ return ExpectedLocationVisitor::TraverseInitListExpr(ILE);
+ }
+
+ bool VisitInitListExpr(InitListExpr *ILE) {
+ Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart());
+ return true;
+ }
+};
+
+TEST(RecursiveASTVisitor, InitListExprIsPreOrderNoQueueVisitedTwice) {
+ InitListExprPreOrderNoQueueVisitor Visitor;
+ Visitor.ExpectMatch("syntactic", 2, 21);
+ Visitor.ExpectMatch("semantic", 2, 21);
+ EXPECT_TRUE(Visitor.runOver("struct S { int x; };\n"
+ "static struct S s = {.x = 0};\n",
+ InitListExprPreOrderNoQueueVisitor::Lang_C));
+}
+
+} // end anonymous namespace
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/IntegerLiteral.cpp b/unittests/Tooling/RecursiveASTVisitorTests/IntegerLiteral.cpp
new file mode 100644
index 000000000000..218f7e0c2df6
--- /dev/null
+++ b/unittests/Tooling/RecursiveASTVisitorTests/IntegerLiteral.cpp
@@ -0,0 +1,33 @@
+//===- unittest/Tooling/RecursiveASTVisitorTests/IntegerLiteral.cpp -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestVisitor.h"
+
+using namespace clang;
+
+namespace {
+
+// Check to ensure that implicit default argument expressions are visited.
+class IntegerLiteralVisitor
+ : public ExpectedLocationVisitor<IntegerLiteralVisitor> {
+public:
+ bool VisitIntegerLiteral(const IntegerLiteral *IL) {
+ Match("literal", IL->getLocation());
+ return true;
+ }
+};
+
+TEST(RecursiveASTVisitor, DefaultArgumentsAreVisited) {
+ IntegerLiteralVisitor Visitor;
+ Visitor.ExpectMatch("literal", 1, 15, 2);
+ EXPECT_TRUE(Visitor.runOver("int f(int i = 1);\n"
+ "static int k = f();\n"));
+}
+
+} // end anonymous namespace
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/LambdaDefaultCapture.cpp b/unittests/Tooling/RecursiveASTVisitorTests/LambdaDefaultCapture.cpp
new file mode 100644
index 000000000000..c3f8e4f41943
--- /dev/null
+++ b/unittests/Tooling/RecursiveASTVisitorTests/LambdaDefaultCapture.cpp
@@ -0,0 +1,35 @@
+//===- unittest/Tooling/RecursiveASTVisitorTests/LambdaDefaultCapture.cpp -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestVisitor.h"
+
+using namespace clang;
+
+namespace {
+
+// Matches the (optional) capture-default of a lambda-introducer.
+class LambdaDefaultCaptureVisitor
+ : public ExpectedLocationVisitor<LambdaDefaultCaptureVisitor> {
+public:
+ bool VisitLambdaExpr(LambdaExpr *Lambda) {
+ if (Lambda->getCaptureDefault() != LCD_None) {
+ Match("", Lambda->getCaptureDefaultLoc());
+ }
+ return true;
+ }
+};
+
+TEST(RecursiveASTVisitor, HasCaptureDefaultLoc) {
+ LambdaDefaultCaptureVisitor Visitor;
+ Visitor.ExpectMatch("", 1, 20);
+ EXPECT_TRUE(Visitor.runOver("void f() { int a; [=]{a;}; }",
+ LambdaDefaultCaptureVisitor::Lang_CXX11));
+}
+
+} // end anonymous namespace
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp b/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp
new file mode 100644
index 000000000000..80aeb43528c4
--- /dev/null
+++ b/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp
@@ -0,0 +1,63 @@
+//===- unittest/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestVisitor.h"
+#include <stack>
+
+using namespace clang;
+
+namespace {
+
+class LambdaExprVisitor : public ExpectedLocationVisitor<LambdaExprVisitor> {
+public:
+ bool VisitLambdaExpr(LambdaExpr *Lambda) {
+ PendingBodies.push(Lambda);
+ Match("", Lambda->getIntroducerRange().getBegin());
+ return true;
+ }
+ /// For each call to VisitLambdaExpr, we expect a subsequent call (with
+ /// proper nesting) to TraverseLambdaBody.
+ bool TraverseLambdaBody(LambdaExpr *Lambda) {
+ EXPECT_FALSE(PendingBodies.empty());
+ EXPECT_EQ(PendingBodies.top(), Lambda);
+ PendingBodies.pop();
+ return TraverseStmt(Lambda->getBody());
+ }
+ /// Determine whether TraverseLambdaBody has been called for every call to
+ /// VisitLambdaExpr.
+ bool allBodiesHaveBeenTraversed() const {
+ return PendingBodies.empty();
+ }
+private:
+ std::stack<LambdaExpr *> PendingBodies;
+};
+
+TEST(RecursiveASTVisitor, VisitsLambdaExpr) {
+ LambdaExprVisitor Visitor;
+ Visitor.ExpectMatch("", 1, 12);
+ EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }",
+ LambdaExprVisitor::Lang_CXX11));
+}
+
+TEST(RecursiveASTVisitor, TraverseLambdaBodyCanBeOverridden) {
+ LambdaExprVisitor Visitor;
+ EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }",
+ LambdaExprVisitor::Lang_CXX11));
+ EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed());
+}
+
+TEST(RecursiveASTVisitor, VisitsAttributedLambdaExpr) {
+ LambdaExprVisitor Visitor;
+ Visitor.ExpectMatch("", 1, 12);
+ EXPECT_TRUE(Visitor.runOver(
+ "void f() { [] () __attribute__ (( fastcall )) { return; }(); }",
+ LambdaExprVisitor::Lang_CXX14));
+}
+
+} // end anonymous namespace
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/NestedNameSpecifiers.cpp b/unittests/Tooling/RecursiveASTVisitorTests/NestedNameSpecifiers.cpp
new file mode 100644
index 000000000000..23afda6e87d0
--- /dev/null
+++ b/unittests/Tooling/RecursiveASTVisitorTests/NestedNameSpecifiers.cpp
@@ -0,0 +1,74 @@
+//===- unittest/Tooling/RecursiveASTVisitorTests/NestedNameSpecifiers.cpp -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestVisitor.h"
+
+using namespace clang;
+
+namespace {
+
+// Check to ensure that nested name specifiers are visited.
+class NestedNameSpecifiersVisitor
+ : public ExpectedLocationVisitor<NestedNameSpecifiersVisitor> {
+public:
+ bool VisitRecordTypeLoc(RecordTypeLoc RTL) {
+ if (!RTL)
+ return true;
+ Match(RTL.getDecl()->getName(), RTL.getNameLoc());
+ return true;
+ }
+
+ bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
+ if (!NNS)
+ return true;
+ if (const NamespaceDecl *ND =
+ NNS.getNestedNameSpecifier()->getAsNamespace())
+ Match(ND->getName(), NNS.getLocalBeginLoc());
+ return ExpectedLocationVisitor::TraverseNestedNameSpecifierLoc(NNS);
+ }
+};
+
+TEST(RecursiveASTVisitor,
+ NestedNameSpecifiersForTemplateSpecializationsAreVisited) {
+ StringRef Source = R"(
+namespace ns {
+struct Outer {
+ template<typename T, typename U>
+ struct Nested { };
+
+ template<typename T>
+ static T x;
+};
+}
+
+template<>
+struct ns::Outer::Nested<int, int>;
+
+template<>
+struct ns::Outer::Nested<int, int> { };
+
+template<typename T>
+struct ns::Outer::Nested<int, T> { };
+
+template<>
+int ns::Outer::x<int> = 0;
+)";
+ NestedNameSpecifiersVisitor Visitor;
+ Visitor.ExpectMatch("ns", 13, 8);
+ Visitor.ExpectMatch("ns", 16, 8);
+ Visitor.ExpectMatch("ns", 19, 8);
+ Visitor.ExpectMatch("ns", 22, 5);
+ Visitor.ExpectMatch("Outer", 13, 12);
+ Visitor.ExpectMatch("Outer", 16, 12);
+ Visitor.ExpectMatch("Outer", 19, 12);
+ Visitor.ExpectMatch("Outer", 22, 9);
+ EXPECT_TRUE(Visitor.runOver(Source, NestedNameSpecifiersVisitor::Lang_CXX14));
+}
+
+} // end anonymous namespace
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/ParenExpr.cpp b/unittests/Tooling/RecursiveASTVisitorTests/ParenExpr.cpp
new file mode 100644
index 000000000000..b6a5a18e0176
--- /dev/null
+++ b/unittests/Tooling/RecursiveASTVisitorTests/ParenExpr.cpp
@@ -0,0 +1,30 @@
+//===- unittest/Tooling/RecursiveASTVisitorTests/ParenExpr.cpp ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestVisitor.h"
+
+using namespace clang;
+
+namespace {
+
+class ParenExprVisitor : public ExpectedLocationVisitor<ParenExprVisitor> {
+public:
+ bool VisitParenExpr(ParenExpr *Parens) {
+ Match("", Parens->getExprLoc());
+ return true;
+ }
+};
+
+TEST(RecursiveASTVisitor, VisitsParensDuringDataRecursion) {
+ ParenExprVisitor Visitor;
+ Visitor.ExpectMatch("", 1, 9);
+ EXPECT_TRUE(Visitor.runOver("int k = (4) + 9;\n"));
+}
+
+} // end anonymous namespace
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp b/unittests/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp
new file mode 100644
index 000000000000..0c9cbf2eb4a8
--- /dev/null
+++ b/unittests/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp
@@ -0,0 +1,40 @@
+//===- unittest/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestVisitor.h"
+
+using namespace clang;
+
+namespace {
+
+class TemplateArgumentLocTraverser
+ : public ExpectedLocationVisitor<TemplateArgumentLocTraverser> {
+public:
+ bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) {
+ std::string ArgStr;
+ llvm::raw_string_ostream Stream(ArgStr);
+ const TemplateArgument &Arg = ArgLoc.getArgument();
+
+ Arg.print(Context->getPrintingPolicy(), Stream);
+ Match(Stream.str(), ArgLoc.getLocation());
+ return ExpectedLocationVisitor<TemplateArgumentLocTraverser>::
+ TraverseTemplateArgumentLoc(ArgLoc);
+ }
+};
+
+TEST(RecursiveASTVisitor, VisitsClassTemplateTemplateParmDefaultArgument) {
+ TemplateArgumentLocTraverser Visitor;
+ Visitor.ExpectMatch("X", 2, 40);
+ EXPECT_TRUE(Visitor.runOver(
+ "template<typename T> class X;\n"
+ "template<template <typename> class T = X> class Y;\n"
+ "template<template <typename> class T> class Y {};\n"));
+}
+
+} // end anonymous namespace
diff --git a/unittests/Tooling/RefactoringActionRulesTest.cpp b/unittests/Tooling/RefactoringActionRulesTest.cpp
index f0b6466fec46..e9a12deb3f0e 100644
--- a/unittests/Tooling/RefactoringActionRulesTest.cpp
+++ b/unittests/Tooling/RefactoringActionRulesTest.cpp
@@ -97,7 +97,7 @@ TEST_F(RefactoringActionRulesTest, MyFirstRefactoringRule) {
auto Rule =
createRefactoringActionRule<ReplaceAWithB>(SelectionRequirement());
- // When the requirements are satisifed, the rule's function must be invoked.
+ // When the requirements are satisfied, the rule's function must be invoked.
{
RefactoringRuleContext RefContext(Context.Sources);
SourceLocation Cursor =
diff --git a/unittests/Tooling/RefactoringTest.cpp b/unittests/Tooling/RefactoringTest.cpp
index 41836f11ee29..fcd2aa593730 100644
--- a/unittests/Tooling/RefactoringTest.cpp
+++ b/unittests/Tooling/RefactoringTest.cpp
@@ -1035,7 +1035,7 @@ TEST(DeduplicateByFileTest, PathsWithDots) {
llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> VFS(
new vfs::InMemoryFileSystem());
FileManager FileMgr(FileSystemOptions(), VFS);
-#if !defined(LLVM_ON_WIN32)
+#if !defined(_WIN32)
StringRef Path1 = "a/b/.././c.h";
StringRef Path2 = "a/c.h";
#else
@@ -1056,7 +1056,7 @@ TEST(DeduplicateByFileTest, PathWithDotSlash) {
llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> VFS(
new vfs::InMemoryFileSystem());
FileManager FileMgr(FileSystemOptions(), VFS);
-#if !defined(LLVM_ON_WIN32)
+#if !defined(_WIN32)
StringRef Path1 = "./a/b/c.h";
StringRef Path2 = "a/b/c.h";
#else
@@ -1077,7 +1077,7 @@ TEST(DeduplicateByFileTest, NonExistingFilePath) {
llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> VFS(
new vfs::InMemoryFileSystem());
FileManager FileMgr(FileSystemOptions(), VFS);
-#if !defined(LLVM_ON_WIN32)
+#if !defined(_WIN32)
StringRef Path1 = "./a/b/c.h";
StringRef Path2 = "a/b/c.h";
#else
diff --git a/unittests/Tooling/ToolingTest.cpp b/unittests/Tooling/ToolingTest.cpp
index 891907a4d081..0a5150a31b7b 100644
--- a/unittests/Tooling/ToolingTest.cpp
+++ b/unittests/Tooling/ToolingTest.cpp
@@ -17,7 +17,6 @@
#include "clang/Tooling/CompilationDatabase.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/Config/llvm-config.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
@@ -216,7 +215,7 @@ struct VerifyEndCallback : public SourceFileCallbacks {
bool Matched;
};
-#if !defined(LLVM_ON_WIN32)
+#if !defined(_WIN32)
TEST(newFrontendActionFactory, InjectsSourceFileCallbacks) {
VerifyEndCallback EndCallback;
@@ -319,8 +318,8 @@ TEST(runToolOnCode, TestSkipFunctionBody) {
TEST(runToolOnCodeWithArgs, TestNoDepFile) {
llvm::SmallString<32> DepFilePath;
- ASSERT_FALSE(
- llvm::sys::fs::createTemporaryFile("depfile", "d", DepFilePath));
+ ASSERT_FALSE(llvm::sys::fs::getPotentiallyUniqueTempFileName("depfile", "d",
+ DepFilePath));
std::vector<std::string> Args;
Args.push_back("-MMD");
Args.push_back("-MT");
@@ -402,6 +401,24 @@ TEST(ClangToolTest, ArgumentAdjusters) {
EXPECT_FALSE(Found);
}
+TEST(ClangToolTest, BaseVirtualFileSystemUsage) {
+ FixedCompilationDatabase Compilations("/", std::vector<std::string>());
+ llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem(
+ new vfs::OverlayFileSystem(vfs::getRealFileSystem()));
+ llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
+ new vfs::InMemoryFileSystem);
+ OverlayFileSystem->pushOverlay(InMemoryFileSystem);
+
+ InMemoryFileSystem->addFile(
+ "a.cpp", 0, llvm::MemoryBuffer::getMemBuffer("int main() {}"));
+
+ ClangTool Tool(Compilations, std::vector<std::string>(1, "a.cpp"),
+ std::make_shared<PCHContainerOperations>(), OverlayFileSystem);
+ std::unique_ptr<FrontendActionFactory> Action(
+ newFrontendActionFactory<SyntaxOnlyAction>());
+ EXPECT_EQ(0, Tool.run(Action.get()));
+}
+
// Check getClangStripDependencyFileAdjuster doesn't strip args after -MD/-MMD.
TEST(ClangToolTest, StripDependencyFileAdjuster) {
FixedCompilationDatabase Compilations("/", {"-MD", "-c", "-MMD", "-w"});
@@ -513,7 +530,7 @@ TEST(addTargetAndModeForProgramName, IgnoresExistingMode) {
ArgsAlt);
}
-#ifndef LLVM_ON_WIN32
+#ifndef _WIN32
TEST(ClangToolTest, BuildASTs) {
FixedCompilationDatabase Compilations("/", std::vector<std::string>());
diff --git a/unittests/libclang/LibclangTest.cpp b/unittests/libclang/LibclangTest.cpp
index f2a96d6be6c1..6fddcb2cbf26 100644
--- a/unittests/libclang/LibclangTest.cpp
+++ b/unittests/libclang/LibclangTest.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "clang-c/Index.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
@@ -466,15 +467,17 @@ public:
unsigned NumDiagnostics = clang_getNumDiagnostics(ClangTU);
for (unsigned i = 0; i < NumDiagnostics; ++i) {
auto Diag = clang_getDiagnostic(ClangTU, i);
- DEBUG(llvm::dbgs() << clang_getCString(clang_formatDiagnostic(
- Diag, clang_defaultDiagnosticDisplayOptions())) << "\n");
+ LLVM_DEBUG(llvm::dbgs()
+ << clang_getCString(clang_formatDiagnostic(
+ Diag, clang_defaultDiagnosticDisplayOptions()))
+ << "\n");
clang_disposeDiagnostic(Diag);
}
}
bool ReparseTU(unsigned num_unsaved_files, CXUnsavedFile* unsaved_files) {
if (clang_reparseTranslationUnit(ClangTU, num_unsaved_files, unsaved_files,
clang_defaultReparseOptions(ClangTU))) {
- DEBUG(llvm::dbgs() << "Reparse failed\n");
+ LLVM_DEBUG(llvm::dbgs() << "Reparse failed\n");
return false;
}
DisplayDiagnostics();
@@ -482,6 +485,21 @@ public:
}
};
+TEST_F(LibclangReparseTest, FileName) {
+ std::string CppName = "main.cpp";
+ WriteFile(CppName, "int main() {}");
+ ClangTU = clang_parseTranslationUnit(Index, CppName.c_str(), nullptr, 0,
+ nullptr, 0, TUFlags);
+ CXFile cxf = clang_getFile(ClangTU, CppName.c_str());
+
+ CXString cxname = clang_getFileName(cxf);
+ ASSERT_STREQ(clang_getCString(cxname), CppName.c_str());
+ clang_disposeString(cxname);
+
+ cxname = clang_File_tryGetRealPathName(cxf);
+ ASSERT_TRUE(llvm::StringRef(clang_getCString(cxname)).endswith("main.cpp"));
+ clang_disposeString(cxname);
+}
TEST_F(LibclangReparseTest, Reparse) {
const char *HeaderTop = "#ifndef H\n#define H\nstruct Foo { int bar;";
@@ -572,3 +590,178 @@ TEST_F(LibclangReparseTest, clang_parseTranslationUnit2FullArgv) {
EXPECT_EQ(0U, clang_getNumDiagnostics(ClangTU));
DisplayDiagnostics();
}
+
+class LibclangPrintingPolicyTest : public LibclangParseTest {
+public:
+ CXPrintingPolicy Policy = nullptr;
+
+ void SetUp() override {
+ LibclangParseTest::SetUp();
+ std::string File = "file.cpp";
+ WriteFile(File, "int i;\n");
+ ClangTU = clang_parseTranslationUnit(Index, File.c_str(), nullptr, 0,
+ nullptr, 0, TUFlags);
+ CXCursor TUCursor = clang_getTranslationUnitCursor(ClangTU);
+ Policy = clang_getCursorPrintingPolicy(TUCursor);
+ }
+ void TearDown() override {
+ clang_PrintingPolicy_dispose(Policy);
+ LibclangParseTest::TearDown();
+ }
+};
+
+TEST_F(LibclangPrintingPolicyTest, SetAndGetProperties) {
+ for (unsigned Value = 0; Value < 2; ++Value) {
+ for (int I = 0; I < CXPrintingPolicy_LastProperty; ++I) {
+ auto Property = static_cast<enum CXPrintingPolicyProperty>(I);
+
+ clang_PrintingPolicy_setProperty(Policy, Property, Value);
+ EXPECT_EQ(Value, clang_PrintingPolicy_getProperty(Policy, Property));
+ }
+ }
+}
+
+TEST_F(LibclangReparseTest, PreprocessorSkippedRanges) {
+ std::string Header = "header.h", Main = "main.cpp";
+ WriteFile(Header,
+ "#ifdef MANGOS\n"
+ "printf(\"mmm\");\n"
+ "#endif");
+ WriteFile(Main,
+ "#include \"header.h\"\n"
+ "#ifdef GUAVA\n"
+ "#endif\n"
+ "#ifdef KIWIS\n"
+ "printf(\"mmm!!\");\n"
+ "#endif");
+
+ for (int i = 0; i != 3; ++i) {
+ unsigned flags = TUFlags | CXTranslationUnit_PrecompiledPreamble;
+ if (i == 2)
+ flags |= CXTranslationUnit_CreatePreambleOnFirstParse;
+
+ if (i != 0)
+ clang_disposeTranslationUnit(ClangTU); // dispose from previous iter
+
+ // parse once
+ ClangTU = clang_parseTranslationUnit(Index, Main.c_str(), nullptr, 0,
+ nullptr, 0, flags);
+ if (i != 0) {
+ // reparse
+ ASSERT_TRUE(ReparseTU(0, nullptr /* No unsaved files. */));
+ }
+
+ // Check all ranges are there
+ CXSourceRangeList *Ranges = clang_getAllSkippedRanges(ClangTU);
+ EXPECT_EQ(3U, Ranges->count);
+
+ CXSourceLocation cxl;
+ unsigned line;
+ cxl = clang_getRangeStart(Ranges->ranges[0]);
+ clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
+ EXPECT_EQ(1U, line);
+ cxl = clang_getRangeEnd(Ranges->ranges[0]);
+ clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
+ EXPECT_EQ(3U, line);
+
+ cxl = clang_getRangeStart(Ranges->ranges[1]);
+ clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
+ EXPECT_EQ(2U, line);
+ cxl = clang_getRangeEnd(Ranges->ranges[1]);
+ clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
+ EXPECT_EQ(3U, line);
+
+ cxl = clang_getRangeStart(Ranges->ranges[2]);
+ clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
+ EXPECT_EQ(4U, line);
+ cxl = clang_getRangeEnd(Ranges->ranges[2]);
+ clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
+ EXPECT_EQ(6U, line);
+
+ clang_disposeSourceRangeList(Ranges);
+
+ // Check obtaining ranges by each file works
+ CXFile cxf = clang_getFile(ClangTU, Header.c_str());
+ Ranges = clang_getSkippedRanges(ClangTU, cxf);
+ EXPECT_EQ(1U, Ranges->count);
+ cxl = clang_getRangeStart(Ranges->ranges[0]);
+ clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
+ EXPECT_EQ(1U, line);
+ clang_disposeSourceRangeList(Ranges);
+
+ cxf = clang_getFile(ClangTU, Main.c_str());
+ Ranges = clang_getSkippedRanges(ClangTU, cxf);
+ EXPECT_EQ(2U, Ranges->count);
+ cxl = clang_getRangeStart(Ranges->ranges[0]);
+ clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
+ EXPECT_EQ(2U, line);
+ cxl = clang_getRangeStart(Ranges->ranges[1]);
+ clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
+ EXPECT_EQ(4U, line);
+ clang_disposeSourceRangeList(Ranges);
+ }
+}
+
+class LibclangSerializationTest : public LibclangParseTest {
+public:
+ bool SaveAndLoadTU(const std::string &Filename) {
+ unsigned options = clang_defaultSaveOptions(ClangTU);
+ if (clang_saveTranslationUnit(ClangTU, Filename.c_str(), options) !=
+ CXSaveError_None) {
+ LLVM_DEBUG(llvm::dbgs() << "Saving failed\n");
+ return false;
+ }
+
+ clang_disposeTranslationUnit(ClangTU);
+
+ ClangTU = clang_createTranslationUnit(Index, Filename.c_str());
+
+ if (!ClangTU) {
+ LLVM_DEBUG(llvm::dbgs() << "Loading failed\n");
+ return false;
+ }
+
+ return true;
+ }
+};
+
+TEST_F(LibclangSerializationTest, TokenKindsAreCorrectAfterLoading) {
+ // Ensure that "class" is recognized as a keyword token after serializing
+ // and reloading the AST, as it is not a keyword for the default LangOptions.
+ std::string HeaderName = "test.h";
+ WriteFile(HeaderName, "enum class Something {};");
+
+ const char *Argv[] = {"-xc++-header", "-std=c++11"};
+
+ ClangTU = clang_parseTranslationUnit(Index, HeaderName.c_str(), Argv,
+ sizeof(Argv) / sizeof(Argv[0]), nullptr,
+ 0, TUFlags);
+
+ auto CheckTokenKinds = [=]() {
+ CXSourceRange Range =
+ clang_getCursorExtent(clang_getTranslationUnitCursor(ClangTU));
+
+ CXToken *Tokens;
+ unsigned int NumTokens;
+ clang_tokenize(ClangTU, Range, &Tokens, &NumTokens);
+
+ ASSERT_EQ(6u, NumTokens);
+ EXPECT_EQ(CXToken_Keyword, clang_getTokenKind(Tokens[0]));
+ EXPECT_EQ(CXToken_Keyword, clang_getTokenKind(Tokens[1]));
+ EXPECT_EQ(CXToken_Identifier, clang_getTokenKind(Tokens[2]));
+ EXPECT_EQ(CXToken_Punctuation, clang_getTokenKind(Tokens[3]));
+ EXPECT_EQ(CXToken_Punctuation, clang_getTokenKind(Tokens[4]));
+ EXPECT_EQ(CXToken_Punctuation, clang_getTokenKind(Tokens[5]));
+
+ clang_disposeTokens(ClangTU, Tokens, NumTokens);
+ };
+
+ CheckTokenKinds();
+
+ std::string ASTName = "test.ast";
+ WriteFile(ASTName, "");
+
+ ASSERT_TRUE(SaveAndLoadTU(ASTName));
+
+ CheckTokenKinds();
+}
diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp
index b0e2ddd91362..0bf7a07cf6e1 100644
--- a/utils/TableGen/ClangAttrEmitter.cpp
+++ b/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";
@@ -3168,7 +3307,7 @@ static std::string GenerateAppertainsTo(const Record &Attr, raw_ostream &OS) {
// name of that check to the caller.
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 (";
for (auto I = Subjects.begin(), E = Subjects.end(); I != E; ++I) {
@@ -3240,7 +3379,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 +3418,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 +3451,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 +3488,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 +3511,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 +3561,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 +3586,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 +3615,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 +3662,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 +3734,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 +3896,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 +3950,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/utils/TableGen/ClangCommentHTMLNamedCharacterReferenceEmitter.cpp b/utils/TableGen/ClangCommentHTMLNamedCharacterReferenceEmitter.cpp
index bfdb268b63ba..bea97ae13289 100644
--- a/utils/TableGen/ClangCommentHTMLNamedCharacterReferenceEmitter.cpp
+++ b/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/utils/TableGen/ClangDiagnosticsEmitter.cpp b/utils/TableGen/ClangDiagnosticsEmitter.cpp
index d9d99e0bb002..6bfb3f9f61f5 100644
--- a/utils/TableGen/ClangDiagnosticsEmitter.cpp
+++ b/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/utils/TableGen/ClangOptionDocEmitter.cpp b/utils/TableGen/ClangOptionDocEmitter.cpp
index 59314510e0ad..7fe487e54698 100644
--- a/utils/TableGen/ClangOptionDocEmitter.cpp
+++ b/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/utils/TableGen/ClangSACheckersEmitter.cpp b/utils/TableGen/ClangSACheckersEmitter.cpp
index 8f3de0b67d77..4fda8e47e4a8 100644
--- a/utils/TableGen/ClangSACheckersEmitter.cpp
+++ b/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/utils/TableGen/NeonEmitter.cpp b/utils/TableGen/NeonEmitter.cpp
index 8117d2f4a232..eca03a5892e2 100644
--- a/utils/TableGen/NeonEmitter.cpp
+++ b/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/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp
index 840b330a732c..a2ba131628f1 100644
--- a/utils/TableGen/TableGen.cpp
+++ b/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/utils/TableGen/TableGenBackends.h b/utils/TableGen/TableGenBackends.h
index 342c889ca47a..706e812ae874 100644
--- a/utils/TableGen/TableGenBackends.h
+++ b/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/utils/analyzer/CmpRuns.py b/utils/analyzer/CmpRuns.py
index 2c0ed6aae3a2..1b8fe7bd698d 100755
--- a/utils/analyzer/CmpRuns.py
+++ b/utils/analyzer/CmpRuns.py
@@ -26,9 +26,25 @@ Usage:
"""
+from collections import defaultdict
+
+from math import log
+from optparse import OptionParser
+import json
import os
import plistlib
+import re
+import sys
+
+STATS_REGEXP = re.compile(r"Statistics: (\{.+\})", re.MULTILINE | re.DOTALL)
+class Colors:
+ """
+ Color for terminal highlight.
+ """
+ RED = '\x1b[2;30;41m'
+ GREEN = '\x1b[6;30;42m'
+ CLEAR = '\x1b[0m'
# Information about analysis run:
# path - the analysis output directory
@@ -47,6 +63,7 @@ class AnalysisDiagnostic:
self._loc = self._data['location']
self._report = report
self._htmlReport = htmlReport
+ self._reportSize = len(self._data['path'])
def getFileName(self):
root = self._report.run.root
@@ -61,6 +78,9 @@ class AnalysisDiagnostic:
def getColumn(self):
return self._loc['col']
+ def getPathLength(self):
+ return self._reportSize
+
def getCategory(self):
return self._data['category']
@@ -81,9 +101,15 @@ class AnalysisDiagnostic:
return os.path.join(self._report.run.path, self._htmlReport)
def getReadableName(self):
- return '%s:%d:%d, %s: %s' % (self.getFileName(), self.getLine(),
- self.getColumn(), self.getCategory(),
- self.getDescription())
+ if 'issue_context' in self._data:
+ funcnamePostfix = "#" + self._data['issue_context']
+ else:
+ funcnamePostfix = ""
+ return '%s%s:%d:%d, %s: %s' % (self.getFileName(),
+ funcnamePostfix,
+ self.getLine(),
+ self.getColumn(), self.getCategory(),
+ self.getDescription())
# Note, the data format is not an API and may change from one analyzer
# version to another.
@@ -91,13 +117,6 @@ class AnalysisDiagnostic:
return self._data
-class CmpOptions:
- def __init__(self, verboseLog=None, rootA="", rootB=""):
- self.rootA = rootA
- self.rootB = rootB
- self.verboseLog = verboseLog
-
-
class AnalysisReport:
def __init__(self, run, files):
self.run = run
@@ -114,12 +133,16 @@ class AnalysisRun:
# Cumulative list of all diagnostics from all the reports.
self.diagnostics = []
self.clang_version = None
+ self.stats = []
def getClangVersion(self):
return self.clang_version
def readSingleFile(self, p, deleteEmpty):
data = plistlib.readPlist(p)
+ if 'statistics' in data:
+ self.stats.append(json.loads(data['statistics']))
+ data.pop('statistics')
# We want to retrieve the clang version even if there are no
# reports. Assume that all reports were created using the same
@@ -193,19 +216,20 @@ def cmpAnalysisDiagnostic(d):
return d.getIssueIdentifier()
-def compareResults(A, B):
+def compareResults(A, B, opts):
"""
compareResults - Generate a relation from diagnostics in run A to
diagnostics in run B.
- The result is the relation as a list of triples (a, b, confidence) where
- each element {a,b} is None or an element from the respective run, and
- confidence is a measure of the match quality (where 0 indicates equality,
- and None is used if either element is None).
+ The result is the relation as a list of triples (a, b) where
+ each element {a,b} is None or a matching element from the respective run
"""
res = []
+ # Map size_before -> size_after
+ path_difference_data = []
+
# Quickly eliminate equal elements.
neqA = []
neqB = []
@@ -217,7 +241,18 @@ def compareResults(A, B):
a = eltsA.pop()
b = eltsB.pop()
if (a.getIssueIdentifier() == b.getIssueIdentifier()):
- res.append((a, b, 0))
+ if a.getPathLength() != b.getPathLength():
+ if opts.relative_path_histogram:
+ path_difference_data.append(
+ float(a.getPathLength()) / b.getPathLength())
+ elif opts.relative_log_path_histogram:
+ path_difference_data.append(
+ log(float(a.getPathLength()) / b.getPathLength()))
+ elif opts.absolute_path_histogram:
+ path_difference_data.append(
+ a.getPathLength() - b.getPathLength())
+
+ res.append((a, b))
elif a.getIssueIdentifier() > b.getIssueIdentifier():
eltsB.append(b)
neqA.append(a)
@@ -234,17 +269,65 @@ def compareResults(A, B):
# in any way on the diagnostic format.
for a in neqA:
- res.append((a, None, None))
+ res.append((a, None))
for b in neqB:
- res.append((None, b, None))
+ res.append((None, b))
- return res
+ if opts.relative_log_path_histogram or opts.relative_path_histogram or \
+ opts.absolute_path_histogram:
+ from matplotlib import pyplot
+ pyplot.hist(path_difference_data, bins=100)
+ pyplot.show()
+ return res
-def dumpScanBuildResultsDiff(dirA, dirB, opts, deleteEmpty=True):
+def deriveStats(results):
+ # Assume all keys are the same in each statistics bucket.
+ combined_data = defaultdict(list)
+ for stat in results.stats:
+ for key, value in stat.iteritems():
+ combined_data[key].append(value)
+ combined_stats = {}
+ for key, values in combined_data.iteritems():
+ combined_stats[str(key)] = {
+ "max": max(values),
+ "min": min(values),
+ "mean": sum(values) / len(values),
+ "median": sorted(values)[len(values) / 2],
+ "total": sum(values)
+ }
+ return combined_stats
+
+
+def compareStats(resultsA, resultsB):
+ statsA = deriveStats(resultsA)
+ statsB = deriveStats(resultsB)
+ keys = sorted(statsA.keys())
+ for key in keys:
+ print key
+ for kkey in statsA[key]:
+ valA = float(statsA[key][kkey])
+ valB = float(statsB[key][kkey])
+ report = "%.3f -> %.3f" % (valA, valB)
+ # Only apply highlighting when writing to TTY and it's not Windows
+ if sys.stdout.isatty() and os.name != 'nt':
+ if valB != 0:
+ ratio = (valB - valA) / valB
+ if ratio < -0.2:
+ report = Colors.GREEN + report + Colors.CLEAR
+ elif ratio > 0.2:
+ report = Colors.RED + report + Colors.CLEAR
+ print "\t %s %s" % (kkey, report)
+
+def dumpScanBuildResultsDiff(dirA, dirB, opts, deleteEmpty=True,
+ Stdout=sys.stdout):
# Load the run results.
resultsA = loadResults(dirA, opts, opts.rootA, deleteEmpty)
resultsB = loadResults(dirB, opts, opts.rootB, deleteEmpty)
+ if resultsA.stats:
+ compareStats(resultsA, resultsB)
+ if opts.stats_only:
+ return
# Open the verbose log, if given.
if opts.verboseLog:
@@ -252,47 +335,41 @@ def dumpScanBuildResultsDiff(dirA, dirB, opts, deleteEmpty=True):
else:
auxLog = None
- diff = compareResults(resultsA, resultsB)
+ diff = compareResults(resultsA, resultsB, opts)
foundDiffs = 0
+ totalAdded = 0
+ totalRemoved = 0
for res in diff:
- a, b, confidence = res
+ a, b = res
if a is None:
- print "ADDED: %r" % b.getReadableName()
+ Stdout.write("ADDED: %r\n" % b.getReadableName())
foundDiffs += 1
+ totalAdded += 1
if auxLog:
- print >>auxLog, ("('ADDED', %r, %r)" % (b.getReadableName(),
- b.getReport()))
+ auxLog.write("('ADDED', %r, %r)\n" % (b.getReadableName(),
+ b.getReport()))
elif b is None:
- print "REMOVED: %r" % a.getReadableName()
- foundDiffs += 1
- if auxLog:
- print >>auxLog, ("('REMOVED', %r, %r)" % (a.getReadableName(),
- a.getReport()))
- elif confidence:
- print "CHANGED: %r to %r" % (a.getReadableName(),
- b.getReadableName())
+ Stdout.write("REMOVED: %r\n" % a.getReadableName())
foundDiffs += 1
+ totalRemoved += 1
if auxLog:
- print >>auxLog, ("('CHANGED', %r, %r, %r, %r)"
- % (a.getReadableName(),
- b.getReadableName(),
- a.getReport(),
- b.getReport()))
+ auxLog.write("('REMOVED', %r, %r)\n" % (a.getReadableName(),
+ a.getReport()))
else:
pass
TotalReports = len(resultsB.diagnostics)
- print "TOTAL REPORTS: %r" % TotalReports
- print "TOTAL DIFFERENCES: %r" % foundDiffs
+ Stdout.write("TOTAL REPORTS: %r\n" % TotalReports)
+ Stdout.write("TOTAL ADDED: %r\n" % totalAdded)
+ Stdout.write("TOTAL REMOVED: %r\n" % totalRemoved)
if auxLog:
- print >>auxLog, "('TOTAL NEW REPORTS', %r)" % TotalReports
- print >>auxLog, "('TOTAL DIFFERENCES', %r)" % foundDiffs
+ auxLog.write("('TOTAL NEW REPORTS', %r)\n" % TotalReports)
+ auxLog.write("('TOTAL DIFFERENCES', %r)\n" % foundDiffs)
+ auxLog.close()
return foundDiffs, len(resultsA.diagnostics), len(resultsB.diagnostics)
-
-def main():
- from optparse import OptionParser
+def generate_option_parser():
parser = OptionParser("usage: %prog [options] [dir A] [dir B]")
parser.add_option("", "--rootA", dest="rootA",
help="Prefix to ignore on source files for directory A",
@@ -302,9 +379,31 @@ def main():
action="store", type=str, default="")
parser.add_option("", "--verbose-log", dest="verboseLog",
help="Write additional information to LOG \
- [default=None]",
+ [default=None]",
action="store", type=str, default=None,
metavar="LOG")
+ parser.add_option("--relative-path-differences-histogram",
+ action="store_true", dest="relative_path_histogram",
+ default=False,
+ help="Show histogram of relative paths differences. \
+ Requires matplotlib")
+ parser.add_option("--relative-log-path-differences-histogram",
+ action="store_true", dest="relative_log_path_histogram",
+ default=False,
+ help="Show histogram of log relative paths differences. \
+ Requires matplotlib")
+ parser.add_option("--absolute-path-differences-histogram",
+ action="store_true", dest="absolute_path_histogram",
+ default=False,
+ help="Show histogram of absolute paths differences. \
+ Requires matplotlib")
+ parser.add_option("--stats-only", action="store_true", dest="stats_only",
+ default=False, help="Only show statistics on reports")
+ return parser
+
+
+def main():
+ parser = generate_option_parser()
(opts, args) = parser.parse_args()
if len(args) != 2:
diff --git a/utils/analyzer/SATestAdd.py b/utils/analyzer/SATestAdd.py
index 4c3e35cdcb5d..041b24409fe3 100644
--- a/utils/analyzer/SATestAdd.py
+++ b/utils/analyzer/SATestAdd.py
@@ -32,11 +32,11 @@ the Repository Directory.
(e.g., to adapt to newer version of clang)
that should be applied to CachedSource
before analysis. To construct this patch,
- run the the download script to download
+ run the download script to download
the project to CachedSource, copy the
CachedSource to another directory (for
example, PatchedSource) and make any
- needed modifications to the the copied
+ needed modifications to the copied
source.
Then run:
diff -ur CachedSource PatchedSource \
diff --git a/utils/analyzer/SATestBuild.py b/utils/analyzer/SATestBuild.py
index 60c8796e338f..4da025aa53b3 100644
--- a/utils/analyzer/SATestBuild.py
+++ b/utils/analyzer/SATestBuild.py
@@ -45,32 +45,55 @@ variable. It should contain a comma separated list.
import CmpRuns
import SATestUtils
-import os
+from subprocess import CalledProcessError, check_call
+import argparse
import csv
-import sys
import glob
+import logging
import math
+import multiprocessing
+import os
+import plistlib
import shutil
+import sys
+import threading
import time
-import plistlib
-import argparse
-from subprocess import check_call, CalledProcessError
-import multiprocessing
+import Queue
#------------------------------------------------------------------------------
# Helper functions.
#------------------------------------------------------------------------------
+Local = threading.local()
+Local.stdout = sys.stdout
+Local.stderr = sys.stderr
+logging.basicConfig(
+ level=logging.DEBUG,
+ format='%(asctime)s:%(levelname)s:%(name)s: %(message)s')
-sys.stdout = SATestUtils.flushfile(sys.stdout)
+class StreamToLogger(object):
+ def __init__(self, logger, log_level=logging.INFO):
+ self.logger = logger
+ self.log_level = log_level
+
+ def write(self, buf):
+ # Rstrip in order not to write an extra newline.
+ self.logger.log(self.log_level, buf.rstrip())
+
+ def flush(self):
+ pass
+
+ def fileno(self):
+ return 0
def getProjectMapPath():
ProjectMapPath = os.path.join(os.path.abspath(os.curdir),
ProjectMapFile)
if not os.path.exists(ProjectMapPath):
- print "Error: Cannot find the Project Map file " + ProjectMapPath +\
- "\nRunning script for the wrong directory?"
+ Local.stdout.write("Error: Cannot find the Project Map file "
+ + ProjectMapPath
+ + "\nRunning script for the wrong directory?\n")
sys.exit(1)
return ProjectMapPath
@@ -100,7 +123,7 @@ if not Clang:
sys.exit(1)
# Number of jobs.
-Jobs = int(math.ceil(multiprocessing.cpu_count() * 0.75))
+MaxJobs = int(math.ceil(multiprocessing.cpu_count() * 0.75))
# Project map stores info about all the "registered" projects.
ProjectMapFile = "projectMap.csv"
@@ -113,6 +136,9 @@ CleanupScript = "cleanup_run_static_analyzer.sh"
# This is a file containing commands for scan-build.
BuildScript = "run_static_analyzer.cmd"
+# A comment in a build script which disables wrapping.
+NoPrefixCmd = "#NOPREFIX"
+
# The log file name.
LogFolderName = "Logs"
BuildLogName = "run_static_analyzer.log"
@@ -157,7 +183,7 @@ Checkers = ",".join([
"nullability"
])
-Verbose = 1
+Verbose = 0
#------------------------------------------------------------------------------
# Test harness logic.
@@ -170,7 +196,8 @@ def runCleanupScript(Dir, PBuildLogFile):
"""
Cwd = os.path.join(Dir, PatchedSourceDirName)
ScriptPath = os.path.join(Dir, CleanupScript)
- SATestUtils.runScript(ScriptPath, PBuildLogFile, Cwd)
+ SATestUtils.runScript(ScriptPath, PBuildLogFile, Cwd,
+ Stdout=Local.stdout, Stderr=Local.stderr)
def runDownloadScript(Dir, PBuildLogFile):
@@ -178,7 +205,8 @@ def runDownloadScript(Dir, PBuildLogFile):
Run the script to download the project, if it exists.
"""
ScriptPath = os.path.join(Dir, DownloadScript)
- SATestUtils.runScript(ScriptPath, PBuildLogFile, Dir)
+ SATestUtils.runScript(ScriptPath, PBuildLogFile, Dir,
+ Stdout=Local.stdout, Stderr=Local.stderr)
def downloadAndPatch(Dir, PBuildLogFile):
@@ -192,8 +220,8 @@ def downloadAndPatch(Dir, PBuildLogFile):
if not os.path.exists(CachedSourceDirPath):
runDownloadScript(Dir, PBuildLogFile)
if not os.path.exists(CachedSourceDirPath):
- print "Error: '%s' not found after download." % (
- CachedSourceDirPath)
+ Local.stderr.write("Error: '%s' not found after download.\n" % (
+ CachedSourceDirPath))
exit(1)
PatchedSourceDirPath = os.path.join(Dir, PatchedSourceDirName)
@@ -211,10 +239,10 @@ def applyPatch(Dir, PBuildLogFile):
PatchfilePath = os.path.join(Dir, PatchfileName)
PatchedSourceDirPath = os.path.join(Dir, PatchedSourceDirName)
if not os.path.exists(PatchfilePath):
- print " No local patches."
+ Local.stdout.write(" No local patches.\n")
return
- print " Applying patch."
+ Local.stdout.write(" Applying patch.\n")
try:
check_call("patch -p1 < '%s'" % (PatchfilePath),
cwd=PatchedSourceDirPath,
@@ -222,7 +250,8 @@ def applyPatch(Dir, PBuildLogFile):
stdout=PBuildLogFile,
shell=True)
except:
- print "Error: Patch failed. See %s for details." % (PBuildLogFile.name)
+ Local.stderr.write("Error: Patch failed. See %s for details.\n" % (
+ PBuildLogFile.name))
sys.exit(1)
@@ -233,7 +262,8 @@ def runScanBuild(Dir, SBOutputDir, PBuildLogFile):
"""
BuildScriptPath = os.path.join(Dir, BuildScript)
if not os.path.exists(BuildScriptPath):
- print "Error: build script is not defined: %s" % BuildScriptPath
+ Local.stderr.write(
+ "Error: build script is not defined: %s\n" % BuildScriptPath)
sys.exit(1)
AllCheckers = Checkers
@@ -247,9 +277,18 @@ def runScanBuild(Dir, SBOutputDir, PBuildLogFile):
SBOptions += "-plist-html -o '%s' " % SBOutputDir
SBOptions += "-enable-checker " + AllCheckers + " "
SBOptions += "--keep-empty "
+ AnalyzerConfig = [
+ ("stable-report-filename", "true"),
+ ("serialize-stats", "true"),
+ ]
+
+ SBOptions += "-analyzer-config '%s' " % (
+ ",".join("%s=%s" % (key, value) for (key, value) in AnalyzerConfig))
+
# Always use ccc-analyze to ensure that we can locate the failures
# directory.
SBOptions += "--override-compiler "
+ ExtraEnv = {}
try:
SBCommandFile = open(BuildScriptPath, "r")
SBPrefix = "scan-build " + SBOptions + " "
@@ -257,23 +296,35 @@ def runScanBuild(Dir, SBOutputDir, PBuildLogFile):
Command = Command.strip()
if len(Command) == 0:
continue
+
+ # Custom analyzer invocation specified by project.
+ # Communicate required information using environment variables
+ # instead.
+ if Command == NoPrefixCmd:
+ SBPrefix = ""
+ ExtraEnv['OUTPUT'] = SBOutputDir
+ ExtraEnv['CC'] = Clang
+ continue
+
# If using 'make', auto imply a -jX argument
# to speed up analysis. xcodebuild will
# automatically use the maximum number of cores.
if (Command.startswith("make ") or Command == "make") and \
"-j" not in Command:
- Command += " -j%d" % Jobs
+ Command += " -j%d" % MaxJobs
SBCommand = SBPrefix + Command
+
if Verbose == 1:
- print " Executing: %s" % (SBCommand,)
+ Local.stdout.write(" Executing: %s\n" % (SBCommand,))
check_call(SBCommand, cwd=SBCwd,
stderr=PBuildLogFile,
stdout=PBuildLogFile,
+ env=dict(os.environ, **ExtraEnv),
shell=True)
except CalledProcessError:
- print "Error: scan-build failed. Its output was: "
+ Local.stderr.write("Error: scan-build failed. Its output was: \n")
PBuildLogFile.seek(0)
- shutil.copyfileobj(PBuildLogFile, sys.stdout)
+ shutil.copyfileobj(PBuildLogFile, Local.stderr)
sys.exit(1)
@@ -282,8 +333,9 @@ def runAnalyzePreprocessed(Dir, SBOutputDir, Mode):
Run analysis on a set of preprocessed files.
"""
if os.path.exists(os.path.join(Dir, BuildScript)):
- print "Error: The preprocessed files project should not contain %s" % \
- BuildScript
+ Local.stderr.write(
+ "Error: The preprocessed files project should not contain %s\n" % (
+ BuildScript))
raise Exception()
CmdPrefix = Clang + " -cc1 "
@@ -313,7 +365,8 @@ def runAnalyzePreprocessed(Dir, SBOutputDir, Mode):
if SATestUtils.hasNoExtension(FileName):
continue
if not SATestUtils.isValidSingleInputFile(FileName):
- print "Error: Invalid single input file %s." % (FullFileName,)
+ Local.stderr.write(
+ "Error: Invalid single input file %s.\n" % (FullFileName,))
raise Exception()
# Build and call the analyzer command.
@@ -322,14 +375,15 @@ def runAnalyzePreprocessed(Dir, SBOutputDir, Mode):
LogFile = open(os.path.join(FailPath, FileName + ".stderr.txt"), "w+b")
try:
if Verbose == 1:
- print " Executing: %s" % (Command,)
+ Local.stdout.write(" Executing: %s\n" % (Command,))
check_call(Command, cwd=Dir, stderr=LogFile,
stdout=LogFile,
shell=True)
except CalledProcessError, e:
- print "Error: Analyzes of %s failed. See %s for details." \
- "Error code %d." % (
- FullFileName, LogFile.name, e.returncode)
+ Local.stderr.write("Error: Analyzes of %s failed. "
+ "See %s for details."
+ "Error code %d.\n" % (
+ FullFileName, LogFile.name, e.returncode))
Failed = True
finally:
LogFile.close()
@@ -349,7 +403,7 @@ def removeLogFile(SBOutputDir):
if (os.path.exists(BuildLogPath)):
RmCommand = "rm '%s'" % BuildLogPath
if Verbose == 1:
- print " Executing: %s" % (RmCommand,)
+ Local.stdout.write(" Executing: %s\n" % (RmCommand,))
check_call(RmCommand, shell=True)
@@ -357,8 +411,8 @@ def buildProject(Dir, SBOutputDir, ProjectBuildMode, IsReferenceBuild):
TBegin = time.time()
BuildLogPath = getBuildLogPath(SBOutputDir)
- print "Log file: %s" % (BuildLogPath,)
- print "Output directory: %s" % (SBOutputDir, )
+ Local.stdout.write("Log file: %s\n" % (BuildLogPath,))
+ Local.stdout.write("Output directory: %s\n" % (SBOutputDir, ))
removeLogFile(SBOutputDir)
@@ -366,8 +420,9 @@ def buildProject(Dir, SBOutputDir, ProjectBuildMode, IsReferenceBuild):
if (os.path.exists(SBOutputDir)):
RmCommand = "rm -r '%s'" % SBOutputDir
if Verbose == 1:
- print " Executing: %s" % (RmCommand,)
- check_call(RmCommand, shell=True)
+ Local.stdout.write(" Executing: %s\n" % (RmCommand,))
+ check_call(RmCommand, shell=True, stdout=Local.stdout,
+ stderr=Local.stderr)
assert(not os.path.exists(SBOutputDir))
os.makedirs(os.path.join(SBOutputDir, LogFolderName))
@@ -384,8 +439,9 @@ def buildProject(Dir, SBOutputDir, ProjectBuildMode, IsReferenceBuild):
runCleanupScript(Dir, PBuildLogFile)
normalizeReferenceResults(Dir, SBOutputDir, ProjectBuildMode)
- print "Build complete (time: %.2f). See the log for more details: %s" % \
- ((time.time() - TBegin), BuildLogPath)
+ Local.stdout.write("Build complete (time: %.2f). "
+ "See the log for more details: %s\n" % (
+ (time.time() - TBegin), BuildLogPath))
def normalizeReferenceResults(Dir, SBOutputDir, ProjectBuildMode):
@@ -456,14 +512,16 @@ def checkBuild(SBOutputDir):
CleanUpEmptyPlists(SBOutputDir)
CleanUpEmptyFolders(SBOutputDir)
Plists = glob.glob(SBOutputDir + "/*/*.plist")
- print "Number of bug reports (non-empty plist files) produced: %d" %\
- len(Plists)
+ Local.stdout.write(
+ "Number of bug reports (non-empty plist files) produced: %d\n" %
+ len(Plists))
return
- print "Error: analysis failed."
- print "Total of %d failures discovered." % TotalFailed
+ Local.stderr.write("Error: analysis failed.\n")
+ Local.stderr.write("Total of %d failures discovered.\n" % TotalFailed)
if TotalFailed > NumOfFailuresInSummary:
- print "See the first %d below.\n" % NumOfFailuresInSummary
+ Local.stderr.write(
+ "See the first %d below.\n" % NumOfFailuresInSummary)
# TODO: Add a line "See the results folder for more."
Idx = 0
@@ -471,9 +529,9 @@ def checkBuild(SBOutputDir):
if Idx >= NumOfFailuresInSummary:
break
Idx += 1
- print "\n-- Error #%d -----------\n" % Idx
+ Local.stderr.write("\n-- Error #%d -----------\n" % Idx)
with open(FailLogPathI, "r") as FailLogI:
- shutil.copyfileobj(FailLogI, sys.stdout)
+ shutil.copyfileobj(FailLogI, Local.stdout)
sys.exit(1)
@@ -526,25 +584,30 @@ def runCmpResults(Dir, Strictness=0):
assert(RefDir != NewDir)
if Verbose == 1:
- print " Comparing Results: %s %s" % (RefDir, NewDir)
+ Local.stdout.write(" Comparing Results: %s %s\n" % (
+ RefDir, NewDir))
PatchedSourceDirPath = os.path.join(Dir, PatchedSourceDirName)
- Opts = CmpRuns.CmpOptions(rootA="", rootB=PatchedSourceDirPath)
+ Opts, Args = CmpRuns.generate_option_parser().parse_args(
+ ["--rootA", "", "--rootB", PatchedSourceDirPath])
# Scan the results, delete empty plist files.
NumDiffs, ReportsInRef, ReportsInNew = \
- CmpRuns.dumpScanBuildResultsDiff(RefDir, NewDir, Opts, False)
+ CmpRuns.dumpScanBuildResultsDiff(RefDir, NewDir, Opts,
+ deleteEmpty=False,
+ Stdout=Local.stdout)
if (NumDiffs > 0):
- print "Warning: %s differences in diagnostics." % NumDiffs
+ Local.stdout.write("Warning: %s differences in diagnostics.\n"
+ % NumDiffs)
if Strictness >= 2 and NumDiffs > 0:
- print "Error: Diffs found in strict mode (2)."
+ Local.stdout.write("Error: Diffs found in strict mode (2).\n")
TestsPassed = False
elif Strictness >= 1 and ReportsInRef != ReportsInNew:
- print "Error: The number of results are different in "\
- "strict mode (1)."
+ Local.stdout.write("Error: The number of results are different " +
+ " strict mode (1).\n")
TestsPassed = False
- print "Diagnostic comparison complete (time: %.2f)." % (
- time.time() - TBegin)
+ Local.stdout.write("Diagnostic comparison complete (time: %.2f).\n" % (
+ time.time() - TBegin))
return TestsPassed
@@ -564,19 +627,49 @@ def cleanupReferenceResults(SBOutputDir):
removeLogFile(SBOutputDir)
+class TestProjectThread(threading.Thread):
+ def __init__(self, TasksQueue, ResultsDiffer, FailureFlag):
+ """
+ :param ResultsDiffer: Used to signify that results differ from
+ the canonical ones.
+ :param FailureFlag: Used to signify a failure during the run.
+ """
+ self.TasksQueue = TasksQueue
+ self.ResultsDiffer = ResultsDiffer
+ self.FailureFlag = FailureFlag
+ super(TestProjectThread, self).__init__()
+
+ # Needed to gracefully handle interrupts with Ctrl-C
+ self.daemon = True
+
+ def run(self):
+ while not self.TasksQueue.empty():
+ try:
+ ProjArgs = self.TasksQueue.get()
+ Logger = logging.getLogger(ProjArgs[0])
+ Local.stdout = StreamToLogger(Logger, logging.INFO)
+ Local.stderr = StreamToLogger(Logger, logging.ERROR)
+ if not testProject(*ProjArgs):
+ self.ResultsDiffer.set()
+ self.TasksQueue.task_done()
+ except:
+ self.FailureFlag.set()
+ raise
+
+
def testProject(ID, ProjectBuildMode, IsReferenceBuild=False, Strictness=0):
"""
Test a given project.
:return TestsPassed: Whether tests have passed according
to the :param Strictness: criteria.
"""
- print " \n\n--- Building project %s" % (ID,)
+ Local.stdout.write(" \n\n--- Building project %s\n" % (ID,))
TBegin = time.time()
Dir = getProjectDir(ID)
if Verbose == 1:
- print " Build directory: %s." % (Dir,)
+ Local.stdout.write(" Build directory: %s.\n" % (Dir,))
# Set the build results directory.
RelOutputDir = getSBOutputDirName(IsReferenceBuild)
@@ -592,8 +685,8 @@ def testProject(ID, ProjectBuildMode, IsReferenceBuild=False, Strictness=0):
else:
TestsPassed = runCmpResults(Dir, Strictness)
- print "Completed tests for project %s (time: %.2f)." % \
- (ID, (time.time() - TBegin))
+ Local.stdout.write("Completed tests for project %s (time: %.2f).\n" % (
+ ID, (time.time() - TBegin)))
return TestsPassed
@@ -626,17 +719,62 @@ def validateProjectFile(PMapFile):
" (single file), 1 (project), or 2(single file c++11)."
raise Exception()
+def singleThreadedTestAll(ProjectsToTest):
+ """
+ Run all projects.
+ :return: whether tests have passed.
+ """
+ Success = True
+ for ProjArgs in ProjectsToTest:
+ Success &= testProject(*ProjArgs)
+ return Success
+
+def multiThreadedTestAll(ProjectsToTest, Jobs):
+ """
+ Run each project in a separate thread.
+
+ This is OK despite GIL, as testing is blocked
+ on launching external processes.
+
+ :return: whether tests have passed.
+ """
+ TasksQueue = Queue.Queue()
+
+ for ProjArgs in ProjectsToTest:
+ TasksQueue.put(ProjArgs)
+
+ ResultsDiffer = threading.Event()
+ FailureFlag = threading.Event()
+
+ for i in range(Jobs):
+ T = TestProjectThread(TasksQueue, ResultsDiffer, FailureFlag)
+ T.start()
+
+ # Required to handle Ctrl-C gracefully.
+ while TasksQueue.unfinished_tasks:
+ time.sleep(0.1) # Seconds.
+ if FailureFlag.is_set():
+ Local.stderr.write("Test runner crashed\n")
+ sys.exit(1)
+ return not ResultsDiffer.is_set()
+
+
+def testAll(Args):
+ ProjectsToTest = []
-def testAll(IsReferenceBuild=False, Strictness=0):
- TestsPassed = True
with projectFileHandler() as PMapFile:
validateProjectFile(PMapFile)
# Test the projects.
for (ProjName, ProjBuildMode) in iterateOverProjects(PMapFile):
- TestsPassed &= testProject(
- ProjName, int(ProjBuildMode), IsReferenceBuild, Strictness)
- return TestsPassed
+ ProjectsToTest.append((ProjName,
+ int(ProjBuildMode),
+ Args.regenerate,
+ Args.strictness))
+ if Args.jobs <= 1:
+ return singleThreadedTestAll(ProjectsToTest)
+ else:
+ return multiThreadedTestAll(ProjectsToTest, Args.jobs)
if __name__ == '__main__':
@@ -650,14 +788,12 @@ if __name__ == '__main__':
reference. Default is 0.')
Parser.add_argument('-r', dest='regenerate', action='store_true',
default=False, help='Regenerate reference output.')
+ Parser.add_argument('-j', '--jobs', dest='jobs', type=int,
+ default=0,
+ help='Number of projects to test concurrently')
Args = Parser.parse_args()
- IsReference = False
- Strictness = Args.strictness
- if Args.regenerate:
- IsReference = True
-
- TestsPassed = testAll(IsReference, Strictness)
+ TestsPassed = testAll(Args)
if not TestsPassed:
print "ERROR: Tests failed."
sys.exit(42)
diff --git a/utils/analyzer/SATestUpdateDiffs.py b/utils/analyzer/SATestUpdateDiffs.py
index 2282af15a523..92bbd83172ef 100755
--- a/utils/analyzer/SATestUpdateDiffs.py
+++ b/utils/analyzer/SATestUpdateDiffs.py
@@ -13,10 +13,10 @@ import sys
Verbose = 1
-def runCmd(Command):
+def runCmd(Command, **kwargs):
if Verbose:
print "Executing %s" % Command
- check_call(Command, shell=True)
+ check_call(Command, shell=True, **kwargs)
def updateReferenceResults(ProjName, ProjBuildMode):
@@ -34,27 +34,30 @@ def updateReferenceResults(ProjName, ProjBuildMode):
"previously run?"
sys.exit(1)
- # Remove reference results: in git, and then again for a good measure
- # with rm, as git might not remove things fully if there are empty
- # directories involved.
- runCmd('git rm -r -q "%s"' % (RefResultsPath,))
- runCmd('rm -rf "%s"' % (RefResultsPath,))
-
- # Replace reference results with a freshly computed once.
- runCmd('cp -r "%s" "%s"' % (CreatedResultsPath, RefResultsPath,))
-
- # Run cleanup script.
BuildLogPath = SATestBuild.getBuildLogPath(RefResultsPath)
+ Dirname = os.path.dirname(os.path.abspath(BuildLogPath))
+ runCmd("mkdir -p '%s'" % Dirname)
with open(BuildLogPath, "wb+") as PBuildLogFile:
+ # Remove reference results: in git, and then again for a good measure
+ # with rm, as git might not remove things fully if there are empty
+ # directories involved.
+ runCmd('git rm -r -q "%s"' % (RefResultsPath,), stdout=PBuildLogFile)
+ runCmd('rm -rf "%s"' % (RefResultsPath,), stdout=PBuildLogFile)
+
+ # Replace reference results with a freshly computed once.
+ runCmd('cp -r "%s" "%s"' % (CreatedResultsPath, RefResultsPath,),
+ stdout=PBuildLogFile)
+
+ # Run cleanup script.
SATestBuild.runCleanupScript(ProjDir, PBuildLogFile)
- SATestBuild.normalizeReferenceResults(
- ProjDir, RefResultsPath, ProjBuildMode)
+ SATestBuild.normalizeReferenceResults(
+ ProjDir, RefResultsPath, ProjBuildMode)
- # Clean up the generated difference results.
- SATestBuild.cleanupReferenceResults(RefResultsPath)
+ # Clean up the generated difference results.
+ SATestBuild.cleanupReferenceResults(RefResultsPath)
- runCmd('git add "%s"' % (RefResultsPath,))
+ runCmd('git add "%s"' % (RefResultsPath,), stdout=PBuildLogFile)
def main(argv):
diff --git a/utils/analyzer/SATestUtils.py b/utils/analyzer/SATestUtils.py
index 9220acc1bdbe..2320652619ed 100644
--- a/utils/analyzer/SATestUtils.py
+++ b/utils/analyzer/SATestUtils.py
@@ -37,18 +37,6 @@ def which(command, paths=None):
return None
-class flushfile(object):
- """
- Wrapper to flush the output after every print statement.
- """
- def __init__(self, f):
- self.f = f
-
- def write(self, x):
- self.f.write(x)
- self.f.flush()
-
-
def hasNoExtension(FileName):
(Root, Ext) = os.path.splitext(FileName)
return (Ext == "")
@@ -71,14 +59,15 @@ def getSDKPath(SDKName):
return check_output(Cmd, shell=True).rstrip()
-def runScript(ScriptPath, PBuildLogFile, Cwd):
+def runScript(ScriptPath, PBuildLogFile, Cwd, Stdout=sys.stdout,
+ Stderr=sys.stderr):
"""
Run the provided script if it exists.
"""
if os.path.exists(ScriptPath):
try:
if Verbose == 1:
- print " Executing: %s" % (ScriptPath,)
+ Stdout.write(" Executing: %s\n" % (ScriptPath,))
check_call("chmod +x '%s'" % ScriptPath, cwd=Cwd,
stderr=PBuildLogFile,
stdout=PBuildLogFile,
@@ -88,8 +77,8 @@ def runScript(ScriptPath, PBuildLogFile, Cwd):
stdout=PBuildLogFile,
shell=True)
except:
- print "Error: Running %s failed. See %s for details." % (
- ScriptPath, PBuildLogFile.name)
+ Stderr.write("Error: Running %s failed. See %s for details.\n" % (
+ ScriptPath, PBuildLogFile.name))
sys.exit(-1)
diff --git a/utils/bash-autocomplete.sh b/utils/bash-autocomplete.sh
index ed815d2d7ad1..bcda789b1c07 100755
--- a/utils/bash-autocomplete.sh
+++ b/utils/bash-autocomplete.sh
@@ -12,7 +12,7 @@ _clang()
{
local cur prev words cword arg flags w1 w2
# If latest bash-completion is not supported just initialize COMPREPLY and
- # initialize variables by setting manualy.
+ # initialize variables by setting manually.
_init_completion -n 2> /dev/null
if [[ "$?" != 0 ]]; then
COMPREPLY=()
@@ -25,39 +25,21 @@ _clang()
w2="${COMP_WORDS[$cword - 2]}"
fi
- # Clang want to know if -cc1 or -Xclang option is specified or not, because we don't want to show
- # cc1 options otherwise.
- if [[ "${COMP_WORDS[1]}" == "-cc1" || "$w1" == "-Xclang" ]]; then
- arg="#"
- fi
-
- # bash always separates '=' as a token even if there's no space before/after '='.
- # On the other hand, '=' is just a regular character for clang options that
- # contain '='. For example, "-stdlib=" is defined as is, instead of "-stdlib" and "=".
- # So, we need to partially undo bash tokenization here for integrity.
- if [[ "$cur" == -* ]]; then
- # -foo<tab>
- arg="$arg$cur"
- elif [[ "$w1" == -* && "$cur" == '=' ]]; then
- # -foo=<tab>
- arg="$arg$w1=,"
- elif [[ "$cur" == -*= ]]; then
- # -foo=<tab>
- arg="$arg$cur,"
- elif [[ "$w1" == -* ]]; then
- # -foo <tab> or -foo bar<tab>
- arg="$arg$w1,$cur"
- elif [[ "$w2" == -* && "$w1" == '=' ]]; then
- # -foo=bar<tab>
- arg="$arg$w2=,$cur"
- elif [[ ${cur: -1} != '=' && ${cur/=} != $cur ]]; then
- # -foo=bar<tab>
- arg="$arg${cur%=*}=,${cur#*=}"
- fi
+ # Pass all the current command-line flags to clang, so that clang can handle
+ # these internally.
+ # '=' is separated differently by bash, so we have to concat them without ','
+ for i in `seq 1 $cword`; do
+ if [[ $i == $cword || "${COMP_WORDS[$(($i+1))]}" == '=' ]]; then
+ arg="$arg${COMP_WORDS[$i]}"
+ else
+ arg="$arg${COMP_WORDS[$i]},"
+ fi
+ done
# expand ~ to $HOME
eval local path=${COMP_WORDS[0]}
- flags=$( "$path" --autocomplete="$arg" 2>/dev/null | sed -e 's/\t.*//' )
+ # Use $'\t' so that bash expands the \t for older versions of sed.
+ flags=$( "$path" --autocomplete="$arg" 2>/dev/null | sed -e $'s/\t.*//' )
# If clang is old that it does not support --autocomplete,
# fall back to the filename completion.
if [[ "$?" != 0 ]]; then
@@ -67,7 +49,7 @@ _clang()
# When clang does not emit any possible autocompletion, or user pushed tab after " ",
# just autocomplete files.
- if [[ "$flags" == "$(echo -e '\n')" || "$arg" == "" ]]; then
+ if [[ "$flags" == "$(echo -e '\n')" ]]; then
# If -foo=<tab> and there was no possible values, autocomplete files.
[[ "$cur" == '=' || "$cur" == -*= ]] && cur=""
_clang_filedir
diff --git a/utils/check_cfc/check_cfc.py b/utils/check_cfc/check_cfc.py
index c6ab9abf2352..7a739f46e308 100755
--- a/utils/check_cfc/check_cfc.py
+++ b/utils/check_cfc/check_cfc.py
@@ -237,7 +237,7 @@ def run_step(command, my_env, error_on_failure):
def get_temp_file_name(suffix):
"""Get a temporary file name with a particular suffix. Let the caller be
- reponsible for deleting it."""
+ responsible for deleting it."""
tf = tempfile.NamedTemporaryFile(suffix=suffix, delete=False)
tf.close()
return tf.name
diff --git a/utils/clangdiag.py b/utils/clangdiag.py
index f434bfeaa4c1..9a80e2696d52 100755
--- a/utils/clangdiag.py
+++ b/utils/clangdiag.py
@@ -107,7 +107,7 @@ def setDiagBreakpoint(frame, bp_loc, dict):
target = frame.GetThread().GetProcess().GetTarget()
diagtool = getDiagtool(target)
name = subprocess.check_output([diagtool, "find-diagnostic-id", id]).rstrip();
- # Make sure we only consider errors, warnings, and extentions.
+ # Make sure we only consider errors, warnings, and extensions.
# FIXME: Make this configurable?
prefixes = ['err_', 'warn_', 'exp_']
if len([prefix for prefix in prefixes+[''] if name.startswith(prefix)][0]):
@@ -124,7 +124,7 @@ def enable(exe_ctx, args):
numOfBreakpoints = target.GetNumBreakpoints()
if args.id:
- # Make sure we only consider errors, warnings, and extentions.
+ # Make sure we only consider errors, warnings, and extensions.
# FIXME: Make this configurable?
prefixes = ['err_', 'warn_', 'exp_']
if len([prefix for prefix in prefixes+[''] if args.id.startswith(prefix)][0]):
diff --git a/utils/find-unused-diagnostics.sh b/utils/find-unused-diagnostics.sh
index cd48e6920fb8..783f58ba1d30 100644
--- a/utils/find-unused-diagnostics.sh
+++ b/utils/find-unused-diagnostics.sh
@@ -8,7 +8,7 @@
ALL_DIAGS=$(grep -E --only-matching --no-filename '(err_|warn_|ext_|note_)[a-z_]+' ./include/clang/Basic/Diagnostic*.td)
# Now look for all potential identifiers in the source files.
-ALL_SOURCES=$(find lib include tools -name \*.cpp -or -name \*.h)
+ALL_SOURCES=$(find lib include tools utils -name \*.cpp -or -name \*.h)
DIAGS_IN_SOURCES=$(grep -E --only-matching --no-filename '(err_|warn_|ext_|note_)[a-z_]+' $ALL_SOURCES)
# Print all diags that occur in the .td files but not in the source.
diff --git a/utils/hmaptool/CMakeLists.txt b/utils/hmaptool/CMakeLists.txt
new file mode 100644
index 000000000000..5573009d343a
--- /dev/null
+++ b/utils/hmaptool/CMakeLists.txt
@@ -0,0 +1,16 @@
+set(CLANG_HMAPTOOL hmaptool)
+
+add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/${CLANG_HMAPTOOL}
+ COMMAND ${CMAKE_COMMAND} -E make_directory
+ ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin
+ COMMAND ${CMAKE_COMMAND} -E copy
+ ${CMAKE_CURRENT_SOURCE_DIR}/${CLANG_HMAPTOOL}
+ ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${CLANG_HMAPTOOL})
+
+list(APPEND Depends ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/${CLANG_HMAPTOOL})
+install(PROGRAMS ${CLANG_HMAPTOOL} DESTINATION bin)
+
+add_custom_target(hmaptool ALL DEPENDS ${Depends})
+set_target_properties(hmaptool PROPERTIES FOLDER "Utils")
+
diff --git a/utils/hmaptool/hmaptool b/utils/hmaptool/hmaptool
new file mode 100755
index 000000000000..2b1ca7436c3f
--- /dev/null
+++ b/utils/hmaptool/hmaptool
@@ -0,0 +1,296 @@
+#!/usr/bin/env python
+from __future__ import print_function
+
+import json
+import optparse
+import os
+import struct
+import sys
+
+###
+
+k_header_magic_LE = 'pamh'
+k_header_magic_BE = 'hmap'
+
+def hmap_hash(str):
+ """hash(str) -> int
+
+ Apply the "well-known" headermap hash function.
+ """
+
+ return sum((ord(c.lower()) * 13
+ for c in str), 0)
+
+class HeaderMap(object):
+ @staticmethod
+ def frompath(path):
+ with open(path, 'rb') as f:
+ magic = f.read(4)
+ if magic == k_header_magic_LE:
+ endian_code = '<'
+ elif magic == k_header_magic_BE:
+ endian_code = '>'
+ else:
+ raise SystemExit("error: %s: not a headermap" % (
+ path,))
+
+ # Read the header information.
+ header_fmt = endian_code + 'HHIIII'
+ header_size = struct.calcsize(header_fmt)
+ data = f.read(header_size)
+ if len(data) != header_size:
+ raise SystemExit("error: %s: truncated headermap header" % (
+ path,))
+
+ (version, reserved, strtable_offset, num_entries,
+ num_buckets, max_value_len) = struct.unpack(header_fmt, data)
+
+ if version != 1:
+ raise SystemExit("error: %s: unknown headermap version: %r" % (
+ path, version))
+ if reserved != 0:
+ raise SystemExit("error: %s: invalid reserved value in header" % (
+ path,))
+
+ # The number of buckets must be a power of two.
+ if num_buckets == 0 or (num_buckets & num_buckets - 1) != 0:
+ raise SystemExit("error: %s: invalid number of buckets" % (
+ path,))
+
+ # Read all of the buckets.
+ bucket_fmt = endian_code + 'III'
+ bucket_size = struct.calcsize(bucket_fmt)
+ buckets_data = f.read(num_buckets * bucket_size)
+ if len(buckets_data) != num_buckets * bucket_size:
+ raise SystemExit("error: %s: truncated headermap buckets" % (
+ path,))
+ buckets = [struct.unpack(bucket_fmt,
+ buckets_data[i*bucket_size:(i+1)*bucket_size])
+ for i in range(num_buckets)]
+
+ # Read the string table; the format doesn't explicitly communicate the
+ # size of the string table (which is dumb), so assume it is the rest of
+ # the file.
+ f.seek(0, 2)
+ strtable_size = f.tell() - strtable_offset
+ f.seek(strtable_offset)
+
+ if strtable_size == 0:
+ raise SystemExit("error: %s: unable to read zero-sized string table"%(
+ path,))
+ strtable = f.read(strtable_size)
+
+ if len(strtable) != strtable_size:
+ raise SystemExit("error: %s: unable to read complete string table"%(
+ path,))
+ if strtable[-1] != '\0':
+ raise SystemExit("error: %s: invalid string table in headermap" % (
+ path,))
+
+ return HeaderMap(num_entries, buckets, strtable)
+
+ def __init__(self, num_entries, buckets, strtable):
+ self.num_entries = num_entries
+ self.buckets = buckets
+ self.strtable = strtable
+
+ def get_string(self, idx):
+ if idx >= len(self.strtable):
+ raise SystemExit("error: %s: invalid string index" % (
+ path,))
+ end_idx = self.strtable.index('\0', idx)
+ return self.strtable[idx:end_idx]
+
+ @property
+ def mappings(self):
+ for key_idx,prefix_idx,suffix_idx in self.buckets:
+ if key_idx == 0:
+ continue
+ yield (self.get_string(key_idx),
+ self.get_string(prefix_idx) + self.get_string(suffix_idx))
+
+###
+
+def action_dump(name, args):
+ "dump a headermap file"
+
+ parser = optparse.OptionParser("%%prog %s [options] <headermap path>" % (
+ name,))
+ parser.add_option("-v", "--verbose", dest="verbose",
+ help="show more verbose output [%default]",
+ action="store_true", default=False)
+ (opts, args) = parser.parse_args(args)
+
+ if len(args) != 1:
+ parser.error("invalid number of arguments")
+
+ path, = args
+
+ hmap = HeaderMap.frompath(path)
+
+ # Dump all of the buckets.
+ print ('Header Map: %s' % (path,))
+ if opts.verbose:
+ print ('headermap: %r' % (path,))
+ print (' num entries: %d' % (hmap.num_entries,))
+ print (' num buckets: %d' % (len(hmap.buckets),))
+ print (' string table size: %d' % (len(hmap.strtable),))
+ for i,bucket in enumerate(hmap.buckets):
+ key_idx,prefix_idx,suffix_idx = bucket
+
+ if key_idx == 0:
+ continue
+
+ # Get the strings.
+ key = hmap.get_string(key_idx)
+ prefix = hmap.get_string(prefix_idx)
+ suffix = hmap.get_string(suffix_idx)
+
+ print (" bucket[%d]: %r -> (%r, %r) -- %d" % (
+ i, key, prefix, suffix, (hmap_hash(key) & (num_buckets - 1))))
+ else:
+ mappings = sorted(hmap.mappings)
+ for key,value in mappings:
+ print ("%s -> %s" % (key, value))
+ print ()
+
+def next_power_of_two(value):
+ if value < 0:
+ raise ArgumentError
+ return 1 if value == 0 else 2**(value - 1).bit_length()
+
+def action_write(name, args):
+ "write a headermap file from a JSON definition"
+
+ parser = optparse.OptionParser("%%prog %s [options] <input path> <output path>" % (
+ name,))
+ (opts, args) = parser.parse_args(args)
+
+ if len(args) != 2:
+ parser.error("invalid number of arguments")
+
+ input_path,output_path = args
+
+ with open(input_path, "r") as f:
+ input_data = json.load(f)
+
+ # Compute the headermap contents, we make a table that is 1/3 full.
+ mappings = input_data['mappings']
+ num_buckets = next_power_of_two(len(mappings) * 3)
+
+ table = [(0, 0, 0)
+ for i in range(num_buckets)]
+ max_value_len = 0
+ strtable = "\0"
+ for key,value in mappings.items():
+ if not isinstance(key, str):
+ key = key.decode('utf-8')
+ if not isinstance(value, str):
+ value = value.decode('utf-8')
+ max_value_len = max(max_value_len, len(value))
+
+ key_idx = len(strtable)
+ strtable += key + '\0'
+ prefix = os.path.dirname(value) + '/'
+ suffix = os.path.basename(value)
+ prefix_idx = len(strtable)
+ strtable += prefix + '\0'
+ suffix_idx = len(strtable)
+ strtable += suffix + '\0'
+
+ hash = hmap_hash(key)
+ for i in range(num_buckets):
+ idx = (hash + i) % num_buckets
+ if table[idx][0] == 0:
+ table[idx] = (key_idx, prefix_idx, suffix_idx)
+ break
+ else:
+ raise RuntimeError
+
+ endian_code = '<'
+ magic = k_header_magic_LE
+ magic_size = 4
+ header_fmt = endian_code + 'HHIIII'
+ header_size = struct.calcsize(header_fmt)
+ bucket_fmt = endian_code + 'III'
+ bucket_size = struct.calcsize(bucket_fmt)
+ strtable_offset = magic_size + header_size + num_buckets * bucket_size
+ header = (1, 0, strtable_offset, len(mappings),
+ num_buckets, max_value_len)
+
+ # Write out the headermap.
+ with open(output_path, 'wb') as f:
+ f.write(magic.encode())
+ f.write(struct.pack(header_fmt, *header))
+ for bucket in table:
+ f.write(struct.pack(bucket_fmt, *bucket))
+ f.write(strtable.encode())
+
+def action_tovfs(name, args):
+ "convert a headermap to a VFS layout"
+
+ parser = optparse.OptionParser("%%prog %s [options] <headermap path>" % (
+ name,))
+ parser.add_option("", "--build-path", dest="build_path",
+ help="build path prefix",
+ action="store", type=str)
+ (opts, args) = parser.parse_args(args)
+
+ if len(args) != 2:
+ parser.error("invalid number of arguments")
+ if opts.build_path is None:
+ parser.error("--build-path is required")
+
+ input_path,output_path = args
+
+ hmap = HeaderMap.frompath(input_path)
+
+ # Create the table for all the objects.
+ vfs = {}
+ vfs['version'] = 0
+ build_dir_contents = []
+ vfs['roots'] = [{
+ 'name' : opts.build_path,
+ 'type' : 'directory',
+ 'contents' : build_dir_contents }]
+
+ # We assume we are mapping framework paths, so a key of "Foo/Bar.h" maps to
+ # "<build path>/Foo.framework/Headers/Bar.h".
+ for key,value in hmap.mappings:
+ # If this isn't a framework style mapping, ignore it.
+ components = key.split('/')
+ if len(components) != 2:
+ continue
+ framework_name,header_name = components
+ build_dir_contents.append({
+ 'name' : '%s.framework/Headers/%s' % (framework_name,
+ header_name),
+ 'type' : 'file',
+ 'external-contents' : value })
+
+ with open(output_path, 'w') as f:
+ json.dump(vfs, f, indent=2)
+
+commands = dict((name[7:].replace("_","-"), f)
+ for name,f in locals().items()
+ if name.startswith('action_'))
+
+def usage():
+ print ("Usage: %s command [options]" % (
+ os.path.basename(sys.argv[0])), file=sys.stderr)
+ print (file=sys.stderr)
+ print ("Available commands:", file=sys.stderr)
+ cmds_width = max(map(len, commands))
+ for name,func in sorted(commands.items()):
+ print (" %-*s - %s" % (cmds_width, name, func.__doc__), file=sys.stderr)
+ sys.exit(1)
+
+def main():
+ if len(sys.argv) < 2 or sys.argv[1] not in commands:
+ usage()
+
+ cmd = sys.argv[1]
+ commands[cmd](cmd, sys.argv[2:])
+
+if __name__ == '__main__':
+ main()
diff --git a/www/OpenProjects.html b/www/OpenProjects.html
index ad1890997bc7..9d8f4df955ce 100644
--- a/www/OpenProjects.html
+++ b/www/OpenProjects.html
@@ -102,7 +102,7 @@ Driver</a> web page for more information.</li>
<li><b>Configuration Manager</b>: Clang/LLVM works on a large number of
architectures and operating systems and can cross-compile to a similarly large
-number of configurations, but the pitfalls of chosing the command-line
+number of configurations, but the pitfalls of choosing the command-line
options, making sure the right sub-architecture is chosen and that the correct
optional elements of your particular system can be a pain.
diff --git a/www/analyzer/alpha_checks.html b/www/analyzer/alpha_checks.html
index 7d84d23343f9..4a250dcb31e1 100644
--- a/www/analyzer/alpha_checks.html
+++ b/www/analyzer/alpha_checks.html
@@ -551,12 +551,12 @@ when generating localized strings.
NSString *reminderText =
NSLocalizedString(@"None", @"Indicates no reminders");
if (reminderCount == 1) {
- // Warning: Plural cases are not supported accross all languages.
+ // Warning: Plural cases are not supported across all languages.
// Use a .stringsdict file instead
reminderText =
NSLocalizedString(@"1 Reminder", @"Indicates single reminder");
} else if (reminderCount >= 2) {
- // Warning: Plural cases are not supported accross all languages.
+ // Warning: Plural cases are not supported across all languages.
// Use a .stringsdict file instead
reminderText =
[NSString stringWithFormat:
@@ -712,7 +712,7 @@ void test() {
size_t ts;
scanf("%zd", &ts); // 'ts' marked as tainted
int *p = (int *)malloc(ts * sizeof(int));
- // warn: untrusted data as bufer size
+ // warn: untrusted data as buffer size
}
</pre></div></div></td></tr>
@@ -800,7 +800,7 @@ Check for misuses of stream APIs:<div class=functions>
fopen<br>
fclose</div>(demo checker, the subject of the demo
(<a href="http://llvm.org/devmtg/2012-11/Zaks-Rose-Checker24Hours.pdf">Slides</a>
-,<a href="http://llvm.org/devmtg/2012-11/videos/Zaks-Rose-Checker24Hours.mp4">Video</a>)
+,<a href="https://youtu.be/kdxlsP5QVPw">Video</a>)
by Anna Zaks and Jordan Rose presented at the <a href="http://llvm.org/devmtg/2012-11/">
2012 LLVM Developers' Meeting).</a></div></div></td>
<td><div class="exampleContainer expandable">
diff --git a/www/analyzer/available_checks.html b/www/analyzer/available_checks.html
index eca8dca616d2..f764e0a19789 100644
--- a/www/analyzer/available_checks.html
+++ b/www/analyzer/available_checks.html
@@ -316,7 +316,7 @@ Check for assigning uninitialized values.</div></div></td>
<div class="example"><pre>
void test() {
int x;
- x |= 1; // warn: left expression is unitialized
+ x |= 1; // warn: left expression is uninitialized
}
</pre></div></div></td></tr>
@@ -1173,6 +1173,40 @@ void test() {
<tr><td><div class="namedescr expandable"><span class="name">
+security.insecureAPI.bcmp</span><span class="lang">
+(C)</span><div class="descr">
+Warn on uses of the <code>bcmp</code> function.</div></div></td>
+<td><div class="exampleContainer expandable">
+<div class="example"><pre>
+void test() {
+ bcmp(ptr0, ptr1, n); // warn
+}
+</pre></div></div></td></tr>
+
+<tr><td><div class="namedescr expandable"><span class="name">
+security.insecureAPI.bcopy</span><span class="lang">
+(C)</span><div class="descr">
+Warn on uses of the <code>bcopy</code> function.</div></div></td>
+<td><div class="exampleContainer expandable">
+<div class="example"><pre>
+void test() {
+ bcopy(src, dst, n); // warn
+}
+</pre></div></div></td></tr>
+
+<tr><td><div class="namedescr expandable"><span class="name">
+security.insecureAPI.bzero</span><span class="lang">
+(C)</span><div class="descr">
+Warn on uses of the <code>bzero</code> function.</div></div></td>
+<td><div class="exampleContainer expandable">
+<div class="example"><pre>
+void test() {
+ bzero(ptr, n); // warn
+}
+</pre></div></div></td></tr>
+
+
+<tr><td><div class="namedescr expandable"><span class="name">
security.insecureAPI.getpw</span><span class="lang">
(C)</span><div class="descr">
Warn on uses of the <code>getpw</code> function.</div></div></td>
diff --git a/www/analyzer/checker_dev_manual.html b/www/analyzer/checker_dev_manual.html
index 4883556383f3..42919fa4de21 100644
--- a/www/analyzer/checker_dev_manual.html
+++ b/www/analyzer/checker_dev_manual.html
@@ -23,7 +23,7 @@ relies on a set of checkers to implement the logic for detecting and
constructing specific bug reports. Anyone who is interested in implementing their own
checker, should check out the Building a Checker in 24 Hours talk
(<a href="http://llvm.org/devmtg/2012-11/Zaks-Rose-Checker24Hours.pdf">slides</a>
- <a href="http://llvm.org/devmtg/2012-11/videos/Zaks-Rose-Checker24Hours.mp4">video</a>)
+ <a href="https://youtu.be/kdxlsP5QVPw">video</a>)
and refer to this page for additional information on writing a checker. The static analyzer is a
part of the Clang project, so consult <a href="http://clang.llvm.org/hacking.html">Hacking on Clang</a>
and <a href="http://llvm.org/docs/ProgrammersManual.html">LLVM Programmer's Manual</a>
@@ -696,7 +696,7 @@ href="http://llvm.org/devmtg/2012-11">November 2012 LLVM Developer's
meeting</a>. Describes the construction of SimpleStreamChecker. <a
href="http://llvm.org/devmtg/2012-11/Zaks-Rose-Checker24Hours.pdf">Slides</a>
and <a
-href="http://llvm.org/devmtg/2012-11/videos/Zaks-Rose-Checker24Hours.mp4">video</a>
+href="https://youtu.be/kdxlsP5QVPw">video</a>
are available.
</ul>
diff --git a/www/analyzer/open_projects.html b/www/analyzer/open_projects.html
index 744f4eca41ec..89601a821366 100644
--- a/www/analyzer/open_projects.html
+++ b/www/analyzer/open_projects.html
@@ -147,7 +147,7 @@ mailing list</a> to notify other members of the community.</p>
<p>A SimpleStreamChecker has been presented in the Building a Checker in 24
Hours talk
(<a href="http://llvm.org/devmtg/2012-11/Zaks-Rose-Checker24Hours.pdf">slides</a>
- <a href="http://llvm.org/devmtg/2012-11/videos/Zaks-Rose-Checker24Hours.mp4">video</a>).
+ <a href="https://youtu.be/kdxlsP5QVPw">video</a>).
We need to implement a production version of the checker with richer set of
APIs and evaluate it by running on real codebases.
<i>(Difficulty: Easy)</i></p>
diff --git a/www/analyzer/scan-build.html b/www/analyzer/scan-build.html
index b16f6bb53fa7..83efea90151d 100644
--- a/www/analyzer/scan-build.html
+++ b/www/analyzer/scan-build.html
@@ -248,7 +248,7 @@ you will probably need to run <tt>configure</tt> script through
<pre class="code_example">
$ scan-build ./configure
-$ scan-build make
+$ scan-build --keep-cc make
</pre>
<p>The reason <tt>configure</tt> also needs to be run through
diff --git a/www/comparison.html b/www/comparison.html
index 26f421d73b94..58dcf13a522b 100644
--- a/www/comparison.html
+++ b/www/comparison.html
@@ -4,7 +4,7 @@
<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>Comparing clang to other open source compilers</title>
+ <title>Comparing Clang to other open source compilers</title>
<link type="text/css" rel="stylesheet" href="menu.css">
<link type="text/css" rel="stylesheet" href="content.css">
</head>
@@ -14,7 +14,7 @@
<h1>Clang vs Other Open Source Compilers</h1>
<p>Building an entirely new compiler front-end is a big task, and it isn't
- always clear to people why we decided to do this. Here we compare clang
+ always clear to people why we decided to do this. Here we compare Clang
and its goals to other open source compiler front-ends that are
available. We restrict the discussion to very specific objective points
to avoid controversy where possible. Also, software is infinitely
@@ -24,7 +24,7 @@
<p>The goal of this list is to describe how differences in goals lead to
different strengths and weaknesses, not to make some compiler look bad.
- This will hopefully help you to evaluate whether using clang is a good
+ This will hopefully help you to evaluate whether using Clang is a good
idea for your personal goals. Because we don't know specifically what
<em>you</em> want to do, we describe the features of these compilers in
terms of <em>our</em> goals: if you are only interested in static
@@ -45,10 +45,10 @@
<h2><a name="gcc">Clang vs GCC (GNU Compiler Collection)</a></h2>
<!--=====================================================================-->
- <p>Pro's of GCC vs clang:</p>
+ <p>Pro's of GCC vs Clang:</p>
<ul>
- <li>GCC supports languages that clang does not aim to, such as Java, Ada,
+ <li>GCC supports languages that Clang does not aim to, such as Java, Ada,
FORTRAN, Go, etc.</li>
<li>GCC supports more targets than LLVM.</li>
<li>GCC supports many language extensions, some of which are not implemented
@@ -59,7 +59,7 @@
allowing VLAs in structs</a>.
</ul>
- <p>Pro's of clang vs GCC:</p>
+ <p>Pro's of Clang vs GCC:</p>
<ul>
<li>The Clang ASTs and design are intended to be <a
@@ -103,7 +103,7 @@
diagnostics and showing macro expansions, but GCC is still catching
up.</li>
<li>GCC is licensed under the GPL license. <a href="features.html#license">
- clang uses a BSD license,</a> which allows it to be embedded in
+ Clang uses a BSD license,</a> which allows it to be embedded in
software that is not GPL-licensed.</li>
<li>Clang inherits a number of features from its use of LLVM as a backend,
including support for a bytecode representation for intermediate code,
@@ -122,7 +122,7 @@
<h2><a name="elsa">Clang vs Elsa (Elkhound-based C++ Parser)</a></h2>
<!--=====================================================================-->
- <p>Pro's of Elsa vs clang:</p>
+ <p>Pro's of Elsa vs Clang:</p>
<ul>
<li>Elsa's parser and AST is designed to be easily extensible by adding
@@ -130,7 +130,7 @@
but requires you to write C++ code to do it.</li>
</ul>
- <p>Pro's of clang vs Elsa:</p>
+ <p>Pro's of Clang vs Elsa:</p>
<ul>
<li>Clang's C and C++ support is far more mature and practically useful than
@@ -143,7 +143,7 @@
file bugs against Clang and they will often be fixed for you. If you
use Elsa, you are (mostly) on your own for bug fixes and feature
enhancements.</li>
- <li>Elsa is not built as a stack of reusable libraries like clang is. It is
+ <li>Elsa is not built as a stack of reusable libraries like Clang is. It is
very difficult to use part of Elsa without the whole front-end. For
example, you cannot use Elsa to parse C/ObjC code without building an
AST. You can do this in Clang and it is much faster than building an
@@ -153,7 +153,7 @@
its original position before preprocessing. Like GCC, it does not keep
track of macro expansions.</li>
<li>Elsa is even slower and uses more memory than GCC, which itself requires
- far more space and time than clang.</li>
+ far more space and time than Clang.</li>
<li>Elsa only does partial semantic analysis. It is intended to work on
code that is already validated by GCC, so it does not do many semantic
checks required by the languages it implements.</li>
@@ -166,18 +166,18 @@
<h2><a name="pcc">Clang vs PCC (Portable C Compiler)</a></h2>
<!--=====================================================================-->
- <p>Pro's of PCC vs clang:</p>
+ <p>Pro's of PCC vs Clang:</p>
<ul>
<li>The PCC source base is very small and builds quickly with just a C
compiler.</li>
</ul>
- <p>Pro's of clang vs PCC:</p>
+ <p>Pro's of Clang vs PCC:</p>
<ul>
<li>PCC dates from the 1970's and has been dormant for most of that time.
- The clang + llvm communities are very active.</li>
+ The Clang and LLVM communities are very active.</li>
<li>PCC doesn't support Objective-C or C++ and doesn't aim to support
C++.</li>
<li>PCC's code generation is very limited compared to LLVM. It produces very
diff --git a/www/cxx_dr_status.html b/www/cxx_dr_status.html
index 98cddaeb33df..cdeb451911dc 100644
--- a/www/cxx_dr_status.html
+++ b/www/cxx_dr_status.html
@@ -28,7 +28,7 @@
<!--*************************************************************************-->
<h1>C++ Defect Report Support in Clang</h1>
<!--*************************************************************************-->
-<p>Last updated: $Date: 2017-12-18 20:46:56 +0100 (Mon, 18 Dec 2017) $</p>
+<p>Last updated: $Date: 2018-07-27 06:41:37 +0200 (Fri, 27 Jul 2018) $</p>
<h2 id="cxxdr">C++ defect report implementation status</h2>
@@ -303,7 +303,7 @@
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#44">44</a></td>
<td>CD1</td>
<td>Member specializations</td>
- <td class="full" align="center">Yes</td>
+ <td class="partial" align="center">Superseded by <a href="#727">727</a></td>
</tr>
<tr id="45">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#45">45</a></td>
@@ -795,7 +795,7 @@
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#126">126</a></td>
<td>TC1</td>
<td>Exception specifications and <TT>const</TT></td>
- <td class="none" align="center">No</td>
+ <td class="partial" align="center">Partial</td>
</tr>
<tr id="127">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#127">127</a></td>
@@ -937,7 +937,7 @@
</tr>
<tr id="150">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#150">150</a></td>
- <td>DR</td>
+ <td>C++17</td>
<td>Template template parameters and default arguments</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -1292,7 +1292,7 @@
<tr id="209">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#209">209</a></td>
<td>NAD</td>
- <td>Must friend declaration names be
+ <td>Must friend declaration names be
accessible?</td>
<td class="full" align="center">Yes</td>
</tr>
@@ -1554,11 +1554,11 @@ accessible?</td>
<td>Looking up deallocation functions in virtual destructors</td>
<td class="full" align="center">Yes</td>
</tr>
- <tr class="open" id="253">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#253">253</a></td>
- <td>drafting</td>
+ <tr id="253">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#253">253</a></td>
+ <td>C++17</td>
<td>Why must empty or fully-initialized const objects be initialized?</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="254">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#254">254</a></td>
@@ -1653,7 +1653,7 @@ accessible?</td>
<tr id="269">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#269">269</a></td>
<td>NAD</td>
- <td>Order of initialization of multiply-defined static data members
+ <td>Order of initialization of multiply-defined static data members
of class templates</td>
<td class="na" align="center">N/A</td>
</tr>
@@ -1921,11 +1921,11 @@ of class templates</td>
<td>Class with single conversion function to integral as array size in <TT>new</TT></td>
<td class="full" align="center">Duplicate of <a href="#299">299</a> (C++11 onwards)</td>
</tr>
- <tr class="open" id="314">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#314">314</a></td>
- <td>drafting</td>
+ <tr id="314">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#314">314</a></td>
+ <td>C++17</td>
<td><TT>template</TT> in base class specifier</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="315">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#315">315</a></td>
@@ -2021,7 +2021,7 @@ of class templates</td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#330">330</a></td>
<td>CD4</td>
<td>Qualification conversions and pointers to arrays of pointers</td>
- <td class="none" align="center">Unknown</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr id="331">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#331">331</a></td>
@@ -2095,11 +2095,11 @@ of class templates</td>
<td>Terminology: "indirection" versus "dereference"</td>
<td class="na" align="center">N/A</td>
</tr>
- <tr class="open" id="343">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#343">343</a></td>
- <td>drafting</td>
+ <tr id="343">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#343">343</a></td>
+ <td>C++17</td>
<td>Make <TT>template</TT> optional in contexts that require a type</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="344">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#344">344</a></td>
@@ -2285,7 +2285,7 @@ of class templates</td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#374">374</a></td>
<td>CD2</td>
<td>Can explicit specialization outside namespace use qualified name?</td>
- <td class="full" align="center">Yes (C++11 onwards)</td>
+ <td class="full" align="center">Yes</td>
</tr>
<tr id="375">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#375">375</a></td>
@@ -2593,11 +2593,11 @@ of class templates</td>
<td>Set of candidates for overloaded built-in operator with float operand</td>
<td class="full" align="center">Yes</td>
</tr>
- <tr class="open" id="426">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#426">426</a></td>
- <td>review</td>
+ <tr id="426">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#426">426</a></td>
+ <td>C++17</td>
<td>Identically-named variables, one internally and one externally linked, allowed?</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="427">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#427">427</a></td>
@@ -3268,8 +3268,8 @@ of class templates</td>
<tr id="538">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#538">538</a></td>
<td>CD1</td>
- <td>Definition and usage
-of <I>structure</I>, <I>POD-struct</I>, <I>POD-union</I>,
+ <td>Definition and usage
+of <I>structure</I>, <I>POD-struct</I>, <I>POD-union</I>,
and <I>POD class</I></td>
<td class="na" align="center">N/A</td>
</tr>
@@ -3615,11 +3615,11 @@ and <I>POD class</I></td>
<td>Exception specifications in templates instantiated from class bodies</td>
<td class="full" align="center">Duplicate of <a href="#1330">1330</a></td>
</tr>
- <tr class="open" id="596">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#596">596</a></td>
- <td>open</td>
+ <tr id="596">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#596">596</a></td>
+ <td>NAD</td>
<td>Replacing an exception object</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="597">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#597">597</a></td>
@@ -3855,11 +3855,11 @@ and <I>POD class</I></td>
<td>Names of constructors and destructors of templates</td>
<td class="full" align="center">Yes</td>
</tr>
- <tr class="open" id="636">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#636">636</a></td>
- <td>drafting</td>
+ <tr id="636">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#636">636</a></td>
+ <td>CD4</td>
<td>Dynamic type of objects and aliasing</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="637">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#637">637</a></td>
@@ -3889,55 +3889,55 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#641">641</a></td>
<td>CD2</td>
<td>Overload resolution and conversion-to-same-type operators</td>
- <td class="none" align="center">Unknown</td>
+ <td class="full" align="center">Yes</td>
</tr>
<tr id="642">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#642">642</a></td>
<td>CD2</td>
<td>Definition and use of &#8220;block scope&#8221; and &#8220;local scope&#8221;</td>
- <td class="none" align="center">Unknown</td>
+ <td class="full" align="center">Yes</td>
</tr>
<tr id="643">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#643">643</a></td>
<td>NAD</td>
<td>Use of <TT>decltype</TT> in a class <I>member-specification</I></td>
- <td class="none" align="center">Unknown</td>
+ <td class="full" align="center">Yes</td>
</tr>
<tr id="644">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#644">644</a></td>
<td>CD1</td>
<td>Should a trivial class type be a literal type?</td>
- <td class="none" align="center">Unknown</td>
+ <td class="partial" align="center">Partial</td>
</tr>
<tr id="645">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#645">645</a></td>
<td>CD2</td>
<td>Are bit-field and non-bit-field members layout compatible?</td>
- <td class="none" align="center">Unknown</td>
+ <td class="na" align="center">N/A</td>
</tr>
<tr id="646">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#646">646</a></td>
<td>NAD</td>
<td>Can a class with a constexpr copy constructor be a literal type?</td>
- <td class="none" align="center">Unknown</td>
+ <td class="none" align="center">Superseded by <a href="#981">981</a></td>
</tr>
<tr id="647">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#647">647</a></td>
<td>CD1</td>
<td>Non-constexpr instances of constexpr constructor templates</td>
- <td class="none" align="center">Unknown</td>
+ <td class="full" align="center">Yes</td>
</tr>
<tr id="648">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#648">648</a></td>
<td>CD1</td>
<td>Constant expressions in constexpr initializers</td>
- <td class="none" align="center">Unknown</td>
+ <td class="full" align="center">Yes</td>
</tr>
<tr id="649">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#649">649</a></td>
<td>CD1</td>
<td>Optionally ill-formed extended alignment requests</td>
- <td class="none" align="center">Unknown</td>
+ <td class="full" align="center">Yes</td>
</tr>
<tr id="650">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#650">650</a></td>
@@ -3949,13 +3949,13 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#651">651</a></td>
<td>CD1</td>
<td>Problems in <TT>decltype</TT> specification and examples</td>
- <td class="none" align="center">Unknown</td>
+ <td class="full" align="center">Yes</td>
</tr>
<tr id="652">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#652">652</a></td>
<td>CD2</td>
<td>Compile-time evaluation of floating-point expressions</td>
- <td class="none" align="center">Unknown</td>
+ <td class="full" align="center">Yes</td>
</tr>
<tr id="653">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#653">653</a></td>
@@ -3967,25 +3967,25 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#654">654</a></td>
<td>CD1</td>
<td>Conversions to and from <TT>nullptr_t</TT></td>
- <td class="none" align="center">Unknown</td>
+ <td class="full" align="center">Yes</td>
</tr>
<tr id="655">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#655">655</a></td>
<td>C++11</td>
<td>Initialization not specified for forwarding constructors</td>
- <td class="none" align="center">Unknown</td>
+ <td class="full" align="center">Yes</td>
</tr>
<tr id="656">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#656">656</a></td>
<td>CD2</td>
<td>Direct binding to the result of a conversion operator</td>
- <td class="none" align="center">Unknown</td>
+ <td class="full" align="center">Yes</td>
</tr>
<tr id="657">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#657">657</a></td>
<td>CD2</td>
<td>Abstract class parameter in synthesized declaration</td>
- <td class="none" align="center">Unknown</td>
+ <td class="partial" align="center">Partial</td>
</tr>
<tr id="658">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#658">658</a></td>
@@ -3997,13 +3997,13 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#659">659</a></td>
<td>CD1</td>
<td>Alignment of function types</td>
- <td class="none" align="center">Unknown</td>
+ <td class="full" align="center">Yes</td>
</tr>
<tr id="660">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#660">660</a></td>
<td>CD1</td>
<td>Unnamed scoped enumerations</td>
- <td class="none" align="center">Unknown</td>
+ <td class="full" align="center">Yes</td>
</tr>
<tr id="661">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#661">661</a></td>
@@ -4015,37 +4015,37 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#662">662</a></td>
<td>NAD</td>
<td>Forming a pointer to a reference type</td>
- <td class="none" align="center">Unknown</td>
+ <td class="full" align="center">Yes</td>
</tr>
<tr id="663">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#663">663</a></td>
<td>CD1</td>
<td>Valid Cyrillic identifier characters</td>
- <td class="none" align="center">Unknown</td>
+ <td class="full" align="center">Yes (C++11 onwards)</td>
</tr>
<tr id="664">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#664">664</a></td>
<td>CD2</td>
<td>Direct binding of references to non-class rvalue references</td>
- <td class="none" align="center">Unknown</td>
+ <td class="full" align="center">Yes</td>
</tr>
<tr id="665">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#665">665</a></td>
<td>CD2</td>
<td>Problems in the specification of <TT>dynamic_cast</TT></td>
- <td class="none" align="center">Unknown</td>
+ <td class="full" align="center">Yes</td>
</tr>
<tr id="666">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#666">666</a></td>
<td>CD1</td>
<td>Dependent <I>qualified-id</I>s without the <TT>typename</TT> keyword</td>
- <td class="none" align="center">Unknown</td>
+ <td class="full" align="center">Yes</td>
</tr>
<tr id="667">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#667">667</a></td>
<td>CD2</td>
<td>Trivial special member functions that cannot be implicitly defined</td>
- <td class="none" align="center">Unknown</td>
+ <td class="full" align="center">Yes</td>
</tr>
<tr id="668">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#668">668</a></td>
@@ -4057,7 +4057,7 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#669">669</a></td>
<td>NAD</td>
<td>Confusing specification of the meaning of <TT>decltype</TT></td>
- <td class="none" align="center">Unknown</td>
+ <td class="full" align="center">Yes</td>
</tr>
<tr class="open" id="670">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#670">670</a></td>
@@ -4069,7 +4069,7 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#671">671</a></td>
<td>CD1</td>
<td>Explicit conversion from a scoped enumeration type to integral type</td>
- <td class="none" align="center">Unknown</td>
+ <td class="full" align="center">Yes</td>
</tr>
<tr id="672">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#672">672</a></td>
@@ -4081,31 +4081,31 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#673">673</a></td>
<td>NAD</td>
<td>Injection of names from <I>elaborated-type-specifier</I>s in <TT>friend</TT> declarations</td>
- <td class="none" align="center">Unknown</td>
+ <td class="full" align="center">Yes</td>
</tr>
<tr id="674">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#674">674</a></td>
<td>C++11</td>
<td>&#8220;matching specialization&#8221; for a friend declaration</td>
- <td class="none" align="center">Unknown</td>
+ <td class="none" align="center">No</td>
</tr>
<tr id="675">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#675">675</a></td>
<td>CD3</td>
<td>Signedness of bit-field with typedef or template parameter type</td>
- <td class="none" align="center">Unknown</td>
+ <td class="none" align="center">Duplicate of <a href="#739">739</a></td>
</tr>
<tr id="676">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#676">676</a></td>
<td>C++11</td>
<td><I>static_assert-declaration</I>s and general requirements for declarations</td>
- <td class="none" align="center">Unknown</td>
+ <td class="na" align="center">N/A</td>
</tr>
<tr id="677">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#677">677</a></td>
<td>CD1</td>
<td>Deleted <TT>operator delete</TT> and virtual destructors</td>
- <td class="none" align="center">Unknown</td>
+ <td class="none" align="center">No</td>
</tr>
<tr id="678">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#678">678</a></td>
@@ -4117,19 +4117,19 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#679">679</a></td>
<td>CD1</td>
<td>Equivalence of <I>template-id</I>s and operator function templates</td>
- <td class="none" align="center">Unknown</td>
+ <td class="full" align="center">Yes</td>
</tr>
<tr id="680">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#680">680</a></td>
<td>CD2</td>
<td>What is a move constructor?</td>
- <td class="none" align="center">Unknown</td>
+ <td class="na" align="center">N/A</td>
</tr>
<tr id="681">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#681">681</a></td>
<td>CD1</td>
<td>Restrictions on declarators with late-specified return types</td>
- <td class="none" align="center">Unknown</td>
+ <td class="partial" align="center">Partial</td>
</tr>
<tr class="open" id="682">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#682">682</a></td>
@@ -4141,25 +4141,25 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#683">683</a></td>
<td>CD1</td>
<td>Requirements for trivial subobject special functions</td>
- <td class="none" align="center">Unknown</td>
+ <td class="full" align="center">Yes</td>
</tr>
<tr id="684">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#684">684</a></td>
<td>CD1</td>
<td>Constant expressions involving the address of an automatic variable</td>
- <td class="none" align="center">Unknown</td>
+ <td class="none" align="center">Superseded by <a href="#1454">1454</a></td>
</tr>
<tr id="685">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#685">685</a></td>
<td>CD2</td>
<td>Integral promotion of enumeration ignores fixed underlying type</td>
- <td class="none" align="center">Unknown</td>
+ <td class="full" align="center">Yes</td>
</tr>
<tr id="686">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#686">686</a></td>
<td>CD1</td>
<td>Type declarations/definitions in <I>type-specifier-seq</I>s and <I>type-id</I>s</td>
- <td class="none" align="center">Unknown</td>
+ <td class="full" align="center">Yes</td>
</tr>
<tr class="open" id="687">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#687">687</a></td>
@@ -4383,11 +4383,11 @@ and <I>POD class</I></td>
<td>Atomic and non-atomic objects in the memory model</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="727">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#727">727</a></td>
- <td>drafting</td>
+ <tr id="727">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#727">727</a></td>
+ <td>C++17</td>
<td>In-class explicit specializations</td>
- <td align="center">Not resolved</td>
+ <td class="partial" align="center">Partial</td>
</tr>
<tr class="open" id="728">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#728">728</a></td>
@@ -5235,11 +5235,11 @@ and <I>POD class</I></td>
<td>Explicit conversion functions in direct class initialization</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr id="900">
+ <tr class="open" id="900">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#900">900</a></td>
- <td>NAD</td>
+ <td>extension</td>
<td>Lifetime of temporaries in range-based <TT>for</TT></td>
- <td class="none" align="center">Unknown</td>
+ <td align="center">Not resolved</td>
</tr>
<tr class="open" id="901">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#901">901</a></td>
@@ -5469,11 +5469,11 @@ and <I>POD class</I></td>
<td>Is <TT>this</TT> an entity?</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="943">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#943">943</a></td>
- <td>open</td>
+ <tr id="943">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#943">943</a></td>
+ <td>DRWP</td>
<td>Is <TT>T()</TT> a temporary?</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="944">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#944">944</a></td>
@@ -6267,11 +6267,11 @@ and <I>POD class</I></td>
<td>Grammar does not allow template alias in <I>type-name</I></td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="1076">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1076">1076</a></td>
- <td>open</td>
+ <tr id="1076">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1076">1076</a></td>
+ <td>DRWP</td>
<td>Value categories and lvalue temporaries</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="1077">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1077">1077</a></td>
@@ -6493,7 +6493,7 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1113">1113</a></td>
<td>C++11</td>
<td>Linkage of namespace member of unnamed namespace</td>
- <td class="none" align="center">Unknown</td>
+ <td class="partial" align="center">Partial</td>
</tr>
<tr id="1114">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1114">1114</a></td>
@@ -7093,7 +7093,7 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1213">1213</a></td>
<td>CD3</td>
<td>Array subscripting and xvalues</td>
- <td class="full" align="center">Clang 4</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr id="1214">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1214">1214</a></td>
@@ -7605,11 +7605,11 @@ and <I>POD class</I></td>
<td>Incorrect example in overload resolution</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="1299">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1299">1299</a></td>
- <td>drafting</td>
+ <tr id="1299">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1299">1299</a></td>
+ <td>DRWP</td>
<td>&#8220;Temporary objects&#8221; vs &#8220;temporary expressions&#8221;</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="1300">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1300">1300</a></td>
@@ -7871,7 +7871,7 @@ and <I>POD class</I></td>
</tr>
<tr id="1343">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1343">1343</a></td>
- <td>DR</td>
+ <td>C++17</td>
<td>Sequencing of non-class initialization</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -8183,7 +8183,7 @@ and <I>POD class</I></td>
</tr>
<tr id="1395">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1395">1395</a></td>
- <td>DR</td>
+ <td>C++17</td>
<td>Partial ordering of variadic templates reconsidered</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -8365,7 +8365,7 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1425">1425</a></td>
<td>CD3</td>
<td>Base-class subobjects of standard-layout structs</td>
- <td class="none" align="center">Unknown</td>
+ <td class="na" align="center">N/A (ABI constraint)</td>
</tr>
<tr class="open" id="1426">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1426">1426</a></td>
@@ -8949,11 +8949,11 @@ and <I>POD class</I></td>
<td>Access checking for <TT>initializer_list</TT> array initialization</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="1523">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1523">1523</a></td>
- <td>drafting</td>
+ <tr id="1523">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1523">1523</a></td>
+ <td>DRWP</td>
<td>Point of declaration in range-based <TT>for</TT></td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="1524">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1524">1524</a></td>
@@ -9544,8 +9544,8 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="1622">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1622">1622</a></td>
- <td>ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1622">1622</a></td>
+ <td>C++17</td>
<td>Empty aggregate initializer for union</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -9847,7 +9847,7 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1672">1672</a></td>
<td>CD4</td>
<td>Layout compatibility with multiple empty bases</td>
- <td class="none" align="center">Unknown</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr id="1673">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1673">1673</a></td>
@@ -9874,8 +9874,8 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="1677">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1677">1677</a></td>
- <td>ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1677">1677</a></td>
+ <td>C++17</td>
<td>Constant initialization via aggregate initialization</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -9937,7 +9937,7 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1687">1687</a></td>
<td>C++14</td>
<td>Conversions of operands of built-in operators</td>
- <td class="none" align="center">Unknown</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr id="1688">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1688">1688</a></td>
@@ -9991,7 +9991,7 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1696">1696</a></td>
<td>CD4</td>
<td>Temporary lifetime and non-static data member initializers</td>
- <td class="none" align="center">Unknown</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr class="open" id="1697">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1697">1697</a></td>
@@ -10035,11 +10035,11 @@ and <I>POD class</I></td>
<td>Language linkage of names of functions with internal linkage</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="1704">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1704">1704</a></td>
- <td>drafting</td>
+ <tr id="1704">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1704">1704</a></td>
+ <td>DRWP</td>
<td>Type checking in explicit instantiation of variable templates</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="1705">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1705">1705</a></td>
@@ -10071,11 +10071,11 @@ and <I>POD class</I></td>
<td>Stringizing raw string literals containing newline</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="1710">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1710">1710</a></td>
- <td>drafting</td>
+ <tr id="1710">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1710">1710</a></td>
+ <td>C++17</td>
<td>Missing <TT>template</TT> keyword in <I>class-or-decltype</I></td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="1711">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1711">1711</a></td>
@@ -10179,11 +10179,11 @@ and <I>POD class</I></td>
<td>Type of a specialization of a variable template</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="1728">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1728">1728</a></td>
- <td>drafting</td>
+ <tr id="1728">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1728">1728</a></td>
+ <td>DRWP</td>
<td>Type of an explicit instantiation of a variable template</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="1729">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1729">1729</a></td>
@@ -10515,17 +10515,17 @@ and <I>POD class</I></td>
<td>Why are virtual destructors non-trivial?</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="1784">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1784">1784</a></td>
- <td>concurrency</td>
+ <tr id="1784">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1784">1784</a></td>
+ <td>C++17</td>
<td>Concurrent execution during static local initialization</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="1785">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1785">1785</a></td>
- <td>drafting</td>
+ <tr id="1785">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1785">1785</a></td>
+ <td>NAD</td>
<td>Conflicting diagnostic requirements for template definitions</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="1786">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1786">1786</a></td>
@@ -10575,11 +10575,11 @@ and <I>POD class</I></td>
<td><TT>thread_local</TT> in explicit specializations</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="1794">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1794">1794</a></td>
- <td>drafting</td>
+ <tr id="1794">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1794">1794</a></td>
+ <td>C++17</td>
<td><TT>template</TT> keyword and alias templates</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="1795">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1795">1795</a></td>
@@ -10683,17 +10683,17 @@ and <I>POD class</I></td>
<td>Lookup of deallocation function in a virtual destructor definition</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="1812">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1812">1812</a></td>
- <td>drafting</td>
+ <tr id="1812">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1812">1812</a></td>
+ <td>C++17</td>
<td>Omission of <TT>template</TT> in a <I>typename-specifier</I></td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="1813">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1813">1813</a></td>
<td>CD4</td>
<td>Direct vs indirect bases in standard-layout classes</td>
- <td class="none" align="center">Unknown</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr id="1814">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1814">1814</a></td>
@@ -10705,7 +10705,7 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1815">1815</a></td>
<td>CD4</td>
<td>Lifetime extension in aggregate initialization</td>
- <td class="none" align="center">Unknown</td>
+ <td class="none" align="center">No</td>
</tr>
<tr id="1816">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1816">1816</a></td>
@@ -10763,7 +10763,7 @@ and <I>POD class</I></td>
</tr>
<tr id="1825">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1825">1825</a></td>
- <td>DR</td>
+ <td>C++17</td>
<td>Partial ordering between variadic and non-variadic function templates</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -10827,11 +10827,11 @@ and <I>POD class</I></td>
<td>Dependent member lookup before <TT>&lt;</TT></td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="1836">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1836">1836</a></td>
- <td>drafting</td>
+ <tr id="1836">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1836">1836</a></td>
+ <td>DRWP</td>
<td>Use of class type being defined in <I>trailing-return-type</I></td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="1837">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1837">1837</a></td>
@@ -10972,8 +10972,8 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="1860">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1860">1860</a></td>
- <td>ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1860">1860</a></td>
+ <td>C++17</td>
<td>What is a &#8220;direct member?&#8221;</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -10983,11 +10983,11 @@ and <I>POD class</I></td>
<td>Values of a bit-field</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="1862">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1862">1862</a></td>
- <td>drafting</td>
+ <tr id="1862">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1862">1862</a></td>
+ <td>DR</td>
<td>Determining &#8220;corresponding members&#8221; for friendship</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="1863">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1863">1863</a></td>
@@ -11101,7 +11101,7 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1881">1881</a></td>
<td>CD4</td>
<td>Standard-layout classes and unnamed bit-fields</td>
- <td class="none" align="center">Unknown</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr id="1882">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1882">1882</a></td>
@@ -11169,11 +11169,11 @@ and <I>POD class</I></td>
<td>Use of <TT>auto</TT> in function type</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="1893">
+ <tr id="1893">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1893">1893</a></td>
- <td>drafting</td>
+ <td>tentatively ready</td>
<td>Function-style cast with <I>braced-init-list</I>s and empty pack expansions</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="1894">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1894">1894</a></td>
@@ -11249,7 +11249,7 @@ and <I>POD class</I></td>
</tr>
<tr class="open" id="1906">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1906">1906</a></td>
- <td>drafting</td>
+ <td>review</td>
<td>Name lookup in member <TT>friend</TT> declaration</td>
<td align="center">Not resolved</td>
</tr>
@@ -11271,11 +11271,11 @@ and <I>POD class</I></td>
<td>Member class template with the same name as the class</td>
<td class="full" align="center">Yes</td>
</tr>
- <tr class="open" id="1910">
+ <tr id="1910">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1910">1910</a></td>
- <td>drafting</td>
+ <td>tentatively ready</td>
<td>&#8220;Shall&#8221; requirement applied to runtime behavior</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="1911">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1911">1911</a></td>
@@ -11579,7 +11579,7 @@ and <I>POD class</I></td>
</tr>
<tr id="1961">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1961">1961</a></td>
- <td>DR</td>
+ <td>C++17</td>
<td>Potentially-concurrent actions within a signal handler</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -11709,11 +11709,11 @@ and <I>POD class</I></td>
<td>Deduction extending parameter pack</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="1983">
+ <tr id="1983">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1983">1983</a></td>
- <td>drafting</td>
+ <td>tentatively ready</td>
<td>Inappropriate use of <I>virt-specifier</I></td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="1984">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1984">1984</a></td>
@@ -11877,11 +11877,11 @@ and <I>POD class</I></td>
<td><I>exception-specification</I>s and conversion operators</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2011">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2011">2011</a></td>
- <td>drafting</td>
+ <tr id="2011">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2011">2011</a></td>
+ <td>C++17</td>
<td>Unclear effect of reference capture of reference</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="2012">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2012">2012</a></td>
@@ -12087,11 +12087,11 @@ and <I>POD class</I></td>
<td>&#8220;Identical&#8221; template parameter lists</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2046">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2046">2046</a></td>
- <td>concurrency</td>
+ <tr id="2046">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2046">2046</a></td>
+ <td>C++17</td>
<td>Incomplete thread specifications</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="2047">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2047">2047</a></td>
@@ -12165,11 +12165,11 @@ and <I>POD class</I></td>
<td>More errors from internal-linkage namespaces</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2059">
+ <tr id="2059">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2059">2059</a></td>
- <td>drafting</td>
+ <td>tentatively ready</td>
<td>Linkage and deduced return types</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="2060">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2060">2060</a></td>
@@ -12297,11 +12297,11 @@ and <I>POD class</I></td>
<td>Example with empty anonymous union member</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2081">
+ <tr id="2081">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2081">2081</a></td>
- <td>drafting</td>
+ <td>tentatively ready</td>
<td>Deduced return type in redeclaration or specialization of function template</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="2082">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2082">2082</a></td>
@@ -12339,11 +12339,11 @@ and <I>POD class</I></td>
<td>Left shift of negative value by zero bits</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2088">
+ <tr id="2088">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2088">2088</a></td>
- <td>drafting</td>
+ <td>tentatively ready</td>
<td>Late tiebreakers in partial ordering</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2089">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2089">2089</a></td>
@@ -12363,11 +12363,11 @@ and <I>POD class</I></td>
<td>Deducing reference non-type template arguments</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2092">
+ <tr id="2092">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2092">2092</a></td>
- <td>drafting</td>
+ <td>tentatively ready</td>
<td>Deduction failure and overload resolution</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="2093">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2093">2093</a></td>
@@ -12377,7 +12377,7 @@ and <I>POD class</I></td>
</tr>
<tr id="2094">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2094">2094</a></td>
- <td>DR</td>
+ <td>C++17</td>
<td>Trivial copy/move constructor for class with volatile member</td>
<td class="full" align="center">Clang 5</td>
</tr>
@@ -12413,7 +12413,7 @@ and <I>POD class</I></td>
</tr>
<tr id="2100">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2100">2100</a></td>
- <td>DR</td>
+ <td>C++17</td>
<td>Value-dependent address of static data member of class template</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12535,7 +12535,7 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2120">2120</a></td>
<td>CD4</td>
<td>Array as first non-static data member in standard-layout class</td>
- <td class="none" align="center">Unknown</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr class="open" id="2121">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2121">2121</a></td>
@@ -12671,7 +12671,7 @@ and <I>POD class</I></td>
</tr>
<tr id="2143">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2143">2143</a></td>
- <td>DR</td>
+ <td>C++17</td>
<td>Value-dependency via injected-class-name</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12743,7 +12743,7 @@ and <I>POD class</I></td>
</tr>
<tr id="2155">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2155">2155</a></td>
- <td>DR</td>
+ <td>C++17</td>
<td>Defining classes and enumerations via <I>using-declaration</I>s</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12765,11 +12765,11 @@ and <I>POD class</I></td>
<td>Polymorphic behavior during destruction</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2159">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2159">2159</a></td>
- <td>concurrency</td>
+ <tr id="2159">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2159">2159</a></td>
+ <td>NAD</td>
<td>Lambda capture and local <TT>thread_local</TT> variables</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2160">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2160">2160</a></td>
@@ -12795,11 +12795,11 @@ and <I>POD class</I></td>
<td>Labels in <TT>constexpr</TT> functions</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2164">
+ <tr id="2164">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2164">2164</a></td>
- <td>drafting</td>
+ <td>tentatively ready</td>
<td>Name hiding and <I>using-directive</I>s</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2165">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2165">2165</a></td>
@@ -12856,8 +12856,8 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="2174">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2174">2174</a></td>
- <td>ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2174">2174</a></td>
+ <td>C++17</td>
<td>Unclear rules for friend definitions in templates</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12873,11 +12873,11 @@ and <I>POD class</I></td>
<td>Destroying the returned object when a destructor throws</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2177">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2177">2177</a></td>
- <td>drafting</td>
+ <tr id="2177">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2177">2177</a></td>
+ <td>DR</td>
<td>Placement <TT>operator delete</TT> and parameter copies</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="2178">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2178">2178</a></td>
@@ -12909,11 +12909,11 @@ and <I>POD class</I></td>
<td>Pointer arithmetic in array-like containers</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2183">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2183">2183</a></td>
- <td>review</td>
+ <tr id="2183">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2183">2183</a></td>
+ <td>NAD</td>
<td>Problems in description of potential exceptions</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="2184">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2184">2184</a></td>
@@ -12958,8 +12958,8 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="2191">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2191">2191</a></td>
- <td>ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2191">2191</a></td>
+ <td>C++17</td>
<td>Incorrect result for <TT>noexcept(typeid(v))</TT></td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12969,17 +12969,17 @@ and <I>POD class</I></td>
<td>Constant expressions and order-of-eval undefined behavior</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2193">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2193">2193</a></td>
- <td>open</td>
+ <tr id="2193">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2193">2193</a></td>
+ <td>NAD</td>
<td><TT>numeric_limits&lt;int&gt;::radix</TT> and <TT>digits</TT></td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr id="2194">
+ <tr class="open" id="2194">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2194">2194</a></td>
- <td>tentatively ready</td>
+ <td>review</td>
<td>Impossible case in list initialization</td>
- <td class="none" align="center">Unknown</td>
+ <td align="center">Not resolved</td>
</tr>
<tr class="open" id="2195">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2195">2195</a></td>
@@ -12987,39 +12987,39 @@ and <I>POD class</I></td>
<td>Unsolicited reading of trailing volatile members</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2196">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2196">2196</a></td>
- <td>open</td>
+ <tr id="2196">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2196">2196</a></td>
+ <td>C++17</td>
<td>Zero-initialization with virtual base classes</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2197">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2197">2197</a></td>
- <td>open</td>
+ <td>review</td>
<td>Overload resolution and deleted special member functions</td>
<td align="center">Not resolved</td>
</tr>
<tr id="2198">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2198">2198</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2198">2198</a></td>
+ <td>C++17</td>
<td>Linkage of enumerators</td>
<td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2199">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2199">2199</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Typedefs and tags</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2200">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2200">2200</a></td>
- <td>open</td>
+ <tr id="2200">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2200">2200</a></td>
+ <td>NAD</td>
<td>Conversions in template argument deduction</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="2201">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2201">2201</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2201">2201</a></td>
+ <td>C++17</td>
<td>Cv-qualification of array types</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -13031,31 +13031,31 @@ and <I>POD class</I></td>
</tr>
<tr class="open" id="2203">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2203">2203</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Defaulted copy/move constructors and UDCs</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2204">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2204">2204</a></td>
- <td>open</td>
+ <tr id="2204">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2204">2204</a></td>
+ <td>NAD</td>
<td>Naming delegated constructors</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="2205">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2205">2205</a></td>
- <td>ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2205">2205</a></td>
+ <td>C++17</td>
<td>Restrictions on use of <TT>alignas</TT></td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2206">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2206">2206</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2206">2206</a></td>
+ <td>C++17</td>
<td>Composite type of object and function pointers</td>
<td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2207">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2207">2207</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Alignment of allocation function return value</td>
<td align="center">Not resolved</td>
</tr>
@@ -13077,11 +13077,11 @@ and <I>POD class</I></td>
<td>Principal/target constructor confusion</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2211">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2211">2211</a></td>
- <td>open</td>
+ <tr id="2211">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2211">2211</a></td>
+ <td>C++17</td>
<td>Hiding by lambda captures and parameters</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2212">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2212">2212</a></td>
@@ -13091,37 +13091,37 @@ and <I>POD class</I></td>
</tr>
<tr class="open" id="2213">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2213">2213</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Forward declaration of partial specializations</td>
<td align="center">Not resolved</td>
</tr>
<tr id="2214">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2214">2214</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2214">2214</a></td>
+ <td>C++17</td>
<td>Missing requirement on representation of integer values</td>
<td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2215">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2215">2215</a></td>
- <td>open</td>
+ <td>review</td>
<td>Redundant description of language linkage in function call</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2216">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2216">2216</a></td>
- <td>open</td>
+ <tr id="2216">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2216">2216</a></td>
+ <td>NAD</td>
<td>Exception specifications in unevaluated contexts</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2217">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2217">2217</a></td>
- <td>open</td>
+ <tr id="2217">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2217">2217</a></td>
+ <td>NAD</td>
<td><TT>constexpr</TT> constructors for non-literal types</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="2218">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2218">2218</a></td>
- <td>ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2218">2218</a></td>
+ <td>C++17</td>
<td>Ambiguity and namespace aliases</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -13132,76 +13132,76 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="2220">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2220">2220</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2220">2220</a></td>
+ <td>C++17</td>
<td>Hiding index variable in range-based <TT>for</TT></td>
<td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2221">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2221">2221</a></td>
- <td>open</td>
+ <td>review</td>
<td>Copying volatile objects</td>
<td align="center">Not resolved</td>
</tr>
<tr class="open" id="2222">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2222">2222</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Additional contexts where instantiation is not required</td>
<td align="center">Not resolved</td>
</tr>
<tr class="open" id="2223">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2223">2223</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Multiple <TT>alignas</TT> specifiers</td>
<td align="center">Not resolved</td>
</tr>
<tr id="2224">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2224">2224</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2224">2224</a></td>
+ <td>C++17</td>
<td>Member subobjects and base-class casts</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2225">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2225">2225</a></td>
- <td>open</td>
+ <tr id="2225">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2225">2225</a></td>
+ <td>NAD</td>
<td><TT>reinterpret_cast</TT> to same floating-point type</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2226">
+ <tr id="2226">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2226">2226</a></td>
- <td>open</td>
+ <td>tentatively ready</td>
<td>Xvalues vs lvalues in conditional expressions</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2227">
+ <tr id="2227">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2227">2227</a></td>
- <td>open</td>
+ <td>tentatively ready</td>
<td>Destructor access and default member initializers</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2228">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2228">2228</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Ambiguity resolution for cast to function type</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2229">
+ <tr id="2229">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2229">2229</a></td>
- <td>open</td>
+ <td>tentatively ready</td>
<td>Volatile unnamed bit-fields</td>
- <td align="center">Not resolved</td>
+ <td class="svn" align="center">SVN</td>
</tr>
- <tr class="open" id="2230">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2230">2230</a></td>
- <td>open</td>
+ <tr id="2230">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2230">2230</a></td>
+ <td>NAD</td>
<td>Linkage of <TT>extern "C"</TT> function in unnamed namespace</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2231">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2231">2231</a></td>
- <td>open</td>
+ <tr id="2231">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2231">2231</a></td>
+ <td>NAD</td>
<td>Class member access to static data member template</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2232">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2232">2232</a></td>
@@ -13209,47 +13209,47 @@ and <I>POD class</I></td>
<td><TT>thread_local</TT> anonymous unions</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2233">
+ <tr id="2233">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2233">2233</a></td>
- <td>open</td>
+ <td>tentatively ready</td>
<td>Function parameter packs following default arguments</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2234">
+ <tr id="2234">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2234">2234</a></td>
- <td>open</td>
+ <td>tentatively ready</td>
<td>Missing rules for <I>simple-template-id</I> as <I>class-name</I></td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2235">
+ <tr id="2235">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2235">2235</a></td>
- <td>open</td>
+ <td>tentatively ready</td>
<td>Partial ordering and non-dependent types</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2236">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2236">2236</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>When is an alias template specialization dependent?</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2237">
+ <tr id="2237">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2237">2237</a></td>
- <td>open</td>
+ <td>tentatively ready</td>
<td>Can a <I>template-id</I> name a constructor?</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2238">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2238">2238</a></td>
- <td>open</td>
+ <tr id="2238">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2238">2238</a></td>
+ <td>NAD</td>
<td>Contradictory alignment requirements for allocation</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2239">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2239">2239</a></td>
- <td>open</td>
+ <tr id="2239">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2239">2239</a></td>
+ <td>NAD</td>
<td>Sized deallocation with a trivial destructor</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2240">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2240">2240</a></td>
@@ -13271,7 +13271,7 @@ and <I>POD class</I></td>
</tr>
<tr class="open" id="2243">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2243">2243</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Incorrect use of implicit conversion sequence</td>
<td align="center">Not resolved</td>
</tr>
@@ -13293,23 +13293,23 @@ and <I>POD class</I></td>
<td>Access of indirect virtual base class constructors</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2247">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2247">2247</a></td>
- <td>open</td>
+ <tr id="2247">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2247">2247</a></td>
+ <td>C++17</td>
<td>Lambda capture and variable argument list</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2248">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2248">2248</a></td>
- <td>review</td>
+ <tr id="2248">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2248">2248</a></td>
+ <td>C++17</td>
<td>Problems with sized delete</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2249">
+ <tr id="2249">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2249">2249</a></td>
- <td>open</td>
+ <td>tentatively ready</td>
<td><I>identifier</I>s and <I>id-expression</I>s</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2250">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2250">2250</a></td>
@@ -13317,11 +13317,11 @@ and <I>POD class</I></td>
<td>Implicit instantiation, destruction, and TUs</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2251">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2251">2251</a></td>
- <td>review</td>
+ <tr id="2251">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2251">2251</a></td>
+ <td>C++17</td>
<td>Unreachable enumeration list-initialization</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2252">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2252">2252</a></td>
@@ -13329,23 +13329,23 @@ and <I>POD class</I></td>
<td>Enumeration list-initialization from the same type</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2253">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2253">2253</a></td>
- <td>open</td>
+ <tr id="2253">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2253">2253</a></td>
+ <td>DRWP</td>
<td>Unnamed bit-fields and zero-initialization</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2254">
+ <tr id="2254">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2254">2254</a></td>
- <td>open</td>
- <td>Standard-layout classes and unnamed bit-fields</td>
- <td align="center">Not resolved</td>
+ <td>tentatively ready</td>
+ <td>Standard-layout classes and bit-fields</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2255">
+ <tr id="2255">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2255">2255</a></td>
- <td>open</td>
+ <td>tentatively ready</td>
<td>Instantiated static data member templates</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2256">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2256">2256</a></td>
@@ -13366,16 +13366,16 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="2259">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2259">2259</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2259">2259</a></td>
+ <td>C++17</td>
<td>Unclear context describing ambiguity</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2260">
+ <tr id="2260">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2260">2260</a></td>
- <td>open</td>
+ <td>tentatively ready</td>
<td>Explicit specializations of deleted member functions</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2261">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2261">2261</a></td>
@@ -13384,8 +13384,8 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="2262">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2262">2262</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2262">2262</a></td>
+ <td>C++17</td>
<td>Attributes for <I>asm-definition</I></td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -13419,66 +13419,540 @@ and <I>POD class</I></td>
<td>Copy-initialization of temporary in reference direct-initialization</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2268">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2268">2268</a></td>
- <td>open</td>
+ <tr id="2268">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2268">2268</a></td>
+ <td>C++17</td>
<td>Unions with mutable members in constant expressions revisited</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2269">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2269">2269</a></td>
- <td>open</td>
+ <tr id="2269">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2269">2269</a></td>
+ <td>dup</td>
<td>Additional recursive references in aggregate DMIs</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2270">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2270">2270</a></td>
- <td>open</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2270">2270</a></td>
+ <td>extension</td>
<td>Non-inline functions and explicit instantiation declarations</td>
<td align="center">Not resolved</td>
</tr>
<tr id="2271">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2271">2271</a></td>
- <td>DR</td>
+ <td>C++17</td>
<td>Aliasing <TT>this</TT></td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2272">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2272">2272</a></td>
- <td>open</td>
+ <tr id="2272">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2272">2272</a></td>
+ <td>C++17</td>
<td>Implicit initialization of aggregate members of reference type</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr id="2273">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2273">2273</a></td>
+ <td>DRWP</td>
+ <td>Inheriting constructors vs implicit default constructor</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr id="2274">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2274">2274</a></td>
+ <td>NAD</td>
+ <td>Generic lambda capture vs constexpr if</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr class="open" id="2275">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2275">2275</a></td>
+ <td>drafting</td>
+ <td>Type-dependence of function template</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2273">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2273">2273</a></td>
+ <tr id="2276">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2276">2276</a></td>
+ <td>C++17</td>
+ <td>Dependent <TT>noexcept</TT> and function type-dependence</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr id="2277">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2277">2277</a></td>
+ <td>DRWP</td>
+ <td>Ambiguity inheriting constructors with default arguments</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr class="open" id="2278">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2278">2278</a></td>
<td>open</td>
- <td>Inheriting constructors vs implicit default constructor</td>
+ <td>Copy elision in constant expressions reconsidered</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr id="2279">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2279">2279</a></td>
+ <td>NAD</td>
+ <td>Multiple <I>attribute-specifier</I>s in one <I>attribute-list</I></td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr class="open" id="2280">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2280">2280</a></td>
+ <td>review</td>
+ <td>Matching a usual deallocation function with placement new</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2274">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2274">2274</a></td>
+ <tr class="open" id="2281">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2281">2281</a></td>
<td>open</td>
- <td>Generic lambda capture vs constexpr if</td>
+ <td>Consistency of aligned <TT>operator delete</TT> replacement</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2275">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2275">2275</a></td>
+ <tr class="open" id="2282">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2282">2282</a></td>
+ <td>drafting</td>
+ <td>Consistency with mismatched aligned/non-over-aligned allocation/deallocation functions</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2283">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2283">2283</a></td>
+ <td>drafting</td>
+ <td>Missing complete type requirements</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2284">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2284">2284</a></td>
<td>open</td>
- <td>Type-dependence of function template</td>
+ <td>Sequencing of <I>braced-init-list</I> arguments</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr id="2285">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2285">2285</a></td>
+ <td>tentatively ready</td>
+ <td>Issues with structured bindings</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr id="2286">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2286">2286</a></td>
+ <td>NAD</td>
+ <td>Assignment evaluation order</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr id="2287">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2287">2287</a></td>
+ <td>DRWP</td>
+ <td>Pointer-interconvertibility in non-standard-layout unions</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr id="2288">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2288">2288</a></td>
+ <td>NAD</td>
+ <td>Contradictory optionality in <I>simple-declaration</I></td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr class="open" id="2289">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2289">2289</a></td>
+ <td>drafting</td>
+ <td>Uniqueness of decomposition declaration names</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr id="2290">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2290">2290</a></td>
+ <td>DRWP</td>
+ <td>Unclear specification for overload resolution and deleted special member functions</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr id="2291">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2291">2291</a></td>
+ <td>dup</td>
+ <td>Implicit conversion sequences in non-call contexts</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr class="open" id="2292">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2292">2292</a></td>
+ <td>drafting</td>
+ <td><I>simple-template-id</I> is ambiguous between <I>class-name</I> and <I>type-name</I></td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2293">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2293">2293</a></td>
+ <td>drafting</td>
+ <td>Requirements for <I>simple-template-id</I> used as a <I>class-name</I></td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2294">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2294">2294</a></td>
+ <td>drafting</td>
+ <td>Dependent <TT>auto</TT> static data members</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2295">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2295">2295</a></td>
+ <td>extension</td>
+ <td>Aggregates with deleted defaulted constructors</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2296">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2296">2296</a></td>
+ <td>extension</td>
+ <td>Are default argument instantiation failures in the &#8220;immediate context&#8221;?</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2297">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2297">2297</a></td>
+ <td>review</td>
+ <td>Unclear specification of atomic operations</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2298">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2298">2298</a></td>
+ <td>concurrency</td>
+ <td>Actions and expression evaluation</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr id="2299">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2299">2299</a></td>
+ <td>tentatively ready</td>
+ <td><TT>constexpr</TT> vararg functions</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr class="open" id="2300">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2300">2300</a></td>
+ <td>drafting</td>
+ <td>Lambdas in multiple definitions</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2276">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2276">2276</a></td>
+ <tr class="open" id="2301">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2301">2301</a></td>
<td>open</td>
- <td>Dependent <TT>noexcept</TT> and function type-dependence</td>
+ <td>Value-initialization and constexpr constructor evaluation</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2277">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2277">2277</a></td>
+ <tr id="2302">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2302">2302</a></td>
+ <td>NAD</td>
+ <td>Address comparison between different member subobjects</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr class="open" id="2303">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2303">2303</a></td>
<td>open</td>
- <td>Ambiguity inheriting constructors with default arguments</td>
+ <td>Partial ordering and recursive variadic inheritance</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr id="2304">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2304">2304</a></td>
+ <td>NAD</td>
+ <td>Incomplete type vs overload resolution</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr id="2305">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2305">2305</a></td>
+ <td>DR</td>
+ <td>Explicit instantiation of constexpr or inline variable template</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr class="open" id="2306">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2306">2306</a></td>
+ <td>open</td>
+ <td>Nested friend templates of class templates</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr id="2307">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2307">2307</a></td>
+ <td>DR</td>
+ <td>Unclear definition of &#8220;equivalent to a nontype template parameter&#8221;</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr class="open" id="2308">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2308">2308</a></td>
+ <td>open</td>
+ <td>Structured bindings and lambda capture</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2309">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2309">2309</a></td>
+ <td>drafting</td>
+ <td>Restrictions on nested statements within <TT>constexpr</TT> functions</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2310">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2310">2310</a></td>
+ <td>open</td>
+ <td>Type completeness and derived-to-base pointer conversions</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2311">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2311">2311</a></td>
+ <td>open</td>
+ <td>Missed case for guaranteed copy elision</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2312">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2312">2312</a></td>
+ <td>drafting</td>
+ <td>Structured bindings and <TT>mutable</TT></td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr id="2313">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2313">2313</a></td>
+ <td>DR</td>
+ <td>Redeclaration of structured binding reference variables</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr id="2314">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2314">2314</a></td>
+ <td>dup</td>
+ <td>Structured bindings and lambda capture</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr id="2315">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2315">2315</a></td>
+ <td>DR</td>
+ <td>What is the &#8220;corresponding special member&#8221; of a variant member?</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr class="open" id="2316">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2316">2316</a></td>
+ <td>drafting</td>
+ <td>Simplifying class conversions in conditional expressions</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2317">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2317">2317</a></td>
+ <td>open</td>
+ <td>Self-referential default member initializers</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2318">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2318">2318</a></td>
+ <td>drafting</td>
+ <td>Nondeduced contexts in deduction from a <I>braced-init-list</I></td>
<td align="center">Not resolved</td>
</tr>
+ <tr class="open" id="2319">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2319">2319</a></td>
+ <td>drafting</td>
+ <td>Nested brace initialization from same type</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2320">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2320">2320</a></td>
+ <td>extension</td>
+ <td><TT>constexpr if</TT> and boolean conversions</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2321">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2321">2321</a></td>
+ <td>drafting</td>
+ <td>Conditional operator and cv-qualified class prvalues</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2322">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2322">2322</a></td>
+ <td>drafting</td>
+ <td>Substitution failure and lexical order</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2323">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2323">2323</a></td>
+ <td>drafting</td>
+ <td>Expunge POD</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2324">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2324">2324</a></td>
+ <td>drafting</td>
+ <td>Size of base class subobject</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2325">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2325">2325</a></td>
+ <td>drafting</td>
+ <td><TT>std::launder</TT> and reuse of character buffers</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr id="2326">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2326">2326</a></td>
+ <td>dup</td>
+ <td>Type deduction with initializer list containing ambiguous functions</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr class="open" id="2327">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2327">2327</a></td>
+ <td>drafting</td>
+ <td>Copy elision for direct-initialization with a conversion function</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2328">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2328">2328</a></td>
+ <td>open</td>
+ <td>Unclear presentation style of template argument deduction rules</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2329">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2329">2329</a></td>
+ <td>drafting</td>
+ <td>Virtual base classes and generated assignment operators</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2330">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2330">2330</a></td>
+ <td>drafting</td>
+ <td>Missing references to variable templates</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2331">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2331">2331</a></td>
+ <td>drafting</td>
+ <td>Redundancy in description of class scope</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2332">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2332">2332</a></td>
+ <td>drafting</td>
+ <td><I>template-name</I> as <I>simple-type-name</I> vs injected-class-name</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2333">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2333">2333</a></td>
+ <td>drafting</td>
+ <td>Escape sequences in UTF-8 character literals</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2334">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2334">2334</a></td>
+ <td>open</td>
+ <td>Creation of objects by <TT>typeid</TT></td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2335">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2335">2335</a></td>
+ <td>open</td>
+ <td>Deduced return types vs member types</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2336">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2336">2336</a></td>
+ <td>drafting</td>
+ <td>Destructor characteristics vs potentially-constructed subobjects</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2337">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2337">2337</a></td>
+ <td>open</td>
+ <td>Incorrect implication of logic ladder for conversion sequence tiebreakers</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr id="2338">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2338">2338</a></td>
+ <td>DR</td>
+ <td>Undefined behavior converting to short enums with fixed underlying types</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr class="open" id="2339">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2339">2339</a></td>
+ <td>drafting</td>
+ <td>Underspecified template arguments in structured bindings</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2340">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2340">2340</a></td>
+ <td>open</td>
+ <td>Reference collapsing and structured bindings</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2341">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2341">2341</a></td>
+ <td>extension</td>
+ <td>Structured bindings with static storage duration</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr id="2342">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2342">2342</a></td>
+ <td>DR</td>
+ <td>Reference <TT>reinterpret_cast</TT> and pointer-interconvertibility</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr class="open" id="2343">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2343">2343</a></td>
+ <td>open</td>
+ <td><TT>void*</TT> non-type template parameters</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2344">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2344">2344</a></td>
+ <td>open</td>
+ <td>Redeclaration of names in <I>init-statement</I>s</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2345">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2345">2345</a></td>
+ <td>open</td>
+ <td>Jumping across initializers in <I>init-statement</I>s and <I>condition</I>s</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2346">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2346">2346</a></td>
+ <td>open</td>
+ <td>Local variables in default arguments</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2347">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2347">2347</a></td>
+ <td>open</td>
+ <td>Passing short scoped enumerations to ellipsis</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2348">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2348">2348</a></td>
+ <td>open</td>
+ <td>Non-templated <TT>constexpr if</TT></td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2349">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2349">2349</a></td>
+ <td>open</td>
+ <td>Class/enumeration names vs conditions</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2350">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2350">2350</a></td>
+ <td>open</td>
+ <td>Forwarding references and deduction guides</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2351">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2351">2351</a></td>
+ <td>open</td>
+ <td><TT>void{}</TT></td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2352">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2352">2352</a></td>
+ <td>open</td>
+ <td>Similar types and reference binding</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2353">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2353">2353</a></td>
+ <td>open</td>
+ <td>Potential results of a member access expression for a static data member</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2354">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2354">2354</a></td>
+ <td>open</td>
+ <td>Extended alignment and object representation</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2355">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2355">2355</a></td>
+ <td>open</td>
+ <td>Deducing <I>noexcept-specifier</I>s</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr id="2356">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2356">2356</a></td>
+ <td>tentatively ready</td>
+ <td>Base class copy and move constructors should not be inherited</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
</table>
</div>
diff --git a/www/cxx_status.html b/www/cxx_status.html
index 0f93758e428c..7318b0bab885 100644
--- a/www/cxx_status.html
+++ b/www/cxx_status.html
@@ -26,7 +26,7 @@
<!--*************************************************************************-->
<h1>C++ Support in Clang</h1>
<!--*************************************************************************-->
-<p>Last updated: $Date: 2017-12-01 00:07:29 +0100 (Fri, 01 Dec 2017) $</p>
+<p>Last updated: $Date: 2018-07-27 06:41:37 +0200 (Fri, 27 Jul 2018) $</p>
<p>Clang fully implements all published ISO C++ standards (<a
href="#cxx98">C++98 / C++03</a>, <a
@@ -56,7 +56,7 @@ each language mode.</p>
<h2 id="cxx11">C++11 implementation status</h2>
<p>Clang 3.3 and later implement all of the <a
- href="http://www.iso.org/iso/catalogue_detail.htm?csnumber=50372">ISO
+ href="http://www.iso.org/standard/50372.html">ISO
C++ 2011 standard</a>.
<p>By default, Clang builds C++ code according to the C++98 standard, with many
@@ -134,10 +134,15 @@ with <a href="http://libcxx.llvm.org/">libc++</a> or with gcc's libstdc++.
<td class="full" align="center">Clang 2.9</td>
</tr>
<tr>
- <td>Lambda expressions</td>
+ <td rowspan="2">Lambda expressions</td>
<td><a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2927.pdf">N2927</a></td>
<td class="full" align="center">Clang 3.1</td>
</tr>
+ <tr>
+ <!-- from Albuquerque 2017 -->
+ <td><a href="http://wg21.link/p0588r1">P0588R1</a> (<a href="#dr">DR</a>)</td>
+ <td class="none" align="center">No</td>
+ </tr>
<tr>
<td>Declared type of an expression</td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2343.pdf">N2343</a></td>
@@ -195,10 +200,15 @@ with <a href="http://libcxx.llvm.org/">libc++</a> or with gcc's libstdc++.
<td class="full" align="center">Clang 3.3 <a href="#n2761">(1)</a></td>
</tr>
<tr>
- <td>Generalized constant expressions</td>
+ <td rowspan="2">Generalized constant expressions</td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdf">N2235</a></td>
<td class="full" align="center">Clang 3.1</td>
</tr>
+ <tr>
+ <!-- from Albuquerque 2017 -->
+ <td><a href="http://wg21.link/p0859r0">P0859R0</a> (<a href="#dr">DR</a>)</td>
+ <td class="none" align="center">No</td>
+ </tr>
<tr>
<td>Alignment support</td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2341.pdf">N2341</a></td>
@@ -220,10 +230,15 @@ with <a href="http://libcxx.llvm.org/">libc++</a> or with gcc's libstdc++.
<td class="full" align="center">Clang 3.0</td>
</tr>
<tr>
- <td>Inheriting constructors</td>
+ <td rowspan="2">Inheriting constructors</td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2540.htm">N2540</a></td>
<td class="full" align="center">Clang 3.3</td>
</tr>
+ <tr>
+ <!-- from Kona 2015 -->
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0136r1.html">P0136R1</a> (<a href="#dr">DR</a>)</td>
+ <td class="full" align="center">Clang 3.9</td>
+ </tr>
<tr>
<td>Explicit conversion operators</td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2437.pdf">N2437</a></td>
@@ -296,10 +311,15 @@ with <a href="http://libcxx.llvm.org/">libc++</a> or with gcc's libstdc++.
<td class="full" align="center">Clang 2.9</td>
</tr>
<tr>
- <td>Range-based for</td>
+ <td rowspan="2">Range-based for</td>
<td><a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2930.html">N2930</a></td>
<td class="full" align="center">Clang 3.0</td>
</tr>
+ <tr>
+ <!-- from Jacksonville 2018 -->
+ <td><a href="http://wg21.link/p0962r1">P0962R1</a> (<a href="#dr">DR</a>)</td>
+ <td class="none" align="center">No</td>
+ </tr>
<tr>
<td>Explicit virtual overrides</td>
<td><a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2928.htm">N2928</a>
@@ -427,7 +447,7 @@ change.</span>
<h2 id="cxx14">C++14 implementation status</h2>
<p>Clang 3.4 and later implement all of the <a
- href="http://www.iso.org/iso/catalogue_detail.htm?csnumber=64029">ISO
+ href="http://www.iso.org/standard/64029.html">ISO
C++ 2014 standard</a>.
<p>You can use Clang in C++14 mode with the <code>-std=c++14</code> option
@@ -521,8 +541,8 @@ version 3.7.
<h2 id="cxx17">C++17 implementation status</h2>
-<p>Clang 5 and later implement all the features
-of the C++ 2017 Draft International Standard.
+<p>Clang 5 and later implement all the features of the
+<a href="https://www.iso.org/standard/68564.html">ISO C++ 2017 standard</a>.
<p>You can use Clang in C++17 mode with the <code>-std=c++17</code> option
(use <code>-std=c++1z</code> in Clang 4 and earlier).</p>
@@ -619,11 +639,6 @@ of the C++ 2017 Draft International Standard.
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0061.html">P0061R1</a></td>
<td class="full" align="center">Yes</td>
</tr>
- <tr>
- <td>New specification for inheriting constructors (<a href="cxx_dr_status.html#1941">DR1941</a> et al)</td>
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0136r1.html">P0136R1</a></td>
- <td class="full" align="center">Clang 3.9 <a href="#p0136">(9)</a></td>
- </tr>
<!-- Jacksonville papers -->
<tr>
<td><tt>[[fallthrough]]</tt> attribute</td>
@@ -682,13 +697,23 @@ of the C++ 2017 Draft International Standard.
<td class="full" align="center">Clang 4</td>
</tr>
<tr>
- <td rowspan="2">Template argument deduction for class templates</td>
+ <td rowspan="4">Template argument deduction for class templates</td>
<td><a href="http://wg21.link/p0091r3">P0091R3</a></td>
<td rowspan="2" class="full" align="center">Clang 5</td>
</tr>
<tr> <!-- from Issaquah -->
<td><a href="http://wg21.link/p0512r0">P0512R0</a></td>
</tr>
+ <tr>
+ <!-- from Kona 2017 -->
+ <td><a href="http://wg21.link/p0620r1">P0620R0</a> (<a href="#dr">DR</a>)</td>
+ <td class="svn" align="center">SVN</td>
+ </tr>
+ <tr>
+ <!-- from Toronto 2017 -->
+ <td><a href="http://wg21.link/p0702r1">P0702R1</a> (<a href="#dr">DR</a>)</td>
+ <td class="full" align="center">Clang 6</td>
+ </tr>
<tr>
<td>Non-type template parameters with <tt>auto</tt> type</td>
<td><a href="http://wg21.link/p0127r2">P0127R2</a></td>
@@ -702,7 +727,7 @@ of the C++ 2017 Draft International Standard.
<tr>
<td rowspan=2>Stricter expression evaluation order</td>
<td><a href="http://wg21.link/p0145r3">P0145R3</a></td>
- <td class="full" align="center" rowspan=2>Clang 4 <a href="#p0145">(10)</a></td>
+ <td class="full" align="center" rowspan=2>Clang 4 <a href="#p0145">(9)</a></td>
</tr>
<tr>
<td><a href="http://wg21.link/p0400r0">P0400R0</a></td>
@@ -723,10 +748,20 @@ of the C++ 2017 Draft International Standard.
<td class="full" align="center">Clang 3.9</td>
</tr>
<tr>
- <td>Structured bindings</td>
+ <td rowspan="3">Structured bindings</td>
<td><a href="http://wg21.link/p0217r3">P0217R3</a></td>
<td class="full" align="center">Clang 4</td>
</tr>
+ <tr>
+ <!-- from Jacksonville 2018 -->
+ <td><a href="http://wg21.link/p0961r1">P0961R1</a> (<a href="#dr">DR</a>)</td>
+ <td class="none" align="center">No</td>
+ </tr>
+ <tr>
+ <!-- from Jacksonville 2018 -->
+ <td><a href="http://wg21.link/p0969r0">P0969R0</a> (<a href="#dr">DR</a>)</td>
+ <td class="none" align="center">No</td>
+ </tr>
<tr>
<td>Separate variable and condition for <tt>if</tt> and <tt>switch</tt></td>
<td><a href="http://wg21.link/p0305r1">P0305R1</a></td>
@@ -736,7 +771,7 @@ of the C++ 2017 Draft International Standard.
<tr>
<td>Matching template template parameters to compatible arguments</td>
<td><a href="http://wg21.link/p0522r0">P0522R0</a></td>
- <td class="partial" align="center">Partial <a href="#p0522">(12)</a></td>
+ <td class="partial" align="center">Partial <a href="#p0522">(10)</a></td>
</tr>
<tr>
<td>Removing deprecated dynamic exception specifications</td>
@@ -756,17 +791,14 @@ all language versions that allow type deduction from <tt>auto</tt>
(per the request of the C++ committee).
In Clang 3.7, a warning is emitted for all cases that would change meaning.
</span><br>
-<span id="p0136">(9): This is the resolution to a Defect Report, so is applied
-to all language versions supporting inheriting constructors.
-</span><br>
-<span id="p0145">(10): Under the MS ABI, function parameters are destroyed from
+<span id="p0145">(9): Under the MS ABI, function parameters are destroyed from
left to right in the callee. As a result, function parameters in calls to
<tt>operator&lt;&lt;</tt>, <tt>operator&gt;&gt;</tt>, <tt>operator-&gt;*</tt>,
<tt>operator&amp;&amp;</tt>, <tt>operator||</tt>, and <tt>operator,</tt>
functions using expression syntax are no longer guaranteed to be destroyed in
reverse construction order in that ABI.
</span><br>
-<span id="p0522">(12): Despite being the the resolution to a Defect Report, this
+<span id="p0522">(10): Despite being the resolution to a Defect Report, this
feature is disabled by default in all language versions, and can be enabled
explicitly with the flag <tt>-frelaxed-template-template-args</tt> in Clang 4
onwards.
@@ -799,23 +831,27 @@ as the draft C++2a standard evolves.
<tr>
<td>Default member initializers for bit-fields</td>
<td><a href="http://wg21.link/p0683r1">P0683R1</a></td>
- <td class="svn" align="center">SVN</td>
+ <td class="full" align="center">Clang 6</td>
</tr>
<tr>
<td><tt>const&amp;</tt>-qualified pointers to members</td>
<td><a href="http://wg21.link/p0704r1">P0704R1</a></td>
- <td class="svn" align="center">SVN</td>
+ <td class="full" align="center">Clang 6</td>
</tr>
<tr>
<td>Allow <i>lambda-capture</i> <tt>[=, this]</tt></td>
<td><a href="http://wg21.link/p0409r2">P0409R2</a></td>
- <td class="svn" align="center">SVN</td>
+ <td class="full" align="center">Clang 6</td>
</tr>
<tr>
- <td><tt>__VA_OPT__</tt> for preprocessor comma elision</td>
+ <td rowspan="2"><tt>__VA_OPT__</tt> for preprocessor comma elision</td>
<td><a href="http://wg21.link/p0306r4">P0306R4</a></td>
- <td class="svn" align="center">SVN</td>
+ <td class="full" align="center">Clang 6</td>
</tr>
+ <tr> <!-- from Rapperswil -->
+ <td><a href="http://wg21.link/p1042r1">P1042R1</a></td>
+ <td class="partial" align="center">Partial</td>
+ </tr>
<tr>
<td>Designated initializers</td>
<td><a href="http://wg21.link/p0329r4">P0329R4</a></td>
@@ -826,11 +862,6 @@ as the draft C++2a standard evolves.
<td><a href="http://wg21.link/p0428r2">P0428R2</a></td>
<td class="none" align="center">No</td>
</tr>
- <tr>
- <td>Initializer list constructors in class template argument deduction</td>
- <td><a href="http://wg21.link/p0702r1">P0702R1</a></td>
- <td class="svn" align="center">SVN <a href="#p0702">(13)</a></td>
- </tr>
<tr id="p0734">
<td rowspan="2">Concepts</td>
<td><a href="http://wg21.link/p0734r0">P0734R0</a></td>
@@ -846,11 +877,6 @@ as the draft C++2a standard evolves.
<td class="none" align="center">No</td>
</tr>
<tr>
- <td>Simplifying implicit lambda capture</td>
- <td><a href="http://wg21.link/p0588r1">P0588R1</a></td>
- <td class="none" align="center">No <a href="#p0588">(14)</a></td>
- </tr>
- <tr>
<td>ADL and function templates that are not visible</td>
<td><a href="http://wg21.link/p0846r0">P0846R0</a></td>
<td class="none" align="center">No</td>
@@ -861,15 +887,16 @@ as the draft C++2a standard evolves.
<td class="none" align="center">No</td>
</tr>
<tr>
- <td>Less eager instantiation of <tt>constexpr</tt> functions</td>
- <td><a href="http://wg21.link/p0859r0">P0859R0</a></td>
- <td class="none" align="center">No <a href="#p0859">(15)</a></td>
- </tr>
- <tr>
- <td>Consistent comparison (<tt>operator&lt;=&gt;</tt>)</td>
+ <td rowspan="3">Consistent comparison (<tt>operator&lt;=&gt;</tt>)</td>
<td><a href="http://wg21.link/p0515r3">P0515R3</a></td>
- <td class="none" align="center">No</td>
+ <td rowspan="3" class="partial" align="center">Partial</td>
</tr>
+ <tr> <!-- from Jacksonville -->
+ <td><a href="http://wg21.link/p0905r1">P0905R1</a></td>
+ </tr>
+ <tr> <!-- from Rapperswil -->
+ <td><a href="http://wg21.link/p1120r0">P1120R0</a></td>
+ </tr>
<tr>
<td>Access checking on specializations</td>
<td><a href="http://wg21.link/p0692r1">P0692R1</a></td>
@@ -885,20 +912,79 @@ as the draft C++2a standard evolves.
<td><a href="http://wg21.link/p0315r4">P0315R4</a></td>
<td class="none" align="center">No</td>
</tr>
+ <!-- Jacksonville papers -->
+ <tr>
+ <td><tt>[[no_unique_address]]</tt> attribute</td>
+ <td><a href="http://wg21.link/p0840r2">P0840R2</a></td>
+ <td class="none" align="center">No</td>
+ </tr>
+ <tr>
+ <td><tt>[[likely]]</tt> and <tt>[[unlikely]]</tt> attributes</td>
+ <td><a href="http://wg21.link/p0479r5">P0479R5</a></td>
+ <td class="none" align="center">No</td>
+ </tr>
+ <tr>
+ <td><tt>typename</tt> optional in more contexts</td>
+ <td><a href="http://wg21.link/p0634r3">P0634R3</a></td>
+ <td class="none" align="center">No</td>
+ </tr>
+ <tr>
+ <td>Pack expansion in lambda <i>init-capture</i></td>
+ <td><a href="http://wg21.link/p0780r2">P0780R2</a></td>
+ <td class="none" align="center">No</td>
+ </tr>
+ <!-- Rapperswil papers -->
+ <tr>
+ <td>Class types as non-type template parameters</td>
+ <td><a href="http://wg21.link/p0732r2">P0732R2</a></td>
+ <td class="none" align="center">No</td>
+ </tr>
+ <tr>
+ <td>Destroying operator delete</td>
+ <td><a href="http://wg21.link/p0722r3">P0722R3</a></td>
+ <td class="full" align="center">Clang 6</td>
+ </tr>
+ <tr>
+ <td>Virtual function calls in constant expressions</td>
+ <td><a href="http://wg21.link/p1064r0">P1064R0</a></td>
+ <td class="none" align="center">No</td>
+ </tr>
+ <tr>
+ <td>Prohibit aggregates with user-declared constructors</td>
+ <td><a href="http://wg21.link/p1008r1">P1008R1</a></td>
+ <td class="none" align="center">No</td>
+ </tr>
+ <tr>
+ <td>Contracts</td>
+ <td><a href="http://wg21.link/p0542r5">P0542R5</a></td>
+ <td class="none" align="center">No</td>
+ </tr>
+ <tr>
+ <td>Feature test macros</td>
+ <td><a href="http://wg21.link/p0941r2">P0941R2</a></td>
+ <td class="full" align="center"><a href="#sd6">(see below)</a></td>
+ </tr>
+ <tr>
+ <td><tt>explicit(bool)</tt></td>
+ <td><a href="http://wg21.link/p0892r2">P0892R2</a></td>
+ <td class="none" align="center">No</td>
+ </tr>
</table>
</details>
-<p>
-<span id="p0702">(13): This is the resolution to a Defect Report, so is applied
-to all language versions supporting class template argument deduction.
-</span><br>
-<span id="p0588">(14): This is the resolution to a Defect Report, so will be applied
-to all language versions supporting lamba expressions.
-</span><br>
-<span id="p0859">(15): This is the resolution to a Defect Report, so will be applied
-to all language versions supporting <tt>constexpr</tt>.
-</span>
-</p>
+<h2 id="dr">Defect reports</h2>
+
+<p>Clang generally aims to implement resolutions to Defect Reports (bug fixes
+against prior standards) retroactively, in all prior standard versions where
+the fix is meaningful. Significant Defect Report changes to language features
+after the publication of the relevant standard are marked (DR) in the above
+table.</p>
+
+<p>Clang also has a test suite for conformance to resolutions for issues on the
+<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_toc.html">C++ core issues list</a>,
+most of which are considered Defect Reports.
+<a href="cxx_dr_status.html">Implementation status for C++ core issues</a> based on
+that test suite is tracked on a separate page.</p>
<h2 id="ts">Technical specifications and standing documents</h2>
@@ -915,10 +1001,10 @@ and library features that are not part of standard C++.</p>
<th>Compiler flag</th>
<th>Available in Clang?</th>
</tr>
- <tr>
- <td rowspan="4">SD-6: SG10 feature test recommendations</td>
- <td rowspan="4"><a href="http://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations">SD-6</a></td>
- <td rowspan="4">N/A</td>
+ <tr id="sd6">
+ <td rowspan="5">SD-6: SG10 feature test recommendations</td>
+ <td rowspan="5"><a href="http://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations">SD-6</a></td>
+ <td rowspan="5">N/A</td>
<td class="full" align="center">
Clang 3.4 (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3745">N3745</a>)</br>
</td>
@@ -938,6 +1024,11 @@ and library features that are not part of standard C++.</p>
Clang 5 (<a href="http://wg21.link/p0096r4">P0096R4</a>)</a>
</td>
</tr>
+ <tr>
+ <td class="svn" align="center">
+ SVN (<a href="http://wg21.link/p0096r5">P0096R5</a>)</a>
+ </td>
+ </tr>
<!-- FIXME: Implement latest recommendations.
<tr>
<td class="svn" align="center">
@@ -947,7 +1038,7 @@ and library features that are not part of standard C++.</p>
-->
<!-- No compiler support is known to be needed for:
* Concurrency TS
- * Parallelism TS
+ * Parallelism TS (v1, v2)
* Ranges TS
* Networking TS
* File System TS
@@ -959,6 +1050,7 @@ and library features that are not part of standard C++.</p>
<td class="na" align="center">Superseded by <a href="#p0734">P0734R0</a></td>
</tr>
<tr>
+ <!-- track unimplemented Coroutines features: p0913r1 p0914r1 -->
<td>[DRAFT TS] Coroutines</td>
<td><a href="https://isocpp.org/files/papers/N4663.pdf">N4663</a></td>
<td><tt>-fcoroutines-ts<br>-stdlib=libc++</tt></td>
@@ -971,18 +1063,24 @@ and library features that are not part of standard C++.</p>
<td class="none" align="center">No</td>
</tr>
<tr>
- <td>[DRAFT TS] Library Fundamentals, Version 2 (<tt>source_location</tt>)</td>
- <td><a href="http://wg21.link/n4600">N4600</a></td>
+ <td>[TS] Library Fundamentals, Version 2 (<tt>source_location</tt>)</td>
+ <td><a href="http://wg21.link/n4617">N4617</a></td>
<td>N/A</td>
<td class="none" align="center">No</td>
</tr>
<tr>
- <td>[DRAFT TS] Modules</td>
- <td><a href="http://wg21.link/n4667">N4667</a></td>
+ <td>[TS] Modules</td>
+ <td><a href="http://wg21.link/n4720">N4720</a></td>
<td><tt>-fmodules-ts</tt></td>
<td class="none" align="center">WIP</td>
</tr>
<tr>
+ <td>[DRAFT TS] Reflection</td>
+ <td><a href="http://wg21.link/n4746">N4746</a></td>
+ <td></td>
+ <td class="none" align="center">No</td>
+ </tr>
+ <tr>
<td>[TS] Transactional Memory</td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4514.pdf">N4514</a></td>
<td></td>
diff --git a/www/diagnostics.html b/www/diagnostics.html
index 00a3f9a9f689..2c9c7913612d 100644
--- a/www/diagnostics.html
+++ b/www/diagnostics.html
@@ -231,7 +231,7 @@ diagnostic.<p>
<h2>Template Type Diffing</h2>
-<p>Templates types can be long and difficult to read. Moreso when part of an
+<p>Templates types can be long and difficult to read. More so when part of an
error message. Instead of just printing out the type name, Clang has enough
information to remove the common elements and highlight the differences. To
show the template structure more clearly, the templated type can also be
diff --git a/www/features.html b/www/features.html
index 8a1c856cd1c0..8fe1209e1256 100644
--- a/www/features.html
+++ b/www/features.html
@@ -68,7 +68,7 @@ profile the cost of each layer of the stack, and the driver has a number of
options for performance analysis. Many detailed benchmarks can be found online.</p>
<p>Compile time performance is important, but when using clang as an API, often
-memory use is even moreso: the less memory the code takes the more code you can
+memory use is even more so: the less memory the code takes the more code you can
fit into memory at a time (useful for whole program analysis tools, for
example).</p>
diff --git a/www/get_involved.html b/www/get_involved.html
index fdd6b8f33c8c..27427cc55dfc 100644
--- a/www/get_involved.html
+++ b/www/get_involved.html
@@ -76,7 +76,7 @@ extensions may propose that the extensions become a part of Clang
itself, to benefit the whole Clang community. But not every idea--not
even every great idea--should become part of Clang. Extensions
(particularly language extensions) pose a long-term maintenance burden
-on Clang, and therefore the benefits of the extension must outweight
+on Clang, and therefore the benefits of the extension must outweigh
those costs. Hence, these are the seven criteria used to evaluate the
merits of a proposed extension:</p>
diff --git a/www/hacking.html b/www/hacking.html
index 96eb7f659474..f2f98f4a9f42 100644
--- a/www/hacking.html
+++ b/www/hacking.html
@@ -180,7 +180,7 @@
<p>Note that the test runner is based on
Python, which must be installed. Find Python at:
<a href="http://www.python.org/download/">http://www.python.org/download/</a>.
- Download the latest stable version (2.6.2 at the time of this writing).</p>
+ Download the latest stable version.</p>
<p>The GnuWin32 tools are also necessary for running the tests.
Get them from <a href="http://getgnuwin32.sourceforge.net/">
diff --git a/www/index.html b/www/index.html
index 63ecc38c8628..3bc7020f07e1 100644
--- a/www/index.html
+++ b/www/index.html
@@ -4,7 +4,7 @@
<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>"clang" C Language Family Frontend for LLVM</title>
+ <title>Clang C Language Family Frontend for LLVM</title>
<link type="text/css" rel="stylesheet" href="menu.css">
<link type="text/css" rel="stylesheet" href="content.css">
</head>
@@ -12,13 +12,15 @@
<!--#include virtual="menu.html.incl"-->
<div id="content">
<!--*********************************************************************-->
- <h1>clang: a C language family frontend for LLVM</h1>
+ <h1>Clang: a C language family frontend for LLVM</h1>
<!--*********************************************************************-->
- <p>The goal of the Clang project is to create a new C based language
- front-end: C, C++, Objective C/C++, OpenCL C and others for the
- <a href="http://www.llvm.org/">LLVM</a> compiler. You can
- <a href="get_started.html">get and build</a> the source today.</p>
+ <p>The Clang project provides a language front-end and tooling infrastructure
+ for languages in the C language family (C, C++, Objective C/C++, OpenCL,
+ CUDA, and RenderScript) for the <a href="http://www.llvm.org/">LLVM</a>
+ project. Both a GCC-compatible compiler driver (<tt>clang</tt>) and an
+ MSVC-compatible compiler driver (<tt>clang-cl.exe</tt>) are provided. You
+ can <a href="get_started.html">get and build</a> the source today.</p>
<!--=====================================================================-->
<h2 id="goals">Features and Goals</h2>
@@ -83,7 +85,7 @@
</ul>
<p>For a more detailed comparison between Clang and other compilers, please
- see the <a href="comparison.html">clang comparison page</a>.</p>
+ see the <a href="comparison.html">Clang comparison page</a>.</p>
<!--=====================================================================-->
<h2>Current Status</h2>
@@ -108,7 +110,7 @@
it will "resonate" with you. :)</p>
<p>Once you've done that, please consider <a href="get_involved.html">getting
- involved in the clang community</a>. The Clang developers include numerous
+ involved in the Clang community</a>. The Clang developers include numerous
volunteer contributors with a variety of backgrounds. If you're
interested in
following the development of Clang, signing up for a mailing list is a good
diff --git a/www/make_cxx_dr_status b/www/make_cxx_dr_status
index 5fe7b9f8871d..5b1991717d6b 100755
--- a/www/make_cxx_dr_status
+++ b/www/make_cxx_dr_status
@@ -108,7 +108,7 @@ def availability(issue):
if status == 'unknown':
avail = 'Unknown'
avail_style = ' class="none"'
- elif status == '6':
+ elif status == '7':
avail = 'SVN'
avail_style = ' class="svn"'
elif re.match('^[0-9]+\.?[0-9]*', status):
@@ -129,6 +129,9 @@ def availability(issue):
elif status == 'na lib':
avail = 'N/A (Library DR)'
avail_style = ' class="na"'
+ elif status == 'na abi':
+ avail = 'N/A (ABI constraint)'
+ avail_style = ' class="na"'
elif status.startswith('sup '):
dup = status.split(' ', 1)[1]
avail = 'Superseded by <a href="#%s">%s</a>' % (dup, dup)
diff --git a/www/related.html b/www/related.html
index ee4ccd5d973b..d14880f3c10c 100644
--- a/www/related.html
+++ b/www/related.html
@@ -93,6 +93,28 @@
</p>
</dd>
+ <dt>CodeCompass</dt>
+ <dd>
+ <p>
+ <b>Site:</b>
+ <a href="http://github.com/Ericsson/CodeCompass">http://github.com/Ericsson/CodeCompass</a>
+ </p>
+ <p>
+ CodeCompass is an open-source, extensible code comprehension framework which uses LLVM/Clang to analyze and visualize C and C++ projects. It also supports both regex-based text search, discovering complex C/C++ language elements, with advanced navigation and visualisation.
+ </p>
+ </dd>
+
+ <dt>CodeChecker</dt>
+ <dd>
+ <p>
+ <b>Site:</b>
+ <a href="http://github.com/Ericsson/CodeChecker">http://github.com/Ericsson/CodeChecker</a>
+ </p>
+ <p>
+ CodeChecker is a static analysis infrastructure built on the LLVM/Clang Static Analyzer toolchain. It provides a user interface to execute analysis of C/C++ projects with Clang SA and Clang-Tidy, which outputs are then stored into a database navigable via a web application. This web application and a corresponding command-line tool supports a variety of report management and issue triaging options, such as difference view between analyses, automatic incremental analysis, marking and commenting on individual reports.
+ </p>
+ </dd>
+
</dl>
</div>
</body>